9Mj9dZddlZddlZddlZddlZddlZddlmZddlm Z ddl m Z ddl m ZddlmZmZdd lmZmZmZejeZd Zd Z dd lmZmZmZdd lm Z n#e!$rdZdZdZdZ YnwxYwde"de"fdZ#de"de"de"de e"fdZ$de"de"ddfdZ%d"de e&de'de"de"fdZ( d#de"de'de'de"de'de e&de"ddfd Z)de"de"ddfd!Z*dS)$z Website isolation support for X-Ray INI files. This module provides functions to manage xray.ini files in per-website directories when CageFS website isolation is enabled. N)iglob)Optional) disable_quota)docroot) user_contextcagefsctl_get_prefix)is_excluded_path$get_domain_php_version_from_selectorINI_USER_LOCATIONSii)(is_website_isolation_allowed_server_wideis_isolation_enabled#get_websites_with_enabled_isolation)get_website_idcdSNFr]/opt/cloudlinux/venv/lib64/python3.11/site-packages/xray/reconfiguration/website_isolation.pyr r =urcdSrrusers rrr@rrcgSNrrs rrrCs rrdomaincDtsdS|t|vSr)r r)rrs ris_per_website_php_selectorrIs) 3 5 5u 8>> >>r website_id php_ver_dirreturnc Ft|}|dSd|d|d|d|d S)a Build path to xray.ini in per-website directory. :param user: Username :param website_id: Website ID hash :param php_ver_dir: PHP version directory (e.g., 'alt-php80') :return: Full path to xray.ini or None if cagefs prefix not available Nz /var/cagefs//z/etc/cl.php.d/z /xray.ini)r)rrr prefixs r_get_per_website_ini_pathr%OsD"$ ' 'F ~t Z& Z Z4 Z Zz Z ZK Z Z ZZrc  t||sdSi}d}d}tD]}t|dD]}t|r |d|}|j|kr1|j}|j}n+#t$rt d|YgwxYwtj |d}tj |s tj|tjtjztjz} nw#t$$rj} | jt&jkr!td|Yd} ~ &td|t/| Yd} ~ Ud} ~ wwxYw tj| } t3j| jsLtd| | d kr( tj| #t$$rYwxYw| j|krStd || j| | d kr( tj| "#t$$rY/wxYw5| jt>krXtd || jt> | d kr( tj| #t$$rYwxYwtj | d 5} d } tj !|} | "t>|| <dddn #1swxYwYno#t$$rb} td |t/| Yd} ~ | d kr( tj| ]#t$$rYjwxYwpd} ~ wwxYw| d kr( tj| #t$$rYwxYw#| d kr& tj| w#t$$rYwwxYwwxYw|r|dStG|}|d}tI|}tK||}|&|}|s/tOtQ|)d}tU|||}tj +|}tj |st,d|dS t[||5t]5t|d5} | /|dddn #1swxYwYdddn #1swxYwYdddn #1swxYwYt d||dS#t$r'} td|| Yd} ~ dSd} ~ wwxYw)a Copy xray.ini files from base user locations to per-website directories. This function is called by cagefsctl when enabling website isolation for a user. If xray.ini exists in base location (meaning user has active tasks), copy it to per-website directories. Overwrites existing files for consistency. Each domain may have a different PHP version set via cloudlinux-selector, so we determine the domain's actual PHP version from cl.selector symlinks. :param user: Username to regenerate ini files for Npathrz!Cannot get pw_record for path: %szxray.iniz Refusing to follow symlink at %sz+Cannot open xray.ini for path: %s, error=%sz'Refusing to read %s: not a regular filez0Refusing to read %s: owner uid %d != user uid %dz3Refusing to read %s: size %d bytes exceeds limit %drz+Cannot read xray.ini for path: %s, error=%srz*Per-website ini directory does not exist: wzCreated %s for domain %szFailed to create %s: %s)0rr rr pw_namepw_uidpw_gid Exceptionloggerdebugosr'joinexistsopenO_RDONLY O_NOFOLLOW O_NONBLOCKOSErrorerrnoELOOPwarningerrorstrfstatstatS_ISREGst_modeclosest_uidst_size MAX_INI_SIZEfdopenbasenameread get_docrootrr getnextitervaluesr%dirnameinforrwrite)rrbase_ini_filesuidgidlocationdir_path pw_recordini_filefdestfr docroot_result document_rootrdomain_php_vercontentini_pathini_dirs r$regenerate_ini_for_website_isolationrb]s} 'tV 4 4N C C&HHhv.//G G H))  ,HV,X66 $,,&&    @(KKK w||Hj99H7>>(++  WXr{R]'BR]'RSS   7ek))NN#ExPPPHHHH JHVYZ[V\V\]]]   & Xb\\|BJ//NNA 688 "59##NNJ    &88 "%: ,,NNM  $  88 "Yr3''G1B"$'"2"28"<"JJHgooh''G 7>>' " " JJJKKK= #s # #  ]__  d8S6I6I Q GGG                                                 /6BBBBB === .!<<<<<<<<<=s A8)A88%B B $9D F(0F )F  FAM&G<< H  H -MI I('I(-7M,K KKM*?L5) M5L9 9M<L9 =MO  N- )N(4O ?N N#"N#(N--O 7O  OO P(O=<P= P P P PV-V#U-4U U-U U-U U-! V-U1 1V4U1 5V8 V-VV- V V-- W7WWexisting_contentscounter php_versionc|t|dkrd}nd|d} d|ddSfd }g}d }t|d D]v\}}|t|d dz }|tks |tkr t dtdtd||wd|S)a: Generate xray.ini content with a specific task counter value. :param existing_contents: Existing ini file lines or None for new file :param counter: Task counter value to set :param php_version: PHP version for extension path (used only for new files) :return: Generated ini file content Nzxray.soz /opt/alt/phpz/usr/lib64/php/modules/xray.soz extension=z ;xray.tasks= c3>KD]}d|vr ddV|dzVdS)Nz xray.tasksz ;xray.tasks=rhr)linerdrcs r update_linez/_generate_ini_with_counter..update_linesX% " "Dt##0W0000000Tk!!!!  " "rrr )startzutf-8 surrogatepassz*existing xray.ini too large to preserve (>z bytes or >z lines))len enumerateencoderE MAX_INI_LINES ValueErrorappendr2) rcrdreso_pathrkout total_bytesnrjs `` r_generate_ini_with_counterrys8c+..22LLLL g  """""" CK[[]]!4444s4;;w@@AAA  % %]):):l\llVclll  4 773<<rrRrSdomain_task_countct||sdS t|}|std|dS|d}t |} n4#t $r'} td|| Yd} ~ dSd} ~ wwxYw| sdSt|| } | std|dSt|| | } | sdStj | } tj | std| dS t|||}n4#t$r'} td| | Yd} ~ dSd} ~ wwxYw t!||5t#5t%| d5}||dddn #1swxYwYdddn #1swxYwYdddn #1swxYwYtd | || |dS#t($r'} td | | Yd} ~ dSd} ~ wwxYw) aT Update xray.ini file in per-website directory for a SPECIFIC domain. This function is called when a tracing task is added/updated for a domain. The ini file is placed in the directory matching the domain's PHP version as configured via cloudlinux-selector. Generates the ini content with domain-specific task counter, which may differ from the per-user counter when a user has tasks for multiple domains. :param user: Username :param uid: User ID for file ownership :param gid: Group ID for file ownership :param domain: Domain name (e.g., 'example.com') - REQUIRED :param domain_task_count: Number of tasks for this specific domain :param existing_contents: Existing per-user ini file lines (to preserve settings) :param php_version: PHP version for extension path (used only for new files) N#Failed to get docroot for domain %sr*Failed to get website_id for domain %s: %s3No specific PHP version set for domain %s, skippingz,Per-website ini directory does not exist: %szRefusing to update %s: %sr*z+Updated %s for domain %s (PHP %s, tasks=%d)zFailed to update %s: %s)rrIr/r0rr.r<r r%r1r'rNisdirryrsr;rrr4rPr8)rrRrSrrzrcrer\r]rrYr^r`rar_r[s rupdate_website_isolation_inirsT6 'tV 4 4 $V,,  LL> G G G F&q) #M22  A61MMM :$ KKN  JFSSS(z>JJH gooh''G 7== ! ! CWMMM,->@QS^__ 2Ha@@@= #s # #  ]__  d8S6I6I Q GGG                                                 BHfVdfwxxxxx === .!<<<<<<<<<=s,AA B $BB 2E E5E00E59H$ G9G")G ? G" G G"G G" G9"G& &G9)G& *G9- H$9G==H$G=!H$$ I.IIcJt||sdS t|}|std|dS|d}t |}n4#t $r'}td||Yd}~dSd}~wwxYw|sdSt||}|std|dSt|||}|sdStj |sdS tj |}t|j|j5tj|dddn #1swxYwYtd|||dS#t $r'}td||Yd}~dSd}~wwxYw)ax Remove xray.ini file from per-website directory for a SPECIFIC domain. This function is called when the last tracing task for a domain is removed. The ini file is removed from the directory matching the domain's PHP version as configured via cloudlinux-selector. :param user: Username :param domain: Domain name (e.g., 'example.com') - REQUIRED Nr|rr}r~z!Removed %s for domain %s (PHP %s)zFailed to remove %s: %s)rrIr/r0rr.r<r r%r1r'r3pwdgetpwnamrr,r-unlink) rrr\r]rrYr^r`rVs rremove_website_isolation_inirQs 'tV 4 4 $V,,  LL> G G G F&q) #M22  A61MMM :$ KKN  JFSSS(z>JJH  7>>( # #=L&& )*I,< = =  Ih                   8(FN[[[[[ === .!<<<<<<<<<=sY,AA B $BB 8.E1&E; E1E  E1E  E11 F";FF"r)NN)+__doc__r9loggingr1rr?globrtypingrsecureiorclcommon.cpapirrIxray.internal.utilsrrxray_inir r r getLogger__name__r/rErrclcagefslib.domainr rr#clcagefslib.webisolation.jail_utilsr ImportErrorr=rr%rblistintryrrrrrrs  """"""111111BBBBBBBB  8 $ $   CBBBBBB   NNN ?c?3???? [C [S [s [xX[} [ [ [ [y=sy=Cy=Dy=y=y=y=x))(4.)3)]`)lo))))d)-I=I= I= I= I=  I=  I=  ~ I=I= I=I=I=I=X0=s0=C0=D0=0=0=0=0=0=sA''A:9A: