routerparse.c 45.8 KB
Newer Older
1
/* Copyright (c) 2001 Matej Pfajfar.
Roger Dingledine's avatar
Roger Dingledine committed
2
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
5
6
7
8
/* See LICENSE for licensing information */

/**
 * \file routerparse.c
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 * \brief Code to parse and validate router descriptors, consenus directories,
 *   and similar objects.
 *
 * The objects parsed by this module use a common text-based metaformat,
 * documented in dir-spec.txt in torspec.git.  This module is itself divided
 * into two major kinds of function: code to handle the metaformat, and code
 * to convert from particular instances of the metaformat into the
 * objects that Tor uses.
 *
 * The generic parsing code works by calling a table-based tokenizer on the
 * input string.  Each token corresponds to a single line with a token, plus
 * optional arguments on that line, plus an optional base-64 encoded object
 * after that line.  Each token has a definition in a table of token_rule_t
 * entries that describes how many arguments it can take, whether it takes an
 * object, how many times it may appear, whether it must appear first, and so
 * on.
 *
 * The tokenizer function tokenize_string() converts its string input into a
 * smartlist full of instances of directory_token_t, according to a provided
 * table of token_rule_t.
 *
 * The generic parts of this module additionally include functions for
 * finding the start and end of signed information inside a signed object, and
 * computing the digest that will be signed.
 *
 * There are also functions for saving objects to disk that have caused
 * parsing to fail.
 *
 * The specific parts of this module describe conversions between
 * particular lists of directory_token_t and particular objects.  The
 * kinds of objects that can be parsed here are:
 *  <ul>
 *  <li>router descriptors (managed from routerlist.c)
 *  <li>extra-info documents (managed from routerlist.c)
 *  <li>microdescriptors (managed from microdesc.c)
 *  <li>vote and consensus networkstatus documents, and the routerstatus_t
 *    objects that they comprise (managed from networkstatus.c)
 *  <li>detached-signature objects used by authorities for gathering
 *    signatures on the networkstatus consensus (managed from dirvote.c)
 *  <li>authority key certificates (managed from routerlist.c)
 *  <li>hidden service descriptors (managed from rendcommon.c and rendcache.c)
 * </ul>
51
52
 **/

teor's avatar
teor committed
53
#define ROUTERDESC_TOKEN_TABLE_PRIVATE
54

55
56
#include "core/or/or.h"
#include "app/config/config.h"
57
#include "core/or/policies.h"
58
#include "core/or/versions.h"
59
#include "feature/dirparse/parsecommon.h"
60
#include "feature/dirparse/policy_parse.h"
61
#include "feature/dirparse/routerparse.h"
62
63
#include "feature/dirparse/sigcommon.h"
#include "feature/dirparse/unparseable.h"
64
65
66
#include "feature/nodelist/describe.h"
#include "feature/nodelist/nickname.h"
#include "feature/nodelist/routerinfo.h"
67
68
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/torcert.h"
69
#include "feature/relay/router.h"
70
71
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_ed25519.h"
72
73
74
#include "lib/crypt_ops/crypto_format.h"
#include "lib/memarea/memarea.h"
#include "lib/sandbox/sandbox.h"
75

76
77
78
79
#include "core/or/addr_policy_st.h"
#include "feature/nodelist/extrainfo_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist_st.h"
80

81
82
/****************************************************************************/

