Loading src/or/circuitlist.c +5 −4 Original line number Diff line number Diff line Loading @@ -943,10 +943,6 @@ circuit_free(circuit_t *circ) crypto_cipher_free(ocirc->n_crypto); crypto_digest_free(ocirc->n_digest); if (ocirc->hs_token) { hs_circuitmap_remove_circuit(ocirc); } if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; tor_assert(other->base_.magic == OR_CIRCUIT_MAGIC); Loading Loading @@ -978,6 +974,11 @@ circuit_free(circuit_t *circ) /* Remove from map. */ 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 * "active" checks will be violated. */ cell_queue_clear(&circ->n_chan_cells); Loading src/or/hs_circuitmap.c +229 −67 Original line number Diff line number Diff line Loading @@ -4,8 +4,9 @@ /** * \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 Loading @@ -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 * two circuits have the same HS token. */ 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 *second_token; Loading Loading @@ -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 * HS token into an unsigned int for use as a key by the hash table routines.*/ 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); Loading @@ -67,11 +68,11 @@ hs_circuit_hash_token(const or_circuit_t *circuit) /* Register the circuitmap hash table */ 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_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, 0.6, tor_reallocarray, tor_free_) Loading Loading @@ -116,13 +117,13 @@ hs_token_free(hs_token_t *hs_token) } /** 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) { tor_assert(the_hs_circuitmap); /* 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; return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ); } Loading @@ -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 circuitmap. This function steals reference of <b>token</b>. */ 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(token); Loading @@ -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 killed circuits without changing the HS token. */ { or_circuit_t *found_circ; circuit_t *found_circ; found_circ = get_circuit_with_token(token); if (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); } } } Loading @@ -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 * <b>token</b> is not set, clear the circuit of any HS tokens. */ 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, const uint8_t *token) { Loading @@ -178,17 +178,19 @@ hs_circuitmap_register_circuit(or_circuit_t *circ, 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, /* 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); Loading @@ -202,87 +204,247 @@ hs_circuitmap_get_circuit(hs_token_type_t type, /* Check that the circuit is useful to us */ 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 found_circ; } /* 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)); 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) { 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; } tor_assert(CIRCUIT_IS_ORCIRC(circ)); return TO_OR_CIRCUIT(circ); } /************** Public circuitmap API ****************************************/ /* Public function: Return v3 introduction circuit with <b>auth_key</b>. Return * NULL if no such circuit is found in the circuitmap. */ /**** 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 * hs_circuitmap_get_intro_circ_v3(const ed25519_public_key_t *auth_key) hs_circuitmap_get_intro_circ_v3_relay_side( const ed25519_public_key_t *auth_key) { tor_assert(auth_key); return hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V3, return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V3_RELAY_SIDE, ED25519_PUBKEY_LEN, auth_key->pubkey, CIRCUIT_PURPOSE_INTRO_POINT); } /* Public function: Return v2 introduction circuit with <b>digest</b>. Return * NULL if no such circuit is found in the circuitmap. */ /* 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(const uint8_t *digest) hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest) { tor_assert(digest); return hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V2, 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. */ 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, 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 * circuitmap. */ 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); } /* 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 * circuitmap. */ 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); } /* Public function: Register v3 intro circuit with key <b>auth_key</b> to the * circuitmap. */ void hs_circuitmap_register_intro_circ_v3(or_circuit_t *circ, 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); } /** 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 hs_circuitmap_remove_circuit(or_circuit_t *circ) hs_circuitmap_remove_circuit(circuit_t *circ) { tor_assert(the_hs_circuitmap); Loading @@ -291,14 +453,14 @@ hs_circuitmap_remove_circuit(or_circuit_t *circ) } /* Remove circ from circuitmap */ or_circuit_t *tmp; circuit_t *tmp; tmp = HT_REMOVE(hs_circuitmap_ht, the_hs_circuitmap, circ); /* ... and ensure the removal was successful. */ if (tmp) { tor_assert(tmp == circ); } else { log_warn(LD_BUG, "Could not find circuit (%u) in circuitmap.", circ->p_circ_id); circ->n_circ_id); } /* Clear token from circ */ Loading @@ -306,7 +468,7 @@ hs_circuitmap_remove_circuit(or_circuit_t *circ) circ->hs_token = NULL; } /* Initialize the global HS circuitmap. */ /* Public function: Initialize the global HS circuitmap. */ void hs_circuitmap_init(void) { Loading @@ -316,7 +478,7 @@ hs_circuitmap_init(void) 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 hs_circuitmap_free_all(void) { Loading src/or/hs_circuitmap.h +51 −18 Original line number Diff line number Diff line Loading @@ -9,26 +9,52 @@ #ifndef 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; struct or_circuit_t; struct origin_circuit_t; /** 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); /** 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(struct or_circuit_t *circ, void hs_circuitmap_register_rend_circ_relay_side(struct or_circuit_t *circ, const uint8_t *cookie); void hs_circuitmap_register_intro_circ_v2(struct or_circuit_t *circ, 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); /** 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(struct or_circuit_t *circ, 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 or_circuit_t *circ); void hs_circuitmap_remove_circuit(struct circuit_t *circ); void hs_circuitmap_init(void); void hs_circuitmap_free_all(void); Loading @@ -37,12 +63,19 @@ void hs_circuitmap_free_all(void); /** Represents the type of HS token. */ 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; /** Represents a token used in the HS protocol. Each such token maps to a Loading src/or/hs_intropoint.c +2 −2 Original line number Diff line number Diff line Loading @@ -196,7 +196,7 @@ handle_verified_establish_intro_cell(or_circuit_t *circ, } /* 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. */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT); Loading Loading @@ -462,7 +462,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, { ed25519_public_key_t auth_key; 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) { char b64_key[ED25519_BASE64_LEN + 1]; ed25519_public_to_base64(b64_key, &auth_key); Loading src/or/or.h +7 −7 Original line number Diff line number Diff line Loading @@ -3074,6 +3074,13 @@ typedef struct circuit_t { * circuit's queues; used only if CELL_STATS events are enabled and * cleared after being sent to control port. */ 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; /** Largest number of relay_early cells that we can send on a given Loading Loading @@ -3383,13 +3390,6 @@ typedef struct or_circuit_t { * is not marked for close. */ 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. */ char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */ Loading Loading
src/or/circuitlist.c +5 −4 Original line number Diff line number Diff line Loading @@ -943,10 +943,6 @@ circuit_free(circuit_t *circ) crypto_cipher_free(ocirc->n_crypto); crypto_digest_free(ocirc->n_digest); if (ocirc->hs_token) { hs_circuitmap_remove_circuit(ocirc); } if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; tor_assert(other->base_.magic == OR_CIRCUIT_MAGIC); Loading Loading @@ -978,6 +974,11 @@ circuit_free(circuit_t *circ) /* Remove from map. */ 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 * "active" checks will be violated. */ cell_queue_clear(&circ->n_chan_cells); Loading
src/or/hs_circuitmap.c +229 −67 Original line number Diff line number Diff line Loading @@ -4,8 +4,9 @@ /** * \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 Loading @@ -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 * two circuits have the same HS token. */ 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 *second_token; Loading Loading @@ -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 * HS token into an unsigned int for use as a key by the hash table routines.*/ 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); Loading @@ -67,11 +68,11 @@ hs_circuit_hash_token(const or_circuit_t *circuit) /* Register the circuitmap hash table */ 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_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, 0.6, tor_reallocarray, tor_free_) Loading Loading @@ -116,13 +117,13 @@ hs_token_free(hs_token_t *hs_token) } /** 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) { tor_assert(the_hs_circuitmap); /* 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; return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ); } Loading @@ -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 circuitmap. This function steals reference of <b>token</b>. */ 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(token); Loading @@ -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 killed circuits without changing the HS token. */ { or_circuit_t *found_circ; circuit_t *found_circ; found_circ = get_circuit_with_token(token); if (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); } } } Loading @@ -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 * <b>token</b> is not set, clear the circuit of any HS tokens. */ 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, const uint8_t *token) { Loading @@ -178,17 +178,19 @@ hs_circuitmap_register_circuit(or_circuit_t *circ, 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, /* 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); Loading @@ -202,87 +204,247 @@ hs_circuitmap_get_circuit(hs_token_type_t type, /* Check that the circuit is useful to us */ 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 found_circ; } /* 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)); 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) { 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; } tor_assert(CIRCUIT_IS_ORCIRC(circ)); return TO_OR_CIRCUIT(circ); } /************** Public circuitmap API ****************************************/ /* Public function: Return v3 introduction circuit with <b>auth_key</b>. Return * NULL if no such circuit is found in the circuitmap. */ /**** 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 * hs_circuitmap_get_intro_circ_v3(const ed25519_public_key_t *auth_key) hs_circuitmap_get_intro_circ_v3_relay_side( const ed25519_public_key_t *auth_key) { tor_assert(auth_key); return hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V3, return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V3_RELAY_SIDE, ED25519_PUBKEY_LEN, auth_key->pubkey, CIRCUIT_PURPOSE_INTRO_POINT); } /* Public function: Return v2 introduction circuit with <b>digest</b>. Return * NULL if no such circuit is found in the circuitmap. */ /* 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(const uint8_t *digest) hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest) { tor_assert(digest); return hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V2, 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. */ 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, 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 * circuitmap. */ 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); } /* 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 * circuitmap. */ 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); } /* Public function: Register v3 intro circuit with key <b>auth_key</b> to the * circuitmap. */ void hs_circuitmap_register_intro_circ_v3(or_circuit_t *circ, 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); } /** 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 hs_circuitmap_remove_circuit(or_circuit_t *circ) hs_circuitmap_remove_circuit(circuit_t *circ) { tor_assert(the_hs_circuitmap); Loading @@ -291,14 +453,14 @@ hs_circuitmap_remove_circuit(or_circuit_t *circ) } /* Remove circ from circuitmap */ or_circuit_t *tmp; circuit_t *tmp; tmp = HT_REMOVE(hs_circuitmap_ht, the_hs_circuitmap, circ); /* ... and ensure the removal was successful. */ if (tmp) { tor_assert(tmp == circ); } else { log_warn(LD_BUG, "Could not find circuit (%u) in circuitmap.", circ->p_circ_id); circ->n_circ_id); } /* Clear token from circ */ Loading @@ -306,7 +468,7 @@ hs_circuitmap_remove_circuit(or_circuit_t *circ) circ->hs_token = NULL; } /* Initialize the global HS circuitmap. */ /* Public function: Initialize the global HS circuitmap. */ void hs_circuitmap_init(void) { Loading @@ -316,7 +478,7 @@ hs_circuitmap_init(void) 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 hs_circuitmap_free_all(void) { Loading
src/or/hs_circuitmap.h +51 −18 Original line number Diff line number Diff line Loading @@ -9,26 +9,52 @@ #ifndef 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; struct or_circuit_t; struct origin_circuit_t; /** 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); /** 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(struct or_circuit_t *circ, void hs_circuitmap_register_rend_circ_relay_side(struct or_circuit_t *circ, const uint8_t *cookie); void hs_circuitmap_register_intro_circ_v2(struct or_circuit_t *circ, 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); /** 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(struct or_circuit_t *circ, 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 or_circuit_t *circ); void hs_circuitmap_remove_circuit(struct circuit_t *circ); void hs_circuitmap_init(void); void hs_circuitmap_free_all(void); Loading @@ -37,12 +63,19 @@ void hs_circuitmap_free_all(void); /** Represents the type of HS token. */ 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; /** Represents a token used in the HS protocol. Each such token maps to a Loading
src/or/hs_intropoint.c +2 −2 Original line number Diff line number Diff line Loading @@ -196,7 +196,7 @@ handle_verified_establish_intro_cell(or_circuit_t *circ, } /* 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. */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT); Loading Loading @@ -462,7 +462,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, { ed25519_public_key_t auth_key; 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) { char b64_key[ED25519_BASE64_LEN + 1]; ed25519_public_to_base64(b64_key, &auth_key); Loading
src/or/or.h +7 −7 Original line number Diff line number Diff line Loading @@ -3074,6 +3074,13 @@ typedef struct circuit_t { * circuit's queues; used only if CELL_STATS events are enabled and * cleared after being sent to control port. */ 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; /** Largest number of relay_early cells that we can send on a given Loading Loading @@ -3383,13 +3390,6 @@ typedef struct or_circuit_t { * is not marked for close. */ 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. */ char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */ Loading