[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/2] libssh2_transport: Add fallback authentication method for password auth



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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]