MetabaseSettings.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / System.ServiceModel.Activation / System / ServiceModel / Activation / MetabaseSettings.cs / 1305376 / MetabaseSettings.cs

                            //---------------------------------------------------------------------------- 
// 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);
 
        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; 
        }
    }

    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)
        { 
            //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; 
        } 
    }
 
    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;
        } 
    } 

    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,
    }
} 

// 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.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);
 
        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; 
        }
    }

    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)
        { 
            //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; 
        } 
    }
 
    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;
        } 
    } 

    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,
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK