⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 router.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  char *onion_pkey; /* Onion key, PEM-encoded. */
  char *identity_pkey; /* Identity key, PEM-encoded. */
  char digest[DIGEST_LEN];
  char published[ISO_TIME_LEN+1];
  char fingerprint[FINGERPRINT_LEN+1];
  char extra_info_digest[HEX_DIGEST_LEN+1];
  size_t onion_pkeylen, identity_pkeylen;
  size_t written;
  int result=0;
  addr_policy_t *tmpe;
  char *family_line;
  or_options_t *options = get_options();

  /* Make sure the identity key matches the one in the routerinfo. */
  if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
    log_warn(LD_BUG,"Tried to sign a router with a private key that didn't "
             "match router's public key!");
    return -1;
  }

  /* record our fingerprint, so we can include it in the descriptor */
  if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) {
    log_err(LD_BUG,"Error computing fingerprint");
    return -1;
  }

  /* PEM-encode the onion key */
  if (crypto_pk_write_public_key_to_string(router->onion_pkey,
                                           &onion_pkey,&onion_pkeylen)<0) {
    log_warn(LD_BUG,"write onion_pkey to string failed!");
    return -1;
  }

  /* PEM-encode the identity key key */
  if (crypto_pk_write_public_key_to_string(router->identity_pkey,
                                        &identity_pkey,&identity_pkeylen)<0) {
    log_warn(LD_BUG,"write identity_pkey to string failed!");
    tor_free(onion_pkey);
    return -1;
  }

  /* Encode the publication time. */
  format_iso_time(published, router->cache_info.published_on);

  if (router->declared_family && smartlist_len(router->declared_family)) {
    size_t n;
    char *family = smartlist_join_strings(router->declared_family, " ", 0, &n);
    n += strlen("family ") + 2; /* 1 for \n, 1 for \0. */
    family_line = tor_malloc(n);
    tor_snprintf(family_line, n, "family %s\n", family);
    tor_free(family);
  } else {
    family_line = tor_strdup("");
  }

  base16_encode(extra_info_digest, sizeof(extra_info_digest),
                router->cache_info.extra_info_digest, DIGEST_LEN);

  /* Generate the easy portion of the router descriptor. */
  result = tor_snprintf(s, maxlen,
                    "router %s %s %d 0 %d\n"
                    "platform %s\n"
                    "opt protocols Link 1 2 Circuit 1\n"
                    "published %s\n"
                    "opt fingerprint %s\n"
                    "uptime %ld\n"
                    "bandwidth %d %d %d\n"
                    "opt extra-info-digest %s\n%s"
                    "onion-key\n%s"
                    "signing-key\n%s"
                    "%s%s%s",
    router->nickname,
    router->address,
    router->or_port,
    decide_to_advertise_dirport(options, router->dir_port),
    router->platform,
    published,
    fingerprint,
    stats_n_seconds_working,
    (int) router->bandwidthrate,
    (int) router->bandwidthburst,
    (int) router->bandwidthcapacity,
    extra_info_digest,
    options->DownloadExtraInfo ? "opt caches-extra-info\n" : "",
    onion_pkey, identity_pkey,
    family_line,
    we_are_hibernating() ? "opt hibernating 1\n" : "",
    options->HidServDirectoryV2 ? "opt hidden-service-dir\n" : "");

  tor_free(family_line);
  tor_free(onion_pkey);
  tor_free(identity_pkey);

  if (result < 0) {
    log_warn(LD_BUG,"descriptor snprintf #1 ran out of room!");
    return -1;
  }
  /* From now on, we use 'written' to remember the current length of 's'. */
  written = result;

  if (options->ContactInfo && strlen(options->ContactInfo)) {
    const char *ci = options->ContactInfo;
    if (strchr(ci, '\n') || strchr(ci, '\r'))
      ci = escaped(ci);
    result = tor_snprintf(s+written,maxlen-written, "contact %s\n", ci);
    if (result<0) {
      log_warn(LD_BUG,"descriptor snprintf #2 ran out of room!");
      return -1;
    }
    written += result;
  }

  /* Write the exit policy to the end of 's'. */
  if (dns_seems_to_be_broken() ||
      !router->exit_policy || !smartlist_len(router->exit_policy)) {
    /* DNS is screwed up; don't claim to be an exit. */
    strlcat(s+written, "reject *:*\n", maxlen-written);
    written += strlen("reject *:*\n");
    tmpe = NULL;
  } else if (router->exit_policy) {
    int i;
    for (i = 0; i < smartlist_len(router->exit_policy); ++i) {
      tmpe = smartlist_get(router->exit_policy, i);
      result = policy_write_item(s+written, maxlen-written, tmpe);
      if (result < 0) {
        log_warn(LD_BUG,"descriptor policy_write_item ran out of room!");
        return -1;
      }
      tor_assert(result == (int)strlen(s+written));
      written += result;
      if (written+2 > maxlen) {
        log_warn(LD_BUG,"descriptor policy_write_item ran out of room (2)!");
        return -1;
      }
      s[written++] = '\n';
    }
  }

  if (written+256 > maxlen) { /* Not enough room for signature. */
    log_warn(LD_BUG,"not enough room left in descriptor for signature!");
    return -1;
  }

  /* Sign the directory */
  strlcpy(s+written, "router-signature\n", maxlen-written);
  written += strlen(s+written);
  s[written] = '\0';
  if (router_get_router_hash(s, digest) < 0) {
    return -1;
  }

  note_crypto_pk_op(SIGN_RTR);
  if (router_append_dirobj_signature(s+written,maxlen-written,
                                     digest,ident_key)<0) {
    log_warn(LD_BUG, "Couldn't sign router descriptor");
    return -1;
  }
  written += strlen(s+written);

  if (written+2 > maxlen) {
    log_warn(LD_BUG,"Not enough room to finish descriptor.");
    return -1;
  }
  /* include a last '\n' */
  s[written] = '\n';
  s[written+1] = 0;

