793 lines
18 KiB
C
793 lines
18 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
rtdmpsec.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
NT level registry security test program #1, basic non-error paths.
|
|||
|
|
|||
|
Dump out the security descriptors of a sub-tree of the registry.
|
|||
|
|
|||
|
rtdmpsec <KeyPath>
|
|||
|
|
|||
|
Will ennumerate and dump out the subkeys and values of KeyPath,
|
|||
|
and then apply itself recursively to each subkey it finds.
|
|||
|
|
|||
|
It assumes data values are null terminated strings.
|
|||
|
|
|||
|
Example:
|
|||
|
|
|||
|
rtdmpsec \REGISTRY\MACHINE\TEST\bigkey
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 24-Jan-92
|
|||
|
|
|||
|
based on rtdmp.c by
|
|||
|
|
|||
|
Bryan Willman (bryanwi) 10-Dec-91
|
|||
|
|
|||
|
and getdacl.c by RobertRe
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Richard Ward (richardw) 14 April 1992 Changed ACE_HEADER
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "cmp.h"
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#define WORK_SIZE 1024
|
|||
|
|
|||
|
//
|
|||
|
// Get a pointer to the first ace in an acl
|
|||
|
//
|
|||
|
|
|||
|
#define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))
|
|||
|
|
|||
|
//
|
|||
|
// Get a pointer to the following ace
|
|||
|
//
|
|||
|
|
|||
|
#define NextAce(Ace) ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize))
|
|||
|
|
|||
|
//
|
|||
|
// Generic ACE structure, to be used for casting ACE's of known types
|
|||
|
//
|
|||
|
|
|||
|
typedef struct _KNOWN_ACE {
|
|||
|
ACE_HEADER Header;
|
|||
|
ACCESS_MASK Mask;
|
|||
|
ULONG SidStart;
|
|||
|
} KNOWN_ACE, *PKNOWN_ACE;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
InitVars();
|
|||
|
|
|||
|
VOID
|
|||
|
PrintAcl (
|
|||
|
IN PACL Acl
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
PrintAccessMask(
|
|||
|
IN ACCESS_MASK AccessMask
|
|||
|
);
|
|||
|
|
|||
|
void __cdecl main(int, char *);
|
|||
|
void processargs();
|
|||
|
|
|||
|
void print(PUNICODE_STRING);
|
|||
|
|
|||
|
void
|
|||
|
DumpSecurity(
|
|||
|
HANDLE Handle
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
Dump(
|
|||
|
HANDLE Handle
|
|||
|
);
|
|||
|
|
|||
|
UNICODE_STRING WorkName;
|
|||
|
WCHAR workbuffer[WORK_SIZE];
|
|||
|
|
|||
|
//
|
|||
|
// Universal well known SIDs
|
|||
|
//
|
|||
|
|
|||
|
PSID NullSid;
|
|||
|
PSID WorldSid;
|
|||
|
PSID LocalSid;
|
|||
|
PSID CreatorOwnerSid;
|
|||
|
|
|||
|
//
|
|||
|
// Sids defined by NT
|
|||
|
//
|
|||
|
|
|||
|
PSID NtAuthoritySid;
|
|||
|
|
|||
|
PSID DialupSid;
|
|||
|
PSID NetworkSid;
|
|||
|
PSID BatchSid;
|
|||
|
PSID InteractiveSid;
|
|||
|
PSID LocalSystemSid;
|
|||
|
|
|||
|
void
|
|||
|
__cdecl main(
|
|||
|
int argc,
|
|||
|
char *argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
HANDLE BaseHandle;
|
|||
|
|
|||
|
InitVars();
|
|||
|
|
|||
|
//
|
|||
|
// Process args
|
|||
|
//
|
|||
|
|
|||
|
WorkName.MaximumLength = WORK_SIZE;
|
|||
|
WorkName.Length = 0L;
|
|||
|
WorkName.Buffer = &(workbuffer[0]);
|
|||
|
|
|||
|
processargs(argc, argv);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set up and open KeyPath
|
|||
|
//
|
|||
|
|
|||
|
printf("rtdmpsec: starting\n");
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&WorkName,
|
|||
|
0,
|
|||
|
(HANDLE)NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
|||
|
|
|||
|
status = NtOpenKey(
|
|||
|
&BaseHandle,
|
|||
|
MAXIMUM_ALLOWED,
|
|||
|
&ObjectAttributes
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
printf("rtdmpsec: t0: %08lx\n", status);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
Dump(BaseHandle);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
Dump(
|
|||
|
HANDLE Handle
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
PKEY_BASIC_INFORMATION KeyInformation;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
ULONG NamePos;
|
|||
|
ULONG index;
|
|||
|
STRING enumname;
|
|||
|
HANDLE WorkHandle;
|
|||
|
ULONG ResultLength;
|
|||
|
static char buffer[WORK_SIZE];
|
|||
|
PUCHAR p;
|
|||
|
|
|||
|
KeyInformation = (PKEY_BASIC_INFORMATION)buffer;
|
|||
|
NamePos = WorkName.Length;
|
|||
|
|
|||
|
//
|
|||
|
// Print name of node we are about to dump out
|
|||
|
//
|
|||
|
printf("\n");
|
|||
|
print(&WorkName);
|
|||
|
printf("::\n");
|
|||
|
|
|||
|
//
|
|||
|
// Print out node's values
|
|||
|
//
|
|||
|
DumpSecurity(Handle);
|
|||
|
|
|||
|
//
|
|||
|
// Enumerate node's children and apply ourselves to each one
|
|||
|
//
|
|||
|
|
|||
|
for (index = 0; TRUE; index++) {
|
|||
|
|
|||
|
RtlZeroMemory(KeyInformation, WORK_SIZE);
|
|||
|
status = NtEnumerateKey(
|
|||
|
Handle,
|
|||
|
index,
|
|||
|
KeyBasicInformation,
|
|||
|
KeyInformation,
|
|||
|
WORK_SIZE,
|
|||
|
&ResultLength
|
|||
|
);
|
|||
|
|
|||
|
if (status == STATUS_NO_MORE_ENTRIES) {
|
|||
|
|
|||
|
WorkName.Length = NamePos;
|
|||
|
return;
|
|||
|
|
|||
|
} else if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
printf("rtdmpsec: dump1: status = %08lx\n", status);
|
|||
|
exit(1);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
enumname.Buffer = &(KeyInformation->Name[0]);
|
|||
|
enumname.Length = KeyInformation->NameLength;
|
|||
|
enumname.MaximumLength = KeyInformation->NameLength;
|
|||
|
|
|||
|
p = WorkName.Buffer;
|
|||
|
p += WorkName.Length;
|
|||
|
*p = '\\';
|
|||
|
p++;
|
|||
|
*p = '\0';
|
|||
|
WorkName.Length += 2;
|
|||
|
|
|||
|
RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)&enumname);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&enumname,
|
|||
|
0,
|
|||
|
Handle,
|
|||
|
NULL
|
|||
|
);
|
|||
|
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
|||
|
|
|||
|
status = NtOpenKey(
|
|||
|
&WorkHandle,
|
|||
|
MAXIMUM_ALLOWED,
|
|||
|
&ObjectAttributes
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
if (status == STATUS_ACCESS_DENIED) {
|
|||
|
printf("\n");
|
|||
|
print(&WorkName);
|
|||
|
printf("::\n\tAccess denied!\n");
|
|||
|
} else {
|
|||
|
printf("rtdmpsec: dump2: %08lx\n", status);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
} else {
|
|||
|
Dump(WorkHandle);
|
|||
|
NtClose(WorkHandle);
|
|||
|
}
|
|||
|
|
|||
|
WorkName.Length = NamePos;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
DumpSecurity(
|
|||
|
HANDLE Handle
|
|||
|
)
|
|||
|
{
|
|||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG Length;
|
|||
|
PACL Dacl;
|
|||
|
BOOLEAN DaclPresent;
|
|||
|
BOOLEAN DaclDefaulted;
|
|||
|
|
|||
|
Status = NtQuerySecurityObject( Handle,
|
|||
|
DACL_SECURITY_INFORMATION,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&Length );
|
|||
|
|
|||
|
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
|||
|
printf("DumpSecurity t0: NtQuerySecurityObject failed %lx\n",Status);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
SecurityDescriptor = malloc(Length);
|
|||
|
if (SecurityDescriptor == NULL) {
|
|||
|
printf("DumpSecurity: couldn't malloc buffer\n");
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
Status = NtQuerySecurityObject( Handle,
|
|||
|
DACL_SECURITY_INFORMATION,
|
|||
|
SecurityDescriptor,
|
|||
|
Length,
|
|||
|
&Length );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
printf("DumpSecurity t1: NtQuerySecurityObject failed %lx\n",Status);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
Dacl = NULL;
|
|||
|
|
|||
|
Status = RtlGetDaclSecurityDescriptor( SecurityDescriptor,
|
|||
|
&DaclPresent,
|
|||
|
&Dacl,
|
|||
|
&DaclDefaulted );
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
printf("DumpSecurity t2: RtlGetDaclSecurityDescriptor failed %lx\n",Status);
|
|||
|
}
|
|||
|
|
|||
|
if (DaclPresent) {
|
|||
|
PrintAcl(Dacl);
|
|||
|
} else {
|
|||
|
printf("\tAcl not present\n");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
print(
|
|||
|
PUNICODE_STRING String
|
|||
|
)
|
|||
|
{
|
|||
|
static ANSI_STRING temp;
|
|||
|
static char tempbuffer[WORK_SIZE];
|
|||
|
|
|||
|
temp.MaximumLength = WORK_SIZE;
|
|||
|
temp.Length = 0L;
|
|||
|
temp.Buffer = tempbuffer;
|
|||
|
|
|||
|
RtlUnicodeStringToAnsiString(&temp, String, FALSE);
|
|||
|
printf("%s", temp.Buffer);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
processargs(
|
|||
|
int argc,
|
|||
|
char *argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ANSI_STRING temp;
|
|||
|
|
|||
|
if ( (argc != 2) )
|
|||
|
{
|
|||
|
printf("Usage: %s <KeyPath>\n",
|
|||
|
argv[0]);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
RtlInitAnsiString(
|
|||
|
&temp,
|
|||
|
argv[1]
|
|||
|
);
|
|||
|
|
|||
|
RtlAnsiStringToUnicodeString(
|
|||
|
&WorkName,
|
|||
|
&temp,
|
|||
|
FALSE
|
|||
|
);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SidTranslation(
|
|||
|
PSID Sid,
|
|||
|
PSTRING AccountName
|
|||
|
)
|
|||
|
// AccountName is expected to have a large maximum length
|
|||
|
|
|||
|
{
|
|||
|
if (RtlEqualSid(Sid, WorldSid)) {
|
|||
|
RtlInitString( AccountName, "WORLD");
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
if (RtlEqualSid(Sid, LocalSid)) {
|
|||
|
RtlInitString( AccountName, "LOCAL");
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
if (RtlEqualSid(Sid, NetworkSid)) {
|
|||
|
RtlInitString( AccountName, "NETWORK");
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
if (RtlEqualSid(Sid, BatchSid)) {
|
|||
|
RtlInitString( AccountName, "BATCH");
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
if (RtlEqualSid(Sid, InteractiveSid)) {
|
|||
|
RtlInitString( AccountName, "INTERACTIVE");
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
if (RtlEqualSid(Sid, LocalSystemSid)) {
|
|||
|
RtlInitString( AccountName, "SYSTEM");
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// if (RtlEqualSid(Sid, LocalManagerSid)) {
|
|||
|
// RtlInitString( AccountName, "LOCAL MANAGER");
|
|||
|
// return(TRUE);
|
|||
|
// }
|
|||
|
|
|||
|
// if (RtlEqualSid(Sid, LocalAdminSid)) {
|
|||
|
// RtlInitString( AccountName, "LOCAL ADMIN");
|
|||
|
// return(TRUE);
|
|||
|
// }
|
|||
|
|
|||
|
return(FALSE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DisplayAccountSid(
|
|||
|
PSID Sid
|
|||
|
)
|
|||
|
{
|
|||
|
UCHAR Buffer[128];
|
|||
|
STRING AccountName;
|
|||
|
UCHAR i;
|
|||
|
ULONG Tmp;
|
|||
|
PSID_IDENTIFIER_AUTHORITY IdentifierAuthority;
|
|||
|
UCHAR SubAuthorityCount;
|
|||
|
|
|||
|
Buffer[0] = 0;
|
|||
|
|
|||
|
AccountName.MaximumLength = 127;
|
|||
|
AccountName.Length = 0;
|
|||
|
AccountName.Buffer = (PVOID)&Buffer[0];
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (SidTranslation( (PSID)Sid, &AccountName) ) {
|
|||
|
|
|||
|
printf("%s\n", AccountName.Buffer );
|
|||
|
|
|||
|
} else {
|
|||
|
IdentifierAuthority = RtlIdentifierAuthoritySid(Sid);
|
|||
|
|
|||
|
//
|
|||
|
// HACK! HACK!
|
|||
|
// The next line prints the revision of the SID. Since there is no
|
|||
|
// rtl routine which gives us the SID revision, we must make due.
|
|||
|
// luckily, the revision field is the first field in the SID, so we
|
|||
|
// can just cast the pointer.
|
|||
|
//
|
|||
|
|
|||
|
printf("S-%u-", (USHORT) *((PUCHAR) Sid) );
|
|||
|
|
|||
|
if ( (IdentifierAuthority->Value[0] != 0) ||
|
|||
|
(IdentifierAuthority->Value[1] != 0) ){
|
|||
|
printf("0x%02hx%02hx%02hx%02hx%02hx%02hx",
|
|||
|
IdentifierAuthority->Value[0],
|
|||
|
IdentifierAuthority->Value[1],
|
|||
|
IdentifierAuthority->Value[2],
|
|||
|
IdentifierAuthority->Value[3],
|
|||
|
IdentifierAuthority->Value[4],
|
|||
|
IdentifierAuthority->Value[5] );
|
|||
|
} else {
|
|||
|
Tmp = IdentifierAuthority->Value[5] +
|
|||
|
(IdentifierAuthority->Value[4] << 8) +
|
|||
|
(IdentifierAuthority->Value[3] << 16) +
|
|||
|
(IdentifierAuthority->Value[2] << 24);
|
|||
|
printf("%lu", Tmp);
|
|||
|
}
|
|||
|
|
|||
|
SubAuthorityCount = *RtlSubAuthorityCountSid(Sid);
|
|||
|
for (i=0;i<SubAuthorityCount ;i++ ) {
|
|||
|
printf("-%lu", (*RtlSubAuthoritySid(Sid, i)));
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
InitVars()
|
|||
|
{
|
|||
|
ULONG SidWithZeroSubAuthorities;
|
|||
|
ULONG SidWithOneSubAuthority;
|
|||
|
ULONG SidWithThreeSubAuthorities;
|
|||
|
ULONG SidWithFourSubAuthorities;
|
|||
|
|
|||
|
SID_IDENTIFIER_AUTHORITY NullSidAuthority = SECURITY_NULL_SID_AUTHORITY;
|
|||
|
SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|||
|
SID_IDENTIFIER_AUTHORITY LocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY;
|
|||
|
SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
|
|||
|
|
|||
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The following SID sizes need to be allocated
|
|||
|
//
|
|||
|
|
|||
|
SidWithZeroSubAuthorities = RtlLengthRequiredSid( 0 );
|
|||
|
SidWithOneSubAuthority = RtlLengthRequiredSid( 1 );
|
|||
|
SidWithThreeSubAuthorities = RtlLengthRequiredSid( 3 );
|
|||
|
SidWithFourSubAuthorities = RtlLengthRequiredSid( 4 );
|
|||
|
|
|||
|
//
|
|||
|
// Allocate and initialize the universal SIDs
|
|||
|
//
|
|||
|
|
|||
|
NullSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
WorldSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
LocalSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
CreatorOwnerSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
|
|||
|
RtlInitializeSid( NullSid, &NullSidAuthority, 1 );
|
|||
|
RtlInitializeSid( WorldSid, &WorldSidAuthority, 1 );
|
|||
|
RtlInitializeSid( LocalSid, &LocalSidAuthority, 1 );
|
|||
|
RtlInitializeSid( CreatorOwnerSid, &CreatorSidAuthority, 1 );
|
|||
|
|
|||
|
*(RtlSubAuthoritySid( NullSid, 0 )) = SECURITY_NULL_RID;
|
|||
|
*(RtlSubAuthoritySid( WorldSid, 0 )) = SECURITY_WORLD_RID;
|
|||
|
*(RtlSubAuthoritySid( LocalSid, 0 )) = SECURITY_LOCAL_RID;
|
|||
|
*(RtlSubAuthoritySid( CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate and initialize the NT defined SIDs
|
|||
|
//
|
|||
|
|
|||
|
NtAuthoritySid = (PSID)malloc(SidWithZeroSubAuthorities);
|
|||
|
DialupSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
NetworkSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
BatchSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
InteractiveSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
LocalSystemSid = (PSID)malloc(SidWithOneSubAuthority);
|
|||
|
|
|||
|
RtlInitializeSid( NtAuthoritySid, &NtAuthority, 0 );
|
|||
|
RtlInitializeSid( DialupSid, &NtAuthority, 1 );
|
|||
|
RtlInitializeSid( NetworkSid, &NtAuthority, 1 );
|
|||
|
RtlInitializeSid( BatchSid, &NtAuthority, 1 );
|
|||
|
RtlInitializeSid( InteractiveSid, &NtAuthority, 1 );
|
|||
|
RtlInitializeSid( LocalSystemSid, &NtAuthority, 1 );
|
|||
|
|
|||
|
*(RtlSubAuthoritySid( DialupSid, 0 )) = SECURITY_DIALUP_RID;
|
|||
|
*(RtlSubAuthoritySid( NetworkSid, 0 )) = SECURITY_NETWORK_RID;
|
|||
|
*(RtlSubAuthoritySid( BatchSid, 0 )) = SECURITY_BATCH_RID;
|
|||
|
*(RtlSubAuthoritySid( InteractiveSid, 0 )) = SECURITY_INTERACTIVE_RID;
|
|||
|
*(RtlSubAuthoritySid( LocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
PrintAcl (
|
|||
|
IN PACL Acl
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine dumps an Acl for debug purposes (via printf). It is
|
|||
|
specialized to dump standard aces.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Acl - Supplies the Acl to dump
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
{
|
|||
|
ULONG i;
|
|||
|
PKNOWN_ACE Ace;
|
|||
|
BOOLEAN KnownType;
|
|||
|
PCHAR AceTypes[] = { "Access Allowed",
|
|||
|
"Access Denied ",
|
|||
|
"System Audit ",
|
|||
|
"System Alarm "
|
|||
|
};
|
|||
|
|
|||
|
if (Acl == NULL) {
|
|||
|
|
|||
|
printf("\tAcl == ALL ACCESS GRANTED!\n");
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the Acl header
|
|||
|
//
|
|||
|
|
|||
|
printf("\tRevision: %02x", Acl->AclRevision);
|
|||
|
printf(" Size: %04x", Acl->AclSize);
|
|||
|
printf(" AceCount: %04x\n", Acl->AceCount);
|
|||
|
|
|||
|
//
|
|||
|
// Now for each Ace we want do dump it
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0, Ace = FirstAce(Acl);
|
|||
|
i < Acl->AceCount;
|
|||
|
i++, Ace = NextAce(Ace) ) {
|
|||
|
|
|||
|
//
|
|||
|
// print out the ace header
|
|||
|
//
|
|||
|
|
|||
|
printf("\n\tAceHeader: %08lx ", *(PULONG)Ace);
|
|||
|
|
|||
|
//
|
|||
|
// special case on the standard ace types
|
|||
|
//
|
|||
|
|
|||
|
if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
|
|||
|
(Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
|
|||
|
(Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
|
|||
|
(Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE)) {
|
|||
|
|
|||
|
//
|
|||
|
// The following array is indexed by ace types and must
|
|||
|
// follow the allowed, denied, audit, alarm seqeuence
|
|||
|
//
|
|||
|
|
|||
|
PCHAR AceTypes[] = { "Access Allowed",
|
|||
|
"Access Denied ",
|
|||
|
"System Audit ",
|
|||
|
"System Alarm "
|
|||
|
};
|
|||
|
|
|||
|
printf(AceTypes[Ace->Header.AceType]);
|
|||
|
PrintAccessMask(Ace->Mask);
|
|||
|
KnownType = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
KnownType = FALSE;
|
|||
|
printf(" Unknown Ace Type\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
printf("\n");
|
|||
|
|
|||
|
printf("\tAceSize = %d\n",Ace->Header.AceSize);
|
|||
|
|
|||
|
printf("\tAce Flags = ");
|
|||
|
if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
|
|||
|
printf("OBJECT_INHERIT_ACE\n");
|
|||
|
printf(" ");
|
|||
|
}
|
|||
|
|
|||
|
if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
|
|||
|
printf("CONTAINER_INHERIT_ACE\n");
|
|||
|
printf(" ");
|
|||
|
}
|
|||
|
|
|||
|
if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
|
|||
|
printf("NO_PROPAGATE_INHERIT_ACE\n");
|
|||
|
printf(" ");
|
|||
|
}
|
|||
|
|
|||
|
if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
|
|||
|
printf("INHERIT_ONLY_ACE\n");
|
|||
|
printf(" ");
|
|||
|
}
|
|||
|
|
|||
|
if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
|
|||
|
printf("SUCCESSFUL_ACCESS_ACE_FLAG\n");
|
|||
|
printf(" ");
|
|||
|
}
|
|||
|
|
|||
|
if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
|
|||
|
printf("FAILED_ACCESS_ACE_FLAG\n");
|
|||
|
printf(" ");
|
|||
|
}
|
|||
|
|
|||
|
printf("\n");
|
|||
|
|
|||
|
printf("\tSid = ");
|
|||
|
DisplayAccountSid(&Ace->SidStart);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
PrintAccessMask(
|
|||
|
IN ACCESS_MASK AccessMask
|
|||
|
)
|
|||
|
{
|
|||
|
printf("\n\tAccess Mask: ");
|
|||
|
|
|||
|
if (AccessMask == KEY_ALL_ACCESS) {
|
|||
|
printf("KEY_ALL_ACCESS\n\t ");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (AccessMask == KEY_READ) {
|
|||
|
printf("KEY_READ\n\t ");
|
|||
|
return;
|
|||
|
}
|
|||
|
if (AccessMask == KEY_WRITE) {
|
|||
|
printf("KEY_WRITE\n\t ");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (AccessMask & KEY_QUERY_VALUE) {
|
|||
|
printf("KEY_QUERY_VALUE\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & KEY_SET_VALUE) {
|
|||
|
printf("KEY_SET_VALUE\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & KEY_CREATE_SUB_KEY) {
|
|||
|
printf("KEY_CREATE_SUB_KEY\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & KEY_ENUMERATE_SUB_KEYS) {
|
|||
|
printf("KEY_ENUMERATE_SUB_KEYS\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & KEY_NOTIFY) {
|
|||
|
printf("KEY_NOTIFY\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & KEY_CREATE_LINK) {
|
|||
|
printf("KEY_CREATE_LINK\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & GENERIC_ALL) {
|
|||
|
printf("GENERIC_ALL\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & GENERIC_EXECUTE) {
|
|||
|
printf("GENERIC_EXECUTE\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & GENERIC_WRITE) {
|
|||
|
printf("GENERIC_WRITE\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & GENERIC_READ) {
|
|||
|
printf("GENERIC_READ\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & GENERIC_READ) {
|
|||
|
printf("GENERIC_READ\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & MAXIMUM_ALLOWED) {
|
|||
|
printf("MAXIMUM_ALLOWED\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & ACCESS_SYSTEM_SECURITY) {
|
|||
|
printf("ACCESS_SYSTEM_SECURITY\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & WRITE_OWNER) {
|
|||
|
printf("WRITE_OWNER\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & WRITE_DAC) {
|
|||
|
printf("WRITE_DAC\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & READ_CONTROL) {
|
|||
|
printf("READ_CONTROL\n\t ");
|
|||
|
}
|
|||
|
if (AccessMask & DELETE) {
|
|||
|
printf("DELETE\n\t ");
|
|||
|
}
|
|||
|
}
|