summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-11-17 04:28:07 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-11-17 04:28:07 +0000
commita82813527551f0e79c6d6ed5a9c1162e3c171bcf (patch)
tree65e82c2976c568a6f4099b8518c490c4d603e4cb
parent29885c58f449609432522b83a7ff026b7fe3e206 (diff)
downloadopenvpn-a82813527551f0e79c6d6ed5a9c1162e3c171bcf.tar.gz
openvpn-a82813527551f0e79c6d6ed5a9c1162e3c171bcf.tar.xz
openvpn-a82813527551f0e79c6d6ed5a9c1162e3c171bcf.zip
* Added additional method parameter to --script-security to preserve
backward compatibility with system() call semantics used in OpenVPN 2.1_rc8 and earlier. To preserve backward compatibility use: script-security 3 system git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3495 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--ChangeLog8
-rw-r--r--buffer.h7
-rw-r--r--common.h2
-rw-r--r--errlevel.h1
-rw-r--r--init.c5
-rw-r--r--misc.c241
-rw-r--r--misc.h17
-rw-r--r--openvpn.825
-rw-r--r--options.c35
-rw-r--r--route.c4
-rw-r--r--tun.c30
-rw-r--r--tun.h2
-rw-r--r--version.m42
-rw-r--r--win32.c109
14 files changed, 383 insertions, 105 deletions
diff --git a/ChangeLog b/ChangeLog
index 14d4a5c..ef5e408 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,7 +3,7 @@ Copyright (C) 2002-2008 OpenVPN Technologies, Inc. <sales@openvpn.net>
$Id$
-2008.11.xx -- Version 2.1_rc13b
+2008.11.xx -- Version 2.1_rc14
* Added AC_GNU_SOURCE to configure.ac to enable struct ucred,
with the goal of fixing a build issue on Fedora 9 that was
@@ -89,6 +89,12 @@ $Id$
config file syntax checking to allow directives for future OpenVPN
versions to be ignored.
+* Added additional method parameter to --script-security to preserve
+ backward compatibility with system() call semantics used in OpenVPN
+ 2.1_rc8 and earlier. To preserve backward compatibility use:
+
+ script-security 3 system
+
2008.10.07 -- Version 2.1_rc13
* Bundled OpenSSL 0.9.8i with Windows installer.
diff --git a/buffer.h b/buffer.h
index bfb6a1c..7872c37 100644
--- a/buffer.h
+++ b/buffer.h
@@ -58,13 +58,6 @@ struct buffer
#endif
};
-/* used by argv_x functions */
-struct argv {
- size_t capacity;
- size_t argc;
- char **argv;
-};
-
/* for garbage collection */
struct gc_entry
diff --git a/common.h b/common.h
index 7aa70a5..59b31b3 100644
--- a/common.h
+++ b/common.h
@@ -84,6 +84,6 @@ typedef unsigned long ptr_type;
/*
* Script security warning
*/
-#define SCRIPT_SECURITY_WARNING "openvpn_execve: external program may not be called unless '--script-security 2' or higher is enabled. See --help text for detailed info."
+#define SCRIPT_SECURITY_WARNING "openvpn_execve: external program may not be called unless '--script-security 2' or higher is enabled. Use '--script-security 3 system' for backward compatibility with 2.1_rc8 and earlier. See --help text or man page for detailed info."
#endif
diff --git a/errlevel.h b/errlevel.h
index b2c423a..fc05fe6 100644
--- a/errlevel.h
+++ b/errlevel.h
@@ -139,6 +139,7 @@
#define D_PS_PROXY_DEBUG LOGLEV(7, 70, M_DEBUG) /* port share proxy debug */
#define D_AUTO_USERID LOGLEV(7, 70, M_DEBUG) /* AUTO_USERID debugging */
#define D_TLS_KEYSELECT LOGLEV(7, 70, M_DEBUG) /* show information on key selection for data channel */
+#define D_ARGV_PARSE_CMD LOGLEV(7, 70, M_DEBUG) /* show parse_line() errors in argv_printf %sc */
#define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG) /* packet filter dropped a broadcast packet */
#define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG) /* packet filter debugging, must also define PF_DEBUG in pf.h */
diff --git a/init.c b/init.c
index 519dc8b..455712a 100644
--- a/init.c
+++ b/init.c
@@ -523,7 +523,7 @@ void
init_options_dev (struct options *options)
{
if (!options->dev)
- options->dev = dev_component_in_dev_node (options->dev_node);
+ options->dev = openvpn_basename (options->dev_node);
}
bool
@@ -2003,6 +2003,9 @@ do_option_warnings (struct context *c)
msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables");
else
msg (M_WARN, "NOTE: " PACKAGE_NAME " 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables");
+
+ if (script_method == SM_SYSTEM)
+ msg (M_WARN, "NOTE: --script-security method='system' is deprecated due to the fact that passed parameters will be subject to shell expansion");
}
static void
diff --git a/misc.c b/misc.c
index 911e911..5f89088 100644
--- a/misc.c
+++ b/misc.c
@@ -46,6 +46,9 @@ const char *iproute_path = IPROUTE_PATH; /* GLOBAL */
/* contains an SSEC_x value defined in misc.h */
int script_security = SSEC_BUILT_IN; /* GLOBAL */
+/* contains SM_x value defined in misc.h */
+int script_method = SM_EXECVE; /* GLOBAL */
+
/* Redefine the top level directory of the filesystem
to restrict access to files for security */
void
@@ -507,23 +510,34 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
#if defined(ENABLE_EXECVE)
if (openvpn_execve_allowed (flags))
{
- 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;
+ 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;
- pid = fork ();
- if (pid == (pid_t)0) /* child side */
+ pid = fork ();
+ if (pid == (pid_t)0) /* child side */
+ {
+ execve (cmd, argv, envp);
+ exit (127);
+ }
+ else if (pid < (pid_t)0) /* fork failed */
+ ;
+ else /* parent side */
+ {
+ if (waitpid (pid, &ret, 0) != pid)
+ ret = -1;
+ }
+ }
+ else if (script_method == SM_SYSTEM)
{
- execve (cmd, argv, envp);
- exit (127);
+ ret = openvpn_system (argv_system_str (a), es, flags);
}
- else if (pid < (pid_t)0) /* fork failed */
- ;
- else /* parent side */
+ else
{
- if (waitpid (pid, &ret, 0) != pid)
- ret = -1;
+ ASSERT (0);
}
}
else
@@ -545,6 +559,52 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
#endif
/*
+ * Wrapper around the system() call.
+ */
+int
+openvpn_system (const char *command, const struct env_set *es, unsigned int flags)
+{
+#ifdef HAVE_SYSTEM
+ int ret;
+
+ perf_push (PERF_SCRIPT);
+
+ /*
+ * add env_set to environment.
+ */
+ if (flags & S_SCRIPT)
+ env_set_add_to_environment (es);
+
+
+ /* debugging */
+ dmsg (D_SCRIPT, "SYSTEM[%u] '%s'", flags, command);
+ if (flags & S_SCRIPT)
+ env_set_print (D_SCRIPT, es);
+
+ /*
+ * execute the command
+ */
+ ret = system (command);
+
+ /* debugging */
+ dmsg (D_SCRIPT, "SYSTEM return=%u", ret);
+
+ /*
+ * remove env_set from environment
+ */
+ if (flags & S_SCRIPT)
+ env_set_remove_from_environment (es);
+
+ perf_pop ();
+ return ret;
+
+#else
+ msg (M_FATAL, "Sorry but I can't execute the shell command '%s' because this operating system doesn't appear to support the system() call", command);
+ return -1; /* NOTREACHED */
+#endif
+}
+
+/*
* Initialize random number seed. random() is only used
* when "weak" random numbers are acceptable.
* OpenSSL routines are always used when cryptographically
@@ -1679,6 +1739,7 @@ argv_init (struct argv *a)
a->capacity = 0;
a->argc = 0;
a->argv = NULL;
+ a->system_str = NULL;
}
struct argv
@@ -1696,6 +1757,7 @@ argv_reset (struct argv *a)
for (i = 0; i < a->argc; ++i)
free (a->argv[i]);
free (a->argv);
+ free (a->system_str);
argv_init (a);
}
@@ -1730,6 +1792,64 @@ argv_append (struct argv *a, char *str) /* str must have been malloced or be NUL
a->argv[a->argc++] = str;
}
+static void
+argv_system_str_append (struct argv *a, const char *str, const bool enquote)
+{
+ if (str)
+ {
+ char *newstr;
+
+ /* compute length of new system_str */
+ size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */
+ if (a->system_str)
+ l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */
+ if (enquote)
+ l += 2; /* space for two quotes */
+
+ /* build new system_str */
+ newstr = (char *) malloc (l);
+ newstr[0] = '\0';
+ check_malloc_return (newstr);
+ if (a->system_str)
+ {
+ strcpy (newstr, a->system_str);
+ strcat (newstr, " ");
+ }
+ if (enquote)
+ strcat (newstr, "\"");
+ strcat (newstr, str);
+ if (enquote)
+ strcat (newstr, "\"");
+ free (a->system_str);
+ a->system_str = newstr;
+ }
+}
+
+static char *
+argv_extract_cmd_name (const char *path)
+{
+ if (path)
+ {
+ const char *bn = openvpn_basename (path);
+ if (bn)
+ {
+ char *ret = string_alloc (bn, NULL);
+ char *dot = strrchr (ret, '.');
+ if (dot)
+ *dot = '\0';
+ if (ret[0] != '\0')
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+const char *
+argv_system_str (const struct argv *a)
+{
+ return a->system_str;
+}
+
struct argv
argv_clone (const struct argv *a, const size_t headroom)
{
@@ -1744,6 +1864,7 @@ argv_clone (const struct argv *a, const size_t headroom)
for (i = 0; i < a->argc; ++i)
argv_append (&r, string_alloc (a->argv[i], NULL));
}
+ r.system_str = string_alloc (a->system_str, NULL);
return r;
}
@@ -1751,10 +1872,17 @@ struct argv
argv_insert_head (const struct argv *a, const char *head)
{
struct argv r;
+ char *s;
r = argv_clone (a, 1);
r.argv[0] = string_alloc (head, NULL);
-
+ s = r.system_str;
+ r.system_str = string_alloc (head, NULL);
+ if (s)
+ {
+ argv_system_str_append (&r, s, false);
+ free (s);
+ }
return r;
}
@@ -1870,6 +1998,7 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
if (!s)
s = "";
argv_append (a, string_alloc (s, NULL));
+ argv_system_str_append (a, s, true);
}
else if (!strcmp (term, "%sc"))
{
@@ -1880,24 +2009,36 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
char *parms[MAX_PARMS+1];
int i;
- nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, M_FATAL, &gc);
- for (i = 0; i < nparms; ++i)
- argv_append (a, string_alloc (parms[i], NULL));
+ nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
+ if (nparms)
+ {
+ for (i = 0; i < nparms; ++i)
+ argv_append (a, string_alloc (parms[i], NULL));
+ }
+ else
+ argv_append (a, string_alloc (s, NULL));
+
+ argv_system_str_append (a, s, false);
}
else
- argv_append (a, string_alloc ("", NULL));
+ {
+ argv_append (a, string_alloc ("", NULL));
+ argv_system_str_append (a, "echo", false);
+ }
}
else if (!strcmp (term, "%d"))
{
char numstr[64];
openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
argv_append (a, string_alloc (numstr, NULL));
+ argv_system_str_append (a, numstr, false);
}
else if (!strcmp (term, "%u"))
{
char numstr[64];
openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
argv_append (a, string_alloc (numstr, NULL));
+ argv_system_str_append (a, numstr, false);
}
else if (!strcmp (term, "%s/%d"))
{
@@ -1918,13 +2059,15 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
strcat (combined, "/");
strcat (combined, numstr);
argv_append (a, combined);
+ argv_system_str_append (a, combined, false);
}
}
- else if (!strcmp (term, "%s%s"))
+ else if (!strcmp (term, "%s%sc"))
{
char *s1 = va_arg (arglist, char *);
char *s2 = va_arg (arglist, char *);
char *combined;
+ char *cmd_name;
if (!s1) s1 = "";
if (!s2) s2 = "";
@@ -1933,6 +2076,13 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
strcpy (combined, s1);
strcat (combined, s2);
argv_append (a, combined);
+
+ cmd_name = argv_extract_cmd_name (combined);
+ if (cmd_name)
+ {
+ argv_system_str_append (a, cmd_name, false);
+ free (cmd_name);
+ }
}
else
ASSERT (0);
@@ -1941,6 +2091,7 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
else
{
argv_append (a, term);
+ argv_system_str_append (a, term, false);
}
}
gc_free (&gc);
@@ -1954,43 +2105,54 @@ argv_test (void)
const char *s;
struct argv a;
+
argv_init (&a);
+ argv_printf (&a, "%sc foo bar %s", "c:\\\\src\\\\test\\\\jyargs.exe", "foo bar");
+ argv_msg_prefix (M_INFO, &a, "ARGV");
+ msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
+ //openvpn_execve_check (&a, NULL, 0, "command failed");
-#ifdef WIN32
- argv_printf (&a, "%s foo bar %s", "c:\\src\\test\\jyargs.exe", "foo bar");
- //argv_printf (&a, "%s %s %s", "c:\\src\\test files\\batargs.bat", "foo", "bar");
-#else
- argv_printf (&a, "./myechox foo bar");
-#endif
+ argv_printf (&a, "%sc %s %s", "c:\\\\src\\\\test files\\\\batargs.bat", "foo", "bar");
+ argv_msg_prefix (M_INFO, &a, "ARGV");
+ msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
+ //openvpn_execve_check (&a, NULL, 0, "command failed");
+ argv_printf (&a, "%s%sc foo bar %s %s/%d %d %u", "/foo", "/bar.exe", "one two", "1.2.3.4", 24, -69, 96);
argv_msg_prefix (M_INFO, &a, "ARGV");
+ msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
//openvpn_execve_check (&a, NULL, 0, "command failed");
argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42);
s = argv_str (&a, &gc, PA_BRACKET);
- printf ("%s\n", s);
+ printf ("PF: %s\n", s);
+ printf ("PF-S: %s\n", argv_system_str(&a));
{
struct argv b = argv_insert_head (&a, "MARK");
s = argv_str (&b, &gc, PA_BRACKET);
+ printf ("PF: %s\n", s);
+ printf ("PF-S: %s\n", argv_system_str(&b));
argv_reset (&b);
- printf ("%s\n", s);
}
argv_printf (&a, "%sc foo bar %d", "\"multi term\" command following \\\"spaces", 99);
s = argv_str (&a, &gc, PA_BRACKET);
+ printf ("PF: %s\n", s);
+ printf ("PF-S: %s\n", argv_system_str(&a));
argv_reset (&a);
- printf ("%s\n", s);
s = argv_str (&a, &gc, PA_BRACKET);
+ printf ("PF: %s\n", s);
+ printf ("PF-S: %s\n", argv_system_str(&a));
argv_reset (&a);
- printf ("%s\n", s);
argv_printf (&a, "foo bar %d", 99);
argv_printf_cat (&a, "bar %d foo %sc", 42, "nonesuch");
argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7);
s = argv_str (&a, &gc, PA_BRACKET);
- printf ("%s\n", s);
+ printf ("PF: %s\n", s);
+ printf ("PF-S: %s\n", argv_system_str(&a));
+ argv_reset (&a);
#if 0
{
@@ -2015,3 +2177,22 @@ argv_test (void)
gc_free (&gc);
}
#endif
+
+const char *
+openvpn_basename (const char *path)
+{
+ const char *ret;
+ const int dirsep = OS_SPECIFIC_DIRSEP;
+
+ if (path)
+ {
+ ret = strrchr (path, dirsep);
+ if (ret && *ret)
+ ++ret;
+ else
+ ret = path;
+ if (*ret)
+ return ret;
+ }
+ return NULL;
+}
diff --git a/misc.h b/misc.h
index a9c011a..d96d171 100644
--- a/misc.h
+++ b/misc.h
@@ -36,6 +36,14 @@
/* forward declarations */
struct plugin_list;
+/* used by argv_x functions */
+struct argv {
+ size_t capacity;
+ size_t argc;
+ char **argv;
+ char *system_str;
+};
+
/*
* Handle environmental variable lists
*/
@@ -126,6 +134,7 @@ const char *system_error_message (int, struct gc_arena *gc);
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);
+int openvpn_system (const char *command, const struct env_set *es, unsigned int flags);
#ifdef HAVE_STRERROR
/* a thread-safe version of strerror */
@@ -297,9 +306,16 @@ extern const char *iproute_path;
#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 */
+#define SM_EXECVE 0 /* call external programs with execve() or CreateProcess() */
+#define SM_SYSTEM 1 /* call external programs with system() */
+extern int script_method; /* GLOBAL */
+
/* return the next largest power of 2 */
size_t adjust_power_of_2 (size_t u);
+/* return the basename of path */
+const char *openvpn_basename (const char *path);
+
/*
* A printf-like function (that only recognizes a subset of standard printf
* format operators) that prints arguments to an argv list instead
@@ -314,6 +330,7 @@ const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned
struct argv argv_insert_head (const struct argv *a, const char *head);
void argv_msg (const int msglev, const struct argv *a);
void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix);
+const char *argv_system_str (const struct argv *a);
#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */
void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist);
diff --git a/openvpn.8 b/openvpn.8
index 921f8fb..c45f839 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -2034,9 +2034,11 @@ is a safety precaution to prevent a LD_PRELOAD style attack
from a malicious or compromised server.
.\"*********************************************************
.TP
-.B --script-security level
+.B --script-security level [method]
This directive offers policy-level control over OpenVPN's usage of external programs
-and scripts. Lower values are more restrictive, higher values are more permissive. Settings for
+and scripts. Lower
+.B level
+values are more restrictive, higher values are more permissive. Settings for
.B level:
.B 0 --
@@ -2050,6 +2052,25 @@ Allow calling of built-in executables and user-defined scripts.
.br
.B 3 --
Allow passwords to be passed to scripts via environmental variables (potentially unsafe).
+
+The
+.B method
+parameter indicates how OpenVPN should call external commands and scripts.
+Settings for
+.B method:
+
+.B execve --
+(default) Use execve() function on Unix family OSes and CreateProcess() on Windows.
+.br
+.B system --
+Use system() function (deprecated and less safe since the external program command
+line is subject to shell expansion).
+
+The
+.B --script-security
+option was introduced in OpenVPN 2.1_rc9. For configuration file compatibility
+with previous OpenVPN versions, use:
+.B --script-security 3 system
.\"*********************************************************
.TP
.B --disable-occ
diff --git a/options.c b/options.c
index 5e579e9..50f6982 100644
--- a/options.c
+++ b/options.c
@@ -193,10 +193,11 @@ static const char usage_message[] =
"--setenv name value : Set a custom environmental variable to pass to script.\n"
"--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"
" directives for future OpenVPN versions to be ignored.\n"
- "--script-security level : 0 -- strictly no calling of external programs\n"
- " 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-security level mode : mode='execve' (default) or 'system', level=\n"
+ " 0 -- strictly no calling of external programs\n"
+ " 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"
"--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"
@@ -1714,6 +1715,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if ((options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) && !ccnr)
msg (M_USAGE, "--auth-user-pass-optional %s", postfix);
}
+
+ if ((options->ssl_flags & SSLF_NO_NAME_REMAPPING) && script_method == SM_SYSTEM)
+ msg (M_USAGE, "--script-security method='system' cannot be combined with --no-name-remapping");
}
else
{
@@ -2843,11 +2847,14 @@ parse_line (const char *line,
if (backslash && out)
{
if (!(out == '\\' || out == '\"' || space (out)))
+ {
#ifdef ENABLE_SMALL
- msg (msglevel, "%sOptions warning: Bad backslash ('\\') usage in %s:%d", error_prefix, file, line_num);
+ msg (msglevel, "%sOptions warning: Bad backslash ('\\') usage in %s:%d", error_prefix, file, line_num);
#else
- msg (msglevel, "%sOptions warning: Bad backslash ('\\') usage in %s:%d: remember that backslashes are treated as shell-escapes and if you need to pass backslash characters as part of a Windows filename, you should use double backslashes such as \"c:\\\\" PACKAGE "\\\\static.key\"", error_prefix, file, line_num);
+ msg (msglevel, "%sOptions warning: Bad backslash ('\\') usage in %s:%d: remember that backslashes are treated as shell-escapes and if you need to pass backslash characters as part of a Windows filename, you should use double backslashes such as \"c:\\\\" PACKAGE "\\\\static.key\"", error_prefix, file, line_num);
#endif
+ return 0;
+ }
}
backslash = false;
}
@@ -4402,7 +4409,21 @@ add_option (struct options *options,
{
VERIFY_PERMISSION (OPT_P_GENERAL);
script_security = atoi (p[1]);
- }
+ if (p[2])
+ {
+ if (streq (p[2], "execve"))
+ script_method = SM_EXECVE;
+ else if (streq (p[2], "system"))
+ script_method = SM_SYSTEM;
+ else
+ {
+ msg (msglevel, "unknown --script-security method: %s", p[2]);
+ goto err;
+ }
+ }
+ else
+ script_method = SM_EXECVE;
+ }
else if (streq (p[0], "mssfix"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/route.c b/route.c
index 86bbfe6..1efcf4e 100644
--- a/route.c
+++ b/route.c
@@ -827,7 +827,7 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
#elif defined (WIN32)
- argv_printf (&argv, "%s%s ADD %s MASK %s %s",
+ argv_printf (&argv, "%s%sc ADD %s MASK %s %s",
get_win_sys_path(),
WIN_ROUTE_PATH_SUFFIX,
network,
@@ -1007,7 +1007,7 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
#elif defined (WIN32)
- argv_printf (&argv, "%s%s DELETE %s MASK %s %s",
+ argv_printf (&argv, "%s%sc DELETE %s MASK %s %s",
get_win_sys_path(),
WIN_ROUTE_PATH_SUFFIX,
network,
diff --git a/tun.c b/tun.c
index ee32e4c..7247d2a 100644
--- a/tun.c
+++ b/tun.c
@@ -106,25 +106,6 @@ dev_type_string (const char *dev, const char *dev_type)
}
}
-const char *
-dev_component_in_dev_node (const char *dev_node)
-{
- const char *ret;
- const int dirsep = OS_SPECIFIC_DIRSEP;
-
- if (dev_node)
- {
- ret = strrchr (dev_node, dirsep);
- if (ret && *ret)
- ++ret;
- else
- ret = dev_node;
- if (*ret)
- return ret;
- }
- return NULL;
-}
-
/*
* Try to predict the actual TUN/TAP device instance name,
* before the device is actually opened.
@@ -3481,7 +3462,7 @@ netsh_ifconfig_options (const char *type,
/* delete existing DNS/WINS settings from TAP interface */
if (delete_first)
{
- argv_printf (&argv, "%s%s interface ip delete %s %s all",
+ argv_printf (&argv, "%s%sc interface ip delete %s %s all",
get_win_sys_path(),
NETSH_PATH_SUFFIX,
type,
@@ -3498,8 +3479,8 @@ netsh_ifconfig_options (const char *type,
if (delete_first || !test_first || !ip_addr_member_of (addr_list[i], current))
{
const char *fmt = count ?
- "%s%s interface ip add %s %s %s"
- : "%s%s interface ip set %s %s static %s";
+ "%s%sc interface ip add %s %s %s"
+ : "%s%sc interface ip set %s %s static %s";
argv_printf (&argv, fmt,
get_win_sys_path(),
@@ -3575,8 +3556,7 @@ netsh_ifconfig (const struct tuntap_options *to,
else
{
/* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */
- argv_printf (&argv,
- "%s%s interface ip set address %s static %s %s",
+ argv_printf (&argv, "%s%sc interface ip set address %s static %s %s",
get_win_sys_path(),
NETSH_PATH_SUFFIX,
flex_name,
@@ -3624,7 +3604,7 @@ netsh_enable_dhcp (const struct tuntap_options *to,
/* example: netsh interface ip set address my-tap dhcp */
argv_printf (&argv,
- "%s%s interface ip set address %s dhcp",
+ "%s%sc interface ip set address %s dhcp",
get_win_sys_path(),
NETSH_PATH_SUFFIX,
actual_name);
diff --git a/tun.h b/tun.h
index 85e850f..9d702fe 100644
--- a/tun.h
+++ b/tun.h
@@ -231,8 +231,6 @@ void do_ifconfig (struct tuntap *tt,
int tun_mtu,
const struct env_set *es);
-const char *dev_component_in_dev_node (const char *dev_node);
-
bool is_dev_type (const char *dev, const char *dev_type, const char *match_type);
int dev_type_enum (const char *dev, const char *dev_type);
const char *dev_type_string (const char *dev, const char *dev_type);
diff --git a/version.m4 b/version.m4
index c8bc01e..46a96fb 100644
--- a/version.m4
+++ b/version.m4
@@ -1,5 +1,5 @@
dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1_rc13b])
+define(PRODUCT_VERSION,[2.1_rc13c])
dnl define the TAP version
define(PRODUCT_TAP_ID,[tap0901])
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
diff --git a/win32.c b/win32.c
index 9272cb7..f6ac6fe 100644
--- a/win32.c
+++ b/win32.c
@@ -75,6 +75,51 @@ struct semaphore netcmd_semaphore; /* GLOBAL */
*/
static char *win_sys_path = NULL; /* GLOBAL */
+/*
+ * Configure PATH. On Windows, sometimes PATH is not set correctly
+ * by default.
+ */
+static void
+configure_win_path (void)
+{
+ static bool done = false; /* GLOBAL */
+ if (!done)
+ {
+ FILE *fp;
+ fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
+ if (fp)
+ {
+ const int bufsiz = 4096;
+ struct gc_arena gc = gc_new ();
+ struct buffer oldpath = alloc_buf_gc (bufsiz, &gc);
+ struct buffer newpath = alloc_buf_gc (bufsiz, &gc);
+ const char* delim = ";";
+ DWORD status;
+ fclose (fp);
+ status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
+#if 0
+ status = 0;
+#endif
+ if (!status)
+ {
+ *BPTR(&oldpath) = '\0';
+ delim = "";
+ }
+ buf_printf (&newpath, "C:\\WINDOWS\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem%s%s",
+ delim,
+ BSTR(&oldpath));
+ SetEnvironmentVariable ("PATH", BSTR(&newpath));
+#if 0
+ status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
+ if (status > 0)
+ printf ("PATH: %s\n", BSTR(&oldpath));
+#endif
+ gc_free (&gc);
+ done = true;
+ }
+ }
+}
+
void
init_win32 (void)
{
@@ -911,41 +956,53 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
{
if (openvpn_execve_allowed (flags))
{
- STARTUPINFO start_info;
- PROCESS_INFORMATION proc_info;
+ if (script_method == SM_EXECVE)
+ {
+ STARTUPINFO start_info;
+ PROCESS_INFORMATION proc_info;
- char *env = env_block (es);
- char *cl = cmd_line (a);
- char *cmd = a->argv[0];
+ char *env = env_block (es);
+ char *cl = cmd_line (a);
+ char *cmd = a->argv[0];
- CLEAR (start_info);
- CLEAR (proc_info);
+ CLEAR (start_info);
+ CLEAR (proc_info);
- /* fill in STARTUPINFO struct */
- GetStartupInfo(&start_info);
- start_info.cb = sizeof(start_info);
- start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
- start_info.wShowWindow = SW_HIDE;
- start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- start_info.hStdOutput = start_info.hStdError = GetStdHandle(STD_OUTPUT_HANDLE);
+ /* fill in STARTUPINFO struct */
+ GetStartupInfo(&start_info);
+ start_info.cb = sizeof(start_info);
+ start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+ start_info.wShowWindow = SW_HIDE;
+ start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ start_info.hStdOutput = start_info.hStdError = GetStdHandle(STD_OUTPUT_HANDLE);
- if (CreateProcess (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info))
- {
- DWORD exit_status = 0;
- CloseHandle (proc_info.hThread);
- WaitForSingleObject (proc_info.hProcess, INFINITE);
- if (GetExitCodeProcess (proc_info.hProcess, &exit_status))
- ret = (int)exit_status;
+ if (CreateProcess (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info))
+ {
+ DWORD exit_status = 0;
+ CloseHandle (proc_info.hThread);
+ WaitForSingleObject (proc_info.hProcess, INFINITE);
+ if (GetExitCodeProcess (proc_info.hProcess, &exit_status))
+ ret = (int)exit_status;
+ else
+ msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %s failed", cmd);
+ CloseHandle (proc_info.hProcess);
+ }
else
- msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %s failed", cmd);
- CloseHandle (proc_info.hProcess);
+ {
+ msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %s failed", cmd);
+ }
+ free (cl);
+ free (env);
+ }
+ else if (script_method == SM_SYSTEM)
+ {
+ configure_win_path ();
+ ret = openvpn_system (argv_system_str (a), es, flags);
}
else
{
- msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %s failed", cmd);
+ ASSERT (0);
}
- free (cl);
- free (env);
}
else
{