2 // MessageSecurityBindingSupport.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
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;
39 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
41 namespace System.ServiceModel.Channels.Security
43 internal abstract class MessageSecurityBindingSupport
45 SecurityTokenManager manager;
46 ChannelProtectionRequirements requirements;
47 SecurityTokenSerializer serializer;
48 SecurityCapabilities element_support;
50 // only filled at prepared state.
51 SecurityTokenAuthenticator authenticator;
52 SecurityTokenResolver auth_token_resolver;
54 protected MessageSecurityBindingSupport (
55 SecurityCapabilities elementSupport,
56 SecurityTokenManager manager,
57 ChannelProtectionRequirements requirements)
59 element_support = elementSupport;
60 Initialize (manager, requirements);
63 public void Initialize (SecurityTokenManager manager,
64 ChannelProtectionRequirements requirements)
66 this.manager = manager;
67 if (requirements == null)
68 requirements = new ChannelProtectionRequirements ();
69 this.requirements = requirements;
72 public abstract IDefaultCommunicationTimeouts Timeouts { get; }
74 public ChannelProtectionRequirements ChannelRequirements {
75 get { return requirements; }
78 public SecurityTokenManager SecurityTokenManager {
79 get { return manager; }
82 public SecurityTokenSerializer TokenSerializer {
84 if (serializer == null)
85 serializer = manager.CreateSecurityTokenSerializer (Element.MessageSecurityVersion.SecurityTokenVersion);
90 public SecurityTokenAuthenticator TokenAuthenticator {
91 get { return authenticator; }
94 public SecurityTokenResolver OutOfBandTokenResolver {
95 get { return auth_token_resolver; }
98 public abstract SecurityToken EncryptionToken { get; }
100 public abstract SecurityToken SigningToken { get; }
102 #region element_support
104 public SecurityBindingElement Element {
105 get { return element_support.Element; }
108 public bool AllowSerializedSigningTokenOnReply {
109 get { return element_support.AllowSerializedSigningTokenOnReply; }
112 public MessageProtectionOrder MessageProtectionOrder {
113 get { return element_support.MessageProtectionOrder; }
116 public SecurityTokenParameters InitiatorParameters {
117 get { return element_support.InitiatorParameters; }
120 public SecurityTokenParameters RecipientParameters {
121 get { return element_support.RecipientParameters; }
124 public bool RequireSignatureConfirmation {
125 get { return element_support.RequireSignatureConfirmation; }
128 public string DefaultSignatureAlgorithm {
129 get { return element_support.DefaultSignatureAlgorithm; }
132 public string DefaultKeyWrapAlgorithm {
133 get { return element_support.DefaultKeyWrapAlgorithm; }
138 public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement)
140 return manager.CreateSecurityTokenProvider (requirement);
143 public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver);
145 protected void PrepareAuthenticator ()
147 authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver);
150 protected void InitializeRequirement (SecurityTokenParameters p, SecurityTokenRequirement r)
152 p.CallInitializeSecurityTokenRequirement (r);
154 // r.Properties [ChannelParametersCollectionProperty] =
155 // r.Properties [ReqType.EndpointFilterTableProperty] =
156 // r.Properties [ReqType.HttpAuthenticationSchemeProperty] =
157 // r.Properties [ReqType.IsOutOfBandTokenProperty] =
158 // r.Properties [ReqType.IssuerAddressProperty] =
159 // r.Properties [ReqType.MessageDirectionProperty] =
160 r.Properties [ReqType.MessageSecurityVersionProperty] = Element.MessageSecurityVersion.SecurityTokenVersion;
161 r.Properties [ReqType.SecurityAlgorithmSuiteProperty] = Element.DefaultAlgorithmSuite;
162 r.Properties [ReqType.SecurityBindingElementProperty] = Element;
163 // r.Properties [ReqType.SupportingTokenAttachmentModeProperty] =
164 // r.TransportScheme =
167 public void Release ()
171 authenticator = null;
174 protected abstract void ReleaseCore ();
176 public SupportingTokenInfoCollection CollectSupportingTokens (string action)
178 SupportingTokenInfoCollection tokens =
179 new SupportingTokenInfoCollection ();
181 SupportingTokenParameters supp;
183 CollectSupportingTokensCore (tokens, Element.EndpointSupportingTokenParameters, true);
184 if (Element.OperationSupportingTokenParameters.TryGetValue (action, out supp))
185 CollectSupportingTokensCore (tokens, supp, true);
186 CollectSupportingTokensCore (tokens, Element.OptionalEndpointSupportingTokenParameters, false);
187 if (Element.OptionalOperationSupportingTokenParameters.TryGetValue (action, out supp))
188 CollectSupportingTokensCore (tokens, supp, false);
193 void CollectSupportingTokensCore (
194 SupportingTokenInfoCollection l,
195 SupportingTokenParameters s,
198 foreach (SecurityTokenParameters p in s.Signed)
199 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Signed, required));
200 foreach (SecurityTokenParameters p in s.Endorsing)
201 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Endorsing, required));
202 foreach (SecurityTokenParameters p in s.SignedEndorsing)
203 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEndorsing, required));
204 foreach (SecurityTokenParameters p in s.SignedEncrypted)
205 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEncrypted, required));
208 SecurityToken GetSigningToken (SecurityTokenParameters p)
210 return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature);
213 SecurityToken GetExchangeToken (SecurityTokenParameters p)
215 return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange);
218 public SecurityToken GetToken (SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)
220 requirement.KeyUsage = usage;
221 requirement.Properties [ReqType.SecurityBindingElementProperty] = Element;
222 requirement.Properties [ReqType.MessageSecurityVersionProperty] =
223 Element.MessageSecurityVersion.SecurityTokenVersion;
225 InitializeRequirement (targetParams, requirement);
227 SecurityTokenProvider provider =
228 CreateTokenProvider (requirement);
229 ICommunicationObject obj = provider as ICommunicationObject;
232 obj.Open (Timeouts.OpenTimeout);
233 return provider.GetToken (Timeouts.SendTimeout);
235 if (obj != null && obj.State == CommunicationState.Opened)
240 public abstract SecurityTokenRequirement CreateRequirement ();
243 internal class InitiatorMessageSecurityBindingSupport : MessageSecurityBindingSupport
245 ChannelFactoryBase factory;
246 EndpointAddress message_to;
247 SecurityToken encryption_token;
248 SecurityToken signing_token;
250 public InitiatorMessageSecurityBindingSupport (
251 SecurityCapabilities elementSupport,
252 SecurityTokenManager manager,
253 ChannelProtectionRequirements requirements)
254 : base (elementSupport, manager, requirements)
258 public override IDefaultCommunicationTimeouts Timeouts {
259 get { return factory; }
262 public void Prepare (ChannelFactoryBase factory, EndpointAddress address)
264 this.factory = factory;
265 this.message_to = address;
267 PrepareAuthenticator ();
269 // This check is almost extra, though it is needed
270 // to check correct signing token existence.
271 if (EncryptionToken == null)
272 throw new Exception ("INTERNAL ERROR");
275 public override SecurityToken EncryptionToken {
277 if (encryption_token == null) {
278 SecurityTokenRequirement r = CreateRequirement ();
279 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
280 InitializeRequirement (RecipientParameters, r);
281 encryption_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Exchange);
283 return encryption_token;
287 public override SecurityToken SigningToken {
289 if (signing_token == null) {
290 SecurityTokenRequirement r = CreateRequirement ();
291 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
292 InitializeRequirement (InitiatorParameters, r);
293 signing_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Signature);
295 return signing_token;
299 protected override void ReleaseCore ()
302 this.message_to = null;
304 IDisposable disposable = signing_token as IDisposable;
305 if (disposable != null)
306 disposable.Dispose ();
307 signing_token = null;
309 disposable = encryption_token as IDisposable;
310 if (disposable != null)
311 disposable.Dispose ();
312 encryption_token = null;
315 public override SecurityTokenRequirement CreateRequirement ()
317 SecurityTokenRequirement r = new InitiatorServiceModelSecurityTokenRequirement ();
318 // r.Properties [ReqType.IssuerAddressProperty] = message_to;
319 r.Properties [ReqType.TargetAddressProperty] = message_to;
324 public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
327 // This check might be almost extra, though it is
328 // needed to check correct signing token existence.
330 // Not sure if it is limited to this condition, but
331 // Ssl parameters do not support token provider and
332 // still do not fail. X509 parameters do fail.
333 if (!InitiatorParameters.InternalSupportsClientAuthentication)
336 SecurityTokenRequirement r = CreateRequirement ();
337 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
338 InitializeRequirement (p, r);
339 return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
343 class RecipientMessageSecurityBindingSupport : MessageSecurityBindingSupport
345 ChannelListenerBase listener;
346 SecurityToken encryption_token;
347 SecurityToken signing_token;
349 public RecipientMessageSecurityBindingSupport (
350 SecurityCapabilities elementSupport,
351 SecurityTokenManager manager,
352 ChannelProtectionRequirements requirements)
353 : base (elementSupport, manager, requirements)
357 public override IDefaultCommunicationTimeouts Timeouts {
358 get { return listener; }
361 public void Prepare (ChannelListenerBase listener)
363 this.listener = listener;
365 PrepareAuthenticator ();
367 // This check is almost extra, though it is needed
368 // to check correct signing token existence.
370 // Not sure if it is limited to this condition, but
371 // Ssl parameters do not support token provider and
372 // still do not fail. X509 parameters do fail.
374 // FIXME: as AsymmetricSecurityBindingElementTest
375 // .ServiceRecipientHasNoKeys() implies, it should be
376 // the recipient's parameters that is used. However
377 // such changes will break some of existing tests...
378 if (InitiatorParameters.InternalHasAsymmetricKey &&
379 EncryptionToken == null)
380 throw new Exception ("INTERNAL ERROR");
383 public override SecurityToken EncryptionToken {
385 if (encryption_token == null) {
386 SecurityTokenRequirement r = CreateRequirement ();
387 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
388 encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
390 return encryption_token;
394 public override SecurityToken SigningToken {
396 if (signing_token == null) {
397 SecurityTokenRequirement r = CreateRequirement ();
398 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
399 InitializeRequirement (RecipientParameters, r);
400 signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature);
402 return signing_token;
406 protected override void ReleaseCore ()
408 this.listener = null;
410 IDisposable disposable = signing_token as IDisposable;
411 if (disposable != null)
412 disposable.Dispose ();
413 signing_token = null;
415 disposable = encryption_token as IDisposable;
416 if (disposable != null)
417 disposable.Dispose ();
418 encryption_token = null;
421 public override SecurityTokenRequirement CreateRequirement ()
423 SecurityTokenRequirement requirement =
424 new RecipientServiceModelSecurityTokenRequirement ();
425 requirement.Properties [ReqType.ListenUriProperty] = listener.Uri;
429 public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
432 // This check might be almost extra, though it is
433 // needed to check correct signing token existence.
435 // Not sure if it is limited to this condition, but
436 // Ssl parameters do not support token provider and
437 // still do not fail. X509 parameters do fail.
438 if (!RecipientParameters.InternalSupportsServerAuthentication)
441 SecurityTokenRequirement r = CreateRequirement ();
442 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
443 InitializeRequirement (p, r);
444 return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);