Browse Source

Fix bug 225: now "attachstream 0" treats conn like it just connected,
doing address remapping, handling .exit and .onion idioms, and so on.

Now we are more uniform in making sure that the controller hears about
all new connections, and making sure it hears when they close.


svn:r5897

Roger Dingledine 19 years ago
parent
commit
0fadf0aad6
3 changed files with 83 additions and 70 deletions
  1. 80 67
      src/or/connection_edge.c
  2. 1 3
      src/or/control.c
  3. 2 0
      src/or/or.h

+ 80 - 67
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;
   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 */
   tor_strlower(socks->address); /* normalize it */
   debug(LD_APP,"Client asked for %s:%d", safe_str(socks->address),
   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 */
   /* For address map controls, remap the address */
   addressmap_rewrite(socks->address, sizeof(socks->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,
     /* 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
      * 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.
      * information.
      */
      */
     warn(LD_APP,"Missing mapping for virtual address '%s'. Refusing.",
     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);
   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);
     warn(LD_APP, "Invalid hostname %s; rejecting", socks->address);
     connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
     connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
     return -1;
     return -1;
@@ -1033,7 +993,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
         /* XXXX Should this use server->address instead? */
         /* XXXX Should this use server->address instead? */
         in.s_addr = htonl(r->addr);
         in.s_addr = htonl(r->addr);
         strlcpy(socks->address, inet_ntoa(in), sizeof(socks->address));
         strlcpy(socks->address, inet_ntoa(in), sizeof(socks->address));
-      } else if (tor_should_handle_stream) {
+      } else {
         warn(LD_APP,
         warn(LD_APP,
              "Unrecognized server in exit address '%s.exit'. Refusing.",
              "Unrecognized server in exit address '%s.exit'. Refusing.",
              safe_str(socks->address));
              safe_str(socks->address));
@@ -1046,8 +1006,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
   if (addresstype != ONION_HOSTNAME) {
   if (addresstype != ONION_HOSTNAME) {
     /* not a hidden-service request (i.e. normal or .exit) */
     /* 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.",
       warn(LD_APP,"Destination '%s' seems to be an invalid hostname. Failing.",
            safe_str(socks->address));
            safe_str(socks->address));
       connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
       connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
@@ -1075,7 +1034,6 @@ connection_ap_handshake_process_socks(connection_t *conn)
         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 */
-      control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE);
     } else { /* socks->command == SOCKS_COMMAND_CONNECT */
     } else { /* socks->command == SOCKS_COMMAND_CONNECT */
       if (socks->port == 0) {
       if (socks->port == 0) {
         notice(LD_APP,"Application asked to connect to port 0. Refusing.");
         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 */
       /* help predict this next time */
       rep_hist_note_used_port(socks->port, time(NULL));
       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;
     return 0;
   } else {
   } else {
@@ -1159,12 +1112,72 @@ connection_ap_handshake_process_socks(connection_t *conn)
         rend_client_refetch_renddesc(conn->rend_query);
         rend_client_refetch_renddesc(conn->rend_query);
       }
       }
     }
     }
-    control_event_stream_status(conn, STREAM_EVENT_NEW);
     return 0;
     return 0;
   }
   }
   return 0; /* unreached but keeps the compiler happy */
   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
 /** 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.
  * already in use; return it. Return 0 if can't get a unique stream_id.
  */
  */

+ 1 - 3
src/or/control.c

@@ -1744,9 +1744,7 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
   }
   }
 
 
   if (zero_circ) {
   if (zero_circ) {
-    ap_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
-    if (connection_ap_handshake_attach_circuit(ap_conn)<0)
-      connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_CANT_ATTACH);
+    connection_ap_handshake_rewrite_and_attach(ap_conn);
     send_control_done(conn);
     send_control_done(conn);
     return 0;
     return 0;
   }
   }

+ 2 - 0
src/or/or.h

@@ -1732,6 +1732,8 @@ int address_is_in_virtual_range(const char *addr);
 const char *addressmap_register_virtual_address(int type, char *new_address);
 const char *addressmap_register_virtual_address(int type, char *new_address);
 void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
 void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
                              time_t max_expires);
                              time_t max_expires);
+int
+connection_ap_handshake_rewrite_and_attach(connection_t *conn);
 
 
 void parse_socks_policy(void);
 void parse_socks_policy(void);
 void free_socks_policy(void);
 void free_socks_policy(void);