relay.c 51.4 KB
Newer Older
Roger Dingledine's avatar
Roger Dingledine committed
1
2
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson. */
4
5
/* See LICENSE for licensing information */
/* $Id$ */
6
7
const char relay_c_id[] =
  "$Id$";
8
9
10

/**
 * \file relay.c
11
12
 * \brief Handle relay cell encryption/decryption, plus packaging and
 * receiving from circuits.
13
14
15
16
17
18
 **/

#include "or.h"

static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
                crypt_path_t **layer_hint, char *recognized);
19
static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
20
                                       int cell_direction);
21
22
23

static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
24
                                   edge_connection_t *conn,
25
26
27
28
29
30
                                   crypt_path_t *layer_hint);
static void
circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint);
static void
circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
static int
31
circuit_resume_edge_reading_helper(edge_connection_t *conn,
32
33
34
35
                                   circuit_t *circ,
                                   crypt_path_t *layer_hint);
static int
circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
36
37
38
39

/** Stats: how many relay cells have originated at this hop, or have
 * been relayed onward (not recognized at this hop)?
 */
40
uint64_t stats_n_relay_cells_relayed = 0;
41
42
43
/** Stats: how many relay cells have been delivered to streams at this
 * hop?
 */
44
uint64_t stats_n_relay_cells_delivered = 0;
45
46
47
48

/** Update digest from the payload of cell. Assign integrity part to
 * cell.
 */
49
50
51
static void
relay_set_digest(crypto_digest_env_t *digest, cell_t *cell)
{
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  char integrity[4];
  relay_header_t rh;

  crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
  crypto_digest_get_digest(digest, integrity, 4);
//  log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.",
//    integrity[0], integrity[1], integrity[2], integrity[3]);
  relay_header_unpack(&rh, cell->payload);
  memcpy(rh.integrity, integrity, 4);
  relay_header_pack(cell->payload, &rh);
}

/** Does the digest for this circuit indicate that this cell is for us?
 *
 * Update digest from the payload of cell (with the integrity part set
 * to 0). If the integrity part is valid, return 1, else restore digest
 * and cell to their original state and return 0.
 */
70
71
72
static int
relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell)
{
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  char received_integrity[4], calculated_integrity[4];
  relay_header_t rh;
  crypto_digest_env_t *backup_digest=NULL;

  backup_digest = crypto_digest_dup(digest);

  relay_header_unpack(&rh, cell->payload);
  memcpy(received_integrity, rh.integrity, 4);
  memset(rh.integrity, 0, 4);
  relay_header_pack(cell->payload, &rh);

//  log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.",
//    received_integrity[0], received_integrity[1],
//    received_integrity[2], received_integrity[3]);

  crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
  crypto_digest_get_digest(digest, calculated_integrity, 4);

91
  if (memcmp(received_integrity, calculated_integrity, 4)) {
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//    log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing.");
// (%d vs %d).", received_integrity, calculated_integrity);
    /* restore digest to its old form */
    crypto_digest_assign(digest, backup_digest);
    /* restore the relay header */
    memcpy(rh.integrity, received_integrity, 4);
    relay_header_pack(cell->payload, &rh);
    crypto_free_digest_env(backup_digest);
    return 0;
  }
  crypto_free_digest_env(backup_digest);
  return 1;
}

/** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b>
 * (in place).
 *
 * If <b>encrypt_mode</b> is 1 then encrypt, else decrypt.
 *
 * Return -1 if the crypto fails, else return 0.
 */
113
114
115
116
static int
relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
                        int encrypt_mode)
{
117
  char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */
118
  int r;
119

120
121
122
123
124
125
  if (encrypt_mode)
    r = crypto_cipher_encrypt(cipher, out, in, CELL_PAYLOAD_SIZE);
  else
    r = crypto_cipher_decrypt(cipher, out, in, CELL_PAYLOAD_SIZE);

  if (r) {
126
    log_warn(LD_BUG,"Error during relay encryption");
127
128
129
130
131
132
133
134
135
136
    return -1;
  }
  memcpy(in,out,CELL_PAYLOAD_SIZE);
  return 0;
}

/** Receive a relay cell:
 *  - Crypt it (encrypt APward, decrypt at AP, decrypt exitward).
 *  - Check if recognized (if exitward).
 *  - If recognized and the digest checks out, then find if there's
Roger Dingledine's avatar
Roger Dingledine committed
137
 *    a conn that the cell is intended for, and deliver it to
138
139
140
 *    connection_edge.
 *  - Else connection_or_write_cell_to_buf to the conn on the other
 *    side of the circuit.
141
142
 *
 * Return -reason on failure.
143
 */
