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

#include "or.h"

Roger Dingledine's avatar
Roger Dingledine committed
10
11
12
/**
 * \file router.c
 * \brief OR functionality, including key maintenance, generating
Nick Mathewson's avatar
Nick Mathewson committed
13
 * and uploading server descriptors, retrying OR connections.
Roger Dingledine's avatar
Roger Dingledine committed
14
 **/
Nick Mathewson's avatar
Nick Mathewson committed
15

16
extern long stats_n_seconds_working;
17

18
/** Exposed for test.c. */ void get_platform_str(char *platform, size_t len);
19

20
21
/************************************************************/

Nick Mathewson's avatar
Nick Mathewson committed
22
23
24
25
/*****
 * Key management: ORs only.
 *****/

Roger Dingledine's avatar
Roger Dingledine committed
26
/** Private keys for this OR.  There is also an SSL key managed by tortls.c.
Nick Mathewson's avatar
Nick Mathewson committed
27
 */
28
static tor_mutex_t *key_lock=NULL;
Nick Mathewson's avatar
Nick Mathewson committed
29
static time_t onionkey_set_at=0; /* When was onionkey last changed? */
30
static crypto_pk_env_t *onionkey=NULL;
31
static crypto_pk_env_t *lastonionkey=NULL;
32
33
static crypto_pk_env_t *identitykey=NULL;

Nick Mathewson's avatar
Nick Mathewson committed
34
/** Replace the current onion key with <b>k</b>.  Does not affect lastonionkey;
Nick Mathewson's avatar
Nick Mathewson committed
35
36
 * to update onionkey correctly, call rotate_onion_key().
 */
37
void set_onion_key(crypto_pk_env_t *k) {
38
  tor_mutex_acquire(key_lock);
39
  onionkey = k;
40
  onionkey_set_at = time(NULL);
41
  tor_mutex_release(key_lock);
42
  mark_my_descriptor_dirty();
43
44
}

Roger Dingledine's avatar
Roger Dingledine committed
45
/** Return the current onion key.  Requires that the onion key has been
Nick Mathewson's avatar
Nick Mathewson committed
46
 * loaded or generated. */
47
crypto_pk_env_t *get_onion_key(void) {
Roger Dingledine's avatar
Roger Dingledine committed
48
  tor_assert(onionkey);
49
50
51
  return onionkey;
}

Roger Dingledine's avatar
Roger Dingledine committed
52
/** Return the onion key that was current before the most recent onion
Nick Mathewson's avatar
Nick Mathewson committed
53
54
55
 * key rotation.  If no rotation has been performed since this process
 * started, return NULL.
 */
56
57
crypto_pk_env_t *get_previous_onion_key(void) {
  return lastonionkey;
58
59
}

60
61
void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last)
{
62
63
  tor_assert(key);
  tor_assert(last);
64
65
66
  tor_mutex_acquire(key_lock);
  *key = crypto_pk_dup_key(onionkey);
  if (lastonionkey)
Nick Mathewson's avatar
Nick Mathewson committed
67
    *last = crypto_pk_dup_key(lastonionkey);
68
69
70
71
72
  else
    *last = NULL;
  tor_mutex_release(key_lock);
}

Roger Dingledine's avatar
Roger Dingledine committed
73
/** Return the time when the onion key was last set.  This is either the time
Nick Mathewson's avatar
Nick Mathewson committed
74
75
76
 * when the process launched, or the time of the most recent key rotation since
 * the process launched.
 */
77
78
time_t get_onion_key_set_at(void) {
  return onionkey_set_at;
79
80
}

Roger Dingledine's avatar
Roger Dingledine committed
81
/** Set the current identity key to k.
Nick Mathewson's avatar
Nick Mathewson committed
82
 */
83
84
85
86
void set_identity_key(crypto_pk_env_t *k) {
  identitykey = k;
}

Roger Dingledine's avatar
Roger Dingledine committed
87
/** Returns the current identity key; requires that the identity key has been
Nick Mathewson's avatar
Nick Mathewson committed
88
89
 * set.
 */
90
crypto_pk_env_t *get_identity_key(void) {
Roger Dingledine's avatar
Roger Dingledine committed
91
  tor_assert(identitykey);
92
93
94
  return identitykey;
}

Nick Mathewson's avatar
Nick Mathewson committed
95
/** Return true iff the identity key has been set. */
96
97
98
99
int identity_key_is_set(void) {
  return identitykey != NULL;
}

Roger Dingledine's avatar
Roger Dingledine committed
100
/** Replace the previous onion key with the current onion key, and generate
101
102
 * a new previous onion key.  Immediately after calling this function,
 * the OR should:
Roger Dingledine's avatar
Roger Dingledine committed
103
104
105
 *   - schedule all previous cpuworkers to shut down _after_ processing
 *     pending work.  (This will cause fresh cpuworkers to be generated.)
 *   - generate and upload a fresh routerinfo.
106
107
108
109
 */
