"""Main logic for fixperms"""
from functools import partial
from subprocess import run, PIPE, CalledProcessError
from concurrent.futures import ProcessPoolExecutor, as_completed
from fixperms_cpanel import CpanelPermMap
from fixperms_cwp import CwpPermMap
from fixperms_wp3 import WP3PermMap
from fixperms_cli import parse_args, Args
from fixperms_ids import IDCache
def check_dso_without_modruid2(role: str):
"""Check if DSO is installed and modruid2 is disabled"""
if rads.IMH_ROLE == 'shared':
return # no need to check on shared
if role not in ('CWP', 'cPanel'):
run_cmd = partial(run, encoding='UTF-8', stdout=PIPE, check=False)
# pylint: disable=unsupported-membership-test
mods = run_cmd(['/usr/local/apache/bin/httpd', '-M']).stdout
# this is the same way /scripts/dso_handler_remove scans for DSO
if not re.search(r'php\d+_module', mods):
good_mods = 'mod_ruid2 or mod_mpm_itk'
kb_url = "http://wiki.centos-webpanel.com/dso-php-handler-for-cwp"
['/usr/local/cpanel/bin/rebuild_phpconf', '--current']
if 'SAPI: dso' not in php:
mods = run_cmd(['/usr/sbin/httpd', '-M']).stdout
good_mods = 'ea-apache24-mod_ruid2 or ea-apache24-mod_mpm_itk'
kb_url = "https://go.cpanel.net/EA4RecDSO"
if 'ruid2_module (shared)' in mods or 'mpm_itk_module (shared)' in mods:
# CWP users might need to build it with /usr/local/apache/bin/apxs
f"""Please install the modruid2 Apache module.
fixperms detected a security issue and exited.
PHP DSO runs as the nobody user by default. In a shared hosting environment,
this is a security issue. We strongly recommend that you install either the
module unless you have single-user system. If you use suPHP, you will add
some security, but may experience performance issues on your server.
For more information, see: {kb_url}"""
"""Main program logic: iterate over each user and run fixperms"""
args.logger.critical('%s. Cannot continue.', exc)
check_dso_without_modruid2(args.role)
if len(args.users) > 1 and args.procs > 1:
parallel_execute(args, ids)
serial_execute(args, ids)
def parallel_execute(args: Args, ids: IDCache):
"""Fork processes to handle each user"""
with ProcessPoolExecutor(max_workers=args.procs) as pool:
perm_map = get_perm_map(args, ids, user)
if not isinstance(exc, CalledProcessError):
args.logger.debug(traceback.format_exc())
args.logger.error(str(exc))
future = pool.submit(perm_map.run)
for future in as_completed(futures):
if not isinstance(exc, CalledProcessError):
args.logger.debug(traceback.format_exc())
args.logger.error(str(exc))
def serial_execute(args: Args, ids: IDCache):
"""Handle each user in the main process"""
get_perm_map(args, ids, user).run()
if not isinstance(exc, CalledProcessError):
args.logger.debug(traceback.format_exc())
args.logger.error(str(exc))
def get_perm_map(args: Args, ids: IDCache, user: str):
"""Return a PermMap subclass object"""
return CwpPermMap(ids, args, user)
if args.role == 'cPanel':
return CpanelPermMap(ids, args, user)
return WP3PermMap(ids, args)
sys.exit(f"BUG in get_perm_map(): {args.role=}")
if __name__ == '__main__':