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.

3723 lines
108 KiB

  1. //depot/private/vishnup_branch/DS/security/services/scerpc/client/polclnt.cpp#3 - edit change 767 (text)
  2. /*++
  3. Copyright (c) 1996 Microsoft Corporation
  4. Module Name:
  5. polclnt.cpp
  6. Abstract:
  7. SCE policy integration Client APIs
  8. Author:
  9. Jin Huang (jinhuang) 23-Jun-1997 created
  10. Revision History:
  11. jinhuang 23-Jan-1998 split to client-server model
  12. --*/
  13. #include "headers.h"
  14. #include "sceutil.h"
  15. #include "clntutil.h"
  16. #include "infp.h"
  17. #include <io.h>
  18. #include <userenv.h>
  19. //#include <shlwapi.h>
  20. //#include "userenvp.h"
  21. #include "scedllrc.h"
  22. #include "dsrole.h"
  23. #include "commonrc.h"
  24. #include "precedence.h"
  25. #include "cgenericlogger.h"
  26. #pragma hdrstop
  27. #include <wincrypt.h>
  28. #include <ntlsa.h>
  29. #include <lmaccess.h>
  30. CRITICAL_SECTION DiagnosisPolicypropSync;
  31. static HANDLE ghAsyncThread = NULL;
  32. extern HINSTANCE MyModuleHandle;
  33. BOOL gbAsyncWinlogonThread;
  34. //
  35. // global into which the RSOP namespace ptr is stashed
  36. // for use when server calls back - diagnosis mode only
  37. //
  38. IWbemServices *tg_pWbemServices = NULL;
  39. //
  40. // global into which the RSOP synch status is stashed
  41. // for use when server calls back - diagnosis mode only
  42. //
  43. HRESULT gHrSynchRsopStatus;
  44. //
  45. // global into which the RSOP asynch status is stashed
  46. // for use when asynch thread done - diagnosis mode only
  47. //
  48. HRESULT gHrAsynchRsopStatus;
  49. typedef DWORD (WINAPI *PFGETDOMAININFO)(LPCWSTR, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL, PBYTE *);
  50. typedef VOID (WINAPI *PFDSFREE)( PVOID );
  51. //
  52. // no need to critical section these variables because propagation always call to
  53. // this dll in sequence.
  54. //
  55. BOOL gbThisIsDC = FALSE;
  56. BOOL gbDCQueried = FALSE;
  57. PWSTR gpwszDCDomainName = NULL;
  58. GUID SceExtGuid = { 0x827D319E, 0x6EAC, 0x11D2, { 0xA4, 0xEA, 0x0, 0xC0, 0x4F, 0x79, 0xF8, 0x3A } };
  59. typedef enum _SCE_ATTACHMENT_TYPE_ {
  60. SCE_ATTACHMENT_SERVICE,
  61. SCE_ATTACHMENT_POLICY
  62. } SCE_ATTACHMENT_TYPE;
  63. typedef struct {
  64. ASYNCCOMPLETIONHANDLE pHandle;
  65. LPWSTR szTemplateName;
  66. LPWSTR szLogName;
  67. AREA_INFORMATION Area;
  68. DWORD dwDiagOptions;
  69. LPSTREAM pStream;
  70. } ENGINEARGS;
  71. static HMODULE hSceDll=NULL;
  72. //
  73. // private functions
  74. //
  75. DWORD
  76. ScepPolStatusCallback(
  77. IN PFNSTATUSMESSAGECALLBACK pStatusCallback OPTIONAL,
  78. IN BOOL bVerbose,
  79. IN INT nId
  80. );
  81. BOOL
  82. ScepShouldTerminateProcessing(
  83. IN BOOL *pbAbort,
  84. IN BOOL bCheckDcpromo
  85. );
  86. BOOL
  87. ScepClearGPObjects(
  88. IN BOOL bPlanning
  89. );
  90. DWORD
  91. ScepControlNotificationQProcess(
  92. IN PWSTR szLogFileName,
  93. IN BOOL bThisIsDC,
  94. IN DWORD ControlFlag
  95. );
  96. /*
  97. BOOL
  98. ScepCheckDemote();
  99. */
  100. DWORD
  101. SceProcessBeforeRSOPLogging(
  102. IN BOOL bPlanningMode,
  103. IN DWORD dwFlags,
  104. IN HANDLE hUserToken,
  105. IN HKEY hKeyRoot,
  106. IN PGROUP_POLICY_OBJECT pDeletedGPOList OPTIONAL,
  107. IN PGROUP_POLICY_OBJECT pChangedGPOList,
  108. IN ASYNCCOMPLETIONHANDLE pHandle OPTIONAL,
  109. IN BOOL *pbAbort,
  110. IN PFNSTATUSMESSAGECALLBACK pStatusCallback OPTIONAL,
  111. OUT AREA_INFORMATION *pAllAreas OPTIONAL,
  112. OUT BOOL *pb OPTIONAL,
  113. OUT PWSTR *pszLogFileName OPTIONAL,
  114. OUT DWORD *pdwWinlogonLog OPTIONAL
  115. );
  116. DWORD
  117. SceProcessAfterRSOPLogging(
  118. IN DWORD dwFlags,
  119. IN ASYNCCOMPLETIONHANDLE pHandle,
  120. IN BOOL *pbAbort,
  121. IN PFNSTATUSMESSAGECALLBACK pStatusCallback,
  122. IN AREA_INFORMATION ThisAreas,
  123. IN BOOL b,
  124. IN PWSTR *ppszLogFileName,
  125. IN DWORD dwWinlogonLog,
  126. IN DWORD dwDiagOptions
  127. );
  128. DWORD
  129. ScepProcessSecurityPolicyInOneGPO(
  130. IN BOOL bPlanningMode,
  131. IN DWORD dwFlags,
  132. IN PGROUP_POLICY_OBJECT pGpoInfo,
  133. IN LPTSTR szLogFileName OPTIONAL,
  134. IN OUT AREA_INFORMATION *pTotalArea
  135. );
  136. AREA_INFORMATION
  137. ScepGetAvailableArea(
  138. IN BOOL bPlanningMode,
  139. IN LPCTSTR SysPathRoot,
  140. IN LPCTSTR DSPath,
  141. IN LPTSTR InfName,
  142. IN GPO_LINK LinkInfo,
  143. IN BOOL bIsDC
  144. );
  145. DWORD
  146. ScepLogLastConfigTime();
  147. DWORD
  148. ScepWinlogonThreadFunc(LPVOID lpv);
  149. DWORD
  150. ScepEnumerateAttachments(
  151. OUT PSCE_NAME_LIST *pEngineList,
  152. IN SCE_ATTACHMENT_TYPE aType
  153. );
  154. DWORD
  155. ScepConfigureEFSPolicy(
  156. IN PUCHAR pEfsBlob,
  157. IN DWORD dwSize,
  158. IN DWORD dwDebugLevel
  159. );
  160. DWORD
  161. ScepWaitConfigSystem(
  162. IN LPTSTR SystemName OPTIONAL,
  163. IN PWSTR InfFileName OPTIONAL,
  164. IN PWSTR DatabaseName OPTIONAL,
  165. IN PWSTR LogFileName OPTIONAL,
  166. IN DWORD ConfigOptions,
  167. IN AREA_INFORMATION Area,
  168. IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL,
  169. IN HANDLE hCallbackWnd OPTIONAL,
  170. OUT PDWORD pdWarning OPTIONAL
  171. );
  172. //
  173. // the new interface - client side extension for RSOP Planning mode
  174. //
  175. DWORD
  176. WINAPI
  177. SceGenerateGroupPolicy(
  178. IN DWORD dwFlags,
  179. IN BOOL *pAbort,
  180. IN WCHAR *pwszSite,
  181. IN PRSOP_TARGET pComputerTarget,
  182. IN PRSOP_TARGET pUserTarget
  183. )
  184. /*
  185. Description:
  186. This is the new interface called from winlogon/userenv to generate planning
  187. RSOP data. The dll name and procedure name are registered to winlogon under
  188. GpExtensions.
  189. This routine simulates a SCE group policy template to the current system.
  190. The template can be in domain level, OU level, or user level.
  191. The input argument contains info about the GPOs to be simulated and a namespace
  192. pointer to log the RSOP data.
  193. This interface shouldn't be called for user policy.
  194. Arguments:
  195. dwFlags - the GPO Info flags
  196. GPO_INFO_FLAG_MACHINE
  197. GPO_INFO_FLAG_SLOWLINK
  198. GPO_INFO_FLAG_BACKGROUND
  199. GPO_INFO_FLAG_VERBOSE
  200. GPO_INFO_FLAG_NOCHANGES
  201. pwszSite - unused now
  202. pComputerTarget - RSOP machine structure having GPOList, token (unused now) etc.
  203. pUserTarget - RSOP user structure having GPOList, token (unused now) etc.
  204. pbAbort - processing of GPO should be aborted if this is set to TRUE
  205. (in case of system shutdown or user log off)
  206. */
  207. {
  208. DWORD rcGPOCreate = ERROR_SUCCESS;
  209. DWORD rcLogging = ERROR_SUCCESS;
  210. PWSTR szLogFileName = NULL;
  211. //
  212. // put a try except block in case arguments are invalid or wbem logging fails
  213. //
  214. __try {
  215. if (pComputerTarget == NULL || pComputerTarget->pWbemServices == NULL)
  216. return ERROR_INVALID_PARAMETER;
  217. (void) InitializeEvents(L"SceCli");
  218. rcGPOCreate = SceProcessBeforeRSOPLogging(
  219. TRUE,
  220. dwFlags,
  221. pComputerTarget->pRsopToken,
  222. 0,
  223. NULL,
  224. pComputerTarget->pGPOList,
  225. NULL,
  226. pAbort,
  227. NULL,
  228. NULL,
  229. NULL,
  230. &szLogFileName,
  231. NULL
  232. );
  233. if (rcGPOCreate != ERROR_OPERATION_ABORTED && pComputerTarget->pGPOList)
  234. rcLogging = SceLogSettingsPrecedenceGPOs(
  235. pComputerTarget->pWbemServices,
  236. TRUE,
  237. &szLogFileName);
  238. if (szLogFileName)
  239. ScepFree(szLogFileName);
  240. (void) ShutdownEvents();
  241. } __except(EXCEPTION_EXECUTE_HANDLER) {
  242. rcGPOCreate = ERROR_INVALID_PARAMETER;
  243. }
  244. //
  245. // rcGPOCreate dominates rcLogging
  246. //
  247. return (rcGPOCreate != ERROR_SUCCESS ? rcGPOCreate : rcLogging );
  248. }
  249. //
  250. // the new interface - client side extension for RSOP Diagnosis mode
  251. //
  252. DWORD
  253. WINAPI
  254. SceProcessSecurityPolicyGPOEx(
  255. IN DWORD dwFlags,
  256. IN HANDLE hUserToken,
  257. IN HKEY hKeyRoot,
  258. IN PGROUP_POLICY_OBJECT pDeletedGPOList,
  259. IN PGROUP_POLICY_OBJECT pChangedGPOList,
  260. IN ASYNCCOMPLETIONHANDLE pHandle,
  261. IN BOOL *pbAbort,
  262. IN PFNSTATUSMESSAGECALLBACK pStatusCallback,
  263. IN IWbemServices *pWbemServices,
  264. OUT HRESULT *pHrRsopStatus
  265. )
  266. /*
  267. Description:
  268. This is the new interface called from winlogon/userenv to process GPOs and log
  269. RSOP data. The dll name and procedure name are registered to winlogon under
  270. GpExtensions.
  271. This routine applies a SCE group policy template to the current system.
  272. The template can be in domain level, OU level, or user level. The template
  273. is applied incrementally to the current system. RSOP data is also logged if
  274. a valid namespace pointer is passed in. The server side callbacks log statuses
  275. to all settings with precedence 1 (which corresponds to the merged settings
  276. in the server side JET database)
  277. This interface can be called during system boot, or every GPFrequency hours
  278. after logon. The input argument contains info for where this interface is
  279. called and under which context (user, or machine) this interface is called.
  280. This interface shouldn't be called for user policy.
  281. Arguments:
  282. dwFlags - the GPO Info flags
  283. GPO_INFO_FLAG_MACHINE
  284. GPO_INFO_FLAG_SLOWLINK
  285. GPO_INFO_FLAG_BACKGROUND
  286. GPO_INFO_FLAG_VERBOSE
  287. GPO_INFO_FLAG_NOCHANGES
  288. hUserToken - the user token for which the user policy should be applied
  289. if it's the machine policy, hUserToken refers to system
  290. hKeyRoot - the root for the policy in registry
  291. pDeletedGPOList - all deleted GPOs to process
  292. pChangedGPOList - all GPOs that are either changed or not changed
  293. pHandle - for asynchronous processing
  294. pbAbort - processing of GPO should be aborted if this is set to TRUE
  295. (in case of system shutdown or user log off)
  296. pStatusCallback - Callback function for displaying status messages
  297. */
  298. {
  299. if ( dwFlags & GPO_INFO_FLAG_SAFEMODE_BOOT ) {
  300. // call me next time
  301. return(ERROR_OVERRIDE_NOCHANGES);
  302. }
  303. DWORD rcGPOCreate = ERROR_SUCCESS;
  304. DWORD rcConfig = ERROR_SUCCESS;
  305. DWORD rcLogging = ERROR_SUCCESS;
  306. AREA_INFORMATION AllAreas;
  307. BOOL b;
  308. PWSTR szLogFileName = NULL;
  309. DWORD dwWinlogonLog;
  310. DWORD dwDiagOptions = 0;
  311. //
  312. // this will protect the RSOP global vars from multiple diagnosis'/policy props
  313. // if asynch thread is spawned successfully, will be released there
  314. // else released in synch main thread
  315. //
  316. EnterCriticalSection(&DiagnosisPolicypropSync);
  317. if ( ghAsyncThread != NULL) {
  318. //
  319. // bug# 173858
  320. // on chk'd builds, LeaveCriticalSection() matches thread id's
  321. // so get the existing behavior in the asynch thread
  322. // with a wait
  323. //
  324. //
  325. // allow waiting thread to continue on wait error
  326. // don't care for error since the spawned thread will log errors etc. and
  327. // other policy propagation threads have to continue
  328. //
  329. WaitForSingleObject( ghAsyncThread, INFINITE);
  330. CloseHandle(ghAsyncThread);
  331. ghAsyncThread = NULL;
  332. }
  333. //
  334. // initialize gbAsyncWinlogonThread so it can be set to TRUE if slow thread is spawned
  335. //
  336. gbAsyncWinlogonThread = FALSE;
  337. gHrSynchRsopStatus = WBEM_S_NO_ERROR;
  338. gHrAsynchRsopStatus = WBEM_S_NO_ERROR;
  339. //
  340. // put a try except block in case arguments are invalid
  341. //
  342. __try {
  343. tg_pWbemServices = pWbemServices;
  344. //
  345. // if the namespace parameter is valid, increment the reference count
  346. // the reference count is decremented by the async thread if spawned
  347. // else by the sync thread
  348. //
  349. if (tg_pWbemServices) {
  350. tg_pWbemServices->AddRef();
  351. }
  352. (void) InitializeEvents(L"SceCli");
  353. rcGPOCreate = SceProcessBeforeRSOPLogging(
  354. FALSE,
  355. dwFlags,
  356. hUserToken,
  357. hKeyRoot,
  358. pDeletedGPOList,
  359. pChangedGPOList,
  360. pHandle,
  361. pbAbort,
  362. pStatusCallback,
  363. &AllAreas,
  364. &b,
  365. &szLogFileName,
  366. &dwWinlogonLog
  367. );
  368. // actually *pRsopStatus should be set after callbacks are successful
  369. // log RSOP data if valid namespace ptr
  370. if ( rcGPOCreate != ERROR_OPERATION_ABORTED &&
  371. rcGPOCreate != ERROR_OVERRIDE_NOCHANGES && pWbemServices )
  372. rcLogging = ScepDosErrorToWbemError(SceLogSettingsPrecedenceGPOs(
  373. pWbemServices,
  374. FALSE,
  375. &szLogFileName
  376. ));
  377. if (pHrRsopStatus) {
  378. *pHrRsopStatus = ScepDosErrorToWbemError(rcLogging);
  379. }
  380. if (rcGPOCreate == ERROR_SUCCESS) {
  381. if (pWbemServices != NULL)
  382. dwDiagOptions |= SCE_RSOP_CALLBACK;
  383. rcConfig = SceProcessAfterRSOPLogging(
  384. dwFlags,
  385. pHandle,
  386. pbAbort,
  387. pStatusCallback,
  388. AllAreas,
  389. b,
  390. &szLogFileName,
  391. dwWinlogonLog,
  392. dwDiagOptions
  393. );
  394. }
  395. if (pHrRsopStatus && *pHrRsopStatus == S_OK && gHrSynchRsopStatus != S_OK) {
  396. *pHrRsopStatus = gHrSynchRsopStatus;
  397. }
  398. if ( szLogFileName ) {
  399. //
  400. // szLogFileName is NULL if it was freed somewhere in the sync thread
  401. // this thread will free if the asynch thread was not spawned
  402. //
  403. LocalFree(szLogFileName);
  404. szLogFileName = NULL;
  405. }
  406. //
  407. // clear callback status
  408. //
  409. ScepPolStatusCallback(pStatusCallback, FALSE, 0);
  410. (void) ShutdownEvents();
  411. if (!gbAsyncWinlogonThread) {
  412. if (tg_pWbemServices) {
  413. tg_pWbemServices->Release();
  414. tg_pWbemServices = NULL;
  415. }
  416. if (gpwszDCDomainName) {
  417. LocalFree(gpwszDCDomainName);
  418. gpwszDCDomainName = NULL;
  419. }
  420. }
  421. } __except(EXCEPTION_EXECUTE_HANDLER) {
  422. rcGPOCreate = ERROR_INVALID_PARAMETER;
  423. }
  424. //
  425. // if slow winlogon async thread was not spawned, this thread needs to release cs
  426. //
  427. LeaveCriticalSection(&DiagnosisPolicypropSync);
  428. //
  429. // make sure to release policy notification queue processing
  430. // if it's not released yet.
  431. //
  432. ScepControlNotificationQProcess(NULL, gbThisIsDC, 0);
  433. return(rcGPOCreate != ERROR_SUCCESS ? rcGPOCreate : rcConfig);
  434. }
  435. //
  436. // old API support
  437. // but if extension is RSOP enabled SceProcessSecurityPolicyGPOEx is called
  438. //
  439. DWORD
  440. WINAPI
  441. SceProcessSecurityPolicyGPO(
  442. IN DWORD dwFlags,
  443. IN HANDLE hUserToken,
  444. IN HKEY hKeyRoot,
  445. IN PGROUP_POLICY_OBJECT pDeletedGPOList,
  446. IN PGROUP_POLICY_OBJECT pChangedGPOList,
  447. IN ASYNCCOMPLETIONHANDLE pHandle,
  448. IN BOOL *pbAbort,
  449. IN PFNSTATUSMESSAGECALLBACK pStatusCallback
  450. )
  451. /*
  452. Description:
  453. This is the old interface called from winlogon/userenv to process GPOs. The dll
  454. name and procedure name are registered to winlogon under GpExtensions.
  455. This routine applies a SCE group policy template to the current system.
  456. The template can be in domain level, OU level, or user level. The template
  457. is applied incrementally to the current system.
  458. This interface can be called during system boot, or every GPFrequency hours
  459. after logon. The input argument contains info for where this interface is
  460. called and under which context (user, or machine) this interface is called.
  461. This interface shouldn't be called for user policy.
  462. Arguments:
  463. dwFlags - the GPO Info flags
  464. GPO_INFO_FLAG_MACHINE
  465. GPO_INFO_FLAG_SLOWLINK
  466. GPO_INFO_FLAG_BACKGROUND
  467. GPO_INFO_FLAG_VERBOSE
  468. GPO_INFO_FLAG_NOCHANGES
  469. hUserToken - the user token for which the user policy should be applied
  470. if it's the machine policy, hUserToken refers to system
  471. hKeyRoot - the root for the policy in registry
  472. pDeletedGPOList - all deleted GPOs to process
  473. pChangedGPOList - all GPOs that are either changed or not changed
  474. pHandle - for asynchronous processing
  475. pbAbort - processing of GPO should be aborted if this is set to TRUE
  476. (in case of system shutdown or user log off)
  477. pStatusCallback - Callback function for displaying status messages
  478. */
  479. {
  480. if ( dwFlags & GPO_INFO_FLAG_SAFEMODE_BOOT ) {
  481. // call me next time
  482. return(ERROR_OVERRIDE_NOCHANGES);
  483. }
  484. DWORD rc = ERROR_SUCCESS;
  485. AREA_INFORMATION AllAreas;
  486. BOOL b;
  487. PWSTR szLogFileName = NULL;
  488. DWORD dwWinlogonLog;
  489. //
  490. // this will protect the RSOP global vars from multiple diagnosis'/policy props
  491. // if asynch is spawned successfully, will be released there
  492. // else released in synch main thread
  493. //
  494. EnterCriticalSection(&DiagnosisPolicypropSync);
  495. if ( ghAsyncThread != NULL) {
  496. //
  497. // bug# 173858
  498. // on chk'd builds, LeaveCriticalSection() matches thread id's
  499. // so get the existing behavior in the asynch thread
  500. // with a wait
  501. //
  502. //
  503. // allow waiting thread to continue on wait error
  504. // don't care for error since the spawned thread will log errors etc. and
  505. // other policy propagation threads have to continue
  506. //
  507. WaitForSingleObject( ghAsyncThread, INFINITE);
  508. CloseHandle(ghAsyncThread);
  509. ghAsyncThread = NULL;
  510. }
  511. //
  512. // initialize gbAsyncWinlogonThread so it can be set to TRUE if slow thread is spawned
  513. //
  514. gbAsyncWinlogonThread = FALSE;
  515. __try {
  516. (void) InitializeEvents(L"SceCli");
  517. rc = SceProcessBeforeRSOPLogging(
  518. FALSE,
  519. dwFlags,
  520. hUserToken,
  521. hKeyRoot,
  522. pDeletedGPOList,
  523. pChangedGPOList,
  524. pHandle,
  525. pbAbort,
  526. pStatusCallback,
  527. &AllAreas,
  528. &b,
  529. &szLogFileName,
  530. &dwWinlogonLog
  531. );
  532. if (rc == ERROR_SUCCESS) {
  533. rc = SceProcessAfterRSOPLogging(
  534. dwFlags,
  535. pHandle,
  536. pbAbort,
  537. pStatusCallback,
  538. AllAreas,
  539. b,
  540. &szLogFileName,
  541. dwWinlogonLog,
  542. 0
  543. );
  544. }
  545. if ( szLogFileName ) {
  546. //
  547. // szLogFileName is NULL if it was freed somewhere in the sync thread
  548. // this thread will free if the asynch thread was not spawned
  549. //
  550. LocalFree(szLogFileName);
  551. szLogFileName = NULL;
  552. }
  553. if (!gbAsyncWinlogonThread) {
  554. if (gpwszDCDomainName) {
  555. LocalFree(gpwszDCDomainName);
  556. gpwszDCDomainName = NULL;
  557. }
  558. }
  559. //
  560. // clear callback status
  561. //
  562. ScepPolStatusCallback(pStatusCallback, FALSE, 0);
  563. (void) ShutdownEvents();
  564. } __except(EXCEPTION_EXECUTE_HANDLER) {
  565. rc = ERROR_INVALID_PARAMETER;
  566. }
  567. //
  568. // if slow winlogon async thread was not spawned, this thread needs to release cs
  569. //
  570. LeaveCriticalSection(&DiagnosisPolicypropSync);
  571. // if (!gbAsyncWinlogonThread) {
  572. // LeaveCriticalSection(&DiagnosisPolicypropSync);
  573. // }
  574. //
  575. // ready to copy GPOs from the sysvol location
  576. // should stop queue processing now
  577. //
  578. ScepControlNotificationQProcess(NULL, gbThisIsDC, 0);
  579. return rc;
  580. }
  581. DWORD
  582. SceProcessBeforeRSOPLogging(
  583. IN BOOL bPlanningMode,
  584. IN DWORD dwFlags,
  585. IN HANDLE hUserToken,
  586. IN HKEY hKeyRoot,
  587. IN PGROUP_POLICY_OBJECT pDeletedGPOList OPTIONAL,
  588. IN PGROUP_POLICY_OBJECT pChangedGPOList,
  589. IN ASYNCCOMPLETIONHANDLE pHandle OPTIONAL,
  590. IN BOOL *pbAbort,
  591. IN PFNSTATUSMESSAGECALLBACK pStatusCallback OPTIONAL,
  592. OUT AREA_INFORMATION *pAllAreas OPTIONAL,
  593. OUT BOOL *pb OPTIONAL,
  594. OUT PWSTR *pszLogFileName OPTIONAL,
  595. OUT DWORD *pdwWinlogonLog OPTIONAL
  596. )
  597. /*
  598. Description:
  599. This routine is called for both planning and diagnosis modes. In this routine,
  600. all GPOs are copied locally into a cache for use by the logging routines and/or
  601. configuration routines after this routine.
  602. SceProcessAfterRSOPLogging is a sister function that is called for diagnosis mode only.
  603. This interface shouldn't be called for user policy but within the routine,
  604. a checking is still made to make sure that user level policies is not processed.
  605. For domain or OU level policies, This routine categories policy: 1) policy
  606. must be enforced before user logon (security policy and user rights),
  607. 2) policy can be applied after user logon (for example, file security). For diagnosis mode,
  608. The 2nd category is applied asynchronously (in a separate thread).
  609. Arguments:
  610. dwFlags - the GPO Info flags
  611. GPO_INFO_FLAG_MACHINE
  612. GPO_INFO_FLAG_SLOWLINK
  613. GPO_INFO_FLAG_BACKGROUND
  614. GPO_INFO_FLAG_VERBOSE
  615. GPO_INFO_FLAG_NOCHANGES
  616. hUserToken - the user token for which the user policy should be applied
  617. if it's the machine policy, hUserToken refers to system
  618. hKeyRoot - the root for the policy in registry
  619. pDeletedGPOList - all deleted GPOs to process
  620. pChangedGPOList - all GPOs that are either changed or not changed
  621. pHandle - for asynchronous processing
  622. pbAbort - processing of GPO should be aborted if this is set to TRUE
  623. (in case of system shutdown or user log off)
  624. pStatusCallback - Callback function for displaying status messages
  625. Return Value:
  626. Win32 error
  627. ERROR_SUCCESS
  628. E_PENDING if asynchonous processing
  629. other errors
  630. Note, if error is returned, the previous cached GPO list will be used for
  631. next propagation (because it didn't succeed this time).
  632. */
  633. {
  634. // validate input parameters
  635. if (!bPlanningMode && !hKeyRoot || !hUserToken ) {
  636. return(ERROR_INVALID_PARAMETER);
  637. }
  638. //
  639. // for diagnosis, continue even if the GPO list is empty because of local security database
  640. //
  641. if ( bPlanningMode && pChangedGPOList == NULL ) {
  642. return(ERROR_SUCCESS);
  643. }
  644. DWORD rc = ERROR_SUCCESS;
  645. DWORD rcSave = ERROR_SUCCESS;
  646. DWORD nRequired=0;
  647. BOOL b = FALSE;
  648. DWORD nDays;
  649. /*
  650. DWORD dPeriodInDays=0;
  651. DWORD dLastSeconds=0;
  652. DWORD dCurrentSeconds=0;
  653. */
  654. LARGE_INTEGER CurrentTime;
  655. AREA_INFORMATION AllAreas=0;
  656. HANDLE hfTemp=INVALID_HANDLE_VALUE;
  657. //
  658. // variables for log file names
  659. //
  660. LPTSTR szLogFileName=NULL;
  661. BOOL bSuspend=FALSE;
  662. //
  663. // check if system is shutdown, or dcpromo is going
  664. //
  665. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  666. return(ERROR_OPERATION_ABORTED);
  667. }
  668. if (!bPlanningMode) {
  669. rc = RtlNtStatusToDosError( ScepIsSystemContext(hUserToken,&b) );
  670. }
  671. if ( !bPlanningMode && !b ) {
  672. //
  673. // can't get current user SID or it's not system SID (maybe user policy)
  674. //
  675. if ( ERROR_SUCCESS != rc ) {
  676. //
  677. // error occurs when querying/comparing user token
  678. //
  679. LogEvent(MyModuleHandle,
  680. STATUS_SEVERITY_ERROR,
  681. SCEPOL_ERROR_PROCESS_GPO,
  682. IDS_ERROR_GET_TOKEN_USER,
  683. rc
  684. );
  685. return( rc );
  686. } else {
  687. //
  688. // this is not the machine (system) token, return
  689. //
  690. return( ERROR_SUCCESS );
  691. }
  692. }
  693. if (!bPlanningMode) {
  694. //
  695. // it is machine policy since user policy is filtered out before this
  696. // try to get the thread/process token to check if it is the system context
  697. //
  698. HANDLE hToken = NULL;
  699. if (!OpenThreadToken( GetCurrentThread(),
  700. TOKEN_QUERY,
  701. FALSE,
  702. &hToken)) {
  703. if (!OpenProcessToken( GetCurrentProcess(),
  704. TOKEN_QUERY,
  705. &hToken)) {
  706. rc = GetLastError();
  707. }
  708. }
  709. if ( ERROR_SUCCESS == rc ) {
  710. rc = RtlNtStatusToDosError( ScepIsSystemContext(hToken,&b) );
  711. if (hToken)
  712. CloseHandle(hToken);
  713. }
  714. if (!b) {
  715. if ( ERROR_SUCCESS != rc ) {
  716. //
  717. // error occurs when querying/comparing system token in machine policy
  718. //
  719. LogEvent(MyModuleHandle,
  720. STATUS_SEVERITY_ERROR,
  721. SCEPOL_ERROR_PROCESS_GPO,
  722. IDS_ERROR_GET_TOKEN_MACHINE,
  723. rc
  724. );
  725. return( rc );
  726. } else {
  727. //
  728. // this is not the machine (system) token, return
  729. //
  730. return( ERROR_SUCCESS );
  731. }
  732. }
  733. }
  734. //
  735. // check if system is shutdown, or dcpromo is going
  736. //
  737. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  738. return(ERROR_OPERATION_ABORTED);
  739. }
  740. //
  741. // build log name %windir%\security\logs\winlogon.log
  742. // if the registry flag is set
  743. //
  744. DWORD dwLog = 0;
  745. ScepRegQueryIntValue(
  746. HKEY_LOCAL_MACHINE,
  747. GPT_SCEDLL_NEW_PATH,
  748. (bPlanningMode ? TEXT("ExtensionRsopPlanningDebugLevel") : TEXT("ExtensionDebugLevel")),
  749. &dwLog
  750. );
  751. if ( dwLog != 0 ) {
  752. nRequired = GetSystemWindowsDirectory(NULL, 0);
  753. if ( nRequired ) {
  754. if (bPlanningMode) {
  755. szLogFileName = (LPTSTR)LocalAlloc(0, (nRequired+1+
  756. lstrlen(PLANNING_LOG_PATH))*sizeof(TCHAR));
  757. }
  758. else{
  759. szLogFileName = (LPTSTR)LocalAlloc(0, (nRequired+1+
  760. lstrlen(WINLOGON_LOG_PATH))*sizeof(TCHAR));
  761. }
  762. if ( szLogFileName ){
  763. GetSystemWindowsDirectory(szLogFileName, nRequired);
  764. szLogFileName[nRequired] = L'\0';
  765. lstrcat(szLogFileName, (bPlanningMode ? PLANNING_LOG_PATH : WINLOGON_LOG_PATH));
  766. }else{
  767. // should not occur
  768. // ignore this error, log is NULL}
  769. } // else ignore, log is NULL} // else log is NULL
  770. }
  771. }
  772. //
  773. // find out if this machine is a domain controller
  774. //
  775. if ( !bPlanningMode && !gbDCQueried ) {
  776. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsRole=NULL;
  777. HINSTANCE hDsRoleDll = LoadLibrary(TEXT("netapi32.dll"));
  778. if ( hDsRoleDll) {
  779. PVOID pfDsRole;
  780. pfDsRole = (PVOID)GetProcAddress(
  781. hDsRoleDll,
  782. "DsRoleGetPrimaryDomainInformation");
  783. if ( pfDsRole ) {
  784. rc = (*((PFGETDOMAININFO)pfDsRole))(
  785. NULL,
  786. DsRolePrimaryDomainInfoBasic,
  787. (PBYTE *)&pDsRole
  788. );
  789. if (rc == ERROR_SUCCESS) {
  790. if ( pDsRole->MachineRole == DsRole_RolePrimaryDomainController ||
  791. pDsRole->MachineRole == DsRole_RoleBackupDomainController ) {
  792. gbThisIsDC = TRUE;
  793. //
  794. // stash the domain name in a buffer for use when canonicalizing group names in diagnosis mode
  795. // should be freed similar to critical section
  796. //
  797. if (pDsRole->DomainNameFlat) {
  798. if (gpwszDCDomainName = (PWSTR) LocalAlloc(LMEM_ZEROINIT,
  799. (wcslen(pDsRole->DomainNameFlat) + 1) * sizeof (WCHAR))) {
  800. wcscpy(gpwszDCDomainName, pDsRole->DomainNameFlat);
  801. }
  802. }
  803. }
  804. gbDCQueried = TRUE;
  805. pfDsRole = (PVOID)GetProcAddress(
  806. hDsRoleDll,
  807. "DsRoleFreeMemory");
  808. if ( pfDsRole ) {
  809. (*((PFDSFREE)pfDsRole))( pDsRole );
  810. }
  811. }
  812. }
  813. FreeLibrary(hDsRoleDll);
  814. }
  815. }
  816. //
  817. // check if system is shutdown, or dcpromo is going
  818. //
  819. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  820. rcSave = ERROR_OPERATION_ABORTED;
  821. goto CleanUp;
  822. }
  823. //
  824. // set the MaxNoGPOListChangesInterval back
  825. //
  826. if ( !bPlanningMode && (ERROR_SUCCESS == ScepRegQueryIntValue(
  827. HKEY_LOCAL_MACHINE,
  828. SCE_ROOT_PATH,
  829. TEXT("GPOSavedInterval"),
  830. &nDays
  831. ) ) ) {
  832. ScepRegSetIntValue(
  833. HKEY_LOCAL_MACHINE,
  834. GPT_SCEDLL_NEW_PATH,
  835. TEXT("MaxNoGPOListChangesInterval"),
  836. nDays
  837. );
  838. ScepRegDeleteValue(
  839. HKEY_LOCAL_MACHINE,
  840. SCE_ROOT_PATH,
  841. TEXT("GPOSavedInterval")
  842. );
  843. }
  844. //
  845. // process any policy filter temp files created in setup
  846. // (if this is the reboot after seutp on DC)
  847. //
  848. if (!bPlanningMode)
  849. ScepProcessPolicyFilterTempFiles(szLogFileName);
  850. //
  851. // prepare the log file
  852. //
  853. if ( !bPlanningMode && szLogFileName ) {
  854. //
  855. // check the log size and wrap it if it's over 1M
  856. //
  857. DWORD dwLogSize=0;
  858. HANDLE hFile = CreateFile(szLogFileName,
  859. GENERIC_READ | GENERIC_WRITE,
  860. FILE_SHARE_READ,
  861. NULL,
  862. OPEN_ALWAYS, // OPEN_EXISTING
  863. FILE_ATTRIBUTE_NORMAL,
  864. NULL);
  865. if ( INVALID_HANDLE_VALUE != hFile ) {
  866. dwLogSize = GetFileSize(hFile, NULL);
  867. if ( dwLogSize < (0x1 << 20) ) {
  868. //
  869. // log a line to separate multiple propagation.
  870. //
  871. SetFilePointer (hFile, 0, NULL, FILE_END);
  872. ScepWriteSingleUnicodeLog(hFile, TRUE, L"**************************");
  873. }
  874. CloseHandle(hFile);
  875. }
  876. if ( dwLogSize >= (0x1 << 20) ) {
  877. nRequired = wcslen(szLogFileName);
  878. LPTSTR szTempName = (LPTSTR)LocalAlloc(0, (nRequired+1)*sizeof(TCHAR));
  879. if ( szTempName ) {
  880. wcscpy(szTempName, szLogFileName);
  881. szTempName[nRequired-3] = L'o';
  882. szTempName[nRequired-2] = L'l';
  883. szTempName[nRequired-1] = L'd';
  884. CopyFile( szLogFileName, szTempName, FALSE );
  885. LocalFree(szTempName);
  886. }
  887. DeleteFile(szLogFileName);
  888. }
  889. }
  890. //
  891. // check if system is shutdown, or dcpromo is going
  892. //
  893. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  894. rcSave = ERROR_OPERATION_ABORTED;
  895. goto CleanUp;
  896. }
  897. if ( !ScepClearGPObjects(bPlanningMode) ) {
  898. rc = GetLastError();
  899. LogEvent(MyModuleHandle,
  900. STATUS_SEVERITY_ERROR,
  901. SCEPOL_ERROR_PROCESS_GPO,
  902. IDS_ERR_DELETE_GP_CACHE,
  903. rc
  904. );
  905. SetLastError(rc);
  906. rcSave = ERROR_OPERATION_ABORTED;
  907. goto CleanUp;
  908. }
  909. //
  910. // callback for status display
  911. //
  912. if (!bPlanningMode)
  913. ScepPolStatusCallback(pStatusCallback, FALSE, IDS_APPLY_SECURITY_POLICY);
  914. //
  915. // process each GPO in the changed gpo list
  916. // deleted GPOs are ignored for security policy
  917. //
  918. PGROUP_POLICY_OBJECT pGpo;
  919. rc = ERROR_SUCCESS;
  920. bSuspend=FALSE;
  921. for ( pGpo = pChangedGPOList; pGpo != NULL; pGpo=pGpo->pNext ) {
  922. //
  923. // callback for status display
  924. //
  925. if (!bPlanningMode && pStatusCallback ) {
  926. pStatusCallback(TRUE, pGpo->lpDisplayName);
  927. }
  928. //
  929. // we don't have security policy in local template. ignore it
  930. // the local security policy is stored in the ESE database.
  931. //
  932. if ( pGpo->GPOLink == GPLinkMachine ) {
  933. continue;
  934. }
  935. if (!bPlanningMode && !bSuspend ) {
  936. //
  937. // ready to copy GPOs from the sysvol location
  938. // should stop queue processing now
  939. //
  940. rc = ScepControlNotificationQProcess(szLogFileName, gbThisIsDC, 1);
  941. if ( gbThisIsDC && (ERROR_OVERRIDE_NOCHANGES == rc) ) {
  942. //
  943. // there is policy notification going on right now
  944. //
  945. rcSave = rc;
  946. break;
  947. }
  948. bSuspend = TRUE;
  949. }
  950. rc = ScepProcessSecurityPolicyInOneGPO( bPlanningMode,
  951. dwFlags,
  952. pGpo,
  953. szLogFileName,
  954. &AllAreas
  955. );
  956. if ( rc != ERROR_SUCCESS ) {
  957. //
  958. // continue logging for planning and diagnosis but do not config
  959. //
  960. rcSave = rc;
  961. }
  962. //
  963. // check if system is shutdown, or dcpromo is going
  964. //
  965. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  966. //
  967. // clear callback status
  968. //
  969. if (!bPlanningMode)
  970. ScepPolStatusCallback(pStatusCallback, FALSE, 0);
  971. rcSave = rc = ERROR_OPERATION_ABORTED;
  972. break;
  973. }
  974. }
  975. CleanUp:
  976. if (pb) *pb = b;
  977. if (pszLogFileName)
  978. *pszLogFileName = szLogFileName;
  979. else if (szLogFileName)
  980. LocalFree(szLogFileName);
  981. if (pAllAreas) *pAllAreas = AllAreas;
  982. if (pdwWinlogonLog) *pdwWinlogonLog = dwLog;
  983. return rcSave;
  984. }
  985. DWORD
  986. SceProcessAfterRSOPLogging(
  987. IN DWORD dwFlags,
  988. IN ASYNCCOMPLETIONHANDLE pHandle,
  989. IN BOOL *pbAbort,
  990. IN PFNSTATUSMESSAGECALLBACK pStatusCallback,
  991. IN AREA_INFORMATION ThisAreas,
  992. IN BOOL b,
  993. IN PWSTR *ppszLogFileName,
  994. IN DWORD dwWinlogonLog,
  995. IN DWORD dwDiagOptions
  996. )
  997. /*
  998. Description:
  999. Routine that is called for diagnosis mode only where the actual configuration is done.
  1000. */
  1001. {
  1002. DWORD rc = ERROR_SUCCESS;
  1003. //
  1004. // no error, process all policies on local machine
  1005. //
  1006. TCHAR Windir[MAX_PATH], Buffer[MAX_PATH+50];
  1007. AREA_INFORMATION AllAreas=ThisAreas;
  1008. Windir[0] = L'\0';
  1009. GetSystemWindowsDirectory(Windir, MAX_PATH);
  1010. Windir[MAX_PATH-1] = L'\0';
  1011. wcscpy(Buffer, Windir);
  1012. wcscat(Buffer, L"\\security\\templates\\policies\\gpt*.*");
  1013. intptr_t hFile;
  1014. struct _wfinddata_t FileInfo;
  1015. LONG NoMoreFiles=0;
  1016. hFile = _wfindfirst(Buffer, &FileInfo);
  1017. DWORD dConfigOpt=0;
  1018. //
  1019. // AllAreas contains the areas defined in current set of GPOs
  1020. // query the areas in previous policy propagation
  1021. //
  1022. AREA_INFORMATION PrevAreas = 0;
  1023. ScepRegQueryIntValue(
  1024. HKEY_LOCAL_MACHINE,
  1025. GPT_SCEDLL_NEW_PATH,
  1026. TEXT("PreviousPolicyAreas"),
  1027. &PrevAreas
  1028. );
  1029. // there is no tattoo value for these areas
  1030. PrevAreas &= ~(AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY | AREA_DS_OBJECTS);
  1031. AllAreas |= PrevAreas;
  1032. if ( hFile != -1 && ThisAreas > 0 ) {
  1033. //
  1034. // query the configure frequency which is set by GPE on DC
  1035. // do not care errors. Note, security policy is not controlled
  1036. // by the configure frequency
  1037. // not used
  1038. //
  1039. b = TRUE; // the first template
  1040. do {
  1041. LogEventAndReport(MyModuleHandle,
  1042. (ppszLogFileName ? *ppszLogFileName : NULL),
  1043. 0,
  1044. 0,
  1045. IDS_PROCESS_TEMPLATE,
  1046. FileInfo.name
  1047. );
  1048. Buffer[0] = L'\0';
  1049. wcscpy(Buffer, Windir);
  1050. wcscat(Buffer, L"\\security\\templates\\policies\\");
  1051. wcscat(Buffer, FileInfo.name);
  1052. NoMoreFiles = _wfindnext(hFile, &FileInfo);
  1053. //
  1054. // Buffer contains the real template name to process
  1055. //
  1056. //
  1057. // if it's not the last template, just update the template
  1058. // without really configuring
  1059. //
  1060. dConfigOpt = SCE_UPDATE_DB | SCE_POLICY_TEMPLATE;
  1061. switch ( dwWinlogonLog ) {
  1062. case 0:
  1063. dConfigOpt |= SCE_DISABLE_LOG;
  1064. break;
  1065. case 1:
  1066. dConfigOpt |= SCE_VERBOSE_LOG;
  1067. break;
  1068. default:
  1069. dConfigOpt |= SCE_DEBUG_LOG;
  1070. }
  1071. if ( b ) {
  1072. dConfigOpt |= SCE_POLICY_FIRST;
  1073. if ( gbThisIsDC ) {
  1074. dConfigOpt |= SCE_NOCOPY_DOMAIN_POLICY;
  1075. }
  1076. b = FALSE; // next tempalte is not the first one
  1077. }
  1078. //
  1079. // check if system is shutdown, or dcpromo is going
  1080. //
  1081. if ( ScepShouldTerminateProcessing( pbAbort, TRUE ) ) {
  1082. rc = GetLastError();
  1083. if ( ppszLogFileName && *ppszLogFileName ) {
  1084. LocalFree(*ppszLogFileName);
  1085. *ppszLogFileName = NULL;
  1086. }
  1087. //
  1088. // clear callback status
  1089. //
  1090. ScepPolStatusCallback(pStatusCallback, FALSE, 0);
  1091. return(rc);
  1092. }
  1093. if ( NoMoreFiles == 0 ) {
  1094. //
  1095. // this is not the last one, import the template to engine
  1096. // no matter if the current thread is background or foreground
  1097. // NO_CONFIG yet.
  1098. //
  1099. dConfigOpt |= SCE_NO_CONFIG;
  1100. if ( gbThisIsDC && wcsstr(Buffer, L".inf") != NULL ) {
  1101. //
  1102. // this is not a domain GPO
  1103. // since this machine is a DC, do not take domain policy from this GPO
  1104. //
  1105. dConfigOpt |= SCE_NO_DOMAIN_POLICY;
  1106. LogEventAndReport(MyModuleHandle,
  1107. (ppszLogFileName ? *ppszLogFileName : NULL),
  1108. 0,
  1109. 0,
  1110. IDS_NOT_LAST_GPO_DC,
  1111. L""
  1112. );
  1113. } else {
  1114. LogEventAndReport(MyModuleHandle,
  1115. (ppszLogFileName ? *ppszLogFileName : NULL),
  1116. 0,
  1117. 0,
  1118. IDS_NOT_LAST_GPO,
  1119. L""
  1120. );
  1121. }
  1122. rc = ScepWaitConfigSystem(
  1123. NULL, // local system
  1124. Buffer,
  1125. NULL,
  1126. (ppszLogFileName ? *ppszLogFileName : NULL),
  1127. dConfigOpt | SCE_POLBIND_NO_AUTH,
  1128. AllAreas, // not used when NO_CONFIG is specified
  1129. NULL, // no callback
  1130. NULL, // no callback window
  1131. NULL // no warning
  1132. );
  1133. if ( ERROR_NOT_SUPPORTED == rc ) {
  1134. //
  1135. // server is not ready
  1136. // log an event log to warn users
  1137. //
  1138. LogEvent(MyModuleHandle,
  1139. STATUS_SEVERITY_WARNING,
  1140. SCEPOL_ERROR_PROCESS_GPO,
  1141. IDS_PROPAGATE_NOT_READY,
  1142. rc
  1143. );
  1144. break;
  1145. } else if ( ERROR_IO_PENDING == rc ) {
  1146. rc = ERROR_OVERRIDE_NOCHANGES;
  1147. break;
  1148. } else if (ERROR_SUCCESS != rc ) {
  1149. //
  1150. // log an event log to warn users
  1151. //
  1152. LPVOID lpMsgBuf=NULL;
  1153. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1154. NULL,
  1155. rc,
  1156. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1157. (LPTSTR)&lpMsgBuf,
  1158. 0,
  1159. NULL
  1160. );
  1161. if ( !(dConfigOpt & SCE_NO_CONFIG) &&
  1162. (ERROR_SPECIAL_ACCOUNT == rc) ) {
  1163. LogEvent(MyModuleHandle,
  1164. STATUS_SEVERITY_WARNING,
  1165. SCEPOL_WARNING_PROCESS_GPO,
  1166. IDS_WARNING_PROPAGATE_SPECIAL,
  1167. rc,
  1168. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1169. );
  1170. rc = ERROR_OVERRIDE_NOCHANGES;
  1171. } else {
  1172. switch (rc) {
  1173. case ERROR_NONE_MAPPED:
  1174. LogEvent(MyModuleHandle,
  1175. STATUS_SEVERITY_WARNING,
  1176. SCEPOL_WARNING_PROCESS_GPO,
  1177. IDS_WARNING_PROPAGATE_NOMAP,
  1178. rc,
  1179. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1180. );
  1181. break;
  1182. case ERROR_TIMEOUT:
  1183. LogEvent(MyModuleHandle,
  1184. STATUS_SEVERITY_WARNING,
  1185. SCEPOL_WARNING_PROCESS_GPO,
  1186. IDS_WARNING_PROPAGATE_TIMEOUT,
  1187. rc,
  1188. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1189. );
  1190. break;
  1191. default:
  1192. LogEvent(MyModuleHandle,
  1193. STATUS_SEVERITY_WARNING,
  1194. SCEPOL_WARNING_PROCESS_GPO,
  1195. IDS_WARNING_PROPAGATE,
  1196. rc,
  1197. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1198. );
  1199. }
  1200. }
  1201. if ( lpMsgBuf ) {
  1202. LocalFree(lpMsgBuf);
  1203. }
  1204. break;
  1205. }
  1206. } else {
  1207. //
  1208. // this is the last template in this cycle
  1209. // should trigger configuration now
  1210. //
  1211. dConfigOpt |= SCE_POLICY_LAST;
  1212. AREA_INFORMATION AreaSave, Area, AreaToConfigure;
  1213. AreaSave = AllAreas & (AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY | AREA_DS_OBJECTS ); // background areas
  1214. Area = AllAreas & ~AreaSave;
  1215. //
  1216. // callback for status display
  1217. //
  1218. ScepPolStatusCallback(pStatusCallback, TRUE, IDS_CONFIGURE_POLICY);
  1219. //
  1220. // always use incremental modal to update security policy first
  1221. //
  1222. if ( dwFlags & GPO_INFO_FLAG_BACKGROUND ) {
  1223. //
  1224. // this GPT thread is currently running in the background
  1225. // so configure all security together
  1226. //
  1227. AreaToConfigure = Area | AreaSave;
  1228. } else {
  1229. //
  1230. // this GPT thread is currently running in the foreground
  1231. // or configure frequency condition is not qualified for other areas
  1232. //
  1233. // configure security policy in this thread first
  1234. //
  1235. AreaToConfigure = Area;
  1236. }
  1237. if ( gbThisIsDC && wcsstr(Buffer, L".inf") != NULL ) {
  1238. //
  1239. // this is not a domain GPO, import the template first
  1240. // since this machine is a DC, do not take domain policy from this GPO
  1241. // this is the last one, we need to pass this GPO in
  1242. // without domain policy but domain policy should be configured
  1243. // if it come from the domain level
  1244. // so pass the GPO in first with NO_CONFIG, then call again
  1245. // to configure
  1246. //
  1247. dConfigOpt |= SCE_NO_DOMAIN_POLICY | SCE_NO_CONFIG;
  1248. LogEventAndReport(MyModuleHandle,
  1249. (ppszLogFileName ? *ppszLogFileName : NULL),
  1250. 0,
  1251. 0,
  1252. IDS_LAST_GPO_DC,
  1253. L""
  1254. );
  1255. rc = ScepWaitConfigSystem(
  1256. NULL, // local system
  1257. Buffer,
  1258. NULL,
  1259. (ppszLogFileName ? *ppszLogFileName : NULL),
  1260. dConfigOpt | SCE_POLBIND_NO_AUTH,
  1261. AreaToConfigure | AreaSave,
  1262. NULL, // no callback
  1263. NULL, // no callback window
  1264. NULL // no warning
  1265. );
  1266. if ( ERROR_SUCCESS == rc ) {
  1267. //
  1268. // this is a DC and it's not been configured yet
  1269. // configure now
  1270. //
  1271. dConfigOpt = SCE_POLICY_TEMPLATE |
  1272. SCE_UPDATE_DB;
  1273. switch ( dwWinlogonLog ) {
  1274. case 0:
  1275. dConfigOpt |= SCE_DISABLE_LOG;
  1276. break;
  1277. case 1:
  1278. dConfigOpt |= SCE_VERBOSE_LOG;
  1279. break;
  1280. default:
  1281. dConfigOpt |= SCE_DEBUG_LOG;
  1282. break;
  1283. }
  1284. if (dwDiagOptions & SCE_RSOP_CALLBACK)
  1285. dConfigOpt |= SCE_RSOP_CALLBACK;
  1286. rc = ScepSceStatusToDosError(
  1287. ScepConfigSystem(
  1288. NULL, // local system
  1289. NULL,
  1290. NULL,
  1291. (ppszLogFileName ? *ppszLogFileName : NULL),
  1292. dConfigOpt | SCE_POLBIND_NO_AUTH,
  1293. AreaToConfigure,
  1294. NULL, // no callback
  1295. NULL, // no callback window
  1296. NULL // no warning
  1297. ));
  1298. }
  1299. } else {
  1300. //
  1301. // import/configure the system
  1302. // Note, if it's running in foreground thread
  1303. // and this last template contains file/key policy
  1304. // we need to import file/key policy but not configure them.
  1305. // They will be configured in the background thread.
  1306. //
  1307. if ( (AreaSave > 0) &&
  1308. !(dwFlags & GPO_INFO_FLAG_BACKGROUND) ) {
  1309. dConfigOpt |= SCE_NO_CONFIG_FILEKEY;
  1310. }
  1311. if (dwDiagOptions & SCE_RSOP_CALLBACK)
  1312. dConfigOpt |= SCE_RSOP_CALLBACK;
  1313. rc = ScepWaitConfigSystem(
  1314. NULL, // local system
  1315. Buffer,
  1316. NULL,
  1317. (ppszLogFileName ? *ppszLogFileName : NULL),
  1318. dConfigOpt | SCE_POLBIND_NO_AUTH,
  1319. AreaToConfigure | AreaSave,
  1320. NULL, // no callback
  1321. NULL, // no callback window
  1322. NULL // no warning
  1323. );
  1324. LogEventAndReport(MyModuleHandle,
  1325. (ppszLogFileName ? *ppszLogFileName : NULL),
  1326. 0,
  1327. 0,
  1328. IDS_LAST_GPO,
  1329. L""
  1330. );
  1331. }
  1332. if ( ERROR_NOT_SUPPORTED == rc ) {
  1333. //
  1334. // server is not ready
  1335. // log an event log to warn users
  1336. //
  1337. LogEvent(MyModuleHandle,
  1338. STATUS_SEVERITY_WARNING,
  1339. SCEPOL_ERROR_PROCESS_GPO,
  1340. IDS_PROPAGATE_NOT_READY,
  1341. rc
  1342. );
  1343. break;
  1344. } else if ( ERROR_IO_PENDING == rc ) {
  1345. rc = ERROR_OVERRIDE_NOCHANGES;
  1346. break;
  1347. } else if ( ERROR_SUCCESS != rc ) {
  1348. //
  1349. // log an event log to warn users
  1350. //
  1351. LPVOID lpMsgBuf=NULL;
  1352. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1353. NULL,
  1354. rc,
  1355. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1356. (LPTSTR)&lpMsgBuf,
  1357. 0,
  1358. NULL
  1359. );
  1360. if ( !(dConfigOpt & SCE_NO_CONFIG) &&
  1361. (ERROR_SPECIAL_ACCOUNT == rc) ) {
  1362. LogEvent(MyModuleHandle,
  1363. STATUS_SEVERITY_WARNING,
  1364. SCEPOL_WARNING_PROCESS_GPO,
  1365. IDS_WARNING_PROPAGATE_SPECIAL,
  1366. rc,
  1367. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1368. );
  1369. rc = ERROR_OVERRIDE_NOCHANGES;
  1370. } else {
  1371. switch ( rc ) {
  1372. case ERROR_NONE_MAPPED:
  1373. LogEvent(MyModuleHandle,
  1374. STATUS_SEVERITY_WARNING,
  1375. SCEPOL_WARNING_PROCESS_GPO,
  1376. IDS_WARNING_PROPAGATE_NOMAP,
  1377. rc,
  1378. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1379. );
  1380. break;
  1381. case ERROR_TIMEOUT:
  1382. LogEvent(MyModuleHandle,
  1383. STATUS_SEVERITY_WARNING,
  1384. SCEPOL_WARNING_PROCESS_GPO,
  1385. IDS_WARNING_PROPAGATE_TIMEOUT,
  1386. rc,
  1387. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1388. );
  1389. break;
  1390. default:
  1391. LogEvent(MyModuleHandle,
  1392. STATUS_SEVERITY_WARNING,
  1393. SCEPOL_WARNING_PROCESS_GPO,
  1394. IDS_WARNING_PROPAGATE,
  1395. rc,
  1396. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1397. );
  1398. break;
  1399. }
  1400. }
  1401. if ( lpMsgBuf ) {
  1402. LocalFree(lpMsgBuf);
  1403. }
  1404. break;
  1405. }
  1406. if ( (AreaSave > 0) &&
  1407. !(dwFlags & GPO_INFO_FLAG_BACKGROUND) ) {
  1408. //
  1409. // The current thread is on winlogon's main thread,
  1410. // Create a separate thread to run this "slow" stuff
  1411. // so winlogon is not blocked
  1412. //
  1413. LogEventAndReport(MyModuleHandle,
  1414. (ppszLogFileName ? *ppszLogFileName : NULL),
  1415. 0,
  1416. 0,
  1417. IDS_GPO_FOREGROUND_THREAD,
  1418. L""
  1419. );
  1420. //
  1421. // variables for the second thread
  1422. //
  1423. ULONG idThread;
  1424. HANDLE hThread;
  1425. ENGINEARGS *pEA;
  1426. pEA = (ENGINEARGS *)LocalAlloc(0, sizeof(ENGINEARGS));
  1427. if ( pEA ) {
  1428. LPSTREAM pStream = NULL;
  1429. //
  1430. // marshall the namespace parameter so the async
  1431. // thread can log RSOP data during callbacks
  1432. //
  1433. if (tg_pWbemServices)
  1434. CoMarshalInterThreadInterfaceInStream(IID_IWbemServices, tg_pWbemServices, &pStream);
  1435. pEA->szTemplateName = NULL;
  1436. pEA->szLogName = (ppszLogFileName ? *ppszLogFileName : NULL);
  1437. pEA->Area = AreaSave;
  1438. pEA->pHandle = pHandle;
  1439. pEA->dwDiagOptions = dwDiagOptions;
  1440. pEA->pStream = pStream;
  1441. hSceDll = LoadLibrary(TEXT("scecli.dll"));
  1442. //
  1443. // the second thread runs ScepWinlogonThreadFunc with
  1444. // arguments pEA
  1445. //
  1446. hThread = CreateThread(NULL,
  1447. 0,
  1448. (PTHREAD_START_ROUTINE)ScepWinlogonThreadFunc,
  1449. (LPVOID)pEA,
  1450. 0,
  1451. &idThread);
  1452. ghAsyncThread = hThread;
  1453. if (hThread) {
  1454. gbAsyncWinlogonThread = TRUE;
  1455. //
  1456. // need not be freed in synch thread - the asynch thread will free it
  1457. //
  1458. if (ppszLogFileName)
  1459. *ppszLogFileName = NULL;
  1460. //
  1461. // do not wait, return to winlogon
  1462. // buffer will be freed by the other thread
  1463. //
  1464. //CloseHandle(hThread);
  1465. rc = (DWORD)E_PENDING;
  1466. } else {
  1467. rc = GetLastError();
  1468. LocalFree(pEA);
  1469. //
  1470. // error occurs to create the thread, the library won't
  1471. // be freed by the thread, so free it here
  1472. //
  1473. if ( hSceDll ) {
  1474. FreeLibrary(hSceDll);
  1475. }
  1476. }
  1477. } else {
  1478. rc = ERROR_NOT_ENOUGH_MEMORY;
  1479. }
  1480. }
  1481. }
  1482. } while ( NoMoreFiles == 0 );
  1483. _findclose(hFile);
  1484. } else {
  1485. //
  1486. // there is no SCE GPOs but we still need to take the local policy
  1487. //
  1488. dConfigOpt = SCE_UPDATE_DB |
  1489. SCE_POLICY_TEMPLATE | SCE_POLICY_FIRST | SCE_POLICY_LAST;
  1490. switch ( dwWinlogonLog ) {
  1491. case 0:
  1492. dConfigOpt |= SCE_DISABLE_LOG;
  1493. break;
  1494. case 1:
  1495. dConfigOpt |= SCE_VERBOSE_LOG;
  1496. break;
  1497. default:
  1498. dConfigOpt |= SCE_DEBUG_LOG;
  1499. break;
  1500. }
  1501. if ( gbThisIsDC ) {//
  1502. // this is not a domain GPO, no domain policy should be
  1503. // set from the local policy table.
  1504. //
  1505. dConfigOpt |= SCE_NO_DOMAIN_POLICY |
  1506. SCE_NOCOPY_DOMAIN_POLICY;
  1507. }
  1508. //
  1509. // callback for status display
  1510. //
  1511. ScepPolStatusCallback(pStatusCallback, TRUE, IDS_CONFIGURE_POLICY);
  1512. //
  1513. // the server may not be initialized yet
  1514. // wait for some time and try again
  1515. //
  1516. rc = ScepWaitConfigSystem(
  1517. NULL, // local system
  1518. NULL,
  1519. NULL,
  1520. (ppszLogFileName ? *ppszLogFileName : NULL),
  1521. dConfigOpt | SCE_POLBIND_NO_AUTH,
  1522. AllAreas, //AREA_SECURITY_POLICY | AREA_PRIVILEGES,
  1523. NULL, // no callback
  1524. NULL, // no callback window
  1525. NULL // no warning
  1526. );
  1527. if ( ERROR_NOT_SUPPORTED == rc ) {
  1528. //
  1529. // server is not ready
  1530. // log an event log to warn users
  1531. //
  1532. LogEvent(MyModuleHandle,
  1533. STATUS_SEVERITY_WARNING,
  1534. SCEPOL_ERROR_PROCESS_GPO,
  1535. IDS_PROPAGATE_NOT_READY,
  1536. rc
  1537. );
  1538. } else if ( ERROR_IO_PENDING == rc ) {
  1539. rc = ERROR_OVERRIDE_NOCHANGES;
  1540. } else if ( ERROR_SUCCESS != rc ) {
  1541. LPVOID lpMsgBuf=NULL;
  1542. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1543. NULL,
  1544. rc,
  1545. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1546. (LPTSTR)&lpMsgBuf,
  1547. 0,
  1548. NULL
  1549. );
  1550. if ( !(dConfigOpt & SCE_NO_CONFIG) &&
  1551. (ERROR_SPECIAL_ACCOUNT == rc) ) {
  1552. LogEvent(MyModuleHandle,
  1553. STATUS_SEVERITY_WARNING,
  1554. SCEPOL_WARNING_PROCESS_GPO,
  1555. IDS_WARNING_PROPAGATE_SPECIAL,
  1556. rc,
  1557. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1558. );
  1559. rc = ERROR_OVERRIDE_NOCHANGES;
  1560. } else {
  1561. switch ( rc ) {
  1562. case ERROR_NONE_MAPPED:
  1563. LogEvent(MyModuleHandle,
  1564. STATUS_SEVERITY_WARNING,
  1565. SCEPOL_WARNING_PROCESS_GPO,
  1566. IDS_WARNING_PROPAGATE_NOMAP,
  1567. rc,
  1568. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1569. );
  1570. break;
  1571. case ERROR_TIMEOUT:
  1572. LogEvent(MyModuleHandle,
  1573. STATUS_SEVERITY_WARNING,
  1574. SCEPOL_WARNING_PROCESS_GPO,
  1575. IDS_WARNING_PROPAGATE_TIMEOUT,
  1576. rc,
  1577. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1578. );
  1579. break;
  1580. default:
  1581. LogEvent(MyModuleHandle,
  1582. STATUS_SEVERITY_WARNING,
  1583. SCEPOL_WARNING_PROCESS_GPO,
  1584. IDS_WARNING_PROPAGATE,
  1585. rc,
  1586. lpMsgBuf ? (PWSTR)lpMsgBuf : L"\r\n"
  1587. );
  1588. break;
  1589. }
  1590. }
  1591. if ( lpMsgBuf ) {
  1592. LocalFree(lpMsgBuf);
  1593. }
  1594. }
  1595. }
  1596. //
  1597. // save configuration time to registry, only care security policy status
  1598. // error from the second thread won't be tracked
  1599. //
  1600. if ( ERROR_SUCCESS == rc ||
  1601. E_PENDING == rc ) {
  1602. ScepLogLastConfigTime();
  1603. //
  1604. // log an informational event to state security policy is applied
  1605. //
  1606. LogEvent(MyModuleHandle,
  1607. STATUS_SEVERITY_INFORMATIONAL,
  1608. SCEPOL_INFO_GPO_COMPLETED,
  1609. 0,
  1610. TEXT("")
  1611. );
  1612. //
  1613. // save ThisAreas for next policy prop (to reset tattoo)
  1614. //
  1615. ScepRegSetIntValue(
  1616. HKEY_LOCAL_MACHINE,
  1617. GPT_SCEDLL_NEW_PATH,
  1618. TEXT("PreviousPolicyAreas"),
  1619. ThisAreas
  1620. );
  1621. } else {
  1622. //
  1623. // Something failed when propagate this set of policy
  1624. // tattoo values from previous policy may not be reset yet.
  1625. // To make sure undefined areas are covered in the next prop
  1626. // we have to save AllAreas for next policy prop (to reset tattoo)
  1627. //
  1628. ScepRegSetIntValue(
  1629. HKEY_LOCAL_MACHINE,
  1630. GPT_SCEDLL_NEW_PATH,
  1631. TEXT("PreviousPolicyAreas"),
  1632. AllAreas
  1633. );
  1634. }
  1635. if ( rc == ERROR_DATABASE_FAILURE ) {
  1636. //
  1637. // policy propagation category error - log to eventlog
  1638. //
  1639. LogEvent(MyModuleHandle,
  1640. STATUS_SEVERITY_ERROR,
  1641. SCEEVENT_ERROR_JET_DATABASE,
  1642. IDS_ERROR_OPEN_JET_DATABASE,
  1643. L"%windir%\\security\\database\\secedit.sdb"
  1644. );
  1645. }
  1646. return rc;
  1647. }
  1648. DWORD
  1649. ScepPolStatusCallback(
  1650. IN PFNSTATUSMESSAGECALLBACK pStatusCallback OPTIONAL,
  1651. IN BOOL bVerbose,
  1652. IN INT nId
  1653. )
  1654. {
  1655. if ( NULL == pStatusCallback ) {
  1656. // no callback
  1657. return ERROR_SUCCESS;
  1658. }
  1659. if ( nId > 0 ) {
  1660. TCHAR szMsg[MAX_PATH];
  1661. if (LoadString (MyModuleHandle, nId, szMsg, MAX_PATH)) {
  1662. pStatusCallback(bVerbose, szMsg);
  1663. return ERROR_SUCCESS;
  1664. }
  1665. }
  1666. pStatusCallback(bVerbose, NULL);
  1667. return ERROR_SUCCESS;
  1668. }
  1669. BOOL
  1670. ScepShouldTerminateProcessing(
  1671. IN BOOL *pbAbort,
  1672. IN BOOL bCheckDcpromo
  1673. )
  1674. /*
  1675. Check if the policy propagation should be terminated. There are two
  1676. conditions: 1) system is requesting a shutdown
  1677. 2) dcpromo is going on
  1678. */
  1679. {
  1680. if ( pbAbort && *pbAbort ) {
  1681. SetLastError( ERROR_OPERATION_ABORTED );
  1682. return TRUE;
  1683. }
  1684. if ( bCheckDcpromo ) {
  1685. DWORD dwPolicyPropOff=0;
  1686. ScepRegQueryIntValue(
  1687. HKEY_LOCAL_MACHINE,
  1688. SCE_ROOT_PATH,
  1689. TEXT("PolicyPropOff"),
  1690. &dwPolicyPropOff
  1691. );
  1692. if ( dwPolicyPropOff ) {
  1693. SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
  1694. return TRUE;
  1695. }
  1696. }
  1697. return FALSE;
  1698. }
  1699. DWORD
  1700. ScepProcessSecurityPolicyInOneGPO(
  1701. IN BOOL bPlanningMode,
  1702. IN DWORD dwFlags,
  1703. IN PGROUP_POLICY_OBJECT pGpoInfo,
  1704. IN LPTSTR szLogFileName OPTIONAL,
  1705. IN OUT AREA_INFORMATION *pTotalArea
  1706. )
  1707. {
  1708. //
  1709. // build the template name and log name
  1710. //
  1711. if ( pGpoInfo == NULL || pGpoInfo->lpFileSysPath == NULL) {
  1712. return(ERROR_INVALID_PARAMETER);
  1713. }
  1714. DWORD rc;
  1715. DWORD nRequired=0;
  1716. LPTSTR szTemplateName=NULL;
  1717. //
  1718. // build security template name for this GPO
  1719. //
  1720. nRequired = lstrlen(pGpoInfo->lpFileSysPath)+2+
  1721. lstrlen(GPTSCE_TEMPLATE);
  1722. szTemplateName = (LPTSTR)LocalAlloc(0, nRequired*sizeof(TCHAR));
  1723. if ( szTemplateName ) {
  1724. swprintf(szTemplateName, L"%s\\%s\0",
  1725. pGpoInfo->lpFileSysPath,
  1726. GPTSCE_TEMPLATE);
  1727. //
  1728. // detect what area is available in the template
  1729. //
  1730. AREA_INFORMATION Area = ScepGetAvailableArea(bPlanningMode,
  1731. pGpoInfo->lpFileSysPath,
  1732. pGpoInfo->lpDSPath,
  1733. szTemplateName,
  1734. pGpoInfo->GPOLink,
  1735. gbThisIsDC);
  1736. //
  1737. // if Area is 0, there must be an error occured to open the template
  1738. //
  1739. if ( Area == 0 ) {
  1740. rc = GetLastError();
  1741. } else {
  1742. rc = 0;
  1743. }
  1744. *pTotalArea |= Area;
  1745. //
  1746. // log GPT header information into the log file
  1747. //
  1748. if ( Area == 0 && rc != 0 ) {
  1749. //
  1750. // template can't be accessed, log the error to event log
  1751. // don't log it if this is a DC (so all GPOs are accessed locally)
  1752. // bug the DC is too busy (rc = 1450)
  1753. //
  1754. if ( !gbThisIsDC || ( ERROR_NO_SYSTEM_RESOURCES != rc) ) {
  1755. LogEventAndReport(MyModuleHandle,
  1756. szLogFileName,
  1757. STATUS_SEVERITY_ERROR,
  1758. SCEPOL_ERROR_PROCESS_GPO,
  1759. IDS_ERROR_ACCESS_TEMPLATE,
  1760. rc,
  1761. szTemplateName
  1762. );
  1763. }
  1764. } else if ( szLogFileName ) {
  1765. if ( Area == 0 ) {
  1766. //
  1767. // template not defined at this level
  1768. //
  1769. LogEventAndReport(MyModuleHandle,
  1770. szLogFileName,
  1771. 0,
  1772. 0,
  1773. IDS_INFO_NO_TEMPLATE,
  1774. pGpoInfo->lpFileSysPath
  1775. );
  1776. } else{
  1777. //
  1778. // process the template
  1779. //
  1780. LogEventAndReport(MyModuleHandle,
  1781. szLogFileName,
  1782. 0,
  1783. 0,
  1784. IDS_INFO_COPY_TEMPLATE,
  1785. szTemplateName
  1786. );
  1787. HANDLE hfTemp = CreateFile(szLogFileName,
  1788. GENERIC_WRITE,
  1789. FILE_SHARE_READ,
  1790. NULL,
  1791. OPEN_ALWAYS,
  1792. FILE_ATTRIBUTE_NORMAL,
  1793. NULL);
  1794. if ( hfTemp != INVALID_HANDLE_VALUE ) {
  1795. DWORD dwBytesWritten;
  1796. SetFilePointer (hfTemp, 0, NULL, FILE_BEGIN);
  1797. BYTE TmpBuf[3];
  1798. TmpBuf[0] = 0xFF;
  1799. TmpBuf[1] = 0xFE;
  1800. TmpBuf[2] = 0;
  1801. WriteFile (hfTemp, (LPCVOID)TmpBuf, 2,
  1802. &dwBytesWritten,
  1803. NULL);
  1804. SetFilePointer (hfTemp, 0, NULL, FILE_END);
  1805. // ScepWriteVariableUnicodeLog( hfTemp, FALSE, "\tGPO Area %x Flag %x (", Area, dwFlags);
  1806. BOOL bCRLF;
  1807. if ( dwFlags & GPO_INFO_FLAG_BACKGROUND )
  1808. bCRLF = FALSE;
  1809. else
  1810. bCRLF = TRUE;
  1811. switch ( pGpoInfo->GPOLink ) {
  1812. case GPLinkDomain:
  1813. ScepWriteSingleUnicodeLog(hfTemp, bCRLF, L"GPLinkDomain ");
  1814. break;
  1815. case GPLinkMachine:
  1816. ScepWriteSingleUnicodeLog(hfTemp, bCRLF, L"GPLinkMachine ");
  1817. break;
  1818. case GPLinkSite:
  1819. ScepWriteSingleUnicodeLog(hfTemp, bCRLF, L"GPLinkSite ");
  1820. break;
  1821. case GPLinkOrganizationalUnit:
  1822. ScepWriteSingleUnicodeLog(hfTemp, bCRLF, L"GPLinkOrganizationUnit ");
  1823. break;
  1824. default:
  1825. ScepWriteVariableUnicodeLog(hfTemp, bCRLF, L"0x%x ", pGpoInfo->GPOLink);
  1826. break;
  1827. }
  1828. if ( dwFlags & GPO_INFO_FLAG_BACKGROUND )
  1829. ScepWriteSingleUnicodeLog(hfTemp, TRUE, L"GPO_INFO_FLAG_BACKGROUND )");
  1830. // if ( pGpoInfo->pNext == NULL ) // last one
  1831. // ScepWriteVariableUnicodeLog( hfTemp, FALSE, " Total area %x", *pTotalArea);
  1832. CloseHandle(hfTemp);
  1833. }
  1834. }
  1835. }
  1836. LocalFree(szTemplateName);
  1837. } else {
  1838. rc = ERROR_NOT_ENOUGH_MEMORY;
  1839. }
  1840. return rc;
  1841. }
  1842. AREA_INFORMATION
  1843. ScepGetAvailableArea(
  1844. IN BOOL bPlanningMode,
  1845. IN LPCTSTR SysPathRoot,
  1846. IN LPCTSTR DSPath,
  1847. IN LPTSTR InfName,
  1848. IN GPO_LINK LinkInfo,
  1849. IN BOOL bIsDC
  1850. )
  1851. {
  1852. int index=0;
  1853. TCHAR Windir[MAX_PATH];
  1854. TCHAR Buffer[MAX_PATH+50], Buf2[MAX_PATH+50];
  1855. Windir[0] = L'\0';
  1856. GetSystemWindowsDirectory(Windir, MAX_PATH);
  1857. Windir[MAX_PATH-1] = L'\0';
  1858. Buffer[MAX_PATH+49] = L'\0';
  1859. Buf2[MAX_PATH+49] = L'\0';
  1860. intptr_t hFile;
  1861. struct _wfinddata_t FileInfo;
  1862. if (bPlanningMode) {
  1863. swprintf(Buf2,
  1864. L"%s"PLANNING_GPT_DIR L"tmpgptfl.inf\0",
  1865. Windir);
  1866. }
  1867. else {
  1868. swprintf(Buf2,
  1869. L"%s"DIAGNOSIS_GPT_DIR L"tmpgptfl.inf\0",
  1870. Windir);
  1871. }
  1872. DeleteFile(Buf2);
  1873. CopyFile( InfName, Buf2, FALSE );
  1874. SetLastError(ERROR_SUCCESS);
  1875. AREA_INFORMATION Area = SceGetAreas(Buf2);
  1876. if ( Area != 0 ) {
  1877. //
  1878. // for diagnosis mode
  1879. // copy the template to local machine %windir%\\security\\templates\\policies\gpt*.* (inf or dom)
  1880. // for planning mode
  1881. // copy the template to local machine %TMP%\\guid\gpt*.* (inf or dom)
  1882. //
  1883. if (bPlanningMode) {
  1884. swprintf(Buffer,
  1885. L"%s"PLANNING_GPT_DIR L"gpt%05d.*\0",
  1886. Windir , index);
  1887. }
  1888. else {
  1889. swprintf(Buffer,
  1890. L"%s"DIAGNOSIS_GPT_DIR L"gpt%05d.*\0",
  1891. Windir, index);
  1892. }
  1893. hFile = _wfindfirst(Buffer, &FileInfo);
  1894. while ( hFile != -1 ) {
  1895. _findclose(hFile);
  1896. index++;
  1897. if (bPlanningMode) {
  1898. swprintf(Buffer,
  1899. L"%s"PLANNING_GPT_DIR L"gpt%05d.*\0",
  1900. Windir, index);
  1901. }
  1902. else {
  1903. swprintf(Buffer,
  1904. L"%s"DIAGNOSIS_GPT_DIR L"gpt%05d.*\0",
  1905. Windir, index);
  1906. }
  1907. hFile = _wfindfirst(Buffer, &FileInfo);
  1908. }
  1909. DWORD Len=wcslen(Buffer);
  1910. if ( LinkInfo == GPLinkDomain ) {
  1911. //
  1912. // this is a domain GPO
  1913. //
  1914. Buffer[Len-1] = L'd';
  1915. Buffer[Len] = L'o';
  1916. Buffer[Len+1] = L'm';
  1917. Buffer[Len+2] = L'\0';
  1918. } else {
  1919. //
  1920. // this is not domain GPO
  1921. //
  1922. Buffer[Len-1] = L'i';
  1923. Buffer[Len] = L'n';
  1924. Buffer[Len+1] = L'f';
  1925. Buffer[Len+2] = L'\0';
  1926. if ( bIsDC ) {
  1927. /*
  1928. LogEvent(MyModuleHandle,
  1929. STATUS_SEVERITY_INFORMATIONAL,
  1930. SCEPOL_INFO_IGNORE_DOMAINPOLICY,
  1931. 0,
  1932. SysPathRoot
  1933. );
  1934. */
  1935. }
  1936. }
  1937. if ( FALSE == CopyFile( Buf2, Buffer, FALSE ) ) {
  1938. //
  1939. // copy failed, report error (GetLastError)
  1940. //
  1941. Area = 0;
  1942. } else {
  1943. //
  1944. // save the GPO sys path in this template
  1945. //
  1946. PWSTR pTemp = wcsstr(_wcsupr((LPTSTR)SysPathRoot), L"\\POLICIES");
  1947. if ( pTemp && *(pTemp+10) != L'\0' ) {
  1948. WritePrivateProfileString (TEXT("Version"),
  1949. TEXT("GPOPath"),
  1950. pTemp+10,
  1951. Buffer);
  1952. } else {
  1953. WritePrivateProfileString (TEXT("Version"),
  1954. TEXT("GPOPath"),
  1955. NULL,
  1956. Buffer);
  1957. }
  1958. //
  1959. // save the stripped GPO DS path in this template to extract canonical GPOID later
  1960. //
  1961. UINT Len = 0;
  1962. PWSTR GpoPath = NULL;
  1963. if (DSPath &&
  1964. (Len = wcslen(DSPath)) &&
  1965. (GpoPath = (PWSTR) ScepAlloc(LMEM_ZEROINIT, (Len + 3) * sizeof(WCHAR)))){
  1966. swprintf(GpoPath,
  1967. L"\"%s\"",
  1968. ScepStripPrefix((LPTSTR)DSPath)
  1969. );
  1970. WritePrivateProfileString (TEXT("Version"),
  1971. TEXT("DSPath"),
  1972. GpoPath,
  1973. Buffer);
  1974. ScepFree(GpoPath);
  1975. }
  1976. else
  1977. WritePrivateProfileString (TEXT("Version"),
  1978. TEXT("DSPath"),
  1979. TEXT("NoName"),
  1980. Buffer);
  1981. //
  1982. // save the GPO LinkInfo in this template to extract SOMID later
  1983. //
  1984. WCHAR StringBuf[10];
  1985. _itow((int)LinkInfo, StringBuf, 10);
  1986. WritePrivateProfileString (TEXT("Version"),
  1987. TEXT("SOMID"),
  1988. StringBuf,
  1989. Buffer);
  1990. }
  1991. } else if ( GetLastError() == ERROR_FILE_NOT_FOUND ||
  1992. GetLastError() == ERROR_PATH_NOT_FOUND ) {
  1993. //
  1994. // two reasons that this will fail:
  1995. // first, the template does not exist; second, FRS/sysvol/network failed
  1996. //
  1997. if ( 0xFFFFFFFF == GetFileAttributes((LPTSTR)SysPathRoot) ) {
  1998. SetLastError(ERROR_PATH_NOT_FOUND);
  1999. } else {
  2000. //
  2001. // the sysvol/network is ok so SCE template is not there (including sub directories)
  2002. //
  2003. SetLastError(ERROR_SUCCESS);
  2004. }
  2005. }
  2006. return(Area);
  2007. }
  2008. AREA_INFORMATION
  2009. SceGetAreas(
  2010. LPTSTR InfName
  2011. )
  2012. {
  2013. if ( InfName == NULL ) {
  2014. SetLastError(ERROR_INVALID_PARAMETER);
  2015. return 0;
  2016. }
  2017. SCESTATUS rc;
  2018. HINF hInf;
  2019. INFCONTEXT InfLine;
  2020. AREA_INFORMATION Area=0;
  2021. rc = SceInfpOpenProfile(
  2022. InfName,
  2023. &hInf
  2024. );
  2025. if ( SCESTATUS_SUCCESS == rc ) {
  2026. //
  2027. // policy attachments sections can't be determined here. So always take security policy section
  2028. //
  2029. if( SetupFindFirstLine(hInf, szSystemAccess, NULL, &InfLine) ||
  2030. SetupFindFirstLine(hInf, szAuditSystemLog, NULL, &InfLine) ||
  2031. SetupFindFirstLine(hInf, szAuditSecurityLog, NULL, &InfLine) ||
  2032. SetupFindFirstLine(hInf, szAuditApplicationLog, NULL, &InfLine) ||
  2033. SetupFindFirstLine(hInf, szAuditEvent, NULL, &InfLine) ||
  2034. SetupFindFirstLine(hInf, szKerberosPolicy, NULL, &InfLine) ||
  2035. SetupFindFirstLine(hInf, szRegistryValues, NULL, &InfLine) ) {
  2036. Area |= AREA_SECURITY_POLICY;
  2037. } else {
  2038. PSCE_NAME_LIST pList=NULL, pTemp;
  2039. rc = ScepEnumerateAttachments(&pList, SCE_ATTACHMENT_POLICY);
  2040. if ( ERROR_SUCCESS == rc && pList ) {
  2041. //
  2042. // find policy attachments
  2043. //
  2044. for ( pTemp = pList; pTemp != NULL; pTemp = pTemp->Next ) {
  2045. if ( SetupFindFirstLine(hInf, pTemp->Name, NULL, &InfLine) ) {
  2046. Area |= AREA_SECURITY_POLICY;
  2047. break;
  2048. }
  2049. }
  2050. ScepFreeNameList(pList);
  2051. }
  2052. }
  2053. if(SetupFindFirstLine(hInf,szPrivilegeRights,NULL,&InfLine)) {
  2054. Area |= AREA_PRIVILEGES;
  2055. }
  2056. if(SetupFindFirstLine(hInf,szGroupMembership,NULL,&InfLine)) {
  2057. Area |= AREA_GROUP_MEMBERSHIP;
  2058. }
  2059. if(SetupFindFirstLine(hInf,szRegistryKeys,NULL,&InfLine)) {
  2060. Area |= AREA_REGISTRY_SECURITY;
  2061. }
  2062. if(SetupFindFirstLine(hInf,szFileSecurity,NULL,&InfLine)) {
  2063. Area |= AREA_FILE_SECURITY;
  2064. }
  2065. #if 0
  2066. if(SetupFindFirstLine(hInf,szDSSecurity,NULL,&InfLine)) {
  2067. Area |= AREA_DS_OBJECTS;
  2068. }
  2069. #endif
  2070. if(SetupFindFirstLine(hInf,szServiceGeneral,NULL,&InfLine)) {
  2071. Area |= AREA_SYSTEM_SERVICE;
  2072. } else {
  2073. PSCE_NAME_LIST pList=NULL, pTemp;
  2074. rc = ScepEnumerateAttachments(&pList, SCE_ATTACHMENT_SERVICE);
  2075. if ( ERROR_SUCCESS == rc && pList ) {
  2076. //
  2077. // find policy attachments
  2078. //
  2079. for ( pTemp = pList; pTemp != NULL; pTemp = pTemp->Next ) {
  2080. if ( SetupFindFirstLine(hInf, pTemp->Name, NULL, &InfLine) ) {
  2081. Area |= AREA_SYSTEM_SERVICE;
  2082. break;
  2083. }
  2084. }
  2085. ScepFreeNameList(pList);
  2086. }
  2087. }
  2088. //
  2089. // close the inf file
  2090. //
  2091. SceInfpCloseProfile(hInf);
  2092. SetLastError(ERROR_SUCCESS);
  2093. }
  2094. return Area;
  2095. }
  2096. BOOL
  2097. ScepClearGPObjects(
  2098. IN BOOL bPlanningMode
  2099. )
  2100. {
  2101. TCHAR Windir[MAX_PATH], Buffer[MAX_PATH+50];
  2102. DWORD rc = ERROR_SUCCESS;
  2103. Windir[0] = L'\0';
  2104. GetSystemWindowsDirectory(Windir, MAX_PATH);
  2105. Windir[MAX_PATH-1] = L'\0';
  2106. // make sure policies or policies\planning directory exist
  2107. // don't worry about errors - later it will be caught
  2108. wcscpy(Buffer, Windir);
  2109. wcscat(Buffer, DIAGNOSIS_GPT_DIR);
  2110. CreateDirectory(Buffer, NULL);
  2111. if (bPlanningMode) {
  2112. wcscat(Buffer, L"planning");
  2113. CreateDirectory(Buffer, NULL);
  2114. }
  2115. wcscpy(Buffer, Windir);
  2116. wcscat(Buffer, (bPlanningMode ? PLANNING_GPT_DIR : DIAGNOSIS_GPT_DIR));
  2117. if (!bPlanningMode)
  2118. SetFileAttributes(Buffer, FILE_ATTRIBUTE_HIDDEN);
  2119. wcscat(Buffer, L"gpt*.*");
  2120. intptr_t hFile;
  2121. struct _wfinddata_t FileInfo;
  2122. hFile = _wfindfirst(Buffer, &FileInfo);
  2123. if ( hFile != -1 ) {
  2124. do {
  2125. Buffer[0] = L'\0';
  2126. wcscpy(Buffer, Windir);
  2127. wcscat(Buffer, (bPlanningMode ? PLANNING_GPT_DIR : DIAGNOSIS_GPT_DIR));
  2128. wcscat(Buffer, FileInfo.name);
  2129. if ( !DeleteFile(Buffer) ){
  2130. rc = GetLastError();
  2131. break;
  2132. }
  2133. } while ( _wfindnext(hFile, &FileInfo) == 0 );
  2134. _findclose(hFile);
  2135. }
  2136. if (rc != ERROR_SUCCESS) {
  2137. SetLastError(rc);
  2138. return(FALSE);
  2139. }
  2140. return(TRUE);
  2141. }
  2142. DWORD
  2143. ScepWinlogonThreadFunc(
  2144. IN LPVOID lpv
  2145. )
  2146. /*
  2147. Routine Description:
  2148. The working thread to apply slow GPT polices. These policies include file
  2149. security, registry security, DS object security if on a DC,
  2150. system service security, and any other SCE extensions security.
  2151. The SCE library is loaded before this thread is created (in order to keep
  2152. the ref count non zero) so the SCE library is freed when this thread exits.
  2153. Memory allocated in the input argument (by primary thread) are freed in this
  2154. thread too.
  2155. Arguments:
  2156. lpv - the input info in ENGINEARGS structure, in which
  2157. szTemplateName is the group policy template name to apply
  2158. szLogName is the optional log file name
  2159. Return Value:
  2160. Win32 errors
  2161. */
  2162. {
  2163. ENGINEARGS *pEA;
  2164. DWORD rc;
  2165. //
  2166. // try-except block to ensure critical section is freed if this thread is entered
  2167. // need two - due to two return's
  2168. //
  2169. if ( lpv ) {
  2170. pEA = (ENGINEARGS *)lpv;
  2171. if ( hSceDll ) {
  2172. __try {
  2173. //
  2174. // need to initialize the COM library to use the unmarshalling functions
  2175. //
  2176. if (pEA->pStream) {
  2177. CoInitializeEx( NULL, COINIT_MULTITHREADED );
  2178. VOID *pV = NULL;
  2179. if (S_OK == CoGetInterfaceAndReleaseStream(pEA->pStream, IID_IWbemServices, &pV))
  2180. tg_pWbemServices = (IWbemServices *) pV;
  2181. else
  2182. tg_pWbemServices = NULL;
  2183. }
  2184. //
  2185. // only apply template to the system if SCE library is loaded in memory
  2186. // otherwise, access violation occurs when access code.
  2187. //
  2188. DWORD dConfigOpt = SCE_UPDATE_DB |
  2189. SCE_POLICY_TEMPLATE |
  2190. SCE_POLBIND_NO_AUTH;
  2191. DWORD dwWinlogonLog=0;
  2192. ScepRegQueryIntValue(
  2193. HKEY_LOCAL_MACHINE,
  2194. GPT_SCEDLL_NEW_PATH,
  2195. TEXT("ExtensionDebugLevel"),
  2196. &dwWinlogonLog
  2197. );
  2198. switch ( dwWinlogonLog ) {
  2199. case 2:
  2200. dConfigOpt |= SCE_DEBUG_LOG;
  2201. break;
  2202. case 1:
  2203. dConfigOpt |= SCE_VERBOSE_LOG;
  2204. break;
  2205. default:
  2206. dConfigOpt |= SCE_DISABLE_LOG;
  2207. }
  2208. if (pEA->dwDiagOptions & SCE_RSOP_CALLBACK)
  2209. dConfigOpt |= SCE_RSOP_CALLBACK;
  2210. rc = ScepSceStatusToDosError(
  2211. ScepConfigSystem(
  2212. NULL,
  2213. pEA->szTemplateName,
  2214. NULL,
  2215. pEA->szLogName,
  2216. (tg_pWbemServices == NULL ? dConfigOpt & ~SCE_RSOP_CALLBACK : dConfigOpt), //rsop not supported
  2217. pEA->Area,
  2218. NULL, // no callback
  2219. NULL, // no callback window
  2220. NULL // no warning
  2221. ));
  2222. if (tg_pWbemServices) {
  2223. tg_pWbemServices->Release();
  2224. tg_pWbemServices = NULL;
  2225. }
  2226. if (pEA->pStream)
  2227. CoUninitialize();
  2228. if (gpwszDCDomainName) {
  2229. LocalFree(gpwszDCDomainName);
  2230. gpwszDCDomainName = NULL;
  2231. }
  2232. if ( ERROR_SUCCESS == rc ) {
  2233. //
  2234. // Log the last config time
  2235. //
  2236. ScepLogLastConfigTime();
  2237. }
  2238. //
  2239. // set status back to GP framework with the new API
  2240. //
  2241. ProcessGroupPolicyCompletedEx(
  2242. &SceExtGuid,
  2243. pEA->pHandle,
  2244. rc,
  2245. gHrAsynchRsopStatus); //WBEM_E_INVALID_PARAMETER
  2246. //
  2247. // free memory allocated by the primary thread
  2248. //
  2249. if ( pEA->szTemplateName ) {
  2250. LocalFree(pEA->szTemplateName);
  2251. }
  2252. if ( pEA->szLogName ) {
  2253. LocalFree(pEA->szLogName);
  2254. }
  2255. LocalFree(pEA);
  2256. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2257. rc = (DWORD)EVENT_E_INTERNALEXCEPTION;
  2258. }
  2259. //
  2260. // leave the cs before returning/exiting
  2261. //
  2262. // LeaveCriticalSection(&DiagnosisPolicypropSync);
  2263. //
  2264. // free library and exit the thread
  2265. //
  2266. FreeLibraryAndExitThread(hSceDll, rc );
  2267. return(rc);
  2268. } else {
  2269. rc = ERROR_INVALID_PARAMETER;
  2270. }
  2271. } else {
  2272. rc = ERROR_INVALID_PARAMETER;
  2273. }
  2274. //
  2275. // the main spawner thread is relying on this thread to release the cs
  2276. // before we exit this thread, under any circumstances, release the cs to enable other
  2277. // diagnosis/policy prop threads to enter
  2278. //
  2279. // LeaveCriticalSection(&DiagnosisPolicypropSync);
  2280. ExitThread(rc);
  2281. return(rc);
  2282. }
  2283. DWORD
  2284. ScepLogLastConfigTime()
  2285. {
  2286. DWORD dCurrentSeconds=0;
  2287. LARGE_INTEGER CurrentTime;
  2288. DWORD rc;
  2289. NTSTATUS NtStatus;
  2290. NtStatus = NtQuerySystemTime(&CurrentTime);
  2291. if ( NT_SUCCESS(NtStatus) ) {
  2292. //
  2293. // Convert to seconds to save
  2294. //
  2295. if ( RtlTimeToSecondsSince1980 (&CurrentTime, &dCurrentSeconds) ) {
  2296. rc = ScepRegSetIntValue(
  2297. HKEY_LOCAL_MACHINE,
  2298. SCE_ROOT_PATH,
  2299. TEXT("LastWinLogonConfig"),
  2300. dCurrentSeconds
  2301. );
  2302. } else {
  2303. rc = GetLastError();
  2304. }
  2305. } else {
  2306. rc = RtlNtStatusToDosError(NtStatus);
  2307. }
  2308. return(rc);
  2309. }
  2310. DWORD
  2311. ScepEnumerateAttachments(
  2312. OUT PSCE_NAME_LIST *pEngineList,
  2313. IN SCE_ATTACHMENT_TYPE aType
  2314. )
  2315. /*
  2316. Routine Description:
  2317. Query all services which has a service engine for security manager
  2318. The service engine information is in the registry:
  2319. MACHINE\Software\Microsoft\Windows NT\CurrentVersion\SeCEdit
  2320. Arguments:
  2321. pEngineList - the service engine name list
  2322. aType - attachment type (service or policy)
  2323. Return Value:
  2324. SCE status
  2325. */
  2326. {
  2327. if ( pEngineList == NULL ) {
  2328. return(ERROR_INVALID_PARAMETER);
  2329. }
  2330. DWORD Win32Rc;
  2331. HKEY hKey=NULL;
  2332. switch ( aType ) {
  2333. case SCE_ATTACHMENT_SERVICE:
  2334. Win32Rc = RegOpenKeyEx(
  2335. HKEY_LOCAL_MACHINE,
  2336. SCE_ROOT_SERVICE_PATH,
  2337. 0,
  2338. KEY_READ,
  2339. &hKey
  2340. );
  2341. break;
  2342. case SCE_ATTACHMENT_POLICY:
  2343. Win32Rc = RegOpenKeyEx(
  2344. HKEY_LOCAL_MACHINE,
  2345. SCE_ROOT_POLICY_PATH,
  2346. 0,
  2347. KEY_READ,
  2348. &hKey
  2349. );
  2350. break;
  2351. default:
  2352. return ERROR_INVALID_PARAMETER;
  2353. }
  2354. if ( Win32Rc == ERROR_SUCCESS ) {
  2355. TCHAR Buffer[MAX_PATH];
  2356. DWORD BufSize;
  2357. DWORD index = 0;
  2358. DWORD EnumRc;
  2359. //
  2360. // enumerate all subkeys of the key
  2361. //
  2362. do {
  2363. memset(Buffer, '\0', MAX_PATH*sizeof(WCHAR));
  2364. BufSize = MAX_PATH;
  2365. EnumRc = RegEnumKeyEx(
  2366. hKey,
  2367. index,
  2368. Buffer,
  2369. &BufSize,
  2370. NULL,
  2371. NULL,
  2372. NULL,
  2373. NULL);
  2374. if ( EnumRc == ERROR_SUCCESS ) {
  2375. index++;
  2376. //
  2377. // get the attachment name
  2378. //
  2379. Win32Rc = ScepAddToNameList(pEngineList, Buffer, BufSize+1);
  2380. if ( Win32Rc != ERROR_SUCCESS ) {
  2381. break;
  2382. }
  2383. }
  2384. } while ( EnumRc != ERROR_NO_MORE_ITEMS );
  2385. RegCloseKey(hKey);
  2386. //
  2387. // remember the error code from enumeration
  2388. //
  2389. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  2390. if ( Win32Rc == ERROR_SUCCESS )
  2391. Win32Rc = EnumRc;
  2392. }
  2393. }
  2394. if ( Win32Rc != NO_ERROR && *pEngineList != NULL ) {
  2395. //
  2396. // free memory allocated for the list
  2397. //
  2398. ScepFreeNameList(*pEngineList);
  2399. *pEngineList = NULL;
  2400. }
  2401. return( Win32Rc );
  2402. }
  2403. DWORD
  2404. WINAPI
  2405. SceProcessEFSRecoveryGPO(
  2406. IN DWORD dwFlags,
  2407. IN HANDLE hUserToken,
  2408. IN HKEY hKeyRoot,
  2409. IN PGROUP_POLICY_OBJECT pDeletedGPOList,
  2410. IN PGROUP_POLICY_OBJECT pChangedGPOList,
  2411. IN ASYNCCOMPLETIONHANDLE pHandle,
  2412. IN BOOL *pbAbort,
  2413. IN PFNSTATUSMESSAGECALLBACK pStatusCallback
  2414. )
  2415. /*
  2416. Description:
  2417. This is a interface called from winlogon/userenv to process GPOs. The dll
  2418. name and procedure name are registered to winlogon under GpExtensions.
  2419. This routine applies a EFS recovery policy to the current system. The EFS
  2420. recovery policy is stored in registry as EfsBlob and will be loaded by
  2421. the registry extension into hKeyRoot. So this extension requires that
  2422. registry.pol must be loaded successfully by the registry extension.
  2423. This interface can be called during system boot, or every GPFrequency hours
  2424. after logon. The input argument contains info for where this interface is
  2425. called and under which context (user, or machine) this interface is called.
  2426. This interface shouldn't be called for user policy but within the routine,
  2427. a checking is still made to make sure that user level policies is not processed.
  2428. Arguments:
  2429. dwFlags - the GPO Info flags
  2430. GPO_INFO_FLAG_MACHINE
  2431. GPO_INFO_FLAG_SLOWLINK
  2432. GPO_INFO_FLAG_BACKGROUND
  2433. GPO_INFO_FLAG_VERBOSE
  2434. GPO_INFO_FLAG_NOCHANGES
  2435. hUserToken - the user token for which the user policy should be applied
  2436. if it's the machine policy, hUserToken refers to system
  2437. hKeyRoot - the root for the policy in registry
  2438. pDeletedGPOList - all deleted GPOs to process
  2439. pChangedGPOList - all GPOs that are either changed or not changed
  2440. pHandle - for asynchronous processing
  2441. pbAbort - processing of GPO should be aborted if this is set to TRUE
  2442. (in case of system shutdown or user log off)
  2443. pStatusCallback - Callback function for displaying status messages
  2444. Return Value:
  2445. Win32 error
  2446. ERROR_SUCCESS
  2447. other errors
  2448. Note, if error is returned, the previous cached GPO list will be used for
  2449. next propagation (because it didn't succeed this time).
  2450. */
  2451. {
  2452. // validate input parameters
  2453. if ( !hKeyRoot || !hUserToken ) {
  2454. return(ERROR_INVALID_PARAMETER);
  2455. }
  2456. //Check if demote flag is set need to add Auth user and Interactive to users group.
  2457. // group membership should be configured by SCE/demote via tattoo table. This is not needed
  2458. // ScepCheckDemote();
  2459. //
  2460. // check if system is shutdown, or dcpromo is going
  2461. //
  2462. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  2463. return(ERROR_OPERATION_ABORTED);
  2464. }
  2465. DWORD rc;
  2466. BOOL b;
  2467. //
  2468. // put a try except block in case arguments are invalid
  2469. //
  2470. __try {
  2471. rc = RtlNtStatusToDosError( ScepIsSystemContext(hUserToken, &b) );
  2472. (void) InitializeEvents(L"SceEfs");
  2473. if ( !b ) {
  2474. //
  2475. // can't get current user SID or it's not system SID
  2476. //
  2477. if ( ERROR_SUCCESS != rc ) {
  2478. //
  2479. // error occurs when querying/comparing user token
  2480. //
  2481. LogEvent(MyModuleHandle,
  2482. STATUS_SEVERITY_ERROR,
  2483. SCEPOL_ERROR_PROCESS_GPO,
  2484. IDS_ERROR_GET_TOKEN_USER,
  2485. rc
  2486. );
  2487. ShutdownEvents();
  2488. return( rc );
  2489. } else {
  2490. //
  2491. // this is not the machine (system) token, return
  2492. //
  2493. ShutdownEvents();
  2494. return( ERROR_SUCCESS );
  2495. }
  2496. }
  2497. //
  2498. // check if system is shutdown, or dcpromo is going
  2499. //
  2500. if ( ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  2501. ShutdownEvents();
  2502. return(ERROR_OPERATION_ABORTED);
  2503. }
  2504. //
  2505. // check if debug log is requested
  2506. //
  2507. DWORD dwDebugLevel=0;
  2508. ScepRegQueryIntValue(
  2509. HKEY_LOCAL_MACHINE, // always save the time in HKEY_LOCAL_MACHINE
  2510. GPT_EFS_NEW_PATH,
  2511. TEXT("ExtensionDebugLevel"),
  2512. &dwDebugLevel
  2513. );
  2514. //
  2515. // if there is no change to EFS policy
  2516. //
  2517. if ( dwFlags & GPO_INFO_FLAG_NOCHANGES ) {
  2518. if ( dwDebugLevel ) {
  2519. LogEvent(MyModuleHandle,
  2520. STATUS_SEVERITY_INFORMATIONAL,
  2521. SCEPOL_INFO_PROCESS_GPO,
  2522. IDS_EFS_NOT_CHANGE
  2523. );
  2524. ShutdownEvents();
  2525. }
  2526. return(ERROR_SUCCESS);
  2527. }
  2528. //
  2529. // process EFS policy
  2530. //
  2531. HKEY hKey=NULL;
  2532. DWORD RegType=0;
  2533. DWORD dSize=0;
  2534. PUCHAR pEfsBlob=NULL;
  2535. if ( (rc = RegOpenKeyEx(
  2536. hKeyRoot,
  2537. CERT_EFSBLOB_REGPATH,
  2538. 0,
  2539. KEY_READ,
  2540. &hKey
  2541. )) == ERROR_SUCCESS ) {
  2542. //
  2543. // query value for EfsBlob
  2544. //
  2545. if(( rc = RegQueryValueEx(hKey,
  2546. CERT_EFSBLOB_VALUE_NAME,
  2547. 0,
  2548. &RegType,
  2549. NULL,
  2550. &dSize
  2551. )) == ERROR_SUCCESS ) {
  2552. if ( REG_BINARY == RegType ) {
  2553. //
  2554. // must be binary type data
  2555. //
  2556. pEfsBlob = (PUCHAR)ScepAlloc( LMEM_ZEROINIT, dSize+1);
  2557. if ( !pEfsBlob ) {
  2558. rc = ERROR_NOT_ENOUGH_MEMORY;
  2559. } else {
  2560. rc = RegQueryValueEx(
  2561. hKey,
  2562. CERT_EFSBLOB_VALUE_NAME,
  2563. 0,
  2564. &RegType,
  2565. (BYTE *)pEfsBlob,
  2566. &dSize
  2567. );
  2568. if ( ERROR_SUCCESS != rc ) {
  2569. ScepFree(pEfsBlob);
  2570. pEfsBlob = NULL;
  2571. dSize = 0;
  2572. }
  2573. }
  2574. } else {
  2575. rc = ERROR_INVALID_DATATYPE;
  2576. }
  2577. }
  2578. RegCloseKey(hKey);
  2579. }
  2580. if ( rc == ERROR_FILE_NOT_FOUND ) {
  2581. //
  2582. // if the key or the value doesn't exist
  2583. // ignore the error (no EFS policy)
  2584. //
  2585. rc = ERROR_SUCCESS;
  2586. }
  2587. //
  2588. // if pEfsBlob is NULL, it means that there is no EFS policy defined
  2589. //
  2590. if ( ERROR_SUCCESS == rc ) {
  2591. //
  2592. // check if system is shutdown, or dcpromo is going
  2593. //
  2594. if ( !ScepShouldTerminateProcessing( pbAbort, FALSE ) ) {
  2595. rc = ScepConfigureEFSPolicy( pEfsBlob, dSize, dwDebugLevel );
  2596. } else {
  2597. rc = GetLastError();
  2598. }
  2599. ScepFree(pEfsBlob);
  2600. } else if ( dwDebugLevel ) {
  2601. LogEvent(MyModuleHandle,
  2602. STATUS_SEVERITY_ERROR,
  2603. SCEPOL_INFO_PROCESS_GPO,
  2604. IDS_NO_EFS_TOTAL,
  2605. rc
  2606. );
  2607. }
  2608. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2609. rc = ERROR_INVALID_PARAMETER;
  2610. }
  2611. ShutdownEvents();
  2612. return rc;
  2613. }
  2614. DWORD
  2615. ScepConfigureEFSPolicy(
  2616. IN PUCHAR pEfsBlob,
  2617. IN DWORD dwSize,
  2618. IN DWORD dwDebugLevel
  2619. )
  2620. /*
  2621. Routine Description:
  2622. This routine writes EFS recovery policy defined in the policy storage
  2623. (all processed by the registry extension) to LSA storage.
  2624. Arguments:
  2625. pEfsBlob - the EFS blob
  2626. Return Value:
  2627. Win32 error code
  2628. */
  2629. {
  2630. DWORD rc=ERROR_SUCCESS;
  2631. NTSTATUS NtStatus;
  2632. BOOL bSet;
  2633. LSA_HANDLE PolicyHandle=NULL;
  2634. PPOLICY_DOMAIN_EFS_INFO Buffer=NULL;
  2635. POLICY_DOMAIN_EFS_INFO EfsInfo;
  2636. //
  2637. // only set to LSA if there is EFS policy defined in any level
  2638. // NO EFS policy is defined as 0 certificated but the EFS blob shouldn't be NULL
  2639. //
  2640. // open LSA policy
  2641. //
  2642. bSet = TRUE; // if to set EFS policy
  2643. NtStatus = ScepOpenLsaPolicy(
  2644. MAXIMUM_ALLOWED, //GENERIC_ALL,
  2645. &PolicyHandle,
  2646. TRUE
  2647. );
  2648. if (NT_SUCCESS(NtStatus)) {
  2649. //
  2650. // query existing EFS policy blob
  2651. // ignore errors from query
  2652. //
  2653. NtStatus = LsaQueryDomainInformationPolicy(
  2654. PolicyHandle,
  2655. PolicyDomainEfsInformation,
  2656. (PVOID *)&Buffer
  2657. );
  2658. if ( NT_SUCCESS(NtStatus) && Buffer ) {
  2659. //
  2660. // compare the length and/or buffer to determine if
  2661. // blob is changed because every time data is set to LSA
  2662. // EFS server will get notified even when policy
  2663. // is changed.
  2664. //
  2665. if ( Buffer->InfoLength != dwSize ||
  2666. (Buffer->EfsBlob && pEfsBlob == NULL) ||
  2667. (Buffer->EfsBlob == NULL && pEfsBlob ) ||
  2668. (Buffer->EfsBlob &&
  2669. memcmp(pEfsBlob, Buffer->EfsBlob, (size_t)dwSize) != 0) ) {
  2670. //
  2671. // the new EFS blob is different than existing one
  2672. //
  2673. bSet = TRUE;
  2674. } else {
  2675. bSet = FALSE;
  2676. }
  2677. }
  2678. //
  2679. // free memory allocated by LSA
  2680. //
  2681. if ( Buffer ) {
  2682. LsaFreeMemory((PVOID)Buffer);
  2683. Buffer = NULL;
  2684. }
  2685. //
  2686. // set EFS policy if bSet is TRUE
  2687. //
  2688. if ( bSet ) {
  2689. EfsInfo.InfoLength = dwSize;
  2690. EfsInfo.EfsBlob = pEfsBlob;
  2691. NtStatus = LsaSetDomainInformationPolicy(
  2692. PolicyHandle,
  2693. PolicyDomainEfsInformation,
  2694. (PVOID)&EfsInfo
  2695. );
  2696. rc = RtlNtStatusToDosError(NtStatus);
  2697. if ( !NT_SUCCESS(NtStatus) ) {
  2698. LogEvent(MyModuleHandle,
  2699. STATUS_SEVERITY_ERROR,
  2700. SCEPOL_ERROR_PROCESS_GPO,
  2701. IDS_SAVE_EFS,
  2702. rc,
  2703. dwSize
  2704. );
  2705. } else if ( dwDebugLevel ) {
  2706. LogEvent(MyModuleHandle,
  2707. STATUS_SEVERITY_INFORMATIONAL,
  2708. SCEPOL_INFO_PROCESS_GPO,
  2709. IDS_SAVE_EFS,
  2710. 0,
  2711. dwSize
  2712. );
  2713. }
  2714. } else if ( dwDebugLevel ) {
  2715. LogEvent(MyModuleHandle,
  2716. STATUS_SEVERITY_INFORMATIONAL,
  2717. SCEPOL_INFO_PROCESS_GPO,
  2718. IDS_EFS_NOT_CHANGE
  2719. );
  2720. }
  2721. //
  2722. // close LSA policy
  2723. //
  2724. LsaClose(PolicyHandle);
  2725. } else {
  2726. rc = RtlNtStatusToDosError( NtStatus );
  2727. LogEvent(MyModuleHandle,
  2728. STATUS_SEVERITY_ERROR,
  2729. SCEPOL_ERROR_PROCESS_GPO,
  2730. IDS_ERROR_OPEN_LSAEFS,
  2731. rc
  2732. );
  2733. }
  2734. return(rc);
  2735. }
  2736. DWORD
  2737. ScepWaitConfigSystem(
  2738. IN LPTSTR SystemName OPTIONAL,
  2739. IN PWSTR InfFileName OPTIONAL,
  2740. IN PWSTR DatabaseName OPTIONAL,
  2741. IN PWSTR LogFileName OPTIONAL,
  2742. IN DWORD ConfigOptions,
  2743. IN AREA_INFORMATION Area,
  2744. IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL,
  2745. IN HANDLE hCallbackWnd OPTIONAL,
  2746. OUT PDWORD pdWarning OPTIONAL
  2747. )
  2748. {
  2749. INT cnt=0;
  2750. DWORD rc;
  2751. while (cnt < 24) {
  2752. rc = ScepSceStatusToDosError(
  2753. ScepConfigSystem(
  2754. SystemName,
  2755. InfFileName,
  2756. DatabaseName,
  2757. LogFileName,
  2758. ConfigOptions,
  2759. Area,
  2760. pCallback,
  2761. hCallbackWnd,
  2762. pdWarning
  2763. ));
  2764. if ( rc != ERROR_NOT_SUPPORTED ) {
  2765. //
  2766. // the server is initialized now.
  2767. //
  2768. break;
  2769. }
  2770. LogEventAndReport(MyModuleHandle,
  2771. LogFileName,
  2772. 0,
  2773. 0,
  2774. IDS_POLICY_TIMEOUT,
  2775. cnt+1
  2776. );
  2777. Sleep(5000); // 5 second
  2778. cnt++;
  2779. }
  2780. return(rc);
  2781. }
  2782. /*
  2783. BOOL
  2784. ScepCheckDemote()
  2785. {
  2786. //
  2787. // If sucess lets see if user just did demote and reboot.
  2788. //
  2789. DWORD dwDemoteInProgress=0;
  2790. ScepRegQueryIntValue(
  2791. HKEY_LOCAL_MACHINE,
  2792. SCE_ROOT_PATH,
  2793. TEXT("DemoteInProgress"),
  2794. &dwDemoteInProgress
  2795. );
  2796. if (dwDemoteInProgress) {
  2797. DWORD rc1;
  2798. //
  2799. // Attempt to add Authenticated Users and Interactive back into Users group.
  2800. //
  2801. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  2802. PSID AuthenticatedUsers = NULL;
  2803. PSID Interactive = NULL;
  2804. WCHAR Name[36];
  2805. BOOL b;
  2806. LOCALGROUP_MEMBERS_INFO_0 lgrmi0[2];
  2807. HMODULE hMod = GetModuleHandle(L"scecli.dll");
  2808. LoadString(hMod, IDS_NAME_USERS, Name, 36);
  2809. b = AllocateAndInitializeSid (
  2810. &NtAuthority,
  2811. 1,
  2812. SECURITY_AUTHENTICATED_USER_RID,
  2813. 0, 0, 0, 0, 0, 0, 0,
  2814. &AuthenticatedUsers
  2815. );
  2816. if (b) {
  2817. lgrmi0[0].lgrmi0_sid = AuthenticatedUsers;
  2818. b = AllocateAndInitializeSid (
  2819. &NtAuthority,
  2820. 1,
  2821. SECURITY_INTERACTIVE_RID,
  2822. 0, 0, 0, 0, 0, 0, 0,
  2823. &Interactive
  2824. );
  2825. if (b) {
  2826. lgrmi0[1].lgrmi0_sid = Interactive;
  2827. rc1 = NetLocalGroupAddMembers(
  2828. NULL,
  2829. Name,
  2830. 0,
  2831. (PBYTE) &lgrmi0,
  2832. 2
  2833. );
  2834. }
  2835. else {
  2836. if ( AuthenticatedUsers ) {
  2837. FreeSid( AuthenticatedUsers );
  2838. }
  2839. return FALSE;
  2840. }
  2841. if ( AuthenticatedUsers ) {
  2842. FreeSid( AuthenticatedUsers );
  2843. }
  2844. if ( Interactive ) {
  2845. FreeSid( Interactive );
  2846. }
  2847. if (rc1 == ERROR_SUCCESS) {
  2848. // Need to delete the value.
  2849. rc1 = ScepRegDeleteValue(
  2850. HKEY_LOCAL_MACHINE,
  2851. SCE_ROOT_PATH,
  2852. TEXT("DemoteInProgress")
  2853. );
  2854. if ( rc1 != ERROR_SUCCESS &&
  2855. rc1 != ERROR_FILE_NOT_FOUND &&
  2856. rc1 != ERROR_PATH_NOT_FOUND ) {
  2857. // if can't delete the value, set the value to 0
  2858. ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  2859. SCE_ROOT_PATH,
  2860. TEXT("DemoteInProgress"),
  2861. 0
  2862. );
  2863. }
  2864. }
  2865. else {
  2866. return FALSE;
  2867. }
  2868. }
  2869. else {
  2870. return FALSE;
  2871. }
  2872. }
  2873. return TRUE;
  2874. }
  2875. */