"""
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 .
Copyright © 2019 Cloud Linux Software Inc.
This software is also available under ImunifyAV commercial license,
see
"""
from enum import Enum
class MalwareScanType:
"""The type of a scan represents how and why it is executed"""
#: .. deprecated:: no longer used
MALWARE_RESPONSE = "malware-response"
#: A scan of arbitrary path or path pattern started by admin or user.
ON_DEMAND = "on-demand"
#: A batch of files scanned by resident mode AI-BOLIT.
#:
#: FIXME this scan type is also used as a default in
#: :meth:`.Scanner._process_scan_task`
#: Afaik, because of this, rescans triggered by ignore list removal,
#: have this `type`. I'm not sure if there are more.
REALTIME = "realtime"
#: Used in :class:`.MalwareHistory` to indicate a manual action on a file,
#: not directly caused by any scan.
#:
#: .. deprecated:: - FIXME this is not really a scan type...
MANUAL = "manual"
#: Similar to :attr:`MalwareScanType.USER`, but started from our cron job.
#:
#: See the `MALWARE_SCAN_SCHEDULE` config option for more info.
#: Background scans are reported to ClickHouse even if there was
#: no malware found.
BACKGROUND = "background"
#: Correlation server asked to rescan some files.
RESCAN = "rescan"
#: Rescan triggered by the agent when file is modified after scanning
RESCAN_OUTDATED = "rescan-outdated"
#: ModSec rule triggered a scan on file upload.
#:
#: .. deprecated:: 4.4.0
#: was used for ModSec upload scans before resident mode AI-BOLIT
#: (DEF-9201)
MODSEC = "modsec"
#: A scan of one user home directory.
USER = "user"
#: An attempt to find a clean version of a file in backups.
RESTORE_FROM_BACKUP = "restore_from_backup"
AIBOLIT_SCAN_INTENSITY_KEY = {
MalwareScanType.ON_DEMAND: "aibolit-on_demand",
MalwareScanType.BACKGROUND: "aibolit-background",
MalwareScanType.USER: "aibolit-user",
MalwareScanType.RESCAN: "aibolit-rescan",
MalwareScanType.RESCAN_OUTDATED: "aibolit-rescan",
MalwareScanType.REALTIME: "aibolit-realtime",
MalwareScanType.RESTORE_FROM_BACKUP: "aibolit-restore_from_backup",
}
APP_VERSION_DETECTOR_INTENSITY_KEY = "app_version_detector"
HSDB_MAKER_INTENSITY_KEY = "aibolit-hsdb_maker"
RESTORE_ORIGINAL_INTENSITY_KEY = "aibolit-restore_original"
PHP_PATH = "/opt/alt/php-internal/usr/bin/php"
SUCCESSFUL_EVENTS = (
DELETED,
FOUND,
ADDED_TO_IGNORE,
DELETED_FROM_IGNORE,
SUBMITTED_FOR_ANALYSIS,
CLEANUP_DONE,
CLEANUP_REMOVED,
RESTORED_ORIGINAL,
# FIXME: not used. Should we save this event in history?
RESTORE_FROM_BACKUP_STARTED,
RESTORED_FROM_BACKUP,
) = (
"deleted",
"found",
"added_to_ignore",
"deleted_from_ignore",
"submitted_for_analysis",
"cleanup_done",
"cleanup_removed",
"restored_original",
"restore_from_backup_started",
"restored_from_backup",
)
FAILED_EVENTS = (
# FIXME: not used
FAILED_TO_DELETE,
# FIXME: not used
FAILED_TO_RESTORE_FROM_BACKUP,
FAILED_TO_IGNORE,
FAILED_TO_DELETE_FROM_IGNORE,
FAILED_TO_CLEANUP,
FAILED_TO_RESTORE_ORIGINAL,
UNABLE_TO_CLEANUP,
FAILED_TO_STORE_ORIGINAL,
REQUIRES_MYIMUNIFY_PROTECTION,
) = (
"failed_to_delete",
"failed_to_restore_from_backup",
"failed_to_ignore",
"failed_to_delete_from_ignore",
"failed_to_cleanup",
"failed_to_restore_original",
"unable_to_cleanup",
"failed_to_store_original",
"requires_myimunify_protection",
)
class MalwareEvent:
def __init__(self, title):
self.title = title
@property
def successful(self) -> bool:
return self.title in SUCCESSFUL_EVENTS
@property
def malware_eliminated(self) -> bool:
"""Malware file was deleted or clean copy was restored"""
return self.title in (DELETED, RESTORED_FROM_BACKUP)
class MalwareEventPostponed:
def __init__(self, message, cause, initiator, post_action, action):
self.message = message
self.cause = cause
self.initiator = initiator
self.post_action = post_action
self.action = action
class Hash:
TYPES = WHITE, BLACK = "white", "black"
IS_IGNORED = {BLACK: False, WHITE: True}
class MalwareHitStatus:
"""
The current state of a resource (a file or a db),
defined by the latest scans and actions.
"""
#: The resource is currently malicious or suspicious.
FOUND = "found"
#: *Db only*.
#: The resource is added to the cleanup queue.
CLEANUP_PENDING = "cleanup_pending"
#: *Files*.
#: Attempting to backup the file.
#:
#: *DBs*.
#: MDS cleanup process was started.
CLEANUP_STARTED = "cleanup_started"
#: The resource is successfuly cleaned from malware.
CLEANUP_DONE = "cleanup_done"
#: *File only*.
#: The file content (or the whole file, based on
#: settings) is removed.
CLEANUP_REMOVED = "cleanup_removed"
#: *File only*.
#: The resource requires MyImunify protection for the cleanup
CLEANUP_REQUIRES_MYIMUNIFY_PROTECTION = (
"cleanup_requires_myimunify_protection"
)
#: *Db only*.
#: The resource is added to the restore queue.
CLEANUP_RESTORE_PENDING = "cleanup_restore_pending"
#: *Db only*.
#: MDS restore process has started.
CLEANUP_RESTORE_STARTED = "cleanup_restore_started"
#: *File only*.
#: Similar to :attr:`CLEANUP_STARTED`, the async restoration process has
#: started, but the file is not yet :attr:`RESTORED_FROM_BACKUP`.
RESTORE_FROM_BACKUP_STARTED = "restore_from_backup_started"
#: *File only*.
#: A clean version of the file was found in backups and successfully
#: restored.
RESTORED_FROM_BACKUP = "restored_from_backup"
# TODO: should we add
# CLEANUP_RESTORE_PENDING, CLEANUP_RESTORE_STARTED here?
CLEANUP = (CLEANUP_PENDING, CLEANUP_STARTED, CLEANUP_DONE, CLEANUP_REMOVED)
RESTORABLE = (CLEANUP_DONE, CLEANUP_REMOVED)
class QueuedScanState(Enum):
stopped = "stopped"
running = "running"
queued = "queued"
class MalwareScanResourceType(Enum):
FILE = "file"
DB = "db"
class ExitDetachedScanType:
"""How/why detached scan ended."""
#: It was stopped by a user.
STOPPED = "stopped"
#: It was aborted for other reasons.
ABORTED = "aborted"
NOTIFY, CLEANUP, CLEANUP_ON_SCHEDULE = (
"notify",
"cleanup",
"cleanup_on_schedule",
)