mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 15:43:32 +01:00
Implement and use a generic auth. cookie initialization function.
Use the generic function for both the ControlPort cookie and the ExtORPort cookie. Also, place the global cookie variables in the heap so that we can pass them around more easily as pointers. Also also, fix the unit tests that broke by this change. Conflicts: src/or/config.h src/or/ext_orport.c
This commit is contained in:
parent
13784d4753
commit
33c3e60a37
@ -6464,3 +6464,58 @@ config_maybe_load_geoip_files_(const or_options_t *options,
|
||||
config_load_geoip_file_(AF_INET6, options->GeoIPv6File, "geoip6");
|
||||
}
|
||||
|
||||
/** Initialize cookie authentication (used so far by the ControlPort
|
||||
* and Extended ORPort).
|
||||
*
|
||||
* Allocate memory and create a cookie (of length <b>cookie_len</b>)
|
||||
* in <b>cookie_out</b>.
|
||||
* Then write it down to <b>fname</b> and prepend it with <b>header</b>.
|
||||
*
|
||||
* If the whole procedure was successful, set
|
||||
* <b>cookie_is_set_out</b> to True. */
|
||||
int
|
||||
init_cookie_authentication(const char *fname, const char *header,
|
||||
int cookie_len,
|
||||
uint8_t **cookie_out, int *cookie_is_set_out)
|
||||
{
|
||||
char cookie_file_str_len = strlen(header) + cookie_len;
|
||||
char *cookie_file_str = tor_malloc(cookie_file_str_len);
|
||||
int retval = -1;
|
||||
|
||||
/* We don't want to generate a new cookie every time we call
|
||||
* options_act(). One should be enough. */
|
||||
if (*cookie_is_set_out) {
|
||||
retval = 0; /* we are all set */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If we've already set the cookie, free it before re-setting
|
||||
it. This can happen if we previously generated a cookie, but
|
||||
couldn't write it to a disk. */
|
||||
if (*cookie_out)
|
||||
tor_free(*cookie_out);
|
||||
|
||||
/* Generate the cookie */
|
||||
*cookie_out = tor_malloc(cookie_len);
|
||||
if (crypto_rand((char *)*cookie_out, cookie_len) < 0)
|
||||
goto done;
|
||||
|
||||
/* Create the string that should be written on the file. */
|
||||
memcpy(cookie_file_str, header, strlen(header));
|
||||
memcpy(cookie_file_str+strlen(header), *cookie_out, cookie_len);
|
||||
if (write_bytes_to_file(fname, cookie_file_str, cookie_file_str_len, 1)) {
|
||||
log_warn(LD_FS,"Error writing auth cookie to %s.", escaped(fname));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
log_info(LD_GENERAL, "Generated auth cookie file in '%s'.", escaped(fname));
|
||||
*cookie_is_set_out = 1;
|
||||
retval = 0;
|
||||
|
||||
done:
|
||||
memwipe(cookie_file_str, 0, cookie_file_str_len);
|
||||
tor_free(cookie_file_str);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,10 @@ uint32_t get_effective_bwburst(const or_options_t *options);
|
||||
|
||||
char *get_transport_bindaddr_from_config(const char *transport);
|
||||
|
||||
int init_cookie_authentication(const char *fname, const char *header,
|
||||
int cookie_len,
|
||||
uint8_t **cookie_out, int *cookie_is_set_out);
|
||||
|
||||
or_options_t *options_new(void);
|
||||
|
||||
void config_register_addressmaps(const or_options_t *options);
|
||||
|
@ -115,7 +115,7 @@ 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 char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
|
||||
static uint8_t *authentication_cookie = NULL;
|
||||
|
||||
#define SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT \
|
||||
"Tor safe cookie authentication server-to-controller hash"
|
||||
@ -4446,44 +4446,27 @@ get_cookie_file(void)
|
||||
}
|
||||
}
|
||||
|
||||
/** Choose a random authentication cookie and write it to disk.
|
||||
* Anybody who can read the cookie from disk will be considered
|
||||
* authorized to use the control connection. Return -1 if we can't
|
||||
* write the file, or 0 on success. */
|
||||
/* 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;
|
||||
char *fname = NULL;
|
||||
int retval;
|
||||
|
||||
if (!enabled) {
|
||||
authentication_cookie_is_set = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We don't want to generate a new cookie every time we call
|
||||
* options_act(). One should be enough. */
|
||||
if (authentication_cookie_is_set)
|
||||
return 0; /* all set */
|
||||
|
||||
fname = get_cookie_file();
|
||||
crypto_rand(authentication_cookie, AUTHENTICATION_COOKIE_LEN);
|
||||
authentication_cookie_is_set = 1;
|
||||
if (write_bytes_to_file(fname, authentication_cookie,
|
||||
AUTHENTICATION_COOKIE_LEN, 1)) {
|
||||
log_warn(LD_FS,"Error writing authentication cookie to %s.",
|
||||
escaped(fname));
|
||||
retval = init_cookie_authentication(fname, "", /* no header */
|
||||
AUTHENTICATION_COOKIE_LEN,
|
||||
&authentication_cookie,
|
||||
&authentication_cookie_is_set);
|
||||
tor_free(fname);
|
||||
return -1;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
if (get_options()->CookieAuthFileGroupReadable) {
|
||||
if (chmod(fname, 0640)) {
|
||||
log_warn(LD_FS,"Unable to make %s group-readable.", escaped(fname));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
tor_free(fname);
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** A copy of the process specifier of Tor's owning controller, or
|
||||
|
@ -88,9 +88,6 @@ connection_ext_or_transition(or_connection_t *conn)
|
||||
#define EXT_OR_PORT_AUTH_COOKIE_LEN 32
|
||||
/** Length of the header of the cookie file. */
|
||||
#define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN 32
|
||||
/** Total length of the cookie file. */
|
||||
#define EXT_OR_PORT_AUTH_COOKIE_FILE_LEN \
|
||||
EXT_OR_PORT_AUTH_COOKIE_LEN+EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN
|
||||
/** Static cookie file header. */
|
||||
#define EXT_OR_PORT_AUTH_COOKIE_HEADER "! Extended ORPort Auth Cookie !\x0a"
|
||||
/** Length of safe-cookie protocol hashes. */
|
||||
@ -112,7 +109,7 @@ STATIC int ext_or_auth_cookie_is_set = 0;
|
||||
/** If ext_or_auth_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 char ext_or_auth_cookie[EXT_OR_PORT_AUTH_COOKIE_LEN] = {0};
|
||||
STATIC uint8_t *ext_or_auth_cookie = NULL;
|
||||
|
||||
/** Helper: Return a newly allocated string containing a path to the
|
||||
* file where we store our authentication cookie. */
|
||||
@ -128,50 +125,27 @@ get_ext_or_auth_cookie_file_name(void)
|
||||
}
|
||||
}
|
||||
|
||||
/** Choose a random authentication cookie and write it to disk.
|
||||
* Anybody who can read the cookie from disk will be considered
|
||||
* authorized to use the control connection. Return -1 if we can't
|
||||
* write the file, or 0 on success. */
|
||||
/* Initialize the cookie-based authentication system of the
|
||||
* Extended ORPort. If <b>is_enabled</b> is 0, then disable the cookie
|
||||
* authentication system. */
|
||||
int
|
||||
init_ext_or_cookie_authentication(int is_enabled)
|
||||
{
|
||||
char *fname;
|
||||
char cookie_file_string[EXT_OR_PORT_AUTH_COOKIE_FILE_LEN];
|
||||
char *fname = NULL;
|
||||
int retval;
|
||||
|
||||
if (!is_enabled) {
|
||||
ext_or_auth_cookie_is_set = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We don't want to generate a new cookie every time we call
|
||||
* options_act(). One should be enough. */
|
||||
if (ext_or_auth_cookie_is_set)
|
||||
return 0; /* all set */
|
||||
|
||||
if (crypto_rand(ext_or_auth_cookie, EXT_OR_PORT_AUTH_COOKIE_LEN) < 0)
|
||||
return -1;
|
||||
ext_or_auth_cookie_is_set = 1;
|
||||
|
||||
memcpy(cookie_file_string, EXT_OR_PORT_AUTH_COOKIE_HEADER,
|
||||
EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN);
|
||||
memcpy(cookie_file_string+EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN,
|
||||
ext_or_auth_cookie, EXT_OR_PORT_AUTH_COOKIE_LEN);
|
||||
|
||||
fname = get_ext_or_auth_cookie_file_name();
|
||||
if (write_bytes_to_file(fname, cookie_file_string,
|
||||
EXT_OR_PORT_AUTH_COOKIE_FILE_LEN, 1)) {
|
||||
log_warn(LD_FS,"Error writing authentication cookie to %s.",
|
||||
escaped(fname));
|
||||
retval = init_cookie_authentication(fname, EXT_OR_PORT_AUTH_COOKIE_HEADER,
|
||||
EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN,
|
||||
&ext_or_auth_cookie,
|
||||
&ext_or_auth_cookie_is_set);
|
||||
tor_free(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info(LD_GENERAL, "Generated Extended ORPort cookie file in '%s'.",
|
||||
fname);
|
||||
|
||||
memwipe(cookie_file_string, 0, sizeof(cookie_file_string));
|
||||
tor_free(fname);
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Read data from <b>conn</b> and see if the client sent us the
|
||||
@ -249,13 +223,13 @@ handle_client_auth_nonce(const char *client_nonce, size_t client_nonce_len,
|
||||
server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
|
||||
|
||||
crypto_hmac_sha256(server_hash,
|
||||
ext_or_auth_cookie,
|
||||
(char*)ext_or_auth_cookie,
|
||||
EXT_OR_PORT_AUTH_COOKIE_LEN,
|
||||
hmac_s_msg,
|
||||
hmac_s_msg_len);
|
||||
|
||||
crypto_hmac_sha256(correct_client_hash,
|
||||
ext_or_auth_cookie,
|
||||
(char*)ext_or_auth_cookie,
|
||||
EXT_OR_PORT_AUTH_COOKIE_LEN,
|
||||
hmac_c_msg,
|
||||
hmac_c_msg_len);
|
||||
|
@ -32,7 +32,7 @@ STATIC int handle_client_auth_nonce(const char *client_nonce,
|
||||
char **client_hash_out,
|
||||
char **reply_out, size_t *reply_len_out);
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern char ext_or_auth_cookie[];
|
||||
extern uint8_t *ext_or_auth_cookie;
|
||||
extern int ext_or_auth_cookie_is_set;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -167,7 +167,8 @@ test_ext_or_init_auth(void *arg)
|
||||
|
||||
/* Shouldn't be initialized already, or our tests will be a bit
|
||||
* meaningless */
|
||||
test_assert(tor_mem_is_zero(ext_or_auth_cookie, 32));
|
||||
ext_or_auth_cookie = tor_malloc_zero(32);
|
||||
test_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
|
||||
|
||||
/* Now make sure we use a temporary file */
|
||||
fn = get_fname("ext_cookie_file");
|
||||
@ -184,7 +185,7 @@ test_ext_or_init_auth(void *arg)
|
||||
test_memeq(cp, "! Extended ORPort Auth Cookie !\x0a", 32);
|
||||
test_memeq(cp+32, ext_or_auth_cookie, 32);
|
||||
memcpy(cookie0, ext_or_auth_cookie, 32);
|
||||
test_assert(!tor_mem_is_zero(ext_or_auth_cookie, 32));
|
||||
test_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
|
||||
|
||||
/* Operation should be idempotent. */
|
||||
tt_int_op(0, ==, init_ext_or_cookie_authentication(1));
|
||||
@ -217,6 +218,7 @@ test_ext_or_cookie_auth(void *arg)
|
||||
tt_int_op(strlen(client_hash_input), ==, 46+32+32);
|
||||
tt_int_op(strlen(server_hash_input), ==, 46+32+32);
|
||||
|
||||
ext_or_auth_cookie = tor_malloc_zero(32);
|
||||
memcpy(ext_or_auth_cookie, "s beside you? When I count, ther", 32);
|
||||
ext_or_auth_cookie_is_set = 1;
|
||||
|
||||
@ -252,9 +254,9 @@ test_ext_or_cookie_auth(void *arg)
|
||||
memcpy(server_hash_input+46+32, reply+32, 32);
|
||||
memcpy(client_hash_input+46+32, reply+32, 32);
|
||||
/* Check the HMACs are correct... */
|
||||
crypto_hmac_sha256(hmac1, ext_or_auth_cookie, 32, server_hash_input,
|
||||
crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
|
||||
46+32+32);
|
||||
crypto_hmac_sha256(hmac2, ext_or_auth_cookie, 32, client_hash_input,
|
||||
crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
|
||||
46+32+32);
|
||||
test_memeq(hmac1, reply, 32);
|
||||
test_memeq(hmac2, client_hash, 32);
|
||||
@ -269,9 +271,9 @@ test_ext_or_cookie_auth(void *arg)
|
||||
memcpy(server_hash_input+46+32, reply2+32, 32);
|
||||
memcpy(client_hash_input+46+32, reply2+32, 32);
|
||||
/* Check the HMACs are correct... */
|
||||
crypto_hmac_sha256(hmac1, ext_or_auth_cookie, 32, server_hash_input,
|
||||
crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
|
||||
46+32+32);
|
||||
crypto_hmac_sha256(hmac2, ext_or_auth_cookie, 32, client_hash_input,
|
||||
crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
|
||||
46+32+32);
|
||||
test_memeq(hmac1, reply2, 32);
|
||||
test_memeq(hmac2, client_hash2, 32);
|
||||
@ -304,6 +306,7 @@ test_ext_or_cookie_auth_testvec(void *arg)
|
||||
const char client_nonce[] = "But when I look ahead up the whi";
|
||||
(void)arg;
|
||||
|
||||
ext_or_auth_cookie = tor_malloc_zero(32);
|
||||
memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
|
||||
ext_or_auth_cookie_is_set = 1;
|
||||
|
||||
@ -393,6 +396,7 @@ test_ext_or_handshake(void *arg)
|
||||
MOCK(connection_write_to_buf_impl_,
|
||||
connection_write_to_buf_impl_replacement);
|
||||
/* Use same authenticators as for test_ext_or_cookie_auth_testvec */
|
||||
ext_or_auth_cookie = tor_malloc_zero(32);
|
||||
memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
|
||||
ext_or_auth_cookie_is_set = 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user