yo4h ddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl ZddlZddlZddlmZddlmZmZddlmZmZddlmZmZmZddlmZddlm Z ddl!m"Z"m#Z#m$Z$m%Z%dd lm&Z&dd lm'Z'dd l(m)Z)dd l*m+Z+dd l,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4ddl5Z5ddl6Z6ddl7Z7ddl8m9Z9e4de/Z:ej;e<Z=dZ>dZ?da@dZAe)dZBdZCe)dZDe)dZEe)dZFGdde ZGejHddZIeddZJe=ddfd ZKGd!d"ZLdejMejMd#dfd$e3eNeOeOffd%ZPddd&d'ZQGd(d)ejRZSeSfd$eOfd*ZTeSfdd+ZUdd$eVfd-ZWd.ZXGd/d0ZYd1ZZGd2d3e[Z\d4Z]d5Z^ dd7Z_d,ddd,dd8d$e`fd9ZaejHdd:Zbdd$eVfd;ZcGd<d=Zdejed>fd?eVd@eNd$eVfdAZf dd?eVd@eNd$e3eVeNffdBZgdCZhdDZiddFZj ddHZkdIZlejHdJeNfdKZmejne5jodLd,MZpdNZqd?ejrdOeOd$dfdPZsdQZtd?ejrdReOd$e`fdSZudTZvGdUdVZwe?fdWZxdXZyedYeNfdZZzdd\eVd$e)fd]Z{d^eVd\eVd$e`fd_Z|d`Z}ddbedceNd$efddZ~deZGdfdgeZejHd6dhZdiZdd$e`fdjZGdkdlZeZdmZdnZGdodpejZdqZ ddrZdsZe[dfdtZefduZdvZdwZd#dxdyZedzd{Zd|Zd}Zd^e)d$eOfd~ZdeOd$e)fdZdZdZde/de.ffdZdZdZdZdZejHddZdLdde2eVfdZddddZddZGddZdZejHddZGdde[ZdZd$efdZe=jfdZdeNfdZde0e-e-fdeNfdZejHddZdS)N)Future) OrderedDictdeque) GeneratorIterable) ExitStackcontextmanagersuppress) timedelta)Enum)LOCK_EXLOCK_NBLOCK_UNflockwraps)islice)Path)NamedTemporaryFile)Any AwaitableCallableDict FrozenSetListTupleTypeVar)rmtreeF)bounduser_id)z User-AgentzAccept-LanguagezAccept-Encoding ConnectionDNTz.i360bakz/run/systemd/systemz/etc/cloudlinux-edition-soloz/var/run/imunify-antivirus.pidz/var/run/imunify360-agent.pidz/var/run/imunify360.pidceZdZdZdZdZdZdS)ScopezAV onlyz AV and IM360z IM360 onlyzIM360 resident onlyN)__name__ __module__ __qualname__AVAV_IM360IM360IM360_RESIDENTS/opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/utils/__init__.pyr'r'As" BH E*NNNr0r')maxsizecto2tot S)zReturn True if /run/systemd/system folder exists: [sd_booted] (https://www.freedesktop.org/software/systemd/man/sd_booted.html) )_SYSTEMD_BOOTED_DIRexistsis_dir is_symlinkr/r0r1is_systemd_bootr8HsC ""$$ 1  & & ( ( 1#..00 0r0c#K|s|sJtj}|p|jd|dVtj}|p|jd|||z dS)z :param str: action name to log :param logging.Logger: logger you want action name and timing to be logged with :param func: log function to use (`log` has preference over `logger_`) z %s startedNz%s took %.2f second(s))time monotonicdebug)actionlogger_logstartstops r1timeitrBUsz c> N  ESGM<000 EEE >  DSGM3VTE\JJJJJr0cfd}|S)NcNtjfd}|S)NcKtpj5|i|d{VcdddS#1swxYwYdSN)r>r?rBr(argskwargsr=funr?r>s r1wrapperz+timefun..decorator..wrappergs.#,SIII 2 2 S$1&11111111 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2s 8<< functoolsrrKrLr=r?r>s` r1 decoratorztimefun..decoratorfsH    2 2 2 2 2 2 2   2r0r/r>r=r?rPs``` r1timefunrRes0 r0c0eZdZdZeeddfdZdS)synczF the same timefun decorator variation but without async/await Ncfd}|S)z :param logging.Logger: logger you want action name and timing to be logged with :param str: action name to log cNtjfd}|S)Ncztpj5|i|cdddS#1swxYwYdSrFrGrHs r1rLz0sync.timefun..decorator..wrappersF2clGMMM003///000000000000000000s 044rMrOs` r1rPzsync.timefun..decorator~sH _S ! ! 0 0 0 0 0 0 0" ! 0Nr0r/rQs``` r1rRz sync.timefunvs0       r0)r(r)r*__doc__ staticmethodloggerrRr/r0r1rTrTqsEt\r0rTFreturnc $K||tdtj}|r't|tsJ|g}t j}n*t|ttfsJt j }ttdtd|||||dd|d{V}| |d{V\} } |d{V} td |||| | | f| | | fS) zYAsynchronous command executor. Returns a tuple (exit_code, stdout_data, stderr_data).Nz/stdin and input arguments may not both be used.r)seconds) max_trieson_errorTstdinstdoutstderrstart_new_sessionz run(%s, stdin=%s, shell=%s) = %s) ValueError _subprocessPIPE isinstancestrasynciocreate_subprocess_shelllisttuplecreate_subprocess_execretry_onBlockingIOError await_for communicatewaitrZr<) commandrbrcrdshellinputrJcreate_subprocessprocouterr exit_codes r1runr}s   NOO O  ;'3''''')#;'D%=11111#:1y/C/C/C             D%%e,,,,,,,,HCiikk!!!!!!I LL*  C  c3 r0)looptimeoutc|rtdD]b} tj}|sn7n#t$rYnwxYwtjtjc|tjt|tj r|ntj ||S)zjRun coroutine from a blocking code (outside the event loop). Coroutine will be wrapped in Task. Nr]r) rangerkget_event_loop is_closed RuntimeErrorset_event_loopnew_event_looprun_until_completewait_forrirTask)coror~r_s r1run_corors  |q = =A -//~~''E       "7#9#;#; < < < <  " "tW^44 LDD',t:L:L     s? A  A ceZdZdZdS) CheckRunErrorcd}||j|j|jpd|jpdS)Nz[Command {cmd!r} returned non-zero code {returncode}, Stdout: {output}, Stderr: {error} )cmd returncodeoutputerror)formatrrrdecoderd)self_MESSAGEs r1__str__zCheckRunError.__str__s_ $  ;%%''/4+$$&&.$    r0N)r(r)r*rr/r0r1rrs#      r0rc`Kt|fi|d{V\}}}|dkr||||||S)zJ Asynchronous command executor. Returns output as bytestring. Nr)r})ru raise_excrJrrzr{s r1 check_runrsZ "%W!7!7!7!7777777JSQi GS#666 Jr0cKt|tjtjtjd{V\}}}|dkr |||dS)z Asynchronous command executor. Raises raise_exc if exit code is nonzero. Stdin, stdout and stderr of command are connected to /dev/null. )rbrcrdNr)r}rgDEVNULL)rurcoders r1check_exit_codersy !"" JD!Q qyyig&&&yr0TcK t|fi|d{V\}}}n,#t$rtd|YdSwxYw|r%|dkrtd|||dS |}n,#t $rtd|YdSwxYw|S)zGSafe run command. Returns stdout as string or empty string on errorNzCommand %s failed with OSErrorrz'Command %s failed with exit code %s: %sz#Command %s returned non-utf8 output)r}OSErrorrZwarningstriprUnicodeDecodeError)rucheck_returncoderJrcrzr{results r1safe_runrs 33F33333333 C 7AAArrB!GG 5wC   r##%% .wrappers  %+--Kr0r/)rrLrs` @r1plainold_lazy_initrs.K Nr0ceZdZdZdZdZdS) PeriodicCheckz Invoke a callback with a certain period and return cached result in between. Raising an exception from the callback does not affect the next check schedule. c||_||_tj|z |_d|_t tj|_ dSr) _cb_coro_check_every_n_secondsr:r;_last_check_timestamp_last_check_resultrrkLock_lock)rcb_corocheck_every_n_secondss r1__init__zPeriodicCheck.__init__,sD &;#%)^%5%58M%M""&' 55 r0cK|4d{Vtj|jz }||jkrVt d|j|jtj|_|j|i|d{V|_|jcdddd{VS#1d{VswxYwYdS)Nz3Timeout %d seconds has expired, doing the check: %s) rr:r;rrrZr<rr)rrIrJdeltas r1__call__zPeriodicCheck.__call__5s\::<< + + + + + + + +N$$t'AAE333 I/M .2^-=-=*0= t0Nv0N0N*N*N*N*N*N*N'* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sBB33 B=B=N)r(r)r*rXrrr/r0r1rr#s<666 + + + + +r0rcfd}|S)Nc$t|Sr)r)rnsecs r1decoratezcache_result..decorateDsT4(((r0r/)rrs` r1 cache_resultrCs#))))) Or0ceZdZdZdS)RecurringCheckStopz: raised by coroutine to stop recurring_check loop Nr(r)r*rXr/r0r1rrJs Dr0rcK t|r!tj|di|d{Vntj|d{VdS#tj$rYdSwxYw)NFTr/)callablerksleepCancelledError)period period_kwargss r1wait_for_periodrRs F   (- 7 7 7 788 8 8 8 8 8 8 8 8-'' ' ' ' ' ' ' 'u  !ttsA AA#"A#c8K|r|rt|fi|d{VndSNF)r)checkrrs r1should_stop_after_period_passedr]sG   of66 666666666 r0 c fd}|S)z run decorated corotine in a loop every :period: seconds. If more then consecutive_err_limit error occured, exit loop. :param period: :param consecutive_err_limit: :param check_period_first: default false :return: cFtfd}|S)NcKd} tfid{VrdS |i|d{Vd}n#t$rOd|vrG t|dtr|dn#t $rYnwxYwYdSt j$rYdSt$r}|dz }|kr t dYd}~dSt|tj r3t d|j |j|j|jnt dYd}~nd}~wwxYwt fid{VrdST)NrT lock_filerz-Error count exceeded limit,exiting check loopz+Failed to run %s (%s). stdout=%s, stderr=%szError executing %s)rrrirunlinkFileNotFoundErrorrkr ExceptionrZ exceptionrgCalledProcessErrorrrrrd) rIrJconsecutive_err_cntexccheck_period_firstconsecutive_err_limitrKrrs r1wrappedz3recurring_check..decorator..wrappedrsH"# ' 8&2?E,#t.v.........:+,''9*"f,,!)&*=tDD= &{ 3 : : < < <0!!! D!EE-EE DDD'1,'*-BBB((K!#{'EFF D((IGNJJ (()=sCCC!D&9**F6CEO' sK0D?5A54D?5 B?D?BD?D? D?"%D: A(D::D?r)rKrrrrrs` r1rPz"recurring_check..decoratorqsI s) ) ) ) ) ) ) )  ) Vr0r/)rrrrrPs```` r1recurring_checkres7--------^ r0)backupuidgidallow_empty_content permissionsc lt|tr|}tt5t |d5}|t|dz}dddn #1swxYwY||kr ddddS dddn #1swxYwY|s |st d||dS|rUt|ttj fr|} ntj |tz} tj|| |k t!jtj|j}n>#t$r1tjd} tj| d| z}YnwxYwtj|\} } t-| st d| t15} t3d | d | d zdd 5fd }| |||*|(tj||tj|tj dddn #1swxYwYtj!j"|| #dddn #1swxYwYdS)aAtomically rewrites *filename* with given *data*. If *filename*'s content is *data* already, do nothing. If both *uid* and *gid* are given then resulting file is chowned to given user id and group id. Skip rewrite with empty content if *allow_empty_content* is False. Chmod to given access *permissions* else preserve *filename* 's permissions. Return True if *filename* file was updated, False otherwise rbrNFzempty content: %r for file: %srizParent dir is missing: wbz .i360editr)modedirsuffixprefix bufferingdeletectt5tjjddddS#1swxYwYdSr)r rosremovename)tfsr1cleanupzatomic_rewrite..cleanups/00''Ibg&&&''''''''''''''''''s=AAT)$rirjencoder ropenreadlenrZrrPathLikefspathBACKUP_EXTENSIONshutilcopystatS_IMODEst_modeumaskpathsplitrr5rrcallbackwriteflushchownfilenochmodfsyncrenamerpop_all)filenamedatarrrrrfile old_contentbackup_filename current_umaskdirpathbasenamestackrrs @r1atomic_rewriters ,${{}} # $ $ (D ! ! 3T))CIIM22K 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 $     t 5tXFFFu / fsBK0 1 1 E$OO i114DDO Ho... 1,rwx'8'8'@AAKK  1 1 1HQKKM H] # # #=.0KKK  1  h//GX ==   ! !G E' E EFFF  c>     " ' ' ' ' ' NN7 # # # HHTNNN HHJJJ3?c3/// HRYY[[+ . . . HRYY[[ ! ! !- " " " " " " " " " " " " " " ". "'8$$$ 38 4s~B.&B6 B.B B. B B..B25B25+E!!8FFL)B=K$ L)$K( (L)+K( ,1L))L-0L-c tdS#t$rYdSwxYw)Nz/etc/system-release)r read_textrstriprr/r0r1os_release_and_versionrsP)**4466==??? tts25 AAc|p t}|r-tjd|}|r|dSntt d|z)z3Return os version, if can't get it raise ValueErrorz\s*(\d+\.\d+\S*)(\s|$)rz!Can't discover os version from %r)rresearchgroup cache_clearrf)release_and_versionrvmatchs r1 os_versionr%st  8 6 8 8B - 3R88  ";;q>> ! " **,,, 82= > >>r0ceZdZdZedZedZedZdZe dZ e de e e ffdZe dee fd Ze de fd Ze de fd Ze d Ze d Ze dZe dZe dZe dZe dZe dZe dZdS) OsReleaseInfoz/etc/os-release)debian)rhelfedoracentos)unknownNct|j5}|D]U} |d\}}|d||<F#t $rYRwxYw dddn #1swxYwYd|vr,t |d|d<dSt |ddf|d<dS)N="ID_LIKEIDlinux)rETC_OS_RELEASErrrrf frozensetget)clsdict_flinekvs r1dict_from_filezOsReleaseInfo.dict_from_files3 #$ % %   ;;==..s33DAq wws||E!HH!D                    (y)9)?)?)A)ABBE)    )%))D'*B*B)DEEE)   s5A;AAA; A+(A;*A++A;;A?A?r[c\|jt}tj|jr||ntj}|r|dr|d d}|dkr d|dvrd}||d<d |d|d|d|d <|d vr |j |d <n.|d vr |j |d <n|j|d <nd |d<|j|d <d |d <||_|jS)NrredzRed Hat Enterprise Linuxr)r1z {} {} ({})rr] PRETTY_NAME) cloudlinuxr+r)r0)ubuntur(r,)r7dictrrr5r3r<distrolinux_distributionlowerrrRHEL_FEDORA_CENTOSDEBIANUNKNOWN)r6r7dosids r1to_dictzOsReleaseInfo.to_dict!sQ 9 $(FFEw~~c011 5""5))))-//515Q4::<<--//2Du}})Cqt)K)K%"&E$K+7+>+>!adAaD,,E-(???+.+Ai((!555+.:i((+.;i(("+E$K'*{E)$+4E-(CIyr0c6|dS)Nr0rKr6s r1id_likezOsReleaseInfo.id_like@s{{}}Y''r0c6|dS)Nr?rMrNs r1 pretty_namezOsReleaseInfo.pretty_nameDs{{}}]++r0cR|ddS)zi :return: OS name, like centos, ubuntu, debian, cloudlinux, redhat in lower case r1r,)rKr5rNs r1get_oszOsReleaseInfo.get_osHs" {{}}  y111r0c2|dkS)Nr)rSrNs r1is_rhelzOsReleaseInfo.is_rhelPszz||v%%r0c2|dkS)Nr+rUrNs r1 is_centoszOsReleaseInfo.is_centosTzz||x''r0c2|dkS)NrArUrNs r1 is_ubuntuzOsReleaseInfo.is_ubuntuXrYr0c.|dvS)N)r@cloudlinuxserverrUrNs r1 is_cloudlinuxzOsReleaseInfo.is_cloudlinux\szz||AAAr0cJtjtSr)rrr5_CL_SOLO_EDITION_FILErNs r1is_cloudlinux_soloz OsReleaseInfo.is_cloudlinux_solo`sw~~3444r0c2|dkS)Nr(rUrNs r1 is_debianzOsReleaseInfo.is_debiandrYr0c2|dkS)NolrUrNs r1is_oracle_linuxzOsReleaseInfo.is_oracle_linuxhszz||t##r0c2|dkS)N almalinuxrUrNs r1 is_almalinuxzOsReleaseInfo.is_almalinuxlszz||{**r0c2|dkS)NrockyrUrNs r1 is_rockylinuxzOsReleaseInfo.is_rockylinuxpszz||w&&r0)r(r)r*r3r4rGrFrHr7 classmethodr<rrjrrKrrOrQrSrVrXr[r^rarcrfrirlr/r0r1r'r' s&N Y{ # #F"#?@@i %%G E F F[ FS#X[<( #((([(,C,,,[,2s222[2&&[&(([((([(BB[B55[5(([($$[$++[+''['''r0r'r chunksizec0t|||dS)zReturn hash of the file `filename`, reading it in chunks. * filename is a path to a file; * hash_func is a function that returns hash object (one of hashlib.md5 etc); * chunksize is a size of chunks to read, in bytes. r)file_hash_and_size)r hash_funcros r1 file_hashrsus h 9 = =a @@r0c|}d}t|d5} ||}|sn(|||t|z }@ dddn #1swxYwY||fS)aCalculate hash and size of the file `filename`, reading it in chunks. * filename is a path to a file; * hash_func is a function that returns hash object (one of hashlib.md5 etc); * chunksize is a size of chunks to read, in bytes. Return tuple(hash, file size).rrTN)rrupdater hexdigest)rrrrohash_sizer8chunks r1rqrqs IKKE D h   FF9%%E  LL    CJJ D    ??  d ""sAA,,A03A0c|\}}||kr&tdjdit|S)z0Given login.defs line, return *varname*'s value.z"Expected {varname!r}, got {name!r}r/)rrfrvars)varname defs_linervalues r1_parse_name_valuersJ//##KD%$D=DNNtvvNNOOO Lr0cHtdkrt\a}tS)Nr%)_MIN_UID_get_max_min_uid)rs r1 get_min_uidrs2~~&(( ! Or0/etc/login.defsc\d\}}ttjz}tt5|r&t drd\}}dddn #1swxYwY t|5}|D]f}|drttd|}|drttd|}g dddn #1swxYwYn#ttf$rYnwxYw||fS)zGet UID_MIN, UID_MAX from the login.defs file specified as *path*. On error, return default for the current OS values. )i`6)rNUID_MINUID_MAX) r'rOrFr rfr% startswithrintrr)ruid_minuid_maxr+rr9s r1rrs #GW  " " $ $}'G GF *  **  *jll--c22 *) GW***************  $ZZ F4 F F??9--F!"3It"D"DEEG??9--F!"3It"D"DEEG  F F F F F F F F F F F F F F F F Z       G sI)A55A9<A9DA*D; DD  DD DD'&D'zimunify360-captchazimunify360-webshieldclt\fdtjDS)z~ :param excludes: users to exclude in results :return: list: list of pwd.struct_passwd objects representing users cPg|]"}|jcxkrknn |jv |#Sr/pw_uidpw_name).0entryexcludesrrs r1 z(get_non_system_users..sS     el - - - -g - - - - -%-x2O2O 2O2O2Or0rpwdgetpwall)rrrs`@@r1get_non_system_usersrsR())GW      \^^   r0cdt\}fdtjDS)z; :return: list: list of str with system user names c4g|]}|jk |jSr/r)rrrs r1rz)get_system_user_names..s.   W 5L5L 5L5L5Lr0r)rrs @r1get_system_user_namesrsE"##JGQ    #&<>>   r0rc0t\}}||kSr)r)rrrs r1is_system_userrs'))GW =r0d)r2typedct|d5}|dd}|dkrF||dz |ddkr|d|||ds|dddddS#1swxYwYdS)Nzr+rr]r rseekrrendswithrrr8 last_char_poss r1append_with_newliners h   q! A   FF=1$ % % %vvayyD     }}T""  GGDMMM                  B"CCCrct|d5}|dd}|dkrF||dz |ddkr|d|||ds|dddddS#1swxYwYdS)z>Append *data* to *filename* making sure there is at the end.zr+brr]r Nrrs r1append_with_newline_bytesrs h   !q! A   FF=1$ % % %vvayyE!!  }}U##  GGENNN                  rcd}t|d5}tfd|Dsd}dddn #1swxYwY|rt||S)zAdd *line* to *filename* if it is not present in the file Returns: True if the file was changed, False otherwise. Frc3HK|]}|kVdSrrr_liner9s r1 z&ensure_line_in_file..088U5;;==D(888888r0TN)ranyrrr9changedr8s ` r1ensure_line_in_filer s G h  8888a88888 G,Hd+++ N>AAr9cd}t|d5}tfd|Dsd}dddn #1swxYwY|rt||S)zAdd *line* to *filename* if it is not present in the file. Returns: True if the file was changed, False otherwise. Frc3HK|]}|kVdSrrrs r1rz,ensure_line_in_file_bytes.. rr0TN)rrrrs ` r1ensure_line_in_file_bytesrs G h  8888a88888 G2!(D111 Nrctj|}t|d5}t d|d5}|D]/}||kr||0tj|j|dddn #1swxYwYddddS#1swxYwYdS)NrwF)rrr) rrdirnamerrrrr r)rr9basedirsfrrs r1remove_line_from_filer's;gooh''G h  %$6 ge%%%%   E{{}}$$ "'8$$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%s6B4A B B4B B4#B $B44B8;B8c,eZdZdZdZefdZdZdZdS)FileLockz` Simple context manager to enable UNIX-specific file locking with flock system call rcZ||_d|_t|d|_||_dS)NFr)rlockedrrr)rrrs r1rzFileLock.__init__:s*  sOO  r0cKtj} t|jttzd|_|S#t tf$r}|jtj kr|j tj|z kr&t d|j Yd}~dStjdd{VYd}~nd}~wwxYw)NTz)Failed to lock file %s. Timeout exceeded.r)r:rrr rrrIOErrorerrnoEAGAINrrZrrrkr)rr@exs r1 __aenter__zFileLock.__aenter__@s  ' 'di7!2333"  W% ' ' '8u|++\DIKK%$777NNCTYEEEEEmA&&&&&&&&&&&&&& ' 's*ACAC/CCcK|jrt|jtd|_|jdSr)rrrrclose)rexc_typeexc_valexc_tbs r1 __aexit__zFileLock.__aexit__XsC ; & $)W % % %  r0N)r(r)r*rX_TIMEOUTrrrr/r0r1rr2sZ H%- '''0r0rc |g}|fdt|Dtj}|d|dd|S#ttf$r%}t d|Yd}~nd}~wwxYwdS)Nc3DK|]\}}|v t|VdSr)rj)rfieldr~fieldss r1rz user_identity..is?  u JJ  r0rutf8surrogateescapez9Generation of user identity hash failed, invalid data: %s) extendsorteditemshashlibsha1rujoinrrvrfUnicodeEncodeErrorrZr) attackers_ipsourceruid_datahash_alges ` r1 user_identityrbs  !>    &v||~~ 6 6      <>>))009JKKLLL!!### * +    G         4sB%B))C:CCc0tjdkS)Nr)rgetuidr/r0r1 is_root_userr}s 9;;! r0maskc#Ktj|} dVtj|dS#tj|wxYwr)rr)r current_masks r1run_with_umaskrsM8D>>L  s 2Arusernamec~t|tstd|ztj|vrtd t j|}n0#t$r#td|wxYwtj |j |}t|S)z Returns user's home dir if `relpath` is not specified. Otherwise, returns absolute path of `relpath` build from `username`'s home dir :raise ValueError: when user home dir is not exists z#Invalid type for %s, should be str!zInvalid usernamezUser {!r} doesn't exist) rirjrfrseprgetpwnamKeyErrorrrrpw_dirr)rrelpathpwabs_paths r1get_abspath_from_user_dirrs h $ $K>IJJJ v+,,,E \( # # EEE299(CCDDDEw||BIw//H >>s A-Brcd} t|}t||d}n>#t$r1}tt |Yd}~nd}~wwxYw|S)NFT)rr relative_torfrZrrj)rrstatus user_homers r1does_path_belong_to_userrs F-h77  T y))) s1vv Ms38 A3'A..A3ctj|std|z tj|rg t jtj|jj S#t$r)ttj|jcYSwxYwtj |})NzPath %s should be absolute!) rrabspathrfr5rgetpwuidrst_uidrrrjrrs r1get_path_ownerrs 7??4 ?6=>>>% 7>>$   1 1|BGDMM$899AA 1 1 1274==/00000 1wt$$ %s/B0B65B6riterable chunk_sizec#Kt|}tt||}|r%|Vtt||}|#dSdS)a Generator that splits iterable on N-parts by chunk_size items in each chunk >>> list(split_for_chunk([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], chunk_size=2)) [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]] :param iterable: :param int chunk_size: :return: generator: N)iterrmr)rripieces r1split_for_chunkr sp XA :&& ' 'E , VAz**++ ,,,,,r0ct|tr+td|DSt|trt d|DS|S)Nc3>K|]\}}|t|fVdSrfreeze)rkeyr~s r1rzfreeze..s1JJ*#u#ve}}-JJJJJJr0c34K|]}t|VdSrr)rr~s r1rzfreeze..s(22uVE]]222222r0)rirBr4rrmrn)rIs r1rrsm!T3JJ JJJJJJ At  322222222 Hr0c&eZdZdZiZfdZxZS) Singletonzc Metaclass for creating only one instance of class, when providing the same arguments. c|t|t|f}|j|s(tt|j|i||j|<|j|Sr)r _instancesr5superrr)r6rIrJr __class__s r1rzSingleton.__call__srF4LL&..1~!!#&& "@% 3"7"7"@###CN3 ~c""r0)r(r)r*rXrr __classcell__)rs@r1rrsI J#########r0rctjdd5}|cdddS#1swxYwYdS)z3 :return str: server's external IP address zhttps://api.ipify.orgr]rN)urllibrequesturlopenrr)rs r1get_external_iprs    7  C C!qvvxx  !!!!!!!!!!!!!!!!!!s&AAAc<d}|||}tj|st d|d|t |d5}|}dddn #1swxYwY|S)z Reads parameter of kernel module from /sys/module/{module_name}/parameters/{parameter} :return str: value of the parameter z(/sys/module/{mod}/parameters/{parameter})mod parameterzCannot find parameter z for module rN)rrrr5rfrrr) module_namer! _MOD_PAR_PATH param_filepr~s r1get_kernel_module_parameterr&s ?M%%+%KKJ 7>>* % % j8A ;; O    j#  !!  !!!!!!!!!!!!!!! Ls'BBBcd}|D][\}}t|tr%||vs|s|||<d}(t|||}?||vs|sJ|d||||<d}\|S)zPerforms deep update of dict dst with values from src. Does not overwrite subdicts in dst blindly with new dicts in src, but does a deep update of (sub)dict content recursivelyFTz already exists in )rrirBdict_deep_update)dstsrcallow_overwriteupdatedr:r;s r1r(r(s G  1 a   ||1|A*3q6155  ---- /CFGG Nr0c8eZdZd dZdZdZdZdedefdZd S) TimedCacherct|tsJ||_||_t |_i|_dSr)rir expirationr2rcache_locks)rr0r2s r1rzTimedCache.__init__s<*i00000$  ]]  r0ct}|jD]J}|j|\}}tj|z |jkr||f||<K||_dS)zClear cache from expired valuesN)rr1r:r0 total_seconds)r tmp_cacherr~added_ats r1_collectzTimedCache._collectshMM : 1 1C"joOE8 h&$/*G*G*I*III!& # r0c:t|_i|_dSr)rr1r2rs r1r!zTimedCache.cache_clear!s ]]  r0c|}|r3t|}|t|z }t|S)z Generate key from call arguments :param args: call positional args :param kwargs: call keyword args :return: )rrrnhash)rrIrJseedkws r1 _make_keyzTimedCache._make_key%sB   ''B E"II DDzzr0funcr[ctfd}tfd}tjr|n|}j|_|S)a  Use it to cache calls to decorated function @TimedCache(expiration=timedelta(minutes=10)) async def func(*args, **kwargs): pass :param func: decorated function :return: NOTE: is not thread safe. chK||}j|}|tjx}j|< tj|jd{VnP#tj $r=|j|urtjx}j|<n j|}YnwxYw   j |\}}ns#t$rftj jkrj d|i|d{V}|t!jfj |<YnwxYw|n#|wxYw|S)NTFlast)r>r2r5rkrracquirer0r4 TimeoutErrorr7r1rrr2popitemr:release)rIrJrlockrrr?rs r1 wrapper_asyncz*TimedCache.__call__..wrapper_async?s..v..C;??3''D|*1,..8t{3' 00!* (E(E(G(G+ 0 0 0 t{3///29,..@t{3//#{3/ 0  0  : $ 3IFAA:::4:$,66 ***666#'4#8#8#8888888F&,dikk&9DJsOOO :   MsEABA C&%C&+FDFA-F>FFFF/cZ||} j|\}}nm#t$r`t jjkrjd|i|}|tjfj|<YnwxYw|S)NFrB)r7r>r1rrr2rFr:)rIrJrrrr?rs r1 wrapper_syncz)TimedCache.__call__..wrapper_syncbs MMOOO..v..C 6 JsO  6 6 6tz??dl22J&&E&222t.v.."($)++"5 3  6 Ms>A'B('B()rrkiscoroutinefunctionr!)rr?rIrKrLs`` r1rzTimedCache.__call__2s t       D t       *400 MM  #.r0N)r) r(r)r*rr7r!r>r rr/r0r1r.r.s   CQC1CCCCCCr0r.cftjtjtjdS)z Send SIGUSR2 to os.getpid() to shutdown agent process by signal (implies exit code -12). Agent will do failover restart then thanks to systemd (or chkservd) if it needs. N)rkillgetpidsignalSIGUSR2r/r0r1fail_agent_servicerR{s$GBIKK(((((r0c K|dttj}t |d5}|t tjj ||dt d||tjj |fi|d{V}t |dzd5}| d|jt!j|jdddn #1swxYwYdddn #1swxYwY|S) z Runs command and log it's output to the log file :param cmd: :param log_file_mask: :return: str path of log file *rTraz Popen(%r, %r)Nz.pidz{:d} {} )replacerjrrOrrurBrk subprocessrrZr<rlrrpidpsutilProcess create_timehex)r log_file_mask popen_kwargslive_log live_log_fprypfs r1run_cmd_and_logras$$S#bikk*:*:;;H h    (0"""&         _c<888'?           (V#S ) ) R HH##HfnTX66BBDDHHJJ                  & Os8BE A*D?3 E?E EE EEEceZdZdZdS)rc `|jdkr7|jr0|dd}|jr |j|d<|j| t j|dS#t$rt|j ddpt|j dd}t|j ddpt|j dd}t|j d dpt|j d d}|j }|r|j p|j }td ||j||YdSwxYw) NPENDINGz%Task was destroyed but it is pending!)taskmessagesource_tracebackr*r(gi_codecr_codegi_framecr_framez+!> Finalizer error in {}() {} at {} line {})_state_log_destroy_pending_source_traceback_loopcall_exception_handlerr__del__AttributeErrorgetattr_coro co_filenamef_linenoco_firstlinenoprintr)rcontextrrframerlinenos r1rqz Task.__del__s{ ;) # #(A #BG% E.2.D*+ J - -g 6 6 6  N4    4:~t<< JAAD4:y$777 It<<DDJ D99W J>>E'H.F43FF =DD$+x       sACD-,D-N)r(r)r*rqr/r0r1rrs#r0rcfd}|S)zReturn async callback which waits for *seconds*. Usage: @retry_on(Error, on_error=await_for(seconds=PAUSE_INTERVAL), timeout=T) async def coro(): 'here's something that may raise Error.' c<Ktjd{VSr)rkr)rIr^s r1pausezawait_for..pauses)]7+++++++++r0r/)r^r~s` r1rrrrs#,,,,, Lr0cftgstdfd}|S)a5 Retry the function call on exception (or exceptions, if given in tuple) at most *max_tries*. Await *on_error* (if set) for each exception. If *timeout* is set, stop all attempts in *timeout* seconds. If *silent* is set to True - don't raise exceptions after max tries or timeout. zSet any of max_tries, timeoutctjfd}tjfd}tjr|S|S)NcNK rtj z} stjdnt d dzD]} rg|tjz }|dkr$t j|i||d{VcS s t jrdn|i|d{VcS}#t jt j f$r$r@}| kr srd|  ||d{VYd}~d}~wwxYwdS)Nrrr Timeout exceeded when calling %s0Max tries exceeded when calling %s with error %s) r:r; itertoolscountrrkrrErr rIrJend_timer remaining_timerrr?r?r_r`silentrs r1rIz2retry_on..decorator..wrapper_asyncs 6>++g5!- """1i!m,,# /# / /;)1DN4D4D)D)A--)0)9 $d 5f 5 5~***$$$$$$$*"&-&: :!$" # $F!"!"!"&*T4%:6%:%::::::::::,g.DE / / /I~~%! II!, $ #   +&hsA......... //# /# /s?C 4C D""6DD"c rtj z} stjdnt d dzD]} rH|tjz }|dkr |i|cS st rdn |i|cSX#$r:}| kr srd|  ||Yd}~d}~wwxYwdS)Nrrrr)r:r;rrrrErrs r1rKz1retry_on..decorator..wrapper_syncsm 6>++g5!- """1i!m,, ) ) ) 5)1DN4D4D)D)A--#'4#8#8#8888#)"&2 2!$" # $F!"!"!" $tT4V44444 ) ) )I~~%! II!, $ #   + a((( )' ) )s%B.)BC 0CCrNrrkrL) r?rIrKrr?r_r`rrs ` r1rPzretry_on..decorators   & /& /& /& /& /& /& /& /& /& /  & /P   " )" )" )" )" )" )" )" )" )" )  " )H  &t , ,   r0)rrf)rr`r_rrr?rPs`````` r1rprpss  7# $ $:8999R R R R R R R R R R h r0ctjfd}tjfd}tjr|n|S)zhIf func throws an exception it is catched, converted to a string and returned as a result of a call.crK |i|d{VS#t$r}t|cYd}~Sd}~wwxYwrrreprrIrJrr?s r1rIz,stub_unexpected_error..wrapper_asyncFsg t.v........ .   77NNNNNN s  6166cb |i|S#t$r}t|cYd}~Sd}~wwxYwrrrs r1rKz+stub_unexpected_error..wrapper_syncMsQ 4((( (   77NNNNNN s .)..r)r?rIrKs` r1stub_unexpected_errorrBs_T _T $7== O==<Or0c2 tjfd}|S)zkA decorator that logs uncaught exceptions ignoring them otherwise. CancelledError is not handled. Nctjfd}tjfd}tjr|S|S)Nc K |i|d{VS#tj$r$r'}dtdd|Yd}~dSd}~wwxYwNzIgnoring exception from %s: %sr*r)rkrrsrIrJrrr log_handlers r1rIz>log_error_and_ignore..decorator..wrapper_async`s !T426222222222)       4D.&99 s AA  Ac t |i|S#$r'}dtdd|Yd}~dSd}~wwxYwr)rsrs r1rKz=log_error_and_ignore..decorator..wrapper_syncms tT,V,,,    4D.&99 s 727r)rrIrKrrs` r1rPz'log_error_and_ignore..decorator_s                          &t , ,   r0)rZr)rrrPs`` r1log_error_and_ignorerWs9 l       < r0cfd}|S)z'Abort the agent service on *exception*.cLtjfd}|S)NcK |i|d{VS#$r/}t|Yd}~dSd}~wwxYwr)rZr)rIrJrabortrrs r1rLz2abort_agent_on..decorator..wrappers !T426222222222     ###  s A$AArM)rrLrrs` r1rPz!abort_agent_on..decoratorsC            r0r/)rrrPs`` r1abort_agent_onrs*       r0cRtjdd|S)zPascalCase to snake_casez([a-z])([A-Z])z\1_\2)rsubrE)strings r1 snake_casers# 6"Hf 5 5 ; ; = ==r0)exec_expr_with_empty_iterc'K|s|rdg}nt|t}ddlm}|j5|D]}||g|REd{V ddddS#1swxYwYdS)a] Get iterator over results of sql expression expr. Given iterable will be split for chunks and we will return iterator containing results of all split queries. Useful for sql selects with in_() in order to avoid too many sql variables error. If exec_expr_with_empty_iter is True and iterable is None(empty) we will process expression once, passing here chunk=None expr(None, *args) :param expr: :param iterable: :param exec_expr_with_empty_iter: if iterable is None(empty) process given expression once, passing here chunk=None expr(None, *args) :return: Nrrinstance)r CHUNK_SIZE_SQL_QUERYdefence360agent.modelrdb transaction)exprrrrIchunksrrys r1get_results_iterable_expressionrs& L1L 6JKKK......  " "** * *EtE)D))) ) ) ) ) ) ) ) ) *******************sA##A'*A'rcd}ddlm}|j5t ||D] }|||g|Rz }! dddn #1swxYwY|S)z Get number of results of sql expression expr. Given iterable will be split for chunks and we will return number of results of all split queries. Useful for sql delete with in_() in order to avoid too many sql variables error rrrN)rrrrr execute)rrrrIrrrys r1execute_iterable_expressionrsG......  " "44$X*EEE 4 4E ttE)D)))1133 3GG 4444444444444444 Ns3A""A&)A&cXtj|dddzS)Nr\nr)rfsencoderUrs r1encode_filenamers% ;t||D%00 1 1E 99r0cbtj|ddddS)Nr%rr)rfsdecoderUrs r1decode_filenamers+ ;t  SbS ! ) )% 6 66r0cNtjtj|Sr)base64 b64encoderrrs r1base64_encode_filenamers  BK-- . ..r0b64namechttjtj|Sr)rrrr b64decode)rs r1base64_decode_filenamers%  F,W5566 7 77r0cV tj|}n#t$rd}YnwxYw|S)zS Like pwd.getpwnam(username) but returns None instead of raising KeyError. N)rrr)rrs r1rrsAh''  Ms  &&c>tt|||S)zH Put the specified `value` inside the [`low`, `high`] interval. )maxmin)r~lowhighs r1cliprs s5$ % %%r0r.crfd}||i|}|||S)z Use this function in plugin initialization instead of loop.create_task to be able to see the exceptions from the specified coroutine. c|sA|/d||ddSdSdS)Nz1Unhandled exception during plugin initialization!)rfrre) cancelledrrp)rer~s r1_log_exceptionz6create_task_and_log_exceptions.._log_exceptionsv~~ DNN$4$4$@  ' 'L!%!1!1        $@$@r0) create_taskadd_done_callback)r~rrIrJrnew_tasks` r1create_task_and_log_exceptionsrsY     d 5f 5 566H ~... Or0cfd}|S)a5 Create coroutine from regular function Useful to pass functions to APIs requiring coroutines Note: coroutine will still block event loop in main thread. For most blocking functions, run_in_executor should be considered instead :param function: :return: coroutine running function cK|i|Srr/)rIrJfunctions r1rzmake_coro..corosx((((r0r/)rrs` r1 make_coror s#))))) Kr0cK|tkr tj}n tj}|dt |ddx}rd|dnd||t jtd{VdS)Nz7Failed to copy data%s to modsec ruleset dir %r, try: %srz ()r)COPY_TO_MODSEC_MAXTRIESrZrrrsrkr_MODSEC_COPY_FAILURE_TIMEOUT)rr r?fns r1log_failed_to_copy_to_modsecrs ###lnCA$S*d;;;rD R "   -4 5 5555555555r0c tt5tstr/t dr ddddSdddn #1swxYwYdS)NrTF)r rfr'rXr^r%rr/r0r1is_centos6_or_cloudlinux6r+s *    # # % % )6)D)D)F)F ll%%c**   5sABB B) err_buf_sizerc 4Kd}t|}tj|dtjjtjjd|d{V} tj||j||j23d{V}|WV 6 |d{V}|dkr%t||dd |dS#|d{V}|dkr%t||dd |wxYw)z Start *cmd*, yield its stdout line by line [b' '] If *cmd* return nonzero exit status, raise CheckRunError with the last *err_buf_size* lines from stderr. cJK|23d{V}||6dSr)append)pipebufr9s r1read_pipe_intoz1readlines_from_cmd_output..read_pipe_into?sL       $ JJt    $$s")maxlenT)rercrdNrr0) rrkrorVrhrrdrcrtrr)rrr]rerr_bufryr9rs r1readlines_from_cmd_outputr5s<(((G/ !&!&         D I NN4;@@AAA+       $JJJJJ&+ 99;;&&&&&& ?? Cchhw6G6GHH H ? 99;;&&&&&& ?? Cchhw6G6GHH H H H H Hs*C:BCADr])r_delaycKtd|dzD]3}||d{V}|s!||krtj|d{V0|cSdS)z Retry *predicate_coro(*args)* until it becomes true, but no more than *max_tries* attempts. Sleep for *delay* seconds before the next *predicate_coro()* call. Return whether the predicate became true. rN)rrkr)predicate_coror_rrIattemptrs r1finally_happenedrWsIM**%~t,,,,,,, 'I---&& & & & & & & &  r0'cKt|dD]-\}}|WV||zdkrtjdd{V.dS)z6Yield to the event loop every *chunk_size* iterations.r)r@rN) enumeraterkr)rrr items r1 nice_iteratorrgsoXQ///##4 Nq -"" " " " " " " "##r0ceZdZdZdZdZdS)LazyLocka Descriptor object to share async Lock between client objects. Used in order to achieve lazy evaluation of the lock and share state between it's clients. Using asyncio.Lock in client code directly: >>> class Foo: >>> lock = asyncio.Lock() leads to an unclear error ([Errno 9] Bad file descriptor), when trying to move this Lock during demonization process. cd|_dSr)rr9s r1rzLazyLock.__init__s  r0cN|jstj|_|jSr)rrkr)rrowners r1__get__zLazyLock.__get__s!z ( DJzr0N)r(r)r*rXrrr/r0r1rrqs<  r0rctj||x}r'|dSdS)Nr)rrr r)regexrms r1_get_system_package_versionrsA IeV $ $$q"wwqzz!!!""r0c~tstrddgdfSddgdfS)Nz dpkg-queryz-lz(?m)^ii\s+{}\s+(\S+).*rpmz-qz{}-([\d\.]*-\d*))r'r[rcr/r0r1_get_cmd_n_regexrsJ  4M$;$;$=$=4t$&?@@ 233r0ceZdZdZdS)FirewallDisabledExceptionz;Exception in case of using firewall api, when it's disabledNrr/r0r1rrsEEEEr0rc<tfd}|S)NcKtjdrtd|i|d{VS)Nz!/var/imunify360/firewall_disabledz"Not available in the current build)rrr5r)rIrJr?s r1rLz(check_disabled_firewall..wrappers\ 7>>= > > +4 T4*6*********r0r)r?rLs` r1check_disabled_firewallrs3 4[[++++[+ Nr0cKt\}t|t|zddd{Vfd|DS)a Retrieves the version of the specified system packages using a command and regex specific to the current system. Parameters: packages (Set[str]): A set of package names to retrieve version for. Returns: A dictionary mapping package names to their corresponding version strings, or None if the package is not installed or version information cannot be retrieved. F)rrNcXi|]&}|t|'Sr/)rr)r package_namerversion_regexps r1 z(system_packages_info..sK     1  ! !, / /     r0)rsafe_run_with_timeoutrm)packagesrrr s @@r1system_packages_infors+,,C( d8nnb5F     %    r0cK tjt|fi||d{VS#tj$r|d|YdSwxYw)Nrz#Command %s failed: Timeout occurredr)rkrrrE)rurr?rJs r1r r s% W ' ' ' '              17;;;rrs&+A  A nc#K|dkrtdt|}tt||x}r%|Vtt||x}#dSdS)Nrzn must be at least one)rfr rmr)rritbatchs r1batchedrs  1uu1222 hBr1 && &% r1 && &%r0rIc#RKt|D]}fd|DVdS)Nc"i|] }|| Sr/r/)rr:rIs r1r z batched_dict..s&&&1q!A$&&&r0)r)rIrrs` r1 batched_dictrsKA''&&&&&&&&&&&''r0cn tjddgd}|d}|s?t drtjddgd}d|vrd}|S#t $r&}td |Yd}~d Sd}~wwxYw) Nhostnamez-fT)text)z.cloudwaysapps.comz.cloudwaysstagingapps.comz/usr/local/sbin/apminfo Cloudwaysz$Error while checking environment: %sF) rg check_outputrrrr5rrZr)r _is_cloudwaysrrs r1 is_cloudwaysrs+  T   %'' !)) ?   %&;!r<s7   ********////////::::::::::222222222222''''''                      GCx     8 $ $ d0116d344 "d#BCC$899+++++D+++Q     K K K K4T    4        00 3u 0000f 0      K2    (5  5    .; ' ' ' ' ' ,   ++++++++@        :?;;;;F   OOO OOOOdQ ? ?C ? ? ? ?h'h'h'h'h'h'h'h'X%[4 A A A58 A A A A A #### 38_ ####26<     $)#         5 T         5 T    %%%--------`0E6D&3#$ % % % , ,h ,C ,) , , , ,    ########"R   !!! !"2eeeeeeeeP )))B7<B   $   ggggTPPP*$-$&&&&R%7&>>> 6;*****@';&:::777//%////8E8d8888&&&i(4      6 6 6Q %(III cIIIID=>Q      ####0""" Q44 4FFFFF FFF   D07=l     'DcN's'''' Q r0