11using System ;
22using System . Buffers ;
33using System . Diagnostics ;
4+ using System . Linq ;
45
56#nullable enable
67
@@ -10,14 +11,34 @@ internal abstract class SspiContextProvider
1011 {
1112 private TdsParser _parser = null ! ;
1213 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+
1320 private protected TdsParserStateObject _physicalStateObj = null ! ;
1421
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+ )
1632 {
1733 _parser = parser ;
1834 _physicalStateObj = physicalStateObj ;
1935 _serverInfo = serverInfo ;
2036
37+ #if NETFRAMEWORK
38+ _authParams = CreateAuthParams ( serverSpn ) ;
39+ #else
40+ _authParams = serverSpns . Select ( CreateAuthParams ) . ToArray ( ) ;
41+ #endif
2142 Initialize ( ) ;
2243 }
2344
@@ -27,46 +48,49 @@ private protected virtual void Initialize()
2748
2849 protected abstract bool GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , SspiAuthenticationParameters authParams ) ;
2950
30- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
51+ internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter )
3152 {
3253 using var _ = TrySNIEventScope . Create ( nameof ( SspiContextProvider ) ) ;
3354
34- if ( ! RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
55+ if ( _authParams is SspiAuthenticationParameters authParam )
3556 {
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 ;
3859 }
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 )
4661 {
47- if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
62+ foreach ( var p in authParams )
4863 {
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+ }
5070 }
5171 }
5272
5373 // If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
5474 SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
5575 }
5676
57- private bool RunGenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
77+ private SspiAuthenticationParameters CreateAuthParams ( string serverSpn )
5878 {
5979 var options = _parser . Connection . ConnectionOptions ;
60- var authParams = new SspiAuthenticationParameters ( options . DataSource , serverSpn )
80+
81+ return new SspiAuthenticationParameters ( options . DataSource , serverSpn )
6182 {
6283 DatabaseName = options . InitialCatalog ,
6384 UserId = options . UserID ,
6485 Password = options . Password ,
6586 } ;
87+ }
6688
89+ private bool RunGenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , SspiAuthenticationParameters authParams )
90+ {
6791 try
6892 {
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 ) ;
7094
7195 return GenerateSspiClientContext ( incomingBlob , outgoingBlobWriter , authParams ) ;
7296 }
0 commit comments