LCOV - code coverage report
Current view: top level - feature/dirauth - process_descs.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 171 398 43.0 %
Date: 2021-11-24 03:28:48 Functions: 14 20 70.0 %

          Line data    Source code
       1             : /* Copyright (c) 2001-2004, Roger Dingledine.
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file process_descs.c
       8             :  * \brief Make decisions about uploaded descriptors
       9             :  *
      10             :  * Authorities use the code in this module to decide what to do with just-
      11             :  * uploaded descriptors, and to manage the fingerprint file that helps
      12             :  * them make those decisions.
      13             :  **/
      14             : 
      15             : #define PROCESS_DESCS_PRIVATE
      16             : 
      17             : #include "core/or/or.h"
      18             : #include "feature/dirauth/process_descs.h"
      19             : 
      20             : #include "app/config/config.h"
      21             : #include "core/or/policies.h"
      22             : #include "core/or/versions.h"
      23             : #include "feature/dirauth/dirauth_sys.h"
      24             : #include "feature/dirauth/keypin.h"
      25             : #include "feature/dirauth/reachability.h"
      26             : #include "feature/dirclient/dlstatus.h"
      27             : #include "feature/dircommon/directory.h"
      28             : #include "feature/nodelist/describe.h"
      29             : #include "feature/nodelist/microdesc.h"
      30             : #include "feature/nodelist/networkstatus.h"
      31             : #include "feature/nodelist/nodelist.h"
      32             : #include "feature/nodelist/routerinfo.h"
      33             : #include "feature/nodelist/routerlist.h"
      34             : #include "feature/dirparse/routerparse.h"
      35             : #include "feature/nodelist/torcert.h"
      36             : #include "feature/relay/router.h"
      37             : 
      38             : #include "core/or/tor_version_st.h"
      39             : #include "feature/dirauth/dirauth_options_st.h"
      40             : #include "feature/nodelist/extrainfo_st.h"
      41             : #include "feature/nodelist/node_st.h"
      42             : #include "feature/nodelist/microdesc_st.h"
      43             : #include "feature/nodelist/routerinfo_st.h"
      44             : #include "feature/nodelist/routerstatus_st.h"
      45             : #include "feature/nodelist/vote_routerstatus_st.h"
      46             : 
      47             : #include "lib/encoding/confline.h"
      48             : #include "lib/crypt_ops/crypto_format.h"
      49             : 
      50             : /** How far in the future do we allow a router to get? (seconds) */
      51             : #define ROUTER_ALLOW_SKEW (60*60*12)
      52             : 
      53             : static void directory_remove_invalid(void);
      54             : static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei,
      55             :                                                 const char **msg);
      56             : static uint32_t
      57             : dirserv_get_status_impl(const char *id_digest,
      58             :                         const ed25519_public_key_t *ed25519_public_key,
      59             :                         const char *nickname, const tor_addr_t *ipv4_addr,
      60             :                         uint16_t ipv4_orport, const char *platform,
      61             :                         const char **msg, int severity);
      62             : 
      63             : /** Should be static; exposed for testing. */
      64             : static authdir_config_t *fingerprint_list = NULL;
      65             : 
      66             : /** Allocate and return a new, empty, authdir_config_t. */
      67             : static authdir_config_t *
      68          24 : authdir_config_new(void)
      69             : {
      70          24 :   authdir_config_t *list = tor_malloc_zero(sizeof(authdir_config_t));
      71          24 :   list->fp_by_name = strmap_new();
      72          24 :   list->status_by_digest = digestmap_new();
      73          24 :   list->status_by_digest256 = digest256map_new();
      74          24 :   return list;
      75             : }
      76             : 
      77             : #ifdef TOR_UNIT_TESTS
      78             : 
      79             : /** Initialize fingerprint_list to a new authdir_config_t. Used for tests. */
      80             : void
      81          17 : authdir_init_fingerprint_list(void)
      82             : {
      83          17 :   fingerprint_list = authdir_config_new();
      84          17 : }
      85             : 
      86             : /* Return the current fingerprint_list. Used for tests. */
      87             : authdir_config_t *
      88          17 : authdir_return_fingerprint_list(void)
      89             : {
      90          17 :   return fingerprint_list;
      91             : }
      92             : 
      93             : #endif /* defined(TOR_UNIT_TESTS) */
      94             : 
      95             : /** Add the fingerprint <b>fp</b> to the smartlist of fingerprint_entry_t's
      96             :  * <b>list</b>, or-ing the currently set status flags with
      97             :  * <b>add_status</b>.
      98             :  */
      99             : int
     100           9 : add_rsa_fingerprint_to_dir(const char *fp, authdir_config_t *list,
     101             :                            rtr_flags_t add_status)
     102             : {
     103           9 :   char *fingerprint;
     104           9 :   char d[DIGEST_LEN];
     105           9 :   rtr_flags_t *status;
     106           9 :   tor_assert(fp);
     107           9 :   tor_assert(list);
     108             : 
     109           9 :   fingerprint = tor_strdup(fp);
     110           9 :   tor_strstrip(fingerprint, " ");
     111           9 :   if (base16_decode(d, DIGEST_LEN,
     112             :                     fingerprint, strlen(fingerprint)) != DIGEST_LEN) {
     113           2 :     log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"",
     114             :              escaped(fp));
     115           2 :     tor_free(fingerprint);
     116           2 :     return -1;
     117             :   }
     118             : 
     119           7 :   status = digestmap_get(list->status_by_digest, d);
     120           7 :   if (!status) {
     121           7 :     status = tor_malloc_zero(sizeof(rtr_flags_t));
     122           7 :     digestmap_set(list->status_by_digest, d, status);
     123             :   }
     124             : 
     125           7 :   tor_free(fingerprint);
     126           7 :   *status |= add_status;
     127           7 :   return 0;
     128             : }
     129             : 
     130             : /** Add the ed25519 key <b>edkey</b> to the smartlist of fingerprint_entry_t's
     131             :  * <b>list</b>, or-ing the currently set status flags with <b>add_status</b>.
     132             :  * Return -1 if we were unable to decode the key, else return 0.
     133             :  */
     134             : int
     135           8 : add_ed25519_to_dir(const ed25519_public_key_t *edkey, authdir_config_t *list,
     136             :                    rtr_flags_t add_status)
     137             : {
     138           8 :   rtr_flags_t *status;
     139             : 
     140           8 :   tor_assert(edkey);
     141           8 :   tor_assert(list);
     142             : 
     143           8 :   if (ed25519_validate_pubkey(edkey) < 0) {
     144           1 :     log_warn(LD_DIRSERV, "Invalid ed25519 key \"%s\"", ed25519_fmt(edkey));
     145           1 :     return -1;
     146             :   }
     147             : 
     148           7 :   status = digest256map_get(list->status_by_digest256, edkey->pubkey);
     149           7 :   if (!status) {
     150           7 :     status = tor_malloc_zero(sizeof(rtr_flags_t));
     151           7 :     digest256map_set(list->status_by_digest256, edkey->pubkey, status);
     152             :   }
     153             : 
     154           7 :   *status |= add_status;
     155           7 :   return 0;
     156             : }
     157             : 
     158             : /** Add the fingerprint for this OR to the global list of recognized
     159             :  * identity key fingerprints. */
     160             : int
     161           1 : dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey)
     162             : {
     163           1 :   char fp[FINGERPRINT_LEN+1];
     164           1 :   if (crypto_pk_get_fingerprint(pk, fp, 0)<0) {
     165           0 :     log_err(LD_BUG, "Error computing fingerprint");
     166           0 :     return -1;
     167             :   }
     168           1 :   if (!fingerprint_list)
     169           0 :     fingerprint_list = authdir_config_new();
     170           1 :   if (add_rsa_fingerprint_to_dir(fp, fingerprint_list, 0) < 0) {
     171           0 :     log_err(LD_BUG, "Error adding RSA fingerprint");
     172           0 :     return -1;
     173             :   }
     174           1 :   if (add_ed25519_to_dir(edkey, fingerprint_list, 0) < 0) {
     175           0 :     log_err(LD_BUG, "Error adding ed25519 key");
     176           0 :     return -1;
     177             :   }
     178             :   return 0;
     179             : }
     180             : 
     181             : /** Load the nickname-\>fingerprint mappings stored in the approved-routers
     182             :  * file.  The file format is line-based, with each non-blank holding one
     183             :  * nickname, some space, and a fingerprint for that nickname.  On success,
     184             :  * replace the current fingerprint list with the new list and return 0.  On
     185             :  * failure, leave the current fingerprint list untouched, and return -1. */
     186             : int
     187           7 : dirserv_load_fingerprint_file(void)
     188             : {
     189           7 :   char *fname;
     190           7 :   char *cf;
     191           7 :   char *nickname, *fingerprint;
     192           7 :   authdir_config_t *fingerprint_list_new;
     193           7 :   int result;
     194           7 :   config_line_t *front=NULL, *list;
     195             : 
     196           7 :   fname = get_datadir_fname("approved-routers");
     197           7 :   log_info(LD_GENERAL,
     198             :            "Reloading approved fingerprints from \"%s\"...", fname);
     199             : 
     200           7 :   cf = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
     201           7 :   if (!cf) {
     202           0 :     log_warn(LD_FS, "Cannot open fingerprint file '%s'. That's ok.", fname);
     203           0 :     tor_free(fname);
     204           0 :     return 0;
     205             :   }
     206           7 :   tor_free(fname);
     207             : 
     208           7 :   result = config_get_lines(cf, &front, 0);
     209           7 :   tor_free(cf);
     210           7 :   if (result < 0) {
     211           0 :     log_warn(LD_CONFIG, "Error reading from fingerprint file");
     212           0 :     return -1;
     213             :   }
     214             : 
     215           7 :   fingerprint_list_new = authdir_config_new();
     216             : 
     217          14 :   for (list=front; list; list=list->next) {
     218           7 :     rtr_flags_t add_status = 0;
     219           7 :     nickname = list->key; fingerprint = list->value;
     220           7 :     tor_strstrip(fingerprint, " "); /* remove spaces */
     221             : 
     222             :    /* Determine what we should do with the relay with the nickname field. */
     223           7 :     if (!strcasecmp(nickname, "!reject")) {
     224             :         add_status = RTR_REJECT;
     225           7 :     } else if (!strcasecmp(nickname, "!badexit")) {
     226             :         add_status = RTR_BADEXIT;
     227           0 :     } else if (!strcasecmp(nickname, "!invalid")) {
     228           0 :         add_status = RTR_INVALID;
     229             :     }
     230             : 
     231             :     /* Check if fingerprint is RSA or ed25519 by verifying it. */
     232           7 :     int ed25519_not_ok = -1, rsa_not_ok = -1;
     233             : 
     234             :     /* Attempt to add the RSA key. */
     235           7 :     if (strlen(fingerprint) == HEX_DIGEST_LEN) {
     236           2 :       rsa_not_ok = add_rsa_fingerprint_to_dir(fingerprint,
     237             :                                               fingerprint_list_new,
     238             :                                               add_status);
     239             :     }
     240             : 
     241             :     /* Check ed25519 key. We check the size to prevent buffer overflows.
     242             :      * If valid, attempt to add it, */
     243           7 :     ed25519_public_key_t ed25519_pubkey_tmp;
     244           7 :     if (strlen(fingerprint) == BASE64_DIGEST256_LEN) {
     245           2 :       if (!digest256_from_base64((char *) ed25519_pubkey_tmp.pubkey,
     246             :                                  fingerprint)) {
     247           1 :         ed25519_not_ok = add_ed25519_to_dir(&ed25519_pubkey_tmp,
     248             :                                             fingerprint_list_new, add_status);
     249             :       }
     250             :     }
     251             : 
     252             :     /* If both keys are invalid (or missing), log and skip. */
     253           7 :     if (ed25519_not_ok && rsa_not_ok) {
     254           5 :       log_warn(LD_CONFIG, "Invalid fingerprint (nickname '%s', "
     255             :                "fingerprint %s). Skipping.", nickname, fingerprint);
     256           5 :       continue;
     257             :     }
     258             :   }
     259             : 
     260           7 :   config_free_lines(front);
     261           7 :   dirserv_free_fingerprint_list();
     262           7 :   fingerprint_list = fingerprint_list_new;
     263             :   /* Delete any routers whose fingerprints we no longer recognize */
     264           7 :   directory_remove_invalid();
     265           7 :   return 0;
     266             : }
     267             : 
     268             : /* If this is set, then we don't allow routers that have advertised an Ed25519
     269             :  * identity to stop doing so.  This is going to be essential for good identity
     270             :  * security: otherwise anybody who can attack RSA-1024 but not Ed25519 could
     271             :  * just sign fake descriptors missing the Ed25519 key.  But we won't actually
     272             :  * be able to prevent that kind of thing until we're confident that there isn't
     273             :  * actually a legit reason to downgrade to 0.2.5.  Now we are not recommending
     274             :  * 0.2.5 anymore so there is no reason to keep the #undef.
     275             :  */
     276             : 
     277             : #define DISABLE_DISABLING_ED25519
     278             : 
     279             : /** Check whether <b>router</b> has:
     280             :  * - a nickname/identity key combination that we recognize from the fingerprint
     281             :  *   list,
     282             :  * - an IP we automatically act on according to our configuration,
     283             :  * - an appropriate version, and
     284             :  * - matching pinned keys.
     285             :  *
     286             :  * Return the appropriate router status.
     287             :  *
     288             :  * If the status is 'RTR_REJECT' and <b>msg</b> is provided, set
     289             :  * *<b>msg</b> to a string constant explaining why. */
     290             : uint32_t
     291           6 : dirserv_router_get_status(const routerinfo_t *router, const char **msg,
     292             :                           int severity)
     293             : {
     294           6 :   char d[DIGEST_LEN];
     295           6 :   const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
     296           6 :   uint32_t r;
     297           6 :   ed25519_public_key_t *signing_key = NULL;
     298             : 
     299           6 :   if (crypto_pk_get_digest(router->identity_pkey, d)) {
     300           0 :     log_warn(LD_BUG,"Error computing fingerprint");
     301           0 :     if (msg)
     302           0 :       *msg = "Bug: Error computing fingerprint";
     303           0 :     return RTR_REJECT;
     304             :   }
     305             : 
     306             :   /* First, check for the more common reasons to reject a router. */
     307           6 :   if (router->cache_info.signing_key_cert) {
     308             :     /* This has an ed25519 identity key. */
     309           6 :     signing_key = &router->cache_info.signing_key_cert->signing_key;
     310             :   }
     311          12 :   r = dirserv_get_status_impl(d, signing_key, router->nickname,
     312           6 :                               &router->ipv4_addr, router->ipv4_orport,
     313           6 :                               router->platform, msg, severity);
     314             : 
     315           6 :   if (r)
     316             :     return r;
     317             : 
     318             :   /* dirserv_get_status_impl already rejects versions older than 0.2.4.18-rc,
     319             :    * and onion_curve25519_pkey was introduced in 0.2.4.8-alpha.
     320             :    * But just in case a relay doesn't provide or lies about its version, or
     321             :    * doesn't include an ntor key in its descriptor, check that it exists,
     322             :    * and is non-zero (clients check that it's non-zero before using it). */
     323           4 :   if (!routerinfo_has_curve25519_onion_key(router)) {
     324           0 :     log_fn(severity, LD_DIR,
     325             :            "Descriptor from router %s (platform %s) "
     326             :            "is missing an ntor curve25519 onion key.",
     327             :            router_describe(router), router->platform);
     328           0 :     if (msg)
     329           0 :       *msg = "Missing ntor curve25519 onion key. Please upgrade!";
     330           0 :     return RTR_REJECT;
     331             :   }
     332             : 
     333           4 :   if (router->cache_info.signing_key_cert) {
     334             :     /* This has an ed25519 identity key. */
     335           4 :     if (KEYPIN_MISMATCH ==
     336           4 :         keypin_check((const uint8_t*)router->cache_info.identity_digest,
     337           4 :                    router->cache_info.signing_key_cert->signing_key.pubkey)) {
     338           0 :       log_fn(severity, LD_DIR,
     339             :              "Descriptor from router %s has an Ed25519 key, "
     340             :                "but the <rsa,ed25519> keys don't match what they were before.",
     341             :                router_describe(router));
     342           0 :       if (key_pinning) {
     343           0 :         if (msg) {
     344           0 :           *msg = "Ed25519 identity key or RSA identity key has changed.";
     345             :         }
     346           0 :         return RTR_REJECT;
     347             :       }
     348             :     }
     349             :   } else {
     350             :     /* No ed25519 key */
     351           0 :     if (KEYPIN_MISMATCH == keypin_check_lone_rsa(
     352           0 :                         (const uint8_t*)router->cache_info.identity_digest)) {
     353           0 :       log_fn(severity, LD_DIR,
     354             :                "Descriptor from router %s has no Ed25519 key, "
     355             :                "when we previously knew an Ed25519 for it. Ignoring for now, "
     356             :                "since Ed25519 keys are fairly new.",
     357             :                router_describe(router));
     358             : #ifdef DISABLE_DISABLING_ED25519
     359           0 :       if (key_pinning) {
     360           0 :         if (msg) {
     361           0 :           *msg = "Ed25519 identity key has disappeared.";
     362             :         }
     363           0 :         return RTR_REJECT;
     364             :       }
     365             : #endif /* defined(DISABLE_DISABLING_ED25519) */
     366             :     }
     367             :   }
     368             : 
     369             :   return 0;
     370             : }
     371             : 
     372             : /** Return true if there is no point in downloading the router described by
     373             :  * <b>rs</b> because this directory would reject it. */
     374             : int
     375           6 : dirserv_would_reject_router(const routerstatus_t *rs,
     376             :                             const vote_routerstatus_t *vrs)
     377             : {
     378           6 :   uint32_t res;
     379           6 :   struct ed25519_public_key_t pk;
     380           6 :   memcpy(&pk.pubkey, vrs->ed25519_id, ED25519_PUBKEY_LEN);
     381             : 
     382          12 :   res = dirserv_get_status_impl(rs->identity_digest, &pk, rs->nickname,
     383           6 :                                 &rs->ipv4_addr, rs->ipv4_orport, NULL, NULL,
     384             :                                 LOG_DEBUG);
     385             : 
     386           6 :   return (res & RTR_REJECT) != 0;
     387             : }
     388             : 
     389             : /**
     390             :  * Check whether the platform string in <b>platform</b> describes a platform
     391             :  * that, as a directory authority, we want to reject.  If it does, return
     392             :  * true, and set *<b>msg</b> (if present) to a rejection message.  Otherwise
     393             :  * return false.
     394             :  */
     395             : STATIC bool
     396          32 : dirserv_rejects_tor_version(const char *platform,
     397             :                             const char **msg)
     398             : {
     399          32 :   if (!platform)
     400             :     return false;
     401             : 
     402          32 :   static const char please_upgrade_string[] =
     403             :     "Tor version is insecure or unsupported. Please upgrade!";
     404             : 
     405             :   /* Versions before Tor 0.3.5 are unsupported.
     406             :    *
     407             :    * Also, reject unstable versions of 0.3.5, since (as of this writing)
     408             :    * they are almost none of the network. */
     409          32 :   if (!tor_version_as_new_as(platform,"0.3.5.7")) {
     410          14 :     if (msg)
     411          14 :       *msg = please_upgrade_string;
     412          14 :     return true;
     413             :   }
     414             : 
     415             :   /* Series between Tor 0.3.6 and 0.4.1 inclusive are unsupported. Reject
     416             :    * them. 0.3.6.0-alpha-dev only existed for a short time, before it was
     417             :    * renamed to 0.4.0.0-alpha-dev. */
     418          34 :   if (tor_version_as_new_as(platform,"0.3.6.0-alpha-dev") &&
     419          16 :       !tor_version_as_new_as(platform,"0.4.2.1-alpha")) {
     420           5 :     if (msg) {
     421           5 :       *msg = please_upgrade_string;
     422             :     }
     423           5 :     return true;
     424             :   }
     425             : 
     426             :   return false;
     427             : }
     428             : 
     429             : /** Helper: As dirserv_router_get_status, but takes the router fingerprint
     430             :  * (hex, no spaces), ed25519 key, nickname, address (used for logging only),
     431             :  * IP address, OR port and platform (logging only) as arguments.
     432             :  *
     433             :  * Log messages at 'severity'. (There's not much point in
     434             :  * logging that we're rejecting servers we'll not download.)
     435             :  */
     436             : static uint32_t
     437          12 : dirserv_get_status_impl(const char *id_digest,
     438             :                         const ed25519_public_key_t *ed25519_public_key,
     439             :                         const char *nickname, const tor_addr_t *ipv4_addr,
     440             :                         uint16_t ipv4_orport, const char *platform,
     441             :                         const char **msg, int severity)
     442             : {
     443          12 :   uint32_t result = 0;
     444          12 :   rtr_flags_t *status_by_digest;
     445             : 
     446          12 :   if (!fingerprint_list)
     447           0 :     fingerprint_list = authdir_config_new();
     448             : 
     449          12 :   log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.",
     450             :             strmap_size(fingerprint_list->fp_by_name),
     451             :             digestmap_size(fingerprint_list->status_by_digest));
     452             : 
     453          12 :   if (platform) {
     454           6 :     tor_version_t ver_tmp;
     455           6 :     if (tor_version_parse_platform(platform, &ver_tmp, 1) < 0) {
     456           0 :       if (msg) {
     457           0 :         *msg = "Malformed platform string.";
     458             :       }
     459           0 :       return RTR_REJECT;
     460             :     }
     461             :   }
     462             : 
     463             :   /* Check whether the version is obsolete, broken, insecure, etc... */
     464          12 :   if (platform && dirserv_rejects_tor_version(platform, msg)) {
     465             :     return RTR_REJECT;
     466             :   }
     467             : 
     468          12 :   status_by_digest = digestmap_get(fingerprint_list->status_by_digest,
     469             :                                    id_digest);
     470          12 :   if (status_by_digest)
     471           4 :     result |= *status_by_digest;
     472             : 
     473          12 :   if (ed25519_public_key) {
     474          24 :     status_by_digest = digest256map_get(fingerprint_list->status_by_digest256,
     475          12 :                                         ed25519_public_key->pubkey);
     476          12 :     if (status_by_digest)
     477           4 :       result |= *status_by_digest;
     478             :   }
     479             : 
     480          12 :   if (result & RTR_REJECT) {
     481           4 :     if (msg)
     482           2 :       *msg = "Fingerprint and/or ed25519 identity is marked rejected -- if "
     483             :              "you think this is a mistake please set a valid email address "
     484             :              "in ContactInfo and send an email to "
     485             :              "bad-relays@lists.torproject.org mentioning your fingerprint(s)?";
     486           4 :     return RTR_REJECT;
     487           8 :   } else if (result & RTR_INVALID) {
     488           0 :     if (msg)
     489           0 :       *msg = "Fingerprint and/or ed25519 identity is marked invalid";
     490             :   }
     491             : 
     492           8 :   if (authdir_policy_badexit_address(ipv4_addr, ipv4_orport)) {
     493           0 :     log_fn(severity, LD_DIRSERV,
     494             :            "Marking '%s' as bad exit because of address '%s'",
     495             :                nickname, fmt_addr(ipv4_addr));
     496           0 :     result |= RTR_BADEXIT;
     497             :   }
     498             : 
     499           8 :   if (!authdir_policy_permits_address(ipv4_addr, ipv4_orport)) {
     500           0 :     log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'",
     501             :                nickname, fmt_addr(ipv4_addr));
     502           0 :     if (msg)
     503           0 :       *msg = "Suspicious relay address range -- if you think this is a "
     504             :              "mistake please set a valid email address in ContactInfo and "
     505             :              "send an email to bad-relays@lists.torproject.org mentioning "
     506             :              "your address(es) and fingerprint(s)?";
     507           0 :     return RTR_REJECT;
     508             :   }
     509           8 :   if (!authdir_policy_valid_address(ipv4_addr, ipv4_orport)) {
     510           0 :     log_fn(severity, LD_DIRSERV,
     511             :            "Not marking '%s' valid because of address '%s'",
     512             :                nickname, fmt_addr(ipv4_addr));
     513           0 :     result |= RTR_INVALID;
     514             :   }
     515             : 
     516             :   return result;
     517             : }
     518             : 
     519             : /** Clear the current fingerprint list. */
     520             : void
     521         266 : dirserv_free_fingerprint_list(void)
     522             : {
     523         266 :   if (!fingerprint_list)
     524             :     return;
     525             : 
     526          24 :   strmap_free(fingerprint_list->fp_by_name, tor_free_);
     527          24 :   digestmap_free(fingerprint_list->status_by_digest, tor_free_);
     528          24 :   digest256map_free(fingerprint_list->status_by_digest256, tor_free_);
     529          24 :   tor_free(fingerprint_list);
     530             : }
     531             : 
     532             : /*
     533             :  *    Descriptor list
     534             :  */
     535             : 
     536             : /** Return -1 if <b>ri</b> has a private or otherwise bad address,
     537             :  * unless we're configured to not care. Return 0 if all ok. */
     538             : STATIC int
     539          18 : dirserv_router_has_valid_address(routerinfo_t *ri)
     540             : {
     541          18 :   if (get_options()->DirAllowPrivateAddresses)
     542             :     return 0; /* whatever it is, we're fine with it */
     543             : 
     544          15 :   if (tor_addr_is_null(&ri->ipv4_addr) ||
     545           6 :       tor_addr_is_internal(&ri->ipv4_addr, 0)) {
     546           4 :     log_info(LD_DIRSERV,
     547             :              "Router %s published internal IPv4 address. Refusing.",
     548             :              router_describe(ri));
     549           4 :     return -1; /* it's a private IP, we should reject it */
     550             :   }
     551             : 
     552             :   /* We only check internal v6 on non-null addresses because we do not require
     553             :    * IPv6 and null IPv6 is normal. */
     554           7 :   if (!tor_addr_is_null(&ri->ipv6_addr) &&
     555           2 :       tor_addr_is_internal(&ri->ipv6_addr, 0)) {
     556           1 :     log_info(LD_DIRSERV,
     557             :              "Router %s published internal IPv6 address. Refusing.",
     558             :              router_describe(ri));
     559           1 :     return -1; /* it's a private IP, we should reject it */
     560             :   }
     561             : 
     562             :   return 0;
     563             : }
     564             : 
     565             : /** Check whether we, as a directory server, want to accept <b>ri</b>.  If so,
     566             :  * set its is_valid,running fields and return 0.  Otherwise, return -1.
     567             :  *
     568             :  * If the router is rejected, set *<b>msg</b> to a string constant explining
     569             :  * why.
     570             :  *
     571             :  * If <b>complain</b> then explain at log-level 'notice' why we refused
     572             :  * a descriptor; else explain at log-level 'info'.
     573             :  */
     574             : int
     575           0 : authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
     576             :                                int complain, int *valid_out)
     577             : {
     578             :   /* Okay.  Now check whether the fingerprint is recognized. */
     579           0 :   time_t now;
     580           0 :   int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO;
     581           0 :   uint32_t status = dirserv_router_get_status(ri, msg, severity);
     582           0 :   tor_assert(msg);
     583           0 :   if (status & RTR_REJECT)
     584             :     return -1; /* msg is already set. */
     585             : 
     586             :   /* Is there too much clock skew? */
     587           0 :   now = time(NULL);
     588           0 :   if (ri->cache_info.published_on > now+ROUTER_ALLOW_SKEW) {
     589           0 :     log_fn(severity, LD_DIRSERV, "Publication time for %s is too "
     590             :            "far (%d minutes) in the future; possible clock skew. Not adding "
     591             :            "(%s)",
     592             :            router_describe(ri),
     593             :            (int)((ri->cache_info.published_on-now)/60),
     594             :            esc_router_info(ri));
     595           0 :     *msg = "Rejected: Your clock is set too far in the future, or your "
     596             :       "timezone is not correct.";
     597           0 :     return -1;
     598             :   }
     599           0 :   if (ri->cache_info.published_on < now-ROUTER_MAX_AGE_TO_PUBLISH) {
     600           0 :     log_fn(severity, LD_DIRSERV,
     601             :            "Publication time for %s is too far "
     602             :            "(%d minutes) in the past. Not adding (%s)",
     603             :            router_describe(ri),
     604             :            (int)((now-ri->cache_info.published_on)/60),
     605             :            esc_router_info(ri));
     606           0 :     *msg = "Rejected: Server is expired, or your clock is too far in the past,"
     607             :       " or your timezone is not correct.";
     608           0 :     return -1;
     609             :   }
     610           0 :   if (dirserv_router_has_valid_address(ri) < 0) {
     611           0 :     log_fn(severity, LD_DIRSERV,
     612             :            "Router %s has invalid address. Not adding (%s).",
     613             :            router_describe(ri),
     614             :            esc_router_info(ri));
     615           0 :     *msg = "Rejected: Address is a private address.";
     616           0 :     return -1;
     617             :   }
     618             : 
     619           0 :   *valid_out = ! (status & RTR_INVALID);
     620             : 
     621           0 :   return 0;
     622             : }
     623             : 
     624             : /** Update the relevant flags of <b>node</b> based on our opinion as a
     625             :  * directory authority in <b>authstatus</b>, as returned by
     626             :  * dirserv_router_get_status or equivalent.  */
     627             : void
     628           0 : dirserv_set_node_flags_from_authoritative_status(node_t *node,
     629             :                                                  uint32_t authstatus)
     630             : {
     631           0 :   node->is_valid = (authstatus & RTR_INVALID) ? 0 : 1;
     632           0 :   node->is_bad_exit = (authstatus & RTR_BADEXIT) ? 1 : 0;
     633           0 : }
     634             : 
     635             : /** True iff <b>a</b> is more severe than <b>b</b>. */
     636             : static int
     637           0 : WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
     638             : {
     639           0 :   return a < b;
     640             : }
     641             : 
     642             : /** As for dirserv_add_descriptor(), but accepts multiple documents, and
     643             :  * returns the most severe error that occurred for any one of them. */
     644             : was_router_added_t
     645           0 : dirserv_add_multiple_descriptors(const char *desc, size_t desclen,
     646             :                                  uint8_t purpose,
     647             :                                  const char *source,
     648             :                                  const char **msg)
     649             : {
     650           0 :   was_router_added_t r, r_tmp;
     651           0 :   const char *msg_out;
     652           0 :   smartlist_t *list;
     653           0 :   const char *s;
     654           0 :   int n_parsed = 0;
     655           0 :   time_t now = time(NULL);
     656           0 :   char annotation_buf[ROUTER_ANNOTATION_BUF_LEN];
     657           0 :   char time_buf[ISO_TIME_LEN+1];
     658           0 :   int general = purpose == ROUTER_PURPOSE_GENERAL;
     659           0 :   tor_assert(msg);
     660             : 
     661           0 :   r=ROUTER_ADDED_SUCCESSFULLY; /* Least severe return value. */
     662             : 
     663           0 :   if (!string_is_utf8_no_bom(desc, desclen)) {
     664           0 :     *msg = "descriptor(s) or extrainfo(s) not valid UTF-8 or had BOM.";
     665           0 :     return ROUTER_AUTHDIR_REJECTS;
     666             :   }
     667             : 
     668           0 :   format_iso_time(time_buf, now);
     669           0 :   if (tor_snprintf(annotation_buf, sizeof(annotation_buf),
     670             :                    "@uploaded-at %s\n"
     671             :                    "@source %s\n"
     672             :                    "%s%s%s", time_buf, escaped(source),
     673             :                    !general ? "@purpose " : "",
     674           0 :                    !general ? router_purpose_to_string(purpose) : "",
     675             :                    !general ? "\n" : "")<0) {
     676           0 :     *msg = "Couldn't format annotations";
     677           0 :     return ROUTER_AUTHDIR_BUG_ANNOTATIONS;
     678             :   }
     679             : 
     680           0 :   s = desc;
     681           0 :   list = smartlist_new();
     682           0 :   if (!router_parse_list_from_string(&s, s+desclen, list, SAVED_NOWHERE, 0, 0,
     683             :                                      annotation_buf, NULL)) {
     684           0 :     SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
     685             :         msg_out = NULL;
     686             :         tor_assert(ri->purpose == purpose);
     687             :         r_tmp = dirserv_add_descriptor(ri, &msg_out, source);
     688             :         if (WRA_MORE_SEVERE(r_tmp, r)) {
     689             :           r = r_tmp;
     690             :           *msg = msg_out;
     691             :         }
     692             :       });
     693             :   }
     694           0 :   n_parsed += smartlist_len(list);
     695           0 :   smartlist_clear(list);
     696             : 
     697           0 :   s = desc;
     698           0 :   if (!router_parse_list_from_string(&s, s+desclen, list, SAVED_NOWHERE, 1, 0,
     699             :                                      NULL, NULL)) {
     700           0 :     SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
     701             :         msg_out = NULL;
     702             : 
     703             :         r_tmp = dirserv_add_extrainfo(ei, &msg_out);
     704             :         if (WRA_MORE_SEVERE(r_tmp, r)) {
     705             :           r = r_tmp;
     706             :           *msg = msg_out;
     707             :         }
     708             :       });
     709             :   }
     710           0 :   n_parsed += smartlist_len(list);
     711           0 :   smartlist_free(list);
     712             : 
     713           0 :   if (! *msg) {
     714           0 :     if (!n_parsed) {
     715           0 :       *msg = "No descriptors found in your POST.";
     716           0 :       if (WRA_WAS_ADDED(r))
     717           0 :         r = ROUTER_IS_ALREADY_KNOWN;
     718             :     } else {
     719           0 :       *msg = "(no message)";
     720             :     }
     721             :   }
     722             : 
     723             :   return r;
     724             : }
     725             : 
     726             : /** Examine the parsed server descriptor in <b>ri</b> and maybe insert it into
     727             :  * the list of server descriptors. Set *<b>msg</b> to a message that should be
     728             :  * passed back to the origin of this descriptor, or NULL if there is no such
     729             :  * message. Use <b>source</b> to produce better log messages.
     730             :  *
     731             :  * If <b>ri</b> is not added to the list of server descriptors, free it.
     732             :  * That means the caller must not access <b>ri</b> after this function
     733             :  * returns, since it might have been freed.
     734             :  *
     735             :  * Return the status of the operation, and set *<b>msg</b> to a string
     736             :  * constant describing the status.
     737             :  *
     738             :  * This function is only called when fresh descriptors are posted, not when
     739             :  * we re-load the cache.
     740             :  */
     741             : was_router_added_t
     742           0 : dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
     743             : {
     744           0 :   was_router_added_t r;
     745           0 :   routerinfo_t *ri_old;
     746           0 :   char *desc, *nickname;
     747           0 :   const size_t desclen = ri->cache_info.signed_descriptor_len +
     748           0 :       ri->cache_info.annotations_len;
     749           0 :   const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
     750           0 :   *msg = NULL;
     751             : 
     752             :   /* If it's too big, refuse it now. Otherwise we'll cache it all over the
     753             :    * network and it'll clog everything up. */
     754           0 :   if (ri->cache_info.signed_descriptor_len > MAX_DESCRIPTOR_UPLOAD_SIZE) {
     755           0 :     log_notice(LD_DIR, "Somebody attempted to publish a router descriptor '%s'"
     756             :                " (source: %s) with size %d. Either this is an attack, or the "
     757             :                "MAX_DESCRIPTOR_UPLOAD_SIZE (%d) constant is too low.",
     758             :                ri->nickname, source, (int)ri->cache_info.signed_descriptor_len,
     759             :                MAX_DESCRIPTOR_UPLOAD_SIZE);
     760           0 :     *msg = "Router descriptor was too large.";
     761           0 :     r = ROUTER_AUTHDIR_REJECTS;
     762           0 :     goto fail;
     763             :   }
     764             : 
     765           0 :   log_info(LD_DIR, "Assessing new descriptor: %s: %s",
     766             :            ri->nickname, ri->platform);
     767             : 
     768             :   /* Check whether this descriptor is semantically identical to the last one
     769             :    * from this server.  (We do this here and not in router_add_to_routerlist
     770             :    * because we want to be able to accept the newest router descriptor that
     771             :    * another authority has, so we all converge on the same one.) */
     772           0 :   ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
     773           0 :   if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
     774           0 :       && router_differences_are_cosmetic(ri_old, ri)
     775           0 :       && !router_is_me(ri)) {
     776           0 :     log_info(LD_DIRSERV,
     777             :              "Not replacing descriptor from %s (source: %s); "
     778             :              "differences are cosmetic.",
     779             :              router_describe(ri), source);
     780           0 :     *msg = "Not replacing router descriptor; no information has changed since "
     781             :       "the last one with this identity.";
     782           0 :     r = ROUTER_IS_ALREADY_KNOWN;
     783           0 :     goto fail;
     784             :   }
     785             : 
     786             :   /* Do keypinning again ... this time, to add the pin if appropriate */
     787           0 :   int keypin_status;
     788           0 :   if (ri->cache_info.signing_key_cert) {
     789           0 :     ed25519_public_key_t *pkey = &ri->cache_info.signing_key_cert->signing_key;
     790             :     /* First let's validate this pubkey before pinning it */
     791           0 :     if (ed25519_validate_pubkey(pkey) < 0) {
     792           0 :       log_warn(LD_DIRSERV, "Received bad key from %s (source %s)",
     793             :                router_describe(ri), source);
     794           0 :       routerinfo_free(ri);
     795           0 :       return ROUTER_AUTHDIR_REJECTS;
     796             :     }
     797             : 
     798             :     /* Now pin it! */
     799           0 :     keypin_status = keypin_check_and_add(
     800             :       (const uint8_t*)ri->cache_info.identity_digest,
     801           0 :       pkey->pubkey, ! key_pinning);
     802             :   } else {
     803           0 :     keypin_status = keypin_check_lone_rsa(
     804             :       (const uint8_t*)ri->cache_info.identity_digest);
     805             : #ifndef DISABLE_DISABLING_ED25519
     806             :     if (keypin_status == KEYPIN_MISMATCH)
     807             :       keypin_status = KEYPIN_NOT_FOUND;
     808             : #endif
     809             :   }
     810           0 :   if (keypin_status == KEYPIN_MISMATCH && key_pinning) {
     811           0 :     log_info(LD_DIRSERV, "Dropping descriptor from %s (source: %s) because "
     812             :              "its key did not match an older RSA/Ed25519 keypair",
     813             :              router_describe(ri), source);
     814           0 :     *msg = "Looks like your keypair has changed? This authority previously "
     815             :       "recorded a different RSA identity for this Ed25519 identity (or vice "
     816             :       "versa.) Did you replace or copy some of your key files, but not "
     817             :       "the others? You should either restore the expected keypair, or "
     818             :       "delete your keys and restart Tor to start your relay with a new "
     819             :       "identity.";
     820           0 :     r = ROUTER_AUTHDIR_REJECTS;
     821           0 :     goto fail;
     822             :   }
     823             : 
     824             :   /* Make a copy of desc, since router_add_to_routerlist might free
     825             :    * ri and its associated signed_descriptor_t. */
     826           0 :   desc = tor_strndup(ri->cache_info.signed_descriptor_body, desclen);
     827           0 :   nickname = tor_strdup(ri->nickname);
     828             : 
     829             :   /* Tell if we're about to need to launch a test if we add this. */
     830           0 :   ri->needs_retest_if_added =
     831           0 :     dirserv_should_launch_reachability_test(ri, ri_old);
     832             : 
     833           0 :   r = router_add_to_routerlist(ri, msg, 0, 0);
     834           0 :   if (!WRA_WAS_ADDED(r)) {
     835             :     /* unless the routerinfo was fine, just out-of-date */
     836           0 :     log_info(LD_DIRSERV,
     837             :              "Did not add descriptor from '%s' (source: %s): %s.",
     838             :              nickname, source, *msg ? *msg : "(no message)");
     839             :   } else {
     840           0 :     smartlist_t *changed;
     841             : 
     842           0 :     changed = smartlist_new();
     843           0 :     smartlist_add(changed, ri);
     844           0 :     routerlist_descriptors_added(changed, 0);
     845           0 :     smartlist_free(changed);
     846           0 :     if (!*msg) {
     847           0 :       *msg =  "Descriptor accepted";
     848             :     }
     849           0 :     log_info(LD_DIRSERV,
     850             :              "Added descriptor from '%s' (source: %s): %s.",
     851             :              nickname, source, *msg);
     852             :   }
     853           0 :   tor_free(desc);
     854           0 :   tor_free(nickname);
     855           0 :   return r;
     856           0 :  fail:
     857             :   {
     858           0 :     const char *desc_digest = ri->cache_info.signed_descriptor_digest;
     859           0 :     download_status_t *dls =
     860           0 :       router_get_dl_status_by_descriptor_digest(desc_digest);
     861           0 :     if (dls) {
     862           0 :       log_info(LD_GENERAL, "Marking router with descriptor %s as rejected, "
     863             :                "and therefore undownloadable",
     864             :                hex_str(desc_digest, DIGEST_LEN));
     865           0 :       download_status_mark_impossible(dls);
     866             :     }
     867           0 :     routerinfo_free(ri);
     868             :   }
     869           0 :   return r;
     870             : }
     871             : 
     872             : /** As dirserv_add_descriptor, but for an extrainfo_t <b>ei</b>. */
     873             : static was_router_added_t
     874           0 : dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
     875             : {
     876           0 :   routerinfo_t *ri;
     877           0 :   int r;
     878           0 :   was_router_added_t rv;
     879           0 :   tor_assert(msg);
     880           0 :   *msg = NULL;
     881             : 
     882             :   /* Needs to be mutable so routerinfo_incompatible_with_extrainfo
     883             :    * can mess with some of the flags in ri->cache_info. */
     884           0 :   ri = router_get_mutable_by_digest(ei->cache_info.identity_digest);
     885           0 :   if (!ri) {
     886           0 :     *msg = "No corresponding router descriptor for extra-info descriptor";
     887           0 :     rv = ROUTER_BAD_EI;
     888           0 :     goto fail;
     889             :   }
     890             : 
     891             :   /* If it's too big, refuse it now. Otherwise we'll cache it all over the
     892             :    * network and it'll clog everything up. */
     893           0 :   if (ei->cache_info.signed_descriptor_len > MAX_EXTRAINFO_UPLOAD_SIZE) {
     894           0 :     log_notice(LD_DIR, "Somebody attempted to publish an extrainfo "
     895             :                "with size %d. Either this is an attack, or the "
     896             :                "MAX_EXTRAINFO_UPLOAD_SIZE (%d) constant is too low.",
     897             :                (int)ei->cache_info.signed_descriptor_len,
     898             :                MAX_EXTRAINFO_UPLOAD_SIZE);
     899           0 :     *msg = "Extrainfo document was too large";
     900           0 :     rv = ROUTER_BAD_EI;
     901           0 :     goto fail;
     902             :   }
     903             : 
     904           0 :   if ((r = routerinfo_incompatible_with_extrainfo(ri->identity_pkey, ei,
     905             :                                                   &ri->cache_info, msg))) {
     906           0 :     if (r<0) {
     907           0 :       extrainfo_free(ei);
     908           0 :       return ROUTER_IS_ALREADY_KNOWN;
     909             :     }
     910           0 :     rv = ROUTER_BAD_EI;
     911           0 :     goto fail;
     912             :   }
     913           0 :   router_add_extrainfo_to_routerlist(ei, msg, 0, 0);
     914           0 :   return ROUTER_ADDED_SUCCESSFULLY;
     915           0 :  fail:
     916             :   {
     917           0 :     const char *d = ei->cache_info.signed_descriptor_digest;
     918           0 :     signed_descriptor_t *sd = router_get_by_extrainfo_digest((char*)d);
     919           0 :     if (sd) {
     920           0 :       log_info(LD_GENERAL, "Marking extrainfo with descriptor %s as "
     921             :                "rejected, and therefore undownloadable",
     922             :                hex_str((char*)d,DIGEST_LEN));
     923           0 :       download_status_mark_impossible(&sd->ei_dl_status);
     924             :     }
     925           0 :     extrainfo_free(ei);
     926             :   }
     927           0 :   return rv;
     928             : }
     929             : 
     930             : /** Remove all descriptors whose nicknames or fingerprints no longer
     931             :  * are allowed by our fingerprint list. (Descriptors that used to be
     932             :  * good can become bad when we reload the fingerprint list.)
     933             :  */
     934             : static void
     935           7 : directory_remove_invalid(void)
     936             : {
     937           7 :   routerlist_t *rl = router_get_routerlist();
     938           7 :   smartlist_t *nodes = smartlist_new();
     939           7 :   smartlist_add_all(nodes, nodelist_get_list());
     940             : 
     941           7 :   SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
     942           0 :     const char *msg = NULL;
     943           0 :     const char *description;
     944           0 :     routerinfo_t *ent = node->ri;
     945           0 :     uint32_t r;
     946           0 :     if (!ent)
     947           0 :       continue;
     948           0 :     r = dirserv_router_get_status(ent, &msg, LOG_INFO);
     949           0 :     description = router_describe(ent);
     950           0 :     if (r & RTR_REJECT) {
     951           0 :       log_info(LD_DIRSERV, "Router %s is now rejected: %s",
     952             :                description, msg?msg:"");
     953           0 :       routerlist_remove(rl, ent, 0, time(NULL));
     954           0 :       continue;
     955             :     }
     956           0 :     if (bool_neq((r & RTR_INVALID), !node->is_valid)) {
     957           0 :       log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
     958             :                (r&RTR_INVALID) ? "in" : "");
     959           0 :       node->is_valid = (r&RTR_INVALID)?0:1;
     960             :     }
     961           0 :     if (bool_neq((r & RTR_BADEXIT), node->is_bad_exit)) {
     962           0 :       log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
     963             :                (r & RTR_BADEXIT) ? "bad" : "good");
     964           0 :       node->is_bad_exit = (r&RTR_BADEXIT) ? 1: 0;
     965             :     }
     966           0 :   } SMARTLIST_FOREACH_END(node);
     967             : 
     968           7 :   routerlist_assert_ok(rl);
     969           7 :   smartlist_free(nodes);
     970           7 : }

Generated by: LCOV version 1.14