windows-nt/Source/XPSP1/NT/base/screg/winreg/server/regsckey.c
2020-09-26 16:20:57 +08:00

294 lines
7.8 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) 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 = 0;
OBJECT_ATTRIBUTES Obja;
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 (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 );
}