OXIESEC PANEL
- Current Dir:
/
/
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
clwpos
Server IP: 2a02:4780:11:1084:0:327f:3464:10
Upload:
Create Dir:
Name
Size
Modified
Perms
📁
..
-
09/05/2025 09:34:06 AM
rwxr-xr-x
📄
__init__.py
928 bytes
08/21/2025 03:04:58 PM
rw-r--r--
📁
__pycache__
-
09/05/2025 10:05:18 AM
rwxr-xr-x
📄
billing.py
6.24 KB
08/21/2025 03:04:58 PM
rw-r--r--
📁
bin
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📄
cl_wpos_exceptions.py
3.59 KB
08/21/2025 03:04:58 PM
rw-r--r--
📁
cli_versions
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📄
constants.py
5.56 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
create_user_uid_dirs.py
754 bytes
08/21/2025 03:04:58 PM
rw-r--r--
📄
cron.py
2.14 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
daemon.py
37.12 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
daemon_base.py
2.84 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
daemon_config.py
621 bytes
08/21/2025 03:04:58 PM
rw-r--r--
📄
daemon_redis_lib.py
11.93 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
daemon_subscription_handler.py
6.44 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
data_collector_utils.py
9.42 KB
08/21/2025 03:04:58 PM
rw-r--r--
📁
feature_suites
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📁
hooks
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📄
logsetup.py
4.04 KB
08/21/2025 03:04:58 PM
rw-r--r--
📁
migrations
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📁
object_cache
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📁
optimization_features
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📄
papi.py
9.87 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
parse.py
2.1 KB
08/21/2025 03:04:58 PM
rw-r--r--
📁
php
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📄
redis_configuration_pid_file_cleaner.py
1.01 KB
08/21/2025 03:04:58 PM
rwxr-xr-x
📄
report_generator.py
21.18 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
scoped_cache.py
1.34 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
socket_utils.py
4.03 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
stats.py
12.02 KB
08/21/2025 03:04:58 PM
rw-r--r--
📁
user
-
09/05/2025 09:34:13 AM
rwxr-xr-x
📄
utils.py
53.91 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
whmcs_utils.py
9.36 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
wp_config.py
725 bytes
08/21/2025 03:04:58 PM
rw-r--r--
📄
wp_utils.py
16.33 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
wpos_admin.py
67.14 KB
08/21/2025 03:04:58 PM
rw-r--r--
📄
wpos_hooks.py
4.85 KB
08/21/2025 03:04:58 PM
rwxr-xr-x
📄
wpos_req_scanner.py
4.38 KB
08/21/2025 03:04:58 PM
rw-r--r--
Editing: daemon_subscription_handler.py
Close
import logging import os import pwd import socket import subprocess import time from dataclasses import dataclass from typing import Optional, Dict, List from clcommon.clpwd import drop_user_privileges from clwpos import socket_utils from clwpos.utils import run_in_cagefs_if_needed @dataclass class EnableFeatureTask: uid: int # some arguments that we need when # we enable module manually domain: str wp_path: str # the features list that we would like to enable feature: list # if true, appends --ignore-errors to enable command ignore_errors: bool # time when we give up and # think that waiting is unsuccessful timeout_timestamp: int # optional argument which indicates that # we are applying advice advice_id: Optional[str] = None # pid of the process which took the task in work pid: Optional[int] = None class PendingSubscriptionWatcher: """ Listen to set-suite and user events in order to automatically enable module when suite is purchased. """ # max time that we wait for the feature to be allowed _FEATURE_STATUS_CHECK_TIMEOUT = 180 def __init__(self, logger=None): # list of pending tasks to automatically enable # module when suite is allowed self._pending_enable_tasks: Dict[int, List[EnableFeatureTask]] = dict() self._logger = logger or logging.getLogger(__name__) def _cleanup_pending_tasks(self): """ Cleanup list of pending tasks by removing outdated. """ for uid, pending_tasks in list(self._pending_enable_tasks.items()): for pending_task in pending_tasks: if pending_task.timeout_timestamp >= time.time(): continue if pending_task.pid: try: os.kill(pending_task.pid, 0) continue except OSError: # process is dead pass pending_tasks.remove(pending_task) if not pending_tasks: self._pending_enable_tasks.pop(uid) self._logger.info('Cleanup of pending tasks. Still active tasks %s', self._pending_enable_tasks) def _run_and_log_results(self, args): self._logger.info('Running %s', ' '.join(args)) try: output = run_in_cagefs_if_needed(args, check=True) self._logger.info('Command succeded with output: \n`%s`', output) except subprocess.CalledProcessError as e: self._logger.exception('Unable to activate feature in background. ' 'Stdout is %s. Stderr is %s', e.stdout, e.stderr) except Exception: self._logger.exception('Unable to activate feature in background') self._logger.debug('Finished %s', ' '.join(args)) def _run_enable_command(self, task): if task.advice_id: self._run_and_log_results([ '/opt/alt/php-xray/cl-smart-advice-user', 'apply', '--advice_id', str(task.advice_id) ]) elif task.domain: for f in task.feature: self._logger.info('activate feature in background: feature=%s', f) cmd = [ 'cloudlinux-awp-user', 'enable', '--feature', f, '--domain', task.domain, '--wp-path', task.wp_path ] if task.ignore_errors: cmd.append('--ignore-errors') self._run_and_log_results(cmd) else: logging.info('Task does not have any advice or domain specified, skipping') def suite_allowed_callback(self, client_socket_obj: socket.socket): self._cleanup_pending_tasks() for uid, tasks in list(self._pending_enable_tasks.items()): for task in tasks: fp = os.fork() if fp: self._logger.info('background process forked: pid=%d', fp) task.pid = fp os.waitpid(fp, 0) self._logger.info('background process finished: pid=%d', fp) del self._pending_enable_tasks[uid] else: from clwpos.feature_suites import get_allowed_modules # drop privileges forever.. or at least till the end of process drop_user_privileges(pwd.getpwuid(task.uid).pw_name, effective_or_real=True, set_env=True) allowed_features = get_allowed_modules(task.uid) for f in task.feature: if f not in allowed_features: self._logger.info('unable to activate feature in background: feature=%s is not allowed', f) continue return self._run_enable_command(task) response: dict = { "result": "success" } socket_utils.send_dict_to_socket_connection_and_close(client_socket_obj, response) def add_pending_upgrade_task(self, client_socket_obj: socket.socket, user_request: dict, uid: int): self._cleanup_pending_tasks() if uid not in self._pending_enable_tasks: self._pending_enable_tasks[uid] = [] self._pending_enable_tasks[uid].append(EnableFeatureTask( uid=uid, domain=user_request['domain'], wp_path=user_request['wp_path'], feature=user_request['feature'].split(','), ignore_errors=user_request['ignore_errors'], advice_id=user_request.get('advice_id'), timeout_timestamp=int(time.time() + self._FEATURE_STATUS_CHECK_TIMEOUT) )) self._logger.info('Successfully added pending upgrade subscription task %s', self._pending_enable_tasks[uid]) response: dict = { "result": "success" } socket_utils.send_dict_to_socket_connection_and_close(client_socket_obj, response) def get_upgrade_task_status(self, client_socket_obj: socket.socket, uid: int, feature: str): self._cleanup_pending_tasks() pending_tasks = self._pending_enable_tasks.get(uid, []) response: dict = { "result": "success", "pending": bool(any(feature in pending_task.feature for pending_task in pending_tasks)) } socket_utils.send_dict_to_socket_connection_and_close(client_socket_obj, response)