📄 accessenum.cpp
字号:
if ( pOwner == NULL )
continue; // no owner, therefore no permissions to report
pSid = pOwner;
}
// Skip LocalSystem account
if ( EqualSid( pSid, (PSID)&SID_NTAUTHORITY_SYSTEM ) ) {
// who cares?
continue;
}
// Check if SID already is in our list
for ( DWORD i = 0; i < AccountCnt; ++i )
if ( EqualSid( pSid, AccountList[i].Account->Sid ) )
break;
// Create new list entry if not already present
if ( i >= AccountCnt ) {
if ( AccountCnt+1 >= MAX_ACCOUNTS_PER_ACL ) {
MessageBox( g.hMainDlg, _T("Internal error: Too many accounts in ACL"), APPNAME, MB_OK|MB_ICONSTOP );
return false;
}
++AccountCnt;
AccountList[i].Account = LookupSid( pSid, host );
AccountList[i].AllowMask = 0;
AccountList[i].DenyMask = 0;
}
#if 0
// Skip None group
if ( EqualSid( pSid, SidNone() ) ) {
// who cares?
continue;
}
#endif
// Merge rights for this ace into existing account rights
if ( ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE )
AccountList[i].AllowMask |= ace->Mask;
else
AccountList[i].DenyMask |= ace->Mask;
}
// Convert rights for each account to generic rights. This
// simplifies the bit arithmetic we do later.
for ( DWORD actIdx = 0; actIdx < AccountCnt; ++actIdx ) {
DWORD & mask = AccountList[actIdx].AllowMask;
mask = (root->AllowRead(mask) ? GENERIC_READ : 0)
| (root->AllowWrite(mask) ? GENERIC_WRITE : 0);
}
#if 1
// Check group membership for each account and
// subtract rights granted by group(s) from account rights.
for ( actIdx = 0; actIdx < AccountCnt; ++actIdx ) {
for ( DWORD other = 0; other < AccountCnt; ++other ) {
// make sure other item is a group, and not us
if ( actIdx == other )
continue;
if ( AccountList[other].Account->Use != SidTypeGroup &&
AccountList[other].Account->Use != SidTypeWellKnownGroup &&
AccountList[other].Account->Use != SidTypeAlias )
continue;
// If Everyone is present then always assume membership
if ( EqualSid( AccountList[other].Account->Sid, (PSID)&SID_EVERYONE ) ) {
// Everyone is a member of Everyone
AccountList[actIdx].AllowMask &= ~AccountList[other].AllowMask;
AccountList[actIdx].DenyMask &= ~AccountList[other].DenyMask;
continue;
}
// check each of our groups to see if we belong to other
for ( DWORD actGrp = 0; actGrp < AccountList[actIdx].Account->GroupLocalCnt; ++actGrp ) {
if ( _tcsicmp( AccountList[actIdx].Account->GroupLocalList[actGrp].lgrui0_name,
AccountList[other].Account->Name ) == 0 )
{
// There is another group that we are a member of.
// Subtract any rights they grant from our rights.
AccountList[actIdx].AllowMask &= ~AccountList[other].AllowMask;
AccountList[actIdx].DenyMask &= ~AccountList[other].DenyMask;
}
}
for ( actGrp = 0; actGrp < AccountList[actIdx].Account->GroupNetCnt; ++actGrp ) {
if ( _tcsicmp( AccountList[actIdx].Account->GroupNetList[actGrp].grui0_name,
AccountList[other].Account->Name ) == 0 )
{
// There is another group that we are a member of
// Subtract any rights they grant from our rights.
AccountList[actIdx].AllowMask &= ~AccountList[other].AllowMask;
AccountList[actIdx].DenyMask &= ~AccountList[other].DenyMask;
}
}
}
}
#endif
// sort list of accounts
qsort( AccountList, AccountCnt, sizeof AccountList[0], CompareAccountRights );
// Generate lists of the accounts with Read, Write and Deny rights present.
DWORD ReadCnt = 0;
DWORD WriteCnt = 0;
DWORD DenyCnt = 0;
for ( actIdx = 0; actIdx < AccountCnt; ++actIdx ) {
if ( AccountList[actIdx].AllowMask & GENERIC_READ ) {
Read[ReadCnt++] = AccountList[actIdx].Account;
}
if ( AccountList[actIdx].AllowMask & GENERIC_WRITE ) {
Write[WriteCnt++] = AccountList[actIdx].Account;
}
if ( AccountList[actIdx].DenyMask ) {
Deny[DenyCnt++] = AccountList[actIdx].Account;
}
}
// set null terminator
Read[ReadCnt] = NULL;
Write[WriteCnt] = NULL;
Deny[DenyCnt] = NULL;
return true;
}
// Both account lists must be sorted
bool AccountListEqual( const ACCOUNT * Account1[], const ACCOUNT * Account2[] )
{
if ( Account1[0] == UNDEFINED_ACCOUNT || Account2[0] == UNDEFINED_ACCOUNT ) {
// if either is undefined, then the undefined one is the superset
return Account2[0] == Account1[0];
}
// Compare each account in turn, using the same comparison function used to sort the lists.
for ( int idx = 0; Account1[idx] && Account2[idx]; ++idx ) {
int diff = CompareAccount( Account1[idx], Account2[idx] );
if ( diff )
return false;
}
return Account1[idx] == Account2[idx];
}
bool AccountListSubset( const ACCOUNT * Sub[], const ACCOUNT * Super[] )
{
// if either is undefined, then the undefined one is the superset
if ( Sub[0] == UNDEFINED_ACCOUNT )
return Super[0] == UNDEFINED_ACCOUNT;
if ( Super[0] == UNDEFINED_ACCOUNT )
return false;
// Compare each account in turn, using the same comparison function used to sort the lists.
for ( int iSub = 0, iSuper = 0; Sub[iSub] && Super[iSuper];) {
int diff = CompareAccount( Sub[iSub], Super[iSuper] );
if ( diff == 0 ) {
++iSub;
++iSuper;
} else if ( diff > 0 ) {
++iSuper;
} else {
return false;
}
}
return Sub[iSub] == NULL;
}
int AddListviewRow( HWND hListview, const TCHAR * path,
const TCHAR * OtherRead, const TCHAR * OtherWrite,
const TCHAR * deny )
{
CShare * share = new CShare( path, OtherRead, OtherWrite, deny, ',' );
share->InsertInList( &g.ShareList );
// get icon
int iImage;
if ( _tcsnicmp( path, _T("HK"), 2 ) == 0 ) {
// registry key
HIMAGELIST hImageList = ListView_GetImageList( hListview, LVSIL_SMALL );
iImage = ImageList_AddIcon( hImageList, LoadIcon( g.hInst, MAKEINTRESOURCE(IDI_FOLDERCLOSED) ) );
} else {
// file
SHFILEINFO info = { 0 };
SHGetFileInfo( path, 0, &info, sizeof info, SHGFI_ICON|SHGFI_SMALLICON );
HIMAGELIST hImageList = ListView_GetImageList( hListview, LVSIL_SMALL );
iImage = ImageList_AddIcon( hImageList, info.hIcon );
DestroyIcon( info.hIcon );
}
// Add to listview
LVITEM item;
item.mask = LVIF_TEXT | LVIF_IMAGE;
item.iItem = 0x7FFFFFFF;
item.iSubItem = 0;
item.iImage = iImage;
item.pszText = (TCHAR *) path;
item.iItem = ListView_InsertItem( hListview, &item );
// set param to index, so we can look ourself up during sorting
item.mask = LVIF_PARAM;
item.lParam = item.iItem;
ListView_SetItem( hListview, &item );
item.mask = LVIF_TEXT;
item.iSubItem += 1;
item.pszText = (TCHAR *) OtherRead;
ListView_SetItem( hListview, &item );
item.iSubItem += 1;
item.pszText = (TCHAR *) OtherWrite;
ListView_SetItem( hListview, &item );
item.iSubItem += 1;
item.pszText = (TCHAR *) deny;
ListView_SetItem( hListview, &item );
return item.iItem;
}
//==============================================================
//
// EnumerateDomains
//
// Create a list of computer domains accessible to this system
//
//==============================================================
class CWorker {
public:
void Start()
{
InterlockedIncrement( &g.ThreadCount );
UpdateStatus();
#if _MT
DWORD id;
HANDLE hThread = CreateThread( NULL, 0, Work, this, CREATE_SUSPENDED, &id );
SetThreadPriority( hThread, THREAD_PRIORITY_LOWEST );
ResumeThread( hThread );
#else
Work();
#endif
}
virtual ~CWorker()
{
}
protected:
void UpdateStatus()
{
TCHAR * msg = g.ThreadCount ? _T("Searching...") : _T("");
SetWindowText( GetDlgItem( g.hMainDlg, IDC_STATUS ), msg );
}
static int ProcessException( int code, const EXCEPTION_POINTERS * ep )
{
TCHAR buf[ MAX_PATH ];
_stprintf( buf, _T("An internal error occured: Exception #0x%X"), code );
MessageBox( g.hMainDlg, buf, APPNAME, MB_OK );
EXCEPTION_RECORD * ExceptionRecord = ep->ExceptionRecord;
CONTEXT * ContextRecord = ep->ContextRecord;
return EXCEPTION_EXECUTE_HANDLER;
}
static DWORD WINAPI Work( void * This )
{
CWorker * obj = (CWorker *)This;
__try {
obj->Work();
} __except ( ProcessException( GetExceptionCode(), GetExceptionInformation() ) ) {
}
return 0;
}
virtual void Work()
{
if ( InterlockedDecrement( &g.ThreadCount ) == 0 ) {
// We're done enumerating
PostMessage( g.hMainDlg, WM_APP_ENUM_COMPLETE, 0, 0 );
}
UpdateStatus();
delete this;
}
};
class CTraversal : public CWorker {
HWND m_hListview;
const bstr_t m_Host;
CEnumeration * m_Root;
#define MISSING_DACL ((PACL) 0xFFFFFFFF)
inline bool EXPLICIT_DACL( PACL d )
{
return d != NULL && d != MISSING_DACL;
}
public:
CTraversal( HWND hListview, const TCHAR * Host, CEnumeration * Root ) :
m_hListview( hListview ), m_Host( Host ), m_Root( Root )
{
}
~CTraversal()
{
}
private:
void GetAccountNames( TCHAR * Text, const ACCOUNT * Account[] )
{
// Analyze DACL
if ( Account[0] == UNDEFINED_ACCOUNT ) {
_tcscpy( Text, _T("???") );
} else {
// convert acl to text
TCHAR * TextStart = Text;
for ( int i = 0; Account[i]; ++i ) {
Text += _stprintf( Text, _T("%s, "), Account[i]->Name );
}
// Trim trailing commas in lists
if ( Text == TextStart ) {
Text[0] = 0;
} else {
Text[-2] = 0;
}
}
}
void ShowAccounts( const TCHAR * Path, const ACCOUNT * Read[], const ACCOUNT * Write[], const ACCOUNT * Deny[] )
{
// Get permissions
TCHAR szRead[ MAX_TEXT ];
TCHAR szWrite[ MAX_TEXT ];
TCHAR szDeny[ MAX_TEXT ];
GetAccountNames( szRead, Read );
GetAccountNames( szWrite, Write );
GetAccountNames( szDeny, Deny );
// Add to list view
AddListviewRow( m_hListview, Path, szRead, szWrite, szDeny );
}
void Enumerate( CEnumeration * Root, const ACCOUNT * ParentRead[], const ACCOUNT * ParentWrite[], const ACCOUNT * ParentDeny[] )
{
// If path is a subdirectory of Exclude then skip it
if ( !!g.Exclude ) {
if ( _tcsnicmp( Root->Path(), g.Exclude, _tcslen(g.Exclude) ) == 0 )
return;
else
g.Exclude = (TCHAR *) NULL;
}
#if 0
if ( _tcsicmp( Root->Path(), _T("HKLM\\Software\\Classes\\Installer\\Components") ) == 0 )
__asm int 3;
#endif
// Show progress
SetDlgItemText( GetParent(m_hListview), IDC_PATH, Root->Path() );
#if 0
if ( wcslen( Root->Path() ) > 100 )
Path = (TCHAR *)9999999999;
#endif
// Get security descriptor
PSECURITY_DESCRIPTOR sd = Root->GetSecurity();
// Convert acl to rights list
const ACCOUNT * Read[ MAX_ACCOUNTS_PER_ACL ];
const ACCOUNT * Write[ MAX_ACCOUNTS_PER_ACL ];
const ACCOUNT * Deny[ MAX_ACCOUNTS_PER_ACL ];
GetCannonicalRights( m_Host, sd, Root, Read, Write, Deny );
bool show;
if ( Root->IsDir() || g.ShowAllFiles ) {
// directory permissions must match exactly
show = !AccountListEqual( Read, ParentRead ) ||
!AccountListEqual( Write, ParentWrite ) ||
!AccountListEqual( Deny, ParentDeny );
} else {
// file permissions its okay to be a subset of parent
show = !AccountListSubset( Read, ParentRead ) ||
!AccountListSubset( Write, ParentWrite ) ||
!AccountListSubset( Deny, ParentDeny );
}
if ( show ) {
// Display permissions
ShowAccounts( Root->Path(), Read, Write, Deny );
}
// Recurse if a directory
if ( Root->IsDir() ) {
DWORD status;
CEnumeration * Child = Root->FindNext( &status );
if ( status ) {
// indicate error while reading children
const TCHAR * msg = FormattedMessage( status );
_bstr_t fullpath = Root->Path() + _T("\\*");
AddListviewRow( m_hListview, fullpath, msg, _T(""), _T("") );
} else {
while ( Child ) {
if ( g.Abort )
break;
// Compute full path and evaluate
#if 0
if ( end - Path + _tcslen( info.cFileName ) + 1 >= MAX_UNCPATH ) {
MessageBox( NULL, _T("Fatal error: MAX_UNCPATH exceeded"), APPNAME, MB_ICONSTOP );
exit(1);
}
_tcscpy( end+1, info.cFileName );
#endif
#if 0
static TCHAR oldPath[ 2*MAX_UNCPATH ];
_tcscpy( oldPath, Path );
if ( _tcscmp( oldPath, _T("C:\\WINDOWS\\Help\\SBSI\\Training\\Database\\bookmrk.CDX") ) == 0 )
__asm int 3;
#endif
Enumerate( Child, Read, Write, Deny );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -