%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/malwarelib/cleanup/
Upload File :
Create Path :
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

Zerion Mini Shell 1.0