Explorar el Código

Add rendezvous-related metadata and code to circuits. Initially, we
thought that a complicated adjunct structure would be necessary, but
it doesn't look that way anymore.

Of course, I might have forgotten something.


svn:r1396

Nick Mathewson hace 21 años
padre
commit
0ba9ab5fb0
Se han modificado 4 ficheros con 87 adiciones y 20 borrados
  1. 11 11
      doc/TODO
  2. 40 1
      src/or/circuit.c
  3. 1 0
      src/or/command.c
  4. 35 8
      src/or/or.h

+ 11 - 11
doc/TODO

@@ -91,25 +91,25 @@ Short-term:
 
 Rendezvous service:
         o Design and specify protocol
-        - Possible preliminary refactoring:
-            - Should we break circuits up into "circuit-with-cpath" and
+        o Possible preliminary refactoring:
+            o Should we break circuits up into "circuit-with-cpath" and
               "circuit-without-cpath"?
-            - We need a way to tag circuits as special-purpose circuits for:
-                - Connecting from Bob's OP to the introduction point
-                - Sending introduction requests from the IPoint to Bob
-                - Connecting from Alice to the rendezvous point for Bob
-                - Connecting from Bob to the rendezvous point for Alice
-                - Waiting at a rendezvous point to be joined
-                - Joined to another circuit at the rendezvous point.
+            o We need a way to tag circuits as special-purpose circuits for:
+                o Connecting from Bob's OP to the introduction point
+                o Sending introduction requests from the IPoint to Bob
+                o Connecting from Alice to the rendezvous point for Bob
+                o Connecting from Bob to the rendezvous point for Alice
+                o Waiting at a rendezvous point to be joined
+                o Joined to another circuit at the rendezvous point.
               (We should also enumerate all the states that these operations
               can be in.) [NM]
-            - Add circuit metadata [NM] 3 hours
+            o Add circuit metadata [NM] 3 hours
         - Code to configure hidden services [NM] 4 hours
         - Service descriptors
             - OPs need to maintain identity keys for hidden services [NM] 1 hour
             - Code to generate and parse service descriptors [NM] 4 hours
         - Advertisement
-            - Generate y.onion hostnames [NM] 1 hour
+            . Generate y.onion hostnames [NM] 1 hour
             - Code to do an HTTP connection over Tor from within Tor [RD]
             - Publish service descriptors to directory [RD]
             - Directory accepts and remembers service descriptors, and

+ 40 - 1
src/or/circuit.c

@@ -127,6 +127,10 @@ void circuit_free(circuit_t *circ) {
     tor_free(circ->build_state->chosen_exit);
   tor_free(circ->build_state);
   circuit_free_cpath(circ->cpath);
+  if (circ->rend_splice) {
+    circ->rend_splice->rend_splice = NULL;
+  }
+
   memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
   free(circ);
 }
@@ -290,6 +294,24 @@ circuit_t *circuit_get_newest(connection_t *conn, int must_be_open) {
   return NULL;
 }
 
+/* Return the first circuit in global_circuitlist whose rend_service
+ * field is servid and whose purpose is purpose. Returns NULL if no circuit
+ * is found.
+ */
+circuit_t *circuit_get_by_service_and_purpose(const char *servid, int purpose)
+{
+  circuit_t *circ;
+  for(circ=global_circuitlist; circ; circ = circ->next) {
+    if (circ->marked_for_close)
+      continue;
+    if (circ->purpose != purpose)
+      continue;
+    if (!memcmp(circ->rend_service, servid, REND_COOKIE_LEN))
+      return circ;
+  }
+  return NULL;
+}
+
 #define MIN_SECONDS_BEFORE_EXPIRING_CIRC 10
 /* circuits that were born at the end of their second might be expired
  * after 10.1 seconds; circuits born at the beginning might be expired
@@ -726,8 +748,13 @@ int _circuit_mark_for_close(circuit_t *circ) {
      * circuit-building failed immediately, it won't be set yet. */
     circuit_increment_failure_count();
   }
-
   circ->marked_for_close = 1;
+
+  if (circ->rend_splice && !circ->rend_splice->marked_for_close) {
+    /* do this after marking this circuit, to avoid infinite recursion. */
+    circuit_mark_for_close(circ->rend_splice);
+    circ->rend_splice = NULL;
+  }
   return 0;
 }
 
@@ -989,6 +1016,7 @@ int circuit_establish_circuit(void) {
   circ = circuit_new(0, NULL); /* sets circ->p_circ_id and circ->p_conn */
   circ->state = CIRCUIT_STATE_OR_WAIT;
   circ->build_state = onion_new_cpath_build_state();
+  circ->purpose = CIRCUIT_PURPOSE_C_GENERAL;
 
   if (! circ->build_state) {
     log_fn(LOG_INFO,"Generating cpath length failed.");
@@ -1348,6 +1376,8 @@ void assert_circuit_ok(const circuit_t *c)
 
   assert(c);
   assert(c->magic == CIRCUIT_MAGIC);
+  assert(c->purpose >= _CIRCUIT_PURPOSE_MIN &&
+         c->purpose <= _CIRCUIT_PURPOSE_MAX);
 
   if (c->n_conn)
     assert(c->n_conn->type == CONN_TYPE_OR);
@@ -1376,6 +1406,15 @@ void assert_circuit_ok(const circuit_t *c)
   if (c->cpath) {
 //XXX    assert_cpath_ok(c->cpath);
   }
+  if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) {
+    if (!c->marked_for_close) {
+      assert(c->rend_splice);
+      assert(c->rend_splice->rend_splice == c);
+    }
+    assert(c->rend_splice != c);
+  } else {
+    assert(!c->rend_splice);
+  }
 }
 
 /*

+ 1 - 0
src/or/command.c

@@ -103,6 +103,7 @@ static void command_process_create_cell(cell_t *cell, connection_t *conn) {
 
   circ = circuit_new(cell->circ_id, conn);
   circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
+  circ->purpose = CIRCUIT_PURPOSE_INTERMEDIATE;
 
   memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
 

+ 35 - 8
src/or/or.h

@@ -188,19 +188,17 @@
 
 #define _CIRCUIT_PURPOSE_MIN 1
 /* these circuits were initiated elsewhere */
