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.IdentityModel.Policy; 9 using System.IdentityModel.Selectors; 10 using System.IdentityModel.Tokens; 11 using System.IO; 12 using System.Net; 13 using System.Net.Security; 14 using System.Runtime; 15 using System.Security.Authentication; 16 using System.Security.Principal; 17 using System.ServiceModel; 18 using System.ServiceModel.Description; 19 using System.ServiceModel.Diagnostics.Application; 20 using System.ServiceModel.Security; 21 22 class WindowsStreamSecurityUpgradeProvider : StreamSecurityUpgradeProvider 23 { 24 bool extractGroupsForWindowsAccounts; 25 EndpointIdentity identity; 26 IdentityVerifier identityVerifier; 27 ProtectionLevel protectionLevel; 28 SecurityTokenManager securityTokenManager; 29 NetworkCredential serverCredential; 30 string scheme; 31 bool isClient; 32 Uri listenUri; 33 WindowsStreamSecurityUpgradeProvider(WindowsStreamSecurityBindingElement bindingElement, BindingContext context, bool isClient)34 public WindowsStreamSecurityUpgradeProvider(WindowsStreamSecurityBindingElement bindingElement, 35 BindingContext context, bool isClient) 36 : base(context.Binding) 37 { 38 this.extractGroupsForWindowsAccounts = TransportDefaults.ExtractGroupsForWindowsAccounts; 39 this.protectionLevel = bindingElement.ProtectionLevel; 40 this.scheme = context.Binding.Scheme; 41 this.isClient = isClient; 42 this.listenUri = TransportSecurityHelpers.GetListenUri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress); 43 44 SecurityCredentialsManager credentialProvider = context.BindingParameters.Find<SecurityCredentialsManager>(); 45 if (credentialProvider == null) 46 { 47 if (isClient) 48 { 49 credentialProvider = ClientCredentials.CreateDefaultCredentials(); 50 } 51 else 52 { 53 credentialProvider = ServiceCredentials.CreateDefaultCredentials(); 54 } 55 } 56 57 58 this.securityTokenManager = credentialProvider.CreateSecurityTokenManager(); 59 } 60 61 public string Scheme 62 { 63 get { return this.scheme; } 64 } 65 66 internal bool ExtractGroupsForWindowsAccounts 67 { 68 get 69 { 70 return this.extractGroupsForWindowsAccounts; 71 } 72 } 73 74 public override EndpointIdentity Identity 75 { 76 get 77 { 78 // If the server credential is null, then we have not been opened yet and have no identity to expose. 79 if (this.serverCredential != null) 80 { 81 if (this.identity == null) 82 { 83 lock (ThisLock) 84 { 85 if (this.identity == null) 86 { 87 this.identity = SecurityUtils.CreateWindowsIdentity(this.serverCredential); 88 } 89 } 90 } 91 } 92 return this.identity; 93 } 94 } 95 96 internal IdentityVerifier IdentityVerifier 97 { 98 get 99 { 100 return this.identityVerifier; 101 } 102 } 103 104 public ProtectionLevel ProtectionLevel 105 { 106 get 107 { 108 return protectionLevel; 109 } 110 } 111 112 NetworkCredential ServerCredential 113 { 114 get 115 { 116 return this.serverCredential; 117 } 118 } 119 CreateUpgradeAcceptor()120 public override StreamUpgradeAcceptor CreateUpgradeAcceptor() 121 { 122 ThrowIfDisposedOrNotOpen(); 123 return new WindowsStreamSecurityUpgradeAcceptor(this); 124 } 125 CreateUpgradeInitiator(EndpointAddress remoteAddress, Uri via)126 public override StreamUpgradeInitiator CreateUpgradeInitiator(EndpointAddress remoteAddress, Uri via) 127 { 128 ThrowIfDisposedOrNotOpen(); 129 return new WindowsStreamSecurityUpgradeInitiator(this, remoteAddress, via); 130 } 131 OnAbort()132 protected override void OnAbort() 133 { 134 } 135 OnClose(TimeSpan timeout)136 protected override void OnClose(TimeSpan timeout) 137 { 138 } 139 OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)140 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) 141 { 142 return new CompletedAsyncResult(callback, state); 143 } 144 OnEndClose(IAsyncResult result)145 protected override void OnEndClose(IAsyncResult result) 146 { 147 CompletedAsyncResult.End(result); 148 } 149 OnOpen(TimeSpan timeout)150 protected override void OnOpen(TimeSpan timeout) 151 { 152 if (!isClient) 153 { 154 SecurityTokenRequirement sspiTokenRequirement = TransportSecurityHelpers.CreateSspiTokenRequirement(this.Scheme, this.listenUri); 155 this.serverCredential = 156 TransportSecurityHelpers.GetSspiCredential(this.securityTokenManager, sspiTokenRequirement, timeout, 157 out this.extractGroupsForWindowsAccounts); 158 } 159 } 160 OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)161 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 162 { 163 OnOpen(timeout); 164 return new CompletedAsyncResult(callback, state); 165 } 166 OnEndOpen(IAsyncResult result)167 protected override void OnEndOpen(IAsyncResult result) 168 { 169 CompletedAsyncResult.End(result); 170 } 171 OnOpened()172 protected override void OnOpened() 173 { 174 base.OnOpened(); 175 176 if (this.identityVerifier == null) 177 { 178 this.identityVerifier = IdentityVerifier.CreateDefault(); 179 } 180 181 if (this.serverCredential == null) 182 { 183 this.serverCredential = CredentialCache.DefaultNetworkCredentials; 184 } 185 } 186 187 class WindowsStreamSecurityUpgradeAcceptor : StreamSecurityUpgradeAcceptorBase 188 { 189 WindowsStreamSecurityUpgradeProvider parent; 190 SecurityMessageProperty clientSecurity; 191 WindowsStreamSecurityUpgradeAcceptor(WindowsStreamSecurityUpgradeProvider parent)192 public WindowsStreamSecurityUpgradeAcceptor(WindowsStreamSecurityUpgradeProvider parent) 193 : base(FramingUpgradeString.Negotiate) 194 { 195 this.parent = parent; 196 this.clientSecurity = new SecurityMessageProperty(); 197 } 198 OnAcceptUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity)199 protected override Stream OnAcceptUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity) 200 { 201 // wrap stream 202 NegotiateStream negotiateStream = new NegotiateStream(stream); 203 204 // authenticate 205 try 206 { 207 if (TD.WindowsStreamSecurityOnAcceptUpgradeIsEnabled()) 208 { 209 TD.WindowsStreamSecurityOnAcceptUpgrade(this.EventTraceActivity); 210 } 211 212 negotiateStream.AuthenticateAsServer(parent.ServerCredential, parent.ProtectionLevel, 213 TokenImpersonationLevel.Identification); 214 } 215 catch (AuthenticationException exception) 216 { 217 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(exception.Message, 218 exception)); 219 } 220 catch (IOException ioException) 221 { 222 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException( 223 SR.GetString(SR.NegotiationFailedIO, ioException.Message), ioException)); 224 } 225 226 remoteSecurity = CreateClientSecurity(negotiateStream, parent.ExtractGroupsForWindowsAccounts); 227 return negotiateStream; 228 } 229 OnBeginAcceptUpgrade(Stream stream, AsyncCallback callback, object state)230 protected override IAsyncResult OnBeginAcceptUpgrade(Stream stream, AsyncCallback callback, object state) 231 { 232 AcceptUpgradeAsyncResult result = new AcceptUpgradeAsyncResult(this, callback, state); 233 result.Begin(stream); 234 return result; 235 } 236 OnEndAcceptUpgrade(IAsyncResult result, out SecurityMessageProperty remoteSecurity)237 protected override Stream OnEndAcceptUpgrade(IAsyncResult result, 238 out SecurityMessageProperty remoteSecurity) 239 { 240 return AcceptUpgradeAsyncResult.End(result, out remoteSecurity); 241 } 242 CreateClientSecurity(NegotiateStream negotiateStream, bool extractGroupsForWindowsAccounts)243 SecurityMessageProperty CreateClientSecurity(NegotiateStream negotiateStream, 244 bool extractGroupsForWindowsAccounts) 245 { 246 WindowsIdentity remoteIdentity = (WindowsIdentity)negotiateStream.RemoteIdentity; 247 SecurityUtils.ValidateAnonymityConstraint(remoteIdentity, false); 248 WindowsSecurityTokenAuthenticator authenticator = new WindowsSecurityTokenAuthenticator(extractGroupsForWindowsAccounts); 249 250 // When NegotiateStream returns a WindowsIdentity the AuthenticationType is passed in the constructor to WindowsIdentity 251 // by it's internal NegoState class. If this changes, then the call to remoteIdentity.AuthenticationType could fail if the 252 // current process token doesn't have sufficient priviledges. It is a first class exception, and caught by the CLR 253 // null is returned. 254 SecurityToken token = new WindowsSecurityToken(remoteIdentity, SecurityUniqueId.Create().Value, remoteIdentity.AuthenticationType); 255 ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = authenticator.ValidateToken(token); 256 this.clientSecurity = new SecurityMessageProperty(); 257 this.clientSecurity.TransportToken = new SecurityTokenSpecification(token, authorizationPolicies); 258 this.clientSecurity.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies); 259 return this.clientSecurity; 260 } 261 GetRemoteSecurity()262 public override SecurityMessageProperty GetRemoteSecurity() 263 { 264 if (this.clientSecurity.TransportToken != null) 265 { 266 return this.clientSecurity; 267 } 268 return base.GetRemoteSecurity(); 269 } 270 271 class AcceptUpgradeAsyncResult : StreamSecurityUpgradeAcceptorAsyncResult 272 { 273 WindowsStreamSecurityUpgradeAcceptor acceptor; 274 NegotiateStream negotiateStream; 275 AcceptUpgradeAsyncResult(WindowsStreamSecurityUpgradeAcceptor acceptor, AsyncCallback callback, object state)276 public AcceptUpgradeAsyncResult(WindowsStreamSecurityUpgradeAcceptor acceptor, AsyncCallback callback, 277 object state) 278 : base(callback, state) 279 { 280 this.acceptor = acceptor; 281 } 282 OnBegin(Stream stream, AsyncCallback callback)283 protected override IAsyncResult OnBegin(Stream stream, AsyncCallback callback) 284 { 285 this.negotiateStream = new NegotiateStream(stream); 286 return this.negotiateStream.BeginAuthenticateAsServer(this.acceptor.parent.ServerCredential, 287 this.acceptor.parent.ProtectionLevel, TokenImpersonationLevel.Identification, callback, this); 288 } 289 OnCompleteAuthenticateAsServer(IAsyncResult result)290 protected override Stream OnCompleteAuthenticateAsServer(IAsyncResult result) 291 { 292 this.negotiateStream.EndAuthenticateAsServer(result); 293 return this.negotiateStream; 294 } 295 ValidateCreateSecurity()296 protected override SecurityMessageProperty ValidateCreateSecurity() 297 { 298 return this.acceptor.CreateClientSecurity(this.negotiateStream, this.acceptor.parent.ExtractGroupsForWindowsAccounts); 299 } 300 } 301 } 302 303 class WindowsStreamSecurityUpgradeInitiator : StreamSecurityUpgradeInitiatorBase 304 { 305 WindowsStreamSecurityUpgradeProvider parent; 306 IdentityVerifier identityVerifier; 307 NetworkCredential credential; 308 TokenImpersonationLevel impersonationLevel; 309 SspiSecurityTokenProvider clientTokenProvider; 310 bool allowNtlm; 311 WindowsStreamSecurityUpgradeInitiator( WindowsStreamSecurityUpgradeProvider parent, EndpointAddress remoteAddress, Uri via)312 public WindowsStreamSecurityUpgradeInitiator( 313 WindowsStreamSecurityUpgradeProvider parent, EndpointAddress remoteAddress, Uri via) 314 : base(FramingUpgradeString.Negotiate, remoteAddress, via) 315 { 316 this.parent = parent; 317 this.clientTokenProvider = TransportSecurityHelpers.GetSspiTokenProvider( 318 parent.securityTokenManager, remoteAddress, via, parent.Scheme, out this.identityVerifier); 319 } 320 BaseBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)321 IAsyncResult BaseBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 322 { 323 return base.BeginOpen(timeout, callback, state); 324 } 325 BaseEndOpen(IAsyncResult result)326 void BaseEndOpen(IAsyncResult result) 327 { 328 base.EndOpen(result); 329 } 330 BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)331 internal override IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 332 { 333 return new OpenAsyncResult(this, timeout, callback, state); 334 } 335 EndOpen(IAsyncResult result)336 internal override void EndOpen(IAsyncResult result) 337 { 338 OpenAsyncResult.End(result); 339 } 340 Open(TimeSpan timeout)341 internal override void Open(TimeSpan timeout) 342 { 343 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 344 base.Open(timeoutHelper.RemainingTime()); 345 SecurityUtils.OpenTokenProviderIfRequired(this.clientTokenProvider, timeoutHelper.RemainingTime()); 346 this.credential = TransportSecurityHelpers.GetSspiCredential(this.clientTokenProvider, timeoutHelper.RemainingTime(), 347 out this.impersonationLevel, out this.allowNtlm); 348 } 349 BaseBeginClose(TimeSpan timeout, AsyncCallback callback, object state)350 IAsyncResult BaseBeginClose(TimeSpan timeout, AsyncCallback callback, object state) 351 { 352 return base.BeginClose(timeout, callback, state); 353 } 354 BaseEndClose(IAsyncResult result)355 void BaseEndClose(IAsyncResult result) 356 { 357 base.EndClose(result); 358 } 359 BeginClose(TimeSpan timeout, AsyncCallback callback, object state)360 internal override IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) 361 { 362 return new CloseAsyncResult(this, timeout, callback, state); 363 } 364 EndClose(IAsyncResult result)365 internal override void EndClose(IAsyncResult result) 366 { 367 CloseAsyncResult.End(result); 368 } 369 Close(TimeSpan timeout)370 internal override void Close(TimeSpan timeout) 371 { 372 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 373 base.Close(timeoutHelper.RemainingTime()); 374 SecurityUtils.CloseTokenProviderIfRequired(this.clientTokenProvider, timeoutHelper.RemainingTime()); 375 } 376 OnBeginInitiateUpgrade(Stream stream, AsyncCallback callback, object state)377 protected override IAsyncResult OnBeginInitiateUpgrade(Stream stream, AsyncCallback callback, object state) 378 { 379 if (TD.WindowsStreamSecurityOnInitiateUpgradeIsEnabled()) 380 { 381 TD.WindowsStreamSecurityOnInitiateUpgrade(); 382 } 383 384 InitiateUpgradeAsyncResult result = new InitiateUpgradeAsyncResult(this, callback, state); 385 result.Begin(stream); 386 return result; 387 } 388 OnEndInitiateUpgrade(IAsyncResult result, out SecurityMessageProperty remoteSecurity)389 protected override Stream OnEndInitiateUpgrade(IAsyncResult result, 390 out SecurityMessageProperty remoteSecurity) 391 { 392 return InitiateUpgradeAsyncResult.End(result, out remoteSecurity); 393 } 394 CreateServerSecurity(NegotiateStream negotiateStream)395 static SecurityMessageProperty CreateServerSecurity(NegotiateStream negotiateStream) 396 { 397 GenericIdentity remoteIdentity = (GenericIdentity)negotiateStream.RemoteIdentity; 398 string principalName = remoteIdentity.Name; 399 if ((principalName != null) && (principalName.Length > 0)) 400 { 401 ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = SecurityUtils.CreatePrincipalNameAuthorizationPolicies(principalName); 402 SecurityMessageProperty result = new SecurityMessageProperty(); 403 result.TransportToken = new SecurityTokenSpecification(null, authorizationPolicies); 404 result.ServiceSecurityContext = new ServiceSecurityContext(authorizationPolicies); 405 return result; 406 } 407 else 408 { 409 return null; 410 } 411 } 412 OnInitiateUpgrade(Stream stream, out SecurityMessageProperty remoteSecurity)413 protected override Stream OnInitiateUpgrade(Stream stream, 414 out SecurityMessageProperty remoteSecurity) 415 { 416 NegotiateStream negotiateStream; 417 string targetName; 418 EndpointIdentity identity; 419 420 if (TD.WindowsStreamSecurityOnInitiateUpgradeIsEnabled()) 421 { 422 TD.WindowsStreamSecurityOnInitiateUpgrade(); 423 } 424 425 // prepare 426 this.InitiateUpgradePrepare(stream, out negotiateStream, out targetName, out identity); 427 428 // authenticate 429 try 430 { 431 negotiateStream.AuthenticateAsClient(credential, targetName, parent.ProtectionLevel, impersonationLevel); 432 } 433 catch (AuthenticationException exception) 434 { 435 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(exception.Message, 436 exception)); 437 } 438 catch (IOException ioException) 439 { 440 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException( 441 SR.GetString(SR.NegotiationFailedIO, ioException.Message), ioException)); 442 } 443 444 remoteSecurity = CreateServerSecurity(negotiateStream); 445 this.ValidateMutualAuth(identity, negotiateStream, remoteSecurity, allowNtlm); 446 447 return negotiateStream; 448 } 449 InitiateUpgradePrepare( Stream stream, out NegotiateStream negotiateStream, out string targetName, out EndpointIdentity identity)450 void InitiateUpgradePrepare( 451 Stream stream, 452 out NegotiateStream negotiateStream, 453 out string targetName, 454 out EndpointIdentity identity) 455 { 456 negotiateStream = new NegotiateStream(stream); 457 458 targetName = string.Empty; 459 identity = null; 460 461 if (parent.IdentityVerifier.TryGetIdentity(this.RemoteAddress, this.Via, out identity)) 462 { 463 targetName = SecurityUtils.GetSpnFromIdentity(identity, this.RemoteAddress); 464 } 465 else 466 { 467 targetName = SecurityUtils.GetSpnFromTarget(this.RemoteAddress); 468 } 469 } 470 ValidateMutualAuth(EndpointIdentity expectedIdentity, NegotiateStream negotiateStream, SecurityMessageProperty remoteSecurity, bool allowNtlm)471 void ValidateMutualAuth(EndpointIdentity expectedIdentity, NegotiateStream negotiateStream, 472 SecurityMessageProperty remoteSecurity, bool allowNtlm) 473 { 474 if (negotiateStream.IsMutuallyAuthenticated) 475 { 476 if (expectedIdentity != null) 477 { 478 if (!parent.IdentityVerifier.CheckAccess(expectedIdentity, 479 remoteSecurity.ServiceSecurityContext.AuthorizationContext)) 480 { 481 string primaryIdentity = SecurityUtils.GetIdentityNamesFromContext(remoteSecurity.ServiceSecurityContext.AuthorizationContext); 482 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString( 483 SR.RemoteIdentityFailedVerification, primaryIdentity))); 484 } 485 } 486 } 487 else if (!allowNtlm) 488 { 489 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString( 490 SR.StreamMutualAuthNotSatisfied))); 491 } 492 } 493 494 class InitiateUpgradeAsyncResult : StreamSecurityUpgradeInitiatorAsyncResult 495 { 496 EndpointIdentity expectedIdentity; 497 WindowsStreamSecurityUpgradeInitiator initiator; 498 NegotiateStream negotiateStream; 499 InitiateUpgradeAsyncResult(WindowsStreamSecurityUpgradeInitiator initiator, AsyncCallback callback, object state)500 public InitiateUpgradeAsyncResult(WindowsStreamSecurityUpgradeInitiator initiator, 501 AsyncCallback callback, object state) 502 : base(callback, state) 503 { 504 this.initiator = initiator; 505 } 506 OnBeginAuthenticateAsClient(Stream stream, AsyncCallback callback)507 protected override IAsyncResult OnBeginAuthenticateAsClient(Stream stream, AsyncCallback callback) 508 { 509 string targetName; 510 this.initiator.InitiateUpgradePrepare(stream, out this.negotiateStream, out targetName, 511 out this.expectedIdentity); 512 513 return this.negotiateStream.BeginAuthenticateAsClient(this.initiator.credential, targetName, 514 this.initiator.parent.ProtectionLevel, this.initiator.impersonationLevel, callback, this); 515 } 516 OnCompleteAuthenticateAsClient(IAsyncResult result)517 protected override Stream OnCompleteAuthenticateAsClient(IAsyncResult result) 518 { 519 this.negotiateStream.EndAuthenticateAsClient(result); 520 return this.negotiateStream; 521 } 522 ValidateCreateSecurity()523 protected override SecurityMessageProperty ValidateCreateSecurity() 524 { 525 SecurityMessageProperty remoteSecurity = CreateServerSecurity(negotiateStream); 526 this.initiator.ValidateMutualAuth(this.expectedIdentity, this.negotiateStream, 527 remoteSecurity, this.initiator.allowNtlm); 528 return remoteSecurity; 529 } 530 } 531 532 class OpenAsyncResult : AsyncResult 533 { 534 WindowsStreamSecurityUpgradeInitiator parent; 535 TimeoutHelper timeoutHelper; 536 AsyncCallback onBaseOpen; 537 AsyncCallback onOpenTokenProvider; 538 AsyncCallback onGetSspiCredential; 539 OpenAsyncResult(WindowsStreamSecurityUpgradeInitiator parent, TimeSpan timeout, AsyncCallback callback, object state)540 public OpenAsyncResult(WindowsStreamSecurityUpgradeInitiator parent, TimeSpan timeout, 541 AsyncCallback callback, object state) 542 : base(callback, state) 543 { 544 this.parent = parent; 545 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 546 547 // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callback 548 this.onBaseOpen = Fx.ThunkCallback(new AsyncCallback(OnBaseOpen)); 549 this.onGetSspiCredential = Fx.ThunkCallback(new AsyncCallback(OnGetSspiCredential)); 550 this.onOpenTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnOpenTokenProvider)); 551 IAsyncResult result = parent.BaseBeginOpen(timeoutHelper.RemainingTime(), onBaseOpen, this); 552 553 if (!result.CompletedSynchronously) 554 { 555 return; 556 } 557 558 if (HandleBaseOpenComplete(result)) 559 { 560 base.Complete(true); 561 } 562 } 563 End(IAsyncResult result)564 public static void End(IAsyncResult result) 565 { 566 AsyncResult.End<OpenAsyncResult>(result); 567 } 568 HandleBaseOpenComplete(IAsyncResult result)569 bool HandleBaseOpenComplete(IAsyncResult result) 570 { 571 parent.BaseEndOpen(result); 572 IAsyncResult openTokenProviderResult = SecurityUtils.BeginOpenTokenProviderIfRequired( 573 parent.clientTokenProvider, timeoutHelper.RemainingTime(), onOpenTokenProvider, this); 574 575 if (!openTokenProviderResult.CompletedSynchronously) 576 { 577 return false; 578 } 579 580 return HandleOpenTokenProviderComplete(openTokenProviderResult); 581 } 582 HandleOpenTokenProviderComplete(IAsyncResult result)583 bool HandleOpenTokenProviderComplete(IAsyncResult result) 584 { 585 SecurityUtils.EndOpenTokenProviderIfRequired(result); 586 IAsyncResult getCredentialResult = TransportSecurityHelpers.BeginGetSspiCredential( 587 parent.clientTokenProvider, timeoutHelper.RemainingTime(), onGetSspiCredential, this); 588 589 if (!getCredentialResult.CompletedSynchronously) 590 { 591 return false; 592 } 593 594 return HandleGetSspiCredentialComplete(getCredentialResult); 595 } 596 HandleGetSspiCredentialComplete(IAsyncResult result)597 bool HandleGetSspiCredentialComplete(IAsyncResult result) 598 { 599 parent.credential = TransportSecurityHelpers.EndGetSspiCredential(result, 600 out parent.impersonationLevel, out parent.allowNtlm); 601 return true; 602 } 603 OnBaseOpen(IAsyncResult result)604 void OnBaseOpen(IAsyncResult result) 605 { 606 if (result.CompletedSynchronously) 607 { 608 return; 609 } 610 611 Exception completionException = null; 612 bool completeSelf = false; 613 try 614 { 615 completeSelf = this.HandleBaseOpenComplete(result); 616 } 617 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread 618 catch (Exception e) 619 { 620 if (Fx.IsFatal(e)) 621 { 622 throw; 623 } 624 625 completeSelf = true; 626 completionException = e; 627 } 628 629 if (completeSelf) 630 { 631 base.Complete(false, completionException); 632 } 633 } 634 OnOpenTokenProvider(IAsyncResult result)635 void OnOpenTokenProvider(IAsyncResult result) 636 { 637 if (result.CompletedSynchronously) 638 { 639 return; 640 } 641 642 Exception completionException = null; 643 bool completeSelf = false; 644 try 645 { 646 completeSelf = this.HandleOpenTokenProviderComplete(result); 647 } 648 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread 649 catch (Exception e) 650 { 651 if (Fx.IsFatal(e)) 652 { 653 throw; 654 } 655 656 completeSelf = true; 657 completionException = e; 658 } 659 660 if (completeSelf) 661 { 662 base.Complete(false, completionException); 663 } 664 } 665 OnGetSspiCredential(IAsyncResult result)666 void OnGetSspiCredential(IAsyncResult result) 667 { 668 if (result.CompletedSynchronously) 669 { 670 return; 671 } 672 673 Exception completionException = null; 674 bool completeSelf = false; 675 try 676 { 677 completeSelf = this.HandleGetSspiCredentialComplete(result); 678 } 679 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread 680 catch (Exception e) 681 { 682 if (Fx.IsFatal(e)) 683 { 684 throw; 685 } 686 687 completeSelf = true; 688 completionException = e; 689 } 690 691 if (completeSelf) 692 { 693 base.Complete(false, completionException); 694 } 695 } 696 } 697 698 class CloseAsyncResult : AsyncResult 699 { 700 WindowsStreamSecurityUpgradeInitiator parent; 701 TimeoutHelper timeoutHelper; 702 AsyncCallback onBaseClose; 703 AsyncCallback onCloseTokenProvider; 704 CloseAsyncResult(WindowsStreamSecurityUpgradeInitiator parent, TimeSpan timeout, AsyncCallback callback, object state)705 public CloseAsyncResult(WindowsStreamSecurityUpgradeInitiator parent, TimeSpan timeout, 706 AsyncCallback callback, object state) 707 : base(callback, state) 708 { 709 this.parent = parent; 710 this.timeoutHelper = new TimeoutHelper(timeout); 711 712 // since we're at channel.Open and not per-message, minimize our statics overhead and leverage GC for our callback 713 this.onBaseClose = Fx.ThunkCallback(new AsyncCallback(OnBaseClose)); 714 this.onCloseTokenProvider = Fx.ThunkCallback(new AsyncCallback(OnCloseTokenProvider)); 715 IAsyncResult result = parent.BaseBeginClose(timeoutHelper.RemainingTime(), onBaseClose, this); 716 717 if (!result.CompletedSynchronously) 718 { 719 return; 720 } 721 722 if (HandleBaseCloseComplete(result)) 723 { 724 base.Complete(true); 725 } 726 } 727 End(IAsyncResult result)728 public static void End(IAsyncResult result) 729 { 730 AsyncResult.End<CloseAsyncResult>(result); 731 } 732 HandleBaseCloseComplete(IAsyncResult result)733 bool HandleBaseCloseComplete(IAsyncResult result) 734 { 735 parent.BaseEndClose(result); 736 IAsyncResult closeTokenProviderResult = SecurityUtils.BeginCloseTokenProviderIfRequired( 737 parent.clientTokenProvider, timeoutHelper.RemainingTime(), onCloseTokenProvider, this); 738 739 if (!closeTokenProviderResult.CompletedSynchronously) 740 { 741 return false; 742 } 743 744 SecurityUtils.EndCloseTokenProviderIfRequired(closeTokenProviderResult); 745 return true; 746 } 747 OnBaseClose(IAsyncResult result)748 void OnBaseClose(IAsyncResult result) 749 { 750 if (result.CompletedSynchronously) 751 { 752 return; 753 } 754 755 Exception completionException = null; 756 bool completeSelf = false; 757 try 758 { 759 completeSelf = this.HandleBaseCloseComplete(result); 760 } 761 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread 762 catch (Exception e) 763 { 764 if (Fx.IsFatal(e)) 765 { 766 throw; 767 } 768 769 completeSelf = true; 770 completionException = e; 771 } 772 773 if (completeSelf) 774 { 775 base.Complete(false, completionException); 776 } 777 } 778 OnCloseTokenProvider(IAsyncResult result)779 void OnCloseTokenProvider(IAsyncResult result) 780 { 781 if (result.CompletedSynchronously) 782 { 783 return; 784 } 785 786 Exception completionException = null; 787 try 788 { 789 SecurityUtils.EndCloseTokenProviderIfRequired(result); 790 } 791 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread 792 catch (Exception e) 793 { 794 if (Fx.IsFatal(e)) 795 { 796 throw; 797 } 798 799 completionException = e; 800 } 801 802 base.Complete(false, completionException); 803 } 804 } 805 } 806 } 807 } 808