Mini Shell
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2024 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
import os
import pwd
import sys
import cldetectlib as detect
import secureio
from clcommon import clcaptain
from clcommon.utils import ExternalProgramFailed
# Create user wrapper for ISP.
# Call also from cl-selector with username and PHP ver only
def ispmanager_create_user_wrapper(username, user_php_ver, user_data=None, is_write_log=False):
# Only for ISP Manager v4.x
detect.getCP()
if not detect.is_ispmanager() or not detect.CP_VERSION.startswith('4'):
return
# 1. Check rights
if user_data is None:
user_data = pwd.getpwnam(username)
uid = user_data.pw_uid
gid = user_data.pw_gid
process_uid = os.geteuid()
if process_uid != uid:
# we work not as the specified user, drop permissions required
drop_perm = True
else:
# we run under user, drop not needed
uid = None
gid = None
drop_perm = False
# 2. Create wrapper with the proper content (if it isn't present) in user dir
user_wrapper_file = os.path.join(user_data.pw_dir, 'php-bin/php')
write_wrapper(user_wrapper_file, user_php_ver, uid, gid, drop_perm, is_write_log)
# 3. Create wrapper with the proper content (if it isn't present) in /var/www/php-bin/[user]
PATH_MASK = "/var/www/php-bin/%s"
user_wrapper_file = os.path.join(PATH_MASK % username, "php")
write_wrapper(user_wrapper_file, user_php_ver, uid, gid, drop_perm, is_write_log)
# Creates user wrapper
def write_wrapper(wrapper_filename, user_php_ver, uid, gid, drop_perm, is_write_log):
def create_wrapper():
if drop_perm:
secureio.write_file_secure([s_wrapper_contents], wrapper_filename, uid, gid, drop_perm, 0o555, is_write_log)
else:
try:
clcaptain.write(wrapper_filename, s_wrapper_contents)
os.chmod(wrapper_filename, 0o555)
except (OSError, IOError, ExternalProgramFailed) as e:
secureio.logging("Error: failed to write file " + wrapper_filename + ": " + str(e), secureio.SILENT_FLAG, 1, is_write_log)
dir_name = os.path.dirname(wrapper_filename)
if os.path.isdir(dir_name):
# wrapper backup file
bak_wrapper_filename = wrapper_filename+'.cagefs.bak'
# determine wrapper content
if user_php_ver == 'native':
s_wrapper_contents = "#!/usr/bin/php-cgi\n"
else:
s_wrapper_contents = "#!/usr/local/bin/php-cgi-etc\n"
if not os.path.lexists(wrapper_filename):
# there is no wrapper, create it
create_wrapper()
return
# wrapper already present
try:
content = secureio.read_file_secure(wrapper_filename, uid, gid, False, is_write_log)
except (OSError, IOError) as e:
secureio.logging("Error: failed to read file " + wrapper_filename + ": " + str(e), secureio.SILENT_FLAG, 1, is_write_log)
return
if not content:
# empty wrapper, create it
create_wrapper()
return
# change wrapper content according to required PHP version
if content[0].strip() == "#!/usr/local/bin/php-cgi-etc":
# alt version wrapper found
if user_php_ver == 'native':
# and switch to native
if os.path.lexists(bak_wrapper_filename) and os.path.getsize(bak_wrapper_filename) > 0:
# backup copy present and is not empty, restore it to wrapper
rename_file_secure(bak_wrapper_filename, wrapper_filename, uid, gid, write_log=is_write_log)
else:
# if backup copy is absent or empty, create our native wrapper
create_wrapper()
else:
# native wrapper found
if user_php_ver != 'native':
# switch to alt version
# make backup copy old wrapper: copy php to php.cagefs.bak
if drop_perm:
secureio.write_file_secure(content, bak_wrapper_filename, uid, gid, drop_perm, 0o444, is_write_log)
else:
try:
clcaptain.write(bak_wrapper_filename, ''.join(content))
os.chmod(bak_wrapper_filename, 0o444)
except (OSError, IOError, ExternalProgramFailed) as e:
secureio.logging("Error: failed to write file " + bak_wrapper_filename + ": " + str(e), secureio.SILENT_FLAG, 1, is_write_log)
# create wrapper
create_wrapper()
# rename file with drop permissions
def rename_file_secure(old_filename, new_filename, uid=None, gid=None, exit_on_error=False, write_log=True):
drop_perm = (uid is not None) and (gid is not None)
if drop_perm:
secureio.set_user_perm(uid, gid)
is_error = False
# if backup present, rename it to wrapper
try:
os.rename(old_filename, new_filename)
os.chmod(new_filename, 0o555)
except (OSError, IOError) as e:
secureio.logging("Error: failed to rename " + old_filename + " to " + new_filename + ": " + str(e), secureio.SILENT_FLAG, 1, write_log)
is_error = True
if drop_perm:
secureio.set_root_perm()
if is_error and exit_on_error:
sys.exit(1)
return is_error
Zerion Mini Shell 1.0