Skip to content

Commit

Permalink
GUACAMOLE-1290: Merge support for ssh public certificate authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
necouchman authored Aug 1, 2023
2 parents 870cc5f + 766b9f6 commit 80598ae
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 1 deletion.
24 changes: 24 additions & 0 deletions src/common-ssh/common-ssh/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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

6 changes: 5 additions & 1 deletion src/common-ssh/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down
14 changes: 14 additions & 0 deletions src/common-ssh/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);

}
Expand Down Expand Up @@ -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;

}

11 changes: 11 additions & 0 deletions src/protocols/ssh/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/protocols/ssh/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
26 changes: 26 additions & 0 deletions src/protocols/ssh/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 80598ae

Please sign in to comment.