94b2861243
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
776 lines
32 KiB
C#
776 lines
32 KiB
C#
//----------------------------------------------------------------------------
|
|
// 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
|
|
{
|
|
// On IIS 8.0 (or later) the "WEBSOCKET_VERSION" server property indicates the WebSocket protocol version supported by the server.
|
|
// The IIS WebSocket module sets this property when initialized.
|
|
private const string WebSocketVersionServerProperty = "WEBSOCKET_VERSION";
|
|
|
|
// Indicates if we determined the WebSocket version. If false, we'll need to check the "WEBSOCKET_VERSION" server property.
|
|
private static bool isWebSocketVersionSet = false;
|
|
|
|
// Provides the version of the WebSocket protocol supported by IIS.
|
|
private static string webSocketVersion;
|
|
|
|
// used to cache SiteName|ApplicationVirtualPath
|
|
static string cachedServiceReference;
|
|
|
|
// used to cache if windows auth is being used
|
|
Nullable<bool> 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 override bool UsingIntegratedPipeline
|
|
{
|
|
get
|
|
{
|
|
return HttpRuntime.UsingIntegratedPipeline;
|
|
}
|
|
}
|
|
|
|
// Provides the version of the WebSocket protocol supported by IIS.
|
|
// Returns null if WebSockets are not supported (because the IIS WebSocketModule is not installed or enabled).
|
|
public override string WebSocketVersion
|
|
{
|
|
get
|
|
{
|
|
return isWebSocketVersionSet ? webSocketVersion : null;
|
|
}
|
|
}
|
|
|
|
public static void Enable()
|
|
{
|
|
AspNetEnvironment hostedEnvironment = new HostedAspNetEnvironment();
|
|
AspNetEnvironment.Current = hostedEnvironment;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to set the 'WebSocketVersion' property. The first call of this method sets the property (based on the "WEBSOCKET_VERSION" server property).
|
|
/// Subsequent calls do nothing.
|
|
/// </summary>
|
|
/// <param name="application">The HttpApplication used to determine the WebSocket version.</param>
|
|
/// <remarks>
|
|
/// Take caution when calling this method. The method initializes the 'WebSocketVersion' property based on the "WEBSOCKET_VERSION" server variable.
|
|
/// This variable gets set by the WebSocketModule when it's loaded by IIS. If you call this method too early (before IIS got a chance to load the module list),
|
|
/// this method might incorrectly set 'WebSocketVersion' to 'null'.
|
|
/// </remarks>
|
|
public static void TrySetWebSocketVersion(HttpApplication application)
|
|
{
|
|
if (!isWebSocketVersionSet)
|
|
{
|
|
webSocketVersion = application.Request.ServerVariables[WebSocketVersionServerProperty];
|
|
isWebSocketVersionSet = true;
|
|
}
|
|
}
|
|
|
|
public override void AddHostingBehavior(ServiceHostBase serviceHost, ServiceDescription description)
|
|
{
|
|
VirtualPathExtension virtualPathExtension = serviceHost.Extensions.Find<VirtualPathExtension>();
|
|
if (virtualPathExtension != null)
|
|
{
|
|
description.Behaviors.Add(new HostedBindingBehavior(virtualPathExtension));
|
|
}
|
|
|
|
foreach (ServiceEndpoint endpoint in description.Endpoints)
|
|
{
|
|
if (ServiceMetadataBehavior.IsMetadataEndpoint(description, endpoint))
|
|
{
|
|
endpoint.Behaviors.Add(new HostedMetadataExchangeEndpointBehavior());
|
|
}
|
|
}
|
|
}
|
|
|
|
public override bool IsWebConfigAboveApplication(object configHostingContext)
|
|
{
|
|
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
|
|
|
|
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<AspNetCompatibilityRequirementsAttribute>();
|
|
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<VirtualPathExtension>();
|
|
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()
|
|
{
|
|
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
|
|
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 bindingElementAuthenticationSchemes, ref ExtendedProtectionPolicy extendedProtectionPolicy, ref string realm)
|
|
{
|
|
// Verify the authentication settings
|
|
AuthenticationSchemes hostSupportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(virtualPath);
|
|
|
|
if ((bindingElementAuthenticationSchemes & hostSupportedSchemes) == 0)
|
|
{
|
|
if (bindingElementAuthenticationSchemes == AuthenticationSchemes.Negotiate ||
|
|
bindingElementAuthenticationSchemes == AuthenticationSchemes.Ntlm ||
|
|
bindingElementAuthenticationSchemes == AuthenticationSchemes.IntegratedWindowsAuthentication)
|
|
{
|
|
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireWindowsAuth));
|
|
}
|
|
else
|
|
{
|
|
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireOtherAuth(bindingElementAuthenticationSchemes.ToString())));
|
|
}
|
|
}
|
|
|
|
//only use AuthenticationSchemes, which are supported both in IIS and the WCF binding
|
|
bindingElementAuthenticationSchemes &= hostSupportedSchemes;
|
|
|
|
if (bindingElementAuthenticationSchemes != 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 bool requireClientCertificate)
|
|
{
|
|
// Do not validate settings for Cassini. Actually current implementation of Cassini does not support HTTPS.
|
|
if (ServiceHostingEnvironment.IsSimpleApplicationHost)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Validate Ssl Settings
|
|
HttpAccessSslFlags sslFlags = HostedTransportConfigurationManager.MetabaseSettings.GetAccessSslFlags(virtualPath);
|
|
HttpAccessSslFlags channelListenerSslFlags = HttpAccessSslFlags.None;
|
|
|
|
// Validating SSL flags. SslRequireCert means "require client certificate" in IIS terminology.
|
|
if ((sslFlags & HttpAccessSslFlags.SslRequireCert) != 0)
|
|
{
|
|
// Require SSL.
|
|
// We apply IIS settings to the ChannelListener to fix the endpoint
|
|
requireClientCertificate = true;
|
|
}
|
|
else if (requireClientCertificate &&
|
|
// Validating SSL flags. SslNegotiateCert means "accept client certificate" in IIS terminology.
|
|
// We want to allow SslNegotiateCert in IIS to support hosting one endpoint requiring client
|
|
// certificates and another endpoint not using client certificates in the same VirtualDirectory.
|
|
// HttpsChannelListener.ValidateAuthentication ensures that authentication is denied for services
|
|
// requiring client certificates when the client does not present one.
|
|
(sslFlags & HttpAccessSslFlags.SslNegotiateCert) == 0)
|
|
{
|
|
// IIS ignores client cert but the binding requires it.
|
|
channelListenerSslFlags |= HttpAccessSslFlags.SslRequireCert;
|
|
|
|
throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_SslSettingsMisconfigured(
|
|
channelListenerSslFlags.ToString(), sslFlags.ToString())));
|
|
}
|
|
|
|
return (sslFlags & HttpAccessSslFlags.SslMapCert) != 0;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
public override 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 void 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);
|
|
}
|
|
}
|
|
|
|
public override void ApplyHostedContext(TransportChannelListener listener, BindingContext context)
|
|
{
|
|
VirtualPathExtension virtualPathExtension = context.BindingParameters.Find<VirtualPathExtension>();
|
|
|
|
if (virtualPathExtension != null)
|
|
{
|
|
HostedMetadataBindingParameter metadataBindingParameter = context.BindingParameters.Find<HostedMetadataBindingParameter>();
|
|
listener.ApplyHostedContext(virtualPathExtension.VirtualPath, metadataBindingParameter != null);
|
|
}
|
|
}
|
|
|
|
internal override void AddMetadataBindingParameters(Uri listenUri, KeyedByTypeCollection<IServiceBehavior> serviceBehaviors, BindingParameterCollection bindingParameters)
|
|
{
|
|
if (serviceBehaviors.Find<HostedBindingBehavior>() != null)
|
|
{
|
|
bindingParameters.Add(new HostedMetadataBindingParameter());
|
|
}
|
|
|
|
VirtualPathExtension virtualPathExtension = bindingParameters.Find<VirtualPathExtension>();
|
|
|
|
if (virtualPathExtension != null)
|
|
{
|
|
AuthenticationSchemes hostSupportedAuthenticationSchemes = AspNetEnvironment.Current.GetAuthenticationSchemes(listenUri);
|
|
|
|
if (hostSupportedAuthenticationSchemes != AuthenticationSchemes.None)
|
|
{
|
|
if (bindingParameters.Find<AuthenticationSchemesBindingParameter>() == null)
|
|
{
|
|
bindingParameters.Add(new AuthenticationSchemesBindingParameter(hostSupportedAuthenticationSchemes));
|
|
}
|
|
}
|
|
}
|
|
|
|
base.AddMetadataBindingParameters(listenUri, serviceBehaviors, bindingParameters);
|
|
}
|
|
|
|
internal override bool IsMetadataListener(BindingParameterCollection bindingParameters)
|
|
{
|
|
return base.IsMetadataListener(bindingParameters) || bindingParameters.Find<HostedMetadataBindingParameter>() != null;
|
|
}
|
|
|
|
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 bool IsSimpleApplicationHost
|
|
{
|
|
get
|
|
{
|
|
return ServiceHostingEnvironment.IsSimpleApplicationHost;
|
|
}
|
|
}
|
|
|
|
public override AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress)
|
|
{
|
|
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
|
|
|
|
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);
|
|
|
|
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)]
|
|
public override bool IsWindowsAuthenticationConfigured()
|
|
{
|
|
if (!this.isWindowsAuthentication.HasValue)
|
|
{
|
|
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
|
|
|
|
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)
|
|
{
|
|
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
|
|
|
|
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)
|
|
{
|
|
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
|
|
|
|
if (virtualPath != null)
|
|
{
|
|
return WebConfigurationManager.GetSection(sectionPath, virtualPath);
|
|
}
|
|
else
|
|
{
|
|
return WebConfigurationManager.GetSection(sectionPath);
|
|
}
|
|
}
|
|
|
|
public override bool IsWithinApp(string absoluteVirtualPath)
|
|
{
|
|
return HostedTransportConfigurationManager.MetabaseSettings.IsWithinApp(absoluteVirtualPath);
|
|
}
|
|
|
|
// This class is intended to be empty.
|
|
class HostedMetadataBindingParameter
|
|
{
|
|
}
|
|
|
|
class HostedMetadataExchangeEndpointBehavior : IEndpointBehavior
|
|
{
|
|
void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
|
{
|
|
bindingParameters.Add(new HostedMetadataBindingParameter());
|
|
}
|
|
|
|
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, Dispatcher.ClientRuntime clientRuntime)
|
|
{
|
|
}
|
|
|
|
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, Dispatcher.EndpointDispatcher endpointDispatcher)
|
|
{
|
|
}
|
|
|
|
void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
|
|
{
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|