All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.filesys.server.auth.passthru.AuthenticateSession Maven / Gradle / Ivy

Go to download

Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems

The newest version!
/*
 * Copyright (C) 2006-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */

package org.filesys.server.auth.passthru;

import java.io.IOException;

import org.filesys.debug.Debug;
import org.filesys.netbios.NetworkSession;
import org.filesys.netbios.RFCNetBIOSProtocol;
import org.filesys.server.auth.PasswordEncryptor;
import org.filesys.server.auth.ntlm.NTLM;
import org.filesys.server.auth.ntlm.Type1NTLMMessage;
import org.filesys.server.auth.ntlm.Type2NTLMMessage;
import org.filesys.server.auth.ntlm.Type3NTLMMessage;
import org.filesys.smb.Capability;
import org.filesys.smb.Dialect;
import org.filesys.smb.NTTime;
import org.filesys.smb.PCShare;
import org.filesys.smb.PacketTypeV1;
import org.filesys.smb.SMBDate;
import org.filesys.smb.SMBException;
import org.filesys.smb.SMBStatus;
import org.filesys.util.DataPacker;

/**
 * Authenticate Session Class
 *
 * 

Used for passthru authentication mechanisms. * * @author gkspencer */ public class AuthenticateSession { // Default packet size private static final int DefaultPacketSize = 1024; // Session security mode public static final int SecurityModeUser = 1; public static final int SecurityModeShare = 2; // Tree identifier that indicates that the disk session has been closed protected final static int Closed = -1; // Debug flags public final static int DBGPacketType = 0x0001; public final static int DBGDumpPacket = 0x0002; public final static int DBGHexDump = 0x0004; // Default SMB packet size to allocate public static final int DEFAULT_BUFSIZE = 4096; // SMB dialect id and string for this session private int m_dialect; private String m_diaStr; // Network session private NetworkSession m_netSession; // SMB packet for protocol exhanges protected SMBPacket m_pkt; // Default packet flags private int m_defFlags = SMBPacket.FLG_CASELESS; private int m_defFlags2 = SMBPacket.FLG2_LONGFILENAMES; // Server connection details private PCShare m_remoteShr; // Domain name private String m_domain; // Remote operating system and LAN manager type private String m_srvOS; private String m_srvLM; // Security mode (user or share) private int m_secMode; // Challenge encryption key private byte[] m_encryptKey; // SMB session information private int m_sessIdx; private int m_userId; private int m_processId; // Tree identifier for this connection protected int m_treeid; // Device type that this session is connected to private int m_devtype; // Maximum transmit buffer size allowed private int m_maxPktSize; // Session capabilities private int m_sessCaps; // Maximum virtual circuits allowed on this session, and maximum multiplxed read/writes private int m_maxVCs; private int m_maxMPX; // Indicate if the session was created as a guest rather than using the supplied username/password private boolean m_guest; // Flag to indicate extended security exchange is being used private boolean m_extendedSec; // Server GUID, if using extended security private byte[] m_serverGUID; // Type 2 security blob from the server private Type2NTLMMessage m_type2Msg; // Global session id private static int m_sessionIdx = 1; // Multiplex id private static int m_multiplexId = 1; // Debug support private static int m_debug = 0; /** * Class constructor * * @param shr PCShare * @param sess NetworkSession * @param dialect int * @param pkt SMBPacket * @exception IOException If an I/O error occurs * @exception SMBException SMB error occurred */ protected AuthenticateSession(PCShare shr, NetworkSession sess, int dialect, SMBPacket pkt) throws IOException, SMBException { // Set the SMB dialect for this session m_dialect = dialect; // Save the remote share details m_remoteShr = shr; // Allocate a unique session index m_sessIdx = getNextSessionId(); // Allocate an SMB protocol packet m_pkt = pkt; if (pkt == null) m_pkt = new SMBPacket(DEFAULT_BUFSIZE); // Save the session and packet setSession(sess); // Extract the details from the negotiate response packet processNegotiateResponse(); } /** * Allocate an SMB packet for this session. The preferred packet size is * specified, if a smaller buffer size has been negotiated a smaller SMB * packet will be returned. * * @param pref Preferred SMB packet size * @return Allocated SMB packet */ protected final SMBPacket allocatePacket(int pref) { // Check if the preferred size is larger than the maximum allowed packet // size for this session. if (pref > m_maxPktSize) return new SMBPacket(m_maxPktSize + RFCNetBIOSProtocol.HEADER_LEN); // Return the preferred SMB packet size return new SMBPacket(pref + RFCNetBIOSProtocol.HEADER_LEN); } /** * Determine if the session supports extended security * * @return true if this session supports extended security, else false */ public final boolean supportsExtendedSecurity() { return (m_sessCaps & Capability.V1ExtendedSecurity) != 0 ? true : false; } /** * Determine if the session supports raw mode read/writes * * @return true if this session supports raw mode, else false */ public final boolean supportsRawMode() { return (m_sessCaps & Capability.V1RawMode) != 0 ? true : false; } /** * Determine if the session supports Unicode * * @return boolean */ public final boolean supportsUnicode() { return (m_sessCaps & Capability.V1Unicode) != 0 ? true : false; } /** * Determine if the session supports large files (ie. 64 bit file offsets) * * @return boolean */ public final boolean supportsLargeFiles() { return (m_sessCaps & Capability.V1LargeFiles) != 0 ? true : false; } /** * Determine if the session supports NT specific SMBs * * @return boolean */ public final boolean supportsNTSmbs() { return (m_sessCaps & Capability.V1NTSMBs) != 0 ? true : false; } /** * Determine if the session supports RPC API requests * * @return boolean */ public final boolean supportsRPCAPIs() { return (m_sessCaps & Capability.V1RemoteAPIs) != 0 ? true : false; } /** * Determine if the session supports NT status codes * * @return boolean */ public final boolean supportsNTStatusCodes() { return (m_sessCaps & Capability.V1NTStatus) != 0 ? true : false; } /** * Determine if the session supports level 2 oplocks * * @return boolean */ public final boolean supportsLevel2Oplocks() { return (m_sessCaps & Capability.V1Level2Oplocks) != 0 ? true : false; } /** * Determine if the session supports lock and read * * @return boolean */ public final boolean supportsLockAndRead() { return (m_sessCaps & Capability.V1LockAndRead) != 0 ? true : false; } /** * Determine if the session supports NT find * * @return boolean */ public final boolean supportsNTFind() { return (m_sessCaps & Capability.V1NTFind) != 0 ? true : false; } /** * Close this connection with the remote server. * * @throws java.io.IOException If an I/O error occurs. * @exception SMBException If an SMB level error occurs */ public void CloseSession() throws java.io.IOException, SMBException { // If the session is valid then hangup the session if (isActive()) { // Close the network session m_netSession.Close(); // Clear the session m_netSession = null; } } /** * Return the default flags settings for this session * * @return int */ public final int getDefaultFlags() { return m_defFlags; } /** * Return the default flags2 settings for this session * * @return int */ public final int getDefaultFlags2() { return m_defFlags2; } /** * Get the device type that this session is connected to. * * @return Device type for this session. */ public final int getDeviceType() { return m_devtype; } /** * Get the SMB dialect property * * @return SMB dialect that this session has negotiated. */ public final int getDialect() { return m_dialect; } /** * Get the SMB dialect string * * @return SMB dialect string for this session. */ public final String getDialectString() { return m_diaStr; } /** * Get the servers primary domain name * * @return Servers primary domain name, if knwon, else null. */ public final String getDomain() { return m_domain; } /** * Determine if there is a challenge encryption key * * @return boolean */ public final boolean hasEncryptionKey() { return m_encryptKey != null ? true : false; } /** * Return the cahllenge encryption key * * @return byte[] */ public final byte[] getEncryptionKey() { return m_encryptKey; } /** * Get the servers LAN manager type * * @return Servers LAN manager type, if known, else null. */ public final String getLANManagerType() { return m_srvLM; } /** * Get the maximum number of multiplxed requests that are allowed * * @return int */ public final int getMaximumMultiplexedRequests() { return m_maxMPX; } /** * Get the maximum packet size allowed for this session * * @return Maximum packet size, in bytes. */ public final int getMaximumPacketSize() { return m_maxPktSize; } /** * Get the maximum virtual circuits allowed on this session * * @return int */ public final int getMaximumVirtualCircuits() { return m_maxVCs; } /** * Get the next multiplex id to uniquely identify a transaction * * @return Unique multiplex id for a transaction */ public final synchronized int getNextMultiplexId() { return m_multiplexId++; } /** * Get the next session id * * @return int */ protected final synchronized int getNextSessionId() { return m_sessionIdx++; } /** * Get the servers operating system type * * @return Servers operating system, if known, else null. */ public final String getOperatingSystem() { return m_srvOS; } /** * Get the remote share password string * * @return Remote share password string */ public final String getPassword() { return m_remoteShr.getPassword(); } /** * Get the remote share details for this session * * @return PCShare information for this session */ public final PCShare getPCShare() { return m_remoteShr; } /** * Return the security mode of the session (user or share) * * @return int */ public final int getSecurityMode() { return m_secMode; } /** * Get the remote server name * * @return Remote server name */ public final String getServer() { return m_remoteShr.getNodeName(); } /** * Access the associated network session * * @return NetworkSession that the SMB session is using */ public final NetworkSession getSession() { return m_netSession; } /** * Return the session capability flags. * * @return int */ public final int getCapabilities() { return m_sessCaps; } /** * Get the process id for this session * * @return int */ public final int getProcessId() { return m_processId; } /** * Get the session identifier property * * @return Session identifier */ public final int getSessionId() { return m_sessIdx; } /** * Get the remote share name * * @return Remote share name string */ public final String getShareName() { return m_remoteShr.getShareName(); } /** * Get the connected tree identifier. * * @return Tree identifier. */ public final int getTreeId() { return m_treeid; } /** * Return the assigned use id for this SMB session * * @return Assigned user id */ public final int getUserId() { return m_userId; } /** * Get the remote share user name string * * @return Remote share user name string */ public final String getUserName() { return m_remoteShr.getUserName(); } /** * Check if there is data available in the network receive buffer * * @return boolean * @exception IOException Network error */ public final boolean hasDataAvailable() throws IOException { return m_netSession.hasData(); } /** * Determine if the specified debugging option is enabled * * @param opt Debug option bit mask * @return true if the debug option is enabled, else false */ public static boolean hasDebugOption(int opt) { if (m_debug == 0) return false; if ((m_debug & opt) != 0) return true; return false; } /** * Determine if the session is valid, ie. still open. * * @return true if the session is still active, else false. */ public final boolean isActive() { return (m_netSession == null) ? false : true; } /** * Determine if SMB session debugging is enabled * * @return true if debugging is enabled, else false. */ public static boolean hasDebug() { return m_debug != 0 ? true : false; } /** * Determine if the session has been created as a guest logon * * @return boolean */ public final boolean isGuest() { return m_guest; } /** * Determine if the Unicode flag is enabled * * @return boolean */ public final boolean isUnicode() { return (m_defFlags2 & SMBPacket.FLG2_UNICODE) != 0 ? true : false; } /** * Determine if extended security exchanges are being used * * @return boolean */ public final boolean isUsingExtendedSecurity() { return m_extendedSec; } /** * Send a single echo request to the server * * @exception IOException If an I/O error occurs * @exception SMBException SMB error occurred */ public final void pingServer() throws IOException, SMBException { // Send a single echo request to the server pingServer(1); } /** * Send an echo request to the server * * @param cnt Number of packets to echo from the remote server * @exception IOException If an I/O error occurs * @exception SMBException SMB error occurred */ public final void pingServer(int cnt) throws java.io.IOException, SMBException { // Build a server ping SMB packet m_pkt.setCommand(PacketTypeV1.Echo); m_pkt.setFlags(0); m_pkt.setTreeId(getTreeId()); m_pkt.setUserId(getUserId()); m_pkt.setProcessId(getProcessId()); m_pkt.setMultiplexId(1); // Set the parameter words m_pkt.setParameterCount(1); m_pkt.setParameter(0, cnt); // number of packets that the server should return String echoStr = "ECHO"; m_pkt.setBytes(echoStr.getBytes()); // Send the echo request m_pkt.SendSMB(this); // Receive the reply packets, if any while (cnt > 0) { // Receive a reply packet m_pkt.ReceiveSMB(this); // Decrement the reply counter cnt--; } } /** * Enable/disable SMB session debugging * * @param dbg Bit mask of debug options to enable, or zero to disable */ public static void setDebug(int dbg) { m_debug = dbg; } /** * Set the default SMB packet flags for this session * * @param flg int */ protected final void setDefaultFlags(int flg) { m_defFlags = flg; } /** * Set the SMB packet default flags2 for this session * * @param flg2 int */ protected final void setDefaultFlags2(int flg2) { m_defFlags2 = flg2; } /** * Set the device type for this session. * * @param dev Device type for this session. */ protected final void setDeviceType(int dev) { m_devtype = dev; } /** * Set the dialect for this session * * @param dia SMB dialect that this session is using. */ protected final void setDialect(int dia) { m_dialect = dia; } /** * Set the dialect string for this session * * @param dia SMB dialect string */ protected final void setDialectString(String dia) { m_diaStr = dia; } /** * Set the remote servers primary domain name * * @param dom Servers primary domain name. */ protected final void setDomain(String dom) { m_domain = dom; } /** * Set the encryption key * * @param key byte[] */ public final void setEncryptionKey(byte[] key) { // Set the challenge response encryption key m_encryptKey = key; } /** * Set the guest status for the session * * @param sts boolean */ protected final void setGuest(boolean sts) { m_guest = sts; } /** * Set the remote servers LAN manager type * * @param lm Servers LAN manager type string. */ protected final void setLANManagerType(String lm) { m_srvLM = lm; } /** * Set the maximum number of multiplexed requests allowed * * @param maxMulti int */ protected final void setMaximumMultiplexedRequests(int maxMulti) { m_maxMPX = maxMulti; } /** * Set the maximum packet size allowed on this session * * @param siz Maximum allowed packet size. */ protected final void setMaximumPacketSize(int siz) { m_maxPktSize = siz; } /** * Set the maximum number of virtual circuits allowed on this session * * @param maxVC int */ protected final void setMaximumVirtualCircuits(int maxVC) { m_maxVCs = maxVC; } /** * Set the remote servers operating system type * * @param os Servers operating system type string. */ protected final void setOperatingSystem(String os) { m_srvOS = os; } /** * Set the remote share password * * @param pwd Remtoe share password string. */ protected final void setPassword(String pwd) { m_remoteShr.setPassword(pwd); } /** * Set the session security mode (user or share) * * @param secMode int */ public final void setSecurityMode(int secMode) { m_secMode = secMode; } /** * Set the remote server name * * @param srv Server name string */ protected final void setServer(String srv) { m_remoteShr.setNodeName(srv); } /** * Set the network session that this SMB session is associated with * * @param netSess Network session that this SMB session is to be associated * with. */ protected final void setSession(NetworkSession netSess) { m_netSession = netSess; } /** * Set the session capability flags * * @param caps Capability flags. */ protected final void setCapabilities(int caps) { m_sessCaps = caps; } /** * Set the remote share name * * @param shr Remote share name string */ protected final void setShareName(String shr) { m_remoteShr.setShareName(shr); } /** * Set the process id for this session * * @param id int */ protected final void setProcessId(int id) { m_processId = id; } /** * Set the connected tree identifier for this session. * * @param id Tree identifier for this session. */ protected final void setTreeId(int id) { m_treeid = id; } /** * Set the user identifier for this session * * @param uid User identifier */ protected final void setUserId(int uid) { m_userId = uid; } /** * Set the remote share user name * * @param user Remote share user name string */ protected final void setUserName(String user) { m_remoteShr.setUserName(user); } /** * Process an asynchronous packet * * @param pkt SMBPacket */ protected void processAsynchResponse(SMBPacket pkt) { // Default is to ignore the packet // // This method is overridden by SMB dialects that can generate asynchronous responses if (Debug.EnableInfo && hasDebug()) Debug.println("++ Asynchronous response received, command = 0x" + pkt.getCommand()); } /** * Output the session details as a string * * @return Session details string */ public String toString() { StringBuffer str = new StringBuffer(); str.append("[\\\\"); str.append(getServer()); str.append("\\"); str.append(getShareName()); str.append(":"); str.append(Dialect.DialectTypeString(m_dialect)); str.append(",UserId="); str.append(getUserId()); str.append("]"); return str.toString(); } /** * Perform a session setup to create a session on the remote server validating the user. * * @param userName String * @param ascPwd ASCII password hash * @param uniPwd Unicode password hash * @throws IOException If a network error occurs * @throws SMBException If a CIFS error occurs */ public final void doSessionSetup(String userName, byte[] ascPwd, byte[] uniPwd) throws IOException, SMBException { doSessionSetup(null, userName, null, ascPwd, uniPwd, 0); } /** * Perform a session using the type3 NTLM response received from the client * * @param type3Msg Type3NTLMMessage * @throws IOException If a network error occurs * @throws SMBException If a CIFS error occurs */ public final void doSessionSetup(Type3NTLMMessage type3Msg) throws IOException, SMBException { doSessionSetup(type3Msg.getDomain(), type3Msg.getUserName(), type3Msg.getWorkstation(), type3Msg.getLMHash(), type3Msg.getNTLMHash(), 0); } /** * Perform a session setup to create a session on the remote server validating the user. * * @param domain String * @param userName String * @param wksName String * @param ascPwd ASCII password hash * @param uniPwd Unicode password hash * @param vcNum Virtual circuit number * @throws IOException If a network error occurs * @throws SMBException If a CIFS error occurs */ public void doSessionSetup(String domain, String userName, String wksName, byte[] ascPwd, byte[] uniPwd, int vcNum) throws IOException, SMBException { // Check if we are using extended security if (isUsingExtendedSecurity()) { // Run the second phase of the extended security session setup doExtendedSessionSetupPhase2(domain, userName, wksName, ascPwd, uniPwd, vcNum); return; } // Create a session setup packet SMBPacket pkt = new SMBPacket(); pkt.setCommand(PacketTypeV1.SessionSetupAndX); // Check if the negotiated SMB dialect is NT LM 1.2 or an earlier dialect if (getDialect() == Dialect.NT) { // NT LM 1.2 SMB dialect int defFlags2 = SMBPacket.FLG2_UNICODE; pkt.setFlags2(defFlags2); pkt.setParameterCount(13); pkt.setAndXCommand(0xFF); // no secondary command pkt.setParameter(1, 0); // offset to next command pkt.setParameter(2, DefaultPacketSize); pkt.setParameter(3, 1); pkt.setParameter(4, vcNum); pkt.setParameterLong(5, 0); // session key // Set the share password length(s) pkt.setParameter(7, ascPwd != null ? ascPwd.length : 0); // ANSI password length pkt.setParameter(8, uniPwd != null ? uniPwd.length : 0); // Unicode password length pkt.setParameter(9, 0); // reserved, must be zero pkt.setParameter(10, 0); // reserved, must be zero // Send the client capabilities int caps = Capability.V1LargeFiles + Capability.V1Unicode + Capability.V1NTSMBs + Capability.V1NTStatus + Capability.V1RemoteAPIs; // Set the client capabilities pkt.setParameterLong(11, caps); // Get the offset to the session setup request byte data int pos = pkt.getByteOffset(); pkt.setPosition(pos); // Store the ASCII password hash, if specified if (ascPwd != null) pkt.packBytes(ascPwd, ascPwd.length); // Store the Unicode password hash, if specified if (uniPwd != null) pkt.packBytes(uniPwd, uniPwd.length); // Pack the account/client details pkt.packString(userName, true); // Check if the share has a domain, if not then use the default domain string if (getPCShare().hasDomain()) pkt.packString(getPCShare().getDomain(), true); else if (domain != null) pkt.packString(domain, true); else pkt.packString("?", true); pkt.packString("Java VM", true); pkt.packString("Java File Server", true); // Set the packet length pkt.setByteCount(pkt.getPosition() - pos); } else { // Earlier SMB dialect pkt.setUserId(1); pkt.setParameterCount(10); pkt.setAndXCommand(0xFF); pkt.setParameter(1, 0); pkt.setParameter(2, DefaultPacketSize); pkt.setParameter(3, 1); pkt.setParameter(4, 0); pkt.setParameter(5, 0); pkt.setParameter(6, 0); pkt.setParameter(7, ascPwd != null ? ascPwd.length : 0); pkt.setParameter(8, 0); pkt.setParameter(9, 0); // Put the password into the SMB packet byte[] buf = pkt.getBuffer(); int pos = pkt.getByteOffset(); if (ascPwd != null) { for (int i = 0; i < ascPwd.length; i++) buf[pos++] = ascPwd[i]; } // Build the account/client details StringBuffer clbuf = new StringBuffer(); clbuf.append(getPCShare().getUserName()); clbuf.append((char) 0x00); // Check if the share has a domain, if not then use the unknown domain string if (getPCShare().hasDomain()) clbuf.append(getPCShare().getDomain()); else clbuf.append("?"); clbuf.append((char) 0x00); clbuf.append("Java VM"); clbuf.append((char) 0x00); clbuf.append("Java File Server"); clbuf.append((char) 0x00); // Copy the remaining data to the SMB packet byte[] byts = clbuf.toString().getBytes(); for (int i = 0; i < byts.length; i++) buf[pos++] = byts[i]; int pwdLen = ascPwd != null ? ascPwd.length : 0; pkt.setByteCount(pwdLen + byts.length); } // Exchange an SMB session setup packet with the remote file server pkt.ExchangeSMB(this, pkt, true); // Save the session user id setUserId(pkt.getUserId()); // Check if the session was created as a guest if (pkt.getParameterCount() >= 3) { // Set the guest status for the session setGuest(pkt.getParameter(2) != 0 ? true : false); } // The response packet should also have the server OS, LAN Manager type // and primary domain name. if (pkt.getByteCount() > 0) { // Get the packet buffer and byte offset byte[] buf = pkt.getBuffer(); int offset = pkt.getByteOffset(); int maxlen = offset + pkt.getByteCount(); // Get the server OS String srvOS = DataPacker.getString(buf, offset, maxlen); setOperatingSystem(srvOS); offset += srvOS.length() + 1; maxlen -= srvOS.length() + 1; // Get the LAN Manager type String lanman = DataPacker.getString(buf, offset, maxlen); setLANManagerType(lanman); // Check if we have the primary domain for this session if (getDomain() == null || getDomain().length() == 0) { // Get the domain name string offset += lanman.length() + 1; maxlen += lanman.length() + 1; String dom = DataPacker.getString(buf, offset, maxlen); setDomain(dom); } } // Check for a core protocol session, set the maximum packet size if (getDialect() == Dialect.Core || getDialect() == Dialect.CorePlus) { // Set the maximum packet size to be used on this session setMaximumPacketSize(pkt.getParameter(2)); } } /** * Process the negotiate response SMB packet * * @throws IOException If a network error occurs * @throws SMBException If a CIFS error occurs */ private void processNegotiateResponse() throws IOException, SMBException { // Set the security mode flags int keyLen = 0; boolean unicodeStr = false; int encAlgorithm = PasswordEncryptor.LANMAN; int defFlags2 = 0; if (getDialect() == Dialect.NT) { // Read the returned negotiate parameters, for NT dialect the parameters are not aligned m_pkt.resetParameterPointer(); m_pkt.skipBytes(2); // skip the dialect index setSecurityMode(m_pkt.unpackByte()); // Set the maximum virtual circuits and multiplxed requests allowed by the server setMaximumMultiplexedRequests(m_pkt.unpackWord()); setMaximumVirtualCircuits(m_pkt.unpackWord()); // Set the maximum buffer size setMaximumPacketSize(m_pkt.unpackInt()); // Skip the maximum raw buffer size and session key m_pkt.skipBytes(8); // Set the server capabailities setCapabilities(m_pkt.unpackInt()); // Check if extended security is enabled if (supportsExtendedSecurity()) m_extendedSec = true; // Get the server system time and timezone SMBDate srvTime = NTTime.toSMBDate(m_pkt.unpackLong()); int tzone = m_pkt.unpackWord(); // Get the encryption key length keyLen = m_pkt.unpackByte(); // Indicate that strings are UniCode unicodeStr = true; // Use NTLMv1 password encryption encAlgorithm = PasswordEncryptor.NTLM1; // Set the default flags for subsequent SMB requests defFlags2 = SMBPacket.FLG2_LONGFILENAMES + SMBPacket.FLG2_UNICODE + SMBPacket.FLG2_LONGERRORCODE + SMBPacket.FLG2_SECURITYSIG; if (isUsingExtendedSecurity()) defFlags2 += SMBPacket.FLG2_EXTENDEDSECURITY; } else if (getDialect() > Dialect.CorePlus) { // Set the security mode and encrypted password mode int secMode = m_pkt.getParameter(1); setSecurityMode((secMode & 0x01) != 0 ? SecurityModeUser : SecurityModeShare); if (m_pkt.getParameterCount() >= 11) keyLen = m_pkt.getParameter(11) & 0xFF; // should always be 8 // Set the maximum virtual circuits and multiplxed requests allowed by the server setMaximumMultiplexedRequests(m_pkt.getParameter(3)); setMaximumVirtualCircuits(m_pkt.getParameter(4)); // Check if Unicode strings are being used if (m_pkt.isUnicode()) unicodeStr = true; // Set the default flags for subsequent SMB requests defFlags2 = SMBPacket.FLG2_LONGFILENAMES; } // Set the default packet flags for this session setDefaultFlags2(defFlags2); // Get the server details from the negotiate SMB packet if (m_pkt.getByteCount() > 0) { // Get the returned byte area length and offset int bytsiz = m_pkt.getByteCount(); int bytpos = m_pkt.getByteOffset(); byte[] buf = m_pkt.getBuffer(); // Original format response if (isUsingExtendedSecurity() == false) { // Extract the challenge response key, if specified if (keyLen > 0) { // Allocate a buffer for the challenge response key byte[] encryptKey = new byte[keyLen]; // Copy the challenge response key for (int keyIdx = 0; keyIdx < keyLen; keyIdx++) encryptKey[keyIdx] = buf[bytpos++]; // Set the sessions encryption key setEncryptionKey(encryptKey); } // Extract the domain name String dom; if (unicodeStr == false) dom = DataPacker.getString(buf, bytpos, bytsiz); else dom = DataPacker.getUnicodeString(buf, bytpos, bytsiz / 2); setDomain(dom); } else { // Extract the server GUID m_serverGUID = new byte[16]; System.arraycopy(buf, bytpos, m_serverGUID, 0, 16); // Run the first phase of the extended security session setup to get the challenge // from the server doExtendedSessionSetupPhase1(); } } } /** * Send the first stage of the extended security session setup * * @throws IOException If a network error occurs * @throws SMBException If a CIFS error occurs */ private final void doExtendedSessionSetupPhase1() throws IOException, SMBException { // Create a session setup packet SMBPacket pkt = new SMBPacket(); pkt.setCommand(PacketTypeV1.SessionSetupAndX); pkt.setFlags(getDefaultFlags()); pkt.setFlags2(getDefaultFlags2()); // Build the extended session setup phase 1 request pkt.setParameterCount(12); pkt.setAndXCommand(0xFF); // no secondary command pkt.setParameter(1, 0); // offset to next command pkt.setParameter(2, DefaultPacketSize); pkt.setParameter(3, 1); pkt.setParameter(4, 0); // virtual circuit number pkt.setParameterLong(5, 0); // session key // Clear the security blob length and reserved area pkt.setParameter(7, 0); // security blob length pkt.setParameterLong(8, 0); // reserved // Send the client capabilities int caps = Capability.V1LargeFiles + Capability.V1Unicode + Capability.V1NTSMBs + Capability.V1NTStatus + Capability.V1RemoteAPIs + Capability.V1ExtendedSecurity; // Set the client capabilities pkt.setParameterLong(10, caps); // Get the offset to the session setup request byte data int pos = pkt.getByteOffset(); pkt.setPosition(pos); // Create a type 1 NTLM message using the session setup request buffer Type1NTLMMessage type1Msg = new Type1NTLMMessage(pkt.getBuffer(), pos, 0); int type1Flags = getPCShare().getExtendedSecurityFlags(); if (type1Flags == 0) type1Flags = NTLM.FlagNegotiateUnicode + NTLM.FlagNegotiateNTLM + NTLM.FlagRequestTarget; type1Msg.buildType1(type1Flags, null, null); // Update the request buffer position pkt.setPosition(pos + type1Msg.getLength()); // Set the security blob length pkt.setParameter(7, type1Msg.getLength()); // Pack the OS details pkt.packString("Java VM", true); pkt.packString("Java File Server", true); pkt.packString("", true); // Set the packet length pkt.setByteCount(pkt.getPosition() - pos); // Exchange an SMB session setup packet with the remote file server pkt.ExchangeSMB(this, pkt, false); // Check the error status, should be a warning status to indicate more processing required if (pkt.isLongErrorCode() == false || pkt.getLongErrorCode() != SMBStatus.NTMoreProcessingRequired) pkt.checkForError(); // Save the session user id setUserId(pkt.getUserId()); // The response packet should also have the type 2 security blob int type2Len = pkt.getParameter(3); if (pkt.getByteCount() > 0) { // Get the packet buffer and byte offset byte[] buf = pkt.getBuffer(); int offset = pkt.getByteOffset(); int maxlen = offset + pkt.getByteCount(); // Take a copy of the type 2 security blob m_type2Msg = new Type2NTLMMessage(); m_type2Msg.copyFrom(buf, offset, type2Len); // Get the encryption key from the security blob m_encryptKey = m_type2Msg.getChallenge(); // Update the byte area offset and align offset = DataPacker.wordAlign(offset + type2Len); maxlen -= type2Len; // Get the server OS String srvOS = DataPacker.getString(buf, offset, maxlen); setOperatingSystem(srvOS); offset += srvOS.length() + 1; maxlen -= srvOS.length() + 1; // Get the LAN Manager type String lanman = DataPacker.getString(buf, offset, maxlen); setLANManagerType(lanman); } } /** * Send the second stage of the extended security session setup * * @param domain String * @param userName String * @param wksName String * @param lmPwd byte[] * @param ntlmPwd byte[] * @param vcNum int * @throws IOException If a network error occurs * @throws SMBException If a CIFS error occurs */ private final void doExtendedSessionSetupPhase2(String domain, String userName, String wksName, byte[] lmPwd, byte[] ntlmPwd, int vcNum) throws IOException, SMBException { // Check if the domain name has been specified, if not then use the domain name from the // original connection details or the servers domain name if (domain == null) { if (getPCShare().hasDomain() && getPCShare().getDomain().length() > 0) domain = getPCShare().getDomain(); else domain = m_type2Msg.getTarget(); } // Create a session setup packet SMBPacket pkt = new SMBPacket(); pkt.setCommand(PacketTypeV1.SessionSetupAndX); pkt.setFlags(getDefaultFlags()); pkt.setFlags2(getDefaultFlags2()); pkt.setUserId(getUserId()); // Build the extended session setup phase 2 request pkt.setParameterCount(12); pkt.setAndXCommand(0xFF); // no secondary command pkt.setParameter(1, 0); // offset to next command pkt.setParameter(2, DefaultPacketSize); pkt.setParameter(3, 1); pkt.setParameter(4, vcNum); pkt.setParameterLong(5, 0); // session key // Clear the security blob length and reserved area pkt.setParameter(7, 0); // security blob length pkt.setParameterLong(8, 0); // reserved // Send the client capabilities int caps = Capability.V1LargeFiles + Capability.V1Unicode + Capability.V1NTSMBs + Capability.V1NTStatus + Capability.V1RemoteAPIs + Capability.V1ExtendedSecurity; // Set the client capabilities pkt.setParameterLong(10, caps); // Get the offset to the session setup request byte data int pos = pkt.getByteOffset(); pkt.setPosition(pos); // Create a type 3 NTLM message using the session setup request buffer Type3NTLMMessage type3Msg = new Type3NTLMMessage(pkt.getBuffer(), pos, 0, true); type3Msg.buildType3(lmPwd, ntlmPwd, domain, userName, wksName != null ? wksName : "", null, m_type2Msg.getFlags()); // Update the request buffer position pkt.setPosition(pos + type3Msg.getLength()); // Set the security blob length pkt.setParameter(7, type3Msg.getLength()); // Pack the OS details pkt.packString("Java VM", true); pkt.packString("Java File Server", true); pkt.packString("", true); // Set the packet length pkt.setByteCount(pkt.getPosition() - pos); // Exchange an SMB session setup packet with the remote file server pkt.ExchangeSMB(this, pkt, true); // Set the guest status for the session setGuest(pkt.getParameter(2) != 0 ? true : false); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy