[tor-commits] [tor/master] test: HS v3 loading client auth keys service side

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


commit 15af47ede07a858bfa0871befa6e1fe76cdd372d
Author: Suphanat Chunhapanya <haxx.pop at gmail.com>
Date:   Sat Aug 18 21:24:26 2018 +0700

    test: HS v3 loading client auth keys service side
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/feature/hs/hs_service.c |   4 +-
 src/feature/hs/hs_service.h |   3 +
 src/test/test_hs_service.c  | 197 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 202 insertions(+), 2 deletions(-)

diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index d61b2809b..8d1ee82ab 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1091,7 +1091,7 @@ load_service_keys(hs_service_t *service)
 
 /* Check if the client file name is valid or not. Return 1 if valid,
  * otherwise return 0. */
-static int
+STATIC int
 client_filename_is_valid(const char *filename)
 {
   int ret = 1;
@@ -1120,7 +1120,7 @@ client_filename_is_valid(const char *filename)
  * The <key-type> can only be "x25519".
  *
  * Return the key on success, return NULL, otherwise. */
-static hs_service_authorized_client_t *
+STATIC hs_service_authorized_client_t *
 parse_authorized_client(const char *client_key_str)
 {
   char *auth_type = NULL;
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index c64eb7763..cab9b41bc 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -349,6 +349,9 @@ STATIC hs_service_descriptor_t *service_desc_find_by_intro(
                                          const hs_service_t *service,
                                          const hs_service_intro_point_t *ip);
 /* Helper functions. */
+STATIC int client_filename_is_valid(const char *filename);
+STATIC hs_service_authorized_client_t *
+parse_authorized_client(const char *client_key_str);
 STATIC void get_objects_from_ident(const hs_ident_circuit_t *ident,
                                    hs_service_t **service,
                                    hs_service_intro_point_t **ip,
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index f8a465629..573c8bc56 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -34,6 +34,7 @@
 #include "core/or/circuitlist.h"
 #include "core/or/circuituse.h"
 #include "lib/crypt_ops/crypto_rand.h"
+#include "lib/fs/dir.h"
 #include "feature/dirauth/dirvote.h"
 #include "feature/nodelist/networkstatus.h"
 #include "feature/nodelist/nodelist.h"
@@ -65,6 +66,13 @@
 /* Trunnel */
 #include "trunnel/hs/cell_establish_intro.h"
 
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 static networkstatus_t mock_ns;
 
 static networkstatus_t *
@@ -303,6 +311,8 @@ test_load_keys(void *arg)
   /* It's in staging? */
   tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
 
+#undef conf_fmt
+
   /* Load the keys for these. After that, the v3 service should be registered
    * in the global map. */
   hs_service_load_all_keys();
@@ -322,6 +332,9 @@ test_load_keys(void *arg)
   tt_int_op(hs_address_is_valid(addr), OP_EQ, 1);
   tt_str_op(addr, OP_EQ, s->onion_address);
 
+  /* Check that the is_client_auth_enabled is not set. */
+  tt_assert(!s->config.is_client_auth_enabled);
+
  done:
   tor_free(hsdir_v2);
   tor_free(hsdir_v3);
@@ -329,6 +342,184 @@ test_load_keys(void *arg)
 }
 
 static void
+test_client_filename_is_valid(void *arg)
+{
+  (void) arg;
+
+  /* Valid file name. */
+  tt_assert(client_filename_is_valid("a.auth"));
+  /* Valid file name with special character. */
+  tt_assert(client_filename_is_valid("a-.auth"));
+  /* Invalid extension. */
+  tt_assert(!client_filename_is_valid("a.ath"));
+  /* Nothing before the extension. */
+  tt_assert(!client_filename_is_valid(".auth"));
+
+ done:
+  ;
+}
+
+static void
+test_parse_authorized_client(void *arg)
+{
+  hs_service_authorized_client_t *client = NULL;
+
+  (void) arg;
+
+  /* Valid authorized client. */
+  client = parse_authorized_client(
+    "descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
+  tt_assert(client);
+
+  /* Wrong number of fields. */
+  tt_assert(!parse_authorized_client("a:b:c:d:e"));
+  /* Wrong auth type. */
+  tt_assert(!parse_authorized_client(
+    "x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
+  /* Wrong key type. */
+  tt_assert(!parse_authorized_client(
+    "descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
+  /* Some malformed string. */
+  tt_assert(!parse_authorized_client("descriptor:x25519:aa=="));
+  tt_assert(!parse_authorized_client("descriptor:"));
+  tt_assert(!parse_authorized_client("descriptor:x25519"));
+  tt_assert(!parse_authorized_client("descriptor:x25519:"));
+  tt_assert(!parse_authorized_client(""));
+
+ done:
+  service_authorized_client_free(client);
+}
+
+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("hs3" PATH_SEPARATOR
+                                  "authorized_clients" PATH_SEPARATOR
+                                  "client1.auth"))) {
+    ret = tor_strdup("descriptor:x25519:"
+                  "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
+    goto done;
+  }
+
+  if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
+                                  "authorized_clients" PATH_SEPARATOR
+                                  "dummy.xxx"))) {
+    ret = tor_strdup("descriptor:x25519:"
+                  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+    goto done;
+  }
+
+  if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
+                                  "authorized_clients" PATH_SEPARATOR
+                                  "client2.auth"))) {
+    ret = tor_strdup("descriptor:x25519:"
+                  "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta");
+    goto done;
+  }
+
+ done:
+  return ret;
+}
+
+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"));
+  smartlist_add(file_list, tor_strdup("dummy.xxx"));
+  smartlist_add(file_list, tor_strdup("client2.auth"));
+
+  return file_list;
+}
+
+static void
+test_load_keys_with_client_auth(void *arg)
+{
+  int ret;
+  char *conf = NULL;
+  smartlist_t *pubkey_b32_list = smartlist_new();
+  char *hsdir_v3 = tor_strdup(get_fname("hs3"));
+  hs_service_t *service;
+
+  (void) arg;
+
+  hs_init();
+  smartlist_add(pubkey_b32_list, tor_strdup(
+                "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
+  smartlist_add(pubkey_b32_list, tor_strdup(
+                "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"));
+
+#define conf_fmt \
+  "HiddenServiceDir %s\n" \
+  "HiddenServiceVersion %d\n" \
+  "HiddenServicePort 65534\n"
+
+  tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
+  ret = helper_config_service(conf);
+  tor_free(conf);
+  tt_int_op(ret, OP_EQ, 0);
+  /* It's in staging? */
+  tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
+
+#undef conf_fmt
+
+  MOCK(read_file_to_str, mock_read_file_to_str);
+  MOCK(tor_listdir, mock_tor_listdir);
+
+  /* Load the keys for these. After that, the v3 service should be registered
+   * in the global map. */
+  hs_service_load_all_keys();
+  tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
+
+  service = get_first_service();
+  tt_assert(service->config.clients);
+  tt_int_op(smartlist_len(service->config.clients), OP_EQ,
+            smartlist_len(pubkey_b32_list));
+
+  /* Test that the is_client_auth_enabled flag is set. */
+  tt_assert(service->config.is_client_auth_enabled);
+
+  /* Test that the keys in clients are correct. */
+  SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) {
+
+    curve25519_public_key_t pubkey;
+    /* This flag will be set if the key is found in clients. */
+    int is_found = 0;
+    base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key),
+                  pubkey_b32, strlen(pubkey_b32));
+
+    SMARTLIST_FOREACH_BEGIN(service->config.clients,
+                            hs_service_authorized_client_t *, client) {
+      if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) {
+        is_found = 1;
+        break;
+      }
+    } SMARTLIST_FOREACH_END(client);
+
+    tt_assert(is_found);
+
+  } SMARTLIST_FOREACH_END(pubkey_b32);
+
+ done:
+  if (pubkey_b32_list) {
+    SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s));
+  }
+  smartlist_free(pubkey_b32_list);
+  tor_free(hsdir_v3);
+  hs_free_all();
+  UNMOCK(read_file_to_str);
+  UNMOCK(tor_listdir);
+}
+
+static void
 test_access_service(void *arg)
 {
   int ret;
@@ -1561,6 +1752,12 @@ struct testcase_t hs_service_tests[] = {
     NULL, NULL },
   { "load_keys", test_load_keys, TT_FORK,
     NULL, NULL },
+  { "client_filename_is_valid", test_client_filename_is_valid, TT_FORK,
+    NULL, NULL },
+  { "parse_authorized_client", test_parse_authorized_client, TT_FORK,
+    NULL, NULL },
+  { "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK,
+    NULL, NULL },
   { "access_service", test_access_service, TT_FORK,
     NULL, NULL },
   { "service_intro_point", test_service_intro_point, TT_FORK,





More information about the tor-commits mailing list