aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/config.c55
-rw-r--r--src/or/config.h4
-rw-r--r--src/or/control.c41
-rw-r--r--src/or/ext_orport.c52
-rw-r--r--src/or/ext_orport.h2
-rw-r--r--src/test/test_extorport.c16
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;