[or-cvs] r17635: {tor} Backport r166558: avoid mis-routing create cells. This has s (in tor/branches/tor-0_2_0-patches: . doc src/or)

nickm at seul.org nickm at seul.org
Tue Dec 16 22:53:24 UTC 2008


Author: nickm
Date: 2008-12-16 17:53:24 -0500 (Tue, 16 Dec 2008)
New Revision: 17635

Modified:
   tor/branches/tor-0_2_0-patches/ChangeLog
   tor/branches/tor-0_2_0-patches/doc/TODO.020
   tor/branches/tor-0_2_0-patches/src/or/connection.c
   tor/branches/tor-0_2_0-patches/src/or/control.c
   tor/branches/tor-0_2_0-patches/src/or/cpuworker.c
   tor/branches/tor-0_2_0-patches/src/or/or.h
Log:
Backport r166558: avoid mis-routing create cells.  This has seen enough testing that we can be more confident in it now.

Modified: tor/branches/tor-0_2_0-patches/ChangeLog
===================================================================
--- tor/branches/tor-0_2_0-patches/ChangeLog	2008-12-16 17:49:39 UTC (rev 17634)
+++ tor/branches/tor-0_2_0-patches/ChangeLog	2008-12-16 22:53:24 UTC (rev 17635)
@@ -6,6 +6,11 @@
       the client never closes the circuit, then the exit relay never
       closes the TCP connection. Bug introduced in Tor 0.1.2.1-alpha;
       reported by "wood".
+    - When sending CREATED cells back for a given circuit, use a 64-bit
+      connection ID to find the right connection, rather than an addr:port
+      combination.  Now that we can have multiple OR connections between the
+      same ORs, it is no longer possible to use addr:port to uniquely
+      identify a connection.
 
   o Minor bugfixes:
     - Do not mark smartlist_bsearch_idx() function as ATTR_PURE.  This bug
@@ -24,7 +29,10 @@
       automatically stop Tor from starting.  Instead, we retry failed
       dns_inits() every 10 minutes, and change the exit policy to reject *:*
       until one succeeds.  Fixes bug 691.
+    - Use 64 bits instead of 32 bits for connection identifiers used with
+      the controller protocol, to greatly reduce risk of identifier reuse.
 
+
   o Minor features:
     - Report the case where all signatures in a detached set are rejected
       differently than the case where there is an error handling the detached

Modified: tor/branches/tor-0_2_0-patches/doc/TODO.020
===================================================================
--- tor/branches/tor-0_2_0-patches/doc/TODO.020	2008-12-16 17:49:39 UTC (rev 17634)
+++ tor/branches/tor-0_2_0-patches/doc/TODO.020	2008-12-16 22:53:24 UTC (rev 17635)
@@ -7,8 +7,7 @@
 
 Backport for 0.2.0 once better tested:
   o r16136: prevent circid collision.  [Also backport to 0.1.2.x??]
-
-  - r16558: Avoid mis-routing CREATED cells.
+  o r16558: Avoid mis-routing CREATED cells.
   - r16621: Make some DNS code more robust (partial; see also libevent
             approach). (Also maybe r16674)
   - r17091: distinguish "no routers support pending circuits" from

Modified: tor/branches/tor-0_2_0-patches/src/or/connection.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/connection.c	2008-12-16 17:49:39 UTC (rev 17634)
+++ tor/branches/tor-0_2_0-patches/src/or/connection.c	2008-12-16 22:53:24 UTC (rev 17635)
@@ -166,7 +166,8 @@
 connection_t *
 connection_new(int type, int socket_family)
 {
-  static uint32_t n_connections_allocated = 1;
+  static uint64_t n_connections_allocated = 1;
+
   connection_t *conn;
   time_t now = time(NULL);
   size_t length;
@@ -200,6 +201,7 @@
   conn->magic = magic;
   conn->s = -1; /* give it a default of 'not used' */
   conn->conn_array_index = -1; /* also default to 'not used' */
+  conn->global_identifier = n_connections_allocated++;
 
   conn->type = type;
   conn->socket_family = socket_family;
@@ -211,9 +213,6 @@
     TO_EDGE_CONN(conn)->socks_request =
       tor_malloc_zero(sizeof(socks_request_t));
   }
-  if (CONN_IS_EDGE(conn)) {
-    TO_EDGE_CONN(conn)->global_identifier = n_connections_allocated++;
-  }
   if (type == CONN_TYPE_OR) {
     TO_OR_CONN(conn)->timestamp_last_added_nonpadding = now;
     TO_OR_CONN(conn)->next_circ_id = crypto_rand_int(1<<15);
@@ -2380,26 +2379,6 @@
   }
 }
 
-/** Return the conn to addr/port that has the most recent
- * timestamp_created, or NULL if no such conn exists. */
-or_connection_t *
-connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
-{
-  or_connection_t *best=NULL;
-  smartlist_t *conns = get_connection_array();
-
-  SMARTLIST_FOREACH(conns, connection_t *, conn,
-  {
-    if (conn->type == CONN_TYPE_OR &&
-        conn->addr == addr &&
-        conn->port == port &&
-        !conn->marked_for_close &&
-        (!best || best->_base.timestamp_created < conn->timestamp_created))
-      best = TO_OR_CONN(conn);
-  });
-  return best;
-}
-
 /** Return a connection with given type, address, port, and purpose;
  * or NULL if no such connection exists. */
 connection_t *
@@ -2423,18 +2402,14 @@
 /** Return the stream with id <b>id</b> if it is not already marked for
  * close.
  */
-edge_connection_t *
-connection_get_by_global_id(uint32_t id)
+connection_t *
+connection_get_by_global_id(uint64_t id)
 {
   smartlist_t *conns = get_connection_array();
   SMARTLIST_FOREACH(conns, connection_t *, conn,
   {
-    if (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->global_identifier == id) {
-      if (!conn->marked_for_close)
-        return TO_EDGE_CONN(conn);
-      else
-        return NULL;
-    }
+    if (conn->global_identifier == id)
+      return conn;
   });
   return NULL;
 }

Modified: tor/branches/tor-0_2_0-patches/src/or/control.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/control.c	2008-12-16 17:49:39 UTC (rev 17634)
+++ tor/branches/tor-0_2_0-patches/src/or/control.c	2008-12-16 22:53:24 UTC (rev 17635)
@@ -643,16 +643,16 @@
 static edge_connection_t *
 get_stream(const char *id)
 {
-  uint32_t n_id;
+  uint64_t n_id;
   int ok;
-  edge_connection_t *conn;
-  n_id = (uint32_t) tor_parse_ulong(id, 10, 0, UINT32_MAX, &ok, NULL);
+  connection_t *conn;
+  n_id = tor_parse_uint64(id, 10, 0, UINT64_MAX, &ok, NULL);
   if (!ok)
     return NULL;
   conn = connection_get_by_global_id(n_id);
-  if (!conn || conn->_base.type != CONN_TYPE_AP)
+  if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close)
     return NULL;
-  return conn;
+  return TO_EDGE_CONN(conn);
 }
 
 /** Helper for setconf and resetconf. Acts like setconf, except
@@ -1586,8 +1586,7 @@
     smartlist_t *conns = get_connection_array();
     smartlist_t *status = smartlist_create();
     char buf[256];
-    SMARTLIST_FOREACH(conns, connection_t *, base_conn,
-    {
+    SMARTLIST_FOREACH(conns, connection_t *, base_conn, {
       const char *state;
       edge_connection_t *conn;
       char *s;
@@ -1629,7 +1628,7 @@
       slen = strlen(buf)+strlen(state)+32;
       s = tor_malloc(slen+1);
       tor_snprintf(s, slen, "%lu %s %lu %s",
-                   (unsigned long) conn->global_identifier,state,
+                   (unsigned long) conn->_base.global_identifier,state,
                    origin_circ?
                          (unsigned long)origin_circ->global_identifier : 0ul,
                    buf);
@@ -3140,8 +3139,8 @@
   if (circ && CIRCUIT_IS_ORIGIN(circ))
     origin_circ = TO_ORIGIN_CIRCUIT(circ);
   send_control_event_extended(EVENT_STREAM_STATUS, ALL_NAMES,
-                        "650 STREAM %lu %s %lu %s@%s%s%s\r\n",
-                        (unsigned long)conn->global_identifier, status,
+                        "650 STREAM "U64_FORMAT" %s %lu %s@%s%s%s\r\n",
+                        U64_PRINTF_ARG(conn->_base.global_identifier), status,
                         origin_circ?
                            (unsigned long)origin_circ->global_identifier : 0ul,
                         buf, reason_buf, addrport_buf, purpose);
@@ -3297,8 +3296,7 @@
     smartlist_t *conns = get_connection_array();
     edge_connection_t *edge_conn;
 
-    SMARTLIST_FOREACH(conns, connection_t *, conn,
-    {
+    SMARTLIST_FOREACH(conns, connection_t *, conn, {
         if (conn->type != CONN_TYPE_AP)
           continue;
         edge_conn = TO_EDGE_CONN(conn);
@@ -3306,8 +3304,8 @@
           continue;
 
         send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_NAMES,
-                            "650 STREAM_BW %lu %lu %lu\r\n",
-                            (unsigned long)edge_conn->global_identifier,
+                            "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n",
+                            U64_PRINTF_ARG(edge_conn->_base.global_identifier),
                             (unsigned long)edge_conn->n_read,
                             (unsigned long)edge_conn->n_written);
 

Modified: tor/branches/tor-0_2_0-patches/src/or/cpuworker.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/cpuworker.c	2008-12-16 17:49:39 UTC (rev 17634)
+++ tor/branches/tor-0_2_0-patches/src/or/cpuworker.c	2008-12-16 22:53:24 UTC (rev 17635)
@@ -23,7 +23,7 @@
 #define MIN_CPUWORKERS 1
 
 /** The tag specifies which circuit this onionskin was from. */
