[tor-commits] [tor/master] test: HS v3 client authorization loading secret key

nickm at torproject.org nickm at torproject.org
Fri Sep 7 19:06:18 UTC 2018


commit 9c362192361bec379f83f37426236b41c2a17e8e
Author: Suphanat Chunhapanya <haxx.pop at gmail.com>
Date:   Sun Aug 19 08:26:43 2018 +0700

    test: HS v3 client authorization loading secret key
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/feature/hs/hs_client.c |  14 +++-
 src/feature/hs/hs_client.h |  11 +++
 src/test/test_hs_client.c  | 174 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 197 insertions(+), 2 deletions(-)

diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 7c545c35d..18c79e0c4 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1428,7 +1428,7 @@ client_service_authorization_free_all(void)
 
 /* Check if the auth key file name is valid or not. Return 1 if valid,
  * otherwise return 0. */
-static int
+STATIC int
 auth_key_filename_is_valid(const char *filename)
 {
   int ret = 1;
@@ -1448,7 +1448,7 @@ auth_key_filename_is_valid(const char *filename)
   return ret;
 }
 
-static hs_client_service_authorization_t *
+STATIC hs_client_service_authorization_t *
 parse_auth_file_content(const char *client_key_str)
 {
   char *onion_address = NULL;
@@ -1836,3 +1836,13 @@ hs_client_dir_info_changed(void)
    * AP_CONN_STATE_RENDDESC_WAIT state in order to fetch the descriptor. */
   retry_all_socks_conn_waiting_for_desc();
 }
+
+#ifdef TOR_UNIT_TESTS
+
+STATIC digest256map_t *
+get_hs_client_auths_map(void)
+{
+  return client_auths;
+}
+
+#endif /* defined(TOR_UNIT_TESTS) */
diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h
index 6d4c84774..1ba0338dc 100644
--- a/src/feature/hs/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -84,6 +84,11 @@ void hs_client_free_all(void);
 
 #ifdef HS_CLIENT_PRIVATE
 
+STATIC int auth_key_filename_is_valid(const char *filename);
+
+STATIC hs_client_service_authorization_t *
+parse_auth_file_content(const char *client_key_str);
+
 STATIC routerstatus_t *
 pick_hsdir_v3(const ed25519_public_key_t *onion_identity_pk);
 
@@ -99,6 +104,12 @@ STATIC int handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
 MOCK_DECL(STATIC hs_client_fetch_status_t,
           fetch_v3_desc, (const ed25519_public_key_t *onion_identity_pk));
 
+#ifdef TOR_UNIT_TESTS
+
+STATIC digest256map_t *get_hs_client_auths_map(void);
+
+#endif /* defined(TOR_UNIT_TESTS) */
+
 #endif /* defined(HS_CLIENT_PRIVATE) */
 
 #endif /* !defined(TOR_HS_CLIENT_H) */
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index e03c80098..eacbd328e 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -6,6 +6,7 @@
  * \brief Test prop224 HS client functionality.
  */
 
+#define CONFIG_PRIVATE
 #define CRYPTO_PRIVATE
 #define MAIN_PRIVATE
 #define HS_CLIENT_PRIVATE
@@ -32,6 +33,7 @@
 #include "feature/hs/hs_circuit.h"
 #include "feature/hs/hs_circuitmap.h"
 #include "feature/hs/hs_client.h"
+#include "feature/hs/hs_config.h"
 #include "feature/hs/hs_ident.h"
 #include "feature/hs/hs_cache.h"
 #include "core/or/circuitlist.h"
@@ -73,6 +75,20 @@ mock_networkstatus_get_live_consensus(time_t now)
   return &mock_ns;
 }
 
