Reputation: 153
I have a site with SSO, which is using NTLM authentication, which was working perfectly so far on XP and win 7 (32bit), but recently my company decided to use win 7 (64bit) computers as well. On these PCs, the handshake ends after type 2 message, and tomcat returns 401. I have no clue how to investigate, maybe someone here can give me some tips.
This is in the servlet's doPost method:
try {
// NTLM Handshake
// 1: Client --> Server | GET ...
// 2: Client <-- Server | 401 Unauthorized/WWW-Authenticate: NTLM
String auth = request.getHeader("Authorization");
if (auth == null) {
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM");
response.flushBuffer();
return;
}
if (auth.startsWith("NTLM ")) {
byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth
.substring(5));
int off = 0, length, offset;
// 3: Client --> Server | GET .../Authorization: NTLM
// <base64-encoded type-1-message>
if (msg[8] == 1) {
// 4: Client <-- Server | 401 Unauthorized/WWW-Authenticate:
// NTLM <base64-encoded type-2-message>
byte z = 0;
byte[] msg1 = { (byte) 'N', (byte) 'T', (byte) 'L',
(byte) 'M', (byte) 'S', (byte) 'S', (byte) 'P', z,
(byte) 2, z, z, z, z, z, z, z, (byte) 40, z, z, z,
(byte) 1, (byte) 130, z, z, z, (byte) 2, (byte) 2,
(byte) 2, z, z, z, z, z, z, z, z, z, z, z, z };
response.setHeader("WWW-Authenticate", "NTLM "
+ new sun.misc.BASE64Encoder().encodeBuffer(msg1));
//response.sendError(response.SC_UNAUTHORIZED);
response.setStatus(response.SC_UNAUTHORIZED);
response.flushBuffer();
return;
}
// 5: Client --> Server | GET .../Authorization: NTLM
// <base64-encoded type-3-message>
else if (msg[8] == 3) {
off = 30;
length = msg[off + 17] * 256 + msg[off + 16];
offset = msg[off + 19] * 256 + msg[off + 18];
String remoteHost = new String(msg, offset, length);
length = msg[off + 1] * 256 + msg[off];
offset = msg[off + 3] * 256 + msg[off + 2];
String domain = new String(msg, offset, length);
for (int i = 0; i < domain.length(); i += 2)
loginDomain += domain.charAt(i);
length = msg[off + 9] * 256 + msg[off + 8];
offset = msg[off + 11] * 256 + msg[off + 10];
String username = new String(msg, offset, length);
for (int i = 0; i < username.length(); i += 2)
loginUser += username.charAt(i);
}
}
} catch (Exception se) {
log.error(loginUser + ", NTLM handshake exception:", se);
}
Upvotes: 3
Views: 7249
Reputation: 71
Try this
Enable NTLM Extended Security using below code
byte[] msg1 = {
(byte) 'N', (byte) 'T', (byte) 'L', (byte) 'M',
(byte) 'S', (byte) 'S', (byte) 'P',
z, (byte) 2, z, z, z, z, z, z, z, (byte) 40, z, z, z,
(byte) 1, (byte) 130, **(byte) 8**, z, z, (byte) 2, (byte) 2,
(byte) 2, z, z, z, z, z, z, z, z, z, z, z, z
};
Upvotes: 5
Reputation: 15
If you still want to insist with JCIFS try these links to overcome the "Invalid parameter error" and "Failed to negotiate with a suitable domain controller for". It works with NTLM but is not guaranteed to work with NTLMv2 more secure.
"Invalid parameter" https://www.sysaid.com/Sysforums/posts/list/9065.page .
"Failed to negotiate with a suitable domain controller for" https://lists.samba.org/archive/jcifs/2005-August/005312.html
Upvotes: 1
Reputation: 4260
Most corporate network will have moved over to NTLMv2. We ran into this problem a while ago and have acquired Jespa from http://www.ioplex.com/. As long as you have a Servlet stack, it works just fine. If you're using a non-Java EE stack like Play, I'm not aware of a solution other than turning down support to NTLMv1.
Upvotes: 0
Reputation: 153
It was a policy issue on the 64 bit PCs as NTLMv2 was forced. Solution is to disable these setting in security policy.
• Run "secpol.msc" This should bring up a window titled "Local Security Policy"
• Security Settings > Local Policies >Security Options > "Network Security: Minimum session security for NTLM SSP based …"
There are two similar entries which begins like this, open and uncheck "Require NTLMv2 session security".
At least it turned out we are using NTLMv1. :|
Upvotes: 2