Beispiel #1
0
 internal static void CacheCredential(SafeFreeCredentials newHandle)
 {
     try {
         SafeCredentialReference newRef = SafeCredentialReference.CreateReference(newHandle);
         if (newRef == null)
         {
             return;
         }
         unchecked
         {
             int index = Interlocked.Increment(ref _Current) & c_MaxCacheSize;
             newRef = Interlocked.Exchange <SafeCredentialReference>(ref _CacheSlots[index], newRef);
         }
         if (newRef != null)
         {
             newRef.Close();
         }
     }
     catch (Exception e) {
         if (!NclUtilities.IsFatal(e))
         {
             GlobalLog.Assert("SSPIHandlCache", "Attempted to throw: " + e.ToString());
         }
     }
 }
Beispiel #2
0
        internal static void CacheCredential(SafeFreeCredentials newHandle)
        {
            try
            {
                SafeCredentialReference newRef = SafeCredentialReference.CreateReference(newHandle);

                if (newRef == null)
                {
                    return;
                }

                unchecked
                {
                    int index = Interlocked.Increment(ref s_current) & c_MaxCacheSize;
                    newRef = Interlocked.Exchange <SafeCredentialReference>(ref s_cacheSlots[index], newRef);
                }

                newRef?.Dispose();
            }
            catch (Exception e)
            {
                if (!ExceptionCheck.IsFatal(e))
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Fail(null, $"Attempted to throw: {e}");
                    }
                }
            }
        }
Beispiel #3
0
        internal static void CacheCredential(SafeFreeCredentials newHandle)
        {
            try
            {
                SafeCredentialReference?newRef = SafeCredentialReference.CreateReference(newHandle);
                if (newRef == null)
                {
                    return;
                }

                int index = Interlocked.Increment(ref s_current) & c_MaxCacheSize;
#pragma warning disable CS8601 // Possible null reference assignment.
                newRef = Interlocked.Exchange <SafeCredentialReference>(ref s_cacheSlots[index], newRef);
#pragma warning restore CS8601 // Possible null reference assignment.

                newRef?.Dispose();
            }
            catch (Exception e)
            {
                if (NetEventSource.Log.IsEnabled() && !ExceptionCheck.IsFatal(e))
                {
                    NetEventSource.Error(null, $"Attempted to throw: {e}");
                }
            }
        }
Beispiel #4
0
        //
        // Returns null or previously cached cred handle.
        //
        // ATTN: The returned handle can be invalid, the callers of InitializeSecurityContext and AcceptSecurityContext
        // must be prepared to execute a back-out code if the call fails.
        //
        internal static SafeFreeCredentials TryCachedCredential(byte[] thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy)
        {
            if (s_CachedCreds.Count == 0)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Print("TryCachedCredential() Not found, Current Cache Count = " + s_CachedCreds.Count);
                }
                return(null);
            }

            object key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy);

            SafeCredentialReference cached = s_CachedCreds[key] as SafeCredentialReference;

            if (cached == null || cached.IsClosed || cached.Target.IsInvalid)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Print("TryCachedCredential() Not found or invalid, Current Cache Count = " + s_CachedCreds.Count);
                }
                return(null);
            }

            if (GlobalLog.IsEnabled)
            {
                GlobalLog.Print("TryCachedCredential() Found a cached Handle = " + cached.Target.ToString());
            }

            return(cached.Target);
        }
Beispiel #5
0
        //
        // The app is calling this method after starting an SSL handshake.
        //
        // ATTN: The thumbPrint must be from inspected and possibly cloned user Cert object or we get a security hole in SslCredKey ctor.
        //
        internal static void CacheCredential(SafeFreeCredentials creds, byte[]?thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy, bool sendTrustList = false)
        {
            Debug.Assert(creds != null, "creds == null");

            if (creds.IsInvalid)
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, $"Refused to cache an Invalid Handle {creds}, Current Cache Count = {s_cachedCreds.Count}");
                }
                return;
            }

            SslCredKey key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy, sendTrustList);

            SafeFreeCredentials?credentials = GetCachedCredential(key);

            DateTime utcNow = DateTime.UtcNow;

            if (credentials == null || credentials.IsClosed || credentials.IsInvalid || credentials.Expiry < utcNow)
            {
                lock (s_cachedCreds)
                {
                    credentials = GetCachedCredential(key);
                    if (credentials == null || credentials.IsClosed || credentials.IsInvalid || credentials.Expiry < utcNow)
                    {
                        SafeCredentialReference?cached = SafeCredentialReference.CreateReference(creds);

                        if (cached == null)
                        {
                            // Means the handle got closed in between, return it back and let caller deal with the issue.
                            return;
                        }

                        s_cachedCreds[key] = cached;
                        if (NetEventSource.Log.IsEnabled())
                        {
                            NetEventSource.Info(null, $"Caching New Handle = {creds}, Current Cache Count = {s_cachedCreds.Count}");
                        }

                        ShrinkCredentialCache();
                    }
                    else
                    {
                        if (NetEventSource.Log.IsEnabled())
                        {
                            NetEventSource.Info(null, $"CacheCredential() (locked retry) Found already cached Handle = {credentials}");
                        }
                    }
                }
            }
            else
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, $"CacheCredential() Ignoring incoming handle = {creds} since found already cached Handle = {credentials}");
                }
            }
