="+Z dZddlZddlZddlZddlZddlmZddlmZm Z m Z m Z ddl m Z mZddlmZmZddlmZddlmZdd lmZdd lmZdd lmZmZdd lmZmZdd l m!Z!ej"e#Z$ej%&ej%j'zrdZ(ndZ(ej)*dej+Z,ej)*ddZ-ej)*ddZ.e/ej)*ddZ0dZ1dZ2dZ3dZ4dZ5Gdde6Z7Gdde7Z8Gd d!e8Z9Gd"d#e8Z:Gd$d%e8Z;Gd&d'e8Z<Gd(d)ej=Z>d*Z? d?d+e@e>zfd,ZAe4fd+e@e>zfd-ZBd.ejCd/eDd0eEeFejCffd1ZGd2ZHe4dfd+e@e>zfd3ZIe4dd4d+e@e>zfd5ZJeGd6d7ZKe4e5fd8ejLd9e e@d0e e e@dffd:ZMejNe6ejOejP;d8ejLdZSdS)@u  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.  If not, see . Copyright © 2019 Cloud Linux Software Inc. This software is also available under ImunifyAV commercial license, see N) dataclass)AnyAsyncGeneratorIterableList)quote_from_bytesurljoin)Requesturlopen)utils) inactivity)Core)Malware) LicenseCLN LicenseError)IAIDTokenErrorIndependentAgentIDAPI) MalwareTunez/opt/alt/curlssl/usr/bin/curlz/opt/alt/curlssl11/usr/bin/curlI360_MRS_API_BASE_URLI360_MRS_ENDPOINT_UPLOADz api/v1/uploadI360_MRS_ENDPOINT_CHECKzapi/v1/check-known-hashesIMUNIFY360_POST_FILE_TIMEOUTifalse_negativefalse_positiveunknowniceZdZdZdS) UploadFailurezBase for upload failuresN__name__ __module__ __qualname____doc__[/opt/imunify360/venv/lib/python3.11/site-packages/imav/malwarelib/utils/malware_response.pyrrAs""""r%rceZdZdZdS)ClientUploadErrorz!A client error during file uploadNrr$r%r&r(r(Es++++r%r(ceZdZdZdS)ConnectionErrorz%A connection error during file uploadNrr$r%r&r*r*Is////r%r*ceZdZdZdS) TimeoutErrorzA timeout during file uploadNrr$r%r&r,r,Ms&&&&r%r,ceZdZdZdS)FileTooLargeErrorz File is too large to be uploadedNrr$r%r&r.r.Qs****r%r.c$eZdZfdZdZxZS)UploadFileResponseErrorcVt||_dSN)super__init__response)selfr5 __class__s r&r4z UploadFileResponseError.__init__Vs$   r%cd|jS)Nzfailed with response: )r5r6s r&__str__zUploadFileResponseError.__str__Zs7 777r%)r r!r"r4r: __classcell__)r7s@r&r0r0UsG!!!!!8888888r%r0cXeZdZdZd dededzfdZedZdZdZ d Z d Z dS) MalwareHitPathzm Wrapper that is used to send a file whose original contents may be located in a different path. N content_path real_pathc"||_||_dSr2) _content_path _real_path)r6r>r?s r&r4zMalwareHitPath.__init__ds)#r%c|jSr2)rAr9s r&r>zMalwareHitPath.content_pathhs !!r%ct|tr |j|jko|j|jkS|j|kSr2) isinstancer=rArB)r6others r&__eq__zMalwareHitPath.__eq__lsI e^ , , "e&998Ou'77 !U**r%c,|j|jS|jSr2)rBr>r9s r&r:zMalwareHitPath.__str__ts ? &? "  r%c*|Sr2r:r9s r&__repr__zMalwareHitPath.__repr__y||~~r%c*|Sr2rJr9s r& __fspath__zMalwareHitPath.__fspath__|rLr%r2) r r!r"r#strr4propertyr>rGr:rKrNr$r%r&r=r=^s $$S$S4Z$$$$""X"+++!!! r%r=ctj}|d|d|d|d|d|dd}d|D}|S) Nidlimitstatustoken_expire_utctoken_created_utcsign)zI360-Idz I360-Limitz I360-StatuszI360-Token-Expire-UtczI360-Token-Created-Utcz I360-Signc4i|]\}}|t|Sr$)rO).0keyvalues r& z%_token_to_headers..s$AAA:3sCJJAAAr%)r get_tokenitems)tokenheaderss r&_token_to_headersrasm  " "E;GnX!&'9!:"'(;"<6] GBAAAAG Nr%filec vK|i}d|D}|}t|tr|j}t t j|dd}t jtg|zdt|dg|duzzddt j| d d  d d |fzd dd|dgz}tj |d{V\}} } |dkrz|dkrtd|dkrt|d} d| || | } |dkrt!| t| | S)a Post *file* as multipart/form-data to *url* with given HTTP *headers*. Return server response as bytes (http body). Raise TimeoutError on timeout. Raise ConnectionError if failed to connect to host. Raise ClientUploadError on error. Ncng|]2\}}d|d|dfz3S)s-H%s: %sasciizlatin-1)encode)rYheaderr[s r& z_post_file..sN FE v}}W--u||I/F/FGGr%)saferes --max-times--formsfile=@"%s";filename="%s"\s\\"s\"s--fails--silents --show-errorrzUpload timed outcxt|trt|ddSt|S)N)rEbytesrepr)r[s r& _safe_textz_post_file.._safe_texts5eU++-;;qt,,E{{"r%z#Failed to post file to {url}: {err})urlerr)r^rEr=r>rosfsencoderf_CURLrOreplacer runr,r(formatr*) rbrur`timeout headers_argsr>quoted_full_pathcmdrcoutrvrtsafe_msgs r& _post_filers$]]__LL$'')( ' D(9(9CCCJJ U     #g,,--g66 77$;N O P  ' L))((v&&      JJw    ,3''''''LBS Qww 88122 2 2XX#D)) ) # # # >EEJsOOJsOOFHQww%h///'111 Jr%cKtjstdt|tr|jn|}t j|}|tj kr.td ||tj ttt}it!d|i}t#|||t$d{V}t'j|}t,d|||ddkrt3||S) z Upload a file to Malware Response Service. :param file: path to file :param upload_reason: one of 'unknown', 'false_positive', 'false_negative' :return: dict representing json response :raises LicenseError: zCFile uploading to Malware Responce Serivce requires a valid licensez@File {} is {} bytes, files larger than {} bytes are not allowed.I360-Upload-Reasonr~NzUploaded file %r to the Malware Response Service with reason: %s. More info: https://blog.imunify360.com/malware-protection-powered-by-imunify-cloudavrTok)ris_validrrEr=r>rxpathgetsizeConfigMAX_MRS_UPLOAD_FILEr.r}r _API_BASE_URL_ENDPOINT_UPLOADrar_POST_FILE_TIMEOUTjsonloadsdecodeloggerinfogetr0)rb upload_reasonr> file_sizerur` response_bodyresults r& upload_filers     '   (n==G4 --I6--- %vi!;      -!1 2 2C   mG% c7$6MZ ,,.. / /F KK U  zz(t##%f--- Mr%futurer~returncKtj|} tj||d{Vd|fS#tj$r7td|dd|fcYSwxYw)a) Wait for the future to complete for the specified timeout. Returns (timed_out, shielded_future) where: - timed_out: True if timeout occurred, False if future completed - shielded_future: The shielded future that can be awaited later Does not cancel the future on timeout. NFz3Upload task timed out. Will continue in background.cBtj|tjdS)Nz+Background upload task failed after timeout)r log_future_errorsrwarning)futs r&z¬ify_after_timeout..s/=r%T)asyncioshieldwait_forr,rradd_done_callback)rr~shieldeds r&notify_after_timeoutrs~f%%H x111111111h     LMMM""     X~ s7AA=<A=clKtd||tjd t |t r|jn|}tj |s=t d| tj ddSgd}t|dz}|}t|dD]\}}td||||tj|d{Vtj |s=t d |tj ddSt#|d | d{V}|s=t d |tj ddS|rtd ||tj ddS#tj dwxYw)z9Helper coroutine to run the retry loop in the background.zQInitial upload failed for %s, reason: %s. Starting retry mechanism in background.zmrs-background-uploadz?File %s no longer exists. Cancelling background upload retries.N)g?g@(d)startzBBackground retry attempt %d/%d for file %s. Retrying in %s secondsz?File %s was deleted during retry. Cancelling background upload.F) raise_errorsrz,Background upload for %s succeeded on retry.zBBackground upload for %s failed after all retries. Final error: %s)rrr trackrrEr=r>rxrexistsrstoplen enumeratersleep _try_uploaderror) rbr initial_errorr>delays max_triesripauses r&_run_retries_in_backgroundr s NN   233367",D.!A!A KD  t w~~l++  KK    V 566666S100KK!O !&222  HAu NN    -&& & & & & & & &7>>,//   & 566666#&5 E  BD 566666    LL     566666 56666sAH9B!H;6HH!H3cKt|tr|jn|}tj|st d|dtj d t|d||d{V}n#tj $rwxYw tj dn$#tj dwxYwt|trtd|dtj d  t|d||d{V}n#tj $rwxYw tj d n$#tj d wxYw|sdSt|t"r|t|t$rtd ||t|tt frFtj}|t+|||t#d |r|dS) a :param file: File to upload :param upload_reason: Reason for upload :param notify_timeout: Time in seconds after which to notify as pending but continue upload :raises LicenseError, ClientUploadError, ConnectionError, FileTooLargeError, zFile z does not exist.z mrs-uploadF)rrnotify_timeoutNzConnection error for z , retrying.zmrs-upload-retryz#File %s is too big. Will not retry.z2Initial connection failed. Retrying in background.)rEr=r>rxrrr(r rrrrCancelledErrorrr*rrr,r.get_event_loop create_taskr)rbrrr>rloops r&upload_with_retriesrcs(n==G4 7>>, ' 'H F F F FGGG<((( ,! ')            !   l++++ l++++%)) 6@t@@@AAA1222 6%"+- EE %         ! !"4 5 5 5 5J  ! !"4 5 5 5 5 t%&& %*++> %''  &t]E B B    @     4s<3B C BC!C#9EFE$$F!F))rrcK |_tjt||}t||d{V\}}|rt d}d|_|S|d{Vnt||d{VnK#t tttf$r+}t d|||r|cYd}~Sd}~wwxYwdS)a;Return error instead of raising it unless *raise_errors* is true. :param notify_timeout: If set, returns TimeoutError after this many seconds but continues upload :raises LicenseError: :raises ClientUploadError, TimeoutError, ConnectionError, FileTooLargeError: if raise_errors is True N)rUpload notification timeout)rz#Failed to upload file %s. Error: %s) rrrrr,argsr(r*r.rdebug) rbrrr upload_task timed_outrres r&rrs0   %!-D >>>K)=^))###### Ix $%BCC=  NNNNNNNNd-@@@ @ @ @ @ @ @ @       :D!DDD     4s$AA= A==C C:CCc$eZdZUeed<eed<dS)HitInforbhashN)r r!r"rO__annotations__r$r%r&rrs" III IIIIIr%rrhashesc Kt|}tjr!td|WVdS t jd{V}n3#t$r&}td|Yd}~dSd}~wwxYwttt}||dd}tj ||}tjdtj5|D]} d| i} tjdt!| d tj5 t#|t%|t'j| |d d{V} | d WVn2#t,$r%}td |Yd}~nd}~wwxYwdddn #1swxYwY ddddS#1swxYwYdS)Nz0NO_CHECK_KNOWN_HASHES is enabled, skipping checkz Failed to acquire IAID token: %szapplication/json)zX-Authrz Content-TypezCheck known hashes)logrzCheck z hashesPOST)datar`methodunknown_hashesz Failed to check known hashes: %s)listrNO_CHECK_KNOWN_HASHESrrrr]rrr r_ENDPOINT_CHECKr split_for_chunktimeitrr _do_requestr rdumpsrf Exception) rrr chunk_sizer_rrur`chunkschunkrequestrs r&check_known_hashesrs &\\F( GHHH +577777777 91=== - 1 1C+*G  "6: 6 6F * < < <JJ J JE'G:s5zz::: LLL J J J#.!%G!4!4!;!;!=!=$+#) $$F!!1222222 JJJNN#EqIIIIIIIIJ J J J J J J J J J J J J J J J JJJJJJJJJJJJJJJJJJJsyA B $BB ":G F3AE54F35 F$ ?F F3F$ $F3' G 3F7 7G :F7 ;G  GG)on_errorr~rcJK|dt|d{VSr2)run_in_executor_do_request_sync)rrs r&rrsG%%       r%ctd|jt|tj5}|jdkrGtd|jtd |jtj | cdddS#1swxYwYdS)Nz Requesting %srrzHTTP response status code is %szstatus code is {})rrfull_urlr rDEFAULT_SOCKET_TIMEOUTrTrrr}rrreadr)rr5s r&rrs KK!1222 $"= > > >4( ?c ! ! NNrs*  !!!!!!66666666666622222222++++++++!!!!!!******111111>>>>>>FFFFFFFF.-----  8 $ $  5#6#==. +EE -E 68IJJ :>>"