#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
  {
    char *s_dup;
    const char *cp;
    routerinfo_t *ri_tmp;
    cp = s_dup = tor_strdup(s);
    ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL);
    if (!ri_tmp) {
      log_err(LD_BUG,
              "We just generated a router descriptor we can't parse.");
      log_err(LD_BUG, "Descriptor was: <<%s>>", s);
      return -1;
    }
    tor_free(s_dup);
    routerinfo_free(ri_tmp);
  }
#endif

  return (int)written+1;
}

/** Write the contents of <b>extrainfo</b> to the <b>maxlen</b>-byte string
 * <b>s</b>, signing them with <b>ident_key</b>.  Return 0 on success,
 * negative on failure. */
int
extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
                         crypto_pk_env_t *ident_key)
{
  or_options_t *options = get_options();
  char identity[HEX_DIGEST_LEN+1];
  char published[ISO_TIME_LEN+1];
  char digest[DIGEST_LEN];
  char *bandwidth_usage;
  int result;
  size_t len;

  base16_encode(identity, sizeof(identity),
                extrainfo->cache_info.identity_digest, DIGEST_LEN);
  format_iso_time(published, extrainfo->cache_info.published_on);
  bandwidth_usage = rep_hist_get_bandwidth_lines(1);

  result = tor_snprintf(s, maxlen,
                        "extra-info %s %s\n"
                        "published %s\n%s",
                        extrainfo->nickname, identity,
                        published, bandwidth_usage);
  tor_free(bandwidth_usage);
  if (result<0)
    return -1;

  if (options->BridgeRelay && options->BridgeRecordUsageByCountry) {
    char *geoip_summary = geoip_get_client_history(time(NULL));
    if (geoip_summary) {
      char geoip_start[ISO_TIME_LEN+1];
      format_iso_time(geoip_start, geoip_get_history_start());
      result = tor_snprintf(s+strlen(s), maxlen-strlen(s),
                            "geoip-start-time %s\n"
                            "geoip-client-origins %s\n",
                            geoip_start, geoip_summary);
      tor_free(geoip_summary);
      if (result<0)
        return -1;
    }
  }

  len = strlen(s);
  strlcat(s+len, "router-signature\n", maxlen-len);
  len += strlen(s+len);
  if (router_get_extrainfo_hash(s, digest)<0)
    return -1;
  if (router_append_dirobj_signature(s+len, maxlen-len, digest, ident_key)<0)
    return -1;

#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
  {
    char *cp, *s_dup;
    extrainfo_t *ei_tmp;
    cp = s_dup = tor_strdup(s);
    ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL);
    if (!ei_tmp) {
      log_err(LD_BUG,
              "We just generated an extrainfo descriptor we can't parse.");
      log_err(LD_BUG, "Descriptor was: <<%s>>", s);
      return -1;
    }
    tor_free(s_dup);
    extrainfo_free(ei_tmp);
  }
