mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 07:07:52 +01:00
Merge remote-tracking branch 'public/owning_control_fd'
This commit is contained in:
commit
cd606d5ad3
9 changed files with 103 additions and 10 deletions
7
changes/ticket23900
Normal file
7
changes/ticket23900
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
o Minor features (API, embedding):
|
||||||
|
- Tor can now start with a preauthenticated control connection
|
||||||
|
created by the process that launched it. This feature is meant
|
||||||
|
for use by programs that want to launch and manage a Tor process
|
||||||
|
without allowing other programs to manage it as well.
|
||||||
|
For more information, see the __OwningControllerFD option
|
||||||
|
documented in control-spec.txt. Closes ticket 23900.
|
|
@ -1186,7 +1186,7 @@ mark_socket_open(tor_socket_t s)
|
||||||
bitarray_set(open_sockets, s);
|
bitarray_set(open_sockets, s);
|
||||||
}
|
}
|
||||||
#else /* !(defined(DEBUG_SOCKET_COUNTING)) */
|
#else /* !(defined(DEBUG_SOCKET_COUNTING)) */
|
||||||
#define mark_socket_open(s) STMT_NIL
|
#define mark_socket_open(s) ((void) (s))
|
||||||
#endif /* defined(DEBUG_SOCKET_COUNTING) */
|
#endif /* defined(DEBUG_SOCKET_COUNTING) */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -1273,11 +1273,22 @@ tor_open_socket_with_extensions(int domain, int type, int protocol,
|
||||||
goto socket_ok; /* So that socket_ok will not be unused. */
|
goto socket_ok; /* So that socket_ok will not be unused. */
|
||||||
|
|
||||||
socket_ok:
|
socket_ok:
|
||||||
|
tor_take_socket_ownership(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For socket accounting: remember that we are the owner of the socket
|
||||||
|
* <b>s</b>. This will prevent us from overallocating sockets, and prevent us
|
||||||
|
* from asserting later when we close the socket <b>s</b>.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
tor_take_socket_ownership(tor_socket_t s)
|
||||||
|
{
|
||||||
socket_accounting_lock();
|
socket_accounting_lock();
|
||||||
++n_sockets_open;
|
++n_sockets_open;
|
||||||
mark_socket_open(s);
|
mark_socket_open(s);
|
||||||
socket_accounting_unlock();
|
socket_accounting_unlock();
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** As accept(), but counts the number of open sockets. */
|
/** As accept(), but counts the number of open sockets. */
|
||||||
|
@ -1358,10 +1369,7 @@ tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
|
||||||
goto socket_ok; /* So that socket_ok will not be unused. */
|
goto socket_ok; /* So that socket_ok will not be unused. */
|
||||||
|
|
||||||
socket_ok:
|
socket_ok:
|
||||||
socket_accounting_lock();
|
tor_take_socket_ownership(s);
|
||||||
++n_sockets_open;
|
|
||||||
mark_socket_open(s);
|
|
||||||
socket_accounting_unlock();
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -483,6 +483,7 @@ typedef int socklen_t;
|
||||||
|
|
||||||
int tor_close_socket_simple(tor_socket_t s);
|
int tor_close_socket_simple(tor_socket_t s);
|
||||||
MOCK_DECL(int, tor_close_socket, (tor_socket_t s));
|
MOCK_DECL(int, tor_close_socket, (tor_socket_t s));
|
||||||
|
void tor_take_socket_ownership(tor_socket_t s);
|
||||||
tor_socket_t tor_open_socket_with_extensions(
|
tor_socket_t tor_open_socket_with_extensions(
|
||||||
int domain, int type, int protocol,
|
int domain, int type, int protocol,
|
||||||
int cloexec, int nonblock);
|
int cloexec, int nonblock);
|
||||||
|
|
|
@ -565,6 +565,7 @@ static config_var_t option_vars_[] = {
|
||||||
VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
|
VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
|
||||||
NULL),
|
NULL),
|
||||||
VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
|
VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
|
||||||
|
VAR("__OwningControllerFD",INT,OwningControllerFD, "-1"),
|
||||||
V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
|
V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
|
||||||
V(TestingServerDownloadSchedule, CSV_INTERVAL, "0, 0, 0, 60, 60, 120, "
|
V(TestingServerDownloadSchedule, CSV_INTERVAL, "0, 0, 0, 60, 60, 120, "
|
||||||
"300, 900, 2147483647"),
|
"300, 900, 2147483647"),
|
||||||
|
@ -1773,6 +1774,24 @@ options_act(const or_options_t *old_options)
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (running_tor && !old_options && options->OwningControllerFD != -1) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
log_warn(LD_CONFIG, "OwningControllerFD is not supported on Windows. "
|
||||||
|
"If you neeed it, tell the Tor developers.");
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
const unsigned ctrl_flags =
|
||||||
|
CC_LOCAL_FD_IS_OWNER |
|
||||||
|
CC_LOCAL_FD_IS_AUTHENTICATED;
|
||||||
|
tor_socket_t ctrl_sock = (tor_socket_t)options->OwningControllerFD;
|
||||||
|
if (control_connection_add_local_fd(ctrl_sock, ctrl_flags) < 0) {
|
||||||
|
log_warn(LD_CONFIG, "Could not add local controller connection with "
|
||||||
|
"given FD.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Load state */
|
/* Load state */
|
||||||
if (! or_state_loaded() && running_tor) {
|
if (! or_state_loaded() && running_tor) {
|
||||||
if (or_state_load())
|
if (or_state_load())
|
||||||
|
@ -4634,6 +4653,12 @@ options_transition_allowed(const or_options_t *old,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old->OwningControllerFD != new_val->OwningControllerFD) {
|
||||||
|
*msg = tor_strdup("While Tor is running, changing OwningControllerFD "
|
||||||
|
"is not allowed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (sandbox_is_active()) {
|
if (sandbox_is_active()) {
|
||||||
#define SB_NOCHANGE_STR(opt) \
|
#define SB_NOCHANGE_STR(opt) \
|
||||||
do { \
|
do { \
|
||||||
|
|
|
@ -118,8 +118,6 @@ static connection_t *connection_listener_new(
|
||||||
const port_cfg_t *portcfg);
|
const port_cfg_t *portcfg);
|
||||||
static void connection_init(time_t now, connection_t *conn, int type,
|
static void connection_init(time_t now, connection_t *conn, int type,
|
||||||
int socket_family);
|
int socket_family);
|
||||||
static int connection_init_accepted_conn(connection_t *conn,
|
|
||||||
const listener_connection_t *listener);
|
|
||||||
static int connection_handle_listener_read(connection_t *conn, int new_type);
|
static int connection_handle_listener_read(connection_t *conn, int new_type);
|
||||||
static int connection_bucket_should_increase(int bucket,
|
static int connection_bucket_should_increase(int bucket,
|
||||||
or_connection_t *conn);
|
or_connection_t *conn);
|
||||||
|
@ -1662,11 +1660,15 @@ connection_handle_listener_read(connection_t *conn, int new_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize states for newly accepted connection <b>conn</b>.
|
/** Initialize states for newly accepted connection <b>conn</b>.
|
||||||
|
*
|
||||||
* If conn is an OR, start the TLS handshake.
|
* If conn is an OR, start the TLS handshake.
|
||||||
|
*
|
||||||
* If conn is a transparent AP, get its original destination
|
* If conn is a transparent AP, get its original destination
|
||||||
* and place it in circuit_wait.
|
* and place it in circuit_wait.
|
||||||
|
*
|
||||||
|
* The <b>listener</b> parameter is only used for AP connections.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
connection_init_accepted_conn(connection_t *conn,
|
connection_init_accepted_conn(connection_t *conn,
|
||||||
const listener_connection_t *listener)
|
const listener_connection_t *listener)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,8 @@ entry_connection_t *entry_connection_new(int type, int socket_family);
|
||||||
control_connection_t *control_connection_new(int socket_family);
|
control_connection_t *control_connection_new(int socket_family);
|
||||||
listener_connection_t *listener_connection_new(int type, int socket_family);
|
listener_connection_t *listener_connection_new(int type, int socket_family);
|
||||||
connection_t *connection_new(int type, int socket_family);
|
connection_t *connection_new(int type, int socket_family);
|
||||||
|
int connection_init_accepted_conn(connection_t *conn,
|
||||||
|
const listener_connection_t *listener);
|
||||||
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
|
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
|
||||||
MOCK_DECL(void,connection_free,(connection_t *conn));
|
MOCK_DECL(void,connection_free,(connection_t *conn));
|
||||||
void connection_free_all(void);
|
void connection_free_all(void);
|
||||||
|
|
|
@ -549,6 +549,49 @@ decode_escaped_string(const char *start, size_t in_len_max,
|
||||||
return end+1;
|
return end+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Create and add a new controller connection on <b>sock</b>. If
|
||||||
|
* <b>CC_LOCAL_FD_IS_OWNER</b> is set in <b>flags</b>, this Tor process should
|
||||||
|
* exit when the connection closes. If <b>CC_LOCAL_FD_IS_AUTHENTICATED</b>
|
||||||
|
* is set, then the connection does not need to authenticate.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
control_connection_add_local_fd(tor_socket_t sock, unsigned flags)
|
||||||
|
{
|
||||||
|
if (BUG(! SOCKET_OK(sock)))
|
||||||
|
return -1;
|
||||||
|
const int is_owner = !!(flags & CC_LOCAL_FD_IS_OWNER);
|
||||||
|
const int is_authenticated = !!(flags & CC_LOCAL_FD_IS_AUTHENTICATED);
|
||||||
|
control_connection_t *control_conn = control_connection_new(AF_UNSPEC);
|
||||||
|
connection_t *conn = TO_CONN(control_conn);
|
||||||
|
conn->s = sock;
|
||||||
|
tor_addr_make_unspec(&conn->addr);
|
||||||
|
conn->port = 1;
|
||||||
|
conn->address = tor_strdup("<local socket>");
|
||||||
|
|
||||||
|
/* We take ownership of this socket so that later, when we close it,
|
||||||
|
* we don't freak out. */
|
||||||
|
tor_take_socket_ownership(sock);
|
||||||
|
|
||||||
|
if (set_socket_nonblocking(sock) < 0 ||
|
||||||
|
connection_add(conn) < 0) {
|
||||||
|
connection_free(conn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
control_conn->is_owning_control_connection = is_owner;
|
||||||
|
|
||||||
|
if (connection_init_accepted_conn(conn, NULL) < 0) {
|
||||||
|
connection_mark_for_close(conn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_authenticated) {
|
||||||
|
conn->state = CONTROL_CONN_STATE_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Acts like sprintf, but writes its formatted string to the end of
|
/** Acts like sprintf, but writes its formatted string to the end of
|
||||||
* <b>conn</b>-\>outbuf. */
|
* <b>conn</b>-\>outbuf. */
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -27,6 +27,10 @@ void control_ports_write_to_file(void);
|
||||||
#define LOG_FN_CONN(conn, args) \
|
#define LOG_FN_CONN(conn, args) \
|
||||||
CONN_LOG_PROTECT(conn, log_fn args)
|
CONN_LOG_PROTECT(conn, log_fn args)
|
||||||
|
|
||||||
|
#define CC_LOCAL_FD_IS_OWNER (1u<<0)
|
||||||
|
#define CC_LOCAL_FD_IS_AUTHENTICATED (1u<<1)
|
||||||
|
int control_connection_add_local_fd(tor_socket_t sock, unsigned flags);
|
||||||
|
|
||||||
int connection_control_finished_flushing(control_connection_t *conn);
|
int connection_control_finished_flushing(control_connection_t *conn);
|
||||||
int connection_control_reached_eof(control_connection_t *conn);
|
int connection_control_reached_eof(control_connection_t *conn);
|
||||||
void connection_control_closed(control_connection_t *conn);
|
void connection_control_closed(control_connection_t *conn);
|
||||||
|
|
|
@ -4071,6 +4071,8 @@ typedef struct {
|
||||||
/** Process specifier for a controller that ‘owns’ this Tor
|
/** Process specifier for a controller that ‘owns’ this Tor
|
||||||
* instance. Tor will terminate if its owning controller does. */
|
* instance. Tor will terminate if its owning controller does. */
|
||||||
char *OwningControllerProcess;
|
char *OwningControllerProcess;
|
||||||
|
/** FD specifier for a controller that owns this Tor instance. */
|
||||||
|
int OwningControllerFD;
|
||||||
|
|
||||||
int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how
|
int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how
|
||||||
* long do we wait before exiting? */
|
* long do we wait before exiting? */
|
||||||
|
|
Loading…
Add table
Reference in a new issue