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.
817 lines
25 KiB
817 lines
25 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
iiscertmap.cxx
|
|
|
|
Abstract:
|
|
IIS Certificate mapping
|
|
|
|
|
|
Author:
|
|
Bilal Alam (BAlam) 19-Apr-2000
|
|
|
|
Environment:
|
|
Win32 - User Mode
|
|
|
|
Project:
|
|
Stream Filter Worker Process
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#include <mbstring.h>
|
|
|
|
|
|
|
|
IIS_CERTIFICATE_MAPPING::IIS_CERTIFICATE_MAPPING( VOID )
|
|
: _pCert11Mapper( NULL ),
|
|
_pCertWildcardMapper( NULL ),
|
|
_cRefs( 1 )
|
|
{
|
|
}
|
|
|
|
IIS_CERTIFICATE_MAPPING::~IIS_CERTIFICATE_MAPPING( VOID )
|
|
{
|
|
if ( _pCert11Mapper != NULL )
|
|
{
|
|
delete _pCert11Mapper;
|
|
_pCert11Mapper = NULL;
|
|
}
|
|
|
|
if ( _pCertWildcardMapper != NULL )
|
|
{
|
|
delete _pCertWildcardMapper;
|
|
_pCertWildcardMapper = NULL;
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
IIS_CERTIFICATE_MAPPING::Read11Mappings(
|
|
DWORD dwSiteId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read 1-1 mappings from metabase
|
|
|
|
Arguments:
|
|
|
|
dwSiteId - Site ID
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
MB mb( g_pW3Server->QueryMDObject() );
|
|
WCHAR achMBPath[ 256 ];
|
|
HRESULT hr = NO_ERROR;
|
|
// besides terminating '\0' one extra char is needed for leading slash
|
|
WCHAR achMappingName[ ADMINDATA_MAX_NAME_LEN + 1 + 1 ];
|
|
BOOL fRet;
|
|
DWORD dwIndex;
|
|
STACK_BUFFER( buff, 1024 );
|
|
DWORD cbRequired;
|
|
STACK_STRU( strTemp, 64 );
|
|
STACK_STRU( strUserName, 64 );
|
|
STACK_STRU( strPassword, 64 );
|
|
DWORD dwEnabled;
|
|
CIisMapping * pCertMapping;
|
|
|
|
//
|
|
// Setup the metabase path to get at 1-1 mappings
|
|
//
|
|
|
|
_snwprintf( achMBPath,
|
|
sizeof( achMBPath ) / sizeof( WCHAR ) - 1,
|
|
L"/LM/W3SVC/%d/Cert11/Mappings",
|
|
dwSiteId );
|
|
achMBPath[ sizeof( achMBPath ) / sizeof( WCHAR ) - 1 ] = '\0';
|
|
|
|
//
|
|
// Open the metabase and read 1-1 mapping properties
|
|
//
|
|
|
|
fRet = mb.Open( achMBPath,
|
|
METADATA_PERMISSION_READ );
|
|
if ( fRet )
|
|
{
|
|
dwIndex = 0;
|
|
achMappingName[ 0 ] = L'/';
|
|
|
|
for ( ; ; ) // loop un
|
|
{
|
|
dwEnabled = FALSE;
|
|
|
|
//
|
|
// We will need to prepend the object name with '/'. Hence
|
|
// goofyness of sending an offseted pointed to name
|
|
//
|
|
|
|
fRet = mb.EnumObjects( L"",
|
|
achMappingName + 1,
|
|
dwIndex );
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get certificate blob
|
|
//
|
|
|
|
cbRequired = buff.QuerySize();
|
|
|
|
fRet = mb.GetData( achMappingName,
|
|
MD_MAPCERT,
|
|
IIS_MD_UT_SERVER,
|
|
BINARY_METADATA,
|
|
buff.QueryPtr(),
|
|
&cbRequired,
|
|
METADATA_NO_ATTRIBUTES );
|
|
if ( !fRet )
|
|
{
|
|
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
DBG_ASSERT( cbRequired > buff.QuerySize() );
|
|
|
|
if ( !buff.Resize( cbRequired ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
break;
|
|
}
|
|
|
|
fRet = mb.GetData( achMappingName,
|
|
MD_MAPCERT,
|
|
IIS_MD_UT_SERVER,
|
|
BINARY_METADATA,
|
|
buff.QueryPtr(),
|
|
&cbRequired,
|
|
METADATA_NO_ATTRIBUTES );
|
|
if ( !fRet )
|
|
{
|
|
DBG_ASSERT( GetLastError() != ERROR_INSUFFICIENT_BUFFER );
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
if ( hr == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
// if cert blob is not present we skip this entry
|
|
goto NextEntry;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
if ( hr == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
// if cert blob is not present we skip this entry
|
|
goto NextEntry;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get NT account name
|
|
//
|
|
|
|
if ( !mb.GetStr( achMappingName,
|
|
MD_MAPNTACCT,
|
|
IIS_MD_UT_SERVER,
|
|
&strUserName ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
if ( hr == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
// if account name is not present we skip this entry
|
|
goto NextEntry;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get NT password
|
|
//
|
|
|
|
if ( !mb.GetStr( achMappingName,
|
|
MD_MAPNTPWD,
|
|
IIS_MD_UT_SERVER,
|
|
&strPassword ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
if ( hr == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
// we assume default password - empty;
|
|
strPassword.Reset();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Is this mapping enabled?
|
|
//
|
|
|
|
if ( !mb.GetDword( achMappingName,
|
|
MD_MAPENABLED,
|
|
IIS_MD_UT_SERVER,
|
|
&dwEnabled ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
if ( hr == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
// we assume default 0 (FALSE);
|
|
dwEnabled = 0;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this mapping is enabled, add it to 1-1 mapper
|
|
//
|
|
|
|
if ( dwEnabled )
|
|
{
|
|
if ( _pCert11Mapper == NULL )
|
|
{
|
|
_pCert11Mapper = new CIisCert11Mapper();
|
|
if ( _pCert11Mapper == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Reset() will configure default hierarchies
|
|
// If hierarchies are not configured then comparison (CIisMapping::Cmp() function
|
|
// implemented in iismap.cxx) will fail
|
|
// (and mapper will always incorrectly map to first available 1to1 mapping)
|
|
//
|
|
|
|
if(!_pCert11Mapper->Reset())
|
|
{
|
|
delete _pCert11Mapper;
|
|
_pCert11Mapper = NULL;
|
|
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
break;
|
|
}
|
|
}
|
|
|
|
DBG_ASSERT( _pCert11Mapper != NULL );
|
|
|
|
pCertMapping = _pCert11Mapper->CreateNewMapping();
|
|
if ( pCertMapping == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
break;
|
|
}
|
|
|
|
if ( !pCertMapping->MappingSetField( IISMDB_INDEX_CERT11_CERT,
|
|
(PBYTE) buff.QueryPtr(),
|
|
cbRequired,
|
|
FALSE ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
break;
|
|
}
|
|
|
|
if ( !pCertMapping->MappingSetField( IISMDB_INDEX_CERT11_NT_ACCT,
|
|
(PBYTE) strUserName.QueryStr(),
|
|
strUserName.QueryCB() + sizeof (WCHAR),
|
|
FALSE ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
delete pCertMapping;
|
|
pCertMapping = NULL;
|
|
break;
|
|
}
|
|
|
|
if ( !pCertMapping->MappingSetField( IISMDB_INDEX_CERT11_NT_PWD,
|
|
(PBYTE) strPassword.QueryStr(),
|
|
strPassword.QueryCB() + sizeof (WCHAR),
|
|
FALSE ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
delete pCertMapping;
|
|
pCertMapping = NULL;
|
|
break;
|
|
}
|
|
|
|
if ( !((CIisAcctMapper*)_pCert11Mapper)->Add( pCertMapping, FALSE ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
delete pCertMapping;
|
|
pCertMapping = NULL;
|
|
break;
|
|
}
|
|
}
|
|
NextEntry:
|
|
dwIndex++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
IIS_CERTIFICATE_MAPPING::ReadWildcardMappings(
|
|
DWORD dwSiteId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read wildcard mappings from metabase
|
|
|
|
Arguments:
|
|
|
|
dwSiteId - Site ID (duh)
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
MB mb( g_pW3Server->QueryMDObject() );
|
|
WCHAR achMBPath[ 256 ];
|
|
BOOL fRet;
|
|
BYTE abBuffer[ 1024 ];
|
|
BUFFER buff( abBuffer, sizeof( abBuffer ) );
|
|
DWORD cbRequired;
|
|
PUCHAR pSerializedMapping;
|
|
|
|
//
|
|
// Setup the metabase path to get at wildcard mappings
|
|
//
|
|
|
|
_snwprintf( achMBPath,
|
|
sizeof( achMBPath ) / sizeof( WCHAR ) - 1,
|
|
L"/LM/W3SVC/%d/",
|
|
dwSiteId );
|
|
achMBPath[ sizeof( achMBPath ) / sizeof( WCHAR ) - 1 ] = '\0';
|
|
|
|
//
|
|
// Open the metabase and read wildcard mappings
|
|
//
|
|
|
|
fRet = mb.Open( achMBPath,
|
|
METADATA_PERMISSION_READ );
|
|
if ( fRet )
|
|
{
|
|
cbRequired = buff.QuerySize();
|
|
|
|
fRet = mb.GetData( L"",
|
|
MD_SERIAL_CERTW,
|
|
IIS_MD_UT_SERVER,
|
|
BINARY_METADATA,
|
|
buff.QueryPtr(),
|
|
&cbRequired,
|
|
METADATA_NO_ATTRIBUTES );
|
|
if ( !fRet )
|
|
{
|
|
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
DBG_ASSERT( cbRequired > buff.QuerySize() );
|
|
|
|
if ( !buff.Resize( cbRequired ) )
|
|
{
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
|
|
fRet = mb.GetData( L"",
|
|
MD_SERIAL_CERTW,
|
|
IIS_MD_UT_SERVER,
|
|
BINARY_METADATA,
|
|
buff.QueryPtr(),
|
|
&cbRequired,
|
|
METADATA_NO_ATTRIBUTES );
|
|
if ( !fRet )
|
|
{
|
|
DBG_ASSERT( GetLastError() != ERROR_INSUFFICIENT_BUFFER );
|
|
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Thanx to the man, I can just unserialize. XBF rocks ;-)
|
|
//
|
|
|
|
DBG_ASSERT( _pCertWildcardMapper == NULL );
|
|
|
|
_pCertWildcardMapper = new CIisRuleMapper();
|
|
if ( _pCertWildcardMapper == NULL )
|
|
{
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
|
|
if( !_pCertWildcardMapper->IsValid() )
|
|
{
|
|
//
|
|
// creation of _pCertWildcardMapper failed
|
|
// assume out of memory
|
|
//
|
|
return HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
|
|
}
|
|
|
|
pSerializedMapping = (PUCHAR) buff.QueryPtr();
|
|
|
|
// Unserialize will change the value of pSerializedMapping
|
|
// It will point to the end of the unserialized data
|
|
// We don't need that modified pointer. But remember not to use
|
|
// pSerializedMapping any more after Unserialize call
|
|
//
|
|
fRet = _pCertWildcardMapper->Unserialize( &pSerializedMapping,
|
|
&cbRequired );
|
|
if ( !fRet )
|
|
{
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
//static
|
|
HRESULT
|
|
IIS_CERTIFICATE_MAPPING::GetCertificateMapping(
|
|
DWORD dwSiteId,
|
|
IIS_CERTIFICATE_MAPPING ** ppCertificateMapping
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read appropriate metabase configuration to get configured IIS
|
|
certificate mapping
|
|
|
|
Arguments:
|
|
|
|
dwSiteId - Site ID (duh)
|
|
ppCertificateMapping - Filled with certificate mapping descriptor on
|
|
success
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
IIS_CERTIFICATE_MAPPING * pCertMapping = NULL;
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
if ( ppCertificateMapping == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
*ppCertificateMapping = NULL;
|
|
|
|
//
|
|
// Create a certificate mapping descriptor
|
|
//
|
|
|
|
pCertMapping = new IIS_CERTIFICATE_MAPPING();
|
|
if ( pCertMapping == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto Finished;
|
|
}
|
|
|
|
//
|
|
// Read 1-1 mappings
|
|
//
|
|
|
|
hr = pCertMapping->Read11Mappings( dwSiteId );
|
|
if ( FAILED( hr ) &&
|
|
hr != HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Error reading 1to1 Certificate Mappings. hr = %x\n",
|
|
hr ));
|
|
|
|
goto Finished;
|
|
}
|
|
hr = NO_ERROR;
|
|
|
|
//
|
|
// Read wildcards
|
|
//
|
|
|
|
hr = pCertMapping->ReadWildcardMappings( dwSiteId );
|
|
if ( FAILED( hr ) &&
|
|
hr != HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Error reading Wildcard Certificate Mappings. hr = %x\n",
|
|
hr ));
|
|
|
|
goto Finished;
|
|
}
|
|
hr = NO_ERROR;
|
|
|
|
Finished:
|
|
if ( FAILED( hr ) )
|
|
{
|
|
if ( pCertMapping != NULL )
|
|
{
|
|
delete pCertMapping;
|
|
pCertMapping = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( pCertMapping != NULL );
|
|
*ppCertificateMapping = pCertMapping;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
IIS_CERTIFICATE_MAPPING::DoMapCredential(
|
|
W3_MAIN_CONTEXT * pMainContext,
|
|
PBYTE pClientCertBlob,
|
|
DWORD cbClientCertBlob,
|
|
TOKEN_CACHE_ENTRY ** ppCachedToken,
|
|
BOOL * pfClientCertDeniedByMapper
|
|
)
|
|
{
|
|
CIisMapping * pQuery;
|
|
CIisMapping * pResult;
|
|
WCHAR wszUserName[ UNLEN + IIS_DNLEN + 1 + 1 ];
|
|
LPWSTR pwszUserName;
|
|
DWORD cbUserName;
|
|
WCHAR wszPassword[ PWLEN + 1 ];
|
|
LPWSTR pwszPassword;
|
|
DWORD cbPassword;
|
|
CHAR * pszDomain;
|
|
BOOL fMatch = FALSE;
|
|
DWORD dwLogonError = NO_ERROR;
|
|
HRESULT hr = S_OK;
|
|
|
|
BOOL fPossibleUPNLogon = FALSE;
|
|
//
|
|
// add 1 to strUserDomainW for separator "\"
|
|
//
|
|
STACK_STRU( strUserDomainW, UNLEN + IIS_DNLEN + 1 + 1 );
|
|
STACK_STRU( strUserNameW, UNLEN + IIS_DNLEN + 1 + 1 );
|
|
STACK_STRU( strDomainNameW, IIS_DNLEN + 1 );
|
|
STACK_STRU( strPasswordW, PWLEN + 1 );
|
|
DBG_ASSERT( pClientCertBlob != NULL );
|
|
DBG_ASSERT( cbClientCertBlob != 0 );
|
|
DBG_ASSERT( ppCachedToken != NULL );
|
|
DBG_ASSERT( pfClientCertDeniedByMapper != NULL );
|
|
|
|
|
|
//
|
|
// First try the 1-1 mapper
|
|
//
|
|
|
|
|
|
if ( _pCert11Mapper != NULL )
|
|
{
|
|
//
|
|
// Build a query mapping to check
|
|
//
|
|
|
|
pQuery = _pCert11Mapper->CreateNewMapping( pClientCertBlob,
|
|
cbClientCertBlob );
|
|
if ( pQuery == NULL )
|
|
{
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
|
|
//
|
|
// no need to lock cert mapper because this is read only copy
|
|
// used for mapping execution in worker process
|
|
|
|
|
|
if ( _pCert11Mapper->FindMatch( pQuery,
|
|
&pResult ) )
|
|
{
|
|
//
|
|
// Awesome. We found a match. Do the deed if the rule is
|
|
// enabled
|
|
//
|
|
|
|
if ( pResult->MappingGetField( IISMDB_INDEX_CERT11_NT_ACCT,
|
|
(PBYTE *)&pwszUserName,
|
|
&cbUserName,
|
|
FALSE ) &&
|
|
pResult->MappingGetField( IISMDB_INDEX_CERT11_NT_PWD,
|
|
(PBYTE *)&pwszPassword,
|
|
&cbPassword,
|
|
FALSE ) )
|
|
{
|
|
//
|
|
// No need to check for Enabled (IISMDB_INDEX_CERT11_ENABLED)
|
|
// since Read11Mappings() will build mapping table consisting only
|
|
// of enabled mappings
|
|
//
|
|
|
|
//
|
|
// Make copy of user and password
|
|
//
|
|
hr = strUserDomainW.Copy( pwszUserName );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = strPasswordW.Copy( pwszPassword );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
fMatch = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
delete pQuery;
|
|
pQuery = NULL;
|
|
}
|
|
|
|
//
|
|
// Try the wildcard mapper if we still haven't found a match
|
|
//
|
|
|
|
if ( !fMatch &&
|
|
_pCertWildcardMapper != NULL )
|
|
{
|
|
|
|
PCCERT_CONTEXT pClientCert = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
pClientCertBlob,
|
|
cbClientCertBlob );
|
|
if ( pClientCert == NULL )
|
|
{
|
|
DBG_ASSERT( pClientCert != NULL );
|
|
}
|
|
// Wildcard mapper assumes that
|
|
// achUserName buffer is greater than UNLEN+IIS_DNLEN+1 and
|
|
// achPassword buffer is greater then PWLEN
|
|
//
|
|
else if ( !_pCertWildcardMapper->Match(
|
|
(PCERT_CONTEXT) pClientCert,
|
|
NULL, // legacy value
|
|
wszUserName,
|
|
wszPassword ) )
|
|
{
|
|
//
|
|
// If the mapping rule is denied then return
|
|
// a NULL pointer through ppCachedToken with SEC_E_OK.
|
|
// That indicated to caller that mapping was denied
|
|
//
|
|
|
|
if ( GetLastError() == ERROR_ACCESS_DENIED )
|
|
{
|
|
*ppCachedToken = NULL;
|
|
*pfClientCertDeniedByMapper = TRUE;
|
|
|
|
if ( pClientCert != NULL )
|
|
{
|
|
CertFreeCertificateContext( pClientCert );
|
|
pClientCert = NULL;
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fMatch = TRUE;
|
|
//
|
|
// Copy user and password (user name may be fully qualified with domain name in it)
|
|
//
|
|
hr = strUserDomainW.Copy( wszUserName );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = strPasswordW.Copy( wszPassword );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
}
|
|
|
|
if ( pClientCert != NULL )
|
|
{
|
|
CertFreeCertificateContext( pClientCert );
|
|
pClientCert = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we still haven't found a match, then return error
|
|
//
|
|
|
|
if ( fMatch )
|
|
{
|
|
|
|
//
|
|
// Split up the user name into domain/user if needed
|
|
// Note: DefaultLogonDomain is not used for cert mapping at all
|
|
// This is to keep behaviour equivalent with former versions of IIS
|
|
//
|
|
|
|
hr = W3_STATE_AUTHENTICATION::SplitUserDomain( strUserDomainW,
|
|
&strUserNameW,
|
|
&strDomainNameW,
|
|
NULL, // no default domain
|
|
&fPossibleUPNLogon );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// We should have valid credentials to call LogonUser()
|
|
//
|
|
DBG_ASSERT( g_pW3Server->QueryTokenCache() != NULL );
|
|
|
|
hr = g_pW3Server->QueryTokenCache()->GetCachedToken(
|
|
strUserNameW.QueryStr(),
|
|
strDomainNameW.QueryStr(),
|
|
strPasswordW.QueryStr(),
|
|
LOGON32_LOGON_NETWORK_CLEARTEXT,
|
|
FALSE, //don't use subauth
|
|
fPossibleUPNLogon,
|
|
pMainContext->QueryRequest()->
|
|
QueryRemoteSockAddress(),
|
|
ppCachedToken,
|
|
&dwLogonError );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
//
|
|
// If *ppCachedToken is NULL, then logon failed
|
|
//
|
|
|
|
if ( *ppCachedToken == NULL )
|
|
{
|
|
//
|
|
// Note: With IIS5 we used to log logon failure to event log
|
|
// however it doesn't seem to be necessary because if logon/logoff auditing is enabled
|
|
// then security log would have relevant information about the logon failure
|
|
//
|
|
DBG_ASSERT( dwLogonError != ERROR_SUCCESS );
|
|
return SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
|
|
DBG_ASSERT( (*ppCachedToken)->CheckSignature() );
|
|
*pfClientCertDeniedByMapper = FALSE;
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
return SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
|
|
|
|
|
|
|