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

9073 lines
264 KiB

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