void rotate_onion_key(void)
{
  char fname[512];
110
  char fname_prev[512];
111
  crypto_pk_env_t *prkey;
112
  tor_snprintf(fname,sizeof(fname),
113
           "%s/keys/secret_onion_key",get_options()->DataDirectory);
114
  tor_snprintf(fname_prev,sizeof(fname_prev),
115
           "%s/keys/secret_onion_key.old",get_options()->DataDirectory);
116
117
118
119
  if (!(prkey = crypto_new_pk_env())) {
    log(LOG_ERR, "Error creating crypto environment.");
    goto error;
  }
120
  if (crypto_pk_generate_key(prkey)) {
121
    log(LOG_ERR, "Error generating onion key");
122
123
    goto error;
  }
124
125
126
127
  if (file_status(fname) == FN_FILE) {
    if (replace_file(fname, fname_prev))
      goto error;
  }
128
129
130
131
  if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
    log(LOG_ERR, "Couldn't write generated key to %s.", fname);
    goto error;
  }
132
  tor_mutex_acquire(key_lock);
133
134
  if (lastonionkey)
    crypto_free_pk_env(lastonionkey);
135
  log_fn(LOG_INFO, "Rotating onion key");
136
137
  lastonionkey = onionkey;
  set_onion_key(prkey);
138
  tor_mutex_release(key_lock);
139
140
141
142
143
  return;
 error:
  log_fn(LOG_WARN, "Couldn't rotate onion key.");
}

144
/** The latest calculated bandwidth usage for our node. */
145
static int bw_capacity = 0;
146
/** Tuck <b>bw</b> away so we can produce it when somebody
147
 * calls router_get_bandwidth_capacity() below.
148
 */
149
150
void router_set_bandwidth_capacity(int bw) {
  bw_capacity = bw;
151
152
}
/** Return the value we tucked away above, or zero by default. */
153
154
int router_get_bandwidth_capacity(void) {
  return bw_capacity;
155
156
}

157
158
159
/* Read an RSA secret key key from a file that was once named fname_old,
 * but is now named fname_new.  Rename the file from old to new as needed.
 */
160
161
162
static crypto_pk_env_t *
init_key_from_file_name_changed(const char *fname_old,
                                const char *fname_new)
163
164
{

165
166
  if (file_status(fname_new) == FN_FILE || file_status(fname_old) != FN_FILE)
    /* The new filename is there, or both are, or neither is. */
167
168
169
170
171
172
173
174
175
176
177
    return init_key_from_file(fname_new);

  /* The old filename exists, and the new one doesn't.  Rename and load. */
  if (rename(fname_old, fname_new) < 0) {
    log_fn(LOG_ERR, "Couldn't rename %s to %s: %s", fname_old, fname_new,
           strerror(errno));
    return NULL;
  }
  return init_key_from_file(fname_new);
}

Nick Mathewson's avatar
Nick Mathewson committed
178
179
180
/** Try to read an RSA key from <b>fname</b>.  If <b>fname</b> doesn't exist,
 * create a new RSA key and save it in <b>fname</b>.  Return the read/created
 * key, or NULL on error.
181
182
 */
crypto_pk_env_t *init_key_from_file(const char *fname)
183
184
185
186
{
  crypto_pk_env_t *prkey = NULL;
  FILE *file = NULL;

187
  if (!(prkey = crypto_new_pk_env())) {
188
189
190
191
    log(LOG_ERR, "Error creating crypto environment.");
    goto error;
  }

192
  switch (file_status(fname)) {
193
194
195
    case FN_DIR:
    case FN_ERROR:
      log(LOG_ERR, "Can't read key from %s", fname);
196
      goto error;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    case FN_NOENT:
      log(LOG_INFO, "No key found in %s; generating fresh key.", fname);
      if (crypto_pk_generate_key(prkey)) {
        log(LOG_ERR, "Error generating onion key");
        goto error;
      }
      if (crypto_pk_check_key(prkey) <= 0) {
        log(LOG_ERR, "Generated key seems invalid");
        goto error;
      }
      log(LOG_INFO, "Generated key seems valid");
      if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
        log(LOG_ERR, "Couldn't write generated key to %s.", fname);
        goto error;
      }
      return prkey;
    case FN_FILE:
      if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
        log(LOG_ERR, "Error loading private key.");
        goto error;
      }
      return prkey;
    default:
      tor_assert(0);
221
222
223
224
225
226
227
228
229
230
  }

 error:
  if (prkey)
    crypto_free_pk_env(prkey);
  if (file)
    fclose(file);
  return NULL;
}

Roger Dingledine's avatar
Roger Dingledine committed
231
/** Initialize all OR private keys, and the TLS context, as necessary.
Nick Mathewson's avatar
Nick Mathewson committed
232
233
 * On OPs, this only initializes the tls context.
 */
