log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
}
- if (conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_EXT_OR)
+ if (conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_EXT_OR) {
connection_or_remove_from_ext_or_id_map(TO_OR_CONN(conn));
+ tor_free(TO_OR_CONN(conn)->ext_or_conn_id);
+ }
#ifdef USE_BUFFEREVENTS
if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
switch (conn->type) {
case CONN_TYPE_OR:
+ case CONN_TYPE_EXT_OR:
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
break;
case CONN_TYPE_AP:
case CONN_TYPE_OR:
tor_assert(conn->state >= OR_CONN_STATE_MIN_);
tor_assert(conn->state <= OR_CONN_STATE_MAX_);
+ case CONN_TYPE_EXT_OR:
+ tor_assert(conn->state >= EXT_OR_CONN_STATE_MIN_);
+ tor_assert(conn->state <= EXT_OR_CONN_STATE_MAX_);
break;
case CONN_TYPE_EXIT:
tor_assert(conn->state >= EXIT_CONN_STATE_MIN_);
/* Unlink everything from the identity map. */
connection_or_clear_identity_map();
+ connection_or_clear_ext_or_id_map();
/* Clear out our list of broken connections */
clear_broken_connection_map(0);
connection_or_remove_from_ext_or_id_map(or_connection_t *conn)
{
or_connection_t *tmp;
- if (!orconn_identity_map)
- orconn_identity_map = digestmap_new();
+ if (!orconn_ext_or_id_map)
+ return;
+ if (!conn->ext_or_conn_id)
+ return;
tmp = digestmap_remove(orconn_ext_or_id_map, conn->ext_or_conn_id);
if (!tor_digest_is_zero(conn->ext_or_conn_id))
connection_or_clear_ext_or_id_map(void)
{
digestmap_free(orconn_ext_or_id_map, NULL);
+ orconn_ext_or_id_map = NULL;
}
/** Creates an Extended ORPort identifier for <b>conn<b/> and deposits
orconn_ext_or_id_map = digestmap_new();
/* Remove any previous identifiers: */
- if (!tor_digest_is_zero(conn->ext_or_conn_id))
+ if (conn->ext_or_conn_id && !tor_digest_is_zero(conn->ext_or_conn_id))
connection_or_remove_from_ext_or_id_map(conn);
do {
crypto_rand(random_id, sizeof(random_id));
} while (digestmap_get(orconn_ext_or_id_map, random_id));
+ if (!conn->ext_or_conn_id)
+ conn->ext_or_conn_id = tor_malloc_zero(EXT_OR_CONN_ID_LEN);
+
memcpy(conn->ext_or_conn_id, random_id, EXT_OR_CONN_ID_LEN);
tmp = digestmap_set(orconn_ext_or_id_map, random_id, conn);
connection_tls_start_handshake(conn, 1);
}
-#define EXT_OR_CMD_WANT_CONTROL 0x0003
+/** DOCDOCDOC */
+#define EXT_OR_PORT_AUTH_COOKIE_LEN 32
+#define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN 32
+#define EXT_OR_PORT_AUTH_COOKIE_FILE_LEN EXT_OR_PORT_AUTH_COOKIE_LEN+EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN
+#define EXT_OR_PORT_AUTH_COOKIE_HEADER "! Extended ORPort Auth Cookie !\x0a"
+
+/** If true, we've set ext_or_auth_cookie to a secret code and stored
+ * it to disk. */
+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};
+
+/** Helper: Return a newly allocated string containing a path to the
+ * file where we store our authentication cookie. */
+char *
+get_ext_or_auth_cookie_file(void)
+{
+ const or_options_t *options = get_options();
+ if (options->ExtORPortCookieAuthFile && strlen(options->ExtORPortCookieAuthFile)) {
+ return tor_strdup(options->ExtORPortCookieAuthFile);
+ } else {
+ return get_datadir_fname("extended_orport_auth_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. */
+int
+init_ext_or_auth_cookie_authentication(int is_enabled)
+{
+ char *fname;
+ char cookie_file_string[EXT_OR_PORT_AUTH_COOKIE_FILE_LEN];
+
+ 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 */
+
+ fname = get_ext_or_auth_cookie_file();
+ crypto_rand(ext_or_auth_cookie, EXT_OR_PORT_AUTH_COOKIE_LEN);
+ 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);
+
+ 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_warn(LD_GENERAL, "Generated Extended ORPort cookie file in '%s'.",
+ fname);
+
+ tor_free(fname);
+ return 0;
+}
/** Extended ORPort commands (Transport-to-Bridge) */
#define EXT_OR_CMD_TB_DONE 0x0000
/* record the address */
tor_addr_copy(&conn->addr, &addr);
conn->port = port;
- } else if (command->cmd == EXT_OR_CMD_WANT_CONTROL) {
- char response[128];
- char *cp;
- memcpy(response, or_conn->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
- cp = response+EXT_OR_CONN_ID_LEN;
- /* XXXX write the TransportControlPort; advance cp. */
- connection_write_ext_or_command(conn, EXT_OR_CMD_BT_OKAY, response,
- cp-response);
} else {
log_notice(LD_NET, "Got an Extended ORPort command we don't understand (%u).",
command->cmd);
ext_or_cmd_free(command);
}
+ return 0;
+
err:
ext_or_cmd_free(command);
return -1;
#include "router.h"
#include "statefile.h"
#include "entrynodes.h"
+#include "connection_or.h"
static process_environment_t *
create_managed_proxy_environment(const managed_proxy_t *mp);
static process_environment_t *
create_managed_proxy_environment(const managed_proxy_t *mp)
{
+ const or_options_t *options = get_options();
+
/* Environment variables to be added to or set in mp's environment. */
smartlist_t *envs = smartlist_new();
/* XXXX The next time someone touches this code, shorten the name of
* (If we remove this line entirely, some joker will stick this
* variable in Tor's environment and crash PTs that try to parse
* it even when not run in server mode.) */
- smartlist_add(envs, tor_strdup("TOR_PT_EXTENDED_SERVER_PORT="));
+
+ if (options->ExtORPort) {
+ char *ext_or_addrport_tmp =
+ get_first_listener_addrport_string(CONN_TYPE_EXT_OR_LISTENER);
+ char *cookie_file_loc = get_ext_or_auth_cookie_file();
+
+ smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
+ ext_or_addrport_tmp);
+ smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s", cookie_file_loc);
+
+ tor_free(ext_or_addrport_tmp);
+ tor_free(cookie_file_loc);
+
+ } else {
+ smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
+ }
}
SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {