]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Allow "management-client" directive to be used
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Fri, 10 Apr 2009 21:33:14 +0000 (21:33 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Fri, 10 Apr 2009 21:33:14 +0000 (21:33 +0000)
with unix domain sockets.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4128 e7ae566f-a301-0410-adde-c780ea21d3b5

manage.c
manage.h
options.c
socket.c
socket.h

index cff43482bf8775920ffc88d2471a773570857832..1dd2825b9f36c96445046d68628e629a00d517b0 100644 (file)
--- 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
index 66fb7d1effe18ba4690feb8c3b7dc8b45f5630a0..9114184eace50b39cfd2821ecc619640bc56900a 100644 (file)
--- 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,
index 758a078f9262c51bb9f8a869dc1bb9ff0ac35cea..f2c7da86c9e5a4466afbf78cd7024ca0e1a12648 100644 (file)
--- 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;
index ba1e3678aa4acabbc69d3d756cd72e761e5a4ada..dacb2c47b6b9f12a2e5a5be7b89a4a533be0c597 100644 (file)
--- 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)
 {
index a8c70978d8ca944ae3a940aad0a14660eeb28979..84d9b4f61c9046547f855cf6ccfcaba1972445a4 100644 (file)
--- 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);