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

[or-cvs] r8527: [Needs review.] Add a BEGIN_DIR relay cell type for an easie (in tor/trunk: . doc src/or)



Author: nickm
Date: 2006-09-28 23:50:11 -0400 (Thu, 28 Sep 2006)
New Revision: 8527

Modified:
   tor/trunk/
   tor/trunk/ChangeLog
   tor/trunk/doc/TODO
   tor/trunk/doc/tor-spec.txt
   tor/trunk/src/or/connection_edge.c
   tor/trunk/src/or/or.h
   tor/trunk/src/or/relay.c
Log:
 r8997@Kushana:  nickm | 2006-09-28 23:40:22 -0400
 [Needs review.] Add a BEGIN_DIR relay cell type for an easier
 in-protocol way to connect to directory servers through Tor.
 Previously, clients could only connect to director servers over Tor
 from exit nodes, but couldn't get directory information anonymously
 from a non-exit cache without getting a directory server involved.
 
 This needs testing, and needs client-side code to actually exercise it.
 



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r8997] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2006-09-29 03:50:06 UTC (rev 8526)
+++ tor/trunk/ChangeLog	2006-09-29 03:50:11 UTC (rev 8527)
@@ -8,6 +8,11 @@
       support eventdns.
     - Specify and implement client-side SOCKS5 interface for reverse DNS
       lookups; see doc/socks-extensions.txt for full information.
