Skip to content

Commit f6feaf9

Browse files
committed
per feedback
1 parent 7e974cf commit f6feaf9

File tree

3 files changed

+35
-20
lines changed

3 files changed

+35
-20
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,14 +437,14 @@ internal void Connect(ServerInfo serverInfo,
437437

438438
_connHandler.pendingSQLDNSObject = null;
439439

440-
string[] serverSpn = null;
440+
string[] serverSpns = null;
441441

442442
// AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server
443443
_physicalStateObj.CreatePhysicalSNIHandle(
444444
serverInfo.ExtendedServerName,
445445
timeout,
446446
out instanceName,
447-
ref serverSpn,
447+
ref serverSpns,
448448
false,
449449
true,
450450
fParallel,
@@ -542,7 +542,7 @@ internal void Connect(ServerInfo serverInfo,
542542
serverInfo.ExtendedServerName,
543543
timeout,
544544
out instanceName,
545-
ref serverSpn,
545+
ref serverSpns,
546546
true,
547547
true,
548548
fParallel,
@@ -593,7 +593,7 @@ internal void Connect(ServerInfo serverInfo,
593593
}
594594
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> Prelogin handshake successful");
595595

596-
_authenticationProvider?.Initialize(serverInfo, _physicalStateObj, this, serverSpn);
596+
_authenticationProvider?.Initialize(serverInfo, _physicalStateObj, this, serverSpns);
597597

598598
if (_fMARS && marsCapable)
599599
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ protected override bool GenerateSspiClientContext(ReadOnlySpan<byte> incomingBlo
1919

2020
_negotiateAuth ??= new(new NegotiateAuthenticationClientOptions { Package = "Negotiate", TargetName = authParams.Resource });
2121

22-
Debug.Assert(_negotiateAuth.TargetName == authParams.Resource, "SSPI resource does not match TargetName");
22+
Debug.Assert(_negotiateAuth.TargetName == authParams.Resource, "SSPI resource does not match TargetName. SspiContextProvider should ensure that once a target is established it will only call with that.");
2323

2424
var sendBuff = _negotiateAuth.GetOutgoingBlob(incomingBlob, out statusCode)!;
2525

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

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Buffers;
3+
using System.Collections.Generic;
34
using System.Diagnostics;
45
using System.Linq;
56

@@ -12,10 +13,8 @@ internal abstract class SspiContextProvider
1213
private TdsParser _parser = null!;
1314
private ServerInfo _serverInfo = null!;
1415

15-
// This is used to store either a single or multiple SspiAuthenticationParameters. Since we initially have potentially
16-
// multiple SPNs, we'll start with that. However, once we've succeeded creating an SSPI context, we'll consider that
17-
// to be the correct SPN going forward
18-
private object? _authParamValue;
16+
private List<SspiAuthenticationParameters>? _authParams;
17+
private SspiAuthenticationParameters? _authParam;
1918

2019
private protected TdsParserStateObject _physicalStateObj = null!;
2120

@@ -35,9 +34,9 @@ string[] serverSpns
3534
_serverInfo = serverInfo;
3635

3736
#if NETFRAMEWORK
38-
_authParamValue = CreateAuthParams(serverSpn);
37+
_authParam = CreateAuthParams(serverSpn);
3938
#else
40-
_authParamValue = serverSpns.Select(CreateAuthParams).ToArray();
39+
_authParams = [.. serverSpns.Select(CreateAuthParams)];
4140
#endif
4241
Initialize();
4342
}
@@ -52,25 +51,41 @@ internal void WriteSSPIContext(ReadOnlySpan<byte> receivedBuff, IBufferWriter<by
5251
{
5352
using var _ = TrySNIEventScope.Create(nameof(SspiContextProvider));
5453

55-
if (_authParamValue is SspiAuthenticationParameters authParam && RunGenerateSspiClientContext(receivedBuff, outgoingBlobWriter, authParam))
54+
if (TryRunSingle(receivedBuff, outgoingBlobWriter) || TryRunMultiple(receivedBuff, outgoingBlobWriter))
5655
{
57-
return;
56+
// If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
57+
SSPIError(SQLMessage.SSPIGenerateError(), TdsEnums.GEN_CLIENT_CONTEXT);
5858
}
59-
else if (_authParamValue is SspiAuthenticationParameters[] authParams)
59+
}
60+
61+
/// <summary>
62+
/// If we only have a single auth param, we know it's the correct one to use.
63+
/// </summary>
64+
private bool TryRunSingle(ReadOnlySpan<byte> receivedBuff, IBufferWriter<byte> outgoingBlobWriter)
65+
{
66+
return _authParam is { } && RunGenerateSspiClientContext(receivedBuff, outgoingBlobWriter, _authParam);
67+
}
68+
69+
/// <summary>
70+
/// If we have multiple, we need to loop through them, and then identify the correct one for future use.
71+
/// </summary>
72+
private bool TryRunMultiple(ReadOnlySpan<byte> receivedBuff, IBufferWriter<byte> outgoingBlobWriter)
73+
{
74+
if (_authParams is { })
6075
{
61-
foreach (var p in authParams)
76+
foreach (var authParam in _authParams)
6277
{
63-
if (RunGenerateSspiClientContext(receivedBuff, outgoingBlobWriter, p))
78+
if (RunGenerateSspiClientContext(receivedBuff, outgoingBlobWriter, authParam))
6479
{
6580
// Reset the _authParams to only have a single one going forward to always call the context with that one
66-
_authParamValue = p;
67-
return;
81+
_authParam = authParam;
82+
_authParams = null;
83+
return true;
6884
}
6985
}
7086
}
7187

72-
// If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
73-
SSPIError(SQLMessage.SSPIGenerateError(), TdsEnums.GEN_CLIENT_CONTEXT);
88+
return false;
7489
}
7590

7691
private SspiAuthenticationParameters CreateAuthParams(string serverSpn)

0 commit comments

Comments
 (0)