VirtualBox

Changeset 92657 in vbox


Ignore:
Timestamp:
Dec 1, 2021 12:57:03 AM (3 years ago)
Author:
vboxsync
Message:

IPRT/RTProcCreateEx/posix: Try use PAM on linux for authentication so we can pick up the environment variables it sets up. Ubuntu (21.04) uses pdm_env.so to load the locale config into the environment, so without this we'll probably end up using the C locale in child processes. bugref:10153

File:
1 edited

Legend:

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

    r92620 r92657  
    8080#endif
    8181
    82 #if !defined(IPRT_USE_PAM) && ( defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD) )
     82#if !defined(IPRT_USE_PAM) \
     83 && ( defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD) )
    8384# define IPRT_USE_PAM
    8485#endif
     
    8788#  include <mach-o/dyld.h>
    8889#  define IPRT_LIBPAM_FILE      "libpam.dylib"
    89 #  define IPRT_PAM_SERVICE_NAME "login"     /** @todo we've been abusing 'login' here, probably not needed? */
    9090# else
    9191#  define IPRT_LIBPAM_FILE      "libpam.so"
    92 #  define IPRT_PAM_SERVICE_NAME "iprt-as-user"
    9392# endif
    9493# include <security/pam_appl.h>
     
    214213    return PAM_SUCCESS;
    215214}
     215
     216
     217/**
     218 * Common PAM driver for rtCheckCredentials and the case where pszAsUser is NULL
     219 * but RTPROC_FLAGS_PROFILE is set.
     220 *
     221 * @returns IPRT status code.
     222 * @param   pszPamService   The PAM service to use for the run.
     223 * @param   pszUser         The user.
     224 * @param   pszPassword     The password.
     225 * @param   ppapszEnv       Where to return PAM environment variables, NULL is
     226 *                          fine if no variables to return. Call
     227 *                          rtProcPosixFreePamEnv to free.  Optional, so NULL
     228 *                          can be passed in.
     229 * @param   pfMayFallBack   Where to return whether a fallback to crypt is
     230 *                          acceptable or if the failure result is due to
     231 *                          authentication failing.  Optional.
     232 */
     233static int rtProcPosixAuthenticateUsingPam(const char *pszPamService, const char *pszUser, const char *pszPassword,
     234                                           char ***ppapszEnv, bool *pfMayFallBack)
     235{
     236    if (pfMayFallBack)
     237        *pfMayFallBack = true;
     238
     239    /*
     240     * Use PAM for the authentication.
     241     * Note! libpam.2.dylib was introduced with 10.6.x (OpenPAM).
     242     */
     243    void *hModPam = dlopen(IPRT_LIBPAM_FILE, RTLD_LAZY | RTLD_GLOBAL);
     244    if (hModPam)
     245    {
     246        int     (*pfnPamStart)(const char *, const char *, struct pam_conv *, pam_handle_t **);
     247        int     (*pfnPamAuthenticate)(pam_handle_t *, int);
     248        int     (*pfnPamAcctMgmt)(pam_handle_t *, int);
     249        int     (*pfnPamSetItem)(pam_handle_t *, int, const void *);
     250        int     (*pfnPamSetCred)(pam_handle_t *, int);
     251        char ** (*pfnPamGetEnvList)(pam_handle_t *);
     252        int     (*pfnPamOpenSession)(pam_handle_t *, int);
     253        int     (*pfnPamCloseSession)(pam_handle_t *, int);
     254        int     (*pfnPamEnd)(pam_handle_t *, int);
     255        *(void **)&pfnPamStart        = dlsym(hModPam, "pam_start");
     256        *(void **)&pfnPamAuthenticate = dlsym(hModPam, "pam_authenticate");
     257        *(void **)&pfnPamAcctMgmt     = dlsym(hModPam, "pam_acct_mgmt");
     258        *(void **)&pfnPamSetItem      = dlsym(hModPam, "pam_set_item");
     259        *(void **)&pfnPamSetCred      = dlsym(hModPam, "pam_setcred");
     260        *(void **)&pfnPamGetEnvList   = dlsym(hModPam, "pam_getenvlist");
     261        *(void **)&pfnPamOpenSession  = dlsym(hModPam, "pam_open_session");
     262        *(void **)&pfnPamCloseSession = dlsym(hModPam, "pam_close_session");
     263        *(void **)&pfnPamEnd          = dlsym(hModPam, "pam_end");
     264        ASMCompilerBarrier();
     265        if (   pfnPamStart
     266            && pfnPamAuthenticate
     267            && pfnPamAcctMgmt
     268            && pfnPamSetItem
     269            && pfnPamEnd)
     270        {
     271# define pam_start           pfnPamStart
     272# define pam_authenticate    pfnPamAuthenticate
     273# define pam_acct_mgmt       pfnPamAcctMgmt
     274# define pam_set_item        pfnPamSetItem
     275# define pam_setcred         pfnPamSetCred
     276# define pam_getenvlist      pfnPamGetEnvList
     277# define pam_open_session    pfnPamOpenSession
     278# define pam_close_session   pfnPamCloseSession
     279# define pam_end             pfnPamEnd
     280
     281            /* Do the PAM stuff. */
     282            pam_handle_t   *hPam        = NULL;
     283            RTPROCPAMARGS   PamConvArgs = { pszUser, pszPassword };
     284            struct pam_conv PamConversation;
     285            RT_ZERO(PamConversation);
     286            PamConversation.appdata_ptr = &PamConvArgs;
     287            PamConversation.conv        = rtPamConv;
     288            int rc = pam_start(pszPamService, pszUser, &PamConversation, &hPam);
     289            if (rc == PAM_SUCCESS)
     290            {
     291                rc = pam_set_item(hPam, PAM_RUSER, pszUser);
     292                if (rc == PAM_SUCCESS)
     293                {
     294                    if (pfMayFallBack)
     295                        *pfMayFallBack = false;
     296                    rc = pam_authenticate(hPam, 0);
     297                    if (rc == PAM_SUCCESS)
     298                    {
     299                        rc = pam_acct_mgmt(hPam, 0);
     300                        if (   rc == PAM_SUCCESS
     301                            || rc == PAM_AUTHINFO_UNAVAIL /*??*/)
     302                        {
     303                            if (   ppapszEnv
     304                                && pfnPamGetEnvList
     305                                && pfnPamSetCred)
     306                            {
     307                                /* pam_env.so creates the environment when pam_setcred is called. */
     308                                rc = pam_setcred(hPam, PAM_ESTABLISH_CRED | PAM_SILENT);
     309                                /** @todo check pam_setcred status code. */
     310                                *ppapszEnv = pam_getenvlist(hPam);
     311                                pam_setcred(hPam, PAM_DELETE_CRED);
     312                            }
     313
     314                            pam_end(hPam, PAM_SUCCESS);
     315                            dlclose(hModPam);
     316                            return VINF_SUCCESS;
     317                        }
     318                        LogFunc(("pam_acct_mgmt -> %d\n", rc));
     319                    }
     320                    else
     321                        LogFunc(("pam_authenticate -> %d\n", rc));
     322                }
     323                else
     324                    LogFunc(("pam_set_item/PAM_RUSER -> %d\n", rc));
     325                pam_end(hPam, rc);
     326            }
     327            else
     328                LogFunc(("pam_start -> %d\n", rc));
     329        }
     330        else
     331            LogFunc(("failed to resolve symbols: %p %p %p %p %p\n",
     332                     pfnPamStart, pfnPamAuthenticate, pfnPamAcctMgmt, pfnPamSetItem, pfnPamEnd));
     333        dlclose(hModPam);
     334    }
     335    else
     336        LogFunc(("Loading " IPRT_LIBPAM_FILE " failed\n"));
     337    return VERR_AUTHENTICATION_FAILURE;
     338}
     339
     340
     341/**
     342 * Checks if the given service file is present in any of the pam.d directories.
     343 */
     344static bool rtProcPosixPamServiceExists(const char *pszService)
     345{
     346    char szPath[256];
     347
     348    /* PAM_CONFIG_D: */
     349    int rc = RTPathJoin(szPath, sizeof(szPath), "/etc/pam.d/", pszService); AssertRC(rc);
     350    if (RTFileExists(szPath))
     351        return true;
     352
     353    /* PAM_CONFIG_DIST_D: */
     354    rc = RTPathJoin(szPath, sizeof(szPath), "/usr/lib/pam.d/", pszService); AssertRC(rc);
     355    if (RTFileExists(szPath))
     356        return true;
     357
     358    /* No support for PAM_CONFIG_DIST2_D. */
     359    return false;
     360}
     361
    216362#endif /* IPRT_USE_PAM */
    217363
    218364
    219 #if defined(IPRT_WITH_DYNAMIC_CRYPT_R) && !defined(IPRT_USE_PAM)
     365#if defined(IPRT_WITH_DYNAMIC_CRYPT_R)
    220366/** Pointer to crypt_r(). */
    221367typedef char *(*PFNCRYPTR)(const char *, const char *, struct crypt_data *);
     
    250396
    251397
     398/** Free the environment list returned by rtCheckCredentials. */
     399static void rtProcPosixFreePamEnv(char **papszEnv)
     400{
     401    if (papszEnv)
     402    {
     403        for (size_t i = 0; papszEnv[i] != NULL; i++)
     404            free(papszEnv[i]);
     405        free(papszEnv);
     406    }
     407}
     408
     409
    252410/**
    253411 * Check the credentials and return the gid/uid of user.
    254412 *
    255  * @param    pszUser     username
    256  * @param    pszPasswd   password
    257  * @param    gid         where to store the GID of the user
    258  * @param    uid         where to store the UID of the user
     413 * @param    pszUser    The username.
     414 * @param    pszPasswd  The password to authenticate with.
     415 * @param    gid        Where to store the GID of the user.
     416 * @param    uid        Where to store the UID of the user.
     417 * @param    ppapszEnv  Where to return PAM environment variables, NULL is fine
     418 *                      if no variables to return. Call rtProcPosixFreePamEnv to
     419 *                      free. Optional, so NULL can be passed in.
    259420 * @returns IPRT status code
    260421 */
    261 static int rtCheckCredentials(const char *pszUser, const char *pszPasswd, gid_t *pGid, uid_t *pUid)
     422static int rtCheckCredentials(const char *pszUser, const char *pszPasswd, gid_t *pGid, uid_t *pUid, char ***ppapszEnv)
    262423{
    263 #ifdef IPRT_USE_PAM
    264     RTLogPrintf("rtCheckCredentials\n");
     424    Log(("rtCheckCredentials: pszUser=%s\n", pszUser));
     425    int rc;
     426
     427    if (ppapszEnv)
     428        *ppapszEnv = NULL;
    265429
    266430    /*
    267431     * Resolve user to UID and GID.
    268432     */
    269     char            szBuf[_4K];
     433    char            achBuf[_4K];
    270434    struct passwd   Pw;
    271435    struct passwd  *pPw;
    272     if (getpwnam_r(pszUser, &Pw, szBuf, sizeof(szBuf), &pPw) != 0)
     436    if (getpwnam_r(pszUser, &Pw, achBuf, sizeof(achBuf), &pPw) != 0)
    273437        return VERR_AUTHENTICATION_FAILURE;
    274438    if (!pPw)
     
    278442    *pGid = pPw->pw_gid;
    279443
    280     /*
    281      * Use PAM for the authentication.
    282      * Note! libpam.2.dylib was introduced with 10.6.x (OpenPAM).
    283      */
    284     void *hModPam = dlopen(IPRT_LIBPAM_FILE, RTLD_LAZY | RTLD_GLOBAL);
    285     if (hModPam)
    286     {
    287         int (*pfnPamStart)(const char *, const char *, struct pam_conv *, pam_handle_t **);
    288         int (*pfnPamAuthenticate)(pam_handle_t *, int);
    289         int (*pfnPamAcctMgmt)(pam_handle_t *, int);
    290         int (*pfnPamSetItem)(pam_handle_t *, int, const void *);
    291         int (*pfnPamEnd)(pam_handle_t *, int);
    292         *(void **)&pfnPamStart        = dlsym(hModPam, "pam_start");
    293         *(void **)&pfnPamAuthenticate = dlsym(hModPam, "pam_authenticate");
    294         *(void **)&pfnPamAcctMgmt     = dlsym(hModPam, "pam_acct_mgmt");
    295         *(void **)&pfnPamSetItem      = dlsym(hModPam, "pam_set_item");
    296         *(void **)&pfnPamEnd          = dlsym(hModPam, "pam_end");
    297         ASMCompilerBarrier();
    298         if (   pfnPamStart
    299             && pfnPamAuthenticate
    300             && pfnPamAcctMgmt
    301             && pfnPamSetItem
    302             && pfnPamEnd)
    303         {
    304 # define pam_start           pfnPamStart
    305 # define pam_authenticate    pfnPamAuthenticate
    306 # define pam_acct_mgmt       pfnPamAcctMgmt
    307 # define pam_set_item        pfnPamSetItem
    308 # define pam_end             pfnPamEnd
    309 
    310             /* Do the PAM stuff. */
    311             pam_handle_t   *hPam        = NULL;
    312             RTPROCPAMARGS   PamConvArgs = { pszUser, pszPasswd };
    313             struct pam_conv PamConversation;
    314             RT_ZERO(PamConversation);
    315             PamConversation.appdata_ptr = &PamConvArgs;
    316             PamConversation.conv        = rtPamConv;
    317             int rc = pam_start(IPRT_PAM_SERVICE_NAME, pszUser, &PamConversation, &hPam);
    318             if (rc == PAM_SUCCESS)
    319             {
    320                 rc = pam_set_item(hPam, PAM_RUSER, pszUser);
    321                 if (rc == PAM_SUCCESS)
    322                     rc = pam_authenticate(hPam, 0);
    323                 if (rc == PAM_SUCCESS)
    324                 {
    325                     rc = pam_acct_mgmt(hPam, 0);
    326                     if (   rc == PAM_SUCCESS
    327                         || rc == PAM_AUTHINFO_UNAVAIL /*??*/)
    328                     {
    329                         pam_end(hPam, PAM_SUCCESS);
    330                         dlclose(hModPam);
    331                         return VINF_SUCCESS;
    332                     }
    333                     Log(("rtCheckCredentials: pam_acct_mgmt -> %d\n", rc));
    334                 }
    335                 else
    336                     Log(("rtCheckCredentials: pam_authenticate -> %d\n", rc));
    337                 pam_end(hPam, rc);
    338             }
    339             else
    340                 Log(("rtCheckCredentials: pam_start -> %d\n", rc));
    341         }
    342         else
    343             Log(("rtCheckCredentials: failed to resolve symbols: %p %p %p %p %p\n",
    344                  pfnPamStart, pfnPamAuthenticate, pfnPamAcctMgmt, pfnPamSetItem, pfnPamEnd));
    345         dlclose(hModPam);
    346     }
    347     else
    348         Log(("rtCheckCredentials: Loading " IPRT_LIBPAM_FILE " failed\n"));
    349     return VERR_AUTHENTICATION_FAILURE;
    350 
    351 #else
    352     /*
    353      * Lookup the user in /etc/passwd first.
     444#ifdef IPRT_USE_PAM
     445    /*
     446     * Try authenticate using PAM, and falling back on crypto if allowed.
     447     */
     448    const char *pszService = "iprt-as-user";
     449    if (!rtProcPosixPamServiceExists("iprt-as-user"))
     450# ifdef IPRT_PAM_NATIVE_SERVICE_NAME_AS_USER
     451        pszService = IPRT_PAM_NATIVE_SERVICE_NAME_AS_USER;
     452# else
     453        pszService = "login";
     454# endif
     455    bool fMayFallBack = false;
     456    rc = rtProcPosixAuthenticateUsingPam(pszService, pszUser, pszPasswd, ppapszEnv, &fMayFallBack);
     457    if (RT_SUCCESS(rc) || !fMayFallBack)
     458    {
     459        RTMemWipeThoroughly(achBuf, sizeof(achBuf), 3);
     460        return rc;
     461    }
     462#endif
     463
     464#if !defined(IPRT_USE_PAM) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_OS2)
     465# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
     466    /*
     467     * Ditto for /etc/shadow and replace pw_passwd from above if we can access it:
    354468     *
    355      * Note! On FreeBSD and OS/2 the root user will open /etc/shadow here, so
    356      *       the getspnam_r step is not necessary.
    357      */
    358     struct passwd  Pwd;
    359     char           szBuf[_4K];
    360     struct passwd *pPwd = NULL;
    361     if (getpwnam_r(pszUser, &Pwd, szBuf, sizeof(szBuf), &pPwd) != 0)
    362         return VERR_AUTHENTICATION_FAILURE;
    363     if (pPwd == NULL)
    364         return VERR_AUTHENTICATION_FAILURE;
    365 
    366 # if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
    367     /*
    368      * Ditto for /etc/shadow and replace pw_passwd from above if we can access it:
     469     * Note! On FreeBSD and OS/2 the root user will open /etc/shadow above, so
     470     *       this getspnam_r step is not necessary.
    369471     */
    370472    struct spwd  ShwPwd;
    371     char         szBuf2[_4K];
     473    char         achBuf2[_4K];
    372474#  if defined(RT_OS_LINUX)
    373475    struct spwd *pShwPwd = NULL;
    374     if (getspnam_r(pszUser, &ShwPwd, szBuf2, sizeof(szBuf2), &pShwPwd) != 0)
     476    if (getspnam_r(pszUser, &ShwPwd, achBuf2, sizeof(achBuf2), &pShwPwd) != 0)
    375477        pShwPwd = NULL;
    376478#  else
    377     struct spwd *pShwPwd = getspnam_r(pszUser, &ShwPwd, szBuf2, sizeof(szBuf2));
     479    struct spwd *pShwPwd = getspnam_r(pszUser, &ShwPwd, achBuf2, sizeof(achBuf2));
    378480#  endif
    379481    if (pShwPwd != NULL)
    380         pPwd->pw_passwd = pShwPwd->sp_pwdp;
     482        pPw->pw_passwd = pShwPwd->sp_pwdp;
    381483# endif
    382484
     
    384486     * Encrypt the passed in password and see if it matches.
    385487     */
    386 # if !defined(RT_OS_LINUX)
    387     int rc;
    388 # else
    389     /* Default fCorrect=true if no password specified. In that case, pPwd->pw_passwd
     488# if defined(RT_OS_LINUX)
     489    /* Default fCorrect=true if no password specified. In that case, pPw->pw_passwd
    390490       must be NULL (no password set for this user). Fail if a password is specified
    391491       but the user does not have one assigned. */
    392     int rc = !pszPasswd || !*pszPasswd ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
    393     if (pPwd->pw_passwd && *pPwd->pw_passwd)
     492    rc = !pszPasswd || !*pszPasswd ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
     493    if (pPw->pw_passwd && *pPw->pw_passwd)
    394494# endif
    395495    {
     
    404504        {
    405505#  ifdef IPRT_WITH_DYNAMIC_CRYPT_R
    406             char *pszEncPasswd = rtProcDynamicCryptR(pszPasswd, pPwd->pw_passwd, pCryptData);
     506            char *pszEncPasswd = rtProcDynamicCryptR(pszPasswd, pPw->pw_passwd, pCryptData);
    407507#  else
    408             char *pszEncPasswd = crypt_r(pszPasswd, pPwd->pw_passwd, pCryptData);
     508            char *pszEncPasswd = crypt_r(pszPasswd, pPw->pw_passwd, pCryptData);
    409509#  endif
    410             rc = pszEncPasswd && !strcmp(pszEncPasswd, pPwd->pw_passwd) ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
     510            rc = pszEncPasswd && !strcmp(pszEncPasswd, pPw->pw_passwd) ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
    411511            RTMemWipeThoroughly(pCryptData, cbCryptData, 3);
    412512            RTMemTmpFree(pCryptData);
     
    415515            rc = VERR_NO_TMP_MEMORY;
    416516# else
    417         char *pszEncPasswd = crypt(pszPasswd, pPwd->pw_passwd);
    418         rc = strcmp(pszEncPasswd, pPwd->pw_passwd) == 0 ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
     517        char *pszEncPasswd = crypt(pszPasswd, pPw->pw_passwd);
     518        rc = strcmp(pszEncPasswd, pPw->pw_passwd) == 0 ? VINF_SUCCESS : VERR_AUTHENTICATION_FAILURE;
    419519# endif
    420520    }
     
    425525    if (RT_SUCCESS(rc))
    426526    {
    427         *pGid = pPwd->pw_gid;
    428         *pUid = pPwd->pw_uid;
    429     }
    430     RTMemWipeThoroughly(szBuf, sizeof(szBuf), 3);
     527        *pGid = pPw->pw_gid;
     528        *pUid = pPw->pw_uid;
     529    }
    431530# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
    432     RTMemWipeThoroughly(szBuf2, sizeof(szBuf2), 3);
     531    RTMemWipeThoroughly(achBuf2, sizeof(achBuf2), 3);
    433532# endif
     533#endif
     534    RTMemWipeThoroughly(achBuf, sizeof(achBuf), 3);
    434535    return rc;
    435 #endif
    436536}
    437537
     
    10461146 * @param   gid         The GID corrsponding to @a pszAsUser, ~0 if NULL.
    10471147 * @param   fFlags      RTPROC_FLAGS_XXX
     1148 * @param   papszPamEnv Array of environment variables returned by PAM, if
     1149 *                      it was used for authentication and produced anything.
     1150 *                      Otherwise NULL.
    10481151 */
    1049 static int rtProcPosixCreateProfileEnv(PRTENV phEnvToUse, const char *pszAsUser, uid_t uid, gid_t gid, uint32_t fFlags)
     1152static int rtProcPosixCreateProfileEnv(PRTENV phEnvToUse, const char *pszAsUser, uid_t uid, gid_t gid,
     1153                                       uint32_t fFlags, char **papszPamEnv)
    10501154{
    10511155    /*
     
    11321236                        }
    11331237#endif
     1238                        /*
     1239                         * Add everything from the PAM environment.
     1240                         */
     1241                        if (RT_SUCCESS(rc) && papszPamEnv != NULL)
     1242                            for (size_t i = 0; papszPamEnv[i] != NULL && RT_SUCCESS(rc); i++)
     1243                            {
     1244                                char *pszEnvVar;
     1245                                rc = RTStrCurrentCPToUtf8(&pszEnvVar, papszPamEnv[i]);
     1246                                if (RT_SUCCESS(rc))
     1247                                {
     1248                                    char *pszValue = strchr(pszEnvVar, '=');
     1249                                    if (pszValue)
     1250                                        *pszValue++ = '\0';
     1251                                    rc = RTEnvSetEx(hEnvToUse, pszEnvVar, pszValue ? pszValue : "");
     1252                                    RTStrFree(pszEnvVar);
     1253                                }
     1254                                /* Ignore conversion issue, though LogRel them. */
     1255                                else if (rc != VERR_NO_STR_MEMORY && rc != VERR_NO_MEMORY)
     1256                                {
     1257                                    LogRelMax(256, ("RTStrCurrentCPToUtf8(,%.*Rhxs) -> %Rrc\n", strlen(pszEnvVar), pszEnvVar, rc));
     1258                                    rc = -rc;
     1259                                }
     1260                            }
    11341261                        if (RT_SUCCESS(rc))
    11351262                        {
     
    12521379
    12531380    /*
    1254      * Resolve the user id if specified.
    1255      */
    1256     uid_t uid = ~(uid_t)0;
    1257     gid_t gid = ~(gid_t)0;
     1381     * Validate the credentials if a user is specified.
     1382     */
     1383    bool const  fNeedLoginEnv = (fFlags & RTPROC_FLAGS_PROFILE)
     1384                             && ((fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) || hEnv == RTENV_DEFAULT);
     1385    uid_t       uid           = ~(uid_t)0;
     1386    gid_t       gid           = ~(gid_t)0;
     1387    char      **papszPamEnv   = NULL;
    12581388    if (pszAsUser)
    12591389    {
    1260         rc = rtCheckCredentials(pszAsUser, pszPassword, &gid, &uid);
     1390        rc = rtCheckCredentials(pszAsUser, pszPassword, &gid, &uid, fNeedLoginEnv ? &papszPamEnv : NULL);
    12611391        if (RT_FAILURE(rc))
    12621392            return rc;
    12631393    }
     1394#ifdef IPRT_USE_PAM
     1395    /*
     1396     * User unchanged, but if PROFILE is request we must try get the PAM
     1397     * environmnet variables.
     1398     *
     1399     * For this to work, we'll need a special PAM service profile which doesn't
     1400     * actually do any authentication, only concerns itself with the enviornment
     1401     * setup.  gdm-launch-environment is such one, and we use it if we haven't
     1402     * got an IPRT specific one there.
     1403     */
     1404    else if (fNeedLoginEnv)
     1405    {
     1406        const char *pszService;
     1407        if (rtProcPosixPamServiceExists("iprt-environment"))
     1408            pszService = "iprt-environment";
     1409# ifdef IPRT_PAM_NATIVE_SERVICE_NAME_ENVIRONMENT
     1410        else if (rtProcPosixPamServiceExists(IPRT_PAM_NATIVE_SERVICE_NAME_ENVIRONMENT))
     1411            pszService = IPRT_PAM_NATIVE_SERVICE_NAME_ENVIRONMENT;
     1412# endif
     1413        else if (rtProcPosixPamServiceExists("gdm-launch-environment"))
     1414            pszService = "gdm-launch-environment";
     1415        else
     1416            pszService = NULL;
     1417        if (pszService)
     1418        {
     1419            char szLoginName[512];
     1420            rc = getlogin_r(szLoginName, sizeof(szLoginName));
     1421            if (rc == 0)
     1422                rc = rtProcPosixAuthenticateUsingPam(pszService, szLoginName, "xxx", &papszPamEnv, NULL);
     1423        }
     1424    }
     1425#endif
    12641426
    12651427    /*
     
    12731435    {
    12741436        if (fFlags & RTPROC_FLAGS_PROFILE)
    1275             rc = rtProcPosixCreateProfileEnv(&hEnvToUse, pszAsUser, uid, gid, fFlags);
     1437            rc = rtProcPosixCreateProfileEnv(&hEnvToUse, pszAsUser, uid, gid, fFlags, papszPamEnv);
    12761438        else
    12771439            rc = RTEnvClone(&hEnvToUse, RTENV_DEFAULT);
     1440        rtProcPosixFreePamEnv(papszPamEnv);
     1441        papszPamEnv = NULL;
    12781442        if (RT_FAILURE(rc))
    12791443            return rc;
     
    12891453        }
    12901454    }
     1455    Assert(papszPamEnv == NULL);
    12911456
    12921457    /*
Note: See TracChangeset for help on using the changeset viewer.

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