AuthenticateSession.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * Copyright (C) 2006-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.alfresco.jlan.client;
  20. import java.io.*;
  21. import org.alfresco.jlan.debug.Debug;
  22. import org.alfresco.jlan.netbios.NetworkSession;
  23. import org.alfresco.jlan.smb.Capability;
  24. import org.alfresco.jlan.smb.Dialect;
  25. import org.alfresco.jlan.smb.NTTime;
  26. import org.alfresco.jlan.smb.PCShare;
  27. import org.alfresco.jlan.smb.PacketType;
  28. import org.alfresco.jlan.smb.SMBDate;
  29. import org.alfresco.jlan.smb.SMBException;
  30. import org.alfresco.jlan.util.DataPacker;
  31. import org.alfresco.jlan.util.HexDump;
  32. /**
  33. * Authenticate Session Class
  34. *
  35. * <p>
  36. * Used for passthru authentication mechanisms.
  37. *
  38. * @author gkspencer
  39. */
  40. public class AuthenticateSession extends Session {
  41. /**
  42. * Class constructor
  43. *
  44. * @param shr PCShare
  45. * @param sess NetworkSession
  46. * @param dialect int
  47. * @param pkt SMBPacket
  48. */
  49. protected AuthenticateSession(PCShare shr, NetworkSession sess, int dialect, SMBPacket pkt) {
  50. super(shr, dialect, pkt);
  51. // Save the session and packet
  52. setSession(sess);
  53. // Extract the details from the negotiate response packet
  54. processNegotiateResponse();
  55. }
  56. /**
  57. * Perform a session setup to create a session on the remote server validating the user.
  58. *
  59. * @param userName String
  60. * @param ascPwd ASCII password hash
  61. * @param uniPwd Unicode password hash
  62. * @param vc Virtual circuit number
  63. */
  64. public final void doSessionSetup(String userName, byte[] ascPwd, byte[] uniPwd, int vc)
  65. throws IOException, SMBException {
  66. // Create a session setup packet
  67. SMBPacket pkt = new SMBPacket();
  68. pkt.setCommand(PacketType.SessionSetupAndX);
  69. // Check if the negotiated SMB dialect is NT LM 1.2 or an earlier dialect
  70. if ( getDialect() == Dialect.NT) {
  71. // NT LM 1.2 SMB dialect
  72. pkt.setParameterCount(13);
  73. pkt.setAndXCommand(0xFF); // no secondary command
  74. pkt.setParameter(1, 0); // offset to next command
  75. pkt.setParameter(2, SessionFactory.DefaultPacketSize());
  76. pkt.setParameter(3, getMaximumMultiplexedRequests());
  77. pkt.setParameter(4, vc); // virtual circuit number
  78. pkt.setParameterLong(5, 0); // session key
  79. // Set the share password length(s)
  80. pkt.setParameter(7, ascPwd != null ? ascPwd.length : 0); // ANSI password length
  81. pkt.setParameter(8, uniPwd != null ? uniPwd.length : 0); // Unicode password length
  82. pkt.setParameter(9, 0); // reserved, must be zero
  83. pkt.setParameter(10, 0); // reserved, must be zero
  84. // Send the client capabilities
  85. int caps = Capability.LargeFiles + Capability.Unicode + Capability.NTSMBs + Capability.NTStatus
  86. + Capability.RemoteAPIs;
  87. pkt.setParameterLong(11, caps);
  88. // Store the encrypted passwords
  89. //
  90. // Store the ASCII password hash, if specified
  91. int pos = pkt.getByteOffset();
  92. pkt.setPosition(pos);
  93. if ( ascPwd != null)
  94. pkt.packBytes(ascPwd, ascPwd.length);
  95. // Store the Unicode password hash, if specified
  96. if ( uniPwd != null)
  97. pkt.packBytes(uniPwd, uniPwd.length);
  98. // Pack the account/client details
  99. pkt.packString(userName, false);
  100. // Check if the share has a domain, if not then use the default domain string
  101. if ( getPCShare().hasDomain())
  102. pkt.packString(getPCShare().getDomain(), false);
  103. else
  104. pkt.packString(SessionFactory.getDefaultDomain(), false);
  105. pkt.packString("Java VM", false);
  106. pkt.packString("JLAN", false);
  107. // Set the packet length
  108. pkt.setByteCount(pkt.getPosition() - pos);
  109. }
  110. else {
  111. // Earlier SMB dialect
  112. pkt.setUserId(1);
  113. pkt.setParameterCount(10);
  114. pkt.setAndXCommand(0xFF); // no secondary command
  115. pkt.setParameter(1, 0); // offset to next command
  116. pkt.setParameter(2, SessionFactory.DefaultPacketSize());
  117. pkt.setParameter(3, 2); // max multiplexed pending requests
  118. pkt.setParameter(4, 0); // getSessionId ());
  119. pkt.setParameter(5, 0);
  120. pkt.setParameter(6, 0);
  121. pkt.setParameter(7, ascPwd != null ? ascPwd.length : 0);
  122. pkt.setParameter(8, 0);
  123. pkt.setParameter(9, 0);
  124. // Put the password into the SMB packet
  125. byte[] buf = pkt.getBuffer();
  126. int pos = pkt.getByteOffset();
  127. if ( ascPwd != null) {
  128. for (int i = 0; i < ascPwd.length; i++)
  129. buf[pos++] = ascPwd[i];
  130. }
  131. // Build the account/client details
  132. StringBuffer clbuf = new StringBuffer();
  133. clbuf.append(getPCShare().getUserName());
  134. clbuf.append((char) 0x00);
  135. // Check if the share has a domain, if not then use the unknown domain string
  136. if ( getPCShare().hasDomain())
  137. clbuf.append(getPCShare().getDomain());
  138. else
  139. clbuf.append(SessionFactory.getDefaultDomain());
  140. clbuf.append((char) 0x00);
  141. clbuf.append("Java VM");
  142. clbuf.append((char) 0x00);
  143. clbuf.append("JLAN");
  144. clbuf.append((char) 0x00);
  145. // Copy the remaining data to the SMB packet
  146. byte[] byts = clbuf.toString().getBytes();
  147. for (int i = 0; i < byts.length; i++)
  148. buf[pos++] = byts[i];
  149. int pwdLen = ascPwd != null ? ascPwd.length : 0;
  150. pkt.setByteCount(pwdLen + byts.length);
  151. }
  152. // Exchange an SMB session setup packet with the remote file server
  153. pkt.ExchangeSMB(this, pkt, true);
  154. // Save the session user id
  155. setUserId(pkt.getUserId());
  156. // Check if the session was created as a guest
  157. if ( pkt.getParameterCount() >= 3) {
  158. // Set the guest status for the session
  159. setGuest(pkt.getParameter(2) != 0 ? true : false);
  160. }
  161. // The response packet should also have the server OS, LAN Manager type
  162. // and primary domain name.
  163. if ( pkt.getByteCount() > 0) {
  164. // Get the packet buffer and byte offset
  165. byte[] buf = pkt.getBuffer();
  166. int offset = pkt.getByteOffset();
  167. int maxlen = offset + pkt.getByteCount();
  168. // Get the server OS
  169. String srvOS = DataPacker.getString(buf, offset, maxlen);
  170. setOperatingSystem(srvOS);
  171. offset += srvOS.length() + 1;
  172. maxlen -= srvOS.length() + 1;
  173. // Get the LAN Manager type
  174. String lanman = DataPacker.getString(buf, offset, maxlen);
  175. setLANManagerType(lanman);
  176. // Check if we have the primary domain for this session
  177. if ( getDomain() == null || getDomain().length() == 0) {
  178. // Get the domain name string
  179. offset += lanman.length() + 1;
  180. maxlen += lanman.length() + 1;
  181. String dom = DataPacker.getString(buf, offset, maxlen);
  182. setDomain(dom);
  183. }
  184. }
  185. // Check for a core protocol session, set the maximum packet size
  186. if ( getDialect() == Dialect.Core || getDialect() == Dialect.CorePlus) {
  187. // Set the maximum packet size to be used on this session
  188. setMaximumPacketSize(pkt.getParameter(2));
  189. }
  190. }
  191. /**
  192. * Process the negotiate response SMB packet
  193. *
  194. */
  195. private void processNegotiateResponse() {
  196. // Set the security mode flags
  197. int keyLen = 0;
  198. boolean unicodeStr = false;
  199. int encAlgorithm = PasswordEncryptor.LANMAN;
  200. int defFlags2 = 0;
  201. if ( getDialect() == Dialect.NT) {
  202. // Read the returned negotiate parameters, for NT dialect the parameters are not aligned
  203. m_pkt.resetParameterPointer();
  204. m_pkt.skipBytes(2); // skip the dialect index
  205. setSecurityMode(m_pkt.unpackByte());
  206. // Set the maximum virtual circuits and multiplxed requests allowed by the server
  207. setMaximumMultiplexedRequests(m_pkt.unpackWord());
  208. setMaximumVirtualCircuits(m_pkt.unpackWord());
  209. // Set the maximum buffer size
  210. setMaximumPacketSize(m_pkt.unpackInt());
  211. // Skip the maximum raw buffer size and session key
  212. m_pkt.skipBytes(8);
  213. // Set the server capabailities
  214. setCapabilities(m_pkt.unpackInt());
  215. // Get the server system time and timezone
  216. SMBDate srvTime = NTTime.toSMBDate(m_pkt.unpackLong());
  217. int tzone = m_pkt.unpackWord();
  218. // Get the encryption key length
  219. keyLen = m_pkt.unpackByte();
  220. // Indicate that strings are UniCode
  221. unicodeStr = true;
  222. // Use NTLMv1 password encryption
  223. encAlgorithm = PasswordEncryptor.NTLM1;
  224. // Set the default flags for subsequent SMB requests
  225. defFlags2 = SMBPacket.FLG2_LONGFILENAMES + SMBPacket.FLG2_UNICODE + SMBPacket.FLG2_LONGERRORCODE;
  226. }
  227. else if ( getDialect() > Dialect.CorePlus) {
  228. // Set the security mode and encrypted password mode
  229. int secMode = m_pkt.getParameter(1);
  230. setSecurityMode((secMode & 0x01) != 0 ? Session.SecurityModeUser : Session.SecurityModeShare);
  231. if ( m_pkt.getParameterCount() >= 11)
  232. keyLen = m_pkt.getParameter(11) & 0xFF; // should always be 8
  233. // Set the maximum virtual circuits and multiplxed requests allowed by the server
  234. setMaximumMultiplexedRequests(m_pkt.getParameter(3));
  235. setMaximumVirtualCircuits(m_pkt.getParameter(4));
  236. // Check if Unicode strings are being used
  237. if ( m_pkt.isUnicode())
  238. unicodeStr = true;
  239. // Set the default flags for subsequent SMB requests
  240. defFlags2 = SMBPacket.FLG2_LONGFILENAMES;
  241. }
  242. // Set the default packet flags for this session
  243. setDefaultFlags2(defFlags2);
  244. // Get the server details from the negotiate SMB packet
  245. if ( m_pkt.getByteCount() > 0) {
  246. // Get the returned byte area length and offset
  247. int bytsiz = m_pkt.getByteCount();
  248. int bytpos = m_pkt.getByteOffset();
  249. byte[] buf = m_pkt.getBuffer();
  250. // Extract the challenge response key, if specified
  251. if ( keyLen > 0) {
  252. // Allocate a buffer for the challenge response key
  253. byte[] encryptKey = new byte[keyLen];
  254. // Copy the challenge response key
  255. for (int keyIdx = 0; keyIdx < keyLen; keyIdx++)
  256. encryptKey[keyIdx] = buf[bytpos++];
  257. // Set the sessions encryption key
  258. setEncryptionKey(encryptKey);
  259. // DEBUG
  260. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket)) {
  261. Debug.print("** Encryption Key: ");
  262. Debug.print(HexDump.hexString(encryptKey));
  263. Debug.println(", length = " + keyLen);
  264. }
  265. }
  266. // Extract the domain name
  267. String dom;
  268. if ( unicodeStr == false)
  269. dom = DataPacker.getString(buf, bytpos, bytsiz);
  270. else
  271. dom = DataPacker.getUnicodeString(buf, bytpos, bytsiz / 2);
  272. setDomain(dom);
  273. // DEBUG
  274. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket))
  275. Debug.println("** Server domain : " + getDomain() + ".");
  276. }
  277. }
  278. }