diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-06-13 11:40:38 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2012-06-13 11:40:38 -0400 |
commit | 5a3d9636f5e0ead80a46163af9ffadcbf6d5195f (patch) | |
tree | 3f9a94eba2b969a313aa9ea01dd40f9b0eed9fca /src/or | |
parent | 62a77f1117335f2ddee86f696379dde106ad1ee0 (diff) | |
parent | ba9a12119c88676fa0dd2a282d927840cd5d94fb (diff) | |
download | tor-5a3d9636f5e0ead80a46163af9ffadcbf6d5195f.tar tor-5a3d9636f5e0ead80a46163af9ffadcbf6d5195f.tar.gz |
Merge remote-tracking branch 'public/bug3940_redux'
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/connection_edge.c | 104 | ||||
-rw-r--r-- | src/or/connection_edge.h | 5 | ||||
-rw-r--r-- | src/or/or.h | 5 | ||||
-rw-r--r-- | src/or/relay.c | 2 |
4 files changed, 78 insertions, 38 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 63a3213d3..eae19bad4 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1095,13 +1095,22 @@ addressmap_match_superdomains(char *address) * address changed; false otherwise. Set *<b>expires_out</b> to the * expiry time of the result, or to <b>time_max</b> if the result does * not expire. + * + * If <b>exit_source_out</b> is non-null, we set it as follows. If we the + * address starts out as a non-exit address, and we remap it to an .exit + * address at any point, then set *<b>exit_source_out</b> to the + * address_entry_source_t of the first such rule. Set *<b>exit_source_out</b> + * to ADDRMAPSRC_NONE if there is no such rewrite. + * */ int -addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) +addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, + addressmap_entry_source_t *exit_source_out) { addressmap_entry_t *ent; int rewrites; time_t expires = TIME_MAX; + addressmap_entry_source_t exit_source = ADDRMAPSRC_NONE; for (rewrites = 0; rewrites < 16; rewrites++) { int exact_match = 0; @@ -1117,9 +1126,7 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) /* This is a rule like *.example.com example.com, and we just got * "example.com" */ tor_free(addr_orig); - if (expires_out) - *expires_out = expires; - return rewrites > 0; + goto done; } exact_match = 1; @@ -1127,9 +1134,7 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) if (!ent || !ent->new_address) { tor_free(addr_orig); - if (expires_out) - *expires_out = expires; - return (rewrites > 0); /* done, no rewrite needed */ + goto done; } if (ent->dst_wildcard && !exact_match) { @@ -1139,6 +1144,12 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) strlcpy(address, ent->new_address, maxlen); } + if (!strcmpend(address, ".exit") && + strcmpend(addr_orig, ".exit") && + exit_source == ADDRMAPSRC_NONE) { + exit_source = ent->source; + } + log_info(LD_APP, "Addressmap: rewriting %s to %s", addr_orig, escaped_safe_str_client(address)); if (ent->expires > 1 && ent->expires < expires) @@ -1149,9 +1160,13 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) "Loop detected: we've rewritten %s 16 times! Using it as-is.", escaped_safe_str_client(address)); /* it's fine to rewrite a rewrite, but don't loop forever */ + + done: + if (exit_source_out) + *exit_source_out = exit_source; if (expires_out) *expires_out = TIME_MAX; - return 1; + return (rewrites > 0); } /** If we have a cached reverse DNS entry for the address stored in the @@ -1782,11 +1797,9 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, int automap = 0; char orig_address[MAX_SOCKS_ADDR_LEN]; time_t map_expires = TIME_MAX; - /* This will be set to true iff the address starts out as a non-.exit - address, and we remap it to one because of an entry in the addressmap. */ - int remapped_to_exit = 0; time_t now = time(NULL); connection_t *base_conn = ENTRY_TO_CONN(conn); + addressmap_entry_source_t exit_source = ADDRMAPSRC_NONE; tor_strlower(socks->address); /* normalize it */ strlcpy(orig_address, socks->address, sizeof(orig_address)); @@ -1794,6 +1807,16 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, safe_str_client(socks->address), socks->port); + if (!strcmpend(socks->address, ".exit") && !options->AllowDotExit) { + log_warn(LD_APP, "The \".exit\" notation is disabled in Tor due to " + "security risks. Set AllowDotExit in your torrc to enable " + "it (at your own risk)."); + control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", + escaped(socks->address)); + connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + return -1; + } + if (! conn->original_dest_address) conn->original_dest_address = tor_strdup(conn->socks_request->address); @@ -1854,16 +1877,11 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } } } else if (!automap) { - int started_without_chosen_exit = strcasecmpend(socks->address, ".exit"); /* For address map controls, remap the address. */ if (addressmap_rewrite(socks->address, sizeof(socks->address), - &map_expires)) { + &map_expires, &exit_source)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, REMAP_STREAM_SOURCE_CACHE); - if (started_without_chosen_exit && - !strcasecmpend(socks->address, ".exit") && - map_expires < TIME_MAX) - remapped_to_exit = 1; } } @@ -1882,8 +1900,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, /* Parse the address provided by SOCKS. Modify it in-place if it * specifies a hidden-service (.onion) or particular exit node (.exit). */ - addresstype = parse_extended_hostname(socks->address, - remapped_to_exit || options->AllowDotExit); + addresstype = parse_extended_hostname(socks->address); if (addresstype == BAD_HOSTNAME) { control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", @@ -1902,14 +1919,42 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, options->_ExcludeExitNodesUnion : options->ExcludeExitNodes; const node_t *node; + if (exit_source == ADDRMAPSRC_AUTOMAP && !options->AllowDotExit) { + /* Whoops; this one is stale. It must have gotten added earlier, + * when AllowDotExit was on. */ + log_warn(LD_APP,"Stale automapped address for '%s.exit', with " + "AllowDotExit disabled. Refusing.", + safe_str_client(socks->address)); + control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", + escaped(socks->address)); + connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + return -1; + } + + if (exit_source == ADDRMAPSRC_DNS || + (exit_source == ADDRMAPSRC_NONE && !options->AllowDotExit)) { + /* It shouldn't be possible to get a .exit address from any of these + * sources. */ + log_warn(LD_BUG,"Address '%s.exit', with impossible source for the " + ".exit part. Refusing.", + safe_str_client(socks->address)); + control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", + escaped(socks->address)); + connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + return -1; + } + tor_assert(!automap); if (s) { /* The address was of the form "(stuff).(name).exit */ if (s[1] != '\0') { conn->chosen_exit_name = tor_strdup(s+1); node = node_get_by_nickname(conn->chosen_exit_name, 1); - if (remapped_to_exit) /* 5 tries before it expires the addressmap */ + + if (exit_source == ADDRMAPSRC_TRACKEXIT) { + /* We 5 tries before it expires the addressmap */ conn->chosen_exit_retries = TRACKHOSTEXITS_RETRIES; + } *s = 0; } else { /* Oops, the address was (stuff)..exit. That's not okay. */ @@ -3427,17 +3472,14 @@ connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit) * If address is of the form "y.onion" with a badly-formed handle y: * Return BAD_HOSTNAME and log a message. * - * If address is of the form "y.exit" and <b>allowdotexit</b> is true: + * If address is of the form "y.exit": * Put a NUL after y and return EXIT_HOSTNAME. * - * If address is of the form "y.exit" and <b>allowdotexit</b> is false: - * Return BAD_HOSTNAME and log a message. - * * Otherwise: * Return NORMAL_HOSTNAME and change nothing. */ hostname_type_t -parse_extended_hostname(char *address, int allowdotexit) +parse_extended_hostname(char *address) { char *s; char query[REND_SERVICE_ID_LEN_BASE32+1]; @@ -3446,16 +3488,8 @@ parse_extended_hostname(char *address, int allowdotexit) if (!s) return NORMAL_HOSTNAME; /* no dot, thus normal */ if (!strcmp(s+1,"exit")) { - if (allowdotexit) { - *s = 0; /* NUL-terminate it */ - return EXIT_HOSTNAME; /* .exit */ - } else { - log_warn(LD_APP, "The \".exit\" notation is disabled in Tor due to " - "security risks. Set AllowDotExit in your torrc to enable " - "it."); - /* FFFF send a controller event too to notify Vidalia users */ - return BAD_HOSTNAME; - } + *s = 0; /* NUL-terminate it */ + return EXIT_HOSTNAME; /* .exit */ } if (strcmp(s+1,"onion")) return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */ diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 78baf75b6..c320d6ba4 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -74,7 +74,8 @@ void addressmap_clean(time_t now); void addressmap_clear_configured(void); void addressmap_clear_transient(void); void addressmap_free_all(void); -int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out); +int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, + addressmap_entry_source_t *exit_source_out); int addressmap_have_mapping(const char *address, int update_timeout); void addressmap_register(const char *address, char *new_address, @@ -101,7 +102,7 @@ int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, typedef enum hostname_type_t { NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME, BAD_HOSTNAME } hostname_type_t; -hostname_type_t parse_extended_hostname(char *address, int allowdotexit); +hostname_type_t parse_extended_hostname(char *address); #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) int get_pf_socket(void); diff --git a/src/or/or.h b/src/or/or.h index 9ca9239ce..7ff628411 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3855,6 +3855,11 @@ typedef enum { /** We're remapping this address because we got a DNS resolution from a * Tor server that told us what its value was. */ ADDRMAPSRC_DNS, + + /** No remapping has occurred. This isn't a possible value for an + * addrmap_entry_t; it's used as a null value when we need to answer "Why + * did this remapping happen." */ + ADDRMAPSRC_NONE } addressmap_entry_source_t; /********************************* control.c ***************************/ diff --git a/src/or/relay.c b/src/or/relay.c index e22ce47b2..0c99c3497 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -764,7 +764,7 @@ connection_ap_process_end_not_open( /* rewrite it to an IP if we learned one. */ if (addressmap_rewrite(conn->socks_request->address, sizeof(conn->socks_request->address), - NULL)) { + NULL, NULL)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); } if (conn->chosen_exit_optional || |