GUAC-1171: Add key and buffer helpers. Partially implement private key auth.
This commit is contained in:
parent
5b627ae5cc
commit
0a015b2843
@ -27,11 +27,15 @@ noinst_LTLIBRARIES = libguac_common_ssh.la
|
||||
|
||||
libguac_common_ssh_la_SOURCES = \
|
||||
guac_sftp.c \
|
||||
guac_ssh.c
|
||||
guac_ssh.c \
|
||||
guac_ssh_buffer.c \
|
||||
guac_ssh_key.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
guac_sftp.h \
|
||||
guac_ssh.h
|
||||
noinst_HEADERS = \
|
||||
guac_sftp.h \
|
||||
guac_ssh.h \
|
||||
guac_ssh_buffer.h \
|
||||
guac_ssh_key.h
|
||||
|
||||
libguac_common_ssh_la_CFLAGS = \
|
||||
-Werror -Wall -pedantic \
|
||||
|
@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "guac_ssh.h"
|
||||
#include "guac_ssh_key.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <libssh2.h>
|
||||
@ -274,17 +275,104 @@ LIBSSH2_SESSION* guac_common_ssh_connect_password(guac_client* client,
|
||||
|
||||
}
|
||||
|
||||
static int __sign_callback(LIBSSH2_SESSION* session,
|
||||
unsigned char** sig, size_t* sig_len,
|
||||
const unsigned char* data, size_t data_len, void **abstract) {
|
||||
|
||||
guac_common_ssh_key* key = (guac_common_ssh_key*) abstract;
|
||||
int length;
|
||||
|
||||
/* Allocate space for signature */
|
||||
*sig = malloc(4096);
|
||||
|
||||
/* Sign with key */
|
||||
length = guac_common_ssh_key_sign(key, (const char*) data, data_len, *sig);
|
||||
if (length < 0)
|
||||
return 1;
|
||||
|
||||
*sig_len = length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBSSH2_SESSION* guac_common_ssh_connect_private_key(guac_client* client,
|
||||
const char* hostname, const char* port,
|
||||
const char* username, const char* private_key,
|
||||
const char* passphrase,
|
||||
const char* username, char* private_key, char* passphrase,
|
||||
int* socket_fd) {
|
||||
|
||||
LIBSSH2_SESSION* session = guac_common_ssh_connect(client,
|
||||
hostname, port, socket_fd);
|
||||
|
||||
/* STUB */
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Attempting private key import (WITHOUT passphrase)");
|
||||
|
||||
/* Attempt to read key without passphrase */
|
||||
guac_common_ssh_key* key = guac_common_ssh_key_alloc(private_key,
|
||||
strlen(private_key), "");
|
||||
|
||||
#if 0
|
||||
/* On failure, attempt with passphrase */
|
||||
if (key == 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 (client_data->key_passphrase[0] == 0)
|
||||
guac_terminal_prompt(client_data->term, "Key passphrase: ",
|
||||
client_data->key_passphrase, sizeof(client_data->key_passphrase), false);
|
||||
|
||||
/* Import key with passphrase */
|
||||
client_data->key = guac_common_ssh_key_alloc(client_data->key_base64,
|
||||
strlen(client_data->key_base64),
|
||||
client_data->key_passphrase);
|
||||
|
||||
/* If still failing, give up */
|
||||
if (client_data->key == NULL) {
|
||||
guac_client_abort(client,
|
||||
GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
"Auth key import failed: %s", guac_common_ssh_key_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} /* end decrypt key with passphrase */
|
||||
#endif
|
||||
|
||||
/* Success */
|
||||
guac_client_log(client, GUAC_LOG_INFO, "Auth key successfully imported.");
|
||||
|
||||
/* Get list of suported authentication methods */
|
||||
char* user_authlist = libssh2_userauth_list(session, username,
|
||||
strlen(username));
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Supported authentication methods: %s", user_authlist);
|
||||
|
||||
/* Check if public key auth is suported on the server */
|
||||
if (strstr(user_authlist, "publickey") == NULL) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
"Public key authentication not suported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempt public key auth */
|
||||
if (libssh2_userauth_publickey(session, username,
|
||||
(unsigned char*) key->public_key, key->public_key_length,
|
||||
__sign_callback, (void**) key)) {
|
||||
|
||||
/* Abort on failure */
|
||||
char* error_message;
|
||||
libssh2_session_last_error(session, &error_message, NULL, 0);
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
"Public key authentication failed: %s", error_message);
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Return new session on success */
|
||||
return session;
|
||||
|
||||
}
|
||||
|
@ -113,8 +113,7 @@ LIBSSH2_SESSION* guac_common_ssh_connect_password(guac_client* client,
|
||||
*/
|
||||
LIBSSH2_SESSION* guac_common_ssh_connect_private_key(guac_client* client,
|
||||
const char* hostname, const char* port,
|
||||
const char* username, const char* private_key,
|
||||
const char* passphrase,
|
||||
const char* username, char* private_key, char* passphrase,
|
||||
int* socket_fd);
|
||||
|
||||
#endif
|
||||
|
136
src/common-ssh/guac_ssh_buffer.c
Normal file
136
src/common-ssh/guac_ssh_buffer.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ossl_typ.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void guac_common_buffer_write_byte(char** buffer, uint8_t value) {
|
||||
|
||||
uint8_t* data = (uint8_t*) *buffer;
|
||||
*data = value;
|
||||
|
||||
(*buffer)++;
|
||||
|
||||
}
|
||||
|
||||
void guac_common_buffer_write_uint32(char** buffer, uint32_t value) {
|
||||
|
||||
uint8_t* data = (uint8_t*) *buffer;
|
||||
|
||||
data[0] = (value & 0xFF000000) >> 24;
|
||||
data[1] = (value & 0x00FF0000) >> 16;
|
||||
data[2] = (value & 0x0000FF00) >> 8;
|
||||
data[3] = value & 0x000000FF;
|
||||
|
||||
*buffer += 4;
|
||||
|
||||
}
|
||||
|
||||
void guac_common_buffer_write_data(char** buffer, const char* data, int length) {
|
||||
memcpy(*buffer, data, length);
|
||||
*buffer += length;
|
||||
}
|
||||
|
||||
void guac_common_buffer_write_bignum(char** buffer, BIGNUM* value) {
|
||||
|
||||
unsigned char* bn_buffer;
|
||||
int length;
|
||||
|
||||
/* If zero, just write zero length */
|
||||
if (BN_is_zero(value)) {
|
||||
guac_common_buffer_write_uint32(buffer, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate output buffer, add padding byte */
|
||||
length = BN_num_bytes(value);
|
||||
bn_buffer = malloc(length);
|
||||
|
||||
/* Convert BIGNUM */
|
||||
BN_bn2bin(value, bn_buffer);
|
||||
|
||||
/* If first byte has high bit set, write padding byte */
|
||||
if (bn_buffer[0] & 0x80) {
|
||||
guac_common_buffer_write_uint32(buffer, length+1);
|
||||
guac_common_buffer_write_byte(buffer, 0);
|
||||
}
|
||||
else
|
||||
guac_common_buffer_write_uint32(buffer, length);
|
||||
|
||||
/* Write data */
|
||||
memcpy(*buffer, bn_buffer, length);
|
||||
*buffer += length;
|
||||
|
||||
free(bn_buffer);
|
||||
|
||||
}
|
||||
|
||||
void guac_common_buffer_write_string(char** buffer, const char* string, int length) {
|
||||
guac_common_buffer_write_uint32(buffer, length);
|
||||
guac_common_buffer_write_data(buffer, string, length);
|
||||
}
|
||||
|
||||
uint8_t guac_common_buffer_read_byte(char** buffer) {
|
||||
|
||||
uint8_t* data = (uint8_t*) *buffer;
|
||||
uint8_t value = *data;
|
||||
|
||||
(*buffer)++;
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
uint32_t guac_common_buffer_read_uint32(char** buffer) {
|
||||
|
||||
uint8_t* data = (uint8_t*) *buffer;
|
||||
uint32_t value =
|
||||
(data[0] << 24)
|
||||
| (data[1] << 16)
|
||||
| (data[2] << 8)
|
||||
| data[3];
|
||||
|
||||
*buffer += 4;
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
char* guac_common_buffer_read_string(char** buffer, int* length) {
|
||||
|
||||
char* value;
|
||||
|
||||
*length = guac_common_buffer_read_uint32(buffer);
|
||||
value = *buffer;
|
||||
|
||||
*buffer += *length;
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
81
src/common-ssh/guac_ssh_buffer.h
Normal file
81
src/common-ssh/guac_ssh_buffer.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_COMMON_SSH_BUFFER_H
|
||||
#define GUAC_COMMON_SSH_BUFFER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Writes the given byte to the given buffer, advancing the buffer pointer by
|
||||
* one byte.
|
||||
*/
|
||||
void guac_common_buffer_write_byte(char** buffer, uint8_t value);
|
||||
|
||||
/**
|
||||
* Writes the given integer to the given buffer, advancing the buffer pointer
|
||||
* four bytes.
|
||||
*/
|
||||
void guac_common_buffer_write_uint32(char** buffer, uint32_t value);
|
||||
|
||||
/**
|
||||
* Writes the given string and its length to the given buffer, advancing the
|
||||
* buffer pointer by the size of the length (four bytes) and the size of the
|
||||
* string.
|
||||
*/
|
||||
void guac_common_buffer_write_string(char** buffer, const char* string, int length);
|
||||
|
||||
/**
|
||||
* Writes the given BIGNUM the given buffer, advancing the buffer pointer by
|
||||
* the size of the length (four bytes) and the size of the BIGNUM.
|
||||
*/
|
||||
void guac_common_buffer_write_bignum(char** buffer, BIGNUM* value);
|
||||
|
||||
/**
|
||||
* Writes the given data the given buffer, advancing the buffer pointer by the
|
||||
* given length.
|
||||
*/
|
||||
void guac_common_buffer_write_data(char** buffer, const char* data, int length);
|
||||
|
||||
/**
|
||||
* Reads a single byte from the given buffer, advancing the buffer by one byte.
|
||||
*/
|
||||
uint8_t guac_common_buffer_read_byte(char** buffer);
|
||||
|
||||
/**
|
||||
* Reads an integer from the given buffer, advancing the buffer by four bytes.
|
||||
*/
|
||||
uint32_t guac_common_buffer_read_uint32(char** buffer);
|
||||
|
||||
/**
|
||||
* Reads a string and its length from the given buffer, advancing the buffer
|
||||
* by the size of the length (four bytes) and the size of the string, and
|
||||
* returning a pointer to the buffer. The length of the string is stored in
|
||||
* the given int.
|
||||
*/
|
||||
char* guac_common_buffer_read_string(char** buffer, int* length);
|
||||
|
||||
#endif
|
||||
|
218
src/common-ssh/guac_ssh_key.c
Normal file
218
src/common-ssh/guac_ssh_key.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "guac_ssh_buffer.h"
|
||||
#include "guac_ssh_key.h"
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
guac_common_ssh_key* guac_common_ssh_key_alloc(char* data, int length,
|
||||
char* passphrase) {
|
||||
|
||||
guac_common_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(guac_common_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 */
|
||||
guac_common_buffer_write_string(&pos, "ssh-rsa", sizeof("ssh-rsa")-1);
|
||||
guac_common_buffer_write_bignum(&pos, rsa_key->e);
|
||||
guac_common_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(guac_common_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 */
|
||||
guac_common_buffer_write_string(&pos, "ssh-dss", sizeof("ssh-dss")-1);
|
||||
guac_common_buffer_write_bignum(&pos, dsa_key->p);
|
||||
guac_common_buffer_write_bignum(&pos, dsa_key->q);
|
||||
guac_common_buffer_write_bignum(&pos, dsa_key->g);
|
||||
guac_common_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 {
|
||||
BIO_free(key_bio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy private key to structure */
|
||||
key->private_key_length = length;
|
||||
key->private_key = malloc(length);
|
||||
memcpy(key->private_key, data, length);
|
||||
|
||||
BIO_free(key_bio);
|
||||
return key;
|
||||
|
||||
}
|
||||
|
||||
const char* guac_common_ssh_key_error() {
|
||||
|
||||
/* Return static error string */
|
||||
return ERR_reason_error_string(ERR_get_error());
|
||||
|
||||
}
|
||||
|
||||
void guac_common_ssh_key_free(guac_common_ssh_key* key) {
|
||||
|
||||
/* Free key-specific data */
|
||||
if (key->type == SSH_KEY_RSA)
|
||||
RSA_free(key->rsa);
|
||||
else if (key->type == SSH_KEY_DSA)
|
||||
DSA_free(key->dsa);
|
||||
|
||||
free(key->public_key);
|
||||
free(key);
|
||||
}
|
||||
|
||||
int guac_common_ssh_key_sign(guac_common_ssh_key* key, const char* data,
|
||||
int length, unsigned char* sig) {
|
||||
|
||||
const EVP_MD* md;
|
||||
EVP_MD_CTX md_ctx;
|
||||
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned 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: {
|
||||
|
||||
DSA_SIG* dsa_sig = DSA_do_sign(digest, dlen, key->dsa);
|
||||
if (dsa_sig != NULL) {
|
||||
|
||||
/* Compute size of each half of signature */
|
||||
int rlen = BN_num_bytes(dsa_sig->r);
|
||||
int slen = BN_num_bytes(dsa_sig->s);
|
||||
|
||||
/* Ensure each number is within the required size */
|
||||
if (rlen > DSA_SIG_NUMBER_SIZE || slen > DSA_SIG_NUMBER_SIZE)
|
||||
return -1;
|
||||
|
||||
/* Init to all zeroes */
|
||||
memset(sig, 0, DSA_SIG_SIZE);
|
||||
|
||||
/* Add R at the end of the first block of the signature */
|
||||
BN_bn2bin(dsa_sig->r, sig + DSA_SIG_SIZE
|
||||
- DSA_SIG_NUMBER_SIZE - rlen);
|
||||
|
||||
/* Add S at the end of the second block of the signature */
|
||||
BN_bn2bin(dsa_sig->s, sig + DSA_SIG_SIZE - slen);
|
||||
|
||||
/* Done */
|
||||
DSA_SIG_free(dsa_sig);
|
||||
return DSA_SIG_SIZE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
138
src/common-ssh/guac_ssh_key.h
Normal file
138
src/common-ssh/guac_ssh_key.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_COMMON_SSH_KEY_H
|
||||
#define GUAC_COMMON_SSH_KEY_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <openssl/ossl_typ.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 size of single number within a DSA signature, in bytes.
|
||||
*/
|
||||
#define DSA_SIG_NUMBER_SIZE 20
|
||||
|
||||
/**
|
||||
* The size of a DSA signature, in bytes.
|
||||
*/
|
||||
#define DSA_SIG_SIZE DSA_SIG_NUMBER_SIZE*2
|
||||
|
||||
/**
|
||||
* The type of an SSH key.
|
||||
*/
|
||||
typedef enum guac_common_ssh_key_type {
|
||||
|
||||
/**
|
||||
* RSA key.
|
||||
*/
|
||||
SSH_KEY_RSA,
|
||||
|
||||
/**
|
||||
* DSA key.
|
||||
*/
|
||||
SSH_KEY_DSA
|
||||
|
||||
} guac_common_ssh_key_type;
|
||||
|
||||
/**
|
||||
* Abstraction of a key used for SSH authentication.
|
||||
*/
|
||||
typedef struct guac_common_ssh_key {
|
||||
|
||||
/**
|
||||
* The type of this key.
|
||||
*/
|
||||
guac_common_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;
|
||||
|
||||
} guac_common_ssh_key;
|
||||
|
||||
/**
|
||||
* Allocates a new key containing the given private key data and specified
|
||||
* passphrase. If unable to read the key, NULL is returned.
|
||||
*/
|
||||
guac_common_ssh_key* guac_common_ssh_key_alloc(char* data, int length,
|
||||
char* passphrase);
|
||||
|
||||
/**
|
||||
* Returns a statically-allocated string describing the most recent SSH key
|
||||
* error.
|
||||
*
|
||||
* @return
|
||||
* A statically-allocated string describing the most recent SSH key error.
|
||||
*/
|
||||
const char* guac_common_ssh_key_error();
|
||||
|
||||
/**
|
||||
* Frees all memory associated with the given key.
|
||||
*/
|
||||
void guac_common_ssh_key_free(guac_common_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 guac_common_ssh_key_sign(guac_common_ssh_key* key, const char* data,
|
||||
int length, unsigned char* sig);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user