EndpointIdentity.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //----------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel
  5. {
  6. using System;
  7. using System.Net;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.DirectoryServices;
  12. using System.DirectoryServices.ActiveDirectory;
  13. using System.Security.Principal;
  14. using System.ServiceModel.Security;
  15. using System.IdentityModel.Claims;
  16. using System.IdentityModel.Policy;
  17. using System.ServiceModel.Channels;
  18. using System.ServiceModel.Diagnostics;
  19. using System.Security.Cryptography;
  20. using System.Security.Cryptography.X509Certificates;
  21. using System.Xml;
  22. using System.Xml.Serialization;
  23. public abstract class EndpointIdentity
  24. {
  25. internal const StoreLocation defaultStoreLocation = StoreLocation.LocalMachine;
  26. internal const StoreName defaultStoreName = StoreName.My;
  27. internal const X509FindType defaultX509FindType = X509FindType.FindBySubjectDistinguishedName;
  28. Claim identityClaim;
  29. IEqualityComparer<Claim> claimComparer;
  30. protected EndpointIdentity()
  31. {
  32. }
  33. protected void Initialize(Claim identityClaim)
  34. {
  35. if (identityClaim == null)
  36. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identityClaim");
  37. Initialize(identityClaim, null);
  38. }
  39. protected void Initialize(Claim identityClaim, IEqualityComparer<Claim> claimComparer)
  40. {
  41. if (identityClaim == null)
  42. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identityClaim");
  43. this.identityClaim = identityClaim;
  44. this.claimComparer = claimComparer;
  45. }
  46. public Claim IdentityClaim
  47. {
  48. get
  49. {
  50. if (this.identityClaim == null)
  51. {
  52. EnsureIdentityClaim();
  53. }
  54. return this.identityClaim;
  55. }
  56. }
  57. public static EndpointIdentity CreateIdentity(Claim identity)
  58. {
  59. if (identity == null)
  60. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
  61. // PreSharp Bug: Parameter 'identity.ClaimType' to this public method must be validated: A null-dereference can occur here.
  62. #pragma warning suppress 56506 // Claim.ClaimType will never return null
  63. if (identity.ClaimType.Equals(ClaimTypes.Dns))
  64. {
  65. return new DnsEndpointIdentity(identity);
  66. }
  67. else if (identity.ClaimType.Equals(ClaimTypes.Spn))
  68. {
  69. return new SpnEndpointIdentity(identity);
  70. }
  71. else if (identity.ClaimType.Equals(ClaimTypes.Upn))
  72. {
  73. return new UpnEndpointIdentity(identity);
  74. }
  75. else if (identity.ClaimType.Equals(ClaimTypes.Rsa))
  76. {
  77. return new RsaEndpointIdentity(identity);
  78. }
  79. else
  80. {
  81. return new GeneralEndpointIdentity(identity);
  82. }
  83. }
  84. public static EndpointIdentity CreateDnsIdentity(string dnsName)
  85. {
  86. return new DnsEndpointIdentity(dnsName);
  87. }
  88. public static EndpointIdentity CreateSpnIdentity(string spnName)
  89. {
  90. return new SpnEndpointIdentity(spnName);
  91. }
  92. public static EndpointIdentity CreateUpnIdentity(string upnName)
  93. {
  94. return new UpnEndpointIdentity(upnName);
  95. }
  96. public static EndpointIdentity CreateRsaIdentity(string publicKey)
  97. {
  98. return new RsaEndpointIdentity(publicKey);
  99. }
  100. public static EndpointIdentity CreateRsaIdentity(X509Certificate2 certificate)
  101. {
  102. return new RsaEndpointIdentity(certificate);
  103. }
  104. public static EndpointIdentity CreateX509CertificateIdentity(X509Certificate2 certificate)
  105. {
  106. return new X509CertificateEndpointIdentity(certificate);
  107. }
  108. public static EndpointIdentity CreateX509CertificateIdentity(X509Certificate2 primaryCertificate, X509Certificate2Collection supportingCertificates)
  109. {
  110. return new X509CertificateEndpointIdentity(primaryCertificate, supportingCertificates);
  111. }
  112. internal static EndpointIdentity CreateX509CertificateIdentity(X509Chain certificateChain)
  113. {
  114. if (certificateChain == null)
  115. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificateChain");
  116. if (certificateChain.ChainElements.Count == 0)
  117. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.X509ChainIsEmpty));
  118. // The first element in the cert chain is the leaf certificate
  119. // we want.
  120. X509Certificate2 primaryCertificate = certificateChain.ChainElements[0].Certificate;
  121. X509Certificate2Collection certificateCollection = new X509Certificate2Collection();
  122. for (int i = 1; i < certificateChain.ChainElements.Count; ++i)
  123. {
  124. certificateCollection.Add(certificateChain.ChainElements[i].Certificate);
  125. }
  126. return new X509CertificateEndpointIdentity(primaryCertificate, certificateCollection);
  127. }
  128. internal virtual void EnsureIdentityClaim()
  129. {
  130. }
  131. public override bool Equals(object obj)
  132. {
  133. if (obj == (object)this)
  134. return true;
  135. // as handles null do we need the double null check?
  136. if (obj == null)
  137. return false;
  138. EndpointIdentity otherIdentity = obj as EndpointIdentity;
  139. if (otherIdentity == null)
  140. return false;
  141. return Matches(otherIdentity.IdentityClaim);
  142. }
  143. public override int GetHashCode()
  144. {
  145. return GetClaimComparer().GetHashCode(this.IdentityClaim);
  146. }
  147. public override string ToString()
  148. {
  149. return "identity(" + this.IdentityClaim + ")";
  150. }
  151. internal bool Matches(Claim claim)
  152. {
  153. return GetClaimComparer().Equals(this.IdentityClaim, claim);
  154. }
  155. IEqualityComparer<Claim> GetClaimComparer()
  156. {
  157. if (this.claimComparer == null)
  158. this.claimComparer = Claim.DefaultComparer;
  159. return this.claimComparer;
  160. }
  161. internal static EndpointIdentity ReadIdentity(XmlDictionaryReader reader)
  162. {
  163. if (reader == null)
  164. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
  165. EndpointIdentity readIdentity = null;
  166. reader.MoveToContent();
  167. if (reader.IsEmptyElement)
  168. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.UnexpectedEmptyElementExpectingClaim, XD.AddressingDictionary.Identity.Value, XD.AddressingDictionary.IdentityExtensionNamespace.Value)));
  169. reader.ReadStartElement(XD.AddressingDictionary.Identity, XD.AddressingDictionary.IdentityExtensionNamespace);
  170. if (reader.IsStartElement(XD.AddressingDictionary.Spn, XD.AddressingDictionary.IdentityExtensionNamespace))
  171. readIdentity = new SpnEndpointIdentity(reader.ReadElementString());
  172. else if (reader.IsStartElement(XD.AddressingDictionary.Upn, XD.AddressingDictionary.IdentityExtensionNamespace))
  173. readIdentity = new UpnEndpointIdentity(reader.ReadElementString());
  174. else if (reader.IsStartElement(XD.AddressingDictionary.Dns, XD.AddressingDictionary.IdentityExtensionNamespace))
  175. readIdentity = new DnsEndpointIdentity(reader.ReadElementString());
  176. else if (reader.IsStartElement(XD.XmlSignatureDictionary.KeyInfo, XD.XmlSignatureDictionary.Namespace))
  177. {
  178. reader.ReadStartElement();
  179. if (reader.IsStartElement(XD.XmlSignatureDictionary.X509Data, XD.XmlSignatureDictionary.Namespace))
  180. {
  181. readIdentity = new X509CertificateEndpointIdentity(reader);
  182. }
  183. else if (reader.IsStartElement(XD.XmlSignatureDictionary.RsaKeyValue, XD.XmlSignatureDictionary.Namespace))
  184. {
  185. readIdentity = new RsaEndpointIdentity(reader);
  186. }
  187. else
  188. {
  189. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.UnrecognizedIdentityType, reader.Name, reader.NamespaceURI)));
  190. }
  191. reader.ReadEndElement();
  192. }
  193. else if (reader.NodeType == XmlNodeType.Element)
  194. {
  195. //
  196. // Something unknown
  197. //
  198. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.UnrecognizedIdentityType, reader.Name, reader.NamespaceURI)));
  199. }
  200. else
  201. {
  202. //
  203. // EndpointIdentity element is empty or some other invalid xml
  204. //
  205. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidIdentityElement)));
  206. }
  207. reader.ReadEndElement();
  208. return readIdentity;
  209. }
  210. internal void WriteTo(XmlDictionaryWriter writer)
  211. {
  212. if (writer == null)
  213. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
  214. writer.WriteStartElement(XD.AddressingDictionary.Identity, XD.AddressingDictionary.IdentityExtensionNamespace);
  215. WriteContentsTo(writer);
  216. writer.WriteEndElement();
  217. }
  218. internal virtual void WriteContentsTo(XmlDictionaryWriter writer)
  219. {
  220. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnrecognizedIdentityPropertyType, this.IdentityClaim.GetType().ToString())));
  221. }
  222. }
  223. }