File manager - Edit - /usr/share/cagefs/repair_homes.py
Back
#!/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 getopt import os import pwd import shutil import stat import subprocess import sys import time from clcommon.utils import mod_makedirs from clcagefslib.const import BASEDIR from secureio import print_error LOGFILE = '/usr/share/cagefs/repair_homes.log' BASE_HOME_DIR = '/home' PASSWD = '/etc/passwd' HTTPD_CONF = '/usr/local/apache/conf/httpd.conf' USERDATA_UPDATE = '/usr/local/cpanel/bin/userdata_update' USERMOD = '/usr/sbin/usermod' USERDATA = '/var/cpanel/userdata' # Function to uninstall cagefs.etc CAGEFS_ETC='/etc/cagefs.etc' DEBUG_PREFIX='' def uninstall_cagefs_etc(): try: dirList = os.listdir(DEBUG_PREFIX + CAGEFS_ETC) except OSError: return for _file in dirList: target = DEBUG_PREFIX + '/etc/' + _file origin = DEBUG_PREFIX + CAGEFS_ETC + '/' + _file if not os.path.islink(target): continue try: os.unlink(target) except OSError: print('Warning: failed to remove', target) try: os.rename(origin, target) except OSError: print('Warning: failed to move', origin, 'to', target) # Functions for unmounting users for CageFS 2.0 UMOUNT='/bin/umount' def umount_list(_list): _list.sort() _list.reverse() for line in _list: subprocess.call([UMOUNT, "-l", line]) def get_mounted_dirs(): mounts = open("/proc/mounts", "r").readlines() _list = [] for line in mounts: mountpoint = line.split()[1] if mountpoint.find(BASEDIR) != -1: _list.append(mountpoint[mountpoint.find('/'):]) return _list def umount(user): subdir = BASEDIR + '/'+user[-2:]+ '/'+user+'/' mounts = open("/proc/mounts", "r").readlines() mylist = [] for line in mounts: mountpoint = line.split()[1] if mountpoint.find(subdir) != -1: mylist.append(mountpoint[mountpoint.find('/'):]) umount_list(mylist) # Returns True if unmounting is done def umount_all(): dirs = get_mounted_dirs() if len(dirs) != 0: umount_list(dirs) return True return False # Functions for enabling/disabling users for CageFS 2.0 INIPREFIX='/etc/cagefs/' disabled_dir = INIPREFIX+'users.disabled' enabled_dir = INIPREFIX+'users.enabled' def toggle_file(_dir, username, enable): prefix = username[-2:] fname = '/'+prefix+'/'+username if enable: try: os.remove(_dir + fname) except OSError: pass try: os.rmdir(_dir + '/'+prefix) except OSError: pass else: try: mod_makedirs(_dir+'/'+prefix, 0o751) except OSError: pass try: open(_dir + fname, 'w').close() os.chmod(_dir + fname, 0o644) except OSError: pass def toggle_user(username, enable): if os.path.isdir(disabled_dir): toggle_file(disabled_dir, username, enable) if os.path.isdir(enabled_dir): toggle_file(enabled_dir, username, not enable) def disable_user(user): toggle_user(user, False) umount(user) def enable_user(user): toggle_user(user, True) def is_text_file(path): if os.path.isfile(path): p = subprocess.Popen(['file','-bi', path], stdout=subprocess.PIPE, text=True) out, _ = p.communicate() if 'text' in out: return True return False def confirm(message): print(message, end=' ', flush=True) while True: line = sys.stdin.readline() if line == "yes\n": break elif line == "no\n": print("Aborting") sys.exit(0) print("Please, reply with yes or no") # Returns True if users with invalid pathes to home directories exist def invalid_homes_exist(): # get all users from /etc/passwd pw = pwd.getpwall() for line in pw: if line.pw_dir.startswith('/var/cagefs/'): return True return False def print_log(log, *messages): for msg in messages: print(msg, end=' ') print(msg, end=' ', file=log) print("") print("", file=log) # Function sets home directory for specified user # Returns True if error has occured def usermod(user, home_dir, log): try: ret = subprocess.call([USERMOD, "-d", home_dir, user]) if ret != 0: print_log(log, "Error:", USERMOD, "-d", home_dir, user, "failed") return True except OSError: print_log(log, 'Error: failed to run', USERMOD, "-d", home_dir, user) return True return False # Run a subprocess with list of options. Log output of subprocess. # Return True if error has occured def run_subprocess(log, command_line_list): error = False try: # run the command and suppress it's output p = subprocess.Popen(command_line_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) (stdoutdata, stderrdata) = p.communicate() if stdoutdata != None: print_log(log, stdoutdata) if stderrdata != None: print_log(log, stderrdata) # check return code of the child if p.returncode != 0: error = True except OSError: print_log(log, 'Error: failed to run', command_line_list) error = True return error def repair_homes(ask = True): log = open(LOGFILE, 'a+') if not invalid_homes_exist(): print_log(log, 'Users with invalid pathes to home directories do NOT exist') log.close() return print("Users that have invalid path to home directory are found") print("(users that have path to home directory starting with /var/cagefs).") print('This script will move home directories to "'+BASE_HOME_DIR+'" and change pathes to home directories') print("in /etc/passwd, /var/cpanel/userdata and /usr/local/apache/conf/httpd.conf") print("Log of all operations will be written to", LOGFILE) print("Backups will be created automatically.") print("") if ask: confirm("Do you want to continue (yes/no)? ") # Print current date and time cur_time = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) print_log(log, "*** Repair started", cur_time) # Make backups shutil.copyfile(PASSWD, PASSWD+'.repair.bak') print_log(log, "Created backup", PASSWD+'.repair.bak') shutil.copyfile(HTTPD_CONF, HTTPD_CONF+'.repair.bak') print_log(log, "Created backup", HTTPD_CONF+'.repair.bak') # Read httpd.conf print_log(log, 'Reading', HTTPD_CONF, '...') _file = open(HTTPD_CONF, "r") httpd_conf = _file.readlines() _file.close() # get all users from /etc/passwd pw = pwd.getpwall() for line in pw: if line.pw_dir.startswith('/var/cagefs/'): # pw_dir is like /var/cagefs/[prefix]/[parent-user]/home/[parent-user]/[invalid-user] # or # like /var/cagefs/[prefix]/[parent-user]/var/cagefs/[prefix2]/[parent-user2]/home/[parent-user2]/[parent-user]/[invalid-user] # etc... print_log(log, "Repairing user", line.pw_name, "...") # Get name of invalid user invalid_user = os.path.basename(line.pw_dir) if invalid_user != line.pw_name: print_log(log, 'Error: Cannot repair home path', line.pw_dir, 'for user', line.pw_name) continue # Get /var/cagefs/[prefix]/[parent-user]/home/[parent-user] # or /var/cagefs/[prefix]/[parent-user]/var/cagefs/[prefix2]/[parent-user2]/home/[parent-user2]/[parent-user] var_cagefs_home_of_parent = os.path.dirname(line.pw_dir) # Get name of "parent" of invalid user parent = os.path.basename( var_cagefs_home_of_parent ) # Get passwd info for parent try: pw_line = pwd.getpwnam(parent) except Exception as e: print_log(log, 'Cannot repair home path', line.pw_dir, 'for user', line.pw_name) print_log(log, 'Error: "Parent" user', parent, 'does NOT exist') print_log(log, str(e)) continue # Get home of parent parent_home = pw_line.pw_dir # if not var_cagefs_home_of_parent.endswith(parent_home): # print_log(log, 'Cannot repair home path', line.pw_dir, 'for user', line.pw_name) # print_log(log, 'Error: Path to home directory in /var/cagefs for parent user is invalid') # print_log(log, 'Parent user:', parent) # print_log(log, 'Home directory of parent user:', parent_home) # print_log(log, 'Home directory of parent user in /var/cagefs:', var_cagefs_home_of_parent) # continue # Get home base (parent) directory (commonly "/home") if parent_home.startswith('/var/cagefs/'): # Cyclic error. Parent user should be repaired already. So home of parent should be "/home" base_home = BASE_HOME_DIR else: base_home = os.path.dirname(parent_home) print_log(log, 'Base home directory:', base_home) # Incorrect (invalid) location of home dir of invalid user src = base_home+'/'+parent+'/'+invalid_user # Correct location of home dir of invalid user dest = base_home+'/'+invalid_user # Check that home dir of invalid user exists in home dir of "parent" user # (Check that /home/[parent-user]/[invalid-user] exists) if not os.path.isdir(src): # Check that home dir of invalid user is in proper location already if not os.path.isdir(dest): print_log(log, 'Error: home directory of user', invalid_user, 'is NOT found') print_log(log, 'Searched locations:', src, "and", dest) continue # SECURITY (F-13): src is not a directory but dest is. We have # no fd-bound inode captured at rename time here (the else # branch below opens one via O_PATH | O_NOFOLLOW; this branch # does no rename), so we cannot tell a legitimate residual # (a prior invocation whose usermod call failed AFTER the # rename) from an attacker-planted inode left at dest by the # "leaving attacker-supplied inode at dest" rollback-failure # path below. Both look identical from disk. Refuse to update # /etc/passwd in this ambiguous state and log a WARNING so an # admin can inspect dest and either move it into place or # remove it before re-running repair. print_log(log, 'Warning: source', src, 'is not a directory but', 'destination', dest, 'exists; refusing to update', '/etc/passwd for user', invalid_user, '(possible residual state from a prior TOCTOU', 'rollback failure -- admin must inspect', dest, 'before re-running repair_homes)') continue else: # Home dir is NOT moved yet # Disable and unmount user disable_user(invalid_user) # SECURITY (CLOS-4558): base_home/parent (e.g. /home/<parent>) is the # home directory of the unprivileged "parent" user, who can plant # <invalid_user> inside it as a symlink to any directory. The old code # resolved that symlink with os.path.realpath() and then renamed the # *target* as root -- letting a local user redirect the move onto # another tenant's home (e.g. /home/<victim>). We instead operate on the # entry by name, relative to a directory fd of the parent home, and # never resolve the final component: os.lstat() and rename(2) do not # follow a symlink in the final path component, so even a symlink # swapped in after the check (TOCTOU) can only move the link itself, # never its target. # # parent_dir is resolved with realpath() (not opened O_NOFOLLOW) on # purpose: every component above the final entry lives under /home and # is root-owned, so a legitimately symlinked home base (/home -> # /data/home) or relocated parent home (/home/<parent> -> /home2/<parent>) # must keep working. Only the final, attacker-writable entry is treated # as untrusted. parent_dir = os.path.realpath(base_home + '/' + parent) try: parent_dfd = os.open(parent_dir, os.O_RDONLY | os.O_DIRECTORY) except OSError as e: print_log(log, 'Error: cannot open parent directory', parent_dir, 'for user', invalid_user, '-', str(e)) enable_user(invalid_user) continue try: # SECURITY (F-13): bind the final-component entry to a fd # via O_PATH | O_NOFOLLOW so every check below refers to the # inode captured at open() time. Using os.lstat(name, dir_fd) # here would re-resolve `name` inside parent_dfd on every # call, letting a parent tenant renameat2(RENAME_EXCHANGE) # swap the entry between the check and the rename(2) below # and slip a different inode into /home/<invalid_user>. The # fd-bound fstat closes that window; a post-rename inode # match (below) catches an attacker who swapped the *entry* # (not the inode) between our open() and the rename call. try: entry_fd = os.open( invalid_user, os.O_PATH | os.O_NOFOLLOW, dir_fd=parent_dfd) except OSError as e: print_log(log, 'Error: cannot open', src, 'for user', invalid_user, '-', str(e)) enable_user(invalid_user) continue try: # fstat via the fd -- reject anything that is not a # real directory (in particular a parent-planted # symlink, which O_PATH|O_NOFOLLOW pins as a symlink # inode, not the target it points at). try: st = os.fstat(entry_fd) except OSError as e: print_log(log, 'Error: cannot stat', src, 'for user', invalid_user, '-', str(e)) enable_user(invalid_user) continue if not stat.S_ISDIR(st.st_mode): print_log(log, 'Error: source path', src, 'is not a regular ' 'directory (possible symlink attack); refusing to ' 'move it for user', invalid_user) enable_user(invalid_user) continue # SECURITY (CLOS-4596, F-37): rename(2) preserves the source # inode's uid/gid -- so a parent tenant who unlinks the # misplaced /home/<parent>/<invalid_user> entry and re-creates # it as a real directory they own would end up with # /home/<invalid_user> registered in /etc/passwd but # parent-owned. Reject the rename unless the final-component # target inode is owned by invalid_user. The uid comes from # fstat(entry_fd) above so a TOCTOU entry swap can never # leak ownership of a different inode through this check. # Also verify the immediate parent directory is owned by the # legitimate parent user (read via fstat() on parent_dfd, # which is bound to the already-opened inode and cannot be # swapped after open) -- if /home/<parent> has been replaced # by an attacker-controlled inode owned by some other uid, # we must not proceed. try: invalid_user_uid = pwd.getpwnam(invalid_user).pw_uid except KeyError as e: print_log(log, 'Error: cannot resolve uid for user', invalid_user, '-', str(e), '; refusing to move', src) enable_user(invalid_user) continue if st.st_uid != invalid_user_uid: print_log(log, 'Security: source path', src, 'is not ' 'owned by user', invalid_user, '(uid=', st.st_uid, 'expected=', invalid_user_uid, '); refusing to move it ' '(possible ownership-confusion attack)') enable_user(invalid_user) continue try: parent_st = os.fstat(parent_dfd) except OSError as e: print_log(log, 'Error: cannot fstat parent directory', parent_dir, 'for user', invalid_user, '-', str(e)) enable_user(invalid_user) continue if parent_st.st_uid != pw_line.pw_uid: print_log(log, 'Security: parent directory', parent_dir, 'is not owned by parent user', parent, '(uid=', parent_st.st_uid, 'expected=', pw_line.pw_uid, '); refusing to move', src, '(possible parent-directory substitution attack)') enable_user(invalid_user) continue # remove dest if it is symlink if os.path.islink(dest): try: os.unlink(dest) except (OSError, IOError): pass # Check that "correct" home directory of invalid_user does NOT exist yet if not os.path.exists(dest): # Do "mv /home/[parent-user]/[invalid-user] /home/[invalid-user]". # Source is given by name relative to parent_dfd so rename(2) # acts on the entry itself and never follows a symlink. try: os.rename(invalid_user, dest, src_dir_fd=parent_dfd) except (OSError, IOError): print_log(log, 'Error while moving', src, 'to', dest) enable_user(invalid_user) continue # SECURITY (F-13): rename(2) re-resolves the source # name at rename time, so an attacker who swapped # the parent's dentry between our fstat above and # this rename would have caused rename(2) to move # their inode -- not the one we validated -- into # /home/<invalid_user>. Compare the inode now at # `dest` against the (dev, ino) we captured on # entry_fd; if they differ, roll the rename back # and refuse to commit /etc/passwd to an attacker- # planted directory. try: dest_st = os.lstat(dest) except OSError as e: print_log(log, 'Error: cannot stat post-rename', dest, 'for user', invalid_user, '-', str(e)) enable_user(invalid_user) continue if (dest_st.st_dev != st.st_dev or dest_st.st_ino != st.st_ino): print_log(log, 'Security: post-rename inode at', dest, '(dev=', dest_st.st_dev, 'ino=', dest_st.st_ino, ') does not match the inode captured ' 'before rename (dev=', st.st_dev, 'ino=', st.st_ino, '); a TOCTOU swap by parent user', parent, 'is suspected -- rolling ' 'back and refusing to move', src) try: os.rename(dest, invalid_user, dst_dir_fd=parent_dfd) except OSError as rollback_err: print_log(log, 'CRITICAL: rollback of', dest, 'to', src, 'failed -', str(rollback_err), '; leaving attacker-supplied ' 'inode at', dest, 'and NOT updating /etc/passwd') enable_user(invalid_user) continue # Check that moving directory was successfull if (not os.path.isdir(dest)) or os.path.lexists(src): print_log(log, 'Error: moving', src, 'to', dest, 'was NOT successfull') enable_user(invalid_user) continue else: # Destination (correct) home directory already exists print_log(log, 'Warning: home directory', dest, 'of user', invalid_user, 'already exists') print_log(log, 'Warning: home directory of user', invalid_user, 'is NOT moved') finally: os.close(entry_fd) finally: os.close(parent_dfd) # Home dir is moved already # Change path to home dir in /etc/passwd if usermod(invalid_user, dest, log): enable_user(invalid_user) continue # Change path to home dir in httpd.conf for ind in range(len(httpd_conf)): if httpd_conf[ind].find('/var/cagefs/') != -1: temp = httpd_conf[ind].replace(line.pw_dir, dest) # Invalid path is repaired correctly ? # line.pw_dir is NOT a part of another more long invalid path (as a result of cyclic error) ? if temp.find('/var/cagefs/') == -1: httpd_conf[ind] = temp # Change path to home dir in all TEXT files in /var/cpanel/userdata for next_file in os.listdir(os.path.join(USERDATA, invalid_user)): file_path = os.path.join(USERDATA, invalid_user) + '/' + next_file if is_text_file(file_path): modified = False userdata_file = open(file_path, 'r') userdata = userdata_file.readlines() userdata_file.close() for ind in range(len(userdata)): if userdata[ind].find('/var/cagefs/') != -1: temp = userdata[ind].replace(line.pw_dir, dest) # Invalid path is repaired correctly ? # line.pw_dir is NOT a part of another more long invalid path (as a result of cyclic error) ? if temp.find('/var/cagefs/') == -1: userdata[ind] = temp modified = True else: print_log(log, 'Error: cannot repair', file_path) modified = False break if modified: shutil.copyfile(file_path, file_path+'.repair.bak') print_log(log, "Created backup", file_path+'.repair.bak') userdata_file = open(file_path, 'w') for next_line in userdata: userdata_file.write(next_line) userdata_file.close() enable_user(invalid_user) print_log(log, 'User', invalid_user, "has been repaired SUCCESSFULLY!") # Write httpd.conf print_log(log, 'Writting', HTTPD_CONF, '...') _file = open(HTTPD_CONF, "w") for line in httpd_conf: _file.write(line) _file.close() # Rebuild /var/cpanel/userdata print_log(log, 'Rebuilding /var/cpanel/userdata...') run_subprocess(log, [USERDATA_UPDATE]) log.close() def print_warning(): print('Please, rename or remove /var/cagefs directory of old version of CageFS') print('in order to correct operation of new version of CageFS.') print('New /var/cagefs directory will be created automatically.') def rename_var_cagefs(): if os.path.exists('/var/cagefs'): # Users with invalid pathes to home directories do NOT exist ? if not invalid_homes_exist(): try: if os.path.isdir('/var/cagefs.old') and (not os.path.islink('/var/cagefs.old')): shutil.rmtree('/var/cagefs.old', True) else: os.unlink('/var/cagefs.old') except (OSError, IOError): pass try: os.rename('/var/cagefs', '/var/cagefs.old') print('/var/cagefs has been renamed to /var/cagefs.old') except (OSError, IOError): print_error('failed to rename /var/cagefs to /var/cagefs.old') print_warning() else: print_warning() def main(): try: opts, _ = getopt.getopt(sys.argv[1:], "f", ["do-not-ask", "rename-var-cagefs", "uninstall_cagefs_etc",\ "add-syslog-socket", "remove-syslog-socket"]) except getopt.GetoptError: print('Usage error') sys.exit(1) if (os.geteuid()!=0): print_error('root privileges required. Abort.') sys.exit(1) for o, _ in opts: if o in ('-f', '--do-not-ask'): repair_homes(False) sys.exit(0) elif o in ('--rename-var-cagefs',): rename_var_cagefs() sys.exit(0) elif o in ('--uninstall_cagefs_etc',): uninstall_cagefs_etc() sys.exit(0) elif o in ('--add-syslog-socket',): print ("Invalid option.\nUse /usr/share/cagefs-plugins/install" "-cagefs-plugin.py --add-syslog-socket") sys.exit(0) elif o in ('--remove-syslog-socket',): print ("Invalid option.\nUse /usr/share/cagefs-plugins/install" "-cagefs-plugin.py --remove-syslog-socket") sys.exit(0) repair_homes(True) # mv /home/mistersc/zthzmnvp /home/zthzmnvp # mkdir -p /var/cagefs/sc/mistersc/home/mistersc # ln -s /home/zthzmnvp /var/cagefs/sc/mistersc/home/mistersc/zthzmnvp # mv /home/lakzqyaa/zcktakme /home/zcktakme # mkdir -p /var/cagefs/aa/lakzqyaa/var/cagefs/sc/mistersc/home/mistersc/lakzqyaa # ln -s /home/zcktakme /var/cagefs/aa/lakzqyaa/var/cagefs/sc/mistersc/home/mistersc/lakzqyaa/zcktakme # OLD function (NOT USED) def repair_homes_old(): print("This script repairs home directories of users that have invalid pathes to home directories") print("(users that have path to home directory starting with /var/cagefs)") print("This script will move home directories to proper location and create") print("appropriate symlink in /var/cagefs") print("") confirm("Do you want to continue (yes/no)? ") log = open(LOGFILE, 'a+') # Print current date and time cur_time = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) print_log(log, "*** Repair started", cur_time) if not invalid_homes_exist(): print_log(log, 'Users with invalid pathes to home directories do NOT exist') log.close() return # get all users from /etc/passwd pw = pwd.getpwall() for line in pw: if line.pw_dir.startswith('/var/cagefs/'): # pw_dir is like /var/cagefs/[prefix]/[parent-user]/home/[parent-user]/[invalid-user] # or # like /var/cagefs/[prefix]/[parent-user]/var/cagefs/[prefix2]/[parent-user2]/home/[parent-user2]/[parent-user]/[invalid-user] # etc... if os.path.islink(line.pw_dir): print_log(log, 'Home', line.pw_dir, 'for user', line.pw_name, 'is repaired already. Skipping...') continue print_log(log, "Repairing user", line.pw_name, "...") # Get name of invalid user invalid_user = os.path.basename(line.pw_dir) if invalid_user != line.pw_name: print_log(log, 'Error: Cannot repair home path', line.pw_dir, 'for user', line.pw_name) continue # Get /var/cagefs/[prefix]/[parent-user]/home/[parent-user] # or /var/cagefs/[prefix]/[parent-user]/var/cagefs/[prefix2]/[parent-user2]/home/[parent-user2]/[parent-user] var_cagefs_home_of_parent = os.path.dirname(line.pw_dir) # Get name of "parent" of invalid user parent = os.path.basename( var_cagefs_home_of_parent ) # Get passwd info for parent try: pw_line = pwd.getpwnam(parent) except Exception as e: print_log(log, 'Cannot repair home path', line.pw_dir, 'for user', line.pw_name) print_log(log, 'Error: "Parent" user', parent, 'does NOT exist') print_log(log, str(e)) continue # Get home of parent parent_home = pw_line.pw_dir if not var_cagefs_home_of_parent.endswith(parent_home): print_log(log, 'Cannot repair home path', line.pw_dir, 'for user', line.pw_name) print_log(log, 'Error: Path to home directory in /var/cagefs for parent user is invalid') print_log(log, 'Parent user:', parent) print_log(log, 'Home directory of parent user:', parent_home) print_log(log, 'Home directory of parent user in /var/cagefs:', var_cagefs_home_of_parent) continue # Get home base (parent) directory (commonly "/home") if parent_home.startswith('/var/cagefs/'): # Cyclic error. Parent user should be repaired already. So home of parent should be "/home" base_home = BASE_HOME_DIR else: base_home = os.path.dirname(parent_home) # Check that home dir of invalid user exists in home dir of "parent" user # (Check that /home/[parent-user]/[invalid-user] exists) src = base_home+'/'+parent+'/'+invalid_user if not os.path.isdir(src): print_log(log, 'Error: home directory of user', invalid_user, 'is NOT found in', base_home+'/'+parent) continue # Check that "correct" home directory of invalid_user does NOT exist yet dest = base_home+'/'+invalid_user if os.path.exists(dest): print_log(log, 'Error: home directory', dest, 'of user', invalid_user, 'already exists') continue # Do "mv /home/[parent-user]/[invalid-user] /home/[invalid-user]" try: os.rename(src, dest) except (OSError, IOError): print_log(log, 'Error while moving', src, 'to', dest) continue # Check that moving directory was successfull if (not os.path.isdir(dest)) or os.path.exists(src): print_log(log, 'Error: moving', src, 'to', dest, 'was NOT successfull') continue # Do "mkdir -p /var/cagefs/[prefix]/[parent-user]/home/[parent-user]" # or "mkdir -p /var/cagefs/[prefix]/[parent-user]/var/cagefs/[prefix2]/[parent-user2]/home/[parent-user2]/[parent-user]" # (ensure that directory exists) try: os.makedirs(var_cagefs_home_of_parent) except (OSError, IOError): pass # Do "ln -s /home/[invalid-user] /var/cagefs/[prefix]/[parent-user]/home/[parent-user]/[invalid-user]" # or "ln -s /home/[invalid-user] /var/cagefs/[prefix]/[parent-user]/var/cagefs/[prefix2]/[parent-user2]/home/[parent-user2]/[parent-user]/[invalid-user]" try: os.symlink(dest, line.pw_dir) except (OSError, IOError): print_log(log, 'Error while creatimg symlink', line.pw_dir, 'to', dest) continue print_log(log, 'User', invalid_user, "has been repaired SUCCESSFULLY!") log.close() if __name__ == "__main__": main()
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Generation time: 0.04 |
proxy
|
phpinfo
|
Settings