CredentialCache.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / CredentialCache.cs / 1 / CredentialCache.cs

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

namespace System.Net { 
    using System.Net.Sockets; 
    using System.Collections;
    using System.Runtime.InteropServices; 
    using System.Security.Permissions;
    using System.Globalization;

    // More sophisticated password cache that stores multiple 
    // name-password pairs and associates these with host/realm
    ///  
    ///    Provides storage for multiple credentials. 
    /// 
    public class CredentialCache : ICredentials, ICredentialsByHost, IEnumerable { 

    // fields

        private Hashtable cache = new Hashtable(); 
        private Hashtable cacheForHosts = new Hashtable();
        internal int m_version; 
 
        private int m_NumbDefaultCredInCache = 0;
 
        // [thread token optimization] The resulting counter of default credential resided in the cache.
        internal bool IsDefaultInCache {
            get {
                return m_NumbDefaultCredInCache != 0; 
            }
        } 
 
    // constructors
 
        /// 
        ///    
        ///       Initializes a new instance of the  class.
        ///     
        /// 
        public CredentialCache() { 
        } 

    // properties 

    // methods

        ///  
        /// Adds a 
        /// instance to the credential cache. 
        ///  
        // UEUE
        public void Add(Uri uriPrefix, string authType, NetworkCredential cred) { 
            //
            // parameter validation
            //
            if (uriPrefix==null) { 
                throw new ArgumentNullException("uriPrefix");
            } 
            if (authType==null) { 
                throw new ArgumentNullException("authType");
            } 
            if ((cred is SystemNetworkCredential)
#if !FEATURE_PAL
                && !((string.Compare(authType, NtlmClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)
                     || (DigestClient.WDigestAvailable && (string.Compare(authType, DigestClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)) 
                     || (string.Compare(authType, KerberosClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)
                     || (string.Compare(authType, NegotiateClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)) 
#endif 
                ) {
                throw new ArgumentException(SR.GetString(SR.net_nodefaultcreds, authType), "authType"); 
            }

            ++m_version;
 
            CredentialKey key = new CredentialKey(uriPrefix, authType);
 
            GlobalLog.Print("CredentialCache::Add() Adding key:[" + key.ToString() + "], cred:[" + cred.Domain + "],[" + cred.UserName + "]"); 

            cache.Add(key, cred); 
            if (cred is SystemNetworkCredential) {
                ++m_NumbDefaultCredInCache;
            }
        } 

 
        public void Add(string host, int port, string authenticationType, NetworkCredential credential) { 
            //
            // parameter validation 
            //
            if (host==null) {
                throw new ArgumentNullException("host");
            } 

            if (authenticationType==null) { 
                throw new ArgumentNullException("authenticationType"); 
            }
 
            if (host.Length == 0) {
                throw new ArgumentException(SR.GetString(SR.net_emptystringcall,"host"));
            }
 
            if (port < 0) {
                throw new ArgumentOutOfRangeException("port"); 
            } 
            if ((credential is SystemNetworkCredential)
#if !FEATURE_PAL 
                && !((string.Compare(authenticationType, NtlmClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)
                     || (DigestClient.WDigestAvailable && (string.Compare(authenticationType, DigestClient.AuthType, StringComparison.OrdinalIgnoreCase)==0))
                     || (string.Compare(authenticationType, KerberosClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)
                     || (string.Compare(authenticationType, NegotiateClient.AuthType, StringComparison.OrdinalIgnoreCase)==0)) 
#endif
                ) { 
                throw new ArgumentException(SR.GetString(SR.net_nodefaultcreds, authenticationType), "authenticationType"); 
            }
 
            ++m_version;

            CredentialHostKey key = new CredentialHostKey(host,port, authenticationType);
 
            GlobalLog.Print("CredentialCache::Add() Adding key:[" + key.ToString() + "], cred:[" + credential.Domain + "],[" + credential.UserName + "]");
 
            cacheForHosts.Add(key, credential); 
            if (credential is SystemNetworkCredential) {
                ++m_NumbDefaultCredInCache; 
            }
        }

 
        /// 
        /// Removes a  
        /// instance from the credential cache. 
        /// 
        public void Remove(Uri uriPrefix, string authType) { 
            if (uriPrefix==null || authType==null) {
                // these couldn't possibly have been inserted into
                // the cache because of the test in Add()
                return; 
            }
 
            ++m_version; 

            CredentialKey key = new CredentialKey(uriPrefix, authType); 

            GlobalLog.Print("CredentialCache::Remove() Removing key:[" + key.ToString() + "]");

            if (cache[key] is SystemNetworkCredential) { 
                --m_NumbDefaultCredInCache;
            } 
            cache.Remove(key); 
        }
 

        public void Remove(string host, int port, string authenticationType) {
            if (host==null || authenticationType==null) {
                // these couldn't possibly have been inserted into 
                // the cache because of the test in Add()
                return; 
            } 

            if (port < 0) { 
                return;
            }

 
            ++m_version;
 
            CredentialHostKey key = new CredentialHostKey(host, port, authenticationType); 

            GlobalLog.Print("CredentialCache::Remove() Removing key:[" + key.ToString() + "]"); 

            if (cacheForHosts[key] is SystemNetworkCredential) {
                --m_NumbDefaultCredInCache;
            } 
            cacheForHosts.Remove(key);
        } 
 
        /// 
        ///     
        ///       Returns the 
        ///       instance associated with the supplied Uri and
        ///       authentication type.
        ///     
        /// 
        public NetworkCredential GetCredential(Uri uriPrefix, string authType) { 
            if (uriPrefix==null) 
                throw new ArgumentNullException("uriPrefix");
            if (authType==null) 
                throw new ArgumentNullException("authType");

            GlobalLog.Print("CredentialCache::GetCredential(uriPrefix=\"" + uriPrefix + "\", authType=\"" + authType + "\")");
 
            int longestMatchPrefix = -1;
            NetworkCredential mostSpecificMatch = null; 
            IDictionaryEnumerator credEnum = cache.GetEnumerator(); 

            // 
            // Enumerate through every credential in the cache
            //

            while (credEnum.MoveNext()) { 

                CredentialKey key = (CredentialKey)credEnum.Key; 
 
                //
                // Determine if this credential is applicable to the current Uri/AuthType 
                //

                if (key.Match(uriPrefix, authType)) {
 
                    int prefixLen = key.UriPrefixLength;
 
                    // 
                    // Check if the match is better than the current-most-specific match
                    // 

                    if (prefixLen > longestMatchPrefix) {

                        // 
                        // Yes-- update the information about currently preferred match
                        // 
 
                        longestMatchPrefix = prefixLen;
                        mostSpecificMatch = (NetworkCredential)credEnum.Value; 
                    }
                }
            }
 
            GlobalLog.Print("CredentialCache::GetCredential returning " + ((mostSpecificMatch==null)?"null":"(" + mostSpecificMatch.UserName + ":" + mostSpecificMatch.Domain + ")"));
 
            return mostSpecificMatch; 
        }
 

        public NetworkCredential GetCredential(string host, int port, string authenticationType) {
            if (host==null) {
                throw new ArgumentNullException("host"); 
            }
            if (authenticationType==null){ 
                throw new ArgumentNullException("authenticationType"); 
            }
            if (host.Length == 0) { 
                throw new ArgumentException(SR.GetString(SR.net_emptystringcall, "host"));
            }
            if (port < 0) {
                throw new ArgumentOutOfRangeException("port"); 
            }
 
 
            GlobalLog.Print("CredentialCache::GetCredential(host=\"" + host + ":" + port.ToString() +"\", authenticationType=\"" + authenticationType + "\")");
 
            NetworkCredential match = null;

            IDictionaryEnumerator credEnum = cacheForHosts.GetEnumerator();
 
            //
            // Enumerate through every credential in the cache 
            // 

            while (credEnum.MoveNext()) { 

                CredentialHostKey key = (CredentialHostKey)credEnum.Key;

                // 
                // Determine if this credential is applicable to the current Uri/AuthType
                // 
 
                if (key.Match(host, port, authenticationType)) {
 
                        match = (NetworkCredential)credEnum.Value;
                }
            }
 
            GlobalLog.Print("CredentialCache::GetCredential returning " + ((match==null)?"null":"(" + match.UserName + ":" + match.Domain + ")"));
            return match; 
        } 

 

        /// 
        ///    [To be supplied]
        ///  

        // 
        // IEnumerable interface 
        //
 
        public IEnumerator GetEnumerator() {
            return new CredentialEnumerator(this, cache ,cacheForHosts, m_version);
        }
 

        ///  
        ///     
        ///       Gets
        ///       the default system credentials from the . 
        ///    
        /// 
        public static ICredentials DefaultCredentials {
            get { 
                //This check will not allow to use local user credentials at will.
                //Hence the username will not be exposed to the network 
                new EnvironmentPermission(EnvironmentPermissionAccess.Read, "USERNAME").Demand(); 
                return SystemNetworkCredential.defaultCredential;
            } 
        }

        public static NetworkCredential DefaultNetworkCredentials {
            get { 
                //This check will not allow to use local user credentials at will.
                //Hence the username will not be exposed to the network 
                new EnvironmentPermission(EnvironmentPermissionAccess.Read, "USERNAME").Demand(); 
                return SystemNetworkCredential.defaultCredential;
            } 
        }

        private class CredentialEnumerator : IEnumerator {
 
        // fields
 
            private CredentialCache m_cache; 
            private ICredentials[] m_array;
            private int m_index = -1; 
            private int m_version;

        // constructors
 
            internal CredentialEnumerator(CredentialCache cache, Hashtable table, Hashtable hostTable, int version) {
                m_cache = cache; 
                m_array = new ICredentials[table.Count + hostTable.Count]; 
                table.Values.CopyTo(m_array, 0);
                hostTable.Values.CopyTo(m_array, table.Count); 
                m_version = version;
            }

        // IEnumerator interface 

        // properties 
 
            object IEnumerator.Current {
                get { 
                    if (m_index < 0 || m_index >= m_array.Length) {
                        throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumOpCantHappen));
                    }
                    if (m_version != m_cache.m_version) { 
                        throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion));
                    } 
                    return m_array[m_index]; 
                }
            } 

        // methods

            bool IEnumerator.MoveNext() { 
                if (m_version != m_cache.m_version) {
                    throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion)); 
                } 
                if (++m_index < m_array.Length) {
                    return true; 
                }
                m_index = m_array.Length;
                return false;
            } 

            void IEnumerator.Reset() { 
                m_index = -1; 
            }
 
        } // class CredentialEnumerator


    } // class CredentialCache 

 
 
