Browse Source

Merge branch 'ticket21889_031_01_squashed'

Nick Mathewson 7 years ago
parent
commit
902672eac6

+ 5 - 4
src/or/circuitlist.c

@@ -943,10 +943,6 @@ circuit_free(circuit_t *circ)
     crypto_cipher_free(ocirc->n_crypto);
     crypto_cipher_free(ocirc->n_crypto);
     crypto_digest_free(ocirc->n_digest);
     crypto_digest_free(ocirc->n_digest);
 
 
-    if (ocirc->hs_token) {
-      hs_circuitmap_remove_circuit(ocirc);
-    }
-
     if (ocirc->rend_splice) {
     if (ocirc->rend_splice) {
       or_circuit_t *other = ocirc->rend_splice;
       or_circuit_t *other = ocirc->rend_splice;
       tor_assert(other->base_.magic == OR_CIRCUIT_MAGIC);
       tor_assert(other->base_.magic == OR_CIRCUIT_MAGIC);
@@ -978,6 +974,11 @@ circuit_free(circuit_t *circ)
   /* Remove from map. */
   /* Remove from map. */
   circuit_set_n_circid_chan(circ, 0, NULL);
   circuit_set_n_circid_chan(circ, 0, NULL);
 
 
+  /* Clear HS circuitmap token from this circ (if any) */
+  if (circ->hs_token) {
+    hs_circuitmap_remove_circuit(circ);
+  }
+
   /* Clear cell queue _after_ removing it from the map.  Otherwise our
   /* Clear cell queue _after_ removing it from the map.  Otherwise our
    * "active" checks will be violated. */
    * "active" checks will be violated. */
   cell_queue_clear(&circ->n_chan_cells);
   cell_queue_clear(&circ->n_chan_cells);

+ 229 - 67
src/or/hs_circuitmap.c

@@ -4,8 +4,9 @@
 /**
 /**
  * \file hs_circuitmap.c
  * \file hs_circuitmap.c
  *
  *
- * \brief Manage the hidden service circuitmap: A hash table that maps binary
- *  tokens to introduction and rendezvous circuits.
+ * \brief Hidden service circuitmap: A hash table that maps binary tokens to
+ *  introduction and rendezvous circuits; it's used both by relays acting as
+ *  intro points and rendezvous points, and also by hidden services themselves.
  **/
  **/
 
 
 #define HS_CIRCUITMAP_PRIVATE
 #define HS_CIRCUITMAP_PRIVATE
@@ -25,8 +26,8 @@ static struct hs_circuitmap_ht *the_hs_circuitmap = NULL;
 /* This is a helper function used by the hash table code (HT_). It returns 1 if
 /* This is a helper function used by the hash table code (HT_). It returns 1 if
  * two circuits have the same HS token. */
  * two circuits have the same HS token. */
 static int
 static int
-hs_circuits_have_same_token(const or_circuit_t *first_circuit,
-                            const or_circuit_t *second_circuit)
+hs_circuits_have_same_token(const circuit_t *first_circuit,
+                            const circuit_t *second_circuit)
 {
 {
   const hs_token_t *first_token;
   const hs_token_t *first_token;
   const hs_token_t *second_token;
   const hs_token_t *second_token;
@@ -57,7 +58,7 @@ hs_circuits_have_same_token(const or_circuit_t *first_circuit,
 /* This is a helper function for the hash table code (HT_). It hashes a circuit
 /* This is a helper function for the hash table code (HT_). It hashes a circuit
  * HS token into an unsigned int for use as a key by the hash table routines.*/
  * HS token into an unsigned int for use as a key by the hash table routines.*/
 static inline unsigned int
 static inline unsigned int
-hs_circuit_hash_token(const or_circuit_t *circuit)
+hs_circuit_hash_token(const circuit_t *circuit)
 {
 {
   tor_assert(circuit->hs_token);
   tor_assert(circuit->hs_token);
 
 
@@ -67,11 +68,11 @@ hs_circuit_hash_token(const or_circuit_t *circuit)
 
 
 /* Register the circuitmap hash table */
 /* Register the circuitmap hash table */
 HT_PROTOTYPE(hs_circuitmap_ht, // The name of the hashtable struct
 HT_PROTOTYPE(hs_circuitmap_ht, // The name of the hashtable struct
-             or_circuit_t,    // The name of the element struct,
+             circuit_t,    // The name of the element struct,
              hs_circuitmap_node,        // The name of HT_ENTRY member
              hs_circuitmap_node,        // The name of HT_ENTRY member
              hs_circuit_hash_token, hs_circuits_have_same_token)
              hs_circuit_hash_token, hs_circuits_have_same_token)
 
 
-HT_GENERATE2(hs_circuitmap_ht, or_circuit_t, hs_circuitmap_node,
+HT_GENERATE2(hs_circuitmap_ht, circuit_t, hs_circuitmap_node,
              hs_circuit_hash_token, hs_circuits_have_same_token,
              hs_circuit_hash_token, hs_circuits_have_same_token,
              0.6, tor_reallocarray, tor_free_)
              0.6, tor_reallocarray, tor_free_)
 
 
@@ -116,13 +117,13 @@ hs_token_free(hs_token_t *hs_token)
 }
 }
 
 
 /** Return the circuit from the circuitmap with token <b>search_token</b>. */
 /** Return the circuit from the circuitmap with token <b>search_token</b>. */
-static or_circuit_t *
+static circuit_t *
 get_circuit_with_token(hs_token_t *search_token)
 get_circuit_with_token(hs_token_t *search_token)
 {
 {
   tor_assert(the_hs_circuitmap);
   tor_assert(the_hs_circuitmap);
 
 
   /* We use a dummy circuit object for the hash table search routine. */
   /* We use a dummy circuit object for the hash table search routine. */
-  or_circuit_t search_circ;
+  circuit_t search_circ;
   search_circ.hs_token = search_token;
   search_circ.hs_token = search_token;
   return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ);
   return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ);
 }
 }
@@ -130,7 +131,7 @@ get_circuit_with_token(hs_token_t *search_token)
 /* Helper function that registers <b>circ</b> with <b>token</b> on the HS
 /* Helper function that registers <b>circ</b> with <b>token</b> on the HS
    circuitmap. This function steals reference of <b>token</b>. */
    circuitmap. This function steals reference of <b>token</b>. */
 static void
 static void
-hs_circuitmap_register_impl(or_circuit_t *circ, hs_token_t *token)
+hs_circuitmap_register_impl(circuit_t *circ, hs_token_t *token)
 {
 {
   tor_assert(circ);
   tor_assert(circ);
   tor_assert(token);
   tor_assert(token);
@@ -145,13 +146,12 @@ hs_circuitmap_register_impl(or_circuit_t *circ, hs_token_t *token)
      take precedence over old ones, so that HSes and clients and reestablish
      take precedence over old ones, so that HSes and clients and reestablish
      killed circuits without changing the HS token. */
      killed circuits without changing the HS token. */
   {
   {
-    or_circuit_t *found_circ;
+    circuit_t *found_circ;
     found_circ = get_circuit_with_token(token);
     found_circ = get_circuit_with_token(token);
     if (found_circ) {
     if (found_circ) {
       hs_circuitmap_remove_circuit(found_circ);
       hs_circuitmap_remove_circuit(found_circ);
-      if (!found_circ->base_.marked_for_close) {
-        circuit_mark_for_close(TO_CIRCUIT(found_circ),
-                               END_CIRC_REASON_FINISHED);
+      if (!found_circ->marked_for_close) {
+        circuit_mark_for_close(found_circ, END_CIRC_REASON_FINISHED);
       }
       }
     }
     }
   }
   }
@@ -165,7 +165,7 @@ hs_circuitmap_register_impl(or_circuit_t *circ, hs_token_t *token)
  *  circuitmap. Use the HS <b>token</b> as the key to the hash table.  If
  *  circuitmap. Use the HS <b>token</b> as the key to the hash table.  If
  *  <b>token</b> is not set, clear the circuit of any HS tokens. */
  *  <b>token</b> is not set, clear the circuit of any HS tokens. */
 static void
 static void
-hs_circuitmap_register_circuit(or_circuit_t *circ,
+hs_circuitmap_register_circuit(circuit_t *circ,
                                hs_token_type_t type, size_t token_len,
                                hs_token_type_t type, size_t token_len,
                                const uint8_t *token)
                                const uint8_t *token)
 {
 {
@@ -178,17 +178,19 @@ hs_circuitmap_register_circuit(or_circuit_t *circ,
   hs_circuitmap_register_impl(circ, hs_token);
   hs_circuitmap_register_impl(circ, hs_token);
 }
 }
 
 
-/* Query circuitmap for circuit with <b>token</b> of size <b>token_len</b>.
- * Only returns a circuit with purpose equal to the <b>wanted_circ_purpose</b>
- * parameter and if it is NOT marked for close. Return NULL if no such circuit
- * is found. */
-static or_circuit_t *
-hs_circuitmap_get_circuit(hs_token_type_t type,
-                          size_t token_len,
-                          const uint8_t *token,
-                          uint8_t wanted_circ_purpose)
+/* Helper function for hs_circuitmap_get_origin_circuit() and
+ * hs_circuitmap_get_or_circuit(). Because only circuit_t are indexed in the
+ * circuitmap, this function returns object type so the specialized functions
+ * using this helper can upcast it to the right type.
+ *
+ * Return NULL if not such circuit is found. */
+static circuit_t *
+hs_circuitmap_get_circuit_impl(hs_token_type_t type,
+                               size_t token_len,
+                               const uint8_t *token,
+                               uint8_t wanted_circ_purpose)
 {
 {
-  or_circuit_t *found_circ = NULL;
+  circuit_t *found_circ = NULL;
 
 
   tor_assert(the_hs_circuitmap);
   tor_assert(the_hs_circuitmap);
 
 
@@ -202,87 +204,247 @@ hs_circuitmap_get_circuit(hs_token_type_t type,
 
 
   /* Check that the circuit is useful to us */
   /* Check that the circuit is useful to us */
   if (!found_circ ||
   if (!found_circ ||
-      found_circ->base_.purpose != wanted_circ_purpose ||
-      found_circ->base_.marked_for_close) {
+      found_circ->purpose != wanted_circ_purpose ||
+      found_circ->marked_for_close) {
     return NULL;
     return NULL;
   }
   }
 
 
   return found_circ;
   return found_circ;
 }
 }
 
 
-/************** Public circuitmap API ****************************************/
+/* Helper function: Query circuitmap for origin circuit with <b>token</b> of
+ * size <b>token_len</b> and <b>type</b>.  Only returns a circuit with purpose
+ * equal to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked
+ * for close. Return NULL if no such circuit is found. */
+static origin_circuit_t *
+hs_circuitmap_get_origin_circuit(hs_token_type_t type,
+                                 size_t token_len,
+                                 const uint8_t *token,
+                                 uint8_t wanted_circ_purpose)
+{
+  circuit_t *circ;
+  tor_assert(token);
+  tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose));
 
 
-/* Public function: Return v3 introduction circuit with <b>auth_key</b>. Return
- * NULL if no such circuit is found in the circuitmap. */
-or_circuit_t *
-hs_circuitmap_get_intro_circ_v3(const ed25519_public_key_t *auth_key)
+  circ = hs_circuitmap_get_circuit_impl(type, token_len, token,
+                                        wanted_circ_purpose);
+  if (!circ) {
+    return NULL;
+  }
+
+  tor_assert(CIRCUIT_IS_ORIGIN(circ));
+  return TO_ORIGIN_CIRCUIT(circ);
+}
+
+/* Helper function: Query circuitmap for OR circuit with <b>token</b> of size
+ * <b>token_len</b> and <b>type</b>.  Only returns a circuit with purpose equal
+ * to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked for
+ * close. Return NULL if no such circuit is found. */
+static or_circuit_t *
+hs_circuitmap_get_or_circuit(hs_token_type_t type,
+                             size_t token_len,
+                             const uint8_t *token,
+                             uint8_t wanted_circ_purpose)
 {
 {
-  tor_assert(auth_key);
+  circuit_t *circ;
+  tor_assert(token);
+  tor_assert(!CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose));
+
+  circ = hs_circuitmap_get_circuit_impl(type, token_len, token,
+                                        wanted_circ_purpose);
+  if (!circ) {
+    return NULL;
+  }
 
 
-  return hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V3,
-                                   ED25519_PUBKEY_LEN, auth_key->pubkey,
-                                   CIRCUIT_PURPOSE_INTRO_POINT);
+  tor_assert(CIRCUIT_IS_ORCIRC(circ));
+  return TO_OR_CIRCUIT(circ);
 }
 }
 
 
-/* Public function: Return v2 introduction circuit with <b>digest</b>. Return
- * NULL if no such circuit is found in the circuitmap. */
+/************** Public circuitmap API ****************************************/
+
+/**** Public relay-side getters: */
+
+/* Public function: Return a v3 introduction circuit to this relay with
+ * <b>auth_key</b>. Return NULL if no such circuit is found in the
+ * circuitmap. */
 or_circuit_t *
 or_circuit_t *
-hs_circuitmap_get_intro_circ_v2(const uint8_t *digest)
+hs_circuitmap_get_intro_circ_v3_relay_side(
+                                          const ed25519_public_key_t *auth_key)
 {
 {
-  tor_assert(digest);
+  return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V3_RELAY_SIDE,
+                                      ED25519_PUBKEY_LEN, auth_key->pubkey,
+                                      CIRCUIT_PURPOSE_INTRO_POINT);
+}
 
 
-  return hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V2,
-                                   REND_TOKEN_LEN, digest,
-                                   CIRCUIT_PURPOSE_INTRO_POINT);
+/* Public function: Return v2 introduction circuit to this relay with
+ * <b>digest</b>. Return NULL if no such circuit is found in the circuitmap. */
+or_circuit_t *
+hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest)
+{
+  return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V2_RELAY_SIDE,
+                                      REND_TOKEN_LEN, digest,
+                                      CIRCUIT_PURPOSE_INTRO_POINT);
 }
 }
 
 
