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.

1119 lines
29 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name :
  4. siteconfig.cxx
  5. Abstract:
  6. SSL configuration for a given site
  7. Author:
  8. Bilal Alam (BAlam) 29-March-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. Stream Filter Worker Process
  13. --*/
  14. #include "precomp.hxx"
  15. ENDPOINT_CONFIG_HASH * ENDPOINT_CONFIG::sm_pEndpointConfigHash;
  16. ENDPOINT_CONFIG::INIT_STATE ENDPOINT_CONFIG::sm_InitState = INIT_NONE;
  17. HANDLE ENDPOINT_CONFIG::sm_hHttpApiConfigChangeEvent = NULL;
  18. HKEY ENDPOINT_CONFIG::sm_hHttpApiConfigKey = NULL;
  19. HANDLE ENDPOINT_CONFIG::sm_hWaitHandle = NULL;
  20. //static
  21. HRESULT
  22. ENDPOINT_CONFIG::Initialize(
  23. VOID
  24. )
  25. /*++
  26. Routine Description:
  27. Initialize site configuration globals
  28. Arguments:
  29. None
  30. Return Value:
  31. HRESULT
  32. --*/
  33. {
  34. HRESULT hr = E_FAIL;
  35. DWORD dwError = NO_ERROR;
  36. HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_1;
  37. //
  38. // Initialize HttpApi to be able to retrieve SSL config
  39. //
  40. dwError = HttpInitialize( HttpApiVersion, HTTP_INITIALIZE_CONFIG, NULL );
  41. if ( dwError != NO_ERROR )
  42. {
  43. hr = HRESULT_FROM_WIN32( dwError );
  44. goto Failed;
  45. }
  46. sm_InitState = INIT_HTTPAPI;
  47. sm_pEndpointConfigHash = new ENDPOINT_CONFIG_HASH();
  48. if ( sm_pEndpointConfigHash == NULL )
  49. {
  50. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  51. goto Failed;
  52. }
  53. sm_InitState = INIT_HASH;
  54. //
  55. // Create event for HttpApi config store change notifications
  56. //
  57. sm_hHttpApiConfigChangeEvent = CreateEvent( NULL, // SD
  58. FALSE, // fManualReset
  59. FALSE, //fInitialState
  60. NULL ); // name*/
  61. if( sm_hHttpApiConfigChangeEvent == NULL )
  62. {
  63. hr = HRESULT_FROM_WIN32( GetLastError() );
  64. DBGPRINTF(( DBG_CONTEXT,
  65. "CreateEvent() failed. hr = 0x%x\n",
  66. hr ));
  67. goto Failed;
  68. }
  69. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  70. L"System\\CurrentControlSet\\Services\\HTTP\\Parameters\\SslBindingInfo",
  71. 0,
  72. KEY_READ,
  73. &sm_hHttpApiConfigKey );
  74. if ( dwError != ERROR_SUCCESS )
  75. {
  76. // backup plan
  77. // if SslBindingInfo doesn't extst yet, simply listen on
  78. // parent node. HTTP\Parameters is guaranteed to exist on valid install
  79. //
  80. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  81. L"System\\CurrentControlSet\\Services\\HTTP\\Parameters",
  82. 0,
  83. KEY_READ,
  84. &sm_hHttpApiConfigKey );
  85. if ( dwError != ERROR_SUCCESS )
  86. {
  87. hr = HRESULT_FROM_WIN32( dwError );
  88. DBGPRINTF(( DBG_CONTEXT,
  89. "Failed to open registry. hr = 0x%x\n",
  90. hr ));
  91. CloseHandle( sm_hHttpApiConfigChangeEvent );
  92. sm_hHttpApiConfigChangeEvent = NULL;
  93. goto Failed;
  94. }
  95. }
  96. DBG_ASSERT( sm_hHttpApiConfigKey != NULL );
  97. //
  98. // Watch the registry key for a change
  99. //
  100. dwError = RegNotifyChangeKeyValue( sm_hHttpApiConfigKey,
  101. TRUE,
  102. REG_NOTIFY_CHANGE_LAST_SET |
  103. REG_NOTIFY_CHANGE_NAME,
  104. sm_hHttpApiConfigChangeEvent,
  105. TRUE );
  106. if( dwError != ERROR_SUCCESS )
  107. {
  108. hr = HRESULT_FROM_WIN32( dwError );
  109. RegCloseKey( sm_hHttpApiConfigKey );
  110. sm_hHttpApiConfigKey = NULL;
  111. CloseHandle( sm_hHttpApiConfigChangeEvent );
  112. sm_hHttpApiConfigChangeEvent = NULL;
  113. DBGPRINTF(( DBG_CONTEXT,
  114. "RegNotifyChangeKeyValue failed. hr = 0x%x\n",
  115. hr ));
  116. goto Failed;
  117. }
  118. //
  119. // Register a callback function to wait on the event
  120. //
  121. if( !RegisterWaitForSingleObject(
  122. &sm_hWaitHandle,
  123. sm_hHttpApiConfigChangeEvent,
  124. ( WAITORTIMERCALLBACK )ENDPOINT_CONFIG::ConfigStoreChangeCallback,
  125. NULL,
  126. INFINITE,
  127. WT_EXECUTEDEFAULT ) )
  128. {
  129. hr = HRESULT_FROM_WIN32( GetLastError() );
  130. RegCloseKey( sm_hHttpApiConfigKey );
  131. sm_hHttpApiConfigKey = NULL;
  132. CloseHandle( sm_hHttpApiConfigChangeEvent );
  133. sm_hHttpApiConfigChangeEvent = NULL;
  134. DBGPRINTF(( DBG_CONTEXT,
  135. "RegisterWaitForSingleObject failed. hr = 0x%x\n",
  136. hr ));
  137. goto Failed;
  138. }
  139. sm_InitState = INIT_CHANGE_NOTIF;
  140. return NO_ERROR;
  141. Failed:
  142. Terminate();
  143. return hr;
  144. }
  145. //static
  146. VOID
  147. ENDPOINT_CONFIG::Terminate(
  148. VOID
  149. )
  150. /*++
  151. Routine Description:
  152. Cleanup site configuration globals
  153. Arguments:
  154. None
  155. Return Value:
  156. None
  157. --*/
  158. {
  159. switch( sm_InitState )
  160. {
  161. case INIT_CHANGE_NOTIF:
  162. if ( sm_hWaitHandle != NULL )
  163. {
  164. UnregisterWaitEx( sm_hWaitHandle,
  165. INVALID_HANDLE_VALUE );
  166. sm_hWaitHandle = NULL;
  167. }
  168. //
  169. // NOTE:
  170. // registry key must be closed before event is destroyed
  171. // because closing handle will assure that sm_hHttpApiConfigChangeEvent event
  172. // will not be used any more
  173. //
  174. if ( sm_hHttpApiConfigKey != NULL )
  175. {
  176. CloseHandle( sm_hHttpApiConfigKey );
  177. sm_hHttpApiConfigKey = NULL;
  178. }
  179. if ( sm_hHttpApiConfigChangeEvent != NULL )
  180. {
  181. CloseHandle( sm_hHttpApiConfigChangeEvent );
  182. sm_hHttpApiConfigChangeEvent = NULL;
  183. }
  184. case INIT_HASH:
  185. if ( sm_pEndpointConfigHash != NULL )
  186. {
  187. //
  188. // Clear hash table before deleting it
  189. //
  190. sm_pEndpointConfigHash->Clear();
  191. delete sm_pEndpointConfigHash;
  192. sm_pEndpointConfigHash = NULL;
  193. }
  194. case INIT_HTTPAPI:
  195. HttpTerminate( HTTP_INITIALIZE_CONFIG, NULL );
  196. case INIT_NONE:
  197. break;
  198. }
  199. }
  200. //private
  201. //static
  202. HRESULT
  203. ENDPOINT_CONFIG::GetEndpointConfigData(
  204. IN DWORD LocalAddress,
  205. IN USHORT LocalPort,
  206. OUT PHTTP_SERVICE_CONFIG_SSL_SET * ppEndpointConfigData,
  207. OUT BOOL * pfWildcardMatch
  208. )
  209. /*++
  210. Routine Description:
  211. lookup SSL configuration
  212. Arguments:
  213. LocalAddress - IP address in network order
  214. LocalPort - Port in network order
  215. ppEndpointConfigData - allocated within this function - delete[] must be used to free it
  216. pfWildcardMatch - was wildcard IP address match used?
  217. )
  218. Return Value:
  219. HRESULT
  220. --*/
  221. {
  222. DWORD dwError;
  223. DWORD ReturnLength = 0;
  224. HTTP_SERVICE_CONFIG_SSL_QUERY QueryParam;
  225. PHTTP_SERVICE_CONFIG_SSL_SET pSetParam = NULL;
  226. HRESULT hr = NO_ERROR;
  227. SOCKADDR_IN SockAddr;
  228. if ( ppEndpointConfigData == NULL ||
  229. pfWildcardMatch == NULL )
  230. {
  231. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  232. }
  233. ZeroMemory( &SockAddr, sizeof(SockAddr) );
  234. ZeroMemory( &QueryParam, sizeof(QueryParam) );
  235. *pfWildcardMatch = FALSE;
  236. QueryParam.QueryDesc = HttpServiceConfigQueryExact;
  237. //
  238. // build sock addr for HTTPAPI lookup
  239. //
  240. SockAddr.sin_family = AF_INET;
  241. SockAddr.sin_port = LocalPort;
  242. SockAddr.sin_addr.s_addr = LocalAddress;
  243. QueryParam.KeyDesc.pIpPort = (PSOCKADDR) &SockAddr;
  244. // Loop - check nonwildcard info first, if it fails then try wildcard
  245. //
  246. for(;;)
  247. {
  248. dwError = HttpQueryServiceConfiguration(
  249. NULL,
  250. HttpServiceConfigSSLCertInfo,
  251. &QueryParam,
  252. sizeof(QueryParam),
  253. NULL,
  254. 0,
  255. &ReturnLength,
  256. NULL
  257. );
  258. if ( dwError == ERROR_INSUFFICIENT_BUFFER )
  259. {
  260. pSetParam = (PHTTP_SERVICE_CONFIG_SSL_SET) new BYTE[ReturnLength];
  261. if ( pSetParam == NULL )
  262. {
  263. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  264. goto Finished;
  265. }
  266. dwError = HttpQueryServiceConfiguration(
  267. NULL,
  268. HttpServiceConfigSSLCertInfo,
  269. &QueryParam,
  270. sizeof(QueryParam),
  271. pSetParam,
  272. ReturnLength,
  273. &ReturnLength,
  274. NULL
  275. );
  276. //
  277. // It is possible that the size returned on the first call may
  278. // have changed between first and second call.
  279. // It would be caused by configuration change.
  280. // Probability of it happening is very low.
  281. // If it happens then one connection attempt will fail and it is
  282. // acceptable
  283. //
  284. }
  285. // If not found (and other error will mean end of trying)
  286. // or if wildcard lookup already executed
  287. // then leave the loop
  288. //
  289. if ( dwError != ERROR_FILE_NOT_FOUND || SockAddr.sin_addr.s_addr == INADDR_ANY )
  290. {
  291. break;
  292. }
  293. else
  294. {
  295. //
  296. // continue loop for wildcard lookup
  297. //
  298. SockAddr.sin_addr.s_addr = INADDR_ANY;
  299. }
  300. }
  301. if ( dwError != NO_ERROR )
  302. {
  303. hr = HRESULT_FROM_WIN32( dwError );
  304. goto Finished;
  305. }
  306. if ( SockAddr.sin_addr.s_addr == INADDR_ANY )
  307. {
  308. *pfWildcardMatch = TRUE;
  309. }
  310. *ppEndpointConfigData = pSetParam;
  311. hr = S_OK;
  312. Finished:
  313. return hr;
  314. }
  315. //static
  316. HRESULT
  317. ENDPOINT_CONFIG::GetEndpointConfig(
  318. CONNECTION_INFO * pConnectionInfo,
  319. ENDPOINT_CONFIG ** ppEndpointConfig,
  320. BOOL fCreateEmptyIfNotFound
  321. )
  322. /*++
  323. Routine Description:
  324. Lookup site configuration in hash table. If not there then create it
  325. and add it to table
  326. Arguments:
  327. dwSiteId - Site ID to lookup
  328. ppEndpointConfig - Filled with pointer to site config on success
  329. fCreateEmptyIfNotFound - if endpoint config was not located
  330. in the persistent store, create empty
  331. endpoint config and stick it to cache
  332. That will optimize lookup for EnableRawFilter
  333. checks
  334. Return Value:
  335. HRESULT
  336. HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) when endpoint config not found
  337. --*/
  338. {
  339. LK_RETCODE lkrc;
  340. ENDPOINT_CONFIG * pEndpointConfig = NULL;
  341. SERVER_CERT * pServerCert = NULL;
  342. IIS_CTL * pIisCtl = NULL;
  343. HRESULT hr = NO_ERROR;
  344. STACK_STRU( strMBPath, 64 );
  345. DWORD LocalAddress = 0;
  346. USHORT LocalPort = 0;
  347. BOOL fWildcardMatch = FALSE;
  348. PHTTP_SERVICE_CONFIG_SSL_SET pEndpointConfigData = NULL;
  349. if ( ppEndpointConfig == NULL ||
  350. pConnectionInfo == NULL )
  351. {
  352. DBG_ASSERT( FALSE );
  353. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  354. }
  355. *ppEndpointConfig = NULL;
  356. //
  357. // Figure out Ip Address and Port
  358. //
  359. //
  360. // Pass Port and IP address in network order
  361. // (HTTP service will return them in network order so no changes are needed)
  362. //
  363. if( pConnectionInfo->LocalAddressType == TDI_ADDRESS_TYPE_IP )
  364. {
  365. LocalAddress = pConnectionInfo->SockLocalAddress.ipv4SockAddress.sin_addr.s_addr;
  366. LocalPort = pConnectionInfo->SockLocalAddress.ipv4SockAddress.sin_port;
  367. }
  368. else if ( pConnectionInfo->LocalAddressType == TDI_ADDRESS_TYPE_IP6 )
  369. {
  370. //
  371. // IPv6 connections will be able to handle SSL connections only
  372. // in the case when all IP addresses on the machine are configured to
  373. // listen on secure port (IPv4 wildcard binding must be configured).
  374. // CODEWORK: Once in the future there may be a need to implement
  375. // for IPv6 support.
  376. //
  377. LocalAddress = INADDR_ANY; // Wildcard IP
  378. LocalPort = pConnectionInfo->SockLocalAddress.ipv6SockAddress.sin6_port;
  379. }
  380. else
  381. {
  382. //
  383. // We support only IPv4 and IPv6. Any other value means error
  384. //
  385. DBG_ASSERT( FALSE );
  386. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  387. goto ExitPoint;
  388. }
  389. //
  390. // First lookup in the cache
  391. // Because we don't preread all the endpoint configuration stored in HttpAPI Config
  392. // store in out hash table, it is not straightforward to handle wildcard endpoint
  393. // configuration
  394. // If endpoint configuration lookup returned data based on wildcard endpoint config
  395. // we will still store it in the hash table for the specific endpoint we looked up
  396. // Otherwise there is is risk that wildcard endpoint config stored in the hash table
  397. // could override individual endpoint settings that exist in the HttpAPI config store
  398. // but were not yet read and stored in our hash table
  399. //
  400. DBG_ASSERT( sm_pEndpointConfigHash != NULL );
  401. ENDPOINT_KEY EndpointKey = GenerateEndpointKey( LocalAddress, LocalPort );
  402. lkrc = sm_pEndpointConfigHash->FindKey(
  403. &EndpointKey,
  404. &pEndpointConfig );
  405. if ( lkrc == LK_SUCCESS )
  406. {
  407. DBG_ASSERT( pEndpointConfig != NULL );
  408. *ppEndpointConfig = pEndpointConfig;
  409. hr = S_OK;
  410. goto ExitPoint;
  411. }
  412. //
  413. // Ok, nothing cached. We will have to make a lookup in the persistent store
  414. //
  415. //
  416. // Try to lookup config info through HTTPAPI
  417. // fWildcardMatch is currently ignored we will store retrieved config data
  418. // for the specific endpoint
  419. //
  420. hr = GetEndpointConfigData(
  421. LocalAddress,
  422. LocalPort,
  423. &pEndpointConfigData,
  424. &fWildcardMatch );
  425. if ( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) && fCreateEmptyIfNotFound )
  426. {
  427. //
  428. // Create empty endpoint info
  429. // This will optimize the EnableRawFilter lookups
  430. // because without cached entry for each new raw Filter connection
  431. // we would need to make HttpApi config lookup
  432. // (empty endpoint indicates that it is OK to do Raw Filter handling)
  433. //
  434. pEndpointConfigData = NULL;
  435. pEndpointConfig = new ENDPOINT_CONFIG( LocalAddress,
  436. LocalPort,
  437. NULL, // no Server Cert info
  438. NULL, // No Ctl info
  439. pEndpointConfigData );
  440. if ( pEndpointConfig == NULL )
  441. {
  442. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  443. goto ExitPoint;
  444. }
  445. else
  446. {
  447. // ENDPOINT_CONFIG took ownership of pEndpointConfigData
  448. pEndpointConfigData = NULL;
  449. }
  450. }
  451. else if ( FAILED( hr ) )
  452. {
  453. //
  454. // Not finding the site just means this is not an SSL site
  455. //
  456. goto ExitPoint;
  457. }
  458. else if ( pEndpointConfigData != NULL &&
  459. pEndpointConfigData->ParamDesc.SslHashLength == 0 )
  460. {
  461. //
  462. // Store endpoint config for nonsecure Endpoint
  463. // to flag if Raw Filters are enabled or disabled
  464. //
  465. pEndpointConfig = new ENDPOINT_CONFIG( LocalAddress,
  466. LocalPort,
  467. NULL,
  468. NULL,
  469. pEndpointConfigData );
  470. if ( pEndpointConfig == NULL )
  471. {
  472. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  473. goto ExitPoint;
  474. }
  475. else
  476. {
  477. // ENDPOINT_CONFIG took ownership of pEndpointConfigData
  478. pEndpointConfigData = NULL;
  479. }
  480. }
  481. else
  482. {
  483. //
  484. // To get this far means that we expect correct SSL endpoint info
  485. // to be available
  486. //
  487. //
  488. // We have enough to lookup in SERVER_CERT cache
  489. //
  490. hr = SERVER_CERT::GetServerCertificate( (PBYTE) pEndpointConfigData->ParamDesc.pSslHash,
  491. pEndpointConfigData->ParamDesc.SslHashLength,
  492. pEndpointConfigData->ParamDesc.pSslCertStoreName,
  493. &pServerCert );
  494. if ( FAILED( hr ) )
  495. {
  496. //
  497. // If we couldn't get a server cert, SSL will
  498. // not be enablable for this site
  499. //
  500. goto ExitPoint;
  501. }
  502. DBG_ASSERT( pServerCert != NULL );
  503. hr = IIS_CTL::GetIisCtl( pEndpointConfigData->ParamDesc.pDefaultSslCtlIdentifier,
  504. pEndpointConfigData->ParamDesc.pDefaultSslCtlStoreName,
  505. &pIisCtl );
  506. //
  507. // if CTL context creation failed, we must not fail site config creation
  508. // because CTLs are not mandatory for all scenarios (only client certificate
  509. // scenarios require them, so we have to make sure that those would be failing )
  510. //
  511. if ( FAILED( hr ) )
  512. {
  513. pIisCtl = NULL;
  514. //
  515. // BUGBUG: Error loading CTL should be logged into event log
  516. //
  517. hr = S_OK;
  518. }
  519. //
  520. // OK. Create the config and attempt to add it to the cache
  521. //
  522. pEndpointConfig = new ENDPOINT_CONFIG( ( LocalAddress ),
  523. LocalPort,
  524. pServerCert,
  525. pIisCtl,
  526. pEndpointConfigData );
  527. if ( pEndpointConfig == NULL )
  528. {
  529. if ( pServerCert != NULL )
  530. {
  531. pServerCert->DereferenceServerCert();
  532. pServerCert = NULL;
  533. }
  534. if ( pIisCtl != NULL )
  535. {
  536. pIisCtl->DereferenceIisCtl();
  537. pIisCtl = NULL;
  538. }
  539. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  540. goto ExitPoint;
  541. }
  542. else
  543. {
  544. // ENDPOINT_CONFIG took ownership of pEndpointConfigData
  545. pEndpointConfigData = NULL;
  546. }
  547. //
  548. // Acquire credentials
  549. //
  550. hr = pEndpointConfig->AcquireCredentials();
  551. if ( FAILED( hr ) )
  552. {
  553. delete pEndpointConfig;
  554. pEndpointConfig = NULL;
  555. goto ExitPoint;
  556. }
  557. }
  558. //
  559. // We don't care what the success of the insertion was. If it failed,
  560. // then the pEndpointConfig will not be extra referenced and the caller
  561. // will clean it up when it derefs
  562. //
  563. sm_pEndpointConfigHash->InsertRecord( pEndpointConfig );
  564. *ppEndpointConfig = pEndpointConfig;
  565. hr = S_OK;
  566. ExitPoint:
  567. if ( pEndpointConfigData != NULL )
  568. {
  569. delete [] pEndpointConfigData;
  570. pEndpointConfigData = NULL;
  571. }
  572. return hr;
  573. }
  574. //static
  575. LK_PREDICATE
  576. ENDPOINT_CONFIG::ServerCertPredicate(
  577. ENDPOINT_CONFIG * pEndpointConfig,
  578. void * pvState
  579. )
  580. /*++
  581. Description:
  582. DeleteIf() predicate used to find items which reference the
  583. SERVER_CERT pointed to by pvState
  584. Arguments:
  585. pEndpointConfig - SSL endpoint config
  586. pvState - SERVER_CERT to check for
  587. Returns:
  588. LK_PREDICATE - LKP_PERFORM indicates removing the current
  589. token from token cache
  590. LKP_NO_ACTION indicates doing nothing.
  591. --*/
  592. {
  593. LK_PREDICATE lkpAction;
  594. SERVER_CERT * pServerCert;
  595. DBG_ASSERT( pEndpointConfig != NULL );
  596. pServerCert = (SERVER_CERT*) pvState;
  597. DBG_ASSERT( pServerCert != NULL );
  598. DBG_ASSERT( pServerCert->CheckSignature() );
  599. if ( pEndpointConfig->QueryServerCert() == pServerCert )
  600. {
  601. lkpAction = LKP_PERFORM;
  602. }
  603. else
  604. {
  605. lkpAction = LKP_NO_ACTION;
  606. }
  607. return lkpAction;
  608. }
  609. //static
  610. HRESULT
  611. ENDPOINT_CONFIG::FlushByServerCert(
  612. SERVER_CERT * pServerCert
  613. )
  614. /*++
  615. Routine Description:
  616. Flush the ENDPOINT_CONFIG cache of anything referecing the given server
  617. certificate
  618. Arguments:
  619. pServerCert - Server certificate to reference
  620. Return Value:
  621. HRESULT
  622. --*/
  623. {
  624. DBG_ASSERT( sm_pEndpointConfigHash != NULL );
  625. sm_pEndpointConfigHash->DeleteIf( ENDPOINT_CONFIG::ServerCertPredicate,
  626. pServerCert );
  627. return NO_ERROR;
  628. }
  629. //static
  630. LK_PREDICATE
  631. ENDPOINT_CONFIG::IisCtlPredicate(
  632. ENDPOINT_CONFIG * pEndpointConfig,
  633. void * pvState
  634. )
  635. /*++
  636. Description:
  637. DeleteIf() predicate used to find items which reference the
  638. SERVER_CERT pointed to by pvState
  639. Arguments:
  640. pEndpointConfig - SSL endpoint config
  641. pvState - IIS_CTL to check for
  642. Returns:
  643. LK_PREDICATE - LKP_PERFORM indicates removing the current
  644. token from token cache
  645. LKP_NO_ACTION indicates doing nothing.
  646. --*/
  647. {
  648. LK_PREDICATE lkpAction;
  649. IIS_CTL * pIisCtl;
  650. DBG_ASSERT( pEndpointConfig != NULL );
  651. pIisCtl = (IIS_CTL*) pvState;
  652. DBG_ASSERT( pIisCtl != NULL );
  653. DBG_ASSERT( pIisCtl->CheckSignature() );
  654. if ( pEndpointConfig->QueryIisCtl() == pIisCtl )
  655. {
  656. lkpAction = LKP_PERFORM;
  657. }
  658. else
  659. {
  660. lkpAction = LKP_NO_ACTION;
  661. }
  662. return lkpAction;
  663. }
  664. //static
  665. HRESULT
  666. ENDPOINT_CONFIG::FlushByIisCtl(
  667. IIS_CTL * pIisCtl
  668. )
  669. /*++
  670. Routine Description:
  671. Flush the ENDPOINT_CONFIG cache of anything referecing the given CTL
  672. Arguments:
  673. pIisCtl -
  674. Return Value:
  675. HRESULT
  676. --*/
  677. {
  678. DBG_ASSERT( sm_pEndpointConfigHash != NULL );
  679. sm_pEndpointConfigHash->DeleteIf( ENDPOINT_CONFIG::IisCtlPredicate,
  680. pIisCtl );
  681. return NO_ERROR;
  682. }
  683. //static
  684. LK_PREDICATE
  685. ENDPOINT_CONFIG::SiteIdPredicate(
  686. ENDPOINT_CONFIG * /*pEndpointConfig*/,
  687. void * pvState
  688. )
  689. /*++
  690. Description:
  691. DeleteIf() predicate to delete config specified by site id (pvState)
  692. Arguments:
  693. pEndpointConfig - SSL Endpoint config
  694. pvState - Site ID
  695. Returns:
  696. LK_PREDICATE - LKP_PERFORM indicates removing the current
  697. token from token cache
  698. LKP_NO_ACTION indicates doing nothing.
  699. --*/
  700. {
  701. LK_PREDICATE lkpAction;
  702. DWORD dwSiteId;
  703. dwSiteId = PtrToUlong(pvState);
  704. //
  705. // Site Id is legacy value - all endpoints will be deleted
  706. // upon change because we don't internally track site ID any more
  707. // CODEWORK: Site concept should be completely removed from the code
  708. // Remove before RC1
  709. lkpAction = LKP_PERFORM;
  710. return lkpAction;
  711. }
  712. //static
  713. LK_PREDICATE
  714. ENDPOINT_CONFIG::EndpointPredicate(
  715. ENDPOINT_CONFIG * pEndpointConfig,
  716. void * pvState
  717. )
  718. /*++
  719. Description:
  720. DeleteIf() predicate to delete config specified by site id (pvState)
  721. Arguments:
  722. pEndpointConfig - SSL Endpoint config
  723. pvState - Endpoint key
  724. Returns:
  725. LK_PREDICATE - LKP_PERFORM indicates removing the current
  726. token from token cache
  727. LKP_NO_ACTION indicates doing nothing.
  728. --*/
  729. {
  730. LK_PREDICATE lkpAction;
  731. ENDPOINT_KEY * pEndpointKey;
  732. DBG_ASSERT( pEndpointConfig != NULL );
  733. pEndpointKey = (ENDPOINT_KEY *) (pvState);
  734. if ( *( pEndpointConfig->QueryEndpointKey() ) == *pEndpointKey ||
  735. *pEndpointKey == GenerateEndpointKey( INADDR_ANY, 0 ) )
  736. {
  737. // 0 means to delete all the endpoint info
  738. lkpAction = LKP_PERFORM;
  739. }
  740. else
  741. {
  742. lkpAction = LKP_NO_ACTION;
  743. }
  744. return lkpAction;
  745. }
  746. //static
  747. HRESULT
  748. ENDPOINT_CONFIG::FlushByEndpoint(
  749. DWORD LocalAddress,
  750. USHORT LocalPort
  751. )
  752. /*++
  753. Routine Description:
  754. Flush specified site configuration. If dwSiteId is 0, then flush all
  755. Arguments:
  756. LocalAddress - IP Address
  757. LocalPort - Port
  758. if LocalAddress=INADDR_ANY and LocalPort=0 then all endpoints will be flushed
  759. Return Value:
  760. HRESULT
  761. --*/
  762. {
  763. DBG_ASSERT( sm_pEndpointConfigHash != NULL );
  764. ENDPOINT_KEY EndpointKey = GenerateEndpointKey( LocalAddress, LocalPort );
  765. sm_pEndpointConfigHash->DeleteIf( ENDPOINT_CONFIG::EndpointPredicate,
  766. (PVOID) &EndpointKey );
  767. return NO_ERROR;
  768. }
  769. ENDPOINT_CONFIG::~ENDPOINT_CONFIG()
  770. {
  771. if ( _pServerCert != NULL )
  772. {
  773. _pServerCert->DereferenceServerCert();
  774. _pServerCert = NULL;
  775. }
  776. if ( _pIisCtl != NULL )
  777. {
  778. _pIisCtl->DereferenceIisCtl();
  779. _pIisCtl = NULL;
  780. }
  781. if ( _pEndpointConfigData != NULL )
  782. {
  783. delete [] _pEndpointConfigData;
  784. _pEndpointConfigData = NULL;
  785. }
  786. _dwSignature = ENDPOINT_CONFIG_SIGNATURE_FREE;
  787. }
  788. HRESULT
  789. ENDPOINT_CONFIG::AcquireCredentials(
  790. VOID
  791. )
  792. /*++
  793. Routine Description:
  794. Do the Schannel thing to get credentials handle representing the
  795. server cert/mapping configuration of this site
  796. Arguments:
  797. None
  798. Return Value:
  799. HRESULT
  800. --*/
  801. {
  802. DBG_ASSERT( _pServerCert != NULL );
  803. return _SiteCreds.AcquireCredentials( _pServerCert,
  804. QueryUseDSMapper() );
  805. }
  806. // static
  807. VOID
  808. WINAPI
  809. ENDPOINT_CONFIG::ConfigStoreChangeCallback(
  810. PVOID /*pParam*/,
  811. BOOL /*fWaitFired*/
  812. )
  813. /*++
  814. Routine Description:
  815. Callback when HttpApi config store change occurs
  816. Note: Currently we listen directly on registry changes
  817. CODEWORK: once httpapi provides change notification mechanism
  818. we have to use that one
  819. Arguments:
  820. not used
  821. Return Value:
  822. --*/
  823. {
  824. //
  825. // If we fail to re-register for change notifications
  826. // we will ignore it. This will unfortunately stop all
  827. // the future change notifications
  828. // CODEWORK: consider if there is anything else we can do
  829. //
  830. RegNotifyChangeKeyValue( sm_hHttpApiConfigKey,
  831. TRUE,
  832. REG_NOTIFY_CHANGE_LAST_SET |
  833. REG_NOTIFY_CHANGE_NAME,
  834. sm_hHttpApiConfigChangeEvent,
  835. TRUE );
  836. //
  837. // There is no straightforward mechanism to figure out individual change
  838. // that happened. That's why we will flush all endpoints config
  839. // ( Changes in the endpoint config are not frequent so this should not be
  840. // a performance problem at all )
  841. //
  842. FlushByEndpoint( INADDR_ANY, 0 );
  843. }
  844. //static
  845. VOID
  846. ENDPOINT_CONFIG::Cleanup(
  847. VOID
  848. )
  849. /*++
  850. Routine Description:
  851. Cleanup must be called before Terminate
  852. Arguments:
  853. none
  854. Return Value:
  855. VOID
  856. --*/
  857. {
  858. sm_pEndpointConfigHash->Clear();
  859. }