Skip to content

Commit 830f5f8

Browse files
committed
Plumbs all the SSPI changes through the SqlConnection
1 parent aaba34f commit 830f5f8

File tree

11 files changed

+80
-32
lines changed

11 files changed

+80
-32
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ private static readonly Dictionary<string, SqlColumnEncryptionKeyStoreProvider>
9191
private IReadOnlyDictionary<string, SqlColumnEncryptionKeyStoreProvider> _customColumnEncryptionKeyStoreProviders;
9292

9393
private Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> _accessTokenCallback;
94+
private SspiContextProvider _sspiContextProvider;
9495

9596
internal bool HasColumnEncryptionKeyStoreProvidersRegistered =>
9697
_customColumnEncryptionKeyStoreProviders is not null && _customColumnEncryptionKeyStoreProviders.Count > 0;
@@ -650,7 +651,7 @@ public override string ConnectionString
650651
CheckAndThrowOnInvalidCombinationOfConnectionOptionAndAccessTokenCallback(connectionOptions);
651652
}
652653
}
653-
ConnectionString_Set(new SqlConnectionPoolKey(value, _credential, _accessToken, _accessTokenCallback));
654+
ConnectionString_Set(new SqlConnectionPoolKey(value, _credential, _accessToken, _accessTokenCallback, _sspiContextProvider));
654655
_connectionString = value; // Change _connectionString value only after value is validated
655656
CacheConnectionStringProperties();
656657
}
@@ -710,7 +711,7 @@ public string AccessToken
710711
}
711712

712713
// Need to call ConnectionString_Set to do proper pool group check
713-
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, credential: _credential, accessToken: value, accessTokenCallback: null));
714+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, credential: _credential, accessToken: value, accessTokenCallback: null, sspiContextProvider: null));
714715
_accessToken = value;
715716
}
716717
}
@@ -733,11 +734,21 @@ public Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticati
733734
CheckAndThrowOnInvalidCombinationOfConnectionOptionAndAccessTokenCallback((SqlConnectionString)ConnectionOptions);
734735
}
735736

736-
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, credential: _credential, accessToken: null, accessTokenCallback: value));
737+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, credential: _credential, accessToken: null, accessTokenCallback: value, sspiContextProvider: null));
737738
_accessTokenCallback = value;
738739
}
739740
}
740741

