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 : }
|