/*
 *  OpenVPN -- An application to securely tunnel IP networks
 *             over a single UDP port, with support for SSL/TLS-based
 *             session authentication and key exchange,
 *             packet encryption, packet authentication, and
 *             packet compression.
 *
 *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
 *  Copyright (C) 2014-2015  David Sommerseth <davids@redhat.com>
 *  Copyright (C) 2016-2018 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
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/*
 *  These functions covers handing user input/output using the default consoles
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#elif defined(_MSC_VER)
#include "config-msvc.h"
#endif

#include "syshead.h"
#include "console.h"
#include "error.h"
#include "buffer.h"
#include "misc.h"

#ifdef _WIN32

#include "win32.h"

/**
 * Get input from a Windows console.
 *
 * @param prompt    Prompt to display to the user
 * @param echo      Should the user input be displayed in the console
 * @param input     Pointer to the buffer the user input will be saved
 * @param capacity  Size of the buffer for the user input
 *
 * @return 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   /* _WIN32 */


#ifdef HAVE_GETPASS

/**
 * Open the current console TTY for read/write operations
 *
 * @params write   If true, the user wants to write to the console
 *                 otherwise read from the console
 *
 * @returns Returns a FILE pointer to either the TTY in read or write mode
 *          or stdin/stderr, depending on the write flag
 *
 */
static FILE *
open_tty(const bool write)
{
    FILE *ret;
    ret = fopen("/dev/tty", write ? "w" : "r");
    if (!ret)
    {
        ret = write ? stderr : stdin;
    }
    return ret;
}

/**
 * Closes the TTY FILE pointer, but only if it is not a stdin/stderr FILE object.
 *
 * @params fp     FILE pointer to close
 *
 */
static void
close_tty(FILE *fp)
{
    if (fp != stderr && fp != stdin)
    {
        fclose(fp);
    }
}

#endif   /* HAVE_GETPASS */


/**
 *  Core function for getting input from console
 *
 *  @params prompt    The prompt to present to the user
 *  @params echo      Should the user see what is being typed
 *  @params input     Pointer to the buffer used to save the user input
 *  @params capacity  Size of the input buffer
 *
 *  @returns Returns True if user input was gathered
 */
static bool
get_console_input(const char *prompt, const bool echo, char *input, const int capacity)
{
    bool ret = false;
    ASSERT(prompt);
    ASSERT(input);
    ASSERT(capacity > 0);
    input[0] = '\0';

#if defined(_WIN32)
    return get_console_input_win32(prompt, echo, input, capacity);
#elif defined(HAVE_GETPASS)

    /* 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;
        }
        close_tty(fp);
    }
    else
    {
        char *gp = getpass(prompt);
        if (gp)
        {
            strncpynt(input, gp, capacity);
            secure_memzero(gp, strlen(gp));
            ret = true;
        }
    }
#else  /* if defined(_WIN32) */
    msg(M_FATAL, "Sorry, but I can't get console input on this OS (%s)", prompt);
#endif /* if defined(_WIN32) */
    return ret;
}


/**
 * @copydoc query_user_exec()
 *
 * Default method for querying user using default stdin/stdout on a console.
 * This needs to be available as a backup interface for the alternative
 * implementations in case they cannot query through their implementation
 * specific methods.
 *
 * If no alternative implementation is declared, a wrapper in console.h will ensure
 * query_user_exec() will call this function instead.
 *
 */
bool
query_user_exec_builtin(void)
{
    bool ret = true; /* Presume everything goes okay */
    int i;

    /* Loop through configured query_user slots */
    for (i = 0; i < QUERY_USER_NUMSLOTS && query_user[i].response != NULL; i++)
    {
        if (!get_console_input(query_user[i].prompt, query_user[i].echo,
                               query_user[i].response, query_user[i].response_len) )
        {
            /* Force the final result state to failed on failure */
            ret = false;
        }
    }

    return ret;
}
