@@ -26,26 +26,80 @@ private protected virtual void Initialize()
2626 {
2727 }
2828
29- protected abstract void GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , ReadOnlySpan < string > _sniSpnBuffer ) ;
29+ protected abstract bool GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , SqlAuthenticationParameters authParams ) ;
3030
31- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string sniSpnBuffer )
32- => SSPIData ( receivedBuff , outgoingBlobWriter , new [ ] { sniSpnBuffer } ) ;
31+ internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string serverName )
32+ {
33+ if ( ! RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverName ) )
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+ }
3339
34- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string [ ] sniSpnBuffer )
40+ internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , ReadOnlySpan < string > serverNames )
3541 {
3642 using ( TrySNIEventScope . Create ( nameof ( SSPIContextProvider ) ) )
3743 {
38- try
44+ foreach ( var serverName in serverNames )
3945 {
40- GenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , sniSpnBuffer ) ;
41- }
42- catch ( Exception e )
43- {
44- SSPIError ( e . Message + Environment . NewLine + e . StackTrace , TdsEnums . GEN_CLIENT_CONTEXT ) ;
46+ if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverName ) )
47+ {
48+ return ;
49+ }
4550 }
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 serverName )
58+ {
59+ var authParams = CreateSqlAuthParams ( _parser . Connection , serverName ) ;
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 , serverName ) ;
66+ #else
67+ SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | SPN={1}" , GetType ( ) . FullName ,
68+ nameof ( GenerateSspiClientContext ) , serverName ) ;
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 ;
4678 }
4779 }
4880
81+ private static SqlAuthenticationParameters CreateSqlAuthParams ( SqlInternalConnectionTds connection , string serverName )
82+ {
83+ var auth = new SqlAuthenticationParameters . Builder (
84+ authenticationMethod : connection . ConnectionOptions . Authentication ,
85+ resource : null ,
86+ authority : null ,
87+ serverName : serverName ,
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+
49103 protected void SSPIError ( string error , string procedure )
50104 {
51105 Debug . Assert ( ! ADP . IsEmpty ( procedure ) , "TdsParser.SSPIError called with an empty or null procedure string" ) ;
0 commit comments