From 93f9fbbd34f03aca68c8c64a7e39b64548462eeb Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 9 Jan 2019 15:08:14 -0500 Subject: [PATCH] prop289: Keep track of the last seen cell digests This makes tor remember the last seen digest of a cell if that cell is the last one before a SENDME on the Exit side. Closes #26839 Signed-off-by: David Goulet --- src/core/or/circuit_st.h | 6 ++++++ src/core/or/circuitlist.c | 6 ++++++ src/core/or/relay.c | 8 ++++++++ src/core/or/sendme.c | 29 +++++++++++++++++++++++++++++ src/core/or/sendme.h | 3 +++ 5 files changed, 52 insertions(+) diff --git a/src/core/or/circuit_st.h b/src/core/or/circuit_st.h index cc21cf62f7..5adb158935 100644 --- a/src/core/or/circuit_st.h +++ b/src/core/or/circuit_st.h @@ -104,6 +104,12 @@ struct circuit_t { * circuit-level sendme cells to indicate that we're willing to accept * more. */ int deliver_window; + /** FIFO containing the digest of the cells that are just before a SENDME is + * sent by the client. It is done at the last cell before our package_window + * goes down to 0 which is when we expect a SENDME. The protocol doesn't + * allow more than 10 outstanding SENDMEs worth of data meaning this list + * should only contain at most 10 digests of 4 bytes each. */ + smartlist_t *sendme_last_digests; /** Temporary field used during circuits_handle_oom. */ uint32_t age_tmp; diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c index afbde06434..6428cdb8a7 100644 --- a/src/core/or/circuitlist.c +++ b/src/core/or/circuitlist.c @@ -1227,6 +1227,12 @@ circuit_free_(circuit_t *circ) * "active" checks will be violated. */ cell_queue_clear(&circ->n_chan_cells); + /* Cleanup possible SENDME state. */ + if (circ->sendme_last_digests) { + SMARTLIST_FOREACH(circ->sendme_last_digests, uint8_t *, d, tor_free(d)); + smartlist_free(circ->sendme_last_digests); + } + log_info(LD_CIRC, "Circuit %u (id: %" PRIu32 ") has been freed.", n_circ_id, CIRCUIT_IS_ORIGIN(circ) ? diff --git a/src/core/or/relay.c b/src/core/or/relay.c index 76f2203a9a..b26360b245 100644 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@ -639,6 +639,14 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *circ, circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; } + + /* If applicable, note the cell digest for the SENDME version 1 purpose if + * we need to. This call needs to be after the circuit_package_relay_cell() + * because the cell digest is set within that function. */ + if (relay_command == RELAY_COMMAND_DATA) { + sendme_note_cell_digest(circ); + } + return 0; } diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c index 64497055e1..69bcac4680 100644 --- a/src/core/or/sendme.c +++ b/src/core/or/sendme.c @@ -11,6 +11,7 @@ #include "app/config/config.h" #include "core/mainloop/connection.h" +#include "core/or/cell_st.h" #include "core/or/circuitlist.h" #include "core/or/circuituse.h" #include "core/or/relay.h" @@ -507,3 +508,31 @@ sendme_stream_data_packaged(edge_connection_t *conn) tor_assert(conn); return --conn->package_window; } + +/* Note the cell digest in the circuit sendme last digests FIFO if applicable. + * It is safe to pass a circuit that isn't meant to track those digests. */ +void +sendme_note_cell_digest(circuit_t *circ) +{ + uint8_t *digest; + + tor_assert(circ); + + /* We only keep the cell digest if we are the Exit on that circuit and if + * this cell is the last one before the client should send a SENDME. */ + if (CIRCUIT_IS_ORIGIN(circ)) { + return; + } + /* 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 + * should expect a SENDME. */ + if (((circ->package_window - 1) % CIRCWINDOW_INCREMENT) != 0) { + return; + } + + digest = tor_malloc_zero(4); + if (circ->sendme_last_digests == NULL) { + circ->sendme_last_digests = smartlist_new(); + } + smartlist_add(circ->sendme_last_digests, digest); +} diff --git a/src/core/or/sendme.h b/src/core/or/sendme.h index 033bc6ff75..300fb25d96 100644 --- a/src/core/or/sendme.h +++ b/src/core/or/sendme.h @@ -34,4 +34,7 @@ int sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint); int sendme_circuit_data_packaged(circuit_t *circ, crypt_path_t *layer_hint); int sendme_stream_data_packaged(edge_connection_t *conn); +/* Track cell digest. */ +void sendme_note_cell_digest(circuit_t *circ); + #endif /* !defined(TOR_SENDME_H) */