LCOV - code coverage report
Current view: top level - feature/dirparse - routerparse.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 559 616 90.7 %
Date: 2021-11-24 03:28:48 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2001 Matej Pfajfar.
       2             :  * Copyright (c) 2001-2004, Roger Dingledine.
       3             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       4             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       5             : /* See LICENSE for licensing information */
       6             : 
       7             : /**
       8             :  * \file routerparse.c
       9             :  * \brief Code to parse and validate router descriptors, consenus directories,
      10             :  *   and similar objects.
      11             :  *
      12             :  * The objects parsed by this module use a common text-based metaformat,
      13             :  * documented in dir-spec.txt in torspec.git.  This module is itself divided
      14             :  * into two major kinds of function: code to handle the metaformat, and code
      15             :  * to convert from particular instances of the metaformat into the
      16             :  * objects that Tor uses.
      17             :  *
      18             :  * The generic parsing code works by calling a table-based tokenizer on the
      19             :  * input string.  Each token corresponds to a single line with a token, plus
      20             :  * optional arguments on that line, plus an optional base-64 encoded object
      21             :  * after that line.  Each token has a definition in a table of token_rule_t
      22             :  * entries that describes how many arguments it can take, whether it takes an
      23             :  * object, how many times it may appear, whether it must appear first, and so
      24             :  * on.
      25             :  *
      26             :  * The tokenizer function tokenize_string() converts its string input into a
      27             :  * smartlist full of instances of directory_token_t, according to a provided
      28             :  * table of token_rule_t.
      29             :  *
      30             :  * The generic parts of this module additionally include functions for
      31             :  * finding the start and end of signed information inside a signed object, and
      32             :  * computing the digest that will be signed.
      33             :  *
      34             :  * There are also functions for saving objects to disk that have caused
      35             :  * parsing to fail.
      36             :  *
      37             :  * The specific parts of this module describe conversions between
      38             :  * particular lists of directory_token_t and particular objects.  The
      39             :  * kinds of objects that can be parsed here are:
      40             :  *  <ul>
      41             :  *  <li>router descriptors (managed from routerlist.c)
      42             :  *  <li>extra-info documents (managed from routerlist.c)
      43             :  *  <li>microdescriptors (managed from microdesc.c)
      44             :  *  <li>vote and consensus networkstatus documents, and the routerstatus_t
      45             :  *    objects that they comprise (managed from networkstatus.c)
      46             :  *  <li>detached-signature objects used by authorities for gathering
      47             :  *    signatures on the networkstatus consensus (managed from dirvote.c)
      48             :  *  <li>authority key certificates (managed from routerlist.c)
      49             :  *  <li>hidden service descriptors (managed from rendcommon.c and rendcache.c)
      50             :  * </ul>
      51             :  **/
      52             : 
      53             : #define ROUTERDESC_TOKEN_TABLE_PRIVATE
      54             : 
      55             : #include "core/or/or.h"
      56             : #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             : #include "feature/dirparse/sigcommon.h"
      63             : #include "feature/dirparse/unparseable.h"
      64             : #include "feature/nodelist/describe.h"
      65             : #include "feature/nodelist/nickname.h"
      66             : #include "feature/nodelist/routerinfo.h"
      67             : #include "feature/nodelist/routerlist.h"
      68             : #include "feature/nodelist/torcert.h"
      69             : #include "feature/relay/router.h"
      70             : #include "lib/crypt_ops/crypto_curve25519.h"
      71             : #include "lib/crypt_ops/crypto_ed25519.h"
      72             : #include "lib/crypt_ops/crypto_format.h"
      73             : #include "lib/memarea/memarea.h"
      74             : #include "lib/sandbox/sandbox.h"
      75             : 
      76             : #include "core/or/addr_policy_st.h"
      77             : #include "feature/nodelist/extrainfo_st.h"
      78             : #include "feature/nodelist/routerinfo_st.h"
      79             : #include "feature/nodelist/routerlist_st.h"
      80             : 
      81             : /****************************************************************************/
      82             : 
      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             :   T0N("reject6",             K_REJECT6,             ARGS,    NO_OBJ ),
      89             :   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             :   T1( "signing-key",         K_SIGNING_KEY,         NO_ARGS, NEED_KEY_1024 ),
      93             :   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             :   T01("read-history",        K_READ_HISTORY,        ARGS,    NO_OBJ ),
     104             :   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             :   T1("identity-ed25519",     K_IDENTITY_ED25519,    NO_ARGS, NEED_OBJ ),
     108             :   T1("master-key-ed25519",   K_MASTER_KEY_ED25519,  GE(1),   NO_OBJ ),
     109             :   T1("router-sig-ed25519",   K_ROUTER_SIG_ED25519,  GE(1),   NO_OBJ ),
     110             :   T1("onion-key-crosscert",  K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
     111             :   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             :   END_OF_TABLE
     126             : };
     127             : // clang-format on
     128             : 
     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             :   T1("identity-ed25519",    K_IDENTITY_ED25519,    NO_ARGS, NEED_OBJ ),
     135             :   T1("router-sig-ed25519",  K_ROUTER_SIG_ED25519,  GE(1),   NO_OBJ ),
     136             :   T0N("opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK ),
     137             :   T01("read-history",        K_READ_HISTORY,        ARGS,    NO_OBJ ),
     138             :   T01("write-history",       K_WRITE_HISTORY,       ARGS,    NO_OBJ ),
     139             :   T01("dirreq-stats-end",    K_DIRREQ_END,          ARGS,    NO_OBJ ),
     140             :   T01("dirreq-v2-ips",       K_DIRREQ_V2_IPS,       ARGS,    NO_OBJ ),
     141             :   T01("dirreq-v3-ips",       K_DIRREQ_V3_IPS,       ARGS,    NO_OBJ ),
     142             :   T01("dirreq-v2-reqs",      K_DIRREQ_V2_REQS,      ARGS,    NO_OBJ ),
     143             :   T01("dirreq-v3-reqs",      K_DIRREQ_V3_REQS,      ARGS,    NO_OBJ ),
     144             :   T01("dirreq-v2-share",     K_DIRREQ_V2_SHARE,     ARGS,    NO_OBJ ),
     145             :   T01("dirreq-v3-share",     K_DIRREQ_V3_SHARE,     ARGS,    NO_OBJ ),
     146             :   T01("dirreq-v2-resp",      K_DIRREQ_V2_RESP,      ARGS,    NO_OBJ ),
     147             :   T01("dirreq-v3-resp",      K_DIRREQ_V3_RESP,      ARGS,    NO_OBJ ),
     148             :   T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR,       ARGS,    NO_OBJ ),
     149             :   T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR,       ARGS,    NO_OBJ ),
     150             :   T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN,     ARGS,    NO_OBJ ),
     151             :   T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN,     ARGS,    NO_OBJ ),
     152             :   T01("entry-stats-end",     K_ENTRY_END,           ARGS,    NO_OBJ ),
     153             :   T01("entry-ips",           K_ENTRY_IPS,           ARGS,    NO_OBJ ),
     154             :   T01("cell-stats-end",      K_CELL_END,            ARGS,    NO_OBJ ),
     155             :   T01("cell-processed-cells", K_CELL_PROCESSED,     ARGS,    NO_OBJ ),
     156             :   T01("cell-queued-cells",   K_CELL_QUEUED,         ARGS,    NO_OBJ ),
     157             :   T01("cell-time-in-queue",  K_CELL_TIME,           ARGS,    NO_OBJ ),
     158             :   T01("cell-circuits-per-decile", K_CELL_CIRCS,     ARGS,    NO_OBJ ),
     159             :   T01("exit-stats-end",      K_EXIT_END,            ARGS,    NO_OBJ ),
     160             :   T01("exit-kibibytes-written", K_EXIT_WRITTEN,     ARGS,    NO_OBJ ),
     161             :   T01("exit-kibibytes-read", K_EXIT_READ,           ARGS,    NO_OBJ ),
     162             :   T01("exit-streams-opened", K_EXIT_OPENED,         ARGS,    NO_OBJ ),
     163             : 
     164             :   T1_START( "extra-info",          K_EXTRA_INFO,          GE(2),   NO_OBJ ),
     165             : 
     166             :   END_OF_TABLE
     167             : };
     168             : // clang-format on
     169             : 
     170             : #undef T
     171             : 
     172             : /* static function prototypes */
     173             : static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
     174             : 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         309 : router_get_router_hash(const char *s, size_t s_len, char *digest)
     181             : {
     182         309 :   return router_get_hash_impl(s, s_len, digest,
     183             :                               "router ","\nrouter-signature", '\n',
     184             :                               DIGEST_SHA1);
     185             : }
     186             : 
     187             : /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
     188             :  * extrainfo string at <b>s</b>.  Return 0 on success, -1 on failure. */
     189             : int
     190         174 : router_get_extrainfo_hash(const char *s, size_t s_len, char *digest)
     191             : {
     192         174 :   return router_get_hash_impl(s, s_len, digest, "extra-info",
     193             :                               "\nrouter-signature",'\n', DIGEST_SHA1);
     194             : }
     195             : 
     196             : /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
     197             :  * or to the first of the annotations proceeding the next router or
     198             :  * extra-info---whichever comes first.  Set <b>is_extrainfo_out</b> to true if
     199             :  * we found an extrainfo, or false if found a router. Do not scan beyond
     200             :  * <b>eos</b>.  Return -1 if we found nothing; 0 if we found something. */
     201             : static int
     202          62 : find_start_of_next_router_or_extrainfo(const char **s_ptr,
     203             :                                        const char *eos,
     204             :                                        int *is_extrainfo_out)
     205             : {
     206          62 :   const char *annotations = NULL;
     207          62 :   const char *s = *s_ptr;
     208             : 
     209          62 :   s = eat_whitespace_eos(s, eos);
     210             : 
     211         110 :   while (s < eos-32) {  /* 32 gives enough room for a the first keyword. */
     212             :     /* We're at the start of a line. */
     213         103 :     tor_assert(*s != '\n');
     214             : 
     215         103 :     if (*s == '@' && !annotations) {
     216             :       annotations = s;
     217          79 :     } else if (*s == 'r' && !strcmpstart(s, "router ")) {
     218          40 :       *s_ptr = annotations ? annotations : s;
     219          40 :       *is_extrainfo_out = 0;
     220          40 :       return 0;
     221          39 :     } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
     222          15 :       *s_ptr = annotations ? annotations : s;
     223          15 :       *is_extrainfo_out = 1;
     224          15 :       return 0;
     225             :     }
     226             : 
     227          48 :     if (!(s = memchr(s+1, '\n', eos-(s+1))))
     228             :       break;
     229          48 :     s = eat_whitespace_eos(s, eos);
     230             :   }
     231             :   return -1;
     232             : }
     233             : 
     234             : /** Given a string *<b>s</b> containing a concatenated sequence of router
     235             :  * descriptors (or extra-info documents if <b>want_extrainfo</b> is set),
     236             :  * parses them and stores the result in <b>dest</b>. All routers are marked
     237             :  * running and valid. Advances *s to a point immediately following the last
     238             :  * router entry. Ignore any trailing router entries that are not complete.
     239             :  *
     240             :  * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
     241             :  * descriptor in the signed_descriptor_body field of each routerinfo_t.  If it
     242             :  * isn't SAVED_NOWHERE, remember the offset of each descriptor.
     243             :  *
     244             :  * Returns 0 on success and -1 on failure.  Adds a digest to
     245             :  * <b>invalid_digests_out</b> for every entry that was unparseable or
     246             :  * invalid. (This may cause duplicate entries.)
     247             :  */
     248             : int
     249           7 : router_parse_list_from_string(const char **s, const char *eos,
     250             :                               smartlist_t *dest,
     251             :                               saved_location_t saved_location,
     252             :                               int want_extrainfo,
     253             :                               int allow_annotations,
     254             :                               const char *prepend_annotations,
     255             :                               smartlist_t *invalid_digests_out)
     256             : {
     257           7 :   routerinfo_t *router;
     258           7 :   extrainfo_t *extrainfo;
     259           7 :   signed_descriptor_t *signed_desc = NULL;
     260           7 :   void *elt;
     261           7 :   const char *end, *start;
     262           7 :   int have_extrainfo;
     263             : 
     264           7 :   tor_assert(s);
     265           7 :   tor_assert(*s);
     266           7 :   tor_assert(dest);
     267             : 
     268           7 :   start = *s;
     269           7 :   if (!eos)
     270           7 :     eos = *s + strlen(*s);
     271             : 
     272           7 :   tor_assert(eos >= *s);
     273             : 
     274          62 :   while (1) {
     275          62 :     char raw_digest[DIGEST_LEN];
     276          62 :     int have_raw_digest = 0;
     277          62 :     int dl_again = 0;
     278          62 :     if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
     279             :       break;
     280             : 
     281          55 :     end = tor_memstr(*s, eos-*s, "\nrouter-signature");
     282          55 :     if (end)
     283          55 :       end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
     284          55 :     if (end)
     285          55 :       end += strlen("\n-----END SIGNATURE-----\n");
     286             : 
     287          55 :     if (!end)
     288             :       break;
     289             : 
     290          55 :     elt = NULL;
     291             : 
     292          55 :     if (have_extrainfo && want_extrainfo) {
     293          10 :       routerlist_t *rl = router_get_routerlist();
     294          10 :       have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
     295          10 :       extrainfo = extrainfo_parse_entry_from_string(*s, end,
     296             :                                        saved_location != SAVED_IN_CACHE,
     297             :                                        rl->identity_map, &dl_again);
     298          10 :       if (extrainfo) {
     299           4 :         signed_desc = &extrainfo->cache_info;
     300           4 :         elt = extrainfo;
     301             :       }
     302          45 :     } else if (!have_extrainfo && !want_extrainfo) {
     303          35 :       have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
     304          35 :       router = router_parse_entry_from_string(*s, end,
     305             :                                               saved_location != SAVED_IN_CACHE,
     306             :                                               allow_annotations,
     307             :                                               prepend_annotations, &dl_again);
     308          35 :       if (router) {
     309          28 :         log_debug(LD_DIR, "Read router '%s', purpose '%s'",
     310             :                   router_describe(router),
     311             :                   router_purpose_to_string(router->purpose));
     312          28 :         signed_desc = &router->cache_info;
     313          28 :         elt = router;
     314             :       }
     315             :     }
     316          55 :     if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
     317          11 :       smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
     318             :     }
     319          55 :     if (!elt) {
     320          23 :       *s = end;
     321          23 :       continue;
     322             :     }
     323          32 :     if (saved_location != SAVED_NOWHERE) {
     324          28 :       tor_assert(signed_desc);
     325          28 :       signed_desc->saved_location = saved_location;
     326          28 :       signed_desc->saved_offset = *s - start;
     327             :     }
     328          32 :     *s = end;
     329          32 :     smartlist_add(dest, elt);
     330             :   }
     331             : 
     332           7 :   return 0;
     333             : }
     334             : 
     335             : /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
     336             :  * with at least one argument (use GE(1) in setup). If found, store
     337             :  * address and port number to <b>addr_out</b> and
     338             :  * <b>port_out</b>. Return number of OR ports found. */
     339             : int
     340         174 : find_single_ipv6_orport(const smartlist_t *list,
     341             :                         tor_addr_t *addr_out,
     342             :                         uint16_t *port_out)
     343             : {
     344         174 :   int ret = 0;
     345         174 :   tor_assert(list != NULL);
     346         174 :   tor_assert(addr_out != NULL);
     347         174 :   tor_assert(port_out != NULL);
     348             : 
     349         181 :   SMARTLIST_FOREACH_BEGIN(list, directory_token_t *, t) {
     350         174 :     tor_addr_t a;
     351         174 :     maskbits_t bits;
     352         174 :     uint16_t port_min, port_max;
     353         174 :     tor_assert(t->n_args >= 1);
     354             :     /* XXXX Prop186 the full spec allows much more than this. */
     355         174 :     if (tor_addr_parse_mask_ports(t->args[0], 0,
     356             :                                   &a, &bits, &port_min,
     357         167 :                                   &port_max) == AF_INET6 &&
     358         167 :         bits == 128 &&
     359         167 :         port_min == port_max) {
     360             :       /* Okay, this is one we can understand. Use it and ignore
     361             :          any potential more addresses in list. */
     362         167 :       tor_addr_copy(addr_out, &a);
     363         167 :       *port_out = port_min;
     364         167 :       ret = 1;
     365         167 :       break;
     366             :     }
     367           7 :   } SMARTLIST_FOREACH_END(t);
     368             : 
     369         174 :   return ret;
     370             : }
     371             : 
     372             : /** Helper function: reads a single router entry from *<b>s</b> ...
     373             :  * *<b>end</b>.  Mallocs a new router and returns it if all goes well, else
     374             :  * returns NULL.  If <b>cache_copy</b> is true, duplicate the contents of
     375             :  * s through end into the signed_descriptor_body of the resulting
     376             :  * routerinfo_t.
     377             :  *
     378             :  * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
     379             :  *
     380             :  * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
     381             :  * before the router; if it's false, reject the router if it's annotated.  If
     382             :  * <b>prepend_annotations</b> is set, it should contain some annotations:
     383             :  * append them to the front of the router before parsing it, and keep them
     384             :  * around when caching the router.
     385             :  *
     386             :  * Only one of allow_annotations and prepend_annotations may be set.
     387             :  *
     388             :  * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
     389             :  * if it's okay to try to download a descriptor with this same digest again,
     390             :  * and 0 if it isn't.  (It might not be okay to download it again if part of
     391             :  * the part covered by the digest is invalid.)
     392             :  */
     393             : routerinfo_t *
     394        1292 : router_parse_entry_from_string(const char *s, const char *end,
     395             :                                int cache_copy, int allow_annotations,
     396             :                                const char *prepend_annotations,
     397             :                                int *can_dl_again_out)
     398             : {
     399        1292 :   routerinfo_t *router = NULL;
     400        1292 :   char digest[128];
     401        1292 :   smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
     402        1292 :   directory_token_t *tok;
     403        1292 :   struct in_addr in;
     404        1292 :   const char *start_of_annotations, *cp, *s_dup = s;
     405        1292 :   size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
     406        1292 :   int ok = 1;
     407        1292 :   memarea_t *area = NULL;
     408        1292 :   tor_cert_t *ntor_cc_cert = NULL;
     409             :   /* Do not set this to '1' until we have parsed everything that we intend to
     410             :    * parse that's covered by the hash. */
     411        1292 :   int can_dl_again = 0;
     412        1292 :   crypto_pk_t *rsa_pubkey = NULL;
     413             : 
     414        1292 :   tor_assert(!allow_annotations || !prepend_annotations);
     415             : 
     416        1292 :   if (!end) {
     417          72 :     end = s + strlen(s);
     418             :   }
     419             : 
     420             :   /* point 'end' to a point immediately after the final newline. */
     421        1716 :   while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
     422         424 :     --end;
     423             : 
     424        1292 :   area = memarea_new();
     425        1292 :   tokens = smartlist_new();
     426        1292 :   if (prepend_annotations) {
     427           2 :     if (tokenize_string(area,prepend_annotations,NULL,tokens,
     428             :                         routerdesc_token_table,TS_NOCHECK)) {
     429           1 :       log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
     430           1 :       goto err;
     431             :     }
     432             :   }
     433             : 
     434        1291 :   start_of_annotations = s;
     435        1291 :   cp = tor_memstr(s, end-s, "\nrouter ");
     436        1291 :   if (!cp) {
     437        1263 :     if (end-s < 7 || strcmpstart(s, "router ")) {
     438           8 :       log_warn(LD_DIR, "No router keyword found.");
     439           8 :       goto err;
     440             :     }
     441             :   } else {
     442          28 :     s = cp+1;
     443             :   }
     444             : 
     445        1283 :   if (start_of_annotations != s) { /* We have annotations */
     446          28 :     if (allow_annotations) {
     447          25 :       if (tokenize_string(area,start_of_annotations,s,tokens,
     448             :                           routerdesc_token_table,TS_NOCHECK)) {
     449           1 :         log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
     450           1 :         goto err;
     451             :       }
     452             :     } else {
     453           3 :       log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
     454             :                "loaded from disk.  Dropping it.");
     455           3 :       goto err;
     456             :     }
     457             :   }
     458             : 
     459        1279 :   if (!tor_memstr(s, end-s, "\nproto ")) {
     460        1021 :     log_debug(LD_DIR, "Found an obsolete router descriptor. "
     461             :               "Rejecting quietly.");
     462        1021 :     goto err;
     463             :   }
     464             : 
     465         258 :   if (router_get_router_hash(s, end - s, digest) < 0) {
     466           0 :     log_warn(LD_DIR, "Couldn't compute router hash.");
     467           0 :     goto err;
     468             :   }
     469             :   {
     470         258 :     int flags = 0;
     471         258 :     if (allow_annotations)
     472          30 :       flags |= TS_ANNOTATIONS_OK;
     473         258 :     if (prepend_annotations)
     474           1 :       flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
     475             : 
     476         258 :     if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
     477         134 :       log_warn(LD_DIR, "Error tokenizing router descriptor.");
     478         134 :       goto err;
     479             :     }
     480             :   }
     481             : 
     482         124 :   if (smartlist_len(tokens) < 2) {
     483           0 :     log_warn(LD_DIR, "Impossibly short router descriptor.");
     484           0 :     goto err;
     485             :   }
     486             : 
     487         124 :   tok = find_by_keyword(tokens, K_ROUTER);
     488         124 :   const int router_token_pos = smartlist_pos(tokens, tok);
     489         124 :   tor_assert(tok->n_args >= 5);
     490             : 
     491         124 :   router = tor_malloc_zero(sizeof(routerinfo_t));
     492         124 :   router->cert_expiration_time = TIME_MAX;
     493         124 :   router->cache_info.routerlist_index = -1;
     494         124 :   router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
     495         124 :   router->cache_info.signed_descriptor_len = end-s;
     496         124 :   if (cache_copy) {
     497          65 :     size_t len = router->cache_info.signed_descriptor_len +
     498             :                  router->cache_info.annotations_len;
     499         130 :     char *signed_body =
     500          65 :       router->cache_info.signed_descriptor_body = tor_malloc(len+1);
     501          65 :     if (prepend_annotations) {
     502           0 :       memcpy(signed_body, prepend_annotations, prepend_len);
     503           0 :       signed_body += prepend_len;
     504             :     }
     505             :     /* This assertion will always succeed.
     506             :      * len == signed_desc_len + annotations_len
     507             :      *     == end-s + s-start_of_annotations + prepend_len
     508             :      *     == end-start_of_annotations + prepend_len
     509             :      * We already wrote prepend_len bytes into the buffer; now we're
     510             :      * writing end-start_of_annotations -NM. */
     511          65 :     tor_assert(signed_body+(end-start_of_annotations) ==
     512             :                router->cache_info.signed_descriptor_body+len);
     513          65 :     memcpy(signed_body, start_of_annotations, end-start_of_annotations);
     514          65 :     router->cache_info.signed_descriptor_body[len] = '\0';
     515          65 :     tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
     516             :   }
     517         124 :   memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
     518             : 
     519         124 :   router->nickname = tor_strdup(tok->args[0]);
     520         124 :   if (!is_legal_nickname(router->nickname)) {
     521           2 :     log_warn(LD_DIR,"Router nickname is invalid");
     522           2 :     goto err;
     523             :   }
     524         122 :   if (!tor_inet_aton(tok->args[1], &in)) {
     525           2 :     log_warn(LD_DIR,"Router address is not an IP address.");
     526           2 :     goto err;
     527             :   }
     528         120 :   tor_addr_from_in(&router->ipv4_addr, &in);
     529             : 
     530         240 :   router->ipv4_orport =
     531         120 :     (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
     532         120 :   if (!ok) {
     533           3 :     log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
     534           3 :     goto err;
     535             :   }
     536         234 :   router->ipv4_dirport =
     537         117 :     (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
     538         117 :   if (!ok) {
     539           1 :     log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
     540           1 :     goto err;
     541             :   }
     542             : 
     543         116 :   tok = find_by_keyword(tokens, K_BANDWIDTH);
     544         116 :   tor_assert(tok->n_args >= 3);
     545         232 :   router->bandwidthrate = (int)
     546         116 :     tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
     547             : 
     548         116 :   if (!ok) {
     549           1 :     log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
     550             :              escaped(tok->args[0]));
     551           1 :     goto err;
     552             :   }
     553         230 :   router->bandwidthburst =
     554         115 :     (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
     555         115 :   if (!ok) {
     556           4 :     log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
     557           4 :     goto err;
     558             :   }
     559         222 :   router->bandwidthcapacity = (int)
     560         111 :     tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
     561         111 :   if (!ok) {
     562           0 :     log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
     563           0 :     goto err;
     564             :   }
     565             : 
     566         111 :   if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
     567           1 :     tor_assert(tok->n_args);
     568           1 :     router->purpose = router_purpose_from_string(tok->args[0]);
     569           1 :     if (router->purpose == ROUTER_PURPOSE_UNKNOWN) {
     570           0 :       goto err;
     571             :     }
     572             :   } else {
     573         110 :     router->purpose = ROUTER_PURPOSE_GENERAL;
     574             :   }
     575         111 :   router->cache_info.send_unencrypted =
     576         111 :     (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
     577             : 
     578         111 :   if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
     579          83 :     tor_assert(tok->n_args >= 1);
     580          83 :     router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
     581          83 :     if (!ok) {
     582           1 :       log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
     583           1 :       goto err;
     584             :     }
     585             :   }
     586             : 
     587         110 :   if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
     588          26 :     tor_assert(tok->n_args >= 1);
     589          26 :     router->is_hibernating
     590          26 :       = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
     591             :   }
     592             : 
     593         110 :   tok = find_by_keyword(tokens, K_PUBLISHED);
     594         110 :   tor_assert(tok->n_args == 1);
     595         110 :   if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
     596           2 :     goto err;
     597             : 
     598         108 :   tok = find_by_keyword(tokens, K_ONION_KEY);
     599         108 :   if (!crypto_pk_public_exponent_ok(tok->key)) {
     600           1 :     log_warn(LD_DIR,
     601             :              "Relay's onion key had invalid exponent.");
     602           1 :     goto err;
     603             :   }
     604         107 :   router->onion_pkey = tor_memdup(tok->object_body, tok->object_size);
     605         107 :   router->onion_pkey_len = tok->object_size;
     606         107 :   crypto_pk_free(tok->key);
     607             : 
     608         107 :   if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
     609         107 :     curve25519_public_key_t k;
     610         107 :     tor_assert(tok->n_args >= 1);
     611         107 :     if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
     612           1 :       log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo");
     613           1 :       goto err;
     614             :     }
     615         106 :     router->onion_curve25519_pkey =
     616         106 :       tor_memdup(&k, sizeof(curve25519_public_key_t));
     617             :   }
     618             : 
     619         106 :   tok = find_by_keyword(tokens, K_SIGNING_KEY);
     620         106 :   router->identity_pkey = tok->key;
     621         106 :   tok->key = NULL; /* Prevent free */
     622         106 :   if (crypto_pk_get_digest(router->identity_pkey,
     623         106 :                            router->cache_info.identity_digest)) {
     624           0 :     log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
     625             :   }
     626             : 
     627             :   {
     628         106 :     directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok,
     629             :       *master_key_tok;
     630         106 :     ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
     631         106 :     ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
     632         106 :     master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519);
     633         106 :     cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT);
     634         106 :     cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
     635         106 :     int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok +
     636         106 :       !!cc_tap_tok + !!cc_ntor_tok;
     637         106 :     if ((n_ed_toks != 0 && n_ed_toks != 4) ||
     638         106 :         (n_ed_toks == 4 && !router->onion_curve25519_pkey)) {
     639           0 :       log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
     640             :                "cross-certification support");
     641           0 :       goto err;
     642             :     }
     643         106 :     if (master_key_tok && !ed_sig_tok) {
     644           0 :       log_warn(LD_DIR, "Router descriptor has ed25519 master key but no "
     645             :                "certificate");
     646           0 :       goto err;
     647             :     }
     648         106 :     if (ed_sig_tok) {
     649         106 :       tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok);
     650         106 :       const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
     651         106 :       if (ed_cert_token_pos == -1 || router_token_pos == -1 ||
     652         106 :           (ed_cert_token_pos != router_token_pos + 1 &&
     653           1 :            ed_cert_token_pos != router_token_pos - 1)) {
     654           1 :         log_warn(LD_DIR, "Ed25519 certificate in wrong position");
     655           9 :         goto err;
     656             :       }
     657         105 :       if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
     658           1 :         log_warn(LD_DIR, "Ed25519 signature in wrong position");
     659           1 :         goto err;
     660             :       }
     661         104 :       if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
     662           0 :         log_warn(LD_DIR, "Wrong object type on identity-ed25519 "
     663             :                          "in descriptor");
     664           0 :         goto err;
     665             :       }
     666         104 :       if (strcmp(cc_ntor_tok->object_type, "ED25519 CERT")) {
     667           0 :         log_warn(LD_DIR, "Wrong object type on ntor-onion-key-crosscert "
     668             :                  "in descriptor");
     669           0 :         goto err;
     670             :       }
     671         104 :       if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
     672           0 :         log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
     673             :                  "in descriptor");
     674           0 :         goto err;
     675             :       }
     676         104 :       if (strcmp(cc_ntor_tok->args[0], "0") &&
     677          48 :           strcmp(cc_ntor_tok->args[0], "1")) {
     678           0 :         log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert");
     679           0 :         goto err;
     680             :       }
     681         104 :       int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1");
     682             : 
     683         104 :       uint8_t d256[DIGEST256_LEN];
     684         104 :       const char *signed_start, *signed_end;
     685         208 :       tor_cert_t *cert = tor_cert_parse(
     686         104 :                        (const uint8_t*)ed_cert_tok->object_body,
     687             :                        ed_cert_tok->object_size);
     688         104 :       if (! cert) {
     689           1 :         log_warn(LD_DIR, "Couldn't parse ed25519 cert");
     690           1 :         goto err;
     691             :       }
     692             :       /* makes sure it gets freed. */
     693         103 :       router->cache_info.signing_key_cert = cert;
     694             : 
     695         103 :       if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
     696             :           ! cert->signing_key_included) {
     697           1 :         log_warn(LD_DIR, "Invalid form for ed25519 cert");
     698           1 :         goto err;
     699             :       }
     700             : 
     701         102 :       if (master_key_tok) {
     702             :         /* This token is optional, but if it's present, it must match
     703             :          * the signature in the signing cert, or supplant it. */
     704         102 :         tor_assert(master_key_tok->n_args >= 1);
     705         102 :         ed25519_public_key_t pkey;
     706         102 :         if (ed25519_public_from_base64(&pkey, master_key_tok->args[0])<0) {
     707           0 :           log_warn(LD_DIR, "Can't parse ed25519 master key");
     708           0 :           goto err;
     709             :         }
     710             : 
     711         102 :         if (fast_memneq(&cert->signing_key.pubkey,
     712             :                         pkey.pubkey, ED25519_PUBKEY_LEN)) {
     713           0 :           log_warn(LD_DIR, "Ed25519 master key does not match "
     714             :                    "key in certificate");
     715           0 :           goto err;
     716             :         }
     717             :       }
     718         102 :       ntor_cc_cert = tor_cert_parse((const uint8_t*)cc_ntor_tok->object_body,
     719             :                                     cc_ntor_tok->object_size);
     720         102 :       if (!ntor_cc_cert) {
     721           0 :         log_warn(LD_DIR, "Couldn't parse ntor-onion-key-crosscert cert");
     722           0 :         goto err;
     723             :       }
     724         204 :       if (ntor_cc_cert->cert_type != CERT_TYPE_ONION_ID ||
     725         102 :           ! ed25519_pubkey_eq(&ntor_cc_cert->signed_key, &cert->signing_key)) {
     726           1 :         log_warn(LD_DIR, "Invalid contents for ntor-onion-key-crosscert cert");
     727           1 :         goto err;
     728             :       }
     729             : 
     730         101 :       ed25519_public_key_t ntor_cc_pk;
     731         101 :       if (ed25519_public_key_from_curve25519_public_key(&ntor_cc_pk,
     732         101 :                                             router->onion_curve25519_pkey,
     733             :                                             ntor_cc_sign_bit)<0) {
     734           0 :         log_warn(LD_DIR, "Error converting onion key to ed25519");
     735           0 :         goto err;
     736             :       }
     737             : 
     738         101 :       if (router_get_hash_impl_helper(s, end-s, "router ",
     739             :                                       "\nrouter-sig-ed25519",
     740             :                                       ' ', LOG_WARN,
     741             :                                       &signed_start, &signed_end) < 0) {
     742           0 :         log_warn(LD_DIR, "Can't find ed25519-signed portion of descriptor");
     743           0 :         goto err;
     744             :       }
     745         101 :       crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
     746         101 :       crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
     747             :         strlen(ED_DESC_SIGNATURE_PREFIX));
     748         101 :       crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
     749         101 :       crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
     750         101 :       crypto_digest_free(d);
     751             : 
     752         101 :       ed25519_checkable_t check[3];
     753         101 :       int check_ok[3];
     754         101 :       time_t expires = TIME_MAX;
     755         101 :       if (tor_cert_get_checkable_sig(&check[0], cert, NULL, &expires) < 0) {
     756           0 :         log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
     757           0 :         goto err;
     758             :       }
     759         101 :       if (tor_cert_get_checkable_sig(&check[1],
     760             :                                ntor_cc_cert, &ntor_cc_pk, &expires) < 0) {
     761           0 :         log_err(LD_BUG, "Couldn't create 'checkable' for ntor_cc_cert.");
     762           0 :         goto err;
     763             :       }
     764             : 
     765         101 :       if (ed25519_signature_from_base64(&check[2].signature,
     766         101 :                                         ed_sig_tok->args[0])<0) {
     767           3 :         log_warn(LD_DIR, "Couldn't decode ed25519 signature");
     768           3 :         goto err;
     769             :       }
     770          98 :       check[2].pubkey = &cert->signed_key;
     771          98 :       check[2].msg = d256;
     772          98 :       check[2].len = DIGEST256_LEN;
     773             : 
     774          98 :       if (ed25519_checksig_batch(check_ok, check, 3) < 0) {
     775           1 :         log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
     776           1 :         goto err;
     777             :       }
     778             : 
     779          97 :       rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey,
     780             :                                              router->onion_pkey_len);
     781          97 :       if (check_tap_onion_key_crosscert(
     782          97 :                       (const uint8_t*)cc_tap_tok->object_body,
     783          97 :                       (int)cc_tap_tok->object_size,
     784             :                       rsa_pubkey,
     785             :                       &cert->signing_key,
     786             :                       (const uint8_t*)router->cache_info.identity_digest)<0) {
     787           0 :         log_warn(LD_DIR, "Incorrect TAP cross-verification");
     788           0 :         goto err;
     789             :       }
     790             : 
     791             :       /* We check this before adding it to the routerlist. */
     792          97 :       router->cert_expiration_time = expires;
     793             :     }
     794             :   }
     795             : 
     796          97 :   if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
     797             :     /* If there's a fingerprint line, it must match the identity digest. */
     798          83 :     char d[DIGEST_LEN];
     799          83 :     tor_assert(tok->n_args == 1);
     800          83 :     tor_strstrip(tok->args[0], " ");
     801          83 :     if (base16_decode(d, DIGEST_LEN,
     802          83 :                       tok->args[0], strlen(tok->args[0])) != DIGEST_LEN) {
     803           6 :       log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
     804             :                escaped(tok->args[0]));
     805           7 :       goto err;
     806             :     }
     807          77 :     if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) {
     808           1 :       log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
     809             :                tok->args[0]);
     810           1 :       goto err;
     811             :     }
     812             :   }
     813             : 
     814             :   {
     815          90 :     const char *version = NULL, *protocols = NULL;
     816          90 :     if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
     817          76 :       router->platform = tor_strdup(tok->args[0]);
     818          76 :       version = tok->args[0];
     819             :     }
     820             : 
     821          90 :     if ((tok = find_opt_by_keyword(tokens, K_PROTO))) {
     822          90 :       router->protocol_list = tor_strdup(tok->args[0]);
     823          90 :       protocols = tok->args[0];
     824             :     }
     825             : 
     826          90 :     summarize_protover_flags(&router->pv, protocols, version);
     827             :   }
     828             : 
     829          90 :   if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
     830          30 :     router->contact_info = tor_strdup(tok->args[0]);
     831             :   }
     832             : 
     833         168 :   if (find_opt_by_keyword(tokens, K_REJECT6) ||
     834          78 :       find_opt_by_keyword(tokens, K_ACCEPT6)) {
     835          12 :     log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
     836             :              "older Tors.");
     837          12 :     goto err;
     838             :   }
     839             :   {
     840          78 :     smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
     841          78 :     if (or_addresses) {
     842          34 :       find_single_ipv6_orport(or_addresses, &router->ipv6_addr,
     843             :                               &router->ipv6_orport);
     844          34 :       smartlist_free(or_addresses);
     845             :     }
     846             :   }
     847          78 :   exit_policy_tokens = find_all_exitpolicy(tokens);
     848          78 :   if (!smartlist_len(exit_policy_tokens)) {
     849           1 :     log_warn(LD_DIR, "No exit policy tokens in descriptor.");
     850           1 :     goto err;
     851             :   }
     852         374 :   SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
     853             :                     if (router_add_exit_policy(router,t)<0) {
     854             :                       log_warn(LD_DIR,"Error in exit policy");
     855             :                       goto err;
     856             :                     });
     857          73 :   policy_expand_private(&router->exit_policy);
     858             : 
     859          73 :   if ((tok = find_opt_by_keyword(tokens, K_IPV6_POLICY)) && tok->n_args) {
     860           5 :     router->ipv6_exit_policy = parse_short_policy(tok->args[0]);
     861           5 :     if (! router->ipv6_exit_policy) {
     862           1 :       log_warn(LD_DIR , "Error in ipv6-policy %s", escaped(tok->args[0]));
     863           1 :       goto err;
     864             :     }
     865             :   }
     866             : 
     867          72 :   if (policy_is_reject_star(router->exit_policy, AF_INET, 1) &&
     868          21 :       (!router->ipv6_exit_policy ||
     869           0 :        short_policy_is_reject_star(router->ipv6_exit_policy)))
     870          21 :     router->policy_is_reject_star = 1;
     871             : 
     872          72 :   if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
     873           7 :     int i;
     874           7 :     router->declared_family = smartlist_new();
     875          25 :     for (i=0;i<tok->n_args;++i) {
     876          20 :       if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
     877           2 :         log_warn(LD_DIR, "Illegal nickname %s in family line",
     878             :                  escaped(tok->args[i]));
     879           2 :         goto err;
     880             :       }
     881          18 :       smartlist_add_strdup(router->declared_family, tok->args[i]);
     882             :     }
     883             :   }
     884             : 
     885          70 :   if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))
     886          13 :     router->caches_extra_info = 1;
     887             : 
     888          70 :   if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))
     889           4 :     router->allow_single_hop_exits = 1;
     890             : 
     891          70 :   if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
     892          43 :     tor_assert(tok->n_args >= 1);
     893          43 :     if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
     894          42 :       if (base16_decode(router->cache_info.extra_info_digest, DIGEST_LEN,
     895             :                         tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN) {
     896           0 :           log_warn(LD_DIR,"Invalid extra info digest");
     897             :       }
     898             :     } else {
     899           1 :       log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
     900             :     }
     901             : 
     902          43 :     if (tok->n_args >= 2) {
     903          39 :       if (digest256_from_base64(router->cache_info.extra_info_digest256,
     904          39 :                                 tok->args[1]) < 0) {
     905           0 :         log_warn(LD_DIR, "Invalid extra info digest256 %s",
     906             :                  escaped(tok->args[1]));
     907             :       }
     908             :     }
     909             :   }
     910             : 
     911          70 :   if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) {
     912          62 :     router->wants_to_be_hs_dir = 1;
     913             :   }
     914             : 
     915             :   /* This router accepts tunnelled directory requests via begindir if it has
     916             :    * an open dirport or it included "tunnelled-dir-server". */
     917          70 :   if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) ||
     918          12 :       router->ipv4_dirport > 0) {
     919          69 :     router->supports_tunnelled_dir_requests = 1;
     920             :   }
     921             : 
     922          70 :   tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
     923             : 
     924          70 :   if (!router->ipv4_orport) {
     925           1 :     log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
     926           1 :     goto err;
     927             :   }
     928             : 
     929             :   /* We've checked everything that's covered by the hash. */
     930          69 :   can_dl_again = 1;
     931          69 :   if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
     932             :                             "router descriptor") < 0)
     933           3 :     goto err;
     934             : 
     935          66 :   if (!router->platform) {
     936           4 :     router->platform = tor_strdup("<unknown>");
     937             :   }
     938          66 :   goto done;
     939             : 
     940        1226 :  err:
     941        1226 :   dump_desc(s_dup, "router descriptor");
     942        1226 :   routerinfo_free(router);
     943        1226 :   router = NULL;
     944        1292 :  done:
     945        1292 :   crypto_pk_free(rsa_pubkey);
     946        1292 :   tor_cert_free(ntor_cc_cert);
     947        1292 :   if (tokens) {
     948        5322 :     SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
     949        1292 :     smartlist_free(tokens);
     950             :   }
     951        1292 :   smartlist_free(exit_policy_tokens);
     952        1292 :   if (area) {
     953        1292 :     DUMP_AREA(area, "routerinfo");
     954        1292 :     memarea_drop_all(area);
     955             :   }
     956        1292 :   if (can_dl_again_out)
     957          67 :     *can_dl_again_out = can_dl_again;
     958        1292 :   return router;
     959             : }
     960             : 
     961             : /** Parse a single extrainfo entry from the string <b>s</b>, ending at
     962             :  * <b>end</b>.  (If <b>end</b> is NULL, parse up to the end of <b>s</b>.)  If
     963             :  * <b>cache_copy</b> is true, make a copy of the extra-info document in the
     964             :  * cache_info fields of the result.  If <b>routermap</b> is provided, use it
     965             :  * as a map from router identity to routerinfo_t when looking up signing keys.
     966             :  *
     967             :  * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
     968             :  * if it's okay to try to download an extrainfo with this same digest again,
     969             :  * and 0 if it isn't.  (It might not be okay to download it again if part of
     970             :  * the part covered by the digest is invalid.)
     971             :  */
     972             : extrainfo_t *
     973         479 : extrainfo_parse_entry_from_string(const char *s, const char *end,
     974             :                             int cache_copy, struct digest_ri_map_t *routermap,
     975             :                             int *can_dl_again_out)
     976             : {
     977         479 :   extrainfo_t *extrainfo = NULL;
     978         479 :   char digest[128];
     979         479 :   smartlist_t *tokens = NULL;
     980         479 :   directory_token_t *tok;
     981         479 :   crypto_pk_t *key = NULL;
     982         479 :   routerinfo_t *router = NULL;
     983         479 :   memarea_t *area = NULL;
     984         479 :   const char *s_dup = s;
     985             :   /* Do not set this to '1' until we have parsed everything that we intend to
     986             :    * parse that's covered by the hash. */
     987         479 :   int can_dl_again = 0;
     988             : 
     989         479 :   if (BUG(s == NULL))
     990           0 :     return NULL;
     991             : 
     992         479 :   if (!end) {
     993          28 :     end = s + strlen(s);
     994             :   }
     995             : 
     996             :   /* point 'end' to a point immediately after the final newline. */
     997         766 :   while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
     998         287 :     --end;
     999             : 
    1000         479 :   if (!tor_memstr(s, end-s, "\nidentity-ed25519")) {
    1001         349 :     log_debug(LD_DIR, "Found an obsolete extrainfo. Rejecting quietly.");
    1002         349 :     goto err;
    1003             :   }
    1004             : 
    1005         130 :   if (router_get_extrainfo_hash(s, end-s, digest) < 0) {
    1006           1 :     log_warn(LD_DIR, "Couldn't compute router hash.");
    1007           1 :     goto err;
    1008             :   }
    1009         129 :   tokens = smartlist_new();
    1010         129 :   area = memarea_new();
    1011         129 :   if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
    1012          13 :     log_warn(LD_DIR, "Error tokenizing extra-info document.");
    1013          13 :     goto err;
    1014             :   }
    1015             : 
    1016         116 :   if (smartlist_len(tokens) < 2) {
    1017           0 :     log_warn(LD_DIR, "Impossibly short extra-info document.");
    1018           0 :     goto err;
    1019             :   }
    1020             : 
    1021             :   /* XXXX Accept this in position 1 too, and ed identity in position 0. */
    1022         116 :   tok = smartlist_get(tokens,0);
    1023         116 :   if (tok->tp != K_EXTRA_INFO) {
    1024           0 :     log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
    1025           0 :     goto err;
    1026             :   }
    1027             : 
    1028         116 :   extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
    1029         116 :   extrainfo->cache_info.is_extrainfo = 1;
    1030         116 :   if (cache_copy)
    1031          21 :     extrainfo->cache_info.signed_descriptor_body = tor_memdup_nulterm(s,end-s);
    1032         116 :   extrainfo->cache_info.signed_descriptor_len = end-s;
    1033         116 :   memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
    1034         116 :   crypto_digest256((char*)extrainfo->digest256, s, end-s, DIGEST_SHA256);
    1035             : 
    1036         116 :   tor_assert(tok->n_args >= 2);
    1037         116 :   if (!is_legal_nickname(tok->args[0])) {
    1038           4 :     log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
    1039           4 :     goto err;
    1040             :   }
    1041         112 :   strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
    1042         223 :   if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
    1043         111 :       base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
    1044             :                     tok->args[1], HEX_DIGEST_LEN) != DIGEST_LEN) {
    1045           3 :     log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
    1046             :              escaped(tok->args[1]));
    1047           3 :     goto err;
    1048             :   }
    1049             : 
    1050         109 :   tok = find_by_keyword(tokens, K_PUBLISHED);
    1051         109 :   if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
    1052           9 :     log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
    1053             :              escaped(tok->args[0]));
    1054           9 :     goto err;
    1055             :   }
    1056             : 
    1057             :   {
    1058         100 :     directory_token_t *ed_sig_tok, *ed_cert_tok;
    1059         100 :     ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
    1060         100 :     ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
    1061         100 :     int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok;
    1062         100 :     if (n_ed_toks != 0 && n_ed_toks != 2) {
    1063           0 :       log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
    1064             :                "cross-certification support");
    1065           0 :       goto err;
    1066             :     }
    1067         100 :     if (ed_sig_tok) {
    1068         100 :       tor_assert(ed_cert_tok);
    1069         100 :       const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
    1070         100 :       if (ed_cert_token_pos != 1) {
    1071             :         /* Accept this in position 0 XXXX */
    1072          10 :         log_warn(LD_DIR, "Ed25519 certificate in wrong position");
    1073          74 :         goto err;
    1074             :       }
    1075          90 :       if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
    1076           3 :         log_warn(LD_DIR, "Ed25519 signature in wrong position");
    1077           3 :         goto err;
    1078             :       }
    1079          87 :       if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
    1080           3 :         log_warn(LD_DIR, "Wrong object type on identity-ed25519 "
    1081             :                          "in descriptor");
    1082           3 :         goto err;
    1083             :       }
    1084             : 
    1085          84 :       uint8_t d256[DIGEST256_LEN];
    1086          84 :       const char *signed_start, *signed_end;
    1087         168 :       tor_cert_t *cert = tor_cert_parse(
    1088          84 :                        (const uint8_t*)ed_cert_tok->object_body,
    1089             :                        ed_cert_tok->object_size);
    1090          84 :       if (! cert) {
    1091          40 :         log_warn(LD_DIR, "Couldn't parse ed25519 cert");
    1092          40 :         goto err;
    1093             :       }
    1094             :       /* makes sure it gets freed. */
    1095          44 :       extrainfo->cache_info.signing_key_cert = cert;
    1096             : 
    1097          44 :       if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
    1098             :           ! cert->signing_key_included) {
    1099          11 :         log_warn(LD_DIR, "Invalid form for ed25519 cert");
    1100          11 :         goto err;
    1101             :       }
    1102             : 
    1103          33 :       if (router_get_hash_impl_helper(s, end-s, "extra-info ",
    1104             :                                       "\nrouter-sig-ed25519",
    1105             :                                       ' ', LOG_WARN,
    1106             :                                       &signed_start, &signed_end) < 0) {
    1107           2 :         log_warn(LD_DIR, "Can't find ed25519-signed portion of extrainfo");
    1108           2 :         goto err;
    1109             :       }
    1110          31 :       crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
    1111          31 :       crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
    1112             :         strlen(ED_DESC_SIGNATURE_PREFIX));
    1113          31 :       crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
    1114          31 :       crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
    1115          31 :       crypto_digest_free(d);
    1116             : 
    1117          31 :       ed25519_checkable_t check[2];
    1118          31 :       int check_ok[2];
    1119          31 :       if (tor_cert_get_checkable_sig(&check[0], cert, NULL, NULL) < 0) {
    1120           0 :         log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
    1121           0 :         goto err;
    1122             :       }
    1123             : 
    1124          31 :       if (ed25519_signature_from_base64(&check[1].signature,
    1125          31 :                                         ed_sig_tok->args[0])<0) {
    1126           5 :         log_warn(LD_DIR, "Couldn't decode ed25519 signature");
    1127           5 :         goto err;
    1128             :       }
    1129          26 :       check[1].pubkey = &cert->signed_key;
    1130          26 :       check[1].msg = d256;
    1131          26 :       check[1].len = DIGEST256_LEN;
    1132             : 
    1133          26 :       if (ed25519_checksig_batch(check_ok, check, 2) < 0) {
    1134           0 :         log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
    1135           0 :         goto err;
    1136             :       }
    1137             :       /* We don't check the certificate expiration time: checking that it
    1138             :        * matches the cert in the router descriptor is adequate. */
    1139             :     }
    1140             :   }
    1141             : 
    1142             :   /* We've checked everything that's covered by the hash. */
    1143          26 :   can_dl_again = 1;
    1144             : 
    1145          26 :   if (routermap &&
    1146           7 :       (router = digestmap_get((digestmap_t*)routermap,
    1147             :                               extrainfo->cache_info.identity_digest))) {
    1148           4 :     key = router->identity_pkey;
    1149             :   }
    1150             : 
    1151          26 :   tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
    1152          26 :   if (strcmp(tok->object_type, "SIGNATURE") ||
    1153          26 :       tok->object_size < 128 || tok->object_size > 512) {
    1154           1 :     log_warn(LD_DIR, "Bad object type or length on extra-info signature");
    1155           1 :     goto err;
    1156             :   }
    1157             : 
    1158          25 :   if (key) {
    1159           4 :     if (check_signature_token(digest, DIGEST_LEN, tok, key, 0,
    1160             :                               "extra-info") < 0)
    1161           0 :       goto err;
    1162             : 
    1163           4 :     if (router)
    1164           4 :       extrainfo->cache_info.send_unencrypted =
    1165           4 :         router->cache_info.send_unencrypted;
    1166             :   } else {
    1167          21 :     extrainfo->pending_sig = tor_memdup(tok->object_body,
    1168             :                                         tok->object_size);
    1169          21 :     extrainfo->pending_sig_len = tok->object_size;
    1170             :   }
    1171             : 
    1172          25 :   goto done;
    1173         454 :  err:
    1174         454 :   dump_desc(s_dup, "extra-info descriptor");
    1175         454 :   extrainfo_free(extrainfo);
    1176         454 :   extrainfo = NULL;
    1177         479 :  done:
    1178         479 :   if (tokens) {
    1179       12258 :     SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    1180         129 :     smartlist_free(tokens);
    1181             :   }
    1182         479 :   if (area) {
    1183         129 :     DUMP_AREA(area, "extrainfo");
    1184         129 :     memarea_drop_all(area);
    1185             :   }
    1186         479 :   if (can_dl_again_out)
    1187         463 :     *can_dl_again_out = can_dl_again;
    1188             :   return extrainfo;
    1189             : }
    1190             : 
    1191             : /** Add an exit policy stored in the token <b>tok</b> to the router info in
    1192             :  * <b>router</b>.  Return 0 on success, -1 on failure. */
    1193             : static int
    1194         301 : router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
    1195             : {
    1196         301 :   addr_policy_t *newe;
    1197             :   /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
    1198         301 :   newe = router_parse_addr_policy(tok, 0);
    1199         301 :   if (!newe)
    1200             :     return -1;
    1201         297 :   if (! router->exit_policy)
    1202          77 :     router->exit_policy = smartlist_new();
    1203             : 
    1204             :   /* Ensure that in descriptors, accept/reject fields are followed by
    1205             :    * IPv4 addresses, and accept6/reject6 fields are followed by
    1206             :    * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
    1207             :    * accept/reject followed by IPv6. */
    1208         297 :   if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
    1209           0 :        tor_addr_family(&newe->addr) == AF_INET)
    1210         297 :       ||
    1211         297 :       ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
    1212         297 :        tor_addr_family(&newe->addr) == AF_INET6)) {
    1213             :     /* There's nothing the user can do about other relays' descriptors,
    1214             :      * so we don't provide usage advice here. */
    1215           0 :     log_warn(LD_DIR, "Mismatch between field type and address type in exit "
    1216             :              "policy '%s'. Discarding entire router descriptor.",
    1217             :              tok->n_args == 1 ? tok->args[0] : "");
    1218           0 :     addr_policy_free(newe);
    1219           0 :     return -1;
    1220             :   }
    1221             : 
    1222         297 :   smartlist_add(router->exit_policy, newe);
    1223             : 
    1224         297 :   return 0;
    1225             : }
    1226             : 
    1227             : /** Return a newly allocated smartlist of all accept or reject tokens in
    1228             :  * <b>s</b>.
    1229             :  */
    1230             : static smartlist_t *
    1231          78 : find_all_exitpolicy(smartlist_t *s)
    1232             : {
    1233          78 :   smartlist_t *out = smartlist_new();
    1234        1961 :   SMARTLIST_FOREACH(s, directory_token_t *, t,
    1235             :       if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
    1236             :           t->tp == K_REJECT || t->tp == K_REJECT6)
    1237             :         smartlist_add(out,t));
    1238          78 :   return out;
    1239             : }
    1240             : 
    1241             : /** Called on startup; right now we just handle scanning the unparseable
    1242             :  * descriptor dumps, but hang anything else we might need to do in the
    1243             :  * future here as well.
    1244             :  */
    1245             : void
    1246         194 : routerparse_init(void)
    1247             : {
    1248             :   /*
    1249             :    * Check both if the sandbox is active and whether it's configured; no
    1250             :    * point in loading all that if we won't be able to use it after the
    1251             :    * sandbox becomes active.
    1252             :    */
    1253         194 :   if (!(sandbox_is_active() || get_options()->Sandbox)) {
    1254         194 :     dump_desc_init();
    1255             :   }
    1256         194 : }
    1257             : 
    1258             : /** Clean up all data structures used by routerparse.c at exit */
    1259             : void
    1260         235 : routerparse_free_all(void)
    1261             : {
    1262         235 :   dump_desc_fifo_cleanup();
    1263         235 : }

Generated by: LCOV version 1.14