| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.IdentityModel.Policy;
- using System.IdentityModel.Selectors;
- using System.IdentityModel.Tokens;
- using System.IO;
- using System.Net.Security;
- using System.Runtime;
- using System.Runtime.Diagnostics;
- using System.Security.Authentication;
- using System.Security.Authentication.ExtendedProtection;
- using System.Security.Cryptography.X509Certificates;
- using System.ServiceModel;
- using System.ServiceModel.Description;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Diagnostics.Application;
- using System.ServiceModel.Security;
- using System.ServiceModel.Security.Tokens;
- class SslStreamSecurityUpgradeProvider : StreamSecurityUpgradeProvider, IStreamUpgradeChannelBindingProvider
- {
- SecurityTokenAuthenticator clientCertificateAuthenticator;
- SecurityTokenManager clientSecurityTokenManager;
- SecurityTokenProvider serverTokenProvider;
- EndpointIdentity identity;
- IdentityVerifier identityVerifier;
- X509Certificate2 serverCertificate;
- bool requireClientCertificate;
- string scheme;
- bool enableChannelBinding;
- SslStreamSecurityUpgradeProvider(IDefaultCommunicationTimeouts timeouts, SecurityTokenManager clientSecurityTokenManager, bool requireClientCertificate, string scheme, IdentityVerifier identityVerifier)
- : base(timeouts)
- {
- this.identityVerifier = identityVerifier;
- this.scheme = scheme;
- this.clientSecurityTokenManager = clientSecurityTokenManager;
- this.requireClientCertificate = requireClientCertificate;
- }
- SslStreamSecurityUpgradeProvider(IDefaultCommunicationTimeouts timeouts, SecurityTokenProvider serverTokenProvider, bool requireClientCertificate, SecurityTokenAuthenticator clientCertificateAuthenticator, string scheme, IdentityVerifier identityVerifier)
- : base(timeouts)
- {
- this.serverTokenProvider = serverTokenProvider;
- this.requireClientCertificate = requireClientCertificate;
- this.clientCertificateAuthenticator = clientCertificateAuthenticator;
- this.identityVerifier = identityVerifier;
- this.scheme = scheme;
- }
- public static SslStreamSecurityUpgradeProvider CreateClientProvider(
- SslStreamSecurityBindingElement bindingElement, BindingContext context)
- {
- SecurityCredentialsManager credentialProvider = context.BindingParameters.Find<SecurityCredentialsManager>();
- if (credentialProvider == null)
- {
- credentialProvider = ClientCredentials.CreateDefaultCredentials();
- }
- SecurityTokenManager tokenManager = credentialProvider.CreateSecurityTokenManager();
- return new SslStreamSecurityUpgradeProvider(context.Binding, tokenManager, bindingElement.RequireClientCertificate, context.Binding.Scheme, bindingElement.IdentityVerifier);
- }
- public static SslStreamSecurityUpgradeProvider CreateServerProvider(
- SslStreamSecurityBindingElement bindingElement, BindingContext context)
- {
- SecurityCredentialsManager credentialProvider =
- context.BindingParameters.Find<SecurityCredentialsManager>();
- if (credentialProvider == null)
- {
- credentialProvider = ServiceCredentials.CreateDefaultCredentials();
- }
- Uri listenUri = TransportSecurityHelpers.GetListenUri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);
- SecurityTokenManager tokenManager = credentialProvider.CreateSecurityTokenManager();
- RecipientServiceModelSecurityTokenRequirement serverCertRequirement = new RecipientServiceModelSecurityTokenRequirement();
- serverCertRequirement.TokenType = SecurityTokenTypes.X509Certificate;
- serverCertRequirement.RequireCryptographicToken = true;
- serverCertRequirement.KeyUsage = SecurityKeyUsage.Exchange;
- serverCertRequirement.TransportScheme = context.Binding.Scheme;
- serverCertRequirement.ListenUri = listenUri;
- SecurityTokenProvider tokenProvider = tokenManager.CreateSecurityTokenProvider(serverCertRequirement);
- if (tokenProvider == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientCredentialsUnableToCreateLocalTokenProvider, serverCertRequirement)));
- }
- SecurityTokenAuthenticator certificateAuthenticator =
- TransportSecurityHelpers.GetCertificateTokenAuthenticator(tokenManager, context.Binding.Scheme, listenUri);
- return new SslStreamSecurityUpgradeProvider(context.Binding, tokenProvider, bindingElement.RequireClientCertificate,
- certificateAuthenticator, context.Binding.Scheme, bindingElement.IdentityVerifier);
- }
- public override EndpointIdentity Identity
- {
- get
- {
- if ((this.identity == null) && (this.serverCertificate != null))
- {
- this.identity = SecurityUtils.GetServiceCertificateIdentity(this.serverCertificate);
- }
- return this.identity;
- }
- }
- public IdentityVerifier IdentityVerifier
- {
- get
- {
- return this.identityVerifier;
- }
- }
- public bool RequireClientCertificate
- {
- get
- {
- return this.requireClientCertificate;
- }
- }
- public X509Certificate2 ServerCertificate
- {
- get
- {
- return this.serverCertificate;
- }
- }
- public SecurityTokenAuthenticator ClientCertificateAuthenticator
- {
- get
- {
- if (this.clientCertificateAuthenticator == null)
- {
- this.clientCertificateAuthenticator = new X509SecurityTokenAuthenticator(X509ClientCertificateAuthentication.DefaultCertificateValidator);
- }
- return this.clientCertificateAuthenticator;
- }
- }
- public SecurityTokenManager ClientSecurityTokenManager
- {
- get
- {
- return this.clientSecurityTokenManager;
- }
- }
- public string Scheme
- {
- get { return this.scheme; }
- }
- public override T GetProperty<T>()
- {
- if (typeof(T) == typeof(IChannelBindingProvider) || typeof(T) == typeof(IStreamUpgradeChannelBindingProvider))
- {
- return (T)(object)this;
- }
- return base.GetProperty<T>();
- }
- ChannelBinding IStreamUpgradeChannelBindingProvider.GetChannelBinding(StreamUpgradeInitiator upgradeInitiator, ChannelBindingKind kind)
- {
- if (upgradeInitiator == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("upgradeInitiator");
- }
- SslStreamSecurityUpgradeInitiator sslUpgradeInitiator = upgradeInitiator as SslStreamSecurityUpgradeInitiator;
- if (sslUpgradeInitiator == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("upgradeInitiator", SR.GetString(SR.UnsupportedUpgradeInitiator, upgradeInitiator.GetType()));
- }
- if (kind != ChannelBindingKind.Endpoint)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("kind", SR.GetString(SR.StreamUpgradeUnsupportedChannelBindingKind, this.GetType(), kind));
- }
- return sslUpgradeInitiator.ChannelBinding;
- }
- ChannelBinding IStreamUpgradeChannelBindingProvider.GetChannelBinding(StreamUpgradeAcceptor upgradeAcceptor, ChannelBindingKind kind)
- {
- if (upgradeAcceptor == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("upgradeAcceptor");
- }
- SslStreamSecurityUpgradeAcceptor sslupgradeAcceptor = upgradeAcceptor as SslStreamSecurityUpgradeAcceptor;
- if (sslupgradeAcceptor == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("upgradeAcceptor", SR.GetString(SR.UnsupportedUpgradeAcceptor, upgradeAcceptor.GetType()));
- }
- if (kind != ChannelBindingKind.Endpoint)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("kind", SR.GetString(SR.StreamUpgradeUnsupportedChannelBindingKind, this.GetType(), kind));
- }
- return sslupgradeAcceptor.ChannelBinding;
- }
- void IChannelBindingProvider.EnableChannelBindingSupport()
- {
- this.enableChannelBinding = true;
- }
- bool IChannelBindingProvider.IsChannelBindingSupportEnabled
- {
- get
- {
- return this.enableChannelBinding;
- }
- }
- public override StreamUpgradeAcceptor CreateUpgradeAcceptor()
- {
- ThrowIfDisposedOrNotOpen();
- return new SslStreamSecurityUpgradeAcceptor(this);
- }
- public override StreamUpgradeInitiator CreateUpgradeInitiator(EndpointAddress remoteAddress, Uri via)
- {
- ThrowIfDisposedOrNotOpen();
- return new SslStreamSecurityUpgradeInitiator(this, remoteAddress, via);
- }
- protected override void OnAbort()
- {
- if (this.clientCertificateAuthenticator != null)
- {
- SecurityUtils.AbortTokenAuthenticatorIfRequired(this.clientCertificateAuthenticator);
- }
- CleanupServerCertificate();
- }
- protected override void OnClose(TimeSpan timeout)
- {
- if (this.clientCertificateAuthenticator != null)
- {
- SecurityUtils.CloseTokenAuthenticatorIfRequired(this.clientCertificateAuthenticator, timeout);
- }
- CleanupServerCertificate();
- }
- protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return SecurityUtils.BeginCloseTokenAuthenticatorIfRequired(this.clientCertificateAuthenticator, timeout, callback, state);
- }
- protected override void OnEndClose(IAsyncResult result)
- {
- SecurityUtils.EndCloseTokenAuthenticatorIfRequired(result);
- CleanupServerCertificate();
- }
- void SetupServerCertificate(SecurityToken token)
- {
- X509SecurityToken x509Token = token as X509SecurityToken;
- if (x509Token == null)
- {
- SecurityUtils.AbortTokenProviderIfRequired(this.serverTokenProvider);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
- SR.InvalidTokenProvided, this.serverTokenProvider.GetType(), typeof(X509SecurityToken))));
- }
- this.serverCertificate = new X509Certificate2(x509Token.Certificate);
- }
- void CleanupServerCertificate()
- {
- if (this.serverCertificate != null)
- {
- SecurityUtils.ResetCertificate(this.serverCertificate);
- this.serverCertificate = null;
- }
- }
- protected override void OnOpen(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- SecurityUtils.OpenTokenAuthenticatorIfRequired(this.ClientCertificateAuthenticator, timeoutHelper.RemainingTime());
- if (this.serverTokenProvider != null)
- {
- SecurityUtils.OpenTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
- SecurityToken token = this.serverTokenProvider.GetToken(timeout);
- SetupServerCertificate(token);
- SecurityUtils.CloseTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
- this.serverTokenProvider = null;
- }
- }
- protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return new OpenAsyncResult(this, timeout, callback, state);
- }
- protected override void OnEndOpen(IAsyncResult result)
- {
- OpenAsyncResult.End(result);
- }
- class OpenAsyncResult : AsyncResult
- {
- SslStreamSecurityUpgradeProvider parent;
- TimeoutHelper timeoutHelper;
- AsyncCallback onOpenTokenAuthenticator;
- AsyncCallback onOpenTokenProvider;
- AsyncCallback onGetToken;
- AsyncCallback onCloseTokenProvider;
- public OpenAsyncResult(SslStreamSecurityUpgradeProvider parent, TimeSpan timeout,
- AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.parent = parent;
- this.timeoutHelper = new TimeoutHelper(timeout);
- // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callbacks
- this.onOpenTokenAuthenticator = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenAuthenticator));
- IAsyncResult result = SecurityUtils.BeginOpenTokenAuthenticatorIfRequired(parent.ClientCertificateAuthenticator,
- timeoutHelper.RemainingTime(), onOpenTokenAuthenticator, this);
- if (!result.CompletedSynchronously)
- {
- return;
- }
- if (HandleOpenAuthenticatorComplete(result))
- {
- base.Complete(true);
- }
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<OpenAsyncResult>(result);
- }
- bool HandleOpenAuthenticatorComplete(IAsyncResult result)
- {
- SecurityUtils.EndOpenTokenAuthenticatorIfRequired(result);
- if (parent.serverTokenProvider == null)
- {
- return true;
- }
- this.onOpenTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenProvider));
- IAsyncResult openTokenProviderResult = SecurityUtils.BeginOpenTokenProviderIfRequired(
- parent.serverTokenProvider, timeoutHelper.RemainingTime(), onOpenTokenProvider, this);
- if (!openTokenProviderResult.CompletedSynchronously)
- {
- return false;
- }
- return HandleOpenTokenProviderComplete(openTokenProviderResult);
- }
- bool HandleOpenTokenProviderComplete(IAsyncResult result)
- {
- SecurityUtils.EndOpenTokenProviderIfRequired(result);
- this.onGetToken = Fx.ThunkCallback(new AsyncCallback(OnGetToken));
- IAsyncResult getTokenResult = parent.serverTokenProvider.BeginGetToken(timeoutHelper.RemainingTime(),
- onGetToken, this);
- if (!getTokenResult.CompletedSynchronously)
- {
- return false;
- }
- return HandleGetTokenComplete(getTokenResult);
- }
- bool HandleGetTokenComplete(IAsyncResult result)
- {
- SecurityToken token = parent.serverTokenProvider.EndGetToken(result);
- parent.SetupServerCertificate(token);
- this.onCloseTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnCloseTokenProvider));
- IAsyncResult closeTokenProviderResult =
- SecurityUtils.BeginCloseTokenProviderIfRequired(parent.serverTokenProvider, timeoutHelper.RemainingTime(),
- onCloseTokenProvider, this);
- if (!closeTokenProviderResult.CompletedSynchronously)
- {
- return false;
- }
- return HandleCloseTokenProviderComplete(closeTokenProviderResult);
- }
- bool HandleCloseTokenProviderComplete(IAsyncResult result)
- {
- SecurityUtils.EndCloseTokenProviderIfRequired(result);
- parent.serverTokenProvider = null;
- return true;
- }
- void OnOpenTokenAuthenticator(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleOpenAuthenticatorComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- void OnOpenTokenProvider(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleOpenTokenProviderComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- void OnGetToken(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleGetTokenComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- void OnCloseTokenProvider(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleCloseTokenProviderComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- }
- }
- class SslStreamSecurityUpgradeAcceptor : StreamSecurityUpgradeAcceptorBase
- {
- SslStreamSecurityUpgradeProvider parent;
- SecurityMessageProperty clientSecurity;
- // for audit
- X509Certificate2 clientCertificate = null;
- ChannelBinding channelBindingToken;
- public SslStreamSecurityUpgradeAcceptor(SslStreamSecurityUpgradeProvider parent)
- : base(FramingUpgradeString.SslOrTls)
- {
- this.parent = parent;
- this.clientSecurity = new SecurityMessageProperty();
- }
- internal ChannelBinding ChannelBinding
- {
- get
- {
- Fx.Assert(this.IsChannelBindingSupportEnabled, "A request for the ChannelBinding is not permitted without enabling ChannelBinding first (through the IChannelBindingProvider interface)");
- return this.channelBindingToken;
- }
- }
- internal bool IsChannelBindingSupportEnabled
- {
- get
- {
- return ((IChannelBindingProvider)parent).IsChannelBindingSupportEnabled;
- }
- }
- protected override Stream OnAcceptUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity)
- {
- if (TD.SslOnAcceptUpgradeIsEnabled())
- {
- TD.SslOnAcceptUpgrade(this.EventTraceActivity);
- }
- SslStream sslStream = new SslStream(stream, false, this.ValidateRemoteCertificate);
- try
- {
- sslStream.AuthenticateAsServer(this.parent.ServerCertificate, this.parent.RequireClientCertificate,
- SslProtocols.Default, false);
- }
- catch (AuthenticationException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(exception.Message,
- exception));
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(
- SR.GetString(SR.NegotiationFailedIO, ioException.Message), ioException));
- }
- if (SecurityUtils.ShouldValidateSslCipherStrength())
- {
- SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
- }
- remoteSecurity = this.clientSecurity;
- if (this.IsChannelBindingSupportEnabled)
- {
- this.channelBindingToken = ChannelBindingUtility.GetToken(sslStream);
- }
- return sslStream;
- }
- protected override IAsyncResult OnBeginAcceptUpgrade(Stream stream, AsyncCallback callback, object state)
- {
- AcceptUpgradeAsyncResult result = new AcceptUpgradeAsyncResult(this, callback, state);
- result.Begin(stream);
- return result;
- }
- protected override Stream OnEndAcceptUpgrade(IAsyncResult result, out SecurityMessageProperty remoteSecurity)
- {
- return AcceptUpgradeAsyncResult.End(result, out remoteSecurity, out this.channelBindingToken);
- }
-
- // callback from schannel
- bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain,
- SslPolicyErrors sslPolicyErrors)
- {
- if (this.parent.RequireClientCertificate)
- {
- if (certificate == null)
- {
- if (DiagnosticUtility.ShouldTraceError)
- {
- TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.SslClientCertMissing,
- SR.GetString(SR.TraceCodeSslClientCertMissing), this);
- }
- return false;
- }
- // Note: add ref to handle since the caller will reset the cert after the callback return.
- X509Certificate2 certificate2 = new X509Certificate2(certificate);
- this.clientCertificate = certificate2;
- try
- {
- SecurityToken token = new X509SecurityToken(certificate2, false);
- ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = this.parent.ClientCertificateAuthenticator.ValidateToken(token);
- this.clientSecurity = new SecurityMessageProperty();
- this.clientSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies);
- this.clientSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies);
- }
- catch (SecurityTokenException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- return false;
- }
- }
- return true;
- }
- public override SecurityMessageProperty GetRemoteSecurity()
- {
- if (this.clientSecurity.TransportToken != null)
- {
- return this.clientSecurity;
- }
- if (this.clientCertificate != null)
- {
- SecurityToken token = new X509SecurityToken(this.clientCertificate);
- ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = SecurityUtils.NonValidatingX509Authenticator.ValidateToken(token);
- this.clientSecurity = new SecurityMessageProperty();
- this.clientSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies);
- this.clientSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies);
- return this.clientSecurity;
- }
- return base.GetRemoteSecurity();
- }
- class AcceptUpgradeAsyncResult : StreamSecurityUpgradeAcceptorAsyncResult
- {
- SslStreamSecurityUpgradeAcceptor acceptor;
- SslStream sslStream;
- ChannelBinding channelBindingToken;
- public AcceptUpgradeAsyncResult(SslStreamSecurityUpgradeAcceptor acceptor, AsyncCallback callback,
- object state)
- : base(callback, state)
- {
- this.acceptor = acceptor;
- }
- protected override IAsyncResult OnBegin(Stream stream, AsyncCallback callback)
- {
- if (TD.SslOnAcceptUpgradeIsEnabled())
- {
- TD.SslOnAcceptUpgrade(acceptor.EventTraceActivity);
- }
- this.sslStream = new SslStream(stream, false, this.acceptor.ValidateRemoteCertificate);
- return this.sslStream.BeginAuthenticateAsServer(this.acceptor.parent.ServerCertificate,
- this.acceptor.parent.RequireClientCertificate, SslProtocols.Default, false, callback, this);
- }
- protected override Stream OnCompleteAuthenticateAsServer(IAsyncResult result)
- {
- this.sslStream.EndAuthenticateAsServer(result);
- if (SecurityUtils.ShouldValidateSslCipherStrength())
- {
- SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
- }
- if (this.acceptor.IsChannelBindingSupportEnabled)
- {
- this.channelBindingToken = ChannelBindingUtility.GetToken(this.sslStream);
- }
- return this.sslStream;
- }
- protected override SecurityMessageProperty ValidateCreateSecurity()
- {
- return this.acceptor.clientSecurity;
- }
- public static Stream End(IAsyncResult result, out SecurityMessageProperty remoteSecurity, out ChannelBinding channelBinding)
- {
- Stream stream = StreamSecurityUpgradeAcceptorAsyncResult.End(result, out remoteSecurity);
- channelBinding = ((AcceptUpgradeAsyncResult)result).channelBindingToken;
- return stream;
- }
- }
- }
- class SslStreamSecurityUpgradeInitiator : StreamSecurityUpgradeInitiatorBase
- {
- SslStreamSecurityUpgradeProvider parent;
- SecurityMessageProperty serverSecurity;
- SecurityTokenProvider clientCertificateProvider;
- X509SecurityToken clientToken;
- SecurityTokenAuthenticator serverCertificateAuthenticator;
- ChannelBinding channelBindingToken;
- static LocalCertificateSelectionCallback clientCertificateSelectionCallback;
- public SslStreamSecurityUpgradeInitiator(SslStreamSecurityUpgradeProvider parent,
- EndpointAddress remoteAddress, Uri via)
- : base(FramingUpgradeString.SslOrTls, remoteAddress, via)
- {
- this.parent = parent;
- InitiatorServiceModelSecurityTokenRequirement serverCertRequirement = new InitiatorServiceModelSecurityTokenRequirement();
- serverCertRequirement.TokenType = SecurityTokenTypes.X509Certificate;
- serverCertRequirement.RequireCryptographicToken = true;
- serverCertRequirement.KeyUsage = SecurityKeyUsage.Exchange;
- serverCertRequirement.TargetAddress = remoteAddress;
- serverCertRequirement.Via = via;
- serverCertRequirement.TransportScheme = this.parent.Scheme;
- serverCertRequirement.PreferSslCertificateAuthenticator = true;
- SecurityTokenResolver dummy;
- this.serverCertificateAuthenticator = (parent.ClientSecurityTokenManager.CreateSecurityTokenAuthenticator(serverCertRequirement, out dummy));
- if (parent.RequireClientCertificate)
- {
- InitiatorServiceModelSecurityTokenRequirement clientCertRequirement = new InitiatorServiceModelSecurityTokenRequirement();
- clientCertRequirement.TokenType = SecurityTokenTypes.X509Certificate;
- clientCertRequirement.RequireCryptographicToken = true;
- clientCertRequirement.KeyUsage = SecurityKeyUsage.Signature;
- clientCertRequirement.TargetAddress = remoteAddress;
- clientCertRequirement.Via = via;
- clientCertRequirement.TransportScheme = this.parent.Scheme;
- this.clientCertificateProvider = parent.ClientSecurityTokenManager.CreateSecurityTokenProvider(clientCertRequirement);
- if (clientCertificateProvider == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientCredentialsUnableToCreateLocalTokenProvider, clientCertRequirement)));
- }
- }
- }
- static LocalCertificateSelectionCallback ClientCertificateSelectionCallback
- {
- get
- {
- if (clientCertificateSelectionCallback == null)
- {
- clientCertificateSelectionCallback = new LocalCertificateSelectionCallback(SelectClientCertificate);
- }
- return clientCertificateSelectionCallback;
- }
- }
- internal ChannelBinding ChannelBinding
- {
- get
- {
- Fx.Assert(this.IsChannelBindingSupportEnabled, "A request for the ChannelBinding is not permitted without enabling ChannelBinding first (through the IChannelBindingProvider interface)");
- return this.channelBindingToken;
- }
- }
- internal bool IsChannelBindingSupportEnabled
- {
- get
- {
- return ((IChannelBindingProvider)parent).IsChannelBindingSupportEnabled;
- }
- }
- IAsyncResult BaseBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return base.BeginOpen(timeout, callback, state);
- }
- void BaseEndOpen(IAsyncResult result)
- {
- base.EndOpen(result);
- }
- internal override IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return new OpenAsyncResult(this, timeout, callback, state);
- }
- internal override void EndOpen(IAsyncResult result)
- {
- OpenAsyncResult.End(result);
- }
- internal override void Open(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- base.Open(timeoutHelper.RemainingTime());
- if (this.clientCertificateProvider != null)
- {
- SecurityUtils.OpenTokenProviderIfRequired(this.clientCertificateProvider, timeoutHelper.RemainingTime());
- this.clientToken = (X509SecurityToken)this.clientCertificateProvider.GetToken(timeoutHelper.RemainingTime());
- }
- }
- IAsyncResult BaseBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return base.BeginClose(timeout, callback, state);
- }
- void BaseEndClose(IAsyncResult result)
- {
- base.EndClose(result);
- }
- internal override IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return new CloseAsyncResult(this, timeout, callback, state);
- }
- internal override void EndClose(IAsyncResult result)
- {
- CloseAsyncResult.End(result);
- }
- internal override void Close(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- base.Close(timeoutHelper.RemainingTime());
- if (this.clientCertificateProvider != null)
- {
- SecurityUtils.CloseTokenProviderIfRequired(this.clientCertificateProvider, timeoutHelper.RemainingTime());
- }
- }
- protected override IAsyncResult OnBeginInitiateUpgrade(Stream stream, AsyncCallback callback, object state)
- {
- if (TD.SslOnInitiateUpgradeIsEnabled())
- {
- TD.SslOnInitiateUpgrade();
- }
- InitiateUpgradeAsyncResult result = new InitiateUpgradeAsyncResult(this, callback, state);
- result.Begin(stream);
- return result;
- }
- protected override Stream OnEndInitiateUpgrade(IAsyncResult result,
- out SecurityMessageProperty remoteSecurity)
- {
- return InitiateUpgradeAsyncResult.End(result, out remoteSecurity, out this.channelBindingToken);
- }
- protected override Stream OnInitiateUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity)
- {
- if (TD.SslOnInitiateUpgradeIsEnabled())
- {
- TD.SslOnInitiateUpgrade();
- }
- X509CertificateCollection clientCertificates = null;
- LocalCertificateSelectionCallback selectionCallback = null;
- if (this.clientToken != null)
- {
- clientCertificates = new X509CertificateCollection();
- clientCertificates.Add(clientToken.Certificate);
- selectionCallback = ClientCertificateSelectionCallback;
- }
- SslStream sslStream = new SslStream(stream, false, this.ValidateRemoteCertificate, selectionCallback);
- try
- {
- sslStream.AuthenticateAsClient(string.Empty, clientCertificates, SslProtocols.Default, false);
- }
- catch (SecurityTokenValidationException tokenValidationException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(tokenValidationException.Message,
- tokenValidationException));
- }
- catch (AuthenticationException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(exception.Message,
- exception));
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(
- SR.GetString(SR.NegotiationFailedIO, ioException.Message), ioException));
- }
- if (SecurityUtils.ShouldValidateSslCipherStrength())
- {
- SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
- }
- remoteSecurity = this.serverSecurity;
- if (this.IsChannelBindingSupportEnabled)
- {
- this.channelBindingToken = ChannelBindingUtility.GetToken(sslStream);
- }
- return sslStream;
- }
- static X509Certificate SelectClientCertificate(object sender, string targetHost,
- X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
- {
- return localCertificates[0];
- }
- bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain,
- SslPolicyErrors sslPolicyErrors)
- {
- // Note: add ref to handle since the caller will reset the cert after the callback return.
- X509Certificate2 certificate2 = new X509Certificate2(certificate);
- SecurityToken token = new X509SecurityToken(certificate2, false);
- ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = this.serverCertificateAuthenticator.ValidateToken(token);
- this.serverSecurity = new SecurityMessageProperty();
- this.serverSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies);
- this.serverSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies);
- AuthorizationContext authzContext = this.serverSecurity.ServiceSecurityContext.AuthorizationContext;
- this.parent.IdentityVerifier.EnsureOutgoingIdentity(this.RemoteAddress, this.Via, authzContext);
- return true;
- }
- class InitiateUpgradeAsyncResult : StreamSecurityUpgradeInitiatorAsyncResult
- {
- X509CertificateCollection clientCertificates;
- SslStreamSecurityUpgradeInitiator initiator;
- LocalCertificateSelectionCallback selectionCallback;
- SslStream sslStream;
- ChannelBinding channelBindingToken;
- public InitiateUpgradeAsyncResult(SslStreamSecurityUpgradeInitiator initiator, AsyncCallback callback,
- object state)
- : base(callback, state)
- {
- this.initiator = initiator;
- if (initiator.clientToken != null)
- {
- this.clientCertificates = new X509CertificateCollection();
- this.clientCertificates.Add(initiator.clientToken.Certificate);
- this.selectionCallback = ClientCertificateSelectionCallback;
- }
- }
- protected override IAsyncResult OnBeginAuthenticateAsClient(Stream stream, AsyncCallback callback)
- {
- this.sslStream = new SslStream(stream, false, this.initiator.ValidateRemoteCertificate,
- this.selectionCallback);
- try
- {
- return this.sslStream.BeginAuthenticateAsClient(string.Empty, this.clientCertificates,
- SslProtocols.Default, false, callback, this);
- }
- catch (SecurityTokenValidationException tokenValidationException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(tokenValidationException.Message,
- tokenValidationException));
- }
- }
- protected override Stream OnCompleteAuthenticateAsClient(IAsyncResult result)
- {
- try
- {
- this.sslStream.EndAuthenticateAsClient(result);
- }
- catch (SecurityTokenValidationException tokenValidationException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(tokenValidationException.Message,
- tokenValidationException));
- }
- if (SecurityUtils.ShouldValidateSslCipherStrength())
- {
- SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
- }
- if (this.initiator.IsChannelBindingSupportEnabled)
- {
- this.channelBindingToken = ChannelBindingUtility.GetToken(this.sslStream);
- }
- return this.sslStream;
- }
- protected override SecurityMessageProperty ValidateCreateSecurity()
- {
- return this.initiator.serverSecurity;
- }
- public static Stream End(IAsyncResult result, out SecurityMessageProperty remoteSecurity, out ChannelBinding channelBinding)
- {
- Stream stream = StreamSecurityUpgradeInitiatorAsyncResult.End(result, out remoteSecurity);
- channelBinding = ((InitiateUpgradeAsyncResult)result).channelBindingToken;
- return stream;
- }
- }
- class OpenAsyncResult : AsyncResult
- {
- SslStreamSecurityUpgradeInitiator parent;
- TimeoutHelper timeoutHelper;
- AsyncCallback onBaseOpen;
- AsyncCallback onOpenTokenProvider;
- AsyncCallback onGetClientToken;
- public OpenAsyncResult(SslStreamSecurityUpgradeInitiator parent, TimeSpan timeout,
- AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.parent = parent;
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callback
- this.onBaseOpen = Fx.ThunkCallback(new AsyncCallback(OnBaseOpen));
- if (parent.clientCertificateProvider != null)
- {
- this.onOpenTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenProvider));
- this.onGetClientToken = Fx.ThunkCallback(new AsyncCallback(OnGetClientToken));
- }
- IAsyncResult result = parent.BaseBeginOpen(timeoutHelper.RemainingTime(), onBaseOpen, this);
- if (!result.CompletedSynchronously)
- {
- return;
- }
- if (HandleBaseOpenComplete(result))
- {
- base.Complete(true);
- }
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<OpenAsyncResult>(result);
- }
- bool HandleBaseOpenComplete(IAsyncResult result)
- {
- parent.BaseEndOpen(result);
- if (parent.clientCertificateProvider == null)
- {
- return true;
- }
- IAsyncResult openTokenProviderResult = SecurityUtils.BeginOpenTokenProviderIfRequired(
- parent.clientCertificateProvider, timeoutHelper.RemainingTime(), onOpenTokenProvider, this);
- if (!openTokenProviderResult.CompletedSynchronously)
- {
- return false;
- }
- return HandleOpenTokenProviderComplete(openTokenProviderResult);
- }
- bool HandleOpenTokenProviderComplete(IAsyncResult result)
- {
- SecurityUtils.EndOpenTokenProviderIfRequired(result);
- IAsyncResult getTokenResult = parent.clientCertificateProvider.BeginGetToken(timeoutHelper.RemainingTime(),
- onGetClientToken, this);
- if (!getTokenResult.CompletedSynchronously)
- {
- return false;
- }
- return HandleGetTokenComplete(getTokenResult);
- }
- bool HandleGetTokenComplete(IAsyncResult result)
- {
- parent.clientToken = (X509SecurityToken)parent.clientCertificateProvider.EndGetToken(result);
- return true;
- }
- void OnBaseOpen(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleBaseOpenComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- void OnOpenTokenProvider(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleOpenTokenProviderComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- void OnGetClientToken(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleGetTokenComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- }
- class CloseAsyncResult : AsyncResult
- {
- SslStreamSecurityUpgradeInitiator parent;
- TimeoutHelper timeoutHelper;
- AsyncCallback onBaseClose;
- AsyncCallback onCloseTokenProvider;
- public CloseAsyncResult(SslStreamSecurityUpgradeInitiator parent, TimeSpan timeout,
- AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.parent = parent;
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callback
- this.onBaseClose = Fx.ThunkCallback(new AsyncCallback(OnBaseClose));
- if (parent.clientCertificateProvider != null)
- {
- this.onCloseTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnCloseTokenProvider));
- }
- IAsyncResult result = parent.BaseBeginClose(timeoutHelper.RemainingTime(), onBaseClose, this);
- if (!result.CompletedSynchronously)
- {
- return;
- }
- if (HandleBaseCloseComplete(result))
- {
- base.Complete(true);
- }
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<CloseAsyncResult>(result);
- }
- bool HandleBaseCloseComplete(IAsyncResult result)
- {
- parent.BaseEndClose(result);
- if (parent.clientCertificateProvider == null)
- {
- return true;
- }
- IAsyncResult closeTokenProviderResult = SecurityUtils.BeginCloseTokenProviderIfRequired(
- parent.clientCertificateProvider, timeoutHelper.RemainingTime(), onCloseTokenProvider, this);
- if (!closeTokenProviderResult.CompletedSynchronously)
- {
- return false;
- }
- SecurityUtils.EndCloseTokenProviderIfRequired(closeTokenProviderResult);
- return true;
- }
- void OnBaseClose(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- bool completeSelf = false;
- try
- {
- completeSelf = this.HandleBaseCloseComplete(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- base.Complete(false, completionException);
- }
- }
- void OnCloseTokenProvider(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- Exception completionException = null;
- try
- {
- SecurityUtils.EndCloseTokenProviderIfRequired(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- }
- base.Complete(false, completionException);
- }
- }
- }
- }
|