# HG changeset patch # User weijun # Date 1404889842 -28800 # Node ID 5e73c95f95db5ce11aa298c5703ac8fa0b8049fc # Parent 4c004dfa3340018f77d69b77babbbbc5919b02d3 7150092: NTLM authentication fail if user specified a different realm Reviewed-by: michaelm diff -r 4c004dfa3340 -r 5e73c95f95db jdk/src/share/classes/com/sun/security/ntlm/Client.java --- a/jdk/src/share/classes/com/sun/security/ntlm/Client.java Tue Jul 08 12:38:47 2014 -0700 +++ b/jdk/src/share/classes/com/sun/security/ntlm/Client.java Wed Jul 09 15:10:42 2014 +0800 @@ -46,7 +46,7 @@ final private String hostname; final private String username; - private String domain; // might be updated by Type 2 msg + private String domain; private byte[] pw1, pw2; /** @@ -82,7 +82,7 @@ } this.hostname = hostname; this.username = username; - this.domain = domain; + this.domain = domain == null ? "" : domain; this.pw1 = getP1(password); this.pw2 = getP2(password); debug("NTLM Client: (h,u,t,version(v)) = (%s,%s,%s,%s(%s))\n", @@ -95,19 +95,13 @@ */ public byte[] type1() { Writer p = new Writer(1, 32); - int flags = 0x8203; - if (hostname != null) { - flags |= 0x2000; - } - if (domain != null) { - flags |= 0x1000; - } + // Negotiate always sign, Negotiate NTLM, + // Request Target, Negotiate OEM, Negotiate unicode + int flags = 0x8207; if (v != Version.NTLM) { flags |= 0x80000; } p.writeInt(12, flags); - p.writeSecurityBuffer(24, hostname, false); - p.writeSecurityBuffer(16, domain, false); debug("NTLM Client: Type 1 created\n"); debug(p.getBytes()); return p.getBytes(); @@ -133,13 +127,10 @@ byte[] challenge = r.readBytes(24, 8); int inputFlags = r.readInt(20); boolean unicode = (inputFlags & 1) == 1; - String domainFromServer = r.readSecurityBuffer(12, unicode); - if (domainFromServer != null) { - domain = domainFromServer; - } - if (domain == null) { - domain = ""; - } + + // IE uses domainFromServer to generate an alist if server has not + // provided one. Firefox/WebKit do not. Neither do we. + //String domainFromServer = r.readSecurityBuffer(12, unicode); int flags = 0x88200 | (inputFlags & 3); Writer p = new Writer(3, 64); @@ -163,7 +154,9 @@ if (writeLM) lm = calcV2(nthash, username.toUpperCase(Locale.US)+domain, nonce, challenge); if (writeNTLM) { - byte[] alist = type2.length > 48 ? + // Some client create a alist even if server does not send + // one: (i16)2 (i16)len target_in_unicode (i16)0 (i16) 0 + byte[] alist = ((inputFlags & 0x800000) != 0) ? r.readSecurityBuffer(40) : new byte[0]; byte[] blob = new byte[32+alist.length]; System.arraycopy(new byte[]{1,1,0,0,0,0,0,0}, 0, blob, 0, 8); diff -r 4c004dfa3340 -r 5e73c95f95db jdk/src/share/classes/com/sun/security/ntlm/Server.java --- a/jdk/src/share/classes/com/sun/security/ntlm/Server.java Tue Jul 08 12:38:47 2014 -0700 +++ b/jdk/src/share/classes/com/sun/security/ntlm/Server.java Wed Jul 09 15:10:42 2014 +0800 @@ -1,3 +1,4 @@ + /* * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -92,7 +93,9 @@ debug("NTLM Server: Type 1 received\n"); if (type1 != null) debug(type1); Writer p = new Writer(2, 32); - int flags = 0x80205; + // Negotiate NTLM2 Key, Target Type Domain, + // Negotiate NTLM, Request Target, Negotiate unicode + int flags = 0x90205; p.writeSecurityBuffer(12, domain, true); p.writeInt(20, flags); p.writeBytes(24, nonce); @@ -127,8 +130,9 @@ "Wrong domain: " + incomingDomain + " vs " + domain); // Needed? }*/ + boolean verified = false; - char[] password = getPassword(domain, username); + char[] password = getPassword(incomingDomain, username); if (password == null) { throw new NTLMException(NTLMException.USER_UNKNOWN, "Unknown user"); @@ -179,6 +183,8 @@ } } if (incomingNTLM.length > 0) { + // We didn't sent alist in type2(), so there + // is nothing to check here. byte[] clientBlob = Arrays.copyOfRange( incomingNTLM, 16, incomingNTLM.length); byte[] ntlmresponse = calcV2(nthash, diff -r 4c004dfa3340 -r 5e73c95f95db jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java --- a/jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java Tue Jul 08 12:38:47 2014 -0700 +++ b/jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java Wed Jul 09 15:10:42 2014 +0800 @@ -160,9 +160,17 @@ } } try { + String name = ncb.getName(); + if (name == null) { + name = authzid; + } + String domain = dcb.getText(); + if (domain == null) { + domain = serverName; + } client = new Client(version, hostname, - ncb.getName(), - dcb.getText(), + name, + domain, pcb.getPassword()); } catch (NTLMException ne) { throw new SaslException( diff -r 4c004dfa3340 -r 5e73c95f95db jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java --- a/jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java Tue Jul 08 12:38:47 2014 -0700 +++ b/jdk/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java Wed Jul 09 15:10:42 2014 +0800 @@ -141,8 +141,10 @@ server = new Server(version, domain) { public char[] getPassword(String ntdomain, String username) { try { - RealmCallback rcb = new RealmCallback( - "Domain: ", ntdomain); + RealmCallback rcb = + (ntdomain == null || ntdomain.isEmpty()) + ? new RealmCallback("Domain: ") + : new RealmCallback("Domain: ", ntdomain); NameCallback ncb = new NameCallback( "Name: ", username); PasswordCallback pcb = new PasswordCallback( diff -r 4c004dfa3340 -r 5e73c95f95db jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java --- a/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Tue Jul 08 12:38:47 2014 -0700 +++ b/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Wed Jul 09 15:10:42 2014 +0800 @@ -77,8 +77,7 @@ static { defaultDomain = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", - "domain")); + new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", "")); }; public static boolean supportsTransparentAuth () { @@ -100,17 +99,13 @@ public String run() { String localhost; try { - localhost = InetAddress.getLocalHost().getHostName().toUpperCase(); + localhost = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { localhost = "localhost"; } return localhost; } }); - int x = hostname.indexOf ('.'); - if (x != -1) { - hostname = hostname.substring (0, x); - } }; PasswordAuthentication pw; diff -r 4c004dfa3340 -r 5e73c95f95db jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java --- a/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Tue Jul 08 12:38:47 2014 -0700 +++ b/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Wed Jul 09 15:10:42 2014 +0800 @@ -23,7 +23,7 @@ /* * @test - * @bug 6911951 + * @bug 6911951 7150092 * @summary NTLM should be a supported Java SASL mechanism */ import java.io.IOException; @@ -59,7 +59,6 @@ checkAuthOnly(); checkClientNameOverride(); - checkServerDomainOverride(); checkClientDomainOverride(); checkVersions(); checkClientHostname(); @@ -116,15 +115,12 @@ Map ps = new HashMap<>(); ps.put("com.sun.security.sasl.ntlm.version", vs); SaslClient clnt = Sasl.createSaslClient( - new String[]{MECH}, USER1, PROTOCOL, null, pc, + new String[]{MECH}, USER1, PROTOCOL, REALM, pc, new CallbackHandler() { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback cb: callbacks) { - if (cb instanceof NameCallback) { - NameCallback ncb = (NameCallback)cb; - ncb.setName(ncb.getDefaultName()); - } else if (cb instanceof PasswordCallback) { + if (cb instanceof PasswordCallback) { ((PasswordCallback)cb).setPassword(PASS1); } } @@ -159,15 +155,12 @@ Map pc = new HashMap<>(); pc.put("com.sun.security.sasl.ntlm.hostname", "this.is.com"); SaslClient clnt = Sasl.createSaslClient( - new String[]{MECH}, USER1, PROTOCOL, null, pc, + new String[]{MECH}, USER1, PROTOCOL, REALM, pc, new CallbackHandler() { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback cb: callbacks) { - if (cb instanceof NameCallback) { - NameCallback ncb = (NameCallback)cb; - ncb.setName(ncb.getDefaultName()); - } else if (cb instanceof PasswordCallback) { + if (cb instanceof PasswordCallback) { ((PasswordCallback)cb).setPassword(PASS1); } } @@ -212,12 +205,8 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback cb: callbacks) { - if (cb instanceof NameCallback) { - NameCallback ncb = (NameCallback)cb; - ncb.setName(ncb.getDefaultName()); - } else if(cb instanceof RealmCallback) { - RealmCallback dcb = (RealmCallback)cb; - dcb.setText("THIRDDOMAIN"); + if (cb instanceof RealmCallback) { + ((RealmCallback)cb).setText(REALM); } else if (cb instanceof PasswordCallback) { ((PasswordCallback)cb).setPassword(PASS1); } @@ -255,13 +244,13 @@ */ private static void checkClientNameOverride() throws Exception { SaslClient clnt = Sasl.createSaslClient( - new String[]{MECH}, null, PROTOCOL, null, null, + new String[]{MECH}, "someone", PROTOCOL, REALM, null, new CallbackHandler() { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback cb: callbacks) { if (cb instanceof NameCallback) { - NameCallback ncb = (NameCallback)cb; + NameCallback ncb = (NameCallback) cb; ncb.setName(USER1); } else if (cb instanceof PasswordCallback) { ((PasswordCallback)cb).setPassword(PASS1); @@ -270,54 +259,7 @@ } }); - SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, REALM, null, - new CallbackHandler() { - public void handle(Callback[] callbacks) - throws IOException, UnsupportedCallbackException { - String domain = null, name = null; - PasswordCallback pcb = null; - for (Callback cb: callbacks) { - if (cb instanceof NameCallback) { - name = ((NameCallback)cb).getDefaultName(); - } else if (cb instanceof RealmCallback) { - domain = ((RealmCallback)cb).getDefaultText(); - } else if (cb instanceof PasswordCallback) { - pcb = (PasswordCallback)cb; - } - } - if (pcb != null) { - pcb.setPassword(getPass(domain, name)); - } - } - }); - - handshake(clnt, srv); - } - - /** - * server side domain provided in props. - * @throws Exception - */ - private static void checkServerDomainOverride() throws Exception { - SaslClient clnt = Sasl.createSaslClient( - new String[]{MECH}, USER1, PROTOCOL, null, null, - new CallbackHandler() { - public void handle(Callback[] callbacks) - throws IOException, UnsupportedCallbackException { - for (Callback cb: callbacks) { - if (cb instanceof NameCallback) { - NameCallback ncb = (NameCallback)cb; - ncb.setName(ncb.getDefaultName()); - } else if (cb instanceof PasswordCallback) { - ((PasswordCallback)cb).setPassword(PASS1); - } - } - } - }); - - Map ps = new HashMap<>(); - ps.put("com.sun.security.sasl.ntlm.domain", REALM); - SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, null, ps, + SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, "FAKE", null, new CallbackHandler() { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {