diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/hs_circuitmap.c | 250 | ||||
-rw-r--r-- | src/or/hs_circuitmap.h | 65 | ||||
-rw-r--r-- | src/or/hs_intropoint.c | 4 | ||||
-rw-r--r-- | src/or/rendmid.c | 14 |
4 files changed, 255 insertions, 78 deletions
diff --git a/src/or/hs_circuitmap.c b/src/or/hs_circuitmap.c index 4d5c89307b..ea66fb5194 100644 --- a/src/or/hs_circuitmap.c +++ b/src/or/hs_circuitmap.c @@ -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 @@ -177,15 +178,17 @@ hs_circuitmap_register_circuit(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. */ +/* 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(hs_token_type_t type, - size_t token_len, - const uint8_t *token, - uint8_t wanted_circ_purpose) +hs_circuitmap_get_circuit_impl(hs_token_type_t type, + size_t token_len, + const uint8_t *token, + uint8_t wanted_circ_purpose) { circuit_t *found_circ = NULL; @@ -209,38 +212,46 @@ hs_circuitmap_get_circuit(hs_token_type_t type, return found_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. */ -or_circuit_t * -hs_circuitmap_get_intro_circ_v3(const ed25519_public_key_t *auth_key) +/* 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(auth_key); + tor_assert(token); + tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose)); - circ = hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V3, - ED25519_PUBKEY_LEN, auth_key->pubkey, - CIRCUIT_PURPOSE_INTRO_POINT); + 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); + tor_assert(CIRCUIT_IS_ORIGIN(circ)); + return TO_ORIGIN_CIRCUIT(circ); } -/* Public function: Return v2 introduction circuit 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) +/* 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(digest); + tor_assert(token); + tor_assert(!CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose)); - circ = hs_circuitmap_get_circuit(HS_TOKEN_INTRO_V2, - REND_TOKEN_LEN, digest, - CIRCUIT_PURPOSE_INTRO_POINT); + circ = hs_circuitmap_get_circuit_impl(type, token_len, token, + wanted_circ_purpose); if (!circ) { return NULL; } @@ -249,58 +260,189 @@ hs_circuitmap_get_intro_circ_v2(const uint8_t *digest) return TO_OR_CIRCUIT(circ); } -/* Public function: Return rendezvous circuit with rendezvous - * <b>cookie</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 * -hs_circuitmap_get_rend_circ(const uint8_t *cookie) +hs_circuitmap_get_intro_circ_v3_relay_side( + const ed25519_public_key_t *auth_key) { - circuit_t *circ; - tor_assert(cookie); + return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V3_RELAY_SIDE, + ED25519_PUBKEY_LEN, auth_key->pubkey, + CIRCUIT_PURPOSE_INTRO_POINT); +} - circ = hs_circuitmap_get_circuit(HS_TOKEN_REND, - REND_TOKEN_LEN, cookie, - CIRCUIT_PURPOSE_REND_POINT_WAITING); - if (!circ) { - return NULL; - } +/* 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); +} - tor_assert(CIRCUIT_IS_ORCIRC(circ)); - return TO_OR_CIRCUIT(circ); +/* 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_relay_side(const uint8_t *cookie) +{ + 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(TO_CIRCUIT(circ), - HS_TOKEN_REND, + 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(TO_CIRCUIT(circ), - HS_TOKEN_INTRO_V2, + 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, - 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(TO_CIRCUIT(circ), - HS_TOKEN_INTRO_V3, + 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(circuit_t *circ) { @@ -326,7 +468,7 @@ hs_circuitmap_remove_circuit(circuit_t *circ) circ->hs_token = NULL; } -/* Initialize the global HS circuitmap. */ +/* Public function: Initialize the global HS circuitmap. */ void hs_circuitmap_init(void) { @@ -336,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) { diff --git a/src/or/hs_circuitmap.h b/src/or/hs_circuitmap.h index 79dea1a572..33d5b64117 100644 --- a/src/or/hs_circuitmap.h +++ b/src/or/hs_circuitmap.h @@ -13,21 +13,47 @@ 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); - -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); +/** 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); @@ -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 diff --git a/src/or/hs_intropoint.c b/src/or/hs_intropoint.c index a7282aba8f..6a63fd6e72 100644 --- a/src/or/hs_intropoint.c +++ b/src/or/hs_intropoint.c @@ -195,7 +195,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); @@ -461,7 +461,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); diff --git a/src/or/rendmid.c b/src/or/rendmid.c index b581f0e5f1..23c3deddaa 100644 --- a/src/or/rendmid.c +++ b/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. */ 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", safe_str(serviceid)); 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. */ 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, "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 * 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) { log_info(LD_REND, "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; } - if (hs_circuitmap_get_rend_circ(request)) { + if (hs_circuitmap_get_rend_circ_relay_side(request)) { log_warn(LD_PROTOCOL, "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS."); 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); - hs_circuitmap_register_rend_circ(circ, request); + hs_circuitmap_register_rend_circ_relay_side(circ, request); 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.", (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) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.", |