circuit.c 30.4 KB
Newer Older
1
2
3
/* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
/* See LICENSE for licensing information */
/* $Id$ */
Roger Dingledine's avatar
Roger Dingledine committed
4
5
6

#include "or.h"

7
8
extern or_options_t options; /* command-line and config-file options */

Roger Dingledine's avatar
Roger Dingledine committed
9
10
11
12
static void circuit_free_cpath(crypt_path_t *cpath);
static void circuit_free_cpath_node(crypt_path_t *victim);
static aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type);  

13
14
15
unsigned long stats_n_relay_cells_relayed = 0;
unsigned long stats_n_relay_cells_delivered = 0;

Roger Dingledine's avatar
Roger Dingledine committed
16
17
/********* START VARIABLES **********/

Roger Dingledine's avatar
Roger Dingledine committed
18
static circuit_t *global_circuitlist=NULL;
Roger Dingledine's avatar
Roger Dingledine committed
19

20
21
char *circuit_state_to_string[] = {
  "receiving the onion",    /* 0 */
22
23
24
  "waiting to process create", /* 1 */
  "connecting to firsthop", /* 2 */
  "open"                    /* 3 */
25
26
};

Roger Dingledine's avatar
Roger Dingledine committed
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/********* END VARIABLES ************/

void circuit_add(circuit_t *circ) {

  if(!global_circuitlist) { /* first one */
    global_circuitlist = circ;
    circ->next = NULL;
  } else {
    circ->next = global_circuitlist;
    global_circuitlist = circ;
  }

}

void circuit_remove(circuit_t *circ) {
  circuit_t *tmpcirc;

Roger Dingledine's avatar
Roger Dingledine committed
44
  assert(circ && global_circuitlist);
Roger Dingledine's avatar
Roger Dingledine committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

  if(global_circuitlist == circ) {
    global_circuitlist = global_circuitlist->next;
    return;
  }

  for(tmpcirc = global_circuitlist;tmpcirc->next;tmpcirc = tmpcirc->next) {
    if(tmpcirc->next == circ) {
      tmpcirc->next = circ->next;
      return;
    }
  }
}

circuit_t *circuit_new(aci_t p_aci, connection_t *p_conn) {
  circuit_t *circ; 

62
  circ = (circuit_t *)tor_malloc(sizeof(circuit_t));
Roger Dingledine's avatar
Roger Dingledine committed
63
64
  memset(circ,0,sizeof(circuit_t)); /* zero it out */

65
  circ->timestamp_created = time(NULL);
66

Roger Dingledine's avatar
Roger Dingledine committed
67
68
69
  circ->p_aci = p_aci;
  circ->p_conn = p_conn;

70
  circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
Roger Dingledine's avatar
Roger Dingledine committed
71
72
73

  /* ACIs */
  circ->p_aci = p_aci;
Roger Dingledine's avatar
Roger Dingledine committed
74
  /* circ->n_aci remains 0 because we haven't identified the next hop yet */
Roger Dingledine's avatar
Roger Dingledine committed
75

76
77
  circ->package_window = CIRCWINDOW_START;
  circ->deliver_window = CIRCWINDOW_START;
78

Roger Dingledine's avatar
Roger Dingledine committed
79
80
81
82
83
84
  circuit_add(circ);

  return circ;
}

void circuit_free(circuit_t *circ) {
85
86
87
88
  if (circ->n_crypto)
    crypto_free_cipher_env(circ->n_crypto);
  if (circ->p_crypto)
    crypto_free_cipher_env(circ->p_crypto);
89
  circuit_free_cpath(circ->cpath);
Roger Dingledine's avatar
Roger Dingledine committed
90
  free(circ);
91
92
}

Roger Dingledine's avatar
Roger Dingledine committed
93
static void circuit_free_cpath(crypt_path_t *cpath) {
94
  crypt_path_t *victim, *head=cpath;
95

96
97
98
99
100
101
102
103
104
105
106
107
108
  if(!cpath)
    return;

  /* it's a doubly linked list, so we have to notice when we've
   * gone through it once. */
  while(cpath->next && cpath->next != head) {
    victim = cpath;
    cpath = victim->next;
    circuit_free_cpath_node(victim);
  }

  circuit_free_cpath_node(cpath);
}
Roger Dingledine's avatar
Roger Dingledine committed
109

Roger Dingledine's avatar
Roger Dingledine committed
110
static void circuit_free_cpath_node(crypt_path_t *victim) {
111
112
113
114
  if(victim->f_crypto)
    crypto_free_cipher_env(victim->f_crypto);
  if(victim->b_crypto)
    crypto_free_cipher_env(victim->b_crypto);
115
116
  if(victim->handshake_state)
    crypto_dh_free(victim->handshake_state);
117
  free(victim);
Roger Dingledine's avatar
Roger Dingledine committed
118
119
}