-/* Public function: Return rendezvous circuit with rendezvous
+/* Public function: Return rendezvous circuit to this relay with rendezvous
  * <b>cookie</b>. Return NULL if no such circuit is found in the circuitmap. */
  * <b>cookie</b>. Return NULL if no such circuit is found in the circuitmap. */
 or_circuit_t *
 or_circuit_t *
-hs_circuitmap_get_rend_circ(const uint8_t *cookie)
+hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
 {
 {
-  tor_assert(cookie);
-
-  return hs_circuitmap_get_circuit(HS_TOKEN_REND,
-                                   REND_TOKEN_LEN, cookie,
-                                   CIRCUIT_PURPOSE_REND_POINT_WAITING);
+  return hs_circuitmap_get_or_circuit(HS_TOKEN_REND_RELAY_SIDE,
+                                      REND_TOKEN_LEN, cookie,
+                                      CIRCUIT_PURPOSE_REND_POINT_WAITING);
 }
 }
 
 
+/** Public relay-side setters: */
+
 /* Public function: Register rendezvous circuit with key <b>cookie</b> to the
 /* Public function: Register rendezvous circuit with key <b>cookie</b> to the
  * circuitmap. */
  * circuitmap. */
 void
 void
-hs_circuitmap_register_rend_circ(or_circuit_t *circ, const uint8_t *cookie)
+hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ,
+                                            const uint8_t *cookie)
 {
 {
-  hs_circuitmap_register_circuit(circ,
-                                 HS_TOKEN_REND,
+  hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
+                                 HS_TOKEN_REND_RELAY_SIDE,
                                  REND_TOKEN_LEN, cookie);
                                  REND_TOKEN_LEN, cookie);
 }
 }
+/* Public function: Register v2 intro circuit with key <b>digest</b> to the
+ * circuitmap. */
+void
+hs_circuitmap_register_intro_circ_v2_relay_side(or_circuit_t *circ,
+                                                const uint8_t *digest)
+{
+  hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
+                                 HS_TOKEN_INTRO_V2_RELAY_SIDE,
+                                 REND_TOKEN_LEN, digest);
+}
+
+/* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
+ * circuitmap. */
+void
+hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ,
+                                          const ed25519_public_key_t *auth_key)
+{
+  hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
+                                 HS_TOKEN_INTRO_V3_RELAY_SIDE,
+                                 ED25519_PUBKEY_LEN, auth_key->pubkey);
+}
+
+/**** Public servide-side getters: */
+
+/* Public function: Return v3 introduction circuit with <b>auth_key</b>
+ * originating from this hidden service. Return NULL if no such circuit is
+ * found in the circuitmap. */
+origin_circuit_t *
+hs_circuitmap_get_intro_circ_v3_service_side(const
+                                             ed25519_public_key_t *auth_key)
+{
+  origin_circuit_t *circ = NULL;
+
+  /* Check first for established intro circuits */
+  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V3_SERVICE_SIDE,
+                                          ED25519_PUBKEY_LEN, auth_key->pubkey,
+                                          CIRCUIT_PURPOSE_S_INTRO);
+  if (circ) {
+    return circ;
+  }
+
+  /* ...if nothing found, check for pending intro circs */
+  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V3_SERVICE_SIDE,
+                                          ED25519_PUBKEY_LEN, auth_key->pubkey,
+                                          CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+
+  return circ;
+}
+
+/* Public function: Return v2 introduction circuit originating from this hidden
+ * service with <b>digest</b>. Return NULL if no such circuit is found in the
+ * circuitmap. */
+origin_circuit_t *
+hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
+{
+  origin_circuit_t *circ = NULL;
+
+  /* Check first for established intro circuits */
+  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V2_SERVICE_SIDE,
+                                          REND_TOKEN_LEN, digest,
+                                          CIRCUIT_PURPOSE_S_INTRO);
+  if (circ) {
+    return circ;
+  }
+
+  /* ...if nothing found, check for pending intro circs */
+  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V2_SERVICE_SIDE,
+                                          REND_TOKEN_LEN, digest,
+                                          CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+
+  return circ;
+}
+
+/* Public function: Return rendezvous circuit originating from this hidden
+ * service with rendezvous <b>cookie</b>. Return NULL if no such circuit is
+ * found in the circuitmap. */
+origin_circuit_t *
+hs_circuitmap_get_rend_circ_service_side(const uint8_t *cookie)
+{
+  origin_circuit_t *circ = NULL;
+
+  /* Try to check if we have a connecting circuit. */
+  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_SERVICE_SIDE,
+                                          REND_TOKEN_LEN, cookie,
+                                          CIRCUIT_PURPOSE_S_CONNECT_REND);
+  if (circ) {
+    return circ;
+  }
+
+  /* Then try for connected circuit. */
+  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_SERVICE_SIDE,
+                                          REND_TOKEN_LEN, cookie,
+                                          CIRCUIT_PURPOSE_S_REND_JOINED);
+  return circ;
+}
+
+/**** Public servide-side setters: */
 
 
 /* Public function: Register v2 intro circuit with key <b>digest</b> to the
 /* Public function: Register v2 intro circuit with key <b>digest</b> to the
  * circuitmap. */
  * circuitmap. */
 void
 void
