RequestSecurityToken.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System;
  7. using System.ServiceModel.Channels;
  8. using System.ServiceModel.Description;
  9. using System.ServiceModel;
  10. using System.Security.Cryptography.Xml;
  11. using System.IdentityModel.Claims;
  12. using System.IdentityModel.Policy;
  13. using System.IdentityModel.Tokens;
  14. using System.IdentityModel.Selectors;
  15. using System.ServiceModel.Security.Tokens;
  16. using System.Runtime.Serialization;
  17. using System.Xml.Serialization;
  18. using System.Xml.Schema;
  19. using System.Xml;
  20. using System.Collections;
  21. using System.Collections.Generic;
  22. using System.Collections.ObjectModel;
  23. using System.IO;
  24. using System.ServiceModel.Security;
  25. using System.Globalization;
  26. using System.ServiceModel.Dispatcher;
  27. using System.Security.Authentication.ExtendedProtection;
  28. class RequestSecurityToken : BodyWriter
  29. {
  30. string context;
  31. string tokenType;
  32. string requestType;
  33. SecurityToken entropyToken;
  34. BinaryNegotiation negotiationData;
  35. XmlElement rstXml;
  36. IList<XmlElement> requestProperties;
  37. byte[] cachedWriteBuffer;
  38. int cachedWriteBufferLength;
  39. int keySize;
  40. Message message;
  41. SecurityKeyIdentifierClause renewTarget;
  42. SecurityKeyIdentifierClause closeTarget;
  43. OnGetBinaryNegotiationCallback onGetBinaryNegotiation;
  44. SecurityStandardsManager standardsManager;
  45. bool isReceiver;
  46. bool isReadOnly;
  47. object appliesTo;
  48. DataContractSerializer appliesToSerializer;
  49. Type appliesToType;
  50. object thisLock = new Object();
  51. public RequestSecurityToken()
  52. : this(SecurityStandardsManager.DefaultInstance)
  53. {
  54. }
  55. public RequestSecurityToken(MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer)
  56. : this(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer))
  57. {
  58. }
  59. public RequestSecurityToken(MessageSecurityVersion messageSecurityVersion,
  60. SecurityTokenSerializer securityTokenSerializer,
  61. XmlElement requestSecurityTokenXml,
  62. string context,
  63. string tokenType,
  64. string requestType,
  65. int keySize,
  66. SecurityKeyIdentifierClause renewTarget,
  67. SecurityKeyIdentifierClause closeTarget)
  68. : this(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer),
  69. requestSecurityTokenXml,
  70. context,
  71. tokenType,
  72. requestType,
  73. keySize,
  74. renewTarget,
  75. closeTarget)
  76. {
  77. }
  78. public RequestSecurityToken(XmlElement requestSecurityTokenXml,
  79. string context,
  80. string tokenType,
  81. string requestType,
  82. int keySize,
  83. SecurityKeyIdentifierClause renewTarget,
  84. SecurityKeyIdentifierClause closeTarget)
  85. : this(SecurityStandardsManager.DefaultInstance,
  86. requestSecurityTokenXml,
  87. context,
  88. tokenType,
  89. requestType,
  90. keySize,
  91. renewTarget,
  92. closeTarget)
  93. {
  94. }
  95. internal RequestSecurityToken(SecurityStandardsManager standardsManager,
  96. XmlElement rstXml,
  97. string context,
  98. string tokenType,
  99. string requestType,
  100. int keySize,
  101. SecurityKeyIdentifierClause renewTarget,
  102. SecurityKeyIdentifierClause closeTarget)
  103. : base(true)
  104. {
  105. if (standardsManager == null)
  106. {
  107. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("standardsManager"));
  108. }
  109. this.standardsManager = standardsManager;
  110. if (rstXml == null)
  111. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstXml");
  112. this.rstXml = rstXml;
  113. this.context = context;
  114. this.tokenType = tokenType;
  115. this.keySize = keySize;
  116. this.requestType = requestType;
  117. this.renewTarget = renewTarget;
  118. this.closeTarget = closeTarget;
  119. this.isReceiver = true;
  120. this.isReadOnly = true;
  121. }
  122. internal RequestSecurityToken(SecurityStandardsManager standardsManager)
  123. : this(standardsManager, true)
  124. {
  125. // no op
  126. }
  127. internal RequestSecurityToken(SecurityStandardsManager standardsManager, bool isBuffered)
  128. : base(isBuffered)
  129. {
  130. if (standardsManager == null)
  131. {
  132. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("standardsManager"));
  133. }
  134. this.standardsManager = standardsManager;
  135. this.requestType = this.standardsManager.TrustDriver.RequestTypeIssue;
  136. this.requestProperties = null;
  137. this.isReceiver = false;
  138. this.isReadOnly = false;
  139. }
  140. public ChannelBinding GetChannelBinding()
  141. {
  142. if (this.message == null)
  143. {
  144. return null;
  145. }
  146. ChannelBindingMessageProperty channelBindingMessageProperty = null;
  147. ChannelBindingMessageProperty.TryGet( this.message, out channelBindingMessageProperty );
  148. ChannelBinding channelBinding = null;
  149. if ( channelBindingMessageProperty != null )
  150. {
  151. channelBinding = channelBindingMessageProperty.ChannelBinding;
  152. }
  153. return channelBinding;
  154. }
  155. /// <summary>
  156. /// Will hold a reference to the outbound message from which we will fish the ChannelBinding out of.
  157. /// </summary>
  158. public Message Message
  159. {
  160. get { return message; }
  161. set { message = value; }
  162. }
  163. public string Context
  164. {
  165. get
  166. {
  167. return this.context;
  168. }
  169. set
  170. {
  171. if (this.IsReadOnly)
  172. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  173. this.context = value;
  174. }
  175. }
  176. public string TokenType
  177. {
  178. get
  179. {
  180. return this.tokenType;
  181. }
  182. set
  183. {
  184. if (this.IsReadOnly)
  185. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  186. this.tokenType = value;
  187. }
  188. }
  189. public int KeySize
  190. {
  191. get
  192. {
  193. return this.keySize;
  194. }
  195. set
  196. {
  197. if (this.IsReadOnly)
  198. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  199. if (value < 0)
  200. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.ValueMustBeNonNegative)));
  201. this.keySize = value;
  202. }
  203. }
  204. public bool IsReadOnly
  205. {
  206. get
  207. {
  208. return this.isReadOnly;
  209. }
  210. }
  211. public delegate void OnGetBinaryNegotiationCallback( ChannelBinding channelBinding );
  212. public OnGetBinaryNegotiationCallback OnGetBinaryNegotiation
  213. {
  214. get
  215. {
  216. return this.onGetBinaryNegotiation;
  217. }
  218. set
  219. {
  220. if (this.IsReadOnly)
  221. {
  222. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  223. }
  224. this.onGetBinaryNegotiation = value;
  225. }
  226. }
  227. public IEnumerable<XmlElement> RequestProperties
  228. {
  229. get
  230. {
  231. if (this.isReceiver)
  232. {
  233. // PreSharp Bug: Property get methods should not throw exceptions.
  234. #pragma warning suppress 56503
  235. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "RequestProperties")));
  236. }
  237. return this.requestProperties;
  238. }
  239. set
  240. {
  241. if (this.IsReadOnly)
  242. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  243. if (value != null)
  244. {
  245. int index = 0;
  246. Collection<XmlElement> coll = new Collection<XmlElement>();
  247. foreach (XmlElement property in value)
  248. {
  249. if (property == null)
  250. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(String.Format(CultureInfo.InvariantCulture, "value[{0}]", index)));
  251. coll.Add(property);
  252. ++index;
  253. }
  254. this.requestProperties = coll;
  255. }
  256. else
  257. {
  258. this.requestProperties = null;
  259. }
  260. }
  261. }
  262. public string RequestType
  263. {
  264. get
  265. {
  266. return this.requestType;
  267. }
  268. set
  269. {
  270. if (this.IsReadOnly)
  271. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  272. if (value == null)
  273. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  274. this.requestType = value;
  275. }
  276. }
  277. public SecurityKeyIdentifierClause RenewTarget
  278. {
  279. get
  280. {
  281. return this.renewTarget;
  282. }
  283. set
  284. {
  285. if (this.IsReadOnly)
  286. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  287. this.renewTarget = value;
  288. }
  289. }
  290. public SecurityKeyIdentifierClause CloseTarget
  291. {
  292. get
  293. {
  294. return this.closeTarget;
  295. }
  296. set
  297. {
  298. if (this.IsReadOnly)
  299. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  300. this.closeTarget = value;
  301. }
  302. }
  303. public XmlElement RequestSecurityTokenXml
  304. {
  305. get
  306. {
  307. if (!this.isReceiver)
  308. {
  309. // PreSharp Bug: Property get methods should not throw exceptions.
  310. #pragma warning suppress 56503
  311. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemAvailableInDeserializedRSTOnly, "RequestSecurityTokenXml")));
  312. }
  313. return this.rstXml;
  314. }
  315. }
  316. internal SecurityStandardsManager StandardsManager
  317. {
  318. get
  319. {
  320. return this.standardsManager;
  321. }
  322. set
  323. {
  324. if (this.IsReadOnly)
  325. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  326. if (value == null)
  327. {
  328. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
  329. }
  330. this.standardsManager = value;
  331. }
  332. }
  333. internal bool IsReceiver
  334. {
  335. get
  336. {
  337. return this.isReceiver;
  338. }
  339. }
  340. internal object AppliesTo
  341. {
  342. get
  343. {
  344. if (this.isReceiver)
  345. {
  346. // PreSharp Bug: Property get methods should not throw exceptions.
  347. #pragma warning suppress 56503
  348. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "AppliesTo")));
  349. }
  350. return this.appliesTo;
  351. }
  352. }
  353. internal DataContractSerializer AppliesToSerializer
  354. {
  355. get
  356. {
  357. if (this.isReceiver)
  358. {
  359. // PreSharp Bug: Property get methods should not throw exceptions.
  360. #pragma warning suppress 56503
  361. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "AppliesToSerializer")));
  362. }
  363. return this.appliesToSerializer;
  364. }
  365. }
  366. internal Type AppliesToType
  367. {
  368. get
  369. {
  370. if (this.isReceiver)
  371. {
  372. // PreSharp Bug: Property get methods should not throw exceptions.
  373. #pragma warning suppress 56503
  374. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "AppliesToType")));
  375. }
  376. return this.appliesToType;
  377. }
  378. }
  379. protected Object ThisLock
  380. {
  381. get
  382. {
  383. return this.thisLock;
  384. }
  385. }
  386. internal void SetBinaryNegotiation(BinaryNegotiation negotiation)
  387. {
  388. if (negotiation == null)
  389. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("negotiation");
  390. if (this.IsReadOnly)
  391. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  392. this.negotiationData = negotiation;
  393. }
  394. internal BinaryNegotiation GetBinaryNegotiation()
  395. {
  396. if (this.isReceiver)
  397. {
  398. return this.standardsManager.TrustDriver.GetBinaryNegotiation(this);
  399. }
  400. else if (this.negotiationData == null && this.onGetBinaryNegotiation != null)
  401. {
  402. this.onGetBinaryNegotiation(this.GetChannelBinding());
  403. }
  404. return this.negotiationData;
  405. }
  406. public SecurityToken GetRequestorEntropy()
  407. {
  408. return this.GetRequestorEntropy(null);
  409. }
  410. internal SecurityToken GetRequestorEntropy(SecurityTokenResolver resolver)
  411. {
  412. if (this.isReceiver)
  413. {
  414. return this.standardsManager.TrustDriver.GetEntropy(this, resolver);
  415. }
  416. else
  417. return this.entropyToken;
  418. }
  419. public void SetRequestorEntropy(byte[] entropy)
  420. {
  421. if (this.IsReadOnly)
  422. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  423. this.entropyToken = (entropy != null) ? new NonceToken(entropy) : null;
  424. }
  425. internal void SetRequestorEntropy(WrappedKeySecurityToken entropyToken)
  426. {
  427. if (this.IsReadOnly)
  428. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  429. this.entropyToken = entropyToken;
  430. }
  431. public void SetAppliesTo<T>(T appliesTo, DataContractSerializer serializer)
  432. {
  433. if (this.IsReadOnly)
  434. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  435. if (appliesTo != null && serializer == null)
  436. {
  437. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
  438. }
  439. this.appliesTo = appliesTo;
  440. this.appliesToSerializer = serializer;
  441. this.appliesToType = typeof(T);
  442. }
  443. public void GetAppliesToQName(out string localName, out string namespaceUri)
  444. {
  445. if (!this.isReceiver)
  446. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemAvailableInDeserializedRSTOnly, "MatchesAppliesTo")));
  447. this.standardsManager.TrustDriver.GetAppliesToQName(this, out localName, out namespaceUri);
  448. }
  449. public T GetAppliesTo<T>()
  450. {
  451. return this.GetAppliesTo<T>(DataContractSerializerDefaults.CreateSerializer(typeof(T), DataContractSerializerDefaults.MaxItemsInObjectGraph));
  452. }
  453. public T GetAppliesTo<T>(XmlObjectSerializer serializer)
  454. {
  455. if (this.isReceiver)
  456. {
  457. if (serializer == null)
  458. {
  459. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
  460. }
  461. return this.standardsManager.TrustDriver.GetAppliesTo<T>(this, serializer);
  462. }
  463. else
  464. {
  465. return (T)this.appliesTo;
  466. }
  467. }
  468. void OnWriteTo(XmlWriter writer)
  469. {
  470. if (this.isReceiver)
  471. {
  472. this.rstXml.WriteTo(writer);
  473. }
  474. else
  475. {
  476. this.standardsManager.TrustDriver.WriteRequestSecurityToken(this, writer);
  477. }
  478. }
  479. public void WriteTo(XmlWriter writer)
  480. {
  481. if (writer == null)
  482. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
  483. if (this.IsReadOnly)
  484. {
  485. // cache the serialized bytes to ensure repeatability
  486. if (this.cachedWriteBuffer == null)
  487. {
  488. MemoryStream stream = new MemoryStream();
  489. using (XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, XD.Dictionary))
  490. {
  491. this.OnWriteTo(binaryWriter);
  492. binaryWriter.Flush();
  493. stream.Flush();
  494. stream.Seek(0, SeekOrigin.Begin);
  495. this.cachedWriteBuffer = stream.GetBuffer();
  496. this.cachedWriteBufferLength = (int)stream.Length;
  497. }
  498. }
  499. writer.WriteNode(XmlDictionaryReader.CreateBinaryReader(this.cachedWriteBuffer, 0, this.cachedWriteBufferLength, XD.Dictionary, XmlDictionaryReaderQuotas.Max), false);
  500. }
  501. else
  502. this.OnWriteTo(writer);
  503. }
  504. public static RequestSecurityToken CreateFrom(XmlReader reader)
  505. {
  506. return CreateFrom(SecurityStandardsManager.DefaultInstance, reader);
  507. }
  508. public static RequestSecurityToken CreateFrom(XmlReader reader, MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer)
  509. {
  510. return CreateFrom(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer), reader);
  511. }
  512. internal static RequestSecurityToken CreateFrom(SecurityStandardsManager standardsManager, XmlReader reader)
  513. {
  514. return standardsManager.TrustDriver.CreateRequestSecurityToken(reader);
  515. }
  516. public void MakeReadOnly()
  517. {
  518. if (!this.isReadOnly)
  519. {
  520. this.isReadOnly = true;
  521. if (this.requestProperties != null)
  522. {
  523. this.requestProperties = new ReadOnlyCollection<XmlElement>(this.requestProperties);
  524. }
  525. this.OnMakeReadOnly();
  526. }
  527. }
  528. internal protected virtual void OnWriteCustomAttributes(XmlWriter writer) { }
  529. internal protected virtual void OnWriteCustomElements(XmlWriter writer) { }
  530. internal protected virtual void OnMakeReadOnly() { }
  531. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  532. {
  533. WriteTo(writer);
  534. }
  535. }
  536. }