Nick Mathewson's avatar
Nick Mathewson committed
83
/** List of tokens recognized in router descriptors */
84
// clang-format off
85
const token_rule_t routerdesc_token_table[] = {
86
  T0N("reject",              K_REJECT,              ARGS,    NO_OBJ ),
87
  T0N("accept",              K_ACCEPT,              ARGS,    NO_OBJ ),
88
89
  T0N("reject6",             K_REJECT6,             ARGS,    NO_OBJ ),
  T0N("accept6",             K_ACCEPT6,             ARGS,    NO_OBJ ),
90
  T1_START( "router",        K_ROUTER,              GE(5),   NO_OBJ ),
91
  T01("ipv6-policy",         K_IPV6_POLICY,         CONCAT_ARGS, NO_OBJ),
92
93
  T1( "signing-key",         K_SIGNING_KEY,         NO_ARGS, NEED_KEY_1024 ),
  T1( "onion-key",           K_ONION_KEY,           NO_ARGS, NEED_KEY_1024 ),
94
  T1("ntor-onion-key",       K_ONION_KEY_NTOR,      GE(1), NO_OBJ ),
95
  T1_END( "router-signature",    K_ROUTER_SIGNATURE,    NO_ARGS, NEED_OBJ ),
96
  T1( "published",           K_PUBLISHED,       CONCAT_ARGS, NO_OBJ ),
97
  T01("uptime",              K_UPTIME,              GE(1),   NO_OBJ ),
98
  T01("fingerprint",         K_FINGERPRINT,     CONCAT_ARGS, NO_OBJ ),
99
  T01("hibernating",         K_HIBERNATING,         GE(1),   NO_OBJ ),
100
  T01("platform",            K_PLATFORM,        CONCAT_ARGS, NO_OBJ ),
101
  T1("proto",                K_PROTO,           CONCAT_ARGS, NO_OBJ ),
102
  T01("contact",             K_CONTACT,         CONCAT_ARGS, NO_OBJ ),
103
104
  T01("read-history",        K_READ_HISTORY,        ARGS,    NO_OBJ ),
  T01("write-history",       K_WRITE_HISTORY,       ARGS,    NO_OBJ ),
105
  T01("extra-info-digest",   K_EXTRA_INFO_DIGEST,   GE(1),   NO_OBJ ),
106
  T01("hidden-service-dir",  K_HIDDEN_SERVICE_DIR,  NO_ARGS, NO_OBJ ),
107
108
109
110
111
  T1("identity-ed25519",     K_IDENTITY_ED25519,    NO_ARGS, NEED_OBJ ),
  T1("master-key-ed25519",   K_MASTER_KEY_ED25519,  GE(1),   NO_OBJ ),
  T1("router-sig-ed25519",   K_ROUTER_SIG_ED25519,  GE(1),   NO_OBJ ),
  T1("onion-key-crosscert",  K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
  T1("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
112
                                                    EQ(1),   NEED_OBJ ),
113

114
  T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS,    NO_ARGS, NO_OBJ ),
115
116

  T01("family",              K_FAMILY,              ARGS,    NO_OBJ ),
117
  T01("caches-extra-info",   K_CACHES_EXTRA_INFO,   NO_ARGS, NO_OBJ ),
118
  T0N("or-address",          K_OR_ADDRESS,          GE(1),   NO_OBJ ),
119
120

  T0N("opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK ),
121
  T1( "bandwidth",           K_BANDWIDTH,           GE(3),   NO_OBJ ),
122
  A01("@purpose",            A_PURPOSE,             GE(1),   NO_OBJ ),
123
  T01("tunnelled-dir-server",K_DIR_TUNNELLED,       NO_ARGS, NO_OBJ ),
124
125
126

  END_OF_TABLE
};
127
// clang-format on
128

Nick Mathewson's avatar
Nick Mathewson committed
129
/** List of tokens recognized in extra-info documents. */
130
// clang-format off
131
static token_rule_t extrainfo_token_table[] = {
132
  T1_END( "router-signature",    K_ROUTER_SIGNATURE,    NO_ARGS, NEED_OBJ ),
133
  T1( "published",           K_PUBLISHED,       CONCAT_ARGS, NO_OBJ ),
134
135
  T1("identity-ed25519",    K_IDENTITY_ED25519,    NO_ARGS, NEED_OBJ ),
  T1("router-sig-ed25519",  K_ROUTER_SIG_ED25519,  GE(1),   NO_OBJ ),
136
137
138
  T0N("opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK ),
  T01("read-history",        K_READ_HISTORY,        ARGS,    NO_OBJ ),
  T01("write-history",       K_WRITE_HISTORY,       ARGS,    NO_OBJ ),
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  T01("dirreq-stats-end",    K_DIRREQ_END,          ARGS,    NO_OBJ ),
  T01("dirreq-v2-ips",       K_DIRREQ_V2_IPS,       ARGS,    NO_OBJ ),
  T01("dirreq-v3-ips",       K_DIRREQ_V3_IPS,       ARGS,    NO_OBJ ),
  T01("dirreq-v2-reqs",      K_DIRREQ_V2_REQS,      ARGS,    NO_OBJ ),
  T01("dirreq-v3-reqs",      K_DIRREQ_V3_REQS,      ARGS,    NO_OBJ ),
  T01("dirreq-v2-share",     K_DIRREQ_V2_SHARE,     ARGS,    NO_OBJ ),
  T01("dirreq-v3-share",     K_DIRREQ_V3_SHARE,     ARGS,    NO_OBJ ),
  T01("dirreq-v2-resp",      K_DIRREQ_V2_RESP,      ARGS,    NO_OBJ ),
  T01("dirreq-v3-resp",      K_DIRREQ_V3_RESP,      ARGS,    NO_OBJ ),
  T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR,       ARGS,    NO_OBJ ),
  T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR,       ARGS,    NO_OBJ ),
  T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN,     ARGS,    NO_OBJ ),
  T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN,     ARGS,    NO_OBJ ),
  T01("entry-stats-end",     K_ENTRY_END,           ARGS,    NO_OBJ ),
  T01("entry-ips",           K_ENTRY_IPS,           ARGS,    NO_OBJ ),
  T01("cell-stats-end",      K_CELL_END,            ARGS,    NO_OBJ ),
  T01("cell-processed-cells", K_CELL_PROCESSED,     ARGS,    NO_OBJ ),
  T01("cell-queued-cells",   K_CELL_QUEUED,         ARGS,    NO_OBJ ),
  T01("cell-time-in-queue",  K_CELL_TIME,           ARGS,    NO_OBJ ),
  T01("cell-circuits-per-decile", K_CELL_CIRCS,     ARGS,    NO_OBJ ),
  T01("exit-stats-end",      K_EXIT_END,            ARGS,    NO_OBJ ),
  T01("exit-kibibytes-written", K_EXIT_WRITTEN,     ARGS,    NO_OBJ ),
  T01("exit-kibibytes-read", K_EXIT_READ,           ARGS,    NO_OBJ ),
  T01("exit-streams-opened", K_EXIT_OPENED,         ARGS,    NO_OBJ ),

