VirtualBox

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


Ignore:
Timestamp:
Dec 6, 2021 9:47:31 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
148666
Message:

IPRT/RTProcCreateEx/posix: Use 'ASCII' instead of 'C' as the default child codeset, iconv_open doesn't grok 'C' and fails. The dynamic loading of libpam must take shared object versioning into account and not expect the dev library libpam.so to be installed, so use RTLdr for loading it and keep it loaded. Ubuntu needs the session to be opened before we get any locale enviornment bits, so do pam_open_session too. bugref:10153

File:
1 edited

Legend:

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

    r92750 r92755  
    9292# ifdef RT_OS_DARWIN
    9393#  include <mach-o/dyld.h>
    94 #  define IPRT_LIBPAM_FILE      "libpam.dylib"
    95 # else
    96 #  define IPRT_LIBPAM_FILE      "libpam.so"
    9794# endif
    9895# include <security/pam_appl.h>
     
    142139#include "internal/path.h"
    143140#include "internal/string.h"
     141
     142
     143/*********************************************************************************************************************************
     144*   Defined Constants And Macros                                                                                                 *
     145*********************************************************************************************************************************/
     146#ifdef IPRT_USE_PAM
     147/*
     148 * The PAM library names and version ranges to try.
     149 */
     150# ifdef RT_OS_DARWIN
     151#  include <mach-o/dyld.h>
     152/** @node libpam.2.dylib was introduced with 10.6.x (OpenPAM); we use
     153 *        libpam.dylib as that's a symlink to the latest and greatest. */
     154#  define IPRT_LIBPAM_FILE_1            "libpam.dylib"
     155#  define IPRT_LIBPAM_FILE_1_FIRST_VER 0
     156#  define IPRT_LIBPAM_FILE_1_END_VER   0
     157#  define IPRT_LIBPAM_FILE_2            "libpam.2.dylib"
     158#  define IPRT_LIBPAM_FILE_2_FIRST_VER 0
     159#  define IPRT_LIBPAM_FILE_2_END_VER   0
     160#  define IPRT_LIBPAM_FILE_3            "libpam.1.dylib"
     161#  define IPRT_LIBPAM_FILE_3_FIRST_VER 0
     162#  define IPRT_LIBPAM_FILE_3_END_VER   0
     163# elif RT_OS_LINUX
     164#  define IPRT_LIBPAM_FILE_1           "libpam.so.0"
     165#  define IPRT_LIBPAM_FILE_1_FIRST_VER 0
     166#  define IPRT_LIBPAM_FILE_1_END_VER   0
     167#  define IPRT_LIBPAM_FILE_2           "libpam.so"
     168#  define IPRT_LIBPAM_FILE_2_FIRST_VER 16
     169#  define IPRT_LIBPAM_FILE_2_END_VER   1
     170# else
     171#  define IPRT_LIBPAM_FILE_1           "libpam.so"
     172#  define IPRT_LIBPAM_FILE_1_MIN_VER   16
     173#  define IPRT_LIBPAM_FILE_1_MAX_VER   0
     174# endif
     175#endif
    144176
    145177
     
    246278
    247279    /*
    248      * Use PAM for the authentication.
    249      * Note! libpam.2.dylib was introduced with 10.6.x (OpenPAM).
    250      */
    251     void *hModPam = dlopen(IPRT_LIBPAM_FILE, RTLD_LAZY | RTLD_GLOBAL);
    252     if (hModPam)
    253     {
    254         int     (*pfnPamStart)(const char *, const char *, struct pam_conv *, pam_handle_t **);
    255         int     (*pfnPamAuthenticate)(pam_handle_t *, int);
    256         int     (*pfnPamAcctMgmt)(pam_handle_t *, int);
    257         int     (*pfnPamSetItem)(pam_handle_t *, int, const void *);
    258         int     (*pfnPamSetCred)(pam_handle_t *, int);
    259         char ** (*pfnPamGetEnvList)(pam_handle_t *);
    260         int     (*pfnPamOpenSession)(pam_handle_t *, int);
    261         int     (*pfnPamCloseSession)(pam_handle_t *, int);
    262         int     (*pfnPamEnd)(pam_handle_t *, int);
    263         *(void **)&pfnPamStart        = dlsym(hModPam, "pam_start");
    264         *(void **)&pfnPamAuthenticate = dlsym(hModPam, "pam_authenticate");
    265         *(void **)&pfnPamAcctMgmt     = dlsym(hModPam, "pam_acct_mgmt");
    266         *(void **)&pfnPamSetItem      = dlsym(hModPam, "pam_set_item");
    267         *(void **)&pfnPamSetCred      = dlsym(hModPam, "pam_setcred");
    268         *(void **)&pfnPamGetEnvList   = dlsym(hModPam, "pam_getenvlist");
    269         *(void **)&pfnPamOpenSession  = dlsym(hModPam, "pam_open_session");
    270         *(void **)&pfnPamCloseSession = dlsym(hModPam, "pam_close_session");
    271         *(void **)&pfnPamEnd          = dlsym(hModPam, "pam_end");
     280     * Dynamically load pam the first time we go thru here.
     281     */
     282    static int     (*s_pfnPamStart)(const char *, const char *, struct pam_conv *, pam_handle_t **);
     283    static int     (*s_pfnPamAuthenticate)(pam_handle_t *, int);
     284    static int     (*s_pfnPamAcctMgmt)(pam_handle_t *, int);
     285    static int     (*s_pfnPamSetItem)(pam_handle_t *, int, const void *);
     286    static int     (*s_pfnPamSetCred)(pam_handle_t *, int);
     287    static char ** (*s_pfnPamGetEnvList)(pam_handle_t *);
     288    static int     (*s_pfnPamOpenSession)(pam_handle_t *, int);
     289    static int     (*s_pfnPamCloseSession)(pam_handle_t *, int);
     290    static int     (*s_pfnPamEnd)(pam_handle_t *, int);
     291    if (   s_pfnPamStart == NULL
     292        || s_pfnPamAuthenticate == NULL
     293        || s_pfnPamAcctMgmt == NULL
     294        || s_pfnPamSetItem == NULL
     295        || s_pfnPamEnd == NULL)
     296    {
     297        RTLDRMOD hModPam = NIL_RTLDRMOD;
     298        const char *pszLast;
     299        int rc = RTLdrLoadSystemEx(pszLast = IPRT_LIBPAM_FILE_1, RTLDRLOAD_FLAGS_GLOBAL | RTLDRLOAD_FLAGS_NO_UNLOAD
     300                                   | RTLDRLOAD_FLAGS_SO_VER_RANGE(IPRT_LIBPAM_FILE_1_FIRST_VER, IPRT_LIBPAM_FILE_1_END_VER),
     301                                   &hModPam);
     302# ifdef IPRT_LIBPAM_FILE_2
     303        if (RT_FAILURE(rc))
     304            rc = RTLdrLoadSystemEx(pszLast = IPRT_LIBPAM_FILE_2, RTLDRLOAD_FLAGS_GLOBAL | RTLDRLOAD_FLAGS_NO_UNLOAD
     305                                   | RTLDRLOAD_FLAGS_SO_VER_RANGE(IPRT_LIBPAM_FILE_2_FIRST_VER, IPRT_LIBPAM_FILE_2_END_VER),
     306                                   &hModPam);
     307# endif
     308# ifdef IPRT_LIBPAM_FILE_3
     309        if (RT_FAILURE(rc))
     310            rc = RTLdrLoadSystemEx(pszLast = IPRT_LIBPAM_FILE_3, RTLDRLOAD_FLAGS_GLOBAL | RTLDRLOAD_FLAGS_NO_UNLOAD
     311                                   | RTLDRLOAD_FLAGS_SO_VER_RANGE(IPRT_LIBPAM_FILE_3_FIRST_VER, IPRT_LIBPAM_FILE_3_END_VER),
     312                                   &hModPam);
     313# endif
     314        if (RT_FAILURE(rc))
     315        {
     316            LogRelMax(10, ("failed to load %s: %Rrc\n", pszLast, rc));
     317            return VERR_AUTHENTICATION_FAILURE;
     318        }
     319
     320        *(PFNRT *)&s_pfnPamStart        = RTLdrGetFunction(hModPam, "pam_start");
     321        *(PFNRT *)&s_pfnPamAuthenticate = RTLdrGetFunction(hModPam, "pam_authenticate");
     322        *(PFNRT *)&s_pfnPamAcctMgmt     = RTLdrGetFunction(hModPam, "pam_acct_mgmt");
     323        *(PFNRT *)&s_pfnPamSetItem      = RTLdrGetFunction(hModPam, "pam_set_item");
     324        *(PFNRT *)&s_pfnPamSetCred      = RTLdrGetFunction(hModPam, "pam_setcred");
     325        *(PFNRT *)&s_pfnPamGetEnvList   = RTLdrGetFunction(hModPam, "pam_getenvlist");
     326        *(PFNRT *)&s_pfnPamOpenSession  = RTLdrGetFunction(hModPam, "pam_open_session");
     327        *(PFNRT *)&s_pfnPamCloseSession = RTLdrGetFunction(hModPam, "pam_close_session");
     328        *(PFNRT *)&s_pfnPamEnd          = RTLdrGetFunction(hModPam, "pam_end");
     329
     330        RTLdrClose(hModPam);
     331
    272332        ASMCompilerBarrier();
    273         if (   pfnPamStart
    274             && pfnPamAuthenticate
    275             && pfnPamAcctMgmt
    276             && pfnPamSetItem
    277             && pfnPamEnd)
    278         {
    279 # define pam_start           pfnPamStart
    280 # define pam_authenticate    pfnPamAuthenticate
    281 # define pam_acct_mgmt       pfnPamAcctMgmt
    282 # define pam_set_item        pfnPamSetItem
    283 # define pam_setcred         pfnPamSetCred
    284 # define pam_getenvlist      pfnPamGetEnvList
    285 # define pam_open_session    pfnPamOpenSession
    286 # define pam_close_session   pfnPamCloseSession
    287 # define pam_end             pfnPamEnd
    288 
    289             /* Do the PAM stuff. */
    290             pam_handle_t   *hPam        = NULL;
    291             RTPROCPAMARGS   PamConvArgs = { pszUser, pszPassword };
    292             struct pam_conv PamConversation;
    293             RT_ZERO(PamConversation);
    294             PamConversation.appdata_ptr = &PamConvArgs;
    295             PamConversation.conv        = rtPamConv;
    296             int rc = pam_start(pszPamService, pszUser, &PamConversation, &hPam);
     333        if (   s_pfnPamStart == NULL
     334            || s_pfnPamAuthenticate == NULL
     335            || s_pfnPamAcctMgmt == NULL
     336            || s_pfnPamSetItem == NULL
     337            || s_pfnPamEnd == NULL)
     338        {
     339            LogRelMax(10, ("failed to resolve symbols: %p %p %p %p %p\n",
     340                           s_pfnPamStart, s_pfnPamAuthenticate, s_pfnPamAcctMgmt, s_pfnPamSetItem, s_pfnPamEnd));
     341            return VERR_AUTHENTICATION_FAILURE;
     342        }
     343    }
     344
     345# define pam_start           s_pfnPamStart
     346# define pam_authenticate    s_pfnPamAuthenticate
     347# define pam_acct_mgmt       s_pfnPamAcctMgmt
     348# define pam_set_item        s_pfnPamSetItem
     349# define pam_setcred         s_pfnPamSetCred
     350# define pam_getenvlist      s_pfnPamGetEnvList
     351# define pam_open_session    s_pfnPamOpenSession
     352# define pam_close_session   s_pfnPamCloseSession
     353# define pam_end             s_pfnPamEnd
     354
     355    /*
     356     * Do the PAM stuff.
     357     */
     358    pam_handle_t   *hPam        = NULL;
     359    RTPROCPAMARGS   PamConvArgs = { pszUser, pszPassword };
     360    struct pam_conv PamConversation;
     361    RT_ZERO(PamConversation);
     362    PamConversation.appdata_ptr = &PamConvArgs;
     363    PamConversation.conv        = rtPamConv;
     364    int rc = pam_start(pszPamService, pszUser, &PamConversation, &hPam);
     365    if (rc == PAM_SUCCESS)
     366    {
     367        rc = pam_set_item(hPam, PAM_RUSER, pszUser);
     368        if (rc == PAM_SUCCESS)
     369        {
     370            if (pfMayFallBack)
     371                *pfMayFallBack = false;
     372            rc = pam_authenticate(hPam, 0);
    297373            if (rc == PAM_SUCCESS)
    298374            {
    299                 rc = pam_set_item(hPam, PAM_RUSER, pszUser);
    300                 if (rc == PAM_SUCCESS)
     375                rc = pam_acct_mgmt(hPam, 0);
     376                if (   rc == PAM_SUCCESS
     377                    || rc == PAM_AUTHINFO_UNAVAIL /*??*/)
    301378                {
    302                     if (pfMayFallBack)
    303                         *pfMayFallBack = false;
    304                     rc = pam_authenticate(hPam, 0);
    305                     if (rc == PAM_SUCCESS)
     379                    if (   ppapszEnv
     380                        && s_pfnPamGetEnvList
     381                        && s_pfnPamSetCred)
    306382                    {
    307                         rc = pam_acct_mgmt(hPam, 0);
    308                         if (   rc == PAM_SUCCESS
    309                             || rc == PAM_AUTHINFO_UNAVAIL /*??*/)
    310                         {
    311                             if (   ppapszEnv
    312                                 && pfnPamGetEnvList
    313                                 && pfnPamSetCred)
    314                             {
    315                                 /* pam_env.so creates the environment when pam_setcred is called. */
    316                                 rc = pam_setcred(hPam, PAM_ESTABLISH_CRED | PAM_SILENT);
    317                                 /** @todo check pam_setcred status code. */
    318                                 *ppapszEnv = pam_getenvlist(hPam);
    319                                 pam_setcred(hPam, PAM_DELETE_CRED);
    320                             }
    321 
    322                             pam_end(hPam, PAM_SUCCESS);
    323                             dlclose(hModPam);
    324                             return VINF_SUCCESS;
    325                         }
    326                         LogFunc(("pam_acct_mgmt -> %d\n", rc));
     383                        /* pam_env.so creates the environment when pam_setcred is called,. */
     384                        int rcSetCred = pam_setcred(hPam, PAM_ESTABLISH_CRED | PAM_SILENT);
     385                        /** @todo check pam_setcred status code? */
     386
     387                        /* Unless it does it during session opening (Ubuntu 21.10).  This
     388                           unfortunately means we might mount user dir and other crap: */
     389                        /** @todo do session handling properly   */
     390                        int rcOpenSession = PAM_ABORT;
     391                        if (   s_pfnPamOpenSession
     392                            && s_pfnPamCloseSession)
     393                            rcOpenSession = pam_open_session(hPam, PAM_SILENT);
     394
     395                        *ppapszEnv = pam_getenvlist(hPam);
     396                        LogFlowFunc(("pam_getenvlist -> %p ([0]=%p); rcSetCred=%d rcOpenSession=%d\n",
     397                                     *ppapszEnv, *ppapszEnv ? **ppapszEnv : NULL, rcSetCred, rcOpenSession)); RT_NOREF(rcSetCred);
     398
     399                        if (rcOpenSession == PAM_SUCCESS)
     400                            pam_close_session(hPam, PAM_SILENT);
     401                        pam_setcred(hPam, PAM_DELETE_CRED);
    327402                    }
    328                     else
    329                         LogFunc(("pam_authenticate -> %d\n", rc));
     403
     404                    pam_end(hPam, PAM_SUCCESS);
     405                    LogFlowFunc(("pam auth (for %s) successful\n", pszPamService));
     406                    return VINF_SUCCESS;
    330407                }
    331                 else
    332                     LogFunc(("pam_set_item/PAM_RUSER -> %d\n", rc));
    333                 pam_end(hPam, rc);
     408                LogFunc(("pam_acct_mgmt -> %d\n", rc));
    334409            }
    335410            else
    336                 LogFunc(("pam_start -> %d\n", rc));
     411                LogFunc(("pam_authenticate -> %d\n", rc));
    337412        }
    338413        else
    339             LogFunc(("failed to resolve symbols: %p %p %p %p %p\n",
    340                      pfnPamStart, pfnPamAuthenticate, pfnPamAcctMgmt, pfnPamSetItem, pfnPamEnd));
    341         dlclose(hModPam);
     414            LogFunc(("pam_set_item/PAM_RUSER -> %d\n", rc));
     415        pam_end(hPam, rc);
    342416    }
    343417    else
    344         LogFunc(("Loading " IPRT_LIBPAM_FILE " failed\n"));
     418        LogFunc(("pam_start(%s) -> %d\n", pszPamService, rc));
    345419    return VERR_AUTHENTICATION_FAILURE;
    346420}
     
    13761450        }
    13771451        else
    1378             pszEncoding = "C";
     1452            pszEncoding = "ASCII";
    13791453    }
    13801454
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