diff options
author | teor <teor@torproject.org> | 2019-08-06 00:18:41 +1000 |
---|---|---|
committer | teor <teor@torproject.org> | 2019-10-03 11:35:42 +1000 |
commit | 3d17fafa04baf23d124edf56560abf3b19ad4425 (patch) | |
tree | 113ef02639a0835d5e11c0028a052e5f71a8c47c /src | |
parent | e1429d91480ee16ebe32be35263a4695e1795ff9 (diff) | |
download | tor-3d17fafa04baf23d124edf56560abf3b19ad4425.tar.gz tor-3d17fafa04baf23d124edf56560abf3b19ad4425.zip |
control/control: Refactor some error handling code
Split some protocol error handling out of
connection_control_process_inbuf().
This refactor reduces the size of a practracker exception.
Closes 31840.
Diffstat (limited to 'src')
-rw-r--r-- | src/feature/control/control.c | 79 |
1 files changed, 55 insertions, 24 deletions
diff --git a/src/feature/control/control.c b/src/feature/control/control.c index 436bf423cf..d6581808c0 100644 --- a/src/feature/control/control.c +++ b/src/feature/control/control.c @@ -339,6 +339,60 @@ static const char CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG[] = "</body>\n" "</html>\n"; +/** Return an error on a control connection that tried to use the v0 protocol. + */ +static void +control_send_v0_reject(control_connection_t *conn) +{ + size_t body_len; + char buf[128]; + set_uint16(buf+2, htons(0x0000)); /* type == error */ + set_uint16(buf+4, htons(0x0001)); /* code == internal error */ + strlcpy(buf+6, "The v0 control protocol is not supported by Tor 0.1.2.17 " + "and later; upgrade your controller.", + sizeof(buf)-6); + body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */ + set_uint16(buf+0, htons(body_len)); + connection_buf_add(buf, 4+body_len, TO_CONN(conn)); + + connection_mark_and_flush(TO_CONN(conn)); +} + +/** Return an error on a control connection that tried to use HTTP. + */ +static void +control_send_http_reject(control_connection_t *conn) +{ + connection_write_str_to_buf(CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG, conn); + log_notice(LD_CONTROL, "Received HTTP request on ControlPort"); + connection_mark_and_flush(TO_CONN(conn)); +} + +/** Check if a control connection has tried to use a known invalid protocol. + * If it has, then: + * - send a reject response, + * - log a notice-level message, and + * - return false. */ +static bool +control_protocol_is_valid(control_connection_t *conn) +{ + /* Detect v0 commands and send a "no more v0" message. */ + if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH && + peek_connection_has_control0_command(TO_CONN(conn))) { + control_send_v0_reject(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))) { + control_send_http_reject(conn); + return 0; + } + + return 1; +} + /** Called when data has arrived on a v1 control connection: Try to fetch * commands from conn->inbuf, and execute them. */ @@ -359,30 +413,7 @@ connection_control_process_inbuf(control_connection_t *conn) conn->incoming_cmd_cur_len = 0; } - if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH && - peek_connection_has_control0_command(TO_CONN(conn))) { - /* Detect v0 commands and send a "no more v0" message. */ - size_t body_len; - char buf[128]; - set_uint16(buf+2, htons(0x0000)); /* type == error */ - set_uint16(buf+4, htons(0x0001)); /* code == internal error */ - strlcpy(buf+6, "The v0 control protocol is not supported by Tor 0.1.2.17 " - "and later; upgrade your controller.", - sizeof(buf)-6); - body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */ - set_uint16(buf+0, htons(body_len)); - connection_buf_add(buf, 4+body_len, TO_CONN(conn)); - - connection_mark_and_flush(TO_CONN(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(CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG, conn); - log_notice(LD_CONTROL, "Received HTTP request on ControlPort"); - connection_mark_and_flush(TO_CONN(conn)); + if (!control_protocol_is_valid(conn)) { return 0; } |