742+
internal SspiContextProvider SspiContextProvider
743+
{
744+
get { return _sspiContextProvider; }
745+
set
746+
{
747+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, credential: _credential, accessToken: null, accessTokenCallback: null, sspiContextProvider: value));
748+
_sspiContextProvider = value;
749+
}
750+
}
751+
741752
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/Database/*' />
742753
[ResDescription(StringsHelper.ResourceNames.SqlConnection_Database)]
743754
[ResCategory(StringsHelper.ResourceNames.SqlConnection_DataSource)]
@@ -1035,7 +1046,7 @@ public SqlCredential Credential
10351046
_credential = value;
10361047

10371048
// Need to call ConnectionString_Set to do proper pool group check
1038-
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, accessToken: _accessToken, accessTokenCallback: _accessTokenCallback));
1049+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, accessToken: _accessToken, accessTokenCallback: _accessTokenCallback, sspiContextProvider: null));
10391050
}
10401051
}
10411052

@@ -2265,7 +2276,7 @@ public static void ChangePassword(string connectionString, string newPassword)
22652276
throw ADP.InvalidArgumentLength(nameof(newPassword), TdsEnums.MAXLEN_NEWPASSWORD);
22662277
}
22672278

2268-
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential: null, accessToken: null, accessTokenCallback: null);
2279+
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential: null, accessToken: null, accessTokenCallback: null, sspiContextProvider: null);
22692280

22702281
SqlConnectionString connectionOptions = SqlConnectionFactory.Instance.FindSqlConnectionOptions(key);
22712282
if (connectionOptions.IntegratedSecurity)
@@ -2314,7 +2325,7 @@ public static void ChangePassword(string connectionString, SqlCredential credent
23142325
throw ADP.InvalidArgumentLength(nameof(newSecurePassword), TdsEnums.MAXLEN_NEWPASSWORD);
23152326
}
23162327

2317-
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null);
2328+
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null, sspiContextProvider: null);
23182329

23192330
SqlConnectionString connectionOptions = SqlConnectionFactory.Instance.FindSqlConnectionOptions(key);
23202331

@@ -2352,7 +2363,7 @@ private static void ChangePassword(string connectionString, SqlConnectionString
23522363
{
23532364
con?.Dispose();
23542365
}
2355-
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null);
2366+
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null, sspiContextProvider: null);
23562367

23572368
SqlConnectionFactory.Instance.ClearPool(key);
23582369
}

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ internal sealed class SqlInternalConnectionTds : SqlInternalConnection, IDisposa
135135
SqlFedAuthToken _fedAuthToken = null;
136136
internal byte[] _accessTokenInBytes;
137137
internal readonly Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> _accessTokenCallback;
138+
internal readonly SspiContextProvider _sspiContextProvider;
138139

139140
private readonly ActiveDirectoryAuthenticationTimeoutRetryHelper _activeDirectoryAuthTimeoutRetryHelper;
140141

@@ -460,8 +461,8 @@ internal SqlInternalConnectionTds(
460461
bool applyTransientFaultHandling = false,
461462
string accessToken = null,
462463
IDbConnectionPool pool = null,
463-
Func<SqlAuthenticationParameters, CancellationToken,
464-
Task<SqlAuthenticationToken>> accessTokenCallback = null) : base(connectionOptions)
464+
Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> accessTokenCallback = null,
465+
SspiContextProvider sspiContextProvider = null) : base(connectionOptions)
465466
{
466467
#if DEBUG
467468
if (reconnectSessionData != null)
@@ -514,6 +515,7 @@ internal SqlInternalConnectionTds(
514515
}
515516

516517
_accessTokenCallback = accessTokenCallback;
518+
_sspiContextProvider = sspiContextProvider;
517519

518520
_activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper();
519521

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ internal void Connect(ServerInfo serverInfo,
409409
// AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server
410410
if (integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated)
411411
{
412-
_authenticationProvider = _physicalStateObj.CreateSspiContextProvider();
412+
_authenticationProvider = Connection._sspiContextProvider ?? _physicalStateObj.CreateSspiContextProvider();
413413
SqlClientEventSource.Log.TryTraceEvent("TdsParser.Connect | SEC | SSPI or Active Directory Authentication Library loaded for SQL Server based integrated authentication");
414414
}
415415

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ private static readonly Dictionary<string, SqlColumnEncryptionKeyStoreProvider>
8989

9090
private Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> _accessTokenCallback;
9191

92+
private SspiContextProvider _sspiContextProvider;
93+
9294
internal bool HasColumnEncryptionKeyStoreProvidersRegistered =>
9395
_customColumnEncryptionKeyStoreProviders is not null && _customColumnEncryptionKeyStoreProviders.Count > 0;
9496

@@ -577,6 +579,16 @@ internal int ConnectRetryInterval
577579
get => ((SqlConnectionString)ConnectionOptions).ConnectRetryInterval;
578580
}
579581

582+
internal SspiContextProvider SspiContextProvider
583+
{
584+
get { return _sspiContextProvider; }
585+
set
586+
{
587+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, accessToken: null, accessTokenCallback: null, sspiContextProvider: value));
588+
_sspiContextProvider = value;
589+
}
590+
}
591+
580592
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/ConnectionString/*' />
581593
[DefaultValue("")]
582594
#pragma warning disable 618 // ignore obsolete warning about RecommendedAsConfigurable to use SettingsBindableAttribute
@@ -645,7 +657,7 @@ public override string ConnectionString
645657
CheckAndThrowOnInvalidCombinationOfConnectionOptionAndAccessTokenCallback(connectionOptions);
646658
}
647659
}
648-
ConnectionString_Set(new SqlConnectionPoolKey(value, _credential, _accessToken, _accessTokenCallback));
660+
ConnectionString_Set(new SqlConnectionPoolKey(value, _credential, _accessToken, _accessTokenCallback, _sspiContextProvider));
649661
_connectionString = value; // Change _connectionString value only after value is validated
650662
CacheConnectionStringProperties();
651663
}
@@ -705,7 +717,7 @@ public string AccessToken
705717

706718
_accessToken = value;
707719
// Need to call ConnectionString_Set to do proper pool group check
708-
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, _accessToken, null));
720+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, _accessToken, null, sspiContextProvider: null));
709721
}
710722
}
711723

@@ -727,7 +739,7 @@ public Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticati
727739
CheckAndThrowOnInvalidCombinationOfConnectionOptionAndAccessTokenCallback((SqlConnectionString)ConnectionOptions);
728740
}
729741

730-
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, null, value));
742+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, null, value, sspiContextProvider: null));
731743
_accessTokenCallback = value;
732744
}
733745
}
@@ -1029,7 +1041,7 @@ public SqlCredential Credential
10291041
_credential = value;
10301042

10311043
// Need to call ConnectionString_Set to do proper pool group check
1032-
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, accessToken: _accessToken, accessTokenCallback: _accessTokenCallback));
1044+
ConnectionString_Set(new SqlConnectionPoolKey(_connectionString, _credential, _accessToken, _accessTokenCallback, sspiContextProvider: null));
10331045
}
10341046
}
10351047

@@ -2184,7 +2196,7 @@ public static void ChangePassword(string connectionString, string newPassword)
21842196
throw ADP.InvalidArgumentLength(nameof(newPassword), TdsEnums.MAXLEN_NEWPASSWORD);
21852197
}
21862198

2187-
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential: null, accessToken: null, accessTokenCallback: null);
2199+
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential: null, accessToken: null, accessTokenCallback: null, sspiContextProvider: null);
21882200

21892201
SqlConnectionString connectionOptions = SqlConnectionFactory.Instance.FindSqlConnectionOptions(key);
21902202
if (connectionOptions.IntegratedSecurity || connectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated)
@@ -2236,7 +2248,7 @@ public static void ChangePassword(string connectionString, SqlCredential credent
22362248
throw ADP.InvalidArgumentLength(nameof(newSecurePassword), TdsEnums.MAXLEN_NEWPASSWORD);
22372249
}
22382250

2239-
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null);
2251+
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null, sspiContextProvider: null);
22402252

22412253
SqlConnectionString connectionOptions = SqlConnectionFactory.Instance.FindSqlConnectionOptions(key);
22422254

@@ -2277,7 +2289,7 @@ private static void ChangePassword(string connectionString, SqlConnectionString
22772289
{
22782290
con?.Dispose();
22792291
}
2280-
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null);
2292+
SqlConnectionPoolKey key = new SqlConnectionPoolKey(connectionString, credential, accessToken: null, accessTokenCallback: null, sspiContextProvider: null);
22812293

22822294
SqlConnectionFactory.Instance.ClearPool(key);
22832295
}

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ internal sealed class SqlInternalConnectionTds : SqlInternalConnection, IDisposa
136136
SqlFedAuthToken _fedAuthToken = null;
137137
internal byte[] _accessTokenInBytes;
138138
internal readonly Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> _accessTokenCallback;
139+
internal readonly SspiContextProvider _sspiContextProvider;
139140

140141
private readonly ActiveDirectoryAuthenticationTimeoutRetryHelper _activeDirectoryAuthTimeoutRetryHelper;
141142

@@ -472,8 +473,8 @@ internal SqlInternalConnectionTds(
472473
bool applyTransientFaultHandling = false,
473474
string accessToken = null,
474475
IDbConnectionPool pool = null,
475-
Func<SqlAuthenticationParameters, CancellationToken,
476-
Task<SqlAuthenticationToken>> accessTokenCallback = null)
476+
Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> accessTokenCallback = null,
477+
SspiContextProvider sspiContextProvider = null)
477478
: base(connectionOptions)
478479
{
479480
#if DEBUG
@@ -525,6 +526,7 @@ internal SqlInternalConnectionTds(
525526
}
526527

527528
_accessTokenCallback = accessTokenCallback;
529+
_sspiContextProvider = sspiContextProvider;
528530

529531
_activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper();
530532

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ internal void Connect(ServerInfo serverInfo,
411411
// AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server
412412
if (integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated)
413413
{
414-
_authenticationProvider = _physicalStateObj.CreateSspiContextProvider();
414+
_authenticationProvider = Connection._sspiContextProvider ?? _physicalStateObj.CreateSspiContextProvider();
415415

416416
if (!string.IsNullOrEmpty(serverInfo.ServerSPN))
417417
{

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/SqlConnectionPoolKey.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ internal class SqlConnectionPoolKey : DbConnectionPoolKey
1818
private readonly SqlCredential _credential;
1919
private readonly string _accessToken;
2020
private Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> _accessTokenCallback;
21+
private SspiContextProvider _sspiContextProvider;
2122

2223
internal SqlCredential Credential => _credential;
2324
internal string AccessToken => _accessToken;
2425
internal Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> AccessTokenCallback => _accessTokenCallback;
26+
internal SspiContextProvider SspiContextProvider => _sspiContextProvider;
2527

2628
internal override string ConnectionString
2729
{
@@ -33,12 +35,18 @@ internal override string ConnectionString
3335
}
3436
}
3537

36-
internal SqlConnectionPoolKey(string connectionString, SqlCredential credential, string accessToken, Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> accessTokenCallback) : base(connectionString)
38+
internal SqlConnectionPoolKey(
39+
string connectionString,
40+
SqlCredential credential,
41+
string accessToken,
42+
Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> accessTokenCallback,
43+
SspiContextProvider sspiContextProvider) : base(connectionString)
3744
{
3845
Debug.Assert(credential == null || accessToken == null || accessTokenCallback == null, "Credential, AccessToken, and Callback can't have a value at the same time.");
3946
_credential = credential;
4047
_accessToken = accessToken;
4148
_accessTokenCallback = accessTokenCallback;
49+
_sspiContextProvider = sspiContextProvider;
4250
CalculateHashCode();
4351
}
4452

@@ -47,6 +55,8 @@ private SqlConnectionPoolKey(SqlConnectionPoolKey key) : base(key)
4755
_credential = key.Credential;
4856
_accessToken = key.AccessToken;
4957
_accessTokenCallback = key._accessTokenCallback;
58+
_sspiContextProvider = key._sspiContextProvider;
59+
5060
CalculateHashCode();
5161
}
5262

@@ -61,7 +71,8 @@ public override bool Equals(object obj)
6171
&& _credential == key._credential
6272
&& ConnectionString == key.ConnectionString
6373
&& _accessTokenCallback == key._accessTokenCallback
64-
&& string.CompareOrdinal(_accessToken, key._accessToken) == 0);
74+
&& string.CompareOrdinal(_accessToken, key._accessToken) == 0
75+
&& _sspiContextProvider == key._sspiContextProvider);
6576
}
6677

6778
public override int GetHashCode()
@@ -94,6 +105,11 @@ private void CalculateHashCode()
94105
_hashValue = _hashValue * 17 + _accessTokenCallback.GetHashCode();
95106
}
96107
}
108+
109+
if (_sspiContextProvider != null)
110+
{
111+
_hashValue = _hashValue * 17 + _sspiContextProvider.GetHashCode();
112+
}
97113
}
98114
}
99115
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SSPI/NativeSspiContextProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private void LoadSSPILibrary()
4949
}
5050
}
5151

52-
protected override bool GenerateSspiClientContext(ReadOnlySpan<byte> incomingBlob, IBufferWriter<byte> outgoingBlobWriter, SspiAuthenticationParameters authParams)
52+
protected override bool GenerateContext(ReadOnlySpan<byte> incomingBlob, IBufferWriter<byte> outgoingBlobWriter, SspiAuthenticationParameters authParams)
5353
{
5454
#if NETFRAMEWORK
5555
SNIHandle handle = _physicalStateObj.Handle;
@@ -62,7 +62,7 @@ protected override bool GenerateSspiClientContext(ReadOnlySpan<byte> incomingBlo
6262
var sendLength = s_maxSSPILength;
6363
var outBuff = outgoingBlobWriter.GetSpan((int)sendLength);
6464

65-
if (0 != SniNativeWrapper.SniSecGenClientContext(handle, incomingBlob, outBuff, ref sendLength, authParams.Resource))
65+
if (SniNativeWrapper.SniSecGenClientContext(handle, incomingBlob, outBuff, ref sendLength, authParams.Resource) != 0)
6666
{
6767
return false;
6868
}

0 commit comments

Comments
 (0)