Blob Blame History Raw
diff --git a/pgjdbc/src/main/java/org/postgresql/sspi/SSPIClient.java b/pgjdbc/src/main/java/org/postgresql/sspi/SSPIClient.java
deleted file mode 100644
index b6c47b8..0000000
--- a/pgjdbc/src/main/java/org/postgresql/sspi/SSPIClient.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2003, PostgreSQL Global Development Group
- * See the LICENSE file in the project root for more information.
- */
-// Copyright (c) 2004, Open Cloud Limited.
-
-package org.postgresql.sspi;
-
-import org.postgresql.core.PGStream;
-import org.postgresql.util.HostSpec;
-import org.postgresql.util.PSQLException;
-import org.postgresql.util.PSQLState;
-
-import com.sun.jna.LastErrorException;
-import com.sun.jna.Platform;
-import com.sun.jna.platform.win32.Sspi;
-import com.sun.jna.platform.win32.Sspi.SecBufferDesc;
-import com.sun.jna.platform.win32.Win32Exception;
-import waffle.windows.auth.IWindowsCredentialsHandle;
-import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
-import waffle.windows.auth.impl.WindowsSecurityContextImpl;
-
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * <p>Use Waffle-JNI to support SSPI authentication when PgJDBC is running on a Windows client and
- * talking to a Windows server.</p>
- *
- * <p>SSPI is not supported on a non-Windows client.</p>
- *
- * @author craig
- */
-public class SSPIClient implements ISSPIClient {
-
-  public static final String SSPI_DEFAULT_SPN_SERVICE_CLASS = "POSTGRES";
-
-  private static final Logger LOGGER = Logger.getLogger(SSPIClient.class.getName());
-  private final PGStream pgStream;
-  private final String spnServiceClass;
-  private final boolean enableNegotiate;
-
-  private IWindowsCredentialsHandle clientCredentials;
-  private WindowsSecurityContextImpl sspiContext;
-  private String targetName;
-
-  /**
-   * <p>Instantiate an SSPIClient for authentication of a connection.</p>
-   *
-   * <p>SSPIClient is not re-usable across connections.</p>
-   *
-   * <p>It is safe to instantiate SSPIClient even if Waffle and JNA are missing or on non-Windows
-   * platforms, however you may not call any methods other than isSSPISupported().</p>
-   *
-   * @param pgStream PostgreSQL connection stream
-   * @param spnServiceClass SSPI SPN service class, defaults to POSTGRES if null
-   * @param enableNegotiate enable negotiate
-   */
-  public SSPIClient(PGStream pgStream, String spnServiceClass, boolean enableNegotiate) {
-    this.pgStream = pgStream;
-
-    if (spnServiceClass == null || spnServiceClass.isEmpty()) {
-      spnServiceClass = SSPI_DEFAULT_SPN_SERVICE_CLASS;
-    }
-    this.spnServiceClass = spnServiceClass;
-
-    /* If we're forcing Kerberos (no spnego), disable SSPI negotiation */
-    this.enableNegotiate = enableNegotiate;
-  }
-
-  /**
-   * Test whether we can attempt SSPI authentication. If false, do not attempt to call any other
-   * SSPIClient methods.
-   *
-   * @return true if it's safe to attempt SSPI authentication
-   */
-  @Override
-  public boolean isSSPISupported() {
-    try {
-      /*
-       * SSPI is windows-only. Attempt to use JNA to identify the platform. If Waffle is missing we
-       * won't have JNA and this will throw a NoClassDefFoundError.
-       */
-      if (!Platform.isWindows()) {
-        LOGGER.log(Level.FINE, "SSPI not supported: non-Windows host");
-        return false;
-      }
-      /* Waffle must be on the CLASSPATH */
-      Class.forName("waffle.windows.auth.impl.WindowsSecurityContextImpl");
-      return true;
-    } catch (NoClassDefFoundError ex) {
-      LOGGER.log(Level.WARNING, "SSPI unavailable (no Waffle/JNA libraries?)", ex);
-      return false;
-    } catch (ClassNotFoundException ex) {
-      LOGGER.log(Level.WARNING, "SSPI unavailable (no Waffle/JNA libraries?)", ex);
-      return false;
-    }
-  }
-
-  private String makeSPN() throws PSQLException {
-    final HostSpec hs = pgStream.getHostSpec();
-
-    try {
-      /*
-      The GSSAPI implementation does not use the port in the service name.
-      Force the port number to 0
-      Fixes issue 1482
-      */
-      return NTDSAPIWrapper.instance.DsMakeSpn(spnServiceClass, hs.getHost(), null,
-          (short) 0, null);
-    } catch (LastErrorException ex) {
-      throw new PSQLException("SSPI setup failed to determine SPN",
-          PSQLState.CONNECTION_UNABLE_TO_CONNECT, ex);
-    }
-  }
-
-  /**
-   * Respond to an authentication request from the back-end for SSPI authentication (AUTH_REQ_SSPI).
-   *
-   * @throws SQLException on SSPI authentication handshake failure
-   * @throws IOException on network I/O issues
-   */
-  @Override
-  public void startSSPI() throws SQLException, IOException {
-
-    /*
-     * We usually use SSPI negotiation (spnego), but it's disabled if the client asked for GSSPI and
-     * usespngo isn't explicitly turned on.
-     */
-    final String securityPackage = enableNegotiate ? "negotiate" : "kerberos";
-
-    LOGGER.log(Level.FINEST, "Beginning SSPI/Kerberos negotiation with SSPI package: {0}", securityPackage);
-
-    try {
-      /*
-       * Acquire a handle for the local Windows login credentials for the current user
-       *
-       * See AcquireCredentialsHandle
-       * (http://msdn.microsoft.com/en-us/library/windows/desktop/aa374712%28v=vs.85%29.aspx)
-       *
-       * This corresponds to pg_SSPI_startup in libpq/fe-auth.c .
-       */
-      try {
-        clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
-        clientCredentials.initialize();
-      } catch (Win32Exception ex) {
-        throw new PSQLException("Could not obtain local Windows credentials for SSPI",
-            PSQLState.CONNECTION_UNABLE_TO_CONNECT /* TODO: Should be authentication error */, ex);
-      }
-
-      try {
-        targetName = makeSPN();
-
-        LOGGER.log(Level.FINEST, "SSPI target name: {0}", targetName);
-
-        sspiContext = new WindowsSecurityContextImpl();
-        sspiContext.setPrincipalName(targetName);
-        sspiContext.setCredentialsHandle(clientCredentials);
-        sspiContext.setSecurityPackage(securityPackage);
-        sspiContext.initialize(null, null, targetName);
-      } catch (Win32Exception ex) {
-        throw new PSQLException("Could not initialize SSPI security context",
-            PSQLState.CONNECTION_UNABLE_TO_CONNECT /* TODO: Should be auth error */, ex);
-      }
-
-      sendSSPIResponse(sspiContext.getToken());
-      LOGGER.log(Level.FINEST, "Sent first SSPI negotiation message");
-    } catch (NoClassDefFoundError ex) {
-      throw new PSQLException(
-          "SSPI cannot be used, Waffle or its dependencies are missing from the classpath",
-          PSQLState.NOT_IMPLEMENTED, ex);
-    }
-  }
-
-  /**
-   * Continue an existing authentication conversation with the back-end in resonse to an
-   * authentication request of type AUTH_REQ_GSS_CONT.
-   *
-   * @param msgLength Length of message to read, excluding length word and message type word
-   * @throws SQLException if something wrong happens
-   * @throws IOException if something wrong happens
-   */
-  @Override
-  public void continueSSPI(int msgLength) throws SQLException, IOException {
-
-    if (sspiContext == null) {
-      throw new IllegalStateException("Cannot continue SSPI authentication that we didn't begin");
-    }
-
-    LOGGER.log(Level.FINEST, "Continuing SSPI negotiation");
-
-    /* Read the response token from the server */
-    byte[] receivedToken = pgStream.receive(msgLength);
-
-    SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, receivedToken);
-
-    sspiContext.initialize(sspiContext.getHandle(), continueToken, targetName);
-
-    /*
-     * Now send the response token. If negotiation is complete there may be zero bytes to send, in
-     * which case we shouldn't send a reply as the server is not expecting one; see fe-auth.c in
-     * libpq for details.
-     */
-    byte[] responseToken = sspiContext.getToken();
-    if (responseToken.length > 0) {
-      sendSSPIResponse(responseToken);
-      LOGGER.log(Level.FINEST, "Sent SSPI negotiation continuation message");
-    } else {
-      LOGGER.log(Level.FINEST, "SSPI authentication complete, no reply required");
-    }
-  }
-
-  private void sendSSPIResponse(byte[] outToken) throws IOException {
-    /*
-     * The sspiContext now contains a token we can send to the server to start the handshake. Send a
-     * 'password' message containing the required data; the server knows we're doing SSPI
-     * negotiation and will deal with it appropriately.
-     */
-    pgStream.sendChar('p');
-    pgStream.sendInteger4(4 + outToken.length);
-    pgStream.send(outToken);
-    pgStream.flush();
-  }
-
-  /**
-   * Clean up native win32 resources after completion or failure of SSPI authentication. This
-   * SSPIClient instance becomes unusable after disposal.
-   */
-  @Override
-  public void dispose() {
-    if (sspiContext != null) {
-      sspiContext.dispose();
-      sspiContext = null;
-    }
-    if (clientCredentials != null) {
-      clientCredentials.dispose();
-      clientCredentials = null;
-    }
-  }
-}