164
  T1_START( "extra-info",          K_EXTRA_INFO,          GE(2),   NO_OBJ ),
165
166
167

  END_OF_TABLE
};
168
// clang-format on
169
170
171

#undef T

172
173
174
/* static function prototypes */
static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
static smartlist_t *find_all_exitpolicy(smartlist_t *s);
175

176
/** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
177
 * <b>s</b>. Return 0 on success, -1 on failure.
178
 */
179
int
180
router_get_router_hash(const char *s, size_t s_len, char *digest)
181
{
182
  return router_get_hash_impl(s, s_len, digest,
183
184
                              "router ","\nrouter-signature", '\n',
                              DIGEST_SHA1);
185
186
}

187
188
/** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
 * extrainfo string at <b>s</b>.  Return 0 on success, -1 on failure. */
189
int
190
router_get_extrainfo_hash(const char *s, size_t s_len, char *digest)
191
{
192
  return router_get_hash_impl(s, s_len, digest, "extra-info",
193
                              "\nrouter-signature",'\n', DIGEST_SHA1);
194
195
}

196
197
198
199
200
/** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
 * or to the first of the annotations proceeding the next router or
 * extra-info---whichever comes first.  Set <b>is_extrainfo_out</b> to true if
 * we found an extrainfo, or false if found a router. Do not scan beyond
 * <b>eos</b>.  Return -1 if we found nothing; 0 if we found something. */
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
static int
find_start_of_next_router_or_extrainfo(const char **s_ptr,
                                       const char *eos,
                                       int *is_extrainfo_out)
{
  const char *annotations = NULL;
  const char *s = *s_ptr;

  s = eat_whitespace_eos(s, eos);

  while (s < eos-32) {  /* 32 gives enough room for a the first keyword. */
    /* We're at the start of a line. */
    tor_assert(*s != '\n');

    if (*s == '@' && !annotations) {
      annotations = s;
    } else if (*s == 'r' && !strcmpstart(s, "router ")) {
      *s_ptr = annotations ? annotations : s;
      *is_extrainfo_out = 0;
      return 0;
    } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
      *s_ptr = annotations ? annotations : s;
      *is_extrainfo_out = 1;
      return 0;
    }

    if (!(s = memchr(s+1, '\n', eos-(s+1))))
      break;
    s = eat_whitespace_eos(s, eos);
  }
  return -1;
}

234
/** Given a string *<b>s</b> containing a concatenated sequence of router
235
236
237
238
 * descriptors (or extra-info documents if <b>want_extrainfo</b> is set),
 * parses them and stores the result in <b>dest</b>. All routers are marked
 * running and valid. Advances *s to a point immediately following the last
 * router entry. Ignore any trailing router entries that are not complete.
239
240
241
242
243
 *
 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
 * descriptor in the signed_descriptor_body field of each routerinfo_t.  If it
 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
 *
244
 * Returns 0 on success and -1 on failure.  Adds a digest to
245
246
 * <b>invalid_digests_out</b> for every entry that was unparseable or
 * invalid. (This may cause duplicate entries.)
247
248
 */
int
249
250
router_parse_list_from_string(const char **s, const char *eos,
                              smartlist_t *dest,
251
                              saved_location_t saved_location,
252
                              int want_extrainfo,
253
                              int allow_annotations,
254
255
                              const char *prepend_annotations,
                              smartlist_t *invalid_digests_out)
256
257
{
  routerinfo_t *router;
258
  extrainfo_t *extrainfo;
259
  signed_descriptor_t *signed_desc = NULL;
260
  void *elt;
261
262
  const char *end, *start;
  int have_extrainfo;
263

264
265
  tor_assert(s);
  tor_assert(*s);
266
  tor_assert(dest);
267

268
  start = *s;
269
270
271
272
273
  if (!eos)
    eos = *s + strlen(*s);

  tor_assert(eos >= *s);

274
  while (1) {
275
276
277
    char raw_digest[DIGEST_LEN];
    int have_raw_digest = 0;
    int dl_again = 0;
278
    if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
279
280
281
      break;

    end = tor_memstr(*s, eos-*s, "\nrouter-signature");
282
    if (end)
283
      end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
284
285
    if (end)
      end += strlen("\n-----END SIGNATURE-----\n");
286

287
288
    if (!end)
      break;
289

290
291
    elt = NULL;

292
    if (have_extrainfo && want_extrainfo) {
293
      routerlist_t *rl = router_get_routerlist();
294
      have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
295
296
      extrainfo = extrainfo_parse_entry_from_string(*s, end,
                                       saved_location != SAVED_IN_CACHE,
297
                                       rl->identity_map, &dl_again);
298
299
300
301
      if (extrainfo) {
        signed_desc = &extrainfo->cache_info;
        elt = extrainfo;
      }
302
    } else if (!have_extrainfo && !want_extrainfo) {
303
      have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
304
      router = router_parse_entry_from_string(*s, end,
305
                                              saved_location != SAVED_IN_CACHE,
306
                                              allow_annotations,
307
                                              prepend_annotations, &dl_again);
308
      if (router) {
309
        log_debug(LD_DIR, "Read router '%s', purpose '%s'",
310
311
                  router_describe(router),
                  router_purpose_to_string(router->purpose));
312
313
314
315
        signed_desc = &router->cache_info;
        elt = router;
      }
    }
316
317
318
    if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
      smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
    }
319
    if (!elt) {
320
      *s = end;
321
322
      continue;
    }
323
    if (saved_location != SAVED_NOWHERE) {
324
      tor_assert(signed_desc);
325
326
      signed_desc->saved_location = saved_location;
      signed_desc->saved_offset = *s - start;
327
    }
328
    *s = end;
329
    smartlist_add(dest, elt);
330
331
332
333
334
  }

  return 0;
}

