windows-nt/Source/XPSP1/NT/base/ntos/config/test/rtdmpsec.c
2020-09-26 16:20:57 +08:00

793 lines
18 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 ");
}
}