B
    u&`bM             *   @   s  d dl mZ d dl mZ d dl mZ d dl mZ d dlmZ e  d dlT d dl	m
Z
 d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd d	l m!Z!m"Z" d d
l#m$Z$m%Z%m&Z&m'Z' d dl(m)Z)m*Z*m+Z+m,Z, d dl-m.Z.m/Z/ d dl0m1Z1m2Z2m3Z3m4Z4 d dl5Z5d dl6Z6d dl7Z7dZ8dZ9dZ:dZ;dZ<da=dZ>dZ?dZ@dZAdZBe@d ZCeAd ZDdZEdZFdZGdZHdZId ZJd!ZKd"ZLd#ZMd$ZNd%aOd&ZPd'ZQd(ZRd)ZSd*ZTd+ZUd,ZVd-ZWd.ZXd/ZYd0ZZd1Z[d2Z\d3Z]d4Z^d5Z_e@d6 Z`e@d7 Zad8Zbd9Zcd:d Zed;Zfejghe? d dl0Z0d dliZid d<ljmkZk d d=l0mlZl eFe0_FeGe0_Gt=e0_=d>d?gZmd<d@dAZndBdC Zod=dDdEZpdFdG ZqdHdI ZrdJdK ZsdLdM ZtdNdO ZudPdQ ZvdRZwd axd aydSdT ZzdUdVdWdXdYdZd[d\d]d^d_d`eUdadbdcdde^{dee^{dfgZ|dUZ}dgZ~dhZdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~ddddddddddddddddddddg*ZdgZdd Zdd Zdd Zd>ddZt=fddZdd Zdd Zdd ZdZdd Zd?ddZdd Zdd Zdd Zdd Zdd Zdd Zd@ddZdd ZdAddZi aeMfddZdd Zdd ZdBddĄZddƄ ZdCddʄZdd̄ Zdd΄ ZdDddЄZdd҄ ZddԄ ZdEddքZdd؄ Zddڄ Zdd܄ Zdejej fdd߄Zdd Zdd Zdd ZdZdadd Zdd ZdFddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zdd ZdGddZdd ZdHddZd	d
 Zdd Zdd Zdd ZdIddZÐdd ZĐdd ZŐdd ZƐdJddZeEfddZȐdd ZeEddfd d!ZʐdKd"d#Zːd$d% Z̐d&d' Zi aeCdddddddfd(d)Zϐd*d+ ZАd,d- Zѐd.d/ ZҐd0d1 ZӐd2d3d4e0jԐd5d6d7gZՐd8d9 Z֐dLd:d;Zedd<d=d>ZِdMd?d@ZڐdAdB ZG dCdD dDe܃ZݐdEdF ZސdGdH ZߐdNdIdJZde0jfdKdLZdOdMdNZdPdOdPZdQdR ZdSdT ZdUdV ZdWdX ZdYdZ Zd[d\ Zd]d^ Zg ai ad_d` ZdQdadbZdcdd ZdRdedfZdgdh Zdidj Zdkdl Zdmdn ZdSdodpZdqdr ZdTdsdtZdUdudvZdwdx Zdydz Zd{d| ZdVd}d~Zdd Zdd ZdWddZ dd Zdd Zdd ZdXddZdd Zdd Zdadd Zdd Z	dd Z
dd Zdd ZdYddZdZddZd[ddZd\ddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdad]ddZdd Zi adde0j  d de0j! d de0j  d ga"dd Z#d^ddZ$dÐdĄ Z%d_dŐdƄZ&d`dǐdȄZ'dadɐdʄZ(dːd̄ Z)dbd͐d΄Z*dϐdЄ Z+dcdѐd҄Z,dddӐdԄZ-da.dՐdք Z/dאd؄ Z0dedِdڄZ1dېZ2da3dܐd݄ Z4dސdߐdddZ5dd Z6dfddZ7dgddZ8dd Z9dd Z:dhddZ;diddZ<djddZ=dkddZ>dd Z?dd Z@dd ZAdd ZBdd ZCdd  ZDdd ZEdd ZFdlddZGdmddZHdnd	d
ZIdd ZJdd ZKi aLdd ZMdd ZNdd ZOdd ZPdd ZQdd ZRdoddZSdd ZTdd  ZUd!d" ZVd#d$ ZWd%d& ZXd'd( ZYd)d* ZZd+d, Z[d-d. Z\d/d0 Z]d1d2 Z^d3d4 Z_d5d6 Z`d7d8 Zaea  d9d: Zbecd;krܐe`  dS (p      )print_function)absolute_import)division)unicode_literals)standard_library)*)
native_strN)is_plesk	is_cpanel)ExternalProgramFailedcreate_symlinkis_socket_filemod_makedirs)ClPwdreload_processes
clconfpars	clcaptain)
unicodeifybyteify)
stripslashCageFSExceptionSYSTEMD_JOURNAL_SOCKETis_new_syslog_socket_usedz/usr/sbin/lvectlz/bin/umountz
/bin/mountz/bin/lve_umountz/var/cagefsz/usr/share/cagefs-skeletonz/cagefs-skeleton/z/usr/share/cagefsz/etc/cagefs/z/usr/share/cagefs/z/etc/cagefs/conf.d/z	cagefs.mpzcagefs.mp.prevz/usr/share/cagefs/.lockz/etc/cagefs/etc.safe/etc.systemz/etc/cagefs/etc.safe/etc.safez/etc/cagefs/etc.safez%/usr/share/cagefs/skeleton.files.listz$/usr/share/cagefs/skeleton.libs.listz/usr/share/cagefs/passwd.cachez/usr/share/cagefs/conf.dz/etc/cagefs/excludez/usr/share/cagefs/excludei  z/etc/cagefs/cagefs.min.uidz/var/lock/subsys/cagefsz"/etc/cagefs/etc.safe/disable.etcfsz/usr/bin/diffz/var/run/proxyexec/cagefs.sockz/var/lib/proxyexec/cagefs.sockz/etc/cagefs/black.listz2/usr/share/cagefs-plugins/install-cagefs-plugin.pyz/usr/share/cagefs/.cagefs.emptyz"/usr/share/cagefs/exclude.packagesz/etc/cagefs/proxy.commandsz/usr/share/cagefs/need.remountz/var/log/cagefs.logz/var/lve/lveinfo.verz/usr/share/l.v.e-manager/cl.{}z/etc/cagefs/dev.shm.optionszusers.disabledzusers.enabledZInitializedzNot initializeda  ImageMagick ImageMagick-c++ ImageMagick-c++-devel ImageMagick-devel ImageMagick-perl cloudlinux-ImageMagick cloudlinux-ImageMagick-c++ cloudlinux-ImageMagick-c++-devel cloudlinux-ImageMagick-devel expat expat-devel libtool-ltdl nss nss-softokn tcl compat-glibc-headers glibc-headers kernel-headers cpp compat-libgcc-296 gcc-gfortran compat-gcc-34-c++ compat-gcc-34-g77 libgcc gcc-c++ compat-gcc-34 gcc redhat-rpm-config automake autoconf m4 mc ghostscript fontconfig fontpackages-filesystem perl-Text-PDF pdf-tools perl-PDF-Reuse libedit aspell aspell-en hunspell hunspell-en cpanel-git git git-core pango mktemp coreutils scl-utils python3-virtualenv python36 libc-client-2007e unixODBC-libs mhash libxml2 tcp_wrappers compat-libstdc++ libmcrypt recode libxslt libtidy crypto-policies libicu libicu-devel tmpwatch net-snmp libgpg-error postgresql-libs libpng gmp pam bzip2-libs cracklib ncurses libidn libc-client-2004g db4 ncurses-libs openldap libXpm libgcrypt cyrus-sasl-lib unixODBC zlib openssl net-snmp-libs alt-libicu enchant libmm freetype freetype-devel curl curl-devel libssh2 GeoIP cyrus-sasl ffmpeg-libs termcap bind-utils libgs libgs-develz7.3.1-1.el7.cloudlinux)sigterm_check)is_ea4_enabledz/usr/local/cpanel/3rdparty/binz/var/lib/spamassassinc          
   C   s   | d krt  } yJtd}ttd}tjt| |dd |	  t| t
td W n2 tk
r } zt dtd| W d d }~X Y nX d S )N?   wb   )Zprotocoli  Zsaving-)secureioget_pwd_dictosumaskopenPASSWD_CACHEpickledumpr   closechmod	Exceptionprint_error)pwumask_savedpferr r/   /usr/share/cagefs/cagefsctl.pysave_passwd_cache   s    


r1   c           
   C   st   i } t jtrpy,ttd}ttj|t	 d} |
  W n2 tk
rn } ztdtd| W d d }~X Y nX | S )Nrb)encodingZloadingr   )r!   pathisfiler$   r#   r   r%   loadlocaleZgetpreferredencodingr'   r)   r   r*   )r+   r-   r.   r/   r/   r0   load_passwd_cache   s    
"r8   c          	   C   s|   | d krt  } |d krt }g }xL|D ]D}y|| | | krH|| W q( tk
rj   || w(Y q(X q(W t| |S )N)r8   r   r    appendKeyErrorr1   )Zpw_oldZpw_newusersuserr/   r/   r0   get_modified_users   s    

r=   c            	   C   s   t   tjtsXyttd W q ttfk
rT   t	dt t
d td Y qX nFyttd W n4 ttfk
r   t	dt t
d td Y nX d S )Ni  zError: failed to create    z$Error: failed to set permissions to )r   r!   r4   lexists	EMPTY_DIRr   IOErrorOSErrorr   loggingSILENTsysexitr(   r/   r/   r/   r0   create_empty_dir   s    rG   c             C   sp   t |  }tj|rlxVtddddt|gtdddt|gfD ]0}t|}|dkr8t	dtd| t
d	 q8W d S )
Nz-nz-onosuidz--bindzremount,ro,nosuid,bindr   zfailed to mountz->r>   )SKELETONr!   r4   isdirMOUNTr@   
subprocesscallr   r*   rE   rF   )r4   destcmdretr/   r/   r0   mount_empty_dir   s    (
rQ   c               C   s   t jtS )N)r!   r4   existsDISABLE_ETCFSr/   r/   r/   r0   etcfs_is_disabled   s    rT   c          	   C   s~   | t j }tj|rvyt|d}| }|  W n tt	fk
rL   dS X |
 }yt|S  tk
rr   dS X ndS d S )Nrr   )	cagefslibETC_VERSIONr!   r4   r5   r#   readliner'   rA   rB   rstripint
ValueError)r4   fpathfverr/   r/   r0   get_etc_version   s    

r_   c          	   C   s|   | t j }td}y$t|d}|d|  |  W n4 ttfk
rl   t	
d| td td Y nX t| d S )Nr   wz%d
zError: failed to write r>   )rV   rW   r!   r"   r#   writer'   rA   rB   r   rC   rD   rE   rF   )r4   r^   r\   r,   r]   r/   r/   r0   set_etc_version   s    


rb   c          
   C   sF   | t j }|t j }yt|| W n tttjfk
r@   Y nX d S )N)rV   rW   shutilZcopy2rB   rA   Error)srcdstZsrcpathZdstpathr/   r/   r0   copy_etc_version   s    

rg   z/var/log/cagefs-update.logc               C   s>   t jtr$ttd td nt jtr:t 	t d S )Nzis a directoryr>   )
r!   r4   rJ   LOGFILEr   r*   rE   rF   r5   remover/   r/   r/   r0   remove_log_file	  s
    rj   z/var/lib/mysqlz/var/lib/davz/var/www/cgi-binz/optz/var/www/php-binz/dev/shmz/var/www/htmlz/var/run/pgsqlz/var/passengerz/dev/ptsz/usr/local/apache/domlogsz/procz/var/spool/atz/var/run/dbusz/usr/local/cpanel/varz/var/run/nscdnodejspythonz/var/lib/mysql/mysql.sockz/usr/local/lswsz/libz/usr/libz/lib64z
/usr/lib64z/usr/includez/usr/share/localez/usr/share/terminfoz/usr/share/zoneinfoz/usr/share/vimz/usr/local/lib/perl5z/usr/local/lib/phpz/usr/local/cpanel/etcz/usr/local/cpanel/Cpanelz/usr/local/cpanel/3rdparty/perlz/usr/local/cpanel/3rdparty/libz /usr/local/cpanel/3rdparty/lib64z /usr/local/cpanel/3rdparty/sharez/usr/local/cpanel/3rdparty/phpz/usr/local/cpanel/installz/usr/local/cpanel/libz/usr/local/cpanel/htdocsz/usr/local/cpanel/sharedz/usr/local/cpanel/whostmgrz/usr/local/cpanel/sharez/usr/local/cpanel/phpz/usr/local/cpanel/libexecz/usr/local/cpanel/langz/usr/local/cpanel/cgi-privz/usr/local/cpanel/cpaddonsz/usr/local/cpanel/Whostmgrz/usr/local/cpanel/img-sysz!/usr/local/cpanel/modules-installz/usr/local/cpanel/localez/usr/local/cpanel/scriptsz/usr/local/cpanel/sbinz/usr/local/cpanel/basez/usr/local/cpanel/hooksz	/usr/javaz
/usr/saasez/usr/local/easyz/var/cpanel/ea4z/usr/share/manz/var/cpanel/userdatac               C   s   t jtS )zT
    Return True when /dev/shm isolation is enabled
    see CAG-954 for details
    )r!   r4   r5   DEV_SHM_OPTIONSr/   r/   r/   r0   is_dev_shm_isolatedJ  s    rn   c             C   s:   t | } x*tD ]"}|d dkr| |d rdS qW dS )Nr   /FT)rV   addslashMPDIRS
startswith)r4   tmpdirr/   r/   r0   is_outside_mp_pathR  s
    

rt   c            	   C   s>   yt tt ttd W n   tdtdt Y nX d S )Ni  copyingto)rc   Zcopyfile
ETC_MPFILEPREV_MPFILEr!   r(   r   r*   r/   r/   r/   r0   save_cagefs_mp_backupZ  s
    ry   Fc             C   s  | st jtrttd d S t d}ttd}|d xXtD ]P}t	 rV|dkrVqB|dkrft
 rfqB|d dkrBt j|rB|| |d	 qBW dd
lm}m}m} t j|rt j|r|d|  nt j|r|d|  n:t j|r|d|  nt j|r(|d|  t jttkrt jt}t j|}	|	dkrtdtd| td td td tdt |r|  t t td n6|	dkrt j|	rt|	r||	 |d	 t jtr|t |d	 |d |d |d |d |d |dtj d  |d |d |d x<tD ]4}|d dkrrt j|rr|d| d	  qrW |d x<tD ]4}|d dkrt j|r|d | d	  qW t rj|d	 dd!lm}
 x.tD ]&}t j|r|d| d	  qW t j|
r`|d|
 d	  |d	 |  t | t  td" t!  t"  t	 rdd#lm#} |  t jt$st%  d S )$NrR      r`   zN# Lines, which start with "/", specify mounts, that are common for all users:
z/var/www/cgi-binz/dev/shmr   ro   
)POSTGRES_CL7_FOLDERPOSTGRES_CONFDEFAULT_POSTGRES_FOLDERz%s
z/tmpz8Warning: MySQL socket is located in /tmp directory: pathz	points toz#This is not compatible with CageFS.zqPlease move socket outside of /tmp directory by changing socket= directive in /etc/my.cnf file and restart MySQL.z"Then execute cagefsctl --create-mpzDefault socket location -r>   zB# You can add personal (individual) mounts for users, like below.
z_# Please, start line with "@" symbol, and then specify path and permissions (comma separated).
z7# These directories will be virtualized for each user.
z@/var/spool/cron,700
z@/var/run/screen,777
@z,700
z!@/var/cache/php-eaccelerator,777
z@/var/php/apm/db,777
zl# Please add exclamation sign at the beginning of the line if you want to mount path read-only, like below.
!zi# Please add "%" sign at the beginning of the line if you want to "split" mount by username, like below.
%)BOX_TRAPPER_DIRi  )add_php_session_dir_plesk)&r!   r4   r5   rw   printr"   r#   ra   rq   r	   rn   rJ   cagefsreconfigurer|   r}   r~   realpath
MYSQL_SOCKdirnamer'   unlinkrE   rF   rt   	LITESPEEDrV   VAR_RUN_CAGEFSREAD_ONLY_MOUNTSSPLITTED_MOUNTSr
   r   SPAMASSASSIN_DIRS_FOR_CAGEFSr(   add_mounts_for_php_selectoradd_mounts_for_ea_php_sessionsr   rx   ry   )forceexit_on_errorr,   r]   rs   r|   r}   r~   ZrpathZrdirr   liner   r/   r/   r0   	create_mpb  s    








"


















r   c          
   C   sN   xH|D ]@}|| kr|  }yt||  W q ttfk
rD   Y qX qW d S )N)rY   r!   
removedirsrB   rA   )mounts
old_mounts	base_pathmountr/   r/   r0   remove_mount_points  s    
r   c              C   s   t jtrg } g }ttdd| |d}|rg }g }t||d}t|| t||  t|| tj }xL|D ]D}|| }t	
|j}	|	d }
t|j|j t|| |
 t  qlW t  d S )NT)mpfileskip_errorsskip_cpanel_checkpersonal_mountssplitted_mounts)r   r   z/.cagefs)r!   r4   r5   rx   read_mpfiler   r   clpwdget_user_dictrV   r   pw_dirset_user_permpw_uidpw_gidset_root_permry   )Zold_personal_mountsZold_splitted_mountsr   r   r   r   r+   r<   r   homepathZ
