/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "config.h"

#include "argv.h"
#include "common/recording.h"
#include "common-ssh/sftp.h"
#include "common-ssh/ssh.h"
#include "settings.h"
#include "sftp.h"
#include "ssh.h"
#include "terminal/terminal.h"
#include "ttymode.h"

#ifdef ENABLE_SSH_AGENT
#include "ssh_agent.h"
#endif

#include <libssh2.h>
#include <libssh2_sftp.h>
#include <guacamole/client.h>
#include <openssl/err.h>
#include <openssl/ssl.h>

#ifdef LIBSSH2_USES_GCRYPT
#include <gcrypt.h>
#endif

#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>

/**
 * Produces a new user object containing a username and password or private
 * key, prompting the user as necessary to obtain that information.
 *
 * @param client
 *     The Guacamole client containing any existing user data, as well as the
 *     terminal to use when prompting the user.
 *
 * @return
 *     A new user object containing the user's username and other credentials,
 *     or NULL if fails to import key.
 */
static guac_common_ssh_user* guac_ssh_get_user(guac_client* client) {

    guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
    guac_ssh_settings* settings = ssh_client->settings;

    guac_common_ssh_user* user;

    /* Get username */
    if (settings->username == NULL)
        settings->username = guac_terminal_prompt(ssh_client->term,
                "Login as: ", true);

    /* Create user object from username */
    user = guac_common_ssh_create_user(settings->username);

    /* If key specified, import */
    if (settings->key_base64 != NULL) {

        guac_client_log(client, GUAC_LOG_DEBUG,
                "Attempting private key import (WITHOUT passphrase)");

        /* Attempt to read key without passphrase */
        if (guac_common_ssh_user_import_key(user,
                    settings->key_base64, NULL)) {

            /* Log failure of initial attempt */
            guac_client_log(client, GUAC_LOG_DEBUG,
                    "Initial import failed: %s",
                    guac_common_ssh_key_error());
  
            guac_client_log(client, GUAC_LOG_DEBUG,
                    "Re-attempting private key import (WITH passphrase)");

            /* Prompt for passphrase if missing */
            if (settings->key_passphrase == NULL)
                settings->key_passphrase =
                    guac_terminal_prompt(ssh_client->term,
                            "Key passphrase: ", false);

            /* Reattempt import with passphrase */
            if (guac_common_ssh_user_import_key(user,
                        settings->key_base64,
                        settings->key_passphrase)) {

                /* If still failing, give up */
                guac_client_abort(client,
                        GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
                        "Auth key import failed: %s",
                        guac_common_ssh_key_error());

                guac_common_ssh_destroy_user(user);
                return NULL;

            }

        } /* end decrypt key with passphrase */

        /* Success */
        guac_client_log(client, GUAC_LOG_INFO,
                "Auth key successfully imported.");

    } /* end if key given */

    /* If available, get password from settings */
    else if (settings->password != NULL) {
        guac_common_ssh_user_set_password(user, settings->password);
    }

    /* Clear screen of any prompts */
    guac_terminal_printf(ssh_client->term, "\x1B[H\x1B[J");

    return user;

}

/**
 * A function used to generate a terminal prompt to gather additional
 * credentials from the guac_client during a connection, and using
 * the specified string to generate the prompt for the user.
 * 
 * @param client
 *     The guac_client object associated with the current connection
 *     where additional credentials are required.
 * 
 * @param cred_name
 *     The prompt text to display to the screen when prompting for the
 *     additional credentials.
 * 
 * @return 
 *     The string of credentials gathered from the user.
 */
static char* guac_ssh_get_credential(guac_client *client, char* cred_name) {

    guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
    return guac_terminal_prompt(ssh_client->term, cred_name, false);
    
}

void* ssh_input_thread(void* data) {

    guac_client* client = (guac_client*) data;
    guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;

    char buffer[8192];
    int bytes_read;

    /* Write all data read */
    while ((bytes_read = guac_terminal_read_stdin(ssh_client->term, buffer, sizeof(buffer))) > 0) {
        pthread_mutex_lock(&(ssh_client->term_channel_lock));
        libssh2_channel_write(ssh_client->term_channel, buffer, bytes_read);
        pthread_mutex_unlock(&(ssh_client->term_channel_lock));

        /* Make sure ssh_input_thread can be terminated anyway */
        if (client->state == GUAC_CLIENT_STOPPING)
            break;
    }

    /* Stop the client so that ssh_client_thread can be terminated */
    guac_client_stop(client);
    return NULL;

}

void* ssh_client_thread(void* data) {

    guac_client* client = (guac_client*) data;
    guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
    guac_ssh_settings* settings = ssh_client->settings;

    char buffer[8192];

    pthread_t input_thread;

    /* Init SSH base libraries */
    if (guac_common_ssh_init(client)) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "SSH library initialization failed");
        return NULL;
    }

    char ssh_ttymodes[GUAC_SSH_TTYMODES_SIZE(1)];

    /* Set up screen recording, if requested */
    if (settings->recording_path != NULL) {
        ssh_client->recording = guac_common_recording_create(client,
                settings->recording_path,
                settings->recording_name,
                settings->create_recording_path,
                !settings->recording_exclude_output,
                !settings->recording_exclude_mouse,
                settings->recording_include_keys);
    }

    /* Create terminal */
    ssh_client->term = guac_terminal_create(client, ssh_client->clipboard,
            settings->max_scrollback, settings->font_name, settings->font_size,
            settings->resolution, settings->width, settings->height,
            settings->color_scheme, settings->backspace);

    /* Fail if terminal init failed */
    if (ssh_client->term == NULL) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "Terminal initialization failed");
        return NULL;
    }

    /* Send current values of exposed arguments to owner only */
    guac_client_for_owner(client, guac_ssh_send_current_argv, ssh_client);

    /* Set up typescript, if requested */
    if (settings->typescript_path != NULL) {
        guac_terminal_create_typescript(ssh_client->term,
                settings->typescript_path,
                settings->typescript_name,
                settings->create_typescript_path);
    }

    /* Get user and credentials */
    ssh_client->user = guac_ssh_get_user(client);
    if (ssh_client->user == NULL) {
        /* Already aborted within guac_ssh_get_user() */
        return NULL;
    }

    /* Ensure connection is kept alive during lengthy connects */
    guac_socket_require_keep_alive(client->socket);

    /* Open SSH session */
    ssh_client->session = guac_common_ssh_create_session(client,
            settings->hostname, settings->port, ssh_client->user, settings->server_alive_interval,
            settings->host_key, guac_ssh_get_credential);
    if (ssh_client->session == NULL) {
        /* Already aborted within guac_common_ssh_create_session() */
        return NULL;
    }

    pthread_mutex_init(&ssh_client->term_channel_lock, NULL);

    /* Open channel for terminal */
    ssh_client->term_channel =
        libssh2_channel_open_session(ssh_client->session->session);
    if (ssh_client->term_channel == NULL) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
                "Unable to open terminal channel.");
        return NULL;
    }

    /* Set the client timezone */
    if (settings->timezone != NULL) {
        if (libssh2_channel_setenv(ssh_client->term_channel, "TZ",
                    settings->timezone)) {
            guac_client_log(client, GUAC_LOG_WARNING,
                    "Unable to set the timezone: SSH server "
                    "refused to set \"TZ\" variable.");
        }
    }


#ifdef ENABLE_SSH_AGENT
    /* Start SSH agent forwarding, if enabled */
    if (ssh_client->enable_agent) {
        libssh2_session_callback_set(ssh_client->session,
                LIBSSH2_CALLBACK_AUTH_AGENT, (void*) ssh_auth_agent_callback);

        /* Request agent forwarding */
        if (libssh2_channel_request_auth_agent(ssh_client->term_channel))
            guac_client_log(client, GUAC_LOG_ERROR, "Agent forwarding request failed");
        else
            guac_client_log(client, GUAC_LOG_INFO, "Agent forwarding enabled.");
    }

    ssh_client->auth_agent = NULL;