-hs_circuitmap_register_intro_circ_v2(or_circuit_t *circ, const uint8_t *digest)
+hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ,
+                                                  const uint8_t *digest)
 {
 {
-  hs_circuitmap_register_circuit(circ,
-                                 HS_TOKEN_INTRO_V2,
+  hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
+                                 HS_TOKEN_INTRO_V2_SERVICE_SIDE,
                                  REND_TOKEN_LEN, digest);
                                  REND_TOKEN_LEN, digest);
 }
 }
 
 
 /* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
 /* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
  * circuitmap. */
  * circuitmap. */
 void
 void
-hs_circuitmap_register_intro_circ_v3(or_circuit_t *circ,
-                                     const ed25519_public_key_t *auth_key)
+hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ,
+                                          const ed25519_public_key_t *auth_key)
 {
 {
-  hs_circuitmap_register_circuit(circ,
-                                 HS_TOKEN_INTRO_V3,
+  hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
+                                 HS_TOKEN_INTRO_V3_SERVICE_SIDE,
                                  ED25519_PUBKEY_LEN, auth_key->pubkey);
                                  ED25519_PUBKEY_LEN, auth_key->pubkey);
 }
 }
 
 
-/** Remove this circuit from the HS circuitmap. Clear its HS token, and remove
- *  it from the hashtable. */
+/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+ * circuitmap. */
+void
+hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ,
+                                              const uint8_t *cookie)
+{
+  hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
+                                 HS_TOKEN_REND_SERVICE_SIDE,
+                                 REND_TOKEN_LEN, cookie);
+}
+
+/**** Misc public functions: */
+
+/** Public function: Remove this circuit from the HS circuitmap. Clear its HS
+ *  token, and remove it from the hashtable. */
 void
 void
-hs_circuitmap_remove_circuit(or_circuit_t *circ)
+hs_circuitmap_remove_circuit(circuit_t *circ)
 {
 {
   tor_assert(the_hs_circuitmap);
   tor_assert(the_hs_circuitmap);
 
 
@@ -291,14 +453,14 @@ hs_circuitmap_remove_circuit(or_circuit_t *circ)
   }
   }
 
 
   /* Remove circ from circuitmap */
   /* Remove circ from circuitmap */
-  or_circuit_t *tmp;
+  circuit_t *tmp;
   tmp = HT_REMOVE(hs_circuitmap_ht, the_hs_circuitmap, circ);
   tmp = HT_REMOVE(hs_circuitmap_ht, the_hs_circuitmap, circ);
   /* ... and ensure the removal was successful. */
   /* ... and ensure the removal was successful. */
   if (tmp) {
   if (tmp) {
     tor_assert(tmp == circ);
     tor_assert(tmp == circ);
   } else {
   } else {
     log_warn(LD_BUG, "Could not find circuit (%u) in circuitmap.",
     log_warn(LD_BUG, "Could not find circuit (%u) in circuitmap.",
-             circ->p_circ_id);
+             circ->n_circ_id);
   }
   }
 
 
   /* Clear token from circ */
   /* Clear token from circ */
@@ -306,7 +468,7 @@ hs_circuitmap_remove_circuit(or_circuit_t *circ)
   circ->hs_token = NULL;
   circ->hs_token = NULL;
 }
 }
 
 
-/* Initialize the global HS circuitmap. */
+/* Public function: Initialize the global HS circuitmap. */
 void
 void
 hs_circuitmap_init(void)
 hs_circuitmap_init(void)
 {
 {
@@ -316,7 +478,7 @@ hs_circuitmap_init(void)
   HT_INIT(hs_circuitmap_ht, the_hs_circuitmap);
   HT_INIT(hs_circuitmap_ht, the_hs_circuitmap);
 }
 }
 
 