    // Abstraction for credentials in password-based
    // authentication schemes (basic, digest, NTLM, Kerberos) 
    // Note this is not applicable to public-key based
    // systems such as SSL client authentication
    // "Password" here may be the clear text password or it
    // could be a one-way hash that is sufficient to 
    // authenticate, as in HTTP/1.1 digest.
 
    // 
    // Object representing default credentials
    // 
    internal class SystemNetworkCredential : NetworkCredential {
        internal static readonly SystemNetworkCredential defaultCredential = new SystemNetworkCredential();

        // We want reference equality to work.  Making this private is a good way to guarantee that. 
        private SystemNetworkCredential() :
            base(string.Empty, string.Empty, string.Empty) { 
        } 
    }
 

    internal class CredentialHostKey {

        internal string Host; 
        internal string AuthenticationType;
        internal int Port; 
 
        internal CredentialHostKey(string host, int port, string authenticationType) {
            Host = host; 
            Port = port;
            AuthenticationType = authenticationType;
        }
 
        internal bool Match(string host, int port, string authenticationType) {
            if (host==null || authenticationType==null) { 
                return false; 
            }
            // 
            // If the protocols dont match this credential
            // is not applicable for the given Uri
            //
            if (string.Compare(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase) != 0) { 
                return false;
            } 
            if (string.Compare(Host, host, StringComparison.OrdinalIgnoreCase ) != 0) { 
                return false;
            } 
            if (port != Port) {
                return false;
            }
 
            GlobalLog.Print("CredentialKey::Match(" + Host.ToString() + ":" + Port.ToString() +" & " + host.ToString() + ":" + port.ToString() + ")");
            return true; 
        } 

 
        private int m_HashCode = 0;
        private bool m_ComputedHashCode = false;
        public override int GetHashCode() {
            if (!m_ComputedHashCode) { 
                //
                // compute HashCode on demand 
                // 

                m_HashCode = AuthenticationType.ToUpperInvariant().GetHashCode() + Host.ToUpperInvariant().GetHashCode() + Port.GetHashCode(); 
                m_ComputedHashCode = true;
            }
            return m_HashCode;
        } 

