mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-11-23 09:43:45 +08:00
* 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:
parent
29885c58f4
commit
a828135275
@ -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.
|
||||
|
7
buffer.h
7
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
|
||||
|
2
common.h
2
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
|
||||
|
@ -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
5
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
|
||||
|
247
misc.c
247
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 */
|
||||
{
|
||||
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
17
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);
|
||||
|
25
openvpn.8
25
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
|
||||
|
35
options.c
35
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);
|
||||
|
4
route.c
4
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,
|
||||
|
30
tun.c
30
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);
|
||||
|
2
tun.h
2
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);
|
||||
|
@ -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
115
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;
|
||||
|
||||
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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user