Hacked By AnonymousFox

Current Path : /usr/share/cagefs/
Upload File :
Current File : //usr/share/cagefs/cagefs_ispmanager_lib.py

# -*- coding: utf-8 -*-
# ISP Manager function library
#
# 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
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions
#are met:
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following
#    disclaimer in the documentation and/or other materials provided
#    with the distribution.
#  * The names of its contributors may not be used to endorse or
#    promote products derived from this software without specific
#    prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
#FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
#COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
#INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
#BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
#ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#POSSIBILITY OF SUCH DAMAGE.
#

# Module functionality:
# Create php.ini files for DA PHP version selector
# Create symlink to user data directory
#

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future import standard_library
standard_library.install_aliases()
from builtins import *
import os
import pwd
import shutil
import subprocess
import cagefslib
import sys
import cldetectlib as detect
from cagefsctl import get_list_of_users, cagefs_is_enabled, save_dir_exists, get_exclude_user_list, get_min_uid, MIN_UID
import secureio
from clcommon import clcaptain
from clcommon.utils import ExternalProgramFailed
from clcommon.utils import mod_makedirs


def install_ispmanager_directory_exclude():
    """
    Install exclude .cagefs folder from backup
    :return: None
    """
    # Only for ISP Manager
    detect.getCP()
    if not detect.is_ispmanager():
        return

    if detect.CP_VERSION.startswith('4'):
        # ISP Manager v4
        isp_command_list = ['/usr/local/ispmgr/sbin/mgrctl', 'backupplan']
        try:
            result = cagefslib.Execute(isp_command_list, check_return_code=False, exit_on_error=False).split('\n')
            for line in result:
                if line.find('id=') != -1:
                    plan_id = str(line.split('name=')[0].replace('id=', '').strip())
                    isp_command_list.extend(['.content.edit plid=' + plan_id, 'sok=ok', 'type=exclude',
                                                                    'module=file','filedata=.cagefs'])
                    cagefslib.Execute(isp_command_list, check_return_code=False, exit_on_error=False)
        except OSError as e:
            secureio.print_error('Failed to set exclude dir for ISPManager 4:', str(e))
    else:
        # ISP Manager v5
        if detect.ispmanager5_is_master():
            # ISP5 Master
            try:
                cagefs_exclude_is_found = False
                exclude_files_list = list()
                # Search .cagefs in excludes
                isp_command_list = ['/usr/local/mgr5/sbin/mgrctl', '-m', 'ispmgr', 'backup2.settings']
                result = cagefslib.Execute(isp_command_list, check_return_code=False, exit_on_error=False).split('\n')
                for line in result:
                    if line.startswith('exclude_files'):
                        # line as:
                        # exclude_files=data/.cagefs data/mod-tmp data/somedir
                        l_parts = line.strip().split('=')
                        if len(l_parts) != 2:
                            continue
                        # l_parts[1] as 'data/.cagefs data/mod-tmp data/somedir'
                        exclude_files_list = l_parts[1].split(' ')
                        # if .cagefs absent in exclude list, add it
                        for exclude_file in exclude_files_list:
                            if '.cagefs' in exclude_file:
                                cagefs_exclude_is_found = True
                                break
                        break
                if not cagefs_exclude_is_found:
                    # .cagefs not found in excludes, add it
                    add_line = ' '.join(exclude_files_list) + ' ' + 'data/.cagefs'
                    add_line = add_line.strip()
                    isp_command_list.extend(['exclude_files=%s' % add_line, 'sok=ok'])
                    cagefslib.Execute(isp_command_list, check_return_code=False, exit_on_error=False).split('\n')
            except (OSError, IOError,) as e:
                secureio.print_error('Failed to set exclude dir for ISPManager 5:', str(e))


