private static DbConnectionPoolIdentity GetCurrentNative() { DbConnectionPoolIdentity current; using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) { IntPtr token = identity.AccessToken.DangerousGetHandle(); SecurityIdentifier user = identity.User; bool isNetwork = user.IsWellKnown(WellKnownSidType.NetworkSid); string sidString = user.Value; // Win32NativeMethods.IsTokenRestricted will raise exception if the native call fails bool isRestricted = Win32NativeMethods.IsTokenRestrictedWrapper(token); var lastIdentity = s_lastIdentity; if ((lastIdentity != null) && (lastIdentity._sidString == sidString) && (lastIdentity._isRestricted == isRestricted) && (lastIdentity._isNetwork == isNetwork)) { current = lastIdentity; } else { current = new DbConnectionPoolIdentity(sidString, isRestricted, isNetwork); } } s_lastIdentity = current; return(current); }
override public bool Equals(object value) { bool result = ((this == NoIdentity) || (this == value)); if (!result && (null != value)) { DbConnectionPoolIdentity that = ((DbConnectionPoolIdentity)value); result = ((this._sidString == that._sidString) && (this._isRestricted == that._isRestricted) && (this._isNetwork == that._isNetwork)); } return(result); }
internal DbConnectionPool GetConnectionPool(DbConnectionFactory connectionFactory) { // When this method returns null it indicates that the connection // factory should not use pooling. // We don't support connection pooling on Win9x; // PoolGroupOptions will only be null when we're not supposed to pool // connections. DbConnectionPool pool = null; if (null != _poolGroupOptions) { DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.NoIdentity; if (_poolGroupOptions.PoolByIdentity) { // if we're pooling by identity (because integrated security is // being used for these connections) then we need to go out and // search for the connectionPool that matches the current identity. currentIdentity = DbConnectionPoolIdentity.GetCurrent(); // If the current token is restricted in some way, then we must // not attempt to pool these connections. if (currentIdentity.IsRestricted) { currentIdentity = null; } } if (null != currentIdentity) { if (!_poolCollection.TryGetValue(currentIdentity, out pool)) // find the pool { lock (this) { // Did someone already add it to the list? if (!_poolCollection.TryGetValue(currentIdentity, out pool)) { DbConnectionPoolProviderInfo connectionPoolProviderInfo = connectionFactory.CreateConnectionPoolProviderInfo(this.ConnectionOptions); DbConnectionPool newPool = new DbConnectionPool(connectionFactory, this, currentIdentity, connectionPoolProviderInfo); if (MarkPoolGroupAsActive()) { // If we get here, we know for certain that we there isn't // a pool that matches the current identity, so we have to // add the optimistically created one newPool.Startup(); // must start pool before usage bool addResult = _poolCollection.TryAdd(currentIdentity, newPool); Debug.Assert(addResult, "No other pool with current identity should exist at this point"); SqlClientEventSource.Log.EnterActiveConnectionPool(); pool = newPool; } else { // else pool entry has been disabled so don't create new pools Debug.Assert(PoolGroupStateDisabled == _state, "state should be disabled"); // don't need to call connectionFactory.QueuePoolForRelease(newPool) because // pool callbacks were delayed and no risk of connections being created newPool.Shutdown(); } } else { // else found an existing pool to use instead Debug.Assert(PoolGroupStateActive == _state, "state should be active since a pool exists and lock holds"); } } } // the found pool could be in any state } } if (null == pool) { lock (this) { // keep the pool entry state active when not pooling MarkPoolGroupAsActive(); } } return(pool); }
static internal DbConnectionPoolIdentity GetCurrent() { // DEVNOTE: GetTokenInfo and EqualSID do not work on 9x. WindowsIdentity does not // work either on 9x. In fact, after checking with native there is no way // to validate the user on 9x, so simply don't. It is a known issue in // native, and we will handle this the same way. if (!ADP.IsWindowsNT) { return(NoIdentity); } WindowsIdentity identity = GetCurrentWindowsIdentity(); IntPtr token = GetWindowsIdentityToken(identity); // Free'd by WindowsIdentity. uint bufferLength = 2048; // Suggested default given by Greg Fee. uint lengthNeeded = 0; IntPtr tokenStruct = IntPtr.Zero; IntPtr SID; IntPtr sidStringBuffer = IntPtr.Zero; bool isNetwork; // Win32NativeMethods.IsTokenRestricted will raise exception if the native call fails bool isRestricted = Win32NativeMethods.IsTokenRestrictedWrapper(token); DbConnectionPoolIdentity current = null; RuntimeHelpers.PrepareConstrainedRegions(); try { if (!UnsafeNativeMethods.CheckTokenMembership(token, NetworkSid, out isNetwork)) { // will always fail with 0x8007051D if token is not an impersonation token IntegratedSecurityError(Win32_CheckTokenMembership); } RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { // allocating memory and assigning to tokenStruct must happen tokenStruct = SafeNativeMethods.LocalAlloc(DbBuffer.LMEM_FIXED, (IntPtr)bufferLength); } if (IntPtr.Zero == tokenStruct) { throw new OutOfMemoryException(); } if (!UnsafeNativeMethods.GetTokenInformation(token, 1, tokenStruct, bufferLength, ref lengthNeeded)) { if (lengthNeeded > bufferLength) { bufferLength = lengthNeeded; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { // freeing token struct and setting tokenstruct to null must happen together // allocating memory and assigning to tokenStruct must happen SafeNativeMethods.LocalFree(tokenStruct); tokenStruct = IntPtr.Zero; // protect against LocalAlloc throwing an exception tokenStruct = SafeNativeMethods.LocalAlloc(DbBuffer.LMEM_FIXED, (IntPtr)bufferLength); } if (IntPtr.Zero == tokenStruct) { throw new OutOfMemoryException(); } if (!UnsafeNativeMethods.GetTokenInformation(token, 1, tokenStruct, bufferLength, ref lengthNeeded)) { IntegratedSecurityError(Win32_GetTokenInformation_1); } } else { IntegratedSecurityError(Win32_GetTokenInformation_2); } } identity.Dispose(); // Keep identity variable alive until after GetTokenInformation calls. SID = Marshal.ReadIntPtr(tokenStruct, 0); if (!UnsafeNativeMethods.ConvertSidToStringSidW(SID, out sidStringBuffer)) { IntegratedSecurityError(Win32_ConvertSidToStringSidW); } if (IntPtr.Zero == sidStringBuffer) { throw ADP.InternalError(ADP.InternalErrorCode.ConvertSidToStringSidWReturnedNull); } string sidString = Marshal.PtrToStringUni(sidStringBuffer); var lastIdentity = _lastIdentity; if ((lastIdentity != null) && (lastIdentity._sidString == sidString) && (lastIdentity._isRestricted == isRestricted) && (lastIdentity._isNetwork == isNetwork)) { current = lastIdentity; } else { current = new DbConnectionPoolIdentity(sidString, isRestricted, isNetwork); } } finally { // Marshal.FreeHGlobal does not have a ReliabilityContract if (IntPtr.Zero != tokenStruct) { SafeNativeMethods.LocalFree(tokenStruct); tokenStruct = IntPtr.Zero; } if (IntPtr.Zero != sidStringBuffer) { SafeNativeMethods.LocalFree(sidStringBuffer); sidStringBuffer = IntPtr.Zero; } } _lastIdentity = current; return(current); }