From a937dfa608470c638b53bccbfa859c6fa2eaddcd Mon Sep 17 00:00:00 2001 From: Gary Spencer Date: Thu, 4 May 2006 15:34:49 +0000 Subject: [PATCH] Updates to the CIFS protocol handlers to use the new authentication code. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2761 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../smb/server/CoreProtocolHandler.java | 6 +- .../smb/server/LanManProtocolHandler.java | 20 +- .../filesys/smb/server/NTParameterPacker.java | 4 +- .../filesys/smb/server/NTProtocolHandler.java | 339 +++--------------- .../server/NetBIOSSessionSocketHandler.java | 18 +- .../filesys/smb/server/SMBServer.java | 94 ++--- .../filesys/smb/server/SMBSrvException.java | 42 ++- .../filesys/smb/server/SMBSrvPacket.java | 25 +- .../filesys/smb/server/SMBSrvSession.java | 273 +++++++------- .../filesys/smb/server/SecurityMode.java | 34 ++ .../smb/server/SessionSocketHandler.java | 4 +- .../server/TcpipSMBSessionSocketHandler.java | 16 +- .../server/win32/Win32NetBIOSLanaMonitor.java | 18 +- .../Win32NetBIOSSessionSocketHandler.java | 50 +-- .../win32/WinsockNetBIOSPacketHandler.java | 7 +- 15 files changed, 381 insertions(+), 569 deletions(-) create mode 100644 source/java/org/alfresco/filesys/smb/server/SecurityMode.java diff --git a/source/java/org/alfresco/filesys/smb/server/CoreProtocolHandler.java b/source/java/org/alfresco/filesys/smb/server/CoreProtocolHandler.java index d127e3e029..0824d388e3 100644 --- a/source/java/org/alfresco/filesys/smb/server/CoreProtocolHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/CoreProtocolHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -19,8 +19,8 @@ package org.alfresco.filesys.smb.server; import java.io.IOException; import org.alfresco.filesys.netbios.RFCNetBIOSProtocol; +import org.alfresco.filesys.server.auth.CifsAuthenticator; import org.alfresco.filesys.server.auth.InvalidUserException; -import org.alfresco.filesys.server.auth.SrvAuthenticator; import org.alfresco.filesys.server.core.InvalidDeviceInterfaceException; import org.alfresco.filesys.server.core.ShareType; import org.alfresco.filesys.server.core.SharedDevice; @@ -3131,7 +3131,7 @@ class CoreProtocolHandler extends ProtocolHandler // Authenticate the share connection depending upon the security mode the server is running // under - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); + CifsAuthenticator auth = getSession().getSMBServer().getAuthenticator(); int filePerm = FileAccess.Writeable; if (auth != null) diff --git a/source/java/org/alfresco/filesys/smb/server/LanManProtocolHandler.java b/source/java/org/alfresco/filesys/smb/server/LanManProtocolHandler.java index 29b21448f6..c956c1634f 100644 --- a/source/java/org/alfresco/filesys/smb/server/LanManProtocolHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/LanManProtocolHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -20,9 +20,9 @@ import java.io.FileNotFoundException; import java.io.IOException; import org.alfresco.filesys.netbios.RFCNetBIOSProtocol; +import org.alfresco.filesys.server.auth.CifsAuthenticator; import org.alfresco.filesys.server.auth.ClientInfo; import org.alfresco.filesys.server.auth.InvalidUserException; -import org.alfresco.filesys.server.auth.SrvAuthenticator; import org.alfresco.filesys.server.core.InvalidDeviceInterfaceException; import org.alfresco.filesys.server.core.ShareType; import org.alfresco.filesys.server.core.SharedDevice; @@ -302,10 +302,10 @@ class LanManProtocolHandler extends CoreProtocolHandler // Authenticate the share connect, if the server is using share mode security - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); + CifsAuthenticator auth = getSession().getSMBServer().getAuthenticator(); int filePerm = FileAccess.Writeable; - if (auth != null && auth.getAccessMode() == SrvAuthenticator.SHARE_MODE) + if (auth != null) { // Validate the share connection @@ -1233,18 +1233,18 @@ class LanManProtocolHandler extends CoreProtocolHandler // Authenticate the user, if the server is using user mode security - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); + CifsAuthenticator auth = getSession().getSMBServer().getAuthenticator(); boolean isGuest = false; - if (auth != null && auth.getAccessMode() == SrvAuthenticator.USER_MODE) + if (auth != null) { // Validate the user - int sts = auth.authenticateUser(client, m_sess, SrvAuthenticator.LANMAN); - if (sts > 0 && (sts & SrvAuthenticator.AUTH_GUEST) != 0) + int sts = auth.authenticateUser(client, m_sess, CifsAuthenticator.LANMAN); + if (sts > 0 && (sts & CifsAuthenticator.AUTH_GUEST) != 0) isGuest = true; - else if (sts != SrvAuthenticator.AUTH_ALLOW) + else if (sts != CifsAuthenticator.AUTH_ALLOW) { // Invalid user, reject the session setup request @@ -2569,7 +2569,7 @@ class LanManProtocolHandler extends CoreProtocolHandler // Authenticate the share connection depending upon the security mode the server is running // under - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); + CifsAuthenticator auth = getSession().getSMBServer().getAuthenticator(); int filePerm = FileAccess.Writeable; if (auth != null) diff --git a/source/java/org/alfresco/filesys/smb/server/NTParameterPacker.java b/source/java/org/alfresco/filesys/smb/server/NTParameterPacker.java index 1d2e2311ee..f118c2f3a7 100644 --- a/source/java/org/alfresco/filesys/smb/server/NTParameterPacker.java +++ b/source/java/org/alfresco/filesys/smb/server/NTParameterPacker.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -23,7 +23,7 @@ import org.alfresco.filesys.util.DataPacker; *

* The NT SMB dialect uses parameters that are not always word/longword aligned. */ -class NTParameterPacker +public class NTParameterPacker { // Buffer and current offset diff --git a/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java b/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java index e1827da1ed..33f53eb4ad 100644 --- a/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -23,9 +23,8 @@ import org.alfresco.filesys.locking.FileLock; import org.alfresco.filesys.locking.LockConflictException; import org.alfresco.filesys.locking.NotLockedException; import org.alfresco.filesys.netbios.RFCNetBIOSProtocol; -import org.alfresco.filesys.server.auth.ClientInfo; +import org.alfresco.filesys.server.auth.CifsAuthenticator; import org.alfresco.filesys.server.auth.InvalidUserException; -import org.alfresco.filesys.server.auth.SrvAuthenticator; import org.alfresco.filesys.server.auth.acl.AccessControl; import org.alfresco.filesys.server.auth.acl.AccessControlManager; import org.alfresco.filesys.server.core.InvalidDeviceInterfaceException; @@ -81,7 +80,6 @@ import org.alfresco.filesys.smb.server.ntfs.NTFSStreamsInterface; import org.alfresco.filesys.smb.server.ntfs.StreamInfoList; import org.alfresco.filesys.util.DataBuffer; import org.alfresco.filesys.util.DataPacker; -import org.alfresco.filesys.util.HexDump; import org.alfresco.filesys.util.WildCard; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -111,8 +109,7 @@ public class NTProtocolHandler extends CoreProtocolHandler public static final int FileSizeChangeRate = 10; // Security descriptor to allow Everyone access, returned by the QuerySecurityDescrptor NT - // transaction - // when NTFS streams are enabled for a virtual filesystem. + // transaction when NTFS streams are enabled for a virtual filesystem. private static byte[] _sdEveryOne = { 0x01, 0x00, 0x04, (byte) 0x80, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -391,244 +388,29 @@ public class NTProtocolHandler extends CoreProtocolHandler TooManyConnectionsException { - // Check that the received packet looks like a valid NT session setup andX request - - if (m_smbPkt.checkPacketIsValid(13, 0) == false) + // Call the authenticator to process the session setup + + CifsAuthenticator cifsAuthenticator = m_sess.getServer().getAuthenticator(); + + try { - m_sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv); + // Process the session setup request, build the response + + cifsAuthenticator.processSessionSetup( m_sess, m_smbPkt, outPkt); + } + catch (SMBSrvException ex) + { + // Return an error response to the client + + m_sess.sendErrorResponseSMB( ex.getNTErrorCode(), ex.getErrorCode(), ex.getErrorClass()); return; } - - // Extract the session details - - int maxBufSize = m_smbPkt.getParameter(2); - int maxMpx = m_smbPkt.getParameter(3); - int vcNum = m_smbPkt.getParameter(4); - int sessKey = m_smbPkt.getParameterLong(5); - int ascPwdLen = m_smbPkt.getParameter(7); - int uniPwdLen = m_smbPkt.getParameter(8); - int capabs = m_smbPkt.getParameter(11); - - // Extract the client details from the session setup request - - int dataPos = m_smbPkt.getByteOffset(); - int dataLen = m_smbPkt.getByteCount(); - byte[] buf = m_smbPkt.getBuffer(); - - // Determine if ASCII or unicode strings are being used - - boolean isUni = m_smbPkt.isUnicode(); - - // Extract the password strings - - byte[] ascPwd = m_smbPkt.unpackBytes(ascPwdLen); - byte[] uniPwd = m_smbPkt.unpackBytes(uniPwdLen); - - // Extract the user name string - - String user = m_smbPkt.unpackString(isUni); - - if (user == null) - { - m_sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv); - return; - } - - // Extract the clients primary domain name string - - String domain = ""; - - if (m_smbPkt.hasMoreData()) - { - - // Extract the callers domain name - - domain = m_smbPkt.unpackString(isUni); - - if (domain == null) - { - m_sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, - SMBStatus.ErrSrv); - return; - } - } - - // Extract the clients native operating system - - String clientOS = ""; - - if (m_smbPkt.hasMoreData()) - { - - // Extract the callers operating system name - - clientOS = m_smbPkt.unpackString(isUni); - - if (clientOS == null) - { - m_sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, - SMBStatus.ErrSrv); - return; - } - } - - // DEBUG - - if (logger.isDebugEnabled() && m_sess.hasDebug(SMBSrvSession.DBG_NEGOTIATE)) - { - logger.debug("NT Session setup from user=" + user + ", password=" - + (uniPwd != null ? HexDump.hexString(uniPwd) : "none") + ", ANSIpwd=" - + (ascPwd != null ? HexDump.hexString(ascPwd) : "none") + ", domain=" + domain + ", os=" + clientOS - + ", VC=" + vcNum + ", maxBuf=" + maxBufSize + ", maxMpx=" + maxMpx - + ", challenge=" + HexDump.hexString(m_sess.getChallengeKey())); - logger.debug(" MID=" + m_smbPkt.getMultiplexId() + ", UID=" + m_smbPkt.getUserId() + ", PID=" - + m_smbPkt.getProcessId()); - } - - // Store the client maximum buffer size, maximum multiplexed requests count and client - // capability flags - - m_sess.setClientMaximumBufferSize(maxBufSize); - m_sess.setClientMaximumMultiplex(maxMpx); - m_sess.setClientCapabilities(capabs); - - // Create the client information and store in the session - - ClientInfo client = new ClientInfo(user, uniPwd); - client.setANSIPassword(ascPwd); - client.setDomain(domain); - client.setOperatingSystem(clientOS); - - if (m_sess.hasRemoteAddress()) - client.setClientAddress(m_sess.getRemoteAddress().getHostAddress()); - - // Check if this is a null session logon - - if (user.length() == 0 && domain.length() == 0 && uniPwdLen == 0 && ascPwdLen == 1) - client.setLogonType(ClientInfo.LogonNull); - - // Authenticate the user, if the server is using user mode security - - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); - boolean isGuest = false; - - if (auth != null && auth.getAccessMode() == SrvAuthenticator.USER_MODE) - { - - // Validate the user - - int sts = auth.authenticateUser(client, m_sess, SrvAuthenticator.NTLM1); - - if (sts > 0 && (sts & SrvAuthenticator.AUTH_GUEST) != 0) - { - - // Guest logon - - isGuest = true; - - // DEBUG - - if (logger.isDebugEnabled() && m_sess.hasDebug(SMBSrvSession.DBG_NEGOTIATE)) - logger.debug("User " + user + ", logged on as guest"); - } - else if (sts != SrvAuthenticator.AUTH_ALLOW) - { - - // Check if the session already has valid client details and the new client details - // have null username/password - // values - - if (getSession().getClientInformation() != null && client.getUserName().length() == 0) - { - - // Use the existing client information details - - client = getSession().getClientInformation(); - - // DEBUG - - if (logger.isDebugEnabled() && m_sess.hasDebug(SMBSrvSession.DBG_NEGOTIATE)) - logger.debug("Null client information, reusing existing client=" + client); - } - else - { - - // Invalid user, reject the session setup request - - m_sess.sendErrorResponseSMB(SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos); - - // DEBUG - - if (logger.isDebugEnabled() && m_sess.hasDebug(SMBSrvSession.DBG_NEGOTIATE)) - logger.debug("User " + user + ", access denied"); - return; - } - } - else if (logger.isDebugEnabled() && m_sess.hasDebug(SMBSrvSession.DBG_NEGOTIATE)) - { - - // DEBUG - - logger.debug("User " + user + " logged on " - + (client != null ? " (type " + client.getLogonTypeString() + ")" : "")); - } - } - - // Update the client information if not already set - - if (getSession().getClientInformation() == null - || getSession().getClientInformation().getUserName().length() == 0) - { - - // Set the client details for the session - - getSession().setClientInformation(client); - } - - // Set the guest flag for the client, indicate that the session is logged on - - client.setGuest(isGuest); - getSession().setLoggedOn(true); - - // Build the session setup response SMB - - outPkt.setParameterCount(3); - outPkt.setParameter(0, 0); // No chained response - outPkt.setParameter(1, 0); // Offset to chained response - outPkt.setParameter(2, isGuest ? 1 : 0); - outPkt.setByteCount(0); - - outPkt.setTreeId(0); - outPkt.setUserId(0); - - // Set the various flags - - int flags = outPkt.getFlags(); - flags &= ~SMBSrvPacket.FLG_CASELESS; - outPkt.setFlags(flags); - - int flags2 = SMBSrvPacket.FLG2_LONGFILENAMES; - if (isUni) - flags2 += SMBSrvPacket.FLG2_UNICODE; - outPkt.setFlags2(flags2); - - // Pack the OS, dialect and domain name strings. - - int pos = outPkt.getByteOffset(); - buf = outPkt.getBuffer(); - - if (isUni) - pos = DataPacker.wordAlign(pos); - - pos = DataPacker.putString("Java", buf, pos, true, isUni); - pos = DataPacker.putString("Alfresco CIFS Server " + m_sess.getServer().isVersion(), buf, pos, true, isUni); - pos = DataPacker.putString(m_sess.getServer().getConfiguration().getDomainName(), buf, pos, true, isUni); - - outPkt.setByteCount(pos - outPkt.getByteOffset()); - + // Check if there is a chained command, or commands - if (m_smbPkt.hasAndXCommand() && dataPos < m_smbPkt.getReceivedLength()) + int pos = outPkt.getLength(); + + if (m_smbPkt.hasAndXCommand() && m_smbPkt.getPosition() < m_smbPkt.getReceivedLength()) { // Process any chained commands, AndX @@ -638,23 +420,28 @@ public class NTProtocolHandler extends CoreProtocolHandler } else { - // Indicate that there are no chained replies outPkt.setAndXCommand(SMBSrvPacket.NO_ANDX_CMD); } - // Send the negotiate response + // Send the session setup response m_sess.sendResponseSMB(outPkt, pos); - // Update the session state + // Update the session state if the response indicates a success status. A multi stage session setup + // response returns a warning status. + + if ( outPkt.getLongErrorCode() == SMBStatus.NTSuccess) + { + // Update the session state - m_sess.setState(SMBSrvSessionState.SMBSESSION); + m_sess.setState(SMBSrvSessionState.SMBSESSION); - // Notify listeners that a user has logged onto the session - - m_sess.getSMBServer().sessionLoggedOn(m_sess); + // Notify listeners that a user has logged onto the session + + m_sess.getSMBServer().sessionLoggedOn(m_sess); + } } /** @@ -790,7 +577,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Extract the parameters - int flags = m_smbPkt.getAndXParameter(cmdOff, 2); +// int flags = m_smbPkt.getAndXParameter(cmdOff, 2); int pwdLen = m_smbPkt.getAndXParameter(cmdOff, 3); // Reset the byte pointer for data unpacking @@ -927,10 +714,10 @@ public class NTProtocolHandler extends CoreProtocolHandler // Authenticate the share connect, if the server is using share mode security - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); + CifsAuthenticator auth = getSession().getSMBServer().getAuthenticator(); int sharePerm = FileAccess.Writeable; - if (auth != null && auth.getAccessMode() == SrvAuthenticator.SHARE_MODE) + if (auth != null) { // Validate the share connection @@ -1221,8 +1008,8 @@ public class NTProtocolHandler extends CoreProtocolHandler // Get the file id from the request int fid = m_smbPkt.getAndXParameter(cmdOff, 0); - int ftime = m_smbPkt.getAndXParameter(cmdOff, 1); - int fdate = m_smbPkt.getAndXParameter(cmdOff, 2); +// int ftime = m_smbPkt.getAndXParameter(cmdOff, 1); +// int fdate = m_smbPkt.getAndXParameter(cmdOff, 2); NetworkFile netFile = conn.findFile(fid); @@ -1308,7 +1095,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Extract the parameters - int flags = m_smbPkt.getParameter(2); +// int flags = m_smbPkt.getParameter(2); int pwdLen = m_smbPkt.getParameter(3); // Initialize the byte area pointer @@ -1446,7 +1233,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Authenticate the share connection depending upon the security mode the server is running // under - SrvAuthenticator auth = getSession().getSMBServer().getAuthenticator(); + CifsAuthenticator auth = getSession().getSMBServer().getAuthenticator(); int sharePerm = FileAccess.Writeable; if (auth != null) @@ -1628,8 +1415,8 @@ public class NTProtocolHandler extends CoreProtocolHandler // Get the file id from the request int fid = m_smbPkt.getParameter(0); - int ftime = m_smbPkt.getParameter(1); - int fdate = m_smbPkt.getParameter(2); +// int ftime = m_smbPkt.getParameter(1); +// int fdate = m_smbPkt.getParameter(2); NetworkFile netFile = conn.findFile(fid); @@ -2335,14 +2122,6 @@ public class NTProtocolHandler extends CoreProtocolHandler protected final void procLogoffAndX(SMBSrvPacket outPkt) throws java.io.IOException, SMBSrvException { - // Check that the received packet looks like a valid logoff andX request - - if (m_smbPkt.checkPacketIsValid(15, 1) == false) - { - m_sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv); - return; - } - // Return a success status SMB m_sess.sendSuccessResponseSMB(); @@ -2409,7 +2188,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Extract the open file parameters - int flags = m_smbPkt.getParameter(2); +// int flags = m_smbPkt.getParameter(2); int access = m_smbPkt.getParameter(3); int srchAttr = m_smbPkt.getParameter(4); int fileAttr = m_smbPkt.getParameter(5); @@ -2878,9 +2657,6 @@ public class NTProtocolHandler extends CoreProtocolHandler // Access the disk interface and rename the requested file - int fid; - NetworkFile netFile = null; - try { @@ -3022,9 +2798,6 @@ public class NTProtocolHandler extends CoreProtocolHandler // Access the disk interface and delete the file(s) - int fid; - NetworkFile netFile = null; - try { @@ -3632,7 +3405,7 @@ public class NTProtocolHandler extends CoreProtocolHandler int searchId = paramBuf.getShort(); int maxFiles = paramBuf.getShort(); int infoLevl = paramBuf.getShort(); - int reskey = paramBuf.getInt(); + paramBuf.getInt(); int srchFlag = paramBuf.getShort(); String resumeName = paramBuf.getString(tbuf.isUnicode()); @@ -3640,15 +3413,9 @@ public class NTProtocolHandler extends CoreProtocolHandler // Access the shared device disk interface SearchContext ctx = null; - DiskInterface disk = null; try { - - // Access the disk interface - - disk = (DiskInterface) conn.getSharedDevice().getInterface(); - // Retrieve the search context ctx = m_sess.getSearchContext(searchId); @@ -3810,18 +3577,6 @@ public class NTProtocolHandler extends CoreProtocolHandler m_sess.sendErrorResponseSMB(SMBStatus.DOSNoMoreFiles, SMBStatus.ErrDos); } - catch (InvalidDeviceInterfaceException ex) - { - - // Deallocate the search - - if (searchId != -1) - m_sess.deallocateSearchSlot(searchId); - - // Failed to get/initialize the disk interface - - m_sess.sendErrorResponseSMB(SMBStatus.DOSInvalidData, SMBStatus.ErrDos); - } catch (UnsupportedInfoLevelException ex) { @@ -5300,9 +5055,9 @@ public class NTProtocolHandler extends CoreProtocolHandler if (logger.isDebugEnabled() && m_sess.hasDebug(SMBSrvSession.DBG_FILEIO)) logger.debug("File Write Error [" + netFile.getFileId() + "] : " + ex.toString()); - // Failed to read the file + // Failed to write the file - m_sess.sendErrorResponseSMB(SMBStatus.HRDWriteFault, SMBStatus.ErrHrd); + m_sess.sendErrorResponseSMB(SMBStatus.NTDiskFull, SMBStatus.HRDWriteFault, SMBStatus.ErrHrd); return; } @@ -7086,7 +6841,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Unpack the request details - DataBuffer paramBuf = tbuf.getParameterBuffer(); +// DataBuffer paramBuf = tbuf.getParameterBuffer(); // Get the tree connection details diff --git a/source/java/org/alfresco/filesys/smb/server/NetBIOSSessionSocketHandler.java b/source/java/org/alfresco/filesys/smb/server/NetBIOSSessionSocketHandler.java index 0e85b2d248..2d3b1c693f 100644 --- a/source/java/org/alfresco/filesys/smb/server/NetBIOSSessionSocketHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/NetBIOSSessionSocketHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -64,7 +64,7 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Waiting for NetBIOS session request ..."); + logger.debug("Waiting for NetBIOS session request ..."); // Wait for a connection @@ -73,7 +73,7 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] NetBIOS session request received from " + logger.debug("NetBIOS session request received from " + sessSock.getInetAddress().getHostAddress()); try @@ -107,7 +107,7 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // Debug - logger.error("[SMB] NetBIOS Failed to create session, ", ex); + logger.error("NetBIOS Failed to create session, ", ex); } } } @@ -118,7 +118,7 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // causes an exception to be thrown. if (hasShutdown() == false) - logger.error("[SMB] NetBIOS Socket error : ", ex); + logger.error("NetBIOS Socket error : ", ex); } catch (Exception ex) { @@ -127,13 +127,13 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // causes an exception to be thrown. if (hasShutdown() == false) - logger.error("[SMB] NetBIOS Server error : ", ex); + logger.error("NetBIOS Server error : ", ex); } // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] NetBIOS session handler closed"); + logger.debug("NetBIOS session handler closed"); } /** @@ -169,7 +169,7 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] TCP NetBIOS session handler created"); + logger.debug("TCP NetBIOS session handler created"); // Check if a host announcer should be created @@ -220,7 +220,7 @@ public class NetBIOSSessionSocketHandler extends SessionSocketHandler // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] TCP NetBIOS host announcer created"); + logger.debug("TCP NetBIOS host announcer created"); } } } diff --git a/source/java/org/alfresco/filesys/smb/server/SMBServer.java b/source/java/org/alfresco/filesys/smb/server/SMBServer.java index b9ea78686d..60644ee9a2 100644 --- a/source/java/org/alfresco/filesys/smb/server/SMBServer.java +++ b/source/java/org/alfresco/filesys/smb/server/SMBServer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -21,20 +21,18 @@ import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; +import java.util.UUID; import java.util.Vector; import org.alfresco.filesys.netbios.NetworkSettings; import org.alfresco.filesys.server.ServerListener; import org.alfresco.filesys.server.SrvSessionList; -import org.alfresco.filesys.server.auth.SrvAuthenticator; -import org.alfresco.filesys.server.auth.UserAccountList; import org.alfresco.filesys.server.config.ServerConfiguration; import org.alfresco.filesys.server.core.InvalidDeviceInterfaceException; import org.alfresco.filesys.server.core.ShareType; import org.alfresco.filesys.server.core.SharedDevice; import org.alfresco.filesys.server.filesys.DiskInterface; import org.alfresco.filesys.server.filesys.NetworkFileServer; -import org.alfresco.filesys.smb.DialectSelector; import org.alfresco.filesys.smb.SMBException; import org.alfresco.filesys.smb.ServerType; import org.alfresco.filesys.smb.mailslot.HostAnnouncer; @@ -44,10 +42,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - *

- * Creates an SMB server with the specified host name. - *

- * The server can optionally announce itself so that it will appear under the Network Neighborhood, + * SMB Server Class + * + *

Creates an SMB server with the specified host name. + * + *

The server can optionally announce itself so that it will appear under the Network Neighborhood, * by enabling the host announcer in the server configuration or using the enableAnnouncer() method. */ public class SMBServer extends NetworkFileServer implements Runnable @@ -90,6 +89,10 @@ public class SMBServer extends NetworkFileServer implements Runnable private boolean m_shutdown = false; private boolean m_active = false; + // Server GUID + + private UUID m_serverGUID; + /** * Create an SMB server using the specified configuration. * @@ -114,8 +117,7 @@ public class SMBServer extends NetworkFileServer implements Runnable { // For disk devices check if the shared device is read-only, this should also check if the - // shared device - // path actully exists. + // shared device path actully exists. if (shr.getType() == ShareType.DISK) { @@ -132,7 +134,7 @@ public class SMBServer extends NetworkFileServer implements Runnable // Debug if (logger.isInfoEnabled()) - logger.info("[SMB] Add Share " + shr.toString() + " : " + sts); + logger.info("Add Share " + shr.toString() + " : " + sts); // Return the add share status @@ -395,26 +397,6 @@ public class SMBServer extends NetworkFileServer implements Runnable return getConfiguration().getSessionDebugFlags(); } - /** - * Return the list of SMB dialects that this server supports. - * - * @return DialectSelector - */ - public final DialectSelector getSMBDialects() - { - return getConfiguration().getEnabledDialects(); - } - - /** - * Return the list of user accounts. - * - * @return UserAccountList - */ - public final UserAccountList getUserAccountList() - { - return getConfiguration().getUserAccounts(); - } - /** * Return the active session list * @@ -439,50 +421,42 @@ public class SMBServer extends NetworkFileServer implements Runnable boolean isWindows = isWindowsNTOnwards(); + // Generate a GUID for the server based on the server name + + m_serverGUID = UUID.nameUUIDFromBytes( getServerName().getBytes()); + // Debug if (logger.isInfoEnabled()) { - // Dump the server name/version and Java runtime details + // Dump the server name and GUID - logger.info("[SMB] SMB Server " + getServerName() + " starting"); - logger.info("[SMB] Version " + isVersion()); - logger.info("[SMB] Java VM " + System.getProperty("java.vm.version")); - logger.info("[SMB] OS " + System.getProperty("os.name") + ", version " + System.getProperty("os.version")); + logger.info("SMB Server " + getServerName() + " starting"); + logger.info("GUID " + m_serverGUID); // Output the authenticator details if (getAuthenticator() != null) - { - String mode = getAuthenticator().getAccessMode() == SrvAuthenticator.SHARE_MODE ? "SHARE" : "USER"; - logger.info("[SMB] Using authenticator " + getAuthenticator().getClass().getName() + ", mode=" + mode); - - // Display the count of user accounts - - if (getUserAccountList() != null) - logger.info("[SMB] " + getUserAccountList().numberOfUsers() + " user accounts defined"); - else - logger.info("[SMB] No user accounts defined"); - } + logger.info("Using authenticator " + getAuthenticator().getClass().getName()); // Display the timezone offset/name if (getConfiguration().getTimeZone() != null) - logger.info("[SMB] Server timezone " + getConfiguration().getTimeZone() + ", offset from UTC = " + logger.info("Server timezone " + getConfiguration().getTimeZone() + ", offset from UTC = " + getConfiguration().getTimeZoneOffset() / 60 + "hrs"); else - logger.info("[SMB] Server timezone offset = " + getConfiguration().getTimeZoneOffset() / 60 + "hrs"); + logger.info("Server timezone offset = " + getConfiguration().getTimeZoneOffset() / 60 + "hrs"); // Dump the share list - logger.info("[SMB] Shares:"); + logger.info("Shares:"); Enumeration enm = getFullShareList(getServerName(), null).enumerateShares(); while (enm.hasMoreElements()) { SharedDevice share = enm.nextElement(); - logger.info("[SMB] " + share.toString() + " " + share.getContext().toString()); + logger.info(" " + share.toString() + " " + share.getContext().toString()); } } @@ -574,7 +548,7 @@ public class SMBServer extends NetworkFileServer implements Runnable // DEBUG - logger.info("[SMB] No valid session handlers, server closing"); + logger.info("No valid session handlers, server closing"); } } catch (SMBException ex) @@ -597,7 +571,7 @@ public class SMBServer extends NetworkFileServer implements Runnable if (m_shutdown == false) { - logger.error("[SMB] Server error : ", ex); + logger.error("Server error : ", ex); // Store the error, fire a server error event @@ -609,7 +583,7 @@ public class SMBServer extends NetworkFileServer implements Runnable // Debug if (logger.isInfoEnabled()) - logger.info("[SMB] SMB Server shutting down ..."); + logger.info("SMB Server shutting down ..."); // Close the host announcer and session handlers @@ -837,7 +811,17 @@ public class SMBServer extends NetworkFileServer implements Runnable // DEBUG - logger.error("[SMB] Error getting local IP addresses", ex); + logger.error("Error getting local IP addresses", ex); } } + + /** + * Return the server GUID + * + * @return UUID + */ + public final UUID getServerGUID() + { + return m_serverGUID; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/filesys/smb/server/SMBSrvException.java b/source/java/org/alfresco/filesys/smb/server/SMBSrvException.java index 882333699e..cad98220fc 100644 --- a/source/java/org/alfresco/filesys/smb/server/SMBSrvException.java +++ b/source/java/org/alfresco/filesys/smb/server/SMBSrvException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -17,6 +17,7 @@ package org.alfresco.filesys.smb.server; import org.alfresco.filesys.smb.SMBErrorText; +import org.alfresco.filesys.smb.SMBStatus; /** * SMB exception class @@ -35,9 +36,16 @@ public class SMBSrvException extends Exception // SMB error code protected int m_errorcode; + + // NT 32-bit error code + + protected int m_NTerror; /** * Construct an SMB exception with the specified error class/error code. + * + * @param errclass int + * @param errcode int */ public SMBSrvException(int errclass, int errcode) { @@ -49,6 +57,10 @@ public class SMBSrvException extends Exception /** * Construct an SMB exception with the specified error class/error code and additional text * error message. + * + * @param errclass int + * @param errcode int + * @param msg String */ public SMBSrvException(int errclass, int errcode, String msg) { @@ -59,6 +71,8 @@ public class SMBSrvException extends Exception /** * Construct an SMB exception using the error class/error code in the SMB packet + * + * @param pkt SMBSrvPacket */ protected SMBSrvException(SMBSrvPacket pkt) { @@ -67,6 +81,21 @@ public class SMBSrvException extends Exception m_errorcode = pkt.getErrorCode(); } + /** + * Construct an SMB exception with the specified error class/error code. + * + * @param nterror int + * @param errclass int + * @param errcode int + */ + public SMBSrvException(int nterror, int errclass, int errcode) + { + super(SMBErrorText.ErrorString(errclass, errcode)); + m_errorclass = errclass; + m_errorcode = errcode; + m_NTerror = nterror; + } + /** * Return the error class for this SMB exception. * @@ -87,6 +116,15 @@ public class SMBSrvException extends Exception return m_errorcode; } + /** + * Return the NT error code + * + * @return int + */ + public int getNTErrorCode() { + return m_NTerror; + } + /** * Return the error text for the SMB exception * @@ -94,6 +132,8 @@ public class SMBSrvException extends Exception */ public String getErrorText() { + if ( getNTErrorCode() != 0) + return SMBErrorText.ErrorString(SMBStatus.NTErr, getNTErrorCode()); return SMBErrorText.ErrorString(m_errorclass, m_errorcode); } } \ No newline at end of file diff --git a/source/java/org/alfresco/filesys/smb/server/SMBSrvPacket.java b/source/java/org/alfresco/filesys/smb/server/SMBSrvPacket.java index 42b44ae197..cd193aa495 100644 --- a/source/java/org/alfresco/filesys/smb/server/SMBSrvPacket.java +++ b/source/java/org/alfresco/filesys/smb/server/SMBSrvPacket.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -74,20 +74,21 @@ public class SMBSrvPacket // Flag bits - public static final int FLG_SUBDIALECT = 0x01; - public static final int FLG_CASELESS = 0x08; - public static final int FLG_CANONICAL = 0x10; - public static final int FLG_OPLOCK = 0x20; - public static final int FLG_NOTIFY = 0x40; - public static final int FLG_RESPONSE = 0x80; + public static final int FLG_SUBDIALECT = 0x01; + public static final int FLG_CASELESS = 0x08; + public static final int FLG_CANONICAL = 0x10; + public static final int FLG_OPLOCK = 0x20; + public static final int FLG_NOTIFY = 0x40; + public static final int FLG_RESPONSE = 0x80; // Flag2 bits - public static final int FLG2_LONGFILENAMES = 0x0001; - public static final int FLG2_EXTENDEDATTRIB = 0x0002; - public static final int FLG2_READIFEXE = 0x2000; - public static final int FLG2_LONGERRORCODE = 0x4000; - public static final int FLG2_UNICODE = 0x8000; + public static final int FLG2_LONGFILENAMES = 0x0001; + public static final int FLG2_EXTENDEDATTRIB = 0x0002; + public static final int FLG2_EXTENDEDSECURITY = 0x0800; + public static final int FLG2_READIFEXE = 0x2000; + public static final int FLG2_LONGERRORCODE = 0x4000; + public static final int FLG2_UNICODE = 0x8000; // Security mode bits diff --git a/source/java/org/alfresco/filesys/smb/server/SMBSrvSession.java b/source/java/org/alfresco/filesys/smb/server/SMBSrvSession.java index cf6761e017..fa924a6944 100644 --- a/source/java/org/alfresco/filesys/smb/server/SMBSrvSession.java +++ b/source/java/org/alfresco/filesys/smb/server/SMBSrvSession.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -29,7 +29,8 @@ import org.alfresco.filesys.netbios.NetBIOSPacket; import org.alfresco.filesys.netbios.NetBIOSSession; import org.alfresco.filesys.netbios.RFCNetBIOSProtocol; import org.alfresco.filesys.server.SrvSession; -import org.alfresco.filesys.server.auth.SrvAuthenticator; +import org.alfresco.filesys.server.auth.AuthenticatorException; +import org.alfresco.filesys.server.auth.CifsAuthenticator; import org.alfresco.filesys.server.core.DeviceInterface; import org.alfresco.filesys.server.core.SharedDevice; import org.alfresco.filesys.server.filesys.DiskDeviceContext; @@ -66,17 +67,18 @@ import org.apache.commons.logging.LogFactory; public class SMBSrvSession extends SrvSession implements Runnable { // Debug logging + private static Log logger = LogFactory.getLog("org.alfresco.smb.protocol"); // Define the default receive buffer size to allocate. - private static final int DefaultBufferSize = 0x010000 + RFCNetBIOSProtocol.HEADER_LEN; - private static final int LanManBufferSize = 8192; + public static final int DefaultBufferSize = 0x010000 + RFCNetBIOSProtocol.HEADER_LEN; + public static final int LanManBufferSize = 8192; // Default and maximum number of connection slots - private static final int DefaultConnections = 4; - private static final int MaxConnections = 16; + public static final int DefaultConnections = 4; + public static final int MaxConnections = 16; // Tree ids are 16bit values @@ -92,12 +94,12 @@ public class SMBSrvSession extends SrvSession implements Runnable // // Setting NTMaxMultiplexed to one will disable asynchronous notifications on the client - private static final int LanManMaxMultiplexed = 1; - private static final int NTMaxMultiplexed = 4; + public static final int LanManMaxMultiplexed = 1; + public static final int NTMaxMultiplexed = 4; // Maximum number of virtual circuits - private static final int MaxVirtualCircuits = 0; + public static final int MaxVirtualCircuits = 0; // Packet handler used to send/receive SMB packets over a particular protocol @@ -148,7 +150,7 @@ public class SMBSrvSession extends SrvSession implements Runnable private NotifyRequestList m_notifyList; private boolean m_notifyPending; - // Default SMB/CIFS flags anf flags2, ORed with the SMB packet flags/flags2 before sending a + // Default SMB/CIFS flags and flags2, ORed with the SMB packet flags/flags2 before sending a // response to the client. private int m_defFlags; @@ -171,6 +173,10 @@ public class SMBSrvSession extends SrvSession implements Runnable private int m_clientCaps; + // Session setup object, temporarily stored by an authenticator when the authentication is multi-stage + + private Object m_setupObject; + // Debug flag values public static final int DBG_NETBIOS = 0x00000001; // NetBIOS layer @@ -188,10 +194,10 @@ public class SMBSrvSession extends SrvSession implements Runnable public static final int DBG_LOCK = 0x00001000; // Lock/unlock requests public static final int DBG_PKTTYPE = 0x00002000; // Received packet type public static final int DBG_DCERPC = 0x00004000; // DCE/RPC - public static final int DBG_STATECACHE = 0x00008000; // File state cache - public static final int DBG_NOTIFY = 0x00010000; // Asynchronous change notification - public static final int DBG_STREAMS = 0x00020000; // NTFS streams - public static final int DBG_SOCKET = 0x00040000; // NetBIOS/native SMB socket connections + public static final int DBG_STATECACHE =0x00008000; // File state cache + public static final int DBG_NOTIFY = 0x00010000; // Asynchronous change notification + public static final int DBG_STREAMS = 0x00020000; // NTFS streams + public static final int DBG_SOCKET = 0x00040000; // NetBIOS/native SMB socket connections /** * Class constructor. @@ -806,6 +812,36 @@ public class SMBSrvSession extends SrvSession implements Runnable return getSMBServer().getServerName(); } + /** + * Determine if the session has a setup object + * + * @return boolean + */ + public final boolean hasSetupObject() + { + return m_setupObject != null; + } + + /** + * Return the session setup object + * + * @return Object + */ + public final Object getSetupObject() + { + return m_setupObject; + } + + /** + * Return the session state + * + * @return int + */ + public final int isState() + { + return m_state; + } + /** * Hangup the session. * @@ -947,11 +983,26 @@ public class SMBSrvSession extends SrvSession implements Runnable if (logger.isDebugEnabled() && hasDebug(DBG_STATE)) logger.debug("State changed to " + SMBSrvSessionState.getStateAsString(state)); + // Clear the setup object if the new state is the main session state + + if ( state == SMBSrvSessionState.SMBSESSION) + m_setupObject = null; + // Change the session state m_state = state; } + /** + * Set the setup object + * + * @param obj Object + */ + public final void setSetupObject( Object obj) + { + m_setupObject = obj; + } + /** * Process the NetBIOS session request message, either accept the session request and send back * a NetBIOS accept or reject the session and send back a NetBIOS reject and hangup the session. @@ -1122,7 +1173,7 @@ public class SMBSrvSession extends SrvSession implements Runnable // Find the highest level SMB dialect that the server and client both support - DialectSelector dia = getSMBServer().getSMBDialects(); + DialectSelector dia = getSMBServer().getConfiguration().getAuthenticator().getEnabledDialects(); int diaIdx = -1; for (int i = 0; i < Dialect.Max; i++) @@ -1198,13 +1249,16 @@ public class SMBSrvSession extends SrvSession implements Runnable { // Could not get a protocol handler for the selected SMB dialect, indicate to the - // client - // that no suitable dialect available. + // client that no suitable dialect available. diaIdx = -1; } } + // Check if the extended security flag has been set by the client + + boolean extendedSecurity = (m_smbPkt.getFlags2() & SMBSrvPacket.FLG2_EXTENDEDSECURITY) != 0 ? true : false; + // Build the negotiate response SMB for Core dialect if (m_dialect == -1 || m_dialect <= Dialect.CorePlus) @@ -1228,35 +1282,19 @@ public class SMBSrvSession extends SrvSession implements Runnable m_smbPkt.setFlags2(SMBSrvPacket.FLG2_LONGFILENAMES); // Access the authenticator for this server and determine if the server is in share or - // user level - // security mode. + // user level security mode. - SrvAuthenticator auth = getServer().getConfiguration().getAuthenticator(); - int secMode = 0; - - if (auth != null) - { - - // Check if the server is in share or user level security mode - - if (auth.getAccessMode() == SrvAuthenticator.USER_MODE) - secMode = 1; - - // Check if encrypted passwords should be used by the client - - if (auth.hasEncryptPasswords()) - secMode += 2; - } + CifsAuthenticator auth = getServer().getConfiguration().getAuthenticator(); // LanMan dialect negotiate response m_smbPkt.setParameterCount(13); m_smbPkt.setParameter(0, diaIdx); - m_smbPkt.setParameter(1, secMode); // Security mode, encrypt passwords + m_smbPkt.setParameter(1, auth.getSecurityMode()); m_smbPkt.setParameter(2, LanManBufferSize); m_smbPkt.setParameter(3, LanManMaxMultiplexed); // maximum multiplexed requests - m_smbPkt.setParameter(4, MaxVirtualCircuits); // maximum number of virtual circuits - m_smbPkt.setParameter(5, 0); // read/write raw mode support + m_smbPkt.setParameter(4, MaxVirtualCircuits); // maximum number of virtual circuits + m_smbPkt.setParameter(5, 0); // read/write raw mode support // Create a session token, using the system clock @@ -1274,43 +1312,32 @@ public class SMBSrvSession extends SrvSession implements Runnable // Encryption key length - m_smbPkt.setParameter(11, 8); // Encryption key length + m_smbPkt.setParameter(11, auth.getEncryptionKeyLength()); m_smbPkt.setParameter(12, 0); - // Encryption key and primary domain string should be returned in the byte area - - setChallengeKey(auth.getChallengeKey(this)); - int pos = m_smbPkt.getByteOffset(); - byte[] buf = m_smbPkt.getBuffer(); - - if (hasChallengeKey() == false) - { - - // Return a dummy encryption key - - for (int i = 0; i < 8; i++) - buf[pos++] = 0; - } - else - { - - // Store the encryption key - - byte[] key = getChallengeKey(); - for (int i = 0; i < key.length; i++) - buf[pos++] = key[i]; - } - - // Set the local domain name - - String domain = getServer().getConfiguration().getDomainName(); - if (domain != null) - pos = DataPacker.putString(domain, buf, pos, true); - - m_smbPkt.setByteCount(pos - m_smbPkt.getByteOffset()); - m_smbPkt.setTreeId(0); m_smbPkt.setUserId(0); + + // Let the authenticator pack any remaining fields in the negotiate response + + try + { + // Pack the remaining negotiate response fields + + auth.generateNegotiateResponse( this, m_smbPkt, extendedSecurity); + } + catch ( AuthenticatorException ex) + { + // Log the error + + if ( logger.isErrorEnabled()) + logger.error("Negotiate error", ex); + + // Close the session + + setState(SMBSrvSessionState.NBHANGUP); + return; + } } else if (m_dialect == Dialect.NT) { @@ -1323,33 +1350,18 @@ public class SMBSrvSession extends SrvSession implements Runnable // Access the authenticator for this server and determine if the server is in share or // user level security mode. - SrvAuthenticator auth = getServer().getConfiguration().getAuthenticator(); - int secMode = 0; - - if (auth != null) - { - - // Check if the server is in share or user level security mode - - if (auth.getAccessMode() == SrvAuthenticator.USER_MODE) - secMode = 1; - - // Check if encrypted passwords should be used by the client - - if (auth.hasEncryptPasswords()) - secMode += 2; - } + CifsAuthenticator auth = getServer().getConfiguration().getAuthenticator(); // NT dialect negotiate response NTParameterPacker nt = new NTParameterPacker(m_smbPkt.getBuffer()); m_smbPkt.setParameterCount(17); - nt.packWord(diaIdx); // selected dialect index - nt.packByte(secMode); // security mode - nt.packWord(NTMaxMultiplexed); // maximum multiplexed requests - // setting to 1 will disable change notify requests from the client - nt.packWord(MaxVirtualCircuits); // maximum number of virtual circuits + nt.packWord(diaIdx); // selected dialect index + nt.packByte(auth.getSecurityMode()); + nt.packWord(NTMaxMultiplexed); // maximum multiplexed requests + // setting to 1 will disable change notify requests from the client + nt.packWord(MaxVirtualCircuits); // maximum number of virtual circuits int maxBufSize = m_smbPkt.getBuffer().length - RFCNetBIOSProtocol.HEADER_LEN; nt.packInt(maxBufSize); @@ -1360,10 +1372,13 @@ public class SMBSrvSession extends SrvSession implements Runnable nt.packInt((int) (System.currentTimeMillis() & 0xFFFFFFFFL)); - // Set server capabilities + // Set server capabilities, switch off extended security if the client does not support it - nt.packInt(Capability.Unicode + Capability.RemoteAPIs + Capability.NTSMBs + Capability.NTFind - + Capability.NTStatus + Capability.LargeFiles + Capability.LargeRead + Capability.LargeWrite); + int srvCapabs = auth.getServerCapabilities(); + if ( extendedSecurity == false) + srvCapabs &= ~Capability.ExtendedSecurity; + + nt.packInt(srvCapabs); // Return the current server date/time, and timezone offset @@ -1374,53 +1389,34 @@ public class SMBSrvSession extends SrvSession implements Runnable // Encryption key length - nt.packByte(8); // encryption key length - - // Encryption key and primary domain string should be returned in the byte area - - setChallengeKey(auth.getChallengeKey(this)); - - int pos = m_smbPkt.getByteOffset(); - byte[] buf = m_smbPkt.getBuffer(); - - if (hasChallengeKey() == false) - { - - // Return a dummy encryption key - - for (int i = 0; i < 8; i++) - buf[pos++] = 0; - } - else - { - - // Store the encryption key - - byte[] key = getChallengeKey(); - - for (int i = 0; i < key.length; i++) - buf[pos++] = key[i]; - } - - // Pack the local domain name - - String domain = getServer().getConfiguration().getDomainName(); - if (domain != null) - pos = DataPacker.putUnicodeString(domain, buf, pos, true); - - // Pack the server name - - pos = DataPacker.putUnicodeString(getServerName(), buf, pos, true); - - // Set the packet length - - m_smbPkt.setByteCount(pos - m_smbPkt.getByteOffset()); + nt.packByte( auth.getEncryptionKeyLength()); m_smbPkt.setFlags( getDefaultFlags()); m_smbPkt.setFlags2( getDefaultFlags2()); m_smbPkt.setTreeId(0); m_smbPkt.setUserId(0); + + // Let the authenticator pack any remaining fields in the negotiate response + + try + { + // Pack the remaining negotiate response fields + + auth.generateNegotiateResponse( this, m_smbPkt, extendedSecurity); + } + catch ( AuthenticatorException ex) + { + // Log the error + + if ( logger.isErrorEnabled()) + logger.error("Negotiate error", ex); + + // Close the session + + setState(SMBSrvSessionState.NBHANGUP); + return; + } } // Make sure the response flag is set @@ -1433,8 +1429,7 @@ public class SMBSrvSession extends SrvSession implements Runnable m_pktHandler.writePacket(m_smbPkt, m_smbPkt.getLength()); // Check if the negotiated SMB dialect supports the session setup command, if not then - // bypass - // the session setup phase. + // bypass the session setup phase. if (m_dialect == -1) setState(SMBSrvSessionState.NBHANGUP); @@ -1724,7 +1719,7 @@ public class SMBSrvSession extends SrvSession implements Runnable // Mask out certain flags that the client may have sent int flags2 = pkt.getFlags2() | getDefaultFlags2(); - flags2 &= ~(SMBPacket.FLG2_EXTENDEDATTRIB + SMBPacket.FLG2_EXTENDNEGOTIATE + SMBPacket.FLG2_DFSRESOLVE + SMBPacket.FLG2_SECURITYSIGS); + flags2 &= ~(SMBPacket.FLG2_EXTENDEDATTRIB + SMBPacket.FLG2_DFSRESOLVE + SMBPacket.FLG2_SECURITYSIGS); pkt.setFlags2(flags2); diff --git a/source/java/org/alfresco/filesys/smb/server/SecurityMode.java b/source/java/org/alfresco/filesys/smb/server/SecurityMode.java new file mode 100644 index 0000000000..8cac16b4f4 --- /dev/null +++ b/source/java/org/alfresco/filesys/smb/server/SecurityMode.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2005-2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.filesys.smb.server; + +/** + * Security Mode Class + * + *

CIFS security mode constants. + * + * @author gkspencer + */ +public class SecurityMode +{ + // Security mode flags returned in the SMB negotiate response + + public static final int UserMode = 0x0001; + public static final int EncryptedPasswords = 0x0002; + public static final int SignaturesEnabled = 0x0004; + public static final int SignaturesRequired = 0x0008; +} diff --git a/source/java/org/alfresco/filesys/smb/server/SessionSocketHandler.java b/source/java/org/alfresco/filesys/smb/server/SessionSocketHandler.java index 4d869c2154..fc4d93e264 100644 --- a/source/java/org/alfresco/filesys/smb/server/SessionSocketHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/SessionSocketHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -252,7 +252,7 @@ public abstract class SessionSocketHandler implements Runnable // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Binding " + getName() + " session handler to local address : " + logger.debug("Binding " + getName() + " session handler to local address : " + (hasBindAddress() ? getBindAddress().getHostAddress() : "ALL")); } diff --git a/source/java/org/alfresco/filesys/smb/server/TcpipSMBSessionSocketHandler.java b/source/java/org/alfresco/filesys/smb/server/TcpipSMBSessionSocketHandler.java index 79aaf90123..bbc6a235d3 100644 --- a/source/java/org/alfresco/filesys/smb/server/TcpipSMBSessionSocketHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/TcpipSMBSessionSocketHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -63,7 +63,7 @@ public class TcpipSMBSessionSocketHandler extends SessionSocketHandler // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Waiting for TCP-SMB session request ..."); + logger.debug("Waiting for TCP-SMB session request ..."); // Wait for a connection @@ -72,7 +72,7 @@ public class TcpipSMBSessionSocketHandler extends SessionSocketHandler // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] TCP-SMB session request received from " + logger.debug("TCP-SMB session request received from " + sessSock.getInetAddress().getHostAddress()); try @@ -106,7 +106,7 @@ public class TcpipSMBSessionSocketHandler extends SessionSocketHandler // Debug - logger.error("[SMB] TCP-SMB Failed to create session, ", ex); + logger.error("TCP-SMB Failed to create session, ", ex); } } } @@ -117,7 +117,7 @@ public class TcpipSMBSessionSocketHandler extends SessionSocketHandler // causes an exception to be thrown. if (hasShutdown() == false) - logger.error("[SMB] TCP-SMB Socket error : ", ex); + logger.error("TCP-SMB Socket error : ", ex); } catch (Exception ex) { @@ -126,13 +126,13 @@ public class TcpipSMBSessionSocketHandler extends SessionSocketHandler // causes an exception to be thrown. if (hasShutdown() == false) - logger.error("[SMB] TCP-SMB Server error : ", ex); + logger.error("TCP-SMB Server error : ", ex); } // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] TCP-SMB session handler closed"); + logger.debug("TCP-SMB session handler closed"); } /** @@ -166,6 +166,6 @@ public class TcpipSMBSessionSocketHandler extends SessionSocketHandler // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] Native SMB TCP session handler created"); + logger.debug("Native SMB TCP session handler created"); } } diff --git a/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSLanaMonitor.java b/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSLanaMonitor.java index 8cd03c20ce..a0341b122e 100644 --- a/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSLanaMonitor.java +++ b/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSLanaMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -179,7 +179,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS register listener for LANA " + lana); + logger.debug("Win32 NetBIOS register listener for LANA " + lana); } /** @@ -221,7 +221,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS initialization error", ex); + logger.debug("Win32 NetBIOS initialization error", ex); // Shutdown the LANA monitor thread @@ -273,7 +273,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS found new LANA, " + lana); + logger.debug("Win32 NetBIOS found new LANA, " + lana); // Create a single Win32 NetBIOS session handler using the specified LANA @@ -289,7 +289,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS failed to create session handler for LANA " + lana, + logger.debug("Win32 NetBIOS failed to create session handler for LANA " + lana, ex); // Clear the session handler @@ -316,7 +316,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS created session handler on LANA " + lana); + logger.debug("Win32 NetBIOS created session handler on LANA " + lana); // Check if a host announcer should be enabled @@ -336,7 +336,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS host announcer enabled on LANA " + lana); + logger.debug("Win32 NetBIOS host announcer enabled on LANA " + lana); } // Set the LANA in the available LANA list, and set the current status to online @@ -364,7 +364,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS LANA online - " + lana); + logger.debug("Win32 NetBIOS LANA online - " + lana); } } } @@ -378,7 +378,7 @@ public class Win32NetBIOSLanaMonitor extends Thread // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS LANA offline - " + i); + logger.debug("Win32 NetBIOS LANA offline - " + i); // Change the LANA status diff --git a/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSSessionSocketHandler.java b/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSSessionSocketHandler.java index 0a29399cc3..8574cbe223 100644 --- a/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSSessionSocketHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/win32/Win32NetBIOSSessionSocketHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -134,7 +134,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS server " + m_srvName + " (using " + + logger.debug("Win32 NetBIOS server " + m_srvName + " (using " + (isUsingWinsock() ? "Winsock" : "Netbios() API") + ")"); // Set the LANA offline polling interval @@ -176,7 +176,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS server " + m_srvName + " (using " + + logger.debug("Win32 NetBIOS server " + m_srvName + " (using " + (isUsingWinsock() ? "Winsock" : "Netbios() API") + ")"); // Set the LANA offline polling interval @@ -215,7 +215,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS server " + m_srvName + " (using " + + logger.debug("Win32 NetBIOS server " + m_srvName + " (using " + (isUsingWinsock() ? "Winsock" : "Netbios() API") + ")"); // Set the LANA offline polling interval @@ -504,7 +504,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple if (logger.isDebugEnabled() && hasDebug()) { - logger.debug("[SMB] Win32 NetBIOS Failed To ReInitialize LANA"); + logger.debug("Win32 NetBIOS Failed To ReInitialize LANA"); logger.debug(" " + ex.getMessage()); } } @@ -512,7 +512,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // DEBUG if (logger.isDebugEnabled() && hasDebug() && isLANAValid()) - logger.debug("[SMB] Win32 NetBIOS LANA " + getLANANumber() + " Back Online"); + logger.debug("Win32 NetBIOS LANA " + getLANANumber() + " Back Online"); } } } @@ -524,7 +524,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple if (hasShutdown() == false) { - logger.debug("[SMB] Win32 NetBIOS Server error : " + ex.toString()); + logger.debug("Win32 NetBIOS Server error : " + ex.toString()); logger.debug(ex); } } @@ -532,7 +532,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS session handler closed"); + logger.debug("Win32 NetBIOS session handler closed"); } /** @@ -546,7 +546,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Waiting for Win32 NetBIOS session request (Netbios API) ..."); + logger.debug("Waiting for Win32 NetBIOS session request (Netbios API) ..."); // Clear the caller name @@ -585,7 +585,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS session request received, lsn=" + lsn + ", caller=[" + logger.debug("Win32 NetBIOS session request received, lsn=" + lsn + ", caller=[" + callerName + "]"); // Create a packet handler for the session @@ -616,7 +616,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS Failed to create session, " + ex.toString()); + logger.debug("Win32 NetBIOS Failed to create session, " + ex.toString()); } } else @@ -637,10 +637,10 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // DEBUG if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS LANA offline/disabled, LANA=" + getLANANumber()); + logger.debug("Win32 NetBIOS LANA offline/disabled, LANA=" + getLANANumber()); } else if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Win32 NetBIOS Listen error, 0x" + Integer.toHexString(-lsn) + ", " + logger.debug("Win32 NetBIOS Listen error, 0x" + Integer.toHexString(-lsn) + ", " + NetBIOS.getErrorString(-lsn)); } } @@ -656,7 +656,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Waiting for Win32 NetBIOS session request (Winsock) ..."); + logger.debug("Waiting for Win32 NetBIOS session request (Winsock) ..."); // Wait for a new NetBIOS session @@ -700,7 +700,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Winsock NetBIOS network down, LANA=" + m_lana); + logger.debug("Winsock NetBIOS network down, LANA=" + m_lana); } } else @@ -708,7 +708,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (hasShutdown() == false && logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Winsock NetBIOS listen error, " + ex.getMessage()); + logger.debug("Winsock NetBIOS listen error, " + ex.getMessage()); } } @@ -730,7 +730,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Winsock NetBIOS session request received, caller=" + logger.debug("Winsock NetBIOS session request received, caller=" + sessSock.getName()); // Create a packet handler for the session @@ -761,7 +761,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // Debug if (logger.isDebugEnabled() && hasDebug()) - logger.debug("[SMB] Winsock NetBIOS Failed to create session, " + ex.toString()); + logger.debug("Winsock NetBIOS Failed to create session, " + ex.toString()); } } } @@ -794,7 +794,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple lanaStr.append(" "); } } - logger.debug("[SMB] Win32 NetBIOS Available LANAs: " + lanaStr.toString()); + logger.debug("Win32 NetBIOS Available LANAs: " + lanaStr.toString()); } // Check if the Win32 NetBIOS session handler should use a particular LANA/network adapter @@ -821,7 +821,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple if (logger.isDebugEnabled() && sockDbg) { - logger.debug("[SMB] Win32 NetBIOS failed to create session handler for LANA " + logger.debug("Win32 NetBIOS failed to create session handler for LANA " + config.getWin32LANA()); logger.debug(" " + ex.getMessage()); } @@ -840,7 +840,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] Win32 NetBIOS created session handler on LANA " + config.getWin32LANA()); + logger.debug("Win32 NetBIOS created session handler on LANA " + config.getWin32LANA()); // Check if a host announcer should be enabled @@ -879,7 +879,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] Win32 NetBIOS host announcer enabled on LANA " + config.getWin32LANA()); + logger.debug("Win32 NetBIOS host announcer enabled on LANA " + config.getWin32LANA()); } // Check if the session handler implements the LANA listener interface @@ -921,7 +921,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple if (logger.isDebugEnabled() && sockDbg) { - logger.debug("[SMB] Win32 NetBIOS failed to create session handler for LANA " + lana); + logger.debug("Win32 NetBIOS failed to create session handler for LANA " + lana); logger.debug(" " + ex.getMessage()); } } @@ -939,7 +939,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] Win32 NetBIOS created session handler on LANA " + lana); + logger.debug("Win32 NetBIOS created session handler on LANA " + lana); // Check if a host announcer should be enabled @@ -978,7 +978,7 @@ public class Win32NetBIOSSessionSocketHandler extends SessionSocketHandler imple // DEBUG if (logger.isDebugEnabled() && sockDbg) - logger.debug("[SMB] Win32 NetBIOS host announcer enabled on LANA " + lana); + logger.debug("Win32 NetBIOS host announcer enabled on LANA " + lana); } // Check if the session handler implements the LANA listener interface diff --git a/source/java/org/alfresco/filesys/smb/server/win32/WinsockNetBIOSPacketHandler.java b/source/java/org/alfresco/filesys/smb/server/win32/WinsockNetBIOSPacketHandler.java index 4154f188da..e008a5d1f5 100644 --- a/source/java/org/alfresco/filesys/smb/server/win32/WinsockNetBIOSPacketHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/win32/WinsockNetBIOSPacketHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2006 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -127,6 +127,8 @@ public class WinsockNetBIOSPacketHandler extends PacketHandler int rxlen2 = m_sessSock.read(pkt.getBuffer(), rxlen + 4, pkt.getBufferLength() - (rxlen + 4)); + System.out.println("Winsock rx2 len=" + rxlen2); + if ( rxlen2 == ReceiveBufferSizeError) throw new WinsockNetBIOSException(WinsockError.WsaEMsgSize); @@ -140,7 +142,8 @@ public class WinsockNetBIOSPacketHandler extends PacketHandler { // Check if the remote client has closed the socket - if ( ex.getErrorCode() == WinsockError.WsaEConnReset) + if ( ex.getErrorCode() == WinsockError.WsaEConnReset || + ex.getErrorCode() == WinsockError.WsaEDiscon) { // Indicate that the socket has been closed