Skip to content

Commit

Permalink
Added handling for SMB session timeout (#102)
Browse files Browse the repository at this point in the history
SMB timeout defaults to 3 seconds instead of 0.1, if timeout, error will be shown.
  • Loading branch information
Xre0uS authored Sep 27, 2024
1 parent 147810b commit 2afa708
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 19 deletions.
4 changes: 3 additions & 1 deletion smbclientng/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def parseArgs():
parser.add_argument("-S", "--startup-script", metavar="startup_script", required=False, type=str, help="File containing the list of commands to be typed at start of the console.")
parser.add_argument("-N", "--not-interactive", dest="not_interactive", required=False, action="store_true", default=False, help="Non interactive mode.")
parser.add_argument("-L", "--logfile", dest="logfile", metavar="LOGFILE", required=False, default=None, type=str, help="File to write logs to.")
parser.add_argument( "--timeout", dest="timeout", metavar="TIMEOUT", required=False, type=float, default=3, help="Timeout in seconds for SMB connections (default: 3)")

group_target = parser.add_argument_group("Target")
group_target.add_argument("--host", action="store", metavar="HOST", required=True, type=str, help="IP address or hostname of the SMB Server to connect to.")
Expand Down Expand Up @@ -125,7 +126,8 @@ def main():
sessionsManager.create_new_session(
credentials=credentials,
host=options.host,
port=options.port
port=options.port,
timeout=options.timeout,
)

# Start the main interactive command line
Expand Down
16 changes: 11 additions & 5 deletions smbclientng/core/SMBSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class SMBSession(object):
test_rights(sharename): Tests read and write access rights on a share.
"""

def __init__(self, host, port, credentials, config=None, logger=None):
def __init__(self, host, port, timeout, credentials, config=None, logger=None):
super(SMBSession, self).__init__()
# Objects
self.config = config
Expand All @@ -63,6 +63,8 @@ def __init__(self, host, port, credentials, config=None, logger=None):
self.host = host
# Target port (by default on 445)
self.port = port
# Timeout (default 3 seconds)
self.timeout = timeout

# Credentials
self.credentials = credentials
Expand Down Expand Up @@ -118,14 +120,17 @@ def init_smb_session(self):
self.logger.debug("[>] Connecting to remote SMB server '%s' ... " % self.host)

try:
if is_port_open(self.host, self.port):
result, error = is_port_open(self.host, self.port, self.timeout)
if result:
self.smbClient = impacket.smbconnection.SMBConnection(
remoteName=self.host,
remoteHost=self.host,
sess_port=int(self.port)
sess_port=int(self.port),
timeout=self.timeout,
)
self.connected = True
else:
self.logger.error("Could not connect to '%s:%d'" % (self.host, int(self.port)))
self.logger.error(f"Could not connect to '{self.host}:{self.port}', {error}.")
self.connected = False
self.smbClient = None
except OSError as err:
Expand Down Expand Up @@ -211,7 +216,8 @@ def ping_smb_session(self):
bool: True if the echo command succeeds (indicating the session is active), False otherwise.
"""

if not is_port_open(self.host, self.port):
result, error = is_port_open(self.host, self.port, self.timeout)
if result:
self.connected = False
else:
try:
Expand Down
7 changes: 5 additions & 2 deletions smbclientng/core/SessionsManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, config, logger):
self.config = config
self.logger = logger

def create_new_session(self, credentials, host, port=445):
def create_new_session(self, credentials, host, timeout, port=445):
"""
Creates a new session with the given session information.
Expand All @@ -52,6 +52,7 @@ def create_new_session(self, credentials, host, port=445):
smbSession = SMBSession(
host=host,
port=port,
timeout=timeout,
credentials=credentials,
config=self.config,
logger=self.logger
Expand Down Expand Up @@ -129,6 +130,7 @@ def process_command_line(self, arguments):
group_target = mode_create.add_argument_group("Target")
group_target.add_argument("--host", action="store", metavar="HOST", required=True, type=str, help="IP address or hostname of the SMB Server to connect to.")
group_target.add_argument("--port", action="store", metavar="PORT", type=int, default=445, help="Port of the SMB Server to connect to. (default: 445)")
group_target.add_argument( "--timeout", dest="timeout", metavar="TIMEOUT", required=False, type=float, default=3, help="Timeout in seconds for SMB connections (default: 3)")
authconn = mode_create.add_argument_group("Authentication & connection")
authconn.add_argument("--kdcHost", dest="kdcHost", action="store", metavar="FQDN KDC", help="FQDN of KDC for Kerberos.")
authconn.add_argument("-d", "--domain", dest="auth_domain", metavar="DOMAIN", action="store", default='.', help="(FQDN) domain to authenticate to.")
Expand Down Expand Up @@ -195,7 +197,8 @@ def process_command_line(self, arguments):
self.create_new_session(
credentials=credentials,
host=options.host,
port=options.port
port=options.port,
timeout=options.timeout
)

#
Expand Down
23 changes: 12 additions & 11 deletions smbclientng/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,26 +452,27 @@ def resolve_remote_files(smbSession, arguments):
return resolved_pathFromRoot_files


def is_port_open(target, port) -> bool:
def is_port_open(target, port, timeout):
"""
Check if a specific port on a target host is open.
This function attempts to establish a TCP connection to the specified port on the target host.
If the connection is successful, it indicates that the port is open. If the connection fails,
it indicates that the port is closed or the host is unreachable.
it returns the error message.
Args:
target (str): The hostname or IP address of the target host.
port (int): The port number to check.
timeout (float): The timeout in seconds for the connection attempt. Default is 1.0 second.
Returns:
bool: True if the port is open, False otherwise.
bool, str: True if the port is open, otherwise False and error message.
"""

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.1)
# Non-existant domains cause a lot of errors, added error handling
try:
return s.connect_ex((target, port)) == 0
except Exception as e:
return False
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((target, port))
return True, None
except Exception as e:
return False, str(e)

0 comments on commit 2afa708

Please sign in to comment.