[or-cvs] r11138: Implement proposal 119. Backport candidate. (in tor/trunk: . doc/spec doc/spec/proposals src/or)

nickm at seul.org nickm at seul.org
Thu Aug 16 17:31:24 UTC 2007


Author: nickm
Date: 2007-08-16 13:31:23 -0400 (Thu, 16 Aug 2007)
New Revision: 11138

Modified:
   tor/trunk/
   tor/trunk/ChangeLog
   tor/trunk/doc/spec/control-spec.txt
   tor/trunk/doc/spec/proposals/000-index.txt
   tor/trunk/doc/spec/proposals/119-controlport-auth.txt
   tor/trunk/src/or/control.c
   tor/trunk/src/or/or.h
Log:
 r14600 at catbus:  nickm | 2007-08-16 13:30:22 -0400
 Implement proposal 119. Backport candidate.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r14600] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2007-08-16 16:57:19 UTC (rev 11137)
+++ tor/trunk/ChangeLog	2007-08-16 17:31:23 UTC (rev 11138)
@@ -26,6 +26,12 @@
     - Read v3 keys from the right location.
     - Numerous bugfixes to directory voting code.
 
+  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 (other):
     - If we require CookieAuthentication but we fail to write the
       cookie file, we would warn but not exit, and end up in a state

Modified: tor/trunk/doc/spec/control-spec.txt
===================================================================
--- tor/trunk/doc/spec/control-spec.txt	2007-08-16 16:57:19 UTC (rev 11137)
+++ tor/trunk/doc/spec/control-spec.txt	2007-08-16 17:31:23 UTC (rev 11138)
@@ -231,9 +231,11 @@
   The format of the 'cookie' is implementation-dependent; see 5.1 below for
   information on how the standard Tor implementation handles it.
 
-  If Tor requires authentication and the controller has not yet sent an
-  AUTHENTICATE message, Tor sends a "514 authentication required" reply to
-  any other kind of message, and then closes the connection.
+  Before the client has authenticated, no command other than PROTOCOLINFO,
+  AUTHENTICATE, or QUIT is valid.  If the controller sends any other command,
+  or sends a malformed command, or sends an unsuccessful AUTHENTICATE
+  command, or sends PROTOCOLINFO more than once, Tor sends an error reply and
+  closes the connection.
 
   (Versions of Tor before 0.1.2.16 and 0.2.0.4-alpha did not close the
   connection after an authentication failure.)
@@ -733,6 +735,56 @@
 
   [Added in Tor 0.2.0.3-alpha]
 
+3.21. PROTOCOLINFO
+
+  The syntax is:
+    "PROTOCOLINFO" *(SP PIVERSION) CRLF
+
+  The server reply format is:
+    "250+PROTOCOLINFO" SP PIVERSION CRLF *InfoLine "250 OK" CRLF
+
+    InfoLine = AuthLine / VersionLine / OtherLine
+
+     AuthLine = "250-AUTH" SP "METHODS=" AuthMethod *(",")AuthMethod
+                       *(SP "COOKIEFILE=" AuthCookieFile) CRLF
+     VersionLine = "250-VERSION" SP "Tor=" TorVersion [SP Arguments] CRLF
+
+     AuthMethod =
+      "NULL"           / ; No authentication is required
+      "HASHEDPASSWORD" / ; A controller must supply the original password
+      "COOKIE"         / ; A controller must supply the contents of a cookie
+
+     AuthCookieFile = QuotedString
+     TorVersion = QuotedString
+
+     OtherLine = "250-" Keyword [SP Arguments] CRLF
+
+    PIVERSION: 1*DIGIT
+
+  Tor MAY give its InfoLines in any order; controllers MUST ignore InfoLines
+  with keywords it does not recognize.  Controllers MUST ignore extraneous
+  data on any InfoLine.
+
+  PIVERSION is there in case we drastically change the syntax one day. For
+  now it should always be "1", for the controller protocol.  Controllers MAY
+  provide a list of the protocol versions they support; Tor MAY select a
+  version that the controller does not support.
+
+  AuthMethod is used to specify one or more control authentication
+  methods that Tor currently accepts.
+
+  AuthCookieFile specifies the absolute path and filename of the
+  authentication cookie that Tor is expecting and is provided iff
+  the METHODS field contains the method "COOKIE".  Controllers MUST handle
+  escape sequences inside this string.
+
+  The VERSION line contains the Tor version.
+
+  [Unlike other commands besides AUTHENTICATE, PROTOCOLINFO may be used (but
+  only once!) before AUTHENTICATE.]
+
+  [PROTOCOLINFO was not supported before Tor 0.2.0.5-alpha.]
+
 4. Replies
 
   Reply codes follow the same 3-character format as used by SMTP, with the

