瀏覽代碼

r16282@catbus: nickm | 2007-10-30 14:28:58 -0400
Implement lots of proposal 105. None of it is enabled yet.


svn:r12285

Nick Mathewson 17 年之前
父節點
當前提交
57f7c852f8
共有 6 個文件被更改,包括 220 次插入39 次删除
  1. 11 6
      doc/TODO
  2. 5 2
      doc/spec/proposals/105-handshake-revision.txt
  3. 135 30
      src/or/command.c
  4. 61 1
      src/or/connection_or.c
  5. 7 0
      src/or/or.h
  6. 1 0
      src/or/router.c

+ 11 - 6
doc/TODO

@@ -42,16 +42,21 @@ Things we'd like to do in 0.2.0.x:
     - 105+TLS, if possible.
     - 105+TLS, if possible.
       - 105 only
       - 105 only
         - Need to get a finished proposal 105
         - Need to get a finished proposal 105
-        - "Pick a version" function
+        o "Pick a version" function
         - Have a 'waiting_for_version' state.
         - Have a 'waiting_for_version' state.
-        - Store version in or_connection_t.
+        o Store version in or_connection_t.
-        - Generate netinfo cells
+        o Generate netinfo cells
-        - Accept netinfo cells
+        o Accept netinfo cells
+        . Add an is_canonical field to or_connection_t.
+          o Set it when we get a match in the netinfo.
+          o Set it when we get a match for a routerinfo we have.
+          - Don't extend a circuit over a noncanonical connection with
+            mismatched address.
         - Version negotiation: send a version cell and enter
         - Version negotiation: send a version cell and enter
           waiting-for-version; when version cell arrives, pick version
           waiting-for-version; when version cell arrives, pick version
           and send netinfo and be "open".
           and send netinfo and be "open".
-        - On netinfo, warn if there's skew from a server.
+        o On netinfo, warn if there's skew from a server.
-        - Handle IP addresses in netinfo properly.
+        - Learn our outgoing IP address from netinfo cells?
       - TLS only
       - TLS only
         - Need to get a finished TLS normalization proposal
         - Need to get a finished TLS normalization proposal
         - Revised authentication.
         - Revised authentication.

+ 5 - 2
doc/spec/proposals/105-handshake-revision.txt

@@ -4,7 +4,7 @@ Version: $Revision$
 Last-Modified: $Date$
 Last-Modified: $Date$
 Author: Nick Mathewson, Roger Dingledine
 Author: Nick Mathewson, Roger Dingledine
 Created:
 Created:
-Status: Open
+Status: Accepted
 
 
 Overview:
 Overview:
 
 
@@ -120,7 +120,7 @@ Proposal:
    When a Tor connection is established, both parties normally send a
    When a Tor connection is established, both parties normally send a
    VERSIONS cell before sending any other cells.  (But see below.)
    VERSIONS cell before sending any other cells.  (But see below.)
 
 
-         VersionsLen          [1 byte]
+         VersionsLen          [2 byte]
          Versions             [VersionsLen bytes]
          Versions             [VersionsLen bytes]
 
 
    "Versions" is a sequence of VersionsLen bytes.  Each value between 1 and
    "Versions" is a sequence of VersionsLen bytes.  Each value between 1 and
@@ -157,6 +157,8 @@ Proposal:
    The VERSIONS cell must be sent as a v1 cell (2 bytes of circuitID, 1
    The VERSIONS cell must be sent as a v1 cell (2 bytes of circuitID, 1
    byte of command, 509 bytes of payload).
    byte of command, 509 bytes of payload).
 
 
+   [NOTE: The VERSIONS cell is assigned the command number 7.]
+
 2.2. MITM-prevention and time checking
 2.2. MITM-prevention and time checking
 
 
    If we negotiate a v2 connection or higher, the second cell we send SHOULD
    If we negotiate a v2 connection or higher, the second cell we send SHOULD
