// 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.jdbc; import net.sourceforge.jtds.jdbc.NtlmAuth; import java.util.Arrays; /** * Unit test for NTLM challenge/response calculation * * @author mdb * @version $Id: NtlmAuthTest.java,v 1.5.2.1 2009-08-04 10:33:54 ickzon Exp $ */ public class NtlmAuthTest extends TestBase { public NtlmAuthTest(String name) { super(name); } public static byte[] hexToBytes(String hex) { byte[] rtn = new byte[hex.length() / 2]; for(int i=0; i < rtn.length; i++) { rtn[i] = (byte)Integer.parseInt(hex.substring(i*2,(i+1)*2),16); } return rtn; } /** * Tests the NT challenge/response against a known-good value. This was captured * from a successful login to one of my (mdb's) test computers. */ public void testChallengeResponse() throws Exception { final String password = "bark"; byte[] challenge = new byte[] { (byte)0xd9, (byte)0x90, (byte)0xed, (byte)0xaf, (byte)0x94, (byte)0x17, (byte)0x36, (byte)0xaf}; byte[] ntResp = NtlmAuth.answerNtChallenge(password, challenge); byte[] lmResp = NtlmAuth.answerLmChallenge(password, challenge); byte[] ntExpected = new byte[] { (byte)0x8e, (byte)0x75, (byte)0x8e, (byte)0x79, (byte)0xe2, (byte)0xa1, (byte)0x45, (byte)0x75, (byte)0xb4, (byte)0x21, (byte)0x55, (byte)0x9b, (byte)0x12, (byte)0x29, (byte)0xd3, (byte)0x5a, (byte)0x23, (byte)0x8b, (byte)0x7d, (byte)0xa8, (byte)0x3a, (byte)0x50, (byte)0xc6, (byte)0xa7}; byte[] lmExpected = new byte[] { (byte)0xe6, (byte)0x19, (byte)0x92, (byte)0xcd, (byte)0x84, (byte)0xf7, (byte)0xb8, (byte)0x49, (byte)0xaf, (byte)0x75, (byte)0xf9, (byte)0x37, (byte)0xd4, (byte)0x0b, (byte)0xe6, (byte)0x81, (byte)0xc4, (byte)0x0c, (byte)0x7c, (byte)0x3f, (byte)0x3e, (byte)0xc6, (byte)0x8b, (byte)0x7f}; assertTrue(Arrays.equals(ntResp, ntExpected)); assertTrue(Arrays.equals(lmResp, lmExpected)); } //-------------------------------------------------------------------------- // these tests came from the web page: // http://davenport.sourceforge.net/ntlm.html //-------------------------------------------------------------------------- public void testLMv2() throws Exception { byte[] answer = NtlmAuth.answerLmv2Challenge( "DOMAIN", "user", "SecREt01", hexToBytes("0123456789abcdef"), hexToBytes("ffffff0011223344")); byte[] expected = hexToBytes( "d6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344"); assertTrue(Arrays.equals(answer, expected)); } public void testNTLMv2() throws Exception { byte[] answer = NtlmAuth.answerNtlmv2Challenge( "DOMAIN", "user", "SecREt01", hexToBytes("0123456789abcdef"), //nonce //target info: hexToBytes("02000c0044004f004d00410049004e0001000c005300450052" + "005600450052000400140064006f006d00610069006e002e00" + "63006f006d00030022007300650072007600650072002e0064" + "006f006d00610069006e002e0063006f006d0000000000"), hexToBytes("ffffff0011223344"),//client nonce 1055844000000L); //timestamp byte[] expected = hexToBytes( "cbabbca713eb795d04c97abc01ee4983" + "01010000000000000090d336b734c301" + "ffffff00112233440000000002000c00" + "44004f004d00410049004e0001000c00" + "53004500520056004500520004001400" + "64006f006d00610069006e002e006300" + "6f006d00030022007300650072007600" + "650072002e0064006f006d0061006900" + "6e002e0063006f006d00000000000000" + "0000"); assertTrue(Arrays.equals(answer, expected)); } public void testTimestampConversion() throws Exception { long time = 1055844000000L; byte[] ts = NtlmAuth.createTimestamp(time); byte[] expected = hexToBytes("0090d336b734c301"); assertTrue(Arrays.equals(ts, expected)); } //-------------------------------------------------------------------------- // these came from tests with real data: //-------------------------------------------------------------------------- public void testLMv2CapturedData() throws Exception { byte[] answer = NtlmAuth.answerLmv2Challenge( "MDB-PADRE", "dog", "bark", hexToBytes("73f35b0fe01a5a31"), hexToBytes("2c66391a0a1b7881")); byte[] expected = hexToBytes( "4dc364696984b6e07df1a659313f277a2c66391a0a1b7881"); assertTrue(Arrays.equals(answer, expected)); } public void testNTLMv2CapturedData() throws Exception { byte[] targetInfo = hexToBytes( "02000c004200450041004500" + "4e004700010014004d00440042002d00" + "42005200450057004500520004002200" + "62006500610065006e0067002e006d00" + "6600650065006e0067002e006f007200" + "6700030038006d00640062002d006200" + "720065007700650072002e0062006500" + "610065006e0067002e006d0066006500" + "65006e0067002e006f00720067000500" + "14006d006600650065006e0067002e00" + "6f007200670000000000"); byte[] answer = NtlmAuth.answerNtlmv2Challenge( "MDB-PADRE", "dog", "bark", hexToBytes("73f35b0fe01a5a31"), targetInfo, hexToBytes("2c66391a0a1b7881"), hexToBytes("06198e3a444dc601")); byte[] expected = hexToBytes( "5416e7ef86091320" + "5b652f7b3002fc7f0101000000000000" + "06198e3a444dc6012c66391a0a1b7881" + "0000000002000c004200450041004500" + "4e004700010014004d00440042002d00" + "42005200450057004500520004002200" + "62006500610065006e0067002e006d00" + "6600650065006e0067002e006f007200" + "6700030038006d00640062002d006200" + "720065007700650072002e0062006500" + "610065006e0067002e006d0066006500" + "65006e0067002e006f00720067000500" + "14006d006600650065006e0067002e00" + "6f00720067000000000000000000"); //debug... /* //debug public static void dump(byte[] bytes, String fileName) { try { FileOutputStream out = new FileOutputStream(fileName); out.write( bytes ); out.close(); } catch(Exception e) { //don't worry about it } } dump(expected, "/home/brinkley/tmp/ntlm2-expected" ); dump(answer, "/home/brinkley/tmp/ntlm2-answer" ); */ assertTrue(Arrays.equals(answer, expected)); } }