commit aa01d0a18337787209241d08a630a2d8c10f29f0 Author: Jérémy Bobbio lunar@debian.org Date: Fri Jul 6 15:31:47 2012 +0200
Implement proposal 204: ignore subdomains in hidden service addresses
The implementation is pretty straightforward: parse_extended_hostname() is modified to drop any leading components from an address like 'foo.aaaaaaaaaaaaaaaa.onion'. --- changes/proposal204 | 5 +++++ src/or/connection_edge.c | 15 ++++++++++++++- src/test/test.c | 9 +++++++++ 3 files changed, 28 insertions(+), 1 deletions(-)
diff --git a/changes/proposal204 b/changes/proposal204 new file mode 100644 index 0000000..4c1854b --- /dev/null +++ b/changes/proposal204 @@ -0,0 +1,5 @@ + o Minor features: + - Ignore sub-domain components of a .onion address. This makes HTTP "virtual" + hosting possible: http://foo.aaaaaaaaaaaaaaaa.onion/ and + http//bar.aaaaaaaaaaaaaaaa.onion/ can be two different websites hosted at + the same location. Implements proposal 204. diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index a68a5cf..870ded9 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -2813,6 +2813,9 @@ connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit) /** If address is of the form "y.onion" with a well-formed handle y: * Put a NUL after y, lower-case it, and return ONION_HOSTNAME. * + * If address is of the form "x.y.onion" with a well-formed handle x: + * Drop "x.", put a NUL after y, lower-case it, and return ONION_HOSTNAME. + * * If address is of the form "y.onion" with a badly-formed handle y: * Return BAD_HOSTNAME and log a message. * @@ -2826,6 +2829,7 @@ hostname_type_t parse_extended_hostname(char *address) { char *s; + char *q; char query[REND_SERVICE_ID_LEN_BASE32+1];
s = strrchr(address,'.'); @@ -2840,9 +2844,18 @@ parse_extended_hostname(char *address)
/* so it is .onion */ *s = 0; /* NUL-terminate it */ - if (strlcpy(query, address, REND_SERVICE_ID_LEN_BASE32+1) >= + /* locate a 'sub-domain' component, in order to remove it */ + q = strrchr(address, '.'); + if (q == address) { + goto failed; /* reject sub-domain, as DNS does */ + } + q = (NULL == q) ? address : q + 1; + if (strlcpy(query, q, REND_SERVICE_ID_LEN_BASE32+1) >= REND_SERVICE_ID_LEN_BASE32+1) goto failed; + if (q != address) { + memmove(address, q, strlen(q) + 1 /* also get \0 */); + } if (rend_valid_service_id(query)) { return ONION_HOSTNAME; /* success */ } diff --git a/src/test/test.c b/src/test/test.c index c219d98..e3e989b 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1412,11 +1412,20 @@ test_rend_fns(void) char address2[] = "aaaaaaaaaaaaaaaa.onion"; char address3[] = "fooaddress.exit"; char address4[] = "www.torproject.org"; + char address5[] = "foo.abcdefghijklmnop.onion"; + char address6[] = "foo.bar.abcdefghijklmnop.onion"; + char address7[] = ".abcdefghijklmnop.onion";
test_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); test_assert(ONION_HOSTNAME == parse_extended_hostname(address2)); + test_streq(address2, "aaaaaaaaaaaaaaaa"); test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); + test_assert(ONION_HOSTNAME == parse_extended_hostname(address5)); + test_streq(address5, "abcdefghijklmnop"); + test_assert(ONION_HOSTNAME == parse_extended_hostname(address6)); + test_streq(address6, "abcdefghijklmnop"); + test_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
pk1 = pk_generate(0); pk2 = pk_generate(1);