diff options
-rw-r--r-- | src/or/config.c | 55 | ||||
-rw-r--r-- | src/or/config.h | 4 | ||||
-rw-r--r-- | src/or/control.c | 41 | ||||
-rw-r--r-- | src/or/ext_orport.c | 52 | ||||
-rw-r--r-- | src/or/ext_orport.h | 2 | ||||
-rw-r--r-- | src/test/test_extorport.c | 16 |
6 files changed, 95 insertions, 75 deletions
diff --git a/src/or/config.c b/src/or/config.c index f13db3011f..8b89cc4045 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -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; +} + diff --git a/src/or/config.h b/src/or/config.h index 16a8a350d5..eb16e74610 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -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); diff --git a/src/or/control.c b/src/or/control.c index 3a32ea6873..b6ba12702e 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -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)); - 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 - + retval = init_cookie_authentication(fname, "", /* no header */ + AUTHENTICATION_COOKIE_LEN, + &authentication_cookie, + &authentication_cookie_is_set); tor_free(fname); - return 0; + return retval; } /** A copy of the process specifier of Tor's owning controller, or diff --git a/src/or/ext_orport.c b/src/or/ext_orport.c index ee50a87d6e..272fef4d1f 100644 --- a/src/or/ext_orport.c +++ b/src/or/ext_orport.c @@ -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)); - 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)); + 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 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); diff --git a/src/or/ext_orport.h b/src/or/ext_orport.h index 2d15c18aad..37874b56f0 100644 --- a/src/or/ext_orport.h +++ b/src/or/ext_orport.h @@ -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 diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index 1d97557e41..e76808fa9c 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -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; |