Partial migration, including SFTP.
This commit is contained in:
parent
602571400d
commit
d32018cf87
@ -52,6 +52,7 @@ libguac_client_ssh_la_SOURCES = \
|
||||
ibar.c \
|
||||
sftp.c \
|
||||
ssh_client.c \
|
||||
ssh_key.c \
|
||||
terminal.c \
|
||||
terminal_handlers.c
|
||||
|
||||
@ -65,9 +66,9 @@ noinst_HEADERS = \
|
||||
display.h \
|
||||
guac_handlers.h \
|
||||
ibar.h \
|
||||
libssh_compat.h \
|
||||
sftp.h \
|
||||
ssh_client.h \
|
||||
ssh_key.h \
|
||||
terminal.h \
|
||||
terminal_handlers.h \
|
||||
types.h
|
||||
|
@ -66,10 +66,8 @@ const char* GUAC_CLIENT_ARGS[] = {
|
||||
"font-name",
|
||||
"font-size",
|
||||
"enable-sftp",
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
"private-key",
|
||||
"passphrase",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -110,7 +108,6 @@ enum __SSH_ARGS_IDX {
|
||||
*/
|
||||
IDX_ENABLE_SFTP,
|
||||
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
IDX_PASSPHRASE,
|
||||
#endif
|
||||
|
||||
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->password, argv[IDX_PASSWORD]);
|
||||
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
/* Init public key auth information */
|
||||
client_data->key = NULL;
|
||||
strcpy(client_data->key_base64, argv[IDX_PRIVATE_KEY]);
|
||||
strcpy(client_data->key_passphrase, argv[IDX_PASSPHRASE]);
|
||||
#endif
|
||||
|
||||
/* Read font name */
|
||||
if (argv[IDX_FONT_NAME][0] != 0)
|
||||
|
@ -40,12 +40,13 @@
|
||||
#define _SSH_GUAC_CLIENT_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
|
||||
#include "terminal.h"
|
||||
#include "cursor.h"
|
||||
#include "sftp.h"
|
||||
#include "ssh_key.h"
|
||||
|
||||
/**
|
||||
* SSH-specific client data.
|
||||
@ -72,7 +73,6 @@ typedef struct ssh_guac_client_data {
|
||||
*/
|
||||
char password[1024];
|
||||
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
ssh_key key;
|
||||
#endif
|
||||
ssh_key* key;
|
||||
|
||||
/**
|
||||
* 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 session;
|
||||
LIBSSH2_SESSION* session;
|
||||
|
||||
/**
|
||||
* 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 sftp_session;
|
||||
LIBSSH2_SFTP* sftp_session;
|
||||
|
||||
/**
|
||||
* 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_channel term_channel;
|
||||
LIBSSH2_CHANNEL* term_channel;
|
||||
|
||||
/**
|
||||
* The terminal which will render all output from the SSH client.
|
||||
|
@ -51,9 +51,7 @@
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include "libssh_compat.h"
|
||||
#include <libssh2.h>
|
||||
|
||||
#include "guac_handlers.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 */
|
||||
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);
|
||||
|
||||
/* Reset scroll region */
|
||||
@ -422,8 +420,8 @@ int ssh_guac_client_free_handler(guac_client* client) {
|
||||
|
||||
/* Close SSH channel */
|
||||
if (guac_client_data->term_channel != NULL) {
|
||||
ssh_channel_close(guac_client_data->term_channel);
|
||||
ssh_channel_send_eof(guac_client_data->term_channel);
|
||||
libssh2_channel_send_eof(guac_client_data->term_channel);
|
||||
libssh2_channel_close(guac_client_data->term_channel);
|
||||
}
|
||||
|
||||
/* Free terminal */
|
||||
@ -431,23 +429,23 @@ int ssh_guac_client_free_handler(guac_client* client) {
|
||||
pthread_join(guac_client_data->client_thread, NULL);
|
||||
|
||||
/* Free channels */
|
||||
ssh_channel_free(guac_client_data->term_channel);
|
||||
libssh2_channel_free(guac_client_data->term_channel);
|
||||
|
||||
/* Clean up SFTP */
|
||||
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)
|
||||
ssh_free(guac_client_data->sftp_ssh_session);
|
||||
if (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 */
|
||||
ssh_free(guac_client_data->session);
|
||||
libssh2_session_free(guac_client_data->session);
|
||||
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
/* Free auth key */
|
||||
if (guac_client_data->key != NULL)
|
||||
ssh_key_free(guac_client_data->key);
|
||||
#endif
|
||||
|
||||
/* Free 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 <fcntl.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include <libssh2.h>
|
||||
|
||||
#include <guacamole/client.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;
|
||||
char fullpath[GUAC_SFTP_MAX_PATH];
|
||||
sftp_file file;
|
||||
LIBSSH2_SFTP_HANDLE* file;
|
||||
int i;
|
||||
|
||||
/* 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';
|
||||
|
||||
/* Open file via SFTP */
|
||||
file = sftp_open(client_data->sftp_session, fullpath,
|
||||
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
file = libssh2_sftp_open(client_data->sftp_session, fullpath,
|
||||
LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
|
||||
/* Inform of status */
|
||||
if (file != NULL) {
|
||||
@ -140,7 +140,7 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
||||
}
|
||||
else {
|
||||
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_STATUS_INTERNAL_ERROR);
|
||||
guac_socket_flush(client->socket);
|
||||
@ -157,10 +157,10 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
||||
|
||||
/* Pull file from stream */
|
||||
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 */
|
||||
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_STATUS_SUCCESS);
|
||||
guac_socket_flush(client->socket);
|
||||
@ -169,7 +169,7 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
||||
/* Inform of any errors */
|
||||
else {
|
||||
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_STATUS_INTERNAL_ERROR);
|
||||
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) {
|
||||
|
||||
/* Pull file from stream */
|
||||
sftp_file file = (sftp_file) stream->data;
|
||||
LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
|
||||
|
||||
/* 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_STATUS_SUCCESS);
|
||||
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) {
|
||||
|
||||
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 (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
|
||||
|
||||
/* Attempt read into buffer */
|
||||
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 > 0)
|
||||
@ -228,7 +228,7 @@ int guac_sftp_ack_handler(guac_client* client, guac_stream* stream,
|
||||
/* Otherwise, fail stream */
|
||||
else {
|
||||
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_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;
|
||||
guac_stream* stream;
|
||||
sftp_file file;
|
||||
LIBSSH2_SFTP_HANDLE* file;
|
||||
|
||||
/* 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,7 @@
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include <libssh2.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
@ -153,7 +152,6 @@ static ssh_session __guac_ssh_create_session(guac_client* client) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
/* Authenticate with key if available */
|
||||
if (client_data->key != NULL) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Authenticate with 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);
|
||||
guac_protocol_send_name(socket, name);
|
||||
|
||||
#ifdef ENABLE_SSH_PUBLIC_KEY
|
||||
/* If key specified, import */
|
||||
if (client_data->key_base64[0] != 0) {
|
||||
|
||||
@ -239,10 +235,6 @@ void* ssh_client_thread(void* data) {
|
||||
|
||||
/* Otherwise, get password if not provided */
|
||||
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,
|
||||
sizeof(client_data->password), false) == 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