| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System;
- using System.Collections.ObjectModel;
- using System.IdentityModel.Policy;
- using System.IdentityModel.Selectors;
- using System.IdentityModel.Tokens;
- using System.Runtime;
- using System.Security.Cryptography.X509Certificates;
- using System.Security.Principal;
- using System.ServiceModel;
- using System.Xml;
- using SchProtocols = System.IdentityModel.SchProtocols;
- sealed class TlsnegoTokenAuthenticator : SspiNegotiationTokenAuthenticator
- {
- SecurityTokenAuthenticator clientTokenAuthenticator;
- SecurityTokenProvider serverTokenProvider;
- X509SecurityToken serverToken;
- bool mapCertificateToWindowsAccount;
- public TlsnegoTokenAuthenticator()
- : base()
- {
- // empty
- }
- public SecurityTokenAuthenticator ClientTokenAuthenticator
- {
- get
- {
- return this.clientTokenAuthenticator;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.clientTokenAuthenticator = value;
- }
- }
- public SecurityTokenProvider ServerTokenProvider
- {
- get
- {
- return this.serverTokenProvider;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.serverTokenProvider = value;
- }
- }
- public bool MapCertificateToWindowsAccount
- {
- get
- {
- return this.mapCertificateToWindowsAccount;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.mapCertificateToWindowsAccount = value;
- }
- }
- X509SecurityToken ValidateX509Token(SecurityToken token)
- {
- X509SecurityToken result = token as X509SecurityToken;
- if (result == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TokenProviderReturnedBadToken, token == null ? "<null>" : token.GetType().ToString())));
- }
- SecurityUtils.EnsureCertificateCanDoKeyExchange(result.Certificate);
- return result;
- }
- // overrides
- public override XmlDictionaryString NegotiationValueType
- {
- get
- {
- if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
- {
- return XD.TrustApr2004Dictionary.TlsnegoValueTypeUri;
- }
- else if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrust13)
- {
- return DXD.TrustDec2005Dictionary.TlsnegoValueTypeUri;
- }
- // Not supported
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException());
- }
- }
- public override void OnOpen(TimeSpan timeout)
- {
- if (this.serverTokenProvider == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoServerX509TokenProvider)));
- }
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- SecurityUtils.OpenTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
- if (this.clientTokenAuthenticator != null)
- {
- SecurityUtils.OpenTokenAuthenticatorIfRequired(this.clientTokenAuthenticator, timeoutHelper.RemainingTime());
- }
- SecurityToken token = this.serverTokenProvider.GetToken(timeoutHelper.RemainingTime());
- this.serverToken = ValidateX509Token(token);
- base.OnOpen(timeoutHelper.RemainingTime());
- }
- public override void OnClose(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- if (this.serverTokenProvider != null)
- {
- SecurityUtils.CloseTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
- this.serverTokenProvider = null;
- }
- if (this.clientTokenAuthenticator != null)
- {
- SecurityUtils.CloseTokenAuthenticatorIfRequired(this.clientTokenAuthenticator, timeoutHelper.RemainingTime());
- this.clientTokenAuthenticator = null;
- }
- if (this.serverToken != null)
- {
- this.serverToken = null;
- }
- base.OnClose(timeoutHelper.RemainingTime());
- }
- public override void OnAbort()
- {
- if (this.serverTokenProvider != null)
- {
- SecurityUtils.AbortTokenProviderIfRequired(this.serverTokenProvider);
- this.serverTokenProvider = null;
- }
- if (this.clientTokenAuthenticator != null)
- {
- SecurityUtils.AbortTokenAuthenticatorIfRequired(this.clientTokenAuthenticator);
- this.clientTokenAuthenticator = null;
- }
- if (this.serverToken != null)
- {
- this.serverToken = null;
- }
- base.OnAbort();
- }
- protected override void ValidateIncomingBinaryNegotiation(BinaryNegotiation incomingNego)
- {
- // Accept both strings for WSTrustFeb2005
- if (incomingNego != null &&
- incomingNego.ValueTypeUri != this.NegotiationValueType.Value &&
- this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
- {
- incomingNego.Validate(DXD.TrustDec2005Dictionary.TlsnegoValueTypeUri);
- }
- else
- {
- base.ValidateIncomingBinaryNegotiation(incomingNego);
- }
- }
- protected override SspiNegotiationTokenAuthenticatorState CreateSspiState(byte[] incomingBlob, string incomingValueTypeUri)
- {
- TlsSspiNegotiation tlsNegotiation = new TlsSspiNegotiation(SchProtocols.TlsServer | SchProtocols.Ssl3Server,
- this.serverToken.Certificate, this.ClientTokenAuthenticator != null);
- // Echo only for TrustFeb2005 and ValueType mismatch
- if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005 &&
- this.NegotiationValueType.Value != incomingValueTypeUri)
- {
- tlsNegotiation.IncomingValueTypeUri = incomingValueTypeUri;
- }
- return new SspiNegotiationTokenAuthenticatorState(tlsNegotiation);
- }
- protected override BinaryNegotiation GetOutgoingBinaryNegotiation(ISspiNegotiation sspiNegotiation, byte[] outgoingBlob)
- {
- TlsSspiNegotiation tlsNegotiation = sspiNegotiation as TlsSspiNegotiation;
- // Echo only for TrustFeb2005 and ValueType mismatch
- if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005 &&
- tlsNegotiation != null &&
- tlsNegotiation.IncomingValueTypeUri != null)
- {
- return new BinaryNegotiation(tlsNegotiation.IncomingValueTypeUri, outgoingBlob);
- }
- else
- {
- return base.GetOutgoingBinaryNegotiation(sspiNegotiation, outgoingBlob);
- }
- }
- protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation)
- {
- TlsSspiNegotiation tlsNegotiation = (TlsSspiNegotiation)sspiNegotiation;
- if (tlsNegotiation.IsValidContext == false)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.InvalidSspiNegotiation)));
- }
- if (this.ClientTokenAuthenticator == null)
- {
- return EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
- }
- X509Certificate2 clientCertificate = tlsNegotiation.RemoteCertificate;
- if (clientCertificate == null)
- {
- // isAnonymous is false. So, fail the negotiation
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityTokenValidationException(SR.GetString(SR.ClientCertificateNotProvided)));
- }
- ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies;
- if (this.ClientTokenAuthenticator != null)
- {
- X509SecurityToken clientToken;
- WindowsIdentity preMappedIdentity;
- if (!this.MapCertificateToWindowsAccount || !tlsNegotiation.TryGetContextIdentity(out preMappedIdentity))
- {
- clientToken = new X509SecurityToken(clientCertificate);
- }
- else
- {
- clientToken = new X509WindowsSecurityToken(clientCertificate, preMappedIdentity, preMappedIdentity.AuthenticationType, true);
- preMappedIdentity.Dispose();
- }
- authorizationPolicies = this.ClientTokenAuthenticator.ValidateToken(clientToken);
- clientToken.Dispose();
- }
- else
- {
- authorizationPolicies = EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
- }
- return authorizationPolicies;
- }
- }
- }
|