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.

2268 lines
55 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. w3inst.cxx
  5. Abstract:
  6. This module defines the W3_SERVER_INSTANCE class
  7. Author:
  8. Johnson Apacible (JohnsonA) June-04-1996
  9. --*/
  10. #include "w3p.hxx"
  11. #include <ole2.h>
  12. #include <imd.h>
  13. #include <mb.hxx>
  14. #include <nsepname.hxx>
  15. #include <mbstring.h>
  16. #include <issched.hxx>
  17. #if DBG
  18. #define VALIDATE_HEAP() DBG_ASSERT( RtlValidateProcessHeaps() )
  19. #else
  20. #define VALIDATE_HEAP()
  21. #endif
  22. //
  23. // Constants
  24. //
  25. //
  26. // Globals
  27. //
  28. LPVOID g_pMappers[MT_LAST] = { NULL, NULL, NULL, NULL };
  29. PFN_SF_NOTIFY g_pFlushMapperNotify[MT_LAST] = { NULL, NULL, NULL, NULL };
  30. PFN_SF_NOTIFY g_pSslKeysNotify = NULL;
  31. extern STORE_CHANGE_NOTIFIER *g_pStoreChangeNotifier;
  32. //
  33. // Prototypes
  34. //
  35. DWORD
  36. InitializeInstances(
  37. PW3_IIS_SERVICE pService
  38. )
  39. /*++
  40. Routine Description:
  41. Reads the instances from the metabase
  42. Arguments:
  43. pService - Server instances added to.
  44. Return Value:
  45. Win32
  46. --*/
  47. {
  48. DWORD i;
  49. DWORD cInstances = 0;
  50. MB mb( (IMDCOM*) pService->QueryMDObject() );
  51. CHAR szKeyName[MAX_PATH+1];
  52. DWORD err = NO_ERROR;
  53. BUFFER buff;
  54. BOOL fMigrateRoots = FALSE;
  55. //
  56. // Open the metabase for write to get an atomic snapshot
  57. //
  58. ReOpen:
  59. if ( !mb.Open( "/LM/W3SVC/",
  60. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  61. {
  62. DBGPRINTF(( DBG_CONTEXT,
  63. "InitializeInstances: Cannot open path %s, error %lu\n",
  64. "/LM/W3SVC/", GetLastError() ));
  65. //
  66. // If the web service key isn't here, just create it
  67. //
  68. if ( !mb.Open( "",
  69. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ) ||
  70. !mb.AddObject( "/LM/W3SVC/" ))
  71. {
  72. return GetLastError();
  73. }
  74. DBGPRINTF(( DBG_CONTEXT,
  75. "/LM/W3Svc not found, auto-created\n" ));
  76. mb.Close();
  77. goto ReOpen;
  78. }
  79. //
  80. // Loop through instance keys and build a list. We don't keep the
  81. // metabase open because the instance instantiation code will need
  82. // to write to the metabase
  83. //
  84. TryAgain:
  85. i = 0;
  86. while ( mb.EnumObjects( "",
  87. szKeyName,
  88. i++ ))
  89. {
  90. BOOL fRet;
  91. DWORD dwInstance;
  92. CHAR szRegKey[MAX_PATH+1];
  93. //
  94. // Get the instance id
  95. //
  96. IF_DEBUG(INSTANCE) {
  97. DBGPRINTF((DBG_CONTEXT,"instance key %s\n",szKeyName));
  98. }
  99. dwInstance = atoi( szKeyName );
  100. if ( dwInstance == 0 ) {
  101. IF_DEBUG(INSTANCE) {
  102. DBGPRINTF((DBG_CONTEXT,"invalid instance ID %s\n",szKeyName));
  103. }
  104. continue;
  105. }
  106. if ( buff.QuerySize() < (cInstances + 1) * sizeof(DWORD) )
  107. {
  108. if ( !buff.Resize( (cInstances + 10) * sizeof(DWORD)) )
  109. {
  110. return GetLastError();
  111. }
  112. }
  113. ((DWORD *) buff.QueryPtr())[cInstances++] = dwInstance;
  114. }
  115. if ( cInstances == 0 )
  116. {
  117. DBGPRINTF(( DBG_CONTEXT,
  118. "No defined instances\n" ));
  119. if ( !mb.AddObject( "1" ))
  120. {
  121. DBGPRINTF(( DBG_CONTEXT,
  122. "Unable to create first instance, error %d\n",
  123. GetLastError() ));
  124. return GetLastError();
  125. }
  126. fMigrateRoots = TRUE; // Force reg->metabase migration of virtual directories
  127. goto TryAgain;
  128. }
  129. DBG_REQUIRE( mb.Close() );
  130. for ( i = 0; i < cInstances; i++ )
  131. {
  132. DWORD dwInstance = ((DWORD *)buff.QueryPtr())[i];
  133. pService->StartUpIndicateClientActivity();
  134. if( !g_pInetSvc->AddInstanceInfo( dwInstance, fMigrateRoots ) ) {
  135. err = GetLastError();
  136. DBGPRINTF((
  137. DBG_CONTEXT,
  138. "InitializeInstances: cannot create instance %lu, error %lu\n",
  139. dwInstance,
  140. err
  141. ));
  142. break;
  143. }
  144. }
  145. return err;
  146. } // InitializeInstances
  147. W3_SERVER_INSTANCE::W3_SERVER_INSTANCE(
  148. IN PW3_IIS_SERVICE pService,
  149. IN DWORD dwInstanceId,
  150. IN USHORT Port,
  151. IN LPCSTR lpszRegParamKey,
  152. IN LPWSTR lpwszAnonPasswordSecretName,
  153. IN LPWSTR lpwszVirtualRootsSecretName,
  154. IN BOOL fMigrateRoots
  155. )
  156. : IIS_SERVER_INSTANCE(pService,
  157. dwInstanceId,
  158. Port,
  159. lpszRegParamKey,
  160. lpwszAnonPasswordSecretName,
  161. lpwszVirtualRootsSecretName,
  162. fMigrateRoots),
  163. m_signature (W3_SERVER_INSTANCE_SIGNATURE),
  164. m_fAnySecureFilters (fAnySecureFilters),
  165. m_dwUseHostName (DEFAULT_W3_USE_HOST_NAME ),
  166. m_pszDefaultHostName (NULL ),
  167. m_fAcceptByteRanges (DEFAULT_W3_ACCEPT_BYTE_RANGES ),
  168. m_fLogErrors (DEFAULT_W3_LOG_ERRORS ),
  169. m_fLogSuccess (DEFAULT_W3_LOG_SUCCESS ),
  170. #if 0
  171. m_cbUploadReadAhead (DEFAULT_W3_UPLOAD_READ_AHEAD ),
  172. #endif
  173. m_fUsePoolThreadForCGI (DEFAULT_W3_USE_POOL_THREAD_FOR_CGI ),
  174. m_pszAccessDeniedMsg (NULL ),
  175. m_dwNetLogonWks (DEFAULT_W3_NET_LOGON_WKS),
  176. m_cAdvNotPwdExpInDays (DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS),
  177. m_dwAdvCacheTTL (DEFAULT_W3_ADV_CACHE_TTL),
  178. m_pFilterList ( NULL ),
  179. m_fAllowPathInfoForScriptMappings ( DEFAULT_W3_ALLOW_PATH_INFO_FOR_SCRIPT_MAPPINGS ),
  180. m_fProcessNtcrIfLoggedOn ( DEFAULT_W3_PROCESS_NTCR_IF_LOGGED_ON ),
  181. m_pW3Stats ( NULL ),
  182. m_dwSslCa ( 0 ),
  183. m_dwJobResetInterval ( DEFAULT_W3_CPU_RESET_INTERVAL ),
  184. m_tsJobLock ( ),
  185. m_llJobResetIntervalCPU ( GetCPUTimeFromInterval(DEFAULT_W3_CPU_RESET_INTERVAL) ),
  186. m_dwJobQueryInterval ( DEFAULT_W3_CPU_QUERY_INTERVAL ),
  187. m_dwJobLoggingSchedulerCookie ( 0 ),
  188. m_dwJobIntervalSchedulerCookie ( 0 ),
  189. m_dwJobCGICPULimit ( DEFAULT_W3_CPU_CGI_LIMIT ),
  190. m_dwJobLoggingOptions ( DEFAULT_W3_CPU_LOGGING_OPTIONS ),
  191. m_pwjoApplication ( NULL ),
  192. m_pwjoCGI ( NULL ),
  193. m_dwLastJobState ( MD_SERVER_STATE_STOPPED ),
  194. m_llJobSiteCPULimitLogEvent ( PercentCPULimitToCPUTime(DEFAULT_W3_CPU_LIMIT_EVENTLOG) ),
  195. m_llJobSiteCPULimitPriority ( PercentCPULimitToCPUTime(DEFAULT_W3_CPU_LIMIT_PRIORITY) ),
  196. m_llJobSiteCPULimitProcStop ( PercentCPULimitToCPUTime(DEFAULT_W3_CPU_LIMIT_PROCSTOP) ),
  197. m_llJobSiteCPULimitPause ( PercentCPULimitToCPUTime(DEFAULT_W3_CPU_LIMIT_PAUSE) ),
  198. m_fJobSiteCPULimitLogEventEnabled ( FALSE ),
  199. m_fJobSiteCPULimitPriorityEnabled ( FALSE ),
  200. m_fJobSiteCPULimitProcStopEnabled ( FALSE ),
  201. m_fJobSiteCPULimitPauseEnabled ( FALSE ),
  202. m_fCPULoggingEnabled ( FALSE ),
  203. m_fCPULimitsEnabled ( FALSE ),
  204. m_pSSLInfo ( NULL )
  205. {
  206. DWORD i;
  207. IF_DEBUG(INSTANCE) {
  208. DBGPRINTF(( DBG_CONTEXT,
  209. "Init instance from %s\n", lpszRegParamKey ));
  210. }
  211. for ( i = 0 ; i < MT_LAST ; ++i ) {
  212. m_apMappers[i] = NULL;
  213. }
  214. if ( QueryServerState( ) == MD_SERVER_STATE_INVALID ) {
  215. return;
  216. }
  217. //
  218. // Create statistics object
  219. //
  220. m_pW3Stats = new W3_SERVER_STATISTICS();
  221. if ( m_pW3Stats == NULL ) {
  222. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  223. SetServerState(MD_SERVER_STATE_INVALID, ERROR_NOT_ENOUGH_MEMORY);
  224. }
  225. return;
  226. } // W3_SERVER_INSTANCE::W3_SERVER_INSTANCE
  227. W3_SERVER_INSTANCE::~W3_SERVER_INSTANCE(
  228. VOID
  229. )
  230. {
  231. DWORD i = 0;
  232. //
  233. // There seems to be a lag betwenn calling RemoveWorkItem and
  234. // the last possible call from the scheduler. For now,
  235. // Just put this at the beginning of the destructor so items
  236. // will actually get removed before constructor completes.
  237. //
  238. if (m_dwJobLoggingSchedulerCookie != 0) {
  239. RemoveWorkItem( m_dwJobLoggingSchedulerCookie );
  240. }
  241. if (m_dwJobIntervalSchedulerCookie != 0) {
  242. RemoveWorkItem( m_dwJobIntervalSchedulerCookie );
  243. }
  244. if ((m_dwJobLoggingSchedulerCookie != 0) ||
  245. (m_dwJobIntervalSchedulerCookie != 0)) {
  246. QueryAndLogJobInfo(JOLE_SITE_STOP);
  247. }
  248. delete m_pwjoApplication;
  249. delete m_pwjoCGI;
  250. //
  251. // delete statistics object
  252. //
  253. if( m_pW3Stats != NULL )
  254. {
  255. delete m_pW3Stats;
  256. m_pW3Stats = NULL;
  257. }
  258. //
  259. // Free the registry strings.
  260. //
  261. CleanupRegistryStrings( );
  262. if ( m_pszDefaultHostName != NULL ) {
  263. TCP_FREE(m_pszDefaultHostName);
  264. m_pszDefaultHostName = NULL;
  265. }
  266. if ( m_pFilterList ) {
  267. FILTER_LIST::Dereference( m_pFilterList );
  268. }
  269. UINT iM;
  270. for ( iM = 0 ; iM < MT_LAST ; ++iM )
  271. {
  272. if ( m_apMappers[iM] )
  273. {
  274. ((RefBlob*)(m_apMappers[iM]))->Release();
  275. }
  276. }
  277. ResetSSLInfo( this );
  278. } // W3_SERVER_INSTANCE::~W3_SERVER_INSTANCE
  279. DWORD
  280. W3_SERVER_INSTANCE::StartInstance()
  281. {
  282. IF_DEBUG(INSTANCE) {
  283. DBGPRINTF((
  284. DBG_CONTEXT,
  285. "W3_SERVER_INSTANCE::StartInstance called for %p. Current state %d\n",
  286. this,
  287. QueryServerState()
  288. ));
  289. }
  290. DWORD dwError = IIS_SERVER_INSTANCE::StartInstance();
  291. if ( dwError)
  292. {
  293. IF_DEBUG(INSTANCE) {
  294. DBGPRINTF((
  295. DBG_CONTEXT,
  296. "W3_SERVER_INSTANCE - IIS_SERVER_INSTANCE Failed. StartInstance returned 0x%x",
  297. dwError
  298. ));
  299. }
  300. return dwError;
  301. }
  302. //
  303. // Read the w3 specfic params
  304. //
  305. if ( !ReadPrivateW3Params( ) ) {
  306. DBGERROR((
  307. DBG_CONTEXT,
  308. "[W3_SERVER_INSTANCE::StartInstance] id(%d) "
  309. "ReadPrivateW3Params failed\n",
  310. QueryInstanceId()
  311. ));
  312. goto error_exit;
  313. }
  314. if ( !ReadPublicW3Params( FC_W3_ALL ) ) {
  315. DBGERROR((
  316. DBG_CONTEXT,
  317. "[W3_SERVER_INSTANCE::StartInstance] id(%d) "
  318. "ReadPublicW3Params failed\n",
  319. QueryInstanceId()
  320. ));
  321. goto error_exit;
  322. }
  323. //
  324. // Get host name
  325. //
  326. InitializeHostName( );
  327. //
  328. // Directory browsing
  329. //
  330. InitializeDirBrowsing( );
  331. if ( !CreateFilterList() ) {
  332. DBGERROR((
  333. DBG_CONTEXT,
  334. "[W3_SERVER_INSTANCE::StartInstance] id(%d) "
  335. "CreateFilterList failed\n",
  336. QueryInstanceId()
  337. ));
  338. goto error_exit;
  339. }
  340. //
  341. // Don't listen on the secure port if there aren't any filters to
  342. // handle it
  343. //
  344. if ( !m_fAnySecureFilters ) {
  345. LockThisForWrite();
  346. RemoveSecureBindings();
  347. UnlockThis();
  348. }
  349. DBG_ASSERT(m_pW3Stats);
  350. m_pW3Stats->UpdateStartTime();
  351. return ERROR_SUCCESS;
  352. error_exit:
  353. //
  354. // We don't know the exact error to set here, as the above functions
  355. // that can fail do not SetLastError() consistently.
  356. //
  357. return (GetLastError() != NO_ERROR) ? GetLastError() :
  358. ERROR_NOT_ENOUGH_MEMORY;
  359. }
  360. DWORD
  361. W3_SERVER_INSTANCE::StopInstance()
  362. {
  363. DBG_ASSERT(m_pW3Stats);
  364. m_pW3Stats->UpdateStopTime();
  365. return IIS_SERVER_INSTANCE::StopInstance();
  366. }
  367. BOOL
  368. W3_SERVER_INSTANCE::ReadMappers(
  369. )
  370. /*++
  371. Description
  372. Read mappers for this instance
  373. Arguments:
  374. None
  375. Return Value:
  376. TRUE if successful, FALSE otherwise
  377. Note :
  378. Instance must be locked before calling this function
  379. --*/
  380. {
  381. DWORD dwR;
  382. UINT iM;
  383. LPVOID aOldMappers[MT_LAST];
  384. BOOL fSt = FALSE;
  385. //
  386. // release reference to current mappers
  387. //
  388. memcpy( aOldMappers, m_apMappers, MT_LAST*sizeof(LPVOID) );
  389. for ( iM = 0 ; iM < MT_LAST ; ++iM )
  390. {
  391. if ( m_apMappers[iM] )
  392. {
  393. ((RefBlob*)(m_apMappers[iM]))->Release();
  394. m_apMappers[iM] = NULL;
  395. }
  396. }
  397. //
  398. // Read mappers from Name Space Extension Metabase
  399. //
  400. if ( !g_pInetSvc->QueryMDNseObject() )
  401. {
  402. return FALSE;
  403. }
  404. MB mbx( (IMDCOM*) g_pInetSvc->QueryMDNseObject() );
  405. if ( mbx.Open( QueryMDPath() ) )
  406. {
  407. dwR = sizeof(LPVOID);
  408. if ( !mbx.GetData( NSEPM_CERT11_PATH,
  409. MD_CPP_CERT11,
  410. IIS_MD_UT_SERVER,
  411. BINARY_METADATA,
  412. &m_apMappers[MT_CERT11],
  413. &dwR,
  414. 0 ) )
  415. {
  416. m_apMappers[MT_CERT11] = NULL;
  417. }
  418. dwR = sizeof(LPVOID);
  419. if ( !mbx.GetData( NSEPM_CERTW_PATH,
  420. MD_CPP_CERTW,
  421. IIS_MD_UT_SERVER,
  422. BINARY_METADATA,
  423. &m_apMappers[MT_CERTW],
  424. &dwR,
  425. 0 ) )
  426. {
  427. m_apMappers[MT_CERTW] = NULL;
  428. }
  429. dwR = sizeof(LPVOID);
  430. if ( !mbx.GetData( NSEPM_BASIC_PATH,
  431. MD_CPP_ITA,
  432. IIS_MD_UT_SERVER,
  433. BINARY_METADATA,
  434. &m_apMappers[MT_ITA],
  435. &dwR,
  436. 0 ) )
  437. {
  438. m_apMappers[MT_ITA] = NULL;
  439. }
  440. dwR = sizeof(LPVOID);
  441. if ( !mbx.GetData( NSEPM_DIGEST_PATH,
  442. MD_CPP_DIGEST,
  443. IIS_MD_UT_SERVER,
  444. BINARY_METADATA,
  445. &m_apMappers[MT_MD5],
  446. &dwR,
  447. 0 ) )
  448. {
  449. m_apMappers[MT_MD5] = NULL;
  450. }
  451. mbx.Close();
  452. fSt = TRUE;
  453. }
  454. //
  455. // Call notification functions for mappers existence change
  456. // ( i.e. from non-exist to exist or exist to non-exist )
  457. //
  458. if ( (aOldMappers[MT_CERT11] == NULL) != (m_apMappers[MT_CERT11] == NULL)
  459. && g_pFlushMapperNotify[MT_CERT11] )
  460. {
  461. (g_pFlushMapperNotify[MT_CERT11])( SF_NOTIFY_MAPPER_CERT11_CHANGED, this );
  462. }
  463. if ( (aOldMappers[MT_CERTW] == NULL) != (m_apMappers[MT_CERTW] == NULL)
  464. && g_pFlushMapperNotify[MT_CERTW] )
  465. {
  466. (g_pFlushMapperNotify[MT_CERTW])( SF_NOTIFY_MAPPER_CERTW_CHANGED, this );
  467. }
  468. if ( (aOldMappers[MT_ITA] == NULL) != (m_apMappers[MT_ITA] == NULL)
  469. && g_pFlushMapperNotify[MT_ITA] )
  470. {
  471. (g_pFlushMapperNotify[MT_ITA])( SF_NOTIFY_MAPPER_ITA_CHANGED, this );
  472. }
  473. if ( (aOldMappers[MT_MD5] == NULL) != (m_apMappers[MT_MD5] == NULL)
  474. && g_pFlushMapperNotify[MT_MD5] )
  475. {
  476. (g_pFlushMapperNotify[MT_MD5])( SF_NOTIFY_MAPPER_MD5_CHANGED, this );
  477. }
  478. return fSt;
  479. }
  480. BOOL
  481. W3_SERVER_INSTANCE::ReadPrivateW3Params(
  482. VOID
  483. )
  484. /*++
  485. Description
  486. Reads reg values not defined in UI
  487. Arguments:
  488. fc - Items to read
  489. Note:
  490. --*/
  491. {
  492. DWORD err;
  493. HKEY hkey;
  494. HKEY hDefkey;
  495. DWORD cProv = 0;
  496. BOOL fRet = TRUE;
  497. STR strProviderList;
  498. MB mb( (IMDCOM*) g_pInetSvc->QueryMDObject() );
  499. DWORD dwValue;
  500. DWORD i;
  501. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  502. QueryRegParamKey( ),
  503. 0,
  504. KEY_READ,
  505. &hkey );
  506. if ( err != NO_ERROR ) {
  507. return(TRUE);
  508. }
  509. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  510. W3_PARAMETERS_KEY,
  511. 0,
  512. KEY_READ,
  513. &hDefkey );
  514. if ( err != NO_ERROR ) {
  515. RegCloseKey( hkey );
  516. return(TRUE);
  517. }
  518. LockThisForWrite();
  519. if ( !ReadMappers() ) {
  520. //
  521. // Ignore error for win95
  522. //
  523. if ( !g_fIsWindows95 ) {
  524. DBGPRINTF((DBG_CONTEXT,"Call to ReadMapper failed\n"));
  525. fRet = FALSE;
  526. goto exit;
  527. }
  528. }
  529. #if 0
  530. m_fUseHostName = !!ReadRegistryDword( hkey,
  531. W3_DEFAULT_HOST_NAME,
  532. DEFAULT_W3_USE_HOST_NAME);
  533. #endif
  534. m_fAcceptByteRanges = !!ReadRegistryDword( hkey,
  535. W3_ACCEPT_BYTE_RANGES,
  536. DEFAULT_W3_ACCEPT_BYTE_RANGES);
  537. m_fLogErrors = !!ReadRegistryDword( hkey,
  538. W3_LOG_ERRORS,
  539. DEFAULT_W3_LOG_ERRORS );
  540. m_fLogSuccess = !!ReadRegistryDword( hkey,
  541. W3_LOG_SUCCESS,
  542. DEFAULT_W3_LOG_SUCCESS );
  543. ReadRegString( hkey,
  544. &m_pszAccessDeniedMsg,
  545. W3_ACCESS_DENIED_MSG,
  546. DEFAULT_W3_ACCESS_DENIED_MSG );
  547. if ( mb.Open( QueryMDPath() ) )
  548. {
  549. mb.GetStr( "",
  550. MD_AUTH_CHANGE_URL,
  551. IIS_MD_UT_SERVER,
  552. &m_strAuthChangeUrl );
  553. mb.GetStr( "",
  554. MD_AUTH_EXPIRED_URL,
  555. IIS_MD_UT_SERVER,
  556. &m_strAuthExpiredUrl );
  557. mb.GetStr( "",
  558. MD_AUTH_NOTIFY_PWD_EXP_URL,
  559. IIS_MD_UT_SERVER,
  560. &m_strAdvNotPwdExpUrl );
  561. mb.GetStr( "",
  562. MD_AUTH_EXPIRED_UNSECUREURL,
  563. IIS_MD_UT_SERVER,
  564. &m_strAuthExpiredUnsecureUrl );
  565. mb.GetStr( "",
  566. MD_AUTH_NOTIFY_PWD_EXP_UNSECUREURL,
  567. IIS_MD_UT_SERVER,
  568. &m_strAdvNotPwdExpUnsecureUrl );
  569. if ( !mb.GetDword( "",
  570. MD_ADV_NOTIFY_PWD_EXP_IN_DAYS,
  571. IIS_MD_UT_SERVER,
  572. &m_cAdvNotPwdExpInDays ) )
  573. {
  574. m_cAdvNotPwdExpInDays = DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS;
  575. }
  576. if ( !mb.GetDword( "",
  577. MD_CERT_CHECK_MODE,
  578. IIS_MD_UT_SERVER,
  579. &m_dwCertCheckMode ) )
  580. {
  581. m_dwCertCheckMode = 0;
  582. }
  583. if ( !mb.GetDword( "",
  584. MD_AUTH_CHANGE_FLAGS,
  585. IIS_MD_UT_SERVER,
  586. &m_dwAuthChangeFlags ) )
  587. {
  588. m_dwAuthChangeFlags = 0;
  589. }
  590. if ( !mb.GetDword( "",
  591. MD_ADV_CACHE_TTL,
  592. IIS_MD_UT_SERVER,
  593. &m_dwAdvCacheTTL ) )
  594. {
  595. m_dwAdvCacheTTL = DEFAULT_W3_ADV_CACHE_TTL;
  596. }
  597. if ( !mb.GetDword( "",
  598. MD_NET_LOGON_WKS,
  599. IIS_MD_UT_SERVER,
  600. &m_dwNetLogonWks ) )
  601. {
  602. m_dwNetLogonWks = DEFAULT_W3_NET_LOGON_WKS;
  603. }
  604. if ( !mb.GetDword( "",
  605. MD_USE_HOST_NAME,
  606. IIS_MD_UT_SERVER,
  607. &m_dwUseHostName ) )
  608. {
  609. m_dwUseHostName = DEFAULT_W3_USE_HOST_NAME;
  610. }
  611. if ( !mb.GetDword( "",
  612. MD_ALLOW_PATH_INFO_FOR_SCRIPT_MAPPINGS,
  613. IIS_MD_UT_SERVER,
  614. &dwValue ) )
  615. {
  616. m_fAllowPathInfoForScriptMappings = DEFAULT_W3_ALLOW_PATH_INFO_FOR_SCRIPT_MAPPINGS;
  617. }
  618. else
  619. {
  620. m_fAllowPathInfoForScriptMappings = !!dwValue;
  621. }
  622. if ( !mb.GetDword( "",
  623. MD_PROCESS_NTCR_IF_LOGGED_ON,
  624. IIS_MD_UT_SERVER,
  625. &dwValue ) )
  626. {
  627. m_fProcessNtcrIfLoggedOn = DEFAULT_W3_PROCESS_NTCR_IF_LOGGED_ON;
  628. }
  629. else
  630. {
  631. m_fProcessNtcrIfLoggedOn = !!dwValue;
  632. }
  633. if ( !mb.GetBuffer( "",
  634. MD_SSL_CA,
  635. IIS_MD_UT_SERVER,
  636. &m_buSslCa,
  637. &m_dwSslCa ) )
  638. {
  639. m_dwSslCa = 0;
  640. }
  641. //
  642. // Get Job Object Info
  643. // Constructor initialized these to defaults, so don't need to handle
  644. // error case. Do need to handle changes;
  645. //
  646. if ((!mb.GetDword( NULL,
  647. MD_CPU_RESET_INTERVAL,
  648. IIS_MD_UT_SERVER,
  649. &dwValue )) ||
  650. (dwValue == 0) )
  651. {
  652. //
  653. // 0 is invalid and could result in a divide by 0 error
  654. //
  655. dwValue = DEFAULT_W3_CPU_RESET_INTERVAL;
  656. }
  657. if (m_dwJobResetInterval != dwValue)
  658. {
  659. m_dwJobResetInterval = dwValue;
  660. ResetJobResetInterval();
  661. }
  662. LockJobsForWrite();
  663. if (!mb.GetDword( NULL,
  664. MD_CPU_LIMITS_ENABLED,
  665. IIS_MD_UT_SERVER,
  666. &dwValue ))
  667. {
  668. dwValue = FALSE;
  669. }
  670. if ((BOOL)dwValue != m_fCPULimitsEnabled)
  671. {
  672. m_fCPULimitsEnabled = dwValue;
  673. if (m_fCPULimitsEnabled) {
  674. //
  675. // Start the reset interval, completion ports, and limits
  676. //
  677. StartJobs();
  678. }
  679. else {
  680. //
  681. // Start the reset interval, completion ports, and limits
  682. //
  683. StopJobs();
  684. }
  685. }
  686. if ((!mb.GetDword( NULL,
  687. MD_CPU_LOGGING_INTERVAL,
  688. IIS_MD_UT_SERVER,
  689. &dwValue )) ||
  690. (dwValue == 0))
  691. {
  692. dwValue = DEFAULT_W3_CPU_QUERY_INTERVAL;
  693. }
  694. if (m_dwJobQueryInterval != dwValue)
  695. {
  696. m_dwJobQueryInterval = dwValue;
  697. ResetJobQueryInterval();
  698. }
  699. if (!mb.GetDword( NULL,
  700. MD_CPU_LOGGING_MASK,
  701. IIS_MD_UT_SERVER,
  702. &dwValue )) {
  703. dwValue = DEFAULT_W3_CPU_LOGGING_MASK;
  704. }
  705. {
  706. BOOL fLoggingEnabled = ((dwValue & MD_CPU_ENABLE_LOGGING) != 0) ? TRUE : FALSE;
  707. if (m_fCPULoggingEnabled != fLoggingEnabled)
  708. {
  709. m_fCPULoggingEnabled = fLoggingEnabled;
  710. if (m_fCPULoggingEnabled) {
  711. //
  712. // Start the reset interval, logging interval
  713. //
  714. StartJobs();
  715. }
  716. else {
  717. //
  718. // Stop the reset interval, logging interval
  719. //
  720. StopJobs();
  721. }
  722. }
  723. }
  724. if (mb.GetDword( NULL,
  725. MD_CPU_CGI_LIMIT,
  726. IIS_MD_UT_SERVER,
  727. &dwValue ))
  728. {
  729. if (m_dwJobCGICPULimit != dwValue)
  730. {
  731. m_dwJobCGICPULimit = dwValue;
  732. SetJobLimits(SLA_PROCESS_CPU_LIMIT, m_dwJobCGICPULimit);
  733. }
  734. }
  735. mb.GetDword( NULL,
  736. MD_CPU_LOGGING_OPTIONS,
  737. IIS_MD_UT_SERVER,
  738. &m_dwJobLoggingOptions );
  739. BOOL fLimitsChanged = FALSE;
  740. if (mb.GetDword( NULL,
  741. MD_CPU_LIMIT_LOGEVENT,
  742. IIS_MD_UT_SERVER,
  743. &dwValue ))
  744. {
  745. if (m_llJobSiteCPULimitLogEvent != PercentCPULimitToCPUTime(dwValue))
  746. {
  747. m_llJobSiteCPULimitLogEvent = PercentCPULimitToCPUTime(dwValue);
  748. fLimitsChanged = TRUE;
  749. }
  750. }
  751. if (mb.GetDword( NULL,
  752. MD_CPU_LIMIT_PRIORITY,
  753. IIS_MD_UT_SERVER,
  754. &dwValue ))
  755. {
  756. if (m_llJobSiteCPULimitPriority != PercentCPULimitToCPUTime(dwValue))
  757. {
  758. m_llJobSiteCPULimitPriority = PercentCPULimitToCPUTime(dwValue);
  759. fLimitsChanged = TRUE;
  760. }
  761. }
  762. if (mb.GetDword( NULL,
  763. MD_CPU_LIMIT_PROCSTOP,
  764. IIS_MD_UT_SERVER,
  765. &dwValue ))
  766. {
  767. if (m_llJobSiteCPULimitProcStop != PercentCPULimitToCPUTime(dwValue))
  768. {
  769. m_llJobSiteCPULimitProcStop = PercentCPULimitToCPUTime(dwValue);
  770. fLimitsChanged = TRUE;
  771. }
  772. }
  773. if (mb.GetDword( NULL,
  774. MD_CPU_LIMIT_PAUSE,
  775. IIS_MD_UT_SERVER,
  776. &dwValue ))
  777. {
  778. if (m_llJobSiteCPULimitPause != PercentCPULimitToCPUTime(dwValue))
  779. {
  780. m_llJobSiteCPULimitPause = PercentCPULimitToCPUTime(dwValue);
  781. fLimitsChanged = TRUE;
  782. }
  783. }
  784. if (fLimitsChanged) {
  785. SetJobSiteCPULimits(TRUE);
  786. }
  787. UnlockJobs();
  788. mb.Close();
  789. }
  790. #if 0
  791. m_cbUploadReadAhead = ReadRegistryDword( hkey,
  792. W3_UPLOAD_READ_AHEAD,
  793. DEFAULT_W3_UPLOAD_READ_AHEAD );
  794. #endif
  795. m_fUsePoolThreadForCGI = !!ReadRegistryDword( hkey,
  796. W3_USE_POOL_THREAD_FOR_CGI,
  797. DEFAULT_W3_USE_POOL_THREAD_FOR_CGI );
  798. exit:
  799. UnlockThis();
  800. DBG_REQUIRE( !RegCloseKey( hkey ));
  801. DBG_REQUIRE( !RegCloseKey( hDefkey ));
  802. return(fRet);
  803. } // W3_SERVER_INSTANCE::ReadPrivateW3Params
  804. BOOL
  805. W3_SERVER_INSTANCE::ReadPublicW3Params(
  806. IN FIELD_CONTROL fc
  807. )
  808. /*++
  809. Routine Description:
  810. Initializes HTTP parameters from the registry
  811. Arguments:
  812. fc - Items to read
  813. Return Value:
  814. TRUE if successful, FALSE on error
  815. --*/
  816. {
  817. #if 0
  818. DWORD err;
  819. BOOL fRet = TRUE;
  820. HKEY hkeyW3;
  821. //
  822. // Connect to the registry.
  823. //
  824. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  825. QueryRegParamKey( ),
  826. 0,
  827. KEY_ALL_ACCESS,
  828. &hkeyW3 );
  829. if( err != NO_ERROR )
  830. {
  831. DBGPRINTF(( DBG_CONTEXT,
  832. "cannot open registry key, error %lu\n",
  833. err ));
  834. err = NO_ERROR;
  835. }
  836. LockThisForWrite();
  837. //
  838. // Read registry data.
  839. //
  840. UnlockThis( );
  841. RegCloseKey( hkeyW3 );
  842. return fRet;
  843. #endif
  844. return TRUE;
  845. } // W3_SERVER_INSTANCE::ReadPublicW3Params
  846. BOOL
  847. W3_SERVER_INSTANCE::WritePublicW3Params(
  848. IN LPW3_CONFIG_INFO pConfig
  849. )
  850. /*++
  851. Description
  852. Updates the registry with the passed parameters
  853. Arguments:
  854. pConfig - Items to write to the registry
  855. --*/
  856. {
  857. DWORD err;
  858. BOOL fRet = TRUE;
  859. HKEY hkey;
  860. DWORD disp;
  861. //
  862. // Connect to the registry.
  863. //
  864. err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  865. QueryRegParamKey(),
  866. 0,
  867. NULL,
  868. 0,
  869. KEY_READ|KEY_WRITE,
  870. NULL,
  871. &hkey,
  872. &disp );
  873. if( err != NO_ERROR )
  874. {
  875. DBGPRINTF(( DBG_CONTEXT,
  876. "cannot open registry key, error %lu\n",
  877. err ));
  878. return FALSE;
  879. }
  880. //
  881. // Write the strings - Note some of these are written for registry
  882. // compatiblity with pre-metabase applications
  883. //
  884. if ( !err && IsFieldSet( pConfig->FieldControl, FC_W3_DEFAULT_LOAD_FILE )
  885. && (pConfig->lpszDefaultLoadFile != NULL) )
  886. {
  887. err = WriteRegistryStringW( hkey,
  888. W3_DEFAULT_FILE_W,
  889. pConfig->lpszDefaultLoadFile,
  890. (wcslen( pConfig->lpszDefaultLoadFile ) + 1) *
  891. sizeof( WCHAR ),
  892. REG_SZ);
  893. }
  894. if ( hkey )
  895. RegCloseKey( hkey );
  896. if ( err )
  897. {
  898. SetLastError( err );
  899. return FALSE;
  900. }
  901. return TRUE;
  902. } // W3_SERVER_INSTANCE::WritePublicW3Params
  903. VOID
  904. W3_SERVER_INSTANCE::MDChangeNotify(
  905. MD_CHANGE_OBJECT * pcoChangeList
  906. )
  907. /*++
  908. This method handles the metabase change notification for this instance
  909. Arguments:
  910. pcoChangeList - path and id that has changed
  911. --*/
  912. {
  913. DWORD i;
  914. BOOL fFiltersModified = FALSE;
  915. PCSTR pszURL;
  916. DWORD dwURLLength;
  917. BOOL fSslModified = FALSE;
  918. LockThisForWrite();
  919. //
  920. // Tell our parent about the change notification first
  921. //
  922. IIS_SERVER_INSTANCE::MDChangeNotify( pcoChangeList );
  923. //
  924. // Now flush the metacache and relevant file handle cache entries.
  925. //
  926. TsFlushMetaCache(METACACHE_W3_SERVER_ID, FALSE);
  927. if (!IISstrnicmp((PUCHAR)pcoChangeList->pszMDPath, (PUCHAR)QueryMDVRPath(),
  928. IISstrlen( (PUCHAR)QueryMDVRPath() )))
  929. {
  930. pszURL = (CHAR *)pcoChangeList->pszMDPath + QueryMDVRPathLen() - 1;
  931. //
  932. // Figure out the length of the URL. Unless this is the root,
  933. // we want to strip the trailing slash.
  934. if (memcmp(pszURL, "/", sizeof("/")) != 0)
  935. {
  936. dwURLLength = strlen(pszURL) - 1;
  937. }
  938. else
  939. {
  940. dwURLLength = sizeof("/") - 1;
  941. }
  942. }
  943. else
  944. {
  945. //
  946. // Presumably this is for a change above the root URL level, i.e. a
  947. // change of a property at the service level. Since this affects
  948. // everything, flush starting at the root.
  949. //
  950. pszURL = "/";
  951. dwURLLength = sizeof("/") - 1;
  952. }
  953. DBG_ASSERT(pszURL != NULL);
  954. DBG_ASSERT(*pszURL != '\0');
  955. TsFlushURL(GetTsvcCache(), pszURL, dwURLLength, RESERVED_DEMUX_URI_INFO);
  956. BOOL fReadPrivateW3Params = FALSE;
  957. for ( i = 0; i < pcoChangeList->dwMDNumDataIDs; i++ )
  958. {
  959. switch ( pcoChangeList->pdwMDDataIDs[i] )
  960. {
  961. case MD_FILTER_ENABLED:
  962. case MD_FILTER_IMAGE_PATH:
  963. case MD_FILTER_LOAD_ORDER:
  964. if ( fFiltersModified ) // First change will pick up all changes
  965. continue;
  966. if ( !CreateFilterList() )
  967. {
  968. DBGPRINTF(( DBG_CONTEXT,
  969. "Failed to create new filter list\n" ));
  970. }
  971. else
  972. {
  973. fFiltersModified = TRUE;
  974. }
  975. break;
  976. case MD_SERIAL_CERT11: // Cert mapper support
  977. case MD_SERIAL_CERTW:
  978. case MD_SERIAL_DIGEST:
  979. case MD_SERIAL_ITA:
  980. case MD_AUTH_CHANGE_URL:
  981. case MD_AUTH_EXPIRED_URL:
  982. case MD_AUTH_NOTIFY_PWD_EXP_URL:
  983. case MD_AUTH_EXPIRED_UNSECUREURL:
  984. case MD_AUTH_NOTIFY_PWD_EXP_UNSECUREURL:
  985. case MD_ADV_NOTIFY_PWD_EXP_IN_DAYS:
  986. case MD_CERT_CHECK_MODE:
  987. case MD_AUTH_CHANGE_FLAGS:
  988. case MD_ADV_CACHE_TTL:
  989. case MD_NET_LOGON_WKS:
  990. case MD_USE_HOST_NAME:
  991. case MD_ALLOW_PATH_INFO_FOR_SCRIPT_MAPPINGS:
  992. case MD_PROCESS_NTCR_IF_LOGGED_ON:
  993. case MD_CPU_LOGGING_OPTIONS:
  994. case MD_CPU_LOGGING_INTERVAL:
  995. case MD_CPU_RESET_INTERVAL:
  996. case MD_CPU_CGI_LIMIT:
  997. case MD_CPU_LIMIT_LOGEVENT:
  998. case MD_CPU_LIMIT_PRIORITY:
  999. case MD_CPU_LIMIT_PROCSTOP:
  1000. case MD_CPU_LIMIT_PAUSE:
  1001. case MD_CPU_LOGGING_MASK:
  1002. case MD_CPU_LIMITS_ENABLED:
  1003. case MD_SERVER_COMMENT:
  1004. fReadPrivateW3Params = TRUE;
  1005. break;
  1006. //
  1007. // Server cert properties
  1008. //
  1009. case MD_SSL_CERT_HASH:
  1010. case MD_SSL_CERT_CONTAINER:
  1011. case MD_SSL_CERT_PROVIDER:
  1012. case MD_SSL_CERT_OPEN_FLAGS:
  1013. case MD_SSL_CERT_STORE_NAME:
  1014. //
  1015. // Fortezza-specific
  1016. //
  1017. case MD_SSL_CERT_IS_FORTEZZA:
  1018. case MD_SSL_CERT_FORTEZZA_PIN:
  1019. case MD_SSL_CERT_FORTEZZA_SERIAL_NUMBER:
  1020. case MD_SSL_CERT_FORTEZZA_PERSONALITY:
  1021. case MD_SSL_CERT_FORTEZZA_PROG_PIN:
  1022. //
  1023. // Server CTL properties
  1024. //
  1025. case MD_SSL_CTL_IDENTIFIER:
  1026. case MD_SSL_CTL_CONTAINER:
  1027. case MD_SSL_CTL_PROVIDER:
  1028. case MD_SSL_CTL_PROVIDER_TYPE:
  1029. case MD_SSL_CTL_OPEN_FLAGS:
  1030. case MD_SSL_CTL_STORE_NAME:
  1031. case MD_SSL_CTL_SIGNER_HASH:
  1032. case MD_SSL_USE_DS_MAPPER:
  1033. fSslModified = TRUE;
  1034. break;
  1035. case MD_SERVER_STATE:
  1036. switch (QueryServerState()) {
  1037. case MD_SERVER_STATE_STARTED:
  1038. ProcessStartNotification();
  1039. break;
  1040. case MD_SERVER_STATE_STOPPED:
  1041. ProcessStopNotification();
  1042. break;
  1043. case MD_SERVER_STATE_PAUSED:
  1044. ProcessPauseNotification();
  1045. break;
  1046. default:
  1047. ;
  1048. }
  1049. break;
  1050. default:
  1051. break;
  1052. }
  1053. }
  1054. if (fReadPrivateW3Params) {
  1055. if ( !ReadPrivateW3Params() )
  1056. {
  1057. DBGPRINTF(( DBG_CONTEXT,
  1058. "Failed to re-read parameters\n" ));
  1059. }
  1060. }
  1061. UnlockThis();
  1062. //
  1063. // If anything related to SSL has changed, call the function used to flush
  1064. // the SSL/Schannel credential cache and reset the server certificate
  1065. //
  1066. if ( fSslModified )
  1067. {
  1068. ResetSSLInfo( this );
  1069. }
  1070. }
  1071. BOOL
  1072. W3_SERVER_INSTANCE::CreateFilterList(
  1073. VOID
  1074. )
  1075. /*++
  1076. Description
  1077. Creates the list of filters this server instance needs to notify.
  1078. If there's an existing filter list on this instance, the old filter
  1079. list is atomically exchanged and allowed to die off.
  1080. Arguments:
  1081. --*/
  1082. {
  1083. CHAR szFilterKey[MAX_PATH+1];
  1084. FILTER_LIST * pfl;
  1085. FILTER_LIST * pflOld;
  1086. DWORD cb;
  1087. DWORD fEnabled;
  1088. CHAR szLoadOrder[1024];
  1089. CHAR szDllName[MAX_PATH+1];
  1090. CHAR * pchFilter;
  1091. CHAR * pchComma;
  1092. MB mb( (IMDCOM*) g_pInetSvc->QueryMDObject() );
  1093. BOOL fOpened;
  1094. strcpy( szFilterKey, QueryMDPath() );
  1095. strcat( szFilterKey, IIS_MD_ISAPI_FILTERS );
  1096. DBG_ASSERT( strlen( szFilterKey ) + 1 < sizeof( szFilterKey ));
  1097. //
  1098. // Create a filter list for this instance
  1099. //
  1100. pfl = new FILTER_LIST();
  1101. if ( !pfl || !pfl->InsertGlobalFilters() ) {
  1102. delete pfl;
  1103. return FALSE;
  1104. }
  1105. //
  1106. // Loop through filter keys, if we can't access the metabase, we assume
  1107. // success and continue
  1108. //
  1109. if ( mb.Open( szFilterKey,
  1110. METADATA_PERMISSION_READ ))
  1111. {
  1112. fOpened = TRUE;
  1113. //
  1114. // Get the filter load order
  1115. //
  1116. cb = sizeof( szLoadOrder );
  1117. *szLoadOrder = '\0';
  1118. if ( mb.GetString( "",
  1119. MD_FILTER_LOAD_ORDER,
  1120. IIS_MD_UT_SERVER,
  1121. szLoadOrder,
  1122. &cb,
  1123. 0 ))
  1124. {
  1125. pchFilter = szLoadOrder;
  1126. while ( *pchFilter )
  1127. {
  1128. if ( !fOpened &&
  1129. !mb.Open( szFilterKey, METADATA_PERMISSION_READ ))
  1130. {
  1131. DBGPRINTF(( DBG_CONTEXT,
  1132. "CreateFilterList: Cannot open path %s, error %lu\n",
  1133. szFilterKey, GetLastError() ));
  1134. break;
  1135. }
  1136. fOpened = TRUE;
  1137. pchComma = strchr( pchFilter, ',' );
  1138. if ( pchComma )
  1139. {
  1140. *pchComma = '\0';
  1141. }
  1142. while ( ISWHITEA( *pchFilter ))
  1143. {
  1144. pchFilter++;
  1145. }
  1146. fEnabled = TRUE;
  1147. mb.GetDword( pchFilter,
  1148. MD_FILTER_ENABLED,
  1149. IIS_MD_UT_SERVER,
  1150. &fEnabled );
  1151. if ( fEnabled )
  1152. {
  1153. cb = sizeof(szDllName);
  1154. if ( mb.GetString( pchFilter,
  1155. MD_FILTER_IMAGE_PATH,
  1156. IIS_MD_UT_SERVER,
  1157. szDllName,
  1158. &cb,
  1159. 0 ))
  1160. {
  1161. mb.Close();
  1162. fOpened = FALSE;
  1163. if ( pfl->LoadFilter( &mb, szFilterKey, &fOpened, pchFilter, szDllName, FALSE ))
  1164. {
  1165. DBGPRINTF(( DBG_CONTEXT,
  1166. "[CreateFilterList] Loaded %s\n",
  1167. szDllName ));
  1168. }
  1169. }
  1170. }
  1171. if ( pchComma )
  1172. {
  1173. pchFilter = pchComma + 1;
  1174. }
  1175. else
  1176. {
  1177. break;
  1178. }
  1179. }
  1180. }
  1181. }
  1182. //
  1183. // Replace the old filter list with the new filter list
  1184. //
  1185. LockThisForWrite();
  1186. pflOld = m_pFilterList;
  1187. m_pFilterList = pfl;
  1188. UnlockThis();
  1189. if ( pflOld ) {
  1190. FILTER_LIST::Dereference( pflOld );
  1191. }
  1192. return TRUE;
  1193. }
  1194. #if 0
  1195. BOOL
  1196. W3_SERVER_INSTANCE::UpdateFilterList(
  1197. CHAR * pszNewDll,
  1198. CHAR * pszOldDll
  1199. )
  1200. /*++
  1201. Description
  1202. Given a filter dll to replace on this instance, this routine updates
  1203. the filter list with the new dll and lets the old filter list die off
  1204. Arguments:
  1205. pszNewDll - Fully Qualified path to new dll - may be NULL
  1206. pszOldDll - The DLL this filter is replacing (or NULL for just adding a
  1207. new Filter)
  1208. --*/
  1209. {
  1210. FILTER_LIST * pfl;
  1211. FILTER_LIST * pflOld;
  1212. DBG_ASSERT( m_pFilterList );
  1213. //
  1214. // Create a new filter list for this instance and copy the old filter list
  1215. //
  1216. pfl = new FILTER_LIST();
  1217. if ( !pfl ||
  1218. !pfl->Copy( m_pFilterList ) ||
  1219. !pfl->LoadFilter( pszNewDll, FALSE ) ||
  1220. !pfl->Remove( pszOldDll ))
  1221. {
  1222. DBGPRINTF(( DBG_CONTEXT,
  1223. "[UpdateFilterList] Failed - Error %d\n",
  1224. GetLastError() ));
  1225. delete pfl;
  1226. return FALSE;
  1227. }
  1228. //
  1229. // Replace the old filter list with the new filter list
  1230. //
  1231. LockThisForWrite();
  1232. pflOld = m_pFilterList;
  1233. m_pFilterList = pfl;
  1234. UnlockThis();
  1235. if ( pflOld ) {
  1236. FILTER_LIST::Dereference( pflOld );
  1237. }
  1238. return TRUE;
  1239. }
  1240. #endif
  1241. APIERR
  1242. W3_SERVER_INSTANCE::InitializeHostName(
  1243. VOID
  1244. )
  1245. /*++
  1246. Routine Description:
  1247. Initializes the default host name
  1248. Arguments:
  1249. None
  1250. Return Value:
  1251. Win32
  1252. --*/
  1253. {
  1254. //
  1255. // Build Host Name to be used in URL creation
  1256. //
  1257. if ( m_dwUseHostName )
  1258. {
  1259. char hn[128];
  1260. PHOSTENT pH;
  1261. if ( !gethostname( hn, sizeof(hn) )
  1262. && (pH = gethostbyname( hn ))
  1263. && pH->h_name
  1264. && pH->h_addr_list
  1265. && pH->h_addr_list[0]
  1266. #if 0
  1267. // disabled for now : if the UseHostName flag is set,
  1268. // we will always use the DNS name specified in the
  1269. // TCP/IP configuration panel
  1270. //
  1271. && pH->h_addr_list[1] == NULL
  1272. #endif
  1273. )
  1274. {
  1275. m_pszDefaultHostName = (PCHAR)TCP_ALLOC(strlen( pH->h_name ) + 1);
  1276. if ( m_pszDefaultHostName == NULL )
  1277. {
  1278. return(ERROR_NOT_ENOUGH_MEMORY);
  1279. }
  1280. strcpy( m_pszDefaultHostName, pH->h_name );
  1281. if ( m_pszDefaultHostName[0] == '\0' ) {
  1282. TCP_FREE(m_pszDefaultHostName);
  1283. m_pszDefaultHostName = NULL;
  1284. }
  1285. }
  1286. }
  1287. return(NO_ERROR);
  1288. } // W3_SERVER_INSTANCE::InitializeHostName
  1289. VOID
  1290. W3_SERVER_INSTANCE::CleanupRegistryStrings(
  1291. VOID
  1292. )
  1293. /*++
  1294. Description
  1295. Frees all configurable strings in the W3_SERVER_INSTANCE class
  1296. Arguments:
  1297. None.
  1298. --*/
  1299. {
  1300. DWORD i = 0;
  1301. if ( m_pszAccessDeniedMsg != NULL ) {
  1302. TCP_FREE(m_pszAccessDeniedMsg);
  1303. m_pszAccessDeniedMsg = NULL;
  1304. }
  1305. return;
  1306. } // W3_SERVER_INSTANCE::CleanupRegistryStrings
  1307. LPVOID
  1308. W3_SERVER_INSTANCE::QueryMapper(
  1309. MAPPER_TYPE mt
  1310. )
  1311. /*++
  1312. Description
  1313. Returns mapper
  1314. Arguments:
  1315. mt - mapper type
  1316. Returns:
  1317. ptr to Blob referencing mapper or NULL if no such mapper
  1318. --*/
  1319. {
  1320. LPVOID pV;
  1321. LockThisForRead();
  1322. if ( pV = m_apMappers[(UINT)mt] )
  1323. {
  1324. ((RefBlob*)pV)->AddRef();
  1325. }
  1326. else
  1327. {
  1328. pV = NULL;
  1329. }
  1330. UnlockThis();
  1331. return pV;
  1332. }
  1333. IIS_SSL_INFO*
  1334. W3_SERVER_INSTANCE::GetAndReferenceSSLInfoObj( VOID )
  1335. /*++
  1336. Description
  1337. Returns SSL info for this instance; calls Reference() before returning
  1338. Arguments:
  1339. Returns:
  1340. Ptr to SSL info object on success, NULL if failure
  1341. --*/
  1342. {
  1343. IIS_SSL_INFO *pPtr = NULL;
  1344. LockThisForRead();
  1345. //
  1346. // If it's null, we may have to create it - unlock, lock for write and make sure it's
  1347. // still NULL before creating it
  1348. //
  1349. if ( !m_pSSLInfo )
  1350. {
  1351. UnlockThis();
  1352. LockThisForWrite();
  1353. //
  1354. // Still null, so create it now
  1355. //
  1356. if ( !m_pSSLInfo )
  1357. {
  1358. m_pSSLInfo = IIS_SSL_INFO::CreateSSLInfo(
  1359. (LPTSTR) QueryMDPath(),
  1360. (IMDCOM *) g_pInetSvc->QueryMDObject() );
  1361. if ( m_pSSLInfo == NULL )
  1362. {
  1363. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1364. UnlockThis();
  1365. return NULL;
  1366. }
  1367. //
  1368. // Acquire an internal reference
  1369. //
  1370. m_pSSLInfo->Reference();
  1371. //
  1372. // Construct the server certificate and CTL and log
  1373. // the status
  1374. //
  1375. IIS_SERVER_CERT *pCert = m_pSSLInfo->GetCertificate();
  1376. if ( pCert )
  1377. {
  1378. LogCertStatus();
  1379. }
  1380. IIS_CTL *pCTL = m_pSSLInfo->GetCTL();
  1381. if ( pCTL )
  1382. {
  1383. LogCTLStatus();
  1384. }
  1385. //
  1386. // Register for changes
  1387. //
  1388. if ( g_pStoreChangeNotifier )
  1389. {
  1390. if ( pCert && pCert->IsValid() )
  1391. {
  1392. //
  1393. // Watch for changes to the store the cert came out of
  1394. //
  1395. if (!g_pStoreChangeNotifier->RegisterStoreForChange( pCert->QueryStoreName(),
  1396. pCert->QueryStoreHandle(),
  1397. ResetSSLInfo,
  1398. (PVOID) this ) )
  1399. {
  1400. DBGPRINTF((DBG_CONTEXT,
  1401. "Failed to register for change event on store %s\n",
  1402. pCert->QueryStoreName()));
  1403. }
  1404. }
  1405. if ( pCTL && pCTL->IsValid() )
  1406. {
  1407. //
  1408. // Watch for changes to the store the CTL came out of
  1409. //
  1410. if (!g_pStoreChangeNotifier->RegisterStoreForChange( pCTL->QueryStoreName(),
  1411. pCTL->QueryOriginalStore(),
  1412. ResetSSLInfo,
  1413. (PVOID) this ) )
  1414. {
  1415. DBGPRINTF((DBG_CONTEXT,
  1416. "Failed to register for change event on store %s\n",
  1417. pCTL->QueryStoreName()));
  1418. }
  1419. }
  1420. if ( ( pCert && pCert->IsValid()) ||
  1421. ( pCTL && pCTL->IsValid() ) )
  1422. {
  1423. HCERTSTORE hRootStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  1424. 0,
  1425. NULL,
  1426. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  1427. "ROOT" );
  1428. if ( hRootStore )
  1429. {
  1430. //
  1431. // Watch for changes to the ROOT store
  1432. //
  1433. if ( !g_pStoreChangeNotifier->RegisterStoreForChange( "ROOT",
  1434. hRootStore,
  1435. ResetSSLInfo,
  1436. (PVOID) this ) )
  1437. {
  1438. DBGPRINTF((DBG_CONTEXT,
  1439. "Failed to register for change event on root store\n"));
  1440. }
  1441. CertCloseStore( hRootStore,
  1442. 0 );
  1443. }
  1444. else
  1445. {
  1446. DBGPRINTF((DBG_CONTEXT,
  1447. "Failed to open ROOT store, error 0x%d\n",
  1448. GetLastError()));
  1449. }
  1450. } // if ( pCert || pCTL )
  1451. } // if (g_pStoreChangeNotifier)
  1452. } // if ( !m_pSSLInfo )
  1453. } //if ( !m_pSSLInfo )
  1454. //
  1455. // At this point, m_pSSLInfo should not be NULL anymore, so add the external reference
  1456. //
  1457. m_pSSLInfo->Reference();
  1458. pPtr = m_pSSLInfo;
  1459. UnlockThis();
  1460. return pPtr;
  1461. }
  1462. BOOL
  1463. SetFlushMapperNotify(
  1464. SF_NOTIFY_TYPE nt,
  1465. PFN_SF_NOTIFY pFn
  1466. )
  1467. /*++
  1468. Description
  1469. Set the function called to notify that a mapper is being flushed
  1470. Can be called only once for a given mapper type
  1471. Arguments:
  1472. nt - notification type
  1473. pFn - function to call to notify mapper flushed
  1474. Returns:
  1475. TRUE if function reference stored, FALSE otherwise
  1476. --*/
  1477. {
  1478. MAPPER_TYPE mt;
  1479. switch ( nt )
  1480. {
  1481. case SF_NOTIFY_MAPPER_MD5_CHANGED:
  1482. mt = MT_MD5;
  1483. break;
  1484. case SF_NOTIFY_MAPPER_ITA_CHANGED:
  1485. mt = MT_ITA;
  1486. break;
  1487. case SF_NOTIFY_MAPPER_CERT11_CHANGED:
  1488. mt = MT_CERT11;
  1489. break;
  1490. case SF_NOTIFY_MAPPER_CERTW_CHANGED:
  1491. mt = MT_CERTW;
  1492. break;
  1493. default:
  1494. return FALSE;
  1495. }
  1496. if ( g_pFlushMapperNotify[(UINT)mt] == NULL || pFn == NULL )
  1497. {
  1498. g_pFlushMapperNotify[(UINT)mt] = pFn;
  1499. return TRUE;
  1500. }
  1501. return FALSE;
  1502. }
  1503. VOID W3_SERVER_INSTANCE::ResetSSLInfo( LPVOID pvParam )
  1504. /*++
  1505. Description:
  1506. Wrapper function for function to call to notify of SSL changes
  1507. Arguments:
  1508. pvParam - pointer to instance for which SSL keys have changed
  1509. Returns:
  1510. Nothing
  1511. --*/
  1512. {
  1513. //
  1514. // Call function to flush credential cache etc
  1515. //
  1516. if ( g_pSslKeysNotify )
  1517. {
  1518. g_pSslKeysNotify( SF_NOTIFY_MAPPER_SSLKEYS_CHANGED,
  1519. pvParam );
  1520. }
  1521. W3_SERVER_INSTANCE *pInst = (W3_SERVER_INSTANCE *) pvParam;
  1522. //
  1523. // Clean up all the SSL information associated with this instance
  1524. //
  1525. pInst->LockThisForRead();
  1526. if ( pInst->m_pSSLInfo )
  1527. {
  1528. pInst->UnlockThis();
  1529. pInst->LockThisForWrite();
  1530. if ( pInst->m_pSSLInfo )
  1531. {
  1532. //
  1533. // Stop watching for change notifications
  1534. //
  1535. IIS_SERVER_CERT *pCert = pInst->m_pSSLInfo->QueryCertificate();
  1536. IIS_CTL *pCTL = pInst->m_pSSLInfo->QueryCTL();
  1537. if ( g_pStoreChangeNotifier )
  1538. {
  1539. //
  1540. // Stop watching the store the cert came out of
  1541. //
  1542. if ( pCert && pCert->IsValid() )
  1543. {
  1544. g_pStoreChangeNotifier->UnregisterStore( pCert->QueryStoreName(),
  1545. ResetSSLInfo,
  1546. (PVOID) pvParam );
  1547. }
  1548. //
  1549. // Stop watching the store the CTL came out of
  1550. //
  1551. if ( pCTL && pCTL->IsValid() )
  1552. {
  1553. g_pStoreChangeNotifier->UnregisterStore( pCTL->QueryStoreName(),
  1554. ResetSSLInfo,
  1555. (PVOID) pvParam );
  1556. }
  1557. //
  1558. // Stop watching the ROOT store
  1559. //
  1560. g_pStoreChangeNotifier->UnregisterStore( "ROOT",
  1561. ResetSSLInfo,
  1562. (PVOID) pvParam );
  1563. }
  1564. pInst->m_pSSLInfo->ReleaseFortezzaHandlers();
  1565. //
  1566. // Release internal reference
  1567. //
  1568. IIS_SSL_INFO::Release( pInst->m_pSSLInfo );
  1569. //
  1570. // Next call to GetAndReferenceSSLObj() will create it again
  1571. //
  1572. pInst->m_pSSLInfo = NULL;
  1573. }
  1574. }
  1575. pInst->UnlockThis();
  1576. }
  1577. VOID W3_SERVER_INSTANCE::LogCertStatus()
  1578. /*++
  1579. Description:
  1580. Writes system log event about status of server certificate if the cert is in some
  1581. way not quite kosher eg expired, revoked, not signature-valid
  1582. Arguments:
  1583. None
  1584. Returns:
  1585. Nothing
  1586. --*/
  1587. {
  1588. DBG_ASSERT( m_pSSLInfo );
  1589. DWORD dwCertValidity = 0;
  1590. //
  1591. // If we didn't construct the cert fully, log an error
  1592. //
  1593. if ( !m_pSSLInfo->QueryCertificate()->IsValid() )
  1594. {
  1595. CONST CHAR *apszMsgs[2];
  1596. CHAR achInstance[20];
  1597. CHAR achErrorNumber[20];
  1598. wsprintf( achInstance,
  1599. "%lu",
  1600. QueryInstanceId() );
  1601. wsprintf( achErrorNumber,
  1602. "0x%x",
  1603. GetLastError() );
  1604. apszMsgs[0] = achInstance;
  1605. apszMsgs[1] = achErrorNumber;
  1606. DWORD dwStatus = m_pSSLInfo->QueryCertificate()->Status();
  1607. DWORD dwStringID = 0;
  1608. DBGPRINTF((DBG_CONTEXT,
  1609. "Couldn't retrieve server cert; status : %d\n",
  1610. dwStatus));
  1611. switch ( dwStatus )
  1612. {
  1613. case CERT_ERR_MB:
  1614. dwStringID = SSL_MSG_CERT_MB_ERROR;
  1615. break;
  1616. case CERT_ERR_CAPI:
  1617. dwStringID = SSL_MSG_CERT_CAPI_ERROR;
  1618. break;
  1619. case CERT_ERR_CERT_NOT_FOUND:
  1620. dwStringID = SSL_MSG_CERT_NOT_FOUND;
  1621. break;
  1622. default:
  1623. dwStringID = SSL_MSG_CERT_INTERNAL_ERROR;
  1624. break;
  1625. }
  1626. g_pInetSvc->LogEvent( dwStringID,
  1627. 2,
  1628. apszMsgs,
  1629. 0 );
  1630. return;
  1631. }
  1632. //
  1633. // If cert is invalid in some other way , write the appropriate log message
  1634. //
  1635. if ( m_pSSLInfo->QueryCertValidity( &dwCertValidity ) )
  1636. {
  1637. const CHAR *apszMsgs[1];
  1638. CHAR achInstance[20];
  1639. wsprintfA( achInstance,
  1640. "%lu",
  1641. QueryInstanceId() );
  1642. apszMsgs[0] = achInstance;
  1643. DWORD dwMsgID = 0;
  1644. if ( ( dwCertValidity & CERT_TRUST_IS_NOT_TIME_VALID ) ||
  1645. ( dwCertValidity & CERT_TRUST_IS_NOT_TIME_NESTED ) ||
  1646. ( dwCertValidity & CERT_TRUST_CTL_IS_NOT_TIME_VALID ) )
  1647. {
  1648. DBGPRINTF((DBG_CONTEXT,
  1649. "Server cert/CTL is not time-valid or time-nested\n"));
  1650. dwMsgID = SSL_MSG_TIME_INVALID_SERVER_CERT;
  1651. }
  1652. if ( dwCertValidity & CERT_TRUST_IS_REVOKED )
  1653. {
  1654. DBGPRINTF((DBG_CONTEXT,
  1655. "Server Cert is revoked\n"));
  1656. dwMsgID = SSL_MSG_REVOKED_SERVER_CERT;
  1657. }
  1658. if ( ( dwCertValidity & CERT_TRUST_IS_UNTRUSTED_ROOT ) ||
  1659. ( dwCertValidity & CERT_TRUST_IS_PARTIAL_CHAIN ) )
  1660. {
  1661. DBGPRINTF((DBG_CONTEXT,
  1662. "Server Cert doesn't chain up to a trusted root\n"));
  1663. dwMsgID = SSL_MSG_UNTRUSTED_SERVER_CERT;
  1664. }
  1665. if ( ( dwCertValidity & CERT_TRUST_IS_NOT_SIGNATURE_VALID ) ||
  1666. ( dwCertValidity & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID ) )
  1667. {
  1668. DBGPRINTF((DBG_CONTEXT,
  1669. "Server Cert/CTL is not signature valid\n"));
  1670. dwMsgID = SSL_MSG_SIGNATURE_INVALID_SERVER_CERT;
  1671. }
  1672. if ( dwMsgID )
  1673. {
  1674. g_pInetSvc->LogEvent( dwMsgID,
  1675. 1,
  1676. apszMsgs,
  1677. 0 ) ;
  1678. }
  1679. }
  1680. }
  1681. VOID W3_SERVER_INSTANCE::LogCTLStatus()
  1682. /*++
  1683. Description:
  1684. Writes system log event about status of server CTL if CTL isn't valid
  1685. Arguments:
  1686. None
  1687. Returns:
  1688. Nothing
  1689. --*/
  1690. {
  1691. DBG_ASSERT( m_pSSLInfo );
  1692. //
  1693. // If we didn't construct the CTL fully, log an error
  1694. //
  1695. if ( !m_pSSLInfo->QueryCTL()->IsValid() )
  1696. {
  1697. CONST CHAR *apszMsgs[2];
  1698. CHAR achInstance[20];
  1699. CHAR achErrorNumber[20];
  1700. wsprintf( achInstance,
  1701. "%lu",
  1702. QueryInstanceId() );
  1703. wsprintf( achErrorNumber,
  1704. "0x%x",
  1705. GetLastError() );
  1706. apszMsgs[0] = achInstance;
  1707. apszMsgs[1] = achErrorNumber;
  1708. DWORD dwStatus = m_pSSLInfo->QueryCTL()->QueryStatus();
  1709. DWORD dwStringID = 0;
  1710. DBGPRINTF((DBG_CONTEXT,
  1711. "Couldn't retrieve server CTL; status : %d\n",
  1712. dwStatus));
  1713. switch ( dwStatus )
  1714. {
  1715. case CERT_ERR_MB:
  1716. dwStringID = SSL_MSG_CTL_MB_ERROR;
  1717. break;
  1718. case CERT_ERR_CAPI:
  1719. dwStringID = SSL_MSG_CTL_CAPI_ERROR;
  1720. break;
  1721. case CERT_ERR_CERT_NOT_FOUND:
  1722. dwStringID = SSL_MSG_CTL_NOT_FOUND;
  1723. break;
  1724. default:
  1725. dwStringID = SSL_MSG_CTL_INTERNAL_ERROR;
  1726. break;
  1727. }
  1728. g_pInetSvc->LogEvent( dwStringID,
  1729. 2,
  1730. apszMsgs,
  1731. 0 );
  1732. return;
  1733. }
  1734. }
  1735. BOOL
  1736. SetSllKeysNotify(
  1737. PFN_SF_NOTIFY pFn
  1738. )
  1739. /*++
  1740. Description
  1741. Set the function called to notify SSL keys have changed
  1742. Can be called only once
  1743. Arguments:
  1744. pFn - function to call to notify SSL keys change
  1745. Returns:
  1746. TRUE if function reference stored, FALSE otherwise
  1747. --*/
  1748. {
  1749. if ( g_pSslKeysNotify == NULL || pFn == NULL )
  1750. {
  1751. g_pSslKeysNotify = pFn;
  1752. return TRUE;
  1753. }
  1754. return FALSE;
  1755. }