Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3483 lines
105 KiB

  1. //*************************************************************
  2. //
  3. // Group Policy Support - Queries about the Policies
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1997-1998
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "gphdr.h"
  11. //*************************************************************
  12. //
  13. // AddGPO()
  14. //
  15. // Purpose: Adds a GPO to the list
  16. //
  17. // Parameters: lpGPOList - list of GPOs
  18. // dwFlags - Flags
  19. // bFound - Was Gpo found ?
  20. // bAccessGranted - Was access granted ?
  21. // bDisabled - Is this Gpo disabled ?
  22. // dwOptions - Options
  23. // dwVersion - Version number
  24. // lpDSPath - DS path
  25. // lpFileSysPath - File system path
  26. // lpDisplayName - Friendly display name
  27. // lpGPOName - GPO name
  28. // lpExtensions - Extensions relevant to this GPO
  29. // lpDSObject - LSDOU
  30. // pSD - Ptr to security descriptor
  31. // cbSDLen - Length of security descriptor in bytes
  32. // GPOLink - GPO link type
  33. // lpLink - SDOU this GPO is linked to
  34. // lParam - lParam
  35. // bFront - Head or end of list
  36. // bBlock - Block from above flag
  37. // bVerbose - Verbose output flag
  38. //
  39. //
  40. // Return: TRUE if successful
  41. // FALSE if an error occurs
  42. //
  43. //*************************************************************
  44. BOOL AddGPO (PGROUP_POLICY_OBJECT * lpGPOList,
  45. DWORD dwFlags, BOOL bFound, BOOL bAccessGranted, BOOL bDisabled, DWORD dwOptions,
  46. DWORD dwVersion, LPTSTR lpDSPath, LPTSTR lpFileSysPath,
  47. LPTSTR lpDisplayName, LPTSTR lpGPOName, LPTSTR lpExtensions,
  48. PSECURITY_DESCRIPTOR pSD, DWORD cbSDLen,
  49. GPO_LINK GPOLink, LPTSTR lpLink,
  50. LPARAM lParam, BOOL bFront, BOOL bBlock, BOOL bVerbose, BOOL bProcessGPO)
  51. {
  52. PGROUP_POLICY_OBJECT lpNew, lpTemp;
  53. DWORD dwSize;
  54. //
  55. // Check if this item should be excluded from the list
  56. //
  57. if (bBlock) {
  58. if (!(dwOptions & GPO_FLAG_FORCE)) {
  59. DebugMsg((DM_VERBOSE, TEXT("AddGPO: GPO %s will not be added to the list since the Block flag is set and this GPO is not in enforce mode."),
  60. lpDisplayName));
  61. if (bVerbose) {
  62. CEvents ev(FALSE, EVENT_SKIP_GPO);
  63. ev.AddArg(lpDisplayName); ev.Report();
  64. }
  65. if (dwFlags & GP_PLANMODE) {
  66. DebugMsg((DM_VERBOSE, TEXT("AddGPO: GPO %s will will still be queried for since this is planning mode."),
  67. lpDisplayName));
  68. bProcessGPO = FALSE;
  69. }
  70. else
  71. return TRUE;
  72. }
  73. }
  74. //
  75. // Calculate the size of the new GPO item
  76. //
  77. dwSize = sizeof (GROUP_POLICY_OBJECT);
  78. if (lpDSPath) {
  79. dwSize += ((lstrlen(lpDSPath) + 1) * sizeof(TCHAR));
  80. }
  81. if (lpFileSysPath) {
  82. dwSize += ((lstrlen(lpFileSysPath) + 1) * sizeof(TCHAR));
  83. }
  84. if (lpDisplayName) {
  85. dwSize += ((lstrlen(lpDisplayName) + 1) * sizeof(TCHAR));
  86. }
  87. if (lpExtensions) {
  88. dwSize += ((lstrlen(lpExtensions) + 1) * sizeof(TCHAR));
  89. }
  90. if (lpLink) {
  91. dwSize += ((lstrlen(lpLink) + 1) * sizeof(TCHAR));
  92. }
  93. dwSize += sizeof(GPOPROCDATA);
  94. //
  95. // Allocate space for it
  96. //
  97. lpNew = (PGROUP_POLICY_OBJECT) LocalAlloc (LPTR, dwSize);
  98. if (!lpNew) {
  99. DebugMsg((DM_WARNING, TEXT("AddGPO: Failed to allocate memory with %d"),
  100. GetLastError()));
  101. return FALSE;
  102. }
  103. //
  104. // Fill in item
  105. //
  106. LPGPOPROCDATA lpGpoProcData;
  107. lpNew->lParam2 = (LPARAM)(((LPBYTE)lpNew) + sizeof(GROUP_POLICY_OBJECT));
  108. lpGpoProcData = (LPGPOPROCDATA)lpNew->lParam2;
  109. lpGpoProcData->bProcessGPO = bProcessGPO;
  110. lpNew->dwOptions = dwOptions;
  111. lpNew->dwVersion = dwVersion;
  112. if (lpDSPath) {
  113. lpNew->lpDSPath = (LPTSTR)(((LPBYTE)lpNew) + sizeof(GROUP_POLICY_OBJECT) + sizeof(GPOPROCDATA));
  114. lstrcpy (lpNew->lpDSPath, lpDSPath);
  115. }
  116. if (lpFileSysPath) {
  117. if (lpDSPath) {
  118. lpNew->lpFileSysPath = lpNew->lpDSPath + lstrlen (lpNew->lpDSPath) + 1;
  119. } else {
  120. lpNew->lpFileSysPath = (LPTSTR)(((LPBYTE)lpNew) + sizeof(GROUP_POLICY_OBJECT) + sizeof(GPOPROCDATA));
  121. }
  122. lstrcpy (lpNew->lpFileSysPath, lpFileSysPath);
  123. }
  124. if (lpDisplayName) {
  125. if (lpFileSysPath) {
  126. lpNew->lpDisplayName = lpNew->lpFileSysPath + lstrlen (lpNew->lpFileSysPath) + 1;
  127. } else {
  128. if (lpDSPath)
  129. {
  130. lpNew->lpDisplayName = lpNew->lpDSPath + lstrlen (lpNew->lpDSPath) + 1;
  131. }
  132. else
  133. {
  134. lpNew->lpDisplayName = (LPTSTR)(((LPBYTE)lpNew) + sizeof(GROUP_POLICY_OBJECT) + sizeof(GPOPROCDATA));
  135. }
  136. }
  137. lstrcpy (lpNew->lpDisplayName, lpDisplayName);
  138. }
  139. if (lpGPOName) {
  140. DmAssert( lstrlen(lpGPOName) < 50 );
  141. lstrcpy (lpNew->szGPOName, lpGPOName);
  142. }
  143. if (lpExtensions) {
  144. if (lpDisplayName) {
  145. lpNew->lpExtensions = lpNew->lpDisplayName + lstrlen(lpNew->lpDisplayName) + 1;
  146. } else {
  147. if (lpFileSysPath) {
  148. lpNew->lpExtensions = lpNew->lpFileSysPath + lstrlen(lpNew->lpFileSysPath) + 1;
  149. } else {
  150. if (lpDSPath) {
  151. lpNew->lpExtensions = lpNew->lpDSPath + lstrlen(lpNew->lpDSPath) + 1;
  152. } else {
  153. lpNew->lpExtensions = (LPTSTR)(((LPBYTE)lpNew) + sizeof(GROUP_POLICY_OBJECT) + sizeof(GPOPROCDATA));
  154. }
  155. }
  156. }
  157. lstrcpy (lpNew->lpExtensions, lpExtensions);
  158. }
  159. if (lpLink) {
  160. if (lpExtensions) {
  161. lpNew->lpLink = lpNew->lpExtensions + lstrlen(lpNew->lpExtensions) + 1;
  162. } else {
  163. if (lpDisplayName) {
  164. lpNew->lpLink = lpNew->lpDisplayName + lstrlen(lpNew->lpDisplayName) + 1;
  165. } else {
  166. if (lpFileSysPath) {
  167. lpNew->lpLink = lpNew->lpFileSysPath + lstrlen(lpNew->lpFileSysPath) + 1;
  168. } else {
  169. if (lpDSPath) {
  170. lpNew->lpLink = lpNew->lpDSPath + lstrlen(lpNew->lpDSPath) + 1;
  171. } else {
  172. lpNew->lpLink = (LPTSTR)(((LPBYTE)lpNew) + sizeof(GROUP_POLICY_OBJECT) + sizeof(GPOPROCDATA));
  173. }
  174. }
  175. }
  176. }
  177. lstrcpy (lpNew->lpLink, lpLink);
  178. }
  179. lpNew->GPOLink = GPOLink;
  180. lpNew->lParam = lParam;
  181. //
  182. // Add item to link list
  183. //
  184. if (*lpGPOList) {
  185. if (bFront) {
  186. (*lpGPOList)->pPrev = lpNew;
  187. lpNew->pNext = *lpGPOList;
  188. *lpGPOList = lpNew;
  189. } else {
  190. lpTemp = *lpGPOList;
  191. while (lpTemp->pNext != NULL) {
  192. lpTemp = lpTemp->pNext;
  193. }
  194. lpTemp->pNext = lpNew;
  195. lpNew->pPrev = lpTemp;
  196. }
  197. } else {
  198. //
  199. // First item in the list
  200. //
  201. *lpGPOList = lpNew;
  202. }
  203. return TRUE;
  204. }
  205. //*************************************************************
  206. //
  207. // AddGPOToRsopList
  208. //
  209. // Purpose: Adds GPO to list of GPOs being logged by Rsop
  210. //
  211. // Parameters: ppGpContainerList - List of Gp Containers
  212. // dwFlags - Flags
  213. // bFound - Was Gpo found ?
  214. // bAccessGranted - Was access granted ?
  215. // bDisabled - Is this Gpo disabled ?
  216. // dwOptions - Options
  217. // dwVersion - Version number
  218. // lpDSPath - DS path
  219. // lpFileSysPath - File system path
  220. // lpDisplayName - Friendly display name
  221. // lpGPOName - GPO name
  222. // pSD - Pointer to security descriptor
  223. // cbSDLen - Length of security descriptor in bytes
  224. // bFilterAllowed - Does GPO pass filter check
  225. // pwszFilterId - WQL filter id
  226. // szSOM - SOM
  227. // dwGPOOptions - GPO options
  228. //
  229. //*************************************************************
  230. BOOL AddGPOToRsopList( LPGPCONTAINER *ppGpContainerList,
  231. DWORD dwFlags,
  232. BOOL bFound,
  233. BOOL bAccessGranted,
  234. BOOL bDisabled,
  235. DWORD dwVersion,
  236. LPTSTR lpDSPath,
  237. LPTSTR lpFileSysPath,
  238. LPTSTR lpDisplayName,
  239. LPTSTR lpGPOName,
  240. PSECURITY_DESCRIPTOR pSD,
  241. DWORD cbSDLen,
  242. BOOL bFilterAllowed,
  243. WCHAR *pwszFilterId,
  244. LPWSTR szSOM,
  245. DWORD dwOptions)
  246. {
  247. GPCONTAINER *pGpContainer = AllocGpContainer( dwFlags,
  248. bFound,
  249. bAccessGranted,
  250. bDisabled,
  251. dwVersion,
  252. lpDSPath,
  253. lpFileSysPath,
  254. lpDisplayName,
  255. lpGPOName,
  256. pSD,
  257. cbSDLen,
  258. bFilterAllowed,
  259. pwszFilterId,
  260. szSOM,
  261. dwOptions );
  262. if ( pGpContainer == NULL ) {
  263. DebugMsg((DM_VERBOSE, TEXT("AddGPO: Failed to allocate memory for Gp Container.")));
  264. return FALSE;
  265. }
  266. //
  267. // Prepend to GpContainer list
  268. //
  269. pGpContainer->pNext = *ppGpContainerList;
  270. *ppGpContainerList = pGpContainer;
  271. return TRUE;
  272. }
  273. //*************************************************************
  274. //
  275. // AddLocalGPO()
  276. //
  277. // Purpose: Adds a local Gpo to the list of SOMs
  278. //
  279. // Parameters: ppSOMList - List of SOMs
  280. //
  281. //*************************************************************
  282. BOOL AddLocalGPO( LPSCOPEOFMGMT *ppSOMList )
  283. {
  284. GPLINK *pGpLink = NULL;
  285. XLastError xe;
  286. SCOPEOFMGMT *pSOM = AllocSOM( L"Local" );
  287. if ( pSOM == NULL ) {
  288. DebugMsg((DM_WARNING, TEXT("AddLocalGPO: Unable to allocate memory for SOM object")));
  289. return FALSE;
  290. }
  291. pSOM->dwType = GPLinkMachine;
  292. // Local GPO cannot be blocked from above
  293. pGpLink = AllocGpLink( L"LocalGPO", 0 );
  294. if ( pGpLink == NULL ) {
  295. xe = GetLastError();
  296. DebugMsg((DM_WARNING, TEXT("AddLocalGPO: Unable to allocate memory for GpLink object")));
  297. FreeSOM( pSOM );
  298. return FALSE;
  299. }
  300. pSOM->pGpLinkList = pGpLink;
  301. pSOM->pNext = *ppSOMList;
  302. *ppSOMList = pSOM;
  303. return TRUE;
  304. }
  305. //*************************************************************
  306. //
  307. // ProcessGPO()
  308. //
  309. // Purpose: Processes a specific GPO
  310. //
  311. // Parameters: lpGPOPath - Path to the GPO
  312. // lpDSPath - DS object
  313. // dwFlags - GetGPOList flags
  314. // HANDLE - user or machine aceess token
  315. // lpGPOList - List of GPOs
  316. // ppGpContainerList - List of Gp containers
  317. // dwGPOOptions - Link options
  318. // bDeferred - Should ldap query be deferred ?
  319. // bVerbose - Verbose output
  320. // GPOLink - GPO link type
  321. // lpDSObject - SDOU this gpo is linked to
  322. // pld - LDAP info
  323. // pLDAP - LDAP api
  324. // pLdapMsg - LDAP message
  325. // bBlock - Block flag
  326. // bRsopToken - Rsop security token
  327. // pGpoFilter - Gpo filter
  328. // pLocator - WMI interface class
  329. // bAddGPO - In planning mode we want to get the gpodata even if
  330. // the GPO is not going to be applied
  331. //
  332. //
  333. // Return: TRUE if successful
  334. // FALSE if an error occurs
  335. //
  336. //*************************************************************
  337. BOOL ProcessGPO(LPTSTR lpGPOPath,
  338. DWORD dwFlags,
  339. HANDLE hToken,
  340. PGROUP_POLICY_OBJECT *lpGPOList,
  341. LPGPCONTAINER *ppGpContainerList,
  342. DWORD dwGPOOptions,
  343. BOOL bDeferred,
  344. BOOL bVerbose,
  345. GPO_LINK GPOLink,
  346. LPTSTR lpDSObject,
  347. PLDAP pld,
  348. PLDAP_API pLDAP,
  349. PLDAPMessage pMessage,
  350. BOOL bBlock,
  351. PRSOPTOKEN pRsopToken,
  352. CGpoFilter *pGpoFilter,
  353. CLocator *pLocator,
  354. BOOL bProcessGPO )
  355. {
  356. ULONG ulResult, i;
  357. BOOL bResult = FALSE;
  358. BOOL bFound = FALSE;
  359. BOOL bOwnLdapMsg = FALSE; // LDAP message owned by us (if true) or caller (if false)
  360. BOOL bAccessGranted;
  361. DWORD dwFunctionalityVersion = 2;
  362. DWORD dwVersion = 0;
  363. DWORD dwGPOFlags = 0;
  364. DWORD dwGPTVersion = 0;
  365. TCHAR szGPOName[80];
  366. TCHAR *pszGPTPath = 0;
  367. TCHAR *pszFriendlyName = 0;
  368. LPTSTR lpPath, lpEnd, lpTemp;
  369. TCHAR *pszExtensions = 0;
  370. TCHAR szLDAP[] = TEXT("LDAP://");
  371. INT iStrLen = lstrlen(szLDAP);
  372. BYTE berValue[8];
  373. LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR)berValue }, TRUE };
  374. LDAPControl referralControl = { LDAP_SERVER_DOMAIN_SCOPE_OID_W, { 0, NULL}, TRUE };
  375. PLDAPControl ServerControls[] = { &SeInfoControl, &referralControl, NULL };
  376. TCHAR szSDProperty[] = TEXT("nTSecurityDescriptor");
  377. TCHAR szCommonName[] = TEXT("cn");
  378. TCHAR szDisplayName[] = TEXT("displayName");
  379. TCHAR szFileSysPath[] = TEXT("gPCFileSysPath");
  380. TCHAR szVersion[] = TEXT("versionNumber");
  381. TCHAR szFunctionalityVersion[] = GPO_FUNCTIONALITY_VERSION;
  382. TCHAR szFlags[] = TEXT("flags");
  383. TCHAR szWmiFilter[] = TEXT("gPCWQLFilter");
  384. PWSTR rgAttribs[12] = {szSDProperty,
  385. szFileSysPath,
  386. szCommonName,
  387. szDisplayName,
  388. szVersion,
  389. szFunctionalityVersion,
  390. szFlags,
  391. GPO_MACHEXTENSION_NAMES,
  392. GPO_USEREXTENSION_NAMES,
  393. szObjectClass,
  394. szWmiFilter,
  395. NULL };
  396. LPTSTR *lpValues;
  397. PSECURITY_DESCRIPTOR pSD = NULL; // Security Descriptor
  398. DWORD cbSDLen = 0; // Length of security descriptor in bytes
  399. BOOL bRsopLogging = (ppGpContainerList != NULL);
  400. BOOL bOldGpoVersion = FALSE;
  401. BOOL bDisabled = FALSE;
  402. BOOL bNoGpoData = FALSE;
  403. BOOL bFilterAllowed = FALSE;
  404. WCHAR *pwszFilterId = NULL;
  405. XLastError xe;
  406. //
  407. // Verbose output
  408. //
  409. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: ==============================")));
  410. //
  411. // Skip the starting LDAP provider if found
  412. //
  413. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  414. lpGPOPath, iStrLen, szLDAP, iStrLen) == CSTR_EQUAL)
  415. {
  416. lpPath = lpGPOPath + iStrLen;
  417. }
  418. else
  419. {
  420. lpPath = lpGPOPath;
  421. }
  422. if ( bDeferred )
  423. {
  424. bResult = AddGPO (lpGPOList, dwFlags, TRUE, TRUE, FALSE, dwGPOOptions, 0, lpPath,
  425. 0, 0, 0, 0, 0, 0, GPOLink, lpDSObject, 0,
  426. FALSE, bBlock, bVerbose, bProcessGPO);
  427. if (!bResult)
  428. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Failed to add GPO <%s> to the list."), lpPath));
  429. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Deferring search for <%s>"), lpGPOPath));
  430. return bResult;
  431. }
  432. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Searching <%s>"), lpGPOPath));
  433. //
  434. // Check if this user or machine has access to the GPO, and if so,
  435. // should that GPO be applied to them.
  436. //
  437. if (!CheckGPOAccess (pld, pLDAP, hToken, pMessage, szSDProperty, dwFlags, &pSD, &cbSDLen, &bAccessGranted, pRsopToken)) {
  438. xe = GetLastError();
  439. DebugMsg((DM_WARNING, TEXT("ProcessGPO: CheckGPOAccess failed for <%s>"), lpGPOPath));
  440. CEvents ev(TRUE, EVENT_FAILED_ACCESS_CHECK);
  441. ev.AddArg(lpGPOPath); ev.AddArgWin32Error(GetLastError()); ev.Report();
  442. goto Exit;
  443. }
  444. if (!bAccessGranted) {
  445. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  446. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Machine does not have access to the GPO and so will not be applied.")));
  447. } else {
  448. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: User does not have access to the GPO and so will not be applied.")));
  449. }
  450. if (bVerbose) {
  451. CEvents ev(FALSE, EVENT_NO_ACCESS);
  452. ev.AddArg(lpGPOPath); ev.Report();
  453. }
  454. bResult = TRUE; // GPO is not getting applied
  455. if ( !bRsopLogging ) {
  456. goto Exit;
  457. }
  458. } else {
  459. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  460. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Machine has access to this GPO.")));
  461. } else {
  462. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: User has access to this GPO.")));
  463. }
  464. }
  465. // only if access is granted will we eval WQL filters
  466. if ( bAccessGranted ) {
  467. if (!FilterCheck(pld, pLDAP, pMessage, pRsopToken, szWmiFilter, pGpoFilter, pLocator, &bFilterAllowed, &pwszFilterId ) ) {
  468. xe = GetLastError();
  469. if (xe == WBEM_E_NOT_FOUND) {
  470. DebugMsg((DM_WARNING, TEXT("ProcessGPO: CheckFilterAcess failed for <%s>. Filter not found"), lpGPOPath));
  471. CEvents ev(TRUE, EVENT_WMIFILTER_NOTFOUND);
  472. ev.AddArg(lpGPOPath); ev.Report();
  473. bFilterAllowed = FALSE;
  474. }
  475. else if (xe == HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED)) {
  476. DebugMsg((DM_WARNING, TEXT("ProcessGPO: CheckFilterAcess failed for <%s>. WMI service is disabled"), lpGPOPath));
  477. CEvents ev(TRUE, EVENT_WMIFILTER_NOTFOUND);
  478. ev.AddArg(lpGPOPath); ev.Report();
  479. bFilterAllowed = FALSE;
  480. }
  481. else {
  482. DebugMsg((DM_WARNING, TEXT("ProcessGPO: CheckFilterAcess failed for <%s>"), lpGPOPath));
  483. CEvents ev(TRUE, EVENT_FAILED_FILTER_CHECK);
  484. ev.AddArg(lpGPOPath); ev.Report();
  485. goto Exit;
  486. }
  487. }
  488. if ( (dwFlags & GP_PLANMODE) && (dwFlags & GPO_LIST_FLAG_MACHINE) && (dwFlags & FLAG_ASSUME_COMP_WQLFILTER_TRUE) ) {
  489. bFilterAllowed = TRUE;
  490. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Machine WQL filter is assumed to be true.")));
  491. }
  492. else if ( (dwFlags & GP_PLANMODE) && ((dwFlags & GPO_LIST_FLAG_MACHINE) == 0) && (dwFlags & FLAG_ASSUME_USER_WQLFILTER_TRUE) ) {
  493. bFilterAllowed = TRUE;
  494. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: User WQL filter is assumed to be true.")));
  495. }
  496. if (!bFilterAllowed)
  497. {
  498. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: The GPO does not pass the filter check and so will not be applied.")));
  499. if (bVerbose) {
  500. CEvents ev(FALSE, EVENT_NO_FILTER_ALLOWED);
  501. ev.AddArg(lpGPOPath); ev.Report();
  502. }
  503. bResult = TRUE; // GPO is not getting applied
  504. if ( !bRsopLogging ) {
  505. goto Exit;
  506. }
  507. } else {
  508. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: GPO passes the filter check.")));
  509. }
  510. }
  511. else {
  512. bFilterAllowed = FALSE;
  513. }
  514. //
  515. // Either user has access to this GPO, or Rsop logging is enabled so retrieve remaining GPO attributes
  516. //
  517. //
  518. // Check if this object is a GPO
  519. //
  520. lpValues = pLDAP->pfnldap_get_values(pld, pMessage, szObjectClass);
  521. if (lpValues) {
  522. bFound = FALSE;
  523. for ( i=0; lpValues[i] != NULL; i++) {
  524. if ( lstrcmp( lpValues[i], szDSClassGPO ) == 0 ) {
  525. bFound = TRUE;
  526. break;
  527. }
  528. }
  529. pLDAP->pfnldap_value_free (lpValues);
  530. if ( !bFound ) {
  531. xe = ERROR_DS_MISSING_REQUIRED_ATT;
  532. // seems like objectclass=dsgpo is required attr
  533. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Object <%s> is not a GPO"), lpGPOPath ));
  534. CEvents ev(TRUE, EVENT_INCORRECT_CLASS);
  535. ev.AddArg(lpGPOPath); ev.AddArg(szDSClassGPO); ev.Report();
  536. goto Exit;
  537. }
  538. }
  539. //
  540. // In the results, get the values that match the gPCFunctionalityVersion attribute
  541. //
  542. lpValues = pLDAP->pfnldap_get_values(pld, pMessage, szFunctionalityVersion);
  543. if (lpValues) {
  544. dwFunctionalityVersion = StringToInt (*lpValues);
  545. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found functionality version of: %d"),
  546. dwFunctionalityVersion));
  547. pLDAP->pfnldap_value_free (lpValues);
  548. } else {
  549. ulResult = pLDAP->pfnLdapGetLastError();
  550. if (ulResult == LDAP_NO_SUCH_ATTRIBUTE) {
  551. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  552. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Machine does not have access to <%s>"), lpGPOPath));
  553. } else {
  554. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: User does not have access to <%s>"), lpGPOPath));
  555. }
  556. if (bVerbose) {
  557. CEvents ev(FALSE, EVENT_NO_ACCESS);
  558. ev.AddArg(lpGPOPath); ev.Report();
  559. }
  560. bResult = TRUE;
  561. } else {
  562. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  563. DebugMsg((DM_WARNING, TEXT("ProcessGPO: GPO %s does not have a functionality version number, error = 0x%x."), lpGPOPath, ulResult));
  564. CEvents ev(TRUE, EVENT_CORRUPT_GPO_FUNCVERSION);
  565. ev.AddArg(lpGPOPath); ev.Report();
  566. }
  567. goto Exit;
  568. }
  569. //
  570. // In the results, get the values that match the gPCFileSystemPath attribute
  571. //
  572. lpValues = pLDAP->pfnldap_get_values (pld, pMessage, szFileSysPath);
  573. if (lpValues) {
  574. pszGPTPath = (LPWSTR) LocalAlloc( LPTR, (lstrlen(*lpValues) +lstrlen(TEXT("\\Machine")) +1) * sizeof(TCHAR) );
  575. if ( pszGPTPath == 0) {
  576. xe = GetLastError();
  577. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Unable to allocate memory")));
  578. pLDAP->pfnldap_value_free (lpValues);
  579. goto Exit;
  580. }
  581. lstrcpy (pszGPTPath, *lpValues);
  582. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found file system path of: <%s>"), pszGPTPath));
  583. pLDAP->pfnldap_value_free (lpValues);
  584. lpEnd = CheckSlash (pszGPTPath);
  585. //
  586. // Get the GPT version number
  587. //
  588. lstrcpy (lpEnd, TEXT("gpt.ini"));
  589. //
  590. // Skip access to sysvol if AGP or filtercheck fails
  591. //
  592. if (bAccessGranted && bFilterAllowed) {
  593. WIN32_FILE_ATTRIBUTE_DATA fad;
  594. //
  595. // Check for the existence of the gpt.ini file.
  596. //
  597. if (GetFileAttributesEx(pszGPTPath, GetFileExInfoStandard, &fad)) {
  598. dwGPTVersion = GetPrivateProfileInt(TEXT("General"), TEXT("Version"), 0, pszGPTPath);
  599. }
  600. else {
  601. xe = GetLastError();
  602. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Couldn't find the group policy template file <%s>, error = 0x%x."), pszGPTPath, GetLastError()));
  603. CEvents ev(TRUE, EVENT_GPT_NOTACCESSIBLE);
  604. ev.AddArg(lpGPOPath); ev.AddArg(pszGPTPath); ev.AddArgWin32Error(GetLastError()); ev.Report();
  605. goto Exit;
  606. }
  607. }
  608. else {
  609. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Sysvol access skipped because GPO is not getting applied.")));
  610. dwGPTVersion = 0xffffffff;
  611. }
  612. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  613. lstrcpy (lpEnd, TEXT("Machine"));
  614. } else {
  615. lstrcpy (lpEnd, TEXT("User"));
  616. }
  617. } else {
  618. ulResult = pLDAP->pfnLdapGetLastError();
  619. if (ulResult == LDAP_NO_SUCH_ATTRIBUTE) {
  620. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  621. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Machine does not have access to <%s>"), lpGPOPath));
  622. } else {
  623. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: User does not have access to <%s>"), lpGPOPath));
  624. }
  625. if (bVerbose) {
  626. CEvents ev(FALSE, EVENT_NO_ACCESS);
  627. ev.AddArg(lpGPOPath); ev.Report();
  628. }
  629. bResult = TRUE;
  630. } else {
  631. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  632. DebugMsg((DM_WARNING, TEXT("ProcessGPO: GPO %s does not have a file system path, error = 0x%x."), lpGPOPath, ulResult));
  633. CEvents ev(TRUE, EVENT_CORRUPT_GPO_FSPATH);
  634. ev.AddArg(lpGPOPath); ev.Report();
  635. }
  636. goto Exit;
  637. }
  638. //
  639. // In the results, get the values that match the common name attribute
  640. //
  641. lpValues = pLDAP->pfnldap_get_values(pld, pMessage, szCommonName);
  642. if (lpValues) {
  643. DmAssert( lstrlen(*lpValues) < 80 );
  644. lstrcpy (szGPOName, *lpValues);
  645. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found common name of: <%s>"), szGPOName));
  646. pLDAP->pfnldap_value_free (lpValues);
  647. } else {
  648. ulResult = pLDAP->pfnLdapGetLastError();
  649. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  650. DebugMsg((DM_WARNING, TEXT("ProcessGPO: GPO %s does not have a common name (a GUID)."), lpGPOPath));
  651. CEvents ev(TRUE, EVENT_CORRUPT_GPO_COMMONNAME);
  652. ev.AddArg(lpGPOPath); ev.Report();
  653. goto Exit;
  654. }
  655. //
  656. // In the results, get the values that match the display name attribute
  657. //
  658. lpValues = pLDAP->pfnldap_get_values(pld, pMessage, szDisplayName);
  659. if (lpValues) {
  660. pszFriendlyName = (LPWSTR) LocalAlloc( LPTR, (lstrlen(*lpValues)+1) * sizeof(TCHAR) );
  661. if ( pszFriendlyName == 0) {
  662. xe = GetLastError();
  663. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Unable to allocate memory")));
  664. pLDAP->pfnldap_value_free (lpValues);
  665. goto Exit;
  666. }
  667. lstrcpy (pszFriendlyName, *lpValues);
  668. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found display name of: <%s>"), pszFriendlyName));
  669. pLDAP->pfnldap_value_free (lpValues);
  670. } else {
  671. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: No display name for this object.")));
  672. pszFriendlyName = (LPWSTR) LocalAlloc( LPTR, 2 * sizeof(TCHAR) );
  673. if ( pszFriendlyName == 0) {
  674. xe = GetLastError();
  675. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Unable to allocate memory")));
  676. goto Exit;
  677. }
  678. pszFriendlyName[0] = TEXT('\0');
  679. }
  680. //
  681. // In the results, get the values that match the version attribute
  682. //
  683. lpValues = pLDAP->pfnldap_get_values(pld, pMessage, szVersion);
  684. if (lpValues) {
  685. dwVersion = StringToInt (*lpValues);
  686. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  687. dwVersion = MAKELONG(LOWORD(dwVersion), LOWORD(dwGPTVersion));
  688. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found machine version of: GPC is %d, GPT is %d"), LOWORD(dwVersion), HIWORD(dwVersion)));
  689. } else {
  690. dwVersion = MAKELONG(HIWORD(dwVersion), HIWORD(dwGPTVersion));
  691. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found user version of: GPC is %d, GPT is %d"), LOWORD(dwVersion), HIWORD(dwVersion)));
  692. }
  693. pLDAP->pfnldap_value_free (lpValues);
  694. } else {
  695. // start treating this as an error.
  696. xe = pLDAP->pfnLdapMapErrorToWin32(pLDAP->pfnLdapGetLastError());
  697. DebugMsg((DM_WARNING, TEXT("ProcessGPO: GPO %s does not have a version number."), lpGPOPath));
  698. CEvents ev(TRUE, EVENT_NODSVERSION);
  699. ev.AddArg(lpGPOPath); ev.AddArgLdapError(pLDAP->pfnLdapGetLastError()); ev.Report();
  700. goto Exit;
  701. }
  702. //
  703. // In the results, get the values that match the flags attribute
  704. //
  705. lpValues = pLDAP->pfnldap_get_values(pld, pMessage, szFlags);
  706. if (lpValues) {
  707. dwGPOFlags = StringToInt (*lpValues);
  708. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found flags of: %d"), dwGPOFlags));
  709. pLDAP->pfnldap_value_free (lpValues);
  710. } else {
  711. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: No flags for this object.")));
  712. }
  713. //
  714. // In the results, get the values that match the extension names attribute
  715. //
  716. lpValues = pLDAP->pfnldap_get_values(pld, pMessage,
  717. (dwFlags & GPO_LIST_FLAG_MACHINE) ? GPO_MACHEXTENSION_NAMES
  718. : GPO_USEREXTENSION_NAMES );
  719. if (lpValues) {
  720. if ( lstrcmpi( *lpValues, TEXT(" ") ) == 0 ) {
  721. //
  722. // A blank char is also a null property case, because Adsi doesn't commit null strings
  723. //
  724. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: No client-side extensions for this object.")));
  725. } else {
  726. pszExtensions = (LPWSTR) LocalAlloc( LPTR, (lstrlen(*lpValues)+1) * sizeof(TCHAR) );
  727. if ( pszExtensions == 0 ) {
  728. xe = GetLastError();
  729. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Unable to allocate memory")));
  730. pLDAP->pfnldap_value_free (lpValues);
  731. goto Exit;
  732. }
  733. lstrcpy( pszExtensions, *lpValues );
  734. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: Found extensions: %s"), pszExtensions));
  735. }
  736. pLDAP->pfnldap_value_free (lpValues);
  737. } else {
  738. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: No client-side extensions for this object.")));
  739. }
  740. //
  741. // Log which GPO we found
  742. //
  743. if (bVerbose) {
  744. CEvents ev(FALSE, EVENT_FOUND_GPO);
  745. ev.AddArg(pszFriendlyName); ev.AddArg(szGPOName); ev.Report();
  746. }
  747. //
  748. // Check the functionalty version number
  749. //
  750. if (dwFunctionalityVersion < 2) {
  751. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: GPO %s was created by an old version of the Group Policy Editor. It will be skipped."), pszFriendlyName));
  752. if (bVerbose) {
  753. CEvents ev(FALSE, EVENT_GPO_TOO_OLD);
  754. ev.AddArg(pszFriendlyName); ev.Report();
  755. }
  756. bOldGpoVersion = TRUE;
  757. }
  758. //
  759. // Check if the GPO is disabled
  760. //
  761. if (((dwFlags & GPO_LIST_FLAG_MACHINE) &&
  762. (dwGPOFlags & GPO_OPTION_DISABLE_MACHINE)) ||
  763. (!(dwFlags & GPO_LIST_FLAG_MACHINE) &&
  764. (dwGPOFlags & GPO_OPTION_DISABLE_USER))) {
  765. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: GPO %s is disabled. It will be skipped."), pszFriendlyName));
  766. if (bVerbose) {
  767. CEvents ev(FALSE, EVENT_GPO_DISABLED);
  768. ev.AddArg(pszFriendlyName); ev.Report();
  769. }
  770. bDisabled = TRUE;
  771. }
  772. //
  773. // Check if the version number is 0, if so there isn't any data
  774. // in the GPO and we can skip it
  775. //
  776. if (dwVersion == 0) {
  777. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: GPO %s doesn't contain any data since the version number is 0. It will be skipped."), pszFriendlyName));
  778. if (bVerbose) {
  779. CEvents ev(FALSE, EVENT_GPO_NO_DATA);
  780. ev.AddArg(pszFriendlyName); ev.Report();
  781. }
  782. bNoGpoData = TRUE;
  783. }
  784. //
  785. // Put the correct container name on the front of the LDAP path
  786. //
  787. lpTemp = (LPWSTR) LocalAlloc (LPTR, (lstrlen(lpGPOPath) + 20) * sizeof(TCHAR));
  788. if (!lpTemp) {
  789. xe = GetLastError();
  790. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Failed to allocate memory with %d"), GetLastError()));
  791. CEvents ev(TRUE, EVENT_OUT_OF_MEMORY);
  792. ev.AddArgWin32Error(GetLastError()); ev.Report();
  793. goto Exit;
  794. }
  795. if (dwFlags & GPO_LIST_FLAG_MACHINE) {
  796. lstrcpy (lpTemp, TEXT("LDAP://CN=Machine,"));
  797. } else {
  798. lstrcpy (lpTemp, TEXT("LDAP://CN=User,"));
  799. }
  800. DmAssert( lstrlen(TEXT("LDAP://CN=Machine,")) + lstrlen(lpPath) < (lstrlen(lpGPOPath) + 20) );
  801. lstrcat (lpTemp, lpPath);
  802. //
  803. // Add this GPO to the list
  804. //
  805. if ( bRsopLogging ) {
  806. bResult = AddGPOToRsopList( ppGpContainerList,
  807. dwFlags,
  808. TRUE,
  809. bAccessGranted,
  810. bDisabled,
  811. dwVersion,
  812. lpTemp,
  813. pszGPTPath,
  814. pszFriendlyName,
  815. szGPOName,
  816. pSD,
  817. cbSDLen,
  818. bFilterAllowed,
  819. pwszFilterId,
  820. lpDSObject,
  821. dwGPOOptions );
  822. if (!bResult) {
  823. xe = GetLastError();
  824. LocalFree(lpTemp);
  825. goto Exit;
  826. }
  827. }
  828. if ( bProcessGPO && bAccessGranted && !bOldGpoVersion && !bDisabled && !bNoGpoData && bFilterAllowed)
  829. {
  830. bResult = AddGPO (lpGPOList, dwFlags, TRUE, bAccessGranted, bDisabled,
  831. dwGPOOptions, dwVersion, lpTemp,
  832. pszGPTPath, pszFriendlyName, szGPOName, pszExtensions, pSD, cbSDLen, GPOLink, lpDSObject, 0,
  833. FALSE, bBlock, bVerbose, bProcessGPO);
  834. }
  835. if (!bResult) {
  836. xe = GetLastError();
  837. DebugMsg((DM_WARNING, TEXT("ProcessGPO: Failed to add GPO <%s> to the list."), pszFriendlyName));
  838. }
  839. LocalFree (lpTemp);
  840. Exit:
  841. if ( pSD )
  842. LocalFree( pSD );
  843. if ( pszGPTPath )
  844. LocalFree( pszGPTPath );
  845. if ( pszFriendlyName )
  846. LocalFree( pszFriendlyName );
  847. if ( pszExtensions )
  848. LocalFree( pszExtensions );
  849. if ( pwszFilterId )
  850. LocalFree( pwszFilterId );
  851. if (pMessage && bOwnLdapMsg ) {
  852. pLDAP->pfnldap_msgfree (pMessage);
  853. }
  854. DebugMsg((DM_VERBOSE, TEXT("ProcessGPO: ==============================")));
  855. return bResult;
  856. }
  857. //*************************************************************
  858. //
  859. // SearchDSObject()
  860. //
  861. // Purpose: Searches the specified DS object for GPOs and
  862. // if found, adds them to the list.
  863. //
  864. // Parameters: lpDSObject - DS object to search
  865. // dwFlags - GetGPOList & GP_PLANMODE flags
  866. // pGPOForcedList - List of forced GPOs
  867. // pGPONonForcedList - List of non-forced GPOs
  868. // ppSOMList - List of LSDOUs
  869. // ppGpContainerList - List of Gp Containers
  870. // bVerbose - Verbose output
  871. // GPOLink - GPO link type
  872. // pld - LDAP info
  873. // pLDAP - LDAP api
  874. // bBlock - Pointer to the block flag
  875. //
  876. //
  877. // Return: TRUE if successful
  878. // FALSE if an error occurs
  879. //
  880. //*************************************************************
  881. BOOL SearchDSObject (LPTSTR lpDSObject, DWORD dwFlags, HANDLE hToken, PGROUP_POLICY_OBJECT *pGPOForcedList,
  882. PGROUP_POLICY_OBJECT *pGPONonForcedList,
  883. LPSCOPEOFMGMT *ppSOMList, LPGPCONTAINER *ppGpContainerList,
  884. BOOL bVerbose,
  885. GPO_LINK GPOLink, PLDAP pld, PLDAP_API pLDAP, PLDAPMessage pLDAPMsg,BOOL *bBlock, PRSOPTOKEN pRsopToken )
  886. {
  887. PGROUP_POLICY_OBJECT pForced = NULL, pNonForced = NULL, lpGPO;
  888. LPTSTR *lpValues;
  889. ULONG ulResult;
  890. BOOL bResult = FALSE;
  891. BOOL bOwnLdapMsg = FALSE; // LDAP message owned by us (if true) or caller (if false)
  892. DWORD dwGPOOptions, dwOptions = 0;
  893. LPTSTR lpTemp, lpList, lpDSClass;
  894. BYTE berValue[8];
  895. LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR)berValue }, TRUE };
  896. PLDAPControl ServerControls[] = { &SeInfoControl, NULL };
  897. TCHAR szGPLink[] = TEXT("gPLink");
  898. TCHAR szGPOPath[512];
  899. TCHAR szGPOOptions[12];
  900. TCHAR szGPOptions[] = TEXT("gPOptions");
  901. TCHAR szSDProperty[] = TEXT("nTSecurityDescriptor");
  902. ULONG i = 0;
  903. LPTSTR lpFullDSObject = NULL;
  904. BOOL bFound = FALSE;
  905. LPTSTR lpAttr[] = { szGPLink,
  906. szGPOptions,
  907. // szObjectClass, not needed
  908. szSDProperty,
  909. NULL
  910. };
  911. SCOPEOFMGMT *pSOM = NULL;
  912. BOOL bRsopLogging = (ppSOMList != NULL);
  913. BOOL bAllGPOs = (dwFlags & FLAG_NO_GPO_FILTER) && (dwFlags & GP_PLANMODE);
  914. XLastError xe;
  915. //
  916. // Setup the BER encoding for the SD
  917. //
  918. berValue[0] = 0x30;
  919. berValue[1] = 0x03;
  920. berValue[2] = 0x02; // denotes an integer
  921. berValue[3] = 0x01; // denotes size
  922. berValue[4] = (BYTE)((DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION) & 0xF);
  923. if ( !pRsopToken )
  924. {
  925. //
  926. // if it is not planning mode, don't get the SD
  927. //
  928. lpAttr[2] = NULL;
  929. ServerControls[0] = NULL;
  930. }
  931. //
  932. // Search for the object
  933. //
  934. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: Searching <%s>"), lpDSObject));
  935. if (bVerbose) {
  936. CEvents ev(FALSE, EVENT_SEARCHING);
  937. ev.AddArg(lpDSObject); ev.Report();
  938. }
  939. if ( bRsopLogging )
  940. {
  941. pSOM = AllocSOM( lpDSObject );
  942. if ( !pSOM ) {
  943. xe = GetLastError();
  944. DebugMsg((DM_WARNING, TEXT("SearchDSObject: Unable to allocate memory for SOM object. Leaving. ")));
  945. goto Exit;
  946. }
  947. pSOM->dwType = GPOLink;
  948. pSOM->bBlocked = *bBlock;
  949. }
  950. if ( pLDAPMsg == NULL ) {
  951. bOwnLdapMsg = TRUE;
  952. ulResult = pLDAP->pfnldap_search_ext_s(pld, lpDSObject, LDAP_SCOPE_BASE,
  953. szDSClassAny, lpAttr, FALSE,
  954. (PLDAPControl*)ServerControls,
  955. NULL, NULL, 0, &pLDAPMsg);
  956. if (ulResult != LDAP_SUCCESS) {
  957. if (ulResult == LDAP_NO_SUCH_ATTRIBUTE) {
  958. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: No GPO(s) for this object.")));
  959. if (bVerbose) {
  960. CEvents ev(FALSE, EVENT_NO_GPOS); ev.AddArg(lpDSObject); ev.Report();
  961. }
  962. bResult = TRUE;
  963. } else if (ulResult == LDAP_NO_SUCH_OBJECT) {
  964. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: Object not found in DS (this is ok). Leaving. ")));
  965. if (bVerbose) {
  966. CEvents ev(FALSE, EVENT_NO_DS_OBJECT);
  967. ev.AddArg(lpDSObject); ev.Report();
  968. }
  969. bResult = TRUE;
  970. } else if (ulResult == LDAP_SIZELIMIT_EXCEEDED) {
  971. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  972. DebugMsg((DM_WARNING, TEXT("SearchDSObject: Too many linked GPOs in search.") ));
  973. CEvents ev(TRUE, EVENT_TOO_MANY_GPOS); ev.Report();
  974. } else {
  975. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  976. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: Failed to find DS object <%s> due to error %d."),
  977. lpDSObject, ulResult));
  978. CEvents ev(TRUE, EVENT_GPLINK_NOT_FOUND);
  979. ev.AddArg(lpDSObject); ev.AddArgLdapError(ulResult); ev.Report();
  980. }
  981. goto Exit;
  982. }
  983. }
  984. if ( bRsopLogging && pRsopToken && !bAllGPOs )
  985. {
  986. //
  987. // In Rsop planning mode, check access to OU
  988. //
  989. BOOL bAccessGranted = FALSE;
  990. BOOL bOk;
  991. bOk = CheckOUAccess(pLDAP,
  992. pld,
  993. pLDAPMsg,
  994. pRsopToken,
  995. &bAccessGranted );
  996. if ( !bOk )
  997. {
  998. xe = GetLastError();
  999. goto Exit;
  1000. }
  1001. if ( !bAccessGranted )
  1002. {
  1003. //
  1004. // no access for the user on the OU. Exit
  1005. //
  1006. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: Access denied in planning mode to SOM <%s>"), lpDSObject));
  1007. if (pLDAPMsg && bOwnLdapMsg )
  1008. {
  1009. pLDAP->pfnldap_msgfree (pLDAPMsg);
  1010. pLDAPMsg = 0;
  1011. }
  1012. CEvents ev(TRUE, EVENT_OU_ACCESSDENIED);
  1013. ev.AddArg(lpDSObject); ev.Report();
  1014. goto Exit;
  1015. }
  1016. }
  1017. //
  1018. // In the results, get the values that match the gPOptions attribute
  1019. //
  1020. lpValues = pLDAP->pfnldap_get_values(pld, pLDAPMsg, szGPOptions);
  1021. if (lpValues && *lpValues) {
  1022. dwOptions = StringToInt (*lpValues);
  1023. pLDAP->pfnldap_value_free (lpValues);
  1024. }
  1025. //
  1026. // In the results, get the values that match the gPLink attribute
  1027. //
  1028. lpValues = pLDAP->pfnldap_get_values(pld, pLDAPMsg, szGPLink);
  1029. if (lpValues && *lpValues) {
  1030. lpList = *lpValues;
  1031. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: Found GPO(s): <%s>"), lpList));
  1032. lpFullDSObject = (LPWSTR) LocalAlloc (LPTR, (lstrlen(lpDSObject) + 8) * sizeof(TCHAR));
  1033. if (!lpFullDSObject) {
  1034. xe = GetLastError();
  1035. DebugMsg((DM_WARNING, TEXT("SearchDSObject: Failed to allocate memory for full DS Object path name with %d"),
  1036. GetLastError()));
  1037. pLDAP->pfnldap_value_free (lpValues);
  1038. goto Exit;
  1039. }
  1040. lstrcpy (lpFullDSObject, TEXT("LDAP://"));
  1041. lstrcat (lpFullDSObject, lpDSObject);
  1042. while (*lpList) {
  1043. //
  1044. // Pull off the GPO ldap path
  1045. //
  1046. lpTemp = szGPOPath;
  1047. dwGPOOptions = 0;
  1048. while (*lpList && (*lpList != TEXT('['))) {
  1049. lpList++;
  1050. }
  1051. if (!(*lpList)) {
  1052. break;
  1053. }
  1054. lpList++;
  1055. while (*lpList && (*lpList != TEXT(';'))) {
  1056. *lpTemp++ = *lpList++;
  1057. }
  1058. if (!(*lpList)) {
  1059. break;
  1060. }
  1061. *lpTemp = TEXT('\0');
  1062. lpList++;
  1063. lpTemp = szGPOOptions;
  1064. *lpTemp = TEXT('\0');
  1065. while (*lpList && (*lpList != TEXT(']'))) {
  1066. *lpTemp++ = *lpList++;
  1067. }
  1068. if (!(*lpList)) {
  1069. break;
  1070. }
  1071. *lpTemp = TEXT('\0');
  1072. lpList++;
  1073. dwGPOOptions = StringToInt (szGPOOptions);
  1074. if ( bRsopLogging ) {
  1075. GPLINK *pGpLink = AllocGpLink( szGPOPath, dwGPOOptions );
  1076. if ( pGpLink == NULL ) {
  1077. xe = GetLastError();
  1078. DebugMsg((DM_WARNING, TEXT("SearchDSObject: Unable to allocate memory for GpLink object. Leaving. ")));
  1079. goto Exit;
  1080. }
  1081. //
  1082. // Append GpLink to end of SOM list
  1083. //
  1084. if ( pSOM->pGpLinkList == NULL ) {
  1085. pSOM->pGpLinkList = pGpLink;
  1086. } else {
  1087. GPLINK *pTrailPtr = NULL;
  1088. GPLINK *pCurPtr = pSOM->pGpLinkList;
  1089. while ( pCurPtr != NULL ) {
  1090. pTrailPtr = pCurPtr;
  1091. pCurPtr = pCurPtr->pNext;
  1092. }
  1093. pTrailPtr->pNext = pGpLink;
  1094. }
  1095. }
  1096. //
  1097. // Check if this link is disabled
  1098. //
  1099. BOOL bProcessGPO = TRUE;
  1100. if ( ( dwGPOOptions & GPO_FLAG_DISABLE ) && !bAllGPOs )
  1101. {
  1102. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: The link to GPO %s is disabled. It will be skipped for processing."), szGPOPath));
  1103. if (bVerbose)
  1104. {
  1105. CEvents ev(FALSE, EVENT_GPO_LINK_DISABLED);
  1106. ev.AddArg(szGPOPath); ev.Report();
  1107. }
  1108. bProcessGPO = FALSE;
  1109. }
  1110. if (bProcessGPO || (dwFlags & GP_PLANMODE)) {
  1111. if (!bProcessGPO) {
  1112. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: The link to GPO %s is disabled. GPO is still being queried. Planning mode."), szGPOPath));
  1113. }
  1114. if ( !ProcessGPO( szGPOPath,
  1115. dwFlags,
  1116. hToken,
  1117. (dwGPOOptions & GPO_FLAG_FORCE) ? &pForced : &pNonForced,
  1118. ppGpContainerList,
  1119. dwGPOOptions,
  1120. TRUE,
  1121. bVerbose,
  1122. GPOLink,
  1123. lpFullDSObject,
  1124. pld,
  1125. pLDAP,
  1126. 0,
  1127. *bBlock,
  1128. pRsopToken,
  1129. 0,
  1130. 0,
  1131. bProcessGPO ) )
  1132. {
  1133. xe = GetLastError();
  1134. DebugMsg((DM_WARNING, TEXT("SearchDSObject: ProcessGPO failed.")));
  1135. pLDAP->pfnldap_value_free (lpValues);
  1136. goto Exit;
  1137. }
  1138. }
  1139. }
  1140. pLDAP->pfnldap_value_free (lpValues);
  1141. //
  1142. // Set the block flag now if requested. This way OU's, domains, etc
  1143. // higher in the namespace will have GPOs removed if appropriate
  1144. //
  1145. if (dwOptions & GPC_BLOCK_POLICY) {
  1146. *bBlock = TRUE;
  1147. if ( bRsopLogging )
  1148. pSOM->bBlocking = TRUE;
  1149. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: <%s> has the Block From Above attribute set"), lpDSObject));
  1150. if (bVerbose) {
  1151. CEvents ev(FALSE, EVENT_BLOCK_ENABLED);
  1152. ev.AddArg(lpDSObject); ev.Report();
  1153. }
  1154. }
  1155. } else {
  1156. DebugMsg((DM_VERBOSE, TEXT("SearchDSObject: No GPO(s) for this object.")));
  1157. if (bVerbose) {
  1158. CEvents ev(FALSE, EVENT_NO_GPOS); ev.AddArg(lpDSObject); ev.Report();
  1159. }
  1160. }
  1161. //
  1162. // Merge the temp and real lists together
  1163. // First the non-forced lists
  1164. //
  1165. if (pNonForced) {
  1166. lpGPO = pNonForced;
  1167. while (lpGPO->pNext) {
  1168. lpGPO = lpGPO->pNext;
  1169. }
  1170. lpGPO->pNext = *pGPONonForcedList;
  1171. if (*pGPONonForcedList) {
  1172. (*pGPONonForcedList)->pPrev = lpGPO;
  1173. }
  1174. *pGPONonForcedList = pNonForced;
  1175. }
  1176. //
  1177. // Now the forced lists
  1178. //
  1179. if (pForced) {
  1180. lpGPO = *pGPOForcedList;
  1181. if (lpGPO) {
  1182. while (lpGPO->pNext) {
  1183. lpGPO = lpGPO->pNext;
  1184. }
  1185. lpGPO->pNext = pForced;
  1186. pForced->pPrev = lpGPO;
  1187. } else {
  1188. *pGPOForcedList = pForced;
  1189. }
  1190. }
  1191. bResult = TRUE;
  1192. Exit:
  1193. if ( !bResult && pSOM != NULL ) {
  1194. FreeSOM( pSOM );
  1195. }
  1196. else {
  1197. if ( bResult && bRsopLogging ) {
  1198. //
  1199. // Insert SOM at the beginning
  1200. //
  1201. pSOM->pNext = *ppSOMList;
  1202. *ppSOMList = pSOM;
  1203. }
  1204. }
  1205. if (lpFullDSObject) {
  1206. LocalFree (lpFullDSObject);
  1207. }
  1208. if (pLDAPMsg && bOwnLdapMsg ) {
  1209. pLDAP->pfnldap_msgfree (pLDAPMsg);
  1210. }
  1211. return bResult;
  1212. }
  1213. //*************************************************************
  1214. //
  1215. // AllocDnEntry()
  1216. //
  1217. // Purpose: Allocates a new struct for dn entry
  1218. //
  1219. //
  1220. // Parameters: pwszDN - Distinguished name
  1221. //
  1222. // Return: Pointer if successful
  1223. // NULL if an error occurs
  1224. //
  1225. //*************************************************************
  1226. DNENTRY * AllocDnEntry( LPTSTR pwszDN )
  1227. {
  1228. DNENTRY *pDnEntry = (DNENTRY *) LocalAlloc (LPTR, sizeof(DNENTRY));
  1229. XLastError xe;
  1230. if ( pDnEntry == NULL ) {
  1231. xe = GetLastError();
  1232. DebugMsg((DM_WARNING, TEXT("AllocDnEntry: Failed to alloc pDnEntry with 0x%x."),
  1233. GetLastError()));
  1234. return NULL;
  1235. }
  1236. pDnEntry->pwszDN = (LPTSTR) LocalAlloc (LPTR, (lstrlen(pwszDN) + 1) * sizeof(TCHAR) );
  1237. if ( pDnEntry->pwszDN == NULL ) {
  1238. xe = GetLastError();
  1239. DebugMsg((DM_WARNING, TEXT("AllocDnEntry: Failed to alloc pwszDN with 0x%x."),
  1240. GetLastError()));
  1241. LocalFree( pDnEntry );
  1242. return NULL;
  1243. }
  1244. lstrcpy( pDnEntry->pwszDN, pwszDN );
  1245. return pDnEntry;
  1246. }
  1247. //*************************************************************
  1248. //
  1249. // FreeDnEntry()
  1250. //
  1251. // Purpose: Frees dn entry struct
  1252. //
  1253. //*************************************************************
  1254. void FreeDnEntry( DNENTRY *pDnEntry )
  1255. {
  1256. if ( pDnEntry ) {
  1257. if ( pDnEntry->pwszDN )
  1258. LocalFree( pDnEntry->pwszDN );
  1259. LocalFree( pDnEntry );
  1260. }
  1261. }
  1262. //*************************************************************
  1263. //
  1264. // AllocLdapQuery()
  1265. //
  1266. // Purpose: Allocates a new struct for ldap query
  1267. //
  1268. //
  1269. // Parameters: pwszDomain - Domain of Gpo
  1270. //
  1271. // Return: Pointer if successful
  1272. // NULL if an error occurs
  1273. //
  1274. //*************************************************************
  1275. LDAPQUERY * AllocLdapQuery( LPTSTR pwszDomain )
  1276. {
  1277. const INIT_ALLOC_SIZE = 1000;
  1278. LDAPQUERY *pQuery = (LDAPQUERY *) LocalAlloc (LPTR, sizeof(LDAPQUERY));
  1279. XLastError xe;
  1280. if ( pQuery == NULL ) {
  1281. xe = GetLastError();
  1282. DebugMsg((DM_WARNING, TEXT("AllocLdapQuery: Failed to alloc pQuery with 0x%x."),
  1283. GetLastError()));
  1284. return NULL;
  1285. }
  1286. pQuery->pwszDomain = (LPTSTR) LocalAlloc (LPTR, (lstrlen(pwszDomain) + 1) * sizeof(TCHAR) );
  1287. if ( pQuery->pwszDomain == NULL ) {
  1288. xe = GetLastError();
  1289. DebugMsg((DM_WARNING, TEXT("AllocLdapQuery: Failed to alloc pwszDomain with 0x%x."),
  1290. GetLastError()));
  1291. LocalFree( pQuery );
  1292. return NULL;
  1293. }
  1294. pQuery->pwszFilter = (LPTSTR) LocalAlloc (LPTR, INIT_ALLOC_SIZE );
  1295. if ( pQuery->pwszFilter == NULL ) {
  1296. xe = GetLastError();
  1297. DebugMsg((DM_WARNING, TEXT("AllocLdapQuery: Failed to alloc pwszFilter with 0x%x."),
  1298. GetLastError()));
  1299. LocalFree( pQuery->pwszDomain );
  1300. LocalFree( pQuery );
  1301. return NULL;
  1302. }
  1303. lstrcpy( pQuery->pwszDomain, pwszDomain );
  1304. lstrcpy( pQuery->pwszFilter, L"(|)" );
  1305. pQuery->cbLen = 8; // 8 = (lstrlen(L"(|)") + 1) * sizeof(TCHAR)
  1306. pQuery->cbAllocLen = INIT_ALLOC_SIZE;
  1307. return pQuery;
  1308. }
  1309. //*************************************************************
  1310. //
  1311. // FreeLdapQuery()
  1312. //
  1313. // Purpose: Frees ldap query struct
  1314. //
  1315. //*************************************************************
  1316. void FreeLdapQuery( PLDAP_API pLDAP, LDAPQUERY *pQuery )
  1317. {
  1318. DNENTRY *pDnEntry = NULL;
  1319. if ( pQuery ) {
  1320. if ( pQuery->pwszDomain )
  1321. LocalFree( pQuery->pwszDomain );
  1322. if ( pQuery->pwszFilter )
  1323. LocalFree( pQuery->pwszFilter );
  1324. if ( pQuery->pMessage )
  1325. pLDAP->pfnldap_msgfree( pQuery->pMessage );
  1326. if ( pQuery->pLdapHandle && pQuery->bOwnLdapHandle )
  1327. pLDAP->pfnldap_unbind( pQuery->pLdapHandle );
  1328. pDnEntry = pQuery->pDnEntry;
  1329. while ( pDnEntry ) {
  1330. DNENTRY *pTemp = pDnEntry->pNext;
  1331. FreeDnEntry( pDnEntry );
  1332. pDnEntry = pTemp;
  1333. }
  1334. LocalFree( pQuery );
  1335. }
  1336. }
  1337. //*************************************************************
  1338. //
  1339. // MatchDnWithDeferredItems()
  1340. //
  1341. // Purpose: Matches the dns from ldap query with the deferred items
  1342. //
  1343. // Parameters: pLDAP - LDAP function table pointer
  1344. // ppLdapQuery - LDAP query list
  1345. //
  1346. // Return: TRUE if successful
  1347. // FALSE if an error occurs
  1348. //
  1349. //*************************************************************
  1350. BOOL MatchDnWithDeferredItems( PLDAP_API pLDAP, LDAPQUERY *pLdapQuery, BOOL bOUProcessing )
  1351. {
  1352. PLDAPMessage pMsg = pLDAP->pfnldap_first_entry( pLdapQuery->pLdapHandle, pLdapQuery->pMessage );
  1353. while ( pMsg ) {
  1354. WCHAR *pwszDN = pLDAP->pfnldap_get_dn( pLdapQuery->pLdapHandle, pMsg );
  1355. DNENTRY *pCurPtr = pLdapQuery->pDnEntry;
  1356. while ( pCurPtr ) {
  1357. INT iResult = CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1358. pwszDN, -1, pCurPtr->pwszDN, -1 );
  1359. if ( iResult == CSTR_EQUAL ) {
  1360. //
  1361. // Store the pointer to ldap message so that it can be used
  1362. // later to retrieve necessary attributes.
  1363. //
  1364. if ( bOUProcessing )
  1365. pCurPtr->pDeferredOU->pOUMsg = pMsg;
  1366. else {
  1367. LPGPOPROCDATA lpGpoProcData = (LPGPOPROCDATA)pCurPtr->pDeferredGPO->lParam2;
  1368. pCurPtr->pDeferredGPO->lParam = (LPARAM) pMsg;
  1369. lpGpoProcData->pLdapHandle = pLdapQuery->pLdapHandle;
  1370. }
  1371. pCurPtr = pCurPtr->pNext;
  1372. } else if ( iResult == CSTR_LESS_THAN ) {
  1373. //
  1374. // Since dns are in ascending order,
  1375. // we are done.
  1376. //
  1377. break;
  1378. } else {
  1379. //
  1380. // Advance down the list
  1381. //
  1382. pCurPtr = pCurPtr->pNext;
  1383. } // final else
  1384. } // while pcurptr
  1385. pLDAP->pfnldap_memfree( pwszDN );
  1386. pMsg = pLDAP->pfnldap_next_entry( pLdapQuery->pLdapHandle, pMsg );
  1387. } // while pmsg
  1388. return TRUE;
  1389. }
  1390. LPWSTR DsQuoteSearchFilter( LPCWSTR );
  1391. //*************************************************************
  1392. //
  1393. // AddDnToFilter()
  1394. //
  1395. // Purpose: ORs in the new dn to the ldap filter
  1396. //
  1397. // Parameters: ppLdapQuery - LDAP query list
  1398. // pGPO - Deferred GPO
  1399. //
  1400. // Return: TRUE if successful
  1401. // FALSE if an error occurs
  1402. //
  1403. //*************************************************************
  1404. BOOL AddDnToFilter( LDAPQUERY *pLdapQuery, LPTSTR pwszDN )
  1405. {
  1406. const DN_SIZE = 20; // 20 = # chars in "(dis..=)"
  1407. BOOL bSuccess = FALSE;
  1408. LPWSTR szQuotedDN;
  1409. szQuotedDN = DsQuoteSearchFilter( pwszDN );
  1410. if ( ! szQuotedDN )
  1411. {
  1412. DebugMsg((DM_WARNING, TEXT("GetGPOInfo: DsQuoteSearchFilter failed with = <%d>"), GetLastError() ));
  1413. goto AddDnToFilter_ExitAndCleanup;
  1414. }
  1415. DWORD cbNew = (lstrlen(szQuotedDN) + DN_SIZE) * sizeof(TCHAR); // + 1 is not needed because \0 is already part of filter string
  1416. DWORD cbSizeRequired = pLdapQuery->cbLen + cbNew;
  1417. if ( cbSizeRequired >= pLdapQuery->cbAllocLen ) {
  1418. //
  1419. // Need to grow buffer because of overflow
  1420. //
  1421. LPTSTR pwszNewFilter = (LPTSTR) LocalAlloc (LPTR, cbSizeRequired * 2);
  1422. if ( pwszNewFilter == NULL ) {
  1423. DebugMsg((DM_WARNING, TEXT("AddDnToFilter: Unable to allocate new filter string") ));
  1424. goto AddDnToFilter_ExitAndCleanup;
  1425. }
  1426. lstrcpy( pwszNewFilter, pLdapQuery->pwszFilter );
  1427. LocalFree( pLdapQuery->pwszFilter );
  1428. pLdapQuery->pwszFilter = pwszNewFilter;
  1429. pLdapQuery->cbAllocLen = cbSizeRequired * 2;
  1430. }
  1431. DmAssert( cbSizeRequired < pLdapQuery->cbAllocLen );
  1432. //
  1433. // Overwrite last ")" and then append the new dn name term
  1434. //
  1435. lstrcpy( &pLdapQuery->pwszFilter[pLdapQuery->cbLen/2 - 2], L"(distinguishedName=" );
  1436. lstrcat( pLdapQuery->pwszFilter, szQuotedDN );
  1437. lstrcat( pLdapQuery->pwszFilter, L"))" );
  1438. pLdapQuery->cbLen += cbNew;
  1439. bSuccess = TRUE;
  1440. AddDnToFilter_ExitAndCleanup:
  1441. if ( szQuotedDN )
  1442. {
  1443. LocalFree( szQuotedDN );
  1444. }
  1445. return bSuccess;
  1446. }
  1447. //*************************************************************
  1448. //
  1449. // InsertDN()
  1450. //
  1451. // Purpose: Adds a distinguished name entry to ldap query's
  1452. // names linked list
  1453. //
  1454. // Parameters: ppLdapQuery - LDAP query list
  1455. // pwszDN - DN
  1456. // pDeferredOU - Deferred OU
  1457. // pDeferredGPO - Deferred GPO
  1458. //
  1459. // Return: TRUE if successful
  1460. // FALSE if an error occurs
  1461. //
  1462. //*************************************************************
  1463. BOOL InsertDN( LDAPQUERY *pLdapQuery, LPTSTR pwszDN,
  1464. DNENTRY *pDeferredOU, PGROUP_POLICY_OBJECT pDeferredGPO )
  1465. {
  1466. DNENTRY *pNewEntry = NULL;
  1467. DNENTRY *pTrailPtr = NULL;
  1468. DNENTRY *pCurPtr = pLdapQuery->pDnEntry;
  1469. XLastError xe;
  1470. DmAssert( !( pDeferredOU && pDeferredGPO ) );
  1471. while ( pCurPtr != NULL ) {
  1472. INT iResult = CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1473. pwszDN, -1, pCurPtr->pwszDN, -1 );
  1474. if ( iResult == CSTR_EQUAL || iResult == CSTR_LESS_THAN ) {
  1475. //
  1476. // Duplicate or since dn's are in ascending order, add new entry
  1477. //
  1478. DNENTRY *pNewEntry = AllocDnEntry( pwszDN );
  1479. if ( pNewEntry == NULL )
  1480. return FALSE;
  1481. if ( !AddDnToFilter( pLdapQuery, pwszDN ) ) {
  1482. xe = GetLastError();
  1483. FreeDnEntry( pNewEntry );
  1484. return FALSE;
  1485. }
  1486. if ( pDeferredOU )
  1487. pNewEntry->pDeferredOU = pDeferredOU;
  1488. else
  1489. pNewEntry->pDeferredGPO = pDeferredGPO;
  1490. pNewEntry->pNext = pCurPtr;
  1491. if ( pTrailPtr == NULL )
  1492. pLdapQuery->pDnEntry = pNewEntry;
  1493. else
  1494. pTrailPtr->pNext = pNewEntry;
  1495. return TRUE;
  1496. } else {
  1497. //
  1498. // Advance down the list
  1499. //
  1500. pTrailPtr = pCurPtr;
  1501. pCurPtr = pCurPtr->pNext;
  1502. }
  1503. } // while
  1504. //
  1505. // Null list or end of list case.
  1506. //
  1507. pNewEntry = AllocDnEntry( pwszDN );
  1508. if ( pNewEntry == NULL ) {
  1509. xe = GetLastError();
  1510. return FALSE;
  1511. }
  1512. if ( !AddDnToFilter( pLdapQuery, pwszDN ) ) {
  1513. xe = GetLastError();
  1514. FreeDnEntry( pNewEntry );
  1515. return FALSE;
  1516. }
  1517. if ( pDeferredOU )
  1518. pNewEntry->pDeferredOU = pDeferredOU;
  1519. else
  1520. pNewEntry->pDeferredGPO = pDeferredGPO;
  1521. pNewEntry->pNext = pCurPtr;
  1522. if ( pTrailPtr == NULL )
  1523. pLdapQuery->pDnEntry = pNewEntry;
  1524. else
  1525. pTrailPtr->pNext = pNewEntry;
  1526. return TRUE;
  1527. }
  1528. //*************************************************************
  1529. //
  1530. // AddDN()
  1531. //
  1532. // Purpose: Adds a distinguished name entry to ldap query
  1533. //
  1534. // Parameters: ppLdapQuery - LDAP query list
  1535. // pwszDN - DN name
  1536. // pDeferredOU - Deferred OU
  1537. // pDeferredGPO - Deferred GPO
  1538. //
  1539. // Return: TRUE if successful
  1540. // FALSE if an error occurs
  1541. //
  1542. //*************************************************************
  1543. BOOL AddDN( PLDAP_API pLDAP, LDAPQUERY **ppLdapQuery,
  1544. LPTSTR pwszDN, DNENTRY *pDeferredOU, PGROUP_POLICY_OBJECT pDeferredGPO )
  1545. {
  1546. LPTSTR pwszDomain = NULL;
  1547. LPTSTR pwszTemp = pwszDN;
  1548. LDAPQUERY *pNewQuery = NULL;
  1549. LDAPQUERY *pTrailPtr = NULL;
  1550. LDAPQUERY *pCurPtr = *ppLdapQuery;
  1551. XLastError xe;
  1552. DmAssert( !( pDeferredOU && pDeferredGPO ) );
  1553. //
  1554. // Find the domain to which the GPO belongs
  1555. //
  1556. if ( pwszTemp == NULL ) {
  1557. DebugMsg((DM_WARNING, TEXT("AddDN: Null pwszDN. Exiting.") ));
  1558. return FALSE;
  1559. }
  1560. while ( *pwszTemp ) {
  1561. //
  1562. // The check below needs to be more sophisticated to take care
  1563. // of spaces in names etc.
  1564. //
  1565. if (CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1566. pwszTemp, 16, TEXT("cn=configuration"), 16) == CSTR_EQUAL ) {
  1567. DebugMsg((DM_VERBOSE, TEXT("AddDN: DN %s is under cn=configuration container. queueing for rebinding"), pwszDN ));
  1568. pwszDomain = pwszTemp;
  1569. break;
  1570. }
  1571. if (CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1572. pwszTemp, 3, TEXT("DC="), 3) == CSTR_EQUAL ) {
  1573. pwszDomain = pwszTemp;
  1574. break;
  1575. }
  1576. //
  1577. // Move to the next chunk of the DN name
  1578. //
  1579. while ( *pwszTemp && (*pwszTemp != TEXT(',')))
  1580. pwszTemp++;
  1581. if ( *pwszTemp == TEXT(','))
  1582. pwszTemp++;
  1583. }
  1584. if ( pwszDomain == NULL ) {
  1585. xe = ERROR_INVALID_DATA;
  1586. DebugMsg((DM_WARNING, TEXT("AddDN: Domain not found for <%s>. Exiting."), pwszDN ));
  1587. return FALSE;
  1588. }
  1589. while ( pCurPtr != NULL ) {
  1590. INT iResult = CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1591. pwszDomain, -1, pCurPtr->pwszDomain, -1 );
  1592. if ( iResult == CSTR_EQUAL ) {
  1593. BOOL bOk = InsertDN( pCurPtr, pwszDN, pDeferredOU, pDeferredGPO );
  1594. return bOk;
  1595. } else if ( iResult == CSTR_LESS_THAN ) {
  1596. //
  1597. // Since domains are in ascending order,
  1598. // pwszDomain is not in list, so add.
  1599. //
  1600. pNewQuery = AllocLdapQuery( pwszDomain );
  1601. if ( pNewQuery == NULL ) {
  1602. xe = GetLastError();
  1603. return FALSE;
  1604. }
  1605. if ( !InsertDN( pNewQuery, pwszDN, pDeferredOU, pDeferredGPO ) ) {
  1606. xe = GetLastError();
  1607. FreeLdapQuery( pLDAP, pNewQuery );
  1608. return FALSE;
  1609. }
  1610. pNewQuery->pNext = pCurPtr;
  1611. if ( pTrailPtr == NULL )
  1612. *ppLdapQuery = pNewQuery;
  1613. else
  1614. pTrailPtr->pNext = pNewQuery;
  1615. return TRUE;
  1616. } else {
  1617. //
  1618. // Advance down the list
  1619. //
  1620. pTrailPtr = pCurPtr;
  1621. pCurPtr = pCurPtr->pNext;
  1622. }
  1623. } // while
  1624. //
  1625. // Null list or end of list case.
  1626. //
  1627. pNewQuery = AllocLdapQuery( pwszDomain );
  1628. if ( pNewQuery == NULL ) {
  1629. xe = GetLastError();
  1630. return FALSE;
  1631. }
  1632. if ( !InsertDN( pNewQuery, pwszDN, pDeferredOU, pDeferredGPO ) ) {
  1633. xe = GetLastError();
  1634. FreeLdapQuery( pLDAP, pNewQuery );
  1635. return FALSE;
  1636. }
  1637. pNewQuery->pNext = pCurPtr;
  1638. if ( pTrailPtr == NULL )
  1639. *ppLdapQuery = pNewQuery;
  1640. else
  1641. pTrailPtr->pNext = pNewQuery;
  1642. return TRUE;
  1643. }
  1644. //*************************************************************
  1645. //
  1646. // EvalList()
  1647. //
  1648. // Purpose: Encapsulates common processing functionality for
  1649. // forced and nonforced lists
  1650. //
  1651. // Parameters: pLDAP - LDAP api
  1652. // dwFlags - GetGPOList flags
  1653. // bVerbose - Verbose flag
  1654. // hToken - User or machine token
  1655. // pDeferredList - List of deferred GPOs
  1656. // ppGPOList - List of evaluated GPOs
  1657. // ppGpContainerList - List of Gp Containers
  1658. // pGpoFilter - Gpo filter
  1659. // pLocator - WMI interfaces
  1660. //
  1661. // Return: TRUE if successful
  1662. // FALSE if an error occurs
  1663. //
  1664. //*************************************************************
  1665. BOOL EvalList( PLDAP_API pLDAP,
  1666. DWORD dwFlags,
  1667. HANDLE hToken,
  1668. BOOL bVerbose,
  1669. PGROUP_POLICY_OBJECT pDeferredList,
  1670. PGROUP_POLICY_OBJECT *ppGPOList,
  1671. LPGPCONTAINER *ppGpContainerList,
  1672. PRSOPTOKEN pRsopToken,
  1673. CGpoFilter *pGpoFilter,
  1674. CLocator *pLocator )
  1675. {
  1676. PGROUP_POLICY_OBJECT pGPOTemp = pDeferredList;
  1677. while ( pGPOTemp ) {
  1678. PLDAPMessage pGPOMsg = (PLDAPMessage) pGPOTemp->lParam;
  1679. if ( pGPOMsg == NULL ) {
  1680. DebugMsg((DM_VERBOSE, TEXT("EvalList: Object <%s> cannot be accessed"),
  1681. pGPOTemp->lpDSPath ));
  1682. if (dwFlags & GP_PLANMODE) {
  1683. CEvents ev(TRUE, EVENT_OBJECT_NOT_FOUND_PLANNING);
  1684. ev.AddArg(pGPOTemp->lpDSPath); ev.Report();
  1685. }
  1686. else {
  1687. if (bVerbose) {
  1688. CEvents ev(FALSE, EVENT_OBJECT_NOT_FOUND);
  1689. ev.AddArg(pGPOTemp->lpDSPath); ev.AddArg((DWORD)0); ev.Report();
  1690. }
  1691. }
  1692. } else {
  1693. DmAssert( pGPOTemp->lParam2 != NULL );
  1694. DmAssert( ((LPGPOPROCDATA)(pGPOTemp->lParam2))->pLdapHandle != NULL );
  1695. if ( !ProcessGPO( pGPOTemp->lpDSPath,
  1696. dwFlags,
  1697. hToken,
  1698. ppGPOList,
  1699. ppGpContainerList,
  1700. pGPOTemp->dwOptions,
  1701. FALSE,
  1702. bVerbose,
  1703. pGPOTemp->GPOLink,
  1704. pGPOTemp->lpLink,
  1705. ((LPGPOPROCDATA)(pGPOTemp->lParam2))->pLdapHandle,
  1706. pLDAP,
  1707. pGPOMsg,
  1708. FALSE,
  1709. pRsopToken,
  1710. pGpoFilter,
  1711. pLocator,
  1712. ((LPGPOPROCDATA)(pGPOTemp->lParam2))->bProcessGPO ) )
  1713. {
  1714. DebugMsg((DM_WARNING, TEXT("EvalList: ProcessGPO failed") ));
  1715. return FALSE;
  1716. }
  1717. }
  1718. pGPOTemp = pGPOTemp->pNext;
  1719. }
  1720. return TRUE;
  1721. }
  1722. //*************************************************************
  1723. //
  1724. // EvaluateDeferredGPOs()
  1725. //
  1726. // Purpose: Uses a single ldap query to evaluate deferred
  1727. // GPO lists.
  1728. //
  1729. // Parameters: pldBound - Bound LDAP handle
  1730. // pLDAP - LDAP api
  1731. // pwszDomainBound - Domain already bound to
  1732. // dwFlags - GetGPOList flags
  1733. // hToken - User or machine token
  1734. // pDeferredForcedList - List of deferred forced GPOs
  1735. // pDeferredNonForcedList - List of deferred non-forced GPOs
  1736. // pGPOForcedList - List of forced GPOs
  1737. // pGPONonForcedList - List of non-forced GPOs
  1738. // ppGpContainerList - List of Gp Containers
  1739. // pGpoFilter - Gpo filter
  1740. // pLocator - WMI interfaces
  1741. //
  1742. // Return: TRUE if successful
  1743. // FALSE if an error occurs
  1744. //
  1745. //*************************************************************
  1746. BOOL EvaluateDeferredGPOs (PLDAP pldBound,
  1747. PLDAP_API pLDAP,
  1748. LPTSTR pwszDomainBound,
  1749. DWORD dwFlags,
  1750. HANDLE hToken,
  1751. BOOL bVerbose,
  1752. PGROUP_POLICY_OBJECT pDeferredForcedList,
  1753. PGROUP_POLICY_OBJECT pDeferredNonForcedList,
  1754. PGROUP_POLICY_OBJECT *ppForcedList,
  1755. PGROUP_POLICY_OBJECT *ppNonForcedList,
  1756. LPGPCONTAINER *ppGpContainerList,
  1757. PRSOPTOKEN pRsopToken,
  1758. CGpoFilter *pGpoFilter,
  1759. CLocator *pLocator )
  1760. {
  1761. ULONG ulResult;
  1762. BOOL bResult = FALSE;
  1763. BYTE berValue[8];
  1764. LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR)berValue }, TRUE };
  1765. LDAPControl referralControl = { LDAP_SERVER_DOMAIN_SCOPE_OID_W, { 0, NULL}, TRUE };
  1766. PLDAPControl ServerControls[] = { &SeInfoControl, &referralControl, NULL };
  1767. TCHAR szSDProperty[] = TEXT("nTSecurityDescriptor");
  1768. TCHAR szCommonName[] = TEXT("cn");
  1769. TCHAR szDisplayName[] = TEXT("displayName");
  1770. TCHAR szFileSysPath[] = TEXT("gPCFileSysPath");
  1771. TCHAR szVersion[] = TEXT("versionNumber");
  1772. TCHAR szFunctionalityVersion[] = GPO_FUNCTIONALITY_VERSION;
  1773. TCHAR szFlags[] = TEXT("flags");
  1774. TCHAR szWmiFilter[] = TEXT("gPCWQLFilter");
  1775. PWSTR rgAttribs[12] = {szSDProperty,
  1776. szFileSysPath,
  1777. szCommonName,
  1778. szDisplayName,
  1779. szVersion,
  1780. szFunctionalityVersion,
  1781. szFlags,
  1782. GPO_MACHEXTENSION_NAMES,
  1783. GPO_USEREXTENSION_NAMES,
  1784. szObjectClass,
  1785. szWmiFilter,
  1786. NULL };
  1787. PGROUP_POLICY_OBJECT pGPOTemp = pDeferredForcedList;
  1788. LDAPQUERY *pLdapQuery = NULL, *pQuery = NULL;
  1789. VOID *pData;
  1790. PDS_API pdsApi;
  1791. BOOL bRsopPlanningMode = (pRsopToken != 0);
  1792. BOOL bConfigContainer = FALSE;
  1793. *ppForcedList = NULL;
  1794. *ppNonForcedList = NULL;
  1795. XLastError xe;
  1796. if ( pDeferredForcedList == NULL && pDeferredNonForcedList == NULL )
  1797. return TRUE;
  1798. //
  1799. // Demand load ntdsapi.dll
  1800. //
  1801. pdsApi = LoadDSApi();
  1802. if ( pdsApi == 0 ) {
  1803. xe = GetLastError();
  1804. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGpos: Failed to load ntdsapi.dll")));
  1805. goto Exit;
  1806. }
  1807. while ( pGPOTemp ) {
  1808. if ( !AddDN( pLDAP, &pLdapQuery, pGPOTemp->lpDSPath, NULL, pGPOTemp ) ) {
  1809. xe = GetLastError();
  1810. goto Exit;
  1811. }
  1812. pGPOTemp = pGPOTemp->pNext;
  1813. }
  1814. pGPOTemp = pDeferredNonForcedList;
  1815. while ( pGPOTemp ) {
  1816. if ( !AddDN( pLDAP, &pLdapQuery, pGPOTemp->lpDSPath, NULL, pGPOTemp ) ) {
  1817. xe = GetLastError();
  1818. goto Exit;
  1819. }
  1820. pGPOTemp = pGPOTemp->pNext;
  1821. }
  1822. //
  1823. // Setup the BER encoding
  1824. //
  1825. berValue[0] = 0x30;
  1826. berValue[1] = 0x03;
  1827. berValue[2] = 0x02; // denotes an integer
  1828. berValue[3] = 0x01; // denotes size
  1829. berValue[4] = (BYTE)((DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION) & 0xF);
  1830. pQuery = pLdapQuery;
  1831. while ( pQuery ) {
  1832. //
  1833. // The check below needs to be more sophisticated to take care
  1834. // of spaces in names etc.
  1835. //
  1836. // It is assumed that the configuration
  1837. // container would be common across the whole forest and will
  1838. // not need a new bind..
  1839. //
  1840. if (CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1841. pQuery->pwszDomain, 16, TEXT("cn=configuration"), 16) == CSTR_EQUAL ) {
  1842. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredGPOs: DN %s is under cn=configuration container"), pQuery->pwszDomain ));
  1843. bConfigContainer = TRUE;
  1844. }
  1845. else
  1846. bConfigContainer = FALSE;
  1847. //
  1848. // Check if this is a cross-domain Gpo and hence needs a new bind
  1849. //
  1850. WCHAR *pDomainString[1];
  1851. PDS_NAME_RESULT pNameResult = NULL;
  1852. PLDAP pLdapHandle = NULL;
  1853. if (!bConfigContainer)
  1854. pDomainString[0] = pQuery->pwszDomain;
  1855. else {
  1856. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredGPOs: The GPO is under the config container. Querying seperately\n")));
  1857. //
  1858. // This is a configuration container and we have to figure
  1859. // out the domain name still..
  1860. //
  1861. LPTSTR pwszTemp = pQuery->pwszDomain;
  1862. pDomainString[0] = NULL;
  1863. while ( *pwszTemp ) {
  1864. if (CompareString ( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1865. pwszTemp, 3, TEXT("DC="), 3) == CSTR_EQUAL ) {
  1866. pDomainString[0] = pwszTemp;
  1867. break;
  1868. }
  1869. //
  1870. // Move to the next chunk of the DN name
  1871. //
  1872. while ( *pwszTemp && (*pwszTemp != TEXT(',')))
  1873. pwszTemp++;
  1874. if ( *pwszTemp == TEXT(','))
  1875. pwszTemp++;
  1876. }
  1877. if ( pDomainString[0] == NULL ) {
  1878. xe = ERROR_INVALID_DATA;
  1879. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGPOs: Domain not found for <%s>. Exiting."), pQuery->pwszDomain ));
  1880. goto Exit;
  1881. }
  1882. }
  1883. ulResult = pdsApi->pfnDsCrackNames( (HANDLE) -1,
  1884. DS_NAME_FLAG_SYNTACTICAL_ONLY,
  1885. DS_FQDN_1779_NAME,
  1886. DS_CANONICAL_NAME,
  1887. 1,
  1888. pDomainString,
  1889. &pNameResult );
  1890. if ( ulResult != ERROR_SUCCESS
  1891. || pNameResult->cItems == 0
  1892. || pNameResult->rItems[0].status != ERROR_SUCCESS
  1893. || pNameResult->rItems[0].pDomain == NULL ) {
  1894. xe = ulResult;
  1895. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredGPOs: DsCrackNames failed with 0x%x."), ulResult ));
  1896. goto Exit;
  1897. }
  1898. //
  1899. // Optimize same domain Gpo queries by not doing an unnecessary bind
  1900. //
  1901. pQuery->pLdapHandle = pldBound;
  1902. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1903. pwszDomainBound, -1, pNameResult->rItems[0].pDomain, -1) != CSTR_EQUAL) {
  1904. //
  1905. // Cross-domain Gpo query and so need to bind to new domain
  1906. //
  1907. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredGPOs: Doing an ldap bind to cross-domain <%s>"),
  1908. pNameResult->rItems[0].pDomain));
  1909. pLdapHandle = pLDAP->pfnldap_init( pNameResult->rItems[0].pDomain, LDAP_PORT);
  1910. if (!pLdapHandle) {
  1911. xe = pLDAP->pfnLdapMapErrorToWin32(pLDAP->pfnLdapGetLastError());
  1912. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGPOs: ldap_init for <%s> failed with = 0x%x or %d"),
  1913. pNameResult->rItems[0].pDomain, pLDAP->pfnLdapGetLastError(), GetLastError()));
  1914. CEvents ev(TRUE, EVENT_FAILED_DS_INIT);
  1915. ev.AddArg(pNameResult->rItems[0].pDomain); ev.AddArgLdapError(pLDAP->pfnLdapGetLastError()); ev.Report();
  1916. pdsApi->pfnDsFreeNameResult( pNameResult );
  1917. goto Exit;
  1918. }
  1919. //
  1920. // Turn on Packet integrity flag
  1921. //
  1922. pData = (VOID *) LDAP_OPT_ON;
  1923. ulResult = pLDAP->pfnldap_set_option(pLdapHandle, LDAP_OPT_SIGN, &pData);
  1924. if (ulResult != LDAP_SUCCESS) {
  1925. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  1926. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGPOs: Failed to turn on LDAP_OPT_SIGN with %d"), ulResult));
  1927. pdsApi->pfnDsFreeNameResult( pNameResult );
  1928. pLDAP->pfnldap_unbind(pLdapHandle);
  1929. pLdapHandle = 0;
  1930. goto Exit;
  1931. }
  1932. ulResult = pLDAP->pfnldap_connect(pLdapHandle, 0);
  1933. if (ulResult != LDAP_SUCCESS) {
  1934. CEvents ev(TRUE, EVENT_FAILED_DS_CONNECT);
  1935. ev.AddArg(pNameResult->rItems[0].pDomain); ev.AddArgLdapError(ulResult); ev.Report();
  1936. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  1937. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGPOs: Failed to connect with %d"), ulResult));
  1938. pdsApi->pfnDsFreeNameResult( pNameResult );
  1939. pLDAP->pfnldap_unbind(pLdapHandle);
  1940. pLdapHandle = 0;
  1941. goto Exit;
  1942. }
  1943. //
  1944. // Transfer ownerhip of ldap handle to pQuery struct
  1945. //
  1946. pQuery->pLdapHandle = pLdapHandle;
  1947. pQuery->bOwnLdapHandle = TRUE;
  1948. if ( !bRsopPlanningMode && (dwFlags & GPO_LIST_FLAG_MACHINE) ) {
  1949. //
  1950. // For machine policies specifically ask for Kerberos as the only authentication
  1951. // mechanism. Otherwise if Kerberos were to fail for some reason, then NTLM is used
  1952. // and localsystem context has no real credentials, which means that we won't get
  1953. // any GPOs back.
  1954. //
  1955. SEC_WINNT_AUTH_IDENTITY_EXW secIdentity;
  1956. secIdentity.Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
  1957. secIdentity.Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EXW);
  1958. secIdentity.User = 0;
  1959. secIdentity.UserLength = 0;
  1960. secIdentity.Domain = 0;
  1961. secIdentity.DomainLength = 0;
  1962. secIdentity.Password = 0;
  1963. secIdentity.PasswordLength = 0;
  1964. secIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  1965. secIdentity.PackageList = wszKerberos;
  1966. secIdentity.PackageListLength = lstrlen( wszKerberos );
  1967. ulResult = pLDAP->pfnldap_bind_s (pLdapHandle, NULL, (WCHAR *)&secIdentity, LDAP_AUTH_SSPI);
  1968. } else
  1969. ulResult = pLDAP->pfnldap_bind_s (pLdapHandle, NULL, NULL, LDAP_AUTH_SSPI);
  1970. if (ulResult != LDAP_SUCCESS) {
  1971. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  1972. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGPOs: ldap_bind_s failed with = <%d>"),
  1973. ulResult));
  1974. CEvents ev(TRUE, EVENT_FAILED_DS_BIND);
  1975. ev.AddArg(pNameResult->rItems[0].pDomain); ev.AddArgLdapError(ulResult); ev.Report();
  1976. pdsApi->pfnDsFreeNameResult( pNameResult );
  1977. goto Exit;
  1978. }
  1979. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredGPOs: Bind sucessful")));
  1980. }
  1981. pdsApi->pfnDsFreeNameResult( pNameResult );
  1982. //
  1983. // Turn referrals off because this is a single domain call
  1984. //
  1985. pData = (VOID *) LDAP_OPT_OFF;
  1986. ulResult = pLDAP->pfnldap_set_option( pQuery->pLdapHandle, LDAP_OPT_REFERRALS, &pData );
  1987. if ( ulResult != LDAP_SUCCESS )
  1988. {
  1989. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  1990. DebugMsg((DM_WARNING, TEXT("EvalauteDeferredGPOs: Failed to turn off referrals with error %d"), ulResult));
  1991. goto Exit;
  1992. }
  1993. //
  1994. // Search for GPOs
  1995. //
  1996. DmAssert( pQuery->pwszDomain != NULL && pQuery->pwszFilter != NULL );
  1997. ulResult = pLDAP->pfnldap_search_ext_s(pQuery->pLdapHandle, pQuery->pwszDomain, LDAP_SCOPE_SUBTREE,
  1998. pQuery->pwszFilter, rgAttribs, 0,
  1999. (PLDAPControl*)ServerControls,
  2000. NULL, NULL, 0x10000, &pQuery->pMessage);
  2001. //
  2002. // If the search fails, store the error code and return
  2003. //
  2004. if (ulResult != LDAP_SUCCESS) {
  2005. if (ulResult == LDAP_NO_SUCH_ATTRIBUTE) {
  2006. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredGPOs: All objects can not be accessed.")));
  2007. if (dwFlags & GP_PLANMODE) {
  2008. CEvents ev(TRUE, EVENT_NO_GPOS2_PLANNING); ev.Report();
  2009. }
  2010. else {
  2011. if (bVerbose) {
  2012. CEvents ev(FALSE, EVENT_NO_GPOS2); ev.Report();
  2013. }
  2014. }
  2015. bResult = TRUE;
  2016. } else if (ulResult == LDAP_NO_SUCH_OBJECT) {
  2017. DebugMsg((DM_VERBOSE, TEXT("EvalateDeferredGPOs: Objects do not exist.") ));
  2018. if (dwFlags & GP_PLANMODE) {
  2019. // Same error or different
  2020. CEvents ev(TRUE, EVENT_NO_GPOS2_PLANNING); ev.Report();
  2021. }
  2022. else {
  2023. if (bVerbose) {
  2024. CEvents ev(FALSE, EVENT_NO_GPOS2); ev.Report();
  2025. }
  2026. }
  2027. bResult = TRUE;
  2028. } else if (ulResult == LDAP_SIZELIMIT_EXCEEDED) {
  2029. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  2030. DebugMsg((DM_WARNING, TEXT("EvalateDeferredGPOs: Too many GPOs in search.") ));
  2031. CEvents ev(TRUE, EVENT_TOO_MANY_GPOS); ev.Report();
  2032. } else {
  2033. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  2034. DebugMsg((DM_WARNING, TEXT("EvaluteDeferredGPOs: Failed to search with error 0x%x"), ulResult));
  2035. CEvents ev(TRUE, EVENT_FAILED_GPO_SEARCH);
  2036. ev.AddArgLdapError(ulResult); ev.Report();
  2037. }
  2038. goto Exit;
  2039. }
  2040. //
  2041. // If the search succeeds, but the message is empty,
  2042. // store the error code and return
  2043. //
  2044. if ( pQuery->pMessage == NULL ) {
  2045. xe = pLDAP->pfnLdapMapErrorToWin32(pQuery->pLdapHandle->ld_errno);
  2046. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredGPOs: Search returned an empty message structure. Error = 0x%x"),
  2047. pQuery->pLdapHandle->ld_errno));
  2048. goto Exit;
  2049. }
  2050. if ( !MatchDnWithDeferredItems( pLDAP, pQuery, FALSE ) ) {
  2051. xe = GetLastError();
  2052. goto Exit;
  2053. }
  2054. pQuery = pQuery->pNext;
  2055. } // while
  2056. if ( !EvalList( pLDAP, dwFlags, hToken, bVerbose,
  2057. pDeferredForcedList, ppForcedList, ppGpContainerList, pRsopToken, pGpoFilter, pLocator ) ) {
  2058. xe = GetLastError();
  2059. goto Exit;
  2060. }
  2061. if ( !EvalList( pLDAP, dwFlags, hToken, bVerbose,
  2062. pDeferredNonForcedList, ppNonForcedList, ppGpContainerList, pRsopToken, pGpoFilter, pLocator ) ) {
  2063. xe = GetLastError();
  2064. goto Exit;
  2065. }
  2066. bResult = TRUE;
  2067. Exit:
  2068. //
  2069. // Free all resources except for ppForcedList, ppNonForcedList
  2070. // which are owned by caller.
  2071. //
  2072. while ( pLdapQuery ) {
  2073. pQuery = pLdapQuery->pNext;
  2074. FreeLdapQuery( pLDAP, pLdapQuery );
  2075. pLdapQuery = pQuery;
  2076. }
  2077. return bResult;
  2078. }
  2079. //*************************************************************
  2080. //
  2081. // AddOU()
  2082. //
  2083. // Purpose: Appends an OU or domain to deferred list.
  2084. //
  2085. // Parameters: ppOUList - OU list to append to
  2086. // pwszOU - OU name
  2087. // gpoLink - Type of Gpo
  2088. //
  2089. // Return: TRUE if successful
  2090. // FALSE if an error occurs
  2091. //
  2092. //*************************************************************
  2093. BOOL AddOU( DNENTRY **ppOUList, LPTSTR pwszOU, GPO_LINK gpoLink )
  2094. {
  2095. DNENTRY *pOUTemp = *ppOUList;
  2096. DNENTRY *pOULast = NULL;
  2097. DNENTRY *pOUNew = AllocDnEntry( pwszOU );
  2098. if ( pOUNew == NULL ) {
  2099. return FALSE;
  2100. }
  2101. pOUNew->gpoLink = gpoLink;
  2102. while ( pOUTemp ) {
  2103. pOULast = pOUTemp;
  2104. pOUTemp = pOUTemp->pNext;
  2105. }
  2106. if ( pOULast )
  2107. pOULast->pNext = pOUNew;
  2108. else
  2109. *ppOUList = pOUNew;
  2110. return TRUE;
  2111. }
  2112. //*************************************************************
  2113. //
  2114. // EvaluateDeferredOUs()
  2115. //
  2116. // Purpose: Uses a single Ldap query to evaluate all OUs
  2117. //
  2118. // Parameters: ppOUList - OU list to append to
  2119. // dwFlags - GetGPOList flags
  2120. // pGPOForcedList - List of forced GPOs
  2121. // pGPONonForcedList - List of non-forced GPOs
  2122. // ppSOMList - List of LSDOUs
  2123. // ppGpContainerList - List of Gp Containers
  2124. // bVerbose - Verbose output
  2125. // pld - LDAP info
  2126. // pLDAP - LDAP api
  2127. // pLDAPMsg - LDAP message
  2128. // bBlock - Pointer to the block flag
  2129. // hToken - User / machine token
  2130. //
  2131. // Return: TRUE if successful
  2132. // FALSE if an error occurs
  2133. //
  2134. //*************************************************************
  2135. BOOL EvaluateDeferredOUs( DNENTRY *pOUList,
  2136. DWORD dwFlags,
  2137. HANDLE hToken,
  2138. PGROUP_POLICY_OBJECT *ppDeferredForcedList,
  2139. PGROUP_POLICY_OBJECT *ppDeferredNonForcedList,
  2140. LPSCOPEOFMGMT *ppSOMList,
  2141. LPGPCONTAINER *ppGpContainerList,
  2142. BOOL bVerbose,
  2143. PLDAP pld,
  2144. PLDAP_API pLDAP,
  2145. BOOL *pbBlock,
  2146. PRSOPTOKEN pRsopToken)
  2147. {
  2148. ULONG ulResult;
  2149. BOOL bResult = FALSE;
  2150. LDAPQUERY *pLdapQuery = NULL;
  2151. BYTE berValue[8];
  2152. LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR)berValue }, TRUE };
  2153. PLDAPControl ServerControls[] = { &SeInfoControl, NULL };
  2154. TCHAR szGPLink[] = TEXT("gPLink");
  2155. TCHAR szGPOptions[] = TEXT("gPOptions");
  2156. TCHAR szSDProperty[] = TEXT("nTSecurityDescriptor");
  2157. LPTSTR lpAttr[] = { szGPLink,
  2158. szGPOptions,
  2159. szSDProperty,
  2160. NULL
  2161. };
  2162. DNENTRY *pOUTemp = pOUList;
  2163. VOID *pData;
  2164. XLastError xe;
  2165. //
  2166. // Setup the BER encoding for the SD
  2167. //
  2168. berValue[0] = 0x30;
  2169. berValue[1] = 0x03;
  2170. berValue[2] = 0x02; // denotes an integer
  2171. berValue[3] = 0x01; // denotes size
  2172. berValue[4] = (BYTE)((DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION) & 0xF);
  2173. if ( !pRsopToken )
  2174. {
  2175. //
  2176. // if it is not planning mode, don't get the SD
  2177. //
  2178. lpAttr[2] = NULL;
  2179. ServerControls[0] = NULL;
  2180. }
  2181. if ( pOUTemp == NULL )
  2182. return TRUE;
  2183. while ( pOUTemp ) {
  2184. if ( !AddDN( pLDAP, &pLdapQuery, pOUTemp->pwszDN, pOUTemp, NULL ) ) {
  2185. xe = GetLastError();
  2186. goto Exit;
  2187. }
  2188. pOUTemp = pOUTemp->pNext;
  2189. }
  2190. pLdapQuery->pLdapHandle = pld;
  2191. //
  2192. // Turn referrals off because this is a single domain call
  2193. //
  2194. if ( !pRsopToken )
  2195. {
  2196. pData = (VOID *) LDAP_OPT_OFF;
  2197. ulResult = pLDAP->pfnldap_set_option( pLdapQuery->pLdapHandle, LDAP_OPT_REFERRALS, &pData );
  2198. if ( ulResult != LDAP_SUCCESS ) {
  2199. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  2200. DebugMsg((DM_WARNING, TEXT("EvaluteDeferredOUs: Failed to turn off referrals with error %d"), ulResult));
  2201. goto Exit;
  2202. }
  2203. }
  2204. ulResult = pLDAP->pfnldap_search_ext_s(pld, pLdapQuery->pwszDomain, LDAP_SCOPE_SUBTREE,
  2205. pLdapQuery->pwszFilter, lpAttr, FALSE,
  2206. (PLDAPControl*)ServerControls,
  2207. NULL, NULL, 0, &pLdapQuery->pMessage);
  2208. //
  2209. // If the search fails, store the error code and return
  2210. //
  2211. if (ulResult != LDAP_SUCCESS) {
  2212. if (ulResult == LDAP_NO_SUCH_ATTRIBUTE) {
  2213. DebugMsg((DM_VERBOSE, TEXT("EvaluateDeferredOUs: All objects can not be accessed.")));
  2214. bResult = TRUE;
  2215. } else if (ulResult == LDAP_NO_SUCH_OBJECT) {
  2216. DebugMsg((DM_VERBOSE, TEXT("EvalateDeferredOUs: Objects do not exist.") ));
  2217. bResult = TRUE;
  2218. } else if (ulResult == LDAP_SIZELIMIT_EXCEEDED) {
  2219. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  2220. DebugMsg((DM_WARNING, TEXT("EvalateDeferredOUs: Too many linked GPOs in search.") ));
  2221. CEvents ev(TRUE, EVENT_TOO_MANY_GPOS); ev.Report();
  2222. } else {
  2223. xe = pLDAP->pfnLdapMapErrorToWin32(ulResult);
  2224. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredOUs: Failed to search with error %d"), ulResult));
  2225. CEvents ev(TRUE, EVENT_FAILED_OU_SEARCH);
  2226. ev.AddArg(ulResult); ev.Report();
  2227. }
  2228. goto Exit;
  2229. }
  2230. //
  2231. // If the search succeeds, but the message is empty,
  2232. // store the error code and return
  2233. //
  2234. if ( pLdapQuery->pMessage == NULL ) {
  2235. xe = pLDAP->pfnLdapMapErrorToWin32(pld->ld_errno);
  2236. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredOUs: Search returned an empty message structure. Error = %d"),
  2237. pld->ld_errno));
  2238. goto Exit;
  2239. }
  2240. if ( !MatchDnWithDeferredItems( pLDAP, pLdapQuery, TRUE ) ) {
  2241. xe = GetLastError();
  2242. goto Exit;
  2243. }
  2244. //
  2245. // Evaluate the OU list
  2246. //
  2247. pOUTemp = pOUList;
  2248. while ( pOUTemp ) {
  2249. PLDAPMessage pOUMsg = pOUTemp->pOUMsg;
  2250. if ( pOUMsg == NULL ) {
  2251. xe = ERROR_INVALID_DATA;
  2252. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredOUs: Object <%s> cannot be accessed"),
  2253. pOUTemp->pwszDN ));
  2254. CEvents ev(TRUE, EVENT_OU_NOTFOUND);
  2255. ev.AddArg(pOUTemp->pwszDN); ev.Report();
  2256. goto Exit;
  2257. } else {
  2258. if ( !SearchDSObject( pOUTemp->pwszDN, dwFlags, hToken, ppDeferredForcedList, ppDeferredNonForcedList,
  2259. ppSOMList, ppGpContainerList,
  2260. bVerbose, pOUTemp->gpoLink, pld, pLDAP, pOUMsg, pbBlock, pRsopToken)) {
  2261. xe = GetLastError();
  2262. DebugMsg((DM_WARNING, TEXT("EvaluateDeferredOUs: SearchDSObject failed") ));
  2263. goto Exit;
  2264. }
  2265. }
  2266. pOUTemp = pOUTemp->pNext;
  2267. }
  2268. bResult = TRUE;
  2269. Exit:
  2270. while ( pLdapQuery ) {
  2271. LDAPQUERY *pQuery = pLdapQuery->pNext;
  2272. FreeLdapQuery( pLDAP, pLdapQuery );
  2273. pLdapQuery = pQuery;
  2274. }
  2275. return bResult;
  2276. }
  2277. //*************************************************************
  2278. //
  2279. // GetMachineDomainDS()
  2280. //
  2281. // Purpose: Obtain the machine domain DS
  2282. //
  2283. // Parameters: pNetApi32 - netapi32.dll
  2284. // pLdapApi - wldap32.dll
  2285. //
  2286. // Return: valid PLDAP if successful
  2287. // 0 if an error occurs
  2288. //
  2289. //*************************************************************
  2290. PLDAP
  2291. GetMachineDomainDS( PNETAPI32_API pNetApi32, PLDAP_API pLdapApi )
  2292. {
  2293. PLDAP pld = 0;
  2294. DWORD dwResult = 0;
  2295. PDOMAIN_CONTROLLER_INFO pDCI = 0;
  2296. ULONG ulResult;
  2297. VOID *pData;
  2298. XLastError xe;
  2299. //
  2300. // get the machine domain name
  2301. //
  2302. dwResult = pNetApi32->pfnDsGetDcName( 0,
  2303. 0,
  2304. 0,
  2305. 0,
  2306. DS_DIRECTORY_SERVICE_REQUIRED,
  2307. &pDCI);
  2308. if ( dwResult == ERROR_SUCCESS )
  2309. {
  2310. SEC_WINNT_AUTH_IDENTITY_EXW secIdentity;
  2311. pld = pLdapApi->pfnldap_init( pDCI->DomainName, LDAP_PORT );
  2312. if (!pld) {
  2313. xe = pLdapApi->pfnLdapMapErrorToWin32(pLdapApi->pfnLdapGetLastError());
  2314. DebugMsg((DM_WARNING, TEXT("GetMachineDomainDS: ldap_open for <%s> failed with = 0x%x or %d"),
  2315. pDCI->DomainName, pLdapApi->pfnLdapGetLastError(), GetLastError()));
  2316. return pld;
  2317. }
  2318. //
  2319. // Turn on Packet integrity flag
  2320. //
  2321. pData = (VOID *) LDAP_OPT_ON;
  2322. ulResult = pLdapApi->pfnldap_set_option(pld, LDAP_OPT_SIGN, &pData);
  2323. if (ulResult != LDAP_SUCCESS) {
  2324. xe = pLdapApi->pfnLdapMapErrorToWin32(ulResult);
  2325. DebugMsg((DM_WARNING, TEXT("GetMachineDomainDS: Failed to turn on LDAP_OPT_SIGN with %d"), ulResult));
  2326. pLdapApi->pfnldap_unbind(pld);
  2327. pld = 0;
  2328. return pld;
  2329. }
  2330. ulResult = pLdapApi->pfnldap_connect(pld, 0);
  2331. if (ulResult != LDAP_SUCCESS) {
  2332. xe = pLdapApi->pfnLdapMapErrorToWin32(ulResult);
  2333. DebugMsg((DM_WARNING, TEXT("GetMachineDomainDS: Failed to connect with %d"), ulResult));
  2334. pLdapApi->pfnldap_unbind(pld);
  2335. pld = 0;
  2336. return pld;
  2337. }
  2338. //
  2339. // For machine policies specifically ask for Kerberos as the only authentication
  2340. // mechanism. Otherwise if Kerberos were to fail for some reason, then NTLM is used
  2341. // and localsystem context has no real credentials, which means that we won't get
  2342. // any GPOs back.
  2343. //
  2344. secIdentity.Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
  2345. secIdentity.Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EXW);
  2346. secIdentity.User = 0;
  2347. secIdentity.UserLength = 0;
  2348. secIdentity.Domain = 0;
  2349. secIdentity.DomainLength = 0;
  2350. secIdentity.Password = 0;
  2351. secIdentity.PasswordLength = 0;
  2352. secIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  2353. secIdentity.PackageList = wszKerberos;
  2354. secIdentity.PackageListLength = lstrlen( wszKerberos );
  2355. if ( (ulResult = pLdapApi->pfnldap_bind_s (pld, 0, (WCHAR *)&secIdentity, LDAP_AUTH_SSPI)) != LDAP_SUCCESS )
  2356. {
  2357. xe = pLdapApi->pfnLdapMapErrorToWin32(ulResult);
  2358. pLdapApi->pfnldap_unbind(pld);
  2359. pld = 0;
  2360. }
  2361. pNetApi32->pfnNetApiBufferFree(pDCI);
  2362. }
  2363. else
  2364. {
  2365. xe = dwResult;
  2366. DebugMsg((DM_WARNING, TEXT("GetMachineDomainDS: The domain does not have a DS")));
  2367. }
  2368. return pld;
  2369. }
  2370. //*************************************************************
  2371. //
  2372. // AllocSOM()
  2373. //
  2374. // Purpose: Allocates a new struct for SOM
  2375. //
  2376. //
  2377. // Parameters: pwszSOMId - Name of SOM
  2378. //
  2379. // Return: Pointer if successful
  2380. // NULL if an error occurs
  2381. //
  2382. //*************************************************************
  2383. SCOPEOFMGMT *AllocSOM( LPWSTR pwszSOMId )
  2384. {
  2385. XLastError xe;
  2386. SCOPEOFMGMT *pSOM = (SCOPEOFMGMT *) LocalAlloc( LPTR, sizeof(SCOPEOFMGMT) );
  2387. if ( pSOM == NULL ) {
  2388. xe = GetLastError();
  2389. return NULL;
  2390. }
  2391. pSOM->pwszSOMId = (LPWSTR) LocalAlloc( LPTR, (lstrlen(pwszSOMId) + 1) * sizeof(WCHAR) );
  2392. if ( pSOM->pwszSOMId == NULL ) {
  2393. xe = GetLastError();
  2394. LocalFree( pSOM );
  2395. return NULL;
  2396. }
  2397. lstrcpy( pSOM->pwszSOMId, pwszSOMId );
  2398. return pSOM;
  2399. }
  2400. //*************************************************************
  2401. //
  2402. // FreeSOM()
  2403. //
  2404. // Purpose: Frees SOM struct
  2405. //
  2406. // Parameters: pSOM - SOM to free
  2407. //
  2408. //*************************************************************
  2409. void FreeSOM( SCOPEOFMGMT *pSOM )
  2410. {
  2411. GPLINK *pGpLink = NULL;
  2412. if ( pSOM ) {
  2413. LocalFree( pSOM->pwszSOMId );
  2414. pGpLink = pSOM->pGpLinkList;
  2415. while ( pGpLink ) {
  2416. GPLINK *pTemp = pGpLink->pNext;
  2417. FreeGpLink( pGpLink );
  2418. pGpLink = pTemp;
  2419. }
  2420. LocalFree( pSOM );
  2421. }
  2422. }
  2423. //*************************************************************
  2424. //
  2425. // AllocGpLink()
  2426. //
  2427. // Purpose: Allocates a new struct for GpLink
  2428. //
  2429. //
  2430. // Parameters: pwszGPO - Name of GPO
  2431. //
  2432. // Return: Pointer if successful
  2433. // NULL if an error occurs
  2434. //
  2435. //*************************************************************
  2436. GPLINK *AllocGpLink( LPWSTR pwszGPO, DWORD dwOptions )
  2437. {
  2438. //
  2439. // Strip out "LDAP://" prefix to get canonical Gpo path
  2440. //
  2441. WCHAR wszPrefix[] = TEXT("LDAP://");
  2442. INT iPrefixLen = lstrlen( wszPrefix );
  2443. WCHAR *pwszPath = pwszGPO;
  2444. GPLINK *pGpLink = NULL;
  2445. XLastError xe;
  2446. if ( (lstrlen(pwszGPO) > iPrefixLen)
  2447. && CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  2448. pwszGPO, iPrefixLen, wszPrefix, iPrefixLen ) == CSTR_EQUAL ) {
  2449. pwszPath = pwszGPO + iPrefixLen;
  2450. }
  2451. pGpLink = (GPLINK *) LocalAlloc( LPTR, sizeof(GPLINK) );
  2452. if ( pGpLink == NULL ) {
  2453. xe = GetLastError();
  2454. return NULL;
  2455. }
  2456. pGpLink->pwszGPO = (LPWSTR) LocalAlloc( LPTR, (lstrlen(pwszPath) + 1) * sizeof(WCHAR) );
  2457. if ( pGpLink->pwszGPO == NULL ) {
  2458. xe = GetLastError();
  2459. LocalFree( pGpLink );
  2460. return NULL;
  2461. }
  2462. lstrcpy( pGpLink->pwszGPO, pwszPath );
  2463. pGpLink->bEnabled = (dwOptions & GPO_FLAG_DISABLE) ? FALSE : TRUE;
  2464. if ( dwOptions & GPO_FLAG_FORCE )
  2465. pGpLink->bNoOverride = TRUE;
  2466. return pGpLink;
  2467. }
  2468. //*************************************************************
  2469. //
  2470. // FreeGpLink()
  2471. //
  2472. // Purpose: Frees GpLink struct
  2473. //
  2474. // Parameters: pGpLink - GpLink to free
  2475. //
  2476. //*************************************************************
  2477. void FreeGpLink( GPLINK *pGpLink )
  2478. {
  2479. if ( pGpLink ) {
  2480. LocalFree( pGpLink->pwszGPO );
  2481. LocalFree( pGpLink );
  2482. }
  2483. }
  2484. //*************************************************************
  2485. //
  2486. // AllocGpContainer()
  2487. //
  2488. // Purpose: Allocates a new struct for GpContainer
  2489. //
  2490. //
  2491. // Parameters: dwFlags - Flags
  2492. // bFound - Was Gpo found ?
  2493. // bAccessGranted - Was access granted ?
  2494. // bDisabled - Is Gp Container disabled ?
  2495. // dwVersion - Version #
  2496. // lpDSPath - DS path to Gpo
  2497. // lpFileSysPath - Sysvol path to Gpo
  2498. // lpDisplayName - Friendly name
  2499. // lpGpoName - Guid name
  2500. // pSD - Security descriptor
  2501. // cbSDLen - Length of security descriptor
  2502. // bFilterAllowed - Does GPO pass filter check
  2503. // pwszFilterId - WQL filter id
  2504. //
  2505. // Return: Pointer if successful
  2506. // NULL if an error occurs
  2507. //
  2508. //*************************************************************
  2509. GPCONTAINER *AllocGpContainer( DWORD dwFlags,
  2510. BOOL bFound,
  2511. BOOL bAccessGranted,
  2512. BOOL bDisabled,
  2513. DWORD dwVersion,
  2514. LPTSTR lpDSPath,
  2515. LPTSTR lpFileSysPath,
  2516. LPTSTR lpDisplayName,
  2517. LPTSTR lpGpoName,
  2518. PSECURITY_DESCRIPTOR pSD,
  2519. DWORD cbSDLen,
  2520. BOOL bFilterAllowed,
  2521. WCHAR *pwszFilterId,
  2522. LPWSTR szSOM,
  2523. DWORD dwOptions )
  2524. {
  2525. WCHAR wszMachPrefix[] = TEXT("LDAP://CN=Machine,");
  2526. INT iMachPrefixLen = lstrlen( wszMachPrefix );
  2527. WCHAR wszUserPrefix[] = TEXT("LDAP://CN=User,");
  2528. INT iUserPrefixLen = lstrlen( wszUserPrefix );
  2529. WCHAR *pwszPath = lpDSPath;
  2530. BOOL bResult = FALSE;
  2531. GPCONTAINER *pGpContainer = NULL;
  2532. XLastError xe;
  2533. //
  2534. // Strip out prefix, if any, to get the canonical path to Gpo
  2535. //
  2536. if ( (lstrlen(lpDSPath) > iUserPrefixLen)
  2537. && CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  2538. lpDSPath, iUserPrefixLen, wszUserPrefix, iUserPrefixLen ) == CSTR_EQUAL ) {
  2539. pwszPath = lpDSPath + iUserPrefixLen;
  2540. } else if ( (lstrlen(lpDSPath) > iMachPrefixLen)
  2541. && CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  2542. lpDSPath, iMachPrefixLen, wszMachPrefix, iMachPrefixLen ) == CSTR_EQUAL ) {
  2543. pwszPath = lpDSPath + iMachPrefixLen;
  2544. }
  2545. pGpContainer = (GPCONTAINER *) LocalAlloc( LPTR, sizeof(GPCONTAINER) );
  2546. if ( pGpContainer == NULL ) {
  2547. xe = GetLastError();
  2548. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2549. return NULL;
  2550. }
  2551. pGpContainer->bAccessDenied = !bAccessGranted;
  2552. pGpContainer->bFound = bFound;
  2553. if ( dwFlags & GP_MACHINE ) {
  2554. pGpContainer->bMachDisabled = bDisabled;
  2555. pGpContainer->dwMachVersion = dwVersion;
  2556. } else {
  2557. pGpContainer->bUserDisabled = bDisabled;
  2558. pGpContainer->dwUserVersion = dwVersion;
  2559. }
  2560. if ( pwszPath ) {
  2561. pGpContainer->pwszDSPath = (LPWSTR) LocalAlloc( LPTR, (lstrlen(pwszPath) + 1) * sizeof(WCHAR) );
  2562. if ( pGpContainer->pwszDSPath == NULL ) {
  2563. xe = GetLastError();
  2564. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2565. goto Exit;
  2566. }
  2567. lstrcpy( pGpContainer->pwszDSPath, pwszPath );
  2568. }
  2569. if ( lpGpoName ) {
  2570. pGpContainer->pwszGPOName = (LPWSTR) LocalAlloc( LPTR, (lstrlen(lpGpoName) + 1) * sizeof(WCHAR) );
  2571. if ( pGpContainer->pwszGPOName == NULL ) {
  2572. xe = GetLastError();
  2573. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2574. goto Exit;
  2575. }
  2576. lstrcpy( pGpContainer->pwszGPOName, lpGpoName );
  2577. }
  2578. if ( lpDisplayName ) {
  2579. pGpContainer->pwszDisplayName = (LPWSTR) LocalAlloc( LPTR, (lstrlen(lpDisplayName) + 1) * sizeof(WCHAR) );
  2580. if ( pGpContainer->pwszDisplayName == NULL ) {
  2581. xe = GetLastError();
  2582. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2583. goto Exit;
  2584. }
  2585. lstrcpy( pGpContainer->pwszDisplayName, lpDisplayName );
  2586. }
  2587. if ( lpFileSysPath ) {
  2588. pGpContainer->pwszFileSysPath = (LPWSTR) LocalAlloc( LPTR, (lstrlen(lpFileSysPath) + 1) * sizeof(WCHAR) );
  2589. if ( pGpContainer->pwszFileSysPath == NULL ) {
  2590. xe = GetLastError();
  2591. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2592. goto Exit;
  2593. }
  2594. lstrcpy( pGpContainer->pwszFileSysPath, lpFileSysPath );
  2595. }
  2596. if ( cbSDLen != 0 ) {
  2597. pGpContainer->pSD = (PSECURITY_DESCRIPTOR) LocalAlloc( LPTR, cbSDLen );
  2598. if ( pGpContainer->pSD == NULL ) {
  2599. xe = GetLastError();
  2600. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2601. goto Exit;
  2602. }
  2603. CopyMemory( pGpContainer->pSD, pSD, cbSDLen );
  2604. }
  2605. pGpContainer->cbSDLen = cbSDLen;
  2606. pGpContainer->bFilterAllowed = bFilterAllowed;
  2607. if ( pwszFilterId ) {
  2608. pGpContainer->pwszFilterId = (LPWSTR) LocalAlloc( LPTR, (lstrlen(pwszFilterId) + 1) * sizeof(WCHAR) );
  2609. if ( pGpContainer->pwszFilterId == NULL ) {
  2610. xe = GetLastError();
  2611. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2612. goto Exit;
  2613. }
  2614. lstrcpy( pGpContainer->pwszFilterId, pwszFilterId );
  2615. }
  2616. if ( szSOM )
  2617. {
  2618. pGpContainer->szSOM = (LPWSTR) LocalAlloc( LPTR, (lstrlen(szSOM) + 1) * sizeof(WCHAR) );
  2619. if ( !pGpContainer->szSOM )
  2620. {
  2621. xe = GetLastError();
  2622. DebugMsg((DM_WARNING, TEXT("AllocGpContainer: Unable to allocate memory for GpContainer object")));
  2623. goto Exit;
  2624. }
  2625. wcscpy( pGpContainer->szSOM, szSOM );
  2626. }
  2627. pGpContainer->dwOptions = dwOptions;
  2628. bResult = TRUE;
  2629. Exit:
  2630. if ( !bResult )
  2631. {
  2632. LocalFree( pGpContainer->pwszDSPath );
  2633. LocalFree( pGpContainer->pwszGPOName );
  2634. LocalFree( pGpContainer->pwszDisplayName );
  2635. LocalFree( pGpContainer->pwszFileSysPath );
  2636. LocalFree( pGpContainer->pSD );
  2637. LocalFree( pGpContainer->pwszFilterId );
  2638. LocalFree( pGpContainer->szSOM );
  2639. LocalFree( pGpContainer );
  2640. return 0;
  2641. }
  2642. return pGpContainer;
  2643. }
  2644. //*************************************************************
  2645. //
  2646. // FreeGpContainer()
  2647. //
  2648. // Purpose: Frees GpContainer struct
  2649. //
  2650. // Parameters: pGpContainer - Gp Container to free
  2651. //
  2652. //*************************************************************
  2653. void FreeGpContainer( GPCONTAINER *pGpContainer )
  2654. {
  2655. if ( pGpContainer ) {
  2656. LocalFree( pGpContainer->pwszDSPath );
  2657. LocalFree( pGpContainer->pwszGPOName );
  2658. LocalFree( pGpContainer->pwszDisplayName );
  2659. LocalFree( pGpContainer->pwszFileSysPath );
  2660. LocalFree( pGpContainer->pSD );
  2661. LocalFree( pGpContainer->pwszFilterId );
  2662. LocalFree( pGpContainer->szSOM );
  2663. LocalFree( pGpContainer );
  2664. }
  2665. }
  2666. //*************************************************************
  2667. //
  2668. // FreeSOMList()
  2669. //
  2670. // Purpose: Frees list of SOMs
  2671. //
  2672. // Parameters: pSOMList - SOM list to free
  2673. //
  2674. //*************************************************************
  2675. void FreeSOMList( SCOPEOFMGMT *pSOMList )
  2676. {
  2677. if ( pSOMList == NULL )
  2678. return;
  2679. while ( pSOMList ) {
  2680. SCOPEOFMGMT *pTemp = pSOMList->pNext;
  2681. FreeSOM( pSOMList );
  2682. pSOMList = pTemp;
  2683. }
  2684. }
  2685. //*************************************************************
  2686. //
  2687. // FreeGpContainerList()
  2688. //
  2689. // Purpose: Frees list of Gp Containers
  2690. //
  2691. // Parameters: pGpContainerList - Gp Container list to free
  2692. //
  2693. //*************************************************************
  2694. void FreeGpContainerList( GPCONTAINER *pGpContainerList )
  2695. {
  2696. if ( pGpContainerList == NULL )
  2697. return;
  2698. while ( pGpContainerList ) {
  2699. GPCONTAINER *pTemp = pGpContainerList->pNext;
  2700. FreeGpContainer( pGpContainerList );
  2701. pGpContainerList = pTemp;
  2702. }
  2703. }
  2704. LPTSTR GetSomPath( LPTSTR szContainer )
  2705. {
  2706. while (*szContainer) {
  2707. //
  2708. // See if the DN name starts with OU=
  2709. //
  2710. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  2711. szContainer, 3, TEXT("OU="), 3) == CSTR_EQUAL) {
  2712. break;
  2713. }
  2714. //
  2715. // See if the DN name starts with DC=
  2716. //
  2717. else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  2718. szContainer, 3, TEXT("DC="), 3) == CSTR_EQUAL) {
  2719. break;
  2720. }
  2721. //
  2722. // Move to the next chunk of the DN name
  2723. //
  2724. while (*szContainer && (*szContainer != TEXT(','))) {
  2725. szContainer++;
  2726. }
  2727. if (*szContainer == TEXT(',')) {
  2728. szContainer++;
  2729. }
  2730. }
  2731. if (!*szContainer) {
  2732. return NULL;
  2733. }
  2734. return szContainer;
  2735. }