Separate "SOCKS_COMMAND_CONNECT_DIR" into two flags in

edge_connection_t: want_onehop if it must attach to a circuit with
only one hop (e.g. for the current tunnelled connections that use
begin_dir), and use_begindir if we mean to use a BEGIN_DIR relay
command to establish the stream rather than the normal BEGIN. Now
we can make anonymized begin_dir connections for (e.g.) more secure
hidden service posting and fetching.


svn:r12244
This commit is contained in:
Roger Dingledine 2007-10-28 08:16:19 +00:00
parent 2dea44181b
commit e5885deab5
7 changed files with 66 additions and 53 deletions

View File

@ -1,4 +1,13 @@
Changes in version 0.2.0.10-alpha - 2007-1?-?? Changes in version 0.2.0.10-alpha - 2007-1?-??
o Major features:
- Separate "SOCKS_COMMAND_CONNECT_DIR" into two flags in
edge_connection_t: want_onehop if it must attach to a circuit with
only one hop (e.g. for the current tunnelled connections that use
begin_dir), and use_begindir if we mean to use a BEGIN_DIR relay
command to establish the stream rather than the normal BEGIN. Now
we can make anonymized begin_dir connections for (e.g.) more secure
hidden service posting and fetching.
o Major bugfixes: o Major bugfixes:
- Stop servers from crashing if they set a Family option (or - Stop servers from crashing if they set a Family option (or
maybe in other situations too). Bugfix on 0.2.0.9-alpha; reported maybe in other situations too). Bugfix on 0.2.0.9-alpha; reported

View File

@ -60,6 +60,8 @@ Tor's extensions to the SOCKS protocol
directory port of the Tor server specified by address:port (the port directory port of the Tor server specified by address:port (the port
specified should be the ORPort of the server). It uses a one-hop tunnel specified should be the ORPort of the server). It uses a one-hop tunnel
and a "BEGIN_DIR" relay cell to accomplish this secure connection. and a "BEGIN_DIR" relay cell to accomplish this secure connection.
Th F2 command value was removed in Tor 0.2.0.10-alpha in favor of a
new use_begindir flag in edge_connection_t.
4. HTTP-resistance 4. HTTP-resistance

View File

