1
14
15 package com.liferay.portal.security.ntlm;
16
17 import com.liferay.portal.kernel.log.Log;
18 import com.liferay.portal.kernel.log.LogFactoryUtil;
19 import com.liferay.portal.security.ntlm.msrpc.NetlogonAuthenticator;
20 import com.liferay.portal.security.ntlm.msrpc.NetlogonIdentityInfo;
21 import com.liferay.portal.security.ntlm.msrpc.NetlogonNetworkInfo;
22 import com.liferay.portal.security.ntlm.msrpc.NetlogonValidationSamInfo;
23 import com.liferay.portal.security.ntlm.msrpc.NetrLogonSamLogon;
24 import com.liferay.portal.security.ntlm.msrpc.NetrServerAuthenticate3;
25 import com.liferay.portal.security.ntlm.msrpc.NetrServerReqChallenge;
26
27 import java.io.IOException;
28
29 import java.security.MessageDigest;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.SecureRandom;
32
33 import java.util.Arrays;
34
35 import jcifs.dcerpc.DcerpcBinding;
36 import jcifs.dcerpc.DcerpcHandle;
37 import jcifs.dcerpc.UnicodeString;
38
39 import jcifs.smb.NtlmPasswordAuthentication;
40 import jcifs.smb.SmbException;
41
42 import jcifs.util.DES;
43 import jcifs.util.Encdec;
44 import jcifs.util.HMACT64;
45 import jcifs.util.MD4;
46
47
52 public class Netlogon {
53
54 public Netlogon() {
55 DcerpcBinding.addInterface(
56 "netlogon", "12345678-1234-abcd-ef00-01234567cffb:1.0");
57 }
58
59 public NtlmUserAccount logon(
60 String domain, String userName, String workstation,
61 byte[] serverChallenge, byte[] ntResponse, byte[] lmResponse) {
62
63 try {
64 connect();
65
66 NetlogonAuthenticator netlogonAuthenticator =
67 computeNetlogonAuthenticator();
68
69 NetlogonIdentityInfo netlogonIdentityInfo =
70 new NetlogonIdentityInfo(
71 domain, 0x00000820, 0, 0, userName, workstation);
72
73 NetlogonNetworkInfo netlogonNetworkInfo = new NetlogonNetworkInfo(
74 netlogonIdentityInfo, serverChallenge, ntResponse, lmResponse);
75
76 NetrLogonSamLogon netrLogonSamLogon = new NetrLogonSamLogon(
77 _domainControllerName, _ntlmServiceAccount.getComputerName(),
78 netlogonAuthenticator, new NetlogonAuthenticator(), 2,
79 netlogonNetworkInfo, 2, new NetlogonValidationSamInfo(), 0);
80
81 _handle.sendrecv(netrLogonSamLogon);
82
83 if (netrLogonSamLogon.getStatus() == 0) {
84 NetlogonValidationSamInfo netlogonValidationSamInfo =
85 netrLogonSamLogon.getNetlogonValidationSamInfo();
86
87 UnicodeString name = new UnicodeString(
88 netlogonValidationSamInfo.getEffectiveName(), false);
89
90 return new NtlmUserAccount(name.toString());
91 }
92 else {
93 SmbException smbe = new SmbException(
94 netrLogonSamLogon.getStatus(), false);
95
96 _log.warn(smbe);
97 }
98 }
99 catch (Exception e) {
100 _log.error(e);
101 }
102 finally {
103 try {
104 disconnect();
105 }
106 catch (Exception e) {
107 _log.error(e);
108 }
109 }
110
111 return null;
112 }
113
114 public void setConfiguration(
115 String domainController, String domainControllerName,
116 NtlmServiceAccount ntlmServiceAccount) {
117
118 _domainController = domainController;
119 _domainControllerName = domainControllerName;
120 _ntlmServiceAccount = ntlmServiceAccount;
121 }
122
123 protected NetlogonAuthenticator computeNetlogonAuthenticator() {
124 int timestamp = (int)System.currentTimeMillis();
125 int input = Encdec.dec_uint32le(_clientCredential, 0) + timestamp;
126
127 Encdec.enc_uint32le(input, _clientCredential, 0);
128
129 byte[] credential = computeNetlogonCredential(
130 _clientCredential, _sessionKey);
131
132 return new NetlogonAuthenticator(credential, timestamp);
133 }
134
135 protected byte[] computeNetlogonCredential(
136 byte[] input, byte[] sessionKey) {
137
138 byte[] k1 = new byte[7];
139 byte[] k2 = new byte[7];
140
141 System.arraycopy(sessionKey, 0, k1, 0, 7);
142 System.arraycopy(sessionKey, 7, k2, 0, 7);
143
144 DES k3 = new DES(k1);
145 DES k4 = new DES(k2);
146
147 byte[] output1 = new byte[8];
148 byte[] output2 = new byte[8];
149
150 k3.encrypt(input, output1);
151 k4.encrypt(output1, output2);
152
153 return output2;
154 }
155
156 protected byte[] computeSessionKey(
157 byte[] sharedSecret, byte[] clientChallenge, byte[] serverChallenge) {
158
159 try {
160 MessageDigest messageDigest = MessageDigest.getInstance("MD5");
161
162 byte[] zeroes = {0, 0, 0, 0};
163
164 messageDigest.update(zeroes, 0, 4);
165 messageDigest.update(clientChallenge, 0, 8);
166 messageDigest.update(serverChallenge, 0, 8);
167
168 HMACT64 hmact64 = new HMACT64(sharedSecret);
169
170 hmact64.update(messageDigest.digest());
171
172 return hmact64.digest();
173 }
174 catch (NoSuchAlgorithmException nsae) {
175 _log.error(nsae);
176 }
177
178 return null;
179 }
180
181 protected void connect() throws IOException {
182 NtlmPasswordAuthentication ntlmPasswordAuthentication =
183 new NtlmPasswordAuthentication(
184 null, _ntlmServiceAccount.getAccount(),
185 _ntlmServiceAccount.getPassword());
186
187 String endpoint =
188 "ncacn_np:" + _domainController + "[\\PIPE\\NETLOGON]";
189
190 _handle = DcerpcHandle.getHandle(endpoint, ntlmPasswordAuthentication);
191
192 _handle.bind();
193
194 byte[] clientChallenge = new byte[8];
195
196 _secureRandom.nextBytes(clientChallenge);
197
198 NetrServerReqChallenge netrServerReqChallenge =
199 new NetrServerReqChallenge(
200 _domainControllerName, _ntlmServiceAccount.getComputerName(),
201 clientChallenge, new byte[8]);
202
203 _handle.sendrecv(netrServerReqChallenge);
204
205 MD4 md4 = new MD4();
206
207 md4.update(_ntlmServiceAccount.getPassword().getBytes("UTF-16LE"));
208
209 byte[] sessionKey = computeSessionKey(
210 md4.digest(), clientChallenge,
211 netrServerReqChallenge.getServerChallenge());
212
213 byte[] clientCredential = computeNetlogonCredential(
214 clientChallenge, sessionKey);
215
216 NetrServerAuthenticate3 netrServerAuthenticate3 =
217 new NetrServerAuthenticate3(
218 _domainControllerName, _ntlmServiceAccount.getAccountName(), 2,
219 _ntlmServiceAccount.getComputerName(), clientCredential,
220 new byte[8], 0xFFFFFFFF);
221
222 _handle.sendrecv(netrServerAuthenticate3);
223
224 byte[] serverCredential = computeNetlogonCredential(
225 netrServerReqChallenge.getServerChallenge(), sessionKey);
226
227 if (!Arrays.equals(
228 serverCredential,
229 netrServerAuthenticate3.getServerCredential())) {
230
231 _log.error("Session key negotiation failed");
232
233 return;
234 }
235
236 _clientCredential = clientCredential;
237 _sessionKey = sessionKey;
238 }
239
240 protected void disconnect() throws IOException {
241 if (_handle != null) {
242 _handle.close();
243
244 _handle = null;
245 }
246 }
247
248 private static Log _log = LogFactoryUtil.getLog(Netlogon.class);
249
250 private byte[] _clientCredential;
251 private String _domainController;
252 private String _domainControllerName;
253 private DcerpcHandle _handle;
254 private NtlmServiceAccount _ntlmServiceAccount;
255 private SecureRandom _secureRandom = new SecureRandom();
256 private byte[] _sessionKey;
257
258 }