234
int init_keys(void) {
235
236
237
238
239
240
  /* XXX009 Two problems with how this is called:
   * 1. It should be idempotent for servers, so we can call init_keys
   *    as much as we need to.
   * 2. Clients should rotate their identity keys at least whenever
   *    their IPs change.
   */
241
  char keydir[512];
242
  char keydir2[512];
243
244
  char fingerprint[FINGERPRINT_LEN+1];
  char fingerprint_line[FINGERPRINT_LEN+MAX_NICKNAME_LEN+3];/*nickname fp\n\0 */
245
  char *cp;
246
  const char *tmp, *mydesc, *datadir;
247
  crypto_pk_env_t *prkey;
248
  char digest[20];
249
  or_options_t *options = get_options();
250

251
  if (!key_lock)
Nick Mathewson's avatar
Nick Mathewson committed
252
    key_lock = tor_mutex_new();
253

254
  /* OP's don't need persistent keys; just make up an identity and
255
   * initialize the TLS context. */
256
  if (!server_mode(options)) {
257
258
259
260
261
    if (!(prkey = crypto_new_pk_env()))
      return -1;
    if (crypto_pk_generate_key(prkey))
      return -1;
    set_identity_key(prkey);
262
    /* Create a TLS context; default the client nickname to "client". */
263
264
    if (tor_tls_context_new(get_identity_key(), 1,
                            options->Nickname ? options->Nickname : "client",
265
266
267
268
                            MAX_SSL_KEY_LIFETIME) < 0) {
      log_fn(LOG_ERR, "Error creating TLS context for OP.");
      return -1;
    }
269
270
    return 0;
  }
Nick Mathewson's avatar
Nick Mathewson committed
271
  /* Make sure DataDirectory exists, and is private. */
272
  datadir = options->DataDirectory;
273
  if (check_private_dir(datadir, CPD_CREATE)) {
274
275
    return -1;
  }
Nick Mathewson's avatar
Nick Mathewson committed
276
  /* Check the key directory. */
277
  tor_snprintf(keydir,sizeof(keydir),"%s/keys", datadir);
278
  if (check_private_dir(keydir, CPD_CREATE)) {
279
280
281
282
283
    return -1;
  }
  cp = keydir + strlen(keydir); /* End of string. */

  /* 1. Read identity key. Make it if none is found. */
284
285
  tor_snprintf(keydir,sizeof(keydir),"%s/keys/identity.key",datadir);
  tor_snprintf(keydir2,sizeof(keydir2),"%s/keys/secret_id_key",datadir);
286
287
  log_fn(LOG_INFO,"Reading/making identity key %s...",keydir2);
  prkey = init_key_from_file_name_changed(keydir,keydir2);
288
289
290
  if (!prkey) return -1;
  set_identity_key(prkey);
  /* 2. Read onion key.  Make it if none is found. */
291
292
  tor_snprintf(keydir,sizeof(keydir),"%s/keys/onion.key",datadir);
  tor_snprintf(keydir2,sizeof(keydir2),"%s/keys/secret_onion_key",datadir);
293
294
  log_fn(LOG_INFO,"Reading/making onion key %s...",keydir2);
  prkey = init_key_from_file_name_changed(keydir,keydir2);
295
296
  if (!prkey) return -1;
  set_onion_key(prkey);
297
  tor_snprintf(keydir,sizeof(keydir),"%s/keys/secret_onion_key.old",datadir);
298
299
300
301
302
  if (file_status(keydir) == FN_FILE) {
    prkey = init_key_from_file(keydir);
    if (prkey)
      lastonionkey = prkey;
  }
303
304

  /* 3. Initialize link key and TLS context. */
305
  if (tor_tls_context_new(get_identity_key(), 1, options->Nickname,
306
                          MAX_SSL_KEY_LIFETIME) < 0) {
307
308
309
310
311
    log_fn(LOG_ERR, "Error initializing TLS context");
    return -1;
  }
  /* 4. Dump router descriptor to 'router.desc' */
  /* Must be called after keys are initialized. */
Roger Dingledine's avatar
Roger Dingledine committed
312
313
  tmp = mydesc = router_get_my_descriptor();
  if (!mydesc) {
314
315
316
    log_fn(LOG_ERR, "Error initializing descriptor.");
    return -1;
  }
317
  if (authdir_mode(options)) {
318
    const char *m;
Roger Dingledine's avatar
Roger Dingledine committed
319
    /* We need to add our own fingerprint so it gets recognized. */
320
    if (dirserv_add_own_fingerprint(options->Nickname, get_identity_key())) {
Roger Dingledine's avatar
Roger Dingledine committed
321
322
323
      log_fn(LOG_ERR, "Error adding own fingerprint to approved set");
      return -1;
    }
324
325
326
    if (dirserv_add_descriptor(&tmp, &m) != 1) {
      log(LOG_ERR, "Unable to add own descriptor to directory: %s",
          m?m:"<unknown error>");
Roger Dingledine's avatar
Roger Dingledine committed
327
328
      return -1;
    }
329
  }
Roger Dingledine's avatar
Roger Dingledine committed
330

331
  tor_snprintf(keydir,sizeof(keydir),"%s/router.desc", datadir);
332
  log_fn(LOG_INFO,"Dumping descriptor to %s...",keydir);
333
  if (write_str_to_file(keydir, mydesc,0)) {
334
335
336
    return -1;
  }
  /* 5. Dump fingerprint to 'fingerprint' */
337
  tor_snprintf(keydir,sizeof(keydir),"%s/fingerprint", datadir);
338
  log_fn(LOG_INFO,"Dumping fingerprint to %s...",keydir);
339
  if (crypto_pk_get_fingerprint(get_identity_key(), fingerprint, 1)<0) {
340
341
342
    log_fn(LOG_ERR, "Error computing fingerprint");
    return -1;
  }
343
344
345
346
347
348
349
  tor_assert(strlen(options->Nickname) <= MAX_NICKNAME_LEN);
  if (tor_snprintf(fingerprint_line, sizeof(fingerprint_line),
                   "%s %s\n",options->Nickname, fingerprint) < 0) {
    log_fn(LOG_ERR, "Error writing fingerprint line");
    return -1;
  }
  if (write_str_to_file(keydir, fingerprint_line, 0))
350
    return -1;
351
  if (!authdir_mode(options))
352
    return 0;
Roger Dingledine's avatar
Roger Dingledine committed
353
  /* 6. [authdirserver only] load approved-routers file */
354
  tor_snprintf(keydir,sizeof(keydir),"%s/approved-routers", datadir);
355
  log_fn(LOG_INFO,"Loading approved fingerprints from %s...",keydir);
356
  if (dirserv_parse_fingerprint_file(keydir) < 0) {
357
358
359
    log_fn(LOG_ERR, "Error loading fingerprints");
    return -1;
  }
360
361
362
  /* 6b. [authdirserver only] add own key to approved directories. */
  crypto_pk_get_digest(get_identity_key(), digest);
  if (!router_digest_is_trusted_dir(digest)) {
363
    add_trusted_dir_server(options->Address, (uint16_t)options->DirPort, digest);
364
  }
Roger Dingledine's avatar
Roger Dingledine committed
365
  /* 7. [authdirserver only] load old directory, if it's there */
366
  tor_snprintf(keydir,sizeof(keydir),"%s/cached-directory", datadir);
367
  log_fn(LOG_INFO,"Loading cached directory from %s...",keydir);
368
  cp = read_file_to_str(keydir,0);
369
  if (!cp) {
370
371
    log_fn(LOG_INFO,"Cached directory %s not present. Ok.",keydir);
  } else {
372
    if (dirserv_load_from_directory_string(cp) < 0) {
373
      log_fn(LOG_WARN, "Cached directory %s is corrupt, only loaded part of it.", keydir);
Roger Dingledine's avatar
Roger Dingledine committed
374
      tor_free(cp);
375
      return 0;
376
    }
377
    tor_free(cp);
378
379
380
381
382
  }
  /* success */
  return 0;
}

