Leaked source code of windows server 2003
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

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