%PDF- %PDF-
Direktori : /opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/malwarelib/cleanup/ |
Current File : //opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/malwarelib/cleanup/storage.py |
""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. Copyright © 2019 Cloud Linux Software Inc. This software is also available under ImunifyAV commercial license, see <https://www.imunify360.com/legal/eula> """ import logging from pathlib import Path from defence360agent.contracts.config import Malware as Config from defence360agent.malwarelib.scan.crontab import is_crontab from defence360agent.malwarelib.subsys.malware import MalwareAction from defence360agent.malwarelib.utils import hash_path, safe_fileops logger = logging.getLogger(__name__) class CleanupStorage: """ Store files before cleanup and restore them by request """ path: Path = Path(Config.CLEANUP_STORAGE) @staticmethod async def _copy(src: Path, dst: Path, safe_src=False, safe_dst=False): await safe_fileops.safe_move( str(src), str(dst), src_unlink=False, dst_overwrite=True, safe_src=safe_src, safe_dst=safe_dst, ) @classmethod def storage_name(cls, filename: str) -> str: """ Get file name for cleanup storage :return: file name """ return hash_path(filename) @classmethod def get_hit_store_path(cls, hit): return cls.path / cls.storage_name(hit.orig_file) @classmethod async def store(cls, hit): src = hit.orig_file_path dst = cls.get_hit_store_path(hit) safe_src = is_crontab(src) await cls._copy(src, dst, safe_src=safe_src, safe_dst=True) @classmethod async def store_all(cls, hits): if not cls.path.exists(): cls.path.mkdir(0o700) succeeded, not_exist, failed = set(), set(), set() for hit in hits: try: await cls.store(hit) succeeded.add(hit) except FileNotFoundError: not_exist.add(hit) except (OSError, safe_fileops.UnsafeFileOperation) as e: logger.warning("Failed to store file before cleanup: %r -- %s", str(hit), e) failed.add(hit) await MalwareAction.cleanup_failed_store(hit.orig_file, hit.user) return succeeded, failed, not_exist @classmethod async def restore(cls, hit): src = cls.get_hit_store_path(hit) dst = hit.orig_file_path safe_dst = is_crontab(dst) await cls._copy(src, dst, safe_src=True, safe_dst=safe_dst) @classmethod async def restore_all(cls, hits): succeeded, failed = set(), set() for hit in hits: try: await cls.restore(hit) await MalwareAction.cleanup_restored_original( hit.orig_file, hit.user ) succeeded.add(hit) except (OSError, safe_fileops.UnsafeFileOperation) as e: await MalwareAction.cleanup_failed_restore( hit.orig_file, hit.user ) logger.warning("Failed to restore file: %r -- %s", str(hit), e) failed.add(hit) return succeeded, failed @classmethod async def _clear(cls, path: Path, keep: float) -> bool: st = path.stat() if st.st_mtime < keep: path.unlink() return True return False @classmethod async def clear(cls, keep: float) -> int: """ Clear storage :param keep: keep files after specified timestamp :return: """ cls.path.mkdir(0o700, exist_ok=True) cleared = 0 for path in cls.path.iterdir(): if await cls._clear(path, keep): cleared += 1 return cleared