Roger Dingledine's avatar
Roger Dingledine committed
120
/* return 0 if can't get a unique aci. */
Roger Dingledine's avatar
Roger Dingledine committed
121
static aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type) {
Roger Dingledine's avatar
Roger Dingledine committed
122
123
  aci_t test_aci;
  connection_t *conn;
124
  uint16_t high_bit;
125

126
  high_bit = (aci_type == ACI_TYPE_HIGHER) ? 1<<15 : 0;
127
  conn = connection_exact_get_by_addr_port(addr,port);
128
  /* XXX race condition: if conn is marked_for_close it won't be noticed */
129
  if (!conn)
Roger Dingledine's avatar
Roger Dingledine committed
130
    return (1|high_bit); /* No connection exists; conflict is impossible. */
131

132
  do {
133
134
    /* Sequentially iterate over test_aci=1...1<<15-1 until we find an
     * aci such that (high_bit|test_aci) is not already used. */
Roger Dingledine's avatar
Roger Dingledine committed
135
136
    /* XXX Will loop forever if all aci's in our range are used.
     * This matters because it's an external DoS vulnerability. */
137
138
139
140
141
142
    test_aci = conn->next_aci++;
    if (test_aci == 0 || test_aci >= 1<<15) {
      test_aci = 1;
      conn->next_aci = 2;
    }
    test_aci |= high_bit;
143
  } while(circuit_get_by_aci_conn(test_aci, conn));
Roger Dingledine's avatar
Roger Dingledine committed
144
145
146
  return test_aci;
}

147
circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *circ, uint32_t naddr, uint16_t nport) {
148

149
150
151
152
153
  if(!circ) /* use circ if it's defined, else start from the beginning */
    circ = global_circuitlist; 
  else
    circ = circ->next;

154
  for( ; circ; circ = circ->next) {
155
156
157
158
159
160
    if(circ->n_addr == naddr && circ->n_port == nport)
       return circ;
  }
  return NULL;
}

Roger Dingledine's avatar
Roger Dingledine committed
161
162
circuit_t *circuit_get_by_aci_conn(aci_t aci, connection_t *conn) {
  circuit_t *circ;
163
  connection_t *tmpconn;
Roger Dingledine's avatar
Roger Dingledine committed
164
165

  for(circ=global_circuitlist;circ;circ = circ->next) {
166
    if(circ->p_aci == aci) {
167
168
169
      if(circ->p_conn == conn)
        return circ;
      for(tmpconn = circ->p_streams; tmpconn; tmpconn = tmpconn->next_stream) {
170
171
172
173
174
        if(tmpconn == conn)
          return circ;
      }
    }
    if(circ->n_aci == aci) {
175
176
177
      if(circ->n_conn == conn)
        return circ;
      for(tmpconn = circ->n_streams; tmpconn; tmpconn = tmpconn->next_stream) {
178
179
180
181
        if(tmpconn == conn)
          return circ;
      }
    }
Roger Dingledine's avatar
Roger Dingledine committed
182
183
184
185
186
187
  }
  return NULL;
}

circuit_t *circuit_get_by_conn(connection_t *conn) {
  circuit_t *circ;
188
  connection_t *tmpconn;
Roger Dingledine's avatar
Roger Dingledine committed
189
190

  for(circ=global_circuitlist;circ;circ = circ->next) {
191
192
193
194
195
    if(circ->p_conn == conn)
      return circ;
    if(circ->n_conn == conn)
      return circ;
    for(tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream)
196
197
      if(tmpconn == conn)
        return circ;
198
    for(tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream)
199
200
      if(tmpconn == conn)
        return circ;
Roger Dingledine's avatar
Roger Dingledine committed
201
202
203
204
  }
  return NULL;
}

Roger Dingledine's avatar
Roger Dingledine committed
205
circuit_t *circuit_get_newest_open(void) {
206
  circuit_t *circ, *bestcirc=NULL;
207
208

  for(circ=global_circuitlist;circ;circ = circ->next) {
Roger Dingledine's avatar
Roger Dingledine committed
209
    if(circ->cpath && circ->state == CIRCUIT_STATE_OPEN && circ->n_conn && (!bestcirc ||
210
      bestcirc->timestamp_created < circ->timestamp_created)) {
Roger Dingledine's avatar
Roger Dingledine committed
211
      log_fn(LOG_DEBUG,"Choosing circuit %s:%d:%d.", circ->n_conn->address, circ->n_port, circ->n_aci);
212
213
      assert(circ->n_aci);
      bestcirc = circ;
214
215
    }
  }
216
  return bestcirc;
217
218
}

219
220
221
222
223
int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ,
                               int cell_direction, crypt_path_t *layer_hint) {
  connection_t *conn=NULL;
  char recognized=0;
  char buf[256];
224
225
226
227

  assert(cell && circ);
  assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN); 

228
229
  buf[0] = cell->length;
  memcpy(buf+1, cell->payload, CELL_PAYLOAD_SIZE);
Roger Dingledine's avatar
Roger Dingledine committed
230

231
  log_fn(LOG_DEBUG,"direction %d, streamid %d before crypt.", cell_direction, *(int*)(cell->payload+1));
232

233
  if(relay_crypt(circ, buf, 1+CELL_PAYLOAD_SIZE, cell_direction, &layer_hint, &recognized, &conn) < 0) {
234
    log_fn(LOG_WARNING,"relay crypt failed. Dropping connection.");
Roger Dingledine's avatar
Roger Dingledine committed
235
236
237
    return -1;
  }

