Changeset 80481 in vbox for trunk/src/VBox
- Timestamp:
- Aug 28, 2019 2:58:11 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/process-win.cpp
r76553 r80481 418 418 419 419 /** 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 */ 424 static 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 */ 462 static 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 /** 420 484 * Get the process token of the process indicated by @a dwPID if the @a pSid 421 485 * matches. … … 459 523 { 460 524 /* 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. 464 528 */ 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); 494 530 } 495 531 else … … 946 982 * @returns Pointer to the SID on success. Free by calling RTMemFree. 947 983 * @param hToken The token.. 948 */ 949 static PSID rtProcWinGetTokenUserSid(HANDLE hToken) 950 { 984 * @param prc Optional return code. 985 */ 986 static PSID rtProcWinGetTokenUserSid(HANDLE hToken, int *prc) 987 { 988 int rcIgn; 989 if (!prc) 990 prc = &rcIgn; 991 *prc = VERR_NO_MEMORY; 992 951 993 /* 952 994 * Get the groups associated with the token. We just try a size first then … … 959 1001 if (!GetTokenInformation(hToken, TokenUser, pUser, cbUser, &cbNeeded)) 960 1002 { 1003 DWORD dwErr = GetLastError(); 961 1004 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); 963 1008 cbUser = cbNeeded + 128; 964 1009 pUser = (PTOKEN_USER)RTMemTmpAlloc(cbUser); … … 966 1011 if (!GetTokenInformation(hToken, TokenUser, pUser, cbUser, &cbNeeded)) 967 1012 { 1013 dwErr = GetLastError(); 1014 *prc = RTErrConvertFromWin32(dwErr); 968 1015 RTMemTmpFree(pUser); 969 Assert FailedReturn(NULL);1016 AssertLogRelMsgFailedReturn(("rtProcWinGetTokenUserSid: GetTokenInformation failed with %u\n", dwErr), NULL); 970 1017 } 971 1018 } … … 1331 1378 { 1332 1379 /*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*/); 1334 1381 if (pSid) 1335 1382 { … … 1442 1489 1443 1490 /** 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 */ 1497 static 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 */ 1541 static 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 /** 1444 1557 * Method \#2. 1558 * 1559 * @note pwszUser can be NULL when RTPROC_FLAGS_AS_IMPERSONATED_TOKEN is set. 1445 1560 */ 1446 1561 static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 *ppwszExec, PRTUTF16 pwszCmdLine, … … 1477 1592 DWORD dwErr = NO_ERROR; 1478 1593 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); 1480 1599 if (RT_SUCCESS(rc)) 1481 1600 { 1482 DWORDfRc;1601 BOOL fRc; 1483 1602 bool fFound = false; 1484 1603 HANDLE hTokenUserDesktop = INVALID_HANDLE_VALUE; … … 1492 1611 if (fFlags & RTPROC_FLAGS_SERVICE) 1493 1612 { 1613 /* 1614 * For the token search we need a SID. 1615 */ 1494 1616 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) 1517 1630 { 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)) 1525 1645 { 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); 1542 1652 if (ntSts == STATUS_SUCCESS) 1543 1653 { 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); 1546 1674 # 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)); 1549 1677 # 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) 1553 1698 { 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)); 1566 1701 rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2; 1567 1702 } 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); 1568 1722 } 1569 1723 else if (g_pfnLsaNtStatusToWinError) 1570 1724 { 1571 1725 dwErr = g_pfnLsaNtStatusToWinError(ntSts); 1572 LogRelFunc(("Lsa LookupNames2failed 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; 1574 1728 } 1575 1729 else 1576 1730 { 1577 LogRelFunc(("Lsa LookupNames2failed with: %#x\n", ntSts));1731 LogRelFunc(("LsaOpenPolicy failed with: %#x\n", ntSts)); 1578 1732 rc = RTErrConvertFromNtStatus(ntSts); 1579 1733 } 1580 1734 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) 1582 1743 { 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. */ 1585 1763 } 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; 1600 1766 } 1601 1767 else 1602 1768 { 1603 LogRelFunc(("L saOpenPolicy 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; 1605 1771 } 1606 1607 /* Note: pSid will be free'd down below. */1608 1772 } 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 */ 1646 1778 if (pSid) 1647 1779 { … … 1653 1785 #ifdef VBOX /* The explorer entry is a fallback in case GA aren't installed. */ 1654 1786 { "VBoxTray.exe" }, 1787 # ifndef IN_GUEST 1788 { "VirtualBox.exe" }, 1789 # endif 1655 1790 #endif 1656 1791 { "explorer.exe" }, … … 1707 1842 */ 1708 1843 PROFILEINFOW ProfileInfo; 1844 PRTUTF16 pwszUserFree = NULL; 1709 1845 RT_ZERO(ProfileInfo); 1710 1846 if (fFlags & RTPROC_FLAGS_PROFILE) 1711 1847 { 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 } 1718 1862 } 1719 1863 if (RT_SUCCESS(rc)) … … 1737 1881 && g_enmWinVer <= kRTWinOSType_NT4) /** @todo test newer versions... */ 1738 1882 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"; 1739 1894 1740 1895 /* … … 1795 1950 #endif 1796 1951 } 1952 if (pwszUserFree) 1953 RTUtf16Free(pwszUserFree); 1797 1954 } 1798 1955 } … … 2046 2203 /* 2047 2204 * 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); 2052 2212 int rc = rtProcWinCreateAsUser1(pwszUser, pwszPassword, ppwszExec, pwszCmdLine, 2053 2213 hEnv, dwCreationFlags, pStartupInfo, pProcInfo, fFlags, pszExec); … … 2227 2387 int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL); 2228 2388 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))) 2230 2390 { 2231 2391 rc = RTOnce(&g_rtProcWinResolveOnce, rtProcWinResolveOnce, NULL); … … 2385 2545 */ 2386 2546 if ( pszAsUser == NULL 2387 && !(fFlags & RTPROC_FLAGS_SERVICE))2547 && !(fFlags & (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN))) 2388 2548 { 2389 2549 /* Create the environment block first. */ … … 2414 2574 * function to do the actual work. 2415 2575 */ 2416 PRTUTF16 pwszUser; 2417 rc = RTStrToUtf16(pszAsUser, &pwszUser); 2576 PRTUTF16 pwszUser = NULL; 2577 if (pszAsUser) 2578 rc = RTStrToUtf16(pszAsUser, &pwszUser); 2418 2579 if (RT_SUCCESS(rc)) 2419 2580 { … … 2439 2600 { 2440 2601 /* 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. 2443 2604 */ 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); 2445 2609 *phProcess = ProcInfo.dwProcessId; 2446 2610 }
Note:
See TracChangeset
for help on using the changeset viewer.