514 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			514 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 1991  Microsoft Corporation
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|     dbdata.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|     Local Security Authority - Database Server Global Data
 | |
| 
 | |
| Author:
 | |
| 
 | |
|     Scott Birrell       (ScottBi)       July 25, 1991
 | |
| 
 | |
| Environment:
 | |
| 
 | |
|     User Mode
 | |
| 
 | |
| Revision History:
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include <lsapch2.h>
 | |
| #include "dbp.h"
 | |
| 
 | |
| OBJECT_ATTRIBUTES  LsapDbObjectAttributes;
 | |
| STRING  LsapDbNameString;
 | |
| LARGE_INTEGER LsapDbInitSize;
 | |
| LARGE_INTEGER LsapDbMaximumSizeOfSection;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| //
 | |
| // LSA Initialized Status
 | |
| //
 | |
| 
 | |
| BOOLEAN LsapInitialized = FALSE;
 | |
| 
 | |
| //
 | |
| // Setup Event Existed
 | |
| // This is necessary to distinguish a psuedo install done
 | |
| // during a developer's first boot after install (which does
 | |
| // an auto init) and the case where a real setup was run.
 | |
| //
 | |
| 
 | |
| BOOLEAN LsapSetupWasRun = FALSE;
 | |
| 
 | |
| //
 | |
| // Boolean indicating that the Ds is up and running
 | |
| //
 | |
| BOOLEAN LsapDsIsRunning = FALSE;
 | |
| 
 | |
| //
 | |
| // Database initialization has been performed
 | |
| //
 | |
| 
 | |
| BOOLEAN LsapDatabaseSetupPerformed = FALSE;
 | |
| 
 | |
| //
 | |
| // Type of product we are running
 | |
| //
 | |
| 
 | |
| NT_PRODUCT_TYPE LsapProductType;
 | |
| 
 | |
| //
 | |
| // Product suites available on the current machine
 | |
| //
 | |
| WORD LsapProductSuiteMask=0;
 | |
| 
 | |
| 
 | |
| //
 | |
| // LSA Database State information
 | |
| //
 | |
| 
 | |
| LSAP_DB_STATE LsapDbState;
 | |
| 
 | |
| #ifdef DBG
 | |
| BOOL g_ScePolicyLocked = FALSE;
 | |
| #endif
 | |
| 
 | |
| //
 | |
| // LsaDb object Handle used internally.
 | |
| // Also one for use throughout LSA.
 | |
| //
 | |
| 
 | |
| LSAPR_HANDLE LsapDbHandle;
 | |
| LSAPR_HANDLE LsapPolicyHandle = NULL;
 | |
| 
 | |
| //
 | |
| // LSA Database Encryption Key
 | |
| //
 | |
| 
 | |
| PLSAP_CR_CIPHER_KEY LsapDbCipherKey;
 | |
| PLSAP_CR_CIPHER_KEY LsapDbSP4SecretCipherKey;
 | |
| PLSAP_CR_CIPHER_KEY LsapDbSecretCipherKeyRead;
 | |
| PLSAP_CR_CIPHER_KEY LsapDbSecretCipherKeyWrite;
 | |
| PVOID   LsapDbSysKey = NULL;
 | |
| PVOID   LsapDbOldSysKey = NULL;
 | |
| 
 | |
| //
 | |
| // Is this a DC in the root domain?
 | |
| //
 | |
| 
 | |
| BOOLEAN DcInRootDomain = FALSE;
 | |
| 
 | |
| //
 | |
| // Queue of name/sid lookup activities.
 | |
| //
 | |
| 
 | |
| LSAP_DB_LOOKUP_WORK_QUEUE LookupWorkQueue;
 | |
| 
 | |
| 
 | |
| //
 | |
| // LSA Database Object SubKey Unicode name string and attributes array
 | |
| //
 | |
| 
 | |
| UNICODE_STRING LsapDbNames[DummyLastName];
 | |
| PLSAP_DB_DS_INFO LsapDbDsAttInfo;
 | |
| 
 | |
| //
 | |
| // LSA Database Object Type Containing Directory Names
 | |
| //
 | |
| 
 | |
| UNICODE_STRING LsapDbContDirs[DummyLastObject];
 | |
| 
 | |
| //
 | |
| // Object Information Requirements.  These arrays, indexed by object
 | |
| // type id indicated whether objects have Sids or Names.
 | |
| //
 | |
| // WARNING! - These arrays must be kept in sync with the LSAP_DB_OBJECT_TYPE_ID
 | |
