//#pragma title ("SidCache.hpp -- Cache, Tree of SIDs") /* Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved. =============================================================================== Module - sidcache.hpp System - SDResolve Author - Christy Boles Created - 97/06/27 Description - Cache of SIDs. Implemented using TNode derived classes, Cache is organized as a tree, sorted by Domain B RID. Each node contains Domain A RID, Domain B RID, Account Name, and counters for stats. Updates - =============================================================================== */ #ifndef TSIDCACHE_HEADER #define TSIDCACHE_HEADER #ifndef TNODEINCLUDED #include "Tnode.hpp" #define TNODEINCLUDED #endif //#import "\bin\McsVarSetMin.tlb" no_namespace //#import "VarSet.tlb" no_namespace rename("property", "aproperty")//#imported below via sdstat.hpp #include "DCTStat.h" #include "WorkObj.h" #include "sdstat.hpp" #include #include #ifndef IStatusObjPtr _COM_SMARTPTR_TYPEDEF(IStatusObj, __uuidof(IStatusObj)); #endif //#define ACCOUNT_NAME_LENGTH 256 #define NUM_IN_BUF 5000 /* the number of accounts to get at one time NetQueryDisplayInfo()*/ #define BUFSIZE 100000 /* preferred max size of buffer for receiving accounts NetQueryDisplayInfo()*/ #define DEFAULT_SID_SIZE 500 #define EALB_OCX_LOCAL_USER 13 #define EALB_OCX_GLOBAL_USER 14 #define EALB_OCX_LOCAL_GROUP 16 #define EALB_OCX_GLOBAL_GROUP 17 #define FST_CACHE_SOME_SOURCE 1 #define FST_CACHE_NO_TARGET 2 #define FST_CACHE_SOME_TARGET 4 #define FST_CACHE_NO_DOMAIN 8 class TAcctNode:public TNode { protected: DWORD owner_changes; // Stats for each node DWORD group_changes; DWORD ace_changes; DWORD sace_changes; public: TAcctNode(); virtual WCHAR * GetAcctName() = 0; virtual bool IsValidOnTgt() const = 0; virtual void AddOwnerChange(objectType type) { owner_changes++; } // Stats functions virtual void AddGroupChange(objectType type) { group_changes++; } virtual void AddAceChange(objectType type) { ace_changes++; } virtual void AddSaceChange(objectType type) { sace_changes++; } virtual void DisplayStats() const; DWORD OwnerChanges() { return owner_changes; } DWORD GroupChanges() { return group_changes; } DWORD DACEChanges() { return ace_changes; } DWORD SACEChanges() { return sace_changes; } BOOL ReportToVarSet(IVarSet * pVarSet, DWORD n); }; class TRidNode:public TAcctNode { public: typedef enum _STATUS { DEFAULT = 0, TARGETSIDISINVALID = 1 } STATUS; protected: DWORD srcRid; // RID for domain A DWORD tgtRid; // RID for domain B DWORD status; short acct_type; int acct_len; // length of account name std::wstring srcDomSid; // source domain sid std::wstring tgtDomSid; // target domain sid std::wstring srcDomName; // source domain name std::wstring tgtDomName; // target domain name WCHAR acct_name[1]; // source account name \0 target account name public: void * operator new(size_t sz,const LPWSTR name1,const LPWSTR name2); TRidNode(const LPWSTR oldacctname, const LPWSTR newacctname); ~TRidNode(); WCHAR * GetAcctName() { return acct_name; } // member "Get" functions WCHAR * GetTargetAcctName() { return acct_name + acct_len + 1; } DWORD SrcRid() const { return srcRid; } DWORD TgtRid() const { return tgtRid; } DWORD GetStatus() { return status; } void SetStatus(DWORD newStatus) { status = newStatus; } bool IsValidOnTgt() const { return tgtRid != 0 && !(status & TARGETSIDISINVALID); } short Type() { return acct_type; } void Type(short newtype) { acct_type = newtype; } void SrcRid(DWORD const val) { srcRid=val; } // member "Set" functions void TgtRid(DWORD const val) { tgtRid=val; } void DisplayStats() const; void DisplaySidInfo() const; PCWSTR GetSrcDomSid() { return srcDomSid.c_str(); } // member "Get" function PCWSTR GetTgtDomSid() { return tgtDomSid.c_str(); } // member "Get" function void SrcDomSid(PCWSTR sSid) { if (sSid) srcDomSid = sSid; else srcDomSid.erase(); } // member "Set" function void TgtDomSid(PCWSTR sSid) { if (sSid) tgtDomSid = sSid; else tgtDomSid.erase(); } // member "Set" function PCWSTR GetSrcDomName() { return srcDomName.c_str(); } // member "Get" function PCWSTR GetTgtDomName() { return tgtDomName.c_str(); } // member "Get" function void SrcDomName(PCWSTR sName) { if (sName) srcDomName = sName; else srcDomName.erase(); } // member "Set" function void TgtDomName(PCWSTR sName) { if (sName) tgtDomName = sName; else tgtDomName.erase(); } // member "Set" function protected: }; class TGeneralSidNode:public TAcctNode { protected: LPWSTR src_acct_name; LPWSTR tgt_acct_name; PSID src_sid; PSID tgt_sid; UCHAR src_nsubs; UCHAR tgt_nsubs; WCHAR * src_domain; WCHAR * tgt_domain; DWORD sizediff; TSDFileDirCell ownerStats; TSDFileDirCell groupStats; TSDFileDirCell daclStats; TSDFileDirCell saclStats; public: TGeneralSidNode(const LPWSTR name1, const LPWSTR name2); TGeneralSidNode(const PSID pSid1, const PSID pSid2); ~TGeneralSidNode(); LPWSTR GetAcctName() { return src_acct_name; } PSID SrcSid() { return src_sid; } PSID TgtSid() { return src_sid; /* this is a hack to allow for counting all references to accounts */ } bool IsValidOnTgt() const { return TRUE;/*tgt_sid != NULL;*/ } void DisplaySidInfo() const; DWORD SizeDiff() const { return 0; } TSDFileDirCell * GetOwnerStats() { return &ownerStats; } TSDFileDirCell * GetGroupStats() { return &groupStats; } TSDFileDirCell * GetDaclStats() { return &daclStats; } TSDFileDirCell * GetSaclStats() { return &saclStats; } virtual void AddOwnerChange(objectType type) { switch (type) { case file: ownerStats.file++; break; case directory: ownerStats.dir++; break; case mailbox: ownerStats.mailbox++; break; case container: ownerStats.container++; break; case share: ownerStats.share++; break; case groupmember: ownerStats.member++; break; case userright: ownerStats.userright++; break; case regkey: ownerStats.regkey++; break; case printer: ownerStats.printer++; break; default: break; }; } virtual void AddGroupChange(objectType type) { switch (type) { case file: groupStats.file++; break; case directory: groupStats.dir++; break; case mailbox: groupStats.mailbox++; break; case container: groupStats.container++; break; case share: groupStats.share++; break; case groupmember: groupStats.member++; break; case userright: groupStats.userright++; break; case regkey: groupStats.regkey++; break; case printer: groupStats.printer++; break; default: break; }; } virtual void AddAceChange(objectType type) { switch (type) { case file: daclStats.file++; break; case directory: daclStats.dir++; break; case mailbox: daclStats.mailbox++; break; case container: daclStats.container++; break; case share: daclStats.share++; break; case groupmember: daclStats.member++; break; case userright: daclStats.userright++; break; case regkey: daclStats.regkey++; break; case printer: daclStats.printer++; break; default: break; }; } virtual void AddSaceChange(objectType type) { switch (type) { case file: saclStats.file++; break; case directory: saclStats.dir++; break; case mailbox: saclStats.mailbox++; break; case container: saclStats.container++; break; case share: saclStats.share++; break; case groupmember: saclStats.member++; break; case userright: saclStats.userright++; break; case regkey: saclStats.regkey++; break; case printer: saclStats.printer++; break; default: break; }; } }; /**************************************************************************************************/ /* TSidCache: Cache for SIDs. The cache is filled by calling FillCache(name_of_domain_A, name_of_domain_B) Lookup, and GetName search the tree for a domain B SID value. Lookup returns a pointer to the node, while GetName returns the account name for the node. GetSidB( tsidnode *) builds and returns the domain B SID for the node (the node contains only the RID) SizeDiff() returns the answer to "How much bigger are domain B sids than domain A sids?" this information is needed when allocating space for ACES. /**************************************************************************************************/ class TAccountCache: public TNodeListSortable { IStatusObjPtr m_pStatus; public: TAccountCache() { m_cancelled = false; m_bAddIfNotFound = FALSE; } ~TAccountCache() {} virtual TAcctNode * Lookup(const PSID psid) = 0; // sid lookup functions virtual LPWSTR GetName(const PSID psid) = 0; //virtual BOOL Insert(const LPWSTR acctname,DWORD srcSid, DWORD tgtSid) = 0; virtual PSID GetTgtSid(const TAcctNode* tnode) = 0; virtual DWORD SizeDiff(const TAcctNode *tnode) const = 0; // returns max( 0 , (length(to_sid) - length(from_sid)) ) bool IsCancelled() { if ( m_pStatus ) { LONG status = 0; // HRESULT hr = m_pStatus->get_Status(&status); m_pStatus->get_Status(&status); return (status == DCT_STATUS_ABORTING); } else { return m_cancelled; } } void Cancel() { m_cancelled = true; if ( m_pStatus ) m_pStatus->put_Status(DCT_STATUS_ABORTING); } void UnCancel() { m_cancelled = false; } void AddIfNotFound(BOOL val) { m_bAddIfNotFound = val; } BOOL AddIfNotFound() { return m_bAddIfNotFound; } void SetStatusObject(IStatusObj * pS) { m_pStatus = pS; } protected: bool m_cancelled; BOOL m_bAddIfNotFound; }; class TGeneralCache; class TSDRidCache: public TAccountCache { protected: WCHAR from_domain[MAX_PATH + 1]; // domain names WCHAR to_domain[MAX_PATH + 1]; WCHAR from_dc[MAX_PATH + 1]; // domain controller (machine) names WCHAR to_dc[MAX_PATH + 1]; PSID from_sid; // domain sids (dynamically allocated) PSID to_sid; UCHAR from_nsubs; // # subauthorities in domain sids UCHAR to_nsubs; DWORD accts; // statistical stuff DWORD accts_resolved; TGeneralCache * m_otherAccounts; typedef std::multimap CRidToNodeMap; CRidToNodeMap m_mapRidToNode; public: TSDRidCache(); ~TSDRidCache(); // filling methods WCHAR const * GetSourceDomainName() { return from_domain; } WCHAR const * GetTargetDomainName() { return to_domain; } WCHAR const * GetSourceDCName() { return from_dc; } WCHAR const * GetTargetDCName() { return to_dc; } void InsertLast(const LPWSTR acctname,DWORD rida, const LPWSTR newname, DWORD ridb, short type = 0, DWORD status = TRidNode::DEFAULT) { TRidNode * tn = new (acctname,newname) TRidNode(acctname,newname); if (tn){ tn->SetStatus(status); tn->SrcRid(rida); tn->TgtRid(ridb); tn->Type(type); if ( ridb != 0 ) accts_resolved++; accts++; TNodeListSortable::InsertBottom((TNode *)tn); }} void InsertLastWithSid(const LPWSTR acctname, LPCWSTR srcdomainsid, LPCWSTR srcdomainname, DWORD rida, const LPWSTR newname, LPCWSTR tgtdomainsid, LPCWSTR tgtdomainname, DWORD ridb, short type = 0, DWORD status = TRidNode::DEFAULT) { TRidNode * tn = new (acctname,newname) TRidNode(acctname,newname); if (tn){ tn->SetStatus(status); tn->SrcRid(rida); tn->TgtRid(ridb); tn->SrcDomSid(srcdomainsid); tn->TgtDomSid(tgtdomainsid); tn->SrcDomName(srcdomainname); tn->TgtDomName(tgtdomainname); tn->Type(type); if ( ridb != 0 ) accts_resolved++; accts++; TNodeListSortable::InsertBottom((TNode *)tn); }} TAcctNode * Lookup(const PSID psid); // sid lookup functions TAcctNode * LookupWODomain(const PSID psid); // sid lookup functions LPWSTR GetName(const PSID psid); // helper methods PSID GetTgtSid(TAcctNode const * tnode) ; // "Get" functions DWORD SizeDiff(const TAcctNode *tnode) const ; // returns max( 0 , (length(to_sid) - length(from_sid)) ) void Display(bool summary, bool detail); void ReportToVarSet(IVarSet * pVarSet,bool summary, bool detail); PSID GetTgtSid(const PSID psid) { return GetTgtSid(Lookup(psid)); } void CopyDomainInfo( TSDRidCache const * other); PSID GetTgtSidWODomain(TAcctNode const * tnode); // "Get" functions PSID GetTgtSidWODomain(const PSID psid); // "Get" functions DWORD GetNumAccts() const {return accts; } DWORD GetNumResolvedAccts() const { return accts_resolved; } void Clear(); void SetSourceAndTargetDomains(WCHAR const * src, WCHAR const * tgt) { SetDomainInfo(src,true); SetDomainInfo(tgt,false); } void SetSourceAndTargetDomainsWithSids(WCHAR const * src, WCHAR const * srcSid, WCHAR const * tgt,WCHAR const * tgtSid) { SetDomainInfoWithSid(src,srcSid,true); SetDomainInfoWithSid(tgt,tgtSid,false); } void ReportAccountReferences(WCHAR const * filename); BOOL IsInitialized() { return from_sid!=NULL && to_sid!=NULL; } void VerifyTargetSids(); protected: int SetDomainInfo(WCHAR const * domname, bool firstdom); int SetDomainInfoWithSid(WCHAR const * domainName, WCHAR const * domainSid, bool firstdom); }; class TGeneralCache : public TAccountCache { protected: DWORD accts; // statistical stuff DWORD accts_resolved; public: TGeneralCache(); ~TGeneralCache(); TAcctNode * Lookup(const PSID psid) ; // sid lookup functions LPWSTR GetName(const PSID psid) ; BOOL Insert(const LPWSTR acctname1,const LPWSTR acctname2,PSID sid1, PSID sid2); PSID GetTgtSid(const TAcctNode* tnode) { return ((TGeneralSidNode *)tnode)->TgtSid(); } DWORD SizeDiff(const TAcctNode *tnode) const { return ((TGeneralSidNode *)tnode)->SizeDiff(); } // returns max( 0 , (length(to_sid) - length(from_sid)) ) }; // Global Functions struct SDRDomainInfo { bool valid; PSID domain_sid; WCHAR domain_name[80]; WCHAR dc_name[80]; UCHAR nsubs; }; int vRidComp(const TNode * tn, const void * v1); int vNameComp(const TNode * tn, const void * v1); int vTargetNameComp(const TNode * tn, const void * v1); int RidComp(const TNode * n1, const TNode * n2); int CompN(const TNode * n1, const TNode * n2); int CompTargetN(const TNode * n1, const TNode * n2); void DisplaySid(const PSID); // displays the contents of a SID void DisplaySid(const PSID,TAccountCache *); // displays the acct name if in cache, or void SetDomainInfoStruct( WCHAR const * domname, // in -name of domain SDRDomainInfo * info // in -struct to put info into ); void SetDomainInfoStructFromSid( PSID pSid, // in -sid for domain SDRDomainInfo * info // in -struct to put info into ); PSID DomainizeSid(PSID psid,BOOL freeOldSid); #endif