Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9054 lines
274 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. analyze.c
  5. Abstract:
  6. Routines to analyze a system. The analysis information is saved in memory
  7. Author:
  8. Jin Huang (jinhuang) 25-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "headers.h"
  12. #include "serverp.h"
  13. #include "pfp.h"
  14. #include "infp.h"
  15. #include "service.h"
  16. #include "regvalue.h"
  17. #include "authz.h"
  18. #if _WIN32_WINNT>=0x0500
  19. #include "kerberos.h"
  20. #endif
  21. #include <aclapi.h>
  22. #include <io.h>
  23. #pragma hdrstop
  24. #define Add2Ptr(pv, cb) ((BYTE *) pv + cb)
  25. #define PSD_BASE_LENGTH 100
  26. //
  27. // properties of SAP engine (thread safe variables)
  28. //
  29. #define SE_VALID_CONTROL_BITS ( SE_DACL_UNTRUSTED | \
  30. SE_SERVER_SECURITY | \
  31. SE_DACL_AUTO_INHERIT_REQ | \
  32. SE_SACL_AUTO_INHERIT_REQ | \
  33. SE_DACL_AUTO_INHERITED | \
  34. SE_SACL_AUTO_INHERITED | \
  35. SE_DACL_PROTECTED | \
  36. SE_SACL_PROTECTED )
  37. extern PSCECONTEXT Thread hProfile;
  38. PSCESECTION Thread hSection=NULL;
  39. extern AUTHZ_RESOURCE_MANAGER_HANDLE ghAuthzResourceManager;
  40. DWORD Thread BadCnt;
  41. DWORD Thread gOptions=0;
  42. static PWSTR AccessItems[] = {
  43. {(PWSTR)TEXT("MinimumPasswordAge")},
  44. {(PWSTR)TEXT("MaximumPasswordAge")},
  45. {(PWSTR)TEXT("MinimumPasswordLength")},
  46. {(PWSTR)TEXT("PasswordComplexity")},
  47. {(PWSTR)TEXT("PasswordHistorySize")},
  48. {(PWSTR)TEXT("LockoutBadCount")},
  49. {(PWSTR)TEXT("ResetLockoutCount")},
  50. {(PWSTR)TEXT("LockoutDuration")},
  51. {(PWSTR)TEXT("RequireLogonToChangePassword")},
  52. {(PWSTR)TEXT("ForceLogoffWhenHourExpire")},
  53. {(PWSTR)TEXT("ClearTextPassword")},
  54. {(PWSTR)TEXT("LSAAnonymousNameLookup")},
  55. {(PWSTR)TEXT("EnableAdminAccount")},
  56. {(PWSTR)TEXT("EnableGuestAccount")}
  57. };
  58. #define MAX_ACCESS_ITEMS sizeof(AccessItems)/sizeof(PWSTR)
  59. #define IDX_MIN_PASS_AGE 0
  60. #define IDX_MAX_PASS_AGE 1
  61. #define IDX_MIN_PASS_LEN 2
  62. #define IDX_PASS_COMPLEX 3
  63. #define IDX_PASS_HISTORY 4
  64. #define IDX_LOCK_COUNT 5
  65. #define IDX_RESET_COUNT 6
  66. #define IDX_LOCK_DURATION 7
  67. #define IDX_CHANGE_PASS 8
  68. #define IDX_FORCE_LOGOFF 9
  69. #define IDX_CLEAR_PASS 10
  70. #define IDX_LSA_ANON_LOOKUP 11
  71. #define IDX_ENABLE_ADMIN 12
  72. #define IDX_ENABLE_GUEST 13
  73. static PWSTR LogItems[]={
  74. {(PWSTR)TEXT("MaximumLogSize")},
  75. {(PWSTR)TEXT("AuditLogRetentionPeriod")},
  76. {(PWSTR)TEXT("RetentionDays")},
  77. {(PWSTR)TEXT("RestrictGuestAccess")}
  78. };
  79. #define MAX_LOG_ITEMS 4
  80. #define IDX_MAX_LOG_SIZE 0
  81. #define IDX_RET_PERIOD 1
  82. #define IDX_RET_DAYS 2
  83. #define IDX_RESTRICT_GUEST 3
  84. static PWSTR EventItems[]={
  85. {(PWSTR)TEXT("AuditSystemEvents")},
  86. {(PWSTR)TEXT("AuditLogonEvents")},
  87. {(PWSTR)TEXT("AuditObjectAccess")},
  88. {(PWSTR)TEXT("AuditPrivilegeUse")},
  89. {(PWSTR)TEXT("AuditPolicyChange")},
  90. {(PWSTR)TEXT("AuditAccountManage")},
  91. {(PWSTR)TEXT("AuditProcessTracking")},
  92. {(PWSTR)TEXT("AuditDSAccess")},
  93. {(PWSTR)TEXT("AuditAccountLogon")}};
  94. #define MAX_EVENT_ITEMS 9
  95. #define IDX_AUDIT_SYSTEM 0
  96. #define IDX_AUDIT_LOGON 1
  97. #define IDX_AUDIT_OBJECT 2
  98. #define IDX_AUDIT_PRIV 3
  99. #define IDX_AUDIT_POLICY 4
  100. #define IDX_AUDIT_ACCOUNT 5
  101. #define IDX_AUDIT_PROCESS 6
  102. #define IDX_AUDIT_DS 7
  103. #define IDX_AUDIT_ACCT_LOGON 8
  104. //
  105. // forward references
  106. //
  107. SCESTATUS
  108. ScepAnalyzeInitialize(
  109. IN PCWSTR InfFileName OPTIONAL,
  110. IN PWSTR DatabaseName,
  111. IN BOOL bAdminLogon,
  112. IN AREA_INFORMATION Area,
  113. IN DWORD AnalyzeOptions
  114. );
  115. SCESTATUS
  116. ScepAnalyzeStart(
  117. IN AREA_INFORMATION Area,
  118. IN BOOL bSystemDb
  119. );
  120. NTSTATUS
  121. ScepAdminGuestAccountsToManage(
  122. IN SAM_HANDLE DomainHandle,
  123. IN DWORD AccountType,
  124. IN PWSTR TargetName OPTIONAL,
  125. OUT PBOOL ToRename,
  126. OUT PWSTR *CurrentName OPTIONAL,
  127. OUT PDWORD pNameLen OPTIONAL
  128. );
  129. SCESTATUS
  130. ScepAnalyzePrivileges(
  131. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivilegeList
  132. );
  133. DWORD
  134. ScepGetLSAPolicyObjectInfo(
  135. OUT DWORD *pdwAllow
  136. );
  137. /*
  138. NTSTATUS
  139. ScepGetCurrentPrivilegesRights(
  140. IN LSA_HANDLE PolicyHandle,
  141. IN SAM_HANDLE BuiltinDomainHandle,
  142. IN PSID BuiltinDomainSid,
  143. IN SAM_HANDLE DomainHandle,
  144. IN PSID DomainSid,
  145. IN SAM_HANDLE UserHandle OPTIONAL,
  146. IN PSID AccountSid,
  147. OUT PDWORD PrivilegeRights,
  148. OUT PSCE_NAME_STATUS_LIST *pPrivList
  149. );
  150. */
  151. SCESTATUS
  152. ScepAddAllBuiltinGroups(
  153. IN PSCE_GROUP_MEMBERSHIP *pGroupList
  154. );
  155. SCESTATUS
  156. ScepAnalyzeGroupMembership(
  157. IN PSCE_GROUP_MEMBERSHIP pGroupMembership
  158. );
  159. NTSTATUS
  160. ScepCompareMembersOfGroup(
  161. IN SAM_HANDLE DomainHandle,
  162. IN PSID ThisDomainSid,
  163. IN LSA_HANDLE PolicyHandle,
  164. IN SID_NAME_USE GrpUse,
  165. IN SAM_HANDLE GroupHandle,
  166. IN PSCE_NAME_LIST pChkMembers,
  167. OUT PSCE_NAME_LIST *ppMembers,
  168. OUT PBOOL bDifferent
  169. );
  170. SCESTATUS
  171. ScepEnumerateRegistryRoots(
  172. OUT PSCE_OBJECT_LIST *pRoots
  173. );
  174. SCESTATUS
  175. ScepEnumerateFileRoots(
  176. OUT PSCE_OBJECT_LIST *pRoots
  177. );
  178. SCESTATUS
  179. ScepAnalyzeObjectSecurity(
  180. IN PSCE_OBJECT_LIST pObjectCheckList,
  181. IN AREA_INFORMATION Area,
  182. IN BOOL bSystemDb
  183. );
  184. DWORD
  185. ScepAnalyzeOneObjectInTree(
  186. IN PSCE_OBJECT_TREE ThisNode,
  187. IN SE_OBJECT_TYPE ObjectType,
  188. IN HANDLE Token,
  189. IN PGENERIC_MAPPING GenericMapping
  190. );
  191. DWORD
  192. ScepAnalyzeObjectOnly(
  193. IN PWSTR ObjectFullName,
  194. IN BOOL IsContainer,
  195. IN SE_OBJECT_TYPE ObjectType,
  196. IN PSECURITY_DESCRIPTOR ProfileSD,
  197. IN SECURITY_INFORMATION ProfileSeInfo
  198. );
  199. DWORD
  200. ScepGetFileSecurityInfo(
  201. IN HANDLE Handle,
  202. IN SECURITY_INFORMATION SecurityInfo,
  203. OUT PSECURITY_DESCRIPTOR * pSecurityDescriptor
  204. );
  205. DWORD
  206. ScepGetSecurityDescriptorParts(
  207. IN PISECURITY_DESCRIPTOR pSecurityDescriptor,
  208. IN SECURITY_INFORMATION SecurityInfo,
  209. OUT PSECURITY_DESCRIPTOR *pOutSecurityDescriptor
  210. );
  211. DWORD
  212. ScepGetKeySecurityInfo(
  213. IN HANDLE Handle,
  214. IN SECURITY_INFORMATION SecurityInfo,
  215. OUT PSECURITY_DESCRIPTOR *pSecurityDescriptor
  216. );
  217. DWORD
  218. ScepAnalyzeObjectAndChildren(
  219. IN PWSTR ObjectFullName,
  220. IN SE_OBJECT_TYPE ObjectType,
  221. IN PSECURITY_DESCRIPTOR ProfileSD,
  222. IN SECURITY_INFORMATION ProfileSeInfo
  223. );
  224. SCESTATUS
  225. ScepAnalyzeSystemAuditing(
  226. IN PSCE_PROFILE_INFO pSmpInfo,
  227. IN PPOLICY_AUDIT_EVENTS_INFO auditEvent
  228. );
  229. SCESTATUS
  230. ScepAnalyzeDeInitialize(
  231. IN SCESTATUS rc,
  232. IN DWORD Options
  233. );
  234. SCESTATUS
  235. ScepMigrateDatabaseRevision0(
  236. IN PSCECONTEXT cxtProfile
  237. );
  238. SCESTATUS
  239. ScepMigrateDatabaseRevision1(
  240. IN PSCECONTEXT cxtProfile
  241. );
  242. SCESTATUS
  243. ScepMigrateObjectSection(
  244. IN PSCECONTEXT cxtProfile,
  245. IN PCWSTR szSection
  246. );
  247. SCESTATUS
  248. ScepMigrateOneSection(
  249. PSCESECTION hSection
  250. );
  251. SCESTATUS
  252. ScepMigrateLocalTableToTattooTable(
  253. IN PSCECONTEXT hProfile
  254. );
  255. SCESTATUS
  256. ScepMigrateDatabase(
  257. IN PSCECONTEXT cxtProfile,
  258. IN BOOL bSystemDb
  259. );
  260. SCESTATUS
  261. ScepDeleteOldRegValuesFromTable(
  262. IN PSCECONTEXT hProfile,
  263. IN SCETYPE TableType
  264. );
  265. BOOL
  266. ScepCompareSidNameList(
  267. IN PSCE_NAME_LIST pList1,
  268. IN PSCE_NAME_LIST pList2
  269. );
  270. DWORD
  271. ScepConvertSidListToStringName(
  272. IN LSA_HANDLE LsaPolicy,
  273. IN OUT PSCE_NAME_LIST pList
  274. );
  275. BOOL
  276. ScepCompareGroupNameList(
  277. IN PUNICODE_STRING DomainName,
  278. IN PSCE_NAME_LIST pListToCmp,
  279. IN PSCE_NAME_LIST pList
  280. );
  281. SCESTATUS
  282. ScepGetSystemPrivileges(
  283. IN DWORD Options,
  284. IN OUT PSCE_ERROR_LOG_INFO *pErrLog,
  285. OUT PSCE_PRIVILEGE_ASSIGNMENT *pCurrent
  286. );
  287. //
  288. // function implementations
  289. //
  290. SCESTATUS
  291. ScepAnalyzeSystem(
  292. IN PCWSTR InfFileName OPTIONAL,
  293. IN PWSTR DatabaseName,
  294. IN DWORD AnalyzeOptions,
  295. IN BOOL bAdminLogon,
  296. IN AREA_INFORMATION Area,
  297. IN PDWORD pdWarning OPTIONAL,
  298. IN PWSTR InfRollback OPTIONAL
  299. )
  300. /*++
  301. Routine Description:
  302. This routine is the exported API to analyze a system and save mismatched/
  303. unknown information to the SAP profile. If any error occurs when loading SMP
  304. information into memory, this routine will stop, free memmory, and return
  305. the error code. If a error occurs when analyze an area, it will stop analyze.
  306. All successful and fail transactions will be logged to the logfile(or stdout).
  307. All analysis information is saved to a SAP profile with a date/time stamp.
  308. All old analysis information is cleared before new SAP information is saved.
  309. Arguments:
  310. InfFileName - The file name of a SCP used to compare the analysis of a system
  311. DatabaseName - The JET analysis database name. If NULL, default is used.
  312. AnalyzeOptions - options to analyze
  313. bAdminLogon - if the current calling thread is in administrator's logon
  314. Area - One or more areas to configure.
  315. AREA_SECURITY_POLICY
  316. AREA_USER_SETTINGS
  317. AREA_GROUP_MEMBERSHIP
  318. AREA_REGISTRY_SECURITY
  319. AREA_SYSTEM_SERVICE
  320. AREA_FILE_SECURITY
  321. pdWarning - the warning level
  322. Return value:
  323. SCESTATUS_SUCCESS
  324. SCESTATUS_NOT_ENOUGH_RESOURCE
  325. SCESTATUS_INVALID_PARAMETER
  326. SCESTATUS_ALREADY_RUNNING
  327. Status from ScepGetDatabaseInfo
  328. -- */
  329. {
  330. SCESTATUS rc;
  331. if ( AnalyzeOptions & SCE_GENERATE_ROLLBACK ) {
  332. if ( InfRollback == NULL )
  333. return SCESTATUS_INVALID_PARAMETER;
  334. //
  335. // check if we can write to the file first
  336. //
  337. rc = ScepVerifyTemplateName(InfRollback, NULL);
  338. if ( rc != ERROR_SUCCESS )
  339. return ScepDosErrorToSceStatus(rc);
  340. Area = Area & ( AREA_SECURITY_POLICY |
  341. AREA_GROUP_MEMBERSHIP |
  342. AREA_PRIVILEGES |
  343. AREA_SYSTEM_SERVICE);
  344. }
  345. rc = ScepAnalyzeInitialize(
  346. InfFileName,
  347. DatabaseName,
  348. bAdminLogon,
  349. Area,
  350. AnalyzeOptions
  351. );
  352. if ( rc != SCESTATUS_SUCCESS ) {
  353. ScepLogOutput3(0,0, SCEDLL_SAP_INIT_ERROR);
  354. ScepPostProgress(gTotalTicks, 0, NULL);
  355. } else {
  356. ScepLogOutput3(0,0, SCEDLL_SAP_INIT_SUCCESS);
  357. if ( !(AnalyzeOptions & SCE_RE_ANALYZE) &&
  358. (AnalyzeOptions & SCE_NO_ANALYZE) ) {
  359. // && hProfile &&
  360. // ( (hProfile->Type & 0xF0L) == SCEJET_MERGE_TABLE_1 ||
  361. // (hProfile->Type & 0xF0L) == SCEJET_MERGE_TABLE_2 ) ) {
  362. //
  363. // there is "merged" policy table already, do not query any policy
  364. //
  365. ScepLogOutput3(0, 0, IDS_NO_ANALYSIS);
  366. } else {
  367. BOOL bSystemDb = FALSE;
  368. if ( bAdminLogon &&
  369. ( AnalyzeOptions & SCE_SYSTEM_DB) ) {
  370. bSystemDb = TRUE;
  371. }
  372. rc = ScepAnalyzeStart( Area, bSystemDb);
  373. if ( (AnalyzeOptions & SCE_GENERATE_ROLLBACK) &&
  374. (SCESTATUS_SUCCESS == rc ) ) {
  375. //
  376. // export the settings in SMP to the INF file
  377. //
  378. if ( !WritePrivateProfileSection(
  379. L"Version",
  380. L"signature=\"$CHICAGO$\"\0Revision=1\0\0",
  381. (LPCTSTR)InfRollback) ) {
  382. rc = ScepDosErrorToSceStatus(GetLastError());
  383. } else {
  384. HINSTANCE hSceCliDll = LoadLibrary(TEXT("scecli.dll"));
  385. if ( hSceCliDll ) {
  386. PFSCEINFWRITEINFO pfSceInfWriteInfo = (PFSCEINFWRITEINFO)GetProcAddress(
  387. hSceCliDll,
  388. "SceWriteSecurityProfileInfo");
  389. if ( pfSceInfWriteInfo ) {
  390. PSCE_ERROR_LOG_INFO pErrlog=NULL, pErr;
  391. PSCE_PROFILE_INFO pSmpInfo=NULL;
  392. //
  393. // get from database
  394. //
  395. rc = ScepGetDatabaseInfo(
  396. hProfile,
  397. SCE_ENGINE_SMP,
  398. Area,
  399. 0,
  400. &pSmpInfo,
  401. &pErrlog
  402. );
  403. if ( rc == SCESTATUS_SUCCESS && pSmpInfo ) {
  404. //
  405. // write it into the template
  406. //
  407. rc = (*pfSceInfWriteInfo) (
  408. InfRollback,
  409. Area,
  410. pSmpInfo,
  411. &pErrlog
  412. );
  413. }
  414. //
  415. // log error
  416. //
  417. for ( pErr=pErrlog; pErr != NULL; pErr = pErr->next ) {
  418. if ( pErr->buffer != NULL ) {
  419. ScepLogOutput2(1, pErr->rc, pErr->buffer );
  420. }
  421. }
  422. //
  423. // free buffer
  424. //
  425. ScepFreeErrorLog(pErrlog);
  426. if ( pSmpInfo ) {
  427. SceFreeProfileMemory(pSmpInfo);
  428. }
  429. } else {
  430. rc = ScepDosErrorToSceStatus(GetLastError());
  431. }
  432. FreeLibrary(hSceCliDll);
  433. } else {
  434. rc = ScepDosErrorToSceStatus(GetLastError());
  435. }
  436. }
  437. if ( rc != SCESTATUS_SUCCESS ) {
  438. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  439. SCEDLL_ERROR_GENERATE,
  440. InfRollback
  441. );
  442. }
  443. }
  444. if ( AnalyzeOptions & SCE_GENERATE_ROLLBACK ) {
  445. //
  446. // empty local policy table
  447. //
  448. ScepDeleteInfoForAreas(
  449. hProfile,
  450. SCE_ENGINE_SMP,
  451. AREA_ALL
  452. );
  453. }
  454. }
  455. }
  456. ScepLogOutput3(0,0, SCEDLL_SAP_UNINIT);
  457. if ( pdWarning ) {
  458. *pdWarning = gWarningCode;
  459. }
  460. //
  461. // return failure if invalid data is found in the template
  462. //
  463. if ( gbInvalidData ) {
  464. rc = SCESTATUS_INVALID_DATA;
  465. }
  466. ScepAnalyzeDeInitialize( rc, AnalyzeOptions );
  467. return(rc);
  468. }
  469. SCESTATUS
  470. ScepAnalyzeStart(
  471. IN AREA_INFORMATION Area,
  472. IN BOOL bSystemDb
  473. )
  474. /*
  475. Routine Description:
  476. Analyze the system (the real work)
  477. Arguments:
  478. Area - the security areas to analyze
  479. Return Value:
  480. SCESTATUS
  481. */
  482. {
  483. SCESTATUS rc;
  484. SCESTATUS Saverc=SCESTATUS_SUCCESS;
  485. SCE_PROFILE_INFO SmpInfo;
  486. PSCE_PROFILE_INFO pSmpInfo=NULL;
  487. PPOLICY_AUDIT_EVENTS_INFO auditEvent=NULL;
  488. BOOL bAuditOff=FALSE;
  489. // PBYTE pFullAudit = NULL;
  490. pSmpInfo = &SmpInfo;
  491. memset(pSmpInfo, '\0', sizeof(SCE_PROFILE_INFO));
  492. /* //
  493. // 462050 - should not turn off object access auditing to leave a
  494. // security hole on the system
  495. //
  496. // turn off object access auditing if file/key is to be configured
  497. // in system context.
  498. //
  499. if ( (Area & AREA_FILE_SECURITY) || (Area & AREA_REGISTRY_SECURITY) )
  500. bAuditOff = TRUE;
  501. //
  502. // if set, this regkey will decide to audit all
  503. //
  504. ScepRegQueryBinaryValue(
  505. HKEY_LOCAL_MACHINE,
  506. L"System\\CurrentControlSet\\Control\\Lsa",
  507. L"fullprivilegeauditing",
  508. &pFullAudit
  509. );
  510. if (pFullAudit) {
  511. if (*pFullAudit & (BYTE)1)
  512. bAuditOff = FALSE;
  513. ScepFree(pFullAudit);
  514. }
  515. */
  516. rc = ScepSaveAndOffAuditing(&auditEvent, bAuditOff, NULL);
  517. // if ( rc != SCESTATUS_SUCCESS )
  518. // goto Done;
  519. // if auditing can't be turned on for some reason, e.g., access denied for
  520. // normal user, just continue (actually normal user shouldn't turn off auditing
  521. //
  522. // privileges
  523. //
  524. if ( Area & AREA_PRIVILEGES ) {
  525. ScepPostProgress(0, AREA_PRIVILEGES, NULL);
  526. ScepLogOutput3(0,0, SCEDLL_SAP_READ_PROFILE);
  527. rc = ScepGetProfileOneArea(
  528. hProfile,
  529. bSystemDb ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  530. AREA_PRIVILEGES,
  531. SCE_ACCOUNT_SID,
  532. &pSmpInfo
  533. );
  534. if ( rc == SCESTATUS_SUCCESS ) {
  535. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_PRIVILEGES);
  536. rc = ScepAnalyzePrivileges( pSmpInfo->OtherInfo.smp.pPrivilegeAssignedTo);
  537. SceFreeMemory((PVOID)pSmpInfo, AREA_PRIVILEGES );
  538. } else {
  539. ScepPostProgress(TICKS_PRIVILEGE, AREA_PRIVILEGES, NULL);
  540. }
  541. if( rc != SCESTATUS_SUCCESS ) {
  542. Saverc = rc;
  543. ScepLogOutput3(0,0, SCEDLL_SAP_PRIVILEGES_ERROR);
  544. } else {
  545. ScepLogOutput3(0,0, SCEDLL_SAP_PRIVILEGES_SUCCESS);
  546. }
  547. }
  548. //
  549. // Group membership
  550. //
  551. if ( ( Area & AREA_GROUP_MEMBERSHIP) &&
  552. !(gOptions & SCE_NO_ANALYZE) ) {
  553. ScepPostProgress(0, AREA_GROUP_MEMBERSHIP, NULL);
  554. ScepLogOutput3(0,0, SCEDLL_SAP_READ_PROFILE);
  555. rc = ScepGetProfileOneArea(
  556. hProfile,
  557. bSystemDb ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  558. AREA_GROUP_MEMBERSHIP,
  559. SCE_ACCOUNT_SID,
  560. &pSmpInfo
  561. );
  562. // need to support nested groups
  563. if ( rc == SCESTATUS_SUCCESS ) {
  564. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_GROUPMGMT);
  565. //
  566. // Prepare a JET section
  567. //
  568. rc = ScepStartANewSection(
  569. hProfile,
  570. &hSection,
  571. (gOptions & SCE_GENERATE_ROLLBACK) ? SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  572. szGroupMembership
  573. );
  574. if ( rc == SCESTATUS_SUCCESS ) {
  575. //
  576. // analyze all builtin groups, what is the baseline for them ?
  577. // don't care if errors
  578. //
  579. if ( !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  580. ScepAddAllBuiltinGroups(&(pSmpInfo->pGroupMembership));
  581. }
  582. #if _WIN32_WINNT>=0x0500
  583. if ( ProductType == NtProductLanManNt ) {
  584. rc = ScepAnalyzeDsGroups( pSmpInfo->pGroupMembership );
  585. //
  586. // some groups may not be analyzed by the DS function
  587. // so do it again here
  588. //
  589. SCESTATUS rc2 = ScepAnalyzeGroupMembership( pSmpInfo->pGroupMembership );
  590. if ( SCESTATUS_SUCCESS != rc2 )
  591. rc = rc2;
  592. } else {
  593. #endif
  594. //
  595. // workstation or NT4 DCs
  596. //
  597. rc = ScepAnalyzeGroupMembership( pSmpInfo->pGroupMembership );
  598. #if _WIN32_WINNT>=0x0500
  599. }
  600. #endif
  601. } else {
  602. ScepPostProgress(TICKS_GROUPS, AREA_GROUP_MEMBERSHIP, NULL);
  603. ScepLogOutput3(0, ScepSceStatusToDosError(rc),
  604. SCEDLL_ERROR_OPEN, (PWSTR)szGroupMembership);
  605. }
  606. SceFreeMemory((PVOID)pSmpInfo, AREA_GROUP_MEMBERSHIP );
  607. } else {
  608. ScepPostProgress(TICKS_GROUPS, AREA_GROUP_MEMBERSHIP, NULL);
  609. }
  610. if( rc != SCESTATUS_SUCCESS ) {
  611. Saverc = rc;
  612. ScepLogOutput3(0,0, SCEDLL_SAP_GROUPMGMT_ERROR);
  613. } else {
  614. ScepLogOutput3(0,0, SCEDLL_SAP_GROUPMGMT_SUCCESS);
  615. }
  616. }
  617. //
  618. // Registry Security area
  619. // do not support snapshot and rollback
  620. //
  621. if ( Area & AREA_REGISTRY_SECURITY &&
  622. !(gOptions & SCE_NO_ANALYZE) &&
  623. !(gOptions & SCE_GENERATE_ROLLBACK ) ) {
  624. ScepPostProgress(0, AREA_REGISTRY_SECURITY, NULL);
  625. ScepLogOutput3(0,0, SCEDLL_SAP_READ_PROFILE);
  626. rc = ScepGetProfileOneArea(
  627. hProfile,
  628. bSystemDb ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  629. AREA_REGISTRY_SECURITY,
  630. 0,
  631. &pSmpInfo
  632. );
  633. if ( rc == SCESTATUS_SUCCESS ) {
  634. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_REGISTRY);
  635. rc = ScepEnumerateRegistryRoots(&(pSmpInfo->pRegistryKeys.pOneLevel));
  636. if ( rc == SCESTATUS_SUCCESS ) {
  637. rc = ScepAnalyzeObjectSecurity(pSmpInfo->pRegistryKeys.pOneLevel,
  638. AREA_REGISTRY_SECURITY,
  639. bSystemDb
  640. );
  641. } else {
  642. ScepPostProgress(gMaxRegTicks, AREA_REGISTRY_SECURITY, NULL);
  643. }
  644. SceFreeMemory((PVOID)pSmpInfo, AREA_REGISTRY_SECURITY);
  645. } else {
  646. ScepPostProgress(gMaxRegTicks, AREA_REGISTRY_SECURITY, NULL);
  647. }
  648. if( rc != SCESTATUS_SUCCESS ) {
  649. Saverc = rc;
  650. ScepLogOutput3(0,0, SCEDLL_SAP_REGISTRY_ERROR);
  651. } else {
  652. ScepLogOutput3(0,0, SCEDLL_SAP_REGISTRY_SUCCESS);
  653. }
  654. }
  655. //
  656. // File Security area
  657. // do not support snapshot and rollback
  658. //
  659. if ( Area & AREA_FILE_SECURITY &&
  660. !(gOptions & SCE_NO_ANALYZE) &&
  661. !(gOptions & SCE_GENERATE_ROLLBACK)) {
  662. ScepPostProgress(0, AREA_FILE_SECURITY, NULL);
  663. ScepLogOutput3(0,0, SCEDLL_SAP_READ_PROFILE);
  664. rc = ScepGetProfileOneArea(
  665. hProfile,
  666. bSystemDb ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  667. AREA_FILE_SECURITY,
  668. 0,
  669. &pSmpInfo
  670. );
  671. if ( rc == SCESTATUS_SUCCESS ) {
  672. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_FILE);
  673. rc = ScepEnumerateFileRoots(&(pSmpInfo->pFiles.pOneLevel));
  674. if ( rc == SCESTATUS_SUCCESS ) {
  675. rc = ScepAnalyzeObjectSecurity(pSmpInfo->pFiles.pOneLevel,
  676. AREA_FILE_SECURITY,
  677. bSystemDb
  678. );
  679. } else {
  680. ScepPostProgress(gMaxFileTicks, AREA_FILE_SECURITY, NULL);
  681. }
  682. SceFreeMemory((PVOID)pSmpInfo, AREA_FILE_SECURITY);
  683. } else {
  684. ScepPostProgress(gMaxFileTicks, AREA_FILE_SECURITY, NULL);
  685. }
  686. if( rc != SCESTATUS_SUCCESS ) {
  687. Saverc = rc;
  688. ScepLogOutput3(0,0, SCEDLL_SAP_FILE_ERROR);
  689. } else {
  690. ScepLogOutput3(0,0, SCEDLL_SAP_FILE_SUCCESS);
  691. }
  692. }
  693. //
  694. // System Service area
  695. //
  696. if ( Area & AREA_SYSTEM_SERVICE &&
  697. !(gOptions & SCE_NO_ANALYZE) ) {
  698. ScepPostProgress(0, AREA_SYSTEM_SERVICE, NULL);
  699. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_GENERALSVC);
  700. rc = ScepAnalyzeGeneralServices( hProfile, gOptions);
  701. if( rc != SCESTATUS_SUCCESS ) {
  702. Saverc = rc;
  703. ScepLogOutput3(0,0, SCEDLL_SAP_GENERALSVC_ERROR);
  704. } else {
  705. ScepLogOutput3(0,0, SCEDLL_SAP_GENERALSVC_SUCCESS);
  706. }
  707. if ( !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  708. //
  709. // attachments
  710. //
  711. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_ATTACHMENT);
  712. rc = ScepInvokeSpecificServices( hProfile, FALSE, SCE_ATTACHMENT_SERVICE );
  713. if( rc != SCESTATUS_SUCCESS && SCESTATUS_SERVICE_NOT_SUPPORT != rc ) {
  714. Saverc = rc;
  715. ScepLogOutput3(0,0, SCEDLL_SAP_ATTACHMENT_ERROR);
  716. } else {
  717. ScepLogOutput3(0,0, SCEDLL_SAP_ATTACHMENT_SUCCESS);
  718. }
  719. }
  720. }
  721. //
  722. // System Access area
  723. //
  724. if ( Area & AREA_SECURITY_POLICY ) {
  725. ScepPostProgress(0, AREA_SECURITY_POLICY, NULL);
  726. ScepLogOutput3(0,0, SCEDLL_SAP_READ_PROFILE);
  727. rc = ScepGetProfileOneArea(
  728. hProfile,
  729. bSystemDb ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  730. AREA_SECURITY_POLICY,
  731. 0,
  732. &pSmpInfo
  733. );
  734. if ( rc == SCESTATUS_SUCCESS ) {
  735. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_POLICY);
  736. rc = ScepAnalyzeSystemAccess( pSmpInfo, NULL, 0, NULL, NULL );
  737. //
  738. // in setup fresh installed, SAM domain can't be opened
  739. // because computer name is changed. In this case
  740. // do not log error because nothing needs to be analyzed
  741. //
  742. if ( !(gOptions & SCE_NO_ANALYZE) ||
  743. (rc != SCESTATUS_SERVICE_NOT_SUPPORT) ) {
  744. if( rc != SCESTATUS_SUCCESS ) {
  745. Saverc = rc;
  746. ScepLogOutput3(0,0, SCEDLL_SAP_ACCESS_ERROR);
  747. } else {
  748. ScepLogOutput3(0,0, SCEDLL_SAP_ACCESS_SUCCESS);
  749. }
  750. }
  751. ScepPostProgress(TICKS_SYSTEM_ACCESS,
  752. AREA_SECURITY_POLICY,
  753. (LPTSTR)szSystemAccess);
  754. //
  755. // System Auditing area
  756. //
  757. rc = ScepAnalyzeSystemAuditing( pSmpInfo, auditEvent );
  758. if( rc != SCESTATUS_SUCCESS ) {
  759. Saverc = rc;
  760. ScepLogOutput3(0,0, SCEDLL_SAP_AUDIT_ERROR);
  761. } else {
  762. ScepLogOutput3(0,0, SCEDLL_SAP_AUDIT_SUCCESS);
  763. }
  764. ScepPostProgress(TICKS_SYSTEM_AUDITING,
  765. AREA_SECURITY_POLICY,
  766. (LPTSTR)szAuditEvent);
  767. #if _WIN32_WINNT>=0x0500
  768. if ( ProductType == NtProductLanManNt &&
  769. !(gOptions & SCE_NO_ANALYZE) ) {
  770. //
  771. // analyze kerberos policy
  772. //
  773. rc = ScepAnalyzeKerberosPolicy( hProfile, pSmpInfo->pKerberosInfo, gOptions );
  774. if( rc != SCESTATUS_SUCCESS ) {
  775. Saverc = rc;
  776. ScepLogOutput3(0,0, SCEDLL_SAP_KERBEROS_ERROR);
  777. } else {
  778. ScepLogOutput3(0,0, SCEDLL_SAP_KERBEROS_SUCCESS);
  779. }
  780. }
  781. #endif
  782. ScepPostProgress(TICKS_KERBEROS,
  783. AREA_SECURITY_POLICY,
  784. (LPTSTR)szKerberosPolicy);
  785. //
  786. // analyze registry values
  787. //
  788. DWORD RegFlag;
  789. if ( gOptions & SCE_NO_ANALYZE ) RegFlag = SCEREG_VALUE_SNAPSHOT;
  790. else if ( gOptions & SCE_GENERATE_ROLLBACK ) RegFlag = SCEREG_VALUE_ROLLBACK;
  791. else RegFlag = SCEREG_VALUE_ANALYZE;
  792. rc = ScepAnalyzeRegistryValues( hProfile,
  793. RegFlag,
  794. pSmpInfo
  795. );
  796. if( rc != SCESTATUS_SUCCESS ) {
  797. Saverc = rc;
  798. ScepLogOutput3(0,0, SCEDLL_SAP_REGVALUES_ERROR);
  799. } else {
  800. ScepLogOutput3(0,0, SCEDLL_SAP_REGVALUES_SUCCESS);
  801. }
  802. ScepPostProgress(TICKS_REGISTRY_VALUES,
  803. AREA_SECURITY_POLICY,
  804. (LPTSTR)szRegistryValues);
  805. SceFreeMemory((PVOID)pSmpInfo, AREA_SECURITY_POLICY);
  806. } else {
  807. ScepPostProgress(TICKS_SECURITY_POLICY_DS, AREA_SECURITY_POLICY, NULL);
  808. Saverc = rc;
  809. ScepLogOutput3(0,0, SCEDLL_SAP_POLICY_ERROR);
  810. }
  811. ScepLogOutput3(0,0, SCEDLL_SAP_BEGIN_ATTACHMENT);
  812. if ( !(gOptions & SCE_NO_ANALYZE) &&
  813. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  814. //
  815. // attachments
  816. //
  817. rc = ScepInvokeSpecificServices( hProfile, FALSE, SCE_ATTACHMENT_POLICY );
  818. if( rc != SCESTATUS_SUCCESS && SCESTATUS_SERVICE_NOT_SUPPORT != rc ) {
  819. Saverc = rc;
  820. ScepLogOutput3(0,0, SCEDLL_SAP_ATTACHMENT_ERROR);
  821. } else {
  822. ScepLogOutput3(0,0, SCEDLL_SAP_ATTACHMENT_SUCCESS);
  823. }
  824. } else {
  825. ScepPostProgress(TICKS_SPECIFIC_POLICIES, AREA_SECURITY_POLICY, NULL);
  826. }
  827. }
  828. if ( NULL != auditEvent && bAuditOff ) {
  829. //
  830. // turn auditing back on if it was on
  831. //
  832. if ( auditEvent->AuditingMode )
  833. rc = ScepRestoreAuditing(auditEvent,NULL);
  834. LsaFreeMemory(auditEvent);
  835. }
  836. return(Saverc);
  837. }
  838. SCESTATUS
  839. ScepAnalyzeInitialize(
  840. IN PCWSTR InfFileName OPTIONAL,
  841. IN PWSTR DatabaseName,
  842. IN BOOL bAdminLogon,
  843. IN AREA_INFORMATION Area,
  844. IN DWORD AnalyzeOptions
  845. )
  846. /* ++
  847. Routine Description:
  848. This routine initializes the SAP engine.
  849. Arguments:
  850. InfFileName - The file name of a SCP file used to compare with the sytem
  851. DatabaseName - The Jet analysis database name
  852. bAdminLogon - if administrator logs on
  853. AnalyzeOptions - The flag to indicate if the template should be appended to the
  854. existing database if one exists
  855. Area - security area to analyze
  856. Return value:
  857. SCESTATUS_SUCCESS
  858. SCESTATUS_INVALID_PARAMETER
  859. SCESTATUS_PROFILE_NOT_FOUND
  860. SCESTATUS_NOT_ENOUGH_RESOURCE
  861. SCESTATUS_ALREADY_RUNNING
  862. -- */
  863. {
  864. SCESTATUS rc=SCESTATUS_SUCCESS;
  865. PCHAR FileName=NULL;
  866. DWORD MBLen=0;
  867. NTSTATUS NtStatus;
  868. DWORD NameLen=MAX_COMPUTERNAME_LENGTH;
  869. PSCE_ERROR_LOG_INFO Errlog=NULL;
  870. DWORD SCPLen=0, DefLen=0;
  871. PWSTR BaseProfile=NULL;
  872. PSECURITY_DESCRIPTOR pSD=NULL;
  873. SECURITY_INFORMATION SeInfo;
  874. DWORD SDsize;
  875. SCEJET_CREATE_TYPE DbFlag;
  876. HKEY hCurrentUser=NULL;
  877. //
  878. // database name can't be NULL because it's already resolved
  879. //
  880. if ( !DatabaseName ) {
  881. return(SCESTATUS_INVALID_PARAMETER);
  882. }
  883. BOOL bSetupDb = (bAdminLogon && (AnalyzeOptions & SCE_NO_ANALYZE) && (AnalyzeOptions & SCE_SYSTEM_DB));
  884. //
  885. // get other system values
  886. //
  887. if ( RtlGetNtProductType (&ProductType) == FALSE ) {
  888. rc = ScepDosErrorToSceStatus(GetLastError());
  889. goto Leave;
  890. }
  891. gTotalTicks = 4*TICKS_MIGRATION_SECTION+TICKS_MIGRATION_V11;
  892. gCurrentTicks = 0;
  893. gWarningCode = 0;
  894. gbInvalidData = FALSE;
  895. cbClientFlag = (BYTE)(AnalyzeOptions & (SCE_CALLBACK_DELTA |
  896. SCE_CALLBACK_TOTAL));
  897. DefLen = wcslen(DatabaseName);
  898. if ( InfFileName != NULL ) {
  899. SCPLen = wcslen(InfFileName);
  900. }
  901. //
  902. // Open the file
  903. //
  904. NtStatus = RtlUnicodeToMultiByteSize(&MBLen, DatabaseName, DefLen*sizeof(WCHAR));
  905. if ( !NT_SUCCESS(NtStatus) ) {
  906. //
  907. // cannot get the length, set default to 512
  908. //
  909. MBLen = 512;
  910. }
  911. FileName = (PCHAR)ScepAlloc(LPTR, MBLen+2);
  912. if ( FileName == NULL ) {
  913. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  914. goto Leave;
  915. }
  916. NtStatus = RtlUnicodeToMultiByteN(
  917. FileName,
  918. MBLen+1,
  919. NULL,
  920. DatabaseName,
  921. DefLen*sizeof(WCHAR)
  922. );
  923. if ( !NT_SUCCESS(NtStatus) ) {
  924. ScepLogOutput3(3, RtlNtStatusToDosError(NtStatus),
  925. SCEDLL_ERROR_PROCESS_UNICODE, DatabaseName );
  926. rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError(NtStatus) );
  927. goto Leave;
  928. }
  929. //
  930. // if the tattoo table doesn't exist yet, the call will still return success
  931. //
  932. rc = SceJetOpenFile(
  933. (LPSTR)FileName,
  934. (AnalyzeOptions & SCE_GENERATE_ROLLBACK) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
  935. bSetupDb ? SCE_TABLE_OPTION_TATTOO : 0,
  936. &hProfile
  937. );
  938. //
  939. // if database exist with wrong format, migrate it
  940. // if it's the system database, delete everything since info there is not needed
  941. // migrate the database
  942. //
  943. SDsize = 0;
  944. if ( (SCESTATUS_BAD_FORMAT == rc) &&
  945. !(AnalyzeOptions & SCE_GENERATE_ROLLBACK) ) {
  946. //
  947. // should this in transaction ???
  948. //
  949. rc = SceJetOpenFile(
  950. (LPSTR)FileName,
  951. SCEJET_OPEN_NOCHECK_VERSION,
  952. 0,
  953. &hProfile
  954. );
  955. if ( SCESTATUS_SUCCESS == rc ) {
  956. rc = ScepMigrateDatabase( hProfile, bSetupDb );
  957. if ( rc != SCESTATUS_BAD_FORMAT ) {
  958. //
  959. // old or current version, migrated
  960. //
  961. if ( rc != SCESTATUS_SUCCESS ) {
  962. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  963. SCEDLL_ERROR_CONVERT, DatabaseName);
  964. }
  965. SDsize = 1;
  966. } // else newer version, not migrated
  967. } else {
  968. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  969. SCEDLL_ERROR_OPEN, DatabaseName);
  970. rc = SCESTATUS_BAD_FORMAT;
  971. }
  972. if ( SDsize == 0 ) {
  973. ScepPostProgress(4*TICKS_MIGRATION_SECTION+TICKS_MIGRATION_V11, 0, NULL);
  974. }
  975. if ( rc != SCESTATUS_SUCCESS ) {
  976. goto Leave;
  977. }
  978. } else if ( SCESTATUS_SUCCESS == rc && bSetupDb ) {
  979. //
  980. // for system database, check to see if the database contain tattoo table
  981. //
  982. if ( hProfile->JetSapID != JET_tableidNil ) {
  983. //
  984. // if the tattoo table already exists, this is the latest database
  985. // nothing needs to be done to migrate
  986. // but we need to make sure that for domain controllers, the tattoo
  987. // table does not contain filtered policies (user rights, account policies)
  988. //
  989. if ( ProductType == NtProductLanManNt ) {
  990. //
  991. // empty tattoo policy settings
  992. //
  993. ScepDeleteInfoForAreas(
  994. hProfile,
  995. SCE_ENGINE_SAP, // tattoo table
  996. AREA_PRIVILEGES
  997. );
  998. //
  999. // delete szSystemAccess section info
  1000. //
  1001. ScepDeleteOneSection(
  1002. hProfile,
  1003. SCE_ENGINE_SAP,
  1004. szSystemAccess
  1005. );
  1006. //
  1007. // delete szAuditEvent section info
  1008. //
  1009. ScepDeleteOneSection(
  1010. hProfile,
  1011. SCE_ENGINE_SAP,
  1012. szAuditEvent
  1013. );
  1014. //
  1015. // delete szKerberosPolicy section info
  1016. //
  1017. ScepDeleteOneSection(
  1018. hProfile,
  1019. SCE_ENGINE_SAP,
  1020. szKerberosPolicy
  1021. );
  1022. ScepLogOutput2(0, 0, L"Empty tattoo table on domain controllers");
  1023. }
  1024. } else {
  1025. //
  1026. // create the tattoo table and move data from local table to the tattoo table
  1027. // for the settings defined in merged policy
  1028. //
  1029. rc = SceJetCreateTable(
  1030. hProfile,
  1031. "SmTblTattoo",
  1032. SCEJET_TABLE_TATTOO,
  1033. SCEJET_CREATE_IN_BUFFER,
  1034. NULL,
  1035. NULL
  1036. );
  1037. if ( SCESTATUS_SUCCESS == rc &&
  1038. ( (hProfile->Type & 0xF0L) == SCEJET_MERGE_TABLE_1 ||
  1039. (hProfile->Type & 0xF0L) == SCEJET_MERGE_TABLE_2 ) ) {
  1040. //
  1041. // effective policy table exist
  1042. // migrate local policy to tattoo table
  1043. // do not care errors
  1044. // note, on domain controllers, user rights are not migrated
  1045. //
  1046. ScepMigrateLocalTableToTattooTable(hProfile);
  1047. ScepLogOutput2(0, 0, L"Migrate local table to tattoo table");
  1048. }
  1049. }
  1050. //
  1051. // empty local policy settings
  1052. //
  1053. if ( SCESTATUS_SUCCESS == rc )
  1054. ScepDeleteInfoForAreas(
  1055. hProfile,
  1056. SCE_ENGINE_SMP,
  1057. AREA_ALL
  1058. );
  1059. ScepPostProgress(4*TICKS_MIGRATION_SECTION+TICKS_MIGRATION_V11, 0, NULL);
  1060. } else {
  1061. ScepPostProgress(4*TICKS_MIGRATION_SECTION+TICKS_MIGRATION_V11, 0, NULL);
  1062. }
  1063. //
  1064. // Logic to determine what to do with the template
  1065. //
  1066. // if InfFileName provided
  1067. // if Jet database exist (either the default, or the DatabaseName)
  1068. //
  1069. // if append flag is on
  1070. // append the template on top of the database then continue to analyze
  1071. //
  1072. // else if DatabaseName provided
  1073. // overwrite the database then continue to analyze
  1074. // else
  1075. // log an error to ignore the template, then continue to analyze
  1076. // else
  1077. // overwrite the database then continue to analyze
  1078. // else
  1079. // if Jet database exist
  1080. // continue to analyze
  1081. // else if query system settings
  1082. // create the database then query settings
  1083. // else
  1084. // error out
  1085. //
  1086. //
  1087. // the HKEY_CURRENT_USER may be linked to .default
  1088. // depends on the current calling process
  1089. //
  1090. if ( RegOpenCurrentUser(
  1091. KEY_READ | KEY_WRITE,
  1092. &hCurrentUser
  1093. ) != ERROR_SUCCESS ) {
  1094. hCurrentUser = NULL;
  1095. }
  1096. if ( hCurrentUser == NULL ) {
  1097. hCurrentUser = HKEY_CURRENT_USER;
  1098. }
  1099. if ( rc == SCESTATUS_SUCCESS &&
  1100. (SCPLen <= 0 || ((AnalyzeOptions & SCE_OVERWRITE_DB) &&
  1101. (AnalyzeOptions & SCE_SYSTEM_DB))) ) {
  1102. //
  1103. // database exists with no template or
  1104. // database exists with template but template is overwriting to the existing database
  1105. //
  1106. if ( SCPLen > 0 && (AnalyzeOptions & SCE_OVERWRITE_DB) &&
  1107. (AnalyzeOptions & SCE_SYSTEM_DB)) {
  1108. ScepLogOutput3(0,0, SCEDLL_SAP_IGNORE_TEMPLATE);
  1109. }
  1110. //
  1111. // continue the analysis
  1112. //
  1113. } else {
  1114. if ( rc != SCESTATUS_SUCCESS && SCPLen <= 0 ) {
  1115. //
  1116. // database does not exist, and template is not provided
  1117. // if SCE_NO_ANALYZE is provided, query the system,
  1118. // otherwise, error out, rc is the error, will be logged later
  1119. if ( AnalyzeOptions & SCE_NO_ANALYZE ) {
  1120. if ( DatabaseName != NULL && DefLen > 0 ) {
  1121. rc = ConvertTextSecurityDescriptor (
  1122. L"D:P(A;CIOI;GA;;;CO)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
  1123. &pSD,
  1124. &SDsize,
  1125. &SeInfo
  1126. );
  1127. if ( rc != NO_ERROR )
  1128. ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, DatabaseName );
  1129. ScepChangeAclRevision(pSD, ACL_REVISION);
  1130. ScepCreateDirectory(
  1131. DatabaseName,
  1132. FALSE, // a file name
  1133. pSD // take parent's security setting
  1134. );
  1135. if ( pSD )
  1136. ScepFree(pSD);
  1137. }
  1138. rc = SceJetCreateFile(
  1139. (LPSTR)FileName,
  1140. SCEJET_OPEN_DUP_EXCLUSIVE,
  1141. SCE_TABLE_OPTION_TATTOO,
  1142. &hProfile
  1143. );
  1144. }
  1145. } else {
  1146. if ( rc == SCESTATUS_SUCCESS && SCPLen > 0 &&
  1147. (AnalyzeOptions & SCE_UPDATE_DB ) ) {
  1148. //
  1149. // database exist, template provided to append
  1150. //
  1151. DbFlag = SCEJET_OPEN_DUP_EXCLUSIVE;
  1152. } else if ( AnalyzeOptions & SCE_GENERATE_ROLLBACK ) {
  1153. DbFlag = SCEJET_OPEN_DUP;
  1154. } else {
  1155. DbFlag = SCEJET_OVERWRITE_DUP;
  1156. }
  1157. //
  1158. // database exist and opened, will be closed when calling CreateFile
  1159. //
  1160. //
  1161. // InfFileName must exist when gets here.
  1162. //
  1163. ScepLogOutput3(3, 0, SCEDLL_PROCESS_TEMPLATE, (PWSTR)InfFileName );
  1164. //
  1165. // make sure the directories exist for the file
  1166. //
  1167. if ( DatabaseName != NULL && DefLen > 0 ) {
  1168. rc = ConvertTextSecurityDescriptor (
  1169. L"D:P(A;CIOI;GA;;;CO)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
  1170. &pSD,
  1171. &SDsize,
  1172. &SeInfo
  1173. );
  1174. if ( rc != NO_ERROR )
  1175. ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, DatabaseName );
  1176. ScepChangeAclRevision(pSD, ACL_REVISION);
  1177. ScepCreateDirectory(
  1178. DatabaseName,
  1179. FALSE, // a file name
  1180. pSD // take parent's security setting
  1181. );
  1182. if ( pSD )
  1183. ScepFree(pSD);
  1184. }
  1185. //
  1186. // close the database
  1187. //
  1188. SceJetCloseFile( hProfile, FALSE, FALSE );
  1189. rc = SceJetConvertInfToJet(
  1190. InfFileName,
  1191. (LPSTR)FileName,
  1192. DbFlag,
  1193. bAdminLogon ?
  1194. AnalyzeOptions :
  1195. (AnalyzeOptions & ~SCE_SYSTEM_DB),
  1196. Area
  1197. );
  1198. if ( rc != SCESTATUS_SUCCESS ) {
  1199. goto Leave;
  1200. }
  1201. rc = SceJetOpenFile(
  1202. (LPSTR)FileName,
  1203. (AnalyzeOptions & SCE_GENERATE_ROLLBACK) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
  1204. 0,
  1205. &hProfile
  1206. );
  1207. if ( rc == SCESTATUS_SUCCESS ) {
  1208. rc = ScepRegSetValue(
  1209. bAdminLogon ?
  1210. HKEY_LOCAL_MACHINE : hCurrentUser,
  1211. SCE_ROOT_PATH,
  1212. L"TemplateUsed",
  1213. REG_SZ,
  1214. (BYTE *)InfFileName,
  1215. SCPLen*sizeof(WCHAR)
  1216. );
  1217. if ( rc != NO_ERROR ) // Win32 error code
  1218. ScepLogOutput3(1, rc, SCEDLL_ERROR_SAVE_REGISTRY, L"TemplateUsed");
  1219. rc = SCESTATUS_SUCCESS;
  1220. }
  1221. }
  1222. if ( rc != SCESTATUS_SUCCESS ) {
  1223. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1224. SCEDLL_ERROR_OPEN, DatabaseName);
  1225. goto Leave;
  1226. }
  1227. }
  1228. rc = ScepRegSetValue(
  1229. bAdminLogon ? HKEY_LOCAL_MACHINE : hCurrentUser,
  1230. SCE_ROOT_PATH,
  1231. L"LastUsedDatabase",
  1232. REG_SZ,
  1233. (BYTE *)DatabaseName,
  1234. DefLen*sizeof(WCHAR)
  1235. );
  1236. if ( rc != NO_ERROR )
  1237. ScepLogOutput3(1, rc, SCEDLL_ERROR_SAVE_REGISTRY, L"LastUsedDatabase");
  1238. //
  1239. // query the total ticks of this analysis
  1240. //
  1241. rc = ScepGetTotalTicks(
  1242. NULL,
  1243. hProfile,
  1244. Area,
  1245. SCE_FLAG_ANALYZE,
  1246. &gTotalTicks
  1247. );
  1248. if ( SCESTATUS_SUCCESS != rc &&
  1249. SCESTATUS_RECORD_NOT_FOUND != rc ) {
  1250. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1251. SCEDLL_TOTAL_TICKS_ERROR);
  1252. }
  1253. gTotalTicks += (4*TICKS_MIGRATION_SECTION+TICKS_MIGRATION_V11);
  1254. //
  1255. // start a new SAP table.
  1256. // Note here the backup SAP is controlled by the transaction
  1257. //
  1258. /* // Maximal version store is 64K by default.
  1259. rc = SceJetStartTransaction( hProfile );
  1260. if ( rc != SCESTATUS_SUCCESS ) {
  1261. ScepLogOutput2(0, 0, L"Cannot start a transaction");
  1262. goto Leave;
  1263. }
  1264. */
  1265. gOptions = AnalyzeOptions;
  1266. if ( !(AnalyzeOptions & SCE_NO_ANALYZE) &&
  1267. !(AnalyzeOptions & SCE_GENERATE_ROLLBACK) ) {
  1268. rc = SceJetDeleteTable( hProfile, "SmTblSap", SCEJET_TABLE_SAP );
  1269. if ( SCESTATUS_ACCESS_DENIED != rc ) {
  1270. rc = SceJetCreateTable(
  1271. hProfile,
  1272. "SmTblSap",
  1273. SCEJET_TABLE_SAP,
  1274. SCEJET_CREATE_IN_BUFFER,
  1275. NULL,
  1276. NULL
  1277. );
  1278. }
  1279. if ( rc != SCESTATUS_SUCCESS ) {
  1280. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1281. SCEDLL_ERROR_CREATE, L"SAP.");
  1282. goto Leave;
  1283. }
  1284. }
  1285. ScepIsDomainLocal(NULL);
  1286. Leave:
  1287. if ( hCurrentUser && hCurrentUser != HKEY_CURRENT_USER ) {
  1288. RegCloseKey(hCurrentUser);
  1289. }
  1290. if ( FileName ) {
  1291. ScepFree(FileName);
  1292. }
  1293. return(rc);
  1294. }
  1295. SCESTATUS
  1296. ScepMigrateLocalTableToTattooTable(
  1297. IN PSCECONTEXT hProfile
  1298. )
  1299. /*
  1300. Copy settings from local policy table to tattoo policy table
  1301. if the settings exist in effective table.
  1302. on domain controllers, privileges are not migrated because we do not
  1303. want to handle the tattoo problem for domain controllers.
  1304. hProfile is opened with tattoo table.
  1305. */
  1306. {
  1307. //
  1308. // delete old registry values from SMP table (because they are
  1309. // moved to new location). Don't care error
  1310. //
  1311. ScepDeleteOldRegValuesFromTable( hProfile, SCE_ENGINE_SMP );
  1312. ScepDeleteOldRegValuesFromTable( hProfile, SCE_ENGINE_SCP );
  1313. SCESTATUS rc=SCESTATUS_SUCCESS;
  1314. //
  1315. // now move the table
  1316. //
  1317. PSCE_ERROR_LOG_INFO Errlog=NULL;
  1318. rc = ScepCopyLocalToMergeTable(hProfile, 0,
  1319. SCE_LOCAL_POLICY_MIGRATE |
  1320. ((ProductType == NtProductLanManNt) ? SCE_LOCAL_POLICY_DC : 0),
  1321. &Errlog );
  1322. ScepLogWriteError( Errlog,1 );
  1323. ScepFreeErrorLog( Errlog );
  1324. Errlog = NULL;
  1325. if ( rc != SCESTATUS_SUCCESS )
  1326. ScepLogOutput2(1,ScepSceStatusToDosError(rc),L"Error occurred in migration");
  1327. return(rc);
  1328. }
  1329. SCESTATUS
  1330. ScepAnalyzeSystemAccess(
  1331. IN OUT PSCE_PROFILE_INFO pSmpInfo,
  1332. IN PSCE_PROFILE_INFO pScpInfo OPTIONAL,
  1333. IN DWORD dwSaveOption,
  1334. OUT BOOL *pbChanged,
  1335. IN OUT PSCE_ERROR_LOG_INFO *pErrLog
  1336. )
  1337. /* ++
  1338. Routine Description:
  1339. This routine analyzies the system security in the area of system access
  1340. which includes account policy, rename admin/guest accounts, and some
  1341. registry values.
  1342. Arguments:
  1343. pSmpInfo - The buffer which contains SMP information to compare with
  1344. If dwSaveOption is set to non zero, the difference is saved
  1345. in this buffer to output
  1346. pScpInfo - If dwSaveOption is set to non zero, pScpInfo may be present to
  1347. be used (as effective policy) to compare with
  1348. dwSaveOption - used by policy filter when to query policy difference
  1349. SCEPOL_SYSTEM_SETTINGS - query for system setting mode
  1350. SCEPOL_SAVE_DB - policy filter for local database
  1351. SCEPOL_SAVE_BUFFER - policy filter for GPO mode (DC)
  1352. 0 - analyze mode
  1353. pbChanged - TRUE if there is any policy changed
  1354. Return value:
  1355. SCESTATUS_SUCCESS
  1356. SCESTATUS_NOT_ENOUGH_RESOURCE
  1357. SCESTATUS_INVALID_PARAMETER
  1358. -- */
  1359. {
  1360. SCESTATUS rc=SCESTATUS_SUCCESS;
  1361. SCESTATUS saveRc=rc;
  1362. NTSTATUS NtStatus;
  1363. SAM_HANDLE DomainHandle=NULL,
  1364. ServerHandle=NULL,
  1365. UserHandle1=NULL;
  1366. PSID DomainSid=NULL;
  1367. PVOID Buffer=NULL;
  1368. DWORD BaseVal;
  1369. PWSTR RegBuf=NULL;
  1370. DWORD CurrentVal;
  1371. BOOL ToRename=FALSE;
  1372. DWORD dwAllow = 0;
  1373. DWORD AccessValues[MAX_ACCESS_ITEMS];
  1374. for ( CurrentVal=0; CurrentVal<MAX_ACCESS_ITEMS; CurrentVal++ ) {
  1375. AccessValues[CurrentVal] = SCE_ERROR_VALUE;
  1376. }
  1377. if ( dwSaveOption &&
  1378. !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) &&
  1379. (pbChanged == NULL) ) {
  1380. return(SCESTATUS_INVALID_PARAMETER);
  1381. }
  1382. //
  1383. // Open account domain
  1384. //
  1385. NtStatus = ScepOpenSamDomain(
  1386. SAM_SERVER_READ | SAM_SERVER_EXECUTE,
  1387. DOMAIN_READ | DOMAIN_EXECUTE,
  1388. &ServerHandle,
  1389. &DomainHandle,
  1390. &DomainSid,
  1391. NULL,
  1392. NULL
  1393. );
  1394. rc = RtlNtStatusToDosError( NtStatus );
  1395. if (!NT_SUCCESS(NtStatus)) {
  1396. if ( !(gOptions & SCE_NO_ANALYZE) && ( ERROR_NO_SUCH_DOMAIN == rc ) ) {
  1397. ScepLogOutput3(1, 0, IDS_NO_ANALYSIS_FRESH);
  1398. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  1399. } else {
  1400. if ( pErrLog ) {
  1401. ScepBuildErrorLogInfo(
  1402. rc,
  1403. pErrLog,
  1404. SCEDLL_ACCOUNT_DOMAIN
  1405. );
  1406. }
  1407. ScepLogOutput3(1, rc, SCEDLL_ACCOUNT_DOMAIN);
  1408. return( ScepDosErrorToSceStatus(rc) );
  1409. }
  1410. }
  1411. PSCE_PROFILE_INFO pTmpInfo=pSmpInfo;
  1412. if ( !dwSaveOption ) {
  1413. //
  1414. // Prepare a new section
  1415. //
  1416. BOOL bSaveSnapshot = FALSE;
  1417. if ( (gOptions & SCE_NO_ANALYZE) ||
  1418. (gOptions & SCE_GENERATE_ROLLBACK ) ) {
  1419. bSaveSnapshot = TRUE;
  1420. }
  1421. rc = ScepStartANewSection(
  1422. hProfile,
  1423. &hSection,
  1424. bSaveSnapshot ? SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  1425. szSystemAccess
  1426. );
  1427. if ( rc != SCESTATUS_SUCCESS ) {
  1428. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1429. SCEDLL_SAP_START_SECTION, (PWSTR)szSystemAccess);
  1430. goto GETOUT;
  1431. }
  1432. } else if ( pScpInfo ) {
  1433. //
  1434. // if saved in buffer (policy filter), should compare with effective
  1435. // policy to determine if anything changed
  1436. //
  1437. pTmpInfo = pScpInfo;
  1438. }
  1439. //
  1440. // Get the current password settings...
  1441. //
  1442. Buffer=NULL;
  1443. NtStatus = SamQueryInformationDomain(
  1444. DomainHandle,
  1445. DomainPasswordInformation,
  1446. &Buffer
  1447. );
  1448. rc = RtlNtStatusToDosError( NtStatus );
  1449. if ( NT_SUCCESS(NtStatus) ) {
  1450. rc = SCESTATUS_SUCCESS;
  1451. CurrentVal = ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength;
  1452. BaseVal = pTmpInfo->MinimumPasswordLength;
  1453. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1454. pSmpInfo->MinimumPasswordLength = CurrentVal;
  1455. } else if ( dwSaveOption ) {
  1456. if ( ( CurrentVal != BaseVal ) &&
  1457. ( BaseVal != SCE_NO_VALUE) ) {
  1458. pSmpInfo->MinimumPasswordLength = CurrentVal;
  1459. *pbChanged = TRUE;
  1460. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1461. //
  1462. // turn this item off to indicate this one is not changed
  1463. //
  1464. pSmpInfo->MinimumPasswordLength = SCE_NO_VALUE;
  1465. }
  1466. } else {
  1467. rc = ScepCompareAndSaveIntValue(
  1468. hSection,
  1469. L"MinimumPasswordLength",
  1470. (gOptions & SCE_GENERATE_ROLLBACK),
  1471. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1472. CurrentVal);
  1473. if ( rc == SCESTATUS_SUCCESS &&
  1474. !(gOptions & SCE_NO_ANALYZE) ) {
  1475. AccessValues[IDX_MIN_PASS_LEN] = CurrentVal;
  1476. }
  1477. }
  1478. if ( rc == SCESTATUS_SUCCESS ) {
  1479. CurrentVal = ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength;
  1480. BaseVal = pTmpInfo->PasswordHistorySize;
  1481. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1482. pSmpInfo->PasswordHistorySize = CurrentVal;
  1483. } else if ( dwSaveOption ) {
  1484. if ( ( CurrentVal != BaseVal ) &&
  1485. ( BaseVal != SCE_NO_VALUE) ) {
  1486. pSmpInfo->PasswordHistorySize = CurrentVal;
  1487. *pbChanged = TRUE;
  1488. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1489. //
  1490. // turn this item off to indicate this one is not changed
  1491. //
  1492. pSmpInfo->PasswordHistorySize = SCE_NO_VALUE;
  1493. }
  1494. } else {
  1495. rc = ScepCompareAndSaveIntValue(
  1496. hSection,
  1497. L"PasswordHistorySize",
  1498. (gOptions & SCE_GENERATE_ROLLBACK),
  1499. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1500. CurrentVal
  1501. );
  1502. if ( rc == SCESTATUS_SUCCESS &&
  1503. !(gOptions & SCE_NO_ANALYZE) ) {
  1504. AccessValues[IDX_PASS_HISTORY] = CurrentVal;
  1505. }
  1506. }
  1507. if ( rc == SCESTATUS_SUCCESS ) {
  1508. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  1509. (pTmpInfo->MaximumPasswordAge == SCE_NO_VALUE) &&
  1510. (pTmpInfo->MinimumPasswordAge == SCE_NO_VALUE) ) {
  1511. //
  1512. // generate rollback template. These two are not defined
  1513. // no need to query/compare
  1514. //
  1515. } else {
  1516. if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.HighPart == MINLONG &&
  1517. ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.LowPart == 0 ) {
  1518. //
  1519. // Maximum password age value is MINLONG,0
  1520. //
  1521. CurrentVal = SCE_FOREVER_VALUE;
  1522. } else {
  1523. CurrentVal = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart /
  1524. (LONGLONG)(10000000L)) );
  1525. CurrentVal /= 3600;
  1526. CurrentVal /= 24;
  1527. }
  1528. BaseVal = pTmpInfo->MaximumPasswordAge;
  1529. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1530. pSmpInfo->MaximumPasswordAge = CurrentVal;
  1531. } else if ( dwSaveOption ) {
  1532. if ( ( CurrentVal != BaseVal ) &&
  1533. ( BaseVal != SCE_NO_VALUE) ) {
  1534. pSmpInfo->MaximumPasswordAge = CurrentVal;
  1535. *pbChanged = TRUE;
  1536. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1537. //
  1538. // turn this item off to indicate this one is not changed
  1539. //
  1540. pSmpInfo->MaximumPasswordAge = SCE_NO_VALUE;
  1541. }
  1542. } else {
  1543. rc = ScepCompareAndSaveIntValue(
  1544. hSection,
  1545. L"MaximumPasswordAge",
  1546. FALSE,
  1547. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1548. CurrentVal);
  1549. if ( rc == SCESTATUS_SUCCESS &&
  1550. !(gOptions & SCE_NO_ANALYZE) ) {
  1551. AccessValues[IDX_MAX_PASS_AGE] = CurrentVal;
  1552. }
  1553. }
  1554. if ( rc == SCESTATUS_SUCCESS ) {
  1555. CurrentVal = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordAge.QuadPart /
  1556. (LONGLONG)(10000000L)) );
  1557. CurrentVal /= 3600;
  1558. CurrentVal /= 24;
  1559. BaseVal = pTmpInfo->MinimumPasswordAge;
  1560. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1561. pSmpInfo->MinimumPasswordAge = CurrentVal;
  1562. } else if ( dwSaveOption ) {
  1563. if ( ( CurrentVal != BaseVal ) &&
  1564. ( BaseVal != SCE_NO_VALUE) ) {
  1565. pSmpInfo->MinimumPasswordAge = CurrentVal;
  1566. *pbChanged = TRUE;
  1567. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1568. //
  1569. // turn this item off to indicate this one is not changed
  1570. //
  1571. pSmpInfo->MinimumPasswordAge = SCE_NO_VALUE;
  1572. }
  1573. } else {
  1574. rc = ScepCompareAndSaveIntValue(
  1575. hSection,
  1576. L"MinimumPasswordAge",
  1577. FALSE,
  1578. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1579. CurrentVal);
  1580. if ( rc == SCESTATUS_SUCCESS &&
  1581. !(gOptions & SCE_NO_ANALYZE) ) {
  1582. AccessValues[IDX_MIN_PASS_AGE] = CurrentVal;
  1583. }
  1584. }
  1585. }
  1586. }
  1587. if ( rc == SCESTATUS_SUCCESS ) {
  1588. //
  1589. // Password Complexity
  1590. //
  1591. if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &
  1592. DOMAIN_PASSWORD_COMPLEX )
  1593. CurrentVal = 1;
  1594. else
  1595. CurrentVal = 0;
  1596. BaseVal = pTmpInfo->PasswordComplexity;
  1597. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1598. pSmpInfo->PasswordComplexity = CurrentVal;
  1599. } else if ( dwSaveOption ) {
  1600. if ( ( CurrentVal != BaseVal ) &&
  1601. ( BaseVal != SCE_NO_VALUE) ) {
  1602. pSmpInfo->PasswordComplexity = CurrentVal;
  1603. *pbChanged = TRUE;
  1604. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1605. //
  1606. // turn this item off to indicate this one is not changed
  1607. //
  1608. pSmpInfo->PasswordComplexity = SCE_NO_VALUE;
  1609. }
  1610. } else {
  1611. rc = ScepCompareAndSaveIntValue(
  1612. hSection,
  1613. L"PasswordComplexity",
  1614. (gOptions & SCE_GENERATE_ROLLBACK),
  1615. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1616. CurrentVal);
  1617. if ( rc == SCESTATUS_SUCCESS &&
  1618. !(gOptions & SCE_NO_ANALYZE) ) {
  1619. AccessValues[IDX_PASS_COMPLEX] = CurrentVal;
  1620. }
  1621. }
  1622. if ( rc == SCESTATUS_SUCCESS ) {
  1623. //
  1624. // RequireLogonToChangePassword
  1625. //
  1626. if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &
  1627. DOMAIN_PASSWORD_NO_ANON_CHANGE )
  1628. CurrentVal = 1;
  1629. else
  1630. CurrentVal = 0;
  1631. BaseVal = pTmpInfo->RequireLogonToChangePassword;
  1632. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1633. pSmpInfo->RequireLogonToChangePassword = CurrentVal;
  1634. } else if ( dwSaveOption ) {
  1635. if ( ( CurrentVal != BaseVal ) &&
  1636. ( BaseVal != SCE_NO_VALUE) ) {
  1637. pSmpInfo->RequireLogonToChangePassword = CurrentVal;
  1638. *pbChanged = TRUE;
  1639. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1640. //
  1641. // turn this item off to indicate this one is not changed
  1642. //
  1643. pSmpInfo->RequireLogonToChangePassword = SCE_NO_VALUE;
  1644. }
  1645. } else {
  1646. rc = ScepCompareAndSaveIntValue(
  1647. hSection,
  1648. L"RequireLogonToChangePassword",
  1649. (gOptions & SCE_GENERATE_ROLLBACK),
  1650. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1651. CurrentVal);
  1652. if ( rc == SCESTATUS_SUCCESS &&
  1653. !(gOptions & SCE_NO_ANALYZE) ) {
  1654. AccessValues[IDX_CHANGE_PASS] = CurrentVal;
  1655. }
  1656. }
  1657. #if _WIN32_WINNT>=0x0500
  1658. if ( rc == SCESTATUS_SUCCESS ) {
  1659. //
  1660. // Clear Text Password
  1661. //
  1662. CurrentVal = 0;
  1663. if ( ( (ProductType == NtProductLanManNt) ||
  1664. (ProductType == NtProductServer ) ) &&
  1665. (gOptions & SCE_NO_ANALYZE) ) {
  1666. //
  1667. // NT4 DC upgrade, check the registry value
  1668. //
  1669. CurrentVal = 0;
  1670. rc = ScepRegQueryIntValue(
  1671. HKEY_LOCAL_MACHINE,
  1672. L"System\\CurrentControlSet\\Control\\Lsa\\MD5-CHAP",
  1673. L"Store Cleartext Passwords",
  1674. &CurrentVal
  1675. );
  1676. if ( rc != SCESTATUS_SUCCESS ) {
  1677. CurrentVal = 0;
  1678. rc = SCESTATUS_SUCCESS;
  1679. }
  1680. }
  1681. if ( CurrentVal == 0 ) {
  1682. // if not NT4 DC upgrade, or clear text password disabled on NT4
  1683. if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &
  1684. DOMAIN_PASSWORD_STORE_CLEARTEXT ) {
  1685. CurrentVal = 1;
  1686. } else {
  1687. CurrentVal = 0;
  1688. }
  1689. }
  1690. BaseVal = pTmpInfo->ClearTextPassword;
  1691. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1692. pSmpInfo->ClearTextPassword = CurrentVal;
  1693. } else if ( dwSaveOption ) {
  1694. if ( ( CurrentVal != BaseVal ) &&
  1695. ( BaseVal != SCE_NO_VALUE) ) {
  1696. pSmpInfo->ClearTextPassword = CurrentVal;
  1697. *pbChanged = TRUE;
  1698. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1699. //
  1700. // turn this item off to indicate this one is not changed
  1701. //
  1702. pSmpInfo->ClearTextPassword = SCE_NO_VALUE;
  1703. }
  1704. } else {
  1705. rc = ScepCompareAndSaveIntValue(
  1706. hSection,
  1707. L"ClearTextPassword",
  1708. (gOptions & SCE_GENERATE_ROLLBACK),
  1709. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1710. CurrentVal);
  1711. if ( rc == SCESTATUS_SUCCESS &&
  1712. !(gOptions & SCE_NO_ANALYZE) ) {
  1713. AccessValues[IDX_CLEAR_PASS] = CurrentVal;
  1714. }
  1715. }
  1716. }
  1717. #else
  1718. AccessValues[IDX_CLEAR_PASS] = 1;
  1719. #endif
  1720. }
  1721. }
  1722. }
  1723. }
  1724. SamFreeMemory(Buffer);
  1725. if ( rc != SCESTATUS_SUCCESS ) {
  1726. saveRc = rc;
  1727. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1728. SCEDLL_SAP_ERROR_PASSWORD);
  1729. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  1730. //
  1731. // if it's not getting system setting, quit on error
  1732. //
  1733. goto GETOUT;
  1734. }
  1735. } else
  1736. ScepLogOutput3(1, 0, SCEDLL_SAP_PASSWORD );
  1737. } else {
  1738. saveRc = ScepDosErrorToSceStatus(rc);
  1739. ScepLogOutput3(1,rc, SCEDLL_ERROR_QUERY_PASSWORD); // ntstatus
  1740. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  1741. //
  1742. // if it's not getting system setting, quit on error
  1743. //
  1744. goto GETOUT;
  1745. }
  1746. }
  1747. if ( pErrLog && (saveRc != SCESTATUS_SUCCESS) ) {
  1748. //
  1749. // password policy failed.
  1750. //
  1751. ScepBuildErrorLogInfo(
  1752. ScepSceStatusToDosError(saveRc),
  1753. pErrLog,
  1754. SCEDLL_ERROR_QUERY_PASSWORD
  1755. );
  1756. }
  1757. //
  1758. // Analyze Lockout information
  1759. //
  1760. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  1761. (pTmpInfo->LockoutBadCount == SCE_NO_VALUE) &&
  1762. (pTmpInfo->ResetLockoutCount == SCE_NO_VALUE) &&
  1763. (pTmpInfo->LockoutDuration == SCE_NO_VALUE) ) {
  1764. rc = NtStatus = STATUS_SUCCESS;
  1765. } else {
  1766. Buffer = NULL;
  1767. NtStatus = SamQueryInformationDomain(
  1768. DomainHandle,
  1769. DomainLockoutInformation,
  1770. &Buffer
  1771. );
  1772. rc = RtlNtStatusToDosError( NtStatus );
  1773. if ( NT_SUCCESS(NtStatus) ) {
  1774. rc = SCESTATUS_SUCCESS;
  1775. CurrentVal = ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold;
  1776. BaseVal = pTmpInfo->LockoutBadCount;
  1777. DWORD dwLockOut = BaseVal;
  1778. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1779. //
  1780. // system setting
  1781. //
  1782. pSmpInfo->LockoutBadCount = CurrentVal;
  1783. } else if ( dwSaveOption ) {
  1784. //
  1785. // policy filter mode
  1786. //
  1787. if ( CurrentVal != BaseVal &&
  1788. BaseVal != SCE_NO_VALUE ) {
  1789. pSmpInfo->LockoutBadCount = CurrentVal;
  1790. *pbChanged = TRUE;
  1791. if ( CurrentVal == 0 ) {
  1792. //
  1793. // if no lockout is allowed,
  1794. // make sure to delete the entries below
  1795. //
  1796. pSmpInfo->ResetLockoutCount = SCE_NO_VALUE;
  1797. pSmpInfo->LockoutDuration = SCE_NO_VALUE;
  1798. }
  1799. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1800. //
  1801. // turn this item off to indicate this one is not changed
  1802. //
  1803. pSmpInfo->LockoutBadCount = SCE_NO_VALUE;
  1804. }
  1805. } else {
  1806. //
  1807. // analyze
  1808. //
  1809. rc = ScepCompareAndSaveIntValue(
  1810. hSection,
  1811. L"LockoutBadCount",
  1812. FALSE,
  1813. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1814. CurrentVal);
  1815. if ( rc == SCESTATUS_SUCCESS &&
  1816. !(gOptions & SCE_NO_ANALYZE) ) {
  1817. AccessValues[IDX_LOCK_COUNT] = CurrentVal;
  1818. }
  1819. }
  1820. if ( rc == SCESTATUS_SUCCESS &&
  1821. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold > 0 ) {
  1822. CurrentVal = (DWORD) (-1 * ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutObservationWindow.QuadPart /
  1823. (60 * 10000000L) );
  1824. BaseVal = pTmpInfo->ResetLockoutCount;
  1825. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1826. pSmpInfo->ResetLockoutCount = CurrentVal;
  1827. } else if ( dwSaveOption ) {
  1828. //
  1829. // if this setting is defined or LockoutBadCount is defined
  1830. // filter this value
  1831. //
  1832. if ( CurrentVal != BaseVal &&
  1833. (BaseVal != SCE_NO_VALUE || dwLockOut != SCE_NO_VALUE) ) {
  1834. pSmpInfo->ResetLockoutCount = CurrentVal;
  1835. *pbChanged = TRUE;
  1836. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1837. //
  1838. // turn this item off to indicate this one is not changed
  1839. //
  1840. pSmpInfo->ResetLockoutCount = SCE_NO_VALUE;
  1841. }
  1842. } else {
  1843. rc = ScepCompareAndSaveIntValue(
  1844. hSection,
  1845. L"ResetLockoutCount",
  1846. FALSE,
  1847. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1848. CurrentVal);
  1849. if ( rc == SCESTATUS_SUCCESS &&
  1850. !(gOptions & SCE_NO_ANALYZE) ) {
  1851. AccessValues[IDX_RESET_COUNT] = CurrentVal;
  1852. }
  1853. }
  1854. if ( rc == SCESTATUS_SUCCESS ) {
  1855. if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.HighPart == MINLONG &&
  1856. ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.LowPart == 0 ) {
  1857. //
  1858. // forever
  1859. //
  1860. CurrentVal = SCE_FOREVER_VALUE;
  1861. } else
  1862. CurrentVal = (DWORD)(-1 * ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.QuadPart /
  1863. (60 * 10000000L) );
  1864. BaseVal = pTmpInfo->LockoutDuration;
  1865. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1866. pSmpInfo->LockoutDuration = CurrentVal;
  1867. } else if ( dwSaveOption ) {
  1868. //
  1869. // if this setting is defined or LockoutBadCount is defined
  1870. // filter this value
  1871. //
  1872. if ( CurrentVal != BaseVal &&
  1873. (BaseVal != SCE_NO_VALUE || dwLockOut != SCE_NO_VALUE) ) {
  1874. pSmpInfo->LockoutDuration = CurrentVal;
  1875. *pbChanged = TRUE;
  1876. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1877. //
  1878. // turn this item off to indicate this one is not changed
  1879. //
  1880. pSmpInfo->LockoutDuration = SCE_NO_VALUE;
  1881. }
  1882. } else {
  1883. rc = ScepCompareAndSaveIntValue(
  1884. hSection,
  1885. L"LockoutDuration",
  1886. FALSE,
  1887. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1888. CurrentVal);
  1889. if ( rc == SCESTATUS_SUCCESS &&
  1890. !(gOptions & SCE_NO_ANALYZE) ) {
  1891. AccessValues[IDX_LOCK_DURATION] = CurrentVal;
  1892. }
  1893. }
  1894. }
  1895. } else {
  1896. AccessValues[IDX_RESET_COUNT] = SCE_NOT_ANALYZED_VALUE;
  1897. AccessValues[IDX_LOCK_DURATION] = SCE_NOT_ANALYZED_VALUE;
  1898. }
  1899. SamFreeMemory(Buffer);
  1900. if ( rc != SCESTATUS_SUCCESS ) {
  1901. saveRc = rc;
  1902. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1903. SCEDLL_SAP_ERROR_LOCKOUT);
  1904. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  1905. goto GETOUT;
  1906. }
  1907. } else
  1908. ScepLogOutput3(1, 0, SCEDLL_SAP_LOCKOUT );
  1909. } else {
  1910. saveRc = ScepDosErrorToSceStatus(rc);
  1911. ScepLogOutput3(1,rc, SCEDLL_ERROR_QUERY_LOCKOUT); // ntstatus
  1912. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  1913. goto GETOUT;
  1914. }
  1915. }
  1916. if ( pErrLog && ( rc != NO_ERROR) ) {
  1917. //
  1918. // account lockout policy failed.
  1919. //
  1920. ScepBuildErrorLogInfo(
  1921. ScepSceStatusToDosError(saveRc),
  1922. pErrLog,
  1923. SCEDLL_ERROR_QUERY_LOCKOUT
  1924. );
  1925. }
  1926. }
  1927. //
  1928. // Force Logoff when hour expire - (on non-DCs too)
  1929. //
  1930. Buffer = NULL;
  1931. NtStatus = SamQueryInformationDomain(
  1932. DomainHandle,
  1933. DomainLogoffInformation,
  1934. &Buffer
  1935. );
  1936. rc = RtlNtStatusToDosError( NtStatus );
  1937. if ( NT_SUCCESS(NtStatus) ) {
  1938. rc = SCESTATUS_SUCCESS;
  1939. if ( ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart == 0 &&
  1940. ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart == 0 ) {
  1941. // yes
  1942. CurrentVal = 1;
  1943. } else
  1944. CurrentVal = 0;
  1945. BaseVal = pTmpInfo->ForceLogoffWhenHourExpire;
  1946. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  1947. pSmpInfo->ForceLogoffWhenHourExpire = CurrentVal;
  1948. } else if ( dwSaveOption ) {
  1949. if ( ( CurrentVal != BaseVal ) &&
  1950. ( BaseVal != SCE_NO_VALUE) ) {
  1951. pSmpInfo->ForceLogoffWhenHourExpire = CurrentVal;
  1952. *pbChanged = TRUE;
  1953. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  1954. //
  1955. // turn this item off to indicate this one is not changed
  1956. //
  1957. pSmpInfo->ForceLogoffWhenHourExpire = SCE_NO_VALUE;
  1958. }
  1959. } else {
  1960. rc = ScepCompareAndSaveIntValue(
  1961. hSection,
  1962. L"ForceLogOffWhenHourExpire",
  1963. (gOptions & SCE_GENERATE_ROLLBACK),
  1964. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  1965. CurrentVal);
  1966. if ( rc == SCESTATUS_SUCCESS &&
  1967. !(gOptions & SCE_NO_ANALYZE) ) {
  1968. AccessValues[IDX_FORCE_LOGOFF] = CurrentVal;
  1969. }
  1970. }
  1971. SamFreeMemory(Buffer);
  1972. if ( rc != SCESTATUS_SUCCESS ) {
  1973. saveRc = rc;
  1974. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1975. SCEDLL_SAP_ERROR_LOGOFF);
  1976. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  1977. goto GETOUT;
  1978. }
  1979. } else
  1980. ScepLogOutput3(1, 0, SCEDLL_SAP_LOGOFF );
  1981. } else {
  1982. saveRc = ScepDosErrorToSceStatus(rc);
  1983. ScepLogOutput3(1,rc, SCEDLL_ERROR_QUERY_LOGOFF); // ntstatus
  1984. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  1985. goto GETOUT;
  1986. }
  1987. }
  1988. if ( pErrLog && (rc != NO_ERROR) ) {
  1989. //
  1990. // force logoff failed.
  1991. //
  1992. ScepBuildErrorLogInfo(
  1993. ScepSceStatusToDosError(saveRc),
  1994. pErrLog,
  1995. SCEDLL_ERROR_QUERY_LOGOFF
  1996. );
  1997. }
  1998. //
  1999. // Check if Administrator/Guest accounts need to be renamed
  2000. //
  2001. if ( (dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ||
  2002. (!(gOptions & SCE_NO_ANALYZE) && (dwSaveOption == 0)) ) {
  2003. RegBuf=NULL;
  2004. CurrentVal=0;
  2005. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  2006. (pSmpInfo->NewAdministratorName == NULL ) ) {
  2007. NtStatus = STATUS_SUCCESS;
  2008. ToRename = FALSE;
  2009. } else {
  2010. NtStatus = ScepAdminGuestAccountsToManage(
  2011. DomainHandle,
  2012. SCE_RENAME_ADMIN,
  2013. pSmpInfo->NewAdministratorName,
  2014. &ToRename,
  2015. &RegBuf,
  2016. &CurrentVal
  2017. );
  2018. }
  2019. rc = RtlNtStatusToDosError(NtStatus);
  2020. if ( NT_SUCCESS( NtStatus ) ) {
  2021. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  2022. pSmpInfo->NewAdministratorName = RegBuf;
  2023. } else {
  2024. if ( ToRename ) {
  2025. rc = ScepCompareAndSaveStringValue(
  2026. hSection,
  2027. L"NewAdministratorName",
  2028. pSmpInfo->NewAdministratorName,
  2029. RegBuf,
  2030. CurrentVal*sizeof(WCHAR)
  2031. );
  2032. rc = ScepSceStatusToDosError(rc);
  2033. }
  2034. ScepFree(RegBuf);
  2035. }
  2036. RegBuf=NULL;
  2037. } else if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) &&
  2038. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2039. //
  2040. // raise this one
  2041. //
  2042. ScepRaiseErrorString(
  2043. hSection,
  2044. L"NewAdministratorName",
  2045. NULL
  2046. );
  2047. }
  2048. if ( rc != NO_ERROR ) {
  2049. saveRc = ScepDosErrorToSceStatus(rc);
  2050. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  2051. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ADMINISTRATOR);
  2052. goto GETOUT;
  2053. } else if ( pErrLog ) {
  2054. //
  2055. // account name failed.
  2056. //
  2057. ScepBuildErrorLogInfo(
  2058. rc,
  2059. pErrLog,
  2060. SCEDLL_SAP_ERROR_ADMINISTRATOR
  2061. );
  2062. }
  2063. }
  2064. RegBuf=NULL;
  2065. CurrentVal=0;
  2066. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  2067. (pSmpInfo->NewGuestName == NULL ) ) {
  2068. NtStatus = STATUS_SUCCESS;
  2069. ToRename = FALSE;
  2070. } else {
  2071. NtStatus = ScepAdminGuestAccountsToManage(
  2072. DomainHandle,
  2073. SCE_RENAME_GUEST,
  2074. pSmpInfo->NewGuestName,
  2075. &ToRename,
  2076. &RegBuf,
  2077. &CurrentVal
  2078. );
  2079. }
  2080. rc = RtlNtStatusToDosError(NtStatus);
  2081. if ( NT_SUCCESS( NtStatus ) ) {
  2082. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  2083. pSmpInfo->NewGuestName = RegBuf;
  2084. } else {
  2085. if ( ToRename ) {
  2086. rc = ScepCompareAndSaveStringValue(
  2087. hSection,
  2088. L"NewGuestName",
  2089. pSmpInfo->NewGuestName,
  2090. RegBuf,
  2091. CurrentVal*sizeof(WCHAR)
  2092. );
  2093. rc = ScepSceStatusToDosError(rc);
  2094. }
  2095. ScepFree(RegBuf);
  2096. }
  2097. RegBuf=NULL;
  2098. } else if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) &&
  2099. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2100. //
  2101. // raise this one
  2102. //
  2103. ScepRaiseErrorString(
  2104. hSection,
  2105. L"NewGuestName",
  2106. NULL
  2107. );
  2108. }
  2109. if ( rc != NO_ERROR ) {
  2110. saveRc = ScepDosErrorToSceStatus(rc);
  2111. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS)) {
  2112. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_GUEST);
  2113. goto GETOUT;
  2114. } else if ( pErrLog ) {
  2115. //
  2116. // account name failed.
  2117. //
  2118. ScepBuildErrorLogInfo(
  2119. rc,
  2120. pErrLog,
  2121. SCEDLL_SAP_ERROR_GUEST
  2122. );
  2123. }
  2124. }
  2125. }
  2126. //
  2127. // Analyze LSA Anonymous Lookup information
  2128. //
  2129. rc = ScepGetLSAPolicyObjectInfo( &dwAllow );
  2130. if ( rc == ERROR_SUCCESS ) {
  2131. CurrentVal = dwAllow;
  2132. BaseVal = pTmpInfo->LSAAnonymousNameLookup;
  2133. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  2134. //
  2135. // system setting
  2136. //
  2137. pSmpInfo->LSAAnonymousNameLookup = CurrentVal;
  2138. } else if ( dwSaveOption ) {
  2139. //
  2140. // policy filter mode
  2141. //
  2142. // (this setting should not be filtered : bug #344311)
  2143. /*
  2144. if ( CurrentVal != BaseVal &&
  2145. BaseVal != SCE_NO_VALUE ) {
  2146. pSmpInfo->LSAAnonymousNameLookup = CurrentVal;
  2147. *pbChanged = TRUE;
  2148. } else if ( dwSaveOption & SCEPOL_SAVE_DB ) {
  2149. //
  2150. // turn this item off to indicate this one is not changed
  2151. //
  2152. pSmpInfo->LSAAnonymousNameLookup = SCE_NO_VALUE;
  2153. }
  2154. */
  2155. } else {
  2156. //
  2157. // analyze
  2158. //
  2159. rc = ScepCompareAndSaveIntValue(
  2160. hSection,
  2161. L"LSAAnonymousNameLookup",
  2162. (gOptions & SCE_GENERATE_ROLLBACK),
  2163. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : BaseVal,
  2164. CurrentVal);
  2165. if ( rc == SCESTATUS_SUCCESS && !(gOptions & SCE_NO_ANALYZE) ) {
  2166. AccessValues[IDX_LSA_ANON_LOOKUP] = CurrentVal;
  2167. }
  2168. }
  2169. if ( rc != SCESTATUS_SUCCESS ) {
  2170. saveRc = rc;
  2171. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  2172. SCEDLL_SAP_ERROR_LSA_ANON_LOOKUP);
  2173. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  2174. goto GETOUT;
  2175. }
  2176. } else
  2177. ScepLogOutput3(1, 0, SCEDLL_SAP_LSAPOLICY );
  2178. } else {
  2179. saveRc = ScepDosErrorToSceStatus(rc);
  2180. ScepLogOutput3(1,rc, SCEDLL_SAP_ERROR_LSA_ANON_LOOKUP);
  2181. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ) {
  2182. goto GETOUT;
  2183. }
  2184. }
  2185. if ( pErrLog && (rc != NO_ERROR) ) {
  2186. //
  2187. // lsa policy failed.
  2188. //
  2189. ScepBuildErrorLogInfo(
  2190. ScepSceStatusToDosError(saveRc),
  2191. pErrLog,
  2192. SCEDLL_SAP_ERROR_LSA_ANON_LOOKUP
  2193. );
  2194. }
  2195. //
  2196. // Admin/Guest accounts are not filtered (controlled by dwSaveOption flag)
  2197. //
  2198. if ( (dwSaveOption & SCEPOL_SYSTEM_SETTINGS) ||
  2199. (!(gOptions & SCE_NO_ANALYZE) && (dwSaveOption == 0)) ) {
  2200. //
  2201. // Analyze administrator account status
  2202. //
  2203. ToRename = FALSE;
  2204. NtStatus = ScepAdminGuestAccountsToManage(
  2205. DomainHandle,
  2206. SCE_DISABLE_ADMIN,
  2207. NULL,
  2208. &ToRename, // TRUE = disabled
  2209. NULL,
  2210. NULL
  2211. );
  2212. rc = RtlNtStatusToDosError(NtStatus);
  2213. if ( NT_SUCCESS( NtStatus ) ) {
  2214. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  2215. pSmpInfo->EnableAdminAccount = ToRename ? 0 : 1;
  2216. } else {
  2217. rc = ScepCompareAndSaveIntValue(
  2218. hSection,
  2219. L"EnableAdminAccount",
  2220. (gOptions & SCE_GENERATE_ROLLBACK),
  2221. pSmpInfo->EnableAdminAccount,
  2222. ToRename ? 0 : 1
  2223. );
  2224. if ( rc == SCESTATUS_SUCCESS && !(gOptions & SCE_NO_ANALYZE) ) {
  2225. AccessValues[IDX_ENABLE_ADMIN] = ToRename ? 0 : 1;
  2226. }
  2227. rc = ScepSceStatusToDosError(rc);
  2228. }
  2229. } else if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) &&
  2230. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2231. //
  2232. // raise this one
  2233. //
  2234. ScepRaiseErrorString(
  2235. hSection,
  2236. L"EnableAdminAccount",
  2237. NULL
  2238. );
  2239. }
  2240. if ( rc != NO_ERROR ) {
  2241. saveRc = ScepDosErrorToSceStatus(rc);
  2242. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS)) {
  2243. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_DISABLE_ADMIN);
  2244. goto GETOUT;
  2245. } else if ( pErrLog ) {
  2246. //
  2247. // account name failed.
  2248. //
  2249. ScepBuildErrorLogInfo(
  2250. rc,
  2251. pErrLog,
  2252. SCEDLL_SAP_ERROR_DISABLE_ADMIN
  2253. );
  2254. }
  2255. }
  2256. //
  2257. // Analyze administrator account status
  2258. //
  2259. ToRename = FALSE;
  2260. NtStatus = ScepAdminGuestAccountsToManage(
  2261. DomainHandle,
  2262. SCE_DISABLE_GUEST,
  2263. NULL,
  2264. &ToRename, // TRUE=disabled
  2265. NULL,
  2266. NULL
  2267. );
  2268. rc = RtlNtStatusToDosError(NtStatus);
  2269. if ( NT_SUCCESS( NtStatus ) ) {
  2270. if ( dwSaveOption & SCEPOL_SYSTEM_SETTINGS ) {
  2271. pSmpInfo->EnableGuestAccount = ToRename ? 0 : 1;
  2272. } else {
  2273. rc = ScepCompareAndSaveIntValue(
  2274. hSection,
  2275. L"EnableGuestAccount",
  2276. (gOptions & SCE_GENERATE_ROLLBACK),
  2277. pSmpInfo->EnableGuestAccount,
  2278. ToRename ? 0 : 1
  2279. );
  2280. if ( rc == SCESTATUS_SUCCESS && !(gOptions & SCE_NO_ANALYZE) ) {
  2281. AccessValues[IDX_ENABLE_GUEST] = ToRename ? 0 : 1;
  2282. }
  2283. rc = ScepSceStatusToDosError(rc);
  2284. }
  2285. } else if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS) &&
  2286. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2287. //
  2288. // raise this one
  2289. //
  2290. ScepRaiseErrorString(
  2291. hSection,
  2292. L"EnableGuestAccount",
  2293. NULL
  2294. );
  2295. }
  2296. if ( rc != NO_ERROR ) {
  2297. saveRc = ScepDosErrorToSceStatus(rc);
  2298. if ( !(dwSaveOption & SCEPOL_SYSTEM_SETTINGS)) {
  2299. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_DISABLE_GUEST);
  2300. goto GETOUT;
  2301. } else if ( pErrLog ) {
  2302. //
  2303. // account name failed.
  2304. //
  2305. ScepBuildErrorLogInfo(
  2306. rc,
  2307. pErrLog,
  2308. SCEDLL_SAP_ERROR_DISABLE_GUEST
  2309. );
  2310. }
  2311. }
  2312. }
  2313. //
  2314. // compare the snapshot with SmpInfo and write to SAP section
  2315. //
  2316. ScepLogOutput3(1, 0, SCEDLL_SAP_OTHER_POLICY);
  2317. GETOUT:
  2318. //
  2319. // Clear out memory and return
  2320. //
  2321. SamCloseHandle( DomainHandle );
  2322. SamCloseHandle( ServerHandle );
  2323. if ( DomainSid != NULL )
  2324. SamFreeMemory(DomainSid);
  2325. //
  2326. // see if there is anything needs to be raised for error
  2327. //
  2328. if ( (dwSaveOption == 0) && !(gOptions & SCE_NO_ANALYZE) &&
  2329. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2330. for ( CurrentVal=0; CurrentVal<MAX_ACCESS_ITEMS; CurrentVal++ ) {
  2331. if ( AccessValues[CurrentVal] == SCE_ERROR_VALUE ||
  2332. AccessValues[CurrentVal] == SCE_NOT_ANALYZED_VALUE) {
  2333. //
  2334. // raise this one
  2335. //
  2336. ScepCompareAndSaveIntValue(
  2337. hSection,
  2338. AccessItems[CurrentVal],
  2339. FALSE,
  2340. SCE_NO_VALUE,
  2341. AccessValues[CurrentVal]);
  2342. }
  2343. }
  2344. }
  2345. return( saveRc );
  2346. }
  2347. NTSTATUS
  2348. ScepAdminGuestAccountsToManage(
  2349. IN SAM_HANDLE DomainHandle,
  2350. IN DWORD AccountType,
  2351. IN PWSTR TargetName OPTIONAL,
  2352. OUT PBOOL ToRename,
  2353. OUT PWSTR *CurrentName OPTIONAL,
  2354. OUT PDWORD pNameLen OPTIONAL
  2355. )
  2356. /* ++
  2357. Routine Description:
  2358. This routine checks the specified account's name to see if the account
  2359. needs to be renamed
  2360. Arguments:
  2361. DomainHandle - The account domain handle
  2362. AccountType - indicate it is Administrator account or Guest account
  2363. SCE_RENAME_ADMIN
  2364. SCE_RENAME_GUEST
  2365. SCE_DISABLE_ADMIN
  2366. SCE_DISABLE_GUEST
  2367. ToRename - for the rename operations,
  2368. TRUE = rename the account, FALSE=do not need to rename
  2369. for the disable operations,
  2370. TRUE = disabled, FALSE = enabled
  2371. Return value:
  2372. NTSTATUS error codes
  2373. -- */
  2374. {
  2375. SAM_HANDLE UserHandle1=NULL;
  2376. PVOID pInfoBuffer=NULL;
  2377. USER_NAME_INFORMATION *Buffer=NULL;
  2378. USER_CONTROL_INFORMATION *pControlBuffer = NULL;
  2379. NTSTATUS NtStatus;
  2380. ULONG UserId;
  2381. BOOL bDisable=FALSE;
  2382. //
  2383. // find the right userid for the account
  2384. //
  2385. switch ( AccountType ) {
  2386. case SCE_DISABLE_ADMIN:
  2387. bDisable = TRUE;
  2388. // fall through
  2389. case SCE_RENAME_ADMIN:
  2390. UserId = DOMAIN_USER_RID_ADMIN;
  2391. break;
  2392. case SCE_DISABLE_GUEST:
  2393. bDisable = TRUE;
  2394. // fall through
  2395. case SCE_RENAME_GUEST:
  2396. UserId = DOMAIN_USER_RID_GUEST;
  2397. break;
  2398. default:
  2399. return(STATUS_INVALID_PARAMETER);
  2400. }
  2401. *ToRename = TRUE;
  2402. if ( pNameLen )
  2403. *pNameLen = 0;
  2404. NtStatus = SamOpenUser(
  2405. DomainHandle,
  2406. USER_READ_GENERAL | (bDisable ? USER_READ_ACCOUNT : 0), // USER_READ | USER_EXECUTE,
  2407. UserId,
  2408. &UserHandle1
  2409. );
  2410. if ( NT_SUCCESS( NtStatus ) ) {
  2411. NtStatus = SamQueryInformationUser(
  2412. UserHandle1,
  2413. bDisable ? UserControlInformation : UserNameInformation,
  2414. &pInfoBuffer
  2415. );
  2416. if ( NT_SUCCESS( NtStatus ) ) {
  2417. if ( bDisable ) {
  2418. //
  2419. // check disable flags
  2420. //
  2421. pControlBuffer = (USER_CONTROL_INFORMATION *)pInfoBuffer;
  2422. if ( pControlBuffer->UserAccountControl & USER_ACCOUNT_DISABLED ) {
  2423. *ToRename = TRUE;
  2424. } else {
  2425. *ToRename = FALSE;
  2426. }
  2427. } else {
  2428. //
  2429. // check account names
  2430. //
  2431. Buffer = (USER_NAME_INFORMATION *)pInfoBuffer;
  2432. if ( Buffer->UserName.Length > 0 && Buffer->UserName.Buffer ) {
  2433. if (CurrentName) {
  2434. *CurrentName = (PWSTR)ScepAlloc(0, Buffer->UserName.Length+2);
  2435. if ( *CurrentName ) {
  2436. wcsncpy(*CurrentName, Buffer->UserName.Buffer, Buffer->UserName.Length/2);
  2437. (*CurrentName)[Buffer->UserName.Length/2] = L'\0';
  2438. } else
  2439. NtStatus = STATUS_NO_MEMORY;
  2440. }
  2441. if ( pNameLen ) {
  2442. *pNameLen = Buffer->UserName.Length/2;
  2443. }
  2444. if ( NT_SUCCESS( NtStatus ) && TargetName ) {
  2445. if ( _wcsnicmp(Buffer->UserName.Buffer, TargetName, Buffer->UserName.Length/2 ) == 0 )
  2446. *ToRename = FALSE;
  2447. }
  2448. }
  2449. }
  2450. }
  2451. SamFreeMemory(pInfoBuffer);
  2452. SamCloseHandle( UserHandle1 );
  2453. }
  2454. return( NtStatus );
  2455. }
  2456. BOOL
  2457. ScepIsThisItemInNameList(
  2458. IN PWSTR Item,
  2459. IN BOOL bIsSid,
  2460. IN PSCE_NAME_LIST pList
  2461. )
  2462. {
  2463. PSCE_NAME_LIST pName2;
  2464. BOOL bSid2;
  2465. if ( Item == NULL || pList == NULL ) {
  2466. return(FALSE);
  2467. }
  2468. for ( pName2=pList; pName2 != NULL; pName2 = pName2->Next ) {
  2469. if ( pName2->Name == NULL ) {
  2470. continue;
  2471. }
  2472. if ( ScepValidSid( (PSID)(pName2->Name) ) ) {
  2473. bSid2 = TRUE;
  2474. } else {
  2475. bSid2 = FALSE;
  2476. }
  2477. //
  2478. // if SID/Name format mismatch, return
  2479. //
  2480. if ( bIsSid != bSid2 ) {
  2481. continue;
  2482. }
  2483. if ( bIsSid && RtlEqualSid( (PSID)(Item), (PSID)(pName2->Name) ) ) {
  2484. //
  2485. // find a SID match
  2486. //
  2487. break;
  2488. }
  2489. if ( !bIsSid && _wcsicmp(Item, pName2->Name) == 0 ) {
  2490. //
  2491. // find a match
  2492. //
  2493. break; // the second for loop
  2494. }
  2495. }
  2496. if ( pName2 ) {
  2497. //
  2498. // find it
  2499. //
  2500. return(TRUE);
  2501. } else {
  2502. return(FALSE);
  2503. }
  2504. }
  2505. BOOL
  2506. ScepCompareSidNameList(
  2507. IN PSCE_NAME_LIST pList1,
  2508. IN PSCE_NAME_LIST pList2
  2509. )
  2510. /*
  2511. Compare two lists where the name field can be a SID or Name.
  2512. The rule is to compare SID to SID and name to name because name
  2513. is only there when it can be mapped to a SID
  2514. */
  2515. {
  2516. PSCE_NAME_LIST pName1, pName2;
  2517. DWORD CountSid1=0, CountSid2=0;
  2518. DWORD CountN1=0, CountN2=0;
  2519. if ( (pList2 == NULL && pList1 != NULL) ||
  2520. (pList2 != NULL && pList1 == NULL) ) {
  2521. // return(TRUE);
  2522. // should be not equal
  2523. return(FALSE);
  2524. }
  2525. for ( pName2=pList2; pName2 != NULL; pName2 = pName2->Next ) {
  2526. if ( pName2->Name == NULL ) {
  2527. continue;
  2528. }
  2529. if ( ScepValidSid( (PSID)(pName2->Name) ) ) {
  2530. CountSid2++;
  2531. } else {
  2532. CountN2++;
  2533. }
  2534. }
  2535. BOOL bSid1;
  2536. for ( pName1=pList1; pName1 != NULL; pName1 = pName1->Next ) {
  2537. if ( pName1->Name == NULL ) {
  2538. continue;
  2539. }
  2540. if ( ScepValidSid( (PSID)(pName1->Name) ) ) {
  2541. bSid1 = TRUE;
  2542. CountSid1++;
  2543. } else {
  2544. bSid1 = FALSE;
  2545. CountN1++;
  2546. }
  2547. if ( !ScepIsThisItemInNameList( pName1->Name, bSid1, pList2 ) ) {
  2548. //
  2549. // does not find a match
  2550. //
  2551. return(FALSE);
  2552. }
  2553. }
  2554. if ( CountSid1 != CountSid2 )
  2555. return(FALSE);
  2556. if ( CountN2 != CountN2 ) {
  2557. return(FALSE);
  2558. }
  2559. return(TRUE);
  2560. }
  2561. DWORD
  2562. ScepConvertSidListToStringName(
  2563. IN LSA_HANDLE LsaPolicy,
  2564. IN OUT PSCE_NAME_LIST pList
  2565. )
  2566. {
  2567. PSCE_NAME_LIST pSidList;
  2568. DWORD rc=ERROR_SUCCESS;
  2569. PWSTR StringSid=NULL;
  2570. for ( pSidList=pList; pSidList != NULL;
  2571. pSidList=pSidList->Next) {
  2572. if ( pSidList->Name == NULL ) {
  2573. continue;
  2574. }
  2575. if ( ScepValidSid( (PSID)(pSidList->Name) ) ) {
  2576. //
  2577. // if the SID is a domain account, convert it to sid string
  2578. // otherwise, convert it to name, then add to the name list
  2579. //
  2580. if ( ScepIsSidFromAccountDomain( (PSID)(pSidList->Name) ) ) {
  2581. rc = ScepConvertSidToPrefixStringSid( (PSID)(pSidList->Name), &StringSid );
  2582. } else {
  2583. //
  2584. // should conver it to name
  2585. //
  2586. rc = RtlNtStatusToDosError(
  2587. ScepConvertSidToName(
  2588. LsaPolicy,
  2589. (PSID)(pSidList->Name),
  2590. FALSE,
  2591. &StringSid,
  2592. NULL
  2593. ));
  2594. }
  2595. if ( rc == ERROR_SUCCESS ) {
  2596. ScepFree( pSidList->Name );
  2597. pSidList->Name = StringSid;
  2598. StringSid = NULL;
  2599. } else {
  2600. break;
  2601. }
  2602. } else {
  2603. //
  2604. // this is not a valid sid so it must be in name format already.
  2605. // just leave it as it is.
  2606. //
  2607. }
  2608. }
  2609. return(rc);
  2610. }
  2611. SCESTATUS
  2612. ScepAnalyzePrivileges(
  2613. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivilegeList
  2614. )
  2615. /* ++
  2616. Routine Description:
  2617. This routine analyzies local system privilege's direct assignments to accounts.
  2618. Different assignment from the profile is saved to the SAP profile
  2619. Arguments:
  2620. pSmpInfo - The buffer which contains profile information to compare with
  2621. Return value:
  2622. SCESTATUS_SUCCESS
  2623. SCESTATUS_NOT_ENOUGH_RESOURCE
  2624. SCESTATUS_INVALID_PARAMETER
  2625. -- */
  2626. {
  2627. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  2628. pPrivilegeList == NULL ) {
  2629. return(SCESTATUS_SUCCESS);
  2630. }
  2631. NTSTATUS NtStatus = STATUS_SUCCESS;
  2632. ULONG CountReturned;
  2633. UNICODE_STRING UserRight;
  2634. PLSA_ENUMERATION_INFORMATION EnumBuffer=NULL;
  2635. LSA_HANDLE PolicyHandle=NULL;
  2636. PLSA_TRANSLATED_NAME Names=NULL;
  2637. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains=NULL;
  2638. DWORD i=0, j;
  2639. SCESTATUS rc;
  2640. PSCE_NAME_LIST pNameList=NULL;
  2641. PSCE_PRIVILEGE_ASSIGNMENT pPrivilege;
  2642. DWORD nPrivCount=0;
  2643. //
  2644. // Prepare Jet's section to write
  2645. //
  2646. rc = ScepStartANewSection(
  2647. hProfile,
  2648. &hSection,
  2649. (gOptions & SCE_NO_ANALYZE || gOptions & SCE_GENERATE_ROLLBACK) ?
  2650. SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  2651. szPrivilegeRights
  2652. );
  2653. if ( rc != SCESTATUS_SUCCESS ) {
  2654. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  2655. SCEDLL_SAP_START_SECTION, (PWSTR)szPrivilegeRights);
  2656. goto Done;
  2657. }
  2658. //
  2659. // Open LSA policy
  2660. //
  2661. NtStatus = ScepOpenLsaPolicy(
  2662. GENERIC_READ | GENERIC_EXECUTE,
  2663. &PolicyHandle,
  2664. TRUE
  2665. );
  2666. if ( !NT_SUCCESS(NtStatus) ) {
  2667. rc = RtlNtStatusToDosError(NtStatus);
  2668. ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY );
  2669. ScepPostProgress(TICKS_PRIVILEGE, AREA_PRIVILEGES, NULL);
  2670. goto Done;
  2671. }
  2672. //
  2673. // enumerate accounts for each user right
  2674. //
  2675. INT iStat=0;
  2676. for ( i=0; i<cPrivCnt; i++) {
  2677. iStat = 0;
  2678. if ( gOptions & SCE_NO_ANALYZE ) {
  2679. pPrivilege = NULL;
  2680. iStat = 3;
  2681. } else {
  2682. for ( pPrivilege=pPrivilegeList;
  2683. pPrivilege != NULL;
  2684. pPrivilege = pPrivilege->Next ) {
  2685. // should compare name, because value is different
  2686. // if ( i == pPrivilege->Value)
  2687. if ( _wcsicmp(SCE_Privileges[i].Name, pPrivilege->Name) == 0 )
  2688. break;
  2689. }
  2690. if ( pPrivilege == NULL ) {
  2691. if ( gOptions & SCE_GENERATE_ROLLBACK )
  2692. continue;
  2693. iStat = 2;
  2694. } else {
  2695. iStat = 1;
  2696. }
  2697. }
  2698. RtlInitUnicodeString( &UserRight, (PCWSTR)(SCE_Privileges[i].Name));
  2699. ScepLogOutput3(1, 0, SCEDLL_SAP_ANALYZE, SCE_Privileges[i].Name);
  2700. if ( nPrivCount < TICKS_PRIVILEGE ) {
  2701. //
  2702. // only post maximum TICKS_PRIVILEGE ticks because that's the number
  2703. // remembers in the total ticks
  2704. //
  2705. ScepPostProgress(1, AREA_PRIVILEGES, SCE_Privileges[i].Name);
  2706. nPrivCount++;
  2707. }
  2708. NtStatus = LsaEnumerateAccountsWithUserRight(
  2709. PolicyHandle,
  2710. &UserRight,
  2711. (PVOID *)&EnumBuffer, // account SIDs
  2712. &CountReturned
  2713. );
  2714. if ( NT_SUCCESS(NtStatus) ) {
  2715. BOOL bUsed;
  2716. for ( j=0; j<CountReturned; j++ ) {
  2717. //
  2718. // build each account into the name list
  2719. // Note, if the SID is invalid, do not add it to
  2720. // the valid account list
  2721. //
  2722. if ( !ScepValidSid( EnumBuffer[j].Sid ) ) {
  2723. continue;
  2724. }
  2725. rc = ScepAddSidToNameList(
  2726. &pNameList,
  2727. EnumBuffer[j].Sid,
  2728. FALSE,
  2729. &bUsed
  2730. );
  2731. if ( rc != NO_ERROR ) {
  2732. ScepLogOutput3(1, rc,
  2733. SCEDLL_SAP_ERROR_SAVE,
  2734. SCE_Privileges[i].Name);
  2735. NtStatus = STATUS_NO_MEMORY;
  2736. break;
  2737. }
  2738. }
  2739. LsaFreeMemory( EnumBuffer );
  2740. EnumBuffer = NULL;
  2741. } else if ( NtStatus != STATUS_NO_MORE_ENTRIES &&
  2742. NtStatus != STATUS_NO_SUCH_PRIVILEGE &&
  2743. NtStatus != STATUS_NOT_FOUND ) {
  2744. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  2745. SCEDLL_SAP_ERROR_ENUMERATE,SCE_Privileges[i].Name);
  2746. }
  2747. if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE &&
  2748. !pNameList ) {
  2749. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  2750. SCEDLL_SAP_ERROR_ENUMERATE,SCE_Privileges[i].Name);
  2751. gWarningCode = RtlNtStatusToDosError(NtStatus);
  2752. if ( !(gOptions & SCE_NO_ANALYZE) &&
  2753. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2754. ScepRaiseErrorString(
  2755. hSection,
  2756. SCE_Privileges[i].Name,
  2757. NULL
  2758. );
  2759. }
  2760. NtStatus = STATUS_SUCCESS;
  2761. continue;
  2762. }
  2763. if ( (NtStatus == STATUS_NOT_FOUND ||
  2764. NtStatus == STATUS_NO_MORE_ENTRIES) &&
  2765. !pNameList ) {
  2766. //
  2767. // no account is assigned this privilege
  2768. // should continue the process
  2769. //
  2770. NtStatus = STATUS_SUCCESS;
  2771. }
  2772. if ( NtStatus == STATUS_NO_MORE_ENTRIES ||
  2773. NtStatus == STATUS_NO_SUCH_PRIVILEGE ||
  2774. NtStatus == STATUS_NOT_FOUND ) {
  2775. if ( pNameList != NULL ) {
  2776. ScepFreeNameList(pNameList);
  2777. pNameList = NULL;
  2778. }
  2779. if ( !(gOptions & SCE_NO_ANALYZE) &&
  2780. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2781. ScepRaiseErrorString(
  2782. hSection,
  2783. SCE_Privileges[i].Name,
  2784. NULL
  2785. );
  2786. }
  2787. continue;
  2788. } else if ( !NT_SUCCESS(NtStatus) ) {
  2789. goto Done;
  2790. } else {
  2791. NtStatus = STATUS_SUCCESS;
  2792. //
  2793. // all entries for this priv is added to the pNameList.
  2794. // compare with SMP privileges list to match
  2795. //
  2796. if ( pPrivilege == NULL ||
  2797. ScepCompareSidNameList(pPrivilege->AssignedTo, pNameList) == FALSE ) {
  2798. //
  2799. // this priv does not exist in the SMP list, or have different
  2800. // accounts assigned to. Save it
  2801. //
  2802. rc = ScepConvertSidListToStringName(PolicyHandle, pNameList);
  2803. if ( SCESTATUS_SUCCESS == rc ) {
  2804. rc = ScepWriteNameListValue(
  2805. PolicyHandle,
  2806. hSection,
  2807. SCE_Privileges[i].Name,
  2808. pNameList,
  2809. SCE_WRITE_EMPTY_LIST,
  2810. iStat
  2811. );
  2812. if ( rc != SCESTATUS_SUCCESS ) {
  2813. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  2814. SCEDLL_SAP_ERROR_SAVE,
  2815. SCE_Privileges[i].Name);
  2816. NtStatus = STATUS_NO_MEMORY;
  2817. goto Done;
  2818. }
  2819. } else if ( !(gOptions & SCE_NO_ANALYZE) &&
  2820. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2821. ScepRaiseErrorString(
  2822. hSection,
  2823. SCE_Privileges[i].Name,
  2824. NULL
  2825. );
  2826. }
  2827. }
  2828. if ( pNameList != NULL ) {
  2829. ScepFreeNameList(pNameList);
  2830. pNameList = NULL;
  2831. }
  2832. }
  2833. }
  2834. Done:
  2835. if ( !(gOptions & SCE_NO_ANALYZE) &&
  2836. !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  2837. for ( j=i; j<cPrivCnt; j++) {
  2838. //
  2839. // raise error for anything not analyzed
  2840. //
  2841. ScepRaiseErrorString(
  2842. hSection,
  2843. SCE_Privileges[j].Name,
  2844. NULL
  2845. );
  2846. }
  2847. }
  2848. if ( pNameList != NULL )
  2849. ScepFreeNameList( pNameList );
  2850. if (PolicyHandle)
  2851. LsaClose(PolicyHandle);
  2852. if ( nPrivCount < TICKS_PRIVILEGE ) {
  2853. ScepPostProgress(TICKS_PRIVILEGE-nPrivCount,
  2854. AREA_PRIVILEGES, NULL);
  2855. }
  2856. return( ScepDosErrorToSceStatus( RtlNtStatusToDosError(NtStatus) ) );
  2857. }
  2858. SCESTATUS
  2859. ScepRaiseErrorString(
  2860. IN PSCESECTION hSectionIn OPTIONAL,
  2861. IN PWSTR KeyName,
  2862. IN PCWSTR szSuffix OPTIONAL
  2863. )
  2864. {
  2865. if ( KeyName == NULL ) {
  2866. return(SCESTATUS_INVALID_PARAMETER);
  2867. }
  2868. PWSTR NewKeyName = NULL;
  2869. if ( szSuffix ) {
  2870. //
  2871. // this is for group membership section
  2872. // append the suffix (szMembers, or szMemberOf)
  2873. //
  2874. NewKeyName = (PWSTR)ScepAlloc(0, (wcslen(KeyName)+wcslen(szSuffix)+1)*sizeof(WCHAR));
  2875. if ( NewKeyName != NULL ) {
  2876. swprintf(NewKeyName, L"%s%s\0", KeyName, szSuffix);
  2877. } else {
  2878. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2879. }
  2880. } else {
  2881. NewKeyName = KeyName;
  2882. }
  2883. SceJetSetLine(
  2884. hSectionIn ? hSectionIn : hSection,
  2885. NewKeyName,
  2886. FALSE,
  2887. SCE_ERROR_STRING,
  2888. wcslen(SCE_ERROR_STRING)*sizeof(WCHAR),
  2889. 0
  2890. );
  2891. //
  2892. // free memory
  2893. //
  2894. if ( NewKeyName != KeyName &&
  2895. NewKeyName ) {
  2896. ScepFree(NewKeyName);
  2897. }
  2898. return SCESTATUS_SUCCESS;
  2899. }
  2900. #if 0
  2901. NTSTATUS
  2902. ScepGetCurrentPrivilegesRights(
  2903. IN LSA_HANDLE PolicyHandle,
  2904. IN SAM_HANDLE BuiltinDomainHandle,
  2905. IN PSID BuiltinDomainSid,
  2906. IN SAM_HANDLE DomainHandle,
  2907. IN PSID DomainSid,
  2908. IN SAM_HANDLE UserHandle OPTIONAL,
  2909. IN PSID AccountSid,
  2910. OUT PDWORD PrivilegeRights,
  2911. OUT PSCE_NAME_STATUS_LIST *pPrivList
  2912. )
  2913. /* ++
  2914. Routine Description:
  2915. This routine queries privilege/rights of a account by looking rights
  2916. assigned to the account explicitly, to the local groups (aliases) the
  2917. account is a member of, or to the global groups the account is a member
  2918. of. The aliases are checked both directly and indirectly. the user rights
  2919. are stores in a DWORD type variable PrivilegeRights, in which each bit
  2920. represents a privilege/right.
  2921. Arguments:
  2922. PolicyHandle - Lsa Policy Domain handle
  2923. BuiltinDomainHandle - SAM builtin domain handle
  2924. BuiltinDomainSid - SAM builtin domain SID
  2925. DomainHandle - SAM account domain handle
  2926. DomainSid - SAM account domain SID
  2927. UserHandle - SAM user account handle
  2928. AccountSid - The SID for the account
  2929. PrivilegeRights - Privilege/Rights of this account
  2930. Return value:
  2931. NTSTATUS
  2932. -- */
  2933. {
  2934. NTSTATUS NtStatus;
  2935. SCESTATUS rc;
  2936. DWORD Rights=0;
  2937. PGROUP_MEMBERSHIP GroupAttributes=NULL;
  2938. ULONG GroupCount=0;
  2939. PSID GroupSid=NULL;
  2940. PSID *Sids=NULL;
  2941. ULONG PartialCount;
  2942. PULONG Aliases=NULL;
  2943. PSID OtherSid=NULL;
  2944. SID_IDENTIFIER_AUTHORITY NtAuthority=SECURITY_NT_AUTHORITY;
  2945. SID_IDENTIFIER_AUTHORITY WorldAuthority=SECURITY_WORLD_SID_AUTHORITY;
  2946. DWORD i;
  2947. PUNICODE_STRING GroupName=NULL;
  2948. PSID_NAME_USE Use=NULL;
  2949. // initialize
  2950. *PrivilegeRights = 0;
  2951. //
  2952. // Check the explicitly assigned rights
  2953. //
  2954. NtStatus = ScepGetAccountExplicitRight(
  2955. PolicyHandle,
  2956. AccountSid,
  2957. &Rights
  2958. );
  2959. if ( !NT_SUCCESS(NtStatus) )
  2960. goto Done;
  2961. *PrivilegeRights |= Rights;
  2962. //
  2963. // add to Privilege list
  2964. //
  2965. if ( pPrivList != NULL && Rights != 0 ) {
  2966. rc = ScepAddToPrivList( pPrivList, Rights, NULL, 0 );
  2967. if ( rc != SCESTATUS_SUCCESS ) {
  2968. NtStatus = STATUS_NO_MEMORY;
  2969. goto Done;
  2970. }
  2971. }
  2972. if ( UserHandle != NULL ) {
  2973. //
  2974. // groups (direct) the account belongs to.
  2975. //
  2976. NtStatus = SamGetGroupsForUser(
  2977. UserHandle,
  2978. &GroupAttributes,
  2979. &GroupCount
  2980. );
  2981. if ( GroupCount == 0 )
  2982. NtStatus = ERROR_SUCCESS;
  2983. if ( !NT_SUCCESS(NtStatus) )
  2984. goto Done;
  2985. }
  2986. //
  2987. // build sids including the user itself
  2988. //
  2989. Sids = (PSID *)ScepAlloc( (UINT)0, (GroupCount+1)*sizeof(PSID));
  2990. if ( Sids == NULL ) {
  2991. NtStatus = STATUS_NO_MEMORY;
  2992. goto Done;
  2993. }
  2994. Sids[0] = AccountSid;
  2995. //
  2996. // get each group's explicitly assigned rights
  2997. //
  2998. for ( i=0; i < GroupCount; i++ ) {
  2999. NtStatus = ScepDomainIdToSid(
  3000. DomainSid,
  3001. GroupAttributes[i].RelativeId,
  3002. &GroupSid
  3003. );
  3004. if ( !NT_SUCCESS(NtStatus) )
  3005. goto Done;
  3006. //
  3007. // Check the explicitly assigned rights for this group
  3008. //
  3009. Rights = 0;
  3010. NtStatus = ScepGetAccountExplicitRight(
  3011. PolicyHandle,
  3012. GroupSid,
  3013. &Rights
  3014. );
  3015. if ( !NT_SUCCESS(NtStatus) )
  3016. goto Done;
  3017. *PrivilegeRights |= Rights;
  3018. //
  3019. // add to Privilege list
  3020. //
  3021. if ( pPrivList != NULL && Rights != 0 ) {
  3022. //
  3023. // Lookup for group's name
  3024. //
  3025. NtStatus = SamLookupIdsInDomain(
  3026. DomainHandle,
  3027. 1,
  3028. &(GroupAttributes[i].RelativeId),
  3029. &GroupName,
  3030. &Use
  3031. );
  3032. if ( !NT_SUCCESS(NtStatus) )
  3033. goto Done;
  3034. rc = ScepAddToPrivList( pPrivList, Rights, GroupName[0].Buffer, GroupName[0].Length/2 );
  3035. if ( rc != SCESTATUS_SUCCESS ) {
  3036. NtStatus = STATUS_NO_MEMORY;
  3037. goto Done;
  3038. }
  3039. SamFreeMemory(Use);
  3040. Use = NULL;
  3041. SamFreeMemory(GroupName);
  3042. GroupName = NULL;
  3043. }
  3044. //
  3045. // Save this Sid in the array for GetAliasMembership
  3046. //
  3047. Sids[i+1] = GroupSid;
  3048. GroupSid = NULL;
  3049. }
  3050. //
  3051. // See what indirect local groups the account belongs to.
  3052. // account domain
  3053. //
  3054. NtStatus = SamGetAliasMembership(
  3055. DomainHandle,
  3056. GroupCount+1,
  3057. Sids,
  3058. &PartialCount,
  3059. &Aliases );
  3060. if ( !NT_SUCCESS(NtStatus) )
  3061. goto Done;
  3062. for ( i=0; i<PartialCount; i++) {
  3063. NtStatus = ScepDomainIdToSid(
  3064. DomainSid,
  3065. Aliases[i],
  3066. &GroupSid
  3067. );
  3068. if ( !NT_SUCCESS(NtStatus) )
  3069. goto Done;
  3070. //
  3071. // Check the explicitly assigned rights for this group
  3072. //
  3073. Rights = 0;
  3074. NtStatus = ScepGetAccountExplicitRight(
  3075. PolicyHandle,
  3076. GroupSid,
  3077. &Rights
  3078. );
  3079. if ( !NT_SUCCESS(NtStatus) )
  3080. goto Done;
  3081. *PrivilegeRights |= Rights;
  3082. //
  3083. // add to Privilege list
  3084. //
  3085. if ( pPrivList != NULL && Rights != 0 ) {
  3086. //
  3087. // Lookup for group's name
  3088. //
  3089. NtStatus = SamLookupIdsInDomain(
  3090. DomainHandle,
  3091. 1,
  3092. &(Aliases[i]),
  3093. &GroupName,
  3094. &Use
  3095. );
  3096. if ( !NT_SUCCESS(NtStatus) )
  3097. goto Done;
  3098. rc = ScepAddToPrivList( pPrivList, Rights, GroupName[0].Buffer, GroupName[0].Length/2 );
  3099. if ( rc != SCESTATUS_SUCCESS ) {
  3100. NtStatus = STATUS_NO_MEMORY;
  3101. goto Done;
  3102. }
  3103. SamFreeMemory(Use);
  3104. Use = NULL;
  3105. SamFreeMemory(GroupName);
  3106. GroupName = NULL;
  3107. }
  3108. ScepFree(GroupSid);
  3109. GroupSid = NULL;
  3110. }
  3111. SamFreeMemory(Aliases);
  3112. Aliases = NULL;
  3113. //
  3114. // check the builtin domain for alias membership
  3115. //
  3116. NtStatus = SamGetAliasMembership(
  3117. BuiltinDomainHandle,
  3118. GroupCount+1,
  3119. Sids,
  3120. &PartialCount,
  3121. &Aliases );
  3122. if ( !NT_SUCCESS(NtStatus) )
  3123. goto Done;
  3124. for ( i=0; i<PartialCount; i++) {
  3125. NtStatus = ScepDomainIdToSid(
  3126. BuiltinDomainSid,
  3127. Aliases[i],
  3128. &GroupSid
  3129. );
  3130. if ( !NT_SUCCESS(NtStatus) )
  3131. goto Done;
  3132. //
  3133. // Check the explicitly assigned rights for this group
  3134. //
  3135. Rights = 0;
  3136. NtStatus = ScepGetAccountExplicitRight(
  3137. PolicyHandle,
  3138. GroupSid,
  3139. &Rights
  3140. );
  3141. if ( !NT_SUCCESS(NtStatus) )
  3142. goto Done;
  3143. *PrivilegeRights |= Rights;
  3144. //
  3145. // add to Privilege list
  3146. //
  3147. if ( pPrivList != NULL && Rights != 0 ) {
  3148. //
  3149. // Lookup for group's name
  3150. //
  3151. NtStatus = SamLookupIdsInDomain(
  3152. BuiltinDomainHandle,
  3153. 1,
  3154. &(Aliases[i]),
  3155. &GroupName,
  3156. &Use
  3157. );
  3158. if ( !NT_SUCCESS(NtStatus) )
  3159. goto Done;
  3160. rc = ScepAddToPrivList( pPrivList, Rights, GroupName[0].Buffer, GroupName[0].Length/2 );
  3161. if ( rc != SCESTATUS_SUCCESS ) {
  3162. NtStatus = STATUS_NO_MEMORY;
  3163. goto Done;
  3164. }
  3165. SamFreeMemory(Use);
  3166. Use = NULL;
  3167. SamFreeMemory(GroupName);
  3168. GroupName = NULL;
  3169. }
  3170. ScepFree(GroupSid);
  3171. GroupSid = NULL;
  3172. }
  3173. //
  3174. // Checking privileges/rights for Everyone and Interactive Users
  3175. //
  3176. NtStatus = RtlAllocateAndInitializeSid(
  3177. &NtAuthority,
  3178. 1,
  3179. SECURITY_INTERACTIVE_RID,
  3180. 0, 0, 0, 0, 0, 0, 0,
  3181. &OtherSid
  3182. );
  3183. if ( NT_SUCCESS(NtStatus) ) {
  3184. Rights = 0;
  3185. NtStatus = ScepGetAccountExplicitRight(
  3186. PolicyHandle,
  3187. OtherSid,
  3188. &Rights
  3189. );
  3190. if ( !NT_SUCCESS(NtStatus) )
  3191. goto Done;
  3192. *PrivilegeRights |= Rights;
  3193. //
  3194. // add to Privilege list
  3195. //
  3196. if ( pPrivList != NULL && Rights != 0 ) {
  3197. rc = ScepAddToPrivList( pPrivList, Rights, L"Interactive Users", 17 );
  3198. if ( rc != SCESTATUS_SUCCESS ) {
  3199. NtStatus = STATUS_NO_MEMORY;
  3200. goto Done;
  3201. }
  3202. }
  3203. RtlFreeSid(OtherSid);
  3204. OtherSid = NULL;
  3205. }
  3206. NtStatus = RtlAllocateAndInitializeSid(
  3207. &WorldAuthority,
  3208. 1,
  3209. SECURITY_WORLD_RID,
  3210. 0, 0, 0, 0, 0, 0, 0,
  3211. &OtherSid
  3212. );
  3213. if ( NT_SUCCESS(NtStatus) ) {
  3214. Rights = 0;
  3215. NtStatus = ScepGetAccountExplicitRight(
  3216. PolicyHandle,
  3217. OtherSid,
  3218. &Rights
  3219. );
  3220. if ( !NT_SUCCESS(NtStatus) )
  3221. goto Done;
  3222. *PrivilegeRights |= Rights;
  3223. //
  3224. // add to Privilege list
  3225. //
  3226. if ( pPrivList != NULL && Rights != 0 ) {
  3227. rc = ScepAddToPrivList( pPrivList, Rights, L"Everyone", 8 );
  3228. if ( rc != SCESTATUS_SUCCESS ) {
  3229. NtStatus = STATUS_NO_MEMORY;
  3230. goto Done;
  3231. }
  3232. }
  3233. RtlFreeSid(OtherSid);
  3234. OtherSid = NULL;
  3235. }
  3236. Done:
  3237. SamFreeMemory(GroupAttributes);
  3238. if ( GroupSid != NULL )
  3239. ScepFree(GroupSid);
  3240. if ( OtherSid != NULL )
  3241. RtlFreeSid(OtherSid);
  3242. if ( Sids != NULL ) {
  3243. //
  3244. // index 0 is the accountSid, DO NOT free
  3245. //
  3246. for ( i=1; i<GroupCount; i++ ) {
  3247. ScepFree(Sids[i]);
  3248. }
  3249. ScepFree(Sids);
  3250. }
  3251. if ( Aliases != NULL )
  3252. SamFreeMemory(Aliases);
  3253. return NtStatus;
  3254. }
  3255. #endif
  3256. SCESTATUS
  3257. ScepAddAllBuiltinGroups(
  3258. IN PSCE_GROUP_MEMBERSHIP *pGroupList
  3259. )
  3260. {
  3261. NTSTATUS NtStatus=ERROR_SUCCESS;
  3262. SCESTATUS rc=SCESTATUS_SUCCESS;
  3263. DWORD Win32rc;
  3264. SAM_ENUMERATE_HANDLE EnumerationContext=0;
  3265. ULONG CountReturned;
  3266. DWORD i;
  3267. PVOID Buffer=NULL;
  3268. SAM_HANDLE ServerHandle=NULL,
  3269. DomainHandle=NULL,
  3270. BuiltinDomainHandle=NULL;
  3271. PSID DomainSid=NULL,
  3272. BuiltinDomainSid=NULL;
  3273. //
  3274. // open sam handle
  3275. //
  3276. NtStatus = ScepOpenSamDomain(
  3277. SAM_SERVER_READ | SAM_SERVER_EXECUTE,
  3278. DOMAIN_READ | DOMAIN_EXECUTE,
  3279. &ServerHandle,
  3280. &DomainHandle,
  3281. &DomainSid,
  3282. &BuiltinDomainHandle,
  3283. &BuiltinDomainSid
  3284. );
  3285. if (!NT_SUCCESS(NtStatus)) {
  3286. Win32rc = RtlNtStatusToDosError(NtStatus);
  3287. ScepLogOutput3(1, Win32rc, SCEDLL_ACCOUNT_DOMAIN);
  3288. rc = ScepDosErrorToSceStatus(Win32rc);
  3289. return( rc );
  3290. }
  3291. //
  3292. // enumerate all aliases
  3293. //
  3294. do {
  3295. NtStatus = SamEnumerateAliasesInDomain(
  3296. BuiltinDomainHandle,
  3297. &EnumerationContext,
  3298. &Buffer,
  3299. 12000,
  3300. &CountReturned
  3301. );
  3302. if ( NT_SUCCESS(NtStatus) && Buffer != NULL ) {
  3303. for (i=0; i<CountReturned; i++) {
  3304. //
  3305. // add this group in
  3306. //
  3307. rc = ScepAddToGroupMembership(
  3308. pGroupList,
  3309. ((PSAM_SID_ENUMERATION)(Buffer))[i].Name.Buffer,
  3310. ((PSAM_SID_ENUMERATION)(Buffer))[i].Name.Length/2,
  3311. NULL, // always use NULL list so mismatch will be raised for administrators, guests, and users
  3312. 1, // memberof list, members should be NC
  3313. TRUE, // seek to the right group if one exists
  3314. FALSE // if to overwrite the value if something is already there
  3315. );
  3316. if ( rc != SCESTATUS_SUCCESS )
  3317. break;
  3318. }
  3319. SamFreeMemory( Buffer );
  3320. Buffer = NULL;
  3321. } else
  3322. rc = ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus));
  3323. } while ( NtStatus == STATUS_MORE_ENTRIES );
  3324. if ( rc != SCESTATUS_SUCCESS ) {
  3325. //
  3326. // grouplist will be freed outside, so continue here
  3327. //
  3328. }
  3329. //
  3330. // close all handles
  3331. //
  3332. SamCloseHandle( DomainHandle );
  3333. SamCloseHandle( BuiltinDomainHandle );
  3334. SamCloseHandle( ServerHandle );
  3335. if ( DomainSid != NULL )
  3336. SamFreeMemory(DomainSid);
  3337. if ( BuiltinDomainSid != NULL )
  3338. RtlFreeSid(BuiltinDomainSid);
  3339. return(rc);
  3340. }
  3341. SCESTATUS
  3342. ScepAnalyzeGroupMembership(
  3343. IN PSCE_GROUP_MEMBERSHIP pGroupMembership
  3344. )
  3345. /* ++
  3346. Routine Description:
  3347. This routine queries groups specified in pGroupMembership and their members
  3348. Arguments:
  3349. ppGroupMembership - The groups and members list in SMP profile
  3350. Return value:
  3351. SCESTATUS
  3352. -- */
  3353. {
  3354. SCESTATUS rc=SCESTATUS_SUCCESS;
  3355. if ( pGroupMembership == NULL ) {
  3356. //
  3357. // post progress
  3358. //
  3359. ScepPostProgress(TICKS_GROUPS,
  3360. AREA_GROUP_MEMBERSHIP,
  3361. NULL);
  3362. return(rc);
  3363. }
  3364. DWORD Win32rc;
  3365. NTSTATUS NtStatus;
  3366. SAM_HANDLE ServerHandle=NULL,
  3367. DomainHandle=NULL,
  3368. BuiltinDomainHandle=NULL;
  3369. PSID DomainSid=NULL,
  3370. BuiltinDomainSid=NULL;
  3371. LSA_HANDLE PolicyHandle=NULL;
  3372. SAM_HANDLE ThisDomain=NULL;
  3373. PSID ThisDomainSid=NULL;
  3374. UNICODE_STRING Name;
  3375. PULONG GrpId=NULL;
  3376. PSID_NAME_USE GrpUse=NULL;
  3377. PSID GrpSid=NULL;
  3378. SAM_HANDLE GroupHandle=NULL;
  3379. PWSTR KeyName=NULL;
  3380. DWORD GroupLen;
  3381. PSCE_GROUP_MEMBERSHIP pGroup;
  3382. PSCE_NAME_LIST pGroupMembers=NULL;
  3383. PSCE_NAME_LIST pGroupsMemberof=NULL;
  3384. PSCE_NAME_STATUS_LIST pPrivilegesHeld=NULL;
  3385. BOOL bDifferent;
  3386. DWORD nGroupCount=0;
  3387. //
  3388. // Open account domain
  3389. //
  3390. NtStatus = ScepOpenSamDomain(
  3391. SAM_SERVER_READ | SAM_SERVER_EXECUTE,
  3392. DOMAIN_READ | DOMAIN_EXECUTE,
  3393. &ServerHandle,
  3394. &DomainHandle,
  3395. &DomainSid,
  3396. &BuiltinDomainHandle,
  3397. &BuiltinDomainSid
  3398. );
  3399. if (!NT_SUCCESS(NtStatus)) {
  3400. Win32rc = RtlNtStatusToDosError(NtStatus);
  3401. ScepLogOutput3(1, Win32rc, SCEDLL_ACCOUNT_DOMAIN);
  3402. rc = ScepDosErrorToSceStatus(Win32rc);
  3403. ScepPostProgress(TICKS_GROUPS,
  3404. AREA_GROUP_MEMBERSHIP,
  3405. NULL);
  3406. return( rc );
  3407. }
  3408. //
  3409. // open local policy
  3410. //
  3411. NtStatus = ScepOpenLsaPolicy(
  3412. POLICY_LOOKUP_NAMES,
  3413. &PolicyHandle,
  3414. TRUE
  3415. );
  3416. if (!NT_SUCCESS(NtStatus)) {
  3417. Win32rc = RtlNtStatusToDosError(NtStatus);
  3418. ScepLogOutput3(1, Win32rc, SCEDLL_LSA_POLICY);
  3419. rc = ScepDosErrorToSceStatus(Win32rc);
  3420. goto Done;
  3421. }
  3422. //
  3423. // Process each group in the GroupMembership list
  3424. //
  3425. UNICODE_STRING uName;
  3426. LPTSTR pTemp;
  3427. for ( pGroup=pGroupMembership; pGroup != NULL; pGroup = pGroup->Next ) {
  3428. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  3429. (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS) &&
  3430. (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  3431. continue;
  3432. }
  3433. if ( (ProductType == NtProductLanManNt) &&
  3434. (pGroup->Status & SCE_GROUP_STATUS_DONE_IN_DS) ) {
  3435. nGroupCount++;
  3436. continue;
  3437. }
  3438. if ( KeyName ) {
  3439. LocalFree(KeyName);
  3440. KeyName = NULL;
  3441. }
  3442. pTemp = wcschr(pGroup->GroupName, L'\\');
  3443. if ( pTemp ) {
  3444. //
  3445. // there is a domain name, check it with computer/domain name
  3446. //
  3447. uName.Buffer = pGroup->GroupName;
  3448. uName.Length = ((USHORT)(pTemp-pGroup->GroupName))*sizeof(TCHAR);
  3449. if ( !ScepIsDomainLocal(&uName) ) {
  3450. // If there is a memberof part, we'll configure it but
  3451. // we don't support analysis. Gracefully continue.
  3452. if(!pGroup->pMemberOf)
  3453. {
  3454. ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pGroup->GroupName);
  3455. rc = SCESTATUS_INVALID_DATA;
  3456. }
  3457. continue;
  3458. }
  3459. ScepConvertNameToSidString(
  3460. PolicyHandle,
  3461. pGroup->GroupName,
  3462. FALSE,
  3463. &KeyName,
  3464. &GroupLen
  3465. );
  3466. if(NULL == KeyName) // failed to map to SID, we'll use GroupName
  3467. {
  3468. GroupLen = wcslen(pGroup->GroupName);
  3469. }
  3470. pTemp++;
  3471. } else {
  3472. if ( ScepLookupWellKnownName(
  3473. pGroup->GroupName,
  3474. PolicyHandle,
  3475. &KeyName ) ) {
  3476. GroupLen = wcslen(KeyName);
  3477. } else {
  3478. KeyName = NULL;
  3479. GroupLen = wcslen(pGroup->GroupName);
  3480. }
  3481. pTemp = pGroup->GroupName;
  3482. }
  3483. ScepLogOutput3(0,0, SCEDLL_SAP_ANALYZE, pGroup->GroupName);
  3484. if ( nGroupCount < TICKS_GROUPS ) {
  3485. ScepPostProgress(1, AREA_GROUP_MEMBERSHIP, pGroup->GroupName);
  3486. nGroupCount++;
  3487. }
  3488. // initialize a UNICODE_STRING for the group name
  3489. RtlInitUnicodeString(&Name, pTemp);
  3490. //
  3491. // lookup the group name in account domain first
  3492. //
  3493. NtStatus = SamLookupNamesInDomain(
  3494. DomainHandle,
  3495. 1,
  3496. &Name,
  3497. &GrpId,
  3498. &GrpUse
  3499. );
  3500. ThisDomain = DomainHandle;
  3501. ThisDomainSid = DomainSid;
  3502. if ( NtStatus == STATUS_NONE_MAPPED ) {
  3503. //
  3504. // not found in account domain. Lookup in the builtin domain
  3505. //
  3506. NtStatus = SamLookupNamesInDomain(
  3507. BuiltinDomainHandle,
  3508. 1,
  3509. &Name,
  3510. &GrpId,
  3511. &GrpUse
  3512. );
  3513. ThisDomain=BuiltinDomainHandle;
  3514. ThisDomainSid = BuiltinDomainSid;
  3515. }
  3516. if ( NtStatus == STATUS_NONE_MAPPED ) {
  3517. ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pGroup->GroupName);
  3518. gWarningCode = ERROR_SOME_NOT_MAPPED;
  3519. NtStatus = STATUS_SUCCESS;
  3520. if ( !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  3521. ScepRaiseErrorString(
  3522. hSection,
  3523. KeyName ? KeyName : pGroup->GroupName,
  3524. szMembers
  3525. );
  3526. }
  3527. continue;
  3528. } else if ( !NT_SUCCESS(NtStatus) ) {
  3529. Win32rc = RtlNtStatusToDosError(NtStatus);
  3530. ScepLogOutput3(1, Win32rc, SCEDLL_NO_MAPPINGS, pGroup->GroupName);
  3531. rc = ScepDosErrorToSceStatus(Win32rc);
  3532. goto Done;
  3533. }
  3534. if ( GrpId[0] == DOMAIN_GROUP_RID_USERS ) {
  3535. // ||
  3536. // GrpId[0] == DOMAIN_ALIAS_RID_USERS )
  3537. //
  3538. // do not check this one
  3539. //
  3540. if ( !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  3541. ScepRaiseErrorString(
  3542. hSection,
  3543. KeyName ? KeyName : pGroup->GroupName,
  3544. szMembers
  3545. );
  3546. }
  3547. SamFreeMemory(GrpId);
  3548. GrpId = NULL;
  3549. SamFreeMemory(GrpUse);
  3550. GrpUse = NULL;
  3551. continue;
  3552. }
  3553. NtStatus = ScepDomainIdToSid(
  3554. ThisDomainSid,
  3555. GrpId[0],
  3556. &GrpSid
  3557. );
  3558. if ( !NT_SUCCESS(NtStatus) ) {
  3559. Win32rc = RtlNtStatusToDosError(NtStatus);
  3560. rc = ScepDosErrorToSceStatus(Win32rc);
  3561. goto Done;
  3562. }
  3563. // open the group to get a handle
  3564. switch ( GrpUse[0] ) {
  3565. case SidTypeGroup:
  3566. NtStatus = SamOpenGroup(
  3567. ThisDomain,
  3568. GROUP_READ | GROUP_EXECUTE,
  3569. GrpId[0],
  3570. &GroupHandle
  3571. );
  3572. break;
  3573. case SidTypeAlias:
  3574. NtStatus = SamOpenAlias(
  3575. ThisDomain,
  3576. ALIAS_READ | ALIAS_EXECUTE,
  3577. GrpId[0],
  3578. &GroupHandle
  3579. );
  3580. break;
  3581. default:
  3582. NtStatus = STATUS_DATA_ERROR;
  3583. ScepLogOutput3(1, 0, SCEDLL_INVALID_GROUP, pGroup->GroupName);
  3584. }
  3585. if ( !NT_SUCCESS(NtStatus) ) {
  3586. Win32rc = RtlNtStatusToDosError(NtStatus);
  3587. ScepLogOutput3(1, Win32rc,
  3588. SCEDLL_ERROR_OPEN, pGroup->GroupName);
  3589. rc = ScepDosErrorToSceStatus(Win32rc);
  3590. goto Done;
  3591. }
  3592. //
  3593. //
  3594. // compare members for the group
  3595. //
  3596. NtStatus = ScepCompareMembersOfGroup(
  3597. ThisDomain,
  3598. ThisDomainSid,
  3599. PolicyHandle,
  3600. GrpUse[0],
  3601. GroupHandle,
  3602. pGroup->pMembers,
  3603. &pGroupMembers,
  3604. &bDifferent
  3605. );
  3606. if ( !NT_SUCCESS(NtStatus) ) {
  3607. Win32rc = RtlNtStatusToDosError(NtStatus);
  3608. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ANALYZE_MEMBERS, pGroup->GroupName);
  3609. rc = ScepDosErrorToSceStatus(Win32rc);
  3610. if ( STATUS_NONE_MAPPED == NtStatus ) {
  3611. SamFreeMemory(GrpId);
  3612. GrpId = NULL;
  3613. SamFreeMemory(GrpUse);
  3614. GrpUse = NULL;
  3615. ScepFree(GrpSid);
  3616. GrpSid = NULL;
  3617. SamCloseHandle(GroupHandle);
  3618. GroupHandle = NULL;
  3619. continue;
  3620. } else {
  3621. goto Done;
  3622. }
  3623. }
  3624. //
  3625. // save members for the group
  3626. // if there is any member difference, then save the whole member list
  3627. //
  3628. if ( bDifferent || ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  3629. (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS) ) ) {
  3630. //
  3631. // not same members, or not configured. Save pGroupMembers now
  3632. //
  3633. rc = ScepSaveMemberMembershipList(
  3634. PolicyHandle,
  3635. szMembers,
  3636. KeyName ? KeyName : pGroup->GroupName,
  3637. GroupLen,
  3638. pGroupMembers,
  3639. ( pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS ) ? 2 : 1
  3640. );
  3641. }
  3642. ScepFreeNameList(pGroupMembers);
  3643. pGroupMembers = NULL;
  3644. //
  3645. // get memberof list
  3646. //
  3647. NtStatus = ScepGetGroupsForAccount(
  3648. DomainHandle,
  3649. BuiltinDomainHandle,
  3650. GroupHandle,
  3651. GrpSid,
  3652. &pGroupsMemberof
  3653. );
  3654. if ( !NT_SUCCESS(NtStatus) ) {
  3655. Win32rc = RtlNtStatusToDosError(NtStatus);
  3656. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ANALYZE_MEMBEROF, pGroup->GroupName);
  3657. rc = ScepDosErrorToSceStatus(Win32rc);
  3658. goto Done;
  3659. }
  3660. //
  3661. // not configured, or compare and save MemberOf for the group
  3662. // pMemberOf must not have domain prefix because they must be alias
  3663. //
  3664. if ( ( pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF ) ||
  3665. SceCompareNameList(pGroup->pMemberOf, pGroupsMemberof) == FALSE ) {
  3666. //
  3667. // there is difference. Save the memberOf
  3668. //
  3669. INT iStat = 0;
  3670. if ( (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ||
  3671. (pGroup->pMemberOf == NULL) ) {
  3672. iStat = 2;
  3673. } else {
  3674. iStat = 1;
  3675. }
  3676. rc = ScepSaveMemberMembershipList(
  3677. PolicyHandle,
  3678. szMemberof,
  3679. KeyName ? KeyName : pGroup->GroupName,
  3680. GroupLen,
  3681. pGroupsMemberof,
  3682. iStat
  3683. );
  3684. }
  3685. ScepFreeNameList(pGroupsMemberof);
  3686. pGroupsMemberof = NULL;
  3687. SamFreeMemory(GrpId);
  3688. GrpId = NULL;
  3689. SamFreeMemory(GrpUse);
  3690. GrpUse = NULL;
  3691. ScepFree(GrpSid);
  3692. GrpSid = NULL;
  3693. SamCloseHandle(GroupHandle);
  3694. GroupHandle = NULL;
  3695. }
  3696. Done:
  3697. if ( KeyName != NULL )
  3698. ScepFree(KeyName);
  3699. if ( GrpId != NULL )
  3700. SamFreeMemory(GrpId);
  3701. if ( GrpUse != NULL )
  3702. SamFreeMemory(GrpUse);
  3703. if ( GrpSid != NULL )
  3704. ScepFree(GrpSid);
  3705. if ( pGroupMembers != NULL )
  3706. ScepFreeNameList( pGroupMembers );
  3707. if ( pGroupsMemberof != NULL )
  3708. ScepFreeNameList( pGroupsMemberof );
  3709. if ( pPrivilegesHeld != NULL )
  3710. ScepFreeNameStatusList( pPrivilegesHeld );
  3711. SamCloseHandle(GroupHandle);
  3712. //
  3713. // raise groups that are errored
  3714. //
  3715. if ( !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  3716. for ( PSCE_GROUP_MEMBERSHIP pTmpGrp=pGroup;
  3717. pTmpGrp != NULL; pTmpGrp = pTmpGrp->Next ) {
  3718. if ( pTmpGrp->GroupName == NULL ) {
  3719. continue;
  3720. }
  3721. if ( pTmpGrp->Status & SCE_GROUP_STATUS_DONE_IN_DS ) {
  3722. continue;
  3723. }
  3724. if ( wcschr(pTmpGrp->GroupName, L'\\') ) {
  3725. ScepConvertNameToSidString(
  3726. PolicyHandle,
  3727. pTmpGrp->GroupName,
  3728. FALSE,
  3729. &KeyName,
  3730. &GroupLen
  3731. );
  3732. } else {
  3733. if ( !ScepLookupWellKnownName(
  3734. pTmpGrp->GroupName,
  3735. PolicyHandle,
  3736. &KeyName ) ) {
  3737. KeyName = NULL;
  3738. }
  3739. }
  3740. ScepRaiseErrorString(
  3741. hSection,
  3742. KeyName ? KeyName : pTmpGrp->GroupName,
  3743. szMembers
  3744. );
  3745. if ( KeyName ) {
  3746. LocalFree(KeyName);
  3747. KeyName = NULL;
  3748. }
  3749. }
  3750. }
  3751. LsaClose( PolicyHandle);
  3752. SamCloseHandle( DomainHandle );
  3753. SamCloseHandle( BuiltinDomainHandle );
  3754. SamCloseHandle( ServerHandle );
  3755. if ( DomainSid != NULL ) {
  3756. SamFreeMemory(DomainSid);
  3757. }
  3758. if ( BuiltinDomainSid != NULL ) {
  3759. RtlFreeSid(BuiltinDomainSid);
  3760. }
  3761. //
  3762. // post progress to the end of this area
  3763. //
  3764. if ( nGroupCount < TICKS_GROUPS ) {
  3765. ScepPostProgress(TICKS_GROUPS-nGroupCount,
  3766. AREA_GROUP_MEMBERSHIP,
  3767. NULL);
  3768. }
  3769. return(rc);
  3770. }
  3771. SCESTATUS
  3772. ScepSaveMemberMembershipList(
  3773. IN LSA_HANDLE LsaPolicy,
  3774. IN PCWSTR szSuffix,
  3775. IN PWSTR GroupName,
  3776. IN DWORD GroupLen,
  3777. IN PSCE_NAME_LIST pList,
  3778. IN INT Status
  3779. )
  3780. {
  3781. PWSTR KeyName;
  3782. SCESTATUS rc;
  3783. if ( szSuffix == NULL || GroupName == NULL || GroupLen == 0 ) {
  3784. return(SCESTATUS_INVALID_PARAMETER);
  3785. }
  3786. KeyName = (PWSTR)ScepAlloc(0, (GroupLen+wcslen(szSuffix)+1)*sizeof(WCHAR));
  3787. if ( KeyName != NULL ) {
  3788. swprintf(KeyName, L"%s%s", GroupName, szSuffix);
  3789. rc = ScepWriteNameListValue(
  3790. LsaPolicy,
  3791. hSection,
  3792. KeyName,
  3793. pList,
  3794. SCE_WRITE_EMPTY_LIST | SCE_WRITE_CONVERT,
  3795. Status
  3796. );
  3797. if ( rc != SCESTATUS_SUCCESS ) {
  3798. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  3799. SCEDLL_SAP_ERROR_SAVE, GroupName);
  3800. }
  3801. ScepFree(KeyName);
  3802. } else
  3803. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3804. return(rc);
  3805. }
  3806. NTSTATUS
  3807. ScepCompareMembersOfGroup(
  3808. IN SAM_HANDLE DomainHandle,
  3809. IN PSID ThisDomainSid,
  3810. IN LSA_HANDLE PolicyHandle,
  3811. IN SID_NAME_USE GrpUse,
  3812. IN SAM_HANDLE GroupHandle,
  3813. IN PSCE_NAME_LIST pChkMembers,
  3814. OUT PSCE_NAME_LIST *ppMembers,
  3815. OUT PBOOL bDifferent
  3816. )
  3817. /* ++
  3818. Routine Description:
  3819. This routine compares members in a group GroupHandle in the domain specified
  3820. by ThisDomainSid with the pChkMembers list. If there is mismatch, the current
  3821. members are added to the output list ppMembers. The domain can be account
  3822. domain or the builtin domain. Groups can be global groups or aliases, indicated
  3823. by GrpUse.
  3824. Arguments:
  3825. ThisDomainSid - The domain SID
  3826. PolicyHandle - The LSA policy handle
  3827. GrpUse - The "type" of the group
  3828. GroupHandle - the group handle
  3829. pChkMembers - The member list to check with
  3830. ppMembers - The group members list to output
  3831. Return value:
  3832. NTSTATUS
  3833. -- */
  3834. {
  3835. NTSTATUS NtStatus=ERROR_SUCCESS;
  3836. PULONG MemberIds=NULL;
  3837. PULONG Attributes=NULL;
  3838. ULONG MemberCount=0;
  3839. PUNICODE_STRING Names=NULL;
  3840. PSID_NAME_USE Use=NULL;
  3841. PSID *MemberAliasSids=NULL;
  3842. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains=NULL;
  3843. PLSA_TRANSLATED_NAME LsaNames=NULL;
  3844. PUNICODE_STRING MemberNames=NULL;
  3845. PSID *Sids=NULL;
  3846. ULONG ChkCount=0;
  3847. DWORD i, j;
  3848. DWORD rc;
  3849. BOOL bMismatch;
  3850. *ppMembers = NULL;
  3851. *bDifferent = FALSE;
  3852. switch ( GrpUse ) {
  3853. case SidTypeGroup:
  3854. NtStatus = SamGetMembersInGroup(
  3855. GroupHandle,
  3856. &MemberIds,
  3857. &Attributes,
  3858. &MemberCount
  3859. );
  3860. if ( !NT_SUCCESS(NtStatus) )
  3861. goto Done;
  3862. //
  3863. // group members only exist in the same domain as the group
  3864. //
  3865. if ( MemberCount > 0 ) {
  3866. NtStatus = SamLookupIdsInDomain(
  3867. DomainHandle,
  3868. MemberCount,
  3869. MemberIds,
  3870. &Names,
  3871. &Use
  3872. );
  3873. }
  3874. break;
  3875. case SidTypeAlias:
  3876. //
  3877. // members of alias may exist in everywhere
  3878. //
  3879. NtStatus = SamGetMembersInAlias(
  3880. GroupHandle,
  3881. &MemberAliasSids,
  3882. &MemberCount
  3883. );
  3884. break;
  3885. default:
  3886. NtStatus = STATUS_DATA_ERROR;
  3887. ScepLogOutput3(1, 0, SCEDLL_INVALID_GROUP);
  3888. return(NtStatus);
  3889. }
  3890. if ( !NT_SUCCESS(NtStatus) )
  3891. goto Done;
  3892. if ( GrpUse == SidTypeGroup ) {
  3893. //
  3894. // add members to the list
  3895. // DomainHandle must point to a account domain because builtin domain
  3896. // won't have SidTypeGroup account
  3897. //
  3898. PDOMAIN_NAME_INFORMATION DomainName=NULL;
  3899. SamQueryInformationDomain(
  3900. DomainHandle,
  3901. DomainNameInformation,
  3902. (PVOID *)&DomainName
  3903. );
  3904. for (j=0; j<MemberCount; j++) {
  3905. if ( Names[j].Length <= 0 )
  3906. continue;
  3907. if ( DomainName && DomainName->DomainName.Length > 0 &&
  3908. DomainName->DomainName.Buffer ) {
  3909. rc = ScepAddTwoNamesToNameList(
  3910. ppMembers,
  3911. TRUE,
  3912. DomainName->DomainName.Buffer,
  3913. DomainName->DomainName.Length/2,
  3914. Names[j].Buffer,
  3915. Names[j].Length/2
  3916. );
  3917. } else {
  3918. rc = ScepAddToNameList(ppMembers, Names[j].Buffer, Names[j].Length/2);
  3919. }
  3920. #ifdef SCE_DBG
  3921. wprintf(L"rc=%d, Add %s to Members list\n", rc, Names[j].Buffer);
  3922. #endif
  3923. }
  3924. // compare with pChkMembers
  3925. if ( !(gOptions & SCE_NO_ANALYZE) && ScepCompareGroupNameList(&(DomainName->DomainName),
  3926. pChkMembers,
  3927. *ppMembers) == TRUE ) {
  3928. //
  3929. // it is same. return NULL for ppMembers
  3930. //
  3931. ScepFreeNameList(*ppMembers);
  3932. *ppMembers = NULL;
  3933. } else {
  3934. *bDifferent = TRUE;
  3935. }
  3936. if ( DomainName ) {
  3937. SamFreeMemory(DomainName);
  3938. DomainName = NULL;
  3939. }
  3940. } else { // alias
  3941. // translate pChkMembers to Sids
  3942. NtStatus = ScepGetMemberListSids(
  3943. ThisDomainSid,
  3944. PolicyHandle,
  3945. pChkMembers,
  3946. &MemberNames,
  3947. &Sids,
  3948. &ChkCount
  3949. );
  3950. bMismatch = FALSE;
  3951. //
  3952. // if returned error, we consider the members different
  3953. //
  3954. if ( NT_SUCCESS(NtStatus) && !(gOptions & SCE_NO_ANALYZE) ) {
  3955. /*
  3956. // The number of members on system and in the configuration must match, including
  3957. // unmapped accounts.
  3958. DWORD newCount=0;
  3959. for ( i=0; i<ChkCount; i++ )
  3960. if ( Sids[i] != NULL ) newCount++;
  3961. if ( newCount == MemberCount ) {
  3962. */
  3963. if ( ChkCount == MemberCount ) {
  3964. for ( i=0; i<ChkCount; i++ ) {
  3965. if ( Sids[i] != NULL ) {
  3966. for ( j=0; j<MemberCount; j++ ) {
  3967. if ( Sids[i] != NULL && MemberAliasSids[j] != NULL &&
  3968. EqualSid(Sids[i], MemberAliasSids[j]) )
  3969. break;
  3970. }
  3971. if ( j >= MemberCount )
  3972. // not find a match
  3973. break;
  3974. } else {
  3975. // a mismatch for unmapped account
  3976. break;
  3977. }
  3978. }
  3979. if ( i < ChkCount )
  3980. // something mismatch
  3981. bMismatch = TRUE;
  3982. } else
  3983. bMismatch = TRUE;
  3984. } else if ( NtStatus != STATUS_NO_MEMORY ) {
  3985. NtStatus = STATUS_SUCCESS;
  3986. bMismatch = TRUE;
  3987. }
  3988. *bDifferent = bMismatch;
  3989. if ( bMismatch ) {
  3990. //
  3991. // translate SID into names
  3992. //
  3993. if ( MemberCount > 0 ) {
  3994. NtStatus = LsaLookupSids(
  3995. PolicyHandle,
  3996. MemberCount,
  3997. MemberAliasSids,
  3998. &ReferencedDomains,
  3999. &LsaNames
  4000. );
  4001. if ( !NT_SUCCESS(NtStatus) )
  4002. goto Done;
  4003. }
  4004. //
  4005. // add members to the list to output
  4006. //
  4007. PWSTR StringSid;
  4008. for (j=0; j<MemberCount; j++) {
  4009. //
  4010. // shouldn't ignore the unknown accounts
  4011. // they might be unresolvable at this moment - show SID string instead
  4012. //
  4013. // if ( LsaNames[j].Name.Length <= 0 )
  4014. // continue;
  4015. if ( LsaNames[j].Use == SidTypeInvalid ||
  4016. LsaNames[j].Use == SidTypeUnknown ||
  4017. LsaNames[j].Name.Length <= 0 ) {
  4018. //
  4019. // convert SID to sid string
  4020. //
  4021. if ( ScepConvertSidToPrefixStringSid(
  4022. MemberAliasSids[j],
  4023. &StringSid) ) {
  4024. ScepAddToNameList(ppMembers, StringSid, 0);
  4025. ScepFree(StringSid);
  4026. StringSid = NULL;
  4027. }
  4028. continue;
  4029. }
  4030. if ( ReferencedDomains->Entries > 0 && LsaNames[0].Use != SidTypeWellKnownGroup &&
  4031. ReferencedDomains->Domains != NULL &&
  4032. LsaNames[j].DomainIndex != -1 &&
  4033. (ULONG)(LsaNames[j].DomainIndex) < ReferencedDomains->Entries &&
  4034. ScepIsSidFromAccountDomain( ReferencedDomains->Domains[LsaNames[j].DomainIndex].Sid ) ) {
  4035. //
  4036. // should add both the domain name and the account name
  4037. //
  4038. rc = ScepAddTwoNamesToNameList(
  4039. ppMembers,
  4040. TRUE,
  4041. ReferencedDomains->Domains[LsaNames[j].DomainIndex].Name.Buffer,
  4042. ReferencedDomains->Domains[LsaNames[j].DomainIndex].Name.Length/2,
  4043. LsaNames[j].Name.Buffer,
  4044. LsaNames[j].Name.Length/2
  4045. );
  4046. #ifdef SCE_DBG
  4047. wprintf(L"rc=%d, Add %s\\%s to Members list\n", rc,
  4048. ReferencedDomains->Domains[LsaNames[j].DomainIndex].Name.Buffer, LsaNames[j].Name.Buffer);
  4049. #endif
  4050. } else {
  4051. rc = ScepAddToNameList(ppMembers, LsaNames[j].Name.Buffer, LsaNames[j].Name.Length/2);
  4052. #ifdef SCE_DBG
  4053. wprintf(L"rc=%d, Add %s to Members list\n", rc, LsaNames[j].Name.Buffer);
  4054. #endif
  4055. }
  4056. if ( rc != NO_ERROR) {
  4057. NtStatus = STATUS_NO_MEMORY;
  4058. goto Done;
  4059. }
  4060. }
  4061. }
  4062. }
  4063. Done:
  4064. if (Use != NULL)
  4065. SamFreeMemory(Use);
  4066. if (Names != NULL)
  4067. SamFreeMemory(Names);
  4068. if (MemberIds != NULL)
  4069. SamFreeMemory(MemberIds);
  4070. if (Attributes != NULL)
  4071. SamFreeMemory(Attributes);
  4072. if (MemberAliasSids != NULL)
  4073. SamFreeMemory(MemberAliasSids);
  4074. if (ReferencedDomains != NULL)
  4075. LsaFreeMemory(ReferencedDomains);
  4076. if (LsaNames != NULL)
  4077. LsaFreeMemory(LsaNames);
  4078. if ( Sids != NULL ) {
  4079. for ( i=0; i<ChkCount; i++ ) {
  4080. if ( Sids[i] != NULL )
  4081. ScepFree( Sids[i] );
  4082. }
  4083. ScepFree( Sids );
  4084. }
  4085. if ( MemberNames != NULL )
  4086. RtlFreeHeap(RtlProcessHeap(), 0, MemberNames);
  4087. return(NtStatus);
  4088. }
  4089. SCESTATUS
  4090. ScepEnumerateRegistryRoots(
  4091. OUT PSCE_OBJECT_LIST *pRoots
  4092. )
  4093. /*
  4094. Routine Description:
  4095. Enumerate all registry roots (MACHINE, USERS, CURRENT_USER, CLASSES_ROOT,
  4096. and CONFIG) and add them to pRoots. If the root is already in the list,
  4097. ignore the addition.
  4098. This routine is used for analysis of all registry roots no matter if the
  4099. root is specified in the profile.
  4100. Arguments:
  4101. pRoots - the object list to add to
  4102. Return Value:
  4103. SCESTATUS_SUCCESS
  4104. SCESTATUS_NOT_ENOUGH_RESOURCE
  4105. */
  4106. {
  4107. DWORD rc;
  4108. rc = ScepAddToObjectList(
  4109. pRoots,
  4110. L"MACHINE",
  4111. 7,
  4112. TRUE,
  4113. SCE_STATUS_IGNORE,
  4114. 0,
  4115. SCE_CHECK_DUP //TRUE // check for duplicate
  4116. );
  4117. if ( rc != ERROR_SUCCESS ) {
  4118. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ADD, L"MACHINE");
  4119. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  4120. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4121. }
  4122. }
  4123. //
  4124. // ignore invalid parameter error and continue
  4125. //
  4126. rc = ScepAddToObjectList(
  4127. pRoots,
  4128. L"USERS",
  4129. 5,
  4130. TRUE,
  4131. SCE_STATUS_IGNORE,
  4132. 0,
  4133. SCE_CHECK_DUP // TRUE
  4134. );
  4135. if ( rc != ERROR_SUCCESS ) {
  4136. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ADD, L"USERS");
  4137. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  4138. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4139. }
  4140. }
  4141. //
  4142. // ignore invalid parameter error and continue
  4143. //
  4144. rc = ScepAddToObjectList(
  4145. pRoots,
  4146. L"CLASSES_ROOT",
  4147. 12,
  4148. TRUE,
  4149. SCE_STATUS_IGNORE,
  4150. 0,
  4151. SCE_CHECK_DUP //TRUE
  4152. );
  4153. if ( rc != ERROR_SUCCESS ) {
  4154. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ADD, L"CLASSES_ROOT");
  4155. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  4156. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4157. }
  4158. }
  4159. return(SCESTATUS_SUCCESS);
  4160. }
  4161. SCESTATUS
  4162. ScepEnumerateFileRoots(
  4163. OUT PSCE_OBJECT_LIST *pRoots
  4164. )
  4165. /*
  4166. Routine Description:
  4167. Add all local disk drives (DRIVE_FIXED, DRIVE_REMOVABLE, DRIVE_RAMDISK)
  4168. to the list if they are not in the list. The drive is added to the list
  4169. in the format of a drive letter plus ":\". If the drive is already in
  4170. the list, ignore the addition.
  4171. This routine is used for analysis of all disk drives no matter if the
  4172. drive is specified in the profile.
  4173. Arguments:
  4174. pRoots - the object list to add to
  4175. Return Value:
  4176. SCESTATUS_SUCCESS
  4177. SCESTATUS_NOT_ENOUGH_RESOURCE
  4178. */
  4179. {
  4180. SCESTATUS rc=SCESTATUS_SUCCESS;
  4181. DWORD Length;
  4182. TCHAR Drives[128]; // 128 characters is enough for 32 drives
  4183. PWSTR pTemp;
  4184. UINT dType;
  4185. DWORD Len;
  4186. memset(Drives, '\0', 256);
  4187. Length = GetLogicalDriveStrings(127, Drives);
  4188. if ( Length > 0 ) {
  4189. pTemp = Drives;
  4190. while ( *pTemp != L'\0') {
  4191. dType = GetDriveType(pTemp);
  4192. Len = wcslen(pTemp);
  4193. if ( dType == DRIVE_FIXED ||
  4194. dType == DRIVE_RAMDISK ) {
  4195. //
  4196. // add this to the root object list (check duplicate)
  4197. //
  4198. pTemp[Len-1] = L'\0'; // take out the '\'
  4199. rc = ScepAddToObjectList(
  4200. pRoots,
  4201. pTemp,
  4202. Len-1, // only drive letter and ':' is added
  4203. TRUE,
  4204. SCE_STATUS_IGNORE,
  4205. 0,
  4206. SCE_CHECK_DUP // TRUE
  4207. );
  4208. if ( rc != ERROR_SUCCESS ) {
  4209. //
  4210. // Log the error and continue
  4211. //
  4212. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ADD, pTemp);
  4213. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  4214. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4215. break;
  4216. } else {
  4217. // ignore other errors
  4218. rc = SCESTATUS_SUCCESS;
  4219. }
  4220. }
  4221. }
  4222. //
  4223. // go to next drive
  4224. //
  4225. pTemp += (Len + 1);
  4226. }
  4227. } else {
  4228. //
  4229. // ignore this error, only log it
  4230. //
  4231. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"file system");
  4232. }
  4233. return(rc);
  4234. }
  4235. SCESTATUS
  4236. ScepAnalyzeObjectSecurity(
  4237. IN PSCE_OBJECT_LIST pRoots,
  4238. IN AREA_INFORMATION Area,
  4239. IN BOOL bSystemDb
  4240. )
  4241. /* ++
  4242. Routine Description:
  4243. Analyze the security setting on objects (registry keys, files, etc) as
  4244. specified in pObjectCheckList. The Recursive is TRUE, all sub keys/
  4245. directories under a object will be checked too. All checked objects
  4246. and their security settings are returned in ppObjectChecked
  4247. Arguments:
  4248. pObjectCheckList - a n-tree of objects to check
  4249. ObjectType - Indicate permission or auditing
  4250. Recursive - TRUE = check all subkeys/directories
  4251. Return value:
  4252. SCESTATUS error codes
  4253. ++ */
  4254. {
  4255. SCESTATUS rc;
  4256. DWORD Win32rc=NO_ERROR;
  4257. HANDLE Token;
  4258. PSCE_OBJECT_LIST pOneRoot;
  4259. PSCE_OBJECT_CHILD_LIST pSecurityObject=NULL;
  4260. PCWSTR SectionName=NULL;
  4261. DWORD FileSystemFlags;
  4262. PSCE_OBJECT_LIST pTempRoot=NULL;
  4263. WCHAR theDrive[4];
  4264. UINT DriveType;
  4265. if ( pRoots == NULL && Area != AREA_DS_OBJECTS ) {
  4266. return(SCESTATUS_SUCCESS);
  4267. }
  4268. switch (Area) {
  4269. case AREA_REGISTRY_SECURITY:
  4270. SectionName = szRegistryKeys;
  4271. break;
  4272. case AREA_FILE_SECURITY:
  4273. SectionName = szFileSecurity;
  4274. break;
  4275. #if 0
  4276. case AREA_DS_OBJECTS:
  4277. SectionName = szDSSecurity;
  4278. break;
  4279. #endif
  4280. default:
  4281. return(SCESTATUS_INVALID_PARAMETER);
  4282. }
  4283. //
  4284. // get current thread/process's token
  4285. //
  4286. if (!OpenThreadToken( GetCurrentThread(),
  4287. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, //TOKEN_ALL_ACCESS,
  4288. TRUE,
  4289. &Token)) {
  4290. if(ERROR_NO_TOKEN == GetLastError()){
  4291. if(!OpenProcessToken( GetCurrentProcess(),
  4292. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  4293. &Token)){
  4294. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  4295. return(ScepDosErrorToSceStatus(GetLastError()));
  4296. }
  4297. } else {
  4298. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  4299. return(ScepDosErrorToSceStatus(GetLastError()));
  4300. }
  4301. }
  4302. //
  4303. // SE_SECURITY_PRIVILEGE, ignore the error if can't adjust privilege
  4304. //
  4305. Win32rc = SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, Token );
  4306. if ( Win32rc != NO_ERROR ) {
  4307. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ADJUST, L"SE_SECURITY_PRIVILEGE");
  4308. }
  4309. //
  4310. // Prepare JET section to write to
  4311. //
  4312. rc = ScepStartANewSection(
  4313. hProfile,
  4314. &hSection,
  4315. SCEJET_TABLE_SAP,
  4316. SectionName
  4317. );
  4318. if ( rc != SCESTATUS_SUCCESS ) {
  4319. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  4320. SCEDLL_SAP_START_SECTION, (PWSTR)SectionName);
  4321. goto Done;
  4322. }
  4323. #if 0
  4324. if ( Area == AREA_DS_OBJECTS && pRoots == NULL ) {
  4325. //
  4326. // nothing specified in the template, then save the domain in SAP
  4327. //
  4328. rc = ScepLdapOpen(NULL);
  4329. if ( rc == SCESTATUS_SUCCESS ) {
  4330. rc = ScepEnumerateDsObjectRoots(NULL, &pTempRoot);
  4331. if ( rc == SCESTATUS_SUCCESS ) {
  4332. rc = ScepSaveDsStatusToSection(
  4333. pTempRoot->Name,
  4334. TRUE,
  4335. SCE_STATUS_NOT_CONFIGURED,
  4336. NULL,
  4337. 0
  4338. );
  4339. ScepFreeObjectList(pTempRoot);
  4340. }
  4341. ScepLdapClose(NULL);
  4342. }
  4343. if ( rc != SCESTATUS_SUCCESS ) {
  4344. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  4345. SCEDLL_SAP_ERROR_SAVE, SectionName);
  4346. }
  4347. }
  4348. #endif
  4349. //
  4350. // Process each root
  4351. // note: SCE_STATUS_NO_AUTO_INHERIT is treated the same as SCE_STATUS_CHECK
  4352. // in analysis
  4353. //
  4354. for ( pOneRoot=pRoots; pOneRoot != NULL; pOneRoot=pOneRoot->Next ) {
  4355. if ( Area == AREA_FILE_SECURITY &&
  4356. (pOneRoot->Status == SCE_STATUS_CHECK ||
  4357. pOneRoot->Status == SCE_STATUS_NO_AUTO_INHERIT ||
  4358. pOneRoot->Status == SCE_STATUS_OVERWRITE) ) {
  4359. //
  4360. // make sure the input data follows file format
  4361. //
  4362. if ( pOneRoot->Name[1] != L'\0' && pOneRoot->Name[1] != L':') {
  4363. ScepLogOutput3(1, ERROR_INVALID_DATA, SCEDLL_CANNOT_FIND, pOneRoot->Name);
  4364. rc = ScepSaveObjectString(
  4365. hSection,
  4366. pOneRoot->Name,
  4367. FALSE,
  4368. SCE_STATUS_ERROR_NOT_AVAILABLE,
  4369. NULL,
  4370. 0
  4371. );
  4372. continue;
  4373. }
  4374. //
  4375. // check if support acl
  4376. //
  4377. theDrive[0] = pOneRoot->Name[0];
  4378. theDrive[1] = L':';
  4379. theDrive[2] = L'\\';
  4380. theDrive[3] = L'\0';
  4381. DriveType = GetDriveType(theDrive);
  4382. if ( DriveType == DRIVE_FIXED ||
  4383. DriveType == DRIVE_RAMDISK ) {
  4384. if ( GetVolumeInformation(theDrive,
  4385. NULL,
  4386. 0,
  4387. NULL,
  4388. NULL,
  4389. &FileSystemFlags,
  4390. NULL,
  4391. 0
  4392. ) ) {
  4393. if ( !( FileSystemFlags & FS_PERSISTENT_ACLS) ) {
  4394. pOneRoot->Status = SCE_STATUS_NO_ACL_SUPPORT;
  4395. rc = ScepSaveObjectString(
  4396. hSection,
  4397. theDrive,
  4398. TRUE,
  4399. SCE_STATUS_NO_ACL_SUPPORT,
  4400. NULL,
  4401. 0
  4402. );
  4403. if ( rc != SCESTATUS_SUCCESS )
  4404. goto Done;
  4405. continue;
  4406. }
  4407. } else {
  4408. //
  4409. // ignore the error and treat the drive as NTFS
  4410. // if it is not, it will error out later
  4411. //
  4412. ScepLogOutput3(1, GetLastError(),
  4413. SCEDLL_ERROR_QUERY_VOLUME, theDrive);
  4414. }
  4415. } else {
  4416. rc = ScepSaveObjectString(
  4417. hSection,
  4418. theDrive,
  4419. TRUE,
  4420. SCE_STATUS_NO_ACL_SUPPORT,
  4421. NULL,
  4422. 0
  4423. );
  4424. if ( rc != SCESTATUS_SUCCESS )
  4425. goto Done;
  4426. continue;
  4427. }
  4428. }
  4429. if ( pOneRoot->Status != SCE_STATUS_CHECK &&
  4430. pOneRoot->Status != SCE_STATUS_NO_AUTO_INHERIT &&
  4431. pOneRoot->Status != SCE_STATUS_OVERWRITE ) {
  4432. //
  4433. // log a point in SAP for not analyzing
  4434. //
  4435. if ( Area == AREA_DS_OBJECTS ) {
  4436. rc = ScepSaveDsStatusToSection(
  4437. pOneRoot->Name,
  4438. TRUE,
  4439. SCE_STATUS_NOT_CONFIGURED,
  4440. NULL,
  4441. 0
  4442. );
  4443. } else {
  4444. rc = ScepSaveObjectString(
  4445. hSection,
  4446. pOneRoot->Name,
  4447. TRUE,
  4448. SCE_STATUS_NOT_CONFIGURED,
  4449. NULL,
  4450. 0
  4451. );
  4452. }
  4453. if ( rc != SCESTATUS_SUCCESS )
  4454. goto Done;
  4455. continue;
  4456. }
  4457. //
  4458. // read scp information for this area
  4459. //
  4460. rc = ScepGetOneSection(
  4461. hProfile,
  4462. Area,
  4463. pOneRoot->Name,
  4464. bSystemDb ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  4465. (PVOID *)&pSecurityObject
  4466. );
  4467. if ( rc != SCESTATUS_SUCCESS )
  4468. goto Done;
  4469. if ( pSecurityObject == NULL ) {
  4470. continue;
  4471. }
  4472. //
  4473. // then process each node in the list
  4474. //
  4475. for (PSCE_OBJECT_CHILD_LIST pTemp = pSecurityObject; pTemp != NULL; pTemp=pTemp->Next) {
  4476. if ( pTemp->Node == NULL ) continue;
  4477. if ( Area == AREA_FILE_SECURITY ) {
  4478. if ( pTemp->Node->ObjectFullName[1] == L':' &&
  4479. pTemp->Node->ObjectFullName[2] == L'\0' ) {
  4480. pTemp->Node->ObjectFullName[2] = L'\\';
  4481. pTemp->Node->ObjectFullName[3] = L'\0';
  4482. }
  4483. }
  4484. //
  4485. // compute the "real" security descriptor for each node,
  4486. // Ds objects DO NOT need to be computed
  4487. //
  4488. if ( Area == AREA_FILE_SECURITY ) {
  4489. rc = ScepCalculateSecurityToApply(
  4490. pTemp->Node,
  4491. SE_FILE_OBJECT,
  4492. Token,
  4493. &FileGenericMapping
  4494. );
  4495. } else if ( Area == AREA_REGISTRY_SECURITY ) {
  4496. rc = ScepCalculateSecurityToApply(
  4497. pTemp->Node,
  4498. SE_REGISTRY_KEY,
  4499. Token,
  4500. &KeyGenericMapping
  4501. );
  4502. }
  4503. if ( rc != SCESTATUS_SUCCESS ) {
  4504. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  4505. SCEDLL_ERROR_COMPUTESD,
  4506. pTemp->Node->ObjectFullName);
  4507. goto Done;
  4508. } else {
  4509. BadCnt = 0;
  4510. if ( Area == AREA_FILE_SECURITY ) {
  4511. //
  4512. // analyze file object tree
  4513. //
  4514. Win32rc = ScepAnalyzeOneObjectInTree(
  4515. pTemp->Node,
  4516. SE_FILE_OBJECT,
  4517. Token,
  4518. &FileGenericMapping
  4519. );
  4520. } else if ( Area == AREA_REGISTRY_SECURITY ) {
  4521. //
  4522. // analyze registry object tree
  4523. //
  4524. Win32rc = ScepAnalyzeOneObjectInTree(
  4525. pTemp->Node,
  4526. SE_REGISTRY_KEY,
  4527. Token,
  4528. &KeyGenericMapping
  4529. );
  4530. } else {
  4531. //
  4532. // analyze ds objects
  4533. //
  4534. Win32rc = ScepAnalyzeDsSecurity( pTemp->Node );
  4535. }
  4536. ScepLogOutput3(0, Win32rc, IDS_ANALYSIS_MISMATCH,
  4537. BadCnt, pTemp->Node->ObjectFullName);
  4538. rc = ScepDosErrorToSceStatus(Win32rc);
  4539. }
  4540. if ( rc != ERROR_SUCCESS ) {
  4541. break;
  4542. }
  4543. }
  4544. ScepFreeObject2Security( pSecurityObject, FALSE);
  4545. pSecurityObject = NULL;
  4546. }
  4547. Done:
  4548. //
  4549. // if privilege is adjusted, turn it off.
  4550. //
  4551. SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, Token );
  4552. CloseHandle(Token);
  4553. if ( pSecurityObject != NULL )
  4554. ScepFreeObject2Security( pSecurityObject, FALSE);
  4555. return(rc);
  4556. }
  4557. DWORD
  4558. ScepAnalyzeOneObjectInTree(
  4559. IN PSCE_OBJECT_TREE ThisNode,
  4560. IN SE_OBJECT_TYPE ObjectType,
  4561. IN HANDLE Token,
  4562. IN PGENERIC_MAPPING GenericMapping
  4563. )
  4564. /* ++
  4565. Routine Description:
  4566. Recursively Analyze each node in the object tree. If Recursive is set to
  4567. TRUE, all sub keys/directories under an node will be analyzed too. All
  4568. files/directories with DIFFERENT security setting from the profile are
  4569. returned in ppObjectChecked.
  4570. Arguments:
  4571. ThisNode - one node in the n-tree to analyze
  4572. ObjectType - Indicate file object or registry object
  4573. Token - thread token used to compute creator owner
  4574. GenericMapping - generic access mapping
  4575. Return value:
  4576. SCESTATUS error codes
  4577. ++ */
  4578. {
  4579. DWORD rc=NO_ERROR;
  4580. BOOL StartChecking = FALSE;
  4581. PSCE_OBJECT_TREE pTempNode;
  4582. if ( ThisNode == NULL ) {
  4583. return(SCESTATUS_SUCCESS);
  4584. }
  4585. if ( ThisNode->Status != SCE_STATUS_CHECK &&
  4586. ThisNode->Status != SCE_STATUS_NO_AUTO_INHERIT &&
  4587. ThisNode->Status != SCE_STATUS_OVERWRITE ) {
  4588. //
  4589. // Log a point in SAP
  4590. //
  4591. rc = ScepSaveObjectString(
  4592. hSection,
  4593. ThisNode->ObjectFullName,
  4594. ThisNode->IsContainer,
  4595. SCE_STATUS_NOT_CONFIGURED,
  4596. NULL,
  4597. 0
  4598. );
  4599. goto SkipNode;
  4600. }
  4601. if ( ThisNode->pSecurityDescriptor != NULL ) {
  4602. //
  4603. // notify the progress bar if there is any
  4604. //
  4605. switch(ObjectType) {
  4606. case SE_FILE_OBJECT:
  4607. ScepPostProgress(1, AREA_FILE_SECURITY, ThisNode->ObjectFullName);
  4608. break;
  4609. case SE_REGISTRY_KEY:
  4610. ScepPostProgress(1, AREA_REGISTRY_SECURITY, ThisNode->ObjectFullName);
  4611. break;
  4612. default:
  4613. ScepPostProgress(1, 0, ThisNode->ObjectFullName);
  4614. break;
  4615. }
  4616. }
  4617. //
  4618. // find if this is the first node in this path to be configured
  4619. //
  4620. for ( pTempNode=ThisNode; pTempNode != NULL;
  4621. pTempNode = pTempNode->Parent ) {
  4622. if ( NULL != pTempNode->pApplySecurityDescriptor ) {
  4623. StartChecking = TRUE;
  4624. break;
  4625. }
  4626. }
  4627. if ( StartChecking &&
  4628. ( NULL != ThisNode->pSecurityDescriptor) ||
  4629. ( ThisNode->Status == SCE_STATUS_OVERWRITE ) ) {
  4630. //
  4631. // only analyze objects with explicit aces specified,
  4632. // or when parent's status is overwrite
  4633. // if this node doesn't have a SD, it's status is coming from the parent
  4634. //
  4635. // process this node first
  4636. //
  4637. rc = ScepAnalyzeObjectOnly(
  4638. ThisNode->ObjectFullName,
  4639. ThisNode->IsContainer,
  4640. ObjectType,
  4641. ThisNode->pApplySecurityDescriptor,
  4642. ThisNode->SeInfo
  4643. );
  4644. //
  4645. // if the object denies access, skip it.
  4646. //
  4647. if ( rc == ERROR_ACCESS_DENIED ||
  4648. rc == ERROR_CANT_ACCESS_FILE ||
  4649. rc == ERROR_SHARING_VIOLATION) {
  4650. //
  4651. // log a point in SAP for skipping
  4652. //
  4653. gWarningCode = rc;
  4654. goto ProcChild;
  4655. }
  4656. //
  4657. // if the object specified in the profile does not exist, skip it and children
  4658. //
  4659. if ( rc == ERROR_FILE_NOT_FOUND ||
  4660. rc == ERROR_PATH_NOT_FOUND ||
  4661. rc == ERROR_INVALID_HANDLE ) {
  4662. gWarningCode = rc;
  4663. rc = SCESTATUS_SUCCESS;
  4664. goto SkipNode;
  4665. }
  4666. } else {
  4667. //
  4668. // log a point in SAP for not analyzing
  4669. //
  4670. rc = ScepSaveObjectString(
  4671. hSection,
  4672. ThisNode->ObjectFullName,
  4673. ThisNode->IsContainer,
  4674. SCE_STATUS_CHILDREN_CONFIGURED,
  4675. NULL,
  4676. 0
  4677. );
  4678. }
  4679. if ( rc != ERROR_SUCCESS )
  4680. return(rc);
  4681. //
  4682. // only process the child objects if the flag is overwrite
  4683. // because for auto-inherit or no inherit case, all child objects will
  4684. // be enumerated as "N.C." status by GetObjectChildren api.
  4685. //
  4686. PSCE_OBJECT_CHILD_LIST pTemp;
  4687. if ( (StartChecking && ThisNode->Status == SCE_STATUS_OVERWRITE) ) { //||
  4688. // (!StartChecking && NULL != ThisNode->LeftChild ) ) {
  4689. //
  4690. // analyze security for other files/keys under this directory
  4691. // or log SAP point for not analyzing
  4692. //
  4693. DWORD BufSize;
  4694. PWSTR Buffer=NULL;
  4695. INT i;
  4696. DWORD EnumRc=0;
  4697. switch ( ObjectType ) {
  4698. case SE_FILE_OBJECT:
  4699. struct _wfinddata_t * pFileInfo;
  4700. //
  4701. // find all files under this directory/file
  4702. //
  4703. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  4704. if ( pFileInfo == NULL ) {
  4705. rc = ERROR_NOT_ENOUGH_MEMORY;
  4706. break;
  4707. }
  4708. BufSize = wcslen(ThisNode->ObjectFullName)+4;
  4709. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  4710. if ( Buffer == NULL ) {
  4711. ScepFree(pFileInfo);
  4712. pFileInfo = NULL;
  4713. rc = ERROR_NOT_ENOUGH_MEMORY;
  4714. break;
  4715. }
  4716. BOOL BackSlashExist;
  4717. intptr_t hFile;
  4718. BackSlashExist = ScepLastBackSlash(ThisNode->ObjectFullName);
  4719. if ( BackSlashExist )
  4720. swprintf(Buffer, L"%s*.*", ThisNode->ObjectFullName);
  4721. else
  4722. swprintf(Buffer, L"%s\\*.*", ThisNode->ObjectFullName);
  4723. hFile = _wfindfirst(Buffer, pFileInfo);
  4724. ScepFree(Buffer);
  4725. Buffer = NULL;
  4726. if ( hFile != -1 &&
  4727. ( 0 == ( GetFileAttributes(ThisNode->ObjectFullName) & // bug 635098: don't propagate permissions
  4728. FILE_ATTRIBUTE_REPARSE_POINT ))) // across junction points
  4729. {
  4730. do {
  4731. if ( wcscmp(L"..", pFileInfo->name) == 0 ||
  4732. wcscmp(L".", pFileInfo->name) == 0 )
  4733. continue;
  4734. //
  4735. // if the file/subdir is in the children list
  4736. // process it later.
  4737. //
  4738. for ( pTemp = ThisNode->ChildList, i=-1;
  4739. pTemp != NULL;
  4740. pTemp = pTemp->Next ) {
  4741. if ( pTemp->Node == NULL ) continue;
  4742. i=_wcsicmp(pTemp->Node->Name, pFileInfo->name);
  4743. if ( i == 0 )
  4744. break;
  4745. }
  4746. if ( pTemp == NULL || i != 0 ) {
  4747. //
  4748. // The name is not in the list, so analyze this one
  4749. //
  4750. BufSize = wcslen(ThisNode->ObjectFullName)+wcslen(pFileInfo->name)+1;
  4751. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  4752. if ( Buffer == NULL ) {
  4753. rc = ERROR_NOT_ENOUGH_MEMORY;
  4754. break;
  4755. }
  4756. if ( BackSlashExist )
  4757. swprintf(Buffer, L"%s%s", ThisNode->ObjectFullName, pFileInfo->name);
  4758. else
  4759. swprintf(Buffer, L"%s\\%s", ThisNode->ObjectFullName, pFileInfo->name);
  4760. EnumRc = pFileInfo->attrib; // borrow this variable temperaorily
  4761. ScepFree(pFileInfo);
  4762. pFileInfo = NULL;
  4763. // if ( StartChecking ) { // raise N.C. status even for SCE_STATUS_CHECK
  4764. if ( StartChecking && ThisNode->Status == SCE_STATUS_OVERWRITE ) {
  4765. //
  4766. // do not check owner and group information
  4767. //
  4768. if ( EnumRc & _A_SUBDIR ) {
  4769. rc = ScepAnalyzeObjectAndChildren(
  4770. Buffer,
  4771. ObjectType,
  4772. NULL,
  4773. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  4774. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION)
  4775. );
  4776. } else {
  4777. rc = ScepAnalyzeObjectOnly(
  4778. Buffer,
  4779. FALSE,
  4780. ObjectType,
  4781. NULL,
  4782. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  4783. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION)
  4784. );
  4785. }
  4786. } else {
  4787. /*
  4788. //
  4789. // Log the SAP point
  4790. //
  4791. rc = ScepSaveObjectString(
  4792. hSection,
  4793. Buffer,
  4794. (EnumRc & _A_SUBDIR) ? TRUE : FALSE,
  4795. SCE_STATUS_NOT_CONFIGURED,
  4796. NULL,
  4797. 0
  4798. );
  4799. */
  4800. }
  4801. ScepFree(Buffer);
  4802. Buffer = NULL;
  4803. if ( rc != ERROR_SUCCESS )
  4804. break;
  4805. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  4806. if ( pFileInfo == NULL ) {
  4807. rc = ERROR_NOT_ENOUGH_MEMORY;
  4808. break;
  4809. }
  4810. }
  4811. } while ( _wfindnext(hFile, pFileInfo) == 0 );
  4812. _findclose(hFile);
  4813. }
  4814. if ( pFileInfo != NULL ) {
  4815. ScepFree(pFileInfo);
  4816. pFileInfo = NULL;
  4817. }
  4818. break;
  4819. case SE_REGISTRY_KEY:
  4820. PWSTR Buffer1;
  4821. HKEY hKey;
  4822. DWORD index;
  4823. //
  4824. // open the key
  4825. //
  4826. Buffer1=NULL;
  4827. rc = ScepOpenRegistryObject(
  4828. SE_REGISTRY_KEY,
  4829. ThisNode->ObjectFullName,
  4830. KEY_READ,
  4831. &hKey
  4832. );
  4833. if ( rc == ERROR_SUCCESS ) {
  4834. index = 0;
  4835. //
  4836. // enumerate all subkeys of the key
  4837. //
  4838. do {
  4839. Buffer1 = (PWSTR)ScepAlloc(LMEM_ZEROINIT, MAX_PATH*sizeof(WCHAR));
  4840. if ( Buffer1 == NULL ) {
  4841. rc = ERROR_NOT_ENOUGH_MEMORY;
  4842. break;
  4843. }
  4844. BufSize = MAX_PATH;
  4845. EnumRc = RegEnumKeyEx(hKey,
  4846. index,
  4847. Buffer1,
  4848. &BufSize,
  4849. NULL,
  4850. NULL,
  4851. NULL,
  4852. NULL);
  4853. if ( EnumRc == ERROR_SUCCESS ) {
  4854. index++;
  4855. //
  4856. // find if the subkey is already in the tree
  4857. // if it is in the tree, it will be processed later
  4858. //
  4859. for ( pTemp = ThisNode->ChildList, i=-1;
  4860. pTemp != NULL;
  4861. pTemp = pTemp->Next ) {
  4862. if ( pTemp->Node == NULL ) continue;
  4863. i=_wcsicmp(pTemp->Node->Name, Buffer1);
  4864. if ( i >= 0 )
  4865. break;
  4866. }
  4867. if ( pTemp == NULL || i > 0 ) {
  4868. //
  4869. // The name is not in the list
  4870. //
  4871. BufSize += wcslen(ThisNode->ObjectFullName)+1;
  4872. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  4873. if ( Buffer == NULL ) {
  4874. rc = ERROR_NOT_ENOUGH_MEMORY;
  4875. break;
  4876. }
  4877. swprintf(Buffer, L"%s\\%s", ThisNode->ObjectFullName, Buffer1);
  4878. ScepFree(Buffer1);
  4879. Buffer1 = NULL;
  4880. // if ( StartChecking ) { // raise N.C. status even for SCE_STATUS_CHECK
  4881. if ( StartChecking && ThisNode->Status == SCE_STATUS_OVERWRITE ) {
  4882. //
  4883. // do not check owner and group information
  4884. //
  4885. rc = ScepAnalyzeObjectAndChildren(
  4886. Buffer,
  4887. ObjectType,
  4888. NULL,
  4889. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  4890. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION)
  4891. );
  4892. } else {
  4893. /*
  4894. rc = ScepSaveObjectString(
  4895. hSection,
  4896. Buffer,
  4897. TRUE,
  4898. SCE_STATUS_NOT_CONFIGURED,
  4899. NULL,
  4900. 0
  4901. );
  4902. */
  4903. }
  4904. if ( rc != ERROR_SUCCESS )
  4905. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_SECURITY, Buffer);
  4906. ScepFree(Buffer);
  4907. Buffer = NULL;
  4908. if ( rc != ERROR_SUCCESS )
  4909. break;
  4910. }
  4911. } else if ( EnumRc != ERROR_NO_MORE_ITEMS ) {
  4912. //
  4913. // Enumeration shouldn't fail if RegOpenKeyEx works right
  4914. // because the ENUMERATE_SUB_KEYS access was requested in
  4915. // the open call.
  4916. // However, due to a app compat bug (for terminal server)
  4917. // when a registry key is opened with some access rights,
  4918. // it is actually opened with MAXIMUM_ALLOWED for certain
  4919. // keys. This will cause RegEnumKeyEx fail with access denied
  4920. // error.
  4921. // In this case, we treat it the same as the open key failed
  4922. // with the error.
  4923. //
  4924. ScepSaveObjectString(
  4925. hSection,
  4926. ThisNode->ObjectFullName,
  4927. TRUE,
  4928. SCE_STATUS_ERROR_NOT_AVAILABLE,
  4929. NULL,
  4930. 0
  4931. );
  4932. //
  4933. // skip it
  4934. //
  4935. gWarningCode = EnumRc;
  4936. rc = ERROR_SUCCESS;
  4937. }
  4938. if ( Buffer1 != NULL ) {
  4939. ScepFree(Buffer1);
  4940. Buffer1 = NULL;
  4941. }
  4942. } while ( EnumRc == ERROR_SUCCESS );
  4943. RegCloseKey(hKey);
  4944. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  4945. ScepLogOutput3(1, EnumRc, SCEDLL_SAP_ERROR_ENUMERATE,
  4946. ThisNode->ObjectFullName);
  4947. }
  4948. } else {
  4949. ScepSaveObjectString(
  4950. hSection,
  4951. ThisNode->ObjectFullName,
  4952. TRUE,
  4953. SCE_STATUS_ERROR_NOT_AVAILABLE,
  4954. NULL,
  4955. 0
  4956. );
  4957. //
  4958. // if access is denied or key does not exist, skip it
  4959. //
  4960. if ( rc == ERROR_PATH_NOT_FOUND ||
  4961. rc == ERROR_FILE_NOT_FOUND ||
  4962. rc == ERROR_INVALID_HANDLE ) {
  4963. gWarningCode = rc;
  4964. rc = ERROR_SUCCESS;
  4965. } else if ( rc == ERROR_ACCESS_DENIED ||
  4966. rc == ERROR_CANT_ACCESS_FILE ||
  4967. rc == ERROR_SHARING_VIOLATION) {
  4968. gWarningCode = rc;
  4969. rc = ERROR_SUCCESS;
  4970. }
  4971. }
  4972. if ( Buffer1 != NULL ) {
  4973. ScepFree(Buffer1);
  4974. Buffer1 = NULL;
  4975. }
  4976. break;
  4977. default:
  4978. break;
  4979. }
  4980. if ( Buffer != NULL ) {
  4981. ScepFree(Buffer);
  4982. Buffer = NULL;
  4983. }
  4984. }
  4985. if ( rc != ERROR_SUCCESS )
  4986. return(rc);
  4987. ProcChild:
  4988. //
  4989. // then process left child
  4990. //
  4991. for(pTemp = ThisNode->ChildList; pTemp != NULL; pTemp=pTemp->Next) {
  4992. if ( pTemp->Node == NULL ) continue;
  4993. rc = ScepAnalyzeOneObjectInTree(
  4994. pTemp->Node,
  4995. ObjectType,
  4996. Token,
  4997. GenericMapping
  4998. );
  4999. if ( rc != ERROR_SUCCESS ) {
  5000. break;
  5001. }
  5002. }
  5003. SkipNode:
  5004. return(rc);
  5005. }
  5006. DWORD
  5007. ScepAnalyzeObjectOnly(
  5008. IN PWSTR ObjectFullName,
  5009. IN BOOL IsContainer,
  5010. IN SE_OBJECT_TYPE ObjectType,
  5011. IN PSECURITY_DESCRIPTOR ProfileSD,
  5012. IN SECURITY_INFORMATION ProfileSeInfo
  5013. )
  5014. /* ++
  5015. Routine Description:
  5016. Get security setting for the current object and compare it with the profile
  5017. setting. This routine analyzes the current object only. If there is
  5018. difference in the security setting, the object will be added to the
  5019. ppObjectChecked object tree to return.
  5020. Arguments:
  5021. ObjectFullName - The object's full path name
  5022. ObjectType - Indicate file object or registry object
  5023. ProfileSD - security descriptor specified in the template
  5024. ProfileSeInfo - security information specified in the template
  5025. Return value:
  5026. SCESTATUS error codes
  5027. ++ */
  5028. {
  5029. DWORD Win32rc=NO_ERROR;
  5030. PSECURITY_DESCRIPTOR pSecurityDescriptor=NULL;
  5031. // UCHAR psdbuffer[PSD_BASE_LENGTH];
  5032. // PISECURITY_DESCRIPTOR psecuritydescriptor = (PISECURITY_DESCRIPTOR) psdbuffer;
  5033. // ULONG NewBytesNeeded, BytesNeeded;
  5034. // NTSTATUS NtStatus;
  5035. //
  5036. // get security information for this object
  5037. //
  5038. // win32 api is too slow!!!
  5039. Win32rc = GetNamedSecurityInfo(
  5040. ObjectFullName,
  5041. ObjectType,
  5042. ProfileSeInfo,
  5043. NULL,
  5044. NULL,
  5045. NULL,
  5046. NULL,
  5047. &pSecurityDescriptor
  5048. );
  5049. /*
  5050. Win32rc = ScepGetNamedSecurityInfo(
  5051. ObjectFullName,
  5052. ObjectType,
  5053. ProfileSeInfo,
  5054. &pSecurityDescriptor
  5055. );
  5056. */
  5057. if ( Win32rc == ERROR_SUCCESS ) {
  5058. //
  5059. // Compare the analysis security descriptor with the profile
  5060. //
  5061. Win32rc = ScepCompareAndAddObject(
  5062. ObjectFullName,
  5063. ObjectType,
  5064. IsContainer,
  5065. pSecurityDescriptor,
  5066. ProfileSD,
  5067. ProfileSeInfo,
  5068. TRUE,
  5069. NULL
  5070. );
  5071. ScepFree(pSecurityDescriptor);
  5072. if ( Win32rc != ERROR_SUCCESS ) {
  5073. ScepLogOutput3(1, Win32rc, SCEDLL_SAP_ERROR_ANALYZE, ObjectFullName);
  5074. }
  5075. } else {
  5076. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_QUERY_SECURITY, ObjectFullName);
  5077. }
  5078. if ( Win32rc != ERROR_SUCCESS ) {
  5079. ScepSaveObjectString(
  5080. hSection,
  5081. ObjectFullName,
  5082. IsContainer,
  5083. SCE_STATUS_ERROR_NOT_AVAILABLE,
  5084. NULL,
  5085. 0
  5086. );
  5087. }
  5088. return(Win32rc);
  5089. }
  5090. DWORD
  5091. ScepGetNamedSecurityInfo(
  5092. IN PWSTR ObjectFullName,
  5093. IN SE_OBJECT_TYPE ObjectType,
  5094. IN SECURITY_INFORMATION ProfileSeInfo,
  5095. OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  5096. )
  5097. {
  5098. DWORD Win32rc=ERROR_INVALID_PARAMETER;
  5099. HANDLE Handle=NULL;
  5100. *ppSecurityDescriptor = NULL;
  5101. switch ( ObjectType ) {
  5102. case SE_FILE_OBJECT:
  5103. Win32rc = ScepOpenFileObject(
  5104. (LPWSTR)ObjectFullName,
  5105. ScepGetDesiredAccess(READ_ACCESS_RIGHTS, ProfileSeInfo),
  5106. &Handle
  5107. );
  5108. if (Win32rc == ERROR_SUCCESS ) {
  5109. Win32rc = ScepGetFileSecurityInfo(
  5110. Handle,
  5111. ProfileSeInfo,
  5112. ppSecurityDescriptor);
  5113. CloseHandle(Handle);
  5114. }
  5115. break;
  5116. case SE_REGISTRY_KEY:
  5117. #ifdef _WIN64
  5118. case SE_REGISTRY_WOW64_32KEY:
  5119. #endif
  5120. Win32rc = ScepOpenRegistryObject(
  5121. ObjectType,
  5122. (LPWSTR)ObjectFullName,
  5123. ScepGetDesiredAccess(READ_ACCESS_RIGHTS, ProfileSeInfo),
  5124. (PHKEY)&Handle
  5125. );
  5126. if (Win32rc == ERROR_SUCCESS ) {
  5127. Win32rc = ScepGetKeySecurityInfo(
  5128. (HKEY)Handle,
  5129. ProfileSeInfo,
  5130. ppSecurityDescriptor);
  5131. RegCloseKey((HKEY)Handle);
  5132. }
  5133. break;
  5134. }
  5135. if ( Win32rc != NO_ERROR && *ppSecurityDescriptor != NULL ) {
  5136. ScepFree(*ppSecurityDescriptor);
  5137. *ppSecurityDescriptor = NULL;
  5138. }
  5139. return(Win32rc);
  5140. }
  5141. DWORD
  5142. ScepGetFileSecurityInfo(
  5143. IN HANDLE Handle,
  5144. IN SECURITY_INFORMATION SecurityInfo,
  5145. OUT PSECURITY_DESCRIPTOR * pSecurityDescriptor
  5146. )
  5147. /* ++
  5148. A modified copy of GetKernelSecurityInfo from windows\base\accctrl\kernel.cxx
  5149. -- */
  5150. {
  5151. UCHAR psdbuffer[PSD_BASE_LENGTH];
  5152. PISECURITY_DESCRIPTOR psecuritydescriptor = (PISECURITY_DESCRIPTOR) psdbuffer;
  5153. DWORD status = NO_ERROR;
  5154. NTSTATUS ntstatus;
  5155. ULONG bytesneeded = 0;
  5156. ULONG newbytesneeded;
  5157. if ( !NT_SUCCESS(ntstatus = NtQuerySecurityObject( Handle,
  5158. SecurityInfo,
  5159. psecuritydescriptor,
  5160. PSD_BASE_LENGTH,
  5161. &bytesneeded))) {
  5162. if (STATUS_BUFFER_TOO_SMALL == ntstatus) {
  5163. if (NULL == (psecuritydescriptor = (PISECURITY_DESCRIPTOR)
  5164. ScepAlloc( LMEM_ZEROINIT, bytesneeded))) {
  5165. return(ERROR_NOT_ENOUGH_MEMORY);
  5166. } else {
  5167. if ( !NT_SUCCESS(ntstatus = NtQuerySecurityObject(Handle,
  5168. SecurityInfo,
  5169. psecuritydescriptor,
  5170. bytesneeded,
  5171. &newbytesneeded))) {
  5172. status = RtlNtStatusToDosError(ntstatus);
  5173. }
  5174. }
  5175. } else {
  5176. status = RtlNtStatusToDosError(ntstatus);
  5177. }
  5178. }
  5179. if (NO_ERROR == status) {
  5180. status = ScepGetSecurityDescriptorParts( psecuritydescriptor,
  5181. SecurityInfo,
  5182. pSecurityDescriptor);
  5183. }
  5184. // if (bytesneeded > PSD_BASE_LENGTH) {
  5185. if ( psecuritydescriptor != (PISECURITY_DESCRIPTOR)psdbuffer ) {
  5186. ScepFree(psecuritydescriptor);
  5187. }
  5188. return(status);
  5189. }
  5190. DWORD
  5191. ScepGetSecurityDescriptorParts(
  5192. IN PISECURITY_DESCRIPTOR pSecurityDescriptor,
  5193. IN SECURITY_INFORMATION SecurityInfo,
  5194. OUT PSECURITY_DESCRIPTOR *pOutSecurityDescriptor
  5195. )
  5196. /* ++
  5197. A modified copy of GetSecurityDescriptorParts from windows\base\accctrl\src\common.cxx
  5198. -- */
  5199. {
  5200. NTSTATUS ntstatus;
  5201. DWORD status = NO_ERROR;
  5202. PSID owner = NULL,
  5203. group = NULL;
  5204. PACL dacl = NULL,
  5205. sacl = NULL;
  5206. ULONG csize = sizeof(SECURITY_DESCRIPTOR);
  5207. BOOLEAN bDummy, bParmPresent = FALSE;
  5208. PISECURITY_DESCRIPTOR poutsd;
  5209. PVOID bufptr=NULL;
  5210. SECURITY_DESCRIPTOR_CONTROL theControl=0;
  5211. ULONG theRevision=0;
  5212. //
  5213. // if no security descriptor found, don't return one!
  5214. //
  5215. *pOutSecurityDescriptor = NULL;
  5216. if ( pSecurityDescriptor ) {
  5217. //
  5218. // if the security descriptor is self relative, get absolute
  5219. // pointers to the components
  5220. //
  5221. ntstatus = RtlGetOwnerSecurityDescriptor( pSecurityDescriptor,
  5222. &owner,
  5223. &bDummy);
  5224. if (NT_SUCCESS(ntstatus)) {
  5225. ntstatus = RtlGetGroupSecurityDescriptor( pSecurityDescriptor,
  5226. &group,
  5227. &bDummy);
  5228. }
  5229. if (NT_SUCCESS(ntstatus)) {
  5230. ntstatus = RtlGetDaclSecurityDescriptor( pSecurityDescriptor,
  5231. &bParmPresent,
  5232. &dacl,
  5233. &bDummy);
  5234. if (NT_SUCCESS(ntstatus) && !bParmPresent)
  5235. dacl = NULL;
  5236. }
  5237. if (NT_SUCCESS(ntstatus)) {
  5238. ntstatus = RtlGetSaclSecurityDescriptor( pSecurityDescriptor,
  5239. &bParmPresent,
  5240. &sacl,
  5241. &bDummy);
  5242. if (NT_SUCCESS(ntstatus) && !bParmPresent)
  5243. sacl = NULL;
  5244. }
  5245. if (NT_SUCCESS(ntstatus)) {
  5246. //
  5247. // Build the new security descriptor
  5248. //
  5249. csize = RtlLengthSecurityDescriptor( pSecurityDescriptor ) +
  5250. sizeof(SECURITY_DESCRIPTOR) - sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  5251. //
  5252. // There is size difference in relative form and absolute form
  5253. // on 64 bit system. - always add the difference to the size.
  5254. // This has no effect on 32bit system. On 64bit system, if the input
  5255. // security descriptor is in absolute form already, we will waste
  5256. // 16 bytes per security descriptor.
  5257. //
  5258. // Another option is to detect the form of the input security descriptor
  5259. // but that takes a pointer deref, a & operation, and code complexity.
  5260. // Plus, it will affect performance of 32bit system. The output SD
  5261. // will be freed after a short period of time, so we go with
  5262. // the first option.
  5263. //
  5264. if (NULL == (poutsd = (PISECURITY_DESCRIPTOR)ScepAlloc(LMEM_ZEROINIT, csize)))
  5265. return(ERROR_NOT_ENOUGH_MEMORY);
  5266. RtlCreateSecurityDescriptor(poutsd, SECURITY_DESCRIPTOR_REVISION);
  5267. ntstatus = RtlGetControlSecurityDescriptor (
  5268. pSecurityDescriptor,
  5269. &theControl,
  5270. &theRevision
  5271. );
  5272. if ( NT_SUCCESS(ntstatus) ) {
  5273. theControl &= SE_VALID_CONTROL_BITS;
  5274. RtlSetControlSecurityDescriptor (
  5275. poutsd,
  5276. theControl,
  5277. theControl
  5278. );
  5279. }
  5280. ntstatus = STATUS_SUCCESS;
  5281. bufptr = Add2Ptr(poutsd, sizeof(SECURITY_DESCRIPTOR));
  5282. if (SecurityInfo & OWNER_SECURITY_INFORMATION) {
  5283. if (NULL != owner) {
  5284. //
  5285. // no error checking as these should not fail!!
  5286. //
  5287. ntstatus = RtlCopySid(RtlLengthSid(owner), (PSID)bufptr, owner);
  5288. if ( NT_SUCCESS(ntstatus) ) {
  5289. ntstatus = RtlSetOwnerSecurityDescriptor(poutsd,
  5290. (PSID)bufptr, FALSE);
  5291. if ( NT_SUCCESS(ntstatus) )
  5292. bufptr = Add2Ptr(bufptr,RtlLengthSid(owner));
  5293. }
  5294. } else
  5295. ntstatus = STATUS_NO_SECURITY_ON_OBJECT;
  5296. }
  5297. if (NT_SUCCESS(ntstatus) && (SecurityInfo & GROUP_SECURITY_INFORMATION) ) {
  5298. if (NULL != group) {
  5299. //
  5300. // no error checking as these should not fail!!
  5301. //
  5302. ntstatus = RtlCopySid(RtlLengthSid(group), (PSID)bufptr, group);
  5303. if ( NT_SUCCESS(ntstatus) ) {
  5304. ntstatus = RtlSetGroupSecurityDescriptor(poutsd,
  5305. (PSID)bufptr, FALSE);
  5306. if ( NT_SUCCESS(ntstatus) )
  5307. bufptr = Add2Ptr(bufptr,RtlLengthSid(group));
  5308. }
  5309. } else
  5310. ntstatus = STATUS_NO_SECURITY_ON_OBJECT;
  5311. }
  5312. //
  5313. // The DACL and SACL may or may not be on the object.
  5314. //
  5315. if ( NT_SUCCESS(ntstatus) && (SecurityInfo & DACL_SECURITY_INFORMATION) ) {
  5316. if (NULL != dacl) {
  5317. RtlCopyMemory(bufptr, dacl, dacl->AclSize);
  5318. ntstatus = RtlSetDaclSecurityDescriptor(poutsd,
  5319. TRUE,
  5320. (ACL *)bufptr,
  5321. FALSE);
  5322. if ( NT_SUCCESS(ntstatus) )
  5323. bufptr = Add2Ptr(bufptr, dacl->AclSize);
  5324. }
  5325. }
  5326. if ( NT_SUCCESS(ntstatus) && (SecurityInfo & SACL_SECURITY_INFORMATION)){
  5327. if (NULL != sacl) {
  5328. RtlCopyMemory(bufptr, sacl, sacl->AclSize);
  5329. ntstatus = RtlSetSaclSecurityDescriptor(poutsd,
  5330. TRUE,
  5331. (ACL *)bufptr,
  5332. FALSE);
  5333. }
  5334. }
  5335. if (!NT_SUCCESS(ntstatus))
  5336. ScepFree(poutsd);
  5337. else
  5338. *pOutSecurityDescriptor = poutsd;
  5339. }
  5340. status = RtlNtStatusToDosError(ntstatus);
  5341. }
  5342. return(status);
  5343. }
  5344. DWORD
  5345. ScepGetKeySecurityInfo(
  5346. IN HANDLE Handle,
  5347. IN SECURITY_INFORMATION SecurityInfo,
  5348. OUT PSECURITY_DESCRIPTOR *pSecurityDescriptor
  5349. )
  5350. /* ++
  5351. A modified copy of GetRegistrySecurityInfo in windows\base\accctrl\src\registry.cxx
  5352. -- */
  5353. {
  5354. if ( SecurityInfo == 0 || pSecurityDescriptor == NULL )
  5355. return ERROR_INVALID_PARAMETER;
  5356. UCHAR psdbuffer[PSD_BASE_LENGTH];
  5357. PISECURITY_DESCRIPTOR psecuritydescriptor = (PISECURITY_DESCRIPTOR) psdbuffer;
  5358. DWORD status;
  5359. ULONG bytesneeded = PSD_BASE_LENGTH;
  5360. if ( NO_ERROR != (status = RegGetKeySecurity(
  5361. (HKEY)Handle,
  5362. SecurityInfo,
  5363. psecuritydescriptor,
  5364. &bytesneeded) ) ) {
  5365. if (ERROR_INSUFFICIENT_BUFFER == status) {
  5366. if (NULL == (psecuritydescriptor = (PISECURITY_DESCRIPTOR)
  5367. ScepAlloc(LMEM_ZEROINIT, bytesneeded))) {
  5368. return(ERROR_NOT_ENOUGH_MEMORY);
  5369. } else {
  5370. status = RegGetKeySecurity((HKEY)Handle,
  5371. SecurityInfo,
  5372. psecuritydescriptor,
  5373. &bytesneeded);
  5374. }
  5375. }
  5376. }
  5377. if (NO_ERROR == status) {
  5378. status = ScepGetSecurityDescriptorParts(
  5379. psecuritydescriptor,
  5380. SecurityInfo,
  5381. pSecurityDescriptor);
  5382. }
  5383. // if (bytesneeded > PSD_BASE_LENGTH)
  5384. if ( psecuritydescriptor != (PISECURITY_DESCRIPTOR)psdbuffer )
  5385. ScepFree(psecuritydescriptor);
  5386. return(status);
  5387. }
  5388. DWORD
  5389. ScepCompareAndAddObject(
  5390. IN PWSTR ObjectFullName,
  5391. IN SE_OBJECT_TYPE ObjectType,
  5392. IN BOOL IsContainer,
  5393. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  5394. IN PSECURITY_DESCRIPTOR ProfileSD,
  5395. IN SECURITY_INFORMATION ProfileSeInfo,
  5396. IN BOOL AddObject,
  5397. OUT PBYTE IsDifferent OPTIONAL
  5398. )
  5399. /* ++
  5400. Routine Description:
  5401. Compare two security descriptors and add the object to the analysis database
  5402. if there is difference.
  5403. Arguments:
  5404. ObjectFullName - The object's full path name
  5405. pSecurityDescriptor - The security descriptor of current object's setting
  5406. ProfileSD - security descriptor specified in the template
  5407. ProfileSeInfo - security information specified in the template
  5408. Return value:
  5409. SCESTATUS error codes
  5410. ++ */
  5411. {
  5412. DWORD rc;
  5413. BYTE Status;
  5414. PWSTR SDspec=NULL;
  5415. DWORD SDsize;
  5416. rc = ScepCompareObjectSecurity(ObjectType,
  5417. IsContainer,
  5418. pSecurityDescriptor,
  5419. ProfileSD,
  5420. ProfileSeInfo,
  5421. &Status
  5422. );
  5423. if ( NO_ERROR == rc ) {
  5424. if ( AddObject && Status && ObjectFullName != NULL ) {
  5425. //
  5426. // save this one in SAP section
  5427. //
  5428. rc = ConvertSecurityDescriptorToText(
  5429. pSecurityDescriptor,
  5430. ProfileSeInfo,
  5431. &SDspec,
  5432. &SDsize
  5433. );
  5434. if ( rc == ERROR_SUCCESS ) {
  5435. //
  5436. // Save to the SAP section
  5437. //
  5438. if ( ObjectType == SE_DS_OBJECT ) {
  5439. rc = ScepSaveDsStatusToSection(
  5440. ObjectFullName,
  5441. IsContainer,
  5442. Status,
  5443. SDspec,
  5444. SDsize
  5445. );
  5446. } else {
  5447. rc = ScepSaveObjectString(
  5448. hSection,
  5449. ObjectFullName,
  5450. IsContainer,
  5451. Status,
  5452. SDspec,
  5453. SDsize
  5454. );
  5455. }
  5456. if ( SCESTATUS_OBJECT_EXIST == rc ) {
  5457. ScepLogOutput3(1, ERROR_FILE_EXISTS, SCEDLL_SAP_ERROR_SAVE, ObjectFullName);
  5458. rc = ERROR_SUCCESS;
  5459. } else if ( rc != SCESTATUS_SUCCESS )
  5460. rc = ScepSceStatusToDosError(rc);
  5461. } else
  5462. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_SAVE, ObjectFullName);
  5463. if ( SDspec != NULL )
  5464. ScepFree(SDspec);
  5465. BadCnt++;
  5466. }
  5467. if ( IsDifferent ) {
  5468. *IsDifferent = Status;
  5469. }
  5470. } else {
  5471. if ( ObjectFullName ) {
  5472. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ACL, ObjectFullName);
  5473. }
  5474. }
  5475. return(rc);
  5476. }
  5477. DWORD
  5478. ScepAnalyzeObjectAndChildren(
  5479. IN PWSTR ObjectFullName,
  5480. IN SE_OBJECT_TYPE ObjectType,
  5481. IN PSECURITY_DESCRIPTOR ProfileSD,
  5482. IN SECURITY_INFORMATION ProfileSeInfo
  5483. )
  5484. /* ++
  5485. Routine Description:
  5486. Analyze current object and all subkeys/files/directories under the object.
  5487. If there is difference in security setting for any object, the object will
  5488. be added to the analysis database.
  5489. Arguments:
  5490. ObjectFullName - The object's full path name
  5491. ObjectType - Indicate file object or registry object
  5492. ProfileSD - security descriptor specified in the template
  5493. ProfileSeInfo - security information specified in the template
  5494. Return value:
  5495. SCESTATUS error codes
  5496. ++ */
  5497. {
  5498. DWORD rc=0;
  5499. PWSTR Buffer=NULL;
  5500. intptr_t hFile;
  5501. struct _wfinddata_t * pFileInfo=NULL;
  5502. DWORD index;
  5503. DWORD BufSize;
  5504. PWSTR Buffer1=NULL;
  5505. DWORD EnumRc=0;
  5506. HKEY hKey;
  5507. DWORD ObjectLen;
  5508. //
  5509. // analyze this file/key first
  5510. //
  5511. rc = ScepAnalyzeObjectOnly(
  5512. ObjectFullName,
  5513. TRUE,
  5514. ObjectType,
  5515. ProfileSD,
  5516. ProfileSeInfo
  5517. );
  5518. //
  5519. // if the object denies access or does not exist, skip it.
  5520. //
  5521. if ( rc == ERROR_ACCESS_DENIED ||
  5522. rc == ERROR_CANT_ACCESS_FILE ||
  5523. rc == ERROR_SHARING_VIOLATION) {
  5524. gWarningCode = rc;
  5525. rc = ScepSaveObjectString(
  5526. hSection,
  5527. ObjectFullName,
  5528. TRUE,
  5529. SCE_STATUS_ERROR_NOT_AVAILABLE,
  5530. NULL,
  5531. 0
  5532. );
  5533. return(rc);
  5534. } else if ( rc == ERROR_FILE_NOT_FOUND ||
  5535. rc == ERROR_PATH_NOT_FOUND ||
  5536. rc == ERROR_INVALID_HANDLE ) {
  5537. gWarningCode = rc;
  5538. return(SCESTATUS_SUCCESS);
  5539. }
  5540. if ( rc != ERROR_SUCCESS )
  5541. return(rc);
  5542. //
  5543. // recursively analyze all children under this file/key
  5544. //
  5545. ObjectLen = wcslen(ObjectFullName);
  5546. switch ( ObjectType ) {
  5547. case SE_FILE_OBJECT:
  5548. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  5549. if ( pFileInfo == NULL ) {
  5550. rc = ERROR_NOT_ENOUGH_MEMORY;
  5551. break;
  5552. }
  5553. //
  5554. // find all files under this directory/file
  5555. //
  5556. BufSize = ObjectLen+4;
  5557. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  5558. if ( Buffer == NULL ) {
  5559. rc = ERROR_NOT_ENOUGH_MEMORY;
  5560. break;
  5561. }
  5562. swprintf(Buffer, L"%s\\*.*", ObjectFullName);
  5563. hFile = _wfindfirst(Buffer, pFileInfo);
  5564. ScepFree(Buffer);
  5565. Buffer = NULL;
  5566. if ( hFile != -1 &&
  5567. ( 0 == ( GetFileAttributes(ObjectFullName) & // bug 635098: don't propagate permissions
  5568. FILE_ATTRIBUTE_REPARSE_POINT ))) // across junction points
  5569. {
  5570. do {
  5571. if ( wcscmp(L"..", pFileInfo->name) == 0 ||
  5572. wcscmp(L".", pFileInfo->name) == 0 )
  5573. continue;
  5574. //
  5575. // The name is not in the list, so analyze this one
  5576. //
  5577. BufSize = ObjectLen+wcslen(pFileInfo->name)+1;
  5578. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  5579. if ( Buffer == NULL ) {
  5580. rc = ERROR_NOT_ENOUGH_MEMORY;
  5581. break;
  5582. }
  5583. swprintf(Buffer, L"%s\\%s", ObjectFullName, pFileInfo->name);
  5584. EnumRc = pFileInfo->attrib; // use this variable temp
  5585. ScepFree(pFileInfo);
  5586. pFileInfo = NULL;
  5587. if ( EnumRc & _A_SUBDIR ) {
  5588. rc = ScepAnalyzeObjectAndChildren(
  5589. Buffer,
  5590. ObjectType,
  5591. ProfileSD,
  5592. ProfileSeInfo
  5593. );
  5594. } else {
  5595. rc = ScepAnalyzeObjectOnly(
  5596. Buffer,
  5597. FALSE,
  5598. ObjectType,
  5599. ProfileSD,
  5600. ProfileSeInfo
  5601. );
  5602. }
  5603. ScepFree(Buffer);
  5604. Buffer = NULL;
  5605. if ( rc != ERROR_SUCCESS )
  5606. break;
  5607. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  5608. if ( pFileInfo == NULL ) {
  5609. rc = ERROR_NOT_ENOUGH_MEMORY;
  5610. break;
  5611. }
  5612. } while ( _wfindnext(hFile, pFileInfo) == 0 );
  5613. _findclose(hFile);
  5614. }
  5615. break;
  5616. case SE_REGISTRY_KEY:
  5617. //
  5618. // open the key
  5619. //
  5620. rc = ScepOpenRegistryObject(
  5621. SE_REGISTRY_KEY,
  5622. ObjectFullName,
  5623. KEY_READ,
  5624. &hKey
  5625. );
  5626. if ( rc == ERROR_SUCCESS ) {
  5627. index = 0;
  5628. //
  5629. // enumerate all subkeys of the key
  5630. //
  5631. do {
  5632. Buffer1 = (PWSTR)ScepAlloc(LMEM_ZEROINIT, MAX_PATH*sizeof(WCHAR));
  5633. if ( Buffer1 == NULL ) {
  5634. rc = ERROR_NOT_ENOUGH_MEMORY;
  5635. break;
  5636. }
  5637. BufSize = MAX_PATH;
  5638. EnumRc = RegEnumKeyEx(hKey,
  5639. index,
  5640. Buffer1,
  5641. &BufSize,
  5642. NULL,
  5643. NULL,
  5644. NULL,
  5645. NULL);
  5646. if ( EnumRc == ERROR_SUCCESS ) {
  5647. index++;
  5648. //
  5649. // analyze children under this key
  5650. //
  5651. BufSize += ObjectLen+1;
  5652. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  5653. if ( Buffer == NULL ) {
  5654. rc = ERROR_NOT_ENOUGH_MEMORY;
  5655. break;
  5656. }
  5657. swprintf(Buffer, L"%s\\%s", ObjectFullName, Buffer1);
  5658. ScepFree(Buffer1);
  5659. Buffer1 = NULL;
  5660. rc = ScepAnalyzeObjectAndChildren(
  5661. Buffer,
  5662. ObjectType,
  5663. ProfileSD,
  5664. ProfileSeInfo
  5665. );
  5666. ScepFree(Buffer);
  5667. Buffer = NULL;
  5668. if ( rc != ERROR_SUCCESS )
  5669. break;
  5670. } else if ( EnumRc != ERROR_NO_MORE_ITEMS ) {
  5671. //
  5672. // Enumeration shouldn't fail if RegOpenKeyEx works right
  5673. // because the ENUMERATE_SUB_KEYS access was requested in
  5674. // the open call.
  5675. // However, due to a app compat bug (for terminal server)
  5676. // when a registry key is opened with some access rights,
  5677. // it is actually opened with MAXIMUM_ALLOWED for certain
  5678. // keys. This will cause RegEnumKeyEx fail with access denied
  5679. // error.
  5680. // In this case, we treat it the same as the open key failed
  5681. // with the error.
  5682. //
  5683. // skip it
  5684. //
  5685. rc = EnumRc;
  5686. }
  5687. if ( Buffer1 != NULL ) {
  5688. ScepFree(Buffer1);
  5689. Buffer1 = NULL;
  5690. }
  5691. } while ( EnumRc == ERROR_SUCCESS );
  5692. RegCloseKey(hKey);
  5693. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  5694. ScepLogOutput3(1, EnumRc, SCEDLL_SAP_ERROR_ENUMERATE, ObjectFullName);
  5695. rc = EnumRc;
  5696. }
  5697. } else
  5698. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, ObjectFullName);
  5699. if ( rc == ERROR_ACCESS_DENIED ||
  5700. rc == ERROR_CANT_ACCESS_FILE ||
  5701. rc == ERROR_SHARING_VIOLATION) {
  5702. gWarningCode = rc;
  5703. rc = ScepSaveObjectString(
  5704. hSection,
  5705. ObjectFullName,
  5706. TRUE,
  5707. SCE_STATUS_ERROR_NOT_AVAILABLE,
  5708. NULL,
  5709. 0
  5710. );
  5711. } else if ( rc == ERROR_PATH_NOT_FOUND ||
  5712. rc == ERROR_FILE_NOT_FOUND ||
  5713. rc == ERROR_INVALID_HANDLE ) {
  5714. gWarningCode = rc;
  5715. rc = SCESTATUS_SUCCESS;
  5716. }
  5717. break;
  5718. default:
  5719. break;
  5720. }
  5721. if ( Buffer != NULL ) {
  5722. ScepFree(Buffer);
  5723. }
  5724. if ( Buffer1 != NULL ) {
  5725. ScepFree(Buffer1);
  5726. }
  5727. if ( pFileInfo != NULL ) {
  5728. ScepFree(pFileInfo);
  5729. }
  5730. return(rc);
  5731. }
  5732. SCESTATUS
  5733. ScepAnalyzeSystemAuditing(
  5734. IN PSCE_PROFILE_INFO pSmpInfo,
  5735. IN PPOLICY_AUDIT_EVENTS_INFO AuditEvent
  5736. )
  5737. /* ++
  5738. Routine Description:
  5739. This routine queries the system auditing security which includes event log
  5740. setting, audit event setting, SACL for registry, and SACL for files.
  5741. Arguments:
  5742. SnapShot - The buffer which contains analyzed system info
  5743. Return value:
  5744. SCESTATUS_SUCCESS
  5745. SCESTATUS_NOT_ENOUGH_MEMORY
  5746. SCESTATUS_INVALID_PARAMETER
  5747. SCESTATUS_OTHER_ERROR
  5748. -- */
  5749. {
  5750. SCESTATUS rc;
  5751. DWORD i,retRc=NO_ERROR;
  5752. WCHAR MsgBuf[256];
  5753. PCWSTR szAuditSection=NULL;
  5754. DWORD MaxSize=0;
  5755. DWORD Retention=0;
  5756. DWORD AuditLogRetentionPeriod;
  5757. DWORD RetentionDays;
  5758. DWORD RestrictGuest;
  5759. NTSTATUS NtStatus;
  5760. LSA_HANDLE LsaHandle=NULL;
  5761. PPOLICY_AUDIT_FULL_QUERY_INFO AuditFull=NULL;
  5762. BOOL bSaveSnapshot=FALSE;
  5763. if ( (gOptions & SCE_NO_ANALYZE) || (gOptions & SCE_GENERATE_ROLLBACK) )
  5764. bSaveSnapshot = TRUE;
  5765. if ( !(gOptions & SCE_NO_ANALYZE) ) {
  5766. //
  5767. // DO NOT query log settings in system upgrade because local policy
  5768. // table doesn't keep log settings
  5769. // only analyze log settings
  5770. // Audit Log settings are saved in the Registry
  5771. // under System\CurrentControlSet\Services\EventLog\<LogName>\MaxSize and Retention
  5772. //
  5773. for ( i=0; i<3; i++) {
  5774. //
  5775. // Different logs have different keys in Registry
  5776. //
  5777. switch (i) {
  5778. case 0:
  5779. wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\System");
  5780. szAuditSection = szAuditSystemLog;
  5781. break;
  5782. case 1:
  5783. wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\Security");
  5784. szAuditSection = szAuditSecurityLog;
  5785. break;
  5786. default:
  5787. wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\Application");
  5788. szAuditSection = szAuditApplicationLog;
  5789. break;
  5790. }
  5791. //
  5792. // Preprea the section to write to
  5793. //
  5794. rc = ScepStartANewSection(
  5795. hProfile,
  5796. &hSection,
  5797. bSaveSnapshot ? SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  5798. szAuditSection
  5799. );
  5800. if ( rc != SCESTATUS_SUCCESS ) {
  5801. retRc = ScepSceStatusToDosError(rc);
  5802. ScepLogOutput3(1, retRc,
  5803. SCEDLL_SAP_START_SECTION, (PWSTR)szAuditSection);
  5804. continue;
  5805. }
  5806. DWORD LogValues[MAX_LOG_ITEMS];
  5807. for ( MaxSize=0; MaxSize<MAX_LOG_ITEMS; MaxSize++ ) {
  5808. LogValues[MaxSize] = SCE_ERROR_VALUE;
  5809. }
  5810. RestrictGuest = 0;
  5811. rc = ScepRegQueryIntValue(
  5812. HKEY_LOCAL_MACHINE,
  5813. MsgBuf,
  5814. L"MaxSize",
  5815. &MaxSize
  5816. );
  5817. if ( rc == NO_ERROR ) {
  5818. rc = ScepRegQueryIntValue(
  5819. HKEY_LOCAL_MACHINE,
  5820. MsgBuf,
  5821. L"Retention",
  5822. &Retention
  5823. );
  5824. if ( rc == NO_ERROR ) {
  5825. ScepRegQueryIntValue(
  5826. HKEY_LOCAL_MACHINE,
  5827. MsgBuf,
  5828. L"RestrictGuestAccess",
  5829. &RestrictGuest
  5830. );
  5831. }
  5832. }
  5833. if ( rc == NO_ERROR ) {
  5834. MaxSize /= 1024;
  5835. rc = ScepCompareAndSaveIntValue(
  5836. hSection,
  5837. L"MaximumLogSize",
  5838. (gOptions & SCE_GENERATE_ROLLBACK),
  5839. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->MaximumLogSize[i],
  5840. MaxSize
  5841. );
  5842. if ( rc == SCESTATUS_SUCCESS ) {
  5843. LogValues[IDX_MAX_LOG_SIZE] = MaxSize;
  5844. switch ( Retention ) {
  5845. case MAXULONG: // manually
  5846. AuditLogRetentionPeriod = 2;
  5847. RetentionDays = SCE_NO_VALUE;
  5848. break;
  5849. case 0:
  5850. AuditLogRetentionPeriod = 0;
  5851. RetentionDays = SCE_NO_VALUE;
  5852. break;
  5853. default:
  5854. AuditLogRetentionPeriod = 1;
  5855. // number of days * seconds/day
  5856. RetentionDays = Retention / (24 * 3600);
  5857. break;
  5858. }
  5859. BOOL bReplaceOnly=FALSE;
  5860. if ( (gOptions & SCE_GENERATE_ROLLBACK) &&
  5861. (pSmpInfo->AuditLogRetentionPeriod[i] == SCE_NO_VALUE) &&
  5862. (pSmpInfo->RetentionDays[i] == SCE_NO_VALUE) ) {
  5863. bReplaceOnly = TRUE;
  5864. }
  5865. rc = ScepCompareAndSaveIntValue(
  5866. hSection,
  5867. L"AuditLogRetentionPeriod",
  5868. bReplaceOnly,
  5869. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditLogRetentionPeriod[i],
  5870. AuditLogRetentionPeriod
  5871. );
  5872. if ( rc == SCESTATUS_SUCCESS ) {
  5873. LogValues[IDX_RET_PERIOD] = AuditLogRetentionPeriod;
  5874. if ( RetentionDays != SCE_NO_VALUE ) {
  5875. rc = ScepCompareAndSaveIntValue(
  5876. hSection,
  5877. L"RetentionDays",
  5878. bReplaceOnly,
  5879. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->RetentionDays[i],
  5880. RetentionDays
  5881. );
  5882. }
  5883. if ( rc == SCESTATUS_SUCCESS ) {
  5884. LogValues[IDX_RET_DAYS] = RetentionDays;
  5885. rc = ScepCompareAndSaveIntValue(
  5886. hSection,
  5887. L"RestrictGuestAccess",
  5888. (gOptions & SCE_GENERATE_ROLLBACK),
  5889. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->RestrictGuestAccess[i],
  5890. RestrictGuest
  5891. );
  5892. if ( rc == SCESTATUS_SUCCESS ) {
  5893. LogValues[IDX_RESTRICT_GUEST] = RestrictGuest;
  5894. }
  5895. }
  5896. }
  5897. }
  5898. rc = ScepSceStatusToDosError(rc);
  5899. } else {
  5900. ScepLogOutput3( 1, rc, SCEDLL_ERROR_QUERY_LOGSETTINGS);
  5901. }
  5902. if ( rc != NO_ERROR && !(gOptions & SCE_GENERATE_ROLLBACK) ) {
  5903. //
  5904. // see if anything should be raised as error
  5905. //
  5906. for ( MaxSize=0; MaxSize<MAX_LOG_ITEMS; MaxSize++ ) {
  5907. if ( LogValues[MaxSize] == SCE_ERROR_VALUE ) {
  5908. ScepCompareAndSaveIntValue(
  5909. hSection,
  5910. LogItems[MaxSize],
  5911. FALSE,
  5912. SCE_NO_VALUE,
  5913. SCE_ERROR_VALUE
  5914. );
  5915. }
  5916. }
  5917. retRc = rc;
  5918. }
  5919. }
  5920. if ( retRc == NO_ERROR ) {
  5921. ScepLogOutput3(1, 0, SCEDLL_SAP_LOGSETTINGS);
  5922. }
  5923. }
  5924. //
  5925. // AuditEvent may be NULL if failed to query the policy
  5926. //
  5927. if ( (gOptions & SCE_NO_ANALYZE) && AuditEvent == NULL ) {
  5928. retRc = ERROR_ACCESS_DENIED;
  5929. } else {
  5930. //
  5931. // Prepare audit event section
  5932. //
  5933. rc = ScepStartANewSection(
  5934. hProfile,
  5935. &hSection,
  5936. bSaveSnapshot ? SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  5937. szAuditEvent
  5938. );
  5939. if ( rc != SCESTATUS_SUCCESS ) {
  5940. rc = ScepSceStatusToDosError(rc);
  5941. ScepLogOutput3(1, rc,
  5942. SCEDLL_SAP_START_SECTION, (PWSTR)szAuditEvent);
  5943. } else {
  5944. DWORD EventValues[MAX_EVENT_ITEMS];
  5945. if ( !(gOptions & SCE_NO_ANALYZE) ) {
  5946. for ( MaxSize=0; MaxSize<MAX_EVENT_ITEMS; MaxSize++ ) {
  5947. EventValues[MaxSize] = SCE_ERROR_VALUE;
  5948. }
  5949. }
  5950. if ( AuditEvent ) {
  5951. if ( !AuditEvent->AuditingMode ) {
  5952. for ( i=0; i<AuditEvent->MaximumAuditEventCount; i++ )
  5953. AuditEvent->EventAuditingOptions[i] = 0;
  5954. }
  5955. rc = ScepCompareAndSaveIntValue(
  5956. hSection,
  5957. L"AuditSystemEvents",
  5958. (gOptions & SCE_GENERATE_ROLLBACK),
  5959. (gOptions & SCE_NO_ANALYZE) ?
  5960. SCE_SNAPSHOT_VALUE :
  5961. pSmpInfo->AuditSystemEvents,
  5962. AuditEvent->EventAuditingOptions[AuditCategorySystem]
  5963. );
  5964. if ( rc == SCESTATUS_SUCCESS ) {
  5965. EventValues[IDX_AUDIT_SYSTEM] = 1;
  5966. rc = ScepCompareAndSaveIntValue(
  5967. hSection,
  5968. L"AuditLogonEvents",
  5969. (gOptions & SCE_GENERATE_ROLLBACK),
  5970. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditLogonEvents,
  5971. AuditEvent->EventAuditingOptions[AuditCategoryLogon]
  5972. );
  5973. if ( rc == SCESTATUS_SUCCESS ) {
  5974. EventValues[IDX_AUDIT_LOGON] = 1;
  5975. rc = ScepCompareAndSaveIntValue(
  5976. hSection,
  5977. L"AuditObjectAccess",
  5978. (gOptions & SCE_GENERATE_ROLLBACK),
  5979. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditObjectAccess,
  5980. AuditEvent->EventAuditingOptions[AuditCategoryObjectAccess]
  5981. );
  5982. if ( rc == SCESTATUS_SUCCESS ) {
  5983. EventValues[IDX_AUDIT_OBJECT] = 1;
  5984. rc = ScepCompareAndSaveIntValue(
  5985. hSection,
  5986. L"AuditPrivilegeUse",
  5987. (gOptions & SCE_GENERATE_ROLLBACK),
  5988. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditPrivilegeUse,
  5989. AuditEvent->EventAuditingOptions[AuditCategoryPrivilegeUse]
  5990. );
  5991. if ( rc == SCESTATUS_SUCCESS ) {
  5992. EventValues[IDX_AUDIT_PRIV] = 1;
  5993. rc = ScepCompareAndSaveIntValue(
  5994. hSection,
  5995. L"AuditProcessTracking",
  5996. (gOptions & SCE_GENERATE_ROLLBACK),
  5997. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditProcessTracking,
  5998. AuditEvent->EventAuditingOptions[AuditCategoryDetailedTracking]
  5999. );
  6000. if ( rc == SCESTATUS_SUCCESS ) {
  6001. EventValues[IDX_AUDIT_PROCESS] = 1;
  6002. rc = ScepCompareAndSaveIntValue(
  6003. hSection,
  6004. L"AuditPolicyChange",
  6005. (gOptions & SCE_GENERATE_ROLLBACK),
  6006. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditPolicyChange,
  6007. AuditEvent->EventAuditingOptions[AuditCategoryPolicyChange]
  6008. );
  6009. if ( rc == SCESTATUS_SUCCESS ) {
  6010. EventValues[IDX_AUDIT_ACCOUNT] = 1;
  6011. rc = ScepCompareAndSaveIntValue(
  6012. hSection,
  6013. L"AuditAccountManage",
  6014. (gOptions & SCE_GENERATE_ROLLBACK),
  6015. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditAccountManage,
  6016. AuditEvent->EventAuditingOptions[AuditCategoryAccountManagement]
  6017. );
  6018. if ( rc == SCESTATUS_SUCCESS ) {
  6019. EventValues[IDX_AUDIT_DS] = 1;
  6020. rc = ScepCompareAndSaveIntValue(
  6021. hSection,
  6022. L"AuditDSAccess",
  6023. (gOptions & SCE_GENERATE_ROLLBACK),
  6024. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditDSAccess,
  6025. AuditEvent->EventAuditingOptions[AuditCategoryDirectoryServiceAccess]
  6026. );
  6027. if ( rc == SCESTATUS_SUCCESS ) {
  6028. EventValues[IDX_AUDIT_ACCT_LOGON] = 1;
  6029. rc = ScepCompareAndSaveIntValue(
  6030. hSection,
  6031. L"AuditAccountLogon",
  6032. (gOptions & SCE_GENERATE_ROLLBACK),
  6033. (gOptions & SCE_NO_ANALYZE) ? SCE_SNAPSHOT_VALUE : pSmpInfo->AuditAccountLogon,
  6034. AuditEvent->EventAuditingOptions[AuditCategoryAccountLogon]
  6035. );
  6036. }
  6037. }
  6038. }
  6039. }
  6040. }
  6041. }
  6042. }
  6043. }
  6044. } else {
  6045. //
  6046. // audit policy is not available
  6047. //
  6048. rc = SCESTATUS_ACCESS_DENIED;
  6049. }
  6050. if ( rc != SCESTATUS_SUCCESS ) {
  6051. rc = ScepSceStatusToDosError(rc);
  6052. ScepLogOutput3( 1, rc,
  6053. SCEDLL_SAP_ERROR_EVENT_AUDITING);
  6054. } else {
  6055. ScepLogOutput3( 1, 0, SCEDLL_SAP_EVENT_AUDITING);
  6056. }
  6057. if ( rc != NO_ERROR ) {
  6058. retRc = rc;
  6059. if ( !bSaveSnapshot ) {
  6060. for ( MaxSize=0; MaxSize<MAX_EVENT_ITEMS; MaxSize++ ) {
  6061. if ( EventValues[MaxSize] == SCE_ERROR_VALUE ) {
  6062. //
  6063. // raise this error
  6064. //
  6065. ScepCompareAndSaveIntValue(
  6066. hSection,
  6067. EventItems[MaxSize],
  6068. FALSE,
  6069. SCE_NO_VALUE,
  6070. SCE_ERROR_VALUE
  6071. );
  6072. }
  6073. }
  6074. }
  6075. }
  6076. }
  6077. }
  6078. if ( LsaHandle ) {
  6079. LsaClose( LsaHandle );
  6080. }
  6081. return(ScepDosErrorToSceStatus(retRc));
  6082. }
  6083. SCESTATUS
  6084. ScepAnalyzeDeInitialize(
  6085. IN SCESTATUS rc,
  6086. IN DWORD Options
  6087. )
  6088. /*++
  6089. Routine Description:
  6090. This routine de-initialize the SCP engine. The operations include
  6091. clear SCE_SCP_INFO buffer and close the SCP profile
  6092. close the error log file
  6093. reset the status
  6094. Arguments:
  6095. rc - SCESTATUS error code (from other routines)
  6096. Return value:
  6097. SCESTATUS error code
  6098. ++*/
  6099. {
  6100. NTSTATUS NtStatus;
  6101. LARGE_INTEGER CurrentTime;
  6102. SCESTATUS Status;
  6103. if ( rc == SCESTATUS_ALREADY_RUNNING ) {
  6104. return(rc);
  6105. }
  6106. //
  6107. // save new time stamp
  6108. //
  6109. if ( hProfile && (hProfile->JetSessionID != JET_sesidNil) &&
  6110. (hProfile->JetDbID != JET_dbidNil) &&
  6111. !(Options & SCE_GENERATE_ROLLBACK) ) {
  6112. NtStatus = NtQuerySystemTime(&CurrentTime);
  6113. if ( NtStatus == STATUS_SUCCESS ) {
  6114. //printf("TimeStamp: %x%x\n", CurrentTime.HighPart, CurrentTime.LowPart);
  6115. Status = SceJetSetTimeStamp(
  6116. hProfile,
  6117. TRUE,
  6118. CurrentTime
  6119. );
  6120. if ( Status != SCESTATUS_SUCCESS )
  6121. ScepLogOutput3(1, ScepSceStatusToDosError(Status),
  6122. SCEDLL_TIMESTAMP_ERROR, L"SAP");
  6123. } else
  6124. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  6125. SCEDLL_TIMESTAMP_ERROR, L"SAP");
  6126. }
  6127. //
  6128. // recover the SAP profile if errors
  6129. //
  6130. if (rc != SCESTATUS_SUCCESS) {
  6131. //
  6132. // rollback all changes
  6133. //
  6134. // SceJetRollback( hProfile, 0 );
  6135. ScepLogOutput3(0, ScepSceStatusToDosError(rc), SCEDLL_SAP_ERROR_OUT);
  6136. } else {
  6137. //
  6138. // Commit the transaction
  6139. //
  6140. // SceJetCommitTransaction( hProfile, 0 );
  6141. }
  6142. gTotalTicks = 0;
  6143. gCurrentTicks = 0;
  6144. gWarningCode = 0;
  6145. cbClientFlag = 0;
  6146. gOptions = 0;
  6147. //
  6148. // Close the JET section and profile handle
  6149. //
  6150. if ( hSection != NULL )
  6151. SceJetCloseSection( &hSection, TRUE );
  6152. hSection = NULL;
  6153. if ( hProfile != NULL )
  6154. SceJetCloseFile( hProfile, TRUE, FALSE );
  6155. hProfile = NULL;
  6156. return( SCESTATUS_SUCCESS );
  6157. }
  6158. DWORD
  6159. ScepSaveDsStatusToSection(
  6160. IN PWSTR ObjectName,
  6161. IN BOOL IsContainer,
  6162. IN BYTE Flag,
  6163. IN PWSTR Value,
  6164. IN DWORD ValueLen
  6165. )
  6166. {
  6167. SCESTATUS rc;
  6168. PWSTR SaveName;
  6169. rc = ScepConvertLdapToJetIndexName(
  6170. ObjectName,
  6171. &SaveName
  6172. );
  6173. if ( rc == SCESTATUS_SUCCESS ) {
  6174. rc = ScepSaveObjectString(
  6175. hSection,
  6176. SaveName,
  6177. IsContainer,
  6178. Flag,
  6179. Value,
  6180. ValueLen
  6181. );
  6182. ScepFree(SaveName);
  6183. }
  6184. return(ScepSceStatusToDosError(rc));
  6185. }
  6186. //****************************************************
  6187. // migration functions
  6188. //
  6189. SCESTATUS
  6190. ScepMigrateDatabase(
  6191. IN PSCECONTEXT cxtProfile,
  6192. IN BOOL bSystemDb
  6193. )
  6194. {
  6195. SCESTATUS rc;
  6196. FLOAT CurrentVersion;
  6197. rc = SceJetCheckVersion( cxtProfile, &CurrentVersion );
  6198. ScepPostProgress(0, 0, NULL);
  6199. if ( rc == SCESTATUS_BAD_FORMAT ) {
  6200. if ( CurrentVersion < (FLOAT)1.2 ) {
  6201. rc = SCESTATUS_SUCCESS;
  6202. if ( bSystemDb ) {
  6203. //
  6204. // just simply delete the local policy and SAP table
  6205. // ignore error occured (e.g, table doesn't exist)
  6206. //
  6207. ScepDeleteInfoForAreas(
  6208. cxtProfile,
  6209. SCE_ENGINE_SMP,
  6210. AREA_ALL
  6211. );
  6212. SceJetDeleteTable( cxtProfile, "SmTblSap", SCEJET_TABLE_SAP );
  6213. ScepPostProgress(4*TICKS_MIGRATION_SECTION, 0, NULL);
  6214. } else {
  6215. //
  6216. // database format is wrong, migrate it
  6217. // Version 1.1: it only contains SDDL syntax change
  6218. // which applies to file/key/DS object/services (general)
  6219. // Version 1.2: table format change (SCP, GPO), more columns
  6220. //
  6221. // service extensions should handle their changes respectively
  6222. // should be handled by WMI schema
  6223. //
  6224. if ( CurrentVersion != (FLOAT)1.1 ) {
  6225. rc = ScepMigrateDatabaseRevision0( cxtProfile );
  6226. } else {
  6227. ScepPostProgress(4*TICKS_MIGRATION_SECTION, 0, NULL);
  6228. }
  6229. }
  6230. if ( SCESTATUS_SUCCESS == rc ) {
  6231. rc = ScepMigrateDatabaseRevision1( cxtProfile );
  6232. }
  6233. ScepPostProgress(TICKS_MIGRATION_V11, 0, NULL);
  6234. } else if ( CurrentVersion == (FLOAT)1.2 ) {
  6235. //
  6236. // current version, no need to migrate
  6237. //
  6238. } // else newer version, BAD_FORMAT
  6239. }
  6240. return rc;
  6241. }
  6242. SCESTATUS
  6243. ScepMigrateDatabaseRevision0(
  6244. IN PSCECONTEXT cxtProfile
  6245. )
  6246. {
  6247. SCESTATUS rc;
  6248. DWORD nTickedSection=0;
  6249. rc = ScepMigrateObjectSection(
  6250. cxtProfile,
  6251. szFileSecurity
  6252. );
  6253. ScepPostProgress(TICKS_MIGRATION_SECTION, 0, NULL);
  6254. nTickedSection++;
  6255. if ( rc == SCESTATUS_SUCCESS ) {
  6256. rc = ScepMigrateObjectSection(
  6257. cxtProfile,
  6258. szRegistryKeys
  6259. );
  6260. ScepPostProgress(TICKS_MIGRATION_SECTION, 0, NULL);
  6261. nTickedSection++;
  6262. if ( rc == SCESTATUS_SUCCESS ) {
  6263. rc = ScepMigrateObjectSection(
  6264. cxtProfile,
  6265. szDSSecurity
  6266. );
  6267. ScepPostProgress(TICKS_MIGRATION_SECTION, 0, NULL);
  6268. nTickedSection++;
  6269. if ( rc == SCESTATUS_SUCCESS ) {
  6270. rc = ScepMigrateObjectSection(
  6271. cxtProfile,
  6272. szServiceGeneral
  6273. );
  6274. if ( rc == SCESTATUS_SUCCESS ) {
  6275. //
  6276. // delete everything in SCP
  6277. //
  6278. SceJetDeleteAll( cxtProfile,
  6279. "SmTblScp",
  6280. SCEJET_TABLE_SCP
  6281. );
  6282. //
  6283. // change version number to 1.1 now
  6284. //
  6285. FLOAT Version = (FLOAT)1.1;
  6286. rc = SceJetSetValueInVersion(
  6287. cxtProfile,
  6288. "SmTblVersion",
  6289. "Version",
  6290. (PWSTR)(&Version), //(PWSTR)CharTimeStamp,
  6291. 4, // number of bytes
  6292. JET_prepReplace
  6293. );
  6294. }
  6295. ScepPostProgress(TICKS_MIGRATION_SECTION, 0, NULL);
  6296. nTickedSection++;
  6297. }
  6298. }
  6299. }
  6300. if ( nTickedSection < 4 ) {
  6301. ScepPostProgress((4-nTickedSection)*TICKS_MIGRATION_SECTION, 0, NULL);
  6302. }
  6303. return rc;
  6304. }
  6305. SCESTATUS
  6306. ScepMigrateObjectSection(
  6307. IN PSCECONTEXT cxtProfile,
  6308. IN PCWSTR szSection
  6309. )
  6310. {
  6311. //
  6312. // should update all three tables (SCP/SMP/SAP)
  6313. // we could just wipe SCP/SAP when SCP is used for accumulated policy
  6314. //
  6315. DOUBLE SectionID = 0;
  6316. SCESTATUS rc;
  6317. //
  6318. // get section id
  6319. //
  6320. rc = SceJetGetSectionIDByName(
  6321. cxtProfile,
  6322. szSection,
  6323. &SectionID
  6324. );
  6325. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  6326. rc = SCESTATUS_SUCCESS;
  6327. } else if ( rc != SCESTATUS_SUCCESS )
  6328. return(rc);
  6329. PSCESECTION h_Section = NULL;
  6330. if ( cxtProfile->JetSmpID != JET_tableidNil ) {
  6331. //
  6332. // SMP table
  6333. //
  6334. rc = SceJetOpenSection(
  6335. cxtProfile,
  6336. SectionID,
  6337. SCEJET_TABLE_SMP,
  6338. &h_Section
  6339. );
  6340. if ( SCESTATUS_SUCCESS == rc ) {
  6341. rc = ScepMigrateOneSection(h_Section);
  6342. }
  6343. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  6344. rc = SCESTATUS_SUCCESS;
  6345. }
  6346. }
  6347. if ( SCESTATUS_SUCCESS == rc &&
  6348. cxtProfile->JetSapID != JET_tableidNil ) {
  6349. //
  6350. // SAP table
  6351. //
  6352. rc = SceJetOpenSection(
  6353. cxtProfile,
  6354. SectionID,
  6355. SCEJET_TABLE_SAP,
  6356. &h_Section
  6357. );
  6358. if ( SCESTATUS_SUCCESS == rc ) {
  6359. rc = ScepMigrateOneSection(h_Section);
  6360. }
  6361. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  6362. rc = SCESTATUS_SUCCESS;
  6363. }
  6364. }
  6365. //
  6366. // SCP table is now pointing to SMP table, no need to migrate
  6367. // all contents in SCP table should be deleted and repropped
  6368. // by policy propagation
  6369. //
  6370. if ( h_Section ) {
  6371. SceJetCloseSection(&h_Section, TRUE);
  6372. }
  6373. return rc;
  6374. }
  6375. SCESTATUS
  6376. ScepMigrateOneSection(
  6377. PSCESECTION hSection
  6378. )
  6379. {
  6380. SCESTATUS rc;
  6381. //
  6382. // goto the first line of this section
  6383. //
  6384. rc = SceJetSeek(
  6385. hSection,
  6386. NULL,
  6387. 0,
  6388. SCEJET_SEEK_GE
  6389. );
  6390. PWSTR pszValue=NULL;
  6391. DWORD ValueSize=0;
  6392. DWORD NewSize;
  6393. while ( rc == SCESTATUS_SUCCESS ) {
  6394. rc = SceJetGetValue(
  6395. hSection,
  6396. SCEJET_CURRENT,
  6397. NULL,
  6398. NULL,
  6399. 0,
  6400. NULL,
  6401. NULL,
  6402. 0,
  6403. &ValueSize
  6404. );
  6405. if ( SCESTATUS_SUCCESS == rc ) {
  6406. pszValue = (PWSTR)LocalAlloc(LPTR, ValueSize+sizeof(WCHAR));
  6407. if ( pszValue ) {
  6408. //
  6409. // get the value
  6410. //
  6411. rc = SceJetGetValue(
  6412. hSection,
  6413. SCEJET_CURRENT,
  6414. NULL,
  6415. NULL,
  6416. 0,
  6417. NULL,
  6418. pszValue,
  6419. ValueSize,
  6420. &NewSize
  6421. );
  6422. if ( SCESTATUS_SUCCESS == rc ) {
  6423. //
  6424. // browse the value field and convert it into new SDDL format
  6425. // the output is saved in the same buffer
  6426. //
  6427. pszValue[ValueSize/2] = L'\0';
  6428. rc = ScepConvertToSDDLFormat(pszValue, ValueSize/2);
  6429. if ( SCESTATUS_SUCCESS == rc ) {
  6430. rc = SceJetSetCurrentLine(
  6431. hSection,
  6432. pszValue,
  6433. ValueSize
  6434. );
  6435. }
  6436. }
  6437. LocalFree(pszValue);
  6438. pszValue = NULL;
  6439. } else {
  6440. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  6441. }
  6442. }
  6443. if ( rc != SCESTATUS_SUCCESS ) {
  6444. break;
  6445. }
  6446. //
  6447. // read next line
  6448. //
  6449. rc = SceJetGetValue(
  6450. hSection,
  6451. SCEJET_NEXT_LINE,
  6452. NULL,
  6453. NULL,
  6454. 0,
  6455. NULL,
  6456. NULL,
  6457. 0,
  6458. &ValueSize
  6459. );
  6460. }
  6461. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  6462. rc = SCESTATUS_SUCCESS;
  6463. }
  6464. return rc;
  6465. }
  6466. SCESTATUS
  6467. ScepMigrateDatabaseRevision1(
  6468. IN PSCECONTEXT cxtProfile
  6469. )
  6470. {
  6471. if ( cxtProfile == NULL ) {
  6472. return SCESTATUS_INVALID_PARAMETER;
  6473. }
  6474. JET_ERR JetErr;
  6475. SCESTATUS rc;
  6476. JET_TABLEID TableID;
  6477. JET_COLUMNDEF ColumnDef;
  6478. JET_COLUMNID ColumnID;
  6479. rc = SceJetStartTransaction( cxtProfile );
  6480. if ( SCESTATUS_SUCCESS != rc ) {
  6481. return(rc);
  6482. }
  6483. //
  6484. // add "LastUsedMergeTable field to the version table
  6485. //
  6486. rc = SceJetOpenTable(
  6487. cxtProfile,
  6488. "SmTblVersion",
  6489. SCEJET_TABLE_VERSION,
  6490. SCEJET_OPEN_READ_WRITE,
  6491. &TableID
  6492. );
  6493. if ( SCESTATUS_SUCCESS == rc ) {
  6494. ColumnDef.cbStruct = sizeof(JET_COLUMNDEF);
  6495. ColumnDef.columnid = 0;
  6496. ColumnDef.coltyp = JET_coltypLong;
  6497. ColumnDef.wCountry = 0;
  6498. ColumnDef.langid = 0;
  6499. ColumnDef.cp = 0;
  6500. ColumnDef.wCollate = 0;
  6501. ColumnDef.cbMax = 4;
  6502. ColumnDef.grbit = 0;
  6503. JetErr = JetAddColumn(
  6504. cxtProfile->JetSessionID,
  6505. TableID,
  6506. "LastUsedMergeTable",
  6507. &ColumnDef,
  6508. NULL,
  6509. 0,
  6510. &ColumnID
  6511. );
  6512. if ( JET_errColumnDuplicate == JetErr ) {
  6513. //
  6514. // column already exist
  6515. //
  6516. JetErr = JET_errSuccess;
  6517. }
  6518. rc = SceJetJetErrorToSceStatus(JetErr);
  6519. JetCloseTable(
  6520. cxtProfile->JetSessionID,
  6521. TableID
  6522. );
  6523. }
  6524. //
  6525. // add "GpoID" filed to the SCP tables
  6526. //
  6527. if ( SCESTATUS_SUCCESS == rc ) {
  6528. TableID = JET_tableidNil;
  6529. rc = SceJetOpenTable(
  6530. cxtProfile,
  6531. "SmTblScp",
  6532. SCEJET_TABLE_SCP,
  6533. SCEJET_OPEN_READ_WRITE,
  6534. &TableID
  6535. );
  6536. if ( SCESTATUS_SUCCESS == rc ) {
  6537. ColumnDef.cbStruct = sizeof(JET_COLUMNDEF);
  6538. ColumnDef.columnid = 0;
  6539. ColumnDef.coltyp = JET_coltypLong;
  6540. ColumnDef.wCountry = 0;
  6541. ColumnDef.langid = 0;
  6542. ColumnDef.cp = 0;
  6543. ColumnDef.wCollate = 0;
  6544. ColumnDef.cbMax = 4;
  6545. ColumnDef.grbit = 0;
  6546. JetErr = JetAddColumn(
  6547. cxtProfile->JetSessionID,
  6548. TableID,
  6549. "GpoID",
  6550. &ColumnDef,
  6551. NULL,
  6552. 0,
  6553. &ColumnID
  6554. );
  6555. if ( JET_errColumnDuplicate == JetErr ) {
  6556. //
  6557. // column already exist
  6558. //
  6559. JetErr = JET_errSuccess;
  6560. }
  6561. rc = SceJetJetErrorToSceStatus(JetErr);
  6562. JetCloseTable(
  6563. cxtProfile->JetSessionID,
  6564. TableID
  6565. );
  6566. }
  6567. }
  6568. if ( SCESTATUS_SUCCESS == rc ) {
  6569. //
  6570. // create the second SCP table
  6571. //
  6572. rc = SceJetCreateTable(
  6573. cxtProfile,
  6574. "SmTblScp2",
  6575. SCEJET_TABLE_SCP,
  6576. SCEJET_CREATE_NO_TABLEID,
  6577. NULL,
  6578. NULL
  6579. );
  6580. if ( rc == SCESTATUS_SUCCESS ) {
  6581. //
  6582. // create the GPO table
  6583. //
  6584. rc = SceJetCreateTable(
  6585. cxtProfile,
  6586. "SmTblGpo",
  6587. SCEJET_TABLE_GPO,
  6588. SCEJET_CREATE_NO_TABLEID,
  6589. NULL,
  6590. NULL
  6591. );
  6592. }
  6593. }
  6594. if ( SCESTATUS_SUCCESS == rc ) {
  6595. //
  6596. // set new version #
  6597. //
  6598. FLOAT Version = (FLOAT)1.2;
  6599. rc = SceJetSetValueInVersion(
  6600. cxtProfile,
  6601. "SmTblVersion",
  6602. "Version",
  6603. (PWSTR)(&Version),
  6604. 4, // number of bytes
  6605. JET_prepReplace
  6606. );
  6607. }
  6608. if ( SCESTATUS_SUCCESS == rc ) {
  6609. SceJetCommitTransaction( cxtProfile, 0 );
  6610. } else {
  6611. SceJetRollback( cxtProfile, 0 );
  6612. }
  6613. return(rc);
  6614. }
  6615. SCESTATUS
  6616. ScepDeleteOldRegValuesFromTable(
  6617. IN PSCECONTEXT hProfile,
  6618. IN SCETYPE TableType
  6619. )
  6620. {
  6621. PSCESECTION h_Section=NULL;
  6622. if ( ScepOpenSectionForName(
  6623. hProfile,
  6624. TableType,
  6625. szRegistryValues,
  6626. &h_Section
  6627. ) == SCESTATUS_SUCCESS ) {
  6628. SceJetDelete(
  6629. h_Section,
  6630. TEXT("machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\disablecad"),
  6631. FALSE,
  6632. SCEJET_DELETE_LINE
  6633. );
  6634. SceJetDelete(
  6635. h_Section,
  6636. TEXT("machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\dontdisplaylastusername"),
  6637. FALSE,
  6638. SCEJET_DELETE_LINE
  6639. );
  6640. SceJetDelete(
  6641. h_Section,
  6642. TEXT("machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\legalnoticecaption"),
  6643. FALSE,
  6644. SCEJET_DELETE_LINE
  6645. );
  6646. SceJetDelete(
  6647. h_Section,
  6648. TEXT("machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\legalnoticetext"),
  6649. FALSE,
  6650. SCEJET_DELETE_LINE
  6651. );
  6652. SceJetDelete(
  6653. h_Section,
  6654. TEXT("machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\shutdownwithoutlogon"),
  6655. FALSE,
  6656. SCEJET_DELETE_LINE
  6657. );
  6658. SceJetDelete(
  6659. h_Section,
  6660. TEXT("machine\\system\\currentcontrolset\\control\\lsa\\fullprivilegeauditing"),
  6661. FALSE,
  6662. SCEJET_DELETE_LINE
  6663. );
  6664. SceJetCloseSection( &h_Section, TRUE );
  6665. }
  6666. return(SCESTATUS_SUCCESS);
  6667. }
  6668. BOOL
  6669. ScepCompareGroupNameList(
  6670. IN PUNICODE_STRING DomainName,
  6671. IN PSCE_NAME_LIST pListToCmp,
  6672. IN PSCE_NAME_LIST pList
  6673. )
  6674. {
  6675. if ( DomainName == NULL ) {
  6676. return(SceCompareNameList(pListToCmp, pList));
  6677. }
  6678. PSCE_NAME_LIST pTmpList, pTL2;
  6679. DWORD count1, count2;
  6680. PWSTR pTemp1, pTemp2;
  6681. for ( pTmpList=pListToCmp, count2=0; pTmpList!=NULL; pTmpList=pTmpList->Next) {
  6682. if ( pTmpList->Name != NULL ) {
  6683. count2++;
  6684. }
  6685. }
  6686. for ( pTmpList=pList,count1=0; pTmpList!=NULL; pTmpList=pTmpList->Next) {
  6687. if ( pTmpList->Name == NULL ) {
  6688. continue;
  6689. }
  6690. count1++;
  6691. pTemp1 = wcschr(pTmpList->Name, L'\\');
  6692. for ( pTL2=pListToCmp; pTL2 != NULL; pTL2=pTL2->Next ) {
  6693. if ( pTL2->Name == NULL ) {
  6694. continue;
  6695. }
  6696. pTemp2 = wcschr(pTmpList->Name, L'\\');
  6697. if ( ( pTemp1 == NULL && pTemp2 == NULL ) ||
  6698. ( pTemp1 != NULL && pTemp2 != NULL ) ) {
  6699. if ( _wcsicmp( pTL2->Name, pTmpList->Name) == 0 ) {
  6700. break;
  6701. }
  6702. } else if ( pTemp1 == NULL ) {
  6703. if ( _wcsicmp( pTmpList->Name, pTemp2+1) == 0 ) {
  6704. //
  6705. // check if pTL2->Name's domain name equal to the account name
  6706. //
  6707. if ( pTemp2-pTL2->Name == DomainName->Length/2 &&
  6708. _wcsnicmp( pTL2->Name, DomainName->Buffer, DomainName->Length/2) == 0 ) {
  6709. break;
  6710. }
  6711. }
  6712. } else {
  6713. //
  6714. // if there is domain prefix, it must be acocunt domain
  6715. // because this list is built by querying system
  6716. //
  6717. if ( _wcsicmp(pTemp1+1, pTL2->Name) == 0 ) {
  6718. break;
  6719. }
  6720. }
  6721. }
  6722. if ( pTL2 == NULL ) {
  6723. return(FALSE);
  6724. }
  6725. }
  6726. if ( count1 == count2 ) {
  6727. return(TRUE);
  6728. } else {
  6729. return(FALSE);
  6730. }
  6731. }
  6732. SCESTATUS
  6733. ScepGetSystemSecurity(
  6734. IN AREA_INFORMATION Area,
  6735. IN DWORD Options,
  6736. OUT PSCE_PROFILE_INFO *ppInfo,
  6737. OUT PSCE_ERROR_LOG_INFO *pErrLog
  6738. )
  6739. //
  6740. // query system settings for system access and user rights area only
  6741. //
  6742. {
  6743. SCESTATUS Saverc = SCESTATUS_SUCCESS;
  6744. SCESTATUS rc;
  6745. if ( ppInfo == NULL || Area == 0 ) {
  6746. //
  6747. // nothing to set
  6748. //
  6749. return(Saverc);
  6750. }
  6751. //
  6752. // initialize product type etc.
  6753. //
  6754. if ( RtlGetNtProductType (&ProductType) == FALSE ) {
  6755. return( ScepDosErrorToSceStatus(GetLastError()));
  6756. }
  6757. //
  6758. // allocate memory
  6759. //
  6760. *ppInfo = (PSCE_PROFILE_INFO)ScepAlloc( (UINT)0, sizeof(SCE_PROFILE_INFO));
  6761. if ( *ppInfo == NULL ) {
  6762. return( SCESTATUS_NOT_ENOUGH_RESOURCE );
  6763. }
  6764. //
  6765. // reset local policy
  6766. //
  6767. memset(*ppInfo, '\0', sizeof(SCE_PROFILE_INFO));
  6768. ScepResetSecurityPolicyArea(*ppInfo);
  6769. (*ppInfo)->Type = SCE_ENGINE_SMP;
  6770. if ( Area & AREA_PRIVILEGES ) {
  6771. rc = ScepGetSystemPrivileges( Options,
  6772. pErrLog,
  6773. &((*ppInfo)->OtherInfo.smp.pPrivilegeAssignedTo)
  6774. );
  6775. if( rc != SCESTATUS_SUCCESS ) {
  6776. Saverc = rc;
  6777. }
  6778. }
  6779. if ( Area & AREA_SECURITY_POLICY ) {
  6780. //
  6781. // snapshot system access. Errors are logged within this function
  6782. //
  6783. rc = ScepAnalyzeSystemAccess(*ppInfo, NULL,
  6784. SCEPOL_SYSTEM_SETTINGS,
  6785. NULL, pErrLog);
  6786. if( rc != SCESTATUS_SUCCESS ) {
  6787. Saverc = rc;
  6788. }
  6789. //
  6790. // Audit policy
  6791. //
  6792. PPOLICY_AUDIT_EVENTS_INFO AuditEvent=NULL;
  6793. rc = ScepSaveAndOffAuditing(&AuditEvent, FALSE, NULL);
  6794. if ( rc == SCESTATUS_SUCCESS && AuditEvent ) {
  6795. //
  6796. // assign auditEvent buffer to the output buffer
  6797. //
  6798. if ( !AuditEvent->AuditingMode ) {
  6799. for ( DWORD i=0; i<AuditEvent->MaximumAuditEventCount; i++ )
  6800. AuditEvent->EventAuditingOptions[i] = 0;
  6801. }
  6802. (*ppInfo)->AuditSystemEvents = AuditEvent->EventAuditingOptions[AuditCategorySystem];
  6803. (*ppInfo)->AuditLogonEvents = AuditEvent->EventAuditingOptions[AuditCategoryLogon];
  6804. (*ppInfo)->AuditObjectAccess = AuditEvent->EventAuditingOptions[AuditCategoryObjectAccess];
  6805. (*ppInfo)->AuditPrivilegeUse = AuditEvent->EventAuditingOptions[AuditCategoryPrivilegeUse];
  6806. (*ppInfo)->AuditProcessTracking = AuditEvent->EventAuditingOptions[AuditCategoryDetailedTracking];
  6807. (*ppInfo)->AuditPolicyChange = AuditEvent->EventAuditingOptions[AuditCategoryPolicyChange];
  6808. (*ppInfo)->AuditAccountManage = AuditEvent->EventAuditingOptions[AuditCategoryAccountManagement];
  6809. (*ppInfo)->AuditDSAccess = AuditEvent->EventAuditingOptions[AuditCategoryDirectoryServiceAccess];
  6810. (*ppInfo)->AuditAccountLogon = AuditEvent->EventAuditingOptions[AuditCategoryAccountLogon];
  6811. } else {
  6812. ScepBuildErrorLogInfo(
  6813. ScepSceStatusToDosError(rc),
  6814. pErrLog,
  6815. SCEDLL_ERROR_QUERY_EVENT_AUDITING
  6816. );
  6817. }
  6818. if ( AuditEvent ) {
  6819. LsaFreeMemory(AuditEvent);
  6820. }
  6821. if( rc != SCESTATUS_SUCCESS ) {
  6822. Saverc = rc;
  6823. }
  6824. //
  6825. // Kerberos Policy
  6826. //
  6827. (*ppInfo)->pKerberosInfo = (PSCE_KERBEROS_TICKET_INFO)ScepAlloc(LPTR,sizeof(SCE_KERBEROS_TICKET_INFO));
  6828. if ( (*ppInfo)->pKerberosInfo ) {
  6829. (*ppInfo)->pKerberosInfo->MaxTicketAge = SCE_NO_VALUE;
  6830. (*ppInfo)->pKerberosInfo->MaxRenewAge = SCE_NO_VALUE;
  6831. (*ppInfo)->pKerberosInfo->MaxServiceAge = SCE_NO_VALUE;
  6832. (*ppInfo)->pKerberosInfo->MaxClockSkew = SCE_NO_VALUE;
  6833. (*ppInfo)->pKerberosInfo->TicketValidateClient = SCE_NO_VALUE;
  6834. rc = ScepAnalyzeKerberosPolicy(NULL,
  6835. (*ppInfo)->pKerberosInfo,
  6836. Options | SCE_SYSTEM_SETTINGS
  6837. );
  6838. } else {
  6839. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  6840. }
  6841. if( rc != SCESTATUS_SUCCESS ) {
  6842. ScepBuildErrorLogInfo(
  6843. ScepSceStatusToDosError(rc),
  6844. pErrLog,
  6845. SCEDLL_SAP_ERROR_KERBEROS
  6846. );
  6847. Saverc = rc;
  6848. }
  6849. //
  6850. // registry values
  6851. //
  6852. rc = ScepAnalyzeRegistryValues(NULL,
  6853. SCEREG_VALUE_SYSTEM,
  6854. *ppInfo
  6855. );
  6856. if( rc != SCESTATUS_SUCCESS ) {
  6857. ScepBuildErrorLogInfo(
  6858. ScepSceStatusToDosError(rc),
  6859. pErrLog,
  6860. SCEDLL_ERROR_QUERY_INFO,
  6861. szRegistryValues
  6862. );
  6863. Saverc = rc;
  6864. }
  6865. }
  6866. //
  6867. // The buffer is not freed even if there is error.
  6868. // because we want to show as many settings as we can.
  6869. //
  6870. return(Saverc);
  6871. }
  6872. SCESTATUS
  6873. ScepGetSystemPrivileges(
  6874. IN DWORD Options,
  6875. IN OUT PSCE_ERROR_LOG_INFO *pErrLog,
  6876. OUT PSCE_PRIVILEGE_ASSIGNMENT *pCurrent
  6877. )
  6878. /*
  6879. query privilege/user right assignments from the current system
  6880. */
  6881. {
  6882. if ( pCurrent == NULL ) {
  6883. return(SCESTATUS_INVALID_PARAMETER);
  6884. }
  6885. NTSTATUS NtStatus;
  6886. LSA_HANDLE PolicyHandle=NULL;
  6887. DWORD rc;
  6888. SCESTATUS saveRc=SCESTATUS_SUCCESS;
  6889. ULONG CountReturned;
  6890. UNICODE_STRING UserRight;
  6891. PLSA_ENUMERATION_INFORMATION EnumBuffer=NULL;
  6892. DWORD i=0, j;
  6893. PLSA_TRANSLATED_NAME Names=NULL;
  6894. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains=NULL;
  6895. PSCE_NAME_LIST pNameList=NULL;
  6896. PSCE_PRIVILEGE_ASSIGNMENT pPrivilege=NULL;
  6897. //
  6898. // Open LSA policy
  6899. //
  6900. NtStatus = ScepOpenLsaPolicy(
  6901. POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES,
  6902. &PolicyHandle,
  6903. TRUE
  6904. );
  6905. if ( !NT_SUCCESS(NtStatus) ) {
  6906. rc = RtlNtStatusToDosError(NtStatus);
  6907. if ( pErrLog ) {
  6908. ScepBuildErrorLogInfo(
  6909. rc,
  6910. pErrLog,
  6911. SCEDLL_LSA_POLICY
  6912. );
  6913. }
  6914. return(ScepDosErrorToSceStatus( rc ));
  6915. }
  6916. //
  6917. // enumerate accounts for each user right
  6918. //
  6919. ScepIsDomainLocal(NULL);
  6920. for ( i=0; i<cPrivCnt; i++) {
  6921. RtlInitUnicodeString( &UserRight, (PCWSTR)(SCE_Privileges[i].Name));
  6922. //
  6923. // now enumerate all accounts for this user right.
  6924. //
  6925. NtStatus = LsaEnumerateAccountsWithUserRight(
  6926. PolicyHandle,
  6927. &UserRight,
  6928. (PVOID *)&EnumBuffer, // account SIDs
  6929. &CountReturned
  6930. );
  6931. rc = RtlNtStatusToDosError(NtStatus);
  6932. if ( !NT_SUCCESS(NtStatus) &&
  6933. NtStatus != STATUS_NO_MORE_ENTRIES &&
  6934. NtStatus != STATUS_NO_SUCH_PRIVILEGE &&
  6935. NtStatus != STATUS_NOT_FOUND ) {
  6936. ScepBuildErrorLogInfo(
  6937. rc,
  6938. pErrLog,
  6939. SCEDLL_SAP_ERROR_ENUMERATE,
  6940. SCE_Privileges[i].Name
  6941. );
  6942. saveRc = ScepDosErrorToSceStatus(rc);
  6943. continue;
  6944. }
  6945. if ( NT_SUCCESS(NtStatus) ) {
  6946. //
  6947. // a sce_privilege_assignment structure. allocate buffer
  6948. //
  6949. pPrivilege = (PSCE_PRIVILEGE_ASSIGNMENT)ScepAlloc( LMEM_ZEROINIT,
  6950. sizeof(SCE_PRIVILEGE_ASSIGNMENT) );
  6951. if ( pPrivilege == NULL ) {
  6952. //
  6953. // when this occurred, the system is hosed.
  6954. // buffer should be freed and error should be returned.
  6955. //
  6956. saveRc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  6957. break;
  6958. }
  6959. pPrivilege->Name = (PWSTR)ScepAlloc( (UINT)0, UserRight.Length+2);
  6960. if ( pPrivilege->Name == NULL ) {
  6961. ScepFree(pPrivilege);
  6962. saveRc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  6963. break;
  6964. }
  6965. wcscpy(pPrivilege->Name, UserRight.Buffer);
  6966. pPrivilege->Value = i;
  6967. pPrivilege->Status = 0;
  6968. // link it to the output buffer
  6969. pPrivilege->Next = *pCurrent;
  6970. *pCurrent = pPrivilege;
  6971. if ( CountReturned > 0 ) {
  6972. //
  6973. // error occurred in lookup will be ignored
  6974. // since accounts will be returned in SID format
  6975. //
  6976. NtStatus = LsaLookupSids(
  6977. PolicyHandle,
  6978. CountReturned,
  6979. (PSID *)EnumBuffer,
  6980. &ReferencedDomains,
  6981. &Names
  6982. );
  6983. rc = RtlNtStatusToDosError(rc);
  6984. if ( NT_SUCCESS(NtStatus) ) {
  6985. //
  6986. // some may not be mapped
  6987. // in this case, return the SID string
  6988. //
  6989. for ( j=0; j<CountReturned; j++ ) {
  6990. if ( Names[j].Use == SidTypeInvalid ||
  6991. Names[j].Use == SidTypeUnknown ||
  6992. Names[j].Use == SidTypeDeletedAccount ) {
  6993. //
  6994. // this name is not mapped, add it in Sid string
  6995. //
  6996. rc = ScepAddSidStringToNameList(&pNameList, EnumBuffer[j].Sid);
  6997. } else {
  6998. //
  6999. // build the full name of each account
  7000. //
  7001. if ( ReferencedDomains->Entries > 0 && Names[j].Use != SidTypeWellKnownGroup &&
  7002. ReferencedDomains->Domains != NULL &&
  7003. Names[j].DomainIndex != -1 &&
  7004. (ULONG)(Names[j].DomainIndex) < ReferencedDomains->Entries &&
  7005. ScepIsDomainLocalBySid(ReferencedDomains->Domains[Names[j].DomainIndex].Sid) == FALSE &&
  7006. ScepIsDomainLocal(&ReferencedDomains->Domains[Names[j].DomainIndex].Name) == FALSE ) {
  7007. //
  7008. // add both domain name and account name
  7009. //
  7010. rc = ScepAddTwoNamesToNameList(
  7011. &pNameList,
  7012. TRUE,
  7013. ReferencedDomains->Domains[Names[j].DomainIndex].Name.Buffer,
  7014. ReferencedDomains->Domains[Names[j].DomainIndex].Name.Length/2,
  7015. Names[j].Name.Buffer,
  7016. Names[j].Name.Length/2);
  7017. } else {
  7018. //
  7019. // add only the account name
  7020. //
  7021. rc = ScepAddToNameList(
  7022. &pNameList,
  7023. Names[j].Name.Buffer,
  7024. Names[j].Name.Length/2);
  7025. }
  7026. }
  7027. if ( NO_ERROR != rc ) {
  7028. pPrivilege->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  7029. saveRc = ScepDosErrorToSceStatus(rc);
  7030. }
  7031. }
  7032. } else {
  7033. //
  7034. // lookup for all sids failed or none is mapped
  7035. // add the SIDs
  7036. //
  7037. for ( j=0; j<CountReturned; j++ ) {
  7038. //
  7039. // build each account into the name list
  7040. // Convert using the Rtl functions
  7041. //
  7042. rc = ScepAddSidStringToNameList(&pNameList, EnumBuffer[j].Sid);
  7043. if ( NO_ERROR != rc ) {
  7044. //
  7045. // mark the status
  7046. //
  7047. pPrivilege->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  7048. saveRc = ScepDosErrorToSceStatus(rc);
  7049. }
  7050. }
  7051. }
  7052. if (ReferencedDomains) {
  7053. LsaFreeMemory(ReferencedDomains);
  7054. ReferencedDomains = NULL;
  7055. }
  7056. if (Names) {
  7057. LsaFreeMemory(Names);
  7058. Names = NULL;
  7059. }
  7060. if ( pPrivilege->Status ) {
  7061. ScepBuildErrorLogInfo(
  7062. rc,
  7063. pErrLog,
  7064. SCEDLL_SAP_ERROR_ENUMERATE,
  7065. SCE_Privileges[i].Name
  7066. );
  7067. }
  7068. pPrivilege->AssignedTo = pNameList;
  7069. pNameList = NULL;
  7070. }
  7071. LsaFreeMemory( EnumBuffer );
  7072. EnumBuffer = NULL;
  7073. } else {
  7074. //
  7075. // no account is assigned this privilege
  7076. // or the privilege is not found
  7077. // should continue the process
  7078. //
  7079. }
  7080. }
  7081. if ( saveRc == SCESTATUS_NOT_ENOUGH_RESOURCE ) {
  7082. //
  7083. // should free the output buffer since there is no more memory
  7084. //
  7085. ScepFreePrivilege(*pCurrent);
  7086. *pCurrent = NULL;
  7087. }
  7088. if ( pNameList != NULL )
  7089. ScepFreeNameList( pNameList );
  7090. LsaClose(PolicyHandle);
  7091. return( saveRc );
  7092. }
  7093. DWORD
  7094. ScepAddSidStringToNameList(
  7095. IN OUT PSCE_NAME_LIST *ppNameList,
  7096. IN PSID pSid
  7097. )
  7098. {
  7099. NTSTATUS NtStatus;
  7100. UNICODE_STRING UnicodeStringSid;
  7101. DWORD rc;
  7102. NtStatus = RtlConvertSidToUnicodeString( &UnicodeStringSid,
  7103. pSid,
  7104. TRUE );
  7105. rc = RtlNtStatusToDosError(NtStatus);
  7106. if ( NT_SUCCESS( NtStatus ) ) {
  7107. rc = ScepAddTwoNamesToNameList(
  7108. ppNameList,
  7109. FALSE,
  7110. L"*",
  7111. 1,
  7112. UnicodeStringSid.Buffer,
  7113. UnicodeStringSid.Length/2
  7114. );
  7115. RtlFreeUnicodeString( &UnicodeStringSid );
  7116. }
  7117. return(rc);
  7118. }
  7119. DWORD
  7120. ScepGetLSAPolicyObjectInfo(
  7121. OUT DWORD *pdwAllow
  7122. )
  7123. /*
  7124. Routine Description:
  7125. This routine checks whether the Anonymous User/SID has permissions to do SID<->name translation.
  7126. No errors are logged by this routine - they will be logged outside if need be.
  7127. Arguments:
  7128. pdwAllow - pointer to the DWORD that is 1 if Anonymous User/SID has this permission, else 0
  7129. Return Value:
  7130. Win32 error code
  7131. */
  7132. {
  7133. NTSTATUS NtStatus = STATUS_SUCCESS;
  7134. DWORD rc = ERROR_SUCCESS;
  7135. PACL pNewAcl = NULL;
  7136. DWORD dwAceType;
  7137. BOOL bAddAce = FALSE;
  7138. PSECURITY_DESCRIPTOR pSDlsaPolicyObject = NULL;
  7139. SECURITY_DESCRIPTOR SDAbsolute;
  7140. if ( pdwAllow == NULL ) {
  7141. return ERROR_INVALID_PARAMETER;
  7142. }
  7143. LSA_HANDLE LsaHandle = NULL;
  7144. NtStatus = ScepOpenLsaPolicy(
  7145. MAXIMUM_ALLOWED,
  7146. &LsaHandle,
  7147. TRUE
  7148. );
  7149. rc = RtlNtStatusToDosError( NtStatus );
  7150. if ( rc == ERROR_SUCCESS ) {
  7151. NtStatus = LsaQuerySecurityObject(
  7152. LsaHandle,
  7153. OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  7154. &pSDlsaPolicyObject
  7155. );
  7156. rc = RtlNtStatusToDosError( NtStatus );
  7157. if ( rc == ERROR_SUCCESS ) {
  7158. if ( ghAuthzResourceManager ) {
  7159. SID AnonymousSid;
  7160. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
  7161. AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext = NULL;
  7162. LUID Identifier = {0};
  7163. RtlInitializeSid ( &AnonymousSid, &NtAuth, 1);
  7164. *RtlSubAuthoritySid ( &AnonymousSid, 0 ) = SECURITY_ANONYMOUS_LOGON_RID;
  7165. if ( AuthzInitializeContextFromSid(0,
  7166. &AnonymousSid,
  7167. ghAuthzResourceManager,
  7168. 0,
  7169. Identifier,
  7170. NULL,
  7171. &hAuthzClientContext) ) {
  7172. AUTHZ_ACCESS_REPLY AuthzReply;
  7173. AUTHZ_ACCESS_REQUEST AuthzRequest;
  7174. ACCESS_MASK GrantedAccessMask;
  7175. DWORD AuthzError;
  7176. AuthzReply.ResultListLength = 1;
  7177. AuthzReply.GrantedAccessMask = &GrantedAccessMask;
  7178. AuthzReply.Error = &AuthzError;
  7179. AuthzReply.SaclEvaluationResults = NULL;
  7180. memset(&AuthzRequest, 0, sizeof(AuthzRequest));
  7181. AuthzRequest.DesiredAccess = POLICY_LOOKUP_NAMES;
  7182. if ( AuthzAccessCheck(0,
  7183. hAuthzClientContext,
  7184. &AuthzRequest,
  7185. NULL,
  7186. pSDlsaPolicyObject,
  7187. NULL,
  7188. NULL,
  7189. &AuthzReply,
  7190. NULL) ) {
  7191. //
  7192. // check if existing access is different from desired access
  7193. // if so, add the appropriate ACE
  7194. //
  7195. if ( GrantedAccessMask & POLICY_LOOKUP_NAMES ) {
  7196. //ASSERT(AuthzError == ERROR_SUCCESS);
  7197. *pdwAllow = 1;
  7198. } else {
  7199. //ASSERT(AuthzError == ERROR_ACCESS_DENIED || AuthzError == ERROR_PRIVILEGE_NOT_HELD);
  7200. *pdwAllow = 0;
  7201. }
  7202. }
  7203. else {
  7204. rc = GetLastError();
  7205. }
  7206. AuthzFreeContext( hAuthzClientContext );
  7207. } else {
  7208. rc = GetLastError();
  7209. }
  7210. }
  7211. else {
  7212. rc = ERROR_RESOURCE_NOT_PRESENT;
  7213. }
  7214. LsaFreeMemory(pSDlsaPolicyObject);
  7215. }
  7216. LsaClose(LsaHandle);
  7217. }
  7218. return rc;
  7219. }