        public override bool Equals(object comparand) { 
            CredentialHostKey comparedCredentialKey = comparand as CredentialHostKey; 

            if (comparand==null) { 
                //
                // this covers also the compared==null case
                //
                return false; 
            }
 
            bool equals = 
                (string.Compare(AuthenticationType, comparedCredentialKey.AuthenticationType, StringComparison.OrdinalIgnoreCase ) == 0) &&
                (string.Compare(Host, comparedCredentialKey.Host, StringComparison.OrdinalIgnoreCase ) == 0) && 
                Port == comparedCredentialKey.Port;

            GlobalLog.Print("CredentialKey::Equals(" + ToString() + ", " + comparedCredentialKey.ToString() + ") returns " + equals.ToString());
 
            return equals;
        } 
 
        public override string ToString() {
            return "[" + Host.Length.ToString(NumberFormatInfo.InvariantInfo) + "]:" + Host + ":" + Port.ToString(NumberFormatInfo.InvariantInfo) + ":" + ValidationHelper.ToString(AuthenticationType); 
        }

    } // class CredentialKey
 

    internal class CredentialKey { 
 
        internal Uri UriPrefix;
        internal int UriPrefixLength = -1; 
        internal string AuthenticationType;

        internal CredentialKey(Uri uriPrefix, string authenticationType) {
            UriPrefix = uriPrefix; 
            UriPrefixLength = UriPrefix.ToString().Length;
            AuthenticationType = authenticationType; 
        } 

