[tor-commits] [tor/master] hs: Refactor the service exit connection code

nickm at torproject.org nickm at torproject.org
Wed Aug 9 00:36:37 UTC 2017


commit 7163ce7f62d6c487193fe43828420ba4fe721b9f
Author: David Goulet <dgoulet at torproject.org>
Date:   Wed May 10 13:43:37 2017 -0400

    hs: Refactor the service exit connection code
    
    This commit simply moves the code from the if condition of a rendezvous
    circuit to a function to handle such a connection. No code was modified
    _except_ the use or rh.stream_id changed to n_stream->stream_id so we don't
    have to pass the cell header to the function.
    
    This is groundwork for prop224 support which will break down the
    handle_hs_exit_conn() depending on the version of hidden service the circuit
    and edge connection is for.
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/connection_edge.c | 112 ++++++++++++++++++++++++++---------------------
 1 file changed, 61 insertions(+), 51 deletions(-)

diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index ddcff6aa9..8e447131f 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -3066,6 +3066,64 @@ begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
   return 0;
 }
 
+/** For the given <b>circ</b> and the edge connection <b>n_stream</b>, setup
+ * the the connection, attach it to the circ and connect it. Return 0 on
+ * success or END_CIRC_AT_ORIGIN if we can't find the requested hidden
+ * service port where the caller should close the circuit. */
+static int
+handle_hs_exit_conn(circuit_t *circ, edge_connection_t *n_stream)
+{
+  origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+  log_info(LD_REND,"begin is for rendezvous. configuring stream.");
+  n_stream->base_.address = tor_strdup("(rendezvous)");
+  n_stream->base_.state = EXIT_CONN_STATE_CONNECTING;
+  n_stream->rend_data = rend_data_dup(origin_circ->rend_data);
+  tor_assert(connection_edge_is_rendezvous_stream(n_stream));
+  assert_circuit_ok(circ);
+
+  const int r = rend_service_set_connection_addr_port(n_stream, origin_circ);
+  if (r < 0) {
+    log_info(LD_REND,"Didn't find rendezvous service (port %d)",
+             n_stream->base_.port);
+    /* Send back reason DONE because we want to make hidden service port
+     * scanning harder thus instead of returning that the exit policy
+     * didn't match, which makes it obvious that the port is closed,
+     * return DONE and kill the circuit. That way, a user (malicious or
+     * not) needs one circuit per bad port unless it matches the policy of
+     * the hidden service. */
+    relay_send_end_cell_from_edge(n_stream->stream_id, circ,
+                                  END_STREAM_REASON_DONE,
+                                  origin_circ->cpath->prev);
+    connection_free(TO_CONN(n_stream));
+
+    /* Drop the circuit here since it might be someone deliberately
+     * scanning the hidden service ports. Note that this mitigates port
+     * scanning by adding more work on the attacker side to successfully
+     * scan but does not fully solve it. */
+    if (r < -1)
+      return END_CIRC_AT_ORIGIN;
+    else
+      return 0;
+  }
+  assert_circuit_ok(circ);
+  log_debug(LD_REND,"Finished assigning addr/port");
+  n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */
+
+  /* add it into the linked list of p_streams on this circuit */
+  n_stream->next_stream = origin_circ->p_streams;
+  n_stream->on_circuit = circ;
+  origin_circ->p_streams = n_stream;
+  assert_circuit_ok(circ);
+
+  origin_circ->rend_data->nr_streams++;
+
+  connection_exit_connect(n_stream);
+
+  /* For path bias: This circuit was used successfully */
+  pathbias_mark_use_success(origin_circ);
+  return 0;
+}
+
 /** A relay 'begin' or 'begin_dir' cell has arrived, and either we are
  * an exit hop for the circuit, or we are the origin and it is a
  * rendezvous begin.
@@ -3217,58 +3275,10 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
   n_stream->deliver_window = STREAMWINDOW_START;
 
   if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
-    tor_assert(origin_circ);
-    log_info(LD_REND,"begin is for rendezvous. configuring stream.");
-    n_stream->base_.address = tor_strdup("(rendezvous)");
-    n_stream->base_.state = EXIT_CONN_STATE_CONNECTING;
-    n_stream->rend_data = rend_data_dup(origin_circ->rend_data);
-    tor_assert(connection_edge_is_rendezvous_stream(n_stream));
-    assert_circuit_ok(circ);
-
-    const int r = rend_service_set_connection_addr_port(n_stream, origin_circ);
-    if (r < 0) {
-      log_info(LD_REND,"Didn't find rendezvous service (port %d)",
-               n_stream->base_.port);
-      /* Send back reason DONE because we want to make hidden service port
-       * scanning harder thus instead of returning that the exit policy
-       * didn't match, which makes it obvious that the port is closed,
-       * return DONE and kill the circuit. That way, a user (malicious or
-       * not) needs one circuit per bad port unless it matches the policy of
-       * the hidden service. */
-      relay_send_end_cell_from_edge(rh.stream_id, circ,
-                                    END_STREAM_REASON_DONE,
-                                    layer_hint);
-      connection_free(TO_CONN(n_stream));
-      tor_free(address);
-
-      /* Drop the circuit here since it might be someone deliberately
-       * scanning the hidden service ports. Note that this mitigates port
-       * scanning by adding more work on the attacker side to successfully
-       * scan but does not fully solve it. */
-      if (r < -1)
-        return END_CIRC_AT_ORIGIN;
-      else
-        return 0;
-    }
-    assert_circuit_ok(circ);
-    log_debug(LD_REND,"Finished assigning addr/port");
-    n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */
-
-    /* add it into the linked list of p_streams on this circuit */
-    n_stream->next_stream = origin_circ->p_streams;
-    n_stream->on_circuit = circ;
-    origin_circ->p_streams = n_stream;
-    assert_circuit_ok(circ);
-
-    origin_circ->rend_data->nr_streams++;
-
-    connection_exit_connect(n_stream);
-
-    /* For path bias: This circuit was used successfully */
-    pathbias_mark_use_success(origin_circ);
-
     tor_free(address);
-    return 0;
+    /* We handle this circuit and stream in this function for all supported
+     * hidden service version. */
+    return handle_hs_exit_conn(circ, n_stream);
   }
   tor_strlower(address);
   n_stream->base_.address = address;





More information about the tor-commits mailing list