[tor-commits] [tor/master] hs-v3: Set extended error when missing/bad client auth

asn at torproject.org asn at torproject.org
Mon Nov 18 17:12:15 UTC 2019


commit 542402cd60bc6b26f43c399b238602a1f3c18d85
Author: David Goulet <dgoulet at torproject.org>
Date:   Tue May 28 13:49:03 2019 -0400

    hs-v3: Set extended error when missing/bad client auth
    
    Part of #30382
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/feature/dirclient/dirclient.c | 37 ++++++++++++++++++++++++++++---------
 src/feature/hs/hs_client.c        | 31 +++++++++++++++++++++++++++++++
 src/feature/hs/hs_client.h        |  2 ++
 3 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index 64205a44e..abece62dd 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -2734,21 +2734,40 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
     /* We got something: Try storing it in the cache. */
     decode_status = hs_cache_store_as_client(body,
                                              &conn->hs_ident->identity_pk);
-    if (decode_status != HS_DESC_DECODE_OK) {
-      log_info(LD_REND, "Failed to store hidden service descriptor");
-      /* Fire control port FAILED event. */
-      hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
-                                   "BAD_DESC");
-      hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
-                                    NULL);
-    } else {
+    switch (decode_status) {
+    case HS_DESC_DECODE_OK:
+    case HS_DESC_DECODE_NEED_CLIENT_AUTH:
+    case HS_DESC_DECODE_BAD_CLIENT_AUTH:
       log_info(LD_REND, "Stored hidden service descriptor successfully.");
       TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
-      hs_client_desc_has_arrived(conn->hs_ident);
+      if (decode_status == HS_DESC_DECODE_OK) {
+        hs_client_desc_has_arrived(conn->hs_ident);
+      } else {
+        /* This handles both client auth decode status. */
+        hs_client_desc_missing_bad_client_auth(conn->hs_ident, decode_status);
+        log_info(LD_REND, "Stored hidden service descriptor requires "
+                          "%s client authorization.",
+                 decode_status == HS_DESC_DECODE_NEED_CLIENT_AUTH ? "missing"
+                                                                  : "new");
+      }
       /* Fire control port RECEIVED event. */
       hs_control_desc_event_received(conn->hs_ident, conn->identity_digest);
       hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
                                     body);
+      break;
+    case HS_DESC_DECODE_ENCRYPTED_ERROR:
+    case HS_DESC_DECODE_SUPERENC_ERROR:
+    case HS_DESC_DECODE_PLAINTEXT_ERROR:
+    case HS_DESC_DECODE_GENERIC_ERROR:
+    default:
+      log_info(LD_REND, "Failed to store hidden service descriptor. "
+                        "Descriptor decoding status: %d", decode_status);
+      /* Fire control port FAILED event. */
+      hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
+                                   "BAD_DESC");
+      hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
+                                    NULL);
+      break;
     }
     break;
   case 404:
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 0e4df73b9..0a10492e0 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1782,6 +1782,37 @@ hs_client_desc_not_found(const hs_ident_dir_conn_t *ident)
   smartlist_free(entry_conns);
 }
 
+/* This is called when a descriptor fetch was successful but the descriptor
+ * couldn't be decrypted due to missing or bad client authorization. */
+void
+hs_client_desc_missing_bad_client_auth(const hs_ident_dir_conn_t *ident,
+                                       hs_desc_decode_status_t status)
+{
+  smartlist_t *entry_conns;
+
+  tor_assert(ident);
+
+  entry_conns = find_entry_conns(&ident->identity_pk);
+
+  SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+    socks5_reply_status_t code;
+    if (status == HS_DESC_DECODE_BAD_CLIENT_AUTH) {
+      code = SOCKS5_HS_BAD_CLIENT_AUTH;
+    } else if (status == HS_DESC_DECODE_NEED_CLIENT_AUTH) {
+      code = SOCKS5_HS_MISSING_CLIENT_AUTH;
+    } else {
+      /* We should not be called with another type of status. Recover by
+       * sending a generic error. */
+      tor_assert_nonfatal_unreached();
+      code = HS_DESC_DECODE_GENERIC_ERROR;
+    }
+    entry_conn->socks_request->socks_extended_error_code = code;
+  } SMARTLIST_FOREACH_END(entry_conn);
+
+  /* We don't have ownership of the objects in this list. */
+  smartlist_free(entry_conns);
+}
+
 /** Return a newly allocated extend_info_t for a randomly chosen introduction
  * point for the given edge connection identifier ident. Return NULL if we
  * can't pick any usable introduction points. */
diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h
index 6bd6e5748..616d31a01 100644
--- a/src/feature/hs/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -74,6 +74,8 @@ int hs_client_receive_rendezvous2(origin_circuit_t *circ,
 
 void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
 void hs_client_desc_not_found(const hs_ident_dir_conn_t *ident);
+void hs_client_desc_missing_bad_client_auth(const hs_ident_dir_conn_t *ident,
+                                            hs_desc_decode_status_t status);
 
 extend_info_t *hs_client_get_random_intro_from_edge(
                                           const edge_connection_t *edge_conn);





More information about the tor-commits mailing list