📄 accessenum.cpp
字号:
#define _WIN32_WINNT 0x0400 // WM_MOUSEWHEEL support
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
#include <tchar.h>
#include <ctype.h>
#include <Aclapi.h>
#include <crtdbg.h> // ASSERT
#include <comdef.h> // bstr_t support
#include <lm.h>
#include <ShlObj.h>
#include "AccessEnum.h"
#include "resource.h"
#include "resizer.h"
#include "listview.h"
#include "Enumeration.h"
PSID DomainAdminSid();
bool IsDomainAdmin();
int GetAccountName( TCHAR * buf, const TCHAR * host, PSID sid );
const TCHAR ALL_DOMAINS[] = _T("<All domains>");
struct _globals {
HINSTANCE hInst;
HWND Abort; // 'abort in progress' window
bool ShowAllFiles;
CShare * ShareList;
long ThreadCount;
HWND hMainDlg;
_bstr_t Exclude;
} g;
const DWORD CFileEnumeration::READ_MASK = GENERIC_ALL|GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL|FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA;
const DWORD CFileEnumeration::WRITE_MASK = GENERIC_ALL|GENERIC_WRITE|DELETE|WRITE_DAC|WRITE_OWNER|FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_DATA|FILE_WRITE_EA;
const DWORD CRegEnumeration::READ_MASK = GENERIC_ALL|GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS|KEY_NOTIFY;
const DWORD CRegEnumeration::WRITE_MASK = GENERIC_ALL|GENERIC_WRITE|DELETE|WRITE_DAC|WRITE_OWNER|KEY_SET_VALUE|KEY_CREATE_SUB_KEY|KEY_CREATE_LINK;
// Everyone
static const SID SID_EVERYONE = { 1, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_NULL_RID };
// creator owner
static const SID SID_CREATOR_OWNER = { 1, 1, SECURITY_CREATOR_SID_AUTHORITY, SECURITY_CREATOR_OWNER_RID };
static const SID SID_CREATOR_GROUP = { 1, 1, SECURITY_CREATOR_SID_AUTHORITY, SECURITY_CREATOR_GROUP_RID };
static const SID SID_CREATOR_OWNERSERVER = { 1, 1, SECURITY_CREATOR_SID_AUTHORITY, SECURITY_CREATOR_OWNER_SERVER_RID };
static const SID SID_CREATOR_GROUPSERVER = { 1, 1, SECURITY_CREATOR_SID_AUTHORITY, SECURITY_CREATOR_GROUP_SERVER_RID };
// local system
static const SID SID_NTAUTHORITY_SYSTEM = { 1, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID };
// alias sids
#if 0
static const SID SID_BUILTIN_ADMIN = { 1, 1, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS };
static const SID SID_BUILTIN_POWERUSERS = { 1, 1, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS };
static const SID SID_BUILTIN_GUESTS = { 1, 1, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS };
static const SID SID_BUILTIN_USERS = { 1, 1, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS };
#endif
static struct LISTVIEW_COLUMN Columns[] =
{
{ TEXT("Path"), 240, DATATYPE_TEXT },
{ TEXT("Read"), 120, DATATYPE_TEXT },
{ TEXT("Write"), 120, DATATYPE_TEXT },
{ TEXT("Deny"), 80, DATATYPE_TEXT },
{ NULL, 0, (DATATYPE)-1 }
};
// Power Users
PSID SidLocalPowerUserAlias()
{
static PSID sid = NULL;
if ( sid == NULL ) {
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
AllocateAndInitializeSid( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS,
0, 0, 0, 0, 0, 0, &sid );
}
return sid;
}
// None
PSID SidNone()
{
static PSID sid = NULL;
if ( sid == NULL ) {
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
AllocateAndInitializeSid( &SystemSidAuthority, 5, SECURITY_NT_NON_UNIQUE, 0x56252AE1, 0xAEF28A35, 0x7D8EE907, 0x00000201, 0, 0, 0, &sid );
}
return sid;
}
// Local Administrators
PSID SidLocalAdminAlias()
{
static PSID sid = NULL;
if ( sid == NULL ) {
SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
AllocateAndInitializeSid( &ntauth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &sid );
}
return sid;
}
const TCHAR * FormattedMessage( DWORD status )
{
static TCHAR msg[ 1024 ];
msg[0] = 0;
FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM, NULL,
status, 0, msg, sizeof msg/sizeof msg[0], NULL );
if ( msg[0] != 0 ) {
TCHAR * ptr = _tcschr( msg, 0 );
while ( ptr > msg && isspace( *--ptr ) )
*ptr = 0;
} else {
_stprintf( msg, _T("Error %d"), status );
}
return msg;
}
bool ShowFileProperties( HWND hDlg, const TCHAR * Path )
{
SHELLEXECUTEINFO shellExecuteInfo = { 0 };
shellExecuteInfo.cbSize = sizeof shellExecuteInfo;
shellExecuteInfo.fMask = SEE_MASK_INVOKEIDLIST;
shellExecuteInfo.hwnd = hDlg;
shellExecuteInfo.lpVerb = _T("properties");
shellExecuteInfo.lpFile = Path;
return ShellExecuteEx( &shellExecuteInfo ) != FALSE;
}
bool ExploreFile( HWND hDlg, const TCHAR * Path )
{
if ( _tcsnicmp( Path, _T("HK"), 2 ) == 0 ) {
// registry key
RegeditJump( hDlg, Path );
return true;
} else {
// file
SHELLEXECUTEINFO shellExecuteInfo = { 0 };
shellExecuteInfo.cbSize = sizeof shellExecuteInfo;
shellExecuteInfo.fMask = SEE_MASK_INVOKEIDLIST;
shellExecuteInfo.hwnd = hDlg;
shellExecuteInfo.lpVerb = _T("explore");
shellExecuteInfo.lpFile = Path;
return ShellExecuteEx( &shellExecuteInfo ) != FALSE;
}
}
TCHAR * GetTextualSid( PSID pSid )
{
PSID_IDENTIFIER_AUTHORITY psia;
DWORD dwSubAuthorities;
DWORD dwSidRev=SID_REVISION;
DWORD dwCounter;
DWORD dwSidSize;
// Validate the binary SID.
if ( ! IsValidSid( pSid ) )
return NULL;
// Get the identifier authority value from the SID.
psia = GetSidIdentifierAuthority( pSid );
// Get the number of subauthorities in the SID.
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
// Compute the buffer length.
// S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
// Check input buffer length.
// If too small, indicate the proper size and set last error.
TCHAR * TextualSid = new TCHAR[ dwSidSize ];
// Add 'S' prefix and revision number to the string.
dwSidSize = wsprintf( TextualSid, TEXT("S-%lu-"), dwSidRev );
// Add SID identifier authority to the string.
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) {
dwSidSize += wsprintf( TextualSid + dwSidSize,
TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
(USHORT)psia->Value[0],
(USHORT)psia->Value[1],
(USHORT)psia->Value[2],
(USHORT)psia->Value[3],
(USHORT)psia->Value[4],
(USHORT)psia->Value[5]);
} else {
dwSidSize += wsprintf( TextualSid + dwSidSize,
TEXT("%lu"),
(ULONG)(psia->Value[5] ) +
(ULONG)(psia->Value[4] << 8) +
(ULONG)(psia->Value[3] << 16) +
(ULONG)(psia->Value[2] << 24) );
}
// Add SID subauthorities to the string.
//
for ( dwCounter = 0; dwCounter < dwSubAuthorities; dwCounter++ ) {
dwSidSize += wsprintf( TextualSid + dwSidSize, TEXT("-%lu"), *GetSidSubAuthority(pSid, dwCounter) );
}
return TextualSid;
}
struct ACCOUNT {
PSID Sid;
const TCHAR * Name;
const GROUP_USERS_INFO_0 * GroupNetList;
DWORD GroupNetCnt;
const LOCALGROUP_USERS_INFO_0 * GroupLocalList;
DWORD GroupLocalCnt;
SID_NAME_USE Use;
};
#define UNDEFINED_ACCOUNT ((ACCOUNT *)-1)
const ACCOUNT * LookupSid( PSID pSid, const TCHAR * host )
{
static ACCOUNT ** AccountList = NULL;
static DWORD AccountCnt = 0;
static DWORD AccountMax = 0;
for ( DWORD idx = 0; idx < AccountCnt; ++idx )
if ( EqualSid( pSid, AccountList[idx]->Sid ) )
return AccountList[idx];
ACCOUNT * act = new ACCOUNT;
// get copy of sid
DWORD sidlen = GetLengthSid( pSid );
act->Sid = new BYTE[ sidlen ];
memcpy( act->Sid, pSid, sidlen );
// Get account name for sid.
TCHAR domainName[MAX_PATH+1+2] = _T("\\\\");
TCHAR userName[MAX_PATH+1];
DWORD userLength = MAX_PATH;
DWORD domainLength = MAX_PATH;
TCHAR fullName[ 2 * MAX_PATH ];
if ( LookupAccountSid( host, pSid, userName, &userLength, domainName+2, &domainLength, &act->Use ) ) {
// found account on remote system
switch ( act->Use ) {
case SidTypeAlias:
_stprintf( fullName, _T("%s"), userName );
break;
case SidTypeUser:
_stprintf( fullName, _T("%s\\%s"), domainName+2, userName );
break;
case SidTypeDeletedAccount:
_stprintf( fullName, _T("%s\\%s(Deleted)"), domainName+2, userName );
break;
default:
_ASSERT(false);
// fall through
case SidTypeGroup:
case SidTypeWellKnownGroup:
if ( domainName[2] )
_stprintf( fullName, _T("%s\\%s"), domainName+2, userName );
else
_stprintf( fullName, _T("%s"), userName );
break;
}
act->Name = _tcsdup( fullName );
} else if ( host && LookupAccountSid( NULL, pSid, userName, &userLength, domainName+2, &domainLength, &act->Use ) ) {
_ASSERT(false);
// found account on local system
switch ( act->Use ) {
case SidTypeAlias:
_stprintf( fullName, _T("%s"), userName );
break;
case SidTypeUser:
_stprintf( fullName, _T("%s\\%s"), domainName+2, userName );
break;
case SidTypeDeletedAccount:
_stprintf( fullName, _T("%s\\%s(Deleted)"), domainName+2, userName );
break;
default:
_ASSERT(false);
// fall through
case SidTypeGroup:
case SidTypeWellKnownGroup:
if ( domainName[2] )
_stprintf( fullName, _T("%s\\%s"), domainName+2, userName );
else
_stprintf( fullName, _T("%s"), userName );
break;
}
act->Name = _tcsdup( fullName );
} else {
if ( EqualSid( pSid, SidLocalPowerUserAlias() ) ) {
_tcscpy( fullName, _T("Power Users") );
act->Name = _tcsdup( fullName );
} else {
// Use plain SID
act->Name = GetTextualSid( pSid );
act->Use = SidTypeUnknown;
fullName[0] = 0;
}
}
act->GroupNetList = NULL;
act->GroupLocalList = NULL;
act->GroupNetCnt = 0;
act->GroupLocalCnt = 0;
if ( act->Use == SidTypeUser ) {
NET_API_STATUS status;
// see what groups account belongs to
DWORD total = 0;
status = NetUserGetGroups( domainName, userName, 0, (BYTE **)&act->GroupNetList, MAX_PREFERRED_LENGTH, &act->GroupNetCnt, &total );
_ASSERT( status == 0 || status == ERROR_ACCESS_DENIED ); // ERROR_INVALID_FUNCTION, NERR_InvalidComputer
total = 0;
TCHAR server[ MAX_PATH ];
if ( host ) {
_stprintf( server, _T("\\\\%s"), host );
host = server;
}
status = NetUserGetLocalGroups( host, fullName, 0, LG_INCLUDE_INDIRECT, (BYTE **)&act->GroupLocalList, MAX_PREFERRED_LENGTH, &act->GroupLocalCnt, &total );
_ASSERT( status == 0 || status == ERROR_ACCESS_DENIED ); // ERROR_INVALID_FUNCTION, NERR_InvalidComputer
}
// add account to list
if ( AccountCnt >= AccountMax ) {
AccountMax = AccountMax ? 2*AccountMax : 1024;
AccountList = (ACCOUNT **)realloc( AccountList, AccountMax * sizeof AccountList[0] );
}
AccountList[ AccountCnt++ ] = act;
return act;
}
struct ACCOUNT_RIGHTS {
const ACCOUNT * Account;
DWORD AllowMask;
DWORD DenyMask;
};
inline int CompareAccount( const ACCOUNT * pa, const ACCOUNT * pb )
{
if ( pa == pb )
return 0;
return _tcsicmp( pa->Name, pb->Name );
}
int __cdecl CompareAccountRights( const void * pa, const void * pb )
{
return CompareAccount( ((const ACCOUNT_RIGHTS *)pa)->Account, ((const ACCOUNT_RIGHTS *)pb)->Account );
}
class CEnumeration;
bool GetCannonicalRights( const TCHAR * host, const PSECURITY_DESCRIPTOR sd, const CEnumeration * root, const ACCOUNT * Read[], const ACCOUNT * Write[], const ACCOUNT * Deny[] )
{
BOOL present, defaulted;
PACL acl = NULL;
if ( host && host[0] == 0 )
host = NULL;
// Get DACL
if ( !IsValidSecurityDescriptor( sd ) ||
!GetSecurityDescriptorDacl( sd, &present, &acl, &defaulted ) ||
!present )
{
// can't say anything about the rights
Read[0] = UNDEFINED_ACCOUNT;
Write[0] = UNDEFINED_ACCOUNT;
Deny[0] = UNDEFINED_ACCOUNT;
Read[1] = NULL;
Write[1] = NULL;
Deny[1] = NULL;
return false;
}
if ( acl == NULL ) {
// NULL dacl grants full access to everyone
Read[0] = LookupSid( (PSID)&SID_EVERYONE, host );
Write[0] = Read[0];
Deny[0] = Read[0];
Read[1] = NULL;
Write[1] = NULL;
Deny[1] = NULL;
return true;
}
// First we'll get a list of all accounts and the rights each has.
ACCOUNT_RIGHTS AccountList[ MAX_ACCOUNTS_PER_ACL ];
DWORD AccountCnt = 0;
// Iterate over aces and acculate a list of accounts
for ( int idx = 0; idx < acl->AceCount; ++idx ) {
ACCESS_ALLOWED_ACE * ace;
// Get the ace
GetAce( acl, idx, (void **)&ace );
if ( ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE &&
ace->Header.AceType != ACCESS_DENIED_ACE_TYPE )
{
continue;
}
// Get SID for ace
PSID pSid = &ace->SidStart;
if ( ! IsValidSid( pSid ) )
continue;
// translate CREATOR_OWNER sid to owner sid
if ( EqualSid( pSid, (PSID)&SID_CREATOR_OWNER ) ) {
PSID pOwner = NULL;
BOOL defaulted;
if ( ! GetSecurityDescriptorOwner( sd, &pOwner, &defaulted ) )
continue;
if ( pOwner == NULL )
continue; // no owner, therefore no permissions to report
pSid = pOwner;
} else if ( EqualSid( pSid, (PSID)&SID_CREATOR_GROUP ) ) {
PSID pOwner = NULL;
BOOL defaulted;
if ( ! GetSecurityDescriptorGroup( sd, &pOwner, &defaulted ) )
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -