1
1
using System ;
2
2
using System . Buffers ;
3
3
using System . Diagnostics ;
4
+ using System . Linq ;
4
5
5
6
#nullable enable
6
7
@@ -10,14 +11,34 @@ internal abstract class SspiContextProvider
10
11
{
11
12
private TdsParser _parser = null ! ;
12
13
private ServerInfo _serverInfo = null ! ;
14
+
15
+ // This is used to store either a single or multiple SspiAuthenticationParameters. Since we initially have potential
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 ? _authParams ;
19
+
13
20
private protected TdsParserStateObject _physicalStateObj = null ! ;
14
21
15
- internal void Initialize ( ServerInfo serverInfo , TdsParserStateObject physicalStateObj , TdsParser parser )
22
+ internal void Initialize (
23
+ ServerInfo serverInfo ,
24
+ TdsParserStateObject physicalStateObj ,
25
+ TdsParser parser ,
26
+ #if NETFRAMEWORK
27
+ string serverSpn
28
+ #else
29
+ string [ ] serverSpns
30
+ #endif
31
+ )
16
32
{
17
33
_parser = parser ;
18
34
_physicalStateObj = physicalStateObj ;
19
35
_serverInfo = serverInfo ;
20
36
37
+ #if NETFRAMEWORK
38
+ _authParams = CreateAuthParams ( serverSpn ) ;
39
+ #else
40
+ _authParams = serverSpns . Select ( CreateAuthParams ) . ToArray ( ) ;
41
+ #endif
21
42
Initialize ( ) ;
22
43
}
23
44
@@ -27,46 +48,49 @@ private protected virtual void Initialize()
27
48
28
49
protected abstract bool GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , SspiAuthenticationParameters authParams ) ;
29
50
30
- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
51
+ internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter )
31
52
{
32
53
using var _ = TrySNIEventScope . Create ( nameof ( SspiContextProvider ) ) ;
33
54
34
- if ( ! RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
55
+ if ( _authParams is SspiAuthenticationParameters authParam )
35
56
{
36
- // If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
37
- SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
57
+ RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , authParam ) ;
58
+ return ;
38
59
}
39
- }
40
-
41
- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , ReadOnlySpan < string > serverSpns )
42
- {
43
- using var _ = TrySNIEventScope . Create ( nameof ( SspiContextProvider ) ) ;
44
-
45
- foreach ( var serverSpn in serverSpns )
60
+ else if ( _authParams is SspiAuthenticationParameters [ ] authParams )
46
61
{
47
- if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
62
+ foreach ( var p in authParams )
48
63
{
49
- return ;
64
+ if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , p ) )
65
+ {
66
+ // Reset the _authParams to only have a single one going forward to always call the context with that one
67
+ _authParams = p ;
68
+ return ;
69
+ }
50
70
}
51
71
}
52
72
53
73
// If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
54
74
SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
55
75
}
56
76
57
- private bool RunGenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
77
+ private SspiAuthenticationParameters CreateAuthParams ( string serverSpn )
58
78
{
59
79
var options = _parser . Connection . ConnectionOptions ;
60
- var authParams = new SspiAuthenticationParameters ( options . DataSource , serverSpn )
80
+
81
+ return new SspiAuthenticationParameters ( options . DataSource , serverSpn )
61
82
{
62
83
DatabaseName = options . InitialCatalog ,
63
84
UserId = options . UserID ,
64
85
Password = options . Password ,
65
86
} ;
87
+ }
66
88
89
+ private bool RunGenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , SspiAuthenticationParameters authParams )
90
+ {
67
91
try
68
92
{
69
- SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | SPN={1}" , GetType ( ) . FullName , nameof ( GenerateSspiClientContext ) , serverSpn ) ;
93
+ SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | SPN={1}" , GetType ( ) . FullName , nameof ( GenerateSspiClientContext ) , authParams . Resource ) ;
70
94
71
95
return GenerateSspiClientContext ( incomingBlob , outgoingBlobWriter , authParams ) ;
72
96
}
0 commit comments