control-port: Implement ONION_CLIENT_AUTH_VIEW.

This commit is contained in:
George Kadianakis 2019-06-03 14:25:38 +03:00
parent ee4b2287c6
commit db6a48b6bf
5 changed files with 133 additions and 7 deletions

View File

@ -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),
};
/**

View File

@ -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;
}

View File

@ -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

View File

@ -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) */

View File

@ -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) */