windows-nt/Source/XPSP1/NT/ds/netapi/netlib/getpriv.c
2020-09-26 16:20:57 +08:00

302 lines
7.6 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:
GETPRIV.C
Abstract:
Contains functions for obtaining and relinquishing privileges
Author:
Dan Lafferty (danl) 20-Mar-1991
Environment:
User Mode -Win32
Revision History:
20-Mar-1991 danl
created
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <netdebug.h>
#include <debuglib.h>
#define PRIVILEGE_BUF_SIZE 512
DWORD
NetpGetPrivilege(
IN DWORD numPrivileges,
IN PULONG pulPrivileges
)
/*++
Routine Description:
This function alters the privilege level for the current thread.
It does this by duplicating the token for the current thread, and then
applying the new privileges to that new token, then the current thread
impersonates with that new token.
Privileges can be relinquished by calling NetpReleasePrivilege().
Arguments:
numPrivileges - This is a count of the number of privileges in the
array of privileges.
pulPrivileges - This is a pointer to the array of privileges that are
desired. This is an array of ULONGs.
Return Value:
NO_ERROR - If the operation was completely successful.
Otherwise, it returns mapped return codes from the various NT
functions that are called.
--*/
{
DWORD status;
NTSTATUS ntStatus;
HANDLE ourToken;
HANDLE newToken;
OBJECT_ATTRIBUTES Obja;
SECURITY_QUALITY_OF_SERVICE SecurityQofS;
ULONG bufLen;
ULONG returnLen;
PTOKEN_PRIVILEGES pPreviousState;
PTOKEN_PRIVILEGES pTokenPrivilege = NULL;
DWORD i;
//
// Initialize the Privileges Structure
//
pTokenPrivilege = LocalAlloc(LMEM_FIXED, sizeof(TOKEN_PRIVILEGES) +
(sizeof(LUID_AND_ATTRIBUTES) * numPrivileges));
if (pTokenPrivilege == NULL) {
status = GetLastError();
IF_DEBUG(SECURITY) {
NetpKdPrint(("NetpGetPrivilege:LocalAlloc Failed %d\n", status));
}
return(status);
}
pTokenPrivilege->PrivilegeCount = numPrivileges;
for (i=0; i<numPrivileges ;i++ ) {
pTokenPrivilege->Privileges[i].Luid = RtlConvertUlongToLuid(
pulPrivileges[i]);
pTokenPrivilege->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
}
//
// Initialize Object Attribute Structure.
//
InitializeObjectAttributes(&Obja,NULL,0L,NULL,NULL);
//
// Initialize Security Quality Of Service Structure
//
SecurityQofS.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
SecurityQofS.ImpersonationLevel = SecurityImpersonation;
SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
SecurityQofS.EffectiveOnly = FALSE;
Obja.SecurityQualityOfService = &SecurityQofS;
//
// Allocate storage for the structure that will hold the Previous State
// information.
//
pPreviousState = LocalAlloc(LMEM_FIXED, PRIVILEGE_BUF_SIZE);
if (pPreviousState == NULL) {
status = GetLastError();
IF_DEBUG(SECURITY) {
NetpKdPrint(("NetpGetPrivilege: LocalAlloc Failed "FORMAT_DWORD"\n",
status));
}
LocalFree(pTokenPrivilege);
return(status);
}
//
// Open our own Token
//
ntStatus = NtOpenProcessToken(
NtCurrentProcess(),
TOKEN_DUPLICATE,
&ourToken);
if (!NT_SUCCESS(ntStatus)) {
IF_DEBUG(SECURITY) {
NetpKdPrint(( "NetpGetPrivilege: NtOpenThreadToken Failed "
"FORMAT_NTSTATUS" "\n", ntStatus));
}
LocalFree(pPreviousState);
LocalFree(pTokenPrivilege);
return(RtlNtStatusToDosError(ntStatus));
}
//
// Duplicate that Token
//
ntStatus = NtDuplicateToken(
ourToken,
TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&Obja,
FALSE, // Duplicate the entire token
TokenImpersonation, // TokenType
&newToken); // Duplicate token
if (!NT_SUCCESS(ntStatus)) {
IF_DEBUG(SECURITY) {
NetpKdPrint(( "NetpGetPrivilege: NtDuplicateToken Failed "
"FORMAT_NTSTATUS" "\n", ntStatus));
}
LocalFree(pPreviousState);
LocalFree(pTokenPrivilege);
NtClose(ourToken);
return(RtlNtStatusToDosError(ntStatus));
}
//
// Add new privileges
//
bufLen = PRIVILEGE_BUF_SIZE;
ntStatus = NtAdjustPrivilegesToken(
newToken, // TokenHandle
FALSE, // DisableAllPrivileges
pTokenPrivilege, // NewState
bufLen, // bufferSize for previous state
pPreviousState, // pointer to previous state info
&returnLen); // numBytes required for buffer.
if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
LocalFree(pPreviousState);
bufLen = returnLen;
pPreviousState = LocalAlloc(LMEM_FIXED, bufLen);
ntStatus = NtAdjustPrivilegesToken(
newToken, // TokenHandle
FALSE, // DisableAllPrivileges
pTokenPrivilege, // NewState
bufLen, // bufferSize for previous state
pPreviousState, // pointer to previous state info
&returnLen); // numBytes required for buffer.
}
if (!NT_SUCCESS(ntStatus)) {
IF_DEBUG(SECURITY) {
NetpKdPrint(( "NetpGetPrivilege: NtAdjustPrivilegesToken Failed "
"FORMAT_NTSTATUS" "\n", ntStatus));
}
LocalFree(pPreviousState);
LocalFree(pTokenPrivilege);
NtClose(ourToken);
NtClose(newToken);
return(RtlNtStatusToDosError(ntStatus));
}
//
// Begin impersonating with the new token
//
ntStatus = NtSetInformationThread(
NtCurrentThread(),
ThreadImpersonationToken,
(PVOID)&newToken,
(ULONG)sizeof(HANDLE));
if (!NT_SUCCESS(ntStatus)) {
IF_DEBUG(SECURITY) {
NetpKdPrint(( "NetpGetPrivilege: NtAdjustPrivilegesToken Failed "
"FORMAT_NTSTATUS" "\n", ntStatus));
}
LocalFree(pPreviousState);
LocalFree(pTokenPrivilege);
NtClose(ourToken);
NtClose(newToken);
return(RtlNtStatusToDosError(ntStatus));
}
LocalFree(pPreviousState);
LocalFree(pTokenPrivilege);
NtClose(ourToken);
NtClose(newToken);
return(NO_ERROR);
}
DWORD
NetpReleasePrivilege(
VOID
)
/*++
Routine Description:
This function relinquishes privileges obtained by calling NetpGetPrivilege().
Arguments:
none
Return Value:
NO_ERROR - If the operation was completely successful.
Otherwise, it returns mapped return codes from the various NT
functions that are called.
--*/
{
NTSTATUS ntStatus;
HANDLE NewToken;
//
// Revert To Self.
//
NewToken = NULL;
ntStatus = NtSetInformationThread(
NtCurrentThread(),
ThreadImpersonationToken,
(PVOID)&NewToken,
(ULONG)sizeof(HANDLE));
if ( !NT_SUCCESS(ntStatus) ) {
return(RtlNtStatusToDosError(ntStatus));
}
return(NO_ERROR);
}