Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / 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
- MetadataException.cs
- PersistChildrenAttribute.cs
- GridViewCommandEventArgs.cs
- ErrorFormatterPage.cs
- _DigestClient.cs
- CollectionViewGroupInternal.cs
- SiteMembershipCondition.cs
- CompilerResults.cs
- DetailsViewPageEventArgs.cs
- ProfilePropertyMetadata.cs
- StylusButtonEventArgs.cs
- TransformDescriptor.cs
- MD5CryptoServiceProvider.cs
- Accessible.cs
- ArraySegment.cs
- TabOrder.cs
- xml.cs
- SimpleExpression.cs
- PathNode.cs
- BufferModeSettings.cs
- MetabaseServerConfig.cs
- StaticFileHandler.cs
- DataGridLinkButton.cs
- AttachedPropertyBrowsableForTypeAttribute.cs
- PerformanceCounterScope.cs
- DrawingState.cs
- FileNotFoundException.cs
- FormViewInsertedEventArgs.cs
- ModifierKeysValueSerializer.cs
- XmlILIndex.cs
- NativeObjectSecurity.cs
- MatrixStack.cs
- LicenseException.cs
- DataGridViewRowCollection.cs
- QilXmlReader.cs
- updatecommandorderer.cs
- ValidatorCompatibilityHelper.cs
- SiteMapNodeItem.cs
- TemporaryBitmapFile.cs
- DataKeyArray.cs
- ColumnPropertiesGroup.cs
- AmbientEnvironment.cs
- DataSourceExpression.cs
- ExpressionBuilder.cs
- StreamAsIStream.cs
- RSAProtectedConfigurationProvider.cs
- CompiledIdentityConstraint.cs
- XPathDescendantIterator.cs
- TriggerActionCollection.cs
- LabelDesigner.cs
- SerializerWriterEventHandlers.cs
- CaseInsensitiveComparer.cs
- PassportIdentity.cs
- ServicePoint.cs
- TrackingMemoryStream.cs
- GradientStop.cs
- MimeBasePart.cs
- CatalogZoneBase.cs
- Cursor.cs
- UserPreferenceChangedEventArgs.cs
- DetailsViewInsertedEventArgs.cs
- PathGradientBrush.cs
- DbCommandTree.cs
- ReferenceEqualityComparer.cs
- DesigntimeLicenseContextSerializer.cs
- Stackframe.cs
- StrongNamePublicKeyBlob.cs
- FloatMinMaxAggregationOperator.cs
- PreviewPrintController.cs
- WebExceptionStatus.cs
- RsaSecurityTokenAuthenticator.cs
- MimeFormImporter.cs
- ComponentDesigner.cs
- EventLogger.cs
- InstanceData.cs
- DivideByZeroException.cs
- BitmapEffectGroup.cs
- _NegotiateClient.cs
- SourceFileBuildProvider.cs
- XsltException.cs
- XPathNodeInfoAtom.cs
- DataReceivedEventArgs.cs
- PartitionResolver.cs
- XmlNamespaceManager.cs
- BaseAutoFormat.cs
- ObjectViewFactory.cs
- ToolBarPanel.cs
- DuplicateWaitObjectException.cs
- DateTimeFormat.cs
- RoleService.cs
- UnionExpr.cs
- UriExt.cs
- ContextMenuService.cs
- RightsManagementPermission.cs
- EncryptedXml.cs
- SecurityContext.cs
- UnknownBitmapDecoder.cs
- columnmapfactory.cs
- ProjectionCamera.cs
- PtsHost.cs