[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r9098: Infrastructure to test BEGIN_DIR cells. New socks command CO (tor/trunk/src/or)



Author: arma
Date: 2006-12-12 19:28:56 -0500 (Tue, 12 Dec 2006)
New Revision: 9098

Modified:
   tor/trunk/src/or/buffers.c
   tor/trunk/src/or/circuituse.c
   tor/trunk/src/or/config.c
   tor/trunk/src/or/connection_edge.c
   tor/trunk/src/or/control.c
   tor/trunk/src/or/directory.c
   tor/trunk/src/or/or.h
   tor/trunk/src/or/relay.c
   tor/trunk/src/or/router.c
   tor/trunk/src/or/routerparse.c
Log:
Infrastructure to test BEGIN_DIR cells.

New socks command CONNECT_DIR. New config option TunnelDirConns that
builds a circ ending at the directory server and delivers a BEGIN_DIR
cell if it's running 0.1.2.2-alpha or later. We still need to make
one-hop circs when appropriate, while making other conns avoid them.


Modified: tor/trunk/src/or/buffers.c
===================================================================
--- tor/trunk/src/or/buffers.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/buffers.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -974,6 +974,7 @@
         return 0; /* not yet */
       req->command = (unsigned char) *(buf->cur+1);
       if (req->command != SOCKS_COMMAND_CONNECT &&
+          req->command != SOCKS_COMMAND_CONNECT_DIR &&
           req->command != SOCKS_COMMAND_RESOLVE &&
           req->command != SOCKS_COMMAND_RESOLVE_PTR) {
         /* not a connect or resolve or a resolve_ptr? we don't support it. */
@@ -1065,6 +1066,7 @@
 
       req->command = (unsigned char) *(buf->cur+1);
       if (req->command != SOCKS_COMMAND_CONNECT &&
+          req->command != SOCKS_COMMAND_CONNECT_DIR &&
           req->command != SOCKS_COMMAND_RESOLVE) {
         /* not a connect or resolve? we don't support it. (No resolve_ptr with
          * socks4.) */

Modified: tor/trunk/src/or/circuituse.c
===================================================================
--- tor/trunk/src/or/circuituse.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/circuituse.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -902,16 +902,18 @@
                                 origin_circuit_t **circp)
 {
   origin_circuit_t *circ;
-  int is_resolve;
+  int check_exit_policy;
   int need_uptime, need_internal;
 
   tor_assert(conn);
   tor_assert(circp);
   tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
-  is_resolve = (conn->socks_request->command == SOCKS_COMMAND_RESOLVE ||
-                conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR);
+  check_exit_policy =
+      (conn->socks_request->command == SOCKS_COMMAND_CONNECT) &&
+      !connection_edge_is_rendezvous_stream(conn);
 
-  need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
+  need_uptime = (conn->socks_request->command == SOCKS_COMMAND_CONNECT) &&
+                smartlist_string_num_isin(get_options()->LongLivedPorts,
                                           conn->socks_request->port);
   need_internal = desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL;
 
@@ -941,7 +943,7 @@
   }
 
   /* Do we need to check exit policy? */
-  if (!is_resolve && !connection_edge_is_rendezvous_stream(conn)) {
+  if (check_exit_policy) {
     struct in_addr in;
     uint32_t addr = 0;
     if (tor_inet_aton(conn->socks_request->address, &in))
@@ -1125,13 +1127,17 @@
 
   link_apconn_to_circ(conn, circ);
   tor_assert(conn->socks_request);
-  if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
-    consider_recording_trackhost(conn, circ);
-    if (connection_ap_handshake_send_begin(conn, circ)<0)
-      return -1;
-  } else {
-    if (connection_ap_handshake_send_resolve(conn, circ)<0)
-      return -1;
+  switch (conn->socks_request->command) {
+    case SOCKS_COMMAND_CONNECT:
+      consider_recording_trackhost(conn, circ);
+      /* fall through */
+    case SOCKS_COMMAND_CONNECT_DIR:
+      if (connection_ap_handshake_send_begin(conn, circ)<0)
+        return -1;
+      break;
+    default:
+      if (connection_ap_handshake_send_resolve(conn, circ)<0)
+        return -1;
   }
 
   return 1;

Modified: tor/trunk/src/or/config.c
===================================================================
--- tor/trunk/src/or/config.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/config.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -247,6 +247,7 @@
   OBSOLETE("TrafficShaping"),
   VAR("TransListenAddress",  LINELIST, TransListenAddress,   NULL),
   VAR("TransPort",           UINT,     TransPort,            "0"),
+  VAR("TunnelDirConns",      BOOL,     TunnelDirConns,       "0"),
   VAR("UseEntryGuards",      BOOL,     UseEntryGuards,       "1"),
   VAR("User",                STRING,   User,                 NULL),
   VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir,   "0"),

Modified: tor/trunk/src/or/connection_edge.c
===================================================================
--- tor/trunk/src/or/connection_edge.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/connection_edge.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -55,7 +55,7 @@
                "Bug: stream (marked at %s:%d) sending two socks replies?",
                file, line);
 
-    if (conn->socks_request->command == SOCKS_COMMAND_CONNECT)
+    if (SOCKS_COMMAND_IS_CONNECT(conn->socks_request->command))
       connection_ap_handshake_socks_reply(conn, NULL, 0, endreason);
     else
       connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR,
@@ -1213,6 +1213,8 @@
       // XXXX NM Do anything here?
 
       rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
+    } else if (socks->command == SOCKS_COMMAND_CONNECT_DIR) {
+      ; /* nothing */
     } else {
       tor_fragile_assert();
     }
@@ -1230,7 +1232,7 @@
     rend_cache_entry_t *entry;
     int r;
 
-    if (socks->command != SOCKS_COMMAND_CONNECT) {
+    if (!SOCKS_COMMAND_IS_CONNECT(socks->command)) {
       /* if it's a resolve request, fail it right now, rather than
        * building all the circuits and then realizing it won't work. */
       log_warn(LD_APP,
@@ -1450,7 +1452,7 @@
     return -1;
   }
 
-  if (socks->command == SOCKS_COMMAND_CONNECT)
+  if (SOCKS_COMMAND_IS_CONNECT(socks->command))
     control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
   else
     control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE, 0);
@@ -1546,7 +1548,7 @@
 
   if (strcmpstart(tmp_buf, "[DEST ")) {
     log_warn(LD_APP,"Natd handshake was ill-formed; closing. The client "
-             "said: '%s'",
+             "said: %s",
              escaped(tmp_buf));
     connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST);
     return -1;
@@ -1564,7 +1566,7 @@
   socks->port = (uint16_t)
     tor_parse_long(tbuf, 10, 1, 65535, &port_ok, &daddr);
   if (!port_ok) {
-    log_warn(LD_APP,"Natd handshake failed; port '%s' is ill-formed or out "
+    log_warn(LD_APP,"Natd handshake failed; port %s is ill-formed or out "
              "of range.", escaped(tbuf));
     connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST);
     return -1;
@@ -1620,10 +1622,12 @@
 {
   char payload[CELL_PAYLOAD_SIZE];
   int payload_len;
+  int begin_type;
 
   tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
   tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
   tor_assert(ap_conn->socks_request);
+  tor_assert(SOCKS_COMMAND_IS_CONNECT(ap_conn->socks_request->command));
 
   ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
   if (ap_conn->stream_id==0) {
@@ -1641,9 +1645,11 @@
   log_debug(LD_APP,
             "Sending relay cell to begin stream %d.", ap_conn->stream_id);
 
+  begin_type = ap_conn->socks_request->command == SOCKS_COMMAND_CONNECT ?
+                 RELAY_COMMAND_BEGIN : RELAY_COMMAND_BEGIN_DIR;
+
   if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
-                                   RELAY_COMMAND_BEGIN,
-                                   payload, payload_len,
+                                   begin_type, payload, payload_len,
                                    ap_conn->cpath_layer) < 0)
     return -1; /* circuit is closed, don't continue */
 
@@ -1669,15 +1675,14 @@
   const char *string_addr;
   char inaddr_buf[32];
 
-  command = ap_conn->socks_request->command;
-
   tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
   tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
   tor_assert(ap_conn->socks_request);
-  tor_assert(command == SOCKS_COMMAND_RESOLVE ||
-             command == SOCKS_COMMAND_RESOLVE_PTR);
   tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
 
+  command = ap_conn->socks_request->command;
+  tor_assert(SOCKS_COMMAND_IS_RESOLVE(command));
+
   ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
   if (ap_conn->stream_id==0) {
     connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
@@ -1729,7 +1734,8 @@
  * Return the other end of the socketpair, or -1 if error.
  */
 int
-connection_ap_make_bridge(char *address, uint16_t port)
+connection_ap_make_bridge(char *address, uint16_t port,
+                          const char *digest, int command)
 {
   int fd[2];
   edge_connection_t *conn;
@@ -1761,7 +1767,13 @@
   strlcpy(conn->socks_request->address, address,
           sizeof(conn->socks_request->address));
   conn->socks_request->port = port;
-  conn->socks_request->command = SOCKS_COMMAND_CONNECT;
+  conn->socks_request->command = command;
+  if (command == SOCKS_COMMAND_CONNECT_DIR) {
+    conn->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+2);
+    conn->chosen_exit_name[0] = '$';
+    base16_encode(conn->chosen_exit_name+1,HEX_DIGEST_LEN+1,
+                  digest, DIGEST_LEN);
+  }
 
   conn->_base.address = tor_strdup("(local bridge)");
   conn->_base.addr = 0;
@@ -2396,8 +2408,7 @@
                                     exit->exit_policy);
     if (r == ADDR_POLICY_REJECTED || r == ADDR_POLICY_PROBABLY_REJECTED)
       return 0;
-  } else { /* Some kind of a resolve. */
-
+  } else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
     /* Can't support reverse lookups without eventdns. */
     if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR &&
         exit->has_old_dnsworkers)

Modified: tor/trunk/src/or/control.c
===================================================================
--- tor/trunk/src/or/control.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/control.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -1619,8 +1619,7 @@
         case AP_CONN_STATE_CONTROLLER_WAIT:
         case AP_CONN_STATE_CIRCUIT_WAIT:
           if (conn->socks_request &&
-              (conn->socks_request->command == SOCKS_COMMAND_RESOLVE ||
-               conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR))
+              SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command))
             state = "NEWRESOLVE";
           else
             state = "NEW";

Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/directory.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -39,7 +39,7 @@
 
 static void
 directory_send_command(dir_connection_t *conn, const char *platform,
-                       int purpose, const char *resource,
+                       int purpose, int direct, const char *resource,
                        const char *payload, size_t payload_len);
 static int directory_handle_command(dir_connection_t *conn);
 static int body_is_plausible(const char *body, size_t body_len, int purpose);
