summaryrefslogtreecommitdiff
path: root/src/openvpn/console.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/console.c')
-rw-r--r--src/openvpn/console.c228
1 files changed, 27 insertions, 201 deletions
diff --git a/src/openvpn/console.c b/src/openvpn/console.c
index 86331a1..c3bb7c3 100644
--- a/src/openvpn/console.c
+++ b/src/openvpn/console.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
@@ -38,219 +40,43 @@
#include <systemd/sd-daemon.h>
#endif
-#ifdef WIN32
-#include "win32.h"
+struct _query_user query_user[QUERY_USER_NUMSLOTS]; /* GLOBAL */
-/*
- * Get input from console.
- *
- * Return false on input error, or if service
- * exit event is signaled.
- */
-
-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
- && !win32_service_interrupt (&win32_signal)
- && WriteFile (err, prompt, strlen (prompt), &len, NULL))
- {
- bool is_console = (GetFileType (in) == FILE_TYPE_CHAR);
- DWORD flags_save = 0;
- int status = 0;
- WCHAR *winput;
-
- if (is_console)
- {
- if (GetConsoleMode (in, &flags_save))
- {
- DWORD flags = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
- if (echo)
- flags |= ENABLE_ECHO_INPUT;
- SetConsoleMode (in, flags);
- }
- else
- is_console = 0;
- }
-
- if (is_console)
- {
- winput = malloc (capacity * sizeof (WCHAR));
- if (winput == NULL)
- return false;
-
- status = ReadConsoleW (in, winput, capacity, &len, NULL);
- WideCharToMultiByte (CP_UTF8, 0, winput, len, input, capacity, NULL, NULL);
- free (winput);
- }
- else
- status = ReadFile (in, input, capacity, &len, NULL);
-
- string_null_terminate (input, (int)len, capacity);
- chomp (input);
-
- if (!echo)
- WriteFile (err, "\r\n", 2, &len, NULL);
- if (is_console)
- SetConsoleMode (in, flags_save);
- if (status && !win32_service_interrupt (&win32_signal))
- return true;
- }
-
- return false;
-}
-
-#endif
-
-#ifdef HAVE_GETPASS
-
-static FILE *
-open_tty (const bool write)
-{
- FILE *ret;
- ret = fopen ("/dev/tty", write ? "w" : "r");
- if (!ret)
- ret = write ? stderr : stdin;
- return ret;
-}
-
-static void
-close_tty (FILE *fp)
-{
- if (fp != stderr && fp != stdin)
- fclose (fp);
-}
-
-#endif
-#ifdef ENABLE_SYSTEMD
-
-/*
- * is systemd running
- */
-
-static bool
-check_systemd_running ()
+void query_user_clear()
{
- struct stat c;
-
- /* We simply test whether the systemd cgroup hierarchy is
- * mounted, as well as the systemd-ask-password executable
- * being available */
+ int i;
- return (sd_booted() > 0)
- && (stat(SYSTEMD_ASK_PASSWORD_PATH, &c) == 0);
-
-}
-
-static bool
-get_console_input_systemd (const char *prompt, const bool echo, char *input, const int capacity)
-{
- int std_out;
- bool ret = false;
- struct argv argv;
-
- argv_init (&argv);
- argv_printf (&argv, SYSTEMD_ASK_PASSWORD_PATH);
- argv_printf_cat (&argv, "%s", prompt);
-
- if ((std_out = openvpn_popen (&argv, NULL)) < 0) {
- return false;
- }
-
- memset (input, 0, capacity);
- if (read (std_out, input, capacity-1) > 0)
- {
- chomp (input);
- ret = true;
+ for( i = 0; i < QUERY_USER_NUMSLOTS; i++ ) {
+ CLEAR(query_user[i]);
}
- close (std_out);
-
- argv_reset (&argv);
-
- return ret;
}
-#endif
-
-/*
- * Get input from console
- */
-bool
-get_console_input (const char *prompt, const bool echo, char *input, const int capacity)
+void query_user_add(char *prompt, size_t prompt_len,
+ char *resp, size_t resp_len,
+ bool echo)
{
- bool ret = false;
- ASSERT (prompt);
- ASSERT (input);
- ASSERT (capacity > 0);
- input[0] = '\0';
-
-#ifdef ENABLE_SYSTEMD
- if (check_systemd_running ())
- return get_console_input_systemd (prompt, echo, input, capacity);
-#endif
+ int i;
-#if defined(WIN32)
- return get_console_input_win32 (prompt, echo, input, capacity);
-#elif defined(HAVE_GETPASS)
+ /* Ensure input is sane. All these must be present otherwise it is
+ * a programming error.
+ */
+ ASSERT( prompt_len > 0 && prompt != NULL && resp_len > 0 && resp != NULL );
- /* did we --daemon'ize before asking for passwords?
- * (in which case neither stdin or stderr are connected to a tty and
- * /dev/tty can not be open()ed anymore)
- */
- if ( !isatty(0) && !isatty(2) )
- {
- int fd = open( "/dev/tty", O_RDWR );
- if ( fd < 0 )
- { msg(M_FATAL, "neither stdin nor stderr are a tty device and you have neither a controlling tty nor systemd - can't ask for '%s'. If you used --daemon, you need to use --askpass to make passphrase-protected keys work, and you can not use --auth-nocache.", prompt ); }
- close(fd);
- }
-
- if (echo)
- {
- FILE *fp;
-
- fp = open_tty (true);
- fprintf (fp, "%s", prompt);
- fflush (fp);
- close_tty (fp);
-
- fp = open_tty (false);
- if (fgets (input, capacity, fp) != NULL)
- {
- chomp (input);
- ret = true;
+ /* Seek to the last unused slot */
+ for (i = 0; i < QUERY_USER_NUMSLOTS; i++) {
+ if( query_user[i].prompt == NULL ) {
+ break;
}
- close_tty (fp);
}
- else
- {
- char *gp = getpass (prompt);
- if (gp)
- {
- strncpynt (input, gp, capacity);
- memset (gp, 0, strlen (gp));
- ret = true;
- }
- }
-#else
- msg (M_FATAL, "Sorry, but I can't get console input on this OS (%s)", prompt);
-#endif
- return ret;
+ ASSERT( i < QUERY_USER_NUMSLOTS ); /* Unlikely, but we want to panic if it happens */
+
+ /* Save the information needed for the user interaction */
+ query_user[i].prompt = prompt;
+ query_user[i].prompt_len = prompt_len;
+ query_user[i].response = resp;
+ query_user[i].response_len = resp_len;
+ query_user[i].echo = echo;
}