From: Lev Stipakov Date: Fri, 25 Jun 2021 01:04:05 +0000 (+0300) Subject: Fix console prompts with redirected log X-Git-Tag: v2.6_beta1~467 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=480e4cc14ff34fac72406ab1dd66290a91cc09f0;p=thirdparty%2Fopenvpn.git Fix console prompts with redirected log When openvpn needs to prompt user for a password (for example, to set management interface password), the prompt is written to standard error device. When log is redirected to a file, that prompt is written to that file and not to the "original" stderr. Moreover, on recent Insider build (21390.2025) openvpn exits with fatal error get_console_input_win32(): unexpected error: No such device or address (errno=6) while attempting to write that prompt. When redirecting stdout/stderr, we use _dup2() to associate stderr descriptor with a log file. This call closes file associated with stderr descriptor, which might explain why it has stopped working (original stderr is closed and WriteFile() fails) and on older versions it appears to work "by accident" - not failing but use redirected stderr instead of original one. Fix by creating new file descriptor with _dup() for stderr before redirect and use this descriptor for writing prompts. While on it, make code a bit more C99-ish by moving variables declaration from the beginning of the scope to the actual initialisation. Signed-off-by: Lev Stipakov Acked-by: Gert Doering Message-Id: <20210625010405.224-1-lstipakov@gmail.com> URL: https://www.mail-archive.com/search?l=mid&q=20210625010405.224-1-lstipakov@gmail.com Signed-off-by: Gert Doering --- diff --git a/src/openvpn/console_builtin.c b/src/openvpn/console_builtin.c index 9bf363478..06b8a77a0 100644 --- a/src/openvpn/console_builtin.c +++ b/src/openvpn/console_builtin.c @@ -62,23 +62,17 @@ static bool get_console_input_win32(const char *prompt, const bool echo, char *input, const int capacity) { - HANDLE in = INVALID_HANDLE_VALUE; - HANDLE err = INVALID_HANDLE_VALUE; - DWORD len = 0; - ASSERT(prompt); ASSERT(input); ASSERT(capacity > 0); input[0] = '\0'; - in = GetStdHandle(STD_INPUT_HANDLE); - err = get_orig_stderr(); - - if (in == INVALID_HANDLE_VALUE - || err == INVALID_HANDLE_VALUE + HANDLE in = GetStdHandle(STD_INPUT_HANDLE); + int orig_stderr = get_orig_stderr(); // guaranteed to be always valid + if ((in == INVALID_HANDLE_VALUE) || win32_service_interrupt(&win32_signal) - || !WriteFile(err, prompt, strlen(prompt), &len, NULL)) + || (_write(orig_stderr, prompt, strlen(prompt)) == -1)) { msg(M_WARN|M_ERRNO, "get_console_input_win32(): unexpected error"); return false; @@ -106,6 +100,8 @@ get_console_input_win32(const char *prompt, const bool echo, char *input, const } } + DWORD len = 0; + if (is_console) { winput = malloc(capacity * sizeof(WCHAR)); @@ -128,7 +124,7 @@ get_console_input_win32(const char *prompt, const bool echo, char *input, const if (!echo) { - WriteFile(err, "\r\n", 2, &len, NULL); + _write(orig_stderr, "\r\n", 2); } if (is_console) { diff --git a/src/openvpn/error.c b/src/openvpn/error.c index b94d387c7..eb82f9c7e 100644 --- a/src/openvpn/error.c +++ b/src/openvpn/error.c @@ -491,22 +491,12 @@ close_syslog(void) } #ifdef _WIN32 +static int orig_stderr; -static HANDLE orig_stderr; - -HANDLE -get_orig_stderr(void) +int get_orig_stderr() { - if (orig_stderr) - { - return orig_stderr; - } - else - { - return GetStdHandle(STD_ERROR_HANDLE); - } + return orig_stderr ? orig_stderr : _fileno(stderr); } - #endif void @@ -550,16 +540,12 @@ redirect_stdout_stderr(const char *file, bool append) } /* save original stderr for password prompts */ - orig_stderr = GetStdHandle(STD_ERROR_HANDLE); - -#if 0 /* seems not be necessary with stdout/stderr redirection below*/ - /* set up for redirection */ - if (!SetStdHandle(STD_OUTPUT_HANDLE, log_handle) - || !SetStdHandle(STD_ERROR_HANDLE, log_handle)) + orig_stderr = _dup(_fileno(stderr)); + if (orig_stderr == -1) { - msg(M_ERR, "Error: cannot redirect stdout/stderr to --log file: %s", file); + msg(M_WARN | M_ERRNO, "Warning: cannot duplicate stderr, password prompts will appear in log file instead of console."); + orig_stderr = _fileno(stderr); } -#endif /* direct stdout/stderr to point to log_handle */ log_fd = _open_osfhandle((intptr_t)log_handle, _O_TEXT); diff --git a/src/openvpn/error.h b/src/openvpn/error.h index f4528ef22..533354b3c 100644 --- a/src/openvpn/error.h +++ b/src/openvpn/error.h @@ -256,8 +256,8 @@ void close_syslog(void); void redirect_stdout_stderr(const char *file, bool append); #ifdef _WIN32 -/* get original stderr handle, even if redirected by --log/--log-append */ -HANDLE get_orig_stderr(void); +/* get original stderr fd, even if redirected by --log/--log-append */ +int get_orig_stderr(void); #endif