mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 15:43:32 +01:00
r13266@catbus: nickm | 2007-06-05 16:38:08 -0400
Patch from peter palfrader: control interface via unix domain socket svn:r10504
This commit is contained in:
parent
f0345d46f6
commit
210beff55a
@ -6,6 +6,11 @@ Changes in version 0.2.0.3-alpha - 2007-??-??
|
|||||||
- tor-gencert creates all files as readable to the file creator only, and
|
- tor-gencert creates all files as readable to the file creator only, and
|
||||||
write-protects the authority identity key.
|
write-protects the authority identity key.
|
||||||
|
|
||||||
|
o Minor feature (controller):
|
||||||
|
- You can now use the ControlSocket option to tell Tor to listen for
|
||||||
|
controller connections on Unix domain sockets on systems that support
|
||||||
|
them. (Patch from Peter Palfrader.)
|
||||||
|
|
||||||
o Minor bugfixes (dns):
|
o Minor bugfixes (dns):
|
||||||
- Fix a crash when DNSPort is set more than once. (Patch from Robert
|
- Fix a crash when DNSPort is set more than once. (Patch from Robert
|
||||||
Hogan.)
|
Hogan.)
|
||||||
|
@ -240,7 +240,7 @@ AC_SYS_LARGEFILE
|
|||||||
|
|
||||||
AC_CHECK_HEADERS(unistd.h string.h signal.h ctype.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/time.h errno.h assert.h time.h, , AC_MSG_WARN(Some headers were not found, compilation may fail. If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
|
AC_CHECK_HEADERS(unistd.h string.h signal.h ctype.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/time.h errno.h assert.h time.h, , AC_MSG_WARN(Some headers were not found, compilation may fail. If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
|
||||||
|
|
||||||
AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h grp.h)
|
AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h grp.h sys/un.h)
|
||||||
|
|
||||||
dnl These headers are not essential
|
dnl These headers are not essential
|
||||||
|
|
||||||
|
@ -149,6 +149,7 @@ static config_var_t _option_vars[] = {
|
|||||||
VAR("ContactInfo", STRING, ContactInfo, NULL),
|
VAR("ContactInfo", STRING, ContactInfo, NULL),
|
||||||
VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
|
VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
|
||||||
VAR("ControlPort", UINT, ControlPort, "0"),
|
VAR("ControlPort", UINT, ControlPort, "0"),
|
||||||
|
VAR("ControlSocket", LINELIST, ControlSocket, NULL),
|
||||||
VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"),
|
VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"),
|
||||||
VAR("DataDirectory", STRING, DataDirectory, NULL),
|
VAR("DataDirectory", STRING, DataDirectory, NULL),
|
||||||
OBSOLETE("DebugLogFile"),
|
OBSOLETE("DebugLogFile"),
|
||||||
@ -811,6 +812,14 @@ options_act_reversible(or_options_t *old_options, char **msg)
|
|||||||
start_daemon();
|
start_daemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_SYS_UN_H
|
||||||
|
if (options->ControlSocket) {
|
||||||
|
*msg = tor_strdup("Unix domain sockets (ControlSocket) not supported"
|
||||||
|
" on this OS/with this build.");
|
||||||
|
goto rollback;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (running_tor) {
|
if (running_tor) {
|
||||||
/* We need to set the connection limit before we can open the listeners. */
|
/* We need to set the connection limit before we can open the listeners. */
|
||||||
options->_ConnLimit =
|
options->_ConnLimit =
|
||||||
|
@ -14,8 +14,9 @@ const char connection_c_id[] =
|
|||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
|
|
||||||
static connection_t *connection_create_listener(const char *listenaddress,
|
static connection_t *connection_create_listener(
|
||||||
uint16_t listenport, int type);
|
struct sockaddr *listensockaddr, int type,
|
||||||
|
char* address);
|
||||||
static int connection_init_accepted_conn(connection_t *conn,
|
static int connection_init_accepted_conn(connection_t *conn,
|
||||||
uint8_t listener_type);
|
uint8_t listener_type);
|
||||||
static int connection_handle_listener_read(connection_t *conn, int new_type);
|
static int connection_handle_listener_read(connection_t *conn, int new_type);
|
||||||
@ -156,7 +157,7 @@ conn_state_to_string(int type, int state)
|
|||||||
* Initialize conn's timestamps to now.
|
* Initialize conn's timestamps to now.
|
||||||
*/
|
*/
|
||||||
connection_t *
|
connection_t *
|
||||||
connection_new(int type)
|
connection_new(int type, int sa_family)
|
||||||
{
|
{
|
||||||
static uint32_t n_connections_allocated = 1;
|
static uint32_t n_connections_allocated = 1;
|
||||||
connection_t *conn;
|
connection_t *conn;
|
||||||
@ -194,6 +195,7 @@ connection_new(int type)
|
|||||||
conn->conn_array_index = -1; /* also default to 'not used' */
|
conn->conn_array_index = -1; /* also default to 'not used' */
|
||||||
|
|
||||||
conn->type = type;
|
conn->type = type;
|
||||||
|
conn->sa_family = sa_family;
|
||||||
if (!connection_is_listener(conn)) { /* listeners never use their buf */
|
if (!connection_is_listener(conn)) { /* listeners never use their buf */
|
||||||
conn->inbuf = buf_new();
|
conn->inbuf = buf_new();
|
||||||
conn->outbuf = buf_new();
|
conn->outbuf = buf_new();
|
||||||
@ -293,6 +295,17 @@ _connection_free(connection_t *conn)
|
|||||||
if (!connection_is_listener(conn)) {
|
if (!connection_is_listener(conn)) {
|
||||||
buf_free(conn->inbuf);
|
buf_free(conn->inbuf);
|
||||||
buf_free(conn->outbuf);
|
buf_free(conn->outbuf);
|
||||||
|
} else {
|
||||||
|
if (conn->sa_family == AF_UNIX) {
|
||||||
|
/* For now only control ports can be unix domain sockets
|
||||||
|
* and listeners at the same time */
|
||||||
|
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
|
||||||
|
|
||||||
|
if (unlink(conn->address) < 0 && errno != ENOENT) {
|
||||||
|
log_warn(LD_NET, "Could not unlink %s: %s", conn->address,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tor_free(conn->address);
|
tor_free(conn->address);
|
||||||
@ -621,43 +634,96 @@ connection_expire_held_open(void)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Bind a new non-blocking socket listening to
|
/** Create an AF_INET listenaddr struct.
|
||||||
* <b>listenaddress</b>:<b>listenport</b>, and add this new connection
|
* <b>listenaddress</b> provides the host and optionally the port information
|
||||||
* (of type <b>type</b>) to the connection array.
|
* for the new structure. If no port is provided in <b>listenaddress</b> then
|
||||||
|
* <b>listenport</b> is used.
|
||||||
*
|
*
|
||||||
* If <b>listenaddress</b> includes a port, we bind on that port;
|
* If not NULL <b>readable_addrress</b> will contain a copy of the host part of
|
||||||
* otherwise, we use listenport.
|
* <b>listenaddress</b>.
|
||||||
|
*
|
||||||
|
* The listenaddr struct has to be freed by the caller.
|
||||||
*/
|
*/
|
||||||
static connection_t *
|
static struct sockaddr_in *
|
||||||
connection_create_listener(const char *listenaddress, uint16_t listenport,
|
create_inet_sockaddr(const char *listenaddress, uint16_t listenport,
|
||||||
int type)
|
char **readable_address) {
|
||||||
{
|
struct sockaddr_in *listenaddr = NULL;
|
||||||
struct sockaddr_in listenaddr; /* where to bind */
|
|
||||||
char *address = NULL;
|
|
||||||
connection_t *conn;
|
|
||||||
uint16_t usePort;
|
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
int s; /* the socket we're going to make */
|
uint16_t usePort = 0;
|
||||||
#ifndef MS_WINDOWS
|
|
||||||
int one=1;
|
|
||||||
#endif
|
|
||||||
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
|
|
||||||
|
|
||||||
memset(&listenaddr,0,sizeof(struct sockaddr_in));
|
if (parse_addr_port(LOG_WARN,
|
||||||
if (parse_addr_port(LOG_WARN, listenaddress, &address, &addr, &usePort)<0) {
|
listenaddress, readable_address, &addr, &usePort)<0) {
|
||||||
log_warn(LD_CONFIG,
|
log_warn(LD_CONFIG,
|
||||||
"Error parsing/resolving ListenAddress %s", listenaddress);
|
"Error parsing/resolving ListenAddress %s", listenaddress);
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usePort==0)
|
if (usePort==0)
|
||||||
usePort = listenport;
|
usePort = listenport;
|
||||||
listenaddr.sin_addr.s_addr = htonl(addr);
|
|
||||||
listenaddr.sin_family = AF_INET;
|
|
||||||
listenaddr.sin_port = htons((uint16_t) usePort);
|
|
||||||
|
|
||||||
log_notice(LD_NET, "Opening %s on %s:%d",
|
listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in));
|
||||||
conn_type_to_string(type), address, usePort);
|
listenaddr->sin_addr.s_addr = htonl(addr);
|
||||||
|
listenaddr->sin_family = AF_INET;
|
||||||
|
listenaddr->sin_port = htons((uint16_t) usePort);
|
||||||
|
|
||||||
|
return listenaddr;
|
||||||
|
|
||||||
|
err:
|
||||||
|
tor_free(listenaddr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
/** Create an AF_UNIX listenaddr struct.
|
||||||
|
* <b>listenaddress</b> provides the path to the unix socket.
|
||||||
|
*
|
||||||
|
* Eventually <b>listenaddress</b> will also optionally contain user, group,
|
||||||
|
* and file permissions for the new socket. But not yet. XXX
|
||||||
|
* Also, since we do not create the socket here the information doesn't help
|
||||||
|
* here.
|
||||||
|
*
|
||||||
|
* If not NULL <b>readable_addrress</b> will contain a copy of the path part of
|
||||||
|
* <b>listenaddress</b>.
|
||||||
|
*
|
||||||
|
* The listenaddr struct has to be freed by the caller.
|
||||||
|
*/
|
||||||
|
static struct sockaddr_un *
|
||||||
|
create_unix_sockaddr(const char *listenaddress, char **readable_address)
|
||||||
|
{
|
||||||
|
struct sockaddr_un *sockaddr = NULL;
|
||||||
|
|
||||||
|
sockaddr = tor_malloc_zero(sizeof(struct sockaddr_un));
|
||||||
|
sockaddr->sun_family = AF_UNIX;
|
||||||
|
strncpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path));
|
||||||
|
|
||||||
|
if (readable_address)
|
||||||
|
*readable_address = tor_strdup(listenaddress);
|
||||||
|
|
||||||
|
return sockaddr;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static struct sockaddr *
|
||||||
|
create_unix_sockaddr(const char *listenaddress, char **readable_address)
|
||||||
|
{
|
||||||
|
log_fn(LOG_ERR, LD_BUG,
|
||||||
|
"Unix domain sockets not supported, yet we tried to create one.");
|
||||||
|
assert(0);
|
||||||
|
};
|
||||||
|
#endif /* HAVE_SYS_UN_H */
|
||||||
|
|
||||||
|
/** Bind a new non-blocking socket listening to the socket described
|
||||||
|
* by <b>listensockaddr</b>.
|
||||||
|
*
|
||||||
|
* <b>address</b> is only used for logging purposes and to add the information
|
||||||
|
* to the conn.
|
||||||
|
*/
|
||||||
|
static connection_t *
|
||||||
|
connection_create_listener(struct sockaddr *listensockaddr, int type,
|
||||||
|
char* address)
|
||||||
|
{
|
||||||
|
connection_t *conn;
|
||||||
|
int s; /* the socket we're going to make */
|
||||||
|
uint16_t usePort = 0;
|
||||||
|
int start_reading = 0;
|
||||||
|
|
||||||
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
|
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
|
||||||
int n_conns = get_n_open_sockets();
|
int n_conns = get_n_open_sockets();
|
||||||
@ -668,48 +734,105 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = tor_open_socket(PF_INET,
|
if (listensockaddr->sa_family == AF_INET) {
|
||||||
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
|
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
|
||||||
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
|
#ifndef MS_WINDOWS
|
||||||
if (s < 0) {
|
int one=1;
|
||||||
log_warn(LD_NET,"Socket creation failed.");
|
#endif
|
||||||
goto err;
|
if (is_tcp)
|
||||||
}
|
start_reading = 1;
|
||||||
|
|
||||||
|
usePort = ntohs( (uint16_t)
|
||||||
|
((struct sockaddr_in *)listensockaddr)->sin_port);
|
||||||
|
|
||||||
|
log_notice(LD_NET, "Opening %s on %s:%d",
|
||||||
|
conn_type_to_string(type), address, usePort);
|
||||||
|
|
||||||
|
s = tor_open_socket(PF_INET,
|
||||||
|
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
|
||||||
|
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
|
||||||
|
if (s < 0) {
|
||||||
|
log_warn(LD_NET,"Socket creation failed.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
/* REUSEADDR on normal places means you can rebind to the port
|
/* REUSEADDR on normal places means you can rebind to the port
|
||||||
* right after somebody else has let it go. But REUSEADDR on win32
|
* right after somebody else has let it go. But REUSEADDR on win32
|
||||||
* means you can bind to the port _even when somebody else
|
* means you can bind to the port _even when somebody else
|
||||||
* already has it bound_. So, don't do that on Win32. */
|
* already has it bound_. So, don't do that on Win32. */
|
||||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one));
|
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (bind(s,(struct sockaddr *)&listenaddr,sizeof(listenaddr)) < 0) {
|
if (bind(s,listensockaddr,sizeof(struct sockaddr_in)) < 0) {
|
||||||
const char *helpfulhint = "";
|
const char *helpfulhint = "";
|
||||||
int e = tor_socket_errno(s);
|
int e = tor_socket_errno(s);
|
||||||
if (ERRNO_IS_EADDRINUSE(e))
|
if (ERRNO_IS_EADDRINUSE(e))
|
||||||
helpfulhint = ". Is Tor already running?";
|
helpfulhint = ". Is Tor already running?";
|
||||||
log_warn(LD_NET, "Could not bind to %s:%u: %s%s", address, usePort,
|
log_warn(LD_NET, "Could not bind to %s:%u: %s%s", address, usePort,
|
||||||
tor_socket_strerror(e), helpfulhint);
|
tor_socket_strerror(e), helpfulhint);
|
||||||
tor_close_socket(s);
|
tor_close_socket(s);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_tcp) {
|
||||||
|
if (listen(s,SOMAXCONN) < 0) {
|
||||||
|
log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort,
|
||||||
|
tor_socket_strerror(tor_socket_errno(s)));
|
||||||
|
tor_close_socket(s);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
} else if (listensockaddr->sa_family == AF_UNIX) {
|
||||||
|
int len;
|
||||||
|
start_reading = 1;
|
||||||
|
|
||||||
|
/* For now only control ports can be unix domain sockets
|
||||||
|
* and listeners at the same time */
|
||||||
|
tor_assert(type == CONN_TYPE_CONTROL_LISTENER);
|
||||||
|
|
||||||
|
log_notice(LD_NET, "Opening %s on %s",
|
||||||
|
conn_type_to_string(type), address);
|
||||||
|
|
||||||
|
if (unlink(address) < 0 && errno != ENOENT) {
|
||||||
|
log_warn(LD_NET, "Could not unlink %s: %s", address,
|
||||||
|
strerror(errno));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
s = tor_open_socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (s < 0) {
|
||||||
|
log_warn(LD_NET,"Socket creation failed: %s.", strerror(errno));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(((struct sockaddr_un *)listensockaddr)->sun_path) +
|
||||||
|
sizeof(((struct sockaddr_un *)listensockaddr)->sun_family);
|
||||||
|
if (bind(s, listensockaddr, len) == -1) {
|
||||||
|
log_warn(LD_NET,"Bind to %s failed: %s.", address,
|
||||||
|
tor_socket_strerror(tor_socket_errno(s)));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_tcp) {
|
|
||||||
if (listen(s,SOMAXCONN) < 0) {
|
if (listen(s,SOMAXCONN) < 0) {
|
||||||
log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort,
|
log_warn(LD_NET, "Could not listen on %s: %s", address,
|
||||||
tor_socket_strerror(tor_socket_errno(s)));
|
tor_socket_strerror(tor_socket_errno(s)));
|
||||||
tor_close_socket(s);
|
tor_close_socket(s);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_SYS_UN_H */
|
||||||
|
} else {
|
||||||
|
log_err(LD_BUG,"Got unexpected address family %d.",
|
||||||
|
listensockaddr->sa_family);
|
||||||
|
tor_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_socket_nonblocking(s);
|
set_socket_nonblocking(s);
|
||||||
|
|
||||||
conn = connection_new(type);
|
conn = connection_new(type, listensockaddr->sa_family);
|
||||||
|
conn->sa_family = listensockaddr->sa_family;
|
||||||
conn->s = s;
|
conn->s = s;
|
||||||
conn->address = address;
|
conn->address = tor_strdup(address);
|
||||||
address = NULL;
|
|
||||||
conn->port = usePort;
|
conn->port = usePort;
|
||||||
|
|
||||||
if (connection_add(conn) < 0) { /* no space, forget it */
|
if (connection_add(conn) < 0) { /* no space, forget it */
|
||||||
@ -722,7 +845,7 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
|
|||||||
conn_type_to_string(type), usePort);
|
conn_type_to_string(type), usePort);
|
||||||
|
|
||||||
conn->state = LISTENER_STATE_READY;
|
conn->state = LISTENER_STATE_READY;
|
||||||
if (is_tcp) {
|
if (start_reading) {
|
||||||
connection_start_reading(conn);
|
connection_start_reading(conn);
|
||||||
} else {
|
} else {
|
||||||
tor_assert(type == CONN_TYPE_AP_DNS_LISTENER);
|
tor_assert(type == CONN_TYPE_AP_DNS_LISTENER);
|
||||||
@ -732,7 +855,6 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
|
|||||||
return conn;
|
return conn;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
tor_free(address);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,55 +923,75 @@ connection_handle_listener_read(connection_t *conn, int new_type)
|
|||||||
|
|
||||||
set_socket_nonblocking(news);
|
set_socket_nonblocking(news);
|
||||||
|
|
||||||
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, LOG_INFO)<0) {
|
tor_assert(((struct sockaddr*)addrbuf)->sa_family == conn->sa_family);
|
||||||
log_info(LD_NET,
|
|
||||||
"accept() returned a strange address; trying getsockname().");
|
if (conn->sa_family == AF_INET) {
|
||||||
remotelen=256;
|
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, LOG_INFO)<0) {
|
||||||
memset(addrbuf, 0, sizeof(addrbuf));
|
log_info(LD_NET,
|
||||||
if (getsockname(news, (struct sockaddr*)addrbuf, &remotelen)<0) {
|
"accept() returned a strange address; trying getsockname().");
|
||||||
int e = tor_socket_errno(news);
|
remotelen=256;
|
||||||
log_warn(LD_NET, "getsockname() for new connection failed: %s",
|
memset(addrbuf, 0, sizeof(addrbuf));
|
||||||
tor_socket_strerror(e));
|
if (getsockname(news, (struct sockaddr*)addrbuf, &remotelen)<0) {
|
||||||
} else {
|
int e = tor_socket_errno(news);
|
||||||
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen,
|
log_warn(LD_NET, "getsockname() for new connection failed: %s",
|
||||||
LOG_WARN) < 0) {
|
tor_socket_strerror(e));
|
||||||
log_warn(LD_NET,"Something's wrong with this conn. Closing it.");
|
} else {
|
||||||
|
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen,
|
||||||
|
LOG_WARN) < 0) {
|
||||||
|
log_warn(LD_NET,"Something's wrong with this conn. Closing it.");
|
||||||
|
tor_close_socket(news);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(&remote, addrbuf, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
/* process entrance policies here, before we even create the connection */
|
||||||
|
if (new_type == CONN_TYPE_AP) {
|
||||||
|
/* check sockspolicy to see if we should accept it */
|
||||||
|
if (socks_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
|
||||||
|
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
|
||||||
|
log_notice(LD_APP,
|
||||||
|
"Denying socks connection from untrusted address %s.",
|
||||||
|
tmpbuf);
|
||||||
tor_close_socket(news);
|
tor_close_socket(news);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (new_type == CONN_TYPE_DIR) {
|
||||||
memcpy(&remote, addrbuf, sizeof(struct sockaddr_in));
|
/* check dirpolicy to see if we should accept it */
|
||||||
|
if (dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
|
||||||
/* process entrance policies here, before we even create the connection */
|
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
|
||||||
if (new_type == CONN_TYPE_AP) {
|
log_notice(LD_DIRSERV,"Denying dir connection from address %s.",
|
||||||
/* check sockspolicy to see if we should accept it */
|
tmpbuf);
|
||||||
if (socks_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
|
tor_close_socket(news);
|
||||||
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
|
return 0;
|
||||||
log_notice(LD_APP,"Denying socks connection from untrusted address %s.",
|
}
|
||||||
tmpbuf);
|
|
||||||
tor_close_socket(news);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (new_type == CONN_TYPE_DIR) {
|
|
||||||
/* check dirpolicy to see if we should accept it */
|
|
||||||
if (dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
|
|
||||||
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
|
|
||||||
log_notice(LD_DIRSERV,"Denying dir connection from address %s.",
|
|
||||||
tmpbuf);
|
|
||||||
tor_close_socket(news);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newconn = connection_new(new_type);
|
newconn = connection_new(new_type, conn->sa_family);
|
||||||
newconn->s = news;
|
newconn->s = news;
|
||||||
|
|
||||||
/* remember the remote address */
|
/* remember the remote address */
|
||||||
newconn->addr = ntohl(remote.sin_addr.s_addr);
|
newconn->addr = ntohl(remote.sin_addr.s_addr);
|
||||||
newconn->port = ntohs(remote.sin_port);
|
newconn->port = ntohs(remote.sin_port);
|
||||||
newconn->address = tor_dup_addr(newconn->addr);
|
newconn->address = tor_dup_addr(newconn->addr);
|
||||||
|
|
||||||
|
} else if (conn->sa_family == AF_UNIX) {
|
||||||
|
/* For now only control ports can be unix domain sockets
|
||||||
|
* and listeners at the same time */
|
||||||
|
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
|
||||||
|
|
||||||
|
newconn = connection_new(new_type, conn->sa_family);
|
||||||
|
newconn->s = news;
|
||||||
|
|
||||||
|
/* remember the remote address -- do we have anything sane to put here? */
|
||||||
|
newconn->addr = 0;
|
||||||
|
newconn->port = 1;
|
||||||
|
newconn->address = tor_strdup(conn->address);
|
||||||
|
} else {
|
||||||
|
tor_assert(0);
|
||||||
|
};
|
||||||
|
|
||||||
if (connection_add(newconn) < 0) { /* no space, forget it */
|
if (connection_add(newconn) < 0) { /* no space, forget it */
|
||||||
connection_free(newconn);
|
connection_free(newconn);
|
||||||
@ -1007,7 +1149,8 @@ retry_listeners(int type, config_line_t *cfg,
|
|||||||
int port_option, const char *default_addr,
|
int port_option, const char *default_addr,
|
||||||
smartlist_t *replaced_conns,
|
smartlist_t *replaced_conns,
|
||||||
smartlist_t *new_conns,
|
smartlist_t *new_conns,
|
||||||
int never_open_conns)
|
int never_open_conns,
|
||||||
|
int sa_family)
|
||||||
{
|
{
|
||||||
smartlist_t *launch = smartlist_create(), *conns;
|
smartlist_t *launch = smartlist_create(), *conns;
|
||||||
int free_launch_elts = 1;
|
int free_launch_elts = 1;
|
||||||
@ -1016,6 +1159,8 @@ retry_listeners(int type, config_line_t *cfg,
|
|||||||
connection_t *conn;
|
connection_t *conn;
|
||||||
config_line_t *line;
|
config_line_t *line;
|
||||||
|
|
||||||
|
tor_assert(sa_family == AF_INET || sa_family == AF_UNIX);
|
||||||
|
|
||||||
if (cfg && port_option) {
|
if (cfg && port_option) {
|
||||||
for (c = cfg; c; c = c->next) {
|
for (c = cfg; c; c = c->next) {
|
||||||
smartlist_add(launch, c);
|
smartlist_add(launch, c);
|
||||||
@ -1036,7 +1181,9 @@ retry_listeners(int type, config_line_t *cfg,
|
|||||||
conns = get_connection_array();
|
conns = get_connection_array();
|
||||||
SMARTLIST_FOREACH(conns, connection_t *, conn,
|
SMARTLIST_FOREACH(conns, connection_t *, conn,
|
||||||
{
|
{
|
||||||
if (conn->type != type || conn->marked_for_close)
|
if (conn->type != type ||
|
||||||
|
conn->sa_family != sa_family ||
|
||||||
|
conn->marked_for_close)
|
||||||
continue;
|
continue;
|
||||||
/* Okay, so this is a listener. Is it configured? */
|
/* Okay, so this is a listener. Is it configured? */
|
||||||
line = NULL;
|
line = NULL;
|
||||||
@ -1044,15 +1191,28 @@ retry_listeners(int type, config_line_t *cfg,
|
|||||||
{
|
{
|
||||||
char *address=NULL;
|
char *address=NULL;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
if (!parse_addr_port(LOG_WARN, wanted->value, &address, NULL, &port)) {
|
switch (sa_family) {
|
||||||
int addr_matches = !strcasecmp(address, conn->address);
|
case AF_INET:
|
||||||
tor_free(address);
|
if (!parse_addr_port(LOG_WARN,
|
||||||
if (! port)
|
wanted->value, &address, NULL, &port)) {
|
||||||
port = port_option;
|
int addr_matches = !strcasecmp(address, conn->address);
|
||||||
if (port == conn->port && addr_matches) {
|
tor_free(address);
|
||||||
line = wanted;
|
if (! port)
|
||||||
|
port = port_option;
|
||||||
|
if (port == conn->port && addr_matches) {
|
||||||
|
line = wanted;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
case AF_UNIX:
|
||||||
|
if (!strcasecmp(wanted->value, conn->address)) {
|
||||||
|
line = wanted;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tor_assert(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (! line) {
|
if (! line) {
|
||||||
@ -1080,8 +1240,31 @@ retry_listeners(int type, config_line_t *cfg,
|
|||||||
if (!never_open_conns) {
|
if (!never_open_conns) {
|
||||||
SMARTLIST_FOREACH(launch, config_line_t *, cfg_line,
|
SMARTLIST_FOREACH(launch, config_line_t *, cfg_line,
|
||||||
{
|
{
|
||||||
conn = connection_create_listener(cfg_line->value,
|
char *address = NULL;
|
||||||
(uint16_t) port_option, type);
|
struct sockaddr *listensockaddr;
|
||||||
|
|
||||||
|
switch (sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
listensockaddr = (struct sockaddr *)
|
||||||
|
create_inet_sockaddr(cfg_line->value,
|
||||||
|
(uint16_t) port_option,
|
||||||
|
&address);
|
||||||
|
break;
|
||||||
|
case AF_UNIX:
|
||||||
|
listensockaddr = (struct sockaddr *)
|
||||||
|
create_unix_sockaddr(cfg_line->value,
|
||||||
|
&address);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tor_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listensockaddr) {
|
||||||
|
conn = connection_create_listener(listensockaddr, type, address);
|
||||||
|
tor_free(address);
|
||||||
|
} else
|
||||||
|
conn = NULL;
|
||||||
|
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
r = -1;
|
r = -1;
|
||||||
} else {
|
} else {
|
||||||
@ -1115,32 +1298,45 @@ retry_all_listeners(smartlist_t *replaced_conns,
|
|||||||
|
|
||||||
if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
|
if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
|
||||||
options->ORPort, "0.0.0.0",
|
options->ORPort, "0.0.0.0",
|
||||||
replaced_conns, new_conns, options->ClientOnly)<0)
|
replaced_conns, new_conns, options->ClientOnly,
|
||||||
|
AF_INET)<0)
|
||||||
return -1;
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
|
if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
|
||||||
options->DirPort, "0.0.0.0",
|
options->DirPort, "0.0.0.0",
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_INET)<0)
|
||||||
return -1;
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
|
if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
|
||||||
options->SocksPort, "127.0.0.1",
|
options->SocksPort, "127.0.0.1",
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_INET)<0)
|
||||||
return -1;
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
|
if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
|
||||||
options->TransPort, "127.0.0.1",
|
options->TransPort, "127.0.0.1",
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_INET)<0)
|
||||||
return -1;
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NatdListenAddress,
|
if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NatdListenAddress,
|
||||||
options->NatdPort, "127.0.0.1",
|
options->NatdPort, "127.0.0.1",
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_INET)<0)
|
||||||
return -1;
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress,
|
if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress,
|
||||||
options->DNSPort, "127.0.0.1",
|
options->DNSPort, "127.0.0.1",
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_INET)<0)
|
||||||
return -1;
|
return -1;
|
||||||
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
|
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
|
||||||
options->ControlListenAddress,
|
options->ControlListenAddress,
|
||||||
options->ControlPort, "127.0.0.1",
|
options->ControlPort, "127.0.0.1",
|
||||||
replaced_conns, new_conns, 0)<0)
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_INET)<0)
|
||||||
|
return -1;
|
||||||
|
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
|
||||||
|
options->ControlSocket,
|
||||||
|
options->ControlSocket ? 1 : 0, NULL,
|
||||||
|
replaced_conns, new_conns, 0,
|
||||||
|
AF_UNIX)<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1916,7 +1916,7 @@ connection_ap_make_bridge(char *address, uint16_t port,
|
|||||||
log_notice(LD_APP,"Making internal anonymized tunnel to %s:%d ...",
|
log_notice(LD_APP,"Making internal anonymized tunnel to %s:%d ...",
|
||||||
safe_str(address),port); /* XXXX020 Downgrade back to info. */
|
safe_str(address),port); /* XXXX020 Downgrade back to info. */
|
||||||
|
|
||||||
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP));
|
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP, AF_INET));
|
||||||
conn->_base.linked = 1; /* so that we can add it safely below. */
|
conn->_base.linked = 1; /* so that we can add it safely below. */
|
||||||
|
|
||||||
/* populate conn->socks_request */
|
/* populate conn->socks_request */
|
||||||
@ -2210,7 +2210,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
|||||||
}
|
}
|
||||||
|
|
||||||
log_debug(LD_EXIT,"Creating new exit connection.");
|
log_debug(LD_EXIT,"Creating new exit connection.");
|
||||||
n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
|
n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT, AF_INET));
|
||||||
n_stream->_base.purpose = EXIT_PURPOSE_CONNECT;
|
n_stream->_base.purpose = EXIT_PURPOSE_CONNECT;
|
||||||
|
|
||||||
n_stream->stream_id = rh.stream_id;
|
n_stream->stream_id = rh.stream_id;
|
||||||
@ -2316,7 +2316,7 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
|
|||||||
* resolved; but if we didn't store them in a connection like this,
|
* resolved; but if we didn't store them in a connection like this,
|
||||||
* the housekeeping in dns.c would get way more complicated.)
|
* the housekeeping in dns.c would get way more complicated.)
|
||||||
*/
|
*/
|
||||||
dummy_conn = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
|
dummy_conn = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT, AF_INET));
|
||||||
dummy_conn->stream_id = rh.stream_id;
|
dummy_conn->stream_id = rh.stream_id;
|
||||||
dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
|
dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
|
||||||
rh.length);
|
rh.length);
|
||||||
@ -2450,7 +2450,7 @@ connection_exit_connect_dir(edge_connection_t *exitconn)
|
|||||||
|
|
||||||
exitconn->_base.state = EXIT_CONN_STATE_OPEN;
|
exitconn->_base.state = EXIT_CONN_STATE_OPEN;
|
||||||
|
|
||||||
dirconn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR));
|
dirconn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
|
||||||
|
|
||||||
dirconn->_base.addr = 0x7f000001;
|
dirconn->_base.addr = 0x7f000001;
|
||||||
dirconn->_base.port = 0;
|
dirconn->_base.port = 0;
|
||||||
|
@ -465,7 +465,7 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = TO_OR_CONN(connection_new(CONN_TYPE_OR));
|
conn = TO_OR_CONN(connection_new(CONN_TYPE_OR, AF_INET));
|
||||||
|
|
||||||
/* set up conn so it's got all the data we need to remember */
|
/* set up conn so it's got all the data we need to remember */
|
||||||
connection_or_init_conn_from_address(conn, addr, port, id_digest, 1);
|
connection_or_init_conn_from_address(conn, addr, port, id_digest, 1);
|
||||||
|
@ -339,7 +339,7 @@ spawn_cpuworker(void)
|
|||||||
tor_free(fdarray);
|
tor_free(fdarray);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
conn = connection_new(CONN_TYPE_CPUWORKER);
|
conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX);
|
||||||
|
|
||||||
set_socket_nonblocking(fd);
|
set_socket_nonblocking(fd);
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
|||||||
tor_assert(0);
|
tor_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR));
|
conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
|
||||||
|
|
||||||
/* set up conn so it's got all the data we need to remember */
|
/* set up conn so it's got all the data we need to remember */
|
||||||
conn->_base.addr = addr;
|
conn->_base.addr = addr;
|
||||||
|
@ -110,7 +110,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
|
|||||||
/* XXXX020 Send a stream event to the controller. */
|
/* XXXX020 Send a stream event to the controller. */
|
||||||
|
|
||||||
/* Make a new dummy AP connection, and attach the request to it. */
|
/* Make a new dummy AP connection, and attach the request to it. */
|
||||||
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP));
|
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP, AF_INET));
|
||||||
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
|
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
|
||||||
if (q->type == EVDNS_TYPE_A)
|
if (q->type == EVDNS_TYPE_A)
|
||||||
conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
|
conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
|
||||||
|
10
src/or/or.h
10
src/or/or.h
@ -56,6 +56,9 @@
|
|||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
#include <sys/un.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_SYS_TIME_H
|
#ifdef HAVE_SYS_TIME_H
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
@ -791,6 +794,9 @@ typedef struct connection_t {
|
|||||||
time_t timestamp_created; /**< When was this connection_t created? */
|
time_t timestamp_created; /**< When was this connection_t created? */
|
||||||
|
|
||||||
/* XXXX020 make this ipv6-capable */
|
/* XXXX020 make this ipv6-capable */
|
||||||
|
int sa_family; /**< Address family of this connection's socket. Usually
|
||||||
|
* AF_INET, but it can also be AF_UNIX, or in the future
|
||||||
|
* AF_INET6 */
|
||||||
uint32_t addr; /**< IP of the other side of the connection; used to identify
|
uint32_t addr; /**< IP of the other side of the connection; used to identify
|
||||||
* routers, along with port. */
|
* routers, along with port. */
|
||||||
uint16_t port; /**< If non-zero, port on the other end
|
uint16_t port; /**< If non-zero, port on the other end
|
||||||
@ -1825,6 +1831,8 @@ typedef struct {
|
|||||||
int TransPort;
|
int TransPort;
|
||||||
int NatdPort; /**< Port to listen on for transparent natd connections. */
|
int NatdPort; /**< Port to listen on for transparent natd connections. */
|
||||||
int ControlPort; /**< Port to listen on for control connections. */
|
int ControlPort; /**< Port to listen on for control connections. */
|
||||||
|
config_line_t * ControlSocket; /**< Unix Domain Socket to listen on
|
||||||
|
* for control connections. */
|
||||||
int DirPort; /**< Port to listen on for directory connections. */
|
int DirPort; /**< Port to listen on for directory connections. */
|
||||||
int DNSPort; /**< Port to listen on for DNS requests. */
|
int DNSPort; /**< Port to listen on for DNS requests. */
|
||||||
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
|
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
|
||||||
@ -2347,7 +2355,7 @@ or_options_t *options_new(void);
|
|||||||
const char *conn_type_to_string(int type);
|
const char *conn_type_to_string(int type);
|
||||||
const char *conn_state_to_string(int type, int state);
|
const char *conn_state_to_string(int type, int state);
|
||||||
|
|
||||||
connection_t *connection_new(int type);
|
connection_t *connection_new(int type, int sa_family);
|
||||||
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
|
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
|
||||||
void connection_unregister_events(connection_t *conn);
|
void connection_unregister_events(connection_t *conn);
|
||||||
void connection_free(connection_t *conn);
|
void connection_free(connection_t *conn);
|
||||||
|
Loading…
Reference in New Issue
Block a user