Mini Shell
Direktori : /usr/lib/fixperms/ |
|
Current File : //usr/lib/fixperms/fixperms_main.py |
"""Main logic for fixperms"""
import sys
import re
from functools import partial
from subprocess import run, PIPE, CalledProcessError
from concurrent.futures import ProcessPoolExecutor, as_completed
import traceback
import rads
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'):
return
run_cmd = partial(run, encoding='UTF-8', stdout=PIPE, check=False)
# pylint: disable=unsupported-membership-test
if role == 'CWP':
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):
return
good_mods = 'mod_ruid2 or mod_mpm_itk'
kb_url = "http://wiki.centos-webpanel.com/dso-php-handler-for-cwp"
else:
php = run_cmd(
['/usr/local/cpanel/bin/rebuild_phpconf', '--current']
).stdout
if 'SAPI: dso' not in php:
return
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:
return
# CWP users might need to build it with /usr/local/apache/bin/apxs
sys.exit(
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
{good_mods} Apache
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}"""
)
def main():
"""Main program logic: iterate over each user and run fixperms"""
args = parse_args()
try:
ids = IDCache(args.role)
except KeyError as exc:
args.logger.critical('%s. Cannot continue.', exc)
sys.exit(1)
check_dso_without_modruid2(args.role)
if len(args.users) > 1 and args.procs > 1:
parallel_execute(args, ids)
else:
serial_execute(args, ids)
def parallel_execute(args: Args, ids: IDCache):
"""Fork processes to handle each user"""
exit_code = 0
with ProcessPoolExecutor(max_workers=args.procs) as pool:
futures = []
for user in args.users:
try:
perm_map = get_perm_map(args, ids, user)
except Exception as exc:
if not isinstance(exc, CalledProcessError):
args.logger.debug(traceback.format_exc())
args.logger.error(str(exc))
exit_code = 1
continue
future = pool.submit(perm_map.run)
futures.append(future)
for future in as_completed(futures):
try:
future.result()
except Exception as exc:
if not isinstance(exc, CalledProcessError):
args.logger.debug(traceback.format_exc())
args.logger.error(str(exc))
exit_code = 1
continue
sys.exit(exit_code)
def serial_execute(args: Args, ids: IDCache):
"""Handle each user in the main process"""
exit_code = 0
for user in args.users:
try:
get_perm_map(args, ids, user).run()
except Exception as exc:
if not isinstance(exc, CalledProcessError):
args.logger.debug(traceback.format_exc())
args.logger.error(str(exc))
exit_code = 1
continue
sys.exit(exit_code)
def get_perm_map(args: Args, ids: IDCache, user: str):
"""Return a PermMap subclass object"""
if args.role == 'CWP':
return CwpPermMap(ids, args, user)
if args.role == 'cPanel':
return CpanelPermMap(ids, args, user)
if args.role == 'WP3':
return WP3PermMap(ids, args)
sys.exit(f"BUG in get_perm_map(): {args.role=}")
if __name__ == '__main__':
main()
Zerion Mini Shell 1.0