Nick Mathewson's avatar
Nick Mathewson committed
383
/*
Nick Mathewson's avatar
Nick Mathewson committed
384
 * Clique maintenance
Nick Mathewson's avatar
Nick Mathewson committed
385
 */
386

387
388
389
/** OR only: if in clique mode, try to open connections to all of the
 * other ORs we know about. Otherwise, open connections to those we
 * think are in clique mode.
Nick Mathewson's avatar
Nick Mathewson committed
390
 */
391
392
393
394
void router_retry_connections(void) {
  int i;
  routerinfo_t *router;
  routerlist_t *rl;
395
  or_options_t *options = get_options();
396

397
  tor_assert(server_mode(options));
398

399
  router_get_routerlist(&rl);
400
  if (!rl) return;
401
402
  for (i=0;i < smartlist_len(rl->routers);i++) {
    router = smartlist_get(rl->routers, i);
403
    if (router_is_me(router))
404
      continue;
405
    if (!clique_mode(options) && !router_is_clique_mode(router))
406
      continue;
407
    if (!connection_get_by_identity_digest(router->identity_digest,
408
                                           CONN_TYPE_OR)) {
409
      /* not in the list */
410
      log_fn(LOG_DEBUG,"connecting to OR at %s:%u.",router->address,router->or_port);
411
      connection_or_connect(router->addr, router->or_port, router->identity_digest);
412
413
414
415
    }
  }
}

416
int router_is_clique_mode(routerinfo_t *router) {
417
  if (router_digest_is_trusted_dir(router->identity_digest))
418
419
420
421
    return 1;
  return 0;
}

Nick Mathewson's avatar
Nick Mathewson committed
422
/*
Nick Mathewson's avatar
Nick Mathewson committed
423
 * OR descriptor generation.
Nick Mathewson's avatar
Nick Mathewson committed
424
 */
Nick Mathewson's avatar
Nick Mathewson committed
425