335
336
337
338
/** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
 * with at least one argument (use GE(1) in setup). If found, store
 * address and port number to <b>addr_out</b> and
 * <b>port_out</b>. Return number of OR ports found. */
339
int
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
find_single_ipv6_orport(const smartlist_t *list,
                        tor_addr_t *addr_out,
                        uint16_t *port_out)
{
  int ret = 0;
  tor_assert(list != NULL);
  tor_assert(addr_out != NULL);
  tor_assert(port_out != NULL);

  SMARTLIST_FOREACH_BEGIN(list, directory_token_t *, t) {
    tor_addr_t a;
    maskbits_t bits;
    uint16_t port_min, port_max;
    tor_assert(t->n_args >= 1);
    /* XXXX Prop186 the full spec allows much more than this. */
355
356
    if (tor_addr_parse_mask_ports(t->args[0], 0,
                                  &a, &bits, &port_min,
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
                                  &port_max) == AF_INET6 &&
        bits == 128 &&
        port_min == port_max) {
      /* Okay, this is one we can understand. Use it and ignore
         any potential more addresses in list. */
      tor_addr_copy(addr_out, &a);
      *port_out = port_min;
      ret = 1;
      break;
    }
  } SMARTLIST_FOREACH_END(t);

  return ret;
}

372
373
/** Helper function: reads a single router entry from *<b>s</b> ...
 * *<b>end</b>.  Mallocs a new router and returns it if all goes well, else
374
375
376
 * returns NULL.  If <b>cache_copy</b> is true, duplicate the contents of
 * s through end into the signed_descriptor_body of the resulting
 * routerinfo_t.
377
 *
Robert Ransom's avatar
Robert Ransom committed
378
 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
379
 *
380
381
382
383
384
385
386
 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
 * before the router; if it's false, reject the router if it's annotated.  If
 * <b>prepend_annotations</b> is set, it should contain some annotations:
 * append them to the front of the router before parsing it, and keep them
 * around when caching the router.
 *
 * Only one of allow_annotations and prepend_annotations may be set.
387
388
389
390
391
 *
 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
 * if it's okay to try to download a descriptor with this same digest again,
 * and 0 if it isn't.  (It might not be okay to download it again if part of
 * the part covered by the digest is invalid.)
392
 */
393
routerinfo_t *
394
router_parse_entry_from_string(const char *s, const char *end,
395
                               int cache_copy, int allow_annotations,
396
397
                               const char *prepend_annotations,
                               int *can_dl_again_out)
398
{
399
400
401
402
  routerinfo_t *router = NULL;
  char digest[128];
  smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
  directory_token_t *tok;
403
  struct in_addr in;
404
  const char *start_of_annotations, *cp, *s_dup = s;
405
  size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
406
  int ok = 1;
407
  memarea_t *area = NULL;
408
  tor_cert_t *ntor_cc_cert = NULL;
409
410
  /* Do not set this to '1' until we have parsed everything that we intend to
   * parse that's covered by the hash. */
411
  int can_dl_again = 0;
412
  crypto_pk_t *rsa_pubkey = NULL;
413

414
415
  tor_assert(!allow_annotations || !prepend_annotations);

416
417
418
419
  if (!end) {
    end = s + strlen(s);
  }

420
421
422
423
  /* point 'end' to a point immediately after the final newline. */
  while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
    --end;

424
  area = memarea_new();
425
  tokens = smartlist_new();
426
  if (prepend_annotations) {
427
    if (tokenize_string(area,prepend_annotations,NULL,tokens,
428
                        routerdesc_token_table,TS_NOCHECK)) {
429
      log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
430
431
432
433
      goto err;
    }
  }

434
435
436
437
438
439
440
441
442
443
444
  start_of_annotations = s;
  cp = tor_memstr(s, end-s, "\nrouter ");
  if (!cp) {
    if (end-s < 7 || strcmpstart(s, "router ")) {
      log_warn(LD_DIR, "No router keyword found.");
      goto err;
    }
  } else {
    s = cp+1;
  }

445
446
447
448
449
450
451
452
453
454
  if (start_of_annotations != s) { /* We have annotations */
    if (allow_annotations) {
      if (tokenize_string(area,start_of_annotations,s,tokens,
                          routerdesc_token_table,TS_NOCHECK)) {
        log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
        goto err;
      }
    } else {
      log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
               "loaded from disk.  Dropping it.");
455
456
457
458
      goto err;
    }
  }

459
460
461
462
463
464
  if (!tor_memstr(s, end-s, "\nproto ")) {
    log_debug(LD_DIR, "Found an obsolete router descriptor. "
              "Rejecting quietly.");
    goto err;
  }

465
  if (router_get_router_hash(s, end - s, digest) < 0) {
466
    log_warn(LD_DIR, "Couldn't compute router hash.");
467
    goto err;
468
  }
469
470
471
472
473
474
475
  {
    int flags = 0;
    if (allow_annotations)
      flags |= TS_ANNOTATIONS_OK;
    if (prepend_annotations)
      flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;

476
    if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
477
478
479
      log_warn(LD_DIR, "Error tokenizing router descriptor.");
      goto err;
    }
480
481
482
  }

  if (smartlist_len(tokens) < 2) {
483
    log_warn(LD_DIR, "Impossibly short router descriptor.");
484
485
486
    goto err;
  }

487
  tok = find_by_keyword(tokens, K_ROUTER);
488
  const int router_token_pos = smartlist_pos(tokens, tok);
489
  tor_assert(tok->n_args >= 5);
490
491

  router = tor_malloc_zero(sizeof(routerinfo_t));
492
  router->cert_expiration_time = TIME_MAX;
493
  router->cache_info.routerlist_index = -1;
494
  router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
495
  router->cache_info.signed_descriptor_len = end-s;
496
497
  if (cache_copy) {
    size_t len = router->cache_info.signed_descriptor_len +
498
                 router->cache_info.annotations_len;
499
    char *signed_body =
500
501
      router->cache_info.signed_descriptor_body = tor_malloc(len+1);
    if (prepend_annotations) {
502
503
      memcpy(signed_body, prepend_annotations, prepend_len);
      signed_body += prepend_len;
504
    }
505
506
507
508
509
510
    /* This assertion will always succeed.
     * len == signed_desc_len + annotations_len
     *     == end-s + s-start_of_annotations + prepend_len
     *     == end-start_of_annotations + prepend_len
     * We already wrote prepend_len bytes into the buffer; now we're
     * writing end-start_of_annotations -NM. */
511
    tor_assert(signed_body+(end-start_of_annotations) ==
512
               router->cache_info.signed_descriptor_body+len);
513
    memcpy(signed_body, start_of_annotations, end-start_of_annotations);
514
515
    router->cache_info.signed_descriptor_body[len] = '\0';
    tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
516
  }
517
  memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
518

519
520
521
  router->nickname = tor_strdup(tok->args[0]);
  if (!is_legal_nickname(router->nickname)) {
    log_warn(LD_DIR,"Router nickname is invalid");
522
523
    goto err;
  }
524
  if (!tor_inet_aton(tok->args[1], &in)) {
525
    log_warn(LD_DIR,"Router address is not an IP address.");
526
    goto err;
527
  }
528
  tor_addr_from_in(&router->ipv4_addr, &in);
529

530
  router->ipv4_orport =
531
532
533
534
535
    (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
  if (!ok) {
    log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
    goto err;
  }
536
  router->ipv4_dirport =
537
538
539
540
541
    (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
  if (!ok) {
    log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
    goto err;
  }
542

543
544
  tok = find_by_keyword(tokens, K_BANDWIDTH);
  tor_assert(tok->n_args >= 3);
545
  router->bandwidthrate = (int)
546
    tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
547

548
  if (!ok) {
549
550
551
    log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
             escaped(tok->args[0]));
    goto err;
552
  }
553
554
  router->bandwidthburst =
    (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
555
556
557
558
  if (!ok) {
    log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
    goto err;
  }
559
  router->bandwidthcapacity = (int)
560
561
562
563
564
    tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
  if (!ok) {
    log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
    goto err;
  }
565

566
  if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
567
    tor_assert(tok->n_args);
568
    router->purpose = router_purpose_from_string(tok->args[0]);
569
570
571
    if (router->purpose == ROUTER_PURPOSE_UNKNOWN) {
      goto err;
    }
572
573
574
  } else {
    router->purpose = ROUTER_PURPOSE_GENERAL;
  }
575
576
  router->cache_info.send_unencrypted =
    (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
577

578
  if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
579
    tor_assert(tok->n_args >= 1);
580
581
582
583
584
    router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
    if (!ok) {
      log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
      goto err;
    }
Nick Mathewson's avatar
Nick Mathewson committed
585
586
  }

587
  if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
588
589
590
    tor_assert(tok->n_args >= 1);
    router->is_hibernating
      = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
591
592
  }

593
  tok = find_by_keyword(tokens, K_PUBLISHED);