@@ -195,6 +197,7 @@ Proposal:
    given in the EXTEND cell is not listed in the NETINFO cell, the first
    given in the EXTEND cell is not listed in the NETINFO cell, the first
    party SHOULD close the connection as a likely MITM attack.
    party SHOULD close the connection as a likely MITM attack.
 
 
+   [NOTE: The NETINFO cell is assigned the command number 8.]
 
 
 Discussion: Versions versus feature lists
 Discussion: Versions versus feature lists
 
 

+ 135 - 30
src/or/command.c

@@ -25,12 +25,16 @@ uint64_t stats_n_create_cells_processed = 0;
 uint64_t stats_n_created_cells_processed = 0;
 uint64_t stats_n_created_cells_processed = 0;
 uint64_t stats_n_relay_cells_processed = 0;
 uint64_t stats_n_relay_cells_processed = 0;
 uint64_t stats_n_destroy_cells_processed = 0;
 uint64_t stats_n_destroy_cells_processed = 0;
+uint64_t stats_n_versions_cells_processed = 0;
+uint64_t stats_n_netinfo_cells_processed = 0;
 
 
-/* These are the main four functions for processing cells */
+/* These are the main functions for processing cells */
 static void command_process_create_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_create_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_created_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_created_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_relay_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_relay_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
 static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