cagefspathr/   r/   r0   remove_unused_mount_points  s*    





r   c             C   s(   | d dkr| d } || d t | kS )Nro   )len)Ztestdirjailr/   r/   r0   	dirinjail  s    r   c             C   s   | t j kS )N)r   r   r   )r<   r/   r/   r0   user_exists  s    r   z.savec               C   s:   t jtr"t jtrdS dS nt jtr2dS dS d S )Nrd   z
Enable AllzDisable AllzNot Initialized)r!   r4   rJ   disabled_direnabled_dirr/   r/   r/   r0   get_user_mode  s    r   c             C   s   | d krt  } | dkr^|rttdtdtddtjd ddtd	d
tjd ddt td nn| dkr|rntt	j
td rtddtjd ddtdtjd ddt ntdtjd  d  td d S )Nrd   zboth directoriesandzexist.
z+Please, run one of the following commands:
r   z--enable-all
z(to enable all users, except specified inr{   zor
z--disable-all
z)to disable all users, except specified inr>   zNot Initializedz/binz mode has not been selected yet.
z
or
z CageFS is not initialized. Use "z --init" to initialize CageFS)r   r   r   r*   r   r   rE   argvrF   r!   r4   rJ   rI   )moderaise_exceptionr/   r/   r0   check_mode_error  s4    




r   c               C   s   t jtpt jtS )N)r!   r4   rJ   r   r   r/   r/   r/   r0   cagefs_is_enabled0  s    r   c               C   s    t jtt pt jtt S )N)r!   r4   rJ   r   save_postfixr   r/   r/   r/   r0   save_dir_exists4  s    r   c          
   C   sv   t j| rrt j| t r0td| t   nByt | | t  W n, ttfk
rp   t	d| d| t  Y nX d S )Nz#Error : directory %s already existszfailed to renamerv   )
r!   r4   rJ   r   r   rC   renamerB   rA   r*   )_dirr/   r/   r0   save_dir8  s    r   c          	   C   sr   t j| t rnt j| r,td|   nByt | t |  W n, ttfk
rl   t	d| t d|  Y nX d S )Nz#Error : directory %s already existszfailed to renamerv   )
r!   r4   rJ   r   r   rC   r   rB   rA   r*   )r   r/   r/   r0   restore_dirD  s    r   c               C   s:   t  std d S t  tt tt t  s6td d S )NzCageFS is disabledzCageFS has been disabled)r   r   r   r   r   r   r/   r/   r/   r0   disable_cagefsP  s    r   c               C   s:   t  rtd d S tt tt t  t  r6td d S )NzCageFS is enabledzCageFS has been enabled)r   r   r   r   r   r   r/   r/   r/   r0   enable_cagefs[  s    r   c             C   s^   t  rZt r8| rttddt d t  td n"| r@tt	d t	d td d S )Nz4CageFS is enabled, but "saved" lists of users exist
zPlease, remove r   r>   zCageFS is disabled.z9Please, run "cagefsctl --enable-cagefs" to enable CageFS.)
r   r   r   r   r*   	INIPREFIXr   rE   rF   r   )r   r/   r/   r0   check_save_dirf  s    r   c              C   s   t   t } td|  d S )NzMode:)r   r   r   )r   r/   r/   r0   print_user_modex  s    r   Tc          
   C   s   t   yttd W n tttjfk
r2   Y nX yttd W n tttjfk
r`   Y nX | ryttd W q tk
r   Y qX n$yttd W n tk
r   Y nX t	  t
  d S )NFi  )r   rc   rmtreer   rB   rA   rd   r   r   check_excluder   )Z
enable_allr/   r/   r0   set_user_mode~  s(    r   c          	   C   s   | t krt |  S g }tj| rxt| D ]}tj| |}tj|r,|dkr,yDt|d}x,| D ] }|	 }|dkr~qh|
| qhW |  W q, tk
r   td| Y q,X q,W |t | < |S )Nz	.htaccessrU    Zreading)exclude_user_list_cacher!   r4   rJ   listdirjoinr5   r#   	readlinesrY   r9   r'   rA   r   r*   )Zexclude_path	user_listZexclude_file_pathr4   r]   r   r/   r/   r0   get_exclude_user_list  s&    
r   c             C   s   t t| tt  S )N)listsetr   )r   r/   r/   r0   filter_users  s    r   c             C   sX   d}yt j| }W n. tjk
rB   t d|   td Y nX || }d| }|S )Nd   zuser %s not foundr>   z%02d)r   r   get_uidr   NoSuchUserExceptionr*   rE   rF   )usernamebaseuidbprefixr/   r/   r0   get_user_prefix  s    r   c          	   C   s  |d krt |}d| d | }|ryt| |  W n ttfk
rN   Y nX t| d |  yt| d |  W n ttfk
r   Y nX nryt| d | d W n ttfk
r   Y nX y&t| | d	  t
| | d W n ttfk
r   Y nX d S )Nro   i  r`   i  )r   r!   ri   rA   rB   remove_htaccessrmdirr   r#   r'   r(   )r   r   enabler   Zfnamer/   r/   r0   toggle_file  s,    r   c             C   s   t   t }t| ytj| }W n$ tjk
rH   td| d d S X |j	t
k rhtd| dt
 d S tj|j	}|dkrx>|D ]}tt|| qW n$|dkrx|D ]}tt||  qW d S )Nr<   zdoes not existzshould have UID >=z
Enable AllzDisable All)r   r   r   r   r   get_pw_by_namer   r   r*   r   MIN_UID	get_namesr   r   r   )r   r   r   r+   Zusername_listZtmp_usernamer/   r/   r0   toggle_user  s$    


r      r;   c             C   s   t | }|dkr||   t|| d}x6t|| D ]&}td| || |d |   q4W td| |d | d   d S )Nr   r   	r>   )r   sortr   ranger   )r;   Zusers_per_linemessageusers_countnamer/   r/   r0   print_users  s    
&r   c             C   sx   g }t j }xdt| D ]V}tjtj| |rx:ttj| |D ]"}||krJ|t|krJ|	| qJW qW |S )N)
r   r   r   r!   r   r4   rJ   r   r   r9   )r   r;   r+   subdir_filer/   r/   r0   !get_list_of_users_from_config_dir  s    
r   c             C   s&   t tj }t t| }t|| S )N)r   r   r   r   r   r   )r   r;   Z	exc_usersr/   r/   r0   get_list_of_users_from_passwd  s    r   c             C   sV   t | t }t|| |dkr6| r,ttS ttS n|dkrR| rJttS ttS d S )Nz
Enable AllzDisable All)r   r   r   r   r   r   r   )enabledr   r   r/   r/   r0   get_list_of_users  s    

r   c               C   s   t  rtdS g S )NT)r   r   r/   r/   r/   r0   get_enabled_users.  s    r   c             C   s~   t   t }t| |dkrH| r2tttdd qzttttdd n2|dkrz| rftttdd nttttdd d S )Nz
Enable Allr>   zenabled user(s)zdisabled user(s)zDisable All)	r   r   r   r   r   r   r   r   r   )r   r   r/   r/   r0   
list_users6  s    r   c       
   
   C   sL  t  r4t r0tddt d t  td nd S t }| d krHt	 } tj
 }x>| D ]6}||krX|dkrztt|d qX|dkrXtt|d qXW t	t}xF|D ]>}|| kr||kr|dkrtt|d q|dkrtt|d qW tjtrHtjts$yttd	 W n tk
r"   Y nX d }zyxrttD ]d}tjt|}tjt|}tj|r:tj|s:yt| W n tk
r   Y nX q:W tjtd
}xNttD ]@}tj||}	ttjt||	 t|	tjt| qW W n. tttj fk
r.   tdtdt Y nX W d |rFt!|d X d S )Nz4CageFS is enabled, but "saved" lists of users exist
zPlease, remove r   r>   z
Enable AllFzDisable AllTi  )dirru   rv   )"r   r   r   r*   r   r   rE   rF   r   r   r   r   r   r   r   EXCLUDE_SAVE_PATHr!   r4   rJ   EXCLUDE_PATHr   rB   r   r   r5   r   tempfileZmkdtemprc   copyr   rA   rd   r   )
ex_listr   r+   r   Zold_ex_listZtmp_dirr]   r4   	orig_pathtmp_pathr/   r/   r0   r   F  s`    


 r   c              C   s  d} t j }tj| rxjt| D ]Z}tjtj| |r*xttj| |D ]}tj| ||}tj|s|	dstj
|ryt| W n ttfk
r   Y nX q^tj
|r |d td  }||ks|t|krNyt| W n ttfk
r   Y nX q^tj|r^||ksB|t|kr^t|d q^W yttj| | W q* ttfk
r   Y q*X q*W d S )Nz/var/cagefsz.lockT)r   r   r   r!   r4   rJ   r   r   islinkendswithr5   ri   rB   rA   r   r   rc   r   r   )bdirpw_dbr   r   r4   r/   r/   r0   clean_var_cagefs  s4    
"r   c             C   s   t  }tj }xpt| D ]b}tjtj| |rxFttj| |D ].}||krL||ksl|t	|krLt
| |d| qLW qW d S )NT)r   r   r   r   r!   r   r4   rJ   r   r   r   )r   r   r   r   r   r/   r/   r0   clean_config_dir  s    
r   c               C   s,   t jtrtt t jtr(tt d S )N)r!   r4   rJ   r   r   r   r/   r/   r/   r0   clean_config_dirs  s    r      c                s   d  fddt| D S )Nr   c             3   s   | ]}t  V  qd S )N)randomZchoice).0_)charsr/   r0   	<genexpr>  s    zid_generator.<locals>.<genexpr>)r   r   )sizer  r/   )r  r0   id_generator  s    r  c          	   C   s  | d t   }yt| | W n2 ttfk
rP   td| d| td Y nX yt	| d W n. ttfk
r   td|  td Y nX tj
 }xZt|D ]L}tjtj||rx0ttj||D ]}||krt| |d qW qW t|d d S )	N.zfailed to renamerv   r>   i  zfailed to createFT)r  r!   r   rB   rA   r   r*   rE   rF   r   r   r   r   r4   rJ   r   r   rc   r   )r   Ztemp_dirr   r   r   r/   r/   r0   migrate_config_dir  s$    
r	  c              C   s   t j } xtttt tt gD ]p}tj|r x^t	|D ]P}tjtj
||r<x4t	tj
||D ]}|| krl|t|krldS qlW q<W q W dS )NFT)r   r   r   r   r   r   r!   r4   rJ   r   r   r   )r   r   r   r   r/   r/   r0   new_prefixes_are_used  s    
r
  c               C   sj   t  sftjtrtt tjtr.tt tjtt rJttt  tjtt rfttt  d S )N)r
  r!   r4   rJ   r   r	  r   r   r/   r/   r/   r0   migrate_to_new_prefixes  s    r  z!/etc/cagefs/cagefs.base.home.dirsc               C   s6   t jtr2td krttatd  dkr2dS dS )Nr   zmount_basedir=1TF)r!   r4   r5   BASEDIRS_FILEbasedirsrV   	read_filerY   r/   r/   r/   r0   mount_base_dir_enabled  s    
r  c             C   sH   xBt D ]:}| }|dks|dkr$qt|| }|d kr| S qW dS )Nzmount_basedir=1zmount_basedir=0r   )r  rY   researchgroup)r   Zreg_expmr/   r/   r0   get_base_dir  s    
r  c             C   s  t  }tj }t }tjtrƐxt	tD ]}tjtj
t|r2xpt	tj
t|D ]V}y|| }W n tk
r   wfY nX |rt|j}|dkrqftj
t||| }ntj
t|||j }tj|rf| r0yt|d W n6 tk
r, }	 ztd|dt|	 W dd}	~	X Y nX qft| yt| W n: tk
r   x t|jD ]}
||
 qfW wfY nX y$td}t|d t| W qf tk
r   Y qfX qfW q2W t|S )z
    Returns list of users which are currently mounted
    :param fix_permissions: when True == fix permissions of directories (mount points) for users' home directories inside /var/cagefs
    :type fix_permissions: bool
    r   i  z-Error: failed to set permissions to directory:Nr   )r  r   r   r   r   r!   r4   rJ   BASEDIRr   r   r:   r  r   r(   rB   r   strr   r   rV   Zget_all_users_with_uidr   addr"   mkdirr   )fix_permissionsZbase_dir_flagr   resr   r<   r+   Zbase_dirZmount_point_patheZuser2r,   r/   r/   r0   get_mounted_users  sJ    

&
r  c        
   	   C   s0  y"t jddgt jdd d } W n, tk
rN   tddd td Y nX t	
d	t	j}g }x| d
D ]}| }t|dkrnd|dd  }||rny"t|d }|tj| W qn tk
r   ||d  Y qn tjk
r   td| Y qnX qnW t|}tt }||@ }	t|	S )Nz/bin/psZauxT)stdouttextr   zfailed to runZpsr>   zsshd:[a-z_][a-z0-9_-]*[$]?@ptsr{   r   
   zCan`t get user name for UID )rL   PopenPIPEcommunicaterB   r   r*   rE   rF   r  compile
IGNORECASEsplitr   r   matchrZ   extendr   r   r[   r9   r   r   r   r  r   )
ZplpatternZlstir   commandr   Zsshd_setZmounted_setZ
result_setr/   r/   r0   get_logged_in_usersC  s0    "

r,  c              C   sP   t dd } | d g }x.| D ]&}t| d }|dkr"|| q"W |S )Nz/proc/lve/listrU   r   )r#   r   poprZ   r&  r9   )linesZlve_listr   Zlveidr/   r/   r0   get_lve_listd  s    

r/  c          
   C   s   |    |   d}x| D ]}t|dkr|d dkr| }y4tjtd|gtjtjd}|  |j	dkrpd}W q t
k
r   tdtd| d}Y qX qW |S )NFr   ro   z-l)r  stderrTzfailed to run)r   reverser   rY   rL   r!  UMOUNTr"  r#  
returncoderB   r   r*   )_listerrorr   pr/   r/   r0   umount_listp  s     

r7  c          
   C   sb   y4t tdt|  g}|dkr2tdt|   dS W n( tk
r\   tdtdt|   dS X dS )Nz-lr   zfailed to unmountTzfailed to runF)rL   rM   r2  rI   r   r*   rB   )r4   rP   r/   r/   r0   
umount_dir  s    r8  c           	   C   s   d} xvt | D ]j}d}y:tjtdddgtjtjd}|  |jdkrLd}nP W q tk
rv   t	d	td
 d}Y qX qW |rt	td |S )zD
    Run lvectl apply all
    Returns True if error has occured
       FZapplyallz--force)r  r0  r   Tzfailed to runz	apply allzapply all failed)
r   rL   r!  LVECTLr"  r#  r3  rB   r   r*   )ATTEMPTSr  r5  r6  r/   r/   r0   	apply_all  s     
r=  c           	   C   s   d} xvt | D ]j}d}y:tjtdddgtjtjd}|  |jdkrLd}nP W q tk
rv   t	d	td
 d}Y qX qW |rt	td |S )z@
    Destroy all LVEs
    Returns True if error has occured
    r9  FZdestroyr:  z--force)r  r0  r   Tzfailed to runzdestroy allzdestroy all failed)
r   rL   r!  r;  r"  r#  r3  rB   r   r*   )r<  r  r5  r6  r/   r/   r0   destroy_all  s     
r>  c             C   s~   d}d}x| D ]}|t | d }qW y,tjtdgtjtjtjdd}|| W n& tk
rx   tdtd d}Y nX |S )z
    Run lvectl destroy for specified uids
    :param uids: list of integers (UIDs)
    :type uids: iterable
    Returns True if error has occured
    Fr   r{   zdestroy-manyT)stdinr  r0  r  zfailed to run)	r  rL   r!  r;  r"  r#  rB   r   r*   )uidsr5  sr   r6  r/   r/   r0   destroy_lve  s    


rB  c             C   s~   d}d}x| D ]}|t | d }qW y,tjtdgtjtjtjdd}|| W n& tk
rx   tdtd d}Y nX |S )z
    Run lvectl apply for specified uids
    :param uids: list of integers (UIDs)
    :type uids: iterable
    Returns True if error has occured
    Fr   r{   z
apply-manyT)r?  r  r0  r  zfailed to run)	r  rL   r!  r;  r"  r#  rB   r   r*   )r@  r5  rA  r   r6  r/   r/   r0   	apply_lve  s    


rC  c          	   C   sL   t j }g }x8| D ]0}y||| j W q tk
rB   wY qX qW |S )N)r   r   r   r9   r   r:   )r;   r   r@  r<   r/   r/   r0   get_uids  s    

rD  c             C   s(   g }x| D ]}||kr
| | q
W |S )N)r9   )r4  r  r*  r/   r/   r0   remove_duplicates  s
    
rE  c             C   s:   d}t | }t|}t|r d}td t|r6d}|S )z
    Remount list of users. Skeleton should be mounted/unmounted before call of this function
    Returns True if error has occured
    :param users: list of usernames
    :type users: iterable
    FTr>   )rD  rE  rB  timesleeprC  )r;   r5  r@  r/   r/   r0   remount  s    