144
145
146
int
circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
{
147
  or_connection_t *or_conn=NULL;
148
149
  crypt_path_t *layer_hint=NULL;
  char recognized=0;
150
  int reason;
151

152
153
154
155
  tor_assert(cell);
  tor_assert(circ);
  tor_assert(cell_direction == CELL_DIRECTION_OUT ||
             cell_direction == CELL_DIRECTION_IN);
156
157
158
  if (circ->marked_for_close)
    return 0;

159
  if (relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) {
160
    log_warn(LD_BUG,"relay crypt failed. Dropping connection.");
161
    return -END_CIRC_REASON_INTERNAL;
162
163
  }

164
  if (recognized) {
165
    edge_connection_t *conn = relay_lookup_conn(circ, cell, cell_direction);
166
    if (cell_direction == CELL_DIRECTION_OUT) {
167
      ++stats_n_relay_cells_delivered;
168
      log_debug(LD_OR,"Sending away from origin.");
169
170
      if ((reason=connection_edge_process_relay_cell(cell, circ, conn, NULL))
          < 0) {
171
        log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
172
173
               "connection_edge_process_relay_cell (away from origin) "
               "failed.");
174
        return reason;
175
176
      }
    }
177
    if (cell_direction == CELL_DIRECTION_IN) {
178
      ++stats_n_relay_cells_delivered;
179
      log_debug(LD_OR,"Sending to origin.");
180
181
      if ((reason = connection_edge_process_relay_cell(cell, circ, conn,
                                                       layer_hint)) < 0) {
182
183
        log_warn(LD_OR,
                 "connection_edge_process_relay_cell (at origin) failed.");
184
        return reason;
185
186
187
188
189
190
      }
    }
    return 0;
  }

  /* not recognized. pass it on. */
191
  if (cell_direction == CELL_DIRECTION_OUT) {
192
    cell->circ_id = circ->n_circ_id; /* switch it */
193
    or_conn = circ->n_conn;
194
195
  } else if (! CIRCUIT_IS_ORIGIN(circ)) {
    cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */
196
    or_conn = TO_OR_CIRCUIT(circ)->p_conn;
197
  } else {
198
199
    log_fn(LOG_PROTOCOL_WARN, LD_OR,
           "Dropping unrecognized inbound cell on origin circuit.");
200
    return 0;
201
202
  }

203
  if (!or_conn) {
204
205
206
207
208
    // XXXX Can this splice stuff be done more cleanly?
    if (! CIRCUIT_IS_ORIGIN(circ) &&
        TO_OR_CIRCUIT(circ)->rend_splice &&
        cell_direction == CELL_DIRECTION_OUT) {
      or_circuit_t *splice = TO_OR_CIRCUIT(circ)->rend_splice;
209
      tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
210
211
212
      tor_assert(splice->_base.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
      cell->circ_id = splice->p_circ_id;
      if ((reason = circuit_receive_relay_cell(cell, TO_CIRCUIT(splice),
213
                                               CELL_DIRECTION_IN)) < 0) {
214
215
        log_warn(LD_REND, "Error relaying cell across rendezvous; closing "
                 "circuits");
216
        /* XXXX Do this here, or just return -1? */
217
218
        circuit_mark_for_close(circ, -reason);
        return reason;
219
220
221
      }
      return 0;
    }
222
223
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "Didn't recognize cell, but circ stops here! Closing circ.");
224
    return -END_CIRC_REASON_TORPROTOCOL;
225
226
  }

227
  log_debug(LD_OR,"Passing on unrecognized cell.");
228
  ++stats_n_relay_cells_relayed;
229
  connection_or_write_cell_to_buf(cell, or_conn);
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  return 0;
}

/** Do the appropriate en/decryptions for <b>cell</b> arriving on
 * <b>circ</b> in direction <b>cell_direction</b>.
 *
 * If cell_direction == CELL_DIRECTION_IN:
 *   - If we're at the origin (we're the OP), for hops 1..N,
 *     decrypt cell. If recognized, stop.
 *   - Else (we're not the OP), encrypt one hop. Cell is not recognized.
 *
 * If cell_direction == CELL_DIRECTION_OUT:
 *   - decrypt one hop. Check if recognized.
 *
 * If cell is recognized, set *recognized to 1, and set
 * *layer_hint to the hop that recognized it.
 *
 * Return -1 to indicate that we should mark the circuit for close,
 * else return 0.
 */
