* 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
This commit is contained in:
james 2008-11-17 04:28:07 +00:00
parent 29885c58f4
commit a828135275
14 changed files with 389 additions and 111 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 */

5
init.c
View File

@ -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

247
misc.c
View File

@ -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 */
{
execve (cmd, argv, envp);
exit (127);
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 (pid < (pid_t)0) /* fork failed */
;
else /* parent side */
else if (script_method == SM_SYSTEM)
{
if (waitpid (pid, &ret, 0) != pid)
ret = -1;
ret = openvpn_system (argv_system_str (a), es, flags);
}
else
{
ASSERT (0);
}
}
else
@ -544,6 +558,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.
@ -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);
#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 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");
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;
}

17
misc.h
View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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,

30
tun.c
View File

@ -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);

2
tun.h
View File

@ -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);

View File

@ -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])

115
win32.c
View File

@ -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;
char *env = env_block (es);
char *cl = cmd_line (a);
char *cmd = a->argv[0];
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);
if (CreateProcess (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info))
if (script_method == SM_EXECVE)
{
DWORD exit_status = 0;
CloseHandle (proc_info.hThread);
WaitForSingleObject (proc_info.hProcess, INFINITE);
if (GetExitCodeProcess (proc_info.hProcess, &exit_status))
ret = (int)exit_status;
STARTUPINFO start_info;
PROCESS_INFORMATION proc_info;
char *env = env_block (es);
char *cl = cmd_line (a);
char *cmd = a->argv[0];
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);
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
{