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.
315 lines
7.1 KiB
315 lines
7.1 KiB
/*++
|
|
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 Active Directory certificate map authentication apply?
|
|
MD_ACCESS_MAP_CERT covers 2 kinds of mappings (DS mapper and IIS mapper)
|
|
CERT_AUTH_PROVIDER represents only the DS mapper
|
|
|
|
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 );
|
|
|
|
//
|
|
// Are certmappings allowed?
|
|
//
|
|
if ( pMetaData->QuerySslAccessPerms() & MD_ACCESS_MAP_CERT )
|
|
{
|
|
DBG_ASSERT( pMainContext->QuerySite() );
|
|
//
|
|
// Is Active Directory mapping allowed
|
|
//
|
|
if ( pMainContext->QuerySite()->QueryUseDSMapper() )
|
|
{
|
|
pCertificateContext = pMainContext->QueryCertificateContext();
|
|
//
|
|
// Did schannel successfully mapped client certificate to token?
|
|
//
|
|
if ( pCertificateContext != NULL )
|
|
{
|
|
if ( pCertificateContext->QueryImpersonationToken() != NULL )
|
|
{
|
|
fApplies = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*pfApplies = fApplies;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
HRESULT
|
|
CERTMAP_AUTH_PROVIDER::DoAuthenticate(
|
|
W3_MAIN_CONTEXT * pMainContext,
|
|
BOOL * // unused
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a user context representing a cert mapped token
|
|
|
|
Arguments:
|
|
|
|
pMainContext - Main context
|
|
pfFilterFinished - Set to TRUE if filter wants out
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CERTMAP_USER_CONTEXT * pUserContext = NULL;
|
|
CERTIFICATE_CONTEXT * pCertificateContext = NULL;
|
|
HANDLE hImpersonation;
|
|
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)
|
|
//
|
|
|
|
hr = pUserContext->Create( hImpersonation );
|
|
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 (not used)
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// No headers to add
|
|
//
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
HRESULT
|
|
CERTMAP_USER_CONTEXT::Create(
|
|
HANDLE hImpersonation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a certificate mapped user context
|
|
|
|
Arguments:
|
|
|
|
hImpersonation - Impersonation token
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
if ( hImpersonation == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
//
|
|
// First the easy stuff
|
|
//
|
|
|
|
if ( !DuplicateTokenEx( hImpersonation,
|
|
TOKEN_ALL_ACCESS,
|
|
NULL,
|
|
SecurityImpersonation,
|
|
TokenImpersonation,
|
|
&_hImpersonationToken ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"DuplicateTokenEx failed, hr = 0x%x\n",
|
|
hr ));
|
|
return hr;
|
|
|
|
}
|
|
|
|
DBG_ASSERT( _hImpersonationToken != NULL );
|
|
|
|
//
|
|
// Disable the backup privilege for the token
|
|
//
|
|
|
|
DisableTokenBackupPrivilege( _hImpersonationToken );
|
|
|
|
//
|
|
// Now get the user name
|
|
//
|
|
|
|
if ( !SetThreadToken( NULL, _hImpersonationToken ) )
|
|
{
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
|
|
// cchUserName includes buffer size in characters including terminating 0
|
|
DWORD cchUserName = sizeof( _achUserName ) / sizeof( WCHAR );
|
|
|
|
if ( !GetUserNameEx( NameSamCompatible,
|
|
_achUserName,
|
|
&cchUserName ) )
|
|
{
|
|
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
RevertToSelf();
|
|
return hr;
|
|
}
|
|
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( _hImpersonationToken != NULL );
|
|
}
|
|
else
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"DuplicateTokenEx failed, hr = 0x%x\n",
|
|
HRESULT_FROM_WIN32( GetLastError() ) ));
|
|
}
|
|
}
|
|
|
|
return _hPrimaryToken;
|
|
}
|