mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Add TTLs to RESOLVED, CONNECTED, and END_REASON_EXITPOLICY cells. Also, add a missing ntohl in connection_ap_handshake_socks_resolved.
svn:r4894
This commit is contained in:
+13
-3
@@ -469,8 +469,16 @@ TODO: (very soon)
|
||||
address cannot be resolved, or a connection can't be established, the
|
||||
exit node replies with a RELAY_END cell. (See 5.4 below.)
|
||||
Otherwise, the exit node replies with a RELAY_CONNECTED cell, whose
|
||||
payload is the 4-byte IPv4 address or the 16-byte IPv6 address to which
|
||||
the connection was made.
|
||||
payload is in one of the following formats:
|
||||
The IPv4 address to which the connection was made [4 octets]
|
||||
A number of seconds (TTL) for which the address may be cached [4 octets]
|
||||
or
|
||||
Four zero-valued octets [4 octets]
|
||||
An address type (6) [1 octet]
|
||||
The IPv6 address to which the connection was made [16 octets]
|
||||
A number of seconds (TTL) for which the address may be cached [4 octets]
|
||||
[XXXX Versions of Tor before 0.1.1.6 ignore and do not generate the TTL
|
||||
field. No version of Tor currently generates the IPv6 format.]
|
||||
|
||||
The OP waits for a RELAY_CONNECTED cell before sending any data.
|
||||
Once a connection has been established, the OP and exit node
|
||||
@@ -511,7 +519,8 @@ TODO: (very soon)
|
||||
Tor protocol violations.)
|
||||
|
||||
(With REASON_EXITPOLICY, the 4-byte IPv4 address or 16-byte IPv6 address
|
||||
forms the optional data; no other reason currently has extra data.)
|
||||
forms the optional data; no other reason currently has extra data.
|
||||
As of 0.1.1.6, the body also contains a 4-byte TTL.)
|
||||
|
||||
OPs and ORs MUST accept reasons not on the above list, since future
|
||||
versions of Tor may provide more fine-grained reasons.
|
||||
@@ -558,6 +567,7 @@ TODO: (very soon)
|
||||
Type (1 octet)
|
||||
Length (1 octet)
|
||||
Value (variable-width)
|
||||
TTL (4 octets)
|
||||
"Length" is the length of the Value field.
|
||||
"Type" is one of:
|
||||
0x00 -- Hostname
|
||||
|
||||
+29
-17
@@ -48,7 +48,7 @@ _connection_mark_unattached_ap(connection_t *conn, int endreason,
|
||||
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT)
|
||||
connection_ap_handshake_socks_reply(conn, NULL, 0, socksreason);
|
||||
else
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL,-1);
|
||||
}
|
||||
|
||||
_connection_mark_for_close(conn, line, file);
|
||||
@@ -194,7 +194,8 @@ connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer)
|
||||
/* this is safe even for rend circs, because they never fail
|
||||
* because of exitpolicy */
|
||||
set_uint32(payload+1, htonl(conn->addr));
|
||||
payload_len += 4;
|
||||
set_uint32(payload+5, htonl(MAX_DNS_ENTRY_AGE)); /* XXXXfill with a real TTL*/
|
||||
payload_len += 8;
|
||||
}
|
||||
|
||||
circ = circuit_get_by_edge_conn(conn);
|
||||
@@ -266,7 +267,6 @@ connection_edge_finished_flushing(connection_t *conn)
|
||||
int
|
||||
connection_edge_finished_connecting(connection_t *conn)
|
||||
{
|
||||
char connected_payload[4];
|
||||
char valbuf[INET_NTOA_BUF_LEN];
|
||||
struct in_addr in;
|
||||
|
||||
@@ -289,9 +289,12 @@ connection_edge_finished_connecting(connection_t *conn)
|
||||
RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0)
|
||||
return 0; /* circuit is closed, don't continue */
|
||||
} else {
|
||||
*(uint32_t*)connected_payload = htonl(conn->addr);
|
||||
char connected_payload[8];
|
||||
set_uint32(connected_payload, htonl(htonl(conn->addr)));
|
||||
set_uint32(connected_payload+4,
|
||||
htonl(MAX_DNS_ENTRY_AGE)); /* XXXX fill with a real TTL */
|
||||
if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
|
||||
RELAY_COMMAND_CONNECTED, connected_payload, 4, conn->cpath_layer) < 0)
|
||||
RELAY_COMMAND_CONNECTED, connected_payload, 8, conn->cpath_layer) < 0)
|
||||
return 0; /* circuit is closed, don't continue */
|
||||
}
|
||||
tor_assert(conn->package_window > 0);
|
||||
@@ -683,9 +686,13 @@ client_dns_clear_failures(const char *address)
|
||||
*
|
||||
* If <b>exitname</b> is defined, then append the addresses with
|
||||
* ".exitname.exit" before registering the mapping.
|
||||
*
|
||||
* If <b>ttl</b> is nonnegative, the mapping will be valid for
|
||||
* <b>ttl</b>seconds.
|
||||
*/
|
||||
void
|
||||
client_dns_set_addressmap(const char *address, uint32_t val, const char *exitname)
|
||||
client_dns_set_addressmap(const char *address, uint32_t val, const char *exitname,
|
||||
int ttl)
|
||||
{
|
||||
struct in_addr in;
|
||||
char extendedaddress[MAX_SOCKS_ADDR_LEN+MAX_HEX_NICKNAME_LEN+10];
|
||||
@@ -694,6 +701,9 @@ client_dns_set_addressmap(const char *address, uint32_t val, const char *exitnam
|
||||
|
||||
tor_assert(address); tor_assert(val);
|
||||
|
||||
if (ttl<0 || ttl>MAX_DNS_ENTRY_AGE)
|
||||
ttl = MAX_DNS_ENTRY_AGE;
|
||||
|
||||
if (tor_inet_aton(address, &in))
|
||||
return; /* If address was an IP address already, don't add a mapping. */
|
||||
in.s_addr = htonl(val);
|
||||
@@ -709,8 +719,7 @@ client_dns_set_addressmap(const char *address, uint32_t val, const char *exitnam
|
||||
tor_snprintf(extendedval, sizeof(extendedval),
|
||||
"%s", valbuf);
|
||||
}
|
||||
addressmap_register(extendedaddress, tor_strdup(extendedval),
|
||||
time(NULL) + MAX_DNS_ENTRY_AGE);
|
||||
addressmap_register(extendedaddress, tor_strdup(extendedval), time(NULL) + ttl);
|
||||
}
|
||||
|
||||
/* Currently, we hand out 127.192.0.1 through 127.254.254.254.
|
||||
@@ -1019,14 +1028,14 @@ connection_ap_handshake_process_socks(connection_t *conn)
|
||||
/* Reply to resolves immediately if we can. */
|
||||
if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) {
|
||||
log_fn(LOG_WARN,"Address to be resolved is too large. Failing.");
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL,-1);
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
|
||||
return -1;
|
||||
}
|
||||
if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */
|
||||
answer = in.s_addr; /* leave it in network order */
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
|
||||
(char*)&answer);
|
||||
(char*)&answer,-1);
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
|
||||
return 0;
|
||||
}
|
||||
@@ -1075,7 +1084,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
|
||||
/* if it's a resolve request, fail it right now, rather than
|
||||
* building all the circuits and then realizing it won't work. */
|
||||
log_fn(LOG_WARN,"Resolve requests to hidden services not allowed. Failing.");
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
|
||||
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL,-1);
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
|
||||
return -1;
|
||||
}
|
||||
@@ -1299,16 +1308,17 @@ void
|
||||
connection_ap_handshake_socks_resolved(connection_t *conn,
|
||||
int answer_type,
|
||||
size_t answer_len,
|
||||
const char *answer)
|
||||
const char *answer,
|
||||
int ttl)
|
||||
{
|
||||
char buf[256];
|
||||
size_t replylen;
|
||||
|
||||
if (answer_type == RESOLVED_TYPE_IPV4) {
|
||||
uint32_t a = get_uint32(answer);
|
||||
uint32_t a = ntohl(get_uint32(answer));
|
||||
if (a)
|
||||
client_dns_set_addressmap(conn->socks_request->address, ntohl(a),
|
||||
conn->chosen_exit_name);
|
||||
conn->chosen_exit_name, ttl);
|
||||
}
|
||||
|
||||
if (conn->socks_request->socks_version == 4) {
|
||||
@@ -1581,7 +1591,6 @@ connection_exit_begin_resolve(cell_t *cell, circuit_t *circ)
|
||||
void
|
||||
connection_exit_connect(connection_t *conn)
|
||||
{
|
||||
char connected_payload[4];
|
||||
uint32_t addr;
|
||||
uint16_t port;
|
||||
|
||||
@@ -1649,10 +1658,13 @@ connection_exit_connect(connection_t *conn)
|
||||
NULL, 0, conn->cpath_layer);
|
||||
} else { /* normal stream */
|
||||
/* This must be the original address, not the redirected address. */
|
||||
*(uint32_t*)connected_payload = htonl(conn->addr);
|
||||
char connected_payload[8];
|
||||
set_uint32(connected_payload, htonl(htonl(conn->addr)));
|
||||
set_uint32(connected_payload+4,
|
||||
htonl(MAX_DNS_ENTRY_AGE)); /* XXXX fill with a real TTL */
|
||||
connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
|
||||
RELAY_COMMAND_CONNECTED,
|
||||
connected_payload, 4, conn->cpath_layer);
|
||||
connected_payload, 8, conn->cpath_layer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-5
@@ -192,14 +192,21 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type)
|
||||
case RESOLVED_TYPE_IPV4:
|
||||
buf[1] = 4;
|
||||
set_uint32(buf+2, htonl(conn->addr));
|
||||
buflen = 6;
|
||||
set_uint32(buf+6, htonl(MAX_DNS_ENTRY_AGE)); /*XXXX send a real TTL*/
|
||||
buflen = 10;
|
||||
break;
|
||||
case RESOLVED_TYPE_ERROR_TRANSIENT:
|
||||
case RESOLVED_TYPE_ERROR:
|
||||
buf[1] = 24; /* length of "error resolving hostname" */
|
||||
strlcpy(buf+2, "error resolving hostname", sizeof(buf)-2);
|
||||
buflen = 26;
|
||||
break;
|
||||
{
|
||||
const char *errmsg = "Error resolving hostname";
|
||||
int msglen = strlen(errmsg);
|
||||
int ttl = (answer_type == RESOLVED_TYPE_ERROR ? MAX_DNS_ENTRY_AGE : 0);
|
||||
buf[1] = msglen;
|
||||
strlcpy(buf+2, errmsg, sizeof(buf)-2);
|
||||
set_uint32(buf+2+msglen, htonl((uint32_t)ttl));
|
||||
buflen = 6+msglen;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
tor_assert(0);
|
||||
}
|
||||
|
||||
+22
-4
@@ -640,14 +640,19 @@ connection_edge_process_end_not_open(
|
||||
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) {
|
||||
log_fn(LOG_INFO,"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;
|
||||
client_dns_set_addressmap(conn->socks_request->address, addr,
|
||||
conn->chosen_exit_name);
|
||||
conn->chosen_exit_name, ttl);
|
||||
}
|
||||
/* check if he *ought* to have allowed it */
|
||||
if (exitrouter &&
|
||||
@@ -735,14 +740,19 @@ connection_edge_process_relay_cell_not_open(
|
||||
(int)(time(NULL) - conn->timestamp_lastread));
|
||||
if (rh->length >= 4) {
|
||||
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
|
||||
int ttl;
|
||||
if (!addr) {
|
||||
log_fn(LOG_INFO,"...but it claims the IP address was 0.0.0.0. Closing.");
|
||||
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, conn->cpath_layer);
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||
return 0;
|
||||
}
|
||||
if (rh->length >= 8)
|
||||
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+8));
|
||||
else
|
||||
ttl = -1;
|
||||
client_dns_set_addressmap(conn->socks_request->address, addr,
|
||||
conn->chosen_exit_name);
|
||||
conn->chosen_exit_name, ttl);
|
||||
}
|
||||
circuit_log_path(LOG_INFO,circ);
|
||||
connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
|
||||
@@ -755,20 +765,28 @@ connection_edge_process_relay_cell_not_open(
|
||||
return 0;
|
||||
}
|
||||
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) {
|
||||
int ttl;
|
||||
int answer_len;
|
||||
if (conn->state != AP_CONN_STATE_RESOLVE_WAIT) {
|
||||
log_fn(LOG_WARN,"Got a 'resolved' cell while not in state resolve_wait. Dropping.");
|
||||
return 0;
|
||||
}
|
||||
tor_assert(conn->socks_request->command == SOCKS_COMMAND_RESOLVE);
|
||||
if (rh->length < 2 || cell->payload[RELAY_HEADER_SIZE+1]+2>rh->length) {
|
||||
answer_len = cell->payload[RELAY_HEADER_SIZE+1];
|
||||
if (rh->length < 2 || answer_len+2>rh->length) {
|
||||
log_fn(LOG_WARN, "Dropping malformed 'resolved' cell");
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||
return 0;
|
||||
}
|
||||
if (rh->length >= answer_len+6)
|
||||
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+6));
|
||||
else
|
||||
ttl = -1;
|
||||
connection_ap_handshake_socks_resolved(conn,
|
||||
cell->payload[RELAY_HEADER_SIZE], /*answer_type*/
|
||||
cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
|
||||
cell->payload+RELAY_HEADER_SIZE+2); /* answer */
|
||||
cell->payload+RELAY_HEADER_SIZE+2,
|
||||
ttl); /* answer */
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user