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

5021 lines
138 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dbinit.c
  5. Abstract:
  6. Local Security Authority - Database Server Initialization
  7. This module contains functions which perform initialization of
  8. the Database Server. Certain information is obtained from the
  9. LSA database and is set up in global data for easy retrieval.
  10. Author:
  11. Scott Birrell (ScottBi) July 25, 1991
  12. Environment:
  13. User Mode
  14. Revision History:
  15. 12-Nov-1997 MikeSw
  16. Added lsa policy handle cache for interdomain lookups
  17. --*/
  18. //
  19. // Define this to allocate all globals in this module
  20. //
  21. #include <lsapch2.h>
  22. #include "lsasrvp.h"
  23. #include "dbp.h"
  24. #include <bndcache.h>
  25. #include <wincrypt.h>
  26. #include <lsapmsgs.h>
  27. #include <ntddnfs.h>
  28. #include <remboot.h>
  29. #ifdef DS_LOOKUP
  30. #include <dslookup.h>
  31. #endif
  32. #include <sertlp.h>
  33. #include <cryptdll.h>
  34. #include <md5.h>
  35. #include <rc4.h>
  36. #include <wxlpc.h>
  37. #include <dnsapi.h>
  38. //
  39. // Well known Sids for security packages include a subauthority equal to
  40. // the associated package's RPC Id. We'll cause a compile time error if
  41. // these numbers ever change.
  42. //
  43. #if (SECURITY_PACKAGE_NTLM_RID != RPC_C_AUTHN_WINNT)
  44. #error SECURITY_PACKAGE_NTLM_RID definition must be equal to \
  45. RPC_C_AUTHN_WINNT
  46. #endif
  47. #if (SECURITY_PACKAGE_DIGEST_RID != RPC_C_AUTHN_DIGEST)
  48. #error SECURITY_PACKAGE_DIGEST_RID definition must equal RPC_C_AUTHN_DIGEST
  49. #endif
  50. #if (SECURITY_PACKAGE_SCHANNEL_RID != RPC_C_AUTHN_GSS_SCHANNEL)
  51. #error SECURITY_PACKAGE_SCHANNEL_RID definition must equal \
  52. RPC_C_AUTHN_GSS_SCHANNEL
  53. #endif
  54. extern LSAP_DB_TRUSTED_DOMAIN_LIST LsapDbTrustedDomainList;
  55. NTSTATUS
  56. LsapDbBuildObjectCaches(
  57. );
  58. NTSTATUS
  59. LsapAssignInitialHiveProtection(
  60. HANDLE HiveRoot
  61. );
  62. NTSTATUS
  63. LsapCreateDatabaseProtection(
  64. PISECURITY_DESCRIPTOR Sd
  65. );
  66. NTSTATUS
  67. LsapGenerateRandomDomainSid(
  68. OUT PSID NewDomainSid
  69. );
  70. NTSTATUS
  71. LsapSetupInitialize(
  72. VOID
  73. );
  74. NTSTATUS
  75. LsapUpdateDatabaseProtection(
  76. IN ULONG Revision
  77. );
  78. NTSTATUS
  79. LsapDsInitFixupQueue(
  80. VOID
  81. );
  82. static UCHAR SyskeyBuffer[LSAP_SYSKEY_SIZE];
  83. static UCHAR OldSyskeyBuffer[LSAP_SYSKEY_SIZE];
  84. NTSTATUS
  85. LsapDbInitializeServer(
  86. IN ULONG Pass
  87. )
  88. /*++
  89. Routine Description:
  90. This function initializes the LSA Database Server. The following
  91. steps are performed:
  92. o Initialize the LSA Database Lock
  93. o Acquire the LSA Database Lock
  94. o Initialize the Unicode Strings for the fixed names within the
  95. LSA Database, e.g. LSA Database object attributes and well-known
  96. object names.
  97. o Initialize the Unicode Strings for the LSA Database Object constant
  98. and well known names, e.g SubKeys, fixed object names.
  99. o Initialize the Unicode Strings for LSA Object Containing Dirs
  100. o Initialize the Generic Mappings for Database Object Types
  101. o Initialize the Lsa Database Handle Table
  102. o Install the LSA Database if necessary - Creates the Lsa Database
  103. o and Manager account objects, and initializes the transaction
  104. subtree
  105. o Initialize the abs min, abs max and installation default quota limits
  106. o Release the LSA Database Lock
  107. Arguments:
  108. None.
  109. Return Value:
  110. NTSTATUS - Standard Nt Result Code
  111. All Result Codes are generated by called routines.
  112. --*/
  113. {
  114. NTSTATUS Status = STATUS_SUCCESS, IgnoreStatus;
  115. BOOL BooleanStatus = TRUE;
  116. BOOLEAN AcquiredLock = FALSE;
  117. BOOLEAN FreeComputerName = FALSE;
  118. LSAP_DB_OBJECT_INFORMATION ObjectInformation;
  119. PLSAPR_POLICY_ACCOUNT_DOM_INFO PolicyAccountDomainInfo = NULL;
  120. PLSAPR_POLICY_DNS_DOMAIN_INFO PolicyDnsDomainInfo = NULL;
  121. UNICODE_STRING ComputerName, CipherKey;
  122. ULONG Length;
  123. ULONG Revision, RevisionLength = sizeof( ULONG );
  124. DWORD WinStatus;
  125. //
  126. // Initialize the LSA Database Lock and set it into the locked state
  127. //
  128. if (Pass == 1 ) {
  129. LsapDsDebugInitialize();
  130. RtlZeroMemory( &LsaDsStateInfo, sizeof( LsaDsStateInfo ) );
  131. LsapDbState.DbServerInitialized = FALSE;
  132. #if DBG
  133. LsapDbState.RegistryTransactionOpen = FALSE;
  134. #endif
  135. //
  136. // Disable Replicator Notifications.
  137. //
  138. LsapDbDisableReplicatorNotification();
  139. //
  140. // This function call will initialize all of the global or well known locks used by
  141. // the Lsa
  142. //
  143. Status = LsapDbInitializeLock();
  144. if (!NT_SUCCESS(Status)) {
  145. goto InitializeServerError;
  146. }
  147. Status = LsapDbInitHandleTables();
  148. if (!NT_SUCCESS(Status)) {
  149. goto InitializeServerError;
  150. }
  151. //
  152. // Initialize the forest trust cache.
  153. // The cache is not usable until populated.
  154. //
  155. Status = LsapForestTrustCacheInitialize();
  156. if (!NT_SUCCESS(Status)) {
  157. goto InitializeServerError;
  158. }
  159. //
  160. // Initialize the policy change notification mechanism
  161. //
  162. Status = LsapInitializeNotifiyList();
  163. if ( !NT_SUCCESS( Status ) ) {
  164. goto InitializeServerError ;
  165. }
  166. //
  167. // Initialize the Fixup queue
  168. //
  169. Status = LsapDsInitFixupQueue();
  170. if ( !NT_SUCCESS( Status ))
  171. {
  172. goto InitializeServerError ;
  173. }
  174. //
  175. // Initialize the binding handle cache
  176. //
  177. Status = LsapInitBindingCache();
  178. if (!NT_SUCCESS(Status)) {
  179. goto InitializeServerError;
  180. }
  181. }
  182. //
  183. // Acquire the LSA Database Lock. This allows subroutines to
  184. // assert that the LSA Database is locked. Otherwise, it is
  185. // not actually necessary, given that no other thread can access the
  186. // LSA until initialization is complete.
  187. //
  188. if (Pass == 1) {
  189. //
  190. // Initialize the Unicode Strings for the fixed names within the
  191. // LSA Database, e.g. LSA Database object attributes and well-known
  192. // object names.
  193. //
  194. Status = LsapDbInitializeUnicodeNames();
  195. if (!NT_SUCCESS(Status)) {
  196. goto InitializeServerError;
  197. }
  198. //
  199. // Initialize the Unicode Strings for the Containing Directories for
  200. // each LSA Database Object Type.
  201. //
  202. Status = LsapDbInitializeContainingDirs();
  203. if (!NT_SUCCESS(Status)) {
  204. goto InitializeServerError;
  205. }
  206. //
  207. // Initialize the LSA Subsystem name string. This is needed for
  208. // NtAccessCheckAuditAlarm calls
  209. //
  210. RtlInitUnicodeString(&LsapState.SubsystemName, L"LSA");
  211. //
  212. // Initialize the Shutdown Pending state.
  213. //
  214. LsapState.SystemShutdownPending = FALSE;
  215. //
  216. // Initialize the Database Object Types. Information stored
  217. // includes the Generic mappings and Object Counts.
  218. //
  219. Status = LsapDbInitializeObjectTypes();
  220. if (!NT_SUCCESS(Status)) {
  221. goto InitializeServerError;
  222. }
  223. //
  224. // Open the LSA Database root Registry subkey. This stays
  225. // open for use in adding transactions.
  226. //
  227. Status = LsapDbOpenRootRegistryKey();
  228. if (!NT_SUCCESS(Status)) {
  229. goto InitializeServerError;
  230. }
  231. //
  232. // Initialize the Lsa Database Cipher Key
  233. // This hard-coded key is used for retrieving old pre-NT4 SP4
  234. // encrypted keys only
  235. //
  236. RtlInitUnicodeString( &CipherKey, L"823543" );
  237. Status = LsapDbInitializeCipherKey( &CipherKey,
  238. &LsapDbCipherKey );
  239. if (!NT_SUCCESS(Status)) {
  240. goto InitializeServerError;
  241. }
  242. //
  243. // Initialize the LSA Database Transaction Subtree, creating it if
  244. // one does not already exist. If the Transaction Subtree exists,
  245. // commit any partially committed transaction if appropriate.
  246. //
  247. Status = RtlInitializeRXact(
  248. LsapDbState.DbRootRegKeyHandle,
  249. TRUE,
  250. (PRTL_RXACT_CONTEXT *) &LsapDbState.RXactContext
  251. );
  252. if (!NT_SUCCESS(Status)) {
  253. if (Status != STATUS_RXACT_STATE_CREATED) {
  254. LsapLogError(
  255. "LsapDbInitializeServer: Registry Transaction Init returned 0x%lx\n",
  256. Status
  257. );
  258. goto InitializeServerError;
  259. }
  260. LsapLogError(
  261. "LsapDbInitializeServer: Registry Transaction State Did Not Exist\n",
  262. Status
  263. );
  264. goto InitializeServerError;
  265. }
  266. //
  267. // Setup attributes for opening the Policy object.
  268. //
  269. ObjectInformation.ObjectTypeId = PolicyObject;
  270. ObjectInformation.ContainerTypeId = 0;
  271. ObjectInformation.Sid = NULL;
  272. ObjectInformation.ObjectAttributeNameOnly = FALSE;
  273. ObjectInformation.DesiredObjectAccess = 0;
  274. InitializeObjectAttributes(
  275. &ObjectInformation.ObjectAttributes,
  276. &LsapDbNames[Policy],
  277. 0L,
  278. NULL,
  279. NULL
  280. );
  281. //
  282. // Now try to open the root LSA Database object (Policy). This is a
  283. // trusted call, so no access checking or impersonation will be done.
  284. // Note that the handle obtained will remain open indefinitely. It is
  285. // used after initialization for all internally generated accesses to
  286. // the Policy object
  287. //
  288. Status = LsapDbOpenObject(
  289. &ObjectInformation,
  290. 0L,
  291. LSAP_DB_TRUSTED,
  292. &LsapDbHandle
  293. );
  294. if (!NT_SUCCESS(Status)) {
  295. //
  296. // Open of LSA Database object failed. If any error other than
  297. // object not found, there is a serious error which prevents the
  298. // LSA from functioning, so abort.
  299. //
  300. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  301. LsapLogError(
  302. "LsapDbInitializeServer: Open failed 0x%lx\n"
  303. "The Lsa Database must be reinstalled or manually\n"
  304. "erased before using the system\n",
  305. Status
  306. );
  307. goto InitializeServerError;
  308. }
  309. //
  310. // The Lsa Database object was not found. Run the database installation
  311. // routine so that people can boot without having to run the
  312. // installation applet first.
  313. //
  314. LsapDatabaseSetupPerformed = TRUE;
  315. Status = LsapDbInstallLsaDatabase(1);
  316. if (!NT_SUCCESS(Status)) {
  317. goto InitializeServerError;
  318. }
  319. }
  320. //
  321. // The Lsa Database object was successfully opened, possibly after
  322. // having just been created. Proceed with the rest of server
  323. // initialization. First, setup in-memory copies of the Installation
  324. // Default, Absolute Min and Absolute Max system quota limits.
  325. //
  326. //
  327. // Make the policy handle available throughout LSA
  328. //
  329. LsapPolicyHandle = LsapDbHandle;
  330. if (!NT_SUCCESS(Status)) {
  331. goto InitializeServerError;
  332. }
  333. //
  334. // Bring the database up to the current revision level,
  335. // if necessary. This is not a syskey upgrade.
  336. //
  337. Status = LsapDbUpgradeRevision(FALSE,FALSE);
  338. if (!NT_SUCCESS(Status)) {
  339. goto InitializeServerError;
  340. }
  341. //
  342. // Read the revision attribute. If the revision is greater than
  343. // LSAP_DB_REVSION_1_5 then obtain the syskey from winlogon. In previous
  344. // revisions SAM would have obtained the syskey from winlogon if the machine
  345. // had been syskey'd
  346. //
  347. Status = LsapDbReadAttributeObject(
  348. LsapDbHandle,
  349. &LsapDbNames[PolRevision],
  350. (PVOID) &Revision,
  351. &RevisionLength
  352. );
  353. if ( !NT_SUCCESS(Status) ) {
  354. goto InitializeServerError;
  355. }
  356. //
  357. // Query the syskey from winlogon. Do so only if the revision is greater than 1_5.
  358. // This is because in previous builds SAM used to manage the syskey. From this
  359. // release onwards. The below routine also intializes the LSA encryption key
  360. //
  361. if (Revision >= LSAP_DB_REVISION_1_5)
  362. {
  363. Status = LsapDbGetSyskeyFromWinlogon();
  364. if (!NT_SUCCESS(Status))
  365. {
  366. goto InitializeServerError;
  367. }
  368. }
  369. //
  370. // Initialize privilege object related code
  371. //
  372. Status = LsapDbInitializePrivilegeObject();
  373. if (!NT_SUCCESS(Status)) {
  374. goto InitializeServerError;
  375. }
  376. //
  377. // Perform initialization for the Replicator. Replications
  378. // are still disabled at this point.
  379. //
  380. Status = LsapDbInitializeReplication();
  381. if (!NT_SUCCESS(Status)) {
  382. goto InitializeServerError;
  383. }
  384. //
  385. // Initialize the data for the new APIs (user rights)
  386. //
  387. Status = LsapDbInitializeRights();
  388. if (!NT_SUCCESS(Status)) {
  389. goto InitializeServerError;
  390. }
  391. } else if (Pass == 2) {
  392. BOOLEAN ExpectTrue;
  393. OSVERSIONINFOEX OsVersionInfoEx = { 0 };
  394. //
  395. // Perform the second stage of database initialization.
  396. // This is the initialization that depends on the product type.
  397. // First, get the product type. Note that the Product Type may
  398. // have already been retrieved from a number of routines that
  399. // may be called during early installation, including
  400. // LsarSetInformationPolicy() and LsarCreateTrustedDomain().
  401. //
  402. ExpectTrue = RtlGetNtProductType(&LsapProductType);
  403. ASSERT( ExpectTrue == TRUE );
  404. //
  405. // find out the product suite mask.
  406. // this is used later to determine if we are running
  407. // on a specific product suite such the small business server
  408. //
  409. OsVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  410. ExpectTrue = (BOOLEAN) GetVersionEx((OSVERSIONINFO*) &OsVersionInfoEx);
  411. ASSERT( ExpectTrue == TRUE );
  412. LsapProductSuiteMask = OsVersionInfoEx.wSuiteMask;
  413. //
  414. // If necessary, install the rest of our database.
  415. //
  416. if (LsapDatabaseSetupPerformed == TRUE) {
  417. Status = LsapDbInstallLsaDatabase(2);
  418. if (!NT_SUCCESS(Status)) {
  419. goto InitializeServerError;
  420. }
  421. }
  422. //
  423. // If this is a Win Nt product, set the SAM Accounts Domain
  424. // Name equal to the Computer Name, which may have been changed
  425. // since the last boot.
  426. //
  427. //
  428. // If this is setup, do nothing, since we've set it elsewhere..
  429. // If this is safe mode mode, don't set it either
  430. //
  431. if ( !LsaISetupWasRun() ) {
  432. if ( ((LsapProductType == NtProductWinNt) ||
  433. (LsapProductType == NtProductServer)) &&
  434. !LsaISafeMode() ) {
  435. Status = LsarQueryInformationPolicy(
  436. LsapPolicyHandle,
  437. PolicyAccountDomainInformation,
  438. (PLSAPR_POLICY_INFORMATION *) &PolicyAccountDomainInfo
  439. );
  440. if (!NT_SUCCESS(Status)) {
  441. goto InitializeServerError;
  442. }
  443. Length = (ULONG) 0;
  444. ComputerName.Buffer = UNICODE_NULL;
  445. FreeComputerName = FALSE;
  446. BooleanStatus = GetComputerNameW(
  447. (LPWSTR) ComputerName.Buffer,
  448. (LPDWORD) &Length
  449. );
  450. WinStatus = GetLastError();
  451. if (WinStatus != ERROR_BUFFER_OVERFLOW) {
  452. KdPrint(("LsapDbInitializeServer: Failed to get Computer Name Length\n"
  453. "Using default MACHINENAME instead\n"));
  454. RtlInitUnicodeString( &ComputerName, LSAP_DB_DEFAULT_COMPUTER_NAME );
  455. Length = (ULONG) ComputerName.Length;
  456. } else if (Length <= 1) {
  457. KdPrint(("LsapDbInitializeServer: Null Computer Name\n"
  458. "Using default MACHINENAME instead\n"));
  459. RtlInitUnicodeString( &ComputerName, LSAP_DB_DEFAULT_COMPUTER_NAME );
  460. Length = (ULONG) ComputerName.Length;
  461. } else {
  462. ComputerName.Length = (USHORT) ((Length - 1) * sizeof (WCHAR));
  463. ComputerName.MaximumLength = (USHORT) (Length * sizeof(WCHAR));
  464. ComputerName.Buffer = MIDL_user_allocate( ComputerName.MaximumLength );
  465. if ( ComputerName.Buffer == NULL ) {
  466. Status = STATUS_INSUFFICIENT_RESOURCES;
  467. goto InitializeServerError;
  468. }
  469. FreeComputerName = TRUE;
  470. }
  471. if (!GetComputerNameW(
  472. (LPWSTR) ComputerName.Buffer,
  473. (LPDWORD) &Length
  474. )) {
  475. KdPrint(("LsapDbInitializeServer: Failed to get Computer Name\n"
  476. "Using default MACHINENAME instead\n"));
  477. RtlInitUnicodeString( &ComputerName, LSAP_DB_DEFAULT_COMPUTER_NAME );
  478. }
  479. PolicyAccountDomainInfo->DomainName = *((PLSAPR_UNICODE_STRING) &ComputerName);
  480. Status = LsarSetInformationPolicy(
  481. LsapPolicyHandle,
  482. PolicyAccountDomainInformation,
  483. (PLSAPR_POLICY_INFORMATION) PolicyAccountDomainInfo
  484. );
  485. if ( FreeComputerName ) {
  486. MIDL_user_free( ComputerName.Buffer );
  487. }
  488. if (!NT_SUCCESS(Status)) {
  489. goto InitializeServerError;
  490. }
  491. }
  492. Status = RpcMgmtEnableIdleCleanup();
  493. if ( !NT_SUCCESS( Status )) {
  494. goto InitializeServerError;
  495. }
  496. } else {
  497. Status = LsapSetupInitialize();
  498. if (!NT_SUCCESS(Status)) {
  499. goto InitializeServerError;
  500. }
  501. }
  502. // Perform initialization for Lookup Sids and Names, including
  503. // initialization of the Trusted Domain List.
  504. //
  505. Status = LsapDbLookupInitialize();
  506. if (!NT_SUCCESS(Status)) {
  507. goto InitializeServerError;
  508. }
  509. //
  510. // Load the object caches. Any that fail to load have caching
  511. // permanently turned off.
  512. //
  513. IgnoreStatus = LsapDbBuildObjectCaches();
  514. //
  515. // Find out if this machine is a DC in a root domain
  516. //
  517. Status = LsapDbQueryInformationPolicy(
  518. LsapPolicyHandle,
  519. PolicyDnsDomainInformation,
  520. ( PLSAPR_POLICY_INFORMATION * )&PolicyDnsDomainInfo
  521. );
  522. if ( !NT_SUCCESS( Status )) {
  523. goto InitializeServerError;
  524. }
  525. if ( DnsNameCompareEqual == DnsNameCompareEx_W(
  526. PolicyDnsDomainInfo->DnsDomainName.Buffer,
  527. PolicyDnsDomainInfo->DnsForestName.Buffer,
  528. 0 )) {
  529. DcInRootDomain = TRUE;
  530. } else {
  531. DcInRootDomain = FALSE;
  532. }
  533. LsaIFree_LSAPR_POLICY_INFORMATION(
  534. PolicyDnsDomainInformation,
  535. ( PLSAPR_POLICY_INFORMATION )PolicyDnsDomainInfo
  536. );
  537. //
  538. // Mark the Server as being completely initialized.
  539. //
  540. LsapDbState.DbServerInitialized = TRUE;
  541. LsapDbEnableReplicatorNotification();
  542. }
  543. InitializeServerFinish:
  544. return(Status);
  545. InitializeServerError:
  546. goto InitializeServerFinish;
  547. }
  548. NTSTATUS
  549. LsapDbUpgradeRevision(
  550. IN BOOLEAN SyskeyUpgrade,
  551. IN BOOLEAN GenerateNewSyskey
  552. )
  553. /*++
  554. Routine Description:
  555. This function brings the LSA policy database up to date if necessary.
  556. Arguments:
  557. SyskeyUpgrade -- This paramter is set to true when this function is called a second
  558. time around when upgrading NT4 or Win2K B3 machines from LsaIHealthCheck
  559. GenerateNewSyskey -- This parameter is set to true when this function is called a second
  560. time around when upgrading NT4 or Win2k B3 machines from LsaIHealthCheck
  561. and the system is not already syskey'd
  562. Return Value:
  563. NTSTATUS - Standard Nt Result Code
  564. All Result Codes are generated by called routines.
  565. --*/
  566. {
  567. NTSTATUS Status;
  568. ULONG Revision = LSAP_DB_REVISION_1_0, RevisionLength = sizeof( ULONG );
  569. LSAP_DB_ATTRIBUTE Attributes[20];
  570. PLSAP_DB_ATTRIBUTE NextAttribute;
  571. ULONG AttributeCount = 0;
  572. BOOLEAN PolRevisionWritten = FALSE;
  573. NextAttribute = Attributes;
  574. //
  575. // Read the Revision Info from the PolRevision attribute
  576. // of the Policy object in the LSA Database.
  577. //
  578. Status = LsapDbReadAttributeObject(
  579. LsapDbHandle,
  580. &LsapDbNames[PolRevision],
  581. (PVOID) &Revision,
  582. &RevisionLength
  583. );
  584. if ( !NT_SUCCESS(Status) ) {
  585. Revision = LSAP_DB_REVISION_1_0;
  586. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  587. //
  588. // attribute doesn't exist.
  589. // This means the database is an NT1.0 format.
  590. // Upgrade it to the current revision.
  591. //
  592. Status = STATUS_SUCCESS;
  593. }
  594. }
  595. //
  596. // Revison 1_1 created the ModifiedIdAtLastPromotion attribute on the policy object.
  597. // This attribute is no longer used for anything so don't create it.
  598. //
  599. //
  600. // Revision 1_2 corresponded to an encryption of secrets that shipped with NT4 that was
  601. // incompatible with NT5. Therefore skip this revision level. The incompatible encryption
  602. // of secrets would be handled by revision number update
  603. //
  604. //
  605. // Update the security descriptor to revision 1.3
  606. //
  607. if ( NT_SUCCESS( Status ) && (Revision < LSAP_DB_REVISION_1_3) ) {
  608. Status = LsapUpdateDatabaseProtection( LSAP_DB_REVISION_1_3 );
  609. if ( NT_SUCCESS( Status ) ) {
  610. Revision = LSAP_DB_REVISION_1_3;
  611. if ( !PolRevisionWritten ) {
  612. LsapDbInitializeAttribute(
  613. NextAttribute,
  614. &LsapDbNames[PolRevision],
  615. &Revision,
  616. sizeof (ULONG),
  617. FALSE
  618. );
  619. NextAttribute++;
  620. AttributeCount++;
  621. PolRevisionWritten = TRUE;
  622. ASSERT( AttributeCount < ( sizeof( Attributes ) / sizeof( LSAP_DB_ATTRIBUTE ) ) );
  623. }
  624. } else {
  625. Status = STATUS_SUCCESS;
  626. }
  627. }
  628. if ( NT_SUCCESS( Status ) && (Revision < LSAP_DB_REVISION_1_5) && (SyskeyUpgrade)) {
  629. BOOLEAN IsUpgrade = FALSE;
  630. PVOID Syskey = NULL;
  631. ULONG SyskeyLength = 0;
  632. LSAP_DB_ENCRYPTION_KEY NewEncryptionKey;
  633. //
  634. // NT4 SP4 shipped with an encryption of secret's that is incompatible with
  635. // NT5 if the syskey'd setting was turned on.
  636. // Therefore we walk over all secrets and patch them back. It is not necessary
  637. // that we have all the key's setup at this point. The way this works is we attempt,
  638. // to patch back all the secrets, and if we did not have the right key to decrypt them
  639. // we will error out. In Syskey'd machines , SAM will have the right key and will call back
  640. // into LSA when it has obtained the key. During SAM's callback this routine will be executed
  641. // again and we will call upgrade all secrets.
  642. //
  643. // This upgrade involves a secret upgrade only. We simply have to read them and
  644. // write them back out and everything will be kosher...
  645. // Note if the secret upgrade fails for any reason, we will not update the database revision.
  646. //
  647. //
  648. // First obtain the syskey from the SAM hive. Admittedly and ahsamedly this does read the SAM
  649. // hive directly
  650. //
  651. //
  652. // If we are a syskey'd machine the syskey should have been passed to us by now.
  653. //
  654. ASSERT((NULL!=LsapDbSysKey) || (GenerateNewSyskey));
  655. //
  656. // Initialize the key for secret encryption
  657. //
  658. Status = LsapDbGenerateNewKey(
  659. &NewEncryptionKey
  660. );
  661. if (NT_SUCCESS(Status))
  662. {
  663. if (GenerateNewSyskey)
  664. {
  665. ULONG SyskeyLength = sizeof(SyskeyBuffer);
  666. // Boot option is WxStored.
  667. NewEncryptionKey.BootType = WxStored;
  668. //
  669. // A new syskey is being generated
  670. //
  671. Status = LsapDbSetupInitialSyskey(
  672. &SyskeyLength,
  673. &LsapDbSysKey
  674. );
  675. }
  676. else
  677. {
  678. //
  679. // Since we are upgrading from a syskey'd machine, get the boot option from SAM
  680. // SAM is initialized enough at this point as it makes the callout to LSA supplying it with
  681. // the syskey. It is O.K to pass in a value of 0, because then the default account domain
  682. // is used.
  683. //
  684. Status = SamIGetBootKeyInformation(
  685. (SAMPR_HANDLE) 0,
  686. (SAMPR_BOOT_TYPE*)&NewEncryptionKey.BootType
  687. );
  688. }
  689. }
  690. if (NT_SUCCESS(Status))
  691. {
  692. //
  693. // Setup the secret cipher key
  694. // Ordinarily, the key used for reading equals the key used for writing
  695. //
  696. LsapDbInitializeSecretCipherKeyRead( &NewEncryptionKey );
  697. LsapDbInitializeSecretCipherKeyWrite( &NewEncryptionKey );
  698. //
  699. // Encrypt the key with syskey
  700. //
  701. LsapDbEncryptKeyWithSyskey(
  702. &NewEncryptionKey,
  703. LsapDbSysKey,
  704. LSAP_SYSKEY_SIZE
  705. );
  706. LsapDbInitializeAttribute(
  707. NextAttribute,
  708. &LsapDbNames[PolSecretEncryptionKey],
  709. &NewEncryptionKey,
  710. sizeof (NewEncryptionKey),
  711. FALSE
  712. );
  713. NextAttribute++;
  714. AttributeCount++;
  715. }
  716. //
  717. // The secret upgrade is executed only during GUI setup upgrade of a workstation, or a DC being upgraded
  718. // from NT4. In all other cases we simply patch the revision number up to the correct value.
  719. //
  720. if ((NT_SUCCESS(Status)) && ( (SamIIsDownlevelDcUpgrade()) ||
  721. ((LsapProductType != NtProductLanManNt) && (SamIIsSetupInProgress(&IsUpgrade)) && (IsUpgrade))))
  722. {
  723. //
  724. // Ignore the return code below, we still want to move the revision
  725. // level to 1.5, and this code will not be retried anyways
  726. //
  727. LsapDbUpgradeSecretForKeyChange();
  728. }
  729. if ( NT_SUCCESS( Status ) ) {
  730. Revision = LSAP_DB_REVISION_1_5;
  731. if ( !PolRevisionWritten ) {
  732. LsapDbInitializeAttribute(
  733. NextAttribute,
  734. &LsapDbNames[PolRevision],
  735. &Revision,
  736. sizeof (ULONG),
  737. FALSE
  738. );
  739. NextAttribute++;
  740. AttributeCount++;
  741. PolRevisionWritten = TRUE;
  742. //
  743. // Revision is now 1.5
  744. //
  745. ASSERT( AttributeCount < ( sizeof( Attributes ) / sizeof( LSAP_DB_ATTRIBUTE ) ) );
  746. }
  747. }
  748. }
  749. //
  750. // Only upgrade past revision 1.5 if we've upgraded to revison 1.5.
  751. //
  752. // We don't upgrade to revision 1.5 in the mainline LSA initialization code.
  753. // Rather, we upgrade to revision 1.5 in a callback from SAM. If then we moved on
  754. // to revisions greater than 1.5 during LSA initialization, we'd never have a chance to
  755. // do the revision 1.5 upgrade code.
  756. //
  757. if ( Revision >= LSAP_DB_REVISION_1_5 ) {
  758. //
  759. // Update the security descriptor to revision 1.6
  760. //
  761. if ( NT_SUCCESS( Status ) && (Revision < LSAP_DB_REVISION_1_6) ) {
  762. Status = LsapUpdateDatabaseProtection( LSAP_DB_REVISION_1_6 );
  763. if ( NT_SUCCESS( Status ) ) {
  764. Revision = LSAP_DB_REVISION_1_6;
  765. if ( !PolRevisionWritten ) {
  766. LsapDbInitializeAttribute(
  767. NextAttribute,
  768. &LsapDbNames[PolRevision],
  769. &Revision,
  770. sizeof (ULONG),
  771. FALSE
  772. );
  773. NextAttribute++;
  774. AttributeCount++;
  775. PolRevisionWritten = TRUE;
  776. //
  777. // Revision is now 1.6
  778. //
  779. ASSERT( AttributeCount < ( sizeof( Attributes ) / sizeof( LSAP_DB_ATTRIBUTE ) ) );
  780. }
  781. } else {
  782. Status = STATUS_SUCCESS;
  783. }
  784. }
  785. //
  786. // Update the security descriptor to revision 1.7
  787. //
  788. if ( NT_SUCCESS( Status ) && (Revision < LSAP_DB_REVISION_1_7) ) {
  789. Status = LsapUpdateDatabaseProtection( LSAP_DB_REVISION_1_7 );
  790. if ( NT_SUCCESS( Status ) ) {
  791. Revision = LSAP_DB_REVISION_1_7;
  792. if ( !PolRevisionWritten ) {
  793. LsapDbInitializeAttribute(
  794. NextAttribute,
  795. &LsapDbNames[PolRevision],
  796. &Revision,
  797. sizeof (ULONG),
  798. FALSE
  799. );
  800. NextAttribute++;
  801. AttributeCount++;
  802. PolRevisionWritten = TRUE;
  803. //
  804. // Revision is now 1.7
  805. //
  806. ASSERT( AttributeCount < ( sizeof( Attributes ) / sizeof( LSAP_DB_ATTRIBUTE ) ) );
  807. }
  808. } else {
  809. Status = STATUS_SUCCESS;
  810. }
  811. }
  812. //
  813. // In the future, revision updates can be made
  814. // by adding "if" blocks similar to the one above.
  815. //
  816. // Remember, however, that the attributes are pointing
  817. // to values in local variables. Any local variable
  818. // value changed before the attribute is written out
  819. // will cause that attribute value to be changed.
  820. //
  821. //
  822. }
  823. //
  824. // Now write out all attributes that have been added (if any)
  825. //
  826. if (AttributeCount > 0) {
  827. Status = LsapDbReferenceObject(
  828. LsapDbHandle,
  829. 0,
  830. PolicyObject,
  831. PolicyObject,
  832. LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION
  833. );
  834. if (NT_SUCCESS(Status)) {
  835. ASSERT( AttributeCount < ( sizeof( Attributes ) / sizeof( LSAP_DB_ATTRIBUTE ) ) );
  836. Status = LsapDbWriteAttributesObject(
  837. LsapDbHandle,
  838. Attributes,
  839. AttributeCount
  840. );
  841. //
  842. // No attributes are replicatable.
  843. // (That's good, too, since SAM hasn't told Netlogon our role yet.)
  844. Status = LsapDbDereferenceObject(
  845. &LsapDbHandle,
  846. PolicyObject,
  847. PolicyObject,
  848. (LSAP_DB_LOCK |
  849. LSAP_DB_FINISH_TRANSACTION |
  850. LSAP_DB_OMIT_REPLICATOR_NOTIFICATION ),
  851. SecurityDbChange,
  852. Status
  853. );
  854. }
  855. }
  856. return( Status );
  857. }
  858. NTSTATUS
  859. LsapDbBuildObjectCaches(
  860. )
  861. /*++
  862. Routine Description:
  863. This function builds caches for Lsa objects. These caches contain a
  864. subset of the information for some object types.
  865. Arguments:
  866. None
  867. Return Values:
  868. NTSTATUS - Standard Nt Result Code.
  869. --*/
  870. {
  871. NTSTATUS IgnoreStatus;
  872. LSAP_DB_OBJECT_TYPE_ID ObjectTypeId;
  873. //
  874. // Initialize all the caches.
  875. //
  876. for (ObjectTypeId = PolicyObject;
  877. ObjectTypeId <= SecretObject;
  878. ObjectTypeId++) {
  879. IgnoreStatus = LsapDbRebuildCache( ObjectTypeId );
  880. }
  881. return(STATUS_SUCCESS);
  882. }
  883. NTSTATUS
  884. LsapDbInitializeObjectTypes(
  885. )
  886. /*++
  887. Routine Description:
  888. This function initializes the information pertinent to each object
  889. type in the LSA Database. This information includes the following:
  890. o Generic Mapping Arrays
  891. The Generic Mapping array for each object defines the list of
  892. object-type-specific access types that correspond to the generic
  893. access types GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE and
  894. GENERIC_ALL for the object type.
  895. o Object Count Information
  896. The Object Count Information includes a count of the number of objects
  897. that exist for each type, the upper limit on this number (if any) for
  898. each object type, and the error code to return when that limit is
  899. reached.
  900. o Write Operation Masks
  901. These specify which access types are update operations
  902. o Default accesses granted to World and Admin aliases
  903. o Invalid access masks for each object type
  904. These masks specify the bits in an access mask that are invalid for
  905. a given object type.
  906. o Initial owners of each object type
  907. o Object caching supported for each object type.
  908. Arguments:
  909. None. The Generic Mapping arrays are held the LsapDbState structure.
  910. Return Value:
  911. NTSTATUS - Standard Nt Result Code. Currently, there are no error
  912. situations in this code, so STATUS_SUCCESS is always returned.
  913. --*/
  914. {
  915. NTSTATUS Status = STATUS_SUCCESS;
  916. PGENERIC_MAPPING GenericMapping;
  917. PLSAP_DB_OBJECT_TYPE ObjectType;
  918. LSAP_DB_OBJECT_TYPE_ID ObjectTypeId;
  919. //
  920. // Initialize the Generic Mapping Array for the PolicyObject Object Type
  921. // Note that there is only one object of this type and objects of this
  922. // type can neither be created nor destroyed.
  923. //
  924. GenericMapping =
  925. &LsapDbState.DbObjectTypes[PolicyObject].GenericMapping;
  926. GenericMapping->GenericRead =
  927. STANDARD_RIGHTS_READ |
  928. POLICY_VIEW_AUDIT_INFORMATION |
  929. POLICY_GET_PRIVATE_INFORMATION;
  930. GenericMapping->GenericWrite =
  931. STANDARD_RIGHTS_WRITE |
  932. POLICY_TRUST_ADMIN |
  933. POLICY_CREATE_ACCOUNT |
  934. POLICY_CREATE_SECRET |
  935. POLICY_CREATE_PRIVILEGE |
  936. POLICY_SET_DEFAULT_QUOTA_LIMITS |
  937. POLICY_SET_AUDIT_REQUIREMENTS |
  938. POLICY_AUDIT_LOG_ADMIN |
  939. POLICY_SERVER_ADMIN;
  940. GenericMapping->GenericExecute =
  941. STANDARD_RIGHTS_EXECUTE |
  942. POLICY_VIEW_LOCAL_INFORMATION |
  943. POLICY_LOOKUP_NAMES;
  944. GenericMapping->GenericAll = POLICY_ALL_ACCESS | POLICY_NOTIFICATION;
  945. //
  946. // Initialize the Generic Mapping Array for the Account Object Type
  947. // Note that Account Objects can be created and destroyed.
  948. //
  949. GenericMapping =
  950. &LsapDbState.DbObjectTypes[AccountObject].GenericMapping;
  951. GenericMapping->GenericRead =
  952. STANDARD_RIGHTS_READ |
  953. ACCOUNT_VIEW;
  954. GenericMapping->GenericWrite =
  955. STANDARD_RIGHTS_WRITE |
  956. ACCOUNT_ADJUST_PRIVILEGES |
  957. ACCOUNT_ADJUST_QUOTAS |
  958. ACCOUNT_ADJUST_SYSTEM_ACCESS;
  959. GenericMapping->GenericExecute =
  960. STANDARD_RIGHTS_EXECUTE;
  961. GenericMapping->GenericAll = ACCOUNT_ALL_ACCESS;
  962. //
  963. // Initialize the Generic Mapping Array for the TrustedDomain Object
  964. // Type.
  965. //
  966. GenericMapping =
  967. &LsapDbState.DbObjectTypes[TrustedDomainObject].GenericMapping;
  968. GenericMapping->GenericRead =
  969. STANDARD_RIGHTS_READ |
  970. TRUSTED_QUERY_DOMAIN_NAME;
  971. GenericMapping->GenericWrite =
  972. STANDARD_RIGHTS_WRITE |
  973. TRUSTED_SET_CONTROLLERS |
  974. TRUSTED_SET_POSIX;
  975. GenericMapping->GenericExecute =
  976. STANDARD_RIGHTS_EXECUTE |
  977. TRUSTED_QUERY_CONTROLLERS |
  978. TRUSTED_QUERY_POSIX;
  979. GenericMapping->GenericAll = TRUSTED_ALL_ACCESS;
  980. //
  981. // Initialize the Generic Mapping Array for the Secret Object
  982. // Type.
  983. //
  984. GenericMapping =
  985. &LsapDbState.DbObjectTypes[SecretObject].GenericMapping;
  986. GenericMapping->GenericRead =
  987. STANDARD_RIGHTS_READ |
  988. SECRET_QUERY_VALUE;
  989. GenericMapping->GenericWrite =
  990. STANDARD_RIGHTS_WRITE |
  991. SECRET_SET_VALUE;
  992. GenericMapping->GenericExecute =
  993. STANDARD_RIGHTS_EXECUTE;
  994. GenericMapping->GenericAll = SECRET_ALL_ACCESS;
  995. //
  996. // Initialize the Object Count Information to defaults
  997. //
  998. ObjectType = &(LsapDbState.DbObjectTypes[PolicyObject]);
  999. for (ObjectTypeId = PolicyObject;
  1000. ObjectTypeId < DummyLastObject;
  1001. ObjectTypeId++) {
  1002. ObjectType->ObjectCount = 0;
  1003. ObjectType->ObjectCountLimited = FALSE;
  1004. ObjectType->ObjectCountError = STATUS_SUCCESS;
  1005. ObjectType->MaximumObjectCount = 0;
  1006. }
  1007. //
  1008. // Set specific limits for Secret Object Type. This is the only
  1009. // object type so far to have limits.
  1010. //
  1011. ObjectType = &(LsapDbState.DbObjectTypes[SecretObject]);
  1012. ObjectType->ObjectCountLimited = TRUE;
  1013. ObjectType->ObjectCountError = STATUS_TOO_MANY_SECRETS;
  1014. ObjectType->MaximumObjectCount = LSA_SECRET_MAXIMUM_COUNT;
  1015. //
  1016. // Initialize the write operations for each object type
  1017. //
  1018. LsapDbState.DbObjectTypes[PolicyObject].WriteOperations = LSAP_POLICY_WRITE_OPS;
  1019. LsapDbState.DbObjectTypes[TrustedDomainObject].WriteOperations = LSAP_TRUSTED_WRITE_OPS;
  1020. LsapDbState.DbObjectTypes[AccountObject].WriteOperations = LSAP_ACCOUNT_WRITE_OPS;
  1021. LsapDbState.DbObjectTypes[SecretObject].WriteOperations = LSAP_SECRET_WRITE_OPS;
  1022. //
  1023. // Initialize the default accesses granted to Domain Admins alias
  1024. //
  1025. LsapDbState.DbObjectTypes[PolicyObject].AliasAdminsAccess = GENERIC_ALL;
  1026. LsapDbState.DbObjectTypes[TrustedDomainObject].AliasAdminsAccess = GENERIC_ALL | DELETE;
  1027. LsapDbState.DbObjectTypes[AccountObject].AliasAdminsAccess = GENERIC_ALL | DELETE;
  1028. LsapDbState.DbObjectTypes[SecretObject].AliasAdminsAccess = GENERIC_ALL | DELETE;
  1029. //
  1030. // Initialize the default accesses granted to World alias
  1031. //
  1032. LsapDbState.DbObjectTypes[PolicyObject].WorldAccess = GENERIC_EXECUTE;
  1033. LsapDbState.DbObjectTypes[TrustedDomainObject].WorldAccess = GENERIC_EXECUTE;
  1034. LsapDbState.DbObjectTypes[AccountObject].WorldAccess = GENERIC_EXECUTE;
  1035. LsapDbState.DbObjectTypes[SecretObject].WorldAccess = GENERIC_EXECUTE;
  1036. //
  1037. // Initialize the default accesses granted to AnonymousLogon alias
  1038. //
  1039. LsapDbState.DbObjectTypes[PolicyObject].AnonymousLogonAccess = POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES;
  1040. LsapDbState.DbObjectTypes[TrustedDomainObject].AnonymousLogonAccess = 0;
  1041. LsapDbState.DbObjectTypes[AccountObject].AnonymousLogonAccess = 0;
  1042. LsapDbState.DbObjectTypes[SecretObject].AnonymousLogonAccess = 0;
  1043. //
  1044. // Initialize the default accesses granted to LocalService and NetworkService
  1045. //
  1046. LsapDbState.DbObjectTypes[PolicyObject].LocalServiceAccess = POLICY_NOTIFICATION;
  1047. LsapDbState.DbObjectTypes[TrustedDomainObject].LocalServiceAccess = 0;
  1048. LsapDbState.DbObjectTypes[AccountObject].LocalServiceAccess = 0;
  1049. LsapDbState.DbObjectTypes[SecretObject].LocalServiceAccess = 0;
  1050. LsapDbState.DbObjectTypes[PolicyObject].NetworkServiceAccess = POLICY_NOTIFICATION;
  1051. LsapDbState.DbObjectTypes[TrustedDomainObject].NetworkServiceAccess = 0;
  1052. LsapDbState.DbObjectTypes[AccountObject].NetworkServiceAccess = 0;
  1053. LsapDbState.DbObjectTypes[SecretObject].NetworkServiceAccess = 0;
  1054. //
  1055. // Initialize the Invalid Access masks for each object type
  1056. //
  1057. LsapDbState.DbObjectTypes[PolicyObject].InvalidMappedAccess =
  1058. ((ACCESS_MASK)(~(POLICY_ALL_ACCESS | POLICY_NOTIFICATION | ACCESS_SYSTEM_SECURITY | MAXIMUM_ALLOWED)));
  1059. LsapDbState.DbObjectTypes[TrustedDomainObject].InvalidMappedAccess =
  1060. ((ACCESS_MASK)(~(TRUSTED_ALL_ACCESS | ACCESS_SYSTEM_SECURITY | MAXIMUM_ALLOWED)));
  1061. LsapDbState.DbObjectTypes[AccountObject].InvalidMappedAccess =
  1062. ((ACCESS_MASK)(~(ACCOUNT_ALL_ACCESS | ACCESS_SYSTEM_SECURITY | MAXIMUM_ALLOWED)));
  1063. LsapDbState.DbObjectTypes[SecretObject].InvalidMappedAccess =
  1064. ((ACCESS_MASK)(~(SECRET_ALL_ACCESS | ACCESS_SYSTEM_SECURITY | MAXIMUM_ALLOWED)));
  1065. //
  1066. // Initialize the Initial Owners for new objects of each type
  1067. //
  1068. LsapDbState.DbObjectTypes[PolicyObject].InitialOwnerSid = LsapAliasAdminsSid;
  1069. LsapDbState.DbObjectTypes[TrustedDomainObject].InitialOwnerSid = LsapAliasAdminsSid;
  1070. LsapDbState.DbObjectTypes[AccountObject].InitialOwnerSid = LsapAliasAdminsSid;
  1071. LsapDbState.DbObjectTypes[SecretObject].InitialOwnerSid = LsapAliasAdminsSid;
  1072. //
  1073. // Specify method of access to objects of the type. Currently, all objects
  1074. // of a given type are accessed in the same way, either by Sid or by Name
  1075. // but not both.
  1076. //
  1077. LsapDbState.DbObjectTypes[PolicyObject].AccessedByName = TRUE;
  1078. LsapDbState.DbObjectTypes[TrustedDomainObject].AccessedByName = FALSE;
  1079. LsapDbState.DbObjectTypes[AccountObject].AccessedByName = FALSE;
  1080. LsapDbState.DbObjectTypes[SecretObject].AccessedByName = TRUE;
  1081. LsapDbState.DbObjectTypes[PolicyObject].AccessedBySid = FALSE;
  1082. LsapDbState.DbObjectTypes[TrustedDomainObject].AccessedBySid = TRUE;
  1083. LsapDbState.DbObjectTypes[AccountObject].AccessedBySid = TRUE;
  1084. LsapDbState.DbObjectTypes[SecretObject].AccessedBySid = FALSE;
  1085. //
  1086. // Specify the object types for which caching is supported (in full
  1087. // or in part) and turn caching off initially for all object types.
  1088. // Object types for which caching is supported have ther caches set
  1089. // to the "Invalid" state. Automatic restore is allowed for caches
  1090. // in this state. Object types for which caching is not supported
  1091. // are set to the "Not supported" state. Note that a cache is
  1092. // also placed in the "not supported" state if an attempt to restore
  1093. // it fails.
  1094. //
  1095. LsapDbMakeCacheInvalid( PolicyObject );
  1096. LsapDbMakeCacheInvalid( TrustedDomainObject );
  1097. LsapDbMakeCacheInvalid( AccountObject );
  1098. LsapDbMakeCacheUnsupported( SecretObject );
  1099. return(Status);
  1100. }
  1101. NTSTATUS
  1102. LsapDbInitializeUnicodeNames()
  1103. /*++
  1104. Routine Description:
  1105. This function initializes two arrays of Unicode Strings. The
  1106. LsapDbNames array contains Unicode Strings for all of the constant
  1107. names in the Lsa Database. The LsapDbObjectTypeNames is indexed
  1108. by Object Type Id and contains the Unicode Strings for all of the
  1109. LSA Database object types.
  1110. Arguments:
  1111. None.
  1112. Return Value:
  1113. NTSTATUS - Standard Nt Result Code
  1114. All Result Codes are generated by called routines.
  1115. --*/
  1116. {
  1117. NTSTATUS Status = STATUS_SUCCESS;
  1118. LSAP_DB_NAMES Index;
  1119. LSAP_DB_OBJECT_TYPE_ID ObjectTypeId;
  1120. PCWSTR UnicodeNames[DummyLastName + 1] = {
  1121. L"SecDesc",
  1122. L"Privilgs",
  1123. L"Sid",
  1124. L"Name",
  1125. L"AdminMod",
  1126. L"OperMode",
  1127. L"QuotaLim",
  1128. L"DefQuota",
  1129. L"PrDomain",
  1130. L"Policy",
  1131. L"Accounts",
  1132. L"Domains",
  1133. L"Secrets",
  1134. L"CurrVal",
  1135. L"OldVal",
  1136. L"CupdTime",
  1137. L"OupdTime",
  1138. L"PolAdtLg",
  1139. L"PolAdtEv",
  1140. L"PolAcDmN",
  1141. L"PolAcDmS",
  1142. L"PolDnDDN",
  1143. L"PolDnTrN",
  1144. L"PolDnDmG",
  1145. L"PolEfDat",
  1146. L"PolPrDmN",
  1147. L"PolPrDmS",
  1148. L"PolPdAcN",
  1149. L"PolRepSc",
  1150. L"PolRepAc",
  1151. L"PolRevision",
  1152. L"PolMod",
  1153. L"PolState",
  1154. L"ActSysAc",
  1155. L"TrDmName",
  1156. L"TrDmTrPN", // Netbios name of trust partner
  1157. L"TrDmSid",
  1158. L"TrDmAcN",
  1159. L"TrDmCtN",
  1160. L"TrDmPxOf",
  1161. L"TrDmCtEn",
  1162. NULL, // TrDmTrTy
  1163. NULL, // TrDmTrDi
  1164. L"TrDmTrLA", // TrDmTrLA
  1165. L"TrDmTrPr", // Trust partner
  1166. L"TrDmTrRt", // Root partner
  1167. L"TrDmSAI", // Incoming auth. info
  1168. L"TrDmSAO", // Outgoing auth. info
  1169. L"TrDmForT", // Forest trust info
  1170. L"TrDmCrSid", // Creator Sid
  1171. L"KerOpts", // Kerberos authentication options
  1172. L"KerMinT", // Kerberos Minimum ticket age
  1173. L"KerMaxT", // Kerberos maximum ticket age
  1174. L"KerMaxR", // Kerberos maximum renewal age
  1175. L"KerProxy", // Kerberos proxy lifetime
  1176. L"KerLogoff", // Kerberos force logoff duration
  1177. L"BhvrVers", // Behavior-Version
  1178. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Eventlog\\Security",
  1179. L"MaxSize",
  1180. L"Retention",
  1181. L"PseudoSystemCritical",
  1182. L"PolSecretEncryptionKey",
  1183. L"XRefDnsRoot",
  1184. L"XRefNetbiosName",
  1185. L"DummyLastName"
  1186. };
  1187. PCWSTR UnicodeObjectTypeNames[DummyLastObject] = {
  1188. L"NullObject",
  1189. L"PolicyObject",
  1190. L"TrustedDomainObject",
  1191. L"UserAccountObject",
  1192. L"SecretObject",
  1193. L"AllObject",
  1194. L"NewTrustedDomainObject"
  1195. };
  1196. //
  1197. // Referenced by LsapDbDsAttInfo
  1198. //
  1199. static LSAP_DB_DS_INFO StaticLsapDbDsAttInfo[DummyLastName + 1] = {
  1200. {ATT_NT_SECURITY_DESCRIPTOR, LsapDbAttribSecDesc, LsapDsLocDs}, // Security Descriptor
  1201. {0, LsapDbAttribUnknown, LsapDsLocUnknown }, // Privileges
  1202. {ATT_SECURITY_IDENTIFIER, LsapDbAttribSid, LsapDsLocDs}, // Sid
  1203. {0, LsapDbAttribUnknown, LsapDsLocDs}, // Name
  1204. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // AdminMod
  1205. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // OperMode
  1206. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // QuotaLim
  1207. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // DefQuota
  1208. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // PrDomain
  1209. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Policy
  1210. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Accounts
  1211. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Domains
  1212. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Secrets
  1213. {ATT_CURRENT_VALUE, LsapDbAttribPByte, LsapDsLocDs}, // CurrVal
  1214. {ATT_PRIOR_VALUE, LsapDbAttribPByte, LsapDsLocDs}, // OldVal
  1215. {ATT_LAST_SET_TIME, LsapDbAttribPByte, LsapDsLocDs}, // CupdTime
  1216. {ATT_PRIOR_SET_TIME, LsapDbAttribPByte, LsapDsLocDs}, // OupdTime
  1217. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // PolAdtLg
  1218. {ATT_AUDITING_POLICY, LsapDbAttribPByte, LsapDsLocRegistry}, // PolAdtEv
  1219. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolAcDmN
  1220. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolAcDmS
  1221. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolDnDDN
  1222. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolDnTrN
  1223. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolDnDmG
  1224. {ATT_EFSPOLICY, LsapDbAttribPByte, LsapDsLocRegistry}, // PolEfDat
  1225. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolPrDmN
  1226. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolPrDmS
  1227. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolPdAcN
  1228. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolRepSc
  1229. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolRepAc
  1230. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // PolRevision
  1231. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolMod
  1232. {0, LsapDbAttribUnknown, LsapDsLocRegistry}, // PolState
  1233. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // ActSysAc
  1234. {ATT_TRUST_PARTNER, LsapDbAttribUnicode, LsapDsLocDs}, // TrDmName
  1235. {ATT_FLAT_NAME, LsapDbAttribUnicode, LsapDsLocDs}, // TrDmTrPN
  1236. {ATT_SECURITY_IDENTIFIER, LsapDbAttribSid, LsapDsLocDs}, // TrDmSid
  1237. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // TrDmAcN
  1238. {0, LsapDbAttribUnicode, LsapDsLocRegistry}, // TrDmCtN
  1239. {ATT_TRUST_POSIX_OFFSET, LsapDbAttribULong, LsapDsLocDs}, // TrDmPxOf
  1240. {0, LsapDbAttribUnicode, LsapDsLocRegistry}, // TrDmCtEn
  1241. {ATT_TRUST_TYPE, LsapDbAttribULong, LsapDsLocDs}, // TrDmTrTy
  1242. {ATT_TRUST_DIRECTION, LsapDbAttribULong, LsapDsLocDs}, // TrDmTrDi
  1243. {ATT_TRUST_ATTRIBUTES, LsapDbAttribULong, LsapDsLocDs}, // TrDmTrLA
  1244. {ATT_DOMAIN_CROSS_REF, LsapDbAttribDsName, LsapDsLocDs}, // TrDmTrPr
  1245. {ATT_ROOT_TRUST, LsapDbAttribDsName, LsapDsLocDs}, // TrDmTrRt
  1246. {ATT_TRUST_AUTH_INCOMING, LsapDbAttribPByte, LsapDsLocDs}, // TrDmSAI
  1247. {ATT_TRUST_AUTH_OUTGOING, LsapDbAttribPByte, LsapDsLocDs}, // TrDmSAO
  1248. {ATT_MS_DS_TRUST_FOREST_TRUST_INFO, LsapDbAttribPByte, LsapDsLocDs}, // TrDmForT
  1249. {ATT_MS_DS_CREATOR_SID, LsapDbAttribSid, LsapDsLocDs}, // TrDmCrSid
  1250. {ATT_AUTHENTICATION_OPTIONS, LsapDbAttribULong, LsapDsLocRegistry}, // KerOpts,
  1251. {ATT_MIN_TICKET_AGE, LsapDbAttribPByte, LsapDsLocRegistry}, // KerMinT,
  1252. {ATT_MAX_TICKET_AGE, LsapDbAttribPByte, LsapDsLocRegistry}, // KerMaxT,
  1253. {ATT_MAX_RENEW_AGE, LsapDbAttribPByte, LsapDsLocRegistry}, // KerMaxR,
  1254. {ATT_PROXY_LIFETIME, LsapDbAttribPByte, LsapDsLocRegistry}, // KerProxy,
  1255. {ATT_FORCE_LOGOFF, LsapDbAttribPByte, LsapDsLocRegistry}, // KerLogoff
  1256. {ATT_MS_DS_BEHAVIOR_VERSION, LsapDbAttribULong, LsapDsLocDs}, // BhvrVers
  1257. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Audit log
  1258. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Audit log size
  1259. {0, LsapDbAttribUnknown, LsapDsLocUnknown}, // Audit Recored Retention Period
  1260. {ATT_IS_CRITICAL_SYSTEM_OBJECT, LsapDbAttribULong, LsapDsLocDs}, // system critical component.
  1261. {0, LsapDbAttribPByte, LsapDsLocRegistry},//PolSecretEncryptionKey
  1262. {ATT_DNS_ROOT, LsapDbAttribUnicode, LsapDsLocDs}, // DNS name of cross-ref
  1263. {ATT_NETBIOS_NAME, LsapDbAttribUnicode, LsapDsLocDs}, // Netbios domain of cross-ref
  1264. {0, LsapDbAttribUnknown, LsapDsLocUnknown} // Dummy Last Name
  1265. };
  1266. //
  1267. // Initialize general array of Unicode Names
  1268. //
  1269. for (Index = SecDesc; Index < DummyLastName; Index++) {
  1270. RtlInitUnicodeString( &LsapDbNames[Index], UnicodeNames[Index] );
  1271. }
  1272. //
  1273. // Initialize array of Unicode Names for Lsa Database Object Types
  1274. //
  1275. for (ObjectTypeId = NullObject;
  1276. ObjectTypeId < DummyLastObject;
  1277. ObjectTypeId++) {
  1278. RtlInitUnicodeString(
  1279. &LsapDbObjectTypeNames[ObjectTypeId],
  1280. UnicodeObjectTypeNames[ObjectTypeId]
  1281. );
  1282. }
  1283. LsapDbDsAttInfo = StaticLsapDbDsAttInfo;
  1284. return(Status);
  1285. }
  1286. NTSTATUS
  1287. LsapDbInitializeContainingDirs()
  1288. /*++
  1289. Routine Description:
  1290. This function initializes Unicode strings for the names of the Containing
  1291. directories for each object type. The Containing Directory is the
  1292. Registry Key under which all objects of the given type are created and is
  1293. relative to the LSA Database root. Note that objects of a given type all
  1294. exist under a single Registry node, that is, the type of an object
  1295. uniquely determines the name of its containing directory.
  1296. NOTE: Containing Directories are used to produce Physical Object Names
  1297. from Logical Object Names. The Physical Object Name is simply
  1298. the Logical Object Name prepended with the Containing Directory
  1299. Name and a "\".
  1300. Arguments:
  1301. None.
  1302. Return Value:
  1303. NTSTATUS - Standard Nt Result Code
  1304. All Result Codes are generated by called routines.
  1305. --*/
  1306. {
  1307. NTSTATUS Status = STATUS_SUCCESS;
  1308. LSAP_DB_OBJECT_TYPE_ID ObjectTypeId;
  1309. PWSTR ContainingDirectories[DummyLastObject] = {
  1310. L"",
  1311. L"",
  1312. L"Domains",
  1313. L"Accounts",
  1314. L"Secrets"
  1315. };
  1316. //
  1317. // Initialize the array of Unicode Strings indexed by object type setting
  1318. // the Containing Directory name for each object type.
  1319. //
  1320. for (ObjectTypeId = PolicyObject;
  1321. ObjectTypeId < DummyLastObject;
  1322. ObjectTypeId++) {
  1323. RtlInitUnicodeString(
  1324. &LsapDbContDirs[ObjectTypeId],
  1325. ContainingDirectories[ ObjectTypeId ]
  1326. );
  1327. }
  1328. return(Status);
  1329. }
  1330. NTSTATUS
  1331. LsapDbInitializeReplication(
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. This function performes LSA initialization for replication and turns
  1336. on notification of LSA Database updates to the LSA Database Replicator.
  1337. Arguments:
  1338. None.
  1339. Return Value:
  1340. NTSTATUS - Standard Nt Result Code
  1341. All Result Codes are generated by called routines.
  1342. --*/
  1343. {
  1344. NTSTATUS Status;
  1345. ULONG PolicyModificationInfoLength = sizeof (POLICY_MODIFICATION_INFO);
  1346. ULONG PolicyLsaServerRoleInfoLength = sizeof(POLICY_LSA_SERVER_ROLE_INFO);
  1347. ULONG LargeIntegerLength = sizeof( LARGE_INTEGER );
  1348. //
  1349. // Read the Policy Modification Info from the PolMod attribute
  1350. // of the Policy object in the LSA Database.
  1351. //
  1352. Status = LsapDbReadAttributeObject(
  1353. LsapDbHandle,
  1354. &LsapDbNames[PolMod],
  1355. (PVOID) &LsapDbState.PolicyModificationInfo,
  1356. &PolicyModificationInfoLength
  1357. );
  1358. if (!NT_SUCCESS(Status)) {
  1359. goto InitializeReplicationError;
  1360. }
  1361. InitializeReplicationFinish:
  1362. return(Status);
  1363. InitializeReplicationError:
  1364. goto InitializeReplicationFinish;
  1365. }
  1366. NTSTATUS
  1367. LsapDbInitializeCipherKey(
  1368. IN PUNICODE_STRING CipherSeed,
  1369. IN PLSAP_CR_CIPHER_KEY *CipherKey
  1370. )
  1371. /*++
  1372. Routine Description:
  1373. This function initializes the LSA Database Cipher Key.
  1374. Arguments:
  1375. None.
  1376. Return Value:
  1377. NTSTATUS - Standard Nt Result Code
  1378. All Result Codes are generated by called routines.
  1379. --*/
  1380. {
  1381. NTSTATUS Status;
  1382. LSAP_CR_CLEAR_VALUE ClearCipherKey;
  1383. PLSAP_CR_CIPHER_VALUE CipherCipherKey;
  1384. *CipherKey = NULL;
  1385. //
  1386. // Initialize the Cipher key to a hardwired constant
  1387. // encrypted with itself.
  1388. //
  1389. LsapCrUnicodeToClearValue( CipherSeed, &ClearCipherKey);
  1390. Status = LsapCrEncryptValue(
  1391. &ClearCipherKey,
  1392. (PLSAP_CR_CIPHER_KEY) &ClearCipherKey,
  1393. &CipherCipherKey
  1394. );
  1395. if (!NT_SUCCESS(Status)) {
  1396. LsapLogError( "LsapDbInitializeReplication: NtQuerySystemTime returned 0x%lx\n",
  1397. Status );
  1398. } else {
  1399. *CipherKey = ( PLSAP_CR_CIPHER_KEY )CipherCipherKey;
  1400. }
  1401. return(Status);
  1402. }
  1403. NTSTATUS
  1404. LsapDbOpenRootRegistryKey(
  1405. )
  1406. /*++
  1407. Routine Description:
  1408. This function opens the LSA Database Root Registry Key. This has
  1409. the fixed name \Registry\Machine\Security.
  1410. Arguments:
  1411. None.
  1412. Return Value:
  1413. NTSTATUS - Standard Nt Result Code
  1414. All Result Codes are generated by called routines.
  1415. --*/
  1416. {
  1417. NTSTATUS Status;
  1418. UNICODE_STRING DbRootRegKeyNameU;
  1419. OBJECT_ATTRIBUTES DbAttributes;
  1420. RtlInitUnicodeString( &DbRootRegKeyNameU, LSAP_DB_ROOT_REG_KEY_NAME );
  1421. InitializeObjectAttributes(
  1422. &DbAttributes,
  1423. &DbRootRegKeyNameU,
  1424. OBJ_CASE_INSENSITIVE,
  1425. NULL,
  1426. NULL
  1427. );
  1428. Status = RtlpNtOpenKey(
  1429. (PHANDLE) &LsapDbState.DbRootRegKeyHandle,
  1430. (KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | WRITE_DAC),
  1431. &DbAttributes,
  1432. 0
  1433. );
  1434. if (!NT_SUCCESS(Status)) {
  1435. LsapLogError(
  1436. "LsapDbOpenRootRegistryKey: Open Root Key for LSA Policy Database returned 0x%lx\n",
  1437. Status
  1438. );
  1439. goto OpenRootRegistryKeyError;
  1440. }
  1441. //
  1442. // If there are no sub-keys, then we are in system-install.
  1443. // Assign the initial protection of this hive.
  1444. //
  1445. Status = LsapAssignInitialHiveProtection( LsapDbState.DbRootRegKeyHandle );
  1446. if (!NT_SUCCESS(Status)) {
  1447. LsapLogError(
  1448. "LsapDbOpenRootRegistryKey: Couldn't assign initial hive protection 0x%lx\n",
  1449. Status
  1450. );
  1451. goto OpenRootRegistryKeyError;
  1452. }
  1453. OpenRootRegistryKeyFinish:
  1454. return(Status);
  1455. OpenRootRegistryKeyError:
  1456. goto OpenRootRegistryKeyFinish;
  1457. }
  1458. NTSTATUS
  1459. LsapAssignInitialHiveProtection(
  1460. HANDLE HiveRoot
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. This function assigns inheritable protection to the hive root key.
  1465. It will only do this if the hive root has no sub-keys.
  1466. This condition will only exist during system installation.
  1467. WARNING -
  1468. THIS ROUTINE IS TAILORED TO OPERATE ON THE \REGISTRY\SECURITY HIVE.
  1469. As such, it expects the Root key to have exactly one sub-key (a
  1470. link to the SAM hive) if the the database has NOT been initialized.
  1471. Otherwise, it expects the LSA policy database keys to be present.
  1472. Arguments:
  1473. None.
  1474. Return Value:
  1475. STATUS_SUCCESS - Everything went fine. No indication of whether
  1476. protection was necessarily assigned or not.
  1477. All other status values are generated by called routines.
  1478. --*/
  1479. {
  1480. NTSTATUS
  1481. Status;
  1482. KEY_BASIC_INFORMATION
  1483. DummyBuffer;
  1484. ULONG
  1485. IgnoreRequiredLength;
  1486. SECURITY_DESCRIPTOR
  1487. Sd;
  1488. //
  1489. // See if the hive has more than 1 sub-keys.
  1490. //
  1491. //
  1492. Status = NtEnumerateKey(
  1493. HiveRoot,
  1494. 1, // Index - 0 is the SAM link, 1 is LSA policy database stuff
  1495. KeyBasicInformation, // Name of key
  1496. &DummyBuffer,
  1497. sizeof(DummyBuffer),
  1498. &IgnoreRequiredLength
  1499. );
  1500. if (Status == STATUS_NO_MORE_ENTRIES) {
  1501. //
  1502. // We are initializing the system...
  1503. // Apply a reasonable ACL to the hive root.
  1504. //
  1505. Status = LsapCreateDatabaseProtection( &Sd );
  1506. if (NT_SUCCESS(Status)) {
  1507. Status = NtSetSecurityObject(
  1508. HiveRoot, // Object to apply to
  1509. DACL_SECURITY_INFORMATION, // Information to set
  1510. (PSECURITY_DESCRIPTOR)&Sd // Descriptor
  1511. );
  1512. }
  1513. } else {
  1514. Status = STATUS_SUCCESS;
  1515. }
  1516. return(Status);
  1517. }
  1518. NTSTATUS
  1519. LsapCreateDatabaseProtection(
  1520. PISECURITY_DESCRIPTOR Sd
  1521. )
  1522. /*++
  1523. Routine Description:
  1524. This function allocates and initializes protection to assign to
  1525. the SAM database.
  1526. Upon return, any non-zero pointers in the security descriptors
  1527. point to memory allocated from process heap. It is the caller's
  1528. responsibility to free this memory.
  1529. Protection is:
  1530. System: All Access
  1531. Admin: ReadControl | WriteDac
  1532. Arguments:
  1533. Sd - Address of a security descriptor to initialize.
  1534. Return Value:
  1535. STATUS_SUCCESS - The Security descriptor has been initialize.
  1536. STATUS_NO_MEMORY - couldn't allocate memory for the protection info.
  1537. --*/
  1538. {
  1539. NTSTATUS
  1540. Status;
  1541. ULONG
  1542. Length;
  1543. USHORT
  1544. i;
  1545. PACL
  1546. Dacl;
  1547. PACE_HEADER
  1548. Ace;
  1549. //
  1550. // Initialize the security descriptor.
  1551. // This call should not fail.
  1552. //
  1553. Status = RtlCreateSecurityDescriptor( Sd, SECURITY_DESCRIPTOR_REVISION1 );
  1554. ASSERT(NT_SUCCESS(Status));
  1555. Length = (ULONG)sizeof(ACL) +
  1556. (2*((ULONG)sizeof(ACCESS_ALLOWED_ACE))) +
  1557. RtlLengthSid( LsapLocalSystemSid ) +
  1558. RtlLengthSid( LsapAliasAdminsSid ) +
  1559. 8; // The 8 is just for good measure
  1560. Dacl = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
  1561. if (Dacl == NULL) {
  1562. return(STATUS_NO_MEMORY);
  1563. }
  1564. Status = RtlCreateAcl (Dacl, Length, ACL_REVISION2 );
  1565. ASSERT(NT_SUCCESS(Status));
  1566. //
  1567. // Add ACEs to the ACL...
  1568. // These calls should not be able to fail.
  1569. //
  1570. Status = RtlAddAccessAllowedAce(
  1571. Dacl,
  1572. ACL_REVISION2,
  1573. (GENERIC_ALL),
  1574. LsapLocalSystemSid
  1575. );
  1576. ASSERT(NT_SUCCESS(Status));
  1577. Status = RtlAddAccessAllowedAce(
  1578. Dacl,
  1579. ACL_REVISION2,
  1580. (READ_CONTROL | WRITE_DAC),
  1581. LsapAliasAdminsSid
  1582. );
  1583. ASSERT(NT_SUCCESS(Status));
  1584. //
  1585. // Now mark the ACEs as inheritable...
  1586. //
  1587. for ( i=0; i<Dacl->AceCount; i++) {
  1588. //
  1589. // Get the address of the next ACE
  1590. // (Shouldn't fail)
  1591. //
  1592. Status = RtlGetAce( Dacl, (ULONG)i, &Ace );
  1593. ASSERT(NT_SUCCESS(Status));
  1594. Ace->AceFlags |= (CONTAINER_INHERIT_ACE);
  1595. }
  1596. //
  1597. // And add the ACL to the security descriptor.
  1598. // This call should not fail.
  1599. //
  1600. Status = RtlSetDaclSecurityDescriptor(
  1601. Sd,
  1602. TRUE, // DaclPresent
  1603. Dacl, // Dacl OPTIONAL
  1604. FALSE // DaclDefaulted OPTIONAL
  1605. );
  1606. ASSERT(NT_SUCCESS(Status));
  1607. return(STATUS_SUCCESS);
  1608. }
  1609. NTSTATUS
  1610. LsapUpdateDatabaseProtection(
  1611. IN ULONG Revision
  1612. )
  1613. /*++
  1614. Routine Description:
  1615. This function allocates and updates protection to assign to
  1616. the LSA database.
  1617. Arguments:
  1618. Revision - New database revision level
  1619. LSAP_DB_REVISION_1_3 -- grant POLICY_NOTIFICATION access to Administrators
  1620. LSAP_DB_REVISION_1_6 -- grant POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES to AnonymousLogonSid
  1621. LSAP_DB_REVISION_1_7 -- grant POLICY_NOTIFICATION to LocalService/NetworkService
  1622. Return Value:
  1623. STATUS_SUCCESS - The Security descriptor has been initialize.
  1624. STATUS_NO_MEMORY - couldn't allocate memory for the protection info.
  1625. --*/
  1626. {
  1627. NTSTATUS Status;
  1628. NTSTATUS TempStatus;
  1629. PSECURITY_DESCRIPTOR CurrentSd = NULL;
  1630. PSECURITY_DESCRIPTOR RelativeSd = NULL;
  1631. ULONG RelativeSdLength;
  1632. PSECURITY_DESCRIPTOR NewSd;
  1633. SECURITY_DESCRIPTOR NewSdBuffer;
  1634. USHORT i;
  1635. PACL Dacl, NewDacl = NULL, TempAcl;
  1636. PACE_HEADER Ace;
  1637. PSID AceSid;
  1638. BOOLEAN AdminAceFound = FALSE;
  1639. BOOLEAN UpdatedSd = FALSE;
  1640. //
  1641. // First, read the initial security descriptor...
  1642. //
  1643. Status = LsapRegReadObjectSD( LsapPolicyHandle,
  1644. &CurrentSd );
  1645. if ( !NT_SUCCESS( Status ) ) {
  1646. goto Cleanup;
  1647. }
  1648. ASSERT( Revision == LSAP_DB_REVISION_1_3
  1649. ||
  1650. Revision == LSAP_DB_REVISION_1_6
  1651. ||
  1652. Revision == LSAP_DB_REVISION_1_7 );
  1653. NewSd = CurrentSd;
  1654. if ( Revision == LSAP_DB_REVISION_1_3
  1655. ||
  1656. Revision == LSAP_DB_REVISION_1_6
  1657. ||
  1658. Revision == LSAP_DB_REVISION_1_7 )
  1659. {
  1660. Dacl = RtlpDaclAddrSecurityDescriptor( ( PISECURITY_DESCRIPTOR )CurrentSd );
  1661. if ( Dacl ) {
  1662. //
  1663. // We'll have to find the ace for local system
  1664. //
  1665. Ace = ( PACE_HEADER )FirstAce( Dacl );
  1666. for(i = 0; i < Dacl->AceCount; i++, Ace = ( PACE_HEADER )NextAce( Ace ) ) {
  1667. if ( IsObjectAceType( Ace ) ) {
  1668. AceSid = RtlObjectAceSid( Ace );
  1669. } else {
  1670. AceSid = &( ( PKNOWN_ACE )Ace )->SidStart;
  1671. }
  1672. //
  1673. // When upgrading to revision 1_3, update the administrators ACE
  1674. //
  1675. if ( Revision == LSAP_DB_REVISION_1_3 &&
  1676. RtlEqualSid( AceSid, LsapAliasAdminsSid ) ) {
  1677. //
  1678. // Get the access mask and or in our new bit
  1679. //
  1680. if ( IsObjectAceType( Ace ) ) {
  1681. if (( ((PKNOWN_OBJECT_ACE)Ace)->Mask & POLICY_NOTIFICATION ) == 0 ) {
  1682. ((PKNOWN_OBJECT_ACE)Ace)->Mask |= POLICY_NOTIFICATION;
  1683. UpdatedSd = TRUE;
  1684. }
  1685. } else {
  1686. if (( ((PKNOWN_ACE)Ace)->Mask & POLICY_NOTIFICATION ) == 0 ) {
  1687. ((PKNOWN_ACE)Ace)->Mask |= POLICY_NOTIFICATION;
  1688. UpdatedSd = TRUE;
  1689. }
  1690. }
  1691. AdminAceFound = TRUE;
  1692. }
  1693. }
  1694. }
  1695. //
  1696. // If we didn't find an ACE to update, make sure to add it...
  1697. //
  1698. if ( !AdminAceFound )
  1699. {
  1700. ULONG NewDaclLength;
  1701. UpdatedSd = TRUE;
  1702. NewDaclLength = Dacl ? Dacl->AclSize : 0;
  1703. if ( Revision == LSAP_DB_REVISION_1_3 )
  1704. {
  1705. NewDaclLength += ( ULONG )sizeof( ACCESS_ALLOWED_ACE ) +
  1706. RtlLengthSid( LsapAliasAdminsSid );
  1707. }
  1708. else if ( Revision == LSAP_DB_REVISION_1_6 )
  1709. {
  1710. NewDaclLength += ( ULONG )sizeof( ACCESS_ALLOWED_ACE ) +
  1711. RtlLengthSid( LsapAnonymousSid );
  1712. }
  1713. else
  1714. {
  1715. ASSERT( Revision == LSAP_DB_REVISION_1_7 );
  1716. NewDaclLength += 2 * ( ULONG )sizeof( ACCESS_ALLOWED_ACE ) +
  1717. RtlLengthSid( LsapLocalServiceSid ) +
  1718. RtlLengthSid( LsapNetworkServiceSid );
  1719. }
  1720. NewDacl = LsapAllocateLsaHeap( NewDaclLength );
  1721. if ( NewDacl == NULL ) {
  1722. Status = STATUS_INSUFFICIENT_RESOURCES;
  1723. goto Cleanup;
  1724. }
  1725. if ( Dacl ) {
  1726. RtlCopyMemory( NewDacl, Dacl, Dacl->AclSize );
  1727. NewDacl->AclSize = ( USHORT )NewDaclLength;
  1728. } else {
  1729. Status = RtlCreateAcl ( NewDacl, NewDaclLength, ACL_REVISION2 );
  1730. if ( !NT_SUCCESS(Status) ) {
  1731. goto Cleanup;
  1732. }
  1733. }
  1734. //
  1735. // For version 1.3, grant administrators All access and Policy notification access
  1736. //
  1737. if ( Revision == LSAP_DB_REVISION_1_3 ) {
  1738. Status = RtlAddAccessAllowedAce( NewDacl,
  1739. ACL_REVISION2,
  1740. POLICY_ALL_ACCESS |
  1741. POLICY_NOTIFICATION,
  1742. LsapAliasAdminsSid );
  1743. if ( !NT_SUCCESS(Status) ) {
  1744. goto Cleanup;
  1745. }
  1746. //
  1747. // For version 1.6, grant anonymous logon View Local and Lookup names access.
  1748. //
  1749. } else if ( Revision == LSAP_DB_REVISION_1_6) {
  1750. Status = RtlAddAccessAllowedAce( NewDacl,
  1751. ACL_REVISION2,
  1752. POLICY_VIEW_LOCAL_INFORMATION |
  1753. POLICY_LOOKUP_NAMES,
  1754. LsapAnonymousSid );
  1755. if ( !NT_SUCCESS(Status) ) {
  1756. goto Cleanup;
  1757. }
  1758. //
  1759. // For version 1.7, grant Policy notification access to LocalService
  1760. // and NetworkService
  1761. //
  1762. } else {
  1763. ASSERT( Revision == LSAP_DB_REVISION_1_7 );
  1764. Status = RtlAddAccessAllowedAce( NewDacl,
  1765. ACL_REVISION2,
  1766. POLICY_NOTIFICATION,
  1767. LsapLocalServiceSid );
  1768. if ( !NT_SUCCESS(Status) ) {
  1769. goto Cleanup;
  1770. }
  1771. Status = RtlAddAccessAllowedAce( NewDacl,
  1772. ACL_REVISION2,
  1773. POLICY_NOTIFICATION,
  1774. LsapNetworkServiceSid );
  1775. if ( !NT_SUCCESS(Status) ) {
  1776. goto Cleanup;
  1777. }
  1778. }
  1779. //
  1780. // If the current security descriptor is self relative,
  1781. // convert it to absolute so I can set the DACL on it.
  1782. //
  1783. if ( RtlpAreControlBitsSet( ( PISECURITY_DESCRIPTOR )CurrentSd,
  1784. SE_SELF_RELATIVE ) ) {
  1785. NewSd = &NewSdBuffer;
  1786. Status = RtlCreateSecurityDescriptor( NewSd,
  1787. SECURITY_DESCRIPTOR_REVISION );
  1788. if ( !NT_SUCCESS(Status) ) {
  1789. goto Cleanup;
  1790. }
  1791. ((PISECURITY_DESCRIPTOR)NewSd)->Control =
  1792. ((PISECURITY_DESCRIPTOR)CurrentSd)->Control;
  1793. AceSid = RtlpOwnerAddrSecurityDescriptor(
  1794. ( PISECURITY_DESCRIPTOR )CurrentSd );
  1795. if ( AceSid ) {
  1796. ( (PISECURITY_DESCRIPTOR)NewSd )->Owner = AceSid;
  1797. }
  1798. AceSid = RtlpGroupAddrSecurityDescriptor(
  1799. ( PISECURITY_DESCRIPTOR )CurrentSd );
  1800. if ( AceSid ) {
  1801. ( ( PISECURITY_DESCRIPTOR )NewSd )->Group = AceSid;
  1802. }
  1803. TempAcl = RtlpSaclAddrSecurityDescriptor(
  1804. ( PISECURITY_DESCRIPTOR )CurrentSd );
  1805. if ( TempAcl ) {
  1806. ( ( PISECURITY_DESCRIPTOR )NewSd )->Sacl = TempAcl;
  1807. }
  1808. RtlpClearControlBits( ( PISECURITY_DESCRIPTOR )NewSd,
  1809. SE_SELF_RELATIVE );
  1810. }
  1811. //
  1812. // Put the computed DACL onto the SD.
  1813. //
  1814. Status = RtlSetDaclSecurityDescriptor( NewSd,
  1815. TRUE,
  1816. NewDacl,
  1817. FALSE );
  1818. if ( !NT_SUCCESS(Status) ) {
  1819. goto Cleanup;
  1820. }
  1821. //
  1822. // Convert the SD to self relative before writing it to the database.
  1823. //
  1824. RelativeSdLength = 0;
  1825. Status = RtlMakeSelfRelativeSD( NewSd,
  1826. NULL,
  1827. &RelativeSdLength );
  1828. if (Status != STATUS_BUFFER_TOO_SMALL) { // This is the expected case
  1829. if ( NT_SUCCESS(Status) ) {
  1830. Status = STATUS_INTERNAL_ERROR;
  1831. }
  1832. goto Cleanup;
  1833. }
  1834. RelativeSd = LsapAllocateLsaHeap( RelativeSdLength );
  1835. if ( RelativeSd == NULL) {
  1836. Status = STATUS_INSUFFICIENT_RESOURCES;
  1837. goto Cleanup;
  1838. }
  1839. Status = RtlMakeSelfRelativeSD( NewSd,
  1840. RelativeSd,
  1841. &RelativeSdLength );
  1842. if ( !NT_SUCCESS(Status) ) {
  1843. goto Cleanup;
  1844. }
  1845. NewSd = RelativeSd;
  1846. }
  1847. }
  1848. if ( UpdatedSd ) {
  1849. ULONG NewSdLength;
  1850. //
  1851. // Set the security descriptor back on the object
  1852. //
  1853. NewSdLength = RtlLengthSecurityDescriptor( NewSd );
  1854. //
  1855. // Add a Registry transaction to write the Security Descriptor as the
  1856. // value of the new object's SecDesc subkey.
  1857. //
  1858. Status = LsapDbReferenceObject(
  1859. LsapDbHandle,
  1860. 0,
  1861. PolicyObject,
  1862. PolicyObject,
  1863. LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION
  1864. );
  1865. if ( !NT_SUCCESS(Status) ) {
  1866. goto Cleanup;
  1867. }
  1868. Status = LsapDbWriteAttributeObject( LsapPolicyHandle,
  1869. &LsapDbNames[ SecDesc ],
  1870. NewSd,
  1871. NewSdLength );
  1872. TempStatus = LsapDbDereferenceObject(
  1873. &LsapDbHandle,
  1874. PolicyObject,
  1875. PolicyObject,
  1876. (LSAP_DB_LOCK |
  1877. LSAP_DB_OMIT_REPLICATOR_NOTIFICATION | // Each BDC should upgrade its own database
  1878. LSAP_DB_FINISH_TRANSACTION),
  1879. (SECURITY_DB_DELTA_TYPE) 0,
  1880. Status );
  1881. if ( !NT_SUCCESS(TempStatus) ) {
  1882. if (NT_SUCCESS(Status) ) {
  1883. Status = TempStatus;
  1884. }
  1885. }
  1886. }
  1887. Cleanup:
  1888. //
  1889. // Free the security descriptor
  1890. //
  1891. LsapFreeLsaHeap( CurrentSd );
  1892. LsapFreeLsaHeap( RelativeSd );
  1893. LsapFreeLsaHeap( NewDacl );
  1894. return( Status );
  1895. }
  1896. NTSTATUS
  1897. LsapDbInitializeLock(
  1898. )
  1899. /*++
  1900. Routine Description:
  1901. This function initializes the LSA Database Lock. It is called once
  1902. only, during LSA Database initialization.
  1903. Arguments:
  1904. None.
  1905. Return Value:
  1906. NTSTATUS - Standard Nt Result Code
  1907. All Result Codes are generated by called routines.
  1908. --*/
  1909. {
  1910. NTSTATUS Status;
  1911. Status = SafeInitializeCriticalSection( &LsapDbState.AccountLock, ( DWORD )ACCOUNT_LOCK_ENUM );
  1912. if (!NT_SUCCESS(Status) ) {
  1913. goto Cleanup;
  1914. }
  1915. Status = SafeInitializeCriticalSection( &LsapDbState.PolicyLock, ( DWORD )POLICY_LOCK_ENUM );
  1916. if (!NT_SUCCESS(Status) ) {
  1917. goto Cleanup;
  1918. }
  1919. Status = SafeInitializeCriticalSection( &LsapDbState.SecretLock, ( DWORD )SECRET_LOCK_ENUM );
  1920. if (!NT_SUCCESS(Status) ) {
  1921. goto Cleanup;
  1922. }
  1923. Status = SafeInitializeCriticalSection( &LsapDbState.RegistryLock, ( DWORD )REGISTRY_LOCK_ENUM );
  1924. if (!NT_SUCCESS(Status) ) {
  1925. goto Cleanup;
  1926. }
  1927. Status = SafeInitializeCriticalSection( &LsapDbState.HandleTableLock, ( DWORD )HANDLE_TABLE_LOCK_ENUM );
  1928. if (!NT_SUCCESS(Status) ) {
  1929. goto Cleanup;
  1930. }
  1931. try
  1932. {
  1933. SafeInitializeResource( &LsapDbState.PolicyCacheLock, ( DWORD )POLICY_CACHE_LOCK_ENUM );
  1934. Status = STATUS_SUCCESS;
  1935. }
  1936. except( EXCEPTION_EXECUTE_HANDLER )
  1937. {
  1938. Status = GetExceptionCode();
  1939. }
  1940. if (!NT_SUCCESS(Status) ) {
  1941. goto Cleanup;
  1942. }
  1943. //
  1944. // Initialize the Resource for the Trusted Domain List.
  1945. //
  1946. InitializeListHead( &LsapDbTrustedDomainList.ListHead );
  1947. LsapDbTrustedDomainList.TrustedDomainCount = 0;
  1948. LsapDbTrustedDomainList.CurrentSequenceNumber = 0;
  1949. LsapDbMakeCacheInvalid( TrustedDomainObject );
  1950. try
  1951. {
  1952. SafeInitializeResource( &LsapDbTrustedDomainList.Resource, ( DWORD )TRUST_LOCK_ENUM );
  1953. Status = STATUS_SUCCESS ;
  1954. }
  1955. except (EXCEPTION_EXECUTE_HANDLER )
  1956. {
  1957. Status = GetExceptionCode();
  1958. }
  1959. if ( !NT_SUCCESS( Status ) ) {
  1960. goto Cleanup;
  1961. }
  1962. try
  1963. {
  1964. //
  1965. // do not use the safelock library for ScePolicyLock
  1966. // because it is usually acquired on one thread and
  1967. // released on another
  1968. //
  1969. RtlInitializeResource( &LsapDbState.ScePolicyLock );
  1970. Status = STATUS_SUCCESS ;
  1971. }
  1972. except ( EXCEPTION_EXECUTE_HANDLER )
  1973. {
  1974. Status = GetExceptionCode();
  1975. }
  1976. if (!NT_SUCCESS( Status )) {
  1977. goto Cleanup;
  1978. }
  1979. LsapDbState.SceSyncEvent = CreateEvent( NULL, TRUE, TRUE, NULL );
  1980. if ( LsapDbState.SceSyncEvent == NULL ) {
  1981. Status = GetLastError();
  1982. goto Cleanup;
  1983. }
  1984. #if DBG
  1985. try
  1986. {
  1987. SafeInitializeResource( &LsapDsThreadInfoListResource, ( DWORD )THREAD_INFO_LIST_LOCK_ENUM );
  1988. Status = STATUS_SUCCESS ;
  1989. }
  1990. except ( EXCEPTION_EXECUTE_HANDLER )
  1991. {
  1992. Status = GetExceptionCode();
  1993. }
  1994. if ( !NT_SUCCESS( Status ) ) {
  1995. goto Cleanup;
  1996. }
  1997. RtlZeroMemory( &LsapDsThreadInfoList, sizeof( LSADS_THREAD_INFO_NODE ) * LSAP_THREAD_INFO_LIST_MAX );
  1998. #endif
  1999. Status = STATUS_SUCCESS;
  2000. Cleanup:
  2001. return( Status );
  2002. }
  2003. NTSTATUS
  2004. LsapDbInitializeWellKnownValues(
  2005. )
  2006. /*++
  2007. Routine Description:
  2008. This function initializes the well-known values used by LSA.
  2009. Arguments:
  2010. None.
  2011. Return Value:
  2012. NTSTATUS - Standard Nt Result Code
  2013. All Result Codes are generated by called routines.
  2014. --*/
  2015. {
  2016. NTSTATUS Status;
  2017. BOOLEAN b;
  2018. //
  2019. // Initialize the Well Known Sids
  2020. //
  2021. b = LsapDbInitializeWellKnownSids( &WellKnownSids );
  2022. if (!b ) {
  2023. Status = STATUS_UNSUCCESSFUL;
  2024. goto InitializeWellKnownValuesError;
  2025. }
  2026. //
  2027. // Initialize the well known privilege values
  2028. //
  2029. Status = LsapDbInitializeWellKnownPrivs();
  2030. if (!NT_SUCCESS(Status)) {
  2031. goto InitializeWellKnownValuesError;
  2032. }
  2033. InitializeWellKnownValuesFinish:
  2034. return(Status);
  2035. InitializeWellKnownValuesError:
  2036. goto InitializeWellKnownValuesFinish;
  2037. }
  2038. NTSTATUS
  2039. LsapDbInitializeWellKnownPrivs(
  2040. )
  2041. /*++
  2042. Routine Description:
  2043. This function initializes the well-known privilege values.
  2044. Arguments:
  2045. None.
  2046. Return Value:
  2047. NTSTATUS - Standard Nt Result Code
  2048. Currently, only STATUS_SUCCESS is returned.
  2049. --*/
  2050. {
  2051. LsapTcbPrivilege = RtlConvertLongToLuid(SE_TCB_PRIVILEGE);
  2052. return STATUS_SUCCESS;
  2053. }
  2054. BOOLEAN
  2055. LsapDbInitializeWellKnownSids(
  2056. OUT PLSAP_WELL_KNOWN_SID_ENTRY *WellKnownSids
  2057. )
  2058. /*++
  2059. Routine Description:
  2060. This function initializes the Well-Known Sids
  2061. Arguments:
  2062. WellKnownSids - Receives a pointer to a newly created table of
  2063. the Well Known Sids.
  2064. Return Value:
  2065. BOOLEAN - TRUE if successful, else FALSE.
  2066. --*/
  2067. {
  2068. NTSTATUS Status;
  2069. BOOLEAN BooleanStatus = TRUE;
  2070. LSAP_WELL_KNOWN_SID_INDEX WellKnownSidIndex;
  2071. ULONG SubAuthorities[LSAP_WELL_KNOWN_MAX_SUBAUTH_LEVEL];
  2072. ULONG OutputWellKnownSidsLength;
  2073. PLSAP_WELL_KNOWN_SID_ENTRY OutputWellKnownSids = NULL;
  2074. UNICODE_STRING SidName, NtAuthorityName, UsersName;
  2075. HMODULE StringsResource;
  2076. SID_IDENTIFIER_AUTHORITY InternetSiteAuthority
  2077. = SECURITY_INTERNETSITE_AUTHORITY;
  2078. //
  2079. // Get the message resource we need to get the SID names from
  2080. //
  2081. StringsResource = (HMODULE) LoadLibrary( L"LSASRV.DLL" );
  2082. if (StringsResource == NULL) {
  2083. return(FALSE);
  2084. }
  2085. Status = LsapGetMessageStrings(
  2086. StringsResource,
  2087. LSAP_SID_NAME_NT_AUTHORITY,
  2088. &NtAuthorityName,
  2089. 0,
  2090. NULL
  2091. ); ASSERT(NT_SUCCESS(Status));
  2092. //
  2093. // Allocate memory for the table of Sids.
  2094. //
  2095. OutputWellKnownSidsLength =
  2096. LsapDummyLastSidIndex * sizeof(LSAP_WELL_KNOWN_SID_ENTRY);
  2097. OutputWellKnownSids = RtlAllocateHeap(
  2098. RtlProcessHeap(),
  2099. 0,
  2100. OutputWellKnownSidsLength
  2101. );
  2102. if (OutputWellKnownSids == NULL) {
  2103. goto InitializeWellKnownSidsError;
  2104. }
  2105. //
  2106. // Allocate and initialize the universal SIDs
  2107. //
  2108. Status = LsapGetMessageStrings(
  2109. StringsResource,
  2110. LSAP_SID_NAME_NULL,
  2111. &SidName,
  2112. 0,
  2113. NULL
  2114. ); ASSERT(NT_SUCCESS(Status));
  2115. SubAuthorities[0] = SECURITY_NULL_RID;
  2116. if (!LsapDbInitializeWellKnownSid(
  2117. OutputWellKnownSids,
  2118. LsapNullSidIndex,
  2119. &LsapNullSidAuthority,
  2120. 1,
  2121. SubAuthorities,
  2122. SidName.Buffer,
  2123. L"",
  2124. SidTypeWellKnownGroup
  2125. )) {
  2126. goto InitializeWellKnownSidsError;
  2127. }
  2128. Status = LsapGetMessageStrings(
  2129. StringsResource,
  2130. LSAP_SID_NAME_WORLD,
  2131. &SidName,
  2132. 0,
  2133. NULL
  2134. ); ASSERT(NT_SUCCESS(Status));
  2135. SubAuthorities[0] = SECURITY_WORLD_RID;
  2136. if (!LsapDbInitializeWellKnownSid(
  2137. OutputWellKnownSids,
  2138. LsapWorldSidIndex,
  2139. &LsapWorldSidAuthority,
  2140. 1,
  2141. SubAuthorities,
  2142. SidName.Buffer,
  2143. L"",
  2144. SidTypeWellKnownGroup
  2145. )) {
  2146. goto InitializeWellKnownSidsError;
  2147. }
  2148. Status = LsapGetMessageStrings(
  2149. StringsResource,
  2150. LSAP_SID_NAME_LOCAL,
  2151. &SidName,
  2152. 0,
  2153. NULL
  2154. ); ASSERT(NT_SUCCESS(Status));
  2155. SubAuthorities[0] = SECURITY_LOCAL_RID;
  2156. if (!LsapDbInitializeWellKnownSid(
  2157. OutputWellKnownSids,
  2158. LsapLocalSidIndex,
  2159. &LsapLocalSidAuthority,
  2160. 1,
  2161. SubAuthorities,
  2162. SidName.Buffer,
  2163. L"",
  2164. SidTypeWellKnownGroup
  2165. )) {
  2166. goto InitializeWellKnownSidsError;
  2167. }
  2168. Status = LsapGetMessageStrings(
  2169. StringsResource,
  2170. LSAP_SID_NAME_CREATOR_OWNER,
  2171. &SidName,
  2172. 0,
  2173. NULL
  2174. ); ASSERT(NT_SUCCESS(Status));
  2175. SubAuthorities[0] = SECURITY_CREATOR_OWNER_RID;
  2176. if (!LsapDbInitializeWellKnownSid(
  2177. OutputWellKnownSids,
  2178. LsapCreatorOwnerSidIndex,
  2179. &LsapCreatorSidAuthority,
  2180. 1,
  2181. SubAuthorities,
  2182. SidName.Buffer,
  2183. L"",
  2184. SidTypeWellKnownGroup
  2185. )) {
  2186. goto InitializeWellKnownSidsError;
  2187. }
  2188. Status = LsapGetMessageStrings(
  2189. StringsResource,
  2190. LSAP_SID_NAME_CREATOR_GROUP,
  2191. &SidName,
  2192. 0,
  2193. NULL
  2194. ); ASSERT(NT_SUCCESS(Status));
  2195. SubAuthorities[0] = SECURITY_CREATOR_GROUP_RID;
  2196. if (!LsapDbInitializeWellKnownSid(
  2197. OutputWellKnownSids,
  2198. LsapCreatorGroupSidIndex,
  2199. &LsapCreatorSidAuthority,
  2200. 1,
  2201. SubAuthorities,
  2202. SidName.Buffer,
  2203. L"",
  2204. SidTypeWellKnownGroup
  2205. )) {
  2206. goto InitializeWellKnownSidsError;
  2207. }
  2208. Status = LsapGetMessageStrings(
  2209. StringsResource,
  2210. LSAP_SID_NAME_CREATOR_OWNER_SERVER,
  2211. &SidName,
  2212. 0,
  2213. NULL
  2214. ); ASSERT(NT_SUCCESS(Status));
  2215. SubAuthorities[0] = SECURITY_CREATOR_OWNER_SERVER_RID;
  2216. if (!LsapDbInitializeWellKnownSid(
  2217. OutputWellKnownSids,
  2218. LsapCreatorOwnerServerSidIndex,
  2219. &LsapCreatorSidAuthority,
  2220. 1,
  2221. SubAuthorities,
  2222. SidName.Buffer,
  2223. L"",
  2224. SidTypeWellKnownGroup
  2225. )) {
  2226. goto InitializeWellKnownSidsError;
  2227. }
  2228. Status = LsapGetMessageStrings(
  2229. StringsResource,
  2230. LSAP_SID_NAME_CREATOR_GROUP_SERVER,
  2231. &SidName,
  2232. 0,
  2233. NULL
  2234. ); ASSERT(NT_SUCCESS(Status));
  2235. SubAuthorities[0] = SECURITY_CREATOR_GROUP_SERVER_RID;
  2236. if (!LsapDbInitializeWellKnownSid(
  2237. OutputWellKnownSids,
  2238. LsapCreatorGroupServerSidIndex,
  2239. &LsapCreatorSidAuthority,
  2240. 1,
  2241. SubAuthorities,
  2242. SidName.Buffer,
  2243. L"",
  2244. SidTypeWellKnownGroup
  2245. )) {
  2246. goto InitializeWellKnownSidsError;
  2247. }
  2248. //
  2249. // Initialize the Nt well-known Sids
  2250. //
  2251. Status = LsapGetMessageStrings(
  2252. StringsResource,
  2253. LSAP_SID_NAME_NT_DOMAIN,
  2254. &SidName,
  2255. 0,
  2256. NULL
  2257. ); ASSERT(NT_SUCCESS(Status));
  2258. if (!LsapDbInitializeWellKnownSid(
  2259. OutputWellKnownSids,
  2260. LsapNtAuthoritySidIndex,
  2261. &LsapNtAuthority,
  2262. 0,
  2263. NULL,
  2264. L"",
  2265. SidName.Buffer,
  2266. SidTypeDomain
  2267. )) {
  2268. goto InitializeWellKnownSidsError;
  2269. }
  2270. Status = LsapGetMessageStrings(
  2271. StringsResource,
  2272. LSAP_SID_NAME_DIALUP,
  2273. &SidName,
  2274. 0,
  2275. NULL
  2276. ); ASSERT(NT_SUCCESS(Status));
  2277. SubAuthorities[0] = SECURITY_DIALUP_RID;
  2278. if (!LsapDbInitializeWellKnownSid(
  2279. OutputWellKnownSids,
  2280. LsapDialupSidIndex,
  2281. &LsapNtAuthority,
  2282. 1,
  2283. SubAuthorities,
  2284. SidName.Buffer,
  2285. NtAuthorityName.Buffer,
  2286. SidTypeWellKnownGroup
  2287. )) {
  2288. goto InitializeWellKnownSidsError;
  2289. }
  2290. Status = LsapGetMessageStrings(
  2291. StringsResource,
  2292. LSAP_SID_NAME_NETWORK,
  2293. &SidName,
  2294. 0,
  2295. NULL
  2296. ); ASSERT(NT_SUCCESS(Status));
  2297. SubAuthorities[0] = SECURITY_NETWORK_RID;
  2298. if (!LsapDbInitializeWellKnownSid(
  2299. OutputWellKnownSids,
  2300. LsapNetworkSidIndex,
  2301. &LsapNtAuthority,
  2302. 1,
  2303. SubAuthorities,
  2304. SidName.Buffer,
  2305. NtAuthorityName.Buffer,
  2306. SidTypeWellKnownGroup
  2307. )) {
  2308. goto InitializeWellKnownSidsError;
  2309. }
  2310. Status = LsapGetMessageStrings(
  2311. StringsResource,
  2312. LSAP_SID_NAME_BATCH,
  2313. &SidName,
  2314. 0,
  2315. NULL
  2316. ); ASSERT(NT_SUCCESS(Status));
  2317. SubAuthorities[0] = SECURITY_BATCH_RID;
  2318. if (!LsapDbInitializeWellKnownSid(
  2319. OutputWellKnownSids,
  2320. LsapBatchSidIndex,
  2321. &LsapNtAuthority,
  2322. 1,
  2323. SubAuthorities,
  2324. SidName.Buffer,
  2325. NtAuthorityName.Buffer,
  2326. SidTypeWellKnownGroup
  2327. )) {
  2328. goto InitializeWellKnownSidsError;
  2329. }
  2330. Status = LsapGetMessageStrings(
  2331. StringsResource,
  2332. LSAP_SID_NAME_INTERACTIVE,
  2333. &SidName,
  2334. 0,
  2335. NULL
  2336. ); ASSERT(NT_SUCCESS(Status));
  2337. SubAuthorities[0] = SECURITY_INTERACTIVE_RID;
  2338. if (!LsapDbInitializeWellKnownSid(
  2339. OutputWellKnownSids,
  2340. LsapInteractiveSidIndex,
  2341. &LsapNtAuthority,
  2342. 1,
  2343. SubAuthorities,
  2344. SidName.Buffer,
  2345. NtAuthorityName.Buffer,
  2346. SidTypeWellKnownGroup
  2347. )) {
  2348. goto InitializeWellKnownSidsError;
  2349. }
  2350. Status = LsapGetMessageStrings(
  2351. StringsResource,
  2352. LSAP_SID_NAME_REMOTE_INTERACTIVE,
  2353. &SidName,
  2354. 0,
  2355. NULL); ASSERT(NT_SUCCESS(Status));
  2356. SubAuthorities[0] = SECURITY_REMOTE_LOGON_RID;
  2357. if (!LsapDbInitializeWellKnownSid(
  2358. OutputWellKnownSids,
  2359. LsapRemoteInteractiveSidIndex,
  2360. &LsapNtAuthority,
  2361. 1,
  2362. SubAuthorities,
  2363. SidName.Buffer,
  2364. NtAuthorityName.Buffer,
  2365. SidTypeWellKnownGroup
  2366. )) {
  2367. goto InitializeWellKnownSidsError;
  2368. }
  2369. Status = LsapGetMessageStrings(
  2370. StringsResource,
  2371. LSAP_SID_NAME_THIS_ORGANIZATION,
  2372. &SidName,
  2373. 0,
  2374. NULL); ASSERT(NT_SUCCESS(Status));
  2375. SubAuthorities[0] = SECURITY_THIS_ORGANIZATION_RID;
  2376. if (!LsapDbInitializeWellKnownSid(
  2377. OutputWellKnownSids,
  2378. LsapThisOrganizationSidIndex,
  2379. &LsapNtAuthority,
  2380. 1,
  2381. SubAuthorities,
  2382. SidName.Buffer,
  2383. NtAuthorityName.Buffer,
  2384. SidTypeWellKnownGroup
  2385. )) {
  2386. goto InitializeWellKnownSidsError;
  2387. }
  2388. Status = LsapGetMessageStrings(
  2389. StringsResource,
  2390. LSAP_SID_NAME_OTHER_ORGANIZATION,
  2391. &SidName,
  2392. 0,
  2393. NULL); ASSERT(NT_SUCCESS(Status));
  2394. SubAuthorities[0] = SECURITY_OTHER_ORGANIZATION_RID;
  2395. if (!LsapDbInitializeWellKnownSid(
  2396. OutputWellKnownSids,
  2397. LsapOtherOrganizationSidIndex,
  2398. &LsapNtAuthority,
  2399. 1,
  2400. SubAuthorities,
  2401. SidName.Buffer,
  2402. NtAuthorityName.Buffer,
  2403. SidTypeWellKnownGroup
  2404. )) {
  2405. goto InitializeWellKnownSidsError;
  2406. }
  2407. Status = LsapGetMessageStrings(
  2408. StringsResource,
  2409. LSAP_SID_NAME_TERMINAL_SERVER,
  2410. &SidName,
  2411. 0,
  2412. NULL
  2413. ); ASSERT(NT_SUCCESS(Status));
  2414. SubAuthorities[0] = SECURITY_TERMINAL_SERVER_RID;
  2415. if (!LsapDbInitializeWellKnownSid(
  2416. OutputWellKnownSids,
  2417. LsapTerminalServerSidIndex,
  2418. &LsapNtAuthority,
  2419. 1,
  2420. SubAuthorities,
  2421. SidName.Buffer,
  2422. NtAuthorityName.Buffer,
  2423. SidTypeWellKnownGroup
  2424. )) {
  2425. goto InitializeWellKnownSidsError;
  2426. }
  2427. Status = LsapGetMessageStrings(
  2428. StringsResource,
  2429. LSAP_SID_NAME_SERVICE,
  2430. &SidName,
  2431. 0,
  2432. NULL
  2433. ); ASSERT(NT_SUCCESS(Status));
  2434. SubAuthorities[0] = SECURITY_SERVICE_RID;
  2435. if (!LsapDbInitializeWellKnownSid(
  2436. OutputWellKnownSids,
  2437. LsapServiceSidIndex,
  2438. &LsapNtAuthority,
  2439. 1,
  2440. SubAuthorities,
  2441. SidName.Buffer,
  2442. NtAuthorityName.Buffer,
  2443. SidTypeWellKnownGroup
  2444. )) {
  2445. goto InitializeWellKnownSidsError;
  2446. }
  2447. Status = LsapGetMessageStrings(
  2448. StringsResource,
  2449. LSAP_SID_NAME_ANONYMOUS,
  2450. &SidName,
  2451. 0,
  2452. NULL
  2453. ); ASSERT(NT_SUCCESS(Status));
  2454. SubAuthorities[0] = SECURITY_ANONYMOUS_LOGON_RID;
  2455. if (!LsapDbInitializeWellKnownSid(
  2456. OutputWellKnownSids,
  2457. LsapAnonymousSidIndex,
  2458. &LsapNtAuthority,
  2459. 1,
  2460. SubAuthorities,
  2461. SidName.Buffer,
  2462. NtAuthorityName.Buffer,
  2463. SidTypeWellKnownGroup
  2464. )) {
  2465. goto InitializeWellKnownSidsError;
  2466. }
  2467. Status = LsapGetMessageStrings(
  2468. StringsResource,
  2469. LSAP_SID_NAME_PROXY,
  2470. &SidName,
  2471. 0,
  2472. NULL
  2473. ); ASSERT(NT_SUCCESS(Status));
  2474. SubAuthorities[0] = SECURITY_PROXY_RID;
  2475. if (!LsapDbInitializeWellKnownSid(
  2476. OutputWellKnownSids,
  2477. LsapProxySidIndex,
  2478. &LsapNtAuthority,
  2479. 1,
  2480. SubAuthorities,
  2481. SidName.Buffer,
  2482. NtAuthorityName.Buffer,
  2483. SidTypeWellKnownGroup
  2484. )) {
  2485. goto InitializeWellKnownSidsError;
  2486. }
  2487. Status = LsapGetMessageStrings(
  2488. StringsResource,
  2489. LSAP_SID_NAME_SERVER,
  2490. &SidName,
  2491. 0,
  2492. NULL
  2493. ); ASSERT(NT_SUCCESS(Status));
  2494. SubAuthorities[0] = SECURITY_SERVER_LOGON_RID;
  2495. if (!LsapDbInitializeWellKnownSid(
  2496. OutputWellKnownSids,
  2497. LsapServerSidIndex,
  2498. &LsapNtAuthority,
  2499. 1,
  2500. SubAuthorities,
  2501. SidName.Buffer,
  2502. NtAuthorityName.Buffer,
  2503. SidTypeWellKnownGroup
  2504. )) {
  2505. goto InitializeWellKnownSidsError;
  2506. }
  2507. Status = LsapGetMessageStrings(
  2508. StringsResource,
  2509. LSAP_SID_NAME_SELF,
  2510. &SidName,
  2511. 0,
  2512. NULL
  2513. ); ASSERT(NT_SUCCESS(Status));
  2514. SubAuthorities[0] = SECURITY_PRINCIPAL_SELF_RID;
  2515. if (!LsapDbInitializeWellKnownSid(
  2516. OutputWellKnownSids,
  2517. LsapSelfSidIndex,
  2518. &LsapNtAuthority,
  2519. 1,
  2520. SubAuthorities,
  2521. SidName.Buffer,
  2522. NtAuthorityName.Buffer,
  2523. SidTypeWellKnownGroup
  2524. )) {
  2525. goto InitializeWellKnownSidsError;
  2526. }
  2527. Status = LsapGetMessageStrings(
  2528. StringsResource,
  2529. LSAP_SID_NAME_AUTHENTICATED_USER,
  2530. &SidName,
  2531. 0,
  2532. NULL
  2533. ); ASSERT(NT_SUCCESS(Status));
  2534. SubAuthorities[0] = SECURITY_AUTHENTICATED_USER_RID;
  2535. if (!LsapDbInitializeWellKnownSid(
  2536. OutputWellKnownSids,
  2537. LsapAuthenticatedUserSidIndex,
  2538. &LsapNtAuthority,
  2539. 1,
  2540. SubAuthorities,
  2541. SidName.Buffer,
  2542. NtAuthorityName.Buffer,
  2543. SidTypeWellKnownGroup
  2544. )) {
  2545. goto InitializeWellKnownSidsError;
  2546. }
  2547. //
  2548. // Add any Logon Id well known sids here.
  2549. //
  2550. SubAuthorities[0] = SECURITY_LOGON_IDS_RID;
  2551. SubAuthorities[1] = 0;
  2552. SubAuthorities[2] = 0;
  2553. if (!LsapDbInitializeWellKnownSid(
  2554. OutputWellKnownSids,
  2555. LsapLogonSidIndex,
  2556. &LsapNtAuthority,
  2557. 3,
  2558. SubAuthorities,
  2559. L"",
  2560. NtAuthorityName.Buffer,
  2561. SidTypeWellKnownGroup
  2562. )) {
  2563. goto InitializeWellKnownSidsError;
  2564. }
  2565. Status = LsapGetMessageStrings(
  2566. StringsResource,
  2567. LSAP_SID_NAME_SYSTEM,
  2568. &SidName,
  2569. 0,
  2570. NULL
  2571. ); ASSERT(NT_SUCCESS(Status));
  2572. SubAuthorities[0] = SECURITY_LOCAL_SYSTEM_RID;
  2573. if (!LsapDbInitializeWellKnownSid(
  2574. OutputWellKnownSids,
  2575. LsapLocalSystemSidIndex,
  2576. &LsapNtAuthority,
  2577. 1,
  2578. SubAuthorities,
  2579. SidName.Buffer,
  2580. NtAuthorityName.Buffer,
  2581. SidTypeWellKnownGroup
  2582. )) {
  2583. goto InitializeWellKnownSidsError;
  2584. }
  2585. Status = LsapGetMessageStrings(
  2586. StringsResource,
  2587. LSAP_SID_NAME_LOCALSERVICE,
  2588. &SidName,
  2589. 0,
  2590. NULL
  2591. ); ASSERT(NT_SUCCESS(Status));
  2592. SubAuthorities[0] = SECURITY_LOCAL_SERVICE_RID;
  2593. if (!LsapDbInitializeWellKnownSid(
  2594. OutputWellKnownSids,
  2595. LsapLocalServiceSidIndex,
  2596. &LsapNtAuthority,
  2597. 1,
  2598. SubAuthorities,
  2599. SidName.Buffer,
  2600. NtAuthorityName.Buffer,
  2601. SidTypeWellKnownGroup
  2602. )) {
  2603. goto InitializeWellKnownSidsError;
  2604. }
  2605. Status = LsapGetMessageStrings(
  2606. StringsResource,
  2607. LSAP_SID_NAME_NETWORKSERVICE,
  2608. &SidName,
  2609. 0,
  2610. NULL
  2611. ); ASSERT(NT_SUCCESS(Status));
  2612. SubAuthorities[0] = SECURITY_NETWORK_SERVICE_RID;
  2613. if (!LsapDbInitializeWellKnownSid(
  2614. OutputWellKnownSids,
  2615. LsapNetworkServiceSidIndex,
  2616. &LsapNtAuthority,
  2617. 1,
  2618. SubAuthorities,
  2619. SidName.Buffer,
  2620. NtAuthorityName.Buffer,
  2621. SidTypeWellKnownGroup
  2622. )) {
  2623. goto InitializeWellKnownSidsError;
  2624. }
  2625. Status = LsapGetMessageStrings(
  2626. StringsResource,
  2627. LSAP_SID_NAME_RESTRICTED,
  2628. &SidName,
  2629. 0,
  2630. NULL
  2631. ); ASSERT(NT_SUCCESS(Status));
  2632. SubAuthorities[0] = SECURITY_RESTRICTED_CODE_RID;
  2633. if (!LsapDbInitializeWellKnownSid(
  2634. OutputWellKnownSids,
  2635. LsapRestrictedSidIndex,
  2636. &LsapNtAuthority,
  2637. 1,
  2638. SubAuthorities,
  2639. SidName.Buffer,
  2640. NtAuthorityName.Buffer,
  2641. SidTypeWellKnownGroup
  2642. )) {
  2643. goto InitializeWellKnownSidsError;
  2644. }
  2645. Status = LsapGetMessageStrings(
  2646. StringsResource,
  2647. LSAP_SID_NAME_INTERNET,
  2648. &SidName,
  2649. 0,
  2650. NULL
  2651. ); ASSERT(NT_SUCCESS(Status));
  2652. if (!LsapDbInitializeWellKnownSid(
  2653. OutputWellKnownSids,
  2654. LsapInternetDomainIndex,
  2655. &InternetSiteAuthority,
  2656. 0,
  2657. SubAuthorities,
  2658. L"",
  2659. SidName.Buffer,
  2660. SidTypeDomain
  2661. )) {
  2662. goto InitializeWellKnownSidsError;
  2663. }
  2664. //
  2665. // Add any security package well known sids
  2666. //
  2667. SubAuthorities[0] = SECURITY_PACKAGE_BASE_RID;
  2668. SubAuthorities[1] = RPC_C_AUTHN_WINNT;
  2669. Status = LsapGetMessageStrings(
  2670. StringsResource,
  2671. LSAP_SID_NAME_NTLM_AUTH,
  2672. &SidName,
  2673. 0,
  2674. NULL
  2675. ); ASSERT(NT_SUCCESS(Status));
  2676. if (!LsapDbInitializeWellKnownSid(
  2677. OutputWellKnownSids,
  2678. LsapNTLMAuthenticationSidIndex,
  2679. &LsapNtAuthority,
  2680. SECURITY_PACKAGE_RID_COUNT,
  2681. SubAuthorities,
  2682. SidName.Buffer,
  2683. NtAuthorityName.Buffer,
  2684. SidTypeWellKnownGroup
  2685. )) {
  2686. goto InitializeWellKnownSidsError;
  2687. }
  2688. SubAuthorities[1] = RPC_C_AUTHN_DIGEST;
  2689. Status = LsapGetMessageStrings(
  2690. StringsResource,
  2691. LSAP_SID_NAME_DIGEST_AUTH,
  2692. &SidName,
  2693. 0,
  2694. NULL
  2695. ); ASSERT(NT_SUCCESS(Status));
  2696. if (!LsapDbInitializeWellKnownSid(
  2697. OutputWellKnownSids,
  2698. LsapDigestAuthenticationSidIndex,
  2699. &LsapNtAuthority,
  2700. SECURITY_PACKAGE_RID_COUNT,
  2701. SubAuthorities,
  2702. SidName.Buffer,
  2703. NtAuthorityName.Buffer,
  2704. SidTypeWellKnownGroup
  2705. )) {
  2706. goto InitializeWellKnownSidsError;
  2707. }
  2708. SubAuthorities[1] = RPC_C_AUTHN_GSS_SCHANNEL;
  2709. Status = LsapGetMessageStrings(
  2710. StringsResource,
  2711. LSAP_SID_NAME_SCHANNEL_AUTH,
  2712. &SidName,
  2713. 0,
  2714. NULL
  2715. ); ASSERT(NT_SUCCESS(Status));
  2716. if (!LsapDbInitializeWellKnownSid(
  2717. OutputWellKnownSids,
  2718. LsapSChannelAuthenticationSidIndex,
  2719. &LsapNtAuthority,
  2720. SECURITY_PACKAGE_RID_COUNT,
  2721. SubAuthorities,
  2722. SidName.Buffer,
  2723. NtAuthorityName.Buffer,
  2724. SidTypeWellKnownGroup
  2725. )) {
  2726. goto InitializeWellKnownSidsError;
  2727. }
  2728. //
  2729. // Initialize SIDs from the BUILTIN domain. Leave the Name
  2730. // field blank for the aliases as they can be renamed while
  2731. // the system is running (and the lookup code will fall
  2732. // through to SAM for these).
  2733. //
  2734. Status = LsapGetMessageStrings(
  2735. StringsResource,
  2736. LSAP_SID_NAME_BUILTIN,
  2737. &SidName,
  2738. 0,
  2739. NULL
  2740. ); ASSERT(NT_SUCCESS(Status));
  2741. SubAuthorities[0] = SECURITY_BUILTIN_DOMAIN_RID;
  2742. if (!LsapDbInitializeWellKnownSid(
  2743. OutputWellKnownSids,
  2744. LsapBuiltInDomainSidIndex,
  2745. &LsapNtAuthority,
  2746. 1,
  2747. SubAuthorities,
  2748. L"",
  2749. SidName.Buffer,
  2750. SidTypeDomain
  2751. )) {
  2752. goto InitializeWellKnownSidsError;
  2753. }
  2754. SubAuthorities[1] = DOMAIN_ALIAS_RID_USERS;
  2755. if (!LsapDbInitializeWellKnownSid(
  2756. OutputWellKnownSids,
  2757. LsapAliasUsersSidIndex,
  2758. &LsapNtAuthority,
  2759. 2,
  2760. SubAuthorities,
  2761. L"",
  2762. SidName.Buffer,
  2763. SidTypeAlias
  2764. )) {
  2765. goto InitializeWellKnownSidsError;
  2766. }
  2767. SubAuthorities[1] = DOMAIN_ALIAS_RID_ADMINS;
  2768. if (!LsapDbInitializeWellKnownSid(
  2769. OutputWellKnownSids,
  2770. LsapAliasAdminsSidIndex,
  2771. &LsapNtAuthority,
  2772. 2,
  2773. SubAuthorities,
  2774. L"",
  2775. SidName.Buffer,
  2776. SidTypeAlias
  2777. )) {
  2778. goto InitializeWellKnownSidsError;
  2779. }
  2780. Status = LsapGetMessageStrings(
  2781. StringsResource,
  2782. LSAP_SID_NAME_USERS,
  2783. &SidName,
  2784. 0,
  2785. NULL
  2786. ); ASSERT(NT_SUCCESS(Status));
  2787. //
  2788. // Check if all Sids initialized.
  2789. //
  2790. #ifdef LSAP_DEBUG_MESSAGE_STRINGS
  2791. DbgPrint("\nLSA (dbinit): Displaying all well known sids...\n\n");
  2792. #endif //LSAP_DEBUG_MESSAGE_STRINGS
  2793. for (WellKnownSidIndex = LsapNullSidIndex;
  2794. WellKnownSidIndex < LsapDummyLastSidIndex;
  2795. WellKnownSidIndex++) {
  2796. #ifdef LSAP_DEBUG_MESSAGE_STRINGS
  2797. DbgPrint(" *%wZ* : *%wZ*\n",
  2798. &OutputWellKnownSids[WellKnownSidIndex].DomainName,
  2799. &OutputWellKnownSids[WellKnownSidIndex].Name);
  2800. #endif //LSAP_DEBUG_MESSAGE_STRINGS
  2801. if (OutputWellKnownSids[WellKnownSidIndex].Sid == NULL) {
  2802. #if DBG
  2803. DbgPrint(
  2804. "Well Known Sid Index %d not initialized\n",
  2805. WellKnownSidIndex
  2806. );
  2807. #endif //DBG
  2808. }
  2809. }
  2810. *WellKnownSids = OutputWellKnownSids;
  2811. return(TRUE);
  2812. InitializeWellKnownSidsError:
  2813. return(FALSE);
  2814. }
  2815. BOOLEAN
  2816. LsapDbInitializeWellKnownSid(
  2817. OUT PLSAP_WELL_KNOWN_SID_ENTRY WellKnownSids,
  2818. IN LSAP_WELL_KNOWN_SID_INDEX WellKnownSidIndex,
  2819. IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
  2820. IN UCHAR SubAuthorityCount,
  2821. IN PULONG SubAuthorities,
  2822. IN PWSTR Name,
  2823. IN PWSTR DomainName,
  2824. IN SID_NAME_USE Use
  2825. )
  2826. /*++
  2827. Routine Description:
  2828. This function initializes an entry in the specified well-known Sid table.
  2829. The entry contains the well known Sid and its name.
  2830. Arguments:
  2831. WellKnownSids - Pointer to the first entry in the Well Known Sid table.
  2832. WellKnownSidIndex - Index into table of Well Known Sids.
  2833. Sid - Receives a pointer to a Sid with the correct size for the
  2834. number of subauthorities specified.
  2835. IdentifierAuthority - Pointer to Identifier authority.
  2836. SubAuthorityCount - Count of SubAuthorities
  2837. SubAuthorities - Array of SubAuthorities.
  2838. Name - Pointer to Unicode Name buffer containing the Sid's Name
  2839. DomainName - Pointer to Unicode Name buffer containing the
  2840. Sids Domain Name (if any) or descriptive text, such as
  2841. "Well Known Group" for Sids of Well Known Groups
  2842. SidNameUse - Specifies code for Sid's Use. The following values
  2843. may be specified:
  2844. SidTypeUser
  2845. SidTypeGroup
  2846. SidTypeDomain
  2847. SidTypeAlias
  2848. SidTypeWellKnownGroup
  2849. SidTypeDeletedAccount
  2850. SidTypeInvalid
  2851. SidTypeUnknown
  2852. Return Value:
  2853. BOOLEAN - TRUE if Sid initialized, else FALSE.
  2854. --*/
  2855. {
  2856. PLSAP_WELL_KNOWN_SID_ENTRY
  2857. WellKnownSidEntry = &WellKnownSids[WellKnownSidIndex];
  2858. PSID OutputSid = NULL;
  2859. OutputSid = RtlAllocateHeap(
  2860. RtlProcessHeap(),
  2861. 0,
  2862. RtlLengthRequiredSid(SubAuthorityCount)
  2863. );
  2864. if (OutputSid == NULL) {
  2865. goto InitializeWellKnownSidError;
  2866. }
  2867. RtlInitializeSid( OutputSid, IdentifierAuthority, SubAuthorityCount);
  2868. if (SubAuthorityCount != 0) {
  2869. RtlCopyMemory(
  2870. RtlSubAuthoritySid( OutputSid, 0 ),
  2871. SubAuthorities,
  2872. SubAuthorityCount * sizeof(ULONG)
  2873. );
  2874. }
  2875. WellKnownSidEntry->Sid = OutputSid;
  2876. //
  2877. // Fill in the Domain Name
  2878. //
  2879. RtlInitUnicodeString(
  2880. &WellKnownSidEntry->DomainName,
  2881. DomainName
  2882. );
  2883. //
  2884. // Fill in the Use and Name.
  2885. //
  2886. WellKnownSidEntry->Use = Use;
  2887. RtlInitUnicodeString(
  2888. &WellKnownSidEntry->Name,
  2889. Name
  2890. );
  2891. return(TRUE);
  2892. InitializeWellKnownSidError:
  2893. #if DBG
  2894. DbgPrint("LSA Initialization of Well Known Sids Failed\n");
  2895. DbgPrint("Insufficient memory resources\n");
  2896. #endif // DBG
  2897. return(FALSE);
  2898. }
  2899. NTSTATUS
  2900. LsapGetMessageStrings(
  2901. LPVOID Resource,
  2902. DWORD Index1,
  2903. PUNICODE_STRING String1,
  2904. DWORD Index2,
  2905. PUNICODE_STRING String2 OPTIONAL
  2906. )
  2907. /*++
  2908. Routine Description:
  2909. This gets 1 or 2 message strings values from a resource message table.
  2910. The string buffers are allocated and the strings initialized properly.
  2911. The strings will be NULL terminated.
  2912. The string buffers must be freed using LocalFree() when no longer needed.
  2913. Arguments:
  2914. Resource - points to the resource table.
  2915. Index1 - Index of first message to retrieve.
  2916. String1 - Points to a UNICODE_STRING structure to receive the first
  2917. message string. The string will be null terminated.
  2918. Index2 - Index of second message to retrieve.
  2919. String2 - Points to a UNICODE_STRING structure to receive the first
  2920. message string. If this parameter is NULL, then only one message
  2921. string is retrieved. The string will be null terminated.
  2922. Return Value:
  2923. None.
  2924. --*/
  2925. {
  2926. #ifdef LSAP_DEBUG_MESSAGE_STRINGS
  2927. DbgPrint("LSA (dbinit): String 1 -\n");
  2928. DbgPrint(" Index: 0x%lx\n", Index1);
  2929. #endif //LSAP_DEBUG_MESSAGE_STRINGS
  2930. String1->Buffer = NULL;
  2931. String1->MaximumLength = (USHORT) FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
  2932. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  2933. Resource,
  2934. Index1,
  2935. 0, // Use caller's language
  2936. (LPWSTR)&(String1->Buffer),
  2937. 0,
  2938. NULL
  2939. );
  2940. if (String1->Buffer == NULL) {
  2941. return(STATUS_RESOURCE_DATA_NOT_FOUND);
  2942. } else {
  2943. //
  2944. // Note that we are retrieving a message from a message file.
  2945. // This message will have a cr/lf tacked on the end of it
  2946. // (0x0d 0x0a) that we don't want to be part of our returned
  2947. // strings. However, we do need to null terminate our string
  2948. // so we will convert the 0x0d into a null terminator.
  2949. //
  2950. // Also note that FormatMessage() returns a character count,
  2951. // not a byte count. So, we have to do some adjusting to make
  2952. // the string lengths correct.
  2953. //
  2954. ASSERT(String1->MaximumLength >= 2); // We always expect cr/lf on our strings
  2955. //
  2956. // Adjust character count
  2957. //
  2958. String1->MaximumLength -= 1; // For the lf - we'll convert the cr.
  2959. //
  2960. // Set null terminator
  2961. //
  2962. String1->Buffer[String1->MaximumLength - 1] = 0;
  2963. //
  2964. // Change lengths to byte count instead of character count
  2965. //
  2966. String1->MaximumLength *= sizeof(WCHAR); // to make it a byte count
  2967. String1->Length = String1->MaximumLength - sizeof(WCHAR);
  2968. #ifdef LSAP_DEBUG_MESSAGE_STRINGS
  2969. DbgPrint(" String: %wZ\n", String1);
  2970. DbgPrint(" Max: (0x%lx)\n", String1->MaximumLength);
  2971. DbgPrint(" Cur: (0x%lx)\n", String1->Length);
  2972. DbgPrint(" ");
  2973. {
  2974. ULONG i;
  2975. for (i=0; i<String1->MaximumLength; i++) {
  2976. DbgPrint("%2x ", (*((PUCHAR)String1->Buffer)+i));
  2977. }
  2978. DbgPrint("\n");
  2979. }
  2980. #endif //LSAP_DEBUG_MESSAGE_STRINGS
  2981. }
  2982. if (!ARGUMENT_PRESENT(String2)) {
  2983. return(STATUS_SUCCESS);
  2984. }
  2985. String2->Buffer = NULL;
  2986. String2->MaximumLength = (USHORT) FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
  2987. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  2988. Resource,
  2989. Index2,
  2990. 0, // Use caller's language
  2991. (LPWSTR)&(String2->Buffer),
  2992. 0,
  2993. NULL
  2994. );
  2995. if (String2->Buffer == NULL) {
  2996. LocalFree( String1->Buffer );
  2997. return(STATUS_RESOURCE_DATA_NOT_FOUND);
  2998. } else {
  2999. //
  3000. // Note that we are retrieving a message from a message file.
  3001. // This message will have a cr/lf tacked on the end of it
  3002. // (0x0d 0x0a) that we don't want to be part of our returned
  3003. // strings. However, we do need to null terminate our string
  3004. // so we will convert the 0x0d into a null terminator.
  3005. //
  3006. // Also note that FormatMessage() returns a character count,
  3007. // not a byte count. So, we have to do some adjusting to make
  3008. // the string lengths correct.
  3009. //
  3010. ASSERT(String2->MaximumLength >= 2); // We always expect cr/lf on our strings
  3011. //
  3012. // Adjust character count
  3013. //
  3014. String2->MaximumLength -= 1; // For the lf - we'll convert the cr.
  3015. //
  3016. // Set null terminator
  3017. //
  3018. String2->Buffer[String2->MaximumLength - 1] = 0;
  3019. //
  3020. // Change lengths to byte count instead of character count
  3021. //
  3022. String2->MaximumLength *= sizeof(WCHAR); // to make it a byte count
  3023. String2->Length = String2->MaximumLength - sizeof(WCHAR);
  3024. #ifdef LSAP_DEBUG_MESSAGE_STRINGS
  3025. DbgPrint(" String: %wZ\n", String2);
  3026. DbgPrint(" Max: (0x%lx)\n", String2->MaximumLength);
  3027. DbgPrint(" Cur: (0x%lx)\n", String2->Length);
  3028. DbgPrint(" ");
  3029. {
  3030. ULONG i;
  3031. for (i=0; i<String2->MaximumLength; i++) {
  3032. DbgPrint("%2x ", (*((PUCHAR)String2->Buffer)+i));
  3033. }
  3034. DbgPrint("\n");
  3035. }
  3036. #endif //LSAP_DEBUG_MESSAGE_STRINGS
  3037. }
  3038. return(STATUS_SUCCESS);
  3039. }
  3040. #if defined(REMOTE_BOOT)
  3041. VOID
  3042. LsapDbInitializeRemoteBootState(
  3043. )
  3044. /*++
  3045. Routine Description:
  3046. This function initializes the remote boot state used by LSA.
  3047. Arguments:
  3048. None.
  3049. Return Value:
  3050. NTSTATUS - Standard Nt Result Code
  3051. All Result Codes are generated by called routines.
  3052. --*/
  3053. {
  3054. NTSTATUS Status ;
  3055. HANDLE RdrDevice ;
  3056. UNICODE_STRING String ;
  3057. OBJECT_ATTRIBUTES ObjA ;
  3058. IO_STATUS_BLOCK IoStatus ;
  3059. //
  3060. // This is the default if anything goes wrong.
  3061. //
  3062. LsapDbState.RemoteBootState = LSAP_DB_REMOTE_BOOT_NO_NOTIFICATION;
  3063. //
  3064. // Open the redirector device.
  3065. //
  3066. RtlInitUnicodeString( &String, DD_NFS_DEVICE_NAME_U );
  3067. InitializeObjectAttributes( &ObjA,
  3068. &String,
  3069. 0,
  3070. 0,
  3071. 0);
  3072. Status = NtOpenFile( &RdrDevice,
  3073. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  3074. &ObjA,
  3075. &IoStatus,
  3076. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3077. 0 );
  3078. if ( !NT_SUCCESS( Status ) )
  3079. {
  3080. DebugLog(( DEB_TRACE, "FAILED to open %ws, status %x\n",
  3081. String.Buffer, Status ));
  3082. return;
  3083. }
  3084. Status = NtFsControlFile(
  3085. RdrDevice,
  3086. NULL,
  3087. NULL,
  3088. NULL,
  3089. &IoStatus,
  3090. FSCTL_LMMR_RI_IS_PASSWORD_SETTABLE,
  3091. NULL,
  3092. 0,
  3093. NULL,
  3094. 0 );
  3095. if ( Status == STATUS_SUCCESS )
  3096. {
  3097. LsapDbState.RemoteBootState = LSAP_DB_REMOTE_BOOT_NOTIFY;
  3098. }
  3099. else if ( Status == STATUS_UNSUCCESSFUL )
  3100. {
  3101. LsapDbState.RemoteBootState = LSAP_DB_REMOTE_BOOT_CANT_NOTIFY;
  3102. }
  3103. NtClose(RdrDevice);
  3104. }
  3105. #endif // defined(REMOTE_BOOT)
  3106. NTSTATUS
  3107. LsapGenerateRandomDomainSid(
  3108. OUT PSID NewDomainSid
  3109. )
  3110. /*++
  3111. Routine Description:
  3112. This function will generate a random sid to be used for the new account domain sid during
  3113. setup.
  3114. Arguments:
  3115. NewDomainSid - Where the new domain sid is returned. Freed via RtlFreeSid()
  3116. Return Values:
  3117. STATUS_SUCCESS -- Success.
  3118. STATUS_INSUFFICIENT_RESOURCES -- A memory allocation failed
  3119. --*/
  3120. {
  3121. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  3122. ULONG SubAuth1, SubAuth2, SubAuth3;
  3123. SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY;
  3124. if(!RtlGenRandom( &SubAuth1, sizeof(SubAuth1) ))
  3125. {
  3126. ASSERT( NT_SUCCESS(Status) );
  3127. return Status;
  3128. }
  3129. if(!RtlGenRandom( &SubAuth2, sizeof(SubAuth2) ))
  3130. {
  3131. ASSERT( NT_SUCCESS(Status) );
  3132. return Status;
  3133. }
  3134. if(!RtlGenRandom( &SubAuth3, sizeof(SubAuth3) ))
  3135. {
  3136. ASSERT( NT_SUCCESS(Status) );
  3137. return Status;
  3138. }
  3139. Status = RtlAllocateAndInitializeSid( &IdentifierAuthority,
  3140. 4,
  3141. 0x15,
  3142. SubAuth1,
  3143. SubAuth2,
  3144. SubAuth3,
  3145. 0,
  3146. 0,
  3147. 0,
  3148. 0,
  3149. NewDomainSid );
  3150. return( Status );
  3151. }
  3152. NTSTATUS
  3153. LsapSetupInitialize(
  3154. VOID
  3155. )
  3156. /*++
  3157. Routine Description:
  3158. This function will generate a random sid to be used for the new account domain sid during
  3159. setup.
  3160. Arguments:
  3161. NewDomainSid - Where the new domain sid is returned. Freed via RtlFreeSid()
  3162. Return Values:
  3163. STATUS_SUCCESS -- Success.
  3164. STATUS_INSUFFICIENT_RESOURCES -- A memory allocation failed
  3165. --*/
  3166. {
  3167. NTSTATUS Status = STATUS_SUCCESS;
  3168. PSID NewDomainSid = NULL;
  3169. HMODULE StringsResource;
  3170. LSAPR_POLICY_ACCOUNT_DOM_INFO AccountDomainInfo;
  3171. Status = LsapGenerateRandomDomainSid( &NewDomainSid );
  3172. if ( NT_SUCCESS( Status ) ) {
  3173. //
  3174. // We can use GetModuleHandle, since we are getting it on ourselves.
  3175. //
  3176. StringsResource = (HMODULE) GetModuleHandle( L"LSASRV.DLL" );
  3177. ASSERT( StringsResource );
  3178. Status = LsapGetMessageStrings( StringsResource,
  3179. LSAP_DEFAULT_DOMAIN_NAME,
  3180. ( PUNICODE_STRING )&AccountDomainInfo.DomainName,
  3181. 0,
  3182. NULL );
  3183. }
  3184. //
  3185. // Ok, if we got this far, then we can initialize the account domain
  3186. //
  3187. if ( NT_SUCCESS( Status ) ) {
  3188. AccountDomainInfo.DomainSid = NewDomainSid;
  3189. Status = LsarSetInformationPolicy( LsapPolicyHandle,
  3190. PolicyAccountDomainInformation,
  3191. ( PLSAPR_POLICY_INFORMATION )&AccountDomainInfo );
  3192. LocalFree( AccountDomainInfo.DomainName.Buffer );
  3193. }
  3194. if ( NewDomainSid ) {
  3195. RtlFreeSid( NewDomainSid );
  3196. }
  3197. return( Status );
  3198. }
  3199. static GUID LsapDbPasswordAuthenticator = {0xf0ce3a80,0x155f,0x11d3,0xb7,0xe6,0x00,0x80,0x5f,0x48,0xca,0xeb};
  3200. NTSTATUS
  3201. LsapDbGenerateNewKey(
  3202. IN LSAP_DB_ENCRYPTION_KEY * NewEncryptionKey
  3203. )
  3204. /*++
  3205. Routine Description
  3206. This routine generates a new Encryption key that can be used for
  3207. encrypting secrets.
  3208. Parameters
  3209. NewEncryptionKey -- Pointer to a structure that contains the new key
  3210. Return Values
  3211. STATUS_SUCCESS
  3212. STATUS_UNSUCCESSFUL
  3213. --*/
  3214. {
  3215. NTSTATUS Status = STATUS_SUCCESS;
  3216. //
  3217. // generate a random number for the key
  3218. //
  3219. if (!RtlGenRandom(NewEncryptionKey->Key,sizeof(NewEncryptionKey->Key)))
  3220. {
  3221. return(STATUS_UNSUCCESSFUL);
  3222. }
  3223. //
  3224. // Copy in the GUID for the authenticator
  3225. //
  3226. NewEncryptionKey->Authenticator = LsapDbPasswordAuthenticator;
  3227. //
  3228. // Set the version #
  3229. //
  3230. NewEncryptionKey->Revision = LSAP_DB_ENCRYPTION_KEY_VERSION ;
  3231. NewEncryptionKey->Flags = 0;
  3232. //
  3233. // Generate a Salt
  3234. //
  3235. if (!RtlGenRandom(NewEncryptionKey->Salt,sizeof(NewEncryptionKey->Salt)))
  3236. {
  3237. return(STATUS_UNSUCCESSFUL);
  3238. }
  3239. //
  3240. // Generate a random value for the old syskey
  3241. //
  3242. if (!RtlGenRandom(NewEncryptionKey->OldSyskey,sizeof(NewEncryptionKey->OldSyskey)))
  3243. {
  3244. return(STATUS_UNSUCCESSFUL);
  3245. }
  3246. //
  3247. // Set the boot type
  3248. //
  3249. NewEncryptionKey->BootType = WxStored;
  3250. return(STATUS_SUCCESS);
  3251. }
  3252. VOID
  3253. LsapDbEncryptKeyWithSyskey(
  3254. OUT LSAP_DB_ENCRYPTION_KEY * KeyToEncrypt,
  3255. IN PVOID Syskey,
  3256. IN ULONG SyskeyLength
  3257. )
  3258. /*++
  3259. This routine encrypts the KeyToEncrypt parameter with
  3260. the syskey passed in
  3261. Arguments
  3262. KeyToEncrypt -- the key to encrypt
  3263. Syskey -- The syskey passed in
  3264. SyskeyLength -- The length of the syskey
  3265. Return Values
  3266. None, void function
  3267. --*/
  3268. {
  3269. MD5_CTX Md5Context;
  3270. struct RC4_KEYSTRUCT Rc4Key;
  3271. ULONG i;
  3272. //
  3273. // Create an MD5 hash of the key and salt
  3274. //
  3275. MD5Init(&Md5Context);
  3276. MD5Update(
  3277. &Md5Context,
  3278. Syskey,
  3279. SyskeyLength
  3280. );
  3281. //
  3282. // Hash in the salt many many times. This slows down
  3283. // attackers employing a brute force approach to attack
  3284. //
  3285. for (i=0;i<1000;i++)
  3286. {
  3287. MD5Update(
  3288. &Md5Context,
  3289. KeyToEncrypt->Salt,
  3290. sizeof(KeyToEncrypt->Salt)
  3291. );
  3292. }
  3293. MD5Final(
  3294. &Md5Context
  3295. );
  3296. //
  3297. // Initialize the RC4 key sequence.
  3298. //
  3299. rc4_key(
  3300. &Rc4Key,
  3301. MD5DIGESTLEN,
  3302. Md5Context.digest
  3303. );
  3304. rc4(
  3305. &Rc4Key,
  3306. sizeof(KeyToEncrypt->Key)+ sizeof(KeyToEncrypt->Authenticator)+sizeof(KeyToEncrypt->OldSyskey),
  3307. (PUCHAR) &KeyToEncrypt->Authenticator
  3308. );
  3309. }
  3310. NTSTATUS
  3311. LsapDbDecryptKeyWithSyskey(
  3312. IN LSAP_DB_ENCRYPTION_KEY * KeyToDecrypt,
  3313. IN PVOID Syskey,
  3314. IN ULONG SyskeyLength
  3315. )
  3316. /*++
  3317. This function provides a decryption using the syskey. Since RC4 is symmetric
  3318. encryption algorithm, this function simply calls the previous encrypt routine
  3319. Arguments
  3320. KeyToDecrypt -- the key to dencrypt
  3321. Syskey -- The syskey passed in
  3322. SyskeyLength -- The length of the syskey
  3323. Return Values
  3324. STATUS_SUCCESS , on successful decryption
  3325. STATUS_WRONG_PASSWORD on unsuccessful decryption
  3326. --*/
  3327. {
  3328. LsapDbEncryptKeyWithSyskey(KeyToDecrypt,Syskey,SyskeyLength);
  3329. if (!RtlEqualMemory(&KeyToDecrypt->Authenticator,&LsapDbPasswordAuthenticator,sizeof(GUID)))
  3330. {
  3331. return(STATUS_WRONG_PASSWORD);
  3332. }
  3333. return(STATUS_SUCCESS);
  3334. }
  3335. NTSTATUS
  3336. LsapDbSetupInitialSyskey(
  3337. OUT PULONG SyskeyLength,
  3338. OUT PVOID *Syskey
  3339. )
  3340. /*++
  3341. This generates a new syskey and changes the winlogon state such that
  3342. winlogon recognizes the new syskey and the boot option of system saves
  3343. syskey.
  3344. Arguments
  3345. SyskeyLength -- The length of the syskey is returned in here
  3346. Syskey -- The syskey itself is returned in here
  3347. Return Values
  3348. STATUS_SUCCESS
  3349. Other resource error codes
  3350. --*/
  3351. {
  3352. NTSTATUS NtStatus = STATUS_SUCCESS;
  3353. *Syskey = LsapAllocateLsaHeap(LSAP_SYSKEY_SIZE );
  3354. if (NULL==*Syskey)
  3355. {
  3356. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  3357. goto Error;
  3358. }
  3359. *SyskeyLength = LSAP_SYSKEY_SIZE;
  3360. //
  3361. // Generate the syskey
  3362. //
  3363. if (!RtlGenRandom( *Syskey, *SyskeyLength))
  3364. {
  3365. NtStatus = STATUS_UNSUCCESSFUL;
  3366. goto Error;
  3367. }
  3368. //
  3369. // Save the syskey in the registry
  3370. // If this operation fails, then no state is changed, machine remains
  3371. // un syskey-d till next boot
  3372. //
  3373. NtStatus = WxSaveSysKey(*SyskeyLength, *Syskey);
  3374. if (!NT_SUCCESS(NtStatus))
  3375. {
  3376. goto Error;
  3377. }
  3378. //
  3379. // Set the boot option in the registry
  3380. // If this operation fails, still no problem. Machine remains unsyskey'd
  3381. // and the boot key that has been saved will be reset on next boot.
  3382. //
  3383. NtStatus = WxSaveBootOption(WxStored);
  3384. if (!NT_SUCCESS(NtStatus))
  3385. {
  3386. goto Error;
  3387. }
  3388. Error:
  3389. if (!NT_SUCCESS(NtStatus))
  3390. {
  3391. *SyskeyLength = 0;
  3392. if (NULL!=*Syskey)
  3393. {
  3394. MIDL_user_free(*Syskey);
  3395. }
  3396. }
  3397. return(NtStatus);
  3398. }
  3399. NTSTATUS
  3400. LsapDbGetSyskeyFromWinlogon()
  3401. /*++
  3402. Routine Description
  3403. This routine obtains the syskey from winlogon and decrypts the
  3404. Password encryption key in the LSA policy database. The global variable
  3405. LsapDbSecretCipherKey is set with the password encryption key and the
  3406. the global variable LsapDbSyskey is set with the syskey. This value is
  3407. then queried by SAM/DS to decrypt their respective password encryption keys
  3408. and then cleared before the end of SamIInitialize.
  3409. The special case handled inside this routine is of the case of a fresh install.
  3410. In this particular case winlogon is not yet setup to expect a query of syskey
  3411. from the lsass process. However since the LSA install code has been called just
  3412. moments, before, that code sets the winlogon state and also fills the global
  3413. LsapDbSyskey. Therefore if LsapDbSyskey is not NULL then this would be the
  3414. fresh install case.
  3415. Arguments
  3416. None
  3417. Return Values
  3418. STATUS_SUCCESS
  3419. STATUS_UNSUCCESSFUL
  3420. --*/
  3421. {
  3422. NTSTATUS Status = STATUS_SUCCESS;
  3423. NTSTATUS DecryptStatus = STATUS_SUCCESS;
  3424. ULONG DecryptionKeyLength = 0;
  3425. HANDLE WinlogonHandle=NULL;
  3426. ULONG Tries = 0;
  3427. LSAP_DB_ENCRYPTION_KEY StoredEncryptionKeyData;
  3428. ULONG StoredEncryptionKeyDataLength = sizeof( LSAP_DB_ENCRYPTION_KEY );
  3429. ULONG SyskeyLen=LSAP_SYSKEY_SIZE;
  3430. BOOLEAN FreshInstall=FALSE;
  3431. //
  3432. // Read the attribute information in the LSA policy database
  3433. //
  3434. Status = LsapDbReadAttributeObject(
  3435. LsapDbHandle,
  3436. &LsapDbNames[PolSecretEncryptionKey],
  3437. (PVOID) &StoredEncryptionKeyData,
  3438. &StoredEncryptionKeyDataLength
  3439. );
  3440. if ( !NT_SUCCESS(Status) ) {
  3441. goto Cleanup;
  3442. }
  3443. if (NULL!=LsapDbSysKey)
  3444. {
  3445. //
  3446. // In the fresh install case , code in dbinstal.c already
  3447. // sets LsapDbSyskey to the syskey value.
  3448. //
  3449. FreshInstall = TRUE;
  3450. Status = LsapDbDecryptKeyWithSyskey(
  3451. &StoredEncryptionKeyData ,
  3452. LsapDbSysKey,
  3453. LSAP_SYSKEY_SIZE
  3454. );
  3455. }
  3456. else
  3457. {
  3458. //
  3459. // because LsapDbDecryptKeyWithSyskey() is an in-place
  3460. // operation, so we'd better save the Encrypted Syskey first
  3461. //
  3462. LSAP_DB_ENCRYPTION_KEY TempStoredEncryptionKeyData;
  3463. TempStoredEncryptionKeyData = StoredEncryptionKeyData;
  3464. //
  3465. // Call Winlogon to obtain the key information.
  3466. //
  3467. Status = WxConnect(
  3468. &WinlogonHandle
  3469. );
  3470. if (!NT_SUCCESS(Status))
  3471. {
  3472. //
  3473. // Winlogon may fail if secret encryption is not enabled. In those
  3474. // cases continue. Else Fail the boot
  3475. //
  3476. if (WxNone==StoredEncryptionKeyData.BootType)
  3477. {
  3478. Status = STATUS_SUCCESS;
  3479. }
  3480. goto Cleanup;
  3481. }
  3482. for (Tries = 0; Tries < LSAP_BOOT_KEY_RETRY_COUNT ; Tries++ )
  3483. {
  3484. //
  3485. // restore the data which need to be decrypted.
  3486. //
  3487. StoredEncryptionKeyData = TempStoredEncryptionKeyData;
  3488. //
  3489. // Retry this RETRY_COUNT_TIMES, this allows the user a chance
  3490. // to correct himself, in case he entered a wrong boot password
  3491. //
  3492. if (WxNone!=StoredEncryptionKeyData.BootType)
  3493. {
  3494. //
  3495. // Get the key to be used to decrypt the PEK list
  3496. //
  3497. Status = WxGetKeyData(
  3498. WinlogonHandle,
  3499. StoredEncryptionKeyData.BootType,
  3500. LSAP_SYSKEY_SIZE,
  3501. SyskeyBuffer,
  3502. &SyskeyLen
  3503. );
  3504. if (!NT_SUCCESS(Status)) {
  3505. goto Cleanup;
  3506. }
  3507. ASSERT(SyskeyLen==LSAP_SYSKEY_SIZE);
  3508. //
  3509. // Decrypt the Blob passed in with the key supplied by winlogon
  3510. //
  3511. Status = LsapDbDecryptKeyWithSyskey(
  3512. &StoredEncryptionKeyData ,
  3513. SyskeyBuffer,
  3514. LSAP_SYSKEY_SIZE
  3515. );
  3516. if (!NT_SUCCESS(Status))
  3517. {
  3518. DecryptStatus = STATUS_WRONG_PASSWORD;
  3519. }
  3520. else
  3521. {
  3522. //
  3523. // We successfully decrypted, break out of the loop
  3524. //
  3525. DecryptStatus = STATUS_SUCCESS;
  3526. break;
  3527. }
  3528. }
  3529. else
  3530. {
  3531. break;
  3532. }
  3533. }
  3534. //
  3535. // Tell winlogon regarding success or failure of the scheme
  3536. //
  3537. Status = WxReportResults(
  3538. WinlogonHandle,
  3539. DecryptStatus
  3540. );
  3541. if (!NT_SUCCESS(Status)) {
  3542. goto Cleanup;
  3543. }
  3544. Status = DecryptStatus;
  3545. }
  3546. if (NT_SUCCESS(Status))
  3547. {
  3548. //
  3549. // Initialize the new secret cipher key
  3550. // The keys used for reading and writing secrets are ordinarily the same
  3551. //
  3552. LsapDbInitializeSecretCipherKeyRead( &StoredEncryptionKeyData );
  3553. LsapDbInitializeSecretCipherKeyWrite( &StoredEncryptionKeyData );
  3554. if (!FreshInstall)
  3555. {
  3556. //
  3557. // Set the global variable LsapDBSysKey
  3558. //
  3559. LsapDbSysKey = SyskeyBuffer;
  3560. //
  3561. // Set up the old syskey for recovery cases
  3562. // by SAM and LSA
  3563. //
  3564. RtlCopyMemory(
  3565. OldSyskeyBuffer,
  3566. StoredEncryptionKeyData.OldSyskey,
  3567. sizeof(StoredEncryptionKeyData.OldSyskey)
  3568. );
  3569. LsapDbOldSysKey = OldSyskeyBuffer;
  3570. }
  3571. }
  3572. Cleanup:
  3573. if (WinlogonHandle != NULL) {
  3574. NtClose(WinlogonHandle);
  3575. }
  3576. return(Status);
  3577. }
  3578. VOID
  3579. LsapDbInitializeSecretCipherKeyRead(
  3580. PLSAP_DB_ENCRYPTION_KEY PassedInEncryptionKeyData
  3581. )
  3582. /*++
  3583. Routine Description
  3584. Given a pointer to the encryption key ( as in the struct ), this routine
  3585. initializes a CipherKey structure that can be used by the LSA's secret encryption
  3586. and decryption routines.
  3587. Arguments
  3588. PassedInEncryptionKeyData -- The struct representing the key
  3589. Return Values
  3590. Void function
  3591. --*/
  3592. {
  3593. static LSAP_DB_ENCRYPTION_KEY StaticEncryptionKeyData;
  3594. static LSAP_CR_CIPHER_KEY DecryptedSecretCipherKey;
  3595. RtlCopyMemory(&StaticEncryptionKeyData,PassedInEncryptionKeyData,sizeof(LSAP_DB_ENCRYPTION_KEY));
  3596. DecryptedSecretCipherKey.Buffer = StaticEncryptionKeyData.Key;
  3597. DecryptedSecretCipherKey.Length = DecryptedSecretCipherKey.MaximumLength
  3598. = sizeof(StaticEncryptionKeyData.Key);
  3599. LsapDbSecretCipherKeyRead = &DecryptedSecretCipherKey;
  3600. }
  3601. VOID
  3602. LsapDbInitializeSecretCipherKeyWrite(
  3603. PLSAP_DB_ENCRYPTION_KEY PassedInEncryptionKeyData
  3604. )
  3605. /*++
  3606. Routine Description
  3607. Given a pointer to the encryption key ( as in the struct ), this routine
  3608. initializes a CipherKey structure that can be used by the LSA's secret encryption
  3609. and decryption routines.
  3610. Arguments
  3611. PassedInEncryptionKeyData -- The struct representing the key
  3612. CipherKey -- The structure that needs to be initialzed with the
  3613. key for LSA's secret encryption
  3614. Return Values
  3615. Void function
  3616. --*/
  3617. {
  3618. static LSAP_DB_ENCRYPTION_KEY StaticEncryptionKeyData;
  3619. static LSAP_CR_CIPHER_KEY DecryptedSecretCipherKey;
  3620. RtlCopyMemory(&StaticEncryptionKeyData,PassedInEncryptionKeyData,sizeof(LSAP_DB_ENCRYPTION_KEY));
  3621. DecryptedSecretCipherKey.Buffer = StaticEncryptionKeyData.Key;
  3622. DecryptedSecretCipherKey.Length = DecryptedSecretCipherKey.MaximumLength
  3623. = sizeof(StaticEncryptionKeyData.Key);
  3624. LsapDbSecretCipherKeyWrite = &DecryptedSecretCipherKey;
  3625. }
  3626. VOID
  3627. LsapDbSetSyskey(
  3628. PVOID Syskey,
  3629. ULONG SyskeyLength
  3630. )
  3631. /*++
  3632. This function sets the syskey in the global syskey buffer
  3633. --*/
  3634. {
  3635. ASSERT(LSAP_SYSKEY_SIZE==SyskeyLength);
  3636. RtlCopyMemory(SyskeyBuffer,Syskey,SyskeyLength);
  3637. LsapDbSysKey = SyskeyBuffer;
  3638. }
  3639. NTSTATUS
  3640. LsaISetBootOption(
  3641. IN ULONG BootOption,
  3642. IN PVOID OldKey,
  3643. IN ULONG OldKeyLength,
  3644. IN PVOID NewKey,
  3645. IN ULONG NewKeyLength
  3646. )
  3647. /*++
  3648. This function is used to change the syskey value in the LSA, or change
  3649. the boot option type.
  3650. Arguments
  3651. BootOption -- New Boot Option
  3652. OldKey -- Old key, used to verify value
  3653. OldKeyLength -- Length of old key
  3654. NewKey -- New key, LSA's password encryption key is encrypted using
  3655. this value
  3656. NewKeyLength -- Length of new key
  3657. Return Values
  3658. --*/
  3659. {
  3660. NTSTATUS Status = STATUS_SUCCESS;
  3661. ULONG StoredEncryptionKeyDataLength = sizeof( LSAP_DB_ENCRYPTION_KEY );
  3662. LSAP_DB_ENCRYPTION_KEY StoredEncryptionKeyData;
  3663. ULONG SyskeyLen=0;
  3664. LSAP_DB_ATTRIBUTE Attributes[20];
  3665. PLSAP_DB_ATTRIBUTE NextAttribute;
  3666. ULONG AttributeCount = 0;
  3667. NextAttribute = Attributes;
  3668. //
  3669. // Validate Some parameters
  3670. //
  3671. if ((NewKeyLength != LSAP_SYSKEY_SIZE ) || (OldKeyLength != LSAP_SYSKEY_SIZE))
  3672. {
  3673. return (STATUS_INVALID_PARAMETER);
  3674. }
  3675. if ((NULL==NewKey) || (NULL==OldKey))
  3676. {
  3677. return(STATUS_INVALID_PARAMETER);
  3678. }
  3679. //
  3680. // Read the attribute information in the LSA policy database
  3681. //
  3682. Status = LsapDbReadAttributeObject(
  3683. LsapDbHandle,
  3684. &LsapDbNames[PolSecretEncryptionKey],
  3685. (PVOID) &StoredEncryptionKeyData,
  3686. &StoredEncryptionKeyDataLength
  3687. );
  3688. if (!NT_SUCCESS(Status) ) {
  3689. goto Cleanup;
  3690. }
  3691. //
  3692. // Decrypt the data
  3693. //
  3694. Status = LsapDbDecryptKeyWithSyskey(
  3695. &StoredEncryptionKeyData,
  3696. OldKey,
  3697. OldKeyLength
  3698. );
  3699. if (!NT_SUCCESS(Status))
  3700. {
  3701. goto Cleanup;
  3702. }
  3703. //
  3704. // Change the boot option
  3705. //
  3706. StoredEncryptionKeyData.BootType = BootOption;
  3707. //
  3708. // Save the old key ( for recovery )
  3709. //
  3710. ASSERT(sizeof(StoredEncryptionKeyData.OldSyskey) == OldKeyLength);
  3711. RtlCopyMemory(
  3712. &StoredEncryptionKeyData.OldSyskey,
  3713. OldKey,
  3714. OldKeyLength
  3715. );
  3716. //
  3717. // Re-encrypt the data using the new key
  3718. //
  3719. LsapDbEncryptKeyWithSyskey(
  3720. &StoredEncryptionKeyData,
  3721. NewKey,
  3722. NewKeyLength
  3723. );
  3724. LsapDbInitializeAttribute(
  3725. NextAttribute,
  3726. &LsapDbNames[PolSecretEncryptionKey],
  3727. &StoredEncryptionKeyData,
  3728. sizeof (StoredEncryptionKeyData),
  3729. FALSE
  3730. );
  3731. NextAttribute++;
  3732. AttributeCount++;
  3733. //
  3734. // Now write out all attributes that have been added (if any)
  3735. //
  3736. if (AttributeCount > 0) {
  3737. Status = LsapDbReferenceObject(
  3738. LsapDbHandle,
  3739. 0,
  3740. PolicyObject,
  3741. PolicyObject,
  3742. LSAP_DB_LOCK | LSAP_DB_START_TRANSACTION
  3743. );
  3744. if (NT_SUCCESS(Status)) {
  3745. ASSERT( AttributeCount < ( sizeof( Attributes ) / sizeof( LSAP_DB_ATTRIBUTE ) ) );
  3746. Status = LsapDbWriteAttributesObject(
  3747. LsapDbHandle,
  3748. Attributes,
  3749. AttributeCount
  3750. );
  3751. //
  3752. // No attributes are replicatable.
  3753. // (That's good, too, since SAM hasn't told Netlogon our role yet.)
  3754. Status = LsapDbDereferenceObject(
  3755. &LsapDbHandle,
  3756. PolicyObject,
  3757. PolicyObject,
  3758. (LSAP_DB_LOCK |
  3759. LSAP_DB_FINISH_TRANSACTION |
  3760. LSAP_DB_OMIT_REPLICATOR_NOTIFICATION ),
  3761. SecurityDbChange,
  3762. Status
  3763. );
  3764. }
  3765. }
  3766. Cleanup:
  3767. return(Status);
  3768. }
  3769. NTSTATUS
  3770. LsaIGetBootOption(
  3771. OUT PULONG BootOption
  3772. )
  3773. /*++
  3774. This function is used to obtain the boot option from LSA
  3775. Arguments
  3776. BootOption -- New Boot is passed in here
  3777. Return Values
  3778. --*/
  3779. {
  3780. NTSTATUS Status = STATUS_SUCCESS;
  3781. ULONG StoredEncryptionKeyDataLength = sizeof( LSAP_DB_ENCRYPTION_KEY );
  3782. LSAP_DB_ENCRYPTION_KEY StoredEncryptionKeyData;
  3783. //
  3784. // Read the attribute information in the LSA policy database
  3785. //
  3786. Status = LsapDbReadAttributeObject(
  3787. LsapDbHandle,
  3788. &LsapDbNames[PolSecretEncryptionKey],
  3789. (PVOID) &StoredEncryptionKeyData,
  3790. &StoredEncryptionKeyDataLength
  3791. );
  3792. if (!NT_SUCCESS(Status) ) {
  3793. goto Cleanup;
  3794. }
  3795. *BootOption = StoredEncryptionKeyData.BootType;
  3796. Cleanup:
  3797. return(Status);
  3798. }