From f7b82a74cc5d39c55a4a232e0e14e7ab51b83ff6 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 6 Mar 2018 11:52:56 +0100 Subject: [PATCH] fix proxy and refactor OIDC --- po/POTFILES.in | 121 +- src/gns/gnunet-gns-proxy.c | 182 +- src/identity-provider/Makefile.am | 16 + .../gnunet-service-identity-provider.c | 1 - .../plugin_rest_identity_provider.c | 1741 +---------------- src/rest/gnunet-rest-server.c | 4 +- 6 files changed, 171 insertions(+), 1894 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 5804b980c..d8c79197d 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/dnsparser.c @@ -125,8 +125,8 @@ src/dv/gnunet-dv.c src/dv/gnunet-service-dv.c src/dv/plugin_transport_dv.c src/exit/gnunet-daemon-exit.c -src/exit/gnunet-helper-exit.c src/exit/gnunet-helper-exit-windows.c +src/exit/gnunet-helper-exit.c src/fragmentation/defragmentation.c src/fragmentation/fragmentation.c src/fs/fs_api.c @@ -151,8 +151,8 @@ src/fs/gnunet-auto-share.c src/fs/gnunet-daemon-fsprofiler.c src/fs/gnunet-directory.c src/fs/gnunet-download.c -src/fs/gnunet-fs.c src/fs/gnunet-fs-profiler.c +src/fs/gnunet-fs.c src/fs/gnunet-helper-fs-publish.c src/fs/gnunet-publish.c src/fs/gnunet-search.c @@ -171,10 +171,10 @@ src/gns/gns_api.c src/gns/gns_tld_api.c src/gns/gnunet-bcd.c src/gns/gnunet-dns2gns.c -src/gns/gnunet-gns.c src/gns/gnunet-gns-helper-service-w32.c src/gns/gnunet-gns-import.c src/gns/gnunet-gns-proxy.c +src/gns/gnunet-gns.c src/gns/gnunet-service-gns.c src/gns/gnunet-service-gns_interceptor.c src/gns/gnunet-service-gns_resolver.c @@ -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 @@ -212,15 +207,21 @@ 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 +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 @@ -234,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/namestore_api.c src/namestore/namestore_api_monitor.c @@ -250,10 +251,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 @@ -262,15 +263,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 @@ -321,13 +322,13 @@ src/rps/gnunet-service-rps_custommap.c src/rps/gnunet-service-rps_sampler.c src/rps/gnunet-service-rps_sampler_elem.c src/rps/gnunet-service-rps_view.c -src/rps/rps_api.c src/rps/rps-test_util.c +src/rps/rps_api.c src/scalarproduct/gnunet-scalarproduct.c -src/scalarproduct/gnunet-service-scalarproduct_alice.c -src/scalarproduct/gnunet-service-scalarproduct_bob.c src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c +src/scalarproduct/gnunet-service-scalarproduct_alice.c +src/scalarproduct/gnunet-service-scalarproduct_bob.c src/scalarproduct/scalarproduct_api.c src/secretsharing/gnunet-secretsharing-profiler.c src/secretsharing/gnunet-service-secretsharing.c @@ -354,15 +355,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 @@ -370,20 +372,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 @@ -392,34 +393,39 @@ src/testing/testing.c src/topology/friends.c src/topology/gnunet-daemon-topology.c src/transport/gnunet-helper-transport-bluetooth.c -src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-helper-transport-wlan-dummy.c -src/transport/gnunet-service-transport_ats.c +src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-service-transport.c +src/transport/gnunet-service-transport_ats.c src/transport/gnunet-service-transport_hello.c src/transport/gnunet-service-transport_manipulation.c src/transport/gnunet-service-transport_neighbours.c src/transport/gnunet-service-transport_plugins.c src/transport/gnunet-service-transport_validation.c -src/transport/gnunet-transport.c src/transport/gnunet-transport-certificate-creation.c src/transport/gnunet-transport-profiler.c src/transport/gnunet-transport-wlan-receiver.c src/transport/gnunet-transport-wlan-sender.c +src/transport/gnunet-transport.c src/transport/plugin_transport_http_client.c src/transport/plugin_transport_http_common.c src/transport/plugin_transport_http_server.c src/transport/plugin_transport_smtp.c src/transport/plugin_transport_tcp.c src/transport/plugin_transport_template.c -src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_udp.c +src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_unix.c src/transport/plugin_transport_wlan.c src/transport/tcp_connection_legacy.c src/transport/tcp_server_legacy.c src/transport/tcp_server_mst_legacy.c src/transport/tcp_service_legacy.c +src/transport/transport-testing-filenames.c +src/transport/transport-testing-loggers.c +src/transport/transport-testing-main.c +src/transport/transport-testing-send.c +src/transport/transport-testing.c src/transport/transport_api_address_to_string.c src/transport/transport_api_blacklist.c src/transport/transport_api_core.c @@ -428,11 +434,6 @@ src/transport/transport_api_manipulation.c src/transport/transport_api_monitor_peers.c src/transport/transport_api_monitor_plugins.c src/transport/transport_api_offer_hello.c -src/transport/transport-testing.c -src/transport/transport-testing-filenames.c -src/transport/transport-testing-loggers.c -src/transport/transport-testing-main.c -src/transport/transport-testing-send.c src/tun/regex.c src/tun/tun.c src/util/bandwidth.c @@ -446,8 +447,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 @@ -467,8 +468,8 @@ src/util/crypto_symmetric.c src/util/disk.c src/util/getopt.c src/util/getopt_helpers.c -src/util/gnunet-config.c src/util/gnunet-config-diff.c +src/util/gnunet-config.c src/util/gnunet-ecc.c src/util/gnunet-helper-w32-console.c src/util/gnunet-resolver.c @@ -499,8 +500,8 @@ src/util/time.c src/util/w32cat.c src/util/win.c src/util/winproc.c -src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-helper-vpn-windows.c +src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-service-vpn.c src/vpn/gnunet-vpn.c src/vpn/vpn_api.c diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 73af0e693..5146eb0d7 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c @@ -480,12 +480,7 @@ struct Socks5Request /** * Handle to GNS lookup, during #SOCKS5_RESOLVING phase. */ - struct GNUNET_GNS_LookupRequest *gns_lookup; - - /** - * Handle to Ego lookup, during #SOCKS5_RESOLVING phase. - */ - struct GNUNET_IDENTITY_EgoLookup *el; + struct GNUNET_GNS_LookupWithTldRequest *gns_lookup; /** * Client socket read task @@ -532,11 +527,6 @@ struct Socks5Request */ char *domain; - /** - * the tld - */ - const char *tld; - /** * DNS Legacy Host Name as given by GNS, NULL if not given. */ @@ -775,7 +765,7 @@ cleanup_s5r (struct Socks5Request *s5r) if (NULL != s5r->wtask) GNUNET_SCHEDULER_cancel (s5r->wtask); if (NULL != s5r->gns_lookup) - GNUNET_GNS_lookup_cancel (s5r->gns_lookup); + GNUNET_GNS_lookup_with_tld_cancel (s5r->gns_lookup); if (NULL != s5r->sock) { if (SOCKS5_SOCKET_WITH_MHD <= s5r->state) @@ -1098,18 +1088,16 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) if (0 == strcasecmp (cookie_domain, s5r->leho + delta_cdomain)) { offset += sprintf (new_cookie_hdr + offset, - " domain=%s.%s;", - s5r->domain, - s5r->tld); + " domain=%s;", + s5r->domain); continue; } } else if (0 == strcmp (cookie_domain, s5r->leho)) { offset += sprintf (new_cookie_hdr + offset, - " domain=%s.%s;", - s5r->domain, - s5r->tld); + " domain=%s;", + s5r->domain); continue; } GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -1138,12 +1126,11 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) strlen (leho_host))) { GNUNET_asprintf (&new_location, - "%s%s.%s%s", + "%s%s%s", (HTTPS_PORT != s5r->port) ? "http://" : "https://", s5r->domain, - s5r->tld, hdr_val + strlen (leho_host)); hdr_val = new_location; } @@ -2389,9 +2376,8 @@ setup_data_transfer (struct Socks5Request *s5r) { case HTTPS_PORT: GNUNET_asprintf (&domain, - "%s.%s", - s5r->domain, - s5r->tld); + "%s", + s5r->domain); hd = lookup_ssl_httpd (domain); if (NULL == hd) { @@ -2556,6 +2542,7 @@ signal_socks_success (struct Socks5Request *s5r) */ static void handle_gns_result (void *cls, + int tld, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { @@ -2690,82 +2677,6 @@ clear_from_s5r_rbuf (struct Socks5Request *s5r, } -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is determined by a name. - * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - */ -static void -identity_zone_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) -{ - struct Socks5Request *s5r = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - - s5r->el = NULL; - if (NULL == ego) - { - signal_socks_failure (s5r, - SOCKS5_STATUS_GENERAL_FAILURE); - return; - - } - GNUNET_IDENTITY_ego_get_public_key (ego, - &pkey); - s5r->gns_lookup = GNUNET_GNS_lookup (gns_handle, - s5r->domain, - &pkey, - GNUNET_DNSPARSER_TYPE_A, - GNUNET_NO /* only cached */, - &handle_gns_result, - s5r); - - -} - -/** - * Obtain TLD from @a name - * - * @param name a name - * @return the part of @a name after the last ".", - * or @a name if @a name does not contain a "." - */ -static const char * -get_tld (const char *name) -{ - const char *tld; - - tld = strrchr (name, - (unsigned char) '.'); - if (NULL == tld) - tld = name; - else - tld++; /* skip the '.' */ - return tld; -} - -/** - * Eat the TLD of the given @a name. - * - * @param name a name - */ -static void -eat_tld (char *name) -{ - char *tld; - - GNUNET_assert (0 < strlen (name)); - tld = strrchr (name, - (unsigned char) '.'); - if (NULL == tld) - strcpy (name, - GNUNET_GNS_MASTERZONE_STR); - else - *tld = '\0'; -} - /** * Read data from incoming Socks5 connection * @@ -2781,9 +2692,6 @@ do_s5r_read (void *cls) ssize_t rlen; size_t alen; const struct GNUNET_SCHEDULER_TaskContext *tc; - char *zonestr; - char *dot_tld; - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; s5r->rtask = NULL; tc = GNUNET_SCHEDULER_get_task_context (); @@ -2934,70 +2842,12 @@ do_s5r_read (void *cls) ntohs (*port)); s5r->state = SOCKS5_RESOLVING; s5r->port = ntohs (*port); - /* TLD is zkey */ - s5r->tld = get_tld (s5r->domain); - if (GNUNET_OK == - GNUNET_CRYPTO_ecdsa_public_key_from_string (s5r->tld, - strlen (s5r->tld), - &pkey)) - { - eat_tld (s5r->domain); - s5r->gns_lookup = GNUNET_GNS_lookup (gns_handle, - s5r->domain, - &pkey, - GNUNET_DNSPARSER_TYPE_A, - GNUNET_NO /* only cached */, - &handle_gns_result, - s5r); - - break; - } - /* TLD is mapped in our config */ - GNUNET_asprintf (&dot_tld, - ".%s", - s5r->tld); - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cfg, - "gns", - dot_tld, - &zonestr)) - { - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (zonestr, - strlen (zonestr), - &pkey)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "gns", - dot_tld, - _("Expected a base32-encoded public zone key\n")); - GNUNET_free (zonestr); - GNUNET_free (dot_tld); - signal_socks_failure (s5r, - SOCKS5_STATUS_GENERAL_FAILURE); - return; - - } - GNUNET_free (zonestr); - GNUNET_free (dot_tld); - eat_tld (s5r->domain); - s5r->gns_lookup = GNUNET_GNS_lookup (gns_handle, - s5r->domain, - &pkey, - GNUNET_DNSPARSER_TYPE_A, - GNUNET_NO /* only cached */, - &handle_gns_result, - s5r); - break; - } - - /* TLD matches against ego */ - eat_tld (s5r->domain); - - s5r->el = GNUNET_IDENTITY_ego_lookup (cfg, - s5r->tld, - &identity_zone_cb, - s5r); + s5r->gns_lookup = GNUNET_GNS_lookup_with_tld (gns_handle, + s5r->domain, + GNUNET_DNSPARSER_TYPE_A, + GNUNET_NO /* only cached */, + &handle_gns_result, + s5r); break; } default: diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am index adf6af3b3..2eb699542 100644 --- a/src/identity-provider/Makefile.am +++ b/src/identity-provider/Makefile.am @@ -32,6 +32,7 @@ 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) @@ -102,6 +103,21 @@ libgnunet_plugin_rest_identity_provider_la_LIBADD = \ 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 = \ diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 523eebf39..207923d5e 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -1736,7 +1736,6 @@ process_consume_abe_key (void *cls, uint32_t rd_count, GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head, handle->parallel_lookups_tail, parallel_lookup); - GNUNET_free (scope); } GNUNET_free (scopes); GNUNET_free (buf); diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index 7b4ebf2fc..398d09cd2 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c @@ -40,7 +40,6 @@ #include "gnunet_signatures.h" #include "gnunet_identity_attribute_lib.h" #include "gnunet_identity_provider_service.h" -#include "jwt.h" /** * REST root namespace @@ -67,26 +66,6 @@ */ #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" -/** - * Authorize endpoint - */ -#define GNUNET_REST_API_NS_AUTHORIZE "/idp/authorize" - -/** - * Token endpoint - */ -#define GNUNET_REST_API_NS_TOKEN "/idp/token" - -/** - * UserInfo endpoint - */ -#define GNUNET_REST_API_NS_USERINFO "/idp/userinfo" - -/** - * Login namespace - */ -#define GNUNET_REST_API_NS_LOGIN "/idp/login" - /** * Attribute key */ @@ -113,111 +92,6 @@ */ #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 - */ -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 */ @@ -236,34 +110,6 @@ struct Plugin const struct GNUNET_CONFIGURATION_Handle *cfg; }; -/** - * OIDC needed variables - */ -struct OIDC_Variables -{ - - struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey; - - char *client_id; - - int is_client_trusted; - - char *redirect_uri; - - char *scope; - - char *state; - - char *nonce; - - char *response_type; - - char *login_identity; - - json_t *response; - -}; - /** * The ego list */ @@ -318,11 +164,6 @@ struct RequestHandle */ struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; - /** - * OIDC variables - */ - struct OIDC_Variables *oidc; - /** * The processing state */ @@ -408,21 +249,11 @@ struct RequestHandle */ char *url; - /** - * The tld for redirect - */ - char *tld; - /** * Error response message */ char *emsg; - /** - * Error response description - */ - char *edesc; - /** * Reponse code */ @@ -462,34 +293,10 @@ cleanup_handle (struct RequestHandle *handle) 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; @@ -537,21 +344,13 @@ do_error (void *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) ? "\"" : ""); + 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); - 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); @@ -559,53 +358,6 @@ do_error (void *cls) } -/** - * 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. * @@ -668,46 +420,6 @@ return_response (void *cls) cleanup_handle (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(char *string) -{ - char *output; - GNUNET_STRINGS_base64_encode(string,strlen(string),&output); - int index = strlen(output)-1; - while ('=' == output[index]) - { - output[index] = '\0'; - index--; - } - return output; -} - static void collect_finished_cb (void *cls) { @@ -1349,1367 +1061,102 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, } /** - * Interprets cookie header and pass its identity keystring to handle + * Handle rest request + * + * @param handle the request handle */ static void -cookie_identity_interpretation (struct RequestHandle *handle) +init_cont (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); + 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 + }; - 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; - } + 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); } } /** - * Redirects to login page stored in configuration file + * 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 -login_redirection(void *cls) +list_ego (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *identifier) { - char *login_base_url; - char *new_redirect; - struct MHD_Response *resp; struct RequestHandle *handle = cls; + struct EgoEntry *ego_entry; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; - 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 + if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) { - 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); + handle->state = ID_REST_STATE_POST_INIT; + init_cont (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); -} + 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 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); - 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); -} - -/** - * 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_minute_ (), - 30)); - 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, *redirect_uri, *expected_redirect_uri; - 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; - - /* - * 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), &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; - } - redirect_uri = GNUNET_CONTAINER_multihashmap_get ( - handle->rest_handle->url_param_map, &cache_key); - - - //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),&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; - } - char *id_token = jwt_create_from_list(&ticket->audience, - cl, - GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego)); - - //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; - - if (NULL == identity) - { - GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); - return; - } - - json_object_set_new (handle->oidc->response, - attr->name, - json_string(attr->data)); -} - -/** - * 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_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_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_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) +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; @@ -2782,42 +1229,6 @@ libgnunet_plugin_rest_identity_provider_done (void *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, diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c index 2f840be8b..325bcfd0a 100644 --- a/src/rest/gnunet-rest-server.c +++ b/src/rest/gnunet-rest-server.c @@ -764,7 +764,7 @@ load_plugin (void *cls, struct GNUNET_HashCode key; if (NULL == lib_ret) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not load plugin `%s'\n", libname); return; @@ -777,7 +777,7 @@ load_plugin (void *cls, plugin, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not load add plugin `%s'\n", libname); return; -- 2.25.1