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

📄 connection_edge.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static char *
addressmap_get_virtual_address(int type)
{
  char buf[64];
  struct in_addr in;
  tor_assert(addressmap);

  if (type == RESOLVED_TYPE_HOSTNAME) {
    char rand[10];
    do {
      crypto_rand(rand, sizeof(rand));
      base32_encode(buf,sizeof(buf),rand,sizeof(rand));
      strlcat(buf, ".virtual", sizeof(buf));
    } while (strmap_get(addressmap, buf));
    return tor_strdup(buf);
  } else if (type == RESOLVED_TYPE_IPV4) {
    // This is an imperfect estimate of how many addresses are available, but
    // that's ok.
    uint32_t available = 1u << (32-virtual_addr_netmask_bits);
    while (available) {
      /* Don't hand out any .0 or .255 address. */
      while ((next_virtual_addr & 0xff) == 0 ||
             (next_virtual_addr & 0xff) == 0xff) {
        ++next_virtual_addr;
      }
      in.s_addr = htonl(next_virtual_addr);
      tor_inet_ntoa(&in, buf, sizeof(buf));
      if (!strmap_get(addressmap, buf)) {
        ++next_virtual_addr;
        break;
      }

      ++next_virtual_addr;
      --available;
      log_info(LD_CONFIG, "%d addrs available", (int)available);
      if (! --available) {
        log_warn(LD_CONFIG, "Ran out of virtual addresses!");
        return NULL;
      }
      if (addr_mask_cmp_bits(next_virtual_addr, virtual_addr_network,
                             virtual_addr_netmask_bits))
        next_virtual_addr = virtual_addr_network;
    }
    return tor_strdup(buf);
  } else {
    log_warn(LD_BUG, "Called with unsupported address type (%d)", type);
    return NULL;
  }
}

/** A controller has requested that we map some address of type
 * <b>type</b> to the address <b>new_address</b>.  Choose an address
 * that is unlikely to be used, and map it, and return it in a newly
 * allocated string.  If another address of the same type is already
 * mapped to <b>new_address</b>, try to return a copy of that address.
 *
 * The string in <b>new_address</b> may be freed, or inserted into a map
 * as appropriate.
 **/
const char *
addressmap_register_virtual_address(int type, char *new_address)
{
  char **addrp;
  virtaddress_entry_t *vent;

  tor_assert(new_address);
  tor_assert(addressmap);
  tor_assert(virtaddress_reversemap);

  vent = strmap_get(virtaddress_reversemap, new_address);
  if (!vent) {
    vent = tor_malloc_zero(sizeof(virtaddress_entry_t));
    strmap_set(virtaddress_reversemap, new_address, vent);
  }

  addrp = (type == RESOLVED_TYPE_IPV4) ?
    &vent->ipv4_address : &vent->hostname_address;
  if (*addrp) {
    addressmap_entry_t *ent = strmap_get(addressmap, *addrp);
    if (ent && ent->new_address &&
        !strcasecmp(new_address, ent->new_address)) {
      tor_free(new_address);
      return tor_strdup(*addrp);
    } else
      log_warn(LD_BUG,
               "Internal confusion: I thought that '%s' was mapped to by "
               "'%s', but '%s' really maps to '%s'. This is a harmless bug.",
               safe_str(new_address), safe_str(*addrp), safe_str(*addrp),
               ent?safe_str(ent->new_address):"(nothing)");
  }

  tor_free(*addrp);
  *addrp = addressmap_get_virtual_address(type);
  log_info(LD_APP, "Registering map from %s to %s", *addrp, new_address);
  addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_CONTROLLER);

#if 0
  {
    /* Try to catch possible bugs */
    addressmap_entry_t *ent;
    ent = strmap_get(addressmap, *addrp);
    tor_assert(ent);
    tor_assert(!strcasecmp(ent->new_address,new_address));
    vent = strmap_get(virtaddress_reversemap, new_address);
    tor_assert(vent);
    tor_assert(!strcasecmp(*addrp,
                           (type == RESOLVED_TYPE_IPV4) ?
                           vent->ipv4_address : vent->hostname_address));
    log_info(LD_APP, "Map from %s to %s okay.",
           safe_str(*addrp),safe_str(new_address));
  }
#endif

  return *addrp;
}

