Hello all,
I am submitting a minor patch which includes an option to specify --script-dir.
i.e. any user defined script will be run ONLY IF it is present in "script-dir".
The reason I needed this is because I had a frontend to configuration file
which allowed administrator to change configuration.
I also have script-security set to 2 because I wanted to run a script when
client connects.
These two option make it insecure. As admin (with bad intention or if admin
password is leaked) can simply call "rm -rf /" for certain commands.
So my idea was
1) Add a new option called script-dir
2) Frontend will not allow word "script-dir" in config file (so admin cant
change it)
3) script-dir will be passed on command line
This way admin can not run anything other than what I have put in script-dir.
This also helps prevent accidentally run script in some other path.
Patch also fixes minor bug in init.c where warning for SSEC_PW_ENV actually
would never be shown.
So please have a look at it and if acceptable then merge in source tree.
Thanks
AMM.
--- openvpn-2.2.2/init.c 2011-12-13 22:28:56.000000000 +0530
+++ openvpn-2.2.2/init.c 2012-08-21 11:53:22.809410085 +0530
@@ -2291,9 +2291,13 @@
#endif
if (script_security >= SSEC_SCRIPTS)
- msg (M_WARN, "NOTE: the current --script-security setting may allow this configuration to call user-defined scripts");
- else if (script_security >= SSEC_PW_ENV)
- msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables");
+ {
+ msg (M_WARN, "NOTE: the current --script-security setting may allow this configuration to call user-defined scripts");
+ if (script_security >= SSEC_PW_ENV)
+ msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables");
+ if (script_dir == NULL)
+ msg (M_WARN, "WARNING: setting --script-dir is recommended for higher security");
+ }
else
msg (M_WARN, "NOTE: " PACKAGE_NAME " 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables");
--- openvpn-2.2.2/misc.c 2011-12-13 22:28:56.000000000 +0530
+++ openvpn-2.2.2/misc.c 2012-08-21 12:27:24.332296778 +0530
@@ -45,6 +45,7 @@
/* contains an SSEC_x value defined in misc.h */
int script_security = SSEC_BUILT_IN; /* GLOBAL */
+const char *script_dir = NULL; /* GLOBAL */
/* contains SM_x value defined in misc.h */
int script_method = SM_EXECVE; /* GLOBAL */
@@ -484,10 +485,14 @@
}
bool
-openvpn_execve_allowed (const unsigned int flags)
+openvpn_execve_allowed (const char *cmd, const unsigned int flags)
{
if (flags & S_SCRIPT)
- return script_security >= SSEC_SCRIPTS;
+ {
+ if (script_dir != NULL && strncmp(script_dir, cmd, strlen(script_dir)))
+ return false;
+ return script_security >= SSEC_SCRIPTS;
+ }
else
return script_security >= SSEC_BUILT_IN;
}
@@ -509,11 +514,11 @@
if (a && a->argv[0])
{
#if defined(ENABLE_EXECVE)
- if (openvpn_execve_allowed (flags))
+ const char *cmd = a->argv[0];
+ if (openvpn_execve_allowed (cmd, flags))
{
if (script_method == SM_EXECVE)
{
- const char *cmd = a->argv[0];
char *const *argv = a->argv;
char *const *envp = (char *const *)make_env_array (es, true, &gc);
pid_t pid;
--- openvpn-2.2.2/misc.h 2011-12-13 22:28:56.000000000 +0530
+++ openvpn-2.2.2/misc.h 2012-08-21 12:10:59.916050919 +0530
@@ -133,7 +133,7 @@
/* wrapper around the execve() call */
int openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags);
bool openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message);
-bool openvpn_execve_allowed (const unsigned int flags);
+bool openvpn_execve_allowed (const char *cmd, const unsigned int flags);
int openvpn_system (const char *command, const struct env_set *es, unsigned int flags);
static inline bool
@@ -353,6 +353,7 @@
#define SSEC_SCRIPTS 2 /* allow calling of built-in programs and user-defined scripts */
#define SSEC_PW_ENV 3 /* allow calling of built-in programs and user-defined scripts that may receive a password as an environmental variable */
extern int script_security; /* GLOBAL */
+extern const char *script_dir; /* GLOBAL */
#define SM_EXECVE 0 /* call external programs with execve() or CreateProcess() */
#define SM_SYSTEM 1 /* call external programs with system() */
--- openvpn-2.2.2/options.c 2011-12-13 22:28:56.000000000 +0530
+++ openvpn-2.2.2/options.c 2012-08-21 11:33:15.955648666 +0530
@@ -218,6 +218,7 @@
" 1 -- (default) only call built-ins such as ifconfig\n"
" 2 -- allow calling of built-ins and scripts\n"
" 3 -- allow password to be passed to scripts via env\n"
+ "--script-dir dir: Only run user-defined scripts if it resides in this directory\n"
"--shaper n : Restrict output to peer to n bytes per second.\n"
"--keepalive n m : Helper option for setting timeouts in server mode. Send\n"
" ping once every n seconds, restart if ping not received\n"
@@ -4748,6 +4749,11 @@
else
script_method = SM_EXECVE;
}
+ else if (streq (p[0], "script-dir") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ script_dir = p[1];
+ }
else if (streq (p[0], "mssfix"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
--- openvpn-2.2.2/win32.c 2011-12-13 22:28:56.000000000 +0530
+++ openvpn-2.2.2/win32.c 2012-08-21 12:15:56.355627974 +0530
@@ -956,7 +956,8 @@
if (a && a->argv[0])
{
- if (openvpn_execve_allowed (flags))
+ char *cmd = a->argv[0];
+ if (openvpn_execve_allowed (cmd, flags))
{
if (script_method == SM_EXECVE)
{
@@ -965,7 +966,6 @@
char *env = env_block (es);
char *cl = cmd_line (a);
- char *cmd = a->argv[0];
CLEAR (start_info);
CLEAR (proc_info);