ServiceCredentials.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Description
  5. {
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.IdentityModel.Configuration;
  9. using System.IdentityModel.Selectors;
  10. using System.IdentityModel.Tokens;
  11. using System.Security.Claims;
  12. using System.Security.Cryptography.X509Certificates;
  13. using System.ServiceModel.Channels;
  14. using System.ServiceModel.Security;
  15. using System.ServiceModel.Security.Tokens;
  16. using System.ServiceModel.Dispatcher;
  17. public class ServiceCredentials : SecurityCredentialsManager, IServiceBehavior
  18. {
  19. UserNamePasswordServiceCredential userName;
  20. X509CertificateInitiatorServiceCredential clientCertificate;
  21. X509CertificateRecipientServiceCredential serviceCertificate;
  22. WindowsServiceCredential windows;
  23. IssuedTokenServiceCredential issuedToken;
  24. PeerCredential peer;
  25. SecureConversationServiceCredential secureConversation;
  26. bool useIdentityConfiguration = false;
  27. bool isReadOnly = false;
  28. bool saveBootstrapTokenInSession = true;
  29. IdentityConfiguration identityConfiguration;
  30. ExceptionMapper exceptionMapper;
  31. public ServiceCredentials()
  32. {
  33. this.userName = new UserNamePasswordServiceCredential();
  34. this.clientCertificate = new X509CertificateInitiatorServiceCredential();
  35. this.serviceCertificate = new X509CertificateRecipientServiceCredential();
  36. this.windows = new WindowsServiceCredential();
  37. this.issuedToken = new IssuedTokenServiceCredential();
  38. this.peer = new PeerCredential();
  39. this.secureConversation = new SecureConversationServiceCredential();
  40. this.exceptionMapper = new ExceptionMapper();
  41. this.UseIdentityConfiguration = false;
  42. }
  43. protected ServiceCredentials(ServiceCredentials other)
  44. {
  45. if (other == null)
  46. {
  47. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("other");
  48. }
  49. this.userName = new UserNamePasswordServiceCredential(other.userName);
  50. this.clientCertificate = new X509CertificateInitiatorServiceCredential(other.clientCertificate);
  51. this.serviceCertificate = new X509CertificateRecipientServiceCredential(other.serviceCertificate);
  52. this.windows = new WindowsServiceCredential(other.windows);
  53. this.issuedToken = new IssuedTokenServiceCredential(other.issuedToken);
  54. this.peer = new PeerCredential(other.peer);
  55. this.secureConversation = new SecureConversationServiceCredential(other.secureConversation);
  56. this.identityConfiguration = other.identityConfiguration;
  57. this.saveBootstrapTokenInSession = other.saveBootstrapTokenInSession;
  58. this.exceptionMapper = other.exceptionMapper;
  59. this.UseIdentityConfiguration = other.useIdentityConfiguration;
  60. }
  61. public UserNamePasswordServiceCredential UserNameAuthentication
  62. {
  63. get
  64. {
  65. return this.userName;
  66. }
  67. }
  68. public X509CertificateInitiatorServiceCredential ClientCertificate
  69. {
  70. get
  71. {
  72. return this.clientCertificate;
  73. }
  74. }
  75. public X509CertificateRecipientServiceCredential ServiceCertificate
  76. {
  77. get
  78. {
  79. return this.serviceCertificate;
  80. }
  81. }
  82. public WindowsServiceCredential WindowsAuthentication
  83. {
  84. get
  85. {
  86. return this.windows;
  87. }
  88. }
  89. public IssuedTokenServiceCredential IssuedTokenAuthentication
  90. {
  91. get
  92. {
  93. return this.issuedToken;
  94. }
  95. }
  96. public PeerCredential Peer
  97. {
  98. get
  99. {
  100. return this.peer;
  101. }
  102. }
  103. public SecureConversationServiceCredential SecureConversationAuthentication
  104. {
  105. get
  106. {
  107. return this.secureConversation;
  108. }
  109. }
  110. /// <summary>
  111. /// Gets or sets the ExceptionMapper to be used when throwing exceptions.
  112. /// </summary>
  113. public ExceptionMapper ExceptionMapper
  114. {
  115. get
  116. {
  117. return this.exceptionMapper;
  118. }
  119. set
  120. {
  121. ThrowIfImmutable();
  122. if (value == null)
  123. {
  124. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  125. }
  126. this.exceptionMapper = value;
  127. }
  128. }
  129. public IdentityConfiguration IdentityConfiguration
  130. {
  131. get
  132. {
  133. return this.identityConfiguration;
  134. }
  135. set
  136. {
  137. ThrowIfImmutable();
  138. this.identityConfiguration = value;
  139. }
  140. }
  141. public bool UseIdentityConfiguration
  142. {
  143. get
  144. {
  145. return this.useIdentityConfiguration;
  146. }
  147. set
  148. {
  149. ThrowIfImmutable();
  150. this.useIdentityConfiguration = value;
  151. if (this.identityConfiguration == null && this.useIdentityConfiguration)
  152. {
  153. this.identityConfiguration = new IdentityConfiguration();
  154. }
  155. }
  156. }
  157. internal static ServiceCredentials CreateDefaultCredentials()
  158. {
  159. return new ServiceCredentials();
  160. }
  161. public override SecurityTokenManager CreateSecurityTokenManager()
  162. {
  163. if (this.useIdentityConfiguration)
  164. {
  165. //
  166. // Note: the token manager we create here is always a wrapper over the default collection of token handlers
  167. //
  168. return new FederatedSecurityTokenManager(this.Clone());
  169. }
  170. else
  171. {
  172. return new ServiceCredentialsSecurityTokenManager(this.Clone());
  173. }
  174. }
  175. protected virtual ServiceCredentials CloneCore()
  176. {
  177. return new ServiceCredentials(this);
  178. }
  179. public ServiceCredentials Clone()
  180. {
  181. ServiceCredentials result = CloneCore();
  182. if (result == null || result.GetType() != this.GetType())
  183. {
  184. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.CloneNotImplementedCorrectly, this.GetType(), (result != null) ? result.ToString() : "null")));
  185. }
  186. return result;
  187. }
  188. void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
  189. {
  190. //
  191. // Only pass a name if there was a name explicitly given to this class, otherwise ServiceConfig will require
  192. // a config section with the default configuration.
  193. //
  194. if (this.UseIdentityConfiguration)
  195. {
  196. ConfigureServiceHost(serviceHostBase);
  197. }
  198. }
  199. /// <summary>
  200. /// Helper method that Initializes the SecurityTokenManager used by the ServiceHost.
  201. /// By default the method sets the SecurityTokenHandlers initialized with IdentityConfiguration on the ServiceHost.
  202. /// </summary>
  203. /// <param name="serviceHost">ServiceHost instance to configure with FederatedSecurityTokenManager.</param>
  204. /// <exception cref="ArgumentNullException">One of the input argument is null.</exception>
  205. void ConfigureServiceHost(ServiceHostBase serviceHost)
  206. {
  207. if (serviceHost == null)
  208. {
  209. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceHost");
  210. }
  211. // Throw if the serviceHost is in a bad state to do the configuration
  212. if (!(serviceHost.State == CommunicationState.Created || serviceHost.State == CommunicationState.Opening))
  213. {
  214. throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4041, serviceHost));
  215. }
  216. #pragma warning suppress 56506
  217. if (this.ServiceCertificate != null)
  218. {
  219. X509Certificate2 serverCert = this.ServiceCertificate.Certificate;
  220. if (serverCert != null)
  221. {
  222. this.IdentityConfiguration.ServiceCertificate = serverCert;
  223. }
  224. }
  225. if (this.IssuedTokenAuthentication != null && this.IssuedTokenAuthentication.KnownCertificates != null && this.IssuedTokenAuthentication.KnownCertificates.Count > 0)
  226. {
  227. this.IdentityConfiguration.KnownIssuerCertificates = new List<X509Certificate2> (this.IssuedTokenAuthentication.KnownCertificates);
  228. }
  229. //
  230. // Initialize the service configuration
  231. //
  232. if (!this.IdentityConfiguration.IsInitialized)
  233. {
  234. this.IdentityConfiguration.Initialize();
  235. }
  236. //
  237. #pragma warning suppress 56506 // serviceHost.Authorization is never null.
  238. if (serviceHost.Authorization.ServiceAuthorizationManager == null)
  239. {
  240. serviceHost.Authorization.ServiceAuthorizationManager = new IdentityModelServiceAuthorizationManager();
  241. }
  242. else if (!(serviceHost.Authorization.ServiceAuthorizationManager is IdentityModelServiceAuthorizationManager))
  243. {
  244. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4039)));
  245. }
  246. // If SecuritySessionTokenHandler is being used then null the WCF SecurityStateEncoder.
  247. if ((this.IdentityConfiguration.SecurityTokenHandlers[typeof(SecurityContextSecurityToken)] != null) &&
  248. (serviceHost.Credentials.SecureConversationAuthentication.SecurityStateEncoder == null))
  249. {
  250. serviceHost.Credentials.SecureConversationAuthentication.SecurityStateEncoder = new NoOpSecurityStateEncoder();
  251. }
  252. }
  253. void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
  254. {
  255. if (parameters == null)
  256. {
  257. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
  258. }
  259. // throw if bindingParameters already has a SecurityCredentialsManager
  260. SecurityCredentialsManager otherCredentialsManager = parameters.Find<SecurityCredentialsManager>();
  261. if (otherCredentialsManager != null)
  262. {
  263. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MultipleSecurityCredentialsManagersInServiceBindingParameters, otherCredentialsManager)));
  264. }
  265. parameters.Add(this);
  266. }
  267. void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
  268. {
  269. for (int i = 0; i < serviceHostBase.ChannelDispatchers.Count; i++)
  270. {
  271. ChannelDispatcher channelDispatcher = serviceHostBase.ChannelDispatchers[i] as ChannelDispatcher;
  272. if (channelDispatcher != null && !ServiceMetadataBehavior.IsHttpGetMetadataDispatcher(description, channelDispatcher))
  273. {
  274. foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
  275. {
  276. DispatchRuntime behavior = endpointDispatcher.DispatchRuntime;
  277. behavior.RequireClaimsPrincipalOnOperationContext = this.useIdentityConfiguration;
  278. }
  279. }
  280. }
  281. }
  282. internal void MakeReadOnly()
  283. {
  284. this.isReadOnly = true;
  285. this.ClientCertificate.MakeReadOnly();
  286. this.IssuedTokenAuthentication.MakeReadOnly();
  287. this.Peer.MakeReadOnly();
  288. this.SecureConversationAuthentication.MakeReadOnly();
  289. this.ServiceCertificate.MakeReadOnly();
  290. this.UserNameAuthentication.MakeReadOnly();
  291. this.WindowsAuthentication.MakeReadOnly();
  292. }
  293. void ThrowIfImmutable()
  294. {
  295. if (this.isReadOnly)
  296. {
  297. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
  298. }
  299. }
  300. }
  301. }