SecuritySessionSecurityTokenProvider.cs 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Collections.ObjectModel;
  7. using System.Diagnostics;
  8. using System.IdentityModel.Policy;
  9. using System.IdentityModel.Tokens;
  10. using System.Runtime;
  11. using System.Runtime.Diagnostics;
  12. using System.Security.Authentication.ExtendedProtection;
  13. using System.ServiceModel;
  14. using System.ServiceModel.Channels;
  15. using System.ServiceModel.Diagnostics;
  16. using System.ServiceModel.Diagnostics.Application;
  17. using System.ServiceModel.Description;
  18. using System.ServiceModel.Dispatcher;
  19. using System.ServiceModel.Security.Tokens;
  20. using System.Net;
  21. using System.Xml;
  22. using SafeFreeCredentials = System.IdentityModel.SafeFreeCredentials;
  23. class SecuritySessionSecurityTokenProvider : CommunicationObjectSecurityTokenProvider
  24. {
  25. static readonly MessageOperationFormatter operationFormatter = new MessageOperationFormatter();
  26. BindingContext issuerBindingContext;
  27. IChannelFactory<IRequestChannel> rstChannelFactory;
  28. SecurityAlgorithmSuite securityAlgorithmSuite;
  29. SecurityStandardsManager standardsManager;
  30. Object thisLock = new Object();
  31. SecurityKeyEntropyMode keyEntropyMode;
  32. SecurityTokenParameters issuedTokenParameters;
  33. bool requiresManualReplyAddressing;
  34. EndpointAddress targetAddress;
  35. SecurityBindingElement bootstrapSecurityBindingElement;
  36. Uri via;
  37. string sctUri;
  38. Uri privacyNoticeUri;
  39. int privacyNoticeVersion;
  40. MessageVersion messageVersion;
  41. EndpointAddress localAddress;
  42. ChannelParameterCollection channelParameters;
  43. SafeFreeCredentials credentialsHandle;
  44. bool ownCredentialsHandle;
  45. WebHeaderCollection webHeaderCollection;
  46. public SecuritySessionSecurityTokenProvider(SafeFreeCredentials credentialsHandle)
  47. : base()
  48. {
  49. this.credentialsHandle = credentialsHandle;
  50. this.standardsManager = SecurityStandardsManager.DefaultInstance;
  51. this.keyEntropyMode = AcceleratedTokenProvider.defaultKeyEntropyMode;
  52. }
  53. public WebHeaderCollection WebHeaders
  54. {
  55. get
  56. {
  57. return this.webHeaderCollection;
  58. }
  59. set
  60. {
  61. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  62. this.webHeaderCollection = value;
  63. }
  64. }
  65. public SecurityAlgorithmSuite SecurityAlgorithmSuite
  66. {
  67. get
  68. {
  69. return this.securityAlgorithmSuite;
  70. }
  71. set
  72. {
  73. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  74. this.securityAlgorithmSuite = value;
  75. }
  76. }
  77. public SecurityKeyEntropyMode KeyEntropyMode
  78. {
  79. get
  80. {
  81. return this.keyEntropyMode;
  82. }
  83. set
  84. {
  85. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  86. SecurityKeyEntropyModeHelper.Validate(value);
  87. this.keyEntropyMode = value;
  88. }
  89. }
  90. MessageVersion MessageVersion
  91. {
  92. get
  93. {
  94. return this.messageVersion;
  95. }
  96. }
  97. public EndpointAddress TargetAddress
  98. {
  99. get { return this.targetAddress; }
  100. set
  101. {
  102. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  103. this.targetAddress = value;
  104. }
  105. }
  106. public EndpointAddress LocalAddress
  107. {
  108. get { return this.localAddress; }
  109. set
  110. {
  111. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  112. this.localAddress = value;
  113. }
  114. }
  115. public Uri Via
  116. {
  117. get { return this.via; }
  118. set
  119. {
  120. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  121. this.via = value;
  122. }
  123. }
  124. public BindingContext IssuerBindingContext
  125. {
  126. get
  127. {
  128. return this.issuerBindingContext;
  129. }
  130. set
  131. {
  132. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  133. if (value == null)
  134. {
  135. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  136. }
  137. this.issuerBindingContext = value.Clone();
  138. }
  139. }
  140. public SecurityBindingElement BootstrapSecurityBindingElement
  141. {
  142. get { return this.bootstrapSecurityBindingElement; }
  143. set
  144. {
  145. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  146. if (value == null)
  147. {
  148. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  149. }
  150. this.bootstrapSecurityBindingElement = (SecurityBindingElement)value.Clone();
  151. }
  152. }
  153. public SecurityStandardsManager StandardsManager
  154. {
  155. get
  156. {
  157. return this.standardsManager;
  158. }
  159. set
  160. {
  161. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  162. if (value == null)
  163. {
  164. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
  165. }
  166. if (!value.TrustDriver.IsSessionSupported)
  167. {
  168. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.TrustDriverVersionDoesNotSupportSession), "value"));
  169. }
  170. if (!value.SecureConversationDriver.IsSessionSupported)
  171. {
  172. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SecureConversationDriverVersionDoesNotSupportSession), "value"));
  173. }
  174. this.standardsManager = value;
  175. }
  176. }
  177. public SecurityTokenParameters IssuedSecurityTokenParameters
  178. {
  179. get
  180. {
  181. return this.issuedTokenParameters;
  182. }
  183. set
  184. {
  185. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  186. this.issuedTokenParameters = value;
  187. }
  188. }
  189. public Uri PrivacyNoticeUri
  190. {
  191. get { return this.privacyNoticeUri; }
  192. set
  193. {
  194. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  195. this.privacyNoticeUri = value;
  196. }
  197. }
  198. public ChannelParameterCollection ChannelParameters
  199. {
  200. get { return this.channelParameters; }
  201. set
  202. {
  203. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  204. this.channelParameters = value;
  205. }
  206. }
  207. public int PrivacyNoticeVersion
  208. {
  209. get { return this.privacyNoticeVersion; }
  210. set
  211. {
  212. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  213. this.privacyNoticeVersion = value;
  214. }
  215. }
  216. public virtual XmlDictionaryString IssueAction
  217. {
  218. get
  219. {
  220. return this.standardsManager.SecureConversationDriver.IssueAction;
  221. }
  222. }
  223. public virtual XmlDictionaryString IssueResponseAction
  224. {
  225. get
  226. {
  227. return this.standardsManager.SecureConversationDriver.IssueResponseAction;
  228. }
  229. }
  230. public virtual XmlDictionaryString RenewAction
  231. {
  232. get
  233. {
  234. return this.standardsManager.SecureConversationDriver.RenewAction;
  235. }
  236. }
  237. public virtual XmlDictionaryString RenewResponseAction
  238. {
  239. get
  240. {
  241. return this.standardsManager.SecureConversationDriver.RenewResponseAction;
  242. }
  243. }
  244. public virtual XmlDictionaryString CloseAction
  245. {
  246. get
  247. {
  248. return standardsManager.SecureConversationDriver.CloseAction;
  249. }
  250. }
  251. public virtual XmlDictionaryString CloseResponseAction
  252. {
  253. get
  254. {
  255. return standardsManager.SecureConversationDriver.CloseResponseAction;
  256. }
  257. }
  258. // ISecurityCommunicationObject methods
  259. public override void OnAbort()
  260. {
  261. if (this.rstChannelFactory != null)
  262. {
  263. this.rstChannelFactory.Abort();
  264. this.rstChannelFactory = null;
  265. }
  266. FreeCredentialsHandle();
  267. }
  268. public override void OnOpen(TimeSpan timeout)
  269. {
  270. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  271. if (this.targetAddress == null)
  272. {
  273. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TargetAddressIsNotSet, this.GetType())));
  274. }
  275. if (this.IssuerBindingContext == null)
  276. {
  277. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.IssuerBuildContextNotSet, this.GetType())));
  278. }
  279. if (this.IssuedSecurityTokenParameters == null)
  280. {
  281. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.IssuedSecurityTokenParametersNotSet, this.GetType())));
  282. }
  283. if (this.BootstrapSecurityBindingElement == null)
  284. {
  285. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BootstrapSecurityBindingElementNotSet, this.GetType())));
  286. }
  287. if (this.SecurityAlgorithmSuite == null)
  288. {
  289. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityAlgorithmSuiteNotSet, this.GetType())));
  290. }
  291. InitializeFactories();
  292. this.rstChannelFactory.Open(timeoutHelper.RemainingTime());
  293. this.sctUri = this.StandardsManager.SecureConversationDriver.TokenTypeUri;
  294. }
  295. public override void OnOpening()
  296. {
  297. base.OnOpening();
  298. if (this.credentialsHandle == null)
  299. {
  300. if (this.IssuerBindingContext == null)
  301. {
  302. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.IssuerBuildContextNotSet, this.GetType())));
  303. }
  304. if (this.BootstrapSecurityBindingElement == null)
  305. {
  306. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BootstrapSecurityBindingElementNotSet, this.GetType())));
  307. }
  308. this.credentialsHandle = SecurityUtils.GetCredentialsHandle(this.bootstrapSecurityBindingElement, this.issuerBindingContext);
  309. this.ownCredentialsHandle = true;
  310. }
  311. }
  312. public override void OnClose(TimeSpan timeout)
  313. {
  314. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  315. if (this.rstChannelFactory != null)
  316. {
  317. this.rstChannelFactory.Close(timeoutHelper.RemainingTime());
  318. this.rstChannelFactory = null;
  319. }
  320. FreeCredentialsHandle();
  321. }
  322. void FreeCredentialsHandle()
  323. {
  324. if (this.credentialsHandle != null)
  325. {
  326. if (this.ownCredentialsHandle)
  327. {
  328. this.credentialsHandle.Close();
  329. }
  330. this.credentialsHandle = null;
  331. }
  332. }
  333. void InitializeFactories()
  334. {
  335. ISecurityCapabilities securityCapabilities = this.BootstrapSecurityBindingElement.GetProperty<ISecurityCapabilities>(this.IssuerBindingContext);
  336. SecurityCredentialsManager securityCredentials = this.IssuerBindingContext.BindingParameters.Find<SecurityCredentialsManager>();
  337. if (securityCredentials == null)
  338. {
  339. securityCredentials = ClientCredentials.CreateDefaultCredentials();
  340. }
  341. BindingContext context = this.IssuerBindingContext;
  342. this.bootstrapSecurityBindingElement.ReaderQuotas = context.GetInnerProperty<XmlDictionaryReaderQuotas>();
  343. if (this.bootstrapSecurityBindingElement.ReaderQuotas == null)
  344. {
  345. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EncodingBindingElementDoesNotHandleReaderQuotas)));
  346. }
  347. TransportBindingElement transportBindingElement = context.RemainingBindingElements.Find<TransportBindingElement>();
  348. if (transportBindingElement != null)
  349. this.bootstrapSecurityBindingElement.MaxReceivedMessageSize = transportBindingElement.MaxReceivedMessageSize;
  350. SecurityProtocolFactory securityProtocolFactory = this.BootstrapSecurityBindingElement.CreateSecurityProtocolFactory<IRequestChannel>(this.IssuerBindingContext.Clone(), securityCredentials, false, this.IssuerBindingContext.Clone());
  351. if (securityProtocolFactory is MessageSecurityProtocolFactory)
  352. {
  353. MessageSecurityProtocolFactory soapBindingFactory = securityProtocolFactory as MessageSecurityProtocolFactory;
  354. soapBindingFactory.ApplyConfidentiality = soapBindingFactory.ApplyIntegrity
  355. = soapBindingFactory.RequireConfidentiality = soapBindingFactory.RequireIntegrity = true;
  356. soapBindingFactory.ProtectionRequirements.IncomingSignatureParts.ChannelParts.IsBodyIncluded = true;
  357. soapBindingFactory.ProtectionRequirements.OutgoingSignatureParts.ChannelParts.IsBodyIncluded = true;
  358. MessagePartSpecification bodyPart = new MessagePartSpecification(true);
  359. soapBindingFactory.ProtectionRequirements.IncomingSignatureParts.AddParts(bodyPart, IssueAction);
  360. soapBindingFactory.ProtectionRequirements.IncomingEncryptionParts.AddParts(bodyPart, IssueAction);
  361. soapBindingFactory.ProtectionRequirements.IncomingSignatureParts.AddParts(bodyPart, RenewAction);
  362. soapBindingFactory.ProtectionRequirements.IncomingEncryptionParts.AddParts(bodyPart, RenewAction);
  363. soapBindingFactory.ProtectionRequirements.OutgoingSignatureParts.AddParts(bodyPart, IssueResponseAction);
  364. soapBindingFactory.ProtectionRequirements.OutgoingEncryptionParts.AddParts(bodyPart, IssueResponseAction);
  365. soapBindingFactory.ProtectionRequirements.OutgoingSignatureParts.AddParts(bodyPart, RenewResponseAction);
  366. soapBindingFactory.ProtectionRequirements.OutgoingEncryptionParts.AddParts(bodyPart, RenewResponseAction);
  367. }
  368. securityProtocolFactory.PrivacyNoticeUri = this.PrivacyNoticeUri;
  369. securityProtocolFactory.PrivacyNoticeVersion = this.privacyNoticeVersion;
  370. if (this.localAddress != null)
  371. {
  372. MessageFilter issueAndRenewFilter = new SessionActionFilter(this.standardsManager, this.IssueResponseAction.Value, this.RenewResponseAction.Value);
  373. context.BindingParameters.Add(new LocalAddressProvider(localAddress, issueAndRenewFilter));
  374. }
  375. ChannelBuilder channelBuilder = new ChannelBuilder(context, true);
  376. IChannelFactory<IRequestChannel> innerChannelFactory;
  377. // if the underlying transport does not support request/reply, wrap it inside
  378. // a service channel factory.
  379. if (channelBuilder.CanBuildChannelFactory<IRequestChannel>())
  380. {
  381. innerChannelFactory = channelBuilder.BuildChannelFactory<IRequestChannel>();
  382. requiresManualReplyAddressing = true;
  383. }
  384. else
  385. {
  386. ClientRuntime clientRuntime = new ClientRuntime("RequestSecuritySession", NamingHelper.DefaultNamespace);
  387. clientRuntime.UseSynchronizationContext = false;
  388. clientRuntime.AddTransactionFlowProperties = false;
  389. clientRuntime.ValidateMustUnderstand = false;
  390. ServiceChannelFactory serviceChannelFactory = ServiceChannelFactory.BuildChannelFactory(channelBuilder, clientRuntime);
  391. ClientOperation issueOperation = new ClientOperation(serviceChannelFactory.ClientRuntime, "Issue", IssueAction.Value);
  392. issueOperation.Formatter = operationFormatter;
  393. serviceChannelFactory.ClientRuntime.Operations.Add(issueOperation);
  394. ClientOperation renewOperation = new ClientOperation(serviceChannelFactory.ClientRuntime, "Renew", RenewAction.Value);
  395. renewOperation.Formatter = operationFormatter;
  396. serviceChannelFactory.ClientRuntime.Operations.Add(renewOperation);
  397. innerChannelFactory = new RequestChannelFactory(serviceChannelFactory);
  398. requiresManualReplyAddressing = false;
  399. }
  400. SecurityChannelFactory<IRequestChannel> securityChannelFactory = new SecurityChannelFactory<IRequestChannel>(
  401. securityCapabilities, this.IssuerBindingContext, channelBuilder, securityProtocolFactory, innerChannelFactory);
  402. // attach the ExtendedProtectionPolicy to the securityProtcolFactory so it will be
  403. // available when building the channel.
  404. if (transportBindingElement != null)
  405. {
  406. if (securityChannelFactory.SecurityProtocolFactory != null)
  407. {
  408. securityChannelFactory.SecurityProtocolFactory.ExtendedProtectionPolicy = transportBindingElement.GetProperty<ExtendedProtectionPolicy>(context);
  409. }
  410. }
  411. this.rstChannelFactory = securityChannelFactory;
  412. this.messageVersion = securityChannelFactory.MessageVersion;
  413. }
  414. // token provider methods
  415. protected override IAsyncResult BeginGetTokenCore(TimeSpan timeout, AsyncCallback callback, object state)
  416. {
  417. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  418. return new SessionOperationAsyncResult(this, SecuritySessionOperation.Issue, this.TargetAddress, this.Via, null, timeout, callback, state);
  419. }
  420. protected override SecurityToken EndGetTokenCore(IAsyncResult result)
  421. {
  422. return SessionOperationAsyncResult.End(result);
  423. }
  424. protected override SecurityToken GetTokenCore(TimeSpan timeout)
  425. {
  426. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  427. return this.DoOperation(SecuritySessionOperation.Issue, this.targetAddress, this.via, null, timeout);
  428. }
  429. protected override IAsyncResult BeginRenewTokenCore(TimeSpan timeout, SecurityToken tokenToBeRenewed, AsyncCallback callback, object state)
  430. {
  431. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  432. return new SessionOperationAsyncResult(this, SecuritySessionOperation.Renew, this.TargetAddress, this.Via, tokenToBeRenewed, timeout, callback, state);
  433. }
  434. protected override SecurityToken EndRenewTokenCore(IAsyncResult result)
  435. {
  436. return SessionOperationAsyncResult.End(result);
  437. }
  438. protected override SecurityToken RenewTokenCore(TimeSpan timeout, SecurityToken tokenToBeRenewed)
  439. {
  440. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  441. return this.DoOperation(SecuritySessionOperation.Renew, this.targetAddress, this.via, tokenToBeRenewed, timeout);
  442. }
  443. IRequestChannel CreateChannel(SecuritySessionOperation operation, EndpointAddress target, Uri via)
  444. {
  445. IChannelFactory<IRequestChannel> cf;
  446. if (operation == SecuritySessionOperation.Issue || operation == SecuritySessionOperation.Renew)
  447. {
  448. cf = this.rstChannelFactory;
  449. }
  450. else
  451. {
  452. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  453. }
  454. IRequestChannel channel;
  455. if (via != null)
  456. {
  457. channel = cf.CreateChannel(target, via);
  458. }
  459. else
  460. {
  461. channel = cf.CreateChannel(target);
  462. }
  463. if (this.channelParameters != null)
  464. {
  465. this.channelParameters.PropagateChannelParameters(channel);
  466. }
  467. if (this.ownCredentialsHandle)
  468. {
  469. ChannelParameterCollection newParameters = channel.GetProperty<ChannelParameterCollection>();
  470. if (newParameters != null)
  471. {
  472. newParameters.Add(new SspiIssuanceChannelParameter(true, this.credentialsHandle));
  473. }
  474. }
  475. return channel;
  476. }
  477. Message CreateRequest(SecuritySessionOperation operation, EndpointAddress target, SecurityToken currentToken, out object requestState)
  478. {
  479. if (operation == SecuritySessionOperation.Issue)
  480. {
  481. return this.CreateIssueRequest(target, out requestState);
  482. }
  483. else if (operation == SecuritySessionOperation.Renew)
  484. {
  485. return this.CreateRenewRequest(target, currentToken, out requestState);
  486. }
  487. else
  488. {
  489. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  490. }
  491. }
  492. GenericXmlSecurityToken ProcessReply(Message reply, SecuritySessionOperation operation, object requestState)
  493. {
  494. ThrowIfFault(reply, this.targetAddress);
  495. GenericXmlSecurityToken issuedToken = null;
  496. if (operation == SecuritySessionOperation.Issue)
  497. {
  498. issuedToken = this.ProcessIssueResponse(reply, requestState);
  499. }
  500. else if (operation == SecuritySessionOperation.Renew)
  501. {
  502. issuedToken = this.ProcessRenewResponse(reply, requestState);
  503. }
  504. return issuedToken;
  505. }
  506. void OnOperationSuccess(SecuritySessionOperation operation, EndpointAddress target, SecurityToken issuedToken, SecurityToken currentToken)
  507. {
  508. SecurityTraceRecordHelper.TraceSecuritySessionOperationSuccess(operation, target, currentToken, issuedToken);
  509. }
  510. void OnOperationFailure(SecuritySessionOperation operation, EndpointAddress target, SecurityToken currentToken, Exception e, IChannel channel)
  511. {
  512. SecurityTraceRecordHelper.TraceSecuritySessionOperationFailure(operation, target, currentToken, e);
  513. if (channel != null)
  514. {
  515. channel.Abort();
  516. }
  517. }
  518. GenericXmlSecurityToken DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
  519. {
  520. if (target == null)
  521. {
  522. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("target");
  523. }
  524. if (operation == SecuritySessionOperation.Renew && currentToken == null)
  525. {
  526. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("currentToken");
  527. }
  528. IRequestChannel channel = null;
  529. try
  530. {
  531. SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken);
  532. channel = this.CreateChannel(operation, target, via);
  533. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  534. channel.Open(timeoutHelper.RemainingTime());
  535. object requestState;
  536. GenericXmlSecurityToken issuedToken;
  537. using (Message requestMessage = this.CreateRequest(operation, target, currentToken, out requestState))
  538. {
  539. EventTraceActivity eventTraceActivity = null;
  540. if (TD.MessageReceivedFromTransportIsEnabled())
  541. {
  542. eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(requestMessage);
  543. }
  544. TraceUtility.ProcessOutgoingMessage(requestMessage, eventTraceActivity);
  545. using (Message reply = channel.Request(requestMessage, timeoutHelper.RemainingTime()))
  546. {
  547. if (reply == null)
  548. {
  549. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation)));
  550. }
  551. if (eventTraceActivity == null && TD.MessageReceivedFromTransportIsEnabled())
  552. {
  553. eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(reply);
  554. }
  555. TraceUtility.ProcessIncomingMessage(reply, eventTraceActivity);
  556. ThrowIfFault(reply, this.targetAddress);
  557. issuedToken = ProcessReply(reply, operation, requestState);
  558. ValidateKeySize(issuedToken);
  559. }
  560. }
  561. channel.Close(timeoutHelper.RemainingTime());
  562. this.OnOperationSuccess(operation, target, issuedToken, currentToken);
  563. return issuedToken;
  564. }
  565. catch (Exception e)
  566. {
  567. if (Fx.IsFatal(e))
  568. throw;
  569. if (e is TimeoutException)
  570. {
  571. e = new TimeoutException(SR.GetString(SR.ClientSecuritySessionRequestTimeout, timeout), e);
  572. }
  573. OnOperationFailure(operation, target, currentToken, e, channel);
  574. throw;
  575. }
  576. }
  577. byte[] GenerateEntropy(int entropySize)
  578. {
  579. byte[] result = DiagnosticUtility.Utility.AllocateByteArray(entropySize / 8);
  580. CryptoHelper.FillRandomBytes(result);
  581. return result;
  582. }
  583. RequestSecurityToken CreateRst(EndpointAddress target, out object requestState)
  584. {
  585. RequestSecurityToken rst = new RequestSecurityToken(this.standardsManager);
  586. //rst.SetAppliesTo<EndpointAddress>(target, new XmlFormatter());
  587. rst.KeySize = this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength;
  588. rst.TokenType = this.sctUri;
  589. if (this.KeyEntropyMode == SecurityKeyEntropyMode.ClientEntropy || this.KeyEntropyMode == SecurityKeyEntropyMode.CombinedEntropy)
  590. {
  591. byte[] entropy = GenerateEntropy(rst.KeySize);
  592. rst.SetRequestorEntropy(entropy);
  593. requestState = entropy;
  594. }
  595. else
  596. {
  597. requestState = null;
  598. }
  599. return rst;
  600. }
  601. void PrepareRequest(Message message)
  602. {
  603. RequestReplyCorrelator.PrepareRequest(message);
  604. if (this.requiresManualReplyAddressing)
  605. {
  606. if (this.localAddress != null)
  607. {
  608. message.Headers.ReplyTo = this.LocalAddress;
  609. }
  610. else
  611. {
  612. message.Headers.ReplyTo = EndpointAddress.AnonymousAddress;
  613. }
  614. }
  615. if (this.webHeaderCollection != null && this.webHeaderCollection.Count > 0)
  616. {
  617. object prop = null;
  618. HttpRequestMessageProperty rmp = null;
  619. if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out prop))
  620. {
  621. rmp = prop as HttpRequestMessageProperty;
  622. }
  623. else
  624. {
  625. rmp = new HttpRequestMessageProperty();
  626. message.Properties.Add(HttpRequestMessageProperty.Name, rmp);
  627. }
  628. if (rmp != null && rmp.Headers != null)
  629. {
  630. rmp.Headers.Add(this.webHeaderCollection);
  631. }
  632. }
  633. }
  634. protected virtual Message CreateIssueRequest(EndpointAddress target, out object requestState)
  635. {
  636. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  637. RequestSecurityToken rst = CreateRst(target, out requestState);
  638. rst.RequestType = this.StandardsManager.TrustDriver.RequestTypeIssue;
  639. rst.MakeReadOnly();
  640. Message result = Message.CreateMessage(this.MessageVersion, ActionHeader.Create(this.IssueAction, this.MessageVersion.Addressing), rst);
  641. PrepareRequest(result);
  642. return result;
  643. }
  644. GenericXmlSecurityToken ExtractToken(Message response, object requestState)
  645. {
  646. // get the claims corresponding to the server
  647. SecurityMessageProperty serverContextProperty = response.Properties.Security;
  648. ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies;
  649. if (serverContextProperty != null && serverContextProperty.ServiceSecurityContext != null)
  650. {
  651. authorizationPolicies = serverContextProperty.ServiceSecurityContext.AuthorizationPolicies;
  652. }
  653. else
  654. {
  655. authorizationPolicies = EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
  656. }
  657. RequestSecurityTokenResponse rstr = null;
  658. XmlDictionaryReader bodyReader = response.GetReaderAtBodyContents();
  659. using (bodyReader)
  660. {
  661. if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
  662. rstr = this.StandardsManager.TrustDriver.CreateRequestSecurityTokenResponse(bodyReader);
  663. else if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrust13)
  664. {
  665. RequestSecurityTokenResponseCollection rstrc = this.StandardsManager.TrustDriver.CreateRequestSecurityTokenResponseCollection(bodyReader);
  666. foreach (RequestSecurityTokenResponse rstrItem in rstrc.RstrCollection)
  667. {
  668. if (rstr != null)
  669. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.MoreThanOneRSTRInRSTRC)));
  670. rstr = rstrItem;
  671. }
  672. }
  673. else
  674. {
  675. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  676. }
  677. response.ReadFromBodyContentsToEnd(bodyReader);
  678. }
  679. byte[] requestorEntropy;
  680. if (requestState != null)
  681. {
  682. requestorEntropy = (byte[])requestState;
  683. }
  684. else
  685. {
  686. requestorEntropy = null;
  687. }
  688. GenericXmlSecurityToken issuedToken = rstr.GetIssuedToken(null, null, this.KeyEntropyMode, requestorEntropy, this.sctUri, authorizationPolicies, this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength, false);
  689. return issuedToken;
  690. }
  691. protected virtual GenericXmlSecurityToken ProcessIssueResponse(Message response, object requestState)
  692. {
  693. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  694. return ExtractToken(response, requestState);
  695. }
  696. protected virtual Message CreateRenewRequest(EndpointAddress target, SecurityToken currentSessionToken, out object requestState)
  697. {
  698. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  699. RequestSecurityToken rst = CreateRst(target, out requestState);
  700. rst.RequestType = this.StandardsManager.TrustDriver.RequestTypeRenew;
  701. rst.RenewTarget = this.IssuedSecurityTokenParameters.CreateKeyIdentifierClause(currentSessionToken, SecurityTokenReferenceStyle.External);
  702. rst.MakeReadOnly();
  703. Message result = Message.CreateMessage(this.MessageVersion, ActionHeader.Create(this.RenewAction, this.MessageVersion.Addressing), rst);
  704. SecurityMessageProperty supportingTokenProperty = new SecurityMessageProperty();
  705. supportingTokenProperty.OutgoingSupportingTokens.Add(new SupportingTokenSpecification(currentSessionToken, EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance, SecurityTokenAttachmentMode.Endorsing, this.IssuedSecurityTokenParameters));
  706. result.Properties.Security = supportingTokenProperty;
  707. PrepareRequest(result);
  708. return result;
  709. }
  710. protected virtual GenericXmlSecurityToken ProcessRenewResponse(Message response, object requestState)
  711. {
  712. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  713. if (response.Headers.Action != this.RenewResponseAction.Value)
  714. {
  715. throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidRenewResponseAction, response.Headers.Action)), response);
  716. }
  717. return ExtractToken(response, requestState);
  718. }
  719. static protected void ThrowIfFault(Message message, EndpointAddress target)
  720. {
  721. SecurityUtils.ThrowIfNegotiationFault(message, target);
  722. }
  723. protected void ValidateKeySize(GenericXmlSecurityToken issuedToken)
  724. {
  725. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  726. ReadOnlyCollection<SecurityKey> issuedKeys = issuedToken.SecurityKeys;
  727. if (issuedKeys != null && issuedKeys.Count == 1)
  728. {
  729. SymmetricSecurityKey symmetricKey = issuedKeys[0] as SymmetricSecurityKey;
  730. if (symmetricKey != null)
  731. {
  732. if (this.SecurityAlgorithmSuite.IsSymmetricKeyLengthSupported(symmetricKey.KeySize))
  733. {
  734. return;
  735. }
  736. else
  737. {
  738. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidIssuedTokenKeySize, symmetricKey.KeySize)));
  739. }
  740. }
  741. }
  742. else
  743. {
  744. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.CannotObtainIssuedTokenKeySize)));
  745. }
  746. }
  747. class SessionOperationAsyncResult : AsyncResult
  748. {
  749. static AsyncCallback openChannelCallback = Fx.ThunkCallback(new AsyncCallback(OpenChannelCallback));
  750. static AsyncCallback closeChannelCallback = Fx.ThunkCallback(new AsyncCallback(CloseChannelCallback));
  751. SecuritySessionSecurityTokenProvider requestor;
  752. SecuritySessionOperation operation;
  753. EndpointAddress target;
  754. Uri via;
  755. SecurityToken currentToken;
  756. GenericXmlSecurityToken issuedToken;
  757. IRequestChannel channel;
  758. TimeoutHelper timeoutHelper;
  759. public SessionOperationAsyncResult(SecuritySessionSecurityTokenProvider requestor, SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout, AsyncCallback callback, object state)
  760. : base(callback, state)
  761. {
  762. this.requestor = requestor;
  763. this.operation = operation;
  764. this.target = target;
  765. this.via = via;
  766. this.currentToken = currentToken;
  767. this.timeoutHelper = new TimeoutHelper(timeout);
  768. SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken);
  769. bool completeSelf = false;
  770. try
  771. {
  772. completeSelf = this.StartOperation();
  773. }
  774. #pragma warning suppress 56500 // covered by FxCOP
  775. catch (Exception e)
  776. {
  777. if (Fx.IsFatal(e))
  778. throw;
  779. this.OnOperationFailure(e);
  780. throw;
  781. }
  782. if (completeSelf)
  783. {
  784. this.OnOperationComplete();
  785. Complete(true);
  786. }
  787. }
  788. /*
  789. * Session issuance/renewal consists of the following steps (some may be async):
  790. * 1. Create a channel ([....])
  791. * 2. Open the channel (async)
  792. * 3. Create the request to send to server ([....])
  793. * 4. Send the message and get reply (async)
  794. * 5. Process the reply to get the token
  795. * 6. Close the channel (async) and complete the async result
  796. */
  797. bool StartOperation()
  798. {
  799. this.channel = this.requestor.CreateChannel(this.operation, this.target, this.via);
  800. IAsyncResult result = this.channel.BeginOpen(this.timeoutHelper.RemainingTime(), openChannelCallback, this);
  801. if (!result.CompletedSynchronously)
  802. {
  803. return false;
  804. }
  805. this.channel.EndOpen(result);
  806. return this.OnChannelOpened();
  807. }
  808. static void OpenChannelCallback(IAsyncResult result)
  809. {
  810. if (result.CompletedSynchronously)
  811. {
  812. return;
  813. }
  814. SessionOperationAsyncResult self = (SessionOperationAsyncResult)result.AsyncState;
  815. bool completeSelf = false;
  816. Exception completionException = null;
  817. try
  818. {
  819. self.channel.EndOpen(result);
  820. completeSelf = self.OnChannelOpened();
  821. if (completeSelf)
  822. {
  823. self.OnOperationComplete();
  824. }
  825. }
  826. #pragma warning suppress 56500 // covered by FxCOP
  827. catch (Exception e)
  828. {
  829. if (Fx.IsFatal(e))
  830. throw;
  831. completeSelf = true;
  832. completionException = e;
  833. self.OnOperationFailure(completionException);
  834. }
  835. if (completeSelf)
  836. {
  837. self.Complete(false, completionException);
  838. }
  839. }
  840. bool OnChannelOpened()
  841. {
  842. object requestState;
  843. Message requestMessage = this.requestor.CreateRequest(this.operation, this.target, this.currentToken, out requestState);
  844. if (requestMessage == null)
  845. {
  846. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NullSessionRequestMessage, this.operation.ToString())));
  847. }
  848. ChannelOpenAsyncResultWrapper wrapper = new ChannelOpenAsyncResultWrapper();
  849. wrapper.Message = requestMessage;
  850. wrapper.RequestState = requestState;
  851. bool closeMessage = true;
  852. try
  853. {
  854. IAsyncResult result = this.channel.BeginRequest(requestMessage, this.timeoutHelper.RemainingTime(), Fx.ThunkCallback(new AsyncCallback(this.RequestCallback)), wrapper);
  855. if (!result.CompletedSynchronously)
  856. {
  857. closeMessage = false;
  858. return false;
  859. }
  860. Message reply = this.channel.EndRequest(result);
  861. return this.OnReplyReceived(reply, requestState);
  862. }
  863. finally
  864. {
  865. if (closeMessage)
  866. {
  867. wrapper.Message.Close();
  868. }
  869. }
  870. }
  871. void RequestCallback(IAsyncResult result)
  872. {
  873. if (result.CompletedSynchronously)
  874. {
  875. return;
  876. }
  877. ChannelOpenAsyncResultWrapper wrapper = (ChannelOpenAsyncResultWrapper)result.AsyncState;
  878. object requestState = wrapper.RequestState;
  879. bool completeSelf = false;
  880. Exception completionException = null;
  881. try
  882. {
  883. Message reply = this.channel.EndRequest(result);
  884. completeSelf = this.OnReplyReceived(reply, requestState);
  885. if (completeSelf)
  886. {
  887. this.OnOperationComplete();
  888. }
  889. }
  890. #pragma warning suppress 56500 // covered by FxCOP
  891. catch (Exception e)
  892. {
  893. if (Fx.IsFatal(e))
  894. throw;
  895. completeSelf = true;
  896. completionException = e;
  897. this.OnOperationFailure(e);
  898. }
  899. finally
  900. {
  901. if (wrapper.Message != null)
  902. wrapper.Message.Close();
  903. }
  904. if (completeSelf)
  905. {
  906. Complete(false, completionException);
  907. }
  908. }
  909. bool OnReplyReceived(Message reply, object requestState)
  910. {
  911. if (reply == null)
  912. {
  913. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation)));
  914. }
  915. using (reply)
  916. {
  917. this.issuedToken = this.requestor.ProcessReply(reply, this.operation, requestState);
  918. this.requestor.ValidateKeySize(this.issuedToken);
  919. }
  920. return this.OnReplyProcessed();
  921. }
  922. bool OnReplyProcessed()
  923. {
  924. IAsyncResult result = this.channel.BeginClose(this.timeoutHelper.RemainingTime(), closeChannelCallback, this);
  925. if (!result.CompletedSynchronously)
  926. {
  927. return false;
  928. }
  929. this.channel.EndClose(result);
  930. return true;
  931. }
  932. static void CloseChannelCallback(IAsyncResult result)
  933. {
  934. if (result.CompletedSynchronously)
  935. {
  936. return;
  937. }
  938. SessionOperationAsyncResult self = (SessionOperationAsyncResult)result.AsyncState;
  939. Exception completionException = null;
  940. try
  941. {
  942. self.channel.EndClose(result);
  943. self.OnOperationComplete();
  944. }
  945. #pragma warning suppress 56500 // covered by FxCOP
  946. catch (Exception e)
  947. {
  948. if (Fx.IsFatal(e))
  949. throw;
  950. completionException = e;
  951. self.OnOperationFailure(completionException);
  952. }
  953. self.Complete(false, completionException);
  954. }
  955. void OnOperationFailure(Exception e)
  956. {
  957. try
  958. {
  959. this.requestor.OnOperationFailure(operation, target, currentToken, e, this.channel);
  960. }
  961. catch (CommunicationException ex)
  962. {
  963. DiagnosticUtility.TraceHandledException(ex, TraceEventType.Information);
  964. }
  965. }
  966. void OnOperationComplete()
  967. {
  968. this.requestor.OnOperationSuccess(this.operation, this.target, this.issuedToken, this.currentToken);
  969. }
  970. public static SecurityToken End(IAsyncResult result)
  971. {
  972. SessionOperationAsyncResult self = AsyncResult.End<SessionOperationAsyncResult>(result);
  973. return self.issuedToken;
  974. }
  975. }
  976. class ChannelOpenAsyncResultWrapper
  977. {
  978. public object RequestState;
  979. public Message Message;
  980. }
  981. internal class RequestChannelFactory : ChannelFactoryBase<IRequestChannel>
  982. {
  983. ServiceChannelFactory serviceChannelFactory;
  984. public RequestChannelFactory(ServiceChannelFactory serviceChannelFactory)
  985. {
  986. this.serviceChannelFactory = serviceChannelFactory;
  987. }
  988. protected override IRequestChannel OnCreateChannel(EndpointAddress address, Uri via)
  989. {
  990. return serviceChannelFactory.CreateChannel<IRequestChannel>(address, via);
  991. }
  992. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  993. {
  994. return this.serviceChannelFactory.BeginOpen(timeout, callback, state);
  995. }
  996. protected override void OnEndOpen(IAsyncResult result)
  997. {
  998. this.serviceChannelFactory.EndOpen(result);
  999. }
  1000. protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  1001. {
  1002. return new ChainedCloseAsyncResult(timeout, callback, state, base.OnBeginClose, base.OnEndClose, this.serviceChannelFactory);
  1003. }
  1004. protected override void OnEndClose(IAsyncResult result)
  1005. {
  1006. ChainedCloseAsyncResult.End(result);
  1007. }
  1008. protected override void OnClose(TimeSpan timeout)
  1009. {
  1010. base.OnClose(timeout);
  1011. this.serviceChannelFactory.Close(timeout);
  1012. }
  1013. protected override void OnOpen(TimeSpan timeout)
  1014. {
  1015. this.serviceChannelFactory.Open(timeout);
  1016. }
  1017. protected override void OnAbort()
  1018. {
  1019. this.serviceChannelFactory.Abort();
  1020. base.OnAbort();
  1021. }
  1022. public override T GetProperty<T>()
  1023. {
  1024. return this.serviceChannelFactory.GetProperty<T>();
  1025. }
  1026. }
  1027. }
  1028. }