1500 lines
47 KiB
C++
1500 lines
47 KiB
C++
|
//#pragma title ("SidCache.hpp -- Cache, Tree of SIDs")
|
||
|
/*
|
||
|
Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
|
||
|
===============================================================================
|
||
|
Module - sidcache.cpp
|
||
|
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 -
|
||
|
===============================================================================
|
||
|
*/
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include <malloc.h>
|
||
|
#include <winbase.h>
|
||
|
#include <lm.h>
|
||
|
#include <lmaccess.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#include "common.hpp"
|
||
|
#include "ErrDct.hpp"
|
||
|
#include "Ustring.hpp"
|
||
|
#include "sidcache.hpp"
|
||
|
|
||
|
#include "CommaLog.hpp"
|
||
|
#include "TxtSid.h"
|
||
|
#include "ResStr.h"
|
||
|
#include "EaLen.hpp"
|
||
|
#include "LSAUtils.h" // For GetDomainDCName
|
||
|
|
||
|
// from sdresolve.hpp
|
||
|
extern BOOL BuiltinRid(DWORD rid);
|
||
|
extern DWORD OpenDomain(WCHAR const * domain);
|
||
|
|
||
|
extern TErrorDct err;
|
||
|
extern bool silent;
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
/* vRidComp is used as a compare function for TSidNode Trees
|
||
|
// It searches for v1 in the ridA field. The Tree must be sorted with RidComp before using this
|
||
|
// search fn.
|
||
|
// Return values: 0 tn->ridA == v1
|
||
|
// 1 tn->ridA < v1
|
||
|
// -1 tn->ridA > v1
|
||
|
//
|
||
|
/**************************************************************************************************/
|
||
|
int
|
||
|
vRidComp(
|
||
|
const TNode * tn, // in -TSidNode
|
||
|
const void * v1 // in -DWORD ridA value to look for
|
||
|
)
|
||
|
{
|
||
|
DWORD rid1;
|
||
|
DWORD rid2;
|
||
|
TRidNode * n2;
|
||
|
int retval;
|
||
|
assert( tn ); // we should always be given valid inputs
|
||
|
assert( v1 );
|
||
|
|
||
|
n2 = (TRidNode *)tn;
|
||
|
rid1 = n2->SrcRid();
|
||
|
rid2 = *(DWORD *)v1;
|
||
|
if ( rid1 < rid2 )
|
||
|
{
|
||
|
retval = -1;
|
||
|
}
|
||
|
if (rid1 > rid2)
|
||
|
{
|
||
|
retval = 1;
|
||
|
}
|
||
|
if ( rid1 == rid2) // ( rid1 == rid2 )
|
||
|
{
|
||
|
retval = 0;
|
||
|
}
|
||
|
return retval;
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* RidComp: used as a compare function for TSidNode Trees
|
||
|
|
||
|
It compares the ridA fields of SIDTNodes
|
||
|
|
||
|
Return Values:
|
||
|
0 t1->ridA == t2->ridA
|
||
|
1 t1->ridA > t2->ridA
|
||
|
-1 t1->ridA < t2->ridA
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
|
||
|
int RidComp(
|
||
|
const TNode * t1, //in -first node to compare
|
||
|
const TNode * t2 //in -second node to compare
|
||
|
)
|
||
|
{
|
||
|
assert( t1 );
|
||
|
assert( t2 );
|
||
|
|
||
|
TRidNode * st1 = (TRidNode *) t1;
|
||
|
TRidNode * st2 = (TRidNode *) t2;
|
||
|
DWORD rid1 = st1->SrcRid();
|
||
|
DWORD rid2 = st2->SrcRid();
|
||
|
int retval;
|
||
|
|
||
|
if ( rid1 < rid2 )
|
||
|
{
|
||
|
retval = -1;
|
||
|
}
|
||
|
if (rid1 > rid2)
|
||
|
{
|
||
|
retval = 1;
|
||
|
}
|
||
|
if ( rid1 == rid2 ) // (rid1 == rid2)
|
||
|
{
|
||
|
retval = 0;
|
||
|
}
|
||
|
return retval;
|
||
|
}
|
||
|
/***************************************************************************************************
|
||
|
vNameComp: used as a compare function for TSidNode trees
|
||
|
|
||
|
It compares a UNICODE string, with the acct_name field in the node
|
||
|
|
||
|
Return Values:
|
||
|
0 tn->acct_name == actname
|
||
|
1 tn->acct_name < actname
|
||
|
-1 tn->acct_name > actname
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
|
||
|
int
|
||
|
vNameComp(
|
||
|
const TNode * tn, //in -tree node
|
||
|
const void * actname //in -name to look for
|
||
|
)
|
||
|
|
||
|
{
|
||
|
assert( tn );
|
||
|
assert( actname );
|
||
|
|
||
|
LPWSTR str1 = ((TRidNode *)tn)->GetAcctName();
|
||
|
LPWSTR str2 = (LPWSTR) actname;
|
||
|
|
||
|
return UStrICmp(str1,str2);
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* CompN: used as a compare function for TSidNode Trees
|
||
|
|
||
|
It compares the acct_name fields of SIDTNodes
|
||
|
|
||
|
Return Values:
|
||
|
0 t1->acct_name == t2->acct_name
|
||
|
1 t1->acct_name > t2->acct_name
|
||
|
-1 t1->acct_name < t2->acct_name
|
||
|
|
||
|
Error Handling:
|
||
|
if given bad inputs, CompN displays an error message and returns 0
|
||
|
/***************************************************************************************************/
|
||
|
|
||
|
int
|
||
|
CompN(
|
||
|
const TNode * v1, //in -first node to compare
|
||
|
const TNode * v2 //in -second node to compare
|
||
|
)
|
||
|
{
|
||
|
assert( v1 );
|
||
|
assert( v2 );
|
||
|
|
||
|
TRidNode * t1 = (TRidNode *)v1;
|
||
|
TRidNode * t2 = (TRidNode *)v2;
|
||
|
|
||
|
return UStrICmp(t1->GetAcctName(),t2->GetAcctName());
|
||
|
}
|
||
|
|
||
|
int
|
||
|
vTargetNameComp(
|
||
|
const TNode * tn, //in -tree node
|
||
|
const void * actname //in -name to look for
|
||
|
)
|
||
|
|
||
|
{
|
||
|
assert( tn );
|
||
|
assert( actname );
|
||
|
|
||
|
LPWSTR str1 = ((TRidNode *)tn)->GetTargetAcctName();
|
||
|
LPWSTR str2 = (LPWSTR) actname;
|
||
|
|
||
|
return UStrICmp(str1,str2);
|
||
|
}
|
||
|
int
|
||
|
CompTargetN(
|
||
|
const TNode * v1, //in -first node to compare
|
||
|
const TNode * v2 //in -second node to compare
|
||
|
)
|
||
|
{
|
||
|
assert( v1 );
|
||
|
assert( v2 );
|
||
|
|
||
|
TRidNode * t1 = (TRidNode *)v1;
|
||
|
TRidNode * t2 = (TRidNode *)v2;
|
||
|
|
||
|
return UStrICmp(t1->GetTargetAcctName(),t2->GetTargetAcctName());
|
||
|
}
|
||
|
|
||
|
int
|
||
|
TSidCompare(
|
||
|
PSID const sid1, // in - first sid to compare
|
||
|
PSID const sid2 // in - second sid to compare
|
||
|
)
|
||
|
{
|
||
|
DWORD len1,
|
||
|
len2;
|
||
|
int retval = 0;
|
||
|
|
||
|
len1 = GetLengthSid(sid1);
|
||
|
len2 = GetLengthSid(sid2);
|
||
|
|
||
|
if ( len1 < len2 )
|
||
|
{
|
||
|
retval = -1;
|
||
|
}
|
||
|
if ( len1 > len2 )
|
||
|
{
|
||
|
retval = 1;
|
||
|
}
|
||
|
if ( len1 == len2 )
|
||
|
{
|
||
|
retval = memcmp(sid1,sid2,len1);
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
/**************************************************************************************************
|
||
|
vSidComp: used as a compare function for TSidNode trees
|
||
|
|
||
|
It compares a UNICODE string, with the acct_name field in the node
|
||
|
|
||
|
Return Values:
|
||
|
0 tn->acct_name == actname
|
||
|
1 tn->acct_name < actname
|
||
|
-1 tn->acct_name > actname
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
int
|
||
|
vSidComp(
|
||
|
const TNode * tn, //in -tree node
|
||
|
const void * val //in -sid to look for
|
||
|
)
|
||
|
{
|
||
|
PSID sid1 = ((TGeneralSidNode *)tn)->SrcSid();
|
||
|
PSID sid2 = (PSID)val;
|
||
|
|
||
|
return TSidCompare(sid1,sid2);
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
nSidComp(
|
||
|
const TNode * v1, //in -first node to compare
|
||
|
const TNode * v2 //in -second node to compare
|
||
|
)
|
||
|
{
|
||
|
TGeneralSidNode * t1 = (TGeneralSidNode *)v1;
|
||
|
TGeneralSidNode * t2 = (TGeneralSidNode *)v2;
|
||
|
|
||
|
return TSidCompare(t1->SrcSid(), t2->SrcSid());
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************************************/
|
||
|
// TSidNode Implementation
|
||
|
/*******************************************************************************************************/
|
||
|
|
||
|
TGeneralCache::TGeneralCache()
|
||
|
{
|
||
|
CompareSet(&nSidComp);
|
||
|
TypeSetTree();
|
||
|
}
|
||
|
|
||
|
TGeneralCache::~TGeneralCache()
|
||
|
{
|
||
|
DeleteAllListItems(TGeneralSidNode);
|
||
|
}
|
||
|
|
||
|
void * TRidNode::operator new(size_t sz, const LPWSTR oldname, const LPWSTR newname)
|
||
|
{
|
||
|
int nlen = UStrLen(newname) + UStrLen(oldname) + 1;
|
||
|
void * node = malloc(sz + nlen * (sizeof WCHAR) );
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
TAcctNode::TAcctNode()
|
||
|
{
|
||
|
owner_changes = 0;
|
||
|
group_changes = 0;
|
||
|
ace_changes = 0;
|
||
|
sace_changes = 0;
|
||
|
}
|
||
|
|
||
|
WCHAR * // ret- domain part of name
|
||
|
GetDomainName(
|
||
|
WCHAR * name // in - domain\\account name
|
||
|
)
|
||
|
{
|
||
|
assert (name);
|
||
|
|
||
|
int i;
|
||
|
int len = UStrLen(name);
|
||
|
WCHAR * domain;
|
||
|
|
||
|
for (i = 2 ; name[i] != '\\' && i < len ; i++ )
|
||
|
;
|
||
|
if ( i < len )
|
||
|
{
|
||
|
domain = new WCHAR[i+1];
|
||
|
if (!domain)
|
||
|
return NULL;
|
||
|
UStrCpy(domain,name,i);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
domain = NULL;
|
||
|
}
|
||
|
return domain;
|
||
|
}
|
||
|
|
||
|
TGeneralSidNode::TGeneralSidNode(
|
||
|
const LPWSTR name1, // in - account name on source domain
|
||
|
const LPWSTR name2 // in - account name on target domain
|
||
|
)
|
||
|
{
|
||
|
assert (name1 && name2);
|
||
|
assert (*name1 && *name2);
|
||
|
|
||
|
WCHAR * domname;
|
||
|
|
||
|
memset(&ownerStats,0,(sizeof ownerStats));
|
||
|
memset(&groupStats,0,(sizeof ownerStats));
|
||
|
memset(&daclStats,0,(sizeof ownerStats));
|
||
|
memset(&saclStats,0,(sizeof ownerStats));
|
||
|
|
||
|
src_acct_name = new WCHAR[UStrLen(name1)+1];
|
||
|
if (!src_acct_name)
|
||
|
return;
|
||
|
safecopy(src_acct_name,name1);
|
||
|
tgt_acct_name = new WCHAR[UStrLen(name2) + 1];
|
||
|
if (!tgt_acct_name)
|
||
|
return;
|
||
|
safecopy(tgt_acct_name,name2);
|
||
|
SDRDomainInfo info;
|
||
|
domname = GetDomainName(name1);
|
||
|
if (!domname)
|
||
|
return;
|
||
|
SetDomainInfoStruct(domname,&info);
|
||
|
if ( info.valid )
|
||
|
{
|
||
|
src_domain = new WCHAR[UStrLen(info.domain_name)];
|
||
|
if (!src_domain)
|
||
|
return;
|
||
|
safecopy(src_domain, info.domain_name);
|
||
|
// src_dc = info.dc_name;
|
||
|
src_nsubs = info.nsubs;
|
||
|
src_sid = info.domain_sid;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite(ErrE,DCT_MSG_DOMAIN_NOT_FOUND_S,domname);
|
||
|
src_domain = NULL;
|
||
|
// src_dc = NULL;
|
||
|
src_nsubs = 0;
|
||
|
src_sid = NULL;
|
||
|
}
|
||
|
delete domname;
|
||
|
domname = GetDomainName(name2);
|
||
|
if (!domname)
|
||
|
return;
|
||
|
SetDomainInfoStruct(domname,&info);
|
||
|
if ( info.valid )
|
||
|
{
|
||
|
tgt_domain = new WCHAR[UStrLen(info.domain_name)];
|
||
|
if (!tgt_domain)
|
||
|
return;
|
||
|
safecopy(tgt_domain, info.domain_name);
|
||
|
tgt_nsubs = info.nsubs;
|
||
|
tgt_sid = info.domain_sid;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite(ErrE,DCT_MSG_DOMAIN_NOT_FOUND_S,domname);
|
||
|
tgt_domain = NULL;
|
||
|
tgt_nsubs = 0;
|
||
|
tgt_sid = NULL;
|
||
|
}
|
||
|
sizediff = GetSidLengthRequired(tgt_nsubs) - GetSidLengthRequired(src_nsubs);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
WCHAR * // ret- textual representation of sid
|
||
|
BuildSidString(
|
||
|
PSID pSid // in - sid
|
||
|
)
|
||
|
{
|
||
|
WCHAR * buf;
|
||
|
DWORD bufLen = 0;
|
||
|
|
||
|
GetTextualSid(pSid,NULL,&bufLen);
|
||
|
|
||
|
buf = new WCHAR[bufLen+1];
|
||
|
if (!buf)
|
||
|
return NULL;
|
||
|
|
||
|
if ( ! GetTextualSid(pSid,buf,&bufLen) )
|
||
|
{
|
||
|
wcscpy(buf,L"<Unknown>");
|
||
|
}
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
TGeneralSidNode::TGeneralSidNode(
|
||
|
const PSID pSid1, // in - source domain sid
|
||
|
const PSID pSid2 // in - target domain sid
|
||
|
)
|
||
|
{
|
||
|
WCHAR domain[LEN_Domain];
|
||
|
WCHAR account[LEN_Account];
|
||
|
DWORD lenDomain = DIM(domain);
|
||
|
DWORD lenAccount = DIM(account);
|
||
|
SID_NAME_USE snu;
|
||
|
DWORD nBytes;
|
||
|
|
||
|
memset(&ownerStats,0,(sizeof ownerStats));
|
||
|
memset(&groupStats,0,(sizeof ownerStats));
|
||
|
memset(&daclStats,0,(sizeof ownerStats));
|
||
|
memset(&saclStats,0,(sizeof ownerStats));
|
||
|
|
||
|
|
||
|
// Source domain
|
||
|
if ( pSid1 )
|
||
|
{
|
||
|
// Make a copy of the SID
|
||
|
src_nsubs = *GetSidSubAuthorityCount(pSid1);
|
||
|
nBytes = GetSidLengthRequired(src_nsubs);
|
||
|
src_sid = new BYTE[nBytes];
|
||
|
if (!src_sid)
|
||
|
return;
|
||
|
CopySid(nBytes,src_sid,pSid1);
|
||
|
// Look up name for source SID
|
||
|
if ( LookupAccountSid(NULL,pSid1,account,&lenAccount,domain,&lenDomain,&snu) )
|
||
|
{
|
||
|
if ( lenAccount == 0 && snu == SidTypeDeletedAccount )
|
||
|
{
|
||
|
WCHAR * buf = BuildSidString(pSid1);
|
||
|
if (!buf)
|
||
|
return;
|
||
|
swprintf(account,L"<Deleted Account (%s)>",buf);
|
||
|
delete buf;
|
||
|
}
|
||
|
src_acct_name = new WCHAR[UStrLen(domain) + 1 + UStrLen(account)+1];
|
||
|
if (!src_acct_name)
|
||
|
return;
|
||
|
swprintf(src_acct_name,L"%s\\%s",domain,account);
|
||
|
src_domain = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
src_acct_name = BuildSidString(pSid1);
|
||
|
if (!src_acct_name)
|
||
|
return;
|
||
|
src_domain = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
src_nsubs = 0;
|
||
|
src_sid = NULL;
|
||
|
src_acct_name = NULL;
|
||
|
src_domain = NULL;
|
||
|
}
|
||
|
|
||
|
// Target domain
|
||
|
if ( pSid2 )
|
||
|
{
|
||
|
tgt_nsubs = *GetSidSubAuthorityCount(pSid2);
|
||
|
nBytes = GetSidLengthRequired(tgt_nsubs);
|
||
|
tgt_sid = new BYTE[nBytes];
|
||
|
if (!tgt_sid)
|
||
|
return;
|
||
|
CopySid(nBytes,tgt_sid,pSid2);
|
||
|
if ( LookupAccountSid(NULL,pSid2,account,&lenAccount,domain,&lenDomain,&snu) )
|
||
|
{
|
||
|
tgt_acct_name = new WCHAR[UStrLen(domain) + 1 + UStrLen(account)+1];
|
||
|
if (!tgt_acct_name)
|
||
|
return;
|
||
|
swprintf(tgt_acct_name,L"%s\\%s",domain,account);
|
||
|
tgt_domain = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tgt_acct_name = NULL;
|
||
|
tgt_domain = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tgt_nsubs = 0;
|
||
|
tgt_sid = NULL;
|
||
|
tgt_acct_name = NULL;
|
||
|
tgt_domain = NULL;
|
||
|
}
|
||
|
sizediff = GetSidLengthRequired(src_nsubs) - GetSidLengthRequired(tgt_nsubs);
|
||
|
}
|
||
|
|
||
|
TGeneralSidNode::~TGeneralSidNode()
|
||
|
{
|
||
|
if ( src_acct_name )
|
||
|
delete src_acct_name;
|
||
|
if ( tgt_acct_name )
|
||
|
delete tgt_acct_name;
|
||
|
if ( src_sid )
|
||
|
delete src_sid;
|
||
|
if ( tgt_sid )
|
||
|
delete tgt_sid;
|
||
|
if ( src_domain )
|
||
|
delete src_domain;
|
||
|
if ( tgt_domain )
|
||
|
delete tgt_domain;
|
||
|
}
|
||
|
|
||
|
TRidNode::TRidNode(
|
||
|
const LPWSTR oldacctname, // in -source account name
|
||
|
const LPWSTR newacctname // in -target account name
|
||
|
)
|
||
|
{
|
||
|
|
||
|
srcRid = 0;
|
||
|
tgtRid = 0;
|
||
|
tgtRidIsValid = false;
|
||
|
|
||
|
if ( ! newacctname )
|
||
|
{
|
||
|
acct_len = -1;
|
||
|
swprintf(acct_name,L"%s",oldacctname);
|
||
|
acct_name[UStrLen(acct_name)+1] = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
acct_len = UStrLen(oldacctname);
|
||
|
swprintf(acct_name,L"%s:%s",oldacctname,newacctname);
|
||
|
acct_name[acct_len] = 0;
|
||
|
}
|
||
|
|
||
|
wcscpy(srcDomSid,L"");
|
||
|
wcscpy(tgtDomSid,L"");
|
||
|
wcscpy(srcDomName,L"");
|
||
|
wcscpy(tgtDomName,L"");
|
||
|
|
||
|
}
|
||
|
TRidNode::~TRidNode()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************************************/
|
||
|
// TSidCache Implementation
|
||
|
/*******************************************************************************************************/
|
||
|
|
||
|
void
|
||
|
TSDRidCache::ReportAccountReferences(
|
||
|
WCHAR const * filename // in - filename to record account references
|
||
|
)
|
||
|
{
|
||
|
if ( m_otherAccounts )
|
||
|
{
|
||
|
CommaDelimitedLog resultLog;
|
||
|
|
||
|
if ( resultLog.LogOpen(filename,FALSE) )
|
||
|
{
|
||
|
|
||
|
TGeneralSidNode * gnode;
|
||
|
TNodeTreeEnum tEnum;
|
||
|
|
||
|
for ( gnode = (TGeneralSidNode *)tEnum.OpenFirst(m_otherAccounts) ; gnode ; gnode = (TGeneralSidNode*)tEnum.Next() )
|
||
|
{
|
||
|
TSDFileDirCell * pOwner = gnode->GetOwnerStats();
|
||
|
TSDFileDirCell * pGroup = gnode->GetGroupStats();
|
||
|
TSDFileDirCell * pDacl = gnode->GetDaclStats();
|
||
|
TSDFileDirCell * pSacl = gnode->GetSaclStats();
|
||
|
WCHAR * sAccountSid = BuildSidString(gnode->SrcSid());
|
||
|
if (!sAccountSid)
|
||
|
return;
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_File),
|
||
|
pOwner->file,
|
||
|
pGroup->file,
|
||
|
pDacl->file,
|
||
|
pSacl->file );
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_Dir),
|
||
|
pOwner->dir,
|
||
|
pGroup->dir,
|
||
|
pDacl->dir,
|
||
|
pSacl->dir );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_Share),
|
||
|
pOwner->share,
|
||
|
pGroup->share,
|
||
|
pDacl->share,
|
||
|
pSacl->share );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_Mailbox),
|
||
|
pOwner->mailbox,
|
||
|
pGroup->mailbox,
|
||
|
pDacl->mailbox,
|
||
|
pSacl->mailbox );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_Container),
|
||
|
pOwner->container,
|
||
|
pGroup->container,
|
||
|
pDacl->container,
|
||
|
pSacl->container );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_Member),
|
||
|
pOwner->member,
|
||
|
pGroup->member,
|
||
|
pDacl->member,
|
||
|
pSacl->member );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_UserRight),
|
||
|
pOwner->userright,
|
||
|
pGroup->userright,
|
||
|
pDacl->userright,
|
||
|
pSacl->userright );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_RegKey),
|
||
|
pOwner->regkey,
|
||
|
pGroup->regkey,
|
||
|
pDacl->regkey,
|
||
|
pSacl->regkey );
|
||
|
|
||
|
resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
|
||
|
sAccountSid,
|
||
|
GET_STRING(IDS_STReference_Printer),
|
||
|
pOwner->printer,
|
||
|
pGroup->printer,
|
||
|
pDacl->printer,
|
||
|
pSacl->printer );
|
||
|
|
||
|
if (sAccountSid)
|
||
|
delete sAccountSid;
|
||
|
}
|
||
|
tEnum.Close();
|
||
|
resultLog.LogClose();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite(ErrE,DCT_MSG_COULD_NOT_OPEN_RESULT_FILE_S,filename);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
TSDRidCache::ReportToVarSet(
|
||
|
IVarSet * pVarSet, // in -varset to write information to
|
||
|
bool summary, // in -flag: whether to print summary information
|
||
|
bool detail // in -flag: whether to print detailed stats
|
||
|
)
|
||
|
{
|
||
|
TNodeTreeEnum tEnum;
|
||
|
TRidNode * tnode;
|
||
|
long users=0;
|
||
|
long lgroups=0;
|
||
|
long ggroups=0;
|
||
|
long other=0;
|
||
|
long unres_users=0;
|
||
|
long unres_lg=0;
|
||
|
long unres_gg=0;
|
||
|
long unres_other=0;
|
||
|
long total=0;
|
||
|
long n = 0;
|
||
|
// sort the cache by names before printing the report
|
||
|
Sort(&CompN);
|
||
|
Balance();
|
||
|
if ( detail )
|
||
|
{
|
||
|
for ( tnode = (TRidNode *)tEnum.OpenFirst(this) ; tnode ; tnode = (TRidNode *)tEnum.Next() )
|
||
|
{
|
||
|
if( tnode->ReportToVarSet(pVarSet,n) )
|
||
|
{
|
||
|
n++;
|
||
|
}
|
||
|
switch ( tnode->Type() )
|
||
|
{
|
||
|
case EA_AccountGroup: ggroups++; break;
|
||
|
case EA_AccountGGroup: ggroups++; break;
|
||
|
case EA_AccountLGroup: lgroups++; break;
|
||
|
case EA_AccountUser: users++; break;
|
||
|
default:
|
||
|
other++;
|
||
|
err.MsgWrite(0,DCT_MSG_BAD_ACCOUNT_TYPE_SD,tnode->GetAcctName(),tnode->Type() );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
tEnum.Close();
|
||
|
|
||
|
if ( m_otherAccounts )
|
||
|
{
|
||
|
TGeneralSidNode * gnode;
|
||
|
|
||
|
for ( gnode = (TGeneralSidNode *)tEnum.OpenFirst(m_otherAccounts) ; gnode ; gnode = (TGeneralSidNode*)tEnum.Next() )
|
||
|
{
|
||
|
if( gnode->ReportToVarSet(pVarSet,n) )
|
||
|
{
|
||
|
n++;
|
||
|
}
|
||
|
other++;
|
||
|
}
|
||
|
}
|
||
|
total = users+lgroups+ggroups+other + unres_gg + unres_lg + unres_users + unres_other;
|
||
|
|
||
|
pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumUsers),users);
|
||
|
pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumGlobalGroups),ggroups);
|
||
|
pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumLocalGroups),lgroups);
|
||
|
pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumOther),other);
|
||
|
|
||
|
}
|
||
|
// re-sort by rid after printing the report
|
||
|
Sort(&RidComp);
|
||
|
Balance();
|
||
|
}
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
/* TSidCache::Display: Displays the summary information, and/or contents of the TSidCache tree
|
||
|
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
void
|
||
|
TSDRidCache::Display(
|
||
|
bool summary, // in -flag: whether to print summary information
|
||
|
bool detail // in -flag: whether to print detailed stats
|
||
|
)
|
||
|
{
|
||
|
TNodeTreeEnum tEnum;
|
||
|
TRidNode * tnode;
|
||
|
long users=0;
|
||
|
long lgroups=0;
|
||
|
long ggroups=0;
|
||
|
long other=0;
|
||
|
long unres_users=0;
|
||
|
long unres_lg=0;
|
||
|
long unres_gg=0;
|
||
|
long unres_other=0;
|
||
|
long total=0;
|
||
|
|
||
|
// sort the cache by names before printing the report
|
||
|
Sort(&CompN);
|
||
|
Balance();
|
||
|
if ( detail )
|
||
|
{
|
||
|
err.MsgWrite(0,DCT_MSG_ACCOUNT_DETAIL_HEADER);
|
||
|
for ( tnode = (TRidNode *)tEnum.OpenFirst(this) ; tnode ; tnode = (TRidNode *)tEnum.Next() )
|
||
|
{
|
||
|
tnode->DisplayStats();
|
||
|
switch ( tnode->Type() )
|
||
|
{
|
||
|
case EA_AccountGroup: ggroups++; break;
|
||
|
case EA_AccountGGroup: ggroups++; break;
|
||
|
case EA_AccountLGroup: lgroups++; break;
|
||
|
case EA_AccountUser: users++; break;
|
||
|
default:
|
||
|
other++;
|
||
|
err.MsgWrite(0,DCT_MSG_BAD_ACCOUNT_TYPE_SD,tnode->GetAcctName(),tnode->Type() );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
total = users+lgroups+ggroups+other + unres_gg + unres_lg + unres_users + unres_other;
|
||
|
|
||
|
err.MsgWrite(0,DCT_MSG_ACCOUNT_DETAIL_FOOTER);
|
||
|
}
|
||
|
if ( summary )
|
||
|
{
|
||
|
err.MsgWrite(0,DCT_MSG_ACCOUNT_USER_GROUP_COUNT_DD,users+unres_users,ggroups+unres_gg+lgroups+unres_lg);
|
||
|
err.MsgWrite(0,DCT_MSG_ACCOUNT_STATUS_COUNT_DDD,accts,accts_resolved,accts - accts_resolved);
|
||
|
}
|
||
|
// re-sort by rid after printing the report
|
||
|
Sort(&RidComp);
|
||
|
Balance();
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* GetSidB:
|
||
|
|
||
|
Builds a sid containing the Identifier Authority from the target-domain SID, along with the
|
||
|
RID from the ridB field of the supplied node.
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
|
||
|
PSID // ret -the domain B sid for the account referenced in tnode
|
||
|
TSDRidCache::GetTgtSid(
|
||
|
const TAcctNode * anode // in -node to copy RID from
|
||
|
)
|
||
|
{
|
||
|
|
||
|
TRidNode * tnode = (TRidNode *)anode;
|
||
|
|
||
|
assert( tnode );
|
||
|
assert( tnode->IsValidOnTgt() );
|
||
|
assert( to_sid ); // we can't resolve if we don't have domain B sid
|
||
|
|
||
|
PDWORD rid;
|
||
|
DWORD sidsize = GetSidLengthRequired(to_nsubs);
|
||
|
PSID newsid = malloc(sidsize);
|
||
|
|
||
|
if (newsid)
|
||
|
{
|
||
|
CopySid(sidsize,newsid,to_sid); // copy the domain B sid
|
||
|
rid = GetSidSubAuthority(newsid,to_nsubs -1);
|
||
|
|
||
|
assert( (*rid) == -1 ); // FillCache makes sure to_sid always ends with -1(f...f)
|
||
|
|
||
|
(*rid)=tnode->TgtRid(); // replace last sub with this node's RID
|
||
|
}
|
||
|
|
||
|
return newsid;
|
||
|
}
|
||
|
|
||
|
// GetTgtSidWODomain:
|
||
|
// Returns the target sid for this node without having the target domain information
|
||
|
// filled in (like when we reACl using a sID mapping file).
|
||
|
PSID // ret -the domain B sid for the account referenced in tnode
|
||
|
TSDRidCache::GetTgtSidWODomain(
|
||
|
const TAcctNode * anode // in -node to copy RID from
|
||
|
)
|
||
|
{
|
||
|
|
||
|
TRidNode * tnode = (TRidNode *)anode;
|
||
|
|
||
|
assert( tnode );
|
||
|
assert( tnode->IsValidOnTgt() );
|
||
|
|
||
|
PDWORD rid;
|
||
|
|
||
|
//get and convert the target domain sid stored in the node to a PSID
|
||
|
PSID pTgtSid = SidFromString(tnode->GetTgtDomSid());
|
||
|
PUCHAR pCount = GetSidSubAuthorityCount(pTgtSid);
|
||
|
DWORD nSub = (DWORD)(*pCount) - 1;
|
||
|
|
||
|
rid = GetSidSubAuthority(pTgtSid,nSub);
|
||
|
|
||
|
assert( (*rid) == -1 ); // FillCache makes sure to_sid always ends with -1(f...f)
|
||
|
|
||
|
(*rid)=tnode->TgtRid(); // replace last sub with this node's RID
|
||
|
|
||
|
return pTgtSid;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
/* Display sid - Displays the contents of a SID.
|
||
|
The sid given is assumed to be a valid SID
|
||
|
/***************************************************************************************************/
|
||
|
void
|
||
|
DisplaySid(
|
||
|
const PSID ps // in -pointer to the sid to display
|
||
|
)
|
||
|
{
|
||
|
assert( ps );
|
||
|
|
||
|
PUCHAR ch = GetSidSubAuthorityCount(ps);
|
||
|
DWORD nsubs = *ch;
|
||
|
DWORD i;
|
||
|
PSID_IDENTIFIER_AUTHORITY ida = GetSidIdentifierAuthority(ps);
|
||
|
|
||
|
for ( i = 0 ; i < 6 ; i++ ) // 6 value fields in IA
|
||
|
{
|
||
|
printf("%ld, ",ida->Value[i]);
|
||
|
}
|
||
|
printf("\n%ld Subs: ",nsubs);
|
||
|
for ( i = 0 ; i < nsubs ; i++ ) // print subauthority values
|
||
|
{
|
||
|
printf("\nS[%d]= %ld ",i,*GetSidSubAuthority(ps,i));
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* DisplaySid: If the sid is found in the cache, display the associated name, otherwise display
|
||
|
the sid contents.
|
||
|
ps and C are assumed to be valid.
|
||
|
/***************************************************************************************************/
|
||
|
void
|
||
|
DisplaySid(
|
||
|
const PSID ps, // in- sid to display
|
||
|
TAccountCache * C // in- TSidCache to look for sid in
|
||
|
)
|
||
|
{
|
||
|
assert ( ps );
|
||
|
|
||
|
if ( !C )
|
||
|
{
|
||
|
DisplaySid(ps);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WCHAR * name = C->GetName(ps);
|
||
|
if ( name )
|
||
|
{
|
||
|
err.MsgWrite(0,DCT_MSG_GENERIC_S,name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DisplaySid(ps);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
//DispSidInfo: Displays contents of the TSidNode
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
void
|
||
|
TRidNode::DisplaySidInfo() const
|
||
|
{
|
||
|
err.DbgMsgWrite(0,L"\nRid A= %ld \nName= %S \nRid B= %ld\n",srcRid,acct_name,tgtRid);
|
||
|
err.DbgMsgWrite(0,L"Owner changes: %ld\n",owner_changes);
|
||
|
err.DbgMsgWrite(0,L"Group changes: %ld\n",group_changes);
|
||
|
err.DbgMsgWrite(0,L"ACE changes: %ld\n",ace_changes);
|
||
|
err.DbgMsgWrite(0,L"SACE changes: %ld\n",sace_changes);
|
||
|
if ( !tgtRidIsValid )
|
||
|
err.DbgMsgWrite(0,L"Target RID is not valid\n");
|
||
|
}
|
||
|
void
|
||
|
TAcctNode::DisplayStats() const
|
||
|
{
|
||
|
LPWSTR res;
|
||
|
if ( IsValidOnTgt() )
|
||
|
res = L"";
|
||
|
else
|
||
|
res = (WCHAR*)GET_BSTR(IDS_UNRESOLVED);
|
||
|
if (owner_changes || group_changes || ace_changes || sace_changes)
|
||
|
err.MsgWrite(0,DCT_MSG_ACCOUNT_REFS_DATA_SDDDDS,owner_changes,group_changes,ace_changes,sace_changes,res);
|
||
|
}
|
||
|
void
|
||
|
TRidNode::DisplayStats() const
|
||
|
{
|
||
|
LPWSTR res;
|
||
|
if ( IsValidOnTgt() )
|
||
|
res = L"";
|
||
|
else
|
||
|
res = (WCHAR*)GET_BSTR(IDS_UNRESOLVED);
|
||
|
#ifndef _DEBUG
|
||
|
if (owner_changes || group_changes || ace_changes || sace_changes )
|
||
|
err.MsgWrite(0,DCT_MSG_ACCOUNT_REFS_DATA_SDDDDS,acct_name,owner_changes,group_changes,ace_changes,sace_changes,res);
|
||
|
#else
|
||
|
if (owner_changes || group_changes || ace_changes || sace_changes || true)
|
||
|
err.DbgMsgWrite(0,L"%-35ls (%ld, %ld, %ld, %ld) %ls [%ld,%ld]",acct_name,owner_changes,group_changes,ace_changes,sace_changes,res,srcRid,tgtRid);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL // ret- TRUE if details reported, FALSE if skipped blank record
|
||
|
TAcctNode::ReportToVarSet(
|
||
|
IVarSet * pVarSet ,// in - VarSet to write data to
|
||
|
DWORD n // in - index of account in varset
|
||
|
)
|
||
|
{
|
||
|
BOOL bRecorded = FALSE;
|
||
|
|
||
|
if ( owner_changes || group_changes || ace_changes || sace_changes )
|
||
|
{
|
||
|
WCHAR key[200];
|
||
|
|
||
|
swprintf(key,L"Stats.Accounts.%ld.Name",n);
|
||
|
pVarSet->put(key,GetAcctName());
|
||
|
|
||
|
swprintf(key,L"Stats.Accounts.%ld.Owners",n);
|
||
|
pVarSet->put(key,(LONG)owner_changes);
|
||
|
|
||
|
swprintf(key,L"Stats.Accounts.%ld.Groups",n);
|
||
|
pVarSet->put(key,(LONG)group_changes);
|
||
|
|
||
|
swprintf(key,L"Stats.Accounts.%ld.ACEs",n);
|
||
|
pVarSet->put(key,(LONG)ace_changes);
|
||
|
|
||
|
swprintf(key,L"Stats.Accounts.%ld.SACEs",n);
|
||
|
pVarSet->put(key,(LONG)sace_changes);
|
||
|
|
||
|
swprintf(key,L"Stats.Accounts.%ld.Resolved",n);
|
||
|
if ( IsValidOnTgt() )
|
||
|
{
|
||
|
pVarSet->put(key,L"Yes");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pVarSet->put(key,L"No");
|
||
|
}
|
||
|
|
||
|
bRecorded = TRUE;
|
||
|
}
|
||
|
return bRecorded;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************************************/
|
||
|
/* SIDTCache Implementation */
|
||
|
/***************************************************************************************************/
|
||
|
TSDRidCache::TSDRidCache()
|
||
|
{
|
||
|
from_sid = NULL;
|
||
|
to_sid = NULL;
|
||
|
from_domain[0] = 0;
|
||
|
to_domain[0] = 0;
|
||
|
from_dc[0] = 0;
|
||
|
to_dc[0] = 0;
|
||
|
from_nsubs = 0;
|
||
|
to_nsubs = 0;
|
||
|
accts = 0;
|
||
|
accts_resolved = 0;
|
||
|
m_otherAccounts = NULL;
|
||
|
CompareSet(&CompN); //start with an empty tree, to be sorted by acct_name
|
||
|
TypeSetTree();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TSDRidCache::CopyDomainInfo(
|
||
|
TSDRidCache const * other
|
||
|
)
|
||
|
{
|
||
|
from_nsubs = other->from_nsubs;
|
||
|
to_nsubs = other->to_nsubs;
|
||
|
from_sid = NULL;
|
||
|
to_sid = NULL;
|
||
|
|
||
|
if ( other->from_sid )
|
||
|
from_sid = malloc(GetSidLengthRequired(from_nsubs));
|
||
|
if ( other->to_sid )
|
||
|
to_sid = malloc(GetSidLengthRequired(to_nsubs));
|
||
|
|
||
|
if ( from_sid )
|
||
|
CopySid(GetSidLengthRequired(from_nsubs),from_sid,other->from_sid);
|
||
|
if ( to_sid )
|
||
|
CopySid(GetSidLengthRequired(to_nsubs),to_sid,other->to_sid);
|
||
|
|
||
|
safecopy(from_domain,other->from_domain);
|
||
|
safecopy(to_domain,other->to_domain);
|
||
|
safecopy(from_dc,other->from_dc);
|
||
|
safecopy(to_dc,other->to_dc);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TSDRidCache::Clear()
|
||
|
{
|
||
|
TRidNode * node;
|
||
|
|
||
|
for ( node = (TRidNode *)Head() ; node ; Remove(node) , free(node), node = (TRidNode *)Head() )
|
||
|
;
|
||
|
|
||
|
accts = 0;
|
||
|
accts_resolved = 0;
|
||
|
}
|
||
|
|
||
|
TSDRidCache::~TSDRidCache()
|
||
|
{
|
||
|
if ( from_sid )
|
||
|
{
|
||
|
free(from_sid);
|
||
|
from_sid = NULL;
|
||
|
}
|
||
|
if ( to_sid )
|
||
|
{
|
||
|
free(to_sid);
|
||
|
to_sid = NULL;
|
||
|
}
|
||
|
// empty the list, and free each node
|
||
|
TRidNode * node;
|
||
|
for ( node = (TRidNode *)Head() ; node ; Remove(node) , free(node), node = (TRidNode *)Head() )
|
||
|
;
|
||
|
if ( m_otherAccounts )
|
||
|
delete m_otherAccounts;
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* SizeDiff:
|
||
|
Returns (Length of Domain B SID) - (Length of Domain A SID)
|
||
|
if Domain B sids are longer, otherwise returns 0
|
||
|
This is used to figure out how much space to allocate for new SIDs in the ACEs
|
||
|
This function assumes that from_sid and to_sid (from_nsubs and to_nsubs) are valid
|
||
|
/***************************************************************************************************/
|
||
|
DWORD
|
||
|
TSDRidCache::SizeDiff(
|
||
|
const TAcctNode * tnode // in -this parameter is not used for TSDRidCache
|
||
|
) const
|
||
|
{
|
||
|
assert( from_sid ); // not having from_sid or to_sid should abort the program
|
||
|
assert( to_sid );
|
||
|
|
||
|
DWORD fromsize = GetSidLengthRequired(from_nsubs);
|
||
|
DWORD tosize = GetSidLengthRequired(to_nsubs);
|
||
|
DWORD retval;
|
||
|
if ( fromsize >= tosize )
|
||
|
{
|
||
|
retval = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
retval = tosize - fromsize;
|
||
|
}
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************************************/
|
||
|
/* DomainizeSidFst:
|
||
|
Takes a domain sid, and verifies that its last subauthority value is -1. If the RID is not
|
||
|
-1, DomainizeSid adds a -1 to the end.
|
||
|
/*****************************************************************************************************/
|
||
|
PSID // ret -the sid with RID = -1
|
||
|
DomainizeSidFst(
|
||
|
PSID psid, // in -sid to check and possibly fix
|
||
|
BOOL freeOldSid // in -whether to free the old sid
|
||
|
)
|
||
|
{
|
||
|
assert (psid);
|
||
|
|
||
|
UCHAR len = (* GetSidSubAuthorityCount(psid));
|
||
|
PDWORD sub = GetSidSubAuthority(psid,len-1);
|
||
|
|
||
|
if ( *sub != -1 )
|
||
|
{
|
||
|
DWORD sdsize = GetSidLengthRequired(len+1); // sid doesn't already have -1 as rid
|
||
|
PSID newsid = (SID *)malloc(sdsize); // copy the sid, and add -1 to the end
|
||
|
if (!newsid)
|
||
|
{
|
||
|
assert(false);
|
||
|
return psid;
|
||
|
}
|
||
|
|
||
|
if ( ! InitializeSid(newsid,GetSidIdentifierAuthority(psid),len+1) ) // make a bigger sid w/same IA
|
||
|
{
|
||
|
err.SysMsgWrite(ErrU,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
|
||
|
assert (false);
|
||
|
}
|
||
|
for ( DWORD i = 0 ; i < len ; i++ )
|
||
|
{
|
||
|
sub = GetSidSubAuthority(newsid,i); // copy subauthorities
|
||
|
(*sub) = (*GetSidSubAuthority(psid,i));
|
||
|
}
|
||
|
sub = GetSidSubAuthority(newsid,len);
|
||
|
*sub = -1; // set rid =-1
|
||
|
if ( freeOldSid )
|
||
|
{
|
||
|
free(psid);
|
||
|
}
|
||
|
psid = newsid;
|
||
|
len++;
|
||
|
}
|
||
|
return psid;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
SetDomainInfoStructFromSid(
|
||
|
PSID pSid, // in -sid for domain
|
||
|
SDRDomainInfo * info // out-struct containing information
|
||
|
)
|
||
|
{
|
||
|
// if ( (pSid) )
|
||
|
if ( IsValidSid(pSid) )
|
||
|
{
|
||
|
info->domain_name[0] = 0;
|
||
|
info->dc_name[0] = 0;
|
||
|
info->domain_sid = DomainizeSidFst(pSid,FALSE/*don't free old sid*/);
|
||
|
info->nsubs = *GetSidSubAuthorityCount(info->domain_sid);
|
||
|
info->valid = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// info->domain_name[0] = 0;
|
||
|
// info->dc_name[0] = 0;
|
||
|
// info->valid = TRUE;
|
||
|
err.MsgWrite(ErrE,DCT_MSG_INVALID_DOMAIN_SID);
|
||
|
info->valid = FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
void
|
||
|
SetDomainInfoStruct(
|
||
|
WCHAR const * domname, // in -name of domain
|
||
|
SDRDomainInfo * info // in -struct to put info into
|
||
|
)
|
||
|
{
|
||
|
DWORD rc = 0;
|
||
|
WCHAR domain[LEN_Computer];
|
||
|
BOOL found = FALSE;
|
||
|
WCHAR * computer = NULL;
|
||
|
|
||
|
|
||
|
safecopy(domain,domname);
|
||
|
|
||
|
info->valid = FALSE;
|
||
|
safecopy(info->domain_name, domname);
|
||
|
// get the domain controller name
|
||
|
if ( GetDomainDCName(domain,&computer) )
|
||
|
{
|
||
|
safecopy(info->dc_name,computer);
|
||
|
NetApiBufferFree(computer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
}
|
||
|
|
||
|
if ( ! rc )
|
||
|
{
|
||
|
// Get the SID for the domain
|
||
|
WCHAR strDomain[LEN_Domain];
|
||
|
DWORD lenStrDomain = DIM(strDomain);
|
||
|
SID_NAME_USE snu;
|
||
|
BYTE sid[200];
|
||
|
DWORD lenSid = DIM(sid);
|
||
|
|
||
|
if ( LookupAccountName(info->dc_name,info->domain_name,sid,&lenSid,strDomain,&lenStrDomain,&snu) )
|
||
|
{
|
||
|
info->domain_sid = DomainizeSidFst(sid, FALSE /*don't free sid*/);
|
||
|
info->nsubs = *GetSidSubAuthorityCount(info->domain_sid);
|
||
|
info->valid = TRUE;
|
||
|
found = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
if ( rc )
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_DOMAIN_GET_INFO_FAILED_S,domain);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
TSDRidCache::SetDomainInfoWithSid(
|
||
|
WCHAR const * strDomain, // in -domain name
|
||
|
WCHAR const * strSid, // in -textual representation of sid
|
||
|
bool firstdom // in -flag: (true => source domain), (false => target domain)
|
||
|
)
|
||
|
{
|
||
|
SDRDomainInfo info;
|
||
|
PSID pSid = SidFromString(strSid);
|
||
|
|
||
|
SetDomainInfoStructFromSid(pSid,&info);
|
||
|
if ( info.valid )
|
||
|
{
|
||
|
if ( firstdom )
|
||
|
{
|
||
|
safecopy(from_domain,strDomain);
|
||
|
from_sid = info.domain_sid;
|
||
|
from_dc[0] = 0;
|
||
|
from_nsubs = info.nsubs;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
safecopy(to_domain,strDomain);
|
||
|
to_sid = info.domain_sid;
|
||
|
to_dc[0] =0;
|
||
|
to_nsubs = info.nsubs;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
FreeSid(pSid);
|
||
|
return info.valid;
|
||
|
}
|
||
|
/*****************************************************************************************************/
|
||
|
/* SetDomainInfo:
|
||
|
sets either ( from_domain, from_sid, from_dc, from_nsubs) if ( firstdom )
|
||
|
or ( to_domain, to_sid, to_dc, to_nsubs) if ( ! firstdom)
|
||
|
/*****************************************************************************************************/
|
||
|
int // ret -true if members were set, false otherwise
|
||
|
TSDRidCache::SetDomainInfo(
|
||
|
WCHAR const * domname, // in -name of domain
|
||
|
bool firstdom // in -flag: (true => source domain), (false => target domain)
|
||
|
)
|
||
|
{
|
||
|
|
||
|
SDRDomainInfo info;
|
||
|
|
||
|
SetDomainInfoStruct(domname,&info);
|
||
|
if ( info.valid ) // we have good information to store
|
||
|
{
|
||
|
if ( firstdom )
|
||
|
{
|
||
|
safecopy(from_domain,info.domain_name);
|
||
|
from_sid = info.domain_sid;
|
||
|
safecopy(from_dc,info.dc_name);
|
||
|
from_nsubs = info.nsubs;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
safecopy(to_domain,info.domain_name);
|
||
|
to_sid = info.domain_sid;
|
||
|
safecopy(to_dc,info.dc_name);
|
||
|
to_nsubs = info.nsubs;
|
||
|
}
|
||
|
}
|
||
|
return info.valid;
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
TGeneralCache::GetName(
|
||
|
const PSID psid // in - SID to lookup account name for
|
||
|
)
|
||
|
{
|
||
|
TGeneralSidNode * tn = (TGeneralSidNode*)Lookup(psid);
|
||
|
|
||
|
if ( tn )
|
||
|
return tn->GetAcctName();
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
TAcctNode *
|
||
|
TGeneralCache::Lookup(
|
||
|
const PSID psid // in - SID to lookup account name for
|
||
|
)
|
||
|
{
|
||
|
TGeneralSidNode * tn = (TGeneralSidNode*)Find(&vSidComp,psid);
|
||
|
|
||
|
return (TAcctNode *)tn;
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* Lookup: takes a sid, checks whether it came from domain A. If so, it finds the corresponding entry
|
||
|
in the cache, and returns that node.
|
||
|
|
||
|
Returns: Pointer to TSidNode whose domain A rid matches asid's rid,
|
||
|
or NULL if not a domain A sid, or not found in the cache
|
||
|
/***************************************************************************************************/
|
||
|
TAcctNode *
|
||
|
TSDRidCache::Lookup(
|
||
|
const PSID psid // in -sid to search for
|
||
|
)
|
||
|
|
||
|
{
|
||
|
TRidNode * tn = NULL;
|
||
|
DWORD rid = 0;
|
||
|
BOOL bFromSourceDomain;
|
||
|
UCHAR * pNsubs;
|
||
|
DWORD nsubs;
|
||
|
TAcctNode * anode = NULL;
|
||
|
assert( IsValidSid(psid) );
|
||
|
assert ( IsValidSid(from_sid) );
|
||
|
|
||
|
pNsubs = GetSidSubAuthorityCount(psid);
|
||
|
if ( pNsubs )
|
||
|
{
|
||
|
nsubs = (*pNsubs);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert(false);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
rid = (* GetSidSubAuthority(psid,nsubs - 1) );
|
||
|
|
||
|
// if ((!from_sid) || (EqualPrefixSid(psid,from_sid))) // first check whether asid matches the from-domain
|
||
|
if ( EqualPrefixSid(psid,from_sid) ) // first check whether asid matches the from-domain
|
||
|
{
|
||
|
bFromSourceDomain = TRUE;
|
||
|
tn = (TRidNode *)Find(&vRidComp,&rid);
|
||
|
anode = tn;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bFromSourceDomain = FALSE;
|
||
|
}
|
||
|
if (! tn )
|
||
|
{
|
||
|
tn = (TRidNode *)-1;
|
||
|
if ( AddIfNotFound() && ! BuiltinRid(rid) ) // Don't lookup builtin accounts
|
||
|
{
|
||
|
if ( ! m_otherAccounts )
|
||
|
{
|
||
|
m_otherAccounts = new TGeneralCache();
|
||
|
if (!m_otherAccounts)
|
||
|
{
|
||
|
assert(false);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
TGeneralSidNode * sn = (TGeneralSidNode *)m_otherAccounts->Lookup(psid);
|
||
|
if ( ! sn )
|
||
|
{
|
||
|
sn = new TGeneralSidNode(psid,NULL);
|
||
|
if (!sn)
|
||
|
{
|
||
|
assert(false);
|
||
|
return NULL;
|
||
|
}
|
||
|
m_otherAccounts->TreeInsert(sn);
|
||
|
}
|
||
|
anode = (TAcctNode*)sn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return anode;
|
||
|
}
|
||
|
/***************************************************************************************************/
|
||
|
/* GetName: Calls SidCache::Lookup, and returns the acct name from the resulting node
|
||
|
/***************************************************************************************************/
|
||
|
LPWSTR // ret -acct_name, or NULL if not found
|
||
|
TSDRidCache::GetName(
|
||
|
const PSID psid // in -sid to look for
|
||
|
)
|
||
|
{
|
||
|
TAcctNode * tn = Lookup(psid);
|
||
|
LPWSTR retval;
|
||
|
|
||
|
if ( tn )
|
||
|
retval = tn->GetAcctName();
|
||
|
else
|
||
|
retval = NULL;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************************************/
|
||
|
/* LookupWODomain: takes a sid, checks whether it came from domain A. If so, it finds the corresponding entry
|
||
|
in the cache, and returns that node. This lookup function is used if the
|
||
|
src domain sid has not been recorded (like in the case of using a sID mapping file).
|
||
|
|
||
|
Returns: Pointer to TSidNode whose domain A rid matches asid's rid,
|
||
|
or NULL if not a domain A sid, or not found in the cache
|
||
|
/***************************************************************************************************/
|
||
|
TAcctNode *
|
||
|
TSDRidCache::LookupWODomain(
|
||
|
const PSID psid // in -sid to search for
|
||
|
)
|
||
|
|
||
|
{
|
||
|
TRidNode * tn = NULL;
|
||
|
DWORD rid = 0;
|
||
|
BOOL bFound = FALSE;
|
||
|
UCHAR * pNsubs;
|
||
|
DWORD nsubs;
|
||
|
TAcctNode * anode = NULL;
|
||
|
assert( IsValidSid(psid) );
|
||
|
|
||
|
pNsubs = GetSidSubAuthorityCount(psid);
|
||
|
if ( pNsubs )
|
||
|
{
|
||
|
nsubs = (*pNsubs);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert(false);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
rid = (* GetSidSubAuthority(psid,nsubs - 1) );
|
||
|
|
||
|
//while not found and more that match the rid, find the next
|
||
|
// do
|
||
|
// {
|
||
|
//look for a matching Rid
|
||
|
tn = (TRidNode *)Find(&vRidComp,&rid);
|
||
|
//if we found a matching Rid, compare the domain part of the sid for a real match
|
||
|
if (tn)
|
||
|
{
|
||
|
//get the source domain sid of the matching Rid node
|
||
|
PSID src_sid = SidFromString(tn->GetSrcDomSid());
|
||
|
if ((src_sid) && (EqualPrefixSid(psid,src_sid))) // check whether asid matches the source domain
|
||
|
{
|
||
|
bFound = TRUE;
|
||
|
anode = tn;
|
||
|
}
|
||
|
if (src_sid)
|
||
|
FreeSid(src_sid);
|
||
|
}//end if Rid match
|
||
|
// } while ((!bFound) && (tn)); //end while no match
|
||
|
|
||
|
return anode;
|
||
|
}
|
||
|
//END LookupWODomain
|
||
|
|