LCOV - code coverage report
Current view: top level - core/or - sendme.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 169 235 71.9 %
Date: 2021-11-24 03:28:48 Functions: 19 22 86.4 %

          Line data    Source code
       1             : /* Copyright (c) 2019-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file sendme.c
       6             :  * \brief Code that is related to SENDME cells both in terms of
       7             :  *        creating/parsing cells and handling the content.
       8             :  */
       9             : 
      10             : #define SENDME_PRIVATE
      11             : 
      12             : #include "core/or/or.h"
      13             : 
      14             : #include "app/config/config.h"
      15             : #include "core/crypto/relay_crypto.h"
      16             : #include "core/mainloop/connection.h"
      17             : #include "core/or/cell_st.h"
      18             : #include "core/or/crypt_path.h"
      19             : #include "core/or/circuitlist.h"
      20             : #include "core/or/circuituse.h"
      21             : #include "core/or/or_circuit_st.h"
      22             : #include "core/or/relay.h"
      23             : #include "core/or/sendme.h"
      24             : #include "feature/nodelist/networkstatus.h"
      25             : #include "lib/ctime/di_ops.h"
      26             : #include "trunnel/sendme_cell.h"
      27             : 
      28             : /* Return the minimum version given by the consensus (if any) that should be
      29             :  * used when emitting a SENDME cell. */
      30             : STATIC int
      31           8 : get_emit_min_version(void)
      32             : {
      33           8 :   return networkstatus_get_param(NULL, "sendme_emit_min_version",
      34             :                                  SENDME_EMIT_MIN_VERSION_DEFAULT,
      35             :                                  SENDME_EMIT_MIN_VERSION_MIN,
      36             :                                  SENDME_EMIT_MIN_VERSION_MAX);
      37             : }
      38             : 
      39             : /* Return the minimum version given by the consensus (if any) that should be
      40             :  * accepted when receiving a SENDME cell. */
      41             : STATIC int
      42          16 : get_accept_min_version(void)
      43             : {
      44          16 :   return networkstatus_get_param(NULL, "sendme_accept_min_version",
      45             :                                  SENDME_ACCEPT_MIN_VERSION_DEFAULT,
      46             :                                  SENDME_ACCEPT_MIN_VERSION_MIN,
      47             :                                  SENDME_ACCEPT_MIN_VERSION_MAX);
      48             : }
      49             : 
      50             : /* Pop the first cell digset on the given circuit from the SENDME last digests
      51             :  * list. NULL is returned if the list is uninitialized or empty.
      52             :  *
      53             :  * The caller gets ownership of the returned digest thus is responsible for
      54             :  * freeing the memory. */
      55             : static uint8_t *
      56           5 : pop_first_cell_digest(const circuit_t *circ)
      57             : {
      58           5 :   uint8_t *circ_digest;
      59             : 
      60           5 :   tor_assert(circ);
      61             : 
      62           5 :   if (circ->sendme_last_digests == NULL ||
      63           5 :       smartlist_len(circ->sendme_last_digests) == 0) {
      64             :     return NULL;
      65             :   }
      66             : 
      67             :   /* More cell digest than the SENDME window is never suppose to happen. The
      68             :    * cell should have been rejected before reaching this point due to its
      69             :    * package_window down to 0 leading to a circuit close. Scream loudly but
      70             :    * still pop the element so we don't memory leak. */
      71           4 :   tor_assert_nonfatal(smartlist_len(circ->sendme_last_digests) <=
      72             :                       CIRCWINDOW_START_MAX / CIRCWINDOW_INCREMENT);
      73             : 
      74           4 :   circ_digest = smartlist_get(circ->sendme_last_digests, 0);
      75           4 :   smartlist_del_keeporder(circ->sendme_last_digests, 0);
      76           4 :   return circ_digest;
      77             : }
      78             : 
      79             : /* Return true iff the given cell digest matches the first digest in the
      80             :  * circuit sendme list. */
      81             : static bool
      82           2 : v1_digest_matches(const uint8_t *circ_digest, const uint8_t *cell_digest)
      83             : {
      84           2 :   tor_assert(circ_digest);
      85           2 :   tor_assert(cell_digest);
      86             : 
      87             :   /* Compare the digest with the one in the SENDME. This cell is invalid
      88             :    * without a perfect match. */
      89           2 :   if (tor_memneq(circ_digest, cell_digest, TRUNNEL_SENDME_V1_DIGEST_LEN)) {
      90           1 :     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
      91             :            "SENDME v1 cell digest do not match.");
      92           1 :     return false;
      93             :   }
      94             : 
      95             :   /* Digests matches! */
      96             :   return true;
      97             : }
      98             : 
      99             : /* Return true iff the given decoded SENDME version 1 cell is valid and
     100             :  * matches the expected digest on the circuit.
     101             :  *
     102             :  * Validation is done by comparing the digest in the cell from the previous
     103             :  * cell we saw which tells us that the other side has in fact seen that cell.
     104             :  * See proposal 289 for more details. */
     105             : static bool
     106           2 : cell_v1_is_valid(const sendme_cell_t *cell, const uint8_t *circ_digest)
     107             : {
     108           2 :   tor_assert(cell);
     109           2 :   tor_assert(circ_digest);
     110             : 
     111           2 :   const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell);
     112           2 :   return v1_digest_matches(circ_digest, cell_digest);
     113             : }
     114             : 
     115             : /* Return true iff the given cell version can be handled or if the minimum
     116             :  * accepted version from the consensus is known to us. */
     117             : STATIC bool
     118          13 : cell_version_can_be_handled(uint8_t cell_version)
     119             : {
     120          13 :   int accept_version = get_accept_min_version();
     121             : 
     122             :   /* We will first check if the consensus minimum accepted version can be
     123             :    * handled by us and if not, regardless of the cell version we got, we can't
     124             :    * continue. */
     125          13 :   if (accept_version > SENDME_MAX_SUPPORTED_VERSION) {
     126           0 :     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     127             :            "Unable to accept SENDME version %u (from consensus). "
     128             :            "We only support <= %u. Probably your tor is too old?",
     129             :            accept_version, SENDME_MAX_SUPPORTED_VERSION);
     130           0 :     goto invalid;
     131             :   }
     132             : 
     133             :   /* Then, is this version below the accepted version from the consensus? If
     134             :    * yes, we must not handle it. */
     135          13 :   if (cell_version < accept_version) {
     136           1 :     log_info(LD_PROTOCOL, "Unacceptable SENDME version %u. Only "
     137             :                           "accepting %u (from consensus). Closing circuit.",
     138             :              cell_version, accept_version);
     139           1 :     goto invalid;
     140             :   }
     141             : 
     142             :   /* Is this cell version supported by us? */
     143          12 :   if (cell_version > SENDME_MAX_SUPPORTED_VERSION) {
     144           1 :     log_info(LD_PROTOCOL, "SENDME cell version %u is not supported by us. "
     145             :                           "We only support <= %u",
     146             :              cell_version, SENDME_MAX_SUPPORTED_VERSION);
     147           1 :     goto invalid;
     148             :   }
     149             : 
     150             :   return true;
     151             :  invalid:
     152             :   return false;
     153             : }
     154             : 
     155             : /* Return true iff the encoded SENDME cell in cell_payload of length
     156             :  * cell_payload_len is valid. For each version:
     157             :  *
     158             :  *  0: No validation
     159             :  *  1: Authenticated with last cell digest.
     160             :  *
     161             :  * This is the main critical function to make sure we can continue to
     162             :  * send/recv cells on a circuit. If the SENDME is invalid, the circuit should
     163             :  * be marked for close by the caller. */
     164             : STATIC bool
     165           7 : sendme_is_valid(const circuit_t *circ, const uint8_t *cell_payload,
     166             :                 size_t cell_payload_len)
     167             : {
     168           7 :   uint8_t cell_version;
     169           7 :   uint8_t *circ_digest = NULL;
     170           7 :   sendme_cell_t *cell = NULL;
     171             : 
     172           7 :   tor_assert(circ);
     173           7 :   tor_assert(cell_payload);
     174             : 
     175             :   /* An empty payload means version 0 so skip trunnel parsing. We won't be
     176             :    * able to parse a 0 length buffer into a valid SENDME cell. */
     177           7 :   if (cell_payload_len == 0) {
     178             :     cell_version = 0;
     179             :   } else {
     180             :     /* First we'll decode the cell so we can get the version. */
     181           5 :     if (sendme_cell_parse(&cell, cell_payload, cell_payload_len) < 0) {
     182           2 :       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     183             :              "Unparseable SENDME cell received. Closing circuit.");
     184           2 :       goto invalid;
     185             :     }
     186           3 :     cell_version = sendme_cell_get_version(cell);
     187             :   }
     188             : 
     189             :   /* Validate that we can handle this cell version. */
     190           5 :   if (!cell_version_can_be_handled(cell_version)) {
     191           0 :     goto invalid;
     192             :   }
     193             : 
     194             :   /* Pop the first element that was added (FIFO). We do that regardless of the
     195             :    * version so we don't accumulate on the circuit if v0 is used by the other
     196             :    * end point. */
     197           5 :   circ_digest = pop_first_cell_digest(circ);
     198           5 :   if (circ_digest == NULL) {
     199             :     /* We shouldn't have received a SENDME if we have no digests. Log at
     200             :      * protocol warning because it can be tricked by sending many SENDMEs
     201             :      * without prior data cell. */
     202           1 :     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     203             :            "We received a SENDME but we have no cell digests to match. "
     204             :            "Closing circuit.");
     205           1 :     goto invalid;
     206             :   }
     207             : 
     208             :   /* Validate depending on the version now. */
     209           4 :   switch (cell_version) {
     210           2 :   case 0x01:
     211           2 :     if (!cell_v1_is_valid(cell, circ_digest)) {
     212           1 :       goto invalid;
     213             :     }
     214             :     break;
     215             :   case 0x00:
     216             :     /* Version 0, there is no work to be done on the payload so it is
     217             :      * necessarily valid if we pass the version validation. */
     218             :     break;
     219           0 :   default:
     220           0 :     log_warn(LD_PROTOCOL, "Unknown SENDME cell version %d received.",
     221             :              cell_version);
     222           0 :     tor_assert_nonfatal_unreached();
     223           0 :     break;
     224             :   }
     225             : 
     226             :   /* Valid cell. */
     227           3 :   sendme_cell_free(cell);
     228           3 :   tor_free(circ_digest);
     229           3 :   return true;
     230           4 :  invalid:
     231           4 :   sendme_cell_free(cell);
     232           4 :   tor_free(circ_digest);
     233           4 :   return false;
     234             : }
     235             : 
     236             : /* Build and encode a version 1 SENDME cell into payload, which must be at
     237             :  * least of RELAY_PAYLOAD_SIZE bytes, using the digest for the cell data.
     238             :  *
     239             :  * Return the size in bytes of the encoded cell in payload. A negative value
     240             :  * is returned on encoding failure. */
     241             : STATIC ssize_t
     242           6 : build_cell_payload_v1(const uint8_t *cell_digest, uint8_t *payload)
     243             : {
     244           6 :   ssize_t len = -1;
     245           6 :   sendme_cell_t *cell = NULL;
     246             : 
     247           6 :   tor_assert(cell_digest);
     248           6 :   tor_assert(payload);
     249             : 
     250           6 :   cell = sendme_cell_new();
     251             : 
     252             :   /* Building a payload for version 1. */
     253           6 :   sendme_cell_set_version(cell, 0x01);
     254             :   /* Set the data length field for v1. */
     255           6 :   sendme_cell_set_data_len(cell, TRUNNEL_SENDME_V1_DIGEST_LEN);
     256             : 
     257             :   /* Copy the digest into the data payload. */
     258           6 :   memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_digest,
     259           6 :          sendme_cell_get_data_len(cell));
     260             : 
     261             :   /* Finally, encode the cell into the payload. */
     262           6 :   len = sendme_cell_encode(payload, RELAY_PAYLOAD_SIZE, cell);
     263             : 
     264           6 :   sendme_cell_free(cell);
     265           6 :   return len;
     266             : }
     267             : 
     268             : /* Send a circuit-level SENDME on the given circuit using the layer_hint if
     269             :  * not NULL. The digest is only used for version 1.
     270             :  *
     271             :  * Return 0 on success else a negative value and the circuit will be closed
     272             :  * because we failed to send the cell on it. */
     273             : static int
     274           5 : send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
     275             :                           const uint8_t *cell_digest)
     276             : {
     277           5 :   uint8_t emit_version;
     278           5 :   uint8_t payload[RELAY_PAYLOAD_SIZE];
     279           5 :   ssize_t payload_len;
     280             : 
     281           5 :   tor_assert(circ);
     282           5 :   tor_assert(cell_digest);
     283             : 
     284           5 :   emit_version = get_emit_min_version();
     285           5 :   switch (emit_version) {
     286           5 :   case 0x01:
     287           5 :     payload_len = build_cell_payload_v1(cell_digest, payload);
     288           5 :     if (BUG(payload_len < 0)) {
     289             :       /* Unable to encode the cell, abort. We can recover from this by closing
     290             :        * the circuit but in theory it should never happen. */
     291           0 :       return -1;
     292             :     }
     293           5 :     log_debug(LD_PROTOCOL, "Emitting SENDME version 1 cell.");
     294           5 :     break;
     295           0 :   case 0x00:
     296           0 :     FALLTHROUGH;
     297             :   default:
     298             :     /* Unknown version, fallback to version 0 meaning no payload. */
     299           0 :     payload_len = 0;
     300           0 :     log_debug(LD_PROTOCOL, "Emitting SENDME version 0 cell. "
     301             :                            "Consensus emit version is %d", emit_version);
     302             :     break;
     303             :   }
     304             : 
     305           5 :   if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME,
     306             :                                    (char *) payload, payload_len,
     307             :                                    layer_hint) < 0) {
     308           0 :     log_warn(LD_CIRC,
     309             :              "SENDME relay_send_command_from_edge failed. Circuit's closed.");
     310           0 :     return -1; /* the circuit's closed, don't continue */
     311             :   }
     312             :   return 0;
     313             : }
     314             : 
     315             : /* Record the cell digest only if the next cell is expected to be a SENDME. */
     316             : static void
     317           5 : record_cell_digest_on_circ(circuit_t *circ, const uint8_t *sendme_digest)
     318             : {
     319           5 :   tor_assert(circ);
     320           5 :   tor_assert(sendme_digest);
     321             : 
     322             :   /* Add the digest to the last seen list in the circuit. */
     323           5 :   if (circ->sendme_last_digests == NULL) {
     324           2 :     circ->sendme_last_digests = smartlist_new();
     325             :   }
     326           5 :   smartlist_add(circ->sendme_last_digests,
     327             :                 tor_memdup(sendme_digest, DIGEST_LEN));
     328           5 : }
     329             : 
     330             : /*
     331             :  * Public API
     332             :  */
     333             : 
     334             : /** Return true iff the next cell for the given cell window is expected to be
     335             :  * a SENDME.
     336             :  *
     337             :  * We are able to know that because the package or deliver window value minus
     338             :  * one cell (the possible SENDME cell) should be a multiple of the increment
     339             :  * window value. */
     340             : static bool
     341         107 : circuit_sendme_cell_is_next(int window)
     342             : {
     343             :   /* At the start of the window, no SENDME will be expected. */
     344         107 :   if (window == CIRCWINDOW_START) {
     345             :     return false;
     346             :   }
     347             : 
     348             :   /* Are we at the limit of the increment and if not, we don't expect next
     349             :    * cell is a SENDME.
     350             :    *
     351             :    * We test against the window minus 1 because when we are looking if the
     352             :    * next cell is a SENDME, the window (either package or deliver) hasn't been
     353             :    * decremented just yet so when this is called, we are currently processing
     354             :    * the "window - 1" cell.
     355             :    *
     356             :    * This function is used when recording a cell digest and this is done quite
     357             :    * low in the stack when decrypting or encrypting a cell. The window is only
     358             :    * updated once the cell is actually put in the outbuf. */
     359          57 :   if (((window - 1) % CIRCWINDOW_INCREMENT) != 0) {
     360          52 :     return false;
     361             :   }
     362             : 
     363             :   /* Next cell is expected to be a SENDME. */
     364             :   return true;
     365             : }
     366             : 
     367             : /** Called when we've just received a relay data cell, when we've just
     368             :  * finished flushing all bytes to stream <b>conn</b>, or when we've flushed
     369             :  * *some* bytes to the stream <b>conn</b>.
     370             :  *
     371             :  * If conn->outbuf is not too full, and our deliver window is low, send back a
     372             :  * suitable number of stream-level sendme cells.
     373             :  */
     374             : void
     375           2 : sendme_connection_edge_consider_sending(edge_connection_t *conn)
     376             : {
     377           2 :   tor_assert(conn);
     378             : 
     379           2 :   int log_domain = TO_CONN(conn)->type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
     380             : 
     381             :   /* Don't send it if we still have data to deliver. */
     382           2 :   if (connection_outbuf_too_full(TO_CONN(conn))) {
     383           0 :     goto end;
     384             :   }
     385             : 
     386           2 :   if (circuit_get_by_edge_conn(conn) == NULL) {
     387             :     /* This can legitimately happen if the destroy has already arrived and
     388             :      * torn down the circuit. */
     389           0 :     log_info(log_domain, "No circuit associated with edge connection. "
     390             :                          "Skipping sending SENDME.");
     391           0 :     goto end;
     392             :   }
     393             : 
     394           2 :   while (conn->deliver_window <=
     395             :          (STREAMWINDOW_START - STREAMWINDOW_INCREMENT)) {
     396           0 :     log_debug(log_domain, "Outbuf %" TOR_PRIuSZ ", queuing stream SENDME.",
     397             :               buf_datalen(TO_CONN(conn)->outbuf));
     398           0 :     conn->deliver_window += STREAMWINDOW_INCREMENT;
     399           0 :     if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME,
     400             :                                      NULL, 0) < 0) {
     401           0 :       log_debug(LD_CIRC, "connection_edge_send_command failed while sending "
     402             :                          "a SENDME. Circuit probably closed, skipping.");
     403           0 :       goto end; /* The circuit's closed, don't continue */
     404             :     }
     405             :   }
     406             : 
     407           2 :  end:
     408           2 :   return;
     409             : }
     410             : 
     411             : /** Check if the deliver_window for circuit <b>circ</b> (at hop
     412             :  * <b>layer_hint</b> if it's defined) is low enough that we should
     413             :  * send a circuit-level sendme back down the circuit. If so, send
     414             :  * enough sendmes that the window would be overfull if we sent any
     415             :  * more.
     416             :  */
     417             : void
     418         507 : sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
     419             : {
     420         507 :   bool sent_one_sendme = false;
     421         507 :   const uint8_t *digest;
     422             : 
     423        1019 :   while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
     424             :           CIRCWINDOW_START - CIRCWINDOW_INCREMENT) {
     425           5 :     log_debug(LD_CIRC,"Queuing circuit sendme.");
     426           5 :     if (layer_hint) {
     427           5 :       layer_hint->deliver_window += CIRCWINDOW_INCREMENT;
     428           5 :       digest = cpath_get_sendme_digest(layer_hint);
     429             :     } else {
     430           0 :       circ->deliver_window += CIRCWINDOW_INCREMENT;
     431           0 :       digest = relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto);
     432             :     }
     433           5 :     if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) {
     434             :       return; /* The circuit's closed, don't continue */
     435             :     }
     436             :     /* Current implementation is not suppose to send multiple SENDME at once
     437             :      * because this means we would use the same relay crypto digest for each
     438             :      * SENDME leading to a mismatch on the other side and the circuit to
     439             :      * collapse. Scream loudly if it ever happens so we can address it. */
     440           5 :     tor_assert_nonfatal(!sent_one_sendme);
     441             :     sent_one_sendme = true;
     442             :   }
     443             : }
     444             : 
     445             : /* Process a circuit-level SENDME cell that we just received. The layer_hint,
     446             :  * if not NULL, is the Exit hop of the connection which means that we are a
     447             :  * client. In that case, circ must be an origin circuit. The cell_body_len is
     448             :  * the length of the SENDME cell payload (excluding the header). The
     449             :  * cell_payload is the payload.
     450             :  *
     451             :  * Return 0 on success (the SENDME is valid and the package window has
     452             :  * been updated properly).
     453             :  *
     454             :  * On error, a negative value is returned, which indicates that the
     455             :  * circuit must be closed using the value as the reason for it. */
     456             : int
     457           2 : sendme_process_circuit_level(crypt_path_t *layer_hint,
     458             :                              circuit_t *circ, const uint8_t *cell_payload,
     459             :                              uint16_t cell_payload_len)
     460             : {
     461           2 :   tor_assert(circ);
     462           2 :   tor_assert(cell_payload);
     463             : 
     464             :   /* Validate the SENDME cell. Depending on the version, different validation
     465             :    * can be done. An invalid SENDME requires us to close the circuit. */
     466           2 :   if (!sendme_is_valid(circ, cell_payload, cell_payload_len)) {
     467             :     return -END_CIRC_REASON_TORPROTOCOL;
     468             :   }
     469             : 
     470             :   /* If we are the origin of the circuit, we are the Client so we use the
     471             :    * layer hint (the Exit hop) for the package window tracking. */
     472           1 :   if (CIRCUIT_IS_ORIGIN(circ)) {
     473             :     /* If we are the origin of the circuit, it is impossible to not have a
     474             :      * cpath. Just in case, bug on it and close the circuit. */
     475           1 :     if (BUG(layer_hint == NULL)) {
     476           0 :       return -END_CIRC_REASON_TORPROTOCOL;
     477             :     }
     478           1 :     if ((layer_hint->package_window + CIRCWINDOW_INCREMENT) >
     479             :         CIRCWINDOW_START_MAX) {
     480           0 :       static struct ratelim_t exit_warn_ratelim = RATELIM_INIT(600);
     481           0 :       log_fn_ratelim(&exit_warn_ratelim, LOG_WARN, LD_PROTOCOL,
     482             :                      "Unexpected sendme cell from exit relay. "
     483             :                      "Closing circ.");
     484           0 :       return -END_CIRC_REASON_TORPROTOCOL;
     485             :     }
     486           1 :     layer_hint->package_window += CIRCWINDOW_INCREMENT;
     487           1 :     log_debug(LD_APP, "circ-level sendme at origin, packagewindow %d.",
     488             :               layer_hint->package_window);
     489             : 
     490             :     /* We count circuit-level sendme's as valid delivered data because they
     491             :      * are rate limited. */
     492           1 :     circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_payload_len);
     493             :   } else {
     494             :     /* We aren't the origin of this circuit so we are the Exit and thus we
     495             :      * track the package window with the circuit object. */
     496           0 :     if ((circ->package_window + CIRCWINDOW_INCREMENT) >
     497             :         CIRCWINDOW_START_MAX) {
     498           0 :       static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
     499           0 :       log_fn_ratelim(&client_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
     500             :                      "Unexpected sendme cell from client. "
     501             :                      "Closing circ (window %d).", circ->package_window);
     502           0 :       return -END_CIRC_REASON_TORPROTOCOL;
     503             :     }
     504           0 :     circ->package_window += CIRCWINDOW_INCREMENT;
     505           0 :     log_debug(LD_EXIT, "circ-level sendme at non-origin, packagewindow %d.",
     506             :               circ->package_window);
     507             :   }
     508             : 
     509             :   return 0;
     510             : }
     511             : 
     512             : /* Process a stream-level SENDME cell that we just received. The conn is the
     513             :  * edge connection (stream) that the circuit circ is associated with. The
     514             :  * cell_body_len is the length of the payload (excluding the header).
     515             :  *
     516             :  * Return 0 on success (the SENDME is valid and the package window has
     517             :  * been updated properly).
     518             :  *
     519             :  * On error, a negative value is returned, which indicates that the
     520             :  * circuit must be closed using the value as the reason for it. */
     521             : int
     522           4 : sendme_process_stream_level(edge_connection_t *conn, circuit_t *circ,
     523             :                             uint16_t cell_body_len)
     524             : {
     525           4 :   tor_assert(conn);
     526           4 :   tor_assert(circ);
     527             : 
     528             :   /* Don't allow the other endpoint to request more than our maximum (i.e.
     529             :    * initial) stream SENDME window worth of data. Well-behaved stock clients
     530             :    * will not request more than this max (as per the check in the while loop
     531             :    * of sendme_connection_edge_consider_sending()). */
     532           4 :   if ((conn->package_window + STREAMWINDOW_INCREMENT) >
     533             :       STREAMWINDOW_START_MAX) {
     534           3 :     static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
     535           3 :     log_fn_ratelim(&stream_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
     536             :                    "Unexpected stream sendme cell. Closing circ (window %d).",
     537             :                    conn->package_window);
     538           3 :     return -END_CIRC_REASON_TORPROTOCOL;
     539             :   }
     540             :   /* At this point, the stream sendme is valid */
     541           1 :   conn->package_window += STREAMWINDOW_INCREMENT;
     542             : 
     543             :   /* We count circuit-level sendme's as valid delivered data because they are
     544             :    * rate limited. */
     545           1 :   if (CIRCUIT_IS_ORIGIN(circ)) {
     546           1 :     circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_body_len);
     547             :   }
     548             : 
     549           1 :   log_debug(CIRCUIT_IS_ORIGIN(circ) ? LD_APP : LD_EXIT,
     550             :             "stream-level sendme, package_window now %d.",
     551             :             conn->package_window);
     552           1 :   return 0;
     553             : }
     554             : 
     555             : /* Called when a relay DATA cell is received on the given circuit. If
     556             :  * layer_hint is NULL, this means we are the Exit end point else we are the
     557             :  * Client. Update the deliver window and return its new value. */
     558             : int
     559         507 : sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint)
     560             : {
     561         507 :   int deliver_window, domain;
     562             : 
     563         507 :   if (CIRCUIT_IS_ORIGIN(circ)) {
     564         507 :     tor_assert(layer_hint);
     565         507 :     --layer_hint->deliver_window;
     566         507 :     deliver_window = layer_hint->deliver_window;
     567         507 :     domain = LD_APP;
     568             :   } else {
     569           0 :     tor_assert(!layer_hint);
     570           0 :     --circ->deliver_window;
     571           0 :     deliver_window = circ->deliver_window;
     572           0 :     domain = LD_EXIT;
     573             :   }
     574             : 
     575         507 :   log_debug(domain, "Circuit deliver_window now %d.", deliver_window);
     576         507 :   return deliver_window;
     577             : }
     578             : 
     579             : /* Called when a relay DATA cell is received for the given edge connection
     580             :  * conn. Update the deliver window and return its new value. */
     581             : int
     582           2 : sendme_stream_data_received(edge_connection_t *conn)
     583             : {
     584           2 :   tor_assert(conn);
     585           2 :   return --conn->deliver_window;
     586             : }
     587             : 
     588             : /* Called when a relay DATA cell is packaged on the given circuit. If
     589             :  * layer_hint is NULL, this means we are the Exit end point else we are the
     590             :  * Client. Update the package window and return its new value. */
     591             : int
     592           0 : sendme_note_circuit_data_packaged(circuit_t *circ, crypt_path_t *layer_hint)
     593             : {
     594           0 :   int package_window, domain;
     595             : 
     596           0 :   tor_assert(circ);
     597             : 
     598           0 :   if (CIRCUIT_IS_ORIGIN(circ)) {
     599             :     /* Client side. */
     600           0 :     tor_assert(layer_hint);
     601           0 :     --layer_hint->package_window;
     602           0 :     package_window = layer_hint->package_window;
     603           0 :     domain = LD_APP;
     604             :   } else {
     605             :     /* Exit side. */
     606           0 :     tor_assert(!layer_hint);
     607           0 :     --circ->package_window;
     608           0 :     package_window = circ->package_window;
     609           0 :     domain = LD_EXIT;
     610             :   }
     611             : 
     612           0 :   log_debug(domain, "Circuit package_window now %d.", package_window);
     613           0 :   return package_window;
     614             : }
     615             : 
     616             : /* Called when a relay DATA cell is packaged for the given edge connection
     617             :  * conn. Update the package window and return its new value. */
     618             : int
     619           0 : sendme_note_stream_data_packaged(edge_connection_t *conn)
     620             : {
     621           0 :   tor_assert(conn);
     622             : 
     623           0 :   --conn->package_window;
     624           0 :   log_debug(LD_APP, "Stream package_window now %d.", conn->package_window);
     625           0 :   return conn->package_window;
     626             : }
     627             : 
     628             : /* Record the cell digest into the circuit sendme digest list depending on
     629             :  * which edge we are. The digest is recorded only if we expect the next cell
     630             :  * that we will receive is a SENDME so we can match the digest. */
     631             : void
     632           7 : sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath)
     633             : {
     634           7 :   int package_window;
     635           7 :   uint8_t *sendme_digest;
     636             : 
     637           7 :   tor_assert(circ);
     638             : 
     639           7 :   package_window = circ->package_window;
     640           7 :   if (cpath) {
     641           1 :     package_window = cpath->package_window;
     642             :   }
     643             : 
     644             :   /* Is this the last cell before a SENDME? The idea is that if the
     645             :    * package_window reaches a multiple of the increment, after this cell, we
     646             :    * should expect a SENDME. */
     647           7 :   if (!circuit_sendme_cell_is_next(package_window)) {
     648             :     return;
     649             :   }
     650             : 
     651             :   /* Getting the digest is expensive so we only do it once we are certain to
     652             :    * record it on the circuit. */
     653           5 :   if (cpath) {
     654           1 :     sendme_digest = cpath_get_sendme_digest(cpath);
     655             :   } else {
     656           4 :     sendme_digest =
     657           4 :       relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto);
     658             :   }
     659             : 
     660           5 :   record_cell_digest_on_circ(circ, sendme_digest);
     661             : }
     662             : 
     663             : /* Called once we decrypted a cell and recognized it. Record the cell digest
     664             :  * as the next sendme digest only if the next cell we'll send on the circuit
     665             :  * is expected to be a SENDME. */
     666             : void
     667           0 : sendme_record_received_cell_digest(circuit_t *circ, crypt_path_t *cpath)
     668             : {
     669           0 :   tor_assert(circ);
     670             : 
     671             :   /* Only record if the next cell is expected to be a SENDME. */
     672           0 :   if (!circuit_sendme_cell_is_next(cpath ? cpath->deliver_window :
     673             :                                            circ->deliver_window)) {
     674             :     return;
     675             :   }
     676             : 
     677           0 :   if (cpath) {
     678             :     /* Record incoming digest. */
     679           0 :     cpath_sendme_record_cell_digest(cpath, false);
     680             :   } else {
     681             :     /* Record forward digest. */
     682           0 :     relay_crypto_record_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, true);
     683             :   }
     684             : }
     685             : 
     686             : /* Called once we encrypted a cell. Record the cell digest as the next sendme
     687             :  * digest only if the next cell we expect to receive is a SENDME so we can
     688             :  * match the digests. */
     689             : void
     690         100 : sendme_record_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath)
     691             : {
     692         100 :   tor_assert(circ);
     693             : 
     694             :   /* Only record if the next cell is expected to be a SENDME. */
     695         100 :   if (!circuit_sendme_cell_is_next(cpath ? cpath->package_window :
     696             :                                            circ->package_window)) {
     697         100 :     goto end;
     698             :   }
     699             : 
     700           0 :   if (cpath) {
     701             :     /* Record the forward digest. */
     702           0 :     cpath_sendme_record_cell_digest(cpath, true);
     703             :   } else {
     704             :     /* Record the incoming digest. */
     705           0 :     relay_crypto_record_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto, false);
     706             :   }
     707             : 
     708         100 :  end:
     709         100 :   return;
     710             : }

Generated by: LCOV version 1.14