250
251
252
253
static int
relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
            crypt_path_t **layer_hint, char *recognized)
{
254
255
  relay_header_t rh;

256
257
258
259
260
  tor_assert(circ);
  tor_assert(cell);
  tor_assert(recognized);
  tor_assert(cell_direction == CELL_DIRECTION_IN ||
             cell_direction == CELL_DIRECTION_OUT);
261

262
263
  if (cell_direction == CELL_DIRECTION_IN) {
    if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit.
264
                                    * We'll want to do layered decrypts. */
265
266
      crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath;
      thishop = cpath;
267
      if (thishop->state != CPATH_STATE_OPEN) {
268
269
        log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
               "Relay cell before first created cell? Closing.");
270
271
272
273
274
        return -1;
      }
      do { /* Remember: cpath is in forward order, that is, first hop first. */
        tor_assert(thishop);

275
        if (relay_crypt_one_payload(thishop->b_crypto, cell->payload, 0) < 0)
276
277
278
          return -1;

        relay_header_unpack(&rh, cell->payload);
279
        if (rh.recognized == 0) {
280
          /* it's possibly recognized. have to check digest to be sure. */
281
          if (relay_digest_matches(thishop->b_digest, cell)) {
282
283
284
285
286
287
288
            *recognized = 1;
            *layer_hint = thishop;
            return 0;
          }
        }

        thishop = thishop->next;
289
      } while (thishop != cpath && thishop->state == CPATH_STATE_OPEN);
290
291
      log_fn(LOG_PROTOCOL_WARN, LD_OR,
             "Incoming cell at client not recognized. Closing.");
292
293
      return -1;
    } else { /* we're in the middle. Just one crypt. */
294
295
      if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto,
                                  cell->payload, 1) < 0)
296
        return -1;
297
//      log_fn(LOG_DEBUG,"Skipping recognized check, because we're not "
298
//             "the client.");
299
300
301
302
    }
  } else /* cell_direction == CELL_DIRECTION_OUT */ {
    /* we're in the middle. Just one crypt. */

303
304
    if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto,
                                cell->payload, 0) < 0)
305
306
307
308
309
      return -1;

    relay_header_unpack(&rh, cell->payload);
    if (rh.recognized == 0) {
      /* it's possibly recognized. have to check digest to be sure. */
310
      if (relay_digest_matches(TO_OR_CIRCUIT(circ)->n_digest, cell)) {
311
312
313
314
315
316
317
318
        *recognized = 1;
        return 0;
      }
    }
  }
  return 0;
}

319
/** Package a relay cell from an edge:
320
321
322
 *  - Encrypt it to the right layer
 *  - connection_or_write_cell_to_buf to the right conn
 */
323
static int
324
325
326
circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
                           int cell_direction,
                           crypt_path_t *layer_hint)
Roger Dingledine's avatar
Roger Dingledine committed
327
{
328
  or_connection_t *conn; /* where to send the cell */
329

330
  if (cell_direction == CELL_DIRECTION_OUT) {
331
    crypt_path_t *thishop; /* counter for repeated crypts */
332
    conn = circ->n_conn;
333
    if (!CIRCUIT_IS_ORIGIN(circ) || !conn) {
334
      log_warn(LD_BUG,"outgoing relay cell has n_conn==NULL. Dropping.");
335
336
337
338
339
340
341
342
      return 0; /* just drop it */
    }
    relay_set_digest(layer_hint->f_digest, cell);

    thishop = layer_hint;
    /* moving from farthest to nearest hop */
    do {
      tor_assert(thishop);
343
      /* XXXX RD This is a bug, right? */
344
      log_debug(LD_OR,"crypting a layer of the relay cell.");
345
      if (relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) {
346
347
348
349
        return -1;
      }

      thishop = thishop->prev;
350
    } while (thishop != TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
351
352

  } else { /* incoming cell */
353
354
    or_circuit_t *or_circ;
    if (CIRCUIT_IS_ORIGIN(circ)) {
355
      /* XXXX RD This is a bug, right? */
356
      log_warn(LD_BUG,"incoming relay cell at origin circuit. Dropping.");
357
      assert_circuit_ok(circ);
358
359
      return 0; /* just drop it */
    }
360
361
362
363
    or_circ = TO_OR_CIRCUIT(circ);
    conn = or_circ->p_conn;
    relay_set_digest(or_circ->p_digest, cell);
    if (relay_crypt_one_payload(or_circ->p_crypto, cell->payload, 1) < 0)
364
365
366
367
368
369
370
371
372
373
      return -1;
  }
  ++stats_n_relay_cells_relayed;
  connection_or_write_cell_to_buf(cell, conn);
  return 0;
}

/** If cell's stream_id matches the stream_id of any conn that's
 * attached to circ, return that conn, else return NULL.
 */
374
static edge_connection_t *
375
376
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
{
377
  edge_connection_t *tmpconn;
378
379
380
381
  relay_header_t rh;

  relay_header_unpack(&rh, cell->payload);

382
  if (!rh.stream_id)
383
384
385
386
387
388
    return NULL;

  /* IN or OUT cells could have come from either direction, now
   * that we allow rendezvous *to* an OP.
   */

389
390
391
  if (CIRCUIT_IS_ORIGIN(circ)) {
    for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
         tmpconn=tmpconn->next_stream) {
392
393
      if (rh.stream_id == tmpconn->stream_id &&
          !tmpconn->_base.marked_for_close) {
394
        log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
395
        return tmpconn;
396
      }
397
    }
398
399
400
  } else {
    for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
         tmpconn=tmpconn->next_stream) {
401
402
      if (rh.stream_id == tmpconn->stream_id &&
          !tmpconn->_base.marked_for_close) {
403
404
405
406
407
        log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
        if (cell_direction == CELL_DIRECTION_OUT ||
            connection_edge_is_rendezvous_stream(tmpconn))
          return tmpconn;
      }
408
    }
409
410
    for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
         tmpconn=tmpconn->next_stream) {
411
412
      if (rh.stream_id == tmpconn->stream_id &&
          !tmpconn->_base.marked_for_close) {
413
414
415
        log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
        return tmpconn;
      }
416
417
418
419
420
    }
  }
  return NULL; /* probably a begin relay cell */
}