-/* Free all memory allocated by the global HS circuitmap. */
+/* Public function: Free all memory allocated by the global HS circuitmap. */
 void
 void
 hs_circuitmap_free_all(void)
 hs_circuitmap_free_all(void)
 {
 {

+ 51 - 18
src/or/hs_circuitmap.h

@@ -9,26 +9,52 @@
 #ifndef TOR_HS_CIRCUITMAP_H
 #ifndef TOR_HS_CIRCUITMAP_H
 #define TOR_HS_CIRCUITMAP_H
 #define TOR_HS_CIRCUITMAP_H
 
 
-typedef HT_HEAD(hs_circuitmap_ht, or_circuit_t) hs_circuitmap_ht;
+typedef HT_HEAD(hs_circuitmap_ht, circuit_t) hs_circuitmap_ht;
 
 
 typedef struct hs_token_s hs_token_t;
 typedef struct hs_token_s hs_token_t;
 struct or_circuit_t;
 struct or_circuit_t;
+struct origin_circuit_t;
 
 
 /** Public HS circuitmap API: */
 /** Public HS circuitmap API: */
 
 
-struct or_circuit_t *hs_circuitmap_get_rend_circ(const uint8_t *cookie);
-struct or_circuit_t *hs_circuitmap_get_intro_circ_v3(
-                                        const ed25519_public_key_t *auth_key);
-struct or_circuit_t *hs_circuitmap_get_intro_circ_v2(const uint8_t *digest);
-
-void hs_circuitmap_register_rend_circ(struct or_circuit_t *circ,
-                                      const uint8_t *cookie);
-void hs_circuitmap_register_intro_circ_v2(struct or_circuit_t *circ,
-                                          const uint8_t *digest);
-void hs_circuitmap_register_intro_circ_v3(struct or_circuit_t *circ,
+/** Public relay-side API: */
+
+struct or_circuit_t *
+hs_circuitmap_get_intro_circ_v3_relay_side(const
+                                           ed25519_public_key_t *auth_key);
+struct or_circuit_t *
+hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest);
+struct or_circuit_t *
+hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie);
+
+void hs_circuitmap_register_rend_circ_relay_side(struct or_circuit_t *circ,
+                                                 const uint8_t *cookie);
+void hs_circuitmap_register_intro_circ_v2_relay_side(struct or_circuit_t *circ,
+                                                     const uint8_t *digest);
+void hs_circuitmap_register_intro_circ_v3_relay_side(struct or_circuit_t *circ,
                                          const ed25519_public_key_t *auth_key);
                                          const ed25519_public_key_t *auth_key);
 
 
-void hs_circuitmap_remove_circuit(struct or_circuit_t *circ);
+/** Public service-side API: */
+
+struct origin_circuit_t *
+hs_circuitmap_get_intro_circ_v3_service_side(const
+                                             ed25519_public_key_t *auth_key);
+struct origin_circuit_t *
+hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest);
+struct origin_circuit_t *
+hs_circuitmap_get_rend_circ_service_side(const uint8_t *cookie);
+
+void hs_circuitmap_register_intro_circ_v2_service_side(
+                                        struct origin_circuit_t *circ,
+                                        const uint8_t *digest);
+void hs_circuitmap_register_intro_circ_v3_service_side(
+                                        struct origin_circuit_t *circ,
+                                        const ed25519_public_key_t *auth_key);
+void hs_circuitmap_register_rend_circ_service_side(
+                                        struct origin_circuit_t *circ,
+                                        const uint8_t *cookie);
+
+void hs_circuitmap_remove_circuit(struct circuit_t *circ);
 
 
 void hs_circuitmap_init(void);
 void hs_circuitmap_init(void);
 void hs_circuitmap_free_all(void);
 void hs_circuitmap_free_all(void);
@@ -37,12 +63,19 @@ void hs_circuitmap_free_all(void);
 
 
 /** Represents the type of HS token. */
 /** Represents the type of HS token. */
 typedef enum {
 typedef enum {
-  /** A rendezvous cookie (128bit)*/
-  HS_TOKEN_REND,
-  /** A v2 introduction point pubkey (160bit) */
-  HS_TOKEN_INTRO_V2,
-  /** A v3 introduction point pubkey (256bit) */
-  HS_TOKEN_INTRO_V3,
+  /** A rendezvous cookie on a relay (128bit)*/
+  HS_TOKEN_REND_RELAY_SIDE,
+  /** A v2 introduction point pubkey on a relay (160bit) */
+  HS_TOKEN_INTRO_V2_RELAY_SIDE,
+  /** A v3 introduction point pubkey on a relay (256bit) */
+  HS_TOKEN_INTRO_V3_RELAY_SIDE,
+
+  /** A rendezvous cookie on a hidden service (128bit)*/
+  HS_TOKEN_REND_SERVICE_SIDE,
+  /** A v2 introduction point pubkey on a hidden service (160bit) */
+  HS_TOKEN_INTRO_V2_SERVICE_SIDE,
+  /** A v3 introduction point pubkey on a hidden service (256bit) */
+  HS_TOKEN_INTRO_V3_SERVICE_SIDE,
 } hs_token_type_t;
 } hs_token_type_t;
 
 
 /** Represents a token used in the HS protocol. Each such token maps to a
 /** Represents a token used in the HS protocol. Each such token maps to a

+ 2 - 2
src/or/hs_intropoint.c

@@ -196,7 +196,7 @@ handle_verified_establish_intro_cell(or_circuit_t *circ,
   }
   }
 
 
   /* Associate intro point auth key with this circuit. */
   /* Associate intro point auth key with this circuit. */
