Commit 7a79acd9 authored by Roger Dingledine's avatar Roger Dingledine
Browse files

clean up socks reply stuff more.

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


svn:r3895
parent ce854906
Loading
Loading
Loading
Loading
+32 −9
Original line number Diff line number Diff line
@@ -26,16 +26,24 @@ static int address_is_in_virtual_range(const char *addr);
 */
void
connection_close_unattached_ap(connection_t *conn, int endreason) {

  tor_assert(conn->type == CONN_TYPE_AP);
  conn->has_sent_end = 1; /* no circ yet */

  if (!conn->socks_request->has_finished) {
    socks5_reply_status_t socksreason =
      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)
      connection_ap_handshake_socks_reply(conn, NULL, 0, socksreason);
    else
      connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
  }

  connection_mark_for_close(conn);
  conn->hold_open_until_flushed = 1;
}
@@ -90,7 +98,7 @@ int connection_edge_process_inbuf(connection_t *conn, int package_partial) {
  switch (conn->state) {
    case AP_CONN_STATE_SOCKS_WAIT:
      if (connection_ap_handshake_process_socks(conn) < 0) {
        connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
        /* already marked */
        return -1;
      }
      return 0;
@@ -345,7 +353,7 @@ void connection_ap_expire_beginning(void) {
    conn->timestamp_lastread += 15;
    /* move it back into 'pending' state, and try to attach. */
    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 */
}
@@ -368,7 +376,7 @@ void connection_ap_attach_pending(void)
        conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
      continue;
    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.");
      connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
                                          SOCKS5_GENERAL_ERROR);
      socks->replylen = 0; /* zero it out so we can do another round of negotiation */
    } else {
      log_fn(LOG_WARN,"Fetching socks handshake failed. Closing.");
      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 */

  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.",
           socks->address);
    connection_close_unattached_ap(conn, END_STREAM_REASON_INTERNAL);
    return -1;
  }

@@ -899,6 +908,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
    char *s = strrchr(socks->address,'.');
    if (!s || s[1] == '\0') {
      log_fn(LOG_WARN,"Malformed exit address '%s'. Refusing.", socks->address);
      connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
      return -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)) {
      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;
    }

@@ -920,13 +931,14 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
      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_close_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;
        connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
                                               (char*)&answer);
        connection_close_unattached_ap(conn, END_STREAM_REASON_DONE);
        connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
        return 0;
      }
      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 */
      if (socks->port == 0) {
        log_fn(LOG_NOTICE,"Application asked to connect to port 0. Refusing.");
        connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
        return -1;
      }
      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) {
      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 {
      conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
      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. */
      log_fn(LOG_WARN,"Resolve requests to hidden services not allowed. Failing.");
      connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
      connection_close_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
      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);
    if (r<0) {
      log_fn(LOG_WARN,"Invalid service descriptor %s", conn->rend_query);
      connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
      return -1;
    }
    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) {
        conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
        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 {
        conn->state = AP_CONN_STATE_RENDDESC_WAIT;
        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 */
  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]);
    return -1;
  }
+1 −1
Original line number Diff line number Diff line
@@ -736,7 +736,7 @@ static int handle_control_attachstream(connection_t *conn, uint32_t len,
  if (!circ_id) {
    ap_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
    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);
    return 0;
  }
+1 −2
Original line number Diff line number Diff line
@@ -478,8 +478,7 @@ void directory_all_unreachable(time_t now) {
                                              AP_CONN_STATE_CIRCUIT_WAIT))) {
    log_fn(LOG_NOTICE,"Network down? Failing connection to '%s:%d'.",
           conn->socks_request->address, conn->socks_request->port);
    connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
// XXX should maybe reflect SOCKS5_NET_UNREACHABLE here. what reason is that?
    connection_close_unattached_ap(conn, END_STREAM_REASON_NET_UNREACHABLE);
  }
}

+8 −0
Original line number Diff line number Diff line
@@ -430,6 +430,14 @@ typedef enum {
#define END_STREAM_REASON_CONNRESET 12
#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_IPV4 4
#define RESOLVED_TYPE_IPV6 6
+10 −3
Original line number Diff line number Diff line
@@ -500,13 +500,13 @@ connection_edge_end_reason_socks5_response(int reason)
    case END_STREAM_REASON_CONNECTREFUSED:
      return SOCKS5_CONNECTION_REFUSED;
    case END_STREAM_REASON_EXITPOLICY:
      return SOCKS5_CONNECTION_REFUSED; // XXX should be SOCKS5_NOT_ALLOWED ?
      return SOCKS5_NOT_ALLOWED;
    case END_STREAM_REASON_DESTROY:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_DONE:
      return SOCKS5_SUCCEEDED;
    case END_STREAM_REASON_TIMEOUT:
      return SOCKS5_TTL_EXPIRED; // XXX is this correct?
      return SOCKS5_TTL_EXPIRED;
    case END_STREAM_REASON_RESOURCELIMIT:
      return SOCKS5_GENERAL_ERROR;
    case END_STREAM_REASON_HIBERNATING:
@@ -517,6 +517,13 @@ connection_edge_end_reason_socks5_response(int reason)
      return SOCKS5_CONNECTION_REFUSED;
    case END_STREAM_REASON_TORPROTOCOL:
      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:
      log_fn(LOG_WARN,"Reason for ending (%d) not recognized.",reason);
      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+1], /*answer_len*/
                   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;
  }

Loading