|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
rtsetsec.c
Abstract:
NT level registry security test program
Assigns a world read-only security descriptor to an existing registry key object.
rtsetsec <KeyPath>
Example:
rtsetsec \REGISTRY\MACHINE\TEST\read_only
Author:
John Vert (jvert) 28-Jan-92
Revision History:
Richard Ward (richardw) 14 April 92 Changed ACE_HEADER
--*/
#include "cmp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
PSID GetMySid( VOID );
PSECURITY_DESCRIPTOR GenerateDescriptor( VOID );
void __cdecl main( int argc, char *argv[] ) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; ANSI_STRING AnsiKeyName; HANDLE KeyHandle; PSECURITY_DESCRIPTOR NewSecurityDescriptor;
//
// Process args
//
if (argc != 2) { printf("Usage: %s <KeyPath>\n",argv[0]); exit(1); }
RtlInitAnsiString(&AnsiKeyName, argv[1]); Status = RtlAnsiStringToUnicodeString(&KeyName, &AnsiKeyName, TRUE); if (!NT_SUCCESS(Status)) { printf("RtlAnsiStringToUnicodeString failed %lx\n",Status); exit(1); }
printf("rtsetsec: starting\n");
//
// Open node that we want to change the security descriptor for.
//
InitializeObjectAttributes( &ObjectAttributes, &KeyName, 0, (HANDLE)NULL, NULL ); ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
Status = NtOpenKey( &KeyHandle, WRITE_DAC, &ObjectAttributes ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: NtOpenKey failed: %08lx\n", Status); exit(1); }
NewSecurityDescriptor = GenerateDescriptor();
Status = NtSetSecurityObject( KeyHandle, DACL_SECURITY_INFORMATION, NewSecurityDescriptor); if (!NT_SUCCESS(Status)) { printf("rtsetsec: NtSetSecurity failed: %08lx\n",Status); exit(1); }
Status = NtClose(KeyHandle); if (!NT_SUCCESS(Status)) { printf("rtsetsec: NtClose failed: %08lx\n", Status); exit(1); }
printf("rtsetsec: successful\n");
}
PSECURITY_DESCRIPTOR GenerateDescriptor( VOID ) { PSECURITY_DESCRIPTOR SecurityDescriptor; PACL Acl; PSID WorldSid, CreatorSid; SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY; ULONG OwnerAceLength, WorldAceLength; ULONG AclLength; NTSTATUS Status; PACCESS_ALLOWED_ACE OwnerAce; PACCESS_ALLOWED_ACE WorldAce;
WorldSid = malloc(RtlLengthRequiredSid(1)); if (WorldSid == NULL) { printf("rtsetsec: GenerateDescriptor() couldn't malloc WorldSID\n"); exit(1); } RtlInitializeSid(WorldSid, &WorldAuthority, 1); *(RtlSubAuthoritySid(WorldSid, 0)) = SECURITY_WORLD_RID; if (!RtlValidSid(WorldSid)) { printf("rtsetsec: GenerateDescriptor() created invalid World SID\n"); exit(1); }
CreatorSid = GetMySid();
//
// Since the ACCESS_DENIED_ACE already contains a ULONG for the
// SID, we subtract this back out when calculating the size of the ACE
//
WorldAceLength = SeLengthSid(WorldSid) - sizeof(ULONG) + sizeof(ACCESS_ALLOWED_ACE) ; WorldAce = malloc(WorldAceLength); if (WorldAce == NULL) { printf("rtsetsec: GenerateDescriptor() couldn't malloc WorldAce\n"); exit(1); }
OwnerAceLength = SeLengthSid(CreatorSid) - sizeof(ULONG) + sizeof(ACCESS_ALLOWED_ACE);
OwnerAce = malloc( OwnerAceLength ); if (OwnerAce == NULL) { printf("rtsetsec: GenerateDescriptor() couldn't malloc OwnerAce\n"); exit(1); }
AclLength = OwnerAceLength + WorldAceLength + sizeof(ACL); Acl = malloc(AclLength); if (Acl == NULL) { printf("rtsetsec: GenerateDescriptor() couldn't malloc ACL\n"); exit(1); }
Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlCreateAcl failed status %08lx\n", Status); exit(1); }
//
// Fill in ACE fields
//
WorldAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; WorldAce->Header.AceSize = (USHORT)WorldAceLength; WorldAce->Header.AceFlags = 0; // clear audit and inherit flags
WorldAce->Mask = KEY_READ; Status = RtlCopySid( SeLengthSid(WorldSid), &WorldAce->SidStart, WorldSid ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlCopySid failed status %08lx\n", Status); exit(1); }
OwnerAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; OwnerAce->Header.AceSize = (USHORT)OwnerAceLength; OwnerAce->Header.AceFlags = 0; // clear audit and inherit flags
OwnerAce->Mask = KEY_ALL_ACCESS; Status = RtlCopySid( SeLengthSid(CreatorSid), &OwnerAce->SidStart, CreatorSid ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlCopySid failed status %08lx\n", Status); exit(1); }
free(WorldSid);
//
// Now add the ACE to the beginning of the ACL.
//
Status = RtlAddAce( Acl, ACL_REVISION, 0, WorldAce, WorldAceLength ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlAddAce (world ace) failed status %08lx\n", Status); exit(1); } Status = RtlAddAce( Acl, ACL_REVISION, 0, OwnerAce, OwnerAceLength ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlAddAce (owner ace) failed status %08lx\n", Status); exit(1); }
free(OwnerAce); free(WorldAce);
//
// Allocate and initialize the Security Descriptor
//
SecurityDescriptor = malloc(sizeof(SECURITY_DESCRIPTOR)); Status = RtlCreateSecurityDescriptor( SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlCreateSecurityDescriptor failed status %08lx\n",Status); exit(1); }
Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor, TRUE, Acl, FALSE ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: RtlSetDaclSecurityDescriptor failed status %08lx\n",Status); exit(1); }
//
// FINALLY we are finished!
//
return(SecurityDescriptor);
}
PSID GetMySid( VOID ) { NTSTATUS Status; HANDLE Token; PTOKEN_OWNER Owner; ULONG Length;
Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &Token ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: GetMySid() NtOpenProcessToken failed status %08lx\n",Status); exit(1); }
Status = NtQueryInformationToken( Token, TokenOwner, Owner, 0, &Length ); if (Status != STATUS_BUFFER_TOO_SMALL) { printf("rtsetsec: GetMySid() NtQueryInformationToken failed status %08lx\n",Status); exit(1); }
Owner = malloc(Length); if (Owner==NULL) { printf("rtsetsec: GetMySid() Couldn't malloc TOKEN_OWNER buffer\n"); exit(1); } Status = NtQueryInformationToken( Token, TokenOwner, Owner, Length, &Length ); if (!NT_SUCCESS(Status)) { printf("rtsetsec: GetMySid() NtQueryInformationToken failed status %08lx\n",Status); exit(1); }
NtClose(Token);
return(Owner->Owner);
}
|