Commit a60f7caa authored by Roger Dingledine's avatar Roger Dingledine
Browse files

start allowing clients to give up on trackhostexits targets if

five circuit attempts fail for a given stream. part of the fix
for bug 437. still an XXX020rc remaining.


svn:r13648
parent 18a209ff
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2876,7 +2876,7 @@ assert_connection_ok(connection_t *conn, time_t now)
    assert_buf_ok(conn->outbuf);
  }

  if (conn->chosen_exit_optional) {
  if (conn->chosen_exit_optional || conn->chosen_exit_retries) {
    tor_assert(conn->type == CONN_TYPE_AP);
    tor_assert((TO_EDGE_CONN(conn))->chosen_exit_name);
  }
+26 −3
Original line number Diff line number Diff line
@@ -472,13 +472,16 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
    if (conn->marked_for_close ||
        conn->type != CONN_TYPE_AP ||
        conn->state != AP_CONN_STATE_CIRCUIT_WAIT ||
        !conn->chosen_exit_optional)
        (!conn->chosen_exit_optional &&
         !conn->chosen_exit_retries))
      continue;
    edge_conn = TO_EDGE_CONN(conn);
    r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
    r2 = router_get_by_nickname(info->nickname, 0);
    if (r1 && r2 && r1==r2) {
    if (!r1 || !r2 || r1 != r2)
      continue;
    tor_assert(edge_conn->socks_request);
    if (conn->chosen_exit_optional) {
      log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.",
               safe_str(edge_conn->chosen_exit_name),
               escaped_safe_str(edge_conn->socks_request->address));
@@ -488,6 +491,16 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
       * think it'll be using an enclave. */
      consider_plaintext_ports(edge_conn, edge_conn->socks_request->port);
    }
    if (conn->chosen_exit_retries) {
      if (--conn->chosen_exit_retries == 0) { /* give up! */
        /* XXX020rc unregister maps from foo to
         * foo.chosen_exit_name.exit \forall foo. -RD */
        tor_free(edge_conn->chosen_exit_name); /* clears it */
        /* if this port is dangerous, warn or reject it now that we don't
         * think it'll be using an enclave. */
        consider_plaintext_ports(edge_conn, edge_conn->socks_request->port);
      }
    }
  });
}

@@ -1244,6 +1257,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
  int automap = 0;
  char orig_address[MAX_SOCKS_ADDR_LEN];
  time_t map_expires = TIME_MAX;
  int remapped_to_exit = 0;
  time_t now = time(NULL);

  tor_strlower(socks->address); /* normalize it */
@@ -1299,11 +1313,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
      }
    }
  } else if (!automap) {
    int started_without_chosen_exit = strcasecmpend(socks->address, ".exit");
    /* For address map controls, remap the address. */
    if (addressmap_rewrite(socks->address, sizeof(socks->address),
                           &map_expires)) {
      control_event_stream_status(conn, STREAM_EVENT_REMAP,
                                  REMAP_STREAM_SOURCE_CACHE);
      if (started_without_chosen_exit &&
          !strcasecmpend(socks->address, ".exit") &&
          map_expires < TIME_MAX)
        remapped_to_exit = 1;
    }
  }

@@ -1340,6 +1359,10 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
    if (s) {
      if (s[1] != '\0') {
        conn->chosen_exit_name = tor_strdup(s+1);
/* DOCDOC */
#define TRACKHOSTEXITS_RETRIES 5
        if (remapped_to_exit) /* 5 tries before it expires the addressmap */
          TO_CONN(conn)->chosen_exit_retries = TRACKHOSTEXITS_RETRIES;
        *s = 0;
      } else {
        log_warn(LD_APP,"Malformed exit address '%s.exit'. Refusing.",
+6 −1
Original line number Diff line number Diff line
@@ -811,6 +811,11 @@ typedef struct connection_t {
  /** For AP connections only. If 1, and we fail to reach the chosen exit,
   * stop requiring it. */
  unsigned int chosen_exit_optional:1;
  /** For AP connections only. If non-zero, this exit node was picked as
   * a result of the TrackHostExit, and the value decrements every time
   * we fail to complete a circuit to our chosen exit -- if it reaches
   * zero, abandon the associated mapaddress. */
  unsigned int chosen_exit_retries:3;
  /** Set to 1 when we're inside connection_flushed_some to keep us from
   * calling connection_handle_write() recursively. */
  unsigned int in_flushed_some:1;
@@ -861,7 +866,7 @@ typedef struct connection_t {
                                      * we marked for close? */
  char *address; /**< FQDN (or IP) of the guy on the other end.
                  * strdup into this, because free_connection frees it. */
  /** Annother connection that's connected to this one in lieu of a socket. */
  /** Another connection that's connected to this one in lieu of a socket. */
  struct connection_t *linked_conn;

  /* XXXX021 move this into a subtype. */
+10 −1
Original line number Diff line number Diff line
@@ -771,9 +771,18 @@ connection_edge_process_end_not_open(
                               NULL)) {
          control_event_stream_status(conn, STREAM_EVENT_REMAP, 0);
        }
        if (conn->_base.chosen_exit_optional) {
        if (conn->_base.chosen_exit_optional ||
            conn->_base.chosen_exit_retries) {
          /* stop wanting a specific exit */
          conn->_base.chosen_exit_optional = 0;
          /* A non-zero chosen_exit_retries can happen if we set a
           * TrackHostExits for this address under a port that the exit
           * relay allows, but then try the same address with a different
           * port that it doesn't allow to exit. We shouldn't unregister
           * the mapping, since it is probably still wanted on the
           * original port. But now we give away to the exit relay that
           * we probably have a TrackHostExits on it. So be it. */
          conn->_base.chosen_exit_retries = 0;
          tor_free(conn->chosen_exit_name); /* clears it */
        }
        if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)