mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-19 19:42:30 +02:00
Management interface can now listen on a unix
domain socket, for example: management /tmp/openvpn unix Also added management-client-user and management-client-group directives to control which processes are allowed to connect to the socket. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3396 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
b0cb50e7e7
commit
bb564a5950
8
basic.h
8
basic.h
@ -26,9 +26,17 @@
|
||||
#define BASIC_H
|
||||
|
||||
/* bool definitions */
|
||||
#ifndef bool
|
||||
#define bool int
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define BOOL_CAST(x) ((x) ? (true) : (false))
|
||||
|
||||
|
@ -339,7 +339,7 @@ AC_CHECK_HEADERS(fcntl.h stdlib.h dnl
|
||||
|
||||
if test "${WIN32}" != "yes"; then
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/time.h sys/socket.h sys/ioctl.h sys/stat.h dnl
|
||||
AC_CHECK_HEADERS(sys/time.h sys/socket.h sys/un.h sys/ioctl.h sys/stat.h dnl
|
||||
sys/mman.h fcntl.h sys/file.h stdlib.h stdint.h dnl
|
||||
stdarg.h unistd.h signal.h stdio.h string.h dnl
|
||||
strings.h ctype.h errno.h syslog.h pwd.h grp.h dnl
|
||||
@ -464,7 +464,7 @@ AC_CHECK_FUNCS(daemon chroot getpwnam setuid nice system getpid dup dup2 dnl
|
||||
getpass strerror syslog openlog mlockall getgrnam setgid dnl
|
||||
setgroups stat flock readv writev time dnl
|
||||
setsid chdir putenv getpeername unlink dnl
|
||||
chsize ftruncate execve)
|
||||
chsize ftruncate execve getpeereid umask)
|
||||
|
||||
# Windows use stdcall for winsock so we cannot auto detect these
|
||||
m4_define([SOCKET_FUNCS], [socket recv recvfrom send sendto listen dnl
|
||||
|
@ -54,6 +54,32 @@
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Addr8
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/libc-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
fun:__libc_dlopen_mode
|
||||
fun:__nss_lookup_function
|
||||
obj:/lib/libc-2.5.so
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Addr8
|
||||
@ -175,6 +201,79 @@
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Addr8
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/libc-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
fun:__libc_dlopen_mode
|
||||
fun:__nss_lookup_function
|
||||
obj:/lib/libc-2.7.so
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
fun:BN_div
|
||||
fun:BN_MONT_CTX_set
|
||||
fun:BN_MONT_CTX_set_locked
|
||||
obj:/usr/lib/libcrypto.so.0.9.8
|
||||
fun:ssl3_ctx_ctrl
|
||||
fun:init_ssl
|
||||
fun:init_instance
|
||||
fun:init_instance_handle_signals
|
||||
fun:tunnel_server_udp
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
fun:BN_div
|
||||
fun:BN_nnmod
|
||||
fun:BN_mod_inverse
|
||||
fun:BN_MONT_CTX_set
|
||||
fun:BN_MONT_CTX_set_locked
|
||||
obj:/usr/lib/libcrypto.so.0.9.8
|
||||
fun:ssl3_ctx_ctrl
|
||||
fun:init_ssl
|
||||
fun:init_instance
|
||||
fun:init_instance_handle_signals
|
||||
fun:tunnel_server_udp
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
fun:BN_mod_inverse
|
||||
fun:BN_MONT_CTX_set
|
||||
fun:BN_MONT_CTX_set_locked
|
||||
obj:/usr/lib/libcrypto.so.0.9.8
|
||||
fun:ssl3_ctx_ctrl
|
||||
fun:init_ssl
|
||||
fun:init_instance
|
||||
fun:init_instance_handle_signals
|
||||
fun:tunnel_server_udp
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
@ -420,6 +519,26 @@
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
obj:/lib/libc-2.5.so
|
||||
obj:/lib/ld-2.5.so
|
||||
fun:__libc_dlopen_mode
|
||||
fun:__nss_lookup_function
|
||||
obj:/lib/libc-2.5.so
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
@ -518,6 +637,21 @@
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:__nss_lookup_function
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
@ -583,6 +717,22 @@
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:tsearch
|
||||
fun:__nss_lookup_function
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
@ -636,3 +786,122 @@
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
obj:/lib/libc-2.5.so
|
||||
fun:__nss_database_lookup
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
obj:/lib/libc-2.7.so
|
||||
fun:__nss_database_lookup
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getpwnam_r
|
||||
fun:getpwnam
|
||||
fun:get_user
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Addr8
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/libc-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
fun:__libc_dlopen_mode
|
||||
fun:__nss_lookup_function
|
||||
obj:/lib/libc-2.7.so
|
||||
fun:getgrnam_r
|
||||
fun:getgrnam
|
||||
fun:get_group
|
||||
fun:do_init_first_time
|
||||
fun:init_instance
|
||||
fun:init_instance_handle_signals
|
||||
fun:tunnel_server_udp
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
obj:/lib/libc-2.7.so
|
||||
fun:__nss_database_lookup
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getgrnam_r
|
||||
fun:getgrnam
|
||||
fun:get_group
|
||||
fun:do_init_first_time
|
||||
fun:init_instance
|
||||
fun:init_instance_handle_signals
|
||||
fun:tunnel_server_udp
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Addr8
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
obj:/lib/libc-2.7.so
|
||||
obj:/lib/ld-2.7.so
|
||||
fun:__libc_dlopen_mode
|
||||
fun:__nss_lookup_function
|
||||
obj:/lib/libc-2.7.so
|
||||
fun:getgrnam_r
|
||||
fun:getgrnam
|
||||
fun:get_group
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:tsearch
|
||||
fun:__nss_lookup_function
|
||||
obj:*
|
||||
obj:*
|
||||
fun:getgrnam_r
|
||||
fun:getgrnam
|
||||
fun:get_group
|
||||
fun:management_open
|
||||
fun:open_management
|
||||
fun:main
|
||||
}
|
||||
|
@ -1290,11 +1290,11 @@ io_wait_dowork (struct context *c, const unsigned int flags)
|
||||
struct event_set_return esr[4];
|
||||
|
||||
/* These shifts all depend on EVENT_READ and EVENT_WRITE */
|
||||
static const int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */
|
||||
static const int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */
|
||||
static const int err_shift = 4; /* depends on ES_ERROR */
|
||||
static int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */
|
||||
static int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */
|
||||
static int err_shift = 4; /* depends on ES_ERROR */
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
static const int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */
|
||||
static int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
2
init.c
2
init.c
@ -2670,6 +2670,8 @@ open_management (struct context *c)
|
||||
c->options.management_addr,
|
||||
c->options.management_port,
|
||||
c->options.management_user_pass,
|
||||
c->options.management_client_user,
|
||||
c->options.management_client_group,
|
||||
c->options.management_log_history_cache,
|
||||
c->options.management_echo_buffer_size,
|
||||
c->options.management_state_buffer_size,
|
||||
|
168
manage.c
168
manage.c
@ -225,6 +225,15 @@ man_prompt (struct management *man)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
man_delete_unix_socket (struct management *man)
|
||||
{
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
if (man->settings.flags & MF_LISTEN_UNIX)
|
||||
socket_delete_unix (&man->settings.local_unix);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
man_close_socket (struct management *man, const socket_descriptor_t sd)
|
||||
{
|
||||
@ -1231,9 +1240,18 @@ man_new_connection_post (struct management *man, const char *description)
|
||||
man_start_ne32 (man);
|
||||
#endif
|
||||
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
|
||||
description,
|
||||
print_sockaddr (&man->settings.local, &gc));
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
if (man->settings.flags & MF_LISTEN_UNIX)
|
||||
{
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
|
||||
description,
|
||||
sockaddr_unix_name (&man->settings.local_unix, "NULL"));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
|
||||
description,
|
||||
print_sockaddr (&man->settings.local, &gc));
|
||||
|
||||
buffer_list_reset (man->connection.out);
|
||||
|
||||
@ -1249,11 +1267,46 @@ static void
|
||||
man_accept (struct management *man)
|
||||
{
|
||||
struct link_socket_actual act;
|
||||
CLEAR (act);
|
||||
|
||||
/*
|
||||
* Accept the TCP client.
|
||||
* Accept the TCP or Unix domain socket client.
|
||||
*/
|
||||
man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &act, false);
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
if (man->settings.flags & MF_LISTEN_UNIX)
|
||||
{
|
||||
struct sockaddr_un remote;
|
||||
man->connection.sd_cli = socket_accept_unix (man->connection.sd_top, &remote);
|
||||
if (socket_defined (man->connection.sd_cli) && (man->settings.client_uid != -1 || man->settings.client_gid != -1))
|
||||
{
|
||||
static const char err_prefix[] = "MANAGEMENT: unix domain socket client connection rejected --";
|
||||
int uid, gid;
|
||||
if (unix_socket_get_peer_uid_gid (man->connection.sd_cli, &uid, &gid))
|
||||
{
|
||||
if (man->settings.client_uid != -1 && man->settings.client_uid != uid)
|
||||
{
|
||||
msg (D_MANAGEMENT, "%s UID of socket peer (%d) doesn't match required value (%d) as given by --management-client-user",
|
||||
err_prefix, uid, man->settings.client_uid);
|
||||
sd_close (&man->connection.sd_cli);
|
||||
}
|
||||
if (man->settings.client_gid != -1 && man->settings.client_gid != gid)
|
||||
{
|
||||
msg (D_MANAGEMENT, "%s GID of socket peer (%d) doesn't match required value (%d) as given by --management-client-group",
|
||||
err_prefix, gid, man->settings.client_gid);
|
||||
sd_close (&man->connection.sd_cli);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msg (D_MANAGEMENT, "%s cannot get UID/GID of socket peer", err_prefix);
|
||||
sd_close (&man->connection.sd_cli);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &act, false);
|
||||
|
||||
if (socket_defined (man->connection.sd_cli))
|
||||
{
|
||||
man->connection.remote = act.dest;
|
||||
@ -1285,12 +1338,19 @@ man_listen (struct management *man)
|
||||
*/
|
||||
if (man->connection.sd_top == SOCKET_UNDEFINED)
|
||||
{
|
||||
man->connection.sd_top = create_socket_tcp ();
|
||||
|
||||
/*
|
||||
* Bind socket
|
||||
*/
|
||||
socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
if (man->settings.flags & MF_LISTEN_UNIX)
|
||||
{
|
||||
man_delete_unix_socket (man);
|
||||
man->connection.sd_top = create_socket_unix ();
|
||||
socket_bind_unix (man->connection.sd_top, &man->settings.local_unix, "MANAGEMENT");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
man->connection.sd_top = create_socket_tcp ();
|
||||
socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
|
||||
}
|
||||
|
||||
/*
|
||||
* Listen for connection
|
||||
@ -1304,8 +1364,16 @@ man_listen (struct management *man)
|
||||
set_nonblock (man->connection.sd_top);
|
||||
set_cloexec (man->connection.sd_top);
|
||||
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
|
||||
print_sockaddr (&man->settings.local, &gc));
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
if (man->settings.flags & MF_LISTEN_UNIX)
|
||||
{
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: unix domain socket listening on %s",
|
||||
sockaddr_unix_name (&man->settings.local_unix, "NULL"));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
|
||||
print_sockaddr (&man->settings.local, &gc));
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
@ -1645,6 +1713,8 @@ man_settings_init (struct man_settings *ms,
|
||||
const char *addr,
|
||||
const int port,
|
||||
const char *pass_file,
|
||||
const char *client_user,
|
||||
const char *client_group,
|
||||
const int log_history_cache,
|
||||
const int echo_buffer_size,
|
||||
const int state_buffer_size,
|
||||
@ -1657,6 +1727,8 @@ man_settings_init (struct man_settings *ms,
|
||||
CLEAR (*ms);
|
||||
|
||||
ms->flags = flags;
|
||||
ms->client_uid = -1;
|
||||
ms->client_gid = -1;
|
||||
|
||||
/*
|
||||
* Get username/password
|
||||
@ -1664,27 +1736,54 @@ man_settings_init (struct man_settings *ms,
|
||||
if (pass_file)
|
||||
get_user_pass (&ms->up, pass_file, "Management", GET_USER_PASS_PASSWORD_ONLY);
|
||||
|
||||
/*
|
||||
* lookup client UID/GID if specified
|
||||
*/
|
||||
if (client_user)
|
||||
{
|
||||
struct user_state s;
|
||||
get_user (client_user, &s);
|
||||
ms->client_uid = user_state_uid (&s);
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: client_uid=%d", ms->client_uid);
|
||||
ASSERT (ms->client_uid >= 0);
|
||||
}
|
||||
if (client_group)
|
||||
{
|
||||
struct group_state s;
|
||||
get_group (client_group, &s);
|
||||
ms->client_gid = group_state_gid (&s);
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: client_gid=%d", ms->client_gid);
|
||||
ASSERT (ms->client_gid >= 0);
|
||||
}
|
||||
|
||||
ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL);
|
||||
|
||||
/*
|
||||
* Initialize socket address
|
||||
*/
|
||||
ms->local.sa.sin_family = AF_INET;
|
||||
ms->local.sa.sin_addr.s_addr = 0;
|
||||
ms->local.sa.sin_port = htons (port);
|
||||
|
||||
/*
|
||||
* Run management over tunnel, or
|
||||
* separate channel?
|
||||
*/
|
||||
if (streq (addr, "tunnel") && !(flags & MF_CONNECT_AS_CLIENT))
|
||||
{
|
||||
ms->management_over_tunnel = true;
|
||||
}
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
if (ms->flags & MF_LISTEN_UNIX)
|
||||
sockaddr_unix_init (&ms->local_unix, addr);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ms->local.sa.sin_addr.s_addr = getaddr
|
||||
(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
|
||||
/*
|
||||
* Initialize socket address
|
||||
*/
|
||||
ms->local.sa.sin_family = AF_INET;
|
||||
ms->local.sa.sin_addr.s_addr = 0;
|
||||
ms->local.sa.sin_port = htons (port);
|
||||
|
||||
/*
|
||||
* Run management over tunnel, or
|
||||
* separate channel?
|
||||
*/
|
||||
if (streq (addr, "tunnel") && !(flags & MF_CONNECT_AS_CLIENT))
|
||||
{
|
||||
ms->management_over_tunnel = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ms->local.sa.sin_addr.s_addr = getaddr
|
||||
(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1764,7 +1863,10 @@ man_connection_close (struct management *man)
|
||||
net_event_win32_close (&mc->ne32);
|
||||
#endif
|
||||
if (socket_defined (mc->sd_top))
|
||||
man_close_socket (man, mc->sd_top);
|
||||
{
|
||||
man_close_socket (man, mc->sd_top);
|
||||
man_delete_unix_socket (man);
|
||||
}
|
||||
if (socket_defined (mc->sd_cli))
|
||||
man_close_socket (man, mc->sd_cli);
|
||||
if (mc->in)
|
||||
@ -1798,6 +1900,8 @@ management_open (struct management *man,
|
||||
const char *addr,
|
||||
const int port,
|
||||
const char *pass_file,
|
||||
const char *client_user,
|
||||
const char *client_group,
|
||||
const int log_history_cache,
|
||||
const int echo_buffer_size,
|
||||
const int state_buffer_size,
|
||||
@ -1815,6 +1919,8 @@ management_open (struct management *man,
|
||||
addr,
|
||||
port,
|
||||
pass_file,
|
||||
client_user,
|
||||
client_group,
|
||||
log_history_cache,
|
||||
echo_buffer_size,
|
||||
state_buffer_size,
|
||||
|
9
manage.h
9
manage.h
@ -202,12 +202,17 @@ struct man_settings {
|
||||
bool defined;
|
||||
unsigned int flags; /* MF_x flags */
|
||||
struct openvpn_sockaddr local;
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
struct sockaddr_un local_unix;
|
||||
#endif
|
||||
bool management_over_tunnel;
|
||||
struct user_pass up;
|
||||
int log_history_cache;
|
||||
int echo_buffer_size;
|
||||
int state_buffer_size;
|
||||
char *write_peer_info_file;
|
||||
int client_uid;
|
||||
int client_gid;
|
||||
|
||||
/* flags for handling the management interface "signal" command */
|
||||
# define MANSIG_IGNORE_USR1_HUP (1<<0)
|
||||
@ -295,10 +300,14 @@ struct management *management_init (void);
|
||||
#ifdef MANAGEMENT_PF
|
||||
# define MF_CLIENT_PF (1<<7)
|
||||
#endif
|
||||
# define MF_LISTEN_UNIX (1<<8)
|
||||
|
||||
bool management_open (struct management *man,
|
||||
const char *addr,
|
||||
const int port,
|
||||
const char *pass_file,
|
||||
const char *client_user,
|
||||
const char *client_group,
|
||||
const int log_history_cache,
|
||||
const int echo_buffer_size,
|
||||
const int state_buffer_size,
|
||||
|
4
misc.c
4
misc.c
@ -82,7 +82,7 @@ get_user (const char *username, struct user_state *state)
|
||||
state->username = username;
|
||||
ret = true;
|
||||
#else
|
||||
msg (M_FATAL, "Sorry but I can't setuid to '%s' because this operating system doesn't appear to support the getpwname() or setuid() system calls", username);
|
||||
msg (M_FATAL, "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
@ -117,7 +117,7 @@ get_group (const char *groupname, struct group_state *state)
|
||||
state->groupname = groupname;
|
||||
ret = true;
|
||||
#else
|
||||
msg (M_FATAL, "Sorry but I can't setgid to '%s' because this operating system doesn't appear to support the getgrnam() or setgid() system calls", groupname);
|
||||
msg (M_FATAL, "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
|
26
misc.h
26
misc.h
@ -119,7 +119,7 @@ void warn_if_group_others_accessible(const char* filename);
|
||||
|
||||
/* interpret the status code returned by system()/execve() */
|
||||
bool system_ok(int);
|
||||
int system_executed (int stat);
|
||||
bool system_executed (int stat);
|
||||
const char *system_error_message (int, struct gc_arena *gc);
|
||||
|
||||
/* wrapper around the execve() call */
|
||||
@ -330,4 +330,28 @@ void argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* Extract UID or GID
|
||||
*/
|
||||
|
||||
static inline int
|
||||
user_state_uid (const struct user_state *s)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
if (s->pw)
|
||||
return s->pw->pw_uid;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
group_state_gid (const struct group_state *s)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
if (s->gr)
|
||||
return s->gr->gr_gid;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
27
openvpn.8
27
openvpn.8
@ -181,7 +181,9 @@ openvpn \- secure IP tunnel daemon.
|
||||
[\ \fB\-\-suppress-timestamps\fR\ ]
|
||||
[\ \fB\-\-lport\fR\ \fIport\fR\ ]
|
||||
[\ \fB\-\-management\-client\-auth\fR\ ]
|
||||
[\ \fB\-\-management\-client\-group\fR\ \fIg\fR\ ]
|
||||
[\ \fB\-\-management\-client\-pf\fR\ ]
|
||||
[\ \fB\-\-management\-client\-user\fR\ \fIu\fR\ ]
|
||||
[\ \fB\-\-management\-forget\-disconnect\fR\ ]
|
||||
[\ \fB\-\-management\-hold\fR\ ]
|
||||
[\ \fB\-\-management\-log\-cache\fR\ \fIn\fR\ ]
|
||||
@ -2455,6 +2457,19 @@ or "stdin" to prompt from standard input. The password
|
||||
provided will set the password which TCP clients will need
|
||||
to provide in order to access management functions.
|
||||
|
||||
The management interface can also listen on a unix domain socket,
|
||||
for those platforms that support it. To use a unix domain socket, specify
|
||||
the unix socket pathname in place of
|
||||
.B IP
|
||||
and set
|
||||
.B port
|
||||
to 'unix'. While the default behavior is to create a unix domain socket
|
||||
that may be connected to by any process, the
|
||||
.B --management-client-user
|
||||
and
|
||||
.B --management-client-group
|
||||
directives can be used to restrict access.
|
||||
|
||||
The management interface provides a special mode where the TCP
|
||||
management link can operate over the tunnel itself. To enable this mode,
|
||||
set
|
||||
@ -2532,6 +2547,18 @@ filter file for each connecting client. See management-notes.txt
|
||||
in OpenVPN distribution for detailed notes.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --management-client-user u
|
||||
When the management interface is listening on a unix domain socket,
|
||||
only allow connections from user
|
||||
.B u.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --management-client-group g
|
||||
When the management interface is listening on a unix domain socket,
|
||||
only allow connections from group
|
||||
.B g.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --plugin module-pathname [init-string]
|
||||
Load plug-in module from the file
|
||||
.B module-pathname,
|
||||
|
50
options.c
50
options.c
@ -311,6 +311,10 @@ static const char usage_message[] =
|
||||
"--management ip port [pass] : Enable a TCP server on ip:port to handle\n"
|
||||
" management functions. pass is a password file\n"
|
||||
" or 'stdin' to prompt from console.\n"
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
" To listen on a unix domain socket, specific the pathname\n"
|
||||
" in place of ip and use 'unix' as the port number.\n"
|
||||
#endif
|
||||
"--management-client : Management interface will connect as a TCP client to\n"
|
||||
" ip/port rather than listen as a TCP server.\n"
|
||||
"--management-query-passwords : Query management channel for private key\n"
|
||||
@ -322,6 +326,12 @@ static const char usage_message[] =
|
||||
" event occurs.\n"
|
||||
"--management-log-cache n : Cache n lines of log file history for usage\n"
|
||||
" by the management channel.\n"
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
"--management-client-user u : When management interface is a unix socket, only\n"
|
||||
" allow connections from user u.\n"
|
||||
"--management-client-group g : When management interface is a unix socket, only\n"
|
||||
" allow connections from group g.\n"
|
||||
#endif
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
"--management-client-auth : gives management interface client the responsibility\n"
|
||||
" to authenticate clients after their client certificate\n"
|
||||
@ -1240,6 +1250,8 @@ show_settings (const struct options *o)
|
||||
SHOW_INT (management_log_history_cache);
|
||||
SHOW_INT (management_echo_buffer_size);
|
||||
SHOW_STR (management_write_peer_info_file);
|
||||
SHOW_STR (management_client_user);
|
||||
SHOW_STR (management_client_group);
|
||||
SHOW_INT (management_flags);
|
||||
#endif
|
||||
#ifdef ENABLE_PLUGIN
|
||||
@ -1554,6 +1566,14 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
||||
|| options->management_write_peer_info_file
|
||||
|| options->management_log_history_cache != defaults.management_log_history_cache))
|
||||
msg (M_USAGE, "--management is not specified, however one or more options which modify the behavior of --management were specified");
|
||||
|
||||
if ((options->management_flags & (MF_LISTEN_UNIX|MF_CONNECT_AS_CLIENT))
|
||||
== (MF_LISTEN_UNIX|MF_CONNECT_AS_CLIENT))
|
||||
msg (M_USAGE, "--management-client does not support unix domain sockets");
|
||||
|
||||
if ((options->management_client_user || options->management_client_group)
|
||||
&& !(options->management_flags & MF_LISTEN_UNIX))
|
||||
msg (M_USAGE, "--management-client-(user|group) can only be used on unix domain sockets");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -3319,14 +3339,26 @@ add_option (struct options *options,
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
else if (streq (p[0], "management") && p[1] && p[2])
|
||||
{
|
||||
int port;
|
||||
int port = 0;
|
||||
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
port = atoi (p[2]);
|
||||
if (!legal_ipv4_port (port))
|
||||
if (streq (p[2], "unix"))
|
||||
{
|
||||
msg (msglevel, "port number associated with --management directive is out of range");
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
options->management_flags |= MF_LISTEN_UNIX;
|
||||
#else
|
||||
msg (msglevel, "MANAGEMENT: this platform does not support unix domain sockets");
|
||||
goto err;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
port = atoi (p[2]);
|
||||
if (!legal_ipv4_port (port))
|
||||
{
|
||||
msg (msglevel, "port number associated with --management directive is out of range");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
options->management_addr = p[1];
|
||||
@ -3336,6 +3368,16 @@ add_option (struct options *options,
|
||||
options->management_user_pass = p[3];
|
||||
}
|
||||
}
|
||||
else if (streq (p[0], "management-client-user") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->management_client_user = p[1];
|
||||
}
|
||||
else if (streq (p[0], "management-client-group") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->management_client_group = p[1];
|
||||
}
|
||||
else if (streq (p[0], "management-query-passwords"))
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
|
@ -319,6 +319,9 @@ struct options
|
||||
int management_state_buffer_size;
|
||||
const char *management_write_peer_info_file;
|
||||
|
||||
const char *management_client_user;
|
||||
const char *management_client_group;
|
||||
|
||||
/* Mask of MF_ values of manage.h */
|
||||
unsigned int management_flags;
|
||||
#endif
|
||||
@ -610,9 +613,9 @@ char *options_string (const struct options *o,
|
||||
bool remote,
|
||||
struct gc_arena *gc);
|
||||
|
||||
int options_cmp_equal_safe (char *actual, const char *expected, size_t actual_n);
|
||||
bool options_cmp_equal_safe (char *actual, const char *expected, size_t actual_n);
|
||||
void options_warning_safe (char *actual, const char *expected, size_t actual_n);
|
||||
int options_cmp_equal (char *actual, const char *expected);
|
||||
bool options_cmp_equal (char *actual, const char *expected);
|
||||
void options_warning (char *actual, const char *expected);
|
||||
|
||||
#endif
|
||||
|
122
socket.c
122
socket.c
@ -2627,3 +2627,125 @@ socket_set (struct link_socket *s,
|
||||
}
|
||||
return rwflags;
|
||||
}
|
||||
|
||||
void
|
||||
sd_close (socket_descriptor_t *sd)
|
||||
{
|
||||
if (sd && socket_defined (*sd))
|
||||
{
|
||||
openvpn_close_socket (*sd);
|
||||
*sd = SOCKET_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
|
||||
/*
|
||||
* code for unix domain sockets
|
||||
*/
|
||||
|
||||
const char *
|
||||
sockaddr_unix_name (const struct sockaddr_un *local, const char *null)
|
||||
{
|
||||
if (local && local->sun_family == PF_UNIX)
|
||||
return local->sun_path;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
socket_descriptor_t
|
||||
create_socket_unix (void)
|
||||
{
|
||||
socket_descriptor_t sd;
|
||||
|
||||
if ((sd = socket (PF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
msg (M_SOCKERR, "Cannot create unix domain socket");
|
||||
return sd;
|
||||
}
|
||||
|
||||
void
|
||||
socket_bind_unix (socket_descriptor_t sd,
|
||||
struct sockaddr_un *local,
|
||||
const char *prefix)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
|
||||
#ifdef HAVE_UMASK
|
||||
const mode_t orig_umask = umask (0);
|
||||
#endif
|
||||
|
||||
if (bind (sd, (struct sockaddr *) local, sizeof (struct sockaddr_un)))
|
||||
{
|
||||
const int errnum = openvpn_errno_socket ();
|
||||
msg (M_FATAL, "%s: Socket bind[%d] failed on unix domain socket %s: %s",
|
||||
prefix,
|
||||
(int)sd,
|
||||
sockaddr_unix_name (local, "NULL"),
|
||||
strerror_ts (errnum, &gc));
|
||||
}
|
||||
|
||||
#ifdef HAVE_UMASK
|
||||
umask (orig_umask);
|
||||
#endif
|
||||
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
socket_descriptor_t
|
||||
socket_accept_unix (socket_descriptor_t sd,
|
||||
struct sockaddr_un *remote)
|
||||
{
|
||||
socklen_t remote_len = sizeof (struct sockaddr_un);
|
||||
socket_descriptor_t ret;
|
||||
|
||||
CLEAR (*remote);
|
||||
ret = accept (sd, (struct sockaddr *) remote, &remote_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
sockaddr_unix_init (struct sockaddr_un *local, const char *path)
|
||||
{
|
||||
local->sun_family = PF_UNIX;
|
||||
strncpynt (local->sun_path, path, sizeof (local->sun_path));
|
||||
}
|
||||
|
||||
void
|
||||
socket_delete_unix (const struct sockaddr_un *local)
|
||||
{
|
||||
const char *name = sockaddr_unix_name (local, NULL);
|
||||
#ifdef HAVE_UNLINK
|
||||
if (name && strlen (name))
|
||||
unlink (name);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *gid)
|
||||
{
|
||||
#ifdef HAVE_GETPEEREID
|
||||
uid_t u;
|
||||
gid_t g;
|
||||
if (getpeereid (sd, &u, &g) == -1)
|
||||
return false;
|
||||
if (uid)
|
||||
*uid = u;
|
||||
if (gid)
|
||||
*gid = g;
|
||||
return true;
|
||||
#elif defined(SO_PEERCRED)
|
||||
struct ucred peercred;
|
||||
socklen_t so_len = sizeof(peercred);
|
||||
if (getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1)
|
||||
return false;
|
||||
if (uid)
|
||||
*uid = peercred.uid;
|
||||
if (gid)
|
||||
*gid = peercred.gid;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
23
socket.h
23
socket.h
@ -322,6 +322,8 @@ void frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto);
|
||||
|
||||
void link_socket_close (struct link_socket *sock);
|
||||
|
||||
void sd_close (socket_descriptor_t *sd);
|
||||
|
||||
#define PS_SHOW_PORT_IF_DEFINED (1<<0)
|
||||
#define PS_SHOW_PORT (1<<1)
|
||||
#define PS_SHOW_PKTINFO (1<<2)
|
||||
@ -408,6 +410,27 @@ socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
|
||||
struct link_socket_actual *act,
|
||||
const bool nowait);
|
||||
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
|
||||
socket_descriptor_t create_socket_unix (void);
|
||||
|
||||
void socket_bind_unix (socket_descriptor_t sd,
|
||||
struct sockaddr_un *local,
|
||||
const char *prefix);
|
||||
|
||||
socket_descriptor_t socket_accept_unix (socket_descriptor_t sd,
|
||||
struct sockaddr_un *remote);
|
||||
|
||||
void sockaddr_unix_init (struct sockaddr_un *local, const char *path);
|
||||
|
||||
const char *sockaddr_unix_name (const struct sockaddr_un *local, const char *null);
|
||||
|
||||
void socket_delete_unix (const struct sockaddr_un *local);
|
||||
|
||||
bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *gid);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DNS resolution
|
||||
*/
|
||||
|
13
syshead.h
13
syshead.h
@ -88,6 +88,10 @@
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
@ -515,6 +519,15 @@ socket_defined (const socket_descriptor_t sd)
|
||||
#define ENABLE_PF
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do we support Unix domain sockets?
|
||||
*/
|
||||
#if defined(PF_UNIX) && !defined(WIN32)
|
||||
#define UNIX_SOCK_SUPPORT 1
|
||||
#else
|
||||
#define UNIX_SOCK_SUPPORT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't compile the struct buffer_list code unless something needs it
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
dnl define the OpenVPN version
|
||||
define(PRODUCT_VERSION,[2.1_rc12])
|
||||
define(PRODUCT_VERSION,[2.1_rc12a])
|
||||
dnl define the TAP version
|
||||
define(PRODUCT_TAP_ID,[tap0901])
|
||||
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
|
||||
|
Loading…
Reference in New Issue
Block a user