networkstatus.c 68 KB
Newer Older
1
2
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4
 * Copyright (c) 2007-2008, The Tor Project, Inc. */
5
6
7
8
9
10
/* See LICENSE for licensing information */
/* $Id$ */
const char networkstatus_c_id[] =
  "$Id$";

/**
11
12
 * \file networkstatus.c
 * \brief Functions and structures for handling network status documents as a
13
 * client or cache.
14
15
16
17
 */

#include "or.h"

18
/* For tracking v2 networkstatus documents.  Only caches do this now. */
19

20
21
/** Map from descriptor digest of routers listed in the v2 networkstatus
 * documents to download_status_t* */
22
23
static digestmap_t *v2_download_status_map = NULL;
/** Global list of all of the current v2 network_status documents that we know
24
 * about.  This list is kept sorted by published_on. */
25
static smartlist_t *networkstatus_v2_list = NULL;
26
27
28
29
/** True iff any member of networkstatus_v2_list has changed since the last
 * time we called download_status_map_update_from_v2_networkstatus() */
static int networkstatus_v2_list_has_changed = 0;

30
/** Map from lowercase nickname to identity digest of named server, if any. */
31
static strmap_t *named_server_map = NULL;
32
33
34
/** Map from lowercase nickname to (void*)1 for all names that are listed
 * as unnamed for some server in the consensus. */
static strmap_t *unnamed_server_map = NULL;
35
36

/** Most recently received and validated v3 consensus network status. */
37
static networkstatus_t *current_consensus = NULL;
38
39
40

/** A v3 consensus networkstatus that we've received, but which we don't
 * have enough certificates to be happy about. */
41
static networkstatus_t *consensus_waiting_for_certs = NULL;
42
/** The encoded version of consensus_waiting_for_certs. */
43
static char *consensus_waiting_for_certs_body = NULL;
44
45
46
/** When did we set the current value of consensus_waiting_for_certs?  If this
 * is too recent, we shouldn't try to fetch a new consensus for a little while,
 * to give ourselves time to get certificates for this one. */
47
static time_t consensus_waiting_for_certs_set_at = 0;
48
49
/** Set to 1 if we've been holding on to consensus_waiting_for_certs so long
 * that we should treat it as maybe being bad. */
50
static int consensus_waiting_for_certs_dl_failed = 0;
51
52
53
54
55
56

/** The last time we tried to download a networkstatus, or 0 for "never".  We
 * use this to rate-limit download attempts for directory caches (including
 * mirrors).  Clients don't use this now. */
static time_t last_networkstatus_download_attempted = 0;

57
58
59
/** A time before which we shouldn't try to replace the current consensus:
 * this will be at some point after the next consensus becomes valid, but
 * before the current consensus becomes invalid. */
60
static time_t time_to_download_next_consensus = 0;
61
/** Download status for the current consensus networkstatus. */
62
static download_status_t consensus_dl_status = { 0, 0, DL_SCHED_CONSENSUS };
63
64

/** True iff we have logged a warning about this OR's version being older than
Roger Dingledine's avatar
Roger Dingledine committed
65
 * listed by the authorities. */
66
67
static int have_warned_about_old_version = 0;
/** True iff we have logged a warning about this OR's version being newer than
Roger Dingledine's avatar
Roger Dingledine committed
68
 * listed by the authorities. */
69
70
static int have_warned_about_new_version = 0;

71
static void download_status_map_update_from_v2_networkstatus(void);
72
static void routerstatus_list_update_named_server_map(void);
73

74
75
/** Forget that we've warned about anything networkstatus-related, so we will
 * give fresh warnings if the same behavior happens again. */
76
77
78
void
networkstatus_reset_warnings(void)
{
79
80
81
82
83
  if (current_consensus) {
    SMARTLIST_FOREACH(current_consensus->routerstatus_list,
                      routerstatus_t *, rs,
                      rs->name_lookup_warned = 0);
  }
84
85
86
87
88

  have_warned_about_old_version = 0;
  have_warned_about_new_version = 0;
}

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/** Reset the descriptor download failure count on all networkstatus docs, so
 * that we can retry any long-failed documents immediately.
 */
void
networkstatus_reset_download_failures(void)
{
  const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
  SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
     SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
       {
         if (!router_get_by_descriptor_digest(rs->descriptor_digest))
           rs->need_to_mirror = 1;
       }));;

  download_status_reset(&consensus_dl_status);
  if (v2_download_status_map) {
    digestmap_iter_t *iter;
    digestmap_t *map = v2_download_status_map;
    const char *key;
    void *val;
    download_status_t *dls;
110
111
    for (iter = digestmap_iter_init(map); !digestmap_iter_done(iter);
         iter = digestmap_iter_next(map, iter) ) {
112
113
114
115
116
117
118
      digestmap_iter_get(iter, &key, &val);
      dls = val;
      download_status_reset(dls);
    }
  }
}

