Leaked source code of windows server 2003
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.
 
 
 
 
 
 

802 lines
18 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
Predefh.c
Abstract:
This module contains routines for opening the Win32 Registry API's
predefined handles.
A predefined handle is used as a root to an absolute or relative
sub-tree in the real Nt Registry. An absolute predefined handle maps
to a specific key within the Registry. A relative predefined handle
maps to a key relative to some additional information such as the
current user.
Predefined handles are strictly part of the Win32 Registry API. The
Nt Registry API knows nothing about them.
A predefined handle can be used anywhere that a non-predefined handle
(i.e. one returned from RegCreateKey(), RegOpenKey() or
RegConnectRegistry()) can be used.
Author:
David J. Gilman (davegi) 15-Nov-1991
--*/
#include <rpc.h>
#include "regrpc.h"
#include "localreg.h"
#include "regclass.h"
#include "ntconreg.h"
#include "regsec.h"
#ifdef LOCAL
#include "tsappcmp.h"
#if defined(LEAK_TRACK)
#include "regleak.h"
#endif // LEAK_TRACK
#endif
//
// Determine the length of a Unicode string w/o the trailing NULL.
//
#define LENGTH( str ) ( sizeof( str ) - sizeof( UNICODE_NULL ))
//
// Nt Registry name space.
//
#define MACHINE L"\\REGISTRY\\MACHINE"
#define USER L"\\REGISTRY\\USER"
#define CLASSES L"\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES"
#define CURRENTCONFIG L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT"
extern const
UNICODE_STRING MachineStringKey = {
LENGTH( MACHINE ),
LENGTH( MACHINE ),
MACHINE
};
extern const
UNICODE_STRING UserStringKey = {
LENGTH( USER ),
LENGTH( USER ),
USER
};
extern const
UNICODE_STRING ClassesStringKey = {
LENGTH( CLASSES ),
LENGTH( CLASSES ),
CLASSES
};
extern const
UNICODE_STRING CurrentConfigStringKey = {
LENGTH( CURRENTCONFIG ),
LENGTH( CURRENTCONFIG ),
CURRENTCONFIG
};
HANDLE RestrictedMachineHandle = NULL;
NTSTATUS
InitSecurityAcls(PSECURITY_DESCRIPTOR *SecurityDescriptor)
/*++
Routine Description:
Gives GENERIC_ALL to admins and denies WRITE_OWNER | WRITE_DAC from everyone
Arguments:
Return Value:
--*/
{
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
PSID BuiltInAdministrators = NULL;
PSID Everyone = NULL;
NTSTATUS Status;
ULONG AclSize;
ACL *Acl;
*SecurityDescriptor = NULL;
Status = RtlAllocateAndInitializeSid(
&WorldAuthority,
1,
SECURITY_WORLD_RID,
0,0,0,0,0,0,0,
&Everyone );
if( !NT_SUCCESS(Status) ) {
goto Exit;
}
Status = RtlAllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,0,0,0,0,0,
&BuiltInAdministrators );
if( !NT_SUCCESS(Status) ) {
goto Exit;
}
AclSize = sizeof (ACL) +
(2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
GetLengthSid(BuiltInAdministrators) +
GetLengthSid(Everyone);
*SecurityDescriptor = (PSECURITY_DESCRIPTOR)RtlAllocateHeap( RtlProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
if (!*SecurityDescriptor) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
Acl = (ACL *)((BYTE *)(*SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH);
Status = RtlCreateAcl( Acl,
AclSize,
ACL_REVISION);
if( !NT_SUCCESS(Status) ) {
goto Exit;
}
Status = RtlAddAccessAllowedAce(Acl,
ACL_REVISION,
(KEY_ALL_ACCESS & ~(WRITE_OWNER | WRITE_DAC)),
Everyone);
if( !NT_SUCCESS(Status) ) {
goto Exit;
}
Status = RtlAddAccessAllowedAce(Acl,
ACL_REVISION,
GENERIC_ALL,
BuiltInAdministrators);
if( !NT_SUCCESS(Status) ) {
goto Exit;
}
Status = RtlCreateSecurityDescriptor(
*SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION
);
if( !NT_SUCCESS(Status) ) {
goto Exit;
}
Status = RtlSetDaclSecurityDescriptor( *SecurityDescriptor,
TRUE,
Acl,
FALSE);
Exit:
if( Everyone ) {
RtlFreeSid( Everyone );
}
if( BuiltInAdministrators ) {
RtlFreeSid( BuiltInAdministrators );
}
return Status;
}
error_status_t
OpenClassesRoot(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_CLASSES_ROOT predefined handle.
Arguments:
ServerName - Not used.
samDesired - This access mask describes the desired security access
for the key.
phKey - Returns a handle to the key \REGISTRY\MACHINE\SOFTWARE\CLASSES.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
UNICODE_STRING UsersHive;
UNICODE_STRING UsersMergedHive;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
#ifdef LOCAL
//
// Multiuser CLASSES key so each user has their own key. If opening
// CLASSES in execute mode - open it under HKEY_CURRENT_USER else
// just let it fall thru here and open the global one.
//
if (gpfnTermsrvOpenUserClasses) {
Status = gpfnTermsrvOpenUserClasses(samDesired,phKey);
} else {
*phKey = NULL;
}
if (!(*phKey)) {
#endif // LOCAL
//
// Initialize the SECURITY_DESCRIPTOR.
//
Status = InitSecurityAcls(&SecurityDescriptor);
if( ! NT_SUCCESS( Status )) {
goto error_exit;
}
#ifdef LOCAL
if (gbCombinedClasses) {
// first try for a per-user HKCR
Status = OpenCombinedClassesRoot( samDesired, phKey );
if ( NT_SUCCESS( Status ) ) {
goto error_exit;
}
}
#endif
//
// Initialize the OBJECT_ATTRIBUTES structure so that it creates
// (opens) the key "\REGISTRY\MACHINE\SOFTWARE\CLASSES" with a Security
// Descriptor that allows everyone complete access.
//
InitializeObjectAttributes(
&Obja,
(PUNICODE_STRING)&ClassesStringKey,
OBJ_CASE_INSENSITIVE,
NULL,
SecurityDescriptor
);
Status = NtCreateKey(
phKey,
samDesired, // MAXIMUM_ALLOWED,
&Obja,
0,
NULL,
REG_OPTION_NON_VOLATILE,
NULL
);
#ifdef LOCAL
}
#endif // LOCAL
#if DBG
if( ! NT_SUCCESS( Status )) {
DbgPrint(
"Winreg Server: "
"Creating HKEY_CLASSES_ROOT failed, status = 0x%x\n",
Status
);
}
#endif
error_exit:
if( SecurityDescriptor != NULL ) {
RtlFreeHeap( RtlProcessHeap(), 0, SecurityDescriptor );
}
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status );
}
error_status_t
OpenCurrentUser(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_CURRENT_USER predefined handle.
Arguments:
ServerName - Not used.
samDesired - This access mask describes the desired security access
for the key.
phKey - Returns a handle to the key \REGISTRY\USER\*.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{
NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
//
// Open the registry key.
//
Status = RtlOpenCurrentUser( samDesired, /* MAXIMUM_ALLOWED, */ phKey );
RPC_REVERT_TO_SELF();
//
// Map the returned status
//
return (error_status_t)RtlNtStatusToDosError( Status );
}
error_status_t
OpenLocalMachine(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempt to open the the HKEY_LOCAL_MACHINE predefined handle.
Arguments:
ServerName - Not used.
samDesired - This access mask describes the desired security access
for the key.
phKey - Returns a handle to the key \REGISTRY\MACHINE.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
InitializeObjectAttributes(
&Obja,
(PUNICODE_STRING)&MachineStringKey,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
phKey,
samDesired, // MAXIMUM_ALLOWED,
&Obja
);
#if DBG
if( ! NT_SUCCESS( Status )) {
DbgPrint(
"Winreg Server: "
"Opening HKEY_LOCAL_MACHINE failed, status = 0x%x\n",
Status
);
}
#endif
if ( NT_SUCCESS( Status ) )
{
if (! REGSEC_CHECK_REMOTE( phKey ) )
{
ASSERT( RestrictedMachineHandle != NULL );
NtClose(*phKey);
*phKey = REGSEC_FLAG_HANDLE( RestrictedMachineHandle, CHECK_MACHINE_PATHS );
}
}
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status );
}
error_status_t
OpenUsers(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_USERS predefined handle.
Arguments:
ServerName - Not used.
samDesired - This access mask describes the desired security access
for the key.
phKey - Returns a handle to the key \REGISTRY\USER.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
InitializeObjectAttributes(
&Obja,
(PUNICODE_STRING)&UserStringKey,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
phKey,
samDesired, // MAXIMUM_ALLOWED,
&Obja
);
#if DBG
if( ! NT_SUCCESS( Status )) {
DbgPrint(
"Winreg Server: "
"Opening HKEY_USERS failed, status = 0x%x\n",
Status
);
}
#endif
/*
if ( NT_SUCCESS( Status ) )
{
if (! REGSEC_CHECK_REMOTE( phKey ) )
{
*phKey = REGSEC_FLAG_HANDLE( *phKey, CHECK_USER_PATHS );
}
}
*/
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status );
}
error_status_t
OpenCurrentConfig(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_CURRENT_CONFIG predefined handle.
Arguments:
ServerName - Not used.
samDesired - This access mask describes the desired security access
for the key.
phKey - Returns a handle to the key \REGISTRY\MACHINE\SYSTEM\CURRENTCONTROLSET\HARDWARE PROFILES\CURRENT
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
InitializeObjectAttributes(
&Obja,
(PUNICODE_STRING)&CurrentConfigStringKey,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
phKey,
samDesired, // MAXIMUM_ALLOWED,
&Obja
);
#if DBG
if( ! NT_SUCCESS( Status )) {
DbgPrint(
"Winreg Server: "
"Opening HKEY_CURRENT_CONFIG failed, status = 0x%x\n",
Status
);
}
#endif
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status );
}
error_status_t
OpenPerformanceData(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_PERFORMANCE_DATA predefined handle.
Arguments:
ServerName - Not used.
samDesired - Not used.
phKey - Returns a the predefined handle HKEY_PERFORMANCE_DATA.
Return Value:
Returns ERROR_SUCCESS (0) for success;
or a DOS (not NT) error-code for failure.
--*/
{
NTSTATUS status;
if ( 0 ) {
DBG_UNREFERENCED_PARAMETER(ServerName);
DBG_UNREFERENCED_PARAMETER(samDesired);
}
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
if ( ! REGSEC_CHECK_PERF( phKey ) )
{
RPC_REVERT_TO_SELF();
return( ERROR_ACCESS_DENIED );
}
// Move lodctr/unlodctr access check to part of PerfOpenKey()
status = PerfOpenKey( HKEY_PERFORMANCE_DATA );
RPC_REVERT_TO_SELF();
*phKey = (RPC_HKEY) HKEY_PERFORMANCE_DATA;
return ERROR_SUCCESS;
}
error_status_t
OpenPerformanceText(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
Arguments:
ServerName - Not used.
samDesired - Not used.
phKey - Returns the predefined handle HKEY_PERFORMANCE_TEXT.
Return Value:
Returns ERROR_SUCCESS (0) for success;
or a DOS (not NT) error-code for failure.
--*/
{
error_status_t Status = ERROR_SUCCESS;
// No need to call OpenPerformanceData for getting text (HWC 4/1994)
// Status = OpenPerformanceData(ServerName, samDesired, phKey);
// if (Status==ERROR_SUCCESS) {
*phKey = HKEY_PERFORMANCE_TEXT;
// }
return(Status);
}
error_status_t
OpenPerformanceNlsText(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
Arguments:
ServerName - Not used.
samDesired - Not used.
phKey - Returns the predefined handle HKEY_PERFORMANCE_NLSTEXT.
Return Value:
Returns ERROR_SUCCESS (0) for success;
or a DOS (not NT) error-code for failure.
--*/
{
error_status_t Status = ERROR_SUCCESS;
// No need to call OpenPerformanceData for getting text (HWC 4/1994)
// Status = OpenPerformanceData(ServerName, samDesired, phKey);
// if (Status==ERROR_SUCCESS) {
*phKey = HKEY_PERFORMANCE_NLSTEXT;
// }
return(Status);
}
error_status_t
OpenDynData(
IN PREGISTRY_SERVER_NAME ServerName,
IN REGSAM samDesired,
OUT PRPC_HKEY phKey
)
/*++
Routine Description:
Attempts to open the the HKEY_DYN_DATA predefined handle.
There is currently no HKEY_DYN_DATA on NT, thus this
function always returns ERROR_CALL_NOT_IMPLEMENTED.
Arguments:
ServerName - Not used.
samDesired - This access mask describes the desired security access
for the key.
phKey - Returns a handle to the key HKEY_DYN_DATA
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{
return((error_status_t)ERROR_CALL_NOT_IMPLEMENTED);
}
//
// Default ("fake") handle returned to all check_machine_paths-like connections
//
NTSTATUS
OpenMachineKey(PHANDLE phKey)
{
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
InitializeObjectAttributes(
&Obja,
(PUNICODE_STRING)&MachineStringKey,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
phKey,
MAXIMUM_ALLOWED,
&Obja
);
return Status;
}
NTSTATUS
InitRestrictedMachineHandle()
{
return OpenMachineKey(&RestrictedMachineHandle);
}
VOID
CleanupRestrictedMachineHandle()
{
if( RestrictedMachineHandle != NULL ) {
NtClose(RestrictedMachineHandle);
RestrictedMachineHandle = NULL;
}
}