/** Return 1 if <b>address</b> has funny characters in it like colons. Return
 * 0 if it's fine, or if we're configured to allow it anyway.  <b>client</b>
 * should be true if we're using this address as a client; false if we're
 * using it as a server.
 */
int
address_is_invalid_destination(const char *address, int client)
{
  if (client) {
    if (get_options()->AllowNonRFC953Hostnames)
      return 0;
  } else {
    if (get_options()->ServerDNSAllowNonRFC953Hostnames)
      return 0;
  }

  while (*address) {
    if (TOR_ISALNUM(*address) ||
        *address == '-' ||
        *address == '.' ||
        *address == '_') /* Underscore is not allowed, but Windows does it
                          * sometimes, just to thumb its nose at the IETF. */
      ++address;
    else
      return 1;
  }
  return 0;
}

/** Iterate over all address mappings which have expiry times between
 * min_expires and max_expires, inclusive.  If sl is provided, add an
 * "old-addr new-addr expiry" string to sl for each mapping, omitting
 * the expiry time if want_expiry is false. If sl is NULL, remove the
 * mappings.
 */
void
addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
                        time_t max_expires, int want_expiry)
{
   strmap_iter_t *iter;
   const char *key;
   void *_val;
   addressmap_entry_t *val;

   if (!addressmap)
     addressmap_init();

   for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) {
     strmap_iter_get(iter, &key, &_val);
     val = _val;
     if (val->expires >= min_expires && val->expires <= max_expires) {
       if (!sl) {
         iter = strmap_iter_next_rmv(addressmap,iter);
         addressmap_ent_remove(key, val);
         continue;
       } else if (val->new_address) {
         size_t len = strlen(key)+strlen(val->new_address)+ISO_TIME_LEN+5;
         char *line = tor_malloc(len);
         if (want_expiry) {
           if (val->expires < 3 || val->expires == TIME_MAX)
             tor_snprintf(line, len, "%s %s NEVER", key, val->new_address);
           else {
             char time[ISO_TIME_LEN+1];
             format_iso_time(time, val->expires);
             tor_snprintf(line, len, "%s %s \"%s\"", key, val->new_address,
                          time);
           }
         } else {
           tor_snprintf(line, len, "%s %s", key, val->new_address);
         }
         smartlist_add(sl, line);
       }
     }
     iter = strmap_iter_next(addressmap,iter);
   }
}

/** Check if <b>conn</b> is using a dangerous port. Then warn and/or
 * reject depending on our config options. */
static int
consider_plaintext_ports(edge_connection_t *conn, uint16_t port)
{
  or_options_t *options = get_options();
  int reject = smartlist_string_num_isin(options->RejectPlaintextPorts, port);

  if (smartlist_string_num_isin(options->WarnPlaintextPorts, port)) {
    log_warn(LD_APP, "Application request to port %d: this port is "
             "commonly used for unencrypted protocols. Please make sure "
             "you don't send anything you would mind the rest of the "
             "Internet reading!%s", port, reject ? " Closing." : "");
    control_event_client_status(LOG_WARN, "DANGEROUS_PORT PORT=%d RESULT=%s",
                                port, reject ? "REJECT" : "WARN");
  }

  if (reject) {
    log_info(LD_APP, "Port %d listed in RejectPlaintextPorts. Closing.", port);
    connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
    return -1;
  }

  return 0;
}

/** Connection <b>conn</b> just finished its socks handshake, or the
 * controller asked us to take care of it. If <b>circ</b> is defined,
 * then that's where we'll want to attach it. Otherwise we have to
 * figure it out ourselves.
 *
 * First, parse whether it's a .exit address, remap it, and so on. Then
 * if it's for a general circuit, try to attach it to a circuit (or launch
 * one as needed), else if it's for a rendezvous circuit, fetch a
 * rendezvous descriptor first (or attach/launch a circuit if the
 * rendezvous descriptor is already here and fresh enough).
 *
 * The stream will exit from the hop
 * indicated by <b>cpath</b>, or from the last hop in circ's cpath if
 * <b>cpath</b> is NULL.
 */
