[tor-commits] [tor/master] test: Unit test for the SOCKS5 HS client auth errors

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


commit c0dd5324b35ee158dc392556b67b5a098de2874a
Author: David Goulet <dgoulet at torproject.org>
Date:   Thu Jun 6 08:43:48 2019 -0400

    test: Unit test for the SOCKS5 HS client auth errors
    
    Part of #30382
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/test/test_hs_client.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 96faa9bb7..cf3763427 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -25,6 +25,7 @@
 #include "app/config/config.h"
 #include "lib/crypt_ops/crypto_cipher.h"
 #include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
 #include "core/or/channeltls.h"
 #include "feature/dircommon/directory.h"
 #include "core/mainloop/mainloop.h"
@@ -92,6 +93,24 @@ helper_config_client(const char *conf, int validate_only)
   return ret;
 }
 
+static void
+helper_add_random_client_auth(const ed25519_public_key_t *service_pk)
+{
+  char *conf = NULL;
+#define conf_fmt "ClientOnionAuthDir %s\n"
+  tor_asprintf(&conf, conf_fmt, get_fname("auth_keys"));
+#undef conf_fmt
+  helper_config_client(conf, 0);
+  tor_free(conf);
+
+  digest256map_t *client_auths = get_hs_client_auths_map();
+  hs_client_service_authorization_t *auth =
+    tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+  curve25519_secret_key_generate(&auth->enc_seckey, 0);
+  hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
+  digest256map_set(client_auths, service_pk->pubkey, auth);
+}
+
 /* Test helper function: Setup a circuit and a stream with the same hidden
  * service destination, and put them in <b>circ_out</b> and
  * <b>conn_out</b>. Make the stream wait for circuits to be established to the
@@ -551,6 +570,17 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason,
 }
 
 static void
+mock_connection_mark_unattached_ap_no_close(entry_connection_t *conn,
+                                            int endreason, int line,
+                                            const char *file)
+{
+  (void) conn;
+  (void) endreason;
+  (void) line;
+  (void) file;
+}
+
+static void
 test_descriptor_fetch(void *arg)
 {
   int ret;
@@ -1094,6 +1124,108 @@ test_close_intro_circuits_cache_clean(void *arg)
   UNMOCK(networkstatus_get_live_consensus);
 }
 
+static void
+test_socks_hs_errors(void *arg)
+{
+  int ret;
+  char *desc_encoded = NULL;
+  ed25519_keypair_t service_kp;
+  ed25519_keypair_t signing_kp;
+  entry_connection_t *socks_conn = NULL;
+  dir_connection_t *dir_conn = NULL;
+  hs_descriptor_t *desc = NULL;
+  uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+
+  (void) arg;
+
+  MOCK(networkstatus_get_live_consensus,
+       mock_networkstatus_get_live_consensus);
+  MOCK(connection_mark_unattached_ap_,
+       mock_connection_mark_unattached_ap_no_close);
+  MOCK(read_file_to_str, mock_read_file_to_str);
+  MOCK(tor_listdir, mock_tor_listdir);
+  MOCK(check_private_dir, mock_check_private_dir);
+
+    /* Set consensus time */
+  parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+                           &mock_ns.valid_after);
+  parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+                           &mock_ns.fresh_until);
+  parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+                           &mock_ns.valid_until);
+
+  hs_init();
+
+  ret = ed25519_keypair_generate(&service_kp, 0);
+  tt_int_op(ret, OP_EQ, 0);
+  ret = ed25519_keypair_generate(&signing_kp, 0);
+  tt_int_op(ret, OP_EQ, 0);
+
+  socks_conn = helper_build_socks_connection(&service_kp.pubkey,
+                                             AP_CONN_STATE_RENDDESC_WAIT);
+  tt_assert(socks_conn);
+
+  /* Create directory connection. */
+  dir_conn = dir_connection_new(AF_INET);
+  dir_conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t));
+  TO_CONN(dir_conn)->purpose = DIR_PURPOSE_FETCH_HSDESC;
+  ed25519_pubkey_copy(&dir_conn->hs_ident->identity_pk, &service_kp.pubkey);
+
+  /* Encode descriptor so we can decode it. */
+  desc = hs_helper_build_hs_desc_with_ip(&service_kp);
+  tt_assert(desc);
+
+  crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+  ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+                                  &desc_encoded);
+  tt_int_op(ret, OP_EQ, 0);
+  tt_assert(desc_encoded);
+
+  /* Try decoding. Point this to an existing descriptor. The following should
+   * fail thus the desc_out should be set to NULL. */
+  hs_descriptor_t *desc_out = desc;
+  ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
+                                    &desc_out);
+  tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+  tt_assert(desc_out == NULL);
+
+  /* The caching will fail to decrypt because the descriptor_cookie used above
+   * is not known to the HS subsystem. This will lead to a missing client
+   * auth. */
+  hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
+
+  tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
+            SOCKS5_HS_MISSING_CLIENT_AUTH);
+
+  /* Add in the global client auth list bad creds for this service. */
+  helper_add_random_client_auth(&service_kp.pubkey);
+
+  ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
+                                    &desc_out);
+  tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
+  tt_assert(desc_out == NULL);
+
+  /* Simmulate a fetch done again. This should replace the cached descriptor
+   * and signal a bad client authorization. */
+  hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
+  tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
+            SOCKS5_HS_BAD_CLIENT_AUTH);
+
+ done:
+  connection_free_minimal(ENTRY_TO_CONN(socks_conn));
+  connection_free_minimal(TO_CONN(dir_conn));
+  hs_descriptor_free(desc);
+  tor_free(desc_encoded);
+
+  hs_free_all();
+
+  UNMOCK(networkstatus_get_live_consensus);
+  UNMOCK(connection_mark_unattached_ap_);
+  UNMOCK(read_file_to_str);
+  UNMOCK(tor_listdir);
+  UNMOCK(check_private_dir);
+}
+
 struct testcase_t hs_client_tests[] = {
   { "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy,
     TT_FORK, NULL, NULL },
@@ -1116,5 +1248,8 @@ struct testcase_t hs_client_tests[] = {
   { "close_intro_circuits_cache_clean", test_close_intro_circuits_cache_clean,
     TT_FORK, NULL, NULL },
 
+  /* SOCKS5 Extended Error Code. */
+  { "socks_hs_errors", test_socks_hs_errors, TT_FORK, NULL, NULL },
+
   END_OF_TESTCASES
 };





More information about the tor-commits mailing list