Line data Source code
1 : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 : /* See LICENSE for licensing information */
4 :
5 : /**
6 : * \file rendmid.c
7 : * \brief Implement introductions points and rendezvous points.
8 : **/
9 :
10 : #include "core/or/or.h"
11 : #include "core/or/channel.h"
12 : #include "core/or/circuitlist.h"
13 : #include "core/or/circuituse.h"
14 : #include "app/config/config.h"
15 : #include "lib/crypt_ops/crypto_cipher.h"
16 : #include "core/or/dos.h"
17 : #include "core/or/relay.h"
18 : #include "feature/rend/rendmid.h"
19 : #include "feature/hs/hs_circuitmap.h"
20 : #include "feature/hs/hs_dos.h"
21 : #include "feature/hs/hs_intropoint.h"
22 :
23 : #include "core/or/or_circuit_st.h"
24 :
25 : /** Process an ESTABLISH_RENDEZVOUS cell by setting the circuit's purpose and
26 : * rendezvous cookie.
27 : */
28 : int
29 0 : rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
30 : size_t request_len)
31 : {
32 0 : char hexid[9];
33 0 : int reason = END_CIRC_REASON_TORPROTOCOL;
34 :
35 0 : log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u",
36 : (unsigned)circ->p_circ_id);
37 :
38 0 : if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) {
39 0 : log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
40 : "Tried to establish rendezvous on non-OR circuit with purpose %s",
41 : circuit_purpose_to_string(circ->base_.purpose));
42 0 : goto err;
43 : }
44 :
45 : /* Check if we are configured to defend ourselves from clients that
46 : * attempt to establish rendezvous points directly to us. */
47 0 : if (channel_is_client(circ->p_chan) &&
48 0 : dos_should_refuse_single_hop_client()) {
49 : /* Note it down for the heartbeat log purposes. */
50 0 : dos_note_refuse_single_hop_client();
51 : /* Silent drop so the client has to time out before moving on. */
52 0 : return 0;
53 : }
54 :
55 0 : if (circ->base_.n_chan) {
56 0 : log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
57 : "Tried to establish rendezvous on non-edge circuit");
58 0 : goto err;
59 : }
60 :
61 0 : if (request_len != REND_COOKIE_LEN) {
62 0 : log_fn(LOG_PROTOCOL_WARN,
63 : LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS.");
64 0 : goto err;
65 : }
66 :
67 0 : if (hs_circuitmap_get_rend_circ_relay_side(request)) {
68 0 : log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
69 : "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
70 0 : goto err;
71 : }
72 :
73 : /* Acknowledge the request. */
74 0 : if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
75 : RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
76 : "", 0, NULL)<0) {
77 0 : log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
78 : /* Stop right now, the circuit has been closed. */
79 0 : return -1;
80 : }
81 :
82 0 : circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_POINT_WAITING);
83 0 : hs_circuitmap_register_rend_circ_relay_side(circ, request);
84 :
85 0 : base16_encode(hexid,9,(char*)request,4);
86 :
87 0 : log_info(LD_REND,
88 : "Established rendezvous point on circuit %u for cookie %s",
89 : (unsigned)circ->p_circ_id, hexid);
90 :
91 0 : return 0;
92 0 : err:
93 0 : circuit_mark_for_close(TO_CIRCUIT(circ), reason);
94 0 : return -1;
95 : }
96 :
97 : /** Process a RENDEZVOUS1 cell by looking up the correct rendezvous
98 : * circuit by its relaying the cell's body in a RENDEZVOUS2 cell, and
99 : * connecting the two circuits.
100 : */
101 : int
102 0 : rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
103 : size_t request_len)
104 : {
105 0 : const or_options_t *options = get_options();
106 0 : or_circuit_t *rend_circ;
107 0 : char hexid[9];
108 0 : int reason = END_CIRC_REASON_INTERNAL;
109 :
110 0 : if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
111 0 : log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
112 : "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
113 : (unsigned)circ->p_circ_id);
114 0 : reason = END_CIRC_REASON_TORPROTOCOL;
115 0 : goto err;
116 : }
117 :
118 0 : if (request_len < REND_COOKIE_LEN) {
119 0 : log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
120 : "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.",
121 : (int)request_len, (unsigned)circ->p_circ_id);
122 0 : reason = END_CIRC_REASON_TORPROTOCOL;
123 0 : goto err;
124 : }
125 :
126 0 : base16_encode(hexid, sizeof(hexid), (const char*)request, 4);
127 :
128 0 : log_info(LD_REND,
129 : "Got request for rendezvous from circuit %u to cookie %s.",
130 : (unsigned)circ->p_circ_id, hexid);
131 :
132 0 : rend_circ = hs_circuitmap_get_rend_circ_relay_side(request);
133 0 : if (!rend_circ) {
134 0 : log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
135 : "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
136 : hexid);
137 0 : reason = END_CIRC_REASON_TORPROTOCOL;
138 0 : goto err;
139 : }
140 :
141 : /* Statistics: Mark circuits as RP circuits */
142 0 : if (options->HiddenServiceStatistics) {
143 : /* `circ` is the RP <-> service circuit */
144 0 : circ->circuit_carries_hs_traffic_stats = 1;
145 : /* `rend_circ` is the client <-> RP circuit */
146 0 : rend_circ->circuit_carries_hs_traffic_stats = 1;
147 : }
148 :
149 : /* Send the RENDEZVOUS2 cell to the client. */
150 0 : if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ),
151 : RELAY_COMMAND_RENDEZVOUS2,
152 : (char*)(request+REND_COOKIE_LEN),
153 : request_len-REND_COOKIE_LEN, NULL)) {
154 0 : log_warn(LD_GENERAL,
155 : "Unable to send RENDEZVOUS2 cell to client on circuit %u.",
156 : (unsigned)rend_circ->p_circ_id);
157 : /* Stop right now, the circuit has been closed. */
158 0 : return -1;
159 : }
160 :
161 : /* Join the circuits. */
162 0 : log_info(LD_REND,
163 : "Completing rendezvous: circuit %u joins circuit %u (cookie %s)",
164 : (unsigned)circ->p_circ_id, (unsigned)rend_circ->p_circ_id, hexid);
165 :
166 0 : circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED);
167 0 : circuit_change_purpose(TO_CIRCUIT(rend_circ),
168 : CIRCUIT_PURPOSE_REND_ESTABLISHED);
169 0 : hs_circuitmap_remove_circuit(TO_CIRCUIT(circ));
170 :
171 0 : rend_circ->rend_splice = circ;
172 0 : circ->rend_splice = rend_circ;
173 :
174 0 : return 0;
175 0 : err:
176 0 : circuit_mark_for_close(TO_CIRCUIT(circ), reason);
177 0 : return -1;
178 : }
|