int
connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
                                           origin_circuit_t *circ,
                                           crypt_path_t *cpath)
{
  socks_request_t *socks = conn->socks_request;
  hostname_type_t addresstype;
  or_options_t *options = get_options();
  struct in_addr addr_tmp;
  int automap = 0;
  char orig_address[MAX_SOCKS_ADDR_LEN];
  time_t map_expires = TIME_MAX;
  int remapped_to_exit = 0;
  time_t now = time(NULL);

  tor_strlower(socks->address); /* normalize it */
  strlcpy(orig_address, socks->address, sizeof(orig_address));
  log_debug(LD_APP,"Client asked for %s:%d",
            safe_str(socks->address),
            socks->port);

  if (socks->command == SOCKS_COMMAND_RESOLVE &&
      !tor_inet_aton(socks->address, &addr_tmp) &&
      options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) {
    SMARTLIST_FOREACH(options->AutomapHostsSuffixes, const char *, cp,
                      if (!strcasecmpend(socks->address, cp)) {
                        automap = 1;
                        break;
                      });
    if (automap) {
      const char *new_addr;
      new_addr = addressmap_register_virtual_address(
                              RESOLVED_TYPE_IPV4, tor_strdup(socks->address));
      tor_assert(new_addr);
      log_info(LD_APP, "Automapping %s to %s",
               escaped_safe_str(socks->address), safe_str(new_addr));
      strlcpy(socks->address, new_addr, sizeof(socks->address));
    }
  }

  if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
    if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address),
                                   &map_expires)) {
      char *result = tor_strdup(socks->address);
      /* remember _what_ is supposed to have been resolved. */
      tor_snprintf(socks->address, sizeof(socks->address), "REVERSE[%s]",
                  orig_address);
      connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME,
                                             strlen(result), result, -1,
                                             map_expires);
      connection_mark_unattached_ap(conn,
                                END_STREAM_REASON_DONE |
                                END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED |
                                END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED);
      return 0;
    }
    if (options->ClientDNSRejectInternalAddresses) {
      /* Don't let people try to do a reverse lookup on 10.0.0.1. */
      tor_addr_t addr;
      struct in_addr in;
      int ok;
      if (!strcasecmpend(socks->address, ".in-addr.arpa"))
        ok = !parse_inaddr_arpa_address(socks->address, &in);
      else
        ok = tor_inet_aton(socks->address, &in);
      /*XXXX021 make this a function. */
      addr.family = AF_INET;
      memcpy(&addr.addr.in_addr, &in, sizeof(struct in_addr));

      if (ok && tor_addr_is_internal(&addr, 0)) {
        connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR,
                                               0, NULL, -1, TIME_MAX);
        connection_mark_unattached_ap(conn,
                                 END_STREAM_REASON_SOCKSPROTOCOL |
                                 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
        return -1;
      }
    }
  } else if (!automap) {
    int started_without_chosen_exit = strcasecmpend(socks->address, ".exit");
    /* For address map controls, remap the address. */
    if (addressmap_rewrite(socks->address, sizeof(socks->address),
                           &map_expires)) {
      control_event_stream_status(conn, STREAM_EVENT_REMAP,
                                  REMAP_STREAM_SOURCE_CACHE);
      if (started_without_chosen_exit &&
          !strcasecmpend(socks->address, ".exit") &&
          map_expires < TIME_MAX)
        remapped_to_exit = 1;
    }
  }

  if (!automap && address_is_in_virtual_range(socks->address)) {
    /* This address was probably handed out by client_dns_get_unmapped_address,
     * but the mapping was discarded for some reason.  We *don't* want to send
     * the address through Tor; that's likely to fail, and may leak
     * information.
     */
    log_warn(LD_APP,"Missing mapping for virtual address '%s'. Refusing.",
             socks->address); /* don't safe_str() this yet. */
    connection_mark_unattached_ap(conn, END_STREAM_REASON_INTERNAL);
    return -1;
  }

  /* Parse the address provided by SOCKS.  Modify it in-place if it
   * specifies a hidden-service (.onion) or particular exit node (.exit).
   */
  addresstype = parse_extended_hostname(socks->address);

  if (addresstype == BAD_HOSTNAME) {
    log_warn(LD_APP, "Invalid hostname %s; rejecting", socks->address);
    control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
                                escaped(socks->address));
    connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
    return -1;
  }

  if (addresstype == EXIT_HOSTNAME) {
    /* foo.exit -- modify conn->chosen_exit_node to specify the exit
     * node, and conn->address to hold only the address portion.*/
    char *s = strrchr(socks->address,'.');
    tor_assert(!automap);
    if (s) {

⌨️ 快捷键说明

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