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.

579 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. w3site.cxx
  5. Abstract:
  6. W3_SITE object holds state for each site
  7. Author:
  8. Anil Ruia (AnilR) 18-Jan-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.hxx"
  12. //
  13. // No advance notification
  14. //
  15. #define DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS 14
  16. //
  17. // OWA change flags
  18. //
  19. #define DEFAULT_W3_AUTH_CHANGE_FLAGS 6
  20. //
  21. // In seconds
  22. //
  23. #define DEFAULT_W3_ADV_CACHE_TTL ( 10 * 60 )
  24. //static
  25. CRITICAL_SECTION W3_SITE::sm_csIISCertMapLock;
  26. W3_SITE::W3_SITE(
  27. DWORD SiteId
  28. ) : m_SiteId ( SiteId ),
  29. m_cRefs ( 1 ),
  30. m_pInstanceFilterList ( NULL ),
  31. m_pLogging ( NULL ),
  32. m_fAllowPathInfoForScriptMappings ( FALSE ),
  33. m_fUseDSMapper ( FALSE ),
  34. m_dwAuthChangeFlags ( 0 ),
  35. m_dwAdvNotPwdExpInDays ( DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS ),
  36. m_dwAdvCacheTTL ( DEFAULT_W3_ADV_CACHE_TTL ),
  37. m_fSSLSupported ( FALSE ),
  38. m_pIISCertMap ( NULL ),
  39. m_fAlreadyAttemptedToLoadIISCertMap ( FALSE ),
  40. m_Signature ( W3_SITE_SIGNATURE )
  41. {
  42. ZeroMemory(&m_PerfCounters, sizeof m_PerfCounters);
  43. }
  44. W3_SITE::~W3_SITE()
  45. {
  46. if (m_pInstanceFilterList != NULL)
  47. {
  48. m_pInstanceFilterList->Dereference();
  49. m_pInstanceFilterList = NULL;
  50. }
  51. if (m_pLogging != NULL)
  52. {
  53. m_pLogging->Release();
  54. m_pLogging = NULL;
  55. }
  56. if ( m_pIISCertMap != NULL )
  57. {
  58. m_pIISCertMap->DereferenceCertMapping();
  59. m_pIISCertMap = NULL;
  60. }
  61. m_Signature = W3_SITE_SIGNATURE_FREE;
  62. }
  63. HRESULT
  64. W3_SITE::Initialize(LOGGING *pLogging,
  65. FILTER_LIST *pFilterList)
  66. /*++
  67. Routine Description:
  68. Initialize W3_SITE. Should be called after constructor
  69. Arguments:
  70. None
  71. Return Value:
  72. HRESULT
  73. --*/
  74. {
  75. HRESULT hr = NO_ERROR;
  76. WCHAR idToStr[MAX_SITEID_LENGTH + 6];
  77. CHAR idToStrA[MAX_SITEID_LENGTH + 6];
  78. //
  79. // Setup Site Name like "W3SVC1"
  80. //
  81. sprintf(idToStrA, "W3SVC%u", m_SiteId);
  82. if (FAILED(hr = m_SiteName.Copy(idToStrA)))
  83. {
  84. goto Failure;
  85. }
  86. //
  87. // Setup site path (like "/LM/W3SVC/1")
  88. //
  89. hr = m_SiteMBPath.Copy(g_pW3Server->QueryMDPath());
  90. if ( FAILED( hr ) )
  91. {
  92. goto Failure;
  93. }
  94. _itow(m_SiteId, idToStr, 10);
  95. hr = m_SiteMBPath.Append( idToStr );
  96. if ( FAILED( hr ) )
  97. {
  98. goto Failure;
  99. }
  100. //
  101. // Setup site root (like "/LM/W3SVC/1/ROOT/")
  102. //
  103. hr = m_SiteMBRoot.Copy( m_SiteMBPath );
  104. if ( FAILED( hr ) )
  105. {
  106. goto Failure;
  107. }
  108. hr = m_SiteMBRoot.Append( L"/Root/" );
  109. if ( FAILED( hr ) )
  110. {
  111. goto Failure;
  112. }
  113. //
  114. // Read the per-site properties from the metabase
  115. //
  116. if (FAILED(hr = ReadPrivateProperties()))
  117. {
  118. goto Failure;
  119. }
  120. //
  121. // Initialize instance filters
  122. //
  123. if (pFilterList)
  124. {
  125. pFilterList->Reference();
  126. m_pInstanceFilterList = pFilterList;
  127. }
  128. else
  129. {
  130. m_pInstanceFilterList = new FILTER_LIST();
  131. if (m_pInstanceFilterList == NULL)
  132. {
  133. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  134. goto Failure;
  135. }
  136. hr = m_pInstanceFilterList->InsertGlobalFilters();
  137. if (FAILED(hr))
  138. {
  139. goto Failure;
  140. }
  141. hr = m_pInstanceFilterList->LoadFilters(m_SiteMBPath.QueryStr(),
  142. FALSE);
  143. if (FAILED(hr))
  144. {
  145. goto Failure;
  146. }
  147. }
  148. //
  149. // Initialize logging
  150. //
  151. if (pLogging)
  152. {
  153. pLogging->AddRef();
  154. m_pLogging = pLogging;
  155. }
  156. else
  157. {
  158. m_pLogging = new LOGGING;
  159. if (m_pLogging == NULL)
  160. {
  161. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  162. goto Failure;
  163. }
  164. if(FAILED(hr = m_pLogging->ActivateLogging(m_SiteName.QueryStr(),
  165. m_SiteMBPath.QueryStr(),
  166. g_pW3Server->QueryMDObject())))
  167. {
  168. goto Failure;
  169. }
  170. }
  171. return S_OK;
  172. Failure:
  173. return hr;
  174. }
  175. HRESULT W3_SITE::ReadPrivateProperties()
  176. /*++
  177. Routine description:
  178. Read the site specific properties from the metabase
  179. Arguments:
  180. none
  181. Return Value:
  182. HRESULT
  183. --*/
  184. {
  185. MB mb( g_pW3Server->QueryMDObject() );
  186. MULTISZ mszSecureBindings;
  187. //
  188. // Read per-site properties from the metabase
  189. //
  190. if ( !mb.Open(m_SiteMBPath.QueryStr()) )
  191. {
  192. return HRESULT_FROM_WIN32(GetLastError());
  193. }
  194. if ( !mb.GetDword(L"",
  195. MD_ALLOW_PATH_INFO_FOR_SCRIPT_MAPPINGS,
  196. IIS_MD_UT_FILE,
  197. (DWORD *)&m_fAllowPathInfoForScriptMappings,
  198. 0) )
  199. {
  200. m_fAllowPathInfoForScriptMappings = FALSE;
  201. }
  202. mb.GetStr( L"",
  203. MD_AUTH_CHANGE_URL,
  204. IIS_MD_UT_SERVER,
  205. &m_strAuthChangeUrl );
  206. mb.GetStr( L"",
  207. MD_AUTH_EXPIRED_URL,
  208. IIS_MD_UT_SERVER,
  209. &m_strAuthExpiredUrl );
  210. mb.GetStr( L"",
  211. MD_AUTH_NOTIFY_PWD_EXP_URL,
  212. IIS_MD_UT_SERVER,
  213. &m_strAdvNotPwdExpUrl );
  214. mb.GetStr( L"",
  215. MD_AUTH_EXPIRED_UNSECUREURL,
  216. IIS_MD_UT_SERVER,
  217. &m_strAuthExpiredUnsecureUrl );
  218. mb.GetStr( L"",
  219. MD_AUTH_NOTIFY_PWD_EXP_UNSECUREURL,
  220. IIS_MD_UT_SERVER,
  221. &m_strAdvNotPwdExpUnsecureUrl );
  222. if ( !mb.GetDword( L"",
  223. MD_ADV_NOTIFY_PWD_EXP_IN_DAYS,
  224. IIS_MD_UT_SERVER,
  225. &m_dwAdvNotPwdExpInDays ) )
  226. {
  227. m_dwAdvNotPwdExpInDays = DEFAULT_W3_ADV_NOT_PWD_EXP_IN_DAYS;
  228. }
  229. if ( !mb.GetDword( L"",
  230. MD_AUTH_CHANGE_FLAGS,
  231. IIS_MD_UT_SERVER,
  232. &m_dwAuthChangeFlags ) )
  233. {
  234. m_dwAuthChangeFlags = DEFAULT_W3_AUTH_CHANGE_FLAGS;
  235. }
  236. if ( !mb.GetDword( L"",
  237. MD_ADV_CACHE_TTL,
  238. IIS_MD_UT_SERVER,
  239. &m_dwAdvCacheTTL ) )
  240. {
  241. m_dwAdvCacheTTL = DEFAULT_W3_ADV_CACHE_TTL;
  242. }
  243. //
  244. // Read the secure bindings.
  245. //
  246. if ( mb.GetMultisz( L"",
  247. MD_SECURE_BINDINGS,
  248. IIS_MD_UT_SERVER,
  249. &mszSecureBindings ) )
  250. {
  251. if( !mszSecureBindings.IsEmpty() )
  252. {
  253. m_fSSLSupported = TRUE;
  254. }
  255. }
  256. DBG_REQUIRE( mb.Close() );
  257. //
  258. // Read global properties from the metabase that affect site config
  259. //
  260. if ( !mb.Open(g_pW3Server->QueryMDPath()) )
  261. {
  262. return HRESULT_FROM_WIN32(GetLastError());
  263. }
  264. if ( !mb.GetDword( L"",
  265. MD_SSL_USE_DS_MAPPER,
  266. IIS_MD_UT_SERVER,
  267. (DWORD*) &m_fUseDSMapper,
  268. 0 ))
  269. {
  270. m_fUseDSMapper = FALSE;
  271. }
  272. DBG_REQUIRE( mb.Close() );
  273. return S_OK;
  274. }
  275. HRESULT
  276. W3_SITE::HandleMetabaseChange(
  277. const MD_CHANGE_OBJECT &ChangeObject,
  278. IN W3_SITE_LIST *pTempSiteList
  279. )
  280. /*++
  281. Routine Description:
  282. Handle metabase changes. The change may be to
  283. either the /LM/W3SVC/ node or they may be
  284. changes to this site or one of its children.
  285. This routine needs to perform cache flushes
  286. and reget site metadata if necessary.
  287. Arguments:
  288. ChangeObject
  289. Return Value:
  290. See W3_SERVER_INSTANCE::MDChangeNotify and
  291. IIS_SERVER_INSTANCE::MDChangeNotify for
  292. implemenation details
  293. --*/
  294. {
  295. DBGPRINTF(( DBG_CONTEXT,
  296. "W3_SITE Notified - Path(%S) Type(%d) NumIds(%08x)\n",
  297. ChangeObject.pszMDPath,
  298. ChangeObject.dwMDChangeType,
  299. ChangeObject.dwMDNumDataIDs
  300. ));
  301. //
  302. // Let the cache manager invalidate the various cache entries dependent
  303. // on metadata
  304. //
  305. W3CacheDoMetadataInvalidation( ChangeObject.pszMDPath,
  306. wcslen( ChangeObject.pszMDPath ) );
  307. //
  308. // Handle any site level change
  309. // That means any changes at /LM/w3svc/n or /LM/w3svc/n/Filters
  310. //
  311. if ((_wcsnicmp(ChangeObject.pszMDPath,
  312. m_SiteMBPath.QueryStr(),
  313. m_SiteMBPath.QueryCCH()) == 0) &&
  314. ((wcscmp(ChangeObject.pszMDPath + m_SiteMBPath.QueryCCH(),
  315. L"/") == 0) ||
  316. (_wcsicmp(ChangeObject.pszMDPath + m_SiteMBPath.QueryCCH(),
  317. L"/Filters/") == 0)))
  318. {
  319. //
  320. // If the site (or its root application) has been deleted, remove it
  321. // unless we are in the iterator in which case it will anyway be
  322. // removed
  323. //
  324. if (ChangeObject.dwMDChangeType == MD_CHANGE_TYPE_DELETE_OBJECT)
  325. {
  326. if (pTempSiteList == NULL)
  327. {
  328. g_pW3Server->RemoveSite(this);
  329. }
  330. return S_OK;
  331. }
  332. //
  333. // Now handle any property changes.
  334. //
  335. BOOL fLoggingHasChanged = FALSE;
  336. BOOL fFiltersHaveChanged = FALSE;
  337. //
  338. // Find out if we would need to handle any logging or filter changes
  339. //
  340. for (DWORD i = 0; i < ChangeObject.dwMDNumDataIDs; i++)
  341. {
  342. DWORD PropertyID = ChangeObject.pdwMDDataIDs[i];
  343. if (((PropertyID >= IIS_MD_LOG_BASE) &&
  344. (PropertyID <= IIS_MD_LOG_LAST)) ||
  345. ((PropertyID >= IIS_MD_LOGCUSTOM_BASE) &&
  346. (PropertyID <= IIS_MD_LOGCUSTOM_LAST)))
  347. {
  348. fLoggingHasChanged = TRUE;
  349. }
  350. else if (PropertyID == MD_FILTER_LOAD_ORDER)
  351. {
  352. fFiltersHaveChanged = TRUE;
  353. }
  354. }
  355. //
  356. // Create a new site
  357. //
  358. W3_SITE *site = new W3_SITE(m_SiteId);
  359. if (site == NULL)
  360. {
  361. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  362. }
  363. //
  364. // Copy over the cache context, and also logging and filter info
  365. // if applicable
  366. //
  367. HRESULT hr;
  368. if (FAILED(hr = site->Initialize(
  369. fLoggingHasChanged ? NULL : m_pLogging,
  370. fFiltersHaveChanged ? NULL : m_pInstanceFilterList)))
  371. {
  372. site->Release();
  373. return hr;
  374. }
  375. //
  376. // Depending on whether we are in the iterator, either replace the
  377. // site in the site list or add it to the temp list which will replace
  378. // the real list later
  379. //
  380. if (pTempSiteList == NULL)
  381. {
  382. g_pW3Server->AddSite(site, true);
  383. }
  384. else
  385. {
  386. pTempSiteList->InsertRecord(site);
  387. }
  388. // Release the extra reference
  389. site->Release();
  390. }
  391. return S_OK;
  392. }
  393. HRESULT
  394. W3_SITE::GetIISCertificateMapping(
  395. IIS_CERTIFICATE_MAPPING ** ppIISCertificateMapping
  396. )
  397. /*++
  398. Routine Description:
  399. Arguments:
  400. ppIISCertificateMapping - returns found iis cert mapping object
  401. m_pIISCertMap is created on demand. It will not be
  402. created when W3_SITE is created, only when first request that requires
  403. certificate mappings
  404. Return Value:
  405. HRESULT
  406. --*/
  407. {
  408. HRESULT hr = E_FAIL;
  409. DBG_ASSERT( ppIISCertificateMapping != NULL );
  410. if ( m_fAlreadyAttemptedToLoadIISCertMap )
  411. {
  412. *ppIISCertificateMapping = m_pIISCertMap;
  413. hr = S_OK;
  414. goto Finished;
  415. }
  416. else
  417. {
  418. IIS_CERTIFICATE_MAPPING * pCertMap = NULL;
  419. //
  420. // This lock only applies when certmapping was not yet read
  421. // Global lock will only apply for reading certmapper for site
  422. // on the very first attempt to fetch file that enables
  423. // IIS certmapping
  424. //
  425. GlobalLockIISCertMap();
  426. //
  427. // try again to prevent loading of mapping multiple times
  428. //
  429. if ( m_fAlreadyAttemptedToLoadIISCertMap )
  430. {
  431. hr = S_OK;
  432. }
  433. else
  434. {
  435. //
  436. // build IIS Certificate mapping structure and
  437. // add update W3_SITE structure
  438. //
  439. if ( m_fUseDSMapper )
  440. {
  441. m_pIISCertMap = NULL;
  442. hr = S_OK;
  443. }
  444. else
  445. {
  446. hr = IIS_CERTIFICATE_MAPPING::GetCertificateMapping( m_SiteId,
  447. &pCertMap );
  448. if ( SUCCEEDED( hr ) )
  449. {
  450. m_pIISCertMap = pCertMap;
  451. }
  452. }
  453. //
  454. // always set m_fAlreadyAttemptedToLoadIISCertMap to TRUE (regardless of error)
  455. // that would prevent reading mappings for each request in the case of failure
  456. // it is valid for m_pIISCertMap to be NULL (regardless of m_fAlreadyAttemptedToLoadIISCertMap)
  457. //
  458. InterlockedExchange( reinterpret_cast<LONG *>(&m_fAlreadyAttemptedToLoadIISCertMap),
  459. TRUE );
  460. }
  461. GlobalUnlockIISCertMap();
  462. if ( FAILED( hr ) )
  463. {
  464. goto Finished;
  465. }
  466. }
  467. *ppIISCertificateMapping = m_pIISCertMap;
  468. hr = S_OK;
  469. Finished:
  470. return hr;
  471. }