Просмотр исходного кода

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 22 лет назад
Родитель
Сommit
0ba9ab5fb0
4 измененных файлов с 87 добавлено и 20 удалено
  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:
 Rendezvous service:
         o Design and specify protocol
         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"?
               "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
               (We should also enumerate all the states that these operations
               can be in.) [NM]
               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
         - Code to configure hidden services [NM] 4 hours
         - Service descriptors
         - Service descriptors
             - OPs need to maintain identity keys for hidden services [NM] 1 hour
             - OPs need to maintain identity keys for hidden services [NM] 1 hour
             - Code to generate and parse service descriptors [NM] 4 hours
             - Code to generate and parse service descriptors [NM] 4 hours
         - Advertisement
         - 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]
             - Code to do an HTTP connection over Tor from within Tor [RD]
             - Publish service descriptors to directory [RD]
             - Publish service descriptors to directory [RD]
             - Directory accepts and remembers service descriptors, and
             - 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->chosen_exit);
   tor_free(circ->build_state);
   tor_free(circ->build_state);
   circuit_free_cpath(circ->cpath);
   circuit_free_cpath(circ->cpath);
+  if (circ->rend_splice) {
+    circ->rend_splice->rend_splice = NULL;
+  }
+
   memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
   memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
   free(circ);
   free(circ);
 }
 }
@@ -290,6 +294,24 @@ circuit_t *circuit_get_newest(connection_t *conn, int must_be_open) {
   return NULL;
   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
 #define MIN_SECONDS_BEFORE_EXPIRING_CIRC 10
 /* circuits that were born at the end of their second might be expired
 /* 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
  * 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-building failed immediately, it won't be set yet. */
     circuit_increment_failure_count();
     circuit_increment_failure_count();
   }
   }
-
   circ->marked_for_close = 1;
   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;
   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 = circuit_new(0, NULL); /* sets circ->p_circ_id and circ->p_conn */
   circ->state = CIRCUIT_STATE_OR_WAIT;
   circ->state = CIRCUIT_STATE_OR_WAIT;
   circ->build_state = onion_new_cpath_build_state();
   circ->build_state = onion_new_cpath_build_state();
+  circ->purpose = CIRCUIT_PURPOSE_C_GENERAL;
 
 
   if (! circ->build_state) {
   if (! circ->build_state) {
     log_fn(LOG_INFO,"Generating cpath length failed.");
     log_fn(LOG_INFO,"Generating cpath length failed.");
@@ -1348,6 +1376,8 @@ void assert_circuit_ok(const circuit_t *c)
 
 
   assert(c);
   assert(c);
   assert(c->magic == CIRCUIT_MAGIC);
   assert(c->magic == CIRCUIT_MAGIC);
+  assert(c->purpose >= _CIRCUIT_PURPOSE_MIN &&
+         c->purpose <= _CIRCUIT_PURPOSE_MAX);
 
 
   if (c->n_conn)
   if (c->n_conn)
     assert(c->n_conn->type == CONN_TYPE_OR);
     assert(c->n_conn->type == CONN_TYPE_OR);
@@ -1376,6 +1406,15 @@ void assert_circuit_ok(const circuit_t *c)
   if (c->cpath) {
   if (c->cpath) {
 //XXX    assert_cpath_ok(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 = circuit_new(cell->circ_id, conn);
   circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
   circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
+  circ->purpose = CIRCUIT_PURPOSE_INTERMEDIATE;
 
 
   memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
   memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
 
 

+ 35 - 8
src/or/or.h

@@ -188,19 +188,17 @@
 
 
 #define _CIRCUIT_PURPOSE_MIN 1
 #define _CIRCUIT_PURPOSE_MIN 1
 /* these circuits were initiated elsewhere */
 /* 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_C_GENERAL 5 /* normal circuit, with cpath */
 #define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 6 /* at Bob, waiting for introductions */
 #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_INTRODUCING 7 /* at Alice, connecting to intro point */
 #define CIRCUIT_PURPOSE_C_ESTABLISH_REND 8 /* at Alice, waiting for Bob */
 #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_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_BEGIN 1
 #define RELAY_COMMAND_DATA 2
 #define RELAY_COMMAND_DATA 2
@@ -473,6 +471,7 @@ struct crypt_path_t {
 #define DH_KEY_LEN CRYPTO_DH_SIZE
 #define DH_KEY_LEN CRYPTO_DH_SIZE
 #define ONIONSKIN_CHALLENGE_LEN (16+DH_KEY_LEN)
 #define ONIONSKIN_CHALLENGE_LEN (16+DH_KEY_LEN)
 #define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+20)
 #define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+20)
+#define REND_COOKIE_LEN CRYPTO_SHA1_DIGEST_LEN
 
 
 typedef struct crypt_path_t crypt_path_t;
 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 */
   time_t timestamp_dirty; /* when the circuit was first used, or 0 if clean */
 
 
   uint8_t state;
   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;
   struct circuit_t *next;
 };
 };
 
 
 typedef struct circuit_t circuit_t;
 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 {
 typedef struct {
   char *LogLevel;
   char *LogLevel;
   char *LogFile;
   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_circ_id_conn(uint16_t circ_id, connection_t *conn);
 circuit_t *circuit_get_by_conn(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_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);
 void circuit_expire_building(void);
 int circuit_count_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_note_extend_failed(const char *from_name, const char *to_name);
 void rep_hist_dump_stats(time_t now, int severity);
 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
 #endif