WSUtilitySpecificationVersion.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Collections.Generic;
  7. using System.ServiceModel;
  8. using System.IO;
  9. using System.IdentityModel.Claims;
  10. using System.IdentityModel.Policy;
  11. using System.ServiceModel.Security.Tokens;
  12. using System.Threading;
  13. using System.Globalization;
  14. using System.ServiceModel.Diagnostics;
  15. using System.Text;
  16. using System.Xml;
  17. using CanonicalFormWriter = System.IdentityModel.CanonicalFormWriter;
  18. using SignatureResourcePool = System.IdentityModel.SignatureResourcePool;
  19. using HashStream = System.IdentityModel.HashStream;
  20. abstract class WSUtilitySpecificationVersion
  21. {
  22. internal static readonly string[] AcceptedDateTimeFormats = new string[]
  23. {
  24. "yyyy-MM-ddTHH:mm:ss.fffffffZ",
  25. "yyyy-MM-ddTHH:mm:ss.ffffffZ",
  26. "yyyy-MM-ddTHH:mm:ss.fffffZ",
  27. "yyyy-MM-ddTHH:mm:ss.ffffZ",
  28. "yyyy-MM-ddTHH:mm:ss.fffZ",
  29. "yyyy-MM-ddTHH:mm:ss.ffZ",
  30. "yyyy-MM-ddTHH:mm:ss.fZ",
  31. "yyyy-MM-ddTHH:mm:ssZ"
  32. };
  33. readonly XmlDictionaryString namespaceUri;
  34. internal WSUtilitySpecificationVersion(XmlDictionaryString namespaceUri)
  35. {
  36. this.namespaceUri = namespaceUri;
  37. }
  38. public static WSUtilitySpecificationVersion Default
  39. {
  40. get { return OneDotZero; }
  41. }
  42. internal XmlDictionaryString NamespaceUri
  43. {
  44. get { return this.namespaceUri; }
  45. }
  46. public static WSUtilitySpecificationVersion OneDotZero
  47. {
  48. get { return WSUtilitySpecificationVersionOneDotZero.Instance; }
  49. }
  50. internal abstract bool IsReaderAtTimestamp(XmlDictionaryReader reader);
  51. internal abstract SecurityTimestamp ReadTimestamp(XmlDictionaryReader reader, string digestAlgorithm, SignatureResourcePool resourcePool);
  52. internal abstract void WriteTimestamp(XmlDictionaryWriter writer, SecurityTimestamp timestamp);
  53. internal abstract void WriteTimestampCanonicalForm(Stream stream, SecurityTimestamp timestamp, byte[] buffer);
  54. sealed class WSUtilitySpecificationVersionOneDotZero : WSUtilitySpecificationVersion
  55. {
  56. static readonly WSUtilitySpecificationVersionOneDotZero instance = new WSUtilitySpecificationVersionOneDotZero();
  57. WSUtilitySpecificationVersionOneDotZero()
  58. : base(XD.UtilityDictionary.Namespace)
  59. {
  60. }
  61. public static WSUtilitySpecificationVersionOneDotZero Instance
  62. {
  63. get { return instance; }
  64. }
  65. internal override bool IsReaderAtTimestamp(XmlDictionaryReader reader)
  66. {
  67. return reader.IsStartElement(XD.UtilityDictionary.Timestamp, XD.UtilityDictionary.Namespace);
  68. }
  69. internal override SecurityTimestamp ReadTimestamp(XmlDictionaryReader reader, string digestAlgorithm, SignatureResourcePool resourcePool)
  70. {
  71. bool canonicalize = digestAlgorithm != null && reader.CanCanonicalize;
  72. HashStream hashStream = null;
  73. reader.MoveToStartElement(XD.UtilityDictionary.Timestamp, XD.UtilityDictionary.Namespace);
  74. if (canonicalize)
  75. {
  76. hashStream = resourcePool.TakeHashStream(digestAlgorithm);
  77. reader.StartCanonicalization(hashStream, false, null);
  78. }
  79. string id = reader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);
  80. reader.ReadStartElement();
  81. reader.ReadStartElement(XD.UtilityDictionary.CreatedElement, XD.UtilityDictionary.Namespace);
  82. DateTime creationTimeUtc = reader.ReadContentAsDateTime().ToUniversalTime();
  83. reader.ReadEndElement();
  84. DateTime expiryTimeUtc;
  85. if (reader.IsStartElement(XD.UtilityDictionary.ExpiresElement, XD.UtilityDictionary.Namespace))
  86. {
  87. reader.ReadStartElement();
  88. expiryTimeUtc = reader.ReadContentAsDateTime().ToUniversalTime();
  89. reader.ReadEndElement();
  90. }
  91. else
  92. {
  93. expiryTimeUtc = SecurityUtils.MaxUtcDateTime;
  94. }
  95. reader.ReadEndElement();
  96. byte[] digest;
  97. if (canonicalize)
  98. {
  99. reader.EndCanonicalization();
  100. digest = hashStream.FlushHashAndGetValue();
  101. }
  102. else
  103. {
  104. digest = null;
  105. }
  106. return new SecurityTimestamp(creationTimeUtc, expiryTimeUtc, id, digestAlgorithm, digest);
  107. }
  108. internal override void WriteTimestamp(XmlDictionaryWriter writer, SecurityTimestamp timestamp)
  109. {
  110. writer.WriteStartElement(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.Timestamp, XD.UtilityDictionary.Namespace);
  111. writer.WriteAttributeString(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace, timestamp.Id);
  112. writer.WriteStartElement(XD.UtilityDictionary.CreatedElement, XD.UtilityDictionary.Namespace);
  113. char[] creationTime = timestamp.GetCreationTimeChars();
  114. writer.WriteChars(creationTime, 0, creationTime.Length);
  115. writer.WriteEndElement(); // wsu:Created
  116. writer.WriteStartElement(XD.UtilityDictionary.ExpiresElement, XD.UtilityDictionary.Namespace);
  117. char[] expiryTime = timestamp.GetExpiryTimeChars();
  118. writer.WriteChars(expiryTime, 0, expiryTime.Length);
  119. writer.WriteEndElement(); // wsu:Expires
  120. writer.WriteEndElement();
  121. }
  122. internal override void WriteTimestampCanonicalForm(Stream stream, SecurityTimestamp timestamp, byte[] workBuffer)
  123. {
  124. TimestampCanonicalFormWriter.Instance.WriteCanonicalForm(
  125. stream,
  126. timestamp.Id, timestamp.GetCreationTimeChars(), timestamp.GetExpiryTimeChars(),
  127. workBuffer);
  128. }
  129. }
  130. sealed class TimestampCanonicalFormWriter : CanonicalFormWriter
  131. {
  132. const string timestamp = UtilityStrings.Prefix + ":" + UtilityStrings.Timestamp;
  133. const string created = UtilityStrings.Prefix + ":" + UtilityStrings.CreatedElement;
  134. const string expires = UtilityStrings.Prefix + ":" + UtilityStrings.ExpiresElement;
  135. const string idAttribute = UtilityStrings.Prefix + ":" + UtilityStrings.IdAttribute;
  136. const string ns = "xmlns:" + UtilityStrings.Prefix + "=\"" + UtilityStrings.Namespace + "\"";
  137. const string xml1 = "<" + timestamp + " " + ns + " " + idAttribute + "=\"";
  138. const string xml2 = "\"><" + created + ">";
  139. const string xml3 = "</" + created + "><" + expires + ">";
  140. const string xml4 = "</" + expires + "></" + timestamp + ">";
  141. readonly byte[] fragment1;
  142. readonly byte[] fragment2;
  143. readonly byte[] fragment3;
  144. readonly byte[] fragment4;
  145. static readonly TimestampCanonicalFormWriter instance = new TimestampCanonicalFormWriter();
  146. TimestampCanonicalFormWriter()
  147. {
  148. UTF8Encoding encoding = CanonicalFormWriter.Utf8WithoutPreamble;
  149. this.fragment1 = encoding.GetBytes(xml1);
  150. this.fragment2 = encoding.GetBytes(xml2);
  151. this.fragment3 = encoding.GetBytes(xml3);
  152. this.fragment4 = encoding.GetBytes(xml4);
  153. }
  154. public static TimestampCanonicalFormWriter Instance
  155. {
  156. get { return instance; }
  157. }
  158. public void WriteCanonicalForm(Stream stream, string id, char[] created, char[] expires, byte[] workBuffer)
  159. {
  160. stream.Write(this.fragment1, 0, this.fragment1.Length);
  161. EncodeAndWrite(stream, workBuffer, id);
  162. stream.Write(this.fragment2, 0, this.fragment2.Length);
  163. EncodeAndWrite(stream, workBuffer, created);
  164. stream.Write(this.fragment3, 0, this.fragment3.Length);
  165. EncodeAndWrite(stream, workBuffer, expires);
  166. stream.Write(this.fragment4, 0, this.fragment4.Length);
  167. }
  168. }
  169. }
  170. }