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.
309 lines
8.5 KiB
309 lines
8.5 KiB
/*++
|
|
|
|
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 );
|
|
}
|