-#define CIRCUIT_PURPOSE_INTERMEDIATE 1 /* normal circuit */
-#define CIRCUIT_PURPOSE_INTRO_POINT 2 /* from Bob, waiting for intro from Alices */
-#define CIRCUIT_PURPOSE_REND_POINT_WAITING 3 /* from Alice, waiting for Bob */
-#define CIRCUIT_PURPOSE_REND_ESTABLISHED 4 /* both circuits have this purpose */
-/* these circuits were initiated at this node */
+#define CIRCUIT_PURPOSE_INTERMEDIATE 1 /* normal circuit, at OR. */
+#define CIRCUIT_PURPOSE_INTRO_POINT 2 /* At OR, from Bob, waiting for intro from Alices */
+#define CIRCUIT_PURPOSE_REND_POINT_WAITING 3 /* At OR, from Alice, waiting for Bob */
+#define CIRCUIT_PURPOSE_REND_ESTABLISHED 4 /* At OR, both circuits have this purpose */
+/* these circuits originate at this node */
 #define CIRCUIT_PURPOSE_C_GENERAL 5 /* normal circuit, with cpath */
 #define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 6 /* at Bob, waiting for introductions */
 #define CIRCUIT_PURPOSE_C_INTRODUCING 7 /* at Alice, connecting to intro point */
 #define CIRCUIT_PURPOSE_C_ESTABLISH_REND 8 /* at Alice, waiting for Bob */
 #define CIRCUIT_PURPOSE_S_RENDEZVOUSING 9 /* at Bob, connecting to rend point */
-#define CIRCUIT_PURPOSE_S_UPLOAD_SERVICE_DESC 10
-#define CIRCUIT_PURPOSE_C_FETCH_SERVICE_DESC 11
-#define _CIRCUIT_PURPOSE_MAX 11
+#define _CIRCUIT_PURPOSE_MAX 9
 
 #define RELAY_COMMAND_BEGIN 1
 #define RELAY_COMMAND_DATA 2
@@ -473,6 +471,7 @@ struct crypt_path_t {
 #define DH_KEY_LEN CRYPTO_DH_SIZE
 #define ONIONSKIN_CHALLENGE_LEN (16+DH_KEY_LEN)
 #define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+20)
+#define REND_COOKIE_LEN CRYPTO_SHA1_DIGEST_LEN
 
 typedef struct crypt_path_t crypt_path_t;
 
@@ -517,12 +516,35 @@ struct circuit_t {
   time_t timestamp_dirty; /* when the circuit was first used, or 0 if clean */
 
   uint8_t state;
+  uint8_t purpose;
+
+  /*
+   * holds hash of location-hidden service's PK if purpose is INTRO_POINT
+   *    or S_ESTABLISH_INTRO or S_RENDEZVOUSING;
+   * holds y portion of y.onion (zero-padded) if purpose is C_INTRODUCING or
+   *    C_ESTABLISH_REND, or is a C_GENERAL for a hidden service.
+   * filled with zeroes otherwise.
+   */
+  char rend_service[CRYPTO_SHA1_DIGEST_LEN];
+  /* Holds rendezvous cookie if purpose is REND_POINT_WAITING or
+   * S_RENDEZVOUSING.  Filled with zeroes otherwise.
+  */
+  char rend_cookie[REND_COOKIE_LEN];
+
+  /* Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
+   * is not marked for close. */
+  struct circuit_t *rend_splice;
 
   struct circuit_t *next;
 };
 
 typedef struct circuit_t circuit_t;
 
+typedef struct circuit_data_rend_point_t {
+  /* for CIRCUIT_PURPOSE_INTRO_POINT (at OR, from Bob, waiting for intro) */
+  char rend_cookie[20];
+} circuit_data_intro_point_t;
+
 typedef struct {
   char *LogLevel;
   char *LogFile;
@@ -630,6 +652,7 @@ int _circuit_mark_for_close(circuit_t *circ);
 circuit_t *circuit_get_by_circ_id_conn(uint16_t circ_id, connection_t *conn);
 circuit_t *circuit_get_by_conn(connection_t *conn);
 circuit_t *circuit_get_newest(connection_t *conn, int must_be_open);
+circuit_t *circuit_get_by_service_and_purpose(const char *servid, int purpose);
 
 void circuit_expire_building(void);
 int circuit_count_building(void);
@@ -938,6 +961,10 @@ void rep_hist_note_extend_succeeded(const char *from_name,
 void rep_hist_note_extend_failed(const char *from_name, const char *to_name);
 void rep_hist_dump_stats(time_t now, int severity);
 
+/********************************* rendcommon.c ***************************/
+
+/* length of 'y' portion of 'y.onion' URL. */
+#define REND_SERVICE_ID_LEN 16
 
 #endif