ChannelProtectionRequirements.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Net.Security;
  7. using System.Runtime;
  8. using System.ServiceModel;
  9. using System.ServiceModel.Channels;
  10. using System.ServiceModel.Description;
  11. using System.Xml;
  12. public class ChannelProtectionRequirements
  13. {
  14. ScopedMessagePartSpecification incomingSignatureParts;
  15. ScopedMessagePartSpecification incomingEncryptionParts;
  16. ScopedMessagePartSpecification outgoingSignatureParts;
  17. ScopedMessagePartSpecification outgoingEncryptionParts;
  18. bool isReadOnly;
  19. public ChannelProtectionRequirements()
  20. {
  21. this.incomingSignatureParts = new ScopedMessagePartSpecification();
  22. this.incomingEncryptionParts = new ScopedMessagePartSpecification();
  23. this.outgoingSignatureParts = new ScopedMessagePartSpecification();
  24. this.outgoingEncryptionParts = new ScopedMessagePartSpecification();
  25. }
  26. public bool IsReadOnly
  27. {
  28. get
  29. {
  30. return this.isReadOnly;
  31. }
  32. }
  33. public ChannelProtectionRequirements(ChannelProtectionRequirements other)
  34. {
  35. if (other == null)
  36. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("other"));
  37. this.incomingSignatureParts = new ScopedMessagePartSpecification(other.incomingSignatureParts);
  38. this.incomingEncryptionParts = new ScopedMessagePartSpecification(other.incomingEncryptionParts);
  39. this.outgoingSignatureParts = new ScopedMessagePartSpecification(other.outgoingSignatureParts);
  40. this.outgoingEncryptionParts = new ScopedMessagePartSpecification(other.outgoingEncryptionParts);
  41. }
  42. internal ChannelProtectionRequirements(ChannelProtectionRequirements other, ProtectionLevel newBodyProtectionLevel)
  43. {
  44. if (other == null)
  45. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("other"));
  46. this.incomingSignatureParts = new ScopedMessagePartSpecification(other.incomingSignatureParts, newBodyProtectionLevel != ProtectionLevel.None);
  47. this.incomingEncryptionParts = new ScopedMessagePartSpecification(other.incomingEncryptionParts, newBodyProtectionLevel == ProtectionLevel.EncryptAndSign);
  48. this.outgoingSignatureParts = new ScopedMessagePartSpecification(other.outgoingSignatureParts, newBodyProtectionLevel != ProtectionLevel.None);
  49. this.outgoingEncryptionParts = new ScopedMessagePartSpecification(other.outgoingEncryptionParts, newBodyProtectionLevel == ProtectionLevel.EncryptAndSign);
  50. }
  51. public ScopedMessagePartSpecification IncomingSignatureParts
  52. {
  53. get
  54. {
  55. return this.incomingSignatureParts;
  56. }
  57. }
  58. public ScopedMessagePartSpecification IncomingEncryptionParts
  59. {
  60. get
  61. {
  62. return this.incomingEncryptionParts;
  63. }
  64. }
  65. public ScopedMessagePartSpecification OutgoingSignatureParts
  66. {
  67. get
  68. {
  69. return this.outgoingSignatureParts;
  70. }
  71. }
  72. public ScopedMessagePartSpecification OutgoingEncryptionParts
  73. {
  74. get
  75. {
  76. return this.outgoingEncryptionParts;
  77. }
  78. }
  79. public void Add(ChannelProtectionRequirements protectionRequirements)
  80. {
  81. this.Add(protectionRequirements, false);
  82. }
  83. public void Add(ChannelProtectionRequirements protectionRequirements, bool channelScopeOnly)
  84. {
  85. if (protectionRequirements == null)
  86. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("protectionRequirements"));
  87. if (protectionRequirements.incomingSignatureParts != null)
  88. this.incomingSignatureParts.AddParts(protectionRequirements.incomingSignatureParts.ChannelParts);
  89. if (protectionRequirements.incomingEncryptionParts != null)
  90. this.incomingEncryptionParts.AddParts(protectionRequirements.incomingEncryptionParts.ChannelParts);
  91. if (protectionRequirements.outgoingSignatureParts != null)
  92. this.outgoingSignatureParts.AddParts(protectionRequirements.outgoingSignatureParts.ChannelParts);
  93. if (protectionRequirements.outgoingEncryptionParts != null)
  94. this.outgoingEncryptionParts.AddParts(protectionRequirements.outgoingEncryptionParts.ChannelParts);
  95. if (!channelScopeOnly)
  96. {
  97. AddActionParts(this.incomingSignatureParts, protectionRequirements.incomingSignatureParts);
  98. AddActionParts(this.incomingEncryptionParts, protectionRequirements.incomingEncryptionParts);
  99. AddActionParts(this.outgoingSignatureParts, protectionRequirements.outgoingSignatureParts);
  100. AddActionParts(this.outgoingEncryptionParts, protectionRequirements.outgoingEncryptionParts);
  101. }
  102. }
  103. static void AddActionParts(ScopedMessagePartSpecification to, ScopedMessagePartSpecification from)
  104. {
  105. foreach (string action in from.Actions)
  106. {
  107. MessagePartSpecification p;
  108. if (from.TryGetParts(action, true, out p))
  109. to.AddParts(p, action);
  110. }
  111. }
  112. public void MakeReadOnly()
  113. {
  114. if (!this.isReadOnly)
  115. {
  116. this.incomingSignatureParts.MakeReadOnly();
  117. this.incomingEncryptionParts.MakeReadOnly();
  118. this.outgoingSignatureParts.MakeReadOnly();
  119. this.outgoingEncryptionParts.MakeReadOnly();
  120. this.isReadOnly = true;
  121. }
  122. }
  123. public ChannelProtectionRequirements CreateInverse()
  124. {
  125. ChannelProtectionRequirements result = new ChannelProtectionRequirements();
  126. result.Add(this, true);
  127. result.incomingSignatureParts = new ScopedMessagePartSpecification(this.OutgoingSignatureParts);
  128. result.outgoingSignatureParts = new ScopedMessagePartSpecification(this.IncomingSignatureParts);
  129. result.incomingEncryptionParts = new ScopedMessagePartSpecification(this.OutgoingEncryptionParts);
  130. result.outgoingEncryptionParts = new ScopedMessagePartSpecification(this.IncomingEncryptionParts);
  131. return result;
  132. }
  133. internal static ChannelProtectionRequirements CreateFromContract(ContractDescription contract, ISecurityCapabilities bindingElement, bool isForClient)
  134. {
  135. return CreateFromContract(contract, bindingElement.SupportedRequestProtectionLevel, bindingElement.SupportedResponseProtectionLevel, isForClient);
  136. }
  137. static MessagePartSpecification UnionMessagePartSpecifications(ScopedMessagePartSpecification actionParts)
  138. {
  139. MessagePartSpecification result = new MessagePartSpecification(false);
  140. foreach (string action in actionParts.Actions)
  141. {
  142. MessagePartSpecification parts;
  143. if (actionParts.TryGetParts(action, out parts))
  144. {
  145. if (parts.IsBodyIncluded)
  146. {
  147. result.IsBodyIncluded = true;
  148. }
  149. foreach (XmlQualifiedName headerType in parts.HeaderTypes)
  150. {
  151. if (!result.IsHeaderIncluded(headerType.Name, headerType.Namespace))
  152. {
  153. result.HeaderTypes.Add(headerType);
  154. }
  155. }
  156. }
  157. }
  158. return result;
  159. }
  160. internal static ChannelProtectionRequirements CreateFromContractAndUnionResponseProtectionRequirements(ContractDescription contract, ISecurityCapabilities bindingElement, bool isForClient)
  161. {
  162. ChannelProtectionRequirements contractRequirements = CreateFromContract(contract, bindingElement.SupportedRequestProtectionLevel, bindingElement.SupportedResponseProtectionLevel, isForClient);
  163. // union all the protection requirements for the response actions
  164. ChannelProtectionRequirements result = new ChannelProtectionRequirements();
  165. //if (isForClient)
  166. //{
  167. // result.IncomingEncryptionParts.AddParts(UnionMessagePartSpecifications(contractRequirements.IncomingEncryptionParts), MessageHeaders.WildcardAction);
  168. // result.IncomingSignatureParts.AddParts(UnionMessagePartSpecifications(contractRequirements.IncomingSignatureParts), MessageHeaders.WildcardAction);
  169. // contractRequirements.OutgoingEncryptionParts.CopyTo(result.OutgoingEncryptionParts);
  170. // contractRequirements.OutgoingSignatureParts.CopyTo(result.OutgoingSignatureParts);
  171. //}
  172. //else
  173. //{
  174. result.OutgoingEncryptionParts.AddParts(UnionMessagePartSpecifications(contractRequirements.OutgoingEncryptionParts), MessageHeaders.WildcardAction);
  175. result.OutgoingSignatureParts.AddParts(UnionMessagePartSpecifications(contractRequirements.OutgoingSignatureParts), MessageHeaders.WildcardAction);
  176. contractRequirements.IncomingEncryptionParts.CopyTo(result.IncomingEncryptionParts);
  177. contractRequirements.IncomingSignatureParts.CopyTo(result.IncomingSignatureParts);
  178. //}
  179. return result;
  180. }
  181. internal static ChannelProtectionRequirements CreateFromContract(ContractDescription contract, ProtectionLevel defaultRequestProtectionLevel, ProtectionLevel defaultResponseProtectionLevel, bool isForClient)
  182. {
  183. if (contract == null)
  184. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("contract"));
  185. ChannelProtectionRequirements requirements = new ChannelProtectionRequirements();
  186. ProtectionLevel contractScopeDefaultRequestProtectionLevel;
  187. ProtectionLevel contractScopeDefaultResponseProtectionLevel;
  188. if (contract.HasProtectionLevel)
  189. {
  190. contractScopeDefaultRequestProtectionLevel = contract.ProtectionLevel;
  191. contractScopeDefaultResponseProtectionLevel = contract.ProtectionLevel;
  192. }
  193. else
  194. {
  195. contractScopeDefaultRequestProtectionLevel = defaultRequestProtectionLevel;
  196. contractScopeDefaultResponseProtectionLevel = defaultResponseProtectionLevel;
  197. }
  198. foreach (OperationDescription operation in contract.Operations)
  199. {
  200. ProtectionLevel operationScopeDefaultRequestProtectionLevel;
  201. ProtectionLevel operationScopeDefaultResponseProtectionLevel;
  202. if (operation.HasProtectionLevel)
  203. {
  204. operationScopeDefaultRequestProtectionLevel = operation.ProtectionLevel;
  205. operationScopeDefaultResponseProtectionLevel = operation.ProtectionLevel;
  206. }
  207. else
  208. {
  209. operationScopeDefaultRequestProtectionLevel = contractScopeDefaultRequestProtectionLevel;
  210. operationScopeDefaultResponseProtectionLevel = contractScopeDefaultResponseProtectionLevel;
  211. }
  212. foreach (MessageDescription message in operation.Messages)
  213. {
  214. ProtectionLevel messageScopeDefaultProtectionLevel;
  215. if (message.HasProtectionLevel)
  216. {
  217. messageScopeDefaultProtectionLevel = message.ProtectionLevel;
  218. }
  219. else if (message.Direction == MessageDirection.Input)
  220. {
  221. messageScopeDefaultProtectionLevel = operationScopeDefaultRequestProtectionLevel;
  222. }
  223. else
  224. {
  225. messageScopeDefaultProtectionLevel = operationScopeDefaultResponseProtectionLevel;
  226. }
  227. MessagePartSpecification signedParts = new MessagePartSpecification();
  228. MessagePartSpecification encryptedParts = new MessagePartSpecification();
  229. // determine header protection requirements for message
  230. foreach (MessageHeaderDescription header in message.Headers)
  231. {
  232. AddHeaderProtectionRequirements(header, signedParts, encryptedParts, messageScopeDefaultProtectionLevel);
  233. }
  234. // determine body protection requirements for message
  235. ProtectionLevel bodyProtectionLevel;
  236. if (message.Body.Parts.Count > 0)
  237. {
  238. // initialize the body protection level to none. all the body parts will be
  239. // unioned to get the effective body protection level
  240. bodyProtectionLevel = ProtectionLevel.None;
  241. }
  242. else if (message.Body.ReturnValue != null)
  243. {
  244. if (!(message.Body.ReturnValue.GetType().Equals(typeof(MessagePartDescription))))
  245. {
  246. Fx.Assert("Only body return values are supported currently");
  247. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OnlyBodyReturnValuesSupported)));
  248. }
  249. MessagePartDescription desc = message.Body.ReturnValue;
  250. bodyProtectionLevel = desc.HasProtectionLevel ? desc.ProtectionLevel : messageScopeDefaultProtectionLevel;
  251. }
  252. else
  253. {
  254. bodyProtectionLevel = messageScopeDefaultProtectionLevel;
  255. }
  256. // determine body protection requirements for message
  257. if (message.Body.Parts.Count > 0)
  258. {
  259. foreach (MessagePartDescription body in message.Body.Parts)
  260. {
  261. ProtectionLevel partProtectionLevel = body.HasProtectionLevel ? body.ProtectionLevel : messageScopeDefaultProtectionLevel;
  262. bodyProtectionLevel = ProtectionLevelHelper.Max(bodyProtectionLevel, partProtectionLevel);
  263. if (bodyProtectionLevel == ProtectionLevel.EncryptAndSign)
  264. break;
  265. }
  266. }
  267. if (bodyProtectionLevel != ProtectionLevel.None)
  268. {
  269. signedParts.IsBodyIncluded = true;
  270. if (bodyProtectionLevel == ProtectionLevel.EncryptAndSign)
  271. encryptedParts.IsBodyIncluded = true;
  272. }
  273. // add requirements for message
  274. if (message.Direction == MessageDirection.Input)
  275. {
  276. requirements.IncomingSignatureParts.AddParts(signedParts, message.Action);
  277. requirements.IncomingEncryptionParts.AddParts(encryptedParts, message.Action);
  278. }
  279. else
  280. {
  281. requirements.OutgoingSignatureParts.AddParts(signedParts, message.Action);
  282. requirements.OutgoingEncryptionParts.AddParts(encryptedParts, message.Action);
  283. }
  284. }
  285. if (operation.Faults != null)
  286. {
  287. if (operation.IsServerInitiated())
  288. {
  289. AddFaultProtectionRequirements(operation.Faults, requirements, operationScopeDefaultRequestProtectionLevel, true);
  290. }
  291. else
  292. {
  293. AddFaultProtectionRequirements(operation.Faults, requirements, operationScopeDefaultResponseProtectionLevel, false);
  294. }
  295. }
  296. }
  297. return requirements;
  298. }
  299. static void AddHeaderProtectionRequirements(MessageHeaderDescription header, MessagePartSpecification signedParts,
  300. MessagePartSpecification encryptedParts, ProtectionLevel defaultProtectionLevel)
  301. {
  302. ProtectionLevel p = header.HasProtectionLevel ? header.ProtectionLevel : defaultProtectionLevel;
  303. if (p != ProtectionLevel.None)
  304. {
  305. XmlQualifiedName headerName = new XmlQualifiedName(header.Name, header.Namespace);
  306. signedParts.HeaderTypes.Add(headerName);
  307. if (p == ProtectionLevel.EncryptAndSign)
  308. encryptedParts.HeaderTypes.Add(headerName);
  309. }
  310. }
  311. static void AddFaultProtectionRequirements(FaultDescriptionCollection faults, ChannelProtectionRequirements requirements, ProtectionLevel defaultProtectionLevel, bool addToIncoming)
  312. {
  313. if (faults == null)
  314. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faults"));
  315. if (requirements == null)
  316. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("requirements"));
  317. foreach (FaultDescription fault in faults)
  318. {
  319. MessagePartSpecification signedParts = new MessagePartSpecification();
  320. MessagePartSpecification encryptedParts = new MessagePartSpecification();
  321. ProtectionLevel p = fault.HasProtectionLevel ? fault.ProtectionLevel : defaultProtectionLevel;
  322. if (p != ProtectionLevel.None)
  323. {
  324. signedParts.IsBodyIncluded = true;
  325. if (p == ProtectionLevel.EncryptAndSign)
  326. {
  327. encryptedParts.IsBodyIncluded = true;
  328. }
  329. }
  330. if (addToIncoming)
  331. {
  332. requirements.IncomingSignatureParts.AddParts(signedParts, fault.Action);
  333. requirements.IncomingEncryptionParts.AddParts(encryptedParts, fault.Action);
  334. }
  335. else
  336. {
  337. requirements.OutgoingSignatureParts.AddParts(signedParts, fault.Action);
  338. requirements.OutgoingEncryptionParts.AddParts(encryptedParts, fault.Action);
  339. }
  340. }
  341. }
  342. }
  343. }