You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
9.2 KiB
379 lines
9.2 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Regsckey.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the client side wrappers for the Win32 Registry
|
|
APIs to set and get the SECURITY_DESCRIPTOR for a key. That is:
|
|
|
|
- RegGetKeySecurity
|
|
- RegSetKeySecurity
|
|
|
|
Author:
|
|
|
|
David J. Gilman (davegi) 18-Mar-1992
|
|
|
|
Notes:
|
|
|
|
See the notes in server\regsckey.c.
|
|
|
|
--*/
|
|
|
|
#include <rpc.h>
|
|
#include "regrpc.h"
|
|
#include "client.h"
|
|
#include <wow64reg.h>
|
|
|
|
NTSTATUS BaseRegGetUserAndMachineClass(
|
|
PVOID pKeySemantics,
|
|
HKEY hKey,
|
|
REGSAM samDesired,
|
|
PHKEY phkMachine,
|
|
PHKEY phkUser);
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegGetKeySecurity (
|
|
HKEY hKey,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
LPDWORD lpcbSecurityDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Win32 RPC wrapper for getting a key's security descriptor.
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_SECURITY_DESCRIPTOR RpcSD;
|
|
LONG Error;
|
|
REGSAM DesiredAccess;
|
|
HKEY hkSpecialHandle = NULL;
|
|
|
|
HKEY hkMachineClass;
|
|
HKEY hkUserClass;
|
|
HKEY hkClassKey = NULL;
|
|
|
|
BOOL fClassesRoot = FALSE;
|
|
HKEY TempHandle = NULL;
|
|
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
if( lpcbSecurityDescriptor == NULL ) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (HKEY_CLASSES_ROOT == hKey) {
|
|
fClassesRoot = TRUE;
|
|
}
|
|
|
|
if( IsPredefinedRegistryHandle( hKey ) &&
|
|
( ( RequestedInformation & SACL_SECURITY_INFORMATION ) != 0 )
|
|
) {
|
|
//
|
|
// If SACL is to be retrieved, open a handle with special access
|
|
//
|
|
DesiredAccess = ACCESS_SYSTEM_SECURITY;
|
|
if( ( RequestedInformation &
|
|
( DACL_SECURITY_INFORMATION |
|
|
OWNER_SECURITY_INFORMATION |
|
|
GROUP_SECURITY_INFORMATION
|
|
) ) != 0 ) {
|
|
DesiredAccess |= READ_CONTROL;
|
|
}
|
|
|
|
Error = OpenPredefinedKeyForSpecialAccess( hKey,
|
|
DesiredAccess,
|
|
&hKey );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
return( Error );
|
|
}
|
|
ASSERT( IsLocalHandle( hKey ) );
|
|
hkSpecialHandle = hKey;
|
|
|
|
} else {
|
|
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
|
|
|
DesiredAccess = MAXIMUM_ALLOWED;
|
|
}
|
|
|
|
if( hKey == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
if (IsLocalHandle( hKey )) {
|
|
|
|
NTSTATUS Status;
|
|
|
|
if (IsSpecialClassesHandle( hKey ) || fClassesRoot) {
|
|
|
|
Status = BaseRegGetUserAndMachineClass(
|
|
NULL,
|
|
hKey,
|
|
DesiredAccess,
|
|
&hkMachineClass,
|
|
&hkUserClass);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
Error = (error_status_t) RtlNtStatusToDosError(Status);
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
if (hkMachineClass && hkUserClass) {
|
|
|
|
if (hkMachineClass != hKey) {
|
|
hkClassKey = hkMachineClass;
|
|
} else {
|
|
hkClassKey = hkUserClass;
|
|
}
|
|
|
|
if (fClassesRoot) {
|
|
hKey = hkMachineClass;
|
|
} else {
|
|
hKey = hkUserClass;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
|
|
//
|
|
RpcSD.lpSecurityDescriptor = pSecurityDescriptor;
|
|
RpcSD.cbInSecurityDescriptor = *lpcbSecurityDescriptor;
|
|
RpcSD.cbOutSecurityDescriptor = 0;
|
|
|
|
if( IsLocalHandle( hKey )) {
|
|
|
|
Error = (LONG)LocalBaseRegGetKeySecurity(
|
|
hKey,
|
|
RequestedInformation,
|
|
&RpcSD
|
|
);
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegGetKeySecurity(
|
|
DereferenceRemoteHandle( hKey ),
|
|
RequestedInformation,
|
|
&RpcSD
|
|
);
|
|
}
|
|
|
|
//
|
|
// Extract the size of the SECURITY_DESCRIPTOR from the RPCable version.
|
|
//
|
|
|
|
*lpcbSecurityDescriptor = RpcSD.cbInSecurityDescriptor;
|
|
|
|
if (hkClassKey) {
|
|
NtClose(hkClassKey);
|
|
}
|
|
|
|
ExitCleanup:
|
|
if(hkSpecialHandle) {
|
|
RegCloseKey(hkSpecialHandle);
|
|
}
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
|
|
}
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegSetKeySecurity(
|
|
HKEY hKey,
|
|
SECURITY_INFORMATION SecurityInformation,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Win32 RPC wrapper for setting a key's security descriptor.
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_SECURITY_DESCRIPTOR RpcSD;
|
|
LONG Error;
|
|
REGSAM DesiredAccess;
|
|
|
|
HKEY hkSpecialHandle = NULL;
|
|
HKEY hkMachineClass;
|
|
HKEY hkUserClass;
|
|
HKEY hkClassKey = NULL;
|
|
|
|
BOOL fClassesRoot = FALSE;
|
|
HKEY TempHandle = NULL;
|
|
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
if (HKEY_CLASSES_ROOT == hKey) {
|
|
fClassesRoot = TRUE;
|
|
}
|
|
|
|
if( IsPredefinedRegistryHandle( hKey ) &&
|
|
( ( SecurityInformation & SACL_SECURITY_INFORMATION ) != 0 )
|
|
) {
|
|
//
|
|
// If the SACL is to be set, open a handle with
|
|
// special access
|
|
//
|
|
DesiredAccess = MAXIMUM_ALLOWED | ACCESS_SYSTEM_SECURITY;
|
|
if( SecurityInformation & DACL_SECURITY_INFORMATION ) {
|
|
DesiredAccess |= WRITE_DAC;
|
|
} else if( SecurityInformation & OWNER_SECURITY_INFORMATION ) {
|
|
DesiredAccess |= WRITE_OWNER;
|
|
}
|
|
|
|
Error = OpenPredefinedKeyForSpecialAccess( hKey,
|
|
DesiredAccess,
|
|
&hKey );
|
|
if( Error != ERROR_SUCCESS ) {
|
|
return( Error );
|
|
}
|
|
ASSERT( IsLocalHandle( hKey ) );
|
|
hkSpecialHandle = hKey;
|
|
|
|
} else {
|
|
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
|
|
|
DesiredAccess = MAXIMUM_ALLOWED;
|
|
}
|
|
|
|
if( hKey == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
if (IsLocalHandle( hKey )) {
|
|
|
|
NTSTATUS Status;
|
|
|
|
if (IsSpecialClassesHandle( hKey ) || fClassesRoot) {
|
|
|
|
Status = BaseRegGetUserAndMachineClass(
|
|
NULL,
|
|
hKey,
|
|
DesiredAccess,
|
|
&hkMachineClass,
|
|
&hkUserClass);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
Error = (error_status_t) RtlNtStatusToDosError(Status);
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
if (hkMachineClass && hkUserClass) {
|
|
|
|
if (hkMachineClass != hKey) {
|
|
hkClassKey = hkMachineClass;
|
|
} else {
|
|
hkClassKey = hkUserClass;
|
|
}
|
|
|
|
if (fClassesRoot) {
|
|
hKey = hkMachineClass;
|
|
} else {
|
|
hKey = hkUserClass;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
|
|
//
|
|
RpcSD.lpSecurityDescriptor = NULL;
|
|
|
|
Error = MapSDToRpcSD(
|
|
pSecurityDescriptor,
|
|
&RpcSD
|
|
);
|
|
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
if( IsLocalHandle( hKey )) {
|
|
|
|
Error = (LONG)LocalBaseRegSetKeySecurity (
|
|
hKey,
|
|
SecurityInformation,
|
|
&RpcSD
|
|
);
|
|
#if defined(_WIN64)
|
|
if ( Error == 0)
|
|
Wow64RegSetKeyDirty (hKey);
|
|
#endif
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegSetKeySecurity (
|
|
DereferenceRemoteHandle( hKey ),
|
|
SecurityInformation,
|
|
&RpcSD
|
|
);
|
|
}
|
|
|
|
//
|
|
// Free the buffer allocated by MapSDToRpcSD.
|
|
//
|
|
|
|
RtlFreeHeap(
|
|
RtlProcessHeap( ), 0,
|
|
RpcSD.lpSecurityDescriptor
|
|
);
|
|
|
|
if (hkClassKey) {
|
|
NtClose(hkClassKey);
|
|
}
|
|
|
|
ExitCleanup:
|
|
if(hkSpecialHandle) {
|
|
RegCloseKey(hkSpecialHandle);
|
|
}
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|