mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 13:53:31 +01:00
Merge branch 'ticket30428_041_02_squashed'
This commit is contained in:
commit
e6b862e6a8
@ -121,8 +121,8 @@ problem file-size /src/core/or/policies.c 3249
|
|||||||
problem function-size /src/core/or/policies.c:policy_summarize() 107
|
problem function-size /src/core/or/policies.c:policy_summarize() 107
|
||||||
problem function-size /src/core/or/protover.c:protover_all_supported() 117
|
problem function-size /src/core/or/protover.c:protover_all_supported() 117
|
||||||
problem file-size /src/core/or/relay.c 3173
|
problem file-size /src/core/or/relay.c 3173
|
||||||
problem function-size /src/core/or/relay.c:circuit_receive_relay_cell() 123
|
problem function-size /src/core/or/relay.c:circuit_receive_relay_cell() 127
|
||||||
problem function-size /src/core/or/relay.c:relay_send_command_from_edge_() 112
|
problem function-size /src/core/or/relay.c:relay_send_command_from_edge_() 116
|
||||||
problem function-size /src/core/or/relay.c:connection_ap_process_end_not_open() 194
|
problem function-size /src/core/or/relay.c:connection_ap_process_end_not_open() 194
|
||||||
problem function-size /src/core/or/relay.c:connection_edge_process_relay_cell_not_open() 139
|
problem function-size /src/core/or/relay.c:connection_edge_process_relay_cell_not_open() 139
|
||||||
problem function-size /src/core/or/relay.c:connection_edge_process_relay_cell() 520
|
problem function-size /src/core/or/relay.c:connection_edge_process_relay_cell() 520
|
||||||
|
@ -100,12 +100,22 @@ relay_crypto_get_sendme_digest(relay_crypto_t *crypto)
|
|||||||
return crypto->sendme_digest;
|
return crypto->sendme_digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Record the b_digest from <b>crypto</b> and put it in the sendme_digest. */
|
/** Record the cell digest, indicated by is_foward_digest or not, as the
|
||||||
|
* SENDME cell digest. */
|
||||||
void
|
void
|
||||||
relay_crypto_record_sendme_digest(relay_crypto_t *crypto)
|
relay_crypto_record_sendme_digest(relay_crypto_t *crypto,
|
||||||
|
bool is_foward_digest)
|
||||||
{
|
{
|
||||||
|
struct crypto_digest_t *digest;
|
||||||
|
|
||||||
tor_assert(crypto);
|
tor_assert(crypto);
|
||||||
crypto_digest_get_digest(crypto->b_digest, (char *) crypto->sendme_digest,
|
|
||||||
|
digest = crypto->b_digest;
|
||||||
|
if (is_foward_digest) {
|
||||||
|
digest = crypto->f_digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_digest_get_digest(digest, (char *) crypto->sendme_digest,
|
||||||
sizeof(crypto->sendme_digest));
|
sizeof(crypto->sendme_digest));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,11 +171,6 @@ relay_decrypt_cell(circuit_t *circ, cell_t *cell,
|
|||||||
if (relay_digest_matches(cpath_get_incoming_digest(thishop), cell)) {
|
if (relay_digest_matches(cpath_get_incoming_digest(thishop), cell)) {
|
||||||
*recognized = 1;
|
*recognized = 1;
|
||||||
*layer_hint = thishop;
|
*layer_hint = thishop;
|
||||||
/* This cell is for us. Keep a record of this cell because we will
|
|
||||||
* use it in the next SENDME cell. */
|
|
||||||
if (sendme_circuit_cell_is_next(thishop->deliver_window)) {
|
|
||||||
cpath_sendme_circuit_record_inbound_cell(thishop);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,6 +218,9 @@ relay_encrypt_cell_outbound(cell_t *cell,
|
|||||||
crypt_path_t *thishop; /* counter for repeated crypts */
|
crypt_path_t *thishop; /* counter for repeated crypts */
|
||||||
cpath_set_cell_forward_digest(layer_hint, cell);
|
cpath_set_cell_forward_digest(layer_hint, cell);
|
||||||
|
|
||||||
|
/* Record cell digest as the SENDME digest if need be. */
|
||||||
|
sendme_record_sending_cell_digest(TO_CIRCUIT(circ), layer_hint);
|
||||||
|
|
||||||
thishop = layer_hint;
|
thishop = layer_hint;
|
||||||
/* moving from farthest to nearest hop */
|
/* moving from farthest to nearest hop */
|
||||||
do {
|
do {
|
||||||
@ -237,11 +245,8 @@ relay_encrypt_cell_inbound(cell_t *cell,
|
|||||||
{
|
{
|
||||||
relay_set_digest(or_circ->crypto.b_digest, cell);
|
relay_set_digest(or_circ->crypto.b_digest, cell);
|
||||||
|
|
||||||
/* We are about to send this cell outbound on the circuit. Keep a record of
|
/* Record cell digest as the SENDME digest if need be. */
|
||||||
* this cell if we are expecting that the next cell is a SENDME. */
|
sendme_record_sending_cell_digest(TO_CIRCUIT(or_circ), NULL);
|
||||||
if (sendme_circuit_cell_is_next(TO_CIRCUIT(or_circ)->package_window)) {
|
|
||||||
sendme_circuit_record_outbound_cell(or_circ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* encrypt one layer */
|
/* encrypt one layer */
|
||||||
relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload);
|
relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload);
|
||||||
|
@ -28,7 +28,10 @@ void relay_crypto_clear(relay_crypto_t *crypto);
|
|||||||
void relay_crypto_assert_ok(const relay_crypto_t *crypto);
|
void relay_crypto_assert_ok(const relay_crypto_t *crypto);
|
||||||
|
|
||||||
uint8_t *relay_crypto_get_sendme_digest(relay_crypto_t *crypto);
|
uint8_t *relay_crypto_get_sendme_digest(relay_crypto_t *crypto);
|
||||||
void relay_crypto_record_sendme_digest(relay_crypto_t *crypto);
|
|
||||||
|
void relay_crypto_record_sendme_digest(relay_crypto_t *crypto,
|
||||||
|
bool is_foward_digest);
|
||||||
|
|
||||||
void
|
void
|
||||||
relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in);
|
relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in);
|
||||||
|
|
||||||
|
@ -115,12 +115,11 @@ struct circuit_t {
|
|||||||
* list can not contain more than 10 digests of DIGEST_LEN bytes (20).
|
* list can not contain more than 10 digests of DIGEST_LEN bytes (20).
|
||||||
*
|
*
|
||||||
* At position i in the list, the digest corresponds to the
|
* At position i in the list, the digest corresponds to the
|
||||||
* ((CIRCWINDOW_INCREMENT * i) - 1)-nth cell received since we expect the
|
* (CIRCWINDOW_INCREMENT * i)-nth cell received since we expect a SENDME to
|
||||||
* (CIRCWINDOW_INCREMENT * i)-nth cell to be the SENDME and thus containing
|
* be received containing that cell digest.
|
||||||
* the previous cell digest.
|
|
||||||
*
|
*
|
||||||
* For example, position 2 (starting at 0) means that we've received 299
|
* For example, position 2 (starting at 0) means that we've received 300
|
||||||
* cells and the 299th cell digest is kept at index 2.
|
* cells so the 300th cell digest is kept at index 2.
|
||||||
*
|
*
|
||||||
* At maximum, this list contains 200 bytes plus the smartlist overhead. */
|
* At maximum, this list contains 200 bytes plus the smartlist overhead. */
|
||||||
smartlist_t *sendme_last_digests;
|
smartlist_t *sendme_last_digests;
|
||||||
|
@ -204,15 +204,6 @@ cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell)
|
|||||||
|
|
||||||
/************ cpath sendme API ***************************/
|
/************ cpath sendme API ***************************/
|
||||||
|
|
||||||
/** Keep the current inbound cell digest for the next SENDME digest. This part
|
|
||||||
* is only done by the client as the circuit came back from the Exit. */
|
|
||||||
void
|
|
||||||
cpath_sendme_circuit_record_inbound_cell(crypt_path_t *cpath)
|
|
||||||
{
|
|
||||||
tor_assert(cpath);
|
|
||||||
relay_crypto_record_sendme_digest(&cpath->pvt_crypto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the sendme_digest of this <b>cpath</b>. */
|
/** Return the sendme_digest of this <b>cpath</b>. */
|
||||||
uint8_t *
|
uint8_t *
|
||||||
cpath_get_sendme_digest(crypt_path_t *cpath)
|
cpath_get_sendme_digest(crypt_path_t *cpath)
|
||||||
@ -220,6 +211,15 @@ cpath_get_sendme_digest(crypt_path_t *cpath)
|
|||||||
return relay_crypto_get_sendme_digest(&cpath->pvt_crypto);
|
return relay_crypto_get_sendme_digest(&cpath->pvt_crypto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Record the cell digest, indicated by is_foward_digest or not, as the
|
||||||
|
* SENDME cell digest. */
|
||||||
|
void
|
||||||
|
cpath_sendme_record_cell_digest(crypt_path_t *cpath, bool is_foward_digest)
|
||||||
|
{
|
||||||
|
tor_assert(cpath);
|
||||||
|
relay_crypto_record_sendme_digest(&cpath->pvt_crypto, is_foward_digest);
|
||||||
|
}
|
||||||
|
|
||||||
/************ other cpath functions ***************************/
|
/************ other cpath functions ***************************/
|
||||||
|
|
||||||
/** Return the first non-open hop in cpath, or return NULL if all
|
/** Return the first non-open hop in cpath, or return NULL if all
|
||||||
|
@ -27,6 +27,9 @@ cpath_crypt_cell(const crypt_path_t *cpath, uint8_t *payload, bool is_decrypt);
|
|||||||
struct crypto_digest_t *
|
struct crypto_digest_t *
|
||||||
cpath_get_incoming_digest(const crypt_path_t *cpath);
|
cpath_get_incoming_digest(const crypt_path_t *cpath);
|
||||||
|
|
||||||
|
void cpath_sendme_record_cell_digest(crypt_path_t *cpath,
|
||||||
|
bool is_foward_digest);
|
||||||
|
|
||||||
void
|
void
|
||||||
cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell);
|
cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell);
|
||||||
|
|
||||||
|
@ -247,6 +247,10 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
|||||||
if (recognized) {
|
if (recognized) {
|
||||||
edge_connection_t *conn = NULL;
|
edge_connection_t *conn = NULL;
|
||||||
|
|
||||||
|
/* Recognized cell, the cell digest has been updated, we'll record it for
|
||||||
|
* the SENDME if need be. */
|
||||||
|
sendme_record_received_cell_digest(circ, layer_hint);
|
||||||
|
|
||||||
if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
|
if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
|
||||||
if (pathbias_check_probe_response(circ, cell) == -1) {
|
if (pathbias_check_probe_response(circ, cell) == -1) {
|
||||||
pathbias_count_valid_cells(circ, cell);
|
pathbias_count_valid_cells(circ, cell);
|
||||||
@ -701,7 +705,7 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *circ,
|
|||||||
* we need to. This call needs to be after the circuit_package_relay_cell()
|
* we need to. This call needs to be after the circuit_package_relay_cell()
|
||||||
* because the cell digest is set within that function. */
|
* because the cell digest is set within that function. */
|
||||||
if (relay_command == RELAY_COMMAND_DATA) {
|
if (relay_command == RELAY_COMMAND_DATA) {
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, cpath_layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -25,20 +25,6 @@
|
|||||||
#include "lib/ctime/di_ops.h"
|
#include "lib/ctime/di_ops.h"
|
||||||
#include "trunnel/sendme.h"
|
#include "trunnel/sendme.h"
|
||||||
|
|
||||||
/* The maximum supported version. Above that value, the cell can't be
|
|
||||||
* recognized as a valid SENDME. */
|
|
||||||
#define SENDME_MAX_SUPPORTED_VERSION 1
|
|
||||||
|
|
||||||
/* The cell version constants for when emitting a cell. */
|
|
||||||
#define SENDME_EMIT_MIN_VERSION_DEFAULT 0
|
|
||||||
#define SENDME_EMIT_MIN_VERSION_MIN 0
|
|
||||||
#define SENDME_EMIT_MIN_VERSION_MAX UINT8_MAX
|
|
||||||
|
|
||||||
/* The cell version constants for when accepting a cell. */
|
|
||||||
#define SENDME_ACCEPT_MIN_VERSION_DEFAULT 0
|
|
||||||
#define SENDME_ACCEPT_MIN_VERSION_MIN 0
|
|
||||||
#define SENDME_ACCEPT_MIN_VERSION_MAX UINT8_MAX
|
|
||||||
|
|
||||||
/* Return the minimum version given by the consensus (if any) that should be
|
/* Return the minimum version given by the consensus (if any) that should be
|
||||||
* used when emitting a SENDME cell. */
|
* used when emitting a SENDME cell. */
|
||||||
STATIC int
|
STATIC int
|
||||||
@ -61,47 +47,53 @@ get_accept_min_version(void)
|
|||||||
SENDME_ACCEPT_MIN_VERSION_MAX);
|
SENDME_ACCEPT_MIN_VERSION_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pop the first cell digset on the given circuit from the SENDME last digests
|
||||||
|
* list. NULL is returned if the list is uninitialized or empty.
|
||||||
|
*
|
||||||
|
* The caller gets ownership of the returned digest thus is responsible for
|
||||||
|
* freeing the memory. */
|
||||||
|
static uint8_t *
|
||||||
|
pop_first_cell_digest(const circuit_t *circ)
|
||||||
|
{
|
||||||
|
uint8_t *circ_digest;
|
||||||
|
|
||||||
|
tor_assert(circ);
|
||||||
|
|
||||||
|
if (circ->sendme_last_digests == NULL ||
|
||||||
|
smartlist_len(circ->sendme_last_digests) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* More cell digest than the SENDME window is never suppose to happen. The
|
||||||
|
* cell should have been rejected before reaching this point due to its
|
||||||
|
* package_window down to 0 leading to a circuit close. Scream loudly but
|
||||||
|
* still pop the element so we don't memory leak. */
|
||||||
|
tor_assert_nonfatal(smartlist_len(circ->sendme_last_digests) <=
|
||||||
|
CIRCWINDOW_START_MAX / CIRCWINDOW_INCREMENT);
|
||||||
|
|
||||||
|
circ_digest = smartlist_get(circ->sendme_last_digests, 0);
|
||||||
|
smartlist_del_keeporder(circ->sendme_last_digests, 0);
|
||||||
|
return circ_digest;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return true iff the given cell digest matches the first digest in the
|
/* Return true iff the given cell digest matches the first digest in the
|
||||||
* circuit sendme list. */
|
* circuit sendme list. */
|
||||||
static bool
|
static bool
|
||||||
v1_digest_matches(const circuit_t *circ, const uint8_t *cell_digest)
|
v1_digest_matches(const uint8_t *circ_digest, const uint8_t *cell_digest)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
tor_assert(circ_digest);
|
||||||
uint8_t *circ_digest = NULL;
|
|
||||||
|
|
||||||
tor_assert(circ);
|
|
||||||
tor_assert(cell_digest);
|
tor_assert(cell_digest);
|
||||||
|
|
||||||
/* We shouldn't have received a SENDME if we have no digests. Log at
|
|
||||||
* protocol warning because it can be tricked by sending many SENDMEs
|
|
||||||
* without prior data cell. */
|
|
||||||
if (circ->sendme_last_digests == NULL ||
|
|
||||||
smartlist_len(circ->sendme_last_digests) == 0) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
||||||
"We received a SENDME but we have no cell digests to match. "
|
|
||||||
"Closing circuit.");
|
|
||||||
goto no_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pop the first element that was added (FIFO) and compare it. */
|
|
||||||
circ_digest = smartlist_get(circ->sendme_last_digests, 0);
|
|
||||||
smartlist_del_keeporder(circ->sendme_last_digests, 0);
|
|
||||||
|
|
||||||
/* Compare the digest with the one in the SENDME. This cell is invalid
|
/* Compare the digest with the one in the SENDME. This cell is invalid
|
||||||
* without a perfect match. */
|
* without a perfect match. */
|
||||||
if (tor_memneq(circ_digest, cell_digest, TRUNNEL_SENDME_V1_DIGEST_LEN)) {
|
if (tor_memneq(circ_digest, cell_digest, TRUNNEL_SENDME_V1_DIGEST_LEN)) {
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||||
"SENDME v1 cell digest do not match.");
|
"SENDME v1 cell digest do not match.");
|
||||||
goto no_match;
|
return false;
|
||||||
}
|
}
|
||||||
/* Digests matches! */
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
no_match:
|
/* Digests matches! */
|
||||||
/* This digest was popped from the circuit list. Regardless of what happens,
|
return true;
|
||||||
* we have no more use for it. */
|
|
||||||
tor_free(circ_digest);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true iff the given decoded SENDME version 1 cell is valid and
|
/* Return true iff the given decoded SENDME version 1 cell is valid and
|
||||||
@ -111,42 +103,53 @@ v1_digest_matches(const circuit_t *circ, const uint8_t *cell_digest)
|
|||||||
* cell we saw which tells us that the other side has in fact seen that cell.
|
* cell we saw which tells us that the other side has in fact seen that cell.
|
||||||
* See proposal 289 for more details. */
|
* See proposal 289 for more details. */
|
||||||
static bool
|
static bool
|
||||||
cell_v1_is_valid(const sendme_cell_t *cell, const circuit_t *circ)
|
cell_v1_is_valid(const sendme_cell_t *cell, const uint8_t *circ_digest)
|
||||||
{
|
{
|
||||||
tor_assert(cell);
|
tor_assert(cell);
|
||||||
tor_assert(circ);
|
tor_assert(circ_digest);
|
||||||
|
|
||||||
const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell);
|
const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell);
|
||||||
return v1_digest_matches(circ, cell_digest);
|
return v1_digest_matches(circ_digest, cell_digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true iff the given cell version can be handled or if the minimum
|
/* Return true iff the given cell version can be handled or if the minimum
|
||||||
* accepted version from the consensus is known to us. */
|
* accepted version from the consensus is known to us. */
|
||||||
STATIC bool
|
STATIC bool
|
||||||
cell_version_is_valid(uint8_t cell_version)
|
cell_version_can_be_handled(uint8_t cell_version)
|
||||||
{
|
{
|
||||||
int accept_version = get_accept_min_version();
|
int accept_version = get_accept_min_version();
|
||||||
|
|
||||||
/* Can we handle this version? */
|
/* We will first check if the consensus minimum accepted version can be
|
||||||
|
* handled by us and if not, regardless of the cell version we got, we can't
|
||||||
|
* continue. */
|
||||||
if (accept_version > SENDME_MAX_SUPPORTED_VERSION) {
|
if (accept_version > SENDME_MAX_SUPPORTED_VERSION) {
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||||
"Unable to accept SENDME version %u (from consensus). "
|
"Unable to accept SENDME version %u (from consensus). "
|
||||||
"We only support <= %d. Probably your tor is too old?",
|
"We only support <= %u. Probably your tor is too old?",
|
||||||
accept_version, cell_version);
|
accept_version, SENDME_MAX_SUPPORTED_VERSION);
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We only accept a SENDME cell from what the consensus tells us. */
|
/* Then, is this version below the accepted version from the consensus? If
|
||||||
|
* yes, we must not handle it. */
|
||||||
if (cell_version < accept_version) {
|
if (cell_version < accept_version) {
|
||||||
log_info(LD_PROTOCOL, "Unacceptable SENDME version %d. Only "
|
log_info(LD_PROTOCOL, "Unacceptable SENDME version %u. Only "
|
||||||
"accepting %u (from consensus). Closing circuit.",
|
"accepting %u (from consensus). Closing circuit.",
|
||||||
cell_version, accept_version);
|
cell_version, accept_version);
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
/* Is this cell version supported by us? */
|
||||||
|
if (cell_version > SENDME_MAX_SUPPORTED_VERSION) {
|
||||||
|
log_info(LD_PROTOCOL, "SENDME cell version %u is not supported by us. "
|
||||||
|
"We only support <= %u",
|
||||||
|
cell_version, SENDME_MAX_SUPPORTED_VERSION);
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
invalid:
|
invalid:
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true iff the encoded SENDME cell in cell_payload of length
|
/* Return true iff the encoded SENDME cell in cell_payload of length
|
||||||
@ -163,6 +166,7 @@ sendme_is_valid(const circuit_t *circ, const uint8_t *cell_payload,
|
|||||||
size_t cell_payload_len)
|
size_t cell_payload_len)
|
||||||
{
|
{
|
||||||
uint8_t cell_version;
|
uint8_t cell_version;
|
||||||
|
uint8_t *circ_digest = NULL;
|
||||||
sendme_cell_t *cell = NULL;
|
sendme_cell_t *cell = NULL;
|
||||||
|
|
||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
@ -183,31 +187,50 @@ sendme_is_valid(const circuit_t *circ, const uint8_t *cell_payload,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Validate that we can handle this cell version. */
|
/* Validate that we can handle this cell version. */
|
||||||
if (!cell_version_is_valid(cell_version)) {
|
if (!cell_version_can_be_handled(cell_version)) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pop the first element that was added (FIFO). We do that regardless of the
|
||||||
|
* version so we don't accumulate on the circuit if v0 is used by the other
|
||||||
|
* end point. */
|
||||||
|
circ_digest = pop_first_cell_digest(circ);
|
||||||
|
if (circ_digest == NULL) {
|
||||||
|
/* We shouldn't have received a SENDME if we have no digests. Log at
|
||||||
|
* protocol warning because it can be tricked by sending many SENDMEs
|
||||||
|
* without prior data cell. */
|
||||||
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||||
|
"We received a SENDME but we have no cell digests to match. "
|
||||||
|
"Closing circuit.");
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate depending on the version now. */
|
/* Validate depending on the version now. */
|
||||||
switch (cell_version) {
|
switch (cell_version) {
|
||||||
case 0x01:
|
case 0x01:
|
||||||
if (!cell_v1_is_valid(cell, circ)) {
|
if (!cell_v1_is_valid(cell, circ_digest)) {
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x00:
|
case 0x00:
|
||||||
/* Fallthrough. Version 0, there is no work to be done on the payload so
|
/* Version 0, there is no work to be done on the payload so it is
|
||||||
* it is necessarily valid if we pass the version validation. */
|
* necessarily valid if we pass the version validation. */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown version means we can't handle it so fallback to version 0. */
|
log_warn(LD_PROTOCOL, "Unknown SENDME cell version %d received.",
|
||||||
|
cell_version);
|
||||||
|
tor_assert_nonfatal_unreached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Valid cell. */
|
/* Valid cell. */
|
||||||
sendme_cell_free(cell);
|
sendme_cell_free(cell);
|
||||||
return 1;
|
tor_free(circ_digest);
|
||||||
|
return true;
|
||||||
invalid:
|
invalid:
|
||||||
sendme_cell_free(cell);
|
sendme_cell_free(cell);
|
||||||
return 0;
|
tor_free(circ_digest);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build and encode a version 1 SENDME cell into payload, which must be at
|
/* Build and encode a version 1 SENDME cell into payload, which must be at
|
||||||
@ -274,6 +297,8 @@ send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
|
|||||||
default:
|
default:
|
||||||
/* Unknown version, fallback to version 0 meaning no payload. */
|
/* Unknown version, fallback to version 0 meaning no payload. */
|
||||||
payload_len = 0;
|
payload_len = 0;
|
||||||
|
log_debug(LD_PROTOCOL, "Emitting SENDME version 0 cell. "
|
||||||
|
"Consensus emit version is %d", emit_version);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,34 +312,54 @@ send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Record the cell digest only if the next cell is expected to be a SENDME. */
|
||||||
|
static void
|
||||||
|
record_cell_digest_on_circ(circuit_t *circ, const uint8_t *sendme_digest)
|
||||||
|
{
|
||||||
|
tor_assert(circ);
|
||||||
|
tor_assert(sendme_digest);
|
||||||
|
|
||||||
|
/* Add the digest to the last seen list in the circuit. */
|
||||||
|
if (circ->sendme_last_digests == NULL) {
|
||||||
|
circ->sendme_last_digests = smartlist_new();
|
||||||
|
}
|
||||||
|
smartlist_add(circ->sendme_last_digests,
|
||||||
|
tor_memdup(sendme_digest, DIGEST_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Public API
|
* Public API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Keep the current inbound cell digest for the next SENDME digest. This part
|
|
||||||
* is only done by the client as the circuit came back from the Exit. */
|
|
||||||
void
|
|
||||||
sendme_circuit_record_outbound_cell(or_circuit_t *or_circ)
|
|
||||||
{
|
|
||||||
tor_assert(or_circ);
|
|
||||||
relay_crypto_record_sendme_digest(&or_circ->crypto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return true iff the next cell for the given cell window is expected to be
|
/** Return true iff the next cell for the given cell window is expected to be
|
||||||
* a SENDME.
|
* a SENDME.
|
||||||
*
|
*
|
||||||
* We are able to know that because the package or deliver window value minus
|
* We are able to know that because the package or deliver window value minus
|
||||||
* one cell (the possible SENDME cell) should be a multiple of the increment
|
* one cell (the possible SENDME cell) should be a multiple of the increment
|
||||||
* window value. */
|
* window value. */
|
||||||
bool
|
static bool
|
||||||
sendme_circuit_cell_is_next(int window)
|
circuit_sendme_cell_is_next(int window)
|
||||||
{
|
{
|
||||||
/* Is this the last cell before a SENDME? The idea is that if the package or
|
/* At the start of the window, no SENDME will be expected. */
|
||||||
* deliver window reaches a multiple of the increment, after this cell, we
|
if (window == CIRCWINDOW_START) {
|
||||||
* should expect a SENDME. */
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are we at the limit of the increment and if not, we don't expect next
|
||||||
|
* cell is a SENDME.
|
||||||
|
*
|
||||||
|
* We test against the window minus 1 because when we are looking if the
|
||||||
|
* next cell is a SENDME, the window (either package or deliver) hasn't been
|
||||||
|
* decremented just yet so when this is called, we are currently processing
|
||||||
|
* the "window - 1" cell.
|
||||||
|
*
|
||||||
|
* This function is used when recording a cell digest and this is done quite
|
||||||
|
* low in the stack when decrypting or encrypting a cell. The window is only
|
||||||
|
* updated once the cell is actually put in the outbuf. */
|
||||||
if (((window - 1) % CIRCWINDOW_INCREMENT) != 0) {
|
if (((window - 1) % CIRCWINDOW_INCREMENT) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next cell is expected to be a SENDME. */
|
/* Next cell is expected to be a SENDME. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -372,6 +417,7 @@ sendme_connection_edge_consider_sending(edge_connection_t *conn)
|
|||||||
void
|
void
|
||||||
sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
|
sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
|
||||||
{
|
{
|
||||||
|
bool sent_one_sendme = false;
|
||||||
const uint8_t *digest;
|
const uint8_t *digest;
|
||||||
|
|
||||||
while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
|
while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
|
||||||
@ -387,6 +433,12 @@ sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
|
|||||||
if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) {
|
if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) {
|
||||||
return; /* The circuit's closed, don't continue */
|
return; /* The circuit's closed, don't continue */
|
||||||
}
|
}
|
||||||
|
/* Current implementation is not suppose to send multiple SENDME at once
|
||||||
|
* because this means we would use the same relay crypto digest for each
|
||||||
|
* SENDME leading to a mismatch on the other side and the circuit to
|
||||||
|
* collapse. Scream loudly if it ever happens so we can address it. */
|
||||||
|
tor_assert_nonfatal(!sent_one_sendme);
|
||||||
|
sent_one_sendme = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,6 +461,12 @@ sendme_process_circuit_level(crypt_path_t *layer_hint,
|
|||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
tor_assert(cell_payload);
|
tor_assert(cell_payload);
|
||||||
|
|
||||||
|
/* Validate the SENDME cell. Depending on the version, different validation
|
||||||
|
* can be done. An invalid SENDME requires us to close the circuit. */
|
||||||
|
if (!sendme_is_valid(circ, cell_payload, cell_payload_len)) {
|
||||||
|
return -END_CIRC_REASON_TORPROTOCOL;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we are the origin of the circuit, we are the Client so we use the
|
/* If we are the origin of the circuit, we are the Client so we use the
|
||||||
* layer hint (the Exit hop) for the package window tracking. */
|
* layer hint (the Exit hop) for the package window tracking. */
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
@ -433,13 +491,6 @@ sendme_process_circuit_level(crypt_path_t *layer_hint,
|
|||||||
* are rate limited. */
|
* are rate limited. */
|
||||||
circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_payload_len);
|
circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_payload_len);
|
||||||
} else {
|
} else {
|
||||||
/* Validate the SENDME cell. Depending on the version, different
|
|
||||||
* validation can be done. An invalid SENDME requires us to close the
|
|
||||||
* circuit. It is only done if we are the Exit of the circuit. */
|
|
||||||
if (!sendme_is_valid(circ, cell_payload, cell_payload_len)) {
|
|
||||||
return -END_CIRC_REASON_TORPROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We aren't the origin of this circuit so we are the Exit and thus we
|
/* We aren't the origin of this circuit so we are the Exit and thus we
|
||||||
* track the package window with the circuit object. */
|
* track the package window with the circuit object. */
|
||||||
if ((circ->package_window + CIRCWINDOW_INCREMENT) >
|
if ((circ->package_window + CIRCWINDOW_INCREMENT) >
|
||||||
@ -568,34 +619,90 @@ int
|
|||||||
sendme_note_stream_data_packaged(edge_connection_t *conn)
|
sendme_note_stream_data_packaged(edge_connection_t *conn)
|
||||||
{
|
{
|
||||||
tor_assert(conn);
|
tor_assert(conn);
|
||||||
return --conn->package_window;
|
log_debug(LD_APP, "Stream package_window now %d.", --conn->package_window);
|
||||||
|
return conn->package_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note the cell digest in the circuit sendme last digests FIFO if applicable.
|
/* Record the cell digest into the circuit sendme digest list depending on
|
||||||
* It is safe to pass a circuit that isn't meant to track those digests. */
|
* which edge we are. The digest is recorded only if we expect the next cell
|
||||||
|
* that we will receive is a SENDME so we can match the digest. */
|
||||||
void
|
void
|
||||||
sendme_record_cell_digest(circuit_t *circ)
|
sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath)
|
||||||
{
|
{
|
||||||
const uint8_t *digest;
|
int package_window;
|
||||||
|
uint8_t *sendme_digest;
|
||||||
|
|
||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
|
|
||||||
/* We only keep the cell digest if we are the Exit on that circuit and if
|
package_window = circ->package_window;
|
||||||
* this cell is the last one before the client should send a SENDME. */
|
if (cpath) {
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
package_window = cpath->package_window;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this the last cell before a SENDME? The idea is that if the
|
/* Is this the last cell before a SENDME? The idea is that if the
|
||||||
* package_window reaches a multiple of the increment, after this cell, we
|
* package_window reaches a multiple of the increment, after this cell, we
|
||||||
* should expect a SENDME. */
|
* should expect a SENDME. */
|
||||||
if (!sendme_circuit_cell_is_next(circ->package_window)) {
|
if (!circuit_sendme_cell_is_next(package_window)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the digest to the last seen list in the circuit. */
|
/* Getting the digest is expensive so we only do it once we are certain to
|
||||||
digest = relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto);
|
* record it on the circuit. */
|
||||||
if (circ->sendme_last_digests == NULL) {
|
if (cpath) {
|
||||||
circ->sendme_last_digests = smartlist_new();
|
sendme_digest = cpath_get_sendme_digest(cpath);
|
||||||
|
} else {
|
||||||
|
sendme_digest =
|
||||||
|
relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto);
|
||||||
}
|
}
|
||||||
smartlist_add(circ->sendme_last_digests, tor_memdup(digest, DIGEST_LEN));
|
|
||||||
|
record_cell_digest_on_circ(circ, sendme_digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called once we decrypted a cell and recognized it. Record the cell digest
|
||||||
|
* as the next sendme digest only if the next cell we'll send on the circuit
|
||||||
|
* is expected to be a SENDME. */
|
||||||
|
void
|
||||||
|
sendme_record_received_cell_digest(circuit_t *circ, crypt_path_t *cpath)
|
||||||
|
{
|
||||||
|
tor_assert(circ);
|
||||||
|
|
||||||
|
/* Only record if the next cell is expected to be a SENDME. */
|
||||||
|
if (!circuit_sendme_cell_is_next(cpath ? cpath->deliver_window :
|
||||||
|
circ->deliver_window)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpath) {
|
||||||
|
/* Record incoming digest. */
|
||||||
|
cpath_sendme_record_cell_digest(cpath, false);
|
||||||
|
} else {
|
||||||
|
/* Record foward digest. */
|
||||||
|
relay_crypto_record_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called once we encrypted a cell. Record the cell digest as the next sendme
|
||||||
|
* digest only if the next cell we expect to receive is a SENDME so we can
|
||||||
|
* match the digests. */
|
||||||
|
void
|
||||||
|
sendme_record_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath)
|
||||||
|
{
|
||||||
|
tor_assert(circ);
|
||||||
|
|
||||||
|
/* Only record if the next cell is expected to be a SENDME. */
|
||||||
|
if (!circuit_sendme_cell_is_next(cpath ? cpath->package_window :
|
||||||
|
circ->package_window)) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpath) {
|
||||||
|
/* Record the forward digest. */
|
||||||
|
cpath_sendme_record_cell_digest(cpath, true);
|
||||||
|
} else {
|
||||||
|
/* Record the incoming digest. */
|
||||||
|
relay_crypto_record_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
@ -34,16 +34,29 @@ int sendme_note_circuit_data_packaged(circuit_t *circ,
|
|||||||
crypt_path_t *layer_hint);
|
crypt_path_t *layer_hint);
|
||||||
int sendme_note_stream_data_packaged(edge_connection_t *conn);
|
int sendme_note_stream_data_packaged(edge_connection_t *conn);
|
||||||
|
|
||||||
/* Track cell digest. */
|
/* Record cell digest on circuit. */
|
||||||
void sendme_record_cell_digest(circuit_t *circ);
|
void sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath);
|
||||||
void sendme_circuit_record_outbound_cell(or_circuit_t *or_circ);
|
/* Record cell digest as the SENDME digest. */
|
||||||
|
void sendme_record_received_cell_digest(circuit_t *circ, crypt_path_t *cpath);
|
||||||
/* Circuit level information. */
|
void sendme_record_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath);
|
||||||
bool sendme_circuit_cell_is_next(int window);
|
|
||||||
|
|
||||||
/* Private section starts. */
|
/* Private section starts. */
|
||||||
#ifdef SENDME_PRIVATE
|
#ifdef SENDME_PRIVATE
|
||||||
|
|
||||||
|
/* The maximum supported version. Above that value, the cell can't be
|
||||||
|
* recognized as a valid SENDME. */
|
||||||
|
#define SENDME_MAX_SUPPORTED_VERSION 1
|
||||||
|
|
||||||
|
/* The cell version constants for when emitting a cell. */
|
||||||
|
#define SENDME_EMIT_MIN_VERSION_DEFAULT 0
|
||||||
|
#define SENDME_EMIT_MIN_VERSION_MIN 0
|
||||||
|
#define SENDME_EMIT_MIN_VERSION_MAX UINT8_MAX
|
||||||
|
|
||||||
|
/* The cell version constants for when accepting a cell. */
|
||||||
|
#define SENDME_ACCEPT_MIN_VERSION_DEFAULT 0
|
||||||
|
#define SENDME_ACCEPT_MIN_VERSION_MIN 0
|
||||||
|
#define SENDME_ACCEPT_MIN_VERSION_MAX UINT8_MAX
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unit tests declaractions.
|
* Unit tests declaractions.
|
||||||
*/
|
*/
|
||||||
@ -52,7 +65,7 @@ bool sendme_circuit_cell_is_next(int window);
|
|||||||
STATIC int get_emit_min_version(void);
|
STATIC int get_emit_min_version(void);
|
||||||
STATIC int get_accept_min_version(void);
|
STATIC int get_accept_min_version(void);
|
||||||
|
|
||||||
STATIC bool cell_version_is_valid(uint8_t cell_version);
|
STATIC bool cell_version_can_be_handled(uint8_t cell_version);
|
||||||
|
|
||||||
STATIC ssize_t build_cell_payload_v1(const uint8_t *cell_digest,
|
STATIC ssize_t build_cell_payload_v1(const uint8_t *cell_digest,
|
||||||
uint8_t *payload);
|
uint8_t *payload);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "core/or/circuitbuild.h"
|
#include "core/or/circuitbuild.h"
|
||||||
#include "core/or/circuitlist.h"
|
#include "core/or/circuitlist.h"
|
||||||
#include "core/or/connection_edge.h"
|
#include "core/or/connection_edge.h"
|
||||||
|
#include "core/or/sendme.h"
|
||||||
#include "core/or/relay.h"
|
#include "core/or/relay.h"
|
||||||
#include "test/test.h"
|
#include "test/test.h"
|
||||||
#include "test/log_test_helpers.h"
|
#include "test/log_test_helpers.h"
|
||||||
@ -812,7 +813,11 @@ test_circbw_relay(void *arg)
|
|||||||
ASSERT_UNCOUNTED_BW();
|
ASSERT_UNCOUNTED_BW();
|
||||||
|
|
||||||
/* Sendme on circuit with non-full window: counted */
|
/* Sendme on circuit with non-full window: counted */
|
||||||
PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
|
PACK_CELL(0, RELAY_COMMAND_SENDME, "");
|
||||||
|
/* Recording a cell, the window is updated after decryption so off by one in
|
||||||
|
* order to record and then we process it with the proper window. */
|
||||||
|
circ->cpath->package_window = 901;
|
||||||
|
sendme_record_cell_digest_on_circ(TO_CIRCUIT(circ), circ->cpath);
|
||||||
circ->cpath->package_window = 900;
|
circ->cpath->package_window = 900;
|
||||||
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
|
connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
|
||||||
circ->cpath);
|
circ->cpath);
|
||||||
|
@ -46,26 +46,12 @@ static void
|
|||||||
test_v1_record_digest(void *arg)
|
test_v1_record_digest(void *arg)
|
||||||
{
|
{
|
||||||
or_circuit_t *or_circ = NULL;
|
or_circuit_t *or_circ = NULL;
|
||||||
origin_circuit_t *orig_circ = NULL;
|
|
||||||
circuit_t *circ = NULL;
|
circuit_t *circ = NULL;
|
||||||
|
|
||||||
(void) arg;
|
(void) arg;
|
||||||
|
|
||||||
/* Create our dummy circuits. */
|
/* Create our dummy circuit. */
|
||||||
orig_circ = origin_circuit_new();
|
|
||||||
tt_assert(orig_circ);
|
|
||||||
or_circ = or_circuit_new(1, NULL);
|
or_circ = or_circuit_new(1, NULL);
|
||||||
|
|
||||||
/* Start by pointing to the origin circuit. */
|
|
||||||
circ = TO_CIRCUIT(orig_circ);
|
|
||||||
circ->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
|
|
||||||
|
|
||||||
/* We should never note SENDME digest on origin circuit. */
|
|
||||||
sendme_record_cell_digest(circ);
|
|
||||||
tt_assert(!circ->sendme_last_digests);
|
|
||||||
/* We do not need the origin circuit for now. */
|
|
||||||
orig_circ = NULL;
|
|
||||||
circuit_free_(circ);
|
|
||||||
/* Points it to the OR circuit now. */
|
/* Points it to the OR circuit now. */
|
||||||
circ = TO_CIRCUIT(or_circ);
|
circ = TO_CIRCUIT(or_circ);
|
||||||
|
|
||||||
@ -73,23 +59,23 @@ test_v1_record_digest(void *arg)
|
|||||||
* in order to catched the CIRCWINDOW_INCREMENT-nth cell. Try something that
|
* in order to catched the CIRCWINDOW_INCREMENT-nth cell. Try something that
|
||||||
* shouldn't be noted. */
|
* shouldn't be noted. */
|
||||||
circ->package_window = CIRCWINDOW_INCREMENT;
|
circ->package_window = CIRCWINDOW_INCREMENT;
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, NULL);
|
||||||
tt_assert(!circ->sendme_last_digests);
|
tt_assert(!circ->sendme_last_digests);
|
||||||
|
|
||||||
/* This should work now. Package window at CIRCWINDOW_INCREMENT + 1. */
|
/* This should work now. Package window at CIRCWINDOW_INCREMENT + 1. */
|
||||||
circ->package_window++;
|
circ->package_window++;
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, NULL);
|
||||||
tt_assert(circ->sendme_last_digests);
|
tt_assert(circ->sendme_last_digests);
|
||||||
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
||||||
|
|
||||||
/* Next cell in the package window shouldn't do anything. */
|
/* Next cell in the package window shouldn't do anything. */
|
||||||
circ->package_window++;
|
circ->package_window++;
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, NULL);
|
||||||
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
||||||
|
|
||||||
/* The next CIRCWINDOW_INCREMENT should add one more digest. */
|
/* The next CIRCWINDOW_INCREMENT should add one more digest. */
|
||||||
circ->package_window = (CIRCWINDOW_INCREMENT * 2) + 1;
|
circ->package_window = (CIRCWINDOW_INCREMENT * 2) + 1;
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, NULL);
|
||||||
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 2);
|
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 2);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -136,9 +122,9 @@ test_v1_consensus_params(void *arg)
|
|||||||
smartlist_add(current_md_consensus->net_params,
|
smartlist_add(current_md_consensus->net_params,
|
||||||
(void *) "sendme_accept_min_version=1");
|
(void *) "sendme_accept_min_version=1");
|
||||||
/* Minimum acceptable value is 1. */
|
/* Minimum acceptable value is 1. */
|
||||||
tt_int_op(cell_version_is_valid(1), OP_EQ, true);
|
tt_int_op(cell_version_can_be_handled(1), OP_EQ, true);
|
||||||
/* Minimum acceptable value is 1 so a cell version of 0 is refused. */
|
/* Minimum acceptable value is 1 so a cell version of 0 is refused. */
|
||||||
tt_int_op(cell_version_is_valid(0), OP_EQ, false);
|
tt_int_op(cell_version_can_be_handled(0), OP_EQ, false);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free_mock_consensus();
|
free_mock_consensus();
|
||||||
@ -157,11 +143,13 @@ test_v1_build_cell(void *arg)
|
|||||||
|
|
||||||
or_circ = or_circuit_new(1, NULL);
|
or_circ = or_circuit_new(1, NULL);
|
||||||
circ = TO_CIRCUIT(or_circ);
|
circ = TO_CIRCUIT(or_circ);
|
||||||
|
circ->sendme_last_digests = smartlist_new();
|
||||||
|
|
||||||
cell_digest = crypto_digest_new();
|
cell_digest = crypto_digest_new();
|
||||||
tt_assert(cell_digest);
|
tt_assert(cell_digest);
|
||||||
crypto_digest_add_bytes(cell_digest, "AAAAAAAAAAAAAAAAAAAA", 20);
|
crypto_digest_add_bytes(cell_digest, "AAAAAAAAAAAAAAAAAAAA", 20);
|
||||||
crypto_digest_get_digest(cell_digest, (char *) digest, sizeof(digest));
|
crypto_digest_get_digest(cell_digest, (char *) digest, sizeof(digest));
|
||||||
|
smartlist_add(circ->sendme_last_digests, tor_memdup(digest, sizeof(digest)));
|
||||||
|
|
||||||
/* SENDME v1 payload is 3 bytes + 20 bytes digest. See spec. */
|
/* SENDME v1 payload is 3 bytes + 20 bytes digest. See spec. */
|
||||||
ret = build_cell_payload_v1(digest, payload);
|
ret = build_cell_payload_v1(digest, payload);
|
||||||
@ -171,6 +159,8 @@ test_v1_build_cell(void *arg)
|
|||||||
|
|
||||||
/* An empty payload means SENDME version 0 thus valid. */
|
/* An empty payload means SENDME version 0 thus valid. */
|
||||||
tt_int_op(sendme_is_valid(circ, payload, 0), OP_EQ, true);
|
tt_int_op(sendme_is_valid(circ, payload, 0), OP_EQ, true);
|
||||||
|
/* Current phoney digest should have been popped. */
|
||||||
|
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0);
|
||||||
|
|
||||||
/* An unparseable cell means invalid. */
|
/* An unparseable cell means invalid. */
|
||||||
setup_full_capture_of_logs(LOG_INFO);
|
setup_full_capture_of_logs(LOG_INFO);
|
||||||
@ -188,7 +178,7 @@ test_v1_build_cell(void *arg)
|
|||||||
|
|
||||||
/* Note the wrong digest in the circuit, cell should fail validation. */
|
/* Note the wrong digest in the circuit, cell should fail validation. */
|
||||||
circ->package_window = CIRCWINDOW_INCREMENT + 1;
|
circ->package_window = CIRCWINDOW_INCREMENT + 1;
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, NULL);
|
||||||
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
||||||
setup_full_capture_of_logs(LOG_INFO);
|
setup_full_capture_of_logs(LOG_INFO);
|
||||||
tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, false);
|
tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, false);
|
||||||
@ -200,7 +190,7 @@ test_v1_build_cell(void *arg)
|
|||||||
/* Record the cell digest into the circuit, cell should validate. */
|
/* Record the cell digest into the circuit, cell should validate. */
|
||||||
memcpy(or_circ->crypto.sendme_digest, digest, sizeof(digest));
|
memcpy(or_circ->crypto.sendme_digest, digest, sizeof(digest));
|
||||||
circ->package_window = CIRCWINDOW_INCREMENT + 1;
|
circ->package_window = CIRCWINDOW_INCREMENT + 1;
|
||||||
sendme_record_cell_digest(circ);
|
sendme_record_cell_digest_on_circ(circ, NULL);
|
||||||
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
|
||||||
tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, true);
|
tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, true);
|
||||||
/* After a validation, the last digests is always popped out. */
|
/* After a validation, the last digests is always popped out. */
|
||||||
@ -253,6 +243,33 @@ test_cell_payload_pad(void *arg)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cell_version_validation(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* We currently only support up to SENDME_MAX_SUPPORTED_VERSION so we are
|
||||||
|
* going to test the boundaries there. */
|
||||||
|
|
||||||
|
tt_assert(cell_version_can_be_handled(SENDME_MAX_SUPPORTED_VERSION));
|
||||||
|
|
||||||
|
/* Version below our supported should pass. */
|
||||||
|
tt_assert(cell_version_can_be_handled(SENDME_MAX_SUPPORTED_VERSION - 1));
|
||||||
|
|
||||||
|
/* Extra version from our supported should fail. */
|
||||||
|
tt_assert(!cell_version_can_be_handled(SENDME_MAX_SUPPORTED_VERSION + 1));
|
||||||
|
|
||||||
|
/* Simple check for version 0. */
|
||||||
|
tt_assert(cell_version_can_be_handled(0));
|
||||||
|
|
||||||
|
/* We MUST handle the default cell version that we emit or accept. */
|
||||||
|
tt_assert(cell_version_can_be_handled(SENDME_EMIT_MIN_VERSION_DEFAULT));
|
||||||
|
tt_assert(cell_version_can_be_handled(SENDME_ACCEPT_MIN_VERSION_DEFAULT));
|
||||||
|
|
||||||
|
done:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
struct testcase_t sendme_tests[] = {
|
struct testcase_t sendme_tests[] = {
|
||||||
{ "v1_record_digest", test_v1_record_digest, TT_FORK,
|
{ "v1_record_digest", test_v1_record_digest, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
@ -262,6 +279,8 @@ struct testcase_t sendme_tests[] = {
|
|||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "cell_payload_pad", test_cell_payload_pad, TT_FORK,
|
{ "cell_payload_pad", test_cell_payload_pad, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
{ "cell_version_validation", test_cell_version_validation, TT_FORK,
|
||||||
|
NULL, NULL },
|
||||||
|
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user