From: VMware, Inc <> Date: Wed, 26 Dec 2012 21:18:30 +0000 (-0800) Subject: auth: fix crashed in Posix backend X-Git-Tag: 2012.12.26-958366~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=82ec43213b359aea2bdfca7fd9167f4ce4f18d74;p=thirdparty%2Fopen-vm-tools.git auth: fix crashed in Posix backend 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 --- diff --git a/open-vm-tools/lib/auth/authPosix.c b/open-vm-tools/lib/auth/authPosix.c index a9297a6e6..beec4eeea 100644 --- a/open-vm-tools/lib/auth/authPosix.c +++ b/open-vm-tools/lib/auth/authPosix.c @@ -53,6 +53,12 @@ #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); } - diff --git a/open-vm-tools/lib/include/auth.h b/open-vm-tools/lib/include/auth.h index 16a747cf7..f1e449843 100644 --- a/open-vm-tools/lib/include/auth.h +++ b/open-vm-tools/lib/include/auth.h @@ -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);