936 lines
19 KiB
C++
936 lines
19 KiB
C++
/*++
|
|
|
|
|
|
|
|
|
|
|
|
opyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
iiscrmap.cxx
|
|
|
|
Abstract:
|
|
|
|
Certificate to NT account mapper
|
|
|
|
Author:
|
|
|
|
Philippe Choquier (phillich) 17-may-1996
|
|
Alex Mallet (amallet) 13-Feb-1998
|
|
|
|
--*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
# include <nt.h>
|
|
# include <ntrtl.h>
|
|
# include <nturtl.h>
|
|
# include <windows.h>
|
|
|
|
#include <stdio.h>
|
|
#if 1 // DBCS
|
|
#include <mbstring.h>
|
|
#endif
|
|
|
|
#include <schnlsp.h>
|
|
|
|
#include <wincrypt.h>
|
|
#include <issperr.h>
|
|
#include <certmap.h>
|
|
#include <cmnull.hxx>
|
|
#include <lmcons.h>
|
|
|
|
#ifdef __cplusplus
|
|
};
|
|
#endif
|
|
|
|
#include <iis64.h>
|
|
#include <iiscrmap.hxx>
|
|
|
|
extern "C" {
|
|
|
|
#include <tchar.h>
|
|
|
|
#include <iisfiltp.h>
|
|
|
|
} // extern "C"
|
|
|
|
#include <tslogon.hxx>
|
|
|
|
#include <iismap.hxx>
|
|
#include <iiscmr.hxx>
|
|
#include "mapmsg.h"
|
|
|
|
#include <dbgutil.h>
|
|
#include <buffer.hxx>
|
|
#include <ole2.h>
|
|
#include <imd.h>
|
|
#include <mb.hxx>
|
|
#include <iiscnfgp.h>
|
|
#include <reftrace.h>
|
|
#include <iiscert.hxx>
|
|
#include <iisctl.hxx>
|
|
#include <capiutil.hxx>
|
|
#include <sslinfo.hxx>
|
|
|
|
#define CALLC WINAPI
|
|
|
|
CRITICAL_SECTION g_csInitCritSec;
|
|
DWORD g_dwNumLocators;
|
|
extern MAPPER_VTABLE g_MapperVtable;
|
|
HANDLE g_hModule;
|
|
|
|
//
|
|
//
|
|
//
|
|
DECLARE_DEBUG_PRINTS_OBJECT();
|
|
#include <initguid.h>
|
|
DEFINE_GUID(IisCrMapGuid,
|
|
0x784d8913, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
|
|
|
|
|
|
extern "C"
|
|
BOOL
|
|
WINAPI
|
|
DLLEntry(
|
|
HINSTANCE hDll,
|
|
DWORD dwReason,
|
|
LPVOID lpvReserved
|
|
)
|
|
{
|
|
switch ( dwReason )
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
#ifdef _NO_TRACING_
|
|
CREATE_DEBUG_PRINT_OBJECT( "IISCRMAP" );
|
|
#else
|
|
CREATE_DEBUG_PRINT_OBJECT( "IISCRMAP" , IisCrMapGuid);
|
|
#endif
|
|
INITIALIZE_CRITICAL_SECTION( &g_csInitCritSec );
|
|
g_dwNumLocators = 0;
|
|
g_hModule = hDll;
|
|
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
if ( g_dwNumLocators )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Still have %d locators left !\n",
|
|
g_dwNumLocators));
|
|
}
|
|
|
|
DELETE_DEBUG_PRINT_OBJECT();
|
|
DeleteCriticalSection( &g_csInitCritSec );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
DWORD CALLC
|
|
CreateInstance(
|
|
OUT HMAPPER** pHMapper
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to initialize the mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Ptr to mapper vtable if success, otherwise NULL
|
|
|
|
--*/
|
|
{
|
|
IisMapper *pMap;
|
|
|
|
if ( !(pMap = (IisMapper*)LocalAlloc( LMEM_FIXED, sizeof(IisMapper) )) )
|
|
{
|
|
return SEC_E_INSUFFICIENT_MEMORY;
|
|
}
|
|
|
|
memcpy ( &pMap->mvtEntryPoints, &g_MapperVtable, sizeof(MAPPER_VTABLE) );
|
|
|
|
pMap->hMapper.m_vtable = &pMap->mvtEntryPoints;
|
|
pMap->hMapper.m_dwMapperVersion = MAPPER_INTERFACE_VER;
|
|
pMap->hMapper.m_Reserved1 = NULL;
|
|
pMap->lRefCount = 1;
|
|
pMap->fIsIisCompliant = TRUE;
|
|
pMap->hInst = (HINSTANCE)g_hModule;
|
|
pMap->pCert11Mapper = NULL;
|
|
pMap->pCertWMapper = NULL;
|
|
pMap->pvInfo = NULL;
|
|
|
|
pMap->dwSignature = IIS_MAPPER_SIGNATURE;
|
|
|
|
*pHMapper = (HMAPPER*)pMap;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
LONG CALLC
|
|
IisReferenceMapper(
|
|
OUT HMAPPER* pMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Increment reference count to mapper
|
|
|
|
Arguments:
|
|
|
|
pMap - ptr to mapper struct
|
|
|
|
Returns:
|
|
|
|
Ref count
|
|
|
|
--*/
|
|
{
|
|
LONG l;
|
|
|
|
EnterCriticalSection( &g_csInitCritSec );
|
|
l = ++((IisMapper*)pMap)->lRefCount;
|
|
LeaveCriticalSection( &g_csInitCritSec );
|
|
|
|
return l;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
LONG CALLC
|
|
IisDeReferenceMapper(
|
|
OUT HMAPPER* pMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Decrement reference count to mapper
|
|
|
|
Arguments:
|
|
|
|
pMap - ptr to mapper struct
|
|
|
|
Returns:
|
|
|
|
Ref count
|
|
|
|
--*/
|
|
{
|
|
LONG l;
|
|
|
|
EnterCriticalSection( &g_csInitCritSec );
|
|
if ( !(l = --((IisMapper*)pMap)->lRefCount) )
|
|
{
|
|
LocalFree( pMap );
|
|
}
|
|
LeaveCriticalSection( &g_csInitCritSec );
|
|
|
|
return l;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
DWORD CALLC
|
|
IisGetChallenge(
|
|
HMAPPER*,
|
|
PBYTE,
|
|
DWORD,
|
|
PBYTE,
|
|
LPDWORD
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get challenge for auth sequence
|
|
|
|
Arguments:
|
|
|
|
Not used
|
|
|
|
Returns:
|
|
|
|
FALSE ( not supported )
|
|
|
|
--*/
|
|
{
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
DWORD CALLC
|
|
IisGetIssuerList(
|
|
IN HMAPPER* phMapper,
|
|
IN LPVOID pvReserved,
|
|
OUT LPBYTE pIssuer,
|
|
IN OUT DWORD * pdwIssuer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to retrieve the list of preferred cert issuers
|
|
|
|
Arguments:
|
|
|
|
phMapper - pointer to mapper object
|
|
pvReserved - nothing useful, right now
|
|
pIssuer -- updated with ptr buffer of issuers. If NULL, caller wants to get size of buffer
|
|
required for issuer list
|
|
pdwIssuer -- updated with issuers buffer size
|
|
|
|
Returns:
|
|
|
|
SEC_E_* error code
|
|
|
|
--*/
|
|
{
|
|
IIS_SSL_INFO *pSslInfo = (IIS_SSL_INFO *) ((IisMapper*) phMapper)->pvInfo;
|
|
BOOL fSuccess = FALSE;
|
|
|
|
//
|
|
// Can't get at any instance-specific information, so we'll just pretend
|
|
// that nothing happened
|
|
//
|
|
if ( !pSslInfo )
|
|
{
|
|
*pdwIssuer = 0;
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
//
|
|
// Pull out all the trusted CAs
|
|
//
|
|
PCCERT_CONTEXT *apContexts = NULL;
|
|
PCCERT_CONTEXT pCert = NULL;
|
|
DWORD dwCertsFound = 0;
|
|
DWORD dwCertsInCTL = 0;
|
|
DWORD dwTotalSize = 0;
|
|
DWORD dwPosition = 0;
|
|
|
|
if ( !pSslInfo->GetTrustedIssuerCerts( &apContexts,
|
|
&dwCertsFound ) )
|
|
{
|
|
return SEC_E_UNTRUSTED_ROOT;
|
|
}
|
|
|
|
|
|
//
|
|
// Figure out total size of chain and whether the buffer passed in is big
|
|
// enough. Each cert is to be encoded as [MSB of length] [LSB of length] [cert],
|
|
// so two extra bytes need to be added to the length for each cert
|
|
//
|
|
for ( DWORD dwIndex = 0; dwIndex < dwCertsFound; dwIndex++ )
|
|
{
|
|
dwTotalSize += apContexts[dwIndex]->cbCertEncoded;
|
|
}
|
|
dwTotalSize += 2*dwCertsFound;
|
|
|
|
//
|
|
// Caller is only interested in size or buffer is too small
|
|
//
|
|
if ( !pIssuer || ( pIssuer &&
|
|
(*pdwIssuer < dwTotalSize) ) )
|
|
{
|
|
*pdwIssuer = dwTotalSize;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Fill in the cert info : [MSB of length] [LSB of length] [Actual cert]
|
|
//
|
|
for ( dwIndex = 0 ; dwIndex < dwCertsFound; dwIndex++ )
|
|
{
|
|
pIssuer[dwPosition++] = (BYTE) ((apContexts[dwIndex]->cbCertEncoded) & 0xFF00) >> 8;
|
|
pIssuer[dwPosition++] = (BYTE) (apContexts[dwIndex]->cbCertEncoded) & 0xFF;
|
|
memcpy( pIssuer + dwPosition, apContexts[dwIndex]->pbCertEncoded,
|
|
apContexts[dwIndex]->cbCertEncoded );
|
|
dwPosition += apContexts[dwIndex]->cbCertEncoded;
|
|
}
|
|
|
|
DBG_ASSERT( dwPosition == dwTotalSize );
|
|
|
|
*pdwIssuer = dwTotalSize;
|
|
|
|
fSuccess = TRUE;
|
|
|
|
cleanup:
|
|
if ( apContexts )
|
|
{
|
|
for ( dwIndex = 0; dwIndex < dwCertsFound; dwIndex++ )
|
|
{
|
|
CertFreeCertificateContext( apContexts[dwIndex] );
|
|
}
|
|
delete [] apContexts;
|
|
}
|
|
|
|
return fSuccess ? SEC_E_OK : SEC_E_UNTRUSTED_ROOT;
|
|
|
|
#if 0
|
|
return ((CIisCert11Mapper*)(((IisMapper*)phMapper)->pCert11Mapper))->GetIssuerBuffer( (LPBYTE)pIssuer, pdwIssuer );
|
|
#endif
|
|
}
|
|
|
|
|
|
extern "C"
|
|
__declspec( dllexport )
|
|
DWORD CALLC
|
|
MapperFree(
|
|
LPVOID pvBuff
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to delete list of issuers returned by GetIssuerList
|
|
|
|
Arguments:
|
|
|
|
pvBuff -- ptr to buffer alloced by the mapper DLL
|
|
|
|
Returns:
|
|
|
|
SEC_E_* error code
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Dead code, I believe
|
|
//
|
|
DBG_ASSERT( TRUE );
|
|
|
|
LocalFree( pvBuff );
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
BOOL CALLC
|
|
TerminateMapper(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to terminate the mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
DWORD CALLC
|
|
IisMapCredential(
|
|
IN HMAPPER * phMapper,
|
|
IN DWORD dwCredentialType,
|
|
IN PVOID pCredential,
|
|
IN PVOID pAuthority,
|
|
OUT HLOCATOR * phToken
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to map a certificate to a NT account
|
|
|
|
Arguments:
|
|
|
|
phMapper - ptr to hmapper struct
|
|
dwCredentialType -- type of credential
|
|
pCredential - ptr to client cert
|
|
pAuthority - ptr to Certifying Authority cert
|
|
phToken -- updated with impersonation access token
|
|
|
|
Returns:
|
|
|
|
SEC_E_* error code
|
|
|
|
--*/
|
|
{
|
|
CIisMapping * pQuery = NULL;
|
|
CIisMapping * pResult = NULL;
|
|
BOOL fSt;
|
|
LPSTR pAcct;
|
|
LPSTR pPwd;
|
|
LPSTR pA;
|
|
DWORD dwA;
|
|
DWORD dwD;
|
|
int x;
|
|
BOOL fAllocedAcct = FALSE;
|
|
CHAR achDomain[256];
|
|
CHAR achUser[64];
|
|
CHAR achCookie[64];
|
|
CIisCert11Mapper* pCertMapper;
|
|
CIisRuleMapper* pCertWildcard;
|
|
LPSTR pEnabled;
|
|
DWORD dwE;
|
|
DWORD dwP;
|
|
CHAR achPwd[PWLEN + 1];
|
|
PCERT_CONTEXT pClientCert = (PCERT_CONTEXT) pCredential;
|
|
|
|
DBG_ASSERT( pClientCert );
|
|
|
|
//
|
|
// Reject request if we do not understand the format
|
|
//
|
|
|
|
if ( dwCredentialType != X509_ASN_CHAIN )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return SEC_E_NOT_SUPPORTED;
|
|
}
|
|
|
|
//
|
|
// IIS 4 used the pAuthority parameter; IIS 5 doesn't, and Schannel always passes in
|
|
// NULL, so remove the error check for it
|
|
//
|
|
#if 0
|
|
//
|
|
// Reject request if CA not recognized
|
|
//
|
|
|
|
//
|
|
// Removing IsCeritificateVerified() since we don't have what
|
|
// we need to do the appropriate queries
|
|
//
|
|
|
|
if ( pAuthority == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
#endif
|
|
|
|
pCertMapper = (CIisCert11Mapper*)((IisMapper*)phMapper)->pCert11Mapper;
|
|
pCertWildcard = (CIisRuleMapper*)((IisMapper*)phMapper)->pCertWMapper;
|
|
|
|
if ( !pCertMapper )
|
|
{
|
|
goto wildcard_mapper;
|
|
}
|
|
|
|
|
|
|
|
#if DBG
|
|
CHAR szSubjectName[1024];
|
|
CHAR szIssuerName[1024];
|
|
if ( CertGetNameString( pClientCert,
|
|
CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
|
0,
|
|
NULL,
|
|
szSubjectName,
|
|
1024 ) &&
|
|
CertGetNameString( pClientCert,
|
|
CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
|
CERT_NAME_ISSUER_FLAG,
|
|
NULL,
|
|
szIssuerName,
|
|
1024 ) )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"[IisMapCredential] Trying to map client cert for subject %s, issued by %s \n",
|
|
szSubjectName,
|
|
szIssuerName));
|
|
}
|
|
else
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"[IisMapCredential] Couldn't get subject or issuer name for client cert : 0x%x\n",
|
|
GetLastError()));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Create a mapping request object
|
|
//
|
|
|
|
if ( !(pQuery = pCertMapper->CreateNewMapping( pClientCert->pbCertEncoded,
|
|
pClientCert->cbCertEncoded ) ) )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"[IisMapCredential] Failed to create cert mapping query !\n"));
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
|
|
//
|
|
// Look for a match. If not found, log event
|
|
//
|
|
|
|
pCertMapper->Lock();
|
|
|
|
if ( pCertMapper->FindMatch( pQuery,
|
|
&pResult ) )
|
|
{
|
|
if ( !pResult->MappingGetField( IISMDB_INDEX_CERT11_NT_ACCT,
|
|
&pAcct,
|
|
&dwA,
|
|
FALSE ) ||
|
|
!pResult->MappingGetField( IISMDB_INDEX_CERT11_ENABLED,
|
|
&pEnabled,
|
|
&dwE,
|
|
FALSE ) ||
|
|
!pResult->MappingGetField( IISMDB_INDEX_CERT11_NT_PWD,
|
|
&pPwd,
|
|
&dwP,
|
|
FALSE ) )
|
|
{
|
|
pCertMapper->Unlock();
|
|
delete pQuery;
|
|
return SEC_E_INTERNAL_ERROR;
|
|
}
|
|
|
|
strncpy( achPwd,
|
|
pPwd,
|
|
sizeof( achPwd ) - 1 );
|
|
|
|
delete pQuery;
|
|
|
|
//
|
|
// if mapping not enabled, ignore it
|
|
//
|
|
|
|
if ( !dwE ||
|
|
( dwE == sizeof(DWORD) && *(UNALIGNED64 DWORD *)pEnabled == 0 ) ||
|
|
( dwE && *pEnabled == '0' ) )
|
|
{
|
|
pCertMapper->Unlock();
|
|
pCertMapper = NULL;
|
|
goto wildcard_mapper;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
//
|
|
// log event
|
|
//
|
|
|
|
LPCTSTR pA[CERT_MAP_NB_FIELDS];
|
|
for ( UINT x = 0 ; x < CERT_MAP_NB_FIELDS ; ++x )
|
|
{
|
|
if ( !pQuery->MappingGetField( x, (LPSTR*)(pA+x) ) || pA[x] == NULL )
|
|
{
|
|
pA[x] = "";
|
|
}
|
|
}
|
|
ReportIisMapEvent( EVENTLOG_INFORMATION_TYPE,
|
|
IISMAP_EVENT_NO_MAPPING,
|
|
CERT_MAP_NB_FIELDS,
|
|
pA );
|
|
#endif
|
|
|
|
pCertMapper->Unlock();
|
|
pCertMapper = NULL;
|
|
|
|
delete pQuery;
|
|
|
|
//
|
|
// Try to find a match using wildcard mapper
|
|
//
|
|
|
|
wildcard_mapper:
|
|
|
|
if ( pCertWildcard )
|
|
{
|
|
if ( !pCertWildcard->Match( pClientCert,
|
|
(PCERT_CONTEXT)pAuthority,
|
|
achCookie,
|
|
achPwd ) )
|
|
{
|
|
//
|
|
// Set token to special value '1' for mappings that deny access
|
|
//
|
|
if ( GetLastError() == ERROR_ACCESS_DENIED )
|
|
{
|
|
*phToken = (HLOCATOR)1;
|
|
return SEC_E_OK;
|
|
}
|
|
else
|
|
{
|
|
pAcct = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pAcct = achCookie;
|
|
dwA = strlen( pAcct );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pAcct = NULL;
|
|
}
|
|
}
|
|
|
|
if ( pAcct == NULL )
|
|
{
|
|
if ( pCertMapper )
|
|
{
|
|
pCertMapper->Unlock();
|
|
}
|
|
|
|
return SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
|
|
// break in domain & user name
|
|
// copy to local storage so we can unlock mapper object
|
|
|
|
LPSTR pSep;
|
|
LPSTR pUser;
|
|
#if 1 // DBCS enabling for user name
|
|
// pAcct is always zero terminated
|
|
if ( (pSep = (LPSTR)_mbschr( (PUCHAR)pAcct, '\\' )) )
|
|
#else
|
|
if ( (pSep = (LPSTR)memchr( pAcct, '\\', dwA )) )
|
|
#endif
|
|
{
|
|
if ( (pSep - pAcct) < sizeof(achDomain) )
|
|
{
|
|
memcpy( achDomain, pAcct, DIFF(pSep - pAcct) );
|
|
achDomain[pSep - pAcct] = '\0';
|
|
}
|
|
else
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
pCertMapper->Unlock();
|
|
return SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
pUser = pSep + 1;
|
|
dwA -= DIFF(pSep - pAcct) + 1;
|
|
}
|
|
else
|
|
{
|
|
achDomain[0] = '\0';
|
|
pUser = pAcct;
|
|
}
|
|
if ( dwA >= sizeof(achUser) || dwA <= 0 )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
pCertMapper->Unlock();
|
|
return SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
memcpy( achUser, pUser, dwA );
|
|
achUser[dwA] = '\0';
|
|
|
|
if ( pCertMapper )
|
|
{
|
|
pCertMapper->Unlock();
|
|
}
|
|
|
|
if ( fAllocedAcct )
|
|
{
|
|
LocalFree( pAcct );
|
|
}
|
|
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Found a mapping, %s\\%s\n",
|
|
(achDomain[0] == '\0' ? "<no domain>" : achDomain),
|
|
achUser));
|
|
|
|
fSt = LogonUserA( achUser,
|
|
achDomain,
|
|
achPwd,
|
|
LOGON32_LOGON_INTERACTIVE,
|
|
LOGON32_PROVIDER_DEFAULT,
|
|
(HANDLE*)phToken );
|
|
|
|
if ( !fSt )
|
|
{
|
|
LPCTSTR pA[2];
|
|
CHAR achAcct[128];
|
|
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Logon of %s\\%s failed, error 0x%x\n",
|
|
(achDomain[0] == '\0' ? "<no domain>" : achDomain),
|
|
achUser,
|
|
GetLastError()));
|
|
|
|
wsprintf( achAcct, "%s\\%s", achDomain, achUser );
|
|
if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
GetLastError(),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPSTR)&pA[1],
|
|
0,
|
|
NULL ) )
|
|
{
|
|
pA[0] = achAcct;
|
|
|
|
ReportIisMapEvent( EVENTLOG_ERROR_TYPE,
|
|
IISMAP_EVENT_ERROR_LOGON,
|
|
sizeof(pA)/sizeof(LPCTSTR),
|
|
pA );
|
|
|
|
LocalFree( (LPVOID)pA[1] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"[IisMapCredential] Successful logon, token 0x%p\n",
|
|
*phToken));
|
|
|
|
g_dwNumLocators++;
|
|
}
|
|
|
|
return fSt ? SEC_E_OK : SEC_E_UNKNOWN_CREDENTIALS;
|
|
}
|
|
|
|
extern "C"
|
|
DWORD CALLC IisQueryMappedCredentialAttributes( IN HMAPPER *phMapper,
|
|
IN HLOCATOR hLocator,
|
|
IN ULONG ulAttribute,
|
|
OUT PVOID pBuffer,
|
|
IN OUT DWORD *pcbBuffer )
|
|
{
|
|
if ( !pBuffer || ( *pcbBuffer < sizeof( HLOCATOR ) ) )
|
|
{
|
|
*pcbBuffer = sizeof( HLOCATOR );
|
|
}
|
|
else
|
|
{
|
|
*((HLOCATOR*)pBuffer) = hLocator;
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
extern "C"
|
|
DWORD CALLC
|
|
IisGetAccessToken(
|
|
IN HMAPPER* phMapper,
|
|
IN HLOCATOR tokenhandle,
|
|
OUT HANDLE *phToken
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to retrieve an access token from a mapping
|
|
|
|
Arguments:
|
|
|
|
phMapper - pointer to mapper to use
|
|
tokenhandle -- HLOCATOR returned by MapCredential
|
|
phToken -- updated with potentially new token
|
|
|
|
Returns:
|
|
|
|
SEC_E_* error code
|
|
|
|
--*/
|
|
{
|
|
|
|
#if 1
|
|
*phToken = (HANDLE) tokenhandle;
|
|
|
|
return SEC_E_OK;
|
|
#else
|
|
//
|
|
// Special value '1' is used to denote mappings that -deny- access
|
|
//
|
|
if ( tokenhandle == 1 )
|
|
{
|
|
*phToken = (HANDLE)tokenhandle;
|
|
}
|
|
else
|
|
{
|
|
if ( !DuplicateTokenEx( (HANDLE)tokenhandle,
|
|
TOKEN_ALL_ACCESS,
|
|
NULL,
|
|
SecurityImpersonation,
|
|
TokenPrimary,
|
|
phToken ))
|
|
{
|
|
return SEC_E_INVALID_TOKEN;
|
|
}
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
#endif
|
|
}
|
|
|
|
|
|
extern "C"
|
|
DWORD CALLC
|
|
IisCloseLocator(
|
|
IN HMAPPER* phMapper,
|
|
IN HLOCATOR tokenhandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to close a HLOCATOR returned by MapCredential
|
|
|
|
Arguments:
|
|
|
|
tokenhandle -- HLOCATOR
|
|
|
|
Returns:
|
|
|
|
SEC_E_* error code
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT( g_dwNumLocators > 0 );
|
|
|
|
if ( tokenhandle != 1 && tokenhandle != NULL )
|
|
{
|
|
CloseHandle( (HANDLE)tokenhandle );
|
|
g_dwNumLocators--;
|
|
}
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
MAPPER_VTABLE g_MapperVtable={
|
|
(REF_MAPPER_FN)IisReferenceMapper,
|
|
(DEREF_MAPPER_FN)IisDeReferenceMapper,
|
|
(GET_ISSUER_LIST_FN)IisGetIssuerList,
|
|
(GET_CHALLENGE_FN)IisGetChallenge,
|
|
(MAP_CREDENTIAL_FN)IisMapCredential,
|
|
(GET_ACCESS_TOKEN_FN)IisGetAccessToken,
|
|
(CLOSE_LOCATOR_FN)IisCloseLocator,
|
|
(QUERY_MAPPED_CREDENTIAL_ATTRIBUTES_FN)IisQueryMappedCredentialAttributes
|
|
} ;
|
|
|
|
|
|
|