§ WèÄjŽ1ãóš—dZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z ddl m Z ddlmZddlmZddlmZmZddlmZmZdd lmZdd lmZmZmZmZm Z dd l!m"Z"m#Z#m$Z$ej%d ¦«Z&ej'd ¦«Z(dZ)dZ*ej+e,¦«Z-e ¦«Z.dZ/dZ0ej'd¦«Z1de2e3e3ffd„Z4de3de5fd„Z6de7de7fd„Z8de3de3fd„Z9de:de5dede2e3e3ffd„Z;dejde,de3fd „Zdejd&e3de3fd'„Z?dejde3fd(„Z@dejddfd)„ZAd+d*„ZBdS),z@ This module contains X-Ray User Manager service implementation éN)ÚLockÚcurrent_thread)Úget_locale_from_envars)Úgettext)ÚBoundedThreadExecutor)ÚRunnerÚ get_runner)Úuser_agent_logÚuser_agent_sock)Ú XRayError)Úcheck_for_rootÚerror_responseÚ extract_credsÚ pack_responseÚunpack_request)Úconfigure_loggingÚ create_socketÚ read_sys_idÚ user_agentz0^[a-zA-Z]{1,5}(_[a-zA-Z]{2})?(\.[a-zA-Z0-9-]+)?$é2éiis![ \t\r\n]*\{[ \t\r\n]*(?:["}]|\Z)Úreturncóf—td¦«}t|¦« ¦«dfS)zN General format of message in case of errors during manager execution z[X-Ray User Plugin failed to execute your request. Please, contact your server administratoró)Ú_rÚencode)Ú_errs úF/opt/cloudlinux/venv/lib64/python3.11/site-packages/xray/user_agent.pyÚgeneral_exec_errorr,s1€õ Ð jÑ kÔ k€DÝ ˜$Ñ Ô × &Ò &Ñ (Ô (¨#Ð -Ð-rÚorig_msgcóR—tjdd| ¦«¦«S)zL Cut data field from the original message, because it could be huge z(?<="data": {).+(?=}, "result")z...)ÚreÚsubÚdecode)r s rÚ log_truncater%4s#€õ Œ6Ð3°U¸H¿OºOÑ)Ú startswithÚsplitÚappend)r&ÚredactedÚtokenÚopts rÚ redact_cmdr1;s†€ð€HØð#ð#ˆØ × Ò ˜DÑ !Ô !ð # c¨U l lØ—+’+˜c 1Ñ%Ô% aÔ(ˆCØ �OŠO˜sÐ/Ð/Ð/Ñ 0Ô 0Ð 0Ð 0à �OŠO˜EÑ "Ô "Ð "Ð "Ø €Orcó4—d„}tjd||¦«S)zA Extend warning 'Task is duplicated by URL' for end user cóJ—d}| d¦«}|dkr||zS|S)zM Add more text for duplicate warning, leave others unchanged sú. In case if you do not see running task for the same URL in your list of tasks below, contact your server administrator and ask him to check whether the requested URL is in the tasks list of X-Ray Admin Plugin or is scheduled for continuous tracing.rsTask is duplicated by URL)Úgroup)ÚmÚ additionalÚwarns rÚgenz#duplicate_warning_cast..genQs7€ðVˆ ð�wŠw�q‰zŒzˆØ Ð/Ò /Ð /ؘ*Ñ$Ð $؈ rs(?<="warning": ").+(?="}))r"r#)r r8s rÚduplicate_warning_castr9Ls(€ð ð ð õ Œ6Ð.°°XÑ >Ô >Ð>rÚcommandÚuserÚrunnercó(‡‡ ‡‡—‰jdkr1 t¦«|d<n#t$rt¦«cYSwxYwˆfd„Šd„Š d}d}||gŠ| |¦«}| |t ¦«¦«}t |t¦«rt  |¦«st ¦«pd}|r0‰|¦«}d‰j ›�d |›�||  d ¦«g}nd‰j ›�|  d ¦«g}|  ˆ ˆˆfd „|  ¦«D¦«¦«||d œ} t d t!|¦«t| ¦«¦« t#j|d| dd¬¦«} n6#t&t(t*t"jf$rt¦«cYSwxYw| j ¦«| j ¦«} } | r:t dt5¦«jt7| ¦«¦«| r:t dt5¦«jt7| ¦«¦«t9| ¦«| fS)zA Trigger runner.target utility with requested parameters ÚmanagerÚ system_idcóF•—|‰jvr‰j||¦«n|S)z0runner may define a special cast for each option)Ú option_cast)r0r<s €rÚrunner_cast_optz(execute_manager..runner_cast_optks.ø€à/2°fÔ6HÐ/HÐ/HÐ&ˆvÔ! #Ô& sÑ+Ô+Ð+ÈcÐQrcó—|durdnd|›�S)z=Hide True value from cmd representation for bool-flag optionsTÚr)©)Úvs rÚ hide_true_valz&execute_manager..hide_true_valos€à˜$�Y�Yˆrˆr G¨ G GÐ+rÚ api_versionÚlangzC.UTF-8z /usr/sbin/r(r:cóT•—g|]$\}}|¯|‰v¯ d‰|¦«›‰|¦«›�‘Œ%S)r(rE)Ú.0ÚkrFrGrBÚ skip_optionss €€€rú z#execute_manager..‡sQø€ÐwÐwÐwÁÀÀ1Ð[\ÐwÐabÐjvÐavÐavÐ;�_�_ QÑ'Ô'Ð;¨¨°qÑ)9Ô)9Ð;Ð;ÐavÐavÐavr)Ú XRAYEXEC_UIDÚLANGz*Going to execute: %s, with environment: %sTéxF)Úcapture_outputÚenvÚtimeoutÚcheckz%[%s] Proxied command stdout: %d bytesz%[%s] Proxied command stderr: %d bytes)Únamerr rÚgetrÚ isinstanceÚstrÚ _LOCALE_REÚmatchÚtargetÚpopÚextendÚitemsÚloggerÚinfor1Ú subprocessÚrunÚOSErrorÚ ValueErrorÚ TypeErrorÚSubprocessErrorÚstdoutÚstripÚstderrrÚlenr9)r:r;r<Úapi_version_keyÚ locale_optionrHÚ target_localeÚcasted_api_versionr&Úwith_envÚpÚbyte_outÚbyte_errrGrBrMs ` @@@rÚexecute_managerrtasÏøøøø€ð„{�iÒÐð (Ý#.¡=¤=ˆG�KÑ Ð øÝð (ð (ð (Ý%Ñ'Ô'Ð 'Ð 'Ð 'ð (øøøðRðRðRðRðRð,ð,ð,ð$€OØ€Mð$ ]Ð3€Là—+’+˜oÑ.Ô.€Kð—K’K  Õ/EÑ/GÔ/GÑHÔH€MÝ �m¥SÑ )Ô )ð>µ×1AÒ1AÀ-Ñ1PÔ1Pð>Ý.Ñ0Ô0Ð=°Iˆ àðEØ,˜_¨_Ñ=Ô=ÐØ+˜FœMÐ+Ð+Ð-FÐ2DÐ-FÐ-FÈ ÐU\×U`ÒU`ÐajÑUkÔUkÐlˆˆà+˜FœMÐ+Ð+¨W¯[ª[¸Ñ-CÔ-CÐDˆð‡J‚JÐwÐwÐwÐwÐwÐwÈÏ Ê ÉÌÐwÑwÔwÑxÔxÐxà $¨mÐ<Ð<€HÝ ‡K‚KÐ<½jȹo¼oÍsÐS[É}Ì}Ñ]Ô]Ð]ð$Ý ŒN˜3¨t¸È3ÐV[Ð \Ñ \Ô \ˆˆøÝ •Z¥­JÔ,FÐ Gð$ð$ð$Ý!Ñ#Ô#Ð#Ð#Ð#ð$øøøðœŸšÑ)Ô)¨1¬8¯>ª>Ñ+;Ô+;ˆh€HððcÝ� Š Ð;½^Ñ=MÔ=MÔ=RÕTWÐX`ÑTaÔTaÑbÔbÐbØðcÝ� Š Ð;½^Ñ=MÔ=MÔ=RÕTWÐX`ÑTaÔTaÑbÔbÐbÝ ! (Ñ +Ô +¨XÐ 5Ð5s‘#£>½>Æ F#Æ#0GÇGÚ connectionÚsizecóâ—t¦«}t|¦«|kr@| |t|¦«z ¦«}|sn||z }t|¦«|k°@t|¦«S)a Read exactly `size` bytes, or fewer if the peer stops sending before that The bytes are gathered in a bytearray: appending to an immutable `bytes` copies everything read so far on every recv(), which makes a request delivered in tiny pieces cost quadratic CPU. )Ú bytearrayrkÚrecvÚbytes)rurvÚdataÚchunks rÚ _recv_exactlyr}šso€õ ‰;Œ;€DÝ ˆd‰)Œ)�dÒ Ð Ø—’ ¥s¨4¡y¤yÑ 0Ñ1Ô1ˆØð Ø Ø �‰ ˆõ ˆd‰)Œ)�dÒ Ð õ �‰;Œ;Ðrr|ÚdepthÚ in_stringÚescapedcóÌ—t|¦«D]O\}}|rd}Œ |r|dkrd}Œ|dkrd}Œ|dkrd}Œ'|dkr|dz }Œ3|dkr|dz}|dkr ||||dzfcSŒP|||d fS) a~ Advance a brace-depth scan over `chunk`, resuming from the given state Returns the state after the chunk plus the offset just past the top-level object's closing brace, or -1 if it has not closed yet. Braces are scanned as raw bytes on purpose: `{`, `}`, `"` and `\` cannot appear inside a UTF-8 multi-byte sequence, so no decoding is needed to find them. Fé\Té"é{r*é}réÿÿÿÿ)Ú enumerate)r|r~rr€ÚindexÚbytes rÚ_scan_json_objectrŠ«s½€õ! Ñ'Ô'ð<ð<‰ ˆˆtØ ð <؈GˆGØ ð <Ø�tŠ|ˆ|Ø��ؘ’�Ø!� øØ �TŠ\ˆ\؈IˆIØ �TŠ\ˆ\Ø �Q‰JˆEˆEØ �TŠ\ˆ\Ø �Q‰JˆEؘŠzˆzؘi¨°%¸!±)Ð;Ð;Ð;Ð;øØ �)˜W bÐ (Ð(rÚheadc óö—t|¦«}|}d\}}} t||||¦«\}}}}|dkr7t|dt|¦«t|¦«z |z…¦«St|¦«tkr"t  dt¦«dS| tttt|¦«z ¦«¦«}|st|¦«S||z }Œâ)aC Read a request that carries no length prefix, `head` being its first bytes Such a client sends the payload alone and then waits for the reply without closing its side, so there is no EOF to read up to: the request ends where its JSON object ends, and the brace depth is what finds that. Each byte is looked at once and copied once - only the newly received chunk is scanned, and the request is gathered in a bytearray - so a caller cannot make the reader do more work by pacing the bytes; validating the result stays `unpack_request`'s job. )rFFTrNz,Unframed request exceeds %i bytes, rejectingr) rxrŠrzrkÚ_MAX_REQUEST_SIZEr`ÚwarningryÚminÚ_READ_CHUNK_SIZE)rur‹r{r|r~rr€Úends rÚ_recv_unframedr’Çsó€õ �T‰?Œ?€DØ €EØ /Ñ€Eˆ9�gðÝ):¸5À%ÈÐT[Ñ)\Ô)\Ñ&ˆˆy˜' 3Ø �!Š8ˆ8ݘÐ<¥ D¡ ¤ ­C°©J¬JÑ 6¸Ñ <Ð<Ô=Ñ>Ô>Ð >å ˆt‰9Œ9Õ)Ò )Ð )Ý �NŠNÐIÕK\Ñ ]Ô ]Ð ]Ø�3ð—’¥Õ$4Õ6GÍ#ÈdÉ)Ì)Ñ6SÑ TÔ TÑUÔUˆØð ݘ‘;”;Ð Ø �‰ ˆðrcó†—t|d¦«}t|¦«dkrdStjd|¦«d}d|cxkr tkr*nn't||¦«}t|¦«|kr|ndSt  |¦«sdSt d¦«t||¦«S)a± Read one request, accepting both framings clients send Current clients prefix the payload with its 4-byte big-endian length (`pack_request`, `ApiSocket::send`). AccelerateWP plugin builds up to 3.23-1.1-46 send bare JSON: they predate the prefix and cannot fetch their own fix through the socket they are unable to talk to, so the agent keeps answering them (CLOS-7023). Telling the two apart is exact, not heuristic: a length within `_MAX_REQUEST_SIZE` leaves 0x00 in the first byte, while JSON starts with a printable ASCII byte, so the first four bytes of a bare payload always decode to a length far above the cap (`{"ru` -> 2065855093). érz>Irz9Request carries no length prefix, reading it as bare JSON) r}rkÚstructÚunpackr�Ú_BARE_JSON_HEAD_REr[r`rar’)rur‹ÚmsglenÚbodys rÚ read_requestršçsÉ€õ ˜ QÑ 'Ô '€DÝ ˆ4�y„y�1‚}€}؈så Œ]˜4 Ñ &Ô & qÔ )€F؈6Ð&Ð&Ò&Ð&Õ&Ò&Ð&Ð&Ð&Ð&ݘZ¨Ñ0Ô0ˆÝ˜4‘y”y FÒ*Ð*ˆtˆt°Ð3å × #Ò # DÑ )Ô )ðð ˆså ‡K‚KÐKÑLÔLÐLÝ ˜* dÑ +Ô +Ð+rc ó —tjdtd¦«id¬¦«}|5| d¦«t |¦«\}}}t |¦«rB| t| ¦«¦«¦« ddd¦«dSt5t  |d¦«tkr4t d|¦« ddd¦«ddd¦«dSt|xxd z cc<ddd¦«n #1swxYwY t|¦«}|s[ t5t|xxd zcc<t|dkrt|=ddd¦«n #1swxYwYddd¦«dS t!|¦«}nÓ#tjt$f$rº}| ttjdt'|¦«id¬¦« ¦«¦«¦«Yd}~t5t|xxd zcc<t|dkrt|=ddd¦«n #1swxYwYddd¦«dSd}~wwxYw t)| d ¦«¦«}n±#t,$r¤}| tt'|¦« ¦«¦«¦«Yd}~t5t|xxd zcc<t|dkrt|=ddd¦«n #1swxYwYddd¦«dSd}~wwxYw | |¦«n±#t0$r¤}| tt'|¦« ¦«¦«¦«Yd}~t5t|xxd zcc<t|dkrt|=ddd¦«n #1swxYwYddd¦«dSd}~wwxYwt3|t'|¦«|¦«\} } | t| p| ¦«¦«np#t4t6f$r\Yt5t|xxd zcc<t|dkrt|=ddd¦«n #1swxYwYddd¦«dSwxYw t5t|xxd zcc<t|dkrt|=ddd¦«n #1swxYwYnR#t5t|xxd zcc<t|dkrt|=ddd¦«w#1swxYwYwxYwddd¦«dS#1swxYwYdS) z Handle incoming connection :param connection: socket object usable to send and receive data on the connection Úresultz#Commands from root are not acceptedF)Ú ensure_asciig@Nrz6Too many concurrent connections from uid=%s, rejectingr*r<)ÚjsonÚdumpsrÚ settimeoutrr ÚsendallrrÚ_uid_connections_lockÚ_uid_connectionsrWÚ_MAX_CONNECTIONS_PER_UIDr`rŽršrÚJSONDecodeErrorÚUnicodeDecodeErrorrYr r]r Ú validatorÚ SystemExitrtÚ TimeoutErrorrd) ruÚ root_errorÚ_pidÚ_uidÚ_gidr{ÚargsÚer<Ú_outrs rÚhandler± sÌ€õ ”˜X¥qÐ)NÑ'OÔ'OÐPÐ_dÐeÑeÔe€JØ ð,/ð,/Ø×Ò˜cÑ"Ô"Ð"Ý(¨Ñ4Ô4шˆd�DÝ ˜$Ñ Ô ð Ø × Ò �}¨Z×->Ò->Ñ-@Ô-@ÑAÔAÑ BÔ BÐ BØ ð ,/ð,/ð,/ñ,/ô,/ð,/ð,/ð,/õ#ð (ð (Ý×#Ò# D¨!Ñ,Ô,Õ0HÒHÐHÝ—’ÐWÐY]Ñ^Ô^Ð^Øð (ð (ð (ñ (ô (ð (ð,/ð,/ð,/ñ,/ô,/ð,/ð,/ð,/õ ˜TÐ "Ð "Ô " aÑ 'Ð "Ð "Ñ "ð  (ð (ð (ñ (ô (ð (ð (ð (ð (ð (ð (øøøð (ð (ð (ð (ð  /Ý  Ñ+Ô+ˆDØð Øõ2'ð /ð /Ý  Ð&Ð&Ô&¨!Ñ+Ð&Ð&Ñ&Ý# DÔ)¨QÒ.Ð.Ý(¨Ð.ð /ð /ð /ñ /ô /ð /ð /ð /ð /ð /ð /øøøð /ð /ð /ð /ðS,/ð,/ð,/ñ,/ô,/ð,/ð,/ð,/ð$ Ý% dÑ+Ô+��øÝÔ(Õ*<Ð=ð ð ð Ø×"Ò"¥=µ´¸XÅsÈ1ÁvÄvÐVÓSÓT!ÓVÓ/TÔ VÔT ÔVÔT ÔVÔ!U0Ô)/U$ Õ U0Õ$U( Õ(U0Õ+U( Õ,U0Õ0VÖVÖVcó¾—tt¦«tt¦«5}t t d¬¦«5} | ¦«\}} | t|¦«nC#tj $r1t  d¦«|  ¦«YnwxYwŒx#1swxYwYddd¦«dS#1swxYwYdS)z Run listening service r)Ú max_workersÚ maxqueuesizeTz(Connection rejected: thread pool is fullN)rr rr rÚ _MAX_WORKERSÚacceptÚsubmitr±ÚqueueÚFullr`ÚerrorÚclose)ÚsÚpoolÚconnrs rrcrc@s>€õ•nÑ%Ô%Ð%Ý •Ñ 'Ô 'ð¨1Õ.CÕP\ÐklÐ.mÑ.mÔ.mðÐquð Ø—h’h‘j”j‰GˆD�!ð Ø— ’ �F DÑ)Ô)Ð)Ð)øÝ”:ð ð ð Ý— ’ ÐGÑHÔHÐHØ— ’ ‘ ” � � � ð øøøð  ððððøøøðððððððñôðððððððøøøððððððsS©CÁB:ÁA6Á5B:Á6=B6Â3B:Â5B6Â6B:Â:B> Â>CÃB> ÃCÃCÃC)rN)CÚ__doc__Ú collectionsržÚloggingr¸r"Úsocketr•rbÚ threadingrrÚclcommon.clwpos_librÚxrayrrÚxray.agent.executorrÚ#xray.console_utils.run_user.runnersrr Úxray.internal.constantsr r Úxray.internal.exceptionsr Úxray.internal.user_plugin_utilsr rrrrÚxray.internal.utilsrrrÚ getLoggerr`ÚcompilerZrµr¤Ú defaultdictÚintr£r¢r�r�r—ÚtuplerzrrYr%Úlistr1r9Údictrtr}ÚboolrŠr’ršr±rcrErrúrÔsyðð ððÐÐÐØ € € € Ø€€€Ø € € € Ø € € € Ø € € € Ø € € € ØÐÐÐØ*Ð*Ð*Ð*Ð*Ð*Ð*Ð*à6Ð6Ð6Ð6Ð6Ð6àÐÐÐÐÐØ5Ð5Ð5Ð5Ð5Ð5ØBÐBÐBÐBÐBÐBÐBÐBØCÐCÐCÐCÐCÐCÐCÐCØ.Ð.Ð.Ð.Ð.Ð.ØxÐxÐxÐxÐxÐxÐxÐxÐxÐxÐxÐxÐxÐxØMÐMÐMÐMÐMÐMÐMÐMÐMÐMà ˆÔ ˜<Ñ (Ô (€Ø ˆRŒZÐKÑ LÔ L€ à€ ØÐØ*�;Ô*¨3Ñ/Ô/ÐØ˜™œÐØÐØÐð �R”ZÐ EÑFÔFÐð.˜E %¨ ,Ô/ð.ð.ð.ð.ðO˜5ðO SðOðOðOðOð�Dð˜Tððððð"? Uð?¨uð?ð?ð?ð?ð*66˜Tð66¨ð66°fð66ÀÀuÈeÀ|ÔATð66ð66ð66ð66ðr˜fœmð°3ð¸5ððððð")˜Uð)¨3ð)¸4ð)È$ð)ÐSXÐY\Ð^bÐdhÐjmÐYmÔSnð)ð)ð)ð)ð8˜vœ}ð°Eð¸eððððð@ ,˜Vœ]ð ,¨uð ,ð ,ð ,ð ,ðF3/�v”}ð3/¨ð3/ð3/ð3/ð3/ðl ð ð ð ð ð r