On 2012年03月21日 01:33, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berra...@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.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to