WindowsStreamSecurityUpgradeProvider.cs 32 KB

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