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.

1942 lines
52 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. credcach.cxx
  5. Abstract:
  6. This module contains the code to associate and cache SSPI credential
  7. handles with local server addresses
  8. Author:
  9. Comments :
  10. This is a two-level cache : the first level is at the instance level [INSTANCE_CACHE_ITEM]
  11. and just contains a pointer to the actual item holding the credential handles. The second level
  12. [CRED_CACHE_ITEM] holds the actual credential handles, as well as pointers to the mappers.
  13. An INSTANCE_CACHE_ITEM points to a CRED_CACHE_ITEM, with a single CRED_CACHE_ITEM potentially
  14. being referenced by several INSTANCE_CACHE_ITEMS, if several instances share the relevant data.
  15. Each instance has 3 SSL-related components : the server certificate for the instance, the
  16. certificate mappers for the instance and the trusted issuers for the instance [a combination of
  17. the certificates in the ROOT store and the Certificate Trust List associated with the server]. Two
  18. instances can share a CRED_CACHE_ITEM under the following circumstances :
  19. 1. The same server certificate
  20. 2. No/Same CTL
  21. 3. No mappers
  22. The INSTANCE_CACHE_ITEM entries are keyed off "<instance ptr>"; the CRED_CACHE_ITEM
  23. entries are keyed off an "SSL info" blob which can be used to uniquely distinguish between
  24. credential sets that don't fulfill the criteria listed above. The SSL info blob is obtained by
  25. querying the instance and consists of "<SHA1 hash of server cert>:<SHA1 hash of CTL>",
  26. which has the advantage of being fixed length [20 bytes for cert hash, 20 bytes for CTL hash,
  27. 1 byte for ':']. If there is no CTL, the length is still 41, but everything after the CERT has is
  28. zeroed out
  29. Revision History:
  30. Nimish Khanolkar FEB'98 Changes related to having one cert per instance
  31. --*/
  32. extern "C" {
  33. #include <nt.h>
  34. #include <ntrtl.h>
  35. #include <nturtl.h>
  36. #include <windows.h>
  37. #include <wincrypt.h>
  38. #include <stdlib.h>
  39. }
  40. #include <dbgutil.h>
  41. #include <buffer.hxx>
  42. #include <ole2.h>
  43. #include <imd.h>
  44. #include <iadm.h>
  45. #include <mb.hxx>
  46. #include <iiscnfg.h>
  47. //#include <iiscnfgp.h>
  48. #include <refb.hxx>
  49. #include <cmnull.hxx>
  50. #include <iiscrmap.hxx>
  51. #include "iistypes.hxx"
  52. extern "C" {
  53. #define SECURITY_WIN32
  54. #include <sspi.h>
  55. #include <ntsecapi.h>
  56. #include <spseal.h>
  57. #include <schnlsp.h>
  58. #include ".\credcach.hxx"
  59. #include <w3svc.h>
  60. }
  61. #include "iiscert.hxx"
  62. #include "iisctl.hxx"
  63. #include "capiutil.hxx"
  64. #if DBG
  65. #define PRINTF( x ) { char buff[256]; wsprintf x; OutputDebugString( buff ); }
  66. #else
  67. #define PRINTF( x )
  68. #endif
  69. #ifdef UNIT_TEST
  70. DEBUG_PRINTS * g_pDebug = 0;
  71. #endif
  72. #define SSPIFILT_CERT_MAP_LIST "CertMapList"
  73. #define SSPIFILT_INIT_MAP "CreateInstance"
  74. #define SSPIFILT_TERM_MAP "TerminateMapper"
  75. //
  76. // Globals
  77. //
  78. LIST_ENTRY CredCacheList;
  79. LIST_ENTRY InstanceCacheList;
  80. CRED_CACHE_ITEM* g_pcciClient = NULL;
  81. IMDCOM* pMDObject;
  82. IMSAdminBaseW* pAdminObject;
  83. //
  84. // Prototypes
  85. //
  86. BOOL
  87. LoadKeys(
  88. IN IIS_SSL_INFO *pSSLInfo,
  89. IN PVOID pvInstance,
  90. IN HMAPPER** ppMappers,
  91. IN DWORD cNbMappers,
  92. OUT CredHandle * phCreds,
  93. OUT DWORD * pcCred,
  94. OUT CredHandle * phCredsMap,
  95. OUT DWORD * pcCredMap,
  96. IN LPSTR pszMdPath
  97. );
  98. BOOL
  99. AddFullyQualifiedItem(
  100. IN WCHAR * pwszServerPrefix,
  101. CHAR * pszId,
  102. IN UINT cId,
  103. CHAR * pszAddress,
  104. IN CHAR * pszPort,
  105. IN LPVOID pvInstanceId,
  106. IN PVOID pvsmc,
  107. IN DWORD dwInstanceId
  108. );
  109. BOOL
  110. AddItem(
  111. CHAR * pszAddress,
  112. LPVOID pvInstanceId,
  113. RefBlob* pCert11,
  114. RefBlob* pCertW,
  115. IIS_SSL_INFO *pSSLInfo,
  116. CRED_CACHE_ITEM** ppcci,
  117. DWORD dwInstanceId,
  118. LPSTR pszMdPath
  119. );
  120. BOOL
  121. LookupCredential(
  122. IN CHAR * pszAddress,
  123. IN LPVOID pvInstanceId,
  124. OUT CRED_CACHE_ITEM * * ppCCI
  125. );
  126. BOOL
  127. InitializeCertMapping(
  128. LPVOID pCert11,
  129. LPVOID pCertW,
  130. LPVOID pSslInfo,
  131. HMAPPER*** pppMappers,
  132. LPDWORD pdwMappers,
  133. DWORD dwInstanceId
  134. );
  135. VOID WINAPI NotifySslChanges(
  136. DWORD dwNotifyType,
  137. LPVOID pInstance
  138. );
  139. BOOL GenerateSSLIdBlob( IIS_SSL_INFO *pSSLInfoObj,
  140. PBYTE pbBlob );
  141. VOID
  142. InitCredCache(
  143. VOID
  144. )
  145. /*++
  146. Routine Description:
  147. Initializes the credential cache
  148. --*/
  149. {
  150. InitializeListHead( &CredCacheList );
  151. InitializeListHead( &InstanceCacheList );
  152. }
  153. VOID
  154. FreeCredCache(
  155. VOID
  156. )
  157. /*++
  158. Routine Description:
  159. Releases all of the memory associated with the credential cache
  160. --*/
  161. {
  162. //LIST_ENTRY * pEntry;
  163. CRED_CACHE_ITEM * pcci;
  164. INSTANCE_CACHE_ITEM * pici;
  165. while ( !IsListEmpty( &InstanceCacheList ))
  166. {
  167. pici = CONTAINING_RECORD( InstanceCacheList.Flink,
  168. INSTANCE_CACHE_ITEM,
  169. m_ListEntry );
  170. RemoveEntryList( &pici->m_ListEntry );
  171. delete pici;
  172. }
  173. while ( !IsListEmpty( &CredCacheList ))
  174. {
  175. pcci = CONTAINING_RECORD( CredCacheList.Flink,
  176. CRED_CACHE_ITEM,
  177. m_ListEntry );
  178. RemoveEntryList( &pcci->m_ListEntry );
  179. pcci->Release();
  180. }
  181. if ( g_pcciClient != NULL )
  182. {
  183. g_pcciClient->Release();
  184. g_pcciClient = NULL;
  185. }
  186. }
  187. BOOL
  188. LookupFullyQualifiedCredential(
  189. IN WCHAR * pwszServerPrefix,
  190. IN CHAR * pszIpAddress,
  191. IN DWORD cbAddress,
  192. IN CHAR * pszPort,
  193. IN DWORD cbPort,
  194. IN LPVOID pvInstanceId,
  195. OUT CRED_CACHE_ITEM * * ppCCI,
  196. IN PVOID pvsmc,
  197. IN DWORD dwInstanceId
  198. )
  199. /*++
  200. Routine Description:
  201. Finds an entry in the credential cache or creates one if it's not found
  202. Arguments:
  203. pszIpAddress - Address name for this credential
  204. cbAddress - Number of bytes (including '\0') of pszIpAddress
  205. pszPort - Port ID for this credential
  206. cbPort - Number of bytes ( including '\0') of pszPort
  207. pvInstanceId - ptr to be used as w3 instance ID for this credential
  208. ppCCI - Receives pointer to a Credential Cache Item
  209. pvsmc - ptr to map context using the instance specified in pvInstanceId
  210. dwInstanceId - w3 instance Id
  211. Returns:
  212. TRUE on success, FALSE on failure. If this item's key couldn't be found,
  213. then ERROR_INVALID_NAME is returned.
  214. --*/
  215. {
  216. INSTANCE_CACHE_ITEM * pcci;
  217. LIST_ENTRY * pEntry;
  218. CHAR achId[MAX_ADDRESS_LEN];
  219. // LPSTR p = achId;
  220. UINT cId = 0;
  221. /*NimishK : not needed
  222. //
  223. // build ID of this credential request : IP address + port + instance
  224. //
  225. memcpy( p, pszIpAddress, cbAddress );
  226. p += cbAddress;
  227. *p++ = ':';
  228. memcpy( p, pszPort, cbPort );
  229. p += cbPort;
  230. *p++ = ':';
  231. // An INSTANCE_CACHE_ITEM is keyed of Instance ptr
  232. // *(LPVOID*)p = pvInstanceId;
  233. // cId = sizeof(LPVOID);
  234. */
  235. RescanList:
  236. for ( pEntry = InstanceCacheList.Flink;
  237. pEntry != &InstanceCacheList;
  238. pEntry = pEntry->Flink )
  239. {
  240. pcci = CONTAINING_RECORD( pEntry, INSTANCE_CACHE_ITEM, m_ListEntry );
  241. // An INSTANCE_CACHE_ITEM is keyed of Instance ptr. Compare it.
  242. if ( pcci->m_pvInstanceId == pvInstanceId )
  243. {
  244. //
  245. // If this is an item we failed to find previously, then return
  246. // an error
  247. //
  248. if ( pcci->m_fValid )
  249. {
  250. *ppCCI = pcci->m_pcci;
  251. pcci->m_pcci->AddRef();
  252. return TRUE;
  253. }
  254. SetLastError( ERROR_INVALID_NAME );
  255. *ppCCI = NULL;
  256. return FALSE;
  257. }
  258. }
  259. //
  260. // This address isn't in the list, try getting it credential cache then
  261. // rescan the list for the new item. Note we leave the list locked
  262. // while we try and get the item. This prevents multiple threads from
  263. // trying to create the same item
  264. //
  265. if ( !AddFullyQualifiedItem( pwszServerPrefix, achId, cId, pszIpAddress, pszPort, pvInstanceId, pvsmc, dwInstanceId ))
  266. {
  267. return FALSE;
  268. }
  269. goto RescanList;
  270. }
  271. VOID
  272. ReleaseCredential(
  273. CRED_CACHE_ITEM * pcci
  274. )
  275. /*++
  276. Routine Description:
  277. Release a credential acquired via LookupFullyQualifiedCredential()
  278. Arguments:
  279. pCCI - pointer to a Credential Cache Item
  280. Returns:
  281. Nothing
  282. --*/
  283. {
  284. if ( pcci )
  285. {
  286. pcci->Release();
  287. }
  288. }
  289. //
  290. // Secret value names. Each value exist in 4 variants,
  291. // used to access the Lsa secret, the 1st one using IP + port
  292. // the 2nd one IP only, the 3rd one port only
  293. // The 4th entry specify designate the default value ( common to all address and ports )
  294. //
  295. LPSTR SecretTableA[4] =
  296. {
  297. "%s:%s", "%s", "%0.0s%s", "default",
  298. };
  299. LPWSTR SecretTableW[4] =
  300. {
  301. L"%S:%S", L"%S", L"%0.0S%S", L"default",
  302. };
  303. BOOL
  304. GetMDSecret(
  305. MB* pMB,
  306. LPSTR pszObj,
  307. DWORD dwId,
  308. UNICODE_STRING**ppusOut
  309. )
  310. {
  311. DWORD dwL = 0;
  312. PUNICODE_STRING pusOut = NULL;
  313. if ( pMB->GetData( pszObj,
  314. dwId,
  315. IIS_MD_UT_SERVER,
  316. BINARY_METADATA,
  317. NULL,
  318. &dwL,
  319. METADATA_SECURE ) || GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  320. {
  321. if ( (pusOut = (PUNICODE_STRING)LocalAlloc( LMEM_FIXED, sizeof(UNICODE_STRING) )) &&
  322. (pusOut->Buffer = (WORD*)LocalAlloc( LMEM_FIXED, dwL )) )
  323. {
  324. if ( pMB->GetData( pszObj,
  325. dwId,
  326. IIS_MD_UT_SERVER,
  327. BINARY_METADATA,
  328. pusOut->Buffer,
  329. &dwL,
  330. METADATA_SECURE ) )
  331. {
  332. pusOut->Length = pusOut->MaximumLength = (WORD)dwL;
  333. *ppusOut = pusOut;
  334. return TRUE;
  335. }
  336. }
  337. if (pusOut) {
  338. if (pusOut->Buffer) {
  339. LocalFree( pusOut->Buffer );
  340. }
  341. LocalFree( pusOut );
  342. }
  343. }
  344. return FALSE;
  345. }
  346. BOOL
  347. GetAdminSecret(
  348. WCHAR * pwszServerPrefix,
  349. IMSAdminBaseW* pAdminObj,
  350. LPWSTR pszObj,
  351. DWORD dwId,
  352. UNICODE_STRING**ppusOut
  353. )
  354. {
  355. DWORD dwL = 0;
  356. DWORD dwErr = 0;
  357. PUNICODE_STRING pusOut;
  358. HRESULT hRes = S_OK;
  359. METADATA_HANDLE RootHandle;
  360. METADATA_RECORD mdRecord;
  361. WCHAR wszMetabaseRoot[256] ;
  362. wsprintfW( wszMetabaseRoot, SSL_SERVICE_KEYS_MD_PATH_W, pwszServerPrefix ) ;
  363. hRes = pAdminObject->OpenKey(
  364. METADATA_MASTER_ROOT_HANDLE,
  365. wszMetabaseRoot,
  366. METADATA_PERMISSION_READ,
  367. 100,
  368. &RootHandle
  369. );
  370. if (FAILED(hRes)) {
  371. return FALSE ;
  372. }
  373. mdRecord.dwMDIdentifier = dwId;
  374. mdRecord.dwMDAttributes = METADATA_SECURE;
  375. mdRecord.dwMDUserType = IIS_MD_UT_SERVER;
  376. mdRecord.dwMDDataType = BINARY_METADATA;
  377. mdRecord.dwMDDataLen = dwL;
  378. mdRecord.pbMDData = NULL;
  379. hRes = pAdminObj->GetData( RootHandle,
  380. pszObj,
  381. &mdRecord,
  382. &dwL ) ;
  383. if( FAILED(hRes) && (HRESULTTOWIN32( hRes ) == ERROR_INSUFFICIENT_BUFFER) )
  384. {
  385. if ( (pusOut = (PUNICODE_STRING)LocalAlloc( LMEM_FIXED, sizeof(UNICODE_STRING) )) &&
  386. (pusOut->Buffer = (WORD*)LocalAlloc( LMEM_FIXED, dwL )) )
  387. {
  388. mdRecord.dwMDIdentifier = dwId;
  389. mdRecord.dwMDAttributes = METADATA_SECURE;
  390. mdRecord.dwMDUserType = IIS_MD_UT_SERVER;
  391. mdRecord.dwMDDataType = BINARY_METADATA;
  392. mdRecord.dwMDDataLen = dwL;
  393. mdRecord.pbMDData = (PBYTE)pusOut->Buffer;
  394. hRes = pAdminObj->GetData( RootHandle,
  395. pszObj,
  396. &mdRecord,
  397. &dwL );
  398. if( SUCCEEDED( hRes ) )
  399. {
  400. pusOut->Length = pusOut->MaximumLength = (WORD)mdRecord.dwMDDataLen;
  401. *ppusOut = pusOut;
  402. pAdminObject->CloseKey(RootHandle);
  403. return TRUE;
  404. }
  405. dwErr = GetLastError();
  406. }
  407. if (pusOut) {
  408. if (pusOut->Buffer) {
  409. LocalFree( pusOut->Buffer );
  410. }
  411. LocalFree( pusOut );
  412. }
  413. }
  414. pAdminObject->CloseKey(RootHandle);
  415. return FALSE;
  416. }
  417. BOOL
  418. AddFullyQualifiedItem(
  419. IN WCHAR * pwszServerPrefix,
  420. IN CHAR * pszId,
  421. IN UINT cId,
  422. IN CHAR * pszAddress,
  423. IN CHAR * pszPort,
  424. IN LPVOID pvInstanceId,
  425. IN PVOID pvsmc,
  426. IN DWORD dwInstanceId
  427. )
  428. /*++
  429. Routine Description:
  430. Creates a new item in the credential cache and adds it to the list
  431. pszAddress must be a simple string that has no odd unicode mappings
  432. This routine must be single threaded
  433. Arguments:
  434. pszId - ID of cache entry to add
  435. pszAddress - Address name for this credential
  436. pszPort - port for this credential
  437. pvInstanceId - ptr to be used as service instance ID for this credential
  438. pvsmc - ptr to map context using the instance specified in pvInstanceId
  439. dwInstanceId - w3 instance Id
  440. Returns:
  441. TRUE on success, FALSE on failure
  442. --*/
  443. {
  444. CHAR achSecretNameA[MAX_SECRET_NAME+1];
  445. /* // NimishK : I don't think these are used anymore
  446. //WCHAR achSecretName[MAX_SECRET_NAME+1];
  447. //UNICODE_STRING * SecretValue[3];
  448. //DWORD i;
  449. //DWORD j;
  450. */
  451. BOOL fRet = TRUE;
  452. INSTANCE_CACHE_ITEM * pcci;
  453. RefBlob* pBlob11 = NULL;
  454. RefBlob* pBlobW = NULL;
  455. CRED_CACHE_ITEM * pci;
  456. //Added for CAPI stuff
  457. IIS_SSL_INFO *pSSLInfoObj = NULL;
  458. PBYTE pbSSLBlob = NULL;
  459. PSERVICE_MAPPING_CONTEXT psmc = (PSERVICE_MAPPING_CONTEXT)pvsmc;
  460. //Need to clean this up with pvInstanceId->QueryMDPath()
  461. CHAR szMDPath[256] ;
  462. wsprintf( szMDPath, "/LM/%S/%d", pwszServerPrefix,dwInstanceId ) ;
  463. /*
  464. // Nimishk : I dont think this is needed
  465. MB mb( pMDObject );
  466. CHAR szMetabaseRoot[256] ;
  467. wsprintf( szMetabaseRoot, SSL_SERVICE_KEYS_MD_PATH, pwszServerPrefix ) ;
  468. if ( !mb.Open( szMetabaseRoot ))
  469. {
  470. return FALSE;
  471. }
  472. */
  473. /* NimishK cId is no longer used
  474. if ( cId > MAX_ADDRESS_LEN )
  475. {
  476. SetLastError( ERROR_INVALID_PARAMETER );
  477. return FALSE;
  478. }
  479. */
  480. //
  481. // Create and initialize the context item
  482. //
  483. pcci = new INSTANCE_CACHE_ITEM;
  484. if ( !pcci )
  485. {
  486. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  487. return FALSE;
  488. }
  489. // memcpy( pcci->m_achId, pszId, cId );
  490. // pcci->m_cbId = cId;
  491. pcci->m_pvInstanceId = pvInstanceId;
  492. pcci->m_fValid = FALSE;
  493. pcci->m_pcci = NULL;
  494. InsertTailList( &InstanceCacheList, &pcci->m_ListEntry );
  495. /*Nimishk : Dont need this anymore
  496. //
  497. // Retrieve the secret from the registry
  498. //
  499. fRet = FALSE;
  500. memset( SecretValue, 0, sizeof( SecretValue ));
  501. */
  502. //
  503. // Get the "SSL id" blob used to locate the CRED_CACHE_ITEM for this instance
  504. //
  505. if ( pvInstanceId )
  506. {
  507. IIS_SERVER_INSTANCE *pIISInstance = (IIS_SERVER_INSTANCE *) pvInstanceId;
  508. if ( ( pSSLInfoObj = pIISInstance->QueryAndReferenceSSLInfoObj()) &&
  509. GenerateSSLIdBlob( pSSLInfoObj,
  510. (PBYTE) achSecretNameA ) )
  511. {
  512. fRet = TRUE ;
  513. }
  514. }
  515. if ( fRet )
  516. {
  517. if( psmc )
  518. {
  519. //
  520. // Retrieve blobs pointing to cert 1:1 mapper & cert wildcard mapper
  521. //
  522. if ( !psmc->ServerSupportFunction( pvInstanceId,
  523. (LPVOID)&pBlob11,
  524. SIMSSL_PROPERTY_MTCERT11 ) )
  525. {
  526. pBlob11 = NULL;
  527. }
  528. if ( !psmc->ServerSupportFunction( pvInstanceId,
  529. (LPVOID)&pBlobW,
  530. SIMSSL_PROPERTY_MTCERTW ) )
  531. {
  532. pBlobW = NULL;
  533. }
  534. }
  535. //
  536. // All instances w/o mappers maps to NULL, so that they share a CRED_CACHE_ENTRY
  537. //
  538. if ( pBlob11 == NULL && pBlobW == NULL )
  539. {
  540. pvInstanceId = NULL;
  541. }
  542. //
  543. // try fo find it in cache
  544. // returned cache entry's refcount is incremented by LookupCredential or AddItem
  545. // if successfull
  546. //
  547. if ( !LookupCredential( (LPSTR)achSecretNameA, pvInstanceId, &pci ) )
  548. {
  549. if ( GetLastError() == ERROR_NO_MORE_ITEMS )
  550. {
  551. //
  552. // This address isn't in the list, try getting it from the lsa then
  553. // rescan the list for the new item. Note we leave the list locked
  554. // while we try and get the item. This prevents multiple threads from
  555. // trying to create the same item
  556. //
  557. if ( AddItem( (LPSTR)achSecretNameA,
  558. pvInstanceId,
  559. pBlob11,
  560. pBlobW,
  561. pSSLInfoObj,
  562. &pci,
  563. dwInstanceId,
  564. (LPSTR)szMDPath ) )
  565. {
  566. pcci->m_pcci = pci;
  567. pcci->m_fValid = TRUE;
  568. }
  569. }
  570. }
  571. else
  572. {
  573. pcci->m_pcci = pci;
  574. pcci->m_fValid = TRUE;
  575. }
  576. }
  577. //
  578. // Return TRUE to indicate we added the item to the list. If the item
  579. // wasn't found, then it's a place holder for that particular address
  580. //
  581. /* Not needed anymore
  582. for ( i = 0; i < 3; i++ )
  583. {
  584. if( SecretValue[i] != NULL )
  585. {
  586. LocalFree( SecretValue[i]->Buffer );
  587. LocalFree( SecretValue[i] );
  588. }
  589. }
  590. */
  591. //
  592. // Release blob now. CRED_CACHE_ITEM added a reference to them
  593. // if entry created
  594. //
  595. if ( pBlob11 != NULL )
  596. {
  597. pBlob11->Release();
  598. }
  599. if ( pBlobW != NULL )
  600. {
  601. pBlobW->Release();
  602. }
  603. //
  604. // Release IIS_SSL_INFO object, since we're done with it
  605. //
  606. if ( pSSLInfoObj )
  607. {
  608. IIS_SSL_INFO::Release( pSSLInfoObj );
  609. }
  610. return TRUE;
  611. }
  612. BOOL
  613. LookupCredential(
  614. IN CHAR * pszAddress,
  615. IN LPVOID pvInstanceId,
  616. OUT CRED_CACHE_ITEM * * ppCCI
  617. )
  618. /*++
  619. Routine Description:
  620. Finds an entry in the credential cache or creates one if it's not found
  621. Arguments:
  622. pszAddress - Address name for this credential
  623. pvInstanceId - ptr to be used as w3 instance ID for this credential
  624. ppCCI - Receives pointer to a Credential Cache Item
  625. Returns:
  626. TRUE on success, FALSE on failure. If this item's key couldn't be found,
  627. then ERROR_NO_MORE_ITEMS is returned.
  628. If key exist but entry invalid then ERROR_INVALID_NAME is returned.
  629. --*/
  630. {
  631. CRED_CACHE_ITEM * pcci;
  632. LIST_ENTRY * pEntry;
  633. for ( pEntry = CredCacheList.Flink;
  634. pEntry != &CredCacheList;
  635. pEntry = pEntry->Flink )
  636. {
  637. pcci = CONTAINING_RECORD( pEntry, CRED_CACHE_ITEM, m_ListEntry );
  638. if ( !memcmp( pcci->m_achSSLIdBlob, pszAddress, MAX_SSL_ID_LEN ) &&
  639. pcci->m_pvInstanceId == pvInstanceId )
  640. {
  641. //
  642. // If this is an item we failed to find previously, then return
  643. // an error
  644. //
  645. if ( pcci->m_fValid )
  646. {
  647. *ppCCI = pcci;
  648. pcci->AddRef();
  649. return TRUE;
  650. }
  651. SetLastError( ERROR_INVALID_NAME );
  652. return FALSE;
  653. }
  654. }
  655. SetLastError( ERROR_NO_MORE_ITEMS );
  656. return FALSE;
  657. }
  658. BOOL
  659. AddItem(
  660. CHAR * pszAddress,
  661. LPVOID pvInstanceId,
  662. RefBlob* pCert11,
  663. RefBlob* pCertW,
  664. IIS_SSL_INFO *pSSLInfoObj,
  665. CRED_CACHE_ITEM** ppcci,
  666. DWORD dwInstanceId,
  667. LPSTR pszMdPath
  668. )
  669. /*++
  670. Routine Description:
  671. Creates a new item in the credential cache and adds it to the list
  672. pszAddress must be a simple string that has no odd unicode mappings
  673. This routine must be single threaded
  674. Arguments:
  675. pszAddress - Address name for this credential
  676. pvInstanceId - ptr to be used as service instance ID for this credential
  677. pCert11 - ptr to blob storing cert 1:1 mapper or NULL if no mapper
  678. pCertW - ptr to blob storing cert wildcard mapper or NULL if no mapper
  679. pSSLInfObj - pointer to SSL info to be used for this item
  680. ppCCI - Receives pointer to a Credential Cache Item
  681. dwInstanceId - w3 instance ID
  682. Returns:
  683. TRUE on success, FALSE on failure
  684. --*/
  685. {
  686. BOOL fRet = TRUE;
  687. BOOL fRetM;
  688. BOOL fRetL;
  689. CRED_CACHE_ITEM * pcci;
  690. //
  691. // Create and initialize the context item
  692. //
  693. pcci = new CRED_CACHE_ITEM;
  694. if ( !pcci )
  695. {
  696. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  697. return FALSE;
  698. }
  699. memcpy( pcci->m_achSSLIdBlob, pszAddress, MAX_SSL_ID_LEN );
  700. pcci->m_pvInstanceId = pvInstanceId;
  701. memset( pcci->m_ahCred, 0, sizeof( pcci->m_ahCred ));
  702. memset( pcci->m_ahCredMap, 0, sizeof( pcci->m_ahCredMap ));
  703. memset( pcci->m_acbTrailer, 0, sizeof( pcci->m_acbTrailer ));
  704. memset( pcci->m_acbHeader, 0, sizeof( pcci->m_acbHeader ));
  705. InsertTailList( &CredCacheList, &pcci->m_ListEntry );
  706. //
  707. // build cert mapper DLLs array
  708. //
  709. if ( fRetM = InitializeCertMapping( pCert11 ? pCert11->QueryPtr() : NULL,
  710. pCertW ? pCertW->QueryPtr() : NULL,
  711. pSSLInfoObj ? (LPVOID) pSSLInfoObj : NULL,
  712. &pcci->m_ppMappers,
  713. &pcci->m_cNbMappers,
  714. dwInstanceId ) )
  715. {
  716. //
  717. // LoadKeys will zero out these values on success or failure. Note
  718. // the password is stored as an ansi string because the SSL
  719. // security structure is expecting an ANSI string
  720. //
  721. fRetL = LoadKeys( pSSLInfoObj,
  722. pvInstanceId,
  723. pcci->m_ppMappers,
  724. pcci->m_cNbMappers,
  725. pcci->m_ahCred,
  726. &pcci->m_cCred,
  727. pcci->m_ahCredMap,
  728. &pcci->m_cCredMap,
  729. pszMdPath );
  730. }
  731. else
  732. {
  733. fRetL = FALSE;
  734. }
  735. //
  736. // Indicate the credential handle is valid on this address if we
  737. // succeeded
  738. //
  739. if ( fRetL && fRetM )
  740. {
  741. pcci->m_fValid = TRUE;
  742. }
  743. else
  744. {
  745. pCert11 = NULL;
  746. pCertW = NULL;
  747. if ( fRetM && !fRetL )
  748. {
  749. TerminateCertMapping( pcci->m_ppMappers, pcci->m_cNbMappers );
  750. pcci->m_ppMappers = NULL;
  751. pcci->m_cNbMappers = 0;
  752. }
  753. }
  754. //
  755. // Store reference to mappers
  756. //
  757. if ( pcci->m_pBlob11 = pCert11 )
  758. {
  759. pCert11->AddRef();
  760. }
  761. if ( pcci->m_pBlobW = pCertW )
  762. {
  763. pCertW->AddRef();
  764. }
  765. //
  766. // Store reference to SSL info
  767. //
  768. if ( pcci->m_pSslInfo = pSSLInfoObj )
  769. {
  770. pSSLInfoObj->Reference();
  771. }
  772. //
  773. // Add ref, as will be referenced by *ppcci
  774. //
  775. pcci->AddRef();
  776. *ppcci = pcci;
  777. //
  778. // Return TRUE to indicate we added the item to the list. If the item
  779. // wasn't found, then it's a place holder for that particular address
  780. //
  781. return TRUE;
  782. }
  783. BOOL
  784. LoadKeys(
  785. IN IIS_SSL_INFO *pSSLInfoObj,
  786. IN PVOID pvInstance,
  787. IN HMAPPER** ppMappers,
  788. IN DWORD cNbMappers,
  789. OUT CredHandle * phCreds,
  790. OUT DWORD * pcCred,
  791. OUT CredHandle * phCredsMap,
  792. OUT DWORD * pcCredMap,
  793. IN LPSTR pszMdPath
  794. )
  795. /*++
  796. Routine Description:
  797. Finds an entry in the credential cache or creates one if it's not found
  798. Arguments:
  799. pSSLInfoObj - object containing SSL info to be used for this credential set
  800. ppMappers - ptr to array of mapper DLLs
  801. cNbMappers - number of entry in ppMappers
  802. phCreds - ptr to array where to store credential handles w/o cert mapping
  803. pcCred - ptr to counter where to store number of entry in phCreds
  804. phCredsMap - ptr to array where to store credential handles w/ cert mapping
  805. pcCredMap - ptr to counter where to store number of entry in phCredsMap
  806. pszMdPath - path to metabase properties
  807. Returns:
  808. TRUE on success, FALSE on failure.
  809. --*/
  810. {
  811. ASSERT( RtlValidateHeap( RtlProcessHeap(), 0, NULL ) );
  812. //SCH_CRED creds;
  813. // CAPI stuff
  814. SCHANNEL_CRED xcreds;
  815. HCERTSTORE hRootStore;
  816. /*NimishK
  817. // SCH_CRED_SECRET_CAPI scsp;
  818. // SCH_CRED_PUBLIC_CERTCHAIN scpc;
  819. */
  820. SECURITY_STATUS scRet;
  821. SECURITY_STATUS scRetM;
  822. TimeStamp tsExpiry;
  823. DWORD i;
  824. /*NimishK
  825. // LPVOID ascsp[1];
  826. // LPVOID ascpc[1];
  827. // DWORD dwV;
  828. // MB mb( pMDObject );
  829. // BUFFER buAlg;
  830. */
  831. // Added for CAPI stuff
  832. PCCERT_CONTEXT pcCert = NULL;
  833. LPVOID pcreds;
  834. *pcCred = 0;
  835. *pcCredMap = 0;
  836. memset(&xcreds, 0, sizeof(xcreds));
  837. xcreds.dwVersion = SCHANNEL_CRED_VERSION;
  838. if ( pSSLInfoObj->GetCertificate() &&
  839. pSSLInfoObj->GetCertificate()->IsValid() )
  840. {
  841. xcreds.cCreds = 1;
  842. xcreds.paCred = pSSLInfoObj->GetCertificate()->QueryCertContextAddr();
  843. }
  844. else
  845. {
  846. return TRUE;
  847. }
  848. xcreds.cMappers = cNbMappers ;
  849. xcreds.aphMappers = ppMappers;
  850. if (pSSLInfoObj->GetTrustedIssuerStore( &hRootStore ))
  851. {
  852. xcreds.hRootStore = hRootStore;
  853. }
  854. else
  855. {
  856. xcreds.hRootStore = NULL;
  857. }
  858. pcreds = (LPVOID) &xcreds;
  859. for ( i = 0; pEncProviders[i].pszName && i < MAX_PROVIDERS; i++ )
  860. {
  861. if ( !pEncProviders[i].fEnabled )
  862. {
  863. continue;
  864. }
  865. //creds.cMappers = 0;
  866. //CAPI
  867. // Credentials with no client cert mapping at all
  868. //
  869. ((SCHANNEL_CRED*)pcreds)->cMappers = 0;
  870. ((SCHANNEL_CRED*)pcreds)->dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
  871. ASSERT( RtlValidateHeap( RtlProcessHeap(), 0, NULL ) );
  872. scRet = g_AcquireCredentialsHandle( NULL, // My name (ignored)
  873. pEncProviders[i].pszName, // Package
  874. SECPKG_CRED_INBOUND,// Use
  875. NULL, // Logon Id (ign.)
  876. pcreds, // auth data
  877. NULL, // dce-stuff
  878. NULL, // dce-stuff
  879. &phCreds[*pcCred], // Handle
  880. &tsExpiry );
  881. PRINTF((buff, "Cred %08x:%08x : mapper %08x\n", phCreds[*pcCred], NULL ));
  882. //
  883. // DS mapper only - no mappers passed to AcquireCredentialsHandle(), clear the flag
  884. // telling Schannel not to use the DS mapper
  885. //
  886. if ( pSSLInfoObj->UseDSMapper() )
  887. {
  888. ((SCHANNEL_CRED*)pcreds)->cMappers = 0;
  889. ((SCHANNEL_CRED*)pcreds)->dwFlags = 0;
  890. // DBGPRINTF((DBG_CONTEXT,
  891. // "[SSPIFILT] Using DS mapper \n"));
  892. }
  893. //
  894. // IIS mappers only - pass mappers to AcquireCredentialsHandle(), set flag in each one
  895. // indicating that only IIS mappers are to be called, keep flag telling Schannel
  896. // not to use DS mapper [set to SCH_CRED_NO_SYSTEM_MAPPER above]
  897. //
  898. else
  899. {
  900. ((SCHANNEL_CRED*)pcreds)->cMappers = cNbMappers;
  901. for ( DWORD dwI = 0; dwI < cNbMappers; dwI++ )
  902. {
  903. ((SCHANNEL_CRED*)pcreds)->aphMappers[dwI]->m_dwFlags = SCH_FLAG_DEFAULT_MAPPER;
  904. }
  905. // DebugTrace(NULL,
  906. // "[SSPIFILT] Using IIS mappers \n"));
  907. }
  908. //creds.cMappers = cNbMappers;
  909. ASSERT( RtlValidateHeap( RtlProcessHeap(), 0, NULL ) );
  910. scRetM = g_AcquireCredentialsHandle( NULL, // My name (ignored)
  911. pEncProviders[i].pszName, // Package
  912. SECPKG_CRED_INBOUND,// Use
  913. NULL, // Logon Id (ign.)
  914. pcreds, // auth data
  915. NULL, // dce-stuff
  916. NULL, // dce-stuff
  917. &phCredsMap[*pcCredMap], // Handle
  918. &tsExpiry );
  919. //PRINTF((buff, "Cred %08x:%08x : mapper %08x\n", phCredsMap[*pcCredMap], creds.aphMappers ));
  920. // Null out creds, it doesn't seem to be used
  921. PRINTF( (buff, "Cred %08x:%08x ", phCredsMap[*pcCredMap] ));
  922. ASSERT( RtlValidateHeap( RtlProcessHeap(), 0, NULL ) );
  923. if ( !FAILED( scRetM ) && !FAILED( scRet ) )
  924. {
  925. *pcCred += 1;
  926. *pcCredMap += 1;
  927. }
  928. }
  929. if ( xcreds.hRootStore )
  930. {
  931. CertCloseStore( xcreds.hRootStore,
  932. 0 );
  933. }
  934. //
  935. // Tell the caller about it.
  936. //
  937. if ( !*pcCred && FAILED( scRet ))
  938. {
  939. SetLastError( scRet );
  940. return FALSE;
  941. }
  942. return TRUE;
  943. }
  944. BOOL
  945. GetSecretW(
  946. WCHAR * pszSecretName,
  947. UNICODE_STRING * * ppSecretValue
  948. )
  949. /*++
  950. Description:
  951. Retrieves the specified unicode secret
  952. Arguments:
  953. pszSecretName - LSA Secret to retrieve
  954. ppSecretValue - Receives pointer to secret value. Memory should be
  955. freed by calling LsaFreeMemory
  956. Returns:
  957. TRUE on success and FALSE if any failure.
  958. --*/
  959. {
  960. BOOL fResult;
  961. NTSTATUS ntStatus;
  962. LSA_UNICODE_STRING unicodeSecret;
  963. LSA_HANDLE hPolicy;
  964. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  965. //
  966. // Open a policy to the remote LSA
  967. //
  968. InitializeObjectAttributes( &ObjectAttributes,
  969. NULL,
  970. 0L,
  971. NULL,
  972. NULL );
  973. ntStatus = LsaOpenPolicy( NULL,
  974. &ObjectAttributes,
  975. POLICY_ALL_ACCESS,
  976. &hPolicy );
  977. if ( !NT_SUCCESS( ntStatus ) )
  978. {
  979. SetLastError( LsaNtStatusToWinError( ntStatus ) );
  980. return FALSE;
  981. }
  982. unicodeSecret.Buffer = pszSecretName;
  983. unicodeSecret.Length = wcslen( pszSecretName ) * sizeof(WCHAR);
  984. unicodeSecret.MaximumLength = unicodeSecret.Length + sizeof(WCHAR);
  985. //
  986. // Query the secret value.
  987. //
  988. ntStatus = LsaRetrievePrivateData( hPolicy,
  989. &unicodeSecret,
  990. (PLSA_UNICODE_STRING *) ppSecretValue );
  991. fResult = NT_SUCCESS(ntStatus);
  992. //
  993. // Cleanup & exit.
  994. //
  995. LsaClose( hPolicy );
  996. if ( !fResult )
  997. SetLastError( LsaNtStatusToWinError( ntStatus ));
  998. return fResult;
  999. } // GetSecretW
  1000. BOOL
  1001. InitializeCertMapping(
  1002. LPVOID pCert11,
  1003. LPVOID pCertW,
  1004. LPVOID pSslInfo,
  1005. HMAPPER*** pppMappers,
  1006. LPDWORD pdwMappers,
  1007. DWORD dwInstanceId
  1008. )
  1009. /*++
  1010. Description:
  1011. Initialize the cert mapping DLL list
  1012. Arguments:
  1013. None
  1014. Returns:
  1015. TRUE on success and FALSE if any failure.
  1016. --*/
  1017. {
  1018. HKEY hKey;
  1019. DWORD dwType;
  1020. DWORD cbData;
  1021. BOOL fSt = TRUE;
  1022. LPSTR pszMapList = NULL;
  1023. LPSTR p;
  1024. LPSTR pDll;
  1025. UINT cMaxMap;
  1026. PFN_INIT_CERT_MAP pfnInit;
  1027. HINSTANCE hInst;
  1028. PMAPPER_VTABLE pVT;
  1029. DWORD cNbMappers = 0;
  1030. HMAPPER** ppMappers = NULL;
  1031. IisMapper* pIM;
  1032. if ( pCert11 == NULL && pCertW == NULL )
  1033. {
  1034. *pppMappers = NULL;
  1035. *pdwMappers = 0;
  1036. return TRUE;
  1037. }
  1038. //
  1039. // Open reg, count # mappers, allocate array, populate array
  1040. //
  1041. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1042. W3_PARAMETERS_KEY,
  1043. 0,
  1044. KEY_ALL_ACCESS,
  1045. &hKey ) == NO_ERROR )
  1046. {
  1047. if ( RegQueryValueEx( hKey,
  1048. SSPIFILT_CERT_MAP_LIST,
  1049. NULL,
  1050. &dwType,
  1051. NULL,
  1052. &cbData ) == ERROR_SUCCESS &&
  1053. dwType == REG_SZ &&
  1054. (pszMapList = (LPSTR)LocalAlloc( LMEM_FIXED, cbData )) &&
  1055. RegQueryValueEx( hKey,
  1056. SSPIFILT_CERT_MAP_LIST,
  1057. NULL,
  1058. &dwType,
  1059. (LPBYTE)pszMapList,
  1060. &cbData ) == ERROR_SUCCESS )
  1061. {
  1062. //
  1063. // Count mappers, allocate structures
  1064. //
  1065. for ( cMaxMap = 1, p = pszMapList ;
  1066. p = strchr( p, ',' ) ;
  1067. ++p, ++cMaxMap )
  1068. {
  1069. }
  1070. if ( !(ppMappers = (HMAPPER**)LocalAlloc( LMEM_FIXED,
  1071. sizeof(HMAPPER*) * cMaxMap )) )
  1072. {
  1073. fSt = FALSE;
  1074. goto cleanup;
  1075. }
  1076. //
  1077. // Load libraries, call init entry point
  1078. //
  1079. for ( pDll = pszMapList, cNbMappers = 0 ;
  1080. *pDll ;
  1081. )
  1082. {
  1083. p = strchr( pDll, ',' );
  1084. if ( p )
  1085. {
  1086. *p = '\0';
  1087. }
  1088. if ( (hInst = LoadLibrary( pDll )) )
  1089. {
  1090. //
  1091. // Use CreateInstance() entry point if present
  1092. //
  1093. if ( (pfnInit = (PFN_INIT_CERT_MAP)GetProcAddress(
  1094. hInst,
  1095. SSPIFILT_INIT_MAP )) )
  1096. {
  1097. if ( SEC_E_OK != (pfnInit)( (HMAPPER**)&pIM ) )
  1098. {
  1099. FreeLibrary( hInst );
  1100. goto next;
  1101. }
  1102. //
  1103. // Mapper handle its own HMAPPER allocation,
  1104. // will be freed when refcount drops to zero.
  1105. // Initial refcount is 1
  1106. //
  1107. ppMappers[cNbMappers] = (HMAPPER*)pIM;
  1108. pIM->pCert11Mapper = pCert11;
  1109. pIM->pCertWMapper = pCertW;
  1110. pIM->pvInfo = pSslInfo;
  1111. //Nimishk : Not sure if this is needed
  1112. pIM->dwInstanceId = dwInstanceId;
  1113. }
  1114. else
  1115. {
  1116. pIM = (IisMapper*)LocalAlloc( LMEM_FIXED, sizeof(IisMapper) );
  1117. ppMappers[cNbMappers] = (HMAPPER*)pIM;
  1118. pIM->hMapper.m_vtable = pVT = &pIM->mvtEntryPoints;
  1119. pIM->hMapper.m_dwMapperVersion = MAPPER_INTERFACE_VER;
  1120. pIM->hMapper.m_Reserved1 = NULL;
  1121. pIM->hInst = hInst;
  1122. pIM->lRefCount = 0;
  1123. pIM->fIsIisCompliant = FALSE;
  1124. pIM->pCert11Mapper = pCert11;
  1125. pIM->pCertWMapper = pCertW;
  1126. pIM->pvInfo = pSslInfo;
  1127. pIM->dwInstanceId = dwInstanceId;
  1128. if ( !(pVT->ReferenceMapper
  1129. = (REF_MAPPER_FN)GetProcAddress(
  1130. hInst,
  1131. "ReferenceMapper" )) ||
  1132. !(pVT->DeReferenceMapper
  1133. = (DEREF_MAPPER_FN)GetProcAddress(
  1134. hInst,
  1135. "DeReferenceMapper" )) ||
  1136. !(pVT->GetIssuerList
  1137. = (GET_ISSUER_LIST_FN)GetProcAddress(
  1138. hInst,
  1139. "GetIssuerList" )) ||
  1140. !(pVT->GetChallenge
  1141. = (GET_CHALLENGE_FN)GetProcAddress(
  1142. hInst,
  1143. "GetChallenge" )) ||
  1144. !(pVT->MapCredential
  1145. = (MAP_CREDENTIAL_FN)GetProcAddress(
  1146. hInst,
  1147. "MapCredential" )) ||
  1148. !(pVT->GetAccessToken
  1149. = (GET_ACCESS_TOKEN_FN)GetProcAddress(
  1150. hInst,
  1151. "GetAccessToken" )) ||
  1152. !(pVT->CloseLocator
  1153. = (CLOSE_LOCATOR_FN)GetProcAddress(
  1154. hInst,
  1155. "CloseLocator" ))
  1156. )
  1157. {
  1158. LocalFree( pIM );
  1159. FreeLibrary( hInst );
  1160. goto next;
  1161. }
  1162. //
  1163. // optional functions
  1164. //
  1165. if ( !(pVT->QueryMappedCredentialAttributes
  1166. = (QUERY_MAPPED_CREDENTIAL_ATTRIBUTES_FN)GetProcAddress(
  1167. hInst,
  1168. "QueryMappedCredentialAttributes" )) )
  1169. {
  1170. pVT->QueryMappedCredentialAttributes = NullQueryMappedCredentialAttributes;
  1171. }
  1172. }
  1173. //
  1174. // Valid mapper. Store reference
  1175. //
  1176. ++cNbMappers;
  1177. }
  1178. next:
  1179. if ( p )
  1180. {
  1181. pDll = p + 1;
  1182. }
  1183. else
  1184. {
  1185. break;
  1186. }
  1187. }
  1188. }
  1189. else
  1190. {
  1191. fSt = FALSE;
  1192. }
  1193. RegCloseKey( hKey );
  1194. }
  1195. cleanup:
  1196. if ( fSt == FALSE )
  1197. {
  1198. if ( ppMappers != NULL )
  1199. {
  1200. LocalFree( ppMappers );
  1201. }
  1202. }
  1203. else
  1204. {
  1205. *pppMappers = ppMappers;
  1206. *pdwMappers = cNbMappers;
  1207. }
  1208. if ( pszMapList != NULL )
  1209. {
  1210. LocalFree( pszMapList );
  1211. }
  1212. return fSt;
  1213. }
  1214. VOID
  1215. SetMapperToEmpty(
  1216. UINT cMappers,
  1217. HMAPPER** pMappers
  1218. )
  1219. /*++
  1220. Description:
  1221. Set ptr to Null mapper ( fail Mapping requests )
  1222. Arguments:
  1223. cMappers - mapper count in pCertMapDlls, pMappers
  1224. pMappers - ptr to array of mappers
  1225. Returns:
  1226. Nothing
  1227. --*/
  1228. {
  1229. PMAPPER_VTABLE pTbl;
  1230. while ( cMappers-- )
  1231. {
  1232. if ( (*(IisMapper**)pMappers)->fIsIisCompliant )
  1233. {
  1234. pTbl = (*pMappers)->m_vtable;
  1235. //
  1236. // switch to infocomm-embedded mapper, so we can FreeLibrary the
  1237. // mapper DLL. refcount is decremented, because we now longer
  1238. // have a reference to the HMAPPER struct.
  1239. //
  1240. pTbl->ReferenceMapper = NullReferenceMapper;
  1241. pTbl->DeReferenceMapper = NullDeReferenceMapper;
  1242. pTbl->GetIssuerList = NullGetIssuerList;
  1243. pTbl->GetChallenge = NullGetChallenge;
  1244. pTbl->MapCredential = NullMapCredential;
  1245. pTbl->GetAccessToken = NullGetAccessToken;
  1246. pTbl->CloseLocator = NullCloseLocator;
  1247. pTbl->QueryMappedCredentialAttributes = NullQueryMappedCredentialAttributes;
  1248. if ( (*(IisMapper**)pMappers)->hInst != NULL )
  1249. {
  1250. FreeLibrary( (*(IisMapper**)pMappers)->hInst );
  1251. }
  1252. (pTbl->DeReferenceMapper)( *pMappers );
  1253. }
  1254. ++pMappers;
  1255. }
  1256. }
  1257. BOOL
  1258. TerminateCertMapping(
  1259. HMAPPER** ppMappers,
  1260. DWORD cNbMappers
  1261. )
  1262. /*++
  1263. Description:
  1264. Terminate access to cert mapping DLL list
  1265. Arguments:
  1266. None
  1267. Returns:
  1268. TRUE on success and FALSE if any failure.
  1269. --*/
  1270. {
  1271. //
  1272. // call terminate mapper for all DLLs, FreeLibrary
  1273. //
  1274. if ( ppMappers != NULL )
  1275. {
  1276. SetMapperToEmpty( cNbMappers, ppMappers );
  1277. LocalFree( ppMappers );
  1278. }
  1279. return TRUE;
  1280. }
  1281. CRED_CACHE_ITEM::~CRED_CACHE_ITEM(
  1282. )
  1283. {
  1284. if ( m_fValid )
  1285. {
  1286. DWORD i;
  1287. for ( i = 0; i < m_cCred; i++ )
  1288. {
  1289. g_FreeCredentialsHandle( &m_ahCred[i] );
  1290. }
  1291. for ( i = 0; i < m_cCredMap; i++ )
  1292. {
  1293. g_FreeCredentialsHandle( &m_ahCredMap[i] );
  1294. }
  1295. TerminateCertMapping( m_ppMappers, m_cNbMappers );
  1296. if ( m_pBlob11 )
  1297. {
  1298. m_pBlob11->Release();
  1299. }
  1300. if ( m_pBlobW )
  1301. {
  1302. m_pBlobW->Release();
  1303. }
  1304. if ( m_pSslInfo )
  1305. {
  1306. IIS_SSL_INFO::Release( m_pSslInfo );
  1307. }
  1308. }
  1309. }
  1310. BOOL
  1311. LookupClientCredential(
  1312. IN WCHAR* pwszServerPrefix,
  1313. IN BOOL fUseCertificate,
  1314. OUT CRED_CACHE_ITEM** ppCCI
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. Finds an entry in the credential cache or creates one if it's not found
  1319. Arguments:
  1320. fUseCertificate - if TRUE, binds client certificate to cred handle
  1321. ppCCI - Receives pointer to a Credential Cache Item
  1322. Returns:
  1323. TRUE on success, FALSE on failure. If this item's key couldn't be found,
  1324. then ERROR_INVALID_NAME is returned.
  1325. --*/
  1326. {
  1327. TimeStamp tsExpiry;
  1328. DWORD i, j;
  1329. CredHandle* phCreds;
  1330. DWORD* pcCred;
  1331. BOOL fCertSet = FALSE;
  1332. WCHAR achSecretName[MAX_SECRET_NAME+1];
  1333. //CHAR achSecretNameA[MAX_SECRET_NAME+1];
  1334. UNICODE_STRING* SecretValue[3];
  1335. PVOID pvPublicKey;
  1336. DWORD cbPublicKey;
  1337. PVOID pvPrivateKey;
  1338. DWORD cbPrivateKey;
  1339. CHAR * pszPassword;
  1340. SCH_CRED creds;
  1341. SCH_CRED_SECRET_PRIVKEY scsp;
  1342. SCH_CRED_PUBLIC_CERTCHAIN scpc;
  1343. SECURITY_STATUS scRet;
  1344. //SECURITY_STATUS scRetM;
  1345. LPVOID ascsp[1];
  1346. LPVOID ascpc[1];
  1347. //TraceFunctEnter( "LookupClientCredential" );
  1348. *ppCCI = NULL;
  1349. //
  1350. // first time thru allocate the single cache entry
  1351. //
  1352. if ( g_pcciClient == NULL )
  1353. {
  1354. g_pcciClient = new CRED_CACHE_ITEM;
  1355. if ( g_pcciClient == NULL )
  1356. {
  1357. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1358. return FALSE;
  1359. }
  1360. //pcciClient->m_cbAddr = 0;
  1361. g_pcciClient->m_cCred = 0;
  1362. g_pcciClient->m_cCredMap = 0;
  1363. g_pcciClient->m_fValid = FALSE;
  1364. g_pcciClient->m_cNbMappers = 0;
  1365. g_pcciClient->m_ppMappers = NULL;
  1366. g_pcciClient->m_pBlob11 = NULL;
  1367. g_pcciClient->m_pBlobW = NULL;
  1368. memset( g_pcciClient->m_ahCred, 0, sizeof( g_pcciClient->m_ahCred ));
  1369. memset( g_pcciClient->m_ahCredMap, 0, sizeof( g_pcciClient->m_ahCredMap ));
  1370. memset( g_pcciClient->m_acbTrailer, 0, sizeof( g_pcciClient->m_acbTrailer ));
  1371. memset( g_pcciClient->m_acbHeader, 0, sizeof( g_pcciClient->m_acbHeader ));
  1372. memset( g_pcciClient->m_acbBlockSize, 0, sizeof( g_pcciClient->m_acbBlockSize ));
  1373. //
  1374. // only the provider name is required for OUTBOUND connections
  1375. //
  1376. phCreds = g_pcciClient->m_ahCred;
  1377. pcCred = &g_pcciClient->m_cCred;
  1378. memset( SecretValue, 0, sizeof( SecretValue ));
  1379. if( fUseCertificate )
  1380. {
  1381. //
  1382. // get certificate from metabase and fill in SCH_CRED struct
  1383. //
  1384. //
  1385. // Try the 4 possible secret names
  1386. //
  1387. for ( j = 0 ; j < 4 ; ++j )
  1388. {
  1389. wsprintfW( achSecretName,
  1390. SecretTableW[j],
  1391. L"127.0.0.1", L"563" );
  1392. if ( GetAdminSecret( pwszServerPrefix,
  1393. pAdminObject,
  1394. achSecretName,
  1395. MD_SSL_PUBLIC_KEY,
  1396. &SecretValue[0] ) &&
  1397. GetAdminSecret( pwszServerPrefix,
  1398. pAdminObject,
  1399. achSecretName,
  1400. MD_SSL_PRIVATE_KEY,
  1401. &SecretValue[1] ) &&
  1402. GetAdminSecret( pwszServerPrefix,
  1403. pAdminObject,
  1404. achSecretName,
  1405. MD_SSL_KEY_PASSWORD,
  1406. &SecretValue[2] ) )
  1407. {
  1408. fCertSet = TRUE;
  1409. pvPublicKey = SecretValue[0]->Buffer;
  1410. cbPublicKey = SecretValue[0]->Length;
  1411. pvPrivateKey = SecretValue[1]->Buffer;
  1412. cbPrivateKey = SecretValue[1]->Length;
  1413. pszPassword = (char*) SecretValue[2]->Buffer;
  1414. break;
  1415. }
  1416. }
  1417. if( fCertSet )
  1418. {
  1419. //*pcCred = 0;
  1420. scsp.dwType = SCHANNEL_SECRET_PRIVKEY;
  1421. scsp.pPrivateKey = ((PBYTE)pvPrivateKey);
  1422. scsp.cbPrivateKey = cbPrivateKey;
  1423. scsp.pszPassword = pszPassword;
  1424. scpc.dwType = SCH_CRED_X509_CERTCHAIN;
  1425. scpc.cbCertChain = cbPublicKey - CERT_DER_PREFIX;
  1426. scpc.pCertChain = ((PBYTE) pvPublicKey) + CERT_DER_PREFIX;
  1427. creds.dwVersion = SCH_CRED_VERSION;
  1428. ascsp[0] = (LPVOID)&scsp;
  1429. ascpc[0] = (LPVOID)&scpc;
  1430. creds.paSecret = (LPVOID*)&ascsp;
  1431. creds.paPublic = (LPVOID*)&ascpc;
  1432. creds.cCreds = 1;
  1433. creds.cMappers = 0;
  1434. }
  1435. }
  1436. for ( i = 0; pEncProviders[i].pszName && i < MAX_PROVIDERS; i++ )
  1437. {
  1438. if ( !pEncProviders[i].fEnabled )
  1439. {
  1440. //DebugTrace( 0, "%s disabled", EncProviders[i].pszName );
  1441. continue;
  1442. }
  1443. scRet = g_AcquireCredentialsHandle( NULL, // My name (ignored)
  1444. pEncProviders[i].pszName, // Package
  1445. SECPKG_CRED_OUTBOUND, // Use
  1446. NULL, // Logon Id (ign.)
  1447. fCertSet ? &creds : NULL, // auth data
  1448. NULL, // dce-stuff
  1449. NULL, // dce-stuff
  1450. &phCreds[*pcCred], // Handle
  1451. &tsExpiry );
  1452. if ( !FAILED( scRet ))
  1453. {
  1454. //DebugTrace( 0, "%s credential: 0x%08X",
  1455. // EncProviders[i].pszName,
  1456. // phCreds[*pcCred] );
  1457. *pcCred += 1;
  1458. }
  1459. }
  1460. if( fCertSet )
  1461. {
  1462. //
  1463. // Zero out and free the key data memory, on success or fail
  1464. //
  1465. ZeroMemory( scsp.pPrivateKey, scsp.cbPrivateKey );
  1466. ZeroMemory( scpc.pCertChain, scpc.cbCertChain );
  1467. ZeroMemory( pszPassword, strlen( pszPassword ));
  1468. }
  1469. for ( i = 0; i < 3; i++ )
  1470. {
  1471. if( SecretValue[i] != NULL )
  1472. {
  1473. LocalFree( SecretValue[i]->Buffer );
  1474. LocalFree( SecretValue[i] );
  1475. }
  1476. }
  1477. //
  1478. // Tell the caller about it.
  1479. //
  1480. if ( !*pcCred && FAILED( scRet ))
  1481. {
  1482. SetLastError( scRet );
  1483. return FALSE;
  1484. }
  1485. else
  1486. {
  1487. g_pcciClient->m_fValid = TRUE;
  1488. g_pcciClient->AddRef();
  1489. *ppCCI = g_pcciClient;
  1490. return TRUE;
  1491. }
  1492. }
  1493. else if ( g_pcciClient->m_fValid == FALSE )
  1494. {
  1495. //
  1496. // cache was allocated but the initialization failed
  1497. //
  1498. SetLastError( ERROR_INVALID_NAME );
  1499. return FALSE;
  1500. }
  1501. else
  1502. {
  1503. //
  1504. // cache was successfully allocated and initialized on a previous call
  1505. //
  1506. g_pcciClient->AddRef();
  1507. *ppCCI = g_pcciClient;
  1508. return TRUE;
  1509. }
  1510. }
  1511. BOOL GenerateSSLIdBlob( IIS_SSL_INFO *pSSLInfoObj,
  1512. PBYTE pbBlob )
  1513. /*++
  1514. Description
  1515. Function called to get blob of data that uniquely identifies this set of SSL info
  1516. Arguments:
  1517. pSSLInfoObj - object containing SSL info to be used to generate the blob
  1518. pbBlob - buffer that gets updated with blob
  1519. Returns:
  1520. True on success, FALSE on failure
  1521. --*/
  1522. {
  1523. //
  1524. // If we haven't loaded the info yet, do so now
  1525. //
  1526. IIS_SERVER_CERT *pCert = pSSLInfoObj->GetCertificate();
  1527. IIS_CTL *pCTL = pSSLInfoObj->GetCTL();
  1528. //
  1529. // Definitely need a certificate
  1530. //
  1531. if ( !pCert || !pCert->IsValid())
  1532. {
  1533. return FALSE;
  1534. }
  1535. DWORD dwSize = MAX_SSL_ID_LEN;
  1536. PBYTE pbCurrent = pbBlob;
  1537. //
  1538. // Clear out old crud
  1539. //
  1540. memset( pbBlob, 0, MAX_SSL_ID_LEN );
  1541. //
  1542. //Try to get the cert hash
  1543. //
  1544. if ( !CertGetCertificateContextProperty( pCert->QueryCertContext(),
  1545. CERT_SHA1_HASH_PROP_ID,
  1546. (PVOID) pbCurrent,
  1547. &dwSize ) )
  1548. {
  1549. return FALSE;
  1550. }
  1551. ASSERT( dwSize == SHA1_HASH_LEN );
  1552. pbCurrent += dwSize;
  1553. dwSize = MAX_SSL_ID_LEN - dwSize - 1;
  1554. //
  1555. // Get and append the CTL hash, if there is one
  1556. //
  1557. if ( pCTL && pCTL->IsValid() )
  1558. {
  1559. if ( !CertGetCTLContextProperty( pCTL->QueryCTLContext(),
  1560. CERT_SHA1_HASH_PROP_ID,
  1561. (PVOID) pbCurrent,
  1562. &dwSize ) )
  1563. {
  1564. return FALSE;
  1565. }
  1566. ASSERT( dwSize == SHA1_HASH_LEN );
  1567. pbBlob[SHA1_HASH_LEN] = ':';
  1568. }
  1569. return TRUE;
  1570. }