Attention is currently required from: flichtenheld.
Hello flichtenheld,
I'd like you to reexamine a change. Please visit
http://gerrit.openvpn.net/c/openvpn/+/1852?usp=email
to look at the new patch set (#9).
The following approvals got outdated and were removed:
Code-Review-1 by flichtenheld
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, 117 insertions(+), 11 deletions(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/52/1852/9
diff --git a/doc/man-sections/management-options.rst
b/doc/man-sections/management-options.rst
index 8dad52b..e2e0773 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 management 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
@@ -127,10 +136,11 @@
(client-only).
--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`.
+ Send :code:`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`` or ``--management`` with
+ :code:`unixscript` this option has no effect since a disconnect will
+ always trigger sending 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 a8e041d..04220f4 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -4337,19 +4337,65 @@
}
}
+void
+run_management_script(struct context *c)
+{
+#if 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 filename that should be ungessuable */
+ char sockname[32] = { 0 };
+ snprintf(sockname, sizeof(sockname),
+ PACKAGE_NAME "_omi_%08" PRIx64 "%08" PRIx64 ".sock",
+ get_random(), get_random());
+
+ c->options.management_addr =
platform_gen_path(platform_get_tmp_dir(), sockname, &c->gc);
+
+ 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 +4407,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 2b0a661..29fdffc 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,10 +2199,18 @@
}
}
+ if (man->settings.flags & MF_UNIX_SOCK_SCRIPT &&
!man_password_needed(man))
+ {
+ msg(D_MANAGEMENT, "MANAGEMENT: Triggering exit on unix-script
disconnect");
+ throw_signal_soft(SIGTERM, "management-exit");
+ }
+
if (man->settings.flags & MF_CONNECT_AS_CLIENT)
{
- msg(D_MANAGEMENT, "MANAGEMENT: Triggering management exit");
- throw_signal_soft(SIGTERM, "management-exit");
+ {
+ msg(D_MANAGEMENT, "MANAGEMENT: Triggering management exit");
+ throw_signal_soft(SIGTERM, "management-exit");
+ }
}
else
{
@@ -2644,6 +2654,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 +2808,13 @@
man_close_socket(man, mc->sd_cli);
}
+#if UNIX_SOCK_SUPPORT
+ if (mc->unix_script_pid)
+ {
+ kill(mc->unix_script_pid, SIGINT);
+ }
+#endif
+
command_line_free(mc->in);
buffer_list_free(mc->out);
diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
index 27d3b60..f752fec 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
+#if 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 5f3f4e9..1939c69 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1720,7 +1720,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))
{
@@ -4301,7 +4301,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;
@@ -4311,7 +4311,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 f472676..131513e 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;
--
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: 9
Gerrit-Owner: plaisthos <[email protected]>
Gerrit-Reviewer: flichtenheld <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: flichtenheld <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel