more internal namespace moving.
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / MessageSecurityBindingSupport.cs
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
54                 protected MessageSecurityBindingSupport (
55                         SecurityCapabilities elementSupport,
56                         SecurityTokenManager manager,
57                         ChannelProtectionRequirements requirements)
58                 {
59                         element_support = elementSupport;
60                         Initialize (manager, requirements);
61                 }
62
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
138                 public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement)
139                 {
140                         return manager.CreateSecurityTokenProvider (requirement);
141                 }
142
143                 public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver);
144
145                 protected void PrepareAuthenticator ()
146                 {
147                         authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver);
148                 }
149
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
167                 public void Release ()
168                 {
169                         ReleaseCore ();
170
171                         authenticator = null;
172                 }
173
174                 protected abstract void ReleaseCore ();
175
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
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
208                 SecurityToken GetSigningToken (SecurityTokenParameters p)
209                 {
210                         return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature);
211                 }
212
213                 SecurityToken GetExchangeToken (SecurityTokenParameters p)
214                 {
215                         return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange);
216                 }
217
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                 
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
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
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
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
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
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                 SecurityToken encryption_token;
347                 SecurityToken signing_token;
348
349                 public RecipientMessageSecurityBindingSupport (
350                         SecurityCapabilities elementSupport,
351                         SecurityTokenManager manager,
352                         ChannelProtectionRequirements requirements)
353                         : base (elementSupport, manager, requirements)
354                 {
355                 }
356
357                 public override IDefaultCommunicationTimeouts Timeouts {
358                         get { return listener; }
359                 }
360
361                 public void Prepare (ChannelListenerBase listener)
362                 {
363                         this.listener = listener;
364
365                         PrepareAuthenticator ();
366
367                         // This check is almost extra, though it is needed
368                         // to check correct signing token existence.
369                         //
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.
373                         //
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");
381                 }
382
383                 public override SecurityToken EncryptionToken {
384                         get {
385                                 if (encryption_token == null) {
386                                         SecurityTokenRequirement r = CreateRequirement ();
387                                         r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
388                                         encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
389                                 }
390                                 return encryption_token;
391                         }
392                 }
393
394                 public override SecurityToken SigningToken {
395                         get {
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);
401                                 }
402                                 return signing_token;
403                         }
404                 }
405
406                 protected override void ReleaseCore ()
407                 {
408                         this.listener = null;
409
410                         IDisposable disposable = signing_token as IDisposable;
411                         if (disposable != null)
412                                 disposable.Dispose ();
413                         signing_token = null;
414
415                         disposable = encryption_token as IDisposable;
416                         if (disposable != null)
417                                 disposable.Dispose ();
418                         encryption_token = null;
419                 }
420
421                 public override SecurityTokenRequirement CreateRequirement ()
422                 {
423                         SecurityTokenRequirement requirement =
424                                 new RecipientServiceModelSecurityTokenRequirement ();
425                         requirement.Properties [ReqType.ListenUriProperty] = listener.Uri;
426                         return requirement;
427                 }
428
429                 public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
430                 {
431                         resolver = null;
432                         // This check might be almost extra, though it is
433                         // needed to check correct signing token existence.
434                         //
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)
439                                 return null;
440
441                         SecurityTokenRequirement r = CreateRequirement ();
442                         r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
443                         InitializeRequirement (p, r);
444                         return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
445                 }
446         }
447 }