[tor-commits] [tor/master] hsv3: Implement permanent storage of auth credentials.
dgoulet at torproject.org
dgoulet at torproject.org
Tue Dec 3 14:28:38 UTC 2019
commit 70572b9abd660448777ebbee3dc71d7d70b37d8c
Author: George Kadianakis <desnacked at riseup.net>
Date: Mon Nov 25 15:55:12 2019 +0200
hsv3: Implement permanent storage of auth credentials.
- See hs_client_register_auth_credentials() for the entry point.
- Also set the permanent flag for credentials we read from the filesystem.
- Also add some missing documentation.
---
src/feature/control/control_hs.c | 4 ++
src/feature/hs/hs_client.c | 95 +++++++++++++++++++++++++++++++++++++++-
src/feature/hs/hs_client.h | 2 +
3 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c
index 4c1d16a8c..97938211d 100644
--- a/src/feature/control/control_hs.c
+++ b/src/feature/control/control_hs.c
@@ -145,6 +145,10 @@ handle_control_onion_client_auth_add(control_connection_t *conn,
/* It's a bug because the service addr has already been validated above */
control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"", hsaddress);
break;
+ case REGISTER_FAIL_PERMANENT_STORAGE:
+ control_printf_endreply(conn, 553, "Unable to store creds for \"%s\"",
+ hsaddress);
+ break;
case REGISTER_SUCCESS_ALREADY_EXISTS:
control_printf_endreply(conn, 251,"Client for onion existed and replaced");
break;
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 787b29b57..3c681dd85 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1445,6 +1445,80 @@ client_dir_fetch_unexpected(dir_connection_t *dir_conn, const char *reason,
NULL);
}
+/** Get the full filename for storing the client auth credentials for the
+ * service in <b>onion_address</b>. The base directory is <b>dir</b>.
+ * This function never returns NULL. */
+static char *
+get_client_auth_creds_filename(const char *onion_address,
+ const char *dir)
+{
+ char *full_fname = NULL;
+ char *fname;
+
+ tor_asprintf(&fname, "%s.auth_private", onion_address);
+ full_fname = hs_path_from_filename(dir, fname);
+ tor_free(fname);
+
+ return full_fname;
+}
+
+/** Permanently store the credentials in <b>creds</b> to disk.
+ *
+ * Return -1 if there was an error while storing the credentials, otherwise
+ * return 0.
+ */
+static int
+store_permanent_client_auth_credentials(
+ const hs_client_service_authorization_t *creds)
+{
+ const or_options_t *options = get_options();
+ char *full_fname = NULL;
+ char *file_contents = NULL;
+ char priv_key_b32[BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)+1];
+ int retval = -1;
+
+ tor_assert(creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
+
+ /* We need ClientOnionAuthDir to be set, otherwise we can't proceed */
+ if (!options->ClientOnionAuthDir) {
+ log_warn(LD_GENERAL, "Can't register permanent client auth credentials "
+ "for %s without ClientOnionAuthDir option. Discarding.",
+ creds->onion_address);
+ goto err;
+ }
+
+ /* Make sure the directory exists and is private enough. */
+ if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
+ goto err;
+ }
+
+ /* Get filename that we should store the credentials */
+ full_fname = get_client_auth_creds_filename(creds->onion_address,
+ options->ClientOnionAuthDir);
+
+ /* Encode client private key */
+ base32_encode(priv_key_b32, sizeof(priv_key_b32),
+ (char*)creds->enc_seckey.secret_key,
+ sizeof(creds->enc_seckey.secret_key));
+
+ /* Get the full file contents and write it to disk! */
+ tor_asprintf(&file_contents, "%s:descriptor:x25519:%s",
+ creds->onion_address, priv_key_b32);
+ if (write_str_to_file(full_fname, file_contents, 0) < 0) {
+ log_warn(LD_GENERAL, "Failed to write client auth creds file for %s!",
+ creds->onion_address);
+ goto err;
+ }
+
+ retval = 0;
+
+ err:
+ tor_free(file_contents);
+ tor_free(full_fname);
+
+ return retval;
+}
+
/** Register the credential <b>creds</b> as part of the client auth subsystem.
*
* Takes ownership of <b>creds</b>.
@@ -1468,6 +1542,15 @@ hs_client_register_auth_credentials(hs_client_service_authorization_t *creds)
return REGISTER_FAIL_BAD_ADDRESS;
}
+ /* If we reach this point, the credentials will be stored one way or another:
+ * Make them permanent if the user asked us to. */
+ if (creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ if (store_permanent_client_auth_credentials(creds) < 0) {
+ client_service_authorization_free(creds);
+ return REGISTER_FAIL_PERMANENT_STORAGE;
+ }
+ }
+
old_creds = digest256map_get(client_auths, service_identity_pk.pubkey);
if (old_creds) {
digest256map_remove(client_auths, service_identity_pk.pubkey);
@@ -1795,6 +1878,13 @@ auth_key_filename_is_valid(const char *filename)
return ret;
}
+/** Parse the client auth credentials off a string in <b>client_key_str</b>
+ * based on the file format documented in the "Client side configuration"
+ * section of rend-spec-v3.txt.
+ *
+ * Return NULL if there was an error, otherwise return a newly allocated
+ * hs_client_service_authorization_t structure.
+ */
STATIC hs_client_service_authorization_t *
parse_auth_file_content(const char *client_key_str)
{
@@ -1825,7 +1915,7 @@ parse_auth_file_content(const char *client_key_str)
goto err;
}
- if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)) {
+ if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_SECKEY_LEN)) {
log_warn(LD_REND, "Client authorization encoded base32 private key "
"length is invalid: %s", seckey_b32);
goto err;
@@ -1842,6 +1932,9 @@ parse_auth_file_content(const char *client_key_str)
}
strncpy(auth->onion_address, onion_address, HS_SERVICE_ADDR_LEN_BASE32);
+ /* We are reading this from the disk, so set the permanent flag anyway. */
+ auth->flags |= CLIENT_AUTH_FLAG_IS_PERMANENT;
+
/* Success. */
goto done;
diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h
index 04827ea92..75a911107 100644
--- a/src/feature/hs/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -43,6 +43,8 @@ typedef enum {
REGISTER_SUCCESS_AND_DECRYPTED,
/* We failed to register these credentials, because of a bad HS address. */
REGISTER_FAIL_BAD_ADDRESS,
+ /* We failed to register these credentials, because of a bad HS address. */
+ REGISTER_FAIL_PERMANENT_STORAGE,
} hs_client_register_auth_status_t;
/* Status code of client auth credential removal */
More information about the tor-commits
mailing list