rH  c             C   sB   d}| r t d}t|rd}|S t r*d}td t r>d}|S )NFTr>   )r   rH  r>  rF  rG  r=  )enabled_users_onlyr5  enabled_usersr/   r/   r0   remount_all6  s    
rK  c             C   s&   x | D ]}t jt| sdS qW dS )NFT)r!   r4   rR   rI   )r4  r   r/   r/   r0   files_existM  s    
rL  c             C   sX   | d krt } tdd}x4| }|dkr*P || d dkr|  dS qW |  dS )Nz/proc/mountsrU   r   ro   r   TF)rI   r#   rX   findr'   )Zskeletonr   r   r/   r/   r0   skeleton_is_mountedU  s    
rN  c               C   s    t  rtdgS tddgS d S )Nz/var/log/messagesz/etc/passwd)rT   rL  r/   r/   r/   r0   cagefs_fuse_is_mountedd  s    
rO  c          	   C   s   d}xt |D ]}d}y4tjdd| gtjtjd}|  |jdkrHd}W n* tk
rt   td|  d	  d}Y nX | d
krt	 rd}P qd} d}q| dkrt	 rd}P qd}q| dkrt	 sd}P qd}qP qW |rtdd| d	  |S )Nr9  Fz/sbin/servicezcagefs-fuse)r  r0  r   Tz#failed to run "service cagefs-fuse "startrestartstop	executingz"service cagefs-fuse)
r   rL   r!  r"  r#  r3  rB   r   r*   rO  )r+  r<  r  r5  r6  r/   r/   r0   cagefs_fusem  s@    

rU  c               C   s   t jt jtdS )NZsocket)r!   r4   r?   r   PROXYEXEC_SOCKET_DIRr/   r/   r/   r0   proxyexecd_is_socket  s    rW  c             C   s   d}ytt jdd| gt jt jd}|  |jdkr6d}| dksF| dkrvt jddd	gt jt jd}|  |jdkrvd}W n* tk
r   td
|  d  d}Y nX |rtdd| d  |S )NFz/sbin/serviceZ
proxyexecd)r  r0  r   TrQ  rR  statusz"failed to run "service proxyexecd rP  rT  z"service proxyexecd)	rL   r!  r"  ZSTDOUTr#  r3  rB   r   r*   )r+  r5  r6  r/   r/   r0   cagefs_proxyexecd  s&    


rY    c          
   C   s   t d}x| D ]|}t jt| rPyt t|  W n ttfk
rN   Y nX t jt| syt	t| | W q ttfk
r   Y qX qW t | d S )Nr   )
r!   r"   r4   r   rI   r   rA   rB   rJ   r   )r4  r   r,   r4   r/   r/   r0   create_mount_points  s    


r[  c              C   sV   t jts4ts*tdtddtjd d t	d t
t} t| rRt
t|  d S )Nfilez
not found
zPlease, run
r   z--create-mpr>   )r!   r4   r5   rw   rD   r   r*   rE   r   rF   rV   r  add_new_line
write_file)Zmp_filer/   r/   r0   check_mp_file  s    

r_  c            	   C   s,   yt t W n ttfk
r&   Y nX d S )N)r!   ri   SERVICE_CAGEFS_LOCKrA   rB   r/   r/   r/   r0   remove_service_lockfile  s    ra  c            	   C   s0   yt td  W n ttfk
r*   Y nX d S )Nr`   )r#   r`  r'   rA   rB   r/   r/   r/   r0   create_service_lockfile  s    rb  c                s    fdd}|st   | }| r&t  tjdr|rP|rtd | pL|}nD|rt  td x.t	d
 D ]}|rrtd| d d	  qrW |S )
Nc                 s@   d} x,t dD ] }t }|s&d} P t| qW ttg | S )NTr   F)r   rV   get_mounted_dirsr7  rI   )r5  r  r   )all_cagefs_mountsr/   r0   unmount  s    

z umount_skeleton.<locals>.unmountz/usr/bin/systemctlz/bin/umount -l /usr &>/dev/nullr>   z/bin/ps --no-headers -xao pidz/usr/bin/nsenter -m -t z8 /bin/bash -c 'if /bin/grep -q cagefs /proc/mounts; thenz6 /usr/sbin/cagefsctl --unmount-cur-ns; fi' &>/dev/null)ra  lvectl_startr!   r4   r5   systemr>  rF  rG  Executer&  )save_mountsrd  current_namespace_onlyall_namespacesre  r5  pidr/   )rd  r0   umount_skeleton  s(    


rm  c          	   C   s   yt | t j W n$ ttfk
r6   td| Y nX y|   W n ttfk
r\   Y nX yt	| W n ttfk
r   Y nX d S )Nzfailed to unlock)
fcntllockfZLOCK_UNrA   rB   r   r*   r'   r!   r   )lockfilelocknamer/   r/   r0   unlock  s    rr  c             C   s   t | }| S )N)r!   popenread)r+  Zhandler/   r/   r0   rh    s    
rh  c          	   C   s   yLt | d}|rtd |s0t|tjtjB  t|tj |rJtd |S  ttfk
r   |s|stt	d
ddkrtd ntd|  td Y nX d S )	Nr`   z!Acquiring lock... Please wait... zLock acquiredzps aux | grep cagefsctlr{   r>   z5cagefsctl is already running. please try again later.zfailed to acquire lock file)r#   r   rn  ro  ZLOCK_EXZLOCK_NBrA   rB   r   rh  r&  r   r*   rE   rF   )rq  waitquietrp  r/   r/   r0   acquire_lock  s     
rw  c          
   C   s
  t | dkr| d dkr|  } tj| sRttd| d |rHd S t	d t
| g ttdddd	| t|  g}|r|dkrttddd
| t|  g}nF|dkr| dkrttddd| t|  g}nttddd| t|  g}|dkrtd|  t	d d S )Nr   ro   zfile contains incorrect path -z$is NOT a directory or does NOT existr>   z-nz-orH   z--rbindzremount,ro,nosuid,bindz/dev/shmz remount,nosuid,noexec,nodev,bindzremount,nosuid,bindzfailed to mount)r   rY   r!   r4   rJ   r   r*   rw   rE   rF   r[  rL   rM   rK   rI   )r   	read_onlyignore_errorsrP   r/   r/   r0   	mount_dir-  s&    


rz  c               C   s.   t dtd t dtd t dtd d S )NzaPlease ensure that the following option in cPanel/WHM is set to blank value (not default "home"):r>   zdWHM -> Server Configuration -> Basic cPanel/WHM Setup -> Basic Config -> Additional home directorieszZWhen this option is set to "home", cPanel can create home directories in incorrect places.)r   rC   rD   r/   r/   r/   r0   print_cpanel_home_warningF  s    r{  c             C   s8   |  dr| dkr4|rdS td|d| td dS )Nro   TzInvalid mount pointzin filer>   F)rr   r   r*   rE   rF   )r4   r   r   r   r/   r/   r0   check_mpfile_lineM  s    
r|  c          	   C   s^  |d krg }|d krg }|d kr$g }|s| t kr|t |  d  |t |  d  |t |  d  |r~t |  d |||fS t |  d S g }ynt| d}	xT|	D ]J}
|
drq|
 }
|
dks|
dd	ks|
d
r|rqtd|
d|  t	
d |
dr^|
d}|d	kr,|
d| }n|
dd  }| }t||
| |rRq|| q|
dr|
dd  }t||
| |rq|| q|
dr|
dd  }t||
| |rq|| ||d  q|
dr||
d  qW |	  W nL ttfk
rJ   |r0|r,g g g g fS g S td|  t	
d Y nX |st rxT|D ]L}
|
 }
|
dd	kr`t r`td|  d |
 d td t  P q`W td |kr|td  td |kr|td  g t | < t |  |d d   t |  |d d   t |  |d d   t |  |d d   |rZ||||fS |S )Nr>   r   r9  r   rU   #ro   z/../r   z/..zInvalid mount pointzin filer   ,r   r   r{   zfailed to readhomezWarning: file z contains line "rP  )mpfile_cacher(  r#   rr   rY   rM  r   r   r*   rE   rF   rfindr|  r9   r'   rA   rB   r
   invalid_homes_existrC   rD   r{  PROXYEXEC_SOCKET_DIR_OLDri   rV  )r   r   r   r   read_only_mountsr   ignore_cacheZreturn_all_mountsr   Zmp_file_objr   posr4   r/   r/   r0   r   Y  s    

 





r   c               C   s   t td  d S )Nz start > /dev/null 2>&1)rh  r;  r/   r/   r/   r0   rf    s    rf  c             C   sB   |  drdS t| } x$|D ]}t|}|  |rdS qW dS )z
    Return True when path is included in one of the read-only paths
    :param path: mount path to check
    :type path: string
    :param read_only_mounts: list of read-only mounts from cagefs.mp file
    :type read_only_mounts: list
    z/opt/cpanel/ea-phpTF)rr   rV   rp   )r4   r  r   r/   r/   r0   mount_should_be_readonly  s    




r  c              C   sj   t jdd} ttdd | } | r&dS g }t|d t jdd}x$|D ]}t |}t||rFdS qFW dS )z
    Search CageFS for mounts that do not have 'nosuid' option
    Also search for read-write mounts that should be read-only
    Return True when found, False otherwise
    For details see CAG-526, CAG-634
    T)without_nosuidc             S   s   d| kS )Nz/proc/sys/fs/binfmt_miscr/   )xr/   r/   r0   <lambda>      z%unsafe_mounts_exist.<locals>.<lambda>)r  )rw_mounts_onlyF)rV   rc  r   filterr   
strip_pathr  )Zno_suid_dirsr  	rw_mountsr   r4   r/   r/   r0   unsafe_mounts_exist  s    



r  c             C   s   d	dd}|t t  ttjdd}x*|D ]"}t|}|||t|| d q*W ttjdd| }x.|D ]&}t|}t|| rj|||dd qjW dS )
z
    Remount all CageFS "unsafe" mounts, so that they become "safe".
    Make all mounts "nosuid", and make some mounts "read-only" (when needed)
    For details see CAG-526, CAG-634
    Fc             S   sR   |r t tdddd|  |g}nt tdddd|  |g}|dkrNtd|  d S )Nz-nz-ozremount,ro,nosuid,bindz(/usr/share/cagefs/not-existing-directoryzremount,nosuid,bindr   zfailed to mount)rL   rM   rK   r   r*   )oldnewrx  rP   r/   r/   r0   remount_dir  s
    z*remount_unsafe_mounts.<locals>.remount_dirT)r  )rx  )r  N)F)rI   r   rV   rc  r  r  )r  r  Z	wo_nosuidZpath_newZpath_oldr  r/   r/   r0   remount_unsafe_mounts  s    






r  z/etcz/var/logz/var/run/screenz/var/spool/cronz/var/cache/php-eacceleratorz/var/.cagefsc             C   s$   y
t | S  tk
r   Y nX dS )zs
    Return value of symlink or None when error occurs
    :param path: path to symlink
    :type path: string
    N)r!   readlinkrB   )r4   r/   r/   r0   read_symlink  s
    
r  c       	   
   C   s  t j| st| sdS t j| } t|  }t j| }| d }t j||}tj	|ddd t j
|rxt j| |st| yt | | W nf tk
r } zHt j|rt j| |std| d |  d t| td	 dS W dd}~X Y nX tj	t| dddd
 t|}||krt| yt || W n` tk
r } z@t|}||krtd| d | d t| td	 dS W dd}~X Y nX |rt|| dS )a7  
    Mount one separate file to CageFS using hardlink & mount
    :param path: path to file
    :type path: string
    :param do_mount: when True mount directory with hardlink to CageFS
    :type do_mount: bool
    :param read_only: when True mount read-only, read-write otherwise
    :type read_only: bool
    Nz.cagefsi  F)allow_symlinkz!Error: failed to create hardlink z to z : r>   )r  update_permz Error: failed to create symlink )r!   r4   r5   r   r   rI   basenamer   rV   make_dirr?   samefiler   linkrB   r   rC   r  rD   r  symlinkrz  )	r4   do_mountrx  Z	skel_pathfilenamedir_pathZhardlink_pathr  spathr/   r/   r0   
mount_file  s:    

&


&r  )r  returnc             C   sZ   t  s
dS tt| d tjtd}tj|sBtj	|dddd t
ttj|d dS )z|
    Mount socket of systemd-journal into CageFS
    :param do_mount: when True mount directory with hardlink to CageFS
    N)r  Zdevi  F)r4   Zpermr  r  log)r   r  r   r!   r4   r   rI   rR   rV   r  r   )r  Zskeleton_dev_dirr/   r/   r0   _mount_systemd_journal_socketB  s"    r  c          
   C   s  t   td tt | s t s2tdr2td tdg tdd t	
tddd	d
ttg}|dkrrtdt g }g }t||dt_t| td}xFttjD ]8}| }|dkr|dkr|dst|||kdd qW yhd}x^t|D ]P}tj||}tj|rt|d"}	x|	D ]}
t|
  q$W W dQ R X qW W n0 tk
rz } ztd| W dd}~X Y nX tdd t t!ddd t"dd td t#| tt t| t| t$  | rt%  t&dd t'  t(  t)  dS )z
    Function remounts skeleton and all users
    !!WARNING!!: part of this logic is duplicated in jail.c from kmoc-lve project
    :param remount_users: when True, destroy&create LVE&namespaces for all users
    :type remount_users: bool
    z,/bin/mount --make-rprivate / >/dev/null 2>&1rR  r>   z/tmpF)ri  z-nz-orH   z--rbindr   zfailed to mount)r   r  z/procz/tmp/T)rx  ry  z/etc/cagefs/empty.dirsrU   NzError while reading file.)r  )r  rx  )rI  )*r_  rh  r[  MOUNT_POINTSrW  rY  rE   rF   rm  rL   rM   rK   rI   r   r*   r   rV   r   r!   r"   sortedrY   rr   rz  r   r4   r   r5   r#   rQ   rA   setup_cpanel_multiphpr  LICENSE_TIMESTAMP_FILEr  r  rf  r   rK  r   remove_remount_flagrb  )remount_usersrP   r  r   r,   r   Zemptied_dirs_pathr  Zemptied_configZemptied_dirs_fileZemptied_dirr  r/   r/   r0   mount_skeletonf  sZ    





$



r  c             C   sl   xf| D ]^}t j|}|d }|td rtd|d t|}||krZtd|d t	
d qW d S )Nro   r4   zis incorrectz(it refers to)r>   )r!   r4   r   rr   rI   r   r*   rV   r   rE   rF   )pathsr4   path2r/   r/   r0   verify_paths  s    

r  c               @   s>   e Zd Zdd ZdddZdd Zdd	 Zd
d Zdd ZdS )cagefs_initc             C   s"   g | _ g | _g | _g | _g | _d S )N)didfilesdidsections
diddevicesdidusers	didgroups)selfr/   r/   r0   __init__  s
    zcagefs_init.__init__r   c             C   sB   |r>t | tj|||d |d d|d d|| j|d d
| _d S )Nr   verboser>   hardlinkupdate)Z
check_libsZtry_hardlinkZretain_ownerZtry_glob_matchingZhandledfilesr  )r  rV   Zcopy_binaries_and_libsr  )r  configchrootr  try_globr/   r/   r0   update_paths  s    zcagefs_init.update_pathsc             C   s   t  }| ||| d S )N)rV   Zget_alt_php_libsr  )r  r  r  r  r/   r/   r0   update_alt_php_libs  s    zcagefs_init.update_alt_php_libsc          	   C   s  |d dkr|d d }t j|sFtd|  t|d t |d t||d}x8|D ]0}t  || j	krZ| 
|||| | j	| qZW t||d}|dkry|d W n tk
r   Y nX |t||d	 }|t||d
 }|t||d }|t||d }| j|||dd t||d}| j|||dd t||d}	x(|	D ] }
tj||
|d dddd qVW g }g }t||d}x$|D ]}|| jkr|| qW t||d}x$|D ]}|| jkr|| qW tt|||d  tt|||d  ttjd |||d  ttjd ||d  | j| | _| j| | _t||d}xZ|D ]R}|| jkrptj|t j||d dddd t|||d  | j| qpW d S )Nr   ro   zCreating jail i  includesectionsr  Zdirectadminz/usr/local/awstats/	librariesexecutablesregularfilesdirectoriesr>   )r  paths_w_owner	emptydirsr  r   )copy_permissionsZ
allow_suidcopy_ownershipr;   groupsz/etcdevices)r!   r4   rR   r   r   r(   rV   config_get_option_as_listr   r  handle_cfg_sectionr9   ri   r[   r  create_parent_pathr  init_passwd_and_groupFUSE_DIRZinit_safe_users_and_groupsETC_TEMPLATE_NEW_DIRinit_shadowr  r  r   Zcopy_device)r  r  r  cfgsectionsectionstmpr  r  r  Zedirr;   r  tmplistr  r/   r/   r0   r    sd    



 


"zcagefs_init.handle_cfg_sectionc             C   s   |rt | t| d S )N)r  rV   Zcopy_to_etc)r  r  r/   r/   r0   update_etc_paths'  s    zcagefs_init.update_etc_pathsc             C   sr  t ||d}x0|D ](}|| jkr| ||| | j| qW t ||d}|t ||d }|t ||d }|t ||d }|t ||d }| | t ||d}| | g }g }	t ||d}
x |
D ]}|| jkr|| qW t ||d	}
x$|
D ]}|| jkr|	| qW t t jd
 ||	|d  t 	t jd
 ||d  | j| | _| j|	 | _
d S )Nr  r  r  r  r  r  r  r;   r  z/etcr  )rV   r  r  update_etc_from_sectionr9   r  r  r  r  r  r  )r  r  r  r  r  r  r  r  r;   r  r  r/   r/   r0   r  ,  s6    






z#cagefs_init.update_etc_from_sectionN)r   )	__name__
__module____qualname__r  r  r  r  r  r  r/   r/   r/   r0   r    s   
@r  c             C   s   x| D ]}t jt| rt jt| sytt| d W n tttj	fk
rZ   dS X y&t 
d}t t|  t 
| W q ttfk
r   Y qX qW dS )NFTr   )r!   r4   rJ   rI   r   rc   r   rA   rB   rd   r"   r  )r4  r4   r,   r/   r/   r0   mount_points_busyR  s    
 

r  c               C   s"   t dgrtd td d S )Nz/tmpz6failed to unmount CageFS - skeleton directory is busy.r>   )r  r   r*   rE   rF   r/   r/   r/   r0   check_skeleton_not_busyc  s    

r  c             C   sb   t |dd td t r0td td | r^t rDtd t	  td |r^t
  d S )NT)rd  rk  r>   z!failed to unmount cagefs-skeleton)rm  rF  rG  rN  r   r*   rE   rF   rK  r   r  )r  
check_busyrd  r/   r/   r0   unmount_allk  s    




r  c             C   sd   t  t_t| |rdS |d kr(t }ttj| }x$|D ]}t|}|||r@dS q@W dS )NTF)	r   rV   r   mounts_are_foundrc  rp   r!   r4   r   )r4   proc_mounts
comparatorr  r   r/   r/   r0   r  ~  s    


r  c             C   s   t | |tjdS )N)r  r  )r  rV   Z$path_includes_mount_point_comparator)r4   r  r/   r/   r0   path_includes_mount_point  s    r  c             C   s   t | |tjdS )N)r  r  )r  rV   Zpath_is_mounted_comparator)r4   r  r/   r/   r0   path_is_mounted  s    r  c           
   C   sL   yt td  W n4 tk
rF }  ztdtt|  W d d } ~ X Y nX d S )Nr`   zfailed to create)r#   REMOUNT_FLAGr'   rA   r   r*   r  )r  r/   r/   r0   create_remount_flag  s    r  c               C   s(   yt t W n tk
r"   Y nX d S )N)r!   r   r  rB   r/   r/   r/   r0   r    s    r  c               C   s   t jdS )Nz$/etc/cagefs/disable.home.dirs.search)r!   r4   r5   r/   r/   r/   r0   home_dirs_search_is_disabled  s    r  c        	      C   s  t  r
dS t } | sdS t }t }d}x| D ]}t| }y|rRtj|rBtj	|r|dkr|st
ddd d}t| t|d n<t|}|dkr|st
ddd d}t| td| nh|dkrtj|s@t| t|d n8t||sN|s*t
ddd d}t| td| ntd| nptj	|r4tj|}|dd }tj|r&tj	|rtt|}||kr$t| t|| n`tj|rt||s$|st
ddd d}t|d t|| nt| t|| nt|| ntj|rtj|rtj	|r|stt
ddd d}t| t|d n(tj|rw4nt| t|d nt|d W q4 tk
r } ztd	|d
t| W dd}~X Y q4X q4W |rt  |S )a  
    Create /usr/share/cagefs-skeleton/home* directories and symlinks when needed,
    so they have the same meaning as in real file system. Make all symlinks relative to /usr/share/cagefs-skeleton.
    Create need.remount flag when needed. Return True if remount is needed.
    Fz/homeT)r  r  i  r  r>   Nzfailed to creater  )r  rV   get_homeN_dirsrc  r  rI   r!   r4   r?   r   r  r   r  r  r  rJ   r  remove_file_or_dirr   r   rc   r   rB   r   r*   r  r  )	homesr  Z!always_home_mounting_mode_enabled	unmountedr  r4   skel_link_tolink_tor.   r/   r/   r0   create_homeN_dirs_in_skeleton  s    










*r  c              C   s   t jtr t s t s t s$dS tjdd} x| D ]}t| }y`t j|rt j|rt j	|}|dd }t
t |}||krt | t || W q6 tk
r } ztd|dt| W dd}~X Y q6X q6W dS )zu
    Update symlinks /usr/share/cagefs-skeleton/home*, so they point to the same location as in real file system
    NT)Zuse_globr>   zfailed to process symlinkr  )r!   r4   rJ   rI   r  r  rV   r  r   r   r   r  r   r  rB   r   r*   r  )r  r  r4   r  r  r.   r/   r/   r0   !update_homeN_symlinks_in_skeleton	  s     

r  c             C   s   d}t |ts$d}t |ts$t|}t }xz| D ]r}tj|}|dr0tj|}xJ|dkr||kr||kr|| |rd||< n
|| tj|}qXW q0W | 	t
| dS )zP Add parent directories to list_of_files if they do not present in set_of_files TFro   r>   N)
isinstancedictr   r!   r4   normpathrr   r   r  r(  r   )list_of_filesZset_of_filesZis_dictparentsr  parentr/   r/   r0   add_parents	  s$    







r  c              C   s   t   i } ttj}x6tt|D ]&}|| ddd||< d| || < q"W t||  |  t	
d}ttd}x|D ]}|d|  qxW |  t	
| t	td d S )Nz/etcr   r>   rz   r`   z%s
i  )r   r   rV   
white_listr   r   replacer  r   r!   r"   r#   FUSE_WHITE_LISTra   r'   r(   )r  Zwhite_list_copyZindr,   r   r  r/   r/   r0   save_etc_white_list6	  s    





r  c               C   s   t tjatjattt d S )N)r   rV   
files_list	list_copyr  r/   r/   r/   r0   add_parents_to_listsQ	  s    
r  c          
   C   s   t   | d krt} |   td}y2ttd}x| D ]}|d|  q6W |  W n< t	k
r } zt
dt d t|  W d d }~X Y nX t| yttd W n< tk
r } zt
dt d t|  W d d }~X Y nX d S )Nr   r`   z%s
zFailed to write z : i  z Failed to change permissions of )r   r  r   r!   r"   r#   
FILES_LISTra   r'   rA   r   r*   r  r(   rB   )r  r,   r]   r  r  r/   r/   r0   save_list_of_files_in_skeletonY	  s"    


,
r   c             C   s   yt | d}W n tk
r"   d S X xX| }|dkr8P |d dkr&| }|dkrl|d dkrl|| q&td|d q&W |  d S )NrU   r   r   r{   ro   r4   zis relative)r#   rA   rX   rY   r9   r   r*   r'   )r  r4  r   r   r/   r/   r0   	load_listn	  s    r  c             C   s   g }t | }d}x||k r| | }||kr|s:tj|}|sF||kr|| |d7 }x4||k r| | |d r|| |  |d7 }qZW q|d7 }qW |S )Nr   r>   ro   )r   r!   r4   r   r9   rr   )r  r  Zignore_realpathZdiffZold_lenitemr   r4   r/   r/   r0   compare_lists	  s"    

r  c             C   s~  t   | d dks| d dkr"d S g }tt| t|t}t }x4|D ]*}t   t| t|}t	| }|
dsJt||sJ| d dkrtd| t| d  qJtj|rtj|sy"t|d td	| td W n0 tttjfk
r   td
| td Y nX qJtj|rJy t| td| td W qJ ttfk
rt   td| td Y qJX qJW d S )Nreinitr>   initz/dev/z
dont-cleanz	Skipping r  FzRemoved directory zError while removing directory zRemoved file zError while removing file )r   r  r  r  r  rV   rc  Zdel_libs_from_listrp   rI   rr   r  r   rC   rD   r!   r4   rJ   r   rc   r   rB   rA   rd   r?   r   )r  Zold_listfiles_to_deleter  r   file2r4   r/   r/   r0   delete_files_from_skeleton	  s8    




r  c              C   s,   x&t d D ]} tt| tj qW d S )Nz/sbin/pidof cagefs-fuse)rh  r&  r!   killrZ   signalSIGUSR1)rl  r/   r/   r0   reload_fuse_conf	  s    r  c             C   s   t j| rt j|sdS y6tjtd| |gtjtjd}|  |jdkrPdS W n6 t	k
r   t
dt d |  d | td	 Y nX dS )
NFz-r)r  r0  r   Tzfailed to run z -r  r>   )r!   r4   rJ   rL   r!  DIFFr"  r#  r3  rB   r   rC   rD   )Zdir1Zdir2r6  r/   r/   r0   are_dirs_equal	  s    
(r  c          
   C   sx   t jtjd| }t| }yt|| W nD tk
rr } z&t	
d| d | t| td W dd}~X Y nX dS )z
    Create symlink to NodeJS/Python/etc selector config directory
    inside template for user etc directory
    For details see CAG-797, CAG-828
    :param selector_name: name of selector: nodejs, python, etc
    z	etc/cl.{}zError while creating symlink z to r>   N)r!   r4   r   rV   r  formatSELECTOR_CONF_DIR_TEMPLATEr   rB   r   rC   r  rD   )Zselector_nameZ	temp_pathr  r  r/   r/   r0   &create_symlink_for_selector_config_dir	  s    
r  c          	   C   s"  t tjd d td td t  tjtj	d rt
tj	d }ttj	d tjd  | stjtjd tj	d ddrd S ttjd |d	  nttjd d	 t tj	d d yttjd tj	d  W nF ttfk
r   td
tj d tj	 d td	 td	 Y nX d S )Nz	/etc/mailTrk   rl   z/etc/passwdz/etcF)Zshallowr>   zError moving z/etc to )rc   r   rV   r  r  remove_blacklisted_filesr!   r4   r5   ETC_TEMPLATE_DIRr_   rg   r  rb   r   rB   rA   r   rC   rD   rE   rF   )force_update_etcZold_etc_versionr/   r/   r0   compare_etc_templates	  s"     "r  c           
   C   s  t   d} tj| |  ryDtj| |  rNtj| |  sNt| |  d nt| |   W nL t	t
tjfk
r } z&td|  |  d t| td W d d }~X Y nX tj| |  rtd|  |  d td td | d }tj|rzy8tj|r"tj|s"t|d n
t| W nJ t	t
tjfk
rx } z"td| d t| td W d d }~X Y nX tj|rtd| d td d S )	Nz/usr/share/cagefs-skeletonFzError: failed to remove z : r>   zError: z  exists. Please remove manually.z/var/cagefs)r   r!   r4   r?   rJ   r   rc   r   r   rB   rA   rd   r   rC   r  rD   rE   rF   )rI   r  r   r/   r/   r0   remove_nested_skeleton
  s,     4
0r  c       
      C   s~  t   t }t }t  t  td}t	tj
d d tjtj
d syttj
d d W n0 tk
r   tdtj
d  td Y nX x$| D ]}|| || t  qW |ttj  |r*xTtj D ]F\}}tj|}	|	drtj|	ddst|rtd	| dS qW t  t| t   t!  t"| d
 d |d krnt#| dd nt#| |d dS )Nr   z/etcTi  creatingr>   z/etc/)etcz CloudLinux Selector setup, path:zforce-update-etc)r  )	all_users)r;   F)$rj   r  read_configrV   read_native_confload_black_listr!   r"   rc   r   r  r4   rJ   r   rB   r   r*   rE   rF   r  r  r  r  r   orig_binariesvaluesitemsr   rr   move_to_alternativesis_mandatory!remove_unwanted_users_from_groups#create_files_for_symlink_protection"create_dirs_for_symlink_protectionr  
update_etc)
r  r;   print_selector_errorscir  r,   r  aliasr   
orig_path2r/   r/   r0   update_etc_only%
  sB    




r+  c             C   s   t  \}}tj| tj| | rt t_t }xttjD ]j}tj	
|r>t| }t||s>tj	
|rxt| q>tj	|s>tjttj	|ddd t| q>W d S )Nr>   )r  r  )build_wrappers_dictsrV   wrappersr  wrappers_namesr   r   rc  r!   r4   r5   rI   r  Zinstall_wrapperrR   r  r   )update_wrappersr-  r.  r  r   r4   r/   r/   r0   load_wrappersc
  s    

r0  c             C   s6   | |krdS | | }t|dkr&dS |d |d fS )N)NNr   r   r>   )r&  r   )Z	separatorr   Z
line_partsr/   r/   r0   check_separatorx
  s    
r1  c             C   s8   |d k	r,t | }||}|d kr(dS dS |r4dS dS )NFT)r  r$  r'  )Zregexpartcan_be_noneZregexp_compZp1r/   r/   r0   validate_with_regex
  s    

r4  c             C   s   |  ds|  rdS td| \}}|dks4|dkr8dS d|krPtd|\}}n|}d}d|krptd|\}}n|}d}|dks|dkrdS tj|sdS | d dkrdS td	|dd
sdS td|dd
sdS td|dd
sdS dS )z+
    Return False if line is corrupted
    r}  T=NFr  r   ro   z^[a-z][-a-z0-9]*$)r3  z^[a-zA-Z][-a-zA-Z0-9_]*$z^[a-zA-Z.][-a-zA-Z0-9_.]*$)rr   isspacer1  r!   r4   isabsstripr4  )r   Zalias_wrapperZuser_commandr)  wrapperr<   r+  r/   r/   r0   check_proxy_line
  s4    r:  c             C   s4  d}t  }i }i }x|D ]}t|sX| rBtdt| d qtdt| d  q|drdq| dd}t|dkr|d  d	d}t|dkr|d d
krq|d  }t|dkr|d  }	n|}	|d 	d	dkr|d  }
n |d  d	d}|d  }
|||
< |	||
< qW ||fS )Nzcagefs.proxy.programzWarning: Found corrupted line:z. Skip line.r}  r5  r>   r   r   r  Z	noproceedr   )
load_wrappers_commandsr:  r)   r  r   rr   r8  r&  r   rM  )r   ZDEFAULT_PROXY_NAMEcommandsr-  r.  r   ZwordsZ
words_leftr)  Zwrapper_namer+  Zwords_rightr/   r/   r0   r,  
  s8    
r,  c              C   sh   t jt} t jt}g }xFt | D ]8}t j| |}||r(t j|r(|	t
| q(W |S )N)r!   r4   r   PROXY_COMMANDSr  r   r   r   r5   r(  rV   r  )Zproxy_commands_dirZproxy_commands_namer<  r  r4   r/   r/   r0   r;  
  s    r;  c              C   sZ  t  } xJt jD ]>}t  |dkr(q|d}|rBt j| }nt| }tj	|r|st
|| r|td| d td qt|| rtd| d td qyFtj|rtj|st|d n
t| td| tt W nJ tttjfk
r. } z"td	| d
 t| td W d d }~X Y nX tj	|rtd| d td qW d S )Nz/usr/local/cpanel/bin/jailshellz/etc/zWarning: blacklisted path z is mountedr>   z includes mount pointFzRemoved zError: failed to remove z : z  exists. Please remove manually.)rV   rc  
black_listr   rr   r  rI   r!   r4   r?   r  r   rC   rD   r  rJ   r   rc   r   r   VERBOSErB   rA   rd   r  )r  Zblack_list_fileZ	is_in_etcr4   r  r/   r/   r0   r  
  s4    