-  hs_circuitmap_register_intro_circ_v3(circ, &auth_key);
+  hs_circuitmap_register_intro_circ_v3_relay_side(circ, &auth_key);
   /* Repurpose this circuit into an intro circuit. */
   /* Repurpose this circuit into an intro circuit. */
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
 
 
@@ -462,7 +462,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
   {
   {
     ed25519_public_key_t auth_key;
     ed25519_public_key_t auth_key;
     get_auth_key_from_cell(&auth_key, RELAY_COMMAND_INTRODUCE1, parsed_cell);
     get_auth_key_from_cell(&auth_key, RELAY_COMMAND_INTRODUCE1, parsed_cell);
-    service_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
+    service_circ = hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
     if (service_circ == NULL) {
     if (service_circ == NULL) {
       char b64_key[ED25519_BASE64_LEN + 1];
       char b64_key[ED25519_BASE64_LEN + 1];
       ed25519_public_to_base64(b64_key, &auth_key);
       ed25519_public_to_base64(b64_key, &auth_key);

+ 7 - 7
src/or/or.h

@@ -3074,6 +3074,13 @@ typedef struct circuit_t {
    * circuit's queues; used only if CELL_STATS events are enabled and
    * circuit's queues; used only if CELL_STATS events are enabled and
    * cleared after being sent to control port. */
    * cleared after being sent to control port. */
   smartlist_t *testing_cell_stats;
   smartlist_t *testing_cell_stats;
+
+  /** If set, points to an HS token that this circuit might be carrying.
+   *  Used by the HS circuitmap.  */
+  hs_token_t *hs_token;
+  /** Hashtable node: used to look up the circuit by its HS token using the HS
+      circuitmap. */
+  HT_ENTRY(circuit_t) hs_circuitmap_node;
 } circuit_t;
 } circuit_t;
 
 
 /** Largest number of relay_early cells that we can send on a given
 /** Largest number of relay_early cells that we can send on a given
@@ -3383,13 +3390,6 @@ typedef struct or_circuit_t {
    * is not marked for close. */
    * is not marked for close. */
   struct or_circuit_t *rend_splice;
   struct or_circuit_t *rend_splice;
 
 
-  /** If set, points to an HS token that this circuit might be carrying.
-   *  Used by the HS circuitmap.  */
-  hs_token_t *hs_token;
-  /** Hashtable node: used to look up the circuit by its HS token using the HS
-      circuitmap. */
-  HT_ENTRY(or_circuit_t) hs_circuitmap_node;
-
   /** Stores KH for the handshake. */
   /** Stores KH for the handshake. */
   char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
   char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
 
 

+ 9 - 7
src/or/rendmid.c

@@ -96,7 +96,8 @@ rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
 
 
   /* Close any other intro circuits with the same pk. */
   /* Close any other intro circuits with the same pk. */
   c = NULL;
   c = NULL;
-  while ((c = hs_circuitmap_get_intro_circ_v2((const uint8_t *)pk_digest))) {
+  while ((c = hs_circuitmap_get_intro_circ_v2_relay_side(
+                                                (const uint8_t *)pk_digest))) {
     log_info(LD_REND, "Replacing old circuit for service %s",
     log_info(LD_REND, "Replacing old circuit for service %s",
              safe_str(serviceid));
              safe_str(serviceid));
     circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
     circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
@@ -111,7 +112,7 @@ rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
 
 
   /* Now, set up this circuit. */
   /* Now, set up this circuit. */
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
-  hs_circuitmap_register_intro_circ_v2(circ, (uint8_t *)pk_digest);
+  hs_circuitmap_register_intro_circ_v2_relay_side(circ, (uint8_t *)pk_digest);
 
 
   log_info(LD_REND,
   log_info(LD_REND,
            "Established introduction point on circuit %u for service %s",
            "Established introduction point on circuit %u for service %s",
@@ -165,7 +166,8 @@ rend_mid_introduce_legacy(or_circuit_t *circ, const uint8_t *request,
 
 
   /* The first 20 bytes are all we look at: they have a hash of the service's
   /* The first 20 bytes are all we look at: they have a hash of the service's
    * PK. */
    * PK. */
-  intro_circ = hs_circuitmap_get_intro_circ_v2((const uint8_t*)request);
+  intro_circ = hs_circuitmap_get_intro_circ_v2_relay_side(
+                                                      (const uint8_t*)request);
   if (!intro_circ) {
   if (!intro_circ) {
     log_info(LD_REND,
     log_info(LD_REND,
              "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; "
              "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; "
@@ -242,7 +244,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
     goto err;
     goto err;
   }
   }
 
 
-  if (hs_circuitmap_get_rend_circ(request)) {
+  if (hs_circuitmap_get_rend_circ_relay_side(request)) {
     log_warn(LD_PROTOCOL,
     log_warn(LD_PROTOCOL,
              "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
              "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
     goto err;
     goto err;
@@ -258,7 +260,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
   }
   }
 
 
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_POINT_WAITING);
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_POINT_WAITING);
-  hs_circuitmap_register_rend_circ(circ, request);
+  hs_circuitmap_register_rend_circ_relay_side(circ, request);
 
 
   base16_encode(hexid,9,(char*)request,4);
   base16_encode(hexid,9,(char*)request,4);
 
 
@@ -307,7 +309,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
            "Got request for rendezvous from circuit %u to cookie %s.",
            "Got request for rendezvous from circuit %u to cookie %s.",
            (unsigned)circ->p_circ_id, hexid);
            (unsigned)circ->p_circ_id, hexid);
 
 
-  rend_circ = hs_circuitmap_get_rend_circ(request);
+  rend_circ = hs_circuitmap_get_rend_circ_relay_side(request);
   if (!rend_circ) {
   if (!rend_circ) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
          "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
          "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
@@ -342,7 +344,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED);
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED);
   circuit_change_purpose(TO_CIRCUIT(rend_circ),
   circuit_change_purpose(TO_CIRCUIT(rend_circ),
                          CIRCUIT_PURPOSE_REND_ESTABLISHED);
                          CIRCUIT_PURPOSE_REND_ESTABLISHED);
-  hs_circuitmap_remove_circuit(circ);
+  hs_circuitmap_remove_circuit(TO_CIRCUIT(circ));
 
 
   rend_circ->rend_splice = circ;
   rend_circ->rend_splice = circ;
   circ->rend_splice = rend_circ;
   circ->rend_splice = rend_circ;

+ 107 - 29
src/test/test_circuitlist.c

@@ -201,68 +201,68 @@ test_rend_token_maps(void *arg)
   tt_int_op(tok3[REND_TOKEN_LEN-1], OP_EQ, '.');
   tt_int_op(tok3[REND_TOKEN_LEN-1], OP_EQ, '.');
 
 
   /* No maps; nothing there. */
   /* No maps; nothing there. */
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok1));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok1));
 
 
-  hs_circuitmap_register_rend_circ(c1, tok1);
-  hs_circuitmap_register_intro_circ_v2(c2, tok2);
+  hs_circuitmap_register_rend_circ_relay_side(c1, tok1);
+  hs_circuitmap_register_intro_circ_v2_relay_side(c2, tok2);
 
 
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok3));
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok1));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok3));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok1));
 
 
   /* Without purpose set, we don't get the circuits */
   /* Without purpose set, we don't get the circuits */
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
 
 
   c1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
   c1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
   c2->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
   c2->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
 
 
   /* Okay, make sure they show up now. */
   /* Okay, make sure they show up now. */
