]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
hs-v3: Report rendezvous circuit failure SOCKS ExtendedErrors
authorDavid Goulet <dgoulet@torproject.org>
Wed, 11 Dec 2019 15:15:02 +0000 (10:15 -0500)
committerDavid Goulet <dgoulet@torproject.org>
Wed, 8 Apr 2020 11:56:54 +0000 (07:56 -0400)
Signed-off-by: David Goulet <dgoulet@torproject.org>
src/feature/hs/hs_circuit.c
src/feature/hs/hs_client.c
src/feature/hs/hs_client.h

index dc13c7045ecb8b440fe1a20e524d045a020b4c44..53f574c14a5c53756aaef0bcab0074b76961db0f 100644 (file)
@@ -621,6 +621,20 @@ setup_introduce1_data(const hs_desc_intro_point_t *ip,
   return ret;
 }
 
+/** Helper: cleanup function for client circuit. This is for every HS version.
+ * It is called from hs_circ_cleanup_on_close() entry point. */
+static void
+cleanup_on_close_client_circ(circuit_t *circ)
+{
+  tor_assert(circ);
+
+  if (circuit_is_hs_v3(circ)) {
+    hs_client_circuit_cleanup_on_close(circ);
+  }
+  /* It is possible the circuit has an HS purpose but no identifier (rend_data
+   * or hs_ident). Thus possible that this passess through. */
+}
+
 /** Helper: cleanup function for client circuit. This is for every HS version.
  * It is called from hs_circ_cleanup_on_free() entry point. */
 static void
@@ -1293,6 +1307,10 @@ hs_circ_cleanup_on_close(circuit_t *circ)
 {
   tor_assert(circ);
 
+  if (circuit_purpose_is_hs_client(circ->purpose)) {
+    cleanup_on_close_client_circ(circ);
+  }
+
   /* On close, we simply remove it from the circuit map. It can not be used
    * anymore. We keep this code path fast and lean. */
 
index 4b9c9cb186c3879af27838fc094b84fa92c20031..ceaba08ff99f5f376dcd49a12edb1dce4d1689f3 100644 (file)
@@ -961,6 +961,27 @@ client_get_random_intro(const ed25519_public_key_t *service_pk)
   return ei;
 }
 
+/** Called when a rendezvous circuit has timed out. Every streams attached to
+ * the circuit will get set with the SOCKS5_HS_REND_FAILED (0xF3) extended
+ * error code so if the connection to the rendezvous point ends up not
+ * working, this code could be sent back as a reason. */
+static void
+socks_report_rend_circuit_timed_out(const origin_circuit_t *rend_circ)
+{
+  tor_assert(rend_circ);
+
+  /* For each entry connections attached to this rendezvous circuit, report
+   * the error. */
+  for (edge_connection_t *edge = rend_circ->p_streams; edge;
+       edge = edge->next_stream) {
+     entry_connection_t *entry = EDGE_TO_ENTRY_CONN(edge);
+     if (entry->socks_request) {
+       entry->socks_request->socks_extended_error_code =
+         SOCKS5_HS_REND_FAILED;
+     }
+  }
+}
+
 /** Called when introduction has failed meaning there is no more usable
  * introduction points to be used (either NACKed or failed) for the given
  * entry connection.
@@ -1779,6 +1800,37 @@ get_hs_client_auths_map(void)
 /* Public API */
 /* ========== */
 
+/** Called when a circuit was just cleaned up. This is done right before the
+ * circuit is marked for close. */
+void
+hs_client_circuit_cleanup_on_close(const circuit_t *circ)
+{
+  bool has_timed_out;
+
+  tor_assert(circ);
+  tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+  has_timed_out =
+    (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT);
+
+  switch (circ->purpose) {
+  case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
+  case CIRCUIT_PURPOSE_C_REND_READY:
+  case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
+  case CIRCUIT_PURPOSE_C_REND_JOINED:
+    /* Report extended SOCKS error code when a rendezvous circuit timeouts.
+     * This MUST be done on_close() because it is possible the entry
+     * connection would get closed before the circuit is freed and thus
+     * failing to report the error code. */
+    if (has_timed_out) {
+      socks_report_rend_circuit_timed_out(CONST_TO_ORIGIN_CIRCUIT(circ));
+    }
+    break;
+  default:
+    break;
+  }
+}
+
 /** Called when a circuit was just cleaned up. This is done right before the
  * circuit is freed. */
 void
index 3660bfa96ccdd4933a80444ae7bc21588578f88a..685b10f95559969f431136ee71021576ab44030b 100644 (file)
@@ -110,6 +110,7 @@ int hs_client_send_introduce1(origin_circuit_t *intro_circ,
                               origin_circuit_t *rend_circ);
 
 void hs_client_circuit_has_opened(origin_circuit_t *circ);
+void hs_client_circuit_cleanup_on_close(const circuit_t *circ);
 void hs_client_circuit_cleanup_on_free(const circuit_t *circ);
 
 int hs_client_receive_rendezvous_acked(origin_circuit_t *circ,