Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Channels / SslStreamSecurityUpgradeProvider.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.ServiceModel.Channels
6 {
7     using System.Collections.ObjectModel;
8     using System.Diagnostics;
9     using System.IdentityModel.Policy;
10     using System.IdentityModel.Selectors;
11     using System.IdentityModel.Tokens;
12     using System.IO;
13     using System.Net.Security;
14     using System.Runtime;
15     using System.Runtime.Diagnostics;
16     using System.Security.Authentication;
17     using System.Security.Authentication.ExtendedProtection;
18     using System.Security.Cryptography.X509Certificates;
19     using System.ServiceModel;
20     using System.ServiceModel.Description;
21     using System.ServiceModel.Diagnostics;
22     using System.ServiceModel.Diagnostics.Application;
23     using System.ServiceModel.Security;
24     using System.ServiceModel.Security.Tokens;
25
26     class SslStreamSecurityUpgradeProvider : StreamSecurityUpgradeProvider, IStreamUpgradeChannelBindingProvider
27     {
28         SecurityTokenAuthenticator clientCertificateAuthenticator;
29         SecurityTokenManager clientSecurityTokenManager;
30         SecurityTokenProvider serverTokenProvider;
31         EndpointIdentity identity;
32         IdentityVerifier identityVerifier;
33         X509Certificate2 serverCertificate;
34         bool requireClientCertificate;
35         string scheme;
36         bool enableChannelBinding;
37         SslProtocols sslProtocols;
38
39         SslStreamSecurityUpgradeProvider(IDefaultCommunicationTimeouts timeouts, SecurityTokenManager clientSecurityTokenManager, bool requireClientCertificate, string scheme, IdentityVerifier identityVerifier, SslProtocols sslProtocols)
40             : base(timeouts)
41         {
42             this.identityVerifier = identityVerifier;
43             this.scheme = scheme;
44             this.clientSecurityTokenManager = clientSecurityTokenManager;
45             this.requireClientCertificate = requireClientCertificate;
46             this.sslProtocols = sslProtocols;
47         }
48
49         SslStreamSecurityUpgradeProvider(IDefaultCommunicationTimeouts timeouts, SecurityTokenProvider serverTokenProvider, bool requireClientCertificate, SecurityTokenAuthenticator clientCertificateAuthenticator, string scheme, IdentityVerifier identityVerifier, SslProtocols sslProtocols)
50             : base(timeouts)
51         {
52             this.serverTokenProvider = serverTokenProvider;
53             this.requireClientCertificate = requireClientCertificate;
54             this.clientCertificateAuthenticator = clientCertificateAuthenticator;
55             this.identityVerifier = identityVerifier;
56             this.scheme = scheme;
57             this.sslProtocols = sslProtocols;
58         }
59
60         public static SslStreamSecurityUpgradeProvider CreateClientProvider(
61             SslStreamSecurityBindingElement bindingElement, BindingContext context)
62         {
63             SecurityCredentialsManager credentialProvider = context.BindingParameters.Find<SecurityCredentialsManager>();
64
65             if (credentialProvider == null)
66             {
67                 credentialProvider = ClientCredentials.CreateDefaultCredentials();
68             }
69             SecurityTokenManager tokenManager = credentialProvider.CreateSecurityTokenManager();
70
71             return new SslStreamSecurityUpgradeProvider(context.Binding, tokenManager, bindingElement.RequireClientCertificate, context.Binding.Scheme, bindingElement.IdentityVerifier, bindingElement.SslProtocols);
72         }
73
74         public static SslStreamSecurityUpgradeProvider CreateServerProvider(
75             SslStreamSecurityBindingElement bindingElement, BindingContext context)
76         {
77             SecurityCredentialsManager credentialProvider =
78                 context.BindingParameters.Find<SecurityCredentialsManager>();
79
80             if (credentialProvider == null)
81             {
82                 credentialProvider = ServiceCredentials.CreateDefaultCredentials();
83             }
84
85             Uri listenUri = TransportSecurityHelpers.GetListenUri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);
86             SecurityTokenManager tokenManager = credentialProvider.CreateSecurityTokenManager();
87
88             RecipientServiceModelSecurityTokenRequirement serverCertRequirement = new RecipientServiceModelSecurityTokenRequirement();
89             serverCertRequirement.TokenType = SecurityTokenTypes.X509Certificate;
90             serverCertRequirement.RequireCryptographicToken = true;
91             serverCertRequirement.KeyUsage = SecurityKeyUsage.Exchange;
92             serverCertRequirement.TransportScheme = context.Binding.Scheme;
93             serverCertRequirement.ListenUri = listenUri;
94
95             SecurityTokenProvider tokenProvider = tokenManager.CreateSecurityTokenProvider(serverCertRequirement);
96             if (tokenProvider == null)
97             {
98                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientCredentialsUnableToCreateLocalTokenProvider, serverCertRequirement)));
99             }
100
101             SecurityTokenAuthenticator certificateAuthenticator =
102                 TransportSecurityHelpers.GetCertificateTokenAuthenticator(tokenManager, context.Binding.Scheme, listenUri);
103
104             return new SslStreamSecurityUpgradeProvider(context.Binding, tokenProvider, bindingElement.RequireClientCertificate,
105                 certificateAuthenticator, context.Binding.Scheme, bindingElement.IdentityVerifier, bindingElement.SslProtocols);
106         }
107
108         public override EndpointIdentity Identity
109         {
110             get
111             {
112                 if ((this.identity == null) && (this.serverCertificate != null))
113                 {
114                     this.identity = SecurityUtils.GetServiceCertificateIdentity(this.serverCertificate);
115                 }
116                 return this.identity;
117             }
118         }
119
120         public IdentityVerifier IdentityVerifier
121         {
122             get
123             {
124                 return this.identityVerifier;
125             }
126         }
127
128         public bool RequireClientCertificate
129         {
130             get
131             {
132                 return this.requireClientCertificate;
133             }
134         }
135
136         public X509Certificate2 ServerCertificate
137         {
138             get
139             {
140                 return this.serverCertificate;
141             }
142         }
143
144         public SecurityTokenAuthenticator ClientCertificateAuthenticator
145         {
146             get
147             {
148                 if (this.clientCertificateAuthenticator == null)
149                 {
150                     this.clientCertificateAuthenticator = new X509SecurityTokenAuthenticator(X509ClientCertificateAuthentication.DefaultCertificateValidator);
151                 }
152
153                 return this.clientCertificateAuthenticator;
154             }
155         }
156
157         public SecurityTokenManager ClientSecurityTokenManager
158         {
159             get
160             {
161                 return this.clientSecurityTokenManager;
162             }
163         }
164
165         public string Scheme
166         {
167             get { return this.scheme; }
168         }
169
170         public SslProtocols SslProtocols
171         {
172             get { return this.sslProtocols; }
173         }
174
175         public override T GetProperty<T>()
176         {
177             if (typeof(T) == typeof(IChannelBindingProvider) || typeof(T) == typeof(IStreamUpgradeChannelBindingProvider))
178             {
179                 return (T)(object)this;
180             }
181             return base.GetProperty<T>();
182         }
183
184         ChannelBinding IStreamUpgradeChannelBindingProvider.GetChannelBinding(StreamUpgradeInitiator upgradeInitiator, ChannelBindingKind kind)
185         {
186             if (upgradeInitiator == null)
187             {
188                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("upgradeInitiator");
189             }
190
191             SslStreamSecurityUpgradeInitiator sslUpgradeInitiator = upgradeInitiator as SslStreamSecurityUpgradeInitiator;
192
193             if (sslUpgradeInitiator == null)
194             {
195                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("upgradeInitiator", SR.GetString(SR.UnsupportedUpgradeInitiator, upgradeInitiator.GetType()));
196             }
197
198             if (kind != ChannelBindingKind.Endpoint)
199             {
200                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("kind", SR.GetString(SR.StreamUpgradeUnsupportedChannelBindingKind, this.GetType(), kind));
201             }
202
203             return sslUpgradeInitiator.ChannelBinding;
204         }
205
206         ChannelBinding IStreamUpgradeChannelBindingProvider.GetChannelBinding(StreamUpgradeAcceptor upgradeAcceptor, ChannelBindingKind kind)
207         {
208             if (upgradeAcceptor == null)
209             {
210                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("upgradeAcceptor");
211             }
212
213             SslStreamSecurityUpgradeAcceptor sslupgradeAcceptor = upgradeAcceptor as SslStreamSecurityUpgradeAcceptor;
214
215             if (sslupgradeAcceptor == null)
216             {
217                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("upgradeAcceptor", SR.GetString(SR.UnsupportedUpgradeAcceptor, upgradeAcceptor.GetType()));
218             }
219
220             if (kind != ChannelBindingKind.Endpoint)
221             {
222                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("kind", SR.GetString(SR.StreamUpgradeUnsupportedChannelBindingKind, this.GetType(), kind));
223             }
224
225             return sslupgradeAcceptor.ChannelBinding;
226         }
227
228         void IChannelBindingProvider.EnableChannelBindingSupport()
229         {
230             this.enableChannelBinding = true;
231         }
232
233
234         bool IChannelBindingProvider.IsChannelBindingSupportEnabled
235         {
236             get
237             {
238                 return this.enableChannelBinding;
239             }
240         }
241
242         public override StreamUpgradeAcceptor CreateUpgradeAcceptor()
243         {
244             ThrowIfDisposedOrNotOpen();
245             return new SslStreamSecurityUpgradeAcceptor(this);
246         }
247
248         public override StreamUpgradeInitiator CreateUpgradeInitiator(EndpointAddress remoteAddress, Uri via)
249         {
250             ThrowIfDisposedOrNotOpen();
251             return new SslStreamSecurityUpgradeInitiator(this, remoteAddress, via);
252         }
253
254         protected override void OnAbort()
255         {
256             if (this.clientCertificateAuthenticator != null)
257             {
258                 SecurityUtils.AbortTokenAuthenticatorIfRequired(this.clientCertificateAuthenticator);
259             }
260             CleanupServerCertificate();
261         }
262
263         protected override void OnClose(TimeSpan timeout)
264         {
265             if (this.clientCertificateAuthenticator != null)
266             {
267                 SecurityUtils.CloseTokenAuthenticatorIfRequired(this.clientCertificateAuthenticator, timeout);
268             }
269             CleanupServerCertificate();
270         }
271
272         protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
273         {
274             return SecurityUtils.BeginCloseTokenAuthenticatorIfRequired(this.clientCertificateAuthenticator, timeout, callback, state);
275         }
276
277         protected override void OnEndClose(IAsyncResult result)
278         {
279             SecurityUtils.EndCloseTokenAuthenticatorIfRequired(result);
280             CleanupServerCertificate();
281         }
282
283         void SetupServerCertificate(SecurityToken token)
284         {
285             X509SecurityToken x509Token = token as X509SecurityToken;
286             if (x509Token == null)
287             {
288                 SecurityUtils.AbortTokenProviderIfRequired(this.serverTokenProvider);
289                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
290                     SR.InvalidTokenProvided, this.serverTokenProvider.GetType(), typeof(X509SecurityToken))));
291             }
292             this.serverCertificate = new X509Certificate2(x509Token.Certificate);
293         }
294
295         void CleanupServerCertificate()
296         {
297             if (this.serverCertificate != null)
298             {
299                 SecurityUtils.ResetCertificate(this.serverCertificate);
300                 this.serverCertificate = null;
301             }
302         }
303
304         protected override void OnOpen(TimeSpan timeout)
305         {
306             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
307             SecurityUtils.OpenTokenAuthenticatorIfRequired(this.ClientCertificateAuthenticator, timeoutHelper.RemainingTime());
308
309             if (this.serverTokenProvider != null)
310             {
311                 SecurityUtils.OpenTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
312                 SecurityToken token = this.serverTokenProvider.GetToken(timeout);
313                 SetupServerCertificate(token);
314                 SecurityUtils.CloseTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
315                 this.serverTokenProvider = null;
316             }
317         }
318
319         protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
320         {
321             return new OpenAsyncResult(this, timeout, callback, state);
322         }
323
324         protected override void OnEndOpen(IAsyncResult result)
325         {
326             OpenAsyncResult.End(result);
327         }
328
329         class OpenAsyncResult : AsyncResult
330         {
331             SslStreamSecurityUpgradeProvider parent;
332             TimeoutHelper timeoutHelper;
333             AsyncCallback onOpenTokenAuthenticator;
334             AsyncCallback onOpenTokenProvider;
335             AsyncCallback onGetToken;
336             AsyncCallback onCloseTokenProvider;
337
338             public OpenAsyncResult(SslStreamSecurityUpgradeProvider parent, TimeSpan timeout,
339                 AsyncCallback callback, object state)
340                 : base(callback, state)
341             {
342                 this.parent = parent;
343                 this.timeoutHelper = new TimeoutHelper(timeout);
344
345
346
347                 // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callbacks
348                 this.onOpenTokenAuthenticator = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenAuthenticator));
349                 IAsyncResult result = SecurityUtils.BeginOpenTokenAuthenticatorIfRequired(parent.ClientCertificateAuthenticator,
350                     timeoutHelper.RemainingTime(), onOpenTokenAuthenticator, this);
351
352                 if (!result.CompletedSynchronously)
353                 {
354                     return;
355                 }
356
357                 if (HandleOpenAuthenticatorComplete(result))
358                 {
359                     base.Complete(true);
360                 }
361             }
362
363             public static void End(IAsyncResult result)
364             {
365                 AsyncResult.End<OpenAsyncResult>(result);
366             }
367
368             bool HandleOpenAuthenticatorComplete(IAsyncResult result)
369             {
370                 SecurityUtils.EndOpenTokenAuthenticatorIfRequired(result);
371
372                 if (parent.serverTokenProvider == null)
373                 {
374                     return true;
375                 }
376
377                 this.onOpenTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenProvider));
378                 IAsyncResult openTokenProviderResult = SecurityUtils.BeginOpenTokenProviderIfRequired(
379                     parent.serverTokenProvider, timeoutHelper.RemainingTime(), onOpenTokenProvider, this);
380
381                 if (!openTokenProviderResult.CompletedSynchronously)
382                 {
383                     return false;
384                 }
385
386                 return HandleOpenTokenProviderComplete(openTokenProviderResult);
387             }
388
389             bool HandleOpenTokenProviderComplete(IAsyncResult result)
390             {
391                 SecurityUtils.EndOpenTokenProviderIfRequired(result);
392                 this.onGetToken = Fx.ThunkCallback(new AsyncCallback(OnGetToken));
393
394                 IAsyncResult getTokenResult = parent.serverTokenProvider.BeginGetToken(timeoutHelper.RemainingTime(),
395                     onGetToken, this);
396
397                 if (!getTokenResult.CompletedSynchronously)
398                 {
399                     return false;
400                 }
401
402                 return HandleGetTokenComplete(getTokenResult);
403             }
404
405             bool HandleGetTokenComplete(IAsyncResult result)
406             {
407                 SecurityToken token = parent.serverTokenProvider.EndGetToken(result);
408                 parent.SetupServerCertificate(token);
409                 this.onCloseTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnCloseTokenProvider));
410                 IAsyncResult closeTokenProviderResult =
411                     SecurityUtils.BeginCloseTokenProviderIfRequired(parent.serverTokenProvider, timeoutHelper.RemainingTime(),
412                     onCloseTokenProvider, this);
413
414                 if (!closeTokenProviderResult.CompletedSynchronously)
415                 {
416                     return false;
417                 }
418
419                 return HandleCloseTokenProviderComplete(closeTokenProviderResult);
420             }
421
422             bool HandleCloseTokenProviderComplete(IAsyncResult result)
423             {
424                 SecurityUtils.EndCloseTokenProviderIfRequired(result);
425                 parent.serverTokenProvider = null;
426                 return true;
427             }
428
429             void OnOpenTokenAuthenticator(IAsyncResult result)
430             {
431                 if (result.CompletedSynchronously)
432                 {
433                     return;
434                 }
435
436                 Exception completionException = null;
437                 bool completeSelf = false;
438                 try
439                 {
440                     completeSelf = this.HandleOpenAuthenticatorComplete(result);
441                 }
442 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
443                 catch (Exception e)
444                 {
445                     if (Fx.IsFatal(e))
446                     {
447                         throw;
448                     }
449
450                     completeSelf = true;
451                     completionException = e;
452                 }
453
454                 if (completeSelf)
455                 {
456                     base.Complete(false, completionException);
457                 }
458             }
459
460             void OnOpenTokenProvider(IAsyncResult result)
461             {
462                 if (result.CompletedSynchronously)
463                 {
464                     return;
465                 }
466
467                 Exception completionException = null;
468                 bool completeSelf = false;
469                 try
470                 {
471                     completeSelf = this.HandleOpenTokenProviderComplete(result);
472                 }
473 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
474                 catch (Exception e)
475                 {
476                     if (Fx.IsFatal(e))
477                     {
478                         throw;
479                     }
480
481                     completeSelf = true;
482                     completionException = e;
483                 }
484
485                 if (completeSelf)
486                 {
487                     base.Complete(false, completionException);
488                 }
489             }
490
491             void OnGetToken(IAsyncResult result)
492             {
493                 if (result.CompletedSynchronously)
494                 {
495                     return;
496                 }
497
498                 Exception completionException = null;
499                 bool completeSelf = false;
500                 try
501                 {
502                     completeSelf = this.HandleGetTokenComplete(result);
503                 }
504 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
505                 catch (Exception e)
506                 {
507                     if (Fx.IsFatal(e))
508                     {
509                         throw;
510                     }
511
512                     completeSelf = true;
513                     completionException = e;
514                 }
515
516                 if (completeSelf)
517                 {
518                     base.Complete(false, completionException);
519                 }
520             }
521
522             void OnCloseTokenProvider(IAsyncResult result)
523             {
524                 if (result.CompletedSynchronously)
525                 {
526                     return;
527                 }
528
529                 Exception completionException = null;
530                 bool completeSelf = false;
531                 try
532                 {
533                     completeSelf = this.HandleCloseTokenProviderComplete(result);
534                 }
535 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
536                 catch (Exception e)
537                 {
538                     if (Fx.IsFatal(e))
539                     {
540                         throw;
541                     }
542
543                     completeSelf = true;
544                     completionException = e;
545                 }
546
547                 if (completeSelf)
548                 {
549                     base.Complete(false, completionException);
550                 }
551             }
552
553         }
554     }
555
556     class SslStreamSecurityUpgradeAcceptor : StreamSecurityUpgradeAcceptorBase
557     {
558         SslStreamSecurityUpgradeProvider parent;
559         SecurityMessageProperty clientSecurity;
560         // for audit
561         X509Certificate2 clientCertificate = null;
562         ChannelBinding channelBindingToken;
563
564         public SslStreamSecurityUpgradeAcceptor(SslStreamSecurityUpgradeProvider parent)
565             : base(FramingUpgradeString.SslOrTls)
566         {
567             this.parent = parent;
568             this.clientSecurity = new SecurityMessageProperty();
569         }
570
571         internal ChannelBinding ChannelBinding
572         {
573             get
574             {
575                 Fx.Assert(this.IsChannelBindingSupportEnabled, "A request for the ChannelBinding is not permitted without enabling ChannelBinding first (through the IChannelBindingProvider interface)");
576                 return this.channelBindingToken;
577             }
578         }
579
580         internal bool IsChannelBindingSupportEnabled
581         {
582             get
583             {
584                 return ((IChannelBindingProvider)parent).IsChannelBindingSupportEnabled;
585             }
586         }
587
588         protected override Stream OnAcceptUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity)
589         {
590             if (TD.SslOnAcceptUpgradeIsEnabled())
591             {
592                 TD.SslOnAcceptUpgrade(this.EventTraceActivity);
593             }
594
595             SslStream sslStream = new SslStream(stream, false, this.ValidateRemoteCertificate);
596
597             try
598             {
599                 sslStream.AuthenticateAsServer(this.parent.ServerCertificate, this.parent.RequireClientCertificate,
600                     this.parent.SslProtocols, false);
601             }
602             catch (AuthenticationException exception)
603             {
604                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(exception.Message,
605                     exception));
606             }
607             catch (IOException ioException)
608             {
609                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(
610                     SR.GetString(SR.NegotiationFailedIO, ioException.Message), ioException));
611             }
612             if (SecurityUtils.ShouldValidateSslCipherStrength())
613             {
614                 SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
615             }
616
617             remoteSecurity = this.clientSecurity;
618
619             if (this.IsChannelBindingSupportEnabled)
620             {
621                 this.channelBindingToken = ChannelBindingUtility.GetToken(sslStream);
622             }
623
624             return sslStream;
625         }
626
627         protected override IAsyncResult OnBeginAcceptUpgrade(Stream stream, AsyncCallback callback, object state)
628         {
629             AcceptUpgradeAsyncResult result = new AcceptUpgradeAsyncResult(this, callback, state);
630             result.Begin(stream);
631             return result;
632         }
633
634         protected override Stream OnEndAcceptUpgrade(IAsyncResult result, out SecurityMessageProperty remoteSecurity)
635         {
636             return AcceptUpgradeAsyncResult.End(result, out remoteSecurity, out this.channelBindingToken);
637         }
638         
639         // callback from schannel
640         bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain,
641             SslPolicyErrors sslPolicyErrors)
642         {
643             if (this.parent.RequireClientCertificate)
644             {
645                 if (certificate == null)
646                 {
647                     if (DiagnosticUtility.ShouldTraceError)
648                     {
649                         TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.SslClientCertMissing,
650                             SR.GetString(SR.TraceCodeSslClientCertMissing), this);
651                     }
652                     return false;
653                 }
654                 // Note: add ref to handle since the caller will reset the cert after the callback return.
655                 X509Certificate2 certificate2 = new X509Certificate2(certificate);
656                 this.clientCertificate = certificate2;
657                 try
658                 {
659                     SecurityToken token = new X509SecurityToken(certificate2, false);
660                     ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = this.parent.ClientCertificateAuthenticator.ValidateToken(token);
661                     this.clientSecurity = new SecurityMessageProperty();
662                     this.clientSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies);
663                     this.clientSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies);
664                 }
665                 catch (SecurityTokenException e)
666                 {
667                     DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
668                     return false;
669                 }
670             }
671             return true;
672         }
673
674         public override SecurityMessageProperty GetRemoteSecurity()
675         {
676             if (this.clientSecurity.TransportToken != null)
677             {
678                 return this.clientSecurity;
679             }
680             if (this.clientCertificate != null)
681             {
682                 SecurityToken token = new X509SecurityToken(this.clientCertificate);
683                 ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = SecurityUtils.NonValidatingX509Authenticator.ValidateToken(token);
684                 this.clientSecurity = new SecurityMessageProperty();
685                 this.clientSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies);
686                 this.clientSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies);
687                 return this.clientSecurity;
688             }
689             return base.GetRemoteSecurity();
690         }
691
692         class AcceptUpgradeAsyncResult : StreamSecurityUpgradeAcceptorAsyncResult
693         {
694             SslStreamSecurityUpgradeAcceptor acceptor;
695             SslStream sslStream;
696             ChannelBinding channelBindingToken;
697
698             public AcceptUpgradeAsyncResult(SslStreamSecurityUpgradeAcceptor acceptor, AsyncCallback callback,
699                 object state)
700                 : base(callback, state)
701             {
702                 this.acceptor = acceptor;
703             }
704
705             protected override IAsyncResult OnBegin(Stream stream, AsyncCallback callback)
706             {
707                 if (TD.SslOnAcceptUpgradeIsEnabled())
708                 {
709                     TD.SslOnAcceptUpgrade(acceptor.EventTraceActivity);
710                 }
711
712                 this.sslStream = new SslStream(stream, false, this.acceptor.ValidateRemoteCertificate);
713                 return this.sslStream.BeginAuthenticateAsServer(this.acceptor.parent.ServerCertificate,
714                     this.acceptor.parent.RequireClientCertificate, this.acceptor.parent.SslProtocols, false, callback, this);
715             }
716
717             protected override Stream OnCompleteAuthenticateAsServer(IAsyncResult result)
718             {
719                 this.sslStream.EndAuthenticateAsServer(result);
720
721                 if (SecurityUtils.ShouldValidateSslCipherStrength())
722                 {
723                     SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
724                 }
725
726                 if (this.acceptor.IsChannelBindingSupportEnabled)
727                 {
728                     this.channelBindingToken = ChannelBindingUtility.GetToken(this.sslStream);
729                 }
730
731                 return this.sslStream;
732             }
733
734             protected override SecurityMessageProperty ValidateCreateSecurity()
735             {
736                 return this.acceptor.clientSecurity;
737             }
738
739             public static Stream End(IAsyncResult result, out SecurityMessageProperty remoteSecurity, out ChannelBinding channelBinding)
740             {
741                 Stream stream = StreamSecurityUpgradeAcceptorAsyncResult.End(result, out remoteSecurity);
742                 channelBinding = ((AcceptUpgradeAsyncResult)result).channelBindingToken;
743                 return stream;
744             }
745         }
746     }
747
748     class SslStreamSecurityUpgradeInitiator : StreamSecurityUpgradeInitiatorBase
749     {
750         SslStreamSecurityUpgradeProvider parent;
751         SecurityMessageProperty serverSecurity;
752         SecurityTokenProvider clientCertificateProvider;
753         X509SecurityToken clientToken;
754         SecurityTokenAuthenticator serverCertificateAuthenticator;
755         ChannelBinding channelBindingToken;
756
757         static LocalCertificateSelectionCallback clientCertificateSelectionCallback;
758
759         public SslStreamSecurityUpgradeInitiator(SslStreamSecurityUpgradeProvider parent,
760             EndpointAddress remoteAddress, Uri via)
761             : base(FramingUpgradeString.SslOrTls, remoteAddress, via)
762         {
763             this.parent = parent;
764
765             InitiatorServiceModelSecurityTokenRequirement serverCertRequirement = new InitiatorServiceModelSecurityTokenRequirement();
766             serverCertRequirement.TokenType = SecurityTokenTypes.X509Certificate;
767             serverCertRequirement.RequireCryptographicToken = true;
768             serverCertRequirement.KeyUsage = SecurityKeyUsage.Exchange;
769             serverCertRequirement.TargetAddress = remoteAddress;
770             serverCertRequirement.Via = via;
771             serverCertRequirement.TransportScheme = this.parent.Scheme;
772             serverCertRequirement.PreferSslCertificateAuthenticator = true;
773
774             SecurityTokenResolver dummy;
775             this.serverCertificateAuthenticator = (parent.ClientSecurityTokenManager.CreateSecurityTokenAuthenticator(serverCertRequirement, out dummy));
776
777             if (parent.RequireClientCertificate)
778             {
779                 InitiatorServiceModelSecurityTokenRequirement clientCertRequirement = new InitiatorServiceModelSecurityTokenRequirement();
780                 clientCertRequirement.TokenType = SecurityTokenTypes.X509Certificate;
781                 clientCertRequirement.RequireCryptographicToken = true;
782                 clientCertRequirement.KeyUsage = SecurityKeyUsage.Signature;
783                 clientCertRequirement.TargetAddress = remoteAddress;
784                 clientCertRequirement.Via = via;
785                 clientCertRequirement.TransportScheme = this.parent.Scheme;
786                 this.clientCertificateProvider = parent.ClientSecurityTokenManager.CreateSecurityTokenProvider(clientCertRequirement);
787                 if (clientCertificateProvider == null)
788                 {
789                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientCredentialsUnableToCreateLocalTokenProvider, clientCertRequirement)));
790                 }
791             }
792         }
793
794         static LocalCertificateSelectionCallback ClientCertificateSelectionCallback
795         {
796             get
797             {
798                 if (clientCertificateSelectionCallback == null)
799                 {
800                     clientCertificateSelectionCallback = new LocalCertificateSelectionCallback(SelectClientCertificate);
801                 }
802                 return clientCertificateSelectionCallback;
803             }
804         }
805
806         internal ChannelBinding ChannelBinding
807         {
808             get
809             {
810                 Fx.Assert(this.IsChannelBindingSupportEnabled, "A request for the ChannelBinding is not permitted without enabling ChannelBinding first (through the IChannelBindingProvider interface)");
811                 return this.channelBindingToken;
812             }
813         }
814
815         internal bool IsChannelBindingSupportEnabled
816         {
817             get
818             {
819                 return ((IChannelBindingProvider)parent).IsChannelBindingSupportEnabled;
820             }
821         }
822
823         IAsyncResult BaseBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
824         {
825             return base.BeginOpen(timeout, callback, state);
826         }
827
828         void BaseEndOpen(IAsyncResult result)
829         {
830             base.EndOpen(result);
831         }
832
833         internal override IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
834         {
835             return new OpenAsyncResult(this, timeout, callback, state);
836         }
837
838         internal override void EndOpen(IAsyncResult result)
839         {
840             OpenAsyncResult.End(result);
841         }
842
843         internal override void Open(TimeSpan timeout)
844         {
845             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
846             base.Open(timeoutHelper.RemainingTime());
847             if (this.clientCertificateProvider != null)
848             {
849                 SecurityUtils.OpenTokenProviderIfRequired(this.clientCertificateProvider, timeoutHelper.RemainingTime());
850                 this.clientToken = (X509SecurityToken)this.clientCertificateProvider.GetToken(timeoutHelper.RemainingTime());
851             }
852         }
853
854         IAsyncResult BaseBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
855         {
856             return base.BeginClose(timeout, callback, state);
857         }
858
859         void BaseEndClose(IAsyncResult result)
860         {
861             base.EndClose(result);
862         }
863
864         internal override IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
865         {
866             return new CloseAsyncResult(this, timeout, callback, state);
867         }
868
869         internal override void EndClose(IAsyncResult result)
870         {
871             CloseAsyncResult.End(result);
872         }
873
874         internal override void Close(TimeSpan timeout)
875         {
876             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
877             base.Close(timeoutHelper.RemainingTime());
878             if (this.clientCertificateProvider != null)
879             {
880                 SecurityUtils.CloseTokenProviderIfRequired(this.clientCertificateProvider, timeoutHelper.RemainingTime());
881             }
882         }
883
884         protected override IAsyncResult OnBeginInitiateUpgrade(Stream stream, AsyncCallback callback, object state)
885         {
886             if (TD.SslOnInitiateUpgradeIsEnabled())
887             {
888                 TD.SslOnInitiateUpgrade();
889             }
890
891             InitiateUpgradeAsyncResult result = new InitiateUpgradeAsyncResult(this, callback, state);
892             result.Begin(stream);
893             return result;
894         }
895
896         protected override Stream OnEndInitiateUpgrade(IAsyncResult result,
897             out SecurityMessageProperty remoteSecurity)
898         {
899             return InitiateUpgradeAsyncResult.End(result, out remoteSecurity, out this.channelBindingToken);
900         }
901
902         protected override Stream OnInitiateUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity)
903         {
904             if (TD.SslOnInitiateUpgradeIsEnabled())
905             {
906                 TD.SslOnInitiateUpgrade();
907             }
908
909             X509CertificateCollection clientCertificates = null;
910             LocalCertificateSelectionCallback selectionCallback = null;
911             if (this.clientToken != null)
912             {
913                 clientCertificates = new X509CertificateCollection();
914                 clientCertificates.Add(clientToken.Certificate);
915                 selectionCallback = ClientCertificateSelectionCallback;
916             }
917
918             SslStream sslStream = new SslStream(stream, false, this.ValidateRemoteCertificate, selectionCallback);
919             try
920             {
921                 sslStream.AuthenticateAsClient(string.Empty, clientCertificates, this.parent.SslProtocols, false);
922             }
923             catch (SecurityTokenValidationException tokenValidationException)
924             {
925                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(tokenValidationException.Message,
926                     tokenValidationException));
927             }
928             catch (AuthenticationException exception)
929             {
930                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(exception.Message,
931                     exception));
932             }
933             catch (IOException ioException)
934             {
935                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(
936                     SR.GetString(SR.NegotiationFailedIO, ioException.Message), ioException));
937             }
938
939             if (SecurityUtils.ShouldValidateSslCipherStrength())
940             {
941                 SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
942             }
943
944             remoteSecurity = this.serverSecurity;
945
946             if (this.IsChannelBindingSupportEnabled)
947             {
948                 this.channelBindingToken = ChannelBindingUtility.GetToken(sslStream);
949             }
950
951             return sslStream;
952         }
953
954         static X509Certificate SelectClientCertificate(object sender, string targetHost,
955             X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
956         {
957             return localCertificates[0];
958         }
959
960         bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain,
961             SslPolicyErrors sslPolicyErrors)
962         {
963             // Note: add ref to handle since the caller will reset the cert after the callback return.
964             X509Certificate2 certificate2 = new X509Certificate2(certificate);
965             SecurityToken token = new X509SecurityToken(certificate2, false);
966             ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = this.serverCertificateAuthenticator.ValidateToken(token);
967             this.serverSecurity = new SecurityMessageProperty();
968             this.serverSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies);
969             this.serverSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies);
970
971             AuthorizationContext authzContext = this.serverSecurity.ServiceSecurityContext.AuthorizationContext;
972             this.parent.IdentityVerifier.EnsureOutgoingIdentity(this.RemoteAddress, this.Via, authzContext);
973
974             return true;
975         }
976
977         class InitiateUpgradeAsyncResult : StreamSecurityUpgradeInitiatorAsyncResult
978         {
979             X509CertificateCollection clientCertificates;
980             SslStreamSecurityUpgradeInitiator initiator;
981             LocalCertificateSelectionCallback selectionCallback;
982             SslStream sslStream;
983             ChannelBinding channelBindingToken;
984
985             public InitiateUpgradeAsyncResult(SslStreamSecurityUpgradeInitiator initiator, AsyncCallback callback,
986                 object state)
987                 : base(callback, state)
988             {
989                 this.initiator = initiator;
990                 if (initiator.clientToken != null)
991                 {
992                     this.clientCertificates = new X509CertificateCollection();
993                     this.clientCertificates.Add(initiator.clientToken.Certificate);
994                     this.selectionCallback = ClientCertificateSelectionCallback;
995                 }
996             }
997
998             protected override IAsyncResult OnBeginAuthenticateAsClient(Stream stream, AsyncCallback callback)
999             {
1000                 this.sslStream = new SslStream(stream, false, this.initiator.ValidateRemoteCertificate,
1001                     this.selectionCallback);
1002
1003                 try
1004                 {
1005                     return this.sslStream.BeginAuthenticateAsClient(string.Empty, this.clientCertificates,
1006                         this.initiator.parent.SslProtocols, false, callback, this);
1007                 }
1008                 catch (SecurityTokenValidationException tokenValidationException)
1009                 {
1010                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(tokenValidationException.Message,
1011                         tokenValidationException));
1012                 }
1013             }
1014
1015             protected override Stream OnCompleteAuthenticateAsClient(IAsyncResult result)
1016             {
1017                 try
1018                 {
1019                     this.sslStream.EndAuthenticateAsClient(result);
1020                 }
1021                 catch (SecurityTokenValidationException tokenValidationException)
1022                 {
1023                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(tokenValidationException.Message,
1024                         tokenValidationException));
1025                 }
1026
1027                 if (SecurityUtils.ShouldValidateSslCipherStrength())
1028                 {
1029                     SecurityUtils.ValidateSslCipherStrength(sslStream.CipherStrength);
1030                 }
1031
1032                 if (this.initiator.IsChannelBindingSupportEnabled)
1033                 {
1034                     this.channelBindingToken = ChannelBindingUtility.GetToken(this.sslStream);
1035                 }
1036
1037                 return this.sslStream;
1038             }
1039
1040             protected override SecurityMessageProperty ValidateCreateSecurity()
1041             {
1042                 return this.initiator.serverSecurity;
1043             }
1044
1045             public static Stream End(IAsyncResult result, out SecurityMessageProperty remoteSecurity, out ChannelBinding channelBinding)
1046             {
1047                 Stream stream = StreamSecurityUpgradeInitiatorAsyncResult.End(result, out remoteSecurity);
1048                 channelBinding = ((InitiateUpgradeAsyncResult)result).channelBindingToken;
1049                 return stream;
1050             }
1051         }
1052
1053         class OpenAsyncResult : AsyncResult
1054         {
1055             SslStreamSecurityUpgradeInitiator parent;
1056             TimeoutHelper timeoutHelper;
1057             AsyncCallback onBaseOpen;
1058             AsyncCallback onOpenTokenProvider;
1059             AsyncCallback onGetClientToken;
1060
1061             public OpenAsyncResult(SslStreamSecurityUpgradeInitiator parent, TimeSpan timeout,
1062                 AsyncCallback callback, object state)
1063                 : base(callback, state)
1064             {
1065                 this.parent = parent;
1066                 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
1067
1068                 // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callback
1069                 this.onBaseOpen = Fx.ThunkCallback(new AsyncCallback(OnBaseOpen));
1070                 if (parent.clientCertificateProvider != null)
1071                 {
1072                     this.onOpenTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenProvider));
1073                     this.onGetClientToken = Fx.ThunkCallback(new AsyncCallback(OnGetClientToken));
1074                 }
1075                 IAsyncResult result = parent.BaseBeginOpen(timeoutHelper.RemainingTime(), onBaseOpen, this);
1076
1077                 if (!result.CompletedSynchronously)
1078                 {
1079                     return;
1080                 }
1081
1082                 if (HandleBaseOpenComplete(result))
1083                 {
1084                     base.Complete(true);
1085                 }
1086             }
1087
1088             public static void End(IAsyncResult result)
1089             {
1090                 AsyncResult.End<OpenAsyncResult>(result);
1091             }
1092
1093             bool HandleBaseOpenComplete(IAsyncResult result)
1094             {
1095                 parent.BaseEndOpen(result);
1096                 if (parent.clientCertificateProvider == null)
1097                 {
1098                     return true;
1099                 }
1100
1101                 IAsyncResult openTokenProviderResult = SecurityUtils.BeginOpenTokenProviderIfRequired(
1102                     parent.clientCertificateProvider, timeoutHelper.RemainingTime(), onOpenTokenProvider, this);
1103
1104                 if (!openTokenProviderResult.CompletedSynchronously)
1105                 {
1106                     return false;
1107                 }
1108
1109                 return HandleOpenTokenProviderComplete(openTokenProviderResult);
1110             }
1111
1112             bool HandleOpenTokenProviderComplete(IAsyncResult result)
1113             {
1114                 SecurityUtils.EndOpenTokenProviderIfRequired(result);
1115                 IAsyncResult getTokenResult = parent.clientCertificateProvider.BeginGetToken(timeoutHelper.RemainingTime(),
1116                     onGetClientToken, this);
1117
1118                 if (!getTokenResult.CompletedSynchronously)
1119                 {
1120                     return false;
1121                 }
1122
1123                 return HandleGetTokenComplete(getTokenResult);
1124             }
1125
1126             bool HandleGetTokenComplete(IAsyncResult result)
1127             {
1128                 parent.clientToken = (X509SecurityToken)parent.clientCertificateProvider.EndGetToken(result);
1129                 return true;
1130             }
1131
1132             void OnBaseOpen(IAsyncResult result)
1133             {
1134                 if (result.CompletedSynchronously)
1135                 {
1136                     return;
1137                 }
1138
1139                 Exception completionException = null;
1140                 bool completeSelf = false;
1141                 try
1142                 {
1143                     completeSelf = this.HandleBaseOpenComplete(result);
1144                 }
1145 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1146                 catch (Exception e)
1147                 {
1148                     if (Fx.IsFatal(e))
1149                     {
1150                         throw;
1151                     }
1152
1153                     completeSelf = true;
1154                     completionException = e;
1155                 }
1156
1157                 if (completeSelf)
1158                 {
1159                     base.Complete(false, completionException);
1160                 }
1161             }
1162
1163             void OnOpenTokenProvider(IAsyncResult result)
1164             {
1165                 if (result.CompletedSynchronously)
1166                 {
1167                     return;
1168                 }
1169
1170                 Exception completionException = null;
1171                 bool completeSelf = false;
1172                 try
1173                 {
1174                     completeSelf = this.HandleOpenTokenProviderComplete(result);
1175                 }
1176 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1177                 catch (Exception e)
1178                 {
1179                     if (Fx.IsFatal(e))
1180                     {
1181                         throw;
1182                     }
1183
1184                     completeSelf = true;
1185                     completionException = e;
1186                 }
1187
1188                 if (completeSelf)
1189                 {
1190                     base.Complete(false, completionException);
1191                 }
1192             }
1193
1194             void OnGetClientToken(IAsyncResult result)
1195             {
1196                 if (result.CompletedSynchronously)
1197                 {
1198                     return;
1199                 }
1200
1201                 Exception completionException = null;
1202                 bool completeSelf = false;
1203                 try
1204                 {
1205                     completeSelf = this.HandleGetTokenComplete(result);
1206                 }
1207 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1208                 catch (Exception e)
1209                 {
1210                     if (Fx.IsFatal(e))
1211                     {
1212                         throw;
1213                     }
1214
1215                     completeSelf = true;
1216                     completionException = e;
1217                 }
1218
1219                 if (completeSelf)
1220                 {
1221                     base.Complete(false, completionException);
1222                 }
1223             }
1224         }
1225
1226         class CloseAsyncResult : AsyncResult
1227         {
1228             SslStreamSecurityUpgradeInitiator parent;
1229             TimeoutHelper timeoutHelper;
1230             AsyncCallback onBaseClose;
1231             AsyncCallback onCloseTokenProvider;
1232
1233             public CloseAsyncResult(SslStreamSecurityUpgradeInitiator parent, TimeSpan timeout,
1234                 AsyncCallback callback, object state)
1235                 : base(callback, state)
1236             {
1237                 this.parent = parent;
1238                 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
1239
1240                 // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callback
1241                 this.onBaseClose = Fx.ThunkCallback(new AsyncCallback(OnBaseClose));
1242                 if (parent.clientCertificateProvider != null)
1243                 {
1244                     this.onCloseTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnCloseTokenProvider));
1245                 }
1246                 IAsyncResult result = parent.BaseBeginClose(timeoutHelper.RemainingTime(), onBaseClose, this);
1247
1248                 if (!result.CompletedSynchronously)
1249                 {
1250                     return;
1251                 }
1252
1253                 if (HandleBaseCloseComplete(result))
1254                 {
1255                     base.Complete(true);
1256                 }
1257             }
1258
1259             public static void End(IAsyncResult result)
1260             {
1261                 AsyncResult.End<CloseAsyncResult>(result);
1262             }
1263
1264             bool HandleBaseCloseComplete(IAsyncResult result)
1265             {
1266                 parent.BaseEndClose(result);
1267                 if (parent.clientCertificateProvider == null)
1268                 {
1269                     return true;
1270                 }
1271
1272                 IAsyncResult closeTokenProviderResult = SecurityUtils.BeginCloseTokenProviderIfRequired(
1273                     parent.clientCertificateProvider, timeoutHelper.RemainingTime(), onCloseTokenProvider, this);
1274
1275                 if (!closeTokenProviderResult.CompletedSynchronously)
1276                 {
1277                     return false;
1278                 }
1279
1280                 SecurityUtils.EndCloseTokenProviderIfRequired(closeTokenProviderResult);
1281                 return true;
1282             }
1283
1284             void OnBaseClose(IAsyncResult result)
1285             {
1286                 if (result.CompletedSynchronously)
1287                 {
1288                     return;
1289                 }
1290
1291                 Exception completionException = null;
1292                 bool completeSelf = false;
1293                 try
1294                 {
1295                     completeSelf = this.HandleBaseCloseComplete(result);
1296                 }
1297 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1298                 catch (Exception e)
1299                 {
1300                     if (Fx.IsFatal(e))
1301                     {
1302                         throw;
1303                     }
1304
1305                     completeSelf = true;
1306                     completionException = e;
1307                 }
1308
1309                 if (completeSelf)
1310                 {
1311                     base.Complete(false, completionException);
1312                 }
1313             }
1314
1315             void OnCloseTokenProvider(IAsyncResult result)
1316             {
1317                 if (result.CompletedSynchronously)
1318                 {
1319                     return;
1320                 }
1321
1322                 Exception completionException = null;
1323                 try
1324                 {
1325                     SecurityUtils.EndCloseTokenProviderIfRequired(result);
1326                 }
1327 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
1328                 catch (Exception e)
1329                 {
1330                     if (Fx.IsFatal(e))
1331                     {
1332                         throw;
1333                     }
1334
1335                     completionException = e;
1336                 }
1337
1338                 base.Complete(false, completionException);
1339             }
1340         }
1341     }
1342 }