@ -1197,7 +1197,6 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return 0; /* not yet */ return 0; /* not yet */
req->command = (unsigned char) *(buf->cur+1); req->command = (unsigned char) *(buf->cur+1);
if (req->command != SOCKS_COMMAND_CONNECT && if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_CONNECT_DIR &&
req->command != SOCKS_COMMAND_RESOLVE && req->command != SOCKS_COMMAND_RESOLVE &&
req->command != SOCKS_COMMAND_RESOLVE_PTR) { req->command != SOCKS_COMMAND_RESOLVE_PTR) {
/* not a connect or resolve or a resolve_ptr? we don't support it. */ /* not a connect or resolve or a resolve_ptr? we don't support it. */
@ -1292,7 +1291,6 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->command = (unsigned char) *(buf->cur+1); req->command = (unsigned char) *(buf->cur+1);
if (req->command != SOCKS_COMMAND_CONNECT && if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_CONNECT_DIR &&
req->command != SOCKS_COMMAND_RESOLVE) { req->command != SOCKS_COMMAND_RESOLVE) {
/* not a connect or resolve? we don't support it. (No resolve_ptr with /* not a connect or resolve? we don't support it. (No resolve_ptr with
* socks4.) */ * socks4.) */

View File

@ -87,7 +87,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
* or is a rendezvous circuit. */ * or is a rendezvous circuit. */
} }
if (build_state->onehop_tunnel) { if (build_state->onehop_tunnel) {
if (conn->socks_request->command != SOCKS_COMMAND_CONNECT_DIR) { if (!conn->want_onehop) {
log_debug(LD_CIRC,"Skipping one-hop circuit."); log_debug(LD_CIRC,"Skipping one-hop circuit.");
return 0; return 0;
} }
@ -100,7 +100,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0; /* this is a circuit to somewhere else */ return 0; /* this is a circuit to somewhere else */
} }
} else { } else {
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT_DIR) { if (conn->want_onehop) {
/* don't use three-hop circuits -- that could hurt our anonymity. */ /* don't use three-hop circuits -- that could hurt our anonymity. */
return 0; return 0;
} }
@ -835,6 +835,8 @@ circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
if ((extend_info || purpose != CIRCUIT_PURPOSE_C_GENERAL) && if ((extend_info || purpose != CIRCUIT_PURPOSE_C_GENERAL) &&
purpose != CIRCUIT_PURPOSE_TESTING && !onehop_tunnel) { purpose != CIRCUIT_PURPOSE_TESTING && !onehop_tunnel) {
/* see if there are appropriate circs available to cannibalize. */ /* see if there are appropriate circs available to cannibalize. */
/* XXX020 if we're planning to add a hop, perhaps we want to look for
* internal circs rather than exit circs? -RD */
circ = circuit_find_to_cannibalize(purpose, extend_info, circ = circuit_find_to_cannibalize(purpose, extend_info,
need_uptime, need_capacity, internal); need_uptime, need_capacity, internal);
if (circ) { if (circ) {
@ -948,11 +950,12 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
tor_assert(circp); tor_assert(circp);
tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
check_exit_policy = check_exit_policy =
(conn->socks_request->command == SOCKS_COMMAND_CONNECT) && conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir &&
!connection_edge_is_rendezvous_stream(conn); !connection_edge_is_rendezvous_stream(conn);
want_onehop = conn->socks_request->command == SOCKS_COMMAND_CONNECT_DIR; want_onehop = conn->want_onehop;
need_uptime = (conn->socks_request->command == SOCKS_COMMAND_CONNECT) && need_uptime = !conn->want_onehop && !conn->use_begindir &&
smartlist_string_num_isin(options->LongLivedPorts, smartlist_string_num_isin(options->LongLivedPorts,
conn->socks_request->port); conn->socks_request->port);
need_internal = desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL; need_internal = desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL;
@ -1005,6 +1008,8 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
/* is one already on the way? */ /* is one already on the way? */
circ = circuit_get_best(conn, 0, desired_circuit_purpose, circ = circuit_get_best(conn, 0, desired_circuit_purpose,
need_uptime, need_internal); need_uptime, need_internal);
if (circ)
log_debug(LD_CIRC, "one on the way!");
if (!circ) { if (!circ) {
extend_info_t *extend_info=NULL; extend_info_t *extend_info=NULL;
uint8_t new_circ_purpose; uint8_t new_circ_purpose;
@ -1221,15 +1226,12 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
link_apconn_to_circ(conn, circ, cpath); link_apconn_to_circ(conn, circ, cpath);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
switch (conn->socks_request->command) { if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
case SOCKS_COMMAND_CONNECT: if (!conn->use_begindir)
consider_recording_trackhost(conn, circ); consider_recording_trackhost(conn, circ);
/* fall through */
case SOCKS_COMMAND_CONNECT_DIR:
if (connection_ap_handshake_send_begin(conn) < 0) if (connection_ap_handshake_send_begin(conn) < 0)
return -1; return -1;
break; } else {
default:
if (connection_ap_handshake_send_resolve(conn) < 0) if (connection_ap_handshake_send_resolve(conn) < 0)
return -1; return -1;
} }
@ -1254,7 +1256,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
tor_assert(conn); tor_assert(conn);
tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
want_onehop = conn->socks_request->command == SOCKS_COMMAND_CONNECT_DIR; want_onehop = conn->want_onehop;
conn_age = time(NULL) - conn->_base.timestamp_created; conn_age = time(NULL) - conn->_base.timestamp_created;
@ -1307,7 +1309,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
log_debug(LD_APP|LD_CIRC, log_debug(LD_APP|LD_CIRC,
"Attaching apconn to circ %d (stream %d sec old).", "Attaching apconn to circ %d (stream %d sec old).",
circ->_base.n_circ_id, conn_age); circ->_base.n_circ_id, conn_age);
/* here, print the circ's path. so people can figure out which circs are /* print the circ's path, so people can figure out which circs are
* sucking. */ * sucking. */
circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ); circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ);

View File

@ -1379,7 +1379,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1; return -1;
} }
if (!conn->chosen_exit_name && !circ) { if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */ /* see if we can find a suitable enclave exit */
routerinfo_t *r = routerinfo_t *r =
router_find_exact_exit_enclave(socks->address, socks->port); router_find_exact_exit_enclave(socks->address, socks->port);
@ -1395,11 +1395,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
} }
} }
if (!conn->use_begindir) {
/* help predict this next time */ /* help predict this next time */
rep_hist_note_used_port(socks->port, time(NULL)); rep_hist_note_used_port(socks->port, time(NULL));
}
} else if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) { } else if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */ rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
} else if (socks->command == SOCKS_COMMAND_CONNECT_DIR) {
; /* nothing */ ; /* nothing */
} else { } else {
tor_fragile_assert(); tor_fragile_assert();
@ -1840,8 +1841,8 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
log_debug(LD_APP, log_debug(LD_APP,
"Sending relay cell to begin stream %d.", ap_conn->stream_id); "Sending relay cell to begin stream %d.", ap_conn->stream_id);
begin_type = ap_conn->socks_request->command == SOCKS_COMMAND_CONNECT ? begin_type = ap_conn->use_begindir ?
RELAY_COMMAND_BEGIN : RELAY_COMMAND_BEGIN_DIR; RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN;
if (begin_type == RELAY_COMMAND_BEGIN) { if (begin_type == RELAY_COMMAND_BEGIN) {
tor_assert(circ->build_state->onehop_tunnel == 0); tor_assert(circ->build_state->onehop_tunnel == 0);
} }
@ -1955,7 +1956,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
*/ */
edge_connection_t * edge_connection_t *
connection_ap_make_link(char *address, uint16_t port, connection_ap_make_link(char *address, uint16_t port,
const char *digest, int command) const char *digest, int use_begindir, int want_onehop)
{ {
edge_connection_t *conn; edge_connection_t *conn;
@ -1973,8 +1974,10 @@ connection_ap_make_link(char *address, uint16_t port,
strlcpy(conn->socks_request->address, address, strlcpy(conn->socks_request->address, address,
sizeof(conn->socks_request->address)); sizeof(conn->socks_request->address));
conn->socks_request->port = port; conn->socks_request->port = port;
conn->socks_request->command = command; conn->socks_request->command = SOCKS_COMMAND_CONNECT;
if (command == SOCKS_COMMAND_CONNECT_DIR) { conn->want_onehop = want_onehop;
conn->use_begindir = use_begindir;
if (use_begindir) {
conn->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+2); conn->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+2);
conn->chosen_exit_name[0] = '$'; conn->chosen_exit_name[0] = '$';
base16_encode(conn->chosen_exit_name+1,HEX_DIGEST_LEN+1, base16_encode(conn->chosen_exit_name+1,HEX_DIGEST_LEN+1,
@ -2622,7 +2625,8 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
} }
} }
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) { if (conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir) {
struct in_addr in; struct in_addr in;
uint32_t addr = 0; uint32_t addr = 0;
addr_policy_result_t r; addr_policy_result_t r;

View File

@ -609,17 +609,17 @@ directory_initiate_command(const char *address, uint32_t addr,
{ {
dir_connection_t *conn; dir_connection_t *conn;
or_options_t *options = get_options(); or_options_t *options = get_options();
int want_to_tunnel = options->TunnelDirConns && supports_begindir && int use_begindir = options->TunnelDirConns && supports_begindir && or_port &&
!anonymized_connection && or_port && (anonymized_connection ||
fascist_firewall_allows_address_or(addr, or_port); fascist_firewall_allows_address_or(addr, or_port));
tor_assert(address); tor_assert(address);
tor_assert(addr); tor_assert(addr);
tor_assert(or_port || dir_port); tor_assert(or_port || dir_port);
tor_assert(digest); tor_assert(digest);
log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.", log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
anonymized_connection, want_to_tunnel); anonymized_connection, use_begindir);
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose)); log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
@ -627,7 +627,7 @@ directory_initiate_command(const char *address, uint32_t addr,
/* set up conn so it's got all the data we need to remember */ /* set up conn so it's got all the data we need to remember */
conn->_base.addr = addr; conn->_base.addr = addr;
conn->_base.port = want_to_tunnel ? or_port : dir_port; conn->_base.port = use_begindir ? or_port : dir_port;
conn->_base.address = tor_strdup(address); conn->_base.address = tor_strdup(address);
memcpy(conn->identity_digest, digest, DIGEST_LEN); memcpy(conn->identity_digest, digest, DIGEST_LEN);
@ -637,11 +637,12 @@ directory_initiate_command(const char *address, uint32_t addr,
/* give it an initial state */ /* give it an initial state */
conn->_base.state = DIR_CONN_STATE_CONNECTING; conn->_base.state = DIR_CONN_STATE_CONNECTING;
if (!anonymized_connection && !want_to_tunnel) { /* decide whether we can learn our IP address from this conn */
/* then we want to connect directly */ conn->dirconn_direct = !anonymized_connection;
if (!anonymized_connection && !use_begindir) {
/* then we want to connect to dirport directly */
/* XXX020 we should set dirconn_direct to 1 even if want_to_tunnel -RD */
conn->dirconn_direct = 1;
if (options->HttpProxy) { if (options->HttpProxy) {
addr = options->HttpProxyAddr; addr = options->HttpProxyAddr;
dir_port = options->HttpProxyPort; dir_port = options->HttpProxyPort;
@ -665,19 +666,15 @@ directory_initiate_command(const char *address, uint32_t addr,
/* writable indicates finish, readable indicates broken link, /* writable indicates finish, readable indicates broken link,
error indicates broken link in windowsland. */ error indicates broken link in windowsland. */
} }
} else { /* we want to connect via tor */ } else { /* we want to connect via a tor connection */
edge_connection_t *linked_conn; edge_connection_t *linked_conn;
/* make an AP connection /* make an AP connection
* populate it and add it at the right state * populate it and add it at the right state
* hook up both sides * hook up both sides
*/ */
conn->dirconn_direct = 0;
linked_conn = linked_conn =
connection_ap_make_link(conn->_base.address, conn->_base.port, connection_ap_make_link(conn->_base.address, conn->_base.port,
digest, digest, use_begindir, conn->dirconn_direct);
anonymized_connection ?
SOCKS_COMMAND_CONNECT :
SOCKS_COMMAND_CONNECT_DIR);
if (!linked_conn) { if (!linked_conn) {
log_warn(LD_NET,"Making tunnel to dirserver failed."); log_warn(LD_NET,"Making tunnel to dirserver failed.");
connection_mark_for_close(TO_CONN(conn)); connection_mark_for_close(TO_CONN(conn));

View File

@ -910,6 +910,12 @@ typedef struct edge_connection_t {
/** True iff this connection is for a dns request only. */ /** True iff this connection is for a dns request only. */
unsigned int is_dns_request : 1; unsigned int is_dns_request : 1;
/** True iff this stream wants a one-hop circuit (e.g. for begin_dir). */
int want_onehop:1;
/** True iff this stream should use a begin_dir connection (either via
* onehop or via a whole circuit). */
int use_begindir:1;
/** If this is a DNSPort connection, this field holds the pending DNS /** If this is a DNSPort connection, this field holds the pending DNS
* request that we're going to try to answer. */ * request that we're going to try to answer. */
struct evdns_server_request *dns_server_request; struct evdns_server_request *dns_server_request;
@ -2212,13 +2218,7 @@ static INLINE void or_state_mark_dirty(or_state_t *state, time_t when)
/** Please turn this IP address into an FQDN, privately. */ /** Please turn this IP address into an FQDN, privately. */
#define SOCKS_COMMAND_RESOLVE_PTR 0xF1 #define SOCKS_COMMAND_RESOLVE_PTR 0xF1
/** Please open an encrypted direct TCP connection to the directory port #define SOCKS_COMMAND_IS_CONNECT(c) ((c)==SOCKS_COMMAND_CONNECT)
* of the Tor server specified by address:port. (In this case address:port
* specifies the ORPort of the server.) */
#define SOCKS_COMMAND_CONNECT_DIR 0xF2
#define SOCKS_COMMAND_IS_CONNECT(c) ((c)==SOCKS_COMMAND_CONNECT || \
(c)==SOCKS_COMMAND_CONNECT_DIR)
#define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \ #define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \
(c)==SOCKS_COMMAND_RESOLVE_PTR) (c)==SOCKS_COMMAND_RESOLVE_PTR)
@ -2583,7 +2583,8 @@ int connection_ap_handshake_send_begin(edge_connection_t *ap_conn);
int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn); int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn);
edge_connection_t *connection_ap_make_link(char *address, uint16_t port, edge_connection_t *connection_ap_make_link(char *address, uint16_t port,
const char *digest, int command); const char *digest,
int use_begindir, int want_onehop);
void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
size_t replylen, size_t replylen,
int endreason); int endreason);