def create_php_cgi_etc(filename, php_ini_path):
    if os.path.isfile(filename):
        # check file content
        content = cagefslib.read_file(filename)
        if content[0] == '#!/bin/bash\n':
            for line in content:
                parts = line.strip().split()
                if (len(parts) == 4) and (parts[0] == 'exec') and (parts[1] == '/usr/bin/php-cgi') and\
                                (parts[2] == '-c') and (parts[3] == php_ini_path):
                    return

    dirpath = os.path.dirname(filename)
    if not os.path.lexists(dirpath):
        mod_makedirs(dirpath, 0o755)

    f = open(filename, 'w')
    f.write('#!/bin/bash\n')
    f.write('exec /usr/bin/php-cgi -c ' + php_ini_path + '\n')
    f.close()
    # make it executable
    os.chmod(filename, 0o755)


# Call from cagefs
def configure_selector_for_ispmanager():
    # Only for ISP Manager v4.x
    detect.getCP()
    if not detect.is_ispmanager() or not detect.CP_VERSION.startswith('4'):
        return

    ISP_MANAGER_CONF_FILE = '/usr/local/ispmgr/etc/ispmgr.conf'
    if not os.path.isfile(ISP_MANAGER_CONF_FILE):
        return

    # 1. Read php.ini path from native conf
    cagefslib.read_native_conf()
    if not cagefslib.config_loaded:
        return
    content = cagefslib.orig_binaries
    php_ini_path = '/etc/php.ini'
    if 'php.ini' in content:
        php_ini_path = content['php.ini']

    # 2. Create /usr/local/bin/php-cgi-etc
    script_file = '/usr/local/bin/php-cgi-etc'
    create_php_cgi_etc(script_file, php_ini_path)

    # 3. Create in CageFs skeleton (/usr/share/cagefs-skeleton/usr/local/bin/php-cgi-etc)
    if os.path.isdir('/usr/share/cagefs-skeleton'):
        create_php_cgi_etc('/usr/share/cagefs-skeleton/usr/local/bin/php-cgi-etc', php_ini_path)

    # 4. Read /usr/local/ispmgr/etc/ispmgr.conf
    content = cagefslib.read_file(ISP_MANAGER_CONF_FILE)
    i = 0
    is_found = False
    old_path = ''
    for line in content:
        parts = line.strip().split()
        if (len(parts) == 3) and (parts[0] == 'path') and (parts[1] == 'phpcgibinary'):
            old_path = parts[2]
            is_found = True
            break
        i += 1

    if is_found:
        # directive found, check path in it
        if old_path != script_file:
            content[i] = 'path phpcgibinary ' + script_file + '\n'
            cagefslib.write_file(ISP_MANAGER_CONF_FILE, content)
    else:
        # directive not found, append it
        f = open(ISP_MANAGER_CONF_FILE, 'a')
        f.write('path phpcgibinary ' + script_file + '\n')
        f.close()

    # 5. 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()

    # 6. Create user php wrappers
    #!/usr/local/bin/php-cgi-etc - for alt versions
    #!/usr/bin/php-cgi           - for native
    if (not cagefs_is_enabled()) or save_dir_exists():
        cagefs_enabled_users = []
    else:
        cagefs_enabled_users = get_list_of_users(True)

    exclude_list = get_exclude_user_list()
    get_min_uid()
    min_uid = MIN_UID

    pw = pwd.getpwall()
    for user_data in pw:
        if user_data.pw_uid < min_uid or user_data.pw_name in exclude_list:
            continue

        is_user_in_cagefs = user_data.pw_name in cagefs_enabled_users
        ispmanager_create_user_wrapper_detect_php_ver(user_data, is_user_in_cagefs, True)


# Creates user wrapper dependently user in cagefs or not
# This function for single-user operations in cagefsctl
def ispmanager_create_user_wrapper_detect_php_ver(user_data, is_user_in_cagefs, 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

    if not is_user_in_cagefs:
        user_php_ver = "native"
    else:
        user_php_ver = cagefslib.get_php_version_for_user(user_data.pw_name)
        if user_php_ver is None:
            return

    ispmanager_create_user_wrapper(user_data.pw_name, user_php_ver, user_data, is_write_log)


# 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

Hacked By AnonymousFox1.0, Coded By AnonymousFox