238
239
240
241
242
  cell->length = buf[0];
  memcpy(cell->payload, buf+1, CELL_PAYLOAD_SIZE);

  if(recognized) {
    if(cell_direction == CELL_DIRECTION_OUT) {
243
      ++stats_n_relay_cells_delivered;
244
      log_fn(LOG_DEBUG,"Sending to exit.");
245
      return connection_edge_process_relay_cell(cell, circ, conn, EDGE_EXIT, NULL);
246
247
    }
    if(cell_direction == CELL_DIRECTION_IN) {
248
      ++stats_n_relay_cells_delivered;
249
      log_fn(LOG_DEBUG,"Sending to AP.");
250
      return connection_edge_process_relay_cell(cell, circ, conn, EDGE_AP, layer_hint);
251
    }
Roger Dingledine's avatar
Roger Dingledine committed
252
  }
253

254
  ++stats_n_relay_cells_relayed;
255
256
257
258
259
260
  /* not recognized. pass it on. */
  if(cell_direction == CELL_DIRECTION_OUT)
    conn = circ->n_conn;
  else
    conn = circ->p_conn;

261
  if(!conn) { //|| !connection_speaks_cells(conn)) {
262
    log_fn(LOG_INFO,"Didn't recognize cell (%d), but circ stops here! Dropping.", *(int *)(cell->payload+1));
263
    return 0;
264
  }
265

266
  log_fn(LOG_DEBUG,"Passing on unrecognized cell.");
267
268
  connection_write_cell_to_buf(cell, conn);
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
269
270
}

271
int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,
272
                crypt_path_t **layer_hint, char *recognized, connection_t **conn) {
273
  crypt_path_t *thishop;
274
  char out[256];
Roger Dingledine's avatar
Roger Dingledine committed
275

276
  assert(circ && in && recognized && conn);
Roger Dingledine's avatar
Roger Dingledine committed
277

278
  assert(inlen < 256);
Roger Dingledine's avatar
Roger Dingledine committed
279

Roger Dingledine's avatar
Roger Dingledine committed
280
  if(cell_direction == CELL_DIRECTION_IN) { 
281
    if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */
282
      thishop = circ->cpath;
283
      if(thishop->state != CPATH_STATE_OPEN) {
284
        log_fn(LOG_WARNING,"Relay cell before first created cell?");
285
286
        return -1;
      }
287
      do { /* Remember: cpath is in forward order, that is, first hop first. */
288
        assert(thishop);
289

290
        log_fn(LOG_DEBUG,"before decrypt: %d",*(int*)(in+2));
291
292
        /* decrypt */
        if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) {
293
          log_fn(LOG_WARNING,"Error performing onion decryption: %s", crypto_perror());
294
295
296
          return -1;
        }
        memcpy(in,out,inlen);
297
        log_fn(LOG_DEBUG,"after decrypt: %d",*(int*)(in+2));
298

299
300
        if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn))) {
          *layer_hint = thishop;
301
          return 0;
302
        }
303

304
        thishop = thishop->next;
305
      } while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
306
      log_fn(LOG_INFO,"in-cell at OP not recognized. Dropping.");
307
      return 0;
308
    } else { /* we're in the middle. Just one crypt. */
309

310
      log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+2));
311
      if(crypto_cipher_encrypt(circ->p_crypto, in, inlen, out)) {
312
        log_fn(LOG_WARNING,"Onion encryption failed for ACI %u: %s",
313
            circ->p_aci, crypto_perror());
314
315
316
        return -1;
      }
      memcpy(in,out,inlen);
317
      log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+2));
318

319
      log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP.");
320
321
      /* don't check for recognized. only the OP can recognize a stream on the way back. */

Roger Dingledine's avatar
Roger Dingledine committed
322
    }
Roger Dingledine's avatar
Roger Dingledine committed
323
  } else if(cell_direction == CELL_DIRECTION_OUT) { 
324
    if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */
325

326
      thishop = *layer_hint; /* we already know which layer, from when we package_raw_inbuf'ed */
327
328
329
      /* moving from last to first hop */
      do {
        assert(thishop);
330

331
        log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+2));
332
        if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, out)) {
333
          log_fn(LOG_WARNING,"Error performing encryption: %s", crypto_perror());
334
335
336
          return -1;
        }
        memcpy(in,out,inlen);
337
        log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+2));
338

339
340
        thishop = thishop->prev;
      } while(thishop != circ->cpath->prev);
341
    } else { /* we're in the middle. Just one crypt. */
342

343
      if(crypto_cipher_decrypt(circ->n_crypto,in, inlen, out)) {
344
        log_fn(LOG_WARNING,"Decryption failed for ACI %u: %s",
345
               circ->n_aci, crypto_perror());
346
347
348
        return -1;
      }
      memcpy(in,out,inlen);
349
350
351
352

      if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn)))
        return 0;

Roger Dingledine's avatar
Roger Dingledine committed
353
    }
354
  } else {
355
    log_fn(LOG_ERR,"unknown cell direction %d.", cell_direction);
356
    assert(0);
Roger Dingledine's avatar
Roger Dingledine committed
357
358
  }

359
360
361
  return 0;
}

362
363
364
365
int relay_check_recognized(circuit_t *circ, int cell_direction, char *stream, connection_t **conn) {
/* FIXME can optimize by passing thishop in */
  connection_t *tmpconn;

366
  if(!memcmp(stream,ZERO_STREAM,STREAM_ID_SIZE)) {
367
    log_fn(LOG_DEBUG,"It's the zero stream. Recognized.");
368
    return 1; /* the zero stream is always recognized */
369
  }
370
  log_fn(LOG_DEBUG,"not the zero stream.");
371
372

  if(cell_direction == CELL_DIRECTION_OUT)
373
    tmpconn = circ->n_streams;
374
  else
375
    tmpconn = circ->p_streams;
376

377
  if(!tmpconn) {
378
    log_fn(LOG_DEBUG,"No conns. Not recognized.");
379
    return 0;
380
381
382
383
  }

  for( ; tmpconn; tmpconn=tmpconn->next_stream) {
    if(!memcmp(stream,tmpconn->stream_id, STREAM_ID_SIZE)) {
384
      log_fn(LOG_DEBUG,"recognized stream %d.", *(int*)stream);
385
386
387
      *conn = tmpconn;
      return 1;
    }
388
    log_fn(LOG_DEBUG,"considered stream %d, not it.",*(int*)tmpconn->stream_id);
389
390
  }

391
  log_fn(LOG_DEBUG,"Didn't recognize on this iteration of decryption.");
392
393
394
395
  return 0;

}

396
void circuit_resume_edge_reading(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) {
397
398
399
400
  connection_t *conn;

  assert(edge_type == EDGE_EXIT || edge_type == EDGE_AP);

401
  log_fn(LOG_DEBUG,"resuming");
402

Roger Dingledine's avatar
   
Roger Dingledine committed
403
  if(edge_type == EDGE_EXIT)
404
    conn = circ->n_streams;
Roger Dingledine's avatar
   
Roger Dingledine committed
405
  else
406
    conn = circ->p_streams;
Roger Dingledine's avatar
   
Roger Dingledine committed
407

408
  for( ; conn; conn=conn->next_stream) {
409
410
    if((edge_type == EDGE_EXIT && conn->package_window > 0) ||
       (edge_type == EDGE_AP   && conn->package_window > 0 && conn->cpath_layer == layer_hint)) {
411
412
      connection_start_reading(conn);
      connection_package_raw_inbuf(conn); /* handle whatever might still be on the inbuf */
413
414
415
416

      /* If the circuit won't accept any more data, return without looking
       * at any more of the streams. Any connections that should be stopped
       * have already been stopped by connection_package_raw_inbuf. */
417
418
      if(circuit_consider_stop_edge_reading(circ, edge_type, layer_hint))
        return;
419
420
421
422
423
    }
  }
}

/* returns 1 if the window is empty, else 0. If it's empty, tell edge conns to stop reading. */
424
int circuit_consider_stop_edge_reading(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) {
425
426
427
  connection_t *conn = NULL;

  assert(edge_type == EDGE_EXIT || edge_type == EDGE_AP);
428
  assert(edge_type == EDGE_EXIT || layer_hint);
429

430
  log_fn(LOG_DEBUG,"considering");
431
  if(edge_type == EDGE_EXIT && circ->package_window <= 0)
432
    conn = circ->n_streams;
433
  else if(edge_type == EDGE_AP && layer_hint->package_window <= 0)
434
    conn = circ->p_streams;
435
436
437
  else
    return 0;

438
  for( ; conn; conn=conn->next_stream)
439
440
    if(!layer_hint || conn->cpath_layer == layer_hint)
      connection_stop_reading(conn);
441

442
  log_fn(LOG_DEBUG,"yes. stopped.");
443
444
445
  return 1;
}

446
447
int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) {
  cell_t cell;
Roger Dingledine's avatar
Roger Dingledine committed
448

449
450
  assert(circ);

451
452
453
454
  memset(&cell, 0, sizeof(cell_t));
  cell.command = CELL_RELAY;
  SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_SENDME);
  SET_CELL_STREAM_ID(cell, ZERO_STREAM);
455

456
  cell.length = RELAY_HEADER_SIZE;
457
  if(edge_type == EDGE_AP) { /* i'm the AP */
458
459
    cell.aci = circ->n_aci;
    while(layer_hint->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) {
460
      log_fn(LOG_DEBUG,"deliver_window %d, Queueing sendme forward.", layer_hint->deliver_window);
461
      layer_hint->deliver_window += CIRCWINDOW_INCREMENT;
462
      if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, layer_hint) < 0) {
Roger Dingledine's avatar
   
Roger Dingledine committed
463
464
        return -1;
      }
465
466
    }
  } else if(edge_type == EDGE_EXIT) { /* i'm the exit */
467
468
    cell.aci = circ->p_aci;
    while(circ->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) {
469
      log_fn(LOG_DEBUG,"deliver_window %d, Queueing sendme back.", circ->deliver_window);
470
      circ->deliver_window += CIRCWINDOW_INCREMENT;
471
      if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_IN, layer_hint) < 0) {
Roger Dingledine's avatar
   
Roger Dingledine committed
472
473
        return -1;
      }
474
475
    }
  }
