InfoCardHelper.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. //
  5. // Presharp uses the c# pragma mechanism to supress its warnings.
  6. // These are not recognised by the base compiler so we need to explictly
  7. // disable the following warnings. See http://winweb/cse/Tools/PREsharp/userguide/default.asp
  8. // for details.
  9. //
  10. #pragma warning disable 1634, 1691 // unknown message, unknown pragma
  11. namespace System.ServiceModel.Security
  12. {
  13. using System.Collections.ObjectModel;
  14. using System.Collections.Generic;
  15. using System.IdentityModel.Selectors;
  16. using System.IdentityModel.Tokens;
  17. using System.ServiceModel;
  18. using System.ServiceModel.Description;
  19. using System.ServiceModel.Security.Tokens;
  20. using System.ServiceModel.Channels;
  21. using System.ServiceModel.Dispatcher;
  22. using System.Xml;
  23. using System.IO;
  24. using System.Text;
  25. using System.Runtime;
  26. using System.Diagnostics.CodeAnalysis;
  27. //
  28. // Summary:
  29. // delegate definition for invokation of the GetToken method.
  30. //
  31. delegate SecurityToken GetInfoCardTokenCallback(bool requiresInfoCard, CardSpacePolicyElement[] chain, SecurityTokenSerializer tokenSerializer);
  32. static class InfoCardHelper
  33. {
  34. const string WSIdentityNamespace = @"http://schemas.microsoft.com/ws/2005/05/identity";
  35. const string IsManagedElementName = @"IsManaged";
  36. static Uri selfIssuerUri;
  37. // Summary:
  38. // If interactive support is requested and an IssuedSecurityTokenParameters is specified this method
  39. // will return an instance of an InfoCardTokenProvider.
  40. // Otherwise this method defers to the base implementation.
  41. //
  42. // Parameters
  43. // parameters - The security token parameters associated with this ChannelFactory.
  44. //
  45. // Note
  46. // The target and issuer information will not be available in this call
  47. //
  48. public static bool TryCreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement, ClientCredentialsSecurityTokenManager clientCredentialsTokenManager, out SecurityTokenProvider provider)
  49. {
  50. if (tokenRequirement == null)
  51. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenRequirement");
  52. if (clientCredentialsTokenManager == null)
  53. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("clientCredentialsTokenManager");
  54. provider = null;
  55. if (!clientCredentialsTokenManager.ClientCredentials.SupportInteractive
  56. || (null != clientCredentialsTokenManager.ClientCredentials.IssuedToken.LocalIssuerAddress && null != clientCredentialsTokenManager.ClientCredentials.IssuedToken.LocalIssuerBinding)
  57. || !clientCredentialsTokenManager.IsIssuedSecurityTokenRequirement(tokenRequirement)
  58. )
  59. {
  60. //IDT.TraceDebug("ICARDTOKPROV: Non Issued SecurityToken requirement submitted to InfoCardClientCredentialsSecurityTokenManager:\n{0}", tokenRequirement);
  61. //IDT.TraceDebug("ICARDTOKPROV: Defering to the base class to create the token provider");
  62. }
  63. else
  64. {
  65. ChannelParameterCollection channelParameter;
  66. InfoCardChannelParameter infocardChannelParameter = null;
  67. if (tokenRequirement.TryGetProperty<ChannelParameterCollection>(ServiceModelSecurityTokenRequirement.ChannelParametersCollectionProperty, out channelParameter))
  68. {
  69. foreach (object obj in channelParameter)
  70. {
  71. if (obj is InfoCardChannelParameter)
  72. {
  73. infocardChannelParameter = (InfoCardChannelParameter)obj;
  74. break;
  75. }
  76. }
  77. }
  78. if (null == infocardChannelParameter || !infocardChannelParameter.RequiresInfoCard)
  79. {
  80. return false;
  81. }
  82. EndpointAddress target = tokenRequirement.GetProperty<EndpointAddress>(ServiceModelSecurityTokenRequirement.TargetAddressProperty);
  83. IssuedSecurityTokenParameters issuedTokenParameters = tokenRequirement.GetProperty<IssuedSecurityTokenParameters>(ServiceModelSecurityTokenRequirement.IssuedSecurityTokenParametersProperty);
  84. Uri privacyNoticeLink;
  85. if (!tokenRequirement.TryGetProperty<Uri>(ServiceModelSecurityTokenRequirement.PrivacyNoticeUriProperty, out privacyNoticeLink))
  86. {
  87. privacyNoticeLink = null;
  88. }
  89. int privacyNoticeVersion;
  90. if (!tokenRequirement.TryGetProperty<int>(ServiceModelSecurityTokenRequirement.PrivacyNoticeVersionProperty, out privacyNoticeVersion))
  91. {
  92. privacyNoticeVersion = 0;
  93. }
  94. //
  95. // This analysis of this chain indicates that interactive support will be required
  96. // The InternalClientCredentials class handles that.
  97. //
  98. provider = CreateTokenProviderForNextLeg(tokenRequirement, target, issuedTokenParameters.IssuerAddress, infocardChannelParameter.RelyingPartyIssuer, clientCredentialsTokenManager, infocardChannelParameter);
  99. }
  100. return provider != null;
  101. }
  102. public static bool IsInfocardRequired(Binding binding, ClientCredentials clientCreds, SecurityTokenManager clientCredentialsTokenManager, EndpointAddress target, out CardSpacePolicyElement[] infocardChain, out Uri relyingPartyIssuer)
  103. {
  104. infocardChain = null;
  105. bool requiresInfoCard = false;
  106. relyingPartyIssuer = null;
  107. if (!clientCreds.SupportInteractive
  108. || (null != clientCreds.IssuedToken.LocalIssuerAddress && null != clientCreds.IssuedToken.LocalIssuerBinding)
  109. )
  110. {
  111. return false;
  112. }
  113. IssuedSecurityTokenParameters parameters = TryGetNextStsIssuedTokenParameters(binding);
  114. if (null != parameters)
  115. {
  116. Uri privacyNotice;
  117. int privacyVersion;
  118. GetPrivacyNoticeLinkFromIssuerBinding(binding, out privacyNotice, out privacyVersion);
  119. PolicyElement[] policyChain = GetPolicyChain(target, binding, parameters, privacyNotice, privacyVersion, clientCredentialsTokenManager);
  120. relyingPartyIssuer = null;
  121. if (null != policyChain)
  122. {
  123. requiresInfoCard = RequiresInfoCard(policyChain, out relyingPartyIssuer);
  124. }
  125. if (requiresInfoCard)
  126. {
  127. infocardChain = new CardSpacePolicyElement[policyChain.Length];
  128. for (int i = 0; i < policyChain.Length; i++)
  129. {
  130. infocardChain[i] = policyChain[i].ToCardSpacePolicyElement();
  131. }
  132. }
  133. }
  134. return requiresInfoCard;
  135. }
  136. static Uri SelfIssuerUri
  137. {
  138. get
  139. {
  140. if (selfIssuerUri == null)
  141. selfIssuerUri = new Uri(WSIdentityNamespace + "/issuer/self");
  142. return selfIssuerUri;
  143. }
  144. }
  145. static PolicyElement[] GetPolicyChain(EndpointAddress target, Binding outerBinding, IssuedSecurityTokenParameters parameters, Uri firstPrivacyNoticeLink, int firstPrivacyNoticeVersion, SecurityTokenManager clientCredentialsTokenManager)
  146. {
  147. EndpointAddress nextTarget = target;
  148. IssuedSecurityTokenParameters nextParameters = parameters;
  149. List<PolicyElement> chain = new List<PolicyElement>();
  150. Uri privacyNoticeLink = firstPrivacyNoticeLink;
  151. int privacyNoticeVersion = firstPrivacyNoticeVersion;
  152. bool isManagedIssuer = false;
  153. //
  154. // this is the binding to the final STS in the chain. Start from here and walk the
  155. // chain backwards to the 1st STS in the chain
  156. //
  157. while (null != nextParameters)
  158. {
  159. MessageSecurityVersion bindingSecurityVersion = null;
  160. if (nextParameters.IssuerBinding == null)
  161. {
  162. bindingSecurityVersion = GetBindingSecurityVersionOrDefault(outerBinding);
  163. }
  164. else
  165. {
  166. bindingSecurityVersion = GetBindingSecurityVersionOrDefault(nextParameters.IssuerBinding);
  167. }
  168. chain.Add(new PolicyElement(nextTarget,
  169. nextParameters.IssuerAddress,
  170. nextParameters.CreateRequestParameters(bindingSecurityVersion, clientCredentialsTokenManager.CreateSecurityTokenSerializer(bindingSecurityVersion.SecurityTokenVersion)),
  171. privacyNoticeLink,
  172. privacyNoticeVersion,
  173. isManagedIssuer,
  174. nextParameters.IssuerBinding));
  175. isManagedIssuer = IsReferralToManagedIssuer(nextParameters.IssuerBinding);
  176. GetPrivacyNoticeLinkFromIssuerBinding(nextParameters.IssuerBinding, out privacyNoticeLink, out privacyNoticeVersion);
  177. nextTarget = nextParameters.IssuerAddress;
  178. outerBinding = nextParameters.IssuerBinding;
  179. nextParameters = TryGetNextStsIssuedTokenParameters(nextParameters.IssuerBinding);
  180. }
  181. //
  182. // Add the last element for the MCIP case
  183. //
  184. if (isManagedIssuer)
  185. {
  186. chain.Add(new PolicyElement(nextTarget,
  187. null,
  188. null,
  189. privacyNoticeLink,
  190. privacyNoticeVersion,
  191. isManagedIssuer,
  192. null));
  193. }
  194. return chain.ToArray();
  195. }
  196. //
  197. // Summary:
  198. // Checks the policy chain to determine which target and issuer in the chain the InfoCard system should be invoked with.
  199. //
  200. // Cases:
  201. //
  202. // i Frame(n-1) Frame(n) RP Index
  203. // - ---------- -------- ---------
  204. // 1 empty Self/Anon/null n
  205. // 2 empty mcip error
  206. // 3 empty anything other than self/anon federated token provider
  207. // null/mcip
  208. // 4 any issuer mcip n-1
  209. // 5 any issuer Self/Anon/null n
  210. // 6 any issuer anything other than self/anon federated token provider
  211. // null/mcip
  212. //
  213. //
  214. // Parameters
  215. // relyingPartyIssuer - The output Uri of the issuer of the relying party requiring
  216. // interactive support.
  217. //
  218. // Returns:
  219. // true - A policy frame was identified to require interactive support from the infocard system.
  220. // false - Interactive support not required
  221. //
  222. static bool RequiresInfoCard(PolicyElement[] chain, out Uri relyingPartyIssuer)
  223. {
  224. relyingPartyIssuer = null;
  225. //IDT.TraceDebug("ICARDTOKPROV: Attempting to identify the relying party requiring infocard support.");
  226. if (0 == chain.Length)
  227. {
  228. //IDT.TraceDebug("ICARDTOKPROV: Zero length policy chain, returning false.");
  229. return false;
  230. }
  231. int n = chain.Length - 1;
  232. int relyingPartyIndex = -1;
  233. bool infocardSupportRequired = false;
  234. //
  235. // Handle a chain which contains only one element - cases 1 and 2
  236. //
  237. if (1 == chain.Length)
  238. {
  239. if (null == chain[n].Issuer
  240. || chain[n].Issuer.IsAnonymous
  241. || SelfIssuerUri.Equals(chain[n].Issuer.Uri)
  242. || (null != chain[n].Issuer && null == chain[n].Binding))
  243. {
  244. //IDT.TraceDebug("ICARDTOKPROV: Policy frame n was selected (case 1).");
  245. //
  246. // Case 1: Return frame n
  247. //
  248. relyingPartyIndex = n;
  249. infocardSupportRequired = true;
  250. }
  251. //
  252. // Case 2: Asert if mcip is at the bottom of the chain and is the only element
  253. //
  254. else if (chain[n].IsManagedIssuer)
  255. {
  256. Fx.Assert("MCIP was found at the bottom of the chain when the chain length was 1");
  257. }
  258. else
  259. {
  260. //
  261. // Case 3: Do nothing so that Indigo will use the default federated token provider.
  262. //
  263. infocardSupportRequired = false;
  264. }
  265. }
  266. else
  267. {
  268. if (chain[n].IsManagedIssuer)
  269. {
  270. //
  271. // Case 4: MCIP followed by a token supported by infocard was found. Return frame n-1.
  272. //
  273. relyingPartyIndex = n - 1;
  274. infocardSupportRequired = true;
  275. }
  276. //
  277. // Case 5: Federated chain ending in self issued/null/anon. Return frame n.
  278. //
  279. else if (null == chain[n].Issuer ||
  280. chain[n].Issuer.IsAnonymous ||
  281. SelfIssuerUri.Equals(chain[n].Issuer.Uri) ||
  282. (null != chain[n].Issuer && null == chain[n].Binding))
  283. {
  284. relyingPartyIndex = n;
  285. infocardSupportRequired = true;
  286. }
  287. else
  288. {
  289. //
  290. // Case 6: Do nothing so that Indigo will use the default federated token provider.
  291. //
  292. infocardSupportRequired = false;
  293. }
  294. //
  295. // Check to make sure that no other leg in the chain specifically requires infocard
  296. //
  297. for (int k = 0; k < n; k++)
  298. {
  299. if (chain[k].IsManagedIssuer
  300. || SelfIssuerUri.Equals(chain[k].Issuer.Uri)
  301. || null == chain[k].Issuer
  302. || chain[k].Issuer.IsAnonymous)
  303. {
  304. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InfoCardInvalidChain)));
  305. }
  306. }
  307. }
  308. //
  309. // Get the issuer Uri from the policy chain. Also, handle the case where
  310. // the issuer may not have been specified.
  311. //
  312. if (infocardSupportRequired)
  313. {
  314. relyingPartyIssuer = (null == chain[relyingPartyIndex].Issuer) ? null : chain[relyingPartyIndex].Issuer.Uri;
  315. }
  316. return infocardSupportRequired;
  317. }
  318. static SecurityTokenProvider CreateTokenProviderForNextLeg(SecurityTokenRequirement tokenRequirement, EndpointAddress target, EndpointAddress issuerAddress, Uri relyingPartyIssuer, ClientCredentialsSecurityTokenManager clientCredentialsTokenManager, InfoCardChannelParameter infocardChannelParameter)
  319. {
  320. if (((null == relyingPartyIssuer && null == issuerAddress) || issuerAddress.Uri == relyingPartyIssuer))
  321. {
  322. return new InternalInfoCardTokenProvider(infocardChannelParameter);
  323. }
  324. else
  325. {
  326. // create a federation token provider and add an internal client credentials shim that contains the chain
  327. IssuedSecurityTokenProvider federationTokenProvider = (IssuedSecurityTokenProvider)clientCredentialsTokenManager.CreateSecurityTokenProvider(tokenRequirement, true);
  328. federationTokenProvider.IssuerChannelBehaviors.Remove<SecurityCredentialsManager>();
  329. federationTokenProvider.IssuerChannelBehaviors.Add(new InternalClientCredentials(clientCredentialsTokenManager.ClientCredentials, target, relyingPartyIssuer, infocardChannelParameter));
  330. return federationTokenProvider;
  331. }
  332. }
  333. //
  334. // Summary:
  335. // Looks for a standards manager on the security binding element of the specified binding.
  336. // If one is not found it returns the default.
  337. //
  338. // Parameters
  339. // binding - Collection
  340. // parameters - Security parameters for current invocation.
  341. //
  342. // Returns:
  343. // Always returns an instance of the SecurityVersion class
  344. //
  345. public static MessageSecurityVersion GetBindingSecurityVersionOrDefault(Binding binding)
  346. {
  347. if (null != binding)
  348. {
  349. SecurityBindingElement sbe = binding.CreateBindingElements().Find<SecurityBindingElement>();
  350. if (null != sbe)
  351. {
  352. return sbe.MessageSecurityVersion;
  353. }
  354. }
  355. return MessageSecurityVersion.Default;
  356. }
  357. //
  358. // Summary:
  359. // Given an Issuer binding determines whether that issuer is a managed card provider.
  360. //
  361. //
  362. static bool IsReferralToManagedIssuer(Binding issuerBinding)
  363. {
  364. bool bRetVal = false;
  365. if (null != issuerBinding)
  366. {
  367. //
  368. // If the UseManagedPresentationBindingElement is present then this is a ManagedCardProvider.
  369. //
  370. UseManagedPresentationBindingElement useManagedPresentationBE =
  371. issuerBinding.CreateBindingElements().Find<UseManagedPresentationBindingElement>();
  372. if (null != useManagedPresentationBE)
  373. {
  374. bRetVal = true;
  375. }
  376. }
  377. return bRetVal;
  378. }
  379. //
  380. // Summary:
  381. // Given an issuer Binding retrieves any privacy notice links that might be present.
  382. //
  383. static void GetPrivacyNoticeLinkFromIssuerBinding(Binding issuerBinding, out Uri privacyNotice, out int privacyNoticeVersion)
  384. {
  385. privacyNotice = null;
  386. privacyNoticeVersion = 0;
  387. if (null != issuerBinding)
  388. {
  389. PrivacyNoticeBindingElement privacyNoticeBE =
  390. issuerBinding.CreateBindingElements().Find<PrivacyNoticeBindingElement>();
  391. if (null != privacyNoticeBE)
  392. {
  393. privacyNotice = privacyNoticeBE.Url;
  394. privacyNoticeVersion = privacyNoticeBE.Version;
  395. }
  396. }
  397. }
  398. // Summary:
  399. // Searches a binding for a single IssuedSecurityTokenParameters. This method will throw an
  400. // argument exception if more than one is found.
  401. //
  402. // Parameters:
  403. // currentStsBinding - The Binding to search.
  404. //
  405. // Return Value:
  406. // Returns an IssuedSecurityTokenParameters if one is found, otherwise null.
  407. //
  408. static IssuedSecurityTokenParameters TryGetNextStsIssuedTokenParameters(Binding currentStsBinding)
  409. {
  410. if (null == currentStsBinding)
  411. {
  412. return null;
  413. }
  414. BindingElementCollection bindingElements = currentStsBinding.CreateBindingElements();
  415. SecurityBindingElement secBindingElement = bindingElements.Find<SecurityBindingElement>();
  416. return TryGetNextStsIssuedTokenParameters(secBindingElement);
  417. }
  418. // Summary:
  419. // Searches a security binding element for a single IssuedSecurityTokenParameters. This method will throw an
  420. // argument exception if more than one is found.
  421. //
  422. // Parameters:
  423. // securityBindingEle - The SecurityBindingElement to search.
  424. //
  425. // Return Value:
  426. // Returns an IssuedSecurityTokenParameters if one is found, otherwise null.
  427. //
  428. static IssuedSecurityTokenParameters TryGetNextStsIssuedTokenParameters(SecurityBindingElement securityBindingEle)
  429. {
  430. if (securityBindingEle == null)
  431. {
  432. return null;
  433. }
  434. //
  435. // This object can have a value assigned to it exactly once. After one assignment of a non-null value
  436. // any other non-null assignment will cause the object to throw an argument excaption.
  437. //
  438. ThrowOnMultipleAssignment<IssuedSecurityTokenParameters> issuedTokenParameters =
  439. new ThrowOnMultipleAssignment<IssuedSecurityTokenParameters>(SR.GetString(SR.TooManyIssuedSecurityTokenParameters));
  440. FindInfoCardIssuerBinding(securityBindingEle, issuedTokenParameters);
  441. return issuedTokenParameters.Value;
  442. }
  443. static void FindInfoCardIssuerBinding(SecurityBindingElement secBindingElement, ThrowOnMultipleAssignment<IssuedSecurityTokenParameters> issuedSecurityTokenParameters)
  444. {
  445. if (secBindingElement == null)
  446. return;
  447. //
  448. // Go down the list of possible places for an IssuedSecurityTokenParameters, and hope we don't
  449. // miss anything.
  450. //
  451. SecurityTokenParametersEnumerable tokenParamEnumerator = new SecurityTokenParametersEnumerable(secBindingElement);
  452. foreach (SecurityTokenParameters param in tokenParamEnumerator)
  453. {
  454. IssuedSecurityTokenParameters issuedTokenParam = param as IssuedSecurityTokenParameters;
  455. if (issuedTokenParam != null &&
  456. ((issuedTokenParam.IssuerBinding == null ||
  457. issuedTokenParam.IssuerAddress == null ||
  458. issuedTokenParam.IssuerAddress.IsAnonymous ||
  459. SelfIssuerUri.Equals(issuedTokenParam.IssuerAddress)) ||
  460. (IsReferralToManagedIssuer(issuedTokenParam.IssuerBinding))))
  461. {
  462. if (issuedSecurityTokenParameters != null)
  463. issuedSecurityTokenParameters.Value = issuedTokenParam;
  464. }
  465. else if (param is SecureConversationSecurityTokenParameters)
  466. {
  467. IssuedSecurityTokenParameters istp = TryGetNextStsIssuedTokenParameters(((SecureConversationSecurityTokenParameters)param).BootstrapSecurityBindingElement);
  468. if ((istp != null) && (issuedSecurityTokenParameters != null))
  469. {
  470. issuedSecurityTokenParameters.Value = istp;
  471. }
  472. }
  473. else if ((issuedTokenParam != null) && (issuedTokenParam.IssuerBinding != null))
  474. {
  475. BindingElementCollection bindingElements = issuedTokenParam.IssuerBinding.CreateBindingElements();
  476. SecurityBindingElement innerSecurityBindingElement = bindingElements.Find<SecurityBindingElement>();
  477. IssuedSecurityTokenParameters istp = TryGetNextStsIssuedTokenParameters(innerSecurityBindingElement);
  478. if ((istp != null) && (issuedSecurityTokenParameters != null))
  479. {
  480. issuedSecurityTokenParameters.Value = issuedTokenParam;
  481. }
  482. }
  483. }
  484. }
  485. //
  486. // Summary:
  487. // This class throws an Argument exception if an attempt is made to assign a non-null
  488. // value to the Value property more than once.
  489. //
  490. class ThrowOnMultipleAssignment<T>
  491. {
  492. string m_errorString;
  493. T m_value;
  494. public T Value
  495. {
  496. get { return m_value; }
  497. set
  498. {
  499. if (null != m_value && null != value)
  500. {
  501. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(m_errorString);
  502. }
  503. else if (null == m_value)
  504. {
  505. m_value = value;
  506. }
  507. }
  508. }
  509. //
  510. // Parameters:
  511. // errorString - If Value gets assigned to more than once an argument exception will be thrown with this
  512. // string as the Exception string.
  513. //
  514. public ThrowOnMultipleAssignment(string errorString)
  515. {
  516. Fx.Assert(!String.IsNullOrEmpty(errorString), "Must have an error string");
  517. m_errorString = errorString;
  518. }
  519. }
  520. class InternalInfoCardTokenProvider : SecurityTokenProvider, IDisposable
  521. {
  522. InfoCardChannelParameter m_infocardChannelParameter;
  523. public InternalInfoCardTokenProvider(InfoCardChannelParameter infocardChannelParameter)
  524. {
  525. this.m_infocardChannelParameter = infocardChannelParameter;
  526. }
  527. protected override SecurityToken GetTokenCore(TimeSpan timeout)
  528. {
  529. if (null != m_infocardChannelParameter && null != m_infocardChannelParameter.Token)
  530. {
  531. if (m_infocardChannelParameter.Token.ValidTo < DateTime.UtcNow)
  532. {
  533. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ExpiredSecurityTokenException((SR.GetString(SR.ExpiredTokenInChannelParameters))));
  534. }
  535. else
  536. {
  537. return m_infocardChannelParameter.Token;
  538. }
  539. }
  540. else
  541. {
  542. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException((SR.GetString(SR.NoTokenInChannelParameters))));
  543. }
  544. }
  545. public void Dispose()
  546. {
  547. //
  548. // Don't want to pull the rug under the user when channel is aborted
  549. // as user may be managing cards - nothing to do.
  550. //
  551. }
  552. }
  553. //
  554. // Summary:
  555. // This class knows how to walk a chain of IssuedSecurityTokenParameters and figure out at what point
  556. // in the chain the InfoCard system should be invoked. The idea is to identify the single most
  557. // appropriate place in the referral chain to involve user selection(if at all) . This decision is affected
  558. // by the previously established relationships that the user has with some issuers. Some issuers may have
  559. // issued "InfoCards" to the user allowing them to choose which collection of claims should be used to generate
  560. // a token for the relying party.
  561. //
  562. // When asked for a token provider this class will return a FederatedServiceTokenProvider for
  563. // an IssuedSecurityTokenParameters until it reaches the previously identified relyingparty/issuer,
  564. // at which point it will return an InternalTokenProvider instance, which will invoke the infocard
  565. // system allowing the user to get involved in the token generatio process.
  566. //
  567. class InternalClientCredentials : ClientCredentials
  568. {
  569. Uri m_relyingPartyIssuer;
  570. ClientCredentials m_clientCredentials;
  571. InfoCardChannelParameter m_infocardChannelParameter;
  572. //
  573. // Summary:
  574. // Constructs the policy chain and determines the depth at which to invoke the InfoCard system.
  575. //
  576. // Parameters
  577. // target - Target specified in CreateChannel call. This will fully specify a referral chain.
  578. // parameters - Security parameters for current invocation.
  579. //
  580. public InternalClientCredentials(
  581. ClientCredentials infocardCredentials,
  582. EndpointAddress target,
  583. Uri relyingPartyIssuer,
  584. InfoCardChannelParameter infocardChannelParameter)
  585. : base(infocardCredentials)
  586. {
  587. m_relyingPartyIssuer = relyingPartyIssuer;
  588. m_clientCredentials = infocardCredentials;
  589. m_infocardChannelParameter = infocardChannelParameter;
  590. }
  591. InternalClientCredentials(InternalClientCredentials other)
  592. : base(other)
  593. {
  594. m_relyingPartyIssuer = other.m_relyingPartyIssuer;
  595. m_clientCredentials = other.m_clientCredentials;
  596. m_infocardChannelParameter = other.InfoCardChannelParameter;
  597. }
  598. public InfoCardChannelParameter InfoCardChannelParameter
  599. {
  600. get
  601. {
  602. return m_infocardChannelParameter;
  603. }
  604. }
  605. public override SecurityTokenManager CreateSecurityTokenManager()
  606. {
  607. return new InternalClientCredentialsSecurityTokenManager(this, m_infocardChannelParameter);
  608. }
  609. public override void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
  610. {
  611. }
  612. protected override ClientCredentials CloneCore()
  613. {
  614. return new InternalClientCredentials(this);
  615. }
  616. class InternalClientCredentialsSecurityTokenManager : ClientCredentialsSecurityTokenManager
  617. {
  618. Uri m_relyingPartyIssuer;
  619. InfoCardChannelParameter m_infocardChannelParameter;
  620. public InternalClientCredentialsSecurityTokenManager(InternalClientCredentials internalClientCredentials, InfoCardChannelParameter infocardChannelParameter)
  621. : base(internalClientCredentials)
  622. {
  623. m_relyingPartyIssuer = internalClientCredentials.m_relyingPartyIssuer;
  624. m_infocardChannelParameter = infocardChannelParameter;
  625. }
  626. public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
  627. {
  628. if (IsIssuedSecurityTokenRequirement(tokenRequirement))
  629. {
  630. EndpointAddress target = tokenRequirement.GetProperty<EndpointAddress>(ServiceModelSecurityTokenRequirement.TargetAddressProperty);
  631. IssuedSecurityTokenParameters issuedTokenParameters = tokenRequirement.GetProperty<IssuedSecurityTokenParameters>(ServiceModelSecurityTokenRequirement.IssuedSecurityTokenParametersProperty);
  632. return InfoCardHelper.CreateTokenProviderForNextLeg(tokenRequirement, target, issuedTokenParameters.IssuerAddress, m_relyingPartyIssuer, this, m_infocardChannelParameter);
  633. }
  634. else
  635. {
  636. return base.CreateSecurityTokenProvider(tokenRequirement);
  637. }
  638. }
  639. }
  640. }
  641. class PolicyElement
  642. {
  643. EndpointAddress m_target;
  644. EndpointAddress m_issuer;
  645. Collection<XmlElement> m_parameters;
  646. Uri m_policyNoticeLink;
  647. int m_policyNoticeVersion;
  648. bool m_isManagedIssuer;
  649. Binding m_binding;
  650. public bool IsManagedIssuer
  651. {
  652. get { return m_isManagedIssuer; }
  653. }
  654. public EndpointAddress Issuer
  655. {
  656. get { return m_issuer; }
  657. }
  658. public Binding Binding
  659. {
  660. get { return m_binding; }
  661. }
  662. //
  663. // Parameters:
  664. // target - The target of the token being described.
  665. // parameters - describes the type of token required by the target.
  666. //
  667. public PolicyElement(EndpointAddress target, EndpointAddress issuer, Collection<XmlElement> parameters, Uri privacyNoticeLink, int privacyNoticeVersion, bool isManagedIssuer, Binding binding)
  668. {
  669. m_target = target;
  670. m_issuer = issuer;
  671. m_parameters = parameters;
  672. m_policyNoticeLink = privacyNoticeLink;
  673. m_policyNoticeVersion = privacyNoticeVersion;
  674. m_isManagedIssuer = isManagedIssuer;
  675. m_binding = binding;
  676. }
  677. //
  678. // Summary:
  679. // Convert the PolicyElement to an CardSpacePolicyElement
  680. //
  681. // Returns:
  682. // The CardSpacePolicyElement object
  683. //
  684. [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The call to CardSpacePolicyElement is safe.")]
  685. public CardSpacePolicyElement ToCardSpacePolicyElement()
  686. {
  687. return new CardSpacePolicyElement(EndPointAddressToXmlElement(m_target),
  688. EndPointAddressToXmlElement(m_issuer),
  689. m_parameters,
  690. m_policyNoticeLink,
  691. m_policyNoticeVersion,
  692. m_isManagedIssuer);
  693. }
  694. //
  695. // Summary:
  696. // Convert an endpoint address to an XmlElement
  697. //
  698. // Parameters:
  699. // epr - EndPointAddress that need to be converted
  700. //
  701. // Returns:
  702. // The XmlElement version of the epr
  703. //
  704. private XmlElement EndPointAddressToXmlElement(EndpointAddress epr)
  705. {
  706. if (null == epr)
  707. return null;
  708. using (MemoryStream buffer = new MemoryStream())
  709. {
  710. using (XmlWriter writer = new XmlTextWriter(buffer, Encoding.UTF8))
  711. {
  712. epr.WriteTo(AddressingVersion.WSAddressing10, writer);
  713. //
  714. // Skip the BOM and trailing padding.
  715. //
  716. writer.Flush();
  717. buffer.Flush();
  718. buffer.Seek(0, 0);
  719. using (XmlReader reader = XmlReader.Create(buffer))
  720. {
  721. XmlDocument doc = new XmlDocument();
  722. return (XmlElement)doc.ReadNode(reader);
  723. }
  724. }
  725. }
  726. }
  727. }
  728. class SecurityTokenParametersEnumerable : IEnumerable<SecurityTokenParameters>
  729. {
  730. SecurityBindingElement sbe;
  731. public SecurityTokenParametersEnumerable(SecurityBindingElement sbe)
  732. {
  733. if (sbe == null)
  734. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sbe");
  735. this.sbe = sbe;
  736. }
  737. public IEnumerator<SecurityTokenParameters> GetEnumerator()
  738. {
  739. foreach (SecurityTokenParameters stp in this.sbe.EndpointSupportingTokenParameters.Endorsing)
  740. if (stp != null)
  741. yield return stp;
  742. foreach (SecurityTokenParameters stp in this.sbe.EndpointSupportingTokenParameters.SignedEndorsing)
  743. if (stp != null)
  744. yield return stp;
  745. foreach (SupportingTokenParameters str in this.sbe.OperationSupportingTokenParameters.Values)
  746. if (str != null)
  747. {
  748. foreach (SecurityTokenParameters stp in str.Endorsing)
  749. if (stp != null)
  750. yield return stp;
  751. foreach (SecurityTokenParameters stp in str.SignedEndorsing)
  752. if (stp != null)
  753. yield return stp;
  754. }
  755. if (this.sbe is SymmetricSecurityBindingElement)
  756. {
  757. SymmetricSecurityBindingElement ssbe = (SymmetricSecurityBindingElement)sbe;
  758. if (ssbe.ProtectionTokenParameters != null)
  759. yield return ssbe.ProtectionTokenParameters;
  760. }
  761. else if (this.sbe is AsymmetricSecurityBindingElement)
  762. {
  763. AsymmetricSecurityBindingElement asbe = (AsymmetricSecurityBindingElement)sbe;
  764. if (asbe.RecipientTokenParameters != null)
  765. yield return asbe.RecipientTokenParameters;
  766. }
  767. }
  768. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  769. {
  770. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
  771. }
  772. }
  773. }
  774. }