From 04bc4d622a4ebdc903fa6feb35192a4efddcc2ca Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 3 Jul 2018 10:30:30 +0200 Subject: rps profiler: correct condition for writing bytes --- src/rps/rps-test_util.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rps/rps-test_util.c b/src/rps/rps-test_util.c index d47e4952f..08fe96097 100644 --- a/src/rps/rps-test_util.c +++ b/src/rps/rps-test_util.c @@ -31,6 +31,17 @@ #define LOG(kind, ...) GNUNET_log_from(kind,"rps-test_util",__VA_ARGS__) +#define B2B_PAT "%c%c%c%c%c%c%c%c" +#define B2B(byte) \ + (byte & 0x80 ? '1' : '0'), \ + (byte & 0x40 ? '1' : '0'), \ + (byte & 0x20 ? '1' : '0'), \ + (byte & 0x10 ? '1' : '0'), \ + (byte & 0x08 ? '1' : '0'), \ + (byte & 0x04 ? '1' : '0'), \ + (byte & 0x02 ? '1' : '0'), \ + (byte & 0x01 ? '1' : '0') + #ifndef TO_FILE #define TO_FILE #endif /* TO_FILE */ @@ -155,6 +166,9 @@ to_file_raw (const char *file_name, const char *buf, size_t size_buf) return; } + LOG (GNUNET_ERROR_TYPE_WARNING, + "Wrote %u bytes raw.\n", + size_written); if (GNUNET_YES != GNUNET_DISK_file_close (f)) LOG (GNUNET_ERROR_TYPE_WARNING, "Unable to close file\n"); @@ -180,6 +194,8 @@ to_file_raw_unaligned (const char *file_name, // num_bits_buf_unaligned = bits_needed % 8; // return; //} + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Was asked to write %u bits\n", bits_needed); char buf_write[size_buf + 1]; const unsigned bytes_iter = (0 != bits_needed % 8? @@ -187,6 +203,14 @@ to_file_raw_unaligned (const char *file_name, bits_needed/8); // TODO what if no iteration happens? unsigned size_buf_write = 0; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "num_bits_buf_unaligned: %u\n", + num_bits_buf_unaligned); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "ua args: size_buf: %u, bits_needed: %u -> iter: %u\n", + size_buf, + bits_needed, + bytes_iter); buf_write[0] = buf_unaligned; /* Iterate over input bytes */ for (unsigned i = 0; i < bytes_iter; i++) @@ -227,17 +251,57 @@ to_file_raw_unaligned (const char *file_name, { num_bits_needed_iter = 8; } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "number of bits needed in this iteration: %u\n", + num_bits_needed_iter); mask_bits_needed_iter = ((char) 1 << num_bits_needed_iter) - 1; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "mask needed bits (current iter): "B2B_PAT"\n", + B2B(mask_bits_needed_iter)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Unaligned byte: "B2B_PAT" (%u bits)\n", + B2B(buf_unaligned), + num_bits_buf_unaligned); byte_input = buf[i]; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "next whole input byte: "B2B_PAT"\n", + B2B(byte_input)); byte_input &= mask_bits_needed_iter; num_bits_to_align = 8 - num_bits_buf_unaligned; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "input byte, needed bits: "B2B_PAT"\n", + B2B(byte_input)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "number of bits needed to align unaligned bit: %u\n", + num_bits_to_align); num_bits_to_move = min (num_bits_to_align, num_bits_needed_iter); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "number of bits of new byte to move: %u\n", + num_bits_to_move); mask_input_to_move = ((char) 1 << num_bits_to_move) - 1; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "mask of bits of new byte to take for moving: "B2B_PAT"\n", + B2B(mask_input_to_move)); bits_to_move = byte_input & mask_input_to_move; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "masked bits of new byte to take for moving: "B2B_PAT"\n", + B2B(bits_to_move)); distance_shift_bits = num_bits_buf_unaligned; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "distance needed to shift bits to their correct spot: %u\n", + distance_shift_bits); bits_moving = bits_to_move << distance_shift_bits; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "shifted, masked bits of new byte being moved: "B2B_PAT"\n", + B2B(bits_moving)); byte_to_fill = buf_unaligned | bits_moving; - if (num_bits_buf_unaligned + num_bits_needed_iter > 8) + LOG (GNUNET_ERROR_TYPE_DEBUG, + "byte being filled: "B2B_PAT"\n", + B2B(byte_to_fill)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "pending bytes: %u\n", + num_bits_buf_unaligned + num_bits_needed_iter); + if (num_bits_buf_unaligned + num_bits_needed_iter >= 8) { /* buf_unaligned was aligned by filling * -> can be written to storage */ @@ -246,10 +310,22 @@ to_file_raw_unaligned (const char *file_name, /* store the leftover, unaligned bits in buffer */ mask_input_leftover = mask_bits_needed_iter & (~ mask_input_to_move); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "mask of leftover bits of new byte: "B2B_PAT"\n", + B2B(mask_input_leftover)); byte_input_leftover = byte_input & mask_input_leftover; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "masked, leftover bits of new byte: "B2B_PAT"\n", + B2B(byte_input_leftover)); num_bits_leftover = num_bits_needed_iter - num_bits_to_move; - num_bits_discard = 8 - num_bits_needed_iter; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "number of unaligned bits left: %u\n", + num_bits_leftover); + //num_bits_discard = 8 - num_bits_needed_iter; byte_unaligned_new = byte_input_leftover >> num_bits_to_move; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "new unaligned byte: "B2B_PAT"\n", + B2B(byte_unaligned_new)); buf_unaligned = byte_unaligned_new; num_bits_buf_unaligned = num_bits_leftover % 8; } -- cgit v1.2.3 From ca09329c05855671f08611dc4cfafd19494842b0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 3 Jul 2018 17:36:55 +0200 Subject: assert no MQ error after MQ destroy --- src/cadet/cadet_api.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c index 319279110..92dd39b97 100644 --- a/src/cadet/cadet_api.c +++ b/src/cadet/cadet_api.c @@ -841,6 +841,7 @@ handle_mq_error (void *cls, h); GNUNET_MQ_destroy (h->mq); h->mq = NULL; + GNUNET_assert (NULL == h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h); -- cgit v1.2.3 From 54a27e268ac6d754232f0d5098fe7c95bc90901f Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 3 Jul 2018 17:56:15 +0200 Subject: reduce relogin time --- src/identity-provider/plugin_rest_openid_connect.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c index d87a345cf..19aac224f 100644 --- a/src/identity-provider/plugin_rest_openid_connect.c +++ b/src/identity-provider/plugin_rest_openid_connect.c @@ -1014,10 +1014,11 @@ login_check (void *cls) return; } } - handle->emsg = GNUNET_strdup("invalid_cookie"); - handle->edesc = GNUNET_strdup( - "The cookie of the login identity is not valid"); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + //handle->emsg = GNUNET_strdup("invalid_cookie"); + //handle->edesc = GNUNET_strdup( + // "The cookie of the login identity is not valid"); + //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + GNUNET_SCHEDULER_add_now (&login_redirection,handle); return; } } @@ -1359,8 +1360,8 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle, current_time = GNUNET_new(struct GNUNET_TIME_Absolute); *current_time = GNUNET_TIME_relative_to_absolute ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_minute_ (), - 30)); + GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), + 5)); last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key); if (NULL != last_time) { -- cgit v1.2.3 From 7653605896fe4485804bdff609a351b6c742f5f6 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 3 Jul 2018 18:14:24 +0200 Subject: update --- po/POTFILES.in | 127 +++++++++++---------- src/identity-provider/plugin_rest_openid_connect.c | 2 + 2 files changed, 66 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/po/POTFILES.in b/po/POTFILES.in index 8a95064a6..83c3c7bdd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,13 +4,21 @@ 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 @@ -21,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 @@ -40,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 @@ -57,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 @@ -102,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 @@ -111,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/gnunet-dns-monitor.c @@ -124,8 +124,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 @@ -150,8 +150,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 @@ -171,10 +171,10 @@ src/gns/gns_tld_api.c src/gns/gnunet-bcd.c src/gns/gnunet-dns2gns.c src/gns/gnunet-gns-benchmark.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 @@ -183,15 +183,15 @@ 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 @@ -200,11 +200,6 @@ 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/gnunet-identity.c -src/identity/gnunet-service-identity.c -src/identity/identity_api.c -src/identity/identity_api_lookup.c -src/identity/plugin_rest_identity.c src/identity-provider/gnunet-idp.c src/identity-provider/gnunet-service-identity-provider.c src/identity-provider/identity_provider_api.c @@ -213,15 +208,20 @@ 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-provider/plugin_rest_openid_connect.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_rest_identity.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 @@ -235,8 +235,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/gnunet-zoneimport.c src/namestore/namestore_api.c @@ -252,10 +252,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 @@ -264,15 +264,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 @@ -317,21 +317,20 @@ src/revocation/gnunet-revocation.c src/revocation/gnunet-service-revocation.c src/revocation/plugin_block_revocation.c src/revocation/revocation_api.c -src/rps/gnunet-rps.c src/rps/gnunet-rps-profiler.c +src/rps/gnunet-rps.c src/rps/gnunet-service-rps.c 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_lib.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 @@ -360,15 +359,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 @@ -376,20 +376,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 @@ -398,28 +397,28 @@ 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/plugin_transport_xt.c @@ -428,6 +427,11 @@ 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 @@ -436,11 +440,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/util/bandwidth.c src/util/bio.c src/util/client.c @@ -452,8 +451,8 @@ 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 @@ -475,13 +474,15 @@ src/util/dnsparser.c src/util/dnsstub.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 src/util/gnunet-scrypt.c src/util/gnunet-service-resolver.c +src/util/gnunet-timeout-w32.c +src/util/gnunet-timeout.c src/util/gnunet-uri.c src/util/helper.c src/util/load.c @@ -509,13 +510,13 @@ src/util/tun.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 -src/zonemaster/gnunet-service-zonemaster.c src/zonemaster/gnunet-service-zonemaster-monitor.c +src/zonemaster/gnunet-service-zonemaster.c src/fs/fs_api.h src/include/gnunet_common.h src/include/gnunet_mq_lib.h diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c index 19aac224f..9c2f7fb3d 100644 --- a/src/identity-provider/plugin_rest_openid_connect.c +++ b/src/identity-provider/plugin_rest_openid_connect.c @@ -732,6 +732,8 @@ cookie_identity_interpretation (struct RequestHandle *handle) { handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY); handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity); + } else { + handle->oidc->login_identity = NULL; } } else -- cgit v1.2.3 From edefc4c42202fd10a48ea9037e3fe04e5ead840d Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 3 Jul 2018 17:27:10 +0200 Subject: fix rps profiler: mark cancelled task as done --- src/rps/gnunet-rps-profiler.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 16f23e86c..54dc7d65e 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -888,6 +888,7 @@ shutdown_op (void *cls) if (NULL != post_test_task) { GNUNET_SCHEDULER_cancel (post_test_task); + post_test_task = NULL; } if (NULL != churn_task) { -- cgit v1.2.3 From 7940449e54a2716d69aed0fd01953ef6204b0229 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 3 Jul 2018 21:09:47 +0200 Subject: fix rps profiler: mark handle unusable after closing it --- src/rps/gnunet-rps-profiler.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 54dc7d65e..f75f9794f 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -900,6 +900,7 @@ shutdown_op (void *cls) if (NULL != rps_peers[i].rps_handle) { GNUNET_RPS_disconnect (rps_peers[i].rps_handle); + rps_peers[i].rps_handle = NULL; } if (NULL != rps_peers[i].op) { -- cgit v1.2.3 From 37d12e4bcfc456ae488cce7d93853339812035fe Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 3 Jul 2018 21:10:38 +0200 Subject: rps profiler: different time for hard shutdown --- src/rps/gnunet-rps-profiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index f75f9794f..ec73f1803 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -2572,7 +2572,7 @@ test_run (void *cls, if (NULL != churn_task) GNUNET_SCHEDULER_cancel (churn_task); post_test_task = GNUNET_SCHEDULER_add_delayed (timeout, &post_test_op, NULL); - timeout = GNUNET_TIME_relative_multiply (timeout, 1 + (0.1 * num_peers)); + timeout = GNUNET_TIME_relative_multiply (timeout, 1.2 + (0.01 * num_peers)); shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_op, NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL); -- cgit v1.2.3 From 00fc4513ebdb851c79b8f7c2591dffb6bd70c5bd Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 3 Jul 2018 21:11:40 +0200 Subject: rps service: stop ignoring own peer id --- src/rps/gnunet-service-rps.c | 60 ++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 5a75ac55a..db09c68d2 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -1045,12 +1045,10 @@ restore_valid_peers () */ void Peers_initialise (char* fn_valid_peers, - struct GNUNET_CADET_Handle *cadet_h, - const struct GNUNET_PeerIdentity *own_id) + struct GNUNET_CADET_Handle *cadet_h) { filename_valid_peers = GNUNET_strdup (fn_valid_peers); cadet_handle = cadet_h; - own_identity = *own_id; peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); restore_valid_peers (); @@ -1136,14 +1134,12 @@ Peers_get_valid_peers (PeersIterator iterator, * @param peer the new #GNUNET_PeerIdentity * * @return #GNUNET_YES if peer was inserted - * #GNUNET_NO otherwise (if peer was already known or - * peer was #own_identity) + * #GNUNET_NO otherwise */ int Peers_insert_peer (const struct GNUNET_PeerIdentity *peer) { - if ( (GNUNET_YES == Peers_check_peer_known (peer)) || - (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity)) ) + if (GNUNET_YES == Peers_check_peer_known (peer)) { return GNUNET_NO; /* We already know this peer - nothing to do */ } @@ -1161,8 +1157,7 @@ Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFl * * @param peer the peer whose liveliness is to be checked * @return #GNUNET_YES if peer had to be inserted - * #GNUNET_NO otherwise (if peer was already known or - * peer was #own_identity) + * #GNUNET_NO otherwise */ int Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer) @@ -1170,10 +1165,6 @@ Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer) struct PeerContext *peer_ctx; int ret; - if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity)) - { - return GNUNET_NO; - } ret = Peers_insert_peer (peer); peer_ctx = get_peer_ctx (peer); if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE)) @@ -1791,10 +1782,6 @@ Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer, struct PeerPendingOp pending_op; struct PeerContext *peer_ctx; - if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity)) - { - return GNUNET_NO; - } GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer)); //TODO if LIVE/ONLINE execute immediately @@ -3373,9 +3360,7 @@ handle_peer_pull_reply (void *cls, if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set, &peers[i]) && GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (mal_peer_set, - &peers[i]) - && 0 != GNUNET_CRYPTO_cmp_peer_identity (&peers[i], - &own_identity)) + &peers[i])) { tmp_att_peer = GNUNET_new (struct AttackedPeer); tmp_att_peer->peer_id = peers[i]; @@ -3387,21 +3372,17 @@ handle_peer_pull_reply (void *cls, continue; } #endif /* ENABLE_MALICIOUS */ - if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, - &peers[i])) - { - /* Make sure we 'know' about this peer */ - (void) Peers_insert_peer (&peers[i]); + /* Make sure we 'know' about this peer */ + (void) Peers_insert_peer (&peers[i]); - if (GNUNET_YES == Peers_check_peer_valid (&peers[i])) - { - CustomPeerMap_put (pull_map, &peers[i]); - } - else - { - Peers_schedule_operation (&peers[i], insert_in_pull_map); - (void) Peers_issue_peer_liveliness_check (&peers[i]); - } + if (GNUNET_YES == Peers_check_peer_valid (&peers[i])) + { + CustomPeerMap_put (pull_map, &peers[i]); + } + else + { + Peers_schedule_operation (&peers[i], insert_in_pull_map); + (void) Peers_issue_peer_liveliness_check (&peers[i]); } } @@ -3836,10 +3817,8 @@ do_round (void *cls) for (i = 0; i < a_peers; i++) { peer = view_array[permut[i]]; - if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer)) // TODO - { // FIXME if this fails schedule/loop this for later - send_push (&peer); - } + // FIXME if this fails schedule/loop this for later + send_push (&peer); } /* Send PULL requests */ @@ -3857,8 +3836,7 @@ do_round (void *cls) for (i = first_border; i < second_border; i++) { peer = view_array[permut[i]]; - if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer) && - GNUNET_NO == Peers_check_peer_flag (&peer, Peers_PULL_REPLY_PENDING)) // TODO + if ( GNUNET_NO == Peers_check_peer_flag (&peer, Peers_PULL_REPLY_PENDING)) { // FIXME if this fails schedule/loop this for later send_pull_request (&peer); } @@ -4372,7 +4350,7 @@ run (void *cls, peerinfo_handle = GNUNET_PEERINFO_connect (cfg); - Peers_initialise (fn_valid_peers, cadet_handle, &own_identity); + Peers_initialise (fn_valid_peers, cadet_handle); GNUNET_free (fn_valid_peers); /* Initialise sampler */ -- cgit v1.2.3 From 18fdfc54ce13a4b67d24c835e013492fc30507db Mon Sep 17 00:00:00 2001 From: xrs Date: Tue, 3 Jul 2018 22:47:49 +0200 Subject: fix codesonar finding 2366.9987 --- src/arm/test_exponential_backoff.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c index 4a7d51bc7..71c98211a 100644 --- a/src/arm/test_exponential_backoff.c +++ b/src/arm/test_exponential_backoff.c @@ -343,7 +343,10 @@ init () cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, "test_arm_api_data.conf")) + { + GNUNET_free (cfg); return GNUNET_SYSERR; + } if (NULL == getcwd (pwd, PATH_MAX)) return GNUNET_SYSERR; GNUNET_assert (0 < GNUNET_asprintf (&binary, -- cgit v1.2.3 From 0a5d0d80c6e2896c0561f77ddafeb0aa99fbf456 Mon Sep 17 00:00:00 2001 From: xrs Date: Tue, 3 Jul 2018 22:53:57 +0200 Subject: fix codesonar finding 2287.9399 --- src/multicast/test_multicast_multipeer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/multicast/test_multicast_multipeer.c b/src/multicast/test_multicast_multipeer.c index 3a7c6d961..92209b774 100644 --- a/src/multicast/test_multicast_multipeer.c +++ b/src/multicast/test_multicast_multipeer.c @@ -328,6 +328,7 @@ origin_notify (void *cls, pp_msg->msg = PONG; *data_size = sizeof (struct pingpong_msg); GNUNET_memcpy(data, pp_msg, *data_size); + GNUNET_free (pp_msg); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n"); -- cgit v1.2.3 From bdb1ee3242fe915f2648295f7430fab70eb31121 Mon Sep 17 00:00:00 2001 From: xrs Date: Tue, 3 Jul 2018 22:58:38 +0200 Subject: fix codesonar finding 2289.9403 --- src/multicast/test_multicast_multipeer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/multicast/test_multicast_multipeer.c b/src/multicast/test_multicast_multipeer.c index 92209b774..7766ff875 100644 --- a/src/multicast/test_multicast_multipeer.c +++ b/src/multicast/test_multicast_multipeer.c @@ -160,6 +160,7 @@ notify (void *cls, *data_size = sizeof (struct pingpong_msg); GNUNET_memcpy(data, pp_msg, *data_size); + GNUNET_free (pp_msg); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer #%u sents ping to origin\n", mc_peer->peer); -- cgit v1.2.3 From 76fc90b73c0fe99379e600da48efbb5e5d080052 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 4 Jul 2018 00:17:20 +0200 Subject: fix --- src/identity-provider/plugin_rest_identity_provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index a83163db2..f8176a101 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c @@ -844,7 +844,7 @@ revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle, rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res, "rnd"); identity_json = GNUNET_JSONAPI_resource_read_attr (json_res, - "identity"); + "issuer"); audience_json = GNUNET_JSONAPI_resource_read_attr (json_res, "audience"); rnd_str = json_string_value (rnd_json); -- cgit v1.2.3 From b658d8c71b3f822fdcd09e2e97cc35a69bcc5f64 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 4 Jul 2018 01:27:46 +0200 Subject: fix --- src/identity-provider/identity_provider_api.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index 772b4a244..9ea7a5d11 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c @@ -1350,7 +1350,6 @@ GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle * void *cb_cls) { struct GNUNET_IDENTITY_PROVIDER_Operation *op; - struct GNUNET_MQ_Envelope *env; struct RevokeTicketMessage *msg; uint32_t rid; @@ -1363,7 +1362,7 @@ GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle * GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); - env = GNUNET_MQ_msg_extra (msg, + op->env = GNUNET_MQ_msg_extra (msg, sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket), GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET); msg->id = htonl (rid); @@ -1371,11 +1370,9 @@ GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle * GNUNET_memcpy (&msg[1], ticket, sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); - if (NULL == h->mq) - op->env = env; - else + if (NULL != h->mq) GNUNET_MQ_send (h->mq, - env); + op->env); return op; } -- cgit v1.2.3 From 1d3e9bf8749be3a67b0b2488af19067cb3a43527 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 4 Jul 2018 01:37:01 +0200 Subject: fix --- src/identity-provider/gnunet-service-identity-provider.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'src') diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index c53e72477..915e8bf44 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -1206,9 +1206,6 @@ reissue_ticket_cont (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", "Unknown Error\n"); send_revocation_finished (rh, GNUNET_SYSERR); - GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, - rh->client->revoke_op_tail, - rh); cleanup_revoke_ticket_handle (rh); return; } @@ -1374,9 +1371,6 @@ revocation_reissue_tickets (struct TicketRevocationHandle *rh) if (GNUNET_NO == ret) { send_revocation_finished (rh, GNUNET_OK); - GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, - rh->client->revoke_op_tail, - rh); cleanup_revoke_ticket_handle (rh); return; } @@ -1392,9 +1386,6 @@ check_attr_error (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to check for existing attribute\n"); send_revocation_finished (rh, GNUNET_SYSERR); - GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, - rh->client->revoke_op_tail, - rh); cleanup_revoke_ticket_handle (rh); } @@ -1458,9 +1449,6 @@ check_attr_cb (void *cls, policy); GNUNET_free (policy); send_revocation_finished (rh, GNUNET_SYSERR); - GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, - rh->client->revoke_op_tail, - rh); cleanup_revoke_ticket_handle (rh); return; } @@ -1571,9 +1559,6 @@ process_attributes_to_update (void *cls, { /* No attributes to reencrypt */ send_revocation_finished (rh, GNUNET_OK); - GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, - rh->client->revoke_op_tail, - rh); cleanup_revoke_ticket_handle (rh); return; } else { -- cgit v1.2.3 From a69d1a0fe703dd269982df7e50bc2c89bea63e07 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 4 Jul 2018 02:01:57 +0200 Subject: fixes --- src/identity-provider/gnunet-service-identity-provider.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 915e8bf44..7f71988f8 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -1385,6 +1385,7 @@ check_attr_error (void *cls) struct TicketRevocationHandle *rh = cls; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to check for existing attribute\n"); + rh->ns_qe = NULL; send_revocation_finished (rh, GNUNET_SYSERR); cleanup_revoke_ticket_handle (rh); } @@ -1417,6 +1418,7 @@ check_attr_cb (void *cls, char* policy; uint32_t attr_ver; + rh->ns_qe = NULL; if (1 != rd_count) { GNUNET_SCHEDULER_add_now (&reenc_next_attribute, rh); @@ -1515,6 +1517,7 @@ attr_reenc_cont (void *cls, struct TicketRevocationHandle *rh = cls; struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; + rh->ns_qe = NULL; if (GNUNET_SYSERR == success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -- cgit v1.2.3 From 0584cf962c6cf44d6ac97e0f81b3dedfd0d1f059 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 4 Jul 2018 06:54:57 +0200 Subject: fix --- src/identity-provider/identity_provider_api.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index 9ea7a5d11..33efe726f 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c @@ -1370,9 +1370,11 @@ GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle * GNUNET_memcpy (&msg[1], ticket, sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); - if (NULL != h->mq) + if (NULL != h->mq) { GNUNET_MQ_send (h->mq, op->env); + op->env = NULL; + } return op; } -- cgit v1.2.3 From 0d128388d4c4da4afc6b65913d1d2e25e039cd8c Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Wed, 4 Jul 2018 07:41:14 +0200 Subject: acutally delete ticket --- .../gnunet-service-identity-provider.c | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 7f71988f8..4563fdfa1 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -1157,6 +1157,9 @@ send_revocation_finished (struct TicketRevocationHandle *rh, { struct GNUNET_MQ_Envelope *env; struct RevokeTicketResultMessage *trm; + + GNUNET_break(TKT_database->delete_ticket (TKT_database->cls, + &rh->ticket)); env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT); @@ -1255,9 +1258,18 @@ ticket_reissue_proc (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Do not reissue for this identity.!\n"); - - rh->offset++; - GNUNET_SCHEDULER_add_now (&reissue_next, rh); + label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd, + sizeof (uint64_t)); + //Delete record + rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, + &rh->identity, + label, + 0, + NULL, + &reissue_ticket_cont, + rh); + + GNUNET_free (label); return; } @@ -1955,7 +1967,7 @@ attr_store_cont (void *cls, struct AttributeStoreHandle *as_handle = cls; struct GNUNET_MQ_Envelope *env; struct AttributeStoreResultMessage *acr_msg; - + as_handle->ns_qe = NULL; GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, as_handle->client->store_op_tail, @@ -2177,14 +2189,14 @@ attr_iter_cb (void *cls, if (rd_count != 1) { GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, - 1); + 1); return; } if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) { GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, - 1); + 1); return; } attr_ver = ntohl(*((uint32_t*)rd->data)); @@ -2201,7 +2213,7 @@ attr_iter_cb (void *cls, if (GNUNET_SYSERR == msg_extra_len) { GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, - 1); + 1); return; } @@ -2252,7 +2264,7 @@ iterate_next_after_abe_bootstrap (void *cls, struct AttributeIterator *ai = cls; ai->abe_key = abe_key; GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, - 1); + 1); } -- cgit v1.2.3 From a08b943874919809fb17656baa0c5e7c99557d92 Mon Sep 17 00:00:00 2001 From: xrs Date: Wed, 4 Jul 2018 19:11:41 +0200 Subject: refix codesonar finding 2366.9987 --- src/arm/test_exponential_backoff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c index 71c98211a..f15bca2db 100644 --- a/src/arm/test_exponential_backoff.c +++ b/src/arm/test_exponential_backoff.c @@ -344,7 +344,7 @@ init () if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, "test_arm_api_data.conf")) { - GNUNET_free (cfg); + GNUNET_CONFIGURATION_destroy (cfg); return GNUNET_SYSERR; } if (NULL == getcwd (pwd, PATH_MAX)) -- cgit v1.2.3 From 61421b558cfd8b0f31328f4d99d045990bd311de Mon Sep 17 00:00:00 2001 From: xrs Date: Wed, 4 Jul 2018 20:04:52 +0200 Subject: fix wrong condition --- src/multicast/gnunet-service-multicast.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c index 20d29b906..f8441cc2b 100644 --- a/src/multicast/gnunet-service-multicast.c +++ b/src/multicast/gnunet-service-multicast.c @@ -1449,17 +1449,15 @@ check_client_member_join (void *cls, struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1]; uint32_t relay_count = ntohl (msg->relay_count); - if (0 == relay_count) + if (0 != relay_count) { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (UINT32_MAX / relay_count < sizeof (*relays)){ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "relay_count (%lu) * sizeof (*relays) (%lu) exceeds UINT32_MAX!\n", - (unsigned long)relay_count, - sizeof (*relays)); - return GNUNET_SYSERR; + if (UINT32_MAX / relay_count < sizeof (*relays)){ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "relay_count (%lu) * sizeof (*relays) (%lu) exceeds UINT32_MAX!\n", + (unsigned long)relay_count, + sizeof (*relays)); + return GNUNET_SYSERR; + } } uint32_t relay_size = relay_count * sizeof (*relays); struct GNUNET_MessageHeader *join_msg = NULL; -- cgit v1.2.3 From 79b600acfc7cbcd20cdaac04be7716c8c893ac4e Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 5 Jul 2018 17:09:06 +0200 Subject: fix rps profiler: mark operation as done on shutdown --- src/rps/gnunet-rps-profiler.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index ec73f1803..dcd72aef1 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -905,6 +905,7 @@ shutdown_op (void *cls) if (NULL != rps_peers[i].op) { GNUNET_TESTBED_operation_done (rps_peers[i].op); + rps_peers[i].op = NULL; } } } @@ -2263,12 +2264,6 @@ void write_final_stats (void){ stat_type < STAT_TYPE_MAX; stat_type++) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Add to sum (%" PRIu64 ") %" PRIu64 " of stat type %u - %s\n", - sums[stat_type], - rps_peers[i].stats[stat_type], - stat_type, - stat_type_2_str (stat_type)); sums[stat_type] += rps_peers[i].stats[stat_type]; } } -- cgit v1.2.3 From 411abad7976fb483fb29bddd8982cbe746502b95 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 5 Jul 2018 22:05:16 +0200 Subject: rps profiler: additional checks and assertions before disconnect from rps --- src/rps/gnunet-rps-profiler.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index dcd72aef1..0427608f1 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -1177,8 +1177,12 @@ rps_disconnect_adapter (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnect_adapter()\n"); GNUNET_assert (NULL != peer); - GNUNET_RPS_disconnect (h); - peer->rps_handle = NULL; + if (NULL != peer->rps_handle) + { + GNUNET_assert (h == peer->rps_handle); + GNUNET_RPS_disconnect (h); + peer->rps_handle = NULL; + } } -- cgit v1.2.3 From dbdb128c604560e22b56b9ba139f0b8ff28efcb3 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 5 Jul 2018 22:06:11 +0200 Subject: rps profiler: different delay for hard shutdown --- src/rps/gnunet-rps-profiler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 0427608f1..09797eaf7 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -2571,7 +2571,8 @@ test_run (void *cls, if (NULL != churn_task) GNUNET_SCHEDULER_cancel (churn_task); post_test_task = GNUNET_SCHEDULER_add_delayed (timeout, &post_test_op, NULL); - timeout = GNUNET_TIME_relative_multiply (timeout, 1.2 + (0.01 * num_peers)); + timeout = GNUNET_TIME_relative_multiply (timeout, 0.2 + (0.01 * num_peers)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for hard shutdown is %u\n", timeout.rel_value_us/1000000); shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_op, NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL); -- cgit v1.2.3 From 8d2bd1dd06bc416277f623d2c9d84cf0da5624fe Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 5 Jul 2018 22:06:54 +0200 Subject: rps service: additional logging of unexpected channel establishing --- src/rps/gnunet-service-rps.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index db09c68d2..aef6a72de 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -1534,6 +1534,9 @@ Peers_handle_inbound_channel (void *cls, /* We only accept one incoming channel per peer */ if (GNUNET_YES == Peers_check_peer_send_intention (initiator)) { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Already got one receive channel. Destroying old one.\n"); + GNUNET_break_op (0); set_channel_flag (peer_ctx->recv_channel_flags, Peers_CHANNEL_ESTABLISHED_TWICE); //GNUNET_CADET_channel_destroy (channel); -- cgit v1.2.3 From 362715ec0e3940f6ab747d787c66c8e07f88eafa Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 7 Jul 2018 17:13:25 +0200 Subject: fix numbering glitch --- src/include/gnunet_signatures.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h index d7accaf2c..280fefa83 100644 --- a/src/include/gnunet_signatures.h +++ b/src/include/gnunet_signatures.h @@ -151,12 +151,12 @@ extern "C" /** * Signature for the first round of distributed key generation. */ -#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 22 +#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 21 /** * Signature for the second round of distributed key generation. */ -#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2 23 +#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2 22 /** * Signature for cooperatice decryption. -- cgit v1.2.3 From 5cf1f3d86bdb95f6df41405df063061d03eb9bcf Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 7 Jul 2018 20:53:11 +0200 Subject: add missing index --- src/datacache/plugin_datacache_sqlite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c index 4684e514c..dc4236a8b 100644 --- a/src/datacache/plugin_datacache_sqlite.c +++ b/src/datacache/plugin_datacache_sqlite.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -749,7 +749,8 @@ libgnunet_plugin_datacache_sqlite_init (void *cls) " value BLOB NOT NULL," " path BLOB DEFAULT '')"); SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds091 (key,type,expire)"); - SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire ON ds091 (prox,expire)"); + SQLITE3_EXEC (dbh, "CREATE INDEX idx_prox_expire ON ds091 (prox,expire)"); + SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire_only ON ds091 (expire)"); plugin = GNUNET_new (struct Plugin); plugin->env = env; plugin->dbh = dbh; -- cgit v1.2.3 From b35da95733c873d6bb625764fd3c43c76a7172f7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 7 Jul 2018 20:54:34 +0200 Subject: fix fmt string --- src/util/dnsparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/util/dnsparser.c b/src/util/dnsparser.c index 6fb6d657f..24f1b18cf 100644 --- a/src/util/dnsparser.c +++ b/src/util/dnsparser.c @@ -959,7 +959,7 @@ GNUNET_DNSPARSER_builder_add_name (char *dst, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid DNS name `%s': label with %u characters encountered\n", name, - len); + (unsigned int) len); goto fail; /* label too long or empty */ } dst[pos++] = (char) (uint8_t) len; -- cgit v1.2.3 From 041218a66dff4e23ac0944a7c1bca7b0833fc2fe Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 10 Jul 2018 11:00:06 +0200 Subject: rps profiler: logging and indentation --- src/rps/gnunet-rps-profiler.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 09797eaf7..26675d782 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -882,7 +882,7 @@ shutdown_op (void *cls) { unsigned int i; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown task scheduled, going down.\n"); in_shutdown = GNUNET_YES; if (NULL != post_test_task) @@ -1033,9 +1033,9 @@ info_cb (void *cb_cls, */ static void rps_connect_complete_cb (void *cls, - struct GNUNET_TESTBED_Operation *op, - void *ca_result, - const char *emsg) + struct GNUNET_TESTBED_Operation *op, + void *ca_result, + const char *emsg) { struct RPSPeer *rps_peer = cls; struct GNUNET_RPS_Handle *rps = ca_result; @@ -1060,7 +1060,9 @@ rps_connect_complete_cb (void *cls, return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Started client successfully (%u)\n", + rps_peer->index); cur_test_run.main_test (rps_peer); } @@ -1078,7 +1080,7 @@ rps_connect_complete_cb (void *cls, */ static void * rps_connect_adapter (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg) + const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_RPS_Handle *h; @@ -1170,12 +1172,14 @@ stat_complete_cb (void *cls, struct GNUNET_TESTBED_Operation *op, */ static void rps_disconnect_adapter (void *cls, - void *op_result) + void *op_result) { struct RPSPeer *peer = cls; struct GNUNET_RPS_Handle *h = op_result; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnect_adapter()\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "disconnect_adapter (%u)\n", + peer->index); GNUNET_assert (NULL != peer); if (NULL != peer->rps_handle) { @@ -2556,6 +2560,8 @@ test_run (void *cls, /* Connect all peers to statistics service */ if (COLLECT_STATISTICS == cur_test_run.have_collect_statistics) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connecting to statistics service\n"); rps_peers[i].stat_op = GNUNET_TESTBED_service_connect (NULL, peers[i], @@ -2571,9 +2577,8 @@ test_run (void *cls, if (NULL != churn_task) GNUNET_SCHEDULER_cancel (churn_task); post_test_task = GNUNET_SCHEDULER_add_delayed (timeout, &post_test_op, NULL); - timeout = GNUNET_TIME_relative_multiply (timeout, 0.2 + (0.01 * num_peers)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for hard shutdown is %u\n", timeout.rel_value_us/1000000); - shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_op, NULL); + timeout = GNUNET_TIME_relative_multiply (timeout, 1.2 + (0.01 * num_peers)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for hard shutdown is %lu\n", timeout.rel_value_us/1000000); shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL); } @@ -2734,7 +2739,6 @@ main (int argc, char *argv[]) GNUNET_free (rps_peers); GNUNET_free (rps_peer_ids); GNUNET_CONTAINER_multipeermap_destroy (peer_map); - printf ("test -1\n"); return ret_value; } -- cgit v1.2.3 From 857f3bc73618d69cd1122a8a519c89a46aee037b Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 10 Jul 2018 11:02:42 +0200 Subject: fix rps profiler: keep track about scheduled tasks properly --- src/rps/gnunet-rps-profiler.c | 157 ++++++++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 26675d782..9ad6d3c3b 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -446,6 +446,10 @@ struct RPSPeer * @brief statistics values */ uint64_t stats[STAT_TYPE_MAX]; + /** + * @brief Handle for the statistics get request + */ + struct GNUNET_STATISTICS_GetHandle *h_stat_get[STAT_TYPE_MAX]; }; /** @@ -874,6 +878,81 @@ static int check_statistics_collect_completed () return GNUNET_YES; } + +static void +cancel_pending_req (struct PendingRequest *pending_req) +{ + struct RPSPeer *rps_peer; + + rps_peer = pending_req->rps_peer; + GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head, + rps_peer->pending_req_tail, + pending_req); + rps_peer->num_pending_reqs--; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cancelling pending rps get request\n"); + GNUNET_SCHEDULER_cancel (pending_req->request_task); + GNUNET_free (pending_req); +} + +static void +cancel_request (struct PendingReply *pending_rep) +{ + struct RPSPeer *rps_peer; + + rps_peer = pending_rep->rps_peer; + GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head, + rps_peer->pending_rep_tail, + pending_rep); + rps_peer->num_pending_reps--; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cancelling rps get reply\n"); + GNUNET_RPS_request_cancel (pending_rep->req_handle); + GNUNET_free (pending_rep); +} + +void +clean_peer (unsigned peer_index) +{ + struct PendingReply *pending_rep; + struct PendingRequest *pending_req; + + pending_rep = rps_peers[peer_index].pending_rep_head; + while (NULL != (pending_rep = rps_peers[peer_index].pending_rep_head)) + { + cancel_request (pending_rep); + } + pending_req = rps_peers[peer_index].pending_req_head; + while (NULL != (pending_req = rps_peers[peer_index].pending_req_head)) + { + cancel_pending_req (pending_req); + } + if (NULL != rps_peers[peer_index].rps_handle) + { + GNUNET_RPS_disconnect (rps_peers[peer_index].rps_handle); + rps_peers[peer_index].rps_handle = NULL; + } + for (unsigned stat_type = STAT_TYPE_ROUNDS; + stat_type < STAT_TYPE_MAX; + stat_type++) + { + if (NULL != rps_peers[peer_index].h_stat_get[stat_type]) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "(%u) did not yet receive stat value for `%s'\n", + rps_peers[peer_index].index, + stat_type_2_str (stat_type)); + GNUNET_STATISTICS_get_cancel ( + rps_peers[peer_index].h_stat_get[stat_type]); + } + } + if (NULL != rps_peers[peer_index].op) + { + GNUNET_TESTBED_operation_done (rps_peers[peer_index].op); + rps_peers[peer_index].op = NULL; + } +} + /** * Task run on timeout to shut everything down. */ @@ -881,10 +960,12 @@ static void shutdown_op (void *cls) { unsigned int i; + struct OpListEntry *entry; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown task scheduled, going down.\n"); in_shutdown = GNUNET_YES; + shutdown_task = NULL; if (NULL != post_test_task) { GNUNET_SCHEDULER_cancel (post_test_task); @@ -895,19 +976,21 @@ shutdown_op (void *cls) GNUNET_SCHEDULER_cancel (churn_task); churn_task = NULL; } + entry = oplist_head; + while (NULL != (entry = oplist_head)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Operation still pending on shutdown (%u)\n", + entry->index); + GNUNET_TESTBED_operation_done (entry->op); + GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry); + GNUNET_free (entry); + } for (i = 0; i < num_peers; i++) { - if (NULL != rps_peers[i].rps_handle) - { - GNUNET_RPS_disconnect (rps_peers[i].rps_handle); - rps_peers[i].rps_handle = NULL; - } - if (NULL != rps_peers[i].op) - { - GNUNET_TESTBED_operation_done (rps_peers[i].op); - rps_peers[i].op = NULL; - } + clean_peer (i); } + GNUNET_SCHEDULER_shutdown (); } @@ -947,7 +1030,6 @@ post_test_op (void *cls) { GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&shutdown_op, NULL); - GNUNET_SCHEDULER_shutdown (); } } @@ -1056,7 +1138,7 @@ rps_connect_complete_cb (void *cls, "Failed to connect to RPS service: %s\n", emsg); ok = 1; - GNUNET_SCHEDULER_shutdown (); + shutdown_op (NULL); return; } @@ -1272,38 +1354,6 @@ request_peers (void *cls) rps_peer->num_pending_reqs--; } -static void -cancel_pending_req (struct PendingRequest *pending_req) -{ - struct RPSPeer *rps_peer; - - rps_peer = pending_req->rps_peer; - GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head, - rps_peer->pending_req_tail, - pending_req); - rps_peer->num_pending_reqs--; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cancelling pending request\n"); - GNUNET_SCHEDULER_cancel (pending_req->request_task); - GNUNET_free (pending_req); -} - -static void -cancel_request (struct PendingReply *pending_rep) -{ - struct RPSPeer *rps_peer; - - rps_peer = pending_rep->rps_peer; - GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head, - rps_peer->pending_rep_tail, - pending_rep); - rps_peer->num_pending_reps--; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cancelling request\n"); - GNUNET_RPS_request_cancel (pending_rep->req_handle); - GNUNET_free (pending_rep); -} - /** * Schedule requests for peer @a rps_peer that have neither been scheduled, nor @@ -1493,7 +1543,7 @@ churn_cb (void *cls, if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n"); - GNUNET_SCHEDULER_shutdown (); + shutdown_op (NULL); return; } GNUNET_assert (0 != entry->delta); @@ -2343,7 +2393,7 @@ post_test_shutdown_ready_cb (void *cls, GNUNET_free (stat_cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); - GNUNET_SCHEDULER_shutdown (); + shutdown_op (NULL); } else { GNUNET_free (stat_cls); } @@ -2368,10 +2418,12 @@ stat_iterator (void *cls, { const struct STATcls *stat_cls = (const struct STATcls *) cls; struct RPSPeer *rps_peer = (struct RPSPeer *) stat_cls->rps_peer; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got stat value: %s - %" PRIu64 "\n", //stat_type_2_str (stat_cls->stat_type), name, value); + rps_peer->h_stat_get[stat_str_2_type (name)] = NULL; to_file (rps_peer->file_name_stats, "%s: %" PRIu64 "\n", name, @@ -2460,12 +2512,13 @@ void post_profiler (struct RPSPeer *rps_peer) stat_cls->stat_type = stat_type; rps_peer->file_name_stats = store_prefix_file_name (rps_peer->peer_id, "stats"); - GNUNET_STATISTICS_get (rps_peer->stats_h, - "rps", - stat_type_2_str (stat_type), - post_test_shutdown_ready_cb, - stat_iterator, - (struct STATcls *) stat_cls); + rps_peer->h_stat_get[stat_type] = GNUNET_STATISTICS_get ( + rps_peer->stats_h, + "rps", + stat_type_2_str (stat_type), + post_test_shutdown_ready_cb, + stat_iterator, + (struct STATcls *) stat_cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requested statistics for %s (peer %" PRIu32 ")\n", stat_type_2_str (stat_type), -- cgit v1.2.3 From d1c8a1e764430a7720bc2962414aa45e1d3b9030 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 10 Jul 2018 12:13:14 +0200 Subject: rps profiler: add option for duration of profiling --- src/rps/gnunet-rps-profiler.c | 50 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 9ad6d3c3b..cab7f6dc4 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -49,7 +49,11 @@ static unsigned bits_needed; /** * How long do we run the test? */ -//#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) +static struct GNUNET_TIME_Relative duration; + +/** + * When do we do a hard shutdown? + */ static struct GNUNET_TIME_Relative timeout; @@ -995,7 +999,7 @@ shutdown_op (void *cls) /** - * Task run on timeout to collect statistics and potentially shut down. + * Task run after #duration to collect statistics and potentially shut down. */ static void post_test_op (void *cls) @@ -1314,7 +1318,8 @@ default_reply_handle (void *cls, if (0 == evaluate () && HAVE_QUICK_QUIT == cur_test_run.have_quick_quit) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test succeeded before timeout\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Test succeeded before end of duration\n"); GNUNET_assert (NULL != post_test_task); GNUNET_SCHEDULER_cancel (post_test_task); post_test_task = GNUNET_SCHEDULER_add_now (&post_test_op, NULL); @@ -2629,11 +2634,9 @@ test_run (void *cls, if (NULL != churn_task) GNUNET_SCHEDULER_cancel (churn_task); - post_test_task = GNUNET_SCHEDULER_add_delayed (timeout, &post_test_op, NULL); - timeout = GNUNET_TIME_relative_multiply (timeout, 1.2 + (0.01 * num_peers)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for hard shutdown is %lu\n", timeout.rel_value_us/1000000); + post_test_task = GNUNET_SCHEDULER_add_delayed (duration, &post_test_op, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for shutdown is %lu\n", timeout.rel_value_us/1000000); shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL); - } @@ -2669,7 +2672,7 @@ run (void *cls, if (0 == cur_test_run.num_requests) cur_test_run.num_requests = 5; //cur_test_run.have_churn = HAVE_CHURN; cur_test_run.have_churn = HAVE_NO_CHURN; - cur_test_run.have_quick_quit = HAVE_NO_QUICK_QUIT; + cur_test_run.have_quick_quit = HAVE_QUICK_QUIT; cur_test_run.have_collect_statistics = COLLECT_STATISTICS; cur_test_run.stat_collect_flags = BIT(STAT_TYPE_ROUNDS) | BIT(STAT_TYPE_BLOCKS) | @@ -2692,9 +2695,30 @@ run (void *cls, /* 'Clean' directory */ (void) GNUNET_DISK_directory_remove ("/tmp/rps/"); GNUNET_DISK_directory_create ("/tmp/rps/"); - if (0 == timeout.rel_value_us) + if (0 == duration.rel_value_us) { - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90); + if (0 == timeout.rel_value_us) + { + duration = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90); + timeout = GNUNET_TIME_relative_multiply (duration, + 1.2 + (0.01 * num_peers)); + } + else + { + duration = GNUNET_TIME_relative_multiply (timeout, 0.75 ); + } + } + else + { + if (0 == timeout.rel_value_us) + { + timeout = GNUNET_TIME_relative_multiply (duration, + 1.2 + (0.01 * num_peers)); + } + else + { + GNUNET_assert (duration.rel_value_us <= timeout.rel_value_us); + } } /* Compute number of bits for representing largest peer id */ @@ -2745,6 +2769,12 @@ main (int argc, char *argv[]) gettext_noop ("number of peers to start"), &num_peers), + GNUNET_GETOPT_option_relative_time ('d', + "duration", + "DURATION", + gettext_noop ("duration of the profiling"), + &duration), + GNUNET_GETOPT_option_relative_time ('t', "timeout", "TIMEOUT", -- cgit v1.2.3 From a5c75acc95be6f1b02f5eb3fb039f7c7fa7e4877 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 10 Jul 2018 12:37:57 +0200 Subject: fix rps profiler: mark statistics get done in right place --- src/rps/gnunet-rps-profiler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index cab7f6dc4..4ebd745e8 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -2372,6 +2372,8 @@ post_test_shutdown_ready_cb (void *cls, { struct STATcls *stat_cls = (struct STATcls *) cls; struct RPSPeer *rps_peer = stat_cls->rps_peer; + + rps_peer->h_stat_get[stat_cls->stat_type] = NULL; if (GNUNET_OK == success) { /* set flag that we we got the value */ @@ -2428,7 +2430,6 @@ stat_iterator (void *cls, //stat_type_2_str (stat_cls->stat_type), name, value); - rps_peer->h_stat_get[stat_str_2_type (name)] = NULL; to_file (rps_peer->file_name_stats, "%s: %" PRIu64 "\n", name, -- cgit v1.2.3 From efc0c09784d55ea347e6208dece55593241f2346 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Wed, 11 Jul 2018 16:36:25 +0200 Subject: rps profiler: reorganise shutdown --- src/rps/gnunet-rps-profiler.c | 70 +++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 4ebd745e8..a1728cccf 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -497,15 +497,16 @@ static unsigned int view_sizes; static int ok; /** - * Identifier for the churn task that runs periodically + * Identifier for the task that runs after the test to collect results */ static struct GNUNET_SCHEDULER_Task *post_test_task; /** - * Identifier for the churn task that runs periodically + * Identifier for the shutdown task */ static struct GNUNET_SCHEDULER_Task *shutdown_task; + /** * Identifier for the churn task that runs periodically */ @@ -969,7 +970,12 @@ shutdown_op (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown task scheduled, going down.\n"); in_shutdown = GNUNET_YES; - shutdown_task = NULL; + + if (NULL != shutdown_task) + { + GNUNET_SCHEDULER_cancel (shutdown_task); + shutdown_task = NULL; + } if (NULL != post_test_task) { GNUNET_SCHEDULER_cancel (post_test_task); @@ -994,6 +1000,14 @@ shutdown_op (void *cls) { clean_peer (i); } +} + +static void +trigger_shutdown (void *cls) +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown was triggerd by timeout, going down.\n"); + shutdown_task = NULL; GNUNET_SCHEDULER_shutdown (); } @@ -1009,7 +1023,7 @@ post_test_op (void *cls) post_test_task = NULL; post_test = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Post test task scheduled, going down.\n"); + "Post test task scheduled.\n"); if (NULL != churn_task) { GNUNET_SCHEDULER_cancel (churn_task); @@ -1033,7 +1047,8 @@ post_test_op (void *cls) GNUNET_YES == check_statistics_collect_completed()) { GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&shutdown_op, NULL); + shutdown_task = NULL; + GNUNET_SCHEDULER_shutdown (); } } @@ -1142,7 +1157,7 @@ rps_connect_complete_cb (void *cls, "Failed to connect to RPS service: %s\n", emsg); ok = 1; - shutdown_op (NULL); + GNUNET_SCHEDULER_shutdown (); return; } @@ -1316,14 +1331,15 @@ default_reply_handle (void *cls, rps_peer->num_recv_ids++; } - if (0 == evaluate () && HAVE_QUICK_QUIT == cur_test_run.have_quick_quit) + if (GNUNET_YES != post_test) return; + if (HAVE_QUICK_QUIT != cur_test_run.have_quick_quit) return; + if (0 == evaluate()) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test succeeded before end of duration\n"); - GNUNET_assert (NULL != post_test_task); - GNUNET_SCHEDULER_cancel (post_test_task); + if (NULL != post_test_task) GNUNET_SCHEDULER_cancel (post_test_task); post_test_task = GNUNET_SCHEDULER_add_now (&post_test_op, NULL); - GNUNET_assert (NULL!= post_test_task); + GNUNET_assert (NULL != post_test_task); } } @@ -1548,7 +1564,7 @@ churn_cb (void *cls, if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n"); - shutdown_op (NULL); + GNUNET_SCHEDULER_shutdown (); return; } GNUNET_assert (0 != entry->delta); @@ -2400,7 +2416,7 @@ post_test_shutdown_ready_cb (void *cls, GNUNET_free (stat_cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); - shutdown_op (NULL); + GNUNET_SCHEDULER_shutdown (); } else { GNUNET_free (stat_cls); } @@ -2637,7 +2653,10 @@ test_run (void *cls, GNUNET_SCHEDULER_cancel (churn_task); post_test_task = GNUNET_SCHEDULER_add_delayed (duration, &post_test_op, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for shutdown is %lu\n", timeout.rel_value_us/1000000); - shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL); + shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, + &trigger_shutdown, + NULL); + GNUNET_SCHEDULER_add_shutdown (shutdown_op, NULL); } @@ -2701,26 +2720,33 @@ run (void *cls, if (0 == timeout.rel_value_us) { duration = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90); - timeout = GNUNET_TIME_relative_multiply (duration, - 1.2 + (0.01 * num_peers)); + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + (90 * 1.2) + + (0.01 * num_peers)); } else { - duration = GNUNET_TIME_relative_multiply (timeout, 0.75 ); + duration = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + (timeout.rel_value_us/1000000) + * 0.75); } } else { if (0 == timeout.rel_value_us) { - timeout = GNUNET_TIME_relative_multiply (duration, - 1.2 + (0.01 * num_peers)); - } - else - { - GNUNET_assert (duration.rel_value_us <= timeout.rel_value_us); + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + ((duration.rel_value_us/1000000) + * 1.2) + (0.01 * num_peers)); } } + GNUNET_assert (duration.rel_value_us < timeout.rel_value_us); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "duration is %lus\n", + duration.rel_value_us/1000000); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "timeout is %lus\n", + timeout.rel_value_us/1000000); /* Compute number of bits for representing largest peer id */ for (bits_needed = 1; (1 << bits_needed) < num_peers; bits_needed++) -- cgit v1.2.3 From 08159b18571f395aace0cfa11562517109900305 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Wed, 11 Jul 2018 17:32:58 +0200 Subject: fix rps profiler: clean data structure in time --- src/rps/gnunet-rps-profiler.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index a1728cccf..02259d628 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -1353,13 +1353,13 @@ request_peers (void *cls) struct RPSPeer *rps_peer; struct PendingReply *pending_rep; - if (GNUNET_YES == in_shutdown || GNUNET_YES == post_test) - return; rps_peer = pending_req->rps_peer; GNUNET_assert (1 <= rps_peer->num_pending_reqs); GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head, rps_peer->pending_req_tail, pending_req); + rps_peer->num_pending_reqs--; + if (GNUNET_YES == in_shutdown || GNUNET_YES == post_test) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting one peer\n"); pending_rep = GNUNET_new (struct PendingReply); @@ -1372,7 +1372,6 @@ request_peers (void *cls) rps_peer->pending_rep_tail, pending_rep); rps_peer->num_pending_reps++; - rps_peer->num_pending_reqs--; } -- cgit v1.2.3 From 26a43982bf3b705770603828043a92663e8dc280 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 11 Jul 2018 23:59:45 +0200 Subject: fix div by zero --- src/core/test_core_api_reliability.c | 4 +++- src/core/test_core_quota_compliance.c | 5 +++-- src/transport/test_quota_compliance.c | 4 +++- src/transport/test_transport_api_reliability.c | 4 +++- 4 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c index 4cc5b4bcd..c7c71f1f1 100644 --- a/src/core/test_core_api_reliability.c +++ b/src/core/test_core_api_reliability.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -143,6 +143,8 @@ do_shutdown (void *cls) unsigned long long delta; delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; + if (0 == delta) + delta = 1; FPRINTF (stderr, "\nThroughput was %llu kb/s\n", total_bytes * 1000000LL / 1024 / delta); diff --git a/src/core/test_core_quota_compliance.c b/src/core/test_core_quota_compliance.c index a15105556..caff045f0 100644 --- a/src/core/test_core_quota_compliance.c +++ b/src/core/test_core_quota_compliance.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -227,7 +227,8 @@ measurement_stop (void *cls) running = GNUNET_NO; delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; - + if (0 == delta) + delta = 1; throughput_out = total_bytes_sent * 1000000LL / delta; /* convert to bytes/s */ throughput_in = total_bytes_recv * 1000000LL / delta; /* convert to bytes/s */ diff --git a/src/transport/test_quota_compliance.c b/src/transport/test_quota_compliance.c index 0ef3c864a..cd93ff855 100644 --- a/src/transport/test_quota_compliance.c +++ b/src/transport/test_quota_compliance.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -65,6 +65,8 @@ report () unsigned long long datarate; delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; + if (0 == delta) + delta = 1; datarate = (total_bytes_recv * 1000 * 1000) / delta; FPRINTF (stderr, diff --git a/src/transport/test_transport_api_reliability.c b/src/transport/test_transport_api_reliability.c index 86e2a7e9d..c6e77bae0 100644 --- a/src/transport/test_transport_api_reliability.c +++ b/src/transport/test_transport_api_reliability.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -174,6 +174,8 @@ custom_shutdown (void *cls) /* Calculcate statistics */ delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; + if (0 == delta) + delta = 1; rate = (1000LL* 1000ll * total_bytes) / (1024 * delta); FPRINTF (stderr, "\nThroughput was %llu KiBytes/s\n", -- cgit v1.2.3 From 4438597b90a7ed009e96aef280fd3be0b1576076 Mon Sep 17 00:00:00 2001 From: Bernd Fix Date: Thu, 12 Jul 2018 23:03:20 +0200 Subject: Changed decription of GNUNET_CRYPTO_EddsaPublicKey. --- src/include/gnunet_crypto_lib.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 0bffef212..7b69c157f 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -206,14 +206,15 @@ struct GNUNET_CRYPTO_EcdsaSignature /** - * Public ECC key (always for Curve25519) encoded in a format suitable - * for network transmission and EdDSA signatures. + * Public ECC key (always for curve Ed25519) encoded in a format + * suitable for network transmission and EdDSA signatures. */ struct GNUNET_CRYPTO_EddsaPublicKey { /** - * Q consists of an x- and a y-value, each mod p (256 bits), given - * here in affine coordinates and Ed25519 standard compact format. + * Point Q consists of a y-value mod p (256 bits); the x-value is + * always positive. The point is stored in Ed25519 standard + * compact format. */ unsigned char q_y[256 / 8]; -- cgit v1.2.3 From f5164502be55aa48ea4c3b44167e19ac15ba53af Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 13 Jul 2018 01:11:32 +0200 Subject: rps profiler: proper disconnect from service --- src/rps/gnunet-rps-profiler.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index 02259d628..a06598764 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -883,6 +883,9 @@ static int check_statistics_collect_completed () return GNUNET_YES; } +static void +rps_disconnect_adapter (void *cls, + void *op_result); static void cancel_pending_req (struct PendingRequest *pending_req) @@ -928,15 +931,8 @@ clean_peer (unsigned peer_index) cancel_request (pending_rep); } pending_req = rps_peers[peer_index].pending_req_head; - while (NULL != (pending_req = rps_peers[peer_index].pending_req_head)) - { - cancel_pending_req (pending_req); - } - if (NULL != rps_peers[peer_index].rps_handle) - { - GNUNET_RPS_disconnect (rps_peers[peer_index].rps_handle); - rps_peers[peer_index].rps_handle = NULL; - } + rps_disconnect_adapter (&rps_peers[peer_index], + &rps_peers[peer_index].rps_handle); for (unsigned stat_type = STAT_TYPE_ROUNDS; stat_type < STAT_TYPE_MAX; stat_type++) @@ -1277,6 +1273,7 @@ rps_disconnect_adapter (void *cls, { struct RPSPeer *peer = cls; struct GNUNET_RPS_Handle *h = op_result; + struct PendingRequest *pending_req; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnect_adapter (%u)\n", @@ -1284,6 +1281,10 @@ rps_disconnect_adapter (void *cls, GNUNET_assert (NULL != peer); if (NULL != peer->rps_handle) { + while (NULL != (pending_req = peer->pending_req_head)) + { + cancel_pending_req (pending_req); + } GNUNET_assert (h == peer->rps_handle); GNUNET_RPS_disconnect (h); peer->rps_handle = NULL; -- cgit v1.2.3 From 330bb7242aed7c426cfdbb589155db5bb3fa83dc Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 13 Jul 2018 01:13:53 +0200 Subject: restructure rps service: start keeping track of channels --- src/rps/gnunet-service-rps.c | 55 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index aef6a72de..c60ab5e63 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -264,6 +264,34 @@ struct PeersIteratorCls void *cls; }; +/** + * @brief Context for a channel + */ +struct ChannelCtx +{ + /** + * @brief Meant to be used in a DLL + */ + struct ChannelCtx *next; + struct ChannelCtx *prev; + + /** + * @brief The channel itself + */ + struct GNUNET_CADET_Channel *channel; + + /** + * @brief The peer context associated with the channel + */ + struct PeerContext *peer_ctx; +}; + +/** + * @brief The DLL of channel contexts + */ +static struct ChannelCtx *channel_ctx_head; +static struct ChannelCtx *channel_ctx_tail; + /** * @brief Hashmap of valid peers. */ @@ -1521,6 +1549,7 @@ Peers_handle_inbound_channel (void *cls, { struct PeerContext *peer_ctx; struct GNUNET_PeerIdentity *ctx_peer; + struct ChannelCtx *channel_ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "New channel was established to us (Peer %s).\n", @@ -1531,6 +1560,10 @@ Peers_handle_inbound_channel (void *cls, set_peer_live (peer_ctx); ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity); *ctx_peer = *initiator; + channel_ctx = GNUNET_new (struct ChannelCtx); + channel_ctx->peer_ctx = peer_ctx; + channel_ctx->channel = channel; + GNUNET_CONTAINER_DLL_insert (channel_ctx_head, channel_ctx_tail, channel_ctx); /* We only accept one incoming channel per peer */ if (GNUNET_YES == Peers_check_peer_send_intention (initiator)) { @@ -1543,10 +1576,10 @@ Peers_handle_inbound_channel (void *cls, GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); peer_ctx->recv_channel = channel; /* return the channel context */ - return ctx_peer; + return channel_ctx; } peer_ctx->recv_channel = channel; - return ctx_peer; + return channel_ctx; } @@ -1658,7 +1691,8 @@ void Peers_cleanup_destroyed_channel (void *cls, const struct GNUNET_CADET_Channel *channel) { - struct GNUNET_PeerIdentity *peer = cls; + struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; struct PeerContext *peer_ctx; uint32_t *channel_flag; @@ -2670,7 +2704,8 @@ static void cleanup_destroyed_channel (void *cls, const struct GNUNET_CADET_Channel *channel) { - struct GNUNET_PeerIdentity *peer = cls; + struct ChannelCtx *channel_ctx = cls; // FIXME: free this context! + struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; uint32_t *channel_flag; struct PeerContext *peer_ctx; @@ -3163,7 +3198,8 @@ static void handle_peer_check (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct GNUNET_PeerIdentity *peer = cls; + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer)); @@ -3183,7 +3219,8 @@ static void handle_peer_push (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct GNUNET_PeerIdentity *peer = cls; + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; // (check the proof of work (?)) @@ -3244,7 +3281,8 @@ static void handle_peer_pull_request (void *cls, const struct GNUNET_MessageHeader *msg) { - struct GNUNET_PeerIdentity *peer = cls; + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; const struct GNUNET_PeerIdentity *view_array; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer)); @@ -3324,8 +3362,9 @@ static void handle_peer_pull_reply (void *cls, const struct GNUNET_RPS_P2P_PullReplyMessage *msg) { + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id; const struct GNUNET_PeerIdentity *peers; - struct GNUNET_PeerIdentity *sender = cls; uint32_t i; #ifdef ENABLE_MALICIOUS struct AttackedPeer *tmp_att_peer; -- cgit v1.2.3 From b197aa1988037a2839c4dcf752a343d9cfae7987 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 13 Jul 2018 01:14:43 +0200 Subject: rps service: check return value when opening cadet port --- src/rps/gnunet-service-rps.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index c60ab5e63..5d568dfac 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -4389,6 +4389,13 @@ run (void *cls, NULL, /* WindowSize handler */ cleanup_destroyed_channel, /* Disconnect handler */ cadet_handlers); + if (NULL == cadet_port) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Cadet port `%s' is already in use.\n", + GNUNET_APPLICATION_PORT_RPS); + GNUNET_assert (0); + } peerinfo_handle = GNUNET_PEERINFO_connect (cfg); -- cgit v1.2.3 From 2a7eb7cb6d8fcc01e3d06b7c2b107549ae8dab40 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 13 Jul 2018 09:53:05 +0200 Subject: Revert "restructure rps service: start keeping track of channels" This reverts commit 330bb7242aed7c426cfdbb589155db5bb3fa83dc. --- src/rps/gnunet-service-rps.c | 55 +++++++------------------------------------- 1 file changed, 8 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 5d568dfac..12794945e 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -264,34 +264,6 @@ struct PeersIteratorCls void *cls; }; -/** - * @brief Context for a channel - */ -struct ChannelCtx -{ - /** - * @brief Meant to be used in a DLL - */ - struct ChannelCtx *next; - struct ChannelCtx *prev; - - /** - * @brief The channel itself - */ - struct GNUNET_CADET_Channel *channel; - - /** - * @brief The peer context associated with the channel - */ - struct PeerContext *peer_ctx; -}; - -/** - * @brief The DLL of channel contexts - */ -static struct ChannelCtx *channel_ctx_head; -static struct ChannelCtx *channel_ctx_tail; - /** * @brief Hashmap of valid peers. */ @@ -1549,7 +1521,6 @@ Peers_handle_inbound_channel (void *cls, { struct PeerContext *peer_ctx; struct GNUNET_PeerIdentity *ctx_peer; - struct ChannelCtx *channel_ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "New channel was established to us (Peer %s).\n", @@ -1560,10 +1531,6 @@ Peers_handle_inbound_channel (void *cls, set_peer_live (peer_ctx); ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity); *ctx_peer = *initiator; - channel_ctx = GNUNET_new (struct ChannelCtx); - channel_ctx->peer_ctx = peer_ctx; - channel_ctx->channel = channel; - GNUNET_CONTAINER_DLL_insert (channel_ctx_head, channel_ctx_tail, channel_ctx); /* We only accept one incoming channel per peer */ if (GNUNET_YES == Peers_check_peer_send_intention (initiator)) { @@ -1576,10 +1543,10 @@ Peers_handle_inbound_channel (void *cls, GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); peer_ctx->recv_channel = channel; /* return the channel context */ - return channel_ctx; + return ctx_peer; } peer_ctx->recv_channel = channel; - return channel_ctx; + return ctx_peer; } @@ -1691,8 +1658,7 @@ void Peers_cleanup_destroyed_channel (void *cls, const struct GNUNET_CADET_Channel *channel) { - struct ChannelCtx *channel_ctx = cls; - const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; + struct GNUNET_PeerIdentity *peer = cls; struct PeerContext *peer_ctx; uint32_t *channel_flag; @@ -2704,8 +2670,7 @@ static void cleanup_destroyed_channel (void *cls, const struct GNUNET_CADET_Channel *channel) { - struct ChannelCtx *channel_ctx = cls; // FIXME: free this context! - struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; + struct GNUNET_PeerIdentity *peer = cls; uint32_t *channel_flag; struct PeerContext *peer_ctx; @@ -3198,8 +3163,7 @@ static void handle_peer_check (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct ChannelCtx *channel_ctx = cls; - const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; + const struct GNUNET_PeerIdentity *peer = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer)); @@ -3219,8 +3183,7 @@ static void handle_peer_push (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct ChannelCtx *channel_ctx = cls; - const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; + const struct GNUNET_PeerIdentity *peer = cls; // (check the proof of work (?)) @@ -3281,8 +3244,7 @@ static void handle_peer_pull_request (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct ChannelCtx *channel_ctx = cls; - const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; + struct GNUNET_PeerIdentity *peer = cls; const struct GNUNET_PeerIdentity *view_array; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer)); @@ -3362,9 +3324,8 @@ static void handle_peer_pull_reply (void *cls, const struct GNUNET_RPS_P2P_PullReplyMessage *msg) { - const struct ChannelCtx *channel_ctx = cls; - const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id; const struct GNUNET_PeerIdentity *peers; + struct GNUNET_PeerIdentity *sender = cls; uint32_t i; #ifdef ENABLE_MALICIOUS struct AttackedPeer *tmp_att_peer; -- cgit v1.2.3 From 0f75e5c54c6e6c9087cf565539266514abd67e98 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Thu, 19 Jul 2018 22:16:00 +0200 Subject: change JWT algorithm to HMAC --- src/identity-provider/identity-provider.conf | 1 + src/identity-provider/jwt.c | 49 +++++----------------- src/identity-provider/jwt.h | 3 +- src/identity-provider/plugin_rest_openid_connect.c | 26 ++++++++++-- 4 files changed, 35 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf index cc50152a1..99c0a50be 100644 --- a/src/identity-provider/identity-provider.conf +++ b/src/identity-provider/identity-provider.conf @@ -16,6 +16,7 @@ DATABASE = sqlite #ADDRESS = https://identity.gnu:8000#/login ADDRESS = https://reclaim.ui/#/login PSW = secret +JWT_SECRET = secret EXPIRATION_TIME = 3600 [identity-provider-sqlite] diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c index 1a984f7b5..7ac4f0025 100644 --- a/src/identity-provider/jwt.c +++ b/src/identity-provider/jwt.c @@ -30,15 +30,14 @@ #define JWT_ALG "alg" -/*TODO is this the correct way to define new algs? */ -#define JWT_ALG_VALUE "urn:org:gnunet:jwt:alg:ecdsa:ed25519" +/* Use 512bit HMAC */ +#define JWT_ALG_VALUE "HS512" #define JWT_TYP "typ" #define JWT_TYP_VALUE "jwt" -//TODO change server address -#define SERVER_ADDRESS "https://localhost" +#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo" static char* create_jwt_header(void) @@ -65,13 +64,12 @@ create_jwt_header(void) */ char* jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, + const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key) + const struct GNUNET_CRYPTO_AuthKey *priv_key) { struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; - struct GNUNET_CRYPTO_EcdsaPublicKey sub_key; - struct GNUNET_CRYPTO_EcdsaSignature signature; - struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + struct GNUNET_HashCode signature; char* audience; char* subject; char* header; @@ -90,32 +88,25 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, //auth_time only if max_age //nonce only if nonce // OPTIONAL acr,amr,azp - GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &sub_key); - /* TODO maybe we should use a local identity here */ subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); audience = GNUNET_STRINGS_data_to_string_alloc (aud_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? */ + //iss REQUIRED case sensitive server uri with https + //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) json_object_set_new (body, "iss", json_string (SERVER_ADDRESS)); //sub REQUIRED public key identity, not exceed 255 ASCII length json_object_set_new (body, "sub", json_string (subject)); - /* TODO what should be in here exactly? */ //aud REQUIRED public key client_id must be there 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); @@ -148,32 +139,13 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 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_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature); GNUNET_STRINGS_base64_encode ((const char*)&signature, - sizeof (struct GNUNET_CRYPTO_EcdsaSignature), + sizeof (struct GNUNET_HashCode), &signature_base64); GNUNET_asprintf (&result, "%s.%s.%s", header_base64, body_base64, signature_base64); @@ -184,6 +156,5 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, GNUNET_free (signature_base64); GNUNET_free (body_base64); GNUNET_free (header_base64); - GNUNET_free (purpose); return result; } diff --git a/src/identity-provider/jwt.h b/src/identity-provider/jwt.h index 072958973..80b6caa33 100644 --- a/src/identity-provider/jwt.h +++ b/src/identity-provider/jwt.h @@ -3,7 +3,8 @@ char* jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, + const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key); + const struct GNUNET_CRYPTO_AuthKey *priv_key); #endif diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c index 9c2f7fb3d..cc4b83dae 100644 --- a/src/identity-provider/plugin_rest_openid_connect.c +++ b/src/identity-provider/plugin_rest_openid_connect.c @@ -1412,6 +1412,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, json_t *root, *ticket_string, *nonce, *max_age; json_error_t error; char *json_response; + char *jwt_secret; /* * Check Authorization @@ -1447,7 +1448,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), &user_psw); + GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw); if ( NULL == user_psw ) { @@ -1598,7 +1599,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } //decode code - GNUNET_STRINGS_base64_decode(code,strlen(code),&code_output); + GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output); root = json_loads (code_output, 0, &error); GNUNET_free(code_output); ticket_string = json_object_get (root, "ticket"); @@ -1717,15 +1718,32 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, { GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code...."); + handle->edesc = GNUNET_strdup("invalid code..."); handle->response_code = MHD_HTTP_BAD_REQUEST; GNUNET_SCHEDULER_add_now (&do_error, handle); GNUNET_free(ticket); return; } + if ( GNUNET_OK + != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + "jwt_secret", &jwt_secret) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("No signing secret configured!"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free(ticket); + return; + } + struct GNUNET_CRYPTO_AuthKey jwt_sign_key; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk); + GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key); char *id_token = jwt_create_from_list(&ticket->audience, + &pk, cl, - GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego)); + &jwt_sign_key); //Create random access_token char* access_token_number; -- cgit v1.2.3 From 4fd677cec39e5621d16bc2c63926b803b31582e3 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Thu, 19 Jul 2018 23:28:53 +0200 Subject: renamed identity-provider subsystem to reclaim --- configure.ac | 4 +- po/POTFILES.in | 20 +- src/Makefile.am | 6 +- src/identity-attribute/Makefile.am | 44 - src/identity-attribute/identity_attribute.c | 444 ---- src/identity-attribute/identity_attribute.h | 54 - .../plugin_identity_attribute_gnuid.c | 182 -- src/identity-provider/.gitignore | 2 - src/identity-provider/Makefile.am | 140 - src/identity-provider/gnunet-idp.c | 517 ---- .../gnunet-service-identity-provider.c | 2786 -------------------- src/identity-provider/identity-provider.conf | 23 - src/identity-provider/identity-token.conf | 2 - src/identity-provider/identity_provider.h | 410 --- src/identity-provider/identity_provider_api.c | 1383 ---------- src/identity-provider/jwt.c | 160 -- src/identity-provider/jwt.h | 10 - .../plugin_gnsrecord_identity_provider.c | 265 -- .../plugin_identity_provider_sqlite.c | 734 ------ .../plugin_rest_identity_provider.c | 1253 --------- src/identity-provider/plugin_rest_openid_connect.c | 2227 ---------------- src/identity-provider/test_idp.conf | 33 - src/identity-provider/test_idp.sh | 31 - src/identity-provider/test_idp_attribute.sh | 40 - src/identity-provider/test_idp_consume.sh | 43 - src/identity-provider/test_idp_defaults.conf | 24 - src/identity-provider/test_idp_issue.sh | 42 - src/identity-provider/test_idp_revoke.sh | 65 - src/include/Makefile.am | 2 +- src/include/gnunet_identity_attribute_lib.h | 281 -- src/include/gnunet_identity_attribute_plugin.h | 147 -- src/include/gnunet_identity_provider_plugin.h | 121 - src/include/gnunet_identity_provider_service.h | 378 --- src/include/gnunet_protocols.h | 30 +- src/include/gnunet_reclaim_attribute_lib.h | 281 ++ src/include/gnunet_reclaim_attribute_plugin.h | 147 ++ src/include/gnunet_reclaim_plugin.h | 121 + src/include/gnunet_reclaim_service.h | 378 +++ src/reclaim-attribute/Makefile.am | 44 + .../plugin_reclaim_attribute_gnuid.c | 182 ++ src/reclaim-attribute/reclaim_attribute.c | 444 ++++ src/reclaim-attribute/reclaim_attribute.h | 54 + src/reclaim/.gitignore | 2 + src/reclaim/Makefile.am | 140 + src/reclaim/gnunet-reclaim.c | 517 ++++ src/reclaim/gnunet-service-reclaim.c | 2786 ++++++++++++++++++++ src/reclaim/jwt.c | 160 ++ src/reclaim/jwt.h | 10 + src/reclaim/plugin_gnsrecord_reclaim.c | 265 ++ src/reclaim/plugin_reclaim_sqlite.c | 734 ++++++ src/reclaim/plugin_rest_openid_connect.c | 2227 ++++++++++++++++ src/reclaim/plugin_rest_reclaim.c | 1253 +++++++++ src/reclaim/reclaim.conf | 23 + src/reclaim/reclaim.h | 410 +++ src/reclaim/reclaim_api.c | 1383 ++++++++++ src/reclaim/test_reclaim.sh | 31 + src/reclaim/test_reclaim_attribute.sh | 40 + src/reclaim/test_reclaim_consume.sh | 43 + src/reclaim/test_reclaim_defaults.conf | 24 + src/reclaim/test_reclaim_issue.sh | 42 + src/reclaim/test_reclaim_revoke.sh | 65 + 61 files changed, 11838 insertions(+), 11871 deletions(-) delete mode 100644 src/identity-attribute/Makefile.am delete mode 100644 src/identity-attribute/identity_attribute.c delete mode 100644 src/identity-attribute/identity_attribute.h delete mode 100644 src/identity-attribute/plugin_identity_attribute_gnuid.c delete mode 100644 src/identity-provider/.gitignore delete mode 100644 src/identity-provider/Makefile.am delete mode 100644 src/identity-provider/gnunet-idp.c delete mode 100644 src/identity-provider/gnunet-service-identity-provider.c delete mode 100644 src/identity-provider/identity-provider.conf delete mode 100644 src/identity-provider/identity-token.conf delete mode 100644 src/identity-provider/identity_provider.h delete mode 100644 src/identity-provider/identity_provider_api.c delete mode 100644 src/identity-provider/jwt.c delete mode 100644 src/identity-provider/jwt.h delete mode 100644 src/identity-provider/plugin_gnsrecord_identity_provider.c delete mode 100644 src/identity-provider/plugin_identity_provider_sqlite.c delete mode 100644 src/identity-provider/plugin_rest_identity_provider.c delete mode 100644 src/identity-provider/plugin_rest_openid_connect.c delete mode 100644 src/identity-provider/test_idp.conf delete mode 100755 src/identity-provider/test_idp.sh delete mode 100755 src/identity-provider/test_idp_attribute.sh delete mode 100755 src/identity-provider/test_idp_consume.sh delete mode 100644 src/identity-provider/test_idp_defaults.conf delete mode 100755 src/identity-provider/test_idp_issue.sh delete mode 100755 src/identity-provider/test_idp_revoke.sh delete mode 100644 src/include/gnunet_identity_attribute_lib.h delete mode 100644 src/include/gnunet_identity_attribute_plugin.h delete mode 100644 src/include/gnunet_identity_provider_plugin.h delete mode 100644 src/include/gnunet_identity_provider_service.h create mode 100644 src/include/gnunet_reclaim_attribute_lib.h create mode 100644 src/include/gnunet_reclaim_attribute_plugin.h create mode 100644 src/include/gnunet_reclaim_plugin.h create mode 100644 src/include/gnunet_reclaim_service.h create mode 100644 src/reclaim-attribute/Makefile.am create mode 100644 src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c create mode 100644 src/reclaim-attribute/reclaim_attribute.c create mode 100644 src/reclaim-attribute/reclaim_attribute.h create mode 100644 src/reclaim/.gitignore create mode 100644 src/reclaim/Makefile.am create mode 100644 src/reclaim/gnunet-reclaim.c create mode 100644 src/reclaim/gnunet-service-reclaim.c create mode 100644 src/reclaim/jwt.c create mode 100644 src/reclaim/jwt.h create mode 100644 src/reclaim/plugin_gnsrecord_reclaim.c create mode 100644 src/reclaim/plugin_reclaim_sqlite.c create mode 100644 src/reclaim/plugin_rest_openid_connect.c create mode 100644 src/reclaim/plugin_rest_reclaim.c create mode 100644 src/reclaim/reclaim.conf create mode 100644 src/reclaim/reclaim.h create mode 100644 src/reclaim/reclaim_api.c create mode 100755 src/reclaim/test_reclaim.sh create mode 100755 src/reclaim/test_reclaim_attribute.sh create mode 100755 src/reclaim/test_reclaim_consume.sh create mode 100644 src/reclaim/test_reclaim_defaults.conf create mode 100755 src/reclaim/test_reclaim_issue.sh create mode 100755 src/reclaim/test_reclaim_revoke.sh (limited to 'src') diff --git a/configure.ac b/configure.ac index c7314d765..535ce0ffe 100644 --- a/configure.ac +++ b/configure.ac @@ -1759,8 +1759,8 @@ src/zonemaster/Makefile src/zonemaster/zonemaster.conf src/rest/Makefile src/abe/Makefile -src/identity-attribute/Makefile -src/identity-provider/Makefile +src/reclaim-attribute/Makefile +src/reclaim/Makefile pkgconfig/Makefile pkgconfig/gnunetarm.pc pkgconfig/gnunetats.pc diff --git a/po/POTFILES.in b/po/POTFILES.in index 83c3c7bdd..86235f860 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -198,16 +198,6 @@ 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-provider/plugin_rest_openid_connect.c src/identity/gnunet-identity.c src/identity/gnunet-service-identity.c src/identity/identity_api.c @@ -297,6 +287,16 @@ src/psycutil/psyc_env.c src/psycutil/psyc_message.c src/psycutil/psyc_slicer.c src/pt/gnunet-daemon-pt.c +src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c +src/reclaim-attribute/reclaim_attribute.c +src/reclaim/gnunet-reclaim.c +src/reclaim/gnunet-service-reclaim.c +src/reclaim/jwt.c +src/reclaim/plugin_gnsrecord_reclaim.c +src/reclaim/plugin_reclaim_sqlite.c +src/reclaim/plugin_rest_openid_connect.c +src/reclaim/plugin_rest_reclaim.c +src/reclaim/reclaim_api.c src/regex/gnunet-daemon-regexprofiler.c src/regex/gnunet-regex-profiler.c src/regex/gnunet-regex-simulation-profiler.c diff --git a/src/Makefile.am b/src/Makefile.am index 00f30adc3..4ded81891 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,11 +19,13 @@ if HAVE_EXPERIMENTAL social # dv (FTBFS) if HAVE_ABE +if HAVE_JSON EXP_DIR += \ abe \ credential \ - identity-attribute \ - identity-provider + reclaim-attribute \ + reclaim +endif endif if HAVE_JSON EXP_DIR += \ diff --git a/src/identity-attribute/Makefile.am b/src/identity-attribute/Makefile.am deleted file mode 100644 index 2c73a443e..000000000 --- a/src/identity-attribute/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -# 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 deleted file mode 100644 index 7d47c46a7..000000000 --- a/src/identity-attribute/identity_attribute.c +++ /dev/null @@ -1,444 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ - -/** - * @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; -} - -/** - * Add a new claim list entry. - * - * @param claim_list the attribute name - * @param attr_name the attribute name - * @param type the attribute type - * @param data the attribute value - * @param data_size the attribute value size - * @return - */ -void -GNUNET_IDENTITY_ATTRIBUTE_list_add (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *claim_list, - const char* attr_name, - uint32_t type, - const void* data, - size_t data_size) -{ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; - le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry); - le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name, - type, - data, - data_size); - GNUNET_CONTAINER_DLL_insert (claim_list->list_head, - claim_list->list_tail, - le); -} - -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; - - 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); - result_le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (le->claim->name, - le->claim->type, - le->claim->data, - le->claim->data_size); - 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 deleted file mode 100644 index 2346dcde1..000000000 --- a/src/identity-attribute/identity_attribute.h +++ /dev/null @@ -1,54 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @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 deleted file mode 100644 index c09b167f5..000000000 --- a/src/identity-attribute/plugin_identity_attribute_gnuid.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @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 - - -/** - * 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/.gitignore b/src/identity-provider/.gitignore deleted file mode 100644 index ef77fccdc..000000000 --- a/src/identity-provider/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -gnunet-service-identity-provider -gnunet-identity-token diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am deleted file mode 100644 index 2eb699542..000000000 --- a/src/identity-provider/Makefile.am +++ /dev/null @@ -1,140 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include - - plugindir = $(libdir)/gnunet - -if MINGW - WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -endif - -if USE_COVERAGE - AM_CFLAGS = --coverage -O0 - 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/ - -pkgcfg_DATA = \ - identity-provider.conf - -lib_LTLIBRARIES = \ - libgnunetidentityprovider.la -plugin_LTLIBRARIES = \ - libgnunet_plugin_rest_identity_provider.la \ - libgnunet_plugin_rest_openid_connect.la \ - libgnunet_plugin_gnsrecord_identity_provider.la \ - $(SQLITE_PLUGIN) - -bin_PROGRAMS = \ - gnunet-idp - -libexec_PROGRAMS = \ - gnunet-service-identity-provider - -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 -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) - -libgnunetidentityprovider_la_SOURCES = \ - identity_provider_api.c \ - identity_provider.h -libgnunetidentityprovider_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) $(XLIB) -libgnunetidentityprovider_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 0:0:0 - -libgnunet_plugin_rest_identity_provider_la_SOURCES = \ - 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) - -libgnunet_plugin_rest_openid_connect_la_SOURCES = \ - plugin_rest_openid_connect.c \ - jwt.c -libgnunet_plugin_rest_openid_connect_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_openid_connect_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) - -gnunet_idp_SOURCES = \ - gnunet-idp.c -gnunet_idp_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(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-idp.c b/src/identity-provider/gnunet-idp.c deleted file mode 100644 index 79e4f8d27..000000000 --- a/src/identity-provider/gnunet-idp.c +++ /dev/null @@ -1,517 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @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; - -/** - * Attribute expiration interval - */ -static struct GNUNET_TIME_Relative exp_interval; - -/** - * Timeout task - */ -static struct GNUNET_SCHEDULER_Task *timeout; - -static void -do_cleanup(void *cls) -{ - if (NULL != timeout) - GNUNET_SCHEDULER_cancel (timeout); - if (NULL != idp_op) - GNUNET_IDENTITY_PROVIDER_cancel (idp_op); - 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; - idp_op = NULL; - 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) -{ - idp_op = NULL; - 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) - { - idp_op = NULL; - 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 -timeout_task (void *cls) -{ - timeout = NULL; - ret = 1; - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - "Timeout\n"); - GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); -} - -static void -process_rvk (void *cls, int success, const char* msg) -{ - idp_op = NULL; - 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); - timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10), - &timeout_task, - NULL); - return; - } - if (revoke_ticket) - { - idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle, - pkey, - &ticket, - &process_rvk, - NULL); - return; - } - if (attr_name) - { - 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, - &exp_interval, - &store_attr_cont, - NULL); - return; - } - GNUNET_SCHEDULER_add_now (&do_cleanup, 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_iter_finished (void *cls) -{ - if (NULL == pkey) - { - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - "Ego %s not found\n", ego_name); - return; - } - - 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 int init = GNUNET_YES; - -static void -ego_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - if (NULL == name) { - if (GNUNET_YES == init) { - init = GNUNET_NO; - GNUNET_SCHEDULER_add_now (&ego_iter_finished, NULL); - } - return; - } - if (0 != strcmp (name, ego_name)) - return; - pkey = GNUNET_IDENTITY_ego_get_private_key (ego); -} - - -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - ret = 0; - if (NULL == ego_name) - { - ret = 1; - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - _("Ego is required\n")); - return; - } - - if ( (NULL == attr_value) && (NULL != attr_name) ) - { - ret = 1; - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - _("Attribute value missing!\n")); - return; - } - - if ( (NULL == rp) && (NULL != issue_attrs) ) - { - ret = 1; - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - _("Requesting party key 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[]) -{ - exp_interval = GNUNET_TIME_UNIT_HOURS; - 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_relative_time ('E', - "expiration", - NULL, - gettext_noop ("Expiration interval of the attribute"), - &exp_interval), - - GNUNET_GETOPT_OPTION_END - }; - if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct", - "ct", options, - &run, NULL)) - return 1; - else - return ret; -} diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c deleted file mode 100644 index 4563fdfa1..000000000 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ /dev/null @@ -1,2786 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @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 "gnunet_constants.h" -#include "gnunet_protocols.h" -#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" - -/** - * First pass state - */ -#define STATE_INIT 0 - -/** - * Normal operation state - */ -#define STATE_POST_INIT 1 - -/** - * Minimum interval between updates - */ -#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES - -/** - * Standard token expiration time - */ -#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS - -/** - * Identity handle - */ -static struct GNUNET_IDENTITY_Handle *identity_handle; - -/** - * Database handle - */ -static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database; - -/** - * Name of DB plugin - */ -static char *db_lib_name; - -/** - * Token expiration interval - */ -static struct GNUNET_TIME_Relative token_expiration_interval; - -/** - * Namestore handle - */ -static struct GNUNET_NAMESTORE_Handle *ns_handle; - -/** - * GNS handle - */ -static struct GNUNET_GNS_Handle *gns_handle; - -/** - * Credential handle - */ -static struct GNUNET_CREDENTIAL_Handle *credential_handle; - -/** - * Namestore qe - */ -static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; - -/** - * Namestore iterator - */ -static struct GNUNET_NAMESTORE_ZoneIterator *ns_it; - -/** - * Timeout task - */ -static struct GNUNET_SCHEDULER_Task *timeout_task; - -/** - * Update task - */ -static struct GNUNET_SCHEDULER_Task *update_task; - - -/** - * Currently processed token - */ -static struct IdentityToken *token; - -/** - * Label for currently processed token - */ -static char* label; - -/** - * Scopes for processed token - */ -static char* scopes; - -/** - * Handle to the statistics service. - */ -static struct GNUNET_STATISTICS_Handle *stats; - -/** - * Our configuration. - */ -static const struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * An idp client - */ -struct IdpClient; - -/** - * A ticket iteration operation. - */ -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; - - /** - * 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; - - /** - * 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; - - /** - * 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 *attr_iter_head; - - /** - * Tail of the DLL of - * Attribute iteration operations - * in progress initiated by this client - */ - struct AttributeIterator *attr_iter_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 *revoke_op_head; - - /** - * Tail of DLL of ticket revocation ops - */ - struct TicketRevocationHandle *revoke_op_tail; - - /** - * Head of DLL of ticket issue ops - */ - struct TicketIssueHandle *issue_op_head; - - /** - * Tail of DLL of ticket issue ops - */ - struct TicketIssueHandle *issue_op_tail; - - /** - * Head of DLL of ticket consume ops - */ - struct ConsumeTicketHandle *consume_op_head; - - /** - * Tail of DLL of ticket consume ops - */ - struct ConsumeTicketHandle *consume_op_tail; - - /** - * Head of DLL of attribute store ops - */ - struct AttributeStoreHandle *store_op_head; - - /** - * Tail of DLL of attribute store ops - */ - struct AttributeStoreHandle *store_op_tail; - -}; - -struct AttributeStoreHandle -{ - /** - * DLL - */ - struct AttributeStoreHandle *next; - - /** - * DLL - */ - struct AttributeStoreHandle *prev; - - /** - * 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; - - /** - * The attribute expiration interval - */ - struct GNUNET_TIME_Relative exp; - - /** - * request id - */ - uint32_t r_id; -}; - - -/* Prototype */ -struct ParallelLookup; - -struct ConsumeTicketHandle -{ - /** - * DLL - */ - struct ConsumeTicketHandle *next; - - /** - * DLL - */ - struct ConsumeTicketHandle *prev; - - /** - * Client connection - */ - struct IdpClient *client; - - /** - * Ticket - */ - struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; - - /** - * LookupRequest - */ - struct GNUNET_GNS_LookupRequest *lookup_request; - - /** - * Audience Key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - /** - * Audience Key - */ - 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; -}; - -/** - * 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 *prev; - - /** - * DLL - */ - struct TicketRevocationHandle *next; - - /** - * Client connection - */ - 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 identity; - - /** - * Ticket to issue - */ - struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; - - /** - * QueueEntry - */ - struct GNUNET_NAMESTORE_QueueEntry *ns_qe; - - /** - * Namestore iterator - */ - struct GNUNET_NAMESTORE_ZoneIterator *ns_it; - - /** - * The ABE master key - */ - struct GNUNET_ABE_AbeMasterKey *abe_key; - - /** - * Offset - */ - uint32_t offset; - - /** - * request id - */ - uint32_t r_id; -}; - - - -/** - * Ticket issue request handle - */ -struct TicketIssueHandle -{ - /** - * DLL - */ - struct TicketIssueHandle *prev; - - /** - * DLL - */ - struct TicketIssueHandle *next; - - /** - * Client connection - */ - struct IdpClient *client; - - /** - * Attributes to issue - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; - - /** - * Issuer Key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - /** - * Ticket to issue - */ - struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; - - /** - * QueueEntry - */ - struct GNUNET_NAMESTORE_QueueEntry *ns_qe; - - /** - * request id - */ - uint32_t r_id; -}; - - -/** - * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format - * - */ -struct EgoEntry -{ - /** - * DLL - */ - struct EgoEntry *next; - - /** - * DLL - */ - struct EgoEntry *prev; - - /** - * Ego handle - */ - struct GNUNET_IDENTITY_Ego *ego; - - /** - * Attribute map. Contains the attributes as json_t - */ - struct GNUNET_CONTAINER_MultiHashMap *attr_map; - -}; - -/** - * 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); - GNUNET_free_non_null (token); - GNUNET_free_non_null (label); - -} - -/** - * Shutdown task - * - * @param cls NULL - */ -static void -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) -{ - struct AbeBootstrapHandle *abh = cls; - if (GNUNET_SYSERR == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to bootstrap ABE master %s\n", - emsg); - abh->proc (abh->proc_cls, NULL); - GNUNET_free (abh->abe_key); - GNUNET_free (abh); - return; - } - abh->proc (abh->proc_cls, abh->abe_key); - GNUNET_free (abh); -} - -/** - * Generates and stores a new ABE key - */ -static void -bootstrap_store_task (void *cls) -{ - 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); -} - -/** - * Error checking for ABE master - */ -static void -bootstrap_abe_error (void *cls) -{ - struct AbeBootstrapHandle *abh = cls; - abh->proc (abh->proc_cls, NULL); - GNUNET_free (abh); -} - - -/** - * Handle ABE lookup in namestore - */ -static void -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;iproc (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); -} - -/** - * 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 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) - { - 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); - } -} - - - -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; -} - -/** - * Cleanup ticket consume handle - * @param handle the handle to clean up - */ -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 -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 TicketResultMessage *irm; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf; - - /* 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); -} - -static void -store_ticket_issue_cont (void *cls, - int32_t success, - const char *emsg) -{ - struct TicketIssueHandle *handle = cls; - - handle->ns_qe = NULL; - GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head, - handle->client->issue_op_tail, - handle); - if (GNUNET_SYSERR == success) - { - 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); -} - - - -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; - } - 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; - } - 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++; - } - 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_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -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); - GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, - idp->issue_op_tail, - ih); - bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO); - GNUNET_SERVICE_client_continue (idp->client); - -} - -/********************************************************** - * 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 -send_revocation_finished (struct TicketRevocationHandle *rh, - uint32_t success) -{ - struct GNUNET_MQ_Envelope *env; - struct RevokeTicketResultMessage *trm; - - GNUNET_break(TKT_database->delete_ticket (TKT_database->cls, - &rh->ticket)); - - 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->revoke_op_head, - rh->client->revoke_op_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 -revocation_reissue_tickets (struct TicketRevocationHandle *rh); - - -static void reissue_next (void *cls) -{ - struct TicketRevocationHandle *rh = cls; - revocation_reissue_tickets (rh); -} - - -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 - * - * @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) -{ - 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_log (GNUNET_ERROR_TYPE_DEBUG, - "Iteration done\n"); - return; - } - - if (0 == memcmp (&ticket->audience, - &rh->ticket.audience, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Do not reissue for this identity.!\n"); - label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd, - sizeof (uint64_t)); - //Delete record - rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, - &rh->identity, - label, - 0, - NULL, - &reissue_ticket_cont, - rh); - - GNUNET_free (label); - return; - } - - /* - * 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) - { - for (le_rollover = rh->rvk_attrs->list_head; - NULL != le_rollover; - le_rollover = le_rollover->next) - { - if (0 == strcmp (le_rollover->claim->name, - le->claim->name)) - { - reissue_ticket = GNUNET_YES; - le->claim->version = le_rollover->claim->version; - } - } - } - - if (GNUNET_NO == reissue_ticket) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Skipping ticket.\n"); - - rh->offset++; - GNUNET_SCHEDULER_add_now (&reissue_next, rh); - - - return; - } - - //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++; - } - 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))) - { - GNUNET_break (0); - } - if (GNUNET_NO == ret) - { - send_revocation_finished (rh, GNUNET_OK); - cleanup_revoke_ticket_handle (rh); - return; - } -} - -/** - * Failed to check for attribute - */ -static void -check_attr_error (void *cls) -{ - struct TicketRevocationHandle *rh = cls; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unable to check for existing attribute\n"); - rh->ns_qe = NULL; - send_revocation_finished (rh, GNUNET_SYSERR); - cleanup_revoke_ticket_handle (rh); -} - - -/** - * Revoke next attribte by reencryption with - * new ABE master - */ -static void -reenc_next_attribute (void *cls); - -/** - * Check for existing attribute and overwrite - */ -static void -check_attr_cb (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd_old) -{ - struct TicketRevocationHandle *rh = cls; - 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; - - rh->ns_qe = NULL; - if (1 != rd_count) { - GNUNET_SCHEDULER_add_now (&reenc_next_attribute, - 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); - if (GNUNET_SYSERR == enc_size) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unable to re-encrypt with policy %s\n", - policy); - GNUNET_free (policy); - send_revocation_finished (rh, GNUNET_SYSERR); - cleanup_revoke_ticket_handle (rh); - return; - } - 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 = rd_old[0].expiration_time; - 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); -} - - -/** - * Revoke next attribte by reencryption with - * new ABE master - */ -static void -reenc_next_attribute (void *cls) -{ - struct TicketRevocationHandle *rh = cls; - if (NULL == rh->attrs->list_head) - { - revocation_reissue_tickets (rh); - return; - } - /* First check if attribute still exists */ - rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, - &rh->identity, - rh->attrs->list_head->claim->name, - &check_attr_error, - rh, - &check_attr_cb, - rh); -} - - -/** - * Namestore callback after revoked attribute - * is stored - */ -static void -attr_reenc_cont (void *cls, - int32_t success, - const char *emsg) -{ - struct TicketRevocationHandle *rh = cls; - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; - - rh->ns_qe = NULL; - if (GNUNET_SYSERR == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to reencrypt attribute %s\n", - emsg); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - return; - } - 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); -} - - -static void -process_attributes_to_update (void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, - const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) -{ - struct TicketRevocationHandle *rh = cls; - - rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Revocation Phase I: Collecting attributes\n"); - /* Reencrypt all attributes with new key */ - if (NULL == rh->attrs->list_head) - { - /* 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); - } - -} - - - -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; -} - -static void -handle_revoke_ticket_message (void *cls, - const struct RevokeTicketMessage *rm) -{ - 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->revoke_op_head, - idp->revoke_op_tail, - rh); - bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO); - GNUNET_SERVICE_client_continue (idp->client); - -} - -/** - * Cleanup ticket consume handle - * @param handle the handle to clean up - */ -static void -cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle) -{ - struct ParallelLookup *lu; - struct ParallelLookup *tmp; - if (NULL != handle->lookup_request) - GNUNET_GNS_lookup_cancel (handle->lookup_request); - 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; - } - - 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 int -check_consume_ticket_message(void *cls, - const struct ConsumeTicketMessage *cm) -{ - uint16_t size; - - size = ntohs (cm->header.size); - if (size <= sizeof (struct ConsumeTicketMessage)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - -static void -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, - "attribute_lookup_time_total", - GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us, - GNUNET_YES); - GNUNET_STATISTICS_update (stats, - "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, - "abe_decrypt_time_total", - GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us, - GNUNET_YES); - GNUNET_STATISTICS_update (stats, - "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); - GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head, - handle->client->consume_op_tail, - handle); - cleanup_consume_ticket_handle (handle); -} - -void -abort_parallel_lookups2 (void *cls) -{ - struct ConsumeTicketHandle *handle = cls; - struct ParallelLookup *lu; - struct ParallelLookup *tmp; - struct AttributeResultMessage *arm; - struct GNUNET_MQ_Envelope *env; - - handle->kill_task = NULL; - 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; - - handle->lookup_request = NULL; - if (1 != rd_count) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Number of keys %d != 1.", - rd_count); - cleanup_consume_ticket_handle (handle); - GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head, - handle->client->consume_op_tail, - handle); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - return; - } - - //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, - "abe_key_lookup_time_total", - GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us, - GNUNET_YES); - GNUNET_STATISTICS_update (stats, - "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_DEBUG, - "Looking up %s\n", scope); - 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, - scope, - &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 (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* 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_log (GNUNET_ERROR_TYPE_DEBUG, - "Looking for ABE key under %s\n", rnd_label); - ch->lookup_start_time = GNUNET_TIME_absolute_get (); - ch->lookup_request - = GNUNET_GNS_lookup (gns_handle, - rnd_label, - &ch->ticket.identity, - GNUNET_GNSRECORD_TYPE_ABE_KEY, - GNUNET_GNS_LO_DEFAULT, - &process_consume_abe_key, - ch); - GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, - idp->consume_op_tail, - ch); - GNUNET_free (rnd_label); - GNUNET_SERVICE_client_continue (idp->client); -} - -/** - * Cleanup attribute store handle - * - * @param handle handle to clean up - */ -static void -cleanup_as_handle (struct AttributeStoreHandle *handle) -{ - if (NULL != handle->ns_qe) - GNUNET_NAMESTORE_cancel (handle->ns_qe); - 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; - - as_handle->ns_qe = NULL; - GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, - as_handle->client->store_op_tail, - as_handle); - - if (GNUNET_SYSERR == success) - { - 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; - } - - 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_as_handle (as_handle); -} - -static void -attr_store_task (void *cls) -{ - 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); - if (GNUNET_SYSERR == enc_size) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to encrypt with policy %s\n", - policy); - GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, - as_handle->client->store_op_tail, - as_handle); - - cleanup_as_handle (as_handle); - GNUNET_free (buf); - GNUNET_free (policy); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - return; - } - 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 = as_handle->exp.rel_value_us; - 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 -store_after_abe_bootstrap (void *cls, - struct GNUNET_ABE_AbeMasterKey *abe_key) -{ - 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); -} - -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 -handle_attribute_store_message (void *cls, - const struct AttributeStoreMessage *sam) -{ - 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; - as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp); - GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, - &as_handle->identity_pkey); - - GNUNET_SERVICE_client_continue (idp->client); - as_handle->client = idp; - GNUNET_CONTAINER_DLL_insert (idp->store_op_head, - idp->store_op_tail, - as_handle); - bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO); -} - -static void -cleanup_attribute_iter_handle (struct AttributeIterator *ai) -{ - if (NULL != ai->abe_key) - GNUNET_ABE_cpabe_delete_master_key (ai->abe_key); - 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"); - GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head, - ai->client->attr_iter_tail, - ai); - cleanup_attribute_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); - GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head, - ai->client->attr_iter_tail, - ai); - cleanup_attribute_iter_handle (ai); -} - -static void -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 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 (ai->ns_it, - 1); - return; - } - - if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) - { - GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, - 1); - 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); - if (GNUNET_SYSERR == msg_extra_len) - { - GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, - 1); - return; - } - - 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; -} - - -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); -} - - -static 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, - 1); -} - - - -static void -handle_iteration_start (void *cls, - const struct AttributeIterationStartMessage *ais_msg) -{ - 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->attr_iter_head, - idp->attr_iter_tail, - ai); - bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO); - GNUNET_SERVICE_client_continue (idp->client); -} - - -static void -handle_iteration_stop (void *cls, - const struct AttributeIterationStopMessage *ais_msg) -{ - struct IdpClient *idp = cls; - struct AttributeIterator *ai; - uint32_t rid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' message\n", - "ATTRIBUTE_ITERATION_STOP"); - rid = ntohl (ais_msg->id); - for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next) - if (ai->request_id == rid) - break; - if (NULL == ai) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (idp->client); - return; - } - GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, - idp->attr_iter_tail, - ai); - GNUNET_free (ai); - GNUNET_SERVICE_client_continue (idp->client); -} - - -static void -handle_iteration_next (void *cls, - const struct AttributeIterationNextMessage *ais_msg) -{ - struct IdpClient *idp = cls; - struct AttributeIterator *ai; - uint32_t rid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received ATTRIBUTE_ITERATION_NEXT message\n"); - rid = ntohl (ais_msg->id); - for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next) - if (ai->request_id == rid) - break; - if (NULL == ai) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (idp->client); - return; - } - bootstrap_abe (&ai->identity, - &iterate_next_after_abe_bootstrap, - ai, - GNUNET_NO); - GNUNET_SERVICE_client_continue (idp->client); -} - -/** - * Ticket iteration processor result - */ -enum ZoneIterationResult -{ - /** - * Iteration start. - */ - IT_START = 0, - - /** - * Found tickets, - * Continue to iterate with next iteration_next call - */ - IT_SUCCESS_MORE_AVAILABLE = 1, - - /** - * Iteration complete - */ - IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2 -}; - - -/** - * Context for ticket iteration - */ -struct TicketIterationProcResult -{ - /** - * 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 -cleanup_ticket_iter_handle (struct TicketIteration *ti) -{ - GNUNET_free (ti); -} - -/** - * Process ticket from database - * - * @param cls struct TicketIterationProcResult - * @param ticket the ticket - * @param attrs the attributes - */ -static void -ticket_iterate_proc (void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, - const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) -{ - struct TicketIterationProcResult *proc = cls; - - if (NULL == ticket) - { - 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); - -} - -/** - * 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; - - memset (&proc, 0, sizeof (proc)); - proc.ti = ti; - proc.res_iteration_finished = IT_START; - while (IT_START == proc.res_iteration_finished) - { - if (GNUNET_SYSERR == - (ret = TKT_database->iterate_tickets (TKT_database->cls, - &ti->identity, - ti->is_audience, - ti->offset, - &ticket_iterate_proc, - &proc))) - { - GNUNET_break (0); - break; - } - if (GNUNET_NO == ret) - proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; - ti->offset++; - } - if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "More results available\n"); - return; /* more later */ - } - /* 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); -} - -static void -handle_ticket_iteration_start (void *cls, - const struct TicketIterationStartMessage *tis_msg) -{ - struct IdpClient *client = cls; - struct TicketIteration *ti; - - 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_break (0); - GNUNET_SERVICE_client_drop (client->client); - return; - } - GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head, - client->ticket_iter_tail, - ti); - cleanup_ticket_iter_handle (ti); - GNUNET_SERVICE_client_continue (client->client); -} - - -static void -handle_ticket_iteration_next (void *cls, - const struct TicketIterationNextMessage *tis_msg) -{ - struct IdpClient *client = cls; - struct TicketIteration *ti; - uint32_t rid; - - 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_break (0); - GNUNET_SERVICE_client_drop (client->client); - return; - } - run_ticket_iteration_round (ti); - GNUNET_SERVICE_client_continue (client->client); -} - - - - -/** - * Main function that will be run - * - * @param cls closure - * @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); - - //Connect to identity and namestore services - ns_handle = GNUNET_NAMESTORE_connect (cfg); - if (NULL == ns_handle) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore"); - } - - gns_handle = GNUNET_GNS_connect (cfg); - if (NULL == gns_handle) - { - 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, - NULL, - NULL); - /* 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, - "identity-provider", - "TOKEN_EXPIRATION_INTERVAL", - &token_expiration_interval)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Time window for zone iteration: %s\n", - GNUNET_STRINGS_relative_time_to_string (token_expiration_interval, - GNUNET_YES)); - } else { - token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL; - } - - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); -} - -/** - * Called whenever a client is disconnected. - * - * @param cls closure - * @param client identification of the client - * @param app_ctx @a client - */ -static void -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; - struct TicketIssueHandle *iss; - struct ConsumeTicketHandle *ct; - struct AttributeStoreHandle *as; - - //TODO other operations - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Client %p disconnected\n", - client); - - while (NULL != (iss = idp->issue_op_head)) - { - GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, - idp->issue_op_tail, - iss); - cleanup_ticket_issue_handle (iss); - } - while (NULL != (ct = idp->consume_op_head)) - { - GNUNET_CONTAINER_DLL_remove (idp->consume_op_head, - idp->consume_op_tail, - ct); - cleanup_consume_ticket_handle (ct); - } - while (NULL != (as = idp->store_op_head)) - { - GNUNET_CONTAINER_DLL_remove (idp->store_op_head, - idp->store_op_tail, - as); - cleanup_as_handle (as); - } - - while (NULL != (ai = idp->attr_iter_head)) - { - GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, - idp->attr_iter_tail, - ai); - cleanup_attribute_iter_handle (ai); - } - while (NULL != (rh = idp->revoke_op_head)) - { - GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, - idp->revoke_op_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); -} - - -/** - * Add a client to our list of active clients. - * - * @param cls NULL - * @param client client to add - * @param mq message queue for @a client - * @return internal namestore client structure for this client - */ -static void * -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); - idp = GNUNET_new (struct IdpClient); - idp->client = client; - idp->mq = mq; - return idp; -} - - - -/** - * Define "main" method using service macro. - */ -GNUNET_SERVICE_MAIN -("identity-provider", - GNUNET_SERVICE_OPTION_NONE, - &run, - &client_connect_cb, - &client_disconnect_cb, - NULL, - 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_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 deleted file mode 100644 index 99c0a50be..000000000 --- a/src/identity-provider/identity-provider.conf +++ /dev/null @@ -1,23 +0,0 @@ -[identity-provider] -START_ON_DEMAND = NO -RUN_PER_USER = YES -#PORT = 2108 -HOSTNAME = localhost -BINARY = gnunet-service-identity-provider -ACCEPT_FROM = 127.0.0.1; -ACCEPT_FROM6 = ::1; -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-rest-plugin] -#ADDRESS = https://identity.gnu:8000#/login -ADDRESS = https://reclaim.ui/#/login -PSW = secret -JWT_SECRET = secret -EXPIRATION_TIME = 3600 - -[identity-provider-sqlite] -FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db diff --git a/src/identity-provider/identity-token.conf b/src/identity-provider/identity-token.conf deleted file mode 100644 index f29f6cdf3..000000000 --- a/src/identity-provider/identity-token.conf +++ /dev/null @@ -1,2 +0,0 @@ -[identity-token] -BINARY=gnunet-service-identity-token diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h deleted file mode 100644 index 6a4b7769f..000000000 --- a/src/identity-provider/identity_provider.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2016 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @author Martin Schanzenbach - * @file identity-provider/identity_provider.h - * - * @brief Common type definitions for the identity provider - * service and API. - */ -#ifndef IDENTITY_PROVIDER_H -#define IDENTITY_PROVIDER_H - -#include "gnunet_common.h" - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Use to store an identity attribute - */ -struct AttributeStoreMessage -{ - /** - * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - - /** - * The length of the attribute - */ - uint32_t attr_len GNUNET_PACKED; - - /** - * The expiration interval of the attribute - */ - uint64_t exp GNUNET_PACKED; - - /** - * Identity - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - /* followed by the serialized attribute */ - -}; - -/** - * Attribute store response message - */ -struct AttributeStoreResultMessage -{ - /** - * 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). - */ - uint32_t id GNUNET_PACKED; - -}; - -/** - * Start a ticket iteration for the given identity - */ -struct TicketIterationStartMessage -{ - /** - * Message - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - - /** - * Identity. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey identity; - - /** - * Identity is audience or issuer - */ - uint32_t is_audience GNUNET_PACKED; -}; - - -/** - * Ask for next result of ticket iteration for the given operation - */ -struct TicketIterationNextMessage -{ - /** - * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - -}; - - -/** - * Stop ticket iteration for the given operation - */ -struct TicketIterationStopMessage -{ - /** - * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - -}; - - - -/** - * Ticket issue message - */ -struct IssueTicketMessage -{ - /** - * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - - /** - * Identity. - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - /** - * Requesting party. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey rp; - - /** - * length of serialized attribute list - */ - uint32_t attr_len GNUNET_PACKED; - - //Followed by a serialized attribute list -}; - -/** - * Ticket revoke message - */ -struct RevokeTicketMessage -{ - /** - * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET - */ - struct GNUNET_MessageHeader header; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - - /** - * Identity. - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey identity; - - /** - * 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; -}; - - -/** - * Ticket result message - */ -struct TicketResultMessage -{ - /** - * 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; - - /** - * Unique identifier for this request (for key collisions). - */ - uint32_t id GNUNET_PACKED; - - /** - * 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 - */ - uint16_t attrs_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 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 deleted file mode 100644 index 33efe726f..000000000 --- a/src/identity-provider/identity_provider_api.c +++ /dev/null @@ -1,1383 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2016 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @file identity-provider/identity_provider_api.c - * @brief api to interact with the identity provider service - * @author Martin Schanzenbach - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_constants.h" -#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. - */ -struct GNUNET_IDENTITY_PROVIDER_Operation -{ - - /** - * Main handle. - */ - struct GNUNET_IDENTITY_PROVIDER_Handle *h; - - /** - * We keep operations in a DLL. - */ - struct GNUNET_IDENTITY_PROVIDER_Operation *next; - - /** - * We keep operations in a DLL. - */ - struct GNUNET_IDENTITY_PROVIDER_Operation *prev; - - /** - * Message to send to the service. - * Allocated at the end of this struct. - */ - const struct GNUNET_MessageHeader *msg; - - /** - * 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_ContinuationWithStatus rvk_cb; - - /** - * Ticket result callback - */ - GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb; - - /** - * Envelope with the message for this queue entry. - */ - struct GNUNET_MQ_Envelope *env; - - /** - * request id - */ - uint32_t r_id; - - /** - * Closure for @e cont or @e cb. - */ - void *cls; - -}; - -/** - * 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. - */ -struct GNUNET_IDENTITY_PROVIDER_Handle -{ - /** - * Configuration to use. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Socket (if available). - */ - struct GNUNET_CLIENT_Connection *client; - - /** - * Closure for 'cb'. - */ - void *cb_cls; - - /** - * Head of active operations. - */ - struct GNUNET_IDENTITY_PROVIDER_Operation *op_head; - - /** - * Tail of active operations. - */ - 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; - - /** - * Task doing exponential back-off trying to reconnect. - */ - struct GNUNET_SCHEDULER_Task * reconnect_task; - - /** - * Time for next connect retry. - */ - struct GNUNET_TIME_Relative reconnect_backoff; - - /** - * Connection to service (if available). - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Request Id generator. Incremented by one for each request. - */ - uint32_t r_id_gen; - - /** - * Are we polling for incoming messages right now? - */ - int in_receive; - -}; - -/** - * Try again to connect to the service. - * - * @param h handle to the identity provider service. - */ -static void -reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); - -/** - * Reconnect - * - * @param cls the handle - */ -static void -reconnect_task (void *cls) -{ - struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; - - handle->reconnect_task = NULL; - reconnect (handle); -} - - -/** - * Disconnect from service and then reconnect. - * - * @param handle our service - */ -static void -force_reconnect (struct GNUNET_IDENTITY_PROVIDER_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); -} - -/** - * 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); -} - -static void -free_op (struct GNUNET_IDENTITY_PROVIDER_Operation* op) -{ - if (NULL == op) - return; - if (NULL != op->env) - GNUNET_MQ_discard (op->env); - GNUNET_free(op); -} - - -/** - * 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_GNS_Handle *` - * @param error error code - */ -static void -mq_error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; - force_reconnect (handle); -} - -/** - * 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); - free_op (op); - -} - - -/** - * Handle an incoming message of type - * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT - * - * @param cls - * @param msg the message we received - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -check_consume_ticket_result (void *cls, - const struct ConsumeTicketResultMessage *msg) -{ - size_t msg_len; - size_t attrs_len; - - 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; - } - return GNUNET_OK; -} - - -/** - * 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); - } - } - if (NULL != op) - { - op->ar_cb (op->cls, - NULL, - NULL); - GNUNET_CONTAINER_DLL_remove (h->op_head, - h->op_tail, - op); - free_op (op); - } - return; - } - GNUNET_assert (0); -} - - -/** - * Handle an incoming message of type - * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT - * - * @param cls - * @param msg the message we received - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -check_attribute_result (void *cls, - const struct AttributeResultMessage *msg) -{ - 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; - } - return GNUNET_OK; -} - - -/** - * Handle an incoming message of type - * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT - * - * @param cls - * @param msg the message we received - */ -static void -handle_attribute_result (void *cls, - const struct AttributeResultMessage *msg) -{ - 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; - 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 == it) && (NULL == op)) - return; - - 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); - free_op (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; -} - - - -/** - * Handle an incoming message of type - * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT - * - * @param cls - * @param msg the message we received - */ -static void -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_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; - for (it = handle->ticket_it_head; NULL != it; it = it->next) - if (it->r_id == r_id) - break; - if ((NULL == op) && (NULL == it)) - return; - msg_len = ntohs (msg->header.size); - if (NULL != op) - { - 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); - } - free_op (op); - return; - } 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; - } - 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); - { - if (NULL != op->rvk_cb) - { - op->rvk_cb (op->cls, - success, - NULL); - } - GNUNET_CONTAINER_DLL_remove (h->op_head, - h->op_tail, - op); - free_op (op); - return; - } - GNUNET_assert (0); -} - - - -/** - * Try again to connect to the 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_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 (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; - - GNUNET_assert (NULL == h->mq); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Connecting to identity provider service.\n"); - - h->mq = GNUNET_CLIENT_connect (h->cfg, - "identity-provider", - handlers, - &mq_error_handler, - h); - if (NULL == h->mq) - return; - for (op = h->op_head; NULL != op; op = op->next) - GNUNET_MQ_send_copy (h->mq, - op->env); -} - - -/** - * Connect to the identity provider service. - * - * @param cfg the configuration to use - * @return handle to use - */ -struct GNUNET_IDENTITY_PROVIDER_Handle * -GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_IDENTITY_PROVIDER_Handle *h; - - h = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Handle); - h->cfg = cfg; - reconnect (h); - if (NULL == h->mq) - { - GNUNET_free (h); - return NULL; - } - return h; -} - - -/** - * 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 - * the operation. - * - * @param op operation to cancel - */ -void -GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op) -{ - struct GNUNET_IDENTITY_PROVIDER_Handle *h = op->h; - - GNUNET_CONTAINER_DLL_remove (h->op_head, - h->op_tail, - op); - free_op (op); -} - - -/** - * Disconnect from service - * - * @param h handle to destroy - */ -void -GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) -{ - GNUNET_assert (NULL != h); - if (NULL != h->mq) - { - GNUNET_MQ_destroy (h->mq); - h->mq = NULL; - } - if (NULL != h->reconnect_task) - { - GNUNET_SCHEDULER_cancel (h->reconnect_task); - h->reconnect_task = NULL; - } - GNUNET_assert (NULL == h->op_head); - GNUNET_free (h); -} - -/** - * 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 exp_interval the relative expiration interval for the attribute - * @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, - const struct GNUNET_TIME_Relative *exp_interval, - 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); - sam->exp = GNUNET_htonll (exp_interval->rel_value_us); - - 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; -} - - -/** - * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start - * for the next record. - * - * @param it the iterator - */ -void -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) -{ - 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; - -} - - -/** - * Lists all tickets that have been issued to remote - * identites (relying parties) - * - * @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 - */ -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) -{ - 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; - -} - - -/** - * Lists all tickets that have been issued to remote - * identites (relying parties) - * - * @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 - */ -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) -{ - 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; - - -} - -/** - * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start - * for the next record. - * - * @param it the iterator - */ -void -GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) -{ - 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); -} - - -/** - * 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_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) -{ - 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 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); - 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; - GNUNET_memcpy (&msg[1], - ticket, - sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); - if (NULL != h->mq) { - GNUNET_MQ_send (h->mq, - op->env); - op->env = NULL; - } - return op; -} - - - -/* end of identity_provider_api.c */ diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c deleted file mode 100644 index 7ac4f0025..000000000 --- a/src/identity-provider/jwt.c +++ /dev/null @@ -1,160 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ - -/** - * @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 - - -#define JWT_ALG "alg" - -/* Use 512bit HMAC */ -#define JWT_ALG_VALUE "HS512" - -#define JWT_TYP "typ" - -#define JWT_TYP_VALUE "jwt" - -#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo" - -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 aud_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 *aud_key, - const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, - const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_CRYPTO_AuthKey *priv_key) -{ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; - struct GNUNET_HashCode signature; - char* audience; - char* subject; - 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; - - //exp REQUIRED time expired from config - //iat REQUIRED time now - //auth_time only if max_age - //nonce only if nonce - // OPTIONAL acr,amr,azp - subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - header = create_jwt_header (); - body = json_object (); - - //iss REQUIRED case sensitive server uri with https - //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) - json_object_set_new (body, - "iss", json_string (SERVER_ADDRESS)); - //sub REQUIRED public key identity, not exceed 255 ASCII length - json_object_set_new (body, - "sub", json_string (subject)); - //aud REQUIRED public key client_id must be there - json_object_set_new (body, - "aud", json_string (audience)); - for (le = attrs->list_head; NULL != le; le = le->next) - { - 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 (subject); - GNUNET_free (audience); - - /** - * Creating the JWT signature. This might not be - * standards compliant, check. - */ - GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); - GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature); - GNUNET_STRINGS_base64_encode ((const char*)&signature, - sizeof (struct GNUNET_HashCode), - &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); - return result; -} diff --git a/src/identity-provider/jwt.h b/src/identity-provider/jwt.h deleted file mode 100644 index 80b6caa33..000000000 --- a/src/identity-provider/jwt.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef JWT_H -#define JWT_H - -char* -jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, - const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, - const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_CRYPTO_AuthKey *priv_key); - -#endif diff --git a/src/identity-provider/plugin_gnsrecord_identity_provider.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c deleted file mode 100644 index f0dc563dc..000000000 --- a/src/identity-provider/plugin_gnsrecord_identity_provider.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2013, 2014 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @file identity-provider/plugin_gnsrecord_identity_provider.c - * @brief gnsrecord plugin to provide the API for identity records - * @author Martin Schanzenbach - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_gnsrecord_lib.h" -#include "gnunet_gnsrecord_plugin.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 * -value_to_string (void *cls, - uint32_t type, - const void *data, - size_t data_size) -{ - const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; - const struct GNUNET_CRYPTO_EcdsaPublicKey *audience_pubkey; - const char *scopes; - char *ecdhe_str; - char *aud_str; - char *result; - - switch (type) - { - case GNUNET_GNSRECORD_TYPE_ID_ATTR: - 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_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)); - ecdhe_str = GNUNET_STRINGS_data_to_string_alloc (ecdhe_privkey, - sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); - aud_str = GNUNET_STRINGS_data_to_string_alloc (audience_pubkey, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - GNUNET_asprintf (&result, - "%s;%s;%s", - ecdhe_str, aud_str, scopes); - GNUNET_free (aud_str); - GNUNET_free (ecdhe_str); - return result; - - 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 -string_to_value (void *cls, - uint32_t type, - const char *s, - void **data, - size_t *data_size) -{ - char* ecdhe_str; - char* aud_keystr; - char* write_ptr; - char* tmp_tok; - char* str; - - if (NULL == s) - return GNUNET_SYSERR; - 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); - ecdhe_str = strtok (tmp_tok, ";"); - if (NULL == ecdhe_str) - { - GNUNET_free (tmp_tok); - return GNUNET_SYSERR; - } - aud_keystr = strtok (NULL, ";"); - if (NULL == aud_keystr) - { - GNUNET_free (tmp_tok); - return GNUNET_SYSERR; - } - str = strtok (NULL, ";"); - if (NULL == str) - { - GNUNET_free (tmp_tok); - return GNUNET_SYSERR; - } - *data_size = strlen (str) + 1 - +sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) - +sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); - *data = GNUNET_malloc (*data_size); - - write_ptr = *data; - GNUNET_STRINGS_string_to_data (ecdhe_str, - strlen (ecdhe_str), - write_ptr, - sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); - write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); - GNUNET_STRINGS_string_to_data (aud_keystr, - strlen (aud_keystr), - write_ptr, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); - GNUNET_memcpy (write_ptr, str, strlen (str) + 1); //with 0-Terminator - GNUNET_free (tmp_tok); - 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[] = { - { "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 } -}; - - -/** - * Convert a type name (i.e. "AAAA") to the corresponding number. - * - * @param cls closure, unused - * @param dns_typename name to convert - * @return corresponding number, UINT32_MAX on error - */ -static uint32_t -typename_to_number (void *cls, - const char *dns_typename) -{ - unsigned int i; - - i=0; - while ( (NULL != name_map[i].name) && - (0 != strcasecmp (dns_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 * -number_to_typename (void *cls, - uint32_t type) -{ - unsigned int i; - - i=0; - while ( (NULL != name_map[i].name) && - (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_identity_provider_init (void *cls) -{ - struct GNUNET_GNSRECORD_PluginFunctions *api; - - api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); - api->value_to_string = &value_to_string; - api->string_to_value = &string_to_value; - api->typename_to_number = &typename_to_number; - api->number_to_typename = &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_identity_provider_done (void *cls) -{ - struct GNUNET_GNSRECORD_PluginFunctions *api = cls; - - GNUNET_free (api); - return NULL; -} - -/* end of plugin_gnsrecord_dns.c */ diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c deleted file mode 100644 index f2a8b7b54..000000000 --- a/src/identity-provider/plugin_identity_provider_sqlite.c +++ /dev/null @@ -1,734 +0,0 @@ - /* - * 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 Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, - * 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 - * Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @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 - -/** - * 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 deleted file mode 100644 index f8176a101..000000000 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ /dev/null @@ -1,1253 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @author Martin Schanzenbach - * @author Philippe Buschmann - * @file identity/plugin_rest_identity.c - * @brief GNUnet Namestore REST plugin - * - */ - -#include "platform.h" -#include "gnunet_rest_plugin.h" -#include "gnunet_identity_service.h" -#include "gnunet_gns_service.h" -#include "gnunet_gnsrecord_lib.h" -#include "gnunet_namestore_service.h" -#include "gnunet_rest_lib.h" -#include "gnunet_jsonapi_lib.h" -#include "gnunet_jsonapi_util.h" -#include "microhttpd.h" -#include -#include -#include "gnunet_signatures.h" -#include "gnunet_identity_attribute_lib.h" -#include "gnunet_identity_provider_service.h" - -/** - * REST root namespace - */ -#define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" - -/** - * Attribute namespace - */ -#define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes" - -/** - * Ticket namespace - */ -#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets" - -/** - * Revoke namespace - */ -#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke" - -/** - * Revoke namespace - */ -#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" - -/** - * Attribute key - */ -#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" - -/** - * Ticket key - */ -#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" - - -/** - * Value key - */ -#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value" - -/** - * State while collecting all egos - */ -#define ID_REST_STATE_INIT 0 - -/** - * Done collecting egos - */ -#define ID_REST_STATE_POST_INIT 1 - -/** - * The configuration handle - */ -const struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * HTTP methods allows for this plugin - */ -static char* allow_methods; - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct Plugin -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; -}; - -/** - * The ego list - */ -struct EgoEntry -{ - /** - * DLL - */ - struct EgoEntry *next; - - /** - * DLL - */ - struct EgoEntry *prev; - - /** - * Ego Identifier - */ - char *identifier; - - /** - * Public key string - */ - char *keystring; - - /** - * The Ego - */ - struct GNUNET_IDENTITY_Ego *ego; -}; - - -struct RequestHandle -{ - /** - * Ego list - */ - struct EgoEntry *ego_head; - - /** - * Ego list - */ - struct EgoEntry *ego_tail; - - /** - * Selected ego - */ - struct EgoEntry *ego_entry; - - /** - * Pointer to ego private key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; - - /** - * The processing state - */ - int state; - - /** - * Handle to Identity service. - */ - struct GNUNET_IDENTITY_Handle *identity_handle; - - /** - * Rest connection - */ - struct GNUNET_REST_RequestHandle *rest_handle; - - /** - * Handle to NAMESTORE - */ - struct GNUNET_NAMESTORE_Handle *namestore_handle; - - /** - * Iterator for NAMESTORE - */ - struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; - - /** - * Attribute claim list - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; - - /** - * IDENTITY Operation - */ - struct GNUNET_IDENTITY_Operation *op; - - /** - * Identity Provider - */ - struct GNUNET_IDENTITY_PROVIDER_Handle *idp; - - /** - * Idp Operation - */ - struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; - - /** - * Attribute iterator - */ - struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it; - - /** - * Ticket iterator - */ - struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it; - - /** - * A ticket - */ - struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; - - /** - * Desired timeout for the lookup (default is no timeout). - */ - struct GNUNET_TIME_Relative timeout; - - /** - * ID of a task associated with the resolution process. - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * The plugin result processor - */ - GNUNET_REST_ResultProcessor proc; - - /** - * The closure of the result processor - */ - void *proc_cls; - - /** - * The url - */ - char *url; - - /** - * Error response message - */ - char *emsg; - - /** - * Reponse code - */ - int response_code; - - /** - * Response object - */ - struct GNUNET_JSONAPI_Document *resp_object; - -}; - -/** - * Cleanup lookup handle - * @param handle Handle to clean up - */ -static void -cleanup_handle (struct RequestHandle *handle) -{ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry; - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp; - struct EgoEntry *ego_entry; - struct EgoEntry *ego_tmp; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->resp_object) - GNUNET_JSONAPI_document_delete (handle->resp_object); - if (NULL != handle->timeout_task) - 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->url) - GNUNET_free (handle->url); - if (NULL != handle->emsg) - GNUNET_free (handle->emsg); - if (NULL != handle->namestore_handle) - GNUNET_NAMESTORE_disconnect (handle->namestore_handle); - if ( NULL != handle->attr_list ) - { - for (claim_entry = handle->attr_list->list_head; - NULL != claim_entry;) - { - claim_tmp = claim_entry; - claim_entry = claim_entry->next; - GNUNET_free(claim_tmp->claim); - GNUNET_free(claim_tmp); - } - GNUNET_free (handle->attr_list); - } - for (ego_entry = handle->ego_head; - NULL != ego_entry;) - { - ego_tmp = ego_entry; - ego_entry = ego_entry->next; - GNUNET_free (ego_tmp->identifier); - GNUNET_free (ego_tmp->keystring); - GNUNET_free (ego_tmp); - } - if (NULL != handle->attr_it) - { - GNUNET_free(handle->attr_it); - } - GNUNET_free (handle); -} - -static void -cleanup_handle_delayed (void *cls) -{ - cleanup_handle (cls); -} - - -/** - * Task run on error, sends error message. Cleans up everything. - * - * @param cls the `struct RequestHandle` - */ -static void -do_error (void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - char *json_error; - - GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", - handle->emsg); - if ( 0 == handle->response_code ) - { - handle->response_code = MHD_HTTP_BAD_REQUEST; - } - resp = GNUNET_REST_create_response (json_error); - MHD_add_response_header (resp, "Content-Type", "application/json"); - handle->proc (handle->proc_cls, resp, handle->response_code); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - GNUNET_free (json_error); -} - - -/** - * Task run on timeout, sends error message. Cleans up everything. - * - * @param cls the `struct RequestHandle` - */ -static void -do_timeout (void *cls) -{ - struct RequestHandle *handle = cls; - - handle->timeout_task = NULL; - do_error (handle); -} - - -static void -collect_error_cb (void *cls) -{ - struct RequestHandle *handle = cls; - - do_error (handle); -} - -static void -finished_cont (void *cls, - int32_t success, - const char *emsg) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - - resp = GNUNET_REST_create_response (emsg); - if (GNUNET_OK != success) - { - 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); -} - - -/** - * 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); - 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); -} - - -/** - * Collect all attributes for an ego - * - */ -static void -ticket_collect (void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) -{ - 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; - 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); - 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) - { - //Done - 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 (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); -} - - -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; - const char* exp_str; - - 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; - struct GNUNET_TIME_Relative exp; - char term_data[handle->rest_handle->data_size+1]; - json_t *value_json; - json_t *data_json; - json_t *exp_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)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - 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, - "Identity unknown (%s)\n", identity); - GNUNET_JSONAPI_document_delete (json_obj); - return; - } - identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); - - if (0 >= handle->rest_handle->data_size) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - 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, - "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_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); - exp_json = GNUNET_JSONAPI_resource_read_attr (json_res, - "exp"); - exp_str = json_string_value (exp_json); - if (NULL == exp_str) { - exp = GNUNET_TIME_UNIT_HOURS; - } else { - if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str, - &exp)) { - exp = GNUNET_TIME_UNIT_HOURS; - } - } - - 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_attribute_store (handle->idp, - identity_priv, - attribute, - &exp, - &finished_cont, - handle); - GNUNET_free (attribute); - GNUNET_JSONAPI_document_delete (json_obj); -} - - - -/** - * Collect all attributes for an ego - * - */ -static void -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; - json_t *value; - char* tmp_value; - - if ((NULL == attr->name) || (NULL == attr->data)) - { - GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); - 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); - - tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type, - attr->data, - attr->data_size); - - value = json_string (tmp_value); - - GNUNET_JSONAPI_resource_add_attr (json_resource, - "value", - value); - json_decref (value); - GNUNET_free(tmp_value); - GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); -} - - - -/** - * List attributes for identity request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -list_attribute_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; - char *identity; - - 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_ERROR, "No identity given.\n"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - 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; - handle->resp_object = GNUNET_JSONAPI_document_new (); - - - if (NULL == ego_entry) - { - //Done - 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 (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); -} - - -static void -revoke_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) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - 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, - "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, - "issuer"); - 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.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); - - 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); -} - -static void -consume_cont (void *cls, - const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) -{ - struct RequestHandle *handle = cls; - struct GNUNET_JSONAPI_Resource *json_resource; - json_t *value; - - 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); -} - -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) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - 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, - "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)); - - 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_ticket_consume (handle->idp, - identity_priv, - &ticket, - &consume_cont, - handle); - GNUNET_JSONAPI_document_delete (json_obj); -} - - - -/** - * Respond to OPTIONS request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp; - struct RequestHandle *handle = cls; - - //For now, independent of path return all options - resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - allow_methods); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); - return; -} - -/** - * Handle rest request - * - * @param handle the request handle - */ -static void -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_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->rest_handle, - handlers, - &err, - handle)) - { - handle->response_code = err.error_code; - GNUNET_SCHEDULER_add_now (&do_error, handle); - } -} - -/** - * If listing is enabled, prints information about the egos. - * - * This function is initially called for all egos and then again - * whenever a ego's identifier changes or if it is deleted. At the - * end of the initial pass over all egos, the function is once called - * with 'NULL' for 'ego'. That does NOT mean that the callback won't - * be invoked in the future or that there was an error. - * - * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', - * this function is only called ONCE, and 'NULL' being passed in - * 'ego' does indicate an error (i.e. name is taken or no default - * value is known). If 'ego' is non-NULL and if '*ctx' - * is set in those callbacks, the value WILL be passed to a subsequent - * call to the identity callback of 'GNUNET_IDENTITY_connect' (if - * that one was not NULL). - * - * When an identity is renamed, this function is called with the - * (known) ego but the NEW identifier. - * - * When an identity is deleted, this function is called with the - * (known) ego and "NULL" for the 'identifier'. In this case, - * the 'ego' is henceforth invalid (and the 'ctx' should also be - * cleaned up). - * - * @param cls closure - * @param ego ego handle - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param identifier identifier assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used - */ -static void -list_ego (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *identifier) -{ - struct RequestHandle *handle = cls; - struct EgoEntry *ego_entry; - struct GNUNET_CRYPTO_EcdsaPublicKey pk; - - if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) - { - handle->state = ID_REST_STATE_POST_INIT; - init_cont (handle); - return; - } - if (ID_REST_STATE_INIT == handle->state) { - ego_entry = GNUNET_new (struct EgoEntry); - GNUNET_IDENTITY_ego_get_public_key (ego, &pk); - ego_entry->keystring = - GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); - ego_entry->ego = ego; - ego_entry->identifier = GNUNET_strdup (identifier); - GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); - } - -} - -static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) -{ - struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - handle->response_code = 0; - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - handle->state = ID_REST_STATE_INIT; - handle->rest_handle = rest_handle; - - 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, - "Connecting...\n"); - handle->identity_handle = GNUNET_IDENTITY_connect (cfg, - &list_ego, - handle); - handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); - handle->timeout_task = - GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_timeout, - handle); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected\n"); -} - -/** - * Entry point for the plugin. - * - * @param cls Config info - * @return NULL on error, otherwise the plugin context - */ -void * -libgnunet_plugin_rest_identity_provider_init (void *cls) -{ - static struct Plugin plugin; - struct GNUNET_REST_Plugin *api; - - cfg = cls; - 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_IDENTITY_PROVIDER; - api->process_request = &rest_identity_process_request; - GNUNET_asprintf (&allow_methods, - "%s, %s, %s, %s, %s", - MHD_HTTP_METHOD_GET, - MHD_HTTP_METHOD_POST, - MHD_HTTP_METHOD_PUT, - MHD_HTTP_METHOD_DELETE, - MHD_HTTP_METHOD_OPTIONS); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Identity Provider 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_identity_provider_done (void *cls) -{ - struct GNUNET_REST_Plugin *api = cls; - struct Plugin *plugin = api->cls; - plugin->cfg = NULL; - - GNUNET_free_non_null (allow_methods); - GNUNET_free (api); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Identity Provider REST plugin is finished\n"); - return NULL; -} - -/* end of plugin_rest_identity_provider.c */ diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c deleted file mode 100644 index cc4b83dae..000000000 --- a/src/identity-provider/plugin_rest_openid_connect.c +++ /dev/null @@ -1,2227 +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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @author Martin Schanzenbach - * @author Philippe Buschmann - * @file identity/plugin_rest_openid_connect.c - * @brief GNUnet Namestore REST plugin - * - */ - -#include "platform.h" -#include "gnunet_rest_plugin.h" -#include "gnunet_identity_service.h" -#include "gnunet_gns_service.h" -#include "gnunet_gnsrecord_lib.h" -#include "gnunet_namestore_service.h" -#include "gnunet_rest_lib.h" -#include "gnunet_jsonapi_lib.h" -#include "gnunet_jsonapi_util.h" -#include "microhttpd.h" -#include -#include -#include "gnunet_signatures.h" -#include "gnunet_identity_attribute_lib.h" -#include "gnunet_identity_provider_service.h" -#include "jwt.h" - -/** - * REST root namespace - */ -#define GNUNET_REST_API_NS_OIDC "/openid" - -/** - * Authorize endpoint - */ -#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize" - -/** - * Token endpoint - */ -#define GNUNET_REST_API_NS_TOKEN "/openid/token" - -/** - * UserInfo endpoint - */ -#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo" - -/** - * Login namespace - */ -#define GNUNET_REST_API_NS_LOGIN "/openid/login" - -/** - * Attribute key - */ -#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" - -/** - * Ticket key - */ -#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" - - -/** - * Value key - */ -#define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value" - -/** - * State while collecting all egos - */ -#define ID_REST_STATE_INIT 0 - -/** - * Done collecting egos - */ -#define ID_REST_STATE_POST_INIT 1 - -/** - * OIDC grant_type key - */ -#define OIDC_GRANT_TYPE_KEY "grant_type" - -/** - * OIDC grant_type key - */ -#define OIDC_GRANT_TYPE_VALUE "authorization_code" - -/** - * OIDC code key - */ -#define OIDC_CODE_KEY "code" - -/** - * OIDC response_type key - */ -#define OIDC_RESPONSE_TYPE_KEY "response_type" - -/** - * OIDC client_id key - */ -#define OIDC_CLIENT_ID_KEY "client_id" - -/** - * OIDC scope key - */ -#define OIDC_SCOPE_KEY "scope" - -/** - * OIDC redirect_uri key - */ -#define OIDC_REDIRECT_URI_KEY "redirect_uri" - -/** - * OIDC state key - */ -#define OIDC_STATE_KEY "state" - -/** - * OIDC nonce key - */ -#define OIDC_NONCE_KEY "nonce" - -/** - * OIDC cookie header key - */ -#define OIDC_COOKIE_HEADER_KEY "cookie" - -/** - * OIDC cookie header information key - */ -#define OIDC_AUTHORIZATION_HEADER_KEY "authorization" - -/** - * OIDC cookie header information key - */ -#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity=" - -/** - * OIDC expected response_type while authorizing - */ -#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code" - -/** - * OIDC expected scope part while authorizing - */ -#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid" - -/** - * OIDC ignored parameter array - */ -static char* OIDC_ignored_parameter_array [] = -{ - "display", - "prompt", - "max_age", - "ui_locales", - "response_mode", - "id_token_hint", - "login_hint", - "acr_values" -}; - -/** - * OIDC authorized identities and times hashmap - */ -struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time; - -/** - * OIDC authorized identities and times hashmap - */ -struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants; - -/** - * OIDC ticket/code use only once - */ -struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once; - -/** - * OIDC access_token to ticket and ego - */ -struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token; - -/** - * The configuration handle - */ -const struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * HTTP methods allows for this plugin - */ -static char* allow_methods; - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct Plugin -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; -}; - -/** - * OIDC needed variables - */ -struct OIDC_Variables -{ - /** - * The RP client public key - */ - struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey; - - /** - * The OIDC client id of the RP - */ - char *client_id; - - /** - * GNUNET_YES if there is a delegation to - * this RP or if it is a local identity - */ - int is_client_trusted; - - /** - * The OIDC redirect uri - */ - char *redirect_uri; - - /** - * The list of oidc scopes - */ - char *scope; - - /** - * The OIDC state - */ - char *state; - - /** - * The OIDC nonce - */ - char *nonce; - - /** - * The OIDC response type - */ - char *response_type; - - /** - * The identity chosen by the user to login - */ - char *login_identity; - - /** - * The response JSON - */ - json_t *response; - -}; - -/** - * The ego list - */ -struct EgoEntry -{ - /** - * DLL - */ - struct EgoEntry *next; - - /** - * DLL - */ - struct EgoEntry *prev; - - /** - * Ego Identifier - */ - char *identifier; - - /** - * Public key string - */ - char *keystring; - - /** - * The Ego - */ - struct GNUNET_IDENTITY_Ego *ego; -}; - - -struct RequestHandle -{ - /** - * Ego list - */ - struct EgoEntry *ego_head; - - /** - * Ego list - */ - struct EgoEntry *ego_tail; - - /** - * Selected ego - */ - struct EgoEntry *ego_entry; - - /** - * Pointer to ego private key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; - - /** - * OIDC variables - */ - struct OIDC_Variables *oidc; - - /** - * The processing state - */ - int state; - - /** - * Handle to Identity service. - */ - struct GNUNET_IDENTITY_Handle *identity_handle; - - /** - * Rest connection - */ - struct GNUNET_REST_RequestHandle *rest_handle; - - /** - * Handle to NAMESTORE - */ - struct GNUNET_NAMESTORE_Handle *namestore_handle; - - /** - * Iterator for NAMESTORE - */ - struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; - - /** - * Attribute claim list - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; - - /** - * IDENTITY Operation - */ - struct GNUNET_IDENTITY_Operation *op; - - /** - * Identity Provider - */ - struct GNUNET_IDENTITY_PROVIDER_Handle *idp; - - /** - * Idp Operation - */ - struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; - - /** - * Attribute iterator - */ - struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it; - - /** - * Ticket iterator - */ - struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it; - - /** - * A ticket - */ - struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; - - /** - * Desired timeout for the lookup (default is no timeout). - */ - struct GNUNET_TIME_Relative timeout; - - /** - * ID of a task associated with the resolution process. - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * The plugin result processor - */ - GNUNET_REST_ResultProcessor proc; - - /** - * The closure of the result processor - */ - void *proc_cls; - - /** - * The url - */ - char *url; - - /** - * The tld for redirect - */ - char *tld; - - /** - * Error response message - */ - char *emsg; - - /** - * Error response description - */ - char *edesc; - - /** - * Reponse code - */ - int response_code; - - /** - * Response object - */ - struct GNUNET_JSONAPI_Document *resp_object; - -}; - -/** - * Cleanup lookup handle - * @param handle Handle to clean up - */ -static void -cleanup_handle (struct RequestHandle *handle) -{ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry; - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp; - struct EgoEntry *ego_entry; - struct EgoEntry *ego_tmp; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->resp_object) - GNUNET_JSONAPI_document_delete (handle->resp_object); - if (NULL != handle->timeout_task) - 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->url) - GNUNET_free (handle->url); - if (NULL != handle->tld) - GNUNET_free (handle->tld); - if (NULL != handle->emsg) - GNUNET_free (handle->emsg); - if (NULL != handle->edesc) - GNUNET_free (handle->edesc); - if (NULL != handle->namestore_handle) - GNUNET_NAMESTORE_disconnect (handle->namestore_handle); - if (NULL != handle->oidc) - { - if (NULL != handle->oidc->client_id) - GNUNET_free(handle->oidc->client_id); - if (NULL != handle->oidc->login_identity) - GNUNET_free(handle->oidc->login_identity); - if (NULL != handle->oidc->nonce) - GNUNET_free(handle->oidc->nonce); - if (NULL != handle->oidc->redirect_uri) - GNUNET_free(handle->oidc->redirect_uri); - if (NULL != handle->oidc->response_type) - GNUNET_free(handle->oidc->response_type); - if (NULL != handle->oidc->scope) - GNUNET_free(handle->oidc->scope); - if (NULL != handle->oidc->state) - GNUNET_free(handle->oidc->state); - if (NULL != handle->oidc->response) - json_decref(handle->oidc->response); - GNUNET_free(handle->oidc); - } - if ( NULL != handle->attr_list ) - { - for (claim_entry = handle->attr_list->list_head; - NULL != claim_entry;) - { - claim_tmp = claim_entry; - claim_entry = claim_entry->next; - GNUNET_free(claim_tmp->claim); - GNUNET_free(claim_tmp); - } - GNUNET_free (handle->attr_list); - } - for (ego_entry = handle->ego_head; - NULL != ego_entry;) - { - ego_tmp = ego_entry; - ego_entry = ego_entry->next; - GNUNET_free (ego_tmp->identifier); - GNUNET_free (ego_tmp->keystring); - GNUNET_free (ego_tmp); - } - if (NULL != handle->attr_it) - { - GNUNET_free(handle->attr_it); - } - GNUNET_free (handle); -} - -static void -cleanup_handle_delayed (void *cls) -{ - cleanup_handle (cls); -} - - -/** - * Task run on error, sends error message. Cleans up everything. - * - * @param cls the `struct RequestHandle` - */ -static void -do_error (void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - char *json_error; - - GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}", - handle->emsg, - (NULL != handle->edesc) ? handle->edesc : "", - (NULL != handle->oidc->state) ? ", \"state\":\"" : "", - (NULL != handle->oidc->state) ? handle->oidc->state : "", - (NULL != handle->oidc->state) ? "\"" : ""); - if ( 0 == handle->response_code ) - { - handle->response_code = MHD_HTTP_BAD_REQUEST; - } - resp = GNUNET_REST_create_response (json_error); - if (MHD_HTTP_UNAUTHORIZED == handle->response_code) - { - MHD_add_response_header(resp, "WWW-Authenticate", "Basic"); - } - MHD_add_response_header (resp, "Content-Type", "application/json"); - handle->proc (handle->proc_cls, resp, handle->response_code); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - GNUNET_free (json_error); -} - - -/** - * Task run on error in userinfo endpoint, sends error header. Cleans up - * everything - * - * @param cls the `struct RequestHandle` - */ -static void -do_userinfo_error (void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - char *error; - - GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"", - handle->emsg, - (NULL != handle->edesc) ? handle->edesc : ""); - resp = GNUNET_REST_create_response (""); - MHD_add_response_header(resp, "WWW-Authenticate", error); - handle->proc (handle->proc_cls, resp, handle->response_code); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - GNUNET_free (error); -} - - -/** - * Task run on error, sends error message and redirects. Cleans up everything. - * - * @param cls the `struct RequestHandle` - */ -static void -do_redirect_error (void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - char* redirect; - GNUNET_asprintf (&redirect, - "%s?error=%s&error_description=%s%s%s", - handle->oidc->redirect_uri, handle->emsg, handle->edesc, - (NULL != handle->oidc->state) ? "&state=" : "", - (NULL != handle->oidc->state) ? handle->oidc->state : ""); - resp = GNUNET_REST_create_response (""); - MHD_add_response_header (resp, "Location", redirect); - handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - GNUNET_free (redirect); -} - -/** - * Task run on timeout, sends error message. Cleans up everything. - * - * @param cls the `struct RequestHandle` - */ -static void -do_timeout (void *cls) -{ - struct RequestHandle *handle = cls; - - handle->timeout_task = NULL; - do_error (handle); -} - -/** - * Return attributes for claim - * - * @param cls the request handle - */ -static void -return_userinfo_response (void *cls) -{ - char* result_str; - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - - result_str = json_dumps (handle->oidc->response, 0); - - resp = GNUNET_REST_create_response (result_str); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result_str); - cleanup_handle (handle); -} - -/** - * Returns base64 encoded string without padding - * - * @param string the string to encode - * @return base64 encoded string - */ -static char* -base_64_encode(const char *s) -{ - char *enc; - char *tmp; - - GNUNET_STRINGS_base64_encode(s, strlen(s), &enc); - tmp = strrchr (enc, '='); - *tmp = '\0'; - return enc; -} - -/** - * Respond to OPTIONS request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp; - struct RequestHandle *handle = cls; - - //For now, independent of path return all options - resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - allow_methods); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); - return; -} - -/** - * Interprets cookie header and pass its identity keystring to handle - */ -static void -cookie_identity_interpretation (struct RequestHandle *handle) -{ - struct GNUNET_HashCode cache_key; - char *cookies; - struct GNUNET_TIME_Absolute current_time, *relog_time; - char delimiter[] = "; "; - - //gets identity of login try with cookie - GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), - &cache_key); - if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, - &cache_key) ) - { - //splits cookies and find 'Identity' cookie - cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); - handle->oidc->login_identity = strtok(cookies, delimiter); - - while ( NULL != handle->oidc->login_identity ) - { - if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) ) - { - break; - } - handle->oidc->login_identity = strtok (NULL, delimiter); - } - GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity), - &cache_key); - if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) ) - { - relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, - &cache_key); - current_time = GNUNET_TIME_absolute_get (); - // 30 min after old login -> redirect to login - if ( current_time.abs_value_us <= relog_time->abs_value_us ) - { - handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY); - handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity); - } else { - handle->oidc->login_identity = NULL; - } - } - else - { - handle->oidc->login_identity = NULL; - } - } -} - -/** - * Redirects to login page stored in configuration file - */ -static void -login_redirection(void *cls) -{ - char *login_base_url; - char *new_redirect; - struct MHD_Response *resp; - struct RequestHandle *handle = cls; - - if ( GNUNET_OK - == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", - "address", &login_base_url) ) - { - GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", - login_base_url, - OIDC_RESPONSE_TYPE_KEY, - handle->oidc->response_type, - OIDC_CLIENT_ID_KEY, - handle->oidc->client_id, - OIDC_REDIRECT_URI_KEY, - handle->oidc->redirect_uri, - OIDC_SCOPE_KEY, - handle->oidc->scope, - OIDC_STATE_KEY, - (NULL != handle->oidc->state) ? handle->oidc->state : "", - OIDC_NONCE_KEY, - (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); - resp = GNUNET_REST_create_response (""); - MHD_add_response_header (resp, "Location", new_redirect); - GNUNET_free(login_base_url); - } - else - { - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup ("gnunet configuration failed"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); - GNUNET_free(new_redirect); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - -/** - * Does internal server error when iteration failed. - */ -static void -oidc_iteration_error (void *cls) -{ - struct RequestHandle *handle = cls; - handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); -} - -static void get_client_name_result (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; - struct MHD_Response *resp; - char *ticket_str; - char *redirect_uri; - char *code_json_string; - char *code_base64_final_string; - char *redirect_path; - char *tmp; - char *tmp_prefix; - char *prefix; - ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, - sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); - //TODO change if more attributes are needed (see max_age) - GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", - ticket_str, - (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", - (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", - (NULL != handle->oidc->nonce) ? "\"" : ""); - code_base64_final_string = base_64_encode(code_json_string); - tmp = GNUNET_strdup (handle->oidc->redirect_uri); - redirect_path = strtok (tmp, "/"); - redirect_path = strtok (NULL, "/"); - redirect_path = strtok (NULL, "/"); - tmp_prefix = GNUNET_strdup (handle->oidc->redirect_uri); - prefix = strrchr (tmp_prefix, - (unsigned char) '.'); - *prefix = '\0'; - GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", - tmp_prefix, - handle->tld, - redirect_path, - handle->oidc->response_type, - code_base64_final_string, handle->oidc->state); - resp = GNUNET_REST_create_response (""); - MHD_add_response_header (resp, "Location", redirect_uri); - handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - GNUNET_free (tmp); - GNUNET_free (tmp_prefix); - GNUNET_free (redirect_uri); - GNUNET_free (ticket_str); - GNUNET_free (code_json_string); - GNUNET_free (code_base64_final_string); - return; -} - -static void -get_client_name_error (void *cls) -{ - struct RequestHandle *handle = cls; - - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client."); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); -} - -/** - * Issues ticket and redirects to relying party with the authorization code as - * parameter. Otherwise redirects with error - */ -static void -oidc_ticket_issue_cb (void* cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) -{ - struct RequestHandle *handle = cls; - handle->idp_op = NULL; - handle->ticket = *ticket; - if (NULL != ticket) { - GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, - &handle->priv_key, - &handle->oidc->client_pkey, - &get_client_name_error, - handle, - &get_client_name_result, - handle); - return; - } - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup("Server cannot generate ticket."); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); -} - -static void -oidc_collect_finished_cb (void *cls) -{ - struct RequestHandle *handle = cls; - handle->attr_it = NULL; - handle->ticket_it = NULL; - if (NULL == handle->attr_list->list_head) - { - handle->emsg = GNUNET_strdup("invalid_scope"); - handle->edesc = GNUNET_strdup("The requested scope is not available."); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - return; - } - handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (handle->idp, - &handle->priv_key, - &handle->oidc->client_pkey, - handle->attr_list, - &oidc_ticket_issue_cb, - handle); -} - - -/** - * Collects all attributes for an ego if in scope parameter - */ -static void -oidc_attr_collect (void *cls, - const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) -{ - struct RequestHandle *handle = cls; - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; - char* scope_variables; - char* scope_variable; - char delimiter[]=" "; - - if ( (NULL == attr->name) || (NULL == attr->data) ) - { - GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); - return; - } - - scope_variables = GNUNET_strdup(handle->oidc->scope); - scope_variable = strtok (scope_variables, delimiter); - while (NULL != scope_variable) - { - if ( 0 == strcmp (attr->name, scope_variable) ) - { - break; - } - scope_variable = strtok (NULL, delimiter); - } - if ( NULL == scope_variable ) - { - GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); - GNUNET_free(scope_variables); - return; - } - GNUNET_free(scope_variables); - - 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(handle->attr_list->list_head, - handle->attr_list->list_tail, le); - GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); -} - - -/** - * Checks time and cookie and redirects accordingly - */ -static void -login_check (void *cls) -{ - struct RequestHandle *handle = cls; - struct GNUNET_TIME_Absolute current_time, *relog_time; - struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey; - struct GNUNET_HashCode cache_key; - char *identity_cookie; - - GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity); - GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); - GNUNET_free(identity_cookie); - //No login time for identity -> redirect to login - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, - &cache_key) ) - { - relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, - &cache_key); - current_time = GNUNET_TIME_absolute_get (); - // 30 min after old login -> redirect to login - if ( current_time.abs_value_us <= relog_time->abs_value_us ) - { - if ( GNUNET_OK - != GNUNET_CRYPTO_ecdsa_public_key_from_string ( - handle->oidc->login_identity, - strlen (handle->oidc->login_identity), &pubkey) ) - { - handle->emsg = GNUNET_strdup("invalid_cookie"); - handle->edesc = GNUNET_strdup( - "The cookie of a login identity is not valid"); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - return; - } - // iterate over egos and compare their public key - for (handle->ego_entry = handle->ego_head; - NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) - { - GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); - if ( 0 - == memcmp (&ego_pkey, &pubkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key ( - handle->ego_entry->ego); - handle->resp_object = GNUNET_JSONAPI_document_new (); - handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); - handle->attr_list = GNUNET_new( - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); - handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start ( - handle->idp, &handle->priv_key, &oidc_iteration_error, handle, - &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle); - return; - } - } - //handle->emsg = GNUNET_strdup("invalid_cookie"); - //handle->edesc = GNUNET_strdup( - // "The cookie of the login identity is not valid"); - //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - GNUNET_SCHEDULER_add_now (&login_redirection,handle); - return; - } - } -} - -/** - * Searches for client_id in namestore. If found trust status stored in handle - * Else continues to search - * - * @param handle the RequestHandle - */ -static void -namestore_iteration_callback ( - void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *rname, unsigned int rd_len, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey; - struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey; - int i; - - for (i = 0; i < rd_len; i++) - { - if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type ) - continue; - - if ( NULL != handle->oidc->login_identity ) - { - GNUNET_CRYPTO_ecdsa_public_key_from_string ( - handle->oidc->login_identity, - strlen (handle->oidc->login_identity), - &login_identity_pkey); - GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, - ¤t_zone_pkey); - - if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - if ( 0 == memcmp (&login_identity_pkey, ¤t_zone_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->oidc->is_client_trusted = GNUNET_YES; - } - } - } - else - { - if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->oidc->is_client_trusted = GNUNET_YES; - } - } - } - - GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it, - 1); -} - - -/** - * Iteration over all results finished, build final - * response. - * - * @param cls the `struct RequestHandle` - */ -static void -namestore_iteration_finished (void *cls) -{ - struct RequestHandle *handle = cls; - struct GNUNET_HashCode cache_key; - - char *expected_scope; - char delimiter[]=" "; - int number_of_ignored_parameter, iterator; - - - handle->ego_entry = handle->ego_entry->next; - - if(NULL != handle->ego_entry) - { - handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); - handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key, - &oidc_iteration_error, handle, &namestore_iteration_callback, handle, - &namestore_iteration_finished, handle); - return; - } - if (GNUNET_NO == handle->oidc->is_client_trusted) - { - handle->emsg = GNUNET_strdup("unauthorized_client"); - handle->edesc = GNUNET_strdup("The client is not authorized to request an " - "authorization code using this method."); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - // REQUIRED value: redirect_uri - GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), - &cache_key); - if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &cache_key)) - { - handle->emsg=GNUNET_strdup("invalid_request"); - handle->edesc=GNUNET_strdup("missing parameter redirect_uri"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, - &cache_key)); - - // REQUIRED value: response_type - GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY), - &cache_key); - if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &cache_key)) - { - handle->emsg=GNUNET_strdup("invalid_request"); - handle->edesc=GNUNET_strdup("missing parameter response_type"); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - return; - } - handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, - &cache_key); - handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type); - - // REQUIRED value: scope - GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key); - if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &cache_key)) - { - handle->emsg=GNUNET_strdup("invalid_request"); - handle->edesc=GNUNET_strdup("missing parameter scope"); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - return; - } - handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, - &cache_key); - handle->oidc->scope = GNUNET_strdup(handle->oidc->scope); - - //OPTIONAL value: nonce - GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key); - if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &cache_key)) - { - handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, - &cache_key); - handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce); - } - - //TODO check other values if needed - number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); - for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) - { - GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], - strlen(OIDC_ignored_parameter_array[iterator]), - &cache_key); - if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map, - &cache_key)) - { - handle->emsg=GNUNET_strdup("access_denied"); - GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s", - OIDC_ignored_parameter_array[iterator]); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - return; - } - } - - // Checks if response_type is 'code' - if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) - { - handle->emsg=GNUNET_strdup("unsupported_response_type"); - handle->edesc=GNUNET_strdup("The authorization server does not support " - "obtaining this authorization code."); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - return; - } - - // Checks if scope contains 'openid' - expected_scope = GNUNET_strdup(handle->oidc->scope); - char* test; - test = strtok (expected_scope, delimiter); - while (NULL != test) - { - if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) ) - { - break; - } - test = strtok (NULL, delimiter); - } - if (NULL == test) - { - handle->emsg = GNUNET_strdup("invalid_scope"); - handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " - "malformed."); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); - GNUNET_free(expected_scope); - return; - } - - GNUNET_free(expected_scope); - - if( NULL != handle->oidc->login_identity ) - { - GNUNET_SCHEDULER_add_now(&login_check,handle); - return; - } - - GNUNET_SCHEDULER_add_now(&login_redirection,handle); -} - -/** - * Responds to authorization GET and url-encoded POST request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct RequestHandle *handle = cls; - struct GNUNET_HashCode cache_key; - struct EgoEntry *tmp_ego; - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; - - cookie_identity_interpretation(handle); - - //RECOMMENDED value: state - REQUIRED for answers - GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key); - if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &cache_key)) - { - handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, - &cache_key); - handle->oidc->state = GNUNET_strdup (handle->oidc->state); - } - - // REQUIRED value: client_id - GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), - &cache_key); - if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &cache_key)) - { - handle->emsg=GNUNET_strdup("invalid_request"); - handle->edesc=GNUNET_strdup("missing parameter client_id"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, - &cache_key)); - - if ( GNUNET_OK - != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id, - strlen (handle->oidc->client_id), - &handle->oidc->client_pkey) ) - { - handle->emsg = GNUNET_strdup("unauthorized_client"); - handle->edesc = GNUNET_strdup("The client is not authorized to request an " - "authorization code using this method."); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - - if ( NULL == handle->ego_head ) - { - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup ("Egos are missing"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - handle->ego_entry = handle->ego_head; - handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); - handle->oidc->is_client_trusted = GNUNET_NO; - - //First check if client_id is one of our egos; TODO: handle other TLD cases: Delegation, from config - for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) - { - priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); - GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, - &pkey); - if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->tld = GNUNET_strdup (tmp_ego->identifier); - handle->oidc->is_client_trusted = GNUNET_YES; - handle->ego_entry = handle->ego_tail; - } - } - - - // Checks if client_id is valid: - handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start ( - handle->namestore_handle, &handle->priv_key, &oidc_iteration_error, - handle, &namestore_iteration_callback, handle, - &namestore_iteration_finished, handle); -} - -/** - * Combines an identity with a login time and responds OK to login request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -login_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp = GNUNET_REST_create_response (""); - struct RequestHandle *handle = cls; - struct GNUNET_HashCode cache_key; - struct GNUNET_TIME_Absolute *current_time; - struct GNUNET_TIME_Absolute *last_time; - char* cookie; - json_t *root; - json_error_t error; - json_t *identity; - char term_data[handle->rest_handle->data_size+1]; - term_data[handle->rest_handle->data_size] = '\0'; - GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size); - root = json_loads (term_data, JSON_DECODE_ANY, &error); - identity = json_object_get (root, "identity"); - if ( json_is_string(identity) ) - { - GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity)); - MHD_add_response_header (resp, "Set-Cookie", cookie); - MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST"); - GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key); - - current_time = GNUNET_new(struct GNUNET_TIME_Absolute); - *current_time = GNUNET_TIME_relative_to_absolute ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), - 5)); - last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key); - if (NULL != last_time) - { - GNUNET_free(last_time); - } - GNUNET_CONTAINER_multihashmap_put ( - OIDC_identity_login_time, &cache_key, current_time, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); - - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free(cookie); - } - else - { - handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); - } - json_decref (root); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - return; -} - -/** - * Responds to token url-encoded POST request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - //TODO static strings - struct RequestHandle *handle = cls; - struct GNUNET_HashCode cache_key; - char *authorization, *credentials; - char delimiter[]=" "; - char delimiter_user_psw[]=":"; - char *grant_type, *code; - char *user_psw = NULL, *client_id, *psw; - char *expected_psw; - int client_exists = GNUNET_NO; - struct MHD_Response *resp; - char* code_output; - json_t *root, *ticket_string, *nonce, *max_age; - json_error_t error; - char *json_response; - char *jwt_secret; - - /* - * Check Authorization - */ - GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, - strlen (OIDC_AUTHORIZATION_HEADER_KEY), - &cache_key); - if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, - &cache_key) ) - { - handle->emsg=GNUNET_strdup("invalid_client"); - handle->edesc=GNUNET_strdup("missing authorization"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); - - //split header in "Basic" and [content] - credentials = strtok (authorization, delimiter); - if (0 != strcmp ("Basic",credentials)) - { - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - credentials = strtok(NULL, delimiter); - if (NULL == credentials) - { - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw); - - if ( NULL == user_psw ) - { - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - client_id = strtok (user_psw, delimiter_user_psw); - if ( NULL == client_id ) - { - GNUNET_free_non_null(user_psw); - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - psw = strtok (NULL, delimiter_user_psw); - if (NULL == psw) - { - GNUNET_free_non_null(user_psw); - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //check client password - if ( GNUNET_OK - == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", - "psw", &expected_psw) ) - { - if (0 != strcmp (expected_psw, psw)) - { - GNUNET_free_non_null(user_psw); - GNUNET_free(expected_psw); - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_free(expected_psw); - } - else - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup ("gnunet configuration failed"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //check client_id - for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; ) - { - if ( 0 == strcmp(handle->ego_entry->keystring, client_id)) - { - client_exists = GNUNET_YES; - break; - } - handle->ego_entry = handle->ego_entry->next; - } - if (GNUNET_NO == client_exists) - { - GNUNET_free_non_null(user_psw); - handle->emsg=GNUNET_strdup("invalid_client"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - /* - * Check parameter - */ - - //TODO Do not allow multiple equal parameter names - //REQUIRED grant_type - GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->url_param_map, &cache_key) ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("missing parameter grant_type"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - grant_type = GNUNET_CONTAINER_multihashmap_get ( - handle->rest_handle->url_param_map, &cache_key); - - //REQUIRED code - GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->url_param_map, &cache_key) ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("missing parameter code"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &cache_key); - - //REQUIRED redirect_uri - GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), - &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->url_param_map, &cache_key) ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //Check parameter grant_type == "authorization_code" - if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) - { - GNUNET_free_non_null(user_psw); - handle->emsg=GNUNET_strdup("unsupported_grant_type"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_CRYPTO_hash (code, strlen (code), &cache_key); - int i = 1; - if ( GNUNET_SYSERR - == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, - &cache_key, - &i, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("Cannot use the same code more than once"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //decode code - GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output); - root = json_loads (code_output, 0, &error); - GNUNET_free(code_output); - ticket_string = json_object_get (root, "ticket"); - nonce = json_object_get (root, "nonce"); - max_age = json_object_get (root, "max_age"); - - if(ticket_string == NULL && !json_is_string(ticket_string)) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket); - if ( GNUNET_OK - != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string), - strlen (json_string_value(ticket_string)), - ticket, - sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket))) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } - // this is the current client (relying party) - struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; - GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); - if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } - - //create jwt - unsigned long long int expiration_time; - if ( GNUNET_OK - != GNUNET_CONFIGURATION_get_value_number(cfg, "identity-rest-plugin", - "expiration_time", &expiration_time) ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup ("gnunet configuration failed"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } - - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); - //aud REQUIRED public key client_id must be there - GNUNET_IDENTITY_ATTRIBUTE_list_add(cl, - "aud", - GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, - client_id, - strlen(client_id)); - //exp REQUIRED time expired from config - struct GNUNET_TIME_Absolute exp_time = GNUNET_TIME_relative_to_absolute ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), - expiration_time)); - const char* exp_time_string = GNUNET_STRINGS_absolute_time_to_string(exp_time); - GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, - "exp", - GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, - exp_time_string, - strlen(exp_time_string)); - //iat REQUIRED time now - struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get(); - const char* time_now_string = GNUNET_STRINGS_absolute_time_to_string(time_now); - GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, - "iat", - GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, - time_now_string, - strlen(time_now_string)); - //nonce only if nonce is provided - if ( NULL != nonce && json_is_string(nonce) ) - { - GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, - "nonce", - GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, - json_string_value(nonce), - strlen(json_string_value(nonce))); - } - //auth_time only if max_age is provided - if ( NULL != max_age && json_is_string(max_age) ) - { - GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, - "auth_time", - GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, - json_string_value(max_age), - strlen(json_string_value(max_age))); - } - //TODO OPTIONAL acr,amr,azp - - struct EgoEntry *ego_entry; - for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) - { - GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); - if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) - { - break; - } - } - if ( NULL == ego_entry ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code..."); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } - if ( GNUNET_OK - != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", - "jwt_secret", &jwt_secret) ) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("No signing secret configured!"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } - struct GNUNET_CRYPTO_AuthKey jwt_sign_key; - struct GNUNET_CRYPTO_EcdsaPublicKey pk; - GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk); - GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key); - char *id_token = jwt_create_from_list(&ticket->audience, - &pk, - cl, - &jwt_sign_key); - - //Create random access_token - char* access_token_number; - char* access_token; - uint64_t random_number; - random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); - GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number); - GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); - - - - //TODO OPTIONAL add refresh_token and scope - GNUNET_asprintf (&json_response, - "{ \"access_token\" : \"%s\", " - "\"token_type\" : \"Bearer\", " - "\"expires_in\" : %d, " - "\"id_token\" : \"%s\"}", - access_token, - expiration_time, - id_token); - GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); - char *id_ticket_combination; - GNUNET_asprintf(&id_ticket_combination, - "%s;%s", - client_id, - json_string_value(ticket_string)); - GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, - &cache_key, - id_ticket_combination, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); - - resp = GNUNET_REST_create_response (json_response); - MHD_add_response_header (resp, "Cache-Control", "no-store"); - MHD_add_response_header (resp, "Pragma", "no-cache"); - MHD_add_response_header (resp, "Content-Type", "application/json"); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - - GNUNET_IDENTITY_ATTRIBUTE_list_destroy(cl); - GNUNET_free(access_token_number); - GNUNET_free(access_token); - GNUNET_free(user_psw); - GNUNET_free(json_response); - GNUNET_free(ticket); - GNUNET_free(id_token); - json_decref (root); - GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle); -} - -/** - * Collects claims and stores them in handle - */ -static void -consume_ticket (void *cls, - const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) -{ - struct RequestHandle *handle = cls; - char *tmp_value; - json_t *value; - - if (NULL == identity) - { - GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); - return; - } - - tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type, - attr->data, - attr->data_size); - - value = json_string (tmp_value); - - - json_object_set_new (handle->oidc->response, - attr->name, - value); - GNUNET_free (tmp_value); -} - -/** - * Responds to userinfo GET and url-encoded POST request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, void *cls) -{ - //TODO expiration time - struct RequestHandle *handle = cls; - char delimiter[] = " "; - char delimiter_db[] = ";"; - struct GNUNET_HashCode cache_key; - char *authorization, *authorization_type, *authorization_access_token; - char *client_ticket, *client, *ticket_str; - struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; - - GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, - strlen (OIDC_AUTHORIZATION_HEADER_KEY), - &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->header_param_map, &cache_key) ) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("No Access Token"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - return; - } - authorization = GNUNET_CONTAINER_multihashmap_get ( - handle->rest_handle->header_param_map, &cache_key); - - //split header in "Bearer" and access_token - authorization = GNUNET_strdup(authorization); - authorization_type = strtok (authorization, delimiter); - if ( 0 != strcmp ("Bearer", authorization_type) ) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("No Access Token"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(authorization); - return; - } - authorization_access_token = strtok (NULL, delimiter); - if ( NULL == authorization_access_token ) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("No Access Token"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(authorization); - return; - } - - GNUNET_CRYPTO_hash (authorization_access_token, - strlen (authorization_access_token), - &cache_key); - if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token, - &cache_key) ) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("The Access Token expired"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(authorization); - return; - } - - client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token, - &cache_key); - client_ticket = GNUNET_strdup(client_ticket); - client = strtok(client_ticket,delimiter_db); - if (NULL == client) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("The Access Token expired"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(authorization); - GNUNET_free(client_ticket); - return; - } - handle->ego_entry = handle->ego_head; - for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) - { - if (0 == strcmp(handle->ego_entry->keystring,client)) - { - break; - } - } - if (NULL == handle->ego_entry) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("The Access Token expired"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(authorization); - GNUNET_free(client_ticket); - return; - } - ticket_str = strtok(NULL, delimiter_db); - if (NULL == ticket_str) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("The Access Token expired"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(authorization); - GNUNET_free(client_ticket); - return; - } - ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket); - if ( GNUNET_OK - != GNUNET_STRINGS_string_to_data (ticket_str, - strlen (ticket_str), - ticket, - sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket))) - { - handle->emsg = GNUNET_strdup("invalid_token"); - handle->edesc = GNUNET_strdup("The Access Token expired"); - handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); - GNUNET_free(ticket); - GNUNET_free(authorization); - GNUNET_free(client_ticket); - return; - } - - handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); - handle->oidc->response = json_object(); - json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring)); - handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume ( - handle->idp, - GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego), - ticket, - consume_ticket, - handle); - GNUNET_free(ticket); - GNUNET_free(authorization); - GNUNET_free(client_ticket); - -} - - -/** - * Handle rest request - * - * @param handle the request handle - */ -static void -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_AUTHORIZE, &authorize_endpoint}, - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint }, - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, - &options_cont}, - GNUNET_REST_HANDLER_END - }; - - if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, - handlers, - &err, - handle)) - { - handle->response_code = err.error_code; - GNUNET_SCHEDULER_add_now (&do_error, handle); - } -} - -/** - * If listing is enabled, prints information about the egos. - * - * This function is initially called for all egos and then again - * whenever a ego's identifier changes or if it is deleted. At the - * end of the initial pass over all egos, the function is once called - * with 'NULL' for 'ego'. That does NOT mean that the callback won't - * be invoked in the future or that there was an error. - * - * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', - * this function is only called ONCE, and 'NULL' being passed in - * 'ego' does indicate an error (i.e. name is taken or no default - * value is known). If 'ego' is non-NULL and if '*ctx' - * is set in those callbacks, the value WILL be passed to a subsequent - * call to the identity callback of 'GNUNET_IDENTITY_connect' (if - * that one was not NULL). - * - * When an identity is renamed, this function is called with the - * (known) ego but the NEW identifier. - * - * When an identity is deleted, this function is called with the - * (known) ego and "NULL" for the 'identifier'. In this case, - * the 'ego' is henceforth invalid (and the 'ctx' should also be - * cleaned up). - * - * @param cls closure - * @param ego ego handle - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param identifier identifier assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used - */ -static void -list_ego (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *identifier) -{ - struct RequestHandle *handle = cls; - struct EgoEntry *ego_entry; - struct GNUNET_CRYPTO_EcdsaPublicKey pk; - - if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) - { - handle->state = ID_REST_STATE_POST_INIT; - init_cont (handle); - return; - } - if (ID_REST_STATE_INIT == handle->state) { - ego_entry = GNUNET_new (struct EgoEntry); - GNUNET_IDENTITY_ego_get_public_key (ego, &pk); - ego_entry->keystring = - GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); - ego_entry->ego = ego; - ego_entry->identifier = GNUNET_strdup (identifier); - GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); - return; - } - /* Ego renamed or added */ - if (identifier != NULL) { - for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { - if (ego_entry->ego == ego) { - /* Rename */ - GNUNET_free (ego_entry->identifier); - ego_entry->identifier = GNUNET_strdup (identifier); - break; - } - } - if (NULL == ego_entry) { - /* Add */ - ego_entry = GNUNET_new (struct EgoEntry); - GNUNET_IDENTITY_ego_get_public_key (ego, &pk); - ego_entry->keystring = - GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); - ego_entry->ego = ego; - ego_entry->identifier = GNUNET_strdup (identifier); - GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); - } - } else { - /* Delete */ - for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { - if (ego_entry->ego == ego) - break; - } - if (NULL != ego_entry) - GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry); - } - -} - -static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) -{ - struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - handle->oidc = GNUNET_new (struct OIDC_Variables); - if ( NULL == OIDC_identity_login_time ) - OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); - if ( NULL == OIDC_identity_grants ) - OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); - if ( NULL == OIDC_ticket_once ) - OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); - if ( NULL == OIDC_interpret_access_token ) - OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); - handle->response_code = 0; - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - handle->state = ID_REST_STATE_INIT; - handle->rest_handle = rest_handle; - - 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, - "Connecting...\n"); - handle->identity_handle = GNUNET_IDENTITY_connect (cfg, - &list_ego, - handle); - handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); - handle->timeout_task = - GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_timeout, - handle); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected\n"); -} - -/** - * Entry point for the plugin. - * - * @param cls Config info - * @return NULL on error, otherwise the plugin context - */ -void * -libgnunet_plugin_rest_openid_connect_init (void *cls) -{ - static struct Plugin plugin; - struct GNUNET_REST_Plugin *api; - - cfg = cls; - 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_OIDC; - api->process_request = &rest_identity_process_request; - GNUNET_asprintf (&allow_methods, - "%s, %s, %s, %s, %s", - MHD_HTTP_METHOD_GET, - MHD_HTTP_METHOD_POST, - MHD_HTTP_METHOD_PUT, - MHD_HTTP_METHOD_DELETE, - MHD_HTTP_METHOD_OPTIONS); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Identity Provider 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_openid_connect_done (void *cls) -{ - struct GNUNET_REST_Plugin *api = cls; - struct Plugin *plugin = api->cls; - plugin->cfg = NULL; - - struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it; - void *value = NULL; - hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create ( - OIDC_identity_login_time); - while (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) - { - if (NULL != value) - GNUNET_free(value); - } - GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time); - hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants); - while (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) - { - if (NULL != value) - GNUNET_free(value); - } - GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants); - hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once); - while (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) - { - if (NULL != value) - GNUNET_free(value); - } - GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once); - hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token); - while (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) - { - if (NULL != value) - GNUNET_free(value); - } - GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token); - GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it); - GNUNET_free_non_null (allow_methods); - GNUNET_free (api); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Identity Provider REST plugin is finished\n"); - return NULL; -} - -/* end of plugin_rest_identity_provider.c */ diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf deleted file mode 100644 index 3e4df561a..000000000 --- a/src/identity-provider/test_idp.conf +++ /dev/null @@ -1,33 +0,0 @@ -@INLINE@ test_idp_defaults.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-peer-1/ - -[dht] -START_ON_DEMAND = YES - -[rest] -START_ON_DEMAND = YES -PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog - -[transport] -PLUGINS = - -[identity-provider] -START_ON_DEMAND = YES -#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog - -[gns] -#PREFIX = valgrind --leak-check=full --track-origins=yes -START_ON_DEMAND = 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 - -[identity-rest-plugin] -address = http://localhost:8000/#/login -psw = mysupersecretpassword -expiration_time = 3600 diff --git a/src/identity-provider/test_idp.sh b/src/identity-provider/test_idp.sh deleted file mode 100755 index 598d1008c..000000000 --- a/src/identity-provider/test_idp.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/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 deleted file mode 100755 index 7f0f06dac..000000000 --- a/src/identity-provider/test_idp_attribute.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/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 deleted file mode 100755 index 11f6865a4..000000000 --- a/src/identity-provider/test_idp_consume.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/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 deleted file mode 100644 index a9a197dea..000000000 --- a/src/identity-provider/test_idp_defaults.conf +++ /dev/null @@ -1,24 +0,0 @@ -@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_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 deleted file mode 100755 index 90487ee73..000000000 --- a/src/identity-provider/test_idp_issue.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/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 deleted file mode 100755 index 7a3f5d030..000000000 --- a/src/identity-provider/test_idp_revoke.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/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 2&>1 > /dev/null -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 -E 15s -a email -V john@doe.gnu -c test_idp.conf -gnunet-idp -e alice -E 15s -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 - -#sleep 6 - -gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf 2&>1 >/dev/null -if test $? == 0 -then - echo "Eve can still resolve attributes..." - gnunet-arm -e -c test_idp.conf - exit 1 -fi - -gnunet-arm -e -c test_idp.conf -gnunet-arm -s -c test_idp.conf 2&>1 > /dev/null - -gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf 2&>1 >/dev/null -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/include/Makefile.am b/src/include/Makefile.am index 08e9dd156..41b2b1382 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -66,7 +66,7 @@ gnunetinclude_HEADERS = \ gnunet_hello_lib.h \ gnunet_helper_lib.h \ gnunet_identity_service.h \ - gnunet_identity_provider_service.h \ + gnunet_reclaim_service.h \ gnunet_json_lib.h \ gnunet_jsonapi_lib.h \ gnunet_jsonapi_util.h \ diff --git a/src/include/gnunet_identity_attribute_lib.h b/src/include/gnunet_identity_attribute_lib.h deleted file mode 100644 index eb01f7ac2..000000000 --- a/src/include/gnunet_identity_attribute_lib.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2017 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @author Martin Schanzenbach - * - * @file - * Identity attribute definitions - * - * @defgroup identity-provider Identity Provider service - * @{ - */ -#ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H -#define GNUNET_IDENTITY_ATTRIBUTE_LIB_H - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -#include "gnunet_util_lib.h" - - -/** - * No value attribute. - */ -#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_NONE 0 - -/** - * String attribute. - */ -#define GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING 1 - - - -/** - * An attribute. - */ -struct GNUNET_IDENTITY_ATTRIBUTE_Claim -{ - /** - * The name of the attribute. Note "name" must never be individually - * free'd - */ - const char* name; - - /** - * Type of Claim - */ - uint32_t type; - - /** - * Version - */ - uint32_t version; - - /** - * Number of bytes in @e data. - */ - size_t data_size; - - /** - * Binary value stored as attribute value. Note: "data" must never - * be individually 'malloc'ed, but instead always points into some - * existing data area. - */ - const void *data; - -}; - -struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList -{ - /** - * List head - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_head; - - /** - * List tail - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *list_tail; -}; - -struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry -{ - /** - * DLL - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *prev; - - /** - * DLL - */ - struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *next; - - /** - * The attribute claim - */ - struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim; -}; - -/** - * Create a new attribute claim. - * - * @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); - - -/** - * Get required size for serialization buffer - * - * @param attrs the attribute list to serialize - * - * @return the required buffer size - */ -size_t -GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); - -void -GNUNET_IDENTITY_ATTRIBUTE_list_destroy (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); - -void -GNUNET_IDENTITY_ATTRIBUTE_list_add (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, - const char* attr_name, - uint32_t type, - const void* data, - size_t data_size); - -/** - * Serialize an attribute list - * - * @param attrs the attribute list to serialize - * @param result the serialized attribute - * - * @return length of serialized data - */ -size_t -GNUNET_IDENTITY_ATTRIBUTE_list_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, - char *result); - -/** - * Deserialize an attribute list - * - * @param data the serialized attribute list - * @param data_size the length of the serialized data - * - * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller - */ -struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList * -GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (const char* data, - size_t data_size); - - -/** - * Get required size for serialization buffer - * - * @param attr the attribute to serialize - * - * @return the required buffer size - */ -size_t -GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr); - - - -/** - * Serialize an attribute - * - * @param attr the attribute to serialize - * @param result the serialized attribute - * - * @return length of serialized data - */ -size_t -GNUNET_IDENTITY_ATTRIBUTE_serialize (const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr, - char *result); - -/** - * Deserialize an attribute - * - * @param data the serialized attribute - * @param data_size the length of the serialized data - * - * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller - */ -struct GNUNET_IDENTITY_ATTRIBUTE_Claim * -GNUNET_IDENTITY_ATTRIBUTE_deserialize (const char* data, - size_t data_size); - -struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList* -GNUNET_IDENTITY_ATTRIBUTE_list_dup (const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); - -/** - * 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); - -/** - * 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); - -/** - * 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); - -/** - * 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); - - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - - -/* ifndef GNUNET_IDENTITY_ATTRIBUTE_LIB_H */ -#endif - -/** @} */ /* end of group identity */ - -/* end of gnunet_identity_attribute_lib.h */ diff --git a/src/include/gnunet_identity_attribute_plugin.h b/src/include/gnunet_identity_attribute_plugin.h deleted file mode 100644 index 7c399c616..000000000 --- a/src/include/gnunet_identity_attribute_plugin.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @author Martin Schanzenbach - * - * @file - * Plugin API for the idp database backend - * - * @defgroup identity-provider-plugin IdP service plugin API - * Plugin API for the idp database backend - * @{ - */ -#ifndef GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H -#define GNUNET_IDENTITY_ATTRIBUTE_PLUGIN_H - -#include "gnunet_util_lib.h" -#include "gnunet_identity_attribute_lib.h" - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - - -/** - * Function called to convert the binary value @a data of an attribute of - * type @a type to a human-readable string. - * - * @param cls closure - * @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 - */ -typedef char * (*GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction) (void *cls, - uint32_t type, - const void *data, - size_t data_size); - - -/** - * Function called to convert human-readable version of the value @a s - * of an attribute of type @a type to the respective binary - * representation. - * - * @param cls closure - * @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 - */ -typedef int (*GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction) (void *cls, - uint32_t type, - const char *s, - void **data, - size_t *data_size); - - -/** - * Function called to convert a type name to the - * corresponding number. - * - * @param cls closure - * @param typename name to convert - * @return corresponding number, UINT32_MAX on error - */ -typedef uint32_t (*GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction) (void *cls, - const char *typename); - - -/** - * Function called to convert a type number (i.e. 1) to the - * corresponding type string - * - * @param cls closure - * @param type number of a type to convert - * @return corresponding typestring, NULL on error - */ -typedef const char * (*GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction) (void *cls, - uint32_t type); - - -/** - * Each plugin is required to return a pointer to a struct of this - * type as the return value from its entry point. - */ -struct GNUNET_IDENTITY_ATTRIBUTE_PluginFunctions -{ - - /** - * Closure for all of the callbacks. - */ - void *cls; - - /** - * Conversion to string. - */ - GNUNET_IDENTITY_ATTRIBUTE_ValueToStringFunction value_to_string; - - /** - * Conversion to binary. - */ - GNUNET_IDENTITY_ATTRIBUTE_StringToValueFunction string_to_value; - - /** - * Typename to number. - */ - GNUNET_IDENTITY_ATTRIBUTE_TypenameToNumberFunction typename_to_number; - - /** - * Number to typename. - */ - GNUNET_IDENTITY_ATTRIBUTE_NumberToTypenameFunction number_to_typename; - -}; - - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif - -/** @} */ /* end of group */ diff --git a/src/include/gnunet_identity_provider_plugin.h b/src/include/gnunet_identity_provider_plugin.h deleted file mode 100644 index 2330066dd..000000000 --- a/src/include/gnunet_identity_provider_plugin.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @author Martin Schanzenbach - * - * @file - * Plugin API for the idp database backend - * - * @defgroup identity-provider-plugin IdP service plugin API - * Plugin API for the idp database backend - * @{ - */ -#ifndef GNUNET_IDENTITY_PROVIDER_PLUGIN_H -#define GNUNET_IDENTITY_PROVIDER_PLUGIN_H - -#include "gnunet_util_lib.h" -#include "gnunet_identity_provider_service.h" - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - - -/** - * Function called by for each matching ticket. - * - * @param cls closure - * @param ticket the ticket - */ -typedef void (*GNUNET_IDENTITY_PROVIDER_TicketIterator) (void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, - const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); - - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct GNUNET_IDENTITY_PROVIDER_PluginFunctions -{ - - /** - * Closure to pass to all plugin functions. - */ - void *cls; - - /** - * Store a ticket in the database. - * - * @param cls closure (internal context for the plugin) - * @param ticket the ticket to store - * @return #GNUNET_OK on success, else #GNUNET_SYSERR - */ - int (*store_ticket) (void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, - const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); - - /** - * Delete a ticket from the database. - * - * @param cls closure (internal context for the plugin) - * @param ticket the ticket to store - * @return #GNUNET_OK on success, else #GNUNET_SYSERR - */ - int (*delete_ticket) (void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); - - - - /** - * Iterate over all tickets - * - * @param cls closure (internal context for the plugin) - * @param identity the identity - * @param audience GNUNET_YES if the identity is the audience of the ticket - * else it is considered the issuer - * @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 - */ - int (*iterate_tickets) (void *cls, - const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - int audience, - uint64_t offset, - GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void *iter_cls); - - int (*get_ticket_attributes) (void* cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, - GNUNET_IDENTITY_PROVIDER_TicketIterator iter, - void *iter_cls); -}; - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif - -/** @} */ /* end of group */ diff --git a/src/include/gnunet_identity_provider_service.h b/src/include/gnunet_identity_provider_service.h deleted file mode 100644 index 0c72556e8..000000000 --- a/src/include/gnunet_identity_provider_service.h +++ /dev/null @@ -1,378 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2016 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @author Martin Schanzenbach - * - * @file - * Identity provider service; implements identity provider for GNUnet - * - * @defgroup identity-provider Identity Provider service - * @{ - */ -#ifndef GNUNET_IDENTITY_PROVIDER_SERVICE_H -#define GNUNET_IDENTITY_PROVIDER_SERVICE_H - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -#include "gnunet_util_lib.h" -#include "gnunet_identity_attribute_lib.h" - -/** - * Version number of GNUnet Identity Provider API. - */ -#define GNUNET_IDENTITY_PROVIDER_VERSION 0x00000000 - -/** - * Handle to access the identity service. - */ -struct GNUNET_IDENTITY_PROVIDER_Handle; - -/** - * Handle for a token. - */ -struct GNUNET_IDENTITY_PROVIDER_Token; - -/** - * The ticket - */ -struct GNUNET_IDENTITY_PROVIDER_Ticket -{ - /** - * The ticket issuer - */ - struct GNUNET_CRYPTO_EcdsaPublicKey identity; - - /** - * The ticket audience - */ - struct GNUNET_CRYPTO_EcdsaPublicKey audience; - - /** - * The ticket random (NBO) - */ - uint64_t rnd; -}; - -/** - * Handle for an operation with the identity provider service. - */ -struct GNUNET_IDENTITY_PROVIDER_Operation; - - -/** - * Connect to the identity provider service. - * - * @param cfg Configuration to contact the identity provider service. - * @return handle to communicate with identity provider service - */ -struct GNUNET_IDENTITY_PROVIDER_Handle * -GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); - -/** - * Continuation called to notify client about result of the - * operation. - * - * @param cls closure - * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) - * #GNUNET_NO if content was already there or not found - * #GNUNET_YES (or other positive value) on success - * @param emsg NULL on success, otherwise an error message - */ -typedef void -(*GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus) (void *cls, - int32_t success, - const char *emsg); - - -/** - * 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 - * @param exp_interval the relative expiration interval for the attribute - * @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, - const struct GNUNET_TIME_Relative *exp_interval, - GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont, - void *cont_cls); - - -/** - * Process an attribute that was stored in the idp. - * - * @param cls closure - * @param identity the identity - * @param attr the attribute - */ -typedef void -(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls, - const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr); - - - -/** - * 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); - - -/** - * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start - * for the next record. - * - * @param it the iterator - */ -void -GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it); - - -/** - * 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); - - -/** - * Method called when a token has been issued. - * On success returns a ticket that can be given to the audience to retrive the - * token - * - * @param cls closure - * @param ticket the ticket - */ -typedef void -(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls, - const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket); - -/** - * Issues a ticket to another identity. The identity may use - * GNUNET_IDENTITY_PROVIDER_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); - -/** - * 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); - - - -/** - * 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 audience) - * @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); - -/** - * Lists all tickets that have been issued to remote - * identites (relying parties) - * - * @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 - */ -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); - -/** - * Lists all tickets that have been issued to remote - * identites (relying parties) - * - * @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 - */ -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); - -/** - * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start - * for the next record. - * - * @param it the iterator - */ -void -GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it); - -/** - * 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_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it); - -/** - * Disconnect from identity provider service. - * - * @param h identity provider service to disconnect - */ -void -GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); - - -/** - * Cancel an identity provider 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 - * the operation. - * - * @param op operation to cancel - */ -void -GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op); - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - - -/* ifndef GNUNET_IDENTITY_PROVIDER_SERVICE_H */ -#endif - -/** @} */ /* end of group identity */ - -/* end of gnunet_identity_provider_service.h */ diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 36aa424b4..4400db7e1 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2656,35 +2656,35 @@ extern "C" * * IDENTITY PROVIDER MESSAGE TYPES */ -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 961 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE 961 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 962 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE 962 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 963 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START 963 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 964 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP 964 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 965 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT 965 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT 966 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967 +#define GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET 967 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968 +#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT 968 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 969 +#define GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET 969 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT 970 +#define GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT 970 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 971 +#define GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET 971 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 972 +#define GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT 972 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 973 +#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START 973 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 974 +#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP 974 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 975 +#define GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT 975 /************************************************** * diff --git a/src/include/gnunet_reclaim_attribute_lib.h b/src/include/gnunet_reclaim_attribute_lib.h new file mode 100644 index 000000000..df5356d76 --- /dev/null +++ b/src/include/gnunet_reclaim_attribute_lib.h @@ -0,0 +1,281 @@ +/* + This file is part of GNUnet. + Copyright (C) 2017 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @author Martin Schanzenbach + * + * @file + * Identity attribute definitions + * + * @defgroup identity-provider Identity Provider service + * @{ + */ +#ifndef GNUNET_RECLAIM_ATTRIBUTE_LIB_H +#define GNUNET_RECLAIM_ATTRIBUTE_LIB_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +#include "gnunet_util_lib.h" + + +/** + * No value attribute. + */ +#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE 0 + +/** + * String attribute. + */ +#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING 1 + + + +/** + * An attribute. + */ +struct GNUNET_RECLAIM_ATTRIBUTE_Claim +{ + /** + * The name of the attribute. Note "name" must never be individually + * free'd + */ + const char* name; + + /** + * Type of Claim + */ + uint32_t type; + + /** + * Version + */ + uint32_t version; + + /** + * Number of bytes in @e data. + */ + size_t data_size; + + /** + * Binary value stored as attribute value. Note: "data" must never + * be individually 'malloc'ed, but instead always points into some + * existing data area. + */ + const void *data; + +}; + +struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList +{ + /** + * List head + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *list_head; + + /** + * List tail + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *list_tail; +}; + +struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry +{ + /** + * DLL + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *prev; + + /** + * DLL + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *next; + + /** + * The attribute claim + */ + struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; +}; + +/** + * Create a new attribute claim. + * + * @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_RECLAIM_ATTRIBUTE_Claim * +GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char* attr_name, + uint32_t type, + const void* data, + size_t data_size); + + +/** + * Get required size for serialization buffer + * + * @param attrs the attribute list to serialize + * + * @return the required buffer size + */ +size_t +GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs); + +void +GNUNET_RECLAIM_ATTRIBUTE_list_destroy (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs); + +void +GNUNET_RECLAIM_ATTRIBUTE_list_add (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const char* attr_name, + uint32_t type, + const void* data, + size_t data_size); + +/** + * Serialize an attribute list + * + * @param attrs the attribute list to serialize + * @param result the serialized attribute + * + * @return length of serialized data + */ +size_t +GNUNET_RECLAIM_ATTRIBUTE_list_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + char *result); + +/** + * Deserialize an attribute list + * + * @param data the serialized attribute list + * @param data_size the length of the serialized data + * + * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller + */ +struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * +GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char* data, + size_t data_size); + + +/** + * Get required size for serialization buffer + * + * @param attr the attribute to serialize + * + * @return the required buffer size + */ +size_t +GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr); + + + +/** + * Serialize an attribute + * + * @param attr the attribute to serialize + * @param result the serialized attribute + * + * @return length of serialized data + */ +size_t +GNUNET_RECLAIM_ATTRIBUTE_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, + char *result); + +/** + * Deserialize an attribute + * + * @param data the serialized attribute + * @param data_size the length of the serialized data + * + * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller + */ +struct GNUNET_RECLAIM_ATTRIBUTE_Claim * +GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char* data, + size_t data_size); + +struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList* +GNUNET_RECLAIM_ATTRIBUTE_list_dup (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs); + +/** + * Convert a type name to the corresponding number + * + * @param typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +uint32_t +GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename); + +/** + * 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_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type, + const char *s, + void **data, + size_t *data_size); + +/** + * 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_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type, + const void* data, + size_t data_size); + +/** + * Convert a type number to the corresponding type string + * + * @param type number of a type + * @return corresponding typestring, NULL on error + */ +const char* +GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type); + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + + +/* ifndef GNUNET_RECLAIM_ATTRIBUTE_LIB_H */ +#endif + +/** @} */ /* end of group identity */ + +/* end of gnunet_reclaim_attribute_lib.h */ diff --git a/src/include/gnunet_reclaim_attribute_plugin.h b/src/include/gnunet_reclaim_attribute_plugin.h new file mode 100644 index 000000000..cf0bb141a --- /dev/null +++ b/src/include/gnunet_reclaim_attribute_plugin.h @@ -0,0 +1,147 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @author Martin Schanzenbach + * + * @file + * Plugin API for the idp database backend + * + * @defgroup identity-provider-plugin IdP service plugin API + * Plugin API for the idp database backend + * @{ + */ +#ifndef GNUNET_RECLAIM_ATTRIBUTE_PLUGIN_H +#define GNUNET_RECLAIM_ATTRIBUTE_PLUGIN_H + +#include "gnunet_util_lib.h" +#include "gnunet_reclaim_attribute_lib.h" + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + + +/** + * Function called to convert the binary value @a data of an attribute of + * type @a type to a human-readable string. + * + * @param cls closure + * @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 + */ +typedef char * (*GNUNET_RECLAIM_ATTRIBUTE_ValueToStringFunction) (void *cls, + uint32_t type, + const void *data, + size_t data_size); + + +/** + * Function called to convert human-readable version of the value @a s + * of an attribute of type @a type to the respective binary + * representation. + * + * @param cls closure + * @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 + */ +typedef int (*GNUNET_RECLAIM_ATTRIBUTE_StringToValueFunction) (void *cls, + uint32_t type, + const char *s, + void **data, + size_t *data_size); + + +/** + * Function called to convert a type name to the + * corresponding number. + * + * @param cls closure + * @param typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +typedef uint32_t (*GNUNET_RECLAIM_ATTRIBUTE_TypenameToNumberFunction) (void *cls, + const char *typename); + + +/** + * Function called to convert a type number (i.e. 1) to the + * corresponding type string + * + * @param cls closure + * @param type number of a type to convert + * @return corresponding typestring, NULL on error + */ +typedef const char * (*GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction) (void *cls, + uint32_t type); + + +/** + * Each plugin is required to return a pointer to a struct of this + * type as the return value from its entry point. + */ +struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions +{ + + /** + * Closure for all of the callbacks. + */ + void *cls; + + /** + * Conversion to string. + */ + GNUNET_RECLAIM_ATTRIBUTE_ValueToStringFunction value_to_string; + + /** + * Conversion to binary. + */ + GNUNET_RECLAIM_ATTRIBUTE_StringToValueFunction string_to_value; + + /** + * Typename to number. + */ + GNUNET_RECLAIM_ATTRIBUTE_TypenameToNumberFunction typename_to_number; + + /** + * Number to typename. + */ + GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction number_to_typename; + +}; + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ /* end of group */ diff --git a/src/include/gnunet_reclaim_plugin.h b/src/include/gnunet_reclaim_plugin.h new file mode 100644 index 000000000..c400af64c --- /dev/null +++ b/src/include/gnunet_reclaim_plugin.h @@ -0,0 +1,121 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @author Martin Schanzenbach + * + * @file + * Plugin API for the idp database backend + * + * @defgroup reclaim-plugin IdP service plugin API + * Plugin API for the idp database backend + * @{ + */ +#ifndef GNUNET_RECLAIM_PLUGIN_H +#define GNUNET_RECLAIM_PLUGIN_H + +#include "gnunet_util_lib.h" +#include "gnunet_reclaim_service.h" + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + + +/** + * Function called by for each matching ticket. + * + * @param cls closure + * @param ticket the ticket + */ +typedef void (*GNUNET_RECLAIM_TicketIterator) (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs); + + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct GNUNET_RECLAIM_PluginFunctions +{ + + /** + * Closure to pass to all plugin functions. + */ + void *cls; + + /** + * Store a ticket in the database. + * + * @param cls closure (internal context for the plugin) + * @param ticket the ticket to store + * @return #GNUNET_OK on success, else #GNUNET_SYSERR + */ + int (*store_ticket) (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs); + + /** + * Delete a ticket from the database. + * + * @param cls closure (internal context for the plugin) + * @param ticket the ticket to store + * @return #GNUNET_OK on success, else #GNUNET_SYSERR + */ + int (*delete_ticket) (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket); + + + + /** + * Iterate over all tickets + * + * @param cls closure (internal context for the plugin) + * @param identity the identity + * @param audience GNUNET_YES if the identity is the audience of the ticket + * else it is considered the issuer + * @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 + */ + int (*iterate_tickets) (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + int audience, + uint64_t offset, + GNUNET_RECLAIM_TicketIterator iter, void *iter_cls); + + int (*get_ticket_attributes) (void* cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + GNUNET_RECLAIM_TicketIterator iter, + void *iter_cls); +}; + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ /* end of group */ diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h new file mode 100644 index 000000000..7e668cd62 --- /dev/null +++ b/src/include/gnunet_reclaim_service.h @@ -0,0 +1,378 @@ +/* + This file is part of GNUnet. + Copyright (C) 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @author Martin Schanzenbach + * + * @file + * Identity provider service; implements identity provider for GNUnet + * + * @defgroup reclaim Identity Provider service + * @{ + */ +#ifndef GNUNET_RECLAIM_SERVICE_H +#define GNUNET_RECLAIM_SERVICE_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +#include "gnunet_util_lib.h" +#include "gnunet_reclaim_attribute_lib.h" + +/** + * Version number of GNUnet Identity Provider API. + */ +#define GNUNET_RECLAIM_VERSION 0x00000000 + +/** + * Handle to access the identity service. + */ +struct GNUNET_RECLAIM_Handle; + +/** + * Handle for a token. + */ +struct GNUNET_RECLAIM_Token; + +/** + * The ticket + */ +struct GNUNET_RECLAIM_Ticket +{ + /** + * The ticket issuer + */ + struct GNUNET_CRYPTO_EcdsaPublicKey identity; + + /** + * The ticket audience + */ + struct GNUNET_CRYPTO_EcdsaPublicKey audience; + + /** + * The ticket random (NBO) + */ + uint64_t rnd; +}; + +/** + * Handle for an operation with the identity provider service. + */ +struct GNUNET_RECLAIM_Operation; + + +/** + * Connect to the identity provider service. + * + * @param cfg Configuration to contact the identity provider service. + * @return handle to communicate with identity provider service + */ +struct GNUNET_RECLAIM_Handle * +GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); + +/** + * Continuation called to notify client about result of the + * operation. + * + * @param cls closure + * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * #GNUNET_NO if content was already there or not found + * #GNUNET_YES (or other positive value) on success + * @param emsg NULL on success, otherwise an error message + */ +typedef void +(*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls, + int32_t success, + const char *emsg); + + +/** + * 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 + * @param exp_interval the relative expiration interval for the attribute + * @param cont continuation to call when done + * @param cont_cls closure for @a cont + * @return handle to abort the request + */ +struct GNUNET_RECLAIM_Operation * +GNUNET_RECLAIM_attribute_store (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, + const struct GNUNET_TIME_Relative *exp_interval, + GNUNET_RECLAIM_ContinuationWithStatus cont, + void *cont_cls); + + +/** + * Process an attribute that was stored in the idp. + * + * @param cls closure + * @param identity the identity + * @param attr the attribute + */ +typedef void +(*GNUNET_RECLAIM_AttributeResult) (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr); + + + +/** + * List all attributes for a local identity. + * This MUST lock the `struct GNUNET_RECLAIM_Handle` + * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and + * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once + * immediately, and then again after + * #GNUNET_RECLAIM_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_RECLAIM_AttributeIterator * +GNUNET_RECLAIM_get_attributes_start (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_AttributeResult proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls); + + +/** + * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it); + + +/** + * 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_RECLAIM_disconnect. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it); + + +/** + * Method called when a token has been issued. + * On success returns a ticket that can be given to the audience to retrive the + * token + * + * @param cls closure + * @param ticket the ticket + */ +typedef void +(*GNUNET_RECLAIM_TicketCallback)(void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket); + +/** + * Issues a ticket to another identity. The identity may use + * GNUNET_RECLAIM_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_RECLAIM_Operation * +GNUNET_RECLAIM_ticket_issue (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, + const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + GNUNET_RECLAIM_TicketCallback cb, + void *cb_cls); + +/** + * 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_RECLAIM_Operation * +GNUNET_RECLAIM_ticket_revoke (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + const struct GNUNET_RECLAIM_Ticket *ticket, + GNUNET_RECLAIM_ContinuationWithStatus cb, + void *cb_cls); + + + +/** + * 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 audience) + * @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_RECLAIM_Operation * +GNUNET_RECLAIM_ticket_consume (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + const struct GNUNET_RECLAIM_Ticket *ticket, + GNUNET_RECLAIM_AttributeResult cb, + void *cb_cls); + +/** + * Lists all tickets that have been issued to remote + * identites (relying parties) + * + * @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 + */ +struct GNUNET_RECLAIM_TicketIterator * +GNUNET_RECLAIM_ticket_iteration_start (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_TicketCallback proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls); + +/** + * Lists all tickets that have been issued to remote + * identites (relying parties) + * + * @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 + */ +struct GNUNET_RECLAIM_TicketIterator * +GNUNET_RECLAIM_ticket_iteration_start_rp (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_TicketCallback proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls); + +/** + * Calls the record processor specified in #GNUNET_RECLAIM_ticket_iteration_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it); + +/** + * 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_RECLAIM_disconnect. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it); + +/** + * Disconnect from identity provider service. + * + * @param h identity provider service to disconnect + */ +void +GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h); + + +/** + * Cancel an identity provider 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 + * the operation. + * + * @param op operation to cancel + */ +void +GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op); + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + + +/* ifndef GNUNET_RECLAIM_SERVICE_H */ +#endif + +/** @} */ /* end of group identity */ + +/* end of gnunet_reclaim_service.h */ diff --git a/src/reclaim-attribute/Makefile.am b/src/reclaim-attribute/Makefile.am new file mode 100644 index 000000000..7db2925b1 --- /dev/null +++ b/src/reclaim-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 = \ + libgnunetreclaimattribute.la + +libgnunetreclaimattribute_la_SOURCES = \ + reclaim_attribute.c +libgnunetreclaimattribute_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +libgnunetreclaimattribute_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + + +plugin_LTLIBRARIES = \ + libgnunet_plugin_reclaim_attribute_gnuid.la + + +libgnunet_plugin_reclaim_attribute_gnuid_la_SOURCES = \ + plugin_reclaim_attribute_gnuid.c +libgnunet_plugin_reclaim_attribute_gnuid_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) +libgnunet_plugin_reclaim_attribute_gnuid_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + + diff --git a/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c new file mode 100644 index 000000000..48afc0732 --- /dev/null +++ b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c @@ -0,0 +1,182 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file reclaim-attribute/plugin_reclaim_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_reclaim_attribute_plugin.h" +#include + + +/** + * 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_RECLAIM_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_RECLAIM_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_RECLAIM_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_reclaim_attribute_gnuid_init (void *cls) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api; + + api = GNUNET_new (struct GNUNET_RECLAIM_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_reclaim_attribute_gnuid_done (void *cls) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; +} + +/* end of plugin_reclaim_attribute_type_gnuid.c */ diff --git a/src/reclaim-attribute/reclaim_attribute.c b/src/reclaim-attribute/reclaim_attribute.c new file mode 100644 index 000000000..74d668ea8 --- /dev/null +++ b/src/reclaim-attribute/reclaim_attribute.c @@ -0,0 +1,444 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ + +/** + * @file reclaim-attribute/reclaim_attribute.c + * @brief helper library to manage identity attributes + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "reclaim_attribute.h" +#include "gnunet_reclaim_attribute_plugin.h" + +/** + * Handle for a plugin + */ +struct Plugin +{ + /** + * Name of the plugin + */ + char *library_name; + + /** + * Plugin API + */ + struct GNUNET_RECLAIM_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_RECLAIM_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_reclaim_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_RECLAIM_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_RECLAIM_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_RECLAIM_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_RECLAIM_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_RECLAIM_ATTRIBUTE_Claim * +GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char* attr_name, + uint32_t type, + const void* data, + size_t data_size) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr; + char *write_ptr; + + attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_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; +} + +/** + * Add a new claim list entry. + * + * @param claim_list the attribute name + * @param attr_name the attribute name + * @param type the attribute type + * @param data the attribute value + * @param data_size the attribute value size + * @return + */ +void +GNUNET_RECLAIM_ATTRIBUTE_list_add (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list, + const char* attr_name, + uint32_t type, + const void* data, + size_t data_size) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); + le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, + type, + data, + data_size); + GNUNET_CONTAINER_DLL_insert (claim_list->list_head, + claim_list->list_tail, + le); +} + +size_t +GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + size_t len = 0; + for (le = attrs->list_head; NULL != le; le = le->next) + len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim); + return len; +} + +size_t +GNUNET_RECLAIM_ATTRIBUTE_list_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + char *result) +{ + struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_serialize (le->claim, + write_ptr); + total_len += len; + write_ptr += len; + } + return total_len; +} + +struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * +GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char* data, + size_t data_size) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + size_t attr_len; + const char* read_ptr; + + if (data_size < sizeof (struct Attribute)) + return NULL; + + attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + read_ptr = data; + while (((data + data_size) - read_ptr) >= sizeof (struct Attribute)) + { + + le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); + le->claim = GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim); + read_ptr += attr_len; + } + return attrs; +} + +struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList* +GNUNET_RECLAIM_ATTRIBUTE_list_dup (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result; + + result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + for (le = attrs->list_head; NULL != le; le = le->next) + { + result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); + result_le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name, + le->claim->type, + le->claim->data, + le->claim->data_size); + GNUNET_CONTAINER_DLL_insert (result->list_head, + result->list_tail, + result_le); + } + return result; +} + + +void +GNUNET_RECLAIM_ATTRIBUTE_list_destroy (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) +{ + return sizeof (struct Attribute) + + strlen (attr->name) + + attr->data_size; +} + +size_t +GNUNET_RECLAIM_ATTRIBUTE_serialize (const struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_Claim * +GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char* data, + size_t data_size) +{ + struct GNUNET_RECLAIM_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_RECLAIM_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 reclaim_attribute.c */ diff --git a/src/reclaim-attribute/reclaim_attribute.h b/src/reclaim-attribute/reclaim_attribute.h new file mode 100644 index 000000000..746d32980 --- /dev/null +++ b/src/reclaim-attribute/reclaim_attribute.h @@ -0,0 +1,54 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @file reclaim-attribute/reclaim_attribute.h + * @brief GNUnet reclaim identity attributes + * + */ +#ifndef RECLAIM_ATTRIBUTE_H +#define RECLAIM_ATTRIBUTE_H + +#include "gnunet_reclaim_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/reclaim/.gitignore b/src/reclaim/.gitignore new file mode 100644 index 000000000..ef77fccdc --- /dev/null +++ b/src/reclaim/.gitignore @@ -0,0 +1,2 @@ +gnunet-service-identity-provider +gnunet-identity-token diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am new file mode 100644 index 000000000..c13c68763 --- /dev/null +++ b/src/reclaim/Makefile.am @@ -0,0 +1,140 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include + + plugindir = $(libdir)/gnunet + +if MINGW + WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +endif + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +if HAVE_SQLITE +SQLITE_PLUGIN = libgnunet_plugin_reclaim_sqlite.la +endif + +EXTRA_DIST = \ + test_reclaim_defaults.conf \ + test_reclaim.conf \ + $(check_SCRIPTS) + +pkgcfgdir= $(pkgdatadir)/config.d/ + +libexecdir= $(pkglibdir)/libexec/ + +pkgcfg_DATA = \ + reclaim.conf + +lib_LTLIBRARIES = \ + libgnunetidentityprovider.la +plugin_LTLIBRARIES = \ + libgnunet_plugin_rest_reclaim.la \ + libgnunet_plugin_rest_openid_connect.la \ + libgnunet_plugin_gnsrecord_reclaim.la \ + $(SQLITE_PLUGIN) + +bin_PROGRAMS = \ + gnunet-reclaim + +libexec_PROGRAMS = \ + gnunet-service-reclaim + +libgnunet_plugin_gnsrecord_reclaim_la_SOURCES = \ + plugin_gnsrecord_reclaim.c +libgnunet_plugin_gnsrecord_reclaim_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) +libgnunet_plugin_gnsrecord_reclaim_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + +libgnunet_plugin_reclaim_sqlite_la_SOURCES = \ + plugin_reclaim_sqlite.c +libgnunet_plugin_reclaim_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_reclaim_sqlite_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + + + +gnunet_service_reclaim_SOURCES = \ + gnunet-service-reclaim.c +gnunet_service_reclaim_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/reclaim-attribute/libgnunetreclaimattribute.la \ + libgnunetidentityprovider.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(GN_LIBINTL) + +libgnunetidentityprovider_la_SOURCES = \ + reclaim_api.c \ + reclaim.h +libgnunetidentityprovider_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) $(XLIB) +libgnunetidentityprovider_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + +libgnunet_plugin_rest_reclaim_la_SOURCES = \ + plugin_rest_reclaim.c \ + jwt.c +libgnunet_plugin_rest_reclaim_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/reclaim-attribute/libgnunetreclaimattribute.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ + $(LTLIBINTL) -ljansson -lmicrohttpd +libgnunet_plugin_rest_reclaim_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + +libgnunet_plugin_rest_openid_connect_la_SOURCES = \ + plugin_rest_openid_connect.c \ + jwt.c +libgnunet_plugin_rest_openid_connect_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/reclaim-attribute/libgnunetreclaimattribute.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ + $(LTLIBINTL) -ljansson -lmicrohttpd +libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + +gnunet_reclaim_SOURCES = \ + gnunet-reclaim.c +gnunet_reclaim_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetidentityprovider.la \ + $(top_builddir)/src/identity/libgnunetidentity.la \ + $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \ + $(GN_LIBINTL) + +check_SCRIPTS = \ + test_reclaim_attribute.sh \ + test_reclaim_issue.sh \ + test_reclaim_consume.sh \ + test_reclaim_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/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c new file mode 100644 index 000000000..9947eac6d --- /dev/null +++ b/src/reclaim/gnunet-reclaim.c @@ -0,0 +1,517 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @file src/reclaim/gnunet-reclaim.c + * @brief Identity Provider utility + * + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_namestore_service.h" +#include "gnunet_reclaim_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; + +/** + * reclaim handle + */ +static struct GNUNET_RECLAIM_Handle *reclaim_handle; + +/** + * reclaim operation + */ +static struct GNUNET_RECLAIM_Operation *reclaim_op; + +/** + * Attribute iterator + */ +static struct GNUNET_RECLAIM_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_RECLAIM_Ticket ticket; + +/** + * Attribute list + */ +static struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list; + +/** + * Attribute expiration interval + */ +static struct GNUNET_TIME_Relative exp_interval; + +/** + * Timeout task + */ +static struct GNUNET_SCHEDULER_Task *timeout; + +static void +do_cleanup(void *cls) +{ + if (NULL != timeout) + GNUNET_SCHEDULER_cancel (timeout); + if (NULL != reclaim_op) + GNUNET_RECLAIM_cancel (reclaim_op); + if (NULL != attr_iterator) + GNUNET_RECLAIM_get_attributes_stop (attr_iterator); + if (NULL != reclaim_handle) + GNUNET_RECLAIM_disconnect (reclaim_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_RECLAIM_Ticket *ticket) +{ + char* ticket_str; + reclaim_op = NULL; + if (NULL != ticket) { + ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, + sizeof (struct GNUNET_RECLAIM_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) +{ + reclaim_op = NULL; + 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_RECLAIM_ATTRIBUTE_Claim *attr) +{ + char *value_str; + if (NULL == identity) + { + reclaim_op = NULL; + GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); + return; + } + if (NULL == attr) + { + ret = 1; + return; + } + value_str = GNUNET_RECLAIM_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 +timeout_task (void *cls) +{ + timeout = NULL; + ret = 1; + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Timeout\n"); + GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); +} + +static void +process_rvk (void *cls, int success, const char* msg) +{ + reclaim_op = NULL; + 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_RECLAIM_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) + { + reclaim_op = GNUNET_RECLAIM_ticket_issue (reclaim_handle, + pkey, + &rp_key, + attr_list, + &ticket_issue_cb, + NULL); + return; + } + if (consume_ticket) + { + reclaim_op = GNUNET_RECLAIM_ticket_consume (reclaim_handle, + pkey, + &ticket, + &process_attrs, + NULL); + timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10), + &timeout_task, + NULL); + return; + } + if (revoke_ticket) + { + reclaim_op = GNUNET_RECLAIM_ticket_revoke (reclaim_handle, + pkey, + &ticket, + &process_rvk, + NULL); + return; + } + if (attr_name) + { + if (NULL == type_str) + type = GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING; + else + type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str); + + GNUNET_assert (GNUNET_SYSERR != GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type, + attr_value, + (void**)&data, + &data_size)); + claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, + type, + data, + data_size); + reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle, + pkey, + claim, + &exp_interval, + &store_attr_cont, + NULL); + return; + } + GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); +} + +static void +iter_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) +{ + struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_ClaimListEntry); + le->claim = GNUNET_RECLAIM_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_RECLAIM_get_attributes_next (attr_iterator); +} + +static void +ego_iter_finished (void *cls) +{ + if (NULL == pkey) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Ego %s not found\n", ego_name); + return; + } + + 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_RECLAIM_Ticket)); + if (NULL != revoke_ticket) + GNUNET_STRINGS_string_to_data (revoke_ticket, + strlen (revoke_ticket), + &ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + + + attr_list = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + + attr_iterator = GNUNET_RECLAIM_get_attributes_start (reclaim_handle, + pkey, + &iter_error, + NULL, + &iter_cb, + NULL, + &iter_finished, + NULL); + + +} + +static int init = GNUNET_YES; + +static void +ego_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + if (NULL == name) { + if (GNUNET_YES == init) { + init = GNUNET_NO; + GNUNET_SCHEDULER_add_now (&ego_iter_finished, NULL); + } + return; + } + if (0 != strcmp (name, ego_name)) + return; + pkey = GNUNET_IDENTITY_ego_get_private_key (ego); +} + + +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + ret = 0; + if (NULL == ego_name) + { + ret = 1; + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Ego is required\n")); + return; + } + + if ( (NULL == attr_value) && (NULL != attr_name) ) + { + ret = 1; + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Attribute value missing!\n")); + return; + } + + if ( (NULL == rp) && (NULL != issue_attrs) ) + { + ret = 1; + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Requesting party key is required!\n")); + return; + } + + reclaim_handle = GNUNET_RECLAIM_connect (c); + //Get Ego + identity_handle = GNUNET_IDENTITY_connect (c, + &ego_cb, + NULL); + + +} + + +int +main(int argc, char *const argv[]) +{ + exp_interval = GNUNET_TIME_UNIT_HOURS; + 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_relative_time ('E', + "expiration", + NULL, + gettext_noop ("Expiration interval of the attribute"), + &exp_interval), + + GNUNET_GETOPT_OPTION_END + }; + if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct", + "ct", options, + &run, NULL)) + return 1; + else + return ret; +} diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c new file mode 100644 index 000000000..bf8780a92 --- /dev/null +++ b/src/reclaim/gnunet-service-reclaim.c @@ -0,0 +1,2786 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @file src/reclaim/gnunet-service-reclaim.c + * @brief reclaim Service + * + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_protocols.h" +#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_reclaim_plugin.h" +#include "gnunet_reclaim_attribute_lib.h" +#include "gnunet_signatures.h" +#include "reclaim.h" + +/** + * First pass state + */ +#define STATE_INIT 0 + +/** + * Normal operation state + */ +#define STATE_POST_INIT 1 + +/** + * Minimum interval between updates + */ +#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES + +/** + * Standard token expiration time + */ +#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS + +/** + * Identity handle + */ +static struct GNUNET_IDENTITY_Handle *identity_handle; + +/** + * Database handle + */ +static struct GNUNET_RECLAIM_PluginFunctions *TKT_database; + +/** + * Name of DB plugin + */ +static char *db_lib_name; + +/** + * Token expiration interval + */ +static struct GNUNET_TIME_Relative token_expiration_interval; + +/** + * Namestore handle + */ +static struct GNUNET_NAMESTORE_Handle *ns_handle; + +/** + * GNS handle + */ +static struct GNUNET_GNS_Handle *gns_handle; + +/** + * Credential handle + */ +static struct GNUNET_CREDENTIAL_Handle *credential_handle; + +/** + * Namestore qe + */ +static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; + +/** + * Namestore iterator + */ +static struct GNUNET_NAMESTORE_ZoneIterator *ns_it; + +/** + * Timeout task + */ +static struct GNUNET_SCHEDULER_Task *timeout_task; + +/** + * Update task + */ +static struct GNUNET_SCHEDULER_Task *update_task; + + +/** + * Currently processed token + */ +static struct IdentityToken *token; + +/** + * Label for currently processed token + */ +static char* label; + +/** + * Scopes for processed token + */ +static char* scopes; + +/** + * Handle to the statistics service. + */ +static struct GNUNET_STATISTICS_Handle *stats; + +/** + * Our configuration. + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * An idp client + */ +struct IdpClient; + +/** + * A ticket iteration operation. + */ +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; + + /** + * 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; + + /** + * 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; + + /** + * 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 *attr_iter_head; + + /** + * Tail of the DLL of + * Attribute iteration operations + * in progress initiated by this client + */ + struct AttributeIterator *attr_iter_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 *revoke_op_head; + + /** + * Tail of DLL of ticket revocation ops + */ + struct TicketRevocationHandle *revoke_op_tail; + + /** + * Head of DLL of ticket issue ops + */ + struct TicketIssueHandle *issue_op_head; + + /** + * Tail of DLL of ticket issue ops + */ + struct TicketIssueHandle *issue_op_tail; + + /** + * Head of DLL of ticket consume ops + */ + struct ConsumeTicketHandle *consume_op_head; + + /** + * Tail of DLL of ticket consume ops + */ + struct ConsumeTicketHandle *consume_op_tail; + + /** + * Head of DLL of attribute store ops + */ + struct AttributeStoreHandle *store_op_head; + + /** + * Tail of DLL of attribute store ops + */ + struct AttributeStoreHandle *store_op_tail; + +}; + +struct AttributeStoreHandle +{ + /** + * DLL + */ + struct AttributeStoreHandle *next; + + /** + * DLL + */ + struct AttributeStoreHandle *prev; + + /** + * 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_RECLAIM_ATTRIBUTE_Claim *claim; + + /** + * The attribute expiration interval + */ + struct GNUNET_TIME_Relative exp; + + /** + * request id + */ + uint32_t r_id; +}; + + +/* Prototype */ +struct ParallelLookup; + +struct ConsumeTicketHandle +{ + /** + * DLL + */ + struct ConsumeTicketHandle *next; + + /** + * DLL + */ + struct ConsumeTicketHandle *prev; + + /** + * Client connection + */ + struct IdpClient *client; + + /** + * Ticket + */ + struct GNUNET_RECLAIM_Ticket ticket; + + /** + * LookupRequest + */ + struct GNUNET_GNS_LookupRequest *lookup_request; + + /** + * Audience Key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * Audience Key + */ + 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_RECLAIM_ATTRIBUTE_ClaimList *attrs; + + /** + * Lookup time + */ + struct GNUNET_TIME_Absolute lookup_start_time; + + /** + * request id + */ + uint32_t r_id; +}; + +/** + * 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 *prev; + + /** + * DLL + */ + struct TicketRevocationHandle *next; + + /** + * Client connection + */ + struct IdpClient *client; + + /** + * Attributes to reissue + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs; + + /** + * Attributes to revoke + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *rvk_attrs; + + /** + * Issuer Key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * Ticket to issue + */ + struct GNUNET_RECLAIM_Ticket ticket; + + /** + * QueueEntry + */ + struct GNUNET_NAMESTORE_QueueEntry *ns_qe; + + /** + * Namestore iterator + */ + struct GNUNET_NAMESTORE_ZoneIterator *ns_it; + + /** + * The ABE master key + */ + struct GNUNET_ABE_AbeMasterKey *abe_key; + + /** + * Offset + */ + uint32_t offset; + + /** + * request id + */ + uint32_t r_id; +}; + + + +/** + * Ticket issue request handle + */ +struct TicketIssueHandle +{ + /** + * DLL + */ + struct TicketIssueHandle *prev; + + /** + * DLL + */ + struct TicketIssueHandle *next; + + /** + * Client connection + */ + struct IdpClient *client; + + /** + * Attributes to issue + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs; + + /** + * Issuer Key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * Ticket to issue + */ + struct GNUNET_RECLAIM_Ticket ticket; + + /** + * QueueEntry + */ + struct GNUNET_NAMESTORE_QueueEntry *ns_qe; + + /** + * request id + */ + uint32_t r_id; +}; + + +/** + * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format + * + */ +struct EgoEntry +{ + /** + * DLL + */ + struct EgoEntry *next; + + /** + * DLL + */ + struct EgoEntry *prev; + + /** + * Ego handle + */ + struct GNUNET_IDENTITY_Ego *ego; + + /** + * Attribute map. Contains the attributes as json_t + */ + struct GNUNET_CONTAINER_MultiHashMap *attr_map; + +}; + +/** + * 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); + GNUNET_free_non_null (token); + GNUNET_free_non_null (label); + +} + +/** + * Shutdown task + * + * @param cls NULL + */ +static void +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) +{ + struct AbeBootstrapHandle *abh = cls; + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to bootstrap ABE master %s\n", + emsg); + abh->proc (abh->proc_cls, NULL); + GNUNET_free (abh->abe_key); + GNUNET_free (abh); + return; + } + abh->proc (abh->proc_cls, abh->abe_key); + GNUNET_free (abh); +} + +/** + * Generates and stores a new ABE key + */ +static void +bootstrap_store_task (void *cls) +{ + 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); +} + +/** + * Error checking for ABE master + */ +static void +bootstrap_abe_error (void *cls) +{ + struct AbeBootstrapHandle *abh = cls; + abh->proc (abh->proc_cls, NULL); + GNUNET_free (abh); +} + + +/** + * Handle ABE lookup in namestore + */ +static void +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;iproc (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); +} + +/** + * 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 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) + { + 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); + } +} + + + +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; +} + +/** + * Cleanup ticket consume handle + * @param handle the handle to clean up + */ +static void +cleanup_ticket_issue_handle (struct TicketIssueHandle *handle) +{ + if (NULL != handle->attrs) + GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs); + if (NULL != handle->ns_qe) + GNUNET_NAMESTORE_cancel (handle->ns_qe); + GNUNET_free (handle); +} + + +static void +send_ticket_result (struct IdpClient *client, + uint32_t r_id, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct TicketResultMessage *irm; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_RECLAIM_Ticket *ticket_buf; + + /* 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_RECLAIM_Ticket), + GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT); + ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1]; + *ticket_buf = *ticket; + irm->id = htonl (r_id); + GNUNET_MQ_send (client->mq, + env); +} + +static void +store_ticket_issue_cont (void *cls, + int32_t success, + const char *emsg) +{ + struct TicketIssueHandle *handle = cls; + + handle->ns_qe = NULL; + GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head, + handle->client->issue_op_tail, + handle); + if (GNUNET_SYSERR == success) + { + 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); +} + + + +int +serialize_abe_keyinfo2 (const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_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_RECLAIM_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; + } + 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; + } + 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_RECLAIM_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++; + } + 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_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +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_RECLAIM_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); + GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, + idp->issue_op_tail, + ih); + bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO); + GNUNET_SERVICE_client_continue (idp->client); + +} + +/********************************************************** + * Revocation + **********************************************************/ + +/** + * Cleanup revoke handle + * + * @param rh the ticket revocation handle + */ +static void +cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh) +{ + if (NULL != rh->attrs) + GNUNET_RECLAIM_ATTRIBUTE_list_destroy (rh->attrs); + if (NULL != rh->rvk_attrs) + GNUNET_RECLAIM_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 +send_revocation_finished (struct TicketRevocationHandle *rh, + uint32_t success) +{ + struct GNUNET_MQ_Envelope *env; + struct RevokeTicketResultMessage *trm; + + GNUNET_break(TKT_database->delete_ticket (TKT_database->cls, + &rh->ticket)); + + env = GNUNET_MQ_msg (trm, + GNUNET_MESSAGE_TYPE_RECLAIM_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->revoke_op_head, + rh->client->revoke_op_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_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs); + +static void +revocation_reissue_tickets (struct TicketRevocationHandle *rh); + + +static void reissue_next (void *cls) +{ + struct TicketRevocationHandle *rh = cls; + revocation_reissue_tickets (rh); +} + + +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 + * + * @param cls struct TicketIterationProcResult + * @param ticket the ticket + * @param attrs the attributes + */ +static void +ticket_reissue_proc (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct TicketRevocationHandle *rh = cls; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + struct GNUNET_RECLAIM_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_log (GNUNET_ERROR_TYPE_DEBUG, + "Iteration done\n"); + return; + } + + if (0 == memcmp (&ticket->audience, + &rh->ticket.audience, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Do not reissue for this identity.!\n"); + label = GNUNET_STRINGS_data_to_string_alloc (&rh->ticket.rnd, + sizeof (uint64_t)); + //Delete record + rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, + &rh->identity, + label, + 0, + NULL, + &reissue_ticket_cont, + rh); + + GNUNET_free (label); + return; + } + + /* + * 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) + { + for (le_rollover = rh->rvk_attrs->list_head; + NULL != le_rollover; + le_rollover = le_rollover->next) + { + if (0 == strcmp (le_rollover->claim->name, + le->claim->name)) + { + reissue_ticket = GNUNET_YES; + le->claim->version = le_rollover->claim->version; + } + } + } + + if (GNUNET_NO == reissue_ticket) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Skipping ticket.\n"); + + rh->offset++; + GNUNET_SCHEDULER_add_now (&reissue_next, rh); + + + return; + } + + //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++; + } + 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))) + { + GNUNET_break (0); + } + if (GNUNET_NO == ret) + { + send_revocation_finished (rh, GNUNET_OK); + cleanup_revoke_ticket_handle (rh); + return; + } +} + +/** + * Failed to check for attribute + */ +static void +check_attr_error (void *cls) +{ + struct TicketRevocationHandle *rh = cls; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to check for existing attribute\n"); + rh->ns_qe = NULL; + send_revocation_finished (rh, GNUNET_SYSERR); + cleanup_revoke_ticket_handle (rh); +} + + +/** + * Revoke next attribte by reencryption with + * new ABE master + */ +static void +reenc_next_attribute (void *cls); + +/** + * Check for existing attribute and overwrite + */ +static void +check_attr_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd_old) +{ + struct TicketRevocationHandle *rh = cls; + 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; + + rh->ns_qe = NULL; + if (1 != rd_count) { + GNUNET_SCHEDULER_add_now (&reenc_next_attribute, + rh); + return; + } + + buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim); + buf = GNUNET_malloc (buf_size); + GNUNET_RECLAIM_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); + if (GNUNET_SYSERR == enc_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to re-encrypt with policy %s\n", + policy); + GNUNET_free (policy); + send_revocation_finished (rh, GNUNET_SYSERR); + cleanup_revoke_ticket_handle (rh); + return; + } + 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 = rd_old[0].expiration_time; + 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); +} + + +/** + * Revoke next attribte by reencryption with + * new ABE master + */ +static void +reenc_next_attribute (void *cls) +{ + struct TicketRevocationHandle *rh = cls; + if (NULL == rh->attrs->list_head) + { + revocation_reissue_tickets (rh); + return; + } + /* First check if attribute still exists */ + rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, + &rh->identity, + rh->attrs->list_head->claim->name, + &check_attr_error, + rh, + &check_attr_cb, + rh); +} + + +/** + * Namestore callback after revoked attribute + * is stored + */ +static void +attr_reenc_cont (void *cls, + int32_t success, + const char *emsg) +{ + struct TicketRevocationHandle *rh = cls; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + + rh->ns_qe = NULL; + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to reencrypt attribute %s\n", + emsg); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + return; + } + 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); +} + + +static void +process_attributes_to_update (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct TicketRevocationHandle *rh = cls; + + rh->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Revocation Phase I: Collecting attributes\n"); + /* Reencrypt all attributes with new key */ + if (NULL == rh->attrs->list_head) + { + /* 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); + } + +} + + + +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; +} + +static void +handle_revoke_ticket_message (void *cls, + const struct RevokeTicketMessage *rm) +{ + struct TicketRevocationHandle *rh; + struct IdpClient *idp = cls; + struct GNUNET_RECLAIM_Ticket *ticket; + + rh = GNUNET_new (struct TicketRevocationHandle); + ticket = (struct GNUNET_RECLAIM_Ticket*)&rm[1]; + rh->rvk_attrs = GNUNET_new (struct GNUNET_RECLAIM_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->revoke_op_head, + idp->revoke_op_tail, + rh); + bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO); + GNUNET_SERVICE_client_continue (idp->client); + +} + +/** + * Cleanup ticket consume handle + * @param handle the handle to clean up + */ +static void +cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle) +{ + struct ParallelLookup *lu; + struct ParallelLookup *tmp; + if (NULL != handle->lookup_request) + GNUNET_GNS_lookup_cancel (handle->lookup_request); + 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; + } + + if (NULL != handle->key) + GNUNET_ABE_cpabe_delete_key (handle->key, + GNUNET_YES); + if (NULL != handle->attrs) + GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs); + GNUNET_free (handle); +} + + + +static int +check_consume_ticket_message(void *cls, + const struct ConsumeTicketMessage *cm) +{ + uint16_t size; + + size = ntohs (cm->header.size); + if (size <= sizeof (struct ConsumeTicketMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +static void +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_RECLAIM_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, + "attribute_lookup_time_total", + GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us, + GNUNET_YES); + GNUNET_STATISTICS_update (stats, + "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, + "abe_decrypt_time_total", + GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us, + GNUNET_YES); + GNUNET_STATISTICS_update (stats, + "abe_decrypt_count", + 1, + GNUNET_YES); + + attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); + attr_le->claim = GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_list_serialize_get_size (handle->attrs); + env = GNUNET_MQ_msg_extra (crm, + attrs_len, + GNUNET_MESSAGE_TYPE_RECLAIM_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_RECLAIM_ATTRIBUTE_list_serialize (handle->attrs, + data_tmp); + GNUNET_MQ_send (handle->client->mq, env); + GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head, + handle->client->consume_op_tail, + handle); + cleanup_consume_ticket_handle (handle); +} + +void +abort_parallel_lookups2 (void *cls) +{ + struct ConsumeTicketHandle *handle = cls; + struct ParallelLookup *lu; + struct ParallelLookup *tmp; + struct AttributeResultMessage *arm; + struct GNUNET_MQ_Envelope *env; + + handle->kill_task = NULL; + 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_RECLAIM_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; + + handle->lookup_request = NULL; + if (1 != rd_count) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Number of keys %d != 1.", + rd_count); + cleanup_consume_ticket_handle (handle); + GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head, + handle->client->consume_op_tail, + handle); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + return; + } + + //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, + "abe_key_lookup_time_total", + GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us, + GNUNET_YES); + GNUNET_STATISTICS_update (stats, + "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_DEBUG, + "Looking up %s\n", scope); + 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, + scope, + &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 (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* 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_RECLAIM_ATTRIBUTE_ClaimList); + GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity, + &ch->identity_pub); + ch->ticket = *((struct GNUNET_RECLAIM_Ticket*)&cm[1]); + rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd, + sizeof (uint64_t)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looking for ABE key under %s\n", rnd_label); + ch->lookup_start_time = GNUNET_TIME_absolute_get (); + ch->lookup_request + = GNUNET_GNS_lookup (gns_handle, + rnd_label, + &ch->ticket.identity, + GNUNET_GNSRECORD_TYPE_ABE_KEY, + GNUNET_GNS_LO_DEFAULT, + &process_consume_abe_key, + ch); + GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, + idp->consume_op_tail, + ch); + GNUNET_free (rnd_label); + GNUNET_SERVICE_client_continue (idp->client); +} + +/** + * Cleanup attribute store handle + * + * @param handle handle to clean up + */ +static void +cleanup_as_handle (struct AttributeStoreHandle *handle) +{ + if (NULL != handle->ns_qe) + GNUNET_NAMESTORE_cancel (handle->ns_qe); + 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; + + as_handle->ns_qe = NULL; + GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, + as_handle->client->store_op_tail, + as_handle); + + if (GNUNET_SYSERR == success) + { + 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; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending ATTRIBUTE_STORE_RESPONSE message\n"); + env = GNUNET_MQ_msg (acr_msg, + GNUNET_MESSAGE_TYPE_RECLAIM_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_as_handle (as_handle); +} + +static void +attr_store_task (void *cls) +{ + 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_RECLAIM_ATTRIBUTE_serialize_get_size (as_handle->claim); + buf = GNUNET_malloc (buf_size); + + GNUNET_RECLAIM_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); + if (GNUNET_SYSERR == enc_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to encrypt with policy %s\n", + policy); + GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, + as_handle->client->store_op_tail, + as_handle); + + cleanup_as_handle (as_handle); + GNUNET_free (buf); + GNUNET_free (policy); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + return; + } + 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 = as_handle->exp.rel_value_us; + 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 +store_after_abe_bootstrap (void *cls, + struct GNUNET_ABE_AbeMasterKey *abe_key) +{ + 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); +} + +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 +handle_attribute_store_message (void *cls, + const struct AttributeStoreMessage *sam) +{ + 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_RECLAIM_ATTRIBUTE_deserialize ((char*)&sam[1], + data_len); + + as_handle->r_id = ntohl (sam->id); + as_handle->identity = sam->identity; + as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp); + GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, + &as_handle->identity_pkey); + + GNUNET_SERVICE_client_continue (idp->client); + as_handle->client = idp; + GNUNET_CONTAINER_DLL_insert (idp->store_op_head, + idp->store_op_tail, + as_handle); + bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO); +} + +static void +cleanup_attribute_iter_handle (struct AttributeIterator *ai) +{ + if (NULL != ai->abe_key) + GNUNET_ABE_cpabe_delete_master_key (ai->abe_key); + 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"); + GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head, + ai->client->attr_iter_tail, + ai); + cleanup_attribute_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_RECLAIM_ATTRIBUTE_RESULT); + arm->id = htonl (ai->request_id); + arm->attr_len = htons (0); + GNUNET_MQ_send (ai->client->mq, env); + GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head, + ai->client->attr_iter_tail, + ai); + cleanup_attribute_iter_handle (ai); +} + +static void +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 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 (ai->ns_it, + 1); + return; + } + + if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) + { + GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, + 1); + 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); + if (GNUNET_SYSERR == msg_extra_len) + { + GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, + 1); + return; + } + + 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_RECLAIM_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; +} + + +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); +} + + +static 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, + 1); +} + + + +static void +handle_iteration_start (void *cls, + const struct AttributeIterationStartMessage *ais_msg) +{ + 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->attr_iter_head, + idp->attr_iter_tail, + ai); + bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO); + GNUNET_SERVICE_client_continue (idp->client); +} + + +static void +handle_iteration_stop (void *cls, + const struct AttributeIterationStopMessage *ais_msg) +{ + struct IdpClient *idp = cls; + struct AttributeIterator *ai; + uint32_t rid; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' message\n", + "ATTRIBUTE_ITERATION_STOP"); + rid = ntohl (ais_msg->id); + for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next) + if (ai->request_id == rid) + break; + if (NULL == ai) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (idp->client); + return; + } + GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, + idp->attr_iter_tail, + ai); + GNUNET_free (ai); + GNUNET_SERVICE_client_continue (idp->client); +} + + +static void +handle_iteration_next (void *cls, + const struct AttributeIterationNextMessage *ais_msg) +{ + struct IdpClient *idp = cls; + struct AttributeIterator *ai; + uint32_t rid; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received ATTRIBUTE_ITERATION_NEXT message\n"); + rid = ntohl (ais_msg->id); + for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next) + if (ai->request_id == rid) + break; + if (NULL == ai) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (idp->client); + return; + } + bootstrap_abe (&ai->identity, + &iterate_next_after_abe_bootstrap, + ai, + GNUNET_NO); + GNUNET_SERVICE_client_continue (idp->client); +} + +/** + * Ticket iteration processor result + */ +enum ZoneIterationResult +{ + /** + * Iteration start. + */ + IT_START = 0, + + /** + * Found tickets, + * Continue to iterate with next iteration_next call + */ + IT_SUCCESS_MORE_AVAILABLE = 1, + + /** + * Iteration complete + */ + IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2 +}; + + +/** + * Context for ticket iteration + */ +struct TicketIterationProcResult +{ + /** + * 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 +cleanup_ticket_iter_handle (struct TicketIteration *ti) +{ + GNUNET_free (ti); +} + +/** + * Process ticket from database + * + * @param cls struct TicketIterationProcResult + * @param ticket the ticket + * @param attrs the attributes + */ +static void +ticket_iterate_proc (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs) +{ + struct TicketIterationProcResult *proc = cls; + + if (NULL == ticket) + { + 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); + +} + +/** + * 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; + + memset (&proc, 0, sizeof (proc)); + proc.ti = ti; + proc.res_iteration_finished = IT_START; + while (IT_START == proc.res_iteration_finished) + { + if (GNUNET_SYSERR == + (ret = TKT_database->iterate_tickets (TKT_database->cls, + &ti->identity, + ti->is_audience, + ti->offset, + &ticket_iterate_proc, + &proc))) + { + GNUNET_break (0); + break; + } + if (GNUNET_NO == ret) + proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; + ti->offset++; + } + if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "More results available\n"); + return; /* more later */ + } + /* send empty response to indicate end of list */ + env = GNUNET_MQ_msg (trm, + GNUNET_MESSAGE_TYPE_RECLAIM_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); +} + +static void +handle_ticket_iteration_start (void *cls, + const struct TicketIterationStartMessage *tis_msg) +{ + struct IdpClient *client = cls; + struct TicketIteration *ti; + + 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_break (0); + GNUNET_SERVICE_client_drop (client->client); + return; + } + GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head, + client->ticket_iter_tail, + ti); + cleanup_ticket_iter_handle (ti); + GNUNET_SERVICE_client_continue (client->client); +} + + +static void +handle_ticket_iteration_next (void *cls, + const struct TicketIterationNextMessage *tis_msg) +{ + struct IdpClient *client = cls; + struct TicketIteration *ti; + uint32_t rid; + + 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_break (0); + GNUNET_SERVICE_client_drop (client->client); + return; + } + run_ticket_iteration_round (ti); + GNUNET_SERVICE_client_continue (client->client); +} + + + + +/** + * Main function that will be run + * + * @param cls closure + * @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 ("reclaim", cfg); + + //Connect to identity and namestore services + ns_handle = GNUNET_NAMESTORE_connect (cfg); + if (NULL == ns_handle) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore"); + } + + gns_handle = GNUNET_GNS_connect (cfg); + if (NULL == gns_handle) + { + 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, + NULL, + NULL); + /* Loading DB plugin */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "reclaim", + "database", + &database)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No database backend configured\n"); + GNUNET_asprintf (&db_lib_name, + "libgnunet_plugin_reclaim_%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, + "reclaim", + "TOKEN_EXPIRATION_INTERVAL", + &token_expiration_interval)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Time window for zone iteration: %s\n", + GNUNET_STRINGS_relative_time_to_string (token_expiration_interval, + GNUNET_YES)); + } else { + token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL; + } + + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); +} + +/** + * Called whenever a client is disconnected. + * + * @param cls closure + * @param client identification of the client + * @param app_ctx @a client + */ +static void +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; + struct TicketIssueHandle *iss; + struct ConsumeTicketHandle *ct; + struct AttributeStoreHandle *as; + + //TODO other operations + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p disconnected\n", + client); + + while (NULL != (iss = idp->issue_op_head)) + { + GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, + idp->issue_op_tail, + iss); + cleanup_ticket_issue_handle (iss); + } + while (NULL != (ct = idp->consume_op_head)) + { + GNUNET_CONTAINER_DLL_remove (idp->consume_op_head, + idp->consume_op_tail, + ct); + cleanup_consume_ticket_handle (ct); + } + while (NULL != (as = idp->store_op_head)) + { + GNUNET_CONTAINER_DLL_remove (idp->store_op_head, + idp->store_op_tail, + as); + cleanup_as_handle (as); + } + + while (NULL != (ai = idp->attr_iter_head)) + { + GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, + idp->attr_iter_tail, + ai); + cleanup_attribute_iter_handle (ai); + } + while (NULL != (rh = idp->revoke_op_head)) + { + GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, + idp->revoke_op_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); +} + + +/** + * Add a client to our list of active clients. + * + * @param cls NULL + * @param client client to add + * @param mq message queue for @a client + * @return internal namestore client structure for this client + */ +static void * +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); + idp = GNUNET_new (struct IdpClient); + idp->client = client; + idp->mq = mq; + return idp; +} + + + +/** + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("reclaim", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_var_size (attribute_store_message, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE, + struct AttributeStoreMessage, + NULL), + GNUNET_MQ_hd_fixed_size (iteration_start, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START, + struct AttributeIterationStartMessage, + NULL), + GNUNET_MQ_hd_fixed_size (iteration_next, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT, + struct AttributeIterationNextMessage, + NULL), + GNUNET_MQ_hd_fixed_size (iteration_stop, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP, + struct AttributeIterationStopMessage, + NULL), + GNUNET_MQ_hd_var_size (issue_ticket_message, + GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET, + struct IssueTicketMessage, + NULL), + GNUNET_MQ_hd_var_size (consume_ticket_message, + GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET, + struct ConsumeTicketMessage, + NULL), + GNUNET_MQ_hd_fixed_size (ticket_iteration_start, + GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START, + struct TicketIterationStartMessage, + NULL), + GNUNET_MQ_hd_fixed_size (ticket_iteration_next, + GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT, + struct TicketIterationNextMessage, + NULL), + GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, + GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP, + struct TicketIterationStopMessage, + NULL), + GNUNET_MQ_hd_var_size (revoke_ticket_message, + GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET, + struct RevokeTicketMessage, + NULL), + GNUNET_MQ_handler_end()); +/* end of gnunet-service-reclaim.c */ diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c new file mode 100644 index 000000000..45b5d73f6 --- /dev/null +++ b/src/reclaim/jwt.c @@ -0,0 +1,160 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ + +/** + * @file reclaim/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_reclaim_attribute_lib.h" +#include + + +#define JWT_ALG "alg" + +/* Use 512bit HMAC */ +#define JWT_ALG_VALUE "HS512" + +#define JWT_TYP "typ" + +#define JWT_TYP_VALUE "jwt" + +#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo" + +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 aud_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 *aud_key, + const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const struct GNUNET_CRYPTO_AuthKey *priv_key) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + struct GNUNET_HashCode signature; + char* audience; + char* subject; + 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; + + //exp REQUIRED time expired from config + //iat REQUIRED time now + //auth_time only if max_age + //nonce only if nonce + // OPTIONAL acr,amr,azp + subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + header = create_jwt_header (); + body = json_object (); + + //iss REQUIRED case sensitive server uri with https + //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) + json_object_set_new (body, + "iss", json_string (SERVER_ADDRESS)); + //sub REQUIRED public key identity, not exceed 255 ASCII length + json_object_set_new (body, + "sub", json_string (subject)); + //aud REQUIRED public key client_id must be there + json_object_set_new (body, + "aud", json_string (audience)); + for (le = attrs->list_head; NULL != le; le = le->next) + { + attr_val_str = GNUNET_RECLAIM_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 (subject); + GNUNET_free (audience); + + /** + * Creating the JWT signature. This might not be + * standards compliant, check. + */ + GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); + GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature); + GNUNET_STRINGS_base64_encode ((const char*)&signature, + sizeof (struct GNUNET_HashCode), + &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); + return result; +} diff --git a/src/reclaim/jwt.h b/src/reclaim/jwt.h new file mode 100644 index 000000000..4b0b01be3 --- /dev/null +++ b/src/reclaim/jwt.h @@ -0,0 +1,10 @@ +#ifndef JWT_H +#define JWT_H + +char* +jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, + const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const struct GNUNET_CRYPTO_AuthKey *priv_key); + +#endif diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c new file mode 100644 index 000000000..0322df752 --- /dev/null +++ b/src/reclaim/plugin_gnsrecord_reclaim.c @@ -0,0 +1,265 @@ +/* + This file is part of GNUnet + Copyright (C) 2013, 2014 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file reclaim/plugin_gnsrecord_reclaim.c + * @brief gnsrecord plugin to provide the API for identity records + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_gnsrecord_plugin.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 * +value_to_string (void *cls, + uint32_t type, + const void *data, + size_t data_size) +{ + const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; + const struct GNUNET_CRYPTO_EcdsaPublicKey *audience_pubkey; + const char *scopes; + char *ecdhe_str; + char *aud_str; + char *result; + + switch (type) + { + case GNUNET_GNSRECORD_TYPE_ID_ATTR: + 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_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)); + ecdhe_str = GNUNET_STRINGS_data_to_string_alloc (ecdhe_privkey, + sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); + aud_str = GNUNET_STRINGS_data_to_string_alloc (audience_pubkey, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + GNUNET_asprintf (&result, + "%s;%s;%s", + ecdhe_str, aud_str, scopes); + GNUNET_free (aud_str); + GNUNET_free (ecdhe_str); + return result; + + 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 +string_to_value (void *cls, + uint32_t type, + const char *s, + void **data, + size_t *data_size) +{ + char* ecdhe_str; + char* aud_keystr; + char* write_ptr; + char* tmp_tok; + char* str; + + if (NULL == s) + return GNUNET_SYSERR; + 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); + ecdhe_str = strtok (tmp_tok, ";"); + if (NULL == ecdhe_str) + { + GNUNET_free (tmp_tok); + return GNUNET_SYSERR; + } + aud_keystr = strtok (NULL, ";"); + if (NULL == aud_keystr) + { + GNUNET_free (tmp_tok); + return GNUNET_SYSERR; + } + str = strtok (NULL, ";"); + if (NULL == str) + { + GNUNET_free (tmp_tok); + return GNUNET_SYSERR; + } + *data_size = strlen (str) + 1 + +sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) + +sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); + *data = GNUNET_malloc (*data_size); + + write_ptr = *data; + GNUNET_STRINGS_string_to_data (ecdhe_str, + strlen (ecdhe_str), + write_ptr, + sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); + write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); + GNUNET_STRINGS_string_to_data (aud_keystr, + strlen (aud_keystr), + write_ptr, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); + GNUNET_memcpy (write_ptr, str, strlen (str) + 1); //with 0-Terminator + GNUNET_free (tmp_tok); + 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[] = { + { "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 } +}; + + +/** + * Convert a type name (i.e. "AAAA") to the corresponding number. + * + * @param cls closure, unused + * @param dns_typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +static uint32_t +typename_to_number (void *cls, + const char *dns_typename) +{ + unsigned int i; + + i=0; + while ( (NULL != name_map[i].name) && + (0 != strcasecmp (dns_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 * +number_to_typename (void *cls, + uint32_t type) +{ + unsigned int i; + + i=0; + while ( (NULL != name_map[i].name) && + (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_reclaim_init (void *cls) +{ + struct GNUNET_GNSRECORD_PluginFunctions *api; + + api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); + api->value_to_string = &value_to_string; + api->string_to_value = &string_to_value; + api->typename_to_number = &typename_to_number; + api->number_to_typename = &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_reclaim_done (void *cls) +{ + struct GNUNET_GNSRECORD_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; +} + +/* end of plugin_gnsrecord_dns.c */ diff --git a/src/reclaim/plugin_reclaim_sqlite.c b/src/reclaim/plugin_reclaim_sqlite.c new file mode 100644 index 000000000..b545a94e8 --- /dev/null +++ b/src/reclaim/plugin_reclaim_sqlite.c @@ -0,0 +1,734 @@ + /* + * 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 Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file reclaim/plugin_reclaim_sqlite.c + * @brief sqlite-based idp backend + * @author Martin Schanzenbach + */ + +#include "platform.h" +#include "gnunet_reclaim_service.h" +#include "gnunet_reclaim_plugin.h" +#include "gnunet_reclaim_attribute_lib.h" +#include "gnunet_sq_lib.h" +#include + +/** + * 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, "reclaim", _("`%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, "reclaim-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, + "reclaim-sqlite", + "FILENAME", + &afsdir)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "reclaim-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 +reclaim_sqlite_store_ticket (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs); + attrs_ser = GNUNET_malloc (attrs_len); + GNUNET_RECLAIM_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 +reclaim_sqlite_delete_ticket (void *cls, + const struct GNUNET_RECLAIM_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_RECLAIM_TicketIterator iter, + void *iter_cls) +{ + struct GNUNET_RECLAIM_Ticket ticket; + struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser, + attrs_len); + if (NULL != iter) + iter (iter_cls, + &ticket, + attrs); + GNUNET_RECLAIM_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 +reclaim_sqlite_ticket_get_attrs (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket, + GNUNET_RECLAIM_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 +reclaim_sqlite_iterate_tickets (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + int audience, + uint64_t offset, + GNUNET_RECLAIM_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_RECLAIM_PluginEnvironment*" + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_reclaim_sqlite_init (void *cls) +{ + static struct Plugin plugin; + const struct GNUNET_CONFIGURATION_Handle *cfg = cls; + struct GNUNET_RECLAIM_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_RECLAIM_PluginFunctions); + api->cls = &plugin; + api->store_ticket = &reclaim_sqlite_store_ticket; + api->delete_ticket = &reclaim_sqlite_delete_ticket; + api->iterate_tickets = &reclaim_sqlite_iterate_tickets; + api->get_ticket_attributes = &reclaim_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_reclaim_sqlite_done (void *cls) +{ + struct GNUNET_RECLAIM_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_reclaim_sqlite.c */ diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c new file mode 100644 index 000000000..abb3f59f5 --- /dev/null +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -0,0 +1,2227 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @author Philippe Buschmann + * @file identity/plugin_rest_openid_connect.c + * @brief GNUnet Namestore REST plugin + * + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include "gnunet_identity_service.h" +#include "gnunet_gns_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_namestore_service.h" +#include "gnunet_rest_lib.h" +#include "gnunet_jsonapi_lib.h" +#include "gnunet_jsonapi_util.h" +#include "microhttpd.h" +#include +#include +#include "gnunet_signatures.h" +#include "gnunet_reclaim_attribute_lib.h" +#include "gnunet_reclaim_service.h" +#include "jwt.h" + +/** + * REST root namespace + */ +#define GNUNET_REST_API_NS_OIDC "/openid" + +/** + * Authorize endpoint + */ +#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize" + +/** + * Token endpoint + */ +#define GNUNET_REST_API_NS_TOKEN "/openid/token" + +/** + * UserInfo endpoint + */ +#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo" + +/** + * Login namespace + */ +#define GNUNET_REST_API_NS_LOGIN "/openid/login" + +/** + * Attribute key + */ +#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute" + +/** + * Ticket key + */ +#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" + + +/** + * Value key + */ +#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value" + +/** + * State while collecting all egos + */ +#define ID_REST_STATE_INIT 0 + +/** + * Done collecting egos + */ +#define ID_REST_STATE_POST_INIT 1 + +/** + * OIDC grant_type key + */ +#define OIDC_GRANT_TYPE_KEY "grant_type" + +/** + * OIDC grant_type key + */ +#define OIDC_GRANT_TYPE_VALUE "authorization_code" + +/** + * OIDC code key + */ +#define OIDC_CODE_KEY "code" + +/** + * OIDC response_type key + */ +#define OIDC_RESPONSE_TYPE_KEY "response_type" + +/** + * OIDC client_id key + */ +#define OIDC_CLIENT_ID_KEY "client_id" + +/** + * OIDC scope key + */ +#define OIDC_SCOPE_KEY "scope" + +/** + * OIDC redirect_uri key + */ +#define OIDC_REDIRECT_URI_KEY "redirect_uri" + +/** + * OIDC state key + */ +#define OIDC_STATE_KEY "state" + +/** + * OIDC nonce key + */ +#define OIDC_NONCE_KEY "nonce" + +/** + * OIDC cookie header key + */ +#define OIDC_COOKIE_HEADER_KEY "cookie" + +/** + * OIDC cookie header information key + */ +#define OIDC_AUTHORIZATION_HEADER_KEY "authorization" + +/** + * OIDC cookie header information key + */ +#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity=" + +/** + * OIDC expected response_type while authorizing + */ +#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code" + +/** + * OIDC expected scope part while authorizing + */ +#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid" + +/** + * OIDC ignored parameter array + */ +static char* OIDC_ignored_parameter_array [] = +{ + "display", + "prompt", + "max_age", + "ui_locales", + "response_mode", + "id_token_hint", + "login_hint", + "acr_values" +}; + +/** + * OIDC authorized identities and times hashmap + */ +struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time; + +/** + * OIDC authorized identities and times hashmap + */ +struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants; + +/** + * OIDC ticket/code use only once + */ +struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once; + +/** + * OIDC access_token to ticket and ego + */ +struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token; + +/** + * The configuration handle + */ +const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * HTTP methods allows for this plugin + */ +static char* allow_methods; + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct Plugin +{ + const struct GNUNET_CONFIGURATION_Handle *cfg; +}; + +/** + * OIDC needed variables + */ +struct OIDC_Variables +{ + /** + * The RP client public key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey; + + /** + * The OIDC client id of the RP + */ + char *client_id; + + /** + * GNUNET_YES if there is a delegation to + * this RP or if it is a local identity + */ + int is_client_trusted; + + /** + * The OIDC redirect uri + */ + char *redirect_uri; + + /** + * The list of oidc scopes + */ + char *scope; + + /** + * The OIDC state + */ + char *state; + + /** + * The OIDC nonce + */ + char *nonce; + + /** + * The OIDC response type + */ + char *response_type; + + /** + * The identity chosen by the user to login + */ + char *login_identity; + + /** + * The response JSON + */ + json_t *response; + +}; + +/** + * The ego list + */ +struct EgoEntry +{ + /** + * DLL + */ + struct EgoEntry *next; + + /** + * DLL + */ + struct EgoEntry *prev; + + /** + * Ego Identifier + */ + char *identifier; + + /** + * Public key string + */ + char *keystring; + + /** + * The Ego + */ + struct GNUNET_IDENTITY_Ego *ego; +}; + + +struct RequestHandle +{ + /** + * Ego list + */ + struct EgoEntry *ego_head; + + /** + * Ego list + */ + struct EgoEntry *ego_tail; + + /** + * Selected ego + */ + struct EgoEntry *ego_entry; + + /** + * Pointer to ego private key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; + + /** + * OIDC variables + */ + struct OIDC_Variables *oidc; + + /** + * The processing state + */ + int state; + + /** + * Handle to Identity service. + */ + struct GNUNET_IDENTITY_Handle *identity_handle; + + /** + * Rest connection + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * Handle to NAMESTORE + */ + struct GNUNET_NAMESTORE_Handle *namestore_handle; + + /** + * Iterator for NAMESTORE + */ + struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; + + /** + * Attribute claim list + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list; + + /** + * IDENTITY Operation + */ + struct GNUNET_IDENTITY_Operation *op; + + /** + * Identity Provider + */ + struct GNUNET_RECLAIM_Handle *idp; + + /** + * Idp Operation + */ + struct GNUNET_RECLAIM_Operation *idp_op; + + /** + * Attribute iterator + */ + struct GNUNET_RECLAIM_AttributeIterator *attr_it; + + /** + * Ticket iterator + */ + struct GNUNET_RECLAIM_TicketIterator *ticket_it; + + /** + * A ticket + */ + struct GNUNET_RECLAIM_Ticket ticket; + + /** + * Desired timeout for the lookup (default is no timeout). + */ + struct GNUNET_TIME_Relative timeout; + + /** + * ID of a task associated with the resolution process. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * The url + */ + char *url; + + /** + * The tld for redirect + */ + char *tld; + + /** + * Error response message + */ + char *emsg; + + /** + * Error response description + */ + char *edesc; + + /** + * Reponse code + */ + int response_code; + + /** + * Response object + */ + struct GNUNET_JSONAPI_Document *resp_object; + +}; + +/** + * Cleanup lookup handle + * @param handle Handle to clean up + */ +static void +cleanup_handle (struct RequestHandle *handle) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp; + struct EgoEntry *ego_entry; + struct EgoEntry *ego_tmp; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + if (NULL != handle->resp_object) + GNUNET_JSONAPI_document_delete (handle->resp_object); + if (NULL != handle->timeout_task) + GNUNET_SCHEDULER_cancel (handle->timeout_task); + if (NULL != handle->identity_handle) + GNUNET_IDENTITY_disconnect (handle->identity_handle); + if (NULL != handle->attr_it) + GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); + if (NULL != handle->ticket_it) + GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); + if (NULL != handle->idp) + GNUNET_RECLAIM_disconnect (handle->idp); + if (NULL != handle->url) + GNUNET_free (handle->url); + if (NULL != handle->tld) + GNUNET_free (handle->tld); + if (NULL != handle->emsg) + GNUNET_free (handle->emsg); + if (NULL != handle->edesc) + GNUNET_free (handle->edesc); + if (NULL != handle->namestore_handle) + GNUNET_NAMESTORE_disconnect (handle->namestore_handle); + if (NULL != handle->oidc) + { + if (NULL != handle->oidc->client_id) + GNUNET_free(handle->oidc->client_id); + if (NULL != handle->oidc->login_identity) + GNUNET_free(handle->oidc->login_identity); + if (NULL != handle->oidc->nonce) + GNUNET_free(handle->oidc->nonce); + if (NULL != handle->oidc->redirect_uri) + GNUNET_free(handle->oidc->redirect_uri); + if (NULL != handle->oidc->response_type) + GNUNET_free(handle->oidc->response_type); + if (NULL != handle->oidc->scope) + GNUNET_free(handle->oidc->scope); + if (NULL != handle->oidc->state) + GNUNET_free(handle->oidc->state); + if (NULL != handle->oidc->response) + json_decref(handle->oidc->response); + GNUNET_free(handle->oidc); + } + if ( NULL != handle->attr_list ) + { + for (claim_entry = handle->attr_list->list_head; + NULL != claim_entry;) + { + claim_tmp = claim_entry; + claim_entry = claim_entry->next; + GNUNET_free(claim_tmp->claim); + GNUNET_free(claim_tmp); + } + GNUNET_free (handle->attr_list); + } + for (ego_entry = handle->ego_head; + NULL != ego_entry;) + { + ego_tmp = ego_entry; + ego_entry = ego_entry->next; + GNUNET_free (ego_tmp->identifier); + GNUNET_free (ego_tmp->keystring); + GNUNET_free (ego_tmp); + } + if (NULL != handle->attr_it) + { + GNUNET_free(handle->attr_it); + } + GNUNET_free (handle); +} + +static void +cleanup_handle_delayed (void *cls) +{ + cleanup_handle (cls); +} + + +/** + * Task run on error, sends error message. Cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + char *json_error; + + GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}", + handle->emsg, + (NULL != handle->edesc) ? handle->edesc : "", + (NULL != handle->oidc->state) ? ", \"state\":\"" : "", + (NULL != handle->oidc->state) ? handle->oidc->state : "", + (NULL != handle->oidc->state) ? "\"" : ""); + if ( 0 == handle->response_code ) + { + handle->response_code = MHD_HTTP_BAD_REQUEST; + } + resp = GNUNET_REST_create_response (json_error); + if (MHD_HTTP_UNAUTHORIZED == handle->response_code) + { + MHD_add_response_header(resp, "WWW-Authenticate", "Basic"); + } + MHD_add_response_header (resp, "Content-Type", "application/json"); + handle->proc (handle->proc_cls, resp, handle->response_code); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + GNUNET_free (json_error); +} + + +/** + * Task run on error in userinfo endpoint, sends error header. Cleans up + * everything + * + * @param cls the `struct RequestHandle` + */ +static void +do_userinfo_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + char *error; + + GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"", + handle->emsg, + (NULL != handle->edesc) ? handle->edesc : ""); + resp = GNUNET_REST_create_response (""); + MHD_add_response_header(resp, "WWW-Authenticate", error); + handle->proc (handle->proc_cls, resp, handle->response_code); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + GNUNET_free (error); +} + + +/** + * Task run on error, sends error message and redirects. Cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_redirect_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + char* redirect; + GNUNET_asprintf (&redirect, + "%s?error=%s&error_description=%s%s%s", + handle->oidc->redirect_uri, handle->emsg, handle->edesc, + (NULL != handle->oidc->state) ? "&state=" : "", + (NULL != handle->oidc->state) ? handle->oidc->state : ""); + resp = GNUNET_REST_create_response (""); + MHD_add_response_header (resp, "Location", redirect); + handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + GNUNET_free (redirect); +} + +/** + * Task run on timeout, sends error message. Cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_timeout (void *cls) +{ + struct RequestHandle *handle = cls; + + handle->timeout_task = NULL; + do_error (handle); +} + +/** + * Return attributes for claim + * + * @param cls the request handle + */ +static void +return_userinfo_response (void *cls) +{ + char* result_str; + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + + result_str = json_dumps (handle->oidc->response, 0); + + resp = GNUNET_REST_create_response (result_str); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free (result_str); + cleanup_handle (handle); +} + +/** + * Returns base64 encoded string without padding + * + * @param string the string to encode + * @return base64 encoded string + */ +static char* +base_64_encode(const char *s) +{ + char *enc; + char *tmp; + + GNUNET_STRINGS_base64_encode(s, strlen(s), &enc); + tmp = strrchr (enc, '='); + *tmp = '\0'; + return enc; +} + +/** + * Respond to OPTIONS request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + //For now, independent of path return all options + resp = GNUNET_REST_create_response (NULL); + MHD_add_response_header (resp, + "Access-Control-Allow-Methods", + allow_methods); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + cleanup_handle (handle); + return; +} + +/** + * Interprets cookie header and pass its identity keystring to handle + */ +static void +cookie_identity_interpretation (struct RequestHandle *handle) +{ + struct GNUNET_HashCode cache_key; + char *cookies; + struct GNUNET_TIME_Absolute current_time, *relog_time; + char delimiter[] = "; "; + + //gets identity of login try with cookie + GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), + &cache_key); + if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, + &cache_key) ) + { + //splits cookies and find 'Identity' cookie + cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); + handle->oidc->login_identity = strtok(cookies, delimiter); + + while ( NULL != handle->oidc->login_identity ) + { + if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) ) + { + break; + } + handle->oidc->login_identity = strtok (NULL, delimiter); + } + GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity), + &cache_key); + if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) ) + { + relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, + &cache_key); + current_time = GNUNET_TIME_absolute_get (); + // 30 min after old login -> redirect to login + if ( current_time.abs_value_us <= relog_time->abs_value_us ) + { + handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY); + handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity); + } else { + handle->oidc->login_identity = NULL; + } + } + else + { + handle->oidc->login_identity = NULL; + } + } +} + +/** + * Redirects to login page stored in configuration file + */ +static void +login_redirection(void *cls) +{ + char *login_base_url; + char *new_redirect; + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + if ( GNUNET_OK + == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + "address", &login_base_url) ) + { + GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", + login_base_url, + OIDC_RESPONSE_TYPE_KEY, + handle->oidc->response_type, + OIDC_CLIENT_ID_KEY, + handle->oidc->client_id, + OIDC_REDIRECT_URI_KEY, + handle->oidc->redirect_uri, + OIDC_SCOPE_KEY, + handle->oidc->scope, + OIDC_STATE_KEY, + (NULL != handle->oidc->state) ? handle->oidc->state : "", + OIDC_NONCE_KEY, + (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); + resp = GNUNET_REST_create_response (""); + MHD_add_response_header (resp, "Location", new_redirect); + GNUNET_free(login_base_url); + } + else + { + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup ("gnunet configuration failed"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); + GNUNET_free(new_redirect); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); +} + +/** + * Does internal server error when iteration failed. + */ +static void +oidc_iteration_error (void *cls) +{ + struct RequestHandle *handle = cls; + handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); +} + +static void get_client_name_result (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; + struct MHD_Response *resp; + char *ticket_str; + char *redirect_uri; + char *code_json_string; + char *code_base64_final_string; + char *redirect_path; + char *tmp; + char *tmp_prefix; + char *prefix; + ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + //TODO change if more attributes are needed (see max_age) + GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", + ticket_str, + (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", + (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", + (NULL != handle->oidc->nonce) ? "\"" : ""); + code_base64_final_string = base_64_encode(code_json_string); + tmp = GNUNET_strdup (handle->oidc->redirect_uri); + redirect_path = strtok (tmp, "/"); + redirect_path = strtok (NULL, "/"); + redirect_path = strtok (NULL, "/"); + tmp_prefix = GNUNET_strdup (handle->oidc->redirect_uri); + prefix = strrchr (tmp_prefix, + (unsigned char) '.'); + *prefix = '\0'; + GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", + tmp_prefix, + handle->tld, + redirect_path, + handle->oidc->response_type, + code_base64_final_string, handle->oidc->state); + resp = GNUNET_REST_create_response (""); + MHD_add_response_header (resp, "Location", redirect_uri); + handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + GNUNET_free (tmp); + GNUNET_free (tmp_prefix); + GNUNET_free (redirect_uri); + GNUNET_free (ticket_str); + GNUNET_free (code_json_string); + GNUNET_free (code_base64_final_string); + return; +} + +static void +get_client_name_error (void *cls) +{ + struct RequestHandle *handle = cls; + + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); +} + +/** + * Issues ticket and redirects to relying party with the authorization code as + * parameter. Otherwise redirects with error + */ +static void +oidc_ticket_issue_cb (void* cls, + const struct GNUNET_RECLAIM_Ticket *ticket) +{ + struct RequestHandle *handle = cls; + handle->idp_op = NULL; + handle->ticket = *ticket; + if (NULL != ticket) { + GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, + &handle->priv_key, + &handle->oidc->client_pkey, + &get_client_name_error, + handle, + &get_client_name_result, + handle); + return; + } + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup("Server cannot generate ticket."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); +} + +static void +oidc_collect_finished_cb (void *cls) +{ + struct RequestHandle *handle = cls; + handle->attr_it = NULL; + handle->ticket_it = NULL; + if (NULL == handle->attr_list->list_head) + { + handle->emsg = GNUNET_strdup("invalid_scope"); + handle->edesc = GNUNET_strdup("The requested scope is not available."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, + &handle->priv_key, + &handle->oidc->client_pkey, + handle->attr_list, + &oidc_ticket_issue_cb, + handle); +} + + +/** + * Collects all attributes for an ego if in scope parameter + */ +static void +oidc_attr_collect (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) +{ + struct RequestHandle *handle = cls; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + char* scope_variables; + char* scope_variable; + char delimiter[]=" "; + + if ( (NULL == attr->name) || (NULL == attr->data) ) + { + GNUNET_RECLAIM_get_attributes_next (handle->attr_it); + return; + } + + scope_variables = GNUNET_strdup(handle->oidc->scope); + scope_variable = strtok (scope_variables, delimiter); + while (NULL != scope_variable) + { + if ( 0 == strcmp (attr->name, scope_variable) ) + { + break; + } + scope_variable = strtok (NULL, delimiter); + } + if ( NULL == scope_variable ) + { + GNUNET_RECLAIM_get_attributes_next (handle->attr_it); + GNUNET_free(scope_variables); + return; + } + GNUNET_free(scope_variables); + + le = GNUNET_new(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); + le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, attr->type, + attr->data, attr->data_size); + GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head, + handle->attr_list->list_tail, le); + GNUNET_RECLAIM_get_attributes_next (handle->attr_it); +} + + +/** + * Checks time and cookie and redirects accordingly + */ +static void +login_check (void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_TIME_Absolute current_time, *relog_time; + struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey; + struct GNUNET_HashCode cache_key; + char *identity_cookie; + + GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity); + GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); + GNUNET_free(identity_cookie); + //No login time for identity -> redirect to login + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, + &cache_key) ) + { + relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, + &cache_key); + current_time = GNUNET_TIME_absolute_get (); + // 30 min after old login -> redirect to login + if ( current_time.abs_value_us <= relog_time->abs_value_us ) + { + if ( GNUNET_OK + != GNUNET_CRYPTO_ecdsa_public_key_from_string ( + handle->oidc->login_identity, + strlen (handle->oidc->login_identity), &pubkey) ) + { + handle->emsg = GNUNET_strdup("invalid_cookie"); + handle->edesc = GNUNET_strdup( + "The cookie of a login identity is not valid"); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + // iterate over egos and compare their public key + for (handle->ego_entry = handle->ego_head; + NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) + { + GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); + if ( 0 + == memcmp (&ego_pkey, &pubkey, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) + { + handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key ( + handle->ego_entry->ego); + handle->resp_object = GNUNET_JSONAPI_document_new (); + handle->idp = GNUNET_RECLAIM_connect (cfg); + handle->attr_list = GNUNET_new( + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + handle->attr_it = GNUNET_RECLAIM_get_attributes_start ( + handle->idp, &handle->priv_key, &oidc_iteration_error, handle, + &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle); + return; + } + } + //handle->emsg = GNUNET_strdup("invalid_cookie"); + //handle->edesc = GNUNET_strdup( + // "The cookie of the login identity is not valid"); + //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + GNUNET_SCHEDULER_add_now (&login_redirection,handle); + return; + } + } +} + +/** + * Searches for client_id in namestore. If found trust status stored in handle + * Else continues to search + * + * @param handle the RequestHandle + */ +static void +namestore_iteration_callback ( + void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, + const char *rname, unsigned int rd_len, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey; + struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey; + int i; + + for (i = 0; i < rd_len; i++) + { + if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type ) + continue; + + if ( NULL != handle->oidc->login_identity ) + { + GNUNET_CRYPTO_ecdsa_public_key_from_string ( + handle->oidc->login_identity, + strlen (handle->oidc->login_identity), + &login_identity_pkey); + GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, + ¤t_zone_pkey); + + if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) + { + if ( 0 == memcmp (&login_identity_pkey, ¤t_zone_pkey, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) + { + handle->oidc->is_client_trusted = GNUNET_YES; + } + } + } + else + { + if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) + { + handle->oidc->is_client_trusted = GNUNET_YES; + } + } + } + + GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it, + 1); +} + + +/** + * Iteration over all results finished, build final + * response. + * + * @param cls the `struct RequestHandle` + */ +static void +namestore_iteration_finished (void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_HashCode cache_key; + + char *expected_scope; + char delimiter[]=" "; + int number_of_ignored_parameter, iterator; + + + handle->ego_entry = handle->ego_entry->next; + + if(NULL != handle->ego_entry) + { + handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); + handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key, + &oidc_iteration_error, handle, &namestore_iteration_callback, handle, + &namestore_iteration_finished, handle); + return; + } + if (GNUNET_NO == handle->oidc->is_client_trusted) + { + handle->emsg = GNUNET_strdup("unauthorized_client"); + handle->edesc = GNUNET_strdup("The client is not authorized to request an " + "authorization code using this method."); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + // REQUIRED value: redirect_uri + GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), + &cache_key); + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) + { + handle->emsg=GNUNET_strdup("invalid_request"); + handle->edesc=GNUNET_strdup("missing parameter redirect_uri"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, + &cache_key)); + + // REQUIRED value: response_type + GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY), + &cache_key); + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) + { + handle->emsg=GNUNET_strdup("invalid_request"); + handle->edesc=GNUNET_strdup("missing parameter response_type"); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, + &cache_key); + handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type); + + // REQUIRED value: scope + GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key); + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) + { + handle->emsg=GNUNET_strdup("invalid_request"); + handle->edesc=GNUNET_strdup("missing parameter scope"); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, + &cache_key); + handle->oidc->scope = GNUNET_strdup(handle->oidc->scope); + + //OPTIONAL value: nonce + GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key); + if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) + { + handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, + &cache_key); + handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce); + } + + //TODO check other values if needed + number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); + for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) + { + GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], + strlen(OIDC_ignored_parameter_array[iterator]), + &cache_key); + if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map, + &cache_key)) + { + handle->emsg=GNUNET_strdup("access_denied"); + GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s", + OIDC_ignored_parameter_array[iterator]); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + } + + // Checks if response_type is 'code' + if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) + { + handle->emsg=GNUNET_strdup("unsupported_response_type"); + handle->edesc=GNUNET_strdup("The authorization server does not support " + "obtaining this authorization code."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + + // Checks if scope contains 'openid' + expected_scope = GNUNET_strdup(handle->oidc->scope); + char* test; + test = strtok (expected_scope, delimiter); + while (NULL != test) + { + if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) ) + { + break; + } + test = strtok (NULL, delimiter); + } + if (NULL == test) + { + handle->emsg = GNUNET_strdup("invalid_scope"); + handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " + "malformed."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + GNUNET_free(expected_scope); + return; + } + + GNUNET_free(expected_scope); + + if( NULL != handle->oidc->login_identity ) + { + GNUNET_SCHEDULER_add_now(&login_check,handle); + return; + } + + GNUNET_SCHEDULER_add_now(&login_redirection,handle); +} + +/** + * Responds to authorization GET and url-encoded POST request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_HashCode cache_key; + struct EgoEntry *tmp_ego; + struct GNUNET_CRYPTO_EcdsaPublicKey pkey; + const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; + + cookie_identity_interpretation(handle); + + //RECOMMENDED value: state - REQUIRED for answers + GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key); + if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) + { + handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, + &cache_key); + handle->oidc->state = GNUNET_strdup (handle->oidc->state); + } + + // REQUIRED value: client_id + GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), + &cache_key); + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) + { + handle->emsg=GNUNET_strdup("invalid_request"); + handle->edesc=GNUNET_strdup("missing parameter client_id"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, + &cache_key)); + + if ( GNUNET_OK + != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id, + strlen (handle->oidc->client_id), + &handle->oidc->client_pkey) ) + { + handle->emsg = GNUNET_strdup("unauthorized_client"); + handle->edesc = GNUNET_strdup("The client is not authorized to request an " + "authorization code using this method."); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + + if ( NULL == handle->ego_head ) + { + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup ("Egos are missing"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + handle->ego_entry = handle->ego_head; + handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); + handle->oidc->is_client_trusted = GNUNET_NO; + + //First check if client_id is one of our egos; TODO: handle other TLD cases: Delegation, from config + for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) + { + priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); + GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, + &pkey); + if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) + { + handle->tld = GNUNET_strdup (tmp_ego->identifier); + handle->oidc->is_client_trusted = GNUNET_YES; + handle->ego_entry = handle->ego_tail; + } + } + + + // Checks if client_id is valid: + handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start ( + handle->namestore_handle, &handle->priv_key, &oidc_iteration_error, + handle, &namestore_iteration_callback, handle, + &namestore_iteration_finished, handle); +} + +/** + * Combines an identity with a login time and responds OK to login request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +login_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp = GNUNET_REST_create_response (""); + struct RequestHandle *handle = cls; + struct GNUNET_HashCode cache_key; + struct GNUNET_TIME_Absolute *current_time; + struct GNUNET_TIME_Absolute *last_time; + char* cookie; + json_t *root; + json_error_t error; + json_t *identity; + char term_data[handle->rest_handle->data_size+1]; + term_data[handle->rest_handle->data_size] = '\0'; + GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size); + root = json_loads (term_data, JSON_DECODE_ANY, &error); + identity = json_object_get (root, "identity"); + if ( json_is_string(identity) ) + { + GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity)); + MHD_add_response_header (resp, "Set-Cookie", cookie); + MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST"); + GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key); + + current_time = GNUNET_new(struct GNUNET_TIME_Absolute); + *current_time = GNUNET_TIME_relative_to_absolute ( + GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), + 5)); + last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key); + if (NULL != last_time) + { + GNUNET_free(last_time); + } + GNUNET_CONTAINER_multihashmap_put ( + OIDC_identity_login_time, &cache_key, current_time, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); + + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free(cookie); + } + else + { + handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); + } + json_decref (root); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + return; +} + +/** + * Responds to token url-encoded POST request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + //TODO static strings + struct RequestHandle *handle = cls; + struct GNUNET_HashCode cache_key; + char *authorization, *credentials; + char delimiter[]=" "; + char delimiter_user_psw[]=":"; + char *grant_type, *code; + char *user_psw = NULL, *client_id, *psw; + char *expected_psw; + int client_exists = GNUNET_NO; + struct MHD_Response *resp; + char* code_output; + json_t *root, *ticket_string, *nonce, *max_age; + json_error_t error; + char *json_response; + char *jwt_secret; + + /* + * Check Authorization + */ + GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, + strlen (OIDC_AUTHORIZATION_HEADER_KEY), + &cache_key); + if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, + &cache_key) ) + { + handle->emsg=GNUNET_strdup("invalid_client"); + handle->edesc=GNUNET_strdup("missing authorization"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); + + //split header in "Basic" and [content] + credentials = strtok (authorization, delimiter); + if (0 != strcmp ("Basic",credentials)) + { + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + credentials = strtok(NULL, delimiter); + if (NULL == credentials) + { + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw); + + if ( NULL == user_psw ) + { + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + client_id = strtok (user_psw, delimiter_user_psw); + if ( NULL == client_id ) + { + GNUNET_free_non_null(user_psw); + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + psw = strtok (NULL, delimiter_user_psw); + if (NULL == psw) + { + GNUNET_free_non_null(user_psw); + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + //check client password + if ( GNUNET_OK + == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + "psw", &expected_psw) ) + { + if (0 != strcmp (expected_psw, psw)) + { + GNUNET_free_non_null(user_psw); + GNUNET_free(expected_psw); + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_free(expected_psw); + } + else + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup ("gnunet configuration failed"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + //check client_id + for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; ) + { + if ( 0 == strcmp(handle->ego_entry->keystring, client_id)) + { + client_exists = GNUNET_YES; + break; + } + handle->ego_entry = handle->ego_entry->next; + } + if (GNUNET_NO == client_exists) + { + GNUNET_free_non_null(user_psw); + handle->emsg=GNUNET_strdup("invalid_client"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + /* + * Check parameter + */ + + //TODO Do not allow multiple equal parameter names + //REQUIRED grant_type + GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &cache_key) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("missing parameter grant_type"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + grant_type = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map, &cache_key); + + //REQUIRED code + GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &cache_key) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("missing parameter code"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &cache_key); + + //REQUIRED redirect_uri + GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), + &cache_key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &cache_key) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + //Check parameter grant_type == "authorization_code" + if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) + { + GNUNET_free_non_null(user_psw); + handle->emsg=GNUNET_strdup("unsupported_grant_type"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_CRYPTO_hash (code, strlen (code), &cache_key); + int i = 1; + if ( GNUNET_SYSERR + == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, + &cache_key, + &i, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("Cannot use the same code more than once"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + //decode code + GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output); + root = json_loads (code_output, 0, &error); + GNUNET_free(code_output); + ticket_string = json_object_get (root, "ticket"); + nonce = json_object_get (root, "nonce"); + max_age = json_object_get (root, "max_age"); + + if(ticket_string == NULL && !json_is_string(ticket_string)) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("invalid code"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + struct GNUNET_RECLAIM_Ticket *ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket); + if ( GNUNET_OK + != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string), + strlen (json_string_value(ticket_string)), + ticket, + sizeof(struct GNUNET_RECLAIM_Ticket))) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("invalid code"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free(ticket); + return; + } + // this is the current client (relying party) + struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; + GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); + if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("invalid code"); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free(ticket); + return; + } + + //create jwt + unsigned long long int expiration_time; + if ( GNUNET_OK + != GNUNET_CONFIGURATION_get_value_number(cfg, "identity-rest-plugin", + "expiration_time", &expiration_time) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup ("gnunet configuration failed"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free(ticket); + return; + } + + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + //aud REQUIRED public key client_id must be there + GNUNET_RECLAIM_ATTRIBUTE_list_add(cl, + "aud", + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, + client_id, + strlen(client_id)); + //exp REQUIRED time expired from config + struct GNUNET_TIME_Absolute exp_time = GNUNET_TIME_relative_to_absolute ( + GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), + expiration_time)); + const char* exp_time_string = GNUNET_STRINGS_absolute_time_to_string(exp_time); + GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, + "exp", + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, + exp_time_string, + strlen(exp_time_string)); + //iat REQUIRED time now + struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get(); + const char* time_now_string = GNUNET_STRINGS_absolute_time_to_string(time_now); + GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, + "iat", + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, + time_now_string, + strlen(time_now_string)); + //nonce only if nonce is provided + if ( NULL != nonce && json_is_string(nonce) ) + { + GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, + "nonce", + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, + json_string_value(nonce), + strlen(json_string_value(nonce))); + } + //auth_time only if max_age is provided + if ( NULL != max_age && json_is_string(max_age) ) + { + GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, + "auth_time", + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, + json_string_value(max_age), + strlen(json_string_value(max_age))); + } + //TODO OPTIONAL acr,amr,azp + + struct EgoEntry *ego_entry; + for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) + { + GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); + if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + break; + } + } + if ( NULL == ego_entry ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("invalid code..."); + handle->response_code = MHD_HTTP_BAD_REQUEST; + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free(ticket); + return; + } + if ( GNUNET_OK + != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + "jwt_secret", &jwt_secret) ) + { + GNUNET_free_non_null(user_psw); + handle->emsg = GNUNET_strdup("invalid_request"); + handle->edesc = GNUNET_strdup("No signing secret configured!"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free(ticket); + return; + } + struct GNUNET_CRYPTO_AuthKey jwt_sign_key; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk); + GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key); + char *id_token = jwt_create_from_list(&ticket->audience, + &pk, + cl, + &jwt_sign_key); + + //Create random access_token + char* access_token_number; + char* access_token; + uint64_t random_number; + random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); + GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number); + GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); + + + + //TODO OPTIONAL add refresh_token and scope + GNUNET_asprintf (&json_response, + "{ \"access_token\" : \"%s\", " + "\"token_type\" : \"Bearer\", " + "\"expires_in\" : %d, " + "\"id_token\" : \"%s\"}", + access_token, + expiration_time, + id_token); + GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); + char *id_ticket_combination; + GNUNET_asprintf(&id_ticket_combination, + "%s;%s", + client_id, + json_string_value(ticket_string)); + GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, + &cache_key, + id_ticket_combination, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); + + resp = GNUNET_REST_create_response (json_response); + MHD_add_response_header (resp, "Cache-Control", "no-store"); + MHD_add_response_header (resp, "Pragma", "no-cache"); + MHD_add_response_header (resp, "Content-Type", "application/json"); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + + GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl); + GNUNET_free(access_token_number); + GNUNET_free(access_token); + GNUNET_free(user_psw); + GNUNET_free(json_response); + GNUNET_free(ticket); + GNUNET_free(id_token); + json_decref (root); + GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle); +} + +/** + * Collects claims and stores them in handle + */ +static void +consume_ticket (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) +{ + struct RequestHandle *handle = cls; + char *tmp_value; + json_t *value; + + if (NULL == identity) + { + GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); + return; + } + + tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, + attr->data, + attr->data_size); + + value = json_string (tmp_value); + + + json_object_set_new (handle->oidc->response, + attr->name, + value); + GNUNET_free (tmp_value); +} + +/** + * Responds to userinfo GET and url-encoded POST request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, void *cls) +{ + //TODO expiration time + struct RequestHandle *handle = cls; + char delimiter[] = " "; + char delimiter_db[] = ";"; + struct GNUNET_HashCode cache_key; + char *authorization, *authorization_type, *authorization_access_token; + char *client_ticket, *client, *ticket_str; + struct GNUNET_RECLAIM_Ticket *ticket; + + GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, + strlen (OIDC_AUTHORIZATION_HEADER_KEY), + &cache_key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->header_param_map, &cache_key) ) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("No Access Token"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + return; + } + authorization = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->header_param_map, &cache_key); + + //split header in "Bearer" and access_token + authorization = GNUNET_strdup(authorization); + authorization_type = strtok (authorization, delimiter); + if ( 0 != strcmp ("Bearer", authorization_type) ) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("No Access Token"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(authorization); + return; + } + authorization_access_token = strtok (NULL, delimiter); + if ( NULL == authorization_access_token ) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("No Access Token"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(authorization); + return; + } + + GNUNET_CRYPTO_hash (authorization_access_token, + strlen (authorization_access_token), + &cache_key); + if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token, + &cache_key) ) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("The Access Token expired"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(authorization); + return; + } + + client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token, + &cache_key); + client_ticket = GNUNET_strdup(client_ticket); + client = strtok(client_ticket,delimiter_db); + if (NULL == client) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("The Access Token expired"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(authorization); + GNUNET_free(client_ticket); + return; + } + handle->ego_entry = handle->ego_head; + for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) + { + if (0 == strcmp(handle->ego_entry->keystring,client)) + { + break; + } + } + if (NULL == handle->ego_entry) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("The Access Token expired"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(authorization); + GNUNET_free(client_ticket); + return; + } + ticket_str = strtok(NULL, delimiter_db); + if (NULL == ticket_str) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("The Access Token expired"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(authorization); + GNUNET_free(client_ticket); + return; + } + ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket); + if ( GNUNET_OK + != GNUNET_STRINGS_string_to_data (ticket_str, + strlen (ticket_str), + ticket, + sizeof(struct GNUNET_RECLAIM_Ticket))) + { + handle->emsg = GNUNET_strdup("invalid_token"); + handle->edesc = GNUNET_strdup("The Access Token expired"); + handle->response_code = MHD_HTTP_UNAUTHORIZED; + GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); + GNUNET_free(ticket); + GNUNET_free(authorization); + GNUNET_free(client_ticket); + return; + } + + handle->idp = GNUNET_RECLAIM_connect (cfg); + handle->oidc->response = json_object(); + json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring)); + handle->idp_op = GNUNET_RECLAIM_ticket_consume ( + handle->idp, + GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego), + ticket, + consume_ticket, + handle); + GNUNET_free(ticket); + GNUNET_free(authorization); + GNUNET_free(client_ticket); + +} + + +/** + * Handle rest request + * + * @param handle the request handle + */ +static void +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_AUTHORIZE, &authorize_endpoint}, + {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded + {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, + {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint }, + {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, + {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, + {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, + &options_cont}, + GNUNET_REST_HANDLER_END + }; + + if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, + handlers, + &err, + handle)) + { + handle->response_code = err.error_code; + GNUNET_SCHEDULER_add_now (&do_error, handle); + } +} + +/** + * If listing is enabled, prints information about the egos. + * + * This function is initially called for all egos and then again + * whenever a ego's identifier changes or if it is deleted. At the + * end of the initial pass over all egos, the function is once called + * with 'NULL' for 'ego'. That does NOT mean that the callback won't + * be invoked in the future or that there was an error. + * + * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', + * this function is only called ONCE, and 'NULL' being passed in + * 'ego' does indicate an error (i.e. name is taken or no default + * value is known). If 'ego' is non-NULL and if '*ctx' + * is set in those callbacks, the value WILL be passed to a subsequent + * call to the identity callback of 'GNUNET_IDENTITY_connect' (if + * that one was not NULL). + * + * When an identity is renamed, this function is called with the + * (known) ego but the NEW identifier. + * + * When an identity is deleted, this function is called with the + * (known) ego and "NULL" for the 'identifier'. In this case, + * the 'ego' is henceforth invalid (and the 'ctx' should also be + * cleaned up). + * + * @param cls closure + * @param ego ego handle + * @param ctx context for application to store data for this ego + * (during the lifetime of this process, initially NULL) + * @param identifier identifier assigned by the user for this ego, + * NULL if the user just deleted the ego and it + * must thus no longer be used + */ +static void +list_ego (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *identifier) +{ + struct RequestHandle *handle = cls; + struct EgoEntry *ego_entry; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + + if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) + { + handle->state = ID_REST_STATE_POST_INIT; + init_cont (handle); + return; + } + if (ID_REST_STATE_INIT == handle->state) { + ego_entry = GNUNET_new (struct EgoEntry); + GNUNET_IDENTITY_ego_get_public_key (ego, &pk); + ego_entry->keystring = + GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->ego = ego; + ego_entry->identifier = GNUNET_strdup (identifier); + GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); + return; + } + /* Ego renamed or added */ + if (identifier != NULL) { + for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { + if (ego_entry->ego == ego) { + /* Rename */ + GNUNET_free (ego_entry->identifier); + ego_entry->identifier = GNUNET_strdup (identifier); + break; + } + } + if (NULL == ego_entry) { + /* Add */ + ego_entry = GNUNET_new (struct EgoEntry); + GNUNET_IDENTITY_ego_get_public_key (ego, &pk); + ego_entry->keystring = + GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->ego = ego; + ego_entry->identifier = GNUNET_strdup (identifier); + GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); + } + } else { + /* Delete */ + for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { + if (ego_entry->ego == ego) + break; + } + if (NULL != ego_entry) + GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry); + } + +} + +static void +rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + handle->oidc = GNUNET_new (struct OIDC_Variables); + if ( NULL == OIDC_identity_login_time ) + OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); + if ( NULL == OIDC_identity_grants ) + OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); + if ( NULL == OIDC_ticket_once ) + OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); + if ( NULL == OIDC_interpret_access_token ) + OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); + handle->response_code = 0; + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + handle->state = ID_REST_STATE_INIT; + handle->rest_handle = rest_handle; + + 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, + "Connecting...\n"); + handle->identity_handle = GNUNET_IDENTITY_connect (cfg, + &list_ego, + handle); + handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); + handle->timeout_task = + GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_timeout, + handle); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connected\n"); +} + +/** + * Entry point for the plugin. + * + * @param cls Config info + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_rest_openid_connect_init (void *cls) +{ + static struct Plugin plugin; + struct GNUNET_REST_Plugin *api; + + cfg = cls; + 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_OIDC; + api->process_request = &rest_identity_process_request; + GNUNET_asprintf (&allow_methods, + "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Identity Provider 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_openid_connect_done (void *cls) +{ + struct GNUNET_REST_Plugin *api = cls; + struct Plugin *plugin = api->cls; + plugin->cfg = NULL; + + struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it; + void *value = NULL; + hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create ( + OIDC_identity_login_time); + while (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) + { + if (NULL != value) + GNUNET_free(value); + } + GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time); + hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants); + while (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) + { + if (NULL != value) + GNUNET_free(value); + } + GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants); + hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once); + while (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) + { + if (NULL != value) + GNUNET_free(value); + } + GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once); + hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token); + while (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) + { + if (NULL != value) + GNUNET_free(value); + } + GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token); + GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it); + GNUNET_free_non_null (allow_methods); + GNUNET_free (api); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Identity Provider REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_identity_provider.c */ diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c new file mode 100644 index 000000000..b54aed5f3 --- /dev/null +++ b/src/reclaim/plugin_rest_reclaim.c @@ -0,0 +1,1253 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @author Philippe Buschmann + * @file reclaim/plugin_rest_reclaim.c + * @brief GNUnet reclaim REST plugin + * + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include "gnunet_identity_service.h" +#include "gnunet_gns_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_namestore_service.h" +#include "gnunet_rest_lib.h" +#include "gnunet_jsonapi_lib.h" +#include "gnunet_jsonapi_util.h" +#include "microhttpd.h" +#include +#include +#include "gnunet_signatures.h" +#include "gnunet_reclaim_attribute_lib.h" +#include "gnunet_reclaim_service.h" + +/** + * REST root namespace + */ +#define GNUNET_REST_API_NS_RECLAIM "/idp" + +/** + * Attribute namespace + */ +#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/idp/attributes" + +/** + * Ticket namespace + */ +#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets" + +/** + * Revoke namespace + */ +#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke" + +/** + * Revoke namespace + */ +#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" + +/** + * Attribute key + */ +#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute" + +/** + * Ticket key + */ +#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" + + +/** + * Value key + */ +#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value" + +/** + * State while collecting all egos + */ +#define ID_REST_STATE_INIT 0 + +/** + * Done collecting egos + */ +#define ID_REST_STATE_POST_INIT 1 + +/** + * The configuration handle + */ +const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * HTTP methods allows for this plugin + */ +static char* allow_methods; + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct Plugin +{ + const struct GNUNET_CONFIGURATION_Handle *cfg; +}; + +/** + * The ego list + */ +struct EgoEntry +{ + /** + * DLL + */ + struct EgoEntry *next; + + /** + * DLL + */ + struct EgoEntry *prev; + + /** + * Ego Identifier + */ + char *identifier; + + /** + * Public key string + */ + char *keystring; + + /** + * The Ego + */ + struct GNUNET_IDENTITY_Ego *ego; +}; + + +struct RequestHandle +{ + /** + * Ego list + */ + struct EgoEntry *ego_head; + + /** + * Ego list + */ + struct EgoEntry *ego_tail; + + /** + * Selected ego + */ + struct EgoEntry *ego_entry; + + /** + * Pointer to ego private key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; + + /** + * The processing state + */ + int state; + + /** + * Handle to Identity service. + */ + struct GNUNET_IDENTITY_Handle *identity_handle; + + /** + * Rest connection + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * Handle to NAMESTORE + */ + struct GNUNET_NAMESTORE_Handle *namestore_handle; + + /** + * Iterator for NAMESTORE + */ + struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; + + /** + * Attribute claim list + */ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list; + + /** + * IDENTITY Operation + */ + struct GNUNET_IDENTITY_Operation *op; + + /** + * Identity Provider + */ + struct GNUNET_RECLAIM_Handle *idp; + + /** + * Idp Operation + */ + struct GNUNET_RECLAIM_Operation *idp_op; + + /** + * Attribute iterator + */ + struct GNUNET_RECLAIM_AttributeIterator *attr_it; + + /** + * Ticket iterator + */ + struct GNUNET_RECLAIM_TicketIterator *ticket_it; + + /** + * A ticket + */ + struct GNUNET_RECLAIM_Ticket ticket; + + /** + * Desired timeout for the lookup (default is no timeout). + */ + struct GNUNET_TIME_Relative timeout; + + /** + * ID of a task associated with the resolution process. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * The url + */ + char *url; + + /** + * Error response message + */ + char *emsg; + + /** + * Reponse code + */ + int response_code; + + /** + * Response object + */ + struct GNUNET_JSONAPI_Document *resp_object; + +}; + +/** + * Cleanup lookup handle + * @param handle Handle to clean up + */ +static void +cleanup_handle (struct RequestHandle *handle) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp; + struct EgoEntry *ego_entry; + struct EgoEntry *ego_tmp; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + if (NULL != handle->resp_object) + GNUNET_JSONAPI_document_delete (handle->resp_object); + if (NULL != handle->timeout_task) + GNUNET_SCHEDULER_cancel (handle->timeout_task); + if (NULL != handle->identity_handle) + GNUNET_IDENTITY_disconnect (handle->identity_handle); + if (NULL != handle->attr_it) + GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); + if (NULL != handle->ticket_it) + GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); + if (NULL != handle->idp) + GNUNET_RECLAIM_disconnect (handle->idp); + if (NULL != handle->url) + GNUNET_free (handle->url); + if (NULL != handle->emsg) + GNUNET_free (handle->emsg); + if (NULL != handle->namestore_handle) + GNUNET_NAMESTORE_disconnect (handle->namestore_handle); + if ( NULL != handle->attr_list ) + { + for (claim_entry = handle->attr_list->list_head; + NULL != claim_entry;) + { + claim_tmp = claim_entry; + claim_entry = claim_entry->next; + GNUNET_free(claim_tmp->claim); + GNUNET_free(claim_tmp); + } + GNUNET_free (handle->attr_list); + } + for (ego_entry = handle->ego_head; + NULL != ego_entry;) + { + ego_tmp = ego_entry; + ego_entry = ego_entry->next; + GNUNET_free (ego_tmp->identifier); + GNUNET_free (ego_tmp->keystring); + GNUNET_free (ego_tmp); + } + if (NULL != handle->attr_it) + { + GNUNET_free(handle->attr_it); + } + GNUNET_free (handle); +} + +static void +cleanup_handle_delayed (void *cls) +{ + cleanup_handle (cls); +} + + +/** + * Task run on error, sends error message. Cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + char *json_error; + + GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", + handle->emsg); + if ( 0 == handle->response_code ) + { + handle->response_code = MHD_HTTP_BAD_REQUEST; + } + resp = GNUNET_REST_create_response (json_error); + MHD_add_response_header (resp, "Content-Type", "application/json"); + handle->proc (handle->proc_cls, resp, handle->response_code); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + GNUNET_free (json_error); +} + + +/** + * Task run on timeout, sends error message. Cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_timeout (void *cls) +{ + struct RequestHandle *handle = cls; + + handle->timeout_task = NULL; + do_error (handle); +} + + +static void +collect_error_cb (void *cls) +{ + struct RequestHandle *handle = cls; + + do_error (handle); +} + +static void +finished_cont (void *cls, + int32_t success, + const char *emsg) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + + resp = GNUNET_REST_create_response (emsg); + if (GNUNET_OK != success) + { + 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); +} + + +/** + * 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); + 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); +} + + +/** + * Collect all attributes for an ego + * + */ +static void +ticket_collect (void *cls, + const struct GNUNET_RECLAIM_Ticket *ticket) +{ + 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_RECLAIM_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; + 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); + 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) + { + //Done + 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 (ego_entry->ego); + handle->idp = GNUNET_RECLAIM_connect (cfg); + handle->ticket_it = GNUNET_RECLAIM_ticket_iteration_start (handle->idp, + priv_key, + &collect_error_cb, + handle, + &ticket_collect, + handle, + &collect_finished_cb, + handle); +} + + +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; + const char* exp_str; + + struct RequestHandle *handle = cls; + struct EgoEntry *ego_entry; + struct MHD_Response *resp; + struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute; + struct GNUNET_JSONAPI_Document *json_obj; + struct GNUNET_JSONAPI_Resource *json_res; + struct GNUNET_TIME_Relative exp; + char term_data[handle->rest_handle->data_size+1]; + json_t *value_json; + json_t *data_json; + json_t *exp_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_RECLAIM_ATTRIBUTES) >= + strlen (handle->url)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_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, + "Identity unknown (%s)\n", identity); + GNUNET_JSONAPI_document_delete (json_obj); + return; + } + identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); + + if (0 >= handle->rest_handle->data_size) + { + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + 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, + "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_RECLAIM_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); + exp_json = GNUNET_JSONAPI_resource_read_attr (json_res, + "exp"); + exp_str = json_string_value (exp_json); + if (NULL == exp_str) { + exp = GNUNET_TIME_UNIT_HOURS; + } else { + if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str, + &exp)) { + exp = GNUNET_TIME_UNIT_HOURS; + } + } + + value_json = GNUNET_JSONAPI_resource_read_attr (json_res, + "value"); + value_str = json_string_value (value_json); + attribute = GNUNET_RECLAIM_ATTRIBUTE_claim_new (name_str, + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, + value_str, + strlen (value_str) + 1); + handle->idp = GNUNET_RECLAIM_connect (cfg); + handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp, + identity_priv, + attribute, + &exp, + &finished_cont, + handle); + GNUNET_free (attribute); + GNUNET_JSONAPI_document_delete (json_obj); +} + + + +/** + * Collect all attributes for an ego + * + */ +static void +attr_collect (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) +{ + struct GNUNET_JSONAPI_Resource *json_resource; + struct RequestHandle *handle = cls; + json_t *value; + char* tmp_value; + + if ((NULL == attr->name) || (NULL == attr->data)) + { + GNUNET_RECLAIM_get_attributes_next (handle->attr_it); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", + attr->name); + json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE, + attr->name); + GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); + + tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, + attr->data, + attr->data_size); + + value = json_string (tmp_value); + + GNUNET_JSONAPI_resource_add_attr (json_resource, + "value", + value); + json_decref (value); + GNUNET_free(tmp_value); + GNUNET_RECLAIM_get_attributes_next (handle->attr_it); +} + + + +/** + * List attributes for identity request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +list_attribute_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; + char *identity; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n", + handle->url); + if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= + strlen (handle->url)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 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) + { + //Done + 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 (ego_entry->ego); + handle->idp = GNUNET_RECLAIM_connect (cfg); + handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp, + priv_key, + &collect_error_cb, + handle, + &attr_collect, + handle, + &collect_finished_cb, + handle); +} + + +static void +revoke_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_RECLAIM_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) + { + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + 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, + "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, + "issuer"); + 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.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); + + handle->idp = GNUNET_RECLAIM_connect (cfg); + handle->idp_op = GNUNET_RECLAIM_ticket_revoke (handle->idp, + identity_priv, + &ticket, + &finished_cont, + handle); + GNUNET_JSONAPI_document_delete (json_obj); +} + +static void +consume_cont (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) +{ + struct RequestHandle *handle = cls; + struct GNUNET_JSONAPI_Resource *json_resource; + json_t *value; + + 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_RECLAIM_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); +} + +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_RECLAIM_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) + { + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + 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, + "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)); + + 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_RECLAIM_connect (cfg); + handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp, + identity_priv, + &ticket, + &consume_cont, + handle); + GNUNET_JSONAPI_document_delete (json_obj); +} + + + +/** + * Respond to OPTIONS request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + //For now, independent of path return all options + resp = GNUNET_REST_create_response (NULL); + MHD_add_response_header (resp, + "Access-Control-Allow-Methods", + allow_methods); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + cleanup_handle (handle); + return; +} + +/** + * Handle rest request + * + * @param handle the request handle + */ +static void +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_RECLAIM_ATTRIBUTES, &list_attribute_cont}, + {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_RECLAIM_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_RECLAIM, + &options_cont}, + GNUNET_REST_HANDLER_END + }; + + if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, + handlers, + &err, + handle)) + { + handle->response_code = err.error_code; + GNUNET_SCHEDULER_add_now (&do_error, handle); + } +} + +/** + * If listing is enabled, prints information about the egos. + * + * This function is initially called for all egos and then again + * whenever a ego's identifier changes or if it is deleted. At the + * end of the initial pass over all egos, the function is once called + * with 'NULL' for 'ego'. That does NOT mean that the callback won't + * be invoked in the future or that there was an error. + * + * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', + * this function is only called ONCE, and 'NULL' being passed in + * 'ego' does indicate an error (i.e. name is taken or no default + * value is known). If 'ego' is non-NULL and if '*ctx' + * is set in those callbacks, the value WILL be passed to a subsequent + * call to the identity callback of 'GNUNET_IDENTITY_connect' (if + * that one was not NULL). + * + * When an identity is renamed, this function is called with the + * (known) ego but the NEW identifier. + * + * When an identity is deleted, this function is called with the + * (known) ego and "NULL" for the 'identifier'. In this case, + * the 'ego' is henceforth invalid (and the 'ctx' should also be + * cleaned up). + * + * @param cls closure + * @param ego ego handle + * @param ctx context for application to store data for this ego + * (during the lifetime of this process, initially NULL) + * @param identifier identifier assigned by the user for this ego, + * NULL if the user just deleted the ego and it + * must thus no longer be used + */ +static void +list_ego (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *identifier) +{ + struct RequestHandle *handle = cls; + struct EgoEntry *ego_entry; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + + if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) + { + handle->state = ID_REST_STATE_POST_INIT; + init_cont (handle); + return; + } + if (ID_REST_STATE_INIT == handle->state) { + ego_entry = GNUNET_new (struct EgoEntry); + GNUNET_IDENTITY_ego_get_public_key (ego, &pk); + ego_entry->keystring = + GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->ego = ego; + ego_entry->identifier = GNUNET_strdup (identifier); + GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); + } + +} + +static void +rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + handle->response_code = 0; + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + handle->state = ID_REST_STATE_INIT; + handle->rest_handle = rest_handle; + + 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, + "Connecting...\n"); + handle->identity_handle = GNUNET_IDENTITY_connect (cfg, + &list_ego, + handle); + handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); + handle->timeout_task = + GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_timeout, + handle); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connected\n"); +} + +/** + * Entry point for the plugin. + * + * @param cls Config info + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_rest_reclaim_init (void *cls) +{ + static struct Plugin plugin; + struct GNUNET_REST_Plugin *api; + + cfg = cls; + 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_RECLAIM; + api->process_request = &rest_identity_process_request; + GNUNET_asprintf (&allow_methods, + "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Identity Provider 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_reclaim_done (void *cls) +{ + struct GNUNET_REST_Plugin *api = cls; + struct Plugin *plugin = api->cls; + plugin->cfg = NULL; + + GNUNET_free_non_null (allow_methods); + GNUNET_free (api); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Identity Provider REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_reclaim.c */ diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf new file mode 100644 index 000000000..e93899e05 --- /dev/null +++ b/src/reclaim/reclaim.conf @@ -0,0 +1,23 @@ +[reclaim] +START_ON_DEMAND = NO +RUN_PER_USER = YES +#PORT = 2108 +HOSTNAME = localhost +BINARY = gnunet-service-reclaim +ACCEPT_FROM = 127.0.0.1; +ACCEPT_FROM6 = ::1; +UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-reclaim.sock +UNIX_MATCH_UID = NO +UNIX_MATCH_GID = YES +TOKEN_EXPIRATION_INTERVAL = 30 m +DATABASE = sqlite + +[reclaim-rest-plugin] +#ADDRESS = https://identity.gnu:8000#/login +ADDRESS = https://reclaim.ui/#/login +PSW = secret +JWT_SECRET = secret +EXPIRATION_TIME = 3600 + +[reclaim-sqlite] +FILENAME = $GNUNET_DATA_HOME/reclaim/sqlite.db diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h new file mode 100644 index 000000000..d2c84686d --- /dev/null +++ b/src/reclaim/reclaim.h @@ -0,0 +1,410 @@ +/* + This file is part of GNUnet. + Copyright (C) 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @author Martin Schanzenbach + * @file reclaim/reclaim.h + * + * @brief Common type definitions for the identity provider + * service and API. + */ +#ifndef RECLAIM_H +#define RECLAIM_H + +#include "gnunet_common.h" + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Use to store an identity attribute + */ +struct AttributeStoreMessage +{ + /** + * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * The length of the attribute + */ + uint32_t attr_len GNUNET_PACKED; + + /** + * The expiration interval of the attribute + */ + uint64_t exp GNUNET_PACKED; + + /** + * Identity + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /* followed by the serialized attribute */ + +}; + +/** + * Attribute store response message + */ +struct AttributeStoreResultMessage +{ + /** + * 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_RECLAIM_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_RECLAIM_ATTRIBUTE_ITERATION_STOP + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + +}; + +/** + * Start a ticket iteration for the given identity + */ +struct TicketIterationStartMessage +{ + /** + * Message + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * Identity. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey identity; + + /** + * Identity is audience or issuer + */ + uint32_t is_audience GNUNET_PACKED; +}; + + +/** + * Ask for next result of ticket iteration for the given operation + */ +struct TicketIterationNextMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + +}; + + +/** + * Stop ticket iteration for the given operation + */ +struct TicketIterationStopMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + +}; + + + +/** + * Ticket issue message + */ +struct IssueTicketMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * Identity. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * Requesting party. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey rp; + + /** + * length of serialized attribute list + */ + uint32_t attr_len GNUNET_PACKED; + + //Followed by a serialized attribute list +}; + +/** + * Ticket revoke message + */ +struct RevokeTicketMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * Identity. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * 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_RECLAIM_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; +}; + + +/** + * Ticket result message + */ +struct TicketResultMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_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_RECLAIM_CONSUME_TICKET + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * 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 + */ + uint16_t attrs_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 attributes data + */ +}; + + + +GNUNET_NETWORK_STRUCT_END + +#endif diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c new file mode 100644 index 000000000..3f1584ccd --- /dev/null +++ b/src/reclaim/reclaim_api.c @@ -0,0 +1,1383 @@ +/* + This file is part of GNUnet. + Copyright (C) 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file reclaim/reclaim_api.c + * @brief api to interact with the reclaim service + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_protocols.h" +#include "gnunet_mq_lib.h" +#include "gnunet_reclaim_service.h" +#include "gnunet_reclaim_attribute_lib.h" +#include "reclaim.h" + +#define LOG(kind,...) GNUNET_log_from (kind, "reclaim-api",__VA_ARGS__) + + +/** + * Handle for an operation with the service. + */ +struct GNUNET_RECLAIM_Operation +{ + + /** + * Main handle. + */ + struct GNUNET_RECLAIM_Handle *h; + + /** + * We keep operations in a DLL. + */ + struct GNUNET_RECLAIM_Operation *next; + + /** + * We keep operations in a DLL. + */ + struct GNUNET_RECLAIM_Operation *prev; + + /** + * Message to send to the service. + * Allocated at the end of this struct. + */ + const struct GNUNET_MessageHeader *msg; + + /** + * Continuation to invoke after attribute store call + */ + GNUNET_RECLAIM_ContinuationWithStatus as_cb; + + /** + * Attribute result callback + */ + GNUNET_RECLAIM_AttributeResult ar_cb; + + /** + * Revocation result callback + */ + GNUNET_RECLAIM_ContinuationWithStatus rvk_cb; + + /** + * Ticket result callback + */ + GNUNET_RECLAIM_TicketCallback tr_cb; + + /** + * Envelope with the message for this queue entry. + */ + struct GNUNET_MQ_Envelope *env; + + /** + * request id + */ + uint32_t r_id; + + /** + * Closure for @e cont or @e cb. + */ + void *cls; + +}; + +/** + * Handle for a ticket iterator operation + */ +struct GNUNET_RECLAIM_TicketIterator +{ + + /** + * Kept in a DLL. + */ + struct GNUNET_RECLAIM_TicketIterator *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_RECLAIM_TicketIterator *prev; + + /** + * Main handle to access the idp. + */ + struct GNUNET_RECLAIM_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_RECLAIM_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_RECLAIM_AttributeIterator +{ + + /** + * Kept in a DLL. + */ + struct GNUNET_RECLAIM_AttributeIterator *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_RECLAIM_AttributeIterator *prev; + + /** + * Main handle to access the idp. + */ + struct GNUNET_RECLAIM_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_RECLAIM_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. + */ +struct GNUNET_RECLAIM_Handle +{ + /** + * Configuration to use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Socket (if available). + */ + struct GNUNET_CLIENT_Connection *client; + + /** + * Closure for 'cb'. + */ + void *cb_cls; + + /** + * Head of active operations. + */ + struct GNUNET_RECLAIM_Operation *op_head; + + /** + * Tail of active operations. + */ + struct GNUNET_RECLAIM_Operation *op_tail; + + /** + * Head of active iterations + */ + struct GNUNET_RECLAIM_AttributeIterator *it_head; + + /** + * Tail of active iterations + */ + struct GNUNET_RECLAIM_AttributeIterator *it_tail; + + /** + * Head of active iterations + */ + struct GNUNET_RECLAIM_TicketIterator *ticket_it_head; + + /** + * Tail of active iterations + */ + struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail; + + + /** + * Currently pending transmission request, or NULL for none. + */ + struct GNUNET_CLIENT_TransmitHandle *th; + + /** + * Task doing exponential back-off trying to reconnect. + */ + struct GNUNET_SCHEDULER_Task * reconnect_task; + + /** + * Time for next connect retry. + */ + struct GNUNET_TIME_Relative reconnect_backoff; + + /** + * Connection to service (if available). + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Request Id generator. Incremented by one for each request. + */ + uint32_t r_id_gen; + + /** + * Are we polling for incoming messages right now? + */ + int in_receive; + +}; + +/** + * Try again to connect to the service. + * + * @param h handle to the reclaim service. + */ +static void +reconnect (struct GNUNET_RECLAIM_Handle *h); + +/** + * Reconnect + * + * @param cls the handle + */ +static void +reconnect_task (void *cls) +{ + struct GNUNET_RECLAIM_Handle *handle = cls; + + handle->reconnect_task = NULL; + reconnect (handle); +} + + +/** + * Disconnect from service and then reconnect. + * + * @param handle our service + */ +static void +force_reconnect (struct GNUNET_RECLAIM_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); +} + +/** + * Free @a it. + * + * @param it entry to free + */ +static void +free_it (struct GNUNET_RECLAIM_AttributeIterator *it) +{ + struct GNUNET_RECLAIM_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); +} + +static void +free_op (struct GNUNET_RECLAIM_Operation* op) +{ + if (NULL == op) + return; + if (NULL != op->env) + GNUNET_MQ_discard (op->env); + GNUNET_free(op); +} + + +/** + * 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_GNS_Handle *` + * @param error error code + */ +static void +mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_RECLAIM_Handle *handle = cls; + force_reconnect (handle); +} + +/** + * 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_RECLAIM_Handle *h = cls; + struct GNUNET_RECLAIM_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); + free_op (op); + +} + + +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT + * + * @param cls + * @param msg the message we received + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +check_consume_ticket_result (void *cls, + const struct ConsumeTicketResultMessage *msg) +{ + size_t msg_len; + size_t attrs_len; + + 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; + } + return GNUNET_OK; +} + + +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_RECLAIM_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_RECLAIM_Handle *h = cls; + struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_ClaimList *attrs; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + attrs = GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_list_destroy (attrs); + } + } + if (NULL != op) + { + op->ar_cb (op->cls, + NULL, + NULL); + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + free_op (op); + } + return; + } + GNUNET_assert (0); +} + + +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT + * + * @param cls + * @param msg the message we received + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +check_attribute_result (void *cls, + const struct AttributeResultMessage *msg) +{ + 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; + } + return GNUNET_OK; +} + + +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT + * + * @param cls + * @param msg the message we received + */ +static void +handle_attribute_result (void *cls, + const struct AttributeResultMessage *msg) +{ + static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy; + struct GNUNET_RECLAIM_Handle *h = cls; + struct GNUNET_RECLAIM_AttributeIterator *it; + struct GNUNET_RECLAIM_Operation *op; + 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 == it) && (NULL == op)) + return; + + 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); + free_op (op); + + } + return; + } + + { + struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr; + attr = GNUNET_RECLAIM_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_RECLAIM_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; +} + + + +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT + * + * @param cls + * @param msg the message we received + */ +static void +handle_ticket_result (void *cls, + const struct TicketResultMessage *msg) +{ + struct GNUNET_RECLAIM_Handle *handle = cls; + struct GNUNET_RECLAIM_Operation *op; + struct GNUNET_RECLAIM_TicketIterator *it; + const struct GNUNET_RECLAIM_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; + for (it = handle->ticket_it_head; NULL != it; it = it->next) + if (it->r_id == r_id) + break; + if ((NULL == op) && (NULL == it)) + return; + msg_len = ntohs (msg->header.size); + if (NULL != op) + { + 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_RECLAIM_Ticket *)&msg[1]; + if (NULL != op->tr_cb) + op->tr_cb (op->cls, ticket); + } + free_op (op); + return; + } 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_RECLAIM_Ticket *)&msg[1]; + if (NULL != it->tr_cb) + it->tr_cb (it->cls, ticket); + } + return; + } + GNUNET_break (0); +} + + +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_RECLAIM_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_RECLAIM_Handle *h = cls; + struct GNUNET_RECLAIM_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); + { + if (NULL != op->rvk_cb) + { + op->rvk_cb (op->cls, + success, + NULL); + } + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + free_op (op); + return; + } + GNUNET_assert (0); +} + + + +/** + * Try again to connect to the service. + * + * @param h handle to the reclaim service. + */ +static void +reconnect (struct GNUNET_RECLAIM_Handle *h) +{ + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_fixed_size (attribute_store_response, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE_RESPONSE, + struct AttributeStoreResultMessage, + h), + GNUNET_MQ_hd_var_size (attribute_result, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT, + struct AttributeResultMessage, + h), + GNUNET_MQ_hd_var_size (ticket_result, + GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT, + struct TicketResultMessage, + h), + GNUNET_MQ_hd_var_size (consume_ticket_result, + GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT, + struct ConsumeTicketResultMessage, + h), + GNUNET_MQ_hd_fixed_size (revoke_ticket_result, + GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT, + struct RevokeTicketResultMessage, + h), + GNUNET_MQ_handler_end () + }; + struct GNUNET_RECLAIM_Operation *op; + + GNUNET_assert (NULL == h->mq); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Connecting to reclaim service.\n"); + + h->mq = GNUNET_CLIENT_connect (h->cfg, + "reclaim", + handlers, + &mq_error_handler, + h); + if (NULL == h->mq) + return; + for (op = h->op_head; NULL != op; op = op->next) + GNUNET_MQ_send_copy (h->mq, + op->env); +} + + +/** + * Connect to the reclaim service. + * + * @param cfg the configuration to use + * @return handle to use + */ +struct GNUNET_RECLAIM_Handle * +GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_RECLAIM_Handle *h; + + h = GNUNET_new (struct GNUNET_RECLAIM_Handle); + h->cfg = cfg; + reconnect (h); + if (NULL == h->mq) + { + GNUNET_free (h); + return NULL; + } + return h; +} + + +/** + * 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 + * the operation. + * + * @param op operation to cancel + */ +void +GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op) +{ + struct GNUNET_RECLAIM_Handle *h = op->h; + + GNUNET_CONTAINER_DLL_remove (h->op_head, + h->op_tail, + op); + free_op (op); +} + + +/** + * Disconnect from service + * + * @param h handle to destroy + */ +void +GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h) +{ + GNUNET_assert (NULL != h); + if (NULL != h->mq) + { + GNUNET_MQ_destroy (h->mq); + h->mq = NULL; + } + if (NULL != h->reconnect_task) + { + GNUNET_SCHEDULER_cancel (h->reconnect_task); + h->reconnect_task = NULL; + } + GNUNET_assert (NULL == h->op_head); + GNUNET_free (h); +} + +/** + * Store an attribute. If the attribute is already present, + * it is replaced with the new attribute. + * + * @param h handle to the reclaim + * @param pkey private key of the identity + * @param attr the attribute value + * @param exp_interval the relative expiration interval for the attribute + * @param cont continuation to call when done + * @param cont_cls closure for @a cont + * @return handle to abort the request + */ +struct GNUNET_RECLAIM_Operation * +GNUNET_RECLAIM_attribute_store (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, + const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, + const struct GNUNET_TIME_Relative *exp_interval, + GNUNET_RECLAIM_ContinuationWithStatus cont, + void *cont_cls) +{ + struct GNUNET_RECLAIM_Operation *op; + struct AttributeStoreMessage *sam; + size_t attr_len; + + op = GNUNET_new (struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_serialize_get_size (attr); + op->env = GNUNET_MQ_msg_extra (sam, + attr_len, + GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE); + sam->identity = *pkey; + sam->id = htonl (op->r_id); + sam->exp = GNUNET_htonll (exp_interval->rel_value_us); + + GNUNET_RECLAIM_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_RECLAIM_Handle` + * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and + * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once + * immediately, and then again after + * #GNUNET_RECLAIM_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_RECLAIM_AttributeIterator * +GNUNET_RECLAIM_get_attributes_start (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_AttributeResult proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls) +{ + struct GNUNET_RECLAIM_AttributeIterator *it; + struct GNUNET_MQ_Envelope *env; + struct AttributeIterationStartMessage *msg; + uint32_t rid; + + rid = h->r_id_gen++; + it = GNUNET_new (struct GNUNET_RECLAIM_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_RECLAIM_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; +} + + +/** + * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it) +{ + struct GNUNET_RECLAIM_Handle *h = it->h; + struct AttributeIterationNextMessage *msg; + struct GNUNET_MQ_Envelope *env; + + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_RECLAIM_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_RECLAIM_disconnect. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it) +{ + struct GNUNET_RECLAIM_Handle *h = it->h; + struct GNUNET_MQ_Envelope *env; + struct AttributeIterationStopMessage *msg; + + if (NULL != h->mq) + { + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_RECLAIM_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_RECLAIM_authorization_ticket_consume to consume the ticket + * and retrieve the attributes specified in the AttributeList. + * + * @param h the reclaim 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_RECLAIM_Operation * +GNUNET_RECLAIM_ticket_issue (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, + const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + GNUNET_RECLAIM_TicketCallback cb, + void *cb_cls) +{ + struct GNUNET_RECLAIM_Operation *op; + struct IssueTicketMessage *tim; + size_t attr_len; + + op = GNUNET_new (struct GNUNET_RECLAIM_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_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs); + op->env = GNUNET_MQ_msg_extra (tim, + attr_len, + GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET); + tim->identity = *iss; + tim->rp = *rp; + tim->id = htonl (op->r_id); + + GNUNET_RECLAIM_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 reclaim 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_RECLAIM_Operation * +GNUNET_RECLAIM_ticket_consume (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + const struct GNUNET_RECLAIM_Ticket *ticket, + GNUNET_RECLAIM_AttributeResult cb, + void *cb_cls) +{ + struct GNUNET_RECLAIM_Operation *op; + struct ConsumeTicketMessage *ctm; + + op = GNUNET_new (struct GNUNET_RECLAIM_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_RECLAIM_Ticket), + GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET); + ctm->identity = *identity; + ctm->id = htonl (op->r_id); + + GNUNET_memcpy ((char*)&ctm[1], + ticket, + sizeof (const struct GNUNET_RECLAIM_Ticket)); + + if (NULL != h->mq) + GNUNET_MQ_send_copy (h->mq, + op->env); + return op; + +} + + +/** + * Lists all tickets that have been issued to remote + * identites (relying parties) + * + * @param h the reclaim 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 + */ +struct GNUNET_RECLAIM_TicketIterator * +GNUNET_RECLAIM_ticket_iteration_start (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_TicketCallback proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls) +{ + struct GNUNET_RECLAIM_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_RECLAIM_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_RECLAIM_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; + +} + + +/** + * Lists all tickets that have been issued to remote + * identites (relying parties) + * + * @param h the reclaim 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 + */ +struct GNUNET_RECLAIM_TicketIterator * +GNUNET_RECLAIM_ticket_iteration_start_rp (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + GNUNET_SCHEDULER_TaskCallback error_cb, + void *error_cb_cls, + GNUNET_RECLAIM_TicketCallback proc, + void *proc_cls, + GNUNET_SCHEDULER_TaskCallback finish_cb, + void *finish_cb_cls) +{ + struct GNUNET_RECLAIM_TicketIterator *it; + struct GNUNET_MQ_Envelope *env; + struct TicketIterationStartMessage *msg; + uint32_t rid; + + rid = h->r_id_gen++; + it = GNUNET_new (struct GNUNET_RECLAIM_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_RECLAIM_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; + + +} + +/** + * Calls the record processor specified in #GNUNET_RECLAIM_ticket_iteration_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it) +{ + struct GNUNET_RECLAIM_Handle *h = it->h; + struct TicketIterationNextMessage *msg; + struct GNUNET_MQ_Envelope *env; + + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_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_RECLAIM_disconnect. + * + * @param it the iterator + */ +void +GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it) +{ + struct GNUNET_RECLAIM_Handle *h = it->h; + struct GNUNET_MQ_Envelope *env; + struct TicketIterationStopMessage *msg; + + if (NULL != h->mq) + { + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_RECLAIM_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 reclaim 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_RECLAIM_Operation * +GNUNET_RECLAIM_ticket_revoke (struct GNUNET_RECLAIM_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, + const struct GNUNET_RECLAIM_Ticket *ticket, + GNUNET_RECLAIM_ContinuationWithStatus cb, + void *cb_cls) +{ + struct GNUNET_RECLAIM_Operation *op; + struct RevokeTicketMessage *msg; + uint32_t rid; + + rid = h->r_id_gen++; + op = GNUNET_new (struct GNUNET_RECLAIM_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); + op->env = GNUNET_MQ_msg_extra (msg, + sizeof (struct GNUNET_RECLAIM_Ticket), + GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET); + msg->id = htonl (rid); + msg->identity = *identity; + GNUNET_memcpy (&msg[1], + ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + if (NULL != h->mq) { + GNUNET_MQ_send (h->mq, + op->env); + op->env = NULL; + } + return op; +} + + + +/* end of reclaim_api.c */ diff --git a/src/reclaim/test_reclaim.sh b/src/reclaim/test_reclaim.sh new file mode 100755 index 000000000..311f5382a --- /dev/null +++ b/src/reclaim/test_reclaim.sh @@ -0,0 +1,31 @@ +#!/bin/bash +#trap "gnunet-arm -e -c test_reclaim_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_reclaim.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_reclaim.conf +gnunet-identity -C testego -c test_reclaim.conf +valgrind gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf +gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf +gnunet-reclaim -e testego -D -c test_reclaim.conf +gnunet-arm -e -c test_reclaim.conf diff --git a/src/reclaim/test_reclaim_attribute.sh b/src/reclaim/test_reclaim_attribute.sh new file mode 100755 index 000000000..39bd715b7 --- /dev/null +++ b/src/reclaim/test_reclaim_attribute.sh @@ -0,0 +1,40 @@ +#!/bin/bash +trap "gnunet-arm -e -c test_reclaim.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_reclaim.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_reclaim.conf +#gnunet-arm -i rest -c test_reclaim.conf +gnunet-identity -C testego -c test_reclaim.conf +gnunet-identity -C rpego -c test_reclaim.conf +TEST_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep testego | awk '{print $3}') +gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf +gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf > /dev/null 2>&1 +if test $? != 0 +then + echo "Failed." + exit 1 +fi + +#curl localhost:7776/reclaim/attributes/testego +gnunet-arm -e -c test_reclaim.conf diff --git a/src/reclaim/test_reclaim_consume.sh b/src/reclaim/test_reclaim_consume.sh new file mode 100755 index 000000000..36c8052d0 --- /dev/null +++ b/src/reclaim/test_reclaim_consume.sh @@ -0,0 +1,43 @@ +#!/bin/bash +trap "gnunet-arm -e -c test_reclaim.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_reclaim.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_reclaim.conf +#gnunet-arm -i rest -c test_reclaim.conf +gnunet-identity -C testego -c test_reclaim.conf +gnunet-identity -C rpego -c test_reclaim.conf +SUBJECT_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep rpego | awk '{print $3}') +TEST_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep testego | awk '{print $3}') +gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf +gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf +TICKET=$(gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf | awk '{print $1}') +gnunet-reclaim -e rpego -C $TICKET -c test_reclaim.conf > /dev/null 2>&1 + +if test $? != 0 +then + "Failed." + exit 1 +fi +#curl http://localhost:7776/reclaim/tickets/testego +gnunet-arm -e -c test_reclaim.conf diff --git a/src/reclaim/test_reclaim_defaults.conf b/src/reclaim/test_reclaim_defaults.conf new file mode 100644 index 000000000..a9a197dea --- /dev/null +++ b/src/reclaim/test_reclaim_defaults.conf @@ -0,0 +1,24 @@ +@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf + +[PATHS] +GNUNET_TEST_HOME = $GNUNET_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/reclaim/test_reclaim_issue.sh b/src/reclaim/test_reclaim_issue.sh new file mode 100755 index 000000000..6a71470e1 --- /dev/null +++ b/src/reclaim/test_reclaim_issue.sh @@ -0,0 +1,42 @@ +#!/bin/bash +trap "gnunet-arm -e -c test_reclaim.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_reclaim.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_reclaim.conf +#gnunet-arm -i rest -c test_reclaim.conf +gnunet-identity -C testego -c test_reclaim.conf +gnunet-identity -C rpego -c test_reclaim.conf +SUBJECT_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep rpego | awk '{print $3}') +TEST_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep testego | awk '{print $3}') +gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf > /dev/null 2>&1 +gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf > /dev/null 2>&1 +#gnunet-reclaim -e testego -D -c test_reclaim.conf +gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf > /dev/null 2>&1 +if test $? != 0 +then + echo "Failed." + exit 1 +fi +#curl http://localhost:7776/reclaim/attributes/testego +gnunet-arm -e -c test_reclaim.conf diff --git a/src/reclaim/test_reclaim_revoke.sh b/src/reclaim/test_reclaim_revoke.sh new file mode 100755 index 000000000..595752fd8 --- /dev/null +++ b/src/reclaim/test_reclaim_revoke.sh @@ -0,0 +1,65 @@ +#!/bin/bash +trap "gnunet-arm -e -c test_reclaim.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_reclaim.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_reclaim.conf 2&>1 > /dev/null +gnunet-identity -C alice -c test_reclaim.conf +gnunet-identity -C bob -c test_reclaim.conf +gnunet-identity -C eve -c test_reclaim.conf +ALICE_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep alice | awk '{print $3}') +BOB_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep bob | awk '{print $3}') +EVE_KEY=$(gnunet-identity -d -c test_reclaim.conf | grep eve | awk '{print $3}') + +gnunet-reclaim -e alice -E 15s -a email -V john@doe.gnu -c test_reclaim.conf +gnunet-reclaim -e alice -E 15s -a name -V John -c test_reclaim.conf +TICKET_BOB=$(gnunet-reclaim -e alice -i "email,name" -r $BOB_KEY -c test_reclaim.conf | awk '{print $1}') +#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf +TICKET_EVE=$(gnunet-reclaim -e alice -i "email" -r $EVE_KEY -c test_reclaim.conf | awk '{print $1}') + +#echo "Consuming $TICKET" +#gnunet-reclaim -e eve -C $TICKET_EVE -c test_reclaim.conf +gnunet-reclaim -e alice -R $TICKET_EVE -c test_reclaim.conf + +#sleep 6 + +gnunet-reclaim -e eve -C $TICKET_EVE -c test_reclaim.conf 2&>1 >/dev/null +if test $? == 0 +then + echo "Eve can still resolve attributes..." + gnunet-arm -e -c test_reclaim.conf + exit 1 +fi + +gnunet-arm -e -c test_reclaim.conf +gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null + +gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf 2&>1 >/dev/null +if test $? != 0 +then + echo "Bob cannot resolve attributes..." + gnunet-arm -e -c test_reclaim.conf + exit 1 +fi + +gnunet-arm -e -c test_reclaim.conf -- cgit v1.2.3 From f89b96d1a0ffe8359fbbda6ea3276a030a701e91 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Fri, 20 Jul 2018 08:39:06 +0200 Subject: remove trust check; we don't need (and thus implicity may slighly deviate from rfc) --- src/reclaim/plugin_rest_openid_connect.c | 111 +------------------------------ 1 file changed, 3 insertions(+), 108 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index abb3f59f5..9b7cf0205 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -229,12 +229,6 @@ struct OIDC_Variables */ char *client_id; - /** - * GNUNET_YES if there is a delegation to - * this RP or if it is a local identity - */ - int is_client_trusted; - /** * The OIDC redirect uri */ @@ -1026,62 +1020,6 @@ login_check (void *cls) } } -/** - * Searches for client_id in namestore. If found trust status stored in handle - * Else continues to search - * - * @param handle the RequestHandle - */ -static void -namestore_iteration_callback ( - void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *rname, unsigned int rd_len, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey; - struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey; - int i; - - for (i = 0; i < rd_len; i++) - { - if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type ) - continue; - - if ( NULL != handle->oidc->login_identity ) - { - GNUNET_CRYPTO_ecdsa_public_key_from_string ( - handle->oidc->login_identity, - strlen (handle->oidc->login_identity), - &login_identity_pkey); - GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, - ¤t_zone_pkey); - - if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - if ( 0 == memcmp (&login_identity_pkey, ¤t_zone_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->oidc->is_client_trusted = GNUNET_YES; - } - } - } - else - { - if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->oidc->is_client_trusted = GNUNET_YES; - } - } - } - - GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it, - 1); -} - - /** * Iteration over all results finished, build final * response. @@ -1089,7 +1027,7 @@ namestore_iteration_callback ( * @param cls the `struct RequestHandle` */ static void -namestore_iteration_finished (void *cls) +build_authz_response (void *cls) { struct RequestHandle *handle = cls; struct GNUNET_HashCode cache_key; @@ -1099,25 +1037,6 @@ namestore_iteration_finished (void *cls) int number_of_ignored_parameter, iterator; - handle->ego_entry = handle->ego_entry->next; - - if(NULL != handle->ego_entry) - { - handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); - handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key, - &oidc_iteration_error, handle, &namestore_iteration_callback, handle, - &namestore_iteration_finished, handle); - return; - } - if (GNUNET_NO == handle->oidc->is_client_trusted) - { - handle->emsg = GNUNET_strdup("unauthorized_client"); - handle->edesc = GNUNET_strdup("The client is not authorized to request an " - "authorization code using this method."); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - // REQUIRED value: redirect_uri GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), &cache_key); @@ -1246,9 +1165,6 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, { struct RequestHandle *handle = cls; struct GNUNET_HashCode cache_key; - struct EgoEntry *tmp_ego; - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; cookie_identity_interpretation(handle); @@ -1302,29 +1218,8 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, handle->ego_entry = handle->ego_head; handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); - handle->oidc->is_client_trusted = GNUNET_NO; - - //First check if client_id is one of our egos; TODO: handle other TLD cases: Delegation, from config - for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) - { - priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); - GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, - &pkey); - if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey, - sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) - { - handle->tld = GNUNET_strdup (tmp_ego->identifier); - handle->oidc->is_client_trusted = GNUNET_YES; - handle->ego_entry = handle->ego_tail; - } - } - - - // Checks if client_id is valid: - handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start ( - handle->namestore_handle, &handle->priv_key, &oidc_iteration_error, - handle, &namestore_iteration_callback, handle, - &namestore_iteration_finished, handle); + + GNUNET_SCHEDULER_add_now (&build_authz_response, handle); } /** -- cgit v1.2.3 From f28f0dc7316ead8735b7e68cd1bd61f3959fa759 Mon Sep 17 00:00:00 2001 From: Nils Gillmann Date: Fri, 20 Jul 2018 07:11:55 +0000 Subject: include/gnunet_abe_lib.h: typo fix in comment Signed-off-by: Nils Gillmann --- src/include/gnunet_abe_lib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/include/gnunet_abe_lib.h b/src/include/gnunet_abe_lib.h index d380c9b03..554d4488b 100644 --- a/src/include/gnunet_abe_lib.h +++ b/src/include/gnunet_abe_lib.h @@ -87,7 +87,7 @@ GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key, * 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) + * @param delete_pub GNUNET_YES if the public key should also be freed (bug in gabe) * @return fresh private key; free using #GNUNET_free */ void -- cgit v1.2.3 From e96a82d77b22f18196d9ae549a259be8575006bf Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Fri, 20 Jul 2018 15:13:29 +0200 Subject: update --- src/reclaim/plugin_rest_reclaim.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c index b54aed5f3..38ffc4ddb 100644 --- a/src/reclaim/plugin_rest_reclaim.c +++ b/src/reclaim/plugin_rest_reclaim.c @@ -42,27 +42,27 @@ /** * REST root namespace */ -#define GNUNET_REST_API_NS_RECLAIM "/idp" +#define GNUNET_REST_API_NS_RECLAIM "/reclaim" /** * Attribute namespace */ -#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/idp/attributes" +#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes" /** * Ticket namespace */ -#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets" +#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets" /** * Revoke namespace */ -#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke" +#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke" /** * Revoke namespace */ -#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" +#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume" /** * Attribute key -- cgit v1.2.3 From 74a80d549aef8452b1040ea69d7c1274679f7338 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Fri, 20 Jul 2018 16:08:08 +0200 Subject: fix --- src/reclaim/plugin_rest_openid_connect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 9b7cf0205..3e53a2836 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -749,7 +749,7 @@ login_redirection(void *cls) struct RequestHandle *handle = cls; if ( GNUNET_OK - == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", "address", &login_base_url) ) { GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", @@ -1373,7 +1373,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, //check client password if ( GNUNET_OK - == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", "psw", &expected_psw) ) { if (0 != strcmp (expected_psw, psw)) @@ -1543,7 +1543,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, //create jwt unsigned long long int expiration_time; if ( GNUNET_OK - != GNUNET_CONFIGURATION_get_value_number(cfg, "identity-rest-plugin", + != GNUNET_CONFIGURATION_get_value_number(cfg, "reclaim-rest-plugin", "expiration_time", &expiration_time) ) { GNUNET_free_non_null(user_psw); @@ -1620,7 +1620,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, return; } if ( GNUNET_OK - != GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", + != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", "jwt_secret", &jwt_secret) ) { GNUNET_free_non_null(user_psw); -- cgit v1.2.3 From 1914b435ce08b95c02d9c630acc292f4a7548a47 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Fri, 20 Jul 2018 21:42:37 +0200 Subject: revert simple TLD mapping --- src/reclaim/plugin_rest_openid_connect.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 3e53a2836..6aa2cd907 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -1165,6 +1165,9 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, { struct RequestHandle *handle = cls; struct GNUNET_HashCode cache_key; + struct EgoEntry *tmp_ego; + const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; + struct GNUNET_CRYPTO_EcdsaPublicKey pkey; cookie_identity_interpretation(handle); @@ -1218,7 +1221,20 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, handle->ego_entry = handle->ego_head; handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); - + //If we know this identity, translated the corresponding TLD + //TODO: We might want to have a reverse lookup functionality for TLDs? + for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) + { + priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); + GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, + &pkey); + if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) + { + handle->tld = GNUNET_strdup (tmp_ego->identifier); + handle->ego_entry = handle->ego_tail; + } + } GNUNET_SCHEDULER_add_now (&build_authz_response, handle); } -- cgit v1.2.3 From ee4adf9768a740c3d79b854453eb8bc0f5c14d30 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 08:00:49 +0200 Subject: add more general HMAC function for JWTs --- src/include/gnunet_crypto_lib.h | 17 +++++++++++++++++ src/reclaim/jwt.c | 16 ++++++++-------- src/reclaim/jwt.h | 2 +- src/reclaim/plugin_rest_openid_connect.c | 4 +--- src/util/crypto_hash.c | 26 ++++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 7b69c157f..8a591fa09 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -725,6 +725,23 @@ void GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext *hc); +/** + * Calculate HMAC of a message (RFC 2104) + * TODO: Shouldn' this be the standard hmac function and + * the above be renamed? + * + * @param key secret key + * @param key_len secret key length + * @param plaintext input plaintext + * @param plaintext_len length of @a plaintext + * @param hmac where to store the hmac + */ +void +GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len, + const void *plaintext, size_t plaintext_len, + struct GNUNET_HashCode *hmac); + + /** * @ingroup hash * Calculate HMAC of a message (RFC 2104) diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index 45b5d73f6..ec1e6d098 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -65,8 +65,8 @@ create_jwt_header(void) char* jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, - const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_CRYPTO_AuthKey *priv_key) + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const char *secret_key) { struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; struct GNUNET_HashCode signature; @@ -89,12 +89,12 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, //nonce only if nonce // OPTIONAL acr,amr,azp subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); header = create_jwt_header (); body = json_object (); - + //iss REQUIRED case sensitive server uri with https //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) json_object_set_new (body, @@ -108,8 +108,8 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, for (le = attrs->list_head; NULL != le; le = le->next) { attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type, - le->claim->data, - le->claim->data_size); + le->claim->data, + le->claim->data_size); json_object_set_new (body, le->claim->name, json_string (attr_val_str)); @@ -142,8 +142,8 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, * Creating the JWT signature. This might not be * standards compliant, check. */ - GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); - GNUNET_CRYPTO_hmac (priv_key, signature_target, strlen (signature_target), &signature); + GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64); + GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, strlen (signature_target), &signature); GNUNET_STRINGS_base64_encode ((const char*)&signature, sizeof (struct GNUNET_HashCode), &signature_base64); diff --git a/src/reclaim/jwt.h b/src/reclaim/jwt.h index 4b0b01be3..39b4e2f3c 100644 --- a/src/reclaim/jwt.h +++ b/src/reclaim/jwt.h @@ -5,6 +5,6 @@ char* jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_CRYPTO_AuthKey *priv_key); + const char* secret_key); #endif diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 6aa2cd907..5a34e5b72 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -1647,14 +1647,12 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_free(ticket); return; } - struct GNUNET_CRYPTO_AuthKey jwt_sign_key; struct GNUNET_CRYPTO_EcdsaPublicKey pk; GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk); - GNUNET_CRYPTO_hash (jwt_secret, strlen (jwt_secret), (struct GNUNET_HashCode*)jwt_sign_key.key); char *id_token = jwt_create_from_list(&ticket->audience, &pk, cl, - &jwt_sign_key); + jwt_secret); //Create random access_token char* access_token_number; diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index 8410b7835..fe1f58df7 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c @@ -365,14 +365,17 @@ GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, /** * Calculate HMAC of a message (RFC 2104) + * TODO: Shouldn' this be the standard hmac function and + * the above be renamed? * * @param key secret key + * @param key_len secret key length * @param plaintext input plaintext * @param plaintext_len length of @a plaintext * @param hmac where to store the hmac */ void -GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, +GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac) { @@ -390,7 +393,7 @@ GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, { gcry_md_reset (md); } - gcry_md_setkey (md, key->key, sizeof (key->key)); + gcry_md_setkey (md, key, key_len); gcry_md_write (md, plaintext, plaintext_len); mc = gcry_md_read (md, GCRY_MD_SHA512); GNUNET_assert (NULL != mc); @@ -398,6 +401,25 @@ GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, } +/** + * Calculate HMAC of a message (RFC 2104) + * + * @param key secret key + * @param plaintext input plaintext + * @param plaintext_len length of @a plaintext + * @param hmac where to store the hmac + */ +void +GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, + const void *plaintext, size_t plaintext_len, + struct GNUNET_HashCode *hmac) +{ + GNUNET_CRYPTO_hmac_raw ((void*) key->key, sizeof (key->key), + plaintext, plaintext_len, + hmac); +} + + /** * Context for cummulative hashing. */ -- cgit v1.2.3 From 2371a7547d958c640b97ed6016160a5d7dde0326 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 08:40:45 +0200 Subject: fix JWT format --- src/reclaim/jwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index ec1e6d098..d23c6a2a9 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -49,7 +49,7 @@ create_jwt_header(void) 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_str = json_dumps (root, JSON_INDENT(0)); json_decref (root); return json_str; } -- cgit v1.2.3 From 8b5994b08ab970ba291b1d39847d0284cd9b323e Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 09:21:01 +0200 Subject: compact JWT serialization --- src/reclaim/jwt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index d23c6a2a9..d9c2447bc 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -49,7 +49,7 @@ create_jwt_header(void) 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(0)); + json_str = json_dumps (root, JSON_INDENT(0) | JSON_COMPACT); json_decref (root); return json_str; } @@ -115,7 +115,7 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, json_string (attr_val_str)); GNUNET_free (attr_val_str); } - body_str = json_dumps (body, JSON_INDENT(0)); + body_str = json_dumps (body, JSON_INDENT(0) | JSON_COMPACT); json_decref (body); GNUNET_STRINGS_base64_encode (header, @@ -147,6 +147,12 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, GNUNET_STRINGS_base64_encode ((const char*)&signature, sizeof (struct GNUNET_HashCode), &signature_base64); + + //Remove GNUNET padding of base64 + padding = strtok(signature_base64, "="); + while (NULL != padding) + padding = strtok(NULL, "="); + GNUNET_asprintf (&result, "%s.%s.%s", header_base64, body_base64, signature_base64); -- cgit v1.2.3 From 51ace4c06634efe9fd7edbb39f91f754befccd5e Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 10:10:22 +0200 Subject: fix base64urlencode for JWT to adhere to RFC4648 --- src/reclaim/jwt.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index d9c2447bc..9885bf467 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -54,6 +54,32 @@ create_jwt_header(void) return json_str; } +static void +replace_char(char* str, char find, char replace){ + char *current_pos = strchr(str,find); + while (current_pos){ + *current_pos = replace; + current_pos = strchr(current_pos,find); + } +} + +//RFC4648 +static void +fix_base64(char* str) { + char *padding; + //First, remove trailing padding '=' + padding = strtok(str, "="); + while (NULL != padding) + padding = strtok(NULL, "="); + + //Replace + with - + replace_char (str, '+', '-'); + + //Replace / with _ + replace_char (str, '/', '_'); + +} + /** * Create a JWT from attributes * @@ -73,7 +99,6 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, char* audience; char* subject; char* header; - char* padding; char* body_str; char* result; char* header_base64; @@ -121,19 +146,12 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64); - //Remove GNUNET padding of base64 - padding = strtok(header_base64, "="); - while (NULL != padding) - padding = strtok(NULL, "="); + fix_base64(header_base64); 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, "="); + fix_base64(body_base64); GNUNET_free (subject); GNUNET_free (audience); @@ -147,11 +165,7 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, GNUNET_STRINGS_base64_encode ((const char*)&signature, sizeof (struct GNUNET_HashCode), &signature_base64); - - //Remove GNUNET padding of base64 - padding = strtok(signature_base64, "="); - while (NULL != padding) - padding = strtok(NULL, "="); + fix_base64(signature_base64); GNUNET_asprintf (&result, "%s.%s.%s", header_base64, body_base64, signature_base64); -- cgit v1.2.3 From d81369afa8c051383727fa4c54479decc4071b9e Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 12:02:24 +0200 Subject: fixes for JWT creation --- src/reclaim/jwt.c | 30 ++++++++++++++--- src/reclaim/jwt.h | 17 ++++++++-- src/reclaim/plugin_rest_openid_connect.c | 55 +++++--------------------------- src/reclaim/reclaim.conf | 2 +- 4 files changed, 50 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index 9885bf467..41a3747ed 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -83,19 +83,25 @@ fix_base64(char* str) { /** * Create a JWT from attributes * - * @param aud_key the public of the subject + * @param aud_key the public of the audience + * @param sub_key the public key of the subject * @param attrs the attribute list - * @param priv_key the key used to sign the JWT + * @param expiration_time the validity of the token + * @param secret_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 *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const struct GNUNET_TIME_Relative *expiration_time, + const char *nonce, const char *secret_key) { struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; struct GNUNET_HashCode signature; + struct GNUNET_TIME_Absolute exp_time; + struct GNUNET_TIME_Absolute time_now; char* audience; char* subject; char* header; @@ -107,9 +113,11 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, char* signature_base64; char* attr_val_str; json_t* body; - - //exp REQUIRED time expired from config + //iat REQUIRED time now + time_now = GNUNET_TIME_absolute_get(); + //exp REQUIRED time expired from config + exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time); //auth_time only if max_age //nonce only if nonce // OPTIONAL acr,amr,azp @@ -130,6 +138,20 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, //aud REQUIRED public key client_id must be there json_object_set_new (body, "aud", json_string (audience)); + //iat + json_object_set_new (body, + "iat", json_integer (time_now.abs_value_us)); + //exp + json_object_set_new (body, + "exp", json_integer (exp_time.abs_value_us)); + //nbf + json_object_set_new (body, + "nbf", json_integer (time_now.abs_value_us)); + //nonce + if (NULL != nonce) + json_object_set_new (body, + "nonce", json_string (nonce)); + for (le = attrs->list_head; NULL != le; le = le->next) { attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type, diff --git a/src/reclaim/jwt.h b/src/reclaim/jwt.h index 39b4e2f3c..12ff85b01 100644 --- a/src/reclaim/jwt.h +++ b/src/reclaim/jwt.h @@ -1,10 +1,23 @@ #ifndef JWT_H #define JWT_H +/** + * Create a JWT from attributes + * + * @param aud_key the public of the audience + * @param sub_key the public key of the subject + * @param attrs the attribute list + * @param expiration_time the validity of the token + * @param nonce the nonce, may be NULL + * @param secret_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 *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, - const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, - const char* secret_key); + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const struct GNUNET_TIME_Relative *expiration_time, + const char *nonce, + const char *secret_key); #endif diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 5a34e5b72..d1c5b31b6 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -168,7 +168,6 @@ static char* OIDC_ignored_parameter_array [] = { "display", "prompt", - "max_age", "ui_locales", "response_mode", "id_token_hint", @@ -1320,7 +1319,9 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, int client_exists = GNUNET_NO; struct MHD_Response *resp; char* code_output; - json_t *root, *ticket_string, *nonce, *max_age; + json_t *root; + json_t *ticket_string; + json_t *nonce; json_error_t error; char *json_response; char *jwt_secret; @@ -1515,7 +1516,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_free(code_output); ticket_string = json_object_get (root, "ticket"); nonce = json_object_get (root, "nonce"); - max_age = json_object_get (root, "max_age"); if(ticket_string == NULL && !json_is_string(ticket_string)) { @@ -1557,9 +1557,9 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } //create jwt - unsigned long long int expiration_time; + struct GNUNET_TIME_Relative expiration_time; if ( GNUNET_OK - != GNUNET_CONFIGURATION_get_value_number(cfg, "reclaim-rest-plugin", + != GNUNET_CONFIGURATION_get_value_time(cfg, "reclaim-rest-plugin", "expiration_time", &expiration_time) ) { GNUNET_free_non_null(user_psw); @@ -1572,48 +1572,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); - //aud REQUIRED public key client_id must be there - GNUNET_RECLAIM_ATTRIBUTE_list_add(cl, - "aud", - GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, - client_id, - strlen(client_id)); - //exp REQUIRED time expired from config - struct GNUNET_TIME_Absolute exp_time = GNUNET_TIME_relative_to_absolute ( - GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), - expiration_time)); - const char* exp_time_string = GNUNET_STRINGS_absolute_time_to_string(exp_time); - GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, - "exp", - GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, - exp_time_string, - strlen(exp_time_string)); - //iat REQUIRED time now - struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get(); - const char* time_now_string = GNUNET_STRINGS_absolute_time_to_string(time_now); - GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, - "iat", - GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, - time_now_string, - strlen(time_now_string)); - //nonce only if nonce is provided - if ( NULL != nonce && json_is_string(nonce) ) - { - GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, - "nonce", - GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, - json_string_value(nonce), - strlen(json_string_value(nonce))); - } - //auth_time only if max_age is provided - if ( NULL != max_age && json_is_string(max_age) ) - { - GNUNET_RECLAIM_ATTRIBUTE_list_add (cl, - "auth_time", - GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING, - json_string_value(max_age), - strlen(json_string_value(max_age))); - } + //TODO OPTIONAL acr,amr,azp struct EgoEntry *ego_entry; @@ -1652,6 +1611,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, char *id_token = jwt_create_from_list(&ticket->audience, &pk, cl, + &expiration_time, + (NULL != nonce && json_is_string(nonce)) ? json_string_value (nonce) : NULL, jwt_secret); //Create random access_token diff --git a/src/reclaim/reclaim.conf b/src/reclaim/reclaim.conf index e93899e05..cf0a0dc5e 100644 --- a/src/reclaim/reclaim.conf +++ b/src/reclaim/reclaim.conf @@ -17,7 +17,7 @@ DATABASE = sqlite ADDRESS = https://reclaim.ui/#/login PSW = secret JWT_SECRET = secret -EXPIRATION_TIME = 3600 +EXPIRATION_TIME = 1d [reclaim-sqlite] FILENAME = $GNUNET_DATA_HOME/reclaim/sqlite.db -- cgit v1.2.3 From 8b3dd615a1c7501e19e6d6733c6ada71eb2eadb4 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 12:50:50 +0200 Subject: fix timestamps --- src/reclaim/jwt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index 41a3747ed..cb1213dad 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -140,13 +140,13 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, "aud", json_string (audience)); //iat json_object_set_new (body, - "iat", json_integer (time_now.abs_value_us)); + "iat", json_integer (time_now.abs_value_us / (1000*1000))); //exp json_object_set_new (body, - "exp", json_integer (exp_time.abs_value_us)); + "exp", json_integer (exp_time.abs_value_us / (1000*1000))); //nbf json_object_set_new (body, - "nbf", json_integer (time_now.abs_value_us)); + "nbf", json_integer (time_now.abs_value_us / (1000*1000))); //nonce if (NULL != nonce) json_object_set_new (body, -- cgit v1.2.3 From 7726b15977bacfc05a7f9321d3b595b04762d30a Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 13:02:18 +0200 Subject: fix --- src/reclaim/jwt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index cb1213dad..041498fb2 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -37,7 +37,7 @@ #define JWT_TYP_VALUE "jwt" -#define SERVER_ADDRESS "https://reclaim.id/api/openid/userinfo" +#define SERVER_ADDRESS "https://reclaim.id" static char* create_jwt_header(void) @@ -123,7 +123,7 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, // OPTIONAL acr,amr,azp subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, + audience = GNUNET_STRINGS_data_to_string_alloc (&aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); header = create_jwt_header (); body = json_object (); -- cgit v1.2.3 From 735e699708247813ae3e9926190dff35a9c8eba1 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 13:04:17 +0200 Subject: actually fix --- src/reclaim/jwt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index 041498fb2..94db19b14 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -121,9 +121,9 @@ jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, //auth_time only if max_age //nonce only if nonce // OPTIONAL acr,amr,azp - subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, + subject = GNUNET_STRINGS_data_to_string_alloc (sub_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - audience = GNUNET_STRINGS_data_to_string_alloc (&aud_key, + audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); header = create_jwt_header (); body = json_object (); -- cgit v1.2.3 From 33d45d039f618ec2892c8db3961f4f76a0e63652 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 21 Jul 2018 13:34:50 +0200 Subject: fix subject in JWT --- src/reclaim/plugin_rest_openid_connect.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index d1c5b31b6..bd11b2de7 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -1606,10 +1606,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_free(ticket); return; } - struct GNUNET_CRYPTO_EcdsaPublicKey pk; - GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pk); char *id_token = jwt_create_from_list(&ticket->audience, - &pk, + &ticket->identity, cl, &expiration_time, (NULL != nonce && json_is_string(nonce)) ? json_string_value (nonce) : NULL, -- cgit v1.2.3 From 214f2e90aff373771838d4504d77444c43194e49 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 22 Jul 2018 15:50:52 +0200 Subject: fix code signing --- src/include/gnunet_signatures.h | 2 +- src/reclaim/plugin_rest_openid_connect.c | 116 ++++++++++++++++++++++++------- 2 files changed, 93 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h index 280fefa83..829f8be7e 100644 --- a/src/include/gnunet_signatures.h +++ b/src/include/gnunet_signatures.h @@ -181,7 +181,7 @@ extern "C" /** * Signature for a GNUid Ticket */ -#define GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET 27 +#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN 27 /** * Signature for a GNUnet credential diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index bd11b2de7..0a6dd2b61 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -794,11 +794,75 @@ oidc_iteration_error (void *cls) GNUNET_SCHEDULER_add_now (&do_error, handle); } -static void get_client_name_result (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) + +static char* +build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, + const struct GNUNET_RECLAIM_Ticket *ticket, + const char* nonce) +{ + char *ticket_str; + json_t *code_json; + char *signature_payload; + char *signature_str; + char *authz_code; + size_t signature_payload_len; + struct GNUNET_CRYPTO_EcdsaSignature signature; + struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + + signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); + if (NULL != nonce) + signature_payload_len += strlen (nonce); + + signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; + purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); + memcpy (&purpose[1], + ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + if (NULL != nonce) + memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + nonce, + strlen (nonce)); + if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, + purpose, + &signature)) + { + GNUNET_free (signature_payload); + return NULL; + } + signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, + sizeof (signature)); + ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + + code_json = json_object (); + json_object_set_new (code_json, + "ticket", + json_string (ticket_str)); + if (NULL != nonce) + json_object_set_new (code_json, + "nonce", + json_string (nonce)); + json_object_set_new (code_json, + "signature", + json_string (signature_str)); + authz_code = json_dumps (code_json, + JSON_INDENT(0) | JSON_COMPACT); + GNUNET_free (signature_payload); + GNUNET_free (signature_str); + GNUNET_free (ticket_str); + json_decref (code_json); + return authz_code; +} + + +static void +get_client_name_result (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; struct MHD_Response *resp; @@ -812,12 +876,16 @@ static void get_client_name_result (void *cls, char *prefix; ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); + //TODO add signature to code payload over nonce and ticket _and_ use jansson here! //TODO change if more attributes are needed (see max_age) - GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", + code_json_string = build_authz_code (&handle->priv_key, + &handle->ticket, + handle->oidc->nonce); + /*GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", ticket_str, (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", - (NULL != handle->oidc->nonce) ? "\"" : ""); + (NULL != handle->oidc->nonce) ? "\"" : "");*/ code_base64_final_string = base_64_encode(code_json_string); tmp = GNUNET_strdup (handle->oidc->redirect_uri); redirect_path = strtok (tmp, "/"); @@ -896,11 +964,11 @@ oidc_collect_finished_cb (void *cls) return; } handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, - &handle->priv_key, - &handle->oidc->client_pkey, - handle->attr_list, - &oidc_ticket_issue_cb, - handle); + &handle->priv_key, + &handle->oidc->client_pkey, + handle->attr_list, + &oidc_ticket_issue_cb, + handle); } @@ -944,7 +1012,7 @@ oidc_attr_collect (void *cls, le = GNUNET_new(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, attr->type, - attr->data, attr->data_size); + attr->data, attr->data_size); GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head, handle->attr_list->list_tail, le); GNUNET_RECLAIM_get_attributes_next (handle->attr_it); @@ -1004,8 +1072,8 @@ login_check (void *cls) handle->attr_list = GNUNET_new( struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); handle->attr_it = GNUNET_RECLAIM_get_attributes_start ( - handle->idp, &handle->priv_key, &oidc_iteration_error, handle, - &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle); + handle->idp, &handle->priv_key, &oidc_iteration_error, handle, + &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle); return; } } @@ -1560,7 +1628,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, struct GNUNET_TIME_Relative expiration_time; if ( GNUNET_OK != GNUNET_CONFIGURATION_get_value_time(cfg, "reclaim-rest-plugin", - "expiration_time", &expiration_time) ) + "expiration_time", &expiration_time) ) { GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("server_error"); @@ -1572,7 +1640,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); - + //TODO OPTIONAL acr,amr,azp struct EgoEntry *ego_entry; @@ -1679,8 +1747,8 @@ consume_ticket (void *cls, } tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, - attr->data, - attr->data_size); + attr->data, + attr->data_size); value = json_string (tmp_value); @@ -1828,11 +1896,11 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, handle->oidc->response = json_object(); json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring)); handle->idp_op = GNUNET_RECLAIM_ticket_consume ( - handle->idp, - GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego), - ticket, - consume_ticket, - handle); + handle->idp, + GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego), + ticket, + consume_ticket, + handle); GNUNET_free(ticket); GNUNET_free(authorization); GNUNET_free(client_ticket); -- cgit v1.2.3 From b68e69365b355f3ef5104f3b682457b0844a70df Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 22 Jul 2018 16:37:49 +0200 Subject: add signature check to token endpoint --- src/reclaim/plugin_rest_openid_connect.c | 250 ++++++++++++++++++++----------- 1 file changed, 162 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 0a6dd2b61..a2d32e126 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -794,66 +794,160 @@ oidc_iteration_error (void *cls) GNUNET_SCHEDULER_add_now (&do_error, handle); } +static int +parse_authz_code (const char* code, + struct GNUNET_RECLAIM_Ticket **ticket, + char **nonce) +{ + json_error_t error; + json_t *code_json; + json_t *ticket_json; + json_t *nonce_json; + json_t *signature_json; + const char *ticket_str; + const char *signature_str; + const char *nonce_str; + char *code_output; + struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + struct GNUNET_CRYPTO_EcdsaSignature signature; + size_t signature_payload_len; + + code_output = NULL; + GNUNET_STRINGS_base64_decode (code, + strlen(code), + (void**)&code_output); + code_json = json_loads (code_output, 0 , &error); + GNUNET_free (code_output); + ticket_json = json_object_get (code_json, "ticket"); + nonce_json = json_object_get (code_json, "nonce"); + signature_json = json_object_get (code_json, "signature"); + *ticket = NULL; + *nonce = NULL; + + if ((NULL == ticket_json || !json_is_string (ticket_json)) || + (NULL == signature_json || !json_is_string (signature_json))) + { + json_decref (code_json); + return GNUNET_SYSERR; + } + ticket_str = json_string_value (ticket_json); + signature_str = json_string_value (signature_json); + nonce_str = NULL; + if (NULL != nonce_json) + nonce_str = json_string_value (nonce_json); + signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); + if (NULL != nonce_str) + signature_payload_len += strlen (nonce_str); + purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + + signature_payload_len); + purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str, + strlen (ticket_str), + &purpose[1], + sizeof (struct GNUNET_RECLAIM_Ticket))) + { + GNUNET_free (purpose); + json_decref (code_json); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Cannot parse ticket!\n"); + return GNUNET_SYSERR; + } + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str, + strlen (signature_str), + &signature, + sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) + { + GNUNET_free (purpose); + json_decref (code_json); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Cannot parse signature!\n"); + return GNUNET_SYSERR; + } + *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket); + memcpy (*ticket, + &purpose[1], + sizeof (struct GNUNET_RECLAIM_Ticket)); + if (NULL != nonce_str) + memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + nonce_str, + strlen (nonce_str)); + if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, + purpose, + &signature, + &(*ticket)->identity)) + { + GNUNET_free (purpose); + GNUNET_free (*ticket); + json_decref (code_json); + *ticket = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Signature of authZ code invalid!\n"); + return GNUNET_SYSERR; + } + *nonce = GNUNET_strdup (nonce_str); + return GNUNET_OK; +} static char* build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const char* nonce) { - char *ticket_str; - json_t *code_json; - char *signature_payload; - char *signature_str; - char *authz_code; - size_t signature_payload_len; - struct GNUNET_CRYPTO_EcdsaSignature signature; - struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; - - signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); - if (NULL != nonce) - signature_payload_len += strlen (nonce); - - signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); - purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; - purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); - purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); - memcpy (&purpose[1], - ticket, - sizeof (struct GNUNET_RECLAIM_Ticket)); - if (NULL != nonce) - memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), - nonce, - strlen (nonce)); - if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, - purpose, - &signature)) - { - GNUNET_free (signature_payload); - return NULL; - } - signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, - sizeof (signature)); - ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, - sizeof (struct GNUNET_RECLAIM_Ticket)); - - code_json = json_object (); - json_object_set_new (code_json, - "ticket", - json_string (ticket_str)); - if (NULL != nonce) - json_object_set_new (code_json, - "nonce", - json_string (nonce)); - json_object_set_new (code_json, - "signature", - json_string (signature_str)); - authz_code = json_dumps (code_json, - JSON_INDENT(0) | JSON_COMPACT); - GNUNET_free (signature_payload); - GNUNET_free (signature_str); - GNUNET_free (ticket_str); - json_decref (code_json); - return authz_code; + char *ticket_str; + json_t *code_json; + char *signature_payload; + char *signature_str; + char *authz_code; + size_t signature_payload_len; + struct GNUNET_CRYPTO_EcdsaSignature signature; + struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + + signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); + if (NULL != nonce) + signature_payload_len += strlen (nonce); + + signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; + purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); + memcpy (&purpose[1], + ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + if (NULL != nonce) + memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + nonce, + strlen (nonce)); + if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, + purpose, + &signature)) + { + GNUNET_free (signature_payload); + return NULL; + } + signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, + sizeof (signature)); + ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + + code_json = json_object (); + json_object_set_new (code_json, + "ticket", + json_string (ticket_str)); + if (NULL != nonce) + json_object_set_new (code_json, + "nonce", + json_string (nonce)); + json_object_set_new (code_json, + "signature", + json_string (signature_str)); + authz_code = json_dumps (code_json, + JSON_INDENT(0) | JSON_COMPACT); + GNUNET_free (signature_payload); + GNUNET_free (signature_str); + GNUNET_free (ticket_str); + json_decref (code_json); + return authz_code; } @@ -882,10 +976,10 @@ get_client_name_result (void *cls, &handle->ticket, handle->oidc->nonce); /*GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", - ticket_str, - (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", - (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", - (NULL != handle->oidc->nonce) ? "\"" : "");*/ + ticket_str, + (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", + (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", + (NULL != handle->oidc->nonce) ? "\"" : "");*/ code_base64_final_string = base_64_encode(code_json_string); tmp = GNUNET_strdup (handle->oidc->redirect_uri); redirect_path = strtok (tmp, "/"); @@ -1386,13 +1480,9 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, char *expected_psw; int client_exists = GNUNET_NO; struct MHD_Response *resp; - char* code_output; - json_t *root; - json_t *ticket_string; - json_t *nonce; - json_error_t error; char *json_response; char *jwt_secret; + char *nonce; /* * Check Authorization @@ -1579,13 +1669,10 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } //decode code - GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output); - root = json_loads (code_output, 0, &error); - GNUNET_free(code_output); - ticket_string = json_object_get (root, "ticket"); - nonce = json_object_get (root, "nonce"); - - if(ticket_string == NULL && !json_is_string(ticket_string)) + struct GNUNET_RECLAIM_Ticket *ticket; + if(GNUNET_OK != parse_authz_code (code, + &ticket, + &nonce)) { GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); @@ -1595,21 +1682,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, return; } - struct GNUNET_RECLAIM_Ticket *ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket); - if ( GNUNET_OK - != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string), - strlen (json_string_value(ticket_string)), - ticket, - sizeof(struct GNUNET_RECLAIM_Ticket))) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } // this is the current client (relying party) struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); @@ -1678,7 +1750,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, &ticket->identity, cl, &expiration_time, - (NULL != nonce && json_is_string(nonce)) ? json_string_value (nonce) : NULL, + (NULL != nonce) ? nonce : NULL, jwt_secret); //Create random access_token @@ -1702,10 +1774,13 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, id_token); GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); char *id_ticket_combination; + char *ticket_string; + ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); GNUNET_asprintf(&id_ticket_combination, "%s;%s", client_id, - json_string_value(ticket_string)); + ticket_string); GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, &cache_key, id_ticket_combination, @@ -1724,7 +1799,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_free(json_response); GNUNET_free(ticket); GNUNET_free(id_token); - json_decref (root); GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle); } -- cgit v1.2.3 From 8b67e9b5f905ff80ee73300bbb278c00e36b9bca Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 22 Jul 2018 18:01:50 +0200 Subject: ensure ticket contains client id --- src/reclaim/plugin_rest_openid_connect.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index a2d32e126..876e221b5 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -795,7 +795,8 @@ oidc_iteration_error (void *cls) } static int -parse_authz_code (const char* code, +parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, + const char* code, struct GNUNET_RECLAIM_Ticket **ticket, char **nonce) { @@ -868,6 +869,19 @@ parse_authz_code (const char* code, memcpy (*ticket, &purpose[1], sizeof (struct GNUNET_RECLAIM_Ticket)); + if (0 != memcmp (audience, + &(*ticket)->audience, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + GNUNET_free (purpose); + GNUNET_free (*ticket); + json_decref (code_json); + *ticket = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Audience in ticket does not match client!\n"); + return GNUNET_SYSERR; + + } if (NULL != nonce_str) memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), nonce_str, @@ -1669,8 +1683,14 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } //decode code + struct GNUNET_CRYPTO_EcdsaPublicKey cid; + GNUNET_STRINGS_string_to_data (client_id, + strlen(client_id), + &cid, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); struct GNUNET_RECLAIM_Ticket *ticket; - if(GNUNET_OK != parse_authz_code (code, + if(GNUNET_OK != parse_authz_code (&cid, + code, &ticket, &nonce)) { -- cgit v1.2.3 From 96fdc9cacc176d6269e51dbd490de568c2254bb4 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 22 Jul 2018 18:02:48 +0200 Subject: cleanup --- src/reclaim/plugin_rest_openid_connect.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 876e221b5..679d8f7d9 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -984,16 +984,10 @@ get_client_name_result (void *cls, char *prefix; ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); - //TODO add signature to code payload over nonce and ticket _and_ use jansson here! //TODO change if more attributes are needed (see max_age) code_json_string = build_authz_code (&handle->priv_key, &handle->ticket, handle->oidc->nonce); - /*GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", - ticket_str, - (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", - (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", - (NULL != handle->oidc->nonce) ? "\"" : "");*/ code_base64_final_string = base_64_encode(code_json_string); tmp = GNUNET_strdup (handle->oidc->redirect_uri); redirect_path = strtok (tmp, "/"); -- cgit v1.2.3 From 0e3d3b63bf18148828e722fa1a29fc196f6f441d Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 22 Jul 2018 21:26:47 +0200 Subject: towards secure redirects --- src/reclaim/plugin_rest_openid_connect.c | 124 ++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 679d8f7d9..0f746f988 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -339,6 +339,16 @@ struct RequestHandle */ struct GNUNET_REST_RequestHandle *rest_handle; + /** + * GNS handle + */ + struct GNUNET_GNS_Handle *gns_handle; + + /** + * GNS lookup op + */ + struct GNUNET_GNS_LookupRequest *gns_op; + /** * Handle to NAMESTORE */ @@ -414,6 +424,16 @@ struct RequestHandle */ char *tld; + /** + * The redirect prefix + */ + char *redirect_prefix; + + /** + * The redirect suffix + */ + char *redirect_suffix; + /** * Error response message */ @@ -465,10 +485,19 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_free (handle->url); if (NULL != handle->tld) GNUNET_free (handle->tld); + if (NULL != handle->redirect_prefix) + GNUNET_free (handle->redirect_prefix); + if (NULL != handle->redirect_suffix) + GNUNET_free (handle->redirect_suffix); if (NULL != handle->emsg) GNUNET_free (handle->emsg); if (NULL != handle->edesc) GNUNET_free (handle->edesc); + if (NULL != handle->gns_op) + GNUNET_GNS_lookup_cancel (handle->gns_op); + if (NULL != handle->gns_handle) + GNUNET_GNS_disconnect (handle->gns_handle); + if (NULL != handle->namestore_handle) GNUNET_NAMESTORE_disconnect (handle->namestore_handle); if (NULL != handle->oidc) @@ -812,7 +841,7 @@ parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; struct GNUNET_CRYPTO_EcdsaSignature signature; size_t signature_payload_len; - + code_output = NULL; GNUNET_STRINGS_base64_decode (code, strlen(code), @@ -978,10 +1007,7 @@ get_client_name_result (void *cls, char *redirect_uri; char *code_json_string; char *code_base64_final_string; - char *redirect_path; - char *tmp; - char *tmp_prefix; - char *prefix; + ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); //TODO change if more attributes are needed (see max_age) @@ -989,33 +1015,25 @@ get_client_name_result (void *cls, &handle->ticket, handle->oidc->nonce); code_base64_final_string = base_64_encode(code_json_string); - tmp = GNUNET_strdup (handle->oidc->redirect_uri); - redirect_path = strtok (tmp, "/"); - redirect_path = strtok (NULL, "/"); - redirect_path = strtok (NULL, "/"); - tmp_prefix = GNUNET_strdup (handle->oidc->redirect_uri); - prefix = strrchr (tmp_prefix, - (unsigned char) '.'); - *prefix = '\0'; GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", - tmp_prefix, + handle->redirect_prefix, handle->tld, - redirect_path, + handle->redirect_suffix, handle->oidc->response_type, code_base64_final_string, handle->oidc->state); resp = GNUNET_REST_create_response (""); MHD_add_response_header (resp, "Location", redirect_uri); handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - GNUNET_free (tmp); - GNUNET_free (tmp_prefix); GNUNET_free (redirect_uri); GNUNET_free (ticket_str); GNUNET_free (code_json_string); GNUNET_free (code_base64_final_string); return; + } + static void get_client_name_error (void *cls) { @@ -1026,6 +1044,52 @@ get_client_name_error (void *cls) GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); } + +static void +lookup_redirect_uri_result (void *cls, + uint32_t rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + char *tmp; + char *tmp_key_str; + char *pos; + struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone; + + handle->gns_op = NULL; + if (1 != rd_count) + { + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + return; + } + tmp = GNUNET_strdup (rd->data); + pos = strrchr (tmp, + (unsigned char) '.'); + *pos = '\0'; + handle->redirect_prefix = GNUNET_strdup (tmp); + tmp_key_str = pos + 1; + pos = strchr (tmp_key_str, + (unsigned char) '/'); + *pos = '\0'; + handle->redirect_suffix = GNUNET_strdup (pos + 1); + GNUNET_free (tmp); + + GNUNET_STRINGS_string_to_data (tmp_key_str, + strlen (tmp_key_str), + &redirect_zone, + sizeof (redirect_zone)); + + GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, + &handle->priv_key, + &redirect_zone, + &get_client_name_error, + handle, + &get_client_name_result, + handle); +} + /** * Issues ticket and redirects to relying party with the authorization code as * parameter. Otherwise redirects with error @@ -1035,21 +1099,24 @@ oidc_ticket_issue_cb (void* cls, const struct GNUNET_RECLAIM_Ticket *ticket) { struct RequestHandle *handle = cls; + handle->idp_op = NULL; handle->ticket = *ticket; - if (NULL != ticket) { - GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, - &handle->priv_key, - &handle->oidc->client_pkey, - &get_client_name_error, - handle, - &get_client_name_result, - handle); + if (NULL == ticket) + { + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup("Server cannot generate ticket."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); return; } - handle->emsg = GNUNET_strdup("server_error"); - handle->edesc = GNUNET_strdup("Server cannot generate ticket."); - GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); + handle->gns_op = GNUNET_GNS_lookup (handle->gns_handle, + handle->oidc->redirect_uri, + &handle->oidc->client_pkey, + GNUNET_DNSPARSER_TYPE_TXT, + GNUNET_GNS_LO_DEFAULT, + &lookup_redirect_uri_result, + handle); + } static void @@ -2148,6 +2215,7 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle); + handle->gns_handle = GNUNET_GNS_connect (cfg); handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, -- cgit v1.2.3 From 98defb69b11bc6ca89cd1b5419de5036004626c4 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sun, 22 Jul 2018 21:49:38 +0200 Subject: fix build --- src/reclaim/Makefile.am | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am index c13c68763..91a041f91 100644 --- a/src/reclaim/Makefile.am +++ b/src/reclaim/Makefile.am @@ -29,7 +29,7 @@ pkgcfg_DATA = \ reclaim.conf lib_LTLIBRARIES = \ - libgnunetidentityprovider.la + libgnunetreclaim.la plugin_LTLIBRARIES = \ libgnunet_plugin_rest_reclaim.la \ libgnunet_plugin_rest_openid_connect.la \ @@ -53,7 +53,7 @@ libgnunet_plugin_gnsrecord_reclaim_la_LDFLAGS = \ libgnunet_plugin_reclaim_sqlite_la_SOURCES = \ plugin_reclaim_sqlite.c libgnunet_plugin_reclaim_sqlite_la_LIBADD = \ - libgnunetidentityprovider.la \ + libgnunetreclaim.la \ $(top_builddir)/src/sq/libgnunetsq.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ @@ -74,17 +74,17 @@ gnunet_service_reclaim_LDADD = \ $(top_builddir)/src/abe/libgnunetabe.la \ $(top_builddir)/src/credential/libgnunetcredential.la \ $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \ - libgnunetidentityprovider.la \ + libgnunetreclaim.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(GN_LIBINTL) -libgnunetidentityprovider_la_SOURCES = \ +libgnunetreclaim_la_SOURCES = \ reclaim_api.c \ reclaim.h -libgnunetidentityprovider_la_LIBADD = \ +libgnunetreclaim_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) -libgnunetidentityprovider_la_LDFLAGS = \ +libgnunetreclaim_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 @@ -93,7 +93,7 @@ libgnunet_plugin_rest_reclaim_la_SOURCES = \ jwt.c libgnunet_plugin_rest_reclaim_la_LIBADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ - libgnunetidentityprovider.la \ + libgnunetreclaim.la \ $(top_builddir)/src/rest/libgnunetrest.la \ $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \ @@ -108,11 +108,13 @@ libgnunet_plugin_rest_openid_connect_la_SOURCES = \ jwt.c libgnunet_plugin_rest_openid_connect_la_LIBADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ - libgnunetidentityprovider.la \ + libgnunetreclaim.la \ $(top_builddir)/src/rest/libgnunetrest.la \ $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) -ljansson -lmicrohttpd libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \ @@ -123,7 +125,7 @@ gnunet_reclaim_SOURCES = \ gnunet_reclaim_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - libgnunetidentityprovider.la \ + libgnunetreclaim.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \ $(GN_LIBINTL) -- cgit v1.2.3 From 97b5905aac2954fd0ce618b86ae80d11671fa1ba Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 12:42:18 +0200 Subject: refactoring of OIDC plugin --- src/reclaim/Makefile.am | 5 +- src/reclaim/jwt.c | 201 ------------ src/reclaim/jwt.h | 23 -- src/reclaim/oidc_helper.c | 440 +++++++++++++++++++++++++ src/reclaim/oidc_helper.h | 109 +++++++ src/reclaim/plugin_rest_openid_connect.c | 531 +++++++++++-------------------- 6 files changed, 737 insertions(+), 572 deletions(-) delete mode 100644 src/reclaim/jwt.h create mode 100644 src/reclaim/oidc_helper.c create mode 100644 src/reclaim/oidc_helper.h (limited to 'src') diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am index 91a041f91..2ee43d21a 100644 --- a/src/reclaim/Makefile.am +++ b/src/reclaim/Makefile.am @@ -89,8 +89,7 @@ libgnunetreclaim_la_LDFLAGS = \ -version-info 0:0:0 libgnunet_plugin_rest_reclaim_la_SOURCES = \ - plugin_rest_reclaim.c \ - jwt.c + plugin_rest_reclaim.c libgnunet_plugin_rest_reclaim_la_LIBADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ libgnunetreclaim.la \ @@ -105,7 +104,7 @@ libgnunet_plugin_rest_reclaim_la_LDFLAGS = \ libgnunet_plugin_rest_openid_connect_la_SOURCES = \ plugin_rest_openid_connect.c \ - jwt.c + oidc_helper.c libgnunet_plugin_rest_openid_connect_la_LIBADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ libgnunetreclaim.la \ diff --git a/src/reclaim/jwt.c b/src/reclaim/jwt.c index 94db19b14..8b1378917 100644 --- a/src/reclaim/jwt.c +++ b/src/reclaim/jwt.c @@ -1,202 +1 @@ -/* - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ - -/** - * @file reclaim/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_reclaim_attribute_lib.h" -#include - - -#define JWT_ALG "alg" - -/* Use 512bit HMAC */ -#define JWT_ALG_VALUE "HS512" - -#define JWT_TYP "typ" - -#define JWT_TYP_VALUE "jwt" - -#define SERVER_ADDRESS "https://reclaim.id" - -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(0) | JSON_COMPACT); - json_decref (root); - return json_str; -} - -static void -replace_char(char* str, char find, char replace){ - char *current_pos = strchr(str,find); - while (current_pos){ - *current_pos = replace; - current_pos = strchr(current_pos,find); - } -} - -//RFC4648 -static void -fix_base64(char* str) { - char *padding; - //First, remove trailing padding '=' - padding = strtok(str, "="); - while (NULL != padding) - padding = strtok(NULL, "="); - - //Replace + with - - replace_char (str, '+', '-'); - - //Replace / with _ - replace_char (str, '/', '_'); - -} - -/** - * Create a JWT from attributes - * - * @param aud_key the public of the audience - * @param sub_key the public key of the subject - * @param attrs the attribute list - * @param expiration_time the validity of the token - * @param secret_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 *aud_key, - const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, - const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_TIME_Relative *expiration_time, - const char *nonce, - const char *secret_key) -{ - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; - struct GNUNET_HashCode signature; - struct GNUNET_TIME_Absolute exp_time; - struct GNUNET_TIME_Absolute time_now; - char* audience; - char* subject; - char* header; - char* body_str; - char* result; - char* header_base64; - char* body_base64; - char* signature_target; - char* signature_base64; - char* attr_val_str; - json_t* body; - - //iat REQUIRED time now - time_now = GNUNET_TIME_absolute_get(); - //exp REQUIRED time expired from config - exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time); - //auth_time only if max_age - //nonce only if nonce - // OPTIONAL acr,amr,azp - subject = GNUNET_STRINGS_data_to_string_alloc (sub_key, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - header = create_jwt_header (); - body = json_object (); - - //iss REQUIRED case sensitive server uri with https - //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) - json_object_set_new (body, - "iss", json_string (SERVER_ADDRESS)); - //sub REQUIRED public key identity, not exceed 255 ASCII length - json_object_set_new (body, - "sub", json_string (subject)); - //aud REQUIRED public key client_id must be there - json_object_set_new (body, - "aud", json_string (audience)); - //iat - json_object_set_new (body, - "iat", json_integer (time_now.abs_value_us / (1000*1000))); - //exp - json_object_set_new (body, - "exp", json_integer (exp_time.abs_value_us / (1000*1000))); - //nbf - json_object_set_new (body, - "nbf", json_integer (time_now.abs_value_us / (1000*1000))); - //nonce - if (NULL != nonce) - json_object_set_new (body, - "nonce", json_string (nonce)); - - for (le = attrs->list_head; NULL != le; le = le->next) - { - attr_val_str = GNUNET_RECLAIM_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_COMPACT); - json_decref (body); - - GNUNET_STRINGS_base64_encode (header, - strlen (header), - &header_base64); - fix_base64(header_base64); - - GNUNET_STRINGS_base64_encode (body_str, - strlen (body_str), - &body_base64); - fix_base64(body_base64); - - GNUNET_free (subject); - GNUNET_free (audience); - - /** - * Creating the JWT signature. This might not be - * standards compliant, check. - */ - GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64); - GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, strlen (signature_target), &signature); - GNUNET_STRINGS_base64_encode ((const char*)&signature, - sizeof (struct GNUNET_HashCode), - &signature_base64); - fix_base64(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); - return result; -} diff --git a/src/reclaim/jwt.h b/src/reclaim/jwt.h deleted file mode 100644 index 12ff85b01..000000000 --- a/src/reclaim/jwt.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef JWT_H -#define JWT_H - -/** - * Create a JWT from attributes - * - * @param aud_key the public of the audience - * @param sub_key the public key of the subject - * @param attrs the attribute list - * @param expiration_time the validity of the token - * @param nonce the nonce, may be NULL - * @param secret_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 *aud_key, - const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, - const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, - const struct GNUNET_TIME_Relative *expiration_time, - const char *nonce, - const char *secret_key); - -#endif diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c new file mode 100644 index 000000000..9a99c5668 --- /dev/null +++ b/src/reclaim/oidc_helper.c @@ -0,0 +1,440 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ + +/** + * @file reclaim/oidc_helper.c + * @brief helper library for OIDC related functions + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_signatures.h" +#include "gnunet_reclaim_service.h" +#include "gnunet_reclaim_attribute_lib.h" +#include +#include +#include "oidc_helper.h" + +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(0) | JSON_COMPACT); + json_decref (root); + return json_str; +} + +static void +replace_char(char* str, char find, char replace){ + char *current_pos = strchr(str,find); + while (current_pos){ + *current_pos = replace; + current_pos = strchr(current_pos,find); + } +} + +//RFC4648 +static void +fix_base64(char* str) { + char *padding; + //First, remove trailing padding '=' + padding = strtok(str, "="); + while (NULL != padding) + padding = strtok(NULL, "="); + + //Replace + with - + replace_char (str, '+', '-'); + + //Replace / with _ + replace_char (str, '/', '_'); + +} + +/** + * Create a JWT from attributes + * + * @param aud_key the public of the audience + * @param sub_key the public key of the subject + * @param attrs the attribute list + * @param expiration_time the validity of the token + * @param secret_key the key used to sign the JWT + * @return a new base64-encoded JWT string. + */ +char* +OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, + const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const struct GNUNET_TIME_Relative *expiration_time, + const char *nonce, + const char *secret_key) +{ + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + struct GNUNET_HashCode signature; + struct GNUNET_TIME_Absolute exp_time; + struct GNUNET_TIME_Absolute time_now; + char* audience; + char* subject; + char* header; + char* body_str; + char* result; + char* header_base64; + char* body_base64; + char* signature_target; + char* signature_base64; + char* attr_val_str; + json_t* body; + + //iat REQUIRED time now + time_now = GNUNET_TIME_absolute_get(); + //exp REQUIRED time expired from config + exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time); + //auth_time only if max_age + //nonce only if nonce + // OPTIONAL acr,amr,azp + subject = GNUNET_STRINGS_data_to_string_alloc (sub_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + header = create_jwt_header (); + body = json_object (); + + //iss REQUIRED case sensitive server uri with https + //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid) + json_object_set_new (body, + "iss", json_string (SERVER_ADDRESS)); + //sub REQUIRED public key identity, not exceed 255 ASCII length + json_object_set_new (body, + "sub", json_string (subject)); + //aud REQUIRED public key client_id must be there + json_object_set_new (body, + "aud", json_string (audience)); + //iat + json_object_set_new (body, + "iat", json_integer (time_now.abs_value_us / (1000*1000))); + //exp + json_object_set_new (body, + "exp", json_integer (exp_time.abs_value_us / (1000*1000))); + //nbf + json_object_set_new (body, + "nbf", json_integer (time_now.abs_value_us / (1000*1000))); + //nonce + if (NULL != nonce) + json_object_set_new (body, + "nonce", json_string (nonce)); + + for (le = attrs->list_head; NULL != le; le = le->next) + { + attr_val_str = GNUNET_RECLAIM_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_COMPACT); + json_decref (body); + + GNUNET_STRINGS_base64_encode (header, + strlen (header), + &header_base64); + fix_base64(header_base64); + + GNUNET_STRINGS_base64_encode (body_str, + strlen (body_str), + &body_base64); + fix_base64(body_base64); + + GNUNET_free (subject); + GNUNET_free (audience); + + /** + * Creating the JWT signature. This might not be + * standards compliant, check. + */ + GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64); + GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, strlen (signature_target), &signature); + GNUNET_STRINGS_base64_encode ((const char*)&signature, + sizeof (struct GNUNET_HashCode), + &signature_base64); + fix_base64(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); + return result; +} +/** + * Builds an OIDC authorization code including + * a reclaim ticket and nonce + * + * @param issuer the issuer of the ticket, used to sign the ticket and nonce + * @param ticket the ticket to include in the code + * @param nonce the nonce to include in the code + * @return a new authorization code (caller must free) + */ +char* +OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, + const struct GNUNET_RECLAIM_Ticket *ticket, + const char* nonce) +{ + char *ticket_str; + json_t *code_json; + char *signature_payload; + char *signature_str; + char *authz_code; + size_t signature_payload_len; + struct GNUNET_CRYPTO_EcdsaSignature signature; + struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + + signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); + if (NULL != nonce) + signature_payload_len += strlen (nonce); + + signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; + purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); + memcpy (&purpose[1], + ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + if (NULL != nonce) + memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + nonce, + strlen (nonce)); + if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, + purpose, + &signature)) + { + GNUNET_free (signature_payload); + return NULL; + } + signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, + sizeof (signature)); + ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + + code_json = json_object (); + json_object_set_new (code_json, + "ticket", + json_string (ticket_str)); + if (NULL != nonce) + json_object_set_new (code_json, + "nonce", + json_string (nonce)); + json_object_set_new (code_json, + "signature", + json_string (signature_str)); + authz_code = json_dumps (code_json, + JSON_INDENT(0) | JSON_COMPACT); + GNUNET_free (signature_payload); + GNUNET_free (signature_str); + GNUNET_free (ticket_str); + json_decref (code_json); + return authz_code; +} + + + + +/** + * Parse reclaim ticket and nonce from + * authorization code. + * This also verifies the signature in the code. + * + * @param audience the expected audience of the code + * @param code the string representation of the code + * @param ticket where to store the ticket + * @param nonce where to store the nonce + * @return GNUNET_OK if successful, else GNUNET_SYSERR + */ +int +OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, + const char* code, + struct GNUNET_RECLAIM_Ticket **ticket, + char **nonce) +{ + json_error_t error; + json_t *code_json; + json_t *ticket_json; + json_t *nonce_json; + json_t *signature_json; + const char *ticket_str; + const char *signature_str; + const char *nonce_str; + char *code_output; + struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; + struct GNUNET_CRYPTO_EcdsaSignature signature; + size_t signature_payload_len; + + code_output = NULL; + GNUNET_STRINGS_base64_decode (code, + strlen(code), + (void**)&code_output); + code_json = json_loads (code_output, 0 , &error); + GNUNET_free (code_output); + ticket_json = json_object_get (code_json, "ticket"); + nonce_json = json_object_get (code_json, "nonce"); + signature_json = json_object_get (code_json, "signature"); + *ticket = NULL; + *nonce = NULL; + + if ((NULL == ticket_json || !json_is_string (ticket_json)) || + (NULL == signature_json || !json_is_string (signature_json))) + { + json_decref (code_json); + return GNUNET_SYSERR; + } + ticket_str = json_string_value (ticket_json); + signature_str = json_string_value (signature_json); + nonce_str = NULL; + if (NULL != nonce_json) + nonce_str = json_string_value (nonce_json); + signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); + if (NULL != nonce_str) + signature_payload_len += strlen (nonce_str); + purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + + signature_payload_len); + purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); + purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str, + strlen (ticket_str), + &purpose[1], + sizeof (struct GNUNET_RECLAIM_Ticket))) + { + GNUNET_free (purpose); + json_decref (code_json); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Cannot parse ticket!\n"); + return GNUNET_SYSERR; + } + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str, + strlen (signature_str), + &signature, + sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) + { + GNUNET_free (purpose); + json_decref (code_json); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Cannot parse signature!\n"); + return GNUNET_SYSERR; + } + *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket); + memcpy (*ticket, + &purpose[1], + sizeof (struct GNUNET_RECLAIM_Ticket)); + if (0 != memcmp (audience, + &(*ticket)->audience, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + GNUNET_free (purpose); + GNUNET_free (*ticket); + json_decref (code_json); + *ticket = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Audience in ticket does not match client!\n"); + return GNUNET_SYSERR; + + } + if (NULL != nonce_str) + memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + nonce_str, + strlen (nonce_str)); + if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, + purpose, + &signature, + &(*ticket)->identity)) + { + GNUNET_free (purpose); + GNUNET_free (*ticket); + json_decref (code_json); + *ticket = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Signature of authZ code invalid!\n"); + return GNUNET_SYSERR; + } + *nonce = GNUNET_strdup (nonce_str); + return GNUNET_OK; +} + +/** + * Build a token response for a token request + * TODO: Maybe we should add the scope here? + * + * @param access_token the access token to include + * @param id_token the id_token to include + * @param expiration_time the expiration time of the token(s) + * @param token_response where to store the response + */ +void +OIDC_build_token_response (const char *access_token, + const char *id_token, + const struct GNUNET_TIME_Relative *expiration_time, + char **token_response) +{ + json_t *root_json; + + root_json = json_object (); + + GNUNET_assert (NULL != access_token); + GNUNET_assert (NULL != id_token); + GNUNET_assert (NULL != expiration_time); + json_object_set_new (root_json, + "access_token", + json_string (access_token)); + json_object_set_new (root_json, + "token_type", + json_string ("Bearer")); + json_object_set_new (root_json, + "expires_in", + json_integer (expiration_time->rel_value_us / (1000 * 1000))); + json_object_set_new (root_json, + "id_token", + json_string (id_token)); + *token_response = json_dumps (root_json, + JSON_INDENT(0) | JSON_COMPACT); + json_decref (root_json); +} + +/** + * Generate a new access token + */ +char* +OIDC_access_token_new () +{ + char* access_token_number; + char* access_token; + uint64_t random_number; + + random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); + GNUNET_asprintf (&access_token_number, "%" PRIu64, random_number); + GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); + return access_token; +} diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h new file mode 100644 index 000000000..7a0f45bf9 --- /dev/null +++ b/src/reclaim/oidc_helper.h @@ -0,0 +1,109 @@ +/* + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ + +/** + * @file reclaim/oidc_helper.h + * @brief helper library for OIDC related functions + * @author Martin Schanzenbach + */ + +#ifndef JWT_H +#define JWT_H + +#define JWT_ALG "alg" + +/* Use 512bit HMAC */ +#define JWT_ALG_VALUE "HS512" + +#define JWT_TYP "typ" + +#define JWT_TYP_VALUE "jwt" + +#define SERVER_ADDRESS "https://reclaim.id" + +/** + * Create a JWT from attributes + * + * @param aud_key the public of the audience + * @param sub_key the public key of the subject + * @param attrs the attribute list + * @param expiration_time the validity of the token + * @param secret_key the key used to sign the JWT + * @return a new base64-encoded JWT string. + */ +char* +OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, + const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, + const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, + const struct GNUNET_TIME_Relative *expiration_time, + const char *nonce, + const char *secret_key); + +/** + * Builds an OIDC authorization code including + * a reclaim ticket and nonce + * + * @param issuer the issuer of the ticket, used to sign the ticket and nonce + * @param ticket the ticket to include in the code + * @param nonce the nonce to include in the code + * @return a new authorization code (caller must free) + */ +char* +OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, + const struct GNUNET_RECLAIM_Ticket *ticket, + const char* nonce); + +/** + * Parse reclaim ticket and nonce from + * authorization code. + * This also verifies the signature in the code. + * + * @param audience the expected audience of the code + * @param code the string representation of the code + * @param ticket where to store the ticket + * @param nonce where to store the nonce + * @return GNUNET_OK if successful, else GNUNET_SYSERR + */ +int +OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, + const char* code, + struct GNUNET_RECLAIM_Ticket **ticket, + char **nonce); + +/** + * Build a token response for a token request + * TODO: Maybe we should add the scope here? + * + * @param access_token the access token to include + * @param id_token the id_token to include + * @param expiration_time the expiration time of the token(s) + * @param token_response where to store the response + */ +void +OIDC_build_token_response (const char *access_token, + const char *id_token, + const struct GNUNET_TIME_Relative *expiration_time, + char **token_response); +/** + * Generate a new access token + */ +char* +OIDC_access_token_new (); + + +#endif diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 0f746f988..06815d9d1 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -38,7 +38,7 @@ #include "gnunet_signatures.h" #include "gnunet_reclaim_attribute_lib.h" #include "gnunet_reclaim_service.h" -#include "jwt.h" +#include "oidc_helper.h" /** * REST root namespace @@ -823,177 +823,6 @@ oidc_iteration_error (void *cls) GNUNET_SCHEDULER_add_now (&do_error, handle); } -static int -parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, - const char* code, - struct GNUNET_RECLAIM_Ticket **ticket, - char **nonce) -{ - json_error_t error; - json_t *code_json; - json_t *ticket_json; - json_t *nonce_json; - json_t *signature_json; - const char *ticket_str; - const char *signature_str; - const char *nonce_str; - char *code_output; - struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; - struct GNUNET_CRYPTO_EcdsaSignature signature; - size_t signature_payload_len; - - code_output = NULL; - GNUNET_STRINGS_base64_decode (code, - strlen(code), - (void**)&code_output); - code_json = json_loads (code_output, 0 , &error); - GNUNET_free (code_output); - ticket_json = json_object_get (code_json, "ticket"); - nonce_json = json_object_get (code_json, "nonce"); - signature_json = json_object_get (code_json, "signature"); - *ticket = NULL; - *nonce = NULL; - - if ((NULL == ticket_json || !json_is_string (ticket_json)) || - (NULL == signature_json || !json_is_string (signature_json))) - { - json_decref (code_json); - return GNUNET_SYSERR; - } - ticket_str = json_string_value (ticket_json); - signature_str = json_string_value (signature_json); - nonce_str = NULL; - if (NULL != nonce_json) - nonce_str = json_string_value (nonce_json); - signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); - if (NULL != nonce_str) - signature_payload_len += strlen (nonce_str); - purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + - signature_payload_len); - purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); - purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); - if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str, - strlen (ticket_str), - &purpose[1], - sizeof (struct GNUNET_RECLAIM_Ticket))) - { - GNUNET_free (purpose); - json_decref (code_json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot parse ticket!\n"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str, - strlen (signature_str), - &signature, - sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) - { - GNUNET_free (purpose); - json_decref (code_json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot parse signature!\n"); - return GNUNET_SYSERR; - } - *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket); - memcpy (*ticket, - &purpose[1], - sizeof (struct GNUNET_RECLAIM_Ticket)); - if (0 != memcmp (audience, - &(*ticket)->audience, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) - { - GNUNET_free (purpose); - GNUNET_free (*ticket); - json_decref (code_json); - *ticket = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Audience in ticket does not match client!\n"); - return GNUNET_SYSERR; - - } - if (NULL != nonce_str) - memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), - nonce_str, - strlen (nonce_str)); - if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, - purpose, - &signature, - &(*ticket)->identity)) - { - GNUNET_free (purpose); - GNUNET_free (*ticket); - json_decref (code_json); - *ticket = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Signature of authZ code invalid!\n"); - return GNUNET_SYSERR; - } - *nonce = GNUNET_strdup (nonce_str); - return GNUNET_OK; -} - -static char* -build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, - const struct GNUNET_RECLAIM_Ticket *ticket, - const char* nonce) -{ - char *ticket_str; - json_t *code_json; - char *signature_payload; - char *signature_str; - char *authz_code; - size_t signature_payload_len; - struct GNUNET_CRYPTO_EcdsaSignature signature; - struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; - - signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); - if (NULL != nonce) - signature_payload_len += strlen (nonce); - - signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); - purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; - purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); - purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); - memcpy (&purpose[1], - ticket, - sizeof (struct GNUNET_RECLAIM_Ticket)); - if (NULL != nonce) - memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), - nonce, - strlen (nonce)); - if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, - purpose, - &signature)) - { - GNUNET_free (signature_payload); - return NULL; - } - signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, - sizeof (signature)); - ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, - sizeof (struct GNUNET_RECLAIM_Ticket)); - - code_json = json_object (); - json_object_set_new (code_json, - "ticket", - json_string (ticket_str)); - if (NULL != nonce) - json_object_set_new (code_json, - "nonce", - json_string (nonce)); - json_object_set_new (code_json, - "signature", - json_string (signature_str)); - authz_code = json_dumps (code_json, - JSON_INDENT(0) | JSON_COMPACT); - GNUNET_free (signature_payload); - GNUNET_free (signature_str); - GNUNET_free (ticket_str); - json_decref (code_json); - return authz_code; -} - - static void get_client_name_result (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, @@ -1011,9 +840,9 @@ get_client_name_result (void *cls, ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); //TODO change if more attributes are needed (see max_age) - code_json_string = build_authz_code (&handle->priv_key, - &handle->ticket, - handle->oidc->nonce); + code_json_string = OIDC_build_authz_code (&handle->priv_key, + &handle->ticket, + handle->oidc->nonce); code_base64_final_string = base_64_encode(code_json_string); GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", handle->redirect_prefix, @@ -1532,36 +1361,19 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle, return; } -/** - * Responds to token url-encoded POST request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) +static int +check_authorization (struct RequestHandle *handle, + struct GNUNET_CRYPTO_EcdsaPublicKey *cid) { - //TODO static strings - struct RequestHandle *handle = cls; struct GNUNET_HashCode cache_key; - char *authorization, *credentials; - char delimiter[]=" "; - char delimiter_user_psw[]=":"; - char *grant_type, *code; - char *user_psw = NULL, *client_id, *psw; - char *expected_psw; + char *authorization; + char *credentials; + char *basic_authorization; + char *client_id; + char *pass; + char *expected_pass; int client_exists = GNUNET_NO; - struct MHD_Response *resp; - char *json_response; - char *jwt_secret; - char *nonce; - /* - * Check Authorization - */ GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, strlen (OIDC_AUTHORIZATION_HEADER_KEY), &cache_key); @@ -1571,80 +1383,75 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, handle->emsg=GNUNET_strdup("invalid_client"); handle->edesc=GNUNET_strdup("missing authorization"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } - authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); + authorization = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map, + &cache_key); //split header in "Basic" and [content] - credentials = strtok (authorization, delimiter); - if (0 != strcmp ("Basic",credentials)) + credentials = strtok (authorization, " "); + if (0 != strcmp ("Basic", credentials)) { handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } - credentials = strtok(NULL, delimiter); + credentials = strtok(NULL, " "); if (NULL == credentials) { handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } - GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw); + GNUNET_STRINGS_base64_decode (credentials, + strlen (credentials), + (void**)&basic_authorization); - if ( NULL == user_psw ) + if ( NULL == basic_authorization ) { handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } - client_id = strtok (user_psw, delimiter_user_psw); + client_id = strtok (basic_authorization, ":"); if ( NULL == client_id ) { - GNUNET_free_non_null(user_psw); + GNUNET_free_non_null(basic_authorization); handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } - psw = strtok (NULL, delimiter_user_psw); - if (NULL == psw) + pass = strtok (NULL, ":"); + if (NULL == pass) { - GNUNET_free_non_null(user_psw); + GNUNET_free_non_null(basic_authorization); handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } //check client password if ( GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", - "psw", &expected_psw) ) + "psw", &expected_pass) ) { - if (0 != strcmp (expected_psw, psw)) + if (0 != strcmp (expected_pass, pass)) { - GNUNET_free_non_null(user_psw); - GNUNET_free(expected_psw); + GNUNET_free_non_null(basic_authorization); + GNUNET_free(expected_pass); handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } - GNUNET_free(expected_psw); + GNUNET_free(expected_pass); } else { - GNUNET_free_non_null(user_psw); + GNUNET_free_non_null(basic_authorization); handle->emsg = GNUNET_strdup("server_error"); handle->edesc = GNUNET_strdup ("gnunet configuration failed"); handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + return GNUNET_SYSERR; } //check client_id @@ -1659,9 +1466,108 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } if (GNUNET_NO == client_exists) { - GNUNET_free_non_null(user_psw); + GNUNET_free_non_null(basic_authorization); handle->emsg=GNUNET_strdup("invalid_client"); handle->response_code = MHD_HTTP_UNAUTHORIZED; + return GNUNET_SYSERR; + } + GNUNET_STRINGS_string_to_data (client_id, + strlen(client_id), + cid, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + + GNUNET_free (client_id); + GNUNET_free (basic_authorization); + return GNUNET_OK; +} + +static int +ego_exists (struct RequestHandle *handle, + struct GNUNET_CRYPTO_EcdsaPublicKey *test_key) +{ + struct EgoEntry *ego_entry; + struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; + + for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) + { + GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); + if (0 == memcmp (&pub_key, + test_key, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + break; + } + } + if (NULL == ego_entry) + return GNUNET_NO; + return GNUNET_YES; +} + +static void +store_ticket_reference (const struct RequestHandle *handle, + const char* access_token, + const struct GNUNET_RECLAIM_Ticket *ticket, + const struct GNUNET_CRYPTO_EcdsaPublicKey *cid) +{ + struct GNUNET_HashCode cache_key; + char *id_ticket_combination; + char *ticket_string; + char *client_id; + + GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); + client_id = GNUNET_STRINGS_data_to_string_alloc (cid, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket, + sizeof (struct GNUNET_RECLAIM_Ticket)); + GNUNET_asprintf(&id_ticket_combination, + "%s;%s", + client_id, + ticket_string); + GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, + &cache_key, + id_ticket_combination, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); + + GNUNET_free (client_id); + GNUNET_free (ticket_string); +} + +/** + * Responds to token url-encoded POST request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_TIME_Relative expiration_time; + struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl; + struct GNUNET_RECLAIM_Ticket *ticket; + struct GNUNET_CRYPTO_EcdsaPublicKey cid; + struct GNUNET_HashCode cache_key; + struct MHD_Response *resp; + char *grant_type; + char *code; + char *json_response; + char *id_token; + char *access_token; + char *jwt_secret; + char *nonce; + int i = 1; + + /* + * Check Authorization + */ + if (GNUNET_SYSERR == check_authorization (handle, + &cid)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "OIDC authorization for token endpoint failed\n"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -1673,27 +1579,25 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, //TODO Do not allow multiple equal parameter names //REQUIRED grant_type GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->url_param_map, &cache_key) ) + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("missing parameter grant_type"); handle->response_code = MHD_HTTP_BAD_REQUEST; GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - grant_type = GNUNET_CONTAINER_multihashmap_get ( - handle->rest_handle->url_param_map, &cache_key); + grant_type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &cache_key); //REQUIRED code GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->url_param_map, &cache_key) ) + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key)) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("missing parameter code"); handle->response_code = MHD_HTTP_BAD_REQUEST; @@ -1706,11 +1610,10 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, //REQUIRED redirect_uri GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), &cache_key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains ( - handle->rest_handle->url_param_map, &cache_key) ) + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &cache_key) ) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); handle->response_code = MHD_HTTP_BAD_REQUEST; @@ -1721,21 +1624,18 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, //Check parameter grant_type == "authorization_code" if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) { - GNUNET_free_non_null(user_psw); handle->emsg=GNUNET_strdup("unsupported_grant_type"); handle->response_code = MHD_HTTP_BAD_REQUEST; GNUNET_SCHEDULER_add_now (&do_error, handle); return; } GNUNET_CRYPTO_hash (code, strlen (code), &cache_key); - int i = 1; - if ( GNUNET_SYSERR - == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, - &cache_key, - &i, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) + if (GNUNET_SYSERR == + GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, + &cache_key, + &i, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("Cannot use the same code more than once"); handle->response_code = MHD_HTTP_BAD_REQUEST; @@ -1744,18 +1644,11 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } //decode code - struct GNUNET_CRYPTO_EcdsaPublicKey cid; - GNUNET_STRINGS_string_to_data (client_id, - strlen(client_id), - &cid, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - struct GNUNET_RECLAIM_Ticket *ticket; - if(GNUNET_OK != parse_authz_code (&cid, - code, - &ticket, - &nonce)) + if(GNUNET_OK != OIDC_parse_authz_code (&cid, + code, + &ticket, + &nonce)) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("invalid code"); handle->response_code = MHD_HTTP_BAD_REQUEST; @@ -1763,27 +1656,13 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, return; } - // this is the current client (relying party) - struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; - GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); - if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) - { - GNUNET_free_non_null(user_psw); - handle->emsg = GNUNET_strdup("invalid_request"); - handle->edesc = GNUNET_strdup("invalid code"); - handle->response_code = MHD_HTTP_BAD_REQUEST; - GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free(ticket); - return; - } - //create jwt - struct GNUNET_TIME_Relative expiration_time; - if ( GNUNET_OK - != GNUNET_CONFIGURATION_get_value_time(cfg, "reclaim-rest-plugin", - "expiration_time", &expiration_time) ) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time(cfg, + "reclaim-rest-plugin", + "expiration_time", + &expiration_time)) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("server_error"); handle->edesc = GNUNET_strdup ("gnunet configuration failed"); handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; @@ -1792,34 +1671,21 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, return; } - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); //TODO OPTIONAL acr,amr,azp - - struct EgoEntry *ego_entry; - for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) - { - GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); - if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) - { - break; - } - } - if ( NULL == ego_entry ) + if (GNUNET_NO == ego_exists (handle, + &ticket->audience)) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("invalid code..."); handle->response_code = MHD_HTTP_BAD_REQUEST; GNUNET_SCHEDULER_add_now (&do_error, handle); GNUNET_free(ticket); - return; } if ( GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", "jwt_secret", &jwt_secret) ) { - GNUNET_free_non_null(user_psw); handle->emsg = GNUNET_strdup("invalid_request"); handle->edesc = GNUNET_strdup("No signing secret configured!"); handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; @@ -1827,56 +1693,31 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_free(ticket); return; } - char *id_token = jwt_create_from_list(&ticket->audience, - &ticket->identity, - cl, - &expiration_time, - (NULL != nonce) ? nonce : NULL, - jwt_secret); - - //Create random access_token - char* access_token_number; - char* access_token; - uint64_t random_number; - random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); - GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number); - GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); - - - - //TODO OPTIONAL add refresh_token and scope - GNUNET_asprintf (&json_response, - "{ \"access_token\" : \"%s\", " - "\"token_type\" : \"Bearer\", " - "\"expires_in\" : %d, " - "\"id_token\" : \"%s\"}", - access_token, - expiration_time, - id_token); - GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); - char *id_ticket_combination; - char *ticket_string; - ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket, - sizeof (struct GNUNET_RECLAIM_Ticket)); - GNUNET_asprintf(&id_ticket_combination, - "%s;%s", - client_id, - ticket_string); - GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, - &cache_key, - id_ticket_combination, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); - + //TODO We should collect the attributes here. cl always empty + cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + id_token = OIDC_id_token_new (&ticket->audience, + &ticket->identity, + cl, + &expiration_time, + (NULL != nonce) ? nonce : NULL, + jwt_secret); + access_token = OIDC_access_token_new (); + OIDC_build_token_response (access_token, + id_token, + &expiration_time, + &json_response); + + store_ticket_reference (handle, + access_token, + ticket, + &cid); resp = GNUNET_REST_create_response (json_response); MHD_add_response_header (resp, "Cache-Control", "no-store"); MHD_add_response_header (resp, "Pragma", "no-cache"); MHD_add_response_header (resp, "Content-Type", "application/json"); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl); - GNUNET_free(access_token_number); GNUNET_free(access_token); - GNUNET_free(user_psw); GNUNET_free(json_response); GNUNET_free(ticket); GNUNET_free(id_token); -- cgit v1.2.3 From 6c4bd20776ce2dd060beee9abd7baaf7d38c4988 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 13:32:54 +0200 Subject: fixes --- src/reclaim/oidc_helper.c | 4 ++-- src/reclaim/plugin_rest_openid_connect.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c index 9a99c5668..5ad1ff0a0 100644 --- a/src/reclaim/oidc_helper.c +++ b/src/reclaim/oidc_helper.c @@ -364,8 +364,8 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, } if (NULL != nonce_str) - memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), - nonce_str, + memcpy (nonce_str, + &purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), strlen (nonce_str)); if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, purpose, diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 06815d9d1..1846df901 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -903,8 +903,7 @@ lookup_redirect_uri_result (void *cls, (unsigned char) '/'); *pos = '\0'; handle->redirect_suffix = GNUNET_strdup (pos + 1); - GNUNET_free (tmp); - + GNUNET_STRINGS_string_to_data (tmp_key_str, strlen (tmp_key_str), &redirect_zone, @@ -917,6 +916,8 @@ lookup_redirect_uri_result (void *cls, handle, &get_client_name_result, handle); + GNUNET_free (tmp); + } /** @@ -1476,7 +1477,6 @@ check_authorization (struct RequestHandle *handle, cid, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - GNUNET_free (client_id); GNUNET_free (basic_authorization); return GNUNET_OK; } -- cgit v1.2.3 From e3383d7cd239905487bfae46967256bb2a1a98ab Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 13:55:18 +0200 Subject: fix --- src/reclaim/oidc_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c index 5ad1ff0a0..f63e38e9a 100644 --- a/src/reclaim/oidc_helper.c +++ b/src/reclaim/oidc_helper.c @@ -226,7 +226,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); if (NULL != nonce) - memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + memcpy (((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket), nonce, strlen (nonce)); if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, @@ -365,7 +365,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, } if (NULL != nonce_str) memcpy (nonce_str, - &purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), + ((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket), strlen (nonce_str)); if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, purpose, -- cgit v1.2.3 From a84e3a97d067bb36d350ee6acb09772fcda37127 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 14:10:33 +0200 Subject: fix signature check --- src/reclaim/oidc_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c index f63e38e9a..1e9e64fec 100644 --- a/src/reclaim/oidc_helper.c +++ b/src/reclaim/oidc_helper.c @@ -364,8 +364,8 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, } if (NULL != nonce_str) - memcpy (nonce_str, - ((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket), + memcpy (((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket), + nonce_str, strlen (nonce_str)); if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, purpose, -- cgit v1.2.3 From 5fb272d662eca0707b1a5c7747ae476f8157d332 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 19:29:44 +0200 Subject: fix --- src/gns/plugin_rest_gns.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 2b729db54..e76a5d116 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -281,6 +281,15 @@ gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) return record_obj; } + +static void +do_cleanup (void *cls) +{ + struct LookupHandle *handle = cls; + cleanup_handle (handle); +} + + /** * Function called with the result of a GNS lookup. * @@ -325,7 +334,7 @@ process_lookup_result (void *cls, uint32_t rd_count, resp = GNUNET_REST_create_response (result); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&do_cleanup, handle); } -- cgit v1.2.3 From 94c9fde8f4136432bb4cbc99ba5102702279df14 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 22:10:47 +0200 Subject: switch to gnsrecord reclaim records for OIDC clients --- src/include/gnunet_gnsrecord_lib.h | 10 +++++ src/reclaim/plugin_gnsrecord_reclaim.c | 6 +++ src/reclaim/plugin_rest_openid_connect.c | 65 ++++++++++++++++++-------------- 3 files changed, 53 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 20846238b..693cc6cdb 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -131,6 +131,16 @@ extern "C" */ #define GNUNET_GNSRECORD_TYPE_ABE_MASTER 65551 +/** + * Record type for reclaim OIDC clients + */ +#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT 65552 + +/** + * Record type for reclaim OIDC redirect URIs + */ +#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT 65553 + /** * Flags that can be set for a record. */ diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c index 0322df752..181a4bbc2 100644 --- a/src/reclaim/plugin_gnsrecord_reclaim.c +++ b/src/reclaim/plugin_gnsrecord_reclaim.c @@ -57,6 +57,8 @@ value_to_string (void *cls, return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_ABE_KEY: case GNUNET_GNSRECORD_TYPE_ABE_MASTER: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: return GNUNET_STRINGS_data_to_string_alloc (data, data_size); case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED ecdhe_privkey = data; @@ -118,6 +120,8 @@ string_to_value (void *cls, return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_ABE_KEY: case GNUNET_GNSRECORD_TYPE_ABE_MASTER: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT: return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, @@ -181,6 +185,8 @@ static struct { { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY }, { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER }, { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA }, + { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT }, + { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT }, { NULL, UINT32_MAX } }; diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 1846df901..99459427c 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -886,38 +886,47 @@ lookup_redirect_uri_result (void *cls, struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone; handle->gns_op = NULL; - if (1 != rd_count) + if (0 == rd_count) { handle->emsg = GNUNET_strdup("server_error"); handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found."); GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); return; } - tmp = GNUNET_strdup (rd->data); - pos = strrchr (tmp, - (unsigned char) '.'); - *pos = '\0'; - handle->redirect_prefix = GNUNET_strdup (tmp); - tmp_key_str = pos + 1; - pos = strchr (tmp_key_str, - (unsigned char) '/'); - *pos = '\0'; - handle->redirect_suffix = GNUNET_strdup (pos + 1); - - GNUNET_STRINGS_string_to_data (tmp_key_str, - strlen (tmp_key_str), - &redirect_zone, - sizeof (redirect_zone)); - - GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, - &handle->priv_key, - &redirect_zone, - &get_client_name_error, - handle, - &get_client_name_result, - handle); - GNUNET_free (tmp); - + for (int i = 0; i < rd_count; i++) + { + if (0 != strcmp (rd[0].data, + handle->oidc->redirect_uri)) + continue; + tmp = GNUNET_strdup (rd[0].data); + pos = strrchr (tmp, + (unsigned char) '.'); + *pos = '\0'; + handle->redirect_prefix = GNUNET_strdup (tmp); + tmp_key_str = pos + 1; + pos = strchr (tmp_key_str, + (unsigned char) '/'); + *pos = '\0'; + handle->redirect_suffix = GNUNET_strdup (pos + 1); + + GNUNET_STRINGS_string_to_data (tmp_key_str, + strlen (tmp_key_str), + &redirect_zone, + sizeof (redirect_zone)); + + GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, + &handle->priv_key, + &redirect_zone, + &get_client_name_error, + handle, + &get_client_name_result, + handle); + GNUNET_free (tmp); + return; + } + handle->emsg = GNUNET_strdup("server_error"); + handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found."); + GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); } /** @@ -940,9 +949,9 @@ oidc_ticket_issue_cb (void* cls, return; } handle->gns_op = GNUNET_GNS_lookup (handle->gns_handle, - handle->oidc->redirect_uri, + "+", &handle->oidc->client_pkey, - GNUNET_DNSPARSER_TYPE_TXT, + GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT, GNUNET_GNS_LO_DEFAULT, &lookup_redirect_uri_result, handle); -- cgit v1.2.3 From 4336c9fddab44104eef6a480f354a92b6befa255 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 22:58:20 +0200 Subject: fix wrong record type --- src/reclaim/plugin_gnsrecord_reclaim.c | 8 ++++---- src/reclaim/plugin_rest_openid_connect.c | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c index 181a4bbc2..ecd1d6e77 100644 --- a/src/reclaim/plugin_gnsrecord_reclaim.c +++ b/src/reclaim/plugin_gnsrecord_reclaim.c @@ -54,11 +54,11 @@ value_to_string (void *cls, case GNUNET_GNSRECORD_TYPE_ID_ATTR: return GNUNET_STRINGS_data_to_string_alloc (data, data_size); case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_ABE_KEY: case GNUNET_GNSRECORD_TYPE_ABE_MASTER: - case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT: - case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: return GNUNET_STRINGS_data_to_string_alloc (data, data_size); case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED ecdhe_privkey = data; @@ -115,13 +115,13 @@ string_to_value (void *cls, *data, *data_size); case GNUNET_GNSRECORD_TYPE_ID_TOKEN: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_ABE_KEY: case GNUNET_GNSRECORD_TYPE_ABE_MASTER: - case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: - case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT: return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 99459427c..24673c692 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -895,10 +895,12 @@ lookup_redirect_uri_result (void *cls, } for (int i = 0; i < rd_count; i++) { - if (0 != strcmp (rd[0].data, + if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type) + continue; + if (0 != strcmp (rd[i].data, handle->oidc->redirect_uri)) continue; - tmp = GNUNET_strdup (rd[0].data); + tmp = GNUNET_strdup (rd[i].data); pos = strrchr (tmp, (unsigned char) '.'); *pos = '\0'; -- cgit v1.2.3 From 60b3288f5af19525e9d6dfbd65efd39f0854575f Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 23 Jul 2018 23:14:17 +0200 Subject: fix --- src/reclaim/plugin_gnsrecord_reclaim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c index ecd1d6e77..781b88abc 100644 --- a/src/reclaim/plugin_gnsrecord_reclaim.c +++ b/src/reclaim/plugin_gnsrecord_reclaim.c @@ -115,7 +115,7 @@ string_to_value (void *cls, *data, *data_size); case GNUNET_GNSRECORD_TYPE_ID_TOKEN: - case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: + case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT: case GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT: *data = GNUNET_strdup (s); *data_size = strlen (s); -- cgit v1.2.3 From 4cc2532d1d842721030f7ac386b2eacc85e0d0b9 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 24 Jul 2018 21:49:47 +0200 Subject: also return empty egos --- src/identity/plugin_rest_identity.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 52685c52e..355d75fd9 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -436,13 +436,6 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, json_decref (name_str); GNUNET_JSONAPI_document_resource_add (json_document, json_resource); } - if (0 == GNUNET_JSONAPI_document_resource_count (json_document)) - { - GNUNET_JSONAPI_document_delete (json_document); - handle->emsg = GNUNET_strdup ("No identities found!"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } GNUNET_JSONAPI_document_serialize (json_document, &result_str); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); -- cgit v1.2.3 From 3430620e67bacdb1910027f29a9b83e5c251a393 Mon Sep 17 00:00:00 2001 From: lurchi Date: Tue, 24 Jul 2018 23:37:57 +0200 Subject: Remove restrictive and unnecessary assert Using the SCHEDULER_add* functions is now allowed before the first call to GNUNET_SCHEDULER_do_work. --- src/util/scheduler.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 93d133d1b..014288944 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -965,8 +965,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) /* scheduler must be running */ GNUNET_assert (NULL != scheduler_driver); - GNUNET_assert ( (NULL != active_task) || - (GNUNET_NO == task->lifeness) ); is_fd_task = (NULL != task->fds); if (is_fd_task) { @@ -1056,9 +1054,9 @@ GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback tas { struct GNUNET_SCHEDULER_Task *t; + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); GNUNET_assert (NULL != task); - GNUNET_assert ((NULL != active_task) || - (GNUNET_SCHEDULER_REASON_STARTUP == reason)); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); t->read_fd = -1; t->write_fd = -1; @@ -1099,7 +1097,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_SCHEDULER_Task *prev; - GNUNET_assert (NULL != active_task); + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); t->callback = task; @@ -1286,7 +1285,8 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, { struct GNUNET_SCHEDULER_Task *t; - GNUNET_assert (NULL != active_task); + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); t->callback = task; @@ -1403,7 +1403,8 @@ add_without_sets (struct GNUNET_TIME_Relative delay, { struct GNUNET_SCHEDULER_Task *t; - GNUNET_assert (NULL != active_task); + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); init_fd_info (t, @@ -1832,7 +1833,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, /* scheduler must be running */ GNUNET_assert (NULL != scheduler_driver); - GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); int no_rs = (NULL == rs); int no_ws = (NULL == ws); @@ -2164,12 +2164,12 @@ struct GNUNET_SCHEDULER_Handle * GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver) { struct GNUNET_SCHEDULER_Handle *sh; - struct GNUNET_SCHEDULER_Task tsk; const struct GNUNET_DISK_FileHandle *pr; - /* general set-up */ - GNUNET_assert (NULL == active_task); + /* scheduler must not be running */ + GNUNET_assert (NULL == scheduler_driver); GNUNET_assert (NULL == shutdown_pipe_handle); + /* general set-up */ sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle); shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, @@ -2204,10 +2204,6 @@ GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver) /* Setup initial tasks */ current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; current_lifeness = GNUNET_NO; - memset (&tsk, - 0, - sizeof (tsk)); - active_task = &tsk; install_parent_control_task = GNUNET_SCHEDULER_add_now (&install_parent_control_handler, NULL); @@ -2217,7 +2213,6 @@ GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver) &shutdown_pipe_cb, NULL); current_lifeness = GNUNET_YES; - active_task = NULL; scheduler_driver->set_wakeup (scheduler_driver->cls, get_timeout ()); /* begin main event loop */ -- cgit v1.2.3 From 5794e80239687f6fe88311bb7156d105d30170de Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Wed, 25 Jul 2018 17:53:31 +0200 Subject: fix rps service: better handling of cadet channels --- src/rps/gnunet-service-rps.c | 282 ++++++++++++++++++++++++++++++++----------- 1 file changed, 214 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 12794945e..fcb68b724 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -163,6 +163,11 @@ struct PendingMessage const char *type; }; +/** + * @brief Context for a channel + */ +struct ChannelCtx; + /** * Struct used to keep track of other peer's status * @@ -181,7 +186,7 @@ struct PeerContext /** * Channel open to client. */ - struct GNUNET_CADET_Channel *send_channel; + struct ChannelCtx *send_channel_ctx; /** * Flags to the sending channel @@ -191,7 +196,7 @@ struct PeerContext /** * Channel open from client. */ - struct GNUNET_CADET_Channel *recv_channel; // unneeded? + struct ChannelCtx *recv_channel_ctx; // unneeded? /** * Flags to the receiving channel @@ -264,6 +269,39 @@ struct PeersIteratorCls void *cls; }; +/** + * @brief Context for a channel + */ +struct ChannelCtx +{ + /** + * @brief Meant to be used in a DLL + */ + struct ChannelCtx *next; + struct ChannelCtx *prev; + + /** + * @brief The channel itself + */ + struct GNUNET_CADET_Channel *channel; + + /** + * @brief The peer context associated with the channel + */ + struct PeerContext *peer_ctx; + + /** + * @brief Scheduled task that will destroy this context + */ + struct GNUNET_SCHEDULER_Task *destruction_task; +}; + +/** + * @brief The DLL of channel contexts + */ +static struct ChannelCtx *channel_ctx_head; +static struct ChannelCtx *channel_ctx_tail; + /** * @brief Hashmap of valid peers. */ @@ -387,8 +425,8 @@ Peers_check_connected (const struct GNUNET_PeerIdentity *peer) /* Get the context */ peer_ctx = get_peer_ctx (peer); /* If we have no channel to this peer we don't know whether it's online */ - if ( (NULL == peer_ctx->send_channel) && - (NULL == peer_ctx->recv_channel) ) + if ( (NULL == peer_ctx->send_channel_ctx) && + (NULL == peer_ctx->recv_channel_ctx) ) { Peers_unset_peer_flag (peer, Peers_ONLINE); return GNUNET_NO; @@ -575,6 +613,24 @@ handle_peer_pull_reply (void *cls, /* End declaration of handlers */ +/** + * @brief Allocate memory for a new channel context and insert it into DLL + * + * @param peer_ctx context of the according peer + * + * @return The channel context + */ +static struct ChannelCtx * +add_channel_ctx (struct PeerContext *peer_ctx); + +/** + * @brief Remove the channel context from the DLL and free the memory. + * + * @param channel_ctx The channel context. + */ +static void +remove_channel_ctx (struct ChannelCtx *channel_ctx); + /** * @brief Get the channel of a peer. If not existing, create. @@ -610,16 +666,17 @@ get_channel (const struct GNUNET_PeerIdentity *peer) peer_ctx = get_peer_ctx (peer); - if (NULL == peer_ctx->send_channel) + if (NULL == peer_ctx->send_channel_ctx) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to establish channel to peer %s\n", GNUNET_i2s (peer)); ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity); *ctx_peer = *peer; - peer_ctx->send_channel = + peer_ctx->send_channel_ctx = add_channel_ctx (peer_ctx); + peer_ctx->send_channel_ctx->channel = GNUNET_CADET_channel_create (cadet_handle, - (struct GNUNET_PeerIdentity *) ctx_peer, /* context */ + peer_ctx->send_channel_ctx, /* context */ peer, &port, GNUNET_CADET_OPTION_RELIABLE, @@ -627,8 +684,9 @@ get_channel (const struct GNUNET_PeerIdentity *peer) cleanup_destroyed_channel, /* Disconnect handler */ cadet_handlers); } - GNUNET_assert (NULL != peer_ctx->send_channel); - return peer_ctx->send_channel; + GNUNET_assert (NULL != peer_ctx->send_channel_ctx); + GNUNET_assert (NULL != peer_ctx->send_channel_ctx->channel); + return peer_ctx->send_channel_ctx->channel; } @@ -1199,7 +1257,7 @@ Peers_check_removable (const struct GNUNET_PeerIdentity *peer) } peer_ctx = get_peer_ctx (peer); - if ( (NULL != peer_ctx->recv_channel) || + if ( (NULL != peer_ctx->recv_channel_ctx) || (NULL != peer_ctx->pending_messages_head) || (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) ) { @@ -1269,23 +1327,28 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) peer_ctx->liveliness_check_pending = NULL; } channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING); - if (NULL != peer_ctx->send_channel && + if (NULL != peer_ctx->send_channel_ctx && GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying send channel\n"); - GNUNET_CADET_channel_destroy (peer_ctx->send_channel); - peer_ctx->send_channel = NULL; + GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); + remove_channel_ctx (peer_ctx->send_channel_ctx); + peer_ctx->send_channel_ctx = NULL; peer_ctx->mq = NULL; } channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING); - if (NULL != peer_ctx->recv_channel && + if (NULL != peer_ctx->recv_channel_ctx && GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying recv channel\n"); - GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); - peer_ctx->recv_channel = NULL; + GNUNET_CADET_channel_destroy (peer_ctx->recv_channel_ctx->channel); + if (NULL != peer_ctx->recv_channel_ctx) + { + remove_channel_ctx (peer_ctx->recv_channel_ctx); + } + peer_ctx->recv_channel_ctx = NULL; } GNUNET_free (peer_ctx->send_channel_flags); @@ -1496,7 +1559,7 @@ Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer) const struct PeerContext *peer_ctx; peer_ctx = get_peer_ctx (peer); - if (NULL != peer_ctx->recv_channel) + if (NULL != peer_ctx->recv_channel_ctx) { return GNUNET_YES; } @@ -1521,6 +1584,7 @@ Peers_handle_inbound_channel (void *cls, { struct PeerContext *peer_ctx; struct GNUNET_PeerIdentity *ctx_peer; + struct ChannelCtx *channel_ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "New channel was established to us (Peer %s).\n", @@ -1531,6 +1595,8 @@ Peers_handle_inbound_channel (void *cls, set_peer_live (peer_ctx); ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity); *ctx_peer = *initiator; + channel_ctx = add_channel_ctx (peer_ctx); + channel_ctx->channel = channel; /* We only accept one incoming channel per peer */ if (GNUNET_YES == Peers_check_peer_send_intention (initiator)) { @@ -1540,13 +1606,14 @@ Peers_handle_inbound_channel (void *cls, set_channel_flag (peer_ctx->recv_channel_flags, Peers_CHANNEL_ESTABLISHED_TWICE); //GNUNET_CADET_channel_destroy (channel); - GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); - peer_ctx->recv_channel = channel; + GNUNET_CADET_channel_destroy (peer_ctx->recv_channel_ctx->channel); + remove_channel_ctx (peer_ctx->recv_channel_ctx); + peer_ctx->recv_channel_ctx = channel_ctx; /* return the channel context */ - return ctx_peer; + return channel_ctx; } - peer_ctx->recv_channel = channel; - return ctx_peer; + peer_ctx->recv_channel_ctx = channel_ctx; + return channel_ctx; } @@ -1568,7 +1635,7 @@ Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer) return GNUNET_NO; } peer_ctx = get_peer_ctx (peer); - if (NULL == peer_ctx->send_channel) + if (NULL == peer_ctx->send_channel_ctx) { return GNUNET_NO; } @@ -1601,12 +1668,14 @@ Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer, } peer_ctx = get_peer_ctx (peer); if ( (Peers_CHANNEL_ROLE_SENDING == role) && - (channel == peer_ctx->send_channel) ) + (NULL != peer_ctx->send_channel_ctx) && + (channel == peer_ctx->send_channel_ctx->channel) ) { return GNUNET_YES; } if ( (Peers_CHANNEL_ROLE_RECEIVING == role) && - (channel == peer_ctx->recv_channel) ) + (NULL != peer_ctx->recv_channel_ctx) && + (channel == peer_ctx->recv_channel_ctx->channel) ) { return GNUNET_YES; } @@ -1636,11 +1705,11 @@ Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer) return GNUNET_NO; } peer_ctx = get_peer_ctx (peer); - if (NULL != peer_ctx->send_channel) + if (NULL != peer_ctx->send_channel_ctx) { set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN); - GNUNET_CADET_channel_destroy (peer_ctx->send_channel); - peer_ctx->send_channel = NULL; + GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); + peer_ctx->send_channel_ctx = NULL; peer_ctx->mq = NULL; (void) Peers_check_connected (peer); return GNUNET_YES; @@ -1648,6 +1717,35 @@ Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer) return GNUNET_NO; } +static void +destroy_channel (void *cls) +{ + struct ChannelCtx *channel_ctx = cls; + struct PeerContext *peer_ctx = channel_ctx->peer_ctx; + uint32_t *channel_flag; + + channel_ctx = NULL; + GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); + channel_flag = Peers_get_channel_flag (&peer_ctx->peer_id, Peers_CHANNEL_ROLE_SENDING); + Peers_set_channel_flag (channel_flag, Peers_CHANNEL_DESTROING); + remove_channel_ctx (peer_ctx->send_channel_ctx); + peer_ctx->send_channel_ctx = NULL; + if (channel_ctx == peer_ctx->send_channel_ctx) + { + peer_ctx->mq = NULL; + } +} + +static void +schedule_channel_destruction (struct ChannelCtx *channel_ctx) +{ + if (NULL != channel_ctx->destruction_task) + { + channel_ctx->destruction_task = + GNUNET_SCHEDULER_add_now (destroy_channel, channel_ctx); + } +} + /** * This is called when a channel is destroyed. * @@ -1658,9 +1756,9 @@ void Peers_cleanup_destroyed_channel (void *cls, const struct GNUNET_CADET_Channel *channel) { - struct GNUNET_PeerIdentity *peer = cls; - struct PeerContext *peer_ctx; - uint32_t *channel_flag; + struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; + struct PeerContext *peer_ctx = channel_ctx->peer_ctx; if (GNUNET_NO == Peers_check_peer_known (peer)) {/* We don't want to implicitly create a context that we're about to kill */ @@ -1669,7 +1767,6 @@ Peers_cleanup_destroyed_channel (void *cls, GNUNET_i2s (peer)); return; } - peer_ctx = get_peer_ctx (peer); /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY * flag will be set. In this case simply make sure that the channels are @@ -1679,30 +1776,23 @@ Peers_cleanup_destroyed_channel (void *cls, {/* We initiatad the destruction of this particular peer */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer is in the process of being destroyed\n"); - if (channel == peer_ctx->send_channel) + if (channel == channel_ctx->channel) { - peer_ctx->send_channel = NULL; + peer_ctx->send_channel_ctx = NULL; peer_ctx->mq = NULL; } - else if (channel == peer_ctx->recv_channel) + else if (channel == peer_ctx->recv_channel_ctx->channel) { - peer_ctx->recv_channel = NULL; + peer_ctx->recv_channel_ctx = NULL; } - if (NULL != peer_ctx->send_channel) + if (NULL != peer_ctx->send_channel_ctx) { - GNUNET_CADET_channel_destroy (peer_ctx->send_channel); - channel_flag = Peers_get_channel_flag (&peer_ctx->peer_id, Peers_CHANNEL_ROLE_SENDING); - Peers_set_channel_flag (channel_flag, Peers_CHANNEL_DESTROING); - peer_ctx->send_channel = NULL; - peer_ctx->mq = NULL; + schedule_channel_destruction (peer_ctx->send_channel_ctx); } - if (NULL != peer_ctx->recv_channel) + if (NULL != peer_ctx->recv_channel_ctx) { - GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); - channel_flag = Peers_get_channel_flag (&peer_ctx->peer_id, Peers_CHANNEL_ROLE_RECEIVING); - Peers_set_channel_flag (channel_flag, Peers_CHANNEL_DESTROING); - peer_ctx->recv_channel = NULL; + schedule_channel_destruction (peer_ctx->recv_channel_ctx); } /* Set the #Peers_ONLINE flag accordingly */ (void) Peers_check_connected (peer); @@ -1713,20 +1803,22 @@ Peers_cleanup_destroyed_channel (void *cls, { /* We did not initiate the destruction of this peer */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer is NOT in the process of being destroyed\n"); - if (channel == peer_ctx->send_channel) + if ( (NULL != peer_ctx->send_channel_ctx) && + (channel == peer_ctx->send_channel_ctx->channel) ) { /* Something (but us) killd the channel - clean up peer */ LOG (GNUNET_ERROR_TYPE_DEBUG, "send channel (%s) was destroyed - cleaning up\n", GNUNET_i2s (peer)); - peer_ctx->send_channel = NULL; + peer_ctx->send_channel_ctx = NULL; peer_ctx->mq = NULL; } - else if (channel == peer_ctx->recv_channel) + else if ( (NULL != peer_ctx->recv_channel_ctx) && + (channel == peer_ctx->recv_channel_ctx->channel) ) { /* Other peer doesn't want to send us messages anymore */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %s destroyed recv channel - cleaning up channel\n", GNUNET_i2s (peer)); - peer_ctx->recv_channel = NULL; + peer_ctx->recv_channel_ctx = NULL; } else { @@ -1818,7 +1910,7 @@ Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer) GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer)); peer_ctx = get_peer_ctx (peer); - return peer_ctx->recv_channel; + return peer_ctx->recv_channel_ctx->channel; } /*********************************************************************** * /Old gnunet-service-rps_peers.c @@ -2654,6 +2746,35 @@ clean_peer (const struct GNUNET_PeerIdentity *peer) } } +/** + * @brief Allocate memory for a new channel context and insert it into DLL + * + * @param peer_ctx context of the according peer + * + * @return The channel context + */ +static struct ChannelCtx * +add_channel_ctx (struct PeerContext *peer_ctx) +{ + struct ChannelCtx *channel_ctx; + channel_ctx = GNUNET_new (struct ChannelCtx); + channel_ctx->peer_ctx = peer_ctx; + GNUNET_CONTAINER_DLL_insert (channel_ctx_head, channel_ctx_tail, channel_ctx); + return channel_ctx; +} + +/** + * @brief Remove the channel context from the DLL and free the memory. + * + * @param channel_ctx The channel context. + */ +static void +remove_channel_ctx (struct ChannelCtx *channel_ctx) +{ + GNUNET_CONTAINER_DLL_remove (channel_ctx_head, channel_ctx_tail, channel_ctx); + GNUNET_free (channel_ctx); +} + /** * @brief This is called when a channel is destroyed. * @@ -2670,7 +2791,8 @@ static void cleanup_destroyed_channel (void *cls, const struct GNUNET_CADET_Channel *channel) { - struct GNUNET_PeerIdentity *peer = cls; + struct ChannelCtx *channel_ctx = cls; + struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; uint32_t *channel_flag; struct PeerContext *peer_ctx; @@ -2681,7 +2803,7 @@ cleanup_destroyed_channel (void *cls, LOG (GNUNET_ERROR_TYPE_WARNING, "channel (%s) without associated context was destroyed\n", GNUNET_i2s (peer)); - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); return; } @@ -2710,7 +2832,21 @@ cleanup_destroyed_channel (void *cls, to_file (file_name_view_log, "-%s\t(cleanup channel, ourself)", GNUNET_i2s_full (peer)); - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); + if (peer_ctx->send_channel_ctx == channel_ctx) + { + peer_ctx->send_channel_ctx = NULL; + } + else if (peer_ctx->recv_channel_ctx == channel_ctx) + { + peer_ctx->recv_channel_ctx = NULL; + } + else + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Trying to remove channel_ctx that is not associated with a peer\n"); + GNUNET_assert (0); + } return; } @@ -2726,7 +2862,7 @@ cleanup_destroyed_channel (void *cls, { /* We are about to clean the sending channel. Clean the respective * context */ Peers_cleanup_destroyed_channel (cls, channel); - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); return; } else @@ -2734,7 +2870,7 @@ cleanup_destroyed_channel (void *cls, * open. It probably went down. Remove it from our knowledge. */ Peers_cleanup_destroyed_channel (cls, channel); remove_peer (peer); - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); return; } } @@ -2751,7 +2887,7 @@ cleanup_destroyed_channel (void *cls, { /* Other peer tried to establish a channel to us twice. We do not accept * that. Clean the context. */ Peers_cleanup_destroyed_channel (cls, channel); - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); return; } else @@ -2759,7 +2895,7 @@ cleanup_destroyed_channel (void *cls, * it. */ Peers_cleanup_destroyed_channel (cls, channel); clean_peer (peer); - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); return; } } @@ -2768,7 +2904,7 @@ cleanup_destroyed_channel (void *cls, LOG (GNUNET_ERROR_TYPE_WARNING, "Destroyed channel is neither sending nor receiving channel\n"); } - GNUNET_free (peer); + remove_channel_ctx (channel_ctx); } /*********************************************************************** @@ -3163,11 +3299,12 @@ static void handle_peer_check (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct GNUNET_PeerIdentity *peer = cls; + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer)); - GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); + GNUNET_CADET_receive_done (channel_ctx->channel); } /** @@ -3183,7 +3320,8 @@ static void handle_peer_push (void *cls, const struct GNUNET_MessageHeader *msg) { - const struct GNUNET_PeerIdentity *peer = cls; + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; // (check the proof of work (?)) @@ -3228,7 +3366,7 @@ handle_peer_push (void *cls, CustomPeerMap_put (push_map, peer); GNUNET_break_op (Peers_check_peer_known (peer)); - GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); + GNUNET_CADET_receive_done (channel_ctx->channel); } @@ -3244,7 +3382,8 @@ static void handle_peer_pull_request (void *cls, const struct GNUNET_MessageHeader *msg) { - struct GNUNET_PeerIdentity *peer = cls; + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; const struct GNUNET_PeerIdentity *view_array; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer)); @@ -3267,7 +3406,7 @@ handle_peer_pull_request (void *cls, #endif /* ENABLE_MALICIOUS */ GNUNET_break_op (Peers_check_peer_known (peer)); - GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); + GNUNET_CADET_receive_done (channel_ctx->channel); view_array = View_get_as_array (); send_pull_reply (peer, view_array, View_size ()); } @@ -3324,8 +3463,9 @@ static void handle_peer_pull_reply (void *cls, const struct GNUNET_RPS_P2P_PullReplyMessage *msg) { + const struct ChannelCtx *channel_ctx = cls; + const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id; const struct GNUNET_PeerIdentity *peers; - struct GNUNET_PeerIdentity *sender = cls; uint32_t i; #ifdef ENABLE_MALICIOUS struct AttackedPeer *tmp_att_peer; @@ -3393,7 +3533,7 @@ handle_peer_pull_reply (void *cls, clean_peer (sender); GNUNET_break_op (Peers_check_peer_known (sender)); - GNUNET_CADET_receive_done (Peers_get_recv_channel (sender)); + GNUNET_CADET_receive_done (channel_ctx->channel); } @@ -4105,6 +4245,7 @@ shutdown_task (void *cls) { struct ClientContext *client_ctx; struct ReplyCls *reply_cls; + struct ChannelCtx *channel_ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "RPS is going down\n"); @@ -4128,6 +4269,11 @@ shutdown_task (void *cls) GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx); GNUNET_free (client_ctx); } + /* Clean all leftover channel contexts */ + while (NULL != (channel_ctx = channel_ctx_head)) + { + remove_channel_ctx (channel_ctx); + } GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle); GNUNET_PEERINFO_disconnect (peerinfo_handle); -- cgit v1.2.3 From 3215ab6ef18080f74362be7cee871179166a9f56 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 26 Jul 2018 16:52:36 +0200 Subject: rps service: don't send 'ping' twice --- src/rps/gnunet-service-rps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index fcb68b724..a5fb88157 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -1225,7 +1225,8 @@ Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer) ret = Peers_insert_peer (peer); peer_ctx = get_peer_ctx (peer); - if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE)) + if ( (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE)) && + (NULL == peer_ctx->liveliness_check_pending) ) { check_peer_live (peer_ctx); } -- cgit v1.2.3 From 85c97d3186e61c9e98528100e7db16e89a220cd8 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 26 Jul 2018 16:53:24 +0200 Subject: fix rps service: don't null out context, just channel --- src/rps/gnunet-service-rps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index a5fb88157..d6c6d0ecc 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -1725,7 +1725,7 @@ destroy_channel (void *cls) struct PeerContext *peer_ctx = channel_ctx->peer_ctx; uint32_t *channel_flag; - channel_ctx = NULL; + channel_ctx->destruction_task = NULL; GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); channel_flag = Peers_get_channel_flag (&peer_ctx->peer_id, Peers_CHANNEL_ROLE_SENDING); Peers_set_channel_flag (channel_flag, Peers_CHANNEL_DESTROING); -- cgit v1.2.3 From 75885ed261991edb96d0f585c1ddef0cdaa97395 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 26 Jul 2018 16:53:51 +0200 Subject: rps service: improve logging - log peer id --- src/rps/gnunet-service-rps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index d6c6d0ecc..8ea10e4ca 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -3447,7 +3447,8 @@ check_peer_pull_reply (void *cls, if (GNUNET_YES != Peers_check_peer_flag (sender, Peers_PULL_REPLY_PENDING)) { LOG (GNUNET_ERROR_TYPE_WARNING, - "Received a pull reply from a peer we didn't request one from!\n"); + "Received a pull reply from a peer (%s) we didn't request one from!\n", + GNUNET_i2s (sender)); GNUNET_break_op (0); return GNUNET_SYSERR; } -- cgit v1.2.3 From a53cfea7ff589a4710671da427186648551008d5 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 26 Jul 2018 17:04:44 +0200 Subject: rps profiler: destroy pending req and rep in right place --- src/rps/gnunet-rps-profiler.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c index a06598764..49714872f 100644 --- a/src/rps/gnunet-rps-profiler.c +++ b/src/rps/gnunet-rps-profiler.c @@ -922,13 +922,11 @@ cancel_request (struct PendingReply *pending_rep) void clean_peer (unsigned peer_index) { - struct PendingReply *pending_rep; struct PendingRequest *pending_req; - pending_rep = rps_peers[peer_index].pending_rep_head; - while (NULL != (pending_rep = rps_peers[peer_index].pending_rep_head)) + while (NULL != (pending_req = rps_peers[peer_index].pending_req_head)) { - cancel_request (pending_rep); + cancel_pending_req (pending_req); } pending_req = rps_peers[peer_index].pending_req_head; rps_disconnect_adapter (&rps_peers[peer_index], @@ -1273,7 +1271,7 @@ rps_disconnect_adapter (void *cls, { struct RPSPeer *peer = cls; struct GNUNET_RPS_Handle *h = op_result; - struct PendingRequest *pending_req; + struct PendingReply *pending_rep; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnect_adapter (%u)\n", @@ -1281,9 +1279,9 @@ rps_disconnect_adapter (void *cls, GNUNET_assert (NULL != peer); if (NULL != peer->rps_handle) { - while (NULL != (pending_req = peer->pending_req_head)) + while (NULL != (pending_rep = peer->pending_rep_head)) { - cancel_pending_req (pending_req); + cancel_request (pending_rep); } GNUNET_assert (h == peer->rps_handle); GNUNET_RPS_disconnect (h); -- cgit v1.2.3 From e5bce382b3c4b1534da95032cc7f01e2c58ae387 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Thu, 26 Jul 2018 17:05:55 +0200 Subject: fix rps service: put peer id into structure once --- src/rps/gnunet-service-rps_custommap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps_custommap.c b/src/rps/gnunet-service-rps_custommap.c index 42507655b..9e003eb39 100644 --- a/src/rps/gnunet-service-rps_custommap.c +++ b/src/rps/gnunet-service-rps_custommap.c @@ -213,7 +213,7 @@ CustomPeerMap_remove_peer (const struct CustomPeerMap *c_peer_map, GNUNET_assert (NULL != last_index); GNUNET_assert (CustomPeerMap_size (c_peer_map) == *last_index); GNUNET_CONTAINER_multihashmap32_put (c_peer_map->hash_map, *index, last_p, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); GNUNET_CONTAINER_multihashmap32_remove_all (c_peer_map->hash_map, *last_index); *last_index = *index; } -- cgit v1.2.3 From 7901ef08d68f9db9a56874f19d6d2b83571e40ba Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 27 Jul 2018 19:57:03 +0200 Subject: Fix rps service: restructure channel-related code There is still an error left. Valgrind reports ==2008== Invalid read of size 8 ==2008== at 0x50662A4: GNUNET_CONTAINER_multipeermap_contains (container_multipeermap.c:542) ==2008== by 0x114E8A: Peers_remove_peer (gnunet-service-rps.c:1306) ==2008== by 0x114E65: destroy_peer (gnunet-service-rps.c:1283) ==2008== by 0x50A29B2: GNUNET_SCHEDULER_do_work (scheduler.c:2104) ==2008== by 0x50A382D: select_loop (scheduler.c:2400) ==2008== by 0x509DE48: GNUNET_SCHEDULER_run (scheduler.c:725) ==2008== by 0x50A989E: GNUNET_SERVICE_run_ (service.c:1875) ==2008== by 0x11EE83: main (gnunet-service-rps.c:4584) ==2008== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==2008== ==2008== ==2008== Process terminating with default action of signal 11 (SIGSEGV) ==2008== Access not within mapped region at address 0x0 ==2008== at 0x50662A4: GNUNET_CONTAINER_multipeermap_contains (container_multipeermap.c:542) ==2008== by 0x114E8A: Peers_remove_peer (gnunet-service-rps.c:1306) ==2008== by 0x114E65: destroy_peer (gnunet-service-rps.c:1283) ==2008== by 0x50A29B2: GNUNET_SCHEDULER_do_work (scheduler.c:2104) ==2008== by 0x50A382D: select_loop (scheduler.c:2400) ==2008== by 0x509DE48: GNUNET_SCHEDULER_run (scheduler.c:725) ==2008== by 0x50A989E: GNUNET_SERVICE_run_ (service.c:1875) ==2008== by 0x11EE83: main (gnunet-service-rps.c:4584) This seems to only appear at shutdown so it is not dramatic. --- src/rps/gnunet-service-rps.c | 324 +++++++++++++++++-------------------------- 1 file changed, 129 insertions(+), 195 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 8ea10e4ca..555660c04 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -246,6 +246,11 @@ struct PeerContext struct PendingMessage *pending_messages_head; struct PendingMessage *pending_messages_tail; + /** + * @brief Task to destroy this context. + */ + struct GNUNET_SCHEDULER_Task *destruction_task; + /** * This is pobably followed by 'statistical' data (when we first saw * it, how did we get its ID, how many pushes (in a timeinterval), @@ -1274,6 +1279,23 @@ Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer, int Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags); +static void +destroy_peer (void *cls) +{ + struct PeerContext *peer_ctx = cls; + + GNUNET_assert (NULL != peer_ctx); + peer_ctx->destruction_task = NULL; + Peers_remove_peer (&peer_ctx->peer_id); +} + +static void +destroy_channel (void *cls); + + +static void +schedule_channel_destruction (struct ChannelCtx *channel_ctx); + /** * @brief Remove peer * @@ -1298,7 +1320,34 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) "Going to remove peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); Peers_unset_peer_flag (peer, Peers_ONLINE); + /* Do we still have to wait for destruction of channels + * or issue the destruction? */ + if (NULL != peer_ctx->send_channel_ctx && + NULL != peer_ctx->send_channel_ctx->destruction_task) + { + GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->recv_channel_ctx && + NULL != peer_ctx->recv_channel_ctx->destruction_task) + { + GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->recv_channel_ctx) + { + schedule_channel_destruction (peer_ctx->recv_channel_ctx); + GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->send_channel_ctx) + { + schedule_channel_destruction (peer_ctx->send_channel_ctx); + GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); + return GNUNET_NO; + } + // TODO this probably leaks memory GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0); while (NULL != peer_ctx->pending_messages_head) { @@ -1311,6 +1360,7 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) peer_ctx->liveliness_check_pending, sizeof (struct PendingMessage))) ) { + // TODO this may leak memory peer_ctx->liveliness_check_pending = NULL; } remove_pending_message (peer_ctx->pending_messages_head, GNUNET_YES); @@ -1327,29 +1377,10 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) remove_pending_message (peer_ctx->liveliness_check_pending, GNUNET_YES); peer_ctx->liveliness_check_pending = NULL; } - channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING); - if (NULL != peer_ctx->send_channel_ctx && - GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Destroying send channel\n"); - GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); - remove_channel_ctx (peer_ctx->send_channel_ctx); - peer_ctx->send_channel_ctx = NULL; - peer_ctx->mq = NULL; - } - channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING); - if (NULL != peer_ctx->recv_channel_ctx && - GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING)) + + if (NULL != peer_ctx->destruction_task) { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Destroying recv channel\n"); - GNUNET_CADET_channel_destroy (peer_ctx->recv_channel_ctx->channel); - if (NULL != peer_ctx->recv_channel_ctx) - { - remove_channel_ctx (peer_ctx->recv_channel_ctx); - } - peer_ctx->recv_channel_ctx = NULL; + GNUNET_SCHEDULER_cancel (peer_ctx->destruction_task); } GNUNET_free (peer_ctx->send_channel_flags); @@ -1363,6 +1394,15 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) return GNUNET_YES; } +static void +schedule_peer_ctx_destruction (struct PeerContext *peer_ctx) +{ + GNUNET_assert (NULL != peer_ctx); + if (NULL == peer_ctx->destruction_task) + { + GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); + } +} /** * @brief set flags on a given peer. @@ -1708,10 +1748,7 @@ Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer) peer_ctx = get_peer_ctx (peer); if (NULL != peer_ctx->send_channel_ctx) { - set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN); - GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); - peer_ctx->send_channel_ctx = NULL; - peer_ctx->mq = NULL; + schedule_channel_destruction (peer_ctx->send_channel_ctx); (void) Peers_check_connected (peer); return GNUNET_YES; } @@ -1723,23 +1760,19 @@ destroy_channel (void *cls) { struct ChannelCtx *channel_ctx = cls; struct PeerContext *peer_ctx = channel_ctx->peer_ctx; - uint32_t *channel_flag; + + GNUNET_assert (channel_ctx == peer_ctx->send_channel_ctx || + channel_ctx == peer_ctx->recv_channel_ctx); channel_ctx->destruction_task = NULL; - GNUNET_CADET_channel_destroy (peer_ctx->send_channel_ctx->channel); - channel_flag = Peers_get_channel_flag (&peer_ctx->peer_id, Peers_CHANNEL_ROLE_SENDING); - Peers_set_channel_flag (channel_flag, Peers_CHANNEL_DESTROING); + GNUNET_CADET_channel_destroy (channel_ctx->channel); remove_channel_ctx (peer_ctx->send_channel_ctx); - peer_ctx->send_channel_ctx = NULL; - if (channel_ctx == peer_ctx->send_channel_ctx) - { - peer_ctx->mq = NULL; - } } static void schedule_channel_destruction (struct ChannelCtx *channel_ctx) { + GNUNET_assert (NULL != channel_ctx); if (NULL != channel_ctx->destruction_task) { channel_ctx->destruction_task = @@ -1747,6 +1780,7 @@ schedule_channel_destruction (struct ChannelCtx *channel_ctx) } } + /** * This is called when a channel is destroyed. * @@ -1772,61 +1806,30 @@ Peers_cleanup_destroyed_channel (void *cls, /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY * flag will be set. In this case simply make sure that the channels are * cleaned. */ - /* FIXME This distinction seems to be redundant */ - if (Peers_check_peer_flag (peer, Peers_TO_DESTROY)) - {/* We initiatad the destruction of this particular peer */ + /* The distinction seems to be redundant */ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Peer is NOT in the process of being destroyed\n"); + if ( (NULL != peer_ctx->send_channel_ctx) && + (channel == peer_ctx->send_channel_ctx->channel) ) + { /* Something (but us) killd the channel - clean up peer */ LOG (GNUNET_ERROR_TYPE_DEBUG, - "Peer is in the process of being destroyed\n"); - if (channel == channel_ctx->channel) - { - peer_ctx->send_channel_ctx = NULL; - peer_ctx->mq = NULL; - } - else if (channel == peer_ctx->recv_channel_ctx->channel) - { - peer_ctx->recv_channel_ctx = NULL; - } - - if (NULL != peer_ctx->send_channel_ctx) - { - schedule_channel_destruction (peer_ctx->send_channel_ctx); - } - if (NULL != peer_ctx->recv_channel_ctx) - { - schedule_channel_destruction (peer_ctx->recv_channel_ctx); - } - /* Set the #Peers_ONLINE flag accordingly */ - (void) Peers_check_connected (peer); - return; + "send channel (%s) was destroyed - cleaning up\n", + GNUNET_i2s (peer)); + remove_channel_ctx (peer_ctx->send_channel_ctx); } - - else - { /* We did not initiate the destruction of this peer */ + else if ( (NULL != peer_ctx->recv_channel_ctx) && + (channel == peer_ctx->recv_channel_ctx->channel) ) + { /* Other peer doesn't want to send us messages anymore */ LOG (GNUNET_ERROR_TYPE_DEBUG, - "Peer is NOT in the process of being destroyed\n"); - if ( (NULL != peer_ctx->send_channel_ctx) && - (channel == peer_ctx->send_channel_ctx->channel) ) - { /* Something (but us) killd the channel - clean up peer */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "send channel (%s) was destroyed - cleaning up\n", - GNUNET_i2s (peer)); - peer_ctx->send_channel_ctx = NULL; - peer_ctx->mq = NULL; - } - else if ( (NULL != peer_ctx->recv_channel_ctx) && - (channel == peer_ctx->recv_channel_ctx->channel) ) - { /* Other peer doesn't want to send us messages anymore */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Peer %s destroyed recv channel - cleaning up channel\n", - GNUNET_i2s (peer)); - peer_ctx->recv_channel_ctx = NULL; - } - else - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "unknown channel (%s) was destroyed\n", - GNUNET_i2s (peer)); - } + "Peer %s destroyed recv channel - cleaning up channel\n", + GNUNET_i2s (peer)); + remove_channel_ctx (peer_ctx->send_channel_ctx); + } + else + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "unknown channel (%s) was destroyed\n", + GNUNET_i2s (peer)); } (void) Peers_check_connected (peer); } @@ -2572,6 +2575,9 @@ send_pull_reply (const struct GNUNET_PeerIdentity *peer_id, Peers_send_message (peer_id, ev, "PULL REPLY"); GNUNET_STATISTICS_update(stats, "# pull reply send issued", 1, GNUNET_NO); + // TODO check with send intention: as send_channel is used/opened we indicate + // a sending intention without intending it. + // -> clean peer afterwards? } @@ -2704,7 +2710,7 @@ remove_peer (const struct GNUNET_PeerIdentity *peer) CustomPeerMap_remove_peer (push_map, peer); RPS_sampler_reinitialise_by_value (prot_sampler, peer); RPS_sampler_reinitialise_by_value (client_sampler, peer); - Peers_remove_peer (peer); + schedule_peer_ctx_destruction (get_peer_ctx (peer)); } @@ -2772,8 +2778,32 @@ add_channel_ctx (struct PeerContext *peer_ctx) static void remove_channel_ctx (struct ChannelCtx *channel_ctx) { - GNUNET_CONTAINER_DLL_remove (channel_ctx_head, channel_ctx_tail, channel_ctx); + struct PeerContext *peer_ctx = channel_ctx->peer_ctx; + if (NULL != channel_ctx->destruction_task) + { + GNUNET_SCHEDULER_cancel (channel_ctx->destruction_task); + } GNUNET_free (channel_ctx); + + if (channel_ctx == peer_ctx->send_channel_ctx) + { + peer_ctx->send_channel_ctx = NULL; + peer_ctx->mq = NULL; + } + else if (channel_ctx == peer_ctx->recv_channel_ctx) + { + peer_ctx->recv_channel_ctx = NULL; + } + else + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Trying to remove channel_ctx that is not associated with a peer\n"); + LOG (GNUNET_ERROR_TYPE_ERROR, + "\trecv: %p\n", peer_ctx->recv_channel_ctx); + LOG (GNUNET_ERROR_TYPE_ERROR, + "\tsend: %p\n", peer_ctx->send_channel_ctx); + GNUNET_assert (0); + } } /** @@ -2809,103 +2839,21 @@ cleanup_destroyed_channel (void *cls, } peer_ctx = get_peer_ctx (peer); - if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Callback on destruction of recv-channel was called (%s)\n", - GNUNET_i2s (peer)); - set_channel_flag (peer_ctx->recv_channel_flags, Peers_CHANNEL_DESTROING); - } else if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Callback on destruction of send-channel was called (%s)\n", - GNUNET_i2s (peer)); - set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_DESTROING); - } else { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Channel to be destroyed has is neither sending nor receiving role\n"); - } - if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY)) - { /* We are in the middle of removing that peer from our knowledge. In this - case simply make sure that the channels are cleaned. */ - Peers_cleanup_destroyed_channel (cls, channel); - to_file (file_name_view_log, - "-%s\t(cleanup channel, ourself)", - GNUNET_i2s_full (peer)); - remove_channel_ctx (channel_ctx); - if (peer_ctx->send_channel_ctx == channel_ctx) - { - peer_ctx->send_channel_ctx = NULL; - } - else if (peer_ctx->recv_channel_ctx == channel_ctx) - { - peer_ctx->recv_channel_ctx = NULL; - } - else - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Trying to remove channel_ctx that is not associated with a peer\n"); - GNUNET_assert (0); - } - return; - } + // What should be done here: + // * cleanup everything related to the channel + // * memory + // * remove peer if necessary - if (GNUNET_YES == - Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING)) - { /* Channel used for sending was destroyed */ - /* Possible causes of channel destruction: - * - ourselves -> cleaning send channel -> clean context - * - other peer -> peer probably went down -> remove - */ - channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING); - if (GNUNET_YES == Peers_check_channel_flag (channel_flag, Peers_CHANNEL_CLEAN)) - { /* We are about to clean the sending channel. Clean the respective - * context */ - Peers_cleanup_destroyed_channel (cls, channel); - remove_channel_ctx (channel_ctx); - return; - } - else - { /* Other peer destroyed our sending channel that it is supposed to keep - * open. It probably went down. Remove it from our knowledge. */ - Peers_cleanup_destroyed_channel (cls, channel); - remove_peer (peer); - remove_channel_ctx (channel_ctx); - return; - } - } - else if (GNUNET_YES == - Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING)) - { /* Channel used for receiving was destroyed */ - /* Possible causes of channel destruction: - * - ourselves -> peer tried to establish channel twice -> clean context - * - other peer -> peer doesn't want to send us data -> clean - */ - channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING); - if (GNUNET_YES == - Peers_check_channel_flag (channel_flag, Peers_CHANNEL_ESTABLISHED_TWICE)) - { /* Other peer tried to establish a channel to us twice. We do not accept - * that. Clean the context. */ - Peers_cleanup_destroyed_channel (cls, channel); - remove_channel_ctx (channel_ctx); - return; - } - else - { /* Other peer doesn't want to send us data anymore. We are free to clean - * it. */ - Peers_cleanup_destroyed_channel (cls, channel); - clean_peer (peer); - remove_channel_ctx (channel_ctx); - return; - } + if (peer_ctx->recv_channel_ctx == channel_ctx) + { + remove_channel_ctx (channel_ctx); } - else + else if (peer_ctx->send_channel_ctx == channel_ctx) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Destroyed channel is neither sending nor receiving channel\n"); + remove_channel_ctx (channel_ctx); + remove_peer (&peer_ctx->peer_id); } - remove_channel_ctx (channel_ctx); } /*********************************************************************** @@ -3164,8 +3112,6 @@ handle_client_seed (void *cls, num_peers = ntohl (msg->num_peers); peers = (struct GNUNET_PeerIdentity *) &msg[1]; - //peers = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity); - //GNUNET_memcpy (peers, &msg[1], num_peers * sizeof (struct GNUNET_PeerIdentity)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Client seeded peers:\n"); @@ -3180,9 +3126,6 @@ handle_client_seed (void *cls, got_peer (&peers[i]); } - - ////GNUNET_free (peers); - GNUNET_SERVICE_client_continue (cli_ctx->client); } @@ -4078,7 +4021,6 @@ do_round (void *cls) "-%s", GNUNET_i2s_full (&peers_to_clean[i])); clean_peer (&peers_to_clean[i]); - //peer_destroy_channel_send (sender); } GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0); @@ -4134,7 +4076,6 @@ do_round (void *cls) GNUNET_i2s (update_peer)); insert_in_sampler (NULL, update_peer); clean_peer (update_peer); /* This cleans only if it is not in the view */ - //peer_destroy_channel_send (sender); } for (i = 0; i < CustomPeerMap_size (pull_map); i++) @@ -4145,7 +4086,6 @@ do_round (void *cls) insert_in_sampler (NULL, CustomPeerMap_get_peer_by_index (pull_map, i)); /* This cleans only if it is not in the view */ clean_peer (CustomPeerMap_get_peer_by_index (pull_map, i)); - //peer_destroy_channel_send (sender); } @@ -4247,7 +4187,6 @@ shutdown_task (void *cls) { struct ClientContext *client_ctx; struct ReplyCls *reply_cls; - struct ChannelCtx *channel_ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "RPS is going down\n"); @@ -4271,11 +4210,6 @@ shutdown_task (void *cls) GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx); GNUNET_free (client_ctx); } - /* Clean all leftover channel contexts */ - while (NULL != (channel_ctx = channel_ctx_head)) - { - remove_channel_ctx (channel_ctx); - } GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle); GNUNET_PEERINFO_disconnect (peerinfo_handle); -- cgit v1.2.3 From 8c418c66fcdba8854c8a4c49696436c75dec856d Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 27 Jul 2018 20:00:45 +0200 Subject: remove now obsolete usage of channel-related flags --- src/rps/gnunet-service-rps.c | 98 +------------------------------------------- 1 file changed, 1 insertion(+), 97 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 555660c04..4d502713f 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -96,11 +96,6 @@ static struct GNUNET_HashCode port; */ #define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask)) -/** - * Set a channel flag of given channel context. - */ -#define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask)) - /** * Get channel flag of given channel context. */ @@ -188,20 +183,10 @@ struct PeerContext */ struct ChannelCtx *send_channel_ctx; - /** - * Flags to the sending channel - */ - uint32_t *send_channel_flags; - /** * Channel open from client. */ - struct ChannelCtx *recv_channel_ctx; // unneeded? - - /** - * Flags to the receiving channel - */ - uint32_t *recv_channel_flags; + struct ChannelCtx *recv_channel_ctx; /** * Array of pending operations on this peer. @@ -375,8 +360,6 @@ create_peer_ctx (const struct GNUNET_PeerIdentity *peer) ctx = GNUNET_new (struct PeerContext); ctx->peer_id = *peer; - ctx->send_channel_flags = GNUNET_new (uint32_t); - ctx->recv_channel_flags = GNUNET_new (uint32_t); ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); GNUNET_assert (GNUNET_OK == ret); @@ -1307,7 +1290,6 @@ int Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *peer_ctx; - uint32_t *channel_flag; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) { @@ -1383,9 +1365,6 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) GNUNET_SCHEDULER_cancel (peer_ctx->destruction_task); } - GNUNET_free (peer_ctx->send_channel_flags); - GNUNET_free (peer_ctx->recv_channel_flags); - if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id)) { LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n"); @@ -1459,77 +1438,6 @@ Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFl return check_peer_flag_set (peer_ctx, flags); } - -/** - * @brief set flags on a given channel. - * - * @param channel the channel to set flags on - * @param flags the flags - */ -void -Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags) -{ - set_channel_flag (channel_flags, flags); -} - - -/** - * @brief unset flags on a given channel. - * - * @param channel the channel to unset flags on - * @param flags the flags - */ -void -Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags) -{ - unset_channel_flag (channel_flags, flags); -} - - -/** - * @brief Check whether flags on a channel are set. - * - * @param channel the channel to check the flag of - * @param flags the flags to check - * - * @return #GNUNET_YES if all given flags are set - * #GNUNET_NO otherwise - */ -int -Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags) -{ - return check_channel_flag_set (channel_flags, flags); -} - -/** - * @brief Get the flags for the channel in @a role for @a peer. - * - * @param peer Peer to get the channel flags for. - * @param role Role of channel to get flags for - * - * @return The flags. - */ -uint32_t * -Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer, - enum Peers_ChannelRole role) -{ - const struct PeerContext *peer_ctx; - - peer_ctx = get_peer_ctx (peer); - if (Peers_CHANNEL_ROLE_SENDING == role) - { - return peer_ctx->send_channel_flags; - } - else if (Peers_CHANNEL_ROLE_RECEIVING == role) - { - return peer_ctx->recv_channel_flags; - } - else - { - GNUNET_assert (0); - } -} - /** * @brief Check whether we have information about the given peer. * @@ -1644,9 +1552,6 @@ Peers_handle_inbound_channel (void *cls, LOG (GNUNET_ERROR_TYPE_WARNING, "Already got one receive channel. Destroying old one.\n"); GNUNET_break_op (0); - set_channel_flag (peer_ctx->recv_channel_flags, - Peers_CHANNEL_ESTABLISHED_TWICE); - //GNUNET_CADET_channel_destroy (channel); GNUNET_CADET_channel_destroy (peer_ctx->recv_channel_ctx->channel); remove_channel_ctx (peer_ctx->recv_channel_ctx); peer_ctx->recv_channel_ctx = channel_ctx; @@ -2824,7 +2729,6 @@ cleanup_destroyed_channel (void *cls, { struct ChannelCtx *channel_ctx = cls; struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id; - uint32_t *channel_flag; struct PeerContext *peer_ctx; GNUNET_assert (NULL != peer); -- cgit v1.2.3 From 07a57f226261b7a78a57cc6de7e9f03738994b29 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Fri, 27 Jul 2018 20:01:28 +0200 Subject: Remove obsolete DLL for cancellations of tasks --- src/rps/gnunet-service-rps.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 4d502713f..f48b3d85d 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -286,12 +286,6 @@ struct ChannelCtx struct GNUNET_SCHEDULER_Task *destruction_task; }; -/** - * @brief The DLL of channel contexts - */ -static struct ChannelCtx *channel_ctx_head; -static struct ChannelCtx *channel_ctx_tail; - /** * @brief Hashmap of valid peers. */ @@ -2671,7 +2665,6 @@ add_channel_ctx (struct PeerContext *peer_ctx) struct ChannelCtx *channel_ctx; channel_ctx = GNUNET_new (struct ChannelCtx); channel_ctx->peer_ctx = peer_ctx; - GNUNET_CONTAINER_DLL_insert (channel_ctx_head, channel_ctx_tail, channel_ctx); return channel_ctx; } -- cgit v1.2.3 From 5bd70d462b4b50afd729eb234e0c2b6a02388bea Mon Sep 17 00:00:00 2001 From: lurchi Date: Sun, 29 Jul 2018 18:18:34 +0200 Subject: GNUNET_SCHEDULER_do_work: always check if shutdown is necessary and update wakeup time --- src/util/scheduler.c | 162 +++++++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 014288944..5d3836639 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -2022,99 +2022,109 @@ GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh) if (timeout.abs_value_us > now.abs_value_us) { /** - * The driver called this function before the current timeout was - * reached (and no FD tasks are ready). This can happen in the - * rare case when the system time is changed while the driver is - * waiting for the timeout, so we handle this gracefully. It might - * also be a programming error in the driver though. + * The event loop called this function before the current timeout was + * reached (and no FD tasks are ready). This is acceptable if + * + * - the system time was changed while the driver was waiting for + * the timeout + * - an external event loop called GNUnet API functions outside of + * the callbacks called in GNUNET_SCHEDULER_do_work and thus + * wasn't notified about the new timeout + * + * It might also mean we are busy-waiting because of a programming + * error in the external event loop. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_SCHEDULER_do_work did not find any ready " "tasks and timeout has not been reached yet.\n"); - return GNUNET_NO; } - /** - * the current timeout was reached but no ready tasks were found, - * internal scheduler error! - */ - GNUNET_assert (0); - } - - /* find out which task priority level we are going to - process this time */ - max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; - GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); - /* yes, p>0 is correct, 0 is "KEEP" which should - * always be an empty queue (see assertion)! */ - for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) - { - pos = ready_head[p]; - if (NULL != pos) - break; + else + { + /** + * the current timeout was reached but no ready tasks were found, + * internal scheduler error! + */ + GNUNET_assert (0); + } } - GNUNET_assert (NULL != pos); /* ready_count wrong? */ - - /* process all tasks at this priority level, then yield */ - while (NULL != (pos = ready_head[p])) + else { - GNUNET_CONTAINER_DLL_remove (ready_head[p], - ready_tail[p], - pos); - ready_count--; - current_priority = pos->priority; - current_lifeness = pos->lifeness; - active_task = pos; -#if PROFILE_DELAYS - if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > - DELAY_THRESHOLD.rel_value_us) + /* find out which task priority level we are going to + process this time */ + max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; + GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); + /* yes, p>0 is correct, 0 is "KEEP" which should + * always be an empty queue (see assertion)! */ + for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Task %p took %s to be scheduled\n", - pos, - GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), - GNUNET_YES)); + pos = ready_head[p]; + if (NULL != pos) + break; } -#endif - tc.reason = pos->reason; - GNUNET_NETWORK_fdset_zero (sh->rs); - GNUNET_NETWORK_fdset_zero (sh->ws); - // FIXME: do we have to remove FdInfos from fds if they are not ready? - tc.fds_len = pos->fds_len; - tc.fds = pos->fds; - for (unsigned int i = 0; i != pos->fds_len; ++i) + GNUNET_assert (NULL != pos); /* ready_count wrong? */ + + /* process all tasks at this priority level, then yield */ + while (NULL != (pos = ready_head[p])) { - struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i]; - if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) + GNUNET_CONTAINER_DLL_remove (ready_head[p], + ready_tail[p], + pos); + ready_count--; + current_priority = pos->priority; + current_lifeness = pos->lifeness; + active_task = pos; +#if PROFILE_DELAYS + if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > + DELAY_THRESHOLD.rel_value_us) { - GNUNET_NETWORK_fdset_set_native (sh->rs, - fdi->sock); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Task %p took %s to be scheduled\n", + pos, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), + GNUNET_YES)); } - if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) +#endif + tc.reason = pos->reason; + GNUNET_NETWORK_fdset_zero (sh->rs); + GNUNET_NETWORK_fdset_zero (sh->ws); + // FIXME: do we have to remove FdInfos from fds if they are not ready? + tc.fds_len = pos->fds_len; + tc.fds = pos->fds; + for (unsigned int i = 0; i != pos->fds_len; ++i) { - GNUNET_NETWORK_fdset_set_native (sh->ws, - fdi->sock); + struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i]; + if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) + { + GNUNET_NETWORK_fdset_set_native (sh->rs, + fdi->sock); + } + if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) + { + GNUNET_NETWORK_fdset_set_native (sh->ws, + fdi->sock); + } } - } - tc.read_ready = sh->rs; - tc.write_ready = sh->ws; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running task %p\n", - pos); - GNUNET_assert (NULL != pos->callback); - pos->callback (pos->callback_cls); - if (NULL != pos->fds) - { - int del_result = scheduler_driver->del (scheduler_driver->cls, pos); - if (GNUNET_OK != del_result) + tc.read_ready = sh->rs; + tc.write_ready = sh->ws; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Running task %p\n", + pos); + GNUNET_assert (NULL != pos->callback); + pos->callback (pos->callback_cls); + if (NULL != pos->fds) { - LOG (GNUNET_ERROR_TYPE_ERROR, - "driver could not delete task %p\n", pos); - GNUNET_assert (0); + int del_result = scheduler_driver->del (scheduler_driver->cls, pos); + if (GNUNET_OK != del_result) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "driver could not delete task %p\n", pos); + GNUNET_assert (0); + } } + active_task = NULL; + dump_backtrace (pos); + destroy_task (pos); } - active_task = NULL; - dump_backtrace (pos); - destroy_task (pos); } shutdown_if_no_lifeness (); if (0 == ready_count) -- cgit v1.2.3 From 7bd650c1a944be9e772a907cb269ac0b50f98de2 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 6 Aug 2018 14:34:56 +0200 Subject: add copying rest plugin --- src/rest/Makefile.am | 14 +++ src/rest/plugin_rest_copying.c | 233 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 src/rest/plugin_rest_copying.c (limited to 'src') diff --git a/src/rest/Makefile.am b/src/rest/Makefile.am index ebfb98024..848b7101c 100644 --- a/src/rest/Makefile.am +++ b/src/rest/Makefile.am @@ -29,6 +29,20 @@ libexec_PROGRAMS = \ EXTRA_DIST = \ rest.conf +plugin_LTLIBRARIES = libgnunet_plugin_rest_copying.la + +libgnunet_plugin_rest_copying_la_SOURCES = \ + plugin_rest_copying.c +libgnunet_plugin_rest_copying_la_LIBADD = \ + $(top_builddir)/src/rest/libgnunetrest.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_copying_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + + gnunet_rest_server_SOURCES = \ gnunet-rest-server.c diff --git a/src/rest/plugin_rest_copying.c b/src/rest/plugin_rest_copying.c new file mode 100644 index 000000000..f6a085c03 --- /dev/null +++ b/src/rest/plugin_rest_copying.c @@ -0,0 +1,233 @@ +/* + This file is part of GNUnet. + Copyright (C) 2012-2018 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @file gns/plugin_rest_copying.c + * @brief REST plugin that serves licensing information. + * + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include +#include +#include + +#define GNUNET_REST_API_NS_COPYING "/copying" + +#define GNUNET_REST_COPYING_TEXT "GNU Affero General Public License version 3 or later. See also: " + +/** + * @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 rest request + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * HTTP response code + */ + int response_code; + +}; + + +/** + * Cleanup request handle. + * + * @param handle Handle to clean up + */ +static void +cleanup_handle (struct RequestHandle *handle) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + GNUNET_free (handle); +} + + +/** + * Task run on shutdown. Cleans up everything. + * + * @param cls unused + * @param tc scheduler context + */ +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); +} + + +/** + * Handle rest request + * + * @param handle the lookup handle + */ +static void +get_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + resp = GNUNET_REST_create_response (GNUNET_REST_COPYING_TEXT); + handle->proc (handle->proc_cls, + resp, + MHD_HTTP_OK); + cleanup_handle (handle); +} + + + +/** + * Handle rest request + * + * @param handle the lookup handle + */ +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + 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); +} + + +/** + * 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 @a proc + * @return #GNUNET_OK if request accepted + */ +static void +rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + static const struct GNUNET_REST_RequestHandler handlers[] = { + {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_COPYING, &get_cont}, + {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_COPYING, &options_cont}, + GNUNET_REST_HANDLER_END + }; + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + struct GNUNET_REST_RequestHandlerError err; + + handle->proc_cls = proc_cls; + handle->proc = proc; + handle->rest_handle = conndata_handle; + + 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_copying_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_COPYING; + api->process_request = &rest_copying_process_request; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("COPYING 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_copying_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, + "COPYING REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_copying.c */ -- cgit v1.2.3 From 070a1c2e37fe8930bad59cbd06d6a0f55a8364f0 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 6 Aug 2018 16:05:57 +0200 Subject: ensure ego identifiers are lowercase --- src/identity/gnunet-service-identity.c | 49 +++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/identity/gnunet-service-identity.c b/src/identity/gnunet-service-identity.c index 6b8e21806..266f5ccc3 100644 --- a/src/identity/gnunet-service-identity.c +++ b/src/identity/gnunet-service-identity.c @@ -371,11 +371,12 @@ handle_get_default_message (void *cls, struct GNUNET_MQ_Envelope *env; struct GNUNET_SERVICE_Client *client = cls; struct Ego *ego; - const char *name; + char *name; char *identifier; - name = (const char *) &gdm[1]; + name = GNUNET_strdup ((const char *) &gdm[1]); + GNUNET_STRINGS_utf8_tolower ((const char *) &gdm[1], name); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received GET_DEFAULT for service `%s' from client\n", name); @@ -387,6 +388,7 @@ handle_get_default_message (void *cls, { send_result_code (client, 1, gettext_noop ("no default known")); GNUNET_SERVICE_client_continue (client); + GNUNET_free (name); return; } for (ego = ego_head; NULL != ego; ego = ego->next) @@ -399,6 +401,7 @@ handle_get_default_message (void *cls, GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env); GNUNET_SERVICE_client_continue (client); GNUNET_free (identifier); + GNUNET_free (name); return; } } @@ -406,6 +409,7 @@ handle_get_default_message (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to find ego `%s'\n", name); + GNUNET_free (name); send_result_code (client, 1, gettext_noop ("default configured, but ego unknown (internal error)")); GNUNET_SERVICE_client_continue (client); @@ -477,9 +481,11 @@ handle_set_default_message (void *cls, { struct Ego *ego; struct GNUNET_SERVICE_Client *client = cls; - const char *str; + char *str; + + str = GNUNET_strdup ((const char *) &sdm[1]); + GNUNET_STRINGS_utf8_tolower ((const char *) &sdm[1], str); - str = (const char *) &sdm[1]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received SET_DEFAULT for service `%s' from client\n", str); @@ -500,10 +506,12 @@ handle_set_default_message (void *cls, subsystem_cfg_file); send_result_code (client, 0, NULL); GNUNET_SERVICE_client_continue (client); + GNUNET_free (str); return; } } send_result_code (client, 1, _("Unknown ego specified for service (internal error)")); + GNUNET_free (str); GNUNET_SERVICE_client_continue (client); } @@ -585,12 +593,13 @@ handle_create_message (void *cls, { struct GNUNET_SERVICE_Client *client = cls; struct Ego *ego; - const char *str; + char *str; char *fn; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREATE message from client\n"); - str = (const char *) &crm[1]; + str = GNUNET_strdup ((const char *) &crm[1]); + GNUNET_STRINGS_utf8_tolower ((const char *) &crm[1], str); for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, @@ -598,6 +607,7 @@ handle_create_message (void *cls, { send_result_code (client, 1, gettext_noop ("identifier already in use for another ego")); GNUNET_SERVICE_client_continue (client); + GNUNET_free (str); return; } } @@ -620,6 +630,7 @@ handle_create_message (void *cls, GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn); GNUNET_free (fn); + GNUNET_free (str); notify_listeners (ego); GNUNET_SERVICE_client_continue (client); } @@ -726,18 +737,22 @@ handle_rename_message (void *cls, { uint16_t old_name_len; struct Ego *ego; - const char *old_name; - const char *new_name; + char *old_name; + char *new_name; struct RenameContext rename_ctx; struct GNUNET_SERVICE_Client *client = cls; char *fn_old; char *fn_new; + const char *old_name_tmp; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received RENAME message from client\n"); old_name_len = ntohs (rm->old_name_len); - old_name = (const char *) &rm[1]; - new_name = &old_name[old_name_len]; + old_name_tmp = (const char *) &rm[1]; + old_name = GNUNET_strdup (old_name_tmp); + GNUNET_STRINGS_utf8_tolower (old_name_tmp, old_name); + new_name = GNUNET_strdup (&old_name_tmp[old_name_len]); + GNUNET_STRINGS_utf8_tolower (&old_name_tmp[old_name_len], old_name); /* check if new name is already in use */ for (ego = ego_head; NULL != ego; ego = ego->next) @@ -747,6 +762,8 @@ handle_rename_message (void *cls, { send_result_code (client, 1, gettext_noop ("target name already exists")); GNUNET_SERVICE_client_continue (client); + GNUNET_free (old_name); + GNUNET_free (new_name); return; } } @@ -776,6 +793,8 @@ handle_rename_message (void *cls, GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rename", fn_old); GNUNET_free (fn_old); GNUNET_free (fn_new); + GNUNET_free (old_name); + GNUNET_free (new_name); notify_listeners (ego); send_result_code (client, 0, NULL); GNUNET_SERVICE_client_continue (client); @@ -785,6 +804,8 @@ handle_rename_message (void *cls, /* failed to locate old name */ send_result_code (client, 1, gettext_noop ("no matching ego found")); + GNUNET_free (old_name); + GNUNET_free (new_name); GNUNET_SERVICE_client_continue (client); } @@ -868,13 +889,15 @@ handle_delete_message (void *cls, const struct DeleteMessage *dm) { struct Ego *ego; - const char *name; + char *name; char *fn; struct GNUNET_SERVICE_Client *client = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DELETE message from client\n"); - name = (const char *) &dm[1]; + name = GNUNET_strdup ((const char *) &dm[1]); + GNUNET_STRINGS_utf8_tolower ((const char *) &dm[1], name); + for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, @@ -901,6 +924,7 @@ handle_delete_message (void *cls, notify_listeners (ego); GNUNET_free (ego->pk); GNUNET_free (ego); + GNUNET_free (name); send_result_code (client, 0, NULL); GNUNET_SERVICE_client_continue (client); return; @@ -908,6 +932,7 @@ handle_delete_message (void *cls, } send_result_code (client, 1, gettext_noop ("no matching ego found")); + GNUNET_free (name); GNUNET_SERVICE_client_continue (client); } -- cgit v1.2.3 From fcaa5854af792cad00c36ed1fd1c4e7fc2602f65 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 6 Aug 2018 16:36:58 +0200 Subject: remove jsonapi dep from copying --- src/rest/Makefile.am | 4 +--- src/rest/plugin_rest_copying.c | 10 ++++------ 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/rest/Makefile.am b/src/rest/Makefile.am index 848b7101c..ce0454d53 100644 --- a/src/rest/Makefile.am +++ b/src/rest/Makefile.am @@ -35,10 +35,8 @@ libgnunet_plugin_rest_copying_la_SOURCES = \ plugin_rest_copying.c libgnunet_plugin_rest_copying_la_LIBADD = \ $(top_builddir)/src/rest/libgnunetrest.la \ - $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ - $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ - $(LTLIBINTL) -ljansson -lmicrohttpd + $(LTLIBINTL) -lmicrohttpd libgnunet_plugin_rest_copying_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) diff --git a/src/rest/plugin_rest_copying.c b/src/rest/plugin_rest_copying.c index f6a085c03..668dc5d38 100644 --- a/src/rest/plugin_rest_copying.c +++ b/src/rest/plugin_rest_copying.c @@ -24,9 +24,7 @@ #include "platform.h" #include "gnunet_rest_plugin.h" -#include #include -#include #define GNUNET_REST_API_NS_COPYING "/copying" @@ -173,10 +171,10 @@ rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, handle->proc = proc; handle->rest_handle = conndata_handle; - if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle, - handlers, - &err, - handle)) + if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle, + handlers, + &err, + handle)) { handle->response_code = err.error_code; GNUNET_SCHEDULER_add_now (&do_error, handle); -- cgit v1.2.3 From b3932f39b028d5db0d2e641e8593679c657b6bd1 Mon Sep 17 00:00:00 2001 From: Julius Bünger Date: Tue, 7 Aug 2018 16:02:36 +0200 Subject: Restructure removal of peers during shutdown (rps service) --- src/rps/gnunet-service-rps.c | 114 ++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index f48b3d85d..21963ee42 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c @@ -68,6 +68,7 @@ static struct GNUNET_STATISTICS_Handle *stats; */ static struct GNUNET_PeerIdentity own_identity; +static int in_shutdown = GNUNET_NO; /** * @brief Port used for cadet. @@ -1271,7 +1272,30 @@ destroy_channel (void *cls); static void -schedule_channel_destruction (struct ChannelCtx *channel_ctx); +schedule_channel_destruction (struct ChannelCtx *channel_ctx) +{ + GNUNET_assert (NULL != channel_ctx); + if (NULL != channel_ctx->destruction_task && + GNUNET_NO == in_shutdown) + { + channel_ctx->destruction_task = + GNUNET_SCHEDULER_add_now (destroy_channel, channel_ctx); + } +} + + +static void +schedule_peer_destruction (struct PeerContext *peer_ctx) +{ + GNUNET_assert (NULL != peer_ctx); + if (NULL != peer_ctx->destruction_task && + GNUNET_NO == in_shutdown) + { + peer_ctx->destruction_task = + GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); + } +} + /** * @brief Remove peer @@ -1285,6 +1309,8 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) { struct PeerContext *peer_ctx; + GNUNET_assert (NULL != peer_map); + if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) { return GNUNET_NO; @@ -1296,35 +1322,13 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) "Going to remove peer %s\n", GNUNET_i2s (&peer_ctx->peer_id)); Peers_unset_peer_flag (peer, Peers_ONLINE); - /* Do we still have to wait for destruction of channels - * or issue the destruction? */ - if (NULL != peer_ctx->send_channel_ctx && - NULL != peer_ctx->send_channel_ctx->destruction_task) - { - GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); - return GNUNET_NO; - } - if (NULL != peer_ctx->recv_channel_ctx && - NULL != peer_ctx->recv_channel_ctx->destruction_task) - { - GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); - return GNUNET_NO; - } - if (NULL != peer_ctx->recv_channel_ctx) - { - schedule_channel_destruction (peer_ctx->recv_channel_ctx); - GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); - return GNUNET_NO; - } - if (NULL != peer_ctx->send_channel_ctx) - { - schedule_channel_destruction (peer_ctx->send_channel_ctx); - GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); - return GNUNET_NO; - } + /* Clear list of pending operations */ // TODO this probably leaks memory + // ('only' the cls to the function. Not sure what to do with it) GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0); + + /* Remove all pending messages */ while (NULL != peer_ctx->pending_messages_head) { LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1341,6 +1345,7 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) } remove_pending_message (peer_ctx->pending_messages_head, GNUNET_YES); } + /* If we are still waiting for notification whether this peer is live * cancel the according task */ if (NULL != peer_ctx->liveliness_check_pending) @@ -1354,6 +1359,35 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) peer_ctx->liveliness_check_pending = NULL; } + + /* Do we still have to wait for destruction of channels + * or issue the destruction? */ + if (NULL != peer_ctx->send_channel_ctx && + NULL != peer_ctx->send_channel_ctx->destruction_task + ) + { + schedule_peer_destruction (peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->recv_channel_ctx && + NULL != peer_ctx->recv_channel_ctx->destruction_task) + { + schedule_peer_destruction (peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->recv_channel_ctx) + { + schedule_channel_destruction (peer_ctx->recv_channel_ctx); + schedule_peer_destruction (peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->send_channel_ctx) + { + schedule_channel_destruction (peer_ctx->send_channel_ctx); + schedule_peer_destruction (peer_ctx); + return GNUNET_NO; + } + if (NULL != peer_ctx->destruction_task) { GNUNET_SCHEDULER_cancel (peer_ctx->destruction_task); @@ -1367,16 +1401,6 @@ Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) return GNUNET_YES; } -static void -schedule_peer_ctx_destruction (struct PeerContext *peer_ctx) -{ - GNUNET_assert (NULL != peer_ctx); - if (NULL == peer_ctx->destruction_task) - { - GNUNET_SCHEDULER_add_now (destroy_peer, peer_ctx); - } -} - /** * @brief set flags on a given peer. * @@ -1668,18 +1692,6 @@ destroy_channel (void *cls) remove_channel_ctx (peer_ctx->send_channel_ctx); } -static void -schedule_channel_destruction (struct ChannelCtx *channel_ctx) -{ - GNUNET_assert (NULL != channel_ctx); - if (NULL != channel_ctx->destruction_task) - { - channel_ctx->destruction_task = - GNUNET_SCHEDULER_add_now (destroy_channel, channel_ctx); - } -} - - /** * This is called when a channel is destroyed. * @@ -2609,7 +2621,7 @@ remove_peer (const struct GNUNET_PeerIdentity *peer) CustomPeerMap_remove_peer (push_map, peer); RPS_sampler_reinitialise_by_value (prot_sampler, peer); RPS_sampler_reinitialise_by_value (client_sampler, peer); - schedule_peer_ctx_destruction (get_peer_ctx (peer)); + schedule_peer_destruction (get_peer_ctx (peer)); } @@ -4085,6 +4097,8 @@ shutdown_task (void *cls) struct ClientContext *client_ctx; struct ReplyCls *reply_cls; + in_shutdown = GNUNET_YES; + LOG (GNUNET_ERROR_TYPE_DEBUG, "RPS is going down\n"); -- cgit v1.2.3