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.
2231 lines
44 KiB
2231 lines
44 KiB
/*++
|
|
|
|
Copyright (C) 1998-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CALLSEC.CPP
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
raymcc 29-Jul-98 First draft.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <initguid.h>
|
|
#ifndef INITGUID
|
|
#define INITGUID
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <wbemint.h>
|
|
#include "CallSec.h"
|
|
|
|
// {4551AB1A-C16F-40f3-A192-6A6264FE89D6}
|
|
DEFINE_GUID(IID_CWbemCallSecurity,
|
|
0x4551ab1a, 0xc16f, 0x40f3, 0xa1, 0x92, 0x6a, 0x62, 0x64, 0xfe, 0x89, 0xd6);
|
|
|
|
// {60B9F5CA-036E-4795-BB7C-017B9807E9B3}
|
|
DEFINE_GUID(IID_CWbemThreadSecurityHandle,
|
|
0x60b9f5ca, 0x36e, 0x4795, 0xbb, 0x7c, 0x1, 0x7b, 0x98, 0x7, 0xe9, 0xb3);
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT IsNetworkLogin (
|
|
|
|
HANDLE a_Token ,
|
|
BOOL &a_Truth
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
PSID t_NetworkSid = NULL ;
|
|
|
|
SID_IDENTIFIER_AUTHORITY t_NtAuthority = SECURITY_NT_AUTHORITY ;
|
|
BOOL t_Status = AllocateAndInitializeSid (
|
|
|
|
&t_NtAuthority,
|
|
1,
|
|
SECURITY_NETWORK_RID,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
& t_NetworkSid
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Status = CheckTokenMembership ( a_Token, t_NetworkSid, & a_Truth ) ;
|
|
if ( t_Status )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
|
|
FreeSid ( t_NetworkSid ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT GetImpersonationLevel (
|
|
|
|
HANDLE a_Token ,
|
|
SECURITY_IMPERSONATION_LEVEL &a_Level ,
|
|
TOKEN_TYPE &a_TokenType
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
DWORD t_ReturnLength = 0 ;
|
|
BOOL t_TokenStatus = GetTokenInformation (
|
|
|
|
a_Token ,
|
|
TokenType ,
|
|
( void * ) & a_TokenType ,
|
|
sizeof ( a_TokenType ) ,
|
|
& t_ReturnLength
|
|
) ;
|
|
|
|
if ( t_TokenStatus )
|
|
{
|
|
if ( a_TokenType == TokenImpersonation )
|
|
{
|
|
BOOL t_TempTokenStatus = GetTokenInformation (
|
|
|
|
a_Token ,
|
|
TokenImpersonationLevel ,
|
|
( void * ) & a_Level ,
|
|
sizeof ( a_Level ) ,
|
|
& t_ReturnLength
|
|
) ;
|
|
|
|
if ( t_TempTokenStatus )
|
|
{
|
|
t_Result = S_OK ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT GetUserSid (
|
|
|
|
HANDLE a_Token ,
|
|
ULONG *a_Size ,
|
|
PSID a_Sid
|
|
)
|
|
{
|
|
HRESULT t_Result = WBEM_E_FAILED ;
|
|
|
|
if ( a_Token )
|
|
{
|
|
if ( a_Size )
|
|
{
|
|
TOKEN_USER *t_TokenUser = NULL ;
|
|
DWORD t_ReturnLength = 0 ;
|
|
TOKEN_INFORMATION_CLASS t_TokenInformationClass = TokenUser ;
|
|
|
|
BOOL t_TokenStatus = GetTokenInformation (
|
|
|
|
a_Token ,
|
|
t_TokenInformationClass ,
|
|
t_TokenUser ,
|
|
t_ReturnLength ,
|
|
& t_ReturnLength
|
|
) ;
|
|
|
|
if ( ! t_TokenStatus )
|
|
{
|
|
DWORD t_LastError = GetLastError () ;
|
|
switch ( t_LastError )
|
|
{
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
{
|
|
if ( a_Sid )
|
|
{
|
|
if ( *a_Size >= t_ReturnLength )
|
|
{
|
|
t_TokenUser = ( TOKEN_USER * ) new BYTE [ t_ReturnLength ] ;
|
|
if ( t_TokenUser )
|
|
{
|
|
t_TokenStatus = GetTokenInformation (
|
|
|
|
a_Token ,
|
|
t_TokenInformationClass ,
|
|
t_TokenUser ,
|
|
t_ReturnLength ,
|
|
& t_ReturnLength
|
|
) ;
|
|
|
|
if ( t_TokenStatus )
|
|
{
|
|
DWORD t_SidLength = GetLengthSid ( t_TokenUser->User.Sid ) ;
|
|
*a_Size = t_SidLength ;
|
|
|
|
CopyMemory ( a_Sid , t_TokenUser->User.Sid , t_SidLength ) ;
|
|
|
|
t_Result = S_OK ;
|
|
}
|
|
|
|
delete [] t_TokenUser ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_BUFFER_TOO_SMALL ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*a_Size = t_ReturnLength ;
|
|
|
|
t_Result = S_OK ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT GetUser (
|
|
|
|
HANDLE a_Token ,
|
|
ULONG *a_Size ,
|
|
LPWSTR a_Buffer
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( a_Token )
|
|
{
|
|
if ( a_Size && a_Buffer )
|
|
{
|
|
TOKEN_USER *t_TokenUser = NULL ;
|
|
DWORD t_ReturnLength = 0 ;
|
|
TOKEN_INFORMATION_CLASS t_TokenInformationClass = TokenUser ;
|
|
|
|
BOOL t_TokenStatus = GetTokenInformation (
|
|
|
|
a_Token ,
|
|
t_TokenInformationClass ,
|
|
t_TokenUser ,
|
|
t_ReturnLength ,
|
|
& t_ReturnLength
|
|
) ;
|
|
|
|
if ( ! t_TokenStatus )
|
|
{
|
|
DWORD t_LastError = GetLastError () ;
|
|
switch ( t_LastError )
|
|
{
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
{
|
|
t_TokenUser = ( TOKEN_USER * ) new BYTE [ t_ReturnLength ] ;
|
|
|
|
t_TokenStatus = GetTokenInformation (
|
|
|
|
a_Token ,
|
|
t_TokenInformationClass ,
|
|
t_TokenUser ,
|
|
t_ReturnLength ,
|
|
& t_ReturnLength
|
|
) ;
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if ( t_TokenStatus )
|
|
{
|
|
SID_NAME_USE t_SidNameUse ;
|
|
wchar_t *t_Domain = NULL ;
|
|
wchar_t *t_User = NULL ;
|
|
ULONG t_DomainSize = 0 ;
|
|
ULONG t_UserSize = 0 ;
|
|
|
|
BOOL t_LookupStatus = LookupAccountSidW (
|
|
|
|
NULL ,
|
|
t_TokenUser->User.Sid ,
|
|
t_User ,
|
|
& t_UserSize ,
|
|
t_Domain ,
|
|
& t_DomainSize ,
|
|
& t_SidNameUse
|
|
) ;
|
|
|
|
if ( ! t_LookupStatus )
|
|
{
|
|
DWORD t_LastError = GetLastError () ;
|
|
|
|
switch ( t_LastError )
|
|
{
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
{
|
|
t_User = new wchar_t [ t_UserSize ] ;
|
|
if ( t_User )
|
|
{
|
|
t_Domain = new wchar_t [ t_DomainSize ] ;
|
|
if ( t_Domain )
|
|
{
|
|
t_LookupStatus = LookupAccountSidW (
|
|
|
|
NULL ,
|
|
t_TokenUser->User.Sid ,
|
|
t_User ,
|
|
& t_UserSize ,
|
|
t_Domain ,
|
|
& t_DomainSize ,
|
|
& t_SidNameUse
|
|
) ;
|
|
|
|
if ( t_LookupStatus )
|
|
{
|
|
ULONG t_Size = wcslen ( t_User ) + wcslen ( t_Domain ) + 2 ;
|
|
|
|
if ( *a_Size >= t_Size )
|
|
{
|
|
StringCchPrintfW ( a_Buffer , *a_Size, L"%s\\%s" , t_Domain , t_User ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_BUFFER_TOO_SMALL ;
|
|
}
|
|
|
|
*a_Size = t_Size ;
|
|
}
|
|
else
|
|
{
|
|
if ( GetLastError () == ERROR_NONE_MAPPED )
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
|
|
delete [] t_Domain ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
|
|
delete [] t_User ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case ERROR_NONE_MAPPED:
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_UNEXPECTED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
DWORD t_LastError = GetLastError () ;
|
|
}
|
|
|
|
if ( t_TokenUser )
|
|
{
|
|
delete [] ( ( BYTE * ) t_TokenUser ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT GetAuthenticationLuid (
|
|
|
|
HANDLE a_Token ,
|
|
LPVOID a_Luid
|
|
)
|
|
{
|
|
if ( a_Token )
|
|
{
|
|
TOKEN_STATISTICS t_Statistics ;
|
|
|
|
DWORD t_Returned = 0 ;
|
|
BOOL t_Status = GetTokenInformation (
|
|
|
|
a_Token,
|
|
TokenStatistics,
|
|
( void * ) & t_Statistics ,
|
|
sizeof ( t_Statistics ) ,
|
|
& t_Returned
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
* ( ( LUID * ) a_Luid ) = t_Statistics.AuthenticationId ;
|
|
}
|
|
else
|
|
{
|
|
return WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemThreadSecurityHandle :: CWbemThreadSecurityHandle ( CLifeControl *a_Control ) :
|
|
|
|
m_ReferenceCount ( 0 ) ,
|
|
m_ThreadToken ( NULL ) ,
|
|
m_ImpersonationLevel ( 0 ) ,
|
|
m_AuthorizationService ( 0 ) ,
|
|
m_AuthenticationService ( 0 ) ,
|
|
m_AuthenticationLevel ( 0 ) ,
|
|
m_ServerPrincipalName ( 0 ) ,
|
|
m_Identity ( NULL ) ,
|
|
m_Origin ( WMI_ORIGIN_UNDEFINED ) ,
|
|
m_Control ( a_Control )
|
|
{
|
|
if ( m_Control )
|
|
{
|
|
m_Control->ObjectCreated ( ( IServerSecurity * ) this ) ;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemThreadSecurityHandle :: CWbemThreadSecurityHandle (
|
|
|
|
const CWbemThreadSecurityHandle &a_Copy
|
|
|
|
) : m_ReferenceCount ( 0 ) ,
|
|
m_ThreadToken ( NULL ) ,
|
|
m_ImpersonationLevel ( 0 ) ,
|
|
m_AuthorizationService ( 0 ) ,
|
|
m_AuthenticationService ( 0 ) ,
|
|
m_AuthenticationLevel ( 0 ) ,
|
|
m_ServerPrincipalName ( 0 ) ,
|
|
m_Identity ( NULL ) ,
|
|
m_Origin ( WMI_ORIGIN_UNDEFINED ) ,
|
|
m_Control ( NULL )
|
|
{
|
|
*this = a_Copy ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemThreadSecurityHandle :: ~CWbemThreadSecurityHandle ()
|
|
{
|
|
if ( m_ThreadToken )
|
|
{
|
|
CloseHandle ( m_ThreadToken ) ;
|
|
}
|
|
|
|
if ( m_ServerPrincipalName )
|
|
{
|
|
CoTaskMemFree ( m_ServerPrincipalName ) ;
|
|
}
|
|
|
|
if ( m_Identity )
|
|
{
|
|
CoTaskMemFree ( m_Identity ) ;
|
|
}
|
|
|
|
if ( m_Control )
|
|
{
|
|
m_Control->ObjectDestroyed ( ( IServerSecurity * ) this ) ;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemThreadSecurityHandle &CWbemThreadSecurityHandle :: operator= ( const CWbemThreadSecurityHandle &a_Copy )
|
|
{
|
|
if ( m_ThreadToken )
|
|
{
|
|
CloseHandle ( m_ThreadToken ) ;
|
|
m_ThreadToken = NULL ;
|
|
}
|
|
|
|
if ( a_Copy.m_ThreadToken )
|
|
{
|
|
BOOL t_Status = DuplicateHandle (
|
|
|
|
GetCurrentProcess () ,
|
|
a_Copy.m_ThreadToken ,
|
|
GetCurrentProcess () ,
|
|
& m_ThreadToken ,
|
|
0 ,
|
|
TRUE ,
|
|
DUPLICATE_SAME_ACCESS
|
|
) ;
|
|
}
|
|
|
|
m_Origin = a_Copy.m_Origin ;
|
|
m_ImpersonationLevel = a_Copy.m_ImpersonationLevel ;
|
|
|
|
m_AuthenticationService = a_Copy.m_AuthenticationService ;
|
|
m_AuthorizationService = a_Copy.m_AuthorizationService ;
|
|
m_AuthenticationLevel = a_Copy.m_AuthenticationLevel ;
|
|
|
|
if ( m_ServerPrincipalName )
|
|
{
|
|
CoTaskMemFree ( m_ServerPrincipalName ) ;
|
|
m_ServerPrincipalName = NULL ;
|
|
}
|
|
|
|
if ( a_Copy.m_ServerPrincipalName )
|
|
{
|
|
m_ServerPrincipalName = ( LPWSTR ) CoTaskMemAlloc ( ( wcslen ( a_Copy.m_ServerPrincipalName ) + 1 ) * 2 ) ;
|
|
if ( m_ServerPrincipalName )
|
|
{
|
|
StringCchCopyW ( m_ServerPrincipalName, wcslen ( a_Copy.m_ServerPrincipalName ) + 1, a_Copy.m_ServerPrincipalName ) ;
|
|
}
|
|
}
|
|
|
|
if ( m_Identity )
|
|
{
|
|
CoTaskMemFree ( m_Identity ) ;
|
|
m_Identity = NULL ;
|
|
}
|
|
|
|
if ( a_Copy.m_Identity )
|
|
{
|
|
m_Identity = ( LPWSTR ) CoTaskMemAlloc ( ( wcslen ( a_Copy.m_Identity ) + 1 ) * 2 ) ;
|
|
if ( m_Identity )
|
|
{
|
|
StringCchCopyW ( m_Identity , wcslen ( a_Copy.m_Identity ) + 1, a_Copy.m_Identity ) ;
|
|
}
|
|
}
|
|
|
|
if ( a_Copy.m_Control )
|
|
{
|
|
m_Control = a_Copy.m_Control ;
|
|
if ( m_Control )
|
|
{
|
|
m_Control->ObjectCreated ( ( IServerSecurity * ) this ) ;
|
|
}
|
|
|
|
}
|
|
|
|
return *this ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
ULONG CWbemThreadSecurityHandle :: AddRef ()
|
|
{
|
|
return InterlockedIncrement ( & m_ReferenceCount ) ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
ULONG CWbemThreadSecurityHandle :: Release ()
|
|
{
|
|
LONG t_ReferenceCount = InterlockedDecrement( & m_ReferenceCount ) ;
|
|
if ( t_ReferenceCount == 0 )
|
|
{
|
|
delete this ;
|
|
}
|
|
|
|
return t_ReferenceCount ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: QueryInterface ( REFIID a_Riid , void **a_Void )
|
|
{
|
|
if ( a_Riid == IID_IUnknown )
|
|
{
|
|
*a_Void = ( void ** ) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else if ( a_Riid == IID__IWmiThreadSecHandle )
|
|
{
|
|
*a_Void = ( void ** ) ( _IWmiThreadSecHandle * ) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else if ( a_Riid == IID_CWbemThreadSecurityHandle )
|
|
{
|
|
*a_Void = ( void ** ) ( CWbemThreadSecurityHandle * ) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE ;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: GetToken ( HANDLE *a_ThreadToken )
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( a_ThreadToken )
|
|
{
|
|
if ( m_ThreadToken )
|
|
{
|
|
HANDLE t_ThreadToken = NULL ;
|
|
|
|
BOOL t_Status = DuplicateHandle (
|
|
|
|
GetCurrentProcess () ,
|
|
m_ThreadToken ,
|
|
GetCurrentProcess () ,
|
|
& t_ThreadToken ,
|
|
0 ,
|
|
TRUE ,
|
|
DUPLICATE_SAME_ACCESS
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
*a_ThreadToken = t_ThreadToken ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: GetUser (
|
|
|
|
ULONG *a_Size ,
|
|
LPWSTR a_Buffer
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( m_ThreadToken )
|
|
{
|
|
t_Result = :: GetUser ( m_ThreadToken , a_Size , a_Buffer ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: GetUserSid (
|
|
|
|
ULONG *a_Size ,
|
|
PSID a_Sid
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( m_ThreadToken )
|
|
{
|
|
t_Result = :: GetUserSid ( m_ThreadToken , a_Size , a_Sid ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: GetAuthenticationLuid ( LPVOID a_Luid )
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( m_ThreadToken )
|
|
{
|
|
t_Result = :: GetAuthenticationLuid ( m_ThreadToken , a_Luid ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: GetImpersonation ( DWORD *a_Level )
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( m_ThreadToken )
|
|
{
|
|
if ( a_Level )
|
|
{
|
|
SECURITY_IMPERSONATION_LEVEL t_ImpersonationLevel = SecurityAnonymous ;
|
|
TOKEN_TYPE t_TokenType = TokenImpersonation ;
|
|
|
|
t_Result = :: GetImpersonationLevel (
|
|
|
|
m_ThreadToken ,
|
|
t_ImpersonationLevel ,
|
|
t_TokenType
|
|
) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
switch ( t_ImpersonationLevel )
|
|
{
|
|
case SecurityAnonymous:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_ANONYMOUS ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityIdentification:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_IDENTIFY ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityImpersonation:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_IMPERSONATE ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityDelegation:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_DELEGATE ;
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
*a_Level = 0 ;
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: GetAuthentication (
|
|
|
|
DWORD *a_Level
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( a_Level )
|
|
{
|
|
*a_Level = GetAuthenticationLevel () ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: CloneRpcContext (
|
|
|
|
IServerSecurity *a_Security
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
// If here, we are not impersonating and we want to gather info
|
|
// about the client's call.
|
|
// ============================================================
|
|
|
|
RPC_AUTHZ_HANDLE t_Authorization = NULL ;
|
|
|
|
// Ensures auto release of the mutex if we crash
|
|
|
|
// CAutoSecurityMutex t_SecurityMutex ;
|
|
|
|
DWORD t_ImpersonationLevel = 0 ;
|
|
|
|
t_Result = a_Security->QueryBlanket (
|
|
|
|
& m_AuthenticationService ,
|
|
& m_AuthorizationService ,
|
|
& m_ServerPrincipalName ,
|
|
& m_AuthenticationLevel ,
|
|
& t_ImpersonationLevel ,
|
|
& t_Authorization ,
|
|
NULL
|
|
) ;
|
|
|
|
if ( FAILED ( t_Result ) )
|
|
{
|
|
|
|
// In some cases, we cant get the name, but the rest is ok. In particular
|
|
// the temporary SMS accounts have that property. Or nt 4 after IPCONFIG /RELEASE
|
|
|
|
t_Result = a_Security->QueryBlanket (
|
|
|
|
& m_AuthenticationService ,
|
|
& m_AuthorizationService ,
|
|
& m_ServerPrincipalName ,
|
|
& m_AuthenticationLevel ,
|
|
& t_ImpersonationLevel ,
|
|
NULL ,
|
|
NULL
|
|
) ;
|
|
|
|
t_Authorization = NULL ;
|
|
}
|
|
|
|
// We don't need this anymore.
|
|
|
|
// t_SecurityMutex.Release () ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
if ( t_Authorization )
|
|
{
|
|
m_Identity = LPWSTR ( CoTaskMemAlloc ( ( wcslen ( LPWSTR ( t_Authorization ) ) + 1 ) * 2 ) ) ;
|
|
if ( m_Identity )
|
|
{
|
|
StringCchCopyW ( m_Identity , wcslen ( LPWSTR ( t_Authorization ) ) + 1, LPWSTR ( t_Authorization ) ) ;
|
|
}
|
|
}
|
|
|
|
// Impersonate the client long enough to clone the thread token.
|
|
// =============================================================
|
|
|
|
BOOL t_Impersonating = a_Security->IsImpersonating () ;
|
|
if ( ! t_Impersonating )
|
|
{
|
|
t_Result = a_Security->ImpersonateClient () ;
|
|
}
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Result = CloneThreadContext () ;
|
|
|
|
if ( ! t_Impersonating )
|
|
{
|
|
a_Security->RevertToSelf () ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// THIS IS A WORKAROUND FOR COM BUG:
|
|
// This failure is indicative of an anonymous-level client.
|
|
// ========================================================
|
|
|
|
m_ImpersonationLevel = 0 ;
|
|
|
|
t_Result = S_OK ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: CloneThreadContext ()
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
BOOL t_Status = OpenThreadToken (
|
|
|
|
GetCurrentThread () ,
|
|
MAXIMUM_ALLOWED ,
|
|
TRUE ,
|
|
& m_ThreadToken
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
// Find out token info.
|
|
// =====================
|
|
|
|
DWORD t_ImpersonationLevel = 0 ;
|
|
DWORD t_Returned = 0 ;
|
|
|
|
t_Status = GetTokenInformation (
|
|
|
|
m_ThreadToken ,
|
|
TokenImpersonationLevel ,
|
|
& t_ImpersonationLevel ,
|
|
sizeof ( DWORD ) ,
|
|
& t_Returned
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
switch ( t_ImpersonationLevel )
|
|
{
|
|
case SecurityAnonymous:
|
|
{
|
|
m_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityIdentification:
|
|
{
|
|
m_ImpersonationLevel = RPC_C_IMP_LEVEL_IDENTIFY ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityImpersonation:
|
|
{
|
|
m_ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityDelegation:
|
|
{
|
|
m_ImpersonationLevel = RPC_C_IMP_LEVEL_DELEGATE ;
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
m_ImpersonationLevel = 0 ;
|
|
}
|
|
break ;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( GetLastError () == ERROR_ACCESS_DENIED )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( GetLastError () == ERROR_ACCESS_DENIED )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemThreadSecurityHandle :: CloneProcessContext ()
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
m_AuthenticationService = RPC_C_AUTHN_WINNT ;
|
|
m_AuthorizationService = RPC_C_AUTHZ_NONE ;
|
|
m_AuthenticationLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY ;
|
|
m_ServerPrincipalName = NULL ;
|
|
m_Identity = NULL ;
|
|
|
|
HANDLE t_ProcessToken = NULL ;
|
|
BOOL t_Status = OpenProcessToken (
|
|
|
|
GetCurrentProcess () ,
|
|
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE ,
|
|
& t_ProcessToken
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Status = DuplicateTokenEx (
|
|
|
|
t_ProcessToken,
|
|
MAXIMUM_ALLOWED ,
|
|
NULL ,
|
|
( SECURITY_IMPERSONATION_LEVEL ) SecurityImpersonation ,
|
|
TokenImpersonation ,
|
|
& m_ThreadToken
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
// This is the basic process thread.
|
|
// =================================
|
|
|
|
m_ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE ;
|
|
|
|
t_Result = S_OK ;
|
|
}
|
|
else
|
|
{
|
|
// Unknown error
|
|
// =============
|
|
|
|
m_ImpersonationLevel = 0 ;
|
|
|
|
t_Result = E_FAIL ;
|
|
}
|
|
|
|
CloseHandle ( t_ProcessToken ) ;
|
|
}
|
|
else
|
|
{
|
|
// Unknown error
|
|
// =============
|
|
|
|
m_ImpersonationLevel = 0 ;
|
|
|
|
t_Result = E_FAIL ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemThreadSecurityHandle *CWbemThreadSecurityHandle :: New ()
|
|
{
|
|
return new CWbemThreadSecurityHandle ( NULL ) ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemCallSecurity :: CWbemCallSecurity (
|
|
|
|
CLifeControl *a_Control
|
|
|
|
) : m_ReferenceCount ( 0 ) ,
|
|
m_ImpersonationLevel ( 0 ) ,
|
|
m_ThreadSecurityHandle ( NULL ) ,
|
|
m_ThreadToken ( NULL ) ,
|
|
m_Control ( a_Control )
|
|
{
|
|
if ( m_Control )
|
|
{
|
|
m_Control->ObjectCreated ( ( IServerSecurity * ) this ) ;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemCallSecurity :: ~CWbemCallSecurity ()
|
|
{
|
|
if ( m_ThreadToken )
|
|
{
|
|
CloseHandle ( m_ThreadToken ) ;
|
|
}
|
|
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
m_ThreadSecurityHandle->Release () ;
|
|
}
|
|
|
|
if ( m_Control )
|
|
{
|
|
m_Control->ObjectDestroyed ( ( IServerSecurity * ) this ) ;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemCallSecurity &CWbemCallSecurity :: operator= ( const CWbemCallSecurity &a_Copy )
|
|
{
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
m_ThreadSecurityHandle->Release () ;
|
|
m_ThreadSecurityHandle = NULL ;
|
|
}
|
|
|
|
if ( a_Copy.m_Control )
|
|
{
|
|
m_Control = a_Copy.m_Control ;
|
|
if ( m_Control )
|
|
{
|
|
m_Control->ObjectCreated ( ( IServerSecurity * ) this ) ;
|
|
}
|
|
}
|
|
|
|
if ( a_Copy.m_ThreadSecurityHandle )
|
|
{
|
|
m_ThreadSecurityHandle = new CWbemThreadSecurityHandle ( * ( a_Copy.m_ThreadSecurityHandle ) ) ;
|
|
}
|
|
|
|
m_ImpersonationLevel = a_Copy.m_ImpersonationLevel ;
|
|
|
|
m_ReferenceCount = 1 ;
|
|
|
|
return *this ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
ULONG CWbemCallSecurity :: AddRef ()
|
|
{
|
|
return InterlockedIncrement ( & m_ReferenceCount ) ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
ULONG CWbemCallSecurity :: Release ()
|
|
{
|
|
LONG t_ReferenceCount = InterlockedDecrement( & m_ReferenceCount ) ;
|
|
if ( t_ReferenceCount == 0 )
|
|
{
|
|
delete this ;
|
|
}
|
|
|
|
return t_ReferenceCount ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: QueryInterface ( REFIID a_Riid , void **a_Void )
|
|
{
|
|
if ( a_Riid == IID_IUnknown )
|
|
{
|
|
*a_Void = ( void ** ) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else if ( a_Riid == IID_IServerSecurity )
|
|
{
|
|
*a_Void = ( void ** ) ( IServerSecurity * ) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else if ( a_Riid == IID_CWbemCallSecurity )
|
|
{
|
|
*a_Void = ( void ** ) ( CWbemCallSecurity * ) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else if ( a_Riid == IID__IWmiCallSec )
|
|
{
|
|
*a_Void = ( void ** ) ( _IWmiCallSec *) this ;
|
|
|
|
AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE ;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: QueryBlanket (
|
|
|
|
DWORD *a_AuthenticationService ,
|
|
DWORD *a_AuthorizationService ,
|
|
OLECHAR **a_ServerPrincipalName ,
|
|
DWORD *a_AuthenticationLevel ,
|
|
DWORD *a_ImpersonationLevel ,
|
|
void **a_Privileges ,
|
|
DWORD *a_Capabilities
|
|
)
|
|
{
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
if ( m_ThreadSecurityHandle->GetImpersonationLevel () == 0 )
|
|
{
|
|
return E_FAIL ;
|
|
}
|
|
|
|
if ( a_AuthenticationService )
|
|
{
|
|
*a_AuthenticationService = m_ThreadSecurityHandle->GetAuthenticationService () ;
|
|
}
|
|
|
|
if ( a_AuthorizationService )
|
|
{
|
|
*a_AuthorizationService = m_ThreadSecurityHandle->GetAuthorizationService () ;
|
|
}
|
|
|
|
if ( a_ImpersonationLevel )
|
|
{
|
|
*a_ImpersonationLevel = m_ThreadSecurityHandle->GetImpersonationLevel () ;
|
|
}
|
|
|
|
if ( a_AuthenticationLevel )
|
|
{
|
|
*a_AuthenticationLevel = m_ThreadSecurityHandle->GetAuthenticationLevel () ;
|
|
}
|
|
|
|
if ( a_ServerPrincipalName )
|
|
{
|
|
*a_ServerPrincipalName = 0 ;
|
|
|
|
if ( m_ThreadSecurityHandle->GetServerPrincipalName () )
|
|
{
|
|
*a_ServerPrincipalName = ( LPWSTR ) CoTaskMemAlloc ( ( wcslen ( m_ThreadSecurityHandle->GetServerPrincipalName () ) + 1 ) * 2 ) ;
|
|
if ( a_ServerPrincipalName )
|
|
{
|
|
StringCchCopyW ( *a_ServerPrincipalName , wcslen ( m_ThreadSecurityHandle->GetServerPrincipalName () ) + 1, m_ThreadSecurityHandle->GetServerPrincipalName () ) ;
|
|
}
|
|
else
|
|
{
|
|
return E_OUTOFMEMORY ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( a_Privileges )
|
|
{
|
|
*a_Privileges = m_ThreadSecurityHandle->GetIdentity () ; // Documented to point to an internal!!
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: ImpersonateClient ()
|
|
{
|
|
if ( m_ImpersonationLevel != 0 )
|
|
{
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
if ( m_ThreadSecurityHandle->GetImpersonationLevel () == 0 )
|
|
{
|
|
return ( ERROR_CANT_OPEN_ANONYMOUS | 0x80070000 ) ;
|
|
}
|
|
|
|
BOOL t_Status = OpenThreadToken (
|
|
|
|
GetCurrentThread () ,
|
|
TOKEN_IMPERSONATE ,
|
|
TRUE ,
|
|
& m_ThreadToken
|
|
) ;
|
|
|
|
if ( t_Status == FALSE )
|
|
{
|
|
DWORD t_LastError = GetLastError () ;
|
|
if ( ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN || t_LastError == ERROR_NO_TOKEN ) )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
return ( ERROR_ACCESS_DENIED | 0x80070000 ) ;
|
|
}
|
|
}
|
|
|
|
t_Status = SetThreadToken ( NULL , m_ThreadSecurityHandle->GetThreadToken () ) ;
|
|
if ( t_Status )
|
|
{
|
|
m_ImpersonationLevel = m_ThreadSecurityHandle->GetImpersonationLevel () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle ( m_ThreadToken ) ;
|
|
|
|
m_ThreadToken = NULL ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
}
|
|
|
|
return E_FAIL ;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: RevertToSelf ()
|
|
{
|
|
if ( m_ImpersonationLevel == 0 )
|
|
{
|
|
return S_OK ;
|
|
}
|
|
else
|
|
{
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
// If here,we are impersonating and can definitely revert.
|
|
// =======================================================
|
|
|
|
BOOL t_Status = SetThreadToken ( NULL , m_ThreadToken ) ;
|
|
if ( t_Status == FALSE )
|
|
{
|
|
return ( GetLastError () | 0x80070000 ) ;
|
|
}
|
|
|
|
CloseHandle ( m_ThreadToken ) ;
|
|
|
|
m_ThreadToken = NULL ;
|
|
|
|
m_ImpersonationLevel = 0 ;
|
|
}
|
|
else
|
|
{
|
|
return ( ERROR_INVALID_HANDLE | 0x80070000 ) ;
|
|
}
|
|
}
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL CWbemCallSecurity :: IsImpersonating ()
|
|
{
|
|
if ( m_ImpersonationLevel != 0 )
|
|
{
|
|
return TRUE ;
|
|
}
|
|
|
|
return FALSE ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: GetThreadSecurity (
|
|
|
|
WMI_THREAD_SECURITY_ORIGIN a_Origin ,
|
|
_IWmiThreadSecHandle **a_ThreadSecurity
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
BOOL t_ValidOrigin = ( ( a_Origin & WMI_ORIGIN_THREAD ) || ( a_Origin & WMI_ORIGIN_EXISTING ) || ( a_Origin & WMI_ORIGIN_RPC ) ) ;
|
|
|
|
if ( a_ThreadSecurity && t_ValidOrigin )
|
|
{
|
|
if ( a_Origin & WMI_ORIGIN_THREAD )
|
|
{
|
|
*a_ThreadSecurity = new CWbemThreadSecurityHandle ( m_Control ) ;
|
|
if ( *a_ThreadSecurity )
|
|
{
|
|
( *a_ThreadSecurity )->AddRef () ;
|
|
|
|
( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity )->SetOrigin ( WMI_ORIGIN_THREAD ) ;
|
|
|
|
t_Result = ( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity)->CloneThreadContext () ;
|
|
if ( FAILED ( t_Result ) )
|
|
{
|
|
( *a_ThreadSecurity )->Release () ;
|
|
*a_ThreadSecurity = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
|
|
if ( t_Result == WBEM_E_NOT_FOUND )
|
|
{
|
|
if ( a_Origin & WMI_ORIGIN_RPC || a_Origin & WMI_ORIGIN_EXISTING )
|
|
{
|
|
// Figure out if the call context is ours or RPCs
|
|
// ==============================================
|
|
|
|
IServerSecurity *t_Security = NULL ;
|
|
t_Result = CoGetCallContext ( IID_IServerSecurity , ( void ** ) & t_Security ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
CWbemCallSecurity *t_Internal = NULL ;
|
|
if ( SUCCEEDED ( t_Security->QueryInterface ( IID_CWbemCallSecurity , ( void ** ) & t_Internal ) ) )
|
|
{
|
|
|
|
// This is our own call context --- this must be an in-proc object
|
|
// calling us from our thread. Behave depending on the flags
|
|
// ===============================================================
|
|
|
|
if ( a_Origin & WMI_ORIGIN_EXISTING )
|
|
{
|
|
*a_ThreadSecurity = new CWbemThreadSecurityHandle ( *t_Internal->GetThreadSecurityHandle () ) ;
|
|
if ( *a_ThreadSecurity )
|
|
{
|
|
(*a_ThreadSecurity)->AddRef () ;
|
|
|
|
t_Result = S_OK ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
|
|
t_Internal->Release () ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
|
|
if ( t_Result == WBEM_E_NOT_FOUND )
|
|
{
|
|
if ( a_Origin & WMI_ORIGIN_RPC )
|
|
{
|
|
*a_ThreadSecurity = new CWbemThreadSecurityHandle ( m_Control ) ;
|
|
if ( *a_ThreadSecurity )
|
|
{
|
|
( *a_ThreadSecurity )->AddRef () ;
|
|
|
|
t_Result = ( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity)->CloneRpcContext (
|
|
|
|
t_Security
|
|
) ;
|
|
|
|
if ( SUCCEEDED( t_Result ) )
|
|
{
|
|
( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity) ->SetOrigin ( WMI_ORIGIN_RPC ) ;
|
|
}
|
|
else
|
|
{
|
|
( *a_ThreadSecurity )->Release ();
|
|
*a_ThreadSecurity = NULL;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
}
|
|
|
|
t_Security->Release();
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
|
|
if ( t_Result == WBEM_E_NOT_FOUND )
|
|
{
|
|
if ( a_Origin & WMI_ORIGIN_THREAD )
|
|
{
|
|
*a_ThreadSecurity = new CWbemThreadSecurityHandle ( m_Control ) ;
|
|
if ( *a_ThreadSecurity )
|
|
{
|
|
( *a_ThreadSecurity )->AddRef () ;
|
|
|
|
( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity )->SetOrigin ( WMI_ORIGIN_THREAD ) ;
|
|
|
|
t_Result = ( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity)->CloneProcessContext () ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( a_Origin & WMI_ORIGIN_THREAD )
|
|
{
|
|
*a_ThreadSecurity = new CWbemThreadSecurityHandle ( m_Control ) ;
|
|
if ( *a_ThreadSecurity )
|
|
{
|
|
( *a_ThreadSecurity )->AddRef () ;
|
|
|
|
( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity )->SetOrigin ( WMI_ORIGIN_THREAD ) ;
|
|
|
|
t_Result = ( ( CWbemThreadSecurityHandle * ) *a_ThreadSecurity)->CloneProcessContext () ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: SetThreadSecurity (
|
|
|
|
_IWmiThreadSecHandle *a_ThreadSecurity
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
m_ThreadSecurityHandle->Release () ;
|
|
m_ThreadSecurityHandle = NULL ;
|
|
}
|
|
|
|
if ( a_ThreadSecurity )
|
|
{
|
|
CWbemThreadSecurityHandle *t_ThreadHandle = NULL ;
|
|
t_Result = a_ThreadSecurity->QueryInterface ( IID_CWbemThreadSecurityHandle , ( void ** ) & t_ThreadHandle ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
m_ThreadSecurityHandle = t_ThreadHandle ;
|
|
|
|
IUnknown *t_Unknown = NULL ;
|
|
IUnknown *t_SwitchUnknown = NULL ;
|
|
t_Result = this->QueryInterface ( IID_IUnknown , ( void **) & t_SwitchUnknown ) ;
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
t_Result = CoSwitchCallContext ( t_SwitchUnknown, & t_Unknown ) ;
|
|
|
|
t_SwitchUnknown->Release () ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: GetUser (
|
|
|
|
ULONG *a_Size ,
|
|
LPWSTR a_Buffer
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
HANDLE t_Token = NULL ;
|
|
|
|
BOOL t_Status = OpenThreadToken (
|
|
|
|
GetCurrentThread() ,
|
|
TOKEN_QUERY,
|
|
TRUE ,
|
|
& t_Token
|
|
) ;
|
|
|
|
DWORD t_LastError = GetLastError () ;
|
|
if ( ! t_Status && ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN || t_LastError == ERROR_NO_TOKEN ) )
|
|
{
|
|
t_Status = OpenProcessToken (
|
|
|
|
GetCurrentProcess() ,
|
|
TOKEN_QUERY,
|
|
& t_Token
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! t_Status )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Result = :: GetUser ( t_Token , a_Size , a_Buffer ) ;
|
|
|
|
CloseHandle ( t_Token ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: GetUserSid (
|
|
|
|
ULONG *a_Size ,
|
|
PSID a_Sid
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
HANDLE t_Token = NULL ;
|
|
|
|
BOOL t_Status = OpenThreadToken (
|
|
|
|
GetCurrentThread () ,
|
|
TOKEN_QUERY,
|
|
TRUE ,
|
|
& t_Token
|
|
) ;
|
|
|
|
DWORD t_LastError = GetLastError () ;
|
|
if ( ! t_Status && ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN || t_LastError == ERROR_NO_TOKEN ) )
|
|
{
|
|
t_Status = OpenProcessToken (
|
|
|
|
GetCurrentProcess () ,
|
|
TOKEN_QUERY,
|
|
& t_Token
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! t_Status )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Result = :: GetUserSid ( t_Token , a_Size , a_Sid ) ;
|
|
|
|
CloseHandle ( t_Token ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: GetAuthenticationLuid ( LPVOID a_Luid )
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
HANDLE t_Token = NULL ;
|
|
|
|
BOOL t_Status = OpenThreadToken (
|
|
|
|
GetCurrentThread () ,
|
|
TOKEN_QUERY,
|
|
TRUE ,
|
|
& t_Token
|
|
) ;
|
|
|
|
DWORD t_LastError = GetLastError () ;
|
|
if ( ! t_Status && ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN || t_LastError == ERROR_NO_TOKEN ) )
|
|
{
|
|
t_Status = OpenProcessToken (
|
|
|
|
GetCurrentProcess () ,
|
|
TOKEN_QUERY,
|
|
& t_Token
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! t_Status )
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Result = :: GetAuthenticationLuid ( t_Token , a_Luid ) ;
|
|
|
|
CloseHandle ( t_Token ) ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: GetImpersonation ( DWORD *a_Level )
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( a_Level )
|
|
{
|
|
HANDLE t_Token = NULL ;
|
|
|
|
BOOL t_Status = OpenThreadToken (
|
|
|
|
GetCurrentThread () ,
|
|
TOKEN_QUERY,
|
|
TRUE ,
|
|
& t_Token
|
|
) ;
|
|
|
|
DWORD t_LastError = GetLastError () ;
|
|
if ( ! t_Status && ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN || t_LastError == ERROR_NO_TOKEN ) )
|
|
{
|
|
*a_Level = 0 ;
|
|
}
|
|
else
|
|
{
|
|
if ( t_Status )
|
|
{
|
|
SECURITY_IMPERSONATION_LEVEL t_ImpersonationLevel = SecurityAnonymous ;
|
|
TOKEN_TYPE t_TokenType = TokenImpersonation ;
|
|
|
|
t_Result = :: GetImpersonationLevel (
|
|
|
|
t_Token ,
|
|
t_ImpersonationLevel ,
|
|
t_TokenType
|
|
) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
switch ( t_ImpersonationLevel )
|
|
{
|
|
case SecurityAnonymous:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_ANONYMOUS ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityIdentification:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_IDENTIFY ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityImpersonation:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_IMPERSONATE ;
|
|
}
|
|
break ;
|
|
|
|
case SecurityDelegation:
|
|
{
|
|
*a_Level = RPC_C_IMP_LEVEL_DELEGATE ;
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
*a_Level = 0 ;
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
|
|
CloseHandle ( t_Token ) ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_ACCESS_DENIED ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CWbemCallSecurity :: GetAuthentication (
|
|
|
|
DWORD *a_Level
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
if ( a_Level )
|
|
{
|
|
if ( m_ThreadSecurityHandle )
|
|
{
|
|
*a_Level = m_ThreadSecurityHandle->GetAuthenticationLevel () ;
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_NOT_FOUND ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = WBEM_E_INVALID_PARAMETER ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CWbemCallSecurity *CWbemCallSecurity :: New ()
|
|
{
|
|
return new CWbemCallSecurity ( NULL ) ;
|
|
}
|