Leaked source code of windows server 2003
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.

3749 lines
111 KiB

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