426
/** My routerinfo. */
Nick Mathewson's avatar
Nick Mathewson committed
427
static routerinfo_t *desc_routerinfo = NULL;
428
/** String representation of my descriptor, signed by me. */
Nick Mathewson's avatar
Nick Mathewson committed
429
static char descriptor[8192];
430
431
432
433
/** Boolean: do we need to regenerate the above? */
static int desc_is_dirty = 1;
/** Boolean: do we need to regenerate the above? */
static int desc_needs_upload = 0;
Nick Mathewson's avatar
Nick Mathewson committed
434

Roger Dingledine's avatar
Roger Dingledine committed
435
/** OR only: try to upload our signed descriptor to all the directory servers
436
 * we know about. DOCDOC force
Nick Mathewson's avatar
Nick Mathewson committed
437
 */
438
void router_upload_dir_desc_to_dirservers(int force) {
Roger Dingledine's avatar
Roger Dingledine committed
439
  const char *s;
440

Roger Dingledine's avatar
Roger Dingledine committed
441
442
  s = router_get_my_descriptor();
  if (!s) {
443
444
445
    log_fn(LOG_WARN, "No descriptor; skipping upload");
    return;
  }
446
447
448
  if (!force || !desc_needs_upload)
    return;
  desc_needs_upload = 0;
Roger Dingledine's avatar
Roger Dingledine committed
449
  directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR, s, strlen(s));
450
451
}

452
#define DEFAULT_EXIT_POLICY "reject 0.0.0.0/8,reject 169.254.0.0/16,reject 127.0.0.0/8,reject 192.168.0.0/16,reject 10.0.0.0/8,reject 172.16.0.0/12,accept *:20-22,accept *:53,accept *:79-81,accept *:110,accept *:143,accept *:389,accept *:443,accept *:636,accept *:706,accept *:873,accept *:993,accept *:995,reject *:1214,reject *:4661-4666,reject *:6346-6347,reject *:6419,reject *:6881-6889,accept *:1024-65535,reject *:*"
453

Nick Mathewson's avatar
Nick Mathewson committed
454
455
456
/** Set the exit policy on <b>router</b> to match the exit policy in the
 * current configuration file.  If the exit policy doesn't have a catch-all
 * rule, then append the default exit policy as well.
Nick Mathewson's avatar
Nick Mathewson committed
457
 */
458
static void router_add_exit_policy_from_config(routerinfo_t *router) {
459
  addr_policy_t *ep;
460
  struct config_line_t default_policy;
461
  config_parse_addr_policy(get_options()->ExitPolicy, &router->exit_policy);
462
463
464
465
466
467

  for (ep = router->exit_policy; ep; ep = ep->next) {
    if (ep->msk == 0 && ep->prt_min <= 1 && ep->prt_max >= 65535) {
      /* if exitpolicy includes a *:* line, then we're done. */
      return;
    }
468
  }
469
470
471

  /* Else, append the default exitpolicy. */
  default_policy.key = NULL;
472
  default_policy.value = (char*)DEFAULT_EXIT_POLICY;
473
  default_policy.next = NULL;
474
  config_parse_addr_policy(&default_policy, &router->exit_policy);
475
476
}

Roger Dingledine's avatar
Roger Dingledine committed
477
/** OR only: Return false if my exit policy says to allow connection to
Nick Mathewson's avatar
Nick Mathewson committed
478
 * conn.  Else return true.
479
 */
480
481
int router_compare_to_my_exit_policy(connection_t *conn)
{
Roger Dingledine's avatar
Roger Dingledine committed
482
  tor_assert(desc_routerinfo);
483
484
485
486
487
488

  /* make sure it's resolved to something. this way we can't get a
     'maybe' below. */
  if (!conn->addr)
    return -1;

489
  return router_compare_addr_to_addr_policy(conn->addr, conn->port,
490
                   desc_routerinfo->exit_policy);
491

492
493
}

Nick Mathewson's avatar
Nick Mathewson committed
494
495
/** Return true iff <b>router</b> has the same nickname as this OR.  (For an
 * OP, always returns false.)
Nick Mathewson's avatar
Nick Mathewson committed
496
 */
497
498
int router_is_me(routerinfo_t *router)
{
499
  routerinfo_t *me = router_get_my_routerinfo();
Roger Dingledine's avatar
Roger Dingledine committed
500
  tor_assert(router);
501
  if (!me || memcmp(me->identity_digest, router->identity_digest, DIGEST_LEN))
502
503
    return 0;
  return 1;
504
505
}

Roger Dingledine's avatar
Roger Dingledine committed
506
/** Return a routerinfo for this OR, rebuilding a fresh one if
Nick Mathewson's avatar
Nick Mathewson committed
507
 * necessary.  Return NULL on error, or if called on an OP. */
508
509
routerinfo_t *router_get_my_routerinfo(void)
{
510
  if (!server_mode(get_options()))
511
512
513
    return NULL;

  if (!desc_routerinfo) {
514
    if (router_rebuild_descriptor(1))
515
516
517
518
519
      return NULL;
  }
  return desc_routerinfo;
}

