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.
650 lines
17 KiB
650 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dbftrust.h
|
|
|
|
Abstract:
|
|
|
|
Forest trust cache class declaration
|
|
|
|
--*/
|
|
|
|
#ifndef __FTCACHE_H
|
|
#define __FTCACHE_H
|
|
|
|
class FTCache
|
|
{
|
|
friend NTSTATUS
|
|
LsarSetForestTrustInformation(
|
|
IN LSAPR_HANDLE PolicyHandle,
|
|
IN LSA_UNICODE_STRING * TrustedDomainName,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE HighestRecordType,
|
|
IN LSA_FOREST_TRUST_INFORMATION * ForestTrustInfo,
|
|
IN BOOLEAN CheckOnly,
|
|
OUT PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo );
|
|
|
|
friend NTSTATUS
|
|
LsapForestTrustCacheInsert(
|
|
IN UNICODE_STRING * TrustedDomainName,
|
|
IN OPTIONAL PSID TrustedDomainSid,
|
|
IN LSA_FOREST_TRUST_INFORMATION * ForestTrustInfo,
|
|
IN BOOLEAN LocalForestEntry );
|
|
|
|
public:
|
|
|
|
FTCache();
|
|
~FTCache();
|
|
|
|
NTSTATUS Initialize();
|
|
|
|
void SetLocalValid() { m_LocalValid = TRUE; }
|
|
void SetExternalValid() { m_ExternalValid = TRUE; }
|
|
void SetInvalid();
|
|
BOOLEAN IsLocalValid() { return m_LocalValid; }
|
|
BOOLEAN IsExternalValid() { return m_ExternalValid; }
|
|
|
|
NTSTATUS
|
|
Remove(
|
|
IN UNICODE_STRING * TrustedDomainName );
|
|
|
|
NTSTATUS
|
|
Retrieve(
|
|
IN UNICODE_STRING * TrustedDomainName,
|
|
OUT LSA_FOREST_TRUST_INFORMATION * * ForestTrustInfo );
|
|
|
|
NTSTATUS
|
|
Match(
|
|
IN LSA_ROUTING_MATCH_TYPE Type,
|
|
IN PVOID Data,
|
|
IN BOOLEAN SearchLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
#if !defined(LSAEXTS) // anything in lsaexts.cxx gets full access
|
|
private:
|
|
#endif
|
|
|
|
BOOLEAN m_Initialized;
|
|
BOOLEAN m_LocalValid;
|
|
BOOLEAN m_ExternalValid;
|
|
|
|
RTL_AVL_TABLE m_TdoTable;
|
|
RTL_AVL_TABLE m_TopLevelNameTable;
|
|
RTL_AVL_TABLE m_DomainSidTable;
|
|
RTL_AVL_TABLE m_DnsNameTable;
|
|
RTL_AVL_TABLE m_NetbiosNameTable;
|
|
|
|
//
|
|
// Every TDO the forest trust information for which is stored in the
|
|
// cache is going to have an entry like this created for it.
|
|
// This way, retrieving and setting information for a particular TDO
|
|
// can be performed efficiently.
|
|
//
|
|
|
|
struct TDO_ENTRY {
|
|
|
|
UNICODE_STRING TrustedDomainName; // name of the corresponding TDO
|
|
PSID TrustedDomainSid; // SID of the corresponding TDO
|
|
LIST_ENTRY TlnList; // list of top level name entries for this TDO list entry
|
|
LIST_ENTRY DomainInfoList; // list of domain info entries for this TDO
|
|
LIST_ENTRY BinaryList; // list of unrecognized entries for this TDO list entry
|
|
ULONG RecordCount; // combined number of records
|
|
BOOLEAN LocalForestEntry; // does this entry correspond to the local forest?
|
|
|
|
BOOLEAN Excludes( IN const UNICODE_STRING * Name );
|
|
|
|
#pragma warning(disable:4200)
|
|
WCHAR TrustedDomainNameBuffer[];
|
|
#pragma warning(default:4200)
|
|
};
|
|
|
|
//
|
|
// Top level name key for AVL tree lookups
|
|
// Contains a top level name and a list of entries matching this TLN
|
|
//
|
|
|
|
struct TLN_KEY {
|
|
|
|
UNICODE_STRING TopLevelName; // MUST be the first field
|
|
ULONG Count; // Number of entries under this key
|
|
LIST_ENTRY List; // List of entries under this key
|
|
|
|
#pragma warning(disable:4200)
|
|
WCHAR TopLevelNameBuffer[];
|
|
#pragma warning(default:4200)
|
|
};
|
|
|
|
//
|
|
// Top level name entry for AVL tree lookups
|
|
//
|
|
|
|
struct TLN_ENTRY {
|
|
|
|
//
|
|
// This 'friend' relationship is a work-around for an ia64 compiler
|
|
// bug that causes FTCache::TDO_ENTRY::Excludes to fail access control
|
|
//
|
|
|
|
friend BOOLEAN
|
|
TDO_ENTRY::Excludes( IN const UNICODE_STRING * Name );
|
|
|
|
LIST_ENTRY TdoListEntry;
|
|
LIST_ENTRY AvlListEntry;
|
|
LARGE_INTEGER Time;
|
|
BOOLEAN Excluded;
|
|
ULONG Index;
|
|
TDO_ENTRY * TdoEntry;
|
|
union {
|
|
TLN_ENTRY * SubordinateEntry; // for regular entries
|
|
TLN_ENTRY * SuperiorEntry; // for excluded entries
|
|
};
|
|
TLN_KEY * TlnKey;
|
|
|
|
BOOLEAN Enabled() {
|
|
|
|
return Excluded ?
|
|
FALSE :
|
|
SubordinateEntry ?
|
|
SubordinateEntry->Enabled() :
|
|
(( m_Flags & LSA_FTRECORD_DISABLED_REASONS ) == 0 );
|
|
}
|
|
|
|
ULONG Flags() {
|
|
|
|
return Excluded ?
|
|
m_Flags :
|
|
SubordinateEntry ?
|
|
SubordinateEntry->Flags() :
|
|
m_Flags;
|
|
}
|
|
|
|
void SetFlags( IN ULONG NewValue ) {
|
|
|
|
if ( Excluded ) {
|
|
|
|
m_Flags = NewValue; // value ignored for excluded entries
|
|
|
|
} else if ( SubordinateEntry ) {
|
|
|
|
SubordinateEntry->SetFlags( NewValue );
|
|
|
|
} else {
|
|
|
|
m_Flags = NewValue;
|
|
}
|
|
}
|
|
|
|
static TLN_ENTRY *
|
|
EntryFromTdoEntry( IN LIST_ENTRY * ListEntry ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntry,
|
|
TLN_ENTRY,
|
|
TdoListEntry
|
|
);
|
|
}
|
|
|
|
static TLN_ENTRY *
|
|
EntryFromAvlEntry( IN LIST_ENTRY * ListEntry ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntry,
|
|
TLN_ENTRY,
|
|
AvlListEntry
|
|
);
|
|
}
|
|
|
|
#if !defined(LSAEXTS) // anything in lsaexts.cxx gets full access
|
|
private:
|
|
#endif
|
|
|
|
ULONG m_Flags;
|
|
};
|
|
|
|
//
|
|
// Domain SID key for AVL tree lookups
|
|
// Contains a domain SID and a list of entries matching this domain SID
|
|
//
|
|
|
|
struct DOMAIN_SID_KEY {
|
|
|
|
SID * DomainSid; // MUST be the first field
|
|
ULONG Count; // Number of entries under this key
|
|
LIST_ENTRY List; // List of entries under this key
|
|
|
|
#pragma warning(disable:4200)
|
|
ULONG SidBuffer[];
|
|
#pragma warning(default:4200)
|
|
};
|
|
|
|
//
|
|
// DNS name key for AVL tree lookups
|
|
// Contains a domain name and a list of entries matching this DNS name
|
|
//
|
|
|
|
struct DNS_NAME_KEY {
|
|
|
|
UNICODE_STRING DnsName; // MUST be the first field
|
|
ULONG Count; // Number of entries under this key
|
|
LIST_ENTRY List; // List of entries under this key
|
|
|
|
#pragma warning(disable:4200)
|
|
WCHAR DnsNameBuffer[];
|
|
#pragma warning(default:4200)
|
|
};
|
|
|
|
//
|
|
// Netbios name key for AVL tree lookups
|
|
// Contains a Netbios name and a list of entries matching this Netbios name
|
|
//
|
|
|
|
struct NETBIOS_NAME_KEY {
|
|
|
|
UNICODE_STRING NetbiosName; // MUST be the first field
|
|
ULONG Count; // Number of entries under this key
|
|
LIST_ENTRY List; // List of entries under this key
|
|
|
|
#pragma warning(disable:4200)
|
|
WCHAR NetbiosNameBuffer[];
|
|
#pragma warning(default:4200)
|
|
};
|
|
|
|
//
|
|
// Domain info entry for AVL tree lookups
|
|
//
|
|
|
|
struct DOMAIN_INFO_ENTRY {
|
|
|
|
LIST_ENTRY TdoListEntry;
|
|
LIST_ENTRY SidAvlListEntry;
|
|
LIST_ENTRY DnsAvlListEntry;
|
|
LIST_ENTRY NetbiosAvlListEntry;
|
|
LARGE_INTEGER Time;
|
|
ULONG Index;
|
|
SID * Sid;
|
|
TDO_ENTRY * TdoEntry;
|
|
TLN_ENTRY * SubordinateTo;
|
|
DOMAIN_SID_KEY * SidKey;
|
|
DNS_NAME_KEY * DnsKey;
|
|
NETBIOS_NAME_KEY * NetbiosKey;
|
|
|
|
#define SID_DISABLED_MASK ( LSA_SID_DISABLED_ADMIN | LSA_SID_DISABLED_CONFLICT )
|
|
BOOLEAN SidEnabled() { return (( m_Flags & SID_DISABLED_MASK ) == 0 ); }
|
|
|
|
#define NETBIOS_DISABLED_MASK ( LSA_NB_DISABLED_ADMIN | LSA_NB_DISABLED_CONFLICT )
|
|
BOOLEAN NetbiosEnabled() { return (( m_Flags & ( SID_DISABLED_MASK | NETBIOS_DISABLED_MASK )) == 0 ); }
|
|
|
|
ULONG Flags() { return m_Flags; }
|
|
|
|
void SetFlags( IN ULONG NewValue ) {
|
|
|
|
m_Flags = NewValue;
|
|
}
|
|
|
|
void SetSidConflict() {
|
|
|
|
SetFlags( Flags() | LSA_SID_DISABLED_CONFLICT );
|
|
}
|
|
|
|
void SetNetbiosConflict() {
|
|
|
|
SetFlags( Flags() | LSA_NB_DISABLED_CONFLICT );
|
|
}
|
|
|
|
BOOLEAN IsSidAdminDisabled() {
|
|
|
|
return ( 0 != ( Flags() && LSA_SID_DISABLED_ADMIN ));
|
|
}
|
|
|
|
BOOLEAN IsNbAdminDisabled() {
|
|
|
|
return ( 0 != ( Flags() && LSA_NB_DISABLED_ADMIN ));
|
|
}
|
|
|
|
static DOMAIN_INFO_ENTRY *
|
|
EntryFromTdoEntry( IN LIST_ENTRY * ListEntryTdo ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntryTdo,
|
|
DOMAIN_INFO_ENTRY,
|
|
TdoListEntry
|
|
);
|
|
}
|
|
|
|
static DOMAIN_INFO_ENTRY *
|
|
EntryFromSidEntry( IN LIST_ENTRY * ListEntrySid ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntrySid,
|
|
DOMAIN_INFO_ENTRY,
|
|
SidAvlListEntry
|
|
);
|
|
}
|
|
|
|
static DOMAIN_INFO_ENTRY *
|
|
EntryFromDnsEntry( IN LIST_ENTRY * ListEntryDns ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntryDns,
|
|
DOMAIN_INFO_ENTRY,
|
|
DnsAvlListEntry
|
|
);
|
|
}
|
|
|
|
static DOMAIN_INFO_ENTRY *
|
|
EntryFromNetbiosEntry( IN LIST_ENTRY * ListEntryNB ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntryNB,
|
|
DOMAIN_INFO_ENTRY,
|
|
NetbiosAvlListEntry
|
|
);
|
|
}
|
|
|
|
#if !defined(LSAEXTS) // anything in lsaexts.cxx gets full access
|
|
private:
|
|
#endif
|
|
|
|
ULONG m_Flags;
|
|
};
|
|
|
|
struct BINARY_ENTRY {
|
|
|
|
LIST_ENTRY TdoListEntry;
|
|
LARGE_INTEGER Time;
|
|
LSA_FOREST_TRUST_RECORD_TYPE Type;
|
|
LSA_FOREST_TRUST_BINARY_DATA Data;
|
|
|
|
BOOLEAN Enabled() { return (( m_Flags & LSA_FTRECORD_DISABLED_REASONS ) == 0 ); }
|
|
|
|
ULONG Flags() { return m_Flags; }
|
|
|
|
void SetFlags( IN ULONG NewValue ) {
|
|
|
|
m_Flags = NewValue;
|
|
}
|
|
|
|
static BINARY_ENTRY *
|
|
EntryFromTdoEntry( IN LIST_ENTRY * ListEntry ) {
|
|
|
|
return CONTAINING_RECORD(
|
|
ListEntry,
|
|
BINARY_ENTRY,
|
|
TdoListEntry
|
|
);
|
|
}
|
|
|
|
#if !defined(LSAEXTS) // anything in lsaexts.cxx gets full access
|
|
private:
|
|
#endif
|
|
|
|
ULONG m_Flags;
|
|
};
|
|
|
|
struct CONFLICT_PAIR {
|
|
|
|
LSA_FOREST_TRUST_RECORD_TYPE EntryType1;
|
|
|
|
union {
|
|
void * Entry1;
|
|
TLN_ENTRY * TlnEntry1;
|
|
DOMAIN_INFO_ENTRY * DomainInfoEntry1;
|
|
};
|
|
|
|
ULONG Flag1;
|
|
|
|
LSA_FOREST_TRUST_RECORD_TYPE EntryType2;
|
|
|
|
union {
|
|
void * Entry2;
|
|
TLN_ENTRY * TlnEntry2;
|
|
DOMAIN_INFO_ENTRY * DomainInfoEntry2;
|
|
};
|
|
|
|
ULONG Flag2;
|
|
|
|
TDO_ENTRY * TdoEntry1() {
|
|
|
|
switch ( EntryType1 ) {
|
|
|
|
case ForestTrustTopLevelName:
|
|
case ForestTrustTopLevelNameEx:
|
|
|
|
ASSERT( TlnEntry1 );
|
|
ASSERT( TlnEntry1->TdoEntry );
|
|
|
|
return TlnEntry1->TdoEntry;
|
|
|
|
case ForestTrustDomainInfo:
|
|
|
|
ASSERT( DomainInfoEntry1 );
|
|
ASSERT( DomainInfoEntry1->TdoEntry );
|
|
|
|
return DomainInfoEntry1->TdoEntry;
|
|
|
|
default:
|
|
|
|
ASSERT( FALSE ); // who created this entry??? it makes no sense.
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
TDO_ENTRY * TdoEntry2() {
|
|
|
|
switch ( EntryType2 ) {
|
|
|
|
case ForestTrustTopLevelName:
|
|
case ForestTrustTopLevelNameEx:
|
|
|
|
ASSERT( TlnEntry2 );
|
|
ASSERT( TlnEntry2->TdoEntry );
|
|
|
|
return TlnEntry2->TdoEntry;
|
|
|
|
case ForestTrustDomainInfo:
|
|
|
|
ASSERT( DomainInfoEntry2 );
|
|
ASSERT( DomainInfoEntry2->TdoEntry );
|
|
|
|
return DomainInfoEntry2->TdoEntry;
|
|
|
|
default:
|
|
|
|
ASSERT( FALSE ); // who created this entry??? it makes no sense.
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void DisableEntry1() {
|
|
|
|
switch ( EntryType1 ) {
|
|
|
|
case ForestTrustTopLevelName:
|
|
case ForestTrustTopLevelNameEx:
|
|
|
|
TlnEntry1->SetFlags( TlnEntry1->Flags() | Flag1 );
|
|
break;
|
|
|
|
case ForestTrustDomainInfo:
|
|
|
|
DomainInfoEntry1->SetFlags( DomainInfoEntry1->Flags() | Flag1 );
|
|
break;
|
|
|
|
default:
|
|
ASSERT( FALSE ); // who created this entry??? it makes no sense.
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DisableEntry2() {
|
|
|
|
switch ( EntryType2 ) {
|
|
|
|
case ForestTrustTopLevelName:
|
|
case ForestTrustTopLevelNameEx:
|
|
|
|
TlnEntry2->SetFlags( TlnEntry2->Flags() | Flag2 );
|
|
break;
|
|
|
|
case ForestTrustDomainInfo:
|
|
|
|
DomainInfoEntry2->SetFlags( DomainInfoEntry2->Flags() | Flag2 );
|
|
break;
|
|
|
|
default:
|
|
ASSERT( FALSE ); // who created this entry??? it makes no sense.
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
BOOLEAN
|
|
IsEmpty() { return NULL != RtlEnumerateGenericTableAvl( &m_TdoTable, TRUE ); }
|
|
|
|
NTSTATUS
|
|
Insert(
|
|
IN UNICODE_STRING * TrustedDomainName,
|
|
IN OPTIONAL PSID TrustedDomainSid,
|
|
IN LSA_FOREST_TRUST_INFORMATION * ForestTrustInfo,
|
|
IN BOOLEAN LocalForestEntry,
|
|
OUT TDO_ENTRY * TdoEntryOld,
|
|
OUT TDO_ENTRY * * TdoEntryNew,
|
|
OUT CONFLICT_PAIR * * ConflictPairs,
|
|
OUT ULONG * ConflictPairsTotal );
|
|
|
|
static
|
|
void
|
|
ReconcileConflictPairs(
|
|
IN OPTIONAL const TDO_ENTRY * TdoEntry,
|
|
IN CONFLICT_PAIR * ConflictPairs,
|
|
IN ULONG ConflictPairsTotal );
|
|
|
|
static
|
|
NTSTATUS
|
|
GenerateConflictInfo(
|
|
IN CONFLICT_PAIR * ConflictPairs,
|
|
IN ULONG ConflictPairsTotal,
|
|
IN TDO_ENTRY * TdoEntry,
|
|
OUT PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo );
|
|
|
|
static
|
|
NTSTATUS
|
|
MarshalBlob(
|
|
IN TDO_ENTRY * TdoEntry,
|
|
OUT ULONG * MarshaledSize,
|
|
OUT PBYTE * MarshaledBlob );
|
|
|
|
void Purge();
|
|
|
|
void
|
|
RollbackChanges(
|
|
IN TDO_ENTRY * TdoEntryNew,
|
|
IN TDO_ENTRY * TdoEntryOld );
|
|
|
|
void
|
|
PurgeTdoEntry( IN TDO_ENTRY * TdoEntry );
|
|
|
|
void
|
|
RemoveTdoEntry( IN TDO_ENTRY * TdoEntry );
|
|
|
|
static
|
|
void
|
|
CopyTdoEntry(
|
|
IN TDO_ENTRY * Destination,
|
|
IN TDO_ENTRY * Source );
|
|
|
|
LSA_FOREST_TRUST_RECORD * RecordFromTopLevelNameEntry( IN TLN_ENTRY * Entry );
|
|
LSA_FOREST_TRUST_RECORD * RecordFromDomainInfoEntry( IN DOMAIN_INFO_ENTRY * Entry );
|
|
LSA_FOREST_TRUST_RECORD * RecordFromBinaryEntry( IN BINARY_ENTRY * Entry );
|
|
|
|
NTSTATUS
|
|
MatchSid(
|
|
IN SID * Sid,
|
|
OUT BOOLEAN * IsLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
NTSTATUS
|
|
MatchDnsName(
|
|
IN UNICODE_STRING * String,
|
|
OUT BOOLEAN * IsLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
NTSTATUS
|
|
MatchNetbiosName(
|
|
IN UNICODE_STRING * String,
|
|
OUT BOOLEAN * IsLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
NTSTATUS
|
|
MatchUpn(
|
|
IN UNICODE_STRING * String,
|
|
OUT BOOLEAN * IsLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
NTSTATUS
|
|
MatchSpn(
|
|
IN UNICODE_STRING * String,
|
|
OUT BOOLEAN * IsLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
NTSTATUS
|
|
MatchNamespace(
|
|
IN UNICODE_STRING * String,
|
|
OUT BOOLEAN * IsLocal,
|
|
OUT OPTIONAL UNICODE_STRING * TrustedDomainName,
|
|
OUT OPTIONAL PSID * TrustedDomainSid );
|
|
|
|
TLN_ENTRY *
|
|
LongestSubstringMatchTln(
|
|
OUT BOOLEAN * IsLocal,
|
|
IN UNICODE_STRING * String );
|
|
|
|
static
|
|
NTSTATUS
|
|
AddConflictPair(
|
|
IN OUT CONFLICT_PAIR * * ConflictPairs,
|
|
IN OUT ULONG * ConflictPairTotal,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE Type1,
|
|
IN void * Conflict1,
|
|
IN ULONG Flag1,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE Type2,
|
|
IN void * Conflict2,
|
|
IN ULONG Flag2 );
|
|
|
|
void
|
|
AuditChanges(
|
|
IN const TDO_ENTRY * OldEntry,
|
|
IN const TDO_ENTRY * NewEntry );
|
|
|
|
void
|
|
AuditCollisions(
|
|
IN CONFLICT_PAIR * ConflictPairs,
|
|
IN ULONG ConflictPairsTotal );
|
|
|
|
#if DBG
|
|
|
|
//
|
|
// Debug-only statistics
|
|
//
|
|
|
|
static DWORD sm_TdoEntries;
|
|
static DWORD sm_TlnEntries;
|
|
static DWORD sm_DomainInfoEntries;
|
|
static DWORD sm_BinaryEntries;
|
|
static DWORD sm_TlnKeys;
|
|
static DWORD sm_SidKeys;
|
|
static DWORD sm_DnsNameKeys;
|
|
static DWORD sm_NetbiosNameKeys;
|
|
|
|
#endif
|
|
};
|
|
|
|
#endif // __FTCACHE_H
|