|
|
/****************************** Module Header ******************************\
* Module Name: lsautil.c * * Copyright (c) 1994, Microsoft Corporation * * Remote shell server main module * * History: * 05-19-94 DaveTh Created. \***************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <ntlsa.h>
#include <windef.h>
#include <nturtl.h>
#include <winbase.h>
#include "rcmdsrv.h"
#define INITIAL_SIZE_REQUIRED 600
DWORD CheckUserSystemAccess( HANDLE TokenHandle, ULONG DesiredSystemAccess, PBOOLEAN UserHasAccess )
/*++
Routine Description:
This function determines whether or not the user whose token is passed has the interactive accesses desired on this machine.
Arguments:
TokenHandle - Handle of user's token.
DesiredSystemAccess - Specifies desired access type(s).
UserHasAccess - pointer to boolean returned - TRUE means that user has interactive access.
Return Value:
ERROR_SUCCESS in absence of errors. UserHasAccess is TRUE if all requested access types are permitted, otherwise FALSE. WIN32 errors are returned in error cases.
--*/ {
DWORD Result; LPVOID LpTokenUserInformation = NULL; LPVOID LpTokenGroupInformation = NULL; DWORD SizeRequired, SizeProvided; LSA_HANDLE PolicyHandle = NULL; LSA_HANDLE AccountHandle = NULL; NTSTATUS NtStatus; OBJECT_ATTRIBUTES ObjectAttributes; POBJECT_ATTRIBUTES LpObjectAttributes; ULONG GrantedSystemAccess, SidSystemAccess; DWORD i;
//
// Access LSA policy database
//
LpObjectAttributes = &ObjectAttributes;
InitializeObjectAttributes( LpObjectAttributes, NULL, 0, NULL, NULL);
if (!NT_SUCCESS(NtStatus = LsaOpenPolicy( NULL, // Local system
LpObjectAttributes, GENERIC_READ, &PolicyHandle))) {
RcDbgPrint("Error opening policy database, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); goto Failure; }
//
// Check groups, user - For each SID, open the account (if it exists).
// If it doesn't exist, no failure, but no access (FALSE). If it
// does exist, accumulate granted accesses in and compare to
// requested mask. If all the bits of the mask have been set at any
// point, UserHasAccess is set TRUE. Otherise, it is left FALSE.
//
*UserHasAccess = FALSE; GrantedSystemAccess = 0;
//
// Get list of SIDs of groups of which user is a member
//
if ((LpTokenGroupInformation = Alloc(INITIAL_SIZE_REQUIRED)) == NULL) { Result = GetLastError(); goto Failure; }
if (!GetTokenInformation ( TokenHandle, TokenGroups, LpTokenGroupInformation, INITIAL_SIZE_REQUIRED, &SizeRequired)) {
Result = GetLastError(); if ( (Result == ERROR_MORE_DATA) || (Result == ERROR_INSUFFICIENT_BUFFER) ) {
Free(LpTokenGroupInformation);
if ((LpTokenGroupInformation = Alloc(SizeRequired)) == NULL) { Result = GetLastError(); goto Failure; }
SizeProvided = SizeRequired;
if (!GetTokenInformation ( TokenHandle, TokenGroups, LpTokenGroupInformation, SizeProvided, &SizeRequired)) {
Result=GetLastError(); RcDbgPrint("Error accessing group SIDs, error = %d\n", Result); goto Failure; }
} else { RcDbgPrint("Error accessing group SIDs, error = %d\n", Result); goto Failure;
}
}
//
// Check for each group that user is a member of since groups
// are most likely source of permitted access. Permitted access types
// are cumulative.
//
for (i=0; i< ((PTOKEN_GROUPS)LpTokenGroupInformation)->GroupCount; i++) {
if (NT_SUCCESS(NtStatus = LsaOpenAccount( PolicyHandle, ((PTOKEN_GROUPS)LpTokenGroupInformation)->Groups[i].Sid, GENERIC_READ, &AccountHandle))) {
//
// found account - accumulate and check accesses
//
if (!NT_SUCCESS(NtStatus = LsaGetSystemAccessAccount ( AccountHandle, &SidSystemAccess))) {
RcDbgPrint("Error getting group account access, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); goto Failure;
} else {
//
// Got system access - don't need account handle anymore
//
if (NT_SUCCESS(NtStatus = LsaClose(AccountHandle))) {
AccountHandle = NULL;
} else {
RcDbgPrint("Error closing account handle, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); goto Failure; }
GrantedSystemAccess |= SidSystemAccess;;
if ((GrantedSystemAccess & DesiredSystemAccess) == DesiredSystemAccess) { *UserHasAccess = TRUE; goto Success; } }
} else if (NtStatus != STATUS_OBJECT_NAME_NOT_FOUND) { RcDbgPrint("Error opening group account, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); goto Failure; }
}
//
// Get user SID
//
if ((LpTokenUserInformation = Alloc(INITIAL_SIZE_REQUIRED)) == NULL) { Result = GetLastError(); goto Failure; }
if (!GetTokenInformation ( TokenHandle, TokenUser, LpTokenUserInformation, INITIAL_SIZE_REQUIRED, &SizeRequired)) {
Result = GetLastError(); if (Result == ERROR_MORE_DATA) { // Not enough - alloc and redo
Free(LpTokenUserInformation);
if ((LpTokenUserInformation = Alloc(SizeRequired)) == NULL) { Result = GetLastError(); goto Failure; }
SizeProvided = SizeRequired;
if (!GetTokenInformation ( TokenHandle, TokenUser, LpTokenUserInformation, SizeProvided, &SizeRequired)) {
RcDbgPrint("Error accessing user SID, error = %d\n", Result); Result=GetLastError(); goto Failure; }
} else { RcDbgPrint("Error accessing user SID, error = %d\n", Result); goto Failure;
} }
//
// Now, check user account. If present, check access and return
// if requested access is allowed. If not allowed, go on to check groups.
// If account doesn't exist, go on to check groups.
//
if (NT_SUCCESS(NtStatus = LsaOpenAccount( PolicyHandle, ((PTOKEN_USER)LpTokenUserInformation)->User.Sid, GENERIC_READ, &AccountHandle))) {
//
// found account - check accesses
//
if (!NT_SUCCESS(NtStatus = LsaGetSystemAccessAccount ( AccountHandle, &GrantedSystemAccess))) {
RcDbgPrint("Error getting group account access, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); goto Failure;
} else {
GrantedSystemAccess |= SidSystemAccess;;
if ((GrantedSystemAccess & DesiredSystemAccess) == DesiredSystemAccess) { *UserHasAccess = TRUE; goto Success; } }
} else if (NtStatus != STATUS_OBJECT_NAME_NOT_FOUND) { RcDbgPrint("Error opening user account, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); goto Failure; }
//
// Success - Jump here if access granted, fall through here on no error
//
Success:
Result = ERROR_SUCCESS;
//
// General failure and success exit - frees memory, closes handles
//
Failure:
if (LpTokenGroupInformation != NULL) { Free(LpTokenGroupInformation); }
if (LpTokenUserInformation != NULL) { Free(LpTokenGroupInformation); }
if ((PolicyHandle != NULL) && (!NT_SUCCESS(NtStatus = LsaClose(PolicyHandle)))) { RcDbgPrint("Error closing policy handle at exit, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); }
if ((AccountHandle != NULL) && (!NT_SUCCESS(NtStatus = LsaClose(AccountHandle)))) { RcDbgPrint("Error closing account handle at exit, error = %x\n", NtStatus); Result = RtlNtStatusToDosError(NtStatus); }
return(Result);
}
|