Source code of Windows XP (NT5)
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.

935 lines
19 KiB

  1. /*++
  2. opyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. iiscrmap.cxx
  5. Abstract:
  6. Certificate to NT account mapper
  7. Author:
  8. Philippe Choquier (phillich) 17-may-1996
  9. Alex Mallet (amallet) 13-Feb-1998
  10. --*/
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14. # include <nt.h>
  15. # include <ntrtl.h>
  16. # include <nturtl.h>
  17. # include <windows.h>
  18. #include <stdio.h>
  19. #if 1 // DBCS
  20. #include <mbstring.h>
  21. #endif
  22. #include <schnlsp.h>
  23. #include <wincrypt.h>
  24. #include <issperr.h>
  25. #include <certmap.h>
  26. #include <cmnull.hxx>
  27. #include <lmcons.h>
  28. #ifdef __cplusplus
  29. };
  30. #endif
  31. #include <iis64.h>
  32. #include <iiscrmap.hxx>
  33. extern "C" {
  34. #include <tchar.h>
  35. #include <iisfiltp.h>
  36. } // extern "C"
  37. #include <tslogon.hxx>
  38. #include <iismap.hxx>
  39. #include <iiscmr.hxx>
  40. #include "mapmsg.h"
  41. #include <dbgutil.h>
  42. #include <buffer.hxx>
  43. #include <ole2.h>
  44. #include <imd.h>
  45. #include <mb.hxx>
  46. #include <iiscnfgp.h>
  47. #include <reftrace.h>
  48. #include <iiscert.hxx>
  49. #include <iisctl.hxx>
  50. #include <capiutil.hxx>
  51. #include <sslinfo.hxx>
  52. #define CALLC WINAPI
  53. CRITICAL_SECTION g_csInitCritSec;
  54. DWORD g_dwNumLocators;
  55. extern MAPPER_VTABLE g_MapperVtable;
  56. HANDLE g_hModule;
  57. //
  58. //
  59. //
  60. DECLARE_DEBUG_PRINTS_OBJECT();
  61. #include <initguid.h>
  62. DEFINE_GUID(IisCrMapGuid,
  63. 0x784d8913, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
  64. extern "C"
  65. BOOL
  66. WINAPI
  67. DLLEntry(
  68. HINSTANCE hDll,
  69. DWORD dwReason,
  70. LPVOID lpvReserved
  71. )
  72. {
  73. switch ( dwReason )
  74. {
  75. case DLL_PROCESS_ATTACH:
  76. #ifdef _NO_TRACING_
  77. CREATE_DEBUG_PRINT_OBJECT( "IISCRMAP" );
  78. #else
  79. CREATE_DEBUG_PRINT_OBJECT( "IISCRMAP" , IisCrMapGuid);
  80. #endif
  81. INITIALIZE_CRITICAL_SECTION( &g_csInitCritSec );
  82. g_dwNumLocators = 0;
  83. g_hModule = hDll;
  84. break;
  85. case DLL_PROCESS_DETACH:
  86. if ( g_dwNumLocators )
  87. {
  88. DBGPRINTF((DBG_CONTEXT,
  89. "Still have %d locators left !\n",
  90. g_dwNumLocators));
  91. }
  92. DELETE_DEBUG_PRINT_OBJECT();
  93. DeleteCriticalSection( &g_csInitCritSec );
  94. break;
  95. default:
  96. break;
  97. }
  98. return TRUE;
  99. }
  100. extern "C"
  101. DWORD CALLC
  102. CreateInstance(
  103. OUT HMAPPER** pHMapper
  104. )
  105. /*++
  106. Routine Description:
  107. Called to initialize the mapper
  108. Arguments:
  109. None
  110. Returns:
  111. Ptr to mapper vtable if success, otherwise NULL
  112. --*/
  113. {
  114. IisMapper *pMap;
  115. if ( !(pMap = (IisMapper*)LocalAlloc( LMEM_FIXED, sizeof(IisMapper) )) )
  116. {
  117. return SEC_E_INSUFFICIENT_MEMORY;
  118. }
  119. memcpy ( &pMap->mvtEntryPoints, &g_MapperVtable, sizeof(MAPPER_VTABLE) );
  120. pMap->hMapper.m_vtable = &pMap->mvtEntryPoints;
  121. pMap->hMapper.m_dwMapperVersion = MAPPER_INTERFACE_VER;
  122. pMap->hMapper.m_Reserved1 = NULL;
  123. pMap->lRefCount = 1;
  124. pMap->fIsIisCompliant = TRUE;
  125. pMap->hInst = (HINSTANCE)g_hModule;
  126. pMap->pCert11Mapper = NULL;
  127. pMap->pCertWMapper = NULL;
  128. pMap->pvInfo = NULL;
  129. pMap->dwSignature = IIS_MAPPER_SIGNATURE;
  130. *pHMapper = (HMAPPER*)pMap;
  131. return SEC_E_OK;
  132. }
  133. extern "C"
  134. LONG CALLC
  135. IisReferenceMapper(
  136. OUT HMAPPER* pMap
  137. )
  138. /*++
  139. Routine Description:
  140. Increment reference count to mapper
  141. Arguments:
  142. pMap - ptr to mapper struct
  143. Returns:
  144. Ref count
  145. --*/
  146. {
  147. LONG l;
  148. EnterCriticalSection( &g_csInitCritSec );
  149. l = ++((IisMapper*)pMap)->lRefCount;
  150. LeaveCriticalSection( &g_csInitCritSec );
  151. return l;
  152. }
  153. extern "C"
  154. LONG CALLC
  155. IisDeReferenceMapper(
  156. OUT HMAPPER* pMap
  157. )
  158. /*++
  159. Routine Description:
  160. Decrement reference count to mapper
  161. Arguments:
  162. pMap - ptr to mapper struct
  163. Returns:
  164. Ref count
  165. --*/
  166. {
  167. LONG l;
  168. EnterCriticalSection( &g_csInitCritSec );
  169. if ( !(l = --((IisMapper*)pMap)->lRefCount) )
  170. {
  171. LocalFree( pMap );
  172. }
  173. LeaveCriticalSection( &g_csInitCritSec );
  174. return l;
  175. }
  176. extern "C"
  177. DWORD CALLC
  178. IisGetChallenge(
  179. HMAPPER*,
  180. PBYTE,
  181. DWORD,
  182. PBYTE,
  183. LPDWORD
  184. )
  185. /*++
  186. Routine Description:
  187. Get challenge for auth sequence
  188. Arguments:
  189. Not used
  190. Returns:
  191. FALSE ( not supported )
  192. --*/
  193. {
  194. return SEC_E_UNSUPPORTED_FUNCTION;
  195. }
  196. extern "C"
  197. DWORD CALLC
  198. IisGetIssuerList(
  199. IN HMAPPER* phMapper,
  200. IN LPVOID pvReserved,
  201. OUT LPBYTE pIssuer,
  202. IN OUT DWORD * pdwIssuer
  203. )
  204. /*++
  205. Routine Description:
  206. Called to retrieve the list of preferred cert issuers
  207. Arguments:
  208. phMapper - pointer to mapper object
  209. pvReserved - nothing useful, right now
  210. pIssuer -- updated with ptr buffer of issuers. If NULL, caller wants to get size of buffer
  211. required for issuer list
  212. pdwIssuer -- updated with issuers buffer size
  213. Returns:
  214. SEC_E_* error code
  215. --*/
  216. {
  217. IIS_SSL_INFO *pSslInfo = (IIS_SSL_INFO *) ((IisMapper*) phMapper)->pvInfo;
  218. BOOL fSuccess = FALSE;
  219. //
  220. // Can't get at any instance-specific information, so we'll just pretend
  221. // that nothing happened
  222. //
  223. if ( !pSslInfo )
  224. {
  225. *pdwIssuer = 0;
  226. return SEC_E_OK;
  227. }
  228. //
  229. // Pull out all the trusted CAs
  230. //
  231. PCCERT_CONTEXT *apContexts = NULL;
  232. PCCERT_CONTEXT pCert = NULL;
  233. DWORD dwCertsFound = 0;
  234. DWORD dwCertsInCTL = 0;
  235. DWORD dwTotalSize = 0;
  236. DWORD dwPosition = 0;
  237. if ( !pSslInfo->GetTrustedIssuerCerts( &apContexts,
  238. &dwCertsFound ) )
  239. {
  240. return SEC_E_UNTRUSTED_ROOT;
  241. }
  242. //
  243. // Figure out total size of chain and whether the buffer passed in is big
  244. // enough. Each cert is to be encoded as [MSB of length] [LSB of length] [cert],
  245. // so two extra bytes need to be added to the length for each cert
  246. //
  247. for ( DWORD dwIndex = 0; dwIndex < dwCertsFound; dwIndex++ )
  248. {
  249. dwTotalSize += apContexts[dwIndex]->cbCertEncoded;
  250. }
  251. dwTotalSize += 2*dwCertsFound;
  252. //
  253. // Caller is only interested in size or buffer is too small
  254. //
  255. if ( !pIssuer || ( pIssuer &&
  256. (*pdwIssuer < dwTotalSize) ) )
  257. {
  258. *pdwIssuer = dwTotalSize;
  259. goto cleanup;
  260. }
  261. //
  262. // Fill in the cert info : [MSB of length] [LSB of length] [Actual cert]
  263. //
  264. for ( dwIndex = 0 ; dwIndex < dwCertsFound; dwIndex++ )
  265. {
  266. pIssuer[dwPosition++] = (BYTE) ((apContexts[dwIndex]->cbCertEncoded) & 0xFF00) >> 8;
  267. pIssuer[dwPosition++] = (BYTE) (apContexts[dwIndex]->cbCertEncoded) & 0xFF;
  268. memcpy( pIssuer + dwPosition, apContexts[dwIndex]->pbCertEncoded,
  269. apContexts[dwIndex]->cbCertEncoded );
  270. dwPosition += apContexts[dwIndex]->cbCertEncoded;
  271. }
  272. DBG_ASSERT( dwPosition == dwTotalSize );
  273. *pdwIssuer = dwTotalSize;
  274. fSuccess = TRUE;
  275. cleanup:
  276. if ( apContexts )
  277. {
  278. for ( dwIndex = 0; dwIndex < dwCertsFound; dwIndex++ )
  279. {
  280. CertFreeCertificateContext( apContexts[dwIndex] );
  281. }
  282. delete [] apContexts;
  283. }
  284. return fSuccess ? SEC_E_OK : SEC_E_UNTRUSTED_ROOT;
  285. #if 0
  286. return ((CIisCert11Mapper*)(((IisMapper*)phMapper)->pCert11Mapper))->GetIssuerBuffer( (LPBYTE)pIssuer, pdwIssuer );
  287. #endif
  288. }
  289. extern "C"
  290. __declspec( dllexport )
  291. DWORD CALLC
  292. MapperFree(
  293. LPVOID pvBuff
  294. )
  295. /*++
  296. Routine Description:
  297. Called to delete list of issuers returned by GetIssuerList
  298. Arguments:
  299. pvBuff -- ptr to buffer alloced by the mapper DLL
  300. Returns:
  301. SEC_E_* error code
  302. --*/
  303. {
  304. //
  305. // Dead code, I believe
  306. //
  307. DBG_ASSERT( TRUE );
  308. LocalFree( pvBuff );
  309. return SEC_E_OK;
  310. }
  311. extern "C"
  312. BOOL CALLC
  313. TerminateMapper(
  314. VOID
  315. )
  316. /*++
  317. Routine Description:
  318. Called to terminate the mapper
  319. Arguments:
  320. None
  321. Returns:
  322. --*/
  323. {
  324. return TRUE;
  325. }
  326. extern "C"
  327. DWORD CALLC
  328. IisMapCredential(
  329. IN HMAPPER * phMapper,
  330. IN DWORD dwCredentialType,
  331. IN PVOID pCredential,
  332. IN PVOID pAuthority,
  333. OUT HLOCATOR * phToken
  334. )
  335. /*++
  336. Routine Description:
  337. Called to map a certificate to a NT account
  338. Arguments:
  339. phMapper - ptr to hmapper struct
  340. dwCredentialType -- type of credential
  341. pCredential - ptr to client cert
  342. pAuthority - ptr to Certifying Authority cert
  343. phToken -- updated with impersonation access token
  344. Returns:
  345. SEC_E_* error code
  346. --*/
  347. {
  348. CIisMapping * pQuery = NULL;
  349. CIisMapping * pResult = NULL;
  350. BOOL fSt;
  351. LPSTR pAcct;
  352. LPSTR pPwd;
  353. LPSTR pA;
  354. DWORD dwA;
  355. DWORD dwD;
  356. int x;
  357. BOOL fAllocedAcct = FALSE;
  358. CHAR achDomain[256];
  359. CHAR achUser[64];
  360. CHAR achCookie[64];
  361. CIisCert11Mapper* pCertMapper;
  362. CIisRuleMapper* pCertWildcard;
  363. LPSTR pEnabled;
  364. DWORD dwE;
  365. DWORD dwP;
  366. CHAR achPwd[PWLEN + 1];
  367. PCERT_CONTEXT pClientCert = (PCERT_CONTEXT) pCredential;
  368. DBG_ASSERT( pClientCert );
  369. //
  370. // Reject request if we do not understand the format
  371. //
  372. if ( dwCredentialType != X509_ASN_CHAIN )
  373. {
  374. SetLastError( ERROR_INVALID_PARAMETER );
  375. return SEC_E_NOT_SUPPORTED;
  376. }
  377. //
  378. // IIS 4 used the pAuthority parameter; IIS 5 doesn't, and Schannel always passes in
  379. // NULL, so remove the error check for it
  380. //
  381. #if 0
  382. //
  383. // Reject request if CA not recognized
  384. //
  385. //
  386. // Removing IsCeritificateVerified() since we don't have what
  387. // we need to do the appropriate queries
  388. //
  389. if ( pAuthority == NULL )
  390. {
  391. SetLastError( ERROR_INVALID_PARAMETER );
  392. return SEC_E_INTERNAL_ERROR;
  393. }
  394. #endif
  395. pCertMapper = (CIisCert11Mapper*)((IisMapper*)phMapper)->pCert11Mapper;
  396. pCertWildcard = (CIisRuleMapper*)((IisMapper*)phMapper)->pCertWMapper;
  397. if ( !pCertMapper )
  398. {
  399. goto wildcard_mapper;
  400. }
  401. #if DBG
  402. CHAR szSubjectName[1024];
  403. CHAR szIssuerName[1024];
  404. if ( CertGetNameString( pClientCert,
  405. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  406. 0,
  407. NULL,
  408. szSubjectName,
  409. 1024 ) &&
  410. CertGetNameString( pClientCert,
  411. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  412. CERT_NAME_ISSUER_FLAG,
  413. NULL,
  414. szIssuerName,
  415. 1024 ) )
  416. {
  417. DBGPRINTF((DBG_CONTEXT,
  418. "[IisMapCredential] Trying to map client cert for subject %s, issued by %s \n",
  419. szSubjectName,
  420. szIssuerName));
  421. }
  422. else
  423. {
  424. DBGPRINTF((DBG_CONTEXT,
  425. "[IisMapCredential] Couldn't get subject or issuer name for client cert : 0x%x\n",
  426. GetLastError()));
  427. }
  428. #endif
  429. //
  430. // Create a mapping request object
  431. //
  432. if ( !(pQuery = pCertMapper->CreateNewMapping( pClientCert->pbCertEncoded,
  433. pClientCert->cbCertEncoded ) ) )
  434. {
  435. DBGPRINTF((DBG_CONTEXT,
  436. "[IisMapCredential] Failed to create cert mapping query !\n"));
  437. return SEC_E_INTERNAL_ERROR;
  438. }
  439. //
  440. // Look for a match. If not found, log event
  441. //
  442. pCertMapper->Lock();
  443. if ( pCertMapper->FindMatch( pQuery,
  444. &pResult ) )
  445. {
  446. if ( !pResult->MappingGetField( IISMDB_INDEX_CERT11_NT_ACCT,
  447. &pAcct,
  448. &dwA,
  449. FALSE ) ||
  450. !pResult->MappingGetField( IISMDB_INDEX_CERT11_ENABLED,
  451. &pEnabled,
  452. &dwE,
  453. FALSE ) ||
  454. !pResult->MappingGetField( IISMDB_INDEX_CERT11_NT_PWD,
  455. &pPwd,
  456. &dwP,
  457. FALSE ) )
  458. {
  459. pCertMapper->Unlock();
  460. delete pQuery;
  461. return SEC_E_INTERNAL_ERROR;
  462. }
  463. strncpy( achPwd,
  464. pPwd,
  465. sizeof( achPwd ) - 1 );
  466. delete pQuery;
  467. //
  468. // if mapping not enabled, ignore it
  469. //
  470. if ( !dwE ||
  471. ( dwE == sizeof(DWORD) && *(UNALIGNED64 DWORD *)pEnabled == 0 ) ||
  472. ( dwE && *pEnabled == '0' ) )
  473. {
  474. pCertMapper->Unlock();
  475. pCertMapper = NULL;
  476. goto wildcard_mapper;
  477. }
  478. }
  479. else
  480. {
  481. #if 0
  482. //
  483. // log event
  484. //
  485. LPCTSTR pA[CERT_MAP_NB_FIELDS];
  486. for ( UINT x = 0 ; x < CERT_MAP_NB_FIELDS ; ++x )
  487. {
  488. if ( !pQuery->MappingGetField( x, (LPSTR*)(pA+x) ) || pA[x] == NULL )
  489. {
  490. pA[x] = "";
  491. }
  492. }
  493. ReportIisMapEvent( EVENTLOG_INFORMATION_TYPE,
  494. IISMAP_EVENT_NO_MAPPING,
  495. CERT_MAP_NB_FIELDS,
  496. pA );
  497. #endif
  498. pCertMapper->Unlock();
  499. pCertMapper = NULL;
  500. delete pQuery;
  501. //
  502. // Try to find a match using wildcard mapper
  503. //
  504. wildcard_mapper:
  505. if ( pCertWildcard )
  506. {
  507. if ( !pCertWildcard->Match( pClientCert,
  508. (PCERT_CONTEXT)pAuthority,
  509. achCookie,
  510. achPwd ) )
  511. {
  512. //
  513. // Set token to special value '1' for mappings that deny access
  514. //
  515. if ( GetLastError() == ERROR_ACCESS_DENIED )
  516. {
  517. *phToken = (HLOCATOR)1;
  518. return SEC_E_OK;
  519. }
  520. else
  521. {
  522. pAcct = NULL;
  523. }
  524. }
  525. else
  526. {
  527. pAcct = achCookie;
  528. dwA = strlen( pAcct );
  529. }
  530. }
  531. else
  532. {
  533. pAcct = NULL;
  534. }
  535. }
  536. if ( pAcct == NULL )
  537. {
  538. if ( pCertMapper )
  539. {
  540. pCertMapper->Unlock();
  541. }
  542. return SEC_E_UNKNOWN_CREDENTIALS;
  543. }
  544. // break in domain & user name
  545. // copy to local storage so we can unlock mapper object
  546. LPSTR pSep;
  547. LPSTR pUser;
  548. #if 1 // DBCS enabling for user name
  549. // pAcct is always zero terminated
  550. if ( (pSep = (LPSTR)_mbschr( (PUCHAR)pAcct, '\\' )) )
  551. #else
  552. if ( (pSep = (LPSTR)memchr( pAcct, '\\', dwA )) )
  553. #endif
  554. {
  555. if ( (pSep - pAcct) < sizeof(achDomain) )
  556. {
  557. memcpy( achDomain, pAcct, DIFF(pSep - pAcct) );
  558. achDomain[pSep - pAcct] = '\0';
  559. }
  560. else
  561. {
  562. SetLastError( ERROR_INVALID_PARAMETER );
  563. pCertMapper->Unlock();
  564. return SEC_E_UNKNOWN_CREDENTIALS;
  565. }
  566. pUser = pSep + 1;
  567. dwA -= DIFF(pSep - pAcct) + 1;
  568. }
  569. else
  570. {
  571. achDomain[0] = '\0';
  572. pUser = pAcct;
  573. }
  574. if ( dwA >= sizeof(achUser) || dwA <= 0 )
  575. {
  576. SetLastError( ERROR_INVALID_PARAMETER );
  577. pCertMapper->Unlock();
  578. return SEC_E_UNKNOWN_CREDENTIALS;
  579. }
  580. memcpy( achUser, pUser, dwA );
  581. achUser[dwA] = '\0';
  582. if ( pCertMapper )
  583. {
  584. pCertMapper->Unlock();
  585. }
  586. if ( fAllocedAcct )
  587. {
  588. LocalFree( pAcct );
  589. }
  590. DBGPRINTF((DBG_CONTEXT,
  591. "Found a mapping, %s\\%s\n",
  592. (achDomain[0] == '\0' ? "<no domain>" : achDomain),
  593. achUser));
  594. fSt = LogonUserA( achUser,
  595. achDomain,
  596. achPwd,
  597. LOGON32_LOGON_INTERACTIVE,
  598. LOGON32_PROVIDER_DEFAULT,
  599. (HANDLE*)phToken );
  600. if ( !fSt )
  601. {
  602. LPCTSTR pA[2];
  603. CHAR achAcct[128];
  604. DBGPRINTF((DBG_CONTEXT,
  605. "Logon of %s\\%s failed, error 0x%x\n",
  606. (achDomain[0] == '\0' ? "<no domain>" : achDomain),
  607. achUser,
  608. GetLastError()));
  609. wsprintf( achAcct, "%s\\%s", achDomain, achUser );
  610. if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  611. NULL,
  612. GetLastError(),
  613. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  614. (LPSTR)&pA[1],
  615. 0,
  616. NULL ) )
  617. {
  618. pA[0] = achAcct;
  619. ReportIisMapEvent( EVENTLOG_ERROR_TYPE,
  620. IISMAP_EVENT_ERROR_LOGON,
  621. sizeof(pA)/sizeof(LPCTSTR),
  622. pA );
  623. LocalFree( (LPVOID)pA[1] );
  624. }
  625. }
  626. else
  627. {
  628. DBGPRINTF((DBG_CONTEXT,
  629. "[IisMapCredential] Successful logon, token 0x%p\n",
  630. *phToken));
  631. g_dwNumLocators++;
  632. }
  633. return fSt ? SEC_E_OK : SEC_E_UNKNOWN_CREDENTIALS;
  634. }
  635. extern "C"
  636. DWORD CALLC IisQueryMappedCredentialAttributes( IN HMAPPER *phMapper,
  637. IN HLOCATOR hLocator,
  638. IN ULONG ulAttribute,
  639. OUT PVOID pBuffer,
  640. IN OUT DWORD *pcbBuffer )
  641. {
  642. if ( !pBuffer || ( *pcbBuffer < sizeof( HLOCATOR ) ) )
  643. {
  644. *pcbBuffer = sizeof( HLOCATOR );
  645. }
  646. else
  647. {
  648. *((HLOCATOR*)pBuffer) = hLocator;
  649. }
  650. return SEC_E_OK;
  651. }
  652. extern "C"
  653. DWORD CALLC
  654. IisGetAccessToken(
  655. IN HMAPPER* phMapper,
  656. IN HLOCATOR tokenhandle,
  657. OUT HANDLE *phToken
  658. )
  659. /*++
  660. Routine Description:
  661. Called to retrieve an access token from a mapping
  662. Arguments:
  663. phMapper - pointer to mapper to use
  664. tokenhandle -- HLOCATOR returned by MapCredential
  665. phToken -- updated with potentially new token
  666. Returns:
  667. SEC_E_* error code
  668. --*/
  669. {
  670. #if 1
  671. *phToken = (HANDLE) tokenhandle;
  672. return SEC_E_OK;
  673. #else
  674. //
  675. // Special value '1' is used to denote mappings that -deny- access
  676. //
  677. if ( tokenhandle == 1 )
  678. {
  679. *phToken = (HANDLE)tokenhandle;
  680. }
  681. else
  682. {
  683. if ( !DuplicateTokenEx( (HANDLE)tokenhandle,
  684. TOKEN_ALL_ACCESS,
  685. NULL,
  686. SecurityImpersonation,
  687. TokenPrimary,
  688. phToken ))
  689. {
  690. return SEC_E_INVALID_TOKEN;
  691. }
  692. }
  693. return SEC_E_OK;
  694. #endif
  695. }
  696. extern "C"
  697. DWORD CALLC
  698. IisCloseLocator(
  699. IN HMAPPER* phMapper,
  700. IN HLOCATOR tokenhandle
  701. )
  702. /*++
  703. Routine Description:
  704. Called to close a HLOCATOR returned by MapCredential
  705. Arguments:
  706. tokenhandle -- HLOCATOR
  707. Returns:
  708. SEC_E_* error code
  709. --*/
  710. {
  711. DBG_ASSERT( g_dwNumLocators > 0 );
  712. if ( tokenhandle != 1 && tokenhandle != NULL )
  713. {
  714. CloseHandle( (HANDLE)tokenhandle );
  715. g_dwNumLocators--;
  716. }
  717. return SEC_E_OK;
  718. }
  719. MAPPER_VTABLE g_MapperVtable={
  720. (REF_MAPPER_FN)IisReferenceMapper,
  721. (DEREF_MAPPER_FN)IisDeReferenceMapper,
  722. (GET_ISSUER_LIST_FN)IisGetIssuerList,
  723. (GET_CHALLENGE_FN)IisGetChallenge,
  724. (MAP_CREDENTIAL_FN)IisMapCredential,
  725. (GET_ACCESS_TOKEN_FN)IisGetAccessToken,
  726. (CLOSE_LOCATOR_FN)IisCloseLocator,
  727. (QUERY_MAPPED_CREDENTIAL_ATTRIBUTES_FN)IisQueryMappedCredentialAttributes
  728. } ;