ContextMessageHeader.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Net.Security;
  9. using System.Runtime;
  10. using System.ServiceModel;
  11. using System.ServiceModel.Security;
  12. using System.Xml;
  13. class ContextMessageHeader : MessageHeader
  14. {
  15. public const string ContextHeaderName = "Context";
  16. public const string ContextHeaderNamespace = "http://schemas.microsoft.com/ws/2006/05/context";
  17. public const string ContextPropertyElement = "Property";
  18. public const string ContextPropertyNameAttribute = "name";
  19. static ChannelProtectionRequirements encryptAndSignChannelProtectionRequirements;
  20. static ChannelProtectionRequirements signChannelProtectionRequirements;
  21. IDictionary<string, string> context;
  22. public ContextMessageHeader(IDictionary<string, string> context)
  23. : base()
  24. {
  25. if (context == null)
  26. {
  27. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
  28. }
  29. this.context = context;
  30. }
  31. public override string Name
  32. {
  33. get { return ContextHeaderName; }
  34. }
  35. public override string Namespace
  36. {
  37. get { return ContextHeaderNamespace; }
  38. }
  39. public static ContextMessageProperty GetContextFromHeaderIfExists(Message message)
  40. {
  41. if (message == null)
  42. {
  43. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  44. }
  45. int i = message.Headers.FindHeader(ContextHeaderName, ContextHeaderNamespace);
  46. if (i >= 0)
  47. {
  48. MessageHeaders headers = message.Headers;
  49. ContextMessageProperty context = ParseContextHeader(headers.GetReaderAtHeader(i));
  50. headers.AddUnderstood(i);
  51. return context;
  52. }
  53. else
  54. {
  55. return null;
  56. }
  57. }
  58. internal static ChannelProtectionRequirements GetChannelProtectionRequirements(ProtectionLevel protectionLevel)
  59. {
  60. ChannelProtectionRequirements result;
  61. if (protectionLevel == ProtectionLevel.EncryptAndSign)
  62. {
  63. if (encryptAndSignChannelProtectionRequirements == null)
  64. {
  65. MessagePartSpecification header = new MessagePartSpecification();
  66. header.HeaderTypes.Add(new XmlQualifiedName(ContextHeaderName, ContextHeaderNamespace));
  67. ChannelProtectionRequirements requirements = new ChannelProtectionRequirements();
  68. requirements.IncomingSignatureParts.AddParts(header);
  69. requirements.IncomingEncryptionParts.AddParts(header);
  70. requirements.OutgoingSignatureParts.AddParts(header);
  71. requirements.OutgoingEncryptionParts.AddParts(header);
  72. requirements.MakeReadOnly();
  73. encryptAndSignChannelProtectionRequirements = requirements;
  74. }
  75. result = encryptAndSignChannelProtectionRequirements;
  76. }
  77. else if (protectionLevel == ProtectionLevel.Sign)
  78. {
  79. if (signChannelProtectionRequirements == null)
  80. {
  81. MessagePartSpecification header = new MessagePartSpecification();
  82. header.HeaderTypes.Add(new XmlQualifiedName(ContextHeaderName, ContextHeaderNamespace));
  83. ChannelProtectionRequirements requirements = new ChannelProtectionRequirements();
  84. requirements.IncomingSignatureParts.AddParts(header);
  85. requirements.OutgoingSignatureParts.AddParts(header);
  86. requirements.MakeReadOnly();
  87. signChannelProtectionRequirements = requirements;
  88. }
  89. result = signChannelProtectionRequirements;
  90. }
  91. else
  92. {
  93. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("protectionLevel"));
  94. }
  95. return result;
  96. }
  97. internal static ContextMessageProperty ParseContextHeader(XmlReader reader)
  98. {
  99. if (reader == null)
  100. {
  101. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
  102. }
  103. ContextMessageProperty result = new ContextMessageProperty();
  104. try
  105. {
  106. if (!reader.IsEmptyElement)
  107. {
  108. reader.ReadStartElement(ContextHeaderName, ContextHeaderNamespace);
  109. while (reader.MoveToContent() == XmlNodeType.Element)
  110. {
  111. if (reader.LocalName != ContextPropertyElement || reader.NamespaceURI != ContextHeaderNamespace)
  112. {
  113. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  114. new ProtocolException(SR.GetString(SR.SchemaViolationInsideContextHeader)));
  115. }
  116. string propertyName = reader.GetAttribute(ContextPropertyNameAttribute);
  117. if (string.IsNullOrEmpty(propertyName) || !ContextDictionary.TryValidateKeyValueSpace(propertyName))
  118. {
  119. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  120. new ProtocolException(SR.GetString(SR.InvalidCookieContent, propertyName)));
  121. }
  122. result.Context[propertyName] = reader.ReadElementString();
  123. }
  124. if (reader.NodeType != XmlNodeType.EndElement)
  125. {
  126. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  127. new ProtocolException(SR.GetString(SR.SchemaViolationInsideContextHeader)));
  128. }
  129. }
  130. }
  131. catch (XmlException e)
  132. {
  133. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  134. new ProtocolException(SR.GetString(SR.XmlFormatViolationInContextHeader), e));
  135. }
  136. return result;
  137. }
  138. internal static void WriteHeaderContents(XmlDictionaryWriter writer, IDictionary<string, string> context)
  139. {
  140. foreach (KeyValuePair<string, string> pair in context)
  141. {
  142. Fx.Assert(!string.IsNullOrEmpty(pair.Key), "ContextProperty name is null");
  143. writer.WriteStartElement(ContextPropertyElement, ContextHeaderNamespace);
  144. writer.WriteAttributeString(ContextPropertyNameAttribute, null, pair.Key);
  145. writer.WriteValue(pair.Value);
  146. writer.WriteEndElement();
  147. }
  148. }
  149. protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
  150. {
  151. if (writer == null)
  152. {
  153. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
  154. }
  155. WriteHeaderContents(writer, this.context);
  156. }
  157. }
  158. }