VirtualBox

Changeset 80481 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 28, 2019 2:58:11 PM (5 years ago)
Author:
vboxsync
Message:

IPRT/process-win.cpp: Adding RTPROC_FLAGS_AS_IMPERSONATED_TOKEN and RTPROC_FLAGS_NO_WAIT for windows. bugref:9341 bugref:8078

File:
1 edited

Legend:

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

    r76553 r80481  
    418418
    419419/**
     420 * The following NT call is for v3.51 and does the equivalent of:
     421 *      DuplicateTokenEx(hSrcToken, MAXIMUM_ALLOWED, NULL,
     422 *                       SecurityIdentification, TokenPrimary, phToken);
     423 */
     424static int rtProcWinDuplicateToken(HANDLE hSrcToken, PHANDLE phToken)
     425{
     426    int rc;
     427    if (g_pfnNtDuplicateToken)
     428    {
     429        SECURITY_QUALITY_OF_SERVICE SecQoS;
     430        SecQoS.Length              = sizeof(SecQoS);
     431        SecQoS.ImpersonationLevel  = SecurityIdentification;
     432        SecQoS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
     433        SecQoS.EffectiveOnly       = FALSE;
     434
     435        OBJECT_ATTRIBUTES ObjAttr;
     436        InitializeObjectAttributes(&ObjAttr, NULL /*Name*/, 0 /*OBJ_XXX*/, NULL /*Root*/, NULL /*SecDesc*/);
     437        ObjAttr.SecurityQualityOfService = &SecQoS;
     438
     439        NTSTATUS rcNt = g_pfnNtDuplicateToken(hSrcToken, MAXIMUM_ALLOWED, &ObjAttr, FALSE, TokenPrimary, phToken);
     440        if (NT_SUCCESS(rcNt))
     441            rc = VINF_SUCCESS;
     442        else
     443            rc = RTErrConvertFromNtStatus(rcNt);
     444    }
     445    else
     446        rc = VERR_SYMBOL_NOT_FOUND; /** @todo do we really need to duplicate the token? */
     447    return rc;
     448}
     449
     450
     451/**
     452 * Get the token assigned to specified thread indicated by @a hThread.
     453 *
     454 * Only used when RTPROC_FLAGS_AS_IMPERSONATED_TOKEN is in effect and the
     455 * purpose is to get a duplicate the impersonated token of the current thread.
     456 *
     457 * @returns IPRT status code.
     458 * @param   hThread         The thread handle (current thread).
     459 * @param   phToken         Where to return the a duplicate of the thread token
     460 *                          handle on success. (The caller closes it.)
     461 */
     462static int rtProcWinGetThreadTokenHandle(HANDLE hThread, PHANDLE phToken)
     463{
     464    AssertPtr(phToken);
     465
     466    int     rc;
     467    HANDLE hTokenThread;
     468    if (OpenThreadToken(hThread,
     469                        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE
     470                        | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
     471                        TRUE /* OpenAsSelf - for impersonation at SecurityIdentification level */,
     472                        &hTokenThread))
     473    {
     474        rc = rtProcWinDuplicateToken(hTokenThread, phToken);
     475        CloseHandle(hTokenThread);
     476    }
     477    else
     478        rc = RTErrConvertFromWin32(GetLastError());
     479    return rc;
     480}
     481
     482
     483/**
    420484 * Get the process token of the process indicated by @a dwPID if the @a pSid
    421485 * matches.
     
    459523                        {
    460524                            /*
    461                              * The following NT call is for v3.51 and does the equivalent of:
    462                              *      DuplicateTokenEx(hTokenProc, MAXIMUM_ALLOWED, NULL,
    463                              *                       SecurityIdentification, TokenPrimary, phToken);
     525                             * So we found the process instance which belongs to the user we want to
     526                             * to run our new process under. This duplicated token will be used for
     527                             * the actual CreateProcessAsUserW() call then.
    464528                             */
    465                             if (g_pfnNtDuplicateToken)
    466                             {
    467                                 SECURITY_QUALITY_OF_SERVICE SecQoS;
    468                                 SecQoS.Length              = sizeof(SecQoS);
    469                                 SecQoS.ImpersonationLevel  = SecurityIdentification;
    470                                 SecQoS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    471                                 SecQoS.EffectiveOnly       = FALSE;
    472 
    473                                 OBJECT_ATTRIBUTES ObjAttr;
    474                                 InitializeObjectAttributes(&ObjAttr, NULL /*Name*/, 0 /*OBJ_XXX*/, NULL /*Root*/, NULL /*SecDesc*/);
    475                                 ObjAttr.SecurityQualityOfService = &SecQoS;
    476 
    477                                 NTSTATUS rcNt = g_pfnNtDuplicateToken(hTokenProc, MAXIMUM_ALLOWED, &ObjAttr, FALSE,
    478                                                                       TokenPrimary, phToken);
    479                                 if (NT_SUCCESS(rcNt))
    480                                 {
    481                                     /*
    482                                      * So we found the process instance which belongs to the user we want to
    483                                      * to run our new process under. This duplicated token will be used for
    484                                      * the actual CreateProcessAsUserW() call then.
    485                                      */
    486                                     rc = VINF_SUCCESS;
    487                                 }
    488                                 else
    489                                     rc = RTErrConvertFromNtStatus(rcNt);
    490 
    491                             }
    492                             else
    493                                 rc = VERR_SYMBOL_NOT_FOUND; /** @todo do we really need to duplicate the token? */
     529                            rc = rtProcWinDuplicateToken(hTokenProc, phToken);
    494530                        }
    495531                        else
     
    946982 * @returns Pointer to the SID on success. Free by calling RTMemFree.
    947983 * @param   hToken              The token..
    948  */
    949 static PSID rtProcWinGetTokenUserSid(HANDLE hToken)
    950 {
     984 * @param   prc                 Optional return code.
     985 */
     986static PSID rtProcWinGetTokenUserSid(HANDLE hToken, int *prc)
     987{
     988    int rcIgn;
     989    if (!prc)
     990        prc = &rcIgn;
     991    *prc = VERR_NO_MEMORY;
     992
    951993    /*
    952994     * Get the groups associated with the token.  We just try a size first then
     
    9591001    if (!GetTokenInformation(hToken, TokenUser, pUser, cbUser, &cbNeeded))
    9601002    {
     1003        DWORD dwErr = GetLastError();
    9611004        RTMemTmpFree(pUser);
    962         AssertReturn(GetLastError() == ERROR_INSUFFICIENT_BUFFER, NULL);
     1005        AssertLogRelMsgReturnStmt(dwErr == ERROR_INSUFFICIENT_BUFFER,
     1006                                  ("rtProcWinGetTokenUserSid: GetTokenInformation failed with %u\n", dwErr),
     1007                                  *prc = RTErrConvertFromWin32(dwErr), NULL);
    9631008        cbUser = cbNeeded + 128;
    9641009        pUser = (PTOKEN_USER)RTMemTmpAlloc(cbUser);
     
    9661011        if (!GetTokenInformation(hToken, TokenUser, pUser, cbUser, &cbNeeded))
    9671012        {
     1013            dwErr = GetLastError();
     1014            *prc = RTErrConvertFromWin32(dwErr);
    9681015            RTMemTmpFree(pUser);
    969             AssertFailedReturn(NULL);
     1016            AssertLogRelMsgFailedReturn(("rtProcWinGetTokenUserSid: GetTokenInformation failed with %u\n", dwErr), NULL);
    9701017        }
    9711018    }
     
    13311378            {
    13321379                /*PSID pSid = rtProcWinGetTokenLogonSid(hTokenToUse); - Better to use the user SID. Avoid overflowing the ACL. */
    1333                 PSID pSid = rtProcWinGetTokenUserSid(hTokenToUse);
     1380                PSID pSid = rtProcWinGetTokenUserSid(hTokenToUse, NULL /*prc*/);
    13341381                if (pSid)
    13351382                {
     
    14421489
    14431490/**
     1491 * Tries to resolve the name of the SID.
     1492 *
     1493 * @returns IPRT status code.
     1494 * @param   pSid        The SID to resolve.
     1495 * @param   ppwszName   Where to return the name. Use RTUtf16Free to free.
     1496 */
     1497static int rtProcWinSidToName(PSID pSid, PRTUTF16 *ppwszName)
     1498{
     1499    *ppwszName = NULL;
     1500
     1501    /*
     1502     * Use large initial buffers here to try avoid having to repeat the call.
     1503     */
     1504    DWORD cwcAllocated = 512;
     1505    while (cwcAllocated < _32K)
     1506    {
     1507        PRTUTF16 pwszName = RTUtf16Alloc(cwcAllocated * sizeof(RTUTF16));
     1508        AssertReturn(pwszName, VERR_NO_UTF16_MEMORY);
     1509        PRTUTF16 pwszDomain = RTUtf16Alloc(cwcAllocated * sizeof(RTUTF16));
     1510        AssertReturnStmt(pwszDomain, RTUtf16Free(pwszName), VERR_NO_UTF16_MEMORY);
     1511
     1512        DWORD cwcName   = cwcAllocated;
     1513        DWORD cwcDomain = cwcAllocated;
     1514        SID_NAME_USE SidNameUse = SidTypeUser;
     1515        if (LookupAccountSidW(NULL /*lpSystemName*/, pSid, pwszName, &cwcName, pwszDomain, &cwcDomain, &SidNameUse))
     1516        {
     1517            *ppwszName = pwszName;
     1518            RTUtf16Free(pwszDomain); /* may need this later. */
     1519            return VINF_SUCCESS;
     1520        }
     1521
     1522        DWORD const dwErr = GetLastError();
     1523        RTUtf16Free(pwszName);
     1524        RTUtf16Free(pwszDomain);
     1525        if (dwErr != ERROR_INSUFFICIENT_BUFFER)
     1526            return RTErrConvertFromWin32(dwErr);
     1527        cwcAllocated = RT_MAX(cwcName, cwcDomain) + 1;
     1528    }
     1529
     1530    return RTErrConvertFromWin32(ERROR_INSUFFICIENT_BUFFER);
     1531}
     1532
     1533
     1534/**
     1535 * Tries to resolve the user name for the token.
     1536 *
     1537 * @returns IPRT status code.
     1538 * @param   hToken      The token.
     1539 * @param   ppwszUser   Where to return the username. Use RTUtf16Free to free.
     1540 */
     1541static int rtProcWinTokenToUsername(HANDLE hToken, PRTUTF16 *ppwszUser)
     1542{
     1543    int rc = VINF_SUCCESS;
     1544    PSID pSid = rtProcWinGetTokenUserSid(hToken, &rc);
     1545    if (pSid)
     1546    {
     1547        rc = rtProcWinSidToName(pSid, ppwszUser);
     1548        RTMemFree(pSid);
     1549    }
     1550    else
     1551        *ppwszUser = NULL;
     1552    return rc;
     1553}
     1554
     1555
     1556/**
    14441557 * Method \#2.
     1558 *
     1559 * @note pwszUser can be NULL when RTPROC_FLAGS_AS_IMPERSONATED_TOKEN is set.
    14451560 */
    14461561static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 *ppwszExec, PRTUTF16 pwszCmdLine,
     
    14771592    DWORD   dwErr       = NO_ERROR;
    14781593    HANDLE  hTokenLogon = INVALID_HANDLE_VALUE;
    1479     int rc = rtProcWinUserLogon(pwszUser, pwszPassword, &hTokenLogon);
     1594    int rc;
     1595    if (fFlags & RTPROC_FLAGS_AS_IMPERSONATED_TOKEN)
     1596        rc = rtProcWinGetThreadTokenHandle(GetCurrentThread(), &hTokenLogon);
     1597    else
     1598        rc = rtProcWinUserLogon(pwszUser, pwszPassword, &hTokenLogon);
    14801599    if (RT_SUCCESS(rc))
    14811600    {
    1482         DWORD  fRc;
     1601        BOOL   fRc;
    14831602        bool   fFound = false;
    14841603        HANDLE hTokenUserDesktop = INVALID_HANDLE_VALUE;
     
    14921611        if (fFlags & RTPROC_FLAGS_SERVICE)
    14931612        {
     1613            /*
     1614             * For the token search we need a SID.
     1615             */
    14941616            PSID pSid = NULL;
    1495 
    1496             /* Try query the SID and domain sizes first. */
    1497             DWORD        cbSid      = 0; /* Must be zero to query size! */
    1498             DWORD        cwcDomain  = 0;
    1499             SID_NAME_USE SidNameUse = SidTypeUser;
    1500             fRc = LookupAccountNameW(NULL, pwszUser, NULL, &cbSid, NULL, &cwcDomain, &SidNameUse);
    1501             if (!fRc)
    1502             {
    1503                 dwErr = GetLastError();
    1504 
    1505                 /*
    1506                  * The errors ERROR_TRUSTED_DOMAIN_FAILURE and ERROR_TRUSTED_RELATIONSHIP_FAILURE
    1507                  * can happen if an ADC (Active Domain Controller) is offline or not reachable.
    1508                  *
    1509                  * Try to handle these errors gracefully by asking the local LSA cache of the
    1510                  * client OS instead then. For this to work, the desired user must have at
    1511                  * least logged in once at that client -- otherwise there will be no cached
    1512                  * authentication available and this fallback will fail.
    1513                  */
    1514                 if (   g_pfnLsaLookupNames2 /* >= Windows XP */
    1515                     && (   dwErr == ERROR_TRUSTED_DOMAIN_FAILURE
    1516                         || dwErr == ERROR_TRUSTED_RELATIONSHIP_FAILURE))
     1617            if (fFlags & RTPROC_FLAGS_AS_IMPERSONATED_TOKEN)
     1618                pSid = rtProcWinGetTokenUserSid(hTokenLogon, &rc);
     1619            else
     1620            {
     1621                /** @todo r=bird: why can't we do this in the same manner as in the
     1622                 *        RTPROC_FLAGS_AS_IMPERSONATED_TOKEN case above? */
     1623
     1624                /* Try query the SID and domain sizes first. */
     1625                DWORD        cbSid      = 0; /* Must be zero to query size! */
     1626                DWORD        cwcDomain  = 0;
     1627                SID_NAME_USE SidNameUse = SidTypeUser;
     1628                fRc = LookupAccountNameW(NULL, pwszUser, NULL, &cbSid, NULL, &cwcDomain, &SidNameUse);
     1629                if (!fRc)
    15171630                {
    1518                     LSA_OBJECT_ATTRIBUTES objAttr;
    1519                     RT_ZERO(objAttr);
    1520                     objAttr.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
    1521 
    1522                     LSA_HANDLE lsahPolicy;
    1523                     NTSTATUS ntSts = LsaOpenPolicy(NULL, &objAttr, POLICY_LOOKUP_NAMES, &lsahPolicy);
    1524                     if (ntSts == STATUS_SUCCESS)
     1631                    dwErr = GetLastError();
     1632
     1633                    /*
     1634                     * The errors ERROR_TRUSTED_DOMAIN_FAILURE and ERROR_TRUSTED_RELATIONSHIP_FAILURE
     1635                     * can happen if an ADC (Active Domain Controller) is offline or not reachable.
     1636                     *
     1637                     * Try to handle these errors gracefully by asking the local LSA cache of the
     1638                     * client OS instead then. For this to work, the desired user must have at
     1639                     * least logged in once at that client -- otherwise there will be no cached
     1640                     * authentication available and this fallback will fail.
     1641                     */
     1642                    if (   g_pfnLsaLookupNames2 /* >= Windows XP */
     1643                        && (   dwErr == ERROR_TRUSTED_DOMAIN_FAILURE
     1644                            || dwErr == ERROR_TRUSTED_RELATIONSHIP_FAILURE))
    15251645                    {
    1526                         RTPROCWINACCOUNTINFO accountInfo;
    1527                         RT_ZERO(accountInfo);
    1528                         rc = rtProcWinParseAccountInfo(pwszUser, &accountInfo);
    1529                         AssertRC(rc);
    1530                         AssertPtr(accountInfo.pwszUserName);
    1531 
    1532                         LSA_UNICODE_STRING lsaUser;
    1533                         lsaUser.Buffer        = accountInfo.pwszUserName;
    1534                         lsaUser.Length        = (USHORT)(RTUtf16Len(accountInfo.pwszUserName) * sizeof(WCHAR));
    1535                         lsaUser.MaximumLength = lsaUser.Length;
    1536 
    1537                         PLSA_REFERENCED_DOMAIN_LIST pDomainList     = NULL;
    1538                         PLSA_TRANSLATED_SID2        pTranslatedSids = NULL;
    1539                         ntSts = g_pfnLsaLookupNames2(lsahPolicy, 0 /* Flags */,
    1540                                                      1 /* Number of users to lookup */,
    1541                                                      &lsaUser, &pDomainList, &pTranslatedSids);
     1646                        LSA_OBJECT_ATTRIBUTES objAttr;
     1647                        RT_ZERO(objAttr);
     1648                        objAttr.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
     1649
     1650                        LSA_HANDLE lsahPolicy;
     1651                        NTSTATUS ntSts = LsaOpenPolicy(NULL, &objAttr, POLICY_LOOKUP_NAMES, &lsahPolicy);
    15421652                        if (ntSts == STATUS_SUCCESS)
    15431653                        {
    1544                             AssertPtr(pDomainList);
    1545                             AssertPtr(pTranslatedSids);
     1654                            RTPROCWINACCOUNTINFO accountInfo;
     1655                            RT_ZERO(accountInfo);
     1656                            rc = rtProcWinParseAccountInfo(pwszUser, &accountInfo);
     1657                            AssertRC(rc);
     1658                            AssertPtr(accountInfo.pwszUserName);
     1659
     1660                            LSA_UNICODE_STRING lsaUser;
     1661                            lsaUser.Buffer        = accountInfo.pwszUserName;
     1662                            lsaUser.Length        = (USHORT)(RTUtf16Len(accountInfo.pwszUserName) * sizeof(WCHAR));
     1663                            lsaUser.MaximumLength = lsaUser.Length;
     1664
     1665                            PLSA_REFERENCED_DOMAIN_LIST pDomainList     = NULL;
     1666                            PLSA_TRANSLATED_SID2        pTranslatedSids = NULL;
     1667                            ntSts = g_pfnLsaLookupNames2(lsahPolicy, 0 /* Flags */,
     1668                                                         1 /* Number of users to lookup */,
     1669                                                         &lsaUser, &pDomainList, &pTranslatedSids);
     1670                            if (ntSts == STATUS_SUCCESS)
     1671                            {
     1672                                AssertPtr(pDomainList);
     1673                                AssertPtr(pTranslatedSids);
    15461674# ifdef DEBUG
    1547                             LogRelFunc(("LsaLookupNames2: cDomains=%u, DomainIndex=%ld, SidUse=%ld\n",
    1548                                         pDomainList->Entries, pTranslatedSids[0].DomainIndex, pTranslatedSids[0].Use));
     1675                                LogRelFunc(("LsaLookupNames2: cDomains=%u, DomainIndex=%ld, SidUse=%ld\n",
     1676                                            pDomainList->Entries, pTranslatedSids[0].DomainIndex, pTranslatedSids[0].Use));
    15491677# endif
    1550                             Assert(pTranslatedSids[0].Use == SidTypeUser);
    1551 
    1552                             if (pDomainList->Entries)
     1678                                Assert(pTranslatedSids[0].Use == SidTypeUser);
     1679
     1680                                if (pDomainList->Entries)
     1681                                {
     1682                                    AssertPtr(pDomainList->Domains);
     1683                                    LogRelFunc(("LsaLookupNames2: Domain=%ls\n",
     1684                                                pDomainList->Domains[pTranslatedSids[0].DomainIndex].Name.Buffer));
     1685                                }
     1686
     1687                                cbSid = GetLengthSid(pTranslatedSids->Sid) + 16;
     1688                                Assert(cbSid);
     1689                                pSid = (PSID)RTMemAllocZ(cbSid);
     1690                                if (!CopySid(cbSid, pSid, pTranslatedSids->Sid))
     1691                                {
     1692                                    dwErr = GetLastError();
     1693                                    LogRelFunc(("CopySid failed with: %ld\n", dwErr));
     1694                                    rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
     1695                                }
     1696                            }
     1697                            else if (g_pfnLsaNtStatusToWinError)
    15531698                            {
    1554                                 AssertPtr(pDomainList->Domains);
    1555                                 LogRelFunc(("LsaLookupNames2: Domain=%ls\n",
    1556                                             pDomainList->Domains[pTranslatedSids[0].DomainIndex].Name.Buffer));
    1557                             }
    1558 
    1559                             cbSid = GetLengthSid(pTranslatedSids->Sid) + 16;
    1560                             Assert(cbSid);
    1561                             pSid = (PSID)RTMemAllocZ(cbSid);
    1562                             if (!CopySid(cbSid, pSid, pTranslatedSids->Sid))
    1563                             {
    1564                                 dwErr = GetLastError();
    1565                                 LogRelFunc(("CopySid failed with: %ld\n", dwErr));
     1699                                dwErr = g_pfnLsaNtStatusToWinError(ntSts);
     1700                                LogRelFunc(("LsaLookupNames2 failed with: %ld\n", dwErr));
    15661701                                rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    15671702                            }
     1703                            else
     1704                            {
     1705                                LogRelFunc(("LsaLookupNames2 failed with: %#x\n", ntSts));
     1706                                rc = RTErrConvertFromNtStatus(ntSts);
     1707                            }
     1708
     1709                            if (pDomainList)
     1710                            {
     1711                                LsaFreeMemory(pDomainList);
     1712                                pDomainList = NULL;
     1713                            }
     1714                            if (pTranslatedSids)
     1715                            {
     1716                                LsaFreeMemory(pTranslatedSids);
     1717                                pTranslatedSids = NULL;
     1718                            }
     1719
     1720                            rtProcWinFreeAccountInfo(&accountInfo);
     1721                            LsaClose(lsahPolicy);
    15681722                        }
    15691723                        else if (g_pfnLsaNtStatusToWinError)
    15701724                        {
    15711725                            dwErr = g_pfnLsaNtStatusToWinError(ntSts);
    1572                             LogRelFunc(("LsaLookupNames2 failed with: %ld\n", dwErr));
    1573                             rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
     1726                            LogRelFunc(("LsaOpenPolicy failed with: %ld\n", dwErr));
     1727                            rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_3;
    15741728                        }
    15751729                        else
    15761730                        {
    1577                             LogRelFunc(("LsaLookupNames2 failed with: %#x\n", ntSts));
     1731                            LogRelFunc(("LsaOpenPolicy failed with: %#x\n", ntSts));
    15781732                            rc = RTErrConvertFromNtStatus(ntSts);
    15791733                        }
    15801734
    1581                         if (pDomainList)
     1735                        /* Note: pSid will be free'd down below. */
     1736                    }
     1737                    else if (dwErr == ERROR_INSUFFICIENT_BUFFER)
     1738                    {
     1739                        /* Allocate memory for the LookupAccountNameW output buffers and do it for real. */
     1740                        cbSid = fRc && cbSid != 0 ? cbSid + 16 : _1K;
     1741                        pSid = (PSID)RTMemAllocZ(cbSid);
     1742                        if (pSid)
    15821743                        {
    1583                             LsaFreeMemory(pDomainList);
    1584                             pDomainList = NULL;
     1744                            cwcDomain = fRc ? cwcDomain + 2 : _4K;
     1745                            PRTUTF16 pwszDomain = (PRTUTF16)RTMemAllocZ(cwcDomain * sizeof(RTUTF16));
     1746                            if (pwszDomain)
     1747                            {
     1748                                /* Note: Just pass in the UPN (User Principal Name), e.g. [email protected] */
     1749                                if (!LookupAccountNameW(NULL /*lpSystemName*/, pwszUser, pSid, &cbSid, pwszDomain, &cwcDomain,
     1750                                                        &SidNameUse))
     1751                                {
     1752                                    dwErr = GetLastError();
     1753                                    LogRelFunc(("LookupAccountNameW(2) failed with: %ld\n", dwErr));
     1754                                    rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_4;
     1755                                }
     1756
     1757                                RTMemFree(pwszDomain);
     1758                            }
     1759                            else
     1760                                rc = VERR_NO_MEMORY;
     1761
     1762                            /* Note: pSid will be free'd down below. */
    15851763                        }
    1586                         if (pTranslatedSids)
    1587                         {
    1588                             LsaFreeMemory(pTranslatedSids);
    1589                             pTranslatedSids = NULL;
    1590                         }
    1591 
    1592                         rtProcWinFreeAccountInfo(&accountInfo);
    1593                         LsaClose(lsahPolicy);
    1594                     }
    1595                     else if (g_pfnLsaNtStatusToWinError)
    1596                     {
    1597                         dwErr = g_pfnLsaNtStatusToWinError(ntSts);
    1598                         LogRelFunc(("LsaOpenPolicy failed with: %ld\n", dwErr));
    1599                         rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_3;
     1764                        else
     1765                            rc = VERR_NO_MEMORY;
    16001766                    }
    16011767                    else
    16021768                    {
    1603                         LogRelFunc(("LsaOpenPolicy failed with: %#x\n", ntSts));
    1604                         rc = RTErrConvertFromNtStatus(ntSts);
     1769                        LogRelFunc(("LookupAccountNameW(1) failed with: %ld\n", dwErr));
     1770                        rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    16051771                    }
    1606 
    1607                     /* Note: pSid will be free'd down below. */
    16081772                }
    1609                 else if (dwErr == ERROR_INSUFFICIENT_BUFFER)
    1610                 {
    1611                     /* Allocate memory for the LookupAccountNameW output buffers and do it for real. */
    1612                     cbSid = fRc && cbSid != 0 ? cbSid + 16 : _1K;
    1613                     pSid = (PSID)RTMemAllocZ(cbSid);
    1614                     if (pSid)
    1615                     {
    1616                         cwcDomain = fRc ? cwcDomain + 2 : _4K;
    1617                         PRTUTF16 pwszDomain = (PRTUTF16)RTMemAllocZ(cwcDomain * sizeof(RTUTF16));
    1618                         if (pwszDomain)
    1619                         {
    1620                             /* Note: Just pass in the UPN (User Principal Name), e.g. [email protected] */
    1621                             if (!LookupAccountNameW(NULL /*lpSystemName*/, pwszUser, pSid, &cbSid, pwszDomain, &cwcDomain,
    1622                                                     &SidNameUse))
    1623                             {
    1624                                 dwErr = GetLastError();
    1625                                 LogRelFunc(("LookupAccountNameW(2) failed with: %ld\n", dwErr));
    1626                                 rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_4;
    1627                             }
    1628 
    1629                             RTMemFree(pwszDomain);
    1630                         }
    1631                         else
    1632                             rc = VERR_NO_MEMORY;
    1633 
    1634                         /* Note: pSid will be free'd down below. */
    1635                     }
    1636                     else
    1637                         rc = VERR_NO_MEMORY;
    1638                 }
    1639                 else
    1640                 {
    1641                     LogRelFunc(("LookupAccountNameW(1) failed with: %ld\n", dwErr));
    1642                     rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    1643                 }
    1644             }
    1645 
     1773            }
     1774
     1775            /*
     1776             * If we got a valid SID, search the running processes.
     1777             */
    16461778            if (pSid)
    16471779            {
     
    16531785#ifdef VBOX             /* The explorer entry is a fallback in case GA aren't installed. */
    16541786                        { "VBoxTray.exe" },
     1787# ifndef IN_GUEST
     1788                        { "VirtualBox.exe" },
     1789# endif
    16551790#endif
    16561791                        { "explorer.exe" },
     
    17071842                 */
    17081843                PROFILEINFOW ProfileInfo;
     1844                PRTUTF16     pwszUserFree = NULL;
    17091845                RT_ZERO(ProfileInfo);
    17101846                if (fFlags & RTPROC_FLAGS_PROFILE)
    17111847                {
    1712                     ProfileInfo.dwSize     = sizeof(ProfileInfo);
    1713                     ProfileInfo.lpUserName = pwszUser;
    1714                     ProfileInfo.dwFlags    = PI_NOUI; /* Prevents the display of profile error messages. */
    1715 
    1716                     if (!g_pfnLoadUserProfileW(hTokenToUse, &ProfileInfo))
    1717                         rc = RTErrConvertFromWin32(GetLastError());
     1848                    if (!pwszUser)
     1849                    {
     1850                        Assert(fFlags & RTPROC_FLAGS_AS_IMPERSONATED_TOKEN);
     1851                        rc = rtProcWinTokenToUsername(hTokenToUse, &pwszUserFree);
     1852                        pwszUser = pwszUserFree;
     1853                    }
     1854                    if (RT_SUCCESS(rc))
     1855                    {
     1856                        ProfileInfo.dwSize     = sizeof(ProfileInfo);
     1857                        ProfileInfo.dwFlags    = PI_NOUI; /* Prevents the display of profile error messages. */
     1858                        ProfileInfo.lpUserName = pwszUser;
     1859                        if (!g_pfnLoadUserProfileW(hTokenToUse, &ProfileInfo))
     1860                            rc = RTErrConvertFromWin32(GetLastError());
     1861                    }
    17181862                }
    17191863                if (RT_SUCCESS(rc))
     
    17371881                                    && g_enmWinVer <= kRTWinOSType_NT4) /** @todo test newer versions... */
    17381882                                    rtProcWinStationPrep(hTokenToUse, pStartupInfo, &hOldWinStation);
     1883
     1884                                /* Specify a window station and desktop when start interactive
     1885                                 * process from service with an impersonated token. */
     1886                                /** @todo r=bird: Why is this needed? */
     1887                                /** @todo r=bird: Why don't we do this for the non-impersonated token case? */
     1888                                /** @todo r=bird: Remind me, does pure RDP logins get a winSta0 too, or do
     1889                                 *        the get a mangled name similar to the services? */
     1890                                if (   fFound
     1891                                    &&    (fFlags & (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN))
     1892                                       ==           (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN))
     1893                                    pStartupInfo->lpDesktop = L"WinSta0\\default";
    17391894
    17401895                                /*
     
    17951950#endif
    17961951                    }
     1952                    if (pwszUserFree)
     1953                        RTUtf16Free(pwszUserFree);
    17971954                }
    17981955            }
     
    20462203    /*
    20472204     * If we run as a service CreateProcessWithLogon will fail, so don't even
    2048      * try it (because of Local System context).  This method is very slow on W2K.
    2049      */
    2050     if (!(fFlags & RTPROC_FLAGS_SERVICE))
    2051     {
     2205     * try it (because of Local System context).  If we got an impersonated token
     2206     * we should use, we also have to have to skip over this approach.
     2207     * Note! This method is very slow on W2K.
     2208     */
     2209    if (!(fFlags & (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN)))
     2210    {
     2211        AssertPtr(pwszUser);
    20522212        int rc = rtProcWinCreateAsUser1(pwszUser, pwszPassword, ppwszExec, pwszCmdLine,
    20532213                                        hEnv, dwCreationFlags, pStartupInfo, pProcInfo, fFlags, pszExec);
     
    22272387    int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL);
    22282388    AssertRCReturn(rc, rc);
    2229     if (pszAsUser || (fFlags & (RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_SERVICE)))
     2389    if (pszAsUser || (fFlags & (RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN)))
    22302390    {
    22312391        rc = RTOnce(&g_rtProcWinResolveOnce, rtProcWinResolveOnce, NULL);
     
    23852545             */
    23862546            if (   pszAsUser == NULL
    2387                 && !(fFlags & RTPROC_FLAGS_SERVICE))
     2547                && !(fFlags & (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN)))
    23882548            {
    23892549                /* Create the environment block first. */
     
    24142574                 * function to do the actual work.
    24152575                 */
    2416                 PRTUTF16 pwszUser;
    2417                 rc = RTStrToUtf16(pszAsUser, &pwszUser);
     2576                PRTUTF16 pwszUser = NULL;
     2577                if (pszAsUser)
     2578                    rc = RTStrToUtf16(pszAsUser, &pwszUser);
    24182579                if (RT_SUCCESS(rc))
    24192580                {
     
    24392600                {
    24402601                    /*
    2441                      * Add the process to the child process list so
    2442                      * RTProcWait can reuse and close the process handle.
     2602                     * Add the process to the child process list so RTProcWait can reuse and close
     2603                     * the process handle, unless, of course, the caller has no intention waiting.
    24432604                     */
    2444                     rtProcWinAddPid(ProcInfo.dwProcessId, ProcInfo.hProcess);
     2605                    if (!(fFlags & RTPROC_FLAGS_NO_WAIT))
     2606                        rtProcWinAddPid(ProcInfo.dwProcessId, ProcInfo.hProcess);
     2607                    else
     2608                        CloseHandle(ProcInfo.hProcess);
    24452609                    *phProcess = ProcInfo.dwProcessId;
    24462610                }
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