#endif

    /* Start SFTP session as well, if enabled */
    if (settings->enable_sftp) {

        /* Create SSH session specific for SFTP */
        guac_client_log(client, GUAC_LOG_DEBUG, "Reconnecting for SFTP...");
        ssh_client->sftp_session =
            guac_common_ssh_create_session(client, settings->hostname,
                    settings->port, ssh_client->user, settings->server_alive_interval,
                    settings->host_key, NULL);
        if (ssh_client->sftp_session == NULL) {
            /* Already aborted within guac_common_ssh_create_session() */
            return NULL;
        }

        /* Request SFTP */
        ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem(
                    ssh_client->sftp_session, settings->sftp_root_directory,
                    NULL);

        /* Expose filesystem to connection owner */
        guac_client_for_owner(client,
                guac_common_ssh_expose_sftp_filesystem,
                ssh_client->sftp_filesystem);

        /* Init handlers for Guacamole-specific console codes */
        ssh_client->term->upload_path_handler = guac_sftp_set_upload_path;
        ssh_client->term->file_download_handler = guac_sftp_download_file;

        guac_client_log(client, GUAC_LOG_DEBUG, "SFTP session initialized");

    }

    /* Set up the ttymode array prior to requesting the PTY */
    int ttymodeBytes = guac_ssh_ttymodes_init(ssh_ttymodes,
            GUAC_SSH_TTY_OP_VERASE, settings->backspace, GUAC_SSH_TTY_OP_END);
    if (ttymodeBytes < 1)
        guac_client_log(client, GUAC_LOG_WARNING, "Unable to set TTY modes."
                "  Backspace may not work as expected.");

    /* Request PTY */
    if (libssh2_channel_request_pty_ex(ssh_client->term_channel,
            settings->terminal_type, strlen(settings->terminal_type),
            ssh_ttymodes, ttymodeBytes, ssh_client->term->term_width,
            ssh_client->term->term_height, 0, 0)) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY.");
        return NULL;
    }

    /* Forward specified locale */
    if (settings->locale != NULL) {
        if (libssh2_channel_setenv(ssh_client->term_channel, "LANG",
                    settings->locale)) {
            guac_client_log(client, GUAC_LOG_WARNING,
                    "Unable to forward locale: SSH server refused to set "
                    "\"LANG\" environment variable.");
        }
    }

    /* If a command is specified, run that instead of a shell */
    if (settings->command != NULL) {
        if (libssh2_channel_exec(ssh_client->term_channel, settings->command)) {
            guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
                    "Unable to execute command.");
            return NULL;
        }
    }

    /* Otherwise, request a shell */
    else if (libssh2_channel_shell(ssh_client->term_channel)) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
                "Unable to associate shell with PTY.");
        return NULL;
    }

    /* Logged in */
    guac_client_log(client, GUAC_LOG_INFO, "SSH connection successful.");
    guac_terminal_start(ssh_client->term);

    /* Start input thread */
    if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
        return NULL;
    }

    /* Set non-blocking */
    libssh2_session_set_blocking(ssh_client->session->session, 0);

    /* While data available, write to terminal */
    int bytes_read = 0;
    for (;;) {

        /* Track total amount of data read */
        int total_read = 0;

        /* Timeout for polling socket activity */
        int timeout;

        pthread_mutex_lock(&(ssh_client->term_channel_lock));

        /* Stop reading at EOF */
        if (libssh2_channel_eof(ssh_client->term_channel)) {
            pthread_mutex_unlock(&(ssh_client->term_channel_lock));
            break;
        }

        /* Client is stopping, break the loop */
        if (client->state == GUAC_CLIENT_STOPPING) {
            pthread_mutex_unlock(&(ssh_client->term_channel_lock));
            break;
        }

        /* Send keepalive at configured interval */
        if (settings->server_alive_interval > 0) {
            timeout = 0;
            if (libssh2_keepalive_send(ssh_client->session->session, &timeout) > 0)
                break;
            timeout *= 1000;
        }
        /* If keepalive is not configured, sleep for the default of 1 second */
        else
            timeout = GUAC_SSH_DEFAULT_POLL_TIMEOUT;

        /* Read terminal data */
        bytes_read = libssh2_channel_read(ssh_client->term_channel,
                buffer, sizeof(buffer));

        pthread_mutex_unlock(&(ssh_client->term_channel_lock));

        /* Attempt to write data received. Exit on failure. */
        if (bytes_read > 0) {
            int written = guac_terminal_write(ssh_client->term, buffer, bytes_read);
            if (written < 0)
                break;

            total_read += bytes_read;
        }

        else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN)
            break;

#ifdef ENABLE_SSH_AGENT
        /* If agent open, handle any agent packets */
        if (ssh_client->auth_agent != NULL) {
            bytes_read = ssh_auth_agent_read(ssh_client->auth_agent);
            if (bytes_read > 0)
                total_read += bytes_read;
            else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN)
                ssh_client->auth_agent = NULL;
        }
#endif

        /* Wait for more data if reads turn up empty */
        if (total_read == 0) {

            /* Wait on the SSH session file descriptor only */
            struct pollfd fds[] = {{
                .fd      = ssh_client->session->fd,
                .events  = POLLIN,
                .revents = 0,
            }};

            /* Wait up to computed timeout */
            if (poll(fds, 1, timeout) < 0)
                break;

        }

    }

    /* Kill client and Wait for input thread to die */
    guac_client_stop(client);
    pthread_join(input_thread, NULL);

    pthread_mutex_destroy(&ssh_client->term_channel_lock);

    guac_client_log(client, GUAC_LOG_INFO, "SSH connection ended.");
    return NULL;

}

