clean up socks reply stuff more.

add a few more reasons so we can be more informative.


svn:r3895
This commit is contained in:
Roger Dingledine 2005-03-27 06:37:56 +00:00
parent ce854906db
commit 7a79acd9f6
6 changed files with 53 additions and 16 deletions

View File

@ -26,16 +26,24 @@ static int address_is_in_virtual_range(const char *addr);
*/ */
void void
connection_close_unattached_ap(connection_t *conn, int endreason) { connection_close_unattached_ap(connection_t *conn, int endreason) {
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->type == CONN_TYPE_AP);
conn->has_sent_end = 1; /* no circ yet */ conn->has_sent_end = 1; /* no circ yet */
if (!conn->socks_request->has_finished) { if (!conn->socks_request->has_finished) {
socks5_reply_status_t socksreason = socks5_reply_status_t socksreason =
connection_edge_end_reason_socks5_response(endreason); connection_edge_end_reason_socks5_response(endreason);
if (endreason == END_STREAM_REASON_ALREADY_SOCKS_REPLIED)
log_fn(LOG_WARN,"Bug: stream (marked at %s:%d) sending two socks replies?",
conn->marked_for_close_file, conn->marked_for_close);
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) if (conn->socks_request->command == SOCKS_COMMAND_CONNECT)
connection_ap_handshake_socks_reply(conn, NULL, 0, socksreason); connection_ap_handshake_socks_reply(conn, NULL, 0, socksreason);
else else
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL); connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
} }
connection_mark_for_close(conn); connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1; conn->hold_open_until_flushed = 1;
} }
@ -90,7 +98,7 @@ int connection_edge_process_inbuf(connection_t *conn, int package_partial) {
switch (conn->state) { switch (conn->state) {
case AP_CONN_STATE_SOCKS_WAIT: case AP_CONN_STATE_SOCKS_WAIT:
if (connection_ap_handshake_process_socks(conn) < 0) { if (connection_ap_handshake_process_socks(conn) < 0) {
connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); /* already marked */
return -1; return -1;
} }
return 0; return 0;
@ -345,7 +353,7 @@ void connection_ap_expire_beginning(void) {
conn->timestamp_lastread += 15; conn->timestamp_lastread += 15;
/* move it back into 'pending' state, and try to attach. */ /* move it back into 'pending' state, and try to attach. */
if (connection_ap_detach_retriable(conn, circ)<0) { if (connection_ap_detach_retriable(conn, circ)<0) {
connection_close_unattached_ap(conn, END_STREAM_REASON_MISC); connection_close_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
} }
} /* end for */ } /* end for */
} }
@ -368,7 +376,7 @@ void connection_ap_attach_pending(void)
conn->state != AP_CONN_STATE_CIRCUIT_WAIT) conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue; continue;
if (connection_ap_handshake_attach_circuit(conn) < 0) { if (connection_ap_handshake_attach_circuit(conn) < 0) {
connection_close_unattached_ap(conn, END_STREAM_REASON_MISC); connection_close_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
} }
} }
} }
@ -865,12 +873,12 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
log_fn(LOG_DEBUG,"reply is already set for us. Using it."); log_fn(LOG_DEBUG,"reply is already set for us. Using it.");
connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen, connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
SOCKS5_GENERAL_ERROR); SOCKS5_GENERAL_ERROR);
socks->replylen = 0; /* zero it out so we can do another round of negotiation */
} else { } else {
log_fn(LOG_WARN,"Fetching socks handshake failed. Closing."); log_fn(LOG_WARN,"Fetching socks handshake failed. Closing.");
connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_GENERAL_ERROR); connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_GENERAL_ERROR);
} }
return sockshere; connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
return -1;
} /* else socks handshake is done, continue processing */ } /* else socks handshake is done, continue processing */
tor_strlower(socks->address); /* normalize it */ tor_strlower(socks->address); /* normalize it */
@ -886,6 +894,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
*/ */
log_fn(LOG_WARN,"Missing mapping for virtual address '%s'. Refusing.", log_fn(LOG_WARN,"Missing mapping for virtual address '%s'. Refusing.",
socks->address); socks->address);
connection_close_unattached_ap(conn, END_STREAM_REASON_INTERNAL);
return -1; return -1;
} }
@ -899,6 +908,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
char *s = strrchr(socks->address,'.'); char *s = strrchr(socks->address,'.');
if (!s || s[1] == '\0') { if (!s || s[1] == '\0') {
log_fn(LOG_WARN,"Malformed exit address '%s'. Refusing.", socks->address); log_fn(LOG_WARN,"Malformed exit address '%s'. Refusing.", socks->address);
connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1; return -1;
} }
conn->chosen_exit_name = tor_strdup(s+1); conn->chosen_exit_name = tor_strdup(s+1);
@ -910,6 +920,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
if (address_is_invalid_destination(socks->address)) { if (address_is_invalid_destination(socks->address)) {
log_fn(LOG_WARN,"Destination '%s' seems to be an invalid hostname. Failing.", socks->address); log_fn(LOG_WARN,"Destination '%s' seems to be an invalid hostname. Failing.", socks->address);
connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1; return -1;
} }
@ -920,13 +931,14 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) { if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) {
log_fn(LOG_WARN,"Address to be resolved is too large. Failing."); 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);
connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
return -1; return -1;
} }
if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */ if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */
answer = in.s_addr; answer = in.s_addr;
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
(char*)&answer); (char*)&answer);
connection_close_unattached_ap(conn, END_STREAM_REASON_DONE); connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
return 0; return 0;
} }
rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */ rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
@ -934,6 +946,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
} else { /* socks->command == SOCKS_COMMAND_CONNECT */ } else { /* socks->command == SOCKS_COMMAND_CONNECT */
if (socks->port == 0) { if (socks->port == 0) {
log_fn(LOG_NOTICE,"Application asked to connect to port 0. Refusing."); log_fn(LOG_NOTICE,"Application asked to connect to port 0. Refusing.");
connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1; return -1;
} }
rep_hist_note_used_port(socks->port, time(NULL)); /* help predict this next time */ rep_hist_note_used_port(socks->port, time(NULL)); /* help predict this next time */
@ -941,7 +954,11 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
} }
if (! get_options()->LeaveStreamsUnattached) { if (! get_options()->LeaveStreamsUnattached) {
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
return connection_ap_handshake_attach_circuit(conn); if (connection_ap_handshake_attach_circuit(conn) < 0) {
connection_close_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
return 0;
} else { } else {
conn->state = AP_CONN_STATE_CONTROLLER_WAIT; conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
return 0; return 0;
@ -956,6 +973,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
* building all the circuits and then realizing it won't work. */ * building all the circuits and then realizing it won't work. */
log_fn(LOG_WARN,"Resolve requests to hidden services not allowed. Failing."); 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);
connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
return -1; return -1;
} }
@ -965,6 +983,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
r = rend_cache_lookup_entry(conn->rend_query, &entry); r = rend_cache_lookup_entry(conn->rend_query, &entry);
if (r<0) { if (r<0) {
log_fn(LOG_WARN,"Invalid service descriptor %s", conn->rend_query); log_fn(LOG_WARN,"Invalid service descriptor %s", conn->rend_query);
connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1; return -1;
} }
if (r==0) { if (r==0) {
@ -978,7 +997,11 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
if (time(NULL) - entry->received < NUM_SECONDS_BEFORE_REFETCH) { if (time(NULL) - entry->received < NUM_SECONDS_BEFORE_REFETCH) {
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
log_fn(LOG_INFO, "Descriptor is here and fresh enough. Great."); log_fn(LOG_INFO, "Descriptor is here and fresh enough. Great.");
return connection_ap_handshake_attach_circuit(conn); if (connection_ap_handshake_attach_circuit(conn) < 0) {
connection_close_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
return 0;
} else { } else {
conn->state = AP_CONN_STATE_RENDDESC_WAIT; conn->state = AP_CONN_STATE_RENDDESC_WAIT;
log_fn(LOG_INFO, "Stale descriptor %s. Refetching.", conn->rend_query); log_fn(LOG_INFO, "Stale descriptor %s. Refetching.", conn->rend_query);
@ -1144,7 +1167,7 @@ int connection_ap_make_bridge(char *address, uint16_t port) {
/* attaching to a dirty circuit is fine */ /* attaching to a dirty circuit is fine */
if (connection_ap_handshake_attach_circuit(conn) < 0) { if (connection_ap_handshake_attach_circuit(conn) < 0) {
connection_close_unattached_ap(conn, END_STREAM_REASON_MISC); connection_close_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
tor_close_socket(fd[1]); tor_close_socket(fd[1]);
return -1; return -1;
} }

View File

@ -736,7 +736,7 @@ static int handle_control_attachstream(connection_t *conn, uint32_t len,
if (!circ_id) { if (!circ_id) {
ap_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; ap_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if (connection_ap_handshake_attach_circuit(ap_conn)<0) if (connection_ap_handshake_attach_circuit(ap_conn)<0)
connection_close_unattached_ap(ap_conn, END_STREAM_REASON_MISC); connection_close_unattached_ap(ap_conn, END_STREAM_REASON_CANT_ATTACH);
send_control_done(conn); send_control_done(conn);
return 0; return 0;
} }

View File

@ -478,8 +478,7 @@ void directory_all_unreachable(time_t now) {
AP_CONN_STATE_CIRCUIT_WAIT))) { AP_CONN_STATE_CIRCUIT_WAIT))) {
log_fn(LOG_NOTICE,"Network down? Failing connection to '%s:%d'.", log_fn(LOG_NOTICE,"Network down? Failing connection to '%s:%d'.",
conn->socks_request->address, conn->socks_request->port); conn->socks_request->address, conn->socks_request->port);
connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); connection_close_unattached_ap(conn, END_STREAM_REASON_NET_UNREACHABLE);
// XXX should maybe reflect SOCKS5_NET_UNREACHABLE here. what reason is that?
} }
} }