Roger Dingledine's avatar
Roger Dingledine committed
476
477
478
479
  return 0;
}

void circuit_close(circuit_t *circ) {
480
  connection_t *conn;
481
  circuit_t *youngest=NULL;
482

483
  assert(circ);
484
  if(options.APPort) {
Roger Dingledine's avatar
Roger Dingledine committed
485
    youngest = circuit_get_newest_open();
486
    log_fn(LOG_DEBUG,"youngest %d, circ %d.",(int)youngest, (int)circ);
487
  }
Roger Dingledine's avatar
Roger Dingledine committed
488
  circuit_remove(circ);
489
490
491
492
  if(circ->n_conn)
    connection_send_destroy(circ->n_aci, circ->n_conn);
  for(conn=circ->n_streams; conn; conn=conn->next_stream) {
    connection_send_destroy(circ->n_aci, conn); 
493
  }
494
495
496
497
  if(circ->p_conn)
    connection_send_destroy(circ->n_aci, circ->p_conn);
  for(conn=circ->p_streams; conn; conn=conn->next_stream) {
    connection_send_destroy(circ->p_aci, conn); 
498
  }
499
500
  if(options.APPort && youngest == circ) { /* check this after we've sent the destroys, to reduce races */
    /* our current circuit just died. Launch another one pronto. */
501
    log_fn(LOG_INFO,"Youngest circuit dying. Launching a replacement.");
502
503
    circuit_launch_new(1);
  }
Roger Dingledine's avatar
Roger Dingledine committed
504
505
506
507
508
509
510
511
512
  circuit_free(circ);
}

void circuit_about_to_close_connection(connection_t *conn) {
  /* send destroys for all circuits using conn */
  /* currently, we assume it's too late to flush conn's buf here.
   * down the road, maybe we'll consider that eof doesn't mean can't-write
   */
  circuit_t *circ;
513
  connection_t *prevconn;
514
515
516

  if(!connection_speaks_cells(conn)) {
    /* it's an edge conn. need to remove it from the linked list of
517
     * conn's for this circuit. Send an 'end' relay command.
518
519
520
521
522
523
524
     * But don't kill the circuit.
     */

    circ = circuit_get_by_conn(conn);
    if(!circ)
      return;

525
526
    if(conn == circ->p_streams) {
      circ->p_streams = conn->next_stream;
527
528
      goto send_end;
    }
529
530
    if(conn == circ->n_streams) {
      circ->n_streams = conn->next_stream;
531
532
      goto send_end;
    }
Roger Dingledine's avatar
bugfix    
Roger Dingledine committed
533
534
    for(prevconn = circ->p_streams; prevconn && prevconn->next_stream && prevconn->next_stream != conn; prevconn = prevconn->next_stream) ;
    if(prevconn && prevconn->next_stream) {
535
      prevconn->next_stream = conn->next_stream;
536
537
      goto send_end;
    }
Roger Dingledine's avatar
bugfix    
Roger Dingledine committed
538
539
    for(prevconn = circ->n_streams; prevconn && prevconn->next_stream && prevconn->next_stream != conn; prevconn = prevconn->next_stream) ;
    if(prevconn && prevconn->next_stream) {
540
      prevconn->next_stream = conn->next_stream;
541
542
      goto send_end;
    }
543
    log_fn(LOG_ERR,"edge conn not in circuit's list?");
544
545
    assert(0); /* should never get here */
send_end:
546
    if(connection_edge_send_command(conn, circ, RELAY_COMMAND_END) < 0) {
547
      log_fn(LOG_DEBUG,"sending end failed. Closing.");
548
549
550
551
      circuit_close(circ);
    }
    return;
  }
Roger Dingledine's avatar
Roger Dingledine committed
552

553
  /* this connection speaks cells. We must close all the circuits on it. */
Roger Dingledine's avatar
Roger Dingledine committed
554
555
  while((circ = circuit_get_by_conn(conn))) {
    if(circ->n_conn == conn) /* it's closing in front of us */
556
      circ->n_conn = NULL;
Roger Dingledine's avatar
Roger Dingledine committed
557
    if(circ->p_conn == conn) /* it's closing behind us */
558
559
      circ->p_conn = NULL;
    circuit_close(circ);
Roger Dingledine's avatar
Roger Dingledine committed
560
561
562
  }  
}

563
/* FIXME this now leaves some out */
564
565
void circuit_dump_by_conn(connection_t *conn) {
  circuit_t *circ;
566
  connection_t *tmpconn;
567
568

  for(circ=global_circuitlist;circ;circ = circ->next) {
569
570
571
572
    if(circ->p_conn == conn)
      printf("Conn %d has App-ward circuit:  aci %d (other side %d), state %d (%s)\n",
        conn->poll_index, circ->p_aci, circ->n_aci, circ->state, circuit_state_to_string[circ->state]);
    for(tmpconn=circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
573
574
575
576
      if(tmpconn == conn) {
        printf("Conn %d has App-ward circuit:  aci %d (other side %d), state %d (%s)\n",
          conn->poll_index, circ->p_aci, circ->n_aci, circ->state, circuit_state_to_string[circ->state]);
      }
577
    }
578
579
580
581
    if(circ->n_conn == conn)
      printf("Conn %d has Exit-ward circuit: aci %d (other side %d), state %d (%s)\n",
        conn->poll_index, circ->n_aci, circ->p_aci, circ->state, circuit_state_to_string[circ->state]);
    for(tmpconn=circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
582
583
584
585
      if(tmpconn == conn) {
        printf("Conn %d has Exit-ward circuit: aci %d (other side %d), state %d (%s)\n",
          conn->poll_index, circ->n_aci, circ->p_aci, circ->state, circuit_state_to_string[circ->state]);
      }
586
587
588
589
    }
  }
}

