diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-09-05 14:34:29 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-09-05 14:34:29 -0400 |
commit | 73b0e2e6fd02140d349ebc6d4ae44c6a28a0f39c (patch) | |
tree | 4520ec8590003e12db93503b7b5973938b63f2a1 /src/or | |
parent | c0b9f594b65f410cf219673d53226ed4eeeedc19 (diff) | |
parent | ad9190404b1cbba3f7e17f8db20034e986093f21 (diff) | |
download | tor-73b0e2e6fd02140d349ebc6d4ae44c6a28a0f39c.tar.gz tor-73b0e2e6fd02140d349ebc6d4ae44c6a28a0f39c.zip |
Merge branch 'http_tunnel_squashed'
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/config.c | 15 | ||||
-rw-r--r-- | src/or/connection.c | 8 | ||||
-rw-r--r-- | src/or/connection_edge.c | 125 | ||||
-rw-r--r-- | src/or/connection_edge.h | 9 | ||||
-rw-r--r-- | src/or/directory.c | 38 | ||||
-rw-r--r-- | src/or/directory.h | 3 | ||||
-rw-r--r-- | src/or/networkstatus.c | 3 | ||||
-rw-r--r-- | src/or/or.h | 18 | ||||
-rw-r--r-- | src/or/reasons.c | 52 | ||||
-rw-r--r-- | src/or/reasons.h | 1 | ||||
-rw-r--r-- | src/or/relay.c | 3 |
11 files changed, 250 insertions, 25 deletions
diff --git a/src/or/config.c b/src/or/config.c index ff70a4465e..eb89d6f5ee 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -372,6 +372,7 @@ static config_var_t option_vars_[] = { V(HTTPProxyAuthenticator, STRING, NULL), V(HTTPSProxy, STRING, NULL), V(HTTPSProxyAuthenticator, STRING, NULL), + VPORT(HTTPTunnelPort), V(IPv6Exit, BOOL, "0"), VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL), V(ServerTransportListenAddr, LINELIST, NULL), @@ -2915,7 +2916,8 @@ options_validate_single_onion(or_options_t *options, char **msg) const int client_port_set = (options->SocksPort_set || options->TransPort_set || options->NATDPort_set || - options->DNSPort_set); + options->DNSPort_set || + options->HTTPTunnelPort_set); if (rend_service_non_anonymous_mode_enabled(options) && client_port_set && !options->Tor2webMode) { REJECT("HiddenServiceNonAnonymousMode is incompatible with using Tor as " @@ -7000,6 +7002,15 @@ parse_ports(or_options_t *options, int validate_only, *msg = tor_strdup("Invalid NatdPort configuration"); goto err; } + if (parse_port_config(ports, + options->HTTPTunnelPort_lines, + "HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER, + "127.0.0.1", 0, + ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL) + | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) { + *msg = tor_strdup("Invalid HTTPTunnelPort configuration"); + goto err; + } { unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS | CL_PORT_WARN_NONLOCAL; @@ -7077,6 +7088,8 @@ parse_ports(or_options_t *options, int validate_only, !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1); options->NATDPort_set = !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1); + options->HTTPTunnelPort_set = + !! count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1); /* Use options->ControlSocket to test if a control socket is set */ options->ControlPort_set = !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0); diff --git a/src/or/connection.c b/src/or/connection.c index 86ea999be0..e2392b52e3 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -162,7 +162,8 @@ static smartlist_t *outgoing_addrs = NULL; case CONN_TYPE_CONTROL_LISTENER: \ case CONN_TYPE_AP_TRANS_LISTENER: \ case CONN_TYPE_AP_NATD_LISTENER: \ - case CONN_TYPE_AP_DNS_LISTENER + case CONN_TYPE_AP_DNS_LISTENER: \ + case CONN_TYPE_AP_HTTP_CONNECT_LISTENER /**************************************************************/ @@ -189,6 +190,7 @@ conn_type_to_string(int type) case CONN_TYPE_CONTROL: return "Control"; case CONN_TYPE_EXT_OR: return "Extended OR"; case CONN_TYPE_EXT_OR_LISTENER: return "Extended OR listener"; + case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: return "HTTP tunnel listener"; default: log_warn(LD_BUG, "unknown connection type %d", type); tor_snprintf(buf, sizeof(buf), "unknown [%d]", type); @@ -1706,6 +1708,8 @@ connection_init_accepted_conn(connection_t *conn, TO_ENTRY_CONN(conn)->is_transparent_ap = 1; conn->state = AP_CONN_STATE_NATD_WAIT; break; + case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: + conn->state = AP_CONN_STATE_HTTP_CONNECT_WAIT; } break; case CONN_TYPE_DIR: @@ -3398,6 +3402,7 @@ connection_handle_read_impl(connection_t *conn) case CONN_TYPE_AP_LISTENER: case CONN_TYPE_AP_TRANS_LISTENER: case CONN_TYPE_AP_NATD_LISTENER: + case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: return connection_handle_listener_read(conn, CONN_TYPE_AP); case CONN_TYPE_DIR_LISTENER: return connection_handle_listener_read(conn, CONN_TYPE_DIR); @@ -4313,6 +4318,7 @@ connection_is_listener(connection_t *conn) conn->type == CONN_TYPE_AP_TRANS_LISTENER || conn->type == CONN_TYPE_AP_DNS_LISTENER || conn->type == CONN_TYPE_AP_NATD_LISTENER || + conn->type == CONN_TYPE_AP_HTTP_CONNECT_LISTENER || conn->type == CONN_TYPE_DIR_LISTENER || conn->type == CONN_TYPE_CONTROL_LISTENER) return 1; diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 9f47f41179..f6c5895396 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -242,6 +242,11 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) return -1; } return 0; + case AP_CONN_STATE_HTTP_CONNECT_WAIT: + if (connection_ap_process_http_connect(EDGE_TO_ENTRY_CONN(conn)) < 0) { + return -1; + } + return 0; case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: if (connection_edge_package_raw_inbuf(conn, package_partial, NULL) < 0) { @@ -491,6 +496,7 @@ connection_edge_finished_flushing(edge_connection_t *conn) case AP_CONN_STATE_CONNECT_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT: case AP_CONN_STATE_RESOLVE_WAIT: + case AP_CONN_STATE_HTTP_CONNECT_WAIT: return 0; default: log_warn(LD_BUG, "Called in unexpected state %d.",conn->base_.state); @@ -1182,10 +1188,10 @@ consider_plaintext_ports(entry_connection_t *conn, uint16_t port) * See connection_ap_handshake_rewrite_and_attach()'s * documentation for arguments and return value. */ -int -connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn, - origin_circuit_t *circ, - crypt_path_t *cpath) +MOCK_IMPL(int, +connection_ap_rewrite_and_attach_if_allowed,(entry_connection_t *conn, + origin_circuit_t *circ, + crypt_path_t *cpath)) { const or_options_t *options = get_options(); @@ -2422,6 +2428,108 @@ connection_ap_process_natd(entry_connection_t *conn) return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); } +/** Called on an HTTP CONNECT entry connection when some bytes have arrived, + * but we have not yet received a full HTTP CONNECT request. Try to parse an + * HTTP CONNECT request from the connection's inbuf. On success, set up the + * connection's socks_request field and try to attach the connection. On + * failure, send an HTTP reply, and mark the connection. + */ +STATIC int +connection_ap_process_http_connect(entry_connection_t *conn) +{ + if (BUG(ENTRY_TO_CONN(conn)->state != AP_CONN_STATE_HTTP_CONNECT_WAIT)) + return -1; + + char *headers = NULL, *body = NULL; + char *command = NULL, *addrport = NULL; + char *addr = NULL; + size_t bodylen = 0; + + const char *errmsg = NULL; + int rv = 0; + + const int http_status = + fetch_from_buf_http(ENTRY_TO_CONN(conn)->inbuf, &headers, 8192, + &body, &bodylen, 1024, 0); + if (http_status < 0) { + /* Bad http status */ + errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n"; + goto err; + } else if (http_status == 0) { + /* no HTTP request yet. */ + goto done; + } + + const int cmd_status = parse_http_command(headers, &command, &addrport); + if (cmd_status < 0) { + errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n"; + goto err; + } + tor_assert(command); + tor_assert(addrport); + if (strcasecmp(command, "connect")) { + errmsg = "HTTP/1.0 405 Method Not Allowed\r\n\r\n"; + goto err; + } + + tor_assert(conn->socks_request); + socks_request_t *socks = conn->socks_request; + uint16_t port; + if (tor_addr_port_split(LOG_WARN, addrport, &addr, &port) < 0) { + errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n"; + goto err; + } + if (strlen(addr) >= MAX_SOCKS_ADDR_LEN) { + errmsg = "HTTP/1.0 414 Request-URI Too Long\r\n\r\n"; + goto err; + } + + /* Abuse the 'username' and 'password' fields here. They are already an + * abuse. */ + { + char *authorization = http_get_header(headers, "Proxy-Authorization: "); + if (authorization) { + socks->username = authorization; // steal reference + socks->usernamelen = strlen(authorization); + } + char *isolation = http_get_header(headers, "X-Tor-Stream-Isolation: "); + if (isolation) { + socks->password = isolation; // steal reference + socks->passwordlen = strlen(isolation); + } + } + + socks->command = SOCKS_COMMAND_CONNECT; + socks->listener_type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER; + strlcpy(socks->address, addr, sizeof(socks->address)); + socks->port = port; + + control_event_stream_status(conn, STREAM_EVENT_NEW, 0); + + rv = connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); + + // XXXX send a "100 Continue" message? + + goto done; + + err: + if (BUG(errmsg == NULL)) + errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n"; + log_warn(LD_EDGE, "Saying %s", escaped(errmsg)); + connection_write_to_buf(errmsg, strlen(errmsg), ENTRY_TO_CONN(conn)); + connection_mark_unattached_ap(conn, + END_STREAM_REASON_HTTPPROTOCOL| + END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); + + done: + tor_free(headers); + tor_free(body); + tor_free(command); + tor_free(addrport); + tor_free(addr); + return rv; +} + /** Iterate over the two bytes of stream_id until we get one that is not * already in use; return it. Return 0 if can't get a unique stream_id. */ @@ -3045,7 +3153,14 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, conn->socks_request->has_finished = 1; return; } - if (conn->socks_request->socks_version == 4) { + if (conn->socks_request->listener_type == + CONN_TYPE_AP_HTTP_CONNECT_LISTENER) { + const char *response = end_reason_to_http_connect_response_line(endreason); + if (!response) { + response = "HTTP/1.0 400 Bad Request\r\n\r\n"; + } + connection_write_to_buf(response, strlen(response), ENTRY_TO_CONN(conn)); + } else if (conn->socks_request->socks_version == 4) { memset(buf,0,SOCKS4_NETWORK_LEN); buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT); /* leave version, destport, destip zero */ diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 914238fc1f..e47043f7fe 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -89,9 +89,10 @@ int connection_ap_process_transparent(entry_connection_t *conn); int address_is_invalid_destination(const char *address, int client); -int connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn, - origin_circuit_t *circ, - crypt_path_t *cpath); +MOCK_DECL(int, connection_ap_rewrite_and_attach_if_allowed, + (entry_connection_t *conn, + origin_circuit_t *circ, + crypt_path_t *cpath)); int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath); @@ -188,6 +189,8 @@ typedef struct { STATIC void connection_ap_handshake_rewrite(entry_connection_t *conn, rewrite_result_t *out); + +STATIC int connection_ap_process_http_connect(entry_connection_t *conn); #endif #endif diff --git a/src/or/directory.c b/src/or/directory.c index b1094634ff..1baf053903 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -104,7 +104,6 @@ static void directory_send_command(dir_connection_t *conn, int direct, const directory_request_t *request); static int body_is_plausible(const char *body, size_t body_len, int purpose); -static char *http_get_header(const char *headers, const char *which); static void http_set_address_origin(const char *headers, connection_t *conn); static void connection_dir_download_routerdesc_failed(dir_connection_t *conn); static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn); @@ -1966,15 +1965,39 @@ directory_send_command(dir_connection_t *conn, STATIC int parse_http_url(const char *headers, char **url) { + char *command = NULL; + if (parse_http_command(headers, &command, url) < 0) { + return -1; + } + if (!strcmpstart(*url, "/tor/")) { + char *new_url = NULL; + tor_asprintf(&new_url, "/tor/%s", *url); + tor_free(*url); + *url = new_url; + } + tor_free(command); + return 0; +} + +/** Parse an HTTP request line at the start of a headers string. On failure, + * return -1. On success, set *<b>command_out</b> to a copy of the HTTP + * command ("get", "post", etc), set *<b>url_out</b> to a copy of the URL, and + * return 0. */ +int +parse_http_command(const char *headers, char **command_out, char **url_out) +{ + const char *command, *end_of_command; char *s, *start, *tmp; s = (char *)eat_whitespace_no_nl(headers); if (!*s) return -1; + command = s; s = (char *)find_whitespace(s); /* get past GET/POST */ if (!*s) return -1; + end_of_command = s; s = (char *)eat_whitespace_no_nl(s); if (!*s) return -1; - start = s; /* this is it, assuming it's valid */ + start = s; /* this is the URL, assuming it's valid */ s = (char *)find_whitespace(start); if (!*s) return -1; @@ -2005,13 +2028,8 @@ parse_http_url(const char *headers, char **url) return -1; } - if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */ - *url = tor_malloc(s - start + 5); - strlcpy(*url,"/tor", s-start+5); - strlcat((*url)+4, start, s-start+1); - } else { - *url = tor_strndup(start, s-start); - } + *url_out = tor_memdup_nulterm(start, s-start); + *command_out = tor_memdup_nulterm(command, end_of_command - command); return 0; } @@ -2019,7 +2037,7 @@ parse_http_url(const char *headers, char **url) * <b>which</b>. The key should be given with a terminating colon and space; * this function copies everything after, up to but not including the * following \\r\\n. */ -static char * +char * http_get_header(const char *headers, const char *which) { const char *cp = headers; diff --git a/src/or/directory.h b/src/or/directory.h index 42bcb55eb2..1200728411 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -87,6 +87,9 @@ MOCK_DECL(void, directory_initiate_request, (directory_request_t *request)); int parse_http_response(const char *headers, int *code, time_t *date, compress_method_t *compression, char **response); +int parse_http_command(const char *headers, + char **command_out, char **url_out); +char *http_get_header(const char *headers, const char *which); int connection_dir_is_encrypted(const dir_connection_t *conn); int connection_dir_reached_eof(dir_connection_t *conn); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 7136ab2968..e25a3d316a 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1683,7 +1683,8 @@ any_client_port_set(const or_options_t *options) options->TransPort_set || options->NATDPort_set || options->ControlPort_set || - options->DNSPort_set); + options->DNSPort_set || + options->HTTPTunnelPort_set); } /** diff --git a/src/or/or.h b/src/or/or.h index 11d3bb31cc..b3cd83f245 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -226,8 +226,10 @@ typedef enum { #define CONN_TYPE_EXT_OR 16 /** Type for sockets listening for Extended ORPort connections. */ #define CONN_TYPE_EXT_OR_LISTENER 17 +/** Type for sockets listening for HTTP CONNECT tunnel connections. */ +#define CONN_TYPE_AP_HTTP_CONNECT_LISTENER 18 -#define CONN_TYPE_MAX_ 17 +#define CONN_TYPE_MAX_ 19 /* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in * connection_t. */ @@ -348,7 +350,9 @@ typedef enum { /** State for a transparent natd connection: waiting for original * destination. */ #define AP_CONN_STATE_NATD_WAIT 12 -#define AP_CONN_STATE_MAX_ 12 +/** State for an HTTP tunnel: waiting for an HTTP CONNECT command. */ +#define AP_CONN_STATE_HTTP_CONNECT_WAIT 13 +#define AP_CONN_STATE_MAX_ 13 /** True iff the AP_CONN_STATE_* value <b>s</b> means that the corresponding * edge connection is not attached to any circuit. */ @@ -648,6 +652,10 @@ typedef enum { /** The target address is in a private network (like 127.0.0.1 or 10.0.0.1); * you don't want to do that over a randomly chosen exit */ #define END_STREAM_REASON_PRIVATE_ADDR 262 +/** This is an HTTP tunnel connection and the client used or misused HTTP in a + * way we can't handle. + */ +#define END_STREAM_REASON_HTTPPROTOCOL 263 /** Bitwise-and this value with endreason to mask out all flags. */ #define END_STREAM_REASON_MASK 511 @@ -3696,6 +3704,8 @@ typedef struct { } TransProxyType_parsed; config_line_t *NATDPort_lines; /**< Ports to listen on for transparent natd * connections. */ + /** Ports to listen on for HTTP Tunnel connections. */ + config_line_t *HTTPTunnelPort_lines; config_line_t *ControlPort_lines; /**< Ports to listen on for control * connections. */ config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on @@ -3722,7 +3732,8 @@ typedef struct { * configured in one of the _lines options above. * For client ports, also true if there is a unix socket configured. * If you are checking for client ports, you may want to use: - * SocksPort_set || TransPort_set || NATDPort_set || DNSPort_set + * SocksPort_set || TransPort_set || NATDPort_set || DNSPort_set || + * HTTPTunnelPort_set * rather than SocksPort_set. * * @{ @@ -3735,6 +3746,7 @@ typedef struct { unsigned int DirPort_set : 1; unsigned int DNSPort_set : 1; unsigned int ExtORPort_set : 1; + unsigned int HTTPTunnelPort_set : 1; /**@}*/ int AssumeReachable; /**< Whether to publish our descriptor regardless. */ diff --git a/src/or/reasons.c b/src/or/reasons.c index e6c325f1b3..717cf57c24 100644 --- a/src/or/reasons.c +++ b/src/or/reasons.c @@ -45,6 +45,8 @@ stream_end_reason_to_control_string(int reason) case END_STREAM_REASON_CANT_ATTACH: return "CANT_ATTACH"; case END_STREAM_REASON_NET_UNREACHABLE: return "NET_UNREACHABLE"; case END_STREAM_REASON_SOCKSPROTOCOL: return "SOCKS_PROTOCOL"; + // XXXX Controlspec + case END_STREAM_REASON_HTTPPROTOCOL: return "HTTP_PROTOCOL"; case END_STREAM_REASON_PRIVATE_ADDR: return "PRIVATE_ADDR"; @@ -138,6 +140,11 @@ stream_end_reason_to_socks5_response(int reason) return SOCKS5_NET_UNREACHABLE; case END_STREAM_REASON_SOCKSPROTOCOL: return SOCKS5_GENERAL_ERROR; + case END_STREAM_REASON_HTTPPROTOCOL: + // LCOV_EXCL_START + tor_assert_nonfatal_unreached(); + return SOCKS5_GENERAL_ERROR; + // LCOV_EXCL_STOP case END_STREAM_REASON_PRIVATE_ADDR: return SOCKS5_GENERAL_ERROR; @@ -442,3 +449,48 @@ bandwidth_weight_rule_to_string(bandwidth_weight_rule_t rule) } } +/** Given a RELAY_END reason value, convert it to an HTTP response to be + * send over an HTTP tunnel connection. */ +const char * +end_reason_to_http_connect_response_line(int endreason) +{ + endreason &= END_STREAM_REASON_MASK; + /* XXXX these are probably all wrong. Should they all be 502? */ + switch (endreason) { + case 0: + return "HTTP/1.0 200 OK\r\n\r\n"; + case END_STREAM_REASON_MISC: + return "HTTP/1.0 500 Internal Server Error\r\n\r\n"; + case END_STREAM_REASON_RESOLVEFAILED: + return "HTTP/1.0 404 Not Found (resolve failed)\r\n\r\n"; + case END_STREAM_REASON_NOROUTE: + return "HTTP/1.0 404 Not Found (no route)\r\n\r\n"; + case END_STREAM_REASON_CONNECTREFUSED: + return "HTTP/1.0 403 Forbidden (connection refused)\r\n\r\n"; + case END_STREAM_REASON_EXITPOLICY: + return "HTTP/1.0 403 Forbidden (exit policy)\r\n\r\n"; + case END_STREAM_REASON_DESTROY: + return "HTTP/1.0 502 Bad Gateway (destroy cell received)\r\n\r\n"; + case END_STREAM_REASON_DONE: + return "HTTP/1.0 502 Bad Gateway (unexpected close)\r\n\r\n"; + case END_STREAM_REASON_TIMEOUT: + return "HTTP/1.0 504 Gateway Timeout\r\n\r\n"; + case END_STREAM_REASON_HIBERNATING: + return "HTTP/1.0 502 Bad Gateway (hibernating server)\r\n\r\n"; + case END_STREAM_REASON_INTERNAL: + return "HTTP/1.0 502 Bad Gateway (internal error)\r\n\r\n"; + case END_STREAM_REASON_RESOURCELIMIT: + return "HTTP/1.0 502 Bad Gateway (resource limit)\r\n\r\n"; + case END_STREAM_REASON_CONNRESET: + return "HTTP/1.0 403 Forbidden (connection reset)\r\n\r\n"; + case END_STREAM_REASON_TORPROTOCOL: + return "HTTP/1.0 502 Bad Gateway (tor protocol violation)\r\n\r\n"; + case END_STREAM_REASON_ENTRYPOLICY: + return "HTTP/1.0 403 Forbidden (entry policy violation)\r\n\r\n"; + case END_STREAM_REASON_NOTDIRECTORY: /* Fall Through */ + default: + tor_assert_nonfatal_unreached(); + return "HTTP/1.0 500 Internal Server Error (weird end reason)\r\n\r\n"; + } +} + diff --git a/src/or/reasons.h b/src/or/reasons.h index 1cadf4e89e..f98db55bdd 100644 --- a/src/or/reasons.h +++ b/src/or/reasons.h @@ -26,6 +26,7 @@ const char *socks4_response_code_to_string(uint8_t code); const char *socks5_response_code_to_string(uint8_t code); const char *bandwidth_weight_rule_to_string(enum bandwidth_weight_rule_t rule); +const char *end_reason_to_http_connect_response_line(int endreason); #endif diff --git a/src/or/relay.c b/src/or/relay.c index e362348bb9..d8f09d320d 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1467,8 +1467,9 @@ connection_edge_process_relay_cell_not_open( circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ)); /* don't send a socks reply to transparent conns */ tor_assert(entry_conn->socks_request != NULL); - if (!entry_conn->socks_request->has_finished) + if (!entry_conn->socks_request->has_finished) { connection_ap_handshake_socks_reply(entry_conn, NULL, 0, 0); + } /* Was it a linked dir conn? If so, a dir request just started to * fetch something; this could be a bootstrap status milestone. */ |