1
1
using System ;
2
2
using System . Buffers ;
3
+ using System . Collections . Generic ;
3
4
using System . Diagnostics ;
4
5
using System . Linq ;
5
6
@@ -12,10 +13,8 @@ internal abstract class SspiContextProvider
12
13
private TdsParser _parser = null ! ;
13
14
private ServerInfo _serverInfo = null ! ;
14
15
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 ;
19
18
20
19
private protected TdsParserStateObject _physicalStateObj = null ! ;
21
20
@@ -35,9 +34,9 @@ string[] serverSpns
35
34
_serverInfo = serverInfo ;
36
35
37
36
#if NETFRAMEWORK
38
- _authParamValue = CreateAuthParams ( serverSpn ) ;
37
+ _authParam = CreateAuthParams ( serverSpn ) ;
39
38
#else
40
- _authParamValue = serverSpns . Select ( CreateAuthParams ) . ToArray ( ) ;
39
+ _authParams = [ .. serverSpns . Select ( CreateAuthParams ) ] ;
41
40
#endif
42
41
Initialize ( ) ;
43
42
}
@@ -52,25 +51,41 @@ internal void WriteSSPIContext(ReadOnlySpan<byte> receivedBuff, IBufferWriter<by
52
51
{
53
52
using var _ = TrySNIEventScope . Create ( nameof ( SspiContextProvider ) ) ;
54
53
55
- if ( _authParamValue is SspiAuthenticationParameters authParam && RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , authParam ) )
54
+ if ( TryRunSingle ( receivedBuff , outgoingBlobWriter ) || TryRunMultiple ( receivedBuff , outgoingBlobWriter ) )
56
55
{
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 ) ;
58
58
}
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 { } )
60
75
{
61
- foreach ( var p in authParams )
76
+ foreach ( var authParam in _authParams )
62
77
{
63
- if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , p ) )
78
+ if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , authParam ) )
64
79
{
65
80
// 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 ;
68
84
}
69
85
}
70
86
}
71
87
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 ;
74
89
}
75
90
76
91
private SspiAuthenticationParameters CreateAuthParams ( string serverSpn )
0 commit comments