+static void command_process_versions_cell(cell_t *cell, or_connection_t *conn);
+static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn);
 
 
 #ifdef KEEP_TIMING_STATS
 #ifdef KEEP_TIMING_STATS
 /** This is a wrapper function around the actual function that processes the
 /** This is a wrapper function around the actual function that processes the
@@ -99,6 +103,16 @@ command_process_cell(cell_t *cell, or_connection_t *conn)
   }
   }
 #endif
 #endif
 
 
+#ifdef KEEP_TIMING_STATS
+#define PROCESS_CELL(tp, cl, cn) STMT_BEGIN {                   \
+    ++num ## tp;                                                \
+    command_time_process_cell(cl, cn, & tp ## time ,            \
+                              command_process_ ## tp ## _cell);  \
+  } STMT_END
+#else
+#define PROCESS_CELL(tp, cl, cn) command_process_ ## tp ## _cell(cl, cn)
+#endif
+
   switch (cell->command) {
   switch (cell->command) {
     case CELL_PADDING:
     case CELL_PADDING:
       ++stats_n_padding_cells_processed;
       ++stats_n_padding_cells_processed;
@@ -107,47 +121,31 @@ command_process_cell(cell_t *cell, or_connection_t *conn)
     case CELL_CREATE:
     case CELL_CREATE:
     case CELL_CREATE_FAST:
     case CELL_CREATE_FAST:
       ++stats_n_create_cells_processed;
       ++stats_n_create_cells_processed;
-#ifdef KEEP_TIMING_STATS
+      PROCESS_CELL(create, cell, conn);
-      ++num_create;
-      command_time_process_cell(cell, conn, &create_time,
-                                command_process_create_cell);
-#else
-      command_process_create_cell(cell, conn);
-#endif
       break;
       break;
     case CELL_CREATED:
     case CELL_CREATED:
     case CELL_CREATED_FAST:
     case CELL_CREATED_FAST:
       ++stats_n_created_cells_processed;
       ++stats_n_created_cells_processed;
-#ifdef KEEP_TIMING_STATS
+      PROCESS_CELL(created, cell, conn);
-      ++num_created;
-      command_time_process_cell(cell, conn, &created_time,
-                                command_process_created_cell);
-#else
-      command_process_created_cell(cell, conn);
-#endif
       break;
       break;
     case CELL_RELAY:
     case CELL_RELAY:
       ++stats_n_relay_cells_processed;
       ++stats_n_relay_cells_processed;
-#ifdef KEEP_TIMING_STATS
+      PROCESS_CELL(relay, cell, conn);
-      ++num_relay;
-      command_time_process_cell(cell, conn, &relay_time,
-                                command_process_relay_cell);
-#else
-      command_process_relay_cell(cell, conn);
-#endif
       break;
       break;
     case CELL_DESTROY:
     case CELL_DESTROY:
       ++stats_n_destroy_cells_processed;
       ++stats_n_destroy_cells_processed;
-#ifdef KEEP_TIMING_STATS
+      PROCESS_CELL(destroy, cell, conn);
-      ++num_destroy;
+      break;
-      command_time_process_cell(cell, conn, &destroy_time,
+    case CELL_VERSIONS:
-                                command_process_destroy_cell);
+      ++stats_n_versions_cells_processed;
-#else
+      PROCESS_CELL(versions, cell, conn);
-      command_process_destroy_cell(cell, conn);
+      break;
-#endif
+    case CELL_NETINFO:
+      ++stats_n_netinfo_cells_processed;
+      PROCESS_CELL(netinfo, cell, conn);
       break;
       break;
     default:
     default:
-      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+      log_fn(LOG_INFO, LD_PROTOCOL,
              "Cell of unknown type (%d) received. Dropping.", cell->command);
              "Cell of unknown type (%d) received. Dropping.", cell->command);
       break;
       break;
   }
   }
@@ -389,3 +387,110 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
   }
   }
 }
 }
 
 
+/** Process a 'versions' cell.  The current link protocol version must be 0
+ * to indicate that no version has yet been negotiated. DOCDOC say more. */
+static void
+command_process_versions_cell(cell_t *cell, or_connection_t *conn)
+{
+  uint16_t versionslen;
+  int highest_supported_version = 0;
+  const char *cp, *end;
+  if (conn->link_proto != 0) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR,
+           "Received a VERSIONS cell on a connection with its version "
+           "already set to %d; dropping", (int) conn->link_proto);
+    return;
+  }
+  versionslen = ntohs(get_uint16(cell->payload));
+  end = cell->payload + 2 + versionslen;
+  if (end > cell->payload + CELL_PAYLOAD_SIZE)
+    end = cell->payload + CELL_PAYLOAD_SIZE; /*XXXX020 warn?*/
+  for (cp = cell->payload + 2; cp < end; ++cp) {
+    uint8_t v = *cp;
+    if (v == 1) {
+      if (v > highest_supported_version)
+        highest_supported_version = v;
+    }
+  }
+  if (!versionslen) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR,
+           "Couldn't find a version in common; defaulting to v1.");
+    /*XXXX020 or just break the connection?*/
+    conn->link_proto = 1;
+    return;
+  }
+}
+
+/** Process a 'netinfo' cell. DOCDOC say more. */
+static void
+command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
+{
+  time_t timestamp;
+  uint8_t my_addr_type;
+  uint8_t my_addr_len;
+  const char *my_addr_ptr;
+  const char *cp, *end;
+  uint8_t n_other_addrs;
+  time_t now = time(NULL);
+
+  /*XXXX020 reject duplicat netinfos. */
+
+  if (conn->link_proto < 2) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR,
+           "Received a NETINFO cell on %s connection; dropping.",
+           conn->link_proto == 0 ? "non-versioned" : "a v1");
+    return;
+  }
+  /* Decode the cell. */
+  timestamp = ntohl(get_uint32(cell->payload));
+  my_addr_type = (uint8_t) cell->payload[4];
+  my_addr_len = (uint8_t) cell->payload[5];
+  my_addr_ptr = cell->payload + 6;
+  /* Possibly learn my address. XXXX020 */
+  end = cell->payload + CELL_PAYLOAD_SIZE;
+  cp = cell->payload + 6 + my_addr_len;
+  if (cp >= end) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR,
+           "Address too long in netinfo cell; dropping.");
+    return;
+  }
+
+  /*XXXX020 magic number 3600 */
+  if (abs(timestamp - now) > 3600 &&
+      router_get_by_digest(conn->identity_digest)) {
+    long delta = now - timestamp;
+    char dbuf[64];
+    /*XXXX020 not always warn!*/
+    format_time_interval(dbuf, sizeof(dbuf), delta);
+    log_fn(LOG_WARN, LD_HTTP, "Received NETINFO cell with skewed time from "
+           "server at %s:%d.  It seems that our clock is %s by %s, or "
+           "that theirs is %s. Tor requires an accurate clock to work: "
+           "please check your time and date settings.",
+           conn->_base.address, (int)conn->_base.port,
+           delta>0 ? "ahead" : "behind", dbuf,
+           delta>0 ? "behind" : "ahead");
+    control_event_general_status(LOG_WARN,
+                                 "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d",
+                                 delta, conn->_base.address, conn->_base.port);
+  }
+
+  n_other_addrs = (uint8_t) *cp++;
+  while (n_other_addrs && cp < end-2) {
+    /* Consider all the other addresses; if any matches, this connection is
+     * "canonical." */
+    uint8_t other_addr_type = (uint8_t) *cp++;
+    uint8_t other_addr_len = (uint8_t) *cp++;
+    if (cp + other_addr_len >= end)
+      break; /*XXXX020 protocol warn. */
+    if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) {
+      uint32_t addr = ntohl(get_uint32(cp));
+      if (addr == conn->real_addr) {
+        conn->is_canonical = 1;
+        break;
+      }
+    }
+    cp += other_addr_len;
+    --n_other_addrs;
+  }
+}
+

