diff options
-rw-r--r-- | src/feature/control/control_cmd.c | 1 | ||||
-rw-r--r-- | src/feature/control/control_hs.c | 117 | ||||
-rw-r--r-- | src/feature/control/control_hs.h | 5 | ||||
-rw-r--r-- | src/feature/hs/hs_client.c | 14 | ||||
-rw-r--r-- | src/feature/hs/hs_client.h | 3 |
5 files changed, 133 insertions, 7 deletions
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index fcd0d8b292..656ddf5ca1 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -2321,6 +2321,7 @@ static const control_cmd_def_t CONTROL_COMMANDS[] = ONE_LINE(del_onion, CMD_FL_WIPE), ONE_LINE(onion_client_auth_add, CMD_FL_WIPE), ONE_LINE(onion_client_auth_remove, 0), + ONE_LINE(onion_client_auth_view, 0), }; /** diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c index 93e66261e0..aa7400c0ce 100644 --- a/src/feature/control/control_hs.c +++ b/src/feature/control/control_hs.c @@ -209,3 +209,120 @@ handle_control_onion_client_auth_remove(control_connection_t *conn, err: return retval; } + +/** Helper: Return a newly allocated string with the encoding of client + * authorization credentials */ +static char * +encode_client_auth_cred_for_control_port( + hs_client_service_authorization_t *cred) +{ + smartlist_t *control_line = smartlist_new(); + char x25519_b64[128]; + char *msg_str = NULL; + + tor_assert(cred); + + if (base64_encode(x25519_b64, sizeof(x25519_b64), + (char *)cred->enc_seckey.secret_key, + sizeof(cred->enc_seckey.secret_key), 0) < 0) { + tor_assert_nonfatal_unreached(); + goto err; + } + + smartlist_add_asprintf(control_line, "CLIENT x25519:%s", x25519_b64); + + if (cred->nickname) { /* nickname is optional */ + smartlist_add_asprintf(control_line, " ClientName=%s", cred->nickname); + } + + if (cred->flags) { /* flags are also optional */ + if (cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) { + smartlist_add_asprintf(control_line, " Flags=Permanent"); + } + } + + /* Join all the components into a single string */ + msg_str = smartlist_join_strings(control_line, "", 0, NULL); + + err: + SMARTLIST_FOREACH(control_line, char *, cp, tor_free(cp)); + smartlist_free(control_line); + + return msg_str; +} + +/** Syntax details for ONION_CLIENT_AUTH_VIEW */ +const control_cmd_syntax_t onion_client_auth_view_syntax = { + .max_args = 1, + .accept_keywords = true, +}; + +/** Called when we get an ONION_CLIENT_AUTH_VIEW command; parse the body, and + * register the new client-side client auth credentials. + * "ONION_CLIENT_AUTH_VIEW" [SP HSAddress] CRLF + */ +int +handle_control_onion_client_auth_view(control_connection_t *conn, + const control_cmd_args_t *args) +{ + int retval = -1; + const char *hsaddress = NULL; + /* We are gonna put all the credential strings into a smartlist, and sort it + before printing, so that we can get a guaranteed order of printing. */ + smartlist_t *creds_str_list = smartlist_new(); + + tor_assert(args); + + int argc = smartlist_len(args->args); + if (argc >= 1) { + hsaddress = smartlist_get(args->args, 0); + if (!hs_address_is_valid(hsaddress)) { + control_printf_endreply(conn, 512, "Invalid v3 addr \"%s\"", hsaddress); + goto err; + } + } + + if (hsaddress) { + control_printf_midreply(conn, 250, "ONION_CLIENT_AUTH_VIEW %s", hsaddress); + } else { + control_printf_midreply(conn, 250, "ONION_CLIENT_AUTH_VIEW"); + } + + /* Create an iterator out of the digest256map */ + digest256map_t *client_auths = get_hs_client_auths_map(); + digest256map_iter_t *itr = digest256map_iter_init(client_auths); + while (!digest256map_iter_done(itr)) { + const uint8_t *service_pubkey; + void *valp; + digest256map_iter_get(itr, &service_pubkey, &valp); + tor_assert(valp); + hs_client_service_authorization_t *cred = valp; + + /* If a specific HS address was requested, only print creds for that one */ + if (hsaddress && strcmp(cred->onion_address, hsaddress)) { + itr = digest256map_iter_next(client_auths, itr); + continue; + } + + char *encoding_str = encode_client_auth_cred_for_control_port(cred); + tor_assert_nonfatal(encoding_str); + smartlist_add(creds_str_list, encoding_str); + + itr = digest256map_iter_next(client_auths, itr); + } + + /* We got everything: Now sort the strings and print them */ + smartlist_sort_strings(creds_str_list); + SMARTLIST_FOREACH_BEGIN(creds_str_list, char *, c) { + control_printf_midreply(conn, 250, "%s", c); + } SMARTLIST_FOREACH_END(c); + + send_control_done(conn); + + retval = 0; + + err: + SMARTLIST_FOREACH(creds_str_list, char *, cp, tor_free(cp)); + smartlist_free(creds_str_list); + return retval; +} diff --git a/src/feature/control/control_hs.h b/src/feature/control/control_hs.h index 067c7dc47f..35ac1b22d4 100644 --- a/src/feature/control/control_hs.h +++ b/src/feature/control/control_hs.h @@ -15,6 +15,7 @@ struct control_cmd_syntax_t; extern const struct control_cmd_syntax_t onion_client_auth_add_syntax; extern const struct control_cmd_syntax_t onion_client_auth_remove_syntax; +extern const struct control_cmd_syntax_t onion_client_auth_view_syntax; int handle_control_onion_client_auth_add(control_connection_t *conn, @@ -24,5 +25,9 @@ int handle_control_onion_client_auth_remove(control_connection_t *conn, const control_cmd_args_t *args); +int +handle_control_onion_client_auth_view(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 bbe7b87a60..9edfd13673 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -1500,6 +1500,13 @@ hs_client_remove_auth_credentials(const char *hsaddress) return REMOVAL_SUCCESS_NOT_FOUND; } +/** Get the HS client auth map. */ +digest256map_t * +get_hs_client_auths_map(void) +{ + return client_auths; +} + /* ========== */ /* Public API */ /* ========== */ @@ -2195,12 +2202,6 @@ hs_client_dir_info_changed(void) #ifdef TOR_UNIT_TESTS -STATIC digest256map_t * -get_hs_client_auths_map(void) -{ - return client_auths; -} - STATIC void set_hs_client_auths_map(digest256map_t *map) { @@ -2208,3 +2209,4 @@ set_hs_client_auths_map(digest256map_t *map) } #endif /* defined(TOR_UNIT_TESTS) */ + diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index 459c19db58..b0122aa14d 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -76,6 +76,8 @@ 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); +digest256map_t *get_hs_client_auths_map(void); + #define client_service_authorization_free(auth) \ FREE_AND_NULL(hs_client_service_authorization_t, \ client_service_authorization_free_, (auth)) @@ -156,7 +158,6 @@ STATIC void retry_all_socks_conn_waiting_for_desc(void); #ifdef TOR_UNIT_TESTS -STATIC digest256map_t *get_hs_client_auths_map(void); STATIC void set_hs_client_auths_map(digest256map_t *map); #endif /* defined(TOR_UNIT_TESTS) */ |