Beispiel #6
0
        internal static SafeCredentialReference CreateReference(SafeFreeCredentials target)
        {
            SafeCredentialReference result = new SafeCredentialReference(target);
            if (result.IsInvalid)
            {
                return null;
            }

            return result;
        }
Beispiel #7
0
        internal static SafeCredentialReference CreateReference(SafeFreeCredentials target)
        {
            SafeCredentialReference result = new SafeCredentialReference(target);
            if (result.IsInvalid)
            {
                return null;
            }

            return result;
        }
 internal static SafeFreeCredentials TryCachedCredential(byte[] thumbPrint, SchProtocols allowedProtocols, EncryptionPolicy encryptionPolicy)
 {
     if (s_CachedCreds.Count != 0)
     {
         object obj2 = new SslCredKey(thumbPrint, allowedProtocols, encryptionPolicy);
         SafeCredentialReference reference = s_CachedCreds[obj2] as SafeCredentialReference;
         if (((reference != null) && !reference.IsClosed) && !reference._Target.IsInvalid)
         {
             return(reference._Target);
         }
     }
     return(null);
 }
 internal static void CacheCredential(SafeFreeCredentials creds, byte[] thumbPrint, SchProtocols allowedProtocols, EncryptionPolicy encryptionPolicy)
 {
     if (!creds.IsInvalid)
     {
         object obj2 = new SslCredKey(thumbPrint, allowedProtocols, encryptionPolicy);
         SafeCredentialReference reference = s_CachedCreds[obj2] as SafeCredentialReference;
         if (((reference == null) || reference.IsClosed) || reference._Target.IsInvalid)
         {
             lock (s_CachedCreds)
             {
                 reference = s_CachedCreds[obj2] as SafeCredentialReference;
                 if ((reference == null) || reference.IsClosed)
                 {
                     reference = SafeCredentialReference.CreateReference(creds);
                     if (reference != null)
                     {
                         s_CachedCreds[obj2] = reference;
                         if ((s_CachedCreds.Count % 0x20) == 0)
                         {
                             DictionaryEntry[] array = new DictionaryEntry[s_CachedCreds.Count];
                             s_CachedCreds.CopyTo(array, 0);
                             for (int i = 0; i < array.Length; i++)
                             {
                                 reference = array[i].Value as SafeCredentialReference;
                                 if (reference != null)
                                 {
                                     creds = reference._Target;
                                     reference.Close();
                                     if ((!creds.IsClosed && !creds.IsInvalid) && ((reference = SafeCredentialReference.CreateReference(creds)) != null))
                                     {
                                         s_CachedCreds[array[i].Key] = reference;
                                     }
                                     else
                                     {
                                         s_CachedCreds.Remove(array[i].Key);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
            static void ShrinkCredentialCache()
            {
                //
                // A simplest way of preventing infinite cache grows.
                //
                // Security relief (DoS):
                //     A number of active creds is never greater than a number of _outstanding_
                //     security sessions, i.e. SSL connections.
                //     So we will try to shrink cache to the number of active creds once in a while.
                //
                //    We won't shrink cache in the case when NO new handles are coming to it.
                //
                if ((s_cachedCreds.Count % CheckExpiredModulo) == 0)
                {
                    KeyValuePair <SslCredKey, SafeCredentialReference>[] toRemoveAttempt = s_cachedCreds.ToArray();

                    for (int i = 0; i < toRemoveAttempt.Length; ++i)
                    {
                        SafeCredentialReference?cahced = toRemoveAttempt[i].Value;
                        SafeFreeCredentials?    creds  = cahced.Target;

                        if (creds == null)
                        {
                            s_cachedCreds.TryRemove(toRemoveAttempt[i].Key, out _);
                            continue;
                        }

                        cahced.Dispose();
                        cahced = SafeCredentialReference.CreateReference(creds);
                        if (cahced != null)
                        {
                            s_cachedCreds[toRemoveAttempt[i].Key] = cahced;
                        }
                        else
                        {
                            s_cachedCreds.TryRemove(toRemoveAttempt[i].Key, out _);
                        }
                    }
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(null, $"Scavenged cache, New Cache Count = {s_cachedCreds.Count}");
                    }
                }
            }
Beispiel #11
0
 internal static void CacheCredential(SafeFreeCredentials newHandle)
 {
     try
     {
         SafeCredentialReference reference = SafeCredentialReference.CreateReference(newHandle);
         if (reference != null)
         {
             int index = Interlocked.Increment(ref _Current) & 0x1f;
             reference = Interlocked.Exchange <SafeCredentialReference>(ref _CacheSlots[index], reference);
             if (reference != null)
             {
                 reference.Close();
             }
         }
     }
     catch (Exception exception)
     {
         NclUtilities.IsFatal(exception);
     }
 }
        //
        // Returns null or previously cached cred handle
        //
        // ATTN: The returned handle can be invalid, the callers of InitializeSecurityContext and AcceptSecurityContext
        // must be prepared to execute a backout code if the call fails.
        //
        // Note:thumbPrint is a cryptographicaly strong hash of a certificate
        //
        internal static SafeFreeCredentials TryCachedCredential(byte[] thumbPrint, SchProtocols allowedProtocols, EncryptionPolicy encryptionPolicy)
        {
            if (s_CachedCreds.Count == 0)
            {
                GlobalLog.Print("TryCachedCredential() Not Found, Current Cache Count = " + s_CachedCreds.Count);
                return(null);
            }

            object key = new SslCredKey(thumbPrint, allowedProtocols, encryptionPolicy);

            SafeCredentialReference cached = s_CachedCreds[key] as SafeCredentialReference;

            if (cached == null || cached.IsClosed || cached._Target.IsInvalid)
            {
                GlobalLog.Print("TryCachedCredential() Not Found, Current Cache Count = " + s_CachedCreds.Count);
                return(null);
            }

            GlobalLog.Print("TryCachedCredential() Found a cached Handle = " + cached._Target.ToString());

            return(cached._Target);
        }
Beispiel #13
0
        internal static void CacheCredential(SafeFreeCredentials newHandle)
        {
            try
            {
                SafeCredentialReference?newRef = SafeCredentialReference.CreateReference(newHandle);
                if (newRef == null)
                {
                    return;
                }

                int index = Interlocked.Increment(ref s_current) & MaxCacheSize;

                Interlocked.Exchange(ref s_cacheSlots[index], newRef)?.Dispose();
            }
            catch (Exception e)
            {
                if (NetEventSource.Log.IsEnabled() && !ExceptionCheck.IsFatal(e))
                {
                    NetEventSource.Error(null, $"Attempted to throw: {e}");
                }
            }
        }
Beispiel #14
0
        //
        // The app is calling this method after starting an SSL handshake.
        //
        // ATTN: The thumbPrint must be from inspected and possibly cloned user Cert object or we get a security hole in SslCredKey ctor.
        //
        internal static void CacheCredential(SafeFreeCredentials creds, byte[]?thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy)
        {
            if (creds == null)
            {
                NetEventSource.Fail(null, "creds == null");
            }

            if (creds !.IsInvalid)
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, $"Refused to cache an Invalid Handle {creds}, Current Cache Count = {s_cachedCreds.Count}");
                }
                return;
            }

            var key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy);

            SafeCredentialReference?cached;

            if (!s_cachedCreds.TryGetValue(key, out cached) || cached.IsClosed || cached.Target.IsInvalid)
            {
                lock (s_cachedCreds)
                {
                    if (!s_cachedCreds.TryGetValue(key, out cached) || cached.IsClosed)
                    {
                        cached = SafeCredentialReference.CreateReference(creds);

                        if (cached == null)
                        {
                            // Means the handle got closed in between, return it back and let caller deal with the issue.
                            return;
                        }

                        s_cachedCreds[key] = cached;
                        if (NetEventSource.Log.IsEnabled())
                        {
                            NetEventSource.Info(null, $"Caching New Handle = {creds}, Current Cache Count = {s_cachedCreds.Count}");
                        }

                        //
                        // A simplest way of preventing infinite cache grows.
                        //
                        // Security relief (DoS):
                        //     A number of active creds is never greater than a number of _outstanding_
                        //     security sessions, i.e. SSL connections.
                        //     So we will try to shrink cache to the number of active creds once in a while.
                        //
                        //    We won't shrink cache in the case when NO new handles are coming to it.
                        //
                        if ((s_cachedCreds.Count % CheckExpiredModulo) == 0)
                        {
                            KeyValuePair <SslCredKey, SafeCredentialReference>[] toRemoveAttempt = s_cachedCreds.ToArray();

                            for (int i = 0; i < toRemoveAttempt.Length; ++i)
                            {
                                cached = toRemoveAttempt[i].Value;

                                if (cached != null)
                                {
                                    creds = cached.Target;
                                    cached.Dispose();

                                    if (!creds.IsClosed && !creds.IsInvalid && (cached = SafeCredentialReference.CreateReference(creds)) != null)
                                    {
                                        s_cachedCreds[toRemoveAttempt[i].Key] = cached;
                                    }
                                    else
                                    {
                                        s_cachedCreds.TryRemove(toRemoveAttempt[i].Key, out cached);
                                    }
                                }
                            }
                            if (NetEventSource.Log.IsEnabled())
                            {
                                NetEventSource.Info(null, $"Scavenged cache, New Cache Count = {s_cachedCreds.Count}");
                            }
                        }
                    }
                    else if (NetEventSource.Log.IsEnabled())
                    {
                        if (NetEventSource.Log.IsEnabled())
                        {
                            NetEventSource.Info(null, $"CacheCredential() (locked retry) Found already cached Handle = {cached.Target}");
                        }
                    }
                }
            }
            else if (NetEventSource.Log.IsEnabled())
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, $"CacheCredential() Ignoring incoming handle = {creds} since found already cached Handle = {cached.Target}");
                }
            }
        }
        //
        // The app is calling this method after starting an SSL handshake.
        //
        // ATTN: The thumbPrint must be from inspected and possbly cloned user Cert object or we get a security hole in SslCredKey ctor.
        //
        internal static void CacheCredential(SafeFreeCredentials creds, byte[] thumbPrint, SchProtocols allowedProtocols, EncryptionPolicy encryptionPolicy)
        {
            GlobalLog.Assert(creds != null, "CacheCredential|creds == null");
            if (creds.IsInvalid)
            {
                GlobalLog.Print("CacheCredential() Refused to cache an Invalid Handle = " + creds.ToString() + ", Current Cache Count = " + s_CachedCreds.Count);
                return;
            }

            object key = new SslCredKey(thumbPrint, allowedProtocols, encryptionPolicy);

            SafeCredentialReference cached = s_CachedCreds[key] as SafeCredentialReference;

            if (cached == null || cached.IsClosed || cached._Target.IsInvalid)
            {
                lock (s_CachedCreds)
                {
                    cached = s_CachedCreds[key] as SafeCredentialReference;

                    if (cached == null || cached.IsClosed)
                    {
                        cached = SafeCredentialReference.CreateReference(creds);

                        if (cached == null)
                        {
                            // Means the handle got closed in between, return it back and let caller deal with the issue.
                            return;
                        }

                        s_CachedCreds[key] = cached;
                        GlobalLog.Print("CacheCredential() Caching New Handle = " + creds.ToString() + ", Current Cache Count = " + s_CachedCreds.Count);

                        //
                        // A simplest way of preventing infinite cache grows.
                        //
                        // Security relief (DoS):
                        //     A number of active creds is never greater than a number of _outstanding_
                        //     security sessions, i.e. ssl connections.
                        //     So we will try to shrink cache to the number of active creds once in a while.
                        //
                        //    Just to make clear we won't shrink cache in the case when NO new handles are coming to it.
                        //
                        if ((s_CachedCreds.Count % c_CheckExpiredModulo) == 0)
                        {
                            DictionaryEntry[] toRemoveAttempt = new DictionaryEntry[s_CachedCreds.Count];
                            s_CachedCreds.CopyTo(toRemoveAttempt, 0);

                            for (int i = 0; i < toRemoveAttempt.Length; ++i)
                            {
                                cached = toRemoveAttempt[i].Value as SafeCredentialReference;

                                if (cached != null)
                                {
                                    creds = cached._Target;
                                    cached.Close();

                                    if (!creds.IsClosed && !creds.IsInvalid && (cached = SafeCredentialReference.CreateReference(creds)) != null)
                                    {
                                        s_CachedCreds[toRemoveAttempt[i].Key] = cached;
                                    }
                                    else
                                    {
                                        s_CachedCreds.Remove(toRemoveAttempt[i].Key);
                                    }
                                }
                            }
                            GlobalLog.Print("Scavenged cache, New Cache Count = " + s_CachedCreds.Count);
                        }
                    }
                    else
                    {
                        GlobalLog.Print("CacheCredential() (locked retry) Found already cached Handle = " + cached._Target.ToString());
                    }
                }
            }
            else
            {
                GlobalLog.Print("CacheCredential() Ignoring incoming handle = " + creds.ToString() + " since found already cached Handle = " + cached._Target.ToString());
            }
        }