Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
hs_circuit.c
Go to the documentation of this file.
1/* Copyright (c) 2017-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file hs_circuit.c
6 **/
7
8#define HS_CIRCUIT_PRIVATE
9
10#include "core/or/or.h"
11#include "app/config/config.h"
12#include "core/crypto/hs_ntor.h"
14#include "core/or/circuitlist.h"
15#include "core/or/circuituse.h"
16#include "core/or/policies.h"
17#include "core/or/relay.h"
18#include "core/or/crypt_path.h"
19#include "core/or/extendinfo.h"
22#include "feature/client/circpathbias.h"
23#include "feature/hs/hs_cell.h"
26#include "feature/hs/hs_ob.h"
29#include "feature/hs/hs_ident.h"
39
40/* Trunnel. */
41#include "trunnel/ed25519_cert.h"
42#include "trunnel/hs/cell_establish_intro.h"
43
50
51/** Helper: Free a pending rend object. */
52static inline void
54{
55 if (!req) {
56 return;
57 }
58 link_specifier_smartlist_free(req->rdv_data.link_specifiers);
59 memwipe(req, 0, sizeof(pending_rend_t));
60 tor_free(req);
61}
62
63/** A circuit is about to become an e2e rendezvous circuit. Check
64 * <b>circ_purpose</b> and ensure that it's properly set. Return true iff
65 * circuit purpose is properly set, otherwise return false. */
66static int
67circuit_purpose_is_correct_for_rend(unsigned int circ_purpose,
68 int is_service_side)
69{
70 if (is_service_side) {
71 if (circ_purpose != CIRCUIT_PURPOSE_S_CONNECT_REND) {
72 log_warn(LD_BUG,
73 "HS e2e circuit setup with wrong purpose (%d)", circ_purpose);
74 return 0;
75 }
76 }
77
78 if (!is_service_side) {
79 if (circ_purpose != CIRCUIT_PURPOSE_C_REND_READY &&
81 log_warn(LD_BUG,
82 "Client e2e circuit setup with wrong purpose (%d)", circ_purpose);
83 return 0;
84 }
85 }
86
87 return 1;
88}
89
90/** Create and return a crypt path for the final hop of a v3 prop224 rendezvous
91 * circuit. Initialize the crypt path crypto using the output material from the
92 * ntor key exchange at <b>ntor_key_seed</b>.
93 *
94 * If <b>is_service_side</b> is set, we are the hidden service and the final
95 * hop of the rendezvous circuit is the client on the other side. */
96static crypt_path_t *
97create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
98 int is_service_side)
99{
100 uint8_t keys[HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN];
101 crypt_path_t *cpath = NULL;
102
103 /* Do the key expansion */
104 if (hs_ntor_circuit_key_expansion(ntor_key_seed, seed_len,
105 keys, sizeof(keys)) < 0) {
106 goto err;
107 }
108
109 /* Setup the cpath */
110 cpath = tor_malloc_zero(sizeof(crypt_path_t));
111 cpath->magic = CRYPT_PATH_MAGIC;
112
113 // TODO CGO: Pick relay cell format based on capabilities.
115
116 if (cpath_init_circuit_crypto(cpath, (char*)keys, sizeof(keys),
117 is_service_side, 1) < 0) {
118 tor_free(cpath);
119 goto err;
120 }
121
122 err:
123 memwipe(keys, 0, sizeof(keys));
124 return cpath;
125}
126
127/** Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
128 * <b>circ</b> ready for use to transfer HS relay cells. */
129static void
131 int is_service_side)
132{
133 tor_assert(circ);
134 tor_assert(hop);
135
136 /* Notify the circuit state machine that we are splicing this circuit */
137 int new_circ_purpose = is_service_side ?
139 circuit_change_purpose(TO_CIRCUIT(circ), new_circ_purpose);
140
141 /* All is well. Extend the circuit. */
142 hop->state = CPATH_STATE_OPEN;
143 /* Set the windows to default. */
146
147 /* If congestion control, transfer ccontrol onto the cpath. */
148 if (TO_CIRCUIT(circ)->ccontrol) {
149 hop->ccontrol = TO_CIRCUIT(circ)->ccontrol;
150 TO_CIRCUIT(circ)->ccontrol = NULL;
151 }
152
153 /* Append the hop to the cpath of this circuit */
154 cpath_extend_linked_list(&circ->cpath, hop);
155
156 /* Finally, mark circuit as ready to be used for client streams */
157 if (!is_service_side) {
159 }
160}
161
162/** For a given circuit and a service introduction point object, register the
163 * intro circuit to the circuitmap. */
164static void
166 origin_circuit_t *circ)
167{
168 tor_assert(ip);
169 tor_assert(circ);
170
172 &ip->auth_key_kp.pubkey);
173}
174
175/** Return the number of opened introduction circuit for the given circuit that
176 * is matching its identity key. */
177static unsigned int
179 const hs_service_descriptor_t *desc)
180{
181 unsigned int count = 0;
182
183 tor_assert(service);
184 tor_assert(desc);
185
186 DIGEST256MAP_FOREACH(desc->intro_points.map, key,
187 const hs_service_intro_point_t *, ip) {
188 const circuit_t *circ;
190 if (ocirc == NULL) {
191 continue;
192 }
193 circ = TO_CIRCUIT(ocirc);
196 /* Having a circuit not for the requested service is really bad. */
198 &ocirc->hs_ident->identity_pk));
199 /* Only count opened circuit and skip circuit that will be closed. */
200 if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN) {
201 count++;
202 }
203 } DIGEST256MAP_FOREACH_END;
204 return count;
205}
206
207/** From a given service, rendezvous cookie and handshake info, create a
208 * rendezvous point circuit identifier. This can't fail. */
211 const uint8_t *rendezvous_cookie,
212 const curve25519_public_key_t *server_pk,
213 const hs_ntor_rend_cell_keys_t *keys)
214{
215 hs_ident_circuit_t *ident;
216 uint8_t handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
217
218 tor_assert(service);
219 tor_assert(rendezvous_cookie);
220 tor_assert(server_pk);
221 tor_assert(keys);
222
223 ident = hs_ident_circuit_new(&service->keys.identity_pk);
224 /* Copy the RENDEZVOUS_COOKIE which is the unique identifier. */
225 memcpy(ident->rendezvous_cookie, rendezvous_cookie,
226 sizeof(ident->rendezvous_cookie));
227 /* Build the HANDSHAKE_INFO which looks like this:
228 * SERVER_PK [32 bytes]
229 * AUTH_INPUT_MAC [32 bytes]
230 */
231 memcpy(handshake_info, server_pk->public_key, CURVE25519_PUBKEY_LEN);
232 memcpy(handshake_info + CURVE25519_PUBKEY_LEN, keys->rend_cell_auth_mac,
234 tor_assert(sizeof(ident->rendezvous_handshake_info) ==
235 sizeof(handshake_info));
236 memcpy(ident->rendezvous_handshake_info, handshake_info,
237 sizeof(ident->rendezvous_handshake_info));
238 /* Finally copy the NTOR_KEY_SEED for e2e encryption on the circuit. */
239 tor_assert(sizeof(ident->rendezvous_ntor_key_seed) ==
240 sizeof(keys->ntor_key_seed));
241 memcpy(ident->rendezvous_ntor_key_seed, keys->ntor_key_seed,
242 sizeof(ident->rendezvous_ntor_key_seed));
243 return ident;
244}
245
246/** From a given service and service intro point, create an introduction point
247 * circuit identifier. This can't fail. */
248static hs_ident_circuit_t *
250 const hs_service_intro_point_t *ip)
251{
252 hs_ident_circuit_t *ident;
253
254 tor_assert(service);
255 tor_assert(ip);
256
257 ident = hs_ident_circuit_new(&service->keys.identity_pk);
258 ed25519_pubkey_copy(&ident->intro_auth_pk, &ip->auth_key_kp.pubkey);
259 tor_assert_nonfatal(!ed25519_public_key_is_zero(&ident->intro_auth_pk));
260
261 return ident;
262}
263
264/** For a given introduction point and an introduction circuit, send the
265 * ESTABLISH_INTRO cell. The service object is used for logging. This can fail
266 * and if so, the circuit is closed and the intro point object is flagged
267 * that the circuit is not established anymore which is important for the
268 * retry mechanism. */
269static void
272{
273 ssize_t cell_len;
274 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX];
275
276 tor_assert(service);
277 tor_assert(ip);
278 tor_assert(circ);
279
280 /* Encode establish intro cell. */
282 &service->config, ip, payload);
283 if (cell_len < 0) {
284 log_warn(LD_REND, "Unable to encode ESTABLISH_INTRO cell for service %s "
285 "on circuit %u. Closing circuit.",
286 safe_str_client(service->onion_address),
287 TO_CIRCUIT(circ)->n_circ_id);
288 goto err;
289 }
290
291 /* Send the cell on the circuit. */
292 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
293 RELAY_COMMAND_ESTABLISH_INTRO,
294 (char *) payload, cell_len,
295 circ->cpath->prev) < 0) {
296 log_info(LD_REND, "Unable to send ESTABLISH_INTRO cell for service %s "
297 "on circuit %u.",
298 safe_str_client(service->onion_address),
299 TO_CIRCUIT(circ)->n_circ_id);
300 /* On error, the circuit has been closed. */
301 goto done;
302 }
303
304 /* Record the attempt to use this circuit. */
306 goto done;
307
308 err:
309 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
310 done:
311 memwipe(payload, 0, sizeof(payload));
312}
313
314/** Return a string constant describing the anonymity of service. */
315static const char *
317{
318 if (service->config.is_single_onion) {
319 return "single onion";
320 } else {
321 return "hidden";
322 }
323}
324
325/** For a given service, the ntor onion key and a rendezvous cookie, launch a
326 * circuit to the rendezvous point specified by the link specifiers. On
327 * success, a circuit identifier is attached to the circuit with the needed
328 * data. This function will try to open a circuit for a maximum value of
329 * MAX_REND_FAILURES then it will give up. */
330MOCK_IMPL(STATIC void,
332 const ed25519_public_key_t *ip_auth_pubkey,
333 const curve25519_keypair_t *ip_enc_key_kp,
334 const hs_cell_intro_rdv_data_t *rdv_data,
335 time_t now))
336{
337 int circ_needs_uptime;
338 extend_info_t *info = NULL;
339 origin_circuit_t *circ;
340
341 tor_assert(service);
342 tor_assert(ip_auth_pubkey);
343 tor_assert(ip_enc_key_kp);
344 tor_assert(rdv_data);
345
346 circ_needs_uptime = hs_service_requires_uptime_circ(service->config.ports);
347
348 /* Get the extend info data structure for the chosen rendezvous point
349 * specified by the given link specifiers. */
351 &rdv_data->onion_pk,
352 service->config.is_single_onion);
353 if (info == NULL) {
354 /* We are done here, we can't extend to the rendezvous point. */
355 log_fn(LOG_PROTOCOL_WARN, LD_REND,
356 "Not enough info to open a circuit to a rendezvous point for "
357 "%s service %s.",
359 safe_str_client(service->onion_address));
360 goto end;
361 }
362
363 for (int i = 0; i < MAX_REND_FAILURES; i++) {
365 if (circ_needs_uptime) {
366 circ_flags |= CIRCLAUNCH_NEED_UPTIME;
367 }
368 /* Firewall and policies are checked when getting the extend info.
369 *
370 * We only use a one-hop path on the first attempt. If the first attempt
371 * fails, we use a 3-hop path for reachability / reliability.
372 * See the comment in retry_service_rendezvous_point() for details. */
373 if (service->config.is_single_onion && i == 0) {
374 circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
375 }
376
378 circ_flags);
379 if (circ != NULL) {
380 /* Stop retrying, we have a circuit! */
381 break;
382 }
383 }
384 if (circ == NULL) {
385 log_warn(LD_REND, "Giving up on launching a rendezvous circuit to %s "
386 "for %s service %s",
387 safe_str_client(extend_info_describe(info)),
389 safe_str_client(service->onion_address));
390 goto end;
391 }
392 /* Update metrics with this new rendezvous circuit launched. */
394
395 log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
396 "for %s service %s",
397 safe_str_client(extend_info_describe(info)),
398 safe_str_client(hex_str((const char *)
399 rdv_data->rendezvous_cookie,
402 safe_str_client(service->onion_address));
403 tor_assert(circ->build_state);
404 /* Rendezvous circuit have a specific timeout for the time spent on trying
405 * to connect to the rendezvous point. */
407
408 /* Create circuit identifier and key material. */
409 {
411 curve25519_keypair_t ephemeral_kp;
412 /* No need for extra strong, this is only for this circuit life time. This
413 * key will be used for the RENDEZVOUS1 cell that will be sent on the
414 * circuit once opened. */
415 curve25519_keypair_generate(&ephemeral_kp, 0);
416 if (hs_ntor_service_get_rendezvous1_keys(ip_auth_pubkey,
417 ip_enc_key_kp,
418 &ephemeral_kp,
419 &rdv_data->client_pk,
420 &keys) < 0) {
421 /* This should not really happened but just in case, don't make tor
422 * freak out, close the circuit and move on. */
423 log_info(LD_REND, "Unable to get RENDEZVOUS1 key material for "
424 "service %s",
425 safe_str_client(service->onion_address));
426 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
427 goto end;
428 }
430 rdv_data->rendezvous_cookie,
431 &ephemeral_kp.pubkey, &keys);
432 memwipe(&ephemeral_kp, 0, sizeof(ephemeral_kp));
433 memwipe(&keys, 0, sizeof(keys));
434 tor_assert(circ->hs_ident);
435 }
436
437 /* Remember PoW state if this introduction included a valid proof of work
438 * client puzzle extension. */
439 if (rdv_data->pow_effort > 0) {
440 circ->hs_pow_effort = rdv_data->pow_effort;
441 circ->hs_with_pow_circ = 1;
442 }
443
444 /* Setup congestion control if asked by the client from the INTRO cell. */
445 if (rdv_data->cc_enabled) {
447 service->config.is_single_onion);
448 }
449
450 end:
451 extend_info_free(info);
452}
453
454/** Return true iff the given service rendezvous circuit circ is allowed for a
455 * relaunch to the rendezvous point. */
456static int
458{
459 tor_assert(circ);
460 /* This is initialized when allocating an origin circuit. */
461 tor_assert(circ->build_state);
463
464 /* XXX: Retrying under certain condition. This is related to #22455. */
465
466 /* We check failure_count >= hs_get_service_max_rend_failures()-1 below, and
467 * the -1 is because we increment the failure count for our current failure
468 * *after* this clause. */
469 int max_rend_failures = hs_get_service_max_rend_failures() - 1;
470
471 /* A failure count that has reached maximum allowed or circuit that expired,
472 * we skip relaunching. */
473 if (circ->build_state->failure_count > max_rend_failures ||
474 circ->build_state->expiry_time <= time(NULL)) {
475 log_info(LD_REND, "Attempt to build a rendezvous circuit to %s has "
476 "failed with %d attempts and expiry time %ld. "
477 "Giving up building.",
478 safe_str_client(
481 (long int) circ->build_state->expiry_time);
482 goto disallow;
483 }
484
485 /* Allowed to relaunch. */
486 return 1;
487 disallow:
488 return 0;
489}
490
491/** Retry the rendezvous point of circ by launching a new circuit to it. */
492static void
494{
495 int flags = 0;
496 origin_circuit_t *new_circ;
497 cpath_build_state_t *bstate;
498
499 tor_assert(circ);
500 /* This is initialized when allocating an origin circuit. */
501 tor_assert(circ->build_state);
503
504 /* Ease our life. */
505 bstate = circ->build_state;
506
507 log_info(LD_REND, "Retrying rendezvous point circuit to %s",
508 safe_str_client(extend_info_describe(bstate->chosen_exit)));
509
510 /* Get the current build state flags for the next circuit. */
511 flags |= (bstate->need_uptime) ? CIRCLAUNCH_NEED_UPTIME : 0;
512 flags |= (bstate->need_capacity) ? CIRCLAUNCH_NEED_CAPACITY : 0;
513 flags |= (bstate->is_internal) ? CIRCLAUNCH_IS_INTERNAL : 0;
514
515 /* We do NOT add the onehop tunnel flag even though it might be a single
516 * onion service. The reason is that if we failed once to connect to the RP
517 * with a direct connection, we consider that chances are that we will fail
518 * again so try a 3-hop circuit and hope for the best. Because the service
519 * has no anonymity (single onion), this change of behavior won't affect
520 * security directly. */
521
523 bstate->chosen_exit, flags);
524 if (new_circ == NULL) {
525 log_warn(LD_REND, "Failed to launch rendezvous circuit to %s",
526 safe_str_client(extend_info_describe(bstate->chosen_exit)));
527
529 HS_METRICS_ERR_RDV_RETRY);
530
531 goto done;
532 }
533
534 /* Transfer build state information to the new circuit state in part to
535 * catch any other failures. */
536 new_circ->build_state->failure_count = bstate->failure_count+1;
537 new_circ->build_state->expiry_time = bstate->expiry_time;
538 new_circ->hs_ident = hs_ident_circuit_dup(circ->hs_ident);
539
540 /* Setup congestion control if asked by the client from the INTRO cell. */
541 if (TO_CIRCUIT(circ)->ccontrol) {
542 /* As per above, in this case, we are a full 3 hop rend, even if we're a
543 * single-onion service. */
545 TO_CIRCUIT(circ)->ccontrol->sendme_inc,
546 false);
547 }
548
549 done:
550 return;
551}
552
553/** Using the given descriptor intro point ip, the node of the
554 * rendezvous point rp_node and the service's subcredential, populate the
555 * already allocated intro1_data object with the needed key material and link
556 * specifiers.
557 *
558 * Return 0 on success or a negative value if we couldn't properly filled the
559 * introduce1 data from the RP node. In other word, it means the RP node is
560 * unusable to use in the introduction. */
561static int
563 const node_t *rp_node,
564 const hs_subcredential_t *subcredential,
565 hs_cell_introduce1_data_t *intro1_data)
566{
567 int ret = -1;
568 smartlist_t *rp_lspecs;
569
570 tor_assert(ip);
571 tor_assert(rp_node);
572 tor_assert(subcredential);
573 tor_assert(intro1_data);
574
575 /* Build the link specifiers from the node at the end of the rendezvous
576 * circuit that we opened for this introduction. */
577 rp_lspecs = node_get_link_specifier_smartlist(rp_node, 0);
578 if (smartlist_len(rp_lspecs) == 0) {
579 /* We can't rendezvous without link specifiers. */
580 smartlist_free(rp_lspecs);
581 goto end;
582 }
583
584 /* Populate the introduce1 data object. */
585 memset(intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
586 intro1_data->auth_pk = &ip->auth_key_cert->signed_key;
587 intro1_data->enc_pk = &ip->enc_key;
588 intro1_data->subcredential = subcredential;
589 intro1_data->link_specifiers = rp_lspecs;
590 intro1_data->onion_pk = node_get_curve25519_onion_key(rp_node);
591 if (intro1_data->onion_pk == NULL) {
592 /* We can't rendezvous without the curve25519 onion key. */
593 goto end;
594 }
595
596 /* Success, we have valid introduce data. */
597 ret = 0;
598
599 end:
600 return ret;
601}
602
603/** Helper: cleanup function for client circuit. This is for every HS version.
604 * It is called from hs_circ_cleanup_on_close() entry point. */
605static void
607{
608 tor_assert(circ);
609
610 if (circuit_is_hs_v3(circ)) {
612 }
613 /* It is possible the circuit has an HS purpose but no identifier (hs_ident).
614 * Thus possible that this passes through. */
615}
616
617/** Helper: cleanup function for client circuit. This is for every HS version.
618 * It is called from hs_circ_cleanup_on_free() entry point. */
619static void
621{
622 tor_assert(circ);
623
624 if (circuit_is_hs_v3(circ)) {
626 }
627 /* It is possible the circuit has an HS purpose but no identifier (hs_ident).
628 * Thus possible that this passes through. */
629}
630
631/** Return less than 0 if a precedes b, 0 if a equals b and greater than 0 if
632 * b precedes a. Note that *higher* effort is *earlier* in the pqueue. */
633static int
634compare_rend_request_by_effort_(const void *_a, const void *_b)
635{
636 const pending_rend_t *a = _a, *b = _b;
637 if (a->rdv_data.pow_effort > b->rdv_data.pow_effort) {
638 return -1;
639 } else if (a->rdv_data.pow_effort == b->rdv_data.pow_effort) {
640 /* tie-breaker! use the time it was added to the queue. older better. */
641 if (a->enqueued_ts < b->enqueued_ts)
642 return -1;
643 if (a->enqueued_ts > b->enqueued_ts)
644 return 1;
645 return 0;
646 } else {
647 return 1;
648 }
649}
650
651/** Return 1 if a request waiting in our service-side pqueue is old
652 * enough that we should just discard it rather than trying to respond,
653 * or 0 if we still like it. As a heuristic, choose half of the total
654 * permitted time interval (so we don't approve trying to respond to
655 * requests when we will then give up on them a moment later).
656 */
657static int
659{
660 if ((req->enqueued_ts + MAX_REND_TIMEOUT/2) < now)
661 return 1;
662 return 0;
663}
664
665/** Our rendezvous request priority queue is too full; keep the first
666 * pqueue_high_level/2 entries and discard the rest.
667 */
668static void
670{
671 smartlist_t *old_pqueue = pow_state->rend_request_pqueue;
672 smartlist_t *new_pqueue = pow_state->rend_request_pqueue = smartlist_new();
673
674 log_info(LD_REND, "Rendezvous request priority queue has "
675 "reached capacity (%d). Discarding the bottom half.",
676 smartlist_len(old_pqueue));
677
678 while (smartlist_len(old_pqueue) &&
679 smartlist_len(new_pqueue) < pow_state->pqueue_high_level/2) {
680 /* while there are still old ones, and the new one isn't full yet */
681 pending_rend_t *req =
682 smartlist_pqueue_pop(old_pqueue,
684 offsetof(pending_rend_t, idx));
685 if (queued_rend_request_is_too_old(req, now)) {
686 log_info(LD_REND, "While trimming, rend request has been pending "
687 "for too long; discarding.");
688
689 pow_state->max_trimmed_effort = MAX(pow_state->max_trimmed_effort,
690 req->rdv_data.pow_effort);
691
693 } else {
694 smartlist_pqueue_add(new_pqueue,
696 offsetof(pending_rend_t, idx), req);
697 }
698 }
699
700 /* Ok, we have rescued all the entries we want to keep. The rest are
701 * all excess. */
702 SMARTLIST_FOREACH_BEGIN(old_pqueue, pending_rend_t *, req) {
703 pow_state->max_trimmed_effort = MAX(pow_state->max_trimmed_effort,
704 req->rdv_data.pow_effort);
706 } SMARTLIST_FOREACH_END(req);
707 smartlist_free(old_pqueue);
708}
709
710/** Count up how many pending outgoing (CIRCUIT_PURPOSE_S_CONNECT_REND)
711 * circuits there are for this service. Used in the PoW rate limiting
712 * world to decide whether it's time to launch any new ones.
713 */
714static int
716{
717 origin_circuit_t *ocirc = NULL;
718 int count = 0;
719 while ((ocirc = circuit_get_next_by_purpose(ocirc,
721 /* Count up circuits that are v3 and for this service. */
722 if (ocirc->hs_ident != NULL &&
724 &service->keys.identity_pk)) {
725 count++;
726 }
727 }
728 return count;
729}
730
731/** Peek at the top entry on the pending rend pqueue, which must not be empty.
732 * If its level of effort is at least what we're suggesting for that service
733 * right now, return 1, else return 0.
734 */
735int
737{
738 tor_assert(pow_state->rend_request_pqueue);
739 tor_assert(smartlist_len(pow_state->rend_request_pqueue));
740
741 pending_rend_t *req =
742 smartlist_get(pow_state->rend_request_pqueue, 0);
743
744 if (req->rdv_data.pow_effort >= pow_state->suggested_effort)
745 return 1;
746
747 return 0;
748}
749
750/** Abandon and free all pending rend requests, leaving the pqueue empty. */
751void
753{
754 tor_assert(pow_state->rend_request_pqueue);
755 while (smartlist_len(pow_state->rend_request_pqueue)) {
756 pending_rend_t *req = smartlist_pop_last(pow_state->rend_request_pqueue);
758 }
759}
760
761/** What is the threshold of in-progress (CIRCUIT_PURPOSE_S_CONNECT_REND)
762 * rendezvous responses above which we won't launch new low-effort rendezvous
763 * responses? (Intro2 cells with suitable PoW effort are not affected
764 * by this threshold.) */
765#define MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS 16
766
767static void
768handle_rend_pqueue_cb(mainloop_event_t *ev, void *arg)
769{
770 hs_service_t *service = arg;
771 hs_pow_service_state_t *pow_state = service->state.pow_state;
772 time_t now = time(NULL);
773 int in_flight = count_service_rp_circuits_pending(service);
774
775 (void) ev; /* Not using the returned event, make compiler happy. */
776
777 log_info(LD_REND, "Considering launching more rendezvous responses. "
778 "%d in-flight, %d pending.",
779 in_flight,
780 smartlist_len(pow_state->rend_request_pqueue));
781
782 /* Process only one rend request per callback, so that this work will not
783 * be prioritized over other event loop callbacks. We may need to retry
784 * in order to find one request that's still viable. */
785 while (smartlist_len(pow_state->rend_request_pqueue) > 0) {
786
787 /* first, peek at the top result to see if we want to pop it */
788 if (in_flight >= MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS &&
790 /* We have queued requests, but they are all low priority, and also
791 * we have too many in-progress rendezvous responses. Don't launch
792 * any more. Schedule ourselves to reassess in a bit. */
793 log_info(LD_REND, "Next request to launch is low priority, and "
794 "%d in-flight already. Waiting to launch more.", in_flight);
795 const struct timeval delay_tv = { 0, 100000 };
796 mainloop_event_schedule(pow_state->pop_pqueue_ev, &delay_tv);
797 return; /* done here! no cleanup needed. */
798 }
799
800 if (pow_state->using_pqueue_bucket) {
801 token_bucket_ctr_refill(&pow_state->pqueue_bucket,
802 (uint32_t) monotime_coarse_absolute_sec());
803
804 if (token_bucket_ctr_get(&pow_state->pqueue_bucket) > 0) {
805 token_bucket_ctr_dec(&pow_state->pqueue_bucket, 1);
806 } else {
807 /* Waiting for pqueue rate limit to refill, come back later */
808 const struct timeval delay_tv = { 0, 100000 };
809 mainloop_event_schedule(pow_state->pop_pqueue_ev, &delay_tv);
810 return;
811 }
812 }
813
814 /* Pop next request by effort. */
815 pending_rend_t *req =
816 smartlist_pqueue_pop(pow_state->rend_request_pqueue,
818 offsetof(pending_rend_t, idx));
819
821 smartlist_len(pow_state->rend_request_pqueue));
822
823 log_info(LD_REND, "Dequeued pending rendezvous request with effort: %u. "
824 "Waited %d. "
825 "Remaining requests: %u",
826 req->rdv_data.pow_effort,
827 (int)(now - req->enqueued_ts),
828 smartlist_len(pow_state->rend_request_pqueue));
829
830 if (queued_rend_request_is_too_old(req, now)) {
831 log_info(LD_REND, "Top rend request has been pending for too long; "
832 "discarding and moving to the next one.");
834 continue; /* do not increment count, this one's free */
835 }
836
837 /* Launch the rendezvous circuit. */
838 launch_rendezvous_point_circuit(service, &req->ip_auth_pubkey,
839 &req->ip_enc_key_kp, &req->rdv_data, now);
841
842 ++pow_state->rend_handled;
843 ++in_flight;
844 break;
845 }
846
847 /* If there are still some pending rendezvous circuits in the pqueue then
848 * reschedule the event in order to continue handling them. */
849 if (smartlist_len(pow_state->rend_request_pqueue) > 0) {
850 mainloop_event_activate(pow_state->pop_pqueue_ev);
851
852 if (smartlist_len(pow_state->rend_request_pqueue) >=
853 pow_state->pqueue_low_level) {
854 pow_state->had_queue = 1;
855 }
856 }
857}
858
859/** Given the information needed to launch a rendezvous circuit and an
860 * effort value, enqueue the rendezvous request in the service's PoW priority
861 * queue with the effort being the priority.
862 *
863 * Return 0 if we successfully enqueued the request else -1. */
864static int
866 hs_cell_introduce2_data_t *data, time_t now)
867{
868 hs_pow_service_state_t *pow_state = NULL;
869 pending_rend_t *req = NULL;
870
871 tor_assert(service);
872 tor_assert(ip);
873 tor_assert(data);
874
875 /* Ease our lives */
876 pow_state = service->state.pow_state;
877
878 req = tor_malloc_zero(sizeof(pending_rend_t));
879
880 /* Copy over the rendezvous request the needed data to launch a circuit. */
881 ed25519_pubkey_copy(&req->ip_auth_pubkey, &ip->auth_key_kp.pubkey);
882 memcpy(&req->ip_enc_key_kp, &ip->enc_key_kp, sizeof(req->ip_enc_key_kp));
883 memcpy(&req->rdv_data, &data->rdv_data, sizeof(req->rdv_data));
884 /* Invalidate the link specifier pointer in the introduce2 data so it
885 * doesn't get freed under us. */
886 data->rdv_data.link_specifiers = NULL;
887 req->idx = -1;
888 req->enqueued_ts = now;
889
890 /* Enqueue the rendezvous request. */
891 smartlist_pqueue_add(pow_state->rend_request_pqueue,
893 offsetof(pending_rend_t, idx), req);
894
896 smartlist_len(pow_state->rend_request_pqueue));
897
898 log_info(LD_REND, "Enqueued rendezvous request with effort: %u. "
899 "Queued requests: %u",
900 req->rdv_data.pow_effort,
901 smartlist_len(pow_state->rend_request_pqueue));
902
903 /* Initialize the priority queue event if it hasn't been done so already. */
904 if (pow_state->pop_pqueue_ev == NULL) {
905 pow_state->pop_pqueue_ev =
906 mainloop_event_postloop_new(handle_rend_pqueue_cb, (void *)service);
907 }
908
909 /* Activate event, we just enqueued a rendezvous request. */
910 mainloop_event_activate(pow_state->pop_pqueue_ev);
911
912 /* See if there are so many cells queued that we need to cull. */
913 if (smartlist_len(pow_state->rend_request_pqueue) >=
914 pow_state->pqueue_high_level) {
915 trim_rend_pqueue(pow_state, now);
917 smartlist_len(pow_state->rend_request_pqueue));
918 }
919
920 return 0;
921}
922
923/* ========== */
924/* Public API */
925/* ========== */
926
927/** Setup on the given circuit congestion control with the given parameters.
928 *
929 * This function assumes that congestion control is enabled on the network and
930 * so it is the caller responsability to make sure of it. */
931void
933 uint8_t sendme_inc, bool is_single_onion)
934{
935 circuit_t *circ = NULL;
936 circuit_params_t circ_params = {0};
937
938 tor_assert(origin_circ);
939
940 /* Ease our lives */
941 circ = TO_CIRCUIT(origin_circ);
942
943 circ_params.cc_enabled = true;
944 circ_params.sendme_inc_cells = sendme_inc;
945
946 /* It is setup on the circuit in order to indicate that congestion control is
947 * enabled. It will be transferred to the RP crypt_path_t once the handshake
948 * is finalized in finalize_rend_circuit() for both client and service
949 * because the final hop is not available until then. */
950
951 if (is_single_onion) {
952 circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION_SOS);
953 } else {
954 if (get_options()->HSLayer3Nodes) {
955 circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION_VG);
956 } else {
957 circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION);
958 }
959 }
960}
961
962/** Return an introduction point circuit matching the given intro point object.
963 * NULL is returned is no such circuit can be found. */
966{
967 tor_assert(ip);
968
970}
971
972/** Return an introduction point established circuit matching the given intro
973 * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL
974 * is returned is no such circuit can be found. */
977{
978 origin_circuit_t *circ;
979
980 tor_assert(ip);
981
983
984 /* Only return circuit if it is established. */
985 return (circ && TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ?
986 circ : NULL;
987}
988
989/** Called when we fail building a rendezvous circuit at some point other than
990 * the last hop: launches a new circuit to the same rendezvous point.
991 *
992 * We currently relaunch connections to rendezvous points if:
993 * - A rendezvous circuit timed out before connecting to RP.
994 * - The rendezvous circuit failed to connect to the RP.
995 *
996 * We avoid relaunching a connection to this rendezvous point if:
997 * - We have already tried MAX_REND_FAILURES times to connect to this RP,
998 * - We've been trying to connect to this RP for more than MAX_REND_TIMEOUT
999 * seconds, or
1000 * - We've already retried this specific rendezvous circuit.
1001 */
1002void
1004{
1005 tor_assert(circ);
1007
1008 /* Check if we are allowed to relaunch to the rendezvous point of circ. */
1010 goto done;
1011 }
1012
1013 /* Legacy services don't have a hidden service ident. */
1014 if (circ->hs_ident) {
1016 }
1017
1018 done:
1019 return;
1020}
1021
1022/** For a given service and a service intro point, launch a circuit to the
1023 * extend info ei. If the service is a single onion, and direct_conn is true,
1024 * a one-hop circuit will be requested.
1025 *
1026 * Return 0 if the circuit was successfully launched and tagged
1027 * with the correct identifier. On error, a negative value is returned. */
1028int
1030 const hs_service_intro_point_t *ip,
1031 extend_info_t *ei,
1032 bool direct_conn)
1033{
1034 /* Standard flags for introduction circuit. */
1035 int ret = -1, circ_flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1036 origin_circuit_t *circ;
1037
1038 tor_assert(service);
1039 tor_assert(ip);
1040 tor_assert(ei);
1041
1042 /* Update circuit flags in case of a single onion service that requires a
1043 * direct connection. */
1044 tor_assert_nonfatal(ip->circuit_retries > 0);
1045 /* Only single onion services can make direct conns */
1046 if (BUG(!service->config.is_single_onion && direct_conn)) {
1047 goto end;
1048 }
1049 /* We only use a one-hop path on the first attempt. If the first attempt
1050 * fails, we use a 3-hop path for reachability / reliability. */
1051 if (direct_conn && ip->circuit_retries == 1) {
1052 circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
1053 }
1054
1055 log_info(LD_REND, "Launching a circuit to intro point %s for service %s.",
1056 safe_str_client(extend_info_describe(ei)),
1057 safe_str_client(service->onion_address));
1058
1059 /* Note down the launch for the retry period. Even if the circuit fails to
1060 * be launched, we still want to respect the retry period to avoid stress on
1061 * the circuit subsystem. */
1062 service->state.num_intro_circ_launched++;
1064 ei, circ_flags);
1065 if (circ == NULL) {
1066 goto end;
1067 }
1068
1069 /* Setup the circuit identifier and attach it to it. */
1070 circ->hs_ident = create_intro_circuit_identifier(service, ip);
1071 tor_assert(circ->hs_ident);
1072 /* Register circuit in the global circuitmap. */
1073 register_intro_circ(ip, circ);
1074
1075 /* Success. */
1076 ret = 0;
1077 end:
1078 return ret;
1079}
1080
1081/** Called when a service introduction point circuit is done building. Given
1082 * the service and intro point object, this function will send the
1083 * ESTABLISH_INTRO cell on the circuit. Return 0 on success. Return 1 if the
1084 * circuit has been repurposed to General because we already have too many
1085 * opened. */
1086int
1089 const hs_service_descriptor_t *desc,
1090 origin_circuit_t *circ)
1091{
1092 int ret = 0;
1093 unsigned int num_intro_circ, num_needed_circ;
1094
1095 tor_assert(service);
1096 tor_assert(ip);
1097 tor_assert(desc);
1098 tor_assert(circ);
1099
1100 /* Count opened circuits that have sent ESTABLISH_INTRO cells or are already
1101 * established introduction circuits */
1102 num_intro_circ = count_opened_desc_intro_point_circuits(service, desc);
1103 num_needed_circ = service->config.num_intro_points;
1104 if (num_intro_circ > num_needed_circ) {
1105 /* There are too many opened valid intro circuit for what the service
1106 * needs so repurpose this one. */
1107
1108 /* XXX: Legacy code checks options->ExcludeNodes and if not NULL it just
1109 * closes the circuit. I have NO idea why it does that so it hasn't been
1110 * added here. I can only assume in case our ExcludeNodes list changes but
1111 * in that case, all circuit are flagged unusable (config.c). --dgoulet */
1112
1113 log_info(LD_CIRC | LD_REND, "Introduction circuit just opened but we "
1114 "have enough for service %s. Repurposing "
1115 "it to general and leaving internal.",
1116 safe_str_client(service->onion_address));
1118 /* Remove it from the circuitmap. */
1120 /* Cleaning up the hidden service identifier and repurpose. */
1121 hs_ident_circuit_free(circ->hs_ident);
1122 circ->hs_ident = NULL;
1123 if (circuit_should_use_vanguards(TO_CIRCUIT(circ)->purpose))
1125 else
1127
1128 /* Inform that this circuit just opened for this new purpose. */
1129 circuit_has_opened(circ);
1130 /* This return value indicate to the caller that the IP object should be
1131 * removed from the service because it's corresponding circuit has just
1132 * been repurposed. */
1133 ret = 1;
1134 goto done;
1135 }
1136
1137 log_info(LD_REND, "Introduction circuit %u established for service %s.",
1138 TO_CIRCUIT(circ)->n_circ_id,
1139 safe_str_client(service->onion_address));
1141
1142 /* Time to send an ESTABLISH_INTRO cell on this circuit. On error, this call
1143 * makes sure the circuit gets closed. */
1144 send_establish_intro(service, ip, circ);
1145
1146 done:
1147 return ret;
1148}
1149
1150/** Called when a service rendezvous point circuit is done building. Given the
1151 * service and the circuit, this function will send a RENDEZVOUS1 cell on the
1152 * circuit using the information in the circuit identifier. If the cell can't
1153 * be sent, the circuit is closed. */
1154void
1156 origin_circuit_t *circ)
1157{
1158 size_t payload_len;
1159 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
1160
1161 tor_assert(service);
1162 tor_assert(circ);
1163 tor_assert(circ->hs_ident);
1164
1165 /* Some useful logging. */
1166 log_info(LD_REND, "Rendezvous circuit %u has opened with cookie %s "
1167 "for service %s",
1168 TO_CIRCUIT(circ)->n_circ_id,
1169 hex_str((const char *) circ->hs_ident->rendezvous_cookie,
1171 safe_str_client(service->onion_address));
1173
1174 /* This can't fail. */
1175 payload_len = hs_cell_build_rendezvous1(
1177 sizeof(circ->hs_ident->rendezvous_cookie),
1179 sizeof(circ->hs_ident->rendezvous_handshake_info),
1180 payload);
1181
1182 /* Pad the payload with random bytes so it matches the size of a legacy cell
1183 * which is normally always bigger. Also, the size of a legacy cell is
1184 * always smaller than the RELAY_PAYLOAD_SIZE so this is safe. */
1185 if (payload_len < HS_LEGACY_RENDEZVOUS_CELL_SIZE) {
1186 crypto_rand((char *) payload + payload_len,
1187 HS_LEGACY_RENDEZVOUS_CELL_SIZE - payload_len);
1188 payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
1189 }
1190
1191 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
1192 RELAY_COMMAND_RENDEZVOUS1,
1193 (const char *) payload,
1194 payload_len,
1195 circ->cpath->prev) < 0) {
1196 /* On error, circuit is closed. */
1197 log_warn(LD_REND, "Unable to send RENDEZVOUS1 cell on circuit %u "
1198 "for service %s",
1199 TO_CIRCUIT(circ)->n_circ_id,
1200 safe_str_client(service->onion_address));
1201
1203 HS_METRICS_ERR_RDV_RENDEZVOUS1);
1204 goto done;
1205 }
1206
1207 /* Setup end-to-end rendezvous circuit between the client and us. */
1210 sizeof(circ->hs_ident->rendezvous_ntor_key_seed),
1211 1) < 0) {
1212 log_warn(LD_GENERAL, "Failed to setup circ");
1213
1214 hs_metrics_failed_rdv(&service->keys.identity_pk, HS_METRICS_ERR_RDV_E2E);
1215 goto done;
1216 }
1217
1218 done:
1219 memwipe(payload, 0, sizeof(payload));
1220}
1221
1222/** Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
1223 * the INTRO_ESTABLISHED cell payload of length payload_len arriving on the
1224 * given introduction circuit circ. The service is only used for logging
1225 * purposes. Return 0 on success else a negative value. */
1226int
1228 const hs_service_intro_point_t *ip,
1229 origin_circuit_t *circ,
1230 const uint8_t *payload, size_t payload_len)
1231{
1232 int ret = -1;
1233
1234 tor_assert(service);
1235 tor_assert(ip);
1236 tor_assert(circ);
1237 tor_assert(payload);
1238
1239 if (BUG(TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)) {
1240 goto done;
1241 }
1242
1243 /* Try to parse the payload into a cell making sure we do actually have a
1244 * valid cell. */
1245 if (hs_cell_parse_intro_established(payload, payload_len) < 0) {
1246 log_warn(LD_REND, "Unable to parse the INTRO_ESTABLISHED cell on "
1247 "circuit %u for service %s",
1248 TO_CIRCUIT(circ)->n_circ_id,
1249 safe_str_client(service->onion_address));
1250 goto done;
1251 }
1252
1253 /* Switch the purpose to a fully working intro point. */
1255 /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully used the
1256 * circuit so update our pathbias subsystem. */
1258 /* Success. */
1259 ret = 0;
1260
1261 done:
1262 return ret;
1263}
1264
1265/**
1266 * Go into <b>data</b> and add the right subcredential to be able to handle
1267 * this incoming cell.
1268 *
1269 * <b>desc_subcred</b> is the subcredential of the descriptor that corresponds
1270 * to the intro point that received this intro request. This subcredential
1271 * should be used if we are not an onionbalance instance.
1272 *
1273 * Return 0 if everything went well, or -1 in case of internal error.
1274 */
1275static int
1278 const hs_subcredential_t *desc_subcred)
1279{
1280 /* Handle the simple case first: We are not an onionbalance instance and we
1281 * should just use the regular descriptor subcredential */
1282 if (!hs_ob_service_is_instance(service)) {
1283 data->n_subcredentials = 1;
1284 data->subcredentials = desc_subcred;
1285 return 0;
1286 }
1287
1288 /* This should not happen since we should have made onionbalance
1289 * subcredentials when we created our descriptors. */
1290 if (BUG(!service->state.ob_subcreds)) {
1291 return -1;
1292 }
1293
1294 /* We are an onionbalance instance: */
1295 data->n_subcredentials = service->state.n_ob_subcreds;
1296 data->subcredentials = service->state.ob_subcreds;
1297
1298 return 0;
1299}
1300
1301/** We just received an INTRODUCE2 cell on the established introduction circuit
1302 * circ. Handle the INTRODUCE2 payload of size payload_len for the given
1303 * circuit and service. This cell is associated with the intro point object ip
1304 * and the subcredential. Return 0 on success else a negative value. */
1305int
1307 const origin_circuit_t *circ,
1309 const hs_subcredential_t *subcredential,
1310 const uint8_t *payload, size_t payload_len)
1311{
1312 int ret = -1;
1313 time_t elapsed;
1315 time_t now = time(NULL);
1316
1317 tor_assert(service);
1318 tor_assert(circ);
1319 tor_assert(ip);
1320 tor_assert(subcredential);
1321 tor_assert(payload);
1322
1323 /* Populate the data structure with everything we need for the cell to be
1324 * parsed, decrypted and key material computed correctly. */
1325 data.auth_pk = &ip->auth_key_kp.pubkey;
1326 data.enc_kp = &ip->enc_key_kp;
1327 data.payload = payload;
1328 data.payload_len = payload_len;
1329 data.replay_cache = ip->replay_cache;
1331 data.rdv_data.cc_enabled = 0;
1332 data.rdv_data.pow_effort = 0;
1333
1335 subcredential)) {
1337 HS_METRICS_ERR_INTRO_REQ_SUBCREDENTIAL);
1338 goto done;
1339 }
1340
1341 if (hs_cell_parse_introduce2(&data, circ, service, ip) < 0) {
1342 hs_metrics_reject_intro_req(service, HS_METRICS_ERR_INTRO_REQ_INTRODUCE2);
1343 goto done;
1344 }
1345
1346 /* Check whether we've seen this REND_COOKIE before to detect repeats. */
1350 sizeof(data.rdv_data.rendezvous_cookie),
1351 &elapsed)) {
1352 /* A Tor client will send a new INTRODUCE1 cell with the same REND_COOKIE
1353 * as its previous one if its intro circ times out while in state
1354 * CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT. If we received the first
1355 * INTRODUCE1 cell (the intro-point relay converts it into an INTRODUCE2
1356 * cell), we are already trying to connect to that rend point (and may
1357 * have already succeeded); drop this cell. */
1358 log_info(LD_REND, "We received an INTRODUCE2 cell with same REND_COOKIE "
1359 "field %ld seconds ago. Dropping cell.",
1360 (long int) elapsed);
1362 HS_METRICS_ERR_INTRO_REQ_INTRODUCE2_REPLAY);
1363 goto done;
1364 }
1365
1366 /* At this point, we just confirmed that the full INTRODUCE2 cell is valid
1367 * so increment our counter that we've seen one on this intro point. */
1368 ip->introduce2_count++;
1369
1370 /* Add the rendezvous request to the priority queue if PoW defenses are
1371 * enabled, otherwise rendezvous as usual. */
1372 if (have_module_pow() && service->config.has_pow_defenses_enabled) {
1373 log_info(LD_REND,
1374 "Adding introduction request to pqueue with effort: %u",
1375 data.rdv_data.pow_effort);
1376 if (enqueue_rend_request(service, ip, &data, now) < 0) {
1377 goto done;
1378 }
1379
1380 /* Track the total effort in valid requests received this period */
1381 service->state.pow_state->total_effort += data.rdv_data.pow_effort;
1382
1383 /* Successfully added rend circuit to priority queue. */
1384 ret = 0;
1385 goto done;
1386 }
1387
1388 /* Launch rendezvous circuit with the onion key and rend cookie. */
1389 launch_rendezvous_point_circuit(service, &ip->auth_key_kp.pubkey,
1390 &ip->enc_key_kp, &data.rdv_data, now);
1391 /* Success. */
1392 ret = 0;
1393
1394 done:
1395 /* Note that if PoW defenses are enabled, this is NULL. */
1396 link_specifier_smartlist_free(data.rdv_data.link_specifiers);
1397 memwipe(&data, 0, sizeof(data));
1398 return ret;
1399}
1400
1401/** Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
1402 * exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
1403 * serve as a rendezvous end-to-end circuit between the client and the
1404 * service. If <b>is_service_side</b> is set, then we are the hidden service
1405 * and the other side is the client.
1406 *
1407 * Return 0 if the operation went well; in case of error return -1. */
1408int
1410 const uint8_t *ntor_key_seed, size_t seed_len,
1411 int is_service_side)
1412{
1413 if (BUG(!circuit_purpose_is_correct_for_rend(TO_CIRCUIT(circ)->purpose,
1414 is_service_side))) {
1415 return -1;
1416 }
1417
1418 crypt_path_t *hop = create_rend_cpath(ntor_key_seed, seed_len,
1419 is_service_side);
1420 if (!hop) {
1421 log_warn(LD_REND, "Couldn't get v3 %s cpath!",
1422 is_service_side ? "service-side" : "client-side");
1423 return -1;
1424 }
1425
1426 finalize_rend_circuit(circ, hop, is_service_side);
1427
1428 return 0;
1429}
1430
1431/** Given the introduction circuit intro_circ, the rendezvous circuit
1432 * rend_circ, a descriptor intro point object ip and the service's
1433 * subcredential, send an INTRODUCE1 cell on intro_circ.
1434 *
1435 * This will also setup the circuit identifier on rend_circ containing the key
1436 * material for the handshake and e2e encryption. Return 0 on success else
1437 * negative value. Because relay_send_command_from_edge() closes the circuit
1438 * on error, it is possible that intro_circ is closed on error. */
1439int
1441 origin_circuit_t *rend_circ,
1442 const hs_desc_intro_point_t *ip,
1443 const hs_subcredential_t *subcredential,
1444 const hs_pow_solution_t *pow_solution)
1445{
1446 int ret = -1;
1447 ssize_t payload_len;
1448 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
1449 hs_cell_introduce1_data_t intro1_data;
1450
1451 tor_assert(intro_circ);
1452 tor_assert(rend_circ);
1453 tor_assert(ip);
1454 tor_assert(subcredential);
1455
1456 /* It is undefined behavior in hs_cell_introduce1_data_clear() if intro1_data
1457 * has been declared on the stack but not initialized. Here, we set it to 0.
1458 */
1459 memset(&intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
1460
1461 /* This takes various objects in order to populate the introduce1 data
1462 * object which is used to build the content of the cell. */
1463 const node_t *exit_node = build_state_get_exit_node(rend_circ->build_state);
1464 if (exit_node == NULL) {
1465 log_info(LD_REND, "Unable to get rendezvous point for circuit %u. "
1466 "Failing.", TO_CIRCUIT(intro_circ)->n_circ_id);
1467 goto done;
1468 }
1469
1470 /* We should never select an invalid rendezvous point in theory but if we
1471 * do, this function will fail to populate the introduce data. */
1472 if (setup_introduce1_data(ip, exit_node, subcredential, &intro1_data) < 0) {
1473 log_info(LD_REND, "Unable to setup INTRODUCE1 data. The chosen rendezvous "
1474 "point is unusable. Closing circuit.");
1475 goto close;
1476 }
1477
1478 /* Set the PoW solution if any. */
1479 intro1_data.pow_solution = pow_solution;
1480
1481 /* If the rend circ was set up for congestion control, add that to the
1482 * intro data, to signal it in an extension */
1483 if (TO_CIRCUIT(rend_circ)->ccontrol) {
1484 intro1_data.cc_enabled = 1;
1485 }
1486
1487 /* Final step before we encode a cell, we setup the circuit identifier which
1488 * will generate both the rendezvous cookie and client keypair for this
1489 * connection. Those are put in the ident. */
1490 intro1_data.rendezvous_cookie = rend_circ->hs_ident->rendezvous_cookie;
1491 intro1_data.client_kp = &rend_circ->hs_ident->rendezvous_client_kp;
1492
1493 memcpy(intro_circ->hs_ident->rendezvous_cookie,
1494 rend_circ->hs_ident->rendezvous_cookie,
1495 sizeof(intro_circ->hs_ident->rendezvous_cookie));
1496
1497 /* From the introduce1 data object, this will encode the INTRODUCE1 cell
1498 * into payload which is then ready to be sent as is. */
1499 payload_len = hs_cell_build_introduce1(&intro1_data, payload);
1500 if (BUG(payload_len < 0)) {
1501 goto close;
1502 }
1503
1504 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(intro_circ),
1505 RELAY_COMMAND_INTRODUCE1,
1506 (const char *) payload, payload_len,
1507 intro_circ->cpath->prev) < 0) {
1508 /* On error, circuit is closed. */
1509 log_warn(LD_REND, "Unable to send INTRODUCE1 cell on circuit %u.",
1510 TO_CIRCUIT(intro_circ)->n_circ_id);
1511 goto done;
1512 }
1513
1514 /* Success. */
1515 ret = 0;
1516 goto done;
1517
1518 close:
1519 circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
1520 done:
1521 hs_cell_introduce1_data_clear(&intro1_data);
1522 memwipe(payload, 0, sizeof(payload));
1523 return ret;
1524}
1525
1526/** Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
1527 * success, 0 is returned else -1 and the circuit is marked for close. */
1528int
1530{
1531 ssize_t cell_len = 0;
1532 uint8_t cell[RELAY_PAYLOAD_SIZE_MAX] = {0};
1533
1534 tor_assert(circ);
1536
1537 log_info(LD_REND, "Send an ESTABLISH_RENDEZVOUS cell on circuit %u",
1538 TO_CIRCUIT(circ)->n_circ_id);
1539
1540 /* Set timestamp_dirty, because circuit_expire_building expects it,
1541 * and the rend cookie also means we've used the circ. */
1542 TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
1543
1544 /* We've attempted to use this circuit. Probe it if we fail */
1546
1547 /* Generate the RENDEZVOUS_COOKIE and place it in the identifier so we can
1548 * complete the handshake when receiving the acknowledgement. */
1550 /* Generate the client keypair. No need to be extra strong, not long term */
1552
1553 cell_len =
1555 cell);
1556 if (BUG(cell_len < 0)) {
1557 goto err;
1558 }
1559
1560 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
1561 RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
1562 (const char *) cell, cell_len,
1563 circ->cpath->prev) < 0) {
1564 /* Circuit has been marked for close */
1565 log_warn(LD_REND, "Unable to send ESTABLISH_RENDEZVOUS cell on "
1566 "circuit %u", TO_CIRCUIT(circ)->n_circ_id);
1567 memwipe(cell, 0, cell_len);
1568 goto err;
1569 }
1570
1571 memwipe(cell, 0, cell_len);
1572 return 0;
1573 err:
1574 return -1;
1575}
1576
1577/** Circuit cleanup strategy:
1578 *
1579 * What follows is a series of functions that notifies the HS subsystem of 3
1580 * different circuit cleanup phase: close, free and repurpose.
1581 *
1582 * Tor can call any of those in any orders so they have to be safe between
1583 * each other. In other words, the free should never depend on close to be
1584 * called before.
1585 *
1586 * The "on_close()" is called from circuit_mark_for_close() which is
1587 * considered the tor fast path and thus as little work as possible should
1588 * done in that function. Currently, we only remove the circuit from the HS
1589 * circuit map and move on.
1590 *
1591 * The "on_free()" is called from circuit circuit_free_() and it is very
1592 * important that at the end of the function, no state or objects related to
1593 * this circuit remains alive.
1594 *
1595 * The "on_repurpose()" is called from circuit_change_purpose() for which we
1596 * simply remove it from the HS circuit map. We do not have other cleanup
1597 * requirements after that.
1598 *
1599 * NOTE: The onion service code, specifically the service code, cleans up
1600 * lingering objects or state if any of its circuit disappear which is why
1601 * our cleanup strategy doesn't involve any service specific actions. As long
1602 * as the circuit is removed from the HS circuit map, it won't be used.
1603 */
1604
1605/** We are about to close this <b>circ</b>. Clean it up from any related HS
1606 * data structures. This function can be called multiple times safely for the
1607 * same circuit. */
1608void
1610{
1611 tor_assert(circ);
1612
1615 }
1616
1618 if (circuit_is_hs_v3(circ)) {
1620 }
1621 }
1622
1623 /* On close, we simply remove it from the circuit map. It can not be used
1624 * anymore. We keep this code path fast and lean. */
1625
1626 if (circ->hs_token) {
1628 }
1629}
1630
1631/** We are about to free this <b>circ</b>. Clean it up from any related HS
1632 * data structures. This function can be called multiple times safely for the
1633 * same circuit. */
1634void
1636{
1637 tor_assert(circ);
1638
1639 /* NOTE: Bulk of the work of cleaning up a circuit is done here. */
1640
1643 }
1644
1645 /* We have no assurance that the given HS circuit has been closed before and
1646 * thus removed from the HS map. This actually happens in unit tests. */
1647 if (circ->hs_token) {
1649 }
1650}
1651
1652/** We are about to repurpose this <b>circ</b>. Clean it up from any related
1653 * HS data structures. This function can be called multiple times safely for
1654 * the same circuit. */
1655void
1657{
1658 tor_assert(circ);
1659
1660 /* On repurpose, we simply remove it from the circuit map but we do not do
1661 * the on_free actions since we don't treat a repurpose as something we need
1662 * to report in the client cache failure. */
1663
1664 if (circ->hs_token) {
1666 }
1667
1668 switch (circ->purpose) {
1670 /* This circuit was connecting to a rendezvous point but it is being
1671 * repurposed so we need to relaunch an attempt else the client will be
1672 * left hanging waiting for the rendezvous. */
1674 break;
1675 default:
1676 break;
1677 }
1678}
1679
1680/** Return true iff the given established client rendezvous circuit was sent
1681 * into the INTRODUCE1 cell. This is called so we can take a decision on
1682 * expiring or not the circuit.
1683 *
1684 * The caller MUST make sure the circuit is an established client rendezvous
1685 * circuit (purpose: CIRCUIT_PURPOSE_C_REND_READY).
1686 *
1687 * This function supports all onion service versions. */
1688bool
1690{
1691 tor_assert(circ);
1692 /* This can only be called for a rendezvous circuit that is an established
1693 * confirmed rendezsvous circuit but without an introduction ACK. */
1695
1696 /* When the INTRODUCE1 cell is sent, the introduction encryption public
1697 * key is copied in the rendezvous circuit hs identifier. If it is a valid
1698 * key, we know that this circuit is waiting the ACK on the introduction
1699 * circuit. We want to _not_ spare the circuit if the key was never set. */
1700
1701 if (circ->hs_ident) {
1702 /* v3. */
1704 return true;
1705 }
1706 } else {
1707 /* A circuit with an HS purpose without an hs_ident in theory can not
1708 * happen. In case, scream loudly and return false to the caller that the
1709 * rendezvous was not sent in the INTRO1 cell. */
1711 }
1712
1713 /* The rendezvous has not been specified in the INTRODUCE1 cell. */
1714 return false;
1715}
const char * hex_str(const char *from, size_t fromlen)
Definition: binascii.c:34
void pathbias_count_use_attempt(origin_circuit_t *circ)
Definition: circpathbias.c:626
void pathbias_mark_use_success(origin_circuit_t *circ)
Definition: circpathbias.c:683
void circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
Definition: circuitbuild.c:356
const node_t * build_state_get_exit_node(cpath_build_state_t *state)
Header file for circuitbuild.c.
origin_circuit_t * circuit_get_next_by_purpose(origin_circuit_t *start, uint8_t purpose)
Definition: circuitlist.c:1804
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:185
int32_t circuit_initial_package_window(void)
Definition: circuitlist.c:1007
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_S_CONNECT_REND
Definition: circuitlist.h:107
#define CIRCUIT_STATE_OPEN
Definition: circuitlist.h:32
#define CIRCUIT_PURPOSE_C_REND_JOINED
Definition: circuitlist.h:88
#define CIRCUIT_PURPOSE_S_INTRO
Definition: circuitlist.h:104
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED
Definition: circuitlist.h:86
#define CIRCUIT_PURPOSE_S_REND_JOINED
Definition: circuitlist.h:110
#define CIRCUIT_PURPOSE_C_REND_READY
Definition: circuitlist.h:83
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
Definition: circuitlist.h:101
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND
Definition: circuitlist.h:81
#define CIRCUIT_PURPOSE_C_GENERAL
Definition: circuitlist.h:70
#define CIRCUIT_PURPOSE_HS_VANGUARDS
Definition: circuitlist.h:131
bool circuit_is_hs_v3(const circuit_t *circ)
Definition: circuituse.c:2001
bool circuit_purpose_is_hs_service(const uint8_t purpose)
Definition: circuituse.c:1986
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Definition: circuituse.c:3099
int circuit_should_use_vanguards(uint8_t purpose)
Definition: circuituse.c:2018
void circuit_has_opened(origin_circuit_t *circ)
Definition: circuituse.c:1664
bool circuit_purpose_is_hs_client(const uint8_t purpose)
Definition: circuituse.c:1978
origin_circuit_t * circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info, int flags)
Definition: circuituse.c:2094
void circuit_try_attaching_streams(origin_circuit_t *circ)
Definition: circuituse.c:1744
Header file for circuituse.c.
#define CIRCLAUNCH_NEED_CAPACITY
Definition: circuituse.h:43
#define CIRCLAUNCH_ONEHOP_TUNNEL
Definition: circuituse.h:39
#define CIRCLAUNCH_IS_INTERNAL
Definition: circuituse.h:46
#define CIRCLAUNCH_NEED_UPTIME
Definition: circuituse.h:41
#define MAX(a, b)
Definition: cmp.h:22
mainloop_event_t * mainloop_event_postloop_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
int mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
void mainloop_event_activate(mainloop_event_t *event)
Functions and types for monotonic times.
const or_options_t * get_options(void)
Definition: config.c:947
Header file for config.c.
congestion_control_t * congestion_control_new(const circuit_params_t *params, cc_path_t path)
Public APIs for congestion control.
static uint8_t congestion_control_sendme_inc(void)
Structure definitions for congestion control.
Circuit-build-stse structure.
int cpath_init_circuit_crypto(crypt_path_t *cpath, const char *key_data, size_t key_data_len, int reverse, int is_hs_v3)
Definition: crypt_path.c:151
void cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop)
Definition: crypt_path.c:42
Header file for crypt_path.c.
Path structures for origin circuits.
int curve25519_keypair_generate(curve25519_keypair_t *keypair_out, int extra_strong)
int curve25519_public_key_is_ok(const curve25519_public_key_t *key)
Headers for crypto_dh.c.
void ed25519_pubkey_copy(ed25519_public_key_t *dest, const ed25519_public_key_t *src)
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
int ed25519_pubkey_eq(const ed25519_public_key_t *key1, const ed25519_public_key_t *key2)
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:479
Common functions for using (pseudo-)random number generators.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
const char * extend_info_describe(const extend_info_t *ei)
Definition: describe.c:224
Header file for describe.c.
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Extend-info structure.
Header for core/or/extendinfo.c.
ssize_t hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, uint8_t *cell_out)
Definition: hs_cell.c:1219
ssize_t hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, const origin_circuit_t *circ, const hs_service_t *service, const hs_service_intro_point_t *ip)
Definition: hs_cell.c:974
ssize_t hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
Definition: hs_cell.c:780
ssize_t hs_cell_build_establish_intro(const char *circ_nonce, const hs_service_config_t *service_config, const hs_service_intro_point_t *ip, uint8_t *cell_out)
Definition: hs_cell.c:665
void hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
Definition: hs_cell.c:1286
ssize_t hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie, size_t rendezvous_cookie_len, const uint8_t *rendezvous_handshake_info, size_t rendezvous_handshake_info_len, uint8_t *cell_out)
Definition: hs_cell.c:1142
ssize_t hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, uint8_t *cell_out)
Definition: hs_cell.c:1178
Header file containing cell data for the whole HS subsystem.
int top_of_rend_pqueue_is_worthwhile(hs_pow_service_state_t *pow_state)
Definition: hs_circuit.c:736
static int queued_rend_request_is_too_old(pending_rend_t *req, time_t now)
Definition: hs_circuit.c:658
void hs_circ_service_rp_has_opened(const hs_service_t *service, origin_circuit_t *circ)
Definition: hs_circuit.c:1155
static int get_subcredential_for_handling_intro2_cell(const hs_service_t *service, hs_cell_introduce2_data_t *data, const hs_subcredential_t *desc_subcred)
Definition: hs_circuit.c:1276
origin_circuit_t * hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:965
void hs_circ_cleanup_on_repurpose(circuit_t *circ)
Definition: hs_circuit.c:1656
static void cleanup_on_close_client_circ(circuit_t *circ)
Definition: hs_circuit.c:606
static void register_intro_circ(const hs_service_intro_point_t *ip, origin_circuit_t *circ)
Definition: hs_circuit.c:165
int hs_circ_send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ, const hs_desc_intro_point_t *ip, const hs_subcredential_t *subcredential, const hs_pow_solution_t *pow_solution)
Definition: hs_circuit.c:1440
int hs_circ_launch_intro_point(hs_service_t *service, const hs_service_intro_point_t *ip, extend_info_t *ei, bool direct_conn)
Definition: hs_circuit.c:1029
static void finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop, int is_service_side)
Definition: hs_circuit.c:130
void hs_circ_setup_congestion_control(origin_circuit_t *origin_circ, uint8_t sendme_inc, bool is_single_onion)
Definition: hs_circuit.c:932
static int count_service_rp_circuits_pending(hs_service_t *service)
Definition: hs_circuit.c:715
origin_circuit_t * hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:976
static hs_ident_circuit_t * create_intro_circuit_identifier(const hs_service_t *service, const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:249
static void retry_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:493
static void free_pending_rend(pending_rend_t *req)
Definition: hs_circuit.c:53
#define MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS
Definition: hs_circuit.c:765
void rend_pqueue_clear(hs_pow_service_state_t *pow_state)
Definition: hs_circuit.c:752
static void trim_rend_pqueue(hs_pow_service_state_t *pow_state, time_t now)
Definition: hs_circuit.c:669
int hs_circ_service_intro_has_opened(hs_service_t *service, hs_service_intro_point_t *ip, const hs_service_descriptor_t *desc, origin_circuit_t *circ)
Definition: hs_circuit.c:1087
STATIC void launch_rendezvous_point_circuit(const hs_service_t *service, const ed25519_public_key_t *ip_auth_pubkey, const curve25519_keypair_t *ip_enc_key_kp, const hs_cell_intro_rdv_data_t *rdv_data, time_t now)
Definition: hs_circuit.c:335
static void cleanup_on_free_client_circ(circuit_t *circ)
Definition: hs_circuit.c:620
void hs_circ_cleanup_on_close(circuit_t *circ)
Definition: hs_circuit.c:1609
static int compare_rend_request_by_effort_(const void *_a, const void *_b)
Definition: hs_circuit.c:634
static void send_establish_intro(const hs_service_t *service, hs_service_intro_point_t *ip, origin_circuit_t *circ)
Definition: hs_circuit.c:270
int hs_circ_handle_introduce2(const hs_service_t *service, const origin_circuit_t *circ, hs_service_intro_point_t *ip, const hs_subcredential_t *subcredential, const uint8_t *payload, size_t payload_len)
Definition: hs_circuit.c:1306
int hs_circ_handle_intro_established(const hs_service_t *service, const hs_service_intro_point_t *ip, origin_circuit_t *circ, const uint8_t *payload, size_t payload_len)
Definition: hs_circuit.c:1227
static int can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:457
static unsigned int count_opened_desc_intro_point_circuits(const hs_service_t *service, const hs_service_descriptor_t *desc)
Definition: hs_circuit.c:178
bool hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
Definition: hs_circuit.c:1689
void hs_circ_retry_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:1003
STATIC hs_ident_circuit_t * create_rp_circuit_identifier(const hs_service_t *service, const uint8_t *rendezvous_cookie, const curve25519_public_key_t *server_pk, const hs_ntor_rend_cell_keys_t *keys)
Definition: hs_circuit.c:210
static int circuit_purpose_is_correct_for_rend(unsigned int circ_purpose, int is_service_side)
Definition: hs_circuit.c:67
static int setup_introduce1_data(const hs_desc_intro_point_t *ip, const node_t *rp_node, const hs_subcredential_t *subcredential, hs_cell_introduce1_data_t *intro1_data)
Definition: hs_circuit.c:562
int hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
Definition: hs_circuit.c:1529
int hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ, const uint8_t *ntor_key_seed, size_t seed_len, int is_service_side)
Definition: hs_circuit.c:1409
void hs_circ_cleanup_on_free(circuit_t *circ)
Definition: hs_circuit.c:1635
static int enqueue_rend_request(const hs_service_t *service, hs_service_intro_point_t *ip, hs_cell_introduce2_data_t *data, time_t now)
Definition: hs_circuit.c:865
static crypt_path_t * create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len, int is_service_side)
Definition: hs_circuit.c:97
static const char * get_service_anonymity_string(const hs_service_t *service)
Definition: hs_circuit.c:316
Header file containing circuit data for the whole HS subsystem.
void hs_circuitmap_remove_circuit(circuit_t *circ)
void hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ, const ed25519_public_key_t *auth_key)
origin_circuit_t * hs_circuitmap_get_intro_circ_v3_service_side(const ed25519_public_key_t *auth_key)
Header file for hs_circuitmap.c.
void hs_client_circuit_cleanup_on_close(const circuit_t *circ)
Definition: hs_client.c:2048
void hs_client_circuit_cleanup_on_free(const circuit_t *circ)
Definition: hs_client.c:2079
Header file containing client data for the HS subsystem.
int hs_get_service_max_rend_failures(void)
Definition: hs_common.c:233
extend_info_t * hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, const curve25519_public_key_t *onion_key, int direct_conn)
Definition: hs_common.c:1596
int hs_service_requires_uptime_circ(const smartlist_t *ports)
Definition: hs_common.c:1016
Header file containing common data for the whole HS subsystem.
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE
Definition: hs_common.h:128
#define MAX_REND_FAILURES
Definition: hs_common.h:44
#define MAX_REND_TIMEOUT
Definition: hs_common.h:47
hs_ident_circuit_t * hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
Definition: hs_ident.c:16
hs_ident_circuit_t * hs_ident_circuit_dup(const hs_ident_circuit_t *src)
Definition: hs_ident.c:37
Header file containing circuit and connection identifier data for the whole HS subsystem.
#define HS_REND_COOKIE_LEN
Definition: hs_ident.h:30
Header for feature/hs/hs_metrics.c.
#define hs_metrics_new_rdv(i)
Definition: hs_metrics.h:74
#define hs_metrics_pow_pqueue_rdv(s, n)
Definition: hs_metrics.h:78
#define hs_metrics_failed_rdv(i, reason)
Definition: hs_metrics.h:63
#define hs_metrics_reject_intro_req(s, reason)
Definition: hs_metrics.h:42
int hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed, size_t seed_len, uint8_t *keys_out, size_t keys_out_len)
Definition: hs_ntor.c:615
Header for hs_ntor.c.
bool hs_ob_service_is_instance(const hs_service_t *service)
Definition: hs_ob.c:201
Header file for the specific code for onion balance.
void hs_service_circuit_cleanup_on_close(const circuit_t *circ)
Definition: hs_service.c:3942
Header file containing service data for the HS subsystem.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_REND
Definition: log.h:84
#define LD_BUG
Definition: log.h:86
#define LD_GENERAL
Definition: log.h:62
#define LD_CIRC
Definition: log.h:82
#define LOG_INFO
Definition: log.h:45
#define tor_free(p)
Definition: malloc.h:56
Node information structure.
const curve25519_public_key_t * node_get_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:2059
Header file for nodelist.c.
Header file for onion_crypto.c.
Master header file for Tor-specific functionality.
#define REND_COOKIE_LEN
Definition: or.h:401
#define TO_CIRCUIT(x)
Definition: or.h:936
#define CIRCWINDOW_START
Definition: or.h:442
#define RELAY_PAYLOAD_SIZE_MAX
Definition: or.h:567
@ RELAY_CELL_FORMAT_V0
Definition: or.h:531
Origin circuit structure.
Header file for policies.c.
Header file for relay.c.
Header file for rephist.c.
int replaycache_add_test_and_elapsed(replaycache_t *r, const void *data, size_t len, time_t *elapsed)
Definition: replaycache.c:195
void * smartlist_pqueue_pop(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset)
Definition: smartlist.c:755
void smartlist_pqueue_add(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset, void *item)
Definition: smartlist.c:726
void * smartlist_pop_last(smartlist_t *sl)
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
uint8_t sendme_inc_cells
Definition: onion_crypto.h:36
struct hs_token_t * hs_token
Definition: circuit_st.h:217
uint8_t state
Definition: circuit_st.h:111
uint16_t marked_for_close
Definition: circuit_st.h:190
uint8_t purpose
Definition: circuit_st.h:112
struct congestion_control_t * ccontrol
Definition: circuit_st.h:250
extend_info_t * chosen_exit
struct crypt_path_t * prev
Definition: crypt_path_st.h:79
uint8_t state
Definition: crypt_path_st.h:72
relay_cell_fmt_t relay_cell_format
Definition: crypt_path_st.h:91
char rend_circ_nonce[DIGEST_LEN]
Definition: crypt_path_st.h:62
struct congestion_control_t * ccontrol
Definition: crypt_path_st.h:88
curve25519_public_key_t onion_pk
Definition: hs_cell.h:54
uint8_t rendezvous_cookie[REND_COOKIE_LEN]
Definition: hs_cell.h:56
unsigned int cc_enabled
Definition: hs_cell.h:62
curve25519_public_key_t client_pk
Definition: hs_cell.h:58
smartlist_t * link_specifiers
Definition: hs_cell.h:60
const ed25519_public_key_t * auth_pk
Definition: hs_cell.h:31
const struct hs_subcredential_t * subcredential
Definition: hs_cell.h:35
const hs_pow_solution_t * pow_solution
Definition: hs_cell.h:47
const curve25519_keypair_t * client_kp
Definition: hs_cell.h:41
const curve25519_public_key_t * enc_pk
Definition: hs_cell.h:33
unsigned int cc_enabled
Definition: hs_cell.h:45
const uint8_t * rendezvous_cookie
Definition: hs_cell.h:39
const curve25519_public_key_t * onion_pk
Definition: hs_cell.h:37
smartlist_t * link_specifiers
Definition: hs_cell.h:43
const ed25519_public_key_t * auth_pk
Definition: hs_cell.h:77
const curve25519_keypair_t * enc_kp
Definition: hs_cell.h:81
replaycache_t * replay_cache
Definition: hs_cell.h:100
const struct hs_subcredential_t * subcredentials
Definition: hs_cell.h:89
const uint8_t * payload
Definition: hs_cell.h:91
hs_cell_intro_rdv_data_t rdv_data
Definition: hs_cell.h:98
curve25519_public_key_t enc_key
tor_cert_t * auth_key_cert
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN]
Definition: hs_ident.h:60
ed25519_public_key_t intro_auth_pk
Definition: hs_ident.h:51
curve25519_keypair_t rendezvous_client_kp
Definition: hs_ident.h:72
curve25519_public_key_t intro_enc_pk
Definition: hs_ident.h:55
uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN]
Definition: hs_ident.h:76
ed25519_public_key_t identity_pk
Definition: hs_ident.h:45
uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN+DIGEST256_LEN]
Definition: hs_ident.h:68
unsigned int is_single_onion
Definition: hs_service.h:252
smartlist_t * ports
Definition: hs_service.h:223
unsigned int num_intro_points
Definition: hs_service.h:240
unsigned int has_pow_defenses_enabled
Definition: hs_service.h:270
hs_service_intropoints_t intro_points
Definition: hs_service.h:172
ed25519_keypair_t auth_key_kp
Definition: hs_service.h:60
replaycache_t * replay_cache
Definition: hs_service.h:94
curve25519_keypair_t enc_key_kp
Definition: hs_service.h:63
digest256map_t * map
Definition: hs_service.h:113
ed25519_public_key_t identity_pk
Definition: hs_service.h:188
replaycache_t * replay_cache_rend_cookie
Definition: hs_service.h:295
hs_pow_service_state_t * pow_state
Definition: hs_service.h:311
unsigned int num_intro_circ_launched
Definition: hs_service.h:288
hs_service_state_t state
Definition: hs_service.h:325
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]
Definition: hs_service.h:318
hs_service_config_t config
Definition: hs_service.h:331
hs_service_keys_t keys
Definition: hs_service.h:328
Definition: node_st.h:34
struct hs_ident_circuit_t * hs_ident
crypt_path_t * cpath
cpath_build_state_t * build_state
unsigned int hs_with_pow_circ
time_t enqueued_ts
Definition: hs_circuit.h:32
ed25519_public_key_t signed_key
Definition: torcert.h:33
#define STATIC
Definition: testsupport.h:32
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
void token_bucket_ctr_refill(token_bucket_ctr_t *bucket, uint32_t now_ts_sec)
Definition: token_bucket.c:296
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177
#define tor_assert(expr)
Definition: util_bug.h:103
#define CURVE25519_PUBKEY_LEN
Definition: x25519_sizes.h:20