diff --git a/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java b/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java index fec5bb0..f6d81d5 100644 --- a/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java +++ b/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java @@ -24,7 +24,7 @@ import org.postgresql.hostchooser.HostChooser; import org.postgresql.hostchooser.HostChooserFactory; import org.postgresql.hostchooser.HostRequirement; import org.postgresql.hostchooser.HostStatus; -import org.postgresql.sspi.SSPIClient; +import org.postgresql.sspi.ISSPIClient; import org.postgresql.util.GT; import org.postgresql.util.HostSpec; import org.postgresql.util.MD5Digest; @@ -68,6 +68,38 @@ public class ConnectionFactoryImpl extends ConnectionFactory { private static class UnsupportedProtocolException extends IOException { } + + private ISSPIClient SSPIfactory(PGStream pgStream, + String spnServiceClass, + boolean enableNegotiate, + Logger logger) { + // arguments to initialize windows version of class + Class[] cArg = new Class[4]; + cArg[0] = PGStream.class; + cArg[1] = String.class; + cArg[2] = boolean.class; + cArg[3] = Logger.class; + + Class c = null; + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux")) { + try { + c = Class.forName("org.postgresql.sspi.ISSPIClient"); + return (ISSPIClient) c.getDeclaredConstructor().newInstance(); + } catch (Throwable e) { + logger.info("Unable to find SSPI class for Linux", e); + } + } else { + try { + c = Class.forName("org.postgresql.sspi.SSPIClient"); + return (ISSPIClient) c.getDeclaredConstructor(cArg).newInstance(pgStream, spnServiceClass, enableNegotiate, logger); + } catch (Throwable e) { + logger.info("Unable to find SSPI class for Linux", e); + } + } + return null; + } + public ProtocolConnection openConnectionImpl(HostSpec[] hostSpecs, String user, String database, Properties info, Logger logger) throws SQLException { // Extract interesting values from the info properties: @@ -404,7 +436,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { String password = PGProperty.PASSWORD.get(info); /* SSPI negotiation state, if used */ - SSPIClient sspiClient = null; + ISSPIClient sspiClient = null; try { authloop: while (true) { @@ -563,7 +595,7 @@ public class ConnectionFactoryImpl extends ConnectionFactory { "Using JSSE GSSAPI, gssapi requested by server and gsslib=sspi not forced"); } else { /* Determine if SSPI is supported by the client */ - sspiClient = new SSPIClient(pgStream, PGProperty.SSPI_SERVICE_CLASS.get(info), + sspiClient = SSPIfactory(pgStream, PGProperty.SSPI_SERVICE_CLASS.get(info), /* Use negotiation for SSPI, or if explicitly requested for GSS */ areq == AUTH_REQ_SSPI || (areq == AUTH_REQ_GSS && usespnego), logger); diff --git a/pgjdbc/src/main/java/org/postgresql/sspi/ISSPIClient.java b/pgjdbc/src/main/java/org/postgresql/sspi/ISSPIClient.java new file mode 100644 index 0000000..27add44 --- /dev/null +++ b/pgjdbc/src/main/java/org/postgresql/sspi/ISSPIClient.java @@ -0,0 +1,37 @@ +package org.postgresql.sspi; + +import java.io.IOException; +import java.sql.SQLException; + +import org.postgresql.core.Logger; +import org.postgresql.core.PGStream; +import org.postgresql.util.HostSpec; +import org.postgresql.util.PSQLException; +import org.postgresql.util.PSQLState; + +/** + * Use Waffle-JNI to support SSPI authentication when PgJDBC is running on a Windows + * client and talking to a Windows server. + * + * SSPI is not supported on a non-Windows client. + * + * + * @author craig + * + */ +public class ISSPIClient { + + public boolean isSSPISupported() { + return false; + } + + public void startSSPI() throws SQLException, IOException { + } + + public void continueSSPI(int msgLength) throws SQLException, IOException { + } + + public void dispose() { + } + +}