0r  c             C   s   t jt}t jt}g t_xt |D ]}t j||}|	|r*t j
|r*t|}x|D ]z}t| }|drb|dks|ddks|	drtd|d| qb|dst j|}|tjkrbtj| qbW q*W t t_| rt  d S )Nro   z/../r   z/..zInvalid pathzin filez/etc/)r!   r4   r   BLACK_LIST_FILEr  rV   r>  r   r   r   r5   r  r  rY   rr   rM  r   r*   r   r9   r   r   r  )ri   Zblack_list_dirZblack_list_namer  r4   r>  r   r/   r/   r0   r    s(    


 

r  c           
   C   s   ddg} d}x| D ]}t tj| }t | }tj|rtj|stj|r`tj|dd yt	|| W q t
tfk
r   td|d| td Y qX qW d S )	Nz/usr/local/cpanel/bin/jailshellz/usr/local/psa/bin/chrootshz	/bin/bashT)Zcheck_mountszcreating symlinkrv   r>   )rI   r!   r4   r   rJ   r   r?   rV   r  r  rB   rA   r   r*   rE   rF   )Zbin_listrN   Zbin_nameZ
parent_dir	link_namer/   r/   r0   replace_jailshell.  s    
rB  c          	   C   s.   x(|  |D ]}|||| || qW d S )N)optionsr   get)re   r  rf   new_sectionZoptionr/   r/   r0   copy_options@  s    rF  c             C   s   |  |r| |s:| dkr:|| t| ||| nXd}x,tdD ] }|t| }| |sHd}P qHW |rz|t  }|| t| ||| d S )NdefaultTr   F)Zhas_sectionlowerZadd_sectionrF  r   r  r  )re   rf   r  r5  numrE  r/   r/   r0   copy_sectionE  s    




rJ  c             C   s  t jdd}i }xttD ]}|drt| }t jdd}|| | rxR| D ]F}||krt	d| d ||  d | t
d td qV|||< qVW x| D ]}t||| qW qW tjtrxttD ]}|drtjt|}t jdd}|| | rlxV| D ]J}||kr^t	d| d ||  d | t
d td n|||< qW x| D ]}t||| qvW qW |S )	NF)strictz.cfgzError: duplicated section [z] in files z and r>   z.work)configparserZRawConfigParserr!   r   
CONFIG_DIRr   rt  r  r   rC   rD   rE   rF   rJ  r4   rJ   WORK_CONFIG_DIRr   )Zfail_if_sections_are_duplicatedr  r  r   r4   r  r  r/   r/   r0   r  W  s<    

&


&r  c           	   C   sZ   t   td } tj| sVytd|  W n* ttfk
rT   t	d|  t
d Y nX d S )Nz/var/tmpz/tmpzError while creating symlink r>   )r   rI   r!   r4   r?   r  rB   rA   r   rC   rD   )r4   r/   r/   r0   create_var_tmp_symlink  s    rO  c          
   C   sn  | d dkr8| d dkr8t  s8ts4td td d S t  t  t  t }| d dkrhtdd	d
 t	 t _
t }t   t  t  | d dkr| d dkrt t t jrRt jrRtjtd rRtddd	d ttd d}t| }|  td |rRtdtt j tdt| tddd	d yNxH|D ]@}x8|| D ],}|t j| krNtdt  d| P qNW q@W W n8 tk
r } ztdt  d| W d d }~X Y nX yPxJt jD ]@}x8t j| D ]*}||| krtdt  d| P qW qW W n8 tk
rH } ztdt  d| W d d }~X Y nX td t d	 t!  t"d}t#  t$%t j&d d	 tj't j&d syt(t j&d d W n2 t)k
r   tdt j&d  t*+d Y nX x.|, D ]"}	t#  |-| t.||	 t/  qW |0| t.t1t j23  |4| t. t 5  t6t7 t"| t j8t.d ddd	d t 9t.d dd t :ddg t;  t<|  t=  t>  t?@t. tA  t Bt t jrDttd  d!}
x2tCt jD ]$}|
Dd"|dEt j| f  qW |
  td#dd	d ttd d!}|DtFt j |  td tG  tH  tI rxtJ sjtK|  ntK| d	d$ n| d dkrtL  | d dkrd%| krtM  tN  t O  tP  tQdd& tRtSdd& t T  tUdd& tV }tW  | d dks| d dkr8tJ s8tXd	 d}tjd'r8tYd( |rFtXd	 tZ rbt[d)td t\  t ]  d S )*Nr  r>   zforce-updater   zWcagefs-skeleton has been updated recently, if you want to force the update, please run:z"cagefsctl --force-update"r  FT)r   r  z	/libs.datzLoading libs.datr  )endflushrU   ZDonez
Pickle lenzEval lenZ	Comparingr   z : NOT EQUALz : Key Errorz/etci  r  z/rootih  )r  r  z/passwdz/groupz	/libs.txtr`   z%s : %s
zSaving libs.dat)r  cagefs_was_enabled)r  z/usr/bin/systemctlz/usr/bin/systemctl start cagefszUpdating statuses of users ...)^rV   Z#update_of_cagefs_skeleton_is_neededrD   r   update_rpm_packages"add_default_rpm_packages_to_cagefsrj   r  r   r   r   r  r  r$  r%  Z	load_libs	LIBS_LISTdebug_optionZ	libs_listr!   r4   r5   LIBDIRr#   evalrt  r'   r   r   r*   linenor:   r0  r  r"   r   rc   r   r  rJ   r   rB   rE   rF   r  r  rI   r  r  r   r  r  r  r#  r[  r  r  	set_ownerZsave_etc_safe_listr  r  rB  rO  cagefs_da_lib create_symlink_to_php_ini_for_DAr   Z	save_libsr  ra   r   reprr  r  rT   r   r&  r  r   rG   Zcreate_utmp_in_skeletoncreate_utmp_for_all_usersr  r  r  Zadd_syslog_socketr  r  r  r  rh  r   rC   update_users_statusZsave_last_update_time)r  r(  r  ZrtfZtdkeyr  r  r,   r  Ztf2Ztfr  r/   r/   r0   update_cagefs  s    
"
&&



$


$ra  c             C   s`   t | ddd trt d d S x<tj }|dkr6P n|dkrPt d td t d	 q W d S )
Nr  T)rP  rQ  Zyeszyes
zno
ZAbortingr>   zPlease, reply with yes or no)r   do_not_ask_optionrE   r?  rX   rF   )r   r   r/   r/   r0   confirmV  s    

rc  c              C   s  t d tdddd ttd d ttd d tdd td	 td
ddd tdddrvtd t	
d td td	 tdddd t rtd t	
d td td	 t  t rtd t	
d t rtd n&tdt ddd ttd td tdt ddd ttd td td } tj| rt| std|  ddd t| d td d S )NzWARNING: If you continue, CageFS will be disabled, and all related files and directories will be removed. Do you want to continue (yes/no)? zDisabling CageFS    r  T)rP  rQ  zusers.disabledzusers.enabled)disable_allz[DONE]zUnmounting skeleton    )rd  rk  zunmounting skeletonr>   zUnmounting users   zunmounting usersz!failed to unmount cagefs-skeletonzPUsers with invalid pathes to home directories exist! DO NOT REMOVE /var/cagefs !z	Removing z	   [DONE]z.old)rc  r   rc   r   r   r_  rm  r   r*   rE   rF   rF  rG  rK  r  rN  repair_homesr  r  rI   r!   r4   rJ   )Zold_skelr/   r/   r0   
remove_allg  sF    









rf  c               C   s  t d t d t tjd d  t d t d t d t d t d	 t d
 t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d t d  t tjd d!  t d t d" t d# t d$ t d% t d& t d' t d( t d) t d* t d+ t d,t t d-t t d. t d/ t d0 t d1 t d2 t d3 t d4 t d t d5 t d6 t d7 t d8 t d9 t d: t d; t d< t d= t d> t d? t d@ t d t dA t dB t dC t dD t dE t dF t dG t dH t dI t dJ t dKtj dL  t dM t dN t dO t dP t dQ t d d S )RNr   z&Use following syntax to manage CageFS:r   z
 [OPTIONS]zOptions:zU -i | --init                 : initialize CageFS (create CageFS if it does not exist)zT -r | --reinit               : reinitialize CageFS (make backup and recreate CageFS)z\ -u | --update               : update files in CageFS (add new and modified files to CageFS,z5                               remove unneeded files)z] -f | --force                : recreate CageFS (do not make backup, overwrite existing files)z_ -d | --dont-clean           : do not delete any files from skeleton (use with --update option)z8 -k | --hardlink             : use hardlinks if possibleze      --create-mp            : Recreates /etc/cagefs/cagefs.mp file with default set of mount points.zr                               WARNING: Any previous changes made to file by admin or by any software will be lostz>      --mount-skel           : mount CageFS skeleton directoryz@      --unmount-skel         : unmount CageFS skeleton directoryzY      --remove-all           : disable CageFS, remove templates and /var/cagefs directoryzx      --sanity-check         : perform basic self-diagnistics of common cagefs-related issues(mostly useful for support)zp      --addrpm               : add rpm-packages into CageFS (run "cagefsctl --update" in order to apply changes)zj                             : only package name should be specified (without package version and release)zF                             : example: cagefsctl --addrpm ImageMagickzs      --delrpm               : remove rpm-packages from CageFS (run "cagefsctl --update" in order to apply changes)zM      --list-rpm             : list rpm-packages that are installed in CageFSz? -e | --enter                : enter into user's CageFS as rootzV      --update-list          : update specified files only (paths are read from stdin)zM      --update-etc           : update etc directory of all or specified usersz[      --set-update-period    : set min period of update of CageFS in days (default = 1 day)zO      --force-update         : force update of CageFS (ignore period of update)zS      --force-update-etc     : force update of /etc directories for users in CageFSz`      --reconfigure-cagefs   : configure CageFS integration with other software (control panels,z5                               database servers, etc)z%Use following syntax to manage users:z$ [OPTIONS] username [more usernames]z5 -m | --remount           : remount specified user(s)zK -M | --remount-all       : remount CageFS skeleton directory and all userszP                            (use this each time you have changed cagefs.mp file)z5 -w | --unmount           : unmount specified user(s)z?    | --unmount-dir       : unmount specified dir for all userszK -W | --unmount-all       : unmount CageFS skeleton directory and all usersz= -l | --list              : list users that entered in CageFSzE      --list-logged-in    : list users that entered in CageFS via SSHz6      --enable            : enable CageFS for the userz7      --disable           : disable CageFS for the userzA      --enable-all        : enable all users, except specified inzB      --disable-all       : disable all users, except specified inzP      --display-user-mode : display current mode ("Enable All" or "Disable All")zE      --toggle-mode       : toggle mode saving current lists of userszR                            (lists of enabled and disabled users remain unchanged)z.      --list-enabled      : list enabled usersz/      --list-disabled     : list disabled userszP      --user-status       : print status of specified user (enabled or disabled)z3      --getprefix         : display prefix for userzPHP Selector related options:zW      --setup-cl-selector         : setup PHP Selector or register new alt-php versionszp      --remove-cl-selector        : unregister alt-php versions, switch users to default php version when neededzq      --rebuild-alt-php-ini       : rebuild alt_php.ini file for specified users (or all users if none specified)zi      --validate-alt-php-ini      : same as --rebuild-alt-php-ini but also validates alt_php.ini options zt      --cl-selector-reset-versions: reset php version for specifed users to default (or all users if none specified)z      --cl-selector-reset-modules : reset php modules (extensions) for specific users to defaults (or all users if none specified)zL      --create-virt-mp            : create virtual mount points for the userzM      --create-virt-mp-all        : create virtual mount points for all userszP      --remount-virtmp            : create virtual mount points and remount userzh      --apply-global-php-ini      : use with 0, 1 or 2 arguments from the list: error_log, date.timezonezh                                    without arguments applies all global php options including two abovezCommon options:z4      --enable-cagefs                : enable CageFSz5      --disable-cagefs               : disable CageFSzP      --cagefs-status                : print CageFS status (enabled or disabled)ze      --check-cagefs-initialized     : properly checks whether CageFS is initialized and print resultz2      --set-min-uid                  : Set min UIDzF      --get-min-uid                  : Display current MIN_UID settingzW      --print-suids                  : Print list of SUID and SGID programs in skeletonzj      --do-not-ask                   : assume "yes" in all queries (should be the first option in command)zf      --clean-var-cagefs             : clean /var/cagefs directory (remove data of non-existent users)zT      --set-tmpwatch                 : set tmpwatch command and parameters (save to z file)zz      --tmpwatch                     : execute tmpwatch (remove outdated files in tmp directories in CageFS for all users)zC      --toggle-plugin                : disable/enable CageFS pluginz5 -v | --verbose                      : verbose outputz      --wait-lock                    : wait for end of execution of other cagefsctl processes (when needed) before execution of the commandz3 -h | --help                         : this message)r   rE   r   r   r   rV   Z
CAGEFS_INIr/   r/   r/   r0   usage  s    

rg  c               C   sF   t  s6tdtd tdtjd  d  td ttd d S )N	directoryzdoes NOT exist or is empty.zUse "r   z --init" to create CageFSr>   i  )	check_cagefs_skeletonr   r*   rI   rE   r   rF   r!   r(   r/   r/   r/   r0   check_skeleton  s
    
rj  c             C   sP   g }xF| D ]>}t |}d}x| D ]}||r"d}P q"W |s
|| q
W |S )NFT)rV   rp   rr   r9   )r  resultr4   r  r  r  r/   r/   r0   remove_parent_dirs  s    



rl  c       
   	   C   s  t }ddlm} || }|d kr4|s0td|   d S tj|syt|d W q tt	fk
r|   t
d| td Y qX n$tj|st
d|d td td	}tj|| d
 }t|d}|d|  d  |d d}t|}t|}x|D ]z}	|	ds |	ds |	ds |	ds |	ds |	ds |dkrf|d|	  n
||	 |d }q W |d |  t| d S )Nr   )get_package_fileszPackage %s not installedi  zfailed to creater>   r4   zshould be directoryr   z.workr`   [z]
zpaths=z/usr/share/man/z/usr/share/locale/z/usr/share/doc/z/usr/share/info/z/usr/lib/.build-id/z/usr/share/licenses/z, r{   )rN  Z
simple_rpmrm  r   r!   r4   r?   r   rB   rA   r   r*   rE   rF   rJ   r"   r   r#   ra   rE  rl  rr   r'   )
pkg_namesilentWORK_DIRrm  Zpackage_filesr,   	WORK_FILEZaFiler*  r   r/   r/   r0   addrpm
  sF    







rs  c          	   C   s  t }tj|| d }tj|s4|s2td|   ntj|sLtj|sZt	|d nyt
| W n$ ttfk
r   t	d| Y nX | tkryFg }tjtrtt}| d |kr|| d  tt|d W n$ ttfk
r   t	d Y nX d S )Nz.workz!Rpm %s is not installed in CageFSzshould be regular filezfailed to remover{   Fzfailed to write package list)rN  r!   r4   r   r?   r   r   r5   r   r*   ri   rB   rA   STD_PACKAGESrR   STD_PACKAGES_FILErV   r  r9   r^  )ro  rp  rq  rr  packagesToExcluder/   r/   r0   delrpm6  s*    

rw  c             C   sj   t }g }tj|rDx.t|D ] }|d |d }|| q W |  | sfx|D ]}t| qVW |S )Nr  )	rN  r!   r4   rJ   r   r  r9   r   r   )rp  rq  rpmsZwork	file_namepackager/   r/   r0   list_rpmS  s    
r{  c             C   sB   x<| D ]4}t   |s.tjtjt|d st|dd qW d S )Nz.workT)rp  )r   r!   r4   r5   r   rN  rs  )args	overwriterpmr/   r/   r0   add_rpm_packages_to_cagefsa  s    
r  c             C   s   x| D ]}t |dd qW d S )NT)rp  )rw  )r|  r~  r/   r/   r0   remove_rpm_packages_from_cagefsh  s    
r  c              C   sN   g } t jtrtt} g }x"tD ]}|d | kr$|| q$W t| d S )Nr{   )	r!   r4   rR   ru  rV   r  rt  r9   r  )rv  ZpackagesToAddZpackNamer/   r/   r0   rT  m  s    

rT  c              C   s    t   tdd} t| dd d S )NT)rp  )r}  )r   r{  r  )rx  r/   r/   r0   rS  {  s    
rS  c             C   s|   t | }|dk r$td td |ay,ttd}t	dt}|
| |  W n"   tdt td Y nX d S )Nr   zMIN UID should be >= 100r>   r   r*  zwritting MIN UID to file)rZ   r   r*   rE   rF   r   r#   MIN_UID_FILENAMEstructpackra   r'   )valueZbuf_valbinfiledatar/   r/   r0   set_min_uid  s    



r  c           
   C   sX   y
t  } W n< tk
rF } ztt|t td W d d }~X Y nX | d k	rT| ad S )Nr>   )	read_min_uidr[   r   r*   r  r  rE   rF   r   )r   r  r/   r/   r0   get_min_uid  s    
r  c              C   s   t jtsdS y*ttd} td}| |}|   W n   t	dY nX t
||krdt	dtd|}t
|dkr|d dkr|d S dS )zg
    Gets minuid from file and returns
    unpacked value if no errors happened
    otherwise None
    Nr2   r*  z failed to read MIN UID from filezreading MIN UID from filer   r   )r!   r4   r5   r  r#   r  calcsizert  r'   r[   r   unpack)r  Zintsizer  rI  r/   r/   r0   r    s    


r  c              C   s~   t   t } t|  | dkrFtd}td xL|D ]}t|d q2W n4| dkrzttd}td x|D ]}t|d qhW d S )Nz
Enable AllTFzDisable All)r   r   r   r   r   r   r   )r   rJ  r<   disabled_usersr/   r/   r0   toggle_mode  s    

r  c             C   s  t | } yt|}W n$   tdt| d td dS t |j	| d s| d }td|d  d | t|d  yd|d d	 t|d
  d }t
|tkrt|dkr|| }|d }t|d}|| |  W n4 tk
r   td|d  d | td dS X dS )Nz(Warning: getgrgid() failed for group id z skipping...r>   r   z
/etc/groupzadding group z to r  z:x:r   r  r{   azERROR: failed to write group )rV   r   grpZgetgrgidr   rC   r  rD   Ztest_group_existZgr_nametyper   r#   ra   r'   rA   )r   group_idr<   r  grr   r  fdr/   r/   r0   addgrouptojail  s*    
"

r  c             C   s  t | |||}|dkrdS yJ| d }t|d}| }x(t|dkrb|d}t|dkrXt|d |krX|d d d d	}	||	kr|  d
S td| d |d  t	|d  |
 }
| }||
t|  t|	d
kr|	d dkr|g}	n
|	| |d d |d  d }d	|	}||d | 7 }|| |  d
S | }q<W W n< tk
r   td| d t| d | t	d
 dS X dS )Nr   z
/etc/groupzr+r     r   r9  r   r~  r>   zAdding user z
 to group r  r   z:x:r{   zERROR: failed to add user z in )r  r#   rX   r   r&  rZ   r'   r   rC   rD   tellrt  seekr9   r   ra   rA   r  )r   r  r<   r  rP   r   r  r   Zsplittedr;   r  Zbufr  Ztmp2r/   r/   r0   addusertogroupinjail  s@    

 "


&r  c          	   C   s\   | d }y6t |d}|d |d |  t|d W n ttfk
rV   Y nX d S )Nz
/.htaccessr`   z#CageFS autogenerated file
zdeny from all
i  )r#   ra   r'   r!   r(   rA   rB   )r4   ry  r   r/   r/   r0   create_htaccess  s    