590
591
592
593
void circuit_expire_unused_circuits(void) {
  circuit_t *circ, *tmpcirc;
  circuit_t *youngest;

Roger Dingledine's avatar
Roger Dingledine committed
594
  youngest = circuit_get_newest_open();
595
596
597
598
599

  circ = global_circuitlist;
  while(circ) {
    tmpcirc = circ;
    circ = circ->next;
600
    if(tmpcirc != youngest && !tmpcirc->p_conn && !tmpcirc->p_streams) {
601
      log_fn(LOG_DEBUG,"Closing n_aci %d",tmpcirc->n_aci);
602
603
604
605
606
607
608
609
610
611
612
613
      circuit_close(tmpcirc);
    }
  }
}

/* failure_status code: negative means reset failures to 0. Other values mean
 * add that value to the current number of failures, then if we don't have too
 * many failures on record, try to make a new circuit.
 */
void circuit_launch_new(int failure_status) {
  static int failures=0;

614
615
616
  if(!options.APPort) /* we're not an application proxy. no need for circuits. */
    return;

617
618
619
620
621
622
623
624
625
626
  if(failure_status == -1) { /* I was called because a circuit succeeded */
    failures = 0;
    return;
  }

  failures += failure_status;

retry_circuit:

  if(failures > 5) {
627
    log_fn(LOG_INFO,"Giving up for now, %d failures.", failures);
628
629
630
    return;
  }

631
  if(circuit_establish_circuit() < 0) {
632
633
634
635
636
637
638
639
    failures++;
    goto retry_circuit;
  }

  failures = 0;
  return;
}

640
int circuit_establish_circuit(void) {
641
642
643
644
645
646
  routerinfo_t *firsthop;
  connection_t *n_conn;
  circuit_t *circ;

  circ = circuit_new(0, NULL); /* sets circ->p_aci and circ->p_conn */
  circ->state = CIRCUIT_STATE_OR_WAIT;
647
648
  circ->cpath = onion_generate_cpath(&firsthop);
  if(!circ->cpath) {
649
    log_fn(LOG_INFO,"Generating cpath failed.");
650
651
652
653
654
    circuit_close(circ);
    return -1;
  }

  /* now see if we're already connected to the first OR in 'route' */
655

656
  log_fn(LOG_DEBUG,"Looking for firsthop '%s:%u'",
657
658
659
660
661
      firsthop->address,firsthop->or_port);
  n_conn = connection_twin_get_by_addr_port(firsthop->addr,firsthop->or_port);
  if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) { /* not currently connected */
    circ->n_addr = firsthop->addr;
    circ->n_port = firsthop->or_port;
662
    if(options.OnionRouter) { /* we would be connected if he were up. but he's not. */
663
      log_fn(LOG_INFO,"Route's firsthop isn't connected.");
664
665
666
667
668
      circuit_close(circ); 
      return -1;
    }

    if(!n_conn) { /* launch the connection */
669
      n_conn = connection_or_connect(firsthop);
670
      if(!n_conn) { /* connect failed, forget the whole thing */
671
        log_fn(LOG_INFO,"connect to firsthop failed. Closing.");
672
673
674
675
676
        circuit_close(circ);
        return -1;
      }
    }

677
    log_fn(LOG_DEBUG,"connecting in progress (or finished). Good.");
678
679
680
681
682
683
    return 0; /* return success. The onion/circuit/etc will be taken care of automatically
               * (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN.
               */ 
  } else { /* it (or a twin) is already open. use it. */
    circ->n_addr = n_conn->addr;
    circ->n_port = n_conn->port;
684
    circ->n_conn = n_conn;
685
    log_fn(LOG_DEBUG,"Conn open. Delivering first onion skin.");
686
    if(circuit_send_next_onion_skin(circ) < 0) {
687
      log_fn(LOG_INFO,"circuit_send_next_onion_skin failed.");
688
689
690
      circuit_close(circ);
      return -1;
    }
691
  }
692
  return 0;
693
694
695
696
697
698
}

/* find circuits that are waiting on me, if any, and get them to send the onion */
void circuit_n_conn_open(connection_t *or_conn) {
  circuit_t *circ;

699
  log_fn(LOG_DEBUG,"Starting.");
700
701
702
703
704
  circ = circuit_enumerate_by_naddr_nport(NULL, or_conn->addr, or_conn->port);
  for(;;) {
    if(!circ)
      return;

705
    log_fn(LOG_DEBUG,"Found circ, sending onion skin.");
706
707
    circ->n_conn = or_conn;
    if(circuit_send_next_onion_skin(circ) < 0) {
708
      log_fn(LOG_INFO,"send_next_onion_skin failed; circuit marked for closing.");
709
710
711
712
713
714
715
      circuit_close(circ);
      return; /* FIXME will want to try the other circuits too? */
    }
    circ = circuit_enumerate_by_naddr_nport(circ, or_conn->addr, or_conn->port);
  }
}

