VirtualBox

Changeset 79007 in vbox for trunk/src/VBox/Runtime/r3/posix


Ignore:
Timestamp:
Jun 5, 2019 5:24:03 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131152
Message:

IPRT/process-creation-posix.cpp: Use reentrant functions for accessing /etc/passwd and /etc/shadow on linux. Tried to combine the code for all non-darwin platforms. ticketref:18682

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/process-creation-posix.cpp

    r76553 r79007  
    265265    return VERR_AUTHENTICATION_FAILURE;
    266266
    267 #elif defined(RT_OS_LINUX)
    268     struct passwd *pw;
    269 
    270     pw = getpwnam(pszUser);
    271     if (!pw)
     267#else
     268    /*
     269     * Lookup the user in /etc/passwd first.
     270     *
     271     * Note! On FreeBSD and OS/2 the root user will open /etc/shadow here, so
     272     *       the getspnam_r step is not necessary.
     273     */
     274    struct passwd  Pwd;
     275    char           szBuf[_4K];
     276    struct passwd *pPwd = NULL;
     277    if (getpwnam_r(pszUser, &Pwd, szBuf, sizeof(szBuf), &pPwd) != 0)
    272278        return VERR_AUTHENTICATION_FAILURE;
    273 
    274     if (!pszPasswd)
    275         pszPasswd = "";
    276 
    277     struct spwd *spwd;
    278     /* works only if /etc/shadow is accessible */
    279     spwd = getspnam(pszUser);
    280     if (spwd)
    281         pw->pw_passwd = spwd->sp_pwdp;
    282 
    283     /* Default fCorrect=true if no password specified. In that case, pw->pw_passwd
    284      * must be NULL (no password set for this user). Fail if a password is specified
    285      * but the user does not have one assigned. */
    286     int fCorrect = !pszPasswd || !*pszPasswd;
    287     if (pw->pw_passwd && *pw->pw_passwd)
    288     {
    289         struct crypt_data *data = (struct crypt_data*)RTMemTmpAllocZ(sizeof(*data));
    290         /* be reentrant */
    291         char *pszEncPasswd = crypt_r(pszPasswd, pw->pw_passwd, data);
    292         fCorrect = pszEncPasswd && !strcmp(pszEncPasswd, pw->pw_passwd);
    293         RTMemTmpFree(data);
    294     }
    295     if (!fCorrect)
     279    if (pPwd == NULL)
    296280        return VERR_AUTHENTICATION_FAILURE;
    297281
    298     *pGid = pw->pw_gid;
    299     *pUid = pw->pw_uid;
    300     return VINF_SUCCESS;
    301 
    302 #elif defined(RT_OS_SOLARIS)
    303     struct passwd *ppw, pw;
    304     char szBuf[1024];
    305 
    306     if (getpwnam_r(pszUser, &pw, szBuf, sizeof(szBuf), &ppw) != 0 || ppw == NULL)
    307         return VERR_AUTHENTICATION_FAILURE;
    308 
    309     if (!pszPasswd)
    310         pszPasswd = "";
    311 
    312     struct spwd spwd;
    313     char szPwdBuf[1024];
    314     /* works only if /etc/shadow is accessible */
    315     if (getspnam_r(pszUser, &spwd, szPwdBuf, sizeof(szPwdBuf)) != NULL)
    316         ppw->pw_passwd = spwd.sp_pwdp;
    317 
    318     char *pszEncPasswd = crypt(pszPasswd, ppw->pw_passwd);
    319     if (strcmp(pszEncPasswd, ppw->pw_passwd))
    320         return VERR_AUTHENTICATION_FAILURE;
    321 
    322     *pGid = ppw->pw_gid;
    323     *pUid = ppw->pw_uid;
    324     return VINF_SUCCESS;
    325 
    326 #else
    327     NOREF(pszUser); NOREF(pszPasswd); NOREF(pGid); NOREF(pUid);
    328     return VERR_AUTHENTICATION_FAILURE;
     282# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
     283    /*
     284     * Ditto for /etc/shadow and replace pw_passwd from above if we can access it:
     285     */
     286    struct spwd  ShwPwd;
     287    char         szBuf2[_4K];
     288#  if defined(RT_OS_LINUX)
     289    struct spwd *pShwPwd = NULL;
     290    if (getspnam_r(pszUser, &ShwPwd, szBuf2, sizeof(szBuf2), &pShwPwd) != 0)
     291        pShwPwd = NULL;
     292#  else
     293    struct spwd *pShwPwd = getspnam_r(pszUser, &ShwPwd, szBuf2, sizeof(szBuf2));
     294#  endif
     295    if (pShwPwd != NULL)
     296        pPwd->pw_passwd = pShwPwd->sp_pwdp;
     297# endif
     298
     299    /*
     300     * Encrypt the passed in password and see if it matches.
     301     */
     302# if !defined(RT_OS_LINUX)
     303    int rc;
     304# else
     305    /* Default fCorrect=true if no password specified. In that case, pPwd->pw_passwd
     306       must be NULL (no password set for this user). Fail if a password is specified
     307       but the user does not have one assigned. */
     308    int rc = !pszPasswd || !*pszPasswd ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
     309    if (pPwd->pw_passwd && *pPwd->pw_passwd)
     310# endif
     311    {
     312# if defined(RT_OS_LINUX) || defined(RT_OS_OS2)
     313        struct crypt_data CryptData;
     314        RT_ZERO(CryptData);
     315        char *pszEncPasswd = crypt_r(pszPasswd, pPwd->pw_passwd, &CryptData);
     316        rc = pszEncPasswd && !strcmp(pszEncPasswd, pPwd->pw_passwd) ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
     317        RTMemWipeThoroughly(&CryptData, sizeof(CryptData), 3);
     318# else
     319        char *pszEncPasswd = crypt(pszPasswd, ppw->pw_passwd);
     320        rc = strcmp(pszEncPasswd, ppw->pw_passwd) == 0 ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
     321# endif
     322    }
     323
     324    /*
     325     * Return GID and UID on success.  Always wipe stack buffers.
     326     */
     327    if (RT_SUCCESS(rc))
     328    {
     329        *pGid = pPwd->pw_gid;
     330        *pUid = pPwd->pw_uid;
     331    }
     332    RTMemWipeThoroughly(szBuf, sizeof(szBuf), 3);
     333# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
     334    RTMemWipeThoroughly(szBuf2, sizeof(szBuf2), 3);
     335# endif
     336    return rc;
    329337#endif
    330338}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette