diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/Makefile.nmake | 56 | ||||
-rw-r--r-- | src/or/buffers.c | 2 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 25 | ||||
-rw-r--r-- | src/or/circuitbuild.h | 3 | ||||
-rw-r--r-- | src/or/command.c | 3 | ||||
-rw-r--r-- | src/or/config.c | 91 | ||||
-rw-r--r-- | src/or/config.h | 3 | ||||
-rw-r--r-- | src/or/connection.c | 3 | ||||
-rw-r--r-- | src/or/connection_edge.c | 40 | ||||
-rw-r--r-- | src/or/connection_edge.h | 3 | ||||
-rw-r--r-- | src/or/connection_or.c | 23 | ||||
-rw-r--r-- | src/or/control.c | 15 | ||||
-rw-r--r-- | src/or/dirserv.c | 9 | ||||
-rw-r--r-- | src/or/dirserv.h | 1 | ||||
-rw-r--r-- | src/or/dirvote.c | 10 | ||||
-rw-r--r-- | src/or/dns.c | 4 | ||||
-rw-r--r-- | src/or/main.c | 8 | ||||
-rw-r--r-- | src/or/networkstatus.c | 4 | ||||
-rw-r--r-- | src/or/or.h | 5 | ||||
-rw-r--r-- | src/or/rendmid.c | 13 | ||||
-rw-r--r-- | src/or/rephist.c | 63 | ||||
-rw-r--r-- | src/or/rephist.h | 3 | ||||
-rw-r--r-- | src/or/router.c | 73 | ||||
-rw-r--r-- | src/or/router.h | 1 | ||||
-rw-r--r-- | src/or/routerlist.c | 11 | ||||
-rw-r--r-- | src/or/routerparse.c | 27 | ||||
-rw-r--r-- | src/or/routerparse.h | 2 | ||||
-rw-r--r-- | src/or/transports.c | 79 |
28 files changed, 419 insertions, 161 deletions
diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake index 919edbbf22..3181e79c20 100644 --- a/src/or/Makefile.nmake +++ b/src/or/Makefile.nmake @@ -1,28 +1,28 @@ -all: tor.exe
-
-CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common
-
-LIBS = ..\..\..\build-alpha\lib\libevent.a \
- ..\..\..\build-alpha\lib\libcrypto.a \
- ..\..\..\build-alpha\lib\libssl.a \
- ..\..\..\build-alpha\lib\libz.a \
- ws2_32.lib advapi32.lib shell32.lib
-
-LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \
- command.obj config.obj connection.obj connection_edge.obj \
- connection_or.obj control.obj cpuworker.obj directory.obj \
- dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
- hibernate.obj main.obj microdesc.obj networkstatus.obj \
- nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
- rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
- rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
- config_codedigest.obj ntmain.obj
-
-libtor.lib: $(LIBTOR_OBJECTS)
- lib $(LIBTOR_OBJECTS) /out:libtor.lib
-
-tor.exe: libtor.lib tor_main.obj
- $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj
-
-clean:
- del $(LIBTOR_OBJECTS) *.lib tor.exe
+all: tor.exe + +CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common + +LIBS = ..\..\..\build-alpha\lib\libevent.a \ + ..\..\..\build-alpha\lib\libcrypto.a \ + ..\..\..\build-alpha\lib\libssl.a \ + ..\..\..\build-alpha\lib\libz.a \ + ws2_32.lib advapi32.lib shell32.lib + +LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \ + command.obj config.obj connection.obj connection_edge.obj \ + connection_or.obj control.obj cpuworker.obj directory.obj \ + dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \ + hibernate.obj main.obj microdesc.obj networkstatus.obj \ + nodelist.obj onion.obj policies.obj reasons.obj relay.obj \ + rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \ + rephist.obj router.obj routerlist.obj routerparse.obj status.obj \ + config_codedigest.obj ntmain.obj + +libtor.lib: $(LIBTOR_OBJECTS) + lib $(LIBTOR_OBJECTS) /out:libtor.lib + +tor.exe: libtor.lib tor_main.obj + $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj + +clean: + del $(LIBTOR_OBJECTS) *.lib tor.exe diff --git a/src/or/buffers.c b/src/or/buffers.c index d60e54e87a..aa3e01fd9d 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1011,7 +1011,7 @@ fetch_from_buf(char *string, size_t string_len, buf_t *buf) /** True iff the cell command <b>command</b> is one that implies a * variable-length cell in Tor link protocol <b>linkproto</b>. */ -static inline int +static INLINE int cell_command_is_var_length(uint8_t command, int linkproto) { /* If linkproto is v2 (2), CELL_VERSIONS is the only variable-length cells diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 5481838ccb..82ff327135 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2847,6 +2847,10 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) if (node) break; smartlist_clear(supporting); + /* If we reach this point, we can't actually support any unhandled + * predicted ports, so clear all the remaining ones. */ + if (smartlist_len(needed_ports)) + rep_hist_remove_predicted_ports(needed_ports); } SMARTLIST_FOREACH(needed_ports, uint16_t *, cp, tor_free(cp)); smartlist_free(needed_ports); @@ -3733,7 +3737,9 @@ entry_guard_free(entry_guard_t *e) /** Remove any entry guard which was selected by an unknown version of Tor, * or which was selected by a version of Tor that's known to select - * entry guards badly. */ + * entry guards badly, or which was selected more 2 months ago. */ +/* XXXX The "obsolete guards" and "chosen long ago guards" things should + * probably be different functions. */ static int remove_obsolete_entry_guards(time_t now) { @@ -3862,6 +3868,8 @@ entry_guards_compute_status(const or_options_t *options, time_t now) if (remove_dead_entry_guards(now)) changed = 1; + if (remove_obsolete_entry_guards(now)) + changed = 1; if (changed) { SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { @@ -4964,6 +4972,21 @@ find_bridge_by_digest(const char *digest) return NULL; } +const char * +find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port) +{ + if (!bridge_list) + return NULL; + + SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) { + if (tor_addr_eq(&bridge->addr, addr) && + (bridge->port == port)) + return bridge->transport_name; + } SMARTLIST_FOREACH_END(bridge); + + return NULL; +} + /** If <b>addr</b> and <b>port</b> match the address and port of a * bridge of ours that uses pluggable transports, place its transport * in <b>transport</b>. diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index a7fd208305..2ef5be8f25 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -157,6 +157,9 @@ void transport_free(transport_t *transport); transport_t *transport_new(const tor_addr_t *addr, uint16_t port, const char *name, int socks_ver); +const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr, + uint16_t port); + int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, const transport_t **transport); transport_t *transport_get_by_name(const char *name); diff --git a/src/or/command.c b/src/or/command.c index 9b14092fed..4e56edd5db 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -601,7 +601,6 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) int reason; circ = circuit_get_by_circid_orconn(cell->circ_id, conn); - reason = (uint8_t)cell->payload[0]; if (!circ) { log_info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.", cell->circ_id, conn->_base.address, conn->_base.port); @@ -609,6 +608,8 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) } log_debug(LD_OR,"Received for circID %d.",cell->circ_id); + reason = (uint8_t)cell->payload[0]; + if (!CIRCUIT_IS_ORIGIN(circ) && cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) { /* the destroy came from behind */ diff --git a/src/or/config.c b/src/or/config.c index bfed4e5db4..27aa8a2f23 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -748,7 +748,7 @@ set_options(or_options_t *new_val, char **msg) } /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is * just starting up then the old_options will be undefined. */ - if (old_options) { + if (old_options && old_options != global_options) { elements = smartlist_new(); for (i=0; options_format.vars[i].name; ++i) { const config_var_t *var = &options_format.vars[i]; @@ -774,7 +774,9 @@ set_options(or_options_t *new_val, char **msg) control_event_conf_changed(elements); smartlist_free(elements); } - config_free(&options_format, old_options); + + if (old_options != global_options) + config_free(&options_format, old_options); return 0; } @@ -783,6 +785,7 @@ extern const char tor_git_revision[]; /* from tor_main.c */ /** The version of this Tor process, as parsed. */ static char *the_tor_version = NULL; +static char *the_short_tor_version = NULL; /** Return the current Tor version. */ const char * @@ -790,14 +793,31 @@ get_version(void) { if (the_tor_version == NULL) { if (strlen(tor_git_revision)) { - tor_asprintf(&the_tor_version, "%s (git-%s)", VERSION, tor_git_revision); + tor_asprintf(&the_tor_version, "%s (git-%s)", get_short_version(), + tor_git_revision); } else { - the_tor_version = tor_strdup(VERSION); + the_tor_version = tor_strdup(get_short_version()); } } return the_tor_version; } +/** Return the current Tor version, without any git tag. */ +const char * +get_short_version(void) +{ + + if (the_short_tor_version == NULL) { +#ifdef TOR_BUILD_TAG + tor_asprintf(&the_short_tor_version, "%s (%s)", VERSION, TOR_BUILD_TAG); +#else + the_short_tor_version = tor_strdup(VERSION); +#endif + } + return the_short_tor_version; +} + + /** Release additional memory allocated in options */ static void @@ -5099,7 +5119,7 @@ parse_client_transport_line(const char *line, int validate_only) *tmp++ = smartlist_get(items, 2); smartlist_del_keeporder(items, 2); } - *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/ + *tmp = NULL; /*terminated with NULL, just like execve() likes it*/ /* kickstart the thing */ pt_kickstart_client_proxy(transport_list, proxy_argv); @@ -5222,7 +5242,7 @@ parse_server_transport_line(const char *line, int validate_only) *tmp++ = smartlist_get(items, 2); smartlist_del_keeporder(items, 2); } - *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/ + *tmp = NULL; /*terminated with NULL, just like execve() likes it*/ /* kickstart the thing */ pt_kickstart_server_proxy(transport_list, proxy_argv); @@ -6040,6 +6060,65 @@ get_configured_ports(void) return configured_ports; } +/** Return an <address>:<port> string representation of the address + * where the first <b>listener_type</b> listener waits for + * connections. Return NULL if we couldn't find a listener. The + * string is allocated on the heap and it's the responsibility of the + * caller to free it after use. + * + * This function is meant to be used by the pluggable transport proxy + * spawning code, please make sure that it fits your purposes before + * using it. */ +char * +get_first_listener_addrport_string(int listener_type) +{ + static const char *ipv4_localhost = "127.0.0.1"; + static const char *ipv6_localhost = "[::1]"; + const char *address; + uint16_t port; + char *string = NULL; + + if (!configured_ports) + return NULL; + + SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) { + if (cfg->no_listen) + continue; + + if (cfg->type == listener_type && + tor_addr_family(&cfg->addr) != AF_UNSPEC) { + + /* We found the first listener of the type we are interested in! */ + + /* If a listener is listening on INADDR_ANY, assume that it's + also listening on 127.0.0.1, and point the transport proxy + there: */ + if (tor_addr_is_null(&cfg->addr)) + address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost; + else + address = fmt_and_decorate_addr(&cfg->addr); + + /* If a listener is configured with port 'auto', we are forced + to iterate all listener connections and find out in which + port it ended up listening: */ + if (cfg->port == CFG_AUTO_PORT) { + port = router_get_active_listener_port_by_type(listener_type); + if (!port) + return NULL; + } else { + port = cfg->port; + } + + tor_asprintf(&string, "%s:%u", address, port); + + return string; + } + + } SMARTLIST_FOREACH_END(cfg); + + return NULL; +} + /** Return the first advertised port of type <b>listener_type</b> in <b>address_family</b>. */ int diff --git a/src/or/config.h b/src/or/config.h index 0f7c618861..a68a3e3113 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -22,6 +22,7 @@ const char *safe_str(const char *address); const char *escaped_safe_str_client(const char *address); const char *escaped_safe_str(const char *address); const char *get_version(void); +const char *get_short_version(void); int config_get_lines(const char *string, config_line_t **result, int extended); void config_free_lines(config_line_t *front); @@ -72,6 +73,8 @@ int get_first_advertised_port_by_type_af(int listener_type, #define get_primary_dir_port() \ (get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET)) +char *get_first_listener_addrport_string(int listener_type); + int options_need_geoip_info(const or_options_t *options, const char **reason_out); diff --git a/src/or/connection.c b/src/or/connection.c index d379533494..0c970cc3b4 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -778,7 +778,8 @@ create_unix_sockaddr(const char *listenaddress, char **readable_address, "Unix domain sockets not supported, yet we tried to create one."); *len_out = 0; tor_assert(0); -}; + return NULL; +} #endif /* HAVE_SYS_UN_H */ /** Warn that an accept or a connect has failed because we're running up diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 03558e557c..ca4bf3ffe4 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -2000,20 +2000,35 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, if (options->ClientRejectInternalAddresses && !conn->use_begindir && !conn->chosen_exit_name && !circ) { tor_addr_t addr; - if (tor_addr_parse(&addr, socks->address) >= 0 && - tor_addr_is_internal(&addr, 0)) { + if (tor_addr_hostname_is_local(socks->address) || + (tor_addr_parse(&addr, socks->address) >= 0 && + tor_addr_is_internal(&addr, 0))) { /* If this is an explicit private address with no chosen exit node, * then we really don't want to try to connect to it. That's * probably an error. */ if (conn->is_transparent_ap) { - log_warn(LD_NET, - "Rejecting request for anonymous connection to private " - "address %s on a TransPort or NATDPort. Possible loop " - "in your NAT rules?", safe_str_client(socks->address)); +#define WARN_INTERVAL_LOOP 300 + static ratelim_t loop_warn_limit = RATELIM_INIT(WARN_INTERVAL_LOOP); + char *m; + if ((m = rate_limit_log(&loop_warn_limit, approx_time()))) { + log_warn(LD_NET, + "Rejecting request for anonymous connection to private " + "address %s on a TransPort or NATDPort. Possible loop " + "in your NAT rules?%s", safe_str_client(socks->address), + m); + tor_free(m); + } } else { - log_warn(LD_NET, - "Rejecting SOCKS request for anonymous connection to " - "private address %s", safe_str_client(socks->address)); +#define WARN_INTERVAL_PRIV 300 + static ratelim_t priv_warn_limit = RATELIM_INIT(WARN_INTERVAL_PRIV); + char *m; + if ((m = rate_limit_log(&priv_warn_limit, approx_time()))) { + log_warn(LD_NET, + "Rejecting SOCKS request for anonymous connection to " + "private address %s.%s", + safe_str_client(socks->address),m); + tor_free(m); + } } connection_mark_unattached_ap(conn, END_STREAM_REASON_PRIVATE_ADDR); return -1; @@ -2304,6 +2319,11 @@ connection_ap_handshake_process_socks(entry_connection_t *conn) connection_write_to_buf((const char*)socks->reply, socks->replylen, base_conn); socks->replylen = 0; + if (sockshere == -1) { + /* An invalid request just got a reply, no additional + * one is necessary. */ + socks->has_finished = 1; + } } if (sockshere == 0) { @@ -2745,7 +2765,7 @@ tell_controller_about_resolved_result(entry_connection_t *conn, answer_type == RESOLVED_TYPE_HOSTNAME)) { return; /* we already told the controller. */ } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) { - char *cp = tor_dup_ip(get_uint32(answer)); + char *cp = tor_dup_ip(ntohl(get_uint32(answer))); control_event_address_mapped(conn->socks_request->address, cp, expires, NULL); tor_free(cp); diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 47c9c45b1a..f6db4b4ef9 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -79,7 +79,8 @@ int addressmap_have_mapping(const char *address, int update_timeout); void addressmap_register(const char *address, char *new_address, time_t expires, addressmap_entry_source_t source, - int address_wildcard, int new_address_wildcard); + const int address_wildcard, + const int new_address_wildcard); int parse_virtual_addr_network(const char *val, int validate_only, char **msg); int client_dns_incr_failures(const char *address); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 0d3f9d87f2..81df70eb37 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1051,8 +1051,27 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, conn->_base.proxy_state = PROXY_INFANT; } } else { - log_warn(LD_GENERAL, "Tried to connect through proxy, but proxy address " - "could not be found."); + /* get_proxy_addrport() might fail if we have a Bridge line that + references a transport, but no ClientTransportPlugin lines + defining its transport proxy. If this is the case, let's try to + output a useful log message to the user. */ + const char *transport_name = + find_transport_name_by_bridge_addrport(&TO_CONN(conn)->addr, + TO_CONN(conn)->port); + + if (transport_name) { + log_warn(LD_GENERAL, "We were supposed to connect to bridge '%s:%u' " + "using pluggable transport '%s', but it seems that we can't " + "find a pluggable transport proxy supporting '%s'. Please make " + "sure that your configuration file is valid.", + fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port, + transport_name, transport_name); + } else { + log_warn(LD_GENERAL, "Tried to connect to '%s:%u' through a proxy, but " + "the proxy address could not be found.", + fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port); + } + connection_free(TO_CONN(conn)); return NULL; } diff --git a/src/or/control.c b/src/or/control.c index 397bb53ab4..ec018ffc23 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2530,6 +2530,10 @@ handle_control_setcircuitpurpose(control_connection_t *conn, { const char *purp = find_element_starting_with(args,1,"PURPOSE="); + if (!purp) { + connection_write_str_to_buf("552 No purpose given\r\n", conn); + goto done; + } new_purpose = circuit_purpose_from_string(purp); if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) { connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp); @@ -2986,13 +2990,14 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len, cp += strlen("SAFECOOKIE"); } else { connection_write_str_to_buf("513 AUTHCHALLENGE only supports SAFECOOKIE " - "authentication", conn); + "authentication\r\n", conn); connection_mark_for_close(TO_CONN(conn)); return -1; } if (!authentication_cookie_is_set) { - connection_write_str_to_buf("515 Cookie authentication is disabled", conn); + connection_write_str_to_buf("515 Cookie authentication is disabled\r\n", + conn); connection_mark_for_close(TO_CONN(conn)); return -1; } @@ -3003,7 +3008,7 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len, decode_escaped_string(cp, len - (cp - body), &client_nonce, &client_nonce_len); if (newcp == NULL) { - connection_write_str_to_buf("513 Invalid quoted client nonce", + connection_write_str_to_buf("513 Invalid quoted client nonce\r\n", conn); connection_mark_for_close(TO_CONN(conn)); return -1; @@ -3017,7 +3022,7 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len, if (base16_decode(client_nonce, client_nonce_len, cp, client_nonce_encoded_len) < 0) { - connection_write_str_to_buf("513 Invalid base16 client nonce", + connection_write_str_to_buf("513 Invalid base16 client nonce\r\n", conn); connection_mark_for_close(TO_CONN(conn)); tor_free(client_nonce); @@ -3030,7 +3035,7 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len, cp += strspn(cp, " \t\n\r"); if (*cp != '\0' || cp != body + len) { - connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command", + connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command\r\n", conn); connection_mark_for_close(TO_CONN(conn)); tor_free(client_nonce); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 1c2579865f..1220c32a50 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1252,6 +1252,15 @@ directory_caches_v2_dir_info(const or_options_t *options) return options->DirPort != NULL; } +/** Return true iff we want to fetch and keep certificates for authorities + * that we don't acknowledge as aurthorities ourself. + */ +int +directory_caches_unknown_auth_certs(const or_options_t *options) +{ + return options->DirPort || options->BridgeRelay; +} + /** Return 1 if we want to keep descriptors, networkstatuses, etc around * and we're willing to serve them to others. Else return 0. */ diff --git a/src/or/dirserv.h b/src/or/dirserv.h index fc48e489e8..3ff08157e0 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -76,6 +76,7 @@ int directory_fetches_dir_info_early(const or_options_t *options); int directory_fetches_dir_info_later(const or_options_t *options); int directory_caches_v2_dir_info(const or_options_t *options); #define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o) +int directory_caches_unknown_auth_certs(const or_options_t *options); int directory_caches_dir_info(const or_options_t *options); int directory_permits_begindir_requests(const or_options_t *options); int directory_permits_controller_requests(const or_options_t *options); diff --git a/src/or/dirvote.c b/src/or/dirvote.c index cddb658244..20dc8c2649 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -668,10 +668,10 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities) const char *next_param; int ok=0; eq = strchr(param, '='); - tor_assert(i<n_votes); + tor_assert(i<n_votes); /* Make sure we prevented vote-stuffing. */ vals[i++] = (int32_t) tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL); - tor_assert(ok); + tor_assert(ok); /* Already checked these when parsing. */ if (param_sl_idx+1 == smartlist_len(param_list)) next_param = NULL; @@ -1005,7 +1005,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G, /* We cast down the weights to 32 bit ints on the assumption that * weight_scale is ~= 10000. We need to ensure a rogue authority * doesn't break this assumption to rig our weights */ - tor_assert(0 < weight_scale && weight_scale < INT32_MAX); + tor_assert(0 < weight_scale && weight_scale <= INT32_MAX); /* * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine @@ -1233,7 +1233,7 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M, /* We cast down the weights to 32 bit ints on the assumption that * weight_scale is ~= 10000. We need to ensure a rogue authority * doesn't break this assumption to rig our weights */ - tor_assert(0 < weight_scale && weight_scale < INT32_MAX); + tor_assert(0 < weight_scale && weight_scale <= INT32_MAX); if (Wgg < 0 || Wgg > weight_scale) { log_warn(LD_DIR, "Bw %s: Wgg="I64_FORMAT"! G="I64_FORMAT @@ -2019,7 +2019,7 @@ networkstatus_compute_consensus(smartlist_t *votes, int ok=0; char *eq = strchr(bw_weight_param, '='); if (eq) { - weight_scale = tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, + weight_scale = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIR, "Bad element '%s' in bw weight param", diff --git a/src/or/dns.c b/src/or/dns.c index 2b7d3e3506..b349f02f68 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -1389,7 +1389,7 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, static int launch_resolve(edge_connection_t *exitconn) { - char *addr = tor_strdup(exitconn->_base.address); + char *addr; struct evdns_request *req = NULL; tor_addr_t a; int r; @@ -1408,6 +1408,8 @@ launch_resolve(edge_connection_t *exitconn) } } + addr = tor_strdup(exitconn->_base.address); + r = tor_addr_parse_PTR_name( &a, exitconn->_base.address, AF_UNSPEC, 0); diff --git a/src/or/main.c b/src/or/main.c index 9022f2eb87..8308b3a238 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1773,8 +1773,16 @@ do_hup(void) } options = get_options(); /* they have changed now */ } else { + char *msg = NULL; log_notice(LD_GENERAL, "Not reloading config file: the controller told " "us not to."); + /* Make stuff get rescanned, reloaded, etc. */ + if (set_options((or_options_t*)options, &msg) < 0) { + if (!msg) + msg = tor_strdup("Unknown error"); + log_warn(LD_GENERAL, "Unable to re-set previous options: %s", msg); + tor_free(msg); + } } if (authdir_mode_handles_descs(options, -1)) { /* reload the approved-routers file */ diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 910b99c5c0..3646ee6844 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1463,8 +1463,10 @@ networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f) return current_ns_consensus; else if (f == FLAV_MICRODESC) return current_md_consensus; - else + else { tor_assert(0); + return NULL; + } } /** Return the most recent consensus that we have downloaded, or NULL if it is diff --git a/src/or/or.h b/src/or/or.h index b8fee649ea..76681c9eea 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -23,11 +23,8 @@ #endif #ifdef _WIN32 -#ifndef WIN32_WINNT -#define WIN32_WINNT 0x400 -#endif #ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x0501 #endif #define WIN32_LEAN_AND_MEAN #endif diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 2742c351b3..894bbb3c54 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -276,13 +276,6 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, or_circuit_t *rend_circ; char hexid[9]; int reason = END_CIRC_REASON_INTERNAL; - base16_encode(hexid,9,(char*)request,request_len<4?request_len:4); - - if (request_len>=4) { - log_info(LD_REND, - "Got request for rendezvous from circuit %d to cookie %s.", - circ->p_circ_id, hexid); - } if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) { log_info(LD_REND, @@ -300,6 +293,12 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, goto err; } + base16_encode(hexid, sizeof(hexid), (const char*)request, 4); + + log_info(LD_REND, + "Got request for rendezvous from circuit %d to cookie %s.", + circ->p_circ_id, hexid); + rend_circ = circuit_get_rendezvous((char*)request); if (!rend_circ) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, diff --git a/src/or/rephist.c b/src/or/rephist.c index 0cd60eeb83..0727c6851a 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1868,6 +1868,26 @@ rep_hist_get_predicted_ports(time_t now) return out; } +/** + * Take a list of uint16_t *, and remove every port in the list from the + * current list of predicted ports. + */ +void +rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports) +{ + /* Let's do this on O(N), not O(N^2). */ + bitarray_t *remove_ports = bitarray_init_zero(UINT16_MAX); + SMARTLIST_FOREACH(rmv_ports, const uint16_t *, p, + bitarray_set(remove_ports, *p)); + SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) { + if (bitarray_is_set(remove_ports, pp->port)) { + tor_free(pp); + SMARTLIST_DEL_CURRENT(predicted_ports_list, pp); + } + } SMARTLIST_FOREACH_END(pp); + bitarray_free(remove_ports); +} + /** The user asked us to do a resolve. Rather than keeping track of * timings and such of resolves, we fake it for now by treating * it the same way as a connection to port 80. This way we will continue @@ -2650,24 +2670,30 @@ rep_hist_format_desc_stats(time_t now) const char *key; void *val; unsigned size; - int *vals; + int *vals, max = 0, q3 = 0, md = 0, q1 = 0, min = 0; int n = 0; if (!start_of_served_descs_stats_interval) return NULL; - size = digestmap_size(served_descs); - if (size == 0) - return NULL; - vals = tor_malloc(size * sizeof(int)); - - for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); - iter = digestmap_iter_next(served_descs, iter) ) { - uintptr_t count; - digestmap_iter_get(iter, &key, &val); - count = (uintptr_t)val; - vals[n++] = (int)count; - (void)key; + size = digestmap_size(served_descs); + if (size > 0) { + vals = tor_malloc(size * sizeof(int)); + for (iter = digestmap_iter_init(served_descs); + !digestmap_iter_done(iter); + iter = digestmap_iter_next(served_descs, iter)) { + uintptr_t count; + digestmap_iter_get(iter, &key, &val); + count = (uintptr_t)val; + vals[n++] = (int)count; + (void)key; + } + max = find_nth_int(vals, size, size-1); + q3 = find_nth_int(vals, size, (3*size-1)/4); + md = find_nth_int(vals, size, (size-1)/2); + q1 = find_nth_int(vals, size, (size-1)/4); + min = find_nth_int(vals, size, 0); + tor_free(vals); } format_iso_time(t, now); @@ -2678,14 +2704,8 @@ rep_hist_format_desc_stats(time_t now) t, (unsigned) (now - start_of_served_descs_stats_interval), total_descriptor_downloads, - size, - find_nth_int(vals, size, size-1), - find_nth_int(vals, size, (3*size-1)/4), - find_nth_int(vals, size, (size-1)/2), - find_nth_int(vals, size, (size-1)/4), - find_nth_int(vals, size, 0)); - - tor_free(vals); + size, max, q3, md, q1, min); + return result; } @@ -2705,6 +2725,7 @@ rep_hist_desc_stats_write(time_t now) return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL; str = rep_hist_format_desc_stats(now); + tor_assert(str != NULL); statsdir = get_datadir_fname("stats"); if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { diff --git a/src/or/rephist.h b/src/or/rephist.h index 0a3e46ae1a..860713c350 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -34,7 +34,7 @@ int rep_hist_load_state(or_state_t *state, char **err); void rep_history_clean(time_t before); void rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr, - uint16_t at_port, time_t when); + const uint16_t at_port, time_t when); void rep_hist_note_router_unreachable(const char *id, time_t when); int rep_hist_record_mtbf_data(time_t now, int missing_means_down); int rep_hist_load_mtbf_data(time_t now); @@ -49,6 +49,7 @@ const char *rep_hist_get_router_stability_doc(time_t now); void rep_hist_note_used_port(time_t now, uint16_t port); smartlist_t *rep_hist_get_predicted_ports(time_t now); +void rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports); void rep_hist_note_used_resolve(time_t now); void rep_hist_note_used_internal(time_t now, int need_uptime, int need_capacity); diff --git a/src/or/router.c b/src/or/router.c index 4cdfd02e56..34e231ae7c 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1228,6 +1228,22 @@ consider_publishable_server(int force) } } +/** Return the port of the first active listener of type + * <b>listener_type</b>. */ +/** XXX not a very good interface. it's not reliable when there are + multiple listeners. */ +uint16_t +router_get_active_listener_port_by_type(int listener_type) +{ + /* Iterate all connections, find one of the right kind and return + the port. Not very sophisticated or fast, but effective. */ + const connection_t *c = connection_get_by_type(listener_type); + if (c) + return c->port; + + return 0; +} + /** Return the port that we should advertise as our ORPort; this is either * the one configured in the ORPort option, or the one we actually bound to * if ORPort is "auto". @@ -1238,12 +1254,11 @@ router_get_advertised_or_port(const or_options_t *options) int port = get_primary_or_port(); (void)options; - if (port == CFG_AUTO_PORT) { - connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER); - if (c) - return c->port; - return 0; - } + /* If the port is in 'auto' mode, we have to use + router_get_listener_port_by_type(). */ + if (port == CFG_AUTO_PORT) + return router_get_active_listener_port_by_type(CONN_TYPE_OR_LISTENER); + return port; } @@ -1260,12 +1275,10 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) if (!dirport_configured) return dirport; - if (dirport_configured == CFG_AUTO_PORT) { - connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER); - if (c) - return c->port; - return 0; - } + + if (dirport_configured == CFG_AUTO_PORT) + return router_get_active_listener_port_by_type(CONN_TYPE_DIR_LISTENER); + return dirport_configured; } @@ -1530,10 +1543,18 @@ router_rebuild_descriptor(int force) if (p->type == CONN_TYPE_OR_LISTENER && ! p->no_advertise && ! p->ipv4_only && - tor_addr_family(&p->addr) == AF_INET6 && - ! tor_addr_is_internal(&p->addr, 1)) { - ipv6_orport = p; - break; + tor_addr_family(&p->addr) == AF_INET6) { + if (! tor_addr_is_internal(&p->addr, 0)) { + ipv6_orport = p; + break; + } else { + char addrbuf[TOR_ADDR_BUF_LEN]; + log_warn(LD_CONFIG, + "Unable to use configured IPv6 address \"%s\" in a " + "descriptor. Skipping it. " + "Try specifying a globally reachable address explicitly. ", + tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1)); + } } } SMARTLIST_FOREACH_END(p); if (ipv6_orport) { @@ -1647,6 +1668,7 @@ router_rebuild_descriptor(int force) ei->cache_info.signed_descriptor_len = strlen(ei->cache_info.signed_descriptor_body); router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body, + ei->cache_info.signed_descriptor_len, ei->cache_info.signed_descriptor_digest); } @@ -1672,12 +1694,15 @@ router_rebuild_descriptor(int force) ri->purpose = options->BridgeRelay ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL; - ri->cache_info.send_unencrypted = 1; - /* Let bridges serve their own descriptors unencrypted, so they can - * pass reachability testing. (If they want to be harder to notice, - * they can always leave the DirPort off). */ - if (ei && !options->BridgeRelay) - ei->cache_info.send_unencrypted = 1; + if (options->BridgeRelay) { + /* Bridges shouldn't be able to send their descriptors unencrypted, + anyway, since they don't have a DirPort, and always connect to the + bridge authority anonymously. But just in case they somehow think of + sending them on an unencrypted connection, don't allow them to try. */ + ri->cache_info.send_unencrypted = ei->cache_info.send_unencrypted = 0; + } else { + ri->cache_info.send_unencrypted = ei->cache_info.send_unencrypted = 1; + } router_get_router_hash(ri->cache_info.signed_descriptor_body, strlen(ri->cache_info.signed_descriptor_body), @@ -1927,7 +1952,7 @@ router_guess_address_from_dir_headers(uint32_t *guess) void get_platform_str(char *platform, size_t len) { - tor_snprintf(platform, len, "Tor %s on %s", get_version(), get_uname()); + tor_snprintf(platform, len, "Tor %s on %s", get_short_version(), get_uname()); } /* XXX need to audit this thing and count fenceposts. maybe @@ -2351,7 +2376,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, } memset(sig, 0, sizeof(sig)); - if (router_get_extrainfo_hash(s, digest) < 0 || + if (router_get_extrainfo_hash(s, strlen(s), digest) < 0 || router_append_dirobj_signature(sig, sizeof(sig), digest, DIGEST_LEN, ident_key) < 0) { log_warn(LD_BUG, "Could not append signature to extra-info " diff --git a/src/or/router.h b/src/or/router.h index fb914349f3..294736e70c 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -53,6 +53,7 @@ int authdir_mode_publishes_statuses(const or_options_t *options); int authdir_mode_tests_reachability(const or_options_t *options); int authdir_mode_bridge(const or_options_t *options); +uint16_t router_get_active_listener_port_by_type(int listener_type); uint16_t router_get_advertised_or_port(const or_options_t *options); uint16_t router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index a64b93f3a9..0abc2e9bcf 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -229,7 +229,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, "signing key %s", from_store ? "cached" : "downloaded", ds->nickname, hex_str(cert->signing_key_digest,DIGEST_LEN)); } else { - int adding = directory_caches_dir_info(get_options()); + int adding = directory_caches_unknown_auth_certs(get_options()); log_info(LD_DIR, "%s %s certificate for unrecognized directory " "authority with signing key %s", adding ? "Adding" : "Not adding", @@ -480,7 +480,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) smartlist_t *missing_digests; char *resource = NULL; cert_list_t *cl; - const int cache = directory_caches_dir_info(get_options()); + const int cache = directory_caches_unknown_auth_certs(get_options()); if (should_delay_dir_fetches(get_options())) return; @@ -2838,6 +2838,13 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) ri->cache_info.signed_descriptor_digest, &(ri->cache_info)); if (sd_old) { + int idx = sd_old->routerlist_index; + sd_old->routerlist_index = -1; + smartlist_del(rl->old_routers, idx); + if (idx < smartlist_len(rl->old_routers)) { + signed_descriptor_t *d = smartlist_get(rl->old_routers, idx); + d->routerlist_index = idx; + } rl->desc_store.bytes_dropped += sd_old->signed_descriptor_len; sdmap_remove(rl->desc_by_eid_map, sd_old->extra_info_digest); signed_descriptor_free(sd_old); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 7cc8b965e6..781c57897d 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -682,12 +682,12 @@ router_get_networkstatus_v3_hash(const char *s, char *digest, ' ', alg); } -/** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo - * string in <b>s</b>. Return 0 on success, -1 on failure. */ +/** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte + * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */ int -router_get_extrainfo_hash(const char *s, char *digest) +router_get_extrainfo_hash(const char *s, size_t s_len, char *digest) { - return router_get_hash_impl(s, strlen(s), digest, "extra-info", + return router_get_hash_impl(s, s_len, digest, "extra-info", "\nrouter-signature",'\n', DIGEST_SHA1); } @@ -1643,7 +1643,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n') --end; - if (router_get_extrainfo_hash(s, digest) < 0) { + if (router_get_extrainfo_hash(s, end-s, digest) < 0) { log_warn(LD_DIR, "Couldn't compute router hash."); goto err; } @@ -2821,6 +2821,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, int i, inorder, n_signatures = 0; memarea_t *area = NULL, *rs_area = NULL; consensus_flavor_t flav = FLAV_NS; + char *last_kwd=NULL; tor_assert(s); @@ -2977,15 +2978,18 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, tok = find_opt_by_keyword(tokens, K_PARAMS); if (tok) { + int any_dups = 0; inorder = 1; ns->net_params = smartlist_new(); for (i = 0; i < tok->n_args; ++i) { int ok=0; char *eq = strchr(tok->args[i], '='); + size_t eq_pos; if (!eq) { log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i])); goto err; } + eq_pos = eq-tok->args[i]; tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i])); @@ -2995,12 +2999,24 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]); inorder = 0; } + if (last_kwd && eq_pos == strlen(last_kwd) && + fast_memeq(last_kwd, tok->args[i], eq_pos)) { + log_warn(LD_DIR, "Duplicate value for %s parameter", + escaped(tok->args[i])); + any_dups = 1; + } + tor_free(last_kwd); + last_kwd = tor_strndup(tok->args[i], eq_pos); smartlist_add(ns->net_params, tor_strdup(tok->args[i])); } if (!inorder) { log_warn(LD_DIR, "params not in order"); goto err; } + if (any_dups) { + log_warn(LD_DIR, "Duplicate in parameters"); + goto err; + } } ns->voters = smartlist_new(); @@ -3339,6 +3355,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } if (rs_area) memarea_drop_all(rs_area); + tor_free(last_kwd); return ns; } diff --git a/src/or/routerparse.h b/src/or/routerparse.h index b274d2196c..6486a09c73 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -19,7 +19,7 @@ int router_get_networkstatus_v2_hash(const char *s, char *digest); int router_get_networkstatus_v3_hash(const char *s, char *digest, digest_algorithm_t algorithm); int router_get_networkstatus_v3_hashes(const char *s, digests_t *digests); -int router_get_extrainfo_hash(const char *s, char *digest); +int router_get_extrainfo_hash(const char *s, size_t s_len, char *digest); #define DIROBJ_MAX_SIG_LEN 256 int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, diff --git a/src/or/transports.c b/src/or/transports.c index 564603e1fe..a20decfc03 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -119,10 +119,6 @@ static INLINE void free_execve_args(char **arg); #define PROTO_CMETHODS_DONE "CMETHODS DONE" #define PROTO_SMETHODS_DONE "SMETHODS DONE" -/* The smallest valid managed proxy protocol line that can - appear. It's the size of "VERSION 1" */ -#define SMALLEST_MANAGED_LINE_SIZE 9 - /** Number of environment variables for managed proxy clients/servers. */ #define ENVIRON_SIZE_CLIENT 3 #define ENVIRON_SIZE_SERVER 7 /* XXX known to be too high, but that's ok */ @@ -340,11 +336,12 @@ pt_configure_remaining_proxies(void) /* This proxy is marked by a SIGHUP. Check whether we need to restart it. */ if (proxy_needs_restart(mp)) { - log_info(LD_GENERAL, "Preparing managed proxy for restart."); + log_info(LD_GENERAL, "Preparing managed proxy '%s' for restart.", + mp->argv[0]); proxy_prepare_for_restart(mp); } else { /* it doesn't need to be restarted. */ - log_info(LD_GENERAL, "Nothing changed for managed proxy after HUP: " - "not restarting."); + log_info(LD_GENERAL, "Nothing changed for managed proxy '%s' after " + "HUP: not restarting.", mp->argv[0]); } continue; @@ -387,7 +384,8 @@ configure_proxy(managed_proxy_t *mp) pos = tor_read_all_handle(tor_process_get_stdout_pipe(mp->process_handle), stdout_buf, sizeof(stdout_buf) - 1, NULL); if (pos < 0) { - log_notice(LD_GENERAL, "Failed to read data from managed proxy"); + log_notice(LD_GENERAL, "Failed to read data from managed proxy '%s'.", + mp->argv[0]); mp->conf_state = PT_PROTO_BROKEN; goto done; } @@ -449,11 +447,13 @@ configure_proxy(managed_proxy_t *mp) } else if (r == IO_STREAM_EAGAIN) { /* check back later */ return; } else if (r == IO_STREAM_CLOSED || r == IO_STREAM_TERM) { /* snap! */ - log_notice(LD_GENERAL, "Managed proxy stream closed. " - "Most probably application stopped running"); + log_warn(LD_GENERAL, "Our communication channel with the managed proxy " + "'%s' closed. Most probably application stopped running.", + mp->argv[0]); mp->conf_state = PT_PROTO_BROKEN; } else { /* unknown stream status */ - log_notice(LD_GENERAL, "Unknown stream status while configuring proxy."); + log_warn(LD_BUG, "Unknown stream status '%d' while configuring managed " + "proxy '%s'.", (int)r, mp->argv[0]); } /* if the proxy finished configuring, exit the loop. */ @@ -586,8 +586,8 @@ handle_finished_proxy(managed_proxy_t *mp) case PT_PROTO_ACCEPTING_METHODS: case PT_PROTO_COMPLETED: default: - log_warn(LD_CONFIG, "Unexpected managed proxy state in " - "handle_finished_proxy()."); + log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.", + (int)mp->conf_state, mp->argv[0]); tor_assert(0); } @@ -612,11 +612,13 @@ handle_methods_done(const managed_proxy_t *mp) tor_assert(mp->transports); if (smartlist_len(mp->transports) == 0) - log_notice(LD_GENERAL, "Proxy was spawned successfully, " - "but it didn't laucn any pluggable transport listeners!"); + log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, " + "but it didn't launch any pluggable transport listeners!", + mp->argv[0]); - log_info(LD_CONFIG, "%s managed proxy configuration completed!", - mp->is_server ? "Server" : "Client"); + log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!", + mp->is_server ? "Server" : "Client", + mp->argv[0]); } /** Handle a configuration protocol <b>line</b> received from a @@ -624,13 +626,8 @@ handle_methods_done(const managed_proxy_t *mp) void handle_proxy_line(const char *line, managed_proxy_t *mp) { - log_debug(LD_GENERAL, "Got a line from managed proxy: %s", line); - - if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) { - log_warn(LD_GENERAL, "Managed proxy configuration line is too small. " - "Discarding"); - goto err; - } + log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)", + mp->argv[0], line); if (!strcmpstart(line, PROTO_ENV_ERROR)) { if (mp->conf_state != PT_PROTO_LAUNCHED) @@ -705,12 +702,13 @@ handle_proxy_line(const char *line, managed_proxy_t *mp) return; } - log_warn(LD_CONFIG, "Unknown line received by managed proxy. (%s)", line); + log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line); + return; err: mp->conf_state = PT_PROTO_BROKEN; log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol" - " and will be destroyed.", mp->argv ? mp->argv[0] : ""); + " and will be destroyed.", mp->argv[0]); } /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */ @@ -957,8 +955,6 @@ get_bindaddr_for_server_proxy(const managed_proxy_t *mp) static process_environment_t * create_managed_proxy_environment(const managed_proxy_t *mp) { - const or_options_t *options = get_options(); - /* Environment variables to be added to or set in mp's environment. */ smartlist_t *envs = smartlist_new(); /* XXXX The next time someone touches this code, shorten the name of @@ -993,8 +989,12 @@ create_managed_proxy_environment(const managed_proxy_t *mp) } if (mp->is_server) { - smartlist_add_asprintf(envs, "TOR_PT_ORPORT=127.0.0.1:%s", - options->ORPort->value); + { + char *orport_tmp = + get_first_listener_addrport_string(CONN_TYPE_OR_LISTENER); + smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp); + tor_free(orport_tmp); + } { char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp); @@ -1027,8 +1027,11 @@ create_managed_proxy_environment(const managed_proxy_t *mp) } /** Create and return a new managed proxy for <b>transport</b> using - * <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server - * managed proxy. */ + * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If + * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of + * <b>proxy_argv</b>. + * + * Requires that proxy_argv have at least one element. */ static managed_proxy_t * managed_proxy_create(const smartlist_t *transport_list, char **proxy_argv, int is_server) @@ -1056,7 +1059,13 @@ managed_proxy_create(const smartlist_t *transport_list, /** Register proxy with <b>proxy_argv</b>, supporting transports in * <b>transport_list</b>, to the managed proxy subsystem. - * If <b>is_server</b> is true, then the proxy is a server proxy. */ + * If <b>is_server</b> is true, then the proxy is a server proxy. + * + * Takes ownership of proxy_argv. + * + * Requires that proxy_argv be a NULL-terminated array of command-line + * elements, containing at least one element. + **/ void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv, int is_server) @@ -1064,6 +1073,10 @@ pt_kickstart_proxy(const smartlist_t *transport_list, managed_proxy_t *mp=NULL; transport_t *old_transport = NULL; + if (!proxy_argv || !proxy_argv[0]) { + return; + } + mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server); if (!mp) { /* we haven't seen this proxy before */ |