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.

11766 lines
368 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. config.c
  5. Abstract:
  6. Routines to configure system to comply the security profile information
  7. Author:
  8. Jin Huang (jinhuang) 7-Nov-1996
  9. Revision History:
  10. jinhuang 27-Jan-1997 split for client-server
  11. --*/
  12. #include "headers.h"
  13. #include "serverp.h"
  14. #include "pfp.h"
  15. #include "kerberos.h"
  16. #include "regvalue.h"
  17. #include "service.h"
  18. #include <io.h>
  19. #include <lmcons.h>
  20. #include <secobj.h>
  21. #include <netlib.h>
  22. #include "infp.h"
  23. #include "sddl.h"
  24. #include "queue.h"
  25. #include "splay.h"
  26. #include "authz.h"
  27. #include "seopaque.h"
  28. #include "scesetup.h"
  29. #include "dsrole.h"
  30. #pragma hdrstop
  31. //
  32. // properties of SCP engine (thread safe variables)
  33. //
  34. BYTE Thread scpBuffer[sizeof(SCE_PROFILE_INFO)];
  35. PSCE_PROFILE_INFO Thread pScpInfo=NULL;
  36. PSCECONTEXT Thread hProfile=NULL;
  37. LSA_HANDLE Thread LsaPrivatePolicy=NULL;
  38. static DSROLE_MACHINE_ROLE gMachineRole = DsRole_RoleStandaloneWorkstation;
  39. extern HINSTANCE MyModuleHandle;
  40. extern AUTHZ_RESOURCE_MANAGER_HANDLE ghAuthzResourceManager;
  41. extern HANDLE ghEventSamFilterAndPolicyPropExclusion;
  42. #define SCE_PRIV_ADD TEXT("Add:")
  43. #define SCE_PRIV_REMOVE TEXT("Remove:")
  44. #define SCEP_NUM_LSA_QUERY_SIDS 2000
  45. #define MAXDWORD 0xffffffff
  46. #define SCEDCPOL_MIN_PASS_AGE 0
  47. #define SCEDCPOL_MAX_PASS_AGE 42
  48. #define SCEDCPOL_MIN_PASS_LEN 0
  49. #define SCEDCPOL_PASS_SIZE 1
  50. #define SCEDCPOL_PASS_COMP 0
  51. #define SCEDCPOL_CLEAR_PASS 0
  52. #define SCEDCPOL_REQUIRE_LOGON 0
  53. #define SCEDCPOL_FORCE_LOGOFF 0
  54. #define SCEDCPOL_ENABLE_ADMIN 1
  55. #define SCEDCPOL_ENABLE_GUEST 0
  56. #define SCEDCPOL_LOCK_COUNT 0
  57. #define SCEDCPOL_LOCK_RESET 30
  58. #define SCEDCPOL_LOCK_DURATION 30
  59. #define SCEDCPOL_LSA_ANON_LOOKUP 1
  60. VOID
  61. ScepWriteSpecialRegistryValuesIntoPolicy(
  62. PWSTR pszFileName,
  63. PSCE_PROFILE_INFO pTemplateProfile,
  64. PSCE_REGISTRY_VALUE_INFO pLocalRegSettings,
  65. DWORD dwNumLocalSettings
  66. );
  67. DWORD
  68. ScepGetTemplateInformation(
  69. IN PWSTR pszFilename,
  70. IN DWORD Area,
  71. IN HINSTANCE hSceCliDll,
  72. OUT PSCE_PROFILE_INFO *pProfileInfo
  73. );
  74. DWORD
  75. ScepConfigureLSAPolicyObject(
  76. IN DWORD dwLSAAnonymousNameLookup,
  77. IN DWORD ConfigOptions,
  78. IN PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
  79. OUT BOOL *pbOldLSAPolicyDifferent
  80. );
  81. DWORD
  82. ScepAddAceToSecurityDescriptor(
  83. IN DWORD AceType,
  84. IN ACCESS_MASK AccessMask,
  85. IN PSID pSid,
  86. IN OUT PSECURITY_DESCRIPTOR pSDAbsolute,
  87. IN PSECURITY_DESCRIPTOR pSDSelfRelative,
  88. OUT PACL *ppNewAcl
  89. );
  90. //
  91. // this function is defined in inftojet.cpp
  92. //
  93. SCESTATUS
  94. ScepBuildNewPrivilegeList(
  95. IN LSA_HANDLE *pPolicyHandle,
  96. IN PWSTR PrivName,
  97. IN PWSTR mszUsers,
  98. IN ULONG dwBuildOption,
  99. OUT PWSTR *pmszNewUsers,
  100. OUT DWORD *pNewLen
  101. );
  102. //
  103. // forward references
  104. //
  105. SCESTATUS
  106. ScepConfigureInitialize(
  107. IN PCWSTR InfFileName OPTIONAL,
  108. IN PWSTR DatabaseName,
  109. IN BOOL bAdminLogon,
  110. IN DWORD ConfigOptions,
  111. IN AREA_INFORMATION Area
  112. );
  113. SCESTATUS
  114. ScepConfigureSystemAccess(
  115. IN PSCE_PROFILE_INFO pScpInfo,
  116. IN DWORD ConfigOptions,
  117. IN PSCE_ERROR_LOG_INFO *pErrLog,
  118. IN DWORD QueueFlag
  119. );
  120. NTSTATUS
  121. ScepManageAdminGuestAccounts(
  122. IN SAM_HANDLE DomainHandle,
  123. IN PWSTR NewName,
  124. IN DWORD ControlFlag,
  125. IN DWORD AccountType,
  126. IN DWORD ConfigOptions,
  127. IN PSCESECTION hSectionDomain,
  128. IN PSCESECTION hSectionTattoo
  129. );
  130. SCESTATUS
  131. ScepConfigurePrivileges(
  132. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
  133. IN BOOL bCreateBuiltinAccount,
  134. IN DWORD Options,
  135. IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
  136. );
  137. SCESTATUS
  138. ScepGetPrivilegeMask(
  139. IN PSCECONTEXT hProfile,
  140. IN SCETYPE ProfileType,
  141. OUT PDWORD pdLowMask,
  142. OUT PDWORD pdHighMask
  143. );
  144. DWORD
  145. ScepCreateBuiltinAccountInLsa(
  146. IN LSA_HANDLE PolicyHandle,
  147. IN LPTSTR AccountName,
  148. OUT PSID AccountSid
  149. );
  150. NTSTATUS
  151. ScepAdjustAccountPrivilegesRights(
  152. IN LSA_HANDLE PolicyHandle,
  153. IN PSID AccountSid,
  154. IN DWORD PrivilegeLowRights,
  155. IN DWORD PrivilegeLowMask,
  156. IN DWORD PrivilegeHighRights,
  157. IN DWORD PrivilegeHighMask,
  158. IN DWORD Options
  159. );
  160. NTSTATUS
  161. ScepAddOrRemoveAccountRights(
  162. IN LSA_HANDLE PolicyHandle,
  163. IN PSID AccountSid,
  164. IN BOOL AddOrRemove,
  165. IN DWORD PrivLowAdjust,
  166. IN DWORD PrivHighAdjust
  167. );
  168. NTSTATUS
  169. ScepValidateUserInGroups(
  170. IN SAM_HANDLE DomainHandle,
  171. IN SAM_HANDLE BuiltinDomainHandle,
  172. IN PSID DomainSid,
  173. IN UNICODE_STRING UserName,
  174. IN ULONG UserId,
  175. IN PSCE_NAME_LIST pGroupsToCheck
  176. );
  177. NTSTATUS
  178. ScepAddUserToGroup(
  179. IN SAM_HANDLE DomainHandle,
  180. IN SAM_HANDLE BuiltinDomainHandle,
  181. IN ULONG UserId,
  182. IN PSID AccountSid,
  183. IN PWSTR GroupName
  184. );
  185. SCESTATUS
  186. ScepConfigureGroupMembership(
  187. IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
  188. IN DWORD ConfigOptions
  189. );
  190. NTSTATUS
  191. ScepConfigureMembersOfGroup(
  192. IN PSCESECTION hSectionDomain,
  193. IN PSCESECTION hSectionTattoo,
  194. IN SAM_HANDLE DomainHandle,
  195. IN PSID ThisDomainSid,
  196. IN ULONG GrpId,
  197. IN PSID GrpSid,
  198. IN PWSTR GrpName,
  199. IN PWSTR GroupSidString,
  200. IN PSCE_NAME_LIST pMembers,
  201. IN DWORD ConfigOptions
  202. );
  203. NTSTATUS
  204. ScepConfigureMembersOfAlias(
  205. IN PSCESECTION hSectionDomain,
  206. IN PSCESECTION hSectionTattoo,
  207. IN SAM_HANDLE DomainHandle,
  208. IN PSID DomainSid,
  209. IN LSA_HANDLE PolicyHandle,
  210. IN ULONG GrpId,
  211. IN PSID GrpSid,
  212. IN PWSTR GrpName,
  213. IN PWSTR GroupSidString,
  214. IN PSCE_NAME_LIST pMembers,
  215. IN DWORD ConfigOptions
  216. );
  217. SCESTATUS
  218. ScepValidateGroupInAliases(
  219. IN SAM_HANDLE DomainHandle,
  220. IN SAM_HANDLE BuiltinDomainHandle,
  221. IN PSCESECTION hSectionTattoo,
  222. IN LSA_HANDLE PolicyHandle,
  223. IN PSID GrpSid,
  224. IN PSCE_NAME_LIST pAliasList,
  225. bool fProcessTattoo
  226. );
  227. SCESTATUS
  228. ScepConfigureObjectSecurity(
  229. IN PSCE_OBJECT_LIST pSecurityObject,
  230. IN AREA_INFORMATION Area,
  231. IN BOOL bPolicyProp,
  232. IN DWORD ConfigOptions
  233. );
  234. SCESTATUS
  235. ScepConfigureSystemAuditing(
  236. IN PSCE_PROFILE_INFO pScpInfo,
  237. IN DWORD ConfigOptions
  238. );
  239. SCESTATUS
  240. ScepConfigureAuditEvent(
  241. IN PSCE_PROFILE_INFO pScpInfo,
  242. IN PPOLICY_AUDIT_EVENTS_INFO auditEvent,
  243. IN DWORD Options,
  244. IN LSA_HANDLE PolicyHandle
  245. );
  246. SCESTATUS
  247. ScepConfigureDeInitialize(
  248. IN SCESTATUS rc,
  249. IN AREA_INFORMATION Area
  250. );
  251. SCESTATUS
  252. ScepMakePolicyIntoFile(
  253. IN DWORD Options,
  254. IN AREA_INFORMATION Area
  255. );
  256. DWORD
  257. ScepWriteOneAttributeToFile(
  258. IN LPCTSTR SectionName,
  259. IN LPCTSTR FileName,
  260. IN LPCTSTR KeyName,
  261. IN DWORD dwValue
  262. );
  263. SCESTATUS
  264. ScepCopyPrivilegesIntoFile(
  265. IN LPTSTR FileName,
  266. IN BOOL bInUpgrade
  267. );
  268. SCESTATUS
  269. ScepCopyPrivilegesFromDatabase(
  270. IN PSCESECTION hSection,
  271. IN PWSTR Keyname,
  272. IN DWORD StrLength,
  273. IN PWSTR StrValue OPTIONAL,
  274. OUT PWSTR *pOldValue,
  275. OUT DWORD *pOldLen
  276. );
  277. SCESTATUS
  278. ScepDeleteDomainPolicies();
  279. SCESTATUS
  280. ScepConfigurePrivilegesWithMask(
  281. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
  282. IN BOOL bCreateBuiltinAccount,
  283. IN DWORD Options,
  284. IN DWORD LowMask,
  285. IN DWORD HighMask,
  286. IN OUT PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
  287. IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
  288. );
  289. SCESTATUS
  290. ScepConfigurePrivilegesByRight(
  291. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivAssign,
  292. IN DWORD Options,
  293. IN OUT PSCE_ERROR_LOG_INFO *pErrLog
  294. );
  295. SCESTATUS
  296. ScepTattooUpdatePrivilegeArrayStatus(
  297. IN DWORD *pStatusArray,
  298. IN DWORD rc,
  299. IN DWORD PrivLowMask,
  300. IN DWORD PrivHighMask
  301. );
  302. SCESTATUS
  303. ScepTattooRemovePrivilegeValues(
  304. IN PSCECONTEXT hProfile,
  305. IN DWORD *pStatusArray
  306. );
  307. SCESTATUS
  308. ScepTattooSavePrivilegeValues(
  309. IN PSCECONTEXT hProfile,
  310. IN LSA_HANDLE PolicyHandle,
  311. IN DWORD PrivLowMask,
  312. IN DWORD PrivHighMask,
  313. IN DWORD ConfigOptions
  314. );
  315. DWORD
  316. ScepTattooCurrentGroupMembers(
  317. IN PSID ThisDomainSid,
  318. IN PSID GrpSid,
  319. IN SID_NAME_USE GrpUse,
  320. IN PULONG MemberRids OPTIONAL,
  321. IN PSID *MemberAliasSids OPTIONAL,
  322. IN DWORD MemberCount,
  323. OUT PSCE_NAME_LIST *ppNameList
  324. );
  325. VOID
  326. ScepBuildDwMaskFromStrArray(
  327. IN PUNICODE_STRING aUserRights,
  328. IN ULONG uCountOfRights,
  329. OUT DWORD *pdwPrivLowThisAccount,
  330. OUT DWORD *pdwPrivHighThisAccount
  331. );
  332. #define SCEP_REMOVE_PRIV_BIT(b,pl,ph) \
  333. if ( b < 32 ) { \
  334. *pl &= ~(1 << b); \
  335. } else if ( b >= 32 && b < 64 ) { \
  336. *ph &= ~( 1 << (b-32)); \
  337. }
  338. #define SCEP_ADD_PRIV_BIT(b,l,h) \
  339. if ( b < 32 ) { \
  340. l |= (1 << b); \
  341. } else if ( b >= 32 && b < 64 ) { \
  342. h |= ( 1 << (b-32)); \
  343. }
  344. #define SCEP_CHECK_PRIV_BIT(i,pl,ph) \
  345. ( (i < 32) && ( pl & (1 << i)) ) || \
  346. ( (i >= 32) && ( ph & ( 1 << (i-32)) ) )
  347. SCESTATUS
  348. ScepCheckNetworkLogonRights(
  349. IN LSA_HANDLE PolicyHandle,
  350. IN OUT DWORD *pLowMask,
  351. IN OUT DWORD *pHighMask,
  352. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned
  353. );
  354. SCESTATUS
  355. ScepAddAccountRightToList(
  356. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
  357. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppParent,
  358. IN INT idxRight,
  359. IN PSID AccountSid
  360. );
  361. SCESTATUS
  362. ScepConfigureLSAAnonymousLookup(
  363. IN PSCE_PROFILE_INFO pScpInfo,
  364. IN DWORD ConfigOptions,
  365. IN PSCE_ERROR_LOG_INFO *pErrLog
  366. );
  367. //
  368. // function implementations
  369. //
  370. SCESTATUS
  371. ScepConfigureSystem(
  372. IN PCWSTR InfFileName OPTIONAL,
  373. IN PWSTR DatabaseName,
  374. IN DWORD ConfigOptions,
  375. IN BOOL bAdminLogon,
  376. IN AREA_INFORMATION Area,
  377. OUT PDWORD pdWarning OPTIONAL
  378. )
  379. /*++
  380. Routine Description:
  381. This routine updates
  382. This routine is the exported API to configure a system by applying a SCP
  383. file (INF) to the system. I a INF template is provided, it is first parsed
  384. and saved in the SAD database. Then the system is configured using the info
  385. in the template.
  386. If any error occurs when loading SCP information, configuration will stop,
  387. and return the error code. If a error occurs when configure an area, it will
  388. stop configuring the whole area but continue to configure other left areas.
  389. All success and fail transactions will be logged to the logfile(or stdout).
  390. Log is already initialized before this call
  391. Arguments:
  392. InfFileName - The SCP file name
  393. DatabaseName - The file name of the JET (for future analysis) profile
  394. ConfigOptions - if the template provided is to update the system, or overwrite
  395. Area - one or more areas to configure.
  396. AREA_SECURITY_POLICY
  397. AREA_USER_SETTINGS // block out for beta1
  398. AREA_GROUP_MEMBERSHIP
  399. AREA_PRIVILEGES
  400. AREA_REGISTRY_SECURITY
  401. AREA_FILE_SECURITY
  402. AREA_SYSTEM_SERVICE
  403. pdWarning - the warning code
  404. Return value:
  405. SCESTATUS_SUCCESS
  406. SCESTATUS_NOT_ENOUGH_RESOURCE
  407. SCESTATUS_INVALID_PARAMETER
  408. SCESTATUS_ALREADY_RUNNING
  409. Status from ScepGetDatabaseInfo
  410. -- */
  411. {
  412. SCESTATUS rc, Saverc;
  413. SCESTATUS PendingRc=SCESTATUS_SUCCESS;
  414. PSCE_ERROR_LOG_INFO pErrlog=NULL;
  415. PPOLICY_AUDIT_EVENTS_INFO auditEvent=NULL;
  416. BOOL bAuditOff=FALSE;
  417. // PBYTE pFullAudit = NULL;
  418. PSCEP_SPLAY_TREE pNotifyAccounts=NULL;
  419. DWORD QueueFlag=0;
  420. Saverc = ScepConfigureInitialize(
  421. InfFileName,
  422. DatabaseName,
  423. bAdminLogon,
  424. ConfigOptions,
  425. Area );
  426. if ( Saverc != SCESTATUS_SUCCESS ) {
  427. ScepPostProgress(gTotalTicks, 0, NULL);
  428. ScepLogOutput3(0,0, SCEDLL_SCP_INIT_ERROR);
  429. } else if ( !(ConfigOptions & SCE_NO_CONFIG) ) {
  430. ScepLogOutput3(0,0, SCEDLL_SCP_INIT_SUCCESS);
  431. Area &= ~AREA_USER_SETTINGS;
  432. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  433. (ConfigOptions & SCE_NO_CONFIG_FILEKEY) ) {
  434. //
  435. // if within policy propagation (at reboot) and
  436. // this is the foreground thread, do not configure
  437. // file and registry sections. They will be configured
  438. // in background thread separately.
  439. //
  440. Area &= ~(AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY);
  441. }
  442. //
  443. // get information from the notification queue so that
  444. // pending notifications are ignored
  445. //
  446. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  447. ( (Area & AREA_PRIVILEGES) ||
  448. (Area & AREA_SECURITY_POLICY) ) ) {
  449. //
  450. // return error is ignored so policy prop will overwrite
  451. //
  452. __try {
  453. //
  454. // initialize the root TreeNode
  455. //
  456. if ( NULL == (pNotifyAccounts = ScepSplayInitialize(SplayNodeSidType)) ) {
  457. rc = ERROR_NOT_ENOUGH_MEMORY;
  458. ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_ERROR_SPLAY_INITIALIZE);
  459. } else if ( ERROR_SUCCESS != (rc=ScepGetQueueInfo(&QueueFlag, pNotifyAccounts)) ) {
  460. QueueFlag = 0;
  461. ScepLogOutput3(1,rc, SCESRV_POLICY_PENDING_QUERY);
  462. }
  463. } __except (EXCEPTION_EXECUTE_HANDLER) {
  464. QueueFlag = 0;
  465. rc = ERROR_IO_PENDING;
  466. ScepLogOutput3(1,rc, SCESRV_POLICY_PENDING_QUERY);
  467. }
  468. if ( ERROR_SUCCESS != rc ) {
  469. PendingRc = ScepDosErrorToSceStatus(rc);
  470. ScepPostProgress(gTotalTicks, 0, NULL);
  471. goto Done;
  472. }
  473. }
  474. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  475. //
  476. // always resume the queue processing after queue info is queried
  477. //
  478. ScepNotificationQControl(0);
  479. }
  480. ScepLogOutput3(0,0, SCEDLL_SCP_READ_PROFILE);
  481. Saverc = ScepGetDatabaseInfo(
  482. hProfile,
  483. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ?
  484. SCE_ENGINE_SCP_INTERNAL : SCE_ENGINE_SMP_INTERNAL,
  485. Area,
  486. SCE_ACCOUNT_SID,
  487. &pScpInfo,
  488. &pErrlog
  489. );
  490. ScepLogWriteError( pErrlog, 1 );
  491. ScepFreeErrorLog( pErrlog );
  492. pErrlog = NULL;
  493. if ( Saverc != SCESTATUS_SUCCESS ) {
  494. ScepPostProgress(gTotalTicks, 0, NULL);
  495. goto Done;
  496. }
  497. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  498. ScepIsSystemShutDown() ) {
  499. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  500. goto Done;
  501. }
  502. /* //
  503. // 462050 - should not turn off object access auditing to leave a
  504. // security hole on the system
  505. //
  506. // turn off object access auditing if file/key is to be configured
  507. // in system context.
  508. //
  509. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  510. ( (Area & AREA_FILE_SECURITY) && pScpInfo->pFiles.pOneLevel ) ||
  511. ( (Area & AREA_REGISTRY_SECURITY) && pScpInfo->pRegistryKeys.pOneLevel ) )
  512. bAuditOff = TRUE;
  513. //
  514. // if set, this regkey will decide to audit all
  515. //
  516. ScepRegQueryBinaryValue(
  517. HKEY_LOCAL_MACHINE,
  518. L"System\\CurrentControlSet\\Control\\Lsa",
  519. L"fullprivilegeauditing",
  520. &pFullAudit
  521. );
  522. if (pFullAudit) {
  523. if (*pFullAudit & (BYTE)1)
  524. bAuditOff = FALSE;
  525. ScepFree(pFullAudit);
  526. }
  527. */
  528. Saverc = ScepSaveAndOffAuditing(&auditEvent, bAuditOff, LsaPrivatePolicy);
  529. // if ( Saverc != SCESTATUS_SUCCESS )
  530. // goto Done;
  531. // if auditing can't be turned on for some reason, e.g., access denied for
  532. // normal user, just continue
  533. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  534. ScepIsSystemShutDown() ) {
  535. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  536. goto Done;
  537. }
  538. //
  539. // User Settings area
  540. //
  541. Saverc = 0;
  542. if ( Area & AREA_PRIVILEGES ) {
  543. ScepPostProgress(0, AREA_PRIVILEGES, NULL);
  544. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_PRIVILEGES);
  545. rc = ScepConfigurePrivileges( &(pScpInfo->OtherInfo.scp.u.pPrivilegeAssignedTo),
  546. (ConfigOptions & SCE_CREATE_BUILTIN_ACCOUNTS),
  547. (bAdminLogon ?
  548. ConfigOptions :
  549. (ConfigOptions & ~SCE_SYSTEM_DB)),
  550. (QueueFlag & SCE_QUEUE_INFO_RIGHTS) ? pNotifyAccounts : NULL
  551. );
  552. if( rc != SCESTATUS_SUCCESS ) {
  553. if ( rc != SCESTATUS_PENDING_IGNORE )
  554. Saverc = rc;
  555. else
  556. PendingRc = rc;
  557. ScepLogOutput3(0,0, SCEDLL_SCP_PRIVILEGES_ERROR);
  558. } else {
  559. ScepLogOutput3(0,0, SCEDLL_SCP_PRIVILEGES_SUCCESS);
  560. }
  561. }
  562. if ( pNotifyAccounts ) {
  563. ScepSplayFreeTree(&pNotifyAccounts, TRUE);
  564. }
  565. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  566. ScepIsSystemShutDown() ) {
  567. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  568. goto Done;
  569. }
  570. //
  571. // Group Membership area
  572. //
  573. if ( Area & AREA_GROUP_MEMBERSHIP) {
  574. ScepPostProgress(0, AREA_GROUP_MEMBERSHIP, NULL);
  575. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_GROUPMGMT);
  576. #if _WIN32_WINNT>=0x0500
  577. // need to support nested groups
  578. if ( ProductType == NtProductLanManNt ) {
  579. rc = ScepConfigDsGroups( pScpInfo->pGroupMembership, ConfigOptions );
  580. //
  581. // some groups (such as local groups) may not be configured in DS
  582. // so try it in SAM
  583. //
  584. SCESTATUS rc2 = ScepConfigureGroupMembership(pScpInfo->pGroupMembership, ConfigOptions );
  585. if ( rc2 != SCESTATUS_SUCCESS )
  586. rc = rc2;
  587. } else {
  588. #endif
  589. rc = ScepConfigureGroupMembership( pScpInfo->pGroupMembership, ConfigOptions );
  590. #if _WIN32_WINNT>=0x0500
  591. }
  592. #endif
  593. if ( rc != SCESTATUS_SUCCESS) {
  594. Saverc = rc;
  595. ScepLogOutput3(0,0, SCEDLL_SCP_GROUPMGMT_ERROR);
  596. } else {
  597. ScepLogOutput3(0,0, SCEDLL_SCP_GROUPMGMT_SUCCESS);
  598. }
  599. }
  600. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  601. ScepIsSystemShutDown() ) {
  602. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  603. goto Done;
  604. }
  605. //
  606. // Registry Security area
  607. //
  608. if ( Area & AREA_REGISTRY_SECURITY ) {
  609. ScepPostProgress(0,
  610. AREA_REGISTRY_SECURITY,
  611. NULL);
  612. //
  613. // Disable reflector on ia64 systems
  614. //
  615. #ifdef _WIN64
  616. Wow64Win32ApiEntry (1, 1, 0);
  617. #endif
  618. rc = ScepConfigureObjectSecurity( pScpInfo->pRegistryKeys.pOneLevel,
  619. AREA_REGISTRY_SECURITY,
  620. (ConfigOptions & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
  621. ConfigOptions
  622. );
  623. //
  624. // Enable reflector on ia64 systems
  625. //
  626. #ifdef _WIN64
  627. Wow64Win32ApiEntry (1, 2, 0);
  628. #endif
  629. if( rc != SCESTATUS_SUCCESS ) {
  630. Saverc = rc;
  631. }
  632. }
  633. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  634. ScepIsSystemShutDown() ) {
  635. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  636. goto Done;
  637. }
  638. //
  639. // File Security area
  640. //
  641. if ( Area & AREA_FILE_SECURITY ) {
  642. ScepPostProgress(0,
  643. AREA_FILE_SECURITY,
  644. NULL);
  645. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_FILE);
  646. rc = ScepConfigureObjectSecurity( pScpInfo->pFiles.pOneLevel,
  647. AREA_FILE_SECURITY,
  648. (ConfigOptions & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
  649. ConfigOptions
  650. );
  651. if( rc != SCESTATUS_SUCCESS ) {
  652. Saverc = rc;
  653. ScepLogOutput3(0,0, SCEDLL_SCP_FILE_ERROR);
  654. } else {
  655. ScepLogOutput3(0,0, SCEDLL_SCP_FILE_SUCCESS);
  656. }
  657. }
  658. #if 0
  659. #if _WIN32_WINNT>=0x0500
  660. if ( (ProductType == NtProductLanManNt) && (Area & AREA_DS_OBJECTS) ) {
  661. ScepPostProgress(0,
  662. AREA_DS_OBJECTS,
  663. NULL);
  664. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_DS);
  665. rc = ScepConfigureObjectSecurity( pScpInfo->pDsObjects.pOneLevel,
  666. AREA_DS_OBJECTS,
  667. (ConfigOptions & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
  668. ConfigOptions
  669. );
  670. if( rc != SCESTATUS_SUCCESS ) {
  671. Saverc = rc;
  672. ScepLogOutput3(0,0, SCEDLL_SCP_DS_ERROR);
  673. } else {
  674. ScepLogOutput3(0,0, SCEDLL_SCP_DS_SUCCESS);
  675. }
  676. }
  677. #endif
  678. #endif
  679. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  680. ScepIsSystemShutDown() ) {
  681. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  682. goto Done;
  683. }
  684. //
  685. // System Service area
  686. //
  687. if ( Area & AREA_SYSTEM_SERVICE ) {
  688. ScepPostProgress(0,
  689. AREA_SYSTEM_SERVICE,
  690. NULL);
  691. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_GENERALSVC);
  692. rc = ScepConfigureGeneralServices( hProfile, pScpInfo->pServices, ConfigOptions );
  693. if( rc != SCESTATUS_SUCCESS ) {
  694. Saverc = rc;
  695. ScepLogOutput3(0,0, SCEDLL_SCP_GENERALSVC_ERROR);
  696. } else {
  697. ScepLogOutput3(0,0, SCEDLL_SCP_GENERALSVC_SUCCESS);
  698. }
  699. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_ATTACHMENT);
  700. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  701. ScepIsSystemShutDown() ) {
  702. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  703. } else {
  704. rc = ScepInvokeSpecificServices( hProfile, TRUE, SCE_ATTACHMENT_SERVICE );
  705. }
  706. if( rc != SCESTATUS_SUCCESS ) {
  707. Saverc = rc;
  708. ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_ERROR);
  709. } else {
  710. ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_SUCCESS);
  711. }
  712. }
  713. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  714. ScepIsSystemShutDown() ) {
  715. Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
  716. goto Done;
  717. }
  718. //
  719. // Security policy
  720. //
  721. if ( Area & AREA_SECURITY_POLICY ) {
  722. ScepPostProgress(0,
  723. AREA_SECURITY_POLICY,
  724. NULL);
  725. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_POLICY);
  726. if ( !( ConfigOptions & SCE_NO_DOMAIN_POLICY ||
  727. ConfigOptions & SCE_POLICY_TEMPLATE &&
  728. gMachineRole == DsRole_RoleBackupDomainController) ) {
  729. rc = ScepConfigureSystemAccess( pScpInfo, ConfigOptions, NULL, QueueFlag );
  730. if( rc != SCESTATUS_SUCCESS ) {
  731. if ( rc != SCESTATUS_PENDING_IGNORE )
  732. Saverc = rc;
  733. else
  734. PendingRc = rc;
  735. ScepLogOutput3(0,0, SCEDLL_SCP_ACCESS_ERROR);
  736. } else {
  737. ScepLogOutput3(0,0, SCEDLL_SCP_ACCESS_SUCCESS);
  738. }
  739. }
  740. rc = ScepConfigureLSAAnonymousLookup( pScpInfo, ConfigOptions, NULL );
  741. if( rc != SCESTATUS_SUCCESS ) {
  742. Saverc = rc;
  743. }
  744. ScepPostProgress(TICKS_SYSTEM_ACCESS,
  745. AREA_SECURITY_POLICY,
  746. (LPTSTR)szSystemAccess);
  747. //
  748. // System Auditing area
  749. //
  750. rc = ScepConfigureSystemAuditing( pScpInfo, ConfigOptions );
  751. if ( rc == SCESTATUS_SUCCESS && NULL != auditEvent ) {
  752. //
  753. // not in policy prop or
  754. // no pending notify for audit
  755. //
  756. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  757. (QueueFlag & SCE_QUEUE_INFO_AUDIT) ) {
  758. rc = ERROR_IO_PENDING;
  759. ScepLogOutput3(0, 0, SCESRV_POLICY_PENDING_AUDIT);
  760. if (ConfigOptions & SCE_RSOP_CALLBACK)
  761. ScepRsopLog(SCE_RSOP_AUDIT_EVENT_INFO, rc, NULL,0,0);
  762. rc = ScepDosErrorToSceStatus(rc);
  763. } else {
  764. rc = ScepConfigureAuditEvent(pScpInfo,
  765. auditEvent,
  766. bAdminLogon ?
  767. ConfigOptions :
  768. (ConfigOptions & ~SCE_SYSTEM_DB),
  769. LsaPrivatePolicy
  770. );
  771. }
  772. }
  773. if( rc != SCESTATUS_SUCCESS ) {
  774. if ( rc != SCESTATUS_PENDING_IGNORE )
  775. Saverc = rc;
  776. else
  777. PendingRc = rc;
  778. ScepLogOutput3(0,0, SCEDLL_SCP_AUDIT_ERROR);
  779. } else {
  780. ScepLogOutput3(0,0, SCEDLL_SCP_AUDIT_SUCCESS);
  781. }
  782. ScepPostProgress(TICKS_SYSTEM_AUDITING,
  783. AREA_SECURITY_POLICY,
  784. (LPTSTR)szAuditEvent);
  785. #if _WIN32_WINNT>=0x0500
  786. if ( ProductType == NtProductLanManNt &&
  787. !(ConfigOptions & SCE_NO_DOMAIN_POLICY ) ) {
  788. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  789. ScepIsSystemShutDown() ) {
  790. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  791. } else {
  792. //
  793. // Kerberos Policy
  794. //
  795. rc = ScepConfigureKerberosPolicy( hProfile,
  796. pScpInfo->pKerberosInfo,
  797. ConfigOptions );
  798. }
  799. if( rc != SCESTATUS_SUCCESS ) {
  800. Saverc = rc;
  801. ScepLogOutput3(0,0, SCEDLL_SCP_KERBEROS_ERROR);
  802. } else {
  803. ScepLogOutput3(0,0, SCEDLL_SCP_KERBEROS_SUCCESS);
  804. }
  805. }
  806. #endif
  807. ScepPostProgress(TICKS_KERBEROS,
  808. AREA_SECURITY_POLICY,
  809. (LPTSTR)szKerberosPolicy);
  810. //
  811. // registry values
  812. //
  813. rc = ScepConfigureRegistryValues( hProfile,
  814. pScpInfo->aRegValues,
  815. pScpInfo->RegValueCount,
  816. NULL,
  817. ConfigOptions,
  818. NULL );
  819. if( rc != SCESTATUS_SUCCESS ) {
  820. Saverc = rc;
  821. ScepLogOutput3(0,0, SCEDLL_SCP_REGVALUES_ERROR);
  822. } else {
  823. ScepLogOutput3(0,0, SCEDLL_SCP_REGVALUES_SUCCESS);
  824. }
  825. ScepPostProgress(TICKS_REGISTRY_VALUES,
  826. AREA_SECURITY_POLICY,
  827. (LPTSTR)szRegistryValues);
  828. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_ATTACHMENT);
  829. //
  830. // implemented in service.cpp
  831. //
  832. rc = ScepInvokeSpecificServices( hProfile, TRUE, SCE_ATTACHMENT_POLICY );
  833. if( rc != SCESTATUS_SUCCESS ) {
  834. Saverc = rc;
  835. ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_ERROR);
  836. } else {
  837. ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_SUCCESS);
  838. }
  839. }
  840. }
  841. Done:
  842. if ( pNotifyAccounts ) {
  843. ScepSplayFreeTree(&pNotifyAccounts, TRUE);
  844. }
  845. if ( NULL != auditEvent ) {
  846. if ( bAuditOff && auditEvent->AuditingMode ) {
  847. rc = ScepRestoreAuditing(auditEvent, LsaPrivatePolicy);
  848. }
  849. LsaFreeMemory(auditEvent);
  850. }
  851. ScepLogOutput3(0,0, SCEDLL_SCP_UNINIT);
  852. if ( pdWarning ) {
  853. *pdWarning = gWarningCode;
  854. }
  855. //
  856. // return failure if invalid data is found in the template
  857. //
  858. if ( gbInvalidData ) {
  859. Saverc = SCESTATUS_INVALID_DATA;
  860. }
  861. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  862. !(ConfigOptions & SCE_NO_CONFIG) ) {
  863. //
  864. // always resume the queue processing after configuration is done
  865. //
  866. ScepNotificationQControl(0);
  867. }
  868. if ( Saverc == SCESTATUS_SUCCESS ) Saverc = PendingRc;
  869. ScepConfigureDeInitialize( Saverc, Area);
  870. return(Saverc);
  871. }
  872. SCESTATUS
  873. ScepConfigureInitialize(
  874. IN PCWSTR InfFileName OPTIONAL,
  875. IN PWSTR DatabaseName,
  876. IN BOOL bAdminLogon,
  877. IN DWORD ConfigOptions,
  878. IN AREA_INFORMATION Area
  879. )
  880. /* ++
  881. Routine Description:
  882. This routine initializes the SCP engine.
  883. Arguments:
  884. InfFileName - The file name of a SCP file used to configure the sytem
  885. DatabaseName - The JET (for future analysis) profile name
  886. ConfigOptions - If the template is to update the system instead of overwriting
  887. Area - security area to initialize
  888. Return value:
  889. SCESTATUS_SUCCESS
  890. SCESTATUS_INVALID_PARAMETER
  891. SCESTATUS_PROFILE_NOT_FOUND
  892. SCESTATUS_NOT_ENOUGH_RESOURCE
  893. SCESTATUS_ALREADY_RUNNING
  894. -- */
  895. {
  896. SCESTATUS rc=SCESTATUS_SUCCESS;
  897. PCHAR FileName=NULL;
  898. DWORD MBLen=0;
  899. NTSTATUS NtStatus;
  900. LARGE_INTEGER CurrentTime;
  901. PSCE_ERROR_LOG_INFO Errlog=NULL;
  902. PSECURITY_DESCRIPTOR pSD=NULL;
  903. SECURITY_INFORMATION SeInfo;
  904. DWORD SDsize;
  905. DWORD DbNameLen;
  906. HKEY hCurrentUser=NULL;
  907. //
  908. // thread variables are not guaranteed to be initialized to NULL
  909. //
  910. hProfile = NULL;
  911. //
  912. // database name can't be NULL because it's already resolved
  913. //
  914. if ( !DatabaseName ) {
  915. return(SCESTATUS_INVALID_PARAMETER);
  916. }
  917. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  918. ScepIsSystemShutDown() ) {
  919. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  920. }
  921. //
  922. // get other system values
  923. //
  924. if ( RtlGetNtProductType (&ProductType) == FALSE ) {
  925. rc = ScepDosErrorToSceStatus(GetLastError());
  926. goto Leave;
  927. }
  928. rc = ScepGetDomainRoleInfo(&gMachineRole, NULL, NULL);
  929. if ( ERROR_SUCCESS != rc)
  930. goto Leave;
  931. //
  932. // Initialize globals
  933. //
  934. gTotalTicks = 0;
  935. gCurrentTicks = 0;
  936. gWarningCode = 0;
  937. gbInvalidData = FALSE;
  938. //
  939. // Initialize engine buffer
  940. //
  941. cbClientFlag = (BYTE)( ConfigOptions & (SCE_CALLBACK_DELTA |
  942. SCE_CALLBACK_TOTAL ));
  943. pScpInfo = (PSCE_PROFILE_INFO)&scpBuffer;
  944. pScpInfo->Type = SCE_ENGINE_SCP_INTERNAL;
  945. //
  946. // convert WCHAR into ANSI
  947. //
  948. DbNameLen = wcslen(DatabaseName);
  949. NtStatus = RtlUnicodeToMultiByteSize(&MBLen, DatabaseName, DbNameLen*sizeof(WCHAR));
  950. if ( !NT_SUCCESS(NtStatus) ) {
  951. //
  952. // cannot get the length, set default to 512
  953. //
  954. MBLen = 512;
  955. }
  956. FileName = (PCHAR)ScepAlloc(LPTR, MBLen+2);
  957. if ( FileName == NULL ) {
  958. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  959. goto Leave;
  960. }
  961. NtStatus = RtlUnicodeToMultiByteN(
  962. FileName,
  963. MBLen+1,
  964. NULL,
  965. DatabaseName,
  966. DbNameLen*sizeof(WCHAR)
  967. );
  968. if ( !NT_SUCCESS(NtStatus) ) {
  969. rc = RtlNtStatusToDosError(NtStatus);
  970. ScepLogOutput3(1, rc, SCEDLL_ERROR_PROCESS_UNICODE, DatabaseName );
  971. rc = ScepDosErrorToSceStatus(rc);
  972. goto Leave;
  973. }
  974. if ( RegOpenCurrentUser(
  975. KEY_READ | KEY_WRITE,
  976. &hCurrentUser
  977. ) != ERROR_SUCCESS ) {
  978. hCurrentUser = NULL;
  979. }
  980. if ( hCurrentUser == NULL ) {
  981. hCurrentUser = HKEY_CURRENT_USER;
  982. }
  983. //
  984. // delay registry filter (into database) is not needed anymore
  985. //
  986. if ( InfFileName != NULL ) { // || InfHandle != NULL ) {
  987. //
  988. // convert inf to jet
  989. //
  990. ScepLogOutput3(3, 0, SCEDLL_PROCESS_TEMPLATE, (PWSTR)InfFileName );
  991. if ( bAdminLogon ) {
  992. //
  993. // make sure the directories exist for the file
  994. //
  995. rc = ConvertTextSecurityDescriptor (
  996. L"D:P(A;CIOI;GA;;;CO)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
  997. &pSD,
  998. &SDsize,
  999. &SeInfo
  1000. );
  1001. if ( rc != NO_ERROR )
  1002. ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, DatabaseName );
  1003. }
  1004. //
  1005. // change revision to ACL_REVISION2 (from 4) because it's for files
  1006. //
  1007. ScepChangeAclRevision(pSD, ACL_REVISION);
  1008. ScepCreateDirectory(
  1009. DatabaseName,
  1010. FALSE, // a file name
  1011. pSD //NULL // take parent's security setting
  1012. );
  1013. if ( pSD ) {
  1014. ScepFree(pSD);
  1015. }
  1016. if ( ConfigOptions & SCE_OVERWRITE_DB ) {
  1017. //
  1018. // only delete existing jet files if jet engine is not running
  1019. // because other threads may use the same version storage
  1020. // for other database.
  1021. //
  1022. // if jet engine is not running, delete version storage files
  1023. // will not force a recovery because overwrite db option means
  1024. // overwrite all previous info in the database.
  1025. //
  1026. SceJetDeleteJetFiles(DatabaseName);
  1027. }
  1028. //
  1029. // copy the inf sections and data to the jet database SCP table
  1030. //
  1031. if ( InfFileName != NULL ) {
  1032. SCEJET_CREATE_TYPE TmpOption;
  1033. if ( ConfigOptions & SCE_UPDATE_DB ) {
  1034. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  1035. TmpOption = SCEJET_OPEN_DUP;
  1036. } else {
  1037. TmpOption = SCEJET_OPEN_DUP_EXCLUSIVE;
  1038. }
  1039. } else {
  1040. TmpOption = SCEJET_OVERWRITE_DUP;
  1041. }
  1042. rc = SceJetConvertInfToJet(
  1043. InfFileName,
  1044. (LPSTR)FileName,
  1045. TmpOption,
  1046. bAdminLogon ? ConfigOptions : (ConfigOptions & ~SCE_SYSTEM_DB),
  1047. Area
  1048. );
  1049. }
  1050. if ( rc != SCESTATUS_SUCCESS ) { // SCESTATUS error code
  1051. goto Leave;
  1052. }
  1053. } else if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1054. (ConfigOptions & SCE_POLICY_FIRST) &&
  1055. (ConfigOptions & SCE_POLICY_LAST) ) {
  1056. //
  1057. // a policy refresh without any domain GPOs, do the local GPO only
  1058. //
  1059. rc = SceJetOpenFile(
  1060. (LPSTR)FileName,
  1061. SCEJET_OPEN_READ_WRITE, // SCEJET_OPEN_EXCLUSIVE,
  1062. SCE_TABLE_OPTION_MERGE_POLICY | SCE_TABLE_OPTION_TATTOO,
  1063. &hProfile
  1064. );
  1065. if ( SCESTATUS_SUCCESS == rc ) {
  1066. rc = ScepDeleteInfoForAreas(
  1067. hProfile,
  1068. SCE_ENGINE_SCP,
  1069. AREA_ALL
  1070. );
  1071. if ( ( rc == SCESTATUS_SUCCESS ) ||
  1072. ( rc == SCESTATUS_RECORD_NOT_FOUND ) ) {
  1073. //
  1074. // delete GPO table to start over
  1075. //
  1076. SceJetDeleteAll( hProfile,
  1077. "SmTblGpo",
  1078. SCEJET_TABLE_GPO
  1079. );
  1080. //
  1081. // copy local table
  1082. //
  1083. ScepLogOutput3(2, rc, SCEDLL_COPY_LOCAL);
  1084. rc = ScepCopyLocalToMergeTable( hProfile, ConfigOptions,
  1085. (ProductType == NtProductLanManNt) ? SCE_LOCAL_POLICY_DC : 0,
  1086. &Errlog );
  1087. ScepLogWriteError( Errlog,1 );
  1088. ScepFreeErrorLog( Errlog );
  1089. Errlog = NULL;
  1090. if ( rc == SCESTATUS_SUCCESS ) {
  1091. DWORD dwThisTable = hProfile->Type & 0xF0L;
  1092. if ( SCEJET_MERGE_TABLE_1 == dwThisTable ||
  1093. SCEJET_MERGE_TABLE_2 == dwThisTable ) {
  1094. rc = SceJetSetValueInVersion(
  1095. hProfile,
  1096. "SmTblVersion",
  1097. "LastUsedMergeTable",
  1098. (PWSTR)&dwThisTable,
  1099. 4,
  1100. JET_prepReplace
  1101. );
  1102. }
  1103. } else {
  1104. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1105. SCEDLL_ERROR_COPY);
  1106. }
  1107. } else {
  1108. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1109. SCEDLL_ERROR_DELETE, L"SCP");
  1110. }
  1111. } else {
  1112. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1113. SCEDLL_ERROR_OPEN, DatabaseName );
  1114. }
  1115. if ( rc != SCESTATUS_SUCCESS ) { // SCESTATUS error code
  1116. goto Leave;
  1117. }
  1118. }
  1119. //
  1120. // set the default profile into Reg
  1121. //
  1122. rc = ScepRegSetValue(
  1123. bAdminLogon ? HKEY_LOCAL_MACHINE : hCurrentUser,
  1124. SCE_ROOT_PATH,
  1125. L"LastUsedDatabase",
  1126. REG_SZ,
  1127. (BYTE *)DatabaseName,
  1128. (DbNameLen + 1) *sizeof(WCHAR)
  1129. );
  1130. if ( rc != NO_ERROR ) // Win32 error code
  1131. ScepLogOutput3(1, rc, SCEDLL_ERROR_SAVE_REGISTRY, L"LastUsedDatabase");
  1132. if ( InfFileName != NULL ) {
  1133. if ( bAdminLogon ) {
  1134. //
  1135. // only save the value if it's not coming from policy prop
  1136. //
  1137. if ( !(ConfigOptions & SCE_POLICY_TEMPLATE) ) {
  1138. rc = ScepRegSetValue(
  1139. HKEY_LOCAL_MACHINE,
  1140. SCE_ROOT_PATH,
  1141. L"TemplateUsed",
  1142. REG_SZ,
  1143. (BYTE *)InfFileName,
  1144. wcslen(InfFileName)*sizeof(WCHAR)
  1145. );
  1146. } else {
  1147. rc = NO_ERROR;
  1148. }
  1149. } else {
  1150. rc = ScepRegSetValue(
  1151. hCurrentUser, // HKEY_CURRENT_USER
  1152. SCE_ROOT_PATH,
  1153. L"TemplateUsed",
  1154. REG_SZ,
  1155. (BYTE *)InfFileName,
  1156. wcslen(InfFileName)*sizeof(WCHAR)
  1157. );
  1158. }
  1159. if ( rc != NO_ERROR ) // Win32 error code
  1160. ScepLogOutput3(1, rc, SCEDLL_ERROR_SAVE_REGISTRY, L"TemplateUsed");
  1161. }
  1162. //
  1163. // if no configuration is requested, just return now.
  1164. //
  1165. if ( ConfigOptions & SCE_NO_CONFIG ) {
  1166. if ( !(ConfigOptions & SCE_COPY_LOCAL_POLICY) ) {
  1167. //
  1168. // if no policy template is requested
  1169. //
  1170. goto Leave;
  1171. }
  1172. }
  1173. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1174. ScepIsSystemShutDown() ) {
  1175. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  1176. goto Leave;
  1177. }
  1178. //
  1179. // open the database now to create some tables and time stamp
  1180. // tattoo is not needed unless it's in policy propagation
  1181. //
  1182. rc = SceJetOpenFile(
  1183. (LPSTR)FileName,
  1184. ( ConfigOptions & (SCE_POLICY_TEMPLATE | SCE_COPY_LOCAL_POLICY) ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
  1185. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0,
  1186. &hProfile
  1187. );
  1188. if ( rc != SCESTATUS_SUCCESS ) {
  1189. //
  1190. // sleep for some time and try open again
  1191. //
  1192. Sleep(2000); // 2 seconds
  1193. rc = SceJetOpenFile(
  1194. (LPSTR)FileName,
  1195. ( ConfigOptions & (SCE_POLICY_TEMPLATE | SCE_COPY_LOCAL_POLICY) ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
  1196. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0,
  1197. &hProfile
  1198. );
  1199. if ( rc != SCESTATUS_SUCCESS ) {
  1200. Sleep(2000); // 2 seconds
  1201. rc = SceJetOpenFile(
  1202. (LPSTR)FileName,
  1203. ( ConfigOptions & (SCE_POLICY_TEMPLATE | SCE_COPY_LOCAL_POLICY) ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
  1204. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0,
  1205. &hProfile
  1206. );
  1207. }
  1208. }
  1209. if ( rc != SCESTATUS_SUCCESS ) {
  1210. ScepLogOutput3(0, ScepSceStatusToDosError(rc),
  1211. SCEDLL_ERROR_OPEN,
  1212. DatabaseName );
  1213. goto Leave;
  1214. }
  1215. SceJetStartTransaction( hProfile );
  1216. if ( ConfigOptions & SCE_COPY_LOCAL_POLICY ) {
  1217. //
  1218. // Copy domain policies (password, account, kerberos) to the special
  1219. // file %windir%\security\FirstDGPO.inf. The info in database will be
  1220. // deleted
  1221. //
  1222. //
  1223. // copy local policies (audit, and user rights) to the special file
  1224. // %windir%\security\FirstOGPO.inf. The local policy info in the
  1225. // database will still be left in.
  1226. //
  1227. rc = ScepMakePolicyIntoFile( ConfigOptions, Area);
  1228. if ( rc != SCESTATUS_SUCCESS) {
  1229. SceJetRollback( hProfile, 0 );
  1230. goto Leave;
  1231. }
  1232. }
  1233. if ( (hProfile->JetSapID != JET_tableidNil) &&
  1234. !(ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1235. !(ConfigOptions & SCE_COPY_LOCAL_POLICY) &&
  1236. ((ConfigOptions & SCE_NO_CONFIG) == 0) ) {
  1237. //
  1238. // analysis was performed before
  1239. // delete SAP info for the area
  1240. //
  1241. ScepLogOutput3(3,0, SCEDLL_DELETE_TABLE, L"SAP");
  1242. // bug 362120
  1243. // after each config, user must re-analyze the computer to get
  1244. // analysis information
  1245. //
  1246. // if ( (ConfigOptions & SCE_OVERWRITE_DB) &&
  1247. // (InfFileName != NULL /*|| InfHandle != NULL */) ) {
  1248. //
  1249. // if it's reconfigured with a new template, all SAP
  1250. // information is obselote, so delete the whole table
  1251. //
  1252. rc = SceJetDeleteTable(
  1253. hProfile,
  1254. "SmTblSap",
  1255. SCEJET_TABLE_SAP
  1256. );
  1257. /*
  1258. } else {
  1259. //
  1260. // the template is incremental, or use the original template
  1261. // just delete sap information for the area, assuming that
  1262. // everything in the area is matched after this configuration
  1263. //
  1264. rc = ScepDeleteInfoForAreas(
  1265. hProfile,
  1266. SCE_ENGINE_SAP,
  1267. Area
  1268. );
  1269. }
  1270. */
  1271. if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND ) {
  1272. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1273. SCEDLL_ERROR_DELETE, L"SAP");
  1274. SceJetRollback( hProfile, 0 );
  1275. goto Leave;
  1276. }
  1277. }
  1278. //
  1279. // set time stamp for this configuration
  1280. //
  1281. if ( (ConfigOptions & SCE_NO_CONFIG) == 0 ) {
  1282. NtStatus = NtQuerySystemTime(&CurrentTime);
  1283. if ( NT_SUCCESS(NtStatus) ) {
  1284. rc = SceJetSetTimeStamp(
  1285. hProfile,
  1286. FALSE,
  1287. CurrentTime
  1288. );
  1289. if ( rc != SCESTATUS_SUCCESS )
  1290. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1291. SCEDLL_TIMESTAMP_ERROR,L"SMP");
  1292. // do not care the status of this call
  1293. rc = SCESTATUS_SUCCESS;
  1294. } else
  1295. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  1296. SCEDLL_TIMESTAMP_ERROR, L"SMP");
  1297. }
  1298. //
  1299. // commit all changes to this database
  1300. // fatal errors won't get here
  1301. //
  1302. SceJetCommitTransaction( hProfile, 0 );
  1303. //
  1304. // now if NO_CONFIG is requested ( with MOVE_POLICY or COPY_POLICY flag )
  1305. // should return now
  1306. //
  1307. if ( ConfigOptions & SCE_NO_CONFIG ) {
  1308. goto Leave;
  1309. }
  1310. //
  1311. // close the exclusively opened database and
  1312. // open it for read only because config engine read from the database
  1313. // NOTE: SceJetOpenFile will close the previous database if the handle
  1314. // is not NULL. The SceJetCloseFile is called with (theHandle,FALSE,FALSE)
  1315. // so jet session and instance are not terminated
  1316. //
  1317. rc = SceJetOpenFile(
  1318. (LPSTR)FileName,
  1319. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_READ_ONLY, // tattoo table will be updated in policy
  1320. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0, // by now the LastUsedMergeTable field is already set
  1321. &hProfile
  1322. );
  1323. if ( rc != SCESTATUS_SUCCESS ) { // SCESTATUS
  1324. ScepLogOutput3(0, ScepSceStatusToDosError(rc),
  1325. SCEDLL_ERROR_OPEN,
  1326. DatabaseName );
  1327. goto Leave;
  1328. }
  1329. //
  1330. // query the total ticks of this configuration
  1331. //
  1332. rc = ScepGetTotalTicks(
  1333. NULL,
  1334. hProfile,
  1335. Area,
  1336. ( ConfigOptions & SCE_POLICY_TEMPLATE ) ?
  1337. SCE_FLAG_CONFIG_SCP : SCE_FLAG_CONFIG,
  1338. &gTotalTicks
  1339. );
  1340. if ( SCESTATUS_SUCCESS != rc &&
  1341. SCESTATUS_RECORD_NOT_FOUND != rc ) {
  1342. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1343. SCEDLL_TOTAL_TICKS_ERROR);
  1344. }
  1345. rc = SCESTATUS_SUCCESS;
  1346. //
  1347. // reset memory buffer
  1348. //
  1349. memset( pScpInfo, '\0',sizeof(SCE_PROFILE_INFO) );
  1350. pScpInfo->Type = SCE_ENGINE_SCP_INTERNAL;
  1351. //
  1352. // open LSA private policy handle (to block other downlevel changes)
  1353. //
  1354. if ( ( ConfigOptions & SCE_POLICY_TEMPLATE ) &&
  1355. !( ConfigOptions & SCE_NO_CONFIG) &&
  1356. ( (Area & AREA_PRIVILEGES) ||
  1357. (Area & AREA_SECURITY_POLICY) ) ) {
  1358. //
  1359. // enable TCB privilege
  1360. //
  1361. SceAdjustPrivilege( SE_TCB_PRIVILEGE, TRUE, NULL );
  1362. LSA_OBJECT_ATTRIBUTES attributes;
  1363. SECURITY_QUALITY_OF_SERVICE service;
  1364. memset( &attributes, 0, sizeof(attributes) );
  1365. attributes.Length = sizeof(attributes);
  1366. attributes.SecurityQualityOfService = &service;
  1367. service.Length = sizeof(service);
  1368. service.ImpersonationLevel= SecurityImpersonation;
  1369. service.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  1370. service.EffectiveOnly = TRUE;
  1371. //
  1372. // open the lsa policy first
  1373. //
  1374. NtStatus = LsaOpenPolicySce( // LsaOpenPolicySce
  1375. NULL,
  1376. &attributes,
  1377. MAXIMUM_ALLOWED,
  1378. &LsaPrivatePolicy
  1379. );
  1380. if ( !NT_SUCCESS(NtStatus) || NtStatus == STATUS_TIMEOUT) {
  1381. if ( STATUS_TIMEOUT == NtStatus ) {
  1382. rc = ERROR_TIMEOUT;
  1383. } else
  1384. rc = RtlNtStatusToDosError(NtStatus);
  1385. LsaPrivatePolicy = NULL;
  1386. ScepLogOutput3(1, rc, SCESRV_ERROR_PRIVATE_LSA );
  1387. rc = ScepDosErrorToSceStatus(rc);
  1388. } else {
  1389. ScepNotifyLogPolicy(0, TRUE, L"Policy Prop: Private LSA handle is returned", 0, 0, NULL );
  1390. }
  1391. }
  1392. Leave:
  1393. if ( hCurrentUser && hCurrentUser != HKEY_CURRENT_USER ) {
  1394. RegCloseKey(hCurrentUser);
  1395. }
  1396. if ( FileName ) {
  1397. ScepFree(FileName);
  1398. }
  1399. return(rc);
  1400. }
  1401. /* ANZ hotfix
  1402. requery notification queue for SAM notification items only
  1403. in case another notification slithered-in between the
  1404. previous LSA+SAM query and now
  1405. no need to hard error-out (but log an error) if querying fails since we're only
  1406. trying to raise the bar (or reduce the "notification dropping" window)
  1407. */
  1408. /*
  1409. */
  1410. #define SCEP_DISALLOW_SAM_FILTER\
  1411. if (!ResetEvent(ghEventSamFilterAndPolicyPropExclusion)){\
  1412. rc = GetLastError();\
  1413. SaveStat = rc;\
  1414. ScepLogOutput3(1,rc, SCESRV_POLICY_SAM_RESET_FILTER_SYNC);\
  1415. /* hard error - otherwise policy prop SAM config -> SAM notification loop might occur */\
  1416. DbgPrint("\nTid =%d PP could not Lock event due to %d\n", GetCurrentThreadId(), rc);\
  1417. goto OtherSettings;\
  1418. }\
  1419. else {\
  1420. DbgPrint("\nTid=%d Policy Propagation Locked event \n", GetCurrentThreadId());\
  1421. }\
  1422. if ( !(QueueFlag & SCE_QUEUE_INFO_SAM) ) {\
  1423. (VOID)ScepGetQueueInfo(&QueueFlag, NULL);\
  1424. }\
  1425. if ((QueueFlag & SCE_QUEUE_INFO_SAM)) {\
  1426. ScepLogOutput3(0, 0, SCESRV_POLICY_NEW_PENDING_SAM);\
  1427. rc = ERROR_IO_PENDING;\
  1428. PendingRc = rc;\
  1429. SCEP_ALLOW_SAM_FILTER\
  1430. goto OtherSettings;\
  1431. }
  1432. #define SCEP_ALLOW_SAM_FILTER\
  1433. if (!SetEvent(ghEventSamFilterAndPolicyPropExclusion)) {\
  1434. rc = GetLastError();\
  1435. SaveStat = rc;\
  1436. bSetEventFailed = TRUE;\
  1437. ScepLogOutput3(1,rc, SCESRV_POLICY_SAM_SET_FILTER_SYNC);\
  1438. /* hard error - otherwise SAM notifications will start getting dropped from now on */\
  1439. DbgPrint("\nTid =%d PP could not Unlock event due to %d\n", GetCurrentThreadId(), rc);\
  1440. }\
  1441. else {\
  1442. DbgPrint("\nTid =%d PP Unlocked event \n", GetCurrentThreadId());\
  1443. }\
  1444. SCESTATUS
  1445. ScepConfigureSystemAccess(
  1446. IN PSCE_PROFILE_INFO pScpInfo,
  1447. IN DWORD ConfigOptions,
  1448. IN PSCE_ERROR_LOG_INFO *pErrLog,
  1449. IN DWORD QueueFlag
  1450. )
  1451. /* ++
  1452. Routine Description:
  1453. This routine configure the system security in the area of system access
  1454. which includes account policy, rename admin/guest accounts, disable
  1455. no activity account, and some registry keys security, e.g., winlogon keys.
  1456. Arguments:
  1457. pScpInfo - The buffer which contains SCP info loaded from the profile
  1458. ConfigOptions - options in configuration
  1459. pErrLog - the output log for potential errors
  1460. QueueFlag - flags for the notification queue, which determines if SAM policy
  1461. should be configured.
  1462. Return value:
  1463. SCESTATUS_SUCCESS
  1464. SCESTATUS_NOT_ENOUGH_RESOURCE
  1465. SCESTATUS_INVALID_PARAMETER
  1466. SCESTATUS_OTHER_ERROR
  1467. -- */
  1468. {
  1469. DWORD rc,PendingRc=0;
  1470. DWORD SaveStat;
  1471. NTSTATUS NtStatus;
  1472. SAM_HANDLE DomainHandle=NULL,
  1473. ServerHandle=NULL,
  1474. UserHandle1=NULL;
  1475. PSID DomainSid=NULL;
  1476. PVOID Buffer=NULL;
  1477. DWORD RegData;
  1478. BOOL bFlagSet;
  1479. BOOL bSetEventFailed = FALSE;
  1480. SCE_TATTOO_KEYS *pTattooKeys=NULL;
  1481. DWORD cTattooKeys=0;
  1482. PSCESECTION hSectionDomain=NULL;
  1483. PSCESECTION hSectionTattoo=NULL;
  1484. #define MAX_PASS_KEYS 7
  1485. #define MAX_LOCKOUT_KEYS 3
  1486. //
  1487. // Open account domain
  1488. //
  1489. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1490. ScepIsSystemShutDown() ) {
  1491. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  1492. }
  1493. NtStatus = ScepOpenSamDomain(
  1494. MAXIMUM_ALLOWED, // SAM_SERVER_ALL_ACCESS,
  1495. DOMAIN_WRITE_PASSWORD_PARAMS | MAXIMUM_ALLOWED,
  1496. &ServerHandle,
  1497. &DomainHandle,
  1498. &DomainSid,
  1499. NULL,
  1500. NULL
  1501. );
  1502. rc = RtlNtStatusToDosError( NtStatus );
  1503. SaveStat = rc;
  1504. if (!NT_SUCCESS(NtStatus)) {
  1505. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  1506. pErrLog ) {
  1507. ScepBuildErrorLogInfo(
  1508. rc,
  1509. pErrLog,
  1510. SCEDLL_ACCOUNT_DOMAIN
  1511. );
  1512. } else {
  1513. ScepLogOutput3(1, rc, SCEDLL_ACCOUNT_DOMAIN);
  1514. }
  1515. if (ConfigOptions & SCE_RSOP_CALLBACK)
  1516. ScepRsopLog(SCE_RSOP_PASSWORD_INFO |
  1517. SCE_RSOP_LOCKOUT_INFO |
  1518. SCE_RSOP_LOGOFF_INFO |
  1519. SCE_RSOP_ADMIN_INFO |
  1520. SCE_RSOP_GUEST_INFO,
  1521. rc,
  1522. NULL,
  1523. 0,
  1524. 0);
  1525. return( ScepDosErrorToSceStatus(rc) );
  1526. }
  1527. //
  1528. // if this is policy propagation, we need to open the sections for
  1529. // updating undo settings if this is not domain controller
  1530. // *** on DCs, domain account policy can't be reset'ed to tattoo
  1531. // on each individual DC. So there is no point to query/save tattoo values
  1532. //
  1533. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1534. ( ProductType != NtProductLanManNt ) ) {
  1535. ScepTattooOpenPolicySections(
  1536. hProfile,
  1537. szSystemAccess,
  1538. &hSectionDomain,
  1539. &hSectionTattoo
  1540. );
  1541. }
  1542. //
  1543. // if there is pending notifications for SAM policy
  1544. // ignore policy prop for SAM
  1545. //
  1546. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1547. (QueueFlag & SCE_QUEUE_INFO_SAM) ) {
  1548. ScepLogOutput3(0, 0, SCESRV_POLICY_PENDING_SAM);
  1549. rc = ERROR_IO_PENDING;
  1550. PendingRc = rc;
  1551. if (ConfigOptions & SCE_RSOP_CALLBACK)
  1552. ScepRsopLog(SCE_RSOP_PASSWORD_INFO |
  1553. SCE_RSOP_LOCKOUT_INFO |
  1554. SCE_RSOP_LOGOFF_INFO,
  1555. rc,
  1556. NULL,
  1557. 0,
  1558. 0);
  1559. goto OtherSettings;
  1560. }
  1561. //
  1562. // Get the current password settings...
  1563. //
  1564. Buffer=NULL;
  1565. NtStatus = SamQueryInformationDomain(
  1566. DomainHandle,
  1567. DomainPasswordInformation,
  1568. &Buffer
  1569. );
  1570. rc = RtlNtStatusToDosError( NtStatus );
  1571. if ( NT_SUCCESS(NtStatus) ) {
  1572. rc = ERROR_SUCCESS;
  1573. // allocate buffer for the tattoo values if necessary
  1574. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1575. ( ProductType != NtProductLanManNt ) ) {
  1576. pTattooKeys = (SCE_TATTOO_KEYS *)ScepAlloc(LPTR,MAX_PASS_KEYS*sizeof(SCE_TATTOO_KEYS));
  1577. if ( !pTattooKeys ) {
  1578. ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_TATTOO_ERROR_CREATE);
  1579. }
  1580. }
  1581. bFlagSet = FALSE;
  1582. if ( (pScpInfo->MinimumPasswordLength != SCE_NO_VALUE) ) {
  1583. //
  1584. // for domain controllers, always use hardcode value as the initial tattoo value
  1585. //
  1586. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1587. (PWSTR)L"MinimumPasswordLength", ConfigOptions,
  1588. (ProductType == NtProductLanManNt) ? SCEDCPOL_MIN_PASS_LEN :
  1589. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength);
  1590. if ( ((USHORT)(pScpInfo->MinimumPasswordLength) != ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength) ) {
  1591. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength = (USHORT)(pScpInfo->MinimumPasswordLength);
  1592. bFlagSet = TRUE;
  1593. }
  1594. }
  1595. if ( (pScpInfo->PasswordHistorySize != SCE_NO_VALUE) ) {
  1596. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1597. (PWSTR)L"PasswordHistorySize", ConfigOptions,
  1598. (ProductType == NtProductLanManNt) ? SCEDCPOL_PASS_SIZE : ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength);
  1599. if ( ((USHORT)(pScpInfo->PasswordHistorySize) != ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength ) ) {
  1600. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength = (USHORT)(pScpInfo->PasswordHistorySize);
  1601. bFlagSet = TRUE;
  1602. }
  1603. }
  1604. if ( pScpInfo->MaximumPasswordAge == SCE_FOREVER_VALUE ) {
  1605. RegData = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart /
  1606. (LONGLONG)(10000000L)) );
  1607. RegData /= 3600;
  1608. RegData /= 24;
  1609. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1610. (PWSTR)L"MaximumPasswordAge", ConfigOptions,
  1611. (ProductType == NtProductLanManNt) ? SCEDCPOL_MAX_PASS_AGE : RegData);
  1612. if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.HighPart != MINLONG ||
  1613. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.LowPart != 0 ) {
  1614. //
  1615. // Maximum LARGE_INTEGER .ie. never
  1616. //
  1617. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.HighPart = MINLONG;
  1618. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.LowPart = 0;
  1619. bFlagSet = TRUE;
  1620. }
  1621. } else if ( pScpInfo->MaximumPasswordAge != SCE_NO_VALUE ) {
  1622. RegData = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart /
  1623. (LONGLONG)(10000000L)) );
  1624. RegData /= 3600;
  1625. RegData /= 24;
  1626. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1627. (PWSTR)L"MaximumPasswordAge", ConfigOptions,
  1628. (ProductType == NtProductLanManNt) ? SCEDCPOL_MAX_PASS_AGE : RegData);
  1629. if ( RegData != pScpInfo->MaximumPasswordAge ) {
  1630. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart = -1 *
  1631. (LONGLONG)pScpInfo->MaximumPasswordAge*24*3600 * 10000000L;
  1632. bFlagSet = TRUE;
  1633. }
  1634. }
  1635. if ( pScpInfo->MinimumPasswordAge != SCE_NO_VALUE ) {
  1636. RegData = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordAge.QuadPart /
  1637. (LONGLONG)(10000000L)) );
  1638. RegData /= 3600;
  1639. RegData /= 24;
  1640. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1641. (PWSTR)L"MinimumPasswordAge", ConfigOptions,
  1642. (ProductType == NtProductLanManNt) ? SCEDCPOL_MIN_PASS_AGE : RegData);
  1643. if ( RegData != pScpInfo->MinimumPasswordAge ) {
  1644. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordAge.QuadPart = -1 *
  1645. (LONGLONG)pScpInfo->MinimumPasswordAge*24*3600 * 10000000L;
  1646. bFlagSet = TRUE;
  1647. }
  1648. }
  1649. if ( pScpInfo->PasswordComplexity != SCE_NO_VALUE ) {
  1650. RegData = ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties & DOMAIN_PASSWORD_COMPLEX) ? 1 : 0;
  1651. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1652. (PWSTR)L"PasswordComplexity", ConfigOptions,
  1653. (ProductType == NtProductLanManNt) ? SCEDCPOL_PASS_COMP : RegData);
  1654. if ( pScpInfo->PasswordComplexity != RegData ) {
  1655. if ( RegData == 0 )
  1656. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties |= DOMAIN_PASSWORD_COMPLEX;
  1657. else
  1658. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &= ~DOMAIN_PASSWORD_COMPLEX;
  1659. bFlagSet = TRUE;
  1660. }
  1661. }
  1662. if ( pScpInfo->RequireLogonToChangePassword != SCE_NO_VALUE ) {
  1663. RegData = ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties & DOMAIN_PASSWORD_NO_ANON_CHANGE) ? 1 : 0;
  1664. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1665. (PWSTR)L"RequireLogonToChangePassword", ConfigOptions,
  1666. (ProductType == NtProductLanManNt) ? SCEDCPOL_REQUIRE_LOGON : RegData);
  1667. if ( pScpInfo->RequireLogonToChangePassword != RegData ) {
  1668. if ( RegData == 0 )
  1669. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties |= DOMAIN_PASSWORD_NO_ANON_CHANGE;
  1670. else
  1671. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &= ~DOMAIN_PASSWORD_NO_ANON_CHANGE;
  1672. bFlagSet = TRUE;
  1673. }
  1674. }
  1675. #if _WIN32_WINNT>=0x0500
  1676. if ( pScpInfo->ClearTextPassword != SCE_NO_VALUE ) {
  1677. RegData = ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) ? 1 : 0;
  1678. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1679. (PWSTR)L"ClearTextPassword", ConfigOptions,
  1680. (ProductType == NtProductLanManNt) ? SCEDCPOL_CLEAR_PASS : RegData);
  1681. if ( pScpInfo->ClearTextPassword != RegData ) {
  1682. if ( RegData == 0 )
  1683. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties |= DOMAIN_PASSWORD_STORE_CLEARTEXT;
  1684. else
  1685. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &= ~DOMAIN_PASSWORD_STORE_CLEARTEXT;
  1686. bFlagSet = TRUE;
  1687. }
  1688. }
  1689. #endif
  1690. if ( bFlagSet ) {
  1691. //
  1692. // if there is pending notifications for SAM policy
  1693. // ignore policy prop for SAM
  1694. //
  1695. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1696. (ProductType == NtProductLanManNt) ) {
  1697. // ANZ hotfix
  1698. //
  1699. // turn off policy filter for SAM notification JUST before SAM config
  1700. // (moved here to reduce "SAM notification dropping" window)
  1701. //
  1702. SCEP_DISALLOW_SAM_FILTER
  1703. }
  1704. NtStatus = SamSetInformationDomain(
  1705. DomainHandle,
  1706. DomainPasswordInformation,
  1707. Buffer
  1708. );
  1709. rc = RtlNtStatusToDosError( NtStatus );
  1710. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1711. (ProductType == NtProductLanManNt) ) {
  1712. // ANZ hotfix
  1713. //
  1714. // turn on policy filter for SAM notification (moved here
  1715. // to reduce "SAM notification dropping" window)
  1716. //
  1717. SCEP_ALLOW_SAM_FILTER
  1718. }
  1719. }
  1720. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1721. ( ProductType != NtProductLanManNt ) &&
  1722. pTattooKeys && cTattooKeys ) {
  1723. //
  1724. // even if there is no change,
  1725. // we still need to check if some tattoo values should be deleted
  1726. //
  1727. ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_ARRAY, cTattooKeys);
  1728. //
  1729. // some policy is different than the system setting
  1730. // check if we should save the existing setting as the tattoo value
  1731. // also remove reset'ed tattoo policy
  1732. //
  1733. ScepTattooManageValues(hSectionDomain, hSectionTattoo, pTattooKeys, cTattooKeys, rc);
  1734. }
  1735. if ( pTattooKeys ) {
  1736. ScepFree(pTattooKeys);
  1737. pTattooKeys = NULL;
  1738. }
  1739. cTattooKeys = 0;
  1740. SamFreeMemory(Buffer);
  1741. Buffer = NULL;
  1742. if ( !NT_SUCCESS( NtStatus ) ) {
  1743. //
  1744. // if error, just log it and continue
  1745. //
  1746. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  1747. ScepBuildErrorLogInfo(
  1748. rc,
  1749. pErrLog,
  1750. SCEDLL_SCP_ERROR_PASSWORD
  1751. );
  1752. } else {
  1753. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_PASSWORD);
  1754. }
  1755. SaveStat = rc;
  1756. // goto GETOUT;
  1757. } else {
  1758. ScepLogOutput3(1, rc, SCEDLL_SCP_PASSWORD);
  1759. }
  1760. } else if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  1761. ScepBuildErrorLogInfo(
  1762. rc,
  1763. pErrLog,
  1764. SCEDLL_ERROR_QUERY_PASSWORD
  1765. );
  1766. } else {
  1767. ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_PASSWORD);
  1768. }
  1769. if (ConfigOptions & SCE_RSOP_CALLBACK)
  1770. ScepRsopLog(SCE_RSOP_PASSWORD_INFO, rc, NULL, 0, 0);
  1771. //
  1772. // Configure Lockout information
  1773. //
  1774. Buffer = NULL;
  1775. NtStatus = SamQueryInformationDomain(
  1776. DomainHandle,
  1777. DomainLockoutInformation,
  1778. &Buffer
  1779. );
  1780. rc = RtlNtStatusToDosError( NtStatus );
  1781. if ( NT_SUCCESS(NtStatus) ) {
  1782. rc = ERROR_SUCCESS;
  1783. // allocate buffer for the tattoo values if necessary
  1784. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1785. ( ProductType != NtProductLanManNt ) ) {
  1786. pTattooKeys = (SCE_TATTOO_KEYS *)ScepAlloc(LPTR,MAX_LOCKOUT_KEYS*sizeof(SCE_TATTOO_KEYS));
  1787. if ( !pTattooKeys ) {
  1788. ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_TATTOO_ERROR_CREATE);
  1789. }
  1790. }
  1791. bFlagSet = FALSE;
  1792. if ( (pScpInfo->LockoutBadCount != SCE_NO_VALUE) ) {
  1793. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1794. (PWSTR)L"LockoutBadCount", ConfigOptions,
  1795. (ProductType == NtProductLanManNt) ? SCEDCPOL_LOCK_COUNT : ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold);
  1796. if ( ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold != (USHORT)(pScpInfo->LockoutBadCount) ) ) {
  1797. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold = (USHORT)(pScpInfo->LockoutBadCount);
  1798. bFlagSet = TRUE;
  1799. }
  1800. }
  1801. if ( (pScpInfo->ResetLockoutCount != SCE_NO_VALUE) &&
  1802. ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold > 0 ) ) {
  1803. RegData = (DWORD) (-1 * ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutObservationWindow.QuadPart /
  1804. (60 * 10000000L) );
  1805. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1806. (PWSTR)L"ResetLockoutCount", ConfigOptions,
  1807. (ProductType == NtProductLanManNt) ? SCEDCPOL_LOCK_RESET : RegData);
  1808. if ( RegData != pScpInfo->ResetLockoutCount ) {
  1809. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutObservationWindow.QuadPart = -1 *
  1810. (LONGLONG)pScpInfo->ResetLockoutCount * 60 * 10000000L;
  1811. bFlagSet = TRUE;
  1812. }
  1813. }
  1814. if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold > 0 ) {
  1815. if ( pScpInfo->LockoutDuration != SCE_NO_VALUE ) {
  1816. RegData = (DWORD)(-1 * ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.QuadPart /
  1817. (60 * 10000000L) );
  1818. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1819. (PWSTR)L"LockoutDuration", ConfigOptions,
  1820. (ProductType == NtProductLanManNt) ? SCEDCPOL_LOCK_DURATION : RegData);
  1821. }
  1822. if ( pScpInfo->LockoutDuration == SCE_FOREVER_VALUE ) {
  1823. if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.HighPart != MINLONG ||
  1824. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.LowPart != 0 ) {
  1825. //
  1826. // forever
  1827. //
  1828. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.HighPart = MINLONG;
  1829. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.LowPart = 0;
  1830. bFlagSet = TRUE;
  1831. }
  1832. } else if ( pScpInfo->LockoutDuration != SCE_NO_VALUE ) {
  1833. if ( RegData != pScpInfo->LockoutDuration ) {
  1834. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.QuadPart = -1 *
  1835. (LONGLONG)pScpInfo->LockoutDuration * 60 * 10000000L;
  1836. bFlagSet = TRUE;
  1837. }
  1838. }
  1839. } else {
  1840. //
  1841. // make sure to delete these two tattoo values if they exist
  1842. //
  1843. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1844. (PWSTR)L"ResetLockoutCount", ConfigOptions,
  1845. SCE_NO_VALUE);
  1846. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  1847. (PWSTR)L"LockoutDuration", ConfigOptions,
  1848. SCE_NO_VALUE);
  1849. }
  1850. if ( bFlagSet ) {
  1851. //
  1852. // if there is pending notifications for SAM policy
  1853. // ignore policy prop for SAM
  1854. //
  1855. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1856. (ProductType == NtProductLanManNt) ) {
  1857. // ANZ hotfix
  1858. //
  1859. // turn off policy filter for SAM notification JUST before SAM config
  1860. // (moved here to reduce "SAM notification dropping" window)
  1861. //
  1862. SCEP_DISALLOW_SAM_FILTER
  1863. }
  1864. NtStatus = SamSetInformationDomain(
  1865. DomainHandle,
  1866. DomainLockoutInformation,
  1867. Buffer
  1868. );
  1869. rc = RtlNtStatusToDosError( NtStatus );
  1870. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1871. (ProductType == NtProductLanManNt) ) {
  1872. // ANZ hotfix
  1873. //
  1874. // turn on policy filter for SAM notification (moved here
  1875. // to reduce "SAM notification dropping" window)
  1876. //
  1877. SCEP_ALLOW_SAM_FILTER
  1878. }
  1879. }
  1880. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1881. ( ProductType != NtProductLanManNt ) &&
  1882. pTattooKeys && cTattooKeys ) {
  1883. //
  1884. // even if there is no change
  1885. // we still need to check if some of the tattoo values should be deleted
  1886. //
  1887. ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_ARRAY, cTattooKeys);
  1888. //
  1889. // some policy is different than the system setting
  1890. // check if we should save the existing setting as the tattoo value
  1891. // also remove reset'ed tattoo policy
  1892. //
  1893. ScepTattooManageValues(hSectionDomain, hSectionTattoo, pTattooKeys, cTattooKeys, rc);
  1894. }
  1895. if ( pTattooKeys ) {
  1896. ScepFree(pTattooKeys);
  1897. pTattooKeys = NULL;
  1898. }
  1899. cTattooKeys = 0;
  1900. SamFreeMemory(Buffer);
  1901. Buffer = NULL;
  1902. if ( !NT_SUCCESS( NtStatus ) ) {
  1903. //
  1904. // if error, just log it and continue
  1905. //
  1906. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  1907. ScepBuildErrorLogInfo(
  1908. rc,
  1909. pErrLog,
  1910. SCEDLL_SCP_ERROR_PASSWORD
  1911. );
  1912. } else {
  1913. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LOCKOUT);
  1914. }
  1915. SaveStat = rc;
  1916. // goto GETOUT;
  1917. } else if ( bFlagSet ) {
  1918. ScepLogOutput3(1, rc, SCEDLL_SCP_LOCKOUT);
  1919. }
  1920. } else if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  1921. ScepBuildErrorLogInfo(
  1922. rc,
  1923. pErrLog,
  1924. SCEDLL_ERROR_QUERY_LOCKOUT
  1925. );
  1926. } else {
  1927. ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_LOCKOUT);
  1928. }
  1929. if (ConfigOptions & SCE_RSOP_CALLBACK)
  1930. ScepRsopLog(SCE_RSOP_LOCKOUT_INFO, rc, NULL, 0, 0);
  1931. //
  1932. // Force Logoff when hour expire
  1933. //
  1934. if ( pScpInfo->ForceLogoffWhenHourExpire != SCE_NO_VALUE ) {
  1935. Buffer = NULL;
  1936. NtStatus = SamQueryInformationDomain(
  1937. DomainHandle,
  1938. DomainLogoffInformation,
  1939. &Buffer
  1940. );
  1941. rc = RtlNtStatusToDosError( NtStatus );
  1942. if ( NT_SUCCESS(NtStatus) ) {
  1943. rc = ERROR_SUCCESS;
  1944. bFlagSet = FALSE;
  1945. RegData = pScpInfo->ForceLogoffWhenHourExpire;
  1946. if ( pScpInfo->ForceLogoffWhenHourExpire == 1 ) { // yes
  1947. if ( ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart != 0 ||
  1948. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart != 0 ) {
  1949. RegData = 0;
  1950. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart = 0;
  1951. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart = 0;
  1952. bFlagSet = TRUE;
  1953. }
  1954. } else {
  1955. if ( ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart != MINLONG ||
  1956. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart != 0 ) {
  1957. RegData = 1;
  1958. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart = MINLONG;
  1959. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart = 0;
  1960. bFlagSet = TRUE;
  1961. }
  1962. }
  1963. if ( bFlagSet ) {
  1964. //
  1965. // if there is pending notifications for SAM policy
  1966. // ignore policy prop for SAM
  1967. //
  1968. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1969. (ProductType == NtProductLanManNt) ) {
  1970. // ANZ hotfix
  1971. //
  1972. // turn off policy filter for SAM notification JUST before SAM config
  1973. // (moved here to reduce "SAM notification dropping" window)
  1974. //
  1975. SCEP_DISALLOW_SAM_FILTER
  1976. }
  1977. NtStatus = SamSetInformationDomain(
  1978. DomainHandle,
  1979. DomainLogoffInformation,
  1980. Buffer
  1981. );
  1982. rc = RtlNtStatusToDosError( NtStatus );
  1983. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1984. (ProductType == NtProductLanManNt) ) {
  1985. // ANZ hotfix
  1986. //
  1987. // turn on policy filter for SAM notification (moved here
  1988. // to reduce "SAM notification dropping" window)
  1989. //
  1990. SCEP_ALLOW_SAM_FILTER
  1991. }
  1992. }
  1993. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  1994. ( ProductType != NtProductLanManNt ) ) {
  1995. //
  1996. // some policy is different than the system setting or this is a domain controller
  1997. // check if we should save the existing setting as the tattoo value
  1998. // also remove reset'ed tattoo policy
  1999. //
  2000. ScepTattooManageOneIntValue(hSectionDomain, hSectionTattoo,
  2001. (PWSTR)L"ForceLogoffWhenHourExpire",
  2002. 0,
  2003. (ProductType == NtProductLanManNt) ? SCEDCPOL_FORCE_LOGOFF : RegData, rc);
  2004. }
  2005. SamFreeMemory(Buffer);
  2006. Buffer = NULL;
  2007. if ( !NT_SUCCESS( NtStatus ) ) {
  2008. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  2009. pErrLog ) {
  2010. ScepBuildErrorLogInfo(
  2011. rc,
  2012. pErrLog,
  2013. SCEDLL_SCP_ERROR_LOGOFF
  2014. );
  2015. } else {
  2016. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LOGOFF);
  2017. }
  2018. SaveStat = rc;
  2019. // goto GETOUT;
  2020. } else {
  2021. ScepLogOutput3(1, rc, SCEDLL_SCP_LOGOFF);
  2022. }
  2023. } else if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  2024. ScepBuildErrorLogInfo(
  2025. rc,
  2026. pErrLog,
  2027. SCEDLL_ERROR_QUERY_LOGOFF
  2028. );
  2029. } else {
  2030. ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_LOGOFF);
  2031. }
  2032. if (ConfigOptions & SCE_RSOP_CALLBACK)
  2033. ScepRsopLog(SCE_RSOP_LOGOFF_INFO, rc, NULL, 0, 0);
  2034. }
  2035. OtherSettings:
  2036. if (Buffer != NULL){
  2037. SamFreeMemory(Buffer);
  2038. Buffer = NULL;
  2039. }
  2040. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  2041. ScepIsSystemShutDown() ) {
  2042. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  2043. SaveStat = rc;
  2044. } else {
  2045. //
  2046. // Rename Administrator/Guest account
  2047. //
  2048. if ( NULL != pScpInfo->NewAdministratorName ) {
  2049. NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
  2050. pScpInfo->NewAdministratorName,
  2051. 0,
  2052. SCE_RENAME_ADMIN,
  2053. ConfigOptions,
  2054. hSectionDomain,
  2055. hSectionTattoo
  2056. );
  2057. rc = RtlNtStatusToDosError(NtStatus);
  2058. if ( NT_SUCCESS( NtStatus ) )
  2059. ScepLogOutput3(0, 0, SCEDLL_SCP_RENAME_ADMIN,
  2060. pScpInfo->NewAdministratorName );
  2061. else {
  2062. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  2063. pErrLog ) {
  2064. ScepBuildErrorLogInfo(
  2065. rc,
  2066. pErrLog,
  2067. SCEDLL_SCP_ERROR_ADMINISTRATOR
  2068. );
  2069. } else {
  2070. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_ADMINISTRATOR);
  2071. }
  2072. SaveStat = rc;
  2073. // goto GETOUT;
  2074. }
  2075. if (ConfigOptions & SCE_RSOP_CALLBACK)
  2076. ScepRsopLog(SCE_RSOP_ADMIN_INFO, rc, NULL, 0, 0);
  2077. }
  2078. if ( NULL != pScpInfo->NewGuestName ) {
  2079. NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
  2080. pScpInfo->NewGuestName,
  2081. 0,
  2082. SCE_RENAME_GUEST,
  2083. ConfigOptions,
  2084. hSectionDomain,
  2085. hSectionTattoo
  2086. );
  2087. rc = RtlNtStatusToDosError(NtStatus);
  2088. if ( NT_SUCCESS( NtStatus ) ) {
  2089. ScepLogOutput3(0,0, SCEDLL_SCP_RENAME_GUEST,
  2090. pScpInfo->NewGuestName );
  2091. } else {
  2092. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  2093. pErrLog ) {
  2094. ScepBuildErrorLogInfo(
  2095. rc,
  2096. pErrLog,
  2097. SCEDLL_SCP_ERROR_GUEST
  2098. );
  2099. } else {
  2100. ScepLogOutput3(1,rc, SCEDLL_SCP_ERROR_GUEST);
  2101. }
  2102. SaveStat = rc;
  2103. // goto GETOUT;
  2104. }
  2105. if (ConfigOptions & SCE_RSOP_CALLBACK)
  2106. ScepRsopLog(SCE_RSOP_GUEST_INFO, rc, NULL, 0, 0);
  2107. }
  2108. //
  2109. // disable admin account
  2110. //
  2111. if ( pScpInfo->EnableAdminAccount != SCE_NO_VALUE ) {
  2112. NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
  2113. NULL,
  2114. (pScpInfo->EnableAdminAccount > 0) ? 0 : 1,
  2115. SCE_DISABLE_ADMIN,
  2116. ConfigOptions,
  2117. hSectionDomain,
  2118. hSectionTattoo
  2119. );
  2120. rc = RtlNtStatusToDosError(NtStatus);
  2121. if ( NT_SUCCESS( NtStatus ) ) {
  2122. ScepLogOutput3(0, 0, pScpInfo->EnableAdminAccount ?
  2123. SCEDLL_SCP_ENABLE_ADMIN : SCEDLL_SCP_DISABLE_ADMIN);
  2124. } else {
  2125. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  2126. pErrLog ) {
  2127. ScepBuildErrorLogInfo(
  2128. rc,
  2129. pErrLog,
  2130. SCEDLL_SCP_ERROR_DISABLE_ADMIN
  2131. );
  2132. } else if ( STATUS_SPECIAL_ACCOUNT == NtStatus ) {
  2133. ScepLogOutput3(0, 0, SCEDLL_SCP_ADMIN_NOT_ALLOWED);
  2134. } else {
  2135. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_DISABLE_ADMIN);
  2136. }
  2137. SaveStat = rc;
  2138. // goto GETOUT;
  2139. }
  2140. if (ConfigOptions & SCE_RSOP_CALLBACK)
  2141. ScepRsopLog(SCE_RSOP_DISABLE_ADMIN_INFO, rc, NULL, 0, 0);
  2142. }
  2143. //
  2144. // disable guest account
  2145. //
  2146. if ( pScpInfo->EnableGuestAccount != SCE_NO_VALUE ) {
  2147. NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
  2148. NULL,
  2149. (pScpInfo->EnableGuestAccount > 0) ? 0 : 1,
  2150. SCE_DISABLE_GUEST,
  2151. ConfigOptions,
  2152. hSectionDomain,
  2153. hSectionTattoo
  2154. );
  2155. rc = RtlNtStatusToDosError(NtStatus);
  2156. if ( NT_SUCCESS( NtStatus ) ) {
  2157. ScepLogOutput3(0, 0, pScpInfo->EnableGuestAccount ?
  2158. SCEDLL_SCP_ENABLE_GUEST : SCEDLL_SCP_DISABLE_GUEST);
  2159. } else {
  2160. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  2161. pErrLog ) {
  2162. ScepBuildErrorLogInfo(
  2163. rc,
  2164. pErrLog,
  2165. SCEDLL_SCP_ERROR_DISABLE_GUEST
  2166. );
  2167. } else if ( STATUS_SPECIAL_ACCOUNT == NtStatus ) {
  2168. ScepLogOutput3(0, 0, SCEDLL_SCP_GUEST_NOT_ALLOWED);
  2169. } else {
  2170. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_DISABLE_GUEST);
  2171. }
  2172. SaveStat = rc;
  2173. // goto GETOUT;
  2174. }
  2175. if (ConfigOptions & SCE_RSOP_CALLBACK)
  2176. ScepRsopLog(SCE_RSOP_DISABLE_GUEST_INFO, rc, NULL, 0, 0);
  2177. }
  2178. }
  2179. //
  2180. // Other Registry Key Values
  2181. //
  2182. bFlagSet = FALSE;
  2183. if ( bFlagSet && rc == NO_ERROR )
  2184. ScepLogOutput3(1, rc, SCEDLL_SCP_OTHER_POLICY);
  2185. if ( hSectionDomain ) SceJetCloseSection( &hSectionDomain, TRUE );
  2186. if ( hSectionTattoo ) SceJetCloseSection( &hSectionTattoo, TRUE );
  2187. //
  2188. // Clear out memory and return
  2189. //
  2190. SamCloseHandle( DomainHandle );
  2191. SamCloseHandle( ServerHandle );
  2192. if ( DomainSid != NULL )
  2193. SamFreeMemory(DomainSid);
  2194. if ( SaveStat == ERROR_SUCCESS )
  2195. SaveStat = PendingRc;
  2196. // ANZ hotfix
  2197. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  2198. TRUE == bSetEventFailed) {
  2199. //
  2200. // set this event just in case it failed before
  2201. //
  2202. SetEvent(ghEventSamFilterAndPolicyPropExclusion);
  2203. }
  2204. return(ScepDosErrorToSceStatus(SaveStat));
  2205. }
  2206. NTSTATUS
  2207. ScepManageAdminGuestAccounts(
  2208. IN SAM_HANDLE DomainHandle,
  2209. IN PWSTR NewName,
  2210. IN DWORD DisableFlag,
  2211. IN DWORD AccountType,
  2212. IN DWORD ConfigOptions,
  2213. IN PSCESECTION hSectionDomain OPTIONAL,
  2214. IN PSCESECTION hSectionTattoo OPTIONAL
  2215. )
  2216. /* ++
  2217. Routine Description:
  2218. This routine renames the specified account's name to the new account name
  2219. in the account domain.
  2220. Arguments:
  2221. DomainHandle - The account domain handle
  2222. NewName - New account name to rename to
  2223. AccountType - indicate it is Administrator account or Guest account
  2224. SCE_RENAME_ADMIN
  2225. SCE_RENAME_GUEST
  2226. SCE_DISABLE_ADMIN
  2227. SCE_DISABLE_GUEST
  2228. Return value:
  2229. NTSTATUS error codes
  2230. -- */
  2231. {
  2232. SAM_HANDLE UserHandle1=NULL;
  2233. USER_NAME_INFORMATION Buffer1, *Buffer=NULL;
  2234. PVOID pInfoBuffer=NULL;
  2235. USER_CONTROL_INFORMATION *pControlBuffer=NULL;
  2236. NTSTATUS NtStatus;
  2237. ULONG UserId;
  2238. PWSTR TempStr=NULL;
  2239. DWORD cb;
  2240. PWSTR KeyName;
  2241. BOOL bDisable = FALSE;
  2242. //
  2243. // find the right userid for the account
  2244. //
  2245. switch ( AccountType ) {
  2246. case SCE_RENAME_ADMIN:
  2247. UserId = DOMAIN_USER_RID_ADMIN;
  2248. KeyName = (PWSTR)L"NewAdministratorName";
  2249. break;
  2250. case SCE_RENAME_GUEST:
  2251. UserId = DOMAIN_USER_RID_GUEST;
  2252. KeyName = (PWSTR)L"NewGuestName";
  2253. break;
  2254. case SCE_DISABLE_ADMIN:
  2255. UserId = DOMAIN_USER_RID_ADMIN;
  2256. KeyName = (PWSTR)L"EnableAdminAccount";
  2257. bDisable = TRUE;
  2258. break;
  2259. case SCE_DISABLE_GUEST:
  2260. UserId = DOMAIN_USER_RID_GUEST;
  2261. KeyName = (PWSTR)L"EnableGuestAccount";
  2262. bDisable = TRUE;
  2263. break;
  2264. default:
  2265. return(STATUS_INVALID_PARAMETER);
  2266. }
  2267. NtStatus = SamOpenUser(
  2268. DomainHandle,
  2269. MAXIMUM_ALLOWED, //USER_ALL_ACCESS,
  2270. UserId,
  2271. &UserHandle1
  2272. );
  2273. if ( NT_SUCCESS( NtStatus ) ) {
  2274. NtStatus = SamQueryInformationUser(
  2275. UserHandle1,
  2276. bDisable? UserControlInformation : UserNameInformation,
  2277. &pInfoBuffer
  2278. );
  2279. if ( NT_SUCCESS( NtStatus ) ) {
  2280. if ( bDisable ) {
  2281. //
  2282. // disable the accounts
  2283. //
  2284. pControlBuffer = (USER_CONTROL_INFORMATION *)pInfoBuffer;
  2285. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  2286. hSectionDomain && hSectionTattoo &&
  2287. (ProductType != NtProductLanManNt) ) {
  2288. //
  2289. // do not save tattoo value of account controls for domain controllers
  2290. //
  2291. ScepTattooManageOneIntValue(hSectionDomain, hSectionTattoo,
  2292. KeyName, 0,
  2293. (pControlBuffer->UserAccountControl & USER_ACCOUNT_DISABLED) ? 0 : 1,
  2294. RtlNtStatusToDosError(NtStatus)
  2295. );
  2296. }
  2297. //
  2298. // compare the control flag with existing flag
  2299. // if it's different, set the new flag to the system
  2300. //
  2301. if ( DisableFlag != (pControlBuffer->UserAccountControl & USER_ACCOUNT_DISABLED) ) {
  2302. pControlBuffer->UserAccountControl &= ~USER_ACCOUNT_DISABLED;
  2303. pControlBuffer->UserAccountControl |= DisableFlag;
  2304. NtStatus = SamSetInformationUser(
  2305. UserHandle1,
  2306. UserControlInformation,
  2307. (PVOID)pControlBuffer
  2308. );
  2309. }
  2310. } else {
  2311. //
  2312. // rename the accounts
  2313. //
  2314. Buffer = (USER_NAME_INFORMATION *)pInfoBuffer;
  2315. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  2316. hSectionDomain && hSectionTattoo &&
  2317. (ProductType != NtProductLanManNt) ) {
  2318. //
  2319. // do not save off account names for domain controllers
  2320. //
  2321. ScepTattooManageOneStringValue(hSectionDomain, hSectionTattoo,
  2322. KeyName, 0,
  2323. Buffer->UserName.Buffer,
  2324. Buffer->UserName.Length/sizeof(WCHAR),
  2325. RtlNtStatusToDosError(NtStatus)
  2326. );
  2327. }
  2328. //
  2329. // compare the new name with existing name
  2330. // if it's different, set the new name to the system
  2331. //
  2332. if ( (Buffer->UserName.Length/sizeof(WCHAR) != wcslen(NewName)) ||
  2333. (_wcsnicmp(NewName, Buffer->UserName.Buffer, Buffer->UserName.Length/sizeof(WCHAR)) != 0) ) {
  2334. //
  2335. // keep the full name and copy the new account name to username field
  2336. //
  2337. cb = Buffer->FullName.Length+2;
  2338. TempStr = (PWSTR)ScepAlloc( (UINT)0, cb);
  2339. if ( TempStr == NULL ) {
  2340. NtStatus = STATUS_NO_MEMORY;
  2341. } else {
  2342. RtlMoveMemory( TempStr, Buffer->FullName.Buffer, cb );
  2343. if(!RtlCreateUnicodeString(&(Buffer1.FullName), TempStr)){
  2344. NtStatus = STATUS_NO_MEMORY;
  2345. } else {
  2346. if(!RtlCreateUnicodeString(&(Buffer1.UserName), NewName )){
  2347. NtStatus = STATUS_NO_MEMORY;
  2348. } else {
  2349. NtStatus = SamSetInformationUser(
  2350. UserHandle1,
  2351. UserNameInformation,
  2352. (PVOID)&Buffer1
  2353. );
  2354. RtlFreeUnicodeString( &(Buffer1.UserName) );
  2355. }
  2356. RtlFreeUnicodeString( &(Buffer1.FullName) );
  2357. }
  2358. ScepFree(TempStr);
  2359. }
  2360. }
  2361. }
  2362. }
  2363. SamFreeMemory(pInfoBuffer);
  2364. SamCloseHandle( UserHandle1 );
  2365. }
  2366. return( NtStatus );
  2367. }
  2368. SCESTATUS
  2369. ScepConfigurePrivileges(
  2370. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
  2371. IN BOOL bCreateBuiltinAccount,
  2372. IN DWORD Options,
  2373. IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
  2374. )
  2375. /* ++
  2376. Routine Description:
  2377. This routine configure the system security in the area of user privilege/rights.
  2378. Arguments:
  2379. ppPrivilegeAssigned - The address of the pointer to a list of user privilege/rights as
  2380. specified in the SCP inf file.
  2381. Note, account in the list is a pointer to SID.
  2382. bCreateBuiltinAccount - if TRUE, builtin accounts (server ops, account ops, print ops,
  2383. power users) will be created if they don't exist
  2384. Options - configuration options
  2385. pIgnoreAccounts - the accounts to ignore in configuration (because of pending notifications)
  2386. Return value:
  2387. SCESTATUS_SUCCESS
  2388. SCESTATUS_NOT_ENOUGH_RESOURCE
  2389. SCESTATUS_INVALID_PARAMETER
  2390. SCESTATUS_OTHER_ERROR
  2391. -- */
  2392. {
  2393. DWORD rc;
  2394. DWORD PrivLowMask=0;
  2395. DWORD PrivHighMask=0;
  2396. if ( !ppPrivilegeAssigned ) {
  2397. return(SCESTATUS_INVALID_PARAMETER);
  2398. }
  2399. //
  2400. // get privilege mask from the template
  2401. //
  2402. rc = ScepGetPrivilegeMask(hProfile,
  2403. (Options & SCE_POLICY_TEMPLATE) ? SCE_ENGINE_SCP :SCE_ENGINE_SMP,
  2404. &PrivLowMask,
  2405. &PrivHighMask
  2406. );
  2407. if ( (rc != ERROR_SUCCESS) && (PrivLowMask == 0) && (PrivHighMask == 0) ) {
  2408. //
  2409. // it's likely not possible to fail here because
  2410. // the previous GetPrivileges succeeded.
  2411. // but if it failed, just return.
  2412. //
  2413. return(rc);
  2414. }
  2415. //
  2416. // have to log success for all privileges concerned since
  2417. // later, errors will be OR'd
  2418. // This is to handle the case when Se... = *nothing* which
  2419. // implies implicit configuration success
  2420. //
  2421. if (Options & SCE_RSOP_CALLBACK) {
  2422. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  2423. ERROR_SUCCESS,
  2424. NULL,
  2425. PrivLowMask,
  2426. PrivHighMask);
  2427. }
  2428. rc = ScepConfigurePrivilegesWithMask(ppPrivilegeAssigned,
  2429. bCreateBuiltinAccount,
  2430. Options,
  2431. PrivLowMask,
  2432. PrivHighMask,
  2433. NULL,
  2434. pIgnoreAccounts
  2435. );
  2436. return(rc);
  2437. }
  2438. SCESTATUS
  2439. ScepConfigurePrivilegesWithMask(
  2440. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
  2441. IN BOOL bCreateBuiltinAccount,
  2442. IN DWORD Options,
  2443. IN DWORD LowMask,
  2444. IN DWORD HighMask,
  2445. IN OUT PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
  2446. IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
  2447. )
  2448. /* ++
  2449. Routine Description:
  2450. This routine configure the system security in the area of user privilege/rights.
  2451. Arguments:
  2452. ppPrivilegeAssigned - The address of the pointer to a list of user privilege/rights as
  2453. specified in the SCP inf file.
  2454. Note, account in the list is a pointer to SID.
  2455. bCreateBuiltinAccount - if TRUE, builtin accounts (server ops, account ops, print ops,
  2456. power users) will be created if they don't exist
  2457. Options - configuration options
  2458. PrivLowMask - the privileges (mask) to configure
  2459. PrivHighMask - more privileges (mask) to configure
  2460. pErrLog - output error info
  2461. pIgnoreAccounts - the accounts to ignore in configuration (because of pending notifications)
  2462. Return value:
  2463. SCESTATUS_SUCCESS
  2464. SCESTATUS_NOT_ENOUGH_RESOURCE
  2465. SCESTATUS_INVALID_PARAMETER
  2466. SCESTATUS_OTHER_ERROR
  2467. -- */
  2468. {
  2469. TCHAR MsgBuf[256];
  2470. DWORD rc=ERROR_SUCCESS;
  2471. DWORD SaveStat=NO_ERROR;
  2472. DWORD PendingRc=NO_ERROR;
  2473. NTSTATUS NtStatus;
  2474. LSA_HANDLE PolicyHandle=NULL;
  2475. BYTE SidBuffer[256];
  2476. PSID AccountSid=NULL;
  2477. DWORD SidLength;
  2478. SID_NAME_USE UserType;
  2479. DWORD DomainLength;
  2480. PSCE_PRIVILEGE_VALUE_LIST pPrivilege;
  2481. DWORD nPrivCount=0;
  2482. PSCE_PRIVILEGE_VALUE_LIST pRemAccounts=NULL;
  2483. PWSTR StringSid=NULL;
  2484. DWORD ConfigStatus[64];
  2485. DWORD DonePrivLowMask=0;
  2486. DWORD DonePrivHighMask=0;
  2487. DWORD PrivLowMask=0;
  2488. DWORD PrivHighMask=0;
  2489. if ( !ppPrivilegeAssigned ) {
  2490. return(SCESTATUS_INVALID_PARAMETER);
  2491. }
  2492. //
  2493. // user privilege/rights -- LSA Server
  2494. // open the lsa policy first
  2495. //
  2496. //
  2497. // since client RSOP logging side uses test-and-set for success/failure, the first error (if any)for
  2498. // a particular privilege will always be seen
  2499. //
  2500. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2501. ScepIsSystemShutDown() ) {
  2502. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  2503. }
  2504. if ( (Options & SCE_POLICY_TEMPLATE) && LsaPrivatePolicy ) {
  2505. PolicyHandle = LsaPrivatePolicy;
  2506. if ( !ScepSplayTreeEmpty(pIgnoreAccounts) )
  2507. ScepNotifyLogPolicy(0, FALSE, L"Configuration will ignore pending notified accounts", 0, 0, NULL );
  2508. else
  2509. ScepNotifyLogPolicy(0, FALSE, L"No pending notified accounts", 0, 0, NULL );
  2510. } else {
  2511. NtStatus = ScepOpenLsaPolicy(
  2512. MAXIMUM_ALLOWED, //GENERIC_ALL,
  2513. &PolicyHandle,
  2514. (Options & ( SCE_POLICY_TEMPLATE | SCE_SYSTEM_DB) ) ? TRUE : FALSE // do not notify policy filter if within policy prop
  2515. );
  2516. if (NtStatus != ERROR_SUCCESS) {
  2517. rc = RtlNtStatusToDosError( NtStatus );
  2518. if ( (Options & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  2519. ScepBuildErrorLogInfo(
  2520. rc,
  2521. pErrLog,
  2522. SCEDLL_LSA_POLICY
  2523. );
  2524. } else {
  2525. ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY);
  2526. }
  2527. SaveStat = rc;
  2528. goto Done;
  2529. }
  2530. }
  2531. AccountSid = (PSID)SidBuffer;
  2532. ScepIsDomainLocal(NULL);
  2533. PrivLowMask = LowMask;
  2534. PrivHighMask = HighMask;
  2535. //
  2536. // make sure Authenticated Users, Everyone and Enterprise Controllers have appropriate rights
  2537. // ignore any error occurred
  2538. //
  2539. (void)ScepCheckNetworkLogonRights(PolicyHandle,
  2540. &PrivLowMask,
  2541. &PrivHighMask,
  2542. ppPrivilegeAssigned);
  2543. //
  2544. // save the old privilege settings
  2545. //
  2546. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2547. ( ProductType != NtProductLanManNt ) ) {
  2548. ScepTattooSavePrivilegeValues(hProfile, PolicyHandle,
  2549. PrivLowMask, PrivHighMask,
  2550. Options
  2551. );
  2552. // initialize
  2553. for ( int i=0;i<64;i++) ConfigStatus[i] = (DWORD)-1;
  2554. }
  2555. //
  2556. // other area accounts to remove for the privilege mask
  2557. //
  2558. NtStatus = ScepBuildAccountsToRemove(
  2559. PolicyHandle,
  2560. PrivLowMask, // the privileges to look up
  2561. PrivHighMask,
  2562. SCE_BUILD_IGNORE_UNKNOWN | SCE_BUILD_ACCOUNT_SID,
  2563. *ppPrivilegeAssigned, // accounts in the template already
  2564. Options,
  2565. pIgnoreAccounts,
  2566. &pRemAccounts // accounts to remove
  2567. );
  2568. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2569. (NtStatus == STATUS_PENDING) ) {
  2570. // this error is to make sure that policy propagation will be invoked again
  2571. ScepLogOutput3(0,0, SCESRV_POLICY_PENDING_REMOVE_RIGHTS);
  2572. PendingRc = ERROR_IO_PENDING;
  2573. NtStatus = STATUS_SUCCESS;
  2574. }
  2575. if ( NT_SUCCESS(NtStatus) && pRemAccounts ) {
  2576. //
  2577. // remove user rights for the accounts first
  2578. //
  2579. for (pPrivilege = pRemAccounts;
  2580. pPrivilege != NULL;
  2581. pPrivilege = pPrivilege->Next ) {
  2582. if ( pPrivilege->PrivLowPart == 0 &&
  2583. pPrivilege->PrivHighPart == 0 ) {
  2584. continue;
  2585. }
  2586. //
  2587. // Note: even though it's an invalid account SID,
  2588. // we still should remove it from the system
  2589. // because this account is enumerated from current system.
  2590. //
  2591. /*
  2592. if ( !ScepValidSid( (PSID)(pPrivilege->Name) ) ) {
  2593. continue;
  2594. }
  2595. */
  2596. //
  2597. // get the user/group sid string (to display)
  2598. //
  2599. ConvertSidToStringSid( (PSID)(pPrivilege->Name), &StringSid );
  2600. if ( !(Options & SCE_SYSTEM_SETTINGS) ) {
  2601. //
  2602. // lookup for the user/group name. If it does not exist
  2603. // log an error and continue ? (or stop ?)
  2604. //
  2605. ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, StringSid ? StringSid : L"SID");
  2606. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2607. ScepIsSystemShutDown() ) {
  2608. SaveStat = ERROR_NOT_SUPPORTED;
  2609. break;
  2610. }
  2611. }
  2612. DonePrivHighMask |= (pPrivilege->PrivHighPart & PrivHighMask);
  2613. DonePrivLowMask |= (pPrivilege->PrivLowPart & PrivLowMask);
  2614. //
  2615. // remove the rights
  2616. //
  2617. NtStatus = ScepAddOrRemoveAccountRights(
  2618. PolicyHandle,
  2619. (PSID)(pPrivilege->Name),
  2620. FALSE,
  2621. pPrivilege->PrivLowPart & PrivLowMask,
  2622. pPrivilege->PrivHighPart & PrivHighMask
  2623. );
  2624. rc = RtlNtStatusToDosError( NtStatus );
  2625. if ( !NT_SUCCESS(NtStatus) ) {
  2626. if ( (Options & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  2627. ScepBuildErrorLogInfo(
  2628. rc,
  2629. pErrLog,
  2630. SCEDLL_SCP_ERROR_CONFIGURE,
  2631. StringSid ? StringSid : L"SID"
  2632. );
  2633. } else {
  2634. ScepLogOutput3(1,rc,SCEDLL_SCP_ERROR_CONFIGURE,
  2635. StringSid ? StringSid : L"SID");
  2636. }
  2637. // update the tattoo status array
  2638. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2639. ( ProductType != NtProductLanManNt ) ) {
  2640. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2641. rc,
  2642. pPrivilege->PrivLowPart & PrivLowMask,
  2643. pPrivilege->PrivHighPart & PrivHighMask
  2644. );
  2645. }
  2646. SaveStat = rc;
  2647. if ( Options & SCE_RSOP_CALLBACK){
  2648. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  2649. rc,
  2650. NULL,
  2651. pPrivilege->PrivLowPart & PrivLowMask,
  2652. pPrivilege->PrivHighPart & PrivHighMask);
  2653. }
  2654. }
  2655. else if (Options & SCE_RSOP_CALLBACK) {
  2656. // success - has to be logged because some privilege may want to remove all accounts and
  2657. // processing is over at this point for such privileges
  2658. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  2659. rc,
  2660. NULL,
  2661. pPrivilege->PrivLowPart & PrivLowMask,
  2662. pPrivilege->PrivHighPart & PrivHighMask);
  2663. }
  2664. if ( StringSid ) {
  2665. LocalFree(StringSid);
  2666. StringSid = NULL;
  2667. }
  2668. }
  2669. } else if ( !NT_SUCCESS(NtStatus) &&
  2670. ( ProductType != NtProductLanManNt ) ) {
  2671. //
  2672. // fail to get the accounts to remove
  2673. // in this case, do not remove any tattoo value
  2674. //
  2675. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2676. RtlNtStatusToDosError(NtStatus),
  2677. PrivLowMask,
  2678. PrivHighMask
  2679. );
  2680. }
  2681. //
  2682. // free the remove account list
  2683. //
  2684. ScepFreePrivilegeValueList(pRemAccounts);
  2685. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2686. ScepIsSystemShutDown() ) {
  2687. SaveStat = ERROR_NOT_SUPPORTED;
  2688. } else {
  2689. for (pPrivilege = *ppPrivilegeAssigned;
  2690. pPrivilege != NULL;
  2691. pPrivilege = pPrivilege->Next ) {
  2692. if ( !(Options & SCE_SYSTEM_SETTINGS) ) {
  2693. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2694. ScepIsSystemShutDown() ) {
  2695. SaveStat = ERROR_NOT_SUPPORTED;
  2696. break;
  2697. }
  2698. }
  2699. //
  2700. // remember the privileges we touched here
  2701. //
  2702. DonePrivHighMask |= pPrivilege->PrivHighPart;
  2703. DonePrivLowMask |= pPrivilege->PrivLowPart;
  2704. //
  2705. // note, this list may contain SID or name (when name can't
  2706. // be mapped to SID, such as in dcpromo case)
  2707. // so both name and SID must be handled here.
  2708. // lookup for the user/group name. If it does not exist
  2709. // log an error and continue ? (or stop ?)
  2710. //
  2711. if ( ScepValidSid( (PSID)(pPrivilege->Name) ) ) {
  2712. //
  2713. // get the user/group sid string (to display)
  2714. //
  2715. ConvertSidToStringSid( (PSID)(pPrivilege->Name), &StringSid );
  2716. if ( !(Options & SCE_SYSTEM_SETTINGS) &&
  2717. (nPrivCount < TICKS_PRIVILEGE) ) {
  2718. //
  2719. // only post maximum TICKS_PRIVILEGE ticks because that's the number
  2720. // remembers in the total ticks
  2721. //
  2722. ScepPostProgress(1, AREA_PRIVILEGES, StringSid);
  2723. nPrivCount++;
  2724. }
  2725. ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, StringSid ? StringSid : L"SID");
  2726. //
  2727. // check if this account should be ignored
  2728. //
  2729. NtStatus = STATUS_SUCCESS;
  2730. if ( (Options & SCE_POLICY_TEMPLATE) ) {
  2731. if ( ScepSplayValueExist( (PVOID)(pPrivilege->Name), pIgnoreAccounts) ) {
  2732. //
  2733. // this one should be ingored in this policy prop
  2734. //
  2735. NtStatus = STATUS_PENDING;
  2736. rc = ERROR_IO_PENDING;
  2737. ScepLogOutput3(1, 0, SCESRV_POLICY_PENDING_RIGHTS, StringSid ? StringSid : L"SID");
  2738. /*
  2739. } else {
  2740. ScepLogOutput2(1, 0, L"%s will be configured.", StringSid ? StringSid : L"SID");
  2741. */ }
  2742. }
  2743. if ( NT_SUCCESS(NtStatus) && (STATUS_PENDING != NtStatus) ) {
  2744. NtStatus = ScepAdjustAccountPrivilegesRights(
  2745. PolicyHandle,
  2746. (PSID)(pPrivilege->Name),
  2747. pPrivilege->PrivLowPart,
  2748. PrivLowMask,
  2749. pPrivilege->PrivHighPart,
  2750. PrivHighMask,
  2751. Options
  2752. );
  2753. rc = RtlNtStatusToDosError( NtStatus );
  2754. }
  2755. if ( !NT_SUCCESS(NtStatus) || (STATUS_PENDING == NtStatus) ) {
  2756. if ( (Options & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  2757. ScepBuildErrorLogInfo(
  2758. rc,
  2759. pErrLog,
  2760. SCEDLL_SCP_ERROR_CONFIGURE,
  2761. StringSid ? StringSid : L"SID"
  2762. );
  2763. } else if ( STATUS_PENDING != NtStatus) {
  2764. ScepLogOutput3(1, rc,
  2765. SCEDLL_SCP_ERROR_CONFIGURE,
  2766. StringSid ? StringSid : L"SID");
  2767. }
  2768. if ( ERROR_IO_PENDING == rc )
  2769. PendingRc = rc;
  2770. else
  2771. SaveStat = rc;
  2772. // update tattoo status array
  2773. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2774. ( ProductType != NtProductLanManNt ) ) {
  2775. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2776. rc,
  2777. pPrivilege->PrivLowPart,
  2778. pPrivilege->PrivHighPart
  2779. );
  2780. }
  2781. }
  2782. if ( StringSid ) {
  2783. LocalFree(StringSid);
  2784. StringSid = NULL;
  2785. }
  2786. } else if (Options & SCE_SYSTEM_SETTINGS ) {
  2787. //
  2788. // if work on system settings directly, the buffer must contain
  2789. // a SID. If not, it's an error
  2790. //
  2791. if ( pErrLog ) {
  2792. ScepBuildErrorLogInfo(
  2793. ERROR_NONE_MAPPED,
  2794. pErrLog,
  2795. SCEDLL_INVALID_GROUP,
  2796. pPrivilege->Name
  2797. );
  2798. }
  2799. if ( Options & SCE_RSOP_CALLBACK ){
  2800. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  2801. ERROR_NONE_MAPPED,
  2802. NULL,
  2803. pPrivilege->PrivLowPart,
  2804. pPrivilege->PrivHighPart);
  2805. }
  2806. } else {
  2807. if ( !(Options & SCE_SYSTEM_SETTINGS) &&
  2808. (nPrivCount < TICKS_PRIVILEGE) ) {
  2809. //
  2810. // only post maximum TICKS_PRIVILEGE ticks because that's the number
  2811. // remembers in the total ticks
  2812. //
  2813. ScepPostProgress(1, AREA_PRIVILEGES, pPrivilege->Name);
  2814. nPrivCount++;
  2815. }
  2816. ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, pPrivilege->Name);
  2817. SidLength=256;
  2818. DomainLength=256;
  2819. MsgBuf[0] = L'\0';
  2820. rc = ERROR_SUCCESS;
  2821. if ( wcschr(pPrivilege->Name, L'\\') == NULL ) {
  2822. //
  2823. // isolated accounts can't be resolved when reading the configuration
  2824. // no need to try now.
  2825. //
  2826. rc = ERROR_NONE_MAPPED;
  2827. } else if ( !LookupAccountName(
  2828. NULL,
  2829. pPrivilege->Name,
  2830. AccountSid,
  2831. &SidLength,
  2832. MsgBuf,
  2833. &DomainLength,
  2834. &UserType
  2835. )) {
  2836. rc = GetLastError();
  2837. }
  2838. if ( ERROR_SUCCESS != rc && bCreateBuiltinAccount ) {
  2839. //
  2840. // builtin accounts should be created here
  2841. //
  2842. rc = ScepCreateBuiltinAccountInLsa(
  2843. PolicyHandle,
  2844. pPrivilege->Name,
  2845. AccountSid
  2846. );
  2847. }
  2848. if ( ERROR_SUCCESS != rc ) {
  2849. ScepLogOutput3(1, rc, SCEDLL_CANNOT_FIND, pPrivilege->Name);
  2850. if ( Options & SCE_RSOP_CALLBACK){
  2851. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  2852. rc,
  2853. NULL,
  2854. pPrivilege->PrivLowPart,
  2855. pPrivilege->PrivHighPart);
  2856. }
  2857. //
  2858. // for accounts not mapped in the tattoo value
  2859. // ignore them so that the tattoo value can be removed
  2860. // update tattoo status array
  2861. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2862. ( ProductType != NtProductLanManNt ) ) {
  2863. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2864. 0, // rc, see comment above
  2865. pPrivilege->PrivLowPart,
  2866. pPrivilege->PrivHighPart
  2867. );
  2868. }
  2869. if ( ERROR_TRUSTED_RELATIONSHIP_FAILURE == rc ) {
  2870. //
  2871. // this error is only returned when the name
  2872. // can't be found locally and trust relationship
  2873. // is broken on the domain
  2874. //
  2875. // for policy propagation, this failure is the same
  2876. // as account not found (locally).
  2877. //
  2878. rc = ERROR_NONE_MAPPED;
  2879. }
  2880. SaveStat = rc;
  2881. continue;
  2882. }
  2883. //
  2884. // check if the account should be ignored
  2885. //
  2886. NtStatus = STATUS_SUCCESS;
  2887. if ( (Options & SCE_POLICY_TEMPLATE) ) {
  2888. if ( ScepSplayValueExist( (PVOID)AccountSid, pIgnoreAccounts) ) {
  2889. //
  2890. // this one should be ingored in this policy prop
  2891. //
  2892. NtStatus = STATUS_PENDING;
  2893. rc = ERROR_IO_PENDING;
  2894. ScepLogOutput3(1, 0, SCESRV_POLICY_PENDING_RIGHTS, pPrivilege->Name);
  2895. /*
  2896. } else {
  2897. ScepLogOutput2(1, 0, L"%s will be configured.", pPrivilege->Name);
  2898. */ }
  2899. }
  2900. if ( NT_SUCCESS(NtStatus) && (NtStatus != STATUS_PENDING) ) {
  2901. NtStatus = ScepAdjustAccountPrivilegesRights(
  2902. PolicyHandle,
  2903. AccountSid,
  2904. pPrivilege->PrivLowPart,
  2905. PrivLowMask,
  2906. pPrivilege->PrivHighPart,
  2907. PrivHighMask,
  2908. Options
  2909. );
  2910. rc = RtlNtStatusToDosError( NtStatus );
  2911. }
  2912. if ( !NT_SUCCESS(NtStatus) || (NtStatus == STATUS_PENDING) ) {
  2913. if ( STATUS_PENDING != NtStatus ) {
  2914. ScepLogOutput3(1, rc,
  2915. SCEDLL_SCP_ERROR_CONFIGURE,
  2916. pPrivilege->Name);
  2917. SaveStat = rc;
  2918. } else
  2919. PendingRc = rc;
  2920. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2921. ( ProductType != NtProductLanManNt ) ) {
  2922. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2923. rc,
  2924. pPrivilege->PrivLowPart,
  2925. pPrivilege->PrivHighPart
  2926. );
  2927. }
  2928. // goto Done;
  2929. continue;
  2930. }
  2931. }
  2932. //
  2933. // at this point, if rc == ERROR_SUCCESS we should log all privs concerned with this acct
  2934. //
  2935. if ( rc == ERROR_SUCCESS &&
  2936. (Options & SCE_RSOP_CALLBACK) ){
  2937. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  2938. rc,
  2939. NULL,
  2940. pPrivilege->PrivLowPart,
  2941. pPrivilege->PrivHighPart);
  2942. }
  2943. }
  2944. }
  2945. Done:
  2946. if ( StringSid ) {
  2947. LocalFree(StringSid);
  2948. }
  2949. if ( !(Options & SCE_SYSTEM_SETTINGS) &&
  2950. (nPrivCount < TICKS_PRIVILEGE) ) {
  2951. ScepPostProgress(TICKS_PRIVILEGE-nPrivCount,
  2952. AREA_PRIVILEGES, NULL);
  2953. }
  2954. if ( SaveStat == ERROR_SUCCESS ) SaveStat = PendingRc;
  2955. if ( (Options & SCE_POLICY_TEMPLATE) &&
  2956. ( ProductType != NtProductLanManNt ) ) {
  2957. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2958. 0,
  2959. DonePrivLowMask,
  2960. DonePrivHighMask
  2961. );
  2962. if ( SaveStat == ERROR_SUCCESS ) {
  2963. //
  2964. // make sure all privileges are covered
  2965. //
  2966. ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
  2967. 0,
  2968. PrivLowMask,
  2969. PrivHighMask
  2970. );
  2971. }
  2972. ScepTattooRemovePrivilegeValues(hProfile,
  2973. ConfigStatus
  2974. );
  2975. }
  2976. if ( PolicyHandle != LsaPrivatePolicy )
  2977. LsaClose(PolicyHandle);
  2978. return( ScepDosErrorToSceStatus(SaveStat) );
  2979. }
  2980. SCESTATUS
  2981. ScepGetPrivilegeMask(
  2982. IN PSCECONTEXT hProfile,
  2983. IN SCETYPE ProfileType,
  2984. OUT PDWORD pdLowMask,
  2985. OUT PDWORD pdHighMask
  2986. )
  2987. {
  2988. SCESTATUS rc;
  2989. PSCESECTION hSection=NULL;
  2990. DWORD nLowMask, nHighMask;
  2991. DWORD i;
  2992. if ( !hProfile || !pdHighMask || !pdLowMask ) {
  2993. return(SCESTATUS_INVALID_PARAMETER);
  2994. }
  2995. //
  2996. // open the section
  2997. //
  2998. rc = ScepOpenSectionForName(
  2999. hProfile,
  3000. ProfileType,
  3001. szPrivilegeRights,
  3002. &hSection
  3003. );
  3004. if ( rc != SCESTATUS_SUCCESS ) {
  3005. ScepLogOutput3( 1,
  3006. ScepSceStatusToDosError(rc),
  3007. SCEERR_OPEN,
  3008. (LPTSTR)szPrivilegeRights
  3009. );
  3010. return(rc);
  3011. }
  3012. nLowMask = 0;
  3013. nHighMask = 0;
  3014. for ( i=0; i<cPrivCnt; i++) {
  3015. rc = SceJetSeek(
  3016. hSection,
  3017. SCE_Privileges[i].Name,
  3018. wcslen(SCE_Privileges[i].Name)*sizeof(WCHAR),
  3019. SCEJET_SEEK_EQ_NO_CASE
  3020. );
  3021. if ( SCESTATUS_SUCCESS == rc ) {
  3022. if ( i < 32 ) {
  3023. nLowMask |= (1 << i );
  3024. } else {
  3025. nHighMask |= (1 << ( i-32 ) );
  3026. }
  3027. }
  3028. }
  3029. //
  3030. // close the section
  3031. //
  3032. SceJetCloseSection( &hSection, TRUE );
  3033. *pdLowMask = nLowMask;
  3034. *pdHighMask = nHighMask;
  3035. return(SCESTATUS_SUCCESS);
  3036. }
  3037. DWORD
  3038. ScepCreateBuiltinAccountInLsa(
  3039. IN LSA_HANDLE PolicyHandle,
  3040. IN LPTSTR AccountName,
  3041. OUT PSID AccountSid
  3042. )
  3043. {
  3044. DWORD rc;
  3045. WCHAR szTempString[256];
  3046. ULONG Rid;
  3047. if ( !PolicyHandle || !AccountName || !AccountSid ) {
  3048. return(ERROR_INVALID_PARAMETER);
  3049. }
  3050. //
  3051. // figure out which constant SID to build
  3052. //
  3053. Rid = 0;
  3054. szTempString[0] = L'\0';
  3055. LoadString( MyModuleHandle,
  3056. SCESRV_ALIAS_NAME_SERVER_OPS,
  3057. szTempString,
  3058. 255
  3059. );
  3060. if ( _wcsicmp(AccountName, szTempString) == 0 ) {
  3061. //
  3062. // it's server operators
  3063. //
  3064. Rid = DOMAIN_ALIAS_RID_SYSTEM_OPS;
  3065. } else {
  3066. szTempString[0] = L'\0';
  3067. LoadString( MyModuleHandle,
  3068. SCESRV_ALIAS_NAME_ACCOUNT_OPS,
  3069. szTempString,
  3070. 255
  3071. );
  3072. if ( _wcsicmp(AccountName, szTempString) == 0 ) {
  3073. //
  3074. // it's account operators
  3075. //
  3076. Rid = DOMAIN_ALIAS_RID_ACCOUNT_OPS;
  3077. } else {
  3078. szTempString[0] = L'\0';
  3079. LoadString( MyModuleHandle,
  3080. SCESRV_ALIAS_NAME_PRINT_OPS,
  3081. szTempString,
  3082. 255
  3083. );
  3084. if ( _wcsicmp(AccountName, szTempString) == 0 ) {
  3085. //
  3086. // it's print operators
  3087. //
  3088. Rid = DOMAIN_ALIAS_RID_PRINT_OPS;
  3089. }
  3090. }
  3091. }
  3092. if ( Rid ) {
  3093. //
  3094. // if found the account, build the SID
  3095. // create the account in lsa database and return the SID
  3096. //
  3097. SID_IDENTIFIER_AUTHORITY sidBuiltinAuthority = SECURITY_NT_AUTHORITY;
  3098. NTSTATUS NtStatus;
  3099. NtStatus = RtlInitializeSid( AccountSid, &sidBuiltinAuthority, 2 );
  3100. if ( NT_SUCCESS(NtStatus) ) {
  3101. *(RtlSubAuthoritySid(AccountSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
  3102. *(RtlSubAuthoritySid(AccountSid, 1)) = Rid;
  3103. //
  3104. // create the account in Lsa
  3105. //
  3106. LSA_HANDLE AccountHandle=NULL;
  3107. NtStatus = LsaCreateAccount(PolicyHandle,
  3108. AccountSid,
  3109. ACCOUNT_ALL_ACCESS,
  3110. &AccountHandle
  3111. );
  3112. if ( STATUS_OBJECT_NAME_EXISTS == NtStatus ||
  3113. STATUS_OBJECT_NAME_COLLISION == NtStatus ) {
  3114. NtStatus = STATUS_SUCCESS;
  3115. }
  3116. rc = RtlNtStatusToDosError(NtStatus);
  3117. if ( AccountHandle ) {
  3118. LsaClose(AccountHandle);
  3119. }
  3120. } else {
  3121. rc = RtlNtStatusToDosError(NtStatus);
  3122. }
  3123. ScepLogOutput3(3,rc, SCESRV_ALIAS_CREATE, Rid);
  3124. } else {
  3125. rc = ERROR_NONE_MAPPED;
  3126. ScepLogOutput3(3,0, SCESRV_ALIAS_UNSUPPORTED, AccountName);
  3127. }
  3128. return(rc);
  3129. }
  3130. NTSTATUS
  3131. ScepBuildAccountsToRemove(
  3132. IN LSA_HANDLE PolicyHandle,
  3133. IN DWORD PrivLowMask,
  3134. IN DWORD PrivHighMask,
  3135. IN DWORD dwBuildRule,
  3136. IN PSCE_PRIVILEGE_VALUE_LIST pTemplateList OPTIONAL,
  3137. IN DWORD Options OPTIONAL,
  3138. IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL,
  3139. OUT PSCE_PRIVILEGE_VALUE_LIST *pRemoveList
  3140. )
  3141. /*
  3142. Routine Description:
  3143. Build a list of accounts which are not in pTemplateList for the privilege(s)
  3144. .
  3145. Note, the account(s) returned are in SID format when dwBuildRule requests
  3146. SCE_BUILD_ACCOUNT_SID, or in name format if the flag is not set.
  3147. The reason to return all name format (instead of name/SID string format) is due
  3148. to the default templates (defltdc.inf, dcup.inf) use names instead of SID string
  3149. for account domain accounts (such as the guest account). Even if a sid string
  3150. is used, the sid string and the account name will be treated as two different
  3151. accounts, which will be eventually duplicated out in configuration (where
  3152. account SID is used).
  3153. */
  3154. {
  3155. //
  3156. // LSA buffers and variables
  3157. //
  3158. ULONG uAccountIndex = 0;
  3159. ULONG uCountOfRights = 0;
  3160. DWORD dwPrivLowThisAccount = 0;
  3161. DWORD dwPrivHighThisAccount = 0;
  3162. ULONG uEnumerationContext;
  3163. ULONG uPreferedMaximumLength;
  3164. ULONG uNumAccounts;
  3165. PLSA_ENUMERATION_INFORMATION aSids = NULL;
  3166. PLSA_TRANSLATED_NAME aNames=NULL;
  3167. PLSA_REFERENCED_DOMAIN_LIST pReferencedDomains=NULL;
  3168. PUNICODE_STRING aUserRights = NULL;
  3169. //
  3170. // other variables
  3171. //
  3172. NTSTATUS NtStatus;
  3173. NTSTATUS NtStatusSave=STATUS_SUCCESS;
  3174. NTSTATUS NtStatusRsop = STATUS_SUCCESS;
  3175. PSCE_NAME_LIST pAccountSidOrName=NULL;
  3176. PSCE_PRIVILEGE_VALUE_LIST pAccountNode=NULL;
  3177. PWSTR pwszStringSid = NULL;
  3178. SCE_NAME_LIST sNameList;
  3179. PSCE_NAME_LIST psList = &sNameList;
  3180. PWSTR StringSid=NULL;
  3181. BOOL bIgnored = FALSE;
  3182. if ( !PolicyHandle || !pRemoveList ) {
  3183. return(SCESTATUS_INVALID_PARAMETER);
  3184. }
  3185. if ( PrivLowMask == 0 && PrivHighMask == 0 ) {
  3186. return(SCESTATUS_SUCCESS);
  3187. }
  3188. //
  3189. // get all the accounts (potentially with multiple calls to LSA - the while loop)
  3190. //
  3191. //
  3192. // say each SID has 20 bytes and we'd like to get about SCEP_NUM_LSA_QUERY_SIDS
  3193. // (currently SCEP_NUM_LSA_QUERY_SIDS = 2000 SIDs at a time (approx 40 kB))
  3194. // we might need to tune SCEP_NUM_LSA_QUERY_SIDS depending on LSA memory performance
  3195. //
  3196. uPreferedMaximumLength = 20 * SCEP_NUM_LSA_QUERY_SIDS;
  3197. uEnumerationContext = 0;
  3198. uNumAccounts = 0;
  3199. NtStatus = LsaEnumerateAccounts(
  3200. PolicyHandle,
  3201. &uEnumerationContext,
  3202. (PVOID *)&aSids,
  3203. uPreferedMaximumLength,
  3204. &uNumAccounts
  3205. );
  3206. //
  3207. // in case there are more accounts returned, continue processing
  3208. // until all SIDs
  3209. // from LSA are exhausted
  3210. //
  3211. while ( NtStatus == STATUS_SUCCESS
  3212. && uNumAccounts > 0
  3213. && aSids != NULL) {
  3214. NtStatus = STATUS_SUCCESS;
  3215. //
  3216. // convert SIDs to names if required
  3217. //
  3218. if ( !(dwBuildRule & SCE_BUILD_ACCOUNT_SID) &&
  3219. !(dwBuildRule & SCE_BUILD_ACCOUNT_SID_STRING) ) {
  3220. NtStatus = LsaLookupSids(
  3221. PolicyHandle,
  3222. uNumAccounts,
  3223. (PSID *)aSids,
  3224. &pReferencedDomains,
  3225. &aNames
  3226. );
  3227. }
  3228. if ( NT_SUCCESS(NtStatus) ) {
  3229. BOOL bUsed;
  3230. for ( uAccountIndex = 0; uAccountIndex < uNumAccounts ; uAccountIndex++ ) {
  3231. ScepFree ( pwszStringSid );
  3232. pwszStringSid = NULL;
  3233. ScepConvertSidToPrefixStringSid(aSids[uAccountIndex].Sid, &pwszStringSid);
  3234. //
  3235. // check if this account is in the ignore list
  3236. //
  3237. if ( (Options & SCE_POLICY_TEMPLATE) ) {
  3238. if ( ScepSplayValueExist( (PVOID)(aSids[uAccountIndex].Sid), pIgnoreAccounts) ) {
  3239. //
  3240. // this one should be ingored in this policy prop
  3241. //
  3242. //
  3243. NtStatusRsop = STATUS_PENDING;
  3244. bIgnored = TRUE;
  3245. ScepLogOutput2(1, 0, L"\t\tIgnore %s.", pwszStringSid ? pwszStringSid : L"");
  3246. continue;
  3247. /*
  3248. } else {
  3249. ScepLogOutput2(1, 0, L"\tSome rights assigned to %s may be removed", pwszStringSid ? pwszStringSid : L"");
  3250. */
  3251. }
  3252. }
  3253. uCountOfRights = 0;
  3254. aUserRights = NULL;
  3255. NtStatus = LsaEnumerateAccountRights(
  3256. PolicyHandle,
  3257. aSids[uAccountIndex].Sid,
  3258. &aUserRights,
  3259. &uCountOfRights
  3260. );
  3261. if ( !NT_SUCCESS(NtStatus) ) {
  3262. //
  3263. // log error for this account and continue with the next account
  3264. //
  3265. ScepLogOutput3(1,
  3266. RtlNtStatusToDosError(NtStatus),
  3267. SCESRV_ERROR_QUERY_ACCOUNT_RIGHTS,
  3268. pwszStringSid);
  3269. if ( aUserRights ) {
  3270. LsaFreeMemory( aUserRights );
  3271. aUserRights = NULL;
  3272. }
  3273. NtStatusSave = NtStatus;
  3274. continue;
  3275. }
  3276. dwPrivLowThisAccount = 0;
  3277. dwPrivHighThisAccount = 0;
  3278. ScepBuildDwMaskFromStrArray(
  3279. aUserRights,
  3280. uCountOfRights,
  3281. &dwPrivLowThisAccount,
  3282. &dwPrivHighThisAccount
  3283. );
  3284. //
  3285. // if account has at least one user right after masking,
  3286. // we have to process it further
  3287. //
  3288. if ( (dwPrivLowThisAccount & PrivLowMask) ||
  3289. (dwPrivHighThisAccount & PrivHighMask) ) {
  3290. if ( dwBuildRule & SCE_BUILD_ACCOUNT_SID ) {
  3291. //
  3292. // add the SID to the name list
  3293. //
  3294. (VOID) ScepAddSidToNameList(
  3295. &pAccountSidOrName,
  3296. aSids[uAccountIndex].Sid,
  3297. FALSE,
  3298. &bUsed);
  3299. } else if ( dwBuildRule & SCE_BUILD_ACCOUNT_SID_STRING ) {
  3300. //
  3301. // add the SID in string format
  3302. //
  3303. if ( ERROR_SUCCESS == ScepConvertSidToPrefixStringSid(
  3304. aSids[uAccountIndex].Sid, &StringSid) ) {
  3305. sNameList.Name = StringSid;
  3306. sNameList.Next = NULL;
  3307. pAccountSidOrName = psList;
  3308. } // else out of memory, catch it later
  3309. } else {
  3310. //
  3311. // detect if the sid can't be mapped, there are two cases:
  3312. // 1) the domain can't be found, a string format of SID is returned
  3313. // 2) the domain is found. If the domain is builtin and the account
  3314. // name has all digits (the RID), then the builtin account can't be found
  3315. // the second case is solely for the server and DC accounts (PU, SO, AO, PO)
  3316. //
  3317. if ( (dwBuildRule & SCE_BUILD_IGNORE_UNKNOWN) &&
  3318. ( aNames[uAccountIndex].Use == SidTypeInvalid ||
  3319. aNames[uAccountIndex].Use == SidTypeUnknown ) ) {
  3320. //
  3321. // this name is not mapped, ignore it and
  3322. // continue with the next account
  3323. //
  3324. if ( aUserRights ) {
  3325. LsaFreeMemory( aUserRights );
  3326. aUserRights = NULL;
  3327. }
  3328. NtStatusSave = NtStatus;
  3329. continue;
  3330. }
  3331. //
  3332. // build the full name of each account
  3333. //
  3334. if ( pReferencedDomains->Entries > 0 && aNames[uAccountIndex].Use != SidTypeWellKnownGroup &&
  3335. pReferencedDomains->Domains != NULL &&
  3336. aNames[uAccountIndex].DomainIndex != -1 &&
  3337. (ULONG)(aNames[uAccountIndex].DomainIndex) < pReferencedDomains->Entries &&
  3338. ScepIsDomainLocalBySid(pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Sid) == FALSE &&
  3339. ScepIsDomainLocal(&pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name) == FALSE ) {
  3340. // For migrated accounts, sid will map to the new account and we'll lose
  3341. // permissions for the original account. Detect this case by doing a reverse
  3342. // lookup and comparing the SIDs
  3343. // If sid -> name -> sid returns a different sid, then it's a sid history
  3344. // name lookup and the account is from a different domain. Converting to current
  3345. // name will cause it to lose the original sid from the policy. We'll hold on
  3346. // to the original SID.
  3347. bool bMigratedAccount = false;
  3348. NtStatus = ScepIsMigratedAccount(
  3349. PolicyHandle,
  3350. &aNames[uAccountIndex].Name,
  3351. &pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name,
  3352. aSids[uAccountIndex].Sid,
  3353. &bMigratedAccount);
  3354. if(NT_SUCCESS(NtStatus) && bMigratedAccount) {
  3355. // add SID string to the list
  3356. (VOID )ScepAddToNameList(
  3357. &pAccountSidOrName,
  3358. pwszStringSid,
  3359. 0);
  3360. } else {
  3361. NtStatus = STATUS_SUCCESS; // ignore failure to detect migrated account
  3362. //
  3363. // add both domain name and account name
  3364. //
  3365. (VOID) ScepAddTwoNamesToNameList(
  3366. &pAccountSidOrName,
  3367. TRUE,
  3368. pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name.Buffer,
  3369. pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name.Length/2,
  3370. aNames[uAccountIndex].Name.Buffer,
  3371. aNames[uAccountIndex].Name.Length/2);
  3372. }
  3373. } else {
  3374. //
  3375. // add only the account name
  3376. //
  3377. (VOID) ScepAddToNameList(
  3378. &pAccountSidOrName,
  3379. aNames[uAccountIndex].Name.Buffer,
  3380. aNames[uAccountIndex].Name.Length/2);
  3381. }
  3382. }
  3383. if ( pAccountSidOrName ) {
  3384. //
  3385. // if sid/name exists in the template list
  3386. // continue (the explicit mask takes care of remove)
  3387. // else
  3388. // add it to the remove list
  3389. //
  3390. for ( pAccountNode=pTemplateList;
  3391. pAccountNode != NULL;
  3392. pAccountNode = pAccountNode->Next ) {
  3393. if ( pAccountNode->Name == NULL ) {
  3394. continue;
  3395. }
  3396. if ( dwBuildRule & SCE_BUILD_ACCOUNT_SID ) {
  3397. if ( ScepValidSid( (PSID)(pAccountNode->Name) ) &&
  3398. RtlEqualSid( (PSID)(pAccountSidOrName->Name), (PSID)(pAccountNode->Name) ) ) {
  3399. break;
  3400. }
  3401. } else if ( _wcsicmp(pAccountNode->Name, pAccountSidOrName->Name) == 0 ) {
  3402. break;
  3403. }
  3404. }
  3405. //
  3406. // always need to add to the remove list since each sid/name
  3407. // is seen only once in the new algorithm
  3408. //
  3409. if ( pAccountNode == NULL ) {
  3410. pAccountNode = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc(
  3411. LPTR,
  3412. sizeof(SCE_PRIVILEGE_VALUE_LIST));
  3413. if ( pAccountNode != NULL ) {
  3414. pAccountNode->Name = pAccountSidOrName->Name;
  3415. pAccountSidOrName->Name = NULL;
  3416. pAccountNode->PrivLowPart = dwPrivLowThisAccount & PrivLowMask;
  3417. pAccountNode->PrivHighPart = dwPrivHighThisAccount & PrivHighMask;
  3418. pAccountNode->Next = *pRemoveList;
  3419. *pRemoveList = pAccountNode;
  3420. }
  3421. }
  3422. //
  3423. // free the buffer
  3424. //
  3425. if ( pAccountSidOrName->Name ) {
  3426. ScepFree(pAccountSidOrName->Name);
  3427. }
  3428. if ( pAccountSidOrName != psList)
  3429. ScepFree(pAccountSidOrName);
  3430. pAccountSidOrName = NULL;
  3431. }
  3432. }
  3433. if ( aUserRights ) {
  3434. LsaFreeMemory( aUserRights );
  3435. aUserRights = NULL;
  3436. }
  3437. }
  3438. } else if ( NtStatus == STATUS_NONE_MAPPED ) {
  3439. //
  3440. // lookup for all sids failed
  3441. //
  3442. NtStatusRsop = NtStatus;
  3443. NtStatus = STATUS_SUCCESS;
  3444. } else {
  3445. NtStatusRsop = NtStatus;
  3446. ScepLogOutput3(3,0, IDS_ERROR_LOOKUP, NtStatus, uNumAccounts);
  3447. NtStatus = STATUS_SUCCESS; // ignore the error for now
  3448. }
  3449. //
  3450. // free and reset all parameters except the enumeration context
  3451. // for which state has to be remembered between calls to LSA
  3452. //
  3453. if (pReferencedDomains) {
  3454. LsaFreeMemory(pReferencedDomains);
  3455. pReferencedDomains = NULL;
  3456. }
  3457. if (aNames) {
  3458. LsaFreeMemory(aNames);
  3459. aNames = NULL;
  3460. }
  3461. if (aSids) {
  3462. LsaFreeMemory( aSids );
  3463. aSids = NULL;
  3464. }
  3465. //
  3466. // attempt to enumerate the next batch of SIDs
  3467. //
  3468. uNumAccounts = 0;
  3469. NtStatus = LsaEnumerateAccounts(
  3470. PolicyHandle,
  3471. &uEnumerationContext,
  3472. (PVOID *)&aSids,
  3473. uPreferedMaximumLength,
  3474. &uNumAccounts
  3475. );
  3476. }
  3477. if ( aSids ) {
  3478. LsaFreeMemory( aSids );
  3479. }
  3480. ScepFree(pwszStringSid);
  3481. pwszStringSid = NULL;
  3482. if ( NtStatus == STATUS_NO_MORE_ENTRIES ||
  3483. NtStatus == STATUS_NOT_FOUND ) {
  3484. //
  3485. // not a real error - just an enumeration warning/status
  3486. //
  3487. NtStatus = STATUS_SUCCESS;
  3488. }
  3489. //
  3490. // in this scheme in which it is "foreach SID" and not "foreach privilege",
  3491. // either log all in case of failure
  3492. //
  3493. if ( ! NT_SUCCESS( NtStatus ) ) {
  3494. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  3495. RtlNtStatusToDosError(NtStatus),
  3496. NULL,
  3497. PrivLowMask,
  3498. PrivHighMask);
  3499. ScepLogOutput3(1,
  3500. RtlNtStatusToDosError(NtStatus),
  3501. SCEDLL_SAP_ERROR_ENUMERATE,
  3502. L"Accounts from LSA");
  3503. }
  3504. if ( NT_SUCCESS(NtStatus) ) {
  3505. if ( bIgnored ) {
  3506. //
  3507. // if some accounts are ignored, return the pending error
  3508. //
  3509. return(STATUS_PENDING);
  3510. } else
  3511. return NtStatusSave;
  3512. } else
  3513. return(NtStatus);
  3514. }
  3515. VOID
  3516. ScepBuildDwMaskFromStrArray(
  3517. IN PUNICODE_STRING aUserRights,
  3518. IN ULONG uCountOfRights,
  3519. OUT DWORD *pdwPrivLowThisAccount,
  3520. OUT DWORD *pdwPrivHighThisAccount
  3521. )
  3522. /* ++
  3523. Routine Description:
  3524. This routine converts a privilege array of unicode strings two DWORD masks.
  3525. Arguments:
  3526. aUserRights - an array of unicode strings, each string is a user right
  3527. uCountOfRights - array count
  3528. pdwPrivLowThisAccount - converted privileges' low 32 mask
  3529. pdwPrivHighThisAccount - converted privileges' high 32 mask
  3530. Return value:
  3531. None except the low 32 and high 32 masks
  3532. -- */
  3533. {
  3534. ULONG uAccountIndex;
  3535. DWORD dwRefPrivIndex;
  3536. DWORD dwLowMask = 0;
  3537. DWORD dwHighMask = 0;
  3538. if (pdwPrivLowThisAccount == NULL ||
  3539. pdwPrivHighThisAccount == NULL ||
  3540. aUserRights == NULL ||
  3541. uCountOfRights == 0 ) {
  3542. return;
  3543. }
  3544. for (uAccountIndex = 0; uAccountIndex < uCountOfRights; uAccountIndex++ ) {
  3545. for (dwRefPrivIndex = 0; dwRefPrivIndex < cPrivCnt; dwRefPrivIndex++ ) {
  3546. if ( 0 == _wcsnicmp(SCE_Privileges[ dwRefPrivIndex ].Name, aUserRights[ uAccountIndex ].Buffer, aUserRights[ uAccountIndex ].Length/sizeof(WCHAR))) {
  3547. if ( dwRefPrivIndex < 32 ) {
  3548. dwLowMask |= 1 << dwRefPrivIndex;
  3549. }
  3550. else {
  3551. dwHighMask |= 1 << (dwRefPrivIndex - 32) ;
  3552. }
  3553. }
  3554. }
  3555. }
  3556. *pdwPrivLowThisAccount = dwLowMask;
  3557. *pdwPrivHighThisAccount = dwHighMask;
  3558. return;
  3559. }
  3560. NTSTATUS
  3561. ScepAdjustAccountPrivilegesRights(
  3562. IN LSA_HANDLE PolicyHandle,
  3563. IN PSID AccountSid,
  3564. IN DWORD PrivilegeLowRights,
  3565. IN DWORD PrivilegeLowMask,
  3566. IN DWORD PrivilegeHighRights,
  3567. IN DWORD PrivilegeHighMask,
  3568. IN DWORD Options
  3569. )
  3570. /* ++
  3571. Routine Description:
  3572. This routine set the privilege/rights as specified in PrivilegeRights
  3573. (DWORD type, each bit represents a privilege/right) to the account
  3574. referenced by AccountSid. This routine compares the current privilege/
  3575. right setting with the "should be" setting and add/remove privileges/
  3576. rights from the account.
  3577. Arguments:
  3578. PolicyHandle - Lsa Policy Domain handle
  3579. AccountSid - The SID for the account
  3580. PrivilegeRights - Privilege/Rights to set for this account
  3581. Return value:
  3582. NTSTATUS
  3583. -- */
  3584. {
  3585. NTSTATUS NtStatus;
  3586. DWORD ExplicitPrivLowRights=0, ExplicitPrivHighRights=0;
  3587. DWORD PrivLowRightAdd,
  3588. PrivLowRightRemove;
  3589. DWORD PrivHighRightAdd,
  3590. PrivHighRightRemove;
  3591. //
  3592. // Enumerate current explicitly assigned privilege/rights
  3593. //
  3594. NtStatus = ScepGetAccountExplicitRight(
  3595. PolicyHandle,
  3596. AccountSid,
  3597. &ExplicitPrivLowRights,
  3598. &ExplicitPrivHighRights
  3599. );
  3600. if ( !NT_SUCCESS(NtStatus) ){
  3601. if ( Options & SCE_RSOP_CALLBACK){
  3602. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  3603. RtlNtStatusToDosError(NtStatus),
  3604. NULL,
  3605. PrivilegeLowRights,
  3606. PrivilegeHighRights);
  3607. }
  3608. return(NtStatus);
  3609. }
  3610. //
  3611. // Compare CurrentPrivRights with pRights->PrivilegeRights for add
  3612. // Example: CurrentPrivRights 10101
  3613. // pRights->PrivilegeRights( change to) 11010
  3614. // where 1 means the privilege/right is on
  3615. // So the privileges/rights to add 01010
  3616. // Compare ExplicitPrivRights with pRights->PrivilegeRights for remove
  3617. //
  3618. PrivLowRightAdd = ~ExplicitPrivLowRights & PrivilegeLowRights;
  3619. PrivLowRightRemove = (~(PrivilegeLowRights) & ExplicitPrivLowRights) & PrivilegeLowMask;
  3620. PrivHighRightAdd = ~ExplicitPrivHighRights & PrivilegeHighRights;
  3621. PrivHighRightRemove = (~(PrivilegeHighRights) & ExplicitPrivHighRights) & PrivilegeHighMask;
  3622. //
  3623. // Add
  3624. //
  3625. if ( PrivLowRightAdd != 0 || PrivHighRightAdd != 0 ) {
  3626. NtStatus = ScepAddOrRemoveAccountRights(
  3627. PolicyHandle,
  3628. AccountSid,
  3629. TRUE,
  3630. PrivLowRightAdd,
  3631. PrivHighRightAdd
  3632. );
  3633. if ( !NT_SUCCESS(NtStatus) ) {
  3634. if ( Options & SCE_RSOP_CALLBACK){
  3635. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  3636. RtlNtStatusToDosError(NtStatus),
  3637. NULL,
  3638. PrivLowRightAdd,
  3639. PrivHighRightAdd);
  3640. }
  3641. if ( RtlNtStatusToDosError(NtStatus) != ERROR_ALREADY_EXISTS ){
  3642. return(NtStatus);
  3643. }
  3644. }
  3645. }
  3646. //
  3647. // Remove
  3648. //
  3649. if ( PrivLowRightRemove != 0 || PrivHighRightRemove != 0 ) {
  3650. NtStatus = ScepAddOrRemoveAccountRights(
  3651. PolicyHandle,
  3652. AccountSid,
  3653. FALSE,
  3654. PrivLowRightRemove,
  3655. PrivHighRightRemove
  3656. );
  3657. if ( !NT_SUCCESS(NtStatus) ){
  3658. if ( Options & SCE_RSOP_CALLBACK){
  3659. ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
  3660. RtlNtStatusToDosError(NtStatus),
  3661. NULL,
  3662. PrivLowRightRemove,
  3663. PrivHighRightRemove);
  3664. }
  3665. return(NtStatus);
  3666. }
  3667. }
  3668. return (NtStatus);
  3669. }
  3670. NTSTATUS
  3671. ScepAddOrRemoveAccountRights(
  3672. IN LSA_HANDLE PolicyHandle,
  3673. IN PSID AccountSid,
  3674. IN BOOL AddOrRemove,
  3675. IN DWORD PrivLowAdjust,
  3676. IN DWORD PrivHighAdjust
  3677. )
  3678. /* ++
  3679. Routine Description:
  3680. This routine add or remove the privilege/rights as specified in PrivAdjust
  3681. to the account referenced by AccountSid.
  3682. Arguments:
  3683. PolicyHandle - Lsa Policy Domain handle
  3684. AccountSid - The SID for the account
  3685. AddOrRemove - TRUE = Add, FALSE = remove
  3686. PrivAdjust - Privilege/Rights to add or remove
  3687. Return value:
  3688. NTSTATUS
  3689. -- */
  3690. {
  3691. NTSTATUS NtStatus=STATUS_SUCCESS;
  3692. DWORD cTotal;
  3693. DWORD i, cnt;
  3694. PLSA_UNICODE_STRING UserRightAdjust=NULL;
  3695. //
  3696. // count how many privileges/rights to adjust
  3697. //
  3698. i = PrivLowAdjust;
  3699. cTotal = 0;
  3700. while ( i != 0 ) {
  3701. if ( i & 0x1 )
  3702. cTotal++;
  3703. i /= 2;
  3704. }
  3705. i = PrivHighAdjust;
  3706. while ( i != 0 ) {
  3707. if ( i & 0x1 )
  3708. cTotal++;
  3709. i /= 2;
  3710. }
  3711. if ( cTotal > 0 ) {
  3712. //
  3713. // add names in privileges table
  3714. //
  3715. UserRightAdjust = (PLSA_UNICODE_STRING)ScepAlloc( (UINT)0,
  3716. cTotal*sizeof(LSA_UNICODE_STRING));
  3717. if ( UserRightAdjust == NULL ) {
  3718. NtStatus = STATUS_NO_MEMORY;
  3719. goto Done;
  3720. }
  3721. for (i = 0, cnt=0; i < cPrivCnt; i++)
  3722. if ( ( ( i < 32 ) && ( PrivLowAdjust & (1 << i) ) ) ||
  3723. ( ( i >= 32 ) && ( PrivHighAdjust & (1 << ( i-32 )) ) ) ) {
  3724. RtlInitUnicodeString(&(UserRightAdjust[cnt]), SCE_Privileges[i].Name);
  3725. if (AddOrRemove)
  3726. ScepLogOutput3(2,0, SCEDLL_SCP_ADD, SCE_Privileges[i].Name);
  3727. else
  3728. ScepLogOutput3(2,0, SCEDLL_SCP_REMOVE, SCE_Privileges[i].Name);
  3729. cnt++;
  3730. }
  3731. if (AddOrRemove) {
  3732. // add
  3733. NtStatus = LsaAddAccountRights(
  3734. PolicyHandle,
  3735. AccountSid,
  3736. UserRightAdjust,
  3737. cTotal
  3738. );
  3739. } else {
  3740. // remove
  3741. NtStatus = LsaRemoveAccountRights(
  3742. PolicyHandle,
  3743. AccountSid,
  3744. FALSE,
  3745. UserRightAdjust,
  3746. cTotal
  3747. );
  3748. }
  3749. }
  3750. Done:
  3751. if (UserRightAdjust != NULL)
  3752. ScepFree(UserRightAdjust);
  3753. return(NtStatus);
  3754. }
  3755. NTSTATUS
  3756. ScepValidateUserInGroups(
  3757. IN SAM_HANDLE DomainHandle,
  3758. IN SAM_HANDLE BuiltinDomainHandle,
  3759. IN PSID DomainSid,
  3760. IN UNICODE_STRING UserName,
  3761. IN ULONG UserId,
  3762. IN PSCE_NAME_LIST pGroupsToCheck
  3763. )
  3764. /* ++
  3765. Routine Description:
  3766. This routine validates the user's group membership to the list of groups.
  3767. If the user is not in one of the groups, add it to the group. If a group
  3768. has more members, just ignore.
  3769. Arguments:
  3770. DomainHandle - The SAM handle of the SAM account domain
  3771. BuiltinDomainHandle - The SAM handle of the SAM builtin domain
  3772. DomainSid - The SID of the account domain
  3773. UserName - The user's name in UNICODE_STRING
  3774. UserId - The user's relative ID
  3775. pGroupsToCheck - The group list to check for this user
  3776. Return value:
  3777. NTSTATUS
  3778. -- */
  3779. {
  3780. NTSTATUS NtStatus;
  3781. SAM_HANDLE UserHandle=NULL;
  3782. PSID AccountSid=NULL;
  3783. PSCE_NAME_LIST GroupList=NULL,
  3784. pGroup, pGroup2;
  3785. BOOL FirstTime=TRUE;
  3786. if ( pGroupsToCheck == NULL )
  3787. return(ERROR_SUCCESS);
  3788. NtStatus = SamOpenUser(
  3789. DomainHandle,
  3790. USER_READ | USER_EXECUTE,
  3791. UserId,
  3792. &UserHandle
  3793. );
  3794. if ( !NT_SUCCESS(NtStatus) ) {
  3795. ScepLogOutput3(1,RtlNtStatusToDosError(NtStatus),
  3796. SCEDLL_USER_OBJECT);
  3797. return(NtStatus);
  3798. }
  3799. //
  3800. // Get user's SID
  3801. //
  3802. NtStatus = ScepDomainIdToSid(
  3803. DomainSid,
  3804. UserId,
  3805. &AccountSid
  3806. );
  3807. if ( !NT_SUCCESS(NtStatus) )
  3808. goto Done;
  3809. //
  3810. // get all current assigned groups of this user.
  3811. //
  3812. NtStatus = ScepGetGroupsForAccount(
  3813. DomainHandle,
  3814. BuiltinDomainHandle,
  3815. UserHandle,
  3816. AccountSid,
  3817. &GroupList
  3818. );
  3819. if ( !NT_SUCCESS(NtStatus) )
  3820. goto Done;
  3821. UNICODE_STRING uName;
  3822. PWSTR pTemp;
  3823. for ( pGroup=pGroupsToCheck; pGroup != NULL; pGroup = pGroup->Next ) {
  3824. //
  3825. // should expect pGroup->Name has domain prefix
  3826. //
  3827. pTemp = wcschr(pGroup->Name, L'\\');
  3828. if ( pTemp ) {
  3829. //
  3830. // check if this group is from a different domain
  3831. //
  3832. uName.Buffer = pGroup->Name;
  3833. uName.Length = ((USHORT)(pTemp-pGroup->Name))*sizeof(TCHAR);
  3834. if ( !ScepIsDomainLocal(&uName) ) {
  3835. ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pGroup->Name);
  3836. continue;
  3837. }
  3838. pTemp++;
  3839. } else {
  3840. pTemp = pGroup->Name;
  3841. }
  3842. for ( pGroup2=GroupList; pGroup2 != NULL; pGroup2 = pGroup2->Next ) {
  3843. if ( _wcsnicmp(pGroup2->Name, pTemp, wcslen(pTemp)) == 0)
  3844. break;
  3845. }
  3846. if ( pGroup2 == NULL ) {
  3847. //
  3848. // Did not find the group. Add the user to it (pGroup->Name)
  3849. //
  3850. if (FirstTime)
  3851. ScepLogOutput3(2, 0, SCEDLL_SCP_ADDTO, pGroup->Name );
  3852. FirstTime = FALSE;
  3853. NtStatus = ScepAddUserToGroup(
  3854. DomainHandle,
  3855. BuiltinDomainHandle,
  3856. UserId,
  3857. AccountSid,
  3858. pTemp // pGroup->Name
  3859. );
  3860. if ( !NT_SUCCESS(NtStatus) && NtStatus != STATUS_NONE_MAPPED ) {
  3861. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  3862. SCEDLL_SCP_ERROR_ADDTO, pGroup->Name);
  3863. goto Done;
  3864. }
  3865. }
  3866. }
  3867. Done:
  3868. SamCloseHandle(UserHandle);
  3869. if (AccountSid != NULL)
  3870. ScepFree(AccountSid);
  3871. ScepFreeNameList(GroupList);
  3872. return(NtStatus);
  3873. }
  3874. NTSTATUS
  3875. ScepAddUserToGroup(
  3876. IN SAM_HANDLE DomainHandle,
  3877. IN SAM_HANDLE BuiltinDomainHandle,
  3878. IN ULONG UserId,
  3879. IN PSID AccountSid,
  3880. IN PWSTR GroupName
  3881. )
  3882. /* ++
  3883. Routine Description:
  3884. Arguments:
  3885. Return value:
  3886. NTSTATUS
  3887. -- */
  3888. {
  3889. NTSTATUS NtStatus=ERROR_SUCCESS;
  3890. SAM_HANDLE ThisDomain=DomainHandle;
  3891. UNICODE_STRING Name;
  3892. PULONG GrpId=NULL;
  3893. PSID_NAME_USE GrpUse=NULL;
  3894. SAM_HANDLE GroupHandle=NULL;
  3895. // initialize a UNICODE_STRING for the group name
  3896. RtlInitUnicodeString(&Name, GroupName);
  3897. //
  3898. // lookup the group name in account domain first
  3899. //
  3900. NtStatus = SamLookupNamesInDomain(
  3901. DomainHandle,
  3902. 1,
  3903. &Name,
  3904. &GrpId,
  3905. &GrpUse
  3906. );
  3907. if ( NtStatus == STATUS_NONE_MAPPED ) {
  3908. //
  3909. // not found in account domain. Lookup in the builtin domain
  3910. //
  3911. NtStatus = SamLookupNamesInDomain(
  3912. BuiltinDomainHandle,
  3913. 1,
  3914. &Name,
  3915. &GrpId,
  3916. &GrpUse
  3917. );
  3918. ThisDomain=BuiltinDomainHandle;
  3919. }
  3920. if ( !NT_SUCCESS(NtStatus) )
  3921. return(NtStatus);
  3922. //
  3923. // add the user to the group/alias
  3924. //
  3925. if (GrpUse != NULL){
  3926. switch ( GrpUse[0] ) {
  3927. case SidTypeGroup:
  3928. NtStatus = SamOpenGroup(
  3929. ThisDomain,
  3930. GROUP_ADD_MEMBER,
  3931. GrpId[0],
  3932. &GroupHandle
  3933. );
  3934. if ( NT_SUCCESS(NtStatus) ) {
  3935. NtStatus = SamAddMemberToGroup(
  3936. GroupHandle,
  3937. UserId,
  3938. SE_GROUP_MANDATORY |
  3939. SE_GROUP_ENABLED_BY_DEFAULT |
  3940. SE_GROUP_ENABLED
  3941. );
  3942. }
  3943. break;
  3944. case SidTypeAlias:
  3945. NtStatus = SamOpenAlias(
  3946. ThisDomain,
  3947. ALIAS_ADD_MEMBER,
  3948. GrpId[0],
  3949. &GroupHandle
  3950. );
  3951. if ( NT_SUCCESS(NtStatus) ) {
  3952. NtStatus = SamAddMemberToAlias(
  3953. GroupHandle,
  3954. AccountSid
  3955. );
  3956. }
  3957. break;
  3958. default:
  3959. NtStatus = STATUS_DATA_ERROR;
  3960. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  3961. SCEDLL_NOT_GROUP, GroupName);
  3962. goto Done;
  3963. }
  3964. }
  3965. Done:
  3966. SamFreeMemory(GrpId);
  3967. SamFreeMemory(GrpUse);
  3968. SamCloseHandle(GroupHandle);
  3969. return(NtStatus);
  3970. }
  3971. SCESTATUS
  3972. ScepConfigureGroupMembership(
  3973. IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
  3974. IN DWORD ConfigOptions
  3975. )
  3976. /* ++
  3977. Routine Description:
  3978. This routine configure restricted group's membership which includes members
  3979. in the group and groups this group belongs to ( Currently a global group can
  3980. only belong to a local group and a local group can't be a member of other
  3981. groups. But this will change in the future). Members in the group are
  3982. configured exactly as the pMembers list in the restricted group. The group
  3983. is only validated (added) as a member of the MemberOf group list. Other
  3984. existing members in those groups won't be removed.
  3985. The restricted groups are specified in the SCP profile by group name. It
  3986. could be a global group, or a alias, but must be defined on the local system.
  3987. Arguments:
  3988. pGroupMembership - the restricted group list to configure
  3989. Return Value:
  3990. SCESTATUS_SUCCESS
  3991. SCESTATUS_NOT_ENOUGH_RESOURCE
  3992. :
  3993. -- */
  3994. {
  3995. NTSTATUS NtStatus;
  3996. NTSTATUS SaveStat=STATUS_SUCCESS;
  3997. PSCE_GROUP_MEMBERSHIP pGroup;
  3998. SAM_HANDLE ServerHandle=NULL,
  3999. DomainHandle=NULL,
  4000. BuiltinDomainHandle=NULL;
  4001. PSID DomainSid=NULL,
  4002. BuiltInDomainSid=NULL;
  4003. LSA_HANDLE PolicyHandle=NULL;
  4004. SAM_HANDLE ThisDomain=NULL;
  4005. PSID ThisDomainSid=NULL;
  4006. UNICODE_STRING Name;
  4007. PULONG GrpId=NULL;
  4008. PSID_NAME_USE GrpUse=NULL;
  4009. PSID GrpSid=NULL;
  4010. DWORD GroupLen;
  4011. DWORD rc;
  4012. SCESTATUS scercSave = SCESTATUS_SUCCESS;
  4013. DWORD nGroupCount=0;
  4014. PSCESECTION hSectionDomain=NULL;
  4015. PSCESECTION hSectionTattoo=NULL;
  4016. PWSTR GroupSidString=NULL;
  4017. if (pGroupMembership == NULL) {
  4018. ScepPostProgress(TICKS_GROUPS,
  4019. AREA_GROUP_MEMBERSHIP,
  4020. NULL);
  4021. return(SCESTATUS_SUCCESS);
  4022. }
  4023. //
  4024. // open LSA policy
  4025. //
  4026. NtStatus = ScepOpenLsaPolicy(
  4027. POLICY_VIEW_LOCAL_INFORMATION |
  4028. POLICY_VIEW_AUDIT_INFORMATION |
  4029. POLICY_GET_PRIVATE_INFORMATION |
  4030. POLICY_LOOKUP_NAMES,
  4031. // GENERIC_ALL,
  4032. &PolicyHandle,
  4033. TRUE
  4034. );
  4035. if (NtStatus != STATUS_SUCCESS) {
  4036. rc = RtlNtStatusToDosError( NtStatus );
  4037. ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY);
  4038. ScepPostProgress(TICKS_GROUPS,
  4039. AREA_GROUP_MEMBERSHIP,
  4040. NULL);
  4041. return(ScepDosErrorToSceStatus(rc));
  4042. }
  4043. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4044. ScepIsSystemShutDown() ) {
  4045. SaveStat = STATUS_NOT_SUPPORTED;
  4046. goto Done;
  4047. }
  4048. //
  4049. // Open SAM domain
  4050. //
  4051. NtStatus = ScepOpenSamDomain(
  4052. SAM_SERVER_ALL_ACCESS,
  4053. MAXIMUM_ALLOWED,
  4054. &ServerHandle,
  4055. &DomainHandle,
  4056. &DomainSid,
  4057. &BuiltinDomainHandle,
  4058. &BuiltInDomainSid
  4059. );
  4060. if ( !NT_SUCCESS(NtStatus) ) {
  4061. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4062. SCEDLL_ACCOUNT_DOMAIN);
  4063. SaveStat = NtStatus;
  4064. goto Done;
  4065. }
  4066. //
  4067. // open policy/tattoo tables
  4068. //
  4069. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4070. ( ProductType != NtProductLanManNt ) ) {
  4071. ScepTattooOpenPolicySections(
  4072. hProfile,
  4073. szGroupMembership,
  4074. &hSectionDomain,
  4075. &hSectionTattoo
  4076. );
  4077. }
  4078. //
  4079. // configure each group
  4080. //
  4081. for ( pGroup=pGroupMembership; pGroup != NULL; pGroup = pGroup->Next ) {
  4082. //
  4083. // Get this group's ID and SID
  4084. // initialize a UNICODE_STRING for the group name
  4085. //
  4086. if ( (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS ) &&
  4087. (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF ) ) {
  4088. // it's not possible to get invalid tattoo group values into the
  4089. // tattoo table so we don't handle tattoo value here
  4090. continue;
  4091. }
  4092. if ( (ProductType == NtProductLanManNt) &&
  4093. (pGroup->Status & SCE_GROUP_STATUS_DONE_IN_DS) ) {
  4094. //
  4095. // this one is already done by DS
  4096. //
  4097. nGroupCount++;
  4098. continue;
  4099. }
  4100. ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, pGroup->GroupName);
  4101. if ( nGroupCount < TICKS_GROUPS ) {
  4102. ScepPostProgress(1, AREA_GROUP_MEMBERSHIP, pGroup->GroupName);
  4103. nGroupCount++;
  4104. }
  4105. LPTSTR pTemp = wcschr(pGroup->GroupName, L'\\');
  4106. if ( pTemp ) {
  4107. //
  4108. // there is a domain name, check it with computer name
  4109. //
  4110. UNICODE_STRING uName;
  4111. uName.Buffer = pGroup->GroupName;
  4112. uName.Length = ((USHORT)(pTemp-pGroup->GroupName))*sizeof(TCHAR);
  4113. if ( !ScepIsDomainLocal(&uName) ) {
  4114. // on member machines we support memberof for domain groups
  4115. if(ProductType != NtProductLanManNt)
  4116. goto memberof;
  4117. ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pGroup->GroupName);
  4118. rc = SCESTATUS_INVALID_DATA;
  4119. continue;
  4120. }
  4121. pTemp++;
  4122. } else {
  4123. pTemp = pGroup->GroupName;
  4124. }
  4125. RtlInitUnicodeString(&Name, pTemp);
  4126. GroupLen = wcslen(pTemp);
  4127. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4128. ScepIsSystemShutDown() ) {
  4129. SaveStat = STATUS_NOT_SUPPORTED;
  4130. break;
  4131. }
  4132. //
  4133. // lookup the group name in account domain first
  4134. //
  4135. NtStatus = SamLookupNamesInDomain(
  4136. DomainHandle,
  4137. 1,
  4138. &Name,
  4139. &GrpId,
  4140. &GrpUse
  4141. );
  4142. ThisDomain = DomainHandle;
  4143. ThisDomainSid = DomainSid;
  4144. if ( NtStatus == STATUS_NONE_MAPPED ) {
  4145. //
  4146. // not found in account domain. Lookup in the builtin domain (maybe a alias)
  4147. //
  4148. NtStatus = SamLookupNamesInDomain(
  4149. BuiltinDomainHandle,
  4150. 1,
  4151. &Name,
  4152. &GrpId,
  4153. &GrpUse
  4154. );
  4155. ThisDomain=BuiltinDomainHandle;
  4156. ThisDomainSid = BuiltInDomainSid;
  4157. }
  4158. if ( !NT_SUCCESS(NtStatus) ) {
  4159. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4160. SCEDLL_NO_MAPPINGS, pGroup->GroupName);
  4161. SaveStat = NtStatus;
  4162. if (ConfigOptions & SCE_RSOP_CALLBACK)
  4163. ScepRsopLog(SCE_RSOP_GROUP_INFO, RtlNtStatusToDosError(NtStatus), pGroup->GroupName, 0, 0);
  4164. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4165. ( ProductType != NtProductLanManNt ) ) {
  4166. ScepTattooManageOneMemberListValue(
  4167. hSectionDomain,
  4168. hSectionTattoo,
  4169. pTemp,
  4170. GroupLen,
  4171. NULL,
  4172. TRUE,
  4173. ERROR_NONE_MAPPED
  4174. );
  4175. }
  4176. // goto Done;
  4177. continue;
  4178. }
  4179. //
  4180. // Get the group's account SID
  4181. //
  4182. NtStatus = ScepDomainIdToSid(
  4183. ThisDomainSid,
  4184. GrpId[0],
  4185. &GrpSid
  4186. );
  4187. if ( !NT_SUCCESS(NtStatus) ) {
  4188. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4189. SCEDLL_NO_MAPPINGS, pGroup->GroupName);
  4190. SaveStat = NtStatus;
  4191. if (ConfigOptions & SCE_RSOP_CALLBACK)
  4192. ScepRsopLog(SCE_RSOP_GROUP_INFO, RtlNtStatusToDosError(NtStatus), pGroup->GroupName, 0, 0);
  4193. goto NextGroup;
  4194. }
  4195. if ( GrpId[0] == DOMAIN_GROUP_RID_USERS ) {
  4196. //
  4197. // do not configure this one
  4198. // there should never be tattoo values for this setting
  4199. // so we don't check tattoo values here
  4200. //
  4201. goto NextGroup;
  4202. }
  4203. if ( GrpId[0] == DOMAIN_ALIAS_RID_ADMINS ) {
  4204. //
  4205. // local builtin administrators alias, make sure local Administrator
  4206. // account is in the members list, if it's not, add it there
  4207. //
  4208. (VOID) ScepAddAdministratorToThisList(
  4209. DomainHandle,
  4210. &(pGroup->pMembers)
  4211. );
  4212. }
  4213. //
  4214. // members
  4215. //
  4216. if ( !(pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS) ) {
  4217. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) ) {
  4218. DWORD rc2 = ScepConvertSidToPrefixStringSid(GrpSid, &GroupSidString);
  4219. if ( ERROR_SUCCESS != rc2 ) {
  4220. ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_SETTING,rc2,pGroup->GroupName);
  4221. GroupSidString = NULL;
  4222. }
  4223. }
  4224. switch ( GrpUse[0] ) {
  4225. case SidTypeGroup:
  4226. NtStatus = ScepConfigureMembersOfGroup(
  4227. hSectionDomain,
  4228. hSectionTattoo,
  4229. ThisDomain,
  4230. ThisDomainSid,
  4231. GrpId[0],
  4232. GrpSid,
  4233. pGroup->GroupName,
  4234. GroupSidString,
  4235. pGroup->pMembers,
  4236. ConfigOptions
  4237. );
  4238. break;
  4239. case SidTypeAlias:
  4240. NtStatus = ScepConfigureMembersOfAlias(
  4241. hSectionDomain,
  4242. hSectionTattoo,
  4243. ThisDomain,
  4244. ThisDomainSid,
  4245. PolicyHandle,
  4246. GrpId[0],
  4247. GrpSid,
  4248. pGroup->GroupName,
  4249. GroupSidString,
  4250. pGroup->pMembers,
  4251. ConfigOptions
  4252. );
  4253. break;
  4254. case SidTypeUser:
  4255. if ( pGroup->pMembers != NULL ) {
  4256. ScepLogOutput3(1, 0, SCEDLL_ERROR_USER_MEMBER);
  4257. NtStatus = STATUS_DATA_ERROR;
  4258. }
  4259. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4260. ( ProductType != NtProductLanManNt ) &&
  4261. GroupSidString ) {
  4262. ScepTattooManageOneMemberListValue(
  4263. hSectionDomain,
  4264. hSectionTattoo,
  4265. GroupSidString,
  4266. wcslen(GroupSidString),
  4267. NULL,
  4268. TRUE,
  4269. ERROR_NONE_MAPPED
  4270. );
  4271. }
  4272. break;
  4273. default:
  4274. NtStatus = STATUS_DATA_ERROR;
  4275. ScepLogOutput3(1, 0, SCEDLL_NOT_GROUP, pGroup->GroupName);
  4276. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4277. ( ProductType != NtProductLanManNt ) &&
  4278. GroupSidString ) {
  4279. ScepTattooManageOneMemberListValue(
  4280. hSectionDomain,
  4281. hSectionTattoo,
  4282. GroupSidString,
  4283. wcslen(GroupSidString),
  4284. NULL,
  4285. TRUE,
  4286. ERROR_NONE_MAPPED
  4287. );
  4288. }
  4289. }
  4290. if (ConfigOptions & SCE_RSOP_CALLBACK)
  4291. ScepRsopLog(
  4292. SCE_RSOP_GROUP_INFO,
  4293. RtlNtStatusToDosError(NtStatus),
  4294. pGroup->GroupName,0,0);
  4295. if ( !NT_SUCCESS(NtStatus) )
  4296. SaveStat = NtStatus;
  4297. if ( GroupSidString ) {
  4298. ScepFree(GroupSidString);
  4299. GroupSidString = NULL;
  4300. }
  4301. }
  4302. memberof:
  4303. //
  4304. // member of
  4305. //
  4306. if ( !(pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  4307. if (!GrpUse)
  4308. {
  4309. // Account not found locally. Handle only the case of
  4310. // groups and aliases memberof aliases.
  4311. PLSA_REFERENCED_DOMAIN_LIST RefDomains=NULL;
  4312. PLSA_TRANSLATED_SID2 Sids=NULL;
  4313. NtStatus = ScepLsaLookupNames2(
  4314. PolicyHandle,
  4315. 0,
  4316. pGroup->GroupName,
  4317. &RefDomains,
  4318. &Sids
  4319. );
  4320. if (NT_SUCCESS(NtStatus) &&
  4321. Sids &&
  4322. (Sids[0].Use == SidTypeGroup ||
  4323. Sids[0].Use == SidTypeAlias)) {
  4324. SCESTATUS scerc = ScepValidateGroupInAliases(
  4325. DomainHandle,
  4326. BuiltinDomainHandle,
  4327. hSectionTattoo,
  4328. PolicyHandle,
  4329. Sids[0].Sid,
  4330. pGroup->pMemberOf,
  4331. ((ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4332. ( ProductType != NtProductLanManNt ))?true:false
  4333. );
  4334. if(SCESTATUS_SUCCESS != scerc)
  4335. scercSave = scerc;
  4336. } else {
  4337. ScepLogOutput3(1, 0, SCEDLL_CANNOT_FIND, pGroup->GroupName);
  4338. }
  4339. if ( Sids ) {
  4340. LsaFreeMemory(Sids);
  4341. }
  4342. if ( RefDomains ) {
  4343. LsaFreeMemory(RefDomains);
  4344. }
  4345. } else if (pGroup->pMemberOf) {
  4346. switch ( GrpUse[0] ) {
  4347. case SidTypeGroup:
  4348. {
  4349. //
  4350. // group can be members of alias only
  4351. //
  4352. SCESTATUS scerc = ScepValidateGroupInAliases(
  4353. DomainHandle,
  4354. BuiltinDomainHandle,
  4355. hSectionTattoo,
  4356. PolicyHandle,
  4357. GrpSid,
  4358. pGroup->pMemberOf,
  4359. ((ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4360. ( ProductType != NtProductLanManNt ))?true:false
  4361. );
  4362. if(SCESTATUS_SUCCESS != scerc)
  4363. scercSave = scerc;
  4364. }
  4365. break;
  4366. case SidTypeUser:
  4367. NtStatus = ScepValidateUserInGroups(
  4368. DomainHandle,
  4369. BuiltinDomainHandle,
  4370. ThisDomainSid,
  4371. Name,
  4372. GrpId[0],
  4373. pGroup->pMemberOf
  4374. );
  4375. break;
  4376. case SidTypeAlias:
  4377. NtStatus = STATUS_DATA_ERROR;
  4378. ScepLogOutput3(1, 0, SCEDLL_ERROR_ALIAS_MEMBER);
  4379. }
  4380. }
  4381. if ( !NT_SUCCESS(NtStatus) )
  4382. SaveStat = NtStatus;
  4383. }
  4384. NextGroup:
  4385. //
  4386. // free memory for this group
  4387. //
  4388. SamFreeMemory(GrpId);
  4389. GrpId = NULL;
  4390. SamFreeMemory(GrpUse);
  4391. GrpUse = NULL;
  4392. ScepFree(GrpSid);
  4393. GrpSid = NULL;
  4394. }
  4395. Done:
  4396. if ( GrpId != NULL )
  4397. SamFreeMemory(GrpId);
  4398. if ( GrpUse != NULL )
  4399. SamFreeMemory(GrpUse);
  4400. if ( GrpSid != NULL )
  4401. ScepFree(GrpSid);
  4402. // close sam handles
  4403. SamCloseHandle(DomainHandle);
  4404. SamCloseHandle(BuiltinDomainHandle);
  4405. SamCloseHandle(ServerHandle);
  4406. if ( DomainSid != NULL )
  4407. SamFreeMemory(DomainSid);
  4408. if ( BuiltInDomainSid != NULL )
  4409. SamFreeMemory(BuiltInDomainSid);
  4410. LsaClose(PolicyHandle);
  4411. if ( nGroupCount < TICKS_GROUPS ) {
  4412. ScepPostProgress(TICKS_GROUPS-nGroupCount,
  4413. AREA_GROUP_MEMBERSHIP,
  4414. NULL);
  4415. }
  4416. SceJetCloseSection(&hSectionDomain, TRUE);
  4417. SceJetCloseSection(&hSectionTattoo, TRUE);
  4418. rc = RtlNtStatusToDosError(SaveStat);
  4419. if(STATUS_SUCCESS != rc)
  4420. scercSave = ScepDosErrorToSceStatus(rc);
  4421. return( scercSave );
  4422. }
  4423. NTSTATUS
  4424. ScepConfigureMembersOfGroup(
  4425. IN PSCESECTION hSectionDomain,
  4426. IN PSCESECTION hSectionTattoo,
  4427. IN SAM_HANDLE DomainHandle,
  4428. IN PSID ThisDomainSid,
  4429. IN ULONG GrpId,
  4430. IN PSID GrpSid,
  4431. IN PWSTR GrpName,
  4432. IN PWSTR GroupSidString,
  4433. IN PSCE_NAME_LIST pMembers,
  4434. IN DWORD ConfigOptions
  4435. )
  4436. /* ++
  4437. Routine Description:
  4438. This routine configure a group's members as specified in the SCP profile (
  4439. pMembers ). Less members are added and extra members are removed.
  4440. Arguments:
  4441. DomainHandle - the SAM domain's handle
  4442. GrpId - the group's RID
  4443. pMembers - the members list as specified in the SCP profile
  4444. Return Value:
  4445. NTSTATUS return SAM APIs
  4446. -- */
  4447. {
  4448. NTSTATUS NtStatus;
  4449. PUNICODE_STRING MemberNames=NULL;
  4450. PULONG MemberRids=NULL;
  4451. PSID_NAME_USE MemberUse=NULL;
  4452. ULONG MemberCount=0;
  4453. SAM_HANDLE GroupHandle=NULL;
  4454. PULONG CurrentRids=NULL;
  4455. PULONG Attributes=NULL;
  4456. ULONG CurrentCount=0;
  4457. DWORD i, j;
  4458. WCHAR MsgBuf[256];
  4459. PUNICODE_STRING pName=NULL;
  4460. PSID_NAME_USE pUse=NULL;
  4461. PSCE_NAME_LIST pMemberList=NULL;
  4462. BOOL bMemberQueried=FALSE;
  4463. /*
  4464. if ( pMembers == NULL )
  4465. return(STATUS_SUCCESS);
  4466. */
  4467. //
  4468. // Accept empty member list
  4469. // look up the members list first (all members should be within this domain
  4470. //
  4471. NtStatus = ScepLookupNamesInDomain(
  4472. DomainHandle,
  4473. pMembers,
  4474. &MemberNames,
  4475. &MemberRids,
  4476. &MemberUse,
  4477. &MemberCount
  4478. );
  4479. if ( !NT_SUCCESS(NtStatus) ) {
  4480. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4481. SCEDLL_ERROR_LOOKUP, pMembers ? pMembers->Name : L"");
  4482. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4483. ( ProductType != NtProductLanManNt ) &&
  4484. hSectionDomain && hSectionTattoo && GrpSid && GroupSidString &&
  4485. (NtStatus == STATUS_NONE_MAPPED)) {
  4486. ScepTattooManageOneMemberListValue(
  4487. hSectionDomain,
  4488. hSectionTattoo,
  4489. GroupSidString,
  4490. wcslen(GroupSidString),
  4491. NULL,
  4492. TRUE,
  4493. 0
  4494. );
  4495. }
  4496. return(NtStatus);
  4497. }
  4498. //
  4499. // open the group to get a handle
  4500. //
  4501. NtStatus = SamOpenGroup(
  4502. DomainHandle,
  4503. MAXIMUM_ALLOWED, // ? GROUP_ALL_ACCESS,
  4504. GrpId,
  4505. &GroupHandle
  4506. );
  4507. if ( !NT_SUCCESS(NtStatus) ) {
  4508. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4509. SCEDLL_ERROR_OPEN, L"");
  4510. goto Done;
  4511. }
  4512. //
  4513. // get current members of the group
  4514. //
  4515. NtStatus = SamGetMembersInGroup(
  4516. GroupHandle,
  4517. &CurrentRids,
  4518. &Attributes,
  4519. &CurrentCount
  4520. );
  4521. if ( !NT_SUCCESS(NtStatus) ) {
  4522. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4523. SCEDLL_ERROR_QUERY_INFO, L"");
  4524. goto Done;
  4525. }
  4526. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4527. ( ProductType != NtProductLanManNt ) &&
  4528. hSectionDomain && hSectionTattoo && GrpSid && GroupSidString ) {
  4529. DWORD rc = ScepTattooCurrentGroupMembers(ThisDomainSid,
  4530. NULL, // GrpSid not needed
  4531. SidTypeGroup,
  4532. CurrentRids,
  4533. NULL,
  4534. CurrentCount,
  4535. &pMemberList
  4536. );
  4537. if ( ERROR_SUCCESS != rc ) {
  4538. //
  4539. // something is wrong when building the list
  4540. // this shoudln't happen unless out of memory etc.
  4541. //
  4542. ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_QUERY,rc,GrpName);
  4543. } else
  4544. bMemberQueried=TRUE;
  4545. }
  4546. //
  4547. // Compare the member ids with the current ids for adding
  4548. //
  4549. for ( i=0; i<MemberCount; i++ ) {
  4550. #ifdef SCE_DBG
  4551. printf("process member %x for adding\n", MemberRids[i]);
  4552. #endif
  4553. if (MemberUse[i] == SidTypeInvalid ||
  4554. MemberUse[i] == SidTypeUnknown ||
  4555. MemberUse[i] == SidTypeDeletedAccount)
  4556. continue;
  4557. for ( j=0; j<CurrentCount; j++)
  4558. if ( MemberRids[i] == CurrentRids[j] )
  4559. break;
  4560. if ( j >= CurrentCount) {
  4561. //
  4562. // Add this member
  4563. //
  4564. memset(MsgBuf, '\0', 512);
  4565. wcsncat(MsgBuf, MemberNames[i].Buffer, MemberNames[i].Length/2);
  4566. ScepLogOutput3(2,0, SCEDLL_SCP_ADD, MsgBuf);
  4567. NtStatus = SamAddMemberToGroup(
  4568. GroupHandle,
  4569. MemberRids[i],
  4570. 0
  4571. );
  4572. if ( !NT_SUCCESS(NtStatus) ) {
  4573. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4574. SCEDLL_SCP_ERROR_ADD, MsgBuf);
  4575. if ( NtStatus == STATUS_NO_SUCH_MEMBER|| NtStatus == STATUS_OBJECT_NAME_NOT_FOUND ) {
  4576. NtStatus = STATUS_SUCCESS;
  4577. continue;
  4578. }
  4579. goto Done;
  4580. }
  4581. }
  4582. }
  4583. //
  4584. // Compare the member ids with the current ids for removing
  4585. //
  4586. for ( i=0; i<CurrentCount; i++ ) {
  4587. #ifdef SCE_DBG
  4588. printf("process member %x for removing\n", CurrentRids[i]);
  4589. #endif
  4590. for ( j=0; j<MemberCount; j++)
  4591. if ( CurrentRids[i] == MemberRids[j] )
  4592. break;
  4593. if ( j >= MemberCount) {
  4594. //
  4595. // Find the member name
  4596. //
  4597. memset(MsgBuf, '\0', 512);
  4598. pName=NULL;
  4599. pUse=NULL;
  4600. if ( NT_SUCCESS( SamLookupIdsInDomain(
  4601. DomainHandle,
  4602. 1,
  4603. &(CurrentRids[i]),
  4604. &pName,
  4605. &pUse
  4606. ) ) ) {
  4607. if ( pName != NULL ) {
  4608. wcsncat(MsgBuf, pName[0].Buffer, pName[0].Length/2);
  4609. } else
  4610. swprintf(MsgBuf, L"(Rid=%d)", CurrentRids[i]);
  4611. if ( pName != NULL )
  4612. SamFreeMemory( pName );
  4613. if ( pUse != NULL )
  4614. SamFreeMemory( pUse );
  4615. } else
  4616. swprintf(MsgBuf, L"(Rid=%d) ", CurrentRids[i]);
  4617. //
  4618. // remove this member
  4619. //
  4620. ScepLogOutput3(2,0, SCEDLL_SCP_REMOVE, MsgBuf);
  4621. NtStatus = SamRemoveMemberFromGroup(
  4622. GroupHandle,
  4623. CurrentRids[i]
  4624. );
  4625. if ( !NT_SUCCESS(NtStatus) ) {
  4626. if ( NtStatus == STATUS_SPECIAL_ACCOUNT )
  4627. ScepLogOutput3(2, RtlNtStatusToDosError(NtStatus),
  4628. SCEDLL_SCP_CANNOT_REMOVE,
  4629. MsgBuf);
  4630. else {
  4631. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4632. SCEDLL_SCP_ERROR_REMOVE, MsgBuf);
  4633. goto Done;
  4634. }
  4635. }
  4636. }
  4637. }
  4638. Done:
  4639. if ( MemberNames != NULL )
  4640. RtlFreeHeap(RtlProcessHeap(), 0, MemberNames);
  4641. if ( MemberRids != NULL )
  4642. SamFreeMemory( MemberRids );
  4643. if ( MemberUse != NULL )
  4644. SamFreeMemory( MemberUse );
  4645. if ( CurrentRids != NULL )
  4646. SamFreeMemory( CurrentRids );
  4647. if ( GroupHandle != NULL )
  4648. SamCloseHandle( GroupHandle );
  4649. //
  4650. // log the tattoo value
  4651. // if fail to get current value for the group, do not save the tattoo value
  4652. //
  4653. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4654. ( ProductType != NtProductLanManNt ) &&
  4655. hSectionDomain && hSectionTattoo &&
  4656. GrpSid && GroupSidString && bMemberQueried) {
  4657. ScepTattooManageOneMemberListValue(
  4658. hSectionDomain,
  4659. hSectionTattoo,
  4660. GroupSidString,
  4661. wcslen(GroupSidString),
  4662. pMemberList,
  4663. FALSE,
  4664. RtlNtStatusToDosError(NtStatus)
  4665. );
  4666. }
  4667. // free name list
  4668. if ( pMemberList )
  4669. ScepFreeNameList(pMemberList);
  4670. return(NtStatus);
  4671. }
  4672. NTSTATUS
  4673. ScepConfigureMembersOfAlias(
  4674. IN PSCESECTION hSectionDomain,
  4675. IN PSCESECTION hSectionTattoo,
  4676. IN SAM_HANDLE DomainHandle,
  4677. IN PSID DomainSid,
  4678. IN LSA_HANDLE PolicyHandle,
  4679. IN ULONG GrpId,
  4680. IN PSID GrpSid,
  4681. IN PWSTR GrpName,
  4682. IN PWSTR GroupSidString,
  4683. IN PSCE_NAME_LIST pMembers,
  4684. IN DWORD ConfigOptions
  4685. )
  4686. /* ++
  4687. Routine Description:
  4688. This routine configure a local group (alias) members as specified in the
  4689. SCP profile ( pMembers ). Less members are added and extra members are removed.
  4690. Arguments:
  4691. DomainHandle - The domains' handle
  4692. DomainSid - The sid for the domain
  4693. PolicyHandle - the LSA policy handle
  4694. GrpId - the alias's RID
  4695. pMembers - the members list as specified in the SCP profile
  4696. Return Value:
  4697. NTSTATUS return SAM APIs
  4698. -- */
  4699. {
  4700. NTSTATUS NtStatus=STATUS_SUCCESS;
  4701. ULONG MemberCount=0;
  4702. PUNICODE_STRING MemberNames=NULL;
  4703. PSID *Sids=NULL;
  4704. SAM_HANDLE GroupHandle=NULL;
  4705. PSID *CurrentSids=NULL;
  4706. ULONG CurrentCount=0;
  4707. DWORD i, j;
  4708. WCHAR MsgBuf[256];
  4709. PLSA_REFERENCED_DOMAIN_LIST pRefDomain;
  4710. PLSA_TRANSLATED_NAME pLsaName;
  4711. LPTSTR StringSid=NULL;
  4712. PSCE_NAME_LIST pMemberList=NULL;
  4713. BOOL bMemberQueried=FALSE;
  4714. /*
  4715. if ( pMembers == NULL )
  4716. return(STATUS_SUCCESS);
  4717. */
  4718. //
  4719. // Accept empty member list
  4720. // find Sids for the pMember list
  4721. //
  4722. NtStatus = ScepGetMemberListSids(
  4723. DomainSid,
  4724. PolicyHandle,
  4725. pMembers,
  4726. &MemberNames,
  4727. &Sids,
  4728. &MemberCount
  4729. );
  4730. if ( !NT_SUCCESS(NtStatus) ) {
  4731. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4732. SCEDLL_ERROR_LOOKUP, pMembers ? pMembers->Name : L"");
  4733. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4734. ( ProductType != NtProductLanManNt ) &&
  4735. hSectionDomain && hSectionTattoo && GrpSid && GroupSidString &&
  4736. (NtStatus == STATUS_NONE_MAPPED)) {
  4737. ScepTattooManageOneMemberListValue(
  4738. hSectionDomain,
  4739. hSectionTattoo,
  4740. GroupSidString,
  4741. wcslen(GroupSidString),
  4742. NULL,
  4743. TRUE,
  4744. 0
  4745. );
  4746. }
  4747. goto Done;
  4748. }
  4749. //
  4750. // open the alias to get a handle
  4751. //
  4752. NtStatus = SamOpenAlias(
  4753. DomainHandle,
  4754. MAXIMUM_ALLOWED, // ? ALIAS_ALL_ACCESS,
  4755. GrpId,
  4756. &GroupHandle
  4757. );
  4758. if ( !NT_SUCCESS(NtStatus) ) {
  4759. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4760. SCEDLL_ERROR_OPEN, L"");
  4761. goto Done;
  4762. }
  4763. //
  4764. // get current members of the alias
  4765. // members of alias may exist in everywhere
  4766. //
  4767. NtStatus = SamGetMembersInAlias(
  4768. GroupHandle,
  4769. &CurrentSids,
  4770. &CurrentCount
  4771. );
  4772. if ( !NT_SUCCESS(NtStatus) ) {
  4773. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4774. SCEDLL_ERROR_QUERY_INFO, L"");
  4775. goto Done;
  4776. }
  4777. //
  4778. // build current group membership into the list
  4779. //
  4780. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4781. ( ProductType != NtProductLanManNt ) &&
  4782. hSectionDomain && hSectionTattoo && GrpSid ) {
  4783. DWORD rc = ScepTattooCurrentGroupMembers(DomainSid,
  4784. GrpSid,
  4785. SidTypeAlias,
  4786. NULL,
  4787. CurrentSids,
  4788. CurrentCount,
  4789. &pMemberList
  4790. );
  4791. if ( ERROR_SUCCESS != rc ) {
  4792. //
  4793. // something is wrong when building the list
  4794. // this shoudln't happen unless out of memory etc.
  4795. //
  4796. ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_QUERY,rc,GrpName);
  4797. } else
  4798. bMemberQueried = TRUE;
  4799. }
  4800. //
  4801. // Compare the member sids with the current sids for adding
  4802. //
  4803. for ( i=0; i<MemberCount; i++ ) {
  4804. #ifdef SCE_DBG
  4805. printf("process member %d for adding\n", i);
  4806. #endif
  4807. memset(MsgBuf, '\0', 512);
  4808. wcsncpy(MsgBuf, MemberNames[i].Buffer, MemberNames[i].Length/2);
  4809. if ( Sids[i] == NULL ) {
  4810. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4811. SCEDLL_CANNOT_FIND, MsgBuf);
  4812. } else {
  4813. for ( j=0; j<CurrentCount; j++) {
  4814. if ( EqualSid(Sids[i], CurrentSids[j]) ) {
  4815. ScepLogOutput3(3,0, SCEDLL_STATUS_MATCH, MsgBuf);
  4816. break;
  4817. }
  4818. }
  4819. if ( j >= CurrentCount) {
  4820. //
  4821. // Add this member
  4822. //
  4823. ScepLogOutput3(2,0, SCEDLL_SCP_ADD, MsgBuf);
  4824. NtStatus = SamAddMemberToAlias(
  4825. GroupHandle,
  4826. Sids[i]
  4827. );
  4828. if ( !NT_SUCCESS(NtStatus) ) {
  4829. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4830. SCEDLL_SCP_ERROR_ADD, MsgBuf);
  4831. if ( NtStatus == STATUS_NO_SUCH_MEMBER || NtStatus == STATUS_OBJECT_NAME_NOT_FOUND) {
  4832. NtStatus = STATUS_SUCCESS;
  4833. continue;
  4834. }
  4835. goto Done;
  4836. }
  4837. }
  4838. }
  4839. }
  4840. //
  4841. // Compare the member ids with the current ids for adding
  4842. //
  4843. for ( i=0; i<CurrentCount; i++ ) {
  4844. #ifdef SCE_DBG
  4845. printf("process member %d for removing\n", i);
  4846. #endif
  4847. memset(MsgBuf, '\0', 512);
  4848. if ( ConvertSidToStringSid(
  4849. CurrentSids[i],
  4850. &StringSid
  4851. ) && StringSid ) {
  4852. swprintf(MsgBuf, L"SID: %s",StringSid);
  4853. LocalFree(StringSid);
  4854. StringSid = NULL;
  4855. } else {
  4856. ScepLogOutput3(3,GetLastError(), IDS_ERROR_CONVERT_SID);
  4857. swprintf(MsgBuf, L"Member %d",i);
  4858. }
  4859. for ( j=0; j<MemberCount; j++) {
  4860. if ( Sids[j] != NULL && EqualSid( CurrentSids[i], Sids[j]) ) {
  4861. ScepLogOutput3(3,0, SCEDLL_STATUS_MATCH, MsgBuf);
  4862. break;
  4863. }
  4864. }
  4865. if ( j >= MemberCount) {
  4866. //
  4867. // Find the member name
  4868. //
  4869. pRefDomain=NULL;
  4870. pLsaName=NULL;
  4871. if ( NT_SUCCESS( LsaLookupSids(
  4872. PolicyHandle,
  4873. 1,
  4874. &(CurrentSids[i]),
  4875. &pRefDomain,
  4876. &pLsaName
  4877. ) ) ) {
  4878. if ( pLsaName != NULL ) {
  4879. if ( pRefDomain != NULL && pRefDomain->Entries > 0 && pLsaName[0].Use != SidTypeWellKnownGroup &&
  4880. pRefDomain->Domains != NULL &&
  4881. pLsaName[0].DomainIndex != -1 &&
  4882. pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Buffer != NULL &&
  4883. ScepIsSidFromAccountDomain( pRefDomain->Domains[pLsaName[0].DomainIndex].Sid ) ) {
  4884. wcsncpy(MsgBuf, pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Buffer,
  4885. pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Length/2);
  4886. MsgBuf[pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Length/2] = L'\0';
  4887. wcscat(MsgBuf, L"\\");
  4888. }
  4889. wcsncat(MsgBuf, pLsaName[0].Name.Buffer, pLsaName[0].Name.Length/2);
  4890. }
  4891. }
  4892. if ( pRefDomain != NULL ) {
  4893. LsaFreeMemory(pRefDomain);
  4894. pRefDomain = NULL;
  4895. }
  4896. if ( pLsaName != NULL ){
  4897. LsaFreeMemory(pLsaName);
  4898. pLsaName = NULL;
  4899. }
  4900. //
  4901. // remove this member
  4902. //
  4903. ScepLogOutput3(2,0, SCEDLL_SCP_REMOVE, MsgBuf);
  4904. NtStatus = SamRemoveMemberFromAlias(
  4905. GroupHandle,
  4906. CurrentSids[i]
  4907. );
  4908. if ( !NT_SUCCESS(NtStatus) ) {
  4909. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  4910. SCEDLL_SCP_ERROR_REMOVE, MsgBuf);
  4911. goto Done;
  4912. }
  4913. }
  4914. }
  4915. Done:
  4916. if ( Sids != NULL ) {
  4917. for ( i=0; i<MemberCount; i++ ) {
  4918. if ( Sids[i] != NULL )
  4919. ScepFree( Sids[i] );
  4920. }
  4921. ScepFree( Sids );
  4922. }
  4923. if ( CurrentSids != NULL )
  4924. LsaFreeMemory(CurrentSids);
  4925. if ( MemberNames != NULL )
  4926. RtlFreeHeap(RtlProcessHeap(), 0, MemberNames);
  4927. if ( GroupHandle != NULL )
  4928. SamCloseHandle( GroupHandle );
  4929. //
  4930. // log the tattoo value
  4931. // if fail to get current value for the group, do not save the tattoo value
  4932. //
  4933. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  4934. ( ProductType != NtProductLanManNt ) &&
  4935. hSectionDomain && hSectionTattoo &&
  4936. GrpSid && GroupSidString && bMemberQueried) {
  4937. ScepTattooManageOneMemberListValue(
  4938. hSectionDomain,
  4939. hSectionTattoo,
  4940. GroupSidString,
  4941. wcslen(GroupSidString),
  4942. pMemberList,
  4943. FALSE,
  4944. RtlNtStatusToDosError(NtStatus)
  4945. );
  4946. }
  4947. // free name list
  4948. if ( pMemberList )
  4949. ScepFreeNameList(pMemberList);
  4950. return(NtStatus);
  4951. }
  4952. SCESTATUS
  4953. ScepParseListConvertStringSidsToNames(
  4954. IN LSA_HANDLE PolicyHandle,
  4955. IN OUT PSCE_NAME_LIST pNameList
  4956. )
  4957. /* ++
  4958. Routine Description:
  4959. This routine parses the group list (expected to contain only string sids in
  4960. *SID format) and replaces the strings sids with names in domain\name format.
  4961. Any string that cannot be mapped to a name will be NULL-ed out.
  4962. Arguments:
  4963. PolicyHandle - LSA handle
  4964. pNameList - list of groups
  4965. Return Value:
  4966. SCESTATUS - return success if all conversion succeeded or some of the SIDs
  4967. cannot be mapped to a name
  4968. -- */
  4969. {
  4970. SCESTATUS rc = SCESTATUS_SUCCESS;
  4971. PSCE_NAME_LIST pName = NULL;
  4972. for(pName = pNameList;
  4973. SCESTATUS_SUCCESS == rc && pName != NULL;
  4974. pName = pName->Next)
  4975. {
  4976. PSID pSid=NULL;
  4977. if(ConvertStringSidToSid(
  4978. (pName->Name)+1, // skip leading '*'
  4979. &pSid))
  4980. {
  4981. PWSTR pszName = NULL; // no need to free, returned in pNameList
  4982. DWORD dwLen = 0;
  4983. NTSTATUS NtStatus;
  4984. NtStatus = ScepConvertSidToName(
  4985. PolicyHandle,
  4986. pSid,
  4987. FALSE, // just name, no domain
  4988. &pszName,
  4989. &dwLen);
  4990. if(NT_SUCCESS(NtStatus) ||
  4991. STATUS_NONE_MAPPED == NtStatus)
  4992. {
  4993. ScepFree(pName->Name);
  4994. pName->Name = pszName; // NULL if failed to map to name
  4995. }
  4996. else
  4997. {
  4998. rc = ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus));
  4999. }
  5000. LocalFree(pSid);
  5001. }
  5002. else
  5003. {
  5004. rc = ScepDosErrorToSceStatus(GetLastError());
  5005. }
  5006. }
  5007. return rc;
  5008. }
  5009. SCESTATUS
  5010. ScepParseListConvertNamesToStringSids(
  5011. IN LSA_HANDLE PolicyHandle,
  5012. IN OUT PSCE_NAME_LIST pNameList
  5013. )
  5014. /* ++
  5015. Routine Description:
  5016. This routine parses the group list (expected to contain only names in domain\name
  5017. format) and replaces them with *SID sid string format
  5018. Arguments:
  5019. PolicyHandle - LSA handle
  5020. pNameList - list of groups
  5021. Return Value:
  5022. SCESTATUS - return success if all conversion succeeded
  5023. -- */
  5024. {
  5025. SCESTATUS rc = SCESTATUS_SUCCESS;
  5026. PSCE_NAME_LIST pName = NULL;
  5027. for(pName = pNameList;
  5028. pName != NULL && SCESTATUS_SUCCESS == rc;
  5029. pName = pName->Next)
  5030. {
  5031. PWSTR pszName = NULL; // no need to free, returned in pNameList
  5032. DWORD dwLen = 0;
  5033. rc = ScepConvertNameToSidString(
  5034. PolicyHandle,
  5035. pName->Name,
  5036. FALSE, // accept names w/ domain
  5037. &pszName,
  5038. &dwLen);
  5039. if(SCESTATUS_SUCCESS != rc)
  5040. {
  5041. break;
  5042. }
  5043. ScepFree(pName->Name);
  5044. pName->Name = pszName;
  5045. }
  5046. return rc;
  5047. }
  5048. bool
  5049. ScepFindInNameList(
  5050. IN PSCE_NAME_LIST pNameList,
  5051. IN PWSTR pszName)
  5052. /* ++
  5053. Routine Description:
  5054. Searches a name in the list, case insensitive. Name list could contain NULL
  5055. entries. All valid names are presumed from the current machine since they were
  5056. previously successfully opened in SAM.
  5057. Arguments:
  5058. pNameList - list of name to search in
  5059. pszName - Name to be searched for
  5060. Return:
  5061. true - if name is found
  5062. -- */
  5063. {
  5064. PSCE_NAME_LIST pCrt;
  5065. PWSTR pszAccountName;
  5066. for(pCrt = pNameList; pCrt; pCrt = pCrt->Next)
  5067. {
  5068. if(!pCrt->Name)
  5069. continue;
  5070. pszAccountName = wcschr(pCrt->Name, L'\\');
  5071. if(pszAccountName)
  5072. pszAccountName++;
  5073. else
  5074. pszAccountName = pCrt->Name;
  5075. if(0 == _wcsicmp(pszAccountName, pszName))
  5076. return true;
  5077. }
  5078. return false;
  5079. }
  5080. NTSTATUS
  5081. ScepSamOpenAlias(
  5082. IN SAM_HANDLE DomainHandle,
  5083. IN SAM_HANDLE BuiltinDomainHandle,
  5084. IN PWSTR pszName,
  5085. OUT SAM_HANDLE *pAliasHandle
  5086. )
  5087. {
  5088. NTSTATUS NtStatus = STATUS_SUCCESS;
  5089. PWSTR pTemp;
  5090. UNICODE_STRING Name;
  5091. PSID_NAME_USE AliasUse=NULL;
  5092. PULONG AliasId=NULL;
  5093. SAM_HANDLE ThisDomain;
  5094. // should expect pGroup->Name has domain prefix
  5095. pTemp = wcschr(pszName, L'\\');
  5096. if ( pTemp )
  5097. {
  5098. // check if this group is from a different domain
  5099. Name.Buffer = pszName;
  5100. Name.Length = ((USHORT)(pTemp-pszName))*sizeof(TCHAR);
  5101. if ( !ScepIsDomainLocal(&Name) )
  5102. {
  5103. ScepLogOutput3(1, 0, SCEDLL_ERROR_ALIAS_MEMBEROF, pszName);
  5104. NtStatus = STATUS_NONE_MAPPED;
  5105. }
  5106. else
  5107. {
  5108. pTemp++;
  5109. }
  5110. } else {
  5111. pTemp = pszName;
  5112. }
  5113. if(NT_SUCCESS(NtStatus))
  5114. {
  5115. RtlInitUnicodeString( &Name, pTemp);
  5116. NtStatus = SamLookupNamesInDomain(
  5117. DomainHandle,
  5118. 1,
  5119. &Name,
  5120. &AliasId,
  5121. &AliasUse
  5122. );
  5123. ThisDomain = DomainHandle;
  5124. if(NtStatus == STATUS_NONE_MAPPED)
  5125. {
  5126. // not found in account domain. Lookup in the builtin domain
  5127. NtStatus = SamLookupNamesInDomain(
  5128. BuiltinDomainHandle,
  5129. 1,
  5130. &Name,
  5131. &AliasId,
  5132. &AliasUse
  5133. );
  5134. ThisDomain = BuiltinDomainHandle;
  5135. }
  5136. if ( !NT_SUCCESS(NtStatus) || !AliasUse || !AliasId )
  5137. {
  5138. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  5139. SCEDLL_CANNOT_FIND, pTemp);
  5140. }
  5141. }
  5142. if(NT_SUCCESS(NtStatus))
  5143. {
  5144. if ( AliasUse[0] != SidTypeAlias ) {
  5145. ScepLogOutput3(1,0, SCEDLL_ERROR_ALIAS_MEMBEROF, pTemp);
  5146. NtStatus = STATUS_NONE_MAPPED;
  5147. }
  5148. }
  5149. if(NT_SUCCESS(NtStatus))
  5150. {
  5151. NtStatus = SamOpenAlias(
  5152. ThisDomain,
  5153. MAXIMUM_ALLOWED,
  5154. AliasId[0],
  5155. pAliasHandle
  5156. );
  5157. if ( !NT_SUCCESS(NtStatus) ) {
  5158. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  5159. SCEDLL_ERROR_OPEN, pszName);
  5160. }
  5161. }
  5162. if(AliasId)
  5163. {
  5164. SamFreeMemory(AliasId);
  5165. }
  5166. if(AliasUse)
  5167. {
  5168. SamFreeMemory(AliasUse);
  5169. }
  5170. return NtStatus;
  5171. }
  5172. SCESTATUS
  5173. ScepValidateGroupInAliases(
  5174. IN SAM_HANDLE DomainHandle,
  5175. IN SAM_HANDLE BuiltinDomainHandle,
  5176. IN PSCESECTION hSectionTattoo,
  5177. IN LSA_HANDLE PolicyHandle,
  5178. IN PSID GrpSid,
  5179. IN PSCE_NAME_LIST pAliasList,
  5180. bool fProcessTattoo
  5181. )
  5182. /* ++
  5183. Routine Description:
  5184. This routine add the group to a list of alieses to ensure the group's
  5185. membership.
  5186. Arguments:
  5187. hSectionTattoo - handle to tatoo table section
  5188. DomainHandle - The account domain handle
  5189. BuiltinDomainHandle - The builtin domain handle
  5190. GrpSid - The group's SID
  5191. pAliasList - the list of aliases to check
  5192. fProcessTattoo - true if we need to process tattoo table, ie during
  5193. policy propagation and if not on a DC
  5194. -- */
  5195. {
  5196. NTSTATUS NtStatus = STATUS_SUCCESS;
  5197. NTSTATUS NtStatusSave = STATUS_SUCCESS;
  5198. SCESTATUS rc = SCESTATUS_SUCCESS;
  5199. PSCE_NAME_LIST pOldTattooList = NULL;
  5200. PSCE_NAME_LIST pNewTattooList = NULL;
  5201. PSCE_NAME_LIST pAliasDeleteList = NULL;
  5202. SAM_HANDLE AliasHandle=NULL;
  5203. PSCE_NAME_LIST pAlias;
  5204. UNICODE_STRING Name;
  5205. /////////////////////////////////////////////////////////////////
  5206. //
  5207. // Algorithm:
  5208. //
  5209. // 1. Retrieve old memberof tattoo list for the group and
  5210. // convert SID strings to names
  5211. //
  5212. // 2. For each group element in effective memberof list
  5213. // if element is valid alias on this machine
  5214. // add the group to alias
  5215. // if successfully added
  5216. // add alias to new tattoo list
  5217. //
  5218. // 3. For each group element in old tattoo list
  5219. // if element exists is effective list
  5220. // add element to new tattoo list
  5221. // else
  5222. // add element to delete list
  5223. //
  5224. // 4. For each element in delete list
  5225. // if element is valid alias on this machine
  5226. // delete group from alias
  5227. // if delete unsuccessful
  5228. // add element to new tattoo list
  5229. //
  5230. // 6. Write new tattoo list to tattoo table after converting
  5231. // names back to SID strings
  5232. //
  5233. /////////////////////////////////////////////////////////////////
  5234. if(fProcessTattoo)
  5235. {
  5236. // Retrieve old memberof tattoo list for the group
  5237. rc = ScepTattooReadOneMemberOfListValue(
  5238. hSectionTattoo,
  5239. GrpSid,
  5240. &pOldTattooList);
  5241. // Parse old tattoo list and replace *SIDs with names
  5242. if(SCESTATUS_SUCCESS == rc)
  5243. {
  5244. rc = ScepParseListConvertStringSidsToNames(
  5245. PolicyHandle,
  5246. pOldTattooList);
  5247. }
  5248. // tattoo entry could be missing, ignore
  5249. if(SCESTATUS_RECORD_NOT_FOUND == rc)
  5250. {
  5251. rc = SCESTATUS_SUCCESS;
  5252. }
  5253. }
  5254. if(SCESTATUS_SUCCESS == rc)
  5255. {
  5256. // For each group element in effective memberof list
  5257. for(pAlias = pAliasList; pAlias != NULL; pAlias = pAlias->Next)
  5258. {
  5259. NtStatus = ScepSamOpenAlias(
  5260. DomainHandle,
  5261. BuiltinDomainHandle,
  5262. pAlias->Name,
  5263. &AliasHandle);
  5264. //
  5265. // if element is not valid alias on this machine go to next
  5266. //
  5267. if(STATUS_NONE_MAPPED == NtStatus)
  5268. {
  5269. ScepLogOutput3(1, 0, SCEDLL_CANNOT_FIND, pAlias->Name);
  5270. NtStatusSave = NtStatus;
  5271. // Alias is not valid on this machine, remove it from the list
  5272. ScepFree(pAlias->Name);
  5273. pAlias->Name = NULL;
  5274. continue;
  5275. }
  5276. if(!NT_SUCCESS(NtStatus))
  5277. {
  5278. goto Done;
  5279. }
  5280. //
  5281. // element is valid alias, add the group to alias
  5282. //
  5283. NtStatus = SamAddMemberToAlias(
  5284. AliasHandle,
  5285. GrpSid
  5286. );
  5287. //
  5288. // If successfully added, add alias to new tattoo list
  5289. //
  5290. if (NT_SUCCESS(NtStatus))
  5291. {
  5292. ScepLogOutput3(1, 0, SCEDLL_SCP_SUCCESS_ADDTO, pAlias->Name);
  5293. rc = ScepAddToNameList(
  5294. &pNewTattooList,
  5295. pAlias->Name,
  5296. 0);
  5297. if(SCESTATUS_SUCCESS != rc)
  5298. {
  5299. goto Done;
  5300. }
  5301. }
  5302. else
  5303. {
  5304. // Ignore error if member was already in the alias
  5305. if(NtStatus == STATUS_MEMBER_IN_ALIAS)
  5306. {
  5307. ScepLogOutput3(1, 0, SCEDLL_SCP_SUCCESS_ADDTO_ALREADYADDED, pAlias->Name);
  5308. NtStatus = STATUS_SUCCESS;
  5309. }
  5310. else
  5311. {
  5312. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  5313. SCEDLL_SCP_ERROR_ADDTO, pAlias->Name);
  5314. NtStatusSave = NtStatus;
  5315. }
  5316. }
  5317. SamCloseHandle(AliasHandle);
  5318. AliasHandle = NULL;
  5319. }
  5320. }
  5321. if(fProcessTattoo)
  5322. {
  5323. if(SCESTATUS_SUCCESS == rc)
  5324. {
  5325. // For each group element in old tattoo list
  5326. for(pAlias = pOldTattooList; pAlias != NULL; pAlias = pAlias->Next)
  5327. {
  5328. // Name could be empty if the conversion *SID -> name failed
  5329. if(!pAlias->Name)
  5330. {
  5331. continue;
  5332. }
  5333. // If element exists is effective list
  5334. if(ScepFindInNameList(pAliasList, pAlias->Name))
  5335. {
  5336. // Add element to new tattoo list if not already in
  5337. if(!ScepFindInNameList(pNewTattooList, pAlias->Name))
  5338. {
  5339. // Add element to delete list
  5340. rc = ScepAddToNameList(
  5341. &pNewTattooList,
  5342. pAlias->Name,
  5343. 0);
  5344. if(SCESTATUS_SUCCESS != rc)
  5345. {
  5346. goto Done;
  5347. }
  5348. }
  5349. }
  5350. else
  5351. {
  5352. // Add element to delete list
  5353. rc = ScepAddToNameList(
  5354. &pAliasDeleteList,
  5355. pAlias->Name,
  5356. 0);
  5357. if(SCESTATUS_SUCCESS != rc)
  5358. {
  5359. goto Done;
  5360. }
  5361. }
  5362. }
  5363. }
  5364. if(SCESTATUS_SUCCESS == rc)
  5365. {
  5366. // For each element in delete list
  5367. for(pAlias = pAliasDeleteList; pAlias != NULL; pAlias = pAlias->Next)
  5368. {
  5369. NtStatus = ScepSamOpenAlias(
  5370. DomainHandle,
  5371. BuiltinDomainHandle,
  5372. pAlias->Name,
  5373. &AliasHandle);
  5374. // if element is not valid alias on this machine go to next
  5375. if(STATUS_NONE_MAPPED == NtStatus)
  5376. {
  5377. NtStatus = STATUS_SUCCESS;
  5378. continue;
  5379. }
  5380. if(!NT_SUCCESS(NtStatus))
  5381. {
  5382. goto Done;
  5383. }
  5384. // Delete group from alias
  5385. NtStatus = SamRemoveMemberFromAlias(
  5386. AliasHandle,
  5387. GrpSid
  5388. );
  5389. if(NT_SUCCESS(NtStatus))
  5390. {
  5391. ScepLogOutput3(1, 0, SCEDLL_SCP_SUCCESS_REMOVEFROM, pAlias->Name);
  5392. }
  5393. else if(STATUS_SPECIAL_ACCOUNT == NtStatus ||
  5394. STATUS_MEMBER_NOT_IN_ALIAS == NtStatus)
  5395. {
  5396. // Ignore not found or special account
  5397. ScepLogOutput3(1, 0, SCEDLL_SCP_SUCCESS_REMOVEFROM_ALREADYREMOVED, pAlias->Name);
  5398. NtStatus = STATUS_SUCCESS;
  5399. }
  5400. else
  5401. {
  5402. NtStatusSave = NtStatus;
  5403. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  5404. SCEDLL_SCP_ERROR_REMOVEFROM, pAlias->Name);
  5405. // If delete unsuccessful, add to new tattoo list so we can
  5406. // retry next time
  5407. rc = ScepAddToNameList(
  5408. &pNewTattooList,
  5409. pAlias->Name,
  5410. 0);
  5411. if(SCESTATUS_SUCCESS != rc)
  5412. {
  5413. goto Done;
  5414. }
  5415. }
  5416. SamCloseHandle(AliasHandle);
  5417. AliasHandle = NULL;
  5418. }
  5419. }
  5420. // Convert new tattoo list to *SID format
  5421. if(SCESTATUS_SUCCESS == rc)
  5422. {
  5423. rc = ScepParseListConvertNamesToStringSids(
  5424. PolicyHandle,
  5425. pNewTattooList);
  5426. }
  5427. if(SCESTATUS_SUCCESS == rc)
  5428. {
  5429. // Write/delete new tattoo list to tattoo table
  5430. rc = ScepTattooWriteOneMemberOfListValue(
  5431. hSectionTattoo,
  5432. GrpSid,
  5433. pNewTattooList);
  5434. }
  5435. } // if(fProcessTattoo)
  5436. Done:
  5437. ScepFreeNameList(pOldTattooList);
  5438. ScepFreeNameList(pNewTattooList);
  5439. ScepFreeNameList(pAliasDeleteList);
  5440. if ( AliasHandle != NULL )
  5441. SamCloseHandle(AliasHandle);
  5442. if (SCESTATUS_SUCCESS == rc && !NT_SUCCESS(NtStatusSave))
  5443. rc = ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatusSave));
  5444. return(rc);
  5445. }
  5446. SCESTATUS
  5447. ScepConfigureObjectSecurity(
  5448. IN PSCE_OBJECT_LIST pRoots,
  5449. IN AREA_INFORMATION Area,
  5450. IN BOOL bPolicyProp,
  5451. IN DWORD ConfigOptions
  5452. )
  5453. /* ++
  5454. Routine Description:
  5455. Configure the security setting on Registry keys as specified in pObject tree
  5456. Arguments:
  5457. pRoots - a list of object roots to configure
  5458. Area - The security area to configure (registry or file)
  5459. ObjectType - Type of the object tree
  5460. SCEJET_AUDITING
  5461. SCEJET_PERMISSION
  5462. Return value:
  5463. SCESTATUS error codes
  5464. ++ */
  5465. {
  5466. if (Area == AREA_REGISTRY_SECURITY) {
  5467. #ifdef _WIN64
  5468. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_REGISTRY_64KEY);
  5469. #else
  5470. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_REGISTRY);
  5471. #endif
  5472. }
  5473. if ( bPolicyProp &&
  5474. ScepIsSystemShutDown() ) {
  5475. return( SCESTATUS_SERVICE_NOT_SUPPORT );
  5476. }
  5477. HANDLE Token;
  5478. SCESTATUS rc;
  5479. SCESTATUS SaveStat=SCESTATUS_SUCCESS;
  5480. DWORD Win32rc;
  5481. PSCE_OBJECT_LIST pOneRoot;
  5482. PSCE_OBJECT_CHILD_LIST pSecurityObject=NULL;
  5483. DWORD FileSystemFlags;
  5484. SID_IDENTIFIER_AUTHORITY IdentifierAuthority=SECURITY_NT_AUTHORITY;
  5485. WCHAR theDrive[4];
  5486. UINT DriveType;
  5487. //
  5488. // get current thread/process's token
  5489. //
  5490. if (!OpenThreadToken( GetCurrentThread(),
  5491. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  5492. TRUE,
  5493. &Token)) {
  5494. if(ERROR_NO_TOKEN == GetLastError()){
  5495. if(!OpenProcessToken( GetCurrentProcess(),
  5496. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  5497. &Token)) {
  5498. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  5499. return(ScepDosErrorToSceStatus(GetLastError()));
  5500. }
  5501. } else {
  5502. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  5503. return(ScepDosErrorToSceStatus(GetLastError()));
  5504. }
  5505. }
  5506. //
  5507. // Adjust privilege for setting SACL
  5508. //
  5509. Win32rc = SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, Token );
  5510. //
  5511. // if can't adjust privilege, still continue
  5512. //
  5513. if ( Win32rc != NO_ERROR )
  5514. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ADJUST, L"SE_SECURITY_PRIVILEGE");
  5515. // adjust take ownership privilege
  5516. // if fails, continue
  5517. Win32rc = SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, Token );
  5518. if ( Win32rc != NO_ERROR )
  5519. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ADJUST, L"SE_TAKE_OWNERSHIP_PRIVILEGE");
  5520. // create a sid for administrators
  5521. // if fails, continue
  5522. if ( ! NT_SUCCESS ( RtlAllocateAndInitializeSid( &IdentifierAuthority,
  5523. 2,
  5524. SECURITY_BUILTIN_DOMAIN_RID,
  5525. DOMAIN_ALIAS_RID_ADMINS,
  5526. 0,0,0,0,0,0,
  5527. &AdminsSid
  5528. ) ) ) {
  5529. ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY,
  5530. SCEDLL_ADMINISTRATORS_SID);
  5531. }
  5532. #ifdef _WIN64
  5533. //
  5534. // declaration for object tree root pointer to remember from the 64-bit phase and use
  5535. // for 32-bit phase for regkeys (only from the HKLM root, since wow6432node resides
  5536. // under this root only). In future, if there are more wow6432node's that need security
  5537. // synchronization, we will have to extend the logic on similar lines to handle them.
  5538. //
  5539. PSCE_OBJECT_CHILD_LIST pHKLMSubtreeRoot = NULL;
  5540. BOOL bIsHKLMSubtree = FALSE;
  5541. #endif
  5542. // process each tree
  5543. for ( pOneRoot=pRoots; pOneRoot != NULL; pOneRoot=pOneRoot->Next ) {
  5544. if ( Area == AREA_FILE_SECURITY &&
  5545. (pOneRoot->Status == SCE_STATUS_CHECK ||
  5546. pOneRoot->Status == SCE_STATUS_NO_AUTO_INHERIT ||
  5547. pOneRoot->Status == SCE_STATUS_OVERWRITE) ) {
  5548. //
  5549. // make sure the input data follows file format
  5550. //
  5551. if ( pOneRoot->Name[1] != L'\0' && pOneRoot->Name[1] != L':') {
  5552. ScepLogOutput3(1, ERROR_INVALID_DATA, SCEDLL_CANNOT_FIND, pOneRoot->Name);
  5553. continue;
  5554. }
  5555. //
  5556. // check if support acl
  5557. //
  5558. theDrive[0] = pOneRoot->Name[0];
  5559. theDrive[1] = L':';
  5560. theDrive[2] = L'\\';
  5561. theDrive[3] = L'\0';
  5562. DriveType = GetDriveType(theDrive);
  5563. if ( DriveType == DRIVE_FIXED ||
  5564. DriveType == DRIVE_RAMDISK ) {
  5565. if ( GetVolumeInformation( theDrive,
  5566. NULL,
  5567. 0,
  5568. NULL,
  5569. NULL,
  5570. &FileSystemFlags,
  5571. NULL,
  5572. 0
  5573. ) ) {
  5574. if ( !( FileSystemFlags & FS_PERSISTENT_ACLS) ) {
  5575. pOneRoot->Status = SCE_STATUS_NO_ACL_SUPPORT;
  5576. ScepLogOutput3(1, 0, SCEDLL_NO_ACL_SUPPORT, theDrive);
  5577. }
  5578. } else {
  5579. ScepLogOutput3(1, GetLastError(),
  5580. SCEDLL_ERROR_QUERY_VOLUME, theDrive);
  5581. }
  5582. } else {
  5583. pOneRoot->Status = SCE_STATUS_NO_ACL_SUPPORT;
  5584. ScepLogOutput3(1, 0, SCEDLL_NO_ACL_SUPPORT, theDrive);
  5585. }
  5586. }
  5587. if ( pOneRoot->Status != SCE_STATUS_CHECK &&
  5588. pOneRoot->Status != SCE_STATUS_NO_AUTO_INHERIT &&
  5589. pOneRoot->Status != SCE_STATUS_OVERWRITE)
  5590. continue;
  5591. //
  5592. // if system is shutting down within policy propagation,
  5593. // quit as soon as possible
  5594. //
  5595. if ( bPolicyProp &&
  5596. ScepIsSystemShutDown() ) {
  5597. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  5598. break;
  5599. }
  5600. rc = ScepGetOneSection(
  5601. hProfile,
  5602. Area,
  5603. pOneRoot->Name,
  5604. bPolicyProp ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  5605. (PVOID *)&pSecurityObject
  5606. );
  5607. if ( rc != SCESTATUS_SUCCESS ) {
  5608. SaveStat = rc;
  5609. continue; //goto Done;
  5610. }
  5611. #ifdef _WIN64
  5612. //
  5613. // on a 64-bit platform, if the closest ancestor of "Machine\Software\Wow6432Node"
  5614. // specified in the template, has mode 2, we have to insert "Machine\Software\Wow6432Node"
  5615. // in the tree in the SCE_STATUS_IGNORE mode since this 32-bit hive should not be
  5616. // configured by SCE in the 64-bit phase (same situation for '0' mode is handled by MARTA apis)
  5617. //
  5618. if ( Area == AREA_REGISTRY_SECURITY ) {
  5619. if ( _wcsnicmp(pSecurityObject->Node->ObjectFullName,
  5620. L"MACHINE",
  5621. sizeof(L"MACHINE")/sizeof(WCHAR) - 1
  5622. ) == 0 ){
  5623. //
  5624. // idea is to find mode of closest ancestor of "Machine\Software\Wow6432Node"
  5625. //
  5626. PSCE_OBJECT_CHILD_LIST pSearchSwHiveNode = pSecurityObject->Node->ChildList;
  5627. BYTE byClosestAncestorStatus;
  5628. //
  5629. // we need to do the 32-bit phase only if we get in here
  5630. // so remember HKLM ptr in the tree for 32-bit phase
  5631. //
  5632. pHKLMSubtreeRoot = pSecurityObject;
  5633. bIsHKLMSubtree = TRUE;
  5634. //
  5635. // try to find "Machine\Software"
  5636. //
  5637. while ( pSearchSwHiveNode ) {
  5638. if ( pSearchSwHiveNode->Node &&
  5639. _wcsnicmp(pSearchSwHiveNode->Node->ObjectFullName + (sizeof(L"MACHINE")/sizeof(WCHAR)),
  5640. L"SOFTWARE",
  5641. sizeof(L"SOFTWARE")/sizeof(WCHAR) - 1
  5642. ) == 0 ) {
  5643. //
  5644. // found "Machine\Software"
  5645. //
  5646. break;
  5647. }
  5648. pSearchSwHiveNode = pSearchSwHiveNode->Next;
  5649. }
  5650. byClosestAncestorStatus = (pSearchSwHiveNode && pSearchSwHiveNode->Node) ? pSearchSwHiveNode->Node->Status : pHKLMSubtreeRoot->Node->Status;
  5651. //
  5652. // if mode of closest ancestor of "Machine\Software\Wow6432Node" is
  5653. // SCE_STATUS_OVERWRITE or "Machine\Software" has some children
  5654. // need to add "Machine\Software\Wow6432Node" with SCE_STATUS_IGNORE
  5655. // to the tree
  5656. //
  5657. if ( ( pSearchSwHiveNode && pSearchSwHiveNode->Node &&
  5658. pSearchSwHiveNode->Node->ChildList != NULL) ||
  5659. byClosestAncestorStatus == SCE_STATUS_OVERWRITE ) {
  5660. rc = ScepBuildObjectTree(
  5661. NULL,
  5662. &pSecurityObject,
  5663. 1,
  5664. L'\\',
  5665. L"MACHINE\\SOFTWARE\\WOW6432Node",
  5666. 1,
  5667. SCE_STATUS_IGNORE,
  5668. NULL,
  5669. 0
  5670. );
  5671. if ( rc != SCESTATUS_SUCCESS ) {
  5672. SaveStat = rc;
  5673. ScepFreeObject2Security( pSecurityObject, FALSE);
  5674. pSecurityObject = NULL;
  5675. continue; //goto Done;
  5676. }
  5677. }
  5678. }
  5679. }
  5680. #endif
  5681. //
  5682. // then process each node in the list
  5683. //
  5684. for (PSCE_OBJECT_CHILD_LIST pTemp = pSecurityObject; pTemp != NULL; pTemp=pTemp->Next) {
  5685. if ( pTemp->Node == NULL ) continue;
  5686. if ( Area == AREA_FILE_SECURITY ) {
  5687. if ( pTemp->Node->ObjectFullName[1] == L':' &&
  5688. pTemp->Node->ObjectFullName[2] == L'\0' ) {
  5689. pTemp->Node->ObjectFullName[2] = L'\\';
  5690. pTemp->Node->ObjectFullName[3] = L'\0';
  5691. }
  5692. }
  5693. if ( bPolicyProp &&
  5694. ScepIsSystemShutDown() ) {
  5695. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  5696. } else {
  5697. //
  5698. // calculate the "real" security descriptor for each node
  5699. //
  5700. if ( Area == AREA_FILE_SECURITY ) {
  5701. rc = ScepCalculateSecurityToApply(
  5702. pTemp->Node,
  5703. SE_FILE_OBJECT,
  5704. Token,
  5705. &FileGenericMapping
  5706. );
  5707. } else if ( Area == AREA_REGISTRY_SECURITY ) {
  5708. rc = ScepCalculateSecurityToApply(
  5709. pTemp->Node,
  5710. SE_REGISTRY_KEY,
  5711. Token,
  5712. &KeyGenericMapping
  5713. );
  5714. }
  5715. }
  5716. if ( rc == SCESTATUS_SUCCESS ) {
  5717. if ( bPolicyProp &&
  5718. ScepIsSystemShutDown() ) {
  5719. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  5720. } else {
  5721. if ( Area == AREA_FILE_SECURITY ) {
  5722. rc = ScepConfigureObjectTree(
  5723. pTemp->Node,
  5724. SE_FILE_OBJECT,
  5725. Token,
  5726. &FileGenericMapping,
  5727. ConfigOptions
  5728. );
  5729. } else if ( Area == AREA_REGISTRY_SECURITY ) {
  5730. rc = ScepConfigureObjectTree(
  5731. pTemp->Node,
  5732. SE_REGISTRY_KEY,
  5733. Token,
  5734. &KeyGenericMapping,
  5735. ConfigOptions
  5736. );
  5737. } else {
  5738. // ds objects
  5739. rc = ScepConfigureDsSecurity( pTemp->Node);
  5740. }
  5741. }
  5742. }
  5743. if ( rc != SCESTATUS_SUCCESS )
  5744. SaveStat = rc;
  5745. }
  5746. #ifdef _WIN64
  5747. //
  5748. // If 64-bit platform and AREA_REGISTRY_SECURITY and HKLM, do
  5749. // not free the whole subtree , only free the computed SDs
  5750. //
  5751. if (Area == AREA_FILE_SECURITY)
  5752. ScepFreeObject2Security( pSecurityObject, FALSE);
  5753. else if (Area == AREA_REGISTRY_SECURITY)
  5754. ScepFreeObject2Security( pSecurityObject, bIsHKLMSubtree);
  5755. bIsHKLMSubtree = FALSE;
  5756. #else
  5757. ScepFreeObject2Security( pSecurityObject, FALSE);
  5758. #endif
  5759. pSecurityObject = NULL;
  5760. //
  5761. // stop right away if bPolicyProp and system is being shutdown
  5762. //
  5763. if (rc == SCESTATUS_SERVICE_NOT_SUPPORT)
  5764. break;
  5765. }
  5766. if ( Area == AREA_REGISTRY_SECURITY ) {
  5767. if ( SaveStat != SCESTATUS_SUCCESS ) {
  5768. ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_ERROR);
  5769. } else {
  5770. ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_SUCCESS);
  5771. }
  5772. }
  5773. #ifdef _WIN64
  5774. //
  5775. // on a 64-bit platform, if AREA_REGISTRY_SECURITY, will have to recompute
  5776. // security and apply for the same keys as before except that it is for the
  5777. // 32-bit hives this time around (idea is to synchronize 64-bit and 32 bit
  5778. // registry security). There is no need to rebuild the tree from the template.
  5779. //
  5780. if (rc != SCESTATUS_SERVICE_NOT_SUPPORT && Area == AREA_REGISTRY_SECURITY) {
  5781. ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_REGISTRY_32KEY);
  5782. if (pSecurityObject = pHKLMSubtreeRoot) {
  5783. //
  5784. // nothing needs to be done to the Wow6432Node that was added in SCE_STATUS_IGNORE
  5785. // mode in the 64-bit phase since it is illegal to specify Wow6432Node in the template
  5786. // (the plan is that registry APIs will treat "Wow6432Node" as a reserved keyname)
  5787. //
  5788. //
  5789. // we will set SCE_STATUS_IGNORE mode to all immediate nodes under HKLM except
  5790. // HKLM\Software. This will take care of HKLM or HKLM\Software being specified
  5791. // in any mode etc. as though it was 32-bit registry configuration, since all
  5792. // we care about now is 32-bit configuration for HKLM\Software and under
  5793. //
  5794. PSCE_OBJECT_CHILD_LIST pHKLMChild = pSecurityObject->Node->ChildList;
  5795. while ( pHKLMChild ) {
  5796. if ( pHKLMChild->Node &&
  5797. _wcsnicmp(pHKLMChild->Node->ObjectFullName + (sizeof(L"MACHINE")/sizeof(WCHAR)),
  5798. L"SOFTWARE",
  5799. sizeof(L"SOFTWARE")/sizeof(WCHAR) - 1
  5800. ) != 0 ) {
  5801. //
  5802. // not "Machine\Software"
  5803. //
  5804. pHKLMChild->Node->Status = SCE_STATUS_IGNORE;
  5805. }
  5806. pHKLMChild = pHKLMChild->Next;
  5807. }
  5808. if ( bPolicyProp &&
  5809. ScepIsSystemShutDown() ) {
  5810. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  5811. } else {
  5812. //
  5813. // calculate the "real" security descriptor for each node
  5814. //
  5815. rc = ScepCalculateSecurityToApply(
  5816. pSecurityObject->Node,
  5817. SE_REGISTRY_WOW64_32KEY,
  5818. Token,
  5819. &KeyGenericMapping
  5820. );
  5821. }
  5822. if ( rc == SCESTATUS_SUCCESS ) {
  5823. if ( bPolicyProp &&
  5824. ScepIsSystemShutDown() ) {
  5825. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  5826. } else {
  5827. rc = ScepConfigureObjectTree(
  5828. pSecurityObject->Node,
  5829. SE_REGISTRY_WOW64_32KEY,
  5830. Token,
  5831. &KeyGenericMapping,
  5832. ConfigOptions
  5833. );
  5834. }
  5835. }
  5836. //
  5837. // Free the whole tree now (done with 32-bit phase)
  5838. //
  5839. ScepFreeObject2Security( pSecurityObject, FALSE);
  5840. pSecurityObject = NULL;
  5841. if( rc != SCESTATUS_SUCCESS ) {
  5842. SaveStat = rc;
  5843. ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_ERROR);
  5844. } else {
  5845. ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_SUCCESS);
  5846. }
  5847. }
  5848. }
  5849. #endif
  5850. if( AdminsSid != NULL ) {
  5851. RtlFreeSid( AdminsSid );
  5852. AdminsSid = NULL;
  5853. }
  5854. SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, Token );
  5855. //
  5856. // disable take ownership privilege, even for administrators
  5857. // because by default it's disabled
  5858. //
  5859. SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, FALSE, Token );
  5860. CloseHandle(Token);
  5861. if ( pSecurityObject != NULL ) {
  5862. ScepFreeObject2Security( pSecurityObject, FALSE);
  5863. }
  5864. return(SaveStat);
  5865. }
  5866. DWORD
  5867. ScepConfigureSystemAuditing(
  5868. IN PSCE_PROFILE_INFO pScpInfo,
  5869. IN DWORD ConfigOptions
  5870. )
  5871. /* ++
  5872. Routine Description:
  5873. This routine configure the system security in the area of auditing which
  5874. includes event log setting, audit event setting, SACL for registry, and
  5875. SACL for files.
  5876. Arguments:
  5877. scpInfo - The buffer which contains SCP info loaded from the INF file
  5878. Return value:
  5879. SCESTATUS_SUCCESS
  5880. SCESTATUS_NOT_ENOUGH_RESOURCE
  5881. SCESTATUS_INVALID_PARAMETER
  5882. SCESTATUS_OTHER_ERROR
  5883. -- */
  5884. {
  5885. DWORD rc = NO_ERROR;
  5886. DWORD Saverc = NO_ERROR;
  5887. DWORD MaxSize=0;
  5888. DWORD Retention=0;
  5889. DWORD RestrictGuest=0;
  5890. DWORD OldMaxSize,OldRetention,OldGuest;
  5891. DWORD AuditLogRetentionPeriod, RetentionDays;
  5892. TCHAR MsgBuf[256];
  5893. DWORD i;
  5894. BOOL bFlagSet=FALSE;
  5895. PCWSTR szAuditSection=NULL;
  5896. PSCESECTION hSectionDomain=NULL;
  5897. PSCESECTION hSectionTattoo=NULL;
  5898. //
  5899. // Set audit log information. Audit Log settings are saved in the Registry
  5900. // under System\CurrentControlSet\Services\EventLog\<LogName>\MaxSize and Retention
  5901. //
  5902. for ( i=0; i<3; i++) {
  5903. if ( pScpInfo->MaximumLogSize[i] == SCE_NO_VALUE )
  5904. MaxSize = SCE_NO_VALUE;
  5905. else
  5906. MaxSize = (pScpInfo->MaximumLogSize[i] - (pScpInfo->MaximumLogSize[i] % 64 )) * 1024;
  5907. switch ( pScpInfo->AuditLogRetentionPeriod[i] ) {
  5908. case SCE_NO_VALUE:
  5909. Retention = SCE_NO_VALUE;
  5910. break;
  5911. case 2: // manually
  5912. Retention = MAXULONG;
  5913. break;
  5914. case 1: // number of days * seconds/day
  5915. if ( pScpInfo->RetentionDays[i] == SCE_NO_VALUE ) {
  5916. Retention = SCE_NO_VALUE;
  5917. } else {
  5918. Retention = pScpInfo->RetentionDays[i] * 24 * 3600;
  5919. }
  5920. break;
  5921. case 0: // as needed
  5922. Retention = 0;
  5923. break;
  5924. }
  5925. if ( pScpInfo->RestrictGuestAccess[i] == SCE_NO_VALUE )
  5926. RestrictGuest = SCE_NO_VALUE;
  5927. else
  5928. RestrictGuest = (pScpInfo->RestrictGuestAccess[i])? 1 : 0;
  5929. //
  5930. // Different logs have different keys in Registry
  5931. //
  5932. if ( MaxSize != SCE_NO_VALUE || Retention != SCE_NO_VALUE ||
  5933. RestrictGuest != SCE_NO_VALUE ) {
  5934. bFlagSet = TRUE;
  5935. switch (i) {
  5936. case 0:
  5937. wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\System");
  5938. szAuditSection = szAuditSystemLog;
  5939. break;
  5940. case 1:
  5941. wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\Security");
  5942. szAuditSection = szAuditSecurityLog;
  5943. break;
  5944. default:
  5945. wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\Application");
  5946. szAuditSection = szAuditApplicationLog;
  5947. break;
  5948. }
  5949. WCHAR StrBuf[2];
  5950. _itow(i, StrBuf, 10);
  5951. //
  5952. // open policy sections
  5953. //
  5954. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  5955. ScepTattooOpenPolicySections(
  5956. hProfile,
  5957. szAuditSection,
  5958. &hSectionDomain,
  5959. &hSectionTattoo
  5960. );
  5961. OldMaxSize=0;
  5962. OldRetention=0;
  5963. OldGuest=0;
  5964. }
  5965. if ( MaxSize != SCE_NO_VALUE ) {
  5966. if ( ConfigOptions & SCE_POLICY_TEMPLATE ||
  5967. ConfigOptions & SCE_PROMOTE_FLAG_REPLICA ) {
  5968. //
  5969. // query existing value
  5970. //
  5971. if ( ERROR_SUCCESS != ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  5972. MsgBuf,
  5973. L"MaxSize",
  5974. &OldMaxSize
  5975. ) )
  5976. OldMaxSize = SCE_NO_VALUE;
  5977. else
  5978. OldMaxSize /= 1024;
  5979. }
  5980. //
  5981. // on DC Promo, do not reduce the log size if already higher
  5982. //
  5983. if ( !(ConfigOptions & SCE_PROMOTE_FLAG_REPLICA) ||
  5984. ((ConfigOptions & SCE_PROMOTE_FLAG_REPLICA) && (OldMaxSize * 1024 < MaxSize))) {
  5985. rc = ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  5986. MsgBuf,
  5987. L"MaxSize",
  5988. MaxSize
  5989. );
  5990. }
  5991. //
  5992. // compare and set if different
  5993. //
  5994. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  5995. (OldMaxSize != SCE_NO_VALUE) ) {
  5996. // even if OldMaxSize = MaxSize, we still need to check if the tattoo value should be deleted
  5997. ScepTattooManageOneIntValue(
  5998. hSectionDomain,
  5999. hSectionTattoo,
  6000. L"MaximumLogSize",
  6001. 0,
  6002. OldMaxSize,
  6003. rc
  6004. );
  6005. }
  6006. if (ConfigOptions & SCE_RSOP_CALLBACK)
  6007. ScepRsopLog(SCE_RSOP_AUDIT_LOG_MAXSIZE_INFO, rc, StrBuf,0,0);
  6008. }
  6009. if ( rc == SCESTATUS_SUCCESS && Retention != SCE_NO_VALUE ) {
  6010. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  6011. //
  6012. // query existing value
  6013. //
  6014. if ( ERROR_SUCCESS == ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  6015. MsgBuf,
  6016. L"Retention",
  6017. &OldRetention
  6018. ) ) {
  6019. switch ( OldRetention ) {
  6020. case MAXULONG: // manually
  6021. AuditLogRetentionPeriod = 2;
  6022. RetentionDays = SCE_NO_VALUE;
  6023. break;
  6024. case 0:
  6025. AuditLogRetentionPeriod = 0;
  6026. RetentionDays = SCE_NO_VALUE;
  6027. break;
  6028. default:
  6029. AuditLogRetentionPeriod = 1;
  6030. // number of days * seconds/day
  6031. RetentionDays = OldRetention / (24 * 3600);
  6032. break;
  6033. }
  6034. } else {
  6035. AuditLogRetentionPeriod = SCE_NO_VALUE;
  6036. RetentionDays = SCE_NO_VALUE;
  6037. }
  6038. }
  6039. rc = ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  6040. MsgBuf,
  6041. L"Retention",
  6042. Retention
  6043. );
  6044. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  6045. (OldRetention != SCE_NO_VALUE) ) {
  6046. //
  6047. // handle the RetentionDays first since
  6048. // it depends on auditlogretentionperiod
  6049. //
  6050. if ( RetentionDays != SCE_NO_VALUE ||
  6051. pScpInfo->RetentionDays[i] != SCE_NO_VALUE ) {
  6052. ScepTattooManageOneIntValueWithDependency(
  6053. hSectionDomain,
  6054. hSectionTattoo,
  6055. L"AuditLogRetentionPeriod",
  6056. 0,
  6057. L"RetentionDays",
  6058. RetentionDays,
  6059. rc
  6060. );
  6061. }
  6062. ScepTattooManageOneIntValue(
  6063. hSectionDomain,
  6064. hSectionTattoo,
  6065. L"AuditLogRetentionPeriod",
  6066. 0,
  6067. AuditLogRetentionPeriod,
  6068. rc
  6069. );
  6070. }
  6071. if (ConfigOptions & SCE_RSOP_CALLBACK)
  6072. ScepRsopLog(SCE_RSOP_AUDIT_LOG_RETENTION_INFO, rc, StrBuf,0,0);
  6073. }
  6074. if ( rc == SCESTATUS_SUCCESS && RestrictGuest != SCE_NO_VALUE ) {
  6075. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  6076. //
  6077. // query existing value
  6078. //
  6079. if ( ERROR_SUCCESS != ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  6080. MsgBuf,
  6081. L"RestrictGuestAccess",
  6082. &OldGuest
  6083. ) )
  6084. OldGuest = SCE_NO_VALUE;
  6085. }
  6086. rc = ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  6087. MsgBuf,
  6088. L"RestrictGuestAccess",
  6089. RestrictGuest
  6090. );
  6091. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  6092. (OldGuest != SCE_NO_VALUE) ) {
  6093. ScepTattooManageOneIntValue(
  6094. hSectionDomain,
  6095. hSectionTattoo,
  6096. L"RestrictGuestAccess",
  6097. 0,
  6098. OldGuest,
  6099. rc
  6100. );
  6101. }
  6102. if (ConfigOptions & SCE_RSOP_CALLBACK)
  6103. ScepRsopLog(SCE_RSOP_AUDIT_LOG_GUEST_INFO, rc, StrBuf,0,0);
  6104. }
  6105. if ( hSectionDomain ) {
  6106. SceJetCloseSection(&hSectionDomain, TRUE);
  6107. hSectionDomain = NULL;
  6108. }
  6109. if ( hSectionTattoo ) {
  6110. SceJetCloseSection(&hSectionTattoo, TRUE);
  6111. hSectionTattoo = NULL;
  6112. }
  6113. }
  6114. if ( rc != SCESTATUS_SUCCESS ) {
  6115. Saverc = rc;
  6116. ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_LOGSETTINGS);
  6117. }
  6118. }
  6119. if ( Saverc == SCESTATUS_SUCCESS && bFlagSet )
  6120. ScepLogOutput3(1,0, SCEDLL_SCP_LOGSETTINGS);
  6121. return(Saverc);
  6122. }
  6123. SCESTATUS
  6124. ScepConfigureAuditEvent(
  6125. IN PSCE_PROFILE_INFO pScpInfo,
  6126. IN PPOLICY_AUDIT_EVENTS_INFO auditEvent,
  6127. IN DWORD Options,
  6128. IN LSA_HANDLE PolicyHandle OPTIONAL
  6129. )
  6130. {
  6131. NTSTATUS status;
  6132. LSA_HANDLE lsaHandle=NULL;
  6133. DWORD rc = NO_ERROR;
  6134. DWORD Saverc = NO_ERROR;
  6135. // POLICY_AUDIT_FULL_SET_INFO AuditFullSet;
  6136. PPOLICY_AUDIT_FULL_QUERY_INFO AuditFullQry=NULL;
  6137. ULONG i;
  6138. ULONG dwAudit;
  6139. SCE_TATTOO_KEYS *pTattooKeys=NULL;
  6140. DWORD cTattooKeys=0;
  6141. PSCESECTION hSectionDomain=NULL;
  6142. PSCESECTION hSectionTattoo=NULL;
  6143. #define MAX_AUDIT_KEYS 9
  6144. if ( (Options & SCE_POLICY_TEMPLATE) &&
  6145. ScepIsSystemShutDown() ) {
  6146. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  6147. }
  6148. if ( PolicyHandle == NULL ) {
  6149. //
  6150. // Set audit event information using LSA APIs
  6151. //
  6152. status = ScepOpenLsaPolicy(
  6153. POLICY_VIEW_AUDIT_INFORMATION |
  6154. POLICY_SET_AUDIT_REQUIREMENTS |
  6155. POLICY_AUDIT_LOG_ADMIN,
  6156. &lsaHandle,
  6157. ( Options & (SCE_POLICY_TEMPLATE | SCE_SYSTEM_DB) ) ? TRUE : FALSE // do not notify policy filter if within policy prop
  6158. );
  6159. if (status != ERROR_SUCCESS) {
  6160. lsaHandle = NULL;
  6161. rc = RtlNtStatusToDosError( status );
  6162. ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
  6163. if (Options & SCE_RSOP_CALLBACK)
  6164. ScepRsopLog(SCE_RSOP_AUDIT_EVENT_INFO, rc, NULL,0,0);
  6165. return(ScepDosErrorToSceStatus(rc));
  6166. }
  6167. } else {
  6168. lsaHandle = PolicyHandle;
  6169. }
  6170. if ( (Options & SCE_POLICY_TEMPLATE) &&
  6171. ( ProductType != NtProductLanManNt ) ) {
  6172. //
  6173. // save off the current auditing settings
  6174. //
  6175. pTattooKeys = (SCE_TATTOO_KEYS *)ScepAlloc(LPTR,MAX_AUDIT_KEYS*sizeof(SCE_TATTOO_KEYS));
  6176. if ( !pTattooKeys ) {
  6177. ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_TATTOO_ERROR_CREATE);
  6178. }
  6179. }
  6180. //
  6181. // Set audit event information
  6182. //
  6183. if ( !auditEvent->AuditingMode ) {
  6184. // reset the event array
  6185. for ( i=0; i<auditEvent->MaximumAuditEventCount; i++ )
  6186. auditEvent->EventAuditingOptions[i] = POLICY_AUDIT_EVENT_NONE;
  6187. }
  6188. //
  6189. // process each event
  6190. //
  6191. i=0;
  6192. if ( (pScpInfo->AuditSystemEvents != SCE_NO_VALUE) ) {
  6193. dwAudit = (auditEvent->EventAuditingOptions[AuditCategorySystem] & ~POLICY_AUDIT_EVENT_NONE );
  6194. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6195. (PWSTR)L"AuditSystemEvents", Options,
  6196. dwAudit );
  6197. if ( (pScpInfo->AuditSystemEvents != dwAudit) ) {
  6198. auditEvent->EventAuditingOptions[AuditCategorySystem] =
  6199. (pScpInfo->AuditSystemEvents & POLICY_AUDIT_EVENT_SUCCESS) |
  6200. (pScpInfo->AuditSystemEvents & POLICY_AUDIT_EVENT_FAILURE) |
  6201. POLICY_AUDIT_EVENT_NONE;
  6202. i=1;
  6203. }
  6204. }
  6205. if ( (pScpInfo->AuditLogonEvents != SCE_NO_VALUE) ) {
  6206. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryLogon] & ~POLICY_AUDIT_EVENT_NONE );
  6207. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6208. (PWSTR)L"AuditLogonEvents", Options,
  6209. dwAudit );
  6210. if ( (pScpInfo->AuditLogonEvents != dwAudit) ) {
  6211. auditEvent->EventAuditingOptions[AuditCategoryLogon] =
  6212. (pScpInfo->AuditLogonEvents & POLICY_AUDIT_EVENT_SUCCESS) |
  6213. (pScpInfo->AuditLogonEvents & POLICY_AUDIT_EVENT_FAILURE) |
  6214. POLICY_AUDIT_EVENT_NONE;
  6215. i=1;
  6216. }
  6217. }
  6218. if ( (pScpInfo->AuditObjectAccess != SCE_NO_VALUE) ) {
  6219. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryObjectAccess] & ~POLICY_AUDIT_EVENT_NONE );
  6220. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6221. (PWSTR)L"AuditObjectAccess", Options,
  6222. dwAudit );
  6223. if ( (pScpInfo->AuditObjectAccess != dwAudit) ) {
  6224. auditEvent->EventAuditingOptions[AuditCategoryObjectAccess] =
  6225. (pScpInfo->AuditObjectAccess & POLICY_AUDIT_EVENT_SUCCESS) |
  6226. (pScpInfo->AuditObjectAccess & POLICY_AUDIT_EVENT_FAILURE) |
  6227. POLICY_AUDIT_EVENT_NONE;
  6228. i=1;
  6229. }
  6230. }
  6231. if ( (pScpInfo->AuditPrivilegeUse != SCE_NO_VALUE) ) {
  6232. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryPrivilegeUse] & ~POLICY_AUDIT_EVENT_NONE );
  6233. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6234. (PWSTR)L"AuditPrivilegeUse", Options,
  6235. dwAudit );
  6236. if ( (pScpInfo->AuditPrivilegeUse != dwAudit) ) {
  6237. auditEvent->EventAuditingOptions[AuditCategoryPrivilegeUse] =
  6238. (pScpInfo->AuditPrivilegeUse & POLICY_AUDIT_EVENT_SUCCESS) |
  6239. (pScpInfo->AuditPrivilegeUse & POLICY_AUDIT_EVENT_FAILURE) |
  6240. POLICY_AUDIT_EVENT_NONE;
  6241. i=1;
  6242. }
  6243. }
  6244. if ( (pScpInfo->AuditProcessTracking != SCE_NO_VALUE) ) {
  6245. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryDetailedTracking] & ~POLICY_AUDIT_EVENT_NONE );
  6246. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6247. (PWSTR)L"AuditProcessTracking", Options,
  6248. dwAudit );
  6249. if ( (pScpInfo->AuditProcessTracking != dwAudit) ) {
  6250. auditEvent->EventAuditingOptions[AuditCategoryDetailedTracking] =
  6251. (pScpInfo->AuditProcessTracking & POLICY_AUDIT_EVENT_SUCCESS) |
  6252. (pScpInfo->AuditProcessTracking & POLICY_AUDIT_EVENT_FAILURE) |
  6253. POLICY_AUDIT_EVENT_NONE;
  6254. i=1;
  6255. }
  6256. }
  6257. if ( (pScpInfo->AuditPolicyChange != SCE_NO_VALUE) ) {
  6258. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryPolicyChange] & ~POLICY_AUDIT_EVENT_NONE );
  6259. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6260. (PWSTR)L"AuditPolicyChange", Options,
  6261. dwAudit );
  6262. if ( (pScpInfo->AuditPolicyChange != dwAudit) ) {
  6263. auditEvent->EventAuditingOptions[AuditCategoryPolicyChange] =
  6264. (pScpInfo->AuditPolicyChange & POLICY_AUDIT_EVENT_SUCCESS) |
  6265. (pScpInfo->AuditPolicyChange & POLICY_AUDIT_EVENT_FAILURE) |
  6266. POLICY_AUDIT_EVENT_NONE;
  6267. i=1;
  6268. }
  6269. }
  6270. if ( (pScpInfo->AuditAccountManage != SCE_NO_VALUE) ) {
  6271. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryAccountManagement] & ~POLICY_AUDIT_EVENT_NONE );
  6272. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6273. (PWSTR)L"AuditAccountManage", Options,
  6274. dwAudit );
  6275. if ( (pScpInfo->AuditAccountManage != dwAudit) ) {
  6276. auditEvent->EventAuditingOptions[AuditCategoryAccountManagement] =
  6277. (pScpInfo->AuditAccountManage & POLICY_AUDIT_EVENT_SUCCESS) |
  6278. (pScpInfo->AuditAccountManage & POLICY_AUDIT_EVENT_FAILURE) |
  6279. POLICY_AUDIT_EVENT_NONE;
  6280. i=1;
  6281. }
  6282. }
  6283. if ( (pScpInfo->AuditDSAccess != SCE_NO_VALUE) ) {
  6284. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryDirectoryServiceAccess] & ~POLICY_AUDIT_EVENT_NONE );
  6285. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6286. (PWSTR)L"AuditDSAccess", Options,
  6287. dwAudit );
  6288. if ( (pScpInfo->AuditDSAccess != dwAudit) ) {
  6289. auditEvent->EventAuditingOptions[AuditCategoryDirectoryServiceAccess] =
  6290. (pScpInfo->AuditDSAccess & POLICY_AUDIT_EVENT_SUCCESS) |
  6291. (pScpInfo->AuditDSAccess & POLICY_AUDIT_EVENT_FAILURE) |
  6292. POLICY_AUDIT_EVENT_NONE;
  6293. i=1;
  6294. }
  6295. }
  6296. if ( (pScpInfo->AuditAccountLogon != SCE_NO_VALUE) ) {
  6297. dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryAccountLogon] & ~POLICY_AUDIT_EVENT_NONE );
  6298. ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
  6299. (PWSTR)L"AuditAccountLogon", Options,
  6300. dwAudit );
  6301. if ( (pScpInfo->AuditAccountLogon != dwAudit) ) {
  6302. auditEvent->EventAuditingOptions[AuditCategoryAccountLogon] =
  6303. (pScpInfo->AuditAccountLogon & POLICY_AUDIT_EVENT_SUCCESS) |
  6304. (pScpInfo->AuditAccountLogon & POLICY_AUDIT_EVENT_FAILURE) |
  6305. POLICY_AUDIT_EVENT_NONE;
  6306. i=1;
  6307. }
  6308. }
  6309. if ( i ) {
  6310. //
  6311. // there are some settings to configure
  6312. //
  6313. auditEvent->AuditingMode = FALSE;
  6314. for ( i=0; i<auditEvent->MaximumAuditEventCount; i++ ) {
  6315. if ( auditEvent->EventAuditingOptions[i] & ~POLICY_AUDIT_EVENT_NONE ) {
  6316. auditEvent->AuditingMode = TRUE;
  6317. break;
  6318. }
  6319. }
  6320. status = LsaSetInformationPolicy( lsaHandle,
  6321. PolicyAuditEventsInformation,
  6322. (PVOID)auditEvent
  6323. );
  6324. rc = RtlNtStatusToDosError( status );
  6325. if ( rc != NO_ERROR ) {
  6326. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
  6327. Saverc = rc;
  6328. } else {
  6329. ScepLogOutput3(1, 0, SCEDLL_SCP_EVENT_AUDITING);
  6330. }
  6331. //
  6332. // turn the mode off so auditing won't be "restored" at the end of configuration
  6333. //
  6334. auditEvent->AuditingMode = FALSE;
  6335. }
  6336. if ( (Options & SCE_POLICY_TEMPLATE) &&
  6337. ( ProductType != NtProductLanManNt ) &&
  6338. pTattooKeys && cTattooKeys ) {
  6339. ScepTattooOpenPolicySections(
  6340. hProfile,
  6341. szAuditEvent,
  6342. &hSectionDomain,
  6343. &hSectionTattoo
  6344. );
  6345. //
  6346. // some policy is different than the system setting
  6347. // check if we should save the existing setting as the tattoo value
  6348. // also remove reset'ed tattoo policy
  6349. //
  6350. ScepLogOutput3(3,0,SCESRV_POLICY_TATTOO_ARRAY,cTattooKeys);
  6351. ScepTattooManageValues(hSectionDomain, hSectionTattoo, pTattooKeys, cTattooKeys, rc);
  6352. if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain,TRUE);
  6353. if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo,TRUE);
  6354. }
  6355. if ( pTattooKeys )
  6356. ScepFree(pTattooKeys);
  6357. if (Options & SCE_RSOP_CALLBACK)
  6358. ScepRsopLog(SCE_RSOP_AUDIT_EVENT_INFO, rc, NULL,0,0);
  6359. if ( lsaHandle && (PolicyHandle != lsaHandle) )
  6360. LsaClose( lsaHandle );
  6361. return(ScepDosErrorToSceStatus(Saverc));
  6362. }
  6363. SCESTATUS
  6364. ScepConfigureDeInitialize(
  6365. IN SCESTATUS rc,
  6366. IN AREA_INFORMATION Area
  6367. )
  6368. /*++
  6369. Routine Description:
  6370. This routine de-initialize the SCP engine. The operations include
  6371. clear SCE_PROFILE_INFO buffer and close the SCP profile
  6372. close the error log file
  6373. reset the status
  6374. Arguments:
  6375. rc - SCESTATUS error code (from other routines)
  6376. Area - one or more area configured
  6377. Return value:
  6378. SCESTATUS error code
  6379. ++*/
  6380. {
  6381. if ( rc == SCESTATUS_ALREADY_RUNNING ) {
  6382. return(SCESTATUS_SUCCESS);
  6383. }
  6384. //
  6385. // free LSA handle
  6386. //
  6387. if ( LsaPrivatePolicy ) {
  6388. ScepNotifyLogPolicy(0, TRUE, L"Policy Prop: Private LSA handle is to be released", 0, 0, NULL );
  6389. LsaClose(LsaPrivatePolicy);
  6390. LsaPrivatePolicy = NULL;
  6391. }
  6392. //
  6393. // Free memory and close the SCP profile
  6394. //
  6395. SceFreeMemory( (PVOID)pScpInfo, Area );
  6396. cbClientFlag = 0;
  6397. gTotalTicks = 0;
  6398. gCurrentTicks = 0;
  6399. gWarningCode = 0;
  6400. if ( hProfile != NULL ) {
  6401. SceJetCloseFile( hProfile, TRUE, FALSE );
  6402. }
  6403. hProfile = NULL;
  6404. return(SCESTATUS_SUCCESS);
  6405. }
  6406. SCESTATUS
  6407. ScepDeleteInfoForAreas(
  6408. IN PSCECONTEXT hProfile,
  6409. IN SCETYPE tblType,
  6410. IN AREA_INFORMATION Area
  6411. )
  6412. {
  6413. SCESTATUS saveRc=SCESTATUS_SUCCESS, rc;
  6414. PSCE_SERVICES pServices=NULL, pNode;
  6415. PSCE_NAME_LIST pList=NULL, pnl;
  6416. if ( Area & AREA_SECURITY_POLICY ) {
  6417. //
  6418. // delete szSystemAccess section info
  6419. //
  6420. rc = ScepDeleteOneSection(
  6421. hProfile,
  6422. tblType,
  6423. szSystemAccess
  6424. );
  6425. if ( saveRc == SCESTATUS_SUCCESS )
  6426. saveRc = rc;
  6427. //
  6428. // delete szAuditSystemLog section info
  6429. //
  6430. rc = ScepDeleteOneSection(
  6431. hProfile,
  6432. tblType,
  6433. szAuditSystemLog
  6434. );
  6435. if ( saveRc == SCESTATUS_SUCCESS )
  6436. saveRc = rc;
  6437. //
  6438. // delete szAuditSecurityLog section info
  6439. //
  6440. rc = ScepDeleteOneSection(
  6441. hProfile,
  6442. tblType,
  6443. szAuditSecurityLog
  6444. );
  6445. if ( saveRc == SCESTATUS_SUCCESS )
  6446. saveRc = rc;
  6447. //
  6448. // delete szAuditApplicationLog section info
  6449. //
  6450. rc = ScepDeleteOneSection(
  6451. hProfile,
  6452. tblType,
  6453. szAuditApplicationLog
  6454. );
  6455. if ( saveRc == SCESTATUS_SUCCESS )
  6456. saveRc = rc;
  6457. //
  6458. // delete szAuditEvent section info
  6459. //
  6460. rc = ScepDeleteOneSection(
  6461. hProfile,
  6462. tblType,
  6463. szAuditEvent
  6464. );
  6465. if ( saveRc == SCESTATUS_SUCCESS )
  6466. saveRc = rc;
  6467. //
  6468. // delete szKerberosPolicy section info
  6469. //
  6470. rc = ScepDeleteOneSection(
  6471. hProfile,
  6472. tblType,
  6473. szKerberosPolicy
  6474. );
  6475. if ( saveRc == SCESTATUS_SUCCESS )
  6476. saveRc = rc;
  6477. //
  6478. // delete szRegistryValues section info
  6479. //
  6480. rc = ScepDeleteOneSection(
  6481. hProfile,
  6482. tblType,
  6483. szRegistryValues
  6484. );
  6485. if ( saveRc == SCESTATUS_SUCCESS )
  6486. saveRc = rc;
  6487. //
  6488. // delete each attachment's sections
  6489. //
  6490. rc = ScepEnumServiceEngines( &pServices, SCE_ATTACHMENT_POLICY );
  6491. if ( rc == SCESTATUS_SUCCESS ) {
  6492. for ( pNode = pServices; pNode != NULL; pNode=pNode->Next ) {
  6493. rc = ScepDeleteOneSection(
  6494. hProfile,
  6495. tblType,
  6496. (PCWSTR)(pNode->ServiceName)
  6497. );
  6498. if ( saveRc == SCESTATUS_SUCCESS )
  6499. saveRc = rc;
  6500. }
  6501. SceFreePSCE_SERVICES( pServices );
  6502. } else if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
  6503. rc != SCESTATUS_RECORD_NOT_FOUND &&
  6504. saveRc == SCESTATUS_SUCCESS ) {
  6505. saveRc = rc;
  6506. }
  6507. }
  6508. if ( Area & AREA_PRIVILEGES ) {
  6509. //
  6510. // delete szPrivilegeRights section info
  6511. //
  6512. rc = ScepDeleteOneSection(
  6513. hProfile,
  6514. tblType,
  6515. szPrivilegeRights
  6516. );
  6517. if ( saveRc == SCESTATUS_SUCCESS )
  6518. saveRc = rc;
  6519. }
  6520. if ( Area & AREA_GROUP_MEMBERSHIP ) {
  6521. //
  6522. // delete szGroupMembership section info
  6523. //
  6524. rc = ScepDeleteOneSection(
  6525. hProfile,
  6526. tblType,
  6527. szGroupMembership
  6528. );
  6529. if ( saveRc == SCESTATUS_SUCCESS )
  6530. saveRc = rc;
  6531. }
  6532. if ( Area & AREA_USER_SETTINGS ) {
  6533. //
  6534. // later - delete the list of profiles/users first
  6535. //
  6536. //
  6537. // delete szAccountProfiles/szUserList section info
  6538. //
  6539. if ( tblType == SCEJET_TABLE_SAP) {
  6540. rc = ScepDeleteOneSection(
  6541. hProfile,
  6542. tblType,
  6543. szUserList
  6544. );
  6545. } else {
  6546. rc = ScepDeleteOneSection(
  6547. hProfile,
  6548. tblType,
  6549. szAccountProfiles
  6550. );
  6551. }
  6552. if ( saveRc == SCESTATUS_SUCCESS )
  6553. saveRc = rc;
  6554. }
  6555. if ( Area & AREA_FILE_SECURITY ) {
  6556. //
  6557. // delete szFileSecurity section info
  6558. //
  6559. rc = ScepDeleteOneSection(
  6560. hProfile,
  6561. tblType,
  6562. szFileSecurity
  6563. );
  6564. if ( saveRc == SCESTATUS_SUCCESS )
  6565. saveRc = rc;
  6566. }
  6567. if ( Area & AREA_REGISTRY_SECURITY ) {
  6568. //
  6569. // delete szRegistryKeys section info
  6570. //
  6571. rc = ScepDeleteOneSection(
  6572. hProfile,
  6573. tblType,
  6574. szRegistryKeys
  6575. );
  6576. if ( saveRc == SCESTATUS_SUCCESS )
  6577. saveRc = rc;
  6578. }
  6579. if ( Area & AREA_DS_OBJECTS ) {
  6580. //
  6581. // delete szDSSecurity section info
  6582. //
  6583. rc = ScepDeleteOneSection(
  6584. hProfile,
  6585. tblType,
  6586. szDSSecurity
  6587. );
  6588. if ( saveRc == SCESTATUS_SUCCESS )
  6589. saveRc = rc;
  6590. }
  6591. if ( Area & AREA_SYSTEM_SERVICE ) {
  6592. //
  6593. // delete szServiceGeneral section info
  6594. //
  6595. rc = ScepDeleteOneSection(
  6596. hProfile,
  6597. tblType,
  6598. szServiceGeneral
  6599. );
  6600. if ( saveRc == SCESTATUS_SUCCESS )
  6601. saveRc = rc;
  6602. //
  6603. // delete each attachment's sections
  6604. //
  6605. rc = ScepEnumServiceEngines( &pServices, SCE_ATTACHMENT_SERVICE );
  6606. if ( rc == SCESTATUS_SUCCESS ) {
  6607. for ( pNode = pServices; pNode != NULL; pNode=pNode->Next ) {
  6608. rc = ScepDeleteOneSection(
  6609. hProfile,
  6610. tblType,
  6611. (PCWSTR)(pNode->ServiceName)
  6612. );
  6613. if ( saveRc == SCESTATUS_SUCCESS )
  6614. saveRc = rc;
  6615. }
  6616. SceFreePSCE_SERVICES( pServices );
  6617. } else if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
  6618. rc != SCESTATUS_RECORD_NOT_FOUND &&
  6619. saveRc == SCESTATUS_SUCCESS ) {
  6620. saveRc = rc;
  6621. }
  6622. }
  6623. if ( Area & AREA_ATTACHMENTS ) {
  6624. //
  6625. // delete attachment sections
  6626. //
  6627. rc = ScepEnumAttachmentSections( hProfile, &pList);
  6628. if ( rc == SCESTATUS_SUCCESS ) {
  6629. for ( pnl = pList; pnl != NULL; pnl=pnl->Next ) {
  6630. rc = ScepDeleteOneSection(
  6631. hProfile,
  6632. tblType,
  6633. (PCWSTR)(pnl->Name)
  6634. );
  6635. if ( saveRc == SCESTATUS_SUCCESS )
  6636. saveRc = rc;
  6637. }
  6638. ScepFreeNameList( pList );
  6639. } else if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
  6640. rc != SCESTATUS_RECORD_NOT_FOUND &&
  6641. saveRc == SCESTATUS_SUCCESS ) {
  6642. saveRc = rc;
  6643. }
  6644. }
  6645. return(saveRc);
  6646. }
  6647. SCESTATUS
  6648. ScepMakePolicyIntoFile(
  6649. IN DWORD Options,
  6650. IN AREA_INFORMATION Area
  6651. )
  6652. {
  6653. SCESTATUS rc=SCESTATUS_SUCCESS;
  6654. if ( Options & SCE_COPY_LOCAL_POLICY ) {
  6655. PSCE_PROFILE_INFO pTmpBuffer=NULL;
  6656. HINSTANCE hSceCliDll = LoadLibrary(TEXT("scecli.dll"));
  6657. if ( hSceCliDll) {
  6658. PFSCEINFWRITEINFO pfSceInfWriteInfo = (PFSCEINFWRITEINFO)GetProcAddress(
  6659. hSceCliDll,
  6660. "SceWriteSecurityProfileInfo");
  6661. if ( pfSceInfWriteInfo ) {
  6662. //
  6663. // have to query the current system setting for privileges
  6664. // because IIS/MTS accounts do not exist in our database
  6665. // we only support AREA_SECURITY_POLICY and AREA_PRIVILEGES
  6666. //
  6667. TCHAR FileName[MAX_PATH+50];
  6668. FileName[0] = L'\0';
  6669. GetSystemWindowsDirectory(FileName, MAX_PATH);
  6670. FileName[MAX_PATH] = L'\0';
  6671. DWORD WindirLen = wcslen(FileName);
  6672. if ( Area & AREA_SECURITY_POLICY ) {
  6673. //
  6674. // get other area's information (AREA_SECURITY_POLICY)
  6675. //
  6676. rc = ScepGetDatabaseInfo(
  6677. hProfile,
  6678. SCE_ENGINE_SMP,
  6679. AREA_SECURITY_POLICY,
  6680. 0,
  6681. &pTmpBuffer,
  6682. NULL
  6683. );
  6684. if ( SCESTATUS_SUCCESS == rc ) {
  6685. wcscat(FileName, L"\\security\\FirstDGPO.inf\0");
  6686. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6687. (LPCTSTR)FileName,
  6688. TEXT("MinimumPasswordAge"),
  6689. pTmpBuffer->MinimumPasswordAge
  6690. );
  6691. if ( ERROR_SUCCESS == rc ) {
  6692. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6693. (LPCTSTR)FileName,
  6694. TEXT("MaximumPasswordAge"),
  6695. pTmpBuffer->MaximumPasswordAge
  6696. );
  6697. }
  6698. if ( ERROR_SUCCESS == rc ) {
  6699. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6700. (LPCTSTR)FileName,
  6701. TEXT("MinimumPasswordLength"),
  6702. pTmpBuffer->MinimumPasswordLength
  6703. );
  6704. }
  6705. if ( ERROR_SUCCESS == rc ) {
  6706. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6707. (LPCTSTR)FileName,
  6708. TEXT("PasswordComplexity"),
  6709. pTmpBuffer->PasswordComplexity
  6710. );
  6711. }
  6712. if ( ERROR_SUCCESS == rc ) {
  6713. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6714. (LPCTSTR)FileName,
  6715. TEXT("PasswordHistorySize"),
  6716. pTmpBuffer->PasswordHistorySize
  6717. );
  6718. }
  6719. if ( ERROR_SUCCESS == rc ) {
  6720. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6721. (LPCTSTR)FileName,
  6722. TEXT("LockoutBadCount"),
  6723. pTmpBuffer->LockoutBadCount
  6724. );
  6725. }
  6726. if ( ERROR_SUCCESS == rc ) {
  6727. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6728. (LPCTSTR)FileName,
  6729. TEXT("ResetLockoutCount"),
  6730. pTmpBuffer->ResetLockoutCount
  6731. );
  6732. }
  6733. if ( ERROR_SUCCESS == rc ) {
  6734. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6735. (LPCTSTR)FileName,
  6736. TEXT("LockoutDuration"),
  6737. pTmpBuffer->LockoutDuration
  6738. );
  6739. }
  6740. if ( ERROR_SUCCESS == rc ) {
  6741. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6742. (LPCTSTR)FileName,
  6743. TEXT("RequireLogonToChangePassword"),
  6744. pTmpBuffer->RequireLogonToChangePassword
  6745. );
  6746. }
  6747. if ( ERROR_SUCCESS == rc ) {
  6748. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6749. (LPCTSTR)FileName,
  6750. TEXT("ForceLogoffWhenHourExpire"),
  6751. pTmpBuffer->ForceLogoffWhenHourExpire
  6752. );
  6753. }
  6754. if ( ERROR_SUCCESS == rc ) {
  6755. rc = ScepWriteOneAttributeToFile(szSystemAccess,
  6756. (LPCTSTR)FileName,
  6757. TEXT("ClearTextPassword"),
  6758. pTmpBuffer->ClearTextPassword
  6759. );
  6760. }
  6761. if ( ERROR_SUCCESS == rc && pTmpBuffer->pKerberosInfo ) {
  6762. rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
  6763. (LPCTSTR)FileName,
  6764. TEXT("MaxTicketAge"),
  6765. pTmpBuffer->pKerberosInfo->MaxTicketAge
  6766. );
  6767. if ( ERROR_SUCCESS == rc ) {
  6768. rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
  6769. (LPCTSTR)FileName,
  6770. TEXT("MaxRenewAge"),
  6771. pTmpBuffer->pKerberosInfo->MaxRenewAge
  6772. );
  6773. }
  6774. if ( ERROR_SUCCESS == rc ) {
  6775. rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
  6776. (LPCTSTR)FileName,
  6777. TEXT("MaxServiceAge"),
  6778. pTmpBuffer->pKerberosInfo->MaxServiceAge
  6779. );
  6780. }
  6781. if ( ERROR_SUCCESS == rc ) {
  6782. rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
  6783. (LPCTSTR)FileName,
  6784. TEXT("MaxClockSkew"),
  6785. pTmpBuffer->pKerberosInfo->MaxClockSkew
  6786. );
  6787. }
  6788. if ( ERROR_SUCCESS == rc ) {
  6789. rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
  6790. (LPCTSTR)FileName,
  6791. TEXT("TicketValidateClient"),
  6792. pTmpBuffer->pKerberosInfo->TicketValidateClient
  6793. );
  6794. }
  6795. }
  6796. if ( ERROR_SUCCESS == rc ) {
  6797. //
  6798. // make sure to delete the local policy sections
  6799. //
  6800. WritePrivateProfileSection(
  6801. szAuditSystemLog,
  6802. NULL,
  6803. (LPCTSTR)FileName);
  6804. WritePrivateProfileSection(
  6805. szAuditSecurityLog,
  6806. NULL,
  6807. (LPCTSTR)FileName);
  6808. WritePrivateProfileSection(
  6809. szAuditApplicationLog,
  6810. NULL,
  6811. (LPCTSTR)FileName);
  6812. WritePrivateProfileSection(
  6813. szAuditEvent,
  6814. NULL,
  6815. (LPCTSTR)FileName);
  6816. WritePrivateProfileSection(
  6817. szRegistryValues,
  6818. NULL,
  6819. (LPCTSTR)FileName);
  6820. }
  6821. ScepLogOutput3(1, rc, IDS_COPY_DOMAIN_GPO);
  6822. rc = ScepDosErrorToSceStatus(rc);
  6823. if ( SCESTATUS_SUCCESS == rc ) {
  6824. wcscpy(FileName+WindirLen, L"\\security\\FirstOGPO.inf\0");
  6825. //
  6826. // do not write registry value section
  6827. //
  6828. DWORD RegValueCount;
  6829. PSCE_REGISTRY_VALUE_INFO pSaveRegValues;
  6830. RegValueCount = pTmpBuffer->RegValueCount;
  6831. pSaveRegValues = pTmpBuffer->aRegValues;
  6832. pTmpBuffer->RegValueCount = 0;
  6833. pTmpBuffer->aRegValues = NULL;
  6834. PSCE_PROFILE_INFO ExistingTemplateProfileInfo = NULL;
  6835. //
  6836. // need to get existing information for registry values from default DC GPO
  6837. //
  6838. rc = ScepGetTemplateInformation(FileName,
  6839. AREA_SECURITY_POLICY,
  6840. hSceCliDll,
  6841. &ExistingTemplateProfileInfo);
  6842. if ( rc == SCESTATUS_SUCCESS ) {
  6843. rc = (*pfSceInfWriteInfo)(
  6844. FileName,
  6845. AREA_SECURITY_POLICY,
  6846. pTmpBuffer,
  6847. NULL
  6848. );
  6849. if ( rc == SCESTATUS_SUCCESS ) {
  6850. SCE_PROFILE_INFO SystemInfo;
  6851. memset (&SystemInfo , 0, sizeof(SCE_PROFILE_INFO));
  6852. rc = ScepAnalyzeRegistryValues(NULL,
  6853. SCEREG_VALUE_SYSTEM,
  6854. &SystemInfo
  6855. );
  6856. if ( rc == SCESTATUS_SUCCESS ) {
  6857. ScepWriteSpecialRegistryValuesIntoPolicy(FileName, ExistingTemplateProfileInfo, SystemInfo.aRegValues, SystemInfo.RegValueCount);
  6858. SceFreeMemory((PVOID)&SystemInfo, AREA_SECURITY_POLICY);
  6859. }
  6860. }
  6861. SceFreeMemory((PVOID)ExistingTemplateProfileInfo, AREA_SECURITY_POLICY);
  6862. ScepFree(ExistingTemplateProfileInfo);
  6863. }
  6864. //
  6865. // restore the buffer
  6866. //
  6867. pTmpBuffer->RegValueCount = RegValueCount;
  6868. pTmpBuffer->aRegValues = pSaveRegValues;
  6869. if ( SCESTATUS_SUCCESS == rc ) {
  6870. //
  6871. // delete the domain policy sections from this file
  6872. //
  6873. WritePrivateProfileSection(
  6874. szSystemAccess,
  6875. NULL,
  6876. (LPCTSTR)FileName);
  6877. WritePrivateProfileSection(
  6878. szKerberosPolicy,
  6879. NULL,
  6880. (LPCTSTR)FileName);
  6881. /*
  6882. WritePrivateProfileSection(
  6883. szRegistryValues,
  6884. NULL,
  6885. (LPCTSTR)FileName);
  6886. */
  6887. }
  6888. ScepLogOutput3(1, rc, IDS_COPY_OU_GPO);
  6889. }
  6890. //
  6891. // free the temp buffer
  6892. //
  6893. SceFreeMemory((PVOID)pTmpBuffer, Area);
  6894. } else {
  6895. ScepLogOutput2(1, ScepSceStatusToDosError(rc), L"Unable to read security policy from database");
  6896. }
  6897. }
  6898. if ( (SCESTATUS_SUCCESS == rc) &&
  6899. (Area & AREA_PRIVILEGES) ) {
  6900. //
  6901. // privileges must be processed separately
  6902. // because they are saved in the GPO template
  6903. // as "Add/Remove" format
  6904. //
  6905. wcscpy(FileName+WindirLen, L"\\security\\FirstOGPO.inf\0");
  6906. //
  6907. // if security policy is also requested, this must be an upgrade
  6908. //
  6909. rc = ScepCopyPrivilegesIntoFile(FileName,
  6910. (Area & AREA_SECURITY_POLICY) //TRUE upgrade
  6911. );
  6912. if ( Area & AREA_SECURITY_POLICY ) {
  6913. ScepLogOutput3(1, ScepSceStatusToDosError(rc), IDS_COPY_PRIVILEGE_UPGRADE);
  6914. } else {
  6915. ScepLogOutput3(1, ScepSceStatusToDosError(rc), IDS_COPY_PRIVILEGE_FRESH);
  6916. }
  6917. }
  6918. } else {
  6919. ScepLogOutput3(1, GetLastError(), IDS_ERROR_GET_PROCADDR, L"SceWriteSecurityProfileInfo");
  6920. rc = SCESTATUS_MOD_NOT_FOUND;
  6921. }
  6922. FreeLibrary(hSceCliDll);
  6923. } else {
  6924. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_LOAD, L"scecli.dll");
  6925. rc = SCESTATUS_MOD_NOT_FOUND;
  6926. }
  6927. }
  6928. return rc;
  6929. }
  6930. VOID
  6931. ScepWriteSpecialRegistryValuesIntoPolicy(
  6932. PWSTR pszFileName,
  6933. PSCE_PROFILE_INFO pTemplateProfile,
  6934. PSCE_REGISTRY_VALUE_INFO pLocalRegSettings,
  6935. DWORD dwNumLocalSettings
  6936. )
  6937. /*++
  6938. Routine Description:
  6939. This routine writes certain registry values to the default DC policy
  6940. If the existing system has the registry values configured stronger, those values will win
  6941. Arguments:
  6942. pszFileName - the name of the policy file
  6943. pTemplateProfile - the existing policy file settings
  6944. pLocalRegSettings - local registry value policy
  6945. dwNumLocalSettings - number of settings in local registry value policy
  6946. Return value:
  6947. none
  6948. ++*/
  6949. {
  6950. WCHAR szValue[MAX_PATH];
  6951. for (DWORD dwIndex = 0; dwIndex < pTemplateProfile->RegValueCount; dwIndex++ ) {
  6952. if (pTemplateProfile->aRegValues[dwIndex].ValueType != REG_DWORD) {
  6953. continue;
  6954. }
  6955. SCE_REGISTRY_VALUE_INFO RegWinner = pTemplateProfile->aRegValues[dwIndex];
  6956. szValue[0] = L'\0';
  6957. for (DWORD dwLocalIndex = 0; dwLocalIndex < dwNumLocalSettings; dwLocalIndex++ ) {
  6958. if (pLocalRegSettings[dwLocalIndex].FullValueName != NULL &&
  6959. pTemplateProfile->aRegValues[dwIndex].FullValueName != NULL &&
  6960. 0 == _wcsicmp(pLocalRegSettings[dwLocalIndex].FullValueName, pTemplateProfile->aRegValues[dwIndex].FullValueName)) {
  6961. //
  6962. // determine the winning value
  6963. //
  6964. if (pLocalRegSettings[dwLocalIndex].Value != NULL && pTemplateProfile->aRegValues[dwIndex].Value != NULL ) {
  6965. if (_wcsicmp(pLocalRegSettings[dwLocalIndex].Value,
  6966. pTemplateProfile->aRegValues[dwIndex].Value) > 0 ) {
  6967. RegWinner = pLocalRegSettings[dwLocalIndex];
  6968. }
  6969. }
  6970. }
  6971. }
  6972. _snwprintf(szValue, MAX_PATH - 1, L"%1d,%s\0", RegWinner.ValueType, RegWinner.Value );
  6973. WritePrivateProfileString (szRegistryValues, RegWinner.FullValueName, szValue, pszFileName);
  6974. }
  6975. return;
  6976. }
  6977. DWORD
  6978. ScepGetTemplateInformation(
  6979. IN PWSTR pszFilename,
  6980. IN DWORD Area,
  6981. IN HINSTANCE hSceCliDll,
  6982. OUT PSCE_PROFILE_INFO *pProfileInfo
  6983. )
  6984. /*++
  6985. Routine Description:
  6986. This gets information from a given template using the dynammically loaded scecli DLL
  6987. Arguments:
  6988. pszFilename - name of the template to get information from
  6989. Area - areas to get information about
  6990. hSceCliDll - handle to dll
  6991. *pProfileInfo - the profile to be filled in
  6992. Return value:
  6993. SCESTATUS error code
  6994. ++*/
  6995. {
  6996. DWORD rc;
  6997. PVOID h_Profile = NULL;
  6998. PFSCEOPENPROFILE pfnSceOpenProfile = (PFSCEOPENPROFILE)GetProcAddress(
  6999. hSceCliDll,
  7000. "SceOpenProfile");
  7001. PFSCECLOSEPROFILE pfnSceCloseProfile = (PFSCECLOSEPROFILE)GetProcAddress(
  7002. hSceCliDll,
  7003. "SceCloseProfile");
  7004. PFSCEGETINFO pfnSceGetSecurityProfileInfo = (PFSCEGETINFO)GetProcAddress(
  7005. hSceCliDll,
  7006. "SceGetSecurityProfileInfo");
  7007. if (pfnSceGetSecurityProfileInfo == NULL ||
  7008. pfnSceCloseProfile == NULL ||
  7009. pfnSceOpenProfile == NULL) {
  7010. return SCESTATUS_MOD_NOT_FOUND;
  7011. }
  7012. rc = ( *pfnSceOpenProfile) (pszFilename,
  7013. SCE_INF_FORMAT,
  7014. &h_Profile);
  7015. if ( rc == SCESTATUS_SUCCESS && h_Profile ) {
  7016. rc = ( *pfnSceGetSecurityProfileInfo) (h_Profile,
  7017. SCE_ENGINE_SCP,
  7018. Area,
  7019. pProfileInfo,
  7020. NULL);
  7021. (* pfnSceCloseProfile) (&h_Profile);
  7022. }
  7023. return rc;
  7024. }
  7025. DWORD
  7026. ScepWriteOneAttributeToFile(
  7027. IN LPCTSTR SectionName,
  7028. IN LPCTSTR FileName,
  7029. IN LPCTSTR KeyName,
  7030. IN DWORD dwValue
  7031. )
  7032. {
  7033. TCHAR valBuf[20];
  7034. DWORD rc=NO_ERROR;
  7035. if ( dwValue != SCE_NO_VALUE ) {
  7036. swprintf(valBuf, L"%d", dwValue);
  7037. if ( !WritePrivateProfileString(SectionName,
  7038. KeyName,
  7039. (LPCTSTR)valBuf,
  7040. FileName
  7041. ) ) {
  7042. rc = GetLastError();
  7043. }
  7044. }
  7045. return rc;
  7046. }
  7047. SCESTATUS
  7048. ScepCopyPrivilegesIntoFile(
  7049. IN LPTSTR FileName,
  7050. IN BOOL bInUpgrade
  7051. )
  7052. {
  7053. if ( FileName == NULL ) {
  7054. return SCESTATUS_INVALID_PARAMETER;
  7055. }
  7056. SCESTATUS rc;
  7057. HINF hInf;
  7058. rc = SceInfpOpenProfile(
  7059. FileName,
  7060. &hInf
  7061. );
  7062. if ( SCESTATUS_SUCCESS != rc ) {
  7063. return rc;
  7064. }
  7065. INFCONTEXT InfLine;
  7066. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  7067. PWSTR StrValue=NULL;
  7068. DWORD ValueLen=0;
  7069. TCHAR TmpNull[2];
  7070. LSA_HANDLE LsaPolicy=NULL;
  7071. TmpNull[0] = L'\0';
  7072. TmpNull[1] = L'\0';
  7073. PSCESECTION hSection=NULL;
  7074. if ( SetupFindFirstLine(hInf,szPrivilegeRights,NULL,&InfLine) ) {
  7075. //
  7076. // do not need database access to get privilege
  7077. // must query from system at real time
  7078. //
  7079. //
  7080. // process each line in the section and save to the scp table.
  7081. // Each INF line has a key and a value.
  7082. //
  7083. do {
  7084. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(TCHAR));
  7085. rc = SCESTATUS_BAD_FORMAT;
  7086. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  7087. //
  7088. // do not save new privileges into the policy file because
  7089. // W2K clients (DCs) do not support them.
  7090. //
  7091. for (DWORD i=cPrivW2k; i<cPrivCnt; i++) {
  7092. if ( _wcsicmp(Keyname, SCE_Privileges[i].Name) == 0 )
  7093. break;
  7094. }
  7095. if ( i < cPrivCnt ) {
  7096. // this is a new user right
  7097. // do not save it in policy
  7098. rc = SCESTATUS_SUCCESS;
  7099. if ( !WritePrivateProfileString(szPrivilegeRights,
  7100. Keyname,
  7101. NULL,
  7102. FileName
  7103. ) ) {
  7104. rc = ScepDosErrorToSceStatus(GetLastError());
  7105. }
  7106. ScepLogOutput3( 1, ScepDosErrorToSceStatus(rc), SCEDLL_ERROR_IGNORE_POLICY, Keyname);
  7107. continue;
  7108. }
  7109. if ( SetupGetMultiSzField(&InfLine, 1, NULL, 0, &ValueLen) ) {
  7110. if ( ValueLen > 1 ) {
  7111. //
  7112. // allocate buffer for the multi string
  7113. //
  7114. StrValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  7115. (ValueLen+1)*sizeof(TCHAR));
  7116. if( StrValue == NULL ) {
  7117. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  7118. } else if( SetupGetMultiSzField(&InfLine, 1, StrValue, ValueLen, NULL) ) {
  7119. rc = SCESTATUS_SUCCESS;
  7120. } else {
  7121. ScepFree(StrValue);
  7122. StrValue = NULL;
  7123. }
  7124. } else
  7125. rc = SCESTATUS_SUCCESS;
  7126. if ( rc == SCESTATUS_SUCCESS ) {
  7127. //
  7128. // another format for user rights (ADD: REMOVE:...)
  7129. // Note, if this is within dcpromo upgrade, the current boot
  7130. // is in the temperatory SAM hive (with a bogus domain SID)
  7131. // IIS/MTS users created during this boot are bogus
  7132. // and any users from the NT4 account domain/trusted domain
  7133. // can't be resolved at this moment.
  7134. // So do not enumerate current privileges, instead, use
  7135. // the settings from local security database.
  7136. //
  7137. PWSTR NewValue=NULL;
  7138. DWORD NewLen=0;
  7139. rc = ScepBuildNewPrivilegeList(&LsaPolicy,
  7140. Keyname,
  7141. StrValue ? StrValue : TmpNull,
  7142. SCE_BUILD_ENUMERATE_PRIV,
  7143. &NewValue,
  7144. &NewLen);
  7145. if ( StrValue ) {
  7146. ScepFree(StrValue);
  7147. }
  7148. if ( rc == SCESTATUS_SUCCESS ) {
  7149. //
  7150. // convert the multi-sz string into comma delimted
  7151. // and write the new multi-sz string back to the file
  7152. //
  7153. if ( NewValue ) {
  7154. ScepConvertMultiSzToDelim(NewValue, NewLen, L'\0', L',');
  7155. }
  7156. if ( !WritePrivateProfileString(szPrivilegeRights,
  7157. Keyname,
  7158. NewValue ? (LPCTSTR)NewValue : (LPCTSTR)TmpNull,
  7159. FileName
  7160. ) ) {
  7161. rc = ScepDosErrorToSceStatus(GetLastError());
  7162. }
  7163. }
  7164. if ( NewValue ) {
  7165. ScepFree(NewValue);
  7166. }
  7167. NewValue = NULL;
  7168. }
  7169. StrValue = NULL;
  7170. }
  7171. if (rc != SCESTATUS_SUCCESS)
  7172. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  7173. SCEDLL_ERROR_CONVERT, Keyname);
  7174. }
  7175. } while( rc == SCESTATUS_SUCCESS && SetupFindNextLine(&InfLine, &InfLine));
  7176. }
  7177. if ( hSection ) {
  7178. SceJetCloseSection( &hSection, TRUE );
  7179. }
  7180. SceInfpCloseProfile(hInf);
  7181. if ( LsaPolicy ) {
  7182. LsaClose(LsaPolicy);
  7183. }
  7184. return rc;
  7185. }
  7186. SCESTATUS
  7187. ScepCopyPrivilegesFromDatabase(
  7188. IN PSCESECTION hSection,
  7189. IN PWSTR Keyname,
  7190. IN DWORD StrLength,
  7191. IN PWSTR StrValue OPTIONAL,
  7192. OUT PWSTR *pOldValue,
  7193. OUT DWORD *pOldLen
  7194. )
  7195. {
  7196. if ( hSection == NULL ||
  7197. Keyname == NULL ||
  7198. pOldValue == NULL ) {
  7199. return(SCESTATUS_INVALID_PARAMETER);
  7200. }
  7201. *pOldValue = NULL;
  7202. *pOldLen = 0;
  7203. SCESTATUS rc;
  7204. DWORD ValueLen;
  7205. rc = SceJetGetValue(
  7206. hSection,
  7207. SCEJET_EXACT_MATCH_NO_CASE,
  7208. Keyname,
  7209. NULL,
  7210. 0,
  7211. NULL,
  7212. NULL,
  7213. 0,
  7214. &ValueLen
  7215. );
  7216. if ( SCESTATUS_SUCCESS == rc ) {
  7217. DWORD Len = wcslen(SCE_PRIV_ADD);
  7218. *pOldValue = (PWSTR)ScepAlloc(LPTR, (Len+1+StrLength+1)*sizeof(WCHAR)+ValueLen+2);
  7219. if ( *pOldValue ) {
  7220. //
  7221. // add the prefix "Add:" first, terminated with a \0 for multi-sz format
  7222. //
  7223. wcscpy(*pOldValue, SCE_PRIV_ADD );
  7224. (*pOldValue)[Len] = L'\0';
  7225. //
  7226. // query the value from database
  7227. //
  7228. DWORD NewLen=0;
  7229. rc = SceJetGetValue(
  7230. hSection,
  7231. SCEJET_CURRENT,
  7232. NULL,
  7233. NULL,
  7234. 0,
  7235. NULL,
  7236. (*pOldValue+Len+1),
  7237. ValueLen,
  7238. &NewLen
  7239. );
  7240. if ( SCESTATUS_SUCCESS == rc ) {
  7241. if ( NewLen > ValueLen ) {
  7242. NewLen = ValueLen;
  7243. }
  7244. //
  7245. // make sure the length is a multiple of 2
  7246. //
  7247. if ( NewLen % 2 != 0 ) {
  7248. NewLen++;
  7249. }
  7250. //
  7251. // process the end of the multi-sz string, make sure that it only contains one \0
  7252. //
  7253. while ( NewLen > 0 &&
  7254. ( *(*pOldValue+Len+1+NewLen/2-1) == L'\0') ) {
  7255. if ( NewLen > 1 ) {
  7256. NewLen -= 2;
  7257. } else {
  7258. NewLen = 0;
  7259. }
  7260. }
  7261. if ( NewLen != 0 ) {
  7262. //
  7263. // include one \0
  7264. //
  7265. NewLen += 2;
  7266. }
  7267. if ( StrValue ) {
  7268. memcpy((*pOldValue+Len+1+NewLen/2), StrValue, StrLength*sizeof(WCHAR));
  7269. *pOldLen = Len+1+NewLen/2+StrLength;
  7270. } else {
  7271. if ( NewLen == 0 ) {
  7272. //
  7273. // no value in both database and template
  7274. //
  7275. ScepFree(*pOldValue);
  7276. *pOldValue = NULL;
  7277. *pOldLen = 0;
  7278. } else {
  7279. //
  7280. // only has value in database, terminate the string with two \0
  7281. //
  7282. *pOldLen = Len+1+NewLen/2+1;
  7283. *(*pOldValue+Len+1+NewLen/2) = L'\0';
  7284. }
  7285. }
  7286. } else {
  7287. ScepFree(*pOldValue);
  7288. *pOldValue = NULL;
  7289. //
  7290. // ignore error (if can't query from the db)
  7291. //
  7292. rc = SCESTATUS_SUCCESS;
  7293. }
  7294. } else {
  7295. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  7296. }
  7297. } else {
  7298. //
  7299. // ignore error (if there is no match)
  7300. //
  7301. rc = SCESTATUS_SUCCESS;
  7302. }
  7303. ScepLogOutput3(1, ScepSceStatusToDosError(rc), IDS_COPY_ONE_PRIVILEGE, Keyname );
  7304. return rc;
  7305. }
  7306. SCESTATUS
  7307. ScepDeleteDomainPolicies()
  7308. {
  7309. SCESTATUS rc;
  7310. PSCESECTION hTmpSect=NULL;
  7311. DOUBLE SectionID=0;
  7312. rc = SceJetGetSectionIDByName(
  7313. hProfile,
  7314. szSystemAccess,
  7315. &SectionID
  7316. );
  7317. if ( SCESTATUS_SUCCESS == rc ) {
  7318. rc = SceJetOpenSection(hProfile,
  7319. SectionID,
  7320. SCEJET_TABLE_SCP,
  7321. &hTmpSect
  7322. );
  7323. if ( SCESTATUS_SUCCESS == rc ) {
  7324. SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
  7325. SceJetCloseSection(&hTmpSect, TRUE);
  7326. }
  7327. rc = SceJetOpenSection(hProfile,
  7328. SectionID,
  7329. SCEJET_TABLE_SMP,
  7330. &hTmpSect
  7331. );
  7332. if ( SCESTATUS_SUCCESS == rc ) {
  7333. SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
  7334. SceJetCloseSection(&hTmpSect, TRUE);
  7335. }
  7336. }
  7337. SectionID = 0;
  7338. rc = SceJetGetSectionIDByName(
  7339. hProfile,
  7340. szKerberosPolicy,
  7341. &SectionID
  7342. );
  7343. if ( SCESTATUS_SUCCESS == rc ) {
  7344. rc = SceJetOpenSection(hProfile,
  7345. SectionID,
  7346. SCEJET_TABLE_SCP,
  7347. &hTmpSect
  7348. );
  7349. if ( SCESTATUS_SUCCESS == rc ) {
  7350. SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
  7351. SceJetCloseSection(&hTmpSect, TRUE);
  7352. }
  7353. rc = SceJetOpenSection(hProfile,
  7354. SectionID,
  7355. SCEJET_TABLE_SMP,
  7356. &hTmpSect
  7357. );
  7358. if ( SCESTATUS_SUCCESS == rc ) {
  7359. SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
  7360. SceJetCloseSection(&hTmpSect, TRUE);
  7361. }
  7362. }
  7363. return rc;
  7364. }
  7365. SCESTATUS
  7366. ScepSetupResetLocalPolicy(
  7367. IN PSCECONTEXT Context,
  7368. IN AREA_INFORMATION Area,
  7369. IN PCWSTR SectionName OPTIONAL,
  7370. IN SCETYPE ProfileType,
  7371. IN BOOL bKeepBasicPolicy
  7372. )
  7373. /*
  7374. Routine Description:
  7375. This routine deletes policies from the local policy table (SMP)
  7376. If a section name is provided, the single section is deleted; otherwise,
  7377. The area information is used.
  7378. If bKeepBasicPolicy is set to TRUE, the following inforamtion WON'T be
  7379. deleted from the table even if that area is requested to delete.
  7380. Password, Lockout, Kerberos, Audit, User Rights, Security Options,
  7381. and SMB settings (any existing service extensions)
  7382. */
  7383. {
  7384. if ( Context == NULL ) {
  7385. return(SCESTATUS_INVALID_PARAMETER);
  7386. }
  7387. SCESTATUS rc;
  7388. if ( SectionName ) {
  7389. //
  7390. // delete one section
  7391. //
  7392. rc = ScepDeleteOneSection(
  7393. Context,
  7394. ProfileType,
  7395. SectionName
  7396. );
  7397. } else {
  7398. AREA_INFORMATION Area2;
  7399. if ( bKeepBasicPolicy && ProfileType == SCE_ENGINE_SMP ) {
  7400. Area2 = Area & ~(AREA_SECURITY_POLICY |
  7401. AREA_PRIVILEGES |
  7402. AREA_SYSTEM_SERVICE);
  7403. } else {
  7404. Area2 = Area;
  7405. }
  7406. rc = ScepDeleteInfoForAreas(
  7407. Context,
  7408. ProfileType,
  7409. Area2
  7410. );
  7411. if ( bKeepBasicPolicy &&
  7412. SCESTATUS_SUCCESS == rc ) {
  7413. //
  7414. // delete log settings sections
  7415. //
  7416. ScepDeleteOneSection(
  7417. Context,
  7418. ProfileType,
  7419. szAuditSystemLog
  7420. );
  7421. ScepDeleteOneSection(
  7422. Context,
  7423. ProfileType,
  7424. szAuditSecurityLog
  7425. );
  7426. ScepDeleteOneSection(
  7427. Context,
  7428. ProfileType,
  7429. szAuditApplicationLog
  7430. );
  7431. //
  7432. // delete general service section
  7433. //
  7434. ScepDeleteOneSection(
  7435. Context,
  7436. ProfileType,
  7437. szServiceGeneral
  7438. );
  7439. }
  7440. }
  7441. return(rc);
  7442. }
  7443. SCESTATUS
  7444. ScepSetSystemSecurity(
  7445. IN AREA_INFORMATION Area,
  7446. IN DWORD ConfigOptions,
  7447. IN PSCE_PROFILE_INFO pInfo,
  7448. OUT PSCE_ERROR_LOG_INFO *pErrLog
  7449. )
  7450. /*
  7451. Description:
  7452. Set security settings directly on the system for security policy area
  7453. and user rights area.
  7454. If some settings fail to be configured, the settings will be logged in the
  7455. error buffer to output.
  7456. */
  7457. {
  7458. SCESTATUS Saverc = SCESTATUS_SUCCESS;
  7459. SCESTATUS rc;
  7460. if ( pInfo == NULL || Area == 0 ) {
  7461. //
  7462. // nothing to set
  7463. //
  7464. return(Saverc);
  7465. }
  7466. if ( Area & AREA_PRIVILEGES ) {
  7467. rc = ScepConfigurePrivilegesByRight( pInfo->OtherInfo.smp.pPrivilegeAssignedTo,
  7468. ConfigOptions,
  7469. pErrLog
  7470. );
  7471. if( rc != SCESTATUS_SUCCESS ) {
  7472. Saverc = rc;
  7473. }
  7474. }
  7475. if ( Area & AREA_SECURITY_POLICY ) {
  7476. if ( pInfo->LockoutBadCount == 0 ) {
  7477. //
  7478. // make sure the other two settings are ignored
  7479. // they might have value SCE_DELETE_VALUE which is not applicable to this mode
  7480. //
  7481. pInfo->ResetLockoutCount = SCE_NO_VALUE;
  7482. pInfo->LockoutDuration = SCE_NO_VALUE;
  7483. }
  7484. rc = ScepConfigureSystemAccess(pInfo,
  7485. ConfigOptions | SCE_SYSTEM_SETTINGS,
  7486. pErrLog,
  7487. 0 );
  7488. if( rc != SCESTATUS_SUCCESS ) {
  7489. Saverc = rc;
  7490. }
  7491. rc = ScepConfigureLSAAnonymousLookup( pInfo, ConfigOptions, pErrLog );
  7492. if( rc != SCESTATUS_SUCCESS ) {
  7493. Saverc = rc;
  7494. }
  7495. //
  7496. // System Auditing area
  7497. //
  7498. PPOLICY_AUDIT_EVENTS_INFO auditEvent=NULL;
  7499. rc = ScepSaveAndOffAuditing(&auditEvent, FALSE, NULL);
  7500. if ( rc == SCESTATUS_SUCCESS && auditEvent ) {
  7501. rc = ScepConfigureAuditEvent(pInfo,
  7502. auditEvent,
  7503. ConfigOptions | SCE_SYSTEM_SETTINGS,
  7504. NULL
  7505. );
  7506. if ( rc != SCESTATUS_SUCCESS ) {
  7507. ScepBuildErrorLogInfo(
  7508. ScepSceStatusToDosError(rc),
  7509. pErrLog,
  7510. SCEDLL_SCP_ERROR_EVENT_AUDITING
  7511. );
  7512. }
  7513. } else {
  7514. ScepBuildErrorLogInfo(
  7515. ScepSceStatusToDosError(rc),
  7516. pErrLog,
  7517. SCEDLL_ERROR_QUERY_EVENT_AUDITING
  7518. );
  7519. }
  7520. if ( auditEvent ) {
  7521. LsaFreeMemory(auditEvent);
  7522. }
  7523. if( rc != SCESTATUS_SUCCESS ) {
  7524. Saverc = rc;
  7525. }
  7526. //
  7527. // Kerberos Policy
  7528. //
  7529. rc = ScepConfigureKerberosPolicy( NULL, pInfo->pKerberosInfo, ConfigOptions );
  7530. if( rc != SCESTATUS_SUCCESS ) {
  7531. ScepBuildErrorLogInfo(
  7532. ScepSceStatusToDosError(rc),
  7533. pErrLog,
  7534. SCEDLL_SCP_ERROR_KERBEROS
  7535. );
  7536. Saverc = rc;
  7537. }
  7538. //
  7539. // registry values
  7540. //
  7541. rc = ScepConfigureRegistryValues( NULL,
  7542. pInfo->aRegValues,
  7543. pInfo->RegValueCount,
  7544. pErrLog,
  7545. ConfigOptions,
  7546. NULL );
  7547. if( rc != SCESTATUS_SUCCESS ) {
  7548. Saverc = rc;
  7549. }
  7550. }
  7551. return(Saverc);
  7552. }
  7553. SCESTATUS
  7554. ScepConfigurePrivilegesByRight(
  7555. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivAssign,
  7556. IN DWORD Options,
  7557. IN OUT PSCE_ERROR_LOG_INFO *pErrLog
  7558. )
  7559. /*
  7560. Description:
  7561. Configure privileges by PSCE_PRIVILEGE_ASSIGNMENT structure which is
  7562. separated by each user right with a list of accounts assigned to.
  7563. */
  7564. {
  7565. if ( pPrivAssign == NULL ) {
  7566. //
  7567. // nothing to configure
  7568. //
  7569. return(SCESTATUS_SUCCESS);
  7570. }
  7571. LSA_HANDLE LsaPolicy=NULL;
  7572. DWORD rc;
  7573. rc = RtlNtStatusToDosError( ScepOpenLsaPolicy(
  7574. POLICY_LOOKUP_NAMES | POLICY_CREATE_ACCOUNT,
  7575. &LsaPolicy,
  7576. FALSE)
  7577. );
  7578. if (rc != ERROR_SUCCESS) {
  7579. if ( pErrLog ) {
  7580. ScepBuildErrorLogInfo(
  7581. rc,
  7582. pErrLog,
  7583. SCEDLL_LSA_POLICY
  7584. );
  7585. }
  7586. return(rc);
  7587. }
  7588. PSCE_PRIVILEGE_ASSIGNMENT pPriv;
  7589. INT PrivValue;
  7590. PSCE_NAME_LIST pList;
  7591. DWORD SaveRc=SCESTATUS_SUCCESS;
  7592. BOOL bBufferUsed;
  7593. PSID pAccountSid;
  7594. DWORD PrivLowMask=0;
  7595. DWORD PrivHighMask=0;
  7596. PSCE_PRIVILEGE_VALUE_LIST pPrivList=NULL;
  7597. //
  7598. // convert the privilege assignment structure to privilege value list
  7599. // and build the mask for privileges (PrivLowMask and PrivHighMask)
  7600. //
  7601. for ( pPriv=pPrivAssign; pPriv != NULL; pPriv=pPriv->Next ) {
  7602. //
  7603. // privilege name is empty, ignore it.
  7604. //
  7605. if ( pPriv->Name == NULL ) {
  7606. continue;
  7607. }
  7608. //
  7609. // search for the privilege value
  7610. //
  7611. PrivValue = ScepLookupPrivByName(pPriv->Name);
  7612. if ( PrivValue == -1 ) {
  7613. //
  7614. // unknown privilege
  7615. //
  7616. if ( pErrLog ) {
  7617. ScepBuildErrorLogInfo(
  7618. 0,
  7619. pErrLog,
  7620. SCEERR_INVALID_PRIVILEGE,
  7621. pPriv->Name
  7622. );
  7623. }
  7624. continue;
  7625. }
  7626. //
  7627. // build privilege mask
  7628. //
  7629. if ( PrivValue < 32 ) {
  7630. PrivLowMask |= (1 << PrivValue);
  7631. } else {
  7632. PrivHighMask |= (1 << (PrivValue-32) );
  7633. }
  7634. for ( pList=pPriv->AssignedTo; pList != NULL; pList=pList->Next ) {
  7635. //
  7636. // translate each one to a SID
  7637. //
  7638. if ( pList->Name == NULL ) {
  7639. continue;
  7640. }
  7641. //
  7642. // reset error code for this new account
  7643. //
  7644. rc = ERROR_SUCCESS;
  7645. pAccountSid = NULL;
  7646. bBufferUsed = FALSE;
  7647. if ( pList->Name[0] == L'*' ) {
  7648. //
  7649. // this is a string SID
  7650. //
  7651. if ( !ConvertStringSidToSid( pList->Name+1, &pAccountSid) ) {
  7652. rc = GetLastError();
  7653. }
  7654. } else {
  7655. //
  7656. // this is a name, could be in the format of domain\account, or
  7657. // just an isolated account
  7658. //
  7659. rc = RtlNtStatusToDosError(
  7660. ScepConvertNameToSid(
  7661. LsaPolicy,
  7662. pList->Name,
  7663. &pAccountSid
  7664. ));
  7665. }
  7666. if ( rc == ERROR_SUCCESS ) {
  7667. //
  7668. // add the account SID to privilege value list
  7669. //
  7670. rc = ScepDosErrorToSceStatus(
  7671. ScepAddSidToPrivilegeList(
  7672. &pPrivList,
  7673. pAccountSid,
  7674. TRUE, // reuse the buffer
  7675. PrivValue,
  7676. &bBufferUsed
  7677. ));
  7678. }
  7679. if ( rc != ERROR_SUCCESS ) {
  7680. //
  7681. // something is wrong with this account. Can't be resolved
  7682. // add it to the error log and continue to process others.
  7683. //
  7684. if ( pErrLog ) {
  7685. ScepBuildErrorLogInfo(
  7686. rc,
  7687. pErrLog,
  7688. SCEDLL_INVALID_GROUP,
  7689. pList->Name
  7690. );
  7691. }
  7692. SaveRc = ScepDosErrorToSceStatus(rc);
  7693. }
  7694. if ( !bBufferUsed && pAccountSid ) {
  7695. ScepFree(pAccountSid);
  7696. }
  7697. pAccountSid = NULL;
  7698. }
  7699. }
  7700. //
  7701. // free LSA handle
  7702. //
  7703. LsaClose(LsaPolicy);
  7704. //
  7705. // now continue to configure even though there may be errors in
  7706. // the previous processing (the erorrs are logged)
  7707. //
  7708. if ( PrivLowMask > 0 || PrivHighMask > 0 ) {
  7709. rc = ScepConfigurePrivilegesWithMask(
  7710. &pPrivList,
  7711. FALSE,
  7712. Options | SCE_SYSTEM_SETTINGS,
  7713. PrivLowMask,
  7714. PrivHighMask,
  7715. pErrLog,
  7716. NULL
  7717. );
  7718. }
  7719. //
  7720. // free privilege list
  7721. //
  7722. return(SaveRc);
  7723. }
  7724. SCESTATUS
  7725. ScepEnumAttachmentSections(
  7726. IN PSCECONTEXT cxtProfile,
  7727. OUT PSCE_NAME_LIST *ppList
  7728. )
  7729. /* ++
  7730. Routine Description:
  7731. Arguments:
  7732. cxtProfile - The profile context handle
  7733. ppList - The output attachment section names
  7734. Return Value:
  7735. -- */
  7736. {
  7737. SCESTATUS rc;
  7738. JET_ERR JetErr;
  7739. DWORD Actual;
  7740. WCHAR Buffer[256];
  7741. DWORD Len;
  7742. if ( cxtProfile == NULL || ppList == NULL )
  7743. return(SCESTATUS_INVALID_PARAMETER);
  7744. if ( cxtProfile->JetTblSecID <= 0) {
  7745. //
  7746. // Section table is not opened yet
  7747. //
  7748. rc = SceJetOpenTable(
  7749. cxtProfile,
  7750. "SmTblSection",
  7751. SCEJET_TABLE_SECTION,
  7752. SCEJET_OPEN_READ_ONLY,
  7753. NULL
  7754. );
  7755. if ( rc != SCESTATUS_SUCCESS )
  7756. return(rc);
  7757. }
  7758. *ppList = NULL;
  7759. //
  7760. // set current index to SecID (the ID)
  7761. //
  7762. JetErr = JetSetCurrentIndex(
  7763. cxtProfile->JetSessionID,
  7764. cxtProfile->JetTblSecID,
  7765. "SecID"
  7766. );
  7767. rc = SceJetJetErrorToSceStatus(JetErr);
  7768. if ( rc != SCESTATUS_SUCCESS )
  7769. return(rc);
  7770. //
  7771. // Move to the first record
  7772. //
  7773. JetErr = JetMove(
  7774. cxtProfile->JetSessionID,
  7775. cxtProfile->JetTblSecID,
  7776. JET_MoveFirst,
  7777. 0
  7778. );
  7779. rc = SceJetJetErrorToSceStatus(JetErr);
  7780. if ( rc == SCESTATUS_SUCCESS ) {
  7781. //
  7782. // find the section record, retrieve column Name
  7783. //
  7784. do {
  7785. Len = 255;
  7786. memset(Buffer, '\0', 256*sizeof(WCHAR));
  7787. JetErr = JetRetrieveColumn(
  7788. cxtProfile->JetSessionID,
  7789. cxtProfile->JetTblSecID,
  7790. cxtProfile->JetSecNameID,
  7791. (void *)Buffer,
  7792. Len*sizeof(WCHAR),
  7793. &Actual,
  7794. 0,
  7795. NULL
  7796. );
  7797. rc = SceJetJetErrorToSceStatus(JetErr);
  7798. if ( rc == SCESTATUS_SUCCESS ) {
  7799. //
  7800. // add this name to the output list
  7801. //
  7802. if ( _wcsicmp(szSystemAccess, Buffer) == 0 ||
  7803. _wcsicmp(szPrivilegeRights, Buffer) == 0 ||
  7804. _wcsicmp(szGroupMembership, Buffer) == 0 ||
  7805. _wcsicmp(szRegistryKeys, Buffer) == 0 ||
  7806. _wcsicmp(szFileSecurity, Buffer) == 0 ||
  7807. _wcsicmp(szAuditSystemLog, Buffer) == 0 ||
  7808. _wcsicmp(szAuditSecurityLog, Buffer) == 0 ||
  7809. _wcsicmp(szAuditApplicationLog, Buffer) == 0 ||
  7810. _wcsicmp(szAuditEvent, Buffer) == 0 ||
  7811. _wcsicmp(szKerberosPolicy, Buffer) == 0 ||
  7812. _wcsicmp(szRegistryValues, Buffer) == 0 ||
  7813. _wcsicmp(szServiceGeneral, Buffer) == 0 ||
  7814. _wcsicmp(szAccountProfiles, Buffer) == 0 ||
  7815. _wcsicmp(szDSSecurity, Buffer) == 0 ||
  7816. _wcsicmp(szUserList, Buffer) == 0
  7817. ) {
  7818. // this is not the attachment section
  7819. } else {
  7820. rc = ScepAddToNameList(ppList, Buffer, 0);
  7821. }
  7822. }
  7823. if ( rc == SCESTATUS_SUCCESS ) {
  7824. //
  7825. // Move to next line
  7826. //
  7827. JetErr = JetMove(cxtProfile->JetSessionID,
  7828. cxtProfile->JetTblSecID,
  7829. JET_MoveNext,
  7830. 0);
  7831. rc = SceJetJetErrorToSceStatus(JetErr);
  7832. }
  7833. } while ( SCESTATUS_SUCCESS == rc );
  7834. }
  7835. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  7836. rc = SCESTATUS_SUCCESS;
  7837. } else if ( rc != SCESTATUS_SUCCESS ) {
  7838. //
  7839. // free the output buffer
  7840. //
  7841. ScepFreeNameList(*ppList);
  7842. *ppList = NULL;
  7843. }
  7844. return(rc);
  7845. }
  7846. SCESTATUS
  7847. ScepTattooUpdatePrivilegeArrayStatus(
  7848. IN DWORD *pStatusArray,
  7849. IN DWORD rc,
  7850. IN DWORD PrivLowMask,
  7851. IN DWORD PrivHighMask
  7852. )
  7853. {
  7854. if ( pStatusArray == NULL ||
  7855. (PrivLowMask == 0 && PrivHighMask == 0) ) {
  7856. return(SCESTATUS_SUCCESS);
  7857. }
  7858. for ( DWORD i=0; i<cPrivCnt; i++) {
  7859. if ( ( (i < 32) && ( PrivLowMask & (1 << i)) ) ||
  7860. ( (i >= 32) && ( PrivHighMask & ( 1 << (i-32)) ) ) ) {
  7861. if ( rc != 0 )
  7862. pStatusArray[i] = rc;
  7863. else if ( pStatusArray[i] == (DWORD)-1 )
  7864. pStatusArray[i] = rc;
  7865. }
  7866. }
  7867. return(SCESTATUS_SUCCESS);
  7868. }
  7869. SCESTATUS
  7870. ScepTattooRemovePrivilegeValues(
  7871. IN PSCECONTEXT hProfile,
  7872. IN DWORD *pStatusArray
  7873. )
  7874. {
  7875. PSCESECTION hSectionDomain=NULL;
  7876. PSCESECTION hSectionTattoo=NULL;
  7877. DWORD i,Len;
  7878. if ( hProfile == NULL || pStatusArray == NULL )
  7879. return(SCESTATUS_INVALID_PARAMETER);
  7880. //
  7881. // open domain and tattoo sections
  7882. //
  7883. ScepTattooOpenPolicySections(
  7884. hProfile,
  7885. szPrivilegeRights,
  7886. &hSectionDomain,
  7887. &hSectionTattoo
  7888. );
  7889. if ( hSectionDomain != NULL && hSectionTattoo != NULL ) {
  7890. for ( i=0; i<cPrivCnt; i++ ) {
  7891. if ( pStatusArray[i] == 0 ) {
  7892. //
  7893. // check if this setting comes from domain
  7894. //
  7895. Len = wcslen(SCE_Privileges[i].Name);
  7896. BOOL bDomainExist = FALSE;
  7897. if ( SCESTATUS_SUCCESS == SceJetSeek(
  7898. hSectionDomain,
  7899. SCE_Privileges[i].Name,
  7900. Len*sizeof(WCHAR),
  7901. SCEJET_SEEK_EQ_NO_CASE
  7902. ) ) {
  7903. if ( hSectionDomain->JetColumnGpoID > 0 ) {
  7904. //
  7905. // check if GpoID > 0
  7906. //
  7907. LONG GpoID = 0;
  7908. DWORD Actual;
  7909. JET_ERR JetErr;
  7910. JetErr = JetRetrieveColumn(
  7911. hSectionDomain->JetSessionID,
  7912. hSectionDomain->JetTableID,
  7913. hSectionDomain->JetColumnGpoID,
  7914. (void *)&GpoID,
  7915. 4,
  7916. &Actual,
  7917. 0,
  7918. NULL
  7919. );
  7920. if ( JET_errSuccess != JetErr ) {
  7921. //
  7922. // if the column is nil (no value), it will return warning
  7923. // but the buffer pGpoID is trashed
  7924. //
  7925. GpoID = 0;
  7926. }
  7927. if ( GpoID > 0 ) {
  7928. bDomainExist = TRUE;
  7929. }
  7930. }
  7931. }
  7932. if ( bDomainExist ) {
  7933. // if the setting comes from domain, don't do anything
  7934. continue;
  7935. }
  7936. //
  7937. // by now, this setting comes from the tattoo table
  7938. // and has been configured successfully
  7939. // now remove the tattoo setting
  7940. //
  7941. SceJetDelete(hSectionTattoo,
  7942. SCE_Privileges[i].Name,
  7943. FALSE,
  7944. SCEJET_DELETE_LINE_NO_CASE);
  7945. ScepLogOutput3(2, 0, SCESRV_POLICY_TATTOO_REMOVE_SETTING, SCE_Privileges[i].Name);
  7946. }
  7947. }
  7948. }
  7949. if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain, TRUE);
  7950. if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo, TRUE);
  7951. return(SCESTATUS_SUCCESS);
  7952. }
  7953. SCESTATUS
  7954. ScepTattooSavePrivilegeValues(
  7955. IN PSCECONTEXT hProfile,
  7956. IN LSA_HANDLE PolicyHandle,
  7957. IN DWORD PrivLowMask,
  7958. IN DWORD PrivHighMask,
  7959. IN DWORD ConfigOptions
  7960. )
  7961. {
  7962. PSCESECTION hSectionDomain=NULL;
  7963. PSCESECTION hSectionTattoo=NULL;
  7964. NTSTATUS NtStatus;
  7965. ULONG CountReturned;
  7966. UNICODE_STRING UserRight;
  7967. PLSA_ENUMERATION_INFORMATION EnumBuffer=NULL;
  7968. DWORD i,j,Len;
  7969. BOOL bSettingExist;
  7970. DWORD rc,rc2;
  7971. SCESTATUS saveRc=SCESTATUS_SUCCESS;
  7972. PSCE_NAME_LIST pNameList=NULL;
  7973. if ( !(ConfigOptions & SCE_POLICY_TEMPLATE) || hProfile == NULL ||
  7974. PolicyHandle == NULL ) {
  7975. return(SCESTATUS_INVALID_PARAMETER);
  7976. }
  7977. if ( PrivLowMask == 0 && PrivHighMask == 0 ) {
  7978. return(SCESTATUS_SUCCESS);
  7979. }
  7980. //
  7981. // open domain and tattoo sections
  7982. //
  7983. ScepTattooOpenPolicySections(
  7984. hProfile,
  7985. szPrivilegeRights,
  7986. &hSectionDomain,
  7987. &hSectionTattoo
  7988. );
  7989. if ( hSectionDomain != NULL && hSectionTattoo != NULL ) {
  7990. for ( i=0; i<cPrivCnt; i++ ) {
  7991. if ( ( (i < 32) && ( PrivLowMask & (1 << i)) ) ||
  7992. ( (i >= 32) && ( PrivHighMask & ( 1 << (i-32)) ) ) ) {
  7993. //
  7994. // check if this setting comes from domain
  7995. //
  7996. Len = wcslen(SCE_Privileges[i].Name);
  7997. bSettingExist = FALSE;
  7998. if ( SCESTATUS_SUCCESS == SceJetSeek(
  7999. hSectionTattoo,
  8000. SCE_Privileges[i].Name,
  8001. Len*sizeof(WCHAR),
  8002. SCEJET_SEEK_EQ_NO_CASE
  8003. ) ) {
  8004. bSettingExist = TRUE;
  8005. }
  8006. // if there is tattoo setting already, no need to save undo value
  8007. if ( bSettingExist ) {
  8008. ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_EXIST, SCE_Privileges[i].Name);
  8009. continue;
  8010. }
  8011. bSettingExist = FALSE;
  8012. if ( SCESTATUS_SUCCESS == SceJetSeek(
  8013. hSectionDomain,
  8014. SCE_Privileges[i].Name,
  8015. Len*sizeof(WCHAR),
  8016. SCEJET_SEEK_EQ_NO_CASE
  8017. ) ) {
  8018. //
  8019. // since there is no tattoo value exist
  8020. // so if this setting is found in domain table, it must come from domain
  8021. //
  8022. bSettingExist = TRUE;
  8023. }
  8024. // if the setting doesn't come from domain, no need to query undo value
  8025. if ( !bSettingExist ) continue;
  8026. //
  8027. // now we need to query the tattoo value for this privilege
  8028. //
  8029. RtlInitUnicodeString( &UserRight, (PCWSTR)(SCE_Privileges[i].Name));
  8030. //
  8031. // now enumerate all accounts for this user right.
  8032. //
  8033. NtStatus = LsaEnumerateAccountsWithUserRight(
  8034. PolicyHandle,
  8035. &UserRight,
  8036. (PVOID *)&EnumBuffer, // account SIDs
  8037. &CountReturned
  8038. );
  8039. if ( NtStatus == STATUS_NO_MORE_ENTRIES ||
  8040. NtStatus == STATUS_NO_SUCH_PRIVILEGE ||
  8041. NtStatus == STATUS_NOT_FOUND ||
  8042. NT_SUCCESS(NtStatus) ) {
  8043. rc = ERROR_SUCCESS;
  8044. } else {
  8045. rc = RtlNtStatusToDosError(NtStatus);
  8046. }
  8047. pNameList = NULL;
  8048. //
  8049. // if fail to get the account list
  8050. // save NULL as the tattoo value
  8051. //
  8052. if ( NT_SUCCESS(NtStatus) && CountReturned > 0 ) {
  8053. //
  8054. // add the SIDs
  8055. //
  8056. for ( j=0; j<CountReturned; j++ ) {
  8057. //
  8058. // build each account into the name list
  8059. // Convert using the Rtl functions
  8060. //
  8061. rc2 = ScepAddSidStringToNameList(&pNameList, EnumBuffer[j].Sid);
  8062. if ( NO_ERROR != rc2 ) {
  8063. rc = rc2;
  8064. }
  8065. }
  8066. }
  8067. LsaFreeMemory( EnumBuffer );
  8068. EnumBuffer = NULL;
  8069. //
  8070. // log an error
  8071. //
  8072. if ( ERROR_SUCCESS != rc ) {
  8073. saveRc = ScepDosErrorToSceStatus(rc);
  8074. ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_QUERY, rc, SCE_Privileges[i].Name);
  8075. } else {
  8076. //
  8077. // now save the name list to the tattoo table
  8078. //
  8079. rc = ScepWriteNameListValue(
  8080. PolicyHandle,
  8081. hSectionTattoo,
  8082. SCE_Privileges[i].Name,
  8083. pNameList,
  8084. SCE_WRITE_EMPTY_LIST,
  8085. 4
  8086. );
  8087. if ( rc != SCESTATUS_SUCCESS ) {
  8088. saveRc = rc;
  8089. ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_SETTING, ScepSceStatusToDosError(rc), SCE_Privileges[i].Name);
  8090. } else {
  8091. ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_CHECK, SCE_Privileges[i].Name);
  8092. }
  8093. }
  8094. if ( pNameList != NULL ) {
  8095. ScepFreeNameList( pNameList );
  8096. pNameList = NULL;
  8097. }
  8098. }
  8099. }
  8100. }
  8101. if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain, TRUE);
  8102. if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo, TRUE);
  8103. return(saveRc);
  8104. }
  8105. BOOL
  8106. ScepAccountHandledByNetJoin(
  8107. IN PSID AliasSid,
  8108. IN PSID MemberSid,
  8109. OUT BOOL *pfAliasHandled)
  8110. /* ++
  8111. Routine Description:
  8112. Checks if the current member for the specified alias is handled by net join. Net
  8113. join currently handles the following groups:
  8114. - in Administrators: Domain Admins
  8115. - in Users: Domain Users
  8116. Arguments:
  8117. AliasSid - group's SID
  8118. MemberSid - group's member SID
  8119. fAliasHandled - optimization variable, the function is called in a loop, we can
  8120. avoid calling it again if alias is not handled by net join
  8121. Return value:
  8122. TRUE - if account is modified by net join
  8123. FALSE - if account not modified or error occured
  8124. -- */
  8125. {
  8126. NTSTATUS NtStatus;
  8127. BOOL fRet = FALSE;
  8128. PSID pSidAdmins = NULL;
  8129. PSID pSidUsers = NULL;
  8130. PSID pSidDomAdmins = NULL;
  8131. PSID pSidDomUsers = NULL;
  8132. PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo=NULL;
  8133. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo=NULL;
  8134. *pfAliasHandled = FALSE;
  8135. if (ERROR_SUCCESS == ScepGetBuiltinSid(DOMAIN_ALIAS_RID_ADMINS, &pSidAdmins) &&
  8136. ERROR_SUCCESS == ScepGetBuiltinSid(DOMAIN_ALIAS_RID_USERS, &pSidUsers))
  8137. {
  8138. //
  8139. // check if group SID is one of the accounts net join changes, otherwise
  8140. // there's no need to further process it
  8141. //
  8142. if (EqualSid(AliasSid, pSidAdmins) ||
  8143. EqualSid(AliasSid, pSidUsers))
  8144. {
  8145. *pfAliasHandled = TRUE;
  8146. NtStatus = ScepGetLsaDomainInfo(
  8147. &AccountDomainInfo,
  8148. &PrimaryDomainInfo
  8149. );
  8150. if(NT_SUCCESS(NtStatus) &&
  8151. NT_SUCCESS(ScepDomainIdToSid(PrimaryDomainInfo->Sid, DOMAIN_GROUP_RID_ADMINS, &pSidDomAdmins)) &&
  8152. NT_SUCCESS(ScepDomainIdToSid(PrimaryDomainInfo->Sid, DOMAIN_GROUP_RID_USERS, &pSidDomUsers)))
  8153. {
  8154. //
  8155. // check if the member group is changed by net join
  8156. //
  8157. if(EqualSid(AliasSid, pSidAdmins) && EqualSid(MemberSid,pSidDomAdmins) ||
  8158. EqualSid(AliasSid, pSidUsers) && EqualSid(MemberSid,pSidDomUsers))
  8159. {
  8160. fRet = TRUE;
  8161. }
  8162. }
  8163. }
  8164. }
  8165. if(pSidAdmins) {
  8166. ScepFree(pSidAdmins);
  8167. }
  8168. if(pSidUsers) {
  8169. ScepFree(pSidUsers);
  8170. }
  8171. if(pSidDomAdmins) {
  8172. ScepFree(pSidDomAdmins);
  8173. }
  8174. if(pSidDomUsers) {
  8175. ScepFree(pSidDomUsers);
  8176. }
  8177. if(AccountDomainInfo != NULL) {
  8178. LsaFreeMemory(AccountDomainInfo);
  8179. }
  8180. if(PrimaryDomainInfo != NULL) {
  8181. LsaFreeMemory(PrimaryDomainInfo);
  8182. }
  8183. return fRet;
  8184. }
  8185. DWORD
  8186. ScepTattooCurrentGroupMembers(
  8187. IN PSID ThisDomainSid,
  8188. IN PSID GrpSid OPTIONAL,
  8189. IN SID_NAME_USE GrpUse,
  8190. IN PULONG MemberRids OPTIONAL,
  8191. IN PSID *MemberAliasSids OPTIONAL,
  8192. IN DWORD MemberCount,
  8193. OUT PSCE_NAME_LIST *ppNameList
  8194. )
  8195. /* ++
  8196. Routine Description:
  8197. This routine builds the current group membership into a name list (in SID string
  8198. format).
  8199. Arguments:
  8200. ThisDomainSid - The domain SID
  8201. GrpUse - The "type" of the group
  8202. MemberRids - the member RIDs (for SidTypeGroup)
  8203. MemberAliasSids - the member SIDs (for SidTypeAlias)
  8204. MemberCount - number of members
  8205. ppNameList - the output name list
  8206. Return value:
  8207. WIN32 errors
  8208. -- */
  8209. {
  8210. NTSTATUS NtStatus=ERROR_SUCCESS;
  8211. DWORD j;
  8212. DWORD saveRc=ERROR_SUCCESS;
  8213. DWORD rc;
  8214. if ( ppNameList == NULL ) {
  8215. return(ERROR_INVALID_PARAMETER);
  8216. }
  8217. *ppNameList = NULL;
  8218. switch ( GrpUse ) {
  8219. case SidTypeGroup:
  8220. //
  8221. // member IDs are passed in as Rids
  8222. // DomainHandle must point to a account domain because builtin domain
  8223. // won't have SidTypeGroup account
  8224. //
  8225. if ( ThisDomainSid == NULL )
  8226. saveRc = ERROR_INVALID_PARAMETER;
  8227. else if ( MemberRids ) {
  8228. PSID AccountSid=NULL;
  8229. for (j=0; j<MemberCount; j++) {
  8230. NtStatus = ScepDomainIdToSid(
  8231. ThisDomainSid,
  8232. MemberRids[j],
  8233. &AccountSid
  8234. );
  8235. rc = RtlNtStatusToDosError(NtStatus);
  8236. if ( NT_SUCCESS(NtStatus) ) {
  8237. rc = ScepAddSidStringToNameList(ppNameList, AccountSid);
  8238. ScepFree(AccountSid);
  8239. AccountSid = NULL;
  8240. }
  8241. if ( ERROR_SUCCESS != rc ) saveRc = rc;
  8242. }
  8243. }
  8244. break;
  8245. case SidTypeAlias:
  8246. //
  8247. // members are passed in as SIDs
  8248. // add them to the output list directly
  8249. //
  8250. if ( MemberAliasSids ) {
  8251. BOOL fAliasHandled = TRUE; // optimization variable, set to FALSE by ScepAccountHandledByNetJoin
  8252. // if group is not handled by net join so we avoid calling
  8253. // ScepAccountHandledByNetJoin unnecessarily
  8254. for ( j=0; j<MemberCount; j++ ) {
  8255. if ( MemberAliasSids[j] != NULL ) {
  8256. //
  8257. // add member to the list
  8258. //
  8259. //
  8260. // Some builtin groups are modified by net join. To avoid undoing net join's changes,
  8261. // we'll save those domain specific accounts handled by net join only as relative SIDs.
  8262. // Upon restore from tattoo table, we'll rebuild the full SID based on the current
  8263. // domain (e.g. so we don't restore old domain Domain Admin, but current one)
  8264. //
  8265. if (fAliasHandled &&
  8266. ScepAccountHandledByNetJoin(
  8267. GrpSid,
  8268. MemberAliasSids[j],
  8269. &fAliasHandled)) {
  8270. rc = ScepAddRelativeSidToNameList(ppNameList, MemberAliasSids[j]);
  8271. } else {
  8272. rc = ScepAddSidStringToNameList(ppNameList, MemberAliasSids[j]);
  8273. }
  8274. if ( ERROR_SUCCESS != rc ) saveRc = rc;
  8275. }
  8276. }
  8277. }
  8278. break;
  8279. default:
  8280. saveRc = ERROR_INVALID_PARAMETER;
  8281. break;
  8282. }
  8283. return(saveRc);
  8284. }
  8285. SCESTATUS
  8286. ScepCheckNetworkLogonRights(
  8287. IN LSA_HANDLE PolicyHandle,
  8288. IN OUT DWORD *pLowMask,
  8289. IN OUT DWORD *pHighMask,
  8290. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned
  8291. )
  8292. /*
  8293. Description:
  8294. This function is to make sure that Authenticated Users already have
  8295. "Network Logon Right" and Authenticated Users & Everyone must not
  8296. have "Deny network logon right".
  8297. If the network logon right or deny network logon right are not defined
  8298. in the privilege mask, no change is made since the user rights are not
  8299. defined in the configuration.
  8300. If Authenticated Users or Everyone is not defined in the privilege list,
  8301. this function will add them in (hard coded). The output of this function
  8302. ppPrivilegeAssigned may contain new added nodes for the hard coded accounts.
  8303. */
  8304. {
  8305. INT i;
  8306. INT idxAllow = -1;
  8307. INT idxDeny = -1;
  8308. INT idxLocal = -1;
  8309. INT idxDenyLocal = -1;
  8310. DWORD PrivHighMask = *pHighMask;
  8311. DWORD PrivLowMask = *pLowMask;
  8312. //
  8313. // check first if Network logon right is defined
  8314. //
  8315. i = ScepLookupPrivByName(SE_NETWORK_LOGON_NAME);
  8316. if ( i != -1 ) {
  8317. if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
  8318. //
  8319. // network logon right is defined
  8320. //
  8321. idxAllow = i;
  8322. }
  8323. }
  8324. //
  8325. // check if Deny Network logon right is defined
  8326. //
  8327. i = ScepLookupPrivByName(SE_DENY_NETWORK_LOGON_NAME);
  8328. if ( i != -1 ) {
  8329. if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
  8330. //
  8331. // deny network logon right is defined
  8332. //
  8333. idxDeny = i;
  8334. }
  8335. }
  8336. //
  8337. // check if logon locally right is defined
  8338. //
  8339. i = ScepLookupPrivByName(SE_INTERACTIVE_LOGON_NAME);
  8340. if ( i != -1 ) {
  8341. if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
  8342. //
  8343. // logon locally right is defined
  8344. //
  8345. idxLocal = i;
  8346. }
  8347. }
  8348. //
  8349. // check if deny logon locally right is defined
  8350. //
  8351. i = ScepLookupPrivByName(SE_DENY_INTERACTIVE_LOGON_NAME);
  8352. if ( i != -1 ) {
  8353. if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
  8354. //
  8355. // deny logon locally right is defined
  8356. //
  8357. idxDenyLocal = i;
  8358. }
  8359. }
  8360. if ( idxAllow == -1 && idxDeny == -1 && idxLocal == -1 && idxDenyLocal == -1 ) {
  8361. //
  8362. // none of them is defined so do not enforce anything
  8363. //
  8364. return(SCESTATUS_SUCCESS);
  8365. }
  8366. //
  8367. // build well known SIDs for the enforcement
  8368. //
  8369. SID EveryoneSid;
  8370. SID AuthSid;
  8371. SID ControllerSid;
  8372. PSID AdminUserSid=NULL;
  8373. SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
  8374. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
  8375. //
  8376. // initialize Administrators group sid
  8377. //
  8378. if ( ! NT_SUCCESS ( RtlAllocateAndInitializeSid( &NtAuth,
  8379. 2,
  8380. SECURITY_BUILTIN_DOMAIN_RID,
  8381. DOMAIN_ALIAS_RID_ADMINS,
  8382. 0,0,0,0,0,0,
  8383. &AdminsSid
  8384. ) ) ) {
  8385. ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY,
  8386. SCEDLL_ADMINISTRATORS_SID);
  8387. //
  8388. // failure to initialize this one SID will still continue to other SIDs
  8389. //
  8390. }
  8391. //
  8392. // initialize administrator SID
  8393. //
  8394. if ( idxDenyLocal != -1 ) {
  8395. NTSTATUS Status;
  8396. //
  8397. // Query the account domain SID
  8398. // failure to initialize this one SID will still continue to
  8399. // enforce other SIDs
  8400. //
  8401. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL;
  8402. Status = LsaQueryInformationPolicy( PolicyHandle,
  8403. PolicyAccountDomainInformation,
  8404. (PVOID *)&PolicyAccountDomainInfo );
  8405. if ( NT_SUCCESS(Status) && PolicyAccountDomainInfo &&
  8406. PolicyAccountDomainInfo->DomainSid ) {
  8407. Status = ScepDomainIdToSid(
  8408. PolicyAccountDomainInfo->DomainSid,
  8409. DOMAIN_USER_RID_ADMIN,
  8410. &AdminUserSid
  8411. );
  8412. }
  8413. if ( PolicyAccountDomainInfo ) {
  8414. LsaFreeMemory( PolicyAccountDomainInfo );
  8415. }
  8416. if ( AdminUserSid == NULL ) {
  8417. ScepLogOutput3(0, RtlNtStatusToDosError(Status),
  8418. SCEDLL_ADMINISTRATORS_SID);
  8419. }
  8420. }
  8421. //
  8422. // initialize well known SIDs
  8423. //
  8424. RtlInitializeSid ( &EveryoneSid, &WorldAuth, 1);
  8425. *RtlSubAuthoritySid ( &EveryoneSid, 0 ) = SECURITY_WORLD_RID;
  8426. RtlInitializeSid ( &AuthSid, &NtAuth, 1);
  8427. *RtlSubAuthoritySid ( &AuthSid, 0 ) = SECURITY_AUTHENTICATED_USER_RID;
  8428. RtlInitializeSid ( &ControllerSid, &NtAuth, 1);
  8429. *RtlSubAuthoritySid ( &ControllerSid, 0 ) = SECURITY_ENTERPRISE_CONTROLLERS_RID;
  8430. PSCE_PRIVILEGE_VALUE_LIST pTemp=*ppPrivilegeAssigned;
  8431. PSCE_PRIVILEGE_VALUE_LIST pParent=NULL;
  8432. BOOL bFindEveryone=FALSE;
  8433. BOOL bFindAuthUsers=FALSE;
  8434. BOOL bFindLocal=FALSE;
  8435. BOOL bFindController=FALSE;
  8436. BOOL bFindAdminUser=FALSE;
  8437. //
  8438. // loop through each one defined in the list to match the above SIDs
  8439. //
  8440. for ( ; pTemp != NULL; pParent=pTemp, pTemp=pTemp->Next) {
  8441. if ( pTemp->Name == NULL ) continue;
  8442. if ( (idxLocal != -1 || idxDenyLocal != -1) && !bFindLocal && AdminsSid &&
  8443. ( bFindLocal = RtlEqualSid( (PSID)(pTemp->Name), AdminsSid) ) ) {
  8444. //
  8445. // make sure Administrators always have the interactive logon right
  8446. //
  8447. if ( idxLocal != -1 ) {
  8448. if ( !SCEP_CHECK_PRIV_BIT(idxLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8449. ScepLogOutput3(0,0, SCESRV_ENFORCE_LOCAL_RIGHT, SE_INTERACTIVE_LOGON_NAME);
  8450. SCEP_ADD_PRIV_BIT(idxLocal, pTemp->PrivLowPart, pTemp->PrivHighPart)
  8451. }
  8452. }
  8453. //
  8454. // make sure administrators don't have deny interactive logon right
  8455. //
  8456. if ( idxDenyLocal != -1 ) {
  8457. if ( SCEP_CHECK_PRIV_BIT(idxDenyLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8458. ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_LOCAL_RIGHT, SE_DENY_INTERACTIVE_LOGON_NAME);
  8459. SCEP_REMOVE_PRIV_BIT(idxDenyLocal, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
  8460. }
  8461. }
  8462. }
  8463. if ( (idxDeny != -1 || idxDenyLocal != -1) &&
  8464. ( !bFindAuthUsers && ( bFindAuthUsers = RtlEqualSid( (PSID)(pTemp->Name), &AuthSid )) ) ||
  8465. ( !bFindEveryone && ( bFindEveryone = RtlEqualSid( (PSID)(pTemp->Name), &EveryoneSid )) ) ) {
  8466. //
  8467. // find Authenticated Users or Everyone
  8468. // make sure they do not have the deny rights
  8469. //
  8470. if ( idxDenyLocal != -1 ) {
  8471. //
  8472. // remove the deny logon locally bit
  8473. //
  8474. if ( SCEP_CHECK_PRIV_BIT(idxDenyLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8475. ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_LOCAL_RIGHT, SE_DENY_INTERACTIVE_LOGON_NAME);
  8476. SCEP_REMOVE_PRIV_BIT(idxDenyLocal, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
  8477. }
  8478. }
  8479. if ( (idxDeny != -1) && (ProductType == NtProductLanManNt) ) {
  8480. //
  8481. // remove the deny network logon bit on domain controllers
  8482. //
  8483. if ( SCEP_CHECK_PRIV_BIT(idxDeny,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8484. ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_NETWORK_RIGHT, SE_DENY_NETWORK_LOGON_NAME);
  8485. SCEP_REMOVE_PRIV_BIT(idxDeny, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
  8486. }
  8487. }
  8488. } else if ( !bFindController && (ProductType == NtProductLanManNt) &&
  8489. ( bFindController = RtlEqualSid( (PSID)(pTemp->Name), &ControllerSid )) ) {
  8490. //
  8491. // find domain controller SID
  8492. // make sure it have network logon right and must not have deny network logon right
  8493. //
  8494. if ( idxDeny != -1 ) {
  8495. //
  8496. // remove the deny network logon bit
  8497. //
  8498. if ( SCEP_CHECK_PRIV_BIT(idxDeny,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8499. ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_NETWORK_RIGHT, SE_DENY_NETWORK_LOGON_NAME);
  8500. SCEP_REMOVE_PRIV_BIT(idxDeny, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
  8501. }
  8502. }
  8503. if ( idxAllow != -1 ) {
  8504. //
  8505. // add the network logon bit
  8506. //
  8507. if ( !SCEP_CHECK_PRIV_BIT(idxAllow,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8508. ScepLogOutput3(0,0, SCESRV_ENFORCE_NETWORK_RIGHT, SE_NETWORK_LOGON_NAME);
  8509. SCEP_ADD_PRIV_BIT(idxAllow, pTemp->PrivLowPart, pTemp->PrivHighPart)
  8510. }
  8511. }
  8512. } else if ( idxDenyLocal != -1 && !bFindAdminUser && AdminUserSid &&
  8513. ( bFindAdminUser = RtlEqualSid( (PSID)(pTemp->Name), AdminUserSid) ) ) {
  8514. //
  8515. // make sure administrator account don't have the deny right
  8516. //
  8517. if ( SCEP_CHECK_PRIV_BIT(idxDenyLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
  8518. ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_LOCAL_RIGHT, SE_DENY_INTERACTIVE_LOGON_NAME);
  8519. SCEP_REMOVE_PRIV_BIT(idxDenyLocal, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
  8520. }
  8521. }
  8522. //
  8523. // all enforcement is done, break the loop now
  8524. //
  8525. if ( (idxLocal == -1 || bFindLocal) &&
  8526. ( (idxDeny == -1 && idxDenyLocal == -1) || (bFindAuthUsers && bFindEveryone) ) &&
  8527. ( bFindController || (ProductType != NtProductLanManNt) ) &&
  8528. (idxDenyLocal == -1 || bFindAdminUser) ) {
  8529. break;
  8530. }
  8531. }
  8532. SCESTATUS rc=SCESTATUS_SUCCESS;
  8533. if ( idxLocal != -1 && !bFindLocal && AdminsSid ) {
  8534. //
  8535. // make sure administrators have "logon locally right"
  8536. // add a new node the the end of the list
  8537. //
  8538. rc = ScepAddAccountRightToList(
  8539. ppPrivilegeAssigned,
  8540. &pParent,
  8541. idxLocal,
  8542. AdminsSid
  8543. );
  8544. if ( rc == SCESTATUS_SUCCESS ) {
  8545. ScepLogOutput3(0,0, SCESRV_ENFORCE_LOCAL_RIGHT, SE_INTERACTIVE_LOGON_NAME);
  8546. } else {
  8547. ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY, SCESRV_ERROR_ENFORCE_LOCAL_RIGHT, SE_INTERACTIVE_LOGON_NAME);
  8548. }
  8549. }
  8550. //
  8551. // if enterprise controllers is not found in the list
  8552. // and it's on a DC, should add it
  8553. //
  8554. rc=SCESTATUS_SUCCESS;
  8555. if ( idxAllow != -1 && !bFindController &&
  8556. ( ProductType == NtProductLanManNt ) ) {
  8557. //
  8558. // make sure enterprise controllers have "network logon right"
  8559. //
  8560. rc = ScepAddAccountRightToList(
  8561. ppPrivilegeAssigned,
  8562. &pParent,
  8563. idxAllow,
  8564. &ControllerSid
  8565. );
  8566. if ( rc == SCESTATUS_SUCCESS ) {
  8567. ScepLogOutput3(0,0, SCESRV_ENFORCE_NETWORK_RIGHT, SE_NETWORK_LOGON_NAME);
  8568. } else {
  8569. ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY, SCESRV_ERROR_ENFORCE_NETWORK_RIGHT, SE_NETWORK_LOGON_NAME);
  8570. }
  8571. }
  8572. //
  8573. // free memory
  8574. //
  8575. if ( AdminsSid ) {
  8576. RtlFreeSid( AdminsSid );
  8577. AdminsSid = NULL;
  8578. }
  8579. if ( AdminUserSid ) {
  8580. RtlFreeSid( AdminUserSid );
  8581. }
  8582. return(rc);
  8583. }
  8584. SCESTATUS
  8585. ScepAddAccountRightToList(
  8586. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
  8587. IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppParent,
  8588. IN INT idxRight,
  8589. IN PSID AccountSid
  8590. )
  8591. /*
  8592. Description:
  8593. Create a new node linked to the end of the link list
  8594. The new node contains the AccountSid for the specified user right "idxRight"
  8595. */
  8596. {
  8597. SCESTATUS rc=SCESTATUS_SUCCESS;
  8598. PSCE_PRIVILEGE_VALUE_LIST pPriv = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc( LMEM_ZEROINIT,
  8599. sizeof(SCE_PRIVILEGE_VALUE_LIST));
  8600. if ( pPriv != NULL ) {
  8601. DWORD Length = RtlLengthSid ( AccountSid );
  8602. //
  8603. // allocate the sid buffer, note it's stored in the name field
  8604. //
  8605. pPriv->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length);
  8606. if ( pPriv->Name != NULL ) {
  8607. //
  8608. // copy the SID in
  8609. //
  8610. RtlCopySid( Length, (PSID)(pPriv->Name), AccountSid );
  8611. //
  8612. // add the interactive logon right bit
  8613. //
  8614. SCEP_ADD_PRIV_BIT(idxRight, pPriv->PrivLowPart, pPriv->PrivHighPart)
  8615. //
  8616. // link to the list
  8617. //
  8618. if ( *ppParent != NULL )
  8619. (*ppParent)->Next = pPriv;
  8620. else
  8621. *ppPrivilegeAssigned = pPriv;
  8622. *ppParent = pPriv;
  8623. } else {
  8624. ScepFree(pPriv);
  8625. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  8626. }
  8627. } else {
  8628. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  8629. }
  8630. return rc;
  8631. }
  8632. DWORD
  8633. ScepAddAceToSecurityDescriptor(
  8634. IN DWORD AceType,
  8635. IN ACCESS_MASK AccessMask,
  8636. IN PSID pSid,
  8637. IN OUT PSECURITY_DESCRIPTOR pSDAbsolute,
  8638. IN PSECURITY_DESCRIPTOR pSDSelfRelative,
  8639. OUT PACL *ppNewAcl
  8640. )
  8641. /*
  8642. Routine Description:
  8643. This routine adds an ACE to a Security Descriptor (at the head only).
  8644. Two optimizations are attempted in adding the ACE.
  8645. Arguments:
  8646. AceType - type of ACE to add
  8647. AccessMask - access mask of ACE to set
  8648. pSid - sid for ACE to add
  8649. pSDAbsolute - absolute SD ptr to build. pSDAbsolute must be empty.
  8650. It's vacuous in the caller's stack hence no SD member
  8651. should be freed outside this routine.
  8652. pSDSelfRelative - self relative SD to get DACL information from
  8653. ppNewAcl - ptr to the new DACL which needs to be freed outside
  8654. Return Value:
  8655. Win32 error code
  8656. */
  8657. {
  8658. DWORD rc = ERROR_SUCCESS;
  8659. BOOL bOrMaskInOldDacl = FALSE;
  8660. if (ppNewAcl == NULL ||
  8661. pSDAbsolute == NULL ||
  8662. pSDSelfRelative == NULL ||
  8663. (AceType != ACCESS_ALLOWED_ACE_TYPE && AceType != ACCESS_DENIED_ACE_TYPE )
  8664. ) {
  8665. return ERROR_INVALID_PARAMETER;
  8666. }
  8667. PACL pNewAcl = *ppNewAcl = NULL;
  8668. NTSTATUS NtStatus = STATUS_SUCCESS;
  8669. BOOLEAN bAclPresent = FALSE;
  8670. PACL pOldAcl = NULL;
  8671. BOOLEAN bDaclDefaulted = FALSE;
  8672. DWORD dwNewAclSize = 0;
  8673. DWORD dwAceSize = 0;
  8674. ACE_HEADER *pFirstAce = NULL;
  8675. DWORD dwFirstAceSize = 0;
  8676. NtStatus = RtlGetDaclSecurityDescriptor(
  8677. pSDSelfRelative,
  8678. &bAclPresent,
  8679. &pOldAcl,
  8680. &bDaclDefaulted);
  8681. rc = RtlNtStatusToDosError( NtStatus );
  8682. if ( rc != ERROR_SUCCESS )
  8683. goto Cleanup;
  8684. //
  8685. // null DACL should never happen - CliffV
  8686. // we shouldn't set the DACL with the one
  8687. // anonymous ACE only since it will deny
  8688. // all other SID's any access
  8689. //
  8690. if ( !bAclPresent ||
  8691. pOldAcl == NULL ||
  8692. pOldAcl->AceCount == 0 ) {
  8693. rc = ERROR_INVALID_ACL;
  8694. goto Cleanup;
  8695. }
  8696. NtStatus = RtlGetAce( pOldAcl,
  8697. 0,
  8698. (PVOID *) &pFirstAce);
  8699. rc = RtlNtStatusToDosError( NtStatus );
  8700. if ( rc != ERROR_SUCCESS )
  8701. goto Cleanup;
  8702. //
  8703. // if the first ACE is for the SID passed in attempt two optimizations
  8704. //
  8705. if ( RtlValidSid((PSID)&((PKNOWN_ACE)pFirstAce)->SidStart) &&
  8706. RtlEqualSid((PSID)&((PKNOWN_ACE)pFirstAce)->SidStart, pSid)) {
  8707. if (pFirstAce->AceType == AceType) {
  8708. //
  8709. // Optimization 1:
  8710. // simply OR in the mask
  8711. //
  8712. ((PKNOWN_ACE)pFirstAce)->Mask |= AccessMask;
  8713. bOrMaskInOldDacl = TRUE;
  8714. goto SetDacl;
  8715. }
  8716. else if (((PKNOWN_ACE)pFirstAce)->Mask == AccessMask ) {
  8717. //
  8718. // Optimization 2:
  8719. // if only AccessMask is turned on, later on
  8720. // (a) prepare a new ACE
  8721. // (b) copy the old ACL except the first ACE
  8722. //
  8723. //
  8724. // remember the size of the first ACE since we need to skip it
  8725. //
  8726. dwFirstAceSize = (DWORD)(((PKNOWN_ACE)pFirstAce)->Header.AceSize);
  8727. }
  8728. }
  8729. switch (AceType) {
  8730. case ACCESS_ALLOWED_ACE_TYPE:
  8731. dwAceSize = sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(pSid) - sizeof(ULONG);
  8732. break;
  8733. case ACCESS_DENIED_ACE_TYPE:
  8734. dwAceSize = sizeof(ACCESS_DENIED_ACE) + RtlLengthSid(pSid) - sizeof(ULONG);
  8735. break;
  8736. default:
  8737. break;
  8738. }
  8739. dwNewAclSize = dwAceSize + pOldAcl->AclSize - dwFirstAceSize;
  8740. *ppNewAcl = pNewAcl = (PACL) LocalAlloc(LMEM_ZEROINIT, dwNewAclSize);
  8741. if ( pNewAcl == NULL ) {
  8742. rc = ERROR_NOT_ENOUGH_MEMORY;
  8743. goto Cleanup;
  8744. }
  8745. //
  8746. // initialize the ACL
  8747. //
  8748. pNewAcl->AclSize = (USHORT) dwNewAclSize;
  8749. pNewAcl->AclRevision = ACL_REVISION;
  8750. pNewAcl->AceCount = 0;
  8751. //
  8752. // add allow/deny ACE to the head of the ACL
  8753. //
  8754. switch (AceType) {
  8755. case ACCESS_ALLOWED_ACE_TYPE:
  8756. if ( ! AddAccessAllowedAce(
  8757. pNewAcl,
  8758. ACL_REVISION,
  8759. AccessMask,
  8760. pSid
  8761. ) ) {
  8762. rc = GetLastError();
  8763. }
  8764. break;
  8765. case ACCESS_DENIED_ACE_TYPE:
  8766. if ( ! AddAccessDeniedAce(
  8767. pNewAcl,
  8768. ACL_REVISION,
  8769. AccessMask,
  8770. pSid
  8771. ) ) {
  8772. rc = GetLastError();
  8773. }
  8774. break;
  8775. default:
  8776. break;
  8777. }
  8778. if ( rc != ERROR_SUCCESS)
  8779. goto Cleanup;
  8780. //
  8781. // copy all the ACEs in the old ACL after the newly added ACE
  8782. // (potentially skipping the first ACE in the old ACL)
  8783. //
  8784. memcpy((PUCHAR)pNewAcl + sizeof(ACL) + dwAceSize,
  8785. (PUCHAR)pOldAcl + sizeof(ACL) + dwFirstAceSize,
  8786. pOldAcl->AclSize - (sizeof(ACL) + dwFirstAceSize) );
  8787. pNewAcl->AceCount += pOldAcl->AceCount;
  8788. if ( dwFirstAceSize != 0 )
  8789. --pNewAcl->AceCount;
  8790. SetDacl:
  8791. //
  8792. // either set the adjusted-ACE ACL, or the added-ACE ACL in the SD
  8793. //
  8794. if ( rc == ERROR_SUCCESS ) {
  8795. NtStatus = RtlSetDaclSecurityDescriptor (
  8796. pSDAbsolute,
  8797. TRUE,
  8798. ( bOrMaskInOldDacl ? pOldAcl : pNewAcl),
  8799. FALSE
  8800. );
  8801. rc = RtlNtStatusToDosError(NtStatus);
  8802. }
  8803. if ( rc == ERROR_SUCCESS ) {
  8804. if ( !IsValidSecurityDescriptor(pSDAbsolute) )
  8805. rc = ERROR_INVALID_SECURITY_DESCR;
  8806. }
  8807. Cleanup:
  8808. if (rc != ERROR_SUCCESS) {
  8809. if (pNewAcl)
  8810. LocalFree(pNewAcl);
  8811. *ppNewAcl = NULL;
  8812. }
  8813. return rc;
  8814. }
  8815. DWORD
  8816. ScepConfigureLSAPolicyObject(
  8817. IN DWORD dwLSAAnonymousNameLookup,
  8818. IN DWORD ConfigOptions,
  8819. IN PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
  8820. OUT BOOL *pbOldLSAPolicyDifferent
  8821. )
  8822. /*
  8823. Routine Description:
  8824. This routine *actually* configures the LSA policy security descriptor ONLY if required.
  8825. Arguments:
  8826. dwLSAAnonymousNameLookup - the value of the desired setting
  8827. ConfigOptions - configuration options
  8828. pErrLog - ptr to error log list
  8829. pbOldLSAPolicyDifferent - ptr to boolean that says whether or not the
  8830. existing setting is different from the desired setting
  8831. this information is required for tattooing
  8832. Return Value:
  8833. Win32 error code
  8834. */
  8835. {
  8836. NTSTATUS NtStatus = STATUS_SUCCESS;
  8837. DWORD rc = ERROR_SUCCESS;
  8838. PACL pNewAcl = NULL;
  8839. DWORD dwAceType;
  8840. BOOL bAddAce = FALSE;
  8841. PSECURITY_DESCRIPTOR pSDCurrentLsaPolicyObject = NULL;
  8842. SECURITY_DESCRIPTOR SDAbsoluteToBuildAndSet;
  8843. if (pbOldLSAPolicyDifferent == NULL ||
  8844. (dwLSAAnonymousNameLookup != 0 && dwLSAAnonymousNameLookup != 1))
  8845. {
  8846. return ERROR_INVALID_PARAMETER;
  8847. }
  8848. LSA_HANDLE LsaHandle = NULL;
  8849. if ( LsaPrivatePolicy == NULL ) {
  8850. NtStatus = ScepOpenLsaPolicy(
  8851. MAXIMUM_ALLOWED,
  8852. &LsaHandle,
  8853. TRUE
  8854. );
  8855. rc = RtlNtStatusToDosError( NtStatus );
  8856. }
  8857. else {
  8858. LsaHandle = LsaPrivatePolicy;
  8859. }
  8860. if ( !NT_SUCCESS( NtStatus ) ) {
  8861. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  8862. ScepBuildErrorLogInfo(
  8863. rc,
  8864. pErrLog,
  8865. SCEDLL_LSA_POLICY
  8866. );
  8867. } else {
  8868. ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY);
  8869. }
  8870. }
  8871. if ( rc == ERROR_SUCCESS ) {
  8872. NtStatus = LsaQuerySecurityObject(
  8873. LsaHandle,
  8874. OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  8875. &pSDCurrentLsaPolicyObject
  8876. );
  8877. rc = RtlNtStatusToDosError( NtStatus );
  8878. if ( !NT_SUCCESS( NtStatus ) ) {
  8879. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  8880. ScepBuildErrorLogInfo(
  8881. rc,
  8882. pErrLog,
  8883. SCEDLL_SCP_ERROR_LSAPOLICY_QUERY
  8884. );
  8885. } else {
  8886. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_QUERY);
  8887. }
  8888. }
  8889. if ( rc == ERROR_SUCCESS ) {
  8890. LPTSTR pwszSDlsaPolicyObject = NULL;
  8891. //
  8892. // log the SDDL SD for diagnostics
  8893. //
  8894. if ( ConvertSecurityDescriptorToStringSecurityDescriptor(
  8895. pSDCurrentLsaPolicyObject,
  8896. SDDL_REVISION_1,
  8897. DACL_SECURITY_INFORMATION,
  8898. &pwszSDlsaPolicyObject,
  8899. NULL
  8900. ) ){
  8901. ScepLogOutput3(1,0,SCEDLL_SCP_INFO_LSAPOLICY_EXISTING_SDDL, pwszSDlsaPolicyObject);
  8902. LocalFree(pwszSDlsaPolicyObject);
  8903. }
  8904. //
  8905. // use AUTHZ to check if desired access is existing access
  8906. //
  8907. if ( ghAuthzResourceManager ) {
  8908. SID AnonymousSid;
  8909. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
  8910. AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext = NULL;
  8911. LUID Identifier = {0};
  8912. RtlInitializeSid ( &AnonymousSid, &NtAuth, 1);
  8913. *RtlSubAuthoritySid ( &AnonymousSid, 0 ) = SECURITY_ANONYMOUS_LOGON_RID;
  8914. if ( AuthzInitializeContextFromSid(0,
  8915. &AnonymousSid,
  8916. ghAuthzResourceManager,
  8917. 0,
  8918. Identifier,
  8919. NULL,
  8920. &hAuthzClientContext) ) {
  8921. AUTHZ_ACCESS_REPLY AuthzReply;
  8922. AUTHZ_ACCESS_REQUEST AuthzRequest;
  8923. ACCESS_MASK GrantedAccessMask;
  8924. DWORD AuthzError;
  8925. AuthzReply.ResultListLength = 1;
  8926. AuthzReply.GrantedAccessMask = &GrantedAccessMask;
  8927. AuthzReply.Error = &AuthzError;
  8928. AuthzReply.SaclEvaluationResults = NULL;
  8929. memset(&AuthzRequest, 0, sizeof(AuthzRequest));
  8930. AuthzRequest.DesiredAccess = POLICY_LOOKUP_NAMES;
  8931. DWORD AceType = 0;
  8932. if ( AuthzAccessCheck(0,
  8933. hAuthzClientContext,
  8934. &AuthzRequest,
  8935. NULL,
  8936. pSDCurrentLsaPolicyObject,
  8937. NULL,
  8938. NULL,
  8939. &AuthzReply,
  8940. NULL) ) {
  8941. //
  8942. // check if existing access is different from desired access
  8943. // if so, add the appropriate ACE or manipulate existing ACEs
  8944. // to get the desired permissions
  8945. //
  8946. if ( GrantedAccessMask & POLICY_LOOKUP_NAMES ) {
  8947. //ASSERT(AuthzError == ERROR_SUCCESS);
  8948. if ( !dwLSAAnonymousNameLookup ) {
  8949. bAddAce = TRUE;
  8950. AceType = ACCESS_DENIED_ACE_TYPE;
  8951. }
  8952. } else {
  8953. //ASSERT(AuthzError == ERROR_ACCESS_DENIED || AuthzError == ERROR_PRIVILEGE_NOT_HELD);
  8954. if ( dwLSAAnonymousNameLookup ) {
  8955. bAddAce = TRUE;
  8956. AceType = ACCESS_ALLOWED_ACE_TYPE;
  8957. }
  8958. }
  8959. if ( bAddAce ) {
  8960. *pbOldLSAPolicyDifferent = TRUE;
  8961. if ( InitializeSecurityDescriptor( &SDAbsoluteToBuildAndSet, SECURITY_DESCRIPTOR_REVISION) ) {
  8962. rc = ScepAddAceToSecurityDescriptor(
  8963. AceType,
  8964. POLICY_LOOKUP_NAMES,
  8965. &AnonymousSid,
  8966. &SDAbsoluteToBuildAndSet,
  8967. pSDCurrentLsaPolicyObject,
  8968. &pNewAcl
  8969. );
  8970. if ( rc == ERROR_SUCCESS) {
  8971. //
  8972. // log the SDDL SD for diagnostics
  8973. //
  8974. pwszSDlsaPolicyObject = NULL;
  8975. if ( ConvertSecurityDescriptorToStringSecurityDescriptor(
  8976. &SDAbsoluteToBuildAndSet,
  8977. SDDL_REVISION_1,
  8978. DACL_SECURITY_INFORMATION,
  8979. &pwszSDlsaPolicyObject,
  8980. NULL
  8981. ) ){
  8982. ScepLogOutput3(1,0,SCEDLL_SCP_INFO_LSAPOLICY_COMPUTED_SDDL, pwszSDlsaPolicyObject);
  8983. LocalFree(pwszSDlsaPolicyObject);
  8984. }
  8985. NtStatus = LsaSetSecurityObject(
  8986. LsaHandle,
  8987. DACL_SECURITY_INFORMATION,
  8988. &SDAbsoluteToBuildAndSet
  8989. );
  8990. LocalFree(pNewAcl);
  8991. rc = RtlNtStatusToDosError( NtStatus );
  8992. if ( !NT_SUCCESS( NtStatus ) ) {
  8993. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  8994. ScepBuildErrorLogInfo(
  8995. rc,
  8996. pErrLog,
  8997. SCEDLL_SCP_ERROR_LSAPOLICY_SET
  8998. );
  8999. } else {
  9000. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_SET);
  9001. }
  9002. }
  9003. }
  9004. else {
  9005. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  9006. ScepBuildErrorLogInfo(
  9007. rc,
  9008. pErrLog,
  9009. SCEDLL_SCP_ERROR_LSAPOLICY_BUILDDACL
  9010. );
  9011. } else {
  9012. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_BUILDDACL);
  9013. }
  9014. }
  9015. }
  9016. else {
  9017. rc = GetLastError();
  9018. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  9019. ScepBuildErrorLogInfo(
  9020. rc,
  9021. pErrLog,
  9022. SCEDLL_SCP_ERROR_LSAPOLICY_SD_INIT
  9023. );
  9024. } else {
  9025. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_SD_INIT);
  9026. }
  9027. }
  9028. }
  9029. }
  9030. else {
  9031. rc = GetLastError();
  9032. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  9033. ScepBuildErrorLogInfo(
  9034. rc,
  9035. pErrLog,
  9036. SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ
  9037. );
  9038. } else {
  9039. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ);
  9040. }
  9041. }
  9042. AuthzFreeContext( hAuthzClientContext );
  9043. } else {
  9044. rc = GetLastError();
  9045. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  9046. ScepBuildErrorLogInfo(
  9047. rc,
  9048. pErrLog,
  9049. SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ
  9050. );
  9051. } else {
  9052. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ);
  9053. }
  9054. }
  9055. }
  9056. else {
  9057. rc = ERROR_RESOURCE_NOT_PRESENT;
  9058. if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
  9059. ScepBuildErrorLogInfo(
  9060. rc,
  9061. pErrLog,
  9062. SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ
  9063. );
  9064. } else {
  9065. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ);
  9066. }
  9067. }
  9068. LsaFreeMemory(pSDCurrentLsaPolicyObject);
  9069. }
  9070. if ( LsaPrivatePolicy == NULL ) {
  9071. LsaClose(LsaHandle);
  9072. }
  9073. }
  9074. return rc;
  9075. }
  9076. SCESTATUS
  9077. ScepConfigureLSAAnonymousLookup(
  9078. IN PSCE_PROFILE_INFO pScpInfo,
  9079. IN DWORD ConfigOptions,
  9080. IN PSCE_ERROR_LOG_INFO *pErrLog)
  9081. /* ++
  9082. Routine Description:
  9083. This routine configures LSA anonymous lookup policy
  9084. Arguments:
  9085. pScpInfo - The buffer which contains SCP info loaded from the profile
  9086. ConfigOptions - options in configuration
  9087. pErrLog - the output log for potential errors
  9088. -- */
  9089. {
  9090. DWORD rc=ERROR_SUCCESS;
  9091. PSCESECTION hSectionDomain=NULL;
  9092. PSCESECTION hSectionTattoo=NULL;
  9093. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  9094. ScepIsSystemShutDown() )
  9095. {
  9096. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  9097. }
  9098. if ( pScpInfo->LSAAnonymousNameLookup != SCE_NO_VALUE )
  9099. {
  9100. BOOL bImpliedOldLSAPolicyDifferent = FALSE;
  9101. DWORD dwImpliedOldLSAAnonymousNameLookup =
  9102. pScpInfo->LSAAnonymousNameLookup;
  9103. rc = ScepConfigureLSAPolicyObject(
  9104. pScpInfo->LSAAnonymousNameLookup,
  9105. ConfigOptions,
  9106. pErrLog,
  9107. &bImpliedOldLSAPolicyDifferent
  9108. );
  9109. if (bImpliedOldLSAPolicyDifferent)
  9110. {
  9111. dwImpliedOldLSAAnonymousNameLookup =
  9112. (pScpInfo->LSAAnonymousNameLookup ? 0 : 1);
  9113. }
  9114. //
  9115. // if this is policy propagation, we need to open the sections for
  9116. // updating undo settings if this is not domain controller
  9117. // *** on DCs, domain account policy can't be reset'ed to tattoo
  9118. // on each individual DC. So there is no point to query/save tattoo values
  9119. //
  9120. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  9121. (ProductType != NtProductLanManNt))
  9122. {
  9123. ScepTattooOpenPolicySections(
  9124. hProfile,
  9125. szSystemAccess,
  9126. &hSectionDomain,
  9127. &hSectionTattoo
  9128. );
  9129. ScepTattooManageOneIntValue(
  9130. hSectionDomain,
  9131. hSectionTattoo,
  9132. (PWSTR)L"LSAAnonymousNameLookup",
  9133. 0,
  9134. dwImpliedOldLSAAnonymousNameLookup,
  9135. rc);
  9136. }
  9137. if ((ConfigOptions & SCE_SYSTEM_SETTINGS) &&
  9138. pErrLog )
  9139. {
  9140. ScepBuildErrorLogInfo(
  9141. rc,
  9142. pErrLog,
  9143. SCEDLL_SCP_LSAPOLICY
  9144. );
  9145. }
  9146. else
  9147. {
  9148. ScepLogOutput3(1, rc, SCEDLL_SCP_LSAPOLICY);
  9149. }
  9150. if (ConfigOptions & SCE_RSOP_CALLBACK)
  9151. {
  9152. ScepRsopLog(SCE_RSOP_LSA_POLICY_INFO, rc, NULL, 0, 0);
  9153. }
  9154. }
  9155. if ( hSectionDomain )
  9156. {
  9157. SceJetCloseSection( &hSectionDomain, TRUE );
  9158. }
  9159. if ( hSectionTattoo )
  9160. {
  9161. SceJetCloseSection( &hSectionTattoo, TRUE );
  9162. }
  9163. return(ScepDosErrorToSceStatus(rc));
  9164. }