SecurityUtils.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 / IdentityModel / System / IdentityModel / SecurityUtils.cs / 1305376 / SecurityUtils.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel 
{
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.Diagnostics;
    using System.IdentityModel.Diagnostics; 
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy;
    using System.IdentityModel.Tokens;
    using System.Security; 
    using System.Security.Authentication.ExtendedProtection;
    using System.Security.Cryptography.X509Certificates; 
    using System.Security.Permissions; 
    using System.Security.Principal;
    using System.Text; 
    using Microsoft.Win32;

    static class SecurityUtils
    { 
        public const string Identities = "Identities";
        static int fipsAlgorithmPolicy = -1; 
        public const int WindowsVistaMajorNumber = 6; 
        static IIdentity anonymousIdentity;
 
        // these should be kept in [....] with IIS70
        public const string AuthTypeNTLM = "NTLM";
        public const string AuthTypeNegotiate = "Negotiate";
        public const string AuthTypeKerberos = "Kerberos"; 
        public const string AuthTypeAnonymous = "";
        public const string AuthTypeCertMap = "SSL/PCT"; // mapped from a cert 
        public const string AuthTypeBasic = "Basic"; //LogonUser 

        internal static IIdentity AnonymousIdentity 
        {
            get
            {
                if (anonymousIdentity == null) 
                    anonymousIdentity = SecurityUtils.CreateIdentity(String.Empty);
                return anonymousIdentity; 
            } 
        }
 
        public static DateTime MaxUtcDateTime
        {
            get
            { 
                // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
                return new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc); 
            } 
        }
 
        public static DateTime MinUtcDateTime
        {
            get
            { 
                // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
                return new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc); 
            } 
        }
 
        internal static IIdentity CreateIdentity(string name, string authenticationType)
        {
            return new GenericIdentity(name, authenticationType);
        } 

        internal static IIdentity CreateIdentity(string name) 
        { 
            return new GenericIdentity(name);
        } 

        internal static byte[] CloneBuffer(byte[] buffer)
        {
            return CloneBuffer(buffer, 0, buffer.Length); 
        }
 
        internal static byte[] CloneBuffer(byte[] buffer, int offset, int len) 
        {
            DiagnosticUtility.DebugAssert(offset >= 0, "Negative offset passed to CloneBuffer."); 
            DiagnosticUtility.DebugAssert(len >= 0, "Negative len passed to CloneBuffer.");
            DiagnosticUtility.DebugAssert(buffer.Length - offset >= len, "Invalid parameters to CloneBuffer.");

            byte[] copy = DiagnosticUtility.Utility.AllocateByteArray(len); 
            Buffer.BlockCopy(buffer, offset, copy, 0, len);
            return copy; 
        } 

        internal static bool MatchesBuffer(byte[] src, byte[] dst) 
        {
            return MatchesBuffer(src, 0, dst, 0);
        }
 
        internal static bool MatchesBuffer(byte[] src, int srcOffset, byte[] dst, int dstOffset)
        { 
            DiagnosticUtility.DebugAssert(dstOffset >= 0, "Negative dstOffset passed to MatchesBuffer."); 
            DiagnosticUtility.DebugAssert(srcOffset >= 0, "Negative srcOffset passed to MatchesBuffer.");
 
            // defensive programming
            if ((dstOffset < 0) || (srcOffset < 0))
                return false;
 
            if (src == null || srcOffset >= src.Length)
                return false; 
            if (dst == null || dstOffset >= dst.Length) 
                return false;
            if ((src.Length - srcOffset) != (dst.Length - dstOffset)) 
                return false;

            for (int i = srcOffset, j = dstOffset; i < src.Length; i++, j++)
            { 
                if (src[i] != dst[j])
                    return false; 
            } 
            return true;
        } 

        internal static string GetCertificateId(X509Certificate2 certificate)
        {
            string certificateId = certificate.SubjectName.Name; 
            if (String.IsNullOrEmpty(certificateId))
                certificateId = certificate.Thumbprint; 
            return certificateId; 
        }
 
        internal static bool IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClockSkew)
        {
            DateTime curEffectiveTime = (effectiveTime < DateTime.MinValue.Add(maxClockSkew)) ? effectiveTime : effectiveTime.Subtract(maxClockSkew);
            DateTime curExpirationTime = (expirationTime > DateTime.MaxValue.Subtract(maxClockSkew)) ? expirationTime : expirationTime.Add(maxClockSkew); 
            DateTime curTime = DateTime.UtcNow;
 
            return (curEffectiveTime.ToUniversalTime() <= curTime) && (curTime < curExpirationTime.ToUniversalTime()); 
        }
 
        // Federal Information Processing Standards Publications
        // at http://www.itl.nist.gov/fipspubs/geninfo.htm
        internal static bool RequiresFipsCompliance
        { 
            /// 
            /// Critical - Calls an UnsafeNativeMethod and a Critical method (GetFipsAlgorithmPolicyKeyFromRegistry) 
            /// Safe - processes the return and just returns a bool, which is safe 
            /// 
            [SecuritySafeCritical] 
            get
            {
                if (fipsAlgorithmPolicy == -1)
                { 
                    if (Environment.OSVersion.Version.Major >= WindowsVistaMajorNumber)
                    { 
                        bool fipsEnabled; 
#pragma warning suppress 56523 // we check for the return code of the method instead of calling GetLastWin32Error
                        bool readPolicy = (CAPI.S_OK == CAPI.BCryptGetFipsAlgorithmMode(out fipsEnabled)); 

                        if (readPolicy && fipsEnabled)
                            fipsAlgorithmPolicy = 1;
                        else 
                            fipsAlgorithmPolicy = 0;
                    } 
                    else 
                    {
                        fipsAlgorithmPolicy = GetFipsAlgorithmPolicyKeyFromRegistry(); 
                        if (fipsAlgorithmPolicy != 1)
                            fipsAlgorithmPolicy = 0;
                    }
                } 
                return fipsAlgorithmPolicy == 1;
            } 
        } 

        const string fipsPolicyRegistryKey = @"System\CurrentControlSet\Control\Lsa"; 

        /// 
        /// Critical - Asserts to get a value from the registry
        ///  
        [SecurityCritical]
        [RegistryPermission(SecurityAction.Assert, Read = @"HKEY_LOCAL_MACHINE\" + fipsPolicyRegistryKey)] 
        static int GetFipsAlgorithmPolicyKeyFromRegistry() 
        {
            int fipsAlgorithmPolicy = -1; 
            using (RegistryKey fipsAlgorithmPolicyKey = Registry.LocalMachine.OpenSubKey(fipsPolicyRegistryKey, false))
            {
                if (fipsAlgorithmPolicyKey != null)
                { 
                    object data = fipsAlgorithmPolicyKey.GetValue("FIPSAlgorithmPolicy");
                    if (data != null) 
                        fipsAlgorithmPolicy = (int)data; 
                }
            } 
            return fipsAlgorithmPolicy;
        }

        class SimpleAuthorizationContext : AuthorizationContext 
        {
            SecurityUniqueId id; 
            UnconditionalPolicy policy; 
            IDictionary properties;
 
            public SimpleAuthorizationContext(IList authorizationPolicies)
            {
                this.policy = (UnconditionalPolicy)authorizationPolicies[0];
                Dictionary properties = new Dictionary(); 
                if (this.policy.PrimaryIdentity != null && this.policy.PrimaryIdentity != SecurityUtils.AnonymousIdentity)
                { 
                    List identities = new List(); 
                    identities.Add(this.policy.PrimaryIdentity);
                    properties.Add(SecurityUtils.Identities, identities); 
                }
                // Might need to port ReadOnlyDictionary?
                this.properties = properties;
            } 

            public override string Id 
            { 
                get
                { 
                    if (this.id == null)
                        this.id = SecurityUniqueId.Create();
                    return this.id.Value;
                } 
            }
            public override ReadOnlyCollection ClaimSets { get { return this.policy.Issuances; } } 
            public override DateTime ExpirationTime { get { return this.policy.ExpirationTime; } } 
            public override IDictionary Properties { get { return this.properties; } }
        } 

        internal static AuthorizationContext CreateDefaultAuthorizationContext(IList authorizationPolicies)
        {
            AuthorizationContext authorizationContext; 
            // This is faster than Policy evaluation.
            if (authorizationPolicies != null && authorizationPolicies.Count == 1 && authorizationPolicies[0] is UnconditionalPolicy) 
            { 
                authorizationContext = new SimpleAuthorizationContext(authorizationPolicies);
            } 
            // degenerate case
            else if (authorizationPolicies == null || authorizationPolicies.Count <= 0)
            {
                return DefaultAuthorizationContext.Empty; 
            }
            else 
            { 
                // there are some policies, run them until they are all done
                DefaultEvaluationContext evaluationContext = new DefaultEvaluationContext(); 
                object[] policyState = new object[authorizationPolicies.Count];
                object done = new object();

                int oldContextCount; 
                do
                { 
                    oldContextCount = evaluationContext.Generation; 

                    for (int i = 0; i < authorizationPolicies.Count; i++) 
                    {
                        if (policyState[i] == done)
                            continue;
 
                        IAuthorizationPolicy policy = authorizationPolicies[i];
                        if (policy == null) 
                        { 
                            policyState[i] = done;
                            continue; 
                        }

                        if (policy.Evaluate(evaluationContext, ref policyState[i]))
                        { 
                            policyState[i] = done;
 
                            if (DiagnosticUtility.ShouldTraceVerbose) 
                            {
                                TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.AuthorizationPolicyEvaluated, 
                                    SR.GetString(SR.AuthorizationPolicyEvaluated, policy.Id));
                            }
                        }
                    } 

                } while (oldContextCount < evaluationContext.Generation); 
 
                authorizationContext = new DefaultAuthorizationContext(evaluationContext);
            } 

            if (DiagnosticUtility.ShouldTraceInformation)
            {
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AuthorizationContextCreated, 
                    SR.GetString(SR.AuthorizationContextCreated, authorizationContext.Id));
            } 
 
            return authorizationContext;
        } 

        internal static string ClaimSetToString(ClaimSet claimSet)
        {
            StringBuilder sb = new StringBuilder(); 
            sb.AppendLine("ClaimSet [");
            for (int i = 0; i < claimSet.Count; i++) 
            { 
                Claim claim = claimSet[i];
                if (claim != null) 
                {
                    sb.Append("  ");
                    sb.AppendLine(claim.ToString());
                } 
            }
            string prefix = "] by "; 
            ClaimSet issuer = claimSet; 
            do
            { 
                // PreSharp Bug: A null-dereference can occur here.
#pragma warning suppress 56506 // issuer was just set to this.
                issuer = issuer.Issuer;
                sb.AppendFormat("{0}{1}", prefix, issuer == claimSet ? "Self" : (issuer.Count <= 0 ? "Unknown" : issuer[0].ToString())); 
                prefix = " -> ";
            } while (issuer.Issuer != issuer); 
            return sb.ToString(); 
        }
 
        // This is the workaround, Since store.Certificates returns a full collection
        // of certs in store.  These are holding native resources.
        internal static void ResetAllCertificates(X509Certificate2Collection certificates)
        { 
            if (certificates != null)
            { 
                for (int i = 0; i < certificates.Count; ++i) 
                {
                    certificates[i].Reset(); 
                }
            }
        }
 
        internal static byte[] DecodeHexString(string hexString)
        { 
            hexString = hexString.Trim(); 

            bool spaceSkippingMode = false; 

            int i = 0;
            int length = hexString.Length;
 
            if ((length >= 2) &&
                (hexString[0] == '0') && 
                ((hexString[1] == 'x') || (hexString[1] == 'X'))) 
            {
                length = hexString.Length - 2; 
                i = 2;
            }

            if (length < 2) 
                throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString)));
 
            byte[] sArray; 

            if (length >= 3 && hexString[i + 2] == ' ') 
            {
                if (length % 3 != 2)
                    throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString)));
 
                spaceSkippingMode = true;
 
                // Each hex digit will take three spaces, except the first (hence the plus 1). 
                sArray = DiagnosticUtility.Utility.AllocateByteArray(length / 3 + 1);
            } 
            else
            {
                if (length % 2 != 0)
                    throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString))); 

                spaceSkippingMode = false; 
 
                // Each hex digit will take two spaces
                sArray = DiagnosticUtility.Utility.AllocateByteArray(length / 2); 
            }

            int digit;
            int rawdigit; 
            for (int j = 0; i < hexString.Length; i += 2, j++)
            { 
                rawdigit = ConvertHexDigit(hexString[i]); 
                digit = ConvertHexDigit(hexString[i + 1]);
                sArray[j] = (byte)(digit | (rawdigit << 4)); 
                if (spaceSkippingMode)
                    i++;
            }
            return (sArray); 
        }
 
        static int ConvertHexDigit(Char val) 
        {
            if (val <= '9' && val >= '0') 
                return (val - '0');
            else if (val >= 'a' && val <= 'f')
                return ((val - 'a') + 10);
            else if (val >= 'A' && val <= 'F') 
                return ((val - 'A') + 10);
            else 
                throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString))); 
        }
 
        internal static ReadOnlyCollection CreateAuthorizationPolicies(ClaimSet claimSet)
        {
            return CreateAuthorizationPolicies(claimSet, SecurityUtils.MaxUtcDateTime);
        } 

        internal static ReadOnlyCollection CreateAuthorizationPolicies(ClaimSet claimSet, DateTime expirationTime) 
        { 
            List policies = new List(1);
            policies.Add(new UnconditionalPolicy(claimSet, expirationTime)); 
            return policies.AsReadOnly();
        }

        internal static string GenerateId() 
        {
            return SecurityUniqueId.Create().Value; 
        } 

        internal static bool IsSupportedAlgorithm(string algorithm, SecurityToken token) 
        {
            if (token.SecurityKeys == null)
            {
                return false; 
            }
            for (int i = 0; i < token.SecurityKeys.Count; ++i) 
            { 
                if (token.SecurityKeys[i].IsSupportedAlgorithm(algorithm))
                { 
                    return true;
                }
            }
            return false; 
        }
 
        internal static IIdentity CloneIdentityIfNecessary(IIdentity identity) 
        {
            if (identity != null) 
            {
                WindowsIdentity wid = identity as WindowsIdentity;
                if (wid != null)
                { 
                    return CloneWindowsIdentityIfNecessary(wid);
                } 
                //X509Identity x509 = identity as X509Identity; 
                //if (x509 != null)
                //{ 
                //    return x509.Clone();
                //}
            }
            return identity; 
        }
 
        ///  
        /// Critical - calls two critical methods: UnsafeGetWindowsIdentityToken and UnsafeCreateWindowsIdentityFromToken
        /// Safe - "clone" operation is considered safe despite using WindowsIdentity IntPtr token 
        ///        must not let IntPtr token leak in or out
        /// 
        [SecuritySafeCritical]
        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid) 
        {
            return CloneWindowsIdentityIfNecessary(wid, wid.AuthenticationType); 
        } 

        [SecuritySafeCritical] 
        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authenticationType)
        {

            if (wid != null) 
            {
                IntPtr token = UnsafeGetWindowsIdentityToken(wid); 
                if (token != IntPtr.Zero) 
                {
                    return UnsafeCreateWindowsIdentityFromToken(token, authenticationType); 
                }
            }
            return wid;
        } 

        ///  
        /// Critical - elevates in order to return the WindowsIdentity.Token property 
        ///            caller must protect return value
        ///  
        [SecurityCritical]
        [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
        static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid)
        { 
            return wid.Token;
        } 
 
        /// 
        /// Critical - elevates in order to construct a WindowsIdentity instance from an IntPtr 
        ///            caller must protect parameter return value
        /// 
        // We pass the authenticationType in as WindowsIdentity will all into a priviledged call in LSA which could fail
        // resulting in a null authenticationType. 
        [SecurityCritical]
        [SecurityPermission(SecurityAction.Assert, ControlPrincipal = true, UnmanagedCode = true)] 
        static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authenticationType) 
        {
            if (authenticationType != null) 
            {
                return new WindowsIdentity(token, authenticationType);
            }
            else 
            {
                return new WindowsIdentity(token); 
            } 
        }
 
        internal static ClaimSet CloneClaimSetIfNecessary(ClaimSet claimSet)
        {
            if (claimSet != null)
            { 
                WindowsClaimSet wic = claimSet as WindowsClaimSet;
                if (wic != null) 
                { 
                    return wic.Clone();
                } 
                //X509CertificateClaimSet x509 = claimSet as X509CertificateClaimSet;
                //if (x509 != null)
                //{
                //    return x509.Clone(); 
                //}
            } 
            return claimSet; 
        }
 
        internal static ReadOnlyCollection CloneClaimSetsIfNecessary(ReadOnlyCollection claimSets)
        {
            if (claimSets != null)
            { 
                bool clone = false;
                for (int i = 0; i < claimSets.Count; ++i) 
                { 
                    if (claimSets[i] is WindowsClaimSet)// || claimSets[i] is X509CertificateClaimSet)
                    { 
                        clone = true;
                        break;
                    }
                } 
                if (clone)
                { 
                    List ret = new List(claimSets.Count); 
                    for (int i = 0; i < claimSets.Count; ++i)
                    { 
                        ret.Add(SecurityUtils.CloneClaimSetIfNecessary(claimSets[i]));
                    }
                    return ret.AsReadOnly();
                } 
            }
            return claimSets; 
        } 

        internal static void DisposeClaimSetIfNecessary(ClaimSet claimSet) 
        {
            if (claimSet != null)
            {
                SecurityUtils.DisposeIfNecessary(claimSet as WindowsClaimSet); 
            }
        } 
 
        internal static void DisposeClaimSetsIfNecessary(ReadOnlyCollection claimSets)
        { 
            if (claimSets != null)
            {
                for (int i = 0; i < claimSets.Count; ++i)
                { 
                    SecurityUtils.DisposeIfNecessary(claimSets[i] as WindowsClaimSet);
                } 
            } 
        }
 
        internal static ReadOnlyCollection CloneAuthorizationPoliciesIfNecessary(ReadOnlyCollection authorizationPolicies)
        {
            if (authorizationPolicies != null && authorizationPolicies.Count > 0)
            { 
                bool clone = false;
                for (int i = 0; i < authorizationPolicies.Count; ++i) 
                { 
                    UnconditionalPolicy policy = authorizationPolicies[i] as UnconditionalPolicy;
                    if (policy != null && policy.IsDisposable) 
                    {
                        clone = true;
                        break;
                    } 
                }
                if (clone) 
                { 
                    List ret = new List(authorizationPolicies.Count);
                    for (int i = 0; i < authorizationPolicies.Count; ++i) 
                    {
                        UnconditionalPolicy policy = authorizationPolicies[i] as UnconditionalPolicy;
                        if (policy != null)
                        { 
                            ret.Add(policy.Clone());
                        } 
                        else 
                        {
                            ret.Add(authorizationPolicies[i]); 
                        }
                    }
                    return ret.AsReadOnly();
                } 
            }
            return authorizationPolicies; 
        } 

        public static void DisposeAuthorizationPoliciesIfNecessary(ReadOnlyCollection authorizationPolicies) 
        {
            if (authorizationPolicies != null && authorizationPolicies.Count > 0)
            {
                for (int i = 0; i < authorizationPolicies.Count; ++i) 
                {
                    DisposeIfNecessary(authorizationPolicies[i] as UnconditionalPolicy); 
                } 
            }
        } 

        public static void DisposeIfNecessary(IDisposable obj)
        {
            if (obj != null) 
            {
                obj.Dispose(); 
            } 
        }
    } 
    /// 
    /// Internal helper class to help keep Kerberos and Spnego in [....].
    /// This code is shared by:
    ///     System\IdentityModel\Tokens\KerberosReceiverSecurityToken.cs 
    ///     System\ServiceModel\Security\WindowsSspiNegotiation.cs
    /// Both this code paths require this logic. 
    ///  
    internal class ExtendedProtectionPolicyHelper
    { 
        //
        // keep the defaults: _protectionScenario and _policyEnforcement, in [....] with: static class System.ServiceModel.Channel.ChannelBindingUtility
        // We can't access those defaults as IdentityModel cannot take a dependency on ServiceModel
        // 
        static ExtendedProtectionPolicy disabledPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
 
        PolicyEnforcement _policyEnforcement; 
        ProtectionScenario _protectionScenario;
        ChannelBinding _channelBinding; 
        ServiceNameCollection _serviceNameCollection;
        bool _checkServiceBinding;

        public ExtendedProtectionPolicyHelper( ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy ) 
        {
            _protectionScenario = DefaultPolicy.ProtectionScenario; 
            _policyEnforcement = DefaultPolicy.PolicyEnforcement; 

            _channelBinding = channelBinding; 
            _serviceNameCollection = null;
            _checkServiceBinding = true;

            if (extendedProtectionPolicy != null) 
            {
                _policyEnforcement = extendedProtectionPolicy.PolicyEnforcement; 
                _protectionScenario = extendedProtectionPolicy.ProtectionScenario; 
                _serviceNameCollection = extendedProtectionPolicy.CustomServiceNames;
            } 

            if (_policyEnforcement == PolicyEnforcement.Never)
            {
                _checkServiceBinding = false; 
            }
        } 
 
        public bool ShouldAddChannelBindingToASC()
        { 
            return (_channelBinding != null && _policyEnforcement != PolicyEnforcement.Never && _protectionScenario != ProtectionScenario.TrustedProxy);
        }

        public ChannelBinding ChannelBinding 
        {
            get { return _channelBinding; } 
        } 

        public bool ShouldCheckServiceBinding 
        {
            get { return _checkServiceBinding; }
        }
 
        public ServiceNameCollection ServiceNameCollection
        { 
            get { return _serviceNameCollection; } 
        }
 
        public ProtectionScenario ProtectionScenario
        {
            get { return _protectionScenario; }
        } 

        public PolicyEnforcement PolicyEnforcement 
        { 
            get { return _policyEnforcement; }
        } 

        /// 
        /// ServiceBinding check has the following logic:
        /// 1. Check PolicyEnforcement - never => return true; 
        /// 1. Check status returned from SecurityContext which is obtained when querying for the serviceBinding
        /// 2. Check PolicyEnforcement 
        ///     a. WhenSupported - valid when OS does not support, null serviceBinding is valid 
        ///     b. Always - a non-empty servicebinding must be available
        /// 3. if serviceBinding is non null, check that an expected value is in the ServiceNameCollection - ignoring case 
        ///    note that the empty string must be explicitly specified in the serviceNames.
        /// 
        /// status Code returned when obtaining serviceBinding from SecurityContext
        /// If servicebinding is valid 
        public void CheckServiceBinding( SafeDeleteContext securityContext, string defaultServiceBinding )
        { 
            if (_policyEnforcement == PolicyEnforcement.Never) 
            {
                return; 
            }

            string serviceBinding = null;
            int statusCode = SspiWrapper.QuerySpecifiedTarget(securityContext, out serviceBinding); 

            if (statusCode != (int)SecurityStatus.OK) 
            { 
                // only two acceptable non-zero values
                // client OS not patched: stausCode == TargetUnknown 
                // service OS not patched: statusCode == Unsupported
                if (statusCode != (int)SecurityStatus.TargetUnknown && statusCode != (int)SecurityStatus.Unsupported)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationNoServiceBinding))); 
                }
 
                // if policyEnforcement is Always we needed to see a TargetName (SPN) 
                if (_policyEnforcement == PolicyEnforcement.Always)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationNoServiceBinding)));
                }

                // in this case we accept because either the client or service is not patched. 
                if (_policyEnforcement == PolicyEnforcement.WhenSupported)
                { 
                    return; 
                }
 
                // guard against futures, force failure and fix as necessary
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationNoServiceBinding)));
            }
 
            switch (_policyEnforcement)
            { 
            case PolicyEnforcement.WhenSupported: 
                // serviceBinding == null => client is not patched
                if (serviceBinding == null) 
                    return;
                break;

            case PolicyEnforcement.Always: 
                // serviceBinding == null => client is not patched
                // serviceBinding == "" => SB was not specified 
                if (string.IsNullOrEmpty(serviceBinding)) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty)));
                break; 
            }

            // iff no values were 'user' set, then check the defaultServiceBinding
            if (_serviceNameCollection == null || _serviceNameCollection.Count < 1) 
            {
                if (defaultServiceBinding == null) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty))); 

                if (string.Compare(defaultServiceBinding, serviceBinding, StringComparison.OrdinalIgnoreCase) == 0) 
                    return;

                if (string.IsNullOrEmpty(serviceBinding))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty))); 
                else
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, serviceBinding))); 
            } 

            foreach (string serviceName in _serviceNameCollection) 
            {
                if (serviceName == null)
                {
                    continue; 
                }
 
                if (string.Compare(serviceName, serviceBinding, StringComparison.OrdinalIgnoreCase) == 0) 
                {
                    return; 
                }
            }

            if (string.IsNullOrEmpty(serviceBinding)) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty)));
            else 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, serviceBinding))); 
        }
 
        /// 
        /// Keep this in [....] with \System\ServiceModel\Channels\ChannelBindingUtility.cs
        /// 
        public static ExtendedProtectionPolicy DefaultPolicy 
        {   //
            //keep the default in [....] with : static class System.ServiceModel.Channels.ChannelBindingUtility 
            //we can't use these defaults as IdentityModel cannot take a dependency on ServiceModel 
            //
 
            // Current POR is "Never" respect the above note.

            get { return disabledPolicy; }
        } 
    }
 
    static class EmptyReadOnlyCollection 
    {
        public static ReadOnlyCollection Instance = new ReadOnlyCollection(new List()); 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel 
{
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.Diagnostics;
    using System.IdentityModel.Diagnostics; 
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy;
    using System.IdentityModel.Tokens;
    using System.Security; 
    using System.Security.Authentication.ExtendedProtection;
    using System.Security.Cryptography.X509Certificates; 
    using System.Security.Permissions; 
    using System.Security.Principal;
    using System.Text; 
    using Microsoft.Win32;

    static class SecurityUtils
    { 
        public const string Identities = "Identities";
        static int fipsAlgorithmPolicy = -1; 
        public const int WindowsVistaMajorNumber = 6; 
        static IIdentity anonymousIdentity;
 
        // these should be kept in [....] with IIS70
        public const string AuthTypeNTLM = "NTLM";
        public const string AuthTypeNegotiate = "Negotiate";
        public const string AuthTypeKerberos = "Kerberos"; 
        public const string AuthTypeAnonymous = "";
        public const string AuthTypeCertMap = "SSL/PCT"; // mapped from a cert 
        public const string AuthTypeBasic = "Basic"; //LogonUser 

        internal static IIdentity AnonymousIdentity 
        {
            get
            {
                if (anonymousIdentity == null) 
                    anonymousIdentity = SecurityUtils.CreateIdentity(String.Empty);
                return anonymousIdentity; 
            } 
        }
 
        public static DateTime MaxUtcDateTime
        {
            get
            { 
                // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
                return new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc); 
            } 
        }
 
        public static DateTime MinUtcDateTime
        {
            get
            { 
                // + and -  TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow.
                return new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc); 
            } 
        }
 
        internal static IIdentity CreateIdentity(string name, string authenticationType)
        {
            return new GenericIdentity(name, authenticationType);
        } 

        internal static IIdentity CreateIdentity(string name) 
        { 
            return new GenericIdentity(name);
        } 

        internal static byte[] CloneBuffer(byte[] buffer)
        {
            return CloneBuffer(buffer, 0, buffer.Length); 
        }
 
        internal static byte[] CloneBuffer(byte[] buffer, int offset, int len) 
        {
            DiagnosticUtility.DebugAssert(offset >= 0, "Negative offset passed to CloneBuffer."); 
            DiagnosticUtility.DebugAssert(len >= 0, "Negative len passed to CloneBuffer.");
            DiagnosticUtility.DebugAssert(buffer.Length - offset >= len, "Invalid parameters to CloneBuffer.");

            byte[] copy = DiagnosticUtility.Utility.AllocateByteArray(len); 
            Buffer.BlockCopy(buffer, offset, copy, 0, len);
            return copy; 
        } 

        internal static bool MatchesBuffer(byte[] src, byte[] dst) 
        {
            return MatchesBuffer(src, 0, dst, 0);
        }
 
        internal static bool MatchesBuffer(byte[] src, int srcOffset, byte[] dst, int dstOffset)
        { 
            DiagnosticUtility.DebugAssert(dstOffset >= 0, "Negative dstOffset passed to MatchesBuffer."); 
            DiagnosticUtility.DebugAssert(srcOffset >= 0, "Negative srcOffset passed to MatchesBuffer.");
 
            // defensive programming
            if ((dstOffset < 0) || (srcOffset < 0))
                return false;
 
            if (src == null || srcOffset >= src.Length)
                return false; 
            if (dst == null || dstOffset >= dst.Length) 
                return false;
            if ((src.Length - srcOffset) != (dst.Length - dstOffset)) 
                return false;

            for (int i = srcOffset, j = dstOffset; i < src.Length; i++, j++)
            { 
                if (src[i] != dst[j])
                    return false; 
            } 
            return true;
        } 

        internal static string GetCertificateId(X509Certificate2 certificate)
        {
            string certificateId = certificate.SubjectName.Name; 
            if (String.IsNullOrEmpty(certificateId))
                certificateId = certificate.Thumbprint; 
            return certificateId; 
        }
 
        internal static bool IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClockSkew)
        {
            DateTime curEffectiveTime = (effectiveTime < DateTime.MinValue.Add(maxClockSkew)) ? effectiveTime : effectiveTime.Subtract(maxClockSkew);
            DateTime curExpirationTime = (expirationTime > DateTime.MaxValue.Subtract(maxClockSkew)) ? expirationTime : expirationTime.Add(maxClockSkew); 
            DateTime curTime = DateTime.UtcNow;
 
            return (curEffectiveTime.ToUniversalTime() <= curTime) && (curTime < curExpirationTime.ToUniversalTime()); 
        }
 
        // Federal Information Processing Standards Publications
        // at http://www.itl.nist.gov/fipspubs/geninfo.htm
        internal static bool RequiresFipsCompliance
        { 
            /// 
            /// Critical - Calls an UnsafeNativeMethod and a Critical method (GetFipsAlgorithmPolicyKeyFromRegistry) 
            /// Safe - processes the return and just returns a bool, which is safe 
            /// 
            [SecuritySafeCritical] 
            get
            {
                if (fipsAlgorithmPolicy == -1)
                { 
                    if (Environment.OSVersion.Version.Major >= WindowsVistaMajorNumber)
                    { 
                        bool fipsEnabled; 
#pragma warning suppress 56523 // we check for the return code of the method instead of calling GetLastWin32Error
                        bool readPolicy = (CAPI.S_OK == CAPI.BCryptGetFipsAlgorithmMode(out fipsEnabled)); 

                        if (readPolicy && fipsEnabled)
                            fipsAlgorithmPolicy = 1;
                        else 
                            fipsAlgorithmPolicy = 0;
                    } 
                    else 
                    {
                        fipsAlgorithmPolicy = GetFipsAlgorithmPolicyKeyFromRegistry(); 
                        if (fipsAlgorithmPolicy != 1)
                            fipsAlgorithmPolicy = 0;
                    }
                } 
                return fipsAlgorithmPolicy == 1;
            } 
        } 

        const string fipsPolicyRegistryKey = @"System\CurrentControlSet\Control\Lsa"; 

        /// 
        /// Critical - Asserts to get a value from the registry
        ///  
        [SecurityCritical]
        [RegistryPermission(SecurityAction.Assert, Read = @"HKEY_LOCAL_MACHINE\" + fipsPolicyRegistryKey)] 
        static int GetFipsAlgorithmPolicyKeyFromRegistry() 
        {
            int fipsAlgorithmPolicy = -1; 
            using (RegistryKey fipsAlgorithmPolicyKey = Registry.LocalMachine.OpenSubKey(fipsPolicyRegistryKey, false))
            {
                if (fipsAlgorithmPolicyKey != null)
                { 
                    object data = fipsAlgorithmPolicyKey.GetValue("FIPSAlgorithmPolicy");
                    if (data != null) 
                        fipsAlgorithmPolicy = (int)data; 
                }
            } 
            return fipsAlgorithmPolicy;
        }

        class SimpleAuthorizationContext : AuthorizationContext 
        {
            SecurityUniqueId id; 
            UnconditionalPolicy policy; 
            IDictionary properties;
 
            public SimpleAuthorizationContext(IList authorizationPolicies)
            {
                this.policy = (UnconditionalPolicy)authorizationPolicies[0];
                Dictionary properties = new Dictionary(); 
                if (this.policy.PrimaryIdentity != null && this.policy.PrimaryIdentity != SecurityUtils.AnonymousIdentity)
                { 
                    List identities = new List(); 
                    identities.Add(this.policy.PrimaryIdentity);
                    properties.Add(SecurityUtils.Identities, identities); 
                }
                // Might need to port ReadOnlyDictionary?
                this.properties = properties;
            } 

            public override string Id 
            { 
                get
                { 
                    if (this.id == null)
                        this.id = SecurityUniqueId.Create();
                    return this.id.Value;
                } 
            }
            public override ReadOnlyCollection ClaimSets { get { return this.policy.Issuances; } } 
            public override DateTime ExpirationTime { get { return this.policy.ExpirationTime; } } 
            public override IDictionary Properties { get { return this.properties; } }
        } 

        internal static AuthorizationContext CreateDefaultAuthorizationContext(IList authorizationPolicies)
        {
            AuthorizationContext authorizationContext; 
            // This is faster than Policy evaluation.
            if (authorizationPolicies != null && authorizationPolicies.Count == 1 && authorizationPolicies[0] is UnconditionalPolicy) 
            { 
                authorizationContext = new SimpleAuthorizationContext(authorizationPolicies);
            } 
            // degenerate case
            else if (authorizationPolicies == null || authorizationPolicies.Count <= 0)
            {
                return DefaultAuthorizationContext.Empty; 
            }
            else 
            { 
                // there are some policies, run them until they are all done
                DefaultEvaluationContext evaluationContext = new DefaultEvaluationContext(); 
                object[] policyState = new object[authorizationPolicies.Count];
                object done = new object();

                int oldContextCount; 
                do
                { 
                    oldContextCount = evaluationContext.Generation; 

                    for (int i = 0; i < authorizationPolicies.Count; i++) 
                    {
                        if (policyState[i] == done)
                            continue;
 
                        IAuthorizationPolicy policy = authorizationPolicies[i];
                        if (policy == null) 
                        { 
                            policyState[i] = done;
                            continue; 
                        }

                        if (policy.Evaluate(evaluationContext, ref policyState[i]))
                        { 
                            policyState[i] = done;
 
                            if (DiagnosticUtility.ShouldTraceVerbose) 
                            {
                                TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.AuthorizationPolicyEvaluated, 
                                    SR.GetString(SR.AuthorizationPolicyEvaluated, policy.Id));
                            }
                        }
                    } 

                } while (oldContextCount < evaluationContext.Generation); 
 
                authorizationContext = new DefaultAuthorizationContext(evaluationContext);
            } 

            if (DiagnosticUtility.ShouldTraceInformation)
            {
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AuthorizationContextCreated, 
                    SR.GetString(SR.AuthorizationContextCreated, authorizationContext.Id));
            } 
 
            return authorizationContext;
        } 

        internal static string ClaimSetToString(ClaimSet claimSet)
        {
            StringBuilder sb = new StringBuilder(); 
            sb.AppendLine("ClaimSet [");
            for (int i = 0; i < claimSet.Count; i++) 
            { 
                Claim claim = claimSet[i];
                if (claim != null) 
                {
                    sb.Append("  ");
                    sb.AppendLine(claim.ToString());
                } 
            }
            string prefix = "] by "; 
            ClaimSet issuer = claimSet; 
            do
            { 
                // PreSharp Bug: A null-dereference can occur here.
#pragma warning suppress 56506 // issuer was just set to this.
                issuer = issuer.Issuer;
                sb.AppendFormat("{0}{1}", prefix, issuer == claimSet ? "Self" : (issuer.Count <= 0 ? "Unknown" : issuer[0].ToString())); 
                prefix = " -> ";
            } while (issuer.Issuer != issuer); 
            return sb.ToString(); 
        }
 
        // This is the workaround, Since store.Certificates returns a full collection
        // of certs in store.  These are holding native resources.
        internal static void ResetAllCertificates(X509Certificate2Collection certificates)
        { 
            if (certificates != null)
            { 
                for (int i = 0; i < certificates.Count; ++i) 
                {
                    certificates[i].Reset(); 
                }
            }
        }
 
        internal static byte[] DecodeHexString(string hexString)
        { 
            hexString = hexString.Trim(); 

            bool spaceSkippingMode = false; 

            int i = 0;
            int length = hexString.Length;
 
            if ((length >= 2) &&
                (hexString[0] == '0') && 
                ((hexString[1] == 'x') || (hexString[1] == 'X'))) 
            {
                length = hexString.Length - 2; 
                i = 2;
            }

            if (length < 2) 
                throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString)));
 
            byte[] sArray; 

            if (length >= 3 && hexString[i + 2] == ' ') 
            {
                if (length % 3 != 2)
                    throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString)));
 
                spaceSkippingMode = true;
 
                // Each hex digit will take three spaces, except the first (hence the plus 1). 
                sArray = DiagnosticUtility.Utility.AllocateByteArray(length / 3 + 1);
            } 
            else
            {
                if (length % 2 != 0)
                    throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString))); 

                spaceSkippingMode = false; 
 
                // Each hex digit will take two spaces
                sArray = DiagnosticUtility.Utility.AllocateByteArray(length / 2); 
            }

            int digit;
            int rawdigit; 
            for (int j = 0; i < hexString.Length; i += 2, j++)
            { 
                rawdigit = ConvertHexDigit(hexString[i]); 
                digit = ConvertHexDigit(hexString[i + 1]);
                sArray[j] = (byte)(digit | (rawdigit << 4)); 
                if (spaceSkippingMode)
                    i++;
            }
            return (sArray); 
        }
 
        static int ConvertHexDigit(Char val) 
        {
            if (val <= '9' && val >= '0') 
                return (val - '0');
            else if (val >= 'a' && val <= 'f')
                return ((val - 'a') + 10);
            else if (val >= 'A' && val <= 'F') 
                return ((val - 'A') + 10);
            else 
                throw  DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidHexString))); 
        }
 
        internal static ReadOnlyCollection CreateAuthorizationPolicies(ClaimSet claimSet)
        {
            return CreateAuthorizationPolicies(claimSet, SecurityUtils.MaxUtcDateTime);
        } 

        internal static ReadOnlyCollection CreateAuthorizationPolicies(ClaimSet claimSet, DateTime expirationTime) 
        { 
            List policies = new List(1);
            policies.Add(new UnconditionalPolicy(claimSet, expirationTime)); 
            return policies.AsReadOnly();
        }

        internal static string GenerateId() 
        {
            return SecurityUniqueId.Create().Value; 
        } 

        internal static bool IsSupportedAlgorithm(string algorithm, SecurityToken token) 
        {
            if (token.SecurityKeys == null)
            {
                return false; 
            }
            for (int i = 0; i < token.SecurityKeys.Count; ++i) 
            { 
                if (token.SecurityKeys[i].IsSupportedAlgorithm(algorithm))
                { 
                    return true;
                }
            }
            return false; 
        }
 
        internal static IIdentity CloneIdentityIfNecessary(IIdentity identity) 
        {
            if (identity != null) 
            {
                WindowsIdentity wid = identity as WindowsIdentity;
                if (wid != null)
                { 
                    return CloneWindowsIdentityIfNecessary(wid);
                } 
                //X509Identity x509 = identity as X509Identity; 
                //if (x509 != null)
                //{ 
                //    return x509.Clone();
                //}
            }
            return identity; 
        }
 
        ///  
        /// Critical - calls two critical methods: UnsafeGetWindowsIdentityToken and UnsafeCreateWindowsIdentityFromToken
        /// Safe - "clone" operation is considered safe despite using WindowsIdentity IntPtr token 
        ///        must not let IntPtr token leak in or out
        /// 
        [SecuritySafeCritical]
        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid) 
        {
            return CloneWindowsIdentityIfNecessary(wid, wid.AuthenticationType); 
        } 

        [SecuritySafeCritical] 
        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authenticationType)
        {

            if (wid != null) 
            {
                IntPtr token = UnsafeGetWindowsIdentityToken(wid); 
                if (token != IntPtr.Zero) 
                {
                    return UnsafeCreateWindowsIdentityFromToken(token, authenticationType); 
                }
            }
            return wid;
        } 

        ///  
        /// Critical - elevates in order to return the WindowsIdentity.Token property 
        ///            caller must protect return value
        ///  
        [SecurityCritical]
        [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
        static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid)
        { 
            return wid.Token;
        } 
 
        /// 
        /// Critical - elevates in order to construct a WindowsIdentity instance from an IntPtr 
        ///            caller must protect parameter return value
        /// 
        // We pass the authenticationType in as WindowsIdentity will all into a priviledged call in LSA which could fail
        // resulting in a null authenticationType. 
        [SecurityCritical]
        [SecurityPermission(SecurityAction.Assert, ControlPrincipal = true, UnmanagedCode = true)] 
        static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authenticationType) 
        {
            if (authenticationType != null) 
            {
                return new WindowsIdentity(token, authenticationType);
            }
            else 
            {
                return new WindowsIdentity(token); 
            } 
        }
 
        internal static ClaimSet CloneClaimSetIfNecessary(ClaimSet claimSet)
        {
            if (claimSet != null)
            { 
                WindowsClaimSet wic = claimSet as WindowsClaimSet;
                if (wic != null) 
                { 
                    return wic.Clone();
                } 
                //X509CertificateClaimSet x509 = claimSet as X509CertificateClaimSet;
                //if (x509 != null)
                //{
                //    return x509.Clone(); 
                //}
            } 
            return claimSet; 
        }
 
        internal static ReadOnlyCollection CloneClaimSetsIfNecessary(ReadOnlyCollection claimSets)
        {
            if (claimSets != null)
            { 
                bool clone = false;
                for (int i = 0; i < claimSets.Count; ++i) 
                { 
                    if (claimSets[i] is WindowsClaimSet)// || claimSets[i] is X509CertificateClaimSet)
                    { 
                        clone = true;
                        break;
                    }
                } 
                if (clone)
                { 
                    List ret = new List(claimSets.Count); 
                    for (int i = 0; i < claimSets.Count; ++i)
                    { 
                        ret.Add(SecurityUtils.CloneClaimSetIfNecessary(claimSets[i]));
                    }
                    return ret.AsReadOnly();
                } 
            }
            return claimSets; 
        } 

        internal static void DisposeClaimSetIfNecessary(ClaimSet claimSet) 
        {
            if (claimSet != null)
            {
                SecurityUtils.DisposeIfNecessary(claimSet as WindowsClaimSet); 
            }
        } 
 
        internal static void DisposeClaimSetsIfNecessary(ReadOnlyCollection claimSets)
        { 
            if (claimSets != null)
            {
                for (int i = 0; i < claimSets.Count; ++i)
                { 
                    SecurityUtils.DisposeIfNecessary(claimSets[i] as WindowsClaimSet);
                } 
            } 
        }
 
        internal static ReadOnlyCollection CloneAuthorizationPoliciesIfNecessary(ReadOnlyCollection authorizationPolicies)
        {
            if (authorizationPolicies != null && authorizationPolicies.Count > 0)
            { 
                bool clone = false;
                for (int i = 0; i < authorizationPolicies.Count; ++i) 
                { 
                    UnconditionalPolicy policy = authorizationPolicies[i] as UnconditionalPolicy;
                    if (policy != null && policy.IsDisposable) 
                    {
                        clone = true;
                        break;
                    } 
                }
                if (clone) 
                { 
                    List ret = new List(authorizationPolicies.Count);
                    for (int i = 0; i < authorizationPolicies.Count; ++i) 
                    {
                        UnconditionalPolicy policy = authorizationPolicies[i] as UnconditionalPolicy;
                        if (policy != null)
                        { 
                            ret.Add(policy.Clone());
                        } 
                        else 
                        {
                            ret.Add(authorizationPolicies[i]); 
                        }
                    }
                    return ret.AsReadOnly();
                } 
            }
            return authorizationPolicies; 
        } 

        public static void DisposeAuthorizationPoliciesIfNecessary(ReadOnlyCollection authorizationPolicies) 
        {
            if (authorizationPolicies != null && authorizationPolicies.Count > 0)
            {
                for (int i = 0; i < authorizationPolicies.Count; ++i) 
                {
                    DisposeIfNecessary(authorizationPolicies[i] as UnconditionalPolicy); 
                } 
            }
        } 

        public static void DisposeIfNecessary(IDisposable obj)
        {
            if (obj != null) 
            {
                obj.Dispose(); 
            } 
        }
    } 
    /// 
    /// Internal helper class to help keep Kerberos and Spnego in [....].
    /// This code is shared by:
    ///     System\IdentityModel\Tokens\KerberosReceiverSecurityToken.cs 
    ///     System\ServiceModel\Security\WindowsSspiNegotiation.cs
    /// Both this code paths require this logic. 
    ///  
    internal class ExtendedProtectionPolicyHelper
    { 
        //
        // keep the defaults: _protectionScenario and _policyEnforcement, in [....] with: static class System.ServiceModel.Channel.ChannelBindingUtility
        // We can't access those defaults as IdentityModel cannot take a dependency on ServiceModel
        // 
        static ExtendedProtectionPolicy disabledPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
 
        PolicyEnforcement _policyEnforcement; 
        ProtectionScenario _protectionScenario;
        ChannelBinding _channelBinding; 
        ServiceNameCollection _serviceNameCollection;
        bool _checkServiceBinding;

        public ExtendedProtectionPolicyHelper( ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy ) 
        {
            _protectionScenario = DefaultPolicy.ProtectionScenario; 
            _policyEnforcement = DefaultPolicy.PolicyEnforcement; 

            _channelBinding = channelBinding; 
            _serviceNameCollection = null;
            _checkServiceBinding = true;

            if (extendedProtectionPolicy != null) 
            {
                _policyEnforcement = extendedProtectionPolicy.PolicyEnforcement; 
                _protectionScenario = extendedProtectionPolicy.ProtectionScenario; 
                _serviceNameCollection = extendedProtectionPolicy.CustomServiceNames;
            } 

            if (_policyEnforcement == PolicyEnforcement.Never)
            {
                _checkServiceBinding = false; 
            }
        } 
 
        public bool ShouldAddChannelBindingToASC()
        { 
            return (_channelBinding != null && _policyEnforcement != PolicyEnforcement.Never && _protectionScenario != ProtectionScenario.TrustedProxy);
        }

        public ChannelBinding ChannelBinding 
        {
            get { return _channelBinding; } 
        } 

        public bool ShouldCheckServiceBinding 
        {
            get { return _checkServiceBinding; }
        }
 
        public ServiceNameCollection ServiceNameCollection
        { 
            get { return _serviceNameCollection; } 
        }
 
        public ProtectionScenario ProtectionScenario
        {
            get { return _protectionScenario; }
        } 

        public PolicyEnforcement PolicyEnforcement 
        { 
            get { return _policyEnforcement; }
        } 

        /// 
        /// ServiceBinding check has the following logic:
        /// 1. Check PolicyEnforcement - never => return true; 
        /// 1. Check status returned from SecurityContext which is obtained when querying for the serviceBinding
        /// 2. Check PolicyEnforcement 
        ///     a. WhenSupported - valid when OS does not support, null serviceBinding is valid 
        ///     b. Always - a non-empty servicebinding must be available
        /// 3. if serviceBinding is non null, check that an expected value is in the ServiceNameCollection - ignoring case 
        ///    note that the empty string must be explicitly specified in the serviceNames.
        /// 
        /// status Code returned when obtaining serviceBinding from SecurityContext
        /// If servicebinding is valid 
        public void CheckServiceBinding( SafeDeleteContext securityContext, string defaultServiceBinding )
        { 
            if (_policyEnforcement == PolicyEnforcement.Never) 
            {
                return; 
            }

            string serviceBinding = null;
            int statusCode = SspiWrapper.QuerySpecifiedTarget(securityContext, out serviceBinding); 

            if (statusCode != (int)SecurityStatus.OK) 
            { 
                // only two acceptable non-zero values
                // client OS not patched: stausCode == TargetUnknown 
                // service OS not patched: statusCode == Unsupported
                if (statusCode != (int)SecurityStatus.TargetUnknown && statusCode != (int)SecurityStatus.Unsupported)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationNoServiceBinding))); 
                }
 
                // if policyEnforcement is Always we needed to see a TargetName (SPN) 
                if (_policyEnforcement == PolicyEnforcement.Always)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationNoServiceBinding)));
                }

                // in this case we accept because either the client or service is not patched. 
                if (_policyEnforcement == PolicyEnforcement.WhenSupported)
                { 
                    return; 
                }
 
                // guard against futures, force failure and fix as necessary
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationNoServiceBinding)));
            }
 
            switch (_policyEnforcement)
            { 
            case PolicyEnforcement.WhenSupported: 
                // serviceBinding == null => client is not patched
                if (serviceBinding == null) 
                    return;
                break;

            case PolicyEnforcement.Always: 
                // serviceBinding == null => client is not patched
                // serviceBinding == "" => SB was not specified 
                if (string.IsNullOrEmpty(serviceBinding)) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty)));
                break; 
            }

            // iff no values were 'user' set, then check the defaultServiceBinding
            if (_serviceNameCollection == null || _serviceNameCollection.Count < 1) 
            {
                if (defaultServiceBinding == null) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty))); 

                if (string.Compare(defaultServiceBinding, serviceBinding, StringComparison.OrdinalIgnoreCase) == 0) 
                    return;

                if (string.IsNullOrEmpty(serviceBinding))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty))); 
                else
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, serviceBinding))); 
            } 

            foreach (string serviceName in _serviceNameCollection) 
            {
                if (serviceName == null)
                {
                    continue; 
                }
 
                if (string.Compare(serviceName, serviceBinding, StringComparison.OrdinalIgnoreCase) == 0) 
                {
                    return; 
                }
            }

            if (string.IsNullOrEmpty(serviceBinding)) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, string.Empty)));
            else 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.InvalidServiceBindingInSspiNegotiationServiceBindingNotMatched, serviceBinding))); 
        }
 
        /// 
        /// Keep this in [....] with \System\ServiceModel\Channels\ChannelBindingUtility.cs
        /// 
        public static ExtendedProtectionPolicy DefaultPolicy 
        {   //
            //keep the default in [....] with : static class System.ServiceModel.Channels.ChannelBindingUtility 
            //we can't use these defaults as IdentityModel cannot take a dependency on ServiceModel 
            //
 
            // Current POR is "Never" respect the above note.

            get { return disabledPolicy; }
        } 
    }
 
    static class EmptyReadOnlyCollection 
    {
        public static ReadOnlyCollection Instance = new ReadOnlyCollection(new List()); 
    }
}

// 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