r14602@catbus: nickm | 2007-08-16 13:33:27 -0400

Make 0.1.2 give a warning on v0 control commands and close the connnection, rather than simply failing apart and yelling.


svn:r11139
This commit is contained in:
Nick Mathewson 2007-08-16 17:34:55 +00:00
parent d0ecd468eb
commit ebb8a62ad4
3 changed files with 30 additions and 64 deletions

View File

@ -1228,54 +1228,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
}
}
/** If there is a complete version 0 control message waiting on buf, then store
* its contents into *<b>type_out</b>, store its body's length into
* *<b>len_out</b>, allocate and store a string for its body into
* *<b>body_out</b>, and return 1. (body_out will always be NUL-terminated,
* even if the control message body doesn't end with NUL.)
*
* If there is not a complete control message waiting, return 0.
*
* Return -1 on error; return -2 on "seems to be control protocol v1."
*/
/** Return 1 iff buf looks more like it has an (obsolete) v0 controller
* command on it than any valid v1 controller command. */
int
fetch_from_buf_control0(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
char **body_out, int check_for_v1)
peek_buf_has_control0_command(buf_t *buf)
{
uint32_t msglen;
uint16_t type;
char tmp[4];
tor_assert(buf);
tor_assert(len_out);
tor_assert(type_out);
tor_assert(body_out);
*len_out = 0;
*body_out = NULL;
if (buf->datalen < 4)
return 0;
peek_from_buf(tmp, 4, buf);
msglen = ntohs(get_uint16(tmp));
type = ntohs(get_uint16(tmp+2));
if (type > 255 && check_for_v1)
return -2;
if (buf->datalen < 4 + (unsigned)msglen)
return 0;
*len_out = msglen;
*type_out = type;
buf_remove_from_front(buf, 4);
if (msglen) {
*body_out = tor_malloc(msglen+1);
fetch_from_buf(*body_out, msglen, buf);
(*body_out)[msglen] = '\0';
if (buf->datalen >= 4) {
char header[4];
uint16_t cmd;
peek_from_buf(header, sizeof(header), buf);
cmd = ntohs(get_uint16(header+2));
if (cmd <= 0x14)
return 1; /* This is definitely not a v1 control command. */
}
return 1;
return 0;
}
/** Helper: return a pointer to the first instance of <b>c</b> in the

View File

@ -19,23 +19,6 @@ const char control_c_id[] =
* See control-spec.txt for full details on protocol.
*/
#if 0
/* Recognized version 0 error codes. Do not expand. */
#define ERR_UNSPECIFIED 0x0000
#define ERR_INTERNAL 0x0001
#define ERR_UNRECOGNIZED_TYPE 0x0002
#define ERR_SYNTAX 0x0003
#define ERR_UNRECOGNIZED_CONFIG_KEY 0x0004
#define ERR_INVALID_CONFIG_VALUE 0x0005
#define ERR_UNRECOGNIZED_EVENT_CODE 0x0006
#define ERR_UNAUTHORIZED 0x0007
#define ERR_REJECTED_AUTHENTICATION 0x0008
#define ERR_RESOURCE_EXHAUSTED 0x0009
#define ERR_NO_STREAM 0x000A
#define ERR_NO_CIRC 0x000B
#define ERR_NO_ROUTER 0x000C
#endif
/* Recognized asynchronous event types. It's okay to expand this list
* because it is used both as a list of v0 event types, and as indices
* into the bitfield to determine which controllers want which events.
@ -2267,6 +2250,24 @@ connection_control_process_inbuf(control_connection_t *conn)
conn->incoming_cmd_cur_len = 0;
}
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
peek_buf_has_control0_command(conn->_base.inbuf)) {
/* 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.2.0.x "
"and later; use Tor 0.1.2.x or upgrade your controller",
sizeof(buf)-6);
body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
set_uint16(buf+0, htons(body_len));
connection_write_to_buf(buf, 4+body_len, TO_CONN(conn));
connection_mark_for_close(TO_CONN(conn));
conn->_base.hold_open_until_flushed = 1;
return 0;
}
again:
while (1) {
size_t last_idx;

View File

@ -1923,8 +1923,7 @@ int fetch_from_buf_http(buf_t *buf,
int force_complete);
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks);
int fetch_from_buf_control0(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
char **body_out, int check_for_v1);
int peek_buf_has_control0_command(buf_t *buf);
int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
int fetch_from_buf_line_lf(buf_t *buf, char *data_out, size_t *data_len);