Tor 0.4.9.0-alpha-dev
rendmid.c
Go to the documentation of this file.
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"
16#include "core/or/dos.h"
17#include "core/or/relay.h"
20#include "feature/hs/hs_dos.h"
23
24#include "core/or/or_circuit_st.h"
25
26/** Process an ESTABLISH_RENDEZVOUS cell by setting the circuit's purpose and
27 * rendezvous cookie.
28 */
29int
30rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
31 size_t request_len)
32{
33 char hexid[9];
34 int reason = END_CIRC_REASON_TORPROTOCOL;
35
36 log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u",
37 (unsigned)circ->p_circ_id);
38
39 if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) {
40 relay_increment_est_rend_action(EST_REND_UNSUITABLE_CIRCUIT);
41 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
42 "Tried to establish rendezvous on non-OR circuit with purpose %s",
44 goto err;
45 }
46
47 /* Check if we are configured to defend ourselves from clients that
48 * attempt to establish rendezvous points directly to us. */
49 if (channel_is_client(circ->p_chan) &&
50 dos_should_refuse_single_hop_client()) {
51 relay_increment_est_rend_action(EST_REND_SINGLE_HOP);
52 /* Note it down for the heartbeat log purposes. */
53 dos_note_refuse_single_hop_client();
54 /* Silent drop so the client has to time out before moving on. */
55 return 0;
56 }
57
58 if (circ->base_.n_chan) {
59 relay_increment_est_rend_action(EST_REND_UNSUITABLE_CIRCUIT);
60 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
61 "Tried to establish rendezvous on non-edge circuit");
62 goto err;
63 }
64
65 if (request_len != REND_COOKIE_LEN) {
66 relay_increment_est_rend_action(EST_REND_MALFORMED);
67 log_fn(LOG_PROTOCOL_WARN,
68 LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS.");
69 goto err;
70 }
71
73 relay_increment_est_rend_action(EST_REND_DUPLICATE_COOKIE);
74 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
75 "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
76 goto err;
77 }
78
79 /* Acknowledge the request. */
80 if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
81 RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
82 "", 0, NULL)<0) {
83 relay_increment_est_rend_action(EST_REND_CIRCUIT_DEAD);
84 log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
85 /* Stop right now, the circuit has been closed. */
86 return -1;
87 }
88
89 relay_increment_est_rend_action(EST_REND_SUCCESS);
92
93 base16_encode(hexid,9,(char*)request,4);
94
95 log_info(LD_REND,
96 "Established rendezvous point on circuit %u for cookie %s",
97 (unsigned)circ->p_circ_id, hexid);
98
99 return 0;
100 err:
101 circuit_mark_for_close(TO_CIRCUIT(circ), reason);
102 return -1;
103}
104
105/** Process a RENDEZVOUS1 cell by looking up the correct rendezvous
106 * circuit by its relaying the cell's body in a RENDEZVOUS2 cell, and
107 * connecting the two circuits.
108 */
109int
110rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
111 size_t request_len)
112{
113 const or_options_t *options = get_options();
114 or_circuit_t *rend_circ;
115 char hexid[9];
116 int reason = END_CIRC_REASON_INTERNAL;
117
118 if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
119 relay_increment_rend1_action(REND1_UNSUITABLE_CIRCUIT);
120 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
121 "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
122 (unsigned)circ->p_circ_id);
123 reason = END_CIRC_REASON_TORPROTOCOL;
124 goto err;
125 }
126
127 if (request_len < REND_COOKIE_LEN) {
128 relay_increment_rend1_action(REND1_MALFORMED);
129 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
130 "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.",
131 (int)request_len, (unsigned)circ->p_circ_id);
132 reason = END_CIRC_REASON_TORPROTOCOL;
133 goto err;
134 }
135
136 base16_encode(hexid, sizeof(hexid), (const char*)request, 4);
137
138 log_info(LD_REND,
139 "Got request for rendezvous from circuit %u to cookie %s.",
140 (unsigned)circ->p_circ_id, hexid);
141
142 rend_circ = hs_circuitmap_get_rend_circ_relay_side(request);
143 if (!rend_circ) {
144 /* Once this was a LOG_PROTOCOL_WARN, but it can happen naturally if a
145 * client gives up on a rendezvous circuit after sending INTRODUCE1, but
146 * before the onion service sends the RENDEZVOUS1 cell.
147 */
148 relay_increment_rend1_action(REND1_UNKNOWN_COOKIE);
150 "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
151 hexid);
152 reason = END_CIRC_REASON_TORPROTOCOL;
153 goto err;
154 }
155
156 /* Statistics: Mark circuits as RP circuits */
157 if (options->HiddenServiceStatistics) {
158 /* `circ` is the RP <-> service circuit */
160 /* `rend_circ` is the client <-> RP circuit */
162 }
163
164 /* Send the RENDEZVOUS2 cell to the client. */
165 if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ),
166 RELAY_COMMAND_RENDEZVOUS2,
167 (char*)(request+REND_COOKIE_LEN),
168 request_len-REND_COOKIE_LEN, NULL)) {
169 relay_increment_rend1_action(REND1_CIRCUIT_DEAD);
170 log_warn(LD_GENERAL,
171 "Unable to send RENDEZVOUS2 cell to client on circuit %u.",
172 (unsigned)rend_circ->p_circ_id);
173 /* Stop right now, the circuit has been closed. */
174 return -1;
175 }
176
177 relay_increment_rend1_action(REND1_SUCCESS);
178 /* Join the circuits. */
179 log_info(LD_REND,
180 "Completing rendezvous: circuit %u joins circuit %u (cookie %s)",
181 (unsigned)circ->p_circ_id, (unsigned)rend_circ->p_circ_id, hexid);
182
187
188 rend_circ->rend_splice = circ;
189 circ->rend_splice = rend_circ;
190
191 return 0;
192 err:
193 circuit_mark_for_close(TO_CIRCUIT(circ), reason);
194 return -1;
195}
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:478
int channel_is_client(const channel_t *chan)
Definition: channel.c:2918
Header file for channel.c.
const char * circuit_purpose_to_string(uint8_t purpose)
Definition: circuitlist.c:929
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_REND_POINT_WAITING
Definition: circuitlist.h:45
#define CIRCUIT_PURPOSE_OR
Definition: circuitlist.h:39
#define CIRCUIT_PURPOSE_REND_ESTABLISHED
Definition: circuitlist.h:47
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Definition: circuituse.c:3095
Header file for circuituse.c.
const or_options_t * get_options(void)
Definition: config.c:944
Header file for config.c.
Headers for crypto_cipher.c.
void hs_circuitmap_remove_circuit(circuit_t *circ)
or_circuit_t * hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
void hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ, const uint8_t *cookie)
Header file for hs_circuitmap.c.
Header file containing denial of service defenses for the HS subsystem for all versions.
Header file for hs_intropoint.c.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_REND
Definition: log.h:84
#define LD_PROTOCOL
Definition: log.h:72
#define LOG_DEBUG
Definition: log.h:42
#define LD_GENERAL
Definition: log.h:62
Master header file for Tor-specific functionality.
#define REND_COOKIE_LEN
Definition: or.h:353
#define TO_CIRCUIT(x)
Definition: or.h:848
Header file for relay.c.
Header for feature/relay/relay_metrics.c.
int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:30
int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:110
Header file for rendmid.c.
uint8_t purpose
Definition: circuit_st.h:112
channel_t * n_chan
Definition: circuit_st.h:70
unsigned int circuit_carries_hs_traffic_stats
Definition: or_circuit_st.h:76
channel_t * p_chan
Definition: or_circuit_st.h:37
circid_t p_circ_id
Definition: or_circuit_st.h:33
struct or_circuit_t * rend_splice
Definition: or_circuit_st.h:58
int HiddenServiceStatistics