7150092: NTLM authentication fail if user specified a different realm
Reviewed-by: michaelm
This commit is contained in:
parent
fb3cf81241
commit
cdbe91ef12
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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<String,Object> 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<String,Object> 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<String,Object> 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user