+    - Add a BEGIN_DIR relay cell type for an easier in-protocol way to
+      connect to directory servers through Tor.  Previously, clients could
+      only connect to director servers over Tor from exit nodes, but couldn't
+      get directory information anonymously from a non-exit cache without
+      getting a directory server involved.
 
   o Minor features:
     - Check for name servers (like Earthlink's) that hijack failing DNS

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2006-09-29 03:50:06 UTC (rev 8526)
+++ tor/trunk/doc/TODO	2006-09-29 03:50:11 UTC (rev 8527)
@@ -52,7 +52,7 @@
 Items for 0.1.2.x:
   o re-enable blossom functionality: let tor servers decide if they
     will use local search when resolving, or not.
-N   - Document it.
+    o Document it.
   - enumerate events of important things that occur in tor, so vidalia can
     react.
 N   - Backend implementation
@@ -61,12 +61,14 @@
 N   - Specify general event system
 R   - Specify actual events.
 
-N - Have (and document) a BEGIN_DIR relay cell that means "Connect to your
+N . Have (and document) a BEGIN_DIR relay cell that means "Connect to your
     directory port."
-    - Specify
-    - Implement
+    o Specify
+    o Implement
     - Use for something, so we can be sure it works.
+    - Test and debug
 
+
 x - We should ship with a list of stable dir mirrors -- they're not
     trusted like the authorities, but they'll provide more robustness
     and diversity for bootstrapping clients.

Modified: tor/trunk/doc/tor-spec.txt
===================================================================
--- tor/trunk/doc/tor-spec.txt	2006-09-29 03:50:06 UTC (rev 8526)
+++ tor/trunk/doc/tor-spec.txt	2006-09-29 03:50:11 UTC (rev 8527)
@@ -624,6 +624,7 @@
         10 -- RELAY_DROP      [forward or backward]
         11 -- RELAY_RESOLVE   [forward]
         12 -- RELAY_RESOLVED  [backward]
+        13 -- RELAY_BEGIN_DIR [forward]
 
    Commands labelled as "forward" must only be sent by the originator
    of the circuit. Commands labelled as "backward" must only be sent by
@@ -710,6 +711,16 @@
    Relay RELAY_DROP cells are long-range dummies; upon receiving such
    a cell, the OR or OP must drop it.
 
+6.2.1. Opening a directory stream
+
+   If a Tor server is a directory server, it should respond to a
+   RELAY_BEGIN_DIR cell as if it had received a BEGIN cell requesting a
+   connection to its directory port.  RELAY_BEGIN_DIR cells ignore exit
+   policy, since the stream is local to the Tor process.
+
+   If the Tor server is not running a directory service, it should respond
+   with a REASON_NOTDIRECTORY RELAY_END cell.
+
 6.3. Closing streams
 
    When an anonymized TCP connection is closed, or an edge node
@@ -738,6 +749,8 @@
       12 -- REASON_CONNRESET      (Connection was unexpectedly reset)
       13 -- REASON_TORPROTOCOL    (Sent when closing connection because of
                                    Tor protocol violations.)
+      14 -- REASON_NOTDIRECTORY   (Client send RELAY_BEGIN_DIR to a
+                                   non-directory server.)
 
    (With REASON_EXITPOLICY, the 4-byte IPv4 address or 16-byte IPv6 address
    forms the optional data; no other reason currently has extra data.

Modified: tor/trunk/src/or/connection_edge.c
===================================================================
--- tor/trunk/src/or/connection_edge.c	2006-09-29 03:50:06 UTC (rev 8526)
+++ tor/trunk/src/or/connection_edge.c	2006-09-29 03:50:11 UTC (rev 8527)
@@ -29,6 +29,7 @@
 
 static int connection_ap_handshake_process_socks(edge_connection_t *conn);
 static int connection_ap_process_transparent(edge_connection_t *conn);
+static int connection_exit_connect_dir(edge_connection_t *exit_conn);
 
 /** An AP stream has failed/finished. If it hasn't already sent back
  * a socks reply, send one now (based on endreason). Also set
@@ -1813,33 +1814,41 @@
   }
 
   relay_header_unpack(&rh, cell->payload);
-
-  if (!memchr(cell->payload+RELAY_HEADER_SIZE, 0, rh.length)) {
-    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
-           "Relay begin cell has no \\0. Dropping.");
-    return 0;
-  }
-  if (parse_addr_port(LOG_PROTOCOL_WARN, cell->payload+RELAY_HEADER_SIZE,
-                      &address,NULL,&port)<0) {
-    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
-           "Unable to parse addr:port in relay begin cell. Dropping.");
-    return 0;
-  }
-  if (port==0) {
-    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
-           "Missing port in relay begin cell. Dropping.");
-    tor_free(address);
-    return 0;
-  }
+  if (rh.command == RELAY_COMMAND_BEGIN) {
+    if (!memchr(cell->payload+RELAY_HEADER_SIZE, 0, rh.length)) {
+      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+             "Relay begin cell has no \\0. Dropping.");
+      return 0;
+    }
+    if (parse_addr_port(LOG_PROTOCOL_WARN, cell->payload+RELAY_HEADER_SIZE,
+                        &address,NULL,&port)<0) {
+      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+             "Unable to parse addr:port in relay begin cell. Dropping.");
+      return 0;
+    }
+    if (port==0) {
+      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+             "Missing port in relay begin cell. Dropping.");
+      tor_free(address);
+      return 0;
+    }
 #if 0
-  if (!tor_strisprint(address)) {
-    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
-           "Non-printing characters in address %s in relay "
-           "begin cell. Dropping.", escaped(address));
-    tor_free(address);
+    if (!tor_strisprint(address)) {
+      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+             "Non-printing characters in address %s in relay "
+             "begin cell. Dropping.", escaped(address));
+      tor_free(address);
+      return 0;
+    }
+#endif
+  } else if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
+    or_options_t *options = get_options();
+    address = tor_strdup("127.0.0.1");
+    port = options->DirPort; /* not actually used. */
+  } else {
+    log_warn(LD_BUG, "Got an unexpected command %d", (int)rh.command);
     return 0;
   }
-#endif
 
   log_debug(LD_EXIT,"Creating new exit connection.");
   n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
@@ -1851,6 +1860,15 @@
   n_stream->package_window = STREAMWINDOW_START;
   n_stream->deliver_window = STREAMWINDOW_START;
 
+  if (rh.command == RELAY_COMMAND_BEGIN_DIR &&
+      (!get_options()->DirPort || circ->purpose != CIRCUIT_PURPOSE_OR)) {
+    connection_edge_end(n_stream, END_STREAM_REASON_NOTDIRECTORY,
+                        n_stream->cpath_layer);
+    connection_free(TO_CONN(n_stream));
+    tor_free(address);
+    return 0;
+  }
+
   if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
     origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
     log_debug(LD_REND,"begin is for rendezvous. configuring stream.");
@@ -1898,6 +1916,13 @@
   }
   log_debug(LD_EXIT,"about to start the dns_resolve().");
 
+  if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
+    n_stream->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
+    n_stream->on_circuit = circ;
+    TO_OR_CIRCUIT(circ)->n_streams = n_stream;
+    return connection_exit_connect_dir(n_stream);
+  }
+
   /* send it off to the gethostbyname farm */
   switch (dns_resolve(n_stream, NULL)) {
     case 1: /* resolve worked */
@@ -2067,6 +2092,83 @@
   }
 }
 
