1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.security.ntlm;
16  
17  import com.liferay.portal.kernel.util.ArrayUtil;
18  import com.liferay.portal.kernel.util.StringPool;
19  
20  import java.io.IOException;
21  import java.io.UnsupportedEncodingException;
22  
23  import java.security.MessageDigest;
24  import java.security.NoSuchAlgorithmException;
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   * @author Michael C. Han
38   */
39  public class NtlmManager {
40  
41      public NtlmManager(
42          String domain, String domainController, String domainControllerName,
43          String serviceAccount, String servicePassword) {
44  
45          setConfiguration(
46              domain, domainController, domainControllerName, serviceAccount,
47              servicePassword);
48      }
49  
50      public NtlmUserAccount authenticate(
51              byte[] material, byte[] serverChallenge)
52          throws IOException, NoSuchAlgorithmException, NtlmLogonException {
53  
54          Type3Message type3Message = new Type3Message(material);
55  
56          if (type3Message.getFlag(
57                  _NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY) &&
58              (type3Message.getNTResponse().length == 24)) {
59  
60              MessageDigest messageDigest = MessageDigest.getInstance("MD5");
61  
62              byte[] bytes = new byte[16];
63  
64              System.arraycopy(serverChallenge, 0, bytes, 0, 8);
65              System.arraycopy(type3Message.getLMResponse(), 0, bytes, 8, 8);
66  
67              messageDigest.update(bytes);
68  
69              serverChallenge = messageDigest.digest();
70          }
71  
72          return _netlogon.logon(
73               type3Message.getDomain(), type3Message.getUser(),
74               type3Message.getWorkstation(), serverChallenge,
75               type3Message.getNTResponse(), type3Message.getLMResponse());
76      }
77  
78      public String getDomain() {
79          return _domain;
80      }
81  
82      public String getDomainController() {
83          return _domainController;
84      }
85  
86      public String getDomainControllerName() {
87          return _domainControllerName;
88      }
89  
90      public String getServiceAccount() {
91          return _ntlmServiceAccount.getAccount();
92      }
93  
94      public String getServicePassword() {
95          return _ntlmServiceAccount.getPassword();
96      }
97  
98      public byte[] negotiate(byte[] material, byte[] serverChallenge)
99          throws IOException {
100 
101         Type1Message type1Message = new Type1Message(material);
102 
103         Type2Message type2Message = new Type2Message(
104             type1Message.getFlags(), serverChallenge, _domain);
105 
106         if (type2Message.getFlag(
107                 _NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY)) {
108 
109             type2Message.setFlag(NtlmFlags.NTLMSSP_NEGOTIATE_LM_KEY, false);
110             type2Message.setFlag(NtlmFlags.NTLMSSP_NEGOTIATE_TARGET_INFO, true);
111             type2Message.setTargetInformation(getTargetInformation());
112         }
113 
114         return type2Message.toByteArray();
115     }
116 
117     public void setConfiguration(
118         String domain, String domainController, String domainControllerName,
119         String serviceAccount, String servicePassword) {
120 
121         _domain = domain;
122         _domainController = domainController;
123         _domainControllerName = domainControllerName;
124         _ntlmServiceAccount = new NtlmServiceAccount(
125             serviceAccount, servicePassword);
126 
127         _netlogon = new Netlogon();
128 
129         _netlogon.setConfiguration(
130             domainController, domainControllerName, _ntlmServiceAccount);
131     }
132 
133     protected byte[] getAVPairBytes(int avId, String value)
134         throws UnsupportedEncodingException{
135 
136         byte[] valueBytes = value.getBytes("UTF-16LE");
137         byte[] avPairBytes = new byte[4 + valueBytes.length];
138 
139         Encdec.enc_uint16le((short)avId, avPairBytes, 0);
140         Encdec.enc_uint16le((short)valueBytes.length, avPairBytes, 2);
141 
142         System.arraycopy(valueBytes, 0, avPairBytes, 4, valueBytes.length);
143 
144         return avPairBytes;
145     }
146 
147     protected byte[] getTargetInformation() throws UnsupportedEncodingException{
148         byte[] computerName = getAVPairBytes(
149             1, _ntlmServiceAccount.getComputerName());
150         byte[] domainName =  getAVPairBytes(2, _domain);
151 
152         byte[] targetInformation = ArrayUtil.append(computerName, domainName);
153 
154         byte[] eol = getAVPairBytes(0, StringPool.BLANK);
155 
156         targetInformation = ArrayUtil.append(targetInformation, eol);
157 
158         return targetInformation;
159     }
160 
161     private static final int _NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY =
162         0x00080000;
163 
164     private String _domain;
165     private String _domainController;
166     private String _domainControllerName;
167     private Netlogon _netlogon;
168     private NtlmServiceAccount _ntlmServiceAccount;
169 
170 }