+static int
+helper_config_client(const char *conf, int validate_only)
+{
+  int ret = 0;
+  or_options_t *options = NULL;
+  tt_assert(conf);
+  options = helper_parse_options(conf);
+  tt_assert(options);
+  ret = hs_config_client_auth_all(options, validate_only);
+ done:
+  or_options_free(options);
+  return ret;
+}
+
 /* 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
@@ -601,6 +617,158 @@ test_descriptor_fetch(void *arg)
   hs_free_all();
 }
 
+static void
+test_auth_key_filename_is_valid(void *arg)
+{
+  (void) arg;
+
+  /* Valid file name. */
+  tt_assert(auth_key_filename_is_valid("a.auth_private"));
+  /* Valid file name with special character. */
+  tt_assert(auth_key_filename_is_valid("a-.auth_private"));
+  /* Invalid extension. */
+  tt_assert(!auth_key_filename_is_valid("a.ath_private"));
+  /* Nothing before the extension. */
+  tt_assert(!auth_key_filename_is_valid(".auth_private"));
+
+ done:
+  ;
+}
+
+static void
+test_parse_auth_file_content(void *arg)
+{
+  hs_client_service_authorization_t *auth = NULL;
+
+  (void) arg;
+
+  /* Valid authorized client. */
+  auth = parse_auth_file_content(
+      "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:"
+      "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq");
+  tt_assert(auth);
+
+  /* Wrong number of fields. */
+  tt_assert(!parse_auth_file_content("a:b"));
+  /* Wrong auth type. */
+  tt_assert(!parse_auth_file_content(
+      "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:x:"
+      "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"));
+  /* Wrong key type. */
+  tt_assert(!parse_auth_file_content(
+      "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:"
+      "x:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"));
+  /* Some malformed string. */
+  tt_assert(!parse_auth_file_content("xx:descriptor:x25519:aa=="));
+
+ done:
+  tor_free(auth);
+}
+
+static char *
+mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out)
+{
+  char *ret = NULL;
+
+  (void) flags;
+  (void) stat_out;
+
+  if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR
+                                              "client1.auth_private"))) {
+    ret = tor_strdup(
+        "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:"
+        "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq");
+    goto done;
+  }
+
+  if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR "dummy.xxx"))) {
+    ret = tor_strdup(
+        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:descriptor:"
+        "x25519:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+    goto done;
+  }
+
+  if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR
+                                              "client2.auth_private"))) {
+    ret = tor_strdup(
+        "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid:descriptor:"
+        "x25519:fdreqzjqso7d2ac7qscrxfl5qfpamdvgy5d6cxejcgzc3hvhurmq");
+    goto done;
+  }
+
+ done:
+  return ret;
+}
+
+static int
+mock_check_private_dir(const char *dirname, cpd_check_t check,
+                       const char *effective_user)
+{
+  (void) dirname;
+  (void) check;
+  (void) effective_user;
+
+  return 0;
+}
+
+static smartlist_t *
+mock_tor_listdir(const char *dirname)
+{
+  smartlist_t *file_list = smartlist_new();
+
+  (void) dirname;
+
+  smartlist_add(file_list, tor_strdup("client1.auth_private"));
+  smartlist_add(file_list, tor_strdup("dummy.xxx"));
+  smartlist_add(file_list, tor_strdup("client2.auth_private"));
+
+  return file_list;
+}
+
+static void
+test_config_client_authorization(void *arg)
+{
+  int ret;
+  char *conf = NULL;
+  ed25519_public_key_t pk1, pk2;
+  digest256map_t *global_map = NULL;
+  char *key_dir = tor_strdup(get_fname("auth_keys"));
+
+  (void) arg;
+
+  MOCK(read_file_to_str, mock_read_file_to_str);
+  MOCK(tor_listdir, mock_tor_listdir);
+  MOCK(check_private_dir, mock_check_private_dir);
+
+#define conf_fmt \
+  "ClientOnionAuthDir %s\n"
+
+  tor_asprintf(&conf, conf_fmt, key_dir);
+  ret = helper_config_client(conf, 0);
+  tor_free(conf);
+  tt_int_op(ret, OP_EQ, 0);
+
+#undef conf_fmt
+
+  global_map = get_hs_client_auths_map();
+  tt_int_op(digest256map_size(global_map), OP_EQ, 2);
+
+  hs_parse_address("4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad",
+                   &pk1, NULL, NULL);
+  hs_parse_address("25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid",
+                   &pk2, NULL, NULL);
+
+  tt_assert(digest256map_get(global_map, pk1.pubkey));
+  tt_assert(digest256map_get(global_map, pk2.pubkey));
+
+ done:
+  tor_free(key_dir);
+  hs_free_all();
+  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 },
@@ -610,5 +778,11 @@ struct testcase_t hs_client_tests[] = {
     TT_FORK, NULL, NULL },
   { "descriptor_fetch", test_descriptor_fetch,
     TT_FORK, NULL, NULL },
+  { "auth_key_filename_is_valid", test_auth_key_filename_is_valid, TT_FORK,
+    NULL, NULL },
+  { "parse_auth_file_content", test_parse_auth_file_content, TT_FORK,
+    NULL, NULL },
+  { "config_client_authorization", test_config_client_authorization,
+    TT_FORK, NULL, NULL },
   END_OF_TESTCASES
 };





More information about the tor-commits mailing list