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.
337 lines
8.0 KiB
337 lines
8.0 KiB
/****************************** 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);
|
|
|
|
}
|