Improve kerberos auth on windows (#6541) · npgsql/npgsql@f703ef8 · GitHub
Skip to content

Commit f703ef8

Browse files
authored
Improve kerberos auth on windows (#6541)
Fixes #6529
1 parent 5f26d61 commit f703ef8

3 files changed

Lines changed: 18 additions & 8 deletions

File tree

‎src/Npgsql/Internal/IntegratedSecurityHandler.cs‎

Lines changed: 3 additions & 3 deletions

‎src/Npgsql/Internal/NpgsqlConnector.Auth.cs‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ await AuthenticateSASL(((AuthenticationSASLMessage)msg).Mechanisms, username, as
6161
case AuthenticationRequestType.GSS:
6262
case AuthenticationRequestType.SSPI:
6363
ThrowIfNotAllowed(requiredAuthModes, msg.AuthRequestType == AuthenticationRequestType.GSS ? RequireAuthMode.GSS : RequireAuthMode.SSPI);
64-
await DataSource.IntegratedSecurityHandler.NegotiateAuthentication(async, this, cancellationToken).ConfigureAwait(false);
64+
var isKerberos = msg.AuthRequestType == AuthenticationRequestType.GSS;
65+
await DataSource.IntegratedSecurityHandler.NegotiateAuthentication(async, isKerberos, this, cancellationToken).ConfigureAwait(false);
6566
return;
6667

6768
case AuthenticationRequestType.GSSContinue:
@@ -327,7 +328,7 @@ async Task AuthenticateMD5(string username, byte[] salt, bool async, Cancellatio
327328
await Flush(async, cancellationToken).ConfigureAwait(false);
328329
}
329330

330-
internal async ValueTask AuthenticateGSS(bool async, CancellationToken cancellationToken)
331+
internal async ValueTask AuthenticateGSS(bool async, bool isKerberos, CancellationToken cancellationToken)
331332
{
332333
var targetName = $"{KerberosServiceName}/{Host}";
333334
// See https://github.com/postgres/postgres/blob/a0dd0702e464f206b08c99a74cb58809c51aafa5/src/interfaces/libpq/fe-auth.c#L111-L123
@@ -337,15 +338,24 @@ internal async ValueTask AuthenticateGSS(bool async, CancellationToken cancellat
337338
TargetName = targetName,
338339
RequireMutualAuthentication = true
339340
};
341+
// If postgres requests GSS, we explicitly ask for Kerberos
342+
// Instead of relying on SSPI on windows to pick the correct protocol (Kerberos instead of NTLM)
343+
// Otherwise, leave Negotiate to allow SSPI to pick whatever it thinks is correct
344+
// This behavior differs from libpq, which prefers SSPI to pick the protocol
345+
// But mimics PGJDBC
346+
// On UNIX only Kerberos is supported, so no need to differentiate between OSes
347+
// TODO: PGJBC has a parameter to force SSPI. Not sure we need something like this.
348+
if (isKerberos)
349+
clientOptions.Package = "Kerberos";
340350

341351
NegotiateOptionsCallback?.Invoke(clientOptions);
342352

343353
using var authContext = new NegotiateAuthentication(clientOptions);
344354
var data = authContext.GetOutgoingBlob(ReadOnlySpan<byte>.Empty, out var statusCode)!;
345-
if (statusCode != NegotiateAuthenticationStatusCode.ContinueNeeded)
355+
if (statusCode is not NegotiateAuthenticationStatusCode.Completed and not NegotiateAuthenticationStatusCode.ContinueNeeded)
346356
{
347357
// Unable to retrieve credentials or some other issue
348-
throw new NpgsqlException($"Unable to authenticate with GSS: received {statusCode} instead of the expected ContinueNeeded");
358+
throw new NpgsqlException($"Unable to authenticate with GSS: received {statusCode} instead of the expected ContinueNeeded or Completed");
349359
}
350360
await WritePassword(data, 0, data.Length, async, cancellationToken).ConfigureAwait(false);
351361
await Flush(async, cancellationToken).ConfigureAwait(false);

‎src/Npgsql/Internal/NpgsqlConnector.cs‎

Lines changed: 1 addition & 1 deletion

0 commit comments

Comments
 (0)