windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/ulw3/certmapprovider.cxx
2020-09-26 16:20:57 +08:00

282 lines
5.6 KiB
C++

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name :
certmapprovider.cxx
Abstract:
Active Directory Certificate Mapper provider
Author:
Bilal Alam (balam) 10-Jan-2000
Environment:
Win32 - User Mode
Project:
ULW3.DLL
--*/
#include "precomp.hxx"
#include "certmapprovider.hxx"
HRESULT
CERTMAP_AUTH_PROVIDER::DoesApply(
W3_MAIN_CONTEXT * pMainContext,
BOOL * pfApplies
)
/*++
Routine Description:
Does certificate map authentication apply?
Arguments:
pMainContext - Main context
pfApplies - Set to TRUE if cert map auth applies
Return Value:
HRESULT
--*/
{
CERTIFICATE_CONTEXT * pCertificateContext;
URL_CONTEXT * pUrlContext = NULL;
W3_METADATA * pMetaData = NULL;
BOOL fApplies = FALSE;
if ( pMainContext == NULL ||
pfApplies == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// If cert mapping is not allowed for this vroot, then ignore client
// cert token and let other authentication mechanisms do their thing
//
pUrlContext = pMainContext->QueryUrlContext();
DBG_ASSERT( pUrlContext != NULL );
pMetaData = pUrlContext->QueryMetaData();
DBG_ASSERT( pMetaData != NULL );
DBG_ASSERT( pMainContext->QuerySite() );
if ( !pMainContext->QuerySite()->QueryUseDSMapper() )
{
fApplies = FALSE;
}
else if ( pMetaData->QuerySslAccessPerms() & VROOT_MASK_MAP_CERT )
{
pCertificateContext = pMainContext->QueryCertificateContext();
if ( pCertificateContext != NULL )
{
if ( pCertificateContext->QueryImpersonationToken() != NULL )
{
fApplies = TRUE;
}
}
}
*pfApplies = fApplies;
return NO_ERROR;
}
HRESULT
CERTMAP_AUTH_PROVIDER::DoAuthenticate(
W3_MAIN_CONTEXT * pMainContext
)
/*++
Routine Description:
Create a user context representing a cert mapped token
Arguments:
pMainContext - Main context
Return Value:
HRESULT
--*/
{
CERTMAP_USER_CONTEXT * pUserContext = NULL;
CERTIFICATE_CONTEXT * pCertificateContext = NULL;
HANDLE hImpersonation;
BOOL fDelegatable = FALSE;
HRESULT hr = NO_ERROR;
if ( pMainContext == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
pCertificateContext = pMainContext->QueryCertificateContext();
DBG_ASSERT( pCertificateContext != NULL );
hImpersonation = pCertificateContext->QueryImpersonationToken();
DBG_ASSERT( hImpersonation != NULL );
//
// Create the user context for this request
//
pUserContext = new CERTMAP_USER_CONTEXT( this );
if ( pUserContext == NULL )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
//
// Is this a delegatable token? Put another way is this token mapped
// using an IIS cert mapper (IIS cert mapper creates delegatable token,
// the DS mapper does not)
//
fDelegatable = FALSE;
hr = pUserContext->Create( hImpersonation, fDelegatable );
if ( FAILED( hr ) )
{
pUserContext->DereferenceUserContext();
pUserContext = NULL;
return hr;
}
pMainContext->SetUserContext( pUserContext );
return NO_ERROR;
}
HRESULT
CERTMAP_AUTH_PROVIDER::OnAccessDenied(
W3_MAIN_CONTEXT * pMainContext
)
/*++
Routine Description:
NOP since we have nothing to do on access denied
Arguments:
pMainContext - Main context
Return Value:
HRESULT
--*/
{
//
// No headers to add
//
return NO_ERROR;
}
HRESULT
CERTMAP_USER_CONTEXT::Create(
HANDLE hImpersonation,
BOOL fDelegatable
)
/*++
Routine Description:
Create a certificate mapped user context
Arguments:
hImpersonation - Impersonation token
fDelegatable - Is this token delegatable?
Return Value:
HRESULT
--*/
{
DWORD cchUserName = sizeof( _achUserName ) / sizeof( WCHAR );
if ( hImpersonation == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// First the easy stuff
//
_fDelegatable = fDelegatable;
_hImpersonationToken = hImpersonation;
//
// Now get the user name
//
if ( !SetThreadToken( NULL, _hImpersonationToken ) )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
if ( !GetUserNameEx( NameSamCompatible,
_achUserName,
&cchUserName ) )
{
RevertToSelf();
return HRESULT_FROM_WIN32( GetLastError() );
}
RevertToSelf();
return NO_ERROR;
}
HANDLE
CERTMAP_USER_CONTEXT::QueryPrimaryToken(
VOID
)
/*++
Routine Description:
Get a primary token
Arguments:
None
Return Value:
HANDLE
--*/
{
if ( _hPrimaryToken == NULL )
{
if ( DuplicateTokenEx( _hImpersonationToken,
TOKEN_ALL_ACCESS,
NULL,
SecurityImpersonation,
TokenPrimary,
&_hPrimaryToken ) )
{
DBG_ASSERT( _hPrimaryToken != NULL );
}
}
return _hPrimaryToken;
}