| // enumerated type.
 | |
| //
 | |
| 
 | |
| BOOLEAN LsapDbRequiresSidInfo[DummyLastObject] = {
 | |
| 
 | |
|     FALSE, // NullObject
 | |
|     FALSE, // LsaDatabaseObject
 | |
|     FALSE, // BuiltInAccountObject
 | |
|     TRUE,  // AccountObject
 | |
|     FALSE  // SecretObject
 | |
| };
 | |
| 
 | |
| BOOLEAN LsapDbRequiresNameInfo[DummyLastObject] = {
 | |
| 
 | |
|     FALSE, // NullObject,
 | |
|     TRUE,  // LsaDatabaseObject
 | |
|     TRUE,  // BuiltInAccountObject
 | |
|     FALSE, // AccountObject
 | |
|     TRUE   // SecretObject
 | |
| };
 | |
| 
 | |
| //
 | |
| // Table of accesses required to query Policy Information.  This table
 | |
| // is indexed by Policy Information Class
 | |
| //
 | |
| 
 | |
| ACCESS_MASK LsapDbRequiredAccessQueryPolicy[PolicyDnsDomainInformationInt + 1] = {
 | |
| 
 | |
|         0,                              // Information classes start at 1
 | |
|         POLICY_VIEW_AUDIT_INFORMATION,  // PolicyAuditLogInformation
 | |
|         POLICY_VIEW_AUDIT_INFORMATION,  // PolicyAuditEventsInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyPrimaryDomainInformation
 | |
|         POLICY_GET_PRIVATE_INFORMATION, // PolicyPdAccountInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyAccountDomainInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyLsaServerRoleInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyReplicaSourceInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyDefaultQuotaInformation
 | |
|         0,                              // Not settable by non-trusted call
 | |
|         0,                              // Not applicable
 | |
|         POLICY_VIEW_AUDIT_INFORMATION,  // PolicyAuditFullQueryInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyDnsDomainInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyDnsDomainInformationInt
 | |
| };
 | |
| 
 | |
| ACCESS_MASK LsapDbRequiredAccessQueryDomainPolicy[PolicyDomainKerberosTicketInformation + 1] = {
 | |
| 
 | |
|         0,                              // Information classes start at 2
 | |
|         0,                              // PolicyDomainQualityOfServiceInformation (outdated)
 | |
|         POLICY_VIEW_LOCAL_INFORMATION,  // PolicyDomainEfsInformation
 | |
|         POLICY_VIEW_LOCAL_INFORMATION   // PolicyDomainKerberosTicketInformation
 | |
| };
 | |
| 
 | |
| //
 | |
| // Table of accesses required to set Policy Information.  This table
 | |
| // is indexed by Policy Information Class
 | |
| //
 | |
| 
 | |
| ACCESS_MASK LsapDbRequiredAccessSetPolicy[PolicyDnsDomainInformationInt + 1] = {
 | |
| 
 | |
|         0,                              // Information classes start at 1
 | |
|         POLICY_AUDIT_LOG_ADMIN,         // PolicyAuditLogInformation
 | |
|         POLICY_SET_AUDIT_REQUIREMENTS,  // PolicyAuditEventsInformation
 | |
|         POLICY_TRUST_ADMIN,             // PolicyPrimaryDomainInformation
 | |
|         0,                              // Not settable by non-trusted call
 | |
|         POLICY_TRUST_ADMIN,             // PolicyAccountDomainInformation
 | |
|         POLICY_SERVER_ADMIN,            // PolicyLsaServerRoleInformation
 | |
|         POLICY_SERVER_ADMIN,            // PolicyReplicaSourceInformation
 | |
|         POLICY_SET_DEFAULT_QUOTA_LIMITS,// PolicyDefaultQuotaInformation
 | |
|         0,                              // Not settable by non-trusted call
 | |
|         POLICY_AUDIT_LOG_ADMIN,         // PolicyAuditFullSetInformation
 | |
|         0,                              // Not applicable
 | |
|         POLICY_TRUST_ADMIN,             // PolicyDnsDomainInformation
 | |
|         POLICY_TRUST_ADMIN,             // PolicyDnsDomainInformationInt
 | |
| };
 | |
| 
 | |