421
422
423
424
/** Pack the relay_header_t host-order structure <b>src</b> into
 * network-order in the buffer <b>dest</b>. See tor-spec.txt for details
 * about the wire format.
 */
425
426
427
void
relay_header_pack(char *dest, const relay_header_t *src)
{
428
429
430
431
432
433
434
435
436
437
438
  *(uint8_t*)(dest) = src->command;

  set_uint16(dest+1, htons(src->recognized));
  set_uint16(dest+3, htons(src->stream_id));
  memcpy(dest+5, src->integrity, 4);
  set_uint16(dest+9, htons(src->length));
}

/** Unpack the network-order buffer <b>src</b> into a host-order
 * relay_header_t structure <b>dest</b>.
 */
439
440
441
void
relay_header_unpack(relay_header_t *dest, const char *src)
{
442
443
444
445
446
447
448
449
  dest->command = *(uint8_t*)(src);

  dest->recognized = ntohs(get_uint16(src+1));
  dest->stream_id = ntohs(get_uint16(src+3));
  memcpy(dest->integrity, src+5, 4);
  dest->length = ntohs(get_uint16(src+9));
}

450
451
452
453
454
/** Make a relay cell out of <b>relay_command</b> and <b>payload</b>, and send
 * it onto the open circuit <b>circ</b>. <b>stream_id</b> is the ID on
 * <b>circ</b> for the stream that's sending the relay cell, or 0 if it's a
 * control cell.  <b>cpath_layer</b> is NULL for OR->OP cells, or the
 * destination hop for OP->OR cells.
455
 *
456
457
 * If you can't send the cell, mark the circuit for close and return -1. Else
 * return 0.
458
 */
459
int
460
relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ,
461
462
463
                             int relay_command, const char *payload,
                             size_t payload_len, crypt_path_t *cpath_layer)
{
464
465
466
  cell_t cell;
  relay_header_t rh;
  int cell_direction;
467
  /* XXXX NM Split this function into a separate versions per circuit type? */
468

469
  tor_assert(circ);
470
471
472

  memset(&cell, 0, sizeof(cell_t));
  cell.command = CELL_RELAY;
473
  if (cpath_layer) {
474
475
    cell.circ_id = circ->n_circ_id;
    cell_direction = CELL_DIRECTION_OUT;
476
477
  } else if (! CIRCUIT_IS_ORIGIN(circ)) {
    cell.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
478
    cell_direction = CELL_DIRECTION_IN;
479
480
  } else {
    return -1;
481
482
483
484
  }

  memset(&rh, 0, sizeof(rh));
  rh.command = relay_command;
485
  rh.stream_id = stream_id;
486
487
  rh.length = payload_len;
  relay_header_pack(cell.payload, &rh);
488
489
  if (payload_len) {
    tor_assert(payload_len <= RELAY_PAYLOAD_SIZE);
490
    memcpy(cell.payload+RELAY_HEADER_SIZE, payload, payload_len);
491
  }
492

493
494
  log_debug(LD_OR,"delivering %d cell %s.", relay_command,
            cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward");
495

496
497
  if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer)
      < 0) {
498
    log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing.");
499
    circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
500
501
502
503
504
    return -1;
  }
  return 0;
}

505
506
507
508
509
510
511
512
513
514
/** Make a relay cell out of <b>relay_command</b> and <b>payload</b>, and
 * send it onto the open circuit <b>circ</b>. <b>fromconn</b> is the stream
 * that's sending the relay cell, or NULL if it's a control cell.
 * <b>cpath_layer</b> is NULL for OR->OP cells, or the destination hop
 * for OP->OR cells.
 *
 * If you can't send the cell, mark the circuit for close and
 * return -1. Else return 0.
 */
int
515
connection_edge_send_command(edge_connection_t *fromconn,
516
                             int relay_command, const char *payload,
517
                             size_t payload_len)
