commit 417d778652770a8f4b0b6f8e5d8e139e193b8b1e Author: Ravi Chandra Padmala neenaoffline@gmail.com Date: Tue Feb 21 08:52:03 2012 +0530
Respond meaningfully to HTTP requests on the control port. Fix #1667
(Squashed with bufferevents portions removed, by nickm) --- changes/bug1667 | 4 ++++ src/or/buffers.c | 25 +++++++++++++++++++++++++ src/or/buffers.h | 2 ++ src/or/control.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+)
diff --git a/changes/bug1667 b/changes/bug1667 new file mode 100644 index 0000000..195993d --- /dev/null +++ b/changes/bug1667 @@ -0,0 +1,4 @@ + o Minor features: + - If the control port is used as the HTTP proxy, responds with + a meaningful "This is the Tor control port" message, and logs + the event. Fixes bug 1667. diff --git a/src/or/buffers.c b/src/or/buffers.c index 3692ed4..af1b67e 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -2022,6 +2022,31 @@ parse_socks_client(const uint8_t *data, size_t datalen, return -1; }
+/** Return true if <b>cmd</b> looks like a HTTP (proxy) request. */ +int +peek_buf_has_http_command(buf_t *buf) +{ + if (peek_buf_startswith(buf, "CONNECT ") || + peek_buf_startswith(buf, "DELETE ") || + peek_buf_startswith(buf, "GET ") || + peek_buf_startswith(buf, "POST ") || + peek_buf_startswith(buf, "PUT " )) + return 1; + return 0; +} + +/** Return 1 iff <b>buf</b> starts with <b>cmd</b>. <b>cmd</b> must be a null + * terminated string */ +int +peek_buf_startswith(buf_t *buf, const char *cmd) +{ + int clen = strlen(cmd); + if (buf->datalen >= clen) + if (!strncasecmp((buf->head)->data, cmd, (size_t) clen)) + return 1; + return 0; +} + /** Return 1 iff buf looks more like it has an (obsolete) v0 controller * command on it than any valid v1 controller command. */ int diff --git a/src/or/buffers.h b/src/or/buffers.h index 23b58a5..5650bea 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -53,6 +53,8 @@ int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason); int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
int peek_buf_has_control0_command(buf_t *buf); +int peek_buf_startswith(buf_t *buf, const char *cmd); +int peek_buf_has_http_command(buf_t *buf);
int fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out);
diff --git a/src/or/control.c b/src/or/control.c index 9454a7a..3e31f17 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -4882,6 +4882,12 @@ peek_connection_has_control0_command(connection_t *conn) return peek_buf_has_control0_command(conn->inbuf); }
+static int +peek_connection_has_http_command(connection_t *conn) +{ + return peek_buf_has_http_command(conn->inbuf); +} + /** Called when data has arrived on a v1 control connection: Try to fetch * commands from conn->inbuf, and execute them. */ @@ -4921,6 +4927,38 @@ connection_control_process_inbuf(control_connection_t *conn) return 0; }
+ /* If the user has the HTTP proxy port and the control port confused. */ + if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH && + peek_connection_has_http_command(TO_CONN(conn))) { + connection_write_str_to_buf("HTTP/1.0 501 Tor ControlPort is not a proxy" +"\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n" +"<html>\n" +"<head>\n" +"<title>Tor's ControlPort is not proxy</title>\n" +"</head>\n" +"<body>\n" +"<h1>Tor's ControlPort is not a proxy</h1>\n" +"<p>\n" +"It appears you have configured your web browser to use Tor's control port" +" as an HTTP proxy.\n" +"This is not correct: Tor's default SOCKS proxy port is 9050.\n" +"Please configure your client accordingly.\n" +"</p>\n" +"<p>\n" +"See <a href="https://www.torproject.org/documentation.html%5C%22%3E" + "https://www.torproject.org/documentation.html</a> for more " + "information.\n" +"<!-- Plus this comment, to make the body response more than 512 bytes, so " +" IE will be willing to display it. Comment comment comment comment " +" comment comment comment comment comment comment comment comment.-->\n" +"</p>\n" +"</body>\n" +"</html>\n", conn); + log_notice(LD_CONTROL, "Received HTTP request on ControlPort"); + connection_mark_and_flush(TO_CONN(conn)); + return 0; + } + again: while (1) { size_t last_idx;