| ACCESS_MASK LsapDbRequiredAccessSetDomainPolicy[PolicyDomainKerberosTicketInformation + 1] = {
 | |
| 
 | |
|         0,                              // Information classes start at 2
 | |
|         0,                              // PolicyDomainQualityOfServiceInformation (outdated)
 | |
|         POLICY_SERVER_ADMIN,            // PolicyDomainEfsInformation
 | |
|         POLICY_SERVER_ADMIN             // PolicyDomainKerberosTicketInformation
 | |
| };
 | |
| 
 | |
| 
 | |
| //
 | |
| // Table of accesses required to query TrustedDomain Information.  This table
 | |
| // is indexed by TrustedDomain Information Class
 | |
| //
 | |
| 
 | |
| ACCESS_MASK LsapDbRequiredAccessQueryTrustedDomain[TrustedDomainFullInformation2Internal + 1] = {
 | |
| 
 | |
|     0,                              // Information classes start at 1
 | |
|     TRUSTED_QUERY_DOMAIN_NAME,      // TrustedDomainNameInformation
 | |
|     TRUSTED_QUERY_CONTROLLERS,      // TrustedControllersInformation
 | |
|     TRUSTED_QUERY_POSIX,            // TrustedPosixOffsetInformation
 | |
|     TRUSTED_QUERY_AUTH,             // TrustedPasswordInformation
 | |
|     TRUSTED_QUERY_DOMAIN_NAME,      // TrustedDomainInformationBasic
 | |
|     TRUSTED_QUERY_DOMAIN_NAME,      // TrustedDomainInformationEx
 | |
|     TRUSTED_QUERY_AUTH,             // TrustedDomainAuthInformation
 | |
|     TRUSTED_QUERY_DOMAIN_NAME |
 | |
|         TRUSTED_QUERY_POSIX |
 | |
|         TRUSTED_QUERY_AUTH,         // TrustedDomainFullInformation
 | |
|     TRUSTED_QUERY_AUTH,             // TrustedDomainAuthInformationInternal
 | |
|     TRUSTED_QUERY_DOMAIN_NAME |
 | |
|         TRUSTED_QUERY_POSIX |
 | |
|         TRUSTED_QUERY_AUTH,         // TrustedDomainFullInformationInternal
 | |
|     TRUSTED_QUERY_DOMAIN_NAME,      // TrustedDomainInformationEx2Internal
 | |
|     TRUSTED_QUERY_DOMAIN_NAME |
 | |
|         TRUSTED_QUERY_POSIX |
 | |
|         TRUSTED_QUERY_AUTH          // TrustedDomainFullInformation2Internal
 | |
| };
 | |
| 
 | |
| //
 | |
| // Table of accesses required to set TrustedDomain Information.  This table
 | |
| // is indexed by TrustedDomain Information Class
 | |
| //
 | |
| 
 | |
| ACCESS_MASK LsapDbRequiredAccessSetTrustedDomain[TrustedDomainFullInformation2Internal + 1] = {
 | |
| 
 | |
|     0,                              // Information classes start at 1
 | |
|     0,                              // not settable (TrustedDomainNameInformation)
 | |
|     TRUSTED_SET_CONTROLLERS,        // TrustedControllersInformation
 | |
|     TRUSTED_SET_POSIX,              // TrustedPosixOffsetInformation
 | |
|     TRUSTED_SET_AUTH,               // TrustedPasswordInformation
 | |
|     TRUSTED_SET_POSIX,              // TrustedDomainInformationBasic  POSIX is a bad bit, but its too late to change it
 | |
|     TRUSTED_SET_POSIX,              // TrustedDomainInformationEx     POSIX is a bad bit, but its too late to change it
 | |
|     TRUSTED_SET_AUTH,               // TrustedDomainAuthInformation
 | |
|     TRUSTED_SET_POSIX |
 | |
|         TRUSTED_SET_AUTH,           // TrustedDomainFullInformation
 | |
|     TRUSTED_SET_AUTH,               // TrustedDomainAuthInformationInternal
 | |
|     TRUSTED_SET_POSIX |
 | |
|         TRUSTED_SET_POSIX |
 | |
|         TRUSTED_SET_AUTH,           // TrustedDomainFullInformationInternal
 | |
|     TRUSTED_SET_POSIX,              // TrustedDomainInformationEx2Internal    POSIX is a bad bit, but its too late to change it
 | |
|     TRUSTED_SET_POSIX |
 | |
|         TRUSTED_SET_AUTH            // TrustedDomainFullInformation2Internal
 | |
| };
 | |
| 
 | |
| 
 | |
| //
 | |
| // Cached Policy Object.  Only default Quota Limits is cached just now.
 | |
| //
 | |
| 
 | |