+ 61 - 1
src/or/connection_or.c

@@ -356,11 +356,16 @@ connection_or_init_conn_from_address(or_connection_t *conn,
   connection_or_set_identity_digest(conn, id_digest);
   connection_or_set_identity_digest(conn, id_digest);
   conn->_base.addr = addr;
   conn->_base.addr = addr;
   conn->_base.port = port;
   conn->_base.port = port;
+  conn->real_addr = addr;
   if (r) {
   if (r) {
+    if (conn->_base.addr == r->addr)
+      conn->is_canonical = 1;
     if (!started_here) {
     if (!started_here) {
       /* Override the addr/port, so our log messages will make sense.
       /* Override the addr/port, so our log messages will make sense.
        * This is dangerous, since if we ever try looking up a conn by
        * This is dangerous, since if we ever try looking up a conn by
        * its actual addr/port, we won't remember. Careful! */
        * its actual addr/port, we won't remember. Careful! */
+      /* XXXX020 this is stupid, and it's the reason we need real_addr to
+       * track is_canonical properly. */
       conn->_base.addr = r->addr;
       conn->_base.addr = r->addr;
       conn->_base.port = r->or_port;
       conn->_base.port = r->or_port;
     }
     }
@@ -740,6 +745,8 @@ connection_tls_finish_handshake(or_connection_t *conn)
   }
   }
   connection_watch_events(TO_CONN(conn), EV_READ);
   connection_watch_events(TO_CONN(conn), EV_READ);
   circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
   circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
+
+  conn->link_proto = 1; /* Version negotiation not yet enabled.XXX020 */
   return 0;
   return 0;
 }
 }
 
 
@@ -773,7 +780,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
   char buf[CELL_NETWORK_SIZE];
   char buf[CELL_NETWORK_SIZE];
   cell_t cell;
   cell_t cell;
 
 
-loop:
+ loop:
   log_debug(LD_OR,
   log_debug(LD_OR,
             "%d: starting, inbuf_datalen %d (%d pending in tls object).",
             "%d: starting, inbuf_datalen %d (%d pending in tls object).",
             conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
             conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
@@ -825,3 +832,56 @@ connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason)
   return 0;
   return 0;
 }
 }
 
 
