]> xenbits.xensource.com Git - libvirt.git/commitdiff
libssh2: Improve password based authentication
authorPeter Krempa <pkrempa@redhat.com>
Tue, 9 Jul 2013 14:34:38 +0000 (16:34 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 12 Jul 2013 07:22:38 +0000 (09:22 +0200)
The password authentication method wasn't used as there wasn't a
pleasant way to pass the password. This patch adds the option to use
virAuth util functions to request the password either from a config file
or uses the conf callback to request it from the user.

src/rpc/virnetsshsession.c

index 211b7d75e831552e5e39e4c6ce23018dbfab454f..25a7efd75323564c0e25539809663a29de8a2b2b 100644 (file)
@@ -36,6 +36,7 @@
 #include "virfile.h"
 #include "virobject.h"
 #include "virstring.h"
+#include "virauth.h"
 
 #define VIR_FROM_THIS VIR_FROM_SSH
 
@@ -97,6 +98,7 @@ struct _virNetSSHSession {
 
     /* authentication stuff */
     virConnectAuthPtr cred;
+    char *authPath;
     virNetSSHAuthCallbackError authCbErr;
     size_t nauths;
     virNetSSHAuthMethodPtr *auths;
@@ -156,6 +158,7 @@ virNetSSHSessionDispose(void *obj)
     VIR_FREE(sess->channelCommand);
     VIR_FREE(sess->hostname);
     VIR_FREE(sess->knownHostsFile);
+    VIR_FREE(sess->authPath);
 }
 
 static virClassPtr virNetSSHSessionClass;
@@ -672,7 +675,8 @@ virNetSSHAuthenticatePrivkey(virNetSSHSessionPtr sess,
     return 0;
 }
 
-/* perform tunelled password authentication
+
+/* perform password authentication, either directly or request the password
  *
  * Returns: 0 on success
  *          1 on authentication failure
@@ -682,27 +686,71 @@ static int
 virNetSSHAuthenticatePassword(virNetSSHSessionPtr sess,
                               virNetSSHAuthMethodPtr priv)
 {
+    char *password = NULL;
     char *errmsg;
-    int ret;
+    int ret = -1;
+    int rc;
+
+    if (priv->password) {
+        /* tunelled password authentication */
+        if ((ret = libssh2_userauth_password(sess->session,
+                                             priv->username,
+                                             priv->password)) == 0) {
+            ret = 0;
+            goto cleanup;
+        }
+    } else {
+        /* password authentication with interactive password request */
+        if (!sess->cred || !sess->cred->cb) {
+            virReportError(VIR_ERR_SSH, "%s",
+                           _("Can't perform authentication: "
+                             "Authentication callback not provided"));
+            goto cleanup;
+        }
 
-    /* tunelled password authentication */
-    if ((ret = libssh2_userauth_password(sess->session,
-                                         priv->username,
-                                         priv->password)) < 0) {
-        libssh2_session_last_error(sess->session, &errmsg, NULL, 0);
-        virReportError(VIR_ERR_AUTH_FAILED,
-                       _("tunelled password authentication failed: %s"),
-                       errmsg);
+        /* Try the authenticating the set amount of times. The server breaks the
+         * connection if maximum number of bad auth tries is exceeded */
+        while (true) {
+            if (!(password = virAuthGetPasswordPath(sess->authPath, sess->cred,
+                                                    "ssh", priv->username,
+                                                    sess->hostname))) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("failed to retrieve password"));
+                goto cleanup;
+            }
 
-        if (ret == LIBSSH2_ERROR_AUTHENTICATION_FAILED)
-            return 1;
-        else
-            return -1;
+            /* tunelled password authentication */
+            if ((rc = libssh2_userauth_password(sess->session,
+                                                priv->username,
+                                                password)) == 0) {
+                ret = 0;
+                goto cleanup;
+            }
+
+            if (ret != LIBSSH2_ERROR_AUTHENTICATION_FAILED)
+                break;
+
+            VIR_FREE(password);
+        }
     }
-    /* auth success */
-    return 0;
+
+    /* error path */
+    libssh2_session_last_error(sess->session, &errmsg, NULL, 0);
+    virReportError(VIR_ERR_AUTH_FAILED,
+                   _("authentication failed: %s"), errmsg);
+
+    /* determine exist status */
+    if (ret == LIBSSH2_ERROR_AUTHENTICATION_FAILED)
+        return 1;
+    else
+        return -1;
+
+cleanup:
+    VIR_FREE(password);
+    return ret;
 }
 
+
 /* perform keyboard interactive authentication
  *
  * Returns: 0 on success