|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
safepolr.c (SAFER Code Authorization Policy)
Abstract:
This module implements the WinSAFER APIs that query and set the persisted and cached policy definitions.
Author:
Jeffrey Lawson (JLawson) - Apr 1999
Environment:
User mode only.
Exported Functions:
Revision History:
Created - Apr 1999
--*/
#include "pch.h"
#pragma hdrstop
#include <winsafer.h>
#include <winsaferp.h>
#include "saferp.h"
NTSTATUS NTAPI CodeAuthzPol_GetInfoCached_LevelListRaw( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) /*++
Routine Description:
Asks the system to query for the list of available WinSafer Levels for the currently loaded policy scope.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - optionally specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - optionally specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
InfoBufferRetSize - optionally specifies a pointer that will receive the size of the results actually written to the InfoBuffer.
Return Value:
Returns STATUS_SUCCESS on successful return. Otherwise a status code such as STATUS_BUFFER_TOO_SMALL or STATUS_NOT_FOUND.
--*/ { NTSTATUS Status; PVOID RestartKey; PAUTHZLEVELTABLERECORD authzobj; DWORD dwSizeNeeded; LPVOID lpNextPtr, lpEndBuffer;
//
// Load the list of all of the available objects.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE && dwScopeId != SAFER_SCOPEID_USER) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } if (g_bNeedCacheReload) { Status = CodeAuthzpImmediateReloadCacheTables(); if (!NT_SUCCESS(Status)) { goto ExitHandler2; } } if (RtlIsGenericTableEmpty(&g_CodeLevelObjTable)) { Status = STATUS_NOT_FOUND; goto ExitHandler2; }
//
// Determine the necessary size needed to store a DWORD array
// of all of the Levels that were found in this scope.
//
dwSizeNeeded = 0; RestartKey = NULL; for (authzobj = (PAUTHZLEVELTABLERECORD) RtlEnumerateGenericTableWithoutSplaying( &g_CodeLevelObjTable, &RestartKey); authzobj != NULL; authzobj = (PAUTHZLEVELTABLERECORD) RtlEnumerateGenericTableWithoutSplaying( &g_CodeLevelObjTable, &RestartKey)) { if (authzobj->isEnumerable) { //only allow enumeration if the level is enumerable
dwSizeNeeded += sizeof(DWORD); } }
if (!ARGUMENT_PRESENT(InfoBuffer) || !InfoBufferSize || InfoBufferSize < dwSizeNeeded) { if (ARGUMENT_PRESENT(InfoBufferRetSize)) *InfoBufferRetSize = dwSizeNeeded;
Status = STATUS_BUFFER_TOO_SMALL; goto ExitHandler2; }
//
// Fill the buffer with the resulting data.
//
lpNextPtr = (LPVOID) InfoBuffer; lpEndBuffer = (LPVOID) ( ((LPBYTE) InfoBuffer) + InfoBufferSize); RestartKey = NULL; for (authzobj = (PAUTHZLEVELTABLERECORD) RtlEnumerateGenericTableWithoutSplaying( &g_CodeLevelObjTable, &RestartKey); authzobj != NULL; authzobj = (PAUTHZLEVELTABLERECORD) RtlEnumerateGenericTableWithoutSplaying( &g_CodeLevelObjTable, &RestartKey)) { if (authzobj->isEnumerable) { //only allow enumeration if the level is enumerable
*((PDWORD)lpNextPtr) = authzobj->dwLevelId; lpNextPtr = (LPVOID) ( ((PBYTE) lpNextPtr) + sizeof(DWORD)); } } ASSERT(lpNextPtr <= lpEndBuffer);
//
// Return the final buffer size and result code.
//
if (ARGUMENT_PRESENT(InfoBufferRetSize)) *InfoBufferRetSize = (DWORD) ((PBYTE) lpNextPtr - (PBYTE) InfoBuffer);
Status = STATUS_SUCCESS;
ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec);
ExitHandler: return Status; }
NTSTATUS NTAPI SaferpPol_GetInfoCommon_DefaultLevel( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL, IN BOOLEAN bUseCached ) /*++
Routine Description:
Queries the current WinSafer Level that has been configured to be the default policy level.
Note that this query always accepts a constant-sized buffer that is only a single DWORD in length.
Although this API directly queries the registry scope indicated, the pre-cached list of available Levels is used to validate the specified Level.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this can be SAFER_SCOPEID_MACHINE or SAFER_SCOPEID_USER.
InfoBufferSize - optionally specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - optionally specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
InfoBufferRetSize - optionally specifies a pointer that will receive the size of the results actually written to the InfoBuffer.
Return Value:
Returns STATUS_SUCCESS on a successful query result. InfoBuffer will be filled with a single DWORD of the level that has been configured to be the default level for this scope. InfoBufferRetSize will contain the length of the result (a single DWORD). Returns STATUS_NOT_FOUND if no default level has been configured for the given scope (or the level defined does not exist). Returns STATUS_BUFFER_TOO_SMALL if there was a defined default level but a buffer was not supplied, or the buffer supplied was too small to accomodate the results.
--*/ { NTSTATUS Status; DWORD dwNewLevelId = (DWORD) -1;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE && dwScopeId != SAFER_SCOPEID_USER) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } if (g_bNeedCacheReload) { Status = CodeAuthzpImmediateReloadCacheTables(); if (!NT_SUCCESS(Status)) { goto ExitHandler2; } } if (RtlIsGenericTableEmpty(&g_CodeLevelObjTable)) { Status = STATUS_NOT_FOUND; goto ExitHandler2; }
//
// Query the current value setting.
//
if (!bUseCached) { HANDLE hKeyBase; ULONG ActualSize; UNICODE_STRING ValueName; WCHAR KeyPathBuffer[ MAXIMUM_FILENAME_LENGTH+6 ]; PKEY_VALUE_FULL_INFORMATION ValueBuffer = (PKEY_VALUE_FULL_INFORMATION) KeyPathBuffer;
Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ, FALSE, &hKeyBase); if (NT_SUCCESS(Status)) { RtlInitUnicodeString(&ValueName, SAFER_DEFAULTOBJ_REGVALUE); Status = NtQueryValueKey(hKeyBase, &ValueName, KeyValueFullInformation, ValueBuffer, // ptr to KeyPathBuffer
sizeof(KeyPathBuffer), &ActualSize); if (NT_SUCCESS(Status)) { if (ValueBuffer->Type != REG_DWORD || ValueBuffer->DataLength != sizeof(DWORD)) { Status = STATUS_NOT_FOUND; } else { dwNewLevelId = * (PDWORD) ((PBYTE) ValueBuffer + ValueBuffer->DataOffset); } } NtClose(hKeyBase); } if (!NT_SUCCESS(Status)) { goto ExitHandler2; } } else { if (dwScopeId == SAFER_SCOPEID_USER) { if (!g_DefaultCodeLevelUser) { dwNewLevelId = SAFER_LEVELID_FULLYTRUSTED; } else { dwNewLevelId = g_DefaultCodeLevelUser->dwLevelId; } } else { if (!g_DefaultCodeLevelMachine) { dwNewLevelId = SAFER_LEVELID_FULLYTRUSTED; } else { dwNewLevelId = g_DefaultCodeLevelMachine->dwLevelId; } } }
//
// Make sure the level we found is actually
// valid (still in our level table).
//
if (!CodeAuthzLevelObjpLookupByLevelId( &g_CodeLevelObjTable, dwNewLevelId)) { Status = STATUS_NOT_FOUND; goto ExitHandler2; }
//
// Make sure the target buffer is large
// enough and copy the levelid into it.
//
if (!ARGUMENT_PRESENT(InfoBuffer) || InfoBufferSize < sizeof(DWORD)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory(InfoBuffer, &dwNewLevelId, sizeof(DWORD)); Status = STATUS_SUCCESS; } if (ARGUMENT_PRESENT(InfoBufferRetSize)) *InfoBufferRetSize = sizeof(DWORD);
ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI CodeAuthzPol_GetInfoCached_DefaultLevel( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) { return SaferpPol_GetInfoCommon_DefaultLevel( dwScopeId, InfoBufferSize, InfoBuffer, InfoBufferRetSize, TRUE); }
NTSTATUS NTAPI CodeAuthzPol_GetInfoRegistry_DefaultLevel( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) { return SaferpPol_GetInfoCommon_DefaultLevel( dwScopeId, InfoBufferSize, InfoBuffer, InfoBufferRetSize, FALSE); }
NTSTATUS NTAPI CodeAuthzPol_SetInfoDual_DefaultLevel( IN DWORD dwScopeId, IN DWORD InfoBufferSize, OUT PVOID InfoBuffer ) /*++
Routine Description:
Modifies the current WinSafer Level that has been configured to be the default policy level.
Note that this query always accepts a constant-sized buffer that is only a single DWORD in length.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this can be SAFER_SCOPEID_MACHINE or SAFER_SCOPEID_USER.
InfoBufferSize - specifies the size of input buffer supplied by the caller to receive the results.
InfoBuffer - specifies the input buffer that was supplied by the caller to receive the results.
Return Value:
Returns STATUS_SUCCESS on a successful query result. InfoBuffer will be filled with a single DWORD of the level that has been configured to be the default level for this scope. InfoBufferRetSize will contain the length of the result (a single DWORD). Returns STATUS_NOT_FOUND if no default level has been configured for the given scope (or the level defined does not exist). Returns STATUS_BUFFER_TOO_SMALL if there was a defined default level but a buffer was not supplied, or the buffer supplied was too small to accomodate the results.
--*/ { NTSTATUS Status; HANDLE hKeyBase; DWORD dwNewLevelId; UNICODE_STRING ValueName; PAUTHZLEVELTABLERECORD pLevelRecord;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE && dwScopeId != SAFER_SCOPEID_USER) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } if (g_bNeedCacheReload) { Status = CodeAuthzpImmediateReloadCacheTables(); if (!NT_SUCCESS(Status)) { goto ExitHandler2; } } Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ | KEY_SET_VALUE, TRUE, &hKeyBase); if (!NT_SUCCESS(Status)) { goto ExitHandler2; }
//
// Load the list of all of the available objects.
//
if (RtlIsGenericTableEmpty(&g_CodeLevelObjTable)) { Status = STATUS_NOT_FOUND; goto ExitHandler3; }
//
// If we are going to set a new default object,
// make sure it is a valid one.
//
if (InfoBufferSize < sizeof(DWORD) || !ARGUMENT_PRESENT(InfoBuffer)) { // Caller wants to clear the default object.
InfoBuffer = NULL; pLevelRecord = NULL; } else { dwNewLevelId = *(PDWORD) InfoBuffer; pLevelRecord = CodeAuthzLevelObjpLookupByLevelId( &g_CodeLevelObjTable, dwNewLevelId); if (!pLevelRecord) { // Caller was trying to set the default to an
// authorization object that does not exist.
Status = STATUS_NOT_FOUND; goto ExitHandler3; } }
//
// Write the name of the default object that is specified.
//
RtlInitUnicodeString(&ValueName, SAFER_DEFAULTOBJ_REGVALUE);
Status = NtSetValueKey(hKeyBase, &ValueName, 0, REG_DWORD, &dwNewLevelId, sizeof(DWORD)); if (NT_SUCCESS(Status)) { if (dwScopeId == SAFER_SCOPEID_USER) { g_DefaultCodeLevelUser = pLevelRecord; } else { g_DefaultCodeLevelMachine = pLevelRecord; }
//
// Compute the effective Default Level (take the least privileged).
//
CodeAuthzpRecomputeEffectiveDefaultLevel(); }
ExitHandler3: NtClose(hKeyBase); ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI SaferpPol_GetInfoCommon_HonorUserIdentities( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL, IN BOOLEAN bUseCached ) /*++
Routine Description:
Queries the current WinSafer policy to determine if Code Identities defined within the User's registry scope should be considered.
Note that this query always accepts a constant-sized buffer that is only a single DWORD in length.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - optionally specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - optionally specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
InfoBufferRetSize - optionally specifies a pointer that will receive the size of the results actually written to the InfoBuffer.
Return Value:
Returns STATUS_SUCCESS on a successful query result. InfoBuffer will be filled with a single DWORD containing either a TRUE or FALSE value that indicates whether the option is enabled. InfoBufferRetSize will contain the length of the result (a single DWORD). Returns STATUS_BUFFER_TOO_SMALL if the buffer was not supplied, or the buffer supplied was too small to accomodate the result.
--*/ { NTSTATUS Status; DWORD dwValueState = (DWORD) -1;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } if (g_bNeedCacheReload) { Status = CodeAuthzpImmediateReloadCacheTables(); if (!NT_SUCCESS(Status)) { goto ExitHandler2; } }
//
// Read or write the name of the policy value that is specified.
//
if (!bUseCached) { HANDLE hKeyBase; ULONG ActualSize; UNICODE_STRING ValueName; WCHAR KeyPathBuffer[ MAXIMUM_FILENAME_LENGTH+6 ]; PKEY_VALUE_FULL_INFORMATION ValueBuffer = (PKEY_VALUE_FULL_INFORMATION) KeyPathBuffer;
Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ, FALSE, &hKeyBase); if (NT_SUCCESS(Status)) { RtlInitUnicodeString(&ValueName, SAFER_HONORUSER_REGVALUE); Status = NtQueryValueKey(hKeyBase, &ValueName, KeyValueFullInformation, ValueBuffer, // ptr to KeyPathBuffer
sizeof(KeyPathBuffer), &ActualSize); if (NT_SUCCESS(Status)) { if (ValueBuffer->Type != REG_DWORD || ValueBuffer->DataLength != sizeof(DWORD)) { Status = STATUS_NOT_FOUND; } else { dwValueState = * (PDWORD) ((PBYTE) ValueBuffer + ValueBuffer->DataOffset); } } NtClose(hKeyBase); } if (!NT_SUCCESS(Status)) { goto ExitHandler2; } } else { dwValueState = (g_bHonorScopeUser ? TRUE : FALSE); }
//
// Make sure the target buffer is large
// enough and copy the object name into it.
//
if (!ARGUMENT_PRESENT(InfoBuffer) || InfoBufferSize < sizeof(DWORD)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory(InfoBuffer, &dwValueState, sizeof(DWORD)); Status = STATUS_SUCCESS; } if (ARGUMENT_PRESENT(InfoBufferRetSize)) *InfoBufferRetSize = sizeof(DWORD);
ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI CodeAuthzPol_GetInfoCached_HonorUserIdentities( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) { return SaferpPol_GetInfoCommon_HonorUserIdentities( dwScopeId, InfoBufferSize, InfoBuffer, InfoBufferRetSize, TRUE); }
NTSTATUS NTAPI CodeAuthzPol_GetInfoRegistry_HonorUserIdentities( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) { return SaferpPol_GetInfoCommon_HonorUserIdentities( dwScopeId, InfoBufferSize, InfoBuffer, InfoBufferRetSize, FALSE); }
NTSTATUS NTAPI CodeAuthzPol_SetInfoDual_HonorUserIdentities( IN DWORD dwScopeId, IN DWORD InfoBufferSize, IN PVOID InfoBuffer ) /*++
Routine Description:
Queries the current WinSafer policy to determine if Code Identities defined within the User's registry scope should be considered.
Note that this API always accepts a constant-sized buffer that is only a single DWORD in length.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
Return Value:
Returns STATUS_SUCCESS on a successful query result. InfoBuffer will be filled with a single DWORD of the level that has been configured to be the default level for this scope. InfoBufferRetSize will contain the length of the result (a single DWORD). Returns STATUS_NOT_FOUND if no default level has been configured for the given scope (or the level defined does not exist). Returns STATUS_BUFFER_TOO_SMALL if there was a defined default level but a buffer was not supplied, or the buffer supplied was too small to accomodate the results.
--*/ { HANDLE hKeyBase; NTSTATUS Status; UNICODE_STRING ValueName;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } if (g_bNeedCacheReload) { Status = CodeAuthzpImmediateReloadCacheTables(); if (!NT_SUCCESS(Status)) { goto ExitHandler2; } } Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, (KEY_READ | KEY_SET_VALUE), TRUE, &hKeyBase); if (!NT_SUCCESS(Status)) { goto ExitHandler2; }
//
// Make sure the input buffer is large enough.
//
if (InfoBufferSize < sizeof(DWORD) || !ARGUMENT_PRESENT(InfoBuffer)) { Status = STATUS_BUFFER_TOO_SMALL; goto ExitHandler3; }
//
// Write the policy value that is specified.
//
RtlInitUnicodeString(&ValueName, SAFER_HONORUSER_REGVALUE);
Status = NtSetValueKey(hKeyBase, &ValueName, 0, REG_DWORD, InfoBuffer, sizeof(DWORD)); if (NT_SUCCESS(Status)) { BOOLEAN bNewHonorScopeUser = (*((PDWORD)InfoBuffer) != 0 ? TRUE : FALSE);
if (g_bHonorScopeUser != bNewHonorScopeUser) { g_bHonorScopeUser = bNewHonorScopeUser;
//
// If the actual value is different from what we had then we
// need to purge the identities table and reload the only the
// parts that we should consider.
//
if (g_hKeyCustomRoot == NULL) { CodeAuthzGuidIdentsEntireTableFree(&g_CodeIdentitiesTable);
CodeAuthzGuidIdentsLoadTableAll( &g_CodeLevelObjTable, &g_CodeIdentitiesTable, SAFER_SCOPEID_MACHINE, NULL);
if (g_bHonorScopeUser) { CodeAuthzGuidIdentsLoadTableAll( &g_CodeLevelObjTable, &g_CodeIdentitiesTable, SAFER_SCOPEID_USER, NULL); } } } }
ExitHandler3: NtClose(hKeyBase); ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI CodeAuthzPol_GetInfoRegistry_TransparentEnabled( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) /*++
Routine Description:
Queries the current "transparent enforcement" setting. This is a global setting that can be used to enable or disable automatic WinSafer token reductions.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - optionally specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - optionally specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
InfoBufferRetSize - optionally specifies a pointer that will receive the size of the results actually written to the InfoBuffer.
Return Value:
Returns STATUS_SUCCESS on a successful query result. If the operation is not successful, then the contents of 'pdwEnabled' are left untouched.
--*/ { NTSTATUS Status; DWORD dwValueState = (DWORD) -1;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } }
//
// Query the current value setting.
//
{ HANDLE hKeyBase; DWORD ActualSize; UNICODE_STRING ValueName; WCHAR KeyPathBuffer[ MAXIMUM_FILENAME_LENGTH+6 ]; PKEY_VALUE_FULL_INFORMATION ValueBuffer = (PKEY_VALUE_FULL_INFORMATION) KeyPathBuffer;
Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ, FALSE, &hKeyBase); if (NT_SUCCESS(Status)) { RtlInitUnicodeString(&ValueName, SAFER_TRANSPARENTENABLED_REGVALUE); Status = NtQueryValueKey(hKeyBase, &ValueName, KeyValueFullInformation, ValueBuffer, // ptr to KeyPathBuffer
sizeof(KeyPathBuffer), &ActualSize); if (NT_SUCCESS(Status)) { if (ValueBuffer->Type != REG_DWORD || ValueBuffer->DataLength != sizeof(DWORD)) { Status = STATUS_NOT_FOUND; } else { dwValueState = * (PDWORD) ((PBYTE) ValueBuffer + ValueBuffer->DataOffset); } } NtClose(hKeyBase); } if (!NT_SUCCESS(Status)) { // On failure, just ignore it and pretend it was FALSE.
dwValueState = FALSE; } }
//
// Make sure the target buffer is large
// enough and copy the object name into it.
//
if (!ARGUMENT_PRESENT(InfoBuffer) || InfoBufferSize < sizeof(DWORD)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory(InfoBuffer, &dwValueState, sizeof(DWORD)); Status = STATUS_SUCCESS; } if (ARGUMENT_PRESENT(InfoBufferRetSize)) *InfoBufferRetSize = sizeof(DWORD);
ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI CodeAuthzPol_SetInfoRegistry_TransparentEnabled( IN DWORD dwScopeId, IN DWORD InfoBufferSize, IN PVOID InfoBuffer ) /*++
Routine Description:
Modifies the current "transparent enforcement" setting. This is a global setting that can be used to enable or disable automatic WinSafer token reductions.
Note that this API always accepts a constant-sized buffer that is only a single DWORD in length.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
Return Value:
Returns STATUS_SUCCESS on a successful result.
--*/ { HANDLE hKeyBase; NTSTATUS Status; UNICODE_STRING ValueName;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ | KEY_SET_VALUE, TRUE, &hKeyBase); if (!NT_SUCCESS(Status)) { goto ExitHandler2; }
//
// Make sure the input buffer is large enough.
//
if (InfoBufferSize < sizeof(DWORD) || !ARGUMENT_PRESENT(InfoBuffer)) { Status = STATUS_BUFFER_TOO_SMALL; goto ExitHandler3; }
//
// Write the policy value that is specified.
//
RtlInitUnicodeString(&ValueName, SAFER_TRANSPARENTENABLED_REGVALUE); Status = NtSetValueKey(hKeyBase, &ValueName, 0, REG_DWORD, InfoBuffer, sizeof(DWORD));
ExitHandler3: NtClose(hKeyBase); ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI CodeAuthzPol_GetInfoRegistry_ScopeFlags( IN DWORD dwScopeId, IN DWORD InfoBufferSize OPTIONAL, OUT PVOID InfoBuffer OPTIONAL, OUT PDWORD InfoBufferRetSize OPTIONAL ) /*++
Routine Description:
Queries the current "scope flags" setting.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - optionally specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - optionally specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
InfoBufferRetSize - optionally specifies a pointer that will receive the size of the results actually written to the InfoBuffer.
Return Value:
Returns STATUS_SUCCESS on a successful query result. If the operation is not successful, then the contents of 'pdwEnabled' are left untouched.
--*/ { NTSTATUS Status; DWORD dwValueState = (DWORD) 0;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } }
//
// Query the current value setting.
//
{ HANDLE hKeyBase; DWORD ActualSize; UNICODE_STRING ValueName; WCHAR KeyPathBuffer[ MAXIMUM_FILENAME_LENGTH+6 ]; PKEY_VALUE_FULL_INFORMATION ValueBuffer = (PKEY_VALUE_FULL_INFORMATION) KeyPathBuffer;
Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ, FALSE, &hKeyBase); if (NT_SUCCESS(Status)) { RtlInitUnicodeString(&ValueName, SAFER_POLICY_SCOPE); Status = NtQueryValueKey(hKeyBase, &ValueName, KeyValueFullInformation, ValueBuffer, // ptr to KeyPathBuffer
sizeof(KeyPathBuffer), &ActualSize); if (NT_SUCCESS(Status)) { if (ValueBuffer->Type != REG_DWORD || ValueBuffer->DataLength != sizeof(DWORD)) { Status = STATUS_NOT_FOUND; } else { dwValueState = * (PDWORD) ((PBYTE) ValueBuffer + ValueBuffer->DataOffset); } } NtClose(hKeyBase); } if (!NT_SUCCESS(Status)) { // On failure, just ignore it and pretend it was FALSE.
dwValueState = 0; } }
//
// Make sure the target buffer is large
// enough and copy the object name into it.
//
if (!ARGUMENT_PRESENT(InfoBuffer) || InfoBufferSize < sizeof(DWORD)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory(InfoBuffer, &dwValueState, sizeof(DWORD)); Status = STATUS_SUCCESS; } if (ARGUMENT_PRESENT(InfoBufferRetSize)) *InfoBufferRetSize = sizeof(DWORD);
ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
NTSTATUS NTAPI CodeAuthzPol_SetInfoRegistry_ScopeFlags( IN DWORD dwScopeId, IN DWORD InfoBufferSize, IN PVOID InfoBuffer ) /*++
Routine Description:
Modifies the current "scope flags" setting.
Note that this API always accepts a constant-sized buffer that is only a single DWORD in length.
Arguments:
dwScopeId - specifies the registry scope that will be examined. If the currently cached scope included a registry handle then AUTHZSCOPE_REGISTRY must be specified. Otherwise, this must be SAFER_SCOPEID_MACHINE.
InfoBufferSize - specifies the size of input buffer supplied by the caller to receive the results. If this argument is supplied, then InfoBuffer must also be supplied.
InfoBuffer - specifies the input buffer that was supplied by the caller to receive the results. If this argument is supplied, then InfoBufferSize must also be supplied.
Return Value:
Returns STATUS_SUCCESS on a successful result.
--*/ { HANDLE hKeyBase; NTSTATUS Status; UNICODE_STRING ValueName;
//
// Open up the regkey to the base of the policies.
//
if (!g_bInitializedFirstTime) { Status = STATUS_UNSUCCESSFUL; goto ExitHandler; } RtlEnterCriticalSection(&g_TableCritSec); if (g_hKeyCustomRoot != NULL) { if (dwScopeId != SAFER_SCOPEID_REGISTRY) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } else { if (dwScopeId != SAFER_SCOPEID_MACHINE) { Status = STATUS_INVALID_PARAMETER_MIX; goto ExitHandler2; } } Status = CodeAuthzpOpenPolicyRootKey( dwScopeId, g_hKeyCustomRoot, L"\\" SAFER_CODEIDS_REGSUBKEY, KEY_READ | KEY_SET_VALUE, TRUE, &hKeyBase); if (!NT_SUCCESS(Status)) { goto ExitHandler2; }
//
// Make sure the input buffer is large enough.
//
if (InfoBufferSize < sizeof(DWORD) || !ARGUMENT_PRESENT(InfoBuffer)) { Status = STATUS_BUFFER_TOO_SMALL; goto ExitHandler3; }
//
// Write the policy value that is specified.
//
RtlInitUnicodeString(&ValueName, SAFER_POLICY_SCOPE); Status = NtSetValueKey(hKeyBase, &ValueName, 0, REG_DWORD, InfoBuffer, sizeof(DWORD));
ExitHandler3: NtClose(hKeyBase); ExitHandler2: RtlLeaveCriticalSection(&g_TableCritSec); ExitHandler: return Status; }
|