|
@@ -705,21 +705,37 @@ connection_ap_process_end_not_open(
|
|
|
switch (reason) {
|
|
|
case END_STREAM_REASON_EXITPOLICY:
|
|
|
if (rh->length >= 5) {
|
|
|
- uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
|
|
|
- int ttl;
|
|
|
- if (!addr) {
|
|
|
+ tor_addr_t addr;
|
|
|
+ int ttl = -1;
|
|
|
+ tor_addr_make_unspec(&addr);
|
|
|
+ if (rh->length == 5 || rh->length == 9) {
|
|
|
+ tor_addr_from_ipv4n(&addr,
|
|
|
+ get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
|
|
|
+ if (rh->length == 9)
|
|
|
+ ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
|
|
|
+ } else if (rh->length == 17 || rh->length == 21) {
|
|
|
+ tor_addr_from_ipv6_bytes(&addr,
|
|
|
+ (char*)(cell->payload+RELAY_HEADER_SIZE+1));
|
|
|
+ if (rh->length == 21)
|
|
|
+ ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+17));
|
|
|
+ }
|
|
|
+ if (tor_addr_is_null(&addr)) {
|
|
|
log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,",
|
|
|
safe_str(conn->socks_request->address));
|
|
|
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
return 0;
|
|
|
}
|
|
|
- if (rh->length >= 9)
|
|
|
- ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
|
|
|
- else
|
|
|
- ttl = -1;
|
|
|
|
|
|
+ if ((tor_addr_family(&addr) == AF_INET && !conn->ipv4_traffic_ok) ||
|
|
|
+ (tor_addr_family(&addr) == AF_INET6 && !conn->ipv6_traffic_ok)) {
|
|
|
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
|
|
+ "Got an EXITPOLICY failure on a connection with a "
|
|
|
+ "mismatched family. Closing.");
|
|
|
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
if (get_options()->ClientDNSRejectInternalAddresses &&
|
|
|
- is_internal_IP(addr, 0)) {
|
|
|
+ tor_addr_is_internal(&addr, 0)) {
|
|
|
log_info(LD_APP,"Address '%s' resolved to internal. Closing,",
|
|
|
safe_str(conn->socks_request->address));
|
|
|
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
@@ -727,7 +743,7 @@ connection_ap_process_end_not_open(
|
|
|
}
|
|
|
|
|
|
client_dns_set_addressmap(circ,
|
|
|
- conn->socks_request->address, addr,
|
|
|
+ conn->socks_request->address, &addr,
|
|
|
conn->chosen_exit_name, ttl);
|
|
|
}
|
|
|
/* check if he *ought* to have allowed it */
|
|
@@ -830,20 +846,56 @@ connection_ap_process_end_not_open(
|
|
|
}
|
|
|
|
|
|
/** Helper: change the socks_request->address field on conn to the
|
|
|
- * dotted-quad representation of <b>new_addr</b> (given in host order),
|
|
|
+ * dotted-quad representation of <b>new_addr</b>,
|
|
|
* and send an appropriate REMAP event. */
|
|
|
static void
|
|
|
-remap_event_helper(entry_connection_t *conn, uint32_t new_addr)
|
|
|
+remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr)
|
|
|
{
|
|
|
- struct in_addr in;
|
|
|
-
|
|
|
- in.s_addr = htonl(new_addr);
|
|
|
- tor_inet_ntoa(&in, conn->socks_request->address,
|
|
|
- sizeof(conn->socks_request->address));
|
|
|
+ tor_addr_to_str(conn->socks_request->address, new_addr,
|
|
|
+ sizeof(conn->socks_request->address),
|
|
|
+ 0); /* XXXXX Should decorate be 1? */
|
|
|
control_event_stream_status(conn, STREAM_EVENT_REMAP,
|
|
|
REMAP_STREAM_SOURCE_EXIT);
|
|
|
}
|
|
|
|
|
|
+/**DOCDOC*/
|
|
|
+int
|
|
|
+connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
|
|
|
+ tor_addr_t *addr_out, int *ttl_out)
|
|
|
+{
|
|
|
+ uint32_t bytes;
|
|
|
+ const uint8_t *payload = cell->payload + RELAY_HEADER_SIZE;
|
|
|
+
|
|
|
+ tor_addr_make_unspec(addr_out);
|
|
|
+ *ttl_out = -1;
|
|
|
+ if (rh->length == 0)
|
|
|
+ return 0;
|
|
|
+ if (rh->length < 4)
|
|
|
+ return -1;
|
|
|
+ bytes = ntohl(get_uint32(payload));
|
|
|
+
|
|
|
+ /* If bytes is 0, this is maybe a v6 address. Otherwise it's a v4 address */
|
|
|
+ if (bytes != 0) {
|
|
|
+ /* v4 address */
|
|
|
+ tor_addr_from_ipv4h(addr_out, bytes);
|
|
|
+ if (rh->length >= 8) {
|
|
|
+ bytes = ntohl(get_uint32(payload + 4));
|
|
|
+ if (bytes <= INT32_MAX)
|
|
|
+ *ttl_out = bytes;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (rh->length < 25) /* 4 bytes of 0s, 1 addr, 16 ipv4, 4 ttl. */
|
|
|
+ return -1;
|
|
|
+ if (get_uint8(payload + 4) != 6)
|
|
|
+ return -1;
|
|
|
+ tor_addr_from_ipv6_bytes(addr_out, (char*)(payload + 5));
|
|
|
+ bytes = ntohl(get_uint32(payload + 21));
|
|
|
+ if (bytes <= INT32_MAX)
|
|
|
+ *ttl_out = (int) bytes;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/** An incoming relay cell has arrived from circuit <b>circ</b> to
|
|
|
* stream <b>conn</b>.
|
|
|
*
|
|
@@ -874,6 +926,8 @@ connection_edge_process_relay_cell_not_open(
|
|
|
|
|
|
if (conn->base_.type == CONN_TYPE_AP &&
|
|
|
rh->command == RELAY_COMMAND_CONNECTED) {
|
|
|
+ tor_addr_t addr;
|
|
|
+ int ttl;
|
|
|
entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
|
|
|
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
|
|
if (conn->base_.state != AP_CONN_STATE_CONNECT_WAIT) {
|
|
@@ -884,27 +938,41 @@ connection_edge_process_relay_cell_not_open(
|
|
|
conn->base_.state = AP_CONN_STATE_OPEN;
|
|
|
log_info(LD_APP,"'connected' received after %d seconds.",
|
|
|
(int)(time(NULL) - conn->base_.timestamp_lastread));
|
|
|
- if (rh->length >= 4) {
|
|
|
- uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
|
|
|
- int ttl;
|
|
|
- if (!addr || (get_options()->ClientDNSRejectInternalAddresses &&
|
|
|
- is_internal_IP(addr, 0))) {
|
|
|
+ if (connected_cell_parse(rh, cell, &addr, &ttl) < 0) {
|
|
|
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
|
|
+ "Got a badly formatted connected cell. Closing.");
|
|
|
+ connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ }
|
|
|
+ if (tor_addr_family(&addr) != AF_UNSPEC) {
|
|
|
+ const sa_family_t family = tor_addr_family(&addr);
|
|
|
+ if (tor_addr_is_null(&addr) ||
|
|
|
+ (get_options()->ClientDNSRejectInternalAddresses &&
|
|
|
+ tor_addr_is_internal(&addr, 0))) {
|
|
|
log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
|
|
|
- fmt_addr32(addr));
|
|
|
+ fmt_addr(&addr));
|
|
|
+ connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ connection_mark_unattached_ap(entry_conn,
|
|
|
+ END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((family == AF_INET && ! entry_conn->ipv4_traffic_ok) ||
|
|
|
+ (family == AF_INET6 && ! entry_conn->ipv6_traffic_ok)) {
|
|
|
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
|
|
+ "Got a connected cell to %s with unsupported address family."
|
|
|
+ " Closing.", fmt_addr(&addr));
|
|
|
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
connection_mark_unattached_ap(entry_conn,
|
|
|
END_STREAM_REASON_TORPROTOCOL);
|
|
|
return 0;
|
|
|
}
|
|
|
- if (rh->length >= 8)
|
|
|
- ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
|
|
|
- else
|
|
|
- ttl = -1;
|
|
|
+
|
|
|
client_dns_set_addressmap(TO_ORIGIN_CIRCUIT(circ),
|
|
|
- entry_conn->socks_request->address, addr,
|
|
|
+ entry_conn->socks_request->address, &addr,
|
|
|
entry_conn->chosen_exit_name, ttl);
|
|
|
|
|
|
- remap_event_helper(entry_conn, addr);
|
|
|
+ remap_event_helper(entry_conn, &addr);
|
|
|
}
|
|
|
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
|
|
|
/* don't send a socks reply to transparent conns */
|
|
@@ -994,8 +1062,14 @@ connection_edge_process_relay_cell_not_open(
|
|
|
ttl,
|
|
|
-1);
|
|
|
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
|
|
- uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
|
|
|
- remap_event_helper(entry_conn, addr);
|
|
|
+ tor_addr_t addr;
|
|
|
+ tor_addr_from_ipv4n(&addr, get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
|
|
|
+ remap_event_helper(entry_conn, &addr);
|
|
|
+ } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
|
|
|
+ tor_addr_t addr;
|
|
|
+ tor_addr_from_ipv6_bytes(&addr,
|
|
|
+ (char*)(cell->payload+RELAY_HEADER_SIZE+2));
|
|
|
+ remap_event_helper(entry_conn, &addr);
|
|
|
}
|
|
|
connection_mark_unattached_ap(entry_conn,
|
|
|
END_STREAM_REASON_DONE |
|