Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / System.ServiceModel.Activation / System / ServiceModel / Activation / HostedAspNetEnvironment.cs / 1407647 / HostedAspNetEnvironment.cs
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Permissions;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Threading;
using System.Transactions;
using System.Web;
using System.Web.Compilation;
using System.Web.Configuration;
class HostedAspNetEnvironment : AspNetEnvironment
{
// used to cache SiteName|ApplicationVirtualPath
static string cachedServiceReference;
// used to cache if windows auth is being used
Nullable isWindowsAuthentication;
HostedAspNetEnvironment()
: base()
{
}
public override bool AspNetCompatibilityEnabled
{
get
{
return ServiceHostingEnvironment.AspNetCompatibilityEnabled;
}
}
public override string ConfigurationPath
{
get
{
if (ServiceHostingEnvironment.CurrentVirtualPath != null)
{
return ServiceHostingEnvironment.CurrentVirtualPath + "web.config";
}
else
{
return base.ConfigurationPath;
}
}
}
public override bool IsConfigurationBased
{
get
{
return ServiceHostingEnvironment.IsConfigurationBased;
}
}
public override string CurrentVirtualPath
{
get
{
return ServiceHostingEnvironment.CurrentVirtualPath;
}
}
public override string XamlFileBaseLocation
{
get
{
return ServiceHostingEnvironment.XamlFileBaseLocation;
}
}
public static void Enable()
{
AspNetEnvironment hostedEnvironment = new HostedAspNetEnvironment();
AspNetEnvironment.Current = hostedEnvironment;
}
public override void AddHostingBehavior(ServiceHostBase serviceHost, ServiceDescription description)
{
VirtualPathExtension virtualPathExtension = serviceHost.Extensions.Find();
if (virtualPathExtension != null)
{
description.Behaviors.Add(new HostedBindingBehavior(virtualPathExtension));
}
}
public override bool IsWebConfigAboveApplication(object configHostingContext)
{
WebContext context = configHostingContext as WebContext;
if (context != null)
{
return context.ApplicationLevel == WebApplicationLevel.AboveApplication;
}
return false; // if we don't recognize the context we can't enforce the special web.config logic
}
public override void EnsureCompatibilityRequirements(ServiceDescription description)
{
AspNetCompatibilityRequirementsAttribute aspNetCompatibilityRequirements = description.Behaviors.Find();
if (aspNetCompatibilityRequirements == null)
{
aspNetCompatibilityRequirements = new AspNetCompatibilityRequirementsAttribute();
description.Behaviors.Add(aspNetCompatibilityRequirements);
}
}
public override bool TryGetFullVirtualPath(out string virtualPath)
{
// subclass will use the virtual path from the compiled string
virtualPath = ServiceHostingEnvironment.FullVirtualPath;
return true;
}
public override string GetAnnotationFromHost(ServiceHostBase host)
{
//Format Website name\Application Virtual Path|\relative service virtual path|serviceName
if (host != null && host.Extensions != null)
{
string serviceName = (host.Description != null) ? host.Description.Name : string.Empty;
string application = ServiceHostingEnvironment.ApplicationVirtualPath;
string servicePath = string.Empty;
VirtualPathExtension extension = host.Extensions.Find();
if (extension != null && extension.VirtualPath != null)
{
servicePath = extension.VirtualPath.Replace("~", application + "|");
return string.Format(CultureInfo.InvariantCulture, "{0}{1}|{2}", ServiceHostingEnvironment.SiteName, servicePath, serviceName);
}
}
if (string.IsNullOrEmpty(HostedAspNetEnvironment.cachedServiceReference))
{
HostedAspNetEnvironment.cachedServiceReference = string.Format(CultureInfo.InvariantCulture, "{0}{1}", ServiceHostingEnvironment.SiteName, ServiceHostingEnvironment.ApplicationVirtualPath);
}
return HostedAspNetEnvironment.cachedServiceReference;
}
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
public override void EnsureAllReferencedAssemblyLoaded()
{
BuildManager.GetReferencedAssemblies();
}
public override BaseUriWithWildcard GetBaseUri(string transportScheme, Uri listenUri)
{
BaseUriWithWildcard baseAddress = null;
HostedTransportConfigurationBase hostedConfiguration =
HostedTransportConfigurationManager.GetConfiguration(transportScheme) as HostedTransportConfigurationBase;
if (hostedConfiguration != null)
{
baseAddress = hostedConfiguration.FindBaseAddress(listenUri);
if (baseAddress == null)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_TransportBindingNotFound(listenUri.ToString())));
}
}
return baseAddress;
}
public override void ValidateHttpSettings(string virtualPath, bool isMetadataListener, bool usingDefaultSpnList, ref AuthenticationSchemes supportedSchemes, ref ExtendedProtectionPolicy extendedProtectionPolicy, ref string realm)
{
// Verify the authentication settings
AuthenticationSchemes hostedSupportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(virtualPath);
if (supportedSchemes == AuthenticationSchemes.Anonymous)
{
if ((hostedSupportedSchemes & AuthenticationSchemes.Anonymous) == 0)
{
if (isMetadataListener)
{
// We apply IIS settings to the ChannelListener to fix mex endpoints.
if ((hostedSupportedSchemes & AuthenticationSchemes.Negotiate) != AuthenticationSchemes.None)
{
supportedSchemes = AuthenticationSchemes.Negotiate;
}
else
{
supportedSchemes = hostedSupportedSchemes;
}
}
}
}
if ((supportedSchemes & hostedSupportedSchemes) == 0)
{
if (AuthenticationSchemesHelper.IsWindowsAuth(supportedSchemes))
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireWindowsAuth));
}
else
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireOtherAuth(supportedSchemes.ToString())));
}
}
if (supportedSchemes != AuthenticationSchemes.Anonymous)
{
//Compare the ExtendedProtectionPolicy setttings to IIS
ExtendedProtectionPolicy iisPolicy = HostedTransportConfigurationManager.MetabaseSettings.GetExtendedProtectionPolicy(virtualPath);
if (iisPolicy == null) //OS doesn't support CBT
{
if (extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.Always)
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.ExtendedProtectionNotSupported));
}
}
else
{
if (isMetadataListener && ChannelBindingUtility.IsDefaultPolicy(extendedProtectionPolicy))
{
//push the IIS policy onto the metadataListener if and only if the default policy is
//in force. policy for non metadata listeners will still have to match IIS policy.
extendedProtectionPolicy = iisPolicy;
}
else
{
if (!ChannelBindingUtility.AreEqual(iisPolicy, extendedProtectionPolicy))
{
string mismatchErrorMessage;
if (iisPolicy.PolicyEnforcement != extendedProtectionPolicy.PolicyEnforcement)
{
mismatchErrorMessage = SR.ExtendedProtectionPolicyEnforcementMismatch(iisPolicy.PolicyEnforcement, extendedProtectionPolicy.PolicyEnforcement);
}
else if (iisPolicy.ProtectionScenario != extendedProtectionPolicy.ProtectionScenario)
{
mismatchErrorMessage = SR.ExtendedProtectionPolicyScenarioMismatch(iisPolicy.ProtectionScenario, extendedProtectionPolicy.ProtectionScenario);
}
else
{
Fx.Assert(iisPolicy.CustomChannelBinding != extendedProtectionPolicy.CustomChannelBinding, "new case in ChannelBindingUtility.AreEqual to account for");
mismatchErrorMessage = SR.ExtendedProtectionPolicyCustomChannelBindingMismatch;
}
if (mismatchErrorMessage != null)
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(mismatchErrorMessage)));
}
}
//when using the default SPN list we auto generate, we should make sure that the IIS policy is also the default...
ServiceNameCollection listenerSpnList = usingDefaultSpnList ? null : extendedProtectionPolicy.CustomServiceNames;
if (!ChannelBindingUtility.IsSubset(iisPolicy.CustomServiceNames, listenerSpnList))
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(SR.Hosting_ExtendedProtectionSPNListNotSubset)));
}
}
}
}
// Do not set realm for Cassini.
if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
{
// Set the realm
realm = HostedTransportConfigurationManager.MetabaseSettings.GetRealm(virtualPath);
}
}
public override bool ValidateHttpsSettings(string virtualPath, ref Nullable requireClientCertificate)
{
bool useHostedClientCertificateMapping = false;
// Do not validate settings for Cassini. Actually current implementation of Cassini does not support HTTPS.
if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
{
// Validate Ssl Settings
HttpAccessSslFlags sslFlags = HostedTransportConfigurationManager.MetabaseSettings.GetAccessSslFlags(virtualPath);
HttpAccessSslFlags channelListenerSslFlags = HttpAccessSslFlags.None;
// Validating SSL flags. SslRequireCert means "require client certificate" in IIS terminology.
bool mismatched = false;
if ((sslFlags & HttpAccessSslFlags.SslRequireCert) != 0)
{
// Require SSL.
if (requireClientCertificate.HasValue)
{
if (!requireClientCertificate.Value)
{
// IIS requires client cert but the binding does not.
mismatched = true;
}
}
else
{
// We apply IIS settings to the ChannelListener to fix mex endpoints.
requireClientCertificate = true;
}
}
else if (requireClientCertificate.GetValueOrDefault())
{
// IIS does not require client cert but the binding does.
channelListenerSslFlags |= HttpAccessSslFlags.SslRequireCert;
mismatched = true;
}
if (!mismatched)
{
if ((sslFlags & HttpAccessSslFlags.SslMapCert) != 0)
{
useHostedClientCertificateMapping = true;
}
}
if (mismatched)
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_SslSettingsMisconfigured(
channelListenerSslFlags.ToString(), sslFlags.ToString())));
}
}
return useHostedClientCertificateMapping;
}
public override void ProcessNotMatchedEndpointAddress(Uri uri, string endpointName)
{
if (!object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttp) &&
!object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttps))
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_NonHTTPInCompatibilityMode(endpointName)));
}
}
public override void ValidateCompatibilityRequirements(AspNetCompatibilityRequirementsMode compatibilityMode)
{
if (compatibilityMode == AspNetCompatibilityRequirementsMode.Allowed)
{
return;
}
else if (ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
compatibilityMode == AspNetCompatibilityRequirementsMode.NotAllowed)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityNotAllowed));
}
else if (!ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
compatibilityMode == AspNetCompatibilityRequirementsMode.Required)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityRequire));
}
}
public override IAspNetMessageProperty GetHostingProperty(Message message)
{
return GetHostingProperty(message, false);
}
IAspNetMessageProperty GetHostingProperty(Message message, bool removeFromMessage)
{
IAspNetMessageProperty result = null;
object property;
if (message.Properties.TryGetValue(HostingMessageProperty.Name, out property))
{
result = (HostingMessageProperty)property;
if (removeFromMessage)
{
message.Properties.Remove(HostingMessageProperty.Name);
}
}
return result;
}
public override IAspNetMessageProperty PrepareMessageForDispatch(Message message)
{
ReceiveContext context = null;
if (ReceiveContext.TryGet(message, out context) && !(context is ReceiveContextBusyCountWrapper))
{
ReceiveContextBusyCountWrapper wrapper = new ReceiveContextBusyCountWrapper(context);
message.Properties.Remove(ReceiveContext.Name);
message.Properties.Add(ReceiveContext.Name, wrapper);
}
return GetHostingProperty(message, true);
}
public override void ApplyHostedContext(TransportChannelListener listener, BindingContext context)
{
VirtualPathExtension virtualPathExtension = context.BindingParameters.Find();
if (virtualPathExtension != null)
{
HostedMetadataBindingParameter metadataBindingParameter = context.BindingParameters.Find();
listener.ApplyHostedContext(virtualPathExtension.VirtualPath, metadataBindingParameter != null);
}
}
public override void ProcessBehaviorForMetadataExtension(IServiceBehavior serviceBehavior, BindingParameterCollection bindingParameters)
{
if (serviceBehavior is HostedBindingBehavior)
{
bindingParameters.Add(((HostedBindingBehavior)serviceBehavior).VirtualPathExtension);
bindingParameters.Add(new HostedMetadataBindingParameter());
}
}
public override void IncrementBusyCount()
{
HostingEnvironmentWrapper.IncrementBusyCount();
}
public override void DecrementBusyCount()
{
HostingEnvironmentWrapper.DecrementBusyCount();
}
public override bool TraceIncrementBusyCountIsEnabled()
{
return TD.IncrementBusyCountIsEnabled();
}
public override bool TraceDecrementBusyCountIsEnabled()
{
return TD.DecrementBusyCountIsEnabled();
}
public override void TraceIncrementBusyCount(string data)
{
if (data == null)
{
data = SR.DefaultBusyCountSource;
}
TD.IncrementBusyCount(data);
}
public override void TraceDecrementBusyCount(string data)
{
if (data == null)
{
data = SR.DefaultBusyCountSource;
}
TD.DecrementBusyCount(data);
}
public override object GetConfigurationSection(string sectionPath)
{
return GetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath);
}
[Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetSectionFromWebConfigurationManager which elevates.")]
[SecurityCritical]
public override object UnsafeGetConfigurationSection(string sectionPath)
{
return UnsafeGetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath);
}
public override AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress)
{
string fileName = VirtualPathUtility.GetFileName(baseAddress.AbsolutePath);
string virtualPath = ServiceHostingEnvironment.CurrentVirtualPath;
string completePath;
if (virtualPath != null && virtualPath.EndsWith("/", StringComparison.Ordinal))
{
completePath = virtualPath + fileName;
}
else
{
completePath = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", virtualPath, fileName);
}
AuthenticationSchemes supportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(completePath);
if (ServiceHostingEnvironment.IsSimpleApplicationHost)
{
// Cassini always reports the auth scheme as anonymous or Ntlm. Map this to Ntlm, except when forms auth
// is requested
if (supportedSchemes == (AuthenticationSchemes.Anonymous | AuthenticationSchemes.Ntlm))
{
if (IsWindowsAuthenticationConfigured())
{
supportedSchemes = AuthenticationSchemes.Ntlm;
}
else
{
supportedSchemes = AuthenticationSchemes.Anonymous;
}
}
}
return supportedSchemes;
}
[Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.",
Safe = "Doesn't leak config objects out of SecurityCritical code.")]
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.NoInlining)]
bool IsWindowsAuthenticationConfigured()
{
if (!this.isWindowsAuthentication.HasValue)
{
AuthenticationSection authSection = (AuthenticationSection)UnsafeGetConfigurationSection("system.web/authentication");
if (authSection != null)
{
this.isWindowsAuthentication = (authSection.Mode == AuthenticationMode.Windows);
}
else
{
this.isWindowsAuthentication = false;
}
}
return this.isWindowsAuthentication.Value;
}
/// Be sure to update UnsafeGetSectionFromWebConfigurationManager if you modify this method
[MethodImpl(MethodImplOptions.NoInlining)]
static object GetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
{
if (virtualPath != null)
{
return WebConfigurationManager.GetSection(sectionPath, virtualPath);
}
else
{
return WebConfigurationManager.GetSection(sectionPath);
}
}
// Be sure to update GetSectionFromWebConfigurationManager if you modify this method
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is from an internal helper class and users have no way to pass arbitrary information to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts ConfigurationPermission in order to fetch config from WebConfigurationManager,"
+ "caller must guard return value.")]
[SecurityCritical]
[ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
[MethodImpl(MethodImplOptions.NoInlining)]
internal static object UnsafeGetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
{
if (virtualPath != null)
{
return WebConfigurationManager.GetSection(sectionPath, virtualPath);
}
else
{
return WebConfigurationManager.GetSection(sectionPath);
}
}
// This class is intended to be empty.
class HostedMetadataBindingParameter
{
}
class ReceiveContextBusyCountWrapper : ReceiveContext
{
ReceiveContext wrappedContext;
//possible values are 0 and 1.
//using an integer to allow usage with Interlocked methods
//synchronized access needed as there could be ---- between calls
//to EndComplete and Tx notification.
int busyCount;
//possible values are 0 and 1
//using an integer to allow usage with Interlocked methods
//synchronized access needed as there could be ---- between calls
//to EndComplete and Tx Status notification.
int ambientTransactionCount;
internal ReceiveContextBusyCountWrapper(ReceiveContext context)
{
this.wrappedContext = context;
this.wrappedContext.Faulted += new EventHandler(OnWrappedContextFaulted);
AspNetEnvironment.Current.IncrementBusyCount();
if (AspNetEnvironment.Current.TraceIncrementBusyCountIsEnabled())
{
AspNetEnvironment.Current.TraceIncrementBusyCount(this.GetType().FullName);
}
Interlocked.Increment(ref busyCount);
}
protected override void OnAbandon(TimeSpan timeout)
{
this.wrappedContext.Abandon(timeout);
DecrementBusyCount();
}
protected override IAsyncResult OnBeginAbandon(TimeSpan timeout, AsyncCallback callback, object state)
{
return this.wrappedContext.BeginAbandon(timeout, callback, state);
}
protected override IAsyncResult OnBeginComplete(TimeSpan timeout, AsyncCallback callback, object state)
{
RegisterForTransactionNotification(Transaction.Current);
return this.wrappedContext.BeginComplete(timeout, callback, state);
}
protected override void OnComplete(TimeSpan timeout)
{
RegisterForTransactionNotification(Transaction.Current);
this.wrappedContext.Complete(timeout);
DecrementOnNoAmbientTransaction();
}
protected override void OnEndAbandon(IAsyncResult result)
{
this.wrappedContext.EndAbandon(result);
DecrementBusyCount();
}
protected override void OnEndComplete(IAsyncResult result)
{
this.wrappedContext.EndComplete(result);
DecrementOnNoAmbientTransaction();
}
protected override void OnFaulted()
{
try
{
this.wrappedContext.Fault();
}
finally
{
base.OnFaulted();
}
}
void OnWrappedContextFaulted(object sender, EventArgs e)
{
try
{
Fault();
}
finally
{
DecrementBusyCount();
}
}
void RegisterForTransactionNotification(Transaction transaction)
{
if (Transaction.Current != null)
{
ReceiveContextEnlistmentNotification notification = new ReceiveContextEnlistmentNotification(this);
transaction.EnlistVolatile(notification, EnlistmentOptions.None);
Interlocked.Increment(ref this.ambientTransactionCount);
}
}
void DecrementOnNoAmbientTransaction()
{
if (Interlocked.Exchange(ref this.ambientTransactionCount, 0) != 1)
{
DecrementBusyCount();
}
}
void DecrementBusyCount()
{
if (Interlocked.Exchange(ref this.busyCount, 0) == 1)
{
AspNetEnvironment.Current.DecrementBusyCount();
if (AspNetEnvironment.Current.TraceDecrementBusyCountIsEnabled())
{
AspNetEnvironment.Current.TraceDecrementBusyCount(this.GetType().FullName);
}
}
}
class ReceiveContextEnlistmentNotification : IEnlistmentNotification
{
ReceiveContextBusyCountWrapper context;
internal ReceiveContextEnlistmentNotification(ReceiveContextBusyCountWrapper context)
{
this.context = context;
}
public void Commit(Enlistment enlistment)
{
this.context.DecrementBusyCount();
enlistment.Done();
}
public void InDoubt(Enlistment enlistment)
{
this.context.DecrementBusyCount();
enlistment.Done();
}
public void Prepare(PreparingEnlistment preparingEnlistment)
{
preparingEnlistment.Prepared();
}
public void Rollback(Enlistment enlistment)
{
enlistment.Done();
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Permissions;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Threading;
using System.Transactions;
using System.Web;
using System.Web.Compilation;
using System.Web.Configuration;
class HostedAspNetEnvironment : AspNetEnvironment
{
// used to cache SiteName|ApplicationVirtualPath
static string cachedServiceReference;
// used to cache if windows auth is being used
Nullable isWindowsAuthentication;
HostedAspNetEnvironment()
: base()
{
}
public override bool AspNetCompatibilityEnabled
{
get
{
return ServiceHostingEnvironment.AspNetCompatibilityEnabled;
}
}
public override string ConfigurationPath
{
get
{
if (ServiceHostingEnvironment.CurrentVirtualPath != null)
{
return ServiceHostingEnvironment.CurrentVirtualPath + "web.config";
}
else
{
return base.ConfigurationPath;
}
}
}
public override bool IsConfigurationBased
{
get
{
return ServiceHostingEnvironment.IsConfigurationBased;
}
}
public override string CurrentVirtualPath
{
get
{
return ServiceHostingEnvironment.CurrentVirtualPath;
}
}
public override string XamlFileBaseLocation
{
get
{
return ServiceHostingEnvironment.XamlFileBaseLocation;
}
}
public static void Enable()
{
AspNetEnvironment hostedEnvironment = new HostedAspNetEnvironment();
AspNetEnvironment.Current = hostedEnvironment;
}
public override void AddHostingBehavior(ServiceHostBase serviceHost, ServiceDescription description)
{
VirtualPathExtension virtualPathExtension = serviceHost.Extensions.Find();
if (virtualPathExtension != null)
{
description.Behaviors.Add(new HostedBindingBehavior(virtualPathExtension));
}
}
public override bool IsWebConfigAboveApplication(object configHostingContext)
{
WebContext context = configHostingContext as WebContext;
if (context != null)
{
return context.ApplicationLevel == WebApplicationLevel.AboveApplication;
}
return false; // if we don't recognize the context we can't enforce the special web.config logic
}
public override void EnsureCompatibilityRequirements(ServiceDescription description)
{
AspNetCompatibilityRequirementsAttribute aspNetCompatibilityRequirements = description.Behaviors.Find();
if (aspNetCompatibilityRequirements == null)
{
aspNetCompatibilityRequirements = new AspNetCompatibilityRequirementsAttribute();
description.Behaviors.Add(aspNetCompatibilityRequirements);
}
}
public override bool TryGetFullVirtualPath(out string virtualPath)
{
// subclass will use the virtual path from the compiled string
virtualPath = ServiceHostingEnvironment.FullVirtualPath;
return true;
}
public override string GetAnnotationFromHost(ServiceHostBase host)
{
//Format Website name\Application Virtual Path|\relative service virtual path|serviceName
if (host != null && host.Extensions != null)
{
string serviceName = (host.Description != null) ? host.Description.Name : string.Empty;
string application = ServiceHostingEnvironment.ApplicationVirtualPath;
string servicePath = string.Empty;
VirtualPathExtension extension = host.Extensions.Find();
if (extension != null && extension.VirtualPath != null)
{
servicePath = extension.VirtualPath.Replace("~", application + "|");
return string.Format(CultureInfo.InvariantCulture, "{0}{1}|{2}", ServiceHostingEnvironment.SiteName, servicePath, serviceName);
}
}
if (string.IsNullOrEmpty(HostedAspNetEnvironment.cachedServiceReference))
{
HostedAspNetEnvironment.cachedServiceReference = string.Format(CultureInfo.InvariantCulture, "{0}{1}", ServiceHostingEnvironment.SiteName, ServiceHostingEnvironment.ApplicationVirtualPath);
}
return HostedAspNetEnvironment.cachedServiceReference;
}
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
public override void EnsureAllReferencedAssemblyLoaded()
{
BuildManager.GetReferencedAssemblies();
}
public override BaseUriWithWildcard GetBaseUri(string transportScheme, Uri listenUri)
{
BaseUriWithWildcard baseAddress = null;
HostedTransportConfigurationBase hostedConfiguration =
HostedTransportConfigurationManager.GetConfiguration(transportScheme) as HostedTransportConfigurationBase;
if (hostedConfiguration != null)
{
baseAddress = hostedConfiguration.FindBaseAddress(listenUri);
if (baseAddress == null)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_TransportBindingNotFound(listenUri.ToString())));
}
}
return baseAddress;
}
public override void ValidateHttpSettings(string virtualPath, bool isMetadataListener, bool usingDefaultSpnList, ref AuthenticationSchemes supportedSchemes, ref ExtendedProtectionPolicy extendedProtectionPolicy, ref string realm)
{
// Verify the authentication settings
AuthenticationSchemes hostedSupportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(virtualPath);
if (supportedSchemes == AuthenticationSchemes.Anonymous)
{
if ((hostedSupportedSchemes & AuthenticationSchemes.Anonymous) == 0)
{
if (isMetadataListener)
{
// We apply IIS settings to the ChannelListener to fix mex endpoints.
if ((hostedSupportedSchemes & AuthenticationSchemes.Negotiate) != AuthenticationSchemes.None)
{
supportedSchemes = AuthenticationSchemes.Negotiate;
}
else
{
supportedSchemes = hostedSupportedSchemes;
}
}
}
}
if ((supportedSchemes & hostedSupportedSchemes) == 0)
{
if (AuthenticationSchemesHelper.IsWindowsAuth(supportedSchemes))
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireWindowsAuth));
}
else
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireOtherAuth(supportedSchemes.ToString())));
}
}
if (supportedSchemes != AuthenticationSchemes.Anonymous)
{
//Compare the ExtendedProtectionPolicy setttings to IIS
ExtendedProtectionPolicy iisPolicy = HostedTransportConfigurationManager.MetabaseSettings.GetExtendedProtectionPolicy(virtualPath);
if (iisPolicy == null) //OS doesn't support CBT
{
if (extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.Always)
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.ExtendedProtectionNotSupported));
}
}
else
{
if (isMetadataListener && ChannelBindingUtility.IsDefaultPolicy(extendedProtectionPolicy))
{
//push the IIS policy onto the metadataListener if and only if the default policy is
//in force. policy for non metadata listeners will still have to match IIS policy.
extendedProtectionPolicy = iisPolicy;
}
else
{
if (!ChannelBindingUtility.AreEqual(iisPolicy, extendedProtectionPolicy))
{
string mismatchErrorMessage;
if (iisPolicy.PolicyEnforcement != extendedProtectionPolicy.PolicyEnforcement)
{
mismatchErrorMessage = SR.ExtendedProtectionPolicyEnforcementMismatch(iisPolicy.PolicyEnforcement, extendedProtectionPolicy.PolicyEnforcement);
}
else if (iisPolicy.ProtectionScenario != extendedProtectionPolicy.ProtectionScenario)
{
mismatchErrorMessage = SR.ExtendedProtectionPolicyScenarioMismatch(iisPolicy.ProtectionScenario, extendedProtectionPolicy.ProtectionScenario);
}
else
{
Fx.Assert(iisPolicy.CustomChannelBinding != extendedProtectionPolicy.CustomChannelBinding, "new case in ChannelBindingUtility.AreEqual to account for");
mismatchErrorMessage = SR.ExtendedProtectionPolicyCustomChannelBindingMismatch;
}
if (mismatchErrorMessage != null)
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(mismatchErrorMessage)));
}
}
//when using the default SPN list we auto generate, we should make sure that the IIS policy is also the default...
ServiceNameCollection listenerSpnList = usingDefaultSpnList ? null : extendedProtectionPolicy.CustomServiceNames;
if (!ChannelBindingUtility.IsSubset(iisPolicy.CustomServiceNames, listenerSpnList))
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(SR.Hosting_ExtendedProtectionSPNListNotSubset)));
}
}
}
}
// Do not set realm for Cassini.
if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
{
// Set the realm
realm = HostedTransportConfigurationManager.MetabaseSettings.GetRealm(virtualPath);
}
}
public override bool ValidateHttpsSettings(string virtualPath, ref Nullable requireClientCertificate)
{
bool useHostedClientCertificateMapping = false;
// Do not validate settings for Cassini. Actually current implementation of Cassini does not support HTTPS.
if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
{
// Validate Ssl Settings
HttpAccessSslFlags sslFlags = HostedTransportConfigurationManager.MetabaseSettings.GetAccessSslFlags(virtualPath);
HttpAccessSslFlags channelListenerSslFlags = HttpAccessSslFlags.None;
// Validating SSL flags. SslRequireCert means "require client certificate" in IIS terminology.
bool mismatched = false;
if ((sslFlags & HttpAccessSslFlags.SslRequireCert) != 0)
{
// Require SSL.
if (requireClientCertificate.HasValue)
{
if (!requireClientCertificate.Value)
{
// IIS requires client cert but the binding does not.
mismatched = true;
}
}
else
{
// We apply IIS settings to the ChannelListener to fix mex endpoints.
requireClientCertificate = true;
}
}
else if (requireClientCertificate.GetValueOrDefault())
{
// IIS does not require client cert but the binding does.
channelListenerSslFlags |= HttpAccessSslFlags.SslRequireCert;
mismatched = true;
}
if (!mismatched)
{
if ((sslFlags & HttpAccessSslFlags.SslMapCert) != 0)
{
useHostedClientCertificateMapping = true;
}
}
if (mismatched)
{
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_SslSettingsMisconfigured(
channelListenerSslFlags.ToString(), sslFlags.ToString())));
}
}
return useHostedClientCertificateMapping;
}
public override void ProcessNotMatchedEndpointAddress(Uri uri, string endpointName)
{
if (!object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttp) &&
!object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttps))
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_NonHTTPInCompatibilityMode(endpointName)));
}
}
public override void ValidateCompatibilityRequirements(AspNetCompatibilityRequirementsMode compatibilityMode)
{
if (compatibilityMode == AspNetCompatibilityRequirementsMode.Allowed)
{
return;
}
else if (ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
compatibilityMode == AspNetCompatibilityRequirementsMode.NotAllowed)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityNotAllowed));
}
else if (!ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
compatibilityMode == AspNetCompatibilityRequirementsMode.Required)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityRequire));
}
}
public override IAspNetMessageProperty GetHostingProperty(Message message)
{
return GetHostingProperty(message, false);
}
IAspNetMessageProperty GetHostingProperty(Message message, bool removeFromMessage)
{
IAspNetMessageProperty result = null;
object property;
if (message.Properties.TryGetValue(HostingMessageProperty.Name, out property))
{
result = (HostingMessageProperty)property;
if (removeFromMessage)
{
message.Properties.Remove(HostingMessageProperty.Name);
}
}
return result;
}
public override IAspNetMessageProperty PrepareMessageForDispatch(Message message)
{
ReceiveContext context = null;
if (ReceiveContext.TryGet(message, out context) && !(context is ReceiveContextBusyCountWrapper))
{
ReceiveContextBusyCountWrapper wrapper = new ReceiveContextBusyCountWrapper(context);
message.Properties.Remove(ReceiveContext.Name);
message.Properties.Add(ReceiveContext.Name, wrapper);
}
return GetHostingProperty(message, true);
}
public override void ApplyHostedContext(TransportChannelListener listener, BindingContext context)
{
VirtualPathExtension virtualPathExtension = context.BindingParameters.Find();
if (virtualPathExtension != null)
{
HostedMetadataBindingParameter metadataBindingParameter = context.BindingParameters.Find();
listener.ApplyHostedContext(virtualPathExtension.VirtualPath, metadataBindingParameter != null);
}
}
public override void ProcessBehaviorForMetadataExtension(IServiceBehavior serviceBehavior, BindingParameterCollection bindingParameters)
{
if (serviceBehavior is HostedBindingBehavior)
{
bindingParameters.Add(((HostedBindingBehavior)serviceBehavior).VirtualPathExtension);
bindingParameters.Add(new HostedMetadataBindingParameter());
}
}
public override void IncrementBusyCount()
{
HostingEnvironmentWrapper.IncrementBusyCount();
}
public override void DecrementBusyCount()
{
HostingEnvironmentWrapper.DecrementBusyCount();
}
public override bool TraceIncrementBusyCountIsEnabled()
{
return TD.IncrementBusyCountIsEnabled();
}
public override bool TraceDecrementBusyCountIsEnabled()
{
return TD.DecrementBusyCountIsEnabled();
}
public override void TraceIncrementBusyCount(string data)
{
if (data == null)
{
data = SR.DefaultBusyCountSource;
}
TD.IncrementBusyCount(data);
}
public override void TraceDecrementBusyCount(string data)
{
if (data == null)
{
data = SR.DefaultBusyCountSource;
}
TD.DecrementBusyCount(data);
}
public override object GetConfigurationSection(string sectionPath)
{
return GetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath);
}
[Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetSectionFromWebConfigurationManager which elevates.")]
[SecurityCritical]
public override object UnsafeGetConfigurationSection(string sectionPath)
{
return UnsafeGetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath);
}
public override AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress)
{
string fileName = VirtualPathUtility.GetFileName(baseAddress.AbsolutePath);
string virtualPath = ServiceHostingEnvironment.CurrentVirtualPath;
string completePath;
if (virtualPath != null && virtualPath.EndsWith("/", StringComparison.Ordinal))
{
completePath = virtualPath + fileName;
}
else
{
completePath = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", virtualPath, fileName);
}
AuthenticationSchemes supportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(completePath);
if (ServiceHostingEnvironment.IsSimpleApplicationHost)
{
// Cassini always reports the auth scheme as anonymous or Ntlm. Map this to Ntlm, except when forms auth
// is requested
if (supportedSchemes == (AuthenticationSchemes.Anonymous | AuthenticationSchemes.Ntlm))
{
if (IsWindowsAuthenticationConfigured())
{
supportedSchemes = AuthenticationSchemes.Ntlm;
}
else
{
supportedSchemes = AuthenticationSchemes.Anonymous;
}
}
}
return supportedSchemes;
}
[Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.",
Safe = "Doesn't leak config objects out of SecurityCritical code.")]
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.NoInlining)]
bool IsWindowsAuthenticationConfigured()
{
if (!this.isWindowsAuthentication.HasValue)
{
AuthenticationSection authSection = (AuthenticationSection)UnsafeGetConfigurationSection("system.web/authentication");
if (authSection != null)
{
this.isWindowsAuthentication = (authSection.Mode == AuthenticationMode.Windows);
}
else
{
this.isWindowsAuthentication = false;
}
}
return this.isWindowsAuthentication.Value;
}
/// Be sure to update UnsafeGetSectionFromWebConfigurationManager if you modify this method
[MethodImpl(MethodImplOptions.NoInlining)]
static object GetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
{
if (virtualPath != null)
{
return WebConfigurationManager.GetSection(sectionPath, virtualPath);
}
else
{
return WebConfigurationManager.GetSection(sectionPath);
}
}
// Be sure to update GetSectionFromWebConfigurationManager if you modify this method
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is from an internal helper class and users have no way to pass arbitrary information to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts ConfigurationPermission in order to fetch config from WebConfigurationManager,"
+ "caller must guard return value.")]
[SecurityCritical]
[ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
[MethodImpl(MethodImplOptions.NoInlining)]
internal static object UnsafeGetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
{
if (virtualPath != null)
{
return WebConfigurationManager.GetSection(sectionPath, virtualPath);
}
else
{
return WebConfigurationManager.GetSection(sectionPath);
}
}
// This class is intended to be empty.
class HostedMetadataBindingParameter
{
}
class ReceiveContextBusyCountWrapper : ReceiveContext
{
ReceiveContext wrappedContext;
//possible values are 0 and 1.
//using an integer to allow usage with Interlocked methods
//synchronized access needed as there could be ---- between calls
//to EndComplete and Tx notification.
int busyCount;
//possible values are 0 and 1
//using an integer to allow usage with Interlocked methods
//synchronized access needed as there could be ---- between calls
//to EndComplete and Tx Status notification.
int ambientTransactionCount;
internal ReceiveContextBusyCountWrapper(ReceiveContext context)
{
this.wrappedContext = context;
this.wrappedContext.Faulted += new EventHandler(OnWrappedContextFaulted);
AspNetEnvironment.Current.IncrementBusyCount();
if (AspNetEnvironment.Current.TraceIncrementBusyCountIsEnabled())
{
AspNetEnvironment.Current.TraceIncrementBusyCount(this.GetType().FullName);
}
Interlocked.Increment(ref busyCount);
}
protected override void OnAbandon(TimeSpan timeout)
{
this.wrappedContext.Abandon(timeout);
DecrementBusyCount();
}
protected override IAsyncResult OnBeginAbandon(TimeSpan timeout, AsyncCallback callback, object state)
{
return this.wrappedContext.BeginAbandon(timeout, callback, state);
}
protected override IAsyncResult OnBeginComplete(TimeSpan timeout, AsyncCallback callback, object state)
{
RegisterForTransactionNotification(Transaction.Current);
return this.wrappedContext.BeginComplete(timeout, callback, state);
}
protected override void OnComplete(TimeSpan timeout)
{
RegisterForTransactionNotification(Transaction.Current);
this.wrappedContext.Complete(timeout);
DecrementOnNoAmbientTransaction();
}
protected override void OnEndAbandon(IAsyncResult result)
{
this.wrappedContext.EndAbandon(result);
DecrementBusyCount();
}
protected override void OnEndComplete(IAsyncResult result)
{
this.wrappedContext.EndComplete(result);
DecrementOnNoAmbientTransaction();
}
protected override void OnFaulted()
{
try
{
this.wrappedContext.Fault();
}
finally
{
base.OnFaulted();
}
}
void OnWrappedContextFaulted(object sender, EventArgs e)
{
try
{
Fault();
}
finally
{
DecrementBusyCount();
}
}
void RegisterForTransactionNotification(Transaction transaction)
{
if (Transaction.Current != null)
{
ReceiveContextEnlistmentNotification notification = new ReceiveContextEnlistmentNotification(this);
transaction.EnlistVolatile(notification, EnlistmentOptions.None);
Interlocked.Increment(ref this.ambientTransactionCount);
}
}
void DecrementOnNoAmbientTransaction()
{
if (Interlocked.Exchange(ref this.ambientTransactionCount, 0) != 1)
{
DecrementBusyCount();
}
}
void DecrementBusyCount()
{
if (Interlocked.Exchange(ref this.busyCount, 0) == 1)
{
AspNetEnvironment.Current.DecrementBusyCount();
if (AspNetEnvironment.Current.TraceDecrementBusyCountIsEnabled())
{
AspNetEnvironment.Current.TraceDecrementBusyCount(this.GetType().FullName);
}
}
}
class ReceiveContextEnlistmentNotification : IEnlistmentNotification
{
ReceiveContextBusyCountWrapper context;
internal ReceiveContextEnlistmentNotification(ReceiveContextBusyCountWrapper context)
{
this.context = context;
}
public void Commit(Enlistment enlistment)
{
this.context.DecrementBusyCount();
enlistment.Done();
}
public void InDoubt(Enlistment enlistment)
{
this.context.DecrementBusyCount();
enlistment.Done();
}
public void Prepare(PreparingEnlistment preparingEnlistment)
{
preparingEnlistment.Prepared();
}
public void Rollback(Enlistment enlistment)
{
enlistment.Done();
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CodeGenerator.cs
- VirtualDirectoryMappingCollection.cs
- GACIdentityPermission.cs
- IPAddressCollection.cs
- QuerySafeNavigator.cs
- DynamicMethod.cs
- DataTableMapping.cs
- MailDefinitionBodyFileNameEditor.cs
- Rfc4050KeyFormatter.cs
- Timeline.cs
- FastPropertyAccessor.cs
- ClientConvert.cs
- DynamicMethod.cs
- ScriptResourceHandler.cs
- HostingEnvironmentSection.cs
- TextDocumentView.cs
- EndpointIdentityConverter.cs
- FormsAuthenticationCredentials.cs
- XmlNodeReader.cs
- IpcChannel.cs
- RSAOAEPKeyExchangeFormatter.cs
- NumberAction.cs
- ResourceProviderFactory.cs
- LinqDataSourceDisposeEventArgs.cs
- PixelFormat.cs
- TextEditorTyping.cs
- TextInfo.cs
- VariableBinder.cs
- Subtree.cs
- QueryProcessor.cs
- ItemList.cs
- CustomValidator.cs
- BasicKeyConstraint.cs
- Mappings.cs
- FlowDocumentPageViewerAutomationPeer.cs
- SqlResolver.cs
- XmlAttributeCollection.cs
- XmlSchemaValidator.cs
- UriTemplateTable.cs
- X509Certificate2Collection.cs
- DefaultValueAttribute.cs
- ObjectDataSourceView.cs
- RuntimeHandles.cs
- GridSplitterAutomationPeer.cs
- XmlSchemaSimpleTypeList.cs
- InteropAutomationProvider.cs
- DataControlCommands.cs
- XamlTreeBuilderBamlRecordWriter.cs
- QueueTransferProtocol.cs
- InfoCardRSAOAEPKeyExchangeDeformatter.cs
- FunctionOverloadResolver.cs
- AmbientLight.cs
- WizardPanel.cs
- SafeMemoryMappedViewHandle.cs
- MediaContext.cs
- _ProxyRegBlob.cs
- DLinqDataModelProvider.cs
- ProfessionalColors.cs
- ComboBoxAutomationPeer.cs
- ApplicationInfo.cs
- TickBar.cs
- compensatingcollection.cs
- CodeTypeMember.cs
- ReferenceAssemblyAttribute.cs
- NavigationHelper.cs
- infer.cs
- SQLConvert.cs
- D3DImage.cs
- WindowsRegion.cs
- WpfPayload.cs
- PolyQuadraticBezierSegment.cs
- XmlILModule.cs
- HeaderElement.cs
- CompositeDataBoundControl.cs
- AmbientLight.cs
- ZipFileInfoCollection.cs
- FixedLineResult.cs
- WindowClosedEventArgs.cs
- CodeGenerator.cs
- XmlUtilWriter.cs
- ColorConvertedBitmap.cs
- PackagePartCollection.cs
- WorkflowDefinitionDispenser.cs
- LinkTarget.cs
- OneOfElement.cs
- Util.cs
- ServiceContractListItem.cs
- TaskResultSetter.cs
- TreeChangeInfo.cs
- ProviderBase.cs
- RNGCryptoServiceProvider.cs
- ValidatedControlConverter.cs
- ClientSettingsStore.cs
- ObjectAnimationUsingKeyFrames.cs
- SiteMapPath.cs
- WpfWebRequestHelper.cs
- TemplateBindingExpressionConverter.cs
- UriTemplateTrieNode.cs
- SyndicationDeserializer.cs
- DemultiplexingDispatchMessageFormatter.cs