[tests] Separate MONO_PATH directories by PLATFORM_PATH_SEPARATOR
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Security / ServiceCredentialsSecurityTokenManager.cs
1 //
2 // ServiceCredentialsSecurityTokenManager.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 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;
29 using System.Net.Security;
30 using System.IdentityModel.Selectors;
31 using System.IdentityModel.Tokens;
32 using System.Security.Cryptography.X509Certificates;
33 using System.ServiceModel;
34 using System.ServiceModel.Channels;
35 using System.ServiceModel.Description;
36 using System.ServiceModel.Security.Tokens;
37
38 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
39
40 namespace System.ServiceModel.Security
41 {
42         public class ServiceCredentialsSecurityTokenManager : SecurityTokenManager, IEndpointIdentityProvider
43         {
44                 ServiceCredentials credentials;
45
46                 public ServiceCredentialsSecurityTokenManager (
47                         ServiceCredentials credentials)
48                 {
49                         this.credentials = credentials;
50                 }
51
52                 public ServiceCredentials ServiceCredentials {
53                         get { return credentials; }
54                 }
55
56                 [MonoTODO]
57                 public virtual EndpointIdentity GetIdentityOfSelf (
58                         SecurityTokenRequirement requirement)
59                 {
60                         throw new NotImplementedException ();
61                 }
62
63                 [MonoTODO]
64                 public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator (
65                         SecurityTokenRequirement requirement,
66                         out SecurityTokenResolver outOfBandTokenResolver)
67                 {
68                         outOfBandTokenResolver = null;
69                         if (requirement.TokenType == SecurityTokenTypes.UserName)
70                                 return CreateUserNameAuthenticator (requirement);
71                         if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
72                                 return CreateX509Authenticator (requirement);
73                         if (requirement.TokenType == SecurityTokenTypes.Rsa)
74                                 return new RsaSecurityTokenAuthenticator ();
75                         if (requirement.TokenType == ServiceModelSecurityTokenTypes.SecureConversation) {
76                                 SecurityBindingElement binding;
77                                 if (!requirement.TryGetProperty<SecurityBindingElement> (ReqType.SecurityBindingElementProperty, out binding))
78                                         throw new ArgumentException ("SecurityBindingElement is required in the security token requirement");
79                                 SecureConversationSecurityTokenParameters issuedParams;
80                                 if (!requirement.TryGetProperty<SecureConversationSecurityTokenParameters> (ReqType.IssuedSecurityTokenParametersProperty, out issuedParams))
81                                         throw new ArgumentException ("IssuedSecurityTokenParameters are required in the security token requirement");
82                                 BindingContext issuerBC;
83                                 if (!requirement.TryGetProperty<BindingContext> (ReqType.IssuerBindingContextProperty, out issuerBC))
84                                         throw new ArgumentException ("IssuerBindingContext is required in the security token requirement");
85                                 SecurityTokenVersion secVer;
86                                 if (!requirement.TryGetProperty<SecurityTokenVersion> (ReqType.MessageSecurityVersionProperty, out secVer))
87                                         throw new ArgumentException ("MessageSecurityVersion property (of type SecurityTokenVersion) is required in the security token requirement");
88
89                                 // FIXME: get parameters from somewhere
90                                 SecurityContextSecurityTokenResolver resolver =
91                                         new SecurityContextSecurityTokenResolver (0x1000, true);
92                                 outOfBandTokenResolver = resolver;
93                                 SecurityContextSecurityTokenAuthenticator sc =
94                                         new SecurityContextSecurityTokenAuthenticator ();
95                                 return new SecureConversationSecurityTokenAuthenticator (requirement, sc, resolver);
96                         }
97                         if (requirement.TokenType == ServiceModelSecurityTokenTypes.AnonymousSslnego)
98                                 return CreateSslTokenAuthenticator (requirement);
99                         if (requirement.TokenType == ServiceModelSecurityTokenTypes.MutualSslnego)
100                                 return CreateSslTokenAuthenticator (requirement);
101                         if (requirement.TokenType == ServiceModelSecurityTokenTypes.Spnego)
102                                 return CreateSpnegoTokenAuthenticator (requirement);
103                         else
104                                 throw new NotImplementedException ("Not implemented token type: " + requirement.TokenType);
105                 }
106
107                 SpnegoSecurityTokenAuthenticator CreateSpnegoTokenAuthenticator (SecurityTokenRequirement requirement)
108                 {
109                         SpnegoSecurityTokenAuthenticator a =
110                                 new SpnegoSecurityTokenAuthenticator (this, requirement);
111                         InitializeAuthenticatorCommunicationObject (a.Communication, requirement);
112                         return a;
113                 }
114
115                 SslSecurityTokenAuthenticator CreateSslTokenAuthenticator (SecurityTokenRequirement requirement)
116                 {
117                         SslSecurityTokenAuthenticator a =
118                                 new SslSecurityTokenAuthenticator (this, requirement);
119                         InitializeAuthenticatorCommunicationObject (a.Communication, requirement);
120                         return a;
121                 }
122
123                 UserNameSecurityTokenAuthenticator CreateUserNameAuthenticator (SecurityTokenRequirement requirement)
124                 {
125                         UserNamePasswordServiceCredential c = ServiceCredentials.UserNameAuthentication;
126                         switch (c.UserNamePasswordValidationMode) {
127                         case UserNamePasswordValidationMode.MembershipProvider:
128                                 if (c.MembershipProvider == null)
129                                         throw new InvalidOperationException ("For MembershipProvider validation mode, MembershipProvider is required to create a user name token authenticator.");
130                                 return new CustomUserNameSecurityTokenAuthenticator (UserNamePasswordValidator.CreateMembershipProviderValidator (c.MembershipProvider));
131                         case UserNamePasswordValidationMode.Windows:
132                                 return new WindowsUserNameSecurityTokenAuthenticator (c.IncludeWindowsGroups);
133                         default:
134                                 if (c.CustomUserNamePasswordValidator == null)
135                                         throw new InvalidOperationException ("For Custom validation mode, CustomUserNamePasswordValidator is required to create a user name token authenticator.");
136                                 return new CustomUserNameSecurityTokenAuthenticator (c.CustomUserNamePasswordValidator);
137                         }
138                 }
139
140                 X509SecurityTokenAuthenticator CreateX509Authenticator (SecurityTokenRequirement requirement)
141                 {
142                         X509CertificateInitiatorServiceCredential c = ServiceCredentials.ClientCertificate;
143                         switch (c.Authentication.CertificateValidationMode) {
144                         case X509CertificateValidationMode.Custom:
145                                 if (c.Authentication.CustomCertificateValidator == null)
146                                         throw new InvalidOperationException ("For Custom certificate validation mode, CustomCertificateValidator is required to create a token authenticator for X509 certificate.");
147                                 return new X509SecurityTokenAuthenticator (c.Authentication.CustomCertificateValidator);
148                         case X509CertificateValidationMode.None:
149                                 return new X509SecurityTokenAuthenticator (X509CertificateValidator.None);
150                         case X509CertificateValidationMode.PeerOrChainTrust:
151                                 return new X509SecurityTokenAuthenticator (X509CertificateValidator.PeerOrChainTrust);
152                         case X509CertificateValidationMode.ChainTrust:
153                                 return new X509SecurityTokenAuthenticator (X509CertificateValidator.ChainTrust);
154                         default:
155                                 return new X509SecurityTokenAuthenticator (X509CertificateValidator.PeerTrust);
156                         }
157                 }
158
159                 void InitializeAuthenticatorCommunicationObject (AuthenticatorCommunicationObject p, SecurityTokenRequirement r)
160                 {
161                         p.ListenUri = r.GetProperty<Uri> (ReqType.ListenUriProperty);
162
163                         // FIXME: use it somewhere, probably to build 
164                         // IssuerBinding. However, there is also IssuerBinding 
165                         // property. SecureConversationSecurityBindingElement
166                         // as well.
167                         SecurityBindingElement sbe =
168                                 r.GetProperty<SecurityBindingElement> (ReqType.SecurityBindingElementProperty);
169                         p.SecurityBindingElement = sbe;
170
171 /*
172                         // I doubt the binding is acquired this way ...
173                         Binding binding;
174                         if (!r.TryGetProperty<Binding> (ReqType.IssuerBindingProperty, out binding))
175                                 binding = new CustomBinding (
176                                         new TextMessageEncodingBindingElement (),
177                                         new HttpTransportBindingElement ());
178                         p.IssuerBinding = binding;
179
180                         // not sure if it is used only for this purpose though ...
181                         BindingContext ctx = r.GetProperty<BindingContext> (ReqType.IssuerBindingContextProperty);
182                         foreach (IEndpointBehavior b in ctx.BindingParameters.FindAll<IEndpointBehavior> ())
183                                 p.IssuerChannelBehaviors.Add (b);
184 */
185
186                         SecurityTokenVersion ver =
187                                 r.GetProperty<SecurityTokenVersion> (ReqType.MessageSecurityVersionProperty);
188                         p.SecurityTokenSerializer =
189                                 CreateSecurityTokenSerializer (ver);
190
191 /*
192                         // seems like they are optional here ... (but possibly
193                         // used later)
194                         EndpointAddress address;
195                         if (!r.TryGetProperty<EndpointAddress> (ReqType.IssuerAddressProperty, out address))
196                                 address = p.TargetAddress;
197                         p.IssuerAddress = address;
198 */
199
200                         // It is somehow not checked as mandatory ...
201                         SecurityAlgorithmSuite suite = null;
202                         r.TryGetProperty<SecurityAlgorithmSuite> (ReqType.SecurityAlgorithmSuiteProperty, out suite);
203                         p.SecurityAlgorithmSuite = suite;
204                 }
205
206                 #region CreateSecurityTokenProvider()
207
208                 [MonoTODO]
209                 public override SecurityTokenProvider CreateSecurityTokenProvider (SecurityTokenRequirement requirement)
210                 {
211                         if (IsIssuedSecurityTokenRequirement (requirement))
212                                 return CreateIssuedTokenProvider (requirement);
213
214                         // not supported: UserName, Rsa, AnonymousSslnego, SecureConv
215
216                         // huh, they are not constants but properties.
217                         if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
218                                 return CreateX509SecurityTokenProvider (requirement);
219                         else if (requirement.TokenType == ServiceModelSecurityTokenTypes.MutualSslnego) {
220                                 // FIXME: implement
221                                 throw new NotImplementedException ();
222                         } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.SecurityContext) {
223                                 // FIXME: implement
224                                 throw new NotImplementedException ();
225                         } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.AnonymousSslnego) {
226                                 throw new NotSupportedException (String.Format ("Token type '{0}' is not supported", requirement.TokenType));
227                         } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.Spnego) {
228                                 // FIXME: implement
229                                 throw new NotImplementedException ();
230                         } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.SspiCredential) {
231                                 // FIXME: implement
232                                 throw new NotImplementedException ();
233                         } else if (requirement.TokenType == SecurityTokenTypes.Saml) {
234                                 // FIXME: implement
235                                 throw new NotImplementedException ();
236                         } else if (requirement.TokenType == SecurityTokenTypes.Kerberos) {
237                                 // FIXME: implement
238                                 throw new NotImplementedException ();
239                         }
240                         throw new NotSupportedException (String.Format ("Securirty token requirement '{0}' is not supported", requirement));
241                 }
242
243                 X509SecurityTokenProvider CreateX509SecurityTokenProvider (SecurityTokenRequirement requirement)
244                 {
245                         bool isInitiator;
246                         requirement.TryGetProperty<bool> (ReqType.IsInitiatorProperty, out isInitiator);
247                         // when it is initiator, then it is for MutualCertificateDuplex.
248                         X509Certificate2 cert;
249                         if (isInitiator) {
250                                 cert = credentials.ClientCertificate.Certificate;
251                                 if (cert == null)
252                                         throw new InvalidOperationException ("Client certificate is not provided in ServiceCredentials.");
253                                 if (cert.PrivateKey == null)
254                                         throw new ArgumentException ("Client certificate for MutualCertificateDuplex does not have a private key which is required for key exchange.");
255                         } else {
256                                 cert = credentials.ServiceCertificate.Certificate;
257                                 if (cert == null)
258                                         throw new InvalidOperationException ("Service certificate is not provided in ServiceCredentials.");
259                                 if (cert.PrivateKey == null)
260                                         throw new ArgumentException ("Service certificate does not have a private key which is required for key exchange.");
261                         }
262                         X509SecurityTokenProvider p =
263                                 new X509SecurityTokenProvider (cert);
264                         return p;
265                 }
266
267                 IssuedSecurityTokenProvider CreateIssuedProviderBase (SecurityTokenRequirement r)
268                 {
269                         IssuedSecurityTokenProvider p =
270                                 new IssuedSecurityTokenProvider ();
271
272                         p.TargetAddress = r.GetProperty<EndpointAddress> (ReqType.TargetAddressProperty);
273
274                         // FIXME: use it somewhere, probably to build 
275                         // IssuerBinding. However, there is also IssuerBinding 
276                         // property. SecureConversationSecurityBindingElement
277                         // as well.
278                         SecurityBindingElement sbe =
279                                 r.GetProperty<SecurityBindingElement> (ReqType.SecurityBindingElementProperty);
280
281                         // I doubt the binding is acquired this way ...
282                         Binding binding;
283                         if (!r.TryGetProperty<Binding> (ReqType.IssuerBindingProperty, out binding))
284                                 binding = new CustomBinding (sbe,
285                                         new TextMessageEncodingBindingElement (),
286                                         new HttpTransportBindingElement ());
287                         p.IssuerBinding = binding;
288
289                         // not sure if it is used only for this purpose though ...
290                         BindingContext ctx = r.GetProperty<BindingContext> (ReqType.IssuerBindingContextProperty);
291                         foreach (IEndpointBehavior b in ctx.BindingParameters.FindAll<IEndpointBehavior> ())
292                                 p.IssuerChannelBehaviors.Add (b);
293
294                         SecurityTokenVersion ver =
295                                 r.GetProperty<SecurityTokenVersion> (ReqType.MessageSecurityVersionProperty);
296                         p.SecurityTokenSerializer =
297                                 CreateSecurityTokenSerializer (ver);
298
299                         // seems like they are optional here ... (but possibly
300                         // used later)
301                         EndpointAddress address;
302                         if (!r.TryGetProperty<EndpointAddress> (ReqType.IssuerAddressProperty, out address))
303                                 address = p.TargetAddress;
304                         p.IssuerAddress = address;
305
306                         // It is somehow not checked as mandatory ...
307                         SecurityAlgorithmSuite suite = null;
308                         r.TryGetProperty<SecurityAlgorithmSuite> (ReqType.SecurityAlgorithmSuiteProperty, out suite);
309                         p.SecurityAlgorithmSuite = suite;
310
311                         return p;
312                 }
313
314                 // FIXME: it is far from done.
315                 SecurityTokenProvider CreateSecureConversationProvider (SecurityTokenRequirement r)
316                 {
317                         IssuedSecurityTokenProvider p =
318                                 CreateIssuedProviderBase (r);
319
320                         // FIXME: use it somewhere.
321                         int keySize = r.KeySize;
322
323                         return p;
324                 }
325
326                 IssuedSecurityTokenProvider CreateIssuedTokenProvider (SecurityTokenRequirement requirement)
327                 {
328                         IssuedSecurityTokenProvider p =
329                                 new IssuedSecurityTokenProvider ();
330                         // FIXME: fill properties
331                         EndpointAddress address;
332                         if (requirement.TryGetProperty<EndpointAddress> (ReqType.IssuerAddressProperty, out address))
333                                 p.IssuerAddress = address;
334                         if (requirement.TryGetProperty<EndpointAddress> (ReqType.TargetAddressProperty, out address))
335                                 p.TargetAddress = address;
336                         Binding binding;
337                         if (requirement.TryGetProperty<Binding> (ReqType.IssuerBindingProperty, out binding))
338                                 p.IssuerBinding = binding;
339                         MessageSecurityVersion ver;
340                         if (requirement.TryGetProperty<MessageSecurityVersion> (ReqType.MessageSecurityVersionProperty, out ver))
341                                 p.SecurityTokenSerializer = CreateSecurityTokenSerializer (ver.SecurityTokenVersion);
342                         SecurityAlgorithmSuite suite;
343                         if (requirement.TryGetProperty<SecurityAlgorithmSuite> (ReqType.SecurityAlgorithmSuiteProperty, out suite))
344                                 p.SecurityAlgorithmSuite = suite;
345                         return p;
346                 }
347
348                 #endregion
349
350                 [MonoTODO ("pass correct arguments to WSSecurityTokenSerializer..ctor()")]
351                 public override SecurityTokenSerializer CreateSecurityTokenSerializer (SecurityTokenVersion version)
352                 {
353                         bool bsp = version.GetSecuritySpecifications ().Contains (Constants.WSBasicSecurityProfileCore1);
354                         SecurityVersion ver =
355                                 version.GetSecuritySpecifications ().Contains (Constants.Wss11Namespace) ?
356                                 SecurityVersion.WSSecurity11 :
357                                 SecurityVersion.WSSecurity10;
358
359                         // FIXME: pass correct arguments.
360                         return new WSSecurityTokenSerializer (ver, bsp, null,
361                                 ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder,
362                                 Type.EmptyTypes,
363                                 int.MaxValue, int.MaxValue, int.MaxValue);
364                 }
365
366                 protected internal bool IsIssuedSecurityTokenRequirement (
367                         SecurityTokenRequirement requirement)
368                 {
369                         SecurityTokenParameters ret;
370                         if (!requirement.TryGetProperty<SecurityTokenParameters> (ServiceModelSecurityTokenRequirement.IssuedSecurityTokenParametersProperty, out ret))
371                                 return false;
372                         return ret is IssuedSecurityTokenParameters;
373                 }
374         }
375 }