MessageSecurityBindingSupport.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. //
  2. // MessageSecurityBindingSupport.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  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. Uri listen_uri;
  290. SecurityToken encryption_token;
  291. SecurityToken signing_token;
  292. public RecipientMessageSecurityBindingSupport (
  293. SecurityCapabilities elementSupport,
  294. SecurityTokenManager manager,
  295. ChannelProtectionRequirements requirements)
  296. : base (elementSupport, manager, requirements)
  297. {
  298. }
  299. public override IDefaultCommunicationTimeouts Timeouts {
  300. get { return listener; }
  301. }
  302. // FIXME: this is invoked inconsistently between SecurityReplyChannel and SecurityDuplexSessionChannel on when to do it.
  303. public void Prepare (ChannelListenerBase listener, Uri listenUri)
  304. {
  305. this.listener = listener;
  306. this.listen_uri = listenUri;
  307. PrepareAuthenticator ();
  308. // This check is almost extra, though it is needed
  309. // to check correct signing token existence.
  310. //
  311. // Not sure if it is limited to this condition, but
  312. // Ssl parameters do not support token provider and
  313. // still do not fail. X509 parameters do fail.
  314. //
  315. // FIXME: as AsymmetricSecurityBindingElementTest
  316. // .ServiceRecipientHasNoKeys() implies, it should be
  317. // the recipient's parameters that is used. However
  318. // such changes will break some of existing tests...
  319. if (InitiatorParameters.InternalHasAsymmetricKey &&
  320. EncryptionToken == null)
  321. throw new Exception ("INTERNAL ERROR");
  322. }
  323. public override SecurityToken EncryptionToken {
  324. get {
  325. if (encryption_token == null) {
  326. SecurityTokenRequirement r = CreateRequirement ();
  327. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
  328. encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
  329. }
  330. return encryption_token;
  331. }
  332. }
  333. public override SecurityToken SigningToken {
  334. get {
  335. if (signing_token == null) {
  336. SecurityTokenRequirement r = CreateRequirement ();
  337. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  338. InitializeRequirement (RecipientParameters, r);
  339. signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature);
  340. }
  341. return signing_token;
  342. }
  343. }
  344. protected override void ReleaseCore ()
  345. {
  346. this.listener = null;
  347. IDisposable disposable = signing_token as IDisposable;
  348. if (disposable != null)
  349. disposable.Dispose ();
  350. signing_token = null;
  351. disposable = encryption_token as IDisposable;
  352. if (disposable != null)
  353. disposable.Dispose ();
  354. encryption_token = null;
  355. }
  356. public override SecurityTokenRequirement CreateRequirement ()
  357. {
  358. SecurityTokenRequirement requirement =
  359. new RecipientServiceModelSecurityTokenRequirement ();
  360. requirement.Properties [ReqType.ListenUriProperty] = listen_uri;
  361. return requirement;
  362. }
  363. public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
  364. {
  365. resolver = null;
  366. // This check might be almost extra, though it is
  367. // needed to check correct signing token existence.
  368. //
  369. // Not sure if it is limited to this condition, but
  370. // Ssl parameters do not support token provider and
  371. // still do not fail. X509 parameters do fail.
  372. if (!RecipientParameters.InternalSupportsServerAuthentication)
  373. return null;
  374. SecurityTokenRequirement r = CreateRequirement ();
  375. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  376. InitializeRequirement (p, r);
  377. return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
  378. }
  379. }
  380. }