//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- namespace System.ServiceModel.Activation { using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.Net; using System.Runtime; using System.Runtime.Diagnostics; using System.Security; using System.Security.Authentication.ExtendedProtection; using System.Security.Permissions; using System.ServiceModel; using System.ServiceModel.Activation.Diagnostics; using System.Web; using Microsoft.Win32; abstract class MetabaseSettings { internal const char AboPathDelimiter = '/'; internal const string DotDelimiter = "."; internal const string LocalMachine = "localhost"; List enabledProtocols; IDictionary bindingsTable; protected MetabaseSettings() { enabledProtocols = new List(); bindingsTable = new Dictionary(); } internal abstract string GetRealm(string virtualPath); internal abstract HttpAccessSslFlags GetAccessSslFlags(string virtualPath); internal abstract AuthenticationSchemes GetAuthenticationSchemes(string virtualPath); internal abstract ExtendedProtectionPolicy GetExtendedProtectionPolicy(string virtualPath); internal abstract bool IsWithinApp(string absoluteVirtualPath); protected List Protocols { get { return enabledProtocols; } set { enabledProtocols = value; } } protected IDictionary Bindings { get { return bindingsTable; } set { bindingsTable = value; } } internal bool GetAllowSslOnly(string virtualPath) { HttpAccessSslFlags flags = this.GetAccessSslFlags(virtualPath); if ((flags & HttpAccessSslFlags.Ssl) != 0) { return true; } return false; } internal string[] GetProtocols() { return enabledProtocols.ToArray(); } internal string[] GetBindings(string scheme) { return bindingsTable[scheme]; } // build NCL ExtendedProtectionPolicy object // From NCL comments: // The NoServiceNameCheck flag can always be ignored because it has no meaning in the .NET Framework // where validation against an SPN list is always required when the scenario does not require a CBT. protected static ExtendedProtectionPolicy BuildExtendedProtectionPolicy( ExtendedProtectionTokenChecking tokenChecking, ExtendedProtectionFlags flags, List spnList) { PolicyEnforcement enforce; ProtectionScenario scenario; ServiceNameCollection serviceNames = null; if (tokenChecking == ExtendedProtectionTokenChecking.None) { return new ExtendedProtectionPolicy(PolicyEnforcement.Never); } else if (tokenChecking == ExtendedProtectionTokenChecking.Allow) { enforce = PolicyEnforcement.WhenSupported; } else if (tokenChecking == ExtendedProtectionTokenChecking.Require) { enforce = PolicyEnforcement.Always; } else { throw FxTrace.Exception.Argument("tokenChecking", SR.Hosting_UnrecognizedTokenCheckingValue); } bool transportSelectedCondition1 = (flags == ExtendedProtectionFlags.None); bool transportSelectedCondition2 = (flags == ExtendedProtectionFlags.AllowDotlessSpn); bool transportSelectedCondition3 = ((flags & ExtendedProtectionFlags.Proxy) != 0) && ((flags & ExtendedProtectionFlags.ProxyCohosting) != 0); bool trustedProxyCondition = (flags & ExtendedProtectionFlags.Proxy) != 0; //only none or allowdotlessspn flag has been selected or both proxy and proxycohosting flags have been selected //set scenario to TransportSelected if (transportSelectedCondition1 || transportSelectedCondition2 || transportSelectedCondition3) { scenario = ProtectionScenario.TransportSelected; } // proxy but no procycohosting flag has been selected, set scenario to TrustedProxy else if (trustedProxyCondition) { scenario = ProtectionScenario.TrustedProxy; } // other nonsupported scenarios, throw NotSupportedException else { throw FxTrace.Exception.Argument("flags", SR.Hosting_ExtendedProtectionFlagsNotSupport(flags)); } // dotless spn check if dotlessspn is not allowed // spn format /:/ per http://msdn.microsoft.com/en-us/library/ms677601(VS.85).aspx if (spnList != null) { if ((flags & ExtendedProtectionFlags.AllowDotlessSpn) == 0) { foreach (string spn in spnList) { string[] parts = spn.Split(AboPathDelimiter); if (parts.Length > 1) { int position = parts[1].IndexOf(DotDelimiter, StringComparison.CurrentCultureIgnoreCase); if (position == -1) { throw FxTrace.Exception.Argument("spn", SR.Hosting_ExtendedProtectionDotlessSpnNotEnabled(spn)); } else if (position == 0 || position == parts[1].Length - 1) { throw FxTrace.Exception.Argument("spn", SR.Hosting_ExtendedProtectionSpnFormatError(spn)); } } else { throw FxTrace.Exception.Argument("spn", SR.Hosting_ExtendedProtectionSpnFormatError(spn)); } } } // ExtendedProtectionPolicy constructor rejects empty collection but accept null // in order to avoid any ambiguilty if (spnList.Count != 0) { serviceNames = new ServiceNameCollection(spnList); } } return new ExtendedProtectionPolicy(enforce, scenario, serviceNames); } } class MetabaseSettingsCassini : MetabaseSettings { internal MetabaseSettingsCassini(HostedHttpRequestAsyncResult result) : base() { if (!ServiceHostingEnvironment.IsSimpleApplicationHost) { throw Fx.AssertAndThrowFatal("MetabaseSettingsCassini..ctor() Not a simple application host."); } // The hostName is hard-coded to "localhost" for Cassini. string binding = string.Format(CultureInfo.InvariantCulture, ":{0}:{1}", result.OriginalRequestUri.Port.ToString(NumberFormatInfo.InvariantInfo), MetabaseSettings.LocalMachine); this.Bindings.Add(result.OriginalRequestUri.Scheme, new string[] { binding }); this.Protocols.Add(result.OriginalRequestUri.Scheme); } internal override string GetRealm(string virtualPath) { return string.Empty; } internal override HttpAccessSslFlags GetAccessSslFlags(string virtualPath) { return HttpAccessSslFlags.None; } internal override AuthenticationSchemes GetAuthenticationSchemes(string virtualPath) { // Special casing Cassini so that Ntlm is supported since the request always has the identity of the // logged on user. return AuthenticationSchemes.Anonymous | AuthenticationSchemes.Ntlm; } internal override ExtendedProtectionPolicy GetExtendedProtectionPolicy(string virtualPath) { //Alwasy return null since cassini does not support Https return null; } internal override bool IsWithinApp(string absoluteVirtualPath) { return true; } } abstract class MetabaseSettingsIis : MetabaseSettings { IDictionary transportSettingsTable; internal const string NegotiateAuthProvider = "negotiate"; internal const string NtlmAuthProvider = "ntlm"; internal static string[] DefaultAuthProviders = { NegotiateAuthProvider, NtlmAuthProvider }; protected MetabaseSettingsIis() : base() { if (ServiceHostingEnvironment.IsSimpleApplicationHost) { throw Fx.AssertAndThrowFatal("MetabaseSettingsIis..ctor() Is a simple application host."); } transportSettingsTable = new Dictionary(StringComparer.OrdinalIgnoreCase); } object ThisLock { get { return this; } } protected abstract HostedServiceTransportSettings CreateTransportSettings(string relativeVirtualPath); internal override string GetRealm(string virtualPath) { HostedServiceTransportSettings transportSettings = GetTransportSettings(virtualPath); return transportSettings.Realm; } internal override HttpAccessSslFlags GetAccessSslFlags(string virtualPath) { HostedServiceTransportSettings transportSettings = GetTransportSettings(virtualPath); return transportSettings.AccessSslFlags; } internal override AuthenticationSchemes GetAuthenticationSchemes(string virtualPath) { HostedServiceTransportSettings transportSettings = GetTransportSettings(virtualPath); return RemapAuthenticationSchemes(transportSettings.AuthFlags, transportSettings.AuthProviders); } internal override ExtendedProtectionPolicy GetExtendedProtectionPolicy(string virtualPath) { HostedServiceTransportSettings transportSettings = GetTransportSettings(virtualPath); return transportSettings.IisExtendedProtectionPolicy; } // IIS and NCL have different enums/values for the various settings // therefore we will have to remap. AuthenticationSchemes RemapAuthenticationSchemes(AuthFlags flags, string[] providers) { // The default value for the authetication in IIS is anonymous AuthenticationSchemes retValue = AuthenticationSchemes.None; if ((flags & AuthFlags.AuthAnonymous) != 0) { retValue = retValue | AuthenticationSchemes.Anonymous; } if ((flags & AuthFlags.AuthBasic) != 0) { retValue = retValue | AuthenticationSchemes.Basic; } if ((flags & AuthFlags.AuthMD5) != 0) { retValue = retValue | AuthenticationSchemes.Digest; } if ((flags & AuthFlags.AuthNTLM) != 0) { for (int i = 0; i < providers.Length; i++) { if (providers[i].StartsWith(NegotiateAuthProvider, StringComparison.OrdinalIgnoreCase)) { retValue = retValue | AuthenticationSchemes.Negotiate; } else if (string.Compare(providers[i], NtlmAuthProvider, StringComparison.OrdinalIgnoreCase) == 0) { retValue = retValue | AuthenticationSchemes.Ntlm; } else { throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_NotSupportedAuthScheme(providers[i]))); } } } if ((flags & AuthFlags.AuthPassport) != 0) { throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_NotSupportedAuthScheme("Passport"))); } return retValue; } HostedServiceTransportSettings GetTransportSettings(string virtualPath) { AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet(); //Make sure we get relative virtual path. string relativeVirtualPath = VirtualPathUtility.ToAppRelative(virtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath); HostedServiceTransportSettings transportSettings; if (!transportSettingsTable.TryGetValue(relativeVirtualPath, out transportSettings)) { lock (ThisLock) { if (!transportSettingsTable.TryGetValue(relativeVirtualPath, out transportSettings)) { transportSettings = CreateTransportSettings(relativeVirtualPath); transportSettingsTable.Add(relativeVirtualPath, transportSettings); } } } return transportSettings; } protected abstract IEnumerable GetSiteApplicationPaths(); internal override bool IsWithinApp(string absoluteVirtualPath) { AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet(); string matchedAppPath = this.FindLongestMatchingAppPath(absoluteVirtualPath); string curAppPath = VirtualPathUtility.AppendTrailingSlash(HostingEnvironmentWrapper.ApplicationVirtualPath); return (string.Compare(matchedAppPath, curAppPath, StringComparison.OrdinalIgnoreCase) == 0); } string FindLongestMatchingAppPath(string absoluteVirtualPath) { AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet(); //we need to append slashes at the end for scenarios like this: // /App1 - current app // /App1/App2 - nested app // aboluteVirtualPath = /App1/App2.svc string longestMatchedAppPath = null; int matchLength = 0; IEnumerable appPaths = this.GetSiteApplicationPaths(); absoluteVirtualPath = VirtualPathUtility.AppendTrailingSlash(absoluteVirtualPath); foreach (string appPath in appPaths) { string childPath = VirtualPathUtility.AppendTrailingSlash(appPath); if (absoluteVirtualPath.StartsWith(childPath, StringComparison.OrdinalIgnoreCase) && childPath.Length > matchLength) { matchLength = childPath.Length; longestMatchedAppPath = childPath; } } return longestMatchedAppPath; } } class MetabaseSettingsIis6 : MetabaseSettingsIis { static class IISConstants { internal const char AboPathDelimiter = '/'; internal const string LMSegment = "/LM"; internal const string RootSegment = "/Root"; internal static char[] CommaSeparator = new char[] { ',' }; internal const string CBTRegistryHKLMPath = @"System\CurrentControlSet\Services\W3SVC\Parameters\ExtendedProtection"; internal const string SpnAttributeName = "spns"; internal const string ExtendedProtectionElementName = "extendedProtection"; internal const string TokenCheckingAttributeName = "tokenChecking"; internal const string FlagsAttributeName = "flags"; } [Fx.Tag.SecurityNote(Critical = "potentially protected data read from the IIS metabase under an elevation.")] [SecurityCritical] string siteAboPath; [Fx.Tag.SecurityNote(Critical = "potentially protected data read from the IIS metabase under an elevation.")] [SecurityCritical] string appAboPath; // Application-level settings [Fx.Tag.SecurityNote(Critical = "A SecurityCritical field, caller must use care.")] [SecurityCritical] HostedServiceTransportSettings appTransportSettings; [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use.")] [SecuritySafeCritical] internal MetabaseSettingsIis6() : base() { if (Iis7Helper.IsIis7) { throw Fx.AssertAndThrowFatal("MetabaseSettingsIis6 constructor must not be called when running in IIS7"); } SetApplicationInfo(); using (MetabaseReader reader = new MetabaseReader()) { PopulateSiteProperties(reader); PopulateApplicationProperties(reader); } } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use, returns sanitized values (safe for read).")] [SecuritySafeCritical] protected override HostedServiceTransportSettings CreateTransportSettings(string relativeVirtualPath) { HostedServiceTransportSettings transportSettings = new HostedServiceTransportSettings(); using (MetabaseReader reader = new MetabaseReader()) { transportSettings.Realm = GetRealm(reader, relativeVirtualPath); transportSettings.AccessSslFlags = GetAccessSslFlags(reader, relativeVirtualPath); transportSettings.AuthFlags = GetAuthFlags(reader, relativeVirtualPath); transportSettings.AuthProviders = GetAuthProviders(reader, relativeVirtualPath); if ((transportSettings.AuthFlags & AuthFlags.AuthNTLM) != 0) { transportSettings.IisExtendedProtectionPolicy = GetExtendedProtectionPolicy(); } } return transportSettings; } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use, returns sanitized values (safe for read).")] [SecuritySafeCritical] string GetRealm(MetabaseReader reader, string relativeVirtualPath) { object propertyValue = FindPropertyUnderAppRoot(reader, MetabasePropertyType.Realm, relativeVirtualPath); if (propertyValue != null) { return (string)propertyValue; } return appTransportSettings.Realm; } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use, returns sanitized values (safe for read).")] [SecuritySafeCritical] HttpAccessSslFlags GetAccessSslFlags(MetabaseReader reader, string relativeVirtualPath) { object propertyValue = FindPropertyUnderAppRoot(reader, MetabasePropertyType.AccessSslFlags, relativeVirtualPath); if (propertyValue != null) { return (HttpAccessSslFlags)(uint)propertyValue; } return appTransportSettings.AccessSslFlags; } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use, returns sanitized values (safe for read).")] [SecuritySafeCritical] AuthFlags GetAuthFlags(MetabaseReader reader, string relativeVirtualPath) { object propertyValue = FindPropertyUnderAppRoot(reader, MetabasePropertyType.AuthFlags, relativeVirtualPath); if (propertyValue != null) { return (AuthFlags)(uint)propertyValue; } return appTransportSettings.AuthFlags; } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use, returns sanitized values (safe for read).")] [SecuritySafeCritical] string[] GetAuthProviders(MetabaseReader reader, string relativeVirtualPath) { object propertyValue = FindPropertyUnderAppRoot(reader, MetabasePropertyType.AuthProviders, relativeVirtualPath); if (propertyValue != null) { string providersString = (string)propertyValue; string[] providers = providersString.Split(IISConstants.CommaSeparator, StringSplitOptions.RemoveEmptyEntries); if (providers != null && providers.Length > 0) { return providers; } } return appTransportSettings.AuthProviders; } [Fx.Tag.SecurityNote(Critical = "Asserts registry access to get multiple values from the registry, caller should not leak value.", Safe = "No value passed to critical method, discards after use, returns sanitized values (safe for readonly)")] [SecuritySafeCritical] [RegistryPermission(SecurityAction.Assert, Read = @"HKEY_LOCAL_MACHINE\" + IISConstants.CBTRegistryHKLMPath)] ExtendedProtectionPolicy GetExtendedProtectionPolicy() { ExtendedProtectionPolicy extendedProtection = null; using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(IISConstants.CBTRegistryHKLMPath)) { if (registryKey != null) { object tokenCheckingObj = registryKey.GetValue(IISConstants.TokenCheckingAttributeName); object flagsObj = registryKey.GetValue(IISConstants.FlagsAttributeName); object spnsObj = registryKey.GetValue(IISConstants.SpnAttributeName); //using the default one if the registry value is missing ExtendedProtectionTokenChecking tokenChecking = (tokenCheckingObj == null) ? ExtendedProtectionTokenChecking.None : (ExtendedProtectionTokenChecking)tokenCheckingObj; ExtendedProtectionFlags flags = flagsObj == null ? ExtendedProtectionFlags.None : (ExtendedProtectionFlags)flagsObj; List spns = spnsObj == null ? null : new List(spnsObj as string[]); extendedProtection = BuildExtendedProtectionPolicy(tokenChecking, flags, spns); } else { // this IIS6 does not support CBT, log a warning to tracing if (DiagnosticUtility.ShouldTraceWarning) { TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.WebHostNoCBTSupport, SR.TraceCodeWebHostNoCBTSupport, this, (Exception)null); } } } return extendedProtection; } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use.")] [SecuritySafeCritical] void SetApplicationInfo() { // find the first '/' after the /LM/W3SVC/ // and get the substring before that string applicationID = HostingEnvironmentWrapper.UnsafeApplicationID; int index = applicationID.IndexOf(IISConstants.AboPathDelimiter, ServiceHostingEnvironment.ISAPIApplicationIdPrefix.Length); siteAboPath = applicationID.Substring(IISConstants.LMSegment.Length, index - IISConstants.LMSegment.Length); if (HostingEnvironmentWrapper.ApplicationVirtualPath.Length > 1) { appAboPath = string.Concat(siteAboPath, IISConstants.RootSegment, HostingEnvironmentWrapper.ApplicationVirtualPath); } else { if (HostingEnvironmentWrapper.ApplicationVirtualPath.Length != 1 || HostingEnvironmentWrapper.ApplicationVirtualPath[0] != IISConstants.AboPathDelimiter) { throw Fx.AssertAndThrowFatal("ApplicationVirtualPath must be '/'."); } appAboPath = string.Concat(siteAboPath, IISConstants.RootSegment); } } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use.")] [SecuritySafeCritical] void PopulateSiteProperties(MetabaseReader reader) { // 1. ServerBindings object propertyValue = reader.GetData(siteAboPath, MetabasePropertyType.ServerBindings); if (propertyValue != null) { string[] serverBindings = (string[])propertyValue; if (serverBindings.Length > 0) { this.Bindings.Add(Uri.UriSchemeHttp, serverBindings); } } // 2. SecureBindings propertyValue = reader.GetData(siteAboPath, MetabasePropertyType.SecureBindings); if (propertyValue != null) { string[] secureBindings = (string[])propertyValue; if (secureBindings.Length > 0) { this.Bindings.Add(Uri.UriSchemeHttps, secureBindings); } } foreach (string scheme in this.Bindings.Keys) { this.Protocols.Add(scheme); } } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase.", Safe = "Only passes MetabaseReader instance to critical methods, discards after use.")] [SecuritySafeCritical] void PopulateApplicationProperties(MetabaseReader reader) { int foundCount = 0; bool foundRealm = false; bool foundAuthFlags = false; bool foundAccessSslFlags = !Bindings.ContainsKey(Uri.UriSchemeHttps); bool foundAuthProviders = false; appTransportSettings = new HostedServiceTransportSettings(); string endAboPath = appAboPath; object propertyValue = null; while (foundCount < 4 && endAboPath.Length >= siteAboPath.Length) { // Realm if (!foundRealm && ((propertyValue = reader.GetData(endAboPath, MetabasePropertyType.Realm)) != null)) { appTransportSettings.Realm = (string)propertyValue; foundRealm = true; foundCount++; } // AuthFlags if (!foundAuthFlags && ((propertyValue = reader.GetData(endAboPath, MetabasePropertyType.AuthFlags)) != null)) { appTransportSettings.AuthFlags = (AuthFlags)(uint)propertyValue; foundAuthFlags = true; foundCount++; } // AccessSslFlags if (!foundAccessSslFlags && ((propertyValue = reader.GetData(endAboPath, MetabasePropertyType.AccessSslFlags)) != null)) { appTransportSettings.AccessSslFlags = (HttpAccessSslFlags)(uint)propertyValue; foundAccessSslFlags = true; foundCount++; } // NTAuthProviders if (!foundAuthProviders && ((propertyValue = reader.GetData(endAboPath, MetabasePropertyType.AuthProviders)) != null)) { string providersString = (string)propertyValue; appTransportSettings.AuthProviders = providersString.Split(IISConstants.CommaSeparator, StringSplitOptions.RemoveEmptyEntries); foundAuthProviders = true; foundCount++; } // Continue the search in the parent path int index = endAboPath.LastIndexOf(IISConstants.AboPathDelimiter); endAboPath = endAboPath.Substring(0, index); } if (appTransportSettings.AuthProviders == null || appTransportSettings.AuthProviders.Length == 0) { appTransportSettings.AuthProviders = DefaultAuthProviders; } } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase." + "Caller must sanitize return value.")] [SecurityCritical] object FindPropertyUnderAppRoot(MetabaseReader reader, MetabasePropertyType propertyType, string relativeVirtualPath) { string matchedPath; return FindPropertyUnderAppRoot(reader, propertyType, relativeVirtualPath, out matchedPath); } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase." + "Caller must sanitize return value.")] [SecurityCritical] object FindPropertyUnderAppRoot(MetabaseReader reader, MetabasePropertyType propertyType, string relativeVirtualPath, out string matchedPath) { string endAboPath = appAboPath + relativeVirtualPath.Substring(1); int index = endAboPath.IndexOf(IISConstants.AboPathDelimiter, appAboPath.Length + 1); string startAboPath; if (index == -1) { startAboPath = endAboPath; } else { startAboPath = endAboPath.Substring(0, index); } return FindHierarchicalProperty(reader, propertyType, startAboPath, endAboPath, out matchedPath); } [Fx.Tag.SecurityNote(Critical = "Uses MetabaseReader (critical class) to read data from metabase." + "Caller must sanitize return value.")] [SecurityCritical] object FindHierarchicalProperty(MetabaseReader reader, MetabasePropertyType propertyType, string startAboPath, string endAboPath, out string matchedPath) { matchedPath = null; while (endAboPath.Length >= startAboPath.Length) { object propertyValue = reader.GetData(endAboPath, propertyType); if (propertyValue != null) { matchedPath = endAboPath; return propertyValue; } // Continue the search in the parent int index = endAboPath.LastIndexOf(IISConstants.AboPathDelimiter); endAboPath = endAboPath.Substring(0, index); } return null; } protected override IEnumerable GetSiteApplicationPaths() { //IsWithinApp is currently only used by WAS features throw Fx.AssertAndThrowFatal("GetSiteApplicationPaths() not implemented for iis6."); } } class HostedServiceTransportSettings { public string Realm = string.Empty; public HttpAccessSslFlags AccessSslFlags = HttpAccessSslFlags.None; public AuthFlags AuthFlags = AuthFlags.None; public string[] AuthProviders = MetabaseSettingsIis.DefaultAuthProviders; public ExtendedProtectionPolicy IisExtendedProtectionPolicy { get; set; } } [Flags] enum AuthFlags { None = 0, AuthAnonymous = 1, AuthBasic = 2, AuthNTLM = 4, // Note: AuthMD5 means IIS AuthScheme is Digest. Not MD5 algorithm. AuthMD5 = 16, AuthPassport = 64, } [Flags] enum HttpAccessSslFlags { None = 0x00000000, Ssl = 0x00000008, SslNegotiateCert = 0x00000020, SslRequireCert = 0x00000040, SslMapCert = 0x00000080, Ssl128 = 0x00000100 } enum ExtendedProtectionTokenChecking { None = 0, Allow = 1, Require = 2, } [Flags] enum ExtendedProtectionFlags { None = 0, Proxy = 1, NoServiceNameCheck = 2, AllowDotlessSpn = 4, ProxyCohosting = 32, } }