tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

describe.c (9650B)


      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 describe.c
      9 * \brief Format short descriptions of relays.
     10 */
     11 
     12 #define DESCRIBE_PRIVATE
     13 
     14 #include "core/or/or.h"
     15 #include "core/or/extendinfo.h"
     16 #include "feature/nodelist/describe.h"
     17 #include "feature/nodelist/nodelist.h"
     18 #include "feature/nodelist/routerinfo.h"
     19 #include "lib/crypt_ops/crypto_ed25519.h"
     20 #include "lib/crypt_ops/crypto_format.h"
     21 
     22 #include "core/or/extend_info_st.h"
     23 #include "feature/nodelist/node_st.h"
     24 #include "feature/nodelist/routerinfo_st.h"
     25 #include "feature/nodelist/routerstatus_st.h"
     26 #include "feature/nodelist/microdesc_st.h"
     27 
     28 /** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
     29 * hold a human-readable description of a node with identity digest
     30 * <b>id_digest</b>, nickname <b>nickname</b>, and addresses <b>addr32h</b> and
     31 * <b>addr</b>.
     32 *
     33 * The <b>nickname</b>, <b>ipv6_addr</b> and <b>ipv4_addr</b> fields are
     34 * optional and may be set to NULL or the null address.
     35 *
     36 * Return a pointer to the front of <b>buf</b>.
     37 * If buf is NULL, return a string constant describing the error.
     38 */
     39 STATIC const char *
     40 format_node_description(char *buf,
     41                        const char *rsa_id_digest,
     42                        const ed25519_public_key_t *ed25519_id,
     43                        const char *nickname,
     44                        const tor_addr_t *ipv4_addr,
     45                        const tor_addr_t *ipv6_addr)
     46 {
     47  size_t rv = 0;
     48  bool has_ipv6 = ipv6_addr && !tor_addr_is_null(ipv6_addr);
     49  bool valid_ipv4 = false;
     50 
     51  if (!buf)
     52    return "<NULL BUFFER>";
     53 
     54  memset(buf, 0, NODE_DESC_BUF_LEN);
     55 
     56  if (!rsa_id_digest) {
     57    /* strlcpy() returns the length of the source string it attempted to copy,
     58     * ignoring any required truncation due to the buffer length. */
     59    rv = strlcpy(buf, "<NULL ID DIGEST>", NODE_DESC_BUF_LEN);
     60    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     61    return buf;
     62  }
     63 
     64  /* strlcat() returns the length of the concatenated string it attempted to
     65   * create, ignoring any required truncation due to the buffer length.  */
     66  rv = strlcat(buf, "$", NODE_DESC_BUF_LEN);
     67  tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     68 
     69  {
     70    char hex_digest[HEX_DIGEST_LEN+1];
     71    memset(hex_digest, 0, sizeof(hex_digest));
     72 
     73    base16_encode(hex_digest, sizeof(hex_digest),
     74                  rsa_id_digest, DIGEST_LEN);
     75    rv = strlcat(buf, hex_digest, NODE_DESC_BUF_LEN);
     76    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     77  }
     78 
     79  if (nickname) {
     80    rv = strlcat(buf, "~", NODE_DESC_BUF_LEN);
     81    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     82    rv = strlcat(buf, nickname, NODE_DESC_BUF_LEN);
     83    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     84  }
     85  if (ed25519_id) {
     86    char ed_base64[ED25519_BASE64_LEN+1];
     87    ed25519_public_to_base64(ed_base64, ed25519_id);
     88    rv = strlcat(buf, " [", NODE_DESC_BUF_LEN);
     89    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     90    rv = strlcat(buf, ed_base64, NODE_DESC_BUF_LEN);
     91    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     92    rv = strlcat(buf, "]", NODE_DESC_BUF_LEN);
     93    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     94  }
     95  if (ipv4_addr || has_ipv6) {
     96    rv = strlcat(buf, " at ", NODE_DESC_BUF_LEN);
     97    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
     98  }
     99  if (ipv4_addr) {
    100    const char *str_rv = NULL;
    101    char addr_str[TOR_ADDR_BUF_LEN];
    102    memset(addr_str, 0, sizeof(addr_str));
    103 
    104    str_rv = tor_addr_to_str(addr_str, ipv4_addr, sizeof(addr_str), 0);
    105    if (str_rv) {
    106      rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
    107      tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
    108      valid_ipv4 = true;
    109    }
    110  }
    111  /* Both addresses are valid */
    112  if (valid_ipv4 && has_ipv6) {
    113    rv = strlcat(buf, " and ", NODE_DESC_BUF_LEN);
    114    tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
    115  }
    116  if (has_ipv6) {
    117    const char *str_rv = NULL;
    118    char addr_str[TOR_ADDR_BUF_LEN];
    119    memset(addr_str, 0, sizeof(addr_str));
    120 
    121    str_rv = tor_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str), 1);
    122    if (str_rv) {
    123      rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
    124      tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
    125    }
    126  }
    127 
    128  return buf;
    129 }
    130 
    131 /** Return a human-readable description of the routerinfo_t <b>ri</b>.
    132 *
    133 * This function is not thread-safe.  Each call to this function invalidates
    134 * previous values returned by this function.
    135 */
    136 const char *
    137 router_describe(const routerinfo_t *ri)
    138 {
    139  static char buf[NODE_DESC_BUF_LEN];
    140 
    141  if (!ri)
    142    return "<null>";
    143 
    144  const ed25519_public_key_t *ed25519_id = routerinfo_get_ed25519_id(ri);
    145 
    146  return format_node_description(buf,
    147                                 ri->cache_info.identity_digest,
    148                                 ed25519_id,
    149                                 ri->nickname,
    150                                 &ri->ipv4_addr,
    151                                 &ri->ipv6_addr);
    152 }
    153 
    154 /** Return a human-readable description of the node_t <b>node</b>.
    155 *
    156 * This function is not thread-safe.  Each call to this function invalidates
    157 * previous values returned by this function.
    158 */
    159 const char *
    160 node_describe(const node_t *node)
    161 {
    162  static char buf[NODE_DESC_BUF_LEN];
    163  const char *nickname = NULL;
    164  const tor_addr_t *ipv6_addr = NULL, *ipv4_addr = NULL;
    165 
    166  if (!node)
    167    return "<null>";
    168 
    169  if (node->rs) {
    170    nickname = node->rs->nickname;
    171    ipv4_addr = &node->rs->ipv4_addr;
    172    ipv6_addr = &node->rs->ipv6_addr;
    173    /* Support consensus versions less than 28, when IPv6 addresses were in
    174     * microdescs. This code can be removed when 0.2.9 is no longer supported,
    175     * and the MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC macro is removed. */
    176    if (node->md && tor_addr_is_null(ipv6_addr)) {
    177      ipv6_addr = &node->md->ipv6_addr;
    178    }
    179  } else if (node->ri) {
    180    nickname = node->ri->nickname;
    181    ipv4_addr = &node->ri->ipv4_addr;
    182    ipv6_addr = &node->ri->ipv6_addr;
    183  } else {
    184    return "<null rs and ri>";
    185  }
    186 
    187  const ed25519_public_key_t *ed25519_id = node_get_ed25519_id(node);
    188 
    189  return format_node_description(buf,
    190                                 node->identity,
    191                                 ed25519_id,
    192                                 nickname,
    193                                 ipv4_addr,
    194                                 ipv6_addr);
    195 }
    196 
    197 /** Return a human-readable description of the routerstatus_t <b>rs</b>.
    198 *
    199 * This function is not thread-safe.  Each call to this function invalidates
    200 * previous values returned by this function.
    201 */
    202 const char *
    203 routerstatus_describe(const routerstatus_t *rs)
    204 {
    205  static char buf[NODE_DESC_BUF_LEN];
    206 
    207  if (!rs)
    208    return "<null>";
    209 
    210  return format_node_description(buf,
    211                                 rs->identity_digest,
    212                                 NULL,
    213                                 rs->nickname,
    214                                 &rs->ipv4_addr,
    215                                 &rs->ipv6_addr);
    216 }
    217 
    218 /** Return a human-readable description of the extend_info_t <b>ei</b>.
    219 *
    220 * This function is not thread-safe.  Each call to this function invalidates
    221 * previous values returned by this function.
    222 */
    223 const char *
    224 extend_info_describe(const extend_info_t *ei)
    225 {
    226  static char buf[NODE_DESC_BUF_LEN];
    227 
    228  if (!ei)
    229    return "<null>";
    230 
    231  const tor_addr_port_t *ap4 = extend_info_get_orport(ei, AF_INET);
    232  const tor_addr_port_t *ap6 = extend_info_get_orport(ei, AF_INET6);
    233  const tor_addr_t *addr4 = ap4 ? &ap4->addr : NULL;
    234  const tor_addr_t *addr6 = ap6 ? &ap6->addr : NULL;
    235 
    236  const ed25519_public_key_t *ed25519_id = &ei->ed_identity;
    237  if (ed25519_public_key_is_zero(ed25519_id))
    238    ed25519_id = NULL;
    239 
    240  return format_node_description(buf,
    241                                 ei->identity_digest,
    242                                 ed25519_id,
    243                                 ei->nickname,
    244                                 addr4,
    245                                 addr6);
    246 }
    247 
    248 /** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
    249 * verbose representation of the identity of <b>router</b>.  The format is:
    250 *  A dollar sign.
    251 *  The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
    252 *  A "=" if the router is named (no longer implemented); a "~" if it is not.
    253 *  The router's nickname.
    254 **/
    255 void
    256 router_get_verbose_nickname(char *buf, const routerinfo_t *router)
    257 {
    258  size_t rv = 0;
    259 
    260  if (!buf)
    261    return;
    262 
    263  memset(buf, 0, MAX_VERBOSE_NICKNAME_LEN+1);
    264 
    265  if (!router) {
    266    /* strlcpy() returns the length of the source string it attempted to copy,
    267     * ignoring any required truncation due to the buffer length. */
    268    rv = strlcpy(buf, "<null>", MAX_VERBOSE_NICKNAME_LEN+1);
    269    tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
    270    return;
    271  }
    272 
    273  /* strlcat() returns the length of the concatenated string it attempted to
    274   * create, ignoring any required truncation due to the buffer length.  */
    275  rv = strlcat(buf, "$", MAX_VERBOSE_NICKNAME_LEN+1);
    276  tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
    277 
    278  {
    279    char hex_digest[HEX_DIGEST_LEN+1];
    280    memset(hex_digest, 0, sizeof(hex_digest));
    281 
    282    base16_encode(hex_digest, sizeof(hex_digest),
    283                  router->cache_info.identity_digest, DIGEST_LEN);
    284    rv = strlcat(buf, hex_digest, MAX_VERBOSE_NICKNAME_LEN+1);
    285    tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
    286  }
    287 
    288  rv = strlcat(buf, "~", MAX_VERBOSE_NICKNAME_LEN+1);
    289  tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
    290 
    291  rv = strlcat(buf, router->nickname, MAX_VERBOSE_NICKNAME_LEN+1);
    292  tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
    293 }