📄 connection_edge.c
字号:
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 + -