MessageSecurityOverTcp.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel
  5. {
  6. using System;
  7. using System.ComponentModel;
  8. using System.Runtime;
  9. using System.Runtime.CompilerServices;
  10. using System.ServiceModel.Channels;
  11. using System.ServiceModel.Security;
  12. using System.ServiceModel.Security.Tokens;
  13. public sealed class MessageSecurityOverTcp
  14. {
  15. internal const MessageCredentialType DefaultClientCredentialType = MessageCredentialType.Windows;
  16. MessageCredentialType clientCredentialType;
  17. SecurityAlgorithmSuite algorithmSuite;
  18. bool wasAlgorithmSuiteSet;
  19. public MessageSecurityOverTcp()
  20. {
  21. clientCredentialType = DefaultClientCredentialType;
  22. algorithmSuite = SecurityAlgorithmSuite.Default;
  23. }
  24. [DefaultValue(MessageSecurityOverTcp.DefaultClientCredentialType)]
  25. public MessageCredentialType ClientCredentialType
  26. {
  27. get { return this.clientCredentialType; }
  28. set
  29. {
  30. if (!MessageCredentialTypeHelper.IsDefined(value))
  31. {
  32. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
  33. }
  34. this.clientCredentialType = value;
  35. }
  36. }
  37. [DefaultValue(typeof(SecurityAlgorithmSuite), System.ServiceModel.Configuration.ConfigurationStrings.Default)]
  38. public SecurityAlgorithmSuite AlgorithmSuite
  39. {
  40. get { return this.algorithmSuite; }
  41. set
  42. {
  43. if (value == null)
  44. {
  45. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  46. }
  47. this.algorithmSuite = value;
  48. wasAlgorithmSuiteSet = true;
  49. }
  50. }
  51. internal bool WasAlgorithmSuiteSet
  52. {
  53. get { return this.wasAlgorithmSuiteSet; }
  54. }
  55. [MethodImpl(MethodImplOptions.NoInlining)]
  56. internal SecurityBindingElement CreateSecurityBindingElement(bool isSecureTransportMode, bool isReliableSession, BindingElement transportBindingElement)
  57. {
  58. SecurityBindingElement result;
  59. SecurityBindingElement oneShotSecurity;
  60. if (isSecureTransportMode)
  61. {
  62. switch (this.clientCredentialType)
  63. {
  64. case MessageCredentialType.None:
  65. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientCredentialTypeMustBeSpecifiedForMixedMode)));
  66. case MessageCredentialType.UserName:
  67. oneShotSecurity = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
  68. break;
  69. case MessageCredentialType.Certificate:
  70. oneShotSecurity = SecurityBindingElement.CreateCertificateOverTransportBindingElement();
  71. break;
  72. case MessageCredentialType.Windows:
  73. oneShotSecurity = SecurityBindingElement.CreateSspiNegotiationOverTransportBindingElement(true);
  74. break;
  75. case MessageCredentialType.IssuedToken:
  76. oneShotSecurity = SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(), this.algorithmSuite));
  77. break;
  78. default:
  79. Fx.Assert("unknown ClientCredentialType");
  80. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  81. }
  82. result = SecurityBindingElement.CreateSecureConversationBindingElement(oneShotSecurity);
  83. }
  84. else
  85. {
  86. switch (this.clientCredentialType)
  87. {
  88. case MessageCredentialType.None:
  89. oneShotSecurity = SecurityBindingElement.CreateSslNegotiationBindingElement(false, true);
  90. break;
  91. case MessageCredentialType.UserName:
  92. // require cancellation so that impersonation is possible
  93. oneShotSecurity = SecurityBindingElement.CreateUserNameForSslBindingElement(true);
  94. break;
  95. case MessageCredentialType.Certificate:
  96. oneShotSecurity = SecurityBindingElement.CreateSslNegotiationBindingElement(true, true);
  97. break;
  98. case MessageCredentialType.Windows:
  99. // require cancellation so that impersonation is possible
  100. oneShotSecurity = SecurityBindingElement.CreateSspiNegotiationBindingElement(true);
  101. break;
  102. case MessageCredentialType.IssuedToken:
  103. oneShotSecurity = SecurityBindingElement.CreateIssuedTokenForSslBindingElement(IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(), this.algorithmSuite), true);
  104. break;
  105. default:
  106. Fx.Assert("unknown ClientCredentialType");
  107. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  108. }
  109. result = SecurityBindingElement.CreateSecureConversationBindingElement(oneShotSecurity, true);
  110. }
  111. // set the algorithm suite and issued token params if required
  112. result.DefaultAlgorithmSuite = oneShotSecurity.DefaultAlgorithmSuite = this.AlgorithmSuite;
  113. result.IncludeTimestamp = true;
  114. if (!isReliableSession)
  115. {
  116. result.LocalServiceSettings.ReconnectTransportOnFailure = false;
  117. result.LocalClientSettings.ReconnectTransportOnFailure = false;
  118. }
  119. else
  120. {
  121. result.LocalServiceSettings.ReconnectTransportOnFailure = true;
  122. result.LocalClientSettings.ReconnectTransportOnFailure = true;
  123. }
  124. // since a session is always bootstrapped, configure the transition sct to live for a short time only
  125. oneShotSecurity.LocalServiceSettings.IssuedCookieLifetime = SpnegoTokenAuthenticator.defaultServerIssuedTransitionTokenLifetime;
  126. result.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
  127. oneShotSecurity.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
  128. return result;
  129. }
  130. internal static bool TryCreate(SecurityBindingElement sbe, bool isReliableSession, BindingElement transportBindingElement, out MessageSecurityOverTcp messageSecurity)
  131. {
  132. messageSecurity = null;
  133. if (sbe == null)
  134. return false;
  135. // do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
  136. if (!sbe.IncludeTimestamp)
  137. return false;
  138. if (sbe.MessageSecurityVersion != MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11
  139. && sbe.MessageSecurityVersion != MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
  140. {
  141. return false;
  142. }
  143. if (sbe.SecurityHeaderLayout != SecurityProtocolFactory.defaultSecurityHeaderLayout)
  144. return false;
  145. MessageCredentialType clientCredentialType;
  146. SecurityBindingElement bootstrapSecurity;
  147. if (!SecurityBindingElement.IsSecureConversationBinding(sbe, true, out bootstrapSecurity))
  148. return false;
  149. bool isSecureTransportMode = bootstrapSecurity is TransportSecurityBindingElement;
  150. IssuedSecurityTokenParameters infocardParameters;
  151. if (isSecureTransportMode)
  152. {
  153. if (SecurityBindingElement.IsUserNameOverTransportBinding(bootstrapSecurity))
  154. clientCredentialType = MessageCredentialType.UserName;
  155. else if (SecurityBindingElement.IsCertificateOverTransportBinding(bootstrapSecurity))
  156. clientCredentialType = MessageCredentialType.Certificate;
  157. else if (SecurityBindingElement.IsSspiNegotiationOverTransportBinding(bootstrapSecurity, true))
  158. clientCredentialType = MessageCredentialType.Windows;
  159. else if (SecurityBindingElement.IsIssuedTokenOverTransportBinding(bootstrapSecurity, out infocardParameters))
  160. {
  161. if (!IssuedSecurityTokenParameters.IsInfoCardParameters(
  162. infocardParameters,
  163. new SecurityStandardsManager(
  164. bootstrapSecurity.MessageSecurityVersion,
  165. new WSSecurityTokenSerializer(
  166. bootstrapSecurity.MessageSecurityVersion.SecurityVersion,
  167. bootstrapSecurity.MessageSecurityVersion.TrustVersion,
  168. bootstrapSecurity.MessageSecurityVersion.SecureConversationVersion,
  169. true,
  170. null, null, null))))
  171. return false;
  172. clientCredentialType = MessageCredentialType.IssuedToken;
  173. }
  174. else
  175. {
  176. // the standard binding does not support None client credential type in mixed mode
  177. return false;
  178. }
  179. }
  180. else
  181. {
  182. if (SecurityBindingElement.IsUserNameForSslBinding(bootstrapSecurity, true))
  183. clientCredentialType = MessageCredentialType.UserName;
  184. else if (SecurityBindingElement.IsSslNegotiationBinding(bootstrapSecurity, true, true))
  185. clientCredentialType = MessageCredentialType.Certificate;
  186. else if (SecurityBindingElement.IsSspiNegotiationBinding(bootstrapSecurity, true))
  187. clientCredentialType = MessageCredentialType.Windows;
  188. else if (SecurityBindingElement.IsIssuedTokenForSslBinding(bootstrapSecurity, true, out infocardParameters))
  189. {
  190. if (!IssuedSecurityTokenParameters.IsInfoCardParameters(
  191. infocardParameters,
  192. new SecurityStandardsManager(
  193. bootstrapSecurity.MessageSecurityVersion,
  194. new WSSecurityTokenSerializer(
  195. bootstrapSecurity.MessageSecurityVersion.SecurityVersion,
  196. bootstrapSecurity.MessageSecurityVersion.TrustVersion,
  197. bootstrapSecurity.MessageSecurityVersion.SecureConversationVersion,
  198. true,
  199. null, null, null))))
  200. return false;
  201. clientCredentialType = MessageCredentialType.IssuedToken;
  202. }
  203. else if (SecurityBindingElement.IsSslNegotiationBinding(bootstrapSecurity, false, true))
  204. clientCredentialType = MessageCredentialType.None;
  205. else
  206. return false;
  207. }
  208. messageSecurity = new MessageSecurityOverTcp();
  209. messageSecurity.ClientCredentialType = clientCredentialType;
  210. // set the algorithm suite and issued token params if required
  211. if (clientCredentialType != MessageCredentialType.IssuedToken)
  212. {
  213. messageSecurity.AlgorithmSuite = bootstrapSecurity.DefaultAlgorithmSuite;
  214. }
  215. return true;
  216. }
  217. internal bool InternalShouldSerialize()
  218. {
  219. return this.ClientCredentialType != NetTcpDefaults.MessageSecurityClientCredentialType
  220. || this.AlgorithmSuite != NetTcpDefaults.MessageSecurityAlgorithmSuite;
  221. }
  222. }
  223. }