MessageLogger.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Diagnostics
  5. {
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.IO;
  9. using System.Runtime;
  10. using System.Runtime.Diagnostics;
  11. using System.Security;
  12. using System.ServiceModel;
  13. using System.ServiceModel.Channels;
  14. using System.ServiceModel.Configuration;
  15. using System.ServiceModel.Diagnostics.Application;
  16. using System.ServiceModel.Dispatcher;
  17. using System.Xml;
  18. [Flags]
  19. internal enum MessageLoggingSource : int
  20. {
  21. None = 0,
  22. TransportReceive = 2,
  23. TransportSend = 4,
  24. Transport = TransportReceive | TransportSend,
  25. ServiceLevelReceiveDatagram = 16,
  26. ServiceLevelSendDatagram = 32,
  27. ServiceLevelReceiveRequest = 64,
  28. ServiceLevelSendRequest = 128,
  29. ServiceLevelReceiveReply = 256,
  30. ServiceLevelSendReply = 512,
  31. ServiceLevelReceive = ServiceLevelReceiveReply | ServiceLevelReceiveRequest | ServiceLevelReceiveDatagram,
  32. ServiceLevelSend = ServiceLevelSendReply | ServiceLevelSendRequest | ServiceLevelSendDatagram,
  33. ServiceLevelService = ServiceLevelSendReply | ServiceLevelReceiveRequest | ServiceLevelReceiveDatagram,
  34. ServiceLevelProxy = ServiceLevelReceiveReply | ServiceLevelSendRequest | ServiceLevelSendDatagram,
  35. ServiceLevel = ServiceLevelReceive | ServiceLevelSend,
  36. Malformed = 1024,
  37. LastChance = 2048,
  38. All = int.MaxValue
  39. }
  40. internal static class MessageLogger
  41. {
  42. const string MessageTraceSourceName = "System.ServiceModel.MessageLogging";
  43. const string DefaultTraceListenerName = "Default";
  44. const int Unlimited = -1;
  45. static MessageLoggingSource sources = default(MessageLoggingSource);
  46. static bool logKnownPii;
  47. static bool logMessageBody = false;
  48. static int maxMessagesToLog;
  49. static int numberOfMessagesToLog;
  50. static int maxMessageSize;
  51. static PiiTraceSource messageTraceSource;
  52. static bool attemptedTraceSourceInitialization = false;
  53. static bool initialized = false;
  54. static bool initializing = false;
  55. static bool inPartialTrust = false;
  56. static object syncObject = new object();
  57. static object filterLock = new object();
  58. static List<XPathMessageFilter> messageFilterTable;
  59. static bool lastWriteSucceeded = true;
  60. static string[][] piiBodyPaths;
  61. static string[][] piiHeadersPaths;
  62. static string[] securityActions;
  63. static int FilterCount
  64. {
  65. get { return MessageLogger.Filters.Count; }
  66. }
  67. static bool FilterMessages
  68. {
  69. get { return MessageLogger.FilterCount > 0 && (MessageLogger.numberOfMessagesToLog > 0 || MessageLogger.numberOfMessagesToLog == MessageLogger.Unlimited); }
  70. }
  71. internal static bool LogKnownPii
  72. {
  73. get
  74. {
  75. Fx.Assert(MessageLogger.initialized, "MessageLogger should be initialized before trying to retrieve LogKnownPii");
  76. return MessageLogger.logKnownPii;
  77. }
  78. set
  79. {
  80. MessageLogger.logKnownPii = value;
  81. }
  82. }
  83. internal static bool LogMalformedMessages
  84. {
  85. get { return (MessageLogger.Sources & MessageLoggingSource.Malformed) != 0; }
  86. set
  87. {
  88. lock (MessageLogger.syncObject)
  89. {
  90. bool shouldProcessAudit = ShouldProcessAudit(MessageLoggingSource.Malformed, value);
  91. if (value)
  92. {
  93. EnsureMessageTraceSource();
  94. if (!MessageLogger.inPartialTrust)
  95. {
  96. MessageLogger.sources |= MessageLoggingSource.Malformed;
  97. }
  98. }
  99. else
  100. {
  101. MessageLogger.sources &= MessageLoggingSource.All & ~MessageLoggingSource.Malformed;
  102. }
  103. if (shouldProcessAudit)
  104. {
  105. ProcessAudit(value);
  106. }
  107. }
  108. }
  109. }
  110. internal static bool LogMessagesAtServiceLevel
  111. {
  112. get { return (MessageLogger.Sources & MessageLoggingSource.ServiceLevel) != 0; }
  113. set
  114. {
  115. lock (MessageLogger.syncObject)
  116. {
  117. bool shouldProcessAudit = ShouldProcessAudit(MessageLoggingSource.ServiceLevel, value);
  118. if (value)
  119. {
  120. EnsureMessageTraceSource();
  121. if (!MessageLogger.inPartialTrust)
  122. {
  123. MessageLogger.sources |= MessageLoggingSource.ServiceLevel;
  124. }
  125. }
  126. else
  127. {
  128. MessageLogger.sources &= MessageLoggingSource.All & ~MessageLoggingSource.ServiceLevel;
  129. }
  130. if (shouldProcessAudit)
  131. {
  132. ProcessAudit(value);
  133. }
  134. }
  135. }
  136. }
  137. internal static bool LogMessagesAtTransportLevel
  138. {
  139. get { return (MessageLogger.Sources & MessageLoggingSource.Transport) != 0; }
  140. set
  141. {
  142. lock (MessageLogger.syncObject)
  143. {
  144. bool shouldProcessAudit = ShouldProcessAudit(MessageLoggingSource.Transport, value);
  145. if (value)
  146. {
  147. EnsureMessageTraceSource();
  148. if (!MessageLogger.inPartialTrust)
  149. {
  150. MessageLogger.sources |= MessageLoggingSource.Transport;
  151. }
  152. }
  153. else
  154. {
  155. MessageLogger.sources &= MessageLoggingSource.All & ~MessageLoggingSource.Transport;
  156. }
  157. if (shouldProcessAudit)
  158. {
  159. ProcessAudit(value);
  160. }
  161. }
  162. }
  163. }
  164. internal static bool LogMessageBody
  165. {
  166. get
  167. {
  168. Fx.Assert(MessageLogger.initialized, "");
  169. return logMessageBody;
  170. }
  171. set { logMessageBody = value; }
  172. }
  173. internal static bool LoggingEnabled
  174. {
  175. get { return MessageLogger.Sources != default(MessageLoggingSource); }
  176. }
  177. internal static int MaxMessageSize
  178. {
  179. get
  180. {
  181. Fx.Assert(MessageLogger.initialized, "");
  182. return maxMessageSize;
  183. }
  184. set { maxMessageSize = value; }
  185. }
  186. internal static int MaxNumberOfMessagesToLog
  187. {
  188. get
  189. {
  190. Fx.Assert(MessageLogger.initialized, "");
  191. return maxMessagesToLog;
  192. }
  193. set
  194. {
  195. //resetting the max resets the actual counter
  196. lock (MessageLogger.syncObject)
  197. {
  198. maxMessagesToLog = value;
  199. MessageLogger.numberOfMessagesToLog = maxMessagesToLog;
  200. }
  201. }
  202. }
  203. static List<XPathMessageFilter> Filters
  204. {
  205. get
  206. {
  207. if (MessageLogger.messageFilterTable == null)
  208. {
  209. lock (MessageLogger.filterLock)
  210. {
  211. if (MessageLogger.messageFilterTable == null)
  212. {
  213. List<XPathMessageFilter> temp = new List<XPathMessageFilter>();
  214. MessageLogger.messageFilterTable = temp;
  215. }
  216. }
  217. }
  218. return MessageLogger.messageFilterTable;
  219. }
  220. }
  221. static MessageLoggingSource Sources
  222. {
  223. get
  224. {
  225. if (!MessageLogger.initialized)
  226. {
  227. MessageLogger.EnsureInitialized();
  228. }
  229. return MessageLogger.sources;
  230. }
  231. }
  232. static bool AddFilter(XPathMessageFilter filter)
  233. {
  234. if (filter == null)
  235. {
  236. filter = new XPathMessageFilter(""); //if there is an empty add filter tag, add a match-all filter
  237. }
  238. MessageLogger.Filters.Add(filter);
  239. return true;
  240. }
  241. internal static bool ShouldLogMalformed
  242. {
  243. get { return ShouldLogMessages(MessageLoggingSource.Malformed); }
  244. }
  245. static bool ShouldLogMessages(MessageLoggingSource source)
  246. {
  247. return (source & MessageLogger.Sources) != 0 &&
  248. ((MessageLogger.MessageTraceSource != null) ||
  249. ((source & MessageLoggingSource.Malformed) != 0 && TD.MessageLogWarningIsEnabled()) ||
  250. TD.MessageLogInfoIsEnabled());
  251. }
  252. internal static void LogMessage(MessageLoggingSource source, string data)
  253. {
  254. try
  255. {
  256. if (ShouldLogMessages(MessageLoggingSource.Malformed))
  257. {
  258. LogInternal(source, data);
  259. }
  260. }
  261. #pragma warning suppress 56500 // covered by FxCOP
  262. catch (Exception e)
  263. {
  264. if (Fx.IsFatal(e)) throw;
  265. FailedToLogMessage(e);
  266. }
  267. }
  268. internal static void LogMessage(Stream stream, MessageLoggingSource source)
  269. {
  270. try
  271. {
  272. ThrowIfNotMalformed(source);
  273. if (ShouldLogMessages(source))
  274. {
  275. LogInternal(new MessageLogTraceRecord(stream, source));
  276. }
  277. }
  278. #pragma warning suppress 56500 // covered by FxCOP
  279. catch (Exception e)
  280. {
  281. if (Fx.IsFatal(e)) throw;
  282. FailedToLogMessage(e);
  283. }
  284. }
  285. internal static void LogMessage(ArraySegment<byte> buffer, MessageLoggingSource source)
  286. {
  287. try
  288. {
  289. ThrowIfNotMalformed(source);
  290. if (ShouldLogMessages(source))
  291. {
  292. LogInternal(new MessageLogTraceRecord(buffer, source));
  293. }
  294. }
  295. #pragma warning suppress 56500 // covered by FxCOP
  296. catch (Exception e)
  297. {
  298. if (Fx.IsFatal(e)) throw;
  299. FailedToLogMessage(e);
  300. }
  301. }
  302. internal static void LogMessage(ref Message message, XmlReader reader, MessageLoggingSource source)
  303. {
  304. Fx.Assert(null != message, "");
  305. try
  306. {
  307. if (ShouldLogMessages(source))
  308. {
  309. LogMessageImpl(ref message, reader, source);
  310. }
  311. }
  312. #pragma warning suppress 56500 // covered by FxCOP
  313. catch (Exception e)
  314. {
  315. if (Fx.IsFatal(e)) throw;
  316. FailedToLogMessage(e);
  317. }
  318. }
  319. internal static void LogMessage(ref Message message, MessageLoggingSource source)
  320. {
  321. LogMessage(ref message, null, source);
  322. }
  323. static void LogMessageImpl(ref Message message, XmlReader reader, MessageLoggingSource source)
  324. {
  325. ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? TraceUtility.ExtractActivity(message) : null;
  326. using (ServiceModelActivity.BoundOperation(activity))
  327. {
  328. if (ShouldLogMessages(source) && (MessageLogger.numberOfMessagesToLog > 0 || MessageLogger.numberOfMessagesToLog == MessageLogger.Unlimited))
  329. {
  330. bool lastChance = (source & MessageLoggingSource.LastChance) != 0 || (source & MessageLoggingSource.TransportSend) != 0;
  331. source &= ~MessageLoggingSource.LastChance;
  332. // MessageLogger doesn't log AddressingVersion.None in the encoder since we want to make sure we log
  333. // as much of the message as possible. So let the Transport log later.
  334. if ((lastChance || message is NullMessage || message.Version.Addressing != AddressingVersion.None)
  335. && MatchFilters(message, source))
  336. {
  337. if (MessageLogger.numberOfMessagesToLog == MessageLogger.Unlimited || MessageLogger.numberOfMessagesToLog > 0)
  338. {
  339. MessageLogTraceRecord record = new MessageLogTraceRecord(ref message, reader, source, MessageLogger.LogMessageBody);
  340. LogInternal(record);
  341. }
  342. }
  343. }
  344. }
  345. }
  346. static bool HasSecurityAction(Message message)
  347. {
  348. Fx.Assert(null != message, "");
  349. string action = message.Headers.Action;
  350. bool result = false;
  351. if (String.IsNullOrEmpty(action))
  352. {
  353. result = true;
  354. }
  355. else
  356. {
  357. foreach (string securityAction in MessageLogger.SecurityActions)
  358. {
  359. if (0 == String.CompareOrdinal(action, securityAction))
  360. {
  361. result = true;
  362. break;
  363. }
  364. }
  365. }
  366. return result;
  367. }
  368. static void LogInternal(MessageLogTraceRecord record)
  369. {
  370. Fx.Assert(null != record, "record cannot be null");
  371. PlainXmlWriter xmlWriter = new PlainXmlWriter(MessageLogger.MaxMessageSize);
  372. try
  373. {
  374. record.WriteTo(xmlWriter);
  375. xmlWriter.Close();
  376. TraceXPathNavigator navigator = xmlWriter.Navigator;
  377. if ((MessageLogger.messageTraceSource != null &&
  378. !MessageLogger.messageTraceSource.ShouldLogPii) ||
  379. !MessageLogger.LogKnownPii)
  380. {
  381. navigator.RemovePii(MessageLogger.PiiHeadersPaths);
  382. if (MessageLogger.LogMessageBody && null != record.Message)
  383. {
  384. if (HasSecurityAction(record.Message))
  385. {
  386. navigator.RemovePii(MessageLogger.PiiBodyPaths);
  387. }
  388. }
  389. }
  390. LogInternal(record.MessageLoggingSource, navigator);
  391. }
  392. catch (PlainXmlWriter.MaxSizeExceededException)
  393. {
  394. if (DiagnosticUtility.ShouldTraceWarning)
  395. {
  396. TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.MessageNotLoggedQuotaExceeded,
  397. SR.GetString(SR.TraceCodeMessageNotLoggedQuotaExceeded), record.Message);
  398. }
  399. }
  400. }
  401. static void IncrementLoggedMessagesCount(object data)
  402. {
  403. if (MessageLogger.numberOfMessagesToLog > 0)
  404. {
  405. lock (MessageLogger.syncObject)
  406. {
  407. if (MessageLogger.numberOfMessagesToLog > 0)
  408. {
  409. MessageLogger.numberOfMessagesToLog--;
  410. if (0 == MessageLogger.numberOfMessagesToLog)
  411. {
  412. if (DiagnosticUtility.ShouldTraceInformation)
  413. {
  414. TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.MessageCountLimitExceeded,
  415. SR.GetString(SR.TraceCodeMessageCountLimitExceeded), data);
  416. }
  417. }
  418. }
  419. }
  420. }
  421. lock (MessageLogger.syncObject)
  422. {
  423. if (!MessageLogger.lastWriteSucceeded)
  424. {
  425. MessageLogger.lastWriteSucceeded = true;
  426. }
  427. }
  428. }
  429. static void FailedToLogMessage(Exception e)
  430. {
  431. //If something goes wrong, we do not want to fail the app, just log one event log entry per block of failures
  432. bool shouldLogError = false;
  433. lock (MessageLogger.syncObject)
  434. {
  435. if (MessageLogger.lastWriteSucceeded)
  436. {
  437. MessageLogger.lastWriteSucceeded = false;
  438. shouldLogError = true;
  439. }
  440. }
  441. if (shouldLogError)
  442. {
  443. DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error,
  444. (ushort)System.Runtime.Diagnostics.EventLogCategory.MessageLogging,
  445. (uint)System.Runtime.Diagnostics.EventLogEventId.FailedToLogMessage,
  446. e.ToString());
  447. }
  448. }
  449. static void LogInternal(MessageLoggingSource source, object data)
  450. {
  451. if ((source & MessageLoggingSource.Malformed) != 0)
  452. {
  453. if (!TD.MessageLogWarning(data.ToString()))
  454. {
  455. if (TD.MessageLogEventSizeExceededIsEnabled())
  456. {
  457. TD.MessageLogEventSizeExceeded();
  458. }
  459. }
  460. }
  461. else
  462. {
  463. if (!TD.MessageLogInfo(data.ToString()))
  464. {
  465. if (TD.MessageLogEventSizeExceededIsEnabled())
  466. {
  467. TD.MessageLogEventSizeExceeded();
  468. }
  469. }
  470. }
  471. if (MessageLogger.MessageTraceSource != null)
  472. {
  473. MessageLogger.MessageTraceSource.TraceData(TraceEventType.Information, 0, data);
  474. }
  475. IncrementLoggedMessagesCount(data);
  476. }
  477. static bool MatchFilters(Message message, MessageLoggingSource source)
  478. {
  479. bool result = true;
  480. if (MessageLogger.FilterMessages && (source & MessageLoggingSource.Malformed) == 0)
  481. {
  482. result = false;
  483. List<XPathMessageFilter> filtersToRemove = new List<XPathMessageFilter>();
  484. lock (MessageLogger.syncObject)
  485. {
  486. foreach (XPathMessageFilter filter in MessageLogger.Filters)
  487. {
  488. try
  489. {
  490. if (filter.Match(message))
  491. {
  492. result = true;
  493. break;
  494. }
  495. }
  496. catch (FilterInvalidBodyAccessException)
  497. {
  498. filtersToRemove.Add(filter);
  499. }
  500. catch (MessageFilterException e)
  501. {
  502. if (DiagnosticUtility.ShouldTraceInformation)
  503. {
  504. TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.FilterNotMatchedNodeQuotaExceeded,
  505. SR.GetString(SR.TraceCodeFilterNotMatchedNodeQuotaExceeded), e, message);
  506. }
  507. }
  508. }
  509. foreach (XPathMessageFilter filter in filtersToRemove)
  510. {
  511. MessageLogger.Filters.Remove(filter);
  512. PlainXmlWriter writer = new PlainXmlWriter();
  513. filter.WriteXPathTo(writer, null, ConfigurationStrings.Filter, null, true);
  514. DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error,
  515. (ushort)System.Runtime.Diagnostics.EventLogCategory.MessageLogging,
  516. (uint)System.Runtime.Diagnostics.EventLogEventId.RemovedBadFilter,
  517. writer.Navigator.ToString());
  518. }
  519. if (MessageLogger.FilterCount == 0)
  520. {
  521. result = true;
  522. }
  523. }
  524. }
  525. return result;
  526. }
  527. static void ReadFiltersFromConfig(DiagnosticSection section)
  528. {
  529. for (int i = 0; i < section.MessageLogging.Filters.Count; i++)
  530. {
  531. XPathMessageFilterElement xfe = section.MessageLogging.Filters[i];
  532. AddFilter(xfe.Filter);
  533. }
  534. }
  535. internal static TraceSource MessageTraceSource
  536. {
  537. get
  538. {
  539. return MessageLogger.messageTraceSource;
  540. }
  541. }
  542. internal static void EnsureInitialized()
  543. {
  544. lock (MessageLogger.syncObject)
  545. {
  546. if (!MessageLogger.initialized && !MessageLogger.initializing)
  547. {
  548. try
  549. {
  550. Initialize();
  551. }
  552. #pragma warning suppress 56500 // covered by FxCOP
  553. catch (SecurityException securityException)
  554. {
  555. // message logging is not support in PT, write the trace
  556. MessageLogger.inPartialTrust = true;
  557. if (DiagnosticUtility.ShouldTraceWarning)
  558. {
  559. TraceUtility.TraceEvent(TraceEventType.Warning,
  560. TraceCode.TraceHandledException,
  561. SR.GetString(SR.PartialTrustMessageLoggingNotEnabled),
  562. null,
  563. securityException);
  564. }
  565. // also write to event log
  566. LogNonFatalInitializationException(
  567. new SecurityException(
  568. SR.GetString(SR.PartialTrustMessageLoggingNotEnabled),
  569. securityException));
  570. }
  571. MessageLogger.initialized = true;
  572. }
  573. }
  574. }
  575. static void EnsureMessageTraceSource()
  576. {
  577. if (!MessageLogger.initialized)
  578. {
  579. MessageLogger.EnsureInitialized();
  580. }
  581. if (null == MessageLogger.MessageTraceSource && !MessageLogger.attemptedTraceSourceInitialization)
  582. {
  583. InitializeMessageTraceSource();
  584. }
  585. }
  586. static string[][] PiiBodyPaths
  587. {
  588. get
  589. {
  590. if (piiBodyPaths == null)
  591. piiBodyPaths = new string[][] {
  592. new string[] { MessageLogTraceRecord.MessageLogTraceRecordElementName, "Envelope", "Body", "RequestSecurityToken" },
  593. new string[] { MessageLogTraceRecord.MessageLogTraceRecordElementName, "Envelope", "Body", "RequestSecurityTokenResponse" },
  594. new string[] { MessageLogTraceRecord.MessageLogTraceRecordElementName, "Envelope", "Body", "RequestSecurityTokenResponseCollection" }
  595. };
  596. return piiBodyPaths;
  597. }
  598. }
  599. static string[][] PiiHeadersPaths
  600. {
  601. get
  602. {
  603. if (piiHeadersPaths == null)
  604. piiHeadersPaths = new string[][] {
  605. new string[] { MessageLogTraceRecord.MessageLogTraceRecordElementName, "Envelope", "Header", "Security" },
  606. new string[] { MessageLogTraceRecord.MessageLogTraceRecordElementName, "Envelope", "Header", "IssuedTokens" }
  607. };
  608. return piiHeadersPaths;
  609. }
  610. }
  611. static string[] SecurityActions
  612. {
  613. get
  614. {
  615. if (securityActions == null)
  616. securityActions = new string[] {
  617. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue",
  618. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue",
  619. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Renew",
  620. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Renew",
  621. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Cancel",
  622. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Cancel",
  623. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Validate",
  624. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Validate",
  625. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT",
  626. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT",
  627. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Amend",
  628. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT/Amend",
  629. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Renew",
  630. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT/Renew",
  631. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Cancel",
  632. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT/Cancel",
  633. "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/KET",
  634. "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/KET",
  635. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/SCT",
  636. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/SCT",
  637. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/SCT-Amend",
  638. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/SCT-Amend",
  639. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/Issue",
  640. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/Issue",
  641. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/Renew",
  642. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/Renew",
  643. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/Validate",
  644. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/Validate",
  645. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/KET",
  646. "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/KET"
  647. };
  648. return securityActions;
  649. }
  650. }
  651. [Fx.Tag.SecurityNote(Critical = "Calls SecurityCritical method UnsafeGetSection which elevates in order to load config.",
  652. Safe = "Does not leak any config objects.")]
  653. [SecuritySafeCritical]
  654. static void Initialize()
  655. {
  656. MessageLogger.initializing = true;
  657. DiagnosticSection section = DiagnosticSection.UnsafeGetSection();
  658. if (section != null)
  659. {
  660. MessageLogger.LogKnownPii = section.MessageLogging.LogKnownPii && MachineSettingsSection.EnableLoggingKnownPii;
  661. MessageLogger.LogMalformedMessages = section.MessageLogging.LogMalformedMessages;
  662. MessageLogger.LogMessageBody = section.MessageLogging.LogEntireMessage;
  663. MessageLogger.LogMessagesAtServiceLevel = section.MessageLogging.LogMessagesAtServiceLevel;
  664. MessageLogger.LogMessagesAtTransportLevel = section.MessageLogging.LogMessagesAtTransportLevel;
  665. MessageLogger.MaxNumberOfMessagesToLog = section.MessageLogging.MaxMessagesToLog;
  666. MessageLogger.MaxMessageSize = section.MessageLogging.MaxSizeOfMessageToLog;
  667. ReadFiltersFromConfig(section);
  668. }
  669. }
  670. static void InitializeMessageTraceSource()
  671. {
  672. try
  673. {
  674. MessageLogger.attemptedTraceSourceInitialization = true;
  675. PiiTraceSource tempSource = new PiiTraceSource(MessageLogger.MessageTraceSourceName, DiagnosticUtility.EventSourceName);
  676. tempSource.Switch.Level = SourceLevels.Information;
  677. tempSource.Listeners.Remove(MessageLogger.DefaultTraceListenerName);
  678. if (tempSource.Listeners.Count > 0)
  679. {
  680. AppDomain.CurrentDomain.DomainUnload += new EventHandler(ExitOrUnloadEventHandler);
  681. AppDomain.CurrentDomain.ProcessExit += new EventHandler(ExitOrUnloadEventHandler);
  682. AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ExitOrUnloadEventHandler);
  683. }
  684. else
  685. {
  686. tempSource = null;
  687. }
  688. MessageLogger.messageTraceSource = tempSource;
  689. }
  690. catch (System.Configuration.ConfigurationErrorsException)
  691. {
  692. throw;
  693. }
  694. #pragma warning suppress 56500 // covered by FxCOP
  695. catch (SecurityException securityException)
  696. {
  697. // message logging is not support in PT, write the trace
  698. MessageLogger.inPartialTrust = true;
  699. if (DiagnosticUtility.ShouldTraceWarning)
  700. {
  701. TraceUtility.TraceEvent(TraceEventType.Warning,
  702. TraceCode.TraceHandledException,
  703. SR.GetString(SR.PartialTrustMessageLoggingNotEnabled),
  704. null,
  705. securityException);
  706. }
  707. // also write to event log
  708. LogNonFatalInitializationException(
  709. new SecurityException(
  710. SR.GetString(SR.PartialTrustMessageLoggingNotEnabled),
  711. securityException));
  712. }
  713. catch (Exception e)
  714. {
  715. MessageLogger.messageTraceSource = null;
  716. if (Fx.IsFatal(e)) throw;
  717. LogNonFatalInitializationException(e);
  718. }
  719. }
  720. [Fx.Tag.SecurityNote(Critical = "Calls into an unsafe method to log event.",
  721. Safe = "Event identities cannot be spoofed as they are constants determined inside the method.")]
  722. [SecuritySafeCritical]
  723. static void LogNonFatalInitializationException(Exception e)
  724. {
  725. DiagnosticUtility.UnsafeEventLog.UnsafeLogEvent(TraceEventType.Critical,
  726. (ushort)System.Runtime.Diagnostics.EventLogCategory.MessageLogging,
  727. (uint)System.Runtime.Diagnostics.EventLogEventId.FailedToCreateMessageLoggingTraceSource,
  728. true,
  729. e.ToString());
  730. }
  731. static void ExitOrUnloadEventHandler(object sender, EventArgs e)
  732. {
  733. lock (MessageLogger.syncObject)
  734. {
  735. if (null != MessageLogger.MessageTraceSource)
  736. {
  737. //Flush is called automatically on close by StreamWriter
  738. MessageLogger.MessageTraceSource.Close();
  739. MessageLogger.messageTraceSource = null;
  740. }
  741. }
  742. }
  743. static void ThrowIfNotMalformed(MessageLoggingSource source)
  744. {
  745. if ((source & MessageLoggingSource.Malformed) == 0)
  746. {
  747. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.OnlyMalformedMessagesAreSupported), "source"));
  748. }
  749. }
  750. static void ProcessAudit(bool turningOn)
  751. {
  752. if (turningOn)
  753. {
  754. if (null != MessageLogger.messageTraceSource)
  755. {
  756. DiagnosticUtility.EventLog.LogEvent(TraceEventType.Information,
  757. (ushort)System.Runtime.Diagnostics.EventLogCategory.MessageLogging,
  758. (uint)System.Runtime.Diagnostics.EventLogEventId.MessageLoggingOn);
  759. }
  760. }
  761. else
  762. {
  763. DiagnosticUtility.EventLog.LogEvent(TraceEventType.Information,
  764. (ushort)System.Runtime.Diagnostics.EventLogCategory.MessageLogging,
  765. (uint)System.Runtime.Diagnostics.EventLogEventId.MessageLoggingOff);
  766. }
  767. }
  768. static bool ShouldProcessAudit(MessageLoggingSource source, bool turningOn)
  769. {
  770. bool result = false;
  771. if (turningOn)
  772. {
  773. result = MessageLogger.sources == MessageLoggingSource.None;
  774. }
  775. else
  776. {
  777. result = MessageLogger.sources == source;
  778. }
  779. return result;
  780. }
  781. }
  782. }