ssh: Use ssh_userauth_publickey_auto

The new ssh_userauth_publickey_auto_get_current_identity allows us to
get all information we need when a key has to be unlocked.
This commit is contained in:
Marius Vollmer 2020-12-14 10:41:33 +02:00 committed by Martin Pitt
parent 1cd33185f2
commit 050d3e54ed
2 changed files with 51 additions and 44 deletions

View File

@ -92,6 +92,11 @@ if test "$enable_polkit" != "no"; then
fi
if test "$enable_ssh" != "no"; then
PKG_CHECK_MODULES(libssh, [libssh >= 0.8.5])
old_CFLAGS=$CFLAGS; CFLAGS=$libssh_CFLAGS
old_LIBS=$LIBS; LIBS=$libssh_LIBS
AC_CHECK_FUNCS(ssh_userauth_publickey_auto_get_current_identity)
CFLAGS=$old_CFLAGS
LIBS=$old_LIBS
fi
# pam

View File

@ -840,6 +840,50 @@ do_password_auth (CockpitSshData *data)
return rc;
}
#ifdef HAVE_SSH_USERAUTH_PUBLICKEY_AUTO_GET_CURRENT_IDENTITY
static int
intercept_prompt (const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata)
{
CockpitSshData *data = userdata;
char *identity = NULL;
if (ssh_userauth_publickey_auto_get_current_identity (data->session, &identity) == SSH_OK)
{
data->problem_error = g_strdup_printf ("locked identity: %s", identity);
ssh_string_free_char (identity);
}
return -1;
}
static int
do_auto_auth (CockpitSshData *data)
{
struct ssh_callbacks_struct cb = { .userdata = data, .auth_function = intercept_prompt };
ssh_callbacks_init (&cb);
ssh_set_callbacks (data->session, &cb);
int rc = ssh_userauth_publickey_auto (data->session, NULL, NULL);
ssh_set_callbacks (data->session, NULL);
return rc;
}
#else
/* When prompting for a key passphrase, versions of libssh without
ssh_userauth_publickey_auto_get_current_identity don't provide
enough information to say which key it is for. We need that
information since Cockpit will offer to load the key into the agent
in order to log in.
Thus, we have to reimplement ssh_userauth_publickey_auto to get the
necessary information.
We would like to iterate over all configured identities, the same
way that the real ssh_userauth_publickey does, but there is no
API to do that either. So we hard code all the names, based on
what ssh-add would add to the agent.
*/
struct CockpitSshPromptData {
CockpitSshData *data;
const gchar *identity;
@ -860,50 +904,6 @@ prompt_for_identity_password (const char *prompt, char *buf, size_t len,
static int
do_auto_auth (CockpitSshData *data)
{
/* HACK: When prompting for a key passphrase, libssh doesn't provide
enough information to say which key it is for, but we need that
information since Cockpit will offer to load the key into the
agent in order to log in.
To get this information, we reimplement
ssh_userauth_publickey_auto here in a way that passes that
information to the callback.
We would like to iterate over all configured identities, the same
way that the real ssh_userauth_publickey does, but there is no
API to do that either. So we hard code all the names, based on
what ssh-add would add to the agent.
This whole thing is meant to be replaced with something like this
eventually:
static int
intercept_prompt (const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata)
{
CockpitSshData *data = userdata;
char *identity = NULL;
if (ssh_userauth_publickey_auto_get_current_identity (data->session, &identity) == SSH_OK)
{
data->problem_error = g_strdup_printf ("locked identity: %s", identity);
ssh_string_free_char (identity);
}
return -1;
}
static int
do_auto_auth (CockpitSshData *data)
{
struct ssh_callbacks_struct cb = { .userdata = data, .auth_function = intercept_prompt };
ssh_callbacks_init (&cb);
ssh_set_callbacks (data->session, &cb);
int rc = ssh_userauth_publickey_auto (data->session, NULL, NULL);
ssh_set_callbacks (data->session, NULL);
return rc;
}
See https://gitlab.com/libssh/libssh-mirror/-/merge_requests/134
*/
int rc;
const gchar *msg;
@ -1020,6 +1020,8 @@ do_auto_auth (CockpitSshData *data)
return rc;
}
#endif
static int
do_key_auth (CockpitSshData *data)
{