716
int circuit_send_next_onion_skin(circuit_t *circ) {
717
  cell_t cell;
718
719
  crypt_path_t *hop;
  routerinfo_t *router;
720

721
  assert(circ && circ->cpath);
722

723
  if(circ->cpath->state == CPATH_STATE_CLOSED) {
724

725
    log_fn(LOG_DEBUG,"First skin; sending create cell.");
726
    circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, ACI_TYPE_BOTH);
727

728
    memset(&cell, 0, sizeof(cell_t));
729
730
    cell.command = CELL_CREATE;
    cell.aci = circ->n_aci;
731
    cell.length = DH_ONIONSKIN_LEN;
732

733
    if(onion_skin_create(circ->n_conn->onion_pkey, &(circ->cpath->handshake_state), cell.payload) < 0) {
734
      log_fn(LOG_WARNING,"onion_skin_create (first hop) failed.");
735
736
737
      return -1;
    }

738
    connection_write_cell_to_buf(&cell, circ->n_conn);
739
740
741

    circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
    circ->state = CIRCUIT_STATE_BUILDING;
742
    log_fn(LOG_DEBUG,"first skin; finished sending create cell.");
743
744
745
  } else {
    assert(circ->cpath->state == CPATH_STATE_OPEN);
    assert(circ->state == CIRCUIT_STATE_BUILDING);
746
    log_fn(LOG_DEBUG,"starting to send subsequent skin.");
747
748
749
750
751
    for(hop=circ->cpath->next;
        hop != circ->cpath && hop->state == CPATH_STATE_OPEN;
        hop=hop->next) ;
    if(hop == circ->cpath) { /* done building the circuit. whew. */
      circ->state = CIRCUIT_STATE_OPEN;
752
      log_fn(LOG_INFO,"circuit built!");
753
754
755
756
757
      return 0;
    }

    router = router_get_by_addr_port(hop->addr,hop->port);
    if(!router) {
758
      log_fn(LOG_WARNING,"couldn't lookup router %d:%d",hop->addr,hop->port);
759
760
761
762
763
764
765
766
767
      return -1;
    }

    memset(&cell, 0, sizeof(cell_t));
    cell.command = CELL_RELAY; 
    cell.aci = circ->n_aci;
    SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_EXTEND);
    SET_CELL_STREAM_ID(cell, ZERO_STREAM);

768
    cell.length = RELAY_HEADER_SIZE + 6 + DH_ONIONSKIN_LEN;
769
    *(uint32_t*)(cell.payload+RELAY_HEADER_SIZE) = htonl(hop->addr);
Nick Mathewson's avatar
Nick Mathewson committed
770
    *(uint16_t*)(cell.payload+RELAY_HEADER_SIZE+4) = htons(hop->port);
771
    if(onion_skin_create(router->onion_pkey, &(hop->handshake_state), cell.payload+RELAY_HEADER_SIZE+6) < 0) {
772
      log_fn(LOG_WARNING,"onion_skin_create failed.");
773
774
775
      return -1;
    }

776
    log_fn(LOG_DEBUG,"Sending extend relay cell.");
777
    /* send it to hop->prev, because it will transfer it to a create cell and then send to hop */
778
    if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, hop->prev) < 0) {
779
      log_fn(LOG_WARNING,"failed to deliver extend cell. Closing.");
780
781
782
783
784
785
786
      return -1;
    }
    hop->state = CPATH_STATE_AWAITING_KEYS;
  }
  return 0;
}

787
788
789
/* take the 'extend' cell, pull out addr/port plus the onion skin. Make
 * sure we're connected to the next hop, and pass it the onion skin in
 * a create cell.
790
791
792
793
794
795
 */
int circuit_extend(cell_t *cell, circuit_t *circ) {
  connection_t *n_conn;
  aci_t aci_type;
  cell_t newcell;

796
  if(circ->n_conn) {
797
    log_fn(LOG_WARNING,"n_conn already set. Bug/attack. Closing.");
798
799
800
    return -1;
  }

801
802
803
804
805
806
807
808
809
810
811
  circ->n_addr = ntohl(*(uint32_t*)(cell->payload+RELAY_HEADER_SIZE));
  circ->n_port = ntohs(*(uint16_t*)(cell->payload+RELAY_HEADER_SIZE+4));

  n_conn = connection_twin_get_by_addr_port(circ->n_addr,circ->n_port);
  if(!n_conn || n_conn->type != CONN_TYPE_OR) {
    /* i've disabled making connections through OPs, but it's definitely
     * possible here. I'm not sure if it would be a bug or a feature. -RD
     */
    /* note also that this will close circuits where the onion has the same
     * router twice in a row in the path. i think that's ok. -RD
     */
812
813
814
    struct in_addr in;
    in.s_addr = htonl(circ->n_addr);
    log_fn(LOG_DEBUG,"Next router (%s:%d) not connected. Closing.", inet_ntoa(in), circ->n_port);
815
816
817
818
819
820
821
822
    /* XXX later we should fail more gracefully here, like with a 'truncated' */
    return -1;
  }

  circ->n_addr = n_conn->addr; /* these are different if we found a twin instead */
  circ->n_port = n_conn->port;

  circ->n_conn = n_conn;
823
  log_fn(LOG_DEBUG,"n_conn is %s:%u",n_conn->address,n_conn->port);
824

825
  aci_type = decide_aci_type(options.Nickname, n_conn->nickname);
826

827
  log_fn(LOG_DEBUG,"aci_type = %u.",aci_type);
828
829
  circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, aci_type);
  if(!circ->n_aci) {
830
    log_fn(LOG_WARNING,"failed to get unique aci.");
831
832
    return -1;
  }