518
519
{
  /* XXXX NM Split this function into a separate versions per circuit type? */
520
521
522
523
524
  crypt_path_t *cpath_layer;
  circuit_t *circ;
  tor_assert(fromconn);
  cpath_layer = fromconn ? fromconn->cpath_layer : NULL;
  circ = fromconn->on_circuit;
525

526
  if (fromconn->_base.marked_for_close) {
527
    log_warn(LD_BUG,
528
             "called on conn that's already marked for close at %s:%d.",
529
530
531
532
533
534
535
536
537
538
539
540
             fromconn->_base.marked_for_close_file,
             fromconn->_base.marked_for_close);
    return 0;
  }

  if (!circ) {
    if (fromconn->_base.type == CONN_TYPE_AP) {
      log_info(LD_APP,"no circ. Closing conn.");
      connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL);
    } else {
      log_info(LD_EXIT,"no circ. Closing conn.");
      fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */
541
      fromconn->end_reason = END_STREAM_REASON_INTERNAL;
542
543
544
545
546
      connection_mark_for_close(TO_CONN(fromconn));
    }
    return -1;
  }

547
548
549
  return relay_send_command_from_edge(fromconn->stream_id, circ,
                                      relay_command, payload,
                                      payload_len, fromconn->cpath_layer);
550
551
}

552
553
554
/** Translate <b>reason</b>, which came from a relay 'end' cell,
 * into a static const string describing why the stream is closing.
 * <b>reason</b> is -1 if no reason was provided.
555
556
 */
static const char *
557
558
connection_edge_end_reason_str(int reason)
{
559
560
  switch (reason) {
    case -1:
561
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
562
             "End cell arrived with length 0. Should be at least 1.");
563
      return "MALFORMED";
564
565
    case END_STREAM_REASON_MISC:           return "misc error";
    case END_STREAM_REASON_RESOLVEFAILED:  return "resolve failed";
566
    case END_STREAM_REASON_CONNECTREFUSED: return "connection refused";
567
568
569
570
    case END_STREAM_REASON_EXITPOLICY:     return "exit policy failed";
    case END_STREAM_REASON_DESTROY:        return "destroyed";
    case END_STREAM_REASON_DONE:           return "closed normally";
    case END_STREAM_REASON_TIMEOUT:        return "gave up (timeout)";
571
572
573
574
    case END_STREAM_REASON_HIBERNATING:    return "server is hibernating";
    case END_STREAM_REASON_INTERNAL:       return "internal error at server";
    case END_STREAM_REASON_RESOURCELIMIT:  return "server out of resources";
    case END_STREAM_REASON_CONNRESET:      return "connection reset";
575
    case END_STREAM_REASON_TORPROTOCOL:    return "Tor protocol error";
576
    case END_STREAM_REASON_NOTDIRECTORY:   return "not a directory";
577
    default:
578
579
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "Reason for ending (%d) not recognized.",reason);
580
581
582
583
      return "unknown";
  }
}

584
585
/** Translate <b>reason</b> (as from a relay 'end' cell) into an
 * appropriate SOCKS5 reply code.
586
 * DODCDOC 0
587
 */
588
589
590
socks5_reply_status_t
connection_edge_end_reason_socks5_response(int reason)
{
591
  switch (reason & END_STREAM_REASON_MASK) {
592
593
    case 0:
      return SOCKS5_SUCCEEDED;
594
595
596
597
598
599
600
    case END_STREAM_REASON_MISC:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_RESOLVEFAILED:
      return SOCKS5_HOST_UNREACHABLE;
    case END_STREAM_REASON_CONNECTREFUSED:
      return SOCKS5_CONNECTION_REFUSED;
    case END_STREAM_REASON_EXITPOLICY:
601
      return SOCKS5_NOT_ALLOWED;
602
603
604
605
606
    case END_STREAM_REASON_DESTROY:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_DONE:
      return SOCKS5_SUCCEEDED;
    case END_STREAM_REASON_TIMEOUT:
607
      return SOCKS5_TTL_EXPIRED;
608
609
610
611
612
613
614
615
    case END_STREAM_REASON_RESOURCELIMIT:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_HIBERNATING:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_INTERNAL:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_CONNRESET:
      return SOCKS5_CONNECTION_REFUSED;
616
617
    case END_STREAM_REASON_TORPROTOCOL:
      return SOCKS5_GENERAL_ERROR;
618
619
620
621
622

    case END_STREAM_REASON_CANT_ATTACH:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_NET_UNREACHABLE:
      return SOCKS5_NET_UNREACHABLE;
623
624
    case END_STREAM_REASON_SOCKSPROTOCOL:
      return SOCKS5_GENERAL_ERROR;
625
    default:
626
627
628
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "Reason for ending (%d) not recognized; "
             "sending generic socks error.", reason);
629
630
631
632
      return SOCKS5_GENERAL_ERROR;
  }
}

633
634
635
636
637
/* We need to use a few macros to deal with the fact that Windows
 * decided that their sockets interface should be a permakludge.
 * E_CASE is for errors where windows has both a EFOO and a WSAEFOO
 * version, and S_CASE is for errors where windows has only a WSAEFOO
 * version.  (The E is for 'error', the S is for 'socket'). */
