From 3a2bbdb05ca6a6996e424c9fb225cb0d53804125 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Iniesta Date: Tue, 27 Dec 2016 18:25:47 +0100 Subject: New upstream version 2.4.0 --- src/openvpn/misc.c | 2224 ++++++++++++++++++++++++++++------------------------ 1 file changed, 1193 insertions(+), 1031 deletions(-) (limited to 'src/openvpn/misc.c') diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index 4e06c91..87f03be 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -5,9 +5,9 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. * Copyright (C) 2014-2015 David Sommerseth - * Copyright (C) 2016 David Sommerseth + * Copyright (C) 2016-2017 David Sommerseth * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -60,92 +60,108 @@ int script_security = SSEC_BUILT_IN; /* GLOBAL */ * Used to execute the up/down script/plugins. */ void -run_up_down (const char *command, - const struct plugin_list *plugins, - int plugin_type, - const char *arg, +run_up_down(const char *command, + const struct plugin_list *plugins, + int plugin_type, + const char *arg, #ifdef _WIN32 - DWORD adapter_index, + DWORD adapter_index, #endif - const char *dev_type, - int tun_mtu, - int link_mtu, - const char *ifconfig_local, - const char* ifconfig_remote, - const char *context, - const char *signal_text, - const char *script_type, - struct env_set *es) -{ - struct gc_arena gc = gc_new (); - - if (signal_text) - setenv_str (es, "signal", signal_text); - setenv_str (es, "script_context", context); - setenv_int (es, "tun_mtu", tun_mtu); - setenv_int (es, "link_mtu", link_mtu); - setenv_str (es, "dev", arg); - if (dev_type) - setenv_str (es, "dev_type", dev_type); + const char *dev_type, + int tun_mtu, + int link_mtu, + const char *ifconfig_local, + const char *ifconfig_remote, + const char *context, + const char *signal_text, + const char *script_type, + struct env_set *es) +{ + struct gc_arena gc = gc_new(); + + if (signal_text) + { + setenv_str(es, "signal", signal_text); + } + setenv_str(es, "script_context", context); + setenv_int(es, "tun_mtu", tun_mtu); + setenv_int(es, "link_mtu", link_mtu); + setenv_str(es, "dev", arg); + if (dev_type) + { + setenv_str(es, "dev_type", dev_type); + } #ifdef _WIN32 - setenv_int (es, "dev_idx", adapter_index); + setenv_int(es, "dev_idx", adapter_index); #endif - if (!ifconfig_local) - ifconfig_local = ""; - if (!ifconfig_remote) - ifconfig_remote = ""; - if (!context) - context = ""; - - if (plugin_defined (plugins, plugin_type)) + if (!ifconfig_local) { - struct argv argv = argv_new (); - ASSERT (arg); - argv_printf (&argv, - "%s %d %d %s %s %s", - arg, - tun_mtu, link_mtu, - ifconfig_local, ifconfig_remote, - context); + ifconfig_local = ""; + } + if (!ifconfig_remote) + { + ifconfig_remote = ""; + } + if (!context) + { + context = ""; + } - if (plugin_call (plugins, plugin_type, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS) - msg (M_FATAL, "ERROR: up/down plugin call failed"); + if (plugin_defined(plugins, plugin_type)) + { + struct argv argv = argv_new(); + ASSERT(arg); + argv_printf(&argv, + "%s %d %d %s %s %s", + arg, + tun_mtu, link_mtu, + ifconfig_local, ifconfig_remote, + context); + + if (plugin_call(plugins, plugin_type, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS) + { + msg(M_FATAL, "ERROR: up/down plugin call failed"); + } - argv_reset (&argv); + argv_reset(&argv); } - if (command) + if (command) { - struct argv argv = argv_new (); - ASSERT (arg); - setenv_str (es, "script_type", script_type); - 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); + struct argv argv = argv_new(); + ASSERT(arg); + setenv_str(es, "script_type", script_type); + 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); } - gc_free (&gc); + gc_free(&gc); } /* Write our PID to a file */ void -write_pid (const char *filename) +write_pid(const char *filename) { - if (filename) + if (filename) { - unsigned int pid = 0; - FILE *fp = platform_fopen (filename, "w"); - if (!fp) - msg (M_ERR, "Open error on pid file %s", filename); + unsigned int pid = 0; + FILE *fp = platform_fopen(filename, "w"); + if (!fp) + { + msg(M_ERR, "Open error on pid file %s", filename); + } - pid = platform_getpid (); - fprintf(fp, "%u\n", pid); - if (fclose (fp)) - msg (M_ERR, "Close error on pid file %s", filename); + pid = platform_getpid(); + fprintf(fp, "%u\n", pid); + if (fclose(fp)) + { + msg(M_ERR, "Close error on pid file %s", filename); + } } } @@ -153,20 +169,22 @@ write_pid (const char *filename) * Set standard file descriptors to /dev/null */ void -set_std_files_to_null (bool stdin_only) +set_std_files_to_null(bool stdin_only) { #if defined(HAVE_DUP) && defined(HAVE_DUP2) - int fd; - if ((fd = open ("/dev/null", O_RDWR, 0)) != -1) - { - dup2 (fd, 0); - if (!stdin_only) - { - dup2 (fd, 1); - dup2 (fd, 2); - } - if (fd > 2) - close (fd); + int fd; + if ((fd = open("/dev/null", O_RDWR, 0)) != -1) + { + dup2(fd, 0); + if (!stdin_only) + { + dup2(fd, 1); + dup2(fd, 2); + } + if (fd > 2) + { + close(fd); + } } #endif } @@ -178,14 +196,16 @@ set_std_files_to_null (bool stdin_only) int inetd_socket_descriptor = SOCKET_UNDEFINED; /* GLOBAL */ void -save_inetd_socket_descriptor (void) +save_inetd_socket_descriptor(void) { - inetd_socket_descriptor = INETD_SOCKET_DESCRIPTOR; + inetd_socket_descriptor = INETD_SOCKET_DESCRIPTOR; #if defined(HAVE_DUP) && defined(HAVE_DUP2) - /* use handle passed by inetd/xinetd */ - if ((inetd_socket_descriptor = dup (INETD_SOCKET_DESCRIPTOR)) < 0) - msg (M_ERR, "INETD_SOCKET_DESCRIPTOR dup(%d) failed", INETD_SOCKET_DESCRIPTOR); - set_std_files_to_null (true); + /* use handle passed by inetd/xinetd */ + if ((inetd_socket_descriptor = dup(INETD_SOCKET_DESCRIPTOR)) < 0) + { + msg(M_ERR, "INETD_SOCKET_DESCRIPTOR dup(%d) failed", INETD_SOCKET_DESCRIPTOR); + } + set_std_files_to_null(true); #endif } @@ -193,62 +213,82 @@ save_inetd_socket_descriptor (void) * Print an error message based on the status code returned by system(). */ const char * -system_error_message (int stat, struct gc_arena *gc) +system_error_message(int stat, struct gc_arena *gc) { - struct buffer out = alloc_buf_gc (256, gc); + struct buffer out = alloc_buf_gc(256, gc); #ifdef _WIN32 - if (stat == -1) - buf_printf (&out, "external program did not execute -- "); - buf_printf (&out, "returned error code %d", stat); -#else - if (stat == -1) - buf_printf (&out, "external program fork failed"); - else if (!WIFEXITED (stat)) - buf_printf (&out, "external program did not exit normally"); - else - { - const int cmd_ret = WEXITSTATUS (stat); - if (!cmd_ret) - buf_printf (&out, "external program exited normally"); - else if (cmd_ret == 127) - buf_printf (&out, "could not execute external program"); - else - buf_printf (&out, "external program exited with error status: %d", cmd_ret); + if (stat == -1) + { + buf_printf(&out, "external program did not execute -- "); } -#endif - return (const char *)out.data; + buf_printf(&out, "returned error code %d", stat); +#else /* ifdef _WIN32 */ + if (stat == -1) + { + buf_printf(&out, "external program fork failed"); + } + else if (!WIFEXITED(stat)) + { + buf_printf(&out, "external program did not exit normally"); + } + else + { + const int cmd_ret = WEXITSTATUS(stat); + if (!cmd_ret) + { + buf_printf(&out, "external program exited normally"); + } + else if (cmd_ret == 127) + { + buf_printf(&out, "could not execute external program"); + } + else + { + buf_printf(&out, "external program exited with error status: %d", cmd_ret); + } + } +#endif /* ifdef _WIN32 */ + return (const char *)out.data; } /* * Wrapper around openvpn_execve */ bool -openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message) +openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message) { - struct gc_arena gc = gc_new (); - const int stat = openvpn_execve (a, es, flags); - int ret = false; + struct gc_arena gc = gc_new(); + const int stat = openvpn_execve(a, es, flags); + int ret = false; - if (platform_system_ok (stat)) - ret = true; - else + if (platform_system_ok(stat)) + { + ret = true; + } + else { - if (error_message) - msg (((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s", - error_message, - system_error_message (stat, &gc)); + if (error_message) + { + msg(((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s", + error_message, + system_error_message(stat, &gc)); + } } - gc_free (&gc); - return ret; + gc_free(&gc); + return ret; } bool -openvpn_execve_allowed (const unsigned int flags) +openvpn_execve_allowed(const unsigned int flags) { - if (flags & S_SCRIPT) - return script_security >= SSEC_SCRIPTS; - else - return script_security >= SSEC_BUILT_IN; + if (flags & S_SCRIPT) + { + return script_security >= SSEC_SCRIPTS; + } + else + { + return script_security >= SSEC_BUILT_IN; + } } @@ -259,54 +299,58 @@ openvpn_execve_allowed (const unsigned int flags) * assocated with formatting and parsing a command line. */ int -openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags) +openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags) { - struct gc_arena gc = gc_new (); - int ret = -1; - static bool warn_shown = false; + struct gc_arena gc = gc_new(); + int ret = -1; + static bool warn_shown = false; - if (a && a->argv[0]) + if (a && a->argv[0]) { #if defined(ENABLE_FEATURE_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; - - pid = fork (); - if (pid == (pid_t)0) /* child side */ + 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; + + pid = fork(); + if (pid == (pid_t)0) /* child side */ { - execve (cmd, argv, envp); - exit (127); + execve(cmd, argv, envp); + exit(127); } - else if (pid < (pid_t)0) /* fork failed */ - msg (M_ERR, "openvpn_execve: unable to fork"); - else /* parent side */ + else if (pid < (pid_t)0) /* fork failed */ { - if (waitpid (pid, &ret, 0) != pid) - ret = -1; + msg(M_ERR, "openvpn_execve: unable to fork"); + } + else /* parent side */ + { + if (waitpid(pid, &ret, 0) != pid) + { + ret = -1; + } } } - else if (!warn_shown && (script_security < SSEC_SCRIPTS)) - { - msg (M_WARN, SCRIPT_SECURITY_WARNING); - warn_shown = true; - } -#else - msg (M_WARN, "openvpn_execve: execve function not available"); -#endif + else if (!warn_shown && (script_security < SSEC_SCRIPTS)) + { + msg(M_WARN, SCRIPT_SECURITY_WARNING); + warn_shown = true; + } +#else /* if defined(ENABLE_FEATURE_EXECVE) */ + msg(M_WARN, "openvpn_execve: execve function not available"); +#endif /* if defined(ENABLE_FEATURE_EXECVE) */ } - else + else { - msg (M_FATAL, "openvpn_execve: called with empty argv"); + msg(M_FATAL, "openvpn_execve: called with empty argv"); } - gc_free (&gc); - return ret; + gc_free(&gc); + return ret; } -#endif +#endif /* ifndef _WIN32 */ /* * Run execve() inside a fork(), duping stdout. Designed to replicate the semantics of popen() but @@ -314,68 +358,70 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i * assocated with formatting and parsing a command line. */ int -openvpn_popen (const struct argv *a, const struct env_set *es) +openvpn_popen(const struct argv *a, const struct env_set *es) { - struct gc_arena gc = gc_new (); - int ret = -1; - static bool warn_shown = false; + struct gc_arena gc = gc_new(); + int ret = -1; + static bool warn_shown = false; - if (a && a->argv[0]) + if (a && a->argv[0]) { #if defined(ENABLE_FEATURE_EXECVE) - if (script_security >= SSEC_BUILT_IN) - { - 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; - int pipe_stdout[2]; - - if (pipe (pipe_stdout) == 0) { - pid = fork (); - if (pid == (pid_t)0) /* child side */ - { - close (pipe_stdout[0]); /* Close read end */ - dup2 (pipe_stdout[1],1); - execve (cmd, argv, envp); - exit (127); - } - 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 for %s", cmd); + if (script_security >= SSEC_BUILT_IN) + { + 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; + int pipe_stdout[2]; + + if (pipe(pipe_stdout) == 0) + { + pid = fork(); + if (pid == (pid_t)0) /* child side */ + { + close(pipe_stdout[0]); /* Close read end */ + dup2(pipe_stdout[1],1); + execve(cmd, argv, envp); + exit(127); + } + 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 for %s", cmd); ret = -1; - } - } - else if (!warn_shown && (script_security < SSEC_SCRIPTS)) - { - msg (M_WARN, SCRIPT_SECURITY_WARNING); - warn_shown = true; - } -#else - msg (M_WARN, "openvpn_popen: execve function not available"); -#endif + } + } + else if (!warn_shown && (script_security < SSEC_SCRIPTS)) + { + msg(M_WARN, SCRIPT_SECURITY_WARNING); + warn_shown = true; + } +#else /* if defined(ENABLE_FEATURE_EXECVE) */ + msg(M_WARN, "openvpn_popen: execve function not available"); +#endif /* if defined(ENABLE_FEATURE_EXECVE) */ } - else + else { - msg (M_FATAL, "openvpn_popen: called with empty argv"); + msg(M_FATAL, "openvpn_popen: called with empty argv"); } - gc_free (&gc); - return ret; + gc_free(&gc); + return ret; } @@ -390,27 +436,27 @@ openvpn_popen (const struct argv *a, const struct env_set *es) void init_random_seed(void) { - struct timeval tv; + struct timeval tv; - if (!gettimeofday (&tv, NULL)) + if (!gettimeofday(&tv, NULL)) { - const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec; - srandom (seed); + const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec; + srandom(seed); } } /* thread-safe strerror */ const char * -strerror_ts (int errnum, struct gc_arena *gc) +strerror_ts(int errnum, struct gc_arena *gc) { #ifdef HAVE_STRERROR - struct buffer out = alloc_buf_gc (256, gc); + struct buffer out = alloc_buf_gc(256, gc); - buf_printf (&out, "%s", openvpn_strerror (errnum, gc)); - return BSTR (&out); + buf_printf(&out, "%s", openvpn_strerror(errnum, gc)); + return BSTR(&out); #else - return "[error string unavailable]"; + return "[error string unavailable]"; #endif } @@ -425,491 +471,525 @@ strerror_ts (int errnum, struct gc_arena *gc) /* General-purpose environmental variable set functions */ static char * -construct_name_value (const char *name, const char *value, struct gc_arena *gc) +construct_name_value(const char *name, const char *value, struct gc_arena *gc) { - struct buffer out; + struct buffer out; - ASSERT (name); - if (!value) - value = ""; - out = alloc_buf_gc (strlen (name) + strlen (value) + 2, gc); - buf_printf (&out, "%s=%s", name, value); - return BSTR (&out); + ASSERT(name); + if (!value) + { + value = ""; + } + out = alloc_buf_gc(strlen(name) + strlen(value) + 2, gc); + buf_printf(&out, "%s=%s", name, value); + return BSTR(&out); } bool -deconstruct_name_value (const char *str, const char **name, const char **value, struct gc_arena *gc) +deconstruct_name_value(const char *str, const char **name, const char **value, struct gc_arena *gc) { - char *cp; + char *cp; - ASSERT (str); - ASSERT (name && value); + ASSERT(str); + ASSERT(name && value); - *name = cp = string_alloc (str, gc); - *value = NULL; + *name = cp = string_alloc(str, gc); + *value = NULL; - while ((*cp)) + while ((*cp)) { - if (*cp == '=' && !*value) - { - *cp = 0; - *value = cp + 1; - } - ++cp; + if (*cp == '=' && !*value) + { + *cp = 0; + *value = cp + 1; + } + ++cp; } - return *name && *value; + return *name && *value; } static bool -env_string_equal (const char *s1, const char *s2) +env_string_equal(const char *s1, const char *s2) { - int c1, c2; - ASSERT (s1); - ASSERT (s2); + int c1, c2; + ASSERT(s1); + ASSERT(s2); - while (true) + while (true) { - c1 = *s1++; - c2 = *s2++; - if (c1 == '=') - c1 = 0; - if (c2 == '=') - c2 = 0; - if (!c1 && !c2) - return true; - if (c1 != c2) - break; + c1 = *s1++; + c2 = *s2++; + if (c1 == '=') + { + c1 = 0; + } + if (c2 == '=') + { + c2 = 0; + } + if (!c1 && !c2) + { + return true; + } + if (c1 != c2) + { + break; + } } - return false; + return false; } static bool -remove_env_item (const char *str, const bool do_free, struct env_item **list) +remove_env_item(const char *str, const bool do_free, struct env_item **list) { - struct env_item *current, *prev; + struct env_item *current, *prev; - ASSERT (str); - ASSERT (list); + ASSERT(str); + ASSERT(list); - for (current = *list, prev = NULL; current != NULL; current = current->next) + for (current = *list, prev = NULL; current != NULL; current = current->next) { - if (env_string_equal (current->string, str)) - { - if (prev) - prev->next = current->next; - else - *list = current->next; - if (do_free) - { - secure_memzero (current->string, strlen (current->string)); - free (current->string); - free (current); - } - return true; - } - prev = current; + if (env_string_equal(current->string, str)) + { + if (prev) + { + prev->next = current->next; + } + else + { + *list = current->next; + } + if (do_free) + { + secure_memzero(current->string, strlen(current->string)); + free(current->string); + free(current); + } + return true; + } + prev = current; } - return false; + return false; } static void -add_env_item (char *str, const bool do_alloc, struct env_item **list, struct gc_arena *gc) +add_env_item(char *str, const bool do_alloc, struct env_item **list, struct gc_arena *gc) { - struct env_item *item; + struct env_item *item; - ASSERT (str); - ASSERT (list); + ASSERT(str); + ASSERT(list); - ALLOC_OBJ_GC (item, struct env_item, gc); - item->string = do_alloc ? string_alloc (str, gc): str; - item->next = *list; - *list = item; + ALLOC_OBJ_GC(item, struct env_item, gc); + item->string = do_alloc ? string_alloc(str, gc) : str; + item->next = *list; + *list = item; } /* struct env_set functions */ static bool -env_set_del_nolock (struct env_set *es, const char *str) +env_set_del_nolock(struct env_set *es, const char *str) { - return remove_env_item (str, es->gc == NULL, &es->list); + return remove_env_item(str, es->gc == NULL, &es->list); } static void -env_set_add_nolock (struct env_set *es, const char *str) +env_set_add_nolock(struct env_set *es, const char *str) { - remove_env_item (str, es->gc == NULL, &es->list); - add_env_item ((char *)str, true, &es->list, es->gc); + remove_env_item(str, es->gc == NULL, &es->list); + add_env_item((char *)str, true, &es->list, es->gc); } struct env_set * -env_set_create (struct gc_arena *gc) +env_set_create(struct gc_arena *gc) { - struct env_set *es; - ALLOC_OBJ_CLEAR_GC (es, struct env_set, gc); - es->list = NULL; - es->gc = gc; - return es; + struct env_set *es; + ALLOC_OBJ_CLEAR_GC(es, struct env_set, gc); + es->list = NULL; + es->gc = gc; + return es; } void -env_set_destroy (struct env_set *es) +env_set_destroy(struct env_set *es) { - if (es && es->gc == NULL) + if (es && es->gc == NULL) { - struct env_item *e = es->list; - while (e) - { - struct env_item *next = e->next; - free (e->string); - free (e); - e = next; - } - free (es); + struct env_item *e = es->list; + while (e) + { + struct env_item *next = e->next; + free(e->string); + free(e); + e = next; + } + free(es); } } bool -env_set_del (struct env_set *es, const char *str) +env_set_del(struct env_set *es, const char *str) { - bool ret; - ASSERT (es); - ASSERT (str); - ret = env_set_del_nolock (es, str); - return ret; + bool ret; + ASSERT(es); + ASSERT(str); + ret = env_set_del_nolock(es, str); + return ret; } void -env_set_add (struct env_set *es, const char *str) +env_set_add(struct env_set *es, const char *str) { - ASSERT (es); - ASSERT (str); - env_set_add_nolock (es, str); + ASSERT(es); + ASSERT(str); + env_set_add_nolock(es, str); } -const char* -env_set_get (const struct env_set *es, const char *name) +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; + 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) +env_set_print(int msglevel, const struct env_set *es) { - if (check_debug_level (msglevel)) + if (check_debug_level(msglevel)) { - const struct env_item *e; - int i; + const struct env_item *e; + int i; - if (es) - { - e = es->list; - i = 0; + if (es) + { + e = es->list; + i = 0; - while (e) - { - if (env_safe_to_print (e->string)) - msg (msglevel, "ENV [%d] '%s'", i, e->string); - ++i; - e = e->next; - } - } + while (e) + { + if (env_safe_to_print(e->string)) + { + msg(msglevel, "ENV [%d] '%s'", i, e->string); + } + ++i; + e = e->next; + } + } } } void -env_set_inherit (struct env_set *es, const struct env_set *src) +env_set_inherit(struct env_set *es, const struct env_set *src) { - const struct env_item *e; + const struct env_item *e; - ASSERT (es); + ASSERT(es); - if (src) + if (src) { - e = src->list; - while (e) - { - env_set_add_nolock (es, e->string); - e = e->next; - } + e = src->list; + while (e) + { + env_set_add_nolock(es, e->string); + e = e->next; + } } } void -env_set_add_to_environment (const struct env_set *es) +env_set_add_to_environment(const struct env_set *es) { - if (es) + if (es) { - struct gc_arena gc = gc_new (); - const struct env_item *e; + struct gc_arena gc = gc_new(); + const struct env_item *e; - e = es->list; + e = es->list; - while (e) - { - const char *name; - const char *value; + while (e) + { + const char *name; + const char *value; - if (deconstruct_name_value (e->string, &name, &value, &gc)) - setenv_str (NULL, name, value); + if (deconstruct_name_value(e->string, &name, &value, &gc)) + { + setenv_str(NULL, name, value); + } - e = e->next; - } - gc_free (&gc); + e = e->next; + } + gc_free(&gc); } } void -env_set_remove_from_environment (const struct env_set *es) +env_set_remove_from_environment(const struct env_set *es) { - if (es) + if (es) { - struct gc_arena gc = gc_new (); - const struct env_item *e; + struct gc_arena gc = gc_new(); + const struct env_item *e; - e = es->list; + e = es->list; - while (e) - { - const char *name; - const char *value; + while (e) + { + const char *name; + const char *value; - if (deconstruct_name_value (e->string, &name, &value, &gc)) - setenv_del (NULL, name); + if (deconstruct_name_value(e->string, &name, &value, &gc)) + { + setenv_del(NULL, name); + } - e = e->next; - } - gc_free (&gc); + e = e->next; + } + gc_free(&gc); } } /* add/modify/delete environmental strings */ void -setenv_counter (struct env_set *es, const char *name, counter_type value) +setenv_counter(struct env_set *es, const char *name, counter_type value) { - char buf[64]; - openvpn_snprintf (buf, sizeof(buf), counter_format, value); - setenv_str (es, name, buf); + char buf[64]; + openvpn_snprintf(buf, sizeof(buf), counter_format, value); + setenv_str(es, name, buf); } void -setenv_int (struct env_set *es, const char *name, int value) +setenv_int(struct env_set *es, const char *name, int value) { - char buf[64]; - openvpn_snprintf (buf, sizeof(buf), "%d", value); - setenv_str (es, name, buf); + char buf[64]; + openvpn_snprintf(buf, sizeof(buf), "%d", value); + setenv_str(es, name, buf); } void -setenv_unsigned (struct env_set *es, const char *name, unsigned int value) +setenv_unsigned(struct env_set *es, const char *name, unsigned int value) { - char buf[64]; - openvpn_snprintf (buf, sizeof(buf), "%u", value); - setenv_str (es, name, buf); + char buf[64]; + openvpn_snprintf(buf, sizeof(buf), "%u", value); + setenv_str(es, name, buf); } void -setenv_str (struct env_set *es, const char *name, const char *value) +setenv_str(struct env_set *es, const char *name, const char *value) { - setenv_str_ex (es, name, value, CC_NAME, 0, 0, CC_PRINT, 0, 0); + setenv_str_ex(es, name, value, CC_NAME, 0, 0, CC_PRINT, 0, 0); } void -setenv_str_safe (struct env_set *es, const char *name, const char *value) +setenv_str_safe(struct env_set *es, const char *name, const char *value) { - uint8_t b[64]; - struct buffer buf; - buf_set_write (&buf, b, sizeof (b)); - if (buf_printf (&buf, "OPENVPN_%s", name)) - setenv_str (es, BSTR(&buf), value); - else - msg (M_WARN, "setenv_str_safe: name overflow"); + uint8_t b[64]; + struct buffer buf; + buf_set_write(&buf, b, sizeof(b)); + if (buf_printf(&buf, "OPENVPN_%s", name)) + { + setenv_str(es, BSTR(&buf), value); + } + else + { + msg(M_WARN, "setenv_str_safe: name overflow"); + } } -void setenv_str_incr(struct env_set *es, const char *name, const char *value) +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) + 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++; + ASSERT(openvpn_snprintf(tmpname, tmpname_len, "%s_%u", name, counter)); + counter++; } - if (counter < 1000) + if (counter < 1000) { - setenv_str (es, tmpname, value); + setenv_str(es, tmpname, value); } - else + else { - msg (D_TLS_DEBUG_MED, "Too many same-name env variables, ignoring: %s", name); + msg(D_TLS_DEBUG_MED, "Too many same-name env variables, ignoring: %s", name); } - free (tmpname); + free(tmpname); } void -setenv_del (struct env_set *es, const char *name) +setenv_del(struct env_set *es, const char *name) { - ASSERT (name); - setenv_str (es, name, NULL); + ASSERT(name); + setenv_str(es, name, NULL); } void -setenv_str_ex (struct env_set *es, - const char *name, - const char *value, - const unsigned int name_include, - const unsigned int name_exclude, - const char name_replace, - const unsigned int value_include, - const unsigned int value_exclude, - const char value_replace) +setenv_str_ex(struct env_set *es, + const char *name, + const char *value, + const unsigned int name_include, + const unsigned int name_exclude, + const char name_replace, + const unsigned int value_include, + const unsigned int value_exclude, + const char value_replace) { - struct gc_arena gc = gc_new (); - const char *name_tmp; - const char *val_tmp = NULL; + struct gc_arena gc = gc_new(); + const char *name_tmp; + const char *val_tmp = NULL; - ASSERT (name && strlen (name) > 1); + ASSERT(name && strlen(name) > 1); - name_tmp = string_mod_const (name, name_include, name_exclude, name_replace, &gc); + name_tmp = string_mod_const(name, name_include, name_exclude, name_replace, &gc); - if (value) - val_tmp = string_mod_const (value, value_include, value_exclude, value_replace, &gc); + if (value) + { + val_tmp = string_mod_const(value, value_include, value_exclude, value_replace, &gc); + } - ASSERT (es); + ASSERT(es); - if (val_tmp) + if (val_tmp) { - const char *str = construct_name_value (name_tmp, val_tmp, &gc); - env_set_add (es, str); + const char *str = construct_name_value(name_tmp, val_tmp, &gc); + env_set_add(es, str); #if DEBUG_VERBOSE_SETENV - msg (M_INFO, "SETENV_ES '%s'", str); + msg(M_INFO, "SETENV_ES '%s'", str); #endif } - else - env_set_del (es, name_tmp); + else + { + env_set_del(es, name_tmp); + } - gc_free (&gc); + gc_free(&gc); } /* * Setenv functions that append an integer index to the name */ static const char * -setenv_format_indexed_name (const char *name, const int i, struct gc_arena *gc) +setenv_format_indexed_name(const char *name, const int i, struct gc_arena *gc) { - struct buffer out = alloc_buf_gc (strlen (name) + 16, gc); - if (i >= 0) - buf_printf (&out, "%s_%d", name, i); - else - buf_printf (&out, "%s", name); - return BSTR (&out); + struct buffer out = alloc_buf_gc(strlen(name) + 16, gc); + if (i >= 0) + { + buf_printf(&out, "%s_%d", name, i); + } + else + { + buf_printf(&out, "%s", name); + } + return BSTR(&out); } void -setenv_int_i (struct env_set *es, const char *name, const int value, const int i) +setenv_int_i(struct env_set *es, const char *name, const int value, const int i) { - struct gc_arena gc = gc_new (); - const char *name_str = setenv_format_indexed_name (name, i, &gc); - setenv_int (es, name_str, value); - gc_free (&gc); + struct gc_arena gc = gc_new(); + const char *name_str = setenv_format_indexed_name(name, i, &gc); + setenv_int(es, name_str, value); + gc_free(&gc); } void -setenv_str_i (struct env_set *es, const char *name, const char *value, const int i) +setenv_str_i(struct env_set *es, const char *name, const char *value, const int i) { - struct gc_arena gc = gc_new (); - const char *name_str = setenv_format_indexed_name (name, i, &gc); - setenv_str (es, name_str, value); - gc_free (&gc); + struct gc_arena gc = gc_new(); + const char *name_str = setenv_format_indexed_name(name, i, &gc); + setenv_str(es, name_str, value); + gc_free(&gc); } /* return true if filename can be opened for read */ bool -test_file (const char *filename) +test_file(const char *filename) { - bool ret = false; - if (filename) + bool ret = false; + if (filename) { - FILE *fp = platform_fopen (filename, "r"); - if (fp) - { - fclose (fp); - ret = true; - } - else - { - if( openvpn_errno () == EACCES ) { - msg( M_WARN | M_ERRNO, "Could not access file '%s'", filename); - } - } + FILE *fp = platform_fopen(filename, "r"); + if (fp) + { + fclose(fp); + ret = true; + } + else + { + if (openvpn_errno() == EACCES) + { + msg( M_WARN | M_ERRNO, "Could not access file '%s'", filename); + } + } } - dmsg (D_TEST_FILE, "TEST FILE '%s' [%d]", - filename ? filename : "UNDEF", - ret); + dmsg(D_TEST_FILE, "TEST FILE '%s' [%d]", + filename ? filename : "UNDEF", + ret); - return ret; + return ret; } #ifdef ENABLE_CRYPTO /* create a temporary filename in directory */ const char * -create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc) +create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc) { - static unsigned int counter; - struct buffer fname = alloc_buf_gc (256, gc); - int fd; - const char *retfname = NULL; - unsigned int attempts = 0; + static unsigned int counter; + struct buffer fname = alloc_buf_gc(256, gc); + int fd; + const char *retfname = NULL; + unsigned int attempts = 0; - do + do { - uint8_t rndbytes[16]; - const char *rndstr; + uint8_t rndbytes[16]; + const char *rndstr; - ++attempts; - ++counter; + ++attempts; + ++counter; - prng_bytes (rndbytes, sizeof rndbytes); - rndstr = format_hex_ex (rndbytes, sizeof rndbytes, 40, 0, NULL, gc); - buf_printf (&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr); + prng_bytes(rndbytes, sizeof rndbytes); + rndstr = format_hex_ex(rndbytes, sizeof rndbytes, 40, 0, NULL, gc); + buf_printf(&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr); - retfname = gen_path (directory, BSTR (&fname), gc); - if (!retfname) + retfname = gen_path(directory, BSTR(&fname), gc); + if (!retfname) { - msg (M_FATAL, "Failed to create temporary filename and path"); - return NULL; + msg(M_FATAL, "Failed to create temporary filename and path"); + return NULL; } - /* Atomically create the file. Errors out if the file already - exists. */ - fd = platform_open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); - if (fd != -1) + /* Atomically create the file. Errors out if the file already + * exists. */ + fd = platform_open(retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); + if (fd != -1) { - close (fd); - return retfname; + close(fd); + return retfname; } - else if (fd == -1 && errno != EEXIST) + else if (fd == -1 && errno != EEXIST) { - /* Something else went wrong, no need to retry. */ - struct gc_arena gcerr = gc_new (); - msg (M_FATAL, "Could not create temporary file '%s': %s", - retfname, strerror_ts (errno, &gcerr)); - gc_free (&gcerr); - return NULL; + /* Something else went wrong, no need to retry. */ + struct gc_arena gcerr = gc_new(); + msg(M_FATAL, "Could not create temporary file '%s': %s", + retfname, strerror_ts(errno, &gcerr)); + gc_free(&gcerr); + return NULL; } } - while (attempts < 6); + while (attempts < 6); - msg (M_FATAL, "Failed to create temporary file after %i attempts", attempts); - return NULL; + msg(M_FATAL, "Failed to create temporary file after %i attempts", attempts); + return NULL; } /* @@ -920,83 +1000,89 @@ create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc const char * hostname_randomize(const char *hostname, struct gc_arena *gc) { -# define n_rnd_bytes 6 +#define n_rnd_bytes 6 - uint8_t rnd_bytes[n_rnd_bytes]; - const char *rnd_str; - struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc); + uint8_t rnd_bytes[n_rnd_bytes]; + const char *rnd_str; + struct buffer hname = alloc_buf_gc(strlen(hostname)+sizeof(rnd_bytes)*2+4, gc); - prng_bytes (rnd_bytes, sizeof (rnd_bytes)); - rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc); - buf_printf(&hname, "%s.%s", rnd_str, hostname); - return BSTR(&hname); -# undef n_rnd_bytes + prng_bytes(rnd_bytes, sizeof(rnd_bytes)); + rnd_str = format_hex_ex(rnd_bytes, sizeof(rnd_bytes), 40, 0, NULL, gc); + buf_printf(&hname, "%s.%s", rnd_str, hostname); + return BSTR(&hname); +#undef n_rnd_bytes } -#else +#else /* ifdef ENABLE_CRYPTO */ const char * hostname_randomize(const char *hostname, struct gc_arena *gc) { - msg (M_WARN, "WARNING: hostname randomization disabled when crypto support is not compiled"); - return hostname; + msg(M_WARN, "WARNING: hostname randomization disabled when crypto support is not compiled"); + return hostname; } -#endif +#endif /* ifdef ENABLE_CRYPTO */ /* * Put a directory and filename together. */ const char * -gen_path (const char *directory, const char *filename, struct gc_arena *gc) +gen_path(const char *directory, const char *filename, struct gc_arena *gc) { #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; + 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 - const int CC_PATH_RESERVED = CC_SLASH; + const int CC_PATH_RESERVED = CC_SLASH; #endif - const char *safe_filename = string_mod_const (filename, CC_PRINT, CC_PATH_RESERVED, '_', gc); + const char *safe_filename = string_mod_const(filename, CC_PRINT, CC_PATH_RESERVED, '_', gc); - if (safe_filename - && strcmp (safe_filename, ".") - && strcmp (safe_filename, "..") + if (safe_filename + && strcmp(safe_filename, ".") + && strcmp(safe_filename, "..") #ifdef _WIN32 - && win_safe_filename (safe_filename) + && win_safe_filename(safe_filename) #endif - ) + ) { - const size_t outsize = strlen(safe_filename) + (directory ? strlen (directory) : 0) + 16; - struct buffer out = alloc_buf_gc (outsize, gc); - char dirsep[2]; + const size_t outsize = strlen(safe_filename) + (directory ? strlen(directory) : 0) + 16; + struct buffer out = alloc_buf_gc(outsize, gc); + char dirsep[2]; - dirsep[0] = OS_SPECIFIC_DIRSEP; - dirsep[1] = '\0'; + dirsep[0] = OS_SPECIFIC_DIRSEP; + dirsep[1] = '\0'; - if (directory) - buf_printf (&out, "%s%s", directory, dirsep); - buf_printf (&out, "%s", safe_filename); + if (directory) + { + buf_printf(&out, "%s%s", directory, dirsep); + } + buf_printf(&out, "%s", safe_filename); - return BSTR (&out); + return BSTR(&out); + } + else + { + return NULL; } - else - return NULL; } bool -absolute_pathname (const char *pathname) +absolute_pathname(const char *pathname) { - if (pathname) + if (pathname) { - const int c = pathname[0]; + const int c = pathname[0]; #ifdef _WIN32 - return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\'); + return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\'); #else - return c == '/'; + return c == '/'; #endif } - else - return false; + else + { + return false; + } } /* @@ -1004,233 +1090,263 @@ absolute_pathname (const char *pathname) */ bool -get_user_pass_cr (struct user_pass *up, - const char *auth_file, - const char *prefix, - const unsigned int flags, - const char *auth_challenge) +get_user_pass_cr(struct user_pass *up, + const char *auth_file, + const char *prefix, + const unsigned int flags, + const char *auth_challenge) { - struct gc_arena gc = gc_new (); + struct gc_arena gc = gc_new(); - if (!up->defined) + if (!up->defined) { - bool from_authfile = (auth_file && !streq (auth_file, "stdin")); - bool username_from_stdin = false; - bool password_from_stdin = false; - bool response_from_stdin = true; + bool from_authfile = (auth_file && !streq(auth_file, "stdin")); + bool username_from_stdin = false; + bool password_from_stdin = false; + bool response_from_stdin = true; - if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) - msg (M_WARN, "Note: previous '%s' credentials failed", prefix); + if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) + { + msg(M_WARN, "Note: previous '%s' credentials failed", prefix); + } #ifdef ENABLE_MANAGEMENT - /* - * Get username/password from management interface? - */ - if (management - && (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT)) - && management_query_user_pass_enabled (management)) - { - const char *sc = NULL; - response_from_stdin = false; - - if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) - management_auth_failure (management, prefix, "previous auth credentials failed"); + /* + * Get username/password from management interface? + */ + if (management + && (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT)) + && management_query_user_pass_enabled(management)) + { + const char *sc = NULL; + response_from_stdin = false; + + if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) + { + management_auth_failure(management, prefix, "previous auth credentials failed"); + } #ifdef ENABLE_CLIENT_CR - if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE)) - sc = auth_challenge; -#endif - if (!management_query_user_pass (management, up, prefix, flags, sc)) - { - if ((flags & GET_USER_PASS_NOFATAL) != 0) - return false; - else - msg (M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", prefix); - } - } - else + if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE)) + { + sc = auth_challenge; + } #endif - /* - * Get NEED_OK confirmation from the console - */ - if (flags & GET_USER_PASS_NEED_OK) - { - struct buffer user_prompt = alloc_buf_gc (128, &gc); - - buf_printf (&user_prompt, "NEED-OK|%s|%s:", prefix, up->username); - if (!query_user_SINGLE (BSTR(&user_prompt), BLEN(&user_prompt), - up->password, USER_PASS_LEN, false)) + if (!management_query_user_pass(management, up, prefix, flags, sc)) { - msg (M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix); + if ((flags & GET_USER_PASS_NOFATAL) != 0) + { + return false; + } + else + { + msg(M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", 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. - */ - else if (from_authfile && !(flags & GET_USER_PASS_DYNAMIC_CHALLENGE)) + } + else +#endif /* ifdef ENABLE_MANAGEMENT */ + /* + * Get NEED_OK confirmation from the console + */ + if (flags & GET_USER_PASS_NEED_OK) { - /* - * Try to get username/password from a file. - */ - FILE *fp; - char password_buf[USER_PASS_LEN] = { '\0' }; + struct buffer user_prompt = alloc_buf_gc(128, &gc); - fp = platform_fopen (auth_file, "r"); - if (!fp) - msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file); + buf_printf(&user_prompt, "NEED-OK|%s|%s:", prefix, up->username); + 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. + */ + else if (from_authfile && !(flags & GET_USER_PASS_DYNAMIC_CHALLENGE)) + { + /* + * Try to get username/password from a file. + */ + FILE *fp; + char password_buf[USER_PASS_LEN] = { '\0' }; + + fp = platform_fopen(auth_file, "r"); + if (!fp) + { + msg(M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file); + } - if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0) + if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0) { - /* Read username first */ - if (fgets (up->username, USER_PASS_LEN, fp) == NULL) - msg (M_FATAL, "Error reading username from %s authfile: %s", - prefix, - auth_file); - } - chomp (up->username); - - if (fgets (password_buf, USER_PASS_LEN, fp) != NULL) + /* Read username first */ + if (fgets(up->username, USER_PASS_LEN, fp) == NULL) + { + msg(M_FATAL, "Error reading username from %s authfile: %s", + prefix, + auth_file); + } + } + chomp(up->username); + + if (fgets(password_buf, USER_PASS_LEN, fp) != NULL) { - chomp (password_buf); + chomp(password_buf); } - if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0]) - msg (M_FATAL, "Error reading password from %s authfile: %s", prefix, auth_file); + if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0]) + { + msg(M_FATAL, "Error reading password from %s authfile: %s", prefix, auth_file); + } - if (password_buf[0]) - strncpy(up->password, password_buf, USER_PASS_LEN); - else - password_from_stdin = 1; + if (password_buf[0]) + { + strncpy(up->password, password_buf, USER_PASS_LEN); + } + else + { + password_from_stdin = 1; + } - fclose (fp); + fclose(fp); - if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen (up->username) == 0) - msg (M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file); + if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen(up->username) == 0) + { + msg(M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file); + } } - else + else { - username_from_stdin = true; - password_from_stdin = true; + username_from_stdin = true; + password_from_stdin = true; } - /* - * Get username/password from standard input? - */ - if (username_from_stdin || password_from_stdin || response_from_stdin) - { + /* + * Get username/password from standard input? + */ + if (username_from_stdin || password_from_stdin || response_from_stdin) + { #ifdef ENABLE_CLIENT_CR - if (auth_challenge && (flags & GET_USER_PASS_DYNAMIC_CHALLENGE) && response_from_stdin) - { - struct auth_challenge_info *ac = get_auth_challenge (auth_challenge, &gc); - if (ac) - { - char *response = (char *) gc_malloc (USER_PASS_LEN, false, &gc); - 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); - - 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); - } - else - { - msg (M_FATAL, "ERROR: received malformed challenge request from server"); - } - } - else -#endif - { - struct buffer user_prompt = alloc_buf_gc (128, &gc); - struct buffer pass_prompt = alloc_buf_gc (128, &gc); + if (auth_challenge && (flags & GET_USER_PASS_DYNAMIC_CHALLENGE) && response_from_stdin) + { + struct auth_challenge_info *ac = get_auth_challenge(auth_challenge, &gc); + if (ac) + { + char *response = (char *) gc_malloc(USER_PASS_LEN, false, &gc); + 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); + + 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); + } + else + { + msg(M_FATAL, "ERROR: received malformed challenge request from server"); + } + } + else +#endif /* ifdef ENABLE_CLIENT_CR */ + { + 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); + 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)) - { - query_user_add (BSTR(&user_prompt), BLEN(&user_prompt), - up->username, USER_PASS_LEN, true); - } + if (username_from_stdin && !(flags & GET_USER_PASS_PASSWORD_ONLY)) + { + query_user_add(BSTR(&user_prompt), BLEN(&user_prompt), + up->username, USER_PASS_LEN, true); + } - if (password_from_stdin) + if (password_from_stdin) { - query_user_add (BSTR(&pass_prompt), BLEN(&pass_prompt), - up->password, USER_PASS_LEN, false); + 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 (!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 (!(flags & GET_USER_PASS_PASSWORD_ONLY)) + { + if (strlen(up->username) == 0) + { + msg(M_FATAL, "ERROR: %s username is empty", 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, challenge; - char *pw64=NULL, *resp64=NULL; - - challenge = alloc_buf_gc (14+strlen(auth_challenge), &gc); - buf_printf (&challenge, "CHALLENGE: %s", auth_challenge); - - 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"); - buf_set_write (&packed_resp, (uint8_t*)up->password, USER_PASS_LEN); - buf_printf (&packed_resp, "SCRV1:%s:%s", pw64, resp64); - string_clear(pw64); - free(pw64); - string_clear(resp64); - free(resp64); - } -#endif - } - } + 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, challenge; + char *pw64 = NULL, *resp64 = NULL; + + challenge = alloc_buf_gc(14+strlen(auth_challenge), &gc); + buf_printf(&challenge, "CHALLENGE: %s", auth_challenge); + + 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"); + } + buf_set_write(&packed_resp, (uint8_t *)up->password, USER_PASS_LEN); + buf_printf(&packed_resp, "SCRV1:%s:%s", pw64, resp64); + string_clear(pw64); + free(pw64); + string_clear(resp64); + free(resp64); + } +#endif /* ifdef ENABLE_CLIENT_CR */ + } + } - string_mod (up->username, CC_PRINT, CC_CRLF, 0); - string_mod (up->password, CC_PRINT, CC_CRLF, 0); + string_mod(up->username, CC_PRINT, CC_CRLF, 0); + string_mod(up->password, CC_PRINT, CC_CRLF, 0); - up->defined = true; + up->defined = true; } #if 0 - msg (M_INFO, "GET_USER_PASS %s u='%s' p='%s'", prefix, up->username, up->password); + msg(M_INFO, "GET_USER_PASS %s u='%s' p='%s'", prefix, up->username, up->password); #endif - gc_free (&gc); + gc_free(&gc); - return true; + return true; } #ifdef ENABLE_CLIENT_CR @@ -1240,125 +1356,143 @@ get_user_pass_cr (struct user_pass *up, * the dynamic challenge/response protocol implemented here. */ struct auth_challenge_info * -get_auth_challenge (const char *auth_challenge, struct gc_arena *gc) -{ - if (auth_challenge) - { - struct auth_challenge_info *ac; - const int len = strlen (auth_challenge); - char *work = (char *) gc_malloc (len+1, false, gc); - char *cp; - - struct buffer b; - buf_set_read (&b, (const uint8_t *)auth_challenge, len); - - ALLOC_OBJ_CLEAR_GC (ac, struct auth_challenge_info, gc); - - /* parse prefix */ - if (!buf_parse(&b, ':', work, len)) - return NULL; - if (strcmp(work, "CRV1")) - return NULL; - - /* parse flags */ - if (!buf_parse(&b, ':', work, len)) - return NULL; - for (cp = work; *cp != '\0'; ++cp) - { - const char c = *cp; - if (c == 'E') - ac->flags |= CR_ECHO; - else if (c == 'R') - ac->flags |= CR_RESPONSE; - } - - /* parse state ID */ - if (!buf_parse(&b, ':', work, len)) - return NULL; - ac->state_id = string_alloc(work, gc); - - /* parse user name */ - if (!buf_parse(&b, ':', work, len)) - return NULL; - ac->user = (char *) gc_malloc (strlen(work)+1, true, gc); - openvpn_base64_decode(work, (void*)ac->user, -1); - - /* parse challenge text */ - ac->challenge_text = string_alloc(BSTR(&b), gc); - - return ac; - } - else - return NULL; +get_auth_challenge(const char *auth_challenge, struct gc_arena *gc) +{ + if (auth_challenge) + { + struct auth_challenge_info *ac; + const int len = strlen(auth_challenge); + char *work = (char *) gc_malloc(len+1, false, gc); + char *cp; + + struct buffer b; + buf_set_read(&b, (const uint8_t *)auth_challenge, len); + + ALLOC_OBJ_CLEAR_GC(ac, struct auth_challenge_info, gc); + + /* parse prefix */ + if (!buf_parse(&b, ':', work, len)) + { + return NULL; + } + if (strcmp(work, "CRV1")) + { + return NULL; + } + + /* parse flags */ + if (!buf_parse(&b, ':', work, len)) + { + return NULL; + } + for (cp = work; *cp != '\0'; ++cp) + { + const char c = *cp; + if (c == 'E') + { + ac->flags |= CR_ECHO; + } + else if (c == 'R') + { + ac->flags |= CR_RESPONSE; + } + } + + /* parse state ID */ + if (!buf_parse(&b, ':', work, len)) + { + return NULL; + } + ac->state_id = string_alloc(work, gc); + + /* parse user name */ + if (!buf_parse(&b, ':', work, len)) + { + return NULL; + } + ac->user = (char *) gc_malloc(strlen(work)+1, true, gc); + openvpn_base64_decode(work, (void *)ac->user, -1); + + /* parse challenge text */ + ac->challenge_text = string_alloc(BSTR(&b), gc); + + return ac; + } + else + { + return NULL; + } } -#endif +#endif /* ifdef ENABLE_CLIENT_CR */ #if AUTO_USERID void -get_user_pass_auto_userid (struct user_pass *up, const char *tag) +get_user_pass_auto_userid(struct user_pass *up, const char *tag) { - struct gc_arena gc = gc_new (); - struct buffer buf; - uint8_t macaddr[6]; - static uint8_t digest [MD5_DIGEST_LENGTH]; - static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST"; + struct gc_arena gc = gc_new(); + struct buffer buf; + uint8_t macaddr[6]; + static uint8_t digest [MD5_DIGEST_LENGTH]; + static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST"; - const md_kt_t *md5_kt = md_kt_get("MD5"); - md_ctx_t ctx; + const md_kt_t *md5_kt = md_kt_get("MD5"); + md_ctx_t ctx; - CLEAR (*up); - buf_set_write (&buf, (uint8_t*)up->username, USER_PASS_LEN); - buf_printf (&buf, "%s", TARGET_PREFIX); - if (get_default_gateway_mac_addr (macaddr)) + CLEAR(*up); + buf_set_write(&buf, (uint8_t *)up->username, USER_PASS_LEN); + buf_printf(&buf, "%s", TARGET_PREFIX); + if (get_default_gateway_mac_addr(macaddr)) + { + dmsg(D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex(macaddr, sizeof(macaddr), 0, 1, ":", &gc)); + md_ctx_init(&ctx, md5_kt); + md_ctx_update(&ctx, hashprefix, sizeof(hashprefix) - 1); + md_ctx_update(&ctx, macaddr, sizeof(macaddr)); + md_ctx_final(&ctx, digest); + md_ctx_cleanup(&ctx) + buf_printf(&buf, "%s", format_hex_ex(digest, sizeof(digest), 0, 256, " ", &gc)); + } + else { - dmsg (D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex (macaddr, sizeof (macaddr), 0, 1, ":", &gc)); - md_ctx_init(&ctx, md5_kt); - md_ctx_update(&ctx, hashprefix, sizeof (hashprefix) - 1); - md_ctx_update(&ctx, macaddr, sizeof (macaddr)); - md_ctx_final(&ctx, digest); - md_ctx_cleanup(&ctx) - buf_printf(&buf, "%s", format_hex_ex (digest, sizeof (digest), 0, 256, " ", &gc)); + buf_printf(&buf, "UNKNOWN"); } - else + if (tag && strcmp(tag, "stdin")) { - buf_printf (&buf, "UNKNOWN"); + buf_printf(&buf, "-%s", tag); } - if (tag && strcmp (tag, "stdin")) - buf_printf (&buf, "-%s", tag); - up->defined = true; - gc_free (&gc); + up->defined = true; + gc_free(&gc); - dmsg (D_AUTO_USERID, "GUPAU: AUTO_USERID: '%s'", up->username); + dmsg(D_AUTO_USERID, "GUPAU: AUTO_USERID: '%s'", up->username); } -#endif +#endif /* if AUTO_USERID */ void -purge_user_pass (struct user_pass *up, const bool force) +purge_user_pass(struct user_pass *up, const bool force) { - const bool nocache = up->nocache; - static bool warn_shown = false; - if (nocache || force) + const bool nocache = up->nocache; + static bool warn_shown = false; + if (nocache || force) { - secure_memzero (up, sizeof(*up)); - up->nocache = nocache; + secure_memzero(up, sizeof(*up)); + up->nocache = nocache; } - else if (!warn_shown) + else if (!warn_shown) { - msg (M_WARN, "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this"); - warn_shown = true; + msg(M_WARN, "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this"); + warn_shown = true; } } void -set_auth_token (struct user_pass *up, const char *token) +set_auth_token(struct user_pass *up, const char *token) { - if (token && strlen(token) && up && up->defined && !up->nocache) + if (token && strlen(token) && up && up->defined && !up->nocache) { - CLEAR (up->password); - strncpynt (up->password, token, USER_PASS_LEN); + CLEAR(up->password); + strncpynt(up->password, token, USER_PASS_LEN); } } @@ -1369,173 +1503,184 @@ set_auth_token (struct user_pass *up, const char *token) * Assumes that string has been null terminated. */ const char * -safe_print (const char *str, struct gc_arena *gc) +safe_print(const char *str, struct gc_arena *gc) { - return string_mod_const (str, CC_PRINT, CC_CRLF, '.', gc); + return string_mod_const(str, CC_PRINT, CC_CRLF, '.', gc); } static bool -is_password_env_var (const char *str) +is_password_env_var(const char *str) { - return (strncmp (str, "password", 8) == 0); + return (strncmp(str, "password", 8) == 0); } bool -env_allowed (const char *str) +env_allowed(const char *str) { - return (script_security >= SSEC_PW_ENV || !is_password_env_var (str)); + return (script_security >= SSEC_PW_ENV || !is_password_env_var(str)); } bool -env_safe_to_print (const char *str) +env_safe_to_print(const char *str) { #ifndef UNSAFE_DEBUG - if (is_password_env_var (str)) - return false; + if (is_password_env_var(str)) + { + return false; + } #endif - return true; + return true; } /* Make arrays of strings */ const char ** -make_env_array (const struct env_set *es, - const bool check_allowed, - struct gc_arena *gc) +make_env_array(const struct env_set *es, + const bool check_allowed, + struct gc_arena *gc) { - char **ret = NULL; - struct env_item *e = NULL; - int i = 0, n = 0; + char **ret = NULL; + struct env_item *e = NULL; + int i = 0, n = 0; - /* figure length of es */ - if (es) + /* figure length of es */ + if (es) { - for (e = es->list; e != NULL; e = e->next) - ++n; + for (e = es->list; e != NULL; e = e->next) + ++n; } - /* alloc return array */ - ALLOC_ARRAY_CLEAR_GC (ret, char *, n+1, gc); + /* alloc return array */ + ALLOC_ARRAY_CLEAR_GC(ret, char *, n+1, gc); - /* fill return array */ - if (es) + /* fill return array */ + if (es) { - i = 0; - for (e = es->list; e != NULL; e = e->next) - { - if (!check_allowed || env_allowed (e->string)) - { - ASSERT (i < n); - ret[i++] = e->string; - } - } + i = 0; + for (e = es->list; e != NULL; e = e->next) + { + if (!check_allowed || env_allowed(e->string)) + { + ASSERT(i < n); + ret[i++] = e->string; + } + } } - ret[i] = NULL; - return (const char **)ret; + ret[i] = NULL; + return (const char **)ret; } const char ** -make_arg_array (const char *first, const char *parms, struct gc_arena *gc) +make_arg_array(const char *first, const char *parms, struct gc_arena *gc) { - char **ret = NULL; - int base = 0; - const int max_parms = MAX_PARMS + 2; - int n = 0; + char **ret = NULL; + int base = 0; + const int max_parms = MAX_PARMS + 2; + int n = 0; - /* alloc return array */ - ALLOC_ARRAY_CLEAR_GC (ret, char *, max_parms, gc); + /* alloc return array */ + ALLOC_ARRAY_CLEAR_GC(ret, char *, max_parms, gc); - /* process first parameter, if provided */ - if (first) + /* process first parameter, if provided */ + if (first) { - ret[base++] = string_alloc (first, gc); + ret[base++] = string_alloc(first, gc); } - if (parms) + if (parms) { - n = parse_line (parms, &ret[base], max_parms - base - 1, "make_arg_array", 0, M_WARN, gc); - ASSERT (n >= 0 && n + base + 1 <= max_parms); + n = parse_line(parms, &ret[base], max_parms - base - 1, "make_arg_array", 0, M_WARN, gc); + ASSERT(n >= 0 && n + base + 1 <= max_parms); } - ret[base + n] = NULL; + ret[base + n] = NULL; - return (const char **)ret; + return (const char **)ret; } static const char ** -make_inline_array (const char *str, struct gc_arena *gc) +make_inline_array(const char *str, struct gc_arena *gc) { - char line[OPTION_LINE_SIZE]; - struct buffer buf; - int len = 0; - char **ret = NULL; - int i = 0; + char line[OPTION_LINE_SIZE]; + struct buffer buf; + int len = 0; + char **ret = NULL; + int i = 0; - buf_set_read (&buf, (const uint8_t *) str, strlen (str)); - while (buf_parse (&buf, '\n', line, sizeof (line))) - ++len; + buf_set_read(&buf, (const uint8_t *) str, strlen(str)); + while (buf_parse(&buf, '\n', line, sizeof(line))) + ++len; - /* alloc return array */ - ALLOC_ARRAY_CLEAR_GC (ret, char *, len + 1, gc); + /* alloc return array */ + ALLOC_ARRAY_CLEAR_GC(ret, char *, len + 1, gc); - buf_set_read (&buf, (const uint8_t *) str, strlen(str)); - while (buf_parse (&buf, '\n', line, sizeof (line))) + buf_set_read(&buf, (const uint8_t *) str, strlen(str)); + while (buf_parse(&buf, '\n', line, sizeof(line))) { - chomp (line); - ASSERT (i < len); - ret[i] = string_alloc (skip_leading_whitespace (line), gc); - ++i; - } - ASSERT (i <= len); - ret[i] = NULL; - return (const char **)ret; + chomp(line); + ASSERT(i < len); + ret[i] = string_alloc(skip_leading_whitespace(line), gc); + ++i; + } + ASSERT(i <= len); + ret[i] = NULL; + return (const char **)ret; } static const char ** -make_arg_copy (char **p, struct gc_arena *gc) +make_arg_copy(char **p, struct gc_arena *gc) { - char **ret = NULL; - const int len = string_array_len ((const char **)p); - const int max_parms = len + 1; - int i; + char **ret = NULL; + const int len = string_array_len((const char **)p); + const int max_parms = len + 1; + int i; - /* alloc return array */ - ALLOC_ARRAY_CLEAR_GC (ret, char *, max_parms, gc); + /* alloc return array */ + ALLOC_ARRAY_CLEAR_GC(ret, char *, max_parms, gc); - for (i = 0; i < len; ++i) - ret[i] = p[i]; + for (i = 0; i < len; ++i) + ret[i] = p[i]; - return (const char **)ret; + return (const char **)ret; } const char ** -make_extended_arg_array (char **p, struct gc_arena *gc) -{ - const int argc = string_array_len ((const char **)p); - if (!strcmp (p[0], INLINE_FILE_TAG) && argc == 2) - return make_inline_array (p[1], gc); - else - if (argc == 0) - return make_arg_array (NULL, NULL, gc); - else if (argc == 1) - return make_arg_array (p[0], NULL, gc); - else if (argc == 2) - return make_arg_array (p[0], p[1], gc); - else - return make_arg_copy (p, gc); +make_extended_arg_array(char **p, struct gc_arena *gc) +{ + const int argc = string_array_len((const char **)p); + if (!strcmp(p[0], INLINE_FILE_TAG) && argc == 2) + { + return make_inline_array(p[1], gc); + } + else if (argc == 0) + { + return make_arg_array(NULL, NULL, gc); + } + else if (argc == 1) + { + return make_arg_array(p[0], NULL, gc); + } + else if (argc == 2) + { + return make_arg_array(p[0], p[1], gc); + } + else + { + return make_arg_copy(p, gc); + } } void -openvpn_sleep (const int n) +openvpn_sleep(const int n) { #ifdef ENABLE_MANAGEMENT - if (management) + if (management) { - management_event_loop_n_seconds (management, n); - return; + management_event_loop_n_seconds(management, n); + return; } #endif - sleep (n); + sleep(n); } /* @@ -1543,17 +1688,17 @@ openvpn_sleep (const int n) * or u if u is a power of 2. */ size_t -adjust_power_of_2 (size_t u) +adjust_power_of_2(size_t u) { - size_t ret = 1; + size_t ret = 1; - while (ret < u) + while (ret < u) { - ret <<= 1; - ASSERT (ret > 0); + ret <<= 1; + ASSERT(ret > 0); } - return ret; + return ret; } /* @@ -1563,57 +1708,61 @@ adjust_power_of_2 (size_t u) const char * sanitize_control_message(const char *src, struct gc_arena *gc) { - char *ret = gc_malloc (strlen(src)+1, false, gc); - char *dest = ret; - bool redact = false; - int skip = 0; - - for (;;) - { - const char c = *src; - if (c == '\0') - break; - if (c == 'S' && !strncmp(src, "SESS_ID_", 8)) - { - skip = 7; - redact = true; - } - else if (c == 'e' && !strncmp(src, "echo ", 5)) - { - 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? */ - { - skip = 0; - redact = false; - } - - if (redact) - { - if (skip > 0) - { - --skip; - *dest++ = c; - } - } - else - *dest++ = c; - - ++src; - } - *dest = '\0'; - return ret; + char *ret = gc_malloc(strlen(src)+1, false, gc); + char *dest = ret; + bool redact = false; + int skip = 0; + + for (;; ) + { + const char c = *src; + if (c == '\0') + { + break; + } + if (c == 'S' && !strncmp(src, "SESS_ID_", 8)) + { + skip = 7; + redact = true; + } + else if (c == 'e' && !strncmp(src, "echo ", 5)) + { + 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? */ + { + skip = 0; + redact = false; + } + + if (redact) + { + if (skip > 0) + { + --skip; + *dest++ = c; + } + } + else + { + *dest++ = c; + } + + ++src; + } + *dest = '\0'; + return ret; } /** @@ -1626,14 +1775,16 @@ sanitize_control_message(const char *src, struct gc_arena *gc) * @return Returns 0 if the flag is not set, otherwise the 'flag' value is returned */ bool -compat_flag (unsigned int flag) +compat_flag(unsigned int flag) { - static unsigned int compat_flags = 0; + static unsigned int compat_flags = 0; - if (flag & COMPAT_FLAG_SET) - compat_flags |= (flag >> 1); + if (flag & COMPAT_FLAG_SET) + { + compat_flags |= (flag >> 1); + } - return (compat_flags & (flag >> 1)); + return (compat_flags & (flag >> 1)); } @@ -1645,49 +1796,60 @@ compat_flag (unsigned int flag) 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); + 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"); +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"); + } } } -- cgit v1.2.3