Modified: tor/trunk/doc/spec/proposals/000-index.txt
===================================================================
--- tor/trunk/doc/spec/proposals/000-index.txt	2007-08-16 16:57:19 UTC (rev 11137)
+++ tor/trunk/doc/spec/proposals/000-index.txt	2007-08-16 17:31:23 UTC (rev 11138)
@@ -37,5 +37,5 @@
 116  Two hop paths from entry guards [OPEN]
 117  IPv6 exits [OPEN]
 118  Advertising multiple ORPorts at once [RESEARCH]
-119  New PROTOCOLINFO command for controllers [ACCEPTED]
+119  New PROTOCOLINFO command for controllers [CLOSED]
 120  Suicide descriptors when Tor servers stop [OPEN]

Modified: tor/trunk/doc/spec/proposals/119-controlport-auth.txt
===================================================================
--- tor/trunk/doc/spec/proposals/119-controlport-auth.txt	2007-08-16 16:57:19 UTC (rev 11137)
+++ tor/trunk/doc/spec/proposals/119-controlport-auth.txt	2007-08-16 17:31:23 UTC (rev 11138)
@@ -4,7 +4,7 @@
 Last-Modified: $Date$
 Author: Roger Dingledine
 Created: 14-Aug-2007
-Status: Accepted
+Status: Closd
 
 Overview:
 

Modified: tor/trunk/src/or/control.c
===================================================================
--- tor/trunk/src/or/control.c	2007-08-16 16:57:19 UTC (rev 11137)
+++ tor/trunk/src/or/control.c	2007-08-16 17:31:23 UTC (rev 11138)
@@ -142,6 +142,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. */
@@ -2236,6 +2237,7 @@
   return 0;
 }
 
+/** DOCDOC */
 static int
 handle_control_resolve(control_connection_t *conn, uint32_t len,
                        const char *body)
@@ -2270,6 +2272,72 @@
   return 0;
 }
 
+/** DOCDOC */
+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 we get a USEFEATURE command: parse the feature list, and
  * set up the control_connection's options properly. */
 static int
@@ -2340,6 +2408,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)
+    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.
  */
@@ -2433,6 +2516,7 @@
     --data_len;
   }
 
+  /* Quit is always valid. */
   if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
     connection_write_str_to_buf("250 closing connection\r\n", conn);
     connection_mark_for_close(TO_CONN(conn));
@@ -2440,7 +2524,7 @@
   }
 
   if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH &&
-      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;
@@ -2503,6 +2587,9 @@
   } else if (!strcasecmp(conn->incoming_cmd, "RESOLVE")) {
     if (handle_control_resolve(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);
@@ -3343,6 +3430,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
@@ -3350,8 +3448,7 @@
 int
 init_cookie_authentication(int enabled)
 {
-  char fname[512];
-
+  char *fname;
   if (!enabled) {
     authentication_cookie_is_set = 0;
     return 0;
@@ -3362,17 +3459,18 @@
   if (authentication_cookie_is_set)
     return 0; /* all set */
 
-  tor_snprintf(fname, sizeof(fname), "%s"PATH_SEPARATOR"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/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-08-16 16:57:19 UTC (rev 11137)
+++ tor/trunk/src/or/or.h	2007-08-16 17:31:23 UTC (rev 11138)
@@ -994,6 +994,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