r  c          	   C   s4   | d }yt | W n ttfk
r.   Y nX d S )Nz
/.htaccess)r!   ri   rA   rB   )r4   ry  r/   r/   r0   r   #  s
    r   c          
   C   s  t j| }t| }tjd }td | d |  d }	|	d }
|rxXdD ]P}tj|| |
| dddkrHt d| | d	 |
 | t	d |sHt
d
 qHW n|d krt| |
}|d dks|d dks|rxyHt|
d tj||
d|ddkrtdt| gdrtd|  W nZ tk
rt } z:t d| d	 |
 d t| t	d |sdt
d
 W d d }~X Y nX nRtj||
dd|ddkst| gdrt d| d	 |
 t	d |st
d
 td krtjdotjdatd tryF|
d }|
d }tj|sBtj|s6t|d td| W nR tk
r } z2t d| d t| t	d |st
d
 W d d }~X Y nX t j|j}t  }x2|D ](}ynt!|
d d}|"|j#d t|d
  d  t|d!  d  |d"  d  |d#  d  |d$  d%  |$  W n4   t d&|j# d' t	d |sZt
d
 Y nX t%|	|d! d |s|st
d
 xD|D ]<}|j#|j&krt'|	|j(|j#|}|s|st
d
 qW t)|
|j#|d(  qW d S ))Nz/etcro   r  )z/passwdz/shadowF)create_parent_dirr>   zError copying z to r   r  r  T)skip_dst_fileszcopytree() failed)r;   z%Failed to setup cl-selector for user zError while copying z: )r  r  z/usr/local/apache/domlogsz/etc/apache2/logs/domlogsz	/apache2/z/apache2/logsz/apache2/logs/domlogsi  zError while creating z : z/passwdr  z:x:r  r9  r  r   r   r{   zError while adding user z to passwd filer  )*r   r   r   r   rV   r  r  	copy_filerC   rD   rE   rF   get_custom_etc_files_for_userrc   r   copytreer)   create_etc_alternativesr  domlogs_foundr!   r4   rJ   SPECIAL_PATHSr9   r?   r   r  rB   get_pw_by_uidr   r  Zgetgrallr#   ra   pw_namer'   r  Zgr_memr  gr_gidZadd_user_to_shadow)r<   r  ry  recreatepasswd_onlycustom_etc_filesZpw_liner   Zetcskelr   ZetcuserZcfr  Zlogs_dir_pathZdomlogs_pathr   r  r+   r  r  rP   r/   r/   r0   copyetc-  s    

"&



T

r  c          
   C   s   yt | }W n ttfk
r&   d S X t|jry"t| d t	
d|  td W q tttjfk
r   t	
d|  td Y qX nLy t |  t	
d|  td W n* ttfk
r   t	
d|  td Y nX d S )NFzRemoved directory r>   zError while removing directory zRemoved file zError while removing file )r!   lstatrB   rA   statS_ISDIRst_moderc   r   r   rC   rD   rd   r   )r4   Zsbufr/   r/   r0   remove_file_or_directory  s    
r  z/mail/ro   c             C   s    xt D ]}| |rdS qW dS )NFT)r  rr   )r4   Z	spec_pathr/   r/   r0   check_special_paths  s    

r  c             C   s   t  s|tkrPi }t j|d ||d d t|}|  t||}|t|< nt| }|d krpt | |d }x^|D ]V}	t |	}
|d |	 }||krvt	|
rv|d dkrt
d| t|d  qvt| qvW d S )Nz/etc)cut_pathz
dont-cleanr>   z	Skipping r  )rV   Zcustom_etc_presentfiles_to_delete_cacheadd_tree_to_listr   r   r  r  rp   r  r   rC   rD   r  )r<   userdiretc_skelr  etc_user_versionr  Zetc_userZetc_user_listr  r   r  r4   r/   r/   r0   	clean_etc  s$    



r  c               C   s   t tj S )N)r   r   r   r   r/   r/   r/   r0   get_all_users_from_passwd  s    r  c          	   C   s  t dtd t||}t }ttjd }tjt	ddd d }xR|D ]H}t
|}t	d | }	d| d | }
t	|
 }|d }t|	drqHt|drqHt||}t||}t|}| d s||krxt d	| d
 td tj|d r| d dks| d dkr&t|| ||d nNt|| ||d |d kr`i }tjtjd |tjd d t|||| ||d nd}||krt d	| d
 td d}t|| |dd t||}|rz|st d	| d
 td |d kri }tjtjd |tjd d d}xV|D ]N}||krZ|| }| d dkrPt d| t| d  qt| nd}qW |rzt|| ||d t|| t|| qHW d S )NzUpdating users ...r>   z/etci  T)r  ro   zforce-update-etczUpdating user z ...z/etc/passwdr  r  )r  )r  F)r  z
dont-cleanz	Skipping r  )r   rC   rD   get_cagefs_usersr=   r_   rV   r  r  r  r   r  r  r!   r4   r5   r  r  r  Zget_custom_etc_files_to_deleter   update_custom_etc_files_for_usersave_custom_etc_log)r  r;   ry  r  Zmodified_usersZetc_skel_versionr  r<   r   Z	prefixdirr   r  user_etc_pathr  custom_etc_files2r  Zmessage_printedZcustom_files_to_deleteZcopyetc_neededr4   Zfullpathr/   r/   r0   r&    sj    
.






r&  c             C   s0   | d krt td} x| D ]}t|d qW d S )NT)r   r   r   )rJ  r<   r/   r/   r0   +enable_cagefs_for_users_with_duplicate_uids  s    
r  c             C   s   | rt  }t|d nj|d k	rB|d k	rB|r4t|}t|| n@ttd}tj|d|d |rjt| td}tj|d|d |d k	rt| d S )NFT)	fix_owner)r  rV   Zupdate_statusr   r   r  (reload_php_for_users_with_changed_status)rd  r;   rX  r  old_enabled_usersrJ  r  r/   r/   r0   r_    s    r_  c             C   s$   t  }tt| |}t| dS )z
    Filter users and reload php process only if status was REALLY changed
    :param old_enabled_users: enabled users before any status change
    :return:
    N)r   r   r   symmetric_differencereload_php_for_users)r  Znew_enabled_usersZusers_to_kill_processr/   r/   r0   r  .  s    r  c             C   s*   | d kr|rt  } n
td|} t| } | S )NT)r  r   r   )r;   r  r   r/   r/   r0   r  =  s    
r  c              C   s&   x t ddD ]} tj| dd qW dS )zz
    Create user's personal /home/user/.cagefs/var/run/cagefs/utmp
    file for all users
    For details see CAG-706
    T)r  F)r   N)r  rV   create_utmp_for_user)r<   r/   r/   r0   r^  H  s    r^  c             C   s&   t | |} x| D ]}td| qW d S )Nphp)r  r   )r;   r  r<   r/   r/   r0   r  R  s    

r  c             C   s   |st j|syt | W n ttfk
r6   Y nX yt| | W nv tttfk
r } zR|rt	
d|| t|ddf td n$td|| t|ddf tjd dS d }~X Y nX dS )	Nz.Error : failed to create symlink %s to %s : %sErrnozErr coder>   z-Error : failed to create symlink %s to %s: %s)r\  TF)r!   r4   r   r   rB   rA   r   r  r   r   rC   r  r  rD   r   rE   r0  )	dest_pathrA  	write_logr   r  r/   r/   r0   switch_symlinkX  s    &$r  c              C   sL   t dkrHtjddd} y| d }W n tk
r:   da dS X | dka t S )z
    Return True if modules selected via PHP Selector (alt_php.ini) must be used always (never use modules selected in cPanel MultiPHP Manager)
    See CAG-511 for details
    Nz/etc/cl.selector/symlinks.rulesT)ry  zphp.d.locationFZselector)use_selectorr   Z	load_oncer:   rH  )Z
syml_rulesvalr/   r/   r0   selector_modules_must_be_usedk  s    r  c              C   s8   t  r4t } | r4y| d dS  tk
r2   Y nX dS )z
    Return True when default system php version selected via MultiPHP Manager in cPanel WHM is ea-php (not alt-php)
    For details see CAG-774
    rG  zea-phpT)r   read_cpanel_ea4_php_confrr   r:   )confr/   r/   r0   !multiphp_system_default_is_ea_php|  s    r  c                s<    fdd}d}t  }x|D ]}||r$d}q$W |S )a~  
    Switch symlink so it will point to directory with modules for alt-php
    For details see CAG-447
    Returns True if error has occured
    Should be called as user (not root)!
    :param php_vers: alt-php version selected for an user (for example 'native' or '5.6')
    :type php_vers: string
    :param force: recreate symlinks even when they exist
    :type force: bool
    c          	      s   t jd| d}t j|}t j|sXytj|ddd W n ttfk
rV   Y nX d	dd }t
 s|| ks|t sd	|  }nt jtjd
|  }t|| S )Nz.cagefs/opt/altz	link/confi  T)	recursiver  r  r   z/opt/alt/%s/etc/php.dzalt-)r!   r4   r   r   r?   r   r  rB   r   r  r  r  rV   ETC_CL_PHP_PATHr  )php_dir	link_pathr  Zselected_php_dirr  )r   homedirphp_versr  r/   r0   switch_symlink_for_dir  s    
z>switch_symlink_for_alt_php_ini.<locals>.switch_symlink_for_dirFT)rV   get_alt_dirs)r  r  r  r   r  r5  alt_php_dirsr  r/   )r   r  r  r  r0   switch_symlink_for_alt_php_ini  s    
r  z/etc/cpanel/ea4/php.confc           	   C   sf   t dkrby ttd} t| a |   W n8 tjtfk
r`   i a y|   W n   Y nX dS X t S )z
    Read /etc/cpanel/ea4/php.conf, return something like {'default': 'ea-php54', 'ea-php56': 'suphp', 'ea-php54': 'cgi', 'ea-php55': 'suphp'}
    Return None if error has occured
    NrU   )EA4_PHP_CONF_CACHEr#   EA4_PHP_CONFyamlr6   r'   Z	YAMLErrorrA   )r]   r/   r/   r0   r    s    

r  )r  z*/opt/cpanel/%s/root/usr/bin/php-cgi.cagefs)zphp-cliz&/opt/cpanel/%s/root/usr/bin/php.cagefs)zphp.iniz&/opt/cpanel/%s/root/etc/php.ini.cagefs)lsphpz(/opt/cpanel/%s/root/usr/bin/lsphp.cagefs)z%s/etc/cl.selector/ea-phpz%s/etc/cl.selector/ea-php-cliz%s/etc/cl.selector/ea-php.iniz%s/etc/cl.selector/ea-lsphpc        	      C   s   t  s
dS ytdj} W n tk
r.   dS X t }|s>dS d}td}x|D ]}|drRxt	
 D ]z}y:|d | }t|d}|d |  t|d|  W qj tk
r } ztd	|d
t| d}W dd}~X Y qjX qjW qRW t| |S )z
    Configure symlink protection for symlinks created for integration with cPanel MultiPHP
    Return True if error has occured
    Flinksaferz   zea-phpr>   r`   z'CageFS integration for cPanel MultiPHP
r   zfailed to create filer  TN)r   r  getgrnamr  r:   r  r!   r"   rr   SYMLINKSr  r#   ra   r'   chownrB   r   r*   r  )	linksafe_gidr  r5  Z	umask_oldr)  r4   Z	file_pathr]   r  r/   r/   r0   r$    s2    





r$  c                s    fdd}t  sdS t }|s$dS y|d }W n tk
rD   dS X |dsTdS | j}td t| d |  |s| }|dk	rd	}||krd}d}	xVt D ]J\}
}|
  }|d	krt	|d
 | |||p|	}	qt	|d |||p|	}	qW |	S )a  
    Switch symlinks that are used for integration with cPanel MultiPHP:
    when selected_php_vers == alt-php version, then create symlinks like /etc/cl.selector/ea-php -> php;
    when selected_php_vers == native version, then create symlinks like /etc/cl.selector/ea-php -> /opt/cpanel/ea-phpXX/root/usr/bin/php.cagefs;
    For details please see CAG-445
    Return True if error has occured
    :param pw: password file entry for an user
    :type pw: as defined in standard pwd module
    :param selected_php_vers: alt-php version selected for an user (for example 'native' or '5.6')
    :type selected_php_vers: string
    :param write_log: write error messages to log or not
    :type write_log: bool
    :param force: recreate symlinks even when they exist
    :type force: bool
    c                 sD   yt d  } W n tk
r&   dS X | dr@| dd S dS )z
        Return string like ea-phpXX when symlinks have been created already and native version is selected
        Return None otherwise
        z%s/etc/cl.selector/ea-php.iniNz/opt/cpanel/ea-phpro   r9  )r!   r  rB   rr   r&  )r  )user_cagefs_pathr/   r0   #get_default_native_version_selected  s    
zPswitch_symlink_for_cpanel_multi_php.<locals>.get_default_native_version_selectedFrG  Tzea-phpro   Nnativer>   r   )
r   r  r:   rr   r  r  r   r  r   r  )r+   Zselected_php_versr  r   r  r  default_phpr   Zold_eaphp_defaultr5  Zsympathr  r  r/   )r  r0   #switch_symlink_for_cpanel_multi_php  s6    
r  c       
   
   C   s   t j| j}t j| jd}|r>t|d| j| j|rdS nRt j	|syt
|d W n4 ttfk
r } ztdt| dS d}~X Y nX |rt| j| j t|| j||}	|rt| |||p|	}	|rt  |	S )a	  
    Create .cagefs directory in home directory of an user (if that dir does not exist),
    and create symlinks to modules for alt-php
    For details see CAG-447
    Also switch symlinks that are used for integration with cPanel MultiPHP
    For details please see CAG-445
    drop_perm should be True when called as root, otherwise drop_perm should be False
    Returns True if error has occured
    :param pw: password file entry for an user
    :type pw: as defined in standard pwd module
    :param php_vers: alt-php version selected for an user (for example 'native' or '5.6')
    :type php_vers: string
    :param write_log: write error messages to log or not
    :type write_log: bool
    :param force: recreate symlinks even when they exist
    :type force: bool
    z.cagefsi  TzError :N)r!   r4   r   r   r   rV   Zmake_userdirr   r   r?   r   r  rB   r   r   r  r   r   r  r  r   )
r+   r  r  Z	drop_permr   Zconfigure_multiphpZreal_homepathr4   r  r5  r/   r/   r0   configure_alt_php0  s&    r  c             C   s   | dkrdS | t  kS )Nr  F)rV   get_alt_versions)r  r/   r/   r0   php_version_is_removedZ  s    r  c             C   s   |d ko| |ko||   S )Nr/   )r  cl_alt_def_php_stater/   r/   r0   php_version_is_disabled`  s    r  c       &      C   s  t | |} d}td}x| D ]~}tj|}t|}	d|	 d | }
t|
 }tj	|r t
j}|| }t
|drzq t
||j|j |t
j }t
|drq t
||j|j t
 \}}}}t
|j|j|j\}}}}|}|d ks|d krDt|st||rD|d ks:|d kr@t|s:t||r@d}n|}d}x t
jD ]}|}|dkrrt
|}n&t
||}|d kr|}n
t
|}t
jd | }|| }tj|s<t
| yt|| |dkrd}W nR ttfk
r6 } z.td| d	 t| d
d t!d d}W d d }~X Y nX qR|rRyt"|} W n4 ttfk
r   td| t!d d}wRY nX | #drRtj$| \}!}"tj$|\}#}$d }%|!|#kr|"|$kr|}%|%d krRyt%| t|%| W nR ttfk
rD } z.td| d	 t| d
d t!d d}W d d }~X Y nX qRW t
&||j|j|j|||||||| t'(||||j|jrd}t)|||dr d}q W t| |S )NFr   ro   i  r  zphp.iniTz!Error : failed to create symlink z : r  zErr coder>   zError: failed to read symlink z/opt/alt/php)r   )*r  r!   r"   r   r   r   r   r  r4   rJ   rV   ETC_CL_ALT_PATHr  rZ  r   r   r  read_cl_alt_defaultsread_cl_alt_backup_as_userr   r  r  r  get_usr_selector_pathget_alt_confr   r  r  rB   rA   rC   r  r  rD   r  rr   r&  r   Zselect_default_php_modulesr[  Zcreate_php_ini_for_DAr  )&r;   r  repair_symlinksreset_modules_to_defaultrebuild_alt_php_inir5  r,   r<   r+   r   r   r  LINK_DIRlink_dirZuser_php_dircl_alt_def_verscl_alt_def_modulesr  cl_alt_def_otherdef_versphp_modulesphp_state_ignoredother_ignoredZdef_vers_oldchangedr)  r  ZLINK_TOZalt_pathZ	LINK_NAMErA  r  r  Zlink_to_dirnameZlink_to_filenameZ_dirnameZ	_filenameZrepairedr/   r/   r0   r  e  s    







"


