mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-19 18:00:33 +01:00
Add __OwningControllerFD to allow controllers without controlports
This feature should help programs that want to launch and manage a Tor process, as well as programs that want to launch and manage a Tor instance in a separate thread. Right now, they have to open a controlport, and then connect to it, with attendant authentication issues. This feature allows them to just start with an authenticated connection. Bug 23900.
This commit is contained in:
parent
f0daaf8d60
commit
f1bf9bf819
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.
|
@ -562,6 +562,7 @@ static config_var_t option_vars_[] = {
|
||||
VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
|
||||
NULL),
|
||||
VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
|
||||
VAR("__OwningControllerFD",INT,OwningControllerFD, "-1"),
|
||||
V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
|
||||
V(TestingServerDownloadSchedule, CSV_INTERVAL, "0, 0, 0, 60, 60, 120, "
|
||||
"300, 900, 2147483647"),
|
||||
@ -1730,6 +1731,24 @@ options_act(const or_options_t *old_options)
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 */
|
||||
if (! or_state_loaded() && running_tor) {
|
||||
if (or_state_load())
|
||||
@ -4572,6 +4591,12 @@ options_transition_allowed(const or_options_t *old,
|
||||
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()) {
|
||||
#define SB_NOCHANGE_STR(opt) \
|
||||
do { \
|
||||
|
@ -549,6 +549,49 @@ decode_escaped_string(const char *start, size_t in_len_max,
|
||||
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
|
||||
* <b>conn</b>-\>outbuf. */
|
||||
static void
|
||||
|
@ -27,6 +27,10 @@ void control_ports_write_to_file(void);
|
||||
#define LOG_FN_CONN(conn, 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_reached_eof(control_connection_t *conn);
|
||||
void connection_control_closed(control_connection_t *conn);
|
||||
|
@ -4066,6 +4066,8 @@ typedef struct {
|
||||
/** Process specifier for a controller that ‘owns’ this Tor
|
||||
* instance. Tor will terminate if its owning controller does. */
|
||||
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
|
||||
* long do we wait before exiting? */
|
||||
|
Loading…
Reference in New Issue
Block a user