diff --git a/CHANGELOG.md b/CHANGELOG.md index 520a0caf317b02437eea977f5c60c17a7236c622..ea6d7b86e338356b9add3bcafd492612aeb4b59e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * Fix unpacking security descriptor ACEs with extra data on the end - https://github.com/jborean93/smbprotocol/pull/143 * Set `index_number` in `FileInternalInformation` to be an unsigned integer to match the other structures +* Clear out expired DFS referrals to avoid memory leaks and stale DFS information - https://github.com/jborean93/smbprotocol/issues/136 + ## 1.7.0 - 2021-09-22 diff --git a/smbclient/_pool.py b/smbclient/_pool.py index 2080a00bf27e4d0cb8011fdd7cabd2095cb870e5..3d69cd633bd1644a0e9da425672b9478eb4ae4d2 100644 --- a/smbclient/_pool.py +++ b/smbclient/_pool.py @@ -5,6 +5,7 @@ import atexit import logging import ntpath +import typing import uuid import warnings @@ -144,18 +145,16 @@ class ClientConfig(object, metaclass=_ConfigSingleton): self._referral_cache.append(ReferralEntry(referral)) def lookup_domain(self, domain_name): # type: (str) -> Optional[DomainEntry] + # TODO: Check domain referral expiry and resend request if expired for domain in self._domain_cache: if domain.domain_name.lower() == ("\\" + domain_name.lower()): return domain - def clear_expired_cache(self): - self._referral_cache = [refferal for refferal in self._referral_cache if not refferal.is_expired] - - def lookup_referral(self, path_components): # type: (List[str]) -> Optional[ReferralEntry] + def lookup_referral(self, path_components: typing.List[str]) -> typing.Optional[ReferralEntry]: """ Checks if the path exists in the DFS referral cache. """ # A lookup in ReferralCache involves searching for an entry with DFSPathPrefix that is a complete prefix of the # path being looked up. - self.clear_expired_cache() + self._clear_expired_cache() hits = [] for referral in self._referral_cache: referral_path_components = [p for p in referral.dfs_path.split("\\") if p] @@ -188,6 +187,9 @@ class ClientConfig(object, metaclass=_ConfigSingleton): if domain_controller: self.domain_controller = config['domain_controller'] + def _clear_expired_cache(self) -> None: + self._referral_cache = [refferal for refferal in self._referral_cache if not refferal.is_expired] + def dfs_request(tree, path): # type: (TreeConnect, str) -> DFSReferralResponse """ Send a DFS Referral request to the IPC tree and return the referrals. """