aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--manage.c112
-rw-r--r--manage.h2
-rw-r--r--options.c8
-rw-r--r--socket.c10
-rw-r--r--socket.h3
5 files changed, 91 insertions, 44 deletions
diff --git a/manage.c b/manage.c
index cff4348..1dd2825 100644
--- a/manage.c
+++ b/manage.c
@@ -230,7 +230,7 @@ static void
man_delete_unix_socket (struct management *man)
{
#if UNIX_SOCK_SUPPORT
- if (man->settings.flags & MF_LISTEN_UNIX)
+ if ((man->settings.flags & (MF_UNIX_SOCK|MF_CONNECT_AS_CLIENT)) == MF_UNIX_SOCK)
socket_delete_unix (&man->settings.local_unix);
#endif
}
@@ -1287,7 +1287,7 @@ man_new_connection_post (struct management *man, const char *description)
#endif
#if UNIX_SOCK_SUPPORT
- if (man->settings.flags & MF_LISTEN_UNIX)
+ if (man->settings.flags & MF_UNIX_SOCK)
{
msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
description,
@@ -1309,6 +1309,39 @@ man_new_connection_post (struct management *man, const char *description)
gc_free (&gc);
}
+#if UNIX_SOCK_SUPPORT
+static bool
+man_verify_unix_peer_uid_gid (struct management *man, const socket_descriptor_t sd)
+{
+ if (socket_defined (sd) && (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);
+ return false;
+ }
+ 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);
+ return false;
+ }
+ }
+ else
+ {
+ msg (D_MANAGEMENT, "%s cannot get UID/GID of socket peer", err_prefix);
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
static void
man_accept (struct management *man)
{
@@ -1319,35 +1352,12 @@ man_accept (struct management *man)
* Accept the TCP or Unix domain socket client.
*/
#if UNIX_SOCK_SUPPORT
- if (man->settings.flags & MF_LISTEN_UNIX)
+ if (man->settings.flags & MF_UNIX_SOCK)
{
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);
- }
- }
+ if (!man_verify_unix_peer_uid_gid (man, man->connection.sd_cli))
+ sd_close (&man->connection.sd_cli);
}
else
#endif
@@ -1385,7 +1395,7 @@ man_listen (struct management *man)
if (man->connection.sd_top == SOCKET_UNDEFINED)
{
#if UNIX_SOCK_SUPPORT
- if (man->settings.flags & MF_LISTEN_UNIX)
+ if (man->settings.flags & MF_UNIX_SOCK)
{
man_delete_unix_socket (man);
man->connection.sd_top = create_socket_unix ();
@@ -1411,7 +1421,7 @@ man_listen (struct management *man)
set_cloexec (man->connection.sd_top);
#if UNIX_SOCK_SUPPORT
- if (man->settings.flags & MF_LISTEN_UNIX)
+ if (man->settings.flags & MF_UNIX_SOCK)
{
msg (D_MANAGEMENT, "MANAGEMENT: unix domain socket listening on %s",
sockaddr_unix_name (&man->settings.local_unix, "NULL"));
@@ -1442,12 +1452,30 @@ man_connect (struct management *man)
man->connection.state = MS_INITIAL;
man->connection.sd_top = SOCKET_UNDEFINED;
- man->connection.sd_cli = create_socket_tcp ();
-
- status = openvpn_connect (man->connection.sd_cli,
- &man->settings.local,
- 5,
- &signal_received);
+#if UNIX_SOCK_SUPPORT
+ if (man->settings.flags & MF_UNIX_SOCK)
+ {
+ man->connection.sd_cli = create_socket_unix ();
+ status = socket_connect_unix (man->connection.sd_cli, &man->settings.local_unix);
+ if (!status && !man_verify_unix_peer_uid_gid (man, man->connection.sd_cli))
+ {
+#ifdef EPERM
+ status = EPERM;
+#else
+ status = 1;
+#endif
+ sd_close (&man->connection.sd_cli);
+ }
+ }
+ else
+#endif
+ {
+ man->connection.sd_cli = create_socket_tcp ();
+ status = openvpn_connect (man->connection.sd_cli,
+ &man->settings.local,
+ 5,
+ &signal_received);
+ }
if (signal_received)
{
@@ -1457,6 +1485,16 @@ man_connect (struct management *man)
if (status)
{
+#if UNIX_SOCK_SUPPORT
+ if (man->settings.flags & MF_UNIX_SOCK)
+ {
+ msg (D_LINK_ERRORS,
+ "MANAGEMENT: connect to unix socket %s failed: %s",
+ sockaddr_unix_name (&man->settings.local_unix, "NULL"),
+ strerror_ts (status, &gc));
+ }
+ else
+#endif
msg (D_LINK_ERRORS,
"MANAGEMENT: connect to %s failed: %s",
print_sockaddr (&man->settings.local, &gc),
@@ -1805,7 +1843,7 @@ man_settings_init (struct man_settings *ms,
ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL);
#if UNIX_SOCK_SUPPORT
- if (ms->flags & MF_LISTEN_UNIX)
+ if (ms->flags & MF_UNIX_SOCK)
sockaddr_unix_init (&ms->local_unix, addr);
else
#endif
diff --git a/manage.h b/manage.h
index 66fb7d1..9114184 100644
--- a/manage.h
+++ b/manage.h
@@ -307,7 +307,7 @@ struct management *management_init (void);
#ifdef MANAGEMENT_PF
# define MF_CLIENT_PF (1<<7)
#endif
-# define MF_LISTEN_UNIX (1<<8)
+# define MF_UNIX_SOCK (1<<8)
bool management_open (struct management *man,
const char *addr,
diff --git a/options.c b/options.c
index 758a078..f2c7da8 100644
--- a/options.c
+++ b/options.c
@@ -1585,12 +1585,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|| 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))
+ && !(options->management_flags & MF_UNIX_SOCK))
msg (M_USAGE, "--management-client-(user|group) can only be used on unix domain sockets");
#endif
@@ -3391,7 +3387,7 @@ add_option (struct options *options,
if (streq (p[2], "unix"))
{
#if UNIX_SOCK_SUPPORT
- options->management_flags |= MF_LISTEN_UNIX;
+ options->management_flags |= MF_UNIX_SOCK;
#else
msg (msglevel, "MANAGEMENT: this platform does not support unix domain sockets");
goto err;
diff --git a/socket.c b/socket.c
index ba1e367..dacb2c4 100644
--- a/socket.c
+++ b/socket.c
@@ -2703,6 +2703,16 @@ socket_accept_unix (socket_descriptor_t sd,
return ret;
}
+int
+socket_connect_unix (socket_descriptor_t sd,
+ struct sockaddr_un *remote)
+{
+ int status = connect (sd, (struct sockaddr *) remote, sizeof (struct sockaddr_un));
+ if (status)
+ status = openvpn_errno_socket ();
+ return status;
+}
+
void
sockaddr_unix_init (struct sockaddr_un *local, const char *path)
{
diff --git a/socket.h b/socket.h
index a8c7097..84d9b4f 100644
--- a/socket.h
+++ b/socket.h
@@ -421,6 +421,9 @@ void socket_bind_unix (socket_descriptor_t sd,
socket_descriptor_t socket_accept_unix (socket_descriptor_t sd,
struct sockaddr_un *remote);
+int socket_connect_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);