#endif

  return (int)strlen(s)+1;
}

/** Return true iff <b>s</b> is a legally valid server nickname. */
int
is_legal_nickname(const char *s)
{
  size_t len;
  tor_assert(s);
  len = strlen(s);
  return len > 0 && len <= MAX_NICKNAME_LEN &&
    strspn(s,LEGAL_NICKNAME_CHARACTERS) == len;
}

/** Return true iff <b>s</b> is a legally valid server nickname or
 * hex-encoded identity-key digest. */
int
is_legal_nickname_or_hexdigest(const char *s)
{
  if (*s!='$')
    return is_legal_nickname(s);
  else
    return is_legal_hexdigest(s);
}

/** Return true iff <b>s</b> is a legally valid hex-encoded identity-key
 * digest. */
int
is_legal_hexdigest(const char *s)
{
  size_t len;
  tor_assert(s);
  if (s[0] == '$') s++;
  len = strlen(s);
  if (len > HEX_DIGEST_LEN) {
    if (s[HEX_DIGEST_LEN] == '=' ||
        s[HEX_DIGEST_LEN] == '~') {
      if (!is_legal_nickname(s+HEX_DIGEST_LEN+1))
        return 0;
    } else {
      return 0;
    }
  }
  return (len >= HEX_DIGEST_LEN &&
          strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN);
}

/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
 * verbose representation of the identity of <b>router</b>.  The format is:
 *  A dollar sign.
 *  The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
 *  A "=" if the router is named; a "~" if it is not.
 *  The router's nickname.
 **/
void
router_get_verbose_nickname(char *buf, routerinfo_t *router)
{
  buf[0] = '$';
  base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
                DIGEST_LEN);
  buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
  strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}

/** Forget that we have issued any router-related warnings, so that we'll
 * warn again if we see the same errors. */
void
router_reset_warnings(void)
{
  if (warned_nonexistent_family) {
    SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));
    smartlist_clear(warned_nonexistent_family);
  }
}

/** Given a router purpose, convert it to a string.  Don't call this on
 * ROUTER_PURPOSE_UNKNOWN: The whole point of that value is that we don't
 * know its string representation. */
const char *
router_purpose_to_string(uint8_t p)
{
  switch (p)
    {
    case ROUTER_PURPOSE_GENERAL: return "general";
    case ROUTER_PURPOSE_BRIDGE: return "bridge";
    case ROUTER_PURPOSE_CONTROLLER: return "controller";
    default:
      tor_assert(0);
    }
  return NULL;
}

/** Given a string, convert it to a router purpose. */
uint8_t
router_purpose_from_string(const char *s)
{
  if (!strcmp(s, "general"))
    return ROUTER_PURPOSE_GENERAL;
  else if (!strcmp(s, "bridge"))
    return ROUTER_PURPOSE_BRIDGE;
  else if (!strcmp(s, "controller"))
    return ROUTER_PURPOSE_CONTROLLER;
  else
    return ROUTER_PURPOSE_UNKNOWN;
}

/** Release all static resources held in router.c */
void
router_free_all(void)
{
  if (onionkey)
    crypto_free_pk_env(onionkey);
  if (lastonionkey)
    crypto_free_pk_env(lastonionkey);
  if (identitykey)
    crypto_free_pk_env(identitykey);
  if (key_lock)
    tor_mutex_free(key_lock);
  if (desc_routerinfo)
    routerinfo_free(desc_routerinfo);
  if (desc_extrainfo)
    extrainfo_free(desc_extrainfo);
  if (authority_signing_key)
    crypto_free_pk_env(authority_signing_key);
  if (authority_key_certificate)
    authority_cert_free(authority_key_certificate);

  if (warned_nonexistent_family) {
    SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));
    smartlist_free(warned_nonexistent_family);
  }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -