1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
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.kernel.util.ArrayUtil;
20  import com.liferay.portal.kernel.util.StringPool;
21  
22  import java.io.UnsupportedEncodingException;
23  
24  import java.security.MessageDigest;
25  
26  import jcifs.ntlmssp.NtlmFlags;
27  import jcifs.ntlmssp.Type1Message;
28  import jcifs.ntlmssp.Type2Message;
29  import jcifs.ntlmssp.Type3Message;
30  
31  import jcifs.util.Encdec;
32  
33  /**
34   * <a href="NtlmManager.java.html"><b><i>View Source</i></b></a>
35   *
36   * @author Marcellus Tavares
37   */
38  public class NtlmManager {
39  
40      public NtlmManager(
41          String domain, String domainController, String domainControllerName,
42          String serviceAccount, String servicePassword) {
43  
44          setConfiguration(
45              domain, domainController, domainControllerName, serviceAccount,
46              servicePassword);
47      }
48  
49      public NtlmUserAccount authenticate(
50          byte[] material, byte[] serverChallenge) {
51  
52          try {
53              Type3Message type3Message = new Type3Message(material);
54  
55              if (type3Message.getFlag(
56                      _NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY) &&
57                  (type3Message.getNTResponse().length == 24)) {
58  
59                  MessageDigest messageDigest = MessageDigest.getInstance("MD5");
60  
61                  byte[] bytes = new byte[16];
62  
63                  System.arraycopy(serverChallenge, 0, bytes, 0, 8);
64                  System.arraycopy(type3Message.getLMResponse(), 0, bytes, 8, 8);
65  
66                  messageDigest.update(bytes);
67  
68                  serverChallenge = messageDigest.digest();
69              }
70  
71               return _netlogon.logon(
72                   type3Message.getDomain(), type3Message.getUser(),
73                   type3Message.getWorkstation(),
74                   serverChallenge, type3Message.getNTResponse(),
75                   type3Message.getLMResponse());
76          }
77          catch (Exception e) {
78              _log.error(e, e);
79  
80              return null;
81          }
82      }
83  
84      public String getDomain() {
85          return _domain;
86      }
87  
88      public String getDomainController() {
89          return _domainController;
90      }
91  
92      public String getDomainControllerName() {
93          return _domainControllerName;
94      }
95  
96      public String getServiceAccount() {
97          return _ntlmServiceAccount.getAccount();
98      }
99  
100     public String getServicePassword() {
101         return _ntlmServiceAccount.getPassword();
102     }
103 
104     public byte[] negotiate(byte[] material, byte[] serverChallenge) {
105         try {
106             Type1Message type1Message = new Type1Message(material);
107 
108             Type2Message type2Message = new Type2Message(
109                 type1Message.getFlags(), serverChallenge, _domain);
110 
111             if (type2Message.getFlag(
112                     _NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY)) {
113 
114                 type2Message.setFlag(NtlmFlags.NTLMSSP_NEGOTIATE_LM_KEY, false);
115                 type2Message.setFlag(
116                     NtlmFlags.NTLMSSP_NEGOTIATE_TARGET_INFO, true);
117                 type2Message.setTargetInformation(getTargetInformation());
118             }
119 
120             return type2Message.toByteArray();
121         }
122         catch (Exception e) {
123             _log.error(e, e);
124 
125             return null;
126         }
127     }
128 
129     public void setConfiguration(
130         String domain, String domainController, String domainControllerName,
131         String serviceAccount, String servicePassword) {
132 
133         _domain = domain;
134         _domainController = domainController;
135         _domainControllerName = domainControllerName;
136         _ntlmServiceAccount = new NtlmServiceAccount(
137             serviceAccount, servicePassword);
138 
139         _netlogon.setConfiguration(
140             domainController, domainControllerName, _ntlmServiceAccount);
141     }
142 
143     protected byte[] getAVPairBytes(int avId, String value)
144         throws UnsupportedEncodingException{
145 
146         byte[] valueBytes = value.getBytes("UTF-16LE");
147         byte[] avPairBytes = new byte[4 + valueBytes.length];
148 
149         Encdec.enc_uint16le((short)avId, avPairBytes, 0);
150         Encdec.enc_uint16le((short)valueBytes.length, avPairBytes, 2);
151 
152         System.arraycopy(valueBytes, 0, avPairBytes, 4, valueBytes.length);
153 
154         return avPairBytes;
155     }
156 
157     protected byte[] getTargetInformation() throws UnsupportedEncodingException{
158         byte[] computerName = getAVPairBytes(
159             1, _ntlmServiceAccount.getComputerName());
160         byte[] domainName =  getAVPairBytes(2, _domain);
161 
162         byte[] targetInformation = ArrayUtil.append(computerName, domainName);
163 
164         byte[] eol = getAVPairBytes(0, StringPool.BLANK);
165 
166         targetInformation = ArrayUtil.append(targetInformation, eol);
167 
168         return targetInformation;
169     }
170 
171     private static final int _NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY =
172         0x00080000;
173 
174     private static Log _log = LogFactoryUtil.getLog(NtlmManager.class);
175 
176     private String _domain;
177     private String _domainController;
178     private String _domainControllerName;
179     private Netlogon _netlogon = new Netlogon();
180     private NtlmServiceAccount _ntlmServiceAccount;
181 
182 }