594
  tor_assert(tok->n_args == 1);
595
  if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
596
    goto err;
597

598
  tok = find_by_keyword(tokens, K_ONION_KEY);
599
  if (!crypto_pk_public_exponent_ok(tok->key)) {
600
601
602
603
    log_warn(LD_DIR,
             "Relay's onion key had invalid exponent.");
    goto err;
  }
604
605
  router->onion_pkey = tor_memdup(tok->object_body, tok->object_size);
  router->onion_pkey_len = tok->object_size;
606
  crypto_pk_free(tok->key);
607

608
  if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
609
    curve25519_public_key_t k;
610
    tor_assert(tok->n_args >= 1);
611
612
    if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
      log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo");
613
614
615
      goto err;
    }
    router->onion_curve25519_pkey =
616
      tor_memdup(&k, sizeof(curve25519_public_key_t));
617
618
  }

619
  tok = find_by_keyword(tokens, K_SIGNING_KEY);
620
621
  router->identity_pkey = tok->key;
  tok->key = NULL; /* Prevent free */
622
623
  if (crypto_pk_get_digest(router->identity_pkey,
                           router->cache_info.identity_digest)) {
624
    log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
625
  }
626

627
  {
628
629
    directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok,
      *master_key_tok;
630
631
    ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
    ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
632
    master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519);
633
634
635
636
637
638
639
640
    cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT);
    cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
    int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok +
      !!cc_tap_tok + !!cc_ntor_tok;
    if ((n_ed_toks != 0 && n_ed_toks != 4) ||
        (n_ed_toks == 4 && !router->onion_curve25519_pkey)) {
      log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
               "cross-certification support");
641
642
      goto err;
    }
643
644
645
646
647
    if (master_key_tok && !ed_sig_tok) {
      log_warn(LD_DIR, "Router descriptor has ed25519 master key but no "
               "certificate");
      goto err;
    }
648
    if (ed_sig_tok) {
649
      tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok);
650
651
652
653
      const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
      if (ed_cert_token_pos == -1 || router_token_pos == -1 ||
          (ed_cert_token_pos != router_token_pos + 1 &&
           ed_cert_token_pos != router_token_pos - 1)) {
654
655
656
657
658
659
660
661
        log_warn(LD_DIR, "Ed25519 certificate in wrong position");
        goto err;
      }
      if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
        log_warn(LD_DIR, "Ed25519 signature in wrong position");
        goto err;
      }
      if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
Samanta Navarro's avatar
Samanta Navarro committed
662
663
        log_warn(LD_DIR, "Wrong object type on identity-ed25519 "
                         "in descriptor");
664
665
        goto err;
      }
666
667
      if (strcmp(cc_ntor_tok->object_type, "ED25519 CERT")) {
        log_warn(LD_DIR, "Wrong object type on ntor-onion-key-crosscert "
Samanta Navarro's avatar
Samanta Navarro committed
668
                 "in descriptor");
669
670
671
672
        goto err;
      }
      if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
        log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
Samanta Navarro's avatar
Samanta Navarro committed
673
                 "in descriptor");
674
675
676
677
678
679
680
681
        goto err;
      }
      if (strcmp(cc_ntor_tok->args[0], "0") &&
          strcmp(cc_ntor_tok->args[0], "1")) {
        log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert");
        goto err;
      }
      int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1");
682
683
684
685
686
687
688
689
690
691

      uint8_t d256[DIGEST256_LEN];
      const char *signed_start, *signed_end;
      tor_cert_t *cert = tor_cert_parse(
                       (const uint8_t*)ed_cert_tok->object_body,
                       ed_cert_tok->object_size);
      if (! cert) {
        log_warn(LD_DIR, "Couldn't parse ed25519 cert");
        goto err;
      }
Nick Mathewson's avatar
Nick Mathewson committed
692
693
      /* makes sure it gets freed. */
      router->cache_info.signing_key_cert = cert;
694

695
696
697
698
699
700
      if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
          ! cert->signing_key_included) {
        log_warn(LD_DIR, "Invalid form for ed25519 cert");
        goto err;
      }

701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
      if (master_key_tok) {
        /* This token is optional, but if it's present, it must match
         * the signature in the signing cert, or supplant it. */
        tor_assert(master_key_tok->n_args >= 1);
        ed25519_public_key_t pkey;
        if (ed25519_public_from_base64(&pkey, master_key_tok->args[0])<0) {
          log_warn(LD_DIR, "Can't parse ed25519 master key");
          goto err;
        }

        if (fast_memneq(&cert->signing_key.pubkey,
                        pkey.pubkey, ED25519_PUBKEY_LEN)) {
          log_warn(LD_DIR, "Ed25519 master key does not match "
                   "key in certificate");
          goto err;
        }
      }
718
719
      ntor_cc_cert = tor_cert_parse((const uint8_t*)cc_ntor_tok->object_body,
                                    cc_ntor_tok->object_size);
