From 1359871c1459a1de5a5e3bc55e752064b8ec4716 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 29 May 2007 19:54:51 +0000 Subject: r13070@catbus: nickm | 2007-05-29 15:53:21 -0400 Fix handling of resolves with very long or otherwise malformed addresses, and comment dns_resolve better, and stop making what should be a BUG warning into an assert(0). This fixes bug 427, which was introduced around 9900/9931/9932. Not a backport candidate: 0.1.2.x never had this bug. svn:r10399 --- src/or/circuituse.c | 5 +++-- src/or/dns.c | 19 ++++++++++++++++--- src/or/eventdns.c | 11 ++++++++++- 3 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 9c4867f09..684a057de 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -536,8 +536,9 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) } } - log_err(LD_BUG,"edge conn not in circuit's list?"); - tor_assert(0); /* should never get here */ + log_warn(LD_BUG,"Edge connection not in circuit's list."); + /* Don't give an error here; it's harmless. */ + // tor_fragile_assert(); } /** Find each circuit that has been unused for too long, or dirty diff --git a/src/or/dns.c b/src/or/dns.c index 1c0630b3d..cfb404d33 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -536,30 +536,42 @@ dns_resolve(edge_connection_t *exitconn) r = dns_resolve_impl(exitconn, is_resolve, oncirc, &hostname); switch (r) { case 1: + /* We got an answer without a lookup. (Either the answer was + * cached, or it was obvious (like an IP address).)*/ if (is_resolve) { + /* Send the answer back right now, and detach. */ if (hostname) send_resolved_hostname_cell(exitconn, hostname); else send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); exitconn->on_circuit = NULL; } else { + /* Add to the n_streams list; the calling function will send back a + * connected cell. */ exitconn->next_stream = oncirc->n_streams; oncirc->n_streams = exitconn; } break; case 0: - /* add it into the linked list of resolving_streams on this circuit */ + /* The request is pending: add the connection into the linked list of + * resolving_streams on this circuit. */ exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; exitconn->next_stream = oncirc->resolving_streams; oncirc->resolving_streams = exitconn; break; case -2: case -1: + /* The request failed before it could start: cancel this connection, + * and stop everybody waiting forthe same connection. */ if (is_resolve) { send_resolved_cell(exitconn, (r == -1) ? RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT); } + exitconn->on_circuit = NULL; + + dns_cancel_pending_resolve(exitconn->_base.address); + if (!exitconn->_base.marked_for_close) { connection_free(TO_CONN(exitconn)); //XXX020 ... and we just leak exitconn otherwise? -RD @@ -838,6 +850,7 @@ dns_cancel_pending_resolve(const char *address) assert_connection_ok(TO_CONN(pendconn), 0); tor_assert(pendconn->_base.s == -1); if (!pendconn->_base.marked_for_close) { + /* XXXX020 RESOURCELIMIT? Not RESOLVEFAILED??? */ connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT); } circ = circuit_get_by_edge_conn(pendconn); @@ -1247,8 +1260,8 @@ launch_resolve(edge_connection_t *exitconn) log_warn(LD_EXIT, "eventdns rejected address %s: error %d.", escaped_safe_str(addr), r); r = evdns_err_is_transient(r) ? -2 : -1; - dns_cancel_pending_resolve(addr); /* also sends end and frees */ - tor_free(addr); + tor_free(addr); /* There is no evdns request in progress; stop + * addr from getting leaked. */ } return r; } diff --git a/src/or/eventdns.c b/src/or/eventdns.c index a3bb3bf24..a53642521 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -2658,14 +2658,23 @@ resolv_conf_parse_line(char *const start, int flags) { #define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) char *const first_token = strtok_r(start, delims, &strtok_state); - if (!first_token) return; + if (!first_token) { + log(EVDNS_LOG_WARN,"No token."); + return; + } + + + log(EVDNS_LOG_WARN,"Token is %s; flags is %d", first_token, flags); if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { const char *const nameserver = NEXT_TOKEN; struct in_addr ina; + log(EVDNS_LOG_WARN,"Parsed nameserver %s", nameserver); + if (inet_aton(nameserver, &ina)) { // address is valid + log(EVDNS_LOG_WARN,"Liked it."); evdns_nameserver_add(ina.s_addr); } } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) { -- cgit v1.2.3