From 9b52c9179b935f3afbf7119e37af2bf6685efa20 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 25 Oct 2018 10:57:35 +0200 Subject: add possibility of hijacking any (sub)domain, not just TLDs, via configuration file [gns] section --- src/gns/Makefile.am | 1 + src/gns/gns_tld_api.c | 94 ++++++++++++++++++++++----------------- src/gns/test_gns_config_lookup.sh | 44 ++++++++++++++++++ 3 files changed, 97 insertions(+), 42 deletions(-) create mode 100755 src/gns/test_gns_config_lookup.sh (limited to 'src/gns') diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 2659f7e6a..e0497b11e 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am @@ -235,6 +235,7 @@ libgnunet_plugin_block_gns_la_LDFLAGS = \ check_SCRIPTS = \ test_gns_lookup.sh \ + test_gns_config_lookup.sh \ test_gns_ipv6_lookup.sh\ test_gns_txt_lookup.sh\ test_gns_mx_lookup.sh \ diff --git a/src/gns/gns_tld_api.c b/src/gns/gns_tld_api.c index 825b51d06..55ee30bd9 100644 --- a/src/gns/gns_tld_api.c +++ b/src/gns/gns_tld_api.c @@ -92,7 +92,7 @@ struct GNUNET_GNS_LookupWithTldRequest * @return the part of @a name after the last ".", * or @a name if @a name does not contain a "." */ -static char * +static const char * get_tld (const char *name) { const char *tld; @@ -103,28 +103,31 @@ get_tld (const char *name) tld = name; else tld++; /* skip the '.' */ - return GNUNET_strdup (tld); + return tld; } /** - * Eat the TLD of the given @a name. + * Eat the "TLD" (last bit) of the given @a name. * * @param[in,out] name a name + * @param tld what to eat (can be more than just the tld) */ static void -eat_tld (char *name) +eat_tld (char *name, + const char *tld) { - char *tld; - GNUNET_assert (0 < strlen (name)); - tld = strrchr (name, - (unsigned char) '.'); if (NULL == tld) + { strcpy (name, GNUNET_GNS_EMPTY_LABEL_AT); + } else - *tld = '\0'; + { + GNUNET_assert (strlen (tld) < strlen (name)); + name[strlen(name) - strlen(tld) - 1] = '\0'; + } } @@ -227,7 +230,7 @@ GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle, void *proc_cls) { struct GNUNET_GNS_LookupWithTldRequest *ltr; - char *tld; + const char *tld; char *dot_tld; char *zonestr; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; @@ -246,51 +249,59 @@ GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle, strlen (tld), &pkey)) { - eat_tld (ltr->name); + eat_tld (ltr->name, + tld); lookup_with_public_key (ltr, &pkey); - GNUNET_free (tld); return ltr; } - /* second case: TLD is mapped in our configuration file */ - GNUNET_asprintf (&dot_tld, - ".%s", - tld); - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (handle->cfg, - "gns", - dot_tld, - &zonestr)) + /* second case: domain is mapped in our configuration file */ + for (const char *domain = name; + NULL != domain; + domain = strchr (domain, + (unsigned char) '.')) { - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (zonestr, - strlen (zonestr), - &pkey)) + if ('.' == domain[0]) + domain++; + GNUNET_asprintf (&dot_tld, + ".%s", + domain); + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (handle->cfg, + "gns", + dot_tld, + &zonestr)) { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "gns", - dot_tld, - _("Expected a base32-encoded public zone key\n")); + 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); + GNUNET_free (ltr->name); + GNUNET_free (ltr); + return NULL; + } + eat_tld (ltr->name, + &dot_tld[1]); GNUNET_free (zonestr); GNUNET_free (dot_tld); - GNUNET_free (ltr->name); - GNUNET_free (ltr); - GNUNET_free (tld); - return NULL; + lookup_with_public_key (ltr, + &pkey); + return ltr; } GNUNET_free (dot_tld); - GNUNET_free (zonestr); - eat_tld (ltr->name); - lookup_with_public_key (ltr, - &pkey); - GNUNET_free (tld); - return ltr; } - GNUNET_free (dot_tld); /* Final case: TLD matches one of our egos */ - eat_tld (ltr->name); + eat_tld (ltr->name, + tld); /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */ if (NULL == strchr (ltr->name, @@ -302,7 +313,6 @@ GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle, tld, &identity_zone_cb, ltr); - GNUNET_free (tld); if (NULL == ltr->id_op) { GNUNET_free (ltr->name); diff --git a/src/gns/test_gns_config_lookup.sh b/src/gns/test_gns_config_lookup.sh new file mode 100755 index 000000000..35d7c32d9 --- /dev/null +++ b/src/gns/test_gns_config_lookup.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# This file is in the public domain. +trap "gnunet-arm -e -c test_gns_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 +MY_EGO="myego" + +rm -rf `gnunet-config -c test_gns_lookup.conf -s PATHS -o GNUNET_HOME -f` +CFG=`mktemp --tmpdir=$PWD` +cp test_gns_lookup.conf $CFG || exit 77 +which timeout &> /dev/null && DO_TIMEOUT="timeout 5" +TEST_IP="dead::beef" +gnunet-arm -s -c $CFG || exit 77 +gnunet-identity -C $MY_EGO -c $CFG +EPUB=`gnunet-identity -d -c $CFG | grep $MY_EGO | awk '{print $3}'` +gnunet-arm -e -c $CFG +gnunet-config -c $CFG -s "gns" -o ".google.com" -V $EPUB +gnunet-arm -s -c $CFG +sleep 1 +gnunet-namestore -p -z $MY_EGO -a -n www -t AAAA -V $TEST_IP -e never -c $CFG +RES_IP=`$DO_TIMEOUT gnunet-gns --raw -u www.google.com -t AAAA -c $CFG` +gnunet-namestore -z $MY_EGO -d -n www -t AAAA -V $TEST_IP -e never -c $CFG +gnunet-identity -D $MY_EGO -c $CFG +gnunet-arm -e -c $CFG +rm -rf `gnunet-config -c $CFG -f -s paths -o GNUNET_TEST_HOME` +rm $CFG + +if [ "$RES_IP" == "$TEST_IP" ] +then + exit 0 +else + echo "Failed to resolve to proper IP, got $RES_IP." + exit 1 +fi -- cgit v1.2.3