summaryrefslogtreecommitdiff
path: root/src/openvpn/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/misc.c')
-rw-r--r--src/openvpn/misc.c728
1 files changed, 168 insertions, 560 deletions
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 48ca0d5..56d43e0 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -6,6 +6,8 @@
* packet compression.
*
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com>
+ * Copyright (C) 2016 David Sommerseth <davids@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -62,7 +64,7 @@ run_up_down (const char *command,
const struct plugin_list *plugins,
int plugin_type,
const char *arg,
-#ifdef WIN32
+#ifdef _WIN32
DWORD adapter_index,
#endif
const char *dev_type,
@@ -85,7 +87,7 @@ run_up_down (const char *command,
setenv_str (es, "dev", arg);
if (dev_type)
setenv_str (es, "dev_type", dev_type);
-#ifdef WIN32
+#ifdef _WIN32
setenv_int (es, "dev_idx", adapter_index);
#endif
@@ -118,13 +120,9 @@ run_up_down (const char *command,
struct argv argv = argv_new ();
ASSERT (arg);
setenv_str (es, "script_type", script_type);
- argv_printf (&argv,
- "%sc %s %d %d %s %s %s",
- command,
- arg,
- tun_mtu, link_mtu,
- ifconfig_local, ifconfig_remote,
- context);
+ argv_parse_cmd (&argv, command);
+ argv_printf_cat (&argv, "%s %d %d %s %s %s", arg, tun_mtu, link_mtu,
+ ifconfig_local, ifconfig_remote, context);
argv_msg (M_INFO, &argv);
openvpn_run_script (&argv, es, S_FATAL, "--up/--down");
argv_reset (&argv);
@@ -192,38 +190,13 @@ save_inetd_socket_descriptor (void)
}
/*
- * Warn if a given file is group/others accessible.
- */
-void
-warn_if_group_others_accessible (const char* filename)
-{
-#ifndef WIN32
-#ifdef HAVE_STAT
- if (strcmp (filename, INLINE_FILE_TAG))
- {
- struct stat st;
- if (stat (filename, &st))
- {
- msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename);
- }
- else
- {
- if (st.st_mode & (S_IRWXG|S_IRWXO))
- msg (M_WARN, "WARNING: file '%s' is group or others accessible", filename);
- }
- }
-#endif
-#endif
-}
-
-/*
* Print an error message based on the status code returned by system().
*/
const char *
system_error_message (int stat, struct gc_arena *gc)
{
struct buffer out = alloc_buf_gc (256, gc);
-#ifdef WIN32
+#ifdef _WIN32
if (stat == -1)
buf_printf (&out, "external program did not execute -- ");
buf_printf (&out, "returned error code %d", stat);
@@ -279,7 +252,7 @@ openvpn_execve_allowed (const unsigned int flags)
}
-#ifndef WIN32
+#ifndef _WIN32
/*
* Run execve() inside a fork(). Designed to replicate the semantics of system() but
* in a safer way that doesn't require the invocation of a shell or the risks
@@ -362,27 +335,29 @@ openvpn_popen (const struct argv *a, const struct env_set *es)
pid = fork ();
if (pid == (pid_t)0) /* child side */
{
- close (pipe_stdout[0]);
+ close (pipe_stdout[0]); /* Close read end */
dup2 (pipe_stdout[1],1);
execve (cmd, argv, envp);
exit (127);
}
- else if (pid < (pid_t)0) /* fork failed */
- {
- msg (M_ERR, "openvpn_popen: unable to fork");
- }
- else /* parent side */
+ else if (pid > (pid_t)0) /* parent side */
{
int status = 0;
+ close (pipe_stdout[1]); /* Close write end */
waitpid(pid, &status, 0);
ret = pipe_stdout[0];
+ }
+ else /* fork failed */
+ {
+ close (pipe_stdout[0]);
close (pipe_stdout[1]);
+ msg (M_ERR, "openvpn_popen: unable to fork %s", cmd);
}
}
else {
- msg (M_WARN, "openvpn_popen: unable to create stdout pipe");
- ret = -1;
+ msg (M_WARN, "openvpn_popen: unable to create stdout pipe for %s", cmd);
+ ret = -1;
}
}
else if (!warn_shown && (script_security < SSEC_SCRIPTS))
@@ -611,6 +586,16 @@ env_set_add (struct env_set *es, const char *str)
env_set_add_nolock (es, str);
}
+const char*
+env_set_get (const struct env_set *es, const char *name)
+{
+ const struct env_item *item = es->list;
+ while (item && !env_string_equal(item->string, name)) {
+ item = item->next;
+ }
+ return item ? item->string : NULL;
+}
+
void
env_set_print (int msglevel, const struct env_set *es)
{
@@ -701,14 +686,6 @@ env_set_remove_from_environment (const struct env_set *es)
}
}
-#ifdef HAVE_PUTENV
-
-/* companion functions to putenv */
-
-static struct env_item *global_env = NULL; /* GLOBAL */
-
-#endif
-
/* add/modify/delete environmental strings */
void
@@ -753,6 +730,28 @@ setenv_str_safe (struct env_set *es, const char *name, const char *value)
msg (M_WARN, "setenv_str_safe: name overflow");
}
+void setenv_str_incr(struct env_set *es, const char *name, const char *value)
+{
+ unsigned int counter = 1;
+ const size_t tmpname_len = strlen(name) + 5; /* 3 digits counter max */
+ char *tmpname = gc_malloc(tmpname_len, true, NULL);
+ strcpy(tmpname, name);
+ while (NULL != env_set_get(es, tmpname) && counter < 1000)
+ {
+ ASSERT (openvpn_snprintf (tmpname, tmpname_len, "%s_%u", name, counter));
+ counter++;
+ }
+ if (counter < 1000)
+ {
+ setenv_str (es, tmpname, value);
+ }
+ else
+ {
+ msg (D_TLS_DEBUG_MED, "Too many same-name env variables, ignoring: %s", name);
+ }
+ free (tmpname);
+}
+
void
setenv_del (struct env_set *es, const char *name)
{
@@ -830,32 +829,6 @@ setenv_str_i (struct env_set *es, const char *name, const char *value, const int
gc_free (&gc);
}
-/*
- * taken from busybox networking/ifupdown.c
- */
-unsigned int
-count_bits(unsigned int a)
-{
- unsigned int result;
- result = (a & 0x55) + ((a >> 1) & 0x55);
- result = (result & 0x33) + ((result >> 2) & 0x33);
- return((result & 0x0F) + ((result >> 4) & 0x0F));
-}
-
-int
-count_netmask_bits(const char *dotted_quad)
-{
- unsigned int result, a, b, c, d;
- /* Found a netmask... Check if it is dotted quad */
- if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
- return -1;
- result = count_bits(a);
- result += count_bits(b);
- result += count_bits(c);
- result += count_bits(d);
- return ((int)result);
-}
-
/* return true if filename can be opened for read */
bool
test_file (const char *filename)
@@ -977,7 +950,7 @@ hostname_randomize(const char *hostname, struct gc_arena *gc)
const char *
gen_path (const char *directory, const char *filename, struct gc_arena *gc)
{
-#if WIN32
+#ifdef _WIN32
const int CC_PATH_RESERVED = CC_LESS_THAN|CC_GREATER_THAN|CC_COLON|
CC_DOUBLE_QUOTE|CC_SLASH|CC_BACKSLASH|CC_PIPE|CC_QUESTION_MARK|CC_ASTERISK;
#else
@@ -988,7 +961,7 @@ gen_path (const char *directory, const char *filename, struct gc_arena *gc)
if (safe_filename
&& strcmp (safe_filename, ".")
&& strcmp (safe_filename, "..")
-#ifdef WIN32
+#ifdef _WIN32
&& win_safe_filename (safe_filename)
#endif
)
@@ -1016,7 +989,7 @@ absolute_pathname (const char *pathname)
if (pathname)
{
const int c = pathname[0];
-#ifdef WIN32
+#ifdef _WIN32
return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\');
#else
return c == '/';
@@ -1085,13 +1058,23 @@ get_user_pass_cr (struct user_pass *up,
struct buffer user_prompt = alloc_buf_gc (128, &gc);
buf_printf (&user_prompt, "NEED-OK|%s|%s:", prefix, up->username);
-
- if (!get_console_input (BSTR (&user_prompt), true, up->password, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix);
+ if (!query_user_SINGLE (BSTR(&user_prompt), BLEN(&user_prompt),
+ up->password, USER_PASS_LEN, false))
+ {
+ msg (M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix);
+ }
if (!strlen (up->password))
strcpy (up->password, "ok");
}
+ else if (flags & GET_USER_PASS_INLINE_CREDS)
+ {
+ struct buffer buf;
+ buf_set_read (&buf, (uint8_t*) auth_file, strlen (auth_file) + 1);
+ if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
+ buf_parse (&buf, '\n', up->username, USER_PASS_LEN);
+ buf_parse (&buf, '\n', up->password, USER_PASS_LEN);
+ }
/*
* Read from auth file unless this is a dynamic challenge request.
*/
@@ -1103,8 +1086,6 @@ get_user_pass_cr (struct user_pass *up,
FILE *fp;
char password_buf[USER_PASS_LEN] = { '\0' };
- warn_if_group_others_accessible (auth_file);
-
fp = platform_fopen (auth_file, "r");
if (!fp)
msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);
@@ -1155,13 +1136,17 @@ get_user_pass_cr (struct user_pass *up,
if (ac)
{
char *response = (char *) gc_malloc (USER_PASS_LEN, false, &gc);
- struct buffer packed_resp;
+ struct buffer packed_resp, challenge;
+ challenge = alloc_buf_gc (14+strlen(ac->challenge_text), &gc);
+ buf_printf (&challenge, "CHALLENGE: %s", ac->challenge_text);
buf_set_write (&packed_resp, (uint8_t*)up->password, USER_PASS_LEN);
- msg (M_INFO|M_NOPREFIX, "CHALLENGE: %s", ac->challenge_text);
- if (!get_console_input (ac->challenge_text, BOOL_CAST(ac->flags&CR_ECHO),
- response, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not read challenge response from stdin");
+
+ if (!query_user_SINGLE (BSTR(&challenge), BLEN(&challenge),
+ response, USER_PASS_LEN, BOOL_CAST(ac->flags&CR_ECHO)))
+ {
+ msg (M_FATAL, "ERROR: could not read challenge response from stdin");
+ }
strncpynt (up->username, ac->user, USER_PASS_LEN);
buf_printf (&packed_resp, "CRV1::%s::%s", ac->state_id, response);
}
@@ -1176,32 +1161,49 @@ get_user_pass_cr (struct user_pass *up,
struct buffer user_prompt = alloc_buf_gc (128, &gc);
struct buffer pass_prompt = alloc_buf_gc (128, &gc);
+ query_user_clear ();
buf_printf (&user_prompt, "Enter %s Username:", prefix);
buf_printf (&pass_prompt, "Enter %s Password:", prefix);
if (username_from_stdin && !(flags & GET_USER_PASS_PASSWORD_ONLY))
{
- if (!get_console_input (BSTR (&user_prompt), true, up->username, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not read %s username from stdin", prefix);
+ query_user_add (BSTR(&user_prompt), BLEN(&user_prompt),
+ up->username, USER_PASS_LEN, true);
+ }
+
+ if (password_from_stdin)
+ {
+ query_user_add (BSTR(&pass_prompt), BLEN(&pass_prompt),
+ up->password, USER_PASS_LEN, false);
+ }
+
+ if( !query_user_exec () )
+ {
+ msg(M_FATAL, "ERROR: Failed retrieving username or password");
+ }
+
+ if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
+ {
if (strlen (up->username) == 0)
msg (M_FATAL, "ERROR: %s username is empty", prefix);
}
- if (password_from_stdin && !get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not not read %s password from stdin", prefix);
-
#ifdef ENABLE_CLIENT_CR
if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE) && response_from_stdin)
{
char *response = (char *) gc_malloc (USER_PASS_LEN, false, &gc);
- struct buffer packed_resp;
+ struct buffer packed_resp, challenge;
char *pw64=NULL, *resp64=NULL;
- msg (M_INFO|M_NOPREFIX, "CHALLENGE: %s", auth_challenge);
+ challenge = alloc_buf_gc (14+strlen(auth_challenge), &gc);
+ buf_printf (&challenge, "CHALLENGE: %s", auth_challenge);
- if (!get_console_input (auth_challenge, BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO),
- response, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not read static challenge response from stdin");
+ if (!query_user_SINGLE (BSTR(&challenge), BLEN(&challenge),
+ response, USER_PASS_LEN,
+ BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO)))
+ {
+ msg (M_FATAL, "ERROR: could not retrieve static challenge response");
+ }
if (openvpn_base64_encode(up->password, strlen(up->password), &pw64) == -1
|| openvpn_base64_encode(response, strlen(response), &resp64) == -1)
msg (M_FATAL, "ERROR: could not base64-encode password/static_response");
@@ -1555,465 +1557,6 @@ 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)
-{
- a->capacity = 0;
- a->argc = 0;
- a->argv = NULL;
- a->system_str = 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);
- free (a->system_str);
- 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;
-}
-
-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)
-{
- char *ret = NULL;
- if (path)
- {
- char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */
- const char *bn = basename (path_cp);
- if (bn)
- {
- char *dot = NULL;
- ret = string_alloc (bn, NULL);
- dot = strrchr (ret, '.');
- if (dot)
- *dot = '\0';
- free(path_cp);
- if (ret[0] == '\0')
- {
- free(ret);
- ret = NULL;
- }
- }
- }
- return ret;
-}
-
-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)
-{
- 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));
- r.system_str = string_alloc (a->system_str, NULL);
- }
- return r;
-}
-
-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;
-}
-
-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));
- argv_system_str_append (a, s, true);
- }
- 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, 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_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"))
- {
- 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);
- argv_system_str_append (a, combined, false);
- }
- }
- 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 = "";
- combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
- check_malloc_return (combined);
- 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);
- free (term);
- }
- else
- {
- argv_append (a, term);
- argv_system_str_append (a, term, false);
- }
- }
- gc_free (&gc);
-}
-
-#ifdef ARGV_TEST
-void
-argv_test (void)
-{
- struct gc_arena gc = gc_new ();
- 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");*/
-
- 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 ("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);
- }
-
- 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);
-
- s = argv_str (&a, &gc, PA_BRACKET);
- printf ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&a));
- argv_reset (&a);
-
- 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 ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&a));
- argv_reset (&a);
-
-#if 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);
- }
- }
- }
-#endif
-
- argv_reset (&a);
- gc_free (&gc);
-}
-#endif
-
-/*
* Remove security-sensitive strings from control message
* so that they will not be output to log file.
*/
@@ -2040,6 +1583,15 @@ sanitize_control_message(const char *src, struct gc_arena *gc)
skip = 4;
redact = true;
}
+ else if (!check_debug_level(D_SHOW_KEYS)
+ && (c == 'a' && !strncmp(src, "auth-token ", 11)))
+ {
+ /* Unless --verb is 7 or higher (D_SHOW_KEYS), hide
+ * the auth-token value coming in the src string
+ */
+ skip = 10;
+ redact = true;
+ }
if (c == ',') /* end of redacted item? */
{
@@ -2084,3 +1636,59 @@ compat_flag (unsigned int flag)
return (compat_flags & (flag >> 1));
}
+
+#if P2MP_SERVER
+
+/* helper to parse peer_info received from multi client, validate
+ * (this is untrusted data) and put into environment
+ */
+bool
+validate_peer_info_line(char *line)
+{
+ uint8_t c;
+ int state = 0;
+ while (*line)
+ {
+ c = *line;
+ switch (state)
+ {
+ case 0:
+ case 1:
+ if (c == '=' && state == 1)
+ state = 2;
+ else if (isalnum(c) || c == '_')
+ state = 1;
+ else
+ return false;
+ case 2:
+ /* after the '=', replace non-printable or shell meta with '_' */
+ if (!isprint(c) || isspace(c) ||
+ c == '$' || c == '(' || c == '`' )
+ *line = '_';
+ }
+ line++;
+ }
+ return (state == 2);
+}
+
+void
+output_peer_info_env (struct env_set *es, const char * peer_info)
+{
+ char line[256];
+ struct buffer buf;
+ buf_set_read (&buf, (const uint8_t *) peer_info, strlen(peer_info));
+ while (buf_parse (&buf, '\n', line, sizeof (line)))
+ {
+ chomp (line);
+ if (validate_peer_info_line(line) &&
+ (strncmp(line, "IV_", 3) == 0 || strncmp(line, "UV_", 3) == 0) )
+ {
+ msg (M_INFO, "peer info: %s", line);
+ env_set_add(es, line);
+ }
+ else
+ msg (M_WARN, "validation failed on peer_info line received from client");
+ }
+}
+
+#endif /* P2MP_SERVER */