SecurityUtils.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / IdentityModel / System / IdentityModel / SecurityUtils.cs / 1 / SecurityUtils.cs

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

namespace System.IdentityModel 
{
    using Microsoft.Win32; 
    using System.Diagnostics; 
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy; 
    using System.IdentityModel.Tokens;
    using System.Text;
    using System.Security.Principal;
    using System.Security.Cryptography.X509Certificates; 
    using System.Collections.ObjectModel;
    using System.Collections.Generic; 
    using System.Security; 
    using System.Security.Permissions;
 
    static class SecurityUtils
    {
        public const string Identities = "Identities";
        static int fipsAlgorithmPolicy = -1; 
        public const int WindowsVistaMajorNumber = 6;
        static IIdentity anonymousIdentity; 
 
        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 
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                if (fipsAlgorithmPolicy == -1)
                {
                    if (Environment.OSVersion.Version.Major >= WindowsVistaMajorNumber) 
                    {
                        bool fipsEnabled; 
#pragma warning suppress 56523 // 
                        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) 
                            { 
                                DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Verbose, System.ServiceModel.Diagnostics.TraceCode.AuthorizationPolicyEvaluated,
                                    SR.GetString(SR.AuthorizationPolicyEvaluated, policy.Id)); 
                            }
                        }
                    }
 
                } while (oldContextCount < evaluationContext.Generation);
 
                authorizationContext = new DefaultAuthorizationContext(evaluationContext); 
            }
 
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, System.ServiceModel.Diagnostics.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 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid)
        { 
            if (wid != null)
            { 
                IntPtr token = UnsafeGetWindowsIdentityToken(wid); 
                if (token != IntPtr.Zero)
                { 
                    return UnsafeCreateWindowsIdentityFromToken(token);
                }
            }
            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
        /// 
        [SecurityCritical] 
        [SecurityPermission(SecurityAction.Assert, ControlPrincipal = true, UnmanagedCode = true)]
        static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token) 
        { 
            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(); 
            }
        } 
    }

    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.
                        

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