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;
+}
+
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);
/** 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"
}
}
-/** 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
#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. */
/** 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. */
}
}
-/** 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
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);
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
/* 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");
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));
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;
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);
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);
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;
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;