commit 8330b4dc2a18befa0eda8e48abb7f6e151596562 Author: George Kadianakis desnacked@riseup.net Date: Mon Jun 3 15:43:54 2019 +0300
control-port: Implement ONION_CLIENT_AUTH_REMOVE. --- src/feature/control/control_cmd.c | 1 + src/feature/control/control_hs.c | 50 +++++++++++++++++++++++++++++++++++++++ src/feature/control/control_hs.h | 6 ++++- src/feature/hs/hs_client.c | 25 ++++++++++++++++++++ src/feature/hs/hs_client.h | 13 ++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index 3c16722e1..fcd0d8b29 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -2320,6 +2320,7 @@ static const control_cmd_def_t CONTROL_COMMANDS[] = ONE_LINE(add_onion, CMD_FL_WIPE), ONE_LINE(del_onion, CMD_FL_WIPE), ONE_LINE(onion_client_auth_add, CMD_FL_WIPE), + ONE_LINE(onion_client_auth_remove, 0), };
/** diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c index 5db8a0f00..93e66261e 100644 --- a/src/feature/control/control_hs.c +++ b/src/feature/control/control_hs.c @@ -159,3 +159,53 @@ handle_control_onion_client_auth_add(control_connection_t *conn, smartlist_free(flags); return retval; } + +/** Syntax details for ONION_CLIENT_AUTH_REMOVE */ +const control_cmd_syntax_t onion_client_auth_remove_syntax = { + .max_args = 1, + .accept_keywords = true, +}; + +/** Called when we get an ONION_CLIENT_AUTH_REMOVE command; parse the body, and + * register the new client-side client auth credentials. + * "ONION_CLIENT_AUTH_REMOVE" SP HSAddress + */ +int +handle_control_onion_client_auth_remove(control_connection_t *conn, + const control_cmd_args_t *args) +{ + int retval = -1; + + tor_assert(args); + + int argc = smartlist_len(args->args); + if (argc < 1) { + control_printf_endreply(conn, 512, + "Incomplete ONION_CLIENT_AUTH_REMOVE command"); + goto err; + } + + const char *hsaddress = smartlist_get(args->args, 0); + if (!hs_address_is_valid(hsaddress)) { + control_printf_endreply(conn, 512, "Invalid v3 address "%s"",hsaddress); + goto err; + } + + hs_client_removal_auth_status_t removal_status; + removal_status = hs_client_remove_auth_credentials(hsaddress); + if (BUG(removal_status == REMOVAL_BAD_ADDRESS)) { + /* It's a bug because the service addr has already been validated above */ + control_printf_endreply(conn, 512, "Invalid v3 address "%s"",hsaddress); + } else if (removal_status == REMOVAL_SUCCESS_NOT_FOUND) { + control_printf_endreply(conn, 251, "No credentials for "%s"",hsaddress); + } else if (removal_status == REMOVAL_SUCCESS) { + control_printf_endreply(conn, 250, "OK"); + } else { + tor_assert_nonfatal_unreached(); + } + + retval = 0; + + err: + return retval; +} diff --git a/src/feature/control/control_hs.h b/src/feature/control/control_hs.h index 1fcd7de36..067c7dc47 100644 --- a/src/feature/control/control_hs.h +++ b/src/feature/control/control_hs.h @@ -13,12 +13,16 @@
struct control_cmd_syntax_t;
-extern const char *onion_client_auth_add_keywords[]; extern const struct control_cmd_syntax_t onion_client_auth_add_syntax; +extern const struct control_cmd_syntax_t onion_client_auth_remove_syntax;
int handle_control_onion_client_auth_add(control_connection_t *conn, const control_cmd_args_t *args);
+int +handle_control_onion_client_auth_remove(control_connection_t *conn, + const control_cmd_args_t *args); + #endif
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index c854737be..bbe7b87a6 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -1475,6 +1475,31 @@ hs_client_register_auth_credentials(hs_client_service_authorization_t *creds) return REGISTER_SUCCESS; }
+/** Remove client auth credentials for the service <b>hs_address</b>. */ +hs_client_removal_auth_status_t +hs_client_remove_auth_credentials(const char *hsaddress) +{ + ed25519_public_key_t service_identity_pk; + + if (!client_auths) { + return REMOVAL_SUCCESS_NOT_FOUND; + } + + if (hs_parse_address(hsaddress, &service_identity_pk, NULL, NULL) < 0) { + return REMOVAL_BAD_ADDRESS; + } + + hs_client_service_authorization_t *cred = NULL; + cred = digest256map_remove(client_auths, service_identity_pk.pubkey); + /* digestmap_remove() returns the previously stored data if there were any */ + if (cred) { + client_service_authorization_free(cred); + return REMOVAL_SUCCESS; + } + + return REMOVAL_SUCCESS_NOT_FOUND; +} + /* ========== */ /* Public API */ /* ========== */ diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index ea726e237..459c19db5 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -41,6 +41,16 @@ typedef enum { REGISTER_FAIL_BAD_ADDRESS, } hs_client_register_auth_status_t;
+/* Status code of client auth credential removal */ +typedef enum { + /* We successfuly removed these credentials */ + REMOVAL_SUCCESS, + /* No need to remove those credentials, because they were not there. */ + REMOVAL_SUCCESS_NOT_FOUND, + /* We failed to register these credentials, because of a bad HS address. */ + REMOVAL_BAD_ADDRESS, +} hs_client_removal_auth_status_t; + /** Flag to set when a client auth is permanent (saved on disk). */ #define CLIENT_AUTH_FLAG_IS_PERMANENT (1<<0)
@@ -63,6 +73,9 @@ typedef struct hs_client_service_authorization_t { hs_client_register_auth_status_t hs_client_register_auth_credentials(hs_client_service_authorization_t *creds);
+hs_client_removal_auth_status_t +hs_client_remove_auth_credentials(const char *hsaddress); + #define client_service_authorization_free(auth) \ FREE_AND_NULL(hs_client_service_authorization_t, \ client_service_authorization_free_, (auth))