[libvirt] [PATCH 14/14] Lookup auth credentials in config file before prompting
Osier Yang
jyang at redhat.com
Thu Mar 22 09:15:19 UTC 2012
On 2012年03月21日 01:33, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange"<berrange at redhat.com>
>
> When SASL requests auth credentials, try to look them up in the
> config file first. If any are found, remove them from the list
> that the user is prompted for
> ---
> src/esx/esx_driver.c | 58 +++++++++---------
> src/hyperv/hyperv_driver.c | 4 +-
> src/phyp/phyp_driver.c | 4 +-
> src/remote/remote_driver.c | 138 ++++++++++++++++++++++++++++++++++++--------
> src/util/virauth.c | 69 +++++++++++++++++++++-
> src/util/virauth.h | 10 +++-
> src/xenapi/xenapi_driver.c | 4 +-
> 7 files changed, 224 insertions(+), 63 deletions(-)
>
> diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
> index 7689306..6962832 100644
> --- a/src/esx/esx_driver.c
> +++ b/src/esx/esx_driver.c
> @@ -667,10 +667,8 @@ esxCapsInit(esxPrivate *priv)
>
>
> static int
> -esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
> - const char *hostname, int port,
> - const char *predefinedUsername,
> - esxVI_ProductVersion expectedProductVersion,
> +esxConnectToHost(virConnectPtr conn,
> + virConnectAuthPtr auth,
> char **vCenterIpAddress)
> {
> int result = -1;
> @@ -682,25 +680,29 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
> esxVI_String *propertyNameList = NULL;
> esxVI_ObjectContent *hostSystem = NULL;
> esxVI_Boolean inMaintenanceMode = esxVI_Boolean_Undefined;
> + esxPrivate *priv = conn->privateData;
> + esxVI_ProductVersion expectedProductVersion = STRCASEEQ(conn->uri->scheme, "esx")
> + ? esxVI_ProductVersion_ESX
> + : esxVI_ProductVersion_GSX;
>
> if (vCenterIpAddress == NULL || *vCenterIpAddress != NULL) {
> ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
> return -1;
> }
>
> - if (esxUtil_ResolveHostname(hostname, ipAddress, NI_MAXHOST)< 0) {
> + if (esxUtil_ResolveHostname(conn->uri->server, ipAddress, NI_MAXHOST)< 0) {
> return -1;
> }
>
> - if (predefinedUsername != NULL) {
> - username = strdup(predefinedUsername);
> + if (conn->uri->user != NULL) {
> + username = strdup(conn->uri->user);
>
> if (username == NULL) {
> virReportOOMError();
> goto cleanup;
> }
> } else {
> - username = virAuthGetUsername(auth, "root", hostname);
> + username = virAuthGetUsername(conn, auth, "esx", "root", conn->uri->server);
>
> if (username == NULL) {
> ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
> @@ -708,7 +710,7 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
> }
> }
>
> - unescapedPassword = virAuthGetPassword(auth, username, hostname);
> + unescapedPassword = virAuthGetPassword(conn, auth, "esx", username, conn->uri->server);
>
> if (unescapedPassword == NULL) {
> ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
> @@ -722,7 +724,7 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
> }
>
> if (virAsprintf(&url, "%s://%s:%d/sdk", priv->parsedUri->transport,
> - hostname, port)< 0) {
> + conn->uri->server, conn->uri->port)< 0) {
> virReportOOMError();
> goto cleanup;
> }
> @@ -743,13 +745,13 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
> priv->host->productVersion != esxVI_ProductVersion_ESX5x) {
> ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
> _("%s is neither an ESX 3.5, 4.x nor 5.x host"),
> - hostname);
> + conn->uri->server);
> goto cleanup;
> }
> } else { /* GSX */
> if (priv->host->productVersion != esxVI_ProductVersion_GSX20) {
> ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
> - _("%s isn't a GSX 2.0 host"), hostname);
> + _("%s isn't a GSX 2.0 host"), conn->uri->server);
> goto cleanup;
> }
> }
> @@ -799,9 +801,9 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
>
>
> static int
> -esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
> - const char *hostname, int port,
> - const char *predefinedUsername,
> +esxConnectToVCenter(virConnectPtr conn,
> + virConnectAuthPtr auth,
> + const char *hostname,
> const char *hostSystemIpAddress)
> {
> int result = -1;
> @@ -810,6 +812,7 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
> char *unescapedPassword = NULL;
> char *password = NULL;
> char *url = NULL;
> + esxPrivate *priv = conn->privateData;
>
> if (hostSystemIpAddress == NULL&&
> (priv->parsedUri->path == NULL || STREQ(priv->parsedUri->path, "/"))) {
> @@ -822,15 +825,15 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
> return -1;
> }
>
> - if (predefinedUsername != NULL) {
> - username = strdup(predefinedUsername);
> + if (conn->uri->user != NULL) {
> + username = strdup(conn->uri->user);
>
> if (username == NULL) {
> virReportOOMError();
> goto cleanup;
> }
> } else {
> - username = virAuthGetUsername(auth, "administrator", hostname);
> + username = virAuthGetUsername(conn, auth, "esx", "administrator", hostname);
>
> if (username == NULL) {
> ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
> @@ -838,7 +841,7 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
> }
> }
>
> - unescapedPassword = virAuthGetPassword(auth, username, hostname);
> + unescapedPassword = virAuthGetPassword(conn, auth, "esx", username, hostname);
>
> if (unescapedPassword == NULL) {
> ESX_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
> @@ -852,7 +855,7 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
> }
>
> if (virAsprintf(&url, "%s://%s:%d/sdk", priv->parsedUri->transport,
> - hostname, port)< 0) {
> + hostname, conn->uri->port)< 0) {
> virReportOOMError();
> goto cleanup;
> }
> @@ -1046,11 +1049,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth,
> if (STRCASEEQ(conn->uri->scheme, "esx") ||
> STRCASEEQ(conn->uri->scheme, "gsx")) {
> /* Connect to host */
> - if (esxConnectToHost(priv, auth, conn->uri->server, conn->uri->port,
> - conn->uri->user,
> - STRCASEEQ(conn->uri->scheme, "esx")
> - ? esxVI_ProductVersion_ESX
> - : esxVI_ProductVersion_GSX,
> + if (esxConnectToHost(conn, auth,
> &potentialVCenterIpAddress)< 0) {
> goto cleanup;
> }
> @@ -1089,8 +1088,8 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth,
> }
> }
>
> - if (esxConnectToVCenter(priv, auth, vCenterIpAddress,
> - conn->uri->port, NULL,
> + if (esxConnectToVCenter(conn, auth,
> + vCenterIpAddress,
> priv->host->ipAddress)< 0) {
> goto cleanup;
> }
> @@ -1099,8 +1098,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth,
> priv->primary = priv->host;
> } else { /* VPX */
> /* Connect to vCenter */
> - if (esxConnectToVCenter(priv, auth, conn->uri->server, conn->uri->port,
> - conn->uri->user, NULL)< 0) {
> + if (esxConnectToVCenter(conn, auth,
> + conn->uri->server,
> + NULL)< 0) {
> goto cleanup;
> }
>
> diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
> index 0469e2e..05fce4f 100644
> --- a/src/hyperv/hyperv_driver.c
> +++ b/src/hyperv/hyperv_driver.c
> @@ -147,7 +147,7 @@ hypervOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
> goto cleanup;
> }
> } else {
> - username = virAuthGetUsername(auth, "administrator", conn->uri->server);
> + username = virAuthGetUsername(conn, auth, "hyperv", "administrator", conn->uri->server);
>
> if (username == NULL) {
> HYPERV_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
> @@ -155,7 +155,7 @@ hypervOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
> }
> }
>
> - password = virAuthGetPassword(auth, username, conn->uri->server);
> + password = virAuthGetPassword(conn, auth, "hyperv", username, conn->uri->server);
>
> if (password == NULL) {
> HYPERV_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
> diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
> index 470706d..b883b56 100644
> --- a/src/phyp/phyp_driver.c
> +++ b/src/phyp/phyp_driver.c
> @@ -1006,7 +1006,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
> goto err;
> }
>
> - username = virAuthGetUsername(auth, NULL, conn->uri->server);
> + username = virAuthGetUsername(conn, auth, "ssh", NULL, conn->uri->server);
>
> if (username == NULL) {
> PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s",
> @@ -1087,7 +1087,7 @@ keyboard_interactive:
> goto disconnect;
> }
>
> - password = virAuthGetPassword(auth, username, conn->uri->server);
> + password = virAuthGetPassword(conn, auth, "ssh", username, conn->uri->server);
>
> if (password == NULL) {
> PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s",
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index 1faaf9e..72b4b8f 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -45,6 +45,8 @@
> #include "intprops.h"
> #include "virtypedparam.h"
> #include "viruri.h"
> +#include "virauth.h"
> +#include "virauthconfig.h"
>
> #define VIR_FROM_THIS VIR_FROM_REMOTE
>
> @@ -461,6 +463,9 @@ doRemoteOpen (virConnectPtr conn,
> pkipath = strdup(var->value);
> if (!pkipath) goto out_of_memory;
> var->ignore = 1;
> + } else if (STRCASEEQ(var->name, "authfile")) {
> + /* Strip this param, used by virauth.c */
> + var->ignore = 1;
> } else {
> VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
> var->name, var->value);
> @@ -2870,27 +2875,35 @@ static int remoteAuthMakeCredentials(sasl_interact_t *interact,
> if (!cred)
> return -1;
>
> - for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++)
> - ; /* empty */
> + for (ninteract = 0, *ncred = 0 ; interact[ninteract].id != 0 ; ninteract++) {
> + if (interact[ninteract].result)
> + continue;
> + (*ncred)++;
> + }
>
> - if (VIR_ALLOC_N(*cred, ninteract)< 0)
> + if (VIR_ALLOC_N(*cred, *ncred)< 0)
> return -1;
>
> - for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
> - (*cred)[ninteract].type = remoteAuthCredSASL2Vir(interact[ninteract].id);
> - if (!(*cred)[ninteract].type) {
> + for (ninteract = 0, *ncred = 0 ; interact[ninteract].id != 0 ; ninteract++) {
> + if (interact[ninteract].result)
> + continue;
> +
> + (*cred)[*ncred].type = remoteAuthCredSASL2Vir(interact[ninteract].id);
> + if (!(*cred)[*ncred].type) {
> + *ncred = 0;
> VIR_FREE(*cred);
> return -1;
> }
> - if (interact[ninteract].challenge)
> - (*cred)[ninteract].challenge = interact[ninteract].challenge;
> - (*cred)[ninteract].prompt = interact[ninteract].prompt;
> - if (interact[ninteract].defresult)
> - (*cred)[ninteract].defresult = interact[ninteract].defresult;
> - (*cred)[ninteract].result = NULL;
> + if (interact[*ncred].challenge)
> + (*cred)[*ncred].challenge = interact[ninteract].challenge;
> + (*cred)[*ncred].prompt = interact[ninteract].prompt;
> + if (interact[*ncred].defresult)
> + (*cred)[*ncred].defresult = interact[ninteract].defresult;
> + (*cred)[*ncred].result = NULL;
> +
> + (*ncred)++;
> }
>
> - *ncred = ninteract;
> return 0;
> }
>
> @@ -2905,22 +2918,91 @@ static int remoteAuthMakeCredentials(sasl_interact_t *interact,
> static void remoteAuthFillInteract(virConnectCredentialPtr cred,
> sasl_interact_t *interact)
> {
> - int ninteract;
> - for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
> - interact[ninteract].result = cred[ninteract].result;
> - interact[ninteract].len = cred[ninteract].resultlen;
> + int ninteract, ncred;
> + for (ninteract = 0, ncred = 0 ; interact[ninteract].id != 0 ; ninteract++) {
> + if (interact[ninteract].result)
> + continue;
> + interact[ninteract].result = cred[ncred].result;
> + interact[ninteract].len = cred[ncred].resultlen;
> + ncred++;
> }
> }
>
> -
> struct remoteAuthInteractState {
> sasl_interact_t *interact;
> virConnectCredentialPtr cred;
> size_t ncred;
> + virAuthConfigPtr config;
> };
>
>
> -static void remoteAuthInteractStateClear(struct remoteAuthInteractState *state)
> +
> +static int remoteAuthFillFromConfig(virConnectPtr conn,
> + struct remoteAuthInteractState *state)
> +{
> + int ret = -1;
> + int ninteract;
> + const char *credname;
> + char *path = NULL;
> +
> + VIR_DEBUG("Trying to fill auth parameters from config file");
> +
> + if (!state->config) {
> + if (virAuthGetConfigFilePath(conn,&path)< 0)
> + goto cleanup;
> + if (path == NULL) {
> + ret = 0;
> + goto cleanup;
> + }
> +
> + if (!(state->config = virAuthConfigNew(path)))
> + goto cleanup;
> + }
> +
> + for (ninteract = 0 ; state->interact[ninteract].id != 0 ; ninteract++) {
> + const char *value = NULL;
> +
> + switch (state->interact[ninteract].id) {
> + case SASL_CB_USER:
> + credname = "username";
> + break;
> + case SASL_CB_AUTHNAME:
> + credname = "authname";
> + break;
> + case SASL_CB_PASS:
> + credname = "password";
> + break;
> + case SASL_CB_GETREALM:
> + credname = "realm";
> + break;
> + default:
> + credname = NULL;
> + break;
> + }
> +
> + if (virAuthConfigLookup(state->config,
> + "libvirt",
> + conn->uri->server,
> + credname,
> +&value)< 0)
> + goto cleanup;
> +
> + if (value) {
> + state->interact[ninteract].result = value;
> + state->interact[ninteract].len = strlen(value);
> + }
> + }
> +
> + ret = 0;
> +
> +cleanup:
> + VIR_FREE(path);
> + return ret;
> +}
> +
> +
> +static void remoteAuthInteractStateClear(struct remoteAuthInteractState *state,
> + bool final)
> {
> size_t i;
> if (!state)
> @@ -2930,15 +3012,23 @@ static void remoteAuthInteractStateClear(struct remoteAuthInteractState *state)
> VIR_FREE(state->cred[i].result);
> VIR_FREE(state->cred);
> state->ncred = 0;
> +
> + if (final)
> + virAuthConfigFree(state->config);
> }
>
>
> -static int remoteAuthInteract(struct remoteAuthInteractState *state,
> +static int remoteAuthInteract(virConnectPtr conn,
> + struct remoteAuthInteractState *state,
> virConnectAuthPtr auth)
> {
> int ret = -1;
>
> - remoteAuthInteractStateClear(state);
> + VIR_DEBUG("Starting SASL interaction");
> + remoteAuthInteractStateClear(state, false);
> +
> + if (remoteAuthFillFromConfig(conn, state)< 0)
> + goto cleanup;
>
> if (remoteAuthMakeCredentials(state->interact,&state->cred,&state->ncred)< 0) {
> remoteError(VIR_ERR_AUTH_FAILED, "%s",
> @@ -3074,7 +3164,7 @@ remoteAuthSASL (virConnectPtr conn, struct private_data *priv,
>
> /* Need to gather some credentials from the client */
> if (err == VIR_NET_SASL_INTERACT) {
> - if (remoteAuthInteract(&state, auth)< 0) {
> + if (remoteAuthInteract(conn,&state, auth)< 0) {
> VIR_FREE(iret.mechlist);
> goto cleanup;
> }
> @@ -3126,7 +3216,7 @@ remoteAuthSASL (virConnectPtr conn, struct private_data *priv,
>
> /* Need to gather some credentials from the client */
> if (err == VIR_NET_SASL_INTERACT) {
> - if (remoteAuthInteract(&state, auth)< 0) {
> + if (remoteAuthInteract(conn,&state, auth)< 0) {
> VIR_FREE(iret.mechlist);
> goto cleanup;
> }
> @@ -3192,7 +3282,7 @@ remoteAuthSASL (virConnectPtr conn, struct private_data *priv,
> cleanup:
> VIR_FREE(serverin);
>
> - remoteAuthInteractStateClear(&state);
> + remoteAuthInteractStateClear(&state, true);
> VIR_FREE(saslcb);
> virNetSASLSessionFree(sasl);
> virNetSASLContextFree(saslCtxt);
> diff --git a/src/util/virauth.c b/src/util/virauth.c
> index 150b8e7..940686f 100644
> --- a/src/util/virauth.c
> +++ b/src/util/virauth.c
> @@ -30,6 +30,7 @@
> #include "datatypes.h"
> #include "virterror_internal.h"
> #include "configmake.h"
> +#include "virauthconfig.h"
>
> #define VIR_FROM_THIS VIR_FROM_AUTH
>
> @@ -100,13 +101,68 @@ no_memory:
> }
>
>
> +static int
> +virAuthGetCredential(virConnectPtr conn,
> + const char *servicename,
> + const char *credname,
> + char **value)
> +{
> + int ret = -1;
> + char *path = NULL;
> + virAuthConfigPtr config = NULL;
> + const char *tmp;
> +
> + *value = NULL;
> +
> + if (virAuthGetConfigFilePath(conn,&path)< 0)
> + goto cleanup;
> +
> + if (path == NULL) {
> + ret = 0;
> + goto cleanup;
> + }
> +
> + if (!(config = virAuthConfigNew(path)))
> + goto cleanup;
> +
> + if (virAuthConfigLookup(config,
> + servicename,
> + conn->uri->server,
> + credname,
> +&tmp)< 0)
> + goto cleanup;
> +
> + if (tmp&&
> + !(*value = strdup(tmp))) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + ret = 0;
> +
> +cleanup:
> + virAuthConfigFree(config);
> + VIR_FREE(path);
> + return ret;
> +}
> +
> +
> char *
> -virAuthGetUsername(virConnectAuthPtr auth, const char *defaultUsername,
> +virAuthGetUsername(virConnectPtr conn,
> + virConnectAuthPtr auth,
> + const char *servicename,
> + const char *defaultUsername,
> const char *hostname)
> {
> unsigned int ncred;
> virConnectCredential cred;
> char *prompt;
> + char *ret = NULL;
> +
> + if (virAuthGetCredential(conn, servicename, "username",&ret)< 0)
> + return NULL;
> + if (ret != NULL)
> + return ret;
>
> memset(&cred, 0, sizeof (virConnectCredential));
>
> @@ -148,12 +204,21 @@ virAuthGetUsername(virConnectAuthPtr auth, const char *defaultUsername,
>
>
> char *
> -virAuthGetPassword(virConnectAuthPtr auth, const char *username,
> +virAuthGetPassword(virConnectPtr conn,
> + virConnectAuthPtr auth,
> + const char *servicename,
> + const char *username,
> const char *hostname)
> {
> unsigned int ncred;
> virConnectCredential cred;
> char *prompt;
> + char *ret = NULL;
> +
> + if (virAuthGetCredential(conn, servicename, "password",&ret)< 0)
> + return NULL;
> + if (ret != NULL)
> + return ret;
>
> memset(&cred, 0, sizeof (virConnectCredential));
>
> diff --git a/src/util/virauth.h b/src/util/virauth.h
> index 7f43bee..1b315c7 100644
> --- a/src/util/virauth.h
> +++ b/src/util/virauth.h
> @@ -27,9 +27,15 @@
> int virAuthGetConfigFilePath(virConnectPtr conn,
> char **path);
>
> -char *virAuthGetUsername(virConnectAuthPtr auth, const char *defaultUsername,
> +char *virAuthGetUsername(virConnectPtr conn,
> + virConnectAuthPtr auth,
> + const char *servicename,
> + const char *defaultUsername,
> const char *hostname);
> -char *virAuthGetPassword(virConnectAuthPtr auth, const char *username,
> +char *virAuthGetPassword(virConnectPtr conn,
> + virConnectAuthPtr auth,
> + const char *servicename,
> + const char *username,
> const char *hostname);
>
> #endif /* __VIR_AUTH_H__ */
> diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
> index 3f88c91..2967f7c 100644
> --- a/src/xenapi/xenapi_driver.c
> +++ b/src/xenapi/xenapi_driver.c
> @@ -138,7 +138,7 @@ xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth,
> goto error;
> }
> } else {
> - username = virAuthGetUsername(auth, NULL, conn->uri->server);
> + username = virAuthGetUsername(conn, auth, "xen", NULL, conn->uri->server);
>
> if (username == NULL) {
> xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED,
> @@ -147,7 +147,7 @@ xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth,
> }
> }
>
> - password = virAuthGetPassword(auth, username, conn->uri->server);
> + password = virAuthGetPassword(conn, auth, "xen", username, conn->uri->server);
>
> if (password == NULL) {
> xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED,
Looks fine to me, ACK.
More information about the libvir-list
mailing list