        internal bool Match(Uri uri, string authenticationType) { 
            if (uri==null || authenticationType==null) {
                return false;
            }
            // 
            // If the protocols dont match this credential
            // is not applicable for the given Uri 
            // 
            if (string.Compare(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase) != 0) {
                return false; 
            }

            GlobalLog.Print("CredentialKey::Match(" + UriPrefix.ToString() + " & " + uri.ToString() + ")");
 
            return IsPrefix(uri, UriPrefix);
        } 
        // 
        // IsPrefix (Uri)
        // 
        //  Determines whether  is a prefix of this URI. A prefix
        //  match is defined as:
        //
        //      scheme match 
        //      + host match
        //      + port match, if any 
        //      +  path is a prefix of  path, if any 
        //
        // Returns: 
        //  True if  is a prefix of this URI
        //
        internal bool IsPrefix(Uri uri, Uri prefixUri) {
 
            if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port)
                return false; 
 
            int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/');
            if (prefixLen > uri.AbsolutePath.LastIndexOf('/')) 
                return false;

            return String.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase ) == 0;
        } 

        private int m_HashCode = 0; 
        private bool m_ComputedHashCode = false; 
        public override int GetHashCode() {
            if (!m_ComputedHashCode) { 
                //
                // compute HashCode on demand
                //
 
                m_HashCode = AuthenticationType.ToUpperInvariant().GetHashCode() + UriPrefixLength + UriPrefix.GetHashCode();
                m_ComputedHashCode = true; 
            } 
            return m_HashCode;
        } 

        public override bool Equals(object comparand) {
            CredentialKey comparedCredentialKey = comparand as CredentialKey;
 
            if (comparand==null) {
                // 
                // this covers also the compared==null case 
                //
                return false; 
            }

            bool equals =
                (string.Compare(AuthenticationType, comparedCredentialKey.AuthenticationType, StringComparison.OrdinalIgnoreCase ) == 0) && 
                UriPrefix.Equals(comparedCredentialKey.UriPrefix);
 
            GlobalLog.Print("CredentialKey::Equals(" + ToString() + ", " + comparedCredentialKey.ToString() + ") returns " + equals.ToString()); 

            return equals; 
        }

        public override string ToString() {
            return "[" + UriPrefixLength.ToString(NumberFormatInfo.InvariantInfo) + "]:" + ValidationHelper.ToString(UriPrefix) + ":" + ValidationHelper.ToString(AuthenticationType); 
        }
 
    } // class CredentialKey 

 
} // namespace System.Net


                        

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