When keyboard-interactive authentication is disabled on a host libvirt
fails when attempting authentication with password. This patch adds code
that simulates keyboard interactive authentication using "password" auth
method in libssh2.
---
src/rpc/virnetsshsession.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/src/rpc/virnetsshsession.c b/src/rpc/virnetsshsession.c
index 13a0368..9b35b03 100644
--- a/src/rpc/virnetsshsession.c
+++ b/src/rpc/virnetsshsession.c
@@ -34,6 +34,7 @@
#include "util.h"
#include "virterror_internal.h"
#include "virobject.h"
+#include "virauth.h"
#define VIR_FROM_THIS VIR_FROM_SSH
@@ -769,6 +770,66 @@ virNetSSHAuthenticateKeyboardInteractive(virNetSSHSessionPtr sess,
return 1;
}
+/* perform keyboard interactive authentication using fallback password method
+ *
+ * Returns: 0 on success
+ * 1 on authentication failure
+ * -1 on error
+ */
+static int
+virNetSSHAuthenticateKeyboardFallback(virNetSSHSessionPtr sess,
+ virNetSSHAuthMethodPtr priv)
+{
+ char *password = NULL;
+ char *errmsg;
+ int ret = -1;
+ int rc;
+
+
+ if (!sess->cred || !sess->cred->cb) {
+ virReportError(VIR_ERR_SSH, "%s",
+ _("Can't perform authentication: "
+ "Authentication callback not provided"));
+ return -1;
+ }
+
+ /* Try the authenticating the set amount of times. The server breaks the
+ * connection if maximum number of bad auth tries is exceeded */
+ while (priv->tries < 0 || priv->tries-- > 0) {
+ if (!(password = virAuthGetPassword(NULL, sess->cred, NULL,
+ priv->username, sess->hostname))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to retrieve password"));
+ goto cleanup;
+ }
+
+ /* tunelled password authentication */
+ if ((rc = libssh2_userauth_password(sess->session,
+ priv->username,
+ password)) == 0) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ /* error path */
+ libssh2_session_last_error(sess->session, &errmsg, NULL, 0);
+ virReportError(VIR_ERR_AUTH_FAILED,
+ _("authentication failed: %s"),
+ errmsg);
+
+ if (ret != LIBSSH2_ERROR_AUTHENTICATION_FAILED)
+ goto cleanup;
+ }
+
+ /* authentication failed */
+ ret = 1;
+
+cleanup:
+ VIR_FREE(password);
+ return ret;
+}
+
+
/* select auth method and authenticate */
static int
virNetSSHAuthenticate(virNetSSHSessionPtr sess)
@@ -814,6 +875,9 @@ virNetSSHAuthenticate(virNetSSHSessionPtr sess)
case VIR_NET_SSH_AUTH_KEYBOARD_INTERACTIVE:
if (strstr(auth_list, "keyboard-interactive"))
ret = virNetSSHAuthenticateKeyboardInteractive(sess, auth);
+ else if (strstr(auth_list, "password"))
+ ret = virNetSSHAuthenticateKeyboardFallback(sess, auth);
+
break;
case VIR_NET_SSH_AUTH_AGENT:
if (strstr(auth_list, "publickey"))
--
1.8.0