119
120
121
/** Repopulate our list of network_status_t objects from the list cached on
 * disk.  Return 0 on success, -1 on failure. */
int
122
router_reload_v2_networkstatus(void)
123
124
125
126
{
  smartlist_t *entries;
  struct stat st;
  char *s;
127
  char *filename = get_datadir_fname("cached-status");
128
129
  int maybe_delete = !directory_caches_v2_dir_info(get_options());
  time_t now = time(NULL);
130
131
  if (!networkstatus_v2_list)
    networkstatus_v2_list = smartlist_create();
132
133

  entries = tor_listdir(filename);
134
135
136
137
138
139
  if (!entries) { /* dir doesn't exist */
    tor_free(filename);
    return 0;
  } else if (!smartlist_len(entries) && maybe_delete) {
    rmdir(filename);
    tor_free(filename);
140
    smartlist_free(entries);
141
    return 0;
142
143
  }
  tor_free(filename);
144
145
  SMARTLIST_FOREACH(entries, const char *, fn, {
      char buf[DIGEST_LEN];
146
147
148
149
150
151
      if (maybe_delete) {
        filename = get_datadir_fname2("cached-status", fn);
        remove_file_if_very_old(filename, now);
        tor_free(filename);
        continue;
      }
152
153
154
155
156
157
      if (strlen(fn) != HEX_DIGEST_LEN ||
          base16_decode(buf, sizeof(buf), fn, strlen(fn))) {
        log_info(LD_DIR,
                 "Skipping cached-status file with unexpected name \"%s\"",fn);
        continue;
      }
158
      filename = get_datadir_fname2("cached-status", fn);
159
160
      s = read_file_to_str(filename, 0, &st);
      if (s) {
161
162
        if (router_set_networkstatus_v2(s, st.st_mtime, NS_FROM_CACHE,
                                        NULL)<0) {
163
164
165
166
          log_warn(LD_FS, "Couldn't load networkstatus from \"%s\"",filename);
        }
        tor_free(s);
      }
167
      tor_free(filename);
168
169
170
    });
  SMARTLIST_FOREACH(entries, char *, fn, tor_free(fn));
  smartlist_free(entries);
171
  networkstatus_v2_list_clean(time(NULL));
172
  routers_update_all_from_networkstatus(time(NULL), 2);
173
174
175
176
177
178
179
  return 0;
}

/** Read the cached v3 consensus networkstatus from the disk. */
int
router_reload_consensus_networkstatus(void)
{
180
  char *filename;
181
  char *s;
182
183
  struct stat st;
  or_options_t *options = get_options();
184
  const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS;
185

186
  /* FFFF Suppress warnings if cached consensus is bad? */
187

188
  filename = get_datadir_fname("cached-consensus");
189
190
  s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
  if (s) {
191
    if (networkstatus_set_current_consensus(s, flags)) {
192
193
194
195
196
      log_warn(LD_FS, "Couldn't load consensus networkstatus from \"%s\"",
               filename);
    }
    tor_free(s);
  }
197
  tor_free(filename);
198

199
  filename = get_datadir_fname("unverified-consensus");
200
201
  s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
  if (s) {
202
203
    if (networkstatus_set_current_consensus(s,
                                     flags|NSSET_WAS_WAITING_FOR_CERTS)) {
204
      log_info(LD_FS, "Couldn't load consensus networkstatus from \"%s\"",
205
206
207
208
               filename);
    }
    tor_free(s);
  }
209
  tor_free(filename);
210
211
212
213
214
215
216

  if (!current_consensus ||
      (stat(options->FallbackNetworkstatusFile, &st)==0 &&
       st.st_mtime > current_consensus->valid_after)) {
    s = read_file_to_str(options->FallbackNetworkstatusFile,
                         RFTS_IGNORE_MISSING, NULL);
    if (s) {
217
      if (networkstatus_set_current_consensus(s, flags)) {
218
219
220
        log_info(LD_FS, "Couldn't load consensus networkstatus from \"%s\"",
                 options->FallbackNetworkstatusFile);
      } else {
Roger Dingledine's avatar
Roger Dingledine committed
221
222
        log_notice(LD_FS,
                   "Loaded fallback consensus networkstatus from \"%s\"",
223
224
225
226
227
228
                   options->FallbackNetworkstatusFile);
      }
      tor_free(s);
    }
  }

229
230
231
232
233
234
235
  if (!current_consensus) {
    if (!named_server_map)
      named_server_map = strmap_new();
    if (!unnamed_server_map)
      unnamed_server_map = strmap_new();
  }

236
237
  update_certificate_downloads(time(NULL));

238
  routers_update_all_from_networkstatus(time(NULL), 3);
239
240
241
242

  return 0;
}

