@@ -26,24 +26,78 @@ private protected virtual void Initialize()
2626 {
2727 }
2828
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 ) ;
3030
3131 internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
32- => SSPIData ( receivedBuff , outgoingBlobWriter , new [ ] { serverSpn } ) ;
32+ {
33+ using var _ = TrySNIEventScope . Create ( nameof ( SSPIContextProvider ) ) ;
3334
34- internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , string [ ] serverSpns )
35+ if ( ! RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
36+ {
37+ // If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
38+ SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
39+ }
40+ }
41+
42+ internal void SSPIData ( ReadOnlySpan < byte > receivedBuff , IBufferWriter < byte > outgoingBlobWriter , ReadOnlySpan < string > serverSpns )
3543 {
36- using ( TrySNIEventScope . Create ( nameof ( SSPIContextProvider ) ) )
44+ using var _ = TrySNIEventScope . Create ( nameof ( SSPIContextProvider ) ) ;
45+
46+ foreach ( var serverSpn in serverSpns )
3747 {
38- try
39- {
40- GenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpns ) ;
41- }
42- catch ( Exception e )
48+ if ( RunGenerateSspiClientContext ( receivedBuff , outgoingBlobWriter , serverSpn ) )
4349 {
44- SSPIError ( e . Message + Environment . NewLine + e . StackTrace , TdsEnums . GEN_CLIENT_CONTEXT ) ;
50+ return ;
4551 }
4652 }
53+
54+ // If we've hit here, the SSPI context provider implementation failed to generate the SSPI context.
55+ SSPIError ( SQLMessage . SSPIGenerateError ( ) , TdsEnums . GEN_CLIENT_CONTEXT ) ;
56+ }
57+
58+ private bool RunGenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , string serverSpn )
59+ {
60+ var authParams = CreateSqlAuthParams ( _parser . Connection , serverSpn ) ;
61+
62+ try
63+ {
64+ #if NET8_0_OR_GREATER
65+ SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | Session Id {2}, SPN={3}" , GetType ( ) . FullName ,
66+ nameof ( GenerateSspiClientContext ) , _physicalStateObj . SessionId , serverSpn ) ;
67+ #else
68+ SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | SPN={1}" , GetType ( ) . FullName ,
69+ nameof ( GenerateSspiClientContext ) , serverSpn ) ;
70+ #endif
71+
72+ return GenerateSspiClientContext ( incomingBlob , outgoingBlobWriter , authParams ) ;
73+ }
74+ catch ( Exception e )
75+ {
76+ SSPIError ( e . Message + Environment . NewLine + e . StackTrace , TdsEnums . GEN_CLIENT_CONTEXT ) ;
77+ return false ;
78+ }
79+ }
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 ;
47101 }
48102
49103 protected void SSPIError ( string error , string procedure )
0 commit comments