Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Net / System / Net / _SslSessionsCache.cs / 1 / _SslSessionsCache.cs
/*++ Copyright (c) Microsoft Corporation Module Name: _SslSessionsCache.cs Abstract: The file implements SSL session caching mechanism based on a static table of SSL credentials Author: Alexei Vopilov 20-Jul-2004 Revision History: --*/ namespace System.Net.Security { using System.Net; using System.Security.Cryptography.X509Certificates; using System.Collections; internal static class SslSessionsCache { private const int c_CheckExpiredModulo = 32; private static Hashtable s_CachedCreds = new Hashtable(32); // // Uses cryptographically strong certificate thumbprint comparison // private struct SslCredKey { private static readonly byte[] s_EmptyArray = new byte[0]; private byte[] _CertThumbPrint; private SchProtocols _AllowedProtocols; private int _HashCode; // // SECURITY: X509Certificate.GetCertHash() is virtual hence before going here // the caller of this ctor has to ensure that a user cert object was inspected and // optionally cloned. // internal SslCredKey(byte[] thumbPrint, SchProtocols allowedProtocols) { _CertThumbPrint = thumbPrint == null? s_EmptyArray: thumbPrint; _HashCode = 0; if (thumbPrint != null) { _HashCode ^= _CertThumbPrint[0]; if (1 < _CertThumbPrint.Length) _HashCode ^= (_CertThumbPrint[1] << 8); if (2 < _CertThumbPrint.Length) _HashCode ^= (_CertThumbPrint[2] << 16); if (3 < _CertThumbPrint.Length) _HashCode ^= (_CertThumbPrint[3] << 24); } _AllowedProtocols = allowedProtocols; _HashCode ^= (int)_AllowedProtocols; } // public override int GetHashCode() { return _HashCode; } // public static bool operator == (SslCredKey sslCredKey1, SslCredKey sslCredKey2) { if ((object)sslCredKey1 == (object)sslCredKey2) { return true; } if ((object)sslCredKey1 == null || (object)sslCredKey2 == null) { return false; } return sslCredKey1.Equals(sslCredKey2); } // public static bool operator != (SslCredKey sslCredKey1, SslCredKey sslCredKey2) { if ((object)sslCredKey1 == (object)sslCredKey2) { return false; } if ((object)sslCredKey1 == null || (object)sslCredKey2 == null) { return true; } return !sslCredKey1.Equals(sslCredKey2); } // public override bool Equals(Object y) { SslCredKey she = (SslCredKey)y; if (_CertThumbPrint.Length != she._CertThumbPrint.Length) return false; if (_HashCode != she._HashCode) return false; for (int i = 0; i < _CertThumbPrint.Length; ++i) if (_CertThumbPrint[i] != she._CertThumbPrint[i]) return false; return true; } } // // 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) { if (s_CachedCreds.Count == 0) { GlobalLog.Print("TryCachedCredential() Not Found, Current Cache Count = " + s_CachedCreds.Count); return null; } object key = new SslCredKey(thumbPrint, allowedProtocols); 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; } // // 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) { 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); 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()); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /*++ Copyright (c) Microsoft Corporation Module Name: _SslSessionsCache.cs Abstract: The file implements SSL session caching mechanism based on a static table of SSL credentials Author: Alexei Vopilov 20-Jul-2004 Revision History: --*/ namespace System.Net.Security { using System.Net; using System.Security.Cryptography.X509Certificates; using System.Collections; internal static class SslSessionsCache { private const int c_CheckExpiredModulo = 32; private static Hashtable s_CachedCreds = new Hashtable(32); // // Uses cryptographically strong certificate thumbprint comparison // private struct SslCredKey { private static readonly byte[] s_EmptyArray = new byte[0]; private byte[] _CertThumbPrint; private SchProtocols _AllowedProtocols; private int _HashCode; // // SECURITY: X509Certificate.GetCertHash() is virtual hence before going here // the caller of this ctor has to ensure that a user cert object was inspected and // optionally cloned. // internal SslCredKey(byte[] thumbPrint, SchProtocols allowedProtocols) { _CertThumbPrint = thumbPrint == null? s_EmptyArray: thumbPrint; _HashCode = 0; if (thumbPrint != null) { _HashCode ^= _CertThumbPrint[0]; if (1 < _CertThumbPrint.Length) _HashCode ^= (_CertThumbPrint[1] << 8); if (2 < _CertThumbPrint.Length) _HashCode ^= (_CertThumbPrint[2] << 16); if (3 < _CertThumbPrint.Length) _HashCode ^= (_CertThumbPrint[3] << 24); } _AllowedProtocols = allowedProtocols; _HashCode ^= (int)_AllowedProtocols; } // public override int GetHashCode() { return _HashCode; } // public static bool operator == (SslCredKey sslCredKey1, SslCredKey sslCredKey2) { if ((object)sslCredKey1 == (object)sslCredKey2) { return true; } if ((object)sslCredKey1 == null || (object)sslCredKey2 == null) { return false; } return sslCredKey1.Equals(sslCredKey2); } // public static bool operator != (SslCredKey sslCredKey1, SslCredKey sslCredKey2) { if ((object)sslCredKey1 == (object)sslCredKey2) { return false; } if ((object)sslCredKey1 == null || (object)sslCredKey2 == null) { return true; } return !sslCredKey1.Equals(sslCredKey2); } // public override bool Equals(Object y) { SslCredKey she = (SslCredKey)y; if (_CertThumbPrint.Length != she._CertThumbPrint.Length) return false; if (_HashCode != she._HashCode) return false; for (int i = 0; i < _CertThumbPrint.Length; ++i) if (_CertThumbPrint[i] != she._CertThumbPrint[i]) return false; return true; } } // // 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) { if (s_CachedCreds.Count == 0) { GlobalLog.Print("TryCachedCredential() Not Found, Current Cache Count = " + s_CachedCreds.Count); return null; } object key = new SslCredKey(thumbPrint, allowedProtocols); 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; } // // 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) { 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); 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()); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Size.cs
- RandomDelaySendsAsyncResult.cs
- SiteMapNode.cs
- Constants.cs
- HttpCookiesSection.cs
- x509store.cs
- CustomValidator.cs
- TreeNodeCollectionEditor.cs
- WindowsMenu.cs
- CompiledELinqQueryState.cs
- ToolStripAdornerWindowService.cs
- ToolStripSplitStackLayout.cs
- EditorResources.cs
- DefaultAssemblyResolver.cs
- WebCategoryAttribute.cs
- LogWriteRestartAreaState.cs
- Int16Storage.cs
- BinaryObjectReader.cs
- Models.cs
- CleanUpVirtualizedItemEventArgs.cs
- SplitterPanel.cs
- SoapObjectWriter.cs
- AsymmetricKeyExchangeDeformatter.cs
- TextBoxAutomationPeer.cs
- IriParsingElement.cs
- TextRangeEditLists.cs
- AnnotationDocumentPaginator.cs
- IERequestCache.cs
- XmlIgnoreAttribute.cs
- SqlCacheDependency.cs
- WindowsRegion.cs
- wmiprovider.cs
- DefaultTextStore.cs
- EncoderBestFitFallback.cs
- SelectedGridItemChangedEvent.cs
- DataGridViewSelectedCellsAccessibleObject.cs
- ImportCatalogPart.cs
- CreateUserWizard.cs
- SchemaTypeEmitter.cs
- InArgument.cs
- GraphicsState.cs
- DocumentViewerHelper.cs
- FileSecurity.cs
- RotateTransform.cs
- TableStyle.cs
- StatusStrip.cs
- PeerEndPoint.cs
- ManagementOperationWatcher.cs
- PageVisual.cs
- UTF8Encoding.cs
- MultiBinding.cs
- CurrentChangingEventArgs.cs
- UIElementHelper.cs
- Hashtable.cs
- UnmanagedMarshal.cs
- ConsoleTraceListener.cs
- DrawItemEvent.cs
- HttpRuntimeSection.cs
- ElementHostAutomationPeer.cs
- ExpressionBindingCollection.cs
- PrimitiveCodeDomSerializer.cs
- PersonalizationStateInfoCollection.cs
- ExpandSegment.cs
- TransformGroup.cs
- ProofTokenCryptoHandle.cs
- SelectionItemPattern.cs
- XmlPreloadedResolver.cs
- ListViewGroupItemCollection.cs
- CommittableTransaction.cs
- _SafeNetHandles.cs
- keycontainerpermission.cs
- ContentType.cs
- ScriptingAuthenticationServiceSection.cs
- IntSecurity.cs
- XmlDigitalSignatureProcessor.cs
- RijndaelManagedTransform.cs
- CodeDirectionExpression.cs
- EncodingInfo.cs
- Paragraph.cs
- SystemWebCachingSectionGroup.cs
- TextTreeInsertElementUndoUnit.cs
- FieldNameLookup.cs
- TextBoxAutomationPeer.cs
- HWStack.cs
- ToolStripSeparator.cs
- AutoResetEvent.cs
- ToolStripDropDown.cs
- ViewEvent.cs
- RTLAwareMessageBox.cs
- BaseTreeIterator.cs
- AutoGeneratedField.cs
- DbgUtil.cs
- AccessKeyManager.cs
- DesignerSerializationVisibilityAttribute.cs
- TimersDescriptionAttribute.cs
- DecoratedNameAttribute.cs
- UpdateCommand.cs
- DictionaryEditChange.cs
- Int64Converter.cs
- MatrixValueSerializer.cs