+/** DOCDOC */
+static int
+connection_or_send_versions(or_connection_t *conn)
+{
+  cell_t cell;
+  uint8_t versions[] = { 1 };
+  int n_versions = sizeof(versions) / sizeof(uint8_t);
+  int i;
+  memset(&cell, 0, sizeof(cell_t));
+  cell.command = CELL_VERSIONS;
+  set_uint16(cell.payload, htons(n_versions));
+  for (i = 0; i < n_versions; ++i) {
+    uint8_t v = versions[i];
+    tor_assert(v > 0 && v < 128);
+    cell.payload[2+i] = v;
+  }
+
+  connection_or_write_cell_to_buf(&cell, conn);
+}
+
+/** DOCDOC */
+static int
+connection_or_send_netinfo(or_connection_t *conn)
+{
+  cell_t cell;
+  time_t now = time(NULL);
+  routerinfo_t *me;
+
+  memset(&cell, 0, sizeof(cell_t));
+  cell.command = CELL_NETINFO;
+
+  /* Their address. */
+  set_uint32(cell.payload, htonl(now));
+  cell.payload[4] = RESOLVED_TYPE_IPV4;
+  cell.payload[5] = 4;
+  set_uint32(cell.payload+6, htonl(conn->_base.addr));
+
+  /* My address. */
+  if ((me = router_get_my_routerinfo())) {
+    cell.payload[10] = 1; /* only one address is supported. */
+    cell.payload[11] = RESOLVED_TYPE_IPV4;
+    cell.payload[12] = 4;
+    set_uint32(cell.payload+13, htonl(me->addr));
+  } else {
+    cell.payload[10] = 0;
+  }
+
+  connection_or_write_cell_to_buf(&cell, conn);
+
+  /*XXXX020 remove these once we send netinfo and versions cells. */
+  (void) connection_or_send_netinfo;
+  (void) connection_or_send_versions;
+}

+ 7 - 0
src/or/or.h

@@ -651,6 +651,8 @@ typedef enum {
 #define CELL_DESTROY 4
 #define CELL_DESTROY 4
 #define CELL_CREATE_FAST 5
 #define CELL_CREATE_FAST 5
 #define CELL_CREATED_FAST 6
 #define CELL_CREATED_FAST 6
+#define CELL_VERSIONS 7
+#define CELL_NETINFO 8
 
 
 /** How long to test reachability before complaining to the user. */
 /** How long to test reachability before complaining to the user. */
 #define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
 #define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
@@ -868,9 +870,14 @@ typedef struct or_connection_t {
    * recent, we can rate limit it further. */
    * recent, we can rate limit it further. */
   time_t client_used;
   time_t client_used;
 
 
+  uint32_t real_addr; /**DOCDOC */
+
   circ_id_type_t circ_id_type:2; /**< When we send CREATE cells along this
   circ_id_type_t circ_id_type:2; /**< When we send CREATE cells along this
                                   * connection, which half of the space should
                                   * connection, which half of the space should
                                   * we use? */
                                   * we use? */
+  unsigned int is_canonical; /**< DOCDOC */
+  uint8_t link_proto; /**< What protocol version are we using? 0 for
+                       * "none negotiated yet." */
   uint16_t next_circ_id; /**< Which circ_id do we try to use next on
   uint16_t next_circ_id; /**< Which circ_id do we try to use next on
                           * this connection?  This is always in the
                           * this connection?  This is always in the
                           * range 0..1<<15-1. */
                           * range 0..1<<15-1. */

+ 1 - 0
src/or/router.c

@@ -1570,6 +1570,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
   result = tor_snprintf(s, maxlen,
   result = tor_snprintf(s, maxlen,
                     "router %s %s %d 0 %d\n"
                     "router %s %s %d 0 %d\n"
                     "platform %s\n"
                     "platform %s\n"
+                    "opt protocols Link 1 Circuit 1\n"
                     "published %s\n"
                     "published %s\n"
                     "opt fingerprint %s\n"
                     "opt fingerprint %s\n"
                     "uptime %ld\n"
                     "uptime %ld\n"