mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 14:51:11 +01:00
Split command-handling and authentication from control.c
This commit is contained in:
parent
4754e9058b
commit
2917ecaa97
16 changed files with 2965 additions and 2856 deletions
|
@ -79,8 +79,8 @@ problem function-size /src/core/mainloop/connection.c:connection_handle_write_im
|
|||
problem function-size /src/core/mainloop/connection.c:assert_connection_ok() 143
|
||||
problem function-size /src/app/config/confparse.c:config_assign_value() 205
|
||||
problem function-size /src/app/config/confparse.c:config_get_assigned_option() 129
|
||||
problem file-size /src/app/config/config.c 8489
|
||||
problem include-count /src/app/config/config.c 85
|
||||
problem file-size /src/app/config/config.c 8490
|
||||
problem include-count /src/app/config/config.c 86
|
||||
problem function-size /src/app/config/config.c:options_act_reversible() 296
|
||||
problem function-size /src/app/config/config.c:options_act() 588
|
||||
problem function-size /src/app/config/config.c:resolve_my_address() 192
|
||||
|
@ -96,7 +96,7 @@ problem function-size /src/app/config/config.c:parse_port_config() 452
|
|||
problem function-size /src/app/config/config.c:parse_ports() 170
|
||||
problem function-size /src/app/config/config.c:getinfo_helper_config() 116
|
||||
problem function-size /src/app/main/ntmain.c:nt_service_install() 125
|
||||
problem include-count /src/app/main/main.c 84
|
||||
problem include-count /src/app/main/main.c 85
|
||||
problem function-size /src/app/main/main.c:dumpstats() 102
|
||||
problem function-size /src/app/main/main.c:tor_init() 136
|
||||
problem function-size /src/app/main/main.c:sandbox_init_filter() 291
|
||||
|
@ -111,19 +111,20 @@ problem function-size /src/feature/dircommon/consdiff.c:gen_ed_diff() 204
|
|||
problem function-size /src/feature/dircommon/consdiff.c:apply_ed_diff() 159
|
||||
problem file-size /src/feature/control/control.c 7592
|
||||
problem include-count /src/feature/control/control.c 90
|
||||
problem function-size /src/feature/control/control.c:handle_control_authenticate() 188
|
||||
problem function-size /src/feature/control/control_auth.c:handle_control_authenticate() 188
|
||||
problem function-size /src/feature/control/control_auth.c:handle_control_authchallenge() 115
|
||||
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_misc() 109
|
||||
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 304
|
||||
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 236
|
||||
problem function-size /src/feature/control/control.c:handle_control_extendcircuit() 151
|
||||
problem function-size /src/feature/control/control.c:handle_control_authchallenge() 115
|
||||
problem function-size /src/feature/control/control.c:handle_control_hsfetch() 114
|
||||
problem function-size /src/feature/control/control.c:handle_control_hspost() 117
|
||||
problem function-size /src/feature/control/control.c:handle_control_add_onion() 293
|
||||
problem function-size /src/feature/control/control.c:add_onion_helper_keyarg() 125
|
||||
problem function-size /src/feature/control/control_cmd.c:handle_control_command() 104
|
||||
problem function-size /src/feature/control/control_cmd.c:handle_control_extendcircuit() 151
|
||||
problem function-size /src/feature/control/control_cmd.c:handle_control_hsfetch() 114
|
||||
problem function-size /src/feature/control/control_cmd.c:handle_control_hspost() 117
|
||||
problem function-size /src/feature/control/control_cmd.c:handle_control_add_onion() 293
|
||||
problem function-size /src/feature/control/control_cmd.c:add_onion_helper_keyarg() 125
|
||||
problem function-size /src/feature/control/control.c:connection_control_process_inbuf() 239
|
||||
problem function-size /src/feature/control/control_events.c:control_event_stream_status() 119
|
||||
problem include-count /src/feature/control/control_getinfo.c 51
|
||||
problem include-count /src/feature/control/control_getinfo.c 52
|
||||
problem function-size /src/feature/stats/rephist.c:rep_hist_load_mtbf_data() 185
|
||||
problem function-size /src/feature/stats/rephist.c:rep_hist_format_exit_stats() 148
|
||||
problem function-size /src/feature/dircache/consdiffmgr.c:consdiffmgr_cleanup() 115
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/client/transports.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/control/control_auth.h"
|
||||
#include "feature/control/control_events.h"
|
||||
#include "feature/dirauth/bwauth.h"
|
||||
#include "feature/dirauth/guardfraction.h"
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/client/transports.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/control/control_auth.h"
|
||||
#include "feature/control/control_events.h"
|
||||
#include "feature/dirauth/bwauth.h"
|
||||
#include "feature/dirauth/keypin.h"
|
||||
|
|
|
@ -70,7 +70,9 @@ LIBTOR_APP_A_SOURCES = \
|
|||
src/feature/control/btrack_orconn_cevent.c \
|
||||
src/feature/control/btrack_orconn_maps.c \
|
||||
src/feature/control/control.c \
|
||||
src/feature/control/control_auth.c \
|
||||
src/feature/control/control_bootstrap.c \
|
||||
src/feature/control/control_cmd.c \
|
||||
src/feature/control/control_events.c \
|
||||
src/feature/control/control_fmt.c \
|
||||
src/feature/control/control_getinfo.c \
|
||||
|
@ -290,6 +292,8 @@ noinst_HEADERS += \
|
|||
src/feature/control/btrack_orconn_maps.h \
|
||||
src/feature/control/btrack_sys.h \
|
||||
src/feature/control/control.h \
|
||||
src/feature/control/control_auth.h \
|
||||
src/feature/control/control_cmd.h \
|
||||
src/feature/control/control_connection_st.h \
|
||||
src/feature/control/control_events.h \
|
||||
src/feature/control/control_fmt.h \
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,10 +42,6 @@ void connection_control_closed(control_connection_t *conn);
|
|||
|
||||
int connection_control_process_inbuf(control_connection_t *conn);
|
||||
|
||||
int init_control_cookie_authentication(int enabled);
|
||||
char *get_controller_cookie_file_name(void);
|
||||
struct config_line_t;
|
||||
smartlist_t *decode_hashed_passwords(struct config_line_t *passwords);
|
||||
void disable_control_logging(void);
|
||||
void enable_control_logging(void);
|
||||
|
||||
|
@ -55,40 +51,14 @@ const char *rend_auth_type_to_string(rend_auth_type_t auth_type);
|
|||
MOCK_DECL(const char *, node_describe_longname_by_id,(const char *id_digest));
|
||||
void control_free_all(void);
|
||||
|
||||
#ifdef CONTROL_PRIVATE
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
|
||||
/* ADD_ONION secret key to create an ephemeral service. The command supports
|
||||
* multiple versions so this union stores the key and passes it to the HS
|
||||
* subsystem depending on the requested version. */
|
||||
typedef union add_onion_secret_key_t {
|
||||
/* Hidden service v2 secret key. */
|
||||
crypto_pk_t *v2;
|
||||
/* Hidden service v3 secret key. */
|
||||
ed25519_secret_key_t *v3;
|
||||
} add_onion_secret_key_t;
|
||||
|
||||
STATIC int add_onion_helper_keyarg(const char *arg, int discard_pk,
|
||||
const char **key_new_alg_out,
|
||||
char **key_new_blob_out,
|
||||
add_onion_secret_key_t *decoded_key,
|
||||
int *hs_version, char **err_msg_out);
|
||||
|
||||
STATIC rend_authorized_client_t *
|
||||
add_onion_helper_clientauth(const char *arg, int *created, char **err_msg_out);
|
||||
|
||||
#endif /* defined(CONTROL_PRIVATE) */
|
||||
|
||||
#ifdef CONTROL_MODULE_PRIVATE
|
||||
struct signal_name_t {
|
||||
int sig;
|
||||
const char *signal_name;
|
||||
};
|
||||
extern const struct signal_name_t signal_table[];
|
||||
|
||||
int get_cached_network_liveness(void);
|
||||
void set_cached_network_liveness(int liveness);
|
||||
smartlist_t * get_detached_onion_services(void);
|
||||
#endif /* defined(CONTROL_MODULE_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONTROL_H) */
|
||||
|
|
439
src/feature/control/control_auth.c
Normal file
439
src/feature/control/control_auth.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2019, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file control_auth.c
|
||||
* \brief Authentication for Tor's control-socket interface.
|
||||
**/
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/control/control_auth.h"
|
||||
#include "feature/control/control_connection_st.h"
|
||||
#include "feature/control/control_fmt.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "lib/crypt_ops/crypto_util.h"
|
||||
#include "lib/encoding/confline.h"
|
||||
|
||||
#include "lib/crypt_ops/crypto_s2k.h"
|
||||
|
||||
/** If we're using cookie-type authentication, how long should our cookies be?
|
||||
*/
|
||||
#define AUTHENTICATION_COOKIE_LEN 32
|
||||
|
||||
/** If true, we've set authentication_cookie to a secret code and
|
||||
* stored it to disk. */
|
||||
static int authentication_cookie_is_set = 0;
|
||||
/** If authentication_cookie_is_set, a secret cookie that we've stored to disk
|
||||
* and which we're using to authenticate controllers. (If the controller can
|
||||
* read it off disk, it has permission to connect.) */
|
||||
static uint8_t *authentication_cookie = NULL;
|
||||
|
||||
#define SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT \
|
||||
"Tor safe cookie authentication server-to-controller hash"
|
||||
#define SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT \
|
||||
"Tor safe cookie authentication controller-to-server hash"
|
||||
#define SAFECOOKIE_SERVER_NONCE_LEN DIGEST256_LEN
|
||||
|
||||
/** Helper: Return a newly allocated string containing a path to the
|
||||
* file where we store our authentication cookie. */
|
||||
char *
|
||||
get_controller_cookie_file_name(void)
|
||||
{
|
||||
const or_options_t *options = get_options();
|
||||
if (options->CookieAuthFile && strlen(options->CookieAuthFile)) {
|
||||
return tor_strdup(options->CookieAuthFile);
|
||||
} else {
|
||||
return get_datadir_fname("control_auth_cookie");
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the cookie-based authentication system of the
|
||||
* ControlPort. If <b>enabled</b> is 0, then disable the cookie
|
||||
* authentication system. */
|
||||
int
|
||||
init_control_cookie_authentication(int enabled)
|
||||
{
|
||||
char *fname = NULL;
|
||||
int retval;
|
||||
|
||||
if (!enabled) {
|
||||
authentication_cookie_is_set = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fname = get_controller_cookie_file_name();
|
||||
retval = init_cookie_authentication(fname, "", /* no header */
|
||||
AUTHENTICATION_COOKIE_LEN,
|
||||
get_options()->CookieAuthFileGroupReadable,
|
||||
&authentication_cookie,
|
||||
&authentication_cookie_is_set);
|
||||
tor_free(fname);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Decode the hashed, base64'd passwords stored in <b>passwords</b>.
|
||||
* Return a smartlist of acceptable passwords (unterminated strings of
|
||||
* length S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on
|
||||
* failure.
|
||||
*/
|
||||
smartlist_t *
|
||||
decode_hashed_passwords(config_line_t *passwords)
|
||||
{
|
||||
char decoded[64];
|
||||
config_line_t *cl;
|
||||
smartlist_t *sl = smartlist_new();
|
||||
|
||||
tor_assert(passwords);
|
||||
|
||||
for (cl = passwords; cl; cl = cl->next) {
|
||||
const char *hashed = cl->value;
|
||||
|
||||
if (!strcmpstart(hashed, "16:")) {
|
||||
if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))
|
||||
!= S2K_RFC2440_SPECIFIER_LEN + DIGEST_LEN
|
||||
|| strlen(hashed+3) != (S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN)*2) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
|
||||
!= S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
smartlist_add(sl,
|
||||
tor_memdup(decoded, S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN));
|
||||
}
|
||||
|
||||
return sl;
|
||||
|
||||
err:
|
||||
SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
|
||||
smartlist_free(sl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Called when we get an AUTHCHALLENGE command. */
|
||||
int
|
||||
handle_control_authchallenge(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
const char *cp = body;
|
||||
char *client_nonce;
|
||||
size_t client_nonce_len;
|
||||
char server_hash[DIGEST256_LEN];
|
||||
char server_hash_encoded[HEX_DIGEST256_LEN+1];
|
||||
char server_nonce[SAFECOOKIE_SERVER_NONCE_LEN];
|
||||
char server_nonce_encoded[(2*SAFECOOKIE_SERVER_NONCE_LEN) + 1];
|
||||
|
||||
cp += strspn(cp, " \t\n\r");
|
||||
if (!strcasecmpstart(cp, "SAFECOOKIE")) {
|
||||
cp += strlen("SAFECOOKIE");
|
||||
} else {
|
||||
connection_write_str_to_buf("513 AUTHCHALLENGE only supports SAFECOOKIE "
|
||||
"authentication\r\n", conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!authentication_cookie_is_set) {
|
||||
connection_write_str_to_buf("515 Cookie authentication is disabled\r\n",
|
||||
conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp += strspn(cp, " \t\n\r");
|
||||
if (*cp == '"') {
|
||||
const char *newcp =
|
||||
decode_escaped_string(cp, len - (cp - body),
|
||||
&client_nonce, &client_nonce_len);
|
||||
if (newcp == NULL) {
|
||||
connection_write_str_to_buf("513 Invalid quoted client nonce\r\n",
|
||||
conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return -1;
|
||||
}
|
||||
cp = newcp;
|
||||
} else {
|
||||
size_t client_nonce_encoded_len = strspn(cp, "0123456789ABCDEFabcdef");
|
||||
|
||||
client_nonce_len = client_nonce_encoded_len / 2;
|
||||
client_nonce = tor_malloc_zero(client_nonce_len);
|
||||
|
||||
if (base16_decode(client_nonce, client_nonce_len,
|
||||
cp, client_nonce_encoded_len)
|
||||
!= (int) client_nonce_len) {
|
||||
connection_write_str_to_buf("513 Invalid base16 client nonce\r\n",
|
||||
conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
tor_free(client_nonce);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp += client_nonce_encoded_len;
|
||||
}
|
||||
|
||||
cp += strspn(cp, " \t\n\r");
|
||||
if (*cp != '\0' ||
|
||||
cp != body + len) {
|
||||
connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command\r\n",
|
||||
conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
tor_free(client_nonce);
|
||||
return -1;
|
||||
}
|
||||
crypto_rand(server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
|
||||
|
||||
/* Now compute and send the server-to-controller response, and the
|
||||
* server's nonce. */
|
||||
tor_assert(authentication_cookie != NULL);
|
||||
|
||||
{
|
||||
size_t tmp_len = (AUTHENTICATION_COOKIE_LEN +
|
||||
client_nonce_len +
|
||||
SAFECOOKIE_SERVER_NONCE_LEN);
|
||||
char *tmp = tor_malloc_zero(tmp_len);
|
||||
char *client_hash = tor_malloc_zero(DIGEST256_LEN);
|
||||
memcpy(tmp, authentication_cookie, AUTHENTICATION_COOKIE_LEN);
|
||||
memcpy(tmp + AUTHENTICATION_COOKIE_LEN, client_nonce, client_nonce_len);
|
||||
memcpy(tmp + AUTHENTICATION_COOKIE_LEN + client_nonce_len,
|
||||
server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
|
||||
|
||||
crypto_hmac_sha256(server_hash,
|
||||
SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT,
|
||||
strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT),
|
||||
tmp,
|
||||
tmp_len);
|
||||
|
||||
crypto_hmac_sha256(client_hash,
|
||||
SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT,
|
||||
strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT),
|
||||
tmp,
|
||||
tmp_len);
|
||||
|
||||
conn->safecookie_client_hash = client_hash;
|
||||
|
||||
tor_free(tmp);
|
||||
}
|
||||
|
||||
base16_encode(server_hash_encoded, sizeof(server_hash_encoded),
|
||||
server_hash, sizeof(server_hash));
|
||||
base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
|
||||
server_nonce, sizeof(server_nonce));
|
||||
|
||||
connection_printf_to_buf(conn,
|
||||
"250 AUTHCHALLENGE SERVERHASH=%s "
|
||||
"SERVERNONCE=%s\r\n",
|
||||
server_hash_encoded,
|
||||
server_nonce_encoded);
|
||||
|
||||
tor_free(client_nonce);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Called when we get an AUTHENTICATE message. Check whether the
|
||||
* authentication is valid, and if so, update the connection's state to
|
||||
* OPEN. Reply with DONE or ERROR.
|
||||
*/
|
||||
int
|
||||
handle_control_authenticate(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
int used_quoted_string = 0;
|
||||
const or_options_t *options = get_options();
|
||||
const char *errstr = "Unknown error";
|
||||
char *password;
|
||||
size_t password_len;
|
||||
const char *cp;
|
||||
int i;
|
||||
int bad_cookie=0, bad_password=0;
|
||||
smartlist_t *sl = NULL;
|
||||
|
||||
if (!len) {
|
||||
password = tor_strdup("");
|
||||
password_len = 0;
|
||||
} else if (TOR_ISXDIGIT(body[0])) {
|
||||
cp = body;
|
||||
while (TOR_ISXDIGIT(*cp))
|
||||
++cp;
|
||||
i = (int)(cp - body);
|
||||
tor_assert(i>0);
|
||||
password_len = i/2;
|
||||
password = tor_malloc(password_len + 1);
|
||||
if (base16_decode(password, password_len+1, body, i)
|
||||
!= (int) password_len) {
|
||||
connection_write_str_to_buf(
|
||||
"551 Invalid hexadecimal encoding. Maybe you tried a plain text "
|
||||
"password? If so, the standard requires that you put it in "
|
||||
"double quotes.\r\n", conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
tor_free(password);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!decode_escaped_string(body, len, &password, &password_len)) {
|
||||
connection_write_str_to_buf("551 Invalid quoted string. You need "
|
||||
"to put the password in double quotes.\r\n", conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
used_quoted_string = 1;
|
||||
}
|
||||
|
||||
if (conn->safecookie_client_hash != NULL) {
|
||||
/* The controller has chosen safe cookie authentication; the only
|
||||
* acceptable authentication value is the controller-to-server
|
||||
* response. */
|
||||
|
||||
tor_assert(authentication_cookie_is_set);
|
||||
|
||||
if (password_len != DIGEST256_LEN) {
|
||||
log_warn(LD_CONTROL,
|
||||
"Got safe cookie authentication response with wrong length "
|
||||
"(%d)", (int)password_len);
|
||||
errstr = "Wrong length for safe cookie response.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tor_memneq(conn->safecookie_client_hash, password, DIGEST256_LEN)) {
|
||||
log_warn(LD_CONTROL,
|
||||
"Got incorrect safe cookie authentication response");
|
||||
errstr = "Safe cookie response did not match expected value.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
tor_free(conn->safecookie_client_hash);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (!options->CookieAuthentication && !options->HashedControlPassword &&
|
||||
!options->HashedControlSessionPassword) {
|
||||
/* if Tor doesn't demand any stronger authentication, then
|
||||
* the controller can get in with anything. */
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (options->CookieAuthentication) {
|
||||
int also_password = options->HashedControlPassword != NULL ||
|
||||
options->HashedControlSessionPassword != NULL;
|
||||
if (password_len != AUTHENTICATION_COOKIE_LEN) {
|
||||
if (!also_password) {
|
||||
log_warn(LD_CONTROL, "Got authentication cookie with wrong length "
|
||||
"(%d)", (int)password_len);
|
||||
errstr = "Wrong length on authentication cookie.";
|
||||
goto err;
|
||||
}
|
||||
bad_cookie = 1;
|
||||
} else if (tor_memneq(authentication_cookie, password, password_len)) {
|
||||
if (!also_password) {
|
||||
log_warn(LD_CONTROL, "Got mismatched authentication cookie");
|
||||
errstr = "Authentication cookie did not match expected value.";
|
||||
goto err;
|
||||
}
|
||||
bad_cookie = 1;
|
||||
} else {
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (options->HashedControlPassword ||
|
||||
options->HashedControlSessionPassword) {
|
||||
int bad = 0;
|
||||
smartlist_t *sl_tmp;
|
||||
char received[DIGEST_LEN];
|
||||
int also_cookie = options->CookieAuthentication;
|
||||
sl = smartlist_new();
|
||||
if (options->HashedControlPassword) {
|
||||
sl_tmp = decode_hashed_passwords(options->HashedControlPassword);
|
||||
if (!sl_tmp)
|
||||
bad = 1;
|
||||
else {
|
||||
smartlist_add_all(sl, sl_tmp);
|
||||
smartlist_free(sl_tmp);
|
||||
}
|
||||
}
|
||||
if (options->HashedControlSessionPassword) {
|
||||
sl_tmp = decode_hashed_passwords(options->HashedControlSessionPassword);
|
||||
if (!sl_tmp)
|
||||
bad = 1;
|
||||
else {
|
||||
smartlist_add_all(sl, sl_tmp);
|
||||
smartlist_free(sl_tmp);
|
||||
}
|
||||
}
|
||||
if (bad) {
|
||||
if (!also_cookie) {
|
||||
log_warn(LD_BUG,
|
||||
"Couldn't decode HashedControlPassword: invalid base16");
|
||||
errstr="Couldn't decode HashedControlPassword value in configuration.";
|
||||
goto err;
|
||||
}
|
||||
bad_password = 1;
|
||||
SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
|
||||
smartlist_free(sl);
|
||||
sl = NULL;
|
||||
} else {
|
||||
SMARTLIST_FOREACH(sl, char *, expected,
|
||||
{
|
||||
secret_to_key_rfc2440(received,DIGEST_LEN,
|
||||
password,password_len,expected);
|
||||
if (tor_memeq(expected + S2K_RFC2440_SPECIFIER_LEN,
|
||||
received, DIGEST_LEN))
|
||||
goto ok;
|
||||
});
|
||||
SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
|
||||
smartlist_free(sl);
|
||||
sl = NULL;
|
||||
|
||||
if (used_quoted_string)
|
||||
errstr = "Password did not match HashedControlPassword value from "
|
||||
"configuration";
|
||||
else
|
||||
errstr = "Password did not match HashedControlPassword value from "
|
||||
"configuration. Maybe you tried a plain text password? "
|
||||
"If so, the standard requires that you put it in double quotes.";
|
||||
bad_password = 1;
|
||||
if (!also_cookie)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/** We only get here if both kinds of authentication failed. */
|
||||
tor_assert(bad_password && bad_cookie);
|
||||
log_warn(LD_CONTROL, "Bad password or authentication cookie on controller.");
|
||||
errstr = "Password did not match HashedControlPassword *or* authentication "
|
||||
"cookie.";
|
||||
|
||||
err:
|
||||
tor_free(password);
|
||||
connection_printf_to_buf(conn, "515 Authentication failed: %s\r\n", errstr);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
if (sl) { /* clean up */
|
||||
SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
|
||||
smartlist_free(sl);
|
||||
}
|
||||
return 0;
|
||||
ok:
|
||||
log_info(LD_CONTROL, "Authenticated control connection ("TOR_SOCKET_T_FORMAT
|
||||
")", conn->base_.s);
|
||||
send_control_done(conn);
|
||||
conn->base_.state = CONTROL_CONN_STATE_OPEN;
|
||||
tor_free(password);
|
||||
if (sl) { /* clean up */
|
||||
SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
|
||||
smartlist_free(sl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
control_auth_free_all(void)
|
||||
{
|
||||
if (authentication_cookie) /* Free the auth cookie */
|
||||
tor_free(authentication_cookie);
|
||||
authentication_cookie_is_set = 0;
|
||||
}
|
27
src/feature/control/control_auth.h
Normal file
27
src/feature/control/control_auth.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2019, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file control_auth.h
|
||||
* \brief Header file for control_auth.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONTROL_AUTH_H
|
||||
#define TOR_CONTROL_AUTH_H
|
||||
|
||||
int init_control_cookie_authentication(int enabled);
|
||||
char *get_controller_cookie_file_name(void);
|
||||
struct config_line_t;
|
||||
smartlist_t *decode_hashed_passwords(struct config_line_t *passwords);
|
||||
|
||||
int handle_control_authchallenge(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
int handle_control_authenticate(control_connection_t *conn,
|
||||
uint32_t cmd_data_len,
|
||||
const char *args);
|
||||
void control_auth_free_all(void);
|
||||
|
||||
#endif /* !defined(TOR_CONTROL_AUTH_H) */
|
2323
src/feature/control/control_cmd.c
Normal file
2323
src/feature/control/control_cmd.c
Normal file
File diff suppressed because it is too large
Load diff
48
src/feature/control/control_cmd.h
Normal file
48
src/feature/control/control_cmd.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2019, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file control_cmd.h
|
||||
* \brief Header file for control_cmd.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONTROL_CMD_H
|
||||
#define TOR_CONTROL_CMD_H
|
||||
|
||||
int handle_control_command(control_connection_t *conn,
|
||||
uint32_t cmd_data_len,
|
||||
char *args);
|
||||
void control_cmd_free_all(void);
|
||||
|
||||
#ifdef CONTROL_CMD_PRIVATE
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
|
||||
/* ADD_ONION secret key to create an ephemeral service. The command supports
|
||||
* multiple versions so this union stores the key and passes it to the HS
|
||||
* subsystem depending on the requested version. */
|
||||
typedef union add_onion_secret_key_t {
|
||||
/* Hidden service v2 secret key. */
|
||||
crypto_pk_t *v2;
|
||||
/* Hidden service v3 secret key. */
|
||||
ed25519_secret_key_t *v3;
|
||||
} add_onion_secret_key_t;
|
||||
|
||||
STATIC int add_onion_helper_keyarg(const char *arg, int discard_pk,
|
||||
const char **key_new_alg_out,
|
||||
char **key_new_blob_out,
|
||||
add_onion_secret_key_t *decoded_key,
|
||||
int *hs_version, char **err_msg_out);
|
||||
|
||||
STATIC rend_authorized_client_t *add_onion_helper_clientauth(const char *arg,
|
||||
int *created, char **err_msg_out);
|
||||
|
||||
#endif /* defined(CONTROL_CMD_PRIVATE) */
|
||||
|
||||
#ifdef CONTROL_MODULE_PRIVATE
|
||||
smartlist_t * get_detached_onion_services(void);
|
||||
#endif /* defined(CONTROL_MODULE_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONTROL_CMD_H) */
|
|
@ -297,3 +297,98 @@ read_escaped_data(const char *data, size_t len, char **out)
|
|||
*outp = '\0';
|
||||
return outp - *out;
|
||||
}
|
||||
|
||||
/** Send a "DONE" message down the control connection <b>conn</b>. */
|
||||
void
|
||||
send_control_done(control_connection_t *conn)
|
||||
{
|
||||
connection_write_str_to_buf("250 OK\r\n", conn);
|
||||
}
|
||||
|
||||
/** If the first <b>in_len_max</b> characters in <b>start</b> contain a
|
||||
* double-quoted string with escaped characters, return the length of that
|
||||
* string (as encoded, including quotes). Otherwise return -1. */
|
||||
static inline int
|
||||
get_escaped_string_length(const char *start, size_t in_len_max,
|
||||
int *chars_out)
|
||||
{
|
||||
const char *cp, *end;
|
||||
int chars = 0;
|
||||
|
||||
if (*start != '\"')
|
||||
return -1;
|
||||
|
||||
cp = start+1;
|
||||
end = start+in_len_max;
|
||||
|
||||
/* Calculate length. */
|
||||
while (1) {
|
||||
if (cp >= end) {
|
||||
return -1; /* Too long. */
|
||||
} else if (*cp == '\\') {
|
||||
if (++cp == end)
|
||||
return -1; /* Can't escape EOS. */
|
||||
++cp;
|
||||
++chars;
|
||||
} else if (*cp == '\"') {
|
||||
break;
|
||||
} else {
|
||||
++cp;
|
||||
++chars;
|
||||
}
|
||||
}
|
||||
if (chars_out)
|
||||
*chars_out = chars;
|
||||
return (int)(cp - start+1);
|
||||
}
|
||||
|
||||
/** As decode_escaped_string, but does not decode the string: copies the
|
||||
* entire thing, including quotation marks. */
|
||||
const char *
|
||||
extract_escaped_string(const char *start, size_t in_len_max,
|
||||
char **out, size_t *out_len)
|
||||
{
|
||||
int length = get_escaped_string_length(start, in_len_max, NULL);
|
||||
if (length<0)
|
||||
return NULL;
|
||||
*out_len = length;
|
||||
*out = tor_strndup(start, *out_len);
|
||||
return start+length;
|
||||
}
|
||||
|
||||
/** Given a pointer to a string starting at <b>start</b> containing
|
||||
* <b>in_len_max</b> characters, decode a string beginning with one double
|
||||
* quote, containing any number of non-quote characters or characters escaped
|
||||
* with a backslash, and ending with a final double quote. Place the resulting
|
||||
* string (unquoted, unescaped) into a newly allocated string in *<b>out</b>;
|
||||
* store its length in <b>out_len</b>. On success, return a pointer to the
|
||||
* character immediately following the escaped string. On failure, return
|
||||
* NULL. */
|
||||
const char *
|
||||
decode_escaped_string(const char *start, size_t in_len_max,
|
||||
char **out, size_t *out_len)
|
||||
{
|
||||
const char *cp, *end;
|
||||
char *outp;
|
||||
int len, n_chars = 0;
|
||||
|
||||
len = get_escaped_string_length(start, in_len_max, &n_chars);
|
||||
if (len<0)
|
||||
return NULL;
|
||||
|
||||
end = start+len-1; /* Index of last quote. */
|
||||
tor_assert(*end == '\"');
|
||||
outp = *out = tor_malloc(len+1);
|
||||
*out_len = n_chars;
|
||||
|
||||
cp = start+1;
|
||||
while (cp < end) {
|
||||
if (*cp == '\\')
|
||||
++cp;
|
||||
*outp++ = *cp++;
|
||||
}
|
||||
*outp = '\0';
|
||||
tor_assert((outp - *out) == (int)*out_len);
|
||||
|
||||
return end+1;
|
||||
}
|
||||
|
|
|
@ -25,5 +25,10 @@ char *circuit_describe_status_for_controller(origin_circuit_t *circ);
|
|||
|
||||
size_t write_escaped_data(const char *data, size_t len, char **out);
|
||||
size_t read_escaped_data(const char *data, size_t len, char **out);
|
||||
const char *extract_escaped_string(const char *start, size_t in_len_max,
|
||||
char **out, size_t *out_len);
|
||||
const char *decode_escaped_string(const char *start, size_t in_len_max,
|
||||
char **out, size_t *out_len);
|
||||
void send_control_done(control_connection_t *conn);
|
||||
|
||||
#endif /* !defined(TOR_CONTROL_FMT_H) */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "feature/client/bridges.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/control/control_cmd.h"
|
||||
#include "feature/control/control_events.h"
|
||||
#include "feature/control/control_fmt.h"
|
||||
#include "feature/control/control_getinfo.h"
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/* Copyright (c) 2015-2019, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#define CONTROL_PRIVATE
|
||||
#define CONTROL_CMD_PRIVATE
|
||||
#define CONTROL_GETINFO_PRIVATE
|
||||
#include "core/or/or.h"
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
#include "feature/client/bridges.h"
|
||||
#include "feature/control/control.h"
|
||||
#include "feature/control/control_cmd.h"
|
||||
#include "feature/control/control_getinfo.h"
|
||||
#include "feature/client/entrynodes.h"
|
||||
#include "feature/hs/hs_common.h"
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#define PT_PRIVATE
|
||||
#define UTIL_PRIVATE
|
||||
#define STATEFILE_PRIVATE
|
||||
//#define CONTROL_PRIVATE
|
||||
#define CONTROL_EVENTS_PRIVATE
|
||||
#define PROCESS_PRIVATE
|
||||
#include "core/or/or.h"
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "orconfig.h"
|
||||
#define COMPAT_PRIVATE
|
||||
#define COMPAT_TIME_PRIVATE
|
||||
#define CONTROL_PRIVATE
|
||||
#define UTIL_PRIVATE
|
||||
#define UTIL_MALLOC_PRIVATE
|
||||
#define SOCKET_PRIVATE
|
||||
|
|
Loading…
Add table
Reference in a new issue