Tor  0.4.7.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"
18 #include "feature/rend/rendmid.h"
20 #include "feature/hs/hs_dos.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 rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
30  size_t request_len)
31 {
32  char hexid[9];
33  int reason = END_CIRC_REASON_TORPROTOCOL;
34 
35  log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u",
36  (unsigned)circ->p_circ_id);
37 
38  if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) {
39  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  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  if (channel_is_client(circ->p_chan) &&
48  dos_should_refuse_single_hop_client()) {
49  /* Note it down for the heartbeat log purposes. */
50  dos_note_refuse_single_hop_client();
51  /* Silent drop so the client has to time out before moving on. */
52  return 0;
53  }
54 
55  if (circ->base_.n_chan) {
56  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
57  "Tried to establish rendezvous on non-edge circuit");
58  goto err;
59  }
60 
61  if (request_len != REND_COOKIE_LEN) {
62  log_fn(LOG_PROTOCOL_WARN,
63  LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS.");
64  goto err;
65  }
66 
68  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
69  "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
70  goto err;
71  }
72 
73  /* Acknowledge the request. */
74  if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
75  RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
76  "", 0, NULL)<0) {
77  log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
78  /* Stop right now, the circuit has been closed. */
79  return -1;
80  }
81 
84 
85  base16_encode(hexid,9,(char*)request,4);
86 
87  log_info(LD_REND,
88  "Established rendezvous point on circuit %u for cookie %s",
89  (unsigned)circ->p_circ_id, hexid);
90 
91  return 0;
92  err:
93  circuit_mark_for_close(TO_CIRCUIT(circ), reason);
94  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 rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
103  size_t request_len)
104 {
105  const or_options_t *options = get_options();
106  or_circuit_t *rend_circ;
107  char hexid[9];
108  int reason = END_CIRC_REASON_INTERNAL;
109 
110  if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
111  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  reason = END_CIRC_REASON_TORPROTOCOL;
115  goto err;
116  }
117 
118  if (request_len < REND_COOKIE_LEN) {
119  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  reason = END_CIRC_REASON_TORPROTOCOL;
123  goto err;
124  }
125 
126  base16_encode(hexid, sizeof(hexid), (const char*)request, 4);
127 
128  log_info(LD_REND,
129  "Got request for rendezvous from circuit %u to cookie %s.",
130  (unsigned)circ->p_circ_id, hexid);
131 
132  rend_circ = hs_circuitmap_get_rend_circ_relay_side(request);
133  if (!rend_circ) {
134  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
135  "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
136  hexid);
137  reason = END_CIRC_REASON_TORPROTOCOL;
138  goto err;
139  }
140 
141  /* Statistics: Mark circuits as RP circuits */
142  if (options->HiddenServiceStatistics) {
143  /* `circ` is the RP <-> service circuit */
145  /* `rend_circ` is the client <-> RP circuit */
146  rend_circ->circuit_carries_hs_traffic_stats = 1;
147  }
148 
149  /* Send the RENDEZVOUS2 cell to the client. */
150  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  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  return -1;
159  }
160 
161  /* Join the circuits. */
162  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 
170 
171  rend_circ->rend_splice = circ;
172  circ->rend_splice = rend_circ;
173 
174  return 0;
175  err:
176  circuit_mark_for_close(TO_CIRCUIT(circ), reason);
177  return -1;
178 }
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:2893
Header file for channel.c.
const char * circuit_purpose_to_string(uint8_t purpose)
Definition: circuitlist.c:903
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:3074
Header file for circuituse.c.
const or_options_t * get_options(void)
Definition: config.c:919
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 LD_GENERAL
Definition: log.h:62
Master header file for Tor-specific functionality.
#define REND_COOKIE_LEN
Definition: or.h:341
#define TO_CIRCUIT(x)
Definition: or.h:845
Header file for relay.c.
int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:29
int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:102
Header file for rendmid.c.
uint8_t purpose
Definition: circuit_st.h:111
channel_t * n_chan
Definition: circuit_st.h:69
unsigned int circuit_carries_hs_traffic_stats
Definition: or_circuit_st.h:64
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:50
int HiddenServiceStatistics