Roger Dingledine's avatar
Roger Dingledine committed
520
/** OR only: Return a signed server descriptor for this OR, rebuilding a fresh
Nick Mathewson's avatar
Nick Mathewson committed
521
522
 * one if necessary.  Return NULL on error.
 */
523
524
const char *router_get_my_descriptor(void) {
  if (!desc_routerinfo) {
525
    if (router_rebuild_descriptor(1))
526
527
528
529
530
531
      return NULL;
  }
  log_fn(LOG_DEBUG,"my desc is '%s'",descriptor);
  return descriptor;
}

Roger Dingledine's avatar
Roger Dingledine committed
532
/** Rebuild a fresh routerinfo and signed server descriptor for this
533
 * OR.  Return 0 on success, -1 on error. DOCDOC force
Nick Mathewson's avatar
Nick Mathewson committed
534
 */
535
int router_rebuild_descriptor(int force) {
536
  routerinfo_t *ri;
537
  uint32_t addr;
538
  char platform[256];
539
  struct in_addr in;
540
  int hibernating = we_are_hibernating();
541
  or_options_t *options = get_options();
542

543
544
545
  if (!desc_is_dirty && !force)
    return 0;

546
  if (resolve_my_address(options->Address, &addr) < 0) {
547
    log_fn(LOG_WARN,"options->Address didn't resolve into an IP.");
548
549
    return -1;
  }
550

551
  ri = tor_malloc_zero(sizeof(routerinfo_t));
552
553
  in.s_addr = htonl(addr);
  ri->address = tor_strdup(inet_ntoa(in));
554
  ri->nickname = tor_strdup(options->Nickname);
555
  ri->addr = addr;
556
  ri->or_port = options->ORPort;
557
  ri->dir_port = hibernating ? 0 : options->DirPort;
558
  ri->published_on = time(NULL);
559
  ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from main thread */
560
  ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
561
562
563
564
  if (crypto_pk_get_digest(ri->identity_pkey, ri->identity_digest)<0) {
    routerinfo_free(ri);
    return -1;
  }
565
566
  get_platform_str(platform, sizeof(platform));
  ri->platform = tor_strdup(platform);
567
568
  ri->bandwidthrate = (int)options->BandwidthRate;
  ri->bandwidthburst = (int)options->BandwidthBurst;
569
  ri->bandwidthcapacity = hibernating ? 0 : router_get_bandwidth_capacity();
570
  router_add_exit_policy_from_config(ri);
571
  if (desc_routerinfo) /* inherit values */
572
    ri->is_verified = desc_routerinfo->is_verified;
573
  if (options->MyFamily) {
574
    ri->declared_family = smartlist_create();
575
    smartlist_split_string(ri->declared_family, options->MyFamily, ",",
576
577
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  }
578

579
580
581
582
583
584
585
  if (desc_routerinfo)
    routerinfo_free(desc_routerinfo);
  desc_routerinfo = ri;
  if (router_dump_router_to_string(descriptor, 8192, ri, get_identity_key())<0) {
    log_fn(LOG_WARN, "Couldn't dump router to string.");
    return -1;
  }
586
587
  desc_is_dirty = 0;
  desc_needs_upload = 1;
588
589
590
  return 0;
}

591
592
593
594
595
596
597
/** DOCDOC */
void
mark_my_descriptor_dirty(void)
{
  desc_is_dirty = 1;
}

Nick Mathewson's avatar
Nick Mathewson committed
598
599
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
 * string describing the version of Tor and the operating system we're
Nick Mathewson's avatar
Nick Mathewson committed
600
601
 * currently running on.
 */
602
void get_platform_str(char *platform, size_t len)
603
{
604
  tor_snprintf(platform, len, "Tor %s on %s",
605
           VERSION, get_uname());
606
607
608
609
610
611
612
613
  return;
}

/* XXX need to audit this thing and count fenceposts. maybe
 *     refactor so we don't have to keep asking if we're
 *     near the end of maxlen?
 */
#define DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
Nick Mathewson's avatar
Nick Mathewson committed
614

Nick Mathewson's avatar
Nick Mathewson committed
615
616
617
618
/** OR only: Given a routerinfo for this router, and an identity key to sign
 * with, encode the routerinfo as a signed server descriptor and write the
 * result into <b>s</b>, using at most <b>maxlen</b> bytes.  Return -1 on
 * failure, and the number of bytes used on success.
Nick Mathewson's avatar
Nick Mathewson committed
619
 */
620
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
621
                                 crypto_pk_env_t *ident_key) {
Nick Mathewson's avatar
Nick Mathewson committed
622
623
  char *onion_pkey; /* Onion key, PEM-encoded. */
  char *identity_pkey; /* Identity key, PEM-encoded. */
624
625
626
  char digest[20];
  char signature[128];
  char published[32];
627
  char fingerprint[FINGERPRINT_LEN+1];
Nick Mathewson's avatar
Nick Mathewson committed
628
  struct in_addr in;
629
630
  size_t onion_pkeylen, identity_pkeylen;
  size_t written;
631
  int result=0;
632
  addr_policy_t *tmpe;
633
  char *bandwidth_usage;
634
  char *family_line;
635
#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
Roger Dingledine's avatar
Roger Dingledine committed
636
  char *s_tmp, *s_dup;
637
  const char *cp;
638
639
  routerinfo_t *ri_tmp;
#endif
Roger Dingledine's avatar
Roger Dingledine committed
640

Nick Mathewson's avatar
Nick Mathewson committed
641
  /* Make sure the identity key matches the one in the routerinfo. */
642
643
644
645
646
  if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
    log_fn(LOG_WARN,"Tried to sign a router with a private key that didn't match router's public key!");
    return -1;
  }

