summaryrefslogtreecommitdiff
path: root/src/or/connection_edge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r--src/or/connection_edge.c147
1 files changed, 80 insertions, 67 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 42f49bfe75..29dcac32c2 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -924,59 +924,20 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
}
}
-/** connection_edge_process_inbuf() found a conn in state
- * socks_wait. See if conn->inbuf has the right bytes to proceed with
- * the socks handshake.
- *
- * If the handshake is complete, and it's for a general circuit, then
- * try to attach it to a circuit (or launch one as needed). If it's for
- * a rendezvous circuit, then fetch a rendezvous descriptor first (or
- * attach/launch a circuit if the rendezvous descriptor is already here
- * and fresh enough).
+/* Connection <b>conn</b> just finished its socks handshake, or the
+ * controller asked us to take care of it.
*
- * Return -1 if an unexpected error with conn (and it should be marked
- * for close), else return 0.
+ * First, parse whether it's a .exit address, remap it, and so on. Then
+ * 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).
*/
-static int
-connection_ap_handshake_process_socks(connection_t *conn)
+int
+connection_ap_handshake_rewrite_and_attach(connection_t *conn)
{
- socks_request_t *socks;
- int sockshere;
+ socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype;
- or_options_t *options = get_options();
- int tor_should_handle_stream = !options->LeaveStreamsUnattached;
-
- tor_assert(conn);
- tor_assert(conn->type == CONN_TYPE_AP);
- tor_assert(conn->state == AP_CONN_STATE_SOCKS_WAIT);
- tor_assert(conn->socks_request);
- socks = conn->socks_request;
-
- debug(LD_APP,"entered.");
-
- sockshere = fetch_from_buf_socks(conn->inbuf, socks, options->TestSocks);
- if (sockshere == 0) {
- if (socks->replylen) {
- connection_write_to_buf(socks->reply, socks->replylen, conn);
- /* zero it out so we can do another round of negotiation */
- socks->replylen = 0;
- } else {
- debug(LD_APP,"socks handshake not all here yet.");
- }
- return 0;
- } else if (sockshere == -1) {
- if (socks->replylen) { /* we should send reply back */
- debug(LD_APP,"reply is already set for us. Using it.");
- connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
- SOCKS5_GENERAL_ERROR);
- } else {
- warn(LD_APP,"Fetching socks handshake failed. Closing.");
- connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_GENERAL_ERROR);
- }
- connection_mark_unattached_ap(conn,
- END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
- return -1;
- } /* else socks handshake is done, continue processing */
tor_strlower(socks->address); /* normalize it */
debug(LD_APP,"Client asked for %s:%d", safe_str(socks->address),
@@ -985,11 +946,10 @@ connection_ap_handshake_process_socks(connection_t *conn)
/* For address map controls, remap the address */
addressmap_rewrite(socks->address, sizeof(socks->address));
- if (tor_should_handle_stream &&
- address_is_in_virtual_range(socks->address)) {
+ if (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
+ * the address through Tor; that's likely to fail, and may leak
* information.
*/
warn(LD_APP,"Missing mapping for virtual address '%s'. Refusing.",
@@ -1003,7 +963,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
*/
addresstype = parse_extended_hostname(socks->address);
- if (tor_should_handle_stream && addresstype == BAD_HOSTNAME) {
+ if (addresstype == BAD_HOSTNAME) {
warn(LD_APP, "Invalid hostname %s; rejecting", socks->address);
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
@@ -1033,7 +993,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
/* XXXX Should this use server->address instead? */
in.s_addr = htonl(r->addr);
strlcpy(socks->address, inet_ntoa(in), sizeof(socks->address));
- } else if (tor_should_handle_stream) {
+ } else {
warn(LD_APP,
"Unrecognized server in exit address '%s.exit'. Refusing.",
safe_str(socks->address));
@@ -1046,8 +1006,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
if (addresstype != ONION_HOSTNAME) {
/* not a hidden-service request (i.e. normal or .exit) */
- if (tor_should_handle_stream &&
- address_is_invalid_destination(socks->address)) {
+ if (address_is_invalid_destination(socks->address)) {
warn(LD_APP,"Destination '%s' seems to be an invalid hostname. Failing.",
safe_str(socks->address));
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
@@ -1075,7 +1034,6 @@ connection_ap_handshake_process_socks(connection_t *conn)
return 0;
}
rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
- control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE);
} else { /* socks->command == SOCKS_COMMAND_CONNECT */
if (socks->port == 0) {
notice(LD_APP,"Application asked to connect to port 0. Refusing.");
@@ -1099,16 +1057,11 @@ connection_ap_handshake_process_socks(connection_t *conn)
/* help predict this next time */
rep_hist_note_used_port(socks->port, time(NULL));
- control_event_stream_status(conn, STREAM_EVENT_NEW);
}
- if (!tor_should_handle_stream) {
- conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
- } else {
- conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- if (connection_ap_handshake_attach_circuit(conn) < 0) {
- connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
- return -1;
- }
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ if (connection_ap_handshake_attach_circuit(conn) < 0) {
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
+ return -1;
}
return 0;
} else {
@@ -1159,12 +1112,72 @@ connection_ap_handshake_process_socks(connection_t *conn)
rend_client_refetch_renddesc(conn->rend_query);
}
}
- control_event_stream_status(conn, STREAM_EVENT_NEW);
return 0;
}
return 0; /* unreached but keeps the compiler happy */
}
+/** connection_edge_process_inbuf() found a conn in state
+ * socks_wait. See if conn->inbuf has the right bytes to proceed with
+ * the socks handshake.
+ *
+ * If the handshake is complete, send it to
+ * connection_ap_handshake_rewrite_and_attach().
+ *
+ * Return -1 if an unexpected error with conn (and it should be marked
+ * for close), else return 0.
+ */
+static int
+connection_ap_handshake_process_socks(connection_t *conn)
+{
+ socks_request_t *socks;
+ int sockshere;
+ or_options_t *options = get_options();
+
+ tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_AP);
+ tor_assert(conn->state == AP_CONN_STATE_SOCKS_WAIT);
+ tor_assert(conn->socks_request);
+ socks = conn->socks_request;
+
+ debug(LD_APP,"entered.");
+
+ sockshere = fetch_from_buf_socks(conn->inbuf, socks, options->TestSocks);
+ if (sockshere == 0) {
+ if (socks->replylen) {
+ connection_write_to_buf(socks->reply, socks->replylen, conn);
+ /* zero it out so we can do another round of negotiation */
+ socks->replylen = 0;
+ } else {
+ debug(LD_APP,"socks handshake not all here yet.");
+ }
+ return 0;
+ } else if (sockshere == -1) {
+ if (socks->replylen) { /* we should send reply back */
+ debug(LD_APP,"reply is already set for us. Using it.");
+ connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
+ SOCKS5_GENERAL_ERROR);
+ } else {
+ warn(LD_APP,"Fetching socks handshake failed. Closing.");
+ connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_GENERAL_ERROR);
+ }
+ connection_mark_unattached_ap(conn,
+ END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
+ return -1;
+ } /* else socks handshake is done, continue processing */
+
+ if (socks->command == SOCKS_COMMAND_CONNECT)
+ control_event_stream_status(conn, STREAM_EVENT_NEW);
+ else
+ control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE);
+
+ if (options->LeaveStreamsUnattached) {
+ conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ return 0;
+ } else
+ return connection_ap_handshake_rewrite_and_attach(conn);
+}
+
/** Iterate over the two bytes of stream_id until we get one that is not
* already in use; return it. Return 0 if can't get a unique stream_id.
*/