diff --git a/src/share/classes/com/sun/security/ntlm/Client.java b/src/share/classes/com/sun/security/ntlm/Client.java index ba3e90c3858a360d69d4ee07c324f94bf828ed2d..9aacd433793c9e1ba3279e63e47b50015894b970 100644 --- a/src/share/classes/com/sun/security/ntlm/Client.java +++ b/src/share/classes/com/sun/security/ntlm/Client.java @@ -46,7 +46,7 @@ public final class Client extends NTLM { 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 @@ public final class Client extends NTLM { } 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 final class Client extends NTLM { */ 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 @@ public final class Client extends NTLM { 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 @@ public final class Client extends NTLM { 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 --git a/src/share/classes/com/sun/security/ntlm/Server.java b/src/share/classes/com/sun/security/ntlm/Server.java index 0593b2e1c8982febf76b28eb485599adb2ff6e63..adec1a3fa29eb7ce9a761d74813d5bb6fe9862be 100644 --- a/src/share/classes/com/sun/security/ntlm/Server.java +++ b/src/share/classes/com/sun/security/ntlm/Server.java @@ -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 @@ public abstract class Server extends NTLM { 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 @@ public abstract class Server extends NTLM { "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 @@ public abstract class Server extends NTLM { } } 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 --git a/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java b/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java index dbb1d610d317e4faaf4dd9d283b2a83b85ec1d6c..2cf561c0d3ce8934502c87bcaed7d04127033759 100644 --- a/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java +++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java @@ -160,9 +160,17 @@ final class NTLMClient implements SaslClient { } } 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 --git a/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java b/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java index 9589abd358e30530ef7e8a03484075d708164f1a..c1a8eb6d59590eea79c9a6380fd14d847736723b 100644 --- a/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java +++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java @@ -141,8 +141,10 @@ final class NTLMServer implements SaslServer { 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 --git a/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 3554d31c558412a3a5fca8172b3543e124416b86..6211811e512cb2ee167887f694048b055e535eb8 100644 --- a/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -77,8 +77,7 @@ public class NTLMAuthentication extends AuthenticationInfo { 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 class NTLMAuthentication extends AuthenticationInfo { 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 --git a/test/com/sun/security/sasl/ntlm/NTLMTest.java b/test/com/sun/security/sasl/ntlm/NTLMTest.java index 64f5eae184c1e9ddf8c509ee5922ccdc4d153d0a..46d2f0413832b4b045d06db12eac25f6dde41065 100644 --- a/test/com/sun/security/sasl/ntlm/NTLMTest.java +++ b/test/com/sun/security/sasl/ntlm/NTLMTest.java @@ -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 @@ public class NTLMTest { checkAuthOnly(); checkClientNameOverride(); - checkServerDomainOverride(); checkClientDomainOverride(); checkVersions(); checkClientHostname(); @@ -116,15 +115,12 @@ public class NTLMTest { 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 @@ public class NTLMTest { 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 class NTLMTest { 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 @@ public class NTLMTest { */ 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 @@ public class NTLMTest { } }); - 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 {