From 050d3e54edb1871b75d8bfb70b8dda0c0956b0c0 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Mon, 14 Dec 2020 10:41:33 +0200 Subject: [PATCH] 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. --- configure.ac | 5 +++ src/ssh/cockpitsshrelay.c | 90 ++++++++++++++++++++------------------- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/configure.ac b/configure.ac index 7659f41da..085ceab7b 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/src/ssh/cockpitsshrelay.c b/src/ssh/cockpitsshrelay.c index 551fa2179..3b747c52a 100644 --- a/src/ssh/cockpitsshrelay.c +++ b/src/ssh/cockpitsshrelay.c @@ -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) {