summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-08-16 17:34:55 +0000
committerNick Mathewson <nickm@torproject.org>2007-08-16 17:34:55 +0000
commitebb8a62ad4e24fd6c1984ada92b13cb073152565 (patch)
treed35f65dfed9a7e046c45bcb10f208f7d6f485ce5
parentd0ecd468eb1e932423a7bc0e30b722044ccc112f (diff)
downloadtor-ebb8a62ad4e24fd6c1984ada92b13cb073152565.tar.gz
tor-ebb8a62ad4e24fd6c1984ada92b13cb073152565.zip
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
-rw-r--r--src/or/buffers.c56
-rw-r--r--src/or/control.c35
-rw-r--r--src/or/or.h3
3 files changed, 30 insertions, 64 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 6ce9c6ac14..33118c2b46 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -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
diff --git a/src/or/control.c b/src/or/control.c
index 521b810a87..80ea17bed0 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -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;
diff --git a/src/or/or.h b/src/or/or.h
index 7b5fd6bd52..b05458f4e2 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -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);