// jTDS JDBC Driver for Microsoft SQL Server and Sybase // Copyright (C) 2004 The jTDS Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // package net.sourceforge.jtds.util; import java.sql.SQLException; /** * A JNI client to SSPI based CPP program (DLL) that returns the user * credentials for NTLM authentication. * <p/> * The DLL name is ntlmauth.dll. * * @author Magendran Sathaiah (mahi@aztec.soft.net) */ public class SSPIJNIClient { /** Singleton instance. */ private static SSPIJNIClient thisInstance; /** SSPI native library loaded flag. */ private static boolean libraryLoaded; /** SSPI client initialized flag. */ private boolean initialized; /** Initializes the SSPI client. */ private native void initialize(); /** Uninitializes the SSPI client. */ private native void unInitialize(); /** * Prepares the NTLM TYPE-1 message and returns it as a * <code>byte[]</code>. */ private native byte[] prepareSSORequest(); /** * Prepares the NTLM TYPE-3 message using the current user's credentials. * <p> * It needs the challenge BLOB and it's size as input. The challenge BLOB * is nothig but the TYPE-2 message that is received from the SQL Server. * * @param buf challenge BLOB * @param size challenge BLOB size * @return NTLM TYPE-3 message */ private native byte[] prepareSSOSubmit(byte[] buf, long size); static { try { System.loadLibrary("ntlmauth"); SSPIJNIClient.libraryLoaded = true; } catch (UnsatisfiedLinkError err) { Logger.println("Unable to load library: " + err); } } /** * Private constructor for singleton. */ private SSPIJNIClient() { //empty constructor } /** * Returns the singleton <code>SSPIJNIClient</code> instance. * * @throws SQLException if an error occurs during initialization */ public static synchronized SSPIJNIClient getInstance() throws Exception { if (thisInstance == null) { if (!libraryLoaded) { throw new Exception("Native SSPI library not loaded. " + "Check the java.library.path system property."); } thisInstance = new SSPIJNIClient(); thisInstance.invokeInitialize(); } return thisInstance; } /** * Calls <code>#initialize()</code> if the SSPI client is not already inited. */ public void invokeInitialize() { if (!initialized) { initialize(); initialized = true; } } /** * Calls <code>#unInitialize()</code> if the SSPI client is inited. */ public void invokeUnInitialize() { if (initialized) { unInitialize(); initialized = false; } } /** * Calls <code>#prepareSSORequest()</code> to prepare the NTLM TYPE-1 message. * * @throws Exception if an error occurs during the call or the SSPI client * is uninitialized */ public byte[] invokePrepareSSORequest() throws Exception { if (!initialized) { throw new Exception("SSPI Not Initialized"); } return prepareSSORequest(); } /** * Calls <code>#prepareSSOSubmit(byte[], long)</code> to prepare the NTLM TYPE-3 * message. * * @throws Exception if an error occurs during the call or the SSPI client * is uninitialized */ public byte[] invokePrepareSSOSubmit(byte[] buf) throws Exception { if (!initialized) { throw new Exception("SSPI Not Initialized"); } return prepareSSOSubmit(buf, buf.length); } }