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.
 
 
 
 
 
 

601 lines
12 KiB

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
secutil.c
Abstract:
This module contains security-related utility routines.
GetUserSid
GetInteractiveSid
IsClientLocal
IsClientUsingLocalConsole
IsClientInteractive
Author:
James G. Cavalaris (jamesca) 31-Jan-2002
Environment:
User-mode only.
Revision History:
31-Jan-2002 Jim Cavalaris (jamesca)
Creation and initial implementation.
--*/
//
// includes
//
#include "precomp.h"
#pragma hdrstop
#include "umpnpi.h"
#include "umpnpdat.h"
#pragma warning(push)
#pragma warning(disable:4214)
#pragma warning(disable:4201)
#include <winsta.h>
#pragma warning(pop)
#include <syslib.h>
PSID
GetUserSid(
IN HANDLE hUserToken
)
/*++
Routine Description:
Retrieves the corresponding user SID for the specified user access token.
Arguments:
hUserToken -
Specifies a handle to a user access token.
Return Value:
If successful, returns a pointer to an allocated buffer containing the SID
for the specified user access token. Otherwise, returns NULL.
Notes:
If successful, it is responsibility of the caller to free the the returned
buffer from the ghPnPHeap with HeapFree.
--*/
{
BOOL bResult;
DWORD cbBuffer, cbRequired;
PTOKEN_USER pUserInfo = NULL;
PSID pUserSid = NULL;
//
// Determine the size of buffer we need to store the TOKEN_USER information
// for the supplied user access token. The TOKEN_USER structure contains
// the SID_AND_ATTRIBUTES information for the User.
//
cbBuffer = 0;
bResult =
GetTokenInformation(
hUserToken,
TokenUser,
NULL,
cbBuffer,
&cbRequired);
ASSERT(bResult == FALSE);
if (bResult) {
SetLastError(ERROR_INVALID_DATA);
goto Clean0;
} else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
goto Clean0;
}
ASSERT(cbRequired > 0);
//
// Allocate a buffer for the TOKEN_USER data.
//
cbBuffer = cbRequired;
pUserInfo =
(PTOKEN_USER)HeapAlloc(
ghPnPHeap, 0, cbBuffer);
if (pUserInfo == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Clean0;
}
//
// Retrieve the TOKEN_USER data.
//
bResult =
GetTokenInformation(
hUserToken,
TokenUser,
pUserInfo,
cbBuffer,
&cbRequired);
if (!bResult) {
goto Clean0;
}
ASSERT(pUserInfo->User.Sid != NULL);
//
// Check that the returned SID is valid.
// Note - calling GetLastError is not valid for IsValidSid!
//
ASSERT(IsValidSid(pUserInfo->User.Sid));
if (!IsValidSid(pUserInfo->User.Sid)) {
SetLastError(ERROR_INVALID_DATA);
goto Clean0;
}
//
// Make a copy of the User SID_AND_ATTRIBUTES.
//
cbBuffer =
GetLengthSid(pUserInfo->User.Sid);
ASSERT(cbBuffer > 0);
pUserSid =
(PSID)HeapAlloc(
ghPnPHeap, 0, cbBuffer);
if (pUserSid == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Clean0;
}
bResult =
CopySid(
cbBuffer,
pUserSid,
pUserInfo->User.Sid);
if (!bResult) {
HeapFree(ghPnPHeap, 0, pUserSid);
pUserSid = NULL;
goto Clean0;
}
//
// Check that the returned SID is valid.
// Note - calling GetLastError is not valid for IsValidSid!
//
ASSERT(IsValidSid(pUserSid));
if (!IsValidSid(pUserSid)) {
SetLastError(ERROR_INVALID_DATA);
HeapFree(ghPnPHeap, 0, pUserSid);
pUserSid = NULL;
goto Clean0;
}
Clean0:
if (pUserInfo != NULL) {
HeapFree(ghPnPHeap, 0, pUserInfo);
}
return pUserSid;
} // GetUserSid
PSID
GetInteractiveSid(
VOID
)
/*++
Routine Description:
Retrieves the Interactive Group SID.
Arguments:
None.
Return Value:
If successful, returns a pointer to an allocated buffer containing the SID
for the Interactive Group. Otherwise, returns NULL.
Notes:
If successful, it is responsibility of the caller to free the the returned
buffer from the ghPnPHeap with HeapFree.
--*/
{
BOOL bResult;
DWORD cbBuffer;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID pSid = NULL, pInteractiveSid = NULL;
//
// Create the Interactive Group SID
//
bResult =
AllocateAndInitializeSid(
&NtAuthority, 1,
SECURITY_INTERACTIVE_RID,
0, 0, 0, 0, 0, 0, 0,
&pInteractiveSid);
if (!bResult) {
goto Clean0;
}
ASSERT(pInteractiveSid != NULL);
//
// Check that the returned SID is valid.
// Note - calling GetLastError is not valid for IsValidSid!
//
ASSERT(IsValidSid(pInteractiveSid));
if (!IsValidSid(pInteractiveSid)) {
SetLastError(ERROR_INVALID_DATA);
goto Clean0;
}
//
// Make a copy of the Interactive Group SID.
//
cbBuffer =
GetLengthSid(pInteractiveSid);
ASSERT(cbBuffer > 0);
pSid =
(PSID)HeapAlloc(
ghPnPHeap, 0, cbBuffer);
if (pSid == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Clean0;
}
bResult =
CopySid(
cbBuffer,
pSid,
pInteractiveSid);
if (!bResult) {
HeapFree(ghPnPHeap, 0, pSid);
pSid = NULL;
goto Clean0;
}
//
// Check that the returned SID is valid.
// Note - calling GetLastError is not valid for IsValidSid!
//
ASSERT(IsValidSid(pSid));
if (!IsValidSid(pSid)) {
SetLastError(ERROR_INVALID_DATA);
HeapFree(ghPnPHeap, 0, pSid);
pSid = NULL;
goto Clean0;
}
Clean0:
if (pInteractiveSid != NULL) {
FreeSid(pInteractiveSid);
}
return pSid;
} // GetInteractiveSid
//
// RPC client attributes and group membership routines
//
BOOL
IsClientLocal(
IN handle_t hBinding
)
/*++
Routine Description:
This routine determines if the client associated with hBinding is on the
local machine.
Arguments:
hBinding RPC Binding handle
Return value:
The return value is TRUE if the client is local to this machine, FALSE if
not or if an error occurs.
--*/
{
RPC_STATUS RpcStatus;
UINT ClientLocalFlag;
//
// If the specified RPC binding handle is NULL, this is an internal call so
// we assume that the privilege has already been checked.
//
if (hBinding == NULL) {
return TRUE;
}
//
// Retrieve the ClientLocalFlags from the RPC binding handle.
//
RpcStatus =
I_RpcBindingIsClientLocal(
hBinding,
&ClientLocalFlag);
if (RpcStatus != RPC_S_OK) {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: I_RpcBindingIsClientLocal failed, RpcStatus=%d\n",
RpcStatus));
return FALSE;
}
//
// If the ClientLocalFlag is not zero, RPC client is local to server.
//
if (ClientLocalFlag != 0) {
return TRUE;
}
//
// Client is not local to this server.
//
return FALSE;
} // IsClientLocal
BOOL
IsClientUsingLocalConsole(
IN handle_t hBinding
)
/*++
Routine Description:
This routine impersonates the client associated with hBinding and checks
if the client is using the current active console session.
Arguments:
hBinding RPC Binding handle
Return value:
The return value is TRUE if the client is using the current active console
session, FALSE if not or if an error occurs.
--*/
{
RPC_STATUS rpcStatus;
BOOL bResult = FALSE;
//
// First, make sure the client is local to the server.
//
if (!IsClientLocal(hBinding)) {
return FALSE;
}
//
// Impersonate the client to retrieve the impersonation token.
//
rpcStatus = RpcImpersonateClient(hBinding);
if (rpcStatus != RPC_S_OK) {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: RpcImpersonateClient failed, error = %d\n",
rpcStatus));
return FALSE;
}
//
// Compare the client's session with the currently active Console session.
//
if (GetClientLogonId() == GetActiveConsoleSessionId()) {
bResult = TRUE;
}
rpcStatus = RpcRevertToSelf();
if (rpcStatus != RPC_S_OK) {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: RpcRevertToSelf failed, error = %d\n",
rpcStatus));
ASSERT(rpcStatus == RPC_S_OK);
}
return bResult;
} // IsClientUsingLocalConsole
BOOL
IsClientInteractive(
IN handle_t hBinding
)
/*++
Routine Description:
This routine impersonates the client associated with hBinding and checks
if the client is a member of the INTERACTIVE well-known group.
Arguments:
hBinding RPC Binding handle
Return value:
The return value is TRUE if the client is interactive, FALSE if not
or if an error occurs.
--*/
{
RPC_STATUS rpcStatus;
BOOL bIsMember;
HANDLE hToken;
PSID pInteractiveSid;
BOOL bResult = FALSE;
//
// First, make sure the client is local to the server.
//
if (!IsClientLocal(hBinding)) {
return FALSE;
}
//
// If the specified RPC binding handle is NULL, this is an internal call so
// we assume that the privilege has already been checked.
//
if (hBinding == NULL) {
return TRUE;
}
//
// Retrieve the Interactive Group SID
//
pInteractiveSid =
GetInteractiveSid();
if (pInteractiveSid == NULL) {
return FALSE;
}
//
// Impersonate the client to retrieve the impersonation token.
//
rpcStatus = RpcImpersonateClient(hBinding);
if (rpcStatus != RPC_S_OK) {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: RpcImpersonateClient failed, error = %d\n",
rpcStatus));
HeapFree(ghPnPHeap, 0, pInteractiveSid);
return FALSE;
}
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) {
if (CheckTokenMembership(hToken,
pInteractiveSid,
&bIsMember)) {
if (bIsMember) {
bResult = TRUE;
}
} else {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: CheckTokenMembership failed, error = %d\n",
GetLastError()));
}
CloseHandle(hToken);
} else {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: OpenThreadToken failed, error = %d\n",
GetLastError()));
}
HeapFree(ghPnPHeap, 0, pInteractiveSid);
rpcStatus = RpcRevertToSelf();
if (rpcStatus != RPC_S_OK) {
KdPrintEx((DPFLTR_PNPMGR_ID,
DBGF_ERRORS,
"UMPNPMGR: RpcRevertToSelf failed, error = %d\n",
rpcStatus));
ASSERT(rpcStatus == RPC_S_OK);
}
return bResult;
} // IsClientInteractive