-#define TAG_LEN 8
+#define TAG_LEN 10
 /** How many bytes are sent from the cpuworker back to tor? */
 #define LEN_ONION_RESPONSE \
   (1+TAG_LEN+ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN)
@@ -60,32 +60,22 @@
   return 0;
 }
 
-/** Pack addr,port,and circ_id; set *tag to the result. (See note on
+/** Pack global_id and circ_id; set *tag to the result. (See note on
  * cpuworker_main for wire format.) */
 static void
-tag_pack(char *tag, uint32_t addr, uint16_t port, uint16_t circ_id)
+tag_pack(char *tag, uint64_t conn_id, uint16_t circ_id)
 {
-  *(uint32_t *)tag     = addr;
-  *(uint16_t *)(tag+4) = port;
-  *(uint16_t *)(tag+6) = circ_id;
+  *(uint64_t*)tag = conn_id;
+  *(uint16_t*)(tag+8) = circ_id;
 }
 
 /** Unpack <b>tag</b> into addr, port, and circ_id.
  */
 static void
-tag_unpack(const char *tag, uint32_t *addr, uint16_t *port, uint16_t *circ_id)
+tag_unpack(const char *tag, uint64_t *conn_id, uint16_t *circ_id)
 {
-  struct in_addr in;
-  char addrbuf[INET_NTOA_BUF_LEN];
-
-  *addr    = *(const uint32_t *)tag;
-  *port    = *(const uint16_t *)(tag+4);
-  *circ_id = *(const uint16_t *)(tag+6);
-
-  in.s_addr = htonl(*addr);
-  tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf));
-  log_debug(LD_OR,
-            "onion was from %s:%d, circ_id %d.", addrbuf, *port, *circ_id);
+  *conn_id = *(const uint64_t *)tag;
+  *circ_id = *(const uint16_t *)(tag+8);
 }
 
 /** Called when the onion key has changed and we need to spawn new
@@ -135,10 +125,10 @@
 {
   char success;
   char buf[LEN_ONION_RESPONSE];
-  uint32_t addr;
-  uint16_t port;
+  uint64_t conn_id;
   uint16_t circ_id;
-  or_connection_t *p_conn;
+  connection_t *tmp_conn;
+  or_connection_t *p_conn = NULL;
   circuit_t *circ;
 
   tor_assert(conn);
@@ -156,12 +146,13 @@
     connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);
 
     /* parse out the circ it was talking about */
-    tag_unpack(buf, &addr, &port, &circ_id);
+    tag_unpack(buf, &conn_id, &circ_id);
     circ = NULL;
-    /* (Here we use connection_or_exact_get_by_addr_port rather than
-     * get_by_identity_digest: we want a specific port here in
-     * case there are multiple connections.) */
-    p_conn = connection_or_exact_get_by_addr_port(addr,port);
+    tmp_conn = connection_get_by_global_id(conn_id);
+    if (tmp_conn && !tmp_conn->marked_for_close &&
+        tmp_conn->type == CONN_TYPE_OR)
+      p_conn = TO_OR_CONN(tmp_conn);
+
     if (p_conn)
       circ = circuit_get_by_circid_orconn(circ_id, p_conn);
 
@@ -468,7 +459,7 @@
       tor_free(onionskin);
       return -1;
     }
-    tag_pack(tag, circ->p_conn->_base.addr, circ->p_conn->_base.port,
+    tag_pack(tag, circ->p_conn->_base.global_identifier,
              circ->p_circ_id);
 
     cpuworker->state = CPUWORKER_STATE_BUSY_ONION;

Modified: tor/branches/tor-0_2_0-patches/src/or/or.h
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/or.h	2008-12-16 17:49:39 UTC (rev 17634)
+++ tor/branches/tor-0_2_0-patches/src/or/or.h	2008-12-16 22:53:24 UTC (rev 17635)
@@ -875,6 +875,9 @@
   /** Another connection that's connected to this one in lieu of a socket. */
   struct connection_t *linked_conn;
 
+  /** Unique identifier for this connection. */
+  uint64_t global_identifier;
+
   /* XXXX021 move this into a subtype. */
   struct evdns_server_port *dns_server_port;
 
@@ -982,10 +985,6 @@
   /** The reason why this connection is closing; passed to the controller. */
   uint16_t end_reason;
 
-  /** Quasi-global identifier for this connection; used for control.c */
-  /* XXXX NM This can get re-used after 2**32 streams */
-  uint32_t global_identifier;
-
   /** Bytes read since last call to control_event_stream_bandwidth_used() */
   uint32_t n_read;
 
@@ -2749,9 +2748,7 @@
   _connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1);
 }
 
-or_connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
-                                                   uint16_t port);
-edge_connection_t *connection_get_by_global_id(uint32_t id);
+connection_t *connection_get_by_global_id(uint64_t id);
 
 connection_t *connection_get_by_type(int type);
 connection_t *connection_get_by_type_purpose(int type, int purpose);



More information about the tor-commits mailing list