|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Regsckey.c
Abstract:
This module contains the server side implementation for the Win32 Registry APIs to set and get the SECURITY_DESCRIPTOR for a key. That is:
- BaseRegGetKeySecurity - BaseRegSetKeySecurity
Author:
David J. Gilman (davegi) 10-Feb-1992
Notes:
See the Notes in Regkey.c.
--*/
#include <rpc.h>
#include "regrpc.h"
#include "localreg.h"
#ifdef LOCAL
#include "tsappcmp.h"
#endif
error_status_t BaseRegGetKeySecurity( HKEY hKey, SECURITY_INFORMATION RequestedInformation, PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor )
/*++
Routine Description:
This API returns a copy of the security descriptor protecting a previously opened key. Based on the caller's access rights and privileges, this API returns a security descriptor containing the requested security descriptor fields. To read the supplied key's security descriptor the caller must be granted READ_CONTROL access or be the owner of the object. In addition, the caller must have SeSecurityPrivilege privilege to read the system ACL.
Arguments:
hKey - Supplies a handle to a previously opened key.
SecurityInformation - Supplies the information needed to determine the type of security returned in the SECURITY_DESCRIPTOR.
pSecurityDescriptor - Supplies a pointer to a buffer where the requested SECURITY_DESCRIPTOR will be written.
lpcbSecurityDescriptor - Supplies a pointer to a DWORD which on input contains the size, in bytes, of the supplied SECURITY_DESCRIPTOR buffer. On output it contains the actual number of bytes required by the SECURITY_DESCRIPTOR.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
Notes:
If the buffer size passed in is too small, the correct value will be returned through lpcbSecurityDescriptor and the API will return, ERROR_INVALID_PARAMETER.
--*/
{ NTSTATUS Status; PSECURITY_DESCRIPTOR lpSD; DWORD cbLen; DWORD Error = ERROR_SUCCESS; HKEY hPerflibKey = NULL; OBJECT_ATTRIBUTES Obja;
if( pRpcSecurityDescriptor == NULL ) { //
// malicious client/RPC attack
//
return ERROR_INVALID_PARAMETER; }
if (hKey == HKEY_PERFORMANCE_DATA || hKey == HKEY_PERFORMANCE_TEXT || hKey == HKEY_PERFORMANCE_NLSTEXT ) { //
// For these special cases, get the hKey for Perflib
// and return the Perflib's Security Info
//
UNICODE_STRING PerflibSubKeyString; BOOL bNeedSACL;
bNeedSACL = RequestedInformation & SACL_SECURITY_INFORMATION;
RtlInitUnicodeString ( &PerflibSubKeyString, L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib");
//
// Initialize the OBJECT_ATTRIBUTES structure and open the key.
//
InitializeObjectAttributes( &Obja, &PerflibSubKeyString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenKey( &hPerflibKey, bNeedSACL ? MAXIMUM_ALLOWED | ACCESS_SYSTEM_SECURITY : MAXIMUM_ALLOWED, &Obja );
if ( ! NT_SUCCESS( Status )) {
Error = RtlNtStatusToDosError( Status ); pRpcSecurityDescriptor->cbInSecurityDescriptor = 0; pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0; return (error_status_t)Error; }
hKey = hPerflibKey;
} else { ASSERT( IsPredefinedRegistryHandle( hKey ) == FALSE ); }
//
// Allocate space for the security descriptor
//
lpSD = (PSECURITY_DESCRIPTOR) RtlAllocateHeap( RtlProcessHeap(), 0, pRpcSecurityDescriptor->cbInSecurityDescriptor );
if ( !lpSD ) {
Error = ERROR_OUTOFMEMORY;
} else {
Status = NtQuerySecurityObject( hKey, RequestedInformation, lpSD, pRpcSecurityDescriptor->cbInSecurityDescriptor, &cbLen );
//
// If the call fails, set the size of the buffer to zero so RPC
// won't copy any data.
//
if( ! NT_SUCCESS( Status )) {
Error = RtlNtStatusToDosError( Status );
} else {
//
// Convert the security descriptor to a Self-relative form
//
Error = MapSDToRpcSD ( lpSD, pRpcSecurityDescriptor ); }
if ( Error != ERROR_SUCCESS ) { pRpcSecurityDescriptor->cbInSecurityDescriptor = cbLen; pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0; }
//
// Free the buffer that we allocated for the security descriptor
//
RtlFreeHeap( RtlProcessHeap(), 0, lpSD ); }
if (hPerflibKey) { // Close the Perflib that was created in the special cases
NtClose(hPerflibKey); }
return (error_status_t)Error; }
error_status_t BaseRegSetKeySecurity( HKEY hKey, SECURITY_INFORMATION SecurityInformation, PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor )
/*++
Routine Description:
This API can be used to set the security of a previously opened key. This call is only successful if the following conditions are met:
o If the key's owner or group is to be set, the caller must have WRITE_OWNER permission or have SeTakeOwnershipPrivilege.
o If the key's DACL is to be set, the caller must have WRITE_DAC permission or be the object's owner.
o If the key's SACL is to be set, the caller must have SeSecurityPrivilege.
Arguments:
hKey - Supplies a handle to a previously opened key.
SecurityInformation - Supplies a pointer to a SECURITY_INFORMATION structure that specifies the contents of the supplied SECURITY_DESCRIPTOR.
pSecurityDescriptor - Supplies a pointer to the SECURITY_DESCRIPTOR to set on the supplied key.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ NTSTATUS Status;
if( pRpcSecurityDescriptor == NULL || pRpcSecurityDescriptor->lpSecurityDescriptor == NULL ) { //
// malicious client/RPC attack
//
return ERROR_INVALID_PARAMETER; }
if (hKey == HKEY_PERFORMANCE_DATA || hKey == HKEY_PERFORMANCE_TEXT || hKey == HKEY_PERFORMANCE_NLSTEXT ) { //
// these keys get their security descriptor from
// other "real" registry keys.
//
Status = STATUS_INVALID_HANDLE; } else { ASSERT( IsPredefinedRegistryHandle( hKey ) == FALSE );
RPC_IMPERSONATE_CLIENT( NULL );
//
// Validate the security descriptor.
//
if( RtlValidRelativeSecurityDescriptor((PSECURITY_DESCRIPTOR)(pRpcSecurityDescriptor->lpSecurityDescriptor), pRpcSecurityDescriptor->cbInSecurityDescriptor, SecurityInformation )) { Status = NtSetSecurityObject( hKey, SecurityInformation, pRpcSecurityDescriptor->lpSecurityDescriptor ); } else { //
// We were passed a bogus security descriptor to set. Bail out
//
Status = STATUS_INVALID_PARAMETER; }
RPC_REVERT_TO_SELF(); }
#ifdef LOCAL
if (NT_SUCCESS(Status) && gpfnTermsrvSetKeySecurity) { gpfnTermsrvSetKeySecurity(hKey, SecurityInformation, pRpcSecurityDescriptor->lpSecurityDescriptor); } #endif
return (error_status_t)RtlNtStatusToDosError( Status ); }
|