|
|
/*++
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 ) ; }
|