View File

@ -430,6 +430,14 @@ typedef enum {
#define END_STREAM_REASON_CONNRESET 12 #define END_STREAM_REASON_CONNRESET 12
#define END_STREAM_REASON_TORPROTOCOL 13 #define END_STREAM_REASON_TORPROTOCOL 13
/* These high-numbered end reasons are not part of the official spec,
* and are not intended to be put in relay end cells. They are here
* to be more informative when sending back socks replies to the
* application. */
#define END_STREAM_REASON_ALREADY_SOCKS_REPLIED 256
#define END_STREAM_REASON_CANT_ATTACH 257
#define END_STREAM_REASON_NET_UNREACHABLE 258
#define RESOLVED_TYPE_HOSTNAME 0 #define RESOLVED_TYPE_HOSTNAME 0
#define RESOLVED_TYPE_IPV4 4 #define RESOLVED_TYPE_IPV4 4
#define RESOLVED_TYPE_IPV6 6 #define RESOLVED_TYPE_IPV6 6

View File

@ -500,13 +500,13 @@ connection_edge_end_reason_socks5_response(int reason)
case END_STREAM_REASON_CONNECTREFUSED: case END_STREAM_REASON_CONNECTREFUSED:
return SOCKS5_CONNECTION_REFUSED; return SOCKS5_CONNECTION_REFUSED;
case END_STREAM_REASON_EXITPOLICY: case END_STREAM_REASON_EXITPOLICY:
return SOCKS5_CONNECTION_REFUSED; // XXX should be SOCKS5_NOT_ALLOWED ? return SOCKS5_NOT_ALLOWED;
case END_STREAM_REASON_DESTROY: case END_STREAM_REASON_DESTROY:
return SOCKS5_GENERAL_ERROR; return SOCKS5_GENERAL_ERROR;
case END_STREAM_REASON_DONE: case END_STREAM_REASON_DONE:
return SOCKS5_SUCCEEDED; return SOCKS5_SUCCEEDED;
case END_STREAM_REASON_TIMEOUT: case END_STREAM_REASON_TIMEOUT:
return SOCKS5_TTL_EXPIRED; // XXX is this correct? return SOCKS5_TTL_EXPIRED;
case END_STREAM_REASON_RESOURCELIMIT: case END_STREAM_REASON_RESOURCELIMIT:
return SOCKS5_GENERAL_ERROR; return SOCKS5_GENERAL_ERROR;
case END_STREAM_REASON_HIBERNATING: case END_STREAM_REASON_HIBERNATING:
@ -517,6 +517,13 @@ connection_edge_end_reason_socks5_response(int reason)
return SOCKS5_CONNECTION_REFUSED; return SOCKS5_CONNECTION_REFUSED;
case END_STREAM_REASON_TORPROTOCOL: case END_STREAM_REASON_TORPROTOCOL:
return SOCKS5_GENERAL_ERROR; return SOCKS5_GENERAL_ERROR;
case END_STREAM_REASON_ALREADY_SOCKS_REPLIED:
return SOCKS5_SUCCEEDED; /* never used */
case END_STREAM_REASON_CANT_ATTACH:
return SOCKS5_GENERAL_ERROR;
case END_STREAM_REASON_NET_UNREACHABLE:
return SOCKS5_NET_UNREACHABLE;
default: default:
log_fn(LOG_WARN,"Reason for ending (%d) not recognized.",reason); log_fn(LOG_WARN,"Reason for ending (%d) not recognized.",reason);
return SOCKS5_GENERAL_ERROR; return SOCKS5_GENERAL_ERROR;
@ -716,7 +723,7 @@ connection_edge_process_relay_cell_not_open(
cell->payload[RELAY_HEADER_SIZE], /*answer_type*/ cell->payload[RELAY_HEADER_SIZE], /*answer_type*/
cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/ cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
cell->payload+RELAY_HEADER_SIZE+2); /* answer */ cell->payload+RELAY_HEADER_SIZE+2); /* answer */
connection_close_unattached_ap(conn, END_STREAM_REASON_DONE); connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
return 0; return 0;
} }

View File

@ -394,7 +394,7 @@ void rend_client_desc_here(char *query) {
if (connection_ap_handshake_attach_circuit(conn) < 0) { if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */ /* it will never work */
log_fn(LOG_WARN,"attaching to a rend circ failed. Closing conn."); log_fn(LOG_WARN,"attaching to a rend circ failed. Closing conn.");
connection_close_unattached_ap(conn, END_STREAM_REASON_MISC); connection_close_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
} }
tor_assert(conn->state != AP_CONN_STATE_RENDDESC_WAIT); /* avoid loop */ tor_assert(conn->state != AP_CONN_STATE_RENDDESC_WAIT); /* avoid loop */
} else { /* 404, or fetch didn't get that far */ } else { /* 404, or fetch didn't get that far */