"
r  c             C   s$   | sd } t | ddd t| d d S )NT)r;   r  r  )r;   )r  r  )r;   r/   r/   r0   r    s    r  c             C   s$   | sd } t | ddd t| d d S )NT)r;   r  r  )r;   )r  r  )r;   r/   r/   r0   r    s    r  c             C   s*   | sd } dt _t| ddd t| d d S )NT)r;   r  r  )r;   )rV   Zvalidate_alt_php_inir  r  )r;   r/   r/   r0   check_php_ini_options  s
    r  c             C   s8   | r4| d dkr4| d d dkr4| d  d7  < dS dS )Nr   r   r   r{   TFr/   )r.  r/   r/   r0   r]    s     r]  c             C   sB   | r>t t}t| ||  t t| ttd t  d S )Ni  )	rV   r  rw   r]  r(  r^  r!   r(   r  )	new_linesr.  r/   r/   r0   write_cagefs_mp   s    

r  c              C   sz   t jdrvt jtrvg } tdd| dd g }td}x2|D ]*}|| kr@t j|r@d| }|| q@W t| dS )zf
    Add mount points like "@/var/cpanel/php/sessions/ea-php56,700" to /etc/cagefs/cagefs.mp file
    z/var/cpanel/php/sessionsT)r   r   r   r  z/var/cpanel/php/sessions/ea*z@%s,700
N)	r!   r4   rJ   r5   rw   r   globr9   r  )r   r  Zphp_dirsr  	mount_strr/   r/   r0   r     s    

r   c              C   s   g } t dd| ddt_g }dtjkrDdtjkrDtjd |d t }xP|D ]H}d| }d| }|| krx|| d| }d| }|| krR|| qRW t| d	S )
zU
    Add mount points for php selector and alt-php to /etc/cagefs/cagefs.mp file
    T)r   r   r   r  z	/opt/alt
z/opt
z/opt/alt/%s/linkz@/opt/alt/%s/link,700
z/opt/alt/%s/var/lib/php/sessionz%@/opt/alt/%s/var/lib/php/session,700
N)r   rV   r   r9   r  r  )r   r  r  r  Z
mount_pathr  r/   r/   r0   r     s"    


r   c              C   s   t dd t D } | dd t D  tt}g }td}d}xR|D ]J}||}|r|	d| ks~|	d| kr|
| qd}qP|
| qPW |rtt| ttd	 t  d
S )z^
    Remove mount points for uninstalled alt-php versions from /etc/cagefs/cagefs.mp file
    c             S   s   g | ]}d | qS )z/opt/alt/%s/linkr/   )r  r  r/   r/   r0   
<listcomp>:  s    z2remove_mounts_for_php_selector.<locals>.<listcomp>c             S   s   g | ]}d | qS )z/opt/alt/%s/var/lib/php/sessionr/   )r  r  r/   r/   r0   r  ;  s    zB@(/opt/alt/php\d\d/link),|@(/opt/alt/php\d\d/var/lib/php/session),Fr>   r   Ti  N)r   rV   r  r  r  rw   r  r$  r'  r  r9   r^  r!   r(   r  )Zneeded_mountsr.  r  r)  r  r   r  r/   r/   r0   remove_mounts_for_php_selector6  s"    



r  c              C   sx   t jtsdS d} g }tdd|d}| |krt| |krttt}t| |d|   t	t| t 
td t  dS )zJ
    Adds mount point for default location of PHP APM DB
    :return:
    Nz/var/php/apm/dbT)r   r   r   z@%s,777
i  )r!   r4   r5   rw   r   rV   r  r]  r9   r^  r(   r  )Zpath_to_addr   r   r.  r/   r/   r0   add_mount_for_php_apmO  s    
r  c              C   s   yt dj} W n tk
r$   dS X t }d}x|D ]}d| }d| }yDtj|sdt	|d t
|d|  t|d  t
|d|  W q8 tk
r } ztdd	t| d
}W dd}~X Y q8X q8W |S )z
    Cretate /etc/cl.php.d/alt-phpNN directories for all alt-php versions (in real filesystem) with group owner 'linksafe'
    for details see CAG-532, CAG-454
    Return True if error has occured
    r  Fz/etc/cl.php.d/alt-%sz /etc/cl.php.d/alt-%s/alt_php.inii  r   r`   zfailed to configure linksafer  TN)r  r  r  r:   rV   r  r!   r4   rR   r   r  r#   r'   rB   r   r*   r  )r  r  r5  r  Zetc_php_dirZalt_php_inir  r/   r/   r0   r%  f  s&    

r%  c             C   sx   xrt | D ]d}|drqt j||}t j| |}t j|sNt| qt j|rt j|st	|| qW dS )z
    Delete from cagefs_dir files/dirs that do not exist in orig_dir
    :param cagefs_dir: path to dir in CageFS (dir to delete files from)
    :type cagefs_dir: string
    :param orig_dir: path to original dir
    :type orig_dir: string
    z.cagefsN)
r!   r   r   r4   r   r?   r  rJ   r   clean_dir_recursive)
cagefs_dirZorig_dirry  r   Zcagefs_pathr/   r/   r0   r    s    

r  c             C   s  t  s
dS ddddd}d}d}t }|s.dS y|d	 }W n tk
rN   dS X x|D ]}|d
rXx|D ]}|| }	dt|	f }
d||	f }tj|	rptj|st  t	
|drt  td | r0ttdddd||
g}|dkrttddd||
g}|dkrbtd| td qpx.t|	D ]}|drTq>tj|	|}tj||}tj|rt	j||ddr>td| d | td td q>||kr||krt|| |r t	| t|| |r td |d7 }t	j||dddr>t	| t	j||ddr>td| d | td td q>W qpW qXW | s~t|d d |dk	r| st	jt }tj|rt	j t|ddrt!| dS )z
    Setup CageFS for integration with cPanel MultiPHP
    For details please see CAG-445
    :param do_mount: when True, do mounting; when False, do copying files to CageFS
    :type do_mount: bool
    Nz/etc/cl.selector/ea-phpz/etc/cl.selector/ea-php-cliz/etc/cl.selector/ea-php.iniz/etc/cl.selector/ea-lsphp)zphp-cgir  zphp.inir  z"/usr/share/cagefs/.cpanel.multiphp)z/opt/cpanel/%s/root/usr/binz/opt/cpanel/%s/root/etcrG  zea-phpz%s%si  r>   z-nz-orH   z--rbindr   zremount,ro,nosuid,bindzfailed to mountz.cagefsT)r  zError copying z to F)r  r  )r  z/opt/cpanel)Z	use_cache)"r   r  r:   rr   rI   r!   r4   rJ   r  rV   r  r  rE   rF   rL   rM   rK   r   r*   r   r   r   r  rC   rD   r  Zkill_phpr  r  r  r  r5   Zis_update_neededr+  )r  r  ZSYMLINK_NAMESZCAGEFS_PHP_BASEDIRZDIRS_TO_MOUNTr  r  r)  r4   ZoptdirZcagefs_optdirr  rP   ry  r   Z	dest_fileZphp_confr/   r/   r0   r    sz    








 r  c          	   C   s|  t   t }t p|}tt t  tj	dsXtj	drXtj
d}t|d t }|rddlm}m} |  || tjdsytdd t  W n, ttfk
r   td td Y nX t  t  t  td	d	d
 t rt| d	dp
|}x"tj ! D ]\}}tj
|}	|"dsptj#|rpt$|spt|t| dkrpd	}t% r|dkr|	"dstj&|	rt$|	st|	t|	 dkrd	}t'|rd	}q|	"dst$|	r t|	d d	}n,tj(|	ddst)|rtd| d	}qW |rN|sNdd l*}
|
+  t,d| d | d sjt-  |sxt.d d S )Nz/usr/local/bin/lsphpz/usr/local/lsws/fcgi-bin/lsphp5r   )litespeed_configure_selectorreplace_alt_settingsz/opt/alti  z#failed to create directory /opt/altr>   T)r  r  )r'  z/etc/)r  zphp-clir  zphp.iniz@is mounted to CageFS. CloudLinux Selector will not be available.F)r  z)CloudLinux Selector setup error for path:)r  r  zskip-php-reloadz%CloudLinux Selector setup: successful)/rj  r$  r%  r[  r\  rI   Z"configure_selector_for_directadminr!   r4   r5   r   rV   r  r  r   r  r  r?   r   r  rB   rA   r   r*   rE   rF   r   r   r  r  Zis_etc_in_native_confr+  r  r   rr   r   r  r   rR   Zcreate_php_stubr!  r"  cagefs_ispmanager_libZ!configure_selector_for_ispmanagerr  r  r   )r  rC  r5  Z
lsphp_pathZaltr  r  r)  r   r*  r	  r/   r/   r0   setup_cl_alt  sl    





""

r
  c             C   s  t | |} t \}}}}t }t|}|d kr:d}	nF|dkrHd}	n8||ks`||kr||| s|d}	td |	|dd|| n|}	d}
|d krd|kr|d sd}
d}xX| D ]N}tj|}t	|}d| d | }t
| }tj}|| }tj|rd}xt|	D ]~}t|}|	dkr*|}nt|	|}|d krDq
|d | }tj|s|dkrld}t| yt|| W n0 ttfk
r   td| td d}Y nX nyt|}W n4 ttfk
r   td	| td d}w
Y nX ||kr>|	dkr>|
s|r>|dkr,d}t||rd}nJ|||fkr
|sj||ksjtj|s
|dkrxd}t||r
d}q
W t||	|d
rd}|rtd| t|j|j |j!\}}}}|d ks||	kr|rt|j|	||j |j! qW |S )Nr  r   FTro   zphp.inizError while creating symlink r>   zError: failed to read symlink )r   r  )"r  rV   r  r  Zget_alt_pathsZwrite_cl_alt_to_backupr   r   r   r   r  r  r!   r4   rJ   Zget_alt_aliasesr  r  r   r  r  rB   rA   rC   rD   r  r  r?   r  r   r  r   r   r   )r;   r  r   r  r  r  r  Zalt_versionsZ	alt_pathsZ	dest_versZnative_php_is_disabledr5  r<   r+   r   r   r  r  r  r  r  Znative_pathr  rA  r  r  r  r  r  r/   r/   r0   remove_etc_alternatives9  s    







 
,


r  c              C   s<   y"t dd} |  }|   t|S  tk
r6   dS X d S )Nz/proc/lve/listrU   F)r#   rX   r'   boolrA   )r]   r   r/   r/   r0   kernel_is_supported  s    
r  c               C   s$   t  s t  td td d S )Nz.Error: current running kernel is NOT supportedr>   )r  rj   r   rC   rE   rF   r/   r/   r/   r0   check_kernel  s    
r  c               C   s   t t d S )N)ra  config_copyr/   r/   r/   r0   do_profiling  s    r  c              C   sl   t jtsdS y0ttdg} | dkr>tdt td dS W n& t	k
rf   tdt td dS X dS )NFz--toggle-pluginr   zError: r>   TzError: failed to run )
r!   r4   r5   PLUGIN_STATErL   rM   r   rC   rD   rB   )rP   r/   r/   r0   run_toggle_plugin_utility  s    r  c               C   s
   t   d S )N)r  r/   r/   r/   r0   toggle_plugin  s    r  c             C   s:   t  r$| tdkr$td td td td d S )NTEnabledr   Disabledr>   )r   r   r   rE   rF   )r<   r/   r/   r0   print_user_status  s    
r  c               C   s.   t  rtd td td td d S )Nr  r   r  r>   )r   r   rE   rF   r/   r/   r/   r0   print_cagefs_status  s
    
r  c             C   sB   t jddd}y||  W n t jk
r2   g S X t|| dS )z, Read paths separated by commas from a file NF)ZinterpolationrK  r  )rL  ZConfigParserrt  rd   rV   r  )r  r  r/   r/   r0   read_paths_from_file  s    r  c          
   C   s   t |}t|}td}yt| d}|d|   |rF|d|  |d x>tt|D ].}|dkr~|d||   q^|||  q^W |d |  W n< t	k
r } zt
d	|  d
 t|  W dd}~X Y nX t| dS )z! Write paths from list to a file r   r`   z[%s]
zcomment=%s
zpaths=r   z, r{   zFailed to write z : N)rE  rl  r!   r"   r#   ra   r   r   r'   rA   r   r*   r  )r  r  commentr,   r]   indexr  r/   r/   r0   write_paths_to_file  s$    



,r  c       	      C   s4  t   tjtjd s,td t	d t
 t_tj }d}x|D ]}|drHd}P qHW |rttjd d tjtjd syttjd d W n0 tk
r   tdtjd  t	d Y nX ttjd tjd ddkrtd	 t	d d}g }x|D ]}| }|d
rtj|sFtj|r|drtj|tj| ddst| d}|| n4t|stj|t| ddst| || qW |rt  t st rt |  t!d }t"|}|#| t$||d g }t%t&| t'|| |#| t(| dS )zH Read paths from stdin and updates appropriate files in cagefs-skeleton z/etcz&skeleton of etc directory is not foundr>   Fz/etc/Ti  r  z.Error while creating skeleton of etc directoryro   )r  zcagefsctl-update-list.cfgz0Files added by "cagefsctl --update-list" commandN))rj  r!   r4   rJ   rV   r  r   r*   rE   rF   r   r   r?  r   rr   rc   r   r  r   rB   r  r8  r5   r   r  r   r9   r  rI   r  r   rT   r&  rM  r  r(  r  r  r  r  r   )	r  filesZ	etc_foundr  Zetc_modifiedZcopied_filesZUPDATE_LIST_CFG_FILEr  r  r/   r/   r0   update_list   sb    




 


(



r  c                s    fdd}|S )Nc                  s   t   t  d S )N)r!   setgidsetuidr/   )gidr   r/   r0   funcF  s    
zdemote.<locals>.funcr/   )r   r   r!  r/   )r   r   r0   demoteE  s    r"  c              C   s  t j } t }tt }|d tj	
dr>|d t snt snt }x|D ]}|d|  qXW tdd}x| D ]}| }| | }tj	|jd}	tj	
|	r~||	 x6|D ].}
tj	|jd|
 }tj	
|r|| qW tj|||t|j|j|jd q~W d S )	Nz/var/cache/php-eacceleratorz/var/lib/php/sessionz/opt/alt/%s/var/lib/php/sessionz	/dev/nullr`   z.cagefs/tmpz.cagefs)r0  r  Z
preexec_fncwd)r   r   r   rV   Zget_tmpwatch_paramsr   Zget_tmpwatch_dirsr  r!   r4   rJ   r
   r	   r  r#   r&  r   r   r9   rL   rM   r"  r   r   )r+   Ztmpwatch_commandZtmpwatch_dirsr  r  Zdev_nullr<   rO   r   r   Zdir_namer  r/   r/   r0   tmpwatchL  s,    







r$  c              C   s2   t  } x$| D ]}| | jddkrdS qW dS )Nzcagefs-skeletonr   TF)r   r    r   rM  )r+   r<   r/   r/   r0   r  k  s
    
r  c             C   sB   g }x8| D ]0}t |r"|| q
td|d td q
W |S )Nr<   zdoes not existr>   )r   r9   r   r*   rE   rF   )r|  r;   r   r/   r/   r0   get_users_from_argsv  s    
r%  c             C   s   yt j| }W n tjk
r&   dS X t| }t  |tkrtj	
trntj	
td t| d |  rndS tj	
trtj	
td t| d |  sdS dS )z,
    Check that cagefs enabled for user
    Fro   T)r   r   r   r   r   r   r  r   r!   r4   rR   r   r  r   )r   r   Zuser_prefixr/   r/   r0   is_user_enabled  s    ,,r&  c             C   sb   t d t|  d |  d }t| |}t||}t| |dd|d t| | t| | d S )Nro   z/etcF)ry  r  r  )r  r   rV   r  r  r  r  r  )r   r  r  r  r  r/   r/   r0   cpetc_for_user  s    r'  c           
   C   s   yt jtsd S ttd} |  }|   dd |D }x2tD ]*}d| }||kr@t j|r@|	| q@W dd |D }ttd} | 
