//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel.Security { using System; using System.Collections.ObjectModel; using System.IdentityModel.Configuration; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.Web.Configuration; using System.Web.Hosting; /// /// ServiceHost for registering SecurityTokenService. The ServiceHost will have multiple endpoints /// registered based on the number of listeners registered in the config. /// public class WSTrustServiceHost : ServiceHost { WSTrustServiceContract _serviceContract; /// /// Initializes an instance of /// /// SecurityTokenServiceConfiguration instance used to initialize this ServiceHost. /// BaseAddress collection for the service host /// /// A default WSTrustServiceContract is instantiated using the SecurityTokenServiceConfiguration instance. /// The SecurityTokenServiceConfiguration instance is used for one-time initialization of the ServiceHost and /// setting properties on the configuration instance after the host is initialization may not result in /// behavioral changes. /// public WSTrustServiceHost(SecurityTokenServiceConfiguration securityTokenServiceConfiguration, params Uri[] baseAddresses) : this(new WSTrustServiceContract(securityTokenServiceConfiguration), baseAddresses) { } /// /// Initializes an instance of /// /// ServiceContract implementation to use. /// BaseAddress collection for the service host /// One of the input argument is null. public WSTrustServiceHost(WSTrustServiceContract serviceContract, params Uri[] baseAddresses) : base(serviceContract, baseAddresses) { if (serviceContract == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceContract"); } if (serviceContract.SecurityTokenServiceConfiguration == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceContract.SecurityTokenServiceConfiguration"); } _serviceContract = serviceContract; } /// /// Gets the WSTrustServiceContract associated with this instance. /// public WSTrustServiceContract ServiceContract { get { return _serviceContract; } } /// /// Gets the SecurityTokenServiceConfiguration /// public SecurityTokenServiceConfiguration SecurityTokenServiceConfiguration { get { return _serviceContract.SecurityTokenServiceConfiguration; } } /// /// Configures metadata (WSDL) for the service host. The method loops through the /// base addresses, and adds mex endpoints for http, https, net.tcp and net.pipe /// addresses, only when no mex endpoints have been previously added by the user. /// For http and htps addresses, HTTP and HTTPS "Get" mechanism for WSDL retrieval /// is enabled. /// protected virtual void ConfigureMetadata() { if (this.BaseAddresses == null || this.BaseAddresses.Count == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID3140)); } // Check if a ServiceMetadataBehavior is added. ServiceMetadataBehavior metadataBehavior = Description.Behaviors.Find(); if (metadataBehavior == null) { metadataBehavior = new ServiceMetadataBehavior(); Description.Behaviors.Add(metadataBehavior); } // Check if an Mex endpoint has alread been added by user. This can be enabled through // configuration. bool isMexEndpointAlreadyAdded = (Description.Endpoints.Find(typeof(IMetadataExchange)) != null); Binding mexBinding = null; foreach (Uri baseAddress in this.BaseAddresses) { if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeHttp)) { metadataBehavior.HttpGetEnabled = true; mexBinding = MetadataExchangeBindings.CreateMexHttpBinding(); } else if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeHttps)) { metadataBehavior.HttpsGetEnabled = true; mexBinding = MetadataExchangeBindings.CreateMexHttpsBinding(); } else if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeNetTcp)) { mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); } else if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeNetPipe)) { mexBinding = MetadataExchangeBindings.CreateMexNamedPipeBinding(); } if (!isMexEndpointAlreadyAdded && (mexBinding != null)) { AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, mexBinding, "mex"); } mexBinding = null; } } /// /// Loads the service description information from the configuration file and /// applies it to the runtime being constructed. /// protected override void ApplyConfiguration() { base.ApplyConfiguration(); // // Configure metadata endpoints // WSTrustServiceContract serviceContract = (WSTrustServiceContract)base.SingletonInstance; if (!serviceContract.SecurityTokenServiceConfiguration.DisableWsdl) { ConfigureMetadata(); } } /// /// Override of the base class method. Configures the on the /// service host and then invokes the base implementation. /// protected override void InitializeRuntime() { if (Description.Endpoints.Count == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID3097))); } UpdateServiceConfiguration(); base.InitializeRuntime(); } /// /// Overrides the on the ServiceHost Credentials /// with the SecurityTokenServiceConfiguration. /// protected virtual void UpdateServiceConfiguration() { Credentials.IdentityConfiguration = _serviceContract.SecurityTokenServiceConfiguration; Credentials.UseIdentityConfiguration = true; } } }