833
  log_fn(LOG_DEBUG,"Chosen ACI %u.",circ->n_aci);
834
835
836
837

  memset(&newcell, 0, sizeof(cell_t));
  newcell.command = CELL_CREATE;
  newcell.aci = circ->n_aci;
838
  newcell.length = DH_ONIONSKIN_LEN;
839

840
  memcpy(newcell.payload, cell->payload+RELAY_HEADER_SIZE+6, DH_ONIONSKIN_LEN);
841

842
  connection_write_cell_to_buf(&newcell, circ->n_conn);
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
  return 0;
}

int circuit_finish_handshake(circuit_t *circ, char *reply) {
  unsigned char iv[16];
  unsigned char keys[32];
  crypt_path_t *hop;

  memset(iv, 0, 16);

  assert(circ->cpath);
  if(circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
    hop = circ->cpath;
  else {
    for(hop=circ->cpath->next;
        hop != circ->cpath && hop->state == CPATH_STATE_OPEN;
        hop=hop->next) ;
    if(hop == circ->cpath) { /* got an extended when we're all done? */
861
      log_fn(LOG_WARNING,"got extended when circ already built? Closing.");
862
      return -1;
863
864
865
866
867
    }
  }
  assert(hop->state == CPATH_STATE_AWAITING_KEYS);

  if(onion_skin_client_handshake(hop->handshake_state, reply, keys, 32) < 0) {
868
    log_fn(LOG_WARNING,"onion_skin_client_handshake failed.");
869
870
871
872
873
874
    return -1;
  }

  crypto_dh_free(hop->handshake_state); /* don't need it anymore */
  hop->handshake_state = NULL;

875
  log_fn(LOG_DEBUG,"hop %d init cipher forward %d, backward %d.", (uint32_t)hop, *(uint32_t*)keys, *(uint32_t*)(keys+16));
876
  if (!(hop->f_crypto =
Nick Mathewson's avatar
src/or    
Nick Mathewson committed
877
        crypto_create_init_cipher(CIRCUIT_CIPHER,keys,iv,1))) {
878
    log(LOG_WARNING,"forward cipher initialization failed.");
879
880
881
882
    return -1;
  }

  if (!(hop->b_crypto =
Nick Mathewson's avatar
src/or    
Nick Mathewson committed
883
        crypto_create_init_cipher(CIRCUIT_CIPHER,keys+16,iv,0))) {
884
    log(LOG_WARNING,"backward cipher initialization failed.");
885
886
    return -1;
  }
887

888
  hop->state = CPATH_STATE_OPEN;
889
  log_fn(LOG_INFO,"finished");
890
891
892
  return 0;
}

893
894
895
896
897
898
899
900
901
902
int circuit_truncated(circuit_t *circ, crypt_path_t *layer) {
  crypt_path_t *victim;
  connection_t *stream;

  assert(circ);
  assert(layer);

  while(layer->next != circ->cpath) {
    /* we need to clear out layer->next */
    victim = layer->next;
903
    log_fn(LOG_DEBUG, "Killing a layer of the cpath.");
904
905
906

    for(stream = circ->p_streams; stream; stream=stream->next_stream) {
      if(stream->cpath_layer == victim) {
907
        log_fn(LOG_INFO, "Marking stream %d for close.", *(int*)stream->stream_id);
908
/*ENDCLOSE*/    stream->marked_for_close = 1;
909
910
911
912
913
914
915
      }
    }

    layer->next = victim->next;
    circuit_free_cpath_node(victim);
  }

916
  log_fn(LOG_INFO, "finished");
917
918
919
  return 0;
}

920

921
void assert_cpath_layer_ok(const crypt_path_t *cp)
922
923
924
925
926
927
928
929
930
931
{
  assert(cp->f_crypto);
  assert(cp->b_crypto);
  assert(cp->addr);
  assert(cp->port);
  switch(cp->state) 
    {
    case CPATH_STATE_CLOSED:
    case CPATH_STATE_OPEN:
      assert(!cp->handshake_state);
932
      break;
933
934
    case CPATH_STATE_AWAITING_KEYS:
      assert(cp->handshake_state);
935
      break;
936
937
938
939
940
941
942
    default:
      assert(0);
    }
  assert(cp->package_window >= 0);
  assert(cp->deliver_window >= 0);
}

943
void assert_cpath_ok(const crypt_path_t *cp)
944
945
946
947
948
949