=============================================================================== Windows Single Sign On in jTDS ~~~~~~~~~~~~~~~ Patch Submitted by Magendran Sathaiah (mahi@aztec.soft.net) =============================================================================== Introduction ============ This document describes the design of the Single Sign On implementation in the jTDS JDBC driver. (Note: This feature requires DES and MD5 implementations. The JCA/JCE is used to access such implementations. The algorithms were previously implemented directly in jTDS' sources, but to eliminate export control restrictions, they were removed and the code now uses the JCA/JCE. Note that MD4 is still implemented directly in jTDS.) Releases 0.9.1 and earlier of jTDS driver support Windows authentication by means of the NTLM protocol. That is, clients using the JDBC Driver passes a valid Windows-Domain-Name, a Windows User and Windows Password; the JDBC driver will submit these to Microsoft SQL Server via NTLM protocol in order to gain access to the database. (This approach still works with all later versions, allowing Windows Authentication to work for non-Windows clients or clients that don't/can't have the native library installed.) In the above approach the client will have to maintain a configuration file to keep the windows logon credentials. That is, the domain name, user name and password need to be stored in encrypted or plain text format. This might not be an acceptable solution for everybody. Starting with release 0.9.2 jTDS is capable of using the Windows credentials of the current user under whose account the client program is running to login to SQL Server (Windows Single Sign On). Using Windows Single Sign On (SSO) clients will be able to connect to Microsoft SQL Server without providing credentials. It would dynamically read current user's credentials and connect to the database. provided that the Windows account has enough rights in the database. This is done using a native (Windows-only) library, ntlmauth.dll. Installation ============ In order for Single Sign On to work, jTDS must be able to load the native SPPI library (ntlmauth.dll). Place this DLL anywhere in the system path (defined by the PATH system variable) and you're all set. Usage ===== In order to set up the jTDS driver to use Windows Single Sign On, users will have to connect without providing a user name and password. This will only work on Windows. Driver example: // No user name or password in URL or as parameters DriverManager.getConnection( "jdbc:jtds:sqlserver://localhost:1433/LionKing"); DataSource example: ds = new JtdsDataSource(); ds.setDescription("test"); // MS SQL Server Host Name ds.setServerName("localhost"); // Port ds.setPortNumber(1433); // Database Name ds.setDatabaseName("LionKing"); // No domain name // No user name Connection conn = ds.getConnection(); Design ====== The patch comprises the following components: 1. ntlmauth.dll A CPP Program that uses SSPI Windows APIs to accquire credentials and NTLM messages from the Windows Operating System. 2. SSPIJNIClient.java A Java Native Interface class that bridges jTDS JDBC driver and ntlmauth.dll. 3. Modified Version jTDS source files. A set of modified jTDS java files that make use of the SSPIJNIClient.java when the driver is set to use Windows Single Sign On. SSPIJNIClient.java ================== It loads the DLL (ntlmauth.dll) in a static block. The ntlmauth.dll must be available in the system path (defined by the system variable PATH). It exposes the following APIs: public static SSPIJNIClient getInstance() throws Exception; Retuns the singleton SSPIJNIClient object. private native void initialize(); Initializes the SSPI Client. private native void unInitialize(); Uninitializes the SSPI client. private native byte[] prepareSSORequest(); Prepares NTLM TYPE-1 message and returns it as a byte[]. private native byte[] prepareSSOSubmit(byte[] challengeBuf, long size); Prepares NTLM TYPE-3 message using current user's credentials. It needs the challenge BLOB and its size as input. The challenge BLOB is nothing but the TYPE-2 message that is received from the SQL Server. API Usage: ---------- ntlmAuthSSO = (user == null || user.length() == 0); if (ntlmAuthSSO) { sspiJNIClient = SSPIJNIClient.getInstance(); ntlm1 = sspiJNIClient.invokePrepareSSORequest(); } // 1.ntlm1 contains Type-1 message now // 2.Send Type-1 Message to the server // // 3.MS SQL Server replies back with Type-2 message // 4.Read Type-2 Message in (say) ntlm2 ntlm3 = sspiJNIClient.invokePrepareSSOSubmit(ntlm2); //1.now, ntlm3 contains Type-3 message //2.Send, Type-3 message to the Server. //3.Check the status - Success | Failure. Modifications to jTDS Classes ============================= The TdsCode.java has been modified as follows 1. Member boolean variable: ntlmAuthSSO A flag that is used to indicate if the client wants to do Windows Single Sign On. The variable is set in the logon(...) as below ntlmAuthSSO = (user == null || user.length() == 0); Note: The user must leave the user name (and password) unset or set them to null or a blank string to instructthe driver to use Windows Single Sign On. 2. Member Variable: sspiJNIClient A reference to the single-ton object of SSPIJNIClient.class It gets initialzied in logon(..) if ntlmAuthSSO is true. 3. login(..) At the begining of the method check if Windows Single Sign On is requested (ntlmAuth == true) If so initialize the SSPI client and prepare NTLM TYPE-1 message 4. send70Login(..) Modified to accept an additional byte[] parameter to pass the NTLM Type-1 message. Set the authLen = ntlmMessage.legnth() if ntlmAuthSSO is true 5. sendNtlmChallengeResponse(...) If ntlmAuthSSO is true, then read the Type-2 message from authToken.getNTLMMessage() Prepare Type-3 message as below type3 = sspiJNIClient.invokePrepareSSOSubmit(type2) Then append it to the command buffer. ------------------------------------------------------------------------------------------------------ Magendran Sathaiah mahi@aztec.soft.net Version: $Id: README.SSO,v 1.1 2004-12-21 12:06:59 alin_sinpalean Exp $