@@ -33,7 +33,13 @@ async Task Authenticate(string username, NpgsqlTimeout timeout, bool async, Canc
3333 case AuthenticationRequestType . Ok :
3434 // If we didn't complete authentication, check whether it's allowed
3535 if ( ! authenticated )
36+ {
37+ // User requested GSS authentication, but server said that no auth is required
38+ // If and only if our connection is gss encrypted, we consider us already authenticated
39+ if ( requiredAuthModes . HasFlag ( RequireAuthMode . GSS ) && IsGssEncrypted )
40+ return ;
3641 ThrowIfNotAllowed ( requiredAuthModes , RequireAuthMode . None ) ;
42+ }
3743 return ;
3844
3945 case AuthenticationRequestType . CleartextPassword :
@@ -55,7 +61,7 @@ await AuthenticateSASL(((AuthenticationSASLMessage)msg).Mechanisms, username, as
5561 case AuthenticationRequestType . GSS :
5662 case AuthenticationRequestType . SSPI :
5763 ThrowIfNotAllowed ( requiredAuthModes , msg . AuthRequestType == AuthenticationRequestType . GSS ? RequireAuthMode . GSS : RequireAuthMode . SSPI ) ;
58- await DataSource . IntegratedSecurityHandler . NegotiateAuthentication ( async , this ) . ConfigureAwait( false ) ;
64+ await DataSource . IntegratedSecurityHandler . NegotiateAuthentication ( async , this , cancellationToken ) . ConfigureAwait( false ) ;
5965 return ;
6066
6167 case AuthenticationRequestType . GSSContinue :
@@ -207,7 +213,7 @@ internal void AuthenticateSASLSha256Plus(ref string mechanism, ref string cbindF
207213 // try authenticate without channel binding even though both
208214 // the client and server supported it. The SCRAM exchange
209215 // checks for that, to prevent downgrade attacks.
210- if ( ! IsSecure )
216+ if ( ! IsSslEncrypted )
211217 throw new NpgsqlException ( "Server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" ) ;
212218
213219 var sslStream = ( SslStream ) _stream ;
@@ -321,7 +327,7 @@ async Task AuthenticateMD5(string username, byte[] salt, bool async, Cancellatio
321327 await Flush ( async , cancellationToken ) . ConfigureAwait( false ) ;
322328 }
323329
324- internal async Task AuthenticateGSS ( bool async )
330+ internal async ValueTask AuthenticateGSS ( bool async , CancellationToken cancellationToken )
325331 {
326332 var targetName = $ "{ KerberosServiceName } /{ Host } ";
327333
@@ -331,24 +337,24 @@ internal async Task AuthenticateGSS(bool async)
331337 using var authContext = new NegotiateAuthentication ( clientOptions ) ;
332338 var data = authContext . GetOutgoingBlob ( ReadOnlySpan < byte > . Empty , out var statusCode ) ! ;
333339 Debug . Assert ( statusCode == NegotiateAuthenticationStatusCode . ContinueNeeded ) ;
334- await WritePassword ( data , 0 , data . Length , async, UserCancellationToken ) . ConfigureAwait ( false ) ;
335- await Flush ( async , UserCancellationToken ) . ConfigureAwait( false ) ;
340+ await WritePassword ( data , 0 , data . Length , async, cancellationToken ) . ConfigureAwait ( false ) ;
341+ await Flush ( async , cancellationToken ) . ConfigureAwait( false ) ;
336342 while ( true )
337343 {
338344 var response = ExpectAny < AuthenticationRequestMessage > ( await ReadMessage ( async ) . ConfigureAwait ( false ) , this ) ;
339345 if ( response . AuthRequestType == AuthenticationRequestType . Ok )
340346 break ;
341347 if ( response is not AuthenticationGSSContinueMessage gssMsg )
342348 throw new NpgsqlException ( $ "Received unexpected authentication request message { response . AuthRequestType } ") ;
343- data = authContext . GetOutgoingBlob ( gssMsg . AuthenticationData . AsSpan ( ) , out statusCode ) ! ;
349+ data = authContext . GetOutgoingBlob ( gssMsg . AuthenticationData . AsSpan ( ) , out statusCode ) ;
344350 if ( statusCode is not NegotiateAuthenticationStatusCode . Completed and not NegotiateAuthenticationStatusCode . ContinueNeeded )
345351 throw new NpgsqlException ( $ "Error while authenticating GSS/SSPI: { statusCode } ") ;
346352 // We might get NegotiateAuthenticationStatusCode.Completed but the data will not be null
347353 // This can happen if it's the first cycle, in which case we have to send that data to complete handshake (#4888)
348354 if ( data is null )
349355 continue ;
350- await WritePassword ( data , 0 , data . Length , async, UserCancellationToken ) . ConfigureAwait ( false ) ;
351- await Flush ( async , UserCancellationToken ) . ConfigureAwait( false ) ;
356+ await WritePassword ( data , 0 , data . Length , async, cancellationToken ) . ConfigureAwait ( false ) ;
357+ await Flush ( async , cancellationToken ) . ConfigureAwait( false ) ;
352358 }
353359 }
354360
0 commit comments