647
  /* record our fingerprint, so we can include it in the descriptor */
648
  if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) {
649
650
651
652
    log_fn(LOG_ERR, "Error computing fingerprint");
    return -1;
  }

Nick Mathewson's avatar
Nick Mathewson committed
653
  /* PEM-encode the onion key */
654
  if (crypto_pk_write_public_key_to_string(router->onion_pkey,
655
                                           &onion_pkey,&onion_pkeylen)<0) {
656
657
658
659
    log_fn(LOG_WARN,"write onion_pkey to string failed!");
    return -1;
  }

Nick Mathewson's avatar
Nick Mathewson committed
660
  /* PEM-encode the identity key key */
661
  if (crypto_pk_write_public_key_to_string(router->identity_pkey,
662
                                           &identity_pkey,&identity_pkeylen)<0) {
663
    log_fn(LOG_WARN,"write identity_pkey to string failed!");
Nick Mathewson's avatar
Nick Mathewson committed
664
    tor_free(onion_pkey);
665
666
667
    return -1;
  }

Nick Mathewson's avatar
Nick Mathewson committed
668
  /* Encode the publication time. */
669
  format_iso_time(published, router->published_on);
Roger Dingledine's avatar
Roger Dingledine committed
670

671
672
  /* How busy have we been? */
  bandwidth_usage = rep_hist_get_bandwidth_lines();
673

674
  if (router->declared_family && smartlist_len(router->declared_family)) {
675
676
677
    size_t n;
    char *s = smartlist_join_strings(router->declared_family, " ", 0, &n);
    n += strlen("opt family ") + 2; /* 1 for \n, 1 for \0. */
678
    family_line = tor_malloc(n);
679
    tor_snprintf(family_line, n, "opt family %s\n", s);
680
681
682
683
684
    tor_free(s);
  } else {
    family_line = tor_strdup("");
  }

Nick Mathewson's avatar
Nick Mathewson committed
685
  /* Generate the easy portion of the router descriptor. */
686
  result = tor_snprintf(s, maxlen,
687
                    "router %s %s %d 0 %d\n"
688
689
                    "platform %s\n"
                    "published %s\n"
690
                    "opt fingerprint %s\n"
691
                    "opt uptime %ld\n"
692
                    "bandwidth %d %d %d\n"
693
                    "onion-key\n%s"
694
                    "signing-key\n%s%s%s",
695
696
697
    router->nickname,
    router->address,
    router->or_port,
698
    router->dir_port,
699
    router->platform,
700
    published,
701
    fingerprint,
702
    stats_n_seconds_working,
703
704
    (int) router->bandwidthrate,
    (int) router->bandwidthburst,
705
    (int) router->bandwidthcapacity,
706
    onion_pkey, identity_pkey,
707
    family_line, bandwidth_usage);
708
  tor_free(family_line);
Nick Mathewson's avatar
Nick Mathewson committed
709
710
  tor_free(onion_pkey);
  tor_free(identity_pkey);
Nick Mathewson's avatar
Nick Mathewson committed
711
  tor_free(bandwidth_usage);
712

713
  if (result < 0)
714
    return -1;
Nick Mathewson's avatar
Nick Mathewson committed
715
  /* From now on, we use 'written' to remember the current length of 's'. */
716
717
  written = result;

718
  if (get_options()->ContactInfo && strlen(get_options()->ContactInfo)) {
719
    result = tor_snprintf(s+written,maxlen-written, "opt contact %s\n",
720
                      get_options()->ContactInfo);
721
    if (result<0)
722
723
724
725
      return -1;
    written += result;
  }

Nick Mathewson's avatar
Nick Mathewson committed
726
  /* Write the exit policy to the end of 's'. */
727
  for (tmpe=router->exit_policy; tmpe; tmpe=tmpe->next) {
728
    in.s_addr = htonl(tmpe->addr);
Nick Mathewson's avatar
Nick Mathewson committed
729
    /* Write: "accept 1.2.3.4" */
730
    result = tor_snprintf(s+written, maxlen-written, "%s %s",
731
        tmpe->policy_type == ADDR_POLICY_ACCEPT ? "accept" : "reject",
732
        tmpe->msk == 0 ? "*" : inet_ntoa(in));
733
    if (result < 0)
734
735
736
      return -1;
    written += result;
    if (tmpe->msk != 0xFFFFFFFFu && tmpe->msk != 0) {
Nick Mathewson's avatar
Nick Mathewson committed
737
      /* Write "/255.255.0.0" */
738
      in.s_addr = htonl(tmpe->msk);
739
      result = tor_snprintf(s+written, maxlen-written, "/%s", inet_ntoa(in));
740
      if (result<0)
741
742
743
        return -1;
      written += result;
    }
744
    if (tmpe->prt_min <= 1 && tmpe->prt_max == 65535) {
Nick Mathewson's avatar
Nick Mathewson committed
745
      /* There is no port set; write ":*" */
746
      if (written+4 > maxlen)
747
        return -1;
748
      strlcat(s+written, ":*\n", maxlen-written);
749
750
      written += 3;
    } else if (tmpe->prt_min == tmpe->prt_max) {
Nick Mathewson's avatar
Nick Mathewson committed
751
      /* There is only one port; write ":80". */
752
      result = tor_snprintf(s+written, maxlen-written, ":%d\n", tmpe->prt_min);
753
      if (result<0)
754
755
756
        return -1;
      written += result;
    } else {
Nick Mathewson's avatar
Nick Mathewson committed
757
      /* There is a range of ports; write ":79-80". */
758
      result = tor_snprintf(s+written, maxlen-written, ":%d-%d\n", tmpe->prt_min,
759
                        tmpe->prt_max);
760
      if (result<0)
761
        return -1;
762
      written += result;
763
    }
764
765
766
    if (tmpe->msk == 0 && tmpe->prt_min <= 1 && tmpe->prt_max == 65535)
      /* This was a catch-all rule, so future rules are irrelevant. */
      break;
767
  } /* end for */
768
  if (written+256 > maxlen) /* Not enough room for signature. */
769
770
    return -1;

Nick Mathewson's avatar
Nick Mathewson committed
771
  /* Sign the directory */
772
  strlcat(s+written, "router-signature\n", maxlen-written);
773
774
775
776
777
  written += strlen(s+written);
  s[written] = '\0';
  if (router_get_router_hash(s, digest) < 0)
    return -1;

778
  if (crypto_pk_private_sign(ident_key, signature, digest, 20) < 0) {
779
780
781
    log_fn(LOG_WARN, "Error signing digest");
    return -1;
  }
782
  strlcat(s+written, "-----BEGIN SIGNATURE-----\n", maxlen-written);
783
784
785
786
787
788
  written += strlen(s+written);
  if (base64_encode(s+written, maxlen-written, signature, 128) < 0) {
    log_fn(LOG_WARN, "Couldn't base64-encode signature");
    return -1;
  }
  written += strlen(s+written);
789
  strlcat(s+written, "-----END SIGNATURE-----\n", maxlen-written);
790
  written += strlen(s+written);
Roger Dingledine's avatar
Roger Dingledine committed
791

792
  if (written+2 > maxlen)
793
794
795
796
797
798
    return -1;
  /* include a last '\n' */
  s[written] = '\n';
  s[written+1] = 0;

#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
799
  cp = s_tmp = s_dup = tor_strdup(s);
800
  ri_tmp = router_parse_entry_from_string(cp, NULL);
801
  if (!ri_tmp) {
Roger Dingledine's avatar
Roger Dingledine committed
802
    log_fn(LOG_ERR, "We just generated a router descriptor we can't parse: <<%s>>",
803
804
805
           s);
    return -1;
  }
Roger Dingledine's avatar
Roger Dingledine committed
806
  tor_free(s_dup);
807
808
809
810
811
812
  routerinfo_free(ri_tmp);
#endif

  return written+1;
}

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
int is_legal_nickname(const char *s)
{
  size_t len;
  tor_assert(s);
  len = strlen(s);
  return len > 0 && len <= MAX_NICKNAME_LEN &&
    strspn(s,LEGAL_NICKNAME_CHARACTERS)==len;
}
int is_legal_nickname_or_hexdigest(const char *s)
{
  size_t len;
  tor_assert(s);
  if (*s!='$')
    return is_legal_nickname(s);

  len = strlen(s);
  return len == HEX_DIGEST_LEN+1 && strspn(s+1,HEX_CHARACTERS)==len-1;
}

832
833
834
835
836
837
838
839
840
841
842
843
844
void router_free_all_keys(void)
{
  if (onionkey)
    crypto_free_pk_env(onionkey);
  if (lastonionkey)
    crypto_free_pk_env(lastonionkey);
  if (identitykey)
    crypto_free_pk_env(identitykey);
  if (key_lock)
    tor_mutex_free(key_lock);
  if (desc_routerinfo)
    routerinfo_free(desc_routerinfo);
}