| |   W n6 tk
r } ztdt|tjd W d d }~X Y nX d S )	NrU   c             S   s   g | ]}|  qS r/   )r8  )r  lr/   r/   r0   r    s    z0add_spamassassin_dirs_cpanel.<locals>.<listcomp>r   c             S   s   g | ]}|d  qS )r{   r/   )r  r(  r/   r/   r0   r    s    r`   zError:)r\  )r!   r4   r5   rw   r#   r   r'   r   rJ   r9   
writelinesrB   r   r  rE   r0  )r]   Zcagefs_mp_linesr   Zline_to_check_and_writer  r/   r/   r0   add_spamassassin_dirs_cpanel  s"    



r*  c             C   sV   xP|D ]H}t jtt|| gt jt jdd}| \}}|jrt|	 t
t qW dS )z
    Unmount path for users.
    Enter to LVE and unmount director without destroy LVE.
    :param: path `str` path for unmount
    :param: users_list `list` list of mounted users uid for process unmount
    :return: None
    T)r  r0  r  N)rL   r!  
LVE_UMOUNTr  r"  r#  r3  r   rC   r8  rD   r?  )r4   
users_listZuser_uidr6  r  Zstrerrr/   r/   r0   unmount_dir  s    
r-  c             C   s   yt j| }W n$ tjk
r4   t d| d dS X t| }tj	t
|| d }tj|}t|d t|ddd}t| grt d|  dS dd	t|jd
dg}ytj|dd W n tk
r   t j|  dS X dS )z
    Unmount CageFS for user. Return True if error has occured
    :param user_name: name of user
    :type user_name: str
    ZUserzdoes not existsTz.locki  )ru  rv  z$Failed to destroy/apply LVE for userz/bin/lve_suwrapperz-mekz/usr/sbin/cagefsctlz--unmount-cur-nsF)shell)r   r   r   r   r   r*   r   r!   r4   r   r  r   rV   r  rw  rH  r  r   rL   rM   rB   )Z	user_namer+   r   Z	lock_pathr  r  rO   r/   r/   r0   unmount_user  s(    

r/  c               C   s   t jt jtdS )z=
    Checks that cagefs skeleton exists and is not empty
    bin)r!   r4   rJ   r   rI   r/   r/   r/   r0   ri    s    ri  c               C   s$   t  stt td tt d S )Nr>   )ri  r   SKELETON_NOT_INITIALIZEDrE   rF   SKELETON_INITIALIZEDr/   r/   r/   r0   print_cagefs_skeleton_status  s    
r3  c           
   C   s   dd l } | td y
t  W nn tk
rT } zttt| W d d }~X Y n< t	k
r } zt
j| jdd td W d d }~X Y nX d S )Nr   Z	cagefsctlT)levelZincludetracebackr>   )syslogZopenlogr   	main_func
SystemExitrE   rF   rZ   r  r)   rV   print_exceptionZLOG_ERR)r5  r  r/   r/   r0   main  s    
"r9  c               C   s   t   tt_ttdt_d S )N)Zmin_uid)r  r   r   r   r   r/   r/   r/   r0   init_min_uid  s    r:  c        $   b   C   s  yt  tjdd  dddddddd	d
ddddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_g^\} }W nD t jk
r  } z"t  td`t| td W d d }~X Y nX dad l}dad l	}dadbl
m} |t}|  i }da|d< x| D ]\}}	|dckrt  tda nl|ddkrtt tda nN|dekrt  tda n2|dfkrd|d< dadt_n|dgkr`dadt_q`W t dakrtdh tdi ytjtatt_W n*   tjdjt dk  td Y nX da|dl< da|dm< da|d< da|d< da|d< da|d	< da|d< da|d< da|d< da|d
< da|d< da|d!< da|d)< da|dV< dn|d4< dn|dF< dn}
dn}do}dn}
x| D 	]\}}	|dpkr tt|	 tda q|dqkr:d|d< do}q|drkrt|dakrftds tdt x|D ]}y<tj !t"|}x&|D ]}t#|j$| t%|j$ qW W nT t&t'j(fk
r    t)|rt#|| t%| ntdu|dv td Y nX qlW tda q|dwkr4t*  tda q|dxkrJdo|dF< q|dykrnt+  t,  tda q|dzkrdad l-}|.  tda q|d{krt/0  tda q|d|krt/1  tda q|d}kr|2  tda q|d~kr|3  tda q|dkr@t4  t5|dk tda q|dkrht6|}t7| tda q|dkrt6|}t8| tda q|dkrt6|}t9| tda q|dkrt6|}|rt:||dkd nt:do|dkd t;  tda q|dkrVtj<ds6tj<t=s6t>?  nt@dodn|dkd tda q|dkrt|dakrtd tdt tAtB }x|D ]}tC|| qW tda q|dkrtD  tda q|dkrtE|	 t4  tda q|dkrttF tda q|dkr:tG|	 tda q|dkrbd|dV< d|d< do}tH  q|dkrtI  tda q|dkrtJdod tda q|dkrtKdod tda q|dkrtL  tda q|dkrtM t_NtOt tda q|dkr,tP  tda q|dkrJtQ  tda q|dkrpt4  tR|	 tda q|dkrtS  tda q|dkrtT  tda q|dkrtU }tV  tWdo|d tX  tda q|dk	r2|dk	r tBdod tY 	r$tU }t4  tW|dk|d tda q|dk	r|	rtZ }|dk	rtU }x|D ]}t[|do 	q^W tW|do|d n8|dk	rtU }x|D ]}t[|dn 	qW tW|dn|d tda q|dk	rt\  tda q|dk
rtH  tM t_Nt]  t^  tda q|dk
r*dn}q|dk
r<do}q|dk
rtU }t_  t`  tW|d tH  ta  tbdo tda q|dk
rtc  tda q|dk
rtd  tda q|dk
rte|	 tda q|dkr.ttjdkrtd td |ftjdt  tda q|dkrN|f  tda q|dkrt|dkrztd td |f|da  tg  tH  ta  d|d!< do}
q|dkr:tg  tH  t  ta  td|	d tdh|	|	 ytijjdd|	dgdnd W n* tkk
r,   td td Y nX tda n|dkrVtl  tda n|dkrztm rntn  tda nr|dkrtB }to|ddÃ tda nJ|dkrtp }to|ddŃ tda n"|dkrtqdndododǍ tda qW t  |rtr|dȍ}ts }t4| ttdɡdkrBtjudˡrBtv rBtw  x| D ]\}}	|dkr~tH  ta  tb  tda qJ|dkrtH  tq  tda qJ|dkrdot_xqJ|dkrd|d)< do}qJ|dkrdoayqJ|dkrtg  d|d< do}
qJ|dkrZtU }t_  t`  tW|d tH  ta  tz rDt{| tbdo tda qJ|dkrtg  tH  ta  d|d< do}
qJ|dkrtg  d|d< do}
qJ|dkrt|  tda qJ|dkrtg  tH  ta  tbdo tda qJ|dkr"tg  tH  ta  d|d!< do}
qJ|dkrvtU }tH  ta  t}do tW|d tz r`t{| tbdo tda qJ|dkrtU }t}dn tW|d tX  tda qJ|dkrt~  tda qJ|dkrd|d	< do}tH  qJ|dkr
d|d< do}tH  qJ|dkrtjutd rHtdttjda f  td d|d< do}tZ }|dksn|dkr t s t}dn qJ|dkrd|d< do}tH  qJ|dkrd|d
< do}qJ|dkrtdo tda qJ|dkr
x|D ]}t| qW tda n|dkr8x|D ]}t| qW tda n|dkrTt  tda n|dkrrt| tda n|dkr|dk|d4< t6|}|rt||d nt| tda nH|dkrt| tda n*|dkrJt r|j|d tda qJW |
r*|r*t  td td |
rVt|dakrVt  td tdt |d dkrpttj y|d dkrdn}x|D ]}t|p|}qW tt"| nj|d dkr(tU }g }x@|D ]8}t)|rt[|dn || ntd| d  qW tW|dn|d t| n|d! dksD|d dkrtU }tb  g }x|D ]}t)|r||kr|d dkrt[|do tz rt{||gdn || n |d dkrtd| d  ntd| d  qZW |d dkrtW|do|d t| ntd tdt W n. tk
rP   t  td td Y nX n|rt}|d r|d s~|d rtd td |d |d  |d  |d	  }|d) dakr|dkrtd td |d dkrtB }t|}|dakr td|d td td tY r@d|d< tV  tWdod t@dodnd yBt|d } t| tj r~t|d  nt|d  W n tttjfk
r   Y nX yt||d  W n ttfk
r   Y nX yt|d  W n ttfk
r   Y nX |d) dkr|a|dkrBdad l}!|!dtd  dad l}"|"td }#t  td td |#dd t  td td |#dd n4t| |d s|d rda |d< |d< t| nt  td d S (	  Nr>   zihvVfurdkwW?lmMe:r  z
dont-cleanr  helpversionr  r   r  r  z
remove-allzset-tmpwatch=r$  r   re  zunmount-dirzunmount-allzunmount-really-allr   Zdisablez
enable-allzdisable-allzdisplay-user-modezlist-enabledz	wait-lockzlist-disabledz	create-mpzcheck-mpz
mount-skelzunmount-skelzremount-allrH  rs  rw  zenter=zenable-cagefszdisable-cagefsz
do-not-askdebugZ	profilingzmigrate-prefixesz
getprefix=zlist-rpmzapply-global-php-inizset-min-uid=zget-min-uidztoggle-moderp  Zcpetcz
update-etczforce-update-etczcheck-kernel-versionzupdate-wrapperszremove-blacklistedzdetect-postgresztoggle-pluginzprint-suidszhook-installzhook-removezreconfigure-cagefszconfigure-litespeedzclean-var-cagefszuser-status=zcagefs-statuszupdate-listzrebuild-alt-php-inizvalidate-alt-php-inizsetup-cl-selectorzskip-php-reloadzcheck-for-unsafe-mountszremove-cl-selectorzcl-selector-reset-versionszsetup-cl-altzremove-cl-altzcl-selector-reset-moduleszupdate-users-statuszupdate-users-status-fix-ownerzset-default-user-statuszremove-unused-mount-pointszcreate-homeN-dirs-in-skeletonzunmount-cur-nsz enable-cagefs-without-etc-updatezwithout-lockzset-update-period=zforce-updatezadd-default-rpm-packageszcreate-virt-mpzcreate-virt-mp-allzremount-virtmpzlist-logged-inzclean-config-dirsz"create-dirs-for-symlink-protectionzsanity-checkzcheck-cagefs-initializedz
Error:r   )
ClAuditLog)z-hz-?z--help)z-Vz	--version)z--check-kernel-version)z-vz	--verbose)z--silentz root privileges required. Abort.r   z8Error while determining real path to skeleton directory r{   zdry-runinteractiveFT)z--getprefix)z-dz--dont-clean)z--cpetczno username or UID specifiedr   zuser or UIDzdoes not exist)z--clean-config-dirs)z--skip-php-reload)z$--create-dirs-for-symlink-protection)z--sanity-check)z--hook-install)z--hook-remove)z--reconfigure-cagefs)z--configure-litespeed)z--list-enabledz--list-disabledz--list-enabled)z--cl-selector-reset-modules)z--rebuild-alt-php-ini)z--validate-alt-php-ini)z--cl-selector-reset-versionsz--remove-cl-selectorz--remove-cl-altz--cl-selector-reset-versions)r;   r   )r  r   )z-Wz--unmount-allz--unmount-really-allz/etc/cagefs/etc.safez--unmount-really-all)r  r  rd  )z--unmount-dirz!no directory to unmount specified)z--migrate-prefixes)z--set-min-uid)z--get-min-uid)z--set-update-period)z--force-update)z--clean-var-cagefs)z--update-wrappers)r/  )z--remove-blacklisted)ri   )z--detect-postgres)z--print-suids)z--toggle-plugin)z--display-user-mode)z--user-status)z--cagefs-status)z--check-cagefs-initialized)z--disable-cagefs)rd  r  )z--update-users-statusz--update-users-status-fix-ownerz--update-users-status-fix-owner)r  )r  r  )z--set-default-user-statusz
Enable All)r;   rX  r  zDisable All)z--remove-unused-mount-points)z--create-homeN-dirs-in-skeleton)	z-wz	--unmountz-mz	--remountz--enablez	--disablez--mount-skelz--unmount-skelz--without-lock)z--wait-lock)z"--enable-cagefs-without-etc-update)r  )z--add-default-rpm-packages)z
--tmpwatch)z--set-tmpwatch)z--create-virt-mpr9  zNo username provided)z--create-virt-mp-all)z--remount-virtmp)z--enterz-ez#You are entering to CageFS for userzas superuser (root).zNNOTE: You can use "su -s /bin/bash - {}" instead to enter to CageFS as user {}z/sbin/cagefs_enter_userz--rootz	/bin/bash)r.  z!executing /sbin/cagefs_enter_user)z
--check-mp)z--check-for-unsafe-mounts)z-lz--listz#CageFS currently mounted for users:)z--list-logged-inz)Users currently logged in CageFS via ssh:)z--unmount-cur-ns)ri  rd  rj  )ru  r  r   z/var/cpanel)z--mount-skel)z--unmount-skel)z--debug)z--profiling)z--do-not-ask)z-wz	--unmount)z--enable-cagefs)z--enable)z	--disable)z--remove-all)z-Mz--remount-all)z-mz	--remount)z--enable-all)z--disable-all)z--toggle-mode)z-fz--force)z-uz--update)z-iz--initz/binzYError : directory %s already exists.
Use "%s --reinit" if you want to reinitialize CageFSrd   zNot Initialized)z-rz--reinit)z-kz
--hardlink)z--create-mp)z--addrpm)z--delrpm)z
--list-rpm)z--update-list)z--update-etcz--force-update-etcz--force-update-etc)r;   )z--setup-cl-selectorz--setup-cl-alt)z--apply-global-php-ini)rC  z&
Error: incompatible options specifiedzaborted, no username specifiedzuser z does not existz is excludedz&No options specified. Nothing to do...z
aborted.. z;cannot specify --dont-clean with --init or --reinit optionszLyou should specify one of the --init, --reinit, --update or --force options
z	WARNING: zCageFS currently mounted.zBIf you proceed, CageFS will be temporarily disabled and unmounted.z"Do you want to continue (yes/no)? rR  )rd  )r  r  z.oldi  zcagefsctl.do_profiling()z/profiling.logz&--------------------------------------zCumulative time:Z
cumulative   zTotal time:rF  )getoptrE   r   ZGetoptErrorrg  r   r  rF   r   virtmp_mountclcommonr>  INFO_LOG_FILEZinfo_log_writecagefs_versionr  r?  rV   ZVERBOSE_FLAGrD   r   ZSILENT_FLAGr!   geteuidr*   r4   r   rI   r0  ra   r   r   r   r  rZ   r'  r  r  r[   r   r   r   r   r%  r$  sanity_checkZcheckcagefshooksZHooksInstallZHooksRemoveZreconfigure_cagefsZlitespeed_configurer   r   r%  r  r  r  r  r  rR   r=  re  Z
umount_allr  rD  r  r-  r  r  r   Zset_update_periodrj  r   r0  r  Zdetect_postgresr   r   Zprint_suidsr  r   r  r  r3  r   r   r_  rK  r   r   r   r   r  r  r   r  r  r  rT  r$  Zset_tmpwatch_paramsZcreate_virtmpr   r  rL   rM   r)   r_  r  r  r   r,  rm  rw  r   rM  rJ   r  r{  rV  rb  rT   r&  rf  r   r  rC   r   r   rs  rw  r{  r  r+  r
  r  r  unshareZCLONE_NEWNSr/  r9   rH  KeyboardInterruptrc  r  r  r  ST_MODErc   r   r   rB   rA   rd   r   r   r  profilerunrW  pstatsZStatsZ
sort_statsZprint_statsra  )$Zoptsr|  r  r   rB  r>  r  r  or  Zmanage_user_flagZbuild_jail_flagZlock_is_requiredZ	wait_lockr   r   r+   rG  r;   r,  rh  r  r   rp  r   Z	user_moder~  r5  Z	usernamesr   Zcount_of_modesr   ZjbufrL  rN  r6  r/   r/   r0   r6    sv   





















































































































































 










r6  __main__)N)NN)F)NF)F)T)N)r   r;   )F)N)F)F)N)rZ  )TFFF)FF)FF)F)FFF)N)N)N)F)F)NF)F)F)F)F)F)F)F)F)FFFN)N)NTF)N)FNNFN)NFF)NF)TT)TT)TT)TTTT)NFFFF)N)N)N)FN)N)NFF)N(d  Z
__future__r   r   r   r   Zfuturer   Zinstall_aliasesbuiltinsZfuture.utilsr   r!   r7   r  rE   rL  rA  stringrc   rL   r   r  rF  rn  r  r  r
  r%   r[  r  r  r   Zcldetectlibr	   r
   Zclcommon.utilsr   r   r   r   rC  r   r   r   r   Zclcommon.clfuncr   r   rV   r   r   r   r   rH  r   rI  r;  r2  rK   r+  r  rI   ZSKELETON_NAMErW  r   Z	MP_PREFIXrM  rw   rx   ZLOCKNAMEr  ZFUSE_SAFE_LISTr  r  rU  r$   rN  r   r   r   r  r`  rS   r  r  rV  r@  r  r@   ru  r=  r  rD  r  r  rm   r   r   r2  r1  r&  rt  rE  r4   r9   re  Zsignals_handlersr   r   r   r1   r8   r=   rG   rQ   rT   r_   rb   rg   rh   rD   r?  rj   r  rq   ZMYSQL_SOCK_DIRr   r   r   r   rn   rt   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Zascii_uppercaseZdigitsr  r	  r
  r  r  r  r  r  r  r,  r/  r7  r8  r=  r>  rB  rC  rD  rE  rH  rK  rL  rN  rO  rU  rW  rY  r[  r_  ra  rb  rm  rr  rh  rw  rz  r{  r|  r  r   rf  r  r  r  r   r  r  r  r  r  r  r  objectr  r  r  r  Zmounts_are_found_comparatorr  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r  r+  r0  r1  r4  r:  r,  r;  r  r  rB  rF  rJ  r  rO  ra  rb  rc  rf  rg  rj  rl  rs  rw  r{  r  r  rT  rS  r  r  r  r  r  r  r  r   r  r  r  r  ZCL_ALT_NAMEZCL_PHP_DIR_NAMEr  r  r  r  r&  r  r_  r  r  r^  r  r  r  r  r  r  r  r  r  r  r$  r  r  r  r  r  r  r  r  r]  r  r   r   r  r  r%  r  r  r
  r  r  r  r  r  r  r  r  r  r  r  r  r"  r$  r  r%  r&  r'  r*  r-  r/  ri  r3  r9  r:  r6  r  r/   r/   r/   r0   <module>	   s  
d'  
E
6!
	+
$
_)$_ [ %>	*+#0
 C6W,&T(O
(!>* |NVj
	
E
%     
