Partial migration, including SFTP.
This commit is contained in:
parent
602571400d
commit
d32018cf87
@ -52,6 +52,7 @@ libguac_client_ssh_la_SOURCES = \
|
|||||||
ibar.c \
|
ibar.c \
|
||||||
sftp.c \
|
sftp.c \
|
||||||
ssh_client.c \
|
ssh_client.c \
|
||||||
|
ssh_key.c \
|
||||||
terminal.c \
|
terminal.c \
|
||||||
terminal_handlers.c
|
terminal_handlers.c
|
||||||
|
|
||||||
@ -65,9 +66,9 @@ noinst_HEADERS = \
|
|||||||
display.h \
|
display.h \
|
||||||
guac_handlers.h \
|
guac_handlers.h \
|
||||||
ibar.h \
|
ibar.h \
|
||||||
libssh_compat.h \
|
|
||||||
sftp.h \
|
sftp.h \
|
||||||
ssh_client.h \
|
ssh_client.h \
|
||||||
|
ssh_key.h \
|
||||||
terminal.h \
|
terminal.h \
|
||||||
terminal_handlers.h \
|
terminal_handlers.h \
|
||||||
types.h
|
types.h
|
||||||
|
@ -66,10 +66,8 @@ const char* GUAC_CLIENT_ARGS[] = {
|
|||||||
"font-name",
|
"font-name",
|
||||||
"font-size",
|
"font-size",
|
||||||
"enable-sftp",
|
"enable-sftp",
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
"private-key",
|
"private-key",
|
||||||
"passphrase",
|
"passphrase",
|
||||||
#endif
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,7 +108,6 @@ enum __SSH_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_ENABLE_SFTP,
|
IDX_ENABLE_SFTP,
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
/**
|
/**
|
||||||
* The private key to use for authentication, if any.
|
* The private key to use for authentication, if any.
|
||||||
*/
|
*/
|
||||||
@ -120,7 +117,6 @@ enum __SSH_ARGS_IDX {
|
|||||||
* The passphrase required to decrypt the private key, if any.
|
* The passphrase required to decrypt the private key, if any.
|
||||||
*/
|
*/
|
||||||
IDX_PASSPHRASE,
|
IDX_PASSPHRASE,
|
||||||
#endif
|
|
||||||
|
|
||||||
SSH_ARGS_COUNT
|
SSH_ARGS_COUNT
|
||||||
};
|
};
|
||||||
@ -149,12 +145,10 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
|||||||
strcpy(client_data->username, argv[IDX_USERNAME]);
|
strcpy(client_data->username, argv[IDX_USERNAME]);
|
||||||
strcpy(client_data->password, argv[IDX_PASSWORD]);
|
strcpy(client_data->password, argv[IDX_PASSWORD]);
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
/* Init public key auth information */
|
/* Init public key auth information */
|
||||||
client_data->key = NULL;
|
client_data->key = NULL;
|
||||||
strcpy(client_data->key_base64, argv[IDX_PRIVATE_KEY]);
|
strcpy(client_data->key_base64, argv[IDX_PRIVATE_KEY]);
|
||||||
strcpy(client_data->key_passphrase, argv[IDX_PASSPHRASE]);
|
strcpy(client_data->key_passphrase, argv[IDX_PASSPHRASE]);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read font name */
|
/* Read font name */
|
||||||
if (argv[IDX_FONT_NAME][0] != 0)
|
if (argv[IDX_FONT_NAME][0] != 0)
|
||||||
|
@ -40,12 +40,13 @@
|
|||||||
#define _SSH_GUAC_CLIENT_H
|
#define _SSH_GUAC_CLIENT_H
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <libssh/libssh.h>
|
#include <libssh2.h>
|
||||||
#include <libssh/sftp.h>
|
#include <libssh2_sftp.h>
|
||||||
|
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "sftp.h"
|
#include "sftp.h"
|
||||||
|
#include "ssh_key.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SSH-specific client data.
|
* SSH-specific client data.
|
||||||
@ -72,7 +73,6 @@ typedef struct ssh_guac_client_data {
|
|||||||
*/
|
*/
|
||||||
char password[1024];
|
char password[1024];
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
/**
|
/**
|
||||||
* The private key, encoded as base64.
|
* The private key, encoded as base64.
|
||||||
*/
|
*/
|
||||||
@ -86,8 +86,7 @@ typedef struct ssh_guac_client_data {
|
|||||||
/**
|
/**
|
||||||
* The private key to use for authentication, if any.
|
* The private key to use for authentication, if any.
|
||||||
*/
|
*/
|
||||||
ssh_key key;
|
ssh_key* key;
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the font to use for display rendering.
|
* The name of the font to use for display rendering.
|
||||||
@ -112,17 +111,17 @@ typedef struct ssh_guac_client_data {
|
|||||||
/**
|
/**
|
||||||
* SSH session, used by the SSH client thread.
|
* SSH session, used by the SSH client thread.
|
||||||
*/
|
*/
|
||||||
ssh_session session;
|
LIBSSH2_SESSION* session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distinct SSH session used for SFTP.
|
* The distinct SSH session used for SFTP.
|
||||||
*/
|
*/
|
||||||
ssh_session sftp_ssh_session;
|
LIBSSH2_SESSION* sftp_ssh_session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SFTP session, used for file transfers.
|
* SFTP session, used for file transfers.
|
||||||
*/
|
*/
|
||||||
sftp_session sftp_session;
|
LIBSSH2_SFTP* sftp_session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path files will be sent to.
|
* The path files will be sent to.
|
||||||
@ -132,7 +131,7 @@ typedef struct ssh_guac_client_data {
|
|||||||
/**
|
/**
|
||||||
* SSH terminal channel, used by the SSH client thread.
|
* SSH terminal channel, used by the SSH client thread.
|
||||||
*/
|
*/
|
||||||
ssh_channel term_channel;
|
LIBSSH2_CHANNEL* term_channel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The terminal which will render all output from the SSH client.
|
* The terminal which will render all output from the SSH client.
|
||||||
|
@ -51,9 +51,7 @@
|
|||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/error.h>
|
#include <guacamole/error.h>
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh2.h>
|
||||||
#include <libssh/sftp.h>
|
|
||||||
#include "libssh_compat.h"
|
|
||||||
|
|
||||||
#include "guac_handlers.h"
|
#include "guac_handlers.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
@ -399,7 +397,7 @@ int ssh_guac_client_size_handler(guac_client* client, int width, int height) {
|
|||||||
|
|
||||||
/* Update SSH pty size if connected */
|
/* Update SSH pty size if connected */
|
||||||
if (guac_client_data->term_channel != NULL)
|
if (guac_client_data->term_channel != NULL)
|
||||||
channel_change_pty_size(guac_client_data->term_channel,
|
libssh2_channel_request_pty_size(guac_client_data->term_channel,
|
||||||
terminal->term_width, terminal->term_height);
|
terminal->term_width, terminal->term_height);
|
||||||
|
|
||||||
/* Reset scroll region */
|
/* Reset scroll region */
|
||||||
@ -422,8 +420,8 @@ int ssh_guac_client_free_handler(guac_client* client) {
|
|||||||
|
|
||||||
/* Close SSH channel */
|
/* Close SSH channel */
|
||||||
if (guac_client_data->term_channel != NULL) {
|
if (guac_client_data->term_channel != NULL) {
|
||||||
ssh_channel_close(guac_client_data->term_channel);
|
libssh2_channel_send_eof(guac_client_data->term_channel);
|
||||||
ssh_channel_send_eof(guac_client_data->term_channel);
|
libssh2_channel_close(guac_client_data->term_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free terminal */
|
/* Free terminal */
|
||||||
@ -431,23 +429,23 @@ int ssh_guac_client_free_handler(guac_client* client) {
|
|||||||
pthread_join(guac_client_data->client_thread, NULL);
|
pthread_join(guac_client_data->client_thread, NULL);
|
||||||
|
|
||||||
/* Free channels */
|
/* Free channels */
|
||||||
ssh_channel_free(guac_client_data->term_channel);
|
libssh2_channel_free(guac_client_data->term_channel);
|
||||||
|
|
||||||
/* Clean up SFTP */
|
/* Clean up SFTP */
|
||||||
if (guac_client_data->sftp_session)
|
if (guac_client_data->sftp_session)
|
||||||
sftp_free(guac_client_data->sftp_session);
|
libssh2_sftp_shutdown(guac_client_data->sftp_session);
|
||||||
|
|
||||||
if (guac_client_data->sftp_ssh_session)
|
if (guac_client_data->sftp_ssh_session) {
|
||||||
ssh_free(guac_client_data->sftp_ssh_session);
|
libssh2_session_disconnect(guac_client_data->sftp_ssh_session, "Bye");
|
||||||
|
libssh2_session_free(guac_client_data->sftp_ssh_session);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free session */
|
/* Free session */
|
||||||
ssh_free(guac_client_data->session);
|
libssh2_session_free(guac_client_data->session);
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
/* Free auth key */
|
/* Free auth key */
|
||||||
if (guac_client_data->key != NULL)
|
if (guac_client_data->key != NULL)
|
||||||
ssh_key_free(guac_client_data->key);
|
ssh_key_free(guac_client_data->key);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Free clipboard data */
|
/* Free clipboard data */
|
||||||
free(guac_client_data->clipboard_data);
|
free(guac_client_data->clipboard_data);
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (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.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is libguac-client-ssh.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Michael Jumper.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef _SSH_GUAC_LIBSSH_COMPAT_H
|
|
||||||
#define _SSH_GUAC_LIBSSH_COMPAT_H
|
|
||||||
|
|
||||||
/* Define ssh_channel_close() if undefined */
|
|
||||||
#ifndef HAVE_SSH_CHANNEL_CLOSE
|
|
||||||
#define ssh_channel_close channel_close
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define ssh_channel_send_eof() if undefined */
|
|
||||||
#ifndef HAVE_SSH_CHANNEL_SEND_EOF
|
|
||||||
#define ssh_channel_send_eof channel_send_eof
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define ssh_channel_free() if undefined */
|
|
||||||
#ifndef HAVE_SSH_CHANNEL_FREE
|
|
||||||
#define ssh_channel_free channel_free
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -43,8 +43,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh2.h>
|
||||||
#include <libssh/sftp.h>
|
|
||||||
|
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
@ -85,7 +84,7 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
|||||||
|
|
||||||
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
||||||
char fullpath[GUAC_SFTP_MAX_PATH];
|
char fullpath[GUAC_SFTP_MAX_PATH];
|
||||||
sftp_file file;
|
LIBSSH2_SFTP_HANDLE* file;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Ensure filename is a valid filename and not a path */
|
/* Ensure filename is a valid filename and not a path */
|
||||||
@ -129,8 +128,9 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
|||||||
fullpath[i] = '\0';
|
fullpath[i] = '\0';
|
||||||
|
|
||||||
/* Open file via SFTP */
|
/* Open file via SFTP */
|
||||||
file = sftp_open(client_data->sftp_session, fullpath,
|
file = libssh2_sftp_open(client_data->sftp_session, fullpath,
|
||||||
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
/* Inform of status */
|
/* Inform of status */
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
@ -140,7 +140,7 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
guac_client_log_error(client, "Unable to open file \"%s\": %s",
|
guac_client_log_error(client, "Unable to open file \"%s\": %s",
|
||||||
fullpath, ssh_get_error(client_data->sftp_ssh_session));
|
fullpath, libssh2_sftp_last_error(client_data->sftp_session));
|
||||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed",
|
guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed",
|
||||||
GUAC_PROTOCOL_STATUS_INTERNAL_ERROR);
|
GUAC_PROTOCOL_STATUS_INTERNAL_ERROR);
|
||||||
guac_socket_flush(client->socket);
|
guac_socket_flush(client->socket);
|
||||||
@ -157,10 +157,10 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
|||||||
|
|
||||||
/* Pull file from stream */
|
/* Pull file from stream */
|
||||||
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
||||||
sftp_file file = (sftp_file) stream->data;
|
LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
|
||||||
|
|
||||||
/* Attempt write */
|
/* Attempt write */
|
||||||
if (sftp_write(file, data, length) == length) {
|
if (libssh2_sftp_write(file, data, length) == length) {
|
||||||
guac_protocol_send_ack(client->socket, stream, "SFTP: OK",
|
guac_protocol_send_ack(client->socket, stream, "SFTP: OK",
|
||||||
GUAC_PROTOCOL_STATUS_SUCCESS);
|
GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||||
guac_socket_flush(client->socket);
|
guac_socket_flush(client->socket);
|
||||||
@ -169,7 +169,7 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
|||||||
/* Inform of any errors */
|
/* Inform of any errors */
|
||||||
else {
|
else {
|
||||||
guac_client_log_error(client, "Unable to write to file: %s",
|
guac_client_log_error(client, "Unable to write to file: %s",
|
||||||
ssh_get_error(client_data->sftp_ssh_session));
|
libssh2_sftp_last_error(client_data->sftp_session));
|
||||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Write failed",
|
guac_protocol_send_ack(client->socket, stream, "SFTP: Write failed",
|
||||||
GUAC_PROTOCOL_STATUS_INTERNAL_ERROR);
|
GUAC_PROTOCOL_STATUS_INTERNAL_ERROR);
|
||||||
guac_socket_flush(client->socket);
|
guac_socket_flush(client->socket);
|
||||||
@ -182,10 +182,10 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
|||||||
int guac_sftp_end_handler(guac_client* client, guac_stream* stream) {
|
int guac_sftp_end_handler(guac_client* client, guac_stream* stream) {
|
||||||
|
|
||||||
/* Pull file from stream */
|
/* Pull file from stream */
|
||||||
sftp_file file = (sftp_file) stream->data;
|
LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
|
||||||
|
|
||||||
/* Attempt to close file */
|
/* Attempt to close file */
|
||||||
if (sftp_close(file) == SSH_OK) {
|
if (libssh2_sftp_close(file) == 0) {
|
||||||
guac_protocol_send_ack(client->socket, stream, "SFTP: OK",
|
guac_protocol_send_ack(client->socket, stream, "SFTP: OK",
|
||||||
GUAC_PROTOCOL_STATUS_SUCCESS);
|
GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||||
guac_socket_flush(client->socket);
|
guac_socket_flush(client->socket);
|
||||||
@ -205,14 +205,14 @@ int guac_sftp_ack_handler(guac_client* client, guac_stream* stream,
|
|||||||
char* message, guac_protocol_status status) {
|
char* message, guac_protocol_status status) {
|
||||||
|
|
||||||
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
||||||
sftp_file file = (sftp_file) stream->data;
|
LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
|
||||||
|
|
||||||
/* If successful, read data */
|
/* If successful, read data */
|
||||||
if (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
|
if (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
|
||||||
|
|
||||||
/* Attempt read into buffer */
|
/* Attempt read into buffer */
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
int bytes_read = sftp_read(file, buffer, sizeof(buffer));
|
int bytes_read = libssh2_sftp_read(file, buffer, sizeof(buffer));
|
||||||
|
|
||||||
/* If bytes read, send as blob */
|
/* If bytes read, send as blob */
|
||||||
if (bytes_read > 0)
|
if (bytes_read > 0)
|
||||||
@ -228,7 +228,7 @@ int guac_sftp_ack_handler(guac_client* client, guac_stream* stream,
|
|||||||
/* Otherwise, fail stream */
|
/* Otherwise, fail stream */
|
||||||
else {
|
else {
|
||||||
guac_client_log_error(client, "Error reading file: %s",
|
guac_client_log_error(client, "Error reading file: %s",
|
||||||
ssh_get_error(client_data->sftp_ssh_session));
|
libssh2_sftp_last_error(client_data->sftp_session));
|
||||||
guac_protocol_send_end(client->socket, stream);
|
guac_protocol_send_end(client->socket, stream);
|
||||||
guac_client_free_stream(client, stream);
|
guac_client_free_stream(client, stream);
|
||||||
}
|
}
|
||||||
@ -249,13 +249,15 @@ guac_stream* guac_sftp_download_file(guac_client* client,
|
|||||||
|
|
||||||
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
||||||
guac_stream* stream;
|
guac_stream* stream;
|
||||||
sftp_file file;
|
LIBSSH2_SFTP_HANDLE* file;
|
||||||
|
|
||||||
/* Attempt to open file for reading */
|
/* Attempt to open file for reading */
|
||||||
file = sftp_open(client_data->sftp_session, filename, O_RDONLY, 0);
|
file = libssh2_sftp_open(client_data->sftp_session, filename,
|
||||||
|
LIBSSH2_FXF_READ, 0);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
guac_client_log_error(client, "Unable to read file \"%s\": %s",
|
guac_client_log_error(client, "Unable to read file \"%s\": %s",
|
||||||
filename, ssh_get_error(client_data->sftp_ssh_session));
|
filename,
|
||||||
|
libssh2_sftp_last_error(client_data->sftp_session));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +44,7 @@
|
|||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
#include <guacamole/socket.h>
|
#include <guacamole/socket.h>
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh2.h>
|
||||||
#include <libssh/sftp.h>
|
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -153,7 +152,6 @@ static ssh_session __guac_ssh_create_session(guac_client* client) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
/* Authenticate with key if available */
|
/* Authenticate with key if available */
|
||||||
if (client_data->key != NULL) {
|
if (client_data->key != NULL) {
|
||||||
if (ssh_userauth_publickey(session, NULL, client_data->key)
|
if (ssh_userauth_publickey(session, NULL, client_data->key)
|
||||||
@ -166,7 +164,6 @@ static ssh_session __guac_ssh_create_session(guac_client* client) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Authenticate with password */
|
/* Authenticate with password */
|
||||||
if (ssh_userauth_password(session, NULL, client_data->password)
|
if (ssh_userauth_password(session, NULL, client_data->password)
|
||||||
@ -205,7 +202,6 @@ void* ssh_client_thread(void* data) {
|
|||||||
snprintf(name, sizeof(name)-1, "%s@%s", client_data->username, client_data->hostname);
|
snprintf(name, sizeof(name)-1, "%s@%s", client_data->username, client_data->hostname);
|
||||||
guac_protocol_send_name(socket, name);
|
guac_protocol_send_name(socket, name);
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
|
||||||
/* If key specified, import */
|
/* If key specified, import */
|
||||||
if (client_data->key_base64[0] != 0) {
|
if (client_data->key_base64[0] != 0) {
|
||||||
|
|
||||||
@ -239,10 +235,6 @@ void* ssh_client_thread(void* data) {
|
|||||||
|
|
||||||
/* Otherwise, get password if not provided */
|
/* Otherwise, get password if not provided */
|
||||||
else if (client_data->password[0] == 0) {
|
else if (client_data->password[0] == 0) {
|
||||||
#else
|
|
||||||
/* Get password if not provided */
|
|
||||||
if (client_data->password[0] == 0) {
|
|
||||||
#endif
|
|
||||||
if (prompt(client, "Password: ", client_data->password,
|
if (prompt(client, "Password: ", client_data->password,
|
||||||
sizeof(client_data->password), false) == NULL)
|
sizeof(client_data->password), false) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
144
src/protocols/ssh/ssh_key.c
Normal file
144
src/protocols/ssh/ssh_key.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
|
#include "ssh_buffer.h"
|
||||||
|
#include "ssh_key.h"
|
||||||
|
|
||||||
|
ssh_key* ssh_key_alloc(char* data, int length, char* passphrase) {
|
||||||
|
|
||||||
|
ssh_key* key;
|
||||||
|
BIO* key_bio;
|
||||||
|
|
||||||
|
char* public_key;
|
||||||
|
char* pos;
|
||||||
|
|
||||||
|
/* Create BIO for reading key from memory */
|
||||||
|
key_bio = BIO_new_mem_buf(data, length);
|
||||||
|
|
||||||
|
/* If RSA key, load RSA */
|
||||||
|
if (length > sizeof(SSH_RSA_KEY_HEADER)-1
|
||||||
|
&& memcmp(SSH_RSA_KEY_HEADER, data,
|
||||||
|
sizeof(SSH_RSA_KEY_HEADER)-1) == 0) {
|
||||||
|
|
||||||
|
RSA* rsa_key;
|
||||||
|
|
||||||
|
/* Read key */
|
||||||
|
rsa_key = PEM_read_bio_RSAPrivateKey(key_bio, NULL, NULL, passphrase);
|
||||||
|
if (rsa_key == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Allocate key */
|
||||||
|
key = malloc(sizeof(ssh_key));
|
||||||
|
key->rsa = rsa_key;
|
||||||
|
|
||||||
|
/* Set type */
|
||||||
|
key->type = SSH_KEY_RSA;
|
||||||
|
|
||||||
|
/* Allocate space for public key */
|
||||||
|
public_key = malloc(4096);
|
||||||
|
pos = public_key;
|
||||||
|
|
||||||
|
/* Derive public key */
|
||||||
|
buffer_write_string(&pos, "ssh-rsa", sizeof("ssh-rsa")-1);
|
||||||
|
buffer_write_bignum(&pos, rsa_key->e);
|
||||||
|
buffer_write_bignum(&pos, rsa_key->n);
|
||||||
|
|
||||||
|
/* Save public key to structure */
|
||||||
|
key->public_key = public_key;
|
||||||
|
key->public_key_length = pos - public_key;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If DSA key, load DSA */
|
||||||
|
else if (length > sizeof(SSH_DSA_KEY_HEADER)-1
|
||||||
|
&& memcmp(SSH_DSA_KEY_HEADER, data,
|
||||||
|
sizeof(SSH_DSA_KEY_HEADER)-1) == 0) {
|
||||||
|
|
||||||
|
DSA* dsa_key;
|
||||||
|
|
||||||
|
/* Read key */
|
||||||
|
dsa_key = PEM_read_bio_DSAPrivateKey(key_bio, NULL, NULL, passphrase);
|
||||||
|
if (dsa_key == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Allocate key */
|
||||||
|
key = malloc(sizeof(ssh_key));
|
||||||
|
key->dsa = dsa_key;
|
||||||
|
|
||||||
|
/* Set type */
|
||||||
|
key->type = SSH_KEY_DSA;
|
||||||
|
|
||||||
|
/* Allocate space for public key */
|
||||||
|
public_key = malloc(4096);
|
||||||
|
pos = public_key;
|
||||||
|
|
||||||
|
/* Derive public key */
|
||||||
|
buffer_write_string(&pos, "ssh-dsa", sizeof("ssh-dsa")-1);
|
||||||
|
buffer_write_bignum(&pos, dsa_key->p);
|
||||||
|
buffer_write_bignum(&pos, dsa_key->q);
|
||||||
|
buffer_write_bignum(&pos, dsa_key->g);
|
||||||
|
buffer_write_bignum(&pos, dsa_key->pub_key);
|
||||||
|
|
||||||
|
/* Save public key to structure */
|
||||||
|
key->public_key = public_key;
|
||||||
|
key->public_key_length = pos - public_key;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, unsupported type */
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Copy private key to structure */
|
||||||
|
key->private_key_length = length;
|
||||||
|
key->private_key = malloc(length);
|
||||||
|
memcpy(key->private_key, data, length);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssh_key_free(ssh_key* key) {
|
||||||
|
free(key->public_key);
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssh_key_sign(ssh_key* key, const char* data, int length, u_char* sig) {
|
||||||
|
|
||||||
|
const EVP_MD* md;
|
||||||
|
EVP_MD_CTX md_ctx;
|
||||||
|
|
||||||
|
u_char digest[EVP_MAX_MD_SIZE];
|
||||||
|
u_int dlen, len;
|
||||||
|
|
||||||
|
/* Get SHA1 digest */
|
||||||
|
if ((md = EVP_get_digestbynid(NID_sha1)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Digest data */
|
||||||
|
EVP_DigestInit(&md_ctx, md);
|
||||||
|
EVP_DigestUpdate(&md_ctx, data, length);
|
||||||
|
EVP_DigestFinal(&md_ctx, digest, &dlen);
|
||||||
|
|
||||||
|
/* Sign with key */
|
||||||
|
switch (key->type) {
|
||||||
|
|
||||||
|
case SSH_KEY_RSA:
|
||||||
|
if (RSA_sign(NID_sha1, digest, dlen, sig, &len, key->rsa) == 1)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
case SSH_KEY_DSA:
|
||||||
|
if (DSA_sign(NID_sha1, digest, dlen, sig, &len, key->dsa) == 1)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
98
src/protocols/ssh/ssh_key.h
Normal file
98
src/protocols/ssh/ssh_key.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
|
||||||
|
#ifndef _GUAC_SSH_KEY_H
|
||||||
|
#define _GUAC_SSH_KEY_H
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/dsa.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The expected header of RSA private keys.
|
||||||
|
*/
|
||||||
|
#define SSH_RSA_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The expected header of DSA private keys.
|
||||||
|
*/
|
||||||
|
#define SSH_DSA_KEY_HEADER "-----BEGIN DSA PRIVATE KEY-----"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of an SSH key.
|
||||||
|
*/
|
||||||
|
typedef enum ssh_key_type {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA key.
|
||||||
|
*/
|
||||||
|
SSH_KEY_RSA,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DSA key.
|
||||||
|
*/
|
||||||
|
SSH_KEY_DSA
|
||||||
|
|
||||||
|
} ssh_key_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction of a key used for SSH authentication.
|
||||||
|
*/
|
||||||
|
typedef struct ssh_key {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of this key.
|
||||||
|
*/
|
||||||
|
ssh_key_type type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Underlying RSA private key, if any.
|
||||||
|
*/
|
||||||
|
RSA* rsa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Underlying DSA private key, if any.
|
||||||
|
*/
|
||||||
|
DSA* dsa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The associated public key, encoded as necessary for SSH.
|
||||||
|
*/
|
||||||
|
char* public_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The length of the public key, in bytes.
|
||||||
|
*/
|
||||||
|
int public_key_length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The private key, encoded as necessary for SSH.
|
||||||
|
*/
|
||||||
|
char* private_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The length of the private key, in bytes.
|
||||||
|
*/
|
||||||
|
int private_key_length;
|
||||||
|
|
||||||
|
} ssh_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a new key containing the given private key data and specified
|
||||||
|
* passphrase. If unable to read the key, NULL is returned.
|
||||||
|
*/
|
||||||
|
ssh_key* ssh_key_alloc(char* data, int length, char* passphrase);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees all memory associated with the given key.
|
||||||
|
*/
|
||||||
|
void ssh_key_free(ssh_key* key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the given data using the given key, returning the length of the
|
||||||
|
* signature in bytes, or a value less than zero on error.
|
||||||
|
*/
|
||||||
|
int ssh_key_sign(ssh_key* key, const char* data, int length, u_char* sig);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user