[or-cvs] r11164: Backport r11138: Implement PROTOCOLINFO/proposal 119. (in tor/branches/tor-0_1_2-patches: . doc src/or)
nickm at seul.org
nickm at seul.org
Sat Aug 18 15:42:57 UTC 2007
Author: nickm
Date: 2007-08-18 11:42:56 -0400 (Sat, 18 Aug 2007)
New Revision: 11164
Modified:
tor/branches/tor-0_1_2-patches/
tor/branches/tor-0_1_2-patches/ChangeLog
tor/branches/tor-0_1_2-patches/doc/TODO.012
tor/branches/tor-0_1_2-patches/src/or/control.c
tor/branches/tor-0_1_2-patches/src/or/or.h
Log:
r14655 at catbus: nickm | 2007-08-18 11:41:49 -0400
Backport r11138: Implement PROTOCOLINFO/proposal 119.
Property changes on: tor/branches/tor-0_1_2-patches
___________________________________________________________________
svk:merge ticket from /tor/012 [r14655] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/branches/tor-0_1_2-patches/ChangeLog
===================================================================
--- tor/branches/tor-0_1_2-patches/ChangeLog 2007-08-18 12:41:30 UTC (rev 11163)
+++ tor/branches/tor-0_1_2-patches/ChangeLog 2007-08-18 15:42:56 UTC (rev 11164)
@@ -4,6 +4,12 @@
deprecated since Tor 0.1.1.1-alpha, and keeping it safe and secure
has been more of a headache than it's worth.
+ o Minor features (controller):
+ - Add a PROTOCOLINFO controller command. Like AUTHENTICATE, it is valid
+ before any authentication has been received. It tells a controller
+ what kind of authentication is expected, and what protocol is spoken.
+ Implements proposal 119.
+
o Minor bugfixes (performance):
- Save on most routerlist_assert_ok() calls in routerlist.c,
thus greatly speeding up loading cached-routers from disk on
Modified: tor/branches/tor-0_1_2-patches/doc/TODO.012
===================================================================
--- tor/branches/tor-0_1_2-patches/doc/TODO.012 2007-08-18 12:41:30 UTC (rev 11163)
+++ tor/branches/tor-0_1_2-patches/doc/TODO.012 2007-08-18 15:42:56 UTC (rev 11164)
@@ -5,7 +5,7 @@
buffer allocation.
o r11117: cookie auth more usable
o disable v0 control protocol
- - r11138: PROTOCOLINFO support.
+ o r11138: PROTOCOLINFO support.
D r11141: CookieAuthFile and CookieAuthFileGroupReadable.
Modified: tor/branches/tor-0_1_2-patches/src/or/control.c
===================================================================
--- tor/branches/tor-0_1_2-patches/src/or/control.c 2007-08-18 12:41:30 UTC (rev 11163)
+++ tor/branches/tor-0_1_2-patches/src/or/control.c 2007-08-18 15:42:56 UTC (rev 11164)
@@ -149,6 +149,7 @@
size_t len);
static void orconn_target_get_name(int long_names, char *buf, size_t len,
or_connection_t *conn);
+static char *get_cookie_file(void);
/** Given a control event code for a message event, return the corresponding
* log severity. */
@@ -2209,6 +2210,73 @@
return 0;
}
+/** Called when we get a <b>protocolinfo</b> command on <b>conn</b>. */
+static int
+handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
+ const char *body)
+{
+ const char *bad_arg = NULL;
+ smartlist_t *args;
+ (void)len;
+
+ conn->have_sent_protocolinfo = 1;
+ args = smartlist_create();
+ smartlist_split_string(args, body, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ SMARTLIST_FOREACH(args, const char *, arg, {
+ int ok;
+ tor_parse_long(arg, 10, 0, LONG_MAX, &ok, NULL);
+ if (!ok) {
+ bad_arg = arg;
+
+ break;
+ }
+ });
+ if (bad_arg) {
+ connection_printf_to_buf(conn, "513 No such version %s\r\n",
+ escaped(bad_arg));
+ /* Don't tolerate bad arguments when not authenticated. */
+ if (!STATE_IS_OPEN(TO_CONN(conn)->state))
+ connection_mark_for_close(TO_CONN(conn));
+ goto done;
+ } else {
+ or_options_t *options = get_options();
+ int cookies = options->CookieAuthentication;
+ char *cfile = get_cookie_file();
+ char *esc_cfile = esc_for_log(cfile);
+ char *methods;
+ {
+ int passwd = (options->HashedControlPassword != NULL) &&
+ strlen(options->HashedControlPassword);
+ smartlist_t *mlist = smartlist_create();
+ if (cookies)
+ smartlist_add(mlist, (char*)"COOKIE");
+ if (passwd)
+ smartlist_add(mlist, (char*)"HASHEDPASSWORD");
+ if (!cookies && !passwd)
+ smartlist_add(mlist, (char*)"NULL");
+ methods = smartlist_join_strings(mlist, ",", 0, NULL);
+ smartlist_free(mlist);
+ }
+
+ connection_printf_to_buf(conn,
+ "250+PROTOCOLINFO 1\r\n"
+ "250-AUTH METHODS=%s%s%s\r\n"
+ "250-VERSION Tor=%s\r\n"
+ "250 OK\r\n",
+ methods,
+ cookies?" COOKIEFILE=":"",
+ cookies?esc_cfile:"",
+ escaped(VERSION));
+ tor_free(cfile);
+ tor_free(esc_cfile);
+ }
+ done:
+ SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
+ smartlist_free(args);
+ return 0;
+}
+
/** Called when <b>conn</b> has no more bytes left on its outbuf. */
int
connection_control_finished_flushing(control_connection_t *conn)
@@ -2230,6 +2298,21 @@
return 0;
}
+/** Return true iff <b>cmd</b> is allowable (or at least forgivable) at this
+ * stage of the protocol. */
+static int
+is_valid_initial_command(control_connection_t *conn, const char *cmd)
+{
+ if (conn->_base.state == CONTROL_CONN_STATE_OPEN_V1)
+ return 1;
+ if (!strcasecmp(cmd, "PROTOCOLINFO"))
+ return !conn->have_sent_protocolinfo;
+ if (!strcasecmp(cmd, "AUTHENTICATE") ||
+ !strcasecmp(cmd, "QUIT"))
+ return 1;
+ return 0;
+}
+
/** Called when data has arrived on a v1 control connection: Try to fetch
* commands from conn->inbuf, and execute them.
*/
@@ -2323,6 +2406,7 @@
--data_len;
}
+ /* Quit is always okay. */
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
connection_write_str_to_buf("250 closing connection\r\n", conn);
connection_mark_for_close(TO_CONN(conn));
@@ -2330,7 +2414,7 @@
}
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
- strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
+ !is_valid_initial_command(conn, conn->incoming_cmd)) {
connection_write_str_to_buf("514 Authentication required.\r\n", conn);
connection_mark_for_close(TO_CONN(conn));
return 0;
@@ -2390,6 +2474,9 @@
} else if (!strcasecmp(conn->incoming_cmd, "USEFEATURE")) {
if (handle_control_usefeature(conn, data_len, args))
return -1;
+ } else if (!strcasecmp(conn->incoming_cmd, "PROTOCOLINFO")) {
+ if (handle_control_protocolinfo(conn, data_len, args))
+ return -1;
} else {
connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
conn->incoming_cmd);
@@ -2399,168 +2486,6 @@
goto again;
}
-#if 0
-/** Called when data has arrived on a v0 control connection: Try to fetch
- * commands from conn->inbuf, and execute them.
- */
-static int
-connection_control_process_inbuf_v0(control_connection_t *conn)
-{
- uint32_t body_len;
- uint16_t command_type;
- char *body=NULL;
- static int have_warned_about_v0_protocol = 0;
-
- again:
- /* Try to suck a control message from the buffer. */
- switch (fetch_from_buf_control0(conn->_base.inbuf, &body_len, &command_type,
- &body,
- conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0))
- {
- case -2:
- tor_free(body);
- log_info(LD_CONTROL,
- "Detected v1 control protocol on connection (fd %d)",
- conn->_base.s);
- conn->_base.state = CONTROL_CONN_STATE_NEEDAUTH_V1;
- return connection_control_process_inbuf_v1(conn);
- case -1:
- tor_free(body);
- log_warn(LD_CONTROL, "Error in control command. Failing.");
- return -1;
- case 0:
- /* Control command not all here yet. Wait. */
- return 0;
- case 1:
- /* We got a command. Process it. */
- break;
- default:
- tor_assert(0);
- }
-
- if (!have_warned_about_v0_protocol) {
- log_warn(LD_CONTROL, "An application has connected to us using the "
- "version 0 control prototol, which has been deprecated since "
- "Tor 0.1.1.1-alpha. This protocol will not be supported by "
- "future versions of Tor; please use the v1 control protocol "
- "instead.");
- have_warned_about_v0_protocol = 1;
- }
-
- /* We got a command. If we need authentication, only authentication
- * commands will be considered. */
- if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0 &&
- command_type != CONTROL0_CMD_AUTHENTICATE) {
- log_info(LD_CONTROL, "Rejecting '%s' command; authentication needed.",
- control_cmd_to_string(command_type));
- send_control0_error(conn, ERR_UNAUTHORIZED, "Authentication required");
- tor_free(body);
- goto again;
- }
-
- if (command_type == CONTROL0_CMD_FRAGMENTHEADER ||
- command_type == CONTROL0_CMD_FRAGMENT) {
- if (handle_control_fragments(conn, command_type, body_len, body))
- return -1;
- tor_free(body);
- if (conn->incoming_cmd_cur_len != conn->incoming_cmd_len)
- goto again;
-
- command_type = conn->incoming_cmd_type;
- body_len = conn->incoming_cmd_len;
- body = conn->incoming_cmd;
- conn->incoming_cmd = NULL;
- } else if (conn->incoming_cmd) {
- log_warn(LD_CONTROL, "Dropping incomplete fragmented command");
- tor_free(conn->incoming_cmd);
- }
-
- /* Okay, we're willing to process the command. */
- switch (command_type)
- {
- case CONTROL0_CMD_SETCONF:
- if (handle_control_setconf(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_GETCONF:
- if (handle_control_getconf(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_SETEVENTS:
- if (handle_control_setevents(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_AUTHENTICATE:
- if (handle_control_authenticate(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_SAVECONF:
- if (handle_control_saveconf(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_SIGNAL:
- if (handle_control_signal(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_MAPADDRESS:
- if (handle_control_mapaddress(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_GETINFO:
- if (handle_control_getinfo(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_EXTENDCIRCUIT:
- if (handle_control_extendcircuit(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_ATTACHSTREAM:
- if (handle_control_attachstream(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_POSTDESCRIPTOR:
- if (handle_control_postdescriptor(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_REDIRECTSTREAM:
- if (handle_control_redirectstream(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_CLOSESTREAM:
- if (handle_control_closestream(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_CLOSECIRCUIT:
- if (handle_control_closecircuit(conn, body_len, body))
- return -1;
- break;
- case CONTROL0_CMD_ERROR:
- case CONTROL0_CMD_DONE:
- case CONTROL0_CMD_CONFVALUE:
- case CONTROL0_CMD_EVENT:
- case CONTROL0_CMD_INFOVALUE:
- log_warn(LD_CONTROL, "Received client-only '%s' command; ignoring.",
- control_cmd_to_string(command_type));
- send_control0_error(conn, ERR_UNRECOGNIZED_TYPE,
- "Command type only valid from server to tor client");
- break;
- case CONTROL0_CMD_FRAGMENTHEADER:
- case CONTROL0_CMD_FRAGMENT:
- log_warn(LD_CONTROL,
- "Recieved command fragment out of order; ignoring.");
- send_control0_error(conn, ERR_SYNTAX, "Bad fragmentation on command.");
- default:
- log_warn(LD_CONTROL, "Received unrecognized command type %d; ignoring.",
- (int)command_type);
- send_control0_error(conn, ERR_UNRECOGNIZED_TYPE,
- "Unrecognized command type");
- break;
- }
- tor_free(body);
- goto again; /* There might be more data. */
-}
-#endif
-
/** Convert a numeric reason for destroying a circuit into a string for a
* CIRCUIT event. */
static const char *
@@ -3372,6 +3297,17 @@
return 0;
}
+/** DOCDOC */
+static char *
+get_cookie_file(void)
+{
+ const char *datadir = get_options()->DataDirectory;
+ size_t len = strlen(datadir)+64;
+ char *fname = tor_malloc(len);
+ tor_snprintf(fname, len, "%s"PATH_SEPARATOR"control_auth_cookie", datadir);
+ return fname;
+}
+
/** Choose a random authentication cookie and write it to disk.
* Anybody who can read the cookie from disk will be considered
* authorized to use the control connection. Return -1 if we can't
@@ -3379,7 +3315,7 @@
int
init_cookie_authentication(int enabled)
{
- char fname[512];
+ char *fname;
if (!enabled) {
authentication_cookie_is_set = 0;
@@ -3389,17 +3325,18 @@
if (authentication_cookie_is_set)
return 0;
- tor_snprintf(fname, sizeof(fname), "%s/control_auth_cookie",
- get_options()->DataDirectory);
+ fname = get_cookie_file();
crypto_rand(authentication_cookie, AUTHENTICATION_COOKIE_LEN);
authentication_cookie_is_set = 1;
if (write_bytes_to_file(fname, authentication_cookie,
AUTHENTICATION_COOKIE_LEN, 1)) {
log_warn(LD_FS,"Error writing authentication cookie to %s.",
escaped(fname));
+ tor_free(fname);
return -1;
}
+ tor_free(fname);
return 0;
}
Modified: tor/branches/tor-0_1_2-patches/src/or/or.h
===================================================================
--- tor/branches/tor-0_1_2-patches/src/or/or.h 2007-08-18 12:41:30 UTC (rev 11163)
+++ tor/branches/tor-0_1_2-patches/src/or/or.h 2007-08-18 15:42:56 UTC (rev 11164)
@@ -936,6 +936,9 @@
* events as appropriate. */
unsigned int use_extended_events:1;
+ /** True if we have sent a protocolinfo reply on this connection. */
+ unsigned int have_sent_protocolinfo:1;
+
uint32_t incoming_cmd_len;
uint32_t incoming_cmd_cur_len;
char *incoming_cmd;
More information about the tor-commits
mailing list