TlsnegoTokenAuthenticator.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System;
  7. using System.Collections.ObjectModel;
  8. using System.IdentityModel.Policy;
  9. using System.IdentityModel.Selectors;
  10. using System.IdentityModel.Tokens;
  11. using System.Runtime;
  12. using System.Security.Cryptography.X509Certificates;
  13. using System.Security.Principal;
  14. using System.ServiceModel;
  15. using System.Xml;
  16. using SchProtocols = System.IdentityModel.SchProtocols;
  17. sealed class TlsnegoTokenAuthenticator : SspiNegotiationTokenAuthenticator
  18. {
  19. SecurityTokenAuthenticator clientTokenAuthenticator;
  20. SecurityTokenProvider serverTokenProvider;
  21. X509SecurityToken serverToken;
  22. bool mapCertificateToWindowsAccount;
  23. public TlsnegoTokenAuthenticator()
  24. : base()
  25. {
  26. // empty
  27. }
  28. public SecurityTokenAuthenticator ClientTokenAuthenticator
  29. {
  30. get
  31. {
  32. return this.clientTokenAuthenticator;
  33. }
  34. set
  35. {
  36. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  37. this.clientTokenAuthenticator = value;
  38. }
  39. }
  40. public SecurityTokenProvider ServerTokenProvider
  41. {
  42. get
  43. {
  44. return this.serverTokenProvider;
  45. }
  46. set
  47. {
  48. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  49. this.serverTokenProvider = value;
  50. }
  51. }
  52. public bool MapCertificateToWindowsAccount
  53. {
  54. get
  55. {
  56. return this.mapCertificateToWindowsAccount;
  57. }
  58. set
  59. {
  60. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  61. this.mapCertificateToWindowsAccount = value;
  62. }
  63. }
  64. X509SecurityToken ValidateX509Token(SecurityToken token)
  65. {
  66. X509SecurityToken result = token as X509SecurityToken;
  67. if (result == null)
  68. {
  69. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TokenProviderReturnedBadToken, token == null ? "<null>" : token.GetType().ToString())));
  70. }
  71. SecurityUtils.EnsureCertificateCanDoKeyExchange(result.Certificate);
  72. return result;
  73. }
  74. // overrides
  75. public override XmlDictionaryString NegotiationValueType
  76. {
  77. get
  78. {
  79. if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
  80. {
  81. return XD.TrustApr2004Dictionary.TlsnegoValueTypeUri;
  82. }
  83. else if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrust13)
  84. {
  85. return DXD.TrustDec2005Dictionary.TlsnegoValueTypeUri;
  86. }
  87. // Not supported
  88. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException());
  89. }
  90. }
  91. public override void OnOpen(TimeSpan timeout)
  92. {
  93. if (this.serverTokenProvider == null)
  94. {
  95. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoServerX509TokenProvider)));
  96. }
  97. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  98. SecurityUtils.OpenTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
  99. if (this.clientTokenAuthenticator != null)
  100. {
  101. SecurityUtils.OpenTokenAuthenticatorIfRequired(this.clientTokenAuthenticator, timeoutHelper.RemainingTime());
  102. }
  103. SecurityToken token = this.serverTokenProvider.GetToken(timeoutHelper.RemainingTime());
  104. this.serverToken = ValidateX509Token(token);
  105. base.OnOpen(timeoutHelper.RemainingTime());
  106. }
  107. public override void OnClose(TimeSpan timeout)
  108. {
  109. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  110. if (this.serverTokenProvider != null)
  111. {
  112. SecurityUtils.CloseTokenProviderIfRequired(this.serverTokenProvider, timeoutHelper.RemainingTime());
  113. this.serverTokenProvider = null;
  114. }
  115. if (this.clientTokenAuthenticator != null)
  116. {
  117. SecurityUtils.CloseTokenAuthenticatorIfRequired(this.clientTokenAuthenticator, timeoutHelper.RemainingTime());
  118. this.clientTokenAuthenticator = null;
  119. }
  120. if (this.serverToken != null)
  121. {
  122. this.serverToken = null;
  123. }
  124. base.OnClose(timeoutHelper.RemainingTime());
  125. }
  126. public override void OnAbort()
  127. {
  128. if (this.serverTokenProvider != null)
  129. {
  130. SecurityUtils.AbortTokenProviderIfRequired(this.serverTokenProvider);
  131. this.serverTokenProvider = null;
  132. }
  133. if (this.clientTokenAuthenticator != null)
  134. {
  135. SecurityUtils.AbortTokenAuthenticatorIfRequired(this.clientTokenAuthenticator);
  136. this.clientTokenAuthenticator = null;
  137. }
  138. if (this.serverToken != null)
  139. {
  140. this.serverToken = null;
  141. }
  142. base.OnAbort();
  143. }
  144. protected override void ValidateIncomingBinaryNegotiation(BinaryNegotiation incomingNego)
  145. {
  146. // Accept both strings for WSTrustFeb2005
  147. if (incomingNego != null &&
  148. incomingNego.ValueTypeUri != this.NegotiationValueType.Value &&
  149. this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
  150. {
  151. incomingNego.Validate(DXD.TrustDec2005Dictionary.TlsnegoValueTypeUri);
  152. }
  153. else
  154. {
  155. base.ValidateIncomingBinaryNegotiation(incomingNego);
  156. }
  157. }
  158. protected override SspiNegotiationTokenAuthenticatorState CreateSspiState(byte[] incomingBlob, string incomingValueTypeUri)
  159. {
  160. TlsSspiNegotiation tlsNegotiation = new TlsSspiNegotiation(SchProtocols.TlsServer | SchProtocols.Ssl3Server,
  161. this.serverToken.Certificate, this.ClientTokenAuthenticator != null);
  162. // Echo only for TrustFeb2005 and ValueType mismatch
  163. if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005 &&
  164. this.NegotiationValueType.Value != incomingValueTypeUri)
  165. {
  166. tlsNegotiation.IncomingValueTypeUri = incomingValueTypeUri;
  167. }
  168. return new SspiNegotiationTokenAuthenticatorState(tlsNegotiation);
  169. }
  170. protected override BinaryNegotiation GetOutgoingBinaryNegotiation(ISspiNegotiation sspiNegotiation, byte[] outgoingBlob)
  171. {
  172. TlsSspiNegotiation tlsNegotiation = sspiNegotiation as TlsSspiNegotiation;
  173. // Echo only for TrustFeb2005 and ValueType mismatch
  174. if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005 &&
  175. tlsNegotiation != null &&
  176. tlsNegotiation.IncomingValueTypeUri != null)
  177. {
  178. return new BinaryNegotiation(tlsNegotiation.IncomingValueTypeUri, outgoingBlob);
  179. }
  180. else
  181. {
  182. return base.GetOutgoingBinaryNegotiation(sspiNegotiation, outgoingBlob);
  183. }
  184. }
  185. protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation)
  186. {
  187. TlsSspiNegotiation tlsNegotiation = (TlsSspiNegotiation)sspiNegotiation;
  188. if (tlsNegotiation.IsValidContext == false)
  189. {
  190. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.InvalidSspiNegotiation)));
  191. }
  192. if (this.ClientTokenAuthenticator == null)
  193. {
  194. return EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
  195. }
  196. X509Certificate2 clientCertificate = tlsNegotiation.RemoteCertificate;
  197. if (clientCertificate == null)
  198. {
  199. // isAnonymous is false. So, fail the negotiation
  200. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityTokenValidationException(SR.GetString(SR.ClientCertificateNotProvided)));
  201. }
  202. ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies;
  203. if (this.ClientTokenAuthenticator != null)
  204. {
  205. X509SecurityToken clientToken;
  206. WindowsIdentity preMappedIdentity;
  207. if (!this.MapCertificateToWindowsAccount || !tlsNegotiation.TryGetContextIdentity(out preMappedIdentity))
  208. {
  209. clientToken = new X509SecurityToken(clientCertificate);
  210. }
  211. else
  212. {
  213. clientToken = new X509WindowsSecurityToken(clientCertificate, preMappedIdentity, preMappedIdentity.AuthenticationType, true);
  214. preMappedIdentity.Dispose();
  215. }
  216. authorizationPolicies = this.ClientTokenAuthenticator.ValidateToken(clientToken);
  217. clientToken.Dispose();
  218. }
  219. else
  220. {
  221. authorizationPolicies = EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
  222. }
  223. return authorizationPolicies;
  224. }
  225. }
  226. }