2
0

MessageSecurityBindingSupport.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  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
  40. {
  41. internal class SupportingTokenInfo
  42. {
  43. public SupportingTokenInfo (SecurityToken token,
  44. SecurityTokenAttachmentMode mode,
  45. bool isOptional)
  46. {
  47. Token = token;
  48. Mode = mode;
  49. IsOptional = isOptional;
  50. }
  51. public SecurityToken Token;
  52. public SecurityTokenAttachmentMode Mode;
  53. public bool IsOptional;
  54. public EncryptedData Encrypted;
  55. }
  56. internal class SupportingTokenInfoCollection : Collection<SupportingTokenInfo>
  57. {
  58. protected override void InsertItem (int index, SupportingTokenInfo item)
  59. {
  60. foreach (SupportingTokenInfo i in this)
  61. if (i.Token.GetType () == item.Token.GetType ())
  62. throw new ArgumentException (String.Format ("Supporting tokens do not allow multiple SecurityTokens of the same type: {0}", i.Token.GetType ()));
  63. base.InsertItem (index, item);
  64. }
  65. }
  66. internal abstract class MessageSecurityBindingSupport
  67. {
  68. SecurityTokenManager manager;
  69. ChannelProtectionRequirements requirements;
  70. SecurityTokenSerializer serializer;
  71. SecurityCapabilities element_support;
  72. // only filled at prepared state.
  73. SecurityTokenAuthenticator authenticator;
  74. SecurityTokenResolver auth_token_resolver;
  75. protected MessageSecurityBindingSupport (
  76. SecurityCapabilities elementSupport,
  77. SecurityTokenManager manager,
  78. ChannelProtectionRequirements requirements)
  79. {
  80. element_support = elementSupport;
  81. Initialize (manager, requirements);
  82. }
  83. public void Initialize (SecurityTokenManager manager,
  84. ChannelProtectionRequirements requirements)
  85. {
  86. this.manager = manager;
  87. if (requirements == null)
  88. requirements = new ChannelProtectionRequirements ();
  89. this.requirements = requirements;
  90. }
  91. public abstract IDefaultCommunicationTimeouts Timeouts { get; }
  92. public ChannelProtectionRequirements ChannelRequirements {
  93. get { return requirements; }
  94. }
  95. public SecurityTokenManager SecurityTokenManager {
  96. get { return manager; }
  97. }
  98. public SecurityTokenSerializer TokenSerializer {
  99. get {
  100. if (serializer == null)
  101. serializer = manager.CreateSecurityTokenSerializer (Element.MessageSecurityVersion.SecurityTokenVersion);
  102. return serializer;
  103. }
  104. }
  105. public SecurityTokenAuthenticator TokenAuthenticator {
  106. get { return authenticator; }
  107. }
  108. public SecurityTokenResolver OutOfBandTokenResolver {
  109. get { return auth_token_resolver; }
  110. }
  111. public abstract SecurityToken EncryptionToken { get; }
  112. public abstract SecurityToken SigningToken { get; }
  113. #region element_support
  114. public SecurityBindingElement Element {
  115. get { return element_support.Element; }
  116. }
  117. public bool AllowSerializedSigningTokenOnReply {
  118. get { return element_support.AllowSerializedSigningTokenOnReply; }
  119. }
  120. public MessageProtectionOrder MessageProtectionOrder {
  121. get { return element_support.MessageProtectionOrder; }
  122. }
  123. public SecurityTokenParameters InitiatorParameters {
  124. get { return element_support.InitiatorParameters; }
  125. }
  126. public SecurityTokenParameters RecipientParameters {
  127. get { return element_support.RecipientParameters; }
  128. }
  129. public bool RequireSignatureConfirmation {
  130. get { return element_support.RequireSignatureConfirmation; }
  131. }
  132. public string DefaultSignatureAlgorithm {
  133. get { return element_support.DefaultSignatureAlgorithm; }
  134. }
  135. public string DefaultKeyWrapAlgorithm {
  136. get { return element_support.DefaultKeyWrapAlgorithm; }
  137. }
  138. #endregion
  139. public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement)
  140. {
  141. return manager.CreateSecurityTokenProvider (requirement);
  142. }
  143. public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver);
  144. protected void PrepareAuthenticator ()
  145. {
  146. authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver);
  147. }
  148. protected void InitializeRequirement (SecurityTokenParameters p, SecurityTokenRequirement r)
  149. {
  150. p.CallInitializeSecurityTokenRequirement (r);
  151. // r.Properties [ChannelParametersCollectionProperty] =
  152. // r.Properties [ReqType.EndpointFilterTableProperty] =
  153. // r.Properties [ReqType.HttpAuthenticationSchemeProperty] =
  154. // r.Properties [ReqType.IsOutOfBandTokenProperty] =
  155. // r.Properties [ReqType.IssuerAddressProperty] =
  156. // r.Properties [ReqType.MessageDirectionProperty] =
  157. r.Properties [ReqType.MessageSecurityVersionProperty] = Element.MessageSecurityVersion.SecurityTokenVersion;
  158. r.Properties [ReqType.SecurityAlgorithmSuiteProperty] = Element.DefaultAlgorithmSuite;
  159. r.Properties [ReqType.SecurityBindingElementProperty] = Element;
  160. // r.Properties [ReqType.SupportingTokenAttachmentModeProperty] =
  161. // r.TransportScheme =
  162. }
  163. public void Release ()
  164. {
  165. ReleaseCore ();
  166. authenticator = null;
  167. }
  168. protected abstract void ReleaseCore ();
  169. public SupportingTokenInfoCollection CollectSupportingTokens (string action)
  170. {
  171. SupportingTokenInfoCollection tokens =
  172. new SupportingTokenInfoCollection ();
  173. SupportingTokenParameters supp;
  174. CollectSupportingTokensCore (tokens, Element.EndpointSupportingTokenParameters, true);
  175. if (Element.OperationSupportingTokenParameters.TryGetValue (action, out supp))
  176. CollectSupportingTokensCore (tokens, supp, true);
  177. CollectSupportingTokensCore (tokens, Element.OptionalEndpointSupportingTokenParameters, false);
  178. if (Element.OptionalOperationSupportingTokenParameters.TryGetValue (action, out supp))
  179. CollectSupportingTokensCore (tokens, supp, false);
  180. return tokens;
  181. }
  182. void CollectSupportingTokensCore (
  183. SupportingTokenInfoCollection l,
  184. SupportingTokenParameters s,
  185. bool required)
  186. {
  187. foreach (SecurityTokenParameters p in s.Signed)
  188. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Signed, required));
  189. foreach (SecurityTokenParameters p in s.Endorsing)
  190. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Endorsing, required));
  191. foreach (SecurityTokenParameters p in s.SignedEndorsing)
  192. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEndorsing, required));
  193. foreach (SecurityTokenParameters p in s.SignedEncrypted)
  194. l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEncrypted, required));
  195. }
  196. SecurityToken GetSigningToken (SecurityTokenParameters p)
  197. {
  198. return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature);
  199. }
  200. SecurityToken GetExchangeToken (SecurityTokenParameters p)
  201. {
  202. return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange);
  203. }
  204. public SecurityToken GetToken (SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)
  205. {
  206. requirement.KeyUsage = usage;
  207. requirement.Properties [ReqType.SecurityBindingElementProperty] = Element;
  208. requirement.Properties [ReqType.MessageSecurityVersionProperty] =
  209. Element.MessageSecurityVersion.SecurityTokenVersion;
  210. InitializeRequirement (targetParams, requirement);
  211. SecurityTokenProvider provider =
  212. CreateTokenProvider (requirement);
  213. ICommunicationObject obj = provider as ICommunicationObject;
  214. try {
  215. if (obj != null)
  216. obj.Open (Timeouts.OpenTimeout);
  217. return provider.GetToken (Timeouts.SendTimeout);
  218. } finally {
  219. if (obj != null && obj.State == CommunicationState.Opened)
  220. obj.Close ();
  221. }
  222. }
  223. public abstract SecurityTokenRequirement CreateRequirement ();
  224. }
  225. internal class InitiatorMessageSecurityBindingSupport : MessageSecurityBindingSupport
  226. {
  227. ChannelFactoryBase factory;
  228. EndpointAddress message_to;
  229. SecurityToken encryption_token;
  230. SecurityToken signing_token;
  231. public InitiatorMessageSecurityBindingSupport (
  232. SecurityCapabilities elementSupport,
  233. SecurityTokenManager manager,
  234. ChannelProtectionRequirements requirements)
  235. : base (elementSupport, manager, requirements)
  236. {
  237. }
  238. public override IDefaultCommunicationTimeouts Timeouts {
  239. get { return factory; }
  240. }
  241. public void Prepare (ChannelFactoryBase factory, EndpointAddress address)
  242. {
  243. this.factory = factory;
  244. this.message_to = address;
  245. PrepareAuthenticator ();
  246. // This check is almost extra, though it is needed
  247. // to check correct signing token existence.
  248. if (EncryptionToken == null)
  249. throw new Exception ("INTERNAL ERROR");
  250. }
  251. public override SecurityToken EncryptionToken {
  252. get {
  253. if (encryption_token == null) {
  254. SecurityTokenRequirement r = CreateRequirement ();
  255. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  256. InitializeRequirement (RecipientParameters, r);
  257. encryption_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Exchange);
  258. }
  259. return encryption_token;
  260. }
  261. }
  262. public override SecurityToken SigningToken {
  263. get {
  264. if (signing_token == null) {
  265. SecurityTokenRequirement r = CreateRequirement ();
  266. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  267. InitializeRequirement (InitiatorParameters, r);
  268. signing_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Signature);
  269. }
  270. return signing_token;
  271. }
  272. }
  273. protected override void ReleaseCore ()
  274. {
  275. this.factory = null;
  276. this.message_to = null;
  277. IDisposable disposable = signing_token as IDisposable;
  278. if (disposable != null)
  279. disposable.Dispose ();
  280. signing_token = null;
  281. disposable = encryption_token as IDisposable;
  282. if (disposable != null)
  283. disposable.Dispose ();
  284. encryption_token = null;
  285. }
  286. public override SecurityTokenRequirement CreateRequirement ()
  287. {
  288. SecurityTokenRequirement r = new InitiatorServiceModelSecurityTokenRequirement ();
  289. // r.Properties [ReqType.IssuerAddressProperty] = message_to;
  290. r.Properties [ReqType.TargetAddressProperty] = message_to;
  291. // FIXME: set Via
  292. return r;
  293. }
  294. public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
  295. {
  296. resolver = null;
  297. // This check might be almost extra, though it is
  298. // needed to check correct signing token existence.
  299. //
  300. // Not sure if it is limited to this condition, but
  301. // Ssl parameters do not support token provider and
  302. // still do not fail. X509 parameters do fail.
  303. if (!InitiatorParameters.InternalSupportsClientAuthentication)
  304. return null;
  305. SecurityTokenRequirement r = CreateRequirement ();
  306. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
  307. InitializeRequirement (p, r);
  308. return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
  309. }
  310. }
  311. class RecipientMessageSecurityBindingSupport : MessageSecurityBindingSupport
  312. {
  313. ChannelListenerBase listener;
  314. SecurityToken encryption_token;
  315. SecurityToken signing_token;
  316. public RecipientMessageSecurityBindingSupport (
  317. SecurityCapabilities elementSupport,
  318. SecurityTokenManager manager,
  319. ChannelProtectionRequirements requirements)
  320. : base (elementSupport, manager, requirements)
  321. {
  322. }
  323. public override IDefaultCommunicationTimeouts Timeouts {
  324. get { return listener; }
  325. }
  326. public void Prepare (ChannelListenerBase listener)
  327. {
  328. this.listener = listener;
  329. PrepareAuthenticator ();
  330. // This check is almost extra, though it is needed
  331. // to check correct signing token existence.
  332. //
  333. // Not sure if it is limited to this condition, but
  334. // Ssl parameters do not support token provider and
  335. // still do not fail. X509 parameters do fail.
  336. //
  337. // FIXME: as AsymmetricSecurityBindingElementTest
  338. // .ServiceRecipientHasNoKeys() implies, it should be
  339. // the recipient's parameters that is used. However
  340. // such changes will break some of existing tests...
  341. if (InitiatorParameters.InternalHasAsymmetricKey &&
  342. EncryptionToken == null)
  343. throw new Exception ("INTERNAL ERROR");
  344. }
  345. public override SecurityToken EncryptionToken {
  346. get {
  347. if (encryption_token == null) {
  348. SecurityTokenRequirement r = CreateRequirement ();
  349. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
  350. encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
  351. }
  352. return encryption_token;
  353. }
  354. }
  355. public override SecurityToken SigningToken {
  356. get {
  357. if (signing_token == null) {
  358. SecurityTokenRequirement r = CreateRequirement ();
  359. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  360. InitializeRequirement (RecipientParameters, r);
  361. signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature);
  362. }
  363. return signing_token;
  364. }
  365. }
  366. protected override void ReleaseCore ()
  367. {
  368. this.listener = null;
  369. IDisposable disposable = signing_token as IDisposable;
  370. if (disposable != null)
  371. disposable.Dispose ();
  372. signing_token = null;
  373. disposable = encryption_token as IDisposable;
  374. if (disposable != null)
  375. disposable.Dispose ();
  376. encryption_token = null;
  377. }
  378. public override SecurityTokenRequirement CreateRequirement ()
  379. {
  380. SecurityTokenRequirement requirement =
  381. new RecipientServiceModelSecurityTokenRequirement ();
  382. requirement.Properties [ReqType.ListenUriProperty] = listener.Uri;
  383. return requirement;
  384. }
  385. public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
  386. {
  387. resolver = null;
  388. // This check might be almost extra, though it is
  389. // needed to check correct signing token existence.
  390. //
  391. // Not sure if it is limited to this condition, but
  392. // Ssl parameters do not support token provider and
  393. // still do not fail. X509 parameters do fail.
  394. if (!RecipientParameters.InternalSupportsServerAuthentication)
  395. return null;
  396. SecurityTokenRequirement r = CreateRequirement ();
  397. r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
  398. InitializeRequirement (p, r);
  399. return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
  400. }
  401. }
  402. internal abstract class SecurityCapabilities
  403. : ISecurityCapabilities
  404. {
  405. public abstract SecurityBindingElement Element { get; }
  406. public abstract bool AllowSerializedSigningTokenOnReply { get; }
  407. public abstract MessageProtectionOrder MessageProtectionOrder { get; }
  408. public abstract SecurityTokenParameters InitiatorParameters { get; }
  409. public abstract SecurityTokenParameters RecipientParameters { get; }
  410. public abstract bool RequireSignatureConfirmation { get; }
  411. public abstract string DefaultKeyWrapAlgorithm { get; }
  412. public abstract string DefaultSignatureAlgorithm { get; }
  413. // ISecurityCapabilities
  414. // FIXME: implement correctly
  415. public ProtectionLevel SupportedRequestProtectionLevel {
  416. get { return ProtectionLevel.EncryptAndSign; }
  417. }
  418. public ProtectionLevel SupportedResponseProtectionLevel {
  419. get { return ProtectionLevel.EncryptAndSign; }
  420. }
  421. public bool SupportsClientAuthentication {
  422. get { return InitiatorParameters != null ? InitiatorParameters.InternalSupportsClientAuthentication : false; }
  423. }
  424. public bool SupportsClientWindowsIdentity {
  425. get { return InitiatorParameters != null ? InitiatorParameters.InternalSupportsClientWindowsIdentity : false; }
  426. }
  427. public bool SupportsServerAuthentication {
  428. get { return RecipientParameters != null ? RecipientParameters.InternalSupportsServerAuthentication : false; }
  429. }
  430. }
  431. internal class SymmetricSecurityCapabilities : SecurityCapabilities
  432. {
  433. SymmetricSecurityBindingElement element;
  434. public SymmetricSecurityCapabilities (
  435. SymmetricSecurityBindingElement element)
  436. {
  437. this.element = element;
  438. }
  439. public override SecurityBindingElement Element {
  440. get { return element; }
  441. }
  442. // FIXME: const true or false
  443. public override bool AllowSerializedSigningTokenOnReply {
  444. get { throw new NotImplementedException (); }
  445. }
  446. public override MessageProtectionOrder MessageProtectionOrder {
  447. get { return element.MessageProtectionOrder; }
  448. }
  449. public override SecurityTokenParameters InitiatorParameters {
  450. get { return element.ProtectionTokenParameters; }
  451. }
  452. public override SecurityTokenParameters RecipientParameters {
  453. get { return element.ProtectionTokenParameters; }
  454. }
  455. public override bool RequireSignatureConfirmation {
  456. get { return element.RequireSignatureConfirmation; }
  457. }
  458. public override string DefaultSignatureAlgorithm {
  459. get { return element.DefaultAlgorithmSuite.DefaultSymmetricSignatureAlgorithm; }
  460. }
  461. public override string DefaultKeyWrapAlgorithm {
  462. get { return element.DefaultAlgorithmSuite.DefaultSymmetricKeyWrapAlgorithm; }
  463. }
  464. }
  465. internal class AsymmetricSecurityCapabilities : SecurityCapabilities
  466. {
  467. AsymmetricSecurityBindingElement element;
  468. public AsymmetricSecurityCapabilities (
  469. AsymmetricSecurityBindingElement element)
  470. {
  471. this.element = element;
  472. }
  473. public override bool AllowSerializedSigningTokenOnReply {
  474. get { return element.AllowSerializedSigningTokenOnReply; }
  475. }
  476. public override SecurityBindingElement Element {
  477. get { return element; }
  478. }
  479. public override MessageProtectionOrder MessageProtectionOrder {
  480. get { return element.MessageProtectionOrder; }
  481. }
  482. public override SecurityTokenParameters InitiatorParameters {
  483. get { return element.InitiatorTokenParameters; }
  484. }
  485. public override SecurityTokenParameters RecipientParameters {
  486. get { return element.RecipientTokenParameters; }
  487. }
  488. public override bool RequireSignatureConfirmation {
  489. get { return element.RequireSignatureConfirmation; }
  490. }
  491. public override string DefaultSignatureAlgorithm {
  492. get { return element.DefaultAlgorithmSuite.DefaultAsymmetricSignatureAlgorithm; }
  493. }
  494. public override string DefaultKeyWrapAlgorithm {
  495. get { return element.DefaultAlgorithmSuite.DefaultAsymmetricKeyWrapAlgorithm; }
  496. }
  497. }
  498. }