638
639
#ifdef MS_WINDOWS
#define E_CASE(s) case s: case WSA ## s
640
#define S_CASE(s) case WSA ## s
641
642
#else
#define E_CASE(s) case s
643
#define S_CASE(s) case s
644
645
#endif

646
647
648
/** Given an errno from a failed exit connection, return a reason code
 * appropriate for use in a RELAY END cell.
 */
649
int
650
errno_to_end_reason(int e)
651
652
{
  switch (e) {
653
    case EPIPE:
654
655
656
657
      return END_STREAM_REASON_DONE;
    E_CASE(EBADF):
    E_CASE(EFAULT):
    E_CASE(EINVAL):
658
659
660
661
    S_CASE(EISCONN):
    S_CASE(ENOTSOCK):
    S_CASE(EPROTONOSUPPORT):
    S_CASE(EAFNOSUPPORT):
662
    E_CASE(EACCES):
663
664
    S_CASE(ENOTCONN):
    S_CASE(ENETUNREACH):
665
      return END_STREAM_REASON_INTERNAL;
666
    S_CASE(ECONNREFUSED):
667
      return END_STREAM_REASON_CONNECTREFUSED;
668
    S_CASE(ECONNRESET):
669
      return END_STREAM_REASON_CONNRESET;
670
    S_CASE(ETIMEDOUT):
671
      return END_STREAM_REASON_TIMEOUT;
672
673
674
    S_CASE(ENOBUFS):
    case ENOMEM:
    case ENFILE:
675
676
677
    E_CASE(EMFILE):
      return END_STREAM_REASON_RESOURCELIMIT;
    default:
678
679
      log_info(LD_EXIT, "Didn't recognize errno %d (%s); telling the client "
               "that we are ending a stream for 'misc' reason.",
680
               e, tor_socket_strerror(e));
681
      return END_STREAM_REASON_MISC;
682
683
684
685
  }
}

/** How many times will I retry a stream that fails due to DNS
686
 * resolve failure or misc error?
687
688
689
 */
#define MAX_RESOLVE_FAILURES 3

690
691
/** Return 1 if reason is something that you should retry if you
 * get the end cell before you've connected; else return 0. */
692
static int
693
694
edge_reason_is_retriable(int reason)
{
695
696
697
  return reason == END_STREAM_REASON_HIBERNATING ||
         reason == END_STREAM_REASON_RESOURCELIMIT ||
         reason == END_STREAM_REASON_EXITPOLICY ||
698
699
         reason == END_STREAM_REASON_RESOLVEFAILED ||
         reason == END_STREAM_REASON_MISC;
700
701
}

702
703
704
/** Called when we receive an END cell on a stream that isn't open yet.
 * Arguments are as for connection_edge_process_relay_cell().
 */
705
706
static int
connection_edge_process_end_not_open(
707
    relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
708
    edge_connection_t *conn, crypt_path_t *layer_hint)
709
{
710
  struct in_addr in;
711
  routerinfo_t *exitrouter;
712
  int reason = *(cell->payload+RELAY_HEADER_SIZE);
713
  int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
714
  (void) layer_hint; /* unused */
715

716
  if (rh->length > 0 && edge_reason_is_retriable(reason) &&
717
      conn->_base.type == CONN_TYPE_AP) {
718
719
720
    log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
             safe_str(conn->socks_request->address),
             connection_edge_end_reason_str(reason));
721
722
    exitrouter =
      router_get_by_digest(circ->build_state->chosen_exit->identity_digest);
723
724
725
726
    switch (reason) {
      case END_STREAM_REASON_EXITPOLICY:
        if (rh->length >= 5) {
          uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
727
          int ttl;
728
          if (!addr) {
729
730
            log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,",
                     safe_str(conn->socks_request->address));
731
732
733
            connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
            return 0;
          }
734
735
736
737
          if (rh->length >= 9)
            ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
          else
            ttl = -1;
738
          client_dns_set_addressmap(conn->socks_request->address, addr,
739
                                    conn->chosen_exit_name, ttl);
740
741
        }
        /* check if he *ought* to have allowed it */
742
743
        if (exitrouter &&
            (rh->length < 5 ||
744
             (tor_inet_aton(conn->socks_request->address, &in) &&
745
              !conn->chosen_exit_name))) {
746
          log_notice(LD_APP,
747
748
749
                 "Exitrouter '%s' seems to be more restrictive than its exit "
                 "policy. Not using this router as exit for now.",
                 exitrouter->nickname);
750
751
          addr_policy_free(exitrouter->exit_policy);
          exitrouter->exit_policy =
752
            router_parse_addr_policy_from_string("reject *:*", -1);
753
        }
754
        /* rewrite it to an IP if we learned one. */
755
756
757
758
        if (addressmap_rewrite(conn->socks_request->address,
                               sizeof(conn->socks_request->address))) {
          control_event_stream_status(conn, STREAM_EVENT_REMAP, 0);
        }
759
760
761
        if (conn->_base.chosen_exit_optional) {
          /* stop wanting a specific exit */
          conn->_base.chosen_exit_optional = 0;
762
          tor_free(conn->chosen_exit_name); /* clears it */
763
        }
764
        if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)
