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

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