mirror of
https://github.com/OpenVPN/openvpn.git
synced 2025-05-09 05:31:05 +08:00
2.1_rc8 and earlier did implicit shell expansion on script
arguments since all scripts were called by system(). The security hardening changes made to 2.1_rc9 no longer use system(), but rather use the safer execve or CreateProcess system calls. The security hardening also introduced a backward incompatibility with 2.1_rc8 and earlier in that script parameters were no longer shell-expanded, so for example: client-connect "docc CLIENT-CONNECT" would fail to work because execve would try to execute a script called "docc CLIENT-CONNECT" instead of "docc" with "CLIENT-CONNECT" as the first argument. This patch fixes the issue, bringing the script argument semantics back to pre 2.1_rc9 behavior in order to preserve backward compatibility while still using execve or CreateProcess to execute the script/executable. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3311 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
0a838de8ad
commit
b8fb090c16
252
buffer.c
252
buffer.c
@ -234,258 +234,6 @@ int openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* A printf-like function (that only recognizes a subset of standard printf
|
||||
* format operators) that prints arguments to an argv list instead
|
||||
* of a standard string. This is used to build up argv arrays for passing
|
||||
* to execve.
|
||||
*/
|
||||
|
||||
void
|
||||
argv_init (struct argv *a)
|
||||
{
|
||||
a->argc = 0;
|
||||
a->argv = NULL;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_new (void)
|
||||
{
|
||||
struct argv ret;
|
||||
argv_init (&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
argv_reset (struct argv *a)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
free (a->argv[i]);
|
||||
free (a->argv);
|
||||
a->argc = 0;
|
||||
a->argv = NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
argv_argc (const char *format)
|
||||
{
|
||||
char *term;
|
||||
const char *f = format;
|
||||
size_t argc = 0;
|
||||
|
||||
while ((term = argv_term (&f)) != NULL)
|
||||
{
|
||||
++argc;
|
||||
free (term);
|
||||
}
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_insert_head (const struct argv *a, const char *head)
|
||||
{
|
||||
struct argv r;
|
||||
size_t i;
|
||||
|
||||
r.argc = (a ? a->argc : 0) + 1;
|
||||
ALLOC_ARRAY_CLEAR (r.argv, char *, r.argc + 1);
|
||||
r.argv[0] = string_alloc (head, NULL);
|
||||
if (a)
|
||||
{
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
r.argv[i+1] = string_alloc (a->argv[i], NULL);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
argv_term (const char **f)
|
||||
{
|
||||
const char *p = *f;
|
||||
const char *term = NULL;
|
||||
size_t termlen = 0;
|
||||
|
||||
if (*p == '\0')
|
||||
return NULL;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const int c = *p;
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (!isspace (c))
|
||||
++termlen;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isspace (c))
|
||||
{
|
||||
term = p;
|
||||
termlen = 1;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*f = p;
|
||||
|
||||
if (term)
|
||||
{
|
||||
char *ret;
|
||||
ASSERT (termlen > 0);
|
||||
ret = malloc (termlen + 1);
|
||||
check_malloc_return (ret);
|
||||
memcpy (ret, term, termlen);
|
||||
ret[termlen] = '\0';
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
|
||||
{
|
||||
if (a->argv)
|
||||
return print_argv ((const char **)a->argv, gc, flags);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
argv_msg (const int msglev, const struct argv *a)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (msglev, "%s", argv_str (a, &gc, 0));
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf (struct argv *a, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start (arglist, format);
|
||||
argv_printf_arglist (a, format, 0, arglist);
|
||||
va_end (arglist);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start (arglist, format);
|
||||
argv_printf_arglist (a, format, APA_CAT, arglist);
|
||||
va_end (arglist);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
|
||||
{
|
||||
char *term;
|
||||
const char *f = format;
|
||||
size_t argc = 0;
|
||||
|
||||
if (flags & APA_CAT)
|
||||
{
|
||||
char **old_argv = a->argv;
|
||||
size_t i;
|
||||
argc = a->argc;
|
||||
a->argc += argv_argc (format);
|
||||
ALLOC_ARRAY_CLEAR (a->argv, char *, a->argc + 1);
|
||||
for (i = 0; i < argc; ++i)
|
||||
a->argv[i] = old_argv[i];
|
||||
free (old_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_reset (a);
|
||||
a->argc = argv_argc (format);
|
||||
ALLOC_ARRAY_CLEAR (a->argv, char *, a->argc + 1);
|
||||
}
|
||||
|
||||
while ((term = argv_term (&f)) != NULL)
|
||||
{
|
||||
ASSERT (argc < a->argc);
|
||||
if (term[0] == '%')
|
||||
{
|
||||
if (!strcmp (term, "%s"))
|
||||
{
|
||||
char *s = va_arg (arglist, char *);
|
||||
if (!s)
|
||||
s = "";
|
||||
a->argv[argc++] = string_alloc (s, NULL);
|
||||
}
|
||||
else if (!strcmp (term, "%d"))
|
||||
{
|
||||
char numstr[64];
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
|
||||
a->argv[argc++] = string_alloc (numstr, NULL);
|
||||
}
|
||||
else if (!strcmp (term, "%u"))
|
||||
{
|
||||
char numstr[64];
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
|
||||
a->argv[argc++] = string_alloc (numstr, NULL);
|
||||
}
|
||||
else if (!strcmp (term, "%s/%d"))
|
||||
{
|
||||
char numstr[64];
|
||||
char *s = va_arg (arglist, char *);
|
||||
|
||||
if (!s)
|
||||
s = "";
|
||||
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
|
||||
|
||||
{
|
||||
const size_t len = strlen(s) + strlen(numstr) + 2;
|
||||
char *combined = (char *) malloc (len);
|
||||
check_malloc_return (combined);
|
||||
|
||||
strcpy (combined, s);
|
||||
strcat (combined, "/");
|
||||
strcat (combined, numstr);
|
||||
a->argv[argc++] = combined;
|
||||
}
|
||||
}
|
||||
else if (!strcmp (term, "%s%s"))
|
||||
{
|
||||
char *s1 = va_arg (arglist, char *);
|
||||
char *s2 = va_arg (arglist, char *);
|
||||
char *combined;
|
||||
|
||||
if (!s1) s1 = "";
|
||||
if (!s2) s2 = "";
|
||||
combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
|
||||
check_malloc_return (combined);
|
||||
strcpy (combined, s1);
|
||||
strcat (combined, s2);
|
||||
a->argv[argc++] = combined;
|
||||
}
|
||||
else
|
||||
ASSERT (0);
|
||||
free (term);
|
||||
}
|
||||
else
|
||||
{
|
||||
a->argv[argc++] = term;
|
||||
}
|
||||
}
|
||||
ASSERT (argc == a->argc);
|
||||
}
|
||||
|
||||
/*
|
||||
* write a string to the end of a buffer that was
|
||||
* truncated by buf_printf
|
||||
|
32
buffer.h
32
buffer.h
@ -60,6 +60,7 @@ struct buffer
|
||||
|
||||
/* used by argv_x functions */
|
||||
struct argv {
|
||||
size_t capacity;
|
||||
size_t argc;
|
||||
char **argv;
|
||||
};
|
||||
@ -292,37 +293,6 @@ int openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* A printf-like function (that only recognizes a subset of standard printf
|
||||
* format operators) that prints arguments to an argv list instead
|
||||
* of a standard string. This is used to build up argv arrays for passing
|
||||
* to execve.
|
||||
*/
|
||||
void argv_init (struct argv *a);
|
||||
struct argv argv_new (void);
|
||||
void argv_reset (struct argv *a);
|
||||
size_t argv_argc (const char *format);
|
||||
char *argv_term (const char **f);
|
||||
const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
|
||||
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);
|
||||
|
||||
#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);
|
||||
|
||||
void argv_printf (struct argv *a, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
void argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* remove/add trailing characters
|
||||
*/
|
||||
|
@ -75,6 +75,7 @@
|
||||
#define D_CLOSE LOGLEV(2, 22, 0) /* show socket and TUN/TAP close */
|
||||
#define D_SHOW_OCC_HASH LOGLEV(2, 23, 0) /* show MD5 hash of option compatibility string */
|
||||
#define D_PROXY LOGLEV(2, 24, 0) /* show http proxy control packets */
|
||||
#define D_ARGV LOGLEV(2, 25, 0) /* show struct argv errors */
|
||||
|
||||
#define D_TLS_DEBUG_LOW LOGLEV(3, 20, 0) /* low frequency info from tls_session routines */
|
||||
#define D_GREMLIN LOGLEV(3, 30, 0) /* show simulated outage info from gremlin module */
|
||||
|
2
init.c
2
init.c
@ -923,7 +923,7 @@ do_route (const struct options *options,
|
||||
{
|
||||
struct argv argv = argv_new ();
|
||||
setenv_str (es, "script_type", "route-up");
|
||||
argv_printf (&argv, "%s", options->route_script);
|
||||
argv_printf (&argv, "%sc", options->route_script);
|
||||
openvpn_execve_check (&argv, es, S_SCRIPT, "Route script failed");
|
||||
argv_reset (&argv);
|
||||
}
|
||||
|
382
misc.c
382
misc.c
@ -220,7 +220,7 @@ run_up_down (const char *command,
|
||||
ASSERT (arg);
|
||||
setenv_str (es, "script_type", script_type);
|
||||
argv_printf (&argv,
|
||||
"%s %s %d %d %s %s %s",
|
||||
"%sc %s %d %d %s %s %s",
|
||||
command,
|
||||
arg,
|
||||
tun_mtu, link_mtu,
|
||||
@ -1190,24 +1190,6 @@ absolute_pathname (const char *pathname)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next largest power of 2
|
||||
* or u if u is a power of 2.
|
||||
*/
|
||||
unsigned int
|
||||
adjust_power_of_2 (unsigned int u)
|
||||
{
|
||||
unsigned int ret = 1;
|
||||
|
||||
while (ret < u)
|
||||
{
|
||||
ret <<= 1;
|
||||
ASSERT (ret > 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETPASS
|
||||
|
||||
static FILE *
|
||||
@ -1666,56 +1648,309 @@ openvpn_sleep (const int n)
|
||||
sleep (n);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Configure PATH. On Windows, sometimes PATH is not set correctly
|
||||
* by default.
|
||||
* Return the next largest power of 2
|
||||
* or u if u is a power of 2.
|
||||
*/
|
||||
void
|
||||
configure_path (void)
|
||||
size_t
|
||||
adjust_power_of_2 (size_t u)
|
||||
{
|
||||
#ifdef WIN32
|
||||
FILE *fp;
|
||||
fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
|
||||
if (fp)
|
||||
size_t ret = 1;
|
||||
|
||||
while (ret < u)
|
||||
{
|
||||
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);
|
||||
ret <<= 1;
|
||||
ASSERT (ret > 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* A printf-like function (that only recognizes a subset of standard printf
|
||||
* format operators) that prints arguments to an argv list instead
|
||||
* of a standard string. This is used to build up argv arrays for passing
|
||||
* to execve.
|
||||
*/
|
||||
|
||||
void
|
||||
argv_init (struct argv *a)
|
||||
{
|
||||
a->capacity = 0;
|
||||
a->argc = 0;
|
||||
a->argv = NULL;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_new (void)
|
||||
{
|
||||
struct argv ret;
|
||||
argv_init (&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
argv_reset (struct argv *a)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
free (a->argv[i]);
|
||||
free (a->argv);
|
||||
argv_init (a);
|
||||
}
|
||||
|
||||
static void
|
||||
argv_extend (struct argv *a, const size_t newcap)
|
||||
{
|
||||
if (newcap > a->capacity)
|
||||
{
|
||||
char **newargv;
|
||||
size_t i;
|
||||
ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
newargv[i] = a->argv[i];
|
||||
free (a->argv);
|
||||
a->argv = newargv;
|
||||
a->capacity = newcap;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
argv_grow (struct argv *a, const size_t add)
|
||||
{
|
||||
const size_t newargc = a->argc + add + 1;
|
||||
ASSERT (newargc > a->argc);
|
||||
argv_extend (a, adjust_power_of_2 (newargc));
|
||||
}
|
||||
|
||||
static void
|
||||
argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
|
||||
{
|
||||
argv_grow (a, 1);
|
||||
a->argv[a->argc++] = str;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_clone (const struct argv *a, const size_t headroom)
|
||||
{
|
||||
struct argv r;
|
||||
size_t i;
|
||||
|
||||
argv_init (&r);
|
||||
for (i = 0; i < headroom; ++i)
|
||||
argv_append (&r, NULL);
|
||||
if (a)
|
||||
{
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
argv_append (&r, string_alloc (a->argv[i], NULL));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_insert_head (const struct argv *a, const char *head)
|
||||
{
|
||||
struct argv r;
|
||||
|
||||
r = argv_clone (a, 1);
|
||||
r.argv[0] = string_alloc (head, NULL);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
argv_term (const char **f)
|
||||
{
|
||||
const char *p = *f;
|
||||
const char *term = NULL;
|
||||
size_t termlen = 0;
|
||||
|
||||
if (*p == '\0')
|
||||
return NULL;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const int c = *p;
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (!isspace (c))
|
||||
++termlen;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isspace (c))
|
||||
{
|
||||
term = p;
|
||||
termlen = 1;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*f = p;
|
||||
|
||||
if (term)
|
||||
{
|
||||
char *ret;
|
||||
ASSERT (termlen > 0);
|
||||
ret = malloc (termlen + 1);
|
||||
check_malloc_return (ret);
|
||||
memcpy (ret, term, termlen);
|
||||
ret[termlen] = '\0';
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
|
||||
{
|
||||
if (a->argv)
|
||||
return print_argv ((const char **)a->argv, gc, flags);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
argv_msg (const int msglev, const struct argv *a)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (msglev, "%s", argv_str (a, &gc, 0));
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf (struct argv *a, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start (arglist, format);
|
||||
argv_printf_arglist (a, format, 0, arglist);
|
||||
va_end (arglist);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start (arglist, format);
|
||||
argv_printf_arglist (a, format, APA_CAT, arglist);
|
||||
va_end (arglist);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
char *term;
|
||||
const char *f = format;
|
||||
|
||||
if (!(flags & APA_CAT))
|
||||
argv_reset (a);
|
||||
argv_extend (a, 1); /* ensure trailing NULL */
|
||||
|
||||
while ((term = argv_term (&f)) != NULL)
|
||||
{
|
||||
if (term[0] == '%')
|
||||
{
|
||||
if (!strcmp (term, "%s"))
|
||||
{
|
||||
char *s = va_arg (arglist, char *);
|
||||
if (!s)
|
||||
s = "";
|
||||
argv_append (a, string_alloc (s, NULL));
|
||||
}
|
||||
else if (!strcmp (term, "%sc"))
|
||||
{
|
||||
char *s = va_arg (arglist, char *);
|
||||
if (s)
|
||||
{
|
||||
int nparms;
|
||||
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));
|
||||
}
|
||||
else
|
||||
argv_append (a, string_alloc ("", NULL));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
else if (!strcmp (term, "%s/%d"))
|
||||
{
|
||||
char numstr[64];
|
||||
char *s = va_arg (arglist, char *);
|
||||
|
||||
if (!s)
|
||||
s = "";
|
||||
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
|
||||
|
||||
{
|
||||
const size_t len = strlen(s) + strlen(numstr) + 2;
|
||||
char *combined = (char *) malloc (len);
|
||||
check_malloc_return (combined);
|
||||
|
||||
strcpy (combined, s);
|
||||
strcat (combined, "/");
|
||||
strcat (combined, numstr);
|
||||
argv_append (a, combined);
|
||||
}
|
||||
}
|
||||
else if (!strcmp (term, "%s%s"))
|
||||
{
|
||||
char *s1 = va_arg (arglist, char *);
|
||||
char *s2 = va_arg (arglist, char *);
|
||||
char *combined;
|
||||
|
||||
if (!s1) s1 = "";
|
||||
if (!s2) s2 = "";
|
||||
combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
|
||||
check_malloc_return (combined);
|
||||
strcpy (combined, s1);
|
||||
strcat (combined, s2);
|
||||
argv_append (a, combined);
|
||||
}
|
||||
else
|
||||
ASSERT (0);
|
||||
free (term);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_append (a, term);
|
||||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ARGV_TEST
|
||||
void
|
||||
argv_test (void)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
char line[512];
|
||||
const char *s;
|
||||
|
||||
struct argv a;
|
||||
@ -1729,7 +1964,7 @@ argv_test (void)
|
||||
#endif
|
||||
|
||||
argv_msg_prefix (M_INFO, &a, "ARGV");
|
||||
openvpn_execve_check (&a, NULL, 0, "command failed");
|
||||
//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);
|
||||
@ -1742,7 +1977,7 @@ argv_test (void)
|
||||
printf ("%s\n", s);
|
||||
}
|
||||
|
||||
argv_printf (&a, "foo bar %d", 99);
|
||||
argv_printf (&a, "%sc foo bar %d", "\"multi term\" command following \\\"spaces", 99);
|
||||
s = argv_str (&a, &gc, PA_BRACKET);
|
||||
argv_reset (&a);
|
||||
printf ("%s\n", s);
|
||||
@ -1752,25 +1987,28 @@ argv_test (void)
|
||||
printf ("%s\n", s);
|
||||
|
||||
argv_printf (&a, "foo bar %d", 99);
|
||||
argv_printf_cat (&a, "bar %d foo", 42);
|
||||
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);
|
||||
|
||||
#if 0
|
||||
while (fgets (line, sizeof(line), stdin) != NULL)
|
||||
{
|
||||
char *term;
|
||||
const char *f = line;
|
||||
int i = 0;
|
||||
{
|
||||
char line[512];
|
||||
while (fgets (line, sizeof(line), stdin) != NULL)
|
||||
{
|
||||
char *term;
|
||||
const char *f = line;
|
||||
int i = 0;
|
||||
|
||||
while ((term = argv_term (&f)) != NULL)
|
||||
{
|
||||
printf ("[%d] '%s'\n", i, term);
|
||||
++i;
|
||||
free (term);
|
||||
}
|
||||
}
|
||||
while ((term = argv_term (&f)) != NULL)
|
||||
{
|
||||
printf ("[%d] '%s'\n", i, term);
|
||||
++i;
|
||||
free (term);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
argv_reset (&a);
|
||||
|
36
misc.h
36
misc.h
@ -221,9 +221,6 @@ bool delete_file (const char *filename);
|
||||
/* return true if pathname is absolute */
|
||||
bool absolute_pathname (const char *pathname);
|
||||
|
||||
/* return the next largest power of 2 */
|
||||
unsigned int adjust_power_of_2 (unsigned int u);
|
||||
|
||||
/*
|
||||
* Get and store a username/password
|
||||
*/
|
||||
@ -300,4 +297,37 @@ 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 */
|
||||
|
||||
/* return the next largest power of 2 */
|
||||
size_t adjust_power_of_2 (size_t u);
|
||||
|
||||
/*
|
||||
* A printf-like function (that only recognizes a subset of standard printf
|
||||
* format operators) that prints arguments to an argv list instead
|
||||
* of a standard string. This is used to build up argv arrays for passing
|
||||
* to execve.
|
||||
*/
|
||||
void argv_init (struct argv *a);
|
||||
struct argv argv_new (void);
|
||||
void argv_reset (struct argv *a);
|
||||
char *argv_term (const char **f);
|
||||
const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
|
||||
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);
|
||||
|
||||
#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);
|
||||
|
||||
void argv_printf (struct argv *a, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
void argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif
|
||||
|
6
multi.c
6
multi.c
@ -103,7 +103,7 @@ learn_address_script (const struct multi_context *m,
|
||||
{
|
||||
struct argv argv = argv_new ();
|
||||
setenv_str (es, "script_type", "learn-address");
|
||||
argv_printf (&argv, "%s %s %s",
|
||||
argv_printf (&argv, "%sc %s %s",
|
||||
m->top.options.learn_address_script,
|
||||
op,
|
||||
mroute_addr_print (addr, &gc));
|
||||
@ -473,7 +473,7 @@ multi_client_disconnect_script (struct multi_context *m,
|
||||
{
|
||||
struct argv argv = argv_new ();
|
||||
setenv_str (mi->context.c2.es, "script_type", "client-disconnect");
|
||||
argv_printf (&argv, "%s", mi->context.options.client_disconnect_script);
|
||||
argv_printf (&argv, "%sc", mi->context.options.client_disconnect_script);
|
||||
openvpn_execve_check (&argv, mi->context.c2.es, S_SCRIPT, "client-disconnect command failed");
|
||||
argv_reset (&argv);
|
||||
}
|
||||
@ -1568,7 +1568,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
|
||||
|
||||
delete_file (dc_file);
|
||||
|
||||
argv_printf (&argv, "%s %s",
|
||||
argv_printf (&argv, "%sc %s",
|
||||
mi->context.options.client_connect_script,
|
||||
dc_file);
|
||||
|
||||
|
2
socket.c
2
socket.c
@ -1539,7 +1539,7 @@ ipchange_fmt (const bool include_cmd, struct argv *argv, const struct link_socke
|
||||
const char *ip = print_sockaddr_ex (&info->lsa->actual.dest, NULL, 0, gc);
|
||||
const char *port = print_sockaddr_ex (&info->lsa->actual.dest, NULL, PS_DONT_SHOW_ADDR|PS_SHOW_PORT, gc);
|
||||
if (include_cmd)
|
||||
argv_printf (argv, "%s %s %s",
|
||||
argv_printf (argv, "%sc %s %s",
|
||||
info->ipchange_command,
|
||||
ip,
|
||||
port);
|
||||
|
4
ssl.c
4
ssl.c
@ -718,7 +718,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
||||
|
||||
setenv_str (opt->es, "script_type", "tls-verify");
|
||||
|
||||
argv_printf (&argv, "%s %d %s",
|
||||
argv_printf (&argv, "%sc %d %s",
|
||||
opt->verify_command,
|
||||
ctx->error_depth,
|
||||
subject);
|
||||
@ -2937,7 +2937,7 @@ verify_user_pass_script (struct tls_session *session, const struct user_pass *up
|
||||
setenv_untrusted (session);
|
||||
|
||||
/* format command line */
|
||||
argv_printf (&argv, "%s %s", session->opt->auth_user_pass_verify_script, tmp_file);
|
||||
argv_printf (&argv, "%sc %s", session->opt->auth_user_pass_verify_script, tmp_file);
|
||||
|
||||
/* call command */
|
||||
retval = openvpn_execve (&argv, session->opt->es, S_SCRIPT);
|
||||
|
Loading…
x
Reference in New Issue
Block a user