@@ -11,27 +11,34 @@ namespace Microsoft.Data.SqlClient
11
11
{
12
12
internal sealed class NegotiateSSPIContextProvider : SSPIContextProvider
13
13
{
14
+ private NegotiateAuthentication ? _negotiateAuth = null ;
15
+
14
16
protected override void GenerateSspiClientContext ( ReadOnlySpan < byte > incomingBlob , IBufferWriter < byte > outgoingBlobWriter , byte [ ] [ ] _sniSpnBuffer )
15
17
{
16
- NegotiateAuthenticationStatusCode statusCode = default ;
18
+ NegotiateAuthenticationStatusCode statusCode = NegotiateAuthenticationStatusCode . UnknownCredentials ;
17
19
18
20
for ( int i = 0 ; i < _sniSpnBuffer . Length ; i ++ )
19
21
{
20
- var negotiateAuth = new NegotiateAuthentication ( new NegotiateAuthenticationClientOptions { Package = "Negotiate" , TargetName = Encoding . Unicode . GetString ( _sniSpnBuffer [ i ] ) } ) ;
21
- var result = negotiateAuth . GetOutgoingBlob ( incomingBlob , out statusCode ) ;
22
-
22
+ _negotiateAuth ??= new ( new NegotiateAuthenticationClientOptions { Package = "Negotiate" , TargetName = Encoding . Unicode . GetString ( _sniSpnBuffer [ i ] ) } ) ;
23
+ var sendBuff = _negotiateAuth . GetOutgoingBlob ( incomingBlob , out statusCode ) ! ;
23
24
// Log session id, status code and the actual SPN used in the negotiation
24
25
SqlClientEventSource . Log . TryTraceEvent ( "{0}.{1} | Info | Session Id {2}, StatusCode={3}, SPN={4}" , nameof ( NegotiateSSPIContextProvider ) ,
25
- nameof ( GenerateSspiClientContext ) , _physicalStateObj . SessionId , statusCode , negotiateAuth . TargetName ) ;
26
-
26
+ nameof ( GenerateSspiClientContext ) , _physicalStateObj . SessionId , statusCode , _negotiateAuth . TargetName ) ;
27
27
if ( statusCode == NegotiateAuthenticationStatusCode . Completed || statusCode == NegotiateAuthenticationStatusCode . ContinueNeeded )
28
28
{
29
- outgoingBlobWriter . Write ( result ) ;
30
- return ;
29
+ outgoingBlobWriter . Write ( sendBuff ) ;
30
+ break ; // Successful case, exit the loop with current SPN.
31
+ }
32
+ else
33
+ {
34
+ _negotiateAuth = null ; // Reset _negotiateAuth to be generated again for next SPN.
31
35
}
32
36
}
33
37
34
- throw new InvalidOperationException ( SQLMessage . SSPIGenerateError ( ) + Environment . NewLine + statusCode ) ;
38
+ if ( statusCode is not NegotiateAuthenticationStatusCode . Completed and not NegotiateAuthenticationStatusCode . ContinueNeeded )
39
+ {
40
+ throw new InvalidOperationException ( SQLMessage . SSPIGenerateError ( ) + Environment . NewLine + statusCode ) ;
41
+ }
35
42
}
36
43
}
37
44
}
0 commit comments