765
766
767
          return 0;
        /* else, conn will get closed below */
        break;
768
      case END_STREAM_REASON_CONNECTREFUSED:
769
        if (!conn->_base.chosen_exit_optional)
770
771
772
          break; /* break means it'll close, below */
        /* Else fall through: expire this circuit, clear the
         * chosen_exit_name field, and try again. */
773
      case END_STREAM_REASON_RESOLVEFAILED:
774
      case END_STREAM_REASON_TIMEOUT:
775
      case END_STREAM_REASON_MISC:
776
777
778
        if (client_dns_incr_failures(conn->socks_request->address)
            < MAX_RESOLVE_FAILURES) {
          /* We haven't retried too many times; reattach the connection. */
779
          circuit_log_path(LOG_INFO,LD_APP,circ);
780
781
          tor_assert(circ->_base.timestamp_dirty);
          circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
782

783
784
785
          if (conn->_base.chosen_exit_optional) {
            /* stop wanting a specific exit */
            conn->_base.chosen_exit_optional = 0;
786
            tor_free(conn->chosen_exit_name); /* clears it */
787
          }
788
          if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)
789
790
791
            return 0;
          /* else, conn will get closed below */
        } else {
792
793
794
795
796
          log_notice(LD_APP,
                     "Have tried resolving or connecting to address '%s' "
                     "at %d different places. Giving up.",
                     safe_str(conn->socks_request->address),
                     MAX_RESOLVE_FAILURES);
797
798
          /* clear the failures, so it will have a full try next time */
          client_dns_clear_failures(conn->socks_request->address);
799
800
801
802
        }
        break;
      case END_STREAM_REASON_HIBERNATING:
      case END_STREAM_REASON_RESOURCELIMIT:
803
804
805
        if (exitrouter) {
          addr_policy_free(exitrouter->exit_policy);
          exitrouter->exit_policy =
806
            router_parse_addr_policy_from_string("reject *:*", -1);
807
        }
808
809
810
        if (conn->_base.chosen_exit_optional) {
          /* stop wanting a specific exit */
          conn->_base.chosen_exit_optional = 0;
811
          tor_free(conn->chosen_exit_name); /* clears it */
812
        }
813
        if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)
814
          return 0;
815
816
817
        /* else, will close below */
        break;
    } /* end switch */
818
    log_info(LD_APP,"Giving up on retrying; conn can't be handled.");
819
  }
820

821
822
  log_info(LD_APP,
           "Edge got end (%s) before we're connected. Marking for close.",
823
       connection_edge_end_reason_str(rh->length > 0 ? reason : -1));
824
  if (conn->_base.type == CONN_TYPE_AP) {
825
    circuit_log_path(LOG_INFO,LD_APP,circ);
826
    connection_mark_unattached_ap(conn, control_reason);
827
  } else {
828
829
    /* we just got an 'end', don't need to send one */
    conn->_base.edge_has_sent_end = 1;
830
    conn->end_reason = control_reason;
831
    connection_mark_for_close(TO_CONN(conn));
832
  }
833
834
835
  return 0;
}

836
837
838
/** Helper: change the socks_request-&gt;address field on conn to the
 * dotted-quad representation of <b>new_addr</b> (given in host order),
 * and send an appropriate REMAP event. */
839
840
841
842
843
844
845
846
847
848
849
850
static void
remap_event_helper(edge_connection_t *conn, uint32_t new_addr)
{
  struct in_addr in;

  in.s_addr = htonl(new_addr);
  tor_inet_ntoa(&in, conn->socks_request->address,
                sizeof(conn->socks_request->address));
  control_event_stream_status(conn, STREAM_EVENT_REMAP,
                              REMAP_STREAM_SOURCE_EXIT);
}

851
852
853
854
855
856
857
858
859
860
/** An incoming relay cell has arrived from circuit <b>circ</b> to
 * stream <b>conn</b>.
 *
 * The arguments here are the same as in
 * connection_edge_process_relay_cell() below; this function is called
 * from there when <b>conn</b> is defined and not in an open state.
 */
static int
connection_edge_process_relay_cell_not_open(
    relay_header_t *rh, cell_t *cell, circuit_t *circ,
861
    edge_connection_t *conn, crypt_path_t *layer_hint)
