commit 9af311630626b920aa74c4fb8d36eb086ebfb8a4 Author: David Goulet dgoulet@torproject.org Date: Tue Jul 25 10:14:00 2017 -0400
prop224: Handle RENDEZVOUS2 cell
The client can now handle RENDEZVOUS2 cell when they arrive. This consolidate both hidden service version in one function.
Signed-off-by: David Goulet dgoulet@torproject.org --- src/or/hs_client.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/or/hs_client.h | 3 ++ src/or/rendclient.c | 11 ------ src/or/rendcommon.c | 2 +- 4 files changed, 100 insertions(+), 12 deletions(-)
diff --git a/src/or/hs_client.c b/src/or/hs_client.c index ff3d12748..337c7477d 100644 --- a/src/or/hs_client.c +++ b/src/or/hs_client.c @@ -26,6 +26,7 @@ #include "connection.h" #include "circpathbias.h" #include "connection.h" +#include "hs_ntor.h"
/* Get all connections that are waiting on a circuit and flag them back to * waiting for a hidden service descriptor for the given service key @@ -584,6 +585,68 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload, return ret; }
+/* Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The + * encoded cell is in payload of length payload_len. Return 0 on success or a + * negative value on error. On error, the circuit is marked for close. */ +static int +handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload, + size_t payload_len) +{ + int ret = -1; + curve25519_public_key_t server_pk; + uint8_t auth_mac[DIGEST256_LEN] = {0}; + uint8_t handshake_info[CURVE25519_PUBKEY_LEN + sizeof(auth_mac)] = {0}; + hs_ntor_rend_cell_keys_t keys; + const hs_ident_circuit_t *ident; + + tor_assert(circ); + tor_assert(payload); + + /* Make things easier. */ + ident = circ->hs_ident; + tor_assert(ident); + + if (hs_cell_parse_rendezvous2(payload, payload_len, handshake_info, + sizeof(handshake_info)) < 0) { + goto err; + } + /* Get from the handshake info the SERVER_PK and AUTH_MAC. */ + memcpy(&server_pk, handshake_info, CURVE25519_PUBKEY_LEN); + memcpy(auth_mac, handshake_info + CURVE25519_PUBKEY_LEN, sizeof(auth_mac)); + + /* Generate the handshake info. */ + if (hs_ntor_client_get_rendezvous1_keys(&ident->intro_auth_pk, + &ident->rendezvous_client_kp, + &ident->intro_enc_pk, &server_pk, + &keys) < 0) { + log_info(LD_REND, "Unable to compute the rendezvous keys."); + goto err; + } + + /* Critical check, make sure that the MAC matches what we got with what we + * computed just above. */ + if (!hs_ntor_client_rendezvous2_mac_is_good(&keys, auth_mac)) { + log_info(LD_REND, "Invalid MAC in RENDEZVOUS2. Rejecting cell."); + goto err; + } + + /* Setup the e2e encryption on the circuit and finalize its state. */ + if (hs_circuit_setup_e2e_rend_circ(circ, keys.ntor_key_seed, + sizeof(keys.ntor_key_seed), 0) < 0) { + log_info(LD_REND, "Unable to setup the e2e encryption."); + goto err; + } + /* Success. Hidden service connection finalized! */ + ret = 0; + goto end; + + err: + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); + end: + memwipe(&keys, 0, sizeof(keys)); + return ret; +} + /* ========== */ /* Public API */ /* ========== */ @@ -881,3 +944,36 @@ hs_client_receive_introduce_ack(origin_circuit_t *circ, return ret; }
+/* Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return + * 0 on success else a negative value is returned. The circuit will be closed + * on error. */ +int +hs_client_receive_rendezvous2(origin_circuit_t *circ, + const uint8_t *payload, size_t payload_len) +{ + int ret = -1; + + tor_assert(circ); + tor_assert(payload); + + /* Circuit can possibly be in both state because we could receive a + * RENDEZVOUS2 cell before the INTRODUCE_ACK has been received. */ + if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_REND_READY && + TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) { + log_warn(LD_PROTOCOL, "Unexpected RENDEZVOUS2 cell on circuit %u. " + "Closing circuit.", + (unsigned int) TO_CIRCUIT(circ)->n_circ_id); + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); + goto end; + } + + log_info(LD_REND, "Got RENDEZVOUS2 cell from hidden service on circuit %u.", + TO_CIRCUIT(circ)->n_circ_id); + + ret = (circ->hs_ident) ? handle_rendezvous2(circ, payload, payload_len) : + rend_client_receive_rendezvous(circ, payload, + payload_len); + end: + return ret; +} + diff --git a/src/or/hs_client.h b/src/or/hs_client.h index 1c0f8a4d2..6681505ee 100644 --- a/src/or/hs_client.h +++ b/src/or/hs_client.h @@ -34,6 +34,9 @@ int hs_client_receive_rendezvous_acked(origin_circuit_t *circ, int hs_client_receive_introduce_ack(origin_circuit_t *circ, const uint8_t *payload, size_t payload_len); +int hs_client_receive_rendezvous2(origin_circuit_t *circ, + const uint8_t *payload, + size_t payload_len);
void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 683a3916e..cb7d99bed 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -932,23 +932,12 @@ int rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, size_t request_len) { - if ((circ->base_.purpose != CIRCUIT_PURPOSE_C_REND_READY && - circ->base_.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) - || !circ->build_state->pending_final_cpath) { - log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not " - "expecting it. Closing."); - circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); - return -1; - } - if (request_len != DH_KEY_LEN+DIGEST_LEN) { log_warn(LD_PROTOCOL,"Incorrect length (%d) on RENDEZVOUS2 cell.", (int)request_len); goto err; }
- log_info(LD_REND,"Got RENDEZVOUS2 cell from hidden service."); - if (hs_circuit_setup_e2e_rend_circ_legacy_client(circ, request) < 0) { log_warn(LD_GENERAL, "Failed to setup circ"); goto err; diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 86dc913cd..f7ae7c61f 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -790,7 +790,7 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, break; case RELAY_COMMAND_RENDEZVOUS2: if (origin_circ) - r = rend_client_receive_rendezvous(origin_circ,payload,length); + r = hs_client_receive_rendezvous2(origin_circ,payload,length); break; case RELAY_COMMAND_INTRO_ESTABLISHED: if (origin_circ)
tor-commits@lists.torproject.org