tor  0.4.2.1-alpha-dev
rendmid.c
Go to the documentation of this file.
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2  * Copyright (c) 2007-2019, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
4 
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"
19 #include "feature/stats/rephist.h"
21 #include "feature/hs/hs_dos.h"
23 
24 #include "core/or/or_circuit_st.h"
25 
29 int
30 rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
31  size_t request_len)
32 {
33  crypto_pk_t *pk = NULL;
34  char buf[DIGEST_LEN+9];
35  char expected_digest[DIGEST_LEN];
36  char pk_digest[DIGEST_LEN];
37  size_t asn1len;
38  or_circuit_t *c;
39  char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
40  int reason = END_CIRC_REASON_INTERNAL;
41 
42  log_info(LD_REND,
43  "Received a legacy ESTABLISH_INTRO request on circuit %u",
44  (unsigned) circ->p_circ_id);
45 
46  if (!hs_intro_circuit_is_suitable_for_establish_intro(circ)) {
47  reason = END_CIRC_REASON_TORPROTOCOL;
48  goto err;
49  }
50 
51  if (request_len < 2+DIGEST_LEN)
52  goto truncated;
53  /* First 2 bytes: length of asn1-encoded key. */
54  asn1len = ntohs(get_uint16(request));
55 
56  /* Next asn1len bytes: asn1-encoded key. */
57  if (request_len < 2+DIGEST_LEN+asn1len)
58  goto truncated;
59  pk = crypto_pk_asn1_decode((char*)(request+2), asn1len);
60  if (!pk) {
61  reason = END_CIRC_REASON_TORPROTOCOL;
62  log_warn(LD_PROTOCOL, "Couldn't decode public key.");
63  goto err;
64  }
65 
66  /* Next 20 bytes: Hash of rend_circ_nonce | "INTRODUCE" */
67  memcpy(buf, circ->rend_circ_nonce, DIGEST_LEN);
68  memcpy(buf+DIGEST_LEN, "INTRODUCE", 9);
69  if (crypto_digest(expected_digest, buf, DIGEST_LEN+9) < 0) {
70  log_warn(LD_BUG, "Internal error computing digest.");
71  goto err;
72  }
73  if (tor_memneq(expected_digest, request+2+asn1len, DIGEST_LEN)) {
74  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
75  "Hash of session info was not as expected.");
76  reason = END_CIRC_REASON_TORPROTOCOL;
77  goto err;
78  }
79  /* Rest of body: signature of previous data */
80  if (crypto_pk_public_checksig_digest(pk,
81  (char*)request, 2+asn1len+DIGEST_LEN,
82  (char*)(request+2+DIGEST_LEN+asn1len),
83  request_len-(2+DIGEST_LEN+asn1len))<0) {
84  log_warn(LD_PROTOCOL,
85  "Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
86  reason = END_CIRC_REASON_TORPROTOCOL;
87  goto err;
88  }
89 
90  /* The request is valid. First, compute the hash of the service's PK.*/
91  if (crypto_pk_get_digest(pk, pk_digest)<0) {
92  log_warn(LD_BUG, "Internal error: couldn't hash public key.");
93  goto err;
94  }
95 
96  crypto_pk_free(pk); /* don't need it anymore */
97  pk = NULL; /* so we don't free it again if err */
98 
100  pk_digest, REND_SERVICE_ID_LEN);
101 
102  /* Close any other intro circuits with the same pk. */
103  c = NULL;
104  while ((c = hs_circuitmap_get_intro_circ_v2_relay_side(
105  (const uint8_t *)pk_digest))) {
106  log_info(LD_REND, "Replacing old circuit for service %s",
107  safe_str(serviceid));
108  circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
109  /* Now it's marked, and it won't be returned next time. */
110  }
111 
112  /* Acknowledge the request. */
113  if (hs_intro_send_intro_established_cell(circ) < 0) {
114  log_info(LD_GENERAL, "Couldn't send INTRO_ESTABLISHED cell.");
115  goto err_no_close;
116  }
117 
118  /* Now, set up this circuit. */
120  hs_circuitmap_register_intro_circ_v2_relay_side(circ, (uint8_t *)pk_digest);
121  hs_dos_setup_default_intro2_defenses(circ);
122 
123  log_info(LD_REND,
124  "Established introduction point on circuit %u for service %s",
125  (unsigned) circ->p_circ_id, safe_str(serviceid));
126 
127  return 0;
128  truncated:
129  log_warn(LD_PROTOCOL, "Rejecting truncated ESTABLISH_INTRO cell.");
130  reason = END_CIRC_REASON_TORPROTOCOL;
131  err:
132  circuit_mark_for_close(TO_CIRCUIT(circ), reason);
133  err_no_close:
134  if (pk) crypto_pk_free(pk);
135  return -1;
136 }
137 
142 int
143 rend_mid_introduce_legacy(or_circuit_t *circ, const uint8_t *request,
144  size_t request_len)
145 {
146  or_circuit_t *intro_circ;
147  char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
148  char nak_body[1];
149 
150  log_info(LD_REND, "Received an INTRODUCE1 request on circuit %u",
151  (unsigned)circ->p_circ_id);
152 
153  /* At this point, we know that the circuit is valid for an INTRODUCE1
154  * because the validation has been made before calling this function. */
155  tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_OR);
156  tor_assert(!circ->base_.n_chan);
157 
158  /* We could change this to MAX_HEX_NICKNAME_LEN now that 0.0.9.x is
159  * obsolete; however, there isn't much reason to do so, and we're going
160  * to revise this protocol anyway.
161  */
162  if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
165  log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %u; "
166  "responding with nack.",
167  (unsigned)circ->p_circ_id);
168  goto err;
169  }
170 
172  (char*)request, REND_SERVICE_ID_LEN);
173 
174  /* The first 20 bytes are all we look at: they have a hash of the service's
175  * PK. */
176  intro_circ = hs_circuitmap_get_intro_circ_v2_relay_side(
177  (const uint8_t*)request);
178  if (!intro_circ) {
179  log_info(LD_REND,
180  "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; "
181  "responding with nack.",
182  safe_str(serviceid), (unsigned)circ->p_circ_id);
183  goto err;
184  }
185 
186  /* Before sending, lets make sure this cell can be sent on the service
187  * circuit asking the DoS defenses. */
188  if (!hs_dos_can_send_intro2(intro_circ)) {
189  log_info(LD_PROTOCOL, "Can't relay INTRODUCE1 v2 cell due to DoS "
190  "limitations. Sending NACK to client.");
191  goto err;
192  }
193 
194  log_info(LD_REND,
195  "Sending introduction request for service %s "
196  "from circ %u to circ %u",
197  safe_str(serviceid), (unsigned)circ->p_circ_id,
198  (unsigned)intro_circ->p_circ_id);
199 
200  /* Great. Now we just relay the cell down the circuit. */
201  if (relay_send_command_from_edge(0, TO_CIRCUIT(intro_circ),
202  RELAY_COMMAND_INTRODUCE2,
203  (char*)request, request_len, NULL)) {
204  log_warn(LD_GENERAL,
205  "Unable to send INTRODUCE2 cell to Tor client.");
206  /* Stop right now, the circuit has been closed. */
207  return -1;
208  }
209  /* And send an ack down the client's circuit. Empty body means succeeded. */
210  if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
211  RELAY_COMMAND_INTRODUCE_ACK,
212  NULL,0,NULL)) {
213  log_warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client.");
214  /* Stop right now, the circuit has been closed. */
215  return -1;
216  }
217 
218  return 0;
219  err:
220  /* Send the client a NACK */
221  nak_body[0] = 1;
222  if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
223  RELAY_COMMAND_INTRODUCE_ACK,
224  nak_body, 1, NULL)) {
225  log_warn(LD_GENERAL, "Unable to send NAK to Tor client.");
226  }
227  return -1;
228 }
229 
233 int
234 rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
235  size_t request_len)
236 {
237  char hexid[9];
238  int reason = END_CIRC_REASON_TORPROTOCOL;
239 
240  log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u",
241  (unsigned)circ->p_circ_id);
242 
243  if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) {
244  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
245  "Tried to establish rendezvous on non-OR circuit with purpose %s",
246  circuit_purpose_to_string(circ->base_.purpose));
247  goto err;
248  }
249 
250  /* Check if we are configured to defend ourselves from clients that
251  * attempt to establish rendezvous points directly to us. */
252  if (channel_is_client(circ->p_chan) &&
253  dos_should_refuse_single_hop_client()) {
254  /* Note it down for the heartbeat log purposes. */
255  dos_note_refuse_single_hop_client();
256  /* Silent drop so the client has to time out before moving on. */
257  return 0;
258  }
259 
260  if (circ->base_.n_chan) {
261  log_warn(LD_PROTOCOL,
262  "Tried to establish rendezvous on non-edge circuit");
263  goto err;
264  }
265 
266  if (request_len != REND_COOKIE_LEN) {
267  log_fn(LOG_PROTOCOL_WARN,
268  LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS.");
269  goto err;
270  }
271 
272  if (hs_circuitmap_get_rend_circ_relay_side(request)) {
273  log_warn(LD_PROTOCOL,
274  "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
275  goto err;
276  }
277 
278  /* Acknowledge the request. */
279  if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
280  RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
281  "", 0, NULL)<0) {
282  log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
283  /* Stop right now, the circuit has been closed. */
284  return -1;
285  }
286 
289 
290  base16_encode(hexid,9,(char*)request,4);
291 
292  log_info(LD_REND,
293  "Established rendezvous point on circuit %u for cookie %s",
294  (unsigned)circ->p_circ_id, hexid);
295 
296  return 0;
297  err:
298  circuit_mark_for_close(TO_CIRCUIT(circ), reason);
299  return -1;
300 }
301 
306 int
307 rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
308  size_t request_len)
309 {
310  const or_options_t *options = get_options();
311  or_circuit_t *rend_circ;
312  char hexid[9];
313  int reason = END_CIRC_REASON_INTERNAL;
314 
315  if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
316  log_info(LD_REND,
317  "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
318  (unsigned)circ->p_circ_id);
319  reason = END_CIRC_REASON_TORPROTOCOL;
320  goto err;
321  }
322 
323  if (request_len < REND_COOKIE_LEN) {
324  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
325  "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.",
326  (int)request_len, (unsigned)circ->p_circ_id);
327  reason = END_CIRC_REASON_TORPROTOCOL;
328  goto err;
329  }
330 
331  base16_encode(hexid, sizeof(hexid), (const char*)request, 4);
332 
333  log_info(LD_REND,
334  "Got request for rendezvous from circuit %u to cookie %s.",
335  (unsigned)circ->p_circ_id, hexid);
336 
337  rend_circ = hs_circuitmap_get_rend_circ_relay_side(request);
338  if (!rend_circ) {
339  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
340  "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
341  hexid);
342  reason = END_CIRC_REASON_TORPROTOCOL;
343  goto err;
344  }
345 
346  /* Statistics: Mark this circuit as an RP circuit so that we collect
347  stats from it. */
348  if (options->HiddenServiceStatistics) {
350  }
351 
352  /* Send the RENDEZVOUS2 cell to the client. */
353  if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ),
354  RELAY_COMMAND_RENDEZVOUS2,
355  (char*)(request+REND_COOKIE_LEN),
356  request_len-REND_COOKIE_LEN, NULL)) {
357  log_warn(LD_GENERAL,
358  "Unable to send RENDEZVOUS2 cell to client on circuit %u.",
359  (unsigned)rend_circ->p_circ_id);
360  /* Stop right now, the circuit has been closed. */
361  return -1;
362  }
363 
364  /* Join the circuits. */
365  log_info(LD_REND,
366  "Completing rendezvous: circuit %u joins circuit %u (cookie %s)",
367  (unsigned)circ->p_circ_id, (unsigned)rend_circ->p_circ_id, hexid);
368 
373 
374  rend_circ->rend_splice = circ;
375  circ->rend_splice = rend_circ;
376 
377  return 0;
378  err:
379  circuit_mark_for_close(TO_CIRCUIT(circ), reason);
380  return -1;
381 }
Header file containing denial of service defenses for the HS subsystem for all versions.
int channel_is_client(const channel_t *chan)
Definition: channel.c:2924
int rend_mid_introduce_legacy(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:143
Headers for crypto_cipher.c.
struct or_circuit_t * rend_splice
Definition: or_circuit_st.h:50
#define LD_GENERAL
Definition: log.h:60
#define CIRCUIT_PURPOSE_REND_POINT_WAITING
Definition: circuitlist.h:44
const char * circuit_purpose_to_string(uint8_t purpose)
Definition: circuitlist.c:898
#define REND_SERVICE_ID_LEN
Definition: or.h:337
#define MAX_NICKNAME_LEN
Definition: or.h:113
int HiddenServiceStatistics
#define TO_CIRCUIT(x)
Definition: or.h:951
Header file for config.c.
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:60
#define CIPHER_KEY_LEN
Definition: crypto_cipher.h:22
#define CIRCUIT_PURPOSE_REND_ESTABLISHED
Definition: circuitlist.h:46
uint8_t purpose
Definition: circuit_st.h:100
char rend_circ_nonce[DIGEST_LEN]
Definition: or_circuit_st.h:53
int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:234
Header file for rendmid.c.
channel_t * p_chan
Definition: or_circuit_st.h:37
crypto_pk_t * crypto_pk_asn1_decode(const char *str, size_t len)
Header file for channel.c.
tor_assert(buffer)
void hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ, const uint8_t *cookie)
#define DIGEST_LEN
Definition: digest_sizes.h:20
Master header file for Tor-specific functionality.
unsigned int circuit_carries_hs_traffic_stats
Definition: or_circuit_st.h:64
Header file for rephist.c.
static uint16_t get_uint16(const void *cp)
Definition: bytes.h:37
#define PKCS1_OAEP_PADDING_OVERHEAD
Definition: crypto_rsa.h:30
Header file for circuituse.c.
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:478
Header file for hs_intropoint.c.
circid_t p_circ_id
Definition: or_circuit_st.h:33
Header file for hs_circuitmap.c.
#define LD_REND
Definition: log.h:82
Header file for circuitlist.c.
void hs_circuitmap_remove_circuit(circuit_t *circ)
#define DH1024_KEY_LEN
Definition: dh_sizes.h:20
#define REND_SERVICE_ID_LEN_BASE32
Definition: or.h:331
int crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
Definition: crypto_rsa.c:356
#define CIRCUIT_PURPOSE_INTRO_POINT
Definition: circuitlist.h:41
Header file for relay.c.
#define CIRCUIT_PURPOSE_OR
Definition: circuitlist.h:38
#define log_fn(severity, domain, args,...)
Definition: log.h:274
int rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:30
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Definition: circuituse.c:3061
#define REND_COOKIE_LEN
Definition: or.h:399
int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len)
Definition: rendmid.c:307
#define LD_PROTOCOL
Definition: log.h:70
#define LD_BUG
Definition: log.h:84
channel_t * n_chan
Definition: circuit_st.h:58