862
{
863
864
865
866
867
868
869
870
  if (rh->command == RELAY_COMMAND_END) {
    if (CIRCUIT_IS_ORIGIN(circ))
      return connection_edge_process_end_not_open(rh, cell,
                                                 TO_ORIGIN_CIRCUIT(circ), conn,
                                                 layer_hint);
    else
      return 0;
  }
871

872
873
  if (conn->_base.type == CONN_TYPE_AP &&
      rh->command == RELAY_COMMAND_CONNECTED) {
874
    tor_assert(CIRCUIT_IS_ORIGIN(circ));
875
    if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
876
877
      log_fn(LOG_PROTOCOL_WARN, LD_APP,
             "Got 'connected' while not in state connect_wait. Dropping.");
878
879
      return 0;
    }
880
    conn->_base.state = AP_CONN_STATE_OPEN;
881
    log_info(LD_APP,"'connected' received after %d seconds.",
882
             (int)(time(NULL) - conn->_base.timestamp_lastread));
883
    if (rh->length >= 4) {
884
      uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
885
      int ttl;
886
      if (!addr) {
887
888
        log_info(LD_APP,
                 "...but it claims the IP address was 0.0.0.0. Closing.");
889
        connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
890
        connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
891
892
        return 0;
      }
893
      if (rh->length >= 8)
894
        ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
895
896
      else
        ttl = -1;
897
      client_dns_set_addressmap(conn->socks_request->address, addr,
898
                                conn->chosen_exit_name, ttl);
899
900

      remap_event_helper(conn, addr);
901
    }
902
    circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
903
904
    /* don't send a socks reply to transparent conns */
    if (!conn->socks_request->has_finished)
905
      connection_ap_handshake_socks_reply(conn, NULL, 0, 0);
906
    /* handle anything that might have queued */
907
    if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
908
      /* (We already sent an end cell if possible) */
909
      connection_mark_for_close(TO_CONN(conn));
910
911
912
913
      return 0;
    }
    return 0;
  }
914
915
  if (conn->_base.type == CONN_TYPE_AP &&
      rh->command == RELAY_COMMAND_RESOLVED) {
916
917
    int ttl;
    int answer_len;
918
    uint8_t answer_type;
919
    if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
920
921
      log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while "
             "not in state resolve_wait. Dropping.");
922
923
      return 0;
    }
924
    tor_assert(SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command));
925
926
    answer_len = cell->payload[RELAY_HEADER_SIZE+1];
    if (rh->length < 2 || answer_len+2>rh->length) {
927
928
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "Dropping malformed 'resolved' cell");
929
      connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
930
931
      return 0;
    }
932
    if (rh->length >= answer_len+6)
933
934
      ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+
                                  2+answer_len));
935
936
    else
      ttl = -1;
937
938

    answer_type = cell->payload[RELAY_HEADER_SIZE];
939
    connection_ap_handshake_socks_resolved(conn,
940
                   answer_type,
Roger Dingledine's avatar
Roger Dingledine committed
941
                   cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
942
943
                   cell->payload+RELAY_HEADER_SIZE+2, /*answer*/
                   ttl);
944
945
946
947
    if (answer_type == RESOLVED_TYPE_IPV4) {
      uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
      remap_event_helper(conn, addr);
    }
948
    connection_mark_unattached_ap(conn,
949
950
                              END_STREAM_REASON_DONE |
                              END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
951
952
    return 0;
  }
953

954
  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
955
         "Got an unexpected relay command %d, in state %d (%s). Dropping.",
956
957
         rh->command, conn->_base.state,
         conn_state_to_string(conn->_base.type, conn->_base.state));
958
  return 0; /* for forward compatibility, don't kill the circuit */
959
//  connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
960
961
//  connection_mark_for_close(conn);
//  return -1;
962
963
964
965
966
967
968
969
970
}

/** An incoming relay cell has arrived on circuit <b>circ</b>. If
 * <b>conn</b> is NULL this is a control cell, else <b>cell</b> is
 * destined for <b>conn</b>.
 *
 * If <b>layer_hint</b> is defined, then we're the origin of the
 * circuit, and it specifies the hop that packaged <b>cell</b>.
 *
971
 * Return -reason if you want to warn and tear down the circuit, else 0.
972
973
974
 */
static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
975
                                   edge_connection_t *conn,
976
977
978
979
                                   crypt_path_t *layer_hint)
{
  static int num_seen=0;
  relay_header_t rh;
980
  unsigned domain = layer_hint?LD_APP:LD_EXIT;
981
  int reason;
982

983
984
  tor_assert(cell);
  tor_assert(circ);
985
986
987
988

  relay_header_unpack(&rh, cell->payload);
//  log_fn(LOG_DEBUG,"command %d stream %d", rh.command, rh.stream_id);
  num_seen++;
989
  log_debug(domain, "Now seen %d relay cells here.", num_seen);
990

991
  if (rh.length > RELAY_PAYLOAD_SIZE) {
992
993
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "Relay cell length field too long. Closing circuit.");
994
    return - END_CIRC_REASON_TORPROTOCOL;
995
996
  }

997
998
999
  /* either conn is NULL, in which case we've got a control cell, or else
   * conn points to the recognized stream. */

1000
  if (conn && !connection_state_is_open(TO_CONN(conn)))