@@ -370,12 +370,18 @@
                            const char *payload, size_t payload_len)
 {
   dir_connection_t *conn;
+  or_options_t *options = get_options();
+  int want_to_tunnel = options->TunnelDirConns && platform &&
+                       tor_version_as_new_as(platform, "0.1.2.2-alpha");
 
   tor_assert(address);
   tor_assert(addr);
   tor_assert(dir_port);
   tor_assert(digest);
 
+  log_debug(LD_DIR, "private %d, want_to_tunnel %d.",
+            private_connection, want_to_tunnel);
+
   switch (purpose) {
     case DIR_PURPOSE_FETCH_DIR:
       log_debug(LD_DIR,"initiating directory fetch");
@@ -415,14 +421,14 @@
 
   /* give it an initial state */
   conn->_base.state = DIR_CONN_STATE_CONNECTING;
-  conn->dirconn_direct = (private_connection == 0);
 
-  if (!private_connection) {
+  if (!private_connection && !want_to_tunnel) {
     /* then we want to connect directly */
 
-    if (get_options()->HttpProxy) {
-      addr = get_options()->HttpProxyAddr;
-      dir_port = get_options()->HttpProxyPort;
+    conn->dirconn_direct = 1;
+    if (options->HttpProxy) {
+      addr = options->HttpProxyAddr;
+      dir_port = options->HttpProxyPort;
     }
 
     switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
@@ -437,7 +443,7 @@
         /* fall through */
       case 0:
         /* queue the command on the outbuf */
-        directory_send_command(conn, platform, purpose, resource,
+        directory_send_command(conn, platform, purpose, 1, resource,
                                payload, payload_len);
         connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
         /* writable indicates finish, readable indicates broken link,
@@ -448,8 +454,13 @@
      * populate it and add it at the right state
      * socketpair and hook up both sides
      */
-    conn->_base.s = connection_ap_make_bridge(conn->_base.address,
-                                              conn->_base.port);
+    conn->dirconn_direct = 0;
+    conn->_base.s =
+      connection_ap_make_bridge(conn->_base.address, conn->_base.port,
+                                digest,
+                                private_connection ?
+                                  SOCKS_COMMAND_CONNECT :
+                                  SOCKS_COMMAND_CONNECT_DIR);
     if (conn->_base.s < 0) {
       log_warn(LD_NET,"Making AP bridge to dirserver failed.");
       connection_mark_for_close(TO_CONN(conn));
@@ -463,7 +474,7 @@
     }
     conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
     /* queue the command on the outbuf */
-    directory_send_command(conn, platform, purpose, resource,
+    directory_send_command(conn, platform, purpose, 0, resource,
                            payload, payload_len);
     connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
   }
@@ -474,7 +485,7 @@
  */
 static void
 directory_send_command(dir_connection_t *conn, const char *platform,
-                       int purpose, const char *resource,
+                       int purpose, int direct, const char *resource,
                        const char *payload, size_t payload_len)
 {
   char proxystring[256];
@@ -501,7 +512,7 @@
   }
 
   /* come up with some proxy lines, if we're using one. */
-  if (get_options()->HttpProxy) {
+  if (direct && get_options()->HttpProxy) {
     char *base64_authenticator=NULL;
     const char *authenticator = get_options()->HttpProxyAuthenticator;
 

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/or.h	2006-12-13 00:28:56 UTC (rev 9098)
@@ -1648,8 +1648,10 @@
   char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
                      * resolver from the file here rather than from
                      * /etc/resolv.conf (Unix) or the registry (Windows). */
-  int EnforceDistinctSubnets; /** If true, don't allow multiple routers in the
+  int EnforceDistinctSubnets; /**< If true, don't allow multiple routers in the
                                * same network zone in the same circuit. */
+  int TunnelDirConns; /**< If true, use BEGIN_DIR rather than BEGIN when
+                       * possible. */
 } or_options_t;
 
 /** Persistent state for an onion router, as saved to disk. */
@@ -1705,17 +1707,21 @@
 
 #define MAX_SOCKS_REPLY_LEN 1024
 #define MAX_SOCKS_ADDR_LEN 256
+
 #define SOCKS_COMMAND_CONNECT 0x01
+#define SOCKS_COMMAND_CONNECT_DIR 0xE0
 #define SOCKS_COMMAND_RESOLVE 0xF0
 #define SOCKS_COMMAND_RESOLVE_PTR 0xF1
 
+#define SOCKS_COMMAND_IS_CONNECT(c) ((c)==SOCKS_COMMAND_CONNECT || \
+                                     (c)==SOCKS_COMMAND_CONNECT_DIR)
 #define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \
                                      (c)==SOCKS_COMMAND_RESOLVE_PTR)
 
 /** State of a SOCKS request from a user to an OP */
 struct socks_request_t {
   char socks_version; /**< Which version of SOCKS did the client use? */
-  int command; /**< What has the user requested? One of CONNECT or RESOLVE. */
+  int command; /**< What has the user requested? One from the above list. */
   size_t replylen; /**< Length of <b>reply</b>. */
   char reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
                                     * we want to specify our own socks reply,
@@ -2017,7 +2023,8 @@
 int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
                                          origin_circuit_t *circ);
 
-int connection_ap_make_bridge(char *address, uint16_t port);
+int connection_ap_make_bridge(char *address, uint16_t port,
+                              const char *digest, int command);
 void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
                                          size_t replylen,
                                          int endreason);

Modified: tor/trunk/src/or/relay.c
===================================================================
--- tor/trunk/src/or/relay.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/relay.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -900,8 +900,7 @@
              "not in state resolve_wait. Dropping.");
       return 0;
     }
-    tor_assert(conn->socks_request->command == SOCKS_COMMAND_RESOLVE ||
-               conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR);
+    tor_assert(SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command));
     answer_len = cell->payload[RELAY_HEADER_SIZE+1];
     if (rh->length < 2 || answer_len+2>rh->length) {
       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,

Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/router.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -1015,7 +1015,8 @@
 
   /* first, learn what the IP address actually is */
   if (!tor_inet_aton(suggestion, &in)) {
-    log_debug(LD_DIR, "Malformed X-Your-Address-Is header. Ignoring.");
+    log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
+              escaped(suggestion));
     return;
   }
   addr = ntohl(in.s_addr);

Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c	2006-12-13 00:05:28 UTC (rev 9097)
+++ tor/trunk/src/or/routerparse.c	2006-12-13 00:28:56 UTC (rev 9098)
@@ -1821,6 +1821,8 @@
   char *s, *start;
   char tmp[128];
 
+  tor_assert(platform);
+
   if (tor_version_parse(cutoff, &cutoff_version)<0) {
     log_warn(LD_DIR,"Bug: cutoff version '%s' unparseable.",cutoff);
     return 0;