243
/** Free all storage held by the vote_routerstatus object <b>rs</b>. */
244
245
246
247
248
249
250
251
static void
vote_routerstatus_free(vote_routerstatus_t *rs)
{
  tor_free(rs->version);
  tor_free(rs->status.exitsummary);
  tor_free(rs);
}

252
253
254
255
/** Free all storage held by the routerstatus object <b>rs</b>. */
void
routerstatus_free(routerstatus_t *rs)
{
256
  tor_free(rs->exitsummary);
257
258
259
260
261
  tor_free(rs);
}

/** Free all storage held by the networkstatus object <b>ns</b>. */
void
262
networkstatus_v2_free(networkstatus_v2_t *ns)
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
{
  tor_free(ns->source_address);
  tor_free(ns->contact);
  if (ns->signing_key)
    crypto_free_pk_env(ns->signing_key);
  tor_free(ns->client_versions);
  tor_free(ns->server_versions);
  if (ns->entries) {
    SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
                      routerstatus_free(rs));
    smartlist_free(ns->entries);
  }
  tor_free(ns);
}

278
279
/** Clear all storage held in <b>ns</b>. */
void
280
networkstatus_vote_free(networkstatus_t *ns)
281
282
283
284
285
286
287
288
289
290
{
  if (!ns)
    return;

  tor_free(ns->client_versions);
  tor_free(ns->server_versions);
  if (ns->known_flags) {
    SMARTLIST_FOREACH(ns->known_flags, char *, c, tor_free(c));
    smartlist_free(ns->known_flags);
  }
291
292
293
294
  if (ns->supported_methods) {
    SMARTLIST_FOREACH(ns->supported_methods, char *, c, tor_free(c));
    smartlist_free(ns->supported_methods);
  }
295
296
297
298
299
300
  if (ns->voters) {
    SMARTLIST_FOREACH(ns->voters, networkstatus_voter_info_t *, voter,
    {
      tor_free(voter->nickname);
      tor_free(voter->address);
      tor_free(voter->contact);
301
302
      tor_free(voter->signature);
      tor_free(voter);
303
304
305
306
307
308
309
    });
    smartlist_free(ns->voters);
  }
  if (ns->cert)
    authority_cert_free(ns->cert);

  if (ns->routerstatus_list) {
310
    if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
311
      SMARTLIST_FOREACH(ns->routerstatus_list, vote_routerstatus_t *, rs,
312
                        vote_routerstatus_free(rs));
313
314
    } else {
      SMARTLIST_FOREACH(ns->routerstatus_list, routerstatus_t *, rs,
315
                        routerstatus_free(rs));
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
    }

    smartlist_free(ns->routerstatus_list);
  }
  if (ns->desc_digest_map)
    digestmap_free(ns->desc_digest_map, NULL);

  memset(ns, 11, sizeof(*ns));
  tor_free(ns);
}

/** Return the voter info from <b>vote</b> for the voter whose identity digest
 * is <b>identity</b>, or NULL if no such voter is associated with
 * <b>vote</b>. */
networkstatus_voter_info_t *
331
networkstatus_get_voter_by_id(networkstatus_t *vote,
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
                              const char *identity)
{
  if (!vote || !vote->voters)
    return NULL;
  SMARTLIST_FOREACH(vote->voters, networkstatus_voter_info_t *, voter,
    if (!memcmp(voter->identity_digest, identity, DIGEST_LEN))
      return voter);
  return NULL;
}

/** Check whether the signature on <b>voter</b> is correctly signed by
 * the signing key of <b>cert</b>. Return -1 if <b>cert</b> doesn't match the
 * signing key; otherwise set the good_signature or bad_signature flag on
 * <b>voter</b>, and return 0. */
/* (private; exposed for testing.) */
int
348
networkstatus_check_voter_signature(networkstatus_t *consensus,
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
                                    networkstatus_voter_info_t *voter,
                                    authority_cert_t *cert)
{
  char d[DIGEST_LEN];
  char *signed_digest;
  size_t signed_digest_len;
  if (crypto_pk_get_digest(cert->signing_key, d)<0)
    return -1;
  if (memcmp(voter->signing_key_digest, d, DIGEST_LEN))
    return -1;
  signed_digest_len = crypto_pk_keysize(cert->signing_key);
  signed_digest = tor_malloc(signed_digest_len);
  if (crypto_pk_public_checksig(cert->signing_key,
                                signed_digest,
                                voter->signature,
                                voter->signature_len) != DIGEST_LEN ||
      memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) {
    log_warn(LD_DIR, "Got a bad signature on a networkstatus vote");
    voter->bad_signature = 1;
  } else {
    voter->good_signature = 1;
  }
371
  tor_free(signed_digest);
372
373
374
375
376
377
378
379
380
381
382
383
  return 0;
}

/** Given a v3 networkstatus consensus in <b>consensus</b>, check every
 * as-yet-unchecked signature on <b>consensus</b>.  Return 1 if there is a
 * signature from every recognized authority on it, 0 if there are
 * enough good signatures from recognized authorities on it, -1 if we might
 * get enough good signatures by fetching missing certificates, and -2
 * otherwise.  Log messages at INFO or WARN: if <b>warn</b> is over 1, warn
 * about every problem; if warn is at least 1, warn only if we can't get
 * enough signatures; if warn is negative, log nothing at all. */
int
384
networkstatus_check_consensus_signature(networkstatus_t *consensus,
385
386
387
388
389
390
391
392
393
394
395
396
397
                                        int warn)
{
  int n_good = 0;
  int n_missing_key = 0;
  int n_bad = 0;
  int n_unknown = 0;
  int n_no_signature = 0;
  int n_v3_authorities = get_n_authorities(V3_AUTHORITY);
  int n_required = n_v3_authorities/2 + 1;
  smartlist_t *need_certs_from = smartlist_create();
  smartlist_t *unrecognized = smartlist_create();
  smartlist_t *missing_authorities = smartlist_create();
  int severity;
398
  time_t now = time(NULL);
399

400
  tor_assert(consensus->type == NS_TYPE_CONSENSUS);
401
402
403
404
405

  SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, voter,
  {
    if (!voter->good_signature && !voter->bad_signature && voter->signature) {
      /* we can try to check the signature. */
406
407
      int is_v3_auth = trusteddirserver_get_by_v3_auth_digest(
                                          voter->identity_digest) != NULL;
408
409
410
      authority_cert_t *cert =
        authority_cert_get_by_digests(voter->identity_digest,
                                      voter->signing_key_digest);
411
412
413
414
      if (!is_v3_auth) {
        smartlist_add(unrecognized, voter);
        ++n_unknown;
        continue;
Nick Mathewson's avatar
Nick Mathewson committed
415
      } else if (!cert || cert->expires < now) {
416
417
        smartlist_add(need_certs_from, voter);
        ++n_missing_key;
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
        continue;
      }
      if (networkstatus_check_voter_signature(consensus, voter, cert) < 0) {
        smartlist_add(need_certs_from, voter);
        ++n_missing_key;
        continue;
      }
    }
    if (voter->good_signature)
      ++n_good;
    else if (voter->bad_signature)
      ++n_bad;
    else
      ++n_no_signature;
  });

  /* Now see whether we're missing any voters entirely. */
  SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
                    trusted_dir_server_t *, ds,
    {
      if ((ds->type & V3_AUTHORITY) &&
          !networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest))
        smartlist_add(missing_authorities, ds);
    });

  if (warn > 1 || (warn >= 0 && n_good < n_required))
    severity = LOG_WARN;
  else
    severity = LOG_INFO;

  if (warn >= 0) {
    SMARTLIST_FOREACH(unrecognized, networkstatus_voter_info_t *, voter,
      {
451
452
453
454
455
        log_info(LD_DIR, "Consensus includes unrecognized authority '%s' "
                 "at %s:%d (contact %s; identity %s)",
                 voter->nickname, voter->address, (int)voter->dir_port,
                 voter->contact?voter->contact:"n/a",
                 hex_str(voter->identity_digest, DIGEST_LEN));
456
457
458
459
460
461
462
463
464
465
466
      });
    SMARTLIST_FOREACH(need_certs_from, networkstatus_voter_info_t *, voter,
      {
        log_info(LD_DIR, "Looks like we need to download a new certificate "
                 "from authority '%s' at %s:%d (contact %s; identity %s)",
                 voter->nickname, voter->address, (int)voter->dir_port,
                 voter->contact?voter->contact:"n/a",
                 hex_str(voter->identity_digest, DIGEST_LEN));
      });
    SMARTLIST_FOREACH(missing_authorities, trusted_dir_server_t *, ds,
      {
467
468
469
470
        log_info(LD_DIR, "Consensus does not include configured "
                 "authority '%s' at %s:%d (identity %s)",
                 ds->nickname, ds->address, (int)ds->dir_port,
                 hex_str(ds->v3_identity_digest, DIGEST_LEN));
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
      });
    log(severity, LD_DIR,
        "%d unknown, %d missing key, %d good, %d bad, %d no signature, "
        "%d required", n_unknown, n_missing_key, n_good, n_bad,
        n_no_signature, n_required);
  }

  smartlist_free(unrecognized);
  smartlist_free(need_certs_from);
  smartlist_free(missing_authorities);

  if (n_good == n_v3_authorities)
    return 1;
  else if (n_good >= n_required)
    return 0;
  else if (n_good + n_missing_key >= n_required)
    return -1;
  else
    return -2;
}

492
493
494
495
496
497
498
/** Helper: return a newly allocated string containing the name of the filename
 * where we plan to cache the network status with the given identity digest. */
char *
networkstatus_get_cache_filename(const char *identity_digest)
{
  char fp[HEX_DIGEST_LEN+1];
  base16_encode(fp, HEX_DIGEST_LEN+1, identity_digest, DIGEST_LEN);
499
  return get_datadir_fname2("cached-status", fp);
500
501
502
503
504
}

/** Helper for smartlist_sort: Compare two networkstatus objects by
 * publication date. */
static int
505
_compare_networkstatus_v2_published_on(const void **_a, const void **_b)
506
{
507
  const networkstatus_v2_t *a = *_a, *b = *_b;
508
509
510
511
512
513
514
515
  if (a->published_on < b->published_on)
    return -1;
  else if (a->published_on > b->published_on)
    return 1;
  else
    return 0;
}

516
/** Add the parsed v2 networkstatus in <b>ns</b> (with original document in
517
 * <b>s</b>) to the disk cache (and the in-memory directory server cache) as
518
519
520
 * appropriate. */
static int
add_networkstatus_to_cache(const char *s,
521
                           v2_networkstatus_source_t source,
522
                           networkstatus_v2_t *ns)
523
524
525
526
527
528
529
530
531
{
  if (source != NS_FROM_CACHE) {
    char *fn = networkstatus_get_cache_filename(ns->identity_digest);
    if (write_str_to_file(fn, s, 0)<0) {
      log_notice(LD_FS, "Couldn't write cached network status to \"%s\"", fn);
    }
    tor_free(fn);
  }

532
  if (directory_caches_v2_dir_info(get_options()))
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
    dirserv_set_cached_networkstatus_v2(s,
                                        ns->identity_digest,
                                        ns->published_on);

  return 0;
}

/** How far in the future do we allow a network-status to get before removing
 * it? (seconds) */
#define NETWORKSTATUS_ALLOW_SKEW (24*60*60)

/** Given a string <b>s</b> containing a network status that we received at
 * <b>arrived_at</b> from <b>source</b>, try to parse it, see if we want to
 * store it, and put it into our cache as necessary.
 *
 * If <b>source</b> is NS_FROM_DIR or NS_FROM_CACHE, do not replace our
 * own networkstatus_t (if we're an authoritative directory server).
 *
 * If <b>source</b> is NS_FROM_CACHE, do not write our networkstatus_t to the
 * cache.
 *
 * If <b>requested_fingerprints</b> is provided, it must contain a list of
 * uppercased identity fingerprints.  Do not update any networkstatus whose
 * fingerprint is not on the list; after updating a networkstatus, remove its
 * fingerprint from the list.
 *
 * Return 0 on success, -1 on failure.
 *
 * Callers should make sure that routers_update_all_from_networkstatus() is
 * invoked after this function succeeds.
 */
int
565
router_set_networkstatus_v2(const char *s, time_t arrived_at,
566
567
                            v2_networkstatus_source_t source,
                            smartlist_t *requested_fingerprints)
568
{
569
  networkstatus_v2_t *ns;
570
571
572
573
574
575
576
577
  int i, found;
  time_t now;
  int skewed = 0;
  trusted_dir_server_t *trusted_dir = NULL;
  const char *source_desc = NULL;
  char fp[HEX_DIGEST_LEN+1];
  char published[ISO_TIME_LEN+1];

578
  if (!directory_caches_v2_dir_info(get_options()))
579
580
581
    return 0; /* Don't bother storing it. */

  ns = networkstatus_v2_parse_from_string(s);
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
  if (!ns) {
    log_warn(LD_DIR, "Couldn't parse network status.");
    return -1;
  }
  base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
  if (!(trusted_dir =
        router_get_trusteddirserver_by_digest(ns->identity_digest)) ||
      !(trusted_dir->type & V2_AUTHORITY)) {
    log_info(LD_DIR, "Network status was signed, but not by an authoritative "
             "directory we recognize.");
    source_desc = fp;
  } else {
    source_desc = trusted_dir->description;
  }
  now = time(NULL);
  if (arrived_at > now)
    arrived_at = now;

  ns->received_on = arrived_at;

  format_iso_time(published, ns->published_on);

  if (ns->published_on > now + NETWORKSTATUS_ALLOW_SKEW) {
605
606
607
608
609
    char dbuf[64];
    long delta = now - ns->published_on;
    format_time_interval(dbuf, sizeof(dbuf), delta);
    log_warn(LD_GENERAL, "Network status from %s was published %s in the "
             "future (%s GMT). Check your time and date settings! "
610
             "Not caching.",
611
             source_desc, dbuf, published);
612
    control_event_general_status(LOG_WARN,
613
614
                       "CLOCK_SKEW MIN_SKEW=%ld SOURCE=NETWORKSTATUS:%s:%d",
                       delta, ns->source_address, ns->source_dirport);
615
616
617
    skewed = 1;
  }

618
619
  if (!networkstatus_v2_list)
    networkstatus_v2_list = smartlist_create();
620
621
622
623

  if ( (source == NS_FROM_DIR_BY_FP || source == NS_FROM_DIR_ALL) &&
       router_digest_is_me(ns->identity_digest)) {
    /* Don't replace our own networkstatus when we get it from somebody else.*/
624
    networkstatus_v2_free(ns);
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
    return 0;
  }

  if (requested_fingerprints) {
    if (smartlist_string_isin(requested_fingerprints, fp)) {
      smartlist_string_remove(requested_fingerprints, fp);
    } else {
      if (source != NS_FROM_DIR_ALL) {
        char *requested =
          smartlist_join_strings(requested_fingerprints," ",0,NULL);
        log_warn(LD_DIR,
               "We received a network status with a fingerprint (%s) that we "
               "never requested. (We asked for: %s.) Dropping.",
               fp, requested);
        tor_free(requested);
        return 0;
      }
    }
  }

  if (!trusted_dir) {
646
    if (!skewed) {
647
648
649
650
651
652
653
      /* We got a non-trusted networkstatus, and we're a directory cache.
       * This means that we asked an authority, and it told us about another
       * authority we didn't recognize. */
      log_info(LD_DIR,
               "We do not recognize authority (%s) but we are willing "
               "to cache it.", fp);
      add_networkstatus_to_cache(s, source, ns);
654
      networkstatus_v2_free(ns);
655
656
657
658
659
    }
    return 0;
  }

  found = 0;
660
661
  for (i=0; i < smartlist_len(networkstatus_v2_list); ++i) {
    networkstatus_v2_t *old_ns = smartlist_get(networkstatus_v2_list, i);
662
663
664
665
666

    if (!memcmp(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) {
      if (!memcmp(old_ns->networkstatus_digest,
                  ns->networkstatus_digest, DIGEST_LEN)) {
        /* Same one we had before. */
667
        networkstatus_v2_free(ns);
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
        tor_assert(trusted_dir);
        log_info(LD_DIR,
                 "Not replacing network-status from %s (published %s); "
                 "we already have it.",
                 trusted_dir->description, published);
        if (old_ns->received_on < arrived_at) {
          if (source != NS_FROM_CACHE) {
            char *fn;
            fn = networkstatus_get_cache_filename(old_ns->identity_digest);
            /* We use mtime to tell when it arrived, so update that. */
            touch_file(fn);
            tor_free(fn);
          }
          old_ns->received_on = arrived_at;
        }
683
        download_status_failed(&trusted_dir->v2_ns_dl_status, 0);
684
685
686
687
688
689
690
691
692
693
        return 0;
      } else if (old_ns->published_on >= ns->published_on) {
        char old_published[ISO_TIME_LEN+1];
        format_iso_time(old_published, old_ns->published_on);
        tor_assert(trusted_dir);
        log_info(LD_DIR,
                 "Not replacing network-status from %s (published %s);"
                 " we have a newer one (published %s) for this authority.",
                 trusted_dir->description, published,
                 old_published);
694
        networkstatus_v2_free(ns);
695
        download_status_failed(&trusted_dir->v2_ns_dl_status, 0);
696
697
        return 0;
      } else {
698
699
        networkstatus_v2_free(old_ns);
        smartlist_set(networkstatus_v2_list, i, ns);
700
701
702
703
704
705
        found = 1;
        break;
      }
    }
  }

706
707
708
  if (source != NS_FROM_CACHE && trusted_dir) {
    download_status_reset(&trusted_dir->v2_ns_dl_status);
  }
709
710

  if (!found)
711
    smartlist_add(networkstatus_v2_list, ns);
712

713
714
715
716
717
718
719
/*XXXX021 magic. */
/*DOCDOC */
#define V2_NETWORKSTATUS_LIFETIME (3*60*60)

  {
    time_t live_until = ns->published_on + V2_NETWORKSTATUS_LIFETIME;
    SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
720
    {
721
722
723
724
725
726
      signed_descriptor_t *sd =
        router_get_by_descriptor_digest(rs->descriptor_digest);
      if (sd) {
        if (sd->last_listed_as_valid_until < live_until)
          sd->last_listed_as_valid_until = live_until;
      } else {
727
        rs->need_to_mirror = 1;
728
      }
729
    });
730
  }
731
732
733
734
735
736

  log_info(LD_DIR, "Setting networkstatus %s %s (published %s)",
           source == NS_FROM_CACHE?"cached from":
           ((source == NS_FROM_DIR_BY_FP || source == NS_FROM_DIR_ALL) ?
             "downloaded from":"generated for"),
           trusted_dir->description, published);
737
  networkstatus_v2_list_has_changed = 1;
738

739
740
  smartlist_sort(networkstatus_v2_list,
                 _compare_networkstatus_v2_published_on);
741
742
743
744
745
746
747
748
749
750

  if (!skewed)
    add_networkstatus_to_cache(s, source, ns);

  return 0;
}

/** Remove all very-old network_status_t objects from memory and from the
 * disk cache. */
void
751
networkstatus_v2_list_clean(time_t now)
752
753
{
  int i;
754
  if (!networkstatus_v2_list)
755
756
    return;

757
758
  for (i = 0; i < smartlist_len(networkstatus_v2_list); ++i) {
    networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i);
759
760
761
762
763
    char *fname = NULL;
    if (ns->published_on + MAX_NETWORKSTATUS_AGE > now)
      continue;
    /* Okay, this one is too old.  Remove it from the list, and delete it
     * from the cache. */
764
    smartlist_del(networkstatus_v2_list, i--);
765
766
767
768
769
770
    fname = networkstatus_get_cache_filename(ns->identity_digest);
    if (file_status(fname) == FN_FILE) {
      log_info(LD_DIR, "Removing too-old networkstatus in %s", fname);
      unlink(fname);
    }
    tor_free(fname);
771
    if (directory_caches_v2_dir_info(get_options())) {
772
773
      dirserv_set_cached_networkstatus_v2(NULL, ns->identity_digest, 0);
    }
774
    networkstatus_v2_free(ns);
775
776
777
778
779
780
781
782
  }

  /* And now go through the directory cache for any cached untrusted
   * networkstatuses and other network info. */
  dirserv_clear_old_networkstatuses(now - MAX_NETWORKSTATUS_AGE);
  dirserv_clear_old_v1_info(now);
}

783
784
/** Helper for bsearching a list of routerstatus_t pointers: compare a
 * digest in the key to the identity digest of a routerstatus_t. */
785
786
787
788
789
790
791
792
793
794
795
static int
_compare_digest_to_routerstatus_entry(const void *_key, const void **_member)
{
  const char *key = _key;
  const routerstatus_t *rs = *_member;
  return memcmp(key, rs->identity_digest, DIGEST_LEN);
}

/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
 * NULL if none was found. */
routerstatus_t *
796
networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
797
798
799
800
801
{
  return smartlist_bsearch(ns->entries, digest,
                           _compare_digest_to_routerstatus_entry);
}

802
803
804
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
 * NULL if none was found. */
routerstatus_t *
805
networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
806
807
808
809
810
{
  return smartlist_bsearch(ns->routerstatus_list, digest,
                           _compare_digest_to_routerstatus_entry);
}

811
/*XXXX make this static once functions are moved into this file. */
812
813
/** Search the routerstatuses in <b>ns</b> for one whose identity digest is
 * <b>digest</b>.  Return value and set *<b>found_out</b> as for
Roger Dingledine's avatar
Roger Dingledine committed
814
 * smartlist_bsearch_idx(). */
815
int
816
networkstatus_vote_find_entry_idx(networkstatus_t *ns,
817
818
819
820
821
822
823
                                  const char *digest, int *found_out)
{
  return smartlist_bsearch_idx(ns->routerstatus_list, digest,
                               _compare_digest_to_routerstatus_entry,
                               found_out);
}

824
/** Return a list of the v2 networkstatus documents. */
825
826
827
const smartlist_t *
networkstatus_get_v2_list(void)
{
828
829
830
  if (!networkstatus_v2_list)
    networkstatus_v2_list = smartlist_create();
  return networkstatus_v2_list;
831
832
}

833
834
835
836
837
/** Return the consensus view of the status of the router whose current
 * <i>descriptor</i> digest is <b>digest</b>, or NULL if no such router is
 * known. */
routerstatus_t *
router_get_consensus_status_by_descriptor_digest(const char *digest)
838
{
839
840
841
842
843
844
845
846
847
848
  if (!current_consensus) return NULL;
  if (!current_consensus->desc_digest_map) {
    digestmap_t * m = current_consensus->desc_digest_map = digestmap_new();
    SMARTLIST_FOREACH(current_consensus->routerstatus_list,
                      routerstatus_t *, rs,
     {
       digestmap_set(m, rs->descriptor_digest, rs);
     });
  }
  return digestmap_get(current_consensus->desc_digest_map, digest);
849
850
}

851
852
/** Given the digest of a router descriptor, return its current download
 * status, or NULL if the digest is unrecognized. */
853
854
download_status_t *
router_get_dl_status_by_descriptor_digest(const char *d)
855
{
856
857
858
859
860
861
862
  routerstatus_t *rs;
  if ((rs = router_get_consensus_status_by_descriptor_digest(d)))
    return &rs->dl_status;
  if (v2_download_status_map)
    return digestmap_get(v2_download_status_map, d);

  return NULL;
863
864
}

865
866
/** Return the consensus view of the status of the router whose identity
 * digest is <b>digest</b>, or NULL if we don't know about any such router. */
867
routerstatus_t *
868
router_get_consensus_status_by_id(const char *digest)
869
{
870
  if (!current_consensus)
871
    return NULL;
872
873
  return smartlist_bsearch(current_consensus->routerstatus_list, digest,
                           _compare_digest_to_routerstatus_entry);
874
875
876
}

/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
877
 * the corresponding routerstatus_t, or NULL if none exists.  Warn the
878
879
 * user if <b>warn_if_unnamed</b> is set, and they have specified a router by
 * nickname, but the Named flag isn't set for that router. */
880
routerstatus_t *
881
router_get_consensus_status_by_nickname(const char *nickname,
882
                                        int warn_if_unnamed)
883
884
{
  char digest[DIGEST_LEN];
885
  routerstatus_t *best=NULL;
886
  smartlist_t *matches=NULL;
887
  const char *named_id=NULL;
888

889
  if (!current_consensus || !nickname)
890
891
    return NULL;

892
  /* Is this name really a hexadecimal identity digest? */
893
  if (nickname[0] == '$') {
894
    if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
895
      return NULL;
896
    return networkstatus_vote_find_entry(current_consensus, digest);
897
  } else if (strlen(nickname) == HEX_DIGEST_LEN &&
898
       (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
899
    return networkstatus_vote_find_entry(current_consensus, digest);
900
901
  }

902
  /* Is there a server that is Named with this name? */
903
904
905
906
907
  if (named_server_map)
    named_id = strmap_get_lc(named_server_map, nickname);
  if (named_id)
    return networkstatus_vote_find_entry(current_consensus, named_id);

908
  /* Okay; is this name listed as Unnamed? */
909
  if (unnamed_server_map &&
910
911
912
913
914
      strmap_get_lc(unnamed_server_map, nickname)) {
    log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
             "canonical name of any server we know.", escaped(nickname));
    return NULL;
  }
915

916
917
  /* This name is not canonical for any server; go through the list and
   * see who it matches. */
918
  /*XXXX This is inefficient; optimize it if it matters. */
919
  matches = smartlist_create();
920
921
  SMARTLIST_FOREACH(current_consensus->routerstatus_list,
                    routerstatus_t *, lrs,
922
    {
923
924
      if (!strcasecmp(lrs->nickname, nickname)) {
        if (lrs->is_named) {
925
          tor_fragile_assert() /* This should never happen. */
926
927
928
          smartlist_free(matches);
          return lrs;
        } else {
929
930
931
932
933
934
          if (lrs->is_unnamed) {
            tor_fragile_assert(); /* nor should this. */
            smartlist_clear(matches);
            best=NULL;
            break;
          }
935
936
937
938
939
940
          smartlist_add(matches, lrs);
          best = lrs;
        }
      }
    });

941
  if (smartlist_len(matches)>1 && warn_if_unnamed) {
942
    int any_unwarned=0;
943
    SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
944
945
946
947
948
949
950
951
952
953
954
955
956
957
      {
        if (! lrs->name_lookup_warned) {
          lrs->name_lookup_warned=1;
          any_unwarned=1;
        }
      });
    if (any_unwarned) {
      log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
               " but none is listed as named by the directory authorites. "
               "Choosing one arbitrarily.", nickname);
    }
  } else if (warn_if_unnamed && best && !best->name_lookup_warned) {
    char fp[HEX_DIGEST_LEN+1];
    base16_encode(fp, sizeof(fp),
958
                  best->identity_digest, DIGEST_LEN);
959
960
961
962
963
964
965
966
967
968
969
970
971
    log_warn(LD_CONFIG,
         "When looking up a status, you specified a server \"%s\" by name, "
         "but the directory authorities do not have any key registered for "
         "this nickname -- so it could be used by any server, "
         "not just the one you meant. "
         "To make sure you get the same server in the future, refer to "
         "it by key, as \"$%s\".", nickname, fp);
    best->name_lookup_warned = 1;
  }
  smartlist_free(matches);
  return best;
}

972
973
/** Return the identity digest that's mapped to officially by
 * <b>nickname</b>. */
974
975
976
977
978
979
980
981
const char *
networkstatus_get_router_digest_by_nickname(const char *nickname)
{
  if (!named_server_map)
    return NULL;
  return strmap_get_lc(named_server_map, nickname);
}

982
983
/** Return true iff <b>nickname</b> is disallowed from being the nickname
 * of any server. */
984
985
986
int
networkstatus_nickname_is_unnamed(const char *nickname)
{
987
988
989
  if (!unnamed_server_map)
    return 0;
  return strmap_get_lc(unnamed_server_map, nickname) != NULL;
990
991
}

992
993
/** How frequently do directory authorities re-download fresh networkstatus
 * documents? */
994
#define AUTHORITY_NS_CACHE_INTERVAL (10*60)
995
996
997

/** How frequently do non-authority directory caches re-download fresh
 * networkstatus documents? */
998
#define NONAUTHORITY_NS_CACHE_INTERVAL (60*60)
999
1000

/** We are a directory server, and so cache network_status documents.
For faster browsing, not all history is shown. View entire blame