-  tt_ptr_op(c1, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
-  tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
+  tt_ptr_op(c1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+  tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
 
 
   /* Two items at the same place with the same token. */
   /* Two items at the same place with the same token. */
   c3->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
   c3->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
-  hs_circuitmap_register_rend_circ(c3, tok2);
-  tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
-  tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
+  hs_circuitmap_register_rend_circ_relay_side(c3, tok2);
+  tt_ptr_op(c2, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
+  tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
 
 
   /* Marking a circuit makes it not get returned any more */
   /* Marking a circuit makes it not get returned any more */
   circuit_mark_for_close(TO_CIRCUIT(c1), END_CIRC_REASON_FINISHED);
   circuit_mark_for_close(TO_CIRCUIT(c1), END_CIRC_REASON_FINISHED);
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok1));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
   circuit_free(TO_CIRCUIT(c1));
   circuit_free(TO_CIRCUIT(c1));
   c1 = NULL;
   c1 = NULL;
 
 
   /* Freeing a circuit makes it not get returned any more. */
   /* Freeing a circuit makes it not get returned any more. */
   circuit_free(TO_CIRCUIT(c2));
   circuit_free(TO_CIRCUIT(c2));
   c2 = NULL;
   c2 = NULL;
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok2));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
 
 
   /* c3 -- are you still there? */
   /* c3 -- are you still there? */
-  tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
+  tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
   /* Change its cookie.  This never happens in Tor per se, but hey. */
   /* Change its cookie.  This never happens in Tor per se, but hey. */
   c3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
   c3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
-  hs_circuitmap_register_intro_circ_v2(c3, tok3);
+  hs_circuitmap_register_intro_circ_v2_relay_side(c3, tok3);
 
 
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ(tok2));
-  tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
+  tt_ptr_op(c3, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
 
 
   /* Now replace c3 with c4. */
   /* Now replace c3 with c4. */
   c4->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
   c4->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
-  hs_circuitmap_register_intro_circ_v2(c4, tok3);
+  hs_circuitmap_register_intro_circ_v2_relay_side(c4, tok3);
 
 
-  tt_ptr_op(c4, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
+  tt_ptr_op(c4, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
 
 
-  tt_ptr_op(c3->hs_token, OP_EQ, NULL);
-  tt_ptr_op(c4->hs_token, OP_NE, NULL);
-  tt_mem_op(c4->hs_token->token, OP_EQ, tok3, REND_TOKEN_LEN);
+  tt_ptr_op(TO_CIRCUIT(c3)->hs_token, OP_EQ, NULL);
+  tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_NE, NULL);
+  tt_mem_op(TO_CIRCUIT(c4)->hs_token->token, OP_EQ, tok3, REND_TOKEN_LEN);
 
 
   /* Now clear c4's cookie. */
   /* Now clear c4's cookie. */
-  hs_circuitmap_remove_circuit(c4);
-  tt_ptr_op(c4->hs_token, OP_EQ, NULL);
-  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2(tok3));
+  hs_circuitmap_remove_circuit(TO_CIRCUIT(c4));
+  tt_ptr_op(TO_CIRCUIT(c4)->hs_token, OP_EQ, NULL);
+  tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok3));
 
 
  done:
  done:
   if (c1)
   if (c1)
@@ -370,10 +370,88 @@ test_pick_circid(void *arg)
   UNMOCK(channel_dump_statistics);
   UNMOCK(channel_dump_statistics);
 }
 }
 
 
