LCOV - code coverage report
Current view: top level - core/or - extendinfo.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 72 121 59.5 %
Date: 2021-11-24 03:28:48 Functions: 8 13 61.5 %

          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 extendinfo.c
       9             :  * @brief Functions for creating and using extend_info_t objects.
      10             :  *
      11             :  * An extend_info_t is the information we hold about a relay in order to
      12             :  * extend a circuit to it.
      13             :  **/
      14             : 
      15             : #include "core/or/or.h"
      16             : #include "core/or/extendinfo.h"
      17             : 
      18             : #include "app/config/config.h"
      19             : #include "core/or/policies.h"
      20             : #include "feature/nodelist/describe.h"
      21             : #include "feature/nodelist/nodelist.h"
      22             : #include "feature/relay/router.h"
      23             : #include "feature/relay/routermode.h"
      24             : #include "lib/crypt_ops/crypto_rand.h"
      25             : 
      26             : #include "core/or/extend_info_st.h"
      27             : #include "feature/nodelist/node_st.h"
      28             : #include "feature/nodelist/routerinfo_st.h"
      29             : #include "feature/nodelist/routerstatus_st.h"
      30             : 
      31             : /** Allocate a new extend_info object based on the various arguments. */
      32             : extend_info_t *
      33         145 : extend_info_new(const char *nickname,
      34             :                 const char *rsa_id_digest,
      35             :                 const ed25519_public_key_t *ed_id,
      36             :                 crypto_pk_t *onion_key,
      37             :                 const curve25519_public_key_t *ntor_key,
      38             :                 const tor_addr_t *addr, uint16_t port)
      39             : {
      40         145 :   extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
      41         145 :   if (rsa_id_digest)
      42         145 :     memcpy(info->identity_digest, rsa_id_digest, DIGEST_LEN);
      43         145 :   if (ed_id && !ed25519_public_key_is_zero(ed_id))
      44           0 :     memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
      45         145 :   if (nickname)
      46          53 :     strlcpy(info->nickname, nickname, sizeof(info->nickname));
      47         145 :   if (onion_key)
      48           0 :     info->onion_key = crypto_pk_dup_key(onion_key);
      49         145 :   if (ntor_key)
      50         102 :     memcpy(&info->curve25519_onion_key, ntor_key,
      51             :            sizeof(curve25519_public_key_t));
      52         435 :   for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
      53         290 :     tor_addr_make_unspec(&info->orports[i].addr);
      54             :   }
      55             : 
      56         145 :   if (addr) {
      57         145 :     extend_info_add_orport(info, addr, port);
      58             :   }
      59         145 :   return info;
      60             : }
      61             : 
      62             : /**
      63             :  * Add another address:port pair to a given extend_info_t, if there is
      64             :  * room.  Return 0 on success, -1 on failure.
      65             :  **/
      66             : int
      67         145 : extend_info_add_orport(extend_info_t *ei,
      68             :                        const tor_addr_t *addr,
      69             :                        uint16_t port)
      70             : {
      71         145 :   for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
      72         145 :     if (tor_addr_is_unspec(&ei->orports[i].addr)) {
      73         145 :       tor_addr_copy(&ei->orports[i].addr, addr);
      74         145 :       ei->orports[i].port = port;
      75         145 :       return 0;
      76             :     }
      77             :   }
      78             :   return -1;
      79             : }
      80             : 
      81             : /** Allocate and return a new extend_info that can be used to build a
      82             :  * circuit to or through the node <b>node</b>. Use the primary address
      83             :  * of the node (i.e. its IPv4 address) unless
      84             :  * <b>for_direct_connect</b> is true, in which case the preferred
      85             :  * address is used instead. May return NULL if there is not enough
      86             :  * info about <b>node</b> to extend to it--for example, if the preferred
      87             :  * routerinfo_t or microdesc_t is missing, or if for_direct_connect is
      88             :  * true and none of the node's addresses is allowed by tor's firewall
      89             :  * and IP version config.
      90             :  **/
      91             : extend_info_t *
      92          21 : extend_info_from_node(const node_t *node, int for_direct_connect)
      93             : {
      94          21 :   crypto_pk_t *rsa_pubkey = NULL;
      95          21 :   extend_info_t *info = NULL;
      96          21 :   tor_addr_port_t ap;
      97          21 :   int valid_addr = 0;
      98             : 
      99          21 :   if (!node_has_preferred_descriptor(node, for_direct_connect)) {
     100             :     return NULL;
     101             :   }
     102             : 
     103             :   /* Choose a preferred address first, but fall back to an allowed address. */
     104          21 :   if (for_direct_connect)
     105           6 :     reachable_addr_choose_from_node(node, FIREWALL_OR_CONNECTION, 0, &ap);
     106             :   else {
     107          15 :     node_get_prim_orport(node, &ap);
     108             :   }
     109          21 :   valid_addr = tor_addr_port_is_valid_ap(&ap, 0);
     110             : 
     111          21 :   if (valid_addr)
     112          21 :     log_debug(LD_CIRC, "using %s for %s",
     113             :               fmt_addrport(&ap.addr, ap.port),
     114             :               node->ri ? node->ri->nickname : node->rs->nickname);
     115             :   else
     116           0 :     log_warn(LD_CIRC, "Could not choose valid address for %s",
     117             :               node->ri ? node->ri->nickname : node->rs->nickname);
     118             : 
     119             :   /* Every node we connect or extend to must support ntor */
     120          21 :   if (!node_has_curve25519_onion_key(node)) {
     121           0 :     log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
     122             :            "Attempted to create extend_info for a node that does not support "
     123             :            "ntor: %s", node_describe(node));
     124           0 :     return NULL;
     125             :   }
     126             : 
     127          21 :   const ed25519_public_key_t *ed_pubkey = NULL;
     128             : 
     129             :   /* Don't send the ed25519 pubkey unless the target node actually supports
     130             :    * authenticating with it. */
     131          21 :   if (node_supports_ed25519_link_authentication(node, 0)) {
     132           0 :     log_info(LD_CIRC, "Including Ed25519 ID for %s", node_describe(node));
     133           0 :     ed_pubkey = node_get_ed25519_id(node);
     134          21 :   } else if (node_get_ed25519_id(node)) {
     135           0 :     log_info(LD_CIRC, "Not including the ed25519 ID for %s, since it won't "
     136             :              "be able to authenticate it.",
     137             :              node_describe(node));
     138             :   }
     139             : 
     140             :   /* Retrieve the curve25519 pubkey. */
     141          21 :   const curve25519_public_key_t *curve_pubkey =
     142          21 :     node_get_curve25519_onion_key(node);
     143          21 :   rsa_pubkey = node_get_rsa_onion_key(node);
     144             : 
     145          21 :   if (valid_addr && node->ri) {
     146           0 :     info = extend_info_new(node->ri->nickname,
     147           0 :                            node->identity,
     148             :                            ed_pubkey,
     149             :                            rsa_pubkey,
     150             :                            curve_pubkey,
     151             :                            &ap.addr,
     152           0 :                            ap.port);
     153          21 :   } else if (valid_addr && node->rs && node->md) {
     154          21 :     info = extend_info_new(node->rs->nickname,
     155          21 :                            node->identity,
     156             :                            ed_pubkey,
     157             :                            rsa_pubkey,
     158             :                            curve_pubkey,
     159             :                            &ap.addr,
     160          21 :                            ap.port);
     161             :   }
     162             : 
     163          21 :   crypto_pk_free(rsa_pubkey);
     164          21 :   return info;
     165             : }
     166             : 
     167             : /** Release storage held by an extend_info_t struct. */
     168             : void
     169         363 : extend_info_free_(extend_info_t *info)
     170             : {
     171         363 :   if (!info)
     172             :     return;
     173         166 :   crypto_pk_free(info->onion_key);
     174         166 :   tor_free(info);
     175             : }
     176             : 
     177             : /** Allocate and return a new extend_info_t with the same contents as
     178             :  * <b>info</b>. */
     179             : extend_info_t *
     180          62 : extend_info_dup(extend_info_t *info)
     181             : {
     182          62 :   extend_info_t *newinfo;
     183          62 :   tor_assert(info);
     184          62 :   newinfo = tor_malloc(sizeof(extend_info_t));
     185          62 :   memcpy(newinfo, info, sizeof(extend_info_t));
     186          62 :   if (info->onion_key)
     187           0 :     newinfo->onion_key = crypto_pk_dup_key(info->onion_key);
     188             :   else
     189          62 :     newinfo->onion_key = NULL;
     190          62 :   return newinfo;
     191             : }
     192             : 
     193             : /* Does ei have a valid TAP key? */
     194             : int
     195           0 : extend_info_supports_tap(const extend_info_t* ei)
     196             : {
     197           0 :   tor_assert(ei);
     198             :   /* Valid TAP keys are not NULL */
     199           0 :   return ei->onion_key != NULL;
     200             : }
     201             : 
     202             : /* Does ei have a valid ntor key? */
     203             : int
     204           8 : extend_info_supports_ntor(const extend_info_t* ei)
     205             : {
     206           8 :   tor_assert(ei);
     207             :   /* Valid ntor keys have at least one non-zero byte */
     208           8 :   return !fast_mem_is_zero(
     209           8 :                           (const char*)ei->curve25519_onion_key.public_key,
     210             :                           CURVE25519_PUBKEY_LEN);
     211             : }
     212             : 
     213             : /* Does ei have an onion key which it would prefer to use?
     214             :  * Currently, we prefer ntor keys*/
     215             : int
     216           0 : extend_info_has_preferred_onion_key(const extend_info_t* ei)
     217             : {
     218           0 :   tor_assert(ei);
     219           0 :   return extend_info_supports_ntor(ei);
     220             : }
     221             : 
     222             : /** Return true iff the given address can be used to extend to. */
     223             : int
     224          81 : extend_info_addr_is_allowed(const tor_addr_t *addr)
     225             : {
     226          81 :   tor_assert(addr);
     227             : 
     228             :   /* Check if we have a private address and if we can extend to it. */
     229          81 :   if ((tor_addr_is_internal(addr, 0) || tor_addr_is_multicast(addr)) &&
     230           0 :       !get_options()->ExtendAllowPrivateAddresses) {
     231           0 :     goto disallow;
     232             :   }
     233             :   /* Allowed! */
     234             :   return 1;
     235           0 :  disallow:
     236           0 :   return 0;
     237             : }
     238             : 
     239             : /**
     240             :  * Return true if @a addr : @a port is a listed ORPort in @a ei.
     241             :  **/
     242             : bool
     243           0 : extend_info_has_orport(const extend_info_t *ei,
     244             :                        const tor_addr_t *addr, uint16_t port)
     245             : {
     246           0 :   IF_BUG_ONCE(ei == NULL) {
     247             :     return false;
     248             :   }
     249             : 
     250           0 :   for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
     251           0 :     const tor_addr_port_t *ei_ap = &ei->orports[i];
     252           0 :     if (tor_addr_eq(&ei_ap->addr, addr) && ei_ap->port == port)
     253             :       return true;
     254             :   }
     255             :   return false;
     256             : }
     257             : 
     258             : /**
     259             :  * If the extend_info @a ei has an orport of the chosen family, then return
     260             :  * that orport.  Otherwise, return NULL.
     261             :  **/
     262             : const tor_addr_port_t *
     263          58 : extend_info_get_orport(const extend_info_t *ei, int family)
     264             : {
     265         120 :   for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
     266          89 :     if (tor_addr_is_unspec(&ei->orports[i].addr))
     267          35 :       continue;
     268          54 :     if (tor_addr_family(&ei->orports[i].addr) == family)
     269          27 :       return &ei->orports[i];
     270             :   }
     271             :   return NULL;
     272             : }
     273             : 
     274             : /**
     275             :  * Chose an addr_port_t within @a ei to connect to.
     276             :  **/
     277             : const tor_addr_port_t *
     278           0 : extend_info_pick_orport(const extend_info_t *ei)
     279             : {
     280           0 :   IF_BUG_ONCE(!ei) {
     281             :     return NULL;
     282             :   }
     283           0 :   const or_options_t *options = get_options();
     284           0 :   if (!server_mode(options)) {
     285             :     // If we aren't a server, just pick the first address we built into
     286             :     // this extendinfo.
     287           0 :     return &ei->orports[0];
     288             :   }
     289             : 
     290           0 :   const bool ipv6_ok = router_can_extend_over_ipv6(options);
     291             : 
     292             :   // Use 'usable' to collect the usable orports, then pick one.
     293           0 :   const tor_addr_port_t *usable[EXTEND_INFO_MAX_ADDRS];
     294           0 :   int n_usable = 0;
     295           0 :   for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
     296           0 :     const tor_addr_port_t *a = &ei->orports[i];
     297           0 :     const int family = tor_addr_family(&a->addr);
     298           0 :     if (family == AF_INET || (ipv6_ok && family == AF_INET6)) {
     299           0 :       usable[n_usable++] = a;
     300             :     }
     301             :   }
     302             : 
     303           0 :   if (n_usable == 0) {
     304             :     // Need to bail out early, since nothing will work.
     305             :     return NULL;
     306             :   }
     307             : 
     308           0 :   crypto_fast_rng_t *rng = get_thread_fast_rng();
     309           0 :   const int idx = crypto_fast_rng_get_uint(rng, n_usable);
     310             : 
     311           0 :   return usable[idx];
     312             : }
     313             : 
     314             : /**
     315             :  * Return true if any orport address in @a ei is an internal address.
     316             :  **/
     317             : bool
     318           0 : extend_info_any_orport_addr_is_internal(const extend_info_t *ei)
     319             : {
     320           0 :   IF_BUG_ONCE(ei == NULL) {
     321             :     return false;
     322             :   }
     323             : 
     324           0 :   for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
     325           0 :     if (! tor_addr_is_unspec(&ei->orports[i].addr) &&
     326           0 :         tor_addr_is_internal(&ei->orports[i].addr, 0))
     327             :       return true;
     328             :   }
     329             :   return false;
     330             : }

Generated by: LCOV version 1.14