SecurityProtocol.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. //----------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.Diagnostics;
  9. using System.IdentityModel.Policy;
  10. using System.IdentityModel.Selectors;
  11. using System.IdentityModel.Tokens;
  12. using System.Runtime;
  13. using System.ServiceModel;
  14. using System.ServiceModel.Channels;
  15. using System.ServiceModel.Description;
  16. using System.ServiceModel.Diagnostics;
  17. using System.ServiceModel.Security.Tokens;
  18. // See SecurityProtocolFactory for contracts on subclasses etc
  19. // SecureOutgoingMessage and VerifyIncomingMessage take message as
  20. // ref parameters (instead of taking a message and returning a
  21. // message) to reduce the likelihood that a caller will forget to
  22. // do the rest of the processing with the modified message object.
  23. // Especially, on the sender-side, not sending the modified
  24. // message will result in sending it with an unencrypted body.
  25. // Correspondingly, the async versions have out parameters instead
  26. // of simple return values.
  27. abstract class SecurityProtocol : ISecurityCommunicationObject
  28. {
  29. static ReadOnlyCollection<SupportingTokenProviderSpecification> emptyTokenProviders;
  30. ICollection<SupportingTokenProviderSpecification> channelSupportingTokenProviderSpecification;
  31. Dictionary<string, ICollection<SupportingTokenProviderSpecification>> scopedSupportingTokenProviderSpecification;
  32. Dictionary<string, Collection<SupportingTokenProviderSpecification>> mergedSupportingTokenProvidersMap;
  33. SecurityProtocolFactory factory;
  34. EndpointAddress target;
  35. Uri via;
  36. WrapperSecurityCommunicationObject communicationObject;
  37. ChannelParameterCollection channelParameters;
  38. protected SecurityProtocol(SecurityProtocolFactory factory, EndpointAddress target, Uri via)
  39. {
  40. this.factory = factory;
  41. this.target = target;
  42. this.via = via;
  43. this.communicationObject = new WrapperSecurityCommunicationObject(this);
  44. }
  45. protected WrapperSecurityCommunicationObject CommunicationObject
  46. {
  47. get { return this.communicationObject; }
  48. }
  49. public SecurityProtocolFactory SecurityProtocolFactory
  50. {
  51. get { return this.factory; }
  52. }
  53. public EndpointAddress Target
  54. {
  55. get { return this.target; }
  56. }
  57. public Uri Via
  58. {
  59. get { return this.via; }
  60. }
  61. public ICollection<SupportingTokenProviderSpecification> ChannelSupportingTokenProviderSpecification
  62. {
  63. get
  64. {
  65. return this.channelSupportingTokenProviderSpecification;
  66. }
  67. }
  68. public Dictionary<string, ICollection<SupportingTokenProviderSpecification>> ScopedSupportingTokenProviderSpecification
  69. {
  70. get
  71. {
  72. return this.scopedSupportingTokenProviderSpecification;
  73. }
  74. }
  75. static ReadOnlyCollection<SupportingTokenProviderSpecification> EmptyTokenProviders
  76. {
  77. get
  78. {
  79. if (emptyTokenProviders == null)
  80. {
  81. emptyTokenProviders = new ReadOnlyCollection<SupportingTokenProviderSpecification>(new List<SupportingTokenProviderSpecification>());
  82. }
  83. return emptyTokenProviders;
  84. }
  85. }
  86. public ChannelParameterCollection ChannelParameters
  87. {
  88. get
  89. {
  90. return this.channelParameters;
  91. }
  92. set
  93. {
  94. this.communicationObject.ThrowIfDisposedOrImmutable();
  95. this.channelParameters = value;
  96. }
  97. }
  98. // ISecurityCommunicationObject members
  99. public TimeSpan DefaultOpenTimeout
  100. {
  101. get { return ServiceDefaults.OpenTimeout; }
  102. }
  103. public TimeSpan DefaultCloseTimeout
  104. {
  105. get { return ServiceDefaults.CloseTimeout; }
  106. }
  107. public IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  108. {
  109. return new OperationWithTimeoutAsyncResult(new OperationWithTimeoutCallback(this.OnClose), timeout, callback, state);
  110. }
  111. public IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  112. {
  113. return new OperationWithTimeoutAsyncResult(new OperationWithTimeoutCallback(this.OnOpen), timeout, callback, state);
  114. }
  115. public void OnClosed()
  116. {
  117. }
  118. public void OnClosing()
  119. {
  120. }
  121. public void OnEndClose(IAsyncResult result)
  122. {
  123. OperationWithTimeoutAsyncResult.End(result);
  124. }
  125. public void OnEndOpen(IAsyncResult result)
  126. {
  127. OperationWithTimeoutAsyncResult.End(result);
  128. }
  129. public void OnFaulted()
  130. {
  131. }
  132. public void OnOpened()
  133. {
  134. }
  135. public void OnOpening()
  136. {
  137. }
  138. internal IList<SupportingTokenProviderSpecification> GetSupportingTokenProviders(string action)
  139. {
  140. if (this.mergedSupportingTokenProvidersMap != null && this.mergedSupportingTokenProvidersMap.Count > 0)
  141. {
  142. if (action != null && this.mergedSupportingTokenProvidersMap.ContainsKey(action))
  143. {
  144. return this.mergedSupportingTokenProvidersMap[action];
  145. }
  146. else if (this.mergedSupportingTokenProvidersMap.ContainsKey(MessageHeaders.WildcardAction))
  147. {
  148. return this.mergedSupportingTokenProvidersMap[MessageHeaders.WildcardAction];
  149. }
  150. }
  151. // return null if the token providers list is empty - this gets a perf benefit since calling Count is expensive for an empty
  152. // ReadOnlyCollection
  153. return (this.channelSupportingTokenProviderSpecification == EmptyTokenProviders) ? null : (IList<SupportingTokenProviderSpecification>)this.channelSupportingTokenProviderSpecification;
  154. }
  155. protected InitiatorServiceModelSecurityTokenRequirement CreateInitiatorSecurityTokenRequirement()
  156. {
  157. InitiatorServiceModelSecurityTokenRequirement requirement = new InitiatorServiceModelSecurityTokenRequirement();
  158. requirement.TargetAddress = this.Target;
  159. requirement.Via = this.via;
  160. requirement.SecurityBindingElement = this.factory.SecurityBindingElement;
  161. requirement.SecurityAlgorithmSuite = this.factory.OutgoingAlgorithmSuite;
  162. requirement.MessageSecurityVersion = this.factory.MessageSecurityVersion.SecurityTokenVersion;
  163. if (this.factory.PrivacyNoticeUri != null)
  164. {
  165. requirement.Properties[ServiceModelSecurityTokenRequirement.PrivacyNoticeUriProperty] = this.factory.PrivacyNoticeUri;
  166. }
  167. if (this.channelParameters != null)
  168. {
  169. requirement.Properties[ServiceModelSecurityTokenRequirement.ChannelParametersCollectionProperty] = this.channelParameters;
  170. }
  171. requirement.Properties[ServiceModelSecurityTokenRequirement.PrivacyNoticeVersionProperty] = this.factory.PrivacyNoticeVersion;
  172. return requirement;
  173. }
  174. InitiatorServiceModelSecurityTokenRequirement CreateInitiatorSecurityTokenRequirement(SecurityTokenParameters parameters, SecurityTokenAttachmentMode attachmentMode)
  175. {
  176. InitiatorServiceModelSecurityTokenRequirement requirement = CreateInitiatorSecurityTokenRequirement();
  177. parameters.InitializeSecurityTokenRequirement(requirement);
  178. requirement.KeyUsage = SecurityKeyUsage.Signature;
  179. requirement.Properties[ServiceModelSecurityTokenRequirement.MessageDirectionProperty] = MessageDirection.Output;
  180. requirement.Properties[ServiceModelSecurityTokenRequirement.SupportingTokenAttachmentModeProperty] = attachmentMode;
  181. return requirement;
  182. }
  183. void AddSupportingTokenProviders(SupportingTokenParameters supportingTokenParameters, bool isOptional, IList<SupportingTokenProviderSpecification> providerSpecList)
  184. {
  185. for (int i = 0; i < supportingTokenParameters.Endorsing.Count; ++i)
  186. {
  187. SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.Endorsing[i], SecurityTokenAttachmentMode.Endorsing);
  188. try
  189. {
  190. if (isOptional)
  191. {
  192. requirement.IsOptionalToken = true;
  193. }
  194. System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement);
  195. if (provider == null)
  196. {
  197. continue;
  198. }
  199. SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.Endorsing, supportingTokenParameters.Endorsing[i]);
  200. providerSpecList.Add(providerSpec);
  201. }
  202. catch (Exception e)
  203. {
  204. if (!isOptional || Fx.IsFatal(e))
  205. {
  206. throw;
  207. }
  208. }
  209. }
  210. for (int i = 0; i < supportingTokenParameters.SignedEndorsing.Count; ++i)
  211. {
  212. SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.SignedEndorsing[i], SecurityTokenAttachmentMode.SignedEndorsing);
  213. try
  214. {
  215. if (isOptional)
  216. {
  217. requirement.IsOptionalToken = true;
  218. }
  219. System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement);
  220. if (provider == null)
  221. {
  222. continue;
  223. }
  224. SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.SignedEndorsing, supportingTokenParameters.SignedEndorsing[i]);
  225. providerSpecList.Add(providerSpec);
  226. }
  227. catch (Exception e)
  228. {
  229. if (!isOptional || Fx.IsFatal(e))
  230. {
  231. throw;
  232. }
  233. }
  234. }
  235. for (int i = 0; i < supportingTokenParameters.SignedEncrypted.Count; ++i)
  236. {
  237. SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.SignedEncrypted[i], SecurityTokenAttachmentMode.SignedEncrypted);
  238. try
  239. {
  240. if (isOptional)
  241. {
  242. requirement.IsOptionalToken = true;
  243. }
  244. System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement);
  245. if (provider == null)
  246. {
  247. continue;
  248. }
  249. SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.SignedEncrypted, supportingTokenParameters.SignedEncrypted[i]);
  250. providerSpecList.Add(providerSpec);
  251. }
  252. catch (Exception e)
  253. {
  254. if (!isOptional || Fx.IsFatal(e))
  255. {
  256. throw;
  257. }
  258. }
  259. }
  260. for (int i = 0; i < supportingTokenParameters.Signed.Count; ++i)
  261. {
  262. SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.Signed[i], SecurityTokenAttachmentMode.Signed);
  263. try
  264. {
  265. if (isOptional)
  266. {
  267. requirement.IsOptionalToken = true;
  268. }
  269. System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement);
  270. if (provider == null)
  271. {
  272. continue;
  273. }
  274. SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.Signed, supportingTokenParameters.Signed[i]);
  275. providerSpecList.Add(providerSpec);
  276. }
  277. catch (Exception e)
  278. {
  279. if (!isOptional || Fx.IsFatal(e))
  280. {
  281. throw;
  282. }
  283. }
  284. }
  285. }
  286. void MergeSupportingTokenProviders(TimeSpan timeout)
  287. {
  288. if (this.ScopedSupportingTokenProviderSpecification.Count == 0)
  289. {
  290. this.mergedSupportingTokenProvidersMap = null;
  291. }
  292. else
  293. {
  294. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  295. this.factory.ExpectSupportingTokens = true;
  296. this.mergedSupportingTokenProvidersMap = new Dictionary<string, Collection<SupportingTokenProviderSpecification>>();
  297. foreach (string action in this.ScopedSupportingTokenProviderSpecification.Keys)
  298. {
  299. ICollection<SupportingTokenProviderSpecification> scopedProviders = this.ScopedSupportingTokenProviderSpecification[action];
  300. if (scopedProviders == null || scopedProviders.Count == 0)
  301. {
  302. continue;
  303. }
  304. Collection<SupportingTokenProviderSpecification> mergedProviders = new Collection<SupportingTokenProviderSpecification>();
  305. foreach (SupportingTokenProviderSpecification spec in this.channelSupportingTokenProviderSpecification)
  306. {
  307. mergedProviders.Add(spec);
  308. }
  309. foreach (SupportingTokenProviderSpecification spec in scopedProviders)
  310. {
  311. SecurityUtils.OpenTokenProviderIfRequired(spec.TokenProvider, timeoutHelper.RemainingTime());
  312. if (spec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.Endorsing || spec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.SignedEndorsing)
  313. {
  314. if (spec.TokenParameters.RequireDerivedKeys && !spec.TokenParameters.HasAsymmetricKey)
  315. {
  316. this.factory.ExpectKeyDerivation = true;
  317. }
  318. }
  319. mergedProviders.Add(spec);
  320. }
  321. this.mergedSupportingTokenProvidersMap.Add(action, mergedProviders);
  322. }
  323. }
  324. }
  325. public void Open(TimeSpan timeout)
  326. {
  327. this.communicationObject.Open(timeout);
  328. }
  329. public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  330. {
  331. return this.communicationObject.BeginOpen(timeout, callback, state);
  332. }
  333. public void EndOpen(IAsyncResult result)
  334. {
  335. this.communicationObject.EndOpen(result);
  336. }
  337. public virtual void OnOpen(TimeSpan timeout)
  338. {
  339. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  340. if (this.factory.ActAsInitiator)
  341. {
  342. this.channelSupportingTokenProviderSpecification = new Collection<SupportingTokenProviderSpecification>();
  343. this.scopedSupportingTokenProviderSpecification = new Dictionary<string, ICollection<SupportingTokenProviderSpecification>>();
  344. AddSupportingTokenProviders(this.factory.SecurityBindingElement.EndpointSupportingTokenParameters, false, (IList<SupportingTokenProviderSpecification>)this.channelSupportingTokenProviderSpecification);
  345. AddSupportingTokenProviders(this.factory.SecurityBindingElement.OptionalEndpointSupportingTokenParameters, true, (IList<SupportingTokenProviderSpecification>)this.channelSupportingTokenProviderSpecification);
  346. foreach (string action in this.factory.SecurityBindingElement.OperationSupportingTokenParameters.Keys)
  347. {
  348. Collection<SupportingTokenProviderSpecification> providerSpecList = new Collection<SupportingTokenProviderSpecification>();
  349. AddSupportingTokenProviders(this.factory.SecurityBindingElement.OperationSupportingTokenParameters[action], false, providerSpecList);
  350. this.scopedSupportingTokenProviderSpecification.Add(action, providerSpecList);
  351. }
  352. foreach (string action in this.factory.SecurityBindingElement.OptionalOperationSupportingTokenParameters.Keys)
  353. {
  354. Collection<SupportingTokenProviderSpecification> providerSpecList;
  355. ICollection<SupportingTokenProviderSpecification> existingList;
  356. if (this.scopedSupportingTokenProviderSpecification.TryGetValue(action, out existingList))
  357. {
  358. providerSpecList = ((Collection<SupportingTokenProviderSpecification>)existingList);
  359. }
  360. else
  361. {
  362. providerSpecList = new Collection<SupportingTokenProviderSpecification>();
  363. this.scopedSupportingTokenProviderSpecification.Add(action, providerSpecList);
  364. }
  365. this.AddSupportingTokenProviders(this.factory.SecurityBindingElement.OptionalOperationSupportingTokenParameters[action], true, providerSpecList);
  366. }
  367. if (!this.channelSupportingTokenProviderSpecification.IsReadOnly)
  368. {
  369. if (this.channelSupportingTokenProviderSpecification.Count == 0)
  370. {
  371. this.channelSupportingTokenProviderSpecification = EmptyTokenProviders;
  372. }
  373. else
  374. {
  375. this.factory.ExpectSupportingTokens = true;
  376. foreach (SupportingTokenProviderSpecification tokenProviderSpec in this.channelSupportingTokenProviderSpecification)
  377. {
  378. SecurityUtils.OpenTokenProviderIfRequired(tokenProviderSpec.TokenProvider, timeoutHelper.RemainingTime());
  379. if (tokenProviderSpec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.Endorsing || tokenProviderSpec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.SignedEndorsing)
  380. {
  381. if (tokenProviderSpec.TokenParameters.RequireDerivedKeys && !tokenProviderSpec.TokenParameters.HasAsymmetricKey)
  382. {
  383. this.factory.ExpectKeyDerivation = true;
  384. }
  385. }
  386. }
  387. this.channelSupportingTokenProviderSpecification =
  388. new ReadOnlyCollection<SupportingTokenProviderSpecification>((Collection<SupportingTokenProviderSpecification>)this.channelSupportingTokenProviderSpecification);
  389. }
  390. }
  391. // create a merged map of the per operation supporting tokens
  392. MergeSupportingTokenProviders(timeoutHelper.RemainingTime());
  393. }
  394. }
  395. public void Close(bool aborted, TimeSpan timeout)
  396. {
  397. if (aborted)
  398. {
  399. this.communicationObject.Abort();
  400. }
  401. else
  402. {
  403. this.communicationObject.Close(timeout);
  404. }
  405. }
  406. public virtual void OnAbort()
  407. {
  408. if (this.factory.ActAsInitiator)
  409. {
  410. foreach (SupportingTokenProviderSpecification spec in this.channelSupportingTokenProviderSpecification)
  411. {
  412. SecurityUtils.AbortTokenProviderIfRequired(spec.TokenProvider);
  413. }
  414. foreach (string action in this.scopedSupportingTokenProviderSpecification.Keys)
  415. {
  416. ICollection<SupportingTokenProviderSpecification> supportingProviders = this.scopedSupportingTokenProviderSpecification[action];
  417. foreach (SupportingTokenProviderSpecification spec in supportingProviders)
  418. {
  419. SecurityUtils.AbortTokenProviderIfRequired(spec.TokenProvider);
  420. }
  421. }
  422. }
  423. }
  424. public virtual void OnClose(TimeSpan timeout)
  425. {
  426. if (this.factory.ActAsInitiator)
  427. {
  428. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  429. foreach (SupportingTokenProviderSpecification spec in this.channelSupportingTokenProviderSpecification)
  430. {
  431. SecurityUtils.CloseTokenProviderIfRequired(spec.TokenProvider, timeoutHelper.RemainingTime());
  432. }
  433. foreach (string action in this.scopedSupportingTokenProviderSpecification.Keys)
  434. {
  435. ICollection<SupportingTokenProviderSpecification> supportingProviders = this.scopedSupportingTokenProviderSpecification[action];
  436. foreach (SupportingTokenProviderSpecification spec in supportingProviders)
  437. {
  438. SecurityUtils.CloseTokenProviderIfRequired(spec.TokenProvider, timeoutHelper.RemainingTime());
  439. }
  440. }
  441. }
  442. }
  443. public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  444. {
  445. return this.communicationObject.BeginClose(timeout, callback, state);
  446. }
  447. public void EndClose(IAsyncResult result)
  448. {
  449. this.communicationObject.EndClose(result);
  450. }
  451. static void SetSecurityHeaderId(SendSecurityHeader securityHeader, Message message)
  452. {
  453. SecurityMessageProperty messageProperty = message.Properties.Security;
  454. if (messageProperty != null)
  455. {
  456. securityHeader.IdPrefix = messageProperty.SenderIdPrefix;
  457. }
  458. }
  459. void AddSupportingTokenSpecification(SecurityMessageProperty security, IList<SecurityToken> tokens, SecurityTokenAttachmentMode attachmentMode, IDictionary<SecurityToken, ReadOnlyCollection<IAuthorizationPolicy>> tokenPoliciesMapping)
  460. {
  461. if (tokens == null || tokens.Count == 0)
  462. {
  463. return;
  464. }
  465. for (int i = 0; i < tokens.Count; ++i)
  466. {
  467. security.IncomingSupportingTokens.Add(new SupportingTokenSpecification(tokens[i], tokenPoliciesMapping[tokens[i]], attachmentMode));
  468. }
  469. }
  470. protected void AddSupportingTokenSpecification(SecurityMessageProperty security, IList<SecurityToken> basicTokens, IList<SecurityToken> endorsingTokens, IList<SecurityToken> signedEndorsingTokens, IList<SecurityToken> signedTokens, IDictionary<SecurityToken, ReadOnlyCollection<IAuthorizationPolicy>> tokenPoliciesMapping)
  471. {
  472. AddSupportingTokenSpecification(security, basicTokens, SecurityTokenAttachmentMode.SignedEncrypted, tokenPoliciesMapping);
  473. AddSupportingTokenSpecification(security, endorsingTokens, SecurityTokenAttachmentMode.Endorsing, tokenPoliciesMapping);
  474. AddSupportingTokenSpecification(security, signedEndorsingTokens, SecurityTokenAttachmentMode.SignedEndorsing, tokenPoliciesMapping);
  475. AddSupportingTokenSpecification(security, signedTokens, SecurityTokenAttachmentMode.Signed, tokenPoliciesMapping);
  476. }
  477. protected SendSecurityHeader CreateSendSecurityHeader(Message message, string actor, SecurityProtocolFactory factory)
  478. {
  479. return CreateSendSecurityHeader(message, actor, factory, true);
  480. }
  481. protected SendSecurityHeader CreateSendSecurityHeaderForTransportProtocol(Message message, string actor, SecurityProtocolFactory factory)
  482. {
  483. return CreateSendSecurityHeader(message, actor, factory, false);
  484. }
  485. SendSecurityHeader CreateSendSecurityHeader(Message message, string actor, SecurityProtocolFactory factory, bool requireMessageProtection)
  486. {
  487. MessageDirection transferDirection = factory.ActAsInitiator ? MessageDirection.Input : MessageDirection.Output;
  488. SendSecurityHeader sendSecurityHeader = factory.StandardsManager.CreateSendSecurityHeader(
  489. message,
  490. actor, true, false,
  491. factory.OutgoingAlgorithmSuite, transferDirection);
  492. sendSecurityHeader.Layout = factory.SecurityHeaderLayout;
  493. sendSecurityHeader.RequireMessageProtection = requireMessageProtection;
  494. SetSecurityHeaderId(sendSecurityHeader, message);
  495. if (factory.AddTimestamp)
  496. {
  497. sendSecurityHeader.AddTimestamp(factory.TimestampValidityDuration);
  498. }
  499. sendSecurityHeader.StreamBufferManager = factory.StreamBufferManager;
  500. return sendSecurityHeader;
  501. }
  502. internal void AddMessageSupportingTokens(Message message, ref IList<SupportingTokenSpecification> supportingTokens)
  503. {
  504. SecurityMessageProperty supportingTokensProperty = message.Properties.Security;
  505. if (supportingTokensProperty != null && supportingTokensProperty.HasOutgoingSupportingTokens)
  506. {
  507. if (supportingTokens == null)
  508. {
  509. supportingTokens = new Collection<SupportingTokenSpecification>();
  510. }
  511. for (int i = 0; i < supportingTokensProperty.OutgoingSupportingTokens.Count; ++i)
  512. {
  513. SupportingTokenSpecification spec = supportingTokensProperty.OutgoingSupportingTokens[i];
  514. if (spec.SecurityTokenParameters == null)
  515. {
  516. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.SenderSideSupportingTokensMustSpecifySecurityTokenParameters)));
  517. }
  518. supportingTokens.Add(spec);
  519. }
  520. }
  521. }
  522. internal bool TryGetSupportingTokens(SecurityProtocolFactory factory, EndpointAddress target, Uri via, Message message, TimeSpan timeout, bool isBlockingCall, out IList<SupportingTokenSpecification> supportingTokens)
  523. {
  524. if (!factory.ActAsInitiator)
  525. {
  526. supportingTokens = null;
  527. return true;
  528. }
  529. if (message == null)
  530. {
  531. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  532. }
  533. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  534. supportingTokens = null;
  535. IList<SupportingTokenProviderSpecification> supportingTokenProviders = this.GetSupportingTokenProviders(message.Headers.Action);
  536. if (supportingTokenProviders != null && supportingTokenProviders.Count > 0)
  537. {
  538. // dont do anything if blocking is not allowed
  539. if (!isBlockingCall)
  540. {
  541. return false;
  542. }
  543. supportingTokens = new Collection<SupportingTokenSpecification>();
  544. for (int i = 0; i < supportingTokenProviders.Count; ++i)
  545. {
  546. SupportingTokenProviderSpecification spec = supportingTokenProviders[i];
  547. SecurityToken supportingToken;
  548. // The ProviderBackedSecurityToken was added in Win7 to allow KerberosRequestorSecurity
  549. // to pass a channel binding to InitializeSecurityContext.
  550. if ((this is TransportSecurityProtocol) && (spec.TokenParameters is KerberosSecurityTokenParameters))
  551. {
  552. supportingToken = new ProviderBackedSecurityToken(spec.TokenProvider, timeoutHelper.RemainingTime());
  553. }
  554. else
  555. {
  556. supportingToken = spec.TokenProvider.GetToken(timeoutHelper.RemainingTime());
  557. }
  558. supportingTokens.Add(new SupportingTokenSpecification(supportingToken, EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance, spec.SecurityTokenAttachmentMode, spec.TokenParameters));
  559. }
  560. }
  561. // add any runtime supporting tokens
  562. AddMessageSupportingTokens(message, ref supportingTokens);
  563. return true;
  564. }
  565. protected IList<SupportingTokenAuthenticatorSpecification> GetSupportingTokenAuthenticatorsAndSetExpectationFlags(SecurityProtocolFactory factory, Message message,
  566. ReceiveSecurityHeader securityHeader)
  567. {
  568. if (factory.ActAsInitiator)
  569. {
  570. return null;
  571. }
  572. if (message == null)
  573. {
  574. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  575. }
  576. bool expectBasicTokens;
  577. bool expectSignedTokens;
  578. bool expectEndorsingTokens;
  579. IList<SupportingTokenAuthenticatorSpecification> authenticators = factory.GetSupportingTokenAuthenticators(message.Headers.Action,
  580. out expectSignedTokens, out expectBasicTokens, out expectEndorsingTokens);
  581. securityHeader.ExpectBasicTokens = expectBasicTokens;
  582. securityHeader.ExpectEndorsingTokens = expectEndorsingTokens;
  583. securityHeader.ExpectSignedTokens = expectSignedTokens;
  584. return authenticators;
  585. }
  586. protected ReadOnlyCollection<SecurityTokenResolver> MergeOutOfBandResolvers(IList<SupportingTokenAuthenticatorSpecification> supportingAuthenticators, ReadOnlyCollection<SecurityTokenResolver> primaryResolvers)
  587. {
  588. Collection<SecurityTokenResolver> outOfBandResolvers = null;
  589. if (supportingAuthenticators != null && supportingAuthenticators.Count > 0)
  590. {
  591. for (int i = 0; i < supportingAuthenticators.Count; ++i)
  592. {
  593. if (supportingAuthenticators[i].TokenResolver != null)
  594. {
  595. outOfBandResolvers = outOfBandResolvers ?? new Collection<SecurityTokenResolver>();
  596. outOfBandResolvers.Add(supportingAuthenticators[i].TokenResolver);
  597. }
  598. }
  599. }
  600. if (outOfBandResolvers != null)
  601. {
  602. if (primaryResolvers != null)
  603. {
  604. for (int i = 0; i < primaryResolvers.Count; ++i)
  605. {
  606. outOfBandResolvers.Insert(0, primaryResolvers[i]);
  607. }
  608. }
  609. return new ReadOnlyCollection<SecurityTokenResolver>(outOfBandResolvers);
  610. }
  611. else
  612. {
  613. return primaryResolvers ?? EmptyReadOnlyCollection<SecurityTokenResolver>.Instance;
  614. }
  615. }
  616. protected void AddSupportingTokens(SendSecurityHeader securityHeader, IList<SupportingTokenSpecification> supportingTokens)
  617. {
  618. if (supportingTokens != null)
  619. {
  620. for (int i = 0; i < supportingTokens.Count; ++i)
  621. {
  622. SecurityToken token = supportingTokens[i].SecurityToken;
  623. SecurityTokenParameters tokenParameters = supportingTokens[i].SecurityTokenParameters;
  624. switch (supportingTokens[i].SecurityTokenAttachmentMode)
  625. {
  626. case SecurityTokenAttachmentMode.Signed:
  627. securityHeader.AddSignedSupportingToken(token, tokenParameters);
  628. break;
  629. case SecurityTokenAttachmentMode.Endorsing:
  630. securityHeader.AddEndorsingSupportingToken(token, tokenParameters);
  631. break;
  632. case SecurityTokenAttachmentMode.SignedEncrypted:
  633. securityHeader.AddBasicSupportingToken(token, tokenParameters);
  634. break;
  635. case SecurityTokenAttachmentMode.SignedEndorsing:
  636. securityHeader.AddSignedEndorsingSupportingToken(token, tokenParameters);
  637. break;
  638. default:
  639. Fx.Assert("Unknown token attachment mode " + supportingTokens[i].SecurityTokenAttachmentMode.ToString());
  640. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnknownTokenAttachmentMode, supportingTokens[i].SecurityTokenAttachmentMode.ToString())));
  641. }
  642. }
  643. }
  644. }
  645. public virtual IAsyncResult BeginSecureOutgoingMessage(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  646. {
  647. SecureOutgoingMessage(ref message, timeout);
  648. return new CompletedAsyncResult<Message>(message, callback, state);
  649. }
  650. public virtual IAsyncResult BeginSecureOutgoingMessage(Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState, AsyncCallback callback, object state)
  651. {
  652. SecurityProtocolCorrelationState newCorrelationState = SecureOutgoingMessage(ref message, timeout, correlationState);
  653. return new CompletedAsyncResult<Message, SecurityProtocolCorrelationState>(message, newCorrelationState, callback, state);
  654. }
  655. public virtual IAsyncResult BeginVerifyIncomingMessage(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  656. {
  657. VerifyIncomingMessage(ref message, timeout);
  658. return new CompletedAsyncResult<Message>(message, callback, state);
  659. }
  660. public virtual IAsyncResult BeginVerifyIncomingMessage(Message message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates, AsyncCallback callback, object state)
  661. {
  662. SecurityProtocolCorrelationState newCorrelationState = VerifyIncomingMessage(ref message, timeout, correlationStates);
  663. return new CompletedAsyncResult<Message, SecurityProtocolCorrelationState>(message, newCorrelationState, callback, state);
  664. }
  665. public virtual void EndSecureOutgoingMessage(IAsyncResult result, out Message message)
  666. {
  667. message = CompletedAsyncResult<Message>.End(result);
  668. }
  669. public virtual void EndSecureOutgoingMessage(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState)
  670. {
  671. message = CompletedAsyncResult<Message, SecurityProtocolCorrelationState>.End(result, out newCorrelationState);
  672. }
  673. public virtual void EndVerifyIncomingMessage(IAsyncResult result, out Message message)
  674. {
  675. message = CompletedAsyncResult<Message>.End(result);
  676. }
  677. public virtual void EndVerifyIncomingMessage(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState)
  678. {
  679. message = CompletedAsyncResult<Message, SecurityProtocolCorrelationState>.End(result, out newCorrelationState);
  680. }
  681. internal static SecurityToken GetToken(SecurityTokenProvider provider, EndpointAddress target, TimeSpan timeout)
  682. {
  683. if (provider == null)
  684. {
  685. // should this be an ArgumentNullException ?
  686. // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("provider"));
  687. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, target)));
  688. }
  689. SecurityToken token = null;
  690. try
  691. {
  692. token = provider.GetToken(timeout);
  693. }
  694. catch (SecurityTokenException exception)
  695. {
  696. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, target), exception));
  697. }
  698. catch (SecurityNegotiationException sne)
  699. {
  700. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, target), sne));
  701. }
  702. return token;
  703. }
  704. public abstract void SecureOutgoingMessage(ref Message message, TimeSpan timeout);
  705. // subclasses that offer correlation should override this version
  706. public virtual SecurityProtocolCorrelationState SecureOutgoingMessage(ref Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState)
  707. {
  708. SecureOutgoingMessage(ref message, timeout);
  709. return null;
  710. }
  711. protected virtual void OnOutgoingMessageSecured(Message securedMessage)
  712. {
  713. SecurityTraceRecordHelper.TraceOutgoingMessageSecured(this, securedMessage);
  714. }
  715. protected virtual void OnSecureOutgoingMessageFailure(Message message)
  716. {
  717. SecurityTraceRecordHelper.TraceSecureOutgoingMessageFailure(this, message);
  718. }
  719. public abstract void VerifyIncomingMessage(ref Message message, TimeSpan timeout);
  720. // subclasses that offer correlation should override this version
  721. public virtual SecurityProtocolCorrelationState VerifyIncomingMessage(ref Message message, TimeSpan timeout, params SecurityProtocolCorrelationState[] correlationStates)
  722. {
  723. VerifyIncomingMessage(ref message, timeout);
  724. return null;
  725. }
  726. protected virtual void OnIncomingMessageVerified(Message verifiedMessage)
  727. {
  728. SecurityTraceRecordHelper.TraceIncomingMessageVerified(this, verifiedMessage);
  729. if (AuditLevel.Success == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Success))
  730. {
  731. SecurityAuditHelper.WriteMessageAuthenticationSuccessEvent(this.factory.AuditLogLocation,
  732. this.factory.SuppressAuditFailure, verifiedMessage, verifiedMessage.Headers.To, verifiedMessage.Headers.Action,
  733. SecurityUtils.GetIdentityNamesFromContext(verifiedMessage.Properties.Security.ServiceSecurityContext.AuthorizationContext));
  734. }
  735. }
  736. protected virtual void OnVerifyIncomingMessageFailure(Message message, Exception exception)
  737. {
  738. SecurityTraceRecordHelper.TraceVerifyIncomingMessageFailure(this, message);
  739. if (PerformanceCounters.PerformanceCountersEnabled && null != this.factory.ListenUri) //service side
  740. {
  741. if ((exception.GetType() == typeof(MessageSecurityException) || exception.GetType().IsSubclassOf(typeof(MessageSecurityException)))
  742. || (exception.GetType() == typeof(SecurityTokenException) || exception.GetType().IsSubclassOf(typeof(SecurityTokenException))))
  743. {
  744. PerformanceCounters.AuthenticationFailed(message, this.factory.ListenUri);
  745. }
  746. }
  747. if (AuditLevel.Failure == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Failure))
  748. {
  749. try
  750. {
  751. SecurityMessageProperty security = message.Properties.Security;
  752. string primaryIdentity;
  753. if (security != null && security.ServiceSecurityContext != null)
  754. primaryIdentity = SecurityUtils.GetIdentityNamesFromContext(security.ServiceSecurityContext.AuthorizationContext);
  755. else
  756. primaryIdentity = SecurityUtils.AnonymousIdentity.Name;
  757. SecurityAuditHelper.WriteMessageAuthenticationFailureEvent(this.factory.AuditLogLocation,
  758. this.factory.SuppressAuditFailure, message, message.Headers.To, message.Headers.Action, primaryIdentity, exception);
  759. }
  760. #pragma warning suppress 56500
  761. catch (Exception auditException)
  762. {
  763. if (Fx.IsFatal(auditException))
  764. throw;
  765. DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error);
  766. }
  767. }
  768. }
  769. protected abstract class GetSupportingTokensAsyncResult : AsyncResult
  770. {
  771. static AsyncCallback getSupportingTokensCallback = Fx.ThunkCallback(new AsyncCallback(GetSupportingTokenCallback));
  772. SecurityProtocol binding;
  773. Message message;
  774. IList<SupportingTokenSpecification> supportingTokens;
  775. int currentTokenProviderIndex = 0;
  776. IList<SupportingTokenProviderSpecification> supportingTokenProviders;
  777. TimeoutHelper timeoutHelper;
  778. public GetSupportingTokensAsyncResult(Message m, SecurityProtocol binding, TimeSpan timeout, AsyncCallback callback, object state)
  779. : base(callback, state)
  780. {
  781. this.message = m;
  782. this.binding = binding;
  783. this.timeoutHelper = new TimeoutHelper(timeout);
  784. }
  785. protected IList<SupportingTokenSpecification> SupportingTokens
  786. {
  787. get { return this.supportingTokens; }
  788. }
  789. protected abstract bool OnGetSupportingTokensDone(TimeSpan timeout);
  790. static void GetSupportingTokenCallback(IAsyncResult result)
  791. {
  792. if (result.CompletedSynchronously)
  793. {
  794. return;
  795. }
  796. GetSupportingTokensAsyncResult self = (GetSupportingTokensAsyncResult)result.AsyncState;
  797. bool completeSelf;
  798. Exception completionException = null;
  799. try
  800. {
  801. self.AddSupportingToken(result);
  802. completeSelf = self.AddSupportingTokens();
  803. }
  804. #pragma warning suppress 56500 // covered by FxCOP
  805. catch (Exception e)
  806. {
  807. if (Fx.IsFatal(e))
  808. {
  809. throw;
  810. }
  811. completeSelf = true;
  812. completionException = e;
  813. }
  814. if (completeSelf)
  815. {
  816. self.Complete(false, completionException);
  817. }
  818. }
  819. void AddSupportingToken(IAsyncResult result)
  820. {
  821. SupportingTokenProviderSpecification spec = supportingTokenProviders[this.currentTokenProviderIndex];
  822. SecurityTokenProvider.SecurityTokenAsyncResult securityTokenAsyncResult = result as SecurityTokenProvider.SecurityTokenAsyncResult;
  823. if (securityTokenAsyncResult != null)
  824. {
  825. this.supportingTokens.Add(new SupportingTokenSpecification(SecurityTokenProvider.SecurityTokenAsyncResult.End(result), EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance, spec.SecurityTokenAttachmentMode, spec.TokenParameters));
  826. }
  827. else
  828. {
  829. this.supportingTokens.Add(new SupportingTokenSpecification(spec.TokenProvider.EndGetToken(result), EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance, spec.SecurityTokenAttachmentMode, spec.TokenParameters));
  830. }
  831. ++this.currentTokenProviderIndex;
  832. }
  833. bool AddSupportingTokens()
  834. {
  835. while (this.currentTokenProviderIndex < supportingTokenProviders.Count)
  836. {
  837. SupportingTokenProviderSpecification spec = supportingTokenProviders[this.currentTokenProviderIndex];
  838. IAsyncResult result = null;
  839. if ((this.binding is TransportSecurityProtocol) && (spec.TokenParameters is KerberosSecurityTokenParameters))
  840. {
  841. result = new SecurityTokenProvider.SecurityTokenAsyncResult(new ProviderBackedSecurityToken(spec.TokenProvider, timeoutHelper.RemainingTime()), null, this);
  842. }
  843. else
  844. {
  845. result = spec.TokenProvider.BeginGetToken(timeoutHelper.RemainingTime(), getSupportingTokensCallback, this);
  846. }
  847. if (!result.CompletedSynchronously)
  848. {
  849. return false;
  850. }
  851. this.AddSupportingToken(result);
  852. }
  853. this.binding.AddMessageSupportingTokens(message, ref this.supportingTokens);
  854. return this.OnGetSupportingTokensDone(timeoutHelper.RemainingTime());
  855. }
  856. protected void Start()
  857. {
  858. bool completeSelf;
  859. if (this.binding.TryGetSupportingTokens(this.binding.SecurityProtocolFactory, this.binding.Target, this.binding.Via, this.message, timeoutHelper.RemainingTime(), false, out supportingTokens))
  860. {
  861. completeSelf = this.OnGetSupportingTokensDone(timeoutHelper.RemainingTime());
  862. }
  863. else
  864. {
  865. this.supportingTokens = new Collection<SupportingTokenSpecification>();
  866. this.supportingTokenProviders = this.binding.GetSupportingTokenProviders(message.Headers.Action);
  867. if (!(this.supportingTokenProviders != null && this.supportingTokenProviders.Count > 0))
  868. {
  869. Fx.Assert("There must be at least 1 supporting token provider");
  870. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException("There must be at least 1 supporting token provider"));
  871. }
  872. completeSelf = this.AddSupportingTokens();
  873. }
  874. if (completeSelf)
  875. {
  876. base.Complete(true);
  877. }
  878. }
  879. }
  880. }
  881. }