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.

1632 lines
52 KiB

  1. //*************************************************************
  2. //
  3. // Group Policy Support for planning mode
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1997-1998
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "gphdr.h"
  11. DWORD GenerateRegistryPolicy( DWORD dwFlags,
  12. BOOL *pbAbort,
  13. WCHAR *pwszSite,
  14. PRSOP_TARGET pComputerTarget,
  15. PRSOP_TARGET pUserTarget );
  16. BOOL GenerateGpoInfo( WCHAR *pwszDomain, WCHAR *pwszDomainDns, WCHAR *pwszAccount,
  17. WCHAR *pwszNewSOM, SAFEARRAY *psaSecGroups,
  18. DWORD dwFlags, BOOL bMachine, WCHAR *pwszSite, CGpoFilter *pGpoFilter, CLocator *pLocator,
  19. WCHAR *pwszMachAccount, WCHAR *pwszNewMachSOM, LPGPOINFO pGpoInfo, PNETAPI32_API pNetAPI32 );
  20. BOOL GetCategory( WCHAR *pwszDomain, WCHAR *pwszAccount, WCHAR **ppwszDNName );
  21. DWORD ProcessMachAndUserGpoList( LPGPEXT lpExtMach, LPGPEXT lpExtUser, DWORD dwFlags, WCHAR *pwszSite,
  22. WCHAR *pwszMach, WCHAR *pwszNewComputerOU, SAFEARRAY *psaComputerSecurityGroups, LPGPOINFO pGpoInfoMach,
  23. WCHAR *pwszUser, WCHAR *pwszNewUserOU, SAFEARRAY *psaUserSecurityGroups, LPGPOINFO pGpoInfoUser );
  24. BOOL ProcessRegistryFiles(PRSOP_TARGET pTarget, REGHASHTABLE *pHashTable);
  25. BOOL ProcessRegistryValue ( void* pUnused,
  26. LPTSTR lpKeyName,
  27. LPTSTR lpValueName,
  28. DWORD dwType,
  29. DWORD dwDataLength,
  30. LPBYTE lpData,
  31. WCHAR *pwszGPO,
  32. WCHAR *pwszSOM,
  33. REGHASHTABLE *pHashTable);
  34. BOOL ProcessAdmData( PRSOP_TARGET pTarget, BOOL bUser );
  35. //*************************************************************
  36. //
  37. // GenerateRsopPolicy()
  38. //
  39. // Purpose: Generates planning mode Rsop policy for specified target
  40. //
  41. // Parameters: dwFlags - Processing flags
  42. // bstrMachName - Target computer name
  43. // bstrNewMachSOM - New machine domain or OU
  44. // psaMachSecGroups - New machine security groups
  45. // bstrUserName - Target user name
  46. // psaUserSecGroups - New user security groups
  47. // bstrSite - Site of target computer
  48. // pwszNameSpace - Namespace to write Rsop data
  49. // pvProgress - Progress indicator class
  50. // pvGpoFilter - GPO filter class
  51. //
  52. // Return: True if successful, False otherwise
  53. //
  54. // Notes: If a new SOM is specified then that is used instead of
  55. // the SOM the target belongs to. Similarly, if new
  56. // security groups are specified then that is used instead of
  57. // the security groups that the target belongs to. If
  58. // target name is null and both new SOM and new security
  59. // groups are non-null, then we simulate a dummy target; otherwise
  60. // we skip generating planning mode info for the target.
  61. //
  62. //*************************************************************
  63. BOOL GenerateRsopPolicy( DWORD dwFlags, BSTR bstrMachName,
  64. BSTR bstrNewMachSOM, SAFEARRAY *psaMachSecGroups,
  65. BSTR bstrUserName, BSTR bstrNewUserSOM,
  66. SAFEARRAY *psaUserSecGroups,
  67. BSTR bstrSite,
  68. WCHAR *pwszNameSpace,
  69. LPVOID pvProgress,
  70. LPVOID pvMachGpoFilter,
  71. LPVOID pvUserGpoFilter )
  72. {
  73. LPGPOINFO pGpoInfoMach = NULL;
  74. LPGPOINFO pGpoInfoUser = NULL;
  75. PNETAPI32_API pNetAPI32 = NULL;
  76. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsInfo = NULL;
  77. BOOL bDC = FALSE;
  78. DWORD dwResult;
  79. LPWSTR pwszDomain = NULL;
  80. LPWSTR pwszMachDns = NULL;
  81. LPWSTR pwszDomainDns = NULL;
  82. DWORD dwSize = 0;
  83. BOOL bResult = FALSE;
  84. LPGPEXT lpExtMach = NULL;
  85. LPGPEXT lpExtUser = NULL;
  86. LPGPEXT lpExt,lpTemp = NULL;
  87. WCHAR *pwszMach = (WCHAR *) bstrMachName;
  88. WCHAR *pwszUser = (WCHAR *) bstrUserName;
  89. DWORD dwExtCount = 1;
  90. DWORD dwIncrPercent;
  91. CProgressIndicator* pProgress = (CProgressIndicator*) pvProgress;
  92. CGpoFilter *pMachGpoFilter = (CGpoFilter *) pvMachGpoFilter;
  93. CGpoFilter *pUserGpoFilter = (CGpoFilter *) pvUserGpoFilter;
  94. RSOPSESSIONDATA rsopSessionData;
  95. LPRSOPSESSIONDATA lprsopSessionData;
  96. BOOL bDummyMach = pwszMach == NULL && bstrNewMachSOM != NULL;
  97. BOOL bDummyUser = pwszUser == NULL && bstrNewUserSOM != NULL;
  98. DWORD dwUserGPCoreError = ERROR_SUCCESS;
  99. DWORD dwMachGPCoreError = ERROR_SUCCESS;
  100. CLocator locator;
  101. HRESULT hr = S_OK;
  102. XLastError xe;
  103. //
  104. // Allow debugging level to be changed dynamically
  105. //
  106. InitDebugSupport( FALSE );
  107. if ( pwszUser == NULL && pwszMach == NULL && !bDummyUser && !bDummyMach ) {
  108. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Both user and machine names cannot be NULL.")));
  109. xe = ERROR_INVALID_PARAMETER;
  110. return FALSE;
  111. }
  112. pNetAPI32 = LoadNetAPI32();
  113. if (!pNetAPI32) {
  114. xe = GetLastError();
  115. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Failed to load netapi32 with %d."),
  116. GetLastError()));
  117. // error logged in LoadNetAPI32
  118. goto Exit;
  119. }
  120. //
  121. // Get the role of this computer
  122. //
  123. dwResult = pNetAPI32->pfnDsRoleGetPrimaryDomainInformation( NULL, DsRolePrimaryDomainInfoBasic,
  124. (PBYTE *)&pDsInfo );
  125. if (dwResult != ERROR_SUCCESS) {
  126. xe = GetLastError();
  127. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: DsRoleGetPrimaryDomainInformation failed with %d."), dwResult));
  128. goto Exit;
  129. }
  130. if ( pDsInfo->MachineRole == DsRole_RoleBackupDomainController
  131. || pDsInfo->MachineRole == DsRole_RolePrimaryDomainController ) {
  132. bDC = TRUE;
  133. }
  134. if ( !bDC ) {
  135. xe = ERROR_ACCESS_DENIED;
  136. DebugMsg((DM_WARNING, TEXT("GeneratRsopPolicy: Rsop data can be generated on a DC only")));
  137. goto Exit;
  138. }
  139. pwszDomain = pDsInfo->DomainNameFlat;
  140. //
  141. // Get the machine name in dns format, so that ldap_bind can be done to this specific DC.
  142. //
  143. dwSize = 0;
  144. GetComputerNameEx( ComputerNameDnsFullyQualified, pwszMachDns, &dwSize );
  145. if ( dwSize > 0 ) {
  146. pwszMachDns = (WCHAR *) LocalAlloc (LPTR, dwSize * sizeof(WCHAR) );
  147. if ( pwszMachDns == NULL ) {
  148. xe = GetLastError();
  149. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Failed to allocate memory")));
  150. goto Exit;
  151. }
  152. } else {
  153. xe = GetLastError();
  154. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GetComputerNameEx failed")));
  155. goto Exit;
  156. }
  157. bResult = GetComputerNameEx( ComputerNameDnsFullyQualified, pwszMachDns, &dwSize );
  158. if ( !bResult ) {
  159. xe = GetLastError();
  160. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GetComputerNameEx failed")));
  161. goto Exit;
  162. }
  163. pwszDomainDns = pwszMachDns;
  164. //
  165. // 5% of the task is done
  166. //
  167. pProgress->IncrementBy( 5 );
  168. //
  169. // Setup computer target info, if any
  170. //
  171. bResult = FALSE;
  172. if ( pwszMach || bDummyMach ) {
  173. pGpoInfoMach = (LPGPOINFO) LocalAlloc (LPTR, sizeof(GPOINFO));
  174. if (!pGpoInfoMach) {
  175. xe = GetLastError();
  176. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to alloc lpGPOInfo (%d)."),
  177. GetLastError()));
  178. CEvents ev(TRUE, EVENT_FAILED_ALLOCATION);
  179. ev.AddArgWin32Error(GetLastError()); ev.Report();
  180. goto Exit;
  181. }
  182. pGpoInfoMach->dwFlags = GP_PLANMODE | GP_MACHINE;
  183. bResult = GetWbemServices( pGpoInfoMach, pwszNameSpace, TRUE, NULL, &(pGpoInfoMach->pWbemServices) );
  184. if (!bResult) {
  185. xe = GetLastError();
  186. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when getting Wbemservices.")));
  187. goto Exit;
  188. }
  189. //
  190. // First set dirty to be true
  191. //
  192. bResult = LogExtSessionStatus(pGpoInfoMach->pWbemServices, NULL, TRUE);
  193. if (!bResult) {
  194. xe = GetLastError();
  195. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  196. goto Exit;
  197. }
  198. if ( ! GenerateGpoInfo( pwszDomain, pwszDomainDns, pwszMach,
  199. (WCHAR *) bstrNewMachSOM, psaMachSecGroups, dwFlags, TRUE,
  200. (WCHAR *) bstrSite, pMachGpoFilter, &locator, NULL, NULL, pGpoInfoMach, pNetAPI32 ) ) {
  201. xe = GetLastError();
  202. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GenerateGpoInfo failed with %d."), xe));
  203. dwMachGPCoreError = (xe) ? xe : E_FAIL;
  204. }
  205. else {
  206. dwMachGPCoreError = ERROR_SUCCESS;
  207. }
  208. }
  209. //
  210. // 10% of the task is done
  211. //
  212. pProgress->IncrementBy( 5 );
  213. //
  214. // Setup user target info, if any
  215. //
  216. if ( pwszUser || bDummyUser ) {
  217. pGpoInfoUser = (LPGPOINFO) LocalAlloc (LPTR, sizeof(GPOINFO));
  218. if (!pGpoInfoUser) {
  219. xe = GetLastError();
  220. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to alloc lpGPOInfo (%d)."),
  221. GetLastError()));
  222. CEvents ev(TRUE, EVENT_FAILED_ALLOCATION);
  223. ev.AddArgWin32Error(GetLastError()); ev.Report();
  224. goto Exit;
  225. }
  226. pGpoInfoUser->dwFlags = GP_PLANMODE;
  227. bResult = GetWbemServices( pGpoInfoUser, pwszNameSpace, TRUE, NULL, &(pGpoInfoUser->pWbemServices));
  228. if (!bResult) {
  229. xe = GetLastError();
  230. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when getting Wbemservices.")));
  231. goto Exit;
  232. }
  233. //
  234. // First set dirty to be true
  235. //
  236. bResult = LogExtSessionStatus(pGpoInfoUser->pWbemServices, NULL, TRUE);
  237. if (!bResult) {
  238. xe = GetLastError();
  239. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  240. goto Exit;
  241. }
  242. if ( ! GenerateGpoInfo( pwszDomain, pwszDomainDns, pwszUser,
  243. (WCHAR *) bstrNewUserSOM, psaUserSecGroups, dwFlags, FALSE, (WCHAR *) bstrSite,
  244. pUserGpoFilter, &locator, pwszMach, (WCHAR *) bstrNewMachSOM, pGpoInfoUser, pNetAPI32 ) ) {
  245. xe = GetLastError();
  246. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: GenerateGpoInfo failed with %d."), xe));
  247. dwUserGPCoreError = (xe) ? xe : E_FAIL;
  248. }
  249. else {
  250. dwUserGPCoreError = ERROR_SUCCESS;
  251. }
  252. }
  253. //
  254. // Log Gpo info to WMI's database
  255. //
  256. lprsopSessionData = &rsopSessionData;
  257. if ( pwszMach || bDummyMach ) {
  258. XPtrLF<TOKEN_GROUPS> xGrps;
  259. hr = RsopSidsFromToken(pGpoInfoMach->pRsopToken, &xGrps);
  260. if (FAILED(hr)) {
  261. xe = HRESULT_CODE(hr);
  262. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: RsopSidsFromToken failed with error 0x%x."), hr));
  263. goto Exit;
  264. }
  265. //
  266. // Fill up the rsop Session Data (Machine Specific)
  267. //
  268. lprsopSessionData->pwszTargetName = pwszMach;
  269. lprsopSessionData->pwszSOM = GetSomPath(bstrNewMachSOM ? bstrNewMachSOM : pGpoInfoMach->lpDNName);
  270. lprsopSessionData->pSecurityGroups = (PTOKEN_GROUPS)xGrps;
  271. lprsopSessionData->bLogSecurityGroup = TRUE;
  272. lprsopSessionData->pwszSite = (WCHAR *) bstrSite;
  273. lprsopSessionData->bMachine = TRUE;
  274. bResult = LogRsopData( pGpoInfoMach, lprsopSessionData );
  275. if (!bResult) {
  276. xe = GetLastError();
  277. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging machine Rsop data.")));
  278. goto Exit;
  279. }
  280. pGpoInfoMach->bRsopLogging = TRUE;
  281. }
  282. if ( pwszUser || bDummyUser ) {
  283. XPtrLF<TOKEN_GROUPS> xGrps;
  284. hr = RsopSidsFromToken(pGpoInfoUser->pRsopToken, &xGrps);
  285. if (FAILED(hr)) {
  286. xe = HRESULT_CODE(hr);
  287. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: RsopSidsFromToken failed with error 0x%x."), hr));
  288. goto Exit;
  289. }
  290. //
  291. // Fill up the rsop Session Data (User Specific)
  292. //
  293. lprsopSessionData->pwszTargetName = pwszUser;
  294. lprsopSessionData->pwszSOM = GetSomPath(bstrNewUserSOM ? bstrNewUserSOM : pGpoInfoUser->lpDNName);
  295. lprsopSessionData->pSecurityGroups = (PTOKEN_GROUPS)xGrps;
  296. lprsopSessionData->bLogSecurityGroup = TRUE;
  297. lprsopSessionData->pwszSite = (WCHAR *) bstrSite;
  298. lprsopSessionData->bMachine = FALSE;
  299. bResult = LogRsopData( pGpoInfoUser, lprsopSessionData );
  300. if (!bResult) {
  301. xe = GetLastError();
  302. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Rsop data.")));
  303. goto Exit;
  304. }
  305. pGpoInfoUser->bRsopLogging = TRUE;
  306. }
  307. if ( ( dwUserGPCoreError != ERROR_SUCCESS) || ( dwMachGPCoreError != ERROR_SUCCESS) ){
  308. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Couldn't fetch the user/computer GPO list. Exitting provider.")));
  309. // note that at this point bResult can be true and we want to actually return that
  310. // since this error will be part of the GP Core error...
  311. goto Exit;
  312. }
  313. //
  314. // 15% of the task is done
  315. //
  316. pProgress->IncrementBy( 5 );
  317. if ( dwFlags & FLAG_NO_CSE_INVOKE )
  318. {
  319. bResult = TRUE;
  320. goto Exit;
  321. }
  322. //
  323. // By this time, pGPOInfoMach should be defined if
  324. // we needed data for mach and pGPOInfoUser should be
  325. // defined if we needed the data for user.
  326. //
  327. // Assumption: lpExt is the same for both user and Machine
  328. //
  329. if (pGpoInfoMach)
  330. lpExt = lpExtMach = pGpoInfoMach->lpExtensions;
  331. if (pGpoInfoUser)
  332. lpExt = lpExtUser = pGpoInfoUser->lpExtensions;
  333. //
  334. // count the number of extensions
  335. //
  336. DmAssert(lpExt);
  337. lpTemp = lpExt;
  338. while ( lpExt )
  339. {
  340. dwExtCount++;
  341. lpExt = lpExt->pNext;
  342. }
  343. lpExt = lpTemp;
  344. dwIncrPercent = ( pProgress->MaxProgress() - pProgress->CurrentProgress() ) / dwExtCount;
  345. //
  346. // Loop through registered extensions, asking them to generate planning mode info
  347. //
  348. while ( lpExt ) {
  349. //
  350. // Add check here for cancellation of policy generation
  351. //
  352. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: -----------------------")));
  353. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: Processing extension %s"), lpExt->lpDisplayName));
  354. if (lpExtMach)
  355. FilterGPOs( lpExtMach, pGpoInfoMach );
  356. if (lpExtUser)
  357. FilterGPOs( lpExtUser, pGpoInfoUser );
  358. __try {
  359. dwResult = ProcessMachAndUserGpoList( lpExtMach, lpExtUser, dwFlags, (WCHAR *) bstrSite,
  360. pwszMach, (WCHAR *) bstrNewMachSOM, psaMachSecGroups, pGpoInfoMach,
  361. pwszUser, (WCHAR *) bstrNewUserSOM, psaUserSecGroups, pGpoInfoUser );
  362. pProgress->IncrementBy( dwIncrPercent );
  363. }
  364. __except( GPOExceptionFilter( GetExceptionInformation() ) ) {
  365. RevertToSelf();
  366. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Extension %s ProcessGroupPolicy threw unhandled exception 0x%x."),
  367. lpExt->lpDisplayName, GetExceptionCode() ));
  368. CEvents ev(TRUE, EVENT_CAUGHT_EXCEPTION);
  369. ev.AddArg(lpExt->lpDisplayName); ev.AddArgHex(GetExceptionCode()); ev.Report();
  370. }
  371. DebugMsg((DM_VERBOSE, TEXT("GenerateRsopPolicy: -----------------------")));
  372. if (lpExtMach)
  373. lpExtMach = lpExtMach->pNext;
  374. if (lpExtUser)
  375. lpExtUser = lpExtUser->pNext;
  376. lpExt = lpExt->pNext;
  377. }
  378. bResult = TRUE;
  379. Exit:
  380. //
  381. // if all logging was successful
  382. //
  383. if ((pGpoInfoUser) && (pGpoInfoUser->bRsopLogging)) {
  384. bResult = UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, NULL, (!bResult), dwUserGPCoreError );
  385. }
  386. if ((pGpoInfoMach) && (pGpoInfoMach->bRsopLogging)) {
  387. bResult = UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, NULL, (!bResult), dwMachGPCoreError);
  388. }
  389. UnloadGPExtensions( pGpoInfoMach );
  390. UnloadGPExtensions( pGpoInfoUser ); // Frees lpExtensions field
  391. if ( pDsInfo ) {
  392. pNetAPI32->pfnDsRoleFreeMemory (pDsInfo);
  393. }
  394. LocalFree( pwszMachDns );
  395. FreeGpoInfo( pGpoInfoUser );
  396. FreeGpoInfo( pGpoInfoMach );
  397. return bResult;
  398. }
  399. //*************************************************************
  400. //
  401. // GenerateGpoInfo()
  402. //
  403. // Purpose: Allocates and fills in pGpoInfo for specified target
  404. //
  405. // Parameters: pwszDomain - Domain name
  406. // pwszDomainDns - Dns name of machine for ldap binding
  407. // pwszAccount - User or machine account name
  408. // pwszNewSOM - New SOM of target
  409. // psaSecGroups - New security groups of target
  410. // dwFlags - Processing flags
  411. // bMachine - Is this machine processing
  412. // pwszSite - Site name
  413. // pGpoFilter - Gpo filter
  414. // pLocator - Wbem interface class
  415. // pwszMachAccount - Machine account
  416. // pwszNewMachSOM - Machine SOM (abv 2 are applicable only for loopback)
  417. // ppGpoInfo - Gpo info returned here
  418. // pNetApi32 - Delay loaded netap32.dll
  419. //
  420. // Return: True if successful, False otherwise
  421. //
  422. //*************************************************************
  423. BOOL GenerateGpoInfo( WCHAR *pwszDomain, WCHAR *pwszDomainDns, WCHAR *pwszAccount,
  424. WCHAR *pwszNewSOM, SAFEARRAY *psaSecGroups,
  425. DWORD dwFlags, BOOL bMachine, WCHAR *pwszSite, CGpoFilter *pGpoFilter, CLocator *pLocator,
  426. WCHAR *pwszMachAccount, WCHAR *pwszNewMachSOM, LPGPOINFO pGpoInfo, PNETAPI32_API pNetAPI32 )
  427. {
  428. HRESULT hr;
  429. BOOL bResult = FALSE;
  430. XPtrLF<WCHAR> xszXlatName;
  431. PSECUR32_API pSecur32;
  432. XLastError xe;
  433. DWORD dwError = ERROR_SUCCESS;
  434. XPtrLF<WCHAR> xwszTargetDomain;
  435. DWORD dwUserPolicyMode = 0;
  436. DWORD dwLocFlags;
  437. if (!bMachine) {
  438. if (dwFlags & FLAG_LOOPBACK_MERGE ) {
  439. dwUserPolicyMode = 1;
  440. }
  441. else if (dwFlags & FLAG_LOOPBACK_REPLACE ) {
  442. dwUserPolicyMode = 2;
  443. }
  444. }
  445. dwLocFlags = GP_PLANMODE | (dwFlags & FLAG_ASSUME_COMP_WQLFILTER_TRUE) | (dwFlags & FLAG_ASSUME_USER_WQLFILTER_TRUE);
  446. //
  447. // Load secur32.dll
  448. //
  449. pSecur32 = LoadSecur32();
  450. if (!pSecur32) {
  451. xe = GetLastError();
  452. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to load Secur32.")));
  453. return NULL;
  454. }
  455. if ( pwszAccount == NULL ) {
  456. if ( pwszNewSOM == NULL ) {
  457. //
  458. // When dummy user is specified then both SOM and security groups
  459. // must be specified.
  460. //
  461. xe = GetLastError();
  462. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Incorrect SOM or security specification for dummy target"),
  463. GetLastError()));
  464. goto Exit;
  465. }
  466. }
  467. if ( bMachine )
  468. dwFlags |= GP_MACHINE;
  469. dwFlags |= GP_PLANMODE; // mark the processing as planning mode processing
  470. pGpoInfo->dwFlags = dwFlags;
  471. //
  472. // caller can force slow link in planning mode
  473. //
  474. if ( dwFlags & FLAG_ASSUME_SLOW_LINK )
  475. {
  476. pGpoInfo->dwFlags |= GP_SLOW_LINK;
  477. }
  478. else
  479. {
  480. pGpoInfo->dwFlags &= ~GP_SLOW_LINK;
  481. }
  482. if ( pwszAccount ) {
  483. if ( !GetCategory( pwszDomain, pwszAccount, &pGpoInfo->lpDNName ) ) {
  484. xe = GetLastError();
  485. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - getCategory failed with error - %d"), GetLastError()));
  486. goto Exit;
  487. }
  488. }
  489. //
  490. // TranslateName to SamCompatible so that the rest of the functions work correctly
  491. // for any of the various name formats
  492. //
  493. if ( pwszAccount ) {
  494. DWORD dwSize = MAX_PATH+1;
  495. xszXlatName = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*dwSize);
  496. if (!xszXlatName) {
  497. xe = GetLastError();
  498. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - Couldn't allocate memory for Name...")));
  499. goto Exit;
  500. }
  501. if (!pSecur32->pfnTranslateName( pwszAccount,
  502. NameUnknown,
  503. NameSamCompatible,
  504. xszXlatName,
  505. &dwSize )) {
  506. BOOL bOk = FALSE;
  507. if (dwSize > (MAX_PATH+1)) {
  508. xszXlatName = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*dwSize);
  509. if (!xszXlatName) {
  510. xe = GetLastError();
  511. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - Couldn't allocate memory for Name...")));
  512. goto Exit;
  513. }
  514. bOk = pSecur32->pfnTranslateName( pwszAccount,
  515. NameUnknown,
  516. NameSamCompatible,
  517. xszXlatName,
  518. &dwSize );
  519. }
  520. if (!bOk) {
  521. xe = GetLastError();
  522. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - TranslateName failed with error %d"), GetLastError()));
  523. goto Exit;
  524. }
  525. }
  526. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: RsopCreateToken for Account Name <%s>"), (LPWSTR)xszXlatName));
  527. }
  528. hr = RsopCreateToken( xszXlatName, psaSecGroups, &pGpoInfo->pRsopToken );
  529. if ( FAILED(hr) ) {
  530. xe = HRESULT_CODE(hr);
  531. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to create Rsop token. Error - %d"), HRESULT_CODE(hr)));
  532. goto Exit;
  533. }
  534. dwError = GetDomain(pwszNewSOM ? pwszNewSOM : pGpoInfo->lpDNName, &xwszTargetDomain);
  535. if (dwError != ERROR_SUCCESS) {
  536. xe = dwError;
  537. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to Get domain. Error - %d"), dwError));
  538. goto Exit;
  539. }
  540. //
  541. // Query for the GPO list based upon the mode
  542. //
  543. // 0 is normal
  544. // 1 is merge. Merge user list + machine list
  545. // 2 is replace. use machine list instead of user list
  546. //
  547. if (dwUserPolicyMode == 0) {
  548. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Calling GetGPOInfo for normal policy mode")));
  549. bResult = GetGPOInfo( dwLocFlags | ((pGpoInfo->dwFlags & GP_MACHINE) ? GPO_LIST_FLAG_MACHINE : 0),
  550. xwszTargetDomain,
  551. pwszNewSOM ? pwszNewSOM : pGpoInfo->lpDNName,
  552. NULL,
  553. &pGpoInfo->lpGPOList,
  554. &pGpoInfo->lpSOMList, &pGpoInfo->lpGpContainerList,
  555. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  556. if ( !bResult ) {
  557. xe = GetLastError();
  558. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  559. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  560. goto Exit;
  561. }
  562. } else if (dwUserPolicyMode == 2) {
  563. XPtrLF<TCHAR> xMachDNName;
  564. XPtrLF<TCHAR> xwszMachDomain;
  565. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for replacement user policy mode")));
  566. if ( pwszMachAccount ) {
  567. if ( !GetCategory( pwszDomain, pwszMachAccount, &xMachDNName ) ) {
  568. xe = GetLastError();
  569. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - getCategory failed with error - %d"), GetLastError()));
  570. goto Exit;
  571. }
  572. }
  573. dwError = GetDomain(pwszNewMachSOM ? pwszNewMachSOM : xMachDNName, &xwszMachDomain);
  574. if (dwError != ERROR_SUCCESS) {
  575. xe = dwError;
  576. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to Get domain. Error - %d"), dwError));
  577. goto Exit;
  578. }
  579. bResult = GetGPOInfo( dwLocFlags | 0,
  580. xwszMachDomain,
  581. pwszNewMachSOM ? pwszNewMachSOM : xMachDNName,
  582. NULL,
  583. &pGpoInfo->lpGPOList,
  584. &pGpoInfo->lpLoopbackSOMList,
  585. &pGpoInfo->lpLoopbackGpContainerList,
  586. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  587. if ( !bResult ) {
  588. xe = GetLastError();
  589. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  590. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  591. goto Exit;
  592. }
  593. }
  594. else {
  595. XPtrLF<TCHAR> xMachDNName;
  596. XPtrLF<TCHAR> xwszMachDomain;
  597. PGROUP_POLICY_OBJECT lpGPO = NULL;
  598. PGROUP_POLICY_OBJECT lpGPOTemp;
  599. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for merging user policy mode")));
  600. bResult = GetGPOInfo( dwLocFlags | ((pGpoInfo->dwFlags & GP_MACHINE) ? GPO_LIST_FLAG_MACHINE : 0),
  601. xwszTargetDomain,
  602. pwszNewSOM ? pwszNewSOM : pGpoInfo->lpDNName,
  603. NULL,
  604. &pGpoInfo->lpGPOList,
  605. &pGpoInfo->lpSOMList, &pGpoInfo->lpGpContainerList,
  606. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  607. if ( !bResult ) {
  608. xe = GetLastError();
  609. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  610. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  611. goto Exit;
  612. }
  613. if ( pwszMachAccount ) {
  614. if ( !GetCategory( pwszDomain, pwszMachAccount, &xMachDNName ) ) {
  615. xe = GetLastError();
  616. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo - getCategory failed with error - %d"), GetLastError()));
  617. goto Exit;
  618. }
  619. }
  620. dwError = GetDomain(pwszNewMachSOM ? pwszNewMachSOM : xMachDNName, &xwszMachDomain);
  621. if (dwError != ERROR_SUCCESS) {
  622. xe = dwError;
  623. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Failed to Get domain. Error - %d"), dwError));
  624. goto Exit;
  625. }
  626. bResult = GetGPOInfo( 0 | dwLocFlags,
  627. xwszMachDomain,
  628. pwszNewMachSOM ? pwszNewMachSOM : xMachDNName,
  629. NULL,
  630. &lpGPO,
  631. &pGpoInfo->lpLoopbackSOMList,
  632. &pGpoInfo->lpLoopbackGpContainerList,
  633. pNetAPI32, FALSE, pGpoInfo->pRsopToken, pwszSite, pGpoFilter, pLocator );
  634. if ( !bResult ) {
  635. xe = GetLastError();
  636. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: GetGPOInfo failed.")));
  637. CEvents ev( TRUE, EVENT_GPO_QUERY_FAILED ); ev.Report();
  638. goto Exit;
  639. }
  640. if (pGpoInfo->lpGPOList && lpGPO) {
  641. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Both user and machine lists are defined. Merging them together.")));
  642. //
  643. // Need to merge the lists together
  644. //
  645. lpGPOTemp = pGpoInfo->lpGPOList;
  646. while (lpGPOTemp->pNext) {
  647. lpGPOTemp = lpGPOTemp->pNext;
  648. }
  649. lpGPOTemp->pNext = lpGPO;
  650. } else if (!pGpoInfo->lpGPOList && lpGPO) {
  651. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Only machine list is defined.")));
  652. pGpoInfo->lpGPOList = lpGPO;
  653. } else {
  654. DebugMsg((DM_VERBOSE, TEXT("GenerateGpoInfo: Only user list is defined.")));
  655. }
  656. }
  657. if ( !ReadGPExtensions( pGpoInfo ) ) {
  658. xe = GetLastError();
  659. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: ReadGPExtensions failed.")));
  660. CEvents ev( TRUE, EVENT_READ_EXT_FAILED ); ev.Report();
  661. goto Exit;
  662. }
  663. if ( !CheckForSkippedExtensions( pGpoInfo, TRUE ) ) {
  664. xe = GetLastError();
  665. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: Checking extensions for skipping failed")));
  666. goto Exit;
  667. }
  668. bResult = SetupGPOFilter( pGpoInfo );
  669. if ( !bResult ) {
  670. xe = GetLastError();
  671. DebugMsg((DM_WARNING, TEXT("GenerateGpoInfo: SetupGPOFilter failed.")));
  672. CEvents ev(TRUE, EVENT_SETUP_GPOFILTER_FAILED); ev.Report();
  673. goto Exit;
  674. }
  675. Exit:
  676. return bResult;
  677. }
  678. //*************************************************************
  679. //
  680. // GetCategory()
  681. //
  682. // Purpose: Gets the fully qualified domain name
  683. //
  684. // Parameters: pwszDomain - Domain name
  685. // pwszAccount - User or machine account name
  686. // pwszDNName - Fully qualified domain name returned here
  687. //
  688. // Return: True if successful, False otherwise
  689. //
  690. //*************************************************************
  691. BOOL GetCategory( WCHAR *pwszDomain, WCHAR *pwszAccount, WCHAR **ppwszDNName )
  692. {
  693. PSECUR32_API pSecur32Api;
  694. BOOL bResult = FALSE;
  695. ULONG ulSize = 512;
  696. XLastError xe;
  697. *ppwszDNName = NULL;
  698. *ppwszDNName = (WCHAR *) LocalAlloc (LPTR, ulSize * sizeof(WCHAR) );
  699. if ( *ppwszDNName == NULL ) {
  700. xe = GetLastError();
  701. DebugMsg((DM_WARNING, TEXT("GetCategory: Memory allocation failed.")));
  702. goto Exit;
  703. }
  704. pSecur32Api = LoadSecur32();
  705. if (!pSecur32Api) {
  706. xe = GetLastError();
  707. DebugMsg((DM_WARNING, TEXT("GetCategory: Failed to load secur32 api.")));
  708. goto Exit;
  709. }
  710. bResult = pSecur32Api->pfnTranslateName( pwszAccount, NameUnknown, NameFullyQualifiedDN,
  711. *ppwszDNName, &ulSize );
  712. if ( !bResult && ulSize > 0 ) {
  713. LocalFree( *ppwszDNName );
  714. *ppwszDNName = (WCHAR *) LocalAlloc (LPTR, ulSize * sizeof(WCHAR) );
  715. if ( *ppwszDNName == NULL ) {
  716. xe = GetLastError();
  717. DebugMsg((DM_WARNING, TEXT("GetCategory: Memory allocation failed.")));
  718. goto Exit;
  719. }
  720. bResult = pSecur32Api->pfnTranslateName( pwszAccount, NameUnknown, NameFullyQualifiedDN,
  721. *ppwszDNName, &ulSize );
  722. if (!bResult) {
  723. xe = GetLastError();
  724. DebugMsg((DM_WARNING, TEXT("GetCategory: TranslateName failed with error %d."), GetLastError()));
  725. }
  726. }
  727. else {
  728. if (!bResult) {
  729. xe = GetLastError();
  730. DebugMsg((DM_WARNING, TEXT("GetCategory: TranslateName failed with error %d."), GetLastError()));
  731. }
  732. }
  733. Exit:
  734. if ( !bResult ) {
  735. LocalFree( *ppwszDNName );
  736. *ppwszDNName = NULL;
  737. }
  738. return bResult;
  739. }
  740. //*************************************************************
  741. //
  742. // ProcessMachAndUserGpoList()
  743. //
  744. // Purpose: Calls the various extensions to do the planning
  745. // mode logging
  746. //
  747. // Parameters: lpExtMach - Machine extension struct
  748. // lpExtUser - User extension struct
  749. // dwFlags - Processing flags
  750. // pwszSite - Site name
  751. // pwszNewComputerSOM - New computer scope of management
  752. // psaCompSecGroups - New computer security groups
  753. // pGpoInfoMach - Machine Gpo info
  754. // ... - Similarly for user account
  755. //
  756. // Return: True if successful, False otherwise
  757. //
  758. //*************************************************************
  759. DWORD ProcessMachAndUserGpoList( LPGPEXT lpExtMach, LPGPEXT lpExtUser, DWORD dwFlags, WCHAR *pwszSite,
  760. WCHAR *pwszMach, WCHAR *pwszNewComputerSOM, SAFEARRAY *psaComputerSecurityGroups, LPGPOINFO pGpoInfoMach,
  761. WCHAR *pwszUser, WCHAR *pwszNewUserSOM, SAFEARRAY *psaUserSecurityGroups, LPGPOINFO pGpoInfoUser )
  762. {
  763. BOOL bAbort = FALSE;
  764. DWORD dwResult;
  765. RSOP_TARGET computerTarget, userTarget;
  766. PRSOP_TARGET pComputerTarget = NULL;
  767. PRSOP_TARGET pUserTarget = NULL;
  768. BOOL bPlanningSupported = TRUE;
  769. LPGPEXT lpExt;
  770. lpExt = (lpExtMach != NULL) ? lpExtMach : lpExtUser;
  771. if (!lpExt) {
  772. DebugMsg((DM_WARNING, TEXT("ProcessMachAndUserGpoList: Both user and computer exts are null, returning.")));
  773. return TRUE;
  774. }
  775. bPlanningSupported = lpExt->bRegistryExt || (lpExt->lpRsopFunctionName ? TRUE : FALSE);
  776. if ( lpExtMach && !lpExtMach->bSkipped && pGpoInfoMach->lpGPOList ) {
  777. //
  778. // Computer target is non-null
  779. //
  780. pComputerTarget = &computerTarget;
  781. pComputerTarget->pwszAccountName = pwszMach;
  782. pComputerTarget->pwszNewSOM = pwszNewComputerSOM;
  783. pComputerTarget->psaSecurityGroups = psaComputerSecurityGroups;
  784. pComputerTarget->pRsopToken = pGpoInfoMach->pRsopToken;
  785. pComputerTarget->pGPOList = pGpoInfoMach->lpGPOList;
  786. pComputerTarget->pWbemServices = pGpoInfoMach->pWbemServices;
  787. if (pGpoInfoMach->bRsopLogging) {
  788. pGpoInfoMach->bRsopLogging = LogExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach,
  789. bPlanningSupported);
  790. if (!pGpoInfoMach->bRsopLogging) {
  791. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  792. }
  793. }
  794. }
  795. if ( lpExtUser && !lpExtUser->bSkipped && pGpoInfoUser->lpGPOList ) {
  796. //
  797. // User target is non-null
  798. //
  799. pUserTarget = &userTarget;
  800. pUserTarget->pwszAccountName = pwszUser;
  801. pUserTarget->pwszNewSOM = pwszNewUserSOM;
  802. pUserTarget->psaSecurityGroups = psaUserSecurityGroups;
  803. pUserTarget->pRsopToken = pGpoInfoUser->pRsopToken;
  804. pUserTarget->pGPOList = pGpoInfoUser->lpGPOList;
  805. pUserTarget->pWbemServices = pGpoInfoUser->pWbemServices;
  806. if (pGpoInfoUser->bRsopLogging) {
  807. pGpoInfoUser->bRsopLogging = LogExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser,
  808. bPlanningSupported);
  809. if (!pGpoInfoUser->bRsopLogging) {
  810. DebugMsg((DM_WARNING, TEXT("GenerateRsopPolicy: Error when logging user Session data.")));
  811. }
  812. }
  813. }
  814. if ( pComputerTarget == NULL && pUserTarget == NULL ) {
  815. DebugMsg((DM_WARNING, TEXT("ProcessMachAndUserGpoList: Both user and computer targets are null, returning.")));
  816. return TRUE;
  817. }
  818. if ( lpExt->bRegistryExt ) {
  819. //
  820. // Registry pseudo extension
  821. //
  822. dwResult = GenerateRegistryPolicy( dwFlags,
  823. &bAbort,
  824. pwszSite,
  825. pComputerTarget,
  826. pUserTarget );
  827. } else {
  828. if ( LoadGPExtension( lpExt, TRUE ) ) {
  829. dwResult = lpExt->pRsopEntryPoint( dwFlags,
  830. &bAbort,
  831. pwszSite,
  832. pComputerTarget,
  833. pUserTarget );
  834. }
  835. else {
  836. dwResult = GetLastError();
  837. }
  838. }
  839. if ( lpExtUser && !lpExtUser->bSkipped && pGpoInfoUser->bRsopLogging) {
  840. if ( !bPlanningSupported )
  841. UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser->lpKeyName, TRUE, ERROR_SUCCESS);
  842. else if (dwResult != ERROR_SUCCESS)
  843. UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser->lpKeyName, TRUE, dwResult);
  844. else
  845. UpdateExtSessionStatus(pGpoInfoUser->pWbemServices, lpExtUser->lpKeyName, FALSE, dwResult);
  846. }
  847. if ( lpExtMach && !lpExtMach->bSkipped && pGpoInfoMach->bRsopLogging) {
  848. if ( !bPlanningSupported )
  849. UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach->lpKeyName, TRUE, ERROR_SUCCESS);
  850. else if (dwResult != ERROR_SUCCESS)
  851. UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach->lpKeyName, TRUE, dwResult);
  852. else
  853. UpdateExtSessionStatus(pGpoInfoMach->pWbemServices, lpExtMach->lpKeyName, FALSE, dwResult);
  854. }
  855. return dwResult;
  856. }
  857. //*********************************************************************
  858. // * Planning mode registry stuff
  859. //*********************************************************************
  860. //*************************************************************
  861. //
  862. // ProcessRegistryFiles()
  863. //
  864. // Purpose: Called from GenerateRegsitryPolicy to process registry data from
  865. // the registry files associated with a policy target.
  866. //
  867. // Parameters:
  868. // pTarget - Policy for which registry policy is to be processed.
  869. // pHashTable - Hash table to keep registry policy information.
  870. //
  871. // Return: On success, TRUE. Otherwise, FALSE.
  872. //
  873. //*************************************************************
  874. BOOL ProcessRegistryFiles(PRSOP_TARGET pTarget, REGHASHTABLE *pHashTable)
  875. {
  876. PGROUP_POLICY_OBJECT lpGPO;
  877. TCHAR szRegistry[MAX_PATH];
  878. LPTSTR lpEnd;
  879. HRESULT hr;
  880. DWORD dwGrantedAccessMask;
  881. BOOL bAccess;
  882. //
  883. // Check parameters
  884. //
  885. DmAssert(pHashTable);
  886. if(!pHashTable) {
  887. DebugMsg((DM_WARNING, TEXT("ProcessRegistryFiles: Invalid parameter.")));
  888. return FALSE;
  889. }
  890. //
  891. // Spin through GPOs in the list.
  892. //
  893. lpGPO = pTarget->pGPOList;
  894. while ( lpGPO ) {
  895. //
  896. // Build the path to Registry.pol
  897. //
  898. DmAssert( lstrlen(lpGPO->lpFileSysPath) + lstrlen(c_szRegistryPol) + 1 < MAX_PATH );
  899. if(lstrlen(lpGPO->lpFileSysPath) + lstrlen(c_szRegistryPol) + 1 >= MAX_PATH) {
  900. DebugMsg((DM_WARNING, TEXT("ProcessRegistryFiles: Length of path to registry.pol exceeded MAX_PATH.")));
  901. return FALSE;
  902. }
  903. lstrcpy (szRegistry, lpGPO->lpFileSysPath);
  904. lpEnd = CheckSlash (szRegistry);
  905. lstrcpy (lpEnd, c_szRegistryPol);
  906. //
  907. // Check if the RsopToken has access to this file.
  908. //
  909. hr = RsopFileAccessCheck(szRegistry, pTarget->pRsopToken, GENERIC_READ, &dwGrantedAccessMask, &bAccess);
  910. if(FAILED(hr)) {
  911. DebugMsg((DM_VERBOSE, TEXT("ProcessRegistryFiles: RsopFileAccessCheck failed.")));
  912. return FALSE;
  913. }
  914. if(!bAccess) {
  915. DebugMsg((DM_VERBOSE, TEXT("ProcessRegistryFiles: The RsopToken does not have access to file %s. Continuing...."), szRegistry));
  916. lpGPO = lpGPO->pNext;
  917. continue;
  918. }
  919. //
  920. // Process registry data for this particular file.
  921. //
  922. if (!ParseRegistryFile (NULL, szRegistry, (PFNREGFILECALLBACK)ProcessRegistryValue, NULL,
  923. lpGPO->lpDSPath, lpGPO->lpLink,pHashTable, TRUE)) {
  924. DebugMsg((DM_WARNING, TEXT("ProcessRegistryFiles: ProcessRegistryFile failed.")));
  925. return FALSE;
  926. }
  927. lpGPO = lpGPO->pNext;
  928. }
  929. return TRUE;
  930. }
  931. //*************************************************************
  932. //
  933. // ProcessAdmData()
  934. //
  935. // Purpose: Called from GenerateRegistryPolicy in order to process Admin templates
  936. // data associated with a registry policy target.
  937. //
  938. // Parameters: pTarget - Target for which data is to be processed
  939. // bUser - Is this for user or machine policy ?
  940. //
  941. // Return: On success, TRUE. Otherwise, FALSE.
  942. //
  943. //*************************************************************
  944. BOOL ProcessAdmData( PRSOP_TARGET pTarget, BOOL bUser )
  945. {
  946. PGROUP_POLICY_OBJECT lpGPO;
  947. WIN32_FIND_DATA findData;
  948. ADMFILEINFO *pAdmFileCache = 0;
  949. TCHAR szRegistry[MAX_PATH];
  950. LPTSTR lpEnd;
  951. HANDLE hFindFile;
  952. WIN32_FILE_ATTRIBUTE_DATA attrData;
  953. DWORD dwFilePathSize;
  954. DWORD dwSize;
  955. WCHAR *pwszEnd;
  956. WCHAR *pwszFile;
  957. HRESULT hr;
  958. DWORD dwGrantedAccessMask;
  959. BOOL bAccess;
  960. //
  961. // Check parameters
  962. //
  963. if(pTarget == NULL ) {
  964. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: Invalid paramter.")));
  965. return FALSE;
  966. }
  967. lpGPO = pTarget->pGPOList;
  968. while(lpGPO) {
  969. //
  970. // Log Adm data
  971. //
  972. dwFilePathSize = lstrlen( lpGPO->lpFileSysPath );
  973. dwSize = dwFilePathSize + MAX_PATH;
  974. pwszFile = (WCHAR *) LocalAlloc( LPTR, dwSize * sizeof(WCHAR) );
  975. if ( pwszFile == 0 ) {
  976. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: Failed to allocate memory.")));
  977. FreeAdmFileCache( pAdmFileCache );
  978. return FALSE;
  979. }
  980. lstrcpy( pwszFile, lpGPO->lpFileSysPath );
  981. //
  982. // Strip off trailing 'machine' or 'user'
  983. //
  984. pwszEnd = pwszFile + lstrlen( pwszFile );
  985. if ( !bUser )
  986. pwszEnd -= 7; // length of "machine"
  987. else
  988. pwszEnd -= 4; // length of "user"
  989. lstrcpy( pwszEnd, L"Adm\\*.adm");
  990. //
  991. // Remember end point so that the actual Adm filename can be
  992. // easily concatenated.
  993. //
  994. pwszEnd = pwszEnd + lstrlen( L"Adm\\" );
  995. //
  996. // Enumerate all Adm files
  997. //
  998. hFindFile = FindFirstFile( pwszFile, &findData);
  999. if ( hFindFile != INVALID_HANDLE_VALUE )
  1000. {
  1001. do
  1002. {
  1003. if ( !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1004. {
  1005. DmAssert( dwFilePathSize + lstrlen(findData.cFileName) + lstrlen( L"\\Adm\\" ) < dwSize );
  1006. lstrcpy( pwszEnd, findData.cFileName);
  1007. ZeroMemory (&attrData, sizeof(attrData));
  1008. //
  1009. // Check if the RsopToken has access to this file.
  1010. //
  1011. hr = RsopFileAccessCheck(pwszFile, pTarget->pRsopToken, GENERIC_READ, &dwGrantedAccessMask, &bAccess);
  1012. if(FAILED(hr)) {
  1013. DebugMsg((DM_VERBOSE, TEXT("ProcessAdmData: RsopFileAccessCheck failed.")));
  1014. FreeAdmFileCache( pAdmFileCache );
  1015. return FALSE;
  1016. }
  1017. if(!bAccess) {
  1018. DebugMsg((DM_VERBOSE, TEXT("ProcessAdmData: The RsopToken does not have access to file %s. Continuing..."), findData.cFileName));
  1019. continue;
  1020. }
  1021. if ( GetFileAttributesEx (pwszFile, GetFileExInfoStandard, &attrData ) != 0 ) {
  1022. if ( !AddAdmFile( pwszFile, lpGPO->lpDSPath,
  1023. &attrData.ftLastWriteTime, NULL, &pAdmFileCache ) ) {
  1024. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: NewAdmData failed.")));
  1025. }
  1026. }
  1027. } // if findData & file_attr_dir
  1028. } while ( FindNextFile(hFindFile, &findData) );// do
  1029. FindClose(hFindFile);
  1030. } // if hfindfile
  1031. LocalFree( pwszFile );
  1032. lpGPO = lpGPO->pNext;
  1033. }
  1034. if ( ! LogAdmRsopData( pAdmFileCache, pTarget->pWbemServices ) ) {
  1035. DebugMsg((DM_WARNING, TEXT("ProcessAdmData: Error when logging Adm Rsop data. Continuing.")));
  1036. }
  1037. FreeAdmFileCache( pAdmFileCache );
  1038. return TRUE;
  1039. }
  1040. //*************************************************************
  1041. //
  1042. // GenerateRegistryPolicy()
  1043. //
  1044. // Purpose: Implementation of Planning mode regsitry pseudo-extension
  1045. //
  1046. // Parameters: dwFlags - Flags
  1047. // pbAbort - Abort processing
  1048. // pwszSite - Site of target
  1049. // pComputerTarget - Computer target specification
  1050. // pUserTarget - User target specification
  1051. //
  1052. // Return: On success, S_OK. Otherwise, E_FAIL.
  1053. //
  1054. //*************************************************************
  1055. DWORD GenerateRegistryPolicy( DWORD dwFlags,
  1056. BOOL *pbAbort,
  1057. WCHAR *pwszSite,
  1058. PRSOP_TARGET pComputerTarget,
  1059. PRSOP_TARGET pUserTarget )
  1060. {
  1061. REGHASHTABLE *pHashTable = NULL;
  1062. BOOL bUser;
  1063. if(pComputerTarget && pComputerTarget->pGPOList) {
  1064. //
  1065. // Setup computer hash table
  1066. //
  1067. pHashTable = AllocHashTable();
  1068. if ( pHashTable == NULL ) {
  1069. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: AllocHashTable failed.")));
  1070. return E_FAIL;
  1071. }
  1072. //
  1073. // Process computer GPO list
  1074. //
  1075. if(!ProcessRegistryFiles(pComputerTarget, pHashTable)) {
  1076. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessRegistryFiles failed.")));
  1077. FreeHashTable( pHashTable );
  1078. return E_FAIL;
  1079. }
  1080. //
  1081. // Log computer registry data to Cimom database
  1082. //
  1083. if ( ! LogRegistryRsopData( GP_MACHINE, pHashTable, pComputerTarget->pWbemServices ) ) {
  1084. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: LogRegistryRsopData failed.")));
  1085. FreeHashTable( pHashTable );
  1086. return E_FAIL;
  1087. }
  1088. FreeHashTable( pHashTable );
  1089. pHashTable = NULL;
  1090. //
  1091. // Process ADM data
  1092. //
  1093. bUser = FALSE;
  1094. if (pComputerTarget && !ProcessAdmData( pComputerTarget, bUser ) ) {
  1095. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessAdmData failed.")));
  1096. return E_FAIL;
  1097. }
  1098. }
  1099. //
  1100. // Process user GPO list
  1101. //
  1102. if(pUserTarget && pUserTarget->pGPOList) {
  1103. //
  1104. // Setup user hash table
  1105. //
  1106. pHashTable = AllocHashTable();
  1107. if ( pHashTable == NULL ) {
  1108. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: AllocHashTable failed.")));
  1109. return E_FAIL;
  1110. }
  1111. if(!ProcessRegistryFiles(pUserTarget, pHashTable)) {
  1112. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessRegistryFiles failed.")));
  1113. FreeHashTable( pHashTable );
  1114. return E_FAIL;
  1115. }
  1116. //
  1117. // Log user registry data to Cimom database
  1118. //
  1119. if ( ! LogRegistryRsopData( 0, pHashTable, pUserTarget->pWbemServices ) ) {
  1120. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: LogRegistryRsopData failed.")));
  1121. FreeHashTable( pHashTable );
  1122. return E_FAIL;
  1123. }
  1124. FreeHashTable( pHashTable );
  1125. pHashTable = NULL;
  1126. //
  1127. // Process ADM data
  1128. //
  1129. bUser = TRUE;
  1130. if (pUserTarget && !ProcessAdmData( pUserTarget, bUser ) ) {
  1131. DebugMsg((DM_WARNING, TEXT("GenerateRegistryPolicy: ProcessAdmData failed.")));
  1132. return E_FAIL;
  1133. }
  1134. }
  1135. return S_OK;
  1136. }
  1137. //*************************************************************
  1138. //
  1139. // CheckOUAccess()
  1140. //
  1141. // Purpose: Determines if the user / machine has read access to
  1142. // the OU.
  1143. //
  1144. // Parameters: pld - LDAP connection
  1145. // pLDAP - LDAP function table pointer
  1146. // pMessage - LDAP message
  1147. // pRsopToken - RSOP token of the user or machine
  1148. // pSD - Security descriptor returned here
  1149. // pcbSDLen - Length of security descriptor returned here
  1150. // pbAccessGranted - Receives the final yes / no status
  1151. //
  1152. // Return: TRUE if successful
  1153. // FALSE if an error occurs.
  1154. //
  1155. //*************************************************************
  1156. BOOL CheckOUAccess( PLDAP_API pLDAP,
  1157. PLDAP pld,
  1158. PLDAPMessage pMessage,
  1159. PRSOPTOKEN pRsopToken,
  1160. BOOL *pbAccessGranted )
  1161. {
  1162. BOOL bResult = FALSE;
  1163. TCHAR szSDProperty[] = TEXT("nTSecurityDescriptor");
  1164. PWSTR *ppwszValues;
  1165. *pbAccessGranted = FALSE;
  1166. //
  1167. // Get the security descriptor value
  1168. //
  1169. ppwszValues = pLDAP->pfnldap_get_values( pld, pMessage, szSDProperty );
  1170. if (!ppwszValues)
  1171. {
  1172. if (pld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
  1173. {
  1174. DebugMsg((DM_VERBOSE, TEXT("CheckOUAccess: Object can not be accessed.")));
  1175. bResult = TRUE;
  1176. }
  1177. else
  1178. {
  1179. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: ldap_get_values failed with 0x%x"),
  1180. pld->ld_errno));
  1181. }
  1182. }
  1183. else
  1184. {
  1185. PLDAP_BERVAL *pSize;
  1186. //
  1187. // Get the length of the security descriptor
  1188. //
  1189. pSize = pLDAP->pfnldap_get_values_len(pld, pMessage, szSDProperty);
  1190. if (!pSize)
  1191. {
  1192. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: ldap_get_values_len failed with 0x%x"),
  1193. pld->ld_errno));
  1194. }
  1195. else
  1196. {
  1197. //
  1198. // Allocate the memory for the security descriptor
  1199. //
  1200. PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, (*pSize)->bv_len);
  1201. if ( pSD == NULL )
  1202. {
  1203. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: Failed to allocate memory for SD with %d"),
  1204. GetLastError()));
  1205. }
  1206. else
  1207. {
  1208. //
  1209. // OU {bf967aa8-0de6-11d0-a285-00aa003049e2}
  1210. //
  1211. GUID OrganizationalUnit = { 0xbf967aa5, 0x0de6, 0x11d0, 0xa2, 0x85, 0x00, 0xaa, 0x00, 0x30, 0x49, 0xe2 };
  1212. //
  1213. // gPOptions {f30e3bbf-9ff0-11d1-b603-0000f80367c1}
  1214. //
  1215. GUID gPOptionsGuid = { 0xf30e3bbf, 0x9ff0, 0x11d1, 0xb6, 0x03, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1 };
  1216. //
  1217. // gPLink {f30e3bbe-9ff0-11d1-b603-0000f80367c1}
  1218. //
  1219. GUID gPLinkGuid = { 0xf30e3bbe, 0x9ff0, 0x11d1, 0xb6, 0x03, 0x00, 0x00, 0xf8, 0x03, 0x67, 0xc1 };
  1220. OBJECT_TYPE_LIST ObjType[] = { { ACCESS_OBJECT_GUID, 0, &OrganizationalUnit },
  1221. { ACCESS_PROPERTY_SET_GUID, 0, &gPLinkGuid },
  1222. { ACCESS_PROPERTY_SET_GUID, 0, &gPOptionsGuid } };
  1223. HRESULT hr;
  1224. PRIVILEGE_SET PrivSet;
  1225. DWORD PrivSetLength = sizeof(PRIVILEGE_SET);
  1226. DWORD dwGrantedAccess;
  1227. BOOL bAccessStatus = TRUE;
  1228. GENERIC_MAPPING DS_GENERIC_MAPPING = { DS_GENERIC_READ,
  1229. DS_GENERIC_WRITE,
  1230. DS_GENERIC_EXECUTE,
  1231. DS_GENERIC_ALL };
  1232. //
  1233. // Copy the security descriptor
  1234. //
  1235. CopyMemory( pSD, (PBYTE)(*pSize)->bv_val, (*pSize)->bv_len);
  1236. //
  1237. // Now we use RsopAccessCheckByType to determine if the user / machine
  1238. // should have this GPO applied to them
  1239. //
  1240. hr = RsopAccessCheckByType(pSD,
  1241. 0,
  1242. pRsopToken,
  1243. ACTRL_DS_READ_PROP,
  1244. ObjType,
  1245. ARRAYSIZE(ObjType),
  1246. &DS_GENERIC_MAPPING,
  1247. &PrivSet,
  1248. &PrivSetLength,
  1249. &dwGrantedAccess,
  1250. &bAccessStatus );
  1251. if ( FAILED( hr ) )
  1252. {
  1253. DebugMsg((DM_WARNING, TEXT("CheckOUAccess: RsopAccessCheckByType failed with %d"), GetLastError()));
  1254. }
  1255. else
  1256. {
  1257. *pbAccessGranted = bAccessStatus;
  1258. bResult = TRUE;
  1259. }
  1260. LocalFree( pSD );
  1261. }
  1262. pLDAP->pfnldap_value_free_len(pSize);
  1263. }
  1264. pLDAP->pfnldap_value_free(ppwszValues);
  1265. }
  1266. return bResult;
  1267. }