GUACAMOLE-1290: Merge support for ssh public certificate authentication
This commit is contained in:
commit
80598ae857
@ -44,6 +44,12 @@ typedef struct guac_common_ssh_user {
|
||||
*/
|
||||
guac_common_ssh_key* private_key;
|
||||
|
||||
/**
|
||||
* The public key which should be used to authenticate this user, if any,
|
||||
* or NULL if a password or just a private key will be used instead.
|
||||
*/
|
||||
char* public_key;
|
||||
|
||||
} guac_common_ssh_user;
|
||||
|
||||
/**
|
||||
@ -104,5 +110,23 @@ void guac_common_ssh_user_set_password(guac_common_ssh_user* user,
|
||||
int guac_common_ssh_user_import_key(guac_common_ssh_user* user,
|
||||
char* private_key, char* passphrase);
|
||||
|
||||
/**
|
||||
* Imports the given public key, associating that key with the given user.
|
||||
* If the public key is imported successfully, it will be used for
|
||||
* future authentication attempts.
|
||||
*
|
||||
* @param user
|
||||
* The user to associate with the given private key.
|
||||
*
|
||||
* @param public_key
|
||||
* The base64-encoded public key to import.
|
||||
*
|
||||
* @return
|
||||
* Zero if public key is successfully imported, or non-zero if the
|
||||
* public key could not be imported due to an error.
|
||||
*/
|
||||
int guac_common_ssh_user_import_public_key(guac_common_ssh_user* user,
|
||||
char* public_key);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -284,6 +284,8 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
|
||||
/* Get user credentials */
|
||||
guac_common_ssh_key* key = user->private_key;
|
||||
|
||||
char* public_key = user->public_key;
|
||||
|
||||
/* Validate username provided */
|
||||
if (user->username == NULL) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
@ -317,9 +319,11 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int public_key_length = public_key == NULL ? 0 : strlen(public_key);
|
||||
|
||||
/* Attempt public key auth */
|
||||
if (libssh2_userauth_publickey_frommemory(session, user->username,
|
||||
username_len, NULL, 0, key->private_key,
|
||||
username_len, public_key, public_key_length, key->private_key,
|
||||
key->private_key_length, key->passphrase)) {
|
||||
|
||||
/* Abort on failure */
|
||||
|
||||
@ -31,6 +31,7 @@ guac_common_ssh_user* guac_common_ssh_create_user(const char* username) {
|
||||
user->username = strdup(username);
|
||||
user->password = NULL;
|
||||
user->private_key = NULL;
|
||||
user->public_key = NULL;
|
||||
|
||||
return user;
|
||||
|
||||
@ -45,6 +46,7 @@ void guac_common_ssh_destroy_user(guac_common_ssh_user* user) {
|
||||
/* Free all other data */
|
||||
free(user->password);
|
||||
free(user->username);
|
||||
free(user->public_key);
|
||||
free(user);
|
||||
|
||||
}
|
||||
@ -80,3 +82,15 @@ int guac_common_ssh_user_import_key(guac_common_ssh_user* user,
|
||||
|
||||
}
|
||||
|
||||
int guac_common_ssh_user_import_public_key(guac_common_ssh_user* user,
|
||||
char* public_key) {
|
||||
|
||||
/* Free existing public key, if present */
|
||||
free(user->public_key);
|
||||
user->public_key = strdup(public_key);
|
||||
|
||||
/* Fail if key could not be read */
|
||||
return user->public_key == NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = {
|
||||
"sftp-disable-upload",
|
||||
"private-key",
|
||||
"passphrase",
|
||||
"public-key",
|
||||
#ifdef ENABLE_SSH_AGENT
|
||||
"enable-agent",
|
||||
#endif
|
||||
@ -148,6 +149,11 @@ enum SSH_ARGS_IDX {
|
||||
*/
|
||||
IDX_PASSPHRASE,
|
||||
|
||||
/**
|
||||
* The public key to use for authentication, if any.
|
||||
*/
|
||||
IDX_PUBLIC_KEY,
|
||||
|
||||
#ifdef ENABLE_SSH_AGENT
|
||||
/**
|
||||
* Whether SSH agent forwarding support should be enabled.
|
||||
@ -373,6 +379,10 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
|
||||
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||
IDX_PASSPHRASE, NULL);
|
||||
|
||||
settings->public_key_base64 =
|
||||
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||
IDX_PUBLIC_KEY, NULL);
|
||||
|
||||
/* Read maximum scrollback size */
|
||||
settings->max_scrollback =
|
||||
guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||
@ -567,6 +577,7 @@ void guac_ssh_settings_free(guac_ssh_settings* settings) {
|
||||
free(settings->password);
|
||||
free(settings->key_base64);
|
||||
free(settings->key_passphrase);
|
||||
free(settings->public_key_base64);
|
||||
|
||||
/* Free display preferences */
|
||||
free(settings->font_name);
|
||||
|
||||
@ -93,6 +93,12 @@ typedef struct guac_ssh_settings {
|
||||
*/
|
||||
char* key_passphrase;
|
||||
|
||||
/**
|
||||
* The public key, encoded as base64, if any. If no public key is specified,
|
||||
* this will be NULL.
|
||||
*/
|
||||
char* public_key_base64;
|
||||
|
||||
/**
|
||||
* Whether this connection is read-only, and user input should be dropped.
|
||||
*/
|
||||
|
||||
@ -134,6 +134,32 @@ static guac_common_ssh_user* guac_ssh_get_user(guac_client* client) {
|
||||
|
||||
} /* end if key given */
|
||||
|
||||
if (settings->public_key_base64 != NULL) {
|
||||
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Attempting public key import");
|
||||
|
||||
/* Attempt to read public key */
|
||||
if (guac_common_ssh_user_import_public_key(user,
|
||||
settings->public_key_base64)) {
|
||||
|
||||
/* If failing*/
|
||||
guac_client_abort(client,
|
||||
GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
"Auth public key import failed: %s",
|
||||
guac_common_ssh_key_error());
|
||||
|
||||
guac_common_ssh_destroy_user(user);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Success */
|
||||
guac_client_log(client, GUAC_LOG_INFO,
|
||||
"Auth public key successfully imported.");
|
||||
|
||||
}
|
||||
|
||||
/* If available, get password from settings */
|
||||
else if (settings->password != NULL) {
|
||||
guac_common_ssh_user_set_password(user, settings->password);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user