720
      if (!ntor_cc_cert) {
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
        log_warn(LD_DIR, "Couldn't parse ntor-onion-key-crosscert cert");
        goto err;
      }
      if (ntor_cc_cert->cert_type != CERT_TYPE_ONION_ID ||
          ! ed25519_pubkey_eq(&ntor_cc_cert->signed_key, &cert->signing_key)) {
        log_warn(LD_DIR, "Invalid contents for ntor-onion-key-crosscert cert");
        goto err;
      }

      ed25519_public_key_t ntor_cc_pk;
      if (ed25519_public_key_from_curve25519_public_key(&ntor_cc_pk,
                                            router->onion_curve25519_pkey,
                                            ntor_cc_sign_bit)<0) {
        log_warn(LD_DIR, "Error converting onion key to ed25519");
        goto err;
      }

738
739
      if (router_get_hash_impl_helper(s, end-s, "router ",
                                      "\nrouter-sig-ed25519",
740
741
                                      ' ', LOG_WARN,
                                      &signed_start, &signed_end) < 0) {
742
743
744
745
746
747
748
749
750
751
        log_warn(LD_DIR, "Can't find ed25519-signed portion of descriptor");
        goto err;
      }
      crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
      crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
        strlen(ED_DESC_SIGNATURE_PREFIX));
      crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
      crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
      crypto_digest_free(d);

752
753
      ed25519_checkable_t check[3];
      int check_ok[3];
754
755
      time_t expires = TIME_MAX;
      if (tor_cert_get_checkable_sig(&check[0], cert, NULL, &expires) < 0) {
756
757
758
        log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
        goto err;
      }
759
      if (tor_cert_get_checkable_sig(&check[1],
760
                               ntor_cc_cert, &ntor_cc_pk, &expires) < 0) {
761
762
763
764
765
        log_err(LD_BUG, "Couldn't create 'checkable' for ntor_cc_cert.");
        goto err;
      }

      if (ed25519_signature_from_base64(&check[2].signature,
766
767
768
769
                                        ed_sig_tok->args[0])<0) {
        log_warn(LD_DIR, "Couldn't decode ed25519 signature");
        goto err;
      }
770
771
772
      check[2].pubkey = &cert->signed_key;
      check[2].msg = d256;
      check[2].len = DIGEST256_LEN;
773

774
775
      if (ed25519_checksig_batch(check_ok, check, 3) < 0) {
        log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
776
777
        goto err;
      }
778

779
780
      rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey,
                                             router->onion_pkey_len);
781
782
783
      if (check_tap_onion_key_crosscert(
                      (const uint8_t*)cc_tap_tok->object_body,
                      (int)cc_tap_tok->object_size,
784
                      rsa_pubkey,
785
786
787
                      &cert->signing_key,
                      (const uint8_t*)router->cache_info.identity_digest)<0) {
        log_warn(LD_DIR, "Incorrect TAP cross-verification");
788
789
790
        goto err;
      }

791
      /* We check this before adding it to the routerlist. */
792
      router->cert_expiration_time = expires;
793
    }
794
  }
795

796
  if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
797
798
    /* If there's a fingerprint line, it must match the identity digest. */
    char d[DIGEST_LEN];
799
    tor_assert(tok->n_args == 1);
800
    tor_strstrip(tok->args[0], " ");
801
802
    if (base16_decode(d, DIGEST_LEN,
                      tok->args[0], strlen(tok->args[0])) != DIGEST_LEN) {
803
      log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
804
               escaped(tok->args[0]));
805
806
      goto err;
    }
807
    if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) {
808
809
      log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
               tok->args[0]);
810
811
812
813
      goto err;
    }
  }

814
815
816
817
818
819
820
821
822
823
824
  {
    const char *version = NULL, *protocols = NULL;
    if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
      router->platform = tor_strdup(tok->args[0]);
      version = tok->args[0];
    }

    if ((tok = find_opt_by_keyword(tokens, K_PROTO))) {
      router->protocol_list = tor_strdup(tok->args[0]);
      protocols = tok->args[0];
    }
825

826
    summarize_protover_flags(&router->pv, protocols, version);
827
828
  }

829
  if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
830
831
832
    router->contact_info = tor_strdup(tok->args[0]);
  }

833
834
835
836
837
838
  if (find_opt_by_keyword(tokens, K_REJECT6) ||
      find_opt_by_keyword(tokens, K_ACCEPT6)) {
    log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
             "older Tors.");
    goto err;
  }
839
840
841
  {
    smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
    if (or_addresses) {
842
843
      find_single_ipv6_orport(or_addresses, &router->ipv6_addr,
                              &router->ipv6_orport);
844
845
846
      smartlist_free(or_addresses);
    }
  }
847
  exit_policy_tokens = find_all_exitpolicy(tokens);
848
849
850
851
  if (!smartlist_len(exit_policy_tokens)) {
    log_warn(LD_DIR, "No exit policy tokens in descriptor.");
    goto err;
  }
852
853
  SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
                    if (router_add_exit_policy(router,t)<0) {
854
                      log_warn(LD_DIR,"Error in exit policy");
Roger Dingledine's avatar
Roger Dingledine committed
855
856
                      goto err;
                    });
