mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
prop224: Handle service INTRO_ESTABLISHED cell
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
d765cf30b5
commit
79e8d113d5
@ -161,3 +161,25 @@ hs_cell_build_establish_intro(const char *circ_nonce,
|
||||
return cell_len;
|
||||
}
|
||||
|
||||
/* Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
|
||||
* are successful at parsing it, return the length of the parsed cell else a
|
||||
* negative value on error. */
|
||||
ssize_t
|
||||
hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
|
||||
{
|
||||
ssize_t ret;
|
||||
trn_cell_intro_established_t *cell = NULL;
|
||||
|
||||
tor_assert(payload);
|
||||
|
||||
/* Try to parse the payload into a cell making sure we do actually have a
|
||||
* valid cell. */
|
||||
ret = trn_cell_intro_established_parse(&cell, payload, payload_len);
|
||||
if (ret >= 0) {
|
||||
/* On success, we do not keep the cell, we just notify the caller that it
|
||||
* was successfully parsed. */
|
||||
trn_cell_intro_established_free(cell);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -15,5 +15,8 @@ ssize_t hs_cell_build_establish_intro(const char *circ_nonce,
|
||||
const hs_service_intro_point_t *ip,
|
||||
uint8_t *cell_out);
|
||||
|
||||
ssize_t hs_cell_parse_intro_established(const uint8_t *payload,
|
||||
size_t payload_len);
|
||||
|
||||
#endif /* TOR_HS_CELL_H */
|
||||
|
||||
|
@ -428,6 +428,46 @@ hs_circ_service_intro_has_opened(hs_service_t *service,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Handle an INTRO_ESTABLISHED cell payload of length payload_len arriving on
|
||||
* the given introduction circuit circ. The service is only used for logging
|
||||
* purposes. Return 0 on success else a negative value. */
|
||||
int
|
||||
hs_circ_handle_intro_established(const hs_service_t *service,
|
||||
const hs_service_intro_point_t *ip,
|
||||
origin_circuit_t *circ,
|
||||
const uint8_t *payload, size_t payload_len)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
tor_assert(service);
|
||||
tor_assert(ip);
|
||||
tor_assert(circ);
|
||||
tor_assert(payload);
|
||||
|
||||
/* Try to parse the payload into a cell making sure we do actually have a
|
||||
* valid cell. For a legacy node, it's an empty payload so as long as we
|
||||
* have the cell, we are good. */
|
||||
if (!ip->base.is_only_legacy &&
|
||||
hs_cell_parse_intro_established(payload, payload_len) < 0) {
|
||||
log_warn(LD_REND, "Unable to parse the INTRO_ESTABLISHED cell on "
|
||||
"circuit %u for service %s",
|
||||
TO_CIRCUIT(circ)->n_circ_id,
|
||||
safe_str_client(service->onion_address));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Switch the purpose to a fully working intro point. */
|
||||
circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_S_INTRO);
|
||||
/* Getting a valid INTRODUCE_ESTABLISHED means we've successfully used the
|
||||
* circuit so update our pathbias subsystem. */
|
||||
pathbias_mark_use_success(circ);
|
||||
/* Success. */
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
|
||||
* exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
|
||||
* serve as a rendezvous end-to-end circuit between the client and the
|
||||
@ -435,7 +475,7 @@ hs_circ_service_intro_has_opened(hs_service_t *service,
|
||||
* and the other side is the client.
|
||||
*
|
||||
* Return 0 if the operation went well; in case of error return -1. */
|
||||
int
|
||||
int
|
||||
hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
|
||||
const uint8_t *ntor_key_seed, size_t seed_len,
|
||||
int is_service_side)
|
||||
|
@ -28,6 +28,11 @@ int hs_circ_launch_intro_point(hs_service_t *service,
|
||||
void hs_circ_send_establish_intro(const hs_service_t *service,
|
||||
hs_service_intro_point_t *ip,
|
||||
origin_circuit_t *circ);
|
||||
int hs_circ_handle_intro_established(const hs_service_t *service,
|
||||
const hs_service_intro_point_t *ip,
|
||||
origin_circuit_t *circ,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len);
|
||||
|
||||
/* e2e circuit API. */
|
||||
|
||||
|
@ -1725,14 +1725,8 @@ service_intro_circ_has_opened(origin_circuit_t *circ)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* From the service object, get the intro point object of that circuit. The
|
||||
* following will query both descriptors intro points list. */
|
||||
ip = service_intro_point_find(service, &circ->hs_ident->intro_auth_pk);
|
||||
if (ip == NULL) {
|
||||
log_warn(LD_REND, "Unknown authentication key on the introduction "
|
||||
"circuit %u for service %s",
|
||||
TO_CIRCUIT(circ)->n_circ_id,
|
||||
safe_str_client(service->onion_address));
|
||||
/* Closing this circuit because we don't recognize the key. */
|
||||
close_reason = END_CIRC_REASON_NOSUCHSERVICE;
|
||||
goto err;
|
||||
@ -1764,10 +1758,103 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ)
|
||||
/* XXX: Implement rendezvous support. */
|
||||
}
|
||||
|
||||
/* Handle an INTRO_ESTABLISHED cell arriving on the given introduction
|
||||
* circuit. Return 0 on success else a negative value. */
|
||||
static int
|
||||
service_handle_intro_established(origin_circuit_t *circ,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len)
|
||||
{
|
||||
hs_service_t *service = NULL;
|
||||
hs_service_intro_point_t *ip = NULL;
|
||||
|
||||
tor_assert(circ);
|
||||
tor_assert(payload);
|
||||
tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
|
||||
|
||||
/* Get service object from the circuit identifier. */
|
||||
service = find_service(hs_service_map, &circ->hs_ident->identity_pk);
|
||||
if (service == NULL) {
|
||||
log_warn(LD_REND, "Unknown service identity key %s on the introduction "
|
||||
"circuit %u. Can't find onion service.",
|
||||
safe_str_client(ed25519_fmt(&circ->hs_ident->identity_pk)),
|
||||
TO_CIRCUIT(circ)->n_circ_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* From the service object, get the intro point object of that circuit. The
|
||||
* following will query both descriptors intro points list. */
|
||||
ip = service_intro_point_find(service, &circ->hs_ident->intro_auth_pk);
|
||||
if (ip == NULL) {
|
||||
/* We don't recognize the key. */
|
||||
log_warn(LD_REND, "Introduction circuit established without an intro "
|
||||
"point object on circuit %u for service %s",
|
||||
TO_CIRCUIT(circ)->n_circ_id,
|
||||
safe_str_client(service->onion_address));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Try to parse the payload into a cell making sure we do actually have a
|
||||
* valid cell. On success, the ip object is updated. */
|
||||
if (hs_circ_handle_intro_established(service, ip, circ, payload,
|
||||
payload_len) < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Flag that we have an established circuit for this intro point. This value
|
||||
* is what indicates the upload scheduled event if we are ready to build the
|
||||
* intro point into the descriptor and upload. */
|
||||
ip->circuit_established = 1;
|
||||
|
||||
log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
|
||||
"on circuit %u for service %s",
|
||||
TO_CIRCUIT(circ)->n_circ_id,
|
||||
safe_str_client(service->onion_address));
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* Public API */
|
||||
/* ========== */
|
||||
|
||||
/* Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an
|
||||
* established introduction point. Return 0 on success else a negative value
|
||||
* and the circuit is closed. */
|
||||
int
|
||||
hs_service_receive_intro_established(origin_circuit_t *circ,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
tor_assert(circ);
|
||||
tor_assert(payload);
|
||||
|
||||
if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
||||
log_warn(LD_PROTOCOL, "Received an INTRO_ESTABLISHED cell on a "
|
||||
"non introduction circuit of purpose %d",
|
||||
TO_CIRCUIT(circ)->purpose);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Handle both version. v2 uses rend_data and v3 uses the hs circuit
|
||||
* identifier hs_ident. Can't be both. */
|
||||
ret = (circ->hs_ident) ? service_handle_intro_established(circ, payload,
|
||||
payload_len) :
|
||||
rend_service_intro_established(circ, payload,
|
||||
payload_len);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Called when any kind of hidden service circuit is done building thus
|
||||
* opened. This is the entry point from the circuit subsystem. */
|
||||
void
|
||||
|
@ -232,6 +232,9 @@ int hs_service_load_all_keys(void);
|
||||
|
||||
void hs_service_run_scheduled_events(time_t now);
|
||||
void hs_service_circuit_has_opened(origin_circuit_t *circ);
|
||||
int hs_service_receive_intro_established(origin_circuit_t *circ,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len);
|
||||
|
||||
/* These functions are only used by unit tests and we need to expose them else
|
||||
* hs_service.o ends up with no symbols in libor.a which makes clang throw a
|
||||
|
@ -793,7 +793,7 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
|
||||
break;
|
||||
case RELAY_COMMAND_INTRO_ESTABLISHED:
|
||||
if (origin_circ)
|
||||
r = rend_service_intro_established(origin_circ,payload,length);
|
||||
r = hs_service_receive_intro_established(origin_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
|
||||
if (origin_circ)
|
||||
|
Loading…
Reference in New Issue
Block a user