PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Security/MessageSecurityBindingSupport.cs

https://github.com/rasmus-toftdahl-olesen/mono
C# | 447 lines | 314 code | 70 blank | 63 comment | 34 complexity | 51394d511df26d9bd38c9b5a26a82a35 MD5 | raw file
  1. //
  2. // MessageSecurityBindingSupport.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <atsushi@ximian.com>
  6. //
  7. // Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System.Collections.Generic;
  29. using System.Collections.ObjectModel;
  30. using System.IdentityModel.Selectors;
  31. using System.IdentityModel.Tokens;
  32. using System.Net.Security;
  33. using System.Security.Cryptography.Xml;
  34. using System.ServiceModel.Channels;
  35. using System.ServiceModel.Description;
  36. using System.ServiceModel.Security;
  37. using System.ServiceModel.Security.Tokens;
  38. using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
  39. namespace System.ServiceModel.Channels.Security
  40. {
  41. internal abstract class MessageSecurityBindingSupport
  42. {
  43. SecurityTokenManager manager;
  44. ChannelProtectionRequirements requirements;
  45. SecurityTokenSerializer serializer;
  46. SecurityCapabilities element_support;
  47. // only filled at prepared state.
  48. SecurityTokenAuthenticator authenticator;
  49. SecurityTokenResolver auth_token_resolver;
  50. protected MessageSecurityBindingSupport (
  51. SecurityCapabilities elementSupport,
  52. SecurityTokenManager manager,
  53. ChannelProtectionRequirements requirements)
  54. {
  55. element_support = elementSupport;
  56. Initialize (manager, requirements);
  57. }
  58. public void Initialize (SecurityTokenManager manager,
  59. ChannelProtectionRequirements requirements)
  60. {
  61. this.manager = manager;
  62. if (requirements == null)
  63. requirements = new ChannelProtectionRequirements ();
  64. this.requirements = requirements;
  65. }
  66. public abstract IDefaultCommunicationTimeouts Timeouts { get; }
  67. public ChannelProtectionRequirements ChannelRequirements {
  68. get { return requirements; }
  69. }
  70. public SecurityTokenManager SecurityTokenManager {
  71. get { return manager; }
  72. }
  73. public SecurityTokenSerializer TokenSerializer {
  74. get {
  75. if (serializer == null)
  76. serializer = manager.CreateSecurityTokenSerializer (Element.MessageSecurityVersion.SecurityTokenVersion);
  77. return serializer;
  78. }
  79. }
  80. public SecurityTokenAuthenticator TokenAuthenticator {
  81. get { return authenticator; }
  82. }
  83. public SecurityTokenResolver OutOfBandTokenResolver {
  84. get { return auth_token_resolver; }
  85. }
  86. public abstract SecurityToken EncryptionToken { get; }
  87. public abstract SecurityToken SigningToken { get; }
  88. #region element_support
  89. public SecurityBindingElement Element {
  90. get { return element_support.Element; }
  91. }
  92. public bool AllowSerializedSigningTokenOnReply {
  93. get { return element_support.AllowSerializedSigningTokenOnReply; }
  94. }
  95. public MessageProtectionOrder MessageProtectionOrder {
  96. get { return element_support.MessageProtectionOrder; }
  97. }
  98. public SecurityTokenParameters InitiatorParameters {
  99. get { return element_support.InitiatorParameters; }
  100. }
  101. public SecurityTokenParameters RecipientParameters {
  102. get { return element_support.RecipientParameters; }
  103. }
  104. public bool RequireSignatureConfirmation {
  105. get { return element_support.RequireSignatureConfirmation; }
  106. }
  107. public string DefaultSignatureAlgorithm {
  108. get { return element_support.DefaultSignatureAlgorithm; }
  109. }
  110. public string DefaultKeyWrapAlgorithm {
  111. get { return element_support.DefaultKeyWrapAlgorithm; }
  112. }
  113. #endregion
  114. public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement)
  115. {
  116. return manager.CreateSecurityTokenProvider (requirement);
  117. }
  118. public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver);
  119. protected void PrepareAuthenticator ()
  120. {
  121. authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver);
  122. }
  123. protected void InitializeRequirement (SecurityTokenParameters p, SecurityTokenRequirement r)
  124. {
  125. p.CallInitializeSecurityTokenRequirement (r);
  126. // r.Properties [ChannelParametersCollectionProperty] =
  127. // r.Properties [ReqType.EndpointFilterTableProperty] =
  128. // r.Properties [ReqType.HttpAuthenticationSchemeProperty] =
  129. // r.Properties [ReqType.IsOutOfBandTokenProperty] =
  130. // r.Properties [ReqType.IssuerAddressProperty] =
  131. // r.Properties [ReqType.MessageDirectionProperty] =
  132. r.Properties [ReqType.MessageSecurityVersionProperty] = Element.MessageSecurityVersion.SecurityTokenVersion;
  133. r.Properties [ReqType.SecurityAlgorithmSuiteProperty] = Element.DefaultAlgorithmSuite;
  134. r.Properties [ReqType.SecurityBindingElementProperty] = Element;
  135. // r.Properties [ReqType.SupportingTokenAttachmentModeProperty] =
  136. // r.TransportScheme =
  137. }
  138. public void Release ()
  139. {
  140. ReleaseCore ();
  141. authenticator = null;
  142. }
  143. protected abstract void ReleaseCore ();
  144. public SupportingTokenInfoCollection CollectSupportingTokens (string action)
  145. {
  146. SupportingTokenInfoCollection tokens =
  147. new SupportingTokenInfoCollection ();
  148. SupportingTokenParameters supp;
  149. CollectSupportingTokensCore (tokens, Element.EndpointSupportingTokenParameters, true);
  150. if (Element.OperationSupportingTokenParameters.TryGetValue (action, out supp))
  151. CollectSupportingTokensCore (tokens, supp, true);
  152. CollectSupportingTokensCore (tokens, Element.OptionalEndpointSupportingTokenParameters, false);
  153. if (Element.OptionalOperationSupportingTokenParameters.TryGetValue (action, out supp))
  154. CollectSupportingTokensCore (tokens, supp, false);
  155. return tokens;
  156. }
  157. void CollectSupportingTokensCore (
  158. SupportingTokenInfoCollection l,
  159. SupportingTokenParameters s,
  160. bool required)
  161. {
  162. foreach (SecurityTokenParameters p in s.Signed)
  163. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Signed, required));
  164. foreach (SecurityTokenParameters p in s.Endorsing)
  165. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Endorsing, required));
  166. foreach (SecurityTokenParameters p in s.SignedEndorsing)
  167. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEndorsing, required));
  168. foreach (SecurityTokenParameters p in s.SignedEncrypted)
  169. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEncrypted, required));
  170. }
  171. SecurityToken GetSigningToken (SecurityTokenParameters p)
  172. {
  173. return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature);
  174. }
  175. SecurityToken GetExchangeToken (SecurityTokenParameters p)
  176. {
  177. return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange);
  178. }
  179. public SecurityToken GetToken (SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)
  180. {
  181. requirement.KeyUsage = usage;
  182. requirement.Properties [ReqType.SecurityBindingElementProperty] = Element;
  183. requirement.Properties [ReqType.MessageSecurityVersionProperty] =
  184. Element.MessageSecurityVersion.SecurityTokenVersion;
  185. InitializeRequirement (targetParams, requirement);
  186. SecurityTokenProvider provider =
  187. CreateTokenProvider (requirement);
  188. ICommunicationObject obj = provider as ICommunicationObject;
  189. try {
  190. if (obj != null)
  191. obj.Open (Timeouts.OpenTimeout);
  192. return provider.GetToken (Timeouts.SendTimeout);
  193. } finally {
  194. if (obj != null && obj.State == CommunicationState.Opened)
  195. obj.Close ();
  196. }
  197. }
  198. public abstract SecurityTokenRequirement CreateRequirement ();
  199. }
  200. internal class InitiatorMessageSecurityBindingSupport : MessageSecurityBindingSupport
  201. {
  202. ChannelFactoryBase factory;
  203. EndpointAddress message_to;
  204. SecurityToken encryption_token;
  205. SecurityToken signing_token;
  206. public InitiatorMessageSecurityBindingSupport (
  207. SecurityCapabilities elementSupport,
  208. SecurityTokenManager manager,
  209. ChannelProtectionRequirements requirements)
  210. : base (elementSupport, manager, requirements)
  211. {
  212. }
  213. public override IDefaultCommunicationTimeouts Timeouts {
  214. get { return factory; }
  215. }
  216. public void Prepare (ChannelFactoryBase factory, EndpointAddress address)
  217. {
  218. this.factory = factory;
  219. this.message_to = address;
  220. PrepareAuthenticator ();
  221. // This check is almost extra, though it is needed
  222. // to check correct signing token existence.
  223. if (EncryptionToken == null)
  224. throw new Exception ("INTERNAL ERROR");
  225. }
  226. public override SecurityToken EncryptionToken {
  227. get {
  228. if (encryption_token == null) {
  229. SecurityTokenRequirement r = CreateRequirement ();
  230. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  231. InitializeRequirement (RecipientParameters, r);
  232. encryption_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Exchange);
  233. }
  234. return encryption_token;
  235. }
  236. }
  237. public override SecurityToken SigningToken {
  238. get {
  239. if (signing_token == null) {
  240. SecurityTokenRequirement r = CreateRequirement ();
  241. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  242. InitializeRequirement (InitiatorParameters, r);
  243. signing_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Signature);
  244. }
  245. return signing_token;
  246. }
  247. }
  248. protected override void ReleaseCore ()
  249. {
  250. this.factory = null;
  251. this.message_to = null;
  252. IDisposable disposable = signing_token as IDisposable;
  253. if (disposable != null)
  254. disposable.Dispose ();
  255. signing_token = null;
  256. disposable = encryption_token as IDisposable;
  257. if (disposable != null)
  258. disposable.Dispose ();
  259. encryption_token = null;
  260. }
  261. public override SecurityTokenRequirement CreateRequirement ()
  262. {
  263. SecurityTokenRequirement r = new InitiatorServiceModelSecurityTokenRequirement ();
  264. // r.Properties [ReqType.IssuerAddressProperty] = message_to;
  265. r.Properties [ReqType.TargetAddressProperty] = message_to;
  266. // FIXME: set Via
  267. return r;
  268. }
  269. public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
  270. {
  271. resolver = null;
  272. // This check might be almost extra, though it is
  273. // needed to check correct signing token existence.
  274. //
  275. // Not sure if it is limited to this condition, but
  276. // Ssl parameters do not support token provider and
  277. // still do not fail. X509 parameters do fail.
  278. if (!InitiatorParameters.InternalSupportsClientAuthentication)
  279. return null;
  280. SecurityTokenRequirement r = CreateRequirement ();
  281. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
  282. InitializeRequirement (p, r);
  283. return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
  284. }
  285. }
  286. class RecipientMessageSecurityBindingSupport : MessageSecurityBindingSupport
  287. {
  288. ChannelListenerBase listener;
  289. SecurityToken encryption_token;
  290. SecurityToken signing_token;
  291. public RecipientMessageSecurityBindingSupport (
  292. SecurityCapabilities elementSupport,
  293. SecurityTokenManager manager,
  294. ChannelProtectionRequirements requirements)
  295. : base (elementSupport, manager, requirements)
  296. {
  297. }
  298. public override IDefaultCommunicationTimeouts Timeouts {
  299. get { return listener; }
  300. }
  301. public void Prepare (ChannelListenerBase listener)
  302. {
  303. this.listener = listener;
  304. PrepareAuthenticator ();
  305. // This check is almost extra, though it is needed
  306. // to check correct signing token existence.
  307. //
  308. // Not sure if it is limited to this condition, but
  309. // Ssl parameters do not support token provider and
  310. // still do not fail. X509 parameters do fail.
  311. //
  312. // FIXME: as AsymmetricSecurityBindingElementTest
  313. // .ServiceRecipientHasNoKeys() implies, it should be
  314. // the recipient's parameters that is used. However
  315. // such changes will break some of existing tests...
  316. if (InitiatorParameters.InternalHasAsymmetricKey &&
  317. EncryptionToken == null)
  318. throw new Exception ("INTERNAL ERROR");
  319. }
  320. public override SecurityToken EncryptionToken {
  321. get {
  322. if (encryption_token == null) {
  323. SecurityTokenRequirement r = CreateRequirement ();
  324. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
  325. encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
  326. }
  327. return encryption_token;
  328. }
  329. }
  330. public override SecurityToken SigningToken {
  331. get {
  332. if (signing_token == null) {
  333. SecurityTokenRequirement r = CreateRequirement ();
  334. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  335. InitializeRequirement (RecipientParameters, r);
  336. signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature);
  337. }
  338. return signing_token;
  339. }
  340. }
  341. protected override void ReleaseCore ()
  342. {
  343. this.listener = null;
  344. IDisposable disposable = signing_token as IDisposable;
  345. if (disposable != null)
  346. disposable.Dispose ();
  347. signing_token = null;
  348. disposable = encryption_token as IDisposable;
  349. if (disposable != null)
  350. disposable.Dispose ();
  351. encryption_token = null;
  352. }
  353. public override SecurityTokenRequirement CreateRequirement ()
  354. {
  355. SecurityTokenRequirement requirement =
  356. new RecipientServiceModelSecurityTokenRequirement ();
  357. requirement.Properties [ReqType.ListenUriProperty] = listener.Uri;
  358. return requirement;
  359. }
  360. public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
  361. {
  362. resolver = null;
  363. // This check might be almost extra, though it is
  364. // needed to check correct signing token existence.
  365. //
  366. // Not sure if it is limited to this condition, but
  367. // Ssl parameters do not support token provider and
  368. // still do not fail. X509 parameters do fail.
  369. if (!RecipientParameters.InternalSupportsServerAuthentication)
  370. return null;
  371. SecurityTokenRequirement r = CreateRequirement ();
  372. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  373. InitializeRequirement (p, r);
  374. return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
  375. }
  376. }
  377. }