§ WèÄj3ãó*—ddlZddlZddlZddlZddlZddlZddlZddlmZddl m Z ddl m Z m Z mZmZddlmZddlmZmZddlmZdd lmZmZdd lmZmZmZdd lm Z dd l!m"Z"ej#d ¦«Z$dZ%dede&fd„Z'de&defd„Z(de&de&fd„Z)dejde&fd„Z*dejdeeeeffd„Z+d(de,de-fd„Z.de e/fd„Z0de/de/fd„Z1de e-fd„Z2d)d„Z3de de fd „Z4d!e/d"e/ddfd#„Z5de de fd$„Z6de de fd%„Z7de de fd&„Z8de de fd'„Z9dS)*éN©Úwraps)Ú HTTPStatus)ÚCallableÚOptionalÚTupleÚAny)Úget_main_username_by_uid)Úis_cl_solo_editionÚis_cl_shared_pro_edition)Úgettexté)Úuser_tasks_countÚfpm_reload_timeout)Ú XRayAPIErrorÚ XRayErrorÚXRayMissingDomain)ÚFPMReloadController)ÚNginxUserCacheÚuser_plugin_utilsz>IÚ_inputÚreturncó¢—tj|¦« ¦«}tjt t |¦«¦«|zS)z; Pack input for sending with length-prefix framing )ÚjsonÚdumpsÚencodeÚstructÚpackÚ_formatÚlen)rÚdatas úV/opt/cloudlinux/venv/lib64/python3.11/site-packages/xray/internal/user_plugin_utils.pyÚ pack_requestr#%s<€õ Œ:�fÑ Ô × $Ò $Ñ &Ô &€DÝ Œ;•w¥ D¡ ¤ Ñ *Ô *¨TÑ 1Ð1óÚ byte_commandcó®—tj| ¦«¦«}t d| d¦«¦«|S)z! Unpack incoming command zCommand requested => %sÚcommand)rÚloadsÚdecodeÚloggerÚinfoÚget)r%Úparseds r"Úunpack_requestr.-sE€õŒZ˜ ×+Ò+Ñ-Ô-Ñ .Ô .€FÝ ‡K‚KÐ)¨6¯:ª:°iÑ+@Ô+@ÑAÔAÐAØ €Mr$Úmsgcó¦—t dt|¦«¦«tjt t|¦«¦«|zS)z- Prefix message with a 4-byte length zPacking message of %i length)r*Údebugr rrr©r/s r"Ú pack_responser36s<€õ ‡L‚LÐ/µ°S±´Ñ:Ô:Ð:Ý Œ;•w¥ C¡¤Ñ )Ô )¨CÑ /Ð/r$Ú sock_objectcó”—d}d}t¦«}| d¦«}|s| |¦«Stjt|¦«d}||krt d|z¦«‚t |¦«|kr>| |¦«}|st d¦«‚||z }t |¦«|k°>|S)z9 Read length-prefixed amount of data from socket ii érz$Response message too large: %d bytesz.Connection closed before full message received)ÚbytesÚrecvrÚunpackrÚConnectionErrorr )r4ÚchunkÚ max_msglenr/Ú raw_msglenÚmsglenÚparts r"Úunpack_responser@>sÚ€ð €EØ!€JÝ ‰'Œ'€CØ×!Ò! !Ñ$Ô$€JØ ð'Ø×Ò Ñ&Ô&Ð&Ý Œ]�7 JÑ /Ô /°Ô 2€Fà � ÒÐÝÐDÀvÑMÑNÔNÐNå ˆc‰(Œ(�VÒ Ð Ø×Ò Ñ&Ô&ˆØð TÝ!Ð"RÑSÔSÐ SØ ˆt‰ ˆõ ˆc‰(Œ(�VÒ Ð ð €Jr$có¼—d}| tjtjt j|¦«¦«}t j||¦«\}}} tj|¦«j tj |¦«j }}t d|||||¦«n-#t$r t d|||¦«YnwxYw|||fS)z6 Retrieve credentials from SO_PEERCRED option Ú3iz%Connected by proc %i of %i:%i (%s:%s)zConnected by proc %i of %i:%i)Ú getsockoptÚsocketÚ SOL_SOCKETÚ SO_PEERCREDrÚcalcsizer9ÚpwdÚgetpwuidÚpw_nameÚgrpÚgetgrgidÚgr_namer*r+ÚKeyError)r4rÚcredsÚ_pidÚ_uidÚ_gidÚuserÚgroups r"Ú extract_credsrUVsä€ð€GØ × "Ò "¥6Ô#4µfÔ6HÍ&Ì/ÐZaÑJbÔJbÑ cÔ c€EÝ”} W¨eÑ4Ô4Ñ€Dˆ$�ð\Ý”l 4Ñ(Ô(Ô0µ#´,¸tÑ2DÔ2DÔ2Lˆeˆõ � Š Ð;¸TÀ4ÈÈtÐUZÑ[Ô[Ð[Ð[øõ ðGðGðGÝ� Š Ð3°T¸4ÀÑFÔFÐFÐFÐFðGøøøð ��tÐ ÐsÁ2B,Â,'CÃCrQcó8—|€tj¦«}|dkS)z9 Check for execution as root | command from root Nr)ÚosÚgeteuid)rQs r"Úcheck_for_rootrYfs€ð €|ÝŒz‰|Œ|ˆØ �1Š9Ðr$có¦—tjd¦«}|�:tt|¦«¦«}t d||¦«|SdS)zK Retrieve the value of XRAYEXEC_UID env and resolve it to username Ú XRAYEXEC_UIDNz/Got XRAYEXEC_UID: %s (%s), working in USER_MODE)rWÚgetenvr Úintr*r+)ÚproxyuidÚ _proxyusers r"Úget_xray_exec_userr`osR€õŒy˜Ñ(Ô(€HØÐÝ-­c°(©m¬mÑ<Ô<ˆ Ý� Š ÐEÀxÐQ[Ñ\Ô\Ð\ØÐðÐr$có2—tjd|id¬¦«S)zF Construct an appropriate formatted response in case of error ÚresultF)Ú ensure_ascii)rrr2s r"Úerror_responserdzs€õ Œ:�x �o°EÐ :Ñ :Ô :Ð:r$cóN—t¦«}|�t|¦«jSdS)z3 Check nginx cache status for current user N)r`rÚ is_enabled)Ú proxyusers r"Únginx_user_cacherh�s.€õ#Ñ$Ô$€IØÐݘiÑ(Ô(Ô3Ð3ðÐr$cót—t¦«s)tttd¦«¦«¦«‚dS)zL Check if utility is executed as root and throw error in case if no z,Only root is allowed to execute this utilityN)rYÚ SystemExitrdÚ_©r$r"Úroot_execution_only_checkrmŠs>€õ Ñ Ô ð\Ý�­Ð*XÑ(YÔ(YÑZÔZÑ[Ô[Ð[ð\ð\r$Úfunccó<‡—t‰¦«ˆfd„¦«}|S)zq Decorator aimed to verify domain owner in X-Ray Manager user mode Applies to get_domain_info method cóx•—t¦«}|€‰|i|¤ŽS ‰|i|¤Ž}nC#t$r6}ttd¦«d|j›�z¦«}d|_|d‚d}~wwxYw|j|krHt d||¦«ttd¦«t|¦«z¦«‚|S)ú Wraps func Nú%s cannot be foundúDomain Tz%s does not belong to user %s) r`rrrkÚ domain_nameÚ_internal_missing_domainrSr*ÚwarningÚstr)ÚargsÚkwargsrgr+ÚeÚerrrns €r"Úwrapperz'user_mode_verification..wrapper›sìø€õ 'Ñ(Ô(ˆ Ø Ð Ø�4˜Ð( Ð(Ð(Ð (ð Ø�4˜Ð( Ð(Ð(ˆDˆDøÝ ð ð ð õ"�AÐ2Ñ3Ô3Ð6OÀÄ Ð6OÐ6OÑOÑPÔPˆCØ+/ˆCÔ (ؘ4Ð øøøøð' øøøð( Œ9˜ Ò !Ð !Ý �NŠNÐ:¸DÀ)Ñ LÔ LÐ Lõ�AÐ2Ñ3Ô3µc¸$±i´iÑ?Ñ@Ô@Ð @؈ s›$¤ A$®1AÁA$r)rnr|s` r"Úuser_mode_verificationr}•s6ø€õ  ˆ4�[„[ð"ð"ð"ð"ñ„[ð"ðH €Nr$rtÚ domain_ownercó²—t¦«}|�D||kr@t d||¦«tt d¦«d|›�z¦«‚dSdS)uZ Enforce caller-owns-domain BEFORE the phpinfo probe's side effects (the temp PHP file-write into the target docroot + HTTP fetch) run. It is called from phpinfo_utils.get_php_configuration — the single sink every panel manager funnels into — so one guard covers Plesk, cPanel, DirectAdmin and custom panels. user_mode_verification only compares ownership AFTER the decorated get_domain_info body has returned, so without this pre-check a user-mode tenant can drive a cross-tenant side effect against another user's domain. Uses the SAME ownership primitive as user_mode_verification (get_xray_exec_user) and raises the SAME uniform error so a foreign domain is indistinguishable from a missing one. For root / non-user-mode callers (proxyuser is None) this is a no-op, preserving existing behaviour. Nz$Domain %s does not belong to user %srrrs)r`r*rvrrk)rtr~rgs r"Úverify_user_owns_domainr€Ãsi€õ #Ñ$Ô$€IØÐ °Ò!:Ð!:Ý�ŠÐ=¸{ÈIÑVÔVÐVÝ�Ð.Ñ/Ô/Ð2I¸KÐ2IÐ2IÑIÑJÔJÐJðÐÐ!:Ð!:r$cóF‡‡—d„Št‰¦«ˆˆfd„¦«}|S)zä Decorator aimed to check if user is not hitting limit of running tasks, set in X-Ray Manager user mode. Applies to start and continue methods. Limiting of user's running tasks is applied to Shared PRO only. c ó²—td¬¦«sdSt¦«}|�°|dj}| ¦«}| d¦«}|�zt d„|D¦«¦«}|t krXttd  tt ¦«tt ¦«¦«¦«¦«‚dSdSdS)zf If XRAYEXEC_UID exists, check if user does not exceed limit of running tasks T©Úskip_jwt_checkNrrbcóD—g|]}| d¦«dk¯|‘ŒS)ÚstatusÚrunning)r,)Ú.0Úitems r"ú z7user_mode_restricted..check..ñs0€Ð$gÐ$gÐ$g¨dÀtÇxÂxÐPXÑGYÔGYÐ]fÒGfÐGf TÐGfÐGfÐGfr$z>Limit of running tasks is {}. You already have {} running task) r r`Ú ui_api_clientÚ get_task_listr,r rrrkÚformatrw)rxrgÚui_api_cli_instanseÚrespÚ list_of_tasksÚ running_counts r"Úcheckz#user_mode_restricted..checkásé€õ(°tÐ<Ñ<Ô<ð Ø ˆFå&Ñ(Ô(ˆ Ø Ð Ø"& q¤'Ô"7Ð Ø&×4Ò4Ñ6Ô6ˆDØ ŸHšH XÑ.Ô.ˆMØÐ(Ý #Ð$gÐ$g°mÐ$gÑ$gÔ$gÑ hÔ h� Ø Õ$4Ò4Ð4Ý#ÝØ\×cÒcÝ #Õ$4Ñ 5Ô 5µsÕ;KÑ7LÔ7Lñôñôñôðð !Ð ð)Ð(à4Ð4r$có•—‰|މ|i|¤ŽS)rqrl)rxryr’rns €€r"r|z%user_mode_restricted..wrapperûs%ø€ð ˆˆtˆ ˆ ؈t�TÐ$˜VÐ$Ð$Ð$r$r©rnr|r’s` @r"Úuser_mode_restrictedr•ÙsJøø€ðððõ4 ˆ4�[„[ð%ð%ð%ð%ð%ñ„[ð%ð €Nr$cóF‡‡—d„Št‰¦«ˆˆfd„¦«}|S)aƒ Decorator aimed to restrict frequent reloads of FPM service Applies to get_domain_info method. Decorator ordering invariant: this decorator MUST sit OUTSIDE user_mode_verification (i.e. ``@with_fpm_reload_restricted`` above ``@user_mode_verification``) on every get_domain_info implementation. The wrapper below runs ``check`` only AFTER ``func`` returns, so any ownership-failure XRayError raised by the inner user_mode_verification wrapper short-circuits the throttle probe. Reversing the order would let the throttle check inspect another user's FPM service name and raise a distinguishable XRayError(flag='warning') before the outer ownership check could uniformise the response, leaking a side channel on whether the queried domain exists and whose service is currently throttled (see XRAY-244 / CLPRO-3079 information-oracle defense). có>—td¬¦«rdSt¦«}|�v|jrq|d |¦«}t |¦« ¦«r7t td¦«tt¦«zd¬¦«‚dSdSdS)ú TrƒNrzhThe X-Ray User service is currently busy. Operation is temporarily not permitted. Try again in %s minuterv)Úflag) r r`Ú panel_fpmÚfpm_service_namerÚrestrictrrkrwr)r!rxrgÚ _fpm_services r"r’z)with_fpm_reload_restricted..checksÀ€õ ¨TÐ 2Ñ 2Ô 2ð Ø ˆFå&Ñ(Ô(ˆ Ø Ð  T¤^Ð Ø œ7×3Ò3°DÑ9Ô9ˆLÝ" <Ñ0Ô0×9Ò9Ñ;Ô;ð ÝÝð1ñôõÕ,Ñ-Ô-ñ .ð #ð ñôðð !Ð Ð Ð ð ð r$có(•—‰|i|¤Ž}‰|d|iŽ|S)rqr!rl)rxryr+r’rns €€r"r|z+with_fpm_reload_restricted..wrapper,s3ø€ð ˆt�TÐ$˜VÐ$Ð$ˆØ ˆˆtИ$ÐÐÐØˆ r$rr”s` @r"Úwith_fpm_reload_restrictedrŸsJøø€ð$ððõ( ˆ4�[„[ðððððñ„[ðð €Nr$cóV‡‡—dtfd„Št‰¦«ˆˆfd„¦«}|S)NÚusernamecón—t¦«}|�"||krttd¦«¦«‚dSdS)zI If exists, check XRAYEXEC_UID against user passed param NzIncorrect user for request)r`rrk)r¡rgs r"Úvalidatez'username_verification..validate9sD€õ'Ñ(Ô(ˆ Ø Ð  X°Ò%:Ð%:Ý�AÐ:Ñ;Ô;Ñ<Ô<Ð <ð !Ð Ð%:Ð%:r$có:•—|d}‰|¦«‰|i|¤ŽS)Nr¡rl)rxryr¡rnr£s €€r"r|z&username_verification..wrapperAs2ø€à˜*Ô%ˆØˆ�ÑÔÐØˆt�TÐ$˜VÐ$Ð$Ð$r$)rwr)rnr|r£s` @r"Úusername_verificationr¥8sVøø€ð=�3ð=ð=ð=ð=õ ˆ4�[„[ð%ð%ð%ð%ð%ñ„[ð%ð €Nr$cóZ‡‡—dtddfd„Št‰¦«ˆˆfd„¦«}|S)z³ Decorator aimed to verify user in X-Ray Smart Advice user mode Applies to get_detailed_advice method, which takes part in advice_details and advice_apply methods r!rNcóâ—t¦«} |dd}n*#t$rttd¦«¦«‚wxYw|�"||krttd¦«¦«‚dSdS)zU If exists, check XRAYEXEC_UID against user in metadata of an advice Úmetadatar¡z#Requested advice cannot be verifiedNúRequested advice does not exist)r`rNrrk)r!rgr¡s r"Úverifyz-user_mode_advice_verification..verifyQs‘€õ'Ñ(Ô(ˆ ð FؘJÔ'¨ Ô3ˆHˆHøÝð Fð Fð FÝ�AÐCÑDÔDÑEÔEÐ Eð Føøøà Ð  X°Ò%:Ð%:Ý�AÐ?Ñ@Ô@ÑAÔAÐ Að !Ð Ð%:Ð%:s �Ÿ'Acóâ•— ‰|i|¤Ž\}}nS#t$rF}t¦«�2|jtjkrt t d¦«¦«d‚‚d}~wwxYw‰|¦«||fS)rqNr©)rr`ÚerrnorÚ NOT_FOUNDrrk)rxryÚ advice_infoÚ advice_objrzrnrªs €€r"r|z.user_mode_advice_verification..wrapper]s˜ø€ð Ø&* d¨DÐ&;°FÐ&;Ð&;Ñ #ˆK˜˜øÝð ð ð õ"Ñ#Ô#Ð/°A´G½zÔ?SÒ4SÐ4SÝ¥Ð"CÑ DÔ DÑEÔEÈ4ÐOØ øøøøð øøøð ˆˆ{ÑÔÐØ˜JÐ&Ð&sƒ � A™AAÁA)Údictr)rnr|rªs` @r"Úuser_mode_advice_verificationr±Jscøø€ð B•Tð B˜dð Bð Bð Bð Bõ ˆ4�[„[ð'ð'ð'ð'ð'ñ„[ð'ð& €Nr$)N)rN):rKrÚloggingrWrHrDrÚ functoolsrÚhttprÚtypingrrrr Úclcommon.cpapir Úclcommon.lib.cleditionr r Úxrayr rkÚ constantsrrÚ exceptionsrrrÚ fpm_utilsrÚ nginx_utilsrÚ getLoggerr*rr7r#r.r3r@rUr]ÚboolrYrwr`rdrhrmr}r€r•rŸr¥r±rlr$r"úr¿s}ðð € € € Ø € € € Ø€€€Ø € € € Ø € € € Ø € € € Ø € € € ØÐÐÐÐÐØÐÐÐÐÐØ1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1à3Ð3Ð3Ð3Ð3Ð3ØOÐOÐOÐOÐOÐOÐOÐOàÐÐÐÐÐØ;Ð;Ð;Ð;Ð;Ð;Ð;Ð;ØBÐBÐBÐBÐBÐBÐBÐBÐBÐBØ*Ð*Ð*Ð*Ð*Ð*Ø'Ð'Ð'Ð'Ð'Ð'ð ˆÔ Ð.Ñ /Ô /€Ø €ð 2˜ð2 ð2ð2ð2ð2ð ð¨3ððððð0�uð0 ð0ð0ð0ð0ð ¤ð°5ððððð0 ˜vœ}ð °°s¸CÀ°}Ô1Eð ð ð ð ð ð˜ð¨ððððð˜H SœMððððð;˜ð; ð;ð;ð;ð;ð4˜( 4œ.ð4ð4ð4ð4ð\ð\ð\ð\ð+ ð+¨hð+ð+ð+ð+ð\K¨ðK¸CðKÀDðKðKðKðKð,*˜xð*¨Hð*ð*ð*ð*ðZ/ Xð/°(ð/ð/ð/ð/ðd ð¨Xððððð$'¨ð'°Xð'ð'ð'ð'ð'ð'r$