857
  policy_expand_private(&router->exit_policy);
858

859
860
861
862
863
864
865
866
  if ((tok = find_opt_by_keyword(tokens, K_IPV6_POLICY)) && tok->n_args) {
    router->ipv6_exit_policy = parse_short_policy(tok->args[0]);
    if (! router->ipv6_exit_policy) {
      log_warn(LD_DIR , "Error in ipv6-policy %s", escaped(tok->args[0]));
      goto err;
    }
  }

Nick Mathewson's avatar
Nick Mathewson committed
867
  if (policy_is_reject_star(router->exit_policy, AF_INET, 1) &&
868
869
870
871
      (!router->ipv6_exit_policy ||
       short_policy_is_reject_star(router->ipv6_exit_policy)))
    router->policy_is_reject_star = 1;

872
  if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
873
    int i;
874
    router->declared_family = smartlist_new();
875
876
    for (i=0;i<tok->n_args;++i) {
      if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
877
878
        log_warn(LD_DIR, "Illegal nickname %s in family line",
                 escaped(tok->args[i]));
879
880
        goto err;
      }
881
      smartlist_add_strdup(router->declared_family, tok->args[i]);
882
883
    }
  }
884

885
  if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))
886
887
    router->caches_extra_info = 1;

888
  if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))
889
890
    router->allow_single_hop_exits = 1;

891
  if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
892
    tor_assert(tok->n_args >= 1);
893
    if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
894
895
896
897
      if (base16_decode(router->cache_info.extra_info_digest, DIGEST_LEN,
                        tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN) {
          log_warn(LD_DIR,"Invalid extra info digest");
      }
898
899
900
    } else {
      log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
    }
901
902

    if (tok->n_args >= 2) {
Nick Mathewson's avatar
Nick Mathewson committed
903
904
      if (digest256_from_base64(router->cache_info.extra_info_digest256,
                                tok->args[1]) < 0) {
905
906
907
908
        log_warn(LD_DIR, "Invalid extra info digest256 %s",
                 escaped(tok->args[1]));
      }
    }
909
910
  }

911
  if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) {
912
913
914
    router->wants_to_be_hs_dir = 1;
  }

915
916
  /* This router accepts tunnelled directory requests via begindir if it has
   * an open dirport or it included "tunnelled-dir-server". */
917
918
  if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) ||
      router->ipv4_dirport > 0) {
919
920
921
    router->supports_tunnelled_dir_requests = 1;
  }

922
  tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
923

924
  if (!router->ipv4_orport) {
925
    log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
926
927
    goto err;
  }
928

929
  /* We've checked everything that's covered by the hash. */
930
931
932
933
934
  can_dl_again = 1;
  if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
                            "router descriptor") < 0)
    goto err;

935
936
937
938
939
940
  if (!router->platform) {
    router->platform = tor_strdup("<unknown>");
  }
  goto done;

 err:
941
  dump_desc(s_dup, "router descriptor");
942
943
944
  routerinfo_free(router);
  router = NULL;
 done:
945
  crypto_pk_free(rsa_pubkey);
946
  tor_cert_free(ntor_cc_cert);
947
  if (tokens) {
948
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
949
950
    smartlist_free(tokens);
  }
951
  smartlist_free(exit_policy_tokens);
952
953
  if (area) {
    DUMP_AREA(area, "routerinfo");
954
    memarea_drop_all(area);
955
  }
956
957
  if (can_dl_again_out)
    *can_dl_again_out = can_dl_again;
958
959
960
  return router;
}

961
962
963
964
965
/** Parse a single extrainfo entry from the string <b>s</b>, ending at
 * <b>end</b>.  (If <b>end</b> is NULL, parse up to the end of <b>s</b>.)  If
 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
 * cache_info fields of the result.  If <b>routermap</b> is provided, use it
 * as a map from router identity to routerinfo_t when looking up signing keys.
966
967
968
969
970
 *
 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
 * if it's okay to try to download an extrainfo with this same digest again,
 * and 0 if it isn't.  (It might not be okay to download it again if part of
 * the part covered by the digest is invalid.)
971
 */
972
973
extrainfo_t *
extrainfo_parse_entry_from_string(const char *s, const char *end,
974
975
                            int cache_copy, struct digest_ri_map_t *routermap,
                            int *can_dl_again_out)
976
977
978
979
980
{
  extrainfo_t *extrainfo = NULL;
  char digest[128];
  smartlist_t *tokens = NULL;
  directory_token_t *tok;
981
  crypto_pk_t *key = NULL;
982
  routerinfo_t *router = NULL;
983
  memarea_t *area = NULL;
984
  const char *s_dup = s;
985
986
  /* Do not set this to '1' until we have parsed everything that we intend to
   * parse that's covered by the hash. */
987
  int can_dl_again = 0;
988

989
990
991
  if (BUG(s == NULL))
    return NULL;

992
993
994
995
996
997
998
999
  if (!end) {
    end = s + strlen(s);
  }

  /* point 'end' to a point immediately after the final newline. */
  while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
    --end;

1000
1001