]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
prop289: Keep track of the last seen cell digests
authorDavid Goulet <dgoulet@torproject.org>
Wed, 9 Jan 2019 20:08:14 +0000 (15:08 -0500)
committerDavid Goulet <dgoulet@torproject.org>
Mon, 29 Apr 2019 16:17:57 +0000 (12:17 -0400)
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 <dgoulet@torproject.org>
src/core/or/circuit_st.h
src/core/or/circuitlist.c
src/core/or/relay.c
src/core/or/sendme.c
src/core/or/sendme.h

index cc21cf62f732e8808b2e568a915358b3d7aaa81e..5adb158935e11995dfa8da8f02ab3814ff17626d 100644 (file)
@@ -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;
index afbde06434103c07276c17e8fac623f67bbc9763..6428cdb8a72a838b243f5ee1bc72276eaee4c177 100644 (file)
@@ -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) ?
index 76f2203a9ad27fd3395b6251cbc0170f6be69c3f..b26360b24501cc0137819a4aa3469c1f5ed40f79 100644 (file)
@@ -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;
 }
 
index 64497055e1dd4c8d553dc2969cae5434a45e526b..69bcac4680922292edee2abbebd338451dbe070d 100644 (file)
@@ -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);
+}
index 033bc6ff753928d1bea779a8a7a10808fea4c650..300fb25d9623aca0ad069e7789438fafa85e43d2 100644 (file)
@@ -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) */