+/** Test that the circuit pools of our HS circuitmap are isolated based on
+ *  their token type. */
+static void
+test_hs_circuitmap_isolation(void *arg)
+{
+  or_circuit_t *circ1 = NULL;
+  origin_circuit_t *circ2 = NULL;
+  or_circuit_t *circ3 = NULL;
+  origin_circuit_t *circ4 = NULL;
+
+  (void)arg;
+
+  hs_circuitmap_init();
+
+  {
+    const uint8_t tok1[REND_TOKEN_LEN] = "bet i got some of th";
+
+    circ1 = or_circuit_new(0, NULL);
+    circ1->base_.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
+
+    /* check that circuitmap is empty right? */
+    tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+
+    /* Register circ1 with tok1 as relay-side rend circ */
+    hs_circuitmap_register_rend_circ_relay_side(circ1, tok1);
+
+    /* check that service-side getters don't work */
+    tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_service_side(tok1));
+    tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_intro_circ_v2_service_side(tok1));
+
+    /* Check that the right getter works. */
+    tt_ptr_op(circ1, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok1));
+  }
+
+  {
+    const uint8_t tok2[REND_TOKEN_LEN] = "you dont know anythi";
+
+    circ2 = origin_circuit_new();
+    circ2->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
+    circ3 = or_circuit_new(0, NULL);
+    circ3->base_.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
+    circ4 = origin_circuit_new();
+    circ4->base_.purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
+
+    /* Register circ2 with tok2 as service-side intro v2 circ */
+    hs_circuitmap_register_intro_circ_v2_service_side(circ2, tok2);
+    /* Register circ3 with tok2 again but for different purpose */
+    hs_circuitmap_register_intro_circ_v2_relay_side(circ3, tok2);
+
+    /* Check that the getters work */
+    tt_ptr_op(circ2, OP_EQ, hs_circuitmap_get_intro_circ_v2_service_side(tok2));
+    tt_ptr_op(circ3, OP_EQ, hs_circuitmap_get_intro_circ_v2_relay_side(tok2));
+
+    /* Register circ4 with tok2: it should override circ2 */
+    hs_circuitmap_register_intro_circ_v2_service_side(circ4, tok2);
+
+    /* check that relay-side getters don't work */
+    tt_ptr_op(NULL, OP_EQ, hs_circuitmap_get_rend_circ_relay_side(tok2));
+
+    /* Check that the getter returns circ4; the last circuit registered with
+     * that token. */
+    tt_ptr_op(circ4, OP_EQ, hs_circuitmap_get_intro_circ_v2_service_side(tok2));
+  }
+
+ done:
+  if (circ1)
+    circuit_free(TO_CIRCUIT(circ1));
+  if (circ2)
+    circuit_free(TO_CIRCUIT(circ2));
+  if (circ3)
+    circuit_free(TO_CIRCUIT(circ3));
+  if (circ4)
+    circuit_free(TO_CIRCUIT(circ4));
+}
+
+
 struct testcase_t circuitlist_tests[] = {
 struct testcase_t circuitlist_tests[] = {
   { "maps", test_clist_maps, TT_FORK, NULL, NULL },
   { "maps", test_clist_maps, TT_FORK, NULL, NULL },
   { "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL },
   { "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL },
   { "pick_circid", test_pick_circid, TT_FORK, NULL, NULL },
   { "pick_circid", test_pick_circid, TT_FORK, NULL, NULL },
+  { "hs_circuitmap_isolation", test_hs_circuitmap_isolation,
+    TT_FORK, NULL, NULL },
   END_OF_TESTCASES
   END_OF_TESTCASES
 };
 };
 
 

+ 6 - 5
src/test/test_hs_intropoint.c

@@ -532,7 +532,7 @@ test_intro_point_registration(void *arg)
     tt_assert(the_hs_circuitmap);
     tt_assert(the_hs_circuitmap);
     tt_int_op(0, ==, HT_SIZE(the_hs_circuitmap));
     tt_int_op(0, ==, HT_SIZE(the_hs_circuitmap));
     /* Do a circuitmap query in any case */
     /* Do a circuitmap query in any case */
-    returned_intro_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
+    returned_intro_circ =hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
     tt_ptr_op(returned_intro_circ, ==, NULL);
     tt_ptr_op(returned_intro_circ, ==, NULL);
   }
   }
 
 
@@ -548,7 +548,7 @@ test_intro_point_registration(void *arg)
     tt_int_op(1, ==, HT_SIZE(the_hs_circuitmap));
     tt_int_op(1, ==, HT_SIZE(the_hs_circuitmap));
     get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO,
     get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO,
                            establish_intro_cell);
                            establish_intro_cell);
-    returned_intro_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
+    returned_intro_circ = hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
     tt_ptr_op(intro_circ, ==, returned_intro_circ);
     tt_ptr_op(intro_circ, ==, returned_intro_circ);
   }
   }
 
 
@@ -569,7 +569,8 @@ test_intro_point_registration(void *arg)
     /* Check that the new element is our legacy intro circuit. */
     /* Check that the new element is our legacy intro circuit. */
     retval = crypto_pk_get_digest(legacy_auth_key, key_digest);
     retval = crypto_pk_get_digest(legacy_auth_key, key_digest);
     tt_int_op(retval, ==, 0);
     tt_int_op(retval, ==, 0);
-    returned_intro_circ= hs_circuitmap_get_intro_circ_v2((uint8_t*)key_digest);
+    returned_intro_circ =
+      hs_circuitmap_get_intro_circ_v2_relay_side((uint8_t*)key_digest);
     tt_ptr_op(legacy_intro_circ, ==, returned_intro_circ);
     tt_ptr_op(legacy_intro_circ, ==, returned_intro_circ);
   }
   }
 
 
@@ -790,7 +791,7 @@ test_received_introduce1_handling(void *arg)
     const uint8_t *cell_auth_key =
     const uint8_t *cell_auth_key =
       trn_cell_introduce1_getconstarray_auth_key(cell);
       trn_cell_introduce1_getconstarray_auth_key(cell);
     memcpy(auth_key.pubkey, cell_auth_key, ED25519_PUBKEY_LEN);
     memcpy(auth_key.pubkey, cell_auth_key, ED25519_PUBKEY_LEN);
-    hs_circuitmap_register_intro_circ_v3(service_circ, &auth_key);
+    hs_circuitmap_register_intro_circ_v3_relay_side(service_circ, &auth_key);
     ret = hs_intro_received_introduce1(circ, request, request_len);
     ret = hs_intro_received_introduce1(circ, request, request_len);
     circuit_free(TO_CIRCUIT(circ));
     circuit_free(TO_CIRCUIT(circ));
     circuit_free(TO_CIRCUIT(service_circ));
     circuit_free(TO_CIRCUIT(service_circ));
@@ -819,7 +820,7 @@ test_received_introduce1_handling(void *arg)
     /* Register the circuit in the map for the auth key of the cell. */
     /* Register the circuit in the map for the auth key of the cell. */
     uint8_t token[REND_TOKEN_LEN];
     uint8_t token[REND_TOKEN_LEN];
     memcpy(token, legacy_key_id, sizeof(token));
     memcpy(token, legacy_key_id, sizeof(token));
-    hs_circuitmap_register_intro_circ_v2(service_circ, token);
+    hs_circuitmap_register_intro_circ_v2_relay_side(service_circ, token);
     ret = hs_intro_received_introduce1(circ, request, request_len);
     ret = hs_intro_received_introduce1(circ, request, request_len);
     circuit_free(TO_CIRCUIT(circ));
     circuit_free(TO_CIRCUIT(circ));
     circuit_free(TO_CIRCUIT(service_circ));
     circuit_free(TO_CIRCUIT(service_circ));