????
Current Path : /usr/share/cagefs-plugins/ |
Current File : //usr/share/cagefs-plugins/install-cagefs-plugin.py |
#!/opt/cloudlinux/venv/bin/python3 -bb # -*- coding: utf-8 -*- # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT from __future__ import print_function from __future__ import absolute_import from __future__ import division from __future__ import unicode_literals from future import standard_library standard_library.install_aliases() from builtins import * import argparse import grp import os import pwd import shutil import stat import sys import subprocess import cldetectlib as detect from copy_directory import CopyDirectory from exec_command import exec_command, exec_command_null_input from mysql_lib import delete_cagefs_module_plesk from clcommon.utils import ( delete_line_from_file, write_file_lines, ) from clcommon.cpapi import admins, DIRECTADMIN_NAME, getCPName, NotSupported from clcommon.utils import mod_makedirs from clsudo import Clsudo # cagefs imports LIBDIR = '/usr/share/cagefs' sys.path.append(LIBDIR) import cagefsctl import cagefslib import cagefs_without_lve_lib import cagefs_universal_hook_lib from cagefslib import verCompare, add_syslog_socket, remove_syslog_socket from cagefsreconfigure import litespeed_enableLVE_configure, litespeed_config_write, litespeed_lsphp5_path_change from cagefsreconfigure import touch, add_mount_to_cagefs_mp, POSTGRES_CONF, POSTGRES_CL7_FOLDER, DEFAULT_POSTGRES_FOLDER # This line is changed in %build section of securelve.spec CAGEFS_VERSION = "7.6.18" # This line is changed in %build section of securelve.spec CAGEFS_RELEASE = "2.el6.cloudlinux" SKELETON = '/usr/share/cagefs-skeleton' SOURCE_PATH = "/usr/share/cagefs-plugins/" ROOT_PLESK_DIR = "/usr/local/psa/admin/" ROOT_CPANEL_DIR = "/usr/local/cpanel/whostmgr/docroot/" ROOT_IWORX_DIR = "/usr/local/interworx/" ROOT_ISPMGR_DIR = "/usr/local/ispmgr/" ROOT_DA_DIR = "/usr/local/directadmin/plugins/" NEED_PLUGIN = "/etc/cagefs/cagefs.plugin.disable" CPANEL_CRON_PATH = '/etc/cron.d/cagefs_cron' CPANEL_PHP_SESSIONS_CRON_PATH = '/etc/cron.d/cpanel_php_sessions_cron' PLESK_CRON_PHP_CLEANER_HOURLY_PATH = '/etc/cron.hourly/clean_user_alt_php_sessions_plesk' NEW_EXCLUDE_PATH = '/usr/share/cagefs/exclude.d' EXCLUDE_USERS_CRON_FILE = '/etc/cron.d/exclude_users_cagefs_cron' CREATE_NAMESPACES_CRON_FILE = '/etc/cron.d/create_namespaces_cagefs_cron' def manage_cron_file(): if verCompare(cp.version,'55.9999') < 0: create_cron_multiphp() else: if os.path.isfile(CPANEL_CRON_PATH): os.unlink(CPANEL_CRON_PATH) def update_sudoers(user): def exit_with_error(message, status=1): sys.stderr.write("%s\n" % (str(message,))) sys.exit(status) try: from clsudo import ( NoSuchUser, UnableToReadFile, UnableToWriteFile) sudo = Clsudo() sudo.add_cagefs_user(user) except ImportError: exit_with_error("Cannot import Clsudo. Check if python-cllib package installed") except (NoSuchUser, UnableToReadFile, UnableToWriteFile) as e: exit_with_error(e) def create_cron_multiphp(): """ This func creates cron task which run every 10 minutes """ if not os.path.exists(CPANEL_CRON_PATH): f = open(CPANEL_CRON_PATH,'w') f.write('*/10 * * * * root /usr/bin/flock -n /var/run/cloudlinux_multiphp.cronlock /usr/share/cagefs/setup_multiphp_integration\n') f.close() def create_cron_cpanel_sessions(): """ This func creates cron task which runs every 30 minutes to clean php sessions inside cagefs """ if not os.path.exists(CPANEL_PHP_SESSIONS_CRON_PATH): f = open(CPANEL_PHP_SESSIONS_CRON_PATH, 'w') f.write('*/29 * * * * root /usr/bin/flock -n /var/run/cloudlinux_cleanuserphpsessions.cronlock /usr/share/cagefs/clean_user_php_sessions\n') f.close() def create_exclude_users_cron(): """ This func creates cron task which runs every 10 minutes to actualize CageFS exclude users file(s) """ if not os.path.exists(EXCLUDE_USERS_CRON_FILE): f = open(EXCLUDE_USERS_CRON_FILE, 'w') f.write('*/10 * * * * root /usr/bin/flock -n /var/run/cloudlinux_cagefs_exclude_users.cronlock /usr/share/cagefs/exclude_users_cleaner.py\n') f.close() def create_cron_namespaces(): """ This func creates cron task that runs every 10 minutes to create namespaces for new users """ if not os.path.exists(CREATE_NAMESPACES_CRON_FILE): f = open(CREATE_NAMESPACES_CRON_FILE, 'w') f.write('*/10 * * * * root /usr/bin/flock -n /var/run/cloudlinux_cagefs_create_namespaces.cronlock /usr/sbin/cagefsctl --create-namespaces\n') f.close() def shared_mounts_are_found(): try: f = open('/proc/self/mountinfo', 'r') found = False for line in f: if line.find(' shared:') != -1: found = True break f.close() return found except IOError: return False def fix_shared_mounts(force=False): """ Change shared mounts to private and remount CageFS when shared mounts are found. see CAG-520 for details :param force: do not search for shared mounts, make changes unconditionally :type force: bool """ if force or shared_mounts_are_found(): exec_command('/usr/sbin/cagefsctl --unmount-really-all > /dev/null 2>&1') if not os.path.isfile('/opt/suphp/sbin/suphp'): exec_command('/bin/umount /opt/suphp/sbin > /dev/null 2>&1') exec_command('/bin/mount --make-rprivate / > /dev/null 2>&1') exec_command('/usr/sbin/cagefsctl --without-lock --remount-all > /dev/null 2>&1') def install_plugin_web(): if cp.name == "Plesk" and verCompare (cp.version, "10") >= 0: cpdir = CopyDirectory(SOURCE_PATH+"plesk-cagefs", ROOT_PLESK_DIR) cpdir.process() register_cagefs_plugin() elif cp.name == "cPanel": cpdir = CopyDirectory(SOURCE_PATH+"cpanel-cagefs/usr/local/cpanel/whostmgr/docroot", ROOT_CPANEL_DIR) cpdir.process() if os.path.exists(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi"): os.chmod(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi", stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) if verCompare(cp.version, '11.38.1') >= 0: if not os.path.isdir("/var/cpanel/apps"): mod_makedirs("/var/cpanel/apps", 0o755) if verCompare(cp.version, '63.9999') >= 0: exec_command("sed -i -e '/^#WHMADDON:cagefs:CageFS/d' "+ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi") if verCompare(cp.version, '65.9999') >= 0: shutil.copyfile(SOURCE_PATH + 'cpanel-cagefs/cagefs-cpanel66.conf', "/var/cpanel/apps/cagefs.conf") else: shutil.copyfile(SOURCE_PATH + 'cpanel-cagefs/cagefs-cpanel64.conf', "/var/cpanel/apps/cagefs.conf") else: shutil.copyfile(SOURCE_PATH + 'cpanel-cagefs/cagefs.conf', "/var/cpanel/apps/cagefs.conf") exec_command("chmod 600 /var/cpanel/apps/cagefs.conf") exec_command("/usr/local/cpanel/bin/register_appconfig /var/cpanel/apps/cagefs.conf") exec_command("/usr/local/cpanel/etc/init/startcpsrvd") manage_cron_file() elif cp.name == "InterWorx": cpdir = CopyDirectory(SOURCE_PATH+"interworx-cagefs/usr/local/interworx", ROOT_IWORX_DIR) cpdir.process() elif cp.name == "ISPManager": if verCompare(cp.version, "5") == -1: # ISP Manager 4 m_path = "{0}ispmanager-cagefs/usr/local/ispmgr/".format(SOURCE_PATH) for name in ["addon", "etc", "skins/sirius"]: CopyDirectory("{0}{1}".format(m_path, name), "{0}{1}".format(ROOT_ISPMGR_DIR, name)).process() if verCompare(cp.version, "4.4.4") <= 0: # for <=4.4.4 version copy mobile skin. for other verions don`t copy CopyDirectory("{}skins/mobile".format(m_path), "{}skins/mobile".format(ROOT_ISPMGR_DIR)).process() exec_command("/usr/bin/killall ispmgr") elif cp.name == "DirectAdmin": cpdir = CopyDirectory(SOURCE_PATH+"directadmin-cagefs/usr/local/directadmin/plugins", ROOT_DA_DIR) cpdir.process() exec_command("chown -R diradmin:diradmin "+ROOT_DA_DIR+"cagefs") exec_command("chmod -R 755 "+ROOT_DA_DIR+"cagefs/admin") def delete_plugin_web(): # remove installed files if cp.name == "Plesk" and verCompare (cp.version, "10") >= 0: delete_cagefs_module_plesk() if os.path.exists(ROOT_PLESK_DIR+"htdocs/images/modules/plesk-cagefs"): shutil.rmtree(ROOT_PLESK_DIR+"htdocs/images/modules/plesk-cagefs") if os.path.exists(ROOT_PLESK_DIR+"htdocs/modules/plesk-cagefs"): shutil.rmtree(ROOT_PLESK_DIR+"htdocs/modules/plesk-cagefs") if os.path.exists(ROOT_PLESK_DIR+"plib/modules/plesk-cagefs"): shutil.rmtree(ROOT_PLESK_DIR+"plib/modules/plesk-cagefs") if os.path.exists(ROOT_PLESK_DIR+"plib/templates/modules/plesk-cagefs"): shutil.rmtree(ROOT_PLESK_DIR+"plib/templates/modules/plesk-cagefs") elif cp.name == "cPanel": if os.path.exists(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi"): os.remove(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi") if os.path.exists(ROOT_CPANEL_DIR+"cgi/cageFS"): shutil.rmtree(ROOT_CPANEL_DIR+"cgi/cageFS") if os.path.exists(ROOT_CPANEL_DIR+"themes/x/icons/cagefs.gif"): os.remove(ROOT_CPANEL_DIR+"themes/x/icons/cagefs.gif") if os.path.exists(ROOT_CPANEL_DIR+"images/CageOnly32.png"): os.remove(ROOT_CPANEL_DIR+"images/CageOnly32.png") if os.path.exists(ROOT_CPANEL_DIR+"images/cagefs-32x32.png"): os.remove(ROOT_CPANEL_DIR+"images/cagefs-32x32.png") if verCompare(cp.version, '11.38.1') >= 0: if (os.path.exists("/var/cpanel/apps/cagefs.conf")): exec_command("/usr/local/cpanel/bin/unregister_appconfig /var/cpanel/apps/cagefs.conf") os.remove("/var/cpanel/apps/cagefs.conf") exec_command("/usr/local/cpanel/etc/init/startcpsrvd") if os.path.isfile(CPANEL_CRON_PATH): os.unlink(CPANEL_CRON_PATH) if os.path.isfile(CPANEL_PHP_SESSIONS_CRON_PATH): os.unlink(CPANEL_PHP_SESSIONS_CRON_PATH) elif cp.name == "InterWorx": if os.path.exists(ROOT_IWORX_DIR+"plugins/cagefs"): shutil.rmtree(ROOT_IWORX_DIR+"plugins/cagefs") if os.path.exists(ROOT_IWORX_DIR+"html/images/cagefs"): shutil.rmtree(ROOT_IWORX_DIR+"html/images/cagefs") elif cp.name == "ISPManager": if verCompare(cp.version, "5") == -1: # ISP Manager 4 if os.path.exists(ROOT_ISPMGR_DIR+"addon/cagefs"): shutil.rmtree(ROOT_ISPMGR_DIR+"addon/cagefs") if (os.path.exists("/usr/local/ispmgr/addon/CageFS.php")): os.remove("/usr/local/ispmgr/addon/CageFS.php") if (os.path.exists("/usr/local/ispmgr/addon/CageFSUser.php")): os.remove("/usr/local/ispmgr/addon/CageFSUser.php") if (os.path.exists("/usr/local/ispmgr/addon/CageFSUser_get.php")): os.remove("/usr/local/ispmgr/addon/CageFSUser_get.php") if (os.path.exists("/usr/local/ispmgr/addon/CageFSBackup.php")): os.remove("/usr/local/ispmgr/addon/CageFSBackup.php") if (os.path.exists("/usr/local/ispmgr/etc/ispmgr_mod_cagefsusers.xml")): os.remove("/usr/local/ispmgr/etc/ispmgr_mod_cagefsusers.xml") if (os.path.exists("/usr/local/ispmgr/etc/ispmgr_mod_cagefs.xml")): os.remove("/usr/local/ispmgr/etc/ispmgr_mod_cagefs.xml") if (os.path.exists("/usr/local/ispmgr/etc/ispmgr_mod_cagefsbackup.xml")): os.remove("/usr/local/ispmgr/etc/ispmgr_mod_cagefsbackup.xml") if (os.path.exists("/usr/local/ispmgr/skins/mobile/mb-cagefs.png")): os.remove("/usr/local/ispmgr/skins/mobile/mb-cagefs.png") if (os.path.exists("/usr/local/ispmgr/skins/mobile/m-cagefs.png")): os.remove("/usr/local/ispmgr/skins/mobile/m-cagefs.png") if (os.path.exists("/usr/local/ispmgr/skins/mobile/t-CagefsStatus.png")): os.remove("/usr/local/ispmgr/skins/mobile/t-CagefsStatus.png") if (os.path.exists("/usr/local/ispmgr/skins/sirius/mb-cagefs.png")): os.remove("/usr/local/ispmgr/skins/sirius/mb-cagefs.png") if (os.path.exists("/usr/local/ispmgr/skins/sirius/m-cagefs.png")): os.remove("/usr/local/ispmgr/skins/sirius/m-cagefs.png") if (os.path.exists("/usr/local/ispmgr/skins/sirius/t-CagefsStatus.png")): os.remove("/usr/local/ispmgr/skins/sirius/t-CagefsStatus.png") # Clear ISP Manager's cache and restart it shutil.rmtree('/usr/local/ispmgr/var/.xmlcache/ispmgr', True) p = subprocess.Popen(['killall', 'ispmgr'], shell=False, stdin=open('/dev/null'), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) p.wait() elif cp.name == "DirectAdmin": if os.path.exists(ROOT_DA_DIR+"cagefs"): shutil.rmtree(ROOT_DA_DIR+"cagefs") def install_file(src, dst, perm=0o644): base_dir = os.path.dirname(dst) if not os.path.isdir(base_dir): mod_makedirs(base_dir, 0o755) if not os.path.isfile(dst): shutil.copyfile(src, dst) os.chmod(dst, perm) def install_native_conf(path): install_file(SOURCE_PATH + path, "/etc/cl.selector/native.conf") def add_read_only_mounts_to_cagefs_mp(): MOUNTS = cagefsctl.READ_ONLY_MOUNTS if os.path.isfile('/etc/cagefs/cagefs.mp'): cagefsctl.check_mp_file() mp_file = cagefslib.read_file('/etc/cagefs/cagefs.mp') comment_added = False comment = '# Please add exclamation sign at the beginning of the line if you want to mount path read-only, like below.\n' mp_changed = False for path in MOUNTS: line = '!' + path + '\n' if (line not in mp_file) and os.path.isdir(path): if (not comment_added) and (comment not in mp_file): mp_file.append(comment) comment_added = True mp_file.append(line) mp_changed = True if mp_changed: cagefslib.write_file('/etc/cagefs/cagefs.mp', mp_file) touch('/usr/share/cagefs/need.remount') def switch_php_ini_symlinks_for_users(): pw = pwd.getpwall() for line in pw: prefix = str(line.pw_uid)[-2:] user = line.pw_name path = '/var/cagefs/' + prefix + '/' + user + '/etc/cl.selector/php.ini' if os.path.islink(path): try: linkto = os.readlink(path) if linkto == '/usr/selector/php.ini': os.unlink(path) os.symlink('/usr/selector.etc/php.ini', path) except OSError as e: print('Error:', str(e), file=sys.stderr) def move_php_ini_to_selector_etc(force = False): old_ini_path = '/usr/selector/php.ini' new_ini_path = '/usr/selector.etc/php.ini' if force or os.path.isfile(SKELETON + old_ini_path): new_dir_path = SKELETON + os.path.dirname(new_ini_path) if not os.path.isdir(new_dir_path): mod_makedirs(new_dir_path, 0o755) if os.path.isfile(SKELETON + old_ini_path) and (not os.path.isfile(SKELETON + new_ini_path)): exec_command('/bin/cp -p ' + SKELETON + old_ini_path + ' ' + SKELETON + new_ini_path) if os.path.isfile(SKELETON + new_ini_path): switch_php_ini_symlinks_for_users() try: os.unlink(SKELETON + old_ini_path) except OSError: pass def add_usr_local_easy_mount(): add_mount_to_cagefs_mp('/usr/local/easy', read_only=True) def delete_mount_from_cagefs_mp(line): path = '/etc/cagefs/cagefs.mp' if os.path.isfile(path): if delete_line_from_file(path, line): touch('/usr/share/cagefs/need.remount') def setup_ea_php_sessions(): delete_mount_from_cagefs_mp('/var/cpanel/php/sessions') cagefsctl.add_mounts_for_ea_php_sessions() def detect_min_uid(): """ Return UID_MIN setting from /etc/login.defs file as string """ min_uid = None try: f = open('/etc/login.defs', 'r') for line in f: if line.startswith('UID_MIN'): a = line.split() if a and a[0] == 'UID_MIN': min_uid = a[1] f.close() except (OSError, IOError) as e: print('Error while reading UID_MIN from /etc/login.defs file', str(e)) return min_uid def set_min_uid(default=500): """ Set min_uid value for CageFS """ if not os.path.isfile('/etc/cagefs/cagefs.min.uid'): min_uid = detect_min_uid() if min_uid: exec_command("/usr/sbin/cagefsctl --set-min-uid="+min_uid) else: exec_command("/usr/sbin/cagefsctl --set-min-uid="+str(default)) def sync_control_panel_admins(): """ Process control panel admins: - Add all admins to sudoers - Add all admins to /etc/cagefs/exclude/*.admins, which proceesed by hooks - Remove 'admin' from /etc/cagefs/exclude/directadminusers :return: None """ if getCPName() == DIRECTADMIN_NAME: admins_list_file = os.path.join(cagefsctl.EXCLUDE_PATH, "directadmin.admins") else: admins_list_file = os.path.join(cagefsctl.EXCLUDE_PATH, "panel.admins") admin_lines_for_write = list() try: list_panel_admins = admins() except NotSupported: # this is ok, just control panel # does not implement our API return for admin_name in list_panel_admins: admin_lines_for_write.append(admin_name + '\n') Clsudo.add_cagefs_user(admin_name) if not admin_lines_for_write: # nothing to write, just exit return write_file_lines(admins_list_file, admin_lines_for_write, 'w') os.chmod(admins_list_file, 0o0600) # We need to remove 'admin' from /etc/cagefs/exclude/directadminusers because # CAG-940 cleaner does not remove it (manually added) if getCPName() == DIRECTADMIN_NAME: admins_list_file = os.path.join(cagefsctl.EXCLUDE_PATH, "directadminusers") delete_line_from_file(admins_list_file, "admin") def install_plugin(): """ Install cagefs plugin on panel """ move_php_ini_to_selector_etc() # Add check CageFS exclude users cron create_exclude_users_cron() # Check for disable etcfs if (not os.path.exists("/etc/cagefs/etc.safe/disable.etcfs")): if (not os.path.exists("/etc/cagefs/etc.safe")): mod_makedirs("/etc/cagefs/etc.safe", 0o751) touch("/etc/cagefs/etc.safe/disable.etcfs") if (os.path.exists("/usr/share/cagefs-skeleton/bin")): exec_command("/usr/sbin/cagefsctl --update-etc") touch('/usr/share/cagefs/etc.update.done') # execution of "cagefsctl --remount-all" is needed touch('/usr/share/cagefs/need.remount') # add mail directory if it isn't exists if (not os.path.exists("/etc/mail")): mod_makedirs("/etc/mail", 0o755) # LU-640: check if license file is inside CageFS and mount it into CageFS when needed if os.path.exists(SKELETON+'/bin') and os.path.exists(cagefsctl.LICENSE_TIMESTAMP_FILE) and \ not os.path.exists(SKELETON+'/var/lve/lveinfo.ver.cagefs/lveinfo.ver'): touch('/usr/share/cagefs/need.remount') add_read_only_mounts_to_cagefs_mp() add_mount_to_cagefs_mp('/var/run/nscd', read_only=False) # CAG-797: mount NodeJS selector config directory into CageFS nodejs_selector_conf_dir = cagefsctl.SELECTOR_CONF_DIR_TEMPLATE.format('nodejs') if not os.path.isdir(nodejs_selector_conf_dir): mod_makedirs(nodejs_selector_conf_dir, 0o755) add_mount_to_cagefs_mp(nodejs_selector_conf_dir, read_only=True) # CAG-828: Add python-selector.json to cagefs python_selector_conf_dir = cagefsctl.SELECTOR_CONF_DIR_TEMPLATE.format('python') if not os.path.isdir(python_selector_conf_dir): mod_makedirs(python_selector_conf_dir, 0o755) add_mount_to_cagefs_mp(python_selector_conf_dir, read_only=True) # CAG-826: fix cagefsctl --enter vulnerability delete_mount_from_cagefs_mp('@/root,700') # CAG-1007: remove LiteSpeed dir /tmp/lshttpd delete_mount_from_cagefs_mp('/tmp/lshttpd') # CAG-936: remove unneeded mount point for awstats delete_mount_from_cagefs_mp('!/usr/local/awstats/wwwroot/cgi-bin') if os.path.isfile(cagefsctl.DEV_SHM_OPTIONS): # CAG-954: remove /dev/shm mount from cagefs.mp when isolation of /dev/shm is enabled delete_mount_from_cagefs_mp('/dev/shm') else: # CAG-954: add /dev/shm mount to cagefs.mp when isolation of /dev/shm is disabled add_mount_to_cagefs_mp('/dev/shm') if os.path.isdir(POSTGRES_CL7_FOLDER) and os.path.isdir(DEFAULT_POSTGRES_FOLDER) and not os.path.isfile(POSTGRES_CONF): # if /var/run/postgresql exists and /etc/sysconfig/postgres does not, # than we assume, that we are on CL7 # in such case, /var/run/postgres directory should be empty (not needed), # and we try to remove it try: os.rmdir(DEFAULT_POSTGRES_FOLDER) removed = True except OSError: removed = False if removed: delete_mount_from_cagefs_mp(DEFAULT_POSTGRES_FOLDER) # install cagefs cronjob if os.path.isdir("/etc/cron.d") and (not os.path.exists("/etc/cron.d/cp-cagefs-cron")): shutil.copyfile(SOURCE_PATH+"plesk-cagefs-cron", "/etc/cron.d/cp-cagefs-cron") if os.path.exists("/etc/cron.daily/cagefs.cron"): os.remove("/etc/cron.daily/cagefs.cron") #install web-face only if not os.path.exists(NEED_PLUGIN): install_plugin_web() # install only. rewrite all existing file if cp.name == "Plesk" and verCompare(cp.version, "10") >= 0: # remove pam_lve and pam_sulve from /etc/pam.d/su on Plesk exec_command("/bin/sed -i '/pam_lve.so/d' /etc/pam.d/su") exec_command("/bin/sed -i '/pam_sulve.so/d' /etc/pam.d/su") update_sudoers('psaadm') if not os.path.exists(NEW_EXCLUDE_PATH): mod_makedirs(NEW_EXCLUDE_PATH, 0o750) shutil.copyfile(SOURCE_PATH+"plesk-cagefs/pleskuserlist", os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist")) os.chmod(os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist"), 0o600) install_native_conf("plesk-cagefs/plesk.native.conf") set_min_uid(10000) touch('/etc/cagefs/enable.duplicate.uids') # Install alt-php sessions clean cron job source = '/usr/share/cagefs/clean_user_alt_php_sessions_plesk' print("%s --> %s" % (source, PLESK_CRON_PHP_CLEANER_HOURLY_PATH)) exec_command("/bin/cp -f %s %s" % (source, PLESK_CRON_PHP_CLEANER_HOURLY_PATH)) elif cp.name == "cPanel": add_usr_local_easy_mount() add_mount_to_cagefs_mp('/usr/local/cpanel/var', read_only=False) for path in cagefsctl.READ_ONLY_MOUNTS: add_mount_to_cagefs_mp(path, read_only=True) setup_ea_php_sessions() # create symlink /usr/share/cagefs-skeleton/usr/local/cpanel/bin/jailshell -> /bin/bash if os.path.exists('/usr/share/cagefs-skeleton/bin/bash'): exec_command('ln -fs /bin/bash /usr/share/cagefs-skeleton/usr/local/cpanel/bin/jailshell') # update perl modules that are needed for cagefs plugin exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller YAML::Syck &> /dev/null &') exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller Template::Constants &> /dev/null &') exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller XML::Simple &> /dev/null &') exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller XML::LibXML &> /dev/null &') exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller IO::Scalar &> /dev/null &') # install hooks for CPanel exec_command("/usr/share/cagefs/cpanel/cpanel-delete-cagefs") exec_command("/usr/share/cagefs/cpanel/cpanel-hooks-cagefs") # install rearrange-acc hook. works only for 11.54+ exec_command("/usr/share/cagefs/cpanel/cpanel_hooks_manage.py -i") print("Rebuilding Apache's suexec...") exec_command("/usr/sbin/cpanel-compile-suexec.sh 500") print("Rebuilding suphp...") exec_command("/usr/sbin/cpanel-compile-suphp.sh 1") if not os.path.exists(NEW_EXCLUDE_PATH): mod_makedirs(NEW_EXCLUDE_PATH, 0o750) shutil.copyfile(SOURCE_PATH+"cpanel-cagefs/cpaneluserlist", os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist")) os.chmod(os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist"), 0o600) install_native_conf("cpanel-cagefs/cpanel.native.conf") install_file(SOURCE_PATH + 'cpanel-cagefs/exclude_mounts.conf', '/etc/container/exclude_mounts.conf') set_min_uid() if os.path.exists(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi"): os.chmod(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi", stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) # clean system from old and not used hooks if os.path.exists("/usr/share/cagefs-plugins/hooks/cpanel/delete-unused-hooks.sh"): exec_command("/usr/share/cagefs-plugins/hooks/cpanel/delete-unused-hooks.sh") if os.path.exists("/usr/share/cagefs-plugins/hooks/jail_shell_disable.sh"): exec_command("/usr/share/cagefs-plugins/hooks/jail_shell_disable.sh") # add cpanel-specific cron jobs # cron task to clean user-specified php-sessions create_cron_cpanel_sessions() cagefs_universal_hook_lib.install_multiphp_universal_hook() cagefs_universal_hook_lib.install_passenger_universal_hook() # install yum universal hook for environments without LVE # to process a new ea-php fpm and native php-fpm packages if cagefslib.is_running_without_lve(): cagefs_universal_hook_lib.install_without_lve_universal_hooks() elif cp.name == "InterWorx": update_sudoers('iworx') if not os.path.exists(NEW_EXCLUDE_PATH): mod_makedirs(NEW_EXCLUDE_PATH, 0o750) shutil.copyfile(SOURCE_PATH+"interworx-cagefs/iworxuserslist", os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist")) os.chmod(os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist"), 0o600) install_native_conf("interworx-cagefs/iworx.native.conf") set_min_uid() if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suexec"): if (not os.path.exists("/usr/sbin/suexec.bak")) and os.path.exists("/usr/sbin/suexec"): shutil.copyfile("/usr/sbin/suexec", "/usr/sbin/suexec.bak") shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suexec", "/usr/sbin/suexec") try: gr = grp.getgrnam('apache') os.chown('/usr/sbin/suexec', 0, gr.gr_gid) except KeyError: pass os.chmod('/usr/sbin/suexec', 0o4510) if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suphp"): if (not os.path.exists("/usr/sbin/suphp.bak")) and os.path.exists("/usr/sbin/suphp"): shutil.copyfile("/usr/sbin/suphp", "/usr/sbin/suphp.bak") shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suphp", "/usr/sbin/suphp") os.chown('/usr/sbin/suphp', 0, 0) os.chmod('/usr/sbin/suphp', 0o4755) elif cp.name == "ISPManager": # ISP Manager 4 if not os.path.isfile('/etc/cagefs/cagefs.base.home.dirs'): exec_command('echo "^/var/www/" > /etc/cagefs/cagefs.base.home.dirs') touch('/usr/share/cagefs/need.remount') if os.path.isdir('/var/www/php-bin'): exec_command('/bin/chmod o-r /var/www/php-bin') add_mount_to_cagefs_mp('/var/www/php-bin') set_min_uid() # Clear ISP Manager's cache and restart it shutil.rmtree('/usr/local/ispmgr/var/.xmlcache/ispmgr', True) exec_command("/usr/bin/killall ispmgr") install_native_conf("ispmanager-cagefs/ispmanager.native.conf") elif cp.name == "DirectAdmin": add_mount_to_cagefs_mp('/var/www/html') set_min_uid() if not os.path.exists(NEW_EXCLUDE_PATH): mod_makedirs(NEW_EXCLUDE_PATH, 0o0750) if not os.path.exists(cagefsctl.EXCLUDE_PATH): mod_makedirs(cagefsctl.EXCLUDE_PATH, 0o0751) shutil.copyfile(SOURCE_PATH+"directadmin-cagefs/directadminusers", os.path.join(NEW_EXCLUDE_PATH, "directadminusers")) # Add all DA admins to sudoers and /etc/cagefs/exclude/directadmin.admins sync_control_panel_admins() install_native_conf("directadmin-cagefs/directadmin.native.conf") # CAG-916: set cagefs=yes in options.conf when installing CageFS on DirectAdmin server subprocess.run('/usr/local/directadmin/custombuild/build set cagefs yes', shell=True, executable='/bin/bash') else: if cp.name == "Unknown" and cagefslib.is_running_without_lve(): # Namespace creation cronjob should only run on no-panel systems in environments without LVE create_cron_namespaces() print("Panel name: "+cp.name+" version: "+cp.version) if not os.path.exists(cagefsctl.EXCLUDE_PATH): mod_makedirs(cagefsctl.EXCLUDE_PATH, 0o751) sync_control_panel_admins() set_min_uid() def delete_plugin(): """ Remove cagefs plugin from system """ #delete web-face delete_plugin_web() # Remove cagefs cronjob if os.path.exists("/etc/cron.d/cp-cagefs-cron"): os.remove("/etc/cron.d/cp-cagefs-cron") if os.path.exists("/etc/cron.daily/cagefs.cron"): os.remove("/etc/cron.daily/cagefs.cron") # Remove alt-php sessions cleaner cron if os.path.exists(PLESK_CRON_PHP_CLEANER_HOURLY_PATH): os.remove(PLESK_CRON_PHP_CLEANER_HOURLY_PATH) # Remove exclude users check cron if os.path.exists(EXCLUDE_USERS_CRON_FILE): os.remove(EXCLUDE_USERS_CRON_FILE) # Remove namespace creation cron if os.path.exists(CREATE_NAMESPACES_CRON_FILE): os.remove(CREATE_NAMESPACES_CRON_FILE) # remove installed files #in CAG-248 securelinks support was removed, but uninstall script should still delete old files if cp.name == "Plesk" and verCompare(cp.version, "10") >= 0: if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist")): os.remove(os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist")) if os.path.exists("/etc/cagefs/securelinks/plesk.htaccess"): os.remove("/etc/cagefs/securelinks/plesk.htaccess") elif cp.name == "cPanel": exec_command("/usr/share/cagefs/cpanel/cpanel-delete-cagefs") # remove rearrange-acc hook. hook works only for 11.54+ exec_command("/usr/share/cagefs/cpanel/cpanel_hooks_manage.py -d") print("Rebuilding Apache's suexec...") exec_command("/usr/sbin/cpanel-compile-suexec.sh 500 restore") print("Rebuilding suphp...") exec_command("/usr/sbin/cpanel-compile-suphp.sh 1 restore") if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist")): os.remove(os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist")) if os.path.exists("/etc/cagefs/securelinks/cpanel.htaccess"): os.remove("/etc/cagefs/securelinks/cpanel.htaccess") cagefs_universal_hook_lib.remove_multiphp_universal_hook() cagefs_universal_hook_lib.remove_passenger_universal_hook() if cagefslib.is_running_without_lve(): cagefs_universal_hook_lib.remove_without_lve_universal_hooks() elif cp.name == "InterWorx": if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist")): os.remove(os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist")) if os.path.exists("/usr/sbin/suexec.bak"): shutil.copyfile("/usr/sbin/suexec.bak", "/usr/sbin/suexec") if os.path.exists("/usr/sbin/suphp.bak"): shutil.copyfile("/usr/sbin/suphp.bak", "/usr/sbin/suphp") if os.path.exists("/etc/cagefs/securelinks/interworx.htaccess"): os.remove("/etc/cagefs/securelinks/interworx.htaccess") elif cp.name == "ISPManager": if verCompare(cp.version, "5") == -1: # ISP Manager 4 exec_command("/usr/bin/killall ispmgr") if os.path.exists("/etc/cagefs/securelinks/ispmanager.htaccess"): os.remove("/etc/cagefs/securelinks/ispmanager.htaccess") elif cp.name == "DirectAdmin": if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "directadminusers")): os.remove(os.path.join(NEW_EXCLUDE_PATH, "directadminusers")) if os.path.exists("/etc/cagefs/securelinks/directadmin.htaccess"): os.remove("/etc/cagefs/securelinks/directadmin.htaccess") else: print("Current panel unsupported. Panel name: "+cp.name+" version: "+cp.version) litespeed_enableLVE_configure(force_value = 0) litespeed_lsphp5_path_change(lsphp5_path = '$SERVER_ROOT/fcgi-bin/lsphp5') litespeed_config_write() if cagefslib.is_running_without_lve(): cagefs_without_lve_lib.restore_httpd_php_fpm_services() def cp_supported(): if cp.name == "Plesk" and verCompare (cp.version, "10") >= 0: return True if cp.name in ("cPanel", "InterWorx", "ISPManager", "DirectAdmin"): return True return False def cron_update(): """ Periodically update cagefs """ lockname = '/var/run/cloudlinux_update_cagefs.cronlock' lockfile = cagefsctl.acquire_lock(lockname, wait=False, quiet=True) try: if os.path.exists('/etc/cagefs/users.disabled') or os.path.exists('/etc/cagefs/users.enabled'): exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --update --do-not-ask --silent > /dev/null 2>&1") exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --skip-php-reload --setup-cl-selector > /dev/null 2>&1") if os.path.isfile('/usr/share/cagefs/need.remount'): exec_command("/usr/sbin/cagefsctl --remount-all > /dev/null 2>&1") exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --clean-var-cagefs > /dev/null 2>&1") exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --clean-config-dirs > /dev/null 2>&1") exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --tmpwatch > /dev/null 2>&1") finally: cagefsctl.unlock(lockfile, lockname) def call_httpdtrigger(): if cp.name == "InterWorx": if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suexec"): if (not os.path.exists("/usr/sbin/suexec.bak")) and os.path.exists("/usr/sbin/suexec"): shutil.copyfile("/usr/sbin/suexec", "/usr/sbin/suexec.bak") shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suexec", "/usr/sbin/suexec") try: gr = grp.getgrnam('apache') os.chown('/usr/sbin/suexec', 0, gr.gr_gid) except KeyError: pass os.chmod('/usr/sbin/suexec', 0o4510) def call_suphptrigger(): if cp.name == "InterWorx": if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suphp"): if (not os.path.exists("/usr/sbin/suphp.bak")) and os.path.exists("/usr/sbin/suphp"): shutil.copyfile("/usr/sbin/suphp", "/usr/sbin/suphp.bak") shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suphp", "/usr/sbin/suphp") os.chown('/usr/sbin/suphp', 0, 0) os.chmod('/usr/sbin/suphp', 0o4755) def toggle_plugin(): if os.path.exists(NEED_PLUGIN): install_plugin_web() os.remove(NEED_PLUGIN) else: delete_plugin_web() touch(NEED_PLUGIN) class ControlPanel(object): name = '' varsion = '' def __init__(self, name, version): self.name = name self.version = version def build_parser(): """ Build argument parser and parse input arguments """ parser = argparse.ArgumentParser() parser.add_argument("-i", "--install", help="install CageFS plugin", action="store_true") parser.add_argument("--install-plesk-wrapper", help=argparse.SUPPRESS, action="store_true") parser.add_argument("-d", "--delete", help="delete CageFS plugin", action="store_true") parser.add_argument("--uninstall", help="do actions while uninstalling CageFS", action="store_true") parser.add_argument("-c", "--cronupdate", help="cagefsctl --update", action="store_true") parser.add_argument("-r", "--httpdtrigger", help=argparse.SUPPRESS, action="store_true") parser.add_argument("-t", "--suphptrigger", help=argparse.SUPPRESS, action="store_true") parser.add_argument("-p", "--toggle-plugin", help=argparse.SUPPRESS, action="store_true") parser.add_argument("-n", "--manage-multiphp-cron-file", help=argparse.SUPPRESS, action="store_true") parser.add_argument("--add-usr-local-easy-mount", help=argparse.SUPPRESS, action="store_true") parser.add_argument("--setup-ea-php-sessions", help=argparse.SUPPRESS, action="store_true") parser.add_argument("--fix-shared-mounts", help=argparse.SUPPRESS, action="store_true") parser.add_argument("--force-fix-shared-mounts", help=argparse.SUPPRESS, action="store_true") parser.add_argument("--fix-services-without-lve", help=argparse.SUPPRESS, action="store_true") help_text = ("add /usr/share/cagefs-skeleton/dev/log to syslog config and" " restart syslog") parser.add_argument("--add-syslog-socket", action="store_true", help=help_text) help_text = ("remove /usr/share/cagefs-skeleton/dev/log from syslog config" " and restart syslog") parser.add_argument("--remove-syslog-socket", action="store_true", help=help_text) return parser def register_cagefs_plugin(): fd = open(ROOT_PLESK_DIR+"plib/modules/plesk-cagefs/meta.xml", 'w') text = """<?xml version="1.0" encoding="utf-8"?> <module> <id>plesk-cagefs</id> <name>CageFS</name> <description>CageFS</description> <url>http://cloudlinux.com/</url> <version>{version}</version> <release>{release}</release> <vendor>Cloud Linux</vendor> <icon>/images/modules/plesk-cagefs/addon_CloudLinux_logo.png</icon> </module>""" release_number = CAGEFS_RELEASE.split('.')[0] fd.write(text.format(version=CAGEFS_VERSION, release=release_number)) fd.close() exec_command('/usr/local/psa/bin/extension --register plesk-cagefs') def uninstall_cagefs(): """ This function is executed while uninstall (not upgrade) of cagefs package """ if cp.name == "DirectAdmin": # CAG-916: set cagefs=no in options.conf when uninstalling CageFS on DirectAdmin server subprocess.run('/usr/local/directadmin/custombuild/build set cagefs no', shell=True, executable='/bin/bash') def fix_services_without_lve(): """ Reconfigure httpd and ea-php-fpm services to work in environment without LVE """ if cagefslib.is_running_without_lve(): cagefs_without_lve_lib.fix_httpd_php_fpm_services() def main(argv): """ Script run function """ parser = build_parser() if len(argv) == 0: parser.print_help() sys.exit(2) args = parser.parse_args(argv) if args.install: install_plugin() if args.install_plesk_wrapper: cagefslib.install_plesk_wrapper() if args.delete: delete_plugin() if args.uninstall: uninstall_cagefs() if args.cronupdate: cron_update() if args.httpdtrigger: call_httpdtrigger() if args.suphptrigger: call_suphptrigger() if args.toggle_plugin: toggle_plugin() if args.add_syslog_socket: add_syslog_socket() if args.remove_syslog_socket: remove_syslog_socket() if args.manage_multiphp_cron_file: manage_cron_file() if args.add_usr_local_easy_mount: add_usr_local_easy_mount() if args.setup_ea_php_sessions: setup_ea_php_sessions() if args.fix_shared_mounts or args.force_fix_shared_mounts: fix_shared_mounts(args.force_fix_shared_mounts) if args.fix_services_without_lve: fix_services_without_lve() if "__main__" == __name__: detect.getCP() cp = ControlPanel(detect.CP_NAME, detect.CP_VERSION) main(sys.argv[1:])