]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
auth: fix crashed in Posix backend
authorVMware, Inc <>
Wed, 26 Dec 2012 21:18:30 +0000 (13:18 -0800)
committerDmitry Torokhov <dtor@vmware.com>
Thu, 27 Dec 2012 19:01:11 +0000 (11:01 -0800)
Now that Auth_CloseToken is no longer a no-op on Posix, it crashes if
called with the results of Posix_Getpwnam and Posix_Getpwuid, which
return static buffers. Create and use wrappers.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/auth/authPosix.c
open-vm-tools/lib/include/auth.h

index a9297a6e656ad5fa581b454f3a3a0f031e80bade..beec4eeeac12c76482594e41b6b66865d43aff00 100644 (file)
 #define LOGLEVEL_MODULE auth
 #include "loglevel_user.h"
 
+typedef struct {
+   struct passwd  pwd;      /* must be first member */
+   size_t         bufSize;
+   uint8          buf[];
+} AuthTokenInternal;
+
 #ifdef USE_PAM
 #if defined(sun)
 #define CURRENT_PAM_LIBRARY    "libpam.so.1"
@@ -242,6 +248,120 @@ static struct pam_conv PAM_conversation = {
 #endif /* USE_PAM */
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * AuthAllocateToken --
+ *
+ *      Allocates an AuthTokenInternal structure, plus helper buffer
+ *      large enough for the Posix_Get*_r calls.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Results:
+ *      An AuthTokenInternal pointer. Free with Auth_CloseToken.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static AuthTokenInternal *
+AuthAllocateToken(void)
+{
+   AuthTokenInternal *ati;
+   size_t bufSize;
+
+   /*
+    * We need to get the maximum size buffer needed by getpwuid_r from
+    * sysconf. Multiply by 4 to compensate for the conversion to UTF-8
+    * by the Posix_Get*_r() wrappers.
+    */
+
+   bufSize = (size_t) sysconf(_SC_GETPW_R_SIZE_MAX) * 4;
+
+   ati = Util_SafeMalloc(sizeof *ati + bufSize);
+   ati->bufSize = bufSize;
+
+   return ati;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Auth_GetPwnam --
+ *
+ *      Wrapper aroung Posix_Getpwnam_r.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Results:
+ *      An AuthToken. Free with Auth_CloseToken.
+ *
+ *----------------------------------------------------------------------
+ */
+
+AuthToken
+Auth_GetPwnam(const char *user)  // IN
+{
+   AuthTokenInternal *ati;
+   int res;
+   struct passwd *ppwd;
+
+   ASSERT(user);
+
+   ati = AuthAllocateToken();
+   res = Posix_Getpwnam_r(user, &ati->pwd, ati->buf, ati->bufSize, &ppwd);
+
+   if ((0 != res) || (ppwd == NULL)) {
+      Auth_CloseToken((AuthToken) ati);
+      return NULL;
+   }
+
+   ASSERT(ppwd == &ati->pwd);
+
+   return (AuthToken) ati;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Auth_AuthenticateSelf --
+ *
+ *      Authenticate as the current user.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Results:
+ *      An AuthToken. Free with Auth_CloseToken.
+ *
+ *----------------------------------------------------------------------
+ */
+
+AuthToken
+Auth_AuthenticateSelf(void)  // IN
+{
+   AuthTokenInternal *ati;
+   int res;
+   struct passwd *ppwd;
+
+   ati = AuthAllocateToken();
+   res = Posix_Getpwuid_r(getuid(), &ati->pwd, ati->buf, ati->bufSize, &ppwd);
+
+   if ((0 != res) || (ppwd == NULL)) {
+      Auth_CloseToken((AuthToken) ati);
+      return NULL;
+   }
+
+   ASSERT(ppwd == &ati->pwd);
+
+   return (AuthToken) ati;
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -264,25 +384,26 @@ AuthToken
 Auth_AuthenticateUser(const char *user,  // IN:
                       const char *pass)  // IN:
 {
-   struct passwd *pwd;
-
 #ifdef USE_PAM
    pam_handle_t *pamh;
    int pam_error;
 #endif
 
+   Bool success = FALSE;
+   AuthTokenInternal *ati = NULL;
+
    if (!CodeSet_Validate(user, strlen(user), "UTF-8")) {
       Log("User not in UTF-8\n");
-      return NULL;
+      goto exit;
    }
    if (!CodeSet_Validate(pass, strlen(pass), "UTF-8")) {
-      Log("Password not in UTF-8\n");                                                     
-      return NULL;
+      Log("Password not in UTF-8\n");
+      goto exit;
    }
 
 #ifdef USE_PAM
    if (!AuthLoadPAM()) {
-      return NULL;
+      goto exit;
    }
 
    /*
@@ -295,7 +416,7 @@ Auth_AuthenticateUser(const char *user,  // IN:
                             __FUNCTION__, __LINE__, \
                             dlpam_strerror(pamh, pam_error), pam_error); \
                   dlpam_end(pamh, pam_error); \
-                  return NULL; \
+                  goto exit; \
                  }
    PAM_username = user;
    PAM_password = pass;
@@ -309,7 +430,7 @@ Auth_AuthenticateUser(const char *user,  // IN:
 #endif
    if (pam_error != PAM_SUCCESS) {
       Log("Failed to start PAM (error = %d).\n", pam_error);
-      return NULL;
+      goto exit;
    }
 
    pam_error = dlpam_authenticate(pamh, 0);
@@ -321,47 +442,50 @@ Auth_AuthenticateUser(const char *user,  // IN:
    dlpam_end(pamh, PAM_SUCCESS);
 
    /* If this point is reached, the user has been authenticated. */
-   setpwent();
-   pwd = Posix_Getpwnam(user);
-   endpwent();
-
+   ati = (AuthTokenInternal *) Auth_GetPwnam(user);
 #else /* !USE_PAM */
 
    /* All of the following issues are dealt with in the PAM configuration
       file, so put all authentication/priviledge checks before the
       corresponding #endif below. */
-   
-   setpwent(); //XXX can kill?
-   pwd = Posix_Getpwnam(user);
-   endpwent(); //XXX can kill?
 
-   if (!pwd) {
-      // No such user
-      return NULL;
+   ati = (AuthTokenInternal *) Auth_GetPwnam(user);
+
+   if (ati == NULL) {
+      goto exit;
    }
 
-   if (*pwd->pw_passwd != '\0') {
-      char *namep = (char *) crypt(pass, pwd->pw_passwd);
+   if (*ati->pwd.pw_passwd != '\0') {
+      char *namep = (char *) crypt(pass, ati->pwd.pw_passwd);
 
-      if (strcmp(namep, pwd->pw_passwd) != 0) {
+      if (strcmp(namep, ati->pwd.pw_passwd) != 0) {
          // Incorrect password
-         return NULL;
+         goto exit;
       }
 
       // Clear out crypt()'s internal state, too.
-      crypt("glurp", pwd->pw_passwd);
+      crypt("glurp", ati->pwd.pw_passwd);
    }
 #endif /* !USE_PAM */
-   
-   return pwd;
+
+   success = TRUE;
+
+  exit:
+   if (success) {
+      return (AuthToken) ati;
+   } else {
+      Auth_CloseToken((AuthToken) ati);
+      return NULL;
+   }
 }
 
+
 /*
  *----------------------------------------------------------------------
  *
  * Auth_CloseToken --
  *
- *      Do nothing.
+ *      Free the token allocated in Auth_AuthenticateUser.
  *
  * Side effects:
  *      None
@@ -373,7 +497,7 @@ Auth_AuthenticateUser(const char *user,  // IN:
  */
 
 void
-Auth_CloseToken(AuthToken token)  // IN:
+Auth_CloseToken(AuthToken token)  // IN (OPT):
 {
+   free((void *) token);
 }
-
index 16a747cf749a68fecc4d66a6c6a009234e145df8..f1e449843071f1fe474873957207ec9420371230 100644 (file)
@@ -59,6 +59,11 @@ BOOL Auth_DeleteAccountInformationStoredForVMs();
 uint32 Auth_RetrieveAccountInformationForVM(const char *filename, uint32 *attributes,
                                            char **username, char **password);
 
+#else
+
+AuthToken Auth_GetPwnam(const char *user);
+AuthToken Auth_AuthenticateSelf(void);
+
 #endif
 
 AuthToken Auth_AuthenticateUser(ConstUnicode user, ConstUnicode pass);