1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

libssh2: Improve password based authentication

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.
This commit is contained in:
Peter Krempa 2013-07-09 16:34:38 +02:00
parent c7dba5d695
commit 676504e3be

View File

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