Subject: [pgjdbc/pgjdbc] issue #3515: GSSAPI/Kerberos authentication in a cross-realm scenario

From: "vpinna80 (@vpinna80)" <[email-masked]>
Date: Fri, 07 Feb 2025 16:22:47 +0000

Please read https://stackoverflow.com/help/minimal-reproducible-example 

**Describe the issue**
This is a reopening of issue #1118, for which there's no solution.
Also, the problem does not show when running `psql` command line utility - only jdbc is affected.
We cannot implement the solution in #1118 (changing default_realm) because that would make other services inaccessible.
The jdbc client should not assume that the client belongs to the same realm as the server machine.

**Driver Version?** 
42.7.5 (maven)

**Java Version?**
openjdk 11.0.25 2024-10-15 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.25.0.9-1) (build 11.0.25+9-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.25.0.9-1) (build 11.0.25+9-LTS, mixed mode, sharing)

**OS Version?**
Linux **************.it 4.18.0-553.33.1.el8_10.x86_64 #1 SMP Fri Dec 6 15:07:20 EST 2024 x86_64 x86_64 x86_64 GNU/Linux

**PostgreSQL Version?**
psql (13.18)

**To Reproduce**
* PSQL with SPN `POSTGRES/psql_machine@DOMAIN_SERVER` (RH IDM)
* USER with TGT `krbtgt/DOMAIN_CLIENT@DOMAIN_CLIENT` (AD)
* AD/IDM trust relationship to allow users of DOMAIN_CLIENT to access services in DOMAIN_SERVER
* User accesses with ssh gssapi-with-mic method the machine psql_machine
* User performs a klist -ef to check that the ticket has been forwarded
* User runs the code blow and gets:
```
Exception in thread "main" org.postgresql.util.PSQLException: GSS Authentication failed
        at org.postgresql.gss.GssAction.run(GssAction.java:136)
        at org.postgresql.gss.GssAction.run(GssAction.java:26)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/javax.security.auth.Subject.doAs(Subject.java:361)
        at org.postgresql.gss.MakeGSS.authenticate(MakeGSS.java:63)
        at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:652)
        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:146)
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:197)
        at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
        at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:217)
        at org.postgresql.Driver.makeConnection(Driver.java:458)
        at org.postgresql.Driver.connect(Driver.java:260)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
        at test.Main.main(Main.java:28)
Caused by: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
        at java.security.jgss/sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:162)
        at java.security.jgss/sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:126)
        at java.security.jgss/sun.security.jgss.GSSManagerImpl.getCredentialElement(GSSManagerImpl.java:187)
        at java.security.jgss/sun.security.jgss.GSSCredentialImpl.add(GSSCredentialImpl.java:439)
        at java.security.jgss/sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.java:89)
        at java.security.jgss/sun.security.jgss.GSSManagerImpl.createCredential(GSSManagerImpl.java:154)
        at org.postgresql.gss.GssAction.run(GssAction.java:74)
```

**Expected behaviour**
An "1" should be printed as result.

**Logs**
No logs were generated on the server, as the connection was unsuccessful.

Using the following template code make sure the bug can be replicated in the driver alone.
```
import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

public class TestKrb5CrossDomain {
    public static void main(String []args) throws SQLException {

	Configuration.setConfiguration(new Configuration() {
		@Override
		public AppConfigurationEntry[] getAppConfigurationEntry(String name)
		{
			Map<String, String> props = Map.of("useTicketCache", "true", "doNotPrompt", "true", "debug", "true", "refreshKrb5Config", "true");
			return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", REQUIRED, props) };
		};
	});

        String url = "jdbc:postgresql://localhost:5432/test";

        Properties props = new Properties();
        try ( Connection conn = DriverManager.getConnection(url, props) ){
            try ( Statement statement = conn.createStatement() ) {
                try (ResultSet rs = statement.executeQuery( "select 1 as test") ){
                    if (rs.next())
                        System.out.println( "Get Int: " + rs.getInt(1));
                }
            }
        }
    }
}
```

---

From: "davecramer (@davecramer)" <[email-masked]>
Date: Sun, 09 Feb 2025 20:49:59 +0000

so what is the solution ?

---

From: "vpinna80 (@vpinna80)" <[email-masked]>
Date: Tue, 11 Feb 2025 11:16:23 +0000

Apparently, an older version of the driver (42.2.14) was injected through the system classpath. With the 42.7.5 version the problem does not happen.
I'm closing this issue.

---

From: "davecramer (@davecramer)" <[email-masked]>
Date: Tue, 11 Feb 2025 12:12:16 +0000

@vpinna80 thanks for closing this!