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 
39 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
40 
41 namespace System.ServiceModel.Channels.Security
42 {
43 	internal abstract class MessageSecurityBindingSupport
44 	{
45 		SecurityTokenManager manager;
46 		ChannelProtectionRequirements requirements;
47 		SecurityTokenSerializer serializer;
48 		SecurityCapabilities element_support;
49 
50 		// only filled at prepared state.
51 		SecurityTokenAuthenticator authenticator;
52 		SecurityTokenResolver auth_token_resolver;
53 
MessageSecurityBindingSupport( SecurityCapabilities elementSupport, SecurityTokenManager manager, ChannelProtectionRequirements requirements)54 		protected MessageSecurityBindingSupport (
55 			SecurityCapabilities elementSupport,
56 			SecurityTokenManager manager,
57 			ChannelProtectionRequirements requirements)
58 		{
59 			element_support = elementSupport;
60 			Initialize (manager, requirements);
61 		}
62 
Initialize(SecurityTokenManager manager, ChannelProtectionRequirements requirements)63 		public void Initialize (SecurityTokenManager manager,
64 			ChannelProtectionRequirements requirements)
65 		{
66 			this.manager = manager;
67 			if (requirements == null)
68 				requirements = new ChannelProtectionRequirements ();
69 			this.requirements = requirements;
70 		}
71 
72 		public abstract IDefaultCommunicationTimeouts Timeouts { get; }
73 
74 		public ChannelProtectionRequirements ChannelRequirements {
75 			get { return requirements; }
76 		}
77 
78 		public SecurityTokenManager SecurityTokenManager {
79 			get { return manager; }
80 		}
81 
82 		public SecurityTokenSerializer TokenSerializer {
83 			get {
84 				if (serializer == null)
85 					serializer = manager.CreateSecurityTokenSerializer (Element.MessageSecurityVersion.SecurityTokenVersion);
86 				return serializer;
87 			}
88 		}
89 
90 		public SecurityTokenAuthenticator TokenAuthenticator {
91 			get { return authenticator; }
92 		}
93 
94 		public SecurityTokenResolver OutOfBandTokenResolver {
95 			get { return auth_token_resolver; }
96 		}
97 
98 		public abstract SecurityToken EncryptionToken { get; }
99 
100 		public abstract SecurityToken SigningToken { get; }
101 
102 		#region element_support
103 
104 		public SecurityBindingElement Element {
105 			get { return element_support.Element; }
106 		}
107 
108 		public bool AllowSerializedSigningTokenOnReply {
109 			get { return element_support.AllowSerializedSigningTokenOnReply; }
110 		}
111 
112 		public MessageProtectionOrder MessageProtectionOrder {
113 			get { return element_support.MessageProtectionOrder; }
114 		}
115 
116 		public SecurityTokenParameters InitiatorParameters {
117 			get { return element_support.InitiatorParameters; }
118 		}
119 
120 		public SecurityTokenParameters RecipientParameters {
121 			get { return element_support.RecipientParameters; }
122 		}
123 
124 		public bool RequireSignatureConfirmation {
125 			get { return element_support.RequireSignatureConfirmation; }
126 		}
127 
128 		public string DefaultSignatureAlgorithm {
129 			get { return element_support.DefaultSignatureAlgorithm; }
130 		}
131 
132 		public string DefaultKeyWrapAlgorithm {
133 			get { return element_support.DefaultKeyWrapAlgorithm; }
134 		}
135 
136 		#endregion
137 
CreateTokenProvider(SecurityTokenRequirement requirement)138 		public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement)
139 		{
140 			return manager.CreateSecurityTokenProvider (requirement);
141 		}
142 
CreateTokenAuthenticator(SecurityTokenParameters p, out SecurityTokenResolver resolver)143 		public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver);
144 
PrepareAuthenticator()145 		protected void PrepareAuthenticator ()
146 		{
147 			authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver);
148 		}
149 
InitializeRequirement(SecurityTokenParameters p, SecurityTokenRequirement r)150 		protected void InitializeRequirement (SecurityTokenParameters p, SecurityTokenRequirement r)
151 		{
152 			p.CallInitializeSecurityTokenRequirement (r);
153 
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 =
165 		}
166 
Release()167 		public void Release ()
168 		{
169 			ReleaseCore ();
170 
171 			authenticator = null;
172 		}
173 
ReleaseCore()174 		protected abstract void ReleaseCore ();
175 
CollectSupportingTokens(string action)176 		public SupportingTokenInfoCollection CollectSupportingTokens (string action)
177 		{
178 			SupportingTokenInfoCollection tokens =
179 				new SupportingTokenInfoCollection ();
180 
181 			SupportingTokenParameters supp;
182 
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);
189 
190 			return tokens;
191 		}
192 
CollectSupportingTokensCore( SupportingTokenInfoCollection l, SupportingTokenParameters s, bool required)193 		void CollectSupportingTokensCore (
194 			SupportingTokenInfoCollection l,
195 			SupportingTokenParameters s,
196 			bool required)
197 		{
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));
206 		}
207 
GetSigningToken(SecurityTokenParameters p)208 		SecurityToken GetSigningToken (SecurityTokenParameters p)
209 		{
210 			return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature);
211 		}
212 
GetExchangeToken(SecurityTokenParameters p)213 		SecurityToken GetExchangeToken (SecurityTokenParameters p)
214 		{
215 			return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange);
216 		}
217 
GetToken(SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)218 		public SecurityToken GetToken (SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)
219 		{
220 			requirement.KeyUsage = usage;
221 			requirement.Properties [ReqType.SecurityBindingElementProperty] = Element;
222 			requirement.Properties [ReqType.MessageSecurityVersionProperty] =
223 				Element.MessageSecurityVersion.SecurityTokenVersion;
224 
225 			InitializeRequirement (targetParams, requirement);
226 
227 			SecurityTokenProvider provider =
228 				CreateTokenProvider (requirement);
229 			ICommunicationObject obj = provider as ICommunicationObject;
230 			try {
231 				if (obj != null)
232 					obj.Open (Timeouts.OpenTimeout);
233 				return provider.GetToken (Timeouts.SendTimeout);
234 			} finally {
235 				if (obj != null && obj.State == CommunicationState.Opened)
236 					obj.Close ();
237 			}
238 		}
239 
CreateRequirement()240 		public abstract SecurityTokenRequirement CreateRequirement ();
241 	}
242 
243 	internal class InitiatorMessageSecurityBindingSupport : MessageSecurityBindingSupport
244 	{
245 		ChannelFactoryBase factory;
246 		EndpointAddress message_to;
247 		SecurityToken encryption_token;
248 		SecurityToken signing_token;
249 
InitiatorMessageSecurityBindingSupport( SecurityCapabilities elementSupport, SecurityTokenManager manager, ChannelProtectionRequirements requirements)250 		public InitiatorMessageSecurityBindingSupport (
251 			SecurityCapabilities elementSupport,
252 			SecurityTokenManager manager,
253 			ChannelProtectionRequirements requirements)
254 			: base (elementSupport, manager, requirements)
255 		{
256 		}
257 
258 		public override IDefaultCommunicationTimeouts Timeouts {
259 			get { return factory; }
260 		}
261 
Prepare(ChannelFactoryBase factory, EndpointAddress address)262 		public void Prepare (ChannelFactoryBase factory, EndpointAddress address)
263 		{
264 			this.factory = factory;
265 			this.message_to = address;
266 
267 			PrepareAuthenticator ();
268 
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");
273 		}
274 
275 		public override SecurityToken EncryptionToken {
276 			get {
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);
282 				}
283 				return encryption_token;
284 			}
285 		}
286 
287 		public override SecurityToken SigningToken {
288 			get {
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);
294 				}
295 				return signing_token;
296 			}
297 		}
298 
ReleaseCore()299 		protected override void ReleaseCore ()
300 		{
301 			this.factory = null;
302 			this.message_to = null;
303 
304 			IDisposable disposable = signing_token as IDisposable;
305 			if (disposable != null)
306 				disposable.Dispose ();
307 			signing_token = null;
308 
309 			disposable = encryption_token as IDisposable;
310 			if (disposable != null)
311 				disposable.Dispose ();
312 			encryption_token = null;
313 		}
314 
CreateRequirement()315 		public override SecurityTokenRequirement CreateRequirement ()
316 		{
317 			SecurityTokenRequirement r = new InitiatorServiceModelSecurityTokenRequirement ();
318 //			r.Properties [ReqType.IssuerAddressProperty] = message_to;
319 			r.Properties [ReqType.TargetAddressProperty] = message_to;
320 			// FIXME: set Via
321 			return r;
322 		}
323 
CreateTokenAuthenticator(SecurityTokenParameters p, out SecurityTokenResolver resolver)324 		public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
325 		{
326 			resolver = null;
327 			// This check might be almost extra, though it is
328 			// needed to check correct signing token existence.
329 			//
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)
334 				return null;
335 
336 			SecurityTokenRequirement r = CreateRequirement ();
337 			r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
338 			InitializeRequirement (p, r);
339 			return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
340 		}
341 	}
342 
343 	class RecipientMessageSecurityBindingSupport : MessageSecurityBindingSupport
344 	{
345 		ChannelListenerBase listener;
346 		Uri listen_uri;
347 		SecurityToken encryption_token;
348 		SecurityToken signing_token;
349 
RecipientMessageSecurityBindingSupport( SecurityCapabilities elementSupport, SecurityTokenManager manager, ChannelProtectionRequirements requirements)350 		public RecipientMessageSecurityBindingSupport (
351 			SecurityCapabilities elementSupport,
352 			SecurityTokenManager manager,
353 			ChannelProtectionRequirements requirements)
354 			: base (elementSupport, manager, requirements)
355 		{
356 		}
357 
358 		public override IDefaultCommunicationTimeouts Timeouts {
359 			get { return listener; }
360 		}
361 
362 		// FIXME: this is invoked inconsistently between SecurityReplyChannel and SecurityDuplexSessionChannel on when to do it.
Prepare(ChannelListenerBase listener, Uri listenUri)363 		public void Prepare (ChannelListenerBase listener, Uri listenUri)
364 		{
365 			this.listener = listener;
366 			this.listen_uri = listenUri;
367 
368 			PrepareAuthenticator ();
369 
370 			// This check is almost extra, though it is needed
371 			// to check correct signing token existence.
372 			//
373 			// Not sure if it is limited to this condition, but
374 			// Ssl parameters do not support token provider and
375 			// still do not fail. X509 parameters do fail.
376 			//
377 			// FIXME: as AsymmetricSecurityBindingElementTest
378 			// .ServiceRecipientHasNoKeys() implies, it should be
379 			// the recipient's parameters that is used. However
380 			// such changes will break some of existing tests...
381 			if (InitiatorParameters.InternalHasAsymmetricKey &&
382 			    EncryptionToken == null)
383 				throw new Exception ("INTERNAL ERROR");
384 		}
385 
386 		public override SecurityToken EncryptionToken {
387 			get {
388 				if (encryption_token == null) {
389 					SecurityTokenRequirement r = CreateRequirement ();
390 					r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
391 					encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
392 				}
393 				return encryption_token;
394 			}
395 		}
396 
397 		public override SecurityToken SigningToken {
398 			get {
399 				if (signing_token == null) {
400 					SecurityTokenRequirement r = CreateRequirement ();
401 					r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
402 					InitializeRequirement (RecipientParameters, r);
403 					signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature);
404 				}
405 				return signing_token;
406 			}
407 		}
408 
ReleaseCore()409 		protected override void ReleaseCore ()
410 		{
411 			this.listener = null;
412 
413 			IDisposable disposable = signing_token as IDisposable;
414 			if (disposable != null)
415 				disposable.Dispose ();
416 			signing_token = null;
417 
418 			disposable = encryption_token as IDisposable;
419 			if (disposable != null)
420 				disposable.Dispose ();
421 			encryption_token = null;
422 		}
423 
CreateRequirement()424 		public override SecurityTokenRequirement CreateRequirement ()
425 		{
426 			SecurityTokenRequirement requirement =
427 				new RecipientServiceModelSecurityTokenRequirement ();
428 			requirement.Properties [ReqType.ListenUriProperty] = listen_uri;
429 			return requirement;
430 		}
431 
CreateTokenAuthenticator(SecurityTokenParameters p, out SecurityTokenResolver resolver)432 		public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
433 		{
434 			resolver = null;
435 			// This check might be almost extra, though it is
436 			// needed to check correct signing token existence.
437 			//
438 			// Not sure if it is limited to this condition, but
439 			// Ssl parameters do not support token provider and
440 			// still do not fail. X509 parameters do fail.
441 			if (!RecipientParameters.InternalSupportsServerAuthentication)
442 				return null;
443 
444 			SecurityTokenRequirement r = CreateRequirement ();
445 			r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
446 			InitializeRequirement (p, r);
447 			return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
448 		}
449 	}
450 }
451