[Openvpn-devel] [M] Change in openvpn[master]: Add unix-script functionality to the --management feature

"plaisthos \(Code Review\) via Openvpn-devel" <[email protected]>
Newsgroups net.sourceforge.lists.openvpn-devel
Message-ID <107edf4906f17a00112a83549d303befef47fe16-EmailReplacePatchSet-HTML@gerrit.openvpn.net>
plaisthos has uploaded a new patch set (#2). ( http://gerrit.openvpn.net/c/openvpn/+/1852?usp=email )


Change subject: Add unix-script functionality to the --management feature
......................................................................

Add unix-script functionality to the --management feature

This allows a script that handles management input/output to
be started alongside OpenVPN simpler in small deployments.

Change-Id: I307e64079f436aa782f7e24bfff665a545ad2fa0
Signed-off-by: Arne Schwabe <[email protected]>
---
M doc/man-sections/management-options.rst
M doc/management-notes.txt
M src/openvpn/init.c
M src/openvpn/manage.c
M src/openvpn/manage.h
M src/openvpn/options.c
M src/openvpn/options.h
7 files changed, 100 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/52/1852/2

diff --git a/doc/man-sections/management-options.rst b/doc/man-sections/management-options.rst
index 8dad52b..d7ece8b 100644
--- a/doc/man-sections/management-options.rst
+++ b/doc/man-sections/management-options.rst
@@ -14,6 +14,7 @@
     management socket-name unix pw-file  # (recommended)
     management IP port                   # (INSECURE)
     management IP port pw-file           #
+    management script unix-script
 
   ``pw-file``, if specified, is a password file where the password must
   be on first line. Instead of a filename it can use the keyword stdin
@@ -25,6 +26,14 @@
   ``--management-client-user`` and ``--management-client-group``
   directives to restrict access.
 
+  When the variant :code:`unix-script` is used, OpenVPN will start the
+  specified script on startup and enable ``--management-hold``.
+  OpenVPN will generate a random path for the unix socket
+  and also management user and password. These are passed as environment
+  variables :code:`MANAGEMENT_SOCKET`, :code:`MANAGEMENT_PASSWORD`
+  to the script when being started. When OpenVPN terminates it sends
+  a :code:`SIGINT` signal to the running script.
+
   The management interface provides a special mode where the TCP
   management link can operate over the tunnel itself. To enable this mode,
   set IP to ``tunnel``. Tunnel mode will cause the management interface to
@@ -129,8 +138,9 @@
 --management-signal
   Send SIGUSR1 signal to OpenVPN if management session disconnects. This
   is useful when you wish to disconnect an OpenVPN session on user logoff.
-  For ``--management-client`` this option is not needed since a disconnect
-  will always generate a :code:`SIGTERM`.
+  For ``--management-client`` or  ``--management`` with :code:`unixscript`
+  this option is not needed since a disconnect  will always generate a
+  :code:`SIGTERM`.
 
 --management-up-down
   Report tunnel up/down events to management interface.
diff --git a/doc/management-notes.txt b/doc/management-notes.txt
index 1126468..d6b3fbb 100644
--- a/doc/management-notes.txt
+++ b/doc/management-notes.txt
@@ -35,6 +35,10 @@
 you can telnet to the management port (make sure to use
 a telnet client which understands "raw" mode).
 
+When password authentication is enabled, the management interface
+will require sending the password on its own line after establishing
+the connection.
+
 Once connected to the management port, you can use
 the "help" command to list all commands.
 
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 66bae34..101fa64 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -4337,19 +4337,59 @@
     }
 }
 
+void
+run_management_script(struct context *c)
+{
+#ifdef UNIX_SOCK_SUPPORT
+    struct gc_arena gc = gc_new();
+    struct argv argv = argv_new();
+    struct env_set *env = env_set_create(&gc);
+
+    setenv_str(env, "MANAGEMENT_USER", management->settings.up.username);
+    setenv_str(env, "MANAGEMENT_PASSWORD", management->settings.up.password);
+    setenv_str(env, "MANAGEMENT_SOCKET", c->options.management_addr);
+
+    argv_printf(&argv, "%s", c->options.management_script);
+
+    int flags = S_NOWAITPID | S_SCRIPT | S_FATAL;
+    int *pid = &management->connection.unix_script_pid;
+    const char *msg_prefix = "WARNING: Failed running management unix-script";
+    *pid = openvpn_execve_check(&argv, env, flags, msg_prefix);
+
+    if (!openvpn_waitpid_check(*pid, msg_prefix, M_FATAL))
+    {
+        *pid = 0;
+    }
+
+    argv_free(&argv);
+    gc_free(&gc);
+#else
+    msg(M_FATAL, "ERROR: Management unix-socket support is not available on this platform );
+#endif
+}
+
 bool
 open_management(struct context *c)
 {
     /* initialize management layer */
     if (management)
     {
+        unsigned int flags = c->options.management_flags;
+        if (flags & MF_UNIX_SOCK_SCRIPT)
+        {
+            /* This creates a file but our management codes deletes the
+             * file before opening a socket with the name */
+            c->options.management_addr = platform_create_temp_file(
+                platform_get_tmp_dir(), "omi", &c->gc);
+        }
+
         if (c->options.management_addr)
         {
-            unsigned int flags = c->options.management_flags;
             if (c->options.mode == MODE_SERVER)
             {
                 flags |= MF_SERVER;
             }
+
             if (management_open(
                     management, c->options.management_addr, c->options.management_port,
                     c->options.management_user_pass, c->options.management_client_user,
@@ -4361,6 +4401,11 @@
                                      NULL);
             }
 
+            if (flags & MF_UNIX_SOCK_SCRIPT)
+            {
+                run_management_script(c);
+            }
+
             /* initial management hold, called early, before first context initialization */
             do_hold(0);
             if (IS_SIG(c))
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 95ff246..bfc2aa2 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -333,10 +333,12 @@
 man_delete_unix_socket(struct management *man)
 {
 #if UNIX_SOCK_SUPPORT
-    if ((man->settings.flags & (MF_UNIX_SOCK | MF_CONNECT_AS_CLIENT)) == MF_UNIX_SOCK)
+    if ((man->settings.flags & (MF_UNIX_SOCK | MF_CONNECT_AS_CLIENT)) == MF_UNIX_SOCK
+        || man->settings.flags & MF_UNIX_SOCK_SCRIPT)
     {
         socket_delete_unix(&man->settings.local_unix);
     }
+
 #endif
 }
 
@@ -2197,7 +2199,7 @@
             }
         }
 
-        if (man->settings.flags & MF_CONNECT_AS_CLIENT)
+        if (man->settings.flags & (MF_CONNECT_AS_CLIENT | MF_UNIX_SOCK_SCRIPT))
         {
             msg(D_MANAGEMENT, "MANAGEMENT: Triggering management exit");
             throw_signal_soft(SIGTERM, "management-exit");
@@ -2644,6 +2646,15 @@
         {
             get_user_pass(&ms->up, pass_file, "Management", GET_USER_PASS_PASSWORD_ONLY);
         }
+        else if (ms->flags & MF_UNIX_SOCK_SCRIPT)
+        {
+            /* Set random password. The password is only
+             * alphanumerical [0-9a-f] but still has 128 bit of randomness,
+             * which is more than enough */
+            snprintf(ms->up.password, sizeof(ms->up.password),
+                     "%" PRIx64 "%" PRIx64, get_random(), get_random());
+            ms->up.defined = true;
+        }
 
 #if UNIX_SOCK_SUPPORT
         /*
@@ -2789,6 +2800,11 @@
         man_close_socket(man, mc->sd_cli);
     }
 
+    if (mc->unix_script_pid)
+    {
+        kill(mc->unix_script_pid, SIGINT);
+    }
+
     command_line_free(mc->in);
     buffer_list_free(mc->out);
 
diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
index 27d3b60..71e88d0 100644
--- a/src/openvpn/manage.h
+++ b/src/openvpn/manage.h
@@ -42,6 +42,7 @@
 #define MF_EXTERNAL_CERT          (1u << 15)
 #define MF_EXTERNAL_KEY_PSSPAD    (1u << 16)
 #define MF_EXTERNAL_KEY_DIGEST    (1u << 17)
+#define MF_UNIX_SOCK_SCRIPT       (1u << 18)
 
 #ifdef ENABLE_MANAGEMENT
 
@@ -327,6 +328,9 @@
     int fdtosend;
     int lastfdreceived;
 #endif
+#ifdef UNIX_SOCK_SUPPORT
+    pid_t unix_script_pid;
+#endif
     int client_version;
 };
 
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 9bd6f01..4391434 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1739,7 +1739,7 @@
      * Check for consistency of management options
      */
 #ifdef ENABLE_MANAGEMENT
-    if (!options->management_addr
+    if (!options->management_addr && !(options->management_flags & MF_UNIX_SOCK_SCRIPT)
         && (options->management_flags
             || options->management_log_history_cache != defaults.management_log_history_cache))
     {
@@ -4333,7 +4333,7 @@
     else if (streq(p[0], "management") && p[1] && p[2] && !p[4])
     {
         VERIFY_PERMISSION(OPT_P_GENERAL);
-        if (streq(p[2], "unix"))
+        if (streq(p[2], "unix") || streq(p[2], "unix-script"))
         {
 #if UNIX_SOCK_SUPPORT
             options->management_flags |= MF_UNIX_SOCK;
@@ -4343,7 +4343,16 @@
 #endif
         }
 
-        options->management_addr = p[1];
+        if (streq(p[2], "unix-script"))
+        {
+            options->management_flags |= MF_UNIX_SOCK_SCRIPT | MF_HOLD;
+            set_user_script(options, &options->management_script, p[1],
+                            "management unix-script", false);
+        }
+        else
+        {
+            options->management_addr = p[1];
+        }
         options->management_port = p[2];
         if (p[3])
         {
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index e93b05b..e92a5cd 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -446,6 +446,8 @@
     const char *management_addr;
     const char *management_port;
     const char *management_user_pass;
+    /** Script executed to talk to the management interface */
+    const char *management_script;
     int management_log_history_cache;
     int management_echo_buffer_size;
     int management_state_buffer_size;
@@ -761,7 +763,8 @@
 #define OPT_P_PUSH_MTU        (1u << 30)
 #define OPT_P_ROUTE_TABLE     (1u << 31)
 
-#define OPT_P_DEFAULT (~(OPT_P_INSTANCE | OPT_P_PULL_MODE | OPT_P_PEER_ID | 0x0ull))
+/* Options allowed in the normal configuration file */
+#define OPT_P_DEFAULT (~(OPT_P_INSTANCE | OPT_P_PULL_MODE | OPT_P_PEER_ID | 0x0ull)))
 
 #define PULL_DEFINED(opt) ((opt)->pull)
 

-- 
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1852?usp=email
To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I307e64079f436aa782f7e24bfff665a545ad2fa0
Gerrit-Change-Number: 1852
Gerrit-PatchSet: 2
Gerrit-Owner: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>

_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.