VirtualBox

Changeset 59781 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
Feb 23, 2016 10:20:30 AM (9 years ago)
Author:
vboxsync
Message:

IPRT/r3/win/process-win.cpp: temporary back out the most recent LSA cache changes to check if these changes are responsible for a recent regression

File:
1 edited

Legend:

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

    r59770 r59781  
    55
    66/*
    7  * Copyright (C) 2006-2016 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3838#include <errno.h>
    3939#include <Strsafe.h>
    40 #ifndef IPRT_TARGET_NT4
    41 # include <LsaLookup.h>
    42 #endif
    4340#include <Lmcons.h>
    44 
    45 #ifndef IPRT_TARGET_NT4
    46 # define _NTDEF_ /* Prevents redefining (P)UNICODE_STRING. */
    47 # include <Ntsecapi.h>
    48 #endif
    4941
    5042#include <iprt/process.h>
     
    114106    HANDLE          hProcess;
    115107}                  *g_paProcesses;
    116 
    117 /** Strucutre for storing a user's account info.
    118  *  Must be free'd with rtProcWinFreeAccountInfo(). */
    119 typedef struct RTPROCWINACCOUNTINFO
    120 {
    121     /** User name. */
    122     PRTUTF16        pwszUserName;
    123     /** Domain this account is tied to. Can be NULL if no domain is being used. */
    124     PRTUTF16        pwszDomain;
    125 } RTPROCWINACCOUNTINFO, *PRTPROCWINACCOUNTINFO;
    126108
    127109/** @name userenv.dll imports (we don't unload it).
     
    12881270
    12891271/**
    1290  * Extracts the user name + domain from a given UPN (User Principal Name, "[email protected]") or
    1291  * Down-Level Logon Name format ("example.com\\joedoe") string.
    1292  *
    1293  * @return  IPRT status code.
    1294  * @param   pwszString      Pointer to string to extract the account info from.
    1295  * @param   pAccountInfo    Where to store the parsed account info.
    1296  *                          Must be free'd with rtProcWinFreeAccountInfo().
    1297  */
    1298 static int rtProcWinParseAccountInfo(PRTUTF16 pwszString, PRTPROCWINACCOUNTINFO pAccountInfo)
    1299 {
    1300     AssertPtrReturn(pwszString,   VERR_INVALID_POINTER);
    1301     AssertPtrReturn(pAccountInfo, VERR_INVALID_POINTER);
    1302 
    1303     /*
    1304      * Note: UPN handling is defined in RFC 822. We only implement very rudimentary parsing for the user
    1305      *       name and domain fields though.
    1306      */
    1307     char *pszString;
    1308     int rc = RTUtf16ToUtf8(pwszString, &pszString);
    1309     if (RT_SUCCESS(rc))
    1310     {
    1311         do
    1312         {
    1313             /* UPN or FQDN handling needed? */
    1314             /** @todo Add more validation here as needed. Regular expressions would be nice. */
    1315             char *pszDelim = strchr(pszString, '@');
    1316             if (pszDelim) /* UPN name? */
    1317             {
    1318                 rc = RTStrToUtf16Ex(pszString, pszDelim - pszString, &pAccountInfo->pwszUserName, 0, NULL);
    1319                 if (RT_FAILURE(rc))
    1320                     break;
    1321 
    1322                 rc = RTStrToUtf16Ex(pszDelim + 1, RTSTR_MAX, &pAccountInfo->pwszDomain, 0, NULL);
    1323                 if (RT_FAILURE(rc))
    1324                     break;
    1325             }
    1326             else if (pszDelim = strchr(pszString, '\\')) /* FQDN name? */
    1327             {
    1328                 rc = RTStrToUtf16Ex(pszString, pszDelim - pszString, &pAccountInfo->pwszDomain, 0, NULL);
    1329                 if (RT_FAILURE(rc))
    1330                     break;
    1331 
    1332                 rc = RTStrToUtf16Ex(pszDelim + 1, RTSTR_MAX, &pAccountInfo->pwszUserName, 0, NULL);
    1333                 if (RT_FAILURE(rc))
    1334                     break;
    1335             }
    1336             else
    1337                 rc = VERR_NOT_SUPPORTED;
    1338 
    1339         } while (0);
    1340 
    1341         RTStrFree(pszString);
    1342     }
    1343 
    1344 #ifdef DEBUG
    1345     LogRelFunc(("Name  : %ls\n", pAccountInfo->pwszUserName));
    1346     LogRelFunc(("Domain: %ls\n", pAccountInfo->pwszDomain));
    1347 #endif
    1348 
    1349     if (RT_FAILURE(rc))
    1350         LogRelFunc(("Parsing \"%ls\" failed with rc=%Rrc\n", pwszString, rc));
    1351     return rc;
    1352 }
    1353 
    1354 
    1355 static void rtProcWinFreeAccountInfo(PRTPROCWINACCOUNTINFO pAccountInfo)
    1356 {
    1357     if (!pAccountInfo)
    1358         return;
    1359 
    1360     if (pAccountInfo->pwszUserName)
    1361     {
    1362         RTUtf16Free(pAccountInfo->pwszUserName);
    1363         pAccountInfo->pwszUserName = NULL;
    1364     }
    1365 
    1366     if (pAccountInfo->pwszDomain)
    1367     {
    1368         RTUtf16Free(pAccountInfo->pwszDomain);
    1369         pAccountInfo->pwszDomain = NULL;
    1370     }
    1371 }
    1372 
    1373 
    1374 /**
    13751272 * Method \#2.
    13761273 */
     
    14231320        if (fFlags & RTPROC_FLAGS_SERVICE)
    14241321        {
    1425             PSID pSid = NULL;
    1426 
    14271322            /* Try query the SID and domain sizes first. */
    1428             DWORD        cbSid      = 0; /* Must be zero to query size! */
    1429             DWORD        cwcDomain  = 0;
    1430             SID_NAME_USE SidNameUse = SidTypeUser;
     1323            DWORD           cbSid      = 0; /* Must be zero to query size! */
     1324            DWORD           cwcDomain  = 0;
     1325            SID_NAME_USE    SidNameUse = SidTypeUser;
    14311326            fRc = LookupAccountNameW(NULL, pwszUser, NULL, &cbSid, NULL, &cwcDomain, &SidNameUse);
    1432             if (!fRc)
    1433             {
    1434                 dwErr = GetLastError();
    1435 
    1436 #ifndef IPRT_TARGET_NT4
    1437                 /*
    1438                  * The errors ERROR_TRUSTED_DOMAIN_FAILURE and ERROR_TRUSTED_RELATIONSHIP_FAILURE
    1439                  * can happen if an ADC (Active Domain Controller) is offline or not reachable.
    1440                  *
    1441                  * Try to handle these errors gracefully by asking the local LSA cache of the
    1442                  * client OS instead then. For this to work, the desired user must have at
    1443                  * least logged in once at that client -- otherwise there will be no cached
    1444                  * authentication available and this fallback will fail.
    1445                  */
    1446                 if (   dwErr == ERROR_TRUSTED_DOMAIN_FAILURE
    1447                     || dwErr == ERROR_TRUSTED_RELATIONSHIP_FAILURE)
     1327
     1328            /* Allocate memory for the LookupAccountNameW output buffers and do it for real. */
     1329            cbSid = fRc && cbSid != 0 ? cbSid + 16 : _1K;
     1330            PSID pSid = (PSID)RTMemAllocZ(cbSid);
     1331            if (pSid)
     1332            {
     1333                cwcDomain = fRc ? cwcDomain + 2 : _4K;
     1334                PRTUTF16 pwszDomain = (PRTUTF16)RTMemAllocZ(cwcDomain * sizeof(RTUTF16));
     1335                if (pwszDomain)
    14481336                {
    1449                     LSA_OBJECT_ATTRIBUTES objAttr;
    1450                     RT_ZERO(objAttr);
    1451                     objAttr.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
    1452 
    1453                     LSA_HANDLE lsahPolicy;
    1454                     NTSTATUS ntSts = LsaOpenPolicy(NULL, &objAttr, POLICY_LOOKUP_NAMES, &lsahPolicy);
    1455                     if (ntSts == STATUS_SUCCESS)
     1337                    /* Note: Just pass in the UPN (User Principal Name), e.g. [email protected] */
     1338                    if (LookupAccountNameW(NULL /*lpSystemName*/, pwszUser, pSid, &cbSid, pwszDomain, &cwcDomain, &SidNameUse))
    14561339                    {
    1457                         RTPROCWINACCOUNTINFO accountInfo;
    1458                         RT_ZERO(accountInfo);
    1459                         rc = rtProcWinParseAccountInfo(pwszUser, &accountInfo);
    1460                         AssertRC(rc);
    1461                         AssertPtr(accountInfo.pwszUserName);
    1462 
    1463                         LSA_UNICODE_STRING lsaUser;
    1464                         lsaUser.Buffer        = accountInfo.pwszUserName;
    1465                         lsaUser.Length        = (USHORT)(RTUtf16Len(accountInfo.pwszUserName) * sizeof(WCHAR));
    1466                         lsaUser.MaximumLength = lsaUser.Length;
    1467 
    1468                         PLSA_REFERENCED_DOMAIN_LIST pDomainList     = NULL;
    1469                         PLSA_TRANSLATED_SID2        pTranslatedSids = NULL;
    1470                         ntSts = LsaLookupNames2(lsahPolicy, 0 /* Flags */,
    1471                                                 1 /* Number of users to lookup */, &lsaUser, &pDomainList, &pTranslatedSids);
    1472                         if (ntSts == STATUS_SUCCESS)
     1340                        if (IsValidSid(pSid))
    14731341                        {
    1474                             AssertPtr(pDomainList);
    1475                             AssertPtr(pTranslatedSids);
    1476 #ifdef DEBUG
    1477                             LogRelFunc(("LsaLookupNames2: cDomains=%u, DomainIndex=%ld, SidUse=%ld\n",
    1478                                         pDomainList->Entries, pTranslatedSids[0].DomainIndex, pTranslatedSids[0].Use));
     1342                            /* Array of process names we want to look for. */
     1343                            static const char * const s_papszProcNames[] =
     1344                            {
     1345#ifdef VBOX                     /* The explorer entry is a fallback in case GA aren't installed. */
     1346                                { "VBoxTray.exe" },
    14791347#endif
    1480                             Assert(pTranslatedSids[0].Use == SidTypeUser);
    1481 
    1482                             if (pDomainList->Entries)
    1483                             {
    1484                                 AssertPtr(pDomainList->Domains);
    1485                                 LogRelFunc(("LsaLookupNames2: Domain=%ls\n",
    1486                                             pDomainList->Domains[pTranslatedSids[0].DomainIndex].Name.Buffer));
    1487                             }
    1488 
    1489                             cbSid = GetLengthSid(pTranslatedSids->Sid) + 16;
    1490                             Assert(cbSid);
    1491                             pSid = (PSID)RTMemAllocZ(cbSid);
    1492                             if (!CopySid(cbSid, pSid, pTranslatedSids->Sid))
    1493                             {
    1494                                 dwErr = GetLastError();
    1495                                 LogRelFunc(("CopySid failed with: %ld\n", dwErr));
    1496                                 rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    1497                             }
     1348                                { "explorer.exe" },
     1349                                NULL
     1350                            };
     1351                            fFound = rtProcWinFindTokenByProcess(s_papszProcNames, pSid, &hTokenUserDesktop);
    14981352                        }
    14991353                        else
    15001354                        {
    1501                             dwErr = LsaNtStatusToWinError(ntSts);
    1502                             LogRelFunc(("LsaLookupNames2 failed with: %ld\n", dwErr));
    1503                             rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
     1355                            dwErr = GetLastError();
     1356                            rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_4;
    15041357                        }
    1505 
    1506                         if (pDomainList)
    1507                         {
    1508                             LsaFreeMemory(pDomainList);
    1509                             pDomainList = NULL;
    1510                         }
    1511                         if (pTranslatedSids)
    1512                         {
    1513                             LsaFreeMemory(pTranslatedSids);
    1514                             pTranslatedSids = NULL;
    1515                         }
    1516 
    1517                         rtProcWinFreeAccountInfo(&accountInfo);
    1518                         LsaClose(lsahPolicy);
    15191358                    }
    15201359                    else
    15211360                    {
    1522                         dwErr = LsaNtStatusToWinError(ntSts);
    1523                         LogRelFunc(("LsaOpenPolicy failed with: %ld\n", dwErr));
     1361                        dwErr = GetLastError();
    15241362                        rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_3;
    15251363                    }
    1526 
    1527                     /* Note: pSid will be free'd down below. */
     1364                    RTMemFree(pwszDomain);
    15281365                }
    15291366                else
    1530 #endif /* !IPRT_TARGET_NT4 */
    1531                 if (dwErr == ERROR_INSUFFICIENT_BUFFER)
    1532                 {
    1533                     /* Allocate memory for the LookupAccountNameW output buffers and do it for real. */
    1534                     cbSid = fRc && cbSid != 0 ? cbSid + 16 : _1K;
    1535                     pSid = (PSID)RTMemAllocZ(cbSid);
    1536                     if (pSid)
    1537                     {
    1538                         cwcDomain = fRc ? cwcDomain + 2 : _4K;
    1539                         PRTUTF16 pwszDomain = (PRTUTF16)RTMemAllocZ(cwcDomain * sizeof(RTUTF16));
    1540                         if (pwszDomain)
    1541                         {
    1542                             /* Note: Just pass in the UPN (User Principal Name), e.g. [email protected] */
    1543                             if (!LookupAccountNameW(NULL /*lpSystemName*/, pwszUser, pSid, &cbSid, pwszDomain, &cwcDomain,
    1544                                                     &SidNameUse))
    1545                             {
    1546                                 dwErr = GetLastError();
    1547                                 LogRelFunc(("LookupAccountNameW(2) failed with: %ld\n", dwErr));
    1548                                 rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_4;
    1549                             }
    1550 
    1551                             RTMemFree(pwszDomain);
    1552                         }
    1553                         else
    1554                             rc = VERR_NO_MEMORY;
    1555 
    1556                         /* Note: pSid will be free'd down below. */
    1557                     }
    1558                     else
    1559                         rc = VERR_NO_MEMORY;
    1560                 }
    1561                 else
    1562                 {
    1563                     LogRelFunc(("LookupAccountNameW(1) failed with: %ld\n", dwErr));
    1564                     rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    1565                 }
    1566             }
    1567 
    1568             if (pSid)
    1569             {
    1570                 if (IsValidSid(pSid))
    1571                 {
    1572                     /* Array of process names we want to look for. */
    1573                     static const char * const s_papszProcNames[] =
    1574                     {
    1575 #ifdef VBOX             /* The explorer entry is a fallback in case GA aren't installed. */
    1576                         { "VBoxTray.exe" },
    1577 #endif
    1578                         { "explorer.exe" },
    1579                         NULL
    1580                     };
    1581                     fFound = rtProcWinFindTokenByProcess(s_papszProcNames, pSid, &hTokenUserDesktop);
    1582                     dwErr  = 0;
    1583                 }
    1584                 else
    1585                 {
    1586                     dwErr = GetLastError();
    1587                     LogRelFunc(("SID is invalid: %ld\n", dwErr));
    1588                     rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_3;
    1589                 }
     1367                    rc = VERR_NO_MEMORY;
    15901368
    15911369                RTMemFree(pSid);
    15921370            }
     1371            else
     1372                rc = VERR_NO_MEMORY;
    15931373        }
    15941374        /* else: !RTPROC_FLAGS_SERVICE: Nothing to do here right now. */
     
    17251505            LogRelFunc(("dwErr=%u (%#x), rc=%Rrc\n", dwErr, dwErr, rc));
    17261506    }
    1727 
    17281507    return rc;
    17291508}
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