+/** Given an exit conn that should attach to us as a directory server, open a
+ * bridge connection with a socketpair, create a new directory conn, and join
+ * them together.  Return 0 on success (or if there was an error we could send
+ * back an end cell for).  Return -1 if the circuit needs to be torn down.
+ * Either connects exit_conn, or frees it, or marks it as appropriate.
+ */
+static int
+connection_exit_connect_dir(edge_connection_t *exit_conn)
+{
+  int fd[2];
+  int err;
+  dir_connection_t *dir_conn = NULL;
+
+  log_info(LD_EXIT, "Opening dir bridge");
+
+  if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) < 0) {
+    log_warn(LD_NET,
+             "Couldn't construct socketpair (%s). Network down? Delaying.",
+             tor_socket_strerror(-err));
+    connection_edge_end(exit_conn, END_STREAM_REASON_RESOURCELIMIT,
+                        exit_conn->cpath_layer);
+    connection_free(TO_CONN(exit_conn));
+    return 0;
+  }
+
+  tor_assert(fd[0] >= 0);
+  tor_assert(fd[1] >= 0);
+
+  set_socket_nonblocking(fd[0]);
+  set_socket_nonblocking(fd[1]);
+
+  exit_conn->_base.s = fd[0];
+  exit_conn->_base.state = EXIT_CONN_STATE_OPEN;
+
+  dir_conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR));
+  dir_conn->_base.s = fd[1];
+
+  dir_conn->_base.addr = 0x7f000001;
+  dir_conn->_base.port = 0;
+  dir_conn->_base.address = tor_strdup("Tor network");
+  dir_conn->_base.type = CONN_TYPE_DIR;
+  dir_conn->_base.purpose = DIR_PURPOSE_SERVER;
+  dir_conn->_base.state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
+
+  if (connection_add(TO_CONN(exit_conn))<0) {
+    connection_edge_end(exit_conn, END_STREAM_REASON_RESOURCELIMIT,
+                        exit_conn->cpath_layer);
+    /* XXXX Have I got the free/mark distinction right? -NM */
+    connection_free(TO_CONN(exit_conn));
+    connection_free(TO_CONN(dir_conn));
+    return 0;
+  }
+
+  if (connection_add(TO_CONN(dir_conn))<0) {
+    connection_edge_end(exit_conn, END_STREAM_REASON_RESOURCELIMIT,
+                        exit_conn->cpath_layer);
+    connection_close_immediate(TO_CONN(exit_conn));
+    connection_mark_for_close(TO_CONN(exit_conn));
+    connection_free(TO_CONN(dir_conn));
+    return 0;
+  }
+
+  connection_start_reading(TO_CONN(dir_conn));
+  connection_start_reading(TO_CONN(exit_conn));
+
+  if (connection_edge_send_command(exit_conn,
+                                   circuit_get_by_edge_conn(exit_conn),
+                                   RELAY_COMMAND_CONNECTED, NULL, 0,
+                                   exit_conn->cpath_layer) < 0) {
+    connection_mark_for_close(TO_CONN(exit_conn));
+    connection_mark_for_close(TO_CONN(dir_conn));
+    return 0;
+  }
+
+  return 0;
+}
+
 /** Return 1 if <b>conn</b> is a rendezvous stream, or 0 if
  * it is a general stream.
  */

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2006-09-29 03:50:06 UTC (rev 8526)
+++ tor/trunk/src/or/or.h	2006-09-29 03:50:11 UTC (rev 8527)
@@ -450,6 +450,7 @@
 #define RELAY_COMMAND_DROP 10
 #define RELAY_COMMAND_RESOLVE 11
 #define RELAY_COMMAND_RESOLVED 12
+#define RELAY_COMMAND_BEGIN_DIR 13
 
 #define RELAY_COMMAND_ESTABLISH_INTRO 32
 #define RELAY_COMMAND_ESTABLISH_RENDEZVOUS 33
@@ -474,6 +475,7 @@
 #define END_STREAM_REASON_RESOURCELIMIT 11
 #define END_STREAM_REASON_CONNRESET 12
 #define END_STREAM_REASON_TORPROTOCOL 13
+#define END_STREAM_REASON_NOTDIRECTORY 14
 
 /* These high-numbered end reasons are not part of the official spec,
  * and are not intended to be put in relay end cells. They are here

Modified: tor/trunk/src/or/relay.c
===================================================================
--- tor/trunk/src/or/relay.c	2006-09-29 03:50:06 UTC (rev 8526)
+++ tor/trunk/src/or/relay.c	2006-09-29 03:50:11 UTC (rev 8527)
@@ -944,6 +944,7 @@
 //      log_info(domain,"Got a relay-level padding cell. Dropping.");
       return 0;
     case RELAY_COMMAND_BEGIN:
+    case RELAY_COMMAND_BEGIN_DIR:
       if (layer_hint &&
           circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) {
         log_warn(LD_APP,"relay begin request unsupported at AP. Dropping.");