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.
900 lines
24 KiB
900 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
urlauth.cxx
|
|
|
|
Abstract:
|
|
|
|
Implements an ISAPI * scriptmap which handles authorization by calling
|
|
into the NT AuthZ framework.
|
|
|
|
Author:
|
|
|
|
Bilal Alam (balam) Nov 26, 2001
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
DECLARE_DEBUG_PRINTS_OBJECT();
|
|
DECLARE_DEBUG_VARIABLE();
|
|
|
|
// local function declarations
|
|
HRESULT
|
|
GetTokenForExecution(
|
|
EXTENSION_CONTROL_BLOCK *pecb,
|
|
HANDLE * phToken
|
|
);
|
|
|
|
// global data
|
|
ADMIN_MANAGER_CACHE * g_pAdminManagerCache;
|
|
|
|
VOID
|
|
WINAPI
|
|
UrlAuthCompletion(
|
|
EXTENSION_CONTROL_BLOCK * pecb,
|
|
PVOID pvContext,
|
|
DWORD,
|
|
DWORD
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Routine to be called whenever ISAPI async stuff completes
|
|
|
|
Arguments:
|
|
|
|
pecb - EXTENSION_CONTROL_BLOCK *
|
|
pContext - Unused
|
|
cbIo - Unused
|
|
dwError - Unused
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if ( pvContext )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( pvContext ) );
|
|
pvContext = NULL;
|
|
}
|
|
|
|
pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_DONE_WITH_SESSION,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
HttpExtensionProc(
|
|
EXTENSION_CONTROL_BLOCK * pecb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main entry point for ISAPI
|
|
|
|
Arguments:
|
|
|
|
pecb - EXTENSION_CONTROL_BLOCK *
|
|
|
|
Return Value:
|
|
|
|
HSE_STATUS_*
|
|
|
|
--*/
|
|
{
|
|
BOOL fRet;
|
|
STACK_BUFFER( buff, 512 );
|
|
DWORD cbBuffer;
|
|
BOOL fAccessGranted = FALSE;
|
|
BOOL fFatalError = FALSE;
|
|
WCHAR * pszAdminStore;
|
|
ADMIN_MANAGER * pAdminManager = NULL;
|
|
AZ_APPLICATION * pApplication = NULL;
|
|
WCHAR * pszScopeName;
|
|
HRESULT hr = NO_ERROR;
|
|
METADATA_RECORD * pRecord;
|
|
HANDLE hImpersonationToken = NULL;
|
|
HSE_CUSTOM_ERROR_INFO CustomErrorInfo = { "500 Server Error", 0, TRUE };
|
|
|
|
//
|
|
// First determine whether URL authorization is even enabled for this
|
|
// URL
|
|
//
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb,
|
|
HSE_REQ_GET_METADATA_PROPERTY,
|
|
buff.QueryPtr(),
|
|
&cbBuffer,
|
|
(LPDWORD) MD_ENABLE_URL_AUTHORIZATION );
|
|
if ( !fRet )
|
|
{
|
|
if ( GetLastError() == ERROR_INVALID_INDEX )
|
|
{
|
|
// the common case is to fail with ERROR_INVALID_INDEX == access granted by no present metadata
|
|
// if the above call failed with someting like OUTOFMEMORY or INVALIDPARAMETER do not allow access.
|
|
fAccessGranted = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
//
|
|
// Check the property now. If invalid type or if 0, then we're done
|
|
//
|
|
|
|
pRecord = (METADATA_RECORD*) buff.QueryPtr();
|
|
if ( pRecord->dwMDDataType != DWORD_METADATA ||
|
|
*((DWORD*)pRecord->pbMDData) == 0 )
|
|
{
|
|
fAccessGranted = TRUE;
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
//
|
|
// If we're still a go, then retrieve the store name from the metabase.
|
|
// This is our key into the AdminManager cache we maintain
|
|
//
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb,
|
|
HSE_REQ_GET_METADATA_PROPERTY,
|
|
buff.QueryPtr(),
|
|
&cbBuffer,
|
|
(LPDWORD) MD_URL_AUTHORIZATION_STORE_NAME );
|
|
if ( !fRet )
|
|
{
|
|
//
|
|
// The only acceptable error is insufficient buffer. Otherwise, we
|
|
// don't have a store name and we're sunk
|
|
//
|
|
|
|
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
CustomErrorInfo.pszStatus = "500 Server Error";
|
|
CustomErrorInfo.uHttpSubError = 17;
|
|
CustomErrorInfo.fAsync = TRUE;
|
|
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
DBG_ASSERT( cbBuffer > buff.QuerySize() );
|
|
|
|
if ( !buff.Resize( cbBuffer ) )
|
|
{
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb,
|
|
HSE_REQ_GET_METADATA_PROPERTY,
|
|
buff.QueryPtr(),
|
|
&cbBuffer,
|
|
(LPDWORD) MD_URL_AUTHORIZATION_STORE_NAME );
|
|
if ( !fRet )
|
|
{
|
|
DBG_ASSERT( GetLastError() != ERROR_INSUFFICIENT_BUFFER );
|
|
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto AccessCheckComplete;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Store name better be a string
|
|
//
|
|
|
|
pRecord = (METADATA_RECORD*) buff.QueryPtr();
|
|
if ( pRecord->dwMDDataType != STRING_METADATA )
|
|
{
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
//
|
|
// We should have an AdminManager store name now. Get an ADMIN_MANAGER
|
|
// from the cache (cache will create it if not already in cache)
|
|
//
|
|
|
|
pszAdminStore = (WCHAR*) pRecord->pbMDData;
|
|
|
|
DBG_ASSERT( g_pAdminManagerCache != NULL );
|
|
|
|
hr = g_pAdminManagerCache->GetAdminManager( pszAdminStore,
|
|
&pAdminManager );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
//
|
|
// That sucks. We couldn't find an admin manager
|
|
//
|
|
|
|
CustomErrorInfo.pszStatus = "500 Server Error";
|
|
CustomErrorInfo.uHttpSubError = 18;
|
|
CustomErrorInfo.fAsync = TRUE;
|
|
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
DBG_ASSERT( pAdminManager != NULL );
|
|
|
|
//
|
|
// Get the application from the AdminManager. That should be trivial
|
|
// since we always have the same application name.
|
|
//
|
|
|
|
hr = pAdminManager->GetApplication( &pApplication );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
fFatalError = TRUE;
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
DBG_ASSERT( pApplication != NULL );
|
|
|
|
//
|
|
// Get the scope name for this request
|
|
//
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb,
|
|
HSE_REQ_GET_METADATA_PROPERTY,
|
|
buff.QueryPtr(),
|
|
&cbBuffer,
|
|
(LPDWORD) MD_URL_AUTHORIZATION_SCOPE_NAME );
|
|
if ( !fRet )
|
|
{
|
|
//
|
|
// It is acceptable to have no scope name. Then we use the NULL scope
|
|
//
|
|
|
|
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
DBG_ASSERT( cbBuffer > buff.QuerySize() );
|
|
|
|
if ( !buff.Resize( cbBuffer ) )
|
|
{
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb,
|
|
HSE_REQ_GET_METADATA_PROPERTY,
|
|
buff.QueryPtr(),
|
|
&cbBuffer,
|
|
(LPDWORD) MD_URL_AUTHORIZATION_SCOPE_NAME );
|
|
if ( !fRet )
|
|
{
|
|
DBG_ASSERT( GetLastError() != ERROR_INSUFFICIENT_BUFFER );
|
|
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto AccessCheckComplete;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fRet )
|
|
{
|
|
pRecord = (METADATA_RECORD*) buff.QueryPtr();
|
|
|
|
if ( pRecord->dwMDDataType != STRING_METADATA )
|
|
{
|
|
fFatalError = TRUE;
|
|
hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
//
|
|
// We have a scope name. It better be a string
|
|
//
|
|
|
|
pszScopeName = (WCHAR*) pRecord->pbMDData;
|
|
}
|
|
else
|
|
{
|
|
pszScopeName = NULL;
|
|
}
|
|
|
|
//
|
|
// Do the access check
|
|
//
|
|
|
|
hr = pApplication->DoAccessCheck( pecb,
|
|
pszScopeName,
|
|
&fAccessGranted );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
fFatalError = TRUE;
|
|
goto AccessCheckComplete;
|
|
}
|
|
|
|
//
|
|
// Determine what impersonation token should be used for execution of real URL
|
|
//
|
|
|
|
if ( fAccessGranted )
|
|
{
|
|
hr = GetTokenForExecution( pecb, &hImpersonationToken );
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
DBG_ASSERT( !hImpersonationToken );
|
|
fAccessGranted = FALSE;
|
|
fFatalError = TRUE;
|
|
goto AccessCheckComplete;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Didn't have access. Thats a 401.7
|
|
//
|
|
|
|
CustomErrorInfo.pszStatus = "401 Unauthorized";
|
|
CustomErrorInfo.uHttpSubError = 7;
|
|
CustomErrorInfo.fAsync = TRUE;
|
|
}
|
|
|
|
AccessCheckComplete:
|
|
|
|
// not OK to have both access granted and a fatal error.
|
|
DBG_ASSERT ( !( fAccessGranted && fFatalError ) );
|
|
|
|
//
|
|
// Do some cleanup
|
|
//
|
|
|
|
if ( pAdminManager != NULL )
|
|
{
|
|
pAdminManager->DereferenceCacheEntry();
|
|
pAdminManager = NULL;
|
|
}
|
|
|
|
//
|
|
// Time to do something (TM).
|
|
//
|
|
|
|
if ( fAccessGranted )
|
|
{
|
|
HSE_EXEC_UNICODE_URL_INFO ExecUrlInfo;
|
|
HSE_EXEC_UNICODE_URL_USER_INFO ExecUrlUserInfo;
|
|
|
|
//
|
|
// Everything is ok. Just execute the original URL
|
|
//
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_IO_COMPLETION,
|
|
UrlAuthCompletion,
|
|
NULL,
|
|
(LPDWORD) hImpersonationToken );
|
|
if ( !fRet )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
if ( hImpersonationToken )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( hImpersonationToken ) );
|
|
hImpersonationToken = NULL;
|
|
}
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
ZeroMemory( &ExecUrlInfo, sizeof( ExecUrlInfo ) );
|
|
|
|
ExecUrlInfo.dwExecUrlFlags = HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR;
|
|
|
|
if ( hImpersonationToken )
|
|
{
|
|
ExecUrlInfo.pUserInfo = &ExecUrlUserInfo;
|
|
|
|
ZeroMemory( &ExecUrlUserInfo, sizeof( ExecUrlUserInfo ) );
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->GetServerVariable( pecb->ConnID,
|
|
"UNICODE_REMOTE_USER",
|
|
buff.QueryPtr(),
|
|
&cbBuffer );
|
|
if ( !fRet )
|
|
{
|
|
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
if ( hImpersonationToken )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( hImpersonationToken ) );
|
|
hImpersonationToken = NULL;
|
|
}
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
DBG_ASSERT( cbBuffer > buff.QuerySize() );
|
|
|
|
fRet = buff.Resize( cbBuffer );
|
|
if ( !fRet )
|
|
{
|
|
if ( hImpersonationToken )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( hImpersonationToken ) );
|
|
hImpersonationToken = NULL;
|
|
}
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->GetServerVariable( pecb->ConnID,
|
|
"UNICODE_REMOTE_USER",
|
|
buff.QueryPtr(),
|
|
&cbBuffer );
|
|
if ( !fRet )
|
|
{
|
|
if ( hImpersonationToken )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( hImpersonationToken ) );
|
|
hImpersonationToken = NULL;
|
|
}
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
}
|
|
|
|
ExecUrlUserInfo.pszCustomUserName = (WCHAR*) buff.QueryPtr();
|
|
|
|
ExecUrlUserInfo.pszCustomAuthType = "URLAUTH";
|
|
|
|
ExecUrlUserInfo.hImpersonationToken = hImpersonationToken;
|
|
}
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_EXEC_UNICODE_URL,
|
|
&ExecUrlInfo,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( !fRet && hImpersonationToken )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( hImpersonationToken ) );
|
|
}
|
|
hImpersonationToken = NULL;
|
|
|
|
return fRet ? HSE_STATUS_PENDING : HSE_STATUS_ERROR;
|
|
}
|
|
else if ( !fFatalError )
|
|
{
|
|
//
|
|
// This just means access wasn't granted. Send back an error
|
|
//
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_IO_COMPLETION,
|
|
UrlAuthCompletion,
|
|
NULL,
|
|
NULL );
|
|
if ( !fRet )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_SEND_CUSTOM_ERROR,
|
|
&CustomErrorInfo,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( !fRet )
|
|
{
|
|
pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_SEND_RESPONSE_HEADER,
|
|
"500 Server Error",
|
|
NULL,
|
|
NULL );
|
|
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return HSE_STATUS_PENDING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fatal error. Just set the last error and bail.
|
|
//
|
|
|
|
SetLastError( WIN32_FROM_HRESULT( hr ) );
|
|
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
GetExtensionVersion(
|
|
HSE_VERSION_INFO * pver
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialization routine for ISAPI
|
|
|
|
Arguments:
|
|
|
|
pver - Version information
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, else FALSE
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Do ISAPI interface init crap
|
|
//
|
|
|
|
pver->dwExtensionVersion = MAKELONG( 0, 1 );
|
|
|
|
strcpy( pver->lpszExtensionDesc,
|
|
"URL Authorization ISAPI" );
|
|
|
|
//
|
|
// Create an admin manager cache
|
|
//
|
|
|
|
g_pAdminManagerCache = new ADMIN_MANAGER_CACHE;
|
|
if ( g_pAdminManagerCache == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize ADMIN_MANAGER globals
|
|
//
|
|
|
|
hr = ADMIN_MANAGER::Initialize();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
delete g_pAdminManagerCache;
|
|
g_pAdminManagerCache = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize AZ_APPLICATION globals
|
|
//
|
|
|
|
hr = AZ_APPLICATION::Initialize();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
ADMIN_MANAGER::Terminate();
|
|
delete g_pAdminManagerCache;
|
|
g_pAdminManagerCache = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
TerminateExtension(
|
|
DWORD
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleanup ISAPI extension
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, else FALSE
|
|
|
|
--*/
|
|
{
|
|
AZ_APPLICATION::Terminate();
|
|
|
|
ADMIN_MANAGER::Terminate();
|
|
|
|
delete g_pAdminManagerCache;
|
|
g_pAdminManagerCache = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DllMain(
|
|
HINSTANCE hDll,
|
|
DWORD dwReason,
|
|
LPVOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DLL Entry Routine
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, else FALSE
|
|
|
|
--*/
|
|
{
|
|
switch ( dwReason )
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
CREATE_DEBUG_PRINT_OBJECT( "urlauth" );
|
|
DisableThreadLibraryCalls( hDll );
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
DELETE_DEBUG_PRINT_OBJECT();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT
|
|
GetTokenForExecution(
|
|
EXTENSION_CONTROL_BLOCK *pecb,
|
|
HANDLE * phToken
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
From metadata, determine the impersonation token to return
|
|
|
|
Arguments:
|
|
|
|
pecb - current ecb for request
|
|
phToken - where to store the token on success
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fRet = FALSE;
|
|
METADATA_RECORD *pRecord = NULL;
|
|
STACK_BUFFER( buff, 512 );
|
|
DWORD cbBuffer;
|
|
DWORD dwValue= 0;
|
|
HANDLE hToken = NULL;
|
|
HANDLE hToken2 = NULL;
|
|
|
|
DBG_ASSERT(pecb);
|
|
DBG_ASSERT(phToken);
|
|
*phToken = NULL;
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb,
|
|
HSE_REQ_GET_METADATA_PROPERTY,
|
|
buff.QueryPtr(),
|
|
&cbBuffer,
|
|
(LPDWORD) MD_URL_AUTHORIZATION_IMPERSONATION_LEVEL );
|
|
if ( !fRet &&
|
|
GetLastError() != ERROR_INVALID_INDEX )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
else if ( fRet )
|
|
{
|
|
//
|
|
// Check the property now. If invalid type then we're done
|
|
//
|
|
|
|
pRecord = (METADATA_RECORD*) buff.QueryPtr();
|
|
if ( pRecord->dwMDDataType != DWORD_METADATA )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
goto exit;
|
|
}
|
|
|
|
// valid type of data - validity of data value done in switch below
|
|
dwValue = *(DWORD*)pRecord->pbMDData;
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( !fRet && GetLastError() == ERROR_INVALID_INDEX );
|
|
|
|
// no metadata present, therefore use the default of zero
|
|
dwValue = 0;
|
|
}
|
|
|
|
switch(dwValue)
|
|
{
|
|
case 0:
|
|
// use the current authenticated user
|
|
fRet = OpenThreadToken( GetCurrentThread(),
|
|
TOKEN_ALL_ACCESS,
|
|
TRUE,
|
|
&hToken );
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
// use the process token to impersonate
|
|
|
|
// first get the current impersonation token
|
|
fRet = OpenThreadToken( GetCurrentThread(),
|
|
TOKEN_IMPERSONATE,
|
|
TRUE,
|
|
&hToken2 );
|
|
if ( fRet )
|
|
{
|
|
DBG_ASSERT( hToken2 != NULL );
|
|
RevertToSelf();
|
|
}
|
|
|
|
// get the current process token - it's a primary token
|
|
fRet = OpenProcessToken( GetCurrentProcess(),
|
|
TOKEN_ALL_ACCESS,
|
|
&hToken );
|
|
|
|
|
|
if ( hToken2 != NULL )
|
|
{
|
|
if ( !SetThreadToken( NULL, hToken2 ) )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
}
|
|
|
|
DBG_REQUIRE( CloseHandle( hToken2 ) );
|
|
hToken2 = NULL;
|
|
}
|
|
|
|
// checking the return value from open the process token here
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
|
|
// create an impersonation token from the primary process token
|
|
fRet = DuplicateHandle ( GetCurrentProcess(),
|
|
hToken,
|
|
GetCurrentProcess(),
|
|
&hToken2,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS );
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
|
|
DBG_REQUIRE( CloseHandle( hToken ) );
|
|
|
|
hToken = hToken2;
|
|
hToken2 = NULL;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
// get the anonymous token for impersonation
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->GetServerVariable( pecb->ConnID,
|
|
"UNICODE_SCRIPT_NAME",
|
|
(CHAR*) buff.QueryPtr(),
|
|
&cbBuffer );
|
|
if ( !fRet )
|
|
{
|
|
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
|
|
DBG_ASSERT( cbBuffer > buff.QuerySize() );
|
|
|
|
fRet = buff.Resize( cbBuffer );
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
|
|
cbBuffer = buff.QuerySize();
|
|
|
|
fRet = pecb->GetServerVariable( pecb->ConnID,
|
|
"UNICODE_SCRIPT_NAME",
|
|
(CHAR*) buff.QueryPtr(),
|
|
&cbBuffer );
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
|
|
fRet = pecb->ServerSupportFunction( pecb->ConnID,
|
|
HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN,
|
|
buff.QueryPtr(),
|
|
(LPDWORD)&hToken,
|
|
NULL );
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto exit;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
// If not 0, 1, or 2 then not valid metadata
|
|
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
goto exit;
|
|
|
|
break;
|
|
}
|
|
|
|
*phToken = hToken;
|
|
hToken = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
|
|
if ( hToken )
|
|
{
|
|
DBG_REQUIRE( CloseHandle( hToken ) );
|
|
hToken = NULL;
|
|
}
|
|
|
|
return hr;
|
|
};
|
|
|