2 // ServiceCredentialsSecurityTokenManager.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2006 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.
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; }
57 public virtual EndpointIdentity
GetIdentityOfSelf (
58 SecurityTokenRequirement requirement
)
60 throw new NotImplementedException ();
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
);
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
);
102 SslSecurityTokenAuthenticator
CreateSslTokenAuthenticator (SecurityTokenRequirement requirement
)
104 SslSecurityTokenAuthenticator a
=
105 new SslSecurityTokenAuthenticator (this, requirement
);
106 InitializeAuthenticatorCommunicationObject (a
.Communication
, requirement
);
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
);
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
);
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
154 SecurityBindingElement sbe
=
155 r
.GetProperty
<SecurityBindingElement
> (ReqType
.SecurityBindingElementProperty
);
156 p
.SecurityBindingElement
= sbe
;
159 // I doubt the binding is acquired this way ...
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
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()
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
) {
208 throw new NotImplementedException ();
209 } else if (requirement
.TokenType
== ServiceModelSecurityTokenTypes
.SecurityContext
) {
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
) {
216 throw new NotImplementedException ();
217 } else if (requirement
.TokenType
== ServiceModelSecurityTokenTypes
.SspiCredential
) {
219 throw new NotImplementedException ();
220 } else if (requirement
.TokenType
== SecurityTokenTypes
.Saml
) {
222 throw new NotImplementedException ();
223 } else if (requirement
.TokenType
== SecurityTokenTypes
.Kerberos
) {
225 throw new NotImplementedException ();
227 throw new NotSupportedException (String
.Format ("Securirty token requirement '{0}' is not supported", requirement
));
230 X509SecurityTokenProvider
CreateX509SecurityTokenProvider (SecurityTokenRequirement requirement
)
233 requirement
.TryGetProperty
<bool> (ReqType
.IsInitiatorProperty
, out isInitiator
);
234 // when it is initiator, then it is for MutualCertificateDuplex.
235 X509Certificate2 cert
;
237 cert
= credentials
.ClientCertificate
.Certificate
;
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.");
243 cert
= credentials
.ServiceCertificate
.Certificate
;
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
);
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
265 SecurityBindingElement sbe
=
266 r
.GetProperty
<SecurityBindingElement
> (ReqType
.SecurityBindingElementProperty
);
268 // I doubt the binding is acquired this way ...
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
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
;
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
;
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
;
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
;
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
,
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
))
359 return ret
is IssuedSecurityTokenParameters
;