From 3df195865fccbbfb25eeefc4201b988514866fe7 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Wed, 6 Sep 2023 06:07:43 +1000 Subject: [PATCH] Fix DFS recurision for missing files The code that handles a missing path does not currently record existing DFS target servers that have been tried resulting in a recursion error. By ensuring a DFS target is only retried if it hasn't already it should avoid this recursion problem. Fixes: https://github.com/jborean93/smbprotocol/issues/228 --- CHANGELOG.md | 1 + src/smbclient/_io.py | 9 +++++++++ tests/test_smbclient_os.py | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 562cd2c4..3a5e48bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix up pre authenticated session id lookups that were failing with Linux ksmbd * Removes `logging.NullHandler()` being set in the root `smbprotocol` namespace * Adds basic support for remote to local and vice versa file operations with `smbclient.shutil.copytree` +* Fixes DFS infinite recursion error when dealing with a file that does not exist on a DFS namespace ## 1.10.1 - 2022-11-14 diff --git a/src/smbclient/_io.py b/src/smbclient/_io.py index f836c9d5..04b4385c 100644 --- a/src/smbclient/_io.py +++ b/src/smbclient/_io.py @@ -244,6 +244,7 @@ def __init__(self, raw): self.raw = raw self.results = None self._actions = [] + self._attempted_dfs_paths = set() def __add__(self, other): send_msg = other[0] @@ -306,6 +307,14 @@ def commit(self): if smb_open.tree_connect.share_name == self.raw.fd.tree_connect.share_name: continue + # Ensure we don't continuously try the same DFS referral targets if it's already been attempted. + # https://github.com/jborean93/smbprotocol/issues/228 + tested_path = f"{smb_open.tree_connect.share_name}{smb_open.file_name}".lower() + if tested_path in self._attempted_dfs_paths: + continue + + self._attempted_dfs_paths.add(tested_path) + self.raw.fd = smb_open # In case this is a transaction with an explicit open we want to reopen it with the new params diff --git a/tests/test_smbclient_os.py b/tests/test_smbclient_os.py index da91c20a..2b11c9d4 100644 --- a/tests/test_smbclient_os.py +++ b/tests/test_smbclient_os.py @@ -2131,3 +2131,10 @@ def test_broken_dfs_path(smb_real): # error and that it doesn't continuously loop. with pytest.raises(SMBOSError): smbclient.listdir(dfs_path, username=smb_real[0], password=smb_real[1], port=smb_real[3]) + + +def test_dfs_nonexisting_path(smb_dfs_share): + fake_file = ntpath.join(smb_dfs_share, "missing file.txt") + + with pytest.raises(SMBOSError): + smbclient.lstat(fake_file)