| LSAP_DB_POLICY LsapDbPolicy = {0};
 | |
| 
 | |
| NTSTATUS
 | |
| LsaIGetPrivateData(
 | |
|     IN LSAPR_HANDLE PolicyHandle,
 | |
|     OUT PULONG DataLength,
 | |
|     OUT PVOID *Data
 | |
|     )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|     This service is a required part of replication.  Private LSA Database
 | |
|     information (i.e. not accessible via other LSA services even at the
 | |
|     trusted level) must be replicated the the beginning of each attempt
 | |
|     to replicate.  This call is used to read Private LSA Database data from
 | |
|     the Primary Domain Controller (PDC) involved in a replication.  The data
 | |
|     returned from this call must be provided to a corresponding
 | |
|     LsaISetPrivateData() call for each Backup Domain Controller involved
 | |
|     in the replication in order to update the private LSA Database information
 | |
|     on those controller(s).
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|     PolicyHandle - Trusted Handle to an Lsa Policy Object.
 | |
| 
 | |
|     DataLength - Length in bytes of the Private Data.
 | |
| 
 | |
|     Data - Pointer to the Private Data.
 | |
| 
 | |
| Return Values:
 | |
| 
 | |
|     NTSTATUS - Standard Nt Result Code
 | |
| 
 | |
|         STATUS_SUCCESS - The call completed successfully.
 | |
| 
 | |
|         STATUS_ACCESS_DENIED - The specified PolicyHandle is not Trusted.
 | |
| 
 | |
|         STATUS_INVALID_HANDLE - The specified PolicyHandle is not a
 | |
|             valid handle to a Policy Object.
 | |
| 
 | |
|         STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
 | |
|             such as memory, to complete the call.
 | |
| --*/
 | |
| 
 | |
| {
 | |
|     NTSTATUS Status;
 | |
|     BOOLEAN ObjectReferenced = FALSE;
 | |
|     PLSAP_DB_POLICY_PRIVATE_DATA PolicyPrivateData = NULL;
 | |
|     LSAP_DB_ATTRIBUTE Attribute = { 0 };
 | |
| 
 | |
|     //
 | |
|     // Acquire the Lsa Database lock.  Verify that the handle is a valid
 | |
|     // Trusted handle to the Policy object.  Reference the handle.
 | |
|     //
 | |
| 
 | |
|     Status = LsapDbReferenceObject(
 | |
|                  PolicyHandle,
 | |
|                  0,
 | |
|                  PolicyObject,
 | |
|                  PolicyObject,
 | |
|                  LSAP_DB_LOCK | LSAP_DB_TRUSTED
 | |
|                  );
 | |
| 
 | |
|     if (!NT_SUCCESS(Status)) {
 | |
| 
 | |
|         goto GetPrivateDataError;
 | |
|     }
 | |
| 
 | |
|     ObjectReferenced = TRUE;
 | |
| 
 | |
|     //
 | |
|     // Read the private LSA Database Data.
 | |
|     //
 | |
| 
 | |
|     Attribute.AttributeName = &LsapDbNames[PolState];
 | |
|     Attribute.AttributeValue = NULL;
 | |
|     Attribute.AttributeValueLength = sizeof (LSAP_DB_POLICY_PRIVATE_DATA);
 | |
|     Attribute.MemoryAllocated = FALSE;
 | |
| 
 | |
|     Status = LsapDbReadAttribute( PolicyHandle, &Attribute );
 | |
| 
 | |
|     if (!NT_SUCCESS(Status)) {
 | |
| 
 | |
|         goto GetPrivateDataError;
 | |
|     }
 | |
| 
 | |
| GetPrivateDataFinish:
 | |
| 
 | |
|     *Data = Attribute.AttributeValue;
 | |
|     *DataLength = Attribute.AttributeValueLength;
 | |
| 
 | |
|     //
 | |
|     // If necessary, dereference the Policy Object, release the LSA Database lock and
 | |
|     // return.
 | |
|     //
 | |
| 
 | |
|     if (ObjectReferenced) {
 | |
| 
 | |
|         Status = LsapDbDereferenceObject(
 | |
|                      &PolicyHandle,
 | |
|                      PolicyObject,
 | |
|                      PolicyObject,
 | |
|                      LSAP_DB_LOCK,
 | |
|                      (SECURITY_DB_DELTA_TYPE) 0,
 | |
|                      Status
 | |
|                      );
 | |
|     }
 | |
| 
 | |
|     return(Status);
 | |
| 
 | |
| GetPrivateDataError:
 | |
| 
 | |
|     Attribute.AttributeValueLength = 0;
 | |
| 
 | |
|     //
 | |
|     // If necessary, free the returned buffer.
 | |
|     //
 | |
| 
 | |
|     if ( Attribute.AttributeValue != NULL ) {
 | |
| 
 | |
|         MIDL_user_free( Attribute.AttributeValue );
 | |
|         Attribute.AttributeValue = NULL;
 | |
|     }
 | |
| 
 | |
|     goto GetPrivateDataFinish;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| NTSTATUS
 | |
| LsaISetPrivateData(
 | |
|     IN LSAPR_HANDLE PolicyHandle,
 | |
|     IN ULONG DataLength,
 | |
|     IN PVOID Data
 | |
|     )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|     This service is a required part of replication.  Private LSA Database
 | |
|     information (i.e. not accessible via other LSA services even at the
 | |
|     trusted level) must be replicated the the beginning of each attempt
 | |
|     to replicate.  Information specified on this call must have been
 | |
|     obtained from a corresponding LsaIGetPrivateData() call that accessed
 | |
|     the Primary Domain Controller (PDC) involved in a replication.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|     PolicyHandle - Trusted Handle to the Lsa Policy Object of a
 | |
|         Backup Domain Controller (BDC) involved in a repilcation.
 | |
| 
 | |
|     ModifiedCount - Specifies a value to be set for the current count of
 | |
|         modifications made to the LSA Database.
 | |
| 
 | |
|     CreationTime - Specifies a value to be set for the date and time at
 | |
|         which the LSA Database was created.
 | |
| 
 | |
|     DataLength - Length in bytes of the Private Data.
 | |
| 
 | |
|     Data - Pointer to the Private Data.
 | |
| 
 | |
| Return Values:
 | |
| 
 | |
|     NTSTATUS - Standard Nt Result Code
 | |
| 
 | |
|         STATUS_SUCCESS - The call completed successfully.
 | |
| 
 | |
|         STATUS_ACCESS_DENIED - The specified PolicyHandle is not Trusted.
 | |
| 
 | |
|         STATUS_INVALID_HANDLE - The specified PolicyHandle is not a
 | |
|             valid handle to a Policy Object.
 | |
| --*/
 | |
| 
 | |
| {
 | |
|     NTSTATUS Status;
 | |
|     BOOLEAN ObjectReferenced = FALSE;
 | |
| 
 | |
|     //
 | |
|     // Acquire the Lsa Database lock.  Verify that the handle is a valid
 | |
|     // Trusted handle to the Policy object.  Reference the handle.
 | |
|     //
 | |
| 
 | |
|     Status = LsapDbReferenceObject(
 | |
|                  PolicyHandle,
 | |
|                  0,
 | |
|                  PolicyObject,
 | |
|                  PolicyObject,
 | |
|                  LSAP_DB_LOCK | LSAP_DB_TRUSTED
 | |
|                  );
 | |
| 
 | |
|     if (!NT_SUCCESS(Status)) {
 | |
| 
 | |
|         goto SetPrivateDataError;
 | |
|     }
 | |
| 
 | |
|     ObjectReferenced = TRUE;
 | |
| 
 | |
|     Status = LsapDbWriteAttributeObject(
 | |
|                  PolicyHandle,
 | |
|                  &LsapDbNames[PolState],
 | |
|                  Data,
 | |
|                  DataLength
 | |
|                  );
 | |
| 
 | |
|     if (!NT_SUCCESS(Status)) {
 | |
| 
 | |
|         goto SetPrivateDataError;
 | |
|     }
 | |
| 
 | |
| SetPrivateDataFinish:
 | |
| 
 | |
|     //
 | |
|     // If necessary, dereference the Policy Object, release the LSA Database lock and
 | |
|     // return.
 | |
|     //
 | |
| 
 | |
|     if (ObjectReferenced) {
 | |
| 
 | |
|         Status = LsapDbDereferenceObject(
 | |
|                      &PolicyHandle,
 | |
|                      PolicyObject,
 | |
|                      PolicyObject,
 | |
|                      LSAP_DB_LOCK,
 | |
|                      (SECURITY_DB_DELTA_TYPE) 0,
 | |
|                      Status
 | |
|                      );
 | |
|     }
 | |
| 
 | |
|     return(Status);
 | |
| 
 | |
| SetPrivateDataError:
 | |
| 
 | |
|     goto SetPrivateDataFinish;
 | |
| }
 |