2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Security / ServiceCredentialsSecurityTokenManager.cs
blobc48944b472dc8ba9edd6be585cfb547976347a24
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.
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;
38 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
40 namespace System.ServiceModel.Security
42 public class ServiceCredentialsSecurityTokenManager : SecurityTokenManager, IEndpointIdentityProvider
44 ServiceCredentials credentials;
46 public ServiceCredentialsSecurityTokenManager (
47 ServiceCredentials credentials)
49 this.credentials = credentials;
52 public ServiceCredentials ServiceCredentials {
53 get { return credentials; }
56 [MonoTODO]
57 public virtual EndpointIdentity GetIdentityOfSelf (
58 SecurityTokenRequirement requirement)
60 throw new NotImplementedException ();
63 [MonoTODO]
64 public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator (
65 SecurityTokenRequirement requirement,
66 out SecurityTokenResolver outOfBandTokenResolver)
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 // FIXME: get parameters from somewhere
77 SecurityContextSecurityTokenResolver resolver =
78 new SecurityContextSecurityTokenResolver (0x1000, true);
79 outOfBandTokenResolver = resolver;
80 SecurityContextSecurityTokenAuthenticator sc =
81 new SecurityContextSecurityTokenAuthenticator ();
82 return new SecureConversationSecurityTokenAuthenticator (requirement, sc, resolver);
84 if (requirement.TokenType == ServiceModelSecurityTokenTypes.AnonymousSslnego)
85 return CreateSslTokenAuthenticator (requirement);
86 if (requirement.TokenType == ServiceModelSecurityTokenTypes.MutualSslnego)
87 return CreateSslTokenAuthenticator (requirement);
88 if (requirement.TokenType == ServiceModelSecurityTokenTypes.Spnego)
89 return CreateSpnegoTokenAuthenticator (requirement);
90 else
91 throw new NotImplementedException ("Not implemented token type: " + requirement.TokenType);
94 SpnegoSecurityTokenAuthenticator CreateSpnegoTokenAuthenticator (SecurityTokenRequirement requirement)
96 SpnegoSecurityTokenAuthenticator a =
97 new SpnegoSecurityTokenAuthenticator (this, requirement);
98 InitializeAuthenticatorCommunicationObject (a.Communication, requirement);
99 return a;
102 SslSecurityTokenAuthenticator CreateSslTokenAuthenticator (SecurityTokenRequirement requirement)
104 SslSecurityTokenAuthenticator a =
105 new SslSecurityTokenAuthenticator (this, requirement);
106 InitializeAuthenticatorCommunicationObject (a.Communication, requirement);
107 return a;
110 UserNameSecurityTokenAuthenticator CreateUserNameAuthenticator (SecurityTokenRequirement requirement)
112 UserNamePasswordServiceCredential c = ServiceCredentials.UserNameAuthentication;
113 switch (c.UserNamePasswordValidationMode) {
114 case UserNamePasswordValidationMode.MembershipProvider:
115 if (c.MembershipProvider == null)
116 throw new InvalidOperationException ("For MembershipProvider validation mode, MembershipProvider is required to create a user name token authenticator.");
117 return new CustomUserNameSecurityTokenAuthenticator (UserNamePasswordValidator.CreateMembershipProviderValidator (c.MembershipProvider));
118 case UserNamePasswordValidationMode.Windows:
119 return new WindowsUserNameSecurityTokenAuthenticator (c.IncludeWindowsGroups);
120 default:
121 if (c.CustomUserNamePasswordValidator == null)
122 throw new InvalidOperationException ("For Custom validation mode, CustomUserNamePasswordValidator is required to create a user name token authenticator.");
123 return new CustomUserNameSecurityTokenAuthenticator (c.CustomUserNamePasswordValidator);
127 X509SecurityTokenAuthenticator CreateX509Authenticator (SecurityTokenRequirement requirement)
129 X509CertificateInitiatorServiceCredential c = ServiceCredentials.ClientCertificate;
130 switch (c.Authentication.CertificateValidationMode) {
131 case X509CertificateValidationMode.Custom:
132 if (c.Authentication.CustomCertificateValidator == null)
133 throw new InvalidOperationException ("For Custom certificate validation mode, CustomCertificateValidator is required to create a token authenticator for X509 certificate.");
134 return new X509SecurityTokenAuthenticator (c.Authentication.CustomCertificateValidator);
135 case X509CertificateValidationMode.None:
136 return new X509SecurityTokenAuthenticator (X509CertificateValidator.None);
137 case X509CertificateValidationMode.PeerOrChainTrust:
138 return new X509SecurityTokenAuthenticator (X509CertificateValidator.PeerOrChainTrust);
139 case X509CertificateValidationMode.ChainTrust:
140 return new X509SecurityTokenAuthenticator (X509CertificateValidator.ChainTrust);
141 default:
142 return new X509SecurityTokenAuthenticator (X509CertificateValidator.PeerTrust);
146 void InitializeAuthenticatorCommunicationObject (AuthenticatorCommunicationObject p, SecurityTokenRequirement r)
148 p.ListenUri = r.GetProperty<Uri> (ReqType.ListenUriProperty);
150 // FIXME: use it somewhere, probably to build
151 // IssuerBinding. However, there is also IssuerBinding
152 // property. SecureConversationSecurityBindingElement
153 // as well.
154 SecurityBindingElement sbe =
155 r.GetProperty<SecurityBindingElement> (ReqType.SecurityBindingElementProperty);
156 p.SecurityBindingElement = sbe;
159 // I doubt the binding is acquired this way ...
160 Binding binding;
161 if (!r.TryGetProperty<Binding> (ReqType.IssuerBindingProperty, out binding))
162 binding = new CustomBinding (
163 new TextMessageEncodingBindingElement (),
164 new HttpTransportBindingElement ());
165 p.IssuerBinding = binding;
167 // not sure if it is used only for this purpose though ...
168 BindingContext ctx = r.GetProperty<BindingContext> (ReqType.IssuerBindingContextProperty);
169 foreach (IEndpointBehavior b in ctx.BindingParameters.FindAll<IEndpointBehavior> ())
170 p.IssuerChannelBehaviors.Add (b);
173 SecurityTokenVersion ver =
174 r.GetProperty<SecurityTokenVersion> (ReqType.MessageSecurityVersionProperty);
175 p.SecurityTokenSerializer =
176 CreateSecurityTokenSerializer (ver);
179 // seems like they are optional here ... (but possibly
180 // used later)
181 EndpointAddress address;
182 if (!r.TryGetProperty<EndpointAddress> (ReqType.IssuerAddressProperty, out address))
183 address = p.TargetAddress;
184 p.IssuerAddress = address;
187 // It is somehow not checked as mandatory ...
188 SecurityAlgorithmSuite suite = null;
189 r.TryGetProperty<SecurityAlgorithmSuite> (ReqType.SecurityAlgorithmSuiteProperty, out suite);
190 p.SecurityAlgorithmSuite = suite;
193 #region CreateSecurityTokenProvider()
195 [MonoTODO]
196 public override SecurityTokenProvider CreateSecurityTokenProvider (SecurityTokenRequirement requirement)
198 if (IsIssuedSecurityTokenRequirement (requirement))
199 return CreateIssuedTokenProvider (requirement);
201 // not supported: UserName, Rsa, AnonymousSslnego, SecureConv
203 // huh, they are not constants but properties.
204 if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
205 return CreateX509SecurityTokenProvider (requirement);
206 else if (requirement.TokenType == ServiceModelSecurityTokenTypes.MutualSslnego) {
207 // FIXME: implement
208 throw new NotImplementedException ();
209 } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.SecurityContext) {
210 // FIXME: implement
211 throw new NotImplementedException ();
212 } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.AnonymousSslnego) {
213 throw new NotSupportedException (String.Format ("Token type '{0}' is not supported", requirement.TokenType));
214 } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.Spnego) {
215 // FIXME: implement
216 throw new NotImplementedException ();
217 } else if (requirement.TokenType == ServiceModelSecurityTokenTypes.SspiCredential) {
218 // FIXME: implement
219 throw new NotImplementedException ();
220 } else if (requirement.TokenType == SecurityTokenTypes.Saml) {
221 // FIXME: implement
222 throw new NotImplementedException ();
223 } else if (requirement.TokenType == SecurityTokenTypes.Kerberos) {
224 // FIXME: implement
225 throw new NotImplementedException ();
227 throw new NotSupportedException (String.Format ("Securirty token requirement '{0}' is not supported", requirement));
230 X509SecurityTokenProvider CreateX509SecurityTokenProvider (SecurityTokenRequirement requirement)
232 bool isInitiator;
233 requirement.TryGetProperty<bool> (ReqType.IsInitiatorProperty, out isInitiator);
234 // when it is initiator, then it is for MutualCertificateDuplex.
235 X509Certificate2 cert;
236 if (isInitiator) {
237 cert = credentials.ClientCertificate.Certificate;
238 if (cert == null)
239 throw new InvalidOperationException ("Client certificate is not provided in ServiceCredentials.");
240 if (cert.PrivateKey == null)
241 throw new ArgumentException ("Client certificate for MutualCertificateDuplex does not have a private key which is required for key exchange.");
242 } else {
243 cert = credentials.ServiceCertificate.Certificate;
244 if (cert == null)
245 throw new InvalidOperationException ("Service certificate is not provided in ServiceCredentials.");
246 if (cert.PrivateKey == null)
247 throw new ArgumentException ("Service certificate does not have a private key which is required for key exchange.");
249 X509SecurityTokenProvider p =
250 new X509SecurityTokenProvider (cert);
251 return p;
254 IssuedSecurityTokenProvider CreateIssuedProviderBase (SecurityTokenRequirement r)
256 IssuedSecurityTokenProvider p =
257 new IssuedSecurityTokenProvider ();
259 p.TargetAddress = r.GetProperty<EndpointAddress> (ReqType.TargetAddressProperty);
261 // FIXME: use it somewhere, probably to build
262 // IssuerBinding. However, there is also IssuerBinding
263 // property. SecureConversationSecurityBindingElement
264 // as well.
265 SecurityBindingElement sbe =
266 r.GetProperty<SecurityBindingElement> (ReqType.SecurityBindingElementProperty);
268 // I doubt the binding is acquired this way ...
269 Binding binding;
270 if (!r.TryGetProperty<Binding> (ReqType.IssuerBindingProperty, out binding))
271 binding = new CustomBinding (sbe,
272 new TextMessageEncodingBindingElement (),
273 new HttpTransportBindingElement ());
274 p.IssuerBinding = binding;
276 // not sure if it is used only for this purpose though ...
277 BindingContext ctx = r.GetProperty<BindingContext> (ReqType.IssuerBindingContextProperty);
278 foreach (IEndpointBehavior b in ctx.BindingParameters.FindAll<IEndpointBehavior> ())
279 p.IssuerChannelBehaviors.Add (b);
281 SecurityTokenVersion ver =
282 r.GetProperty<SecurityTokenVersion> (ReqType.MessageSecurityVersionProperty);
283 p.SecurityTokenSerializer =
284 CreateSecurityTokenSerializer (ver);
286 // seems like they are optional here ... (but possibly
287 // used later)
288 EndpointAddress address;
289 if (!r.TryGetProperty<EndpointAddress> (ReqType.IssuerAddressProperty, out address))
290 address = p.TargetAddress;
291 p.IssuerAddress = address;
293 // It is somehow not checked as mandatory ...
294 SecurityAlgorithmSuite suite = null;
295 r.TryGetProperty<SecurityAlgorithmSuite> (ReqType.SecurityAlgorithmSuiteProperty, out suite);
296 p.SecurityAlgorithmSuite = suite;
298 return p;
301 // FIXME: it is far from done.
302 SecurityTokenProvider CreateSecureConversationProvider (SecurityTokenRequirement r)
304 IssuedSecurityTokenProvider p =
305 CreateIssuedProviderBase (r);
307 // FIXME: use it somewhere.
308 int keySize = r.KeySize;
310 return p;
313 IssuedSecurityTokenProvider CreateIssuedTokenProvider (SecurityTokenRequirement requirement)
315 IssuedSecurityTokenProvider p =
316 new IssuedSecurityTokenProvider ();
317 // FIXME: fill properties
318 EndpointAddress address;
319 if (requirement.TryGetProperty<EndpointAddress> (ReqType.IssuerAddressProperty, out address))
320 p.IssuerAddress = address;
321 if (requirement.TryGetProperty<EndpointAddress> (ReqType.TargetAddressProperty, out address))
322 p.TargetAddress = address;
323 Binding binding;
324 if (requirement.TryGetProperty<Binding> (ReqType.IssuerBindingProperty, out binding))
325 p.IssuerBinding = binding;
326 MessageSecurityVersion ver;
327 if (requirement.TryGetProperty<MessageSecurityVersion> (ReqType.MessageSecurityVersionProperty, out ver))
328 p.SecurityTokenSerializer = CreateSecurityTokenSerializer (ver.SecurityTokenVersion);
329 SecurityAlgorithmSuite suite;
330 if (requirement.TryGetProperty<SecurityAlgorithmSuite> (ReqType.SecurityAlgorithmSuiteProperty, out suite))
331 p.SecurityAlgorithmSuite = suite;
332 return p;
335 #endregion
337 [MonoTODO ("pass correct arguments to WSSecurityTokenSerializer..ctor()")]
338 public override SecurityTokenSerializer CreateSecurityTokenSerializer (SecurityTokenVersion version)
340 bool bsp = version.GetSecuritySpecifications ().Contains (Constants.WSBasicSecurityProfileCore1);
341 SecurityVersion ver =
342 version.GetSecuritySpecifications ().Contains (Constants.Wss11Namespace) ?
343 SecurityVersion.WSSecurity11 :
344 SecurityVersion.WSSecurity10;
346 // FIXME: pass correct arguments.
347 return new WSSecurityTokenSerializer (ver, bsp, null,
348 ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder,
349 Type.EmptyTypes,
350 int.MaxValue, int.MaxValue, int.MaxValue);
353 protected internal bool IsIssuedSecurityTokenRequirement (
354 SecurityTokenRequirement requirement)
356 SecurityTokenParameters ret;
357 if (!requirement.TryGetProperty<SecurityTokenParameters> (ServiceModelSecurityTokenRequirement.IssuedSecurityTokenParametersProperty, out ret))
358 return false;
359 return ret is IssuedSecurityTokenParameters;