@@ -26,26 +26,80 @@ private protected virtual void Initialize()
26
26
{
27
27
}
28
28
29
- protected abstract void GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , ReadOnlySpan < string > serverSpns ) ;
29
+ protected abstract bool GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , SqlAuthenticationParameters authParams ) ;
30
30
31
31
internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
32
- => SSPIData ( receivedBuff , outgoingBlobWriter , new [ ] { serverSpn } ) ;
32
+ {
33
+ if ( ! RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
34
+ {
35
+ // If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
36
+ SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
37
+ }
38
+ }
33
39
34
- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string [ ] serverSpns )
40
+ internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , ReadOnlySpan < string > serverSpns )
35
41
{
36
42
using ( TrySNIEventScope . Create ( nameof ( SSPIContextProvider ) ) )
37
43
{
38
- try
44
+ foreach ( var serverSpn in serverSpns )
39
45
{
40
- GenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpns ) ;
41
- }
42
- catch ( Exception e )
43
- {
44
- SSPIError ( e . Message + Environment . NewLine + e . StackTrace , TdsEnums . GEN_CLIENT_CONTEXT ) ;
46
+ if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
47
+ {
48
+ return ;
49
+ }
45
50
}
51
+
52
+ // If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
53
+ SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
54
+ }
55
+ }
56
+
57
+ private bool RunGenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
58
+ {
59
+ var authParams = CreateSqlAuthParams ( _parser . Connection , serverSpn ) ;
60
+
61
+ try
62
+ {
63
+ #if NET8_0_OR_GREATER
64
+ SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | Session Id {2}, SPN={3}" , GetType ( ) . FullName ,
65
+ nameof ( GenerateSspiClientContext ) , _physicalStateObj . SessionId , serverSpn ) ;
66
+ #else
67
+ SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | SPN={1}" , GetType ( ) . FullName ,
68
+ nameof ( GenerateSspiClientContext ) , serverSpn ) ;
69
+ #endif
70
+
71
+ return GenerateSspiClientContext ( incomingBlob , outgoingBlobWriter , authParams ) ;
72
+ }
73
+ catch ( Exception e )
74
+ {
75
+ //throw new InvalidOperationException(SQLMessage.SSPIGenerateError() + Environment.NewLine + statusCode);
76
+ SSPIError ( e . Message + Environment . NewLine + e . StackTrace , TdsEnums . GEN_CLIENT_CONTEXT ) ;
77
+ return false ;
46
78
}
47
79
}
48
80
81
+ private static SqlAuthenticationParameters CreateSqlAuthParams ( SqlInternalConnectionTds connection , string serverSpn )
82
+ {
83
+ var auth = new SqlAuthenticationParameters . Builder (
84
+ authenticationMethod : connection . ConnectionOptions . Authentication ,
85
+ resource : null ,
86
+ authority : null ,
87
+ serverName : serverSpn ,
88
+ connection . ConnectionOptions . InitialCatalog ) ;
89
+
90
+ if ( connection . ConnectionOptions . UserID is { } userId )
91
+ {
92
+ auth . WithUserId ( userId ) ;
93
+ }
94
+
95
+ if ( connection . ConnectionOptions . Password is { } password )
96
+ {
97
+ auth . WithPassword ( password ) ;
98
+ }
99
+
100
+ return auth ;
101
+ }
102
+
49
103
protected void SSPIError ( string error , string procedure )
50
104
{
51
105
Debug . Assert ( ! ADP . IsEmpty ( procedure ) , "TdsParser.SSPIError called with an empty or null procedure string" ) ;
0 commit comments