) dZddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z ddl m Z ddl mZddlmZddlmZmZdd lmZdd lmZdd lmZdd lmZmZmZdd lm Z ddl!m"Z#ddl$m%Z%ddl&m'Z'ddl(m)Z)m*Z*ddl+m,Z,dZ-dZ.ej/e0Z1edde2e3e4e3ffdZ5de3de3de4fdZ6e dde7fdZ8dZ9d e3d!e4de4fd"Z:de3d#e3de4e3fd$Z;d%e'd e3dee3fd&Zd)Z?d*e@d+e@d e3d%e'd,e2de2f d-ZAd.e3d/eBd0eBddfd1ZCd2e2de3fd3ZDd4ed/eBd0eBddfd5ZEd%e'd6ejFdefd7ZGdS)8u  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) defaultdict)datetime timedelta) lru_cache)Path)Optional)choose_value_from_configMalwareScanScheduleInterval) LicenseCLN) HostingPanel)Plesk)async_lru_cacheatomic_rewrite check_run) MalwareHit)QueueSupervisorSync) user_list)WPSite)cliWP_CLI_WRAPPER_PATH)PHPErrorz/usr/sbin/cagefs_enter_userz/usr/sbin/cagefsctl<)ttlreturncKt}|d{V}tt}|D]%\}}|D]}|||&|S)zN Get a mapping of docroots to their associated domains, with caching. N)r get_domain_pathsrlistitemsappend) hosting_panel panel_paths docroot_mapdomaindocrootsdocroots I/opt/imunify360/venv/lib/python3.11/site-packages/imav/wordpress/utils.pyrr>s !NNM%6688888888Kd##K'--//00 0 0G  ' ' / / / / 0 php_pathr%c0tt||gS)zGet wp cli common command list)strr)r(r%s r& wp_wrapperr+Ls # $ $h 88r')maxsizectjtr$tjttjst Stjtdgdd}|j dkrt S|j d}t |ddS)z)Get the list of users enabled for CageFS.z--list-enabledT)capture_outputtextr r,N) ospathisfileCAGEFS_CTL_PATHaccessX_OKset subprocessrun returncodestdoutstripsplit)resultliness r&get_cagefs_enabled_usersrAQs 7>>/ * *")33uu ^ *+DtFAuu M   ! ! ' ' - -E uQRRy>>r'c8tdS)z-Clear the cache for get_cagefs_enabled_users.N)rA cache_clearr'r&$clear_get_cagefs_enabled_users_cacherEcs((*****r'usernameargsc|tvrTtjtr0tjttjr td|g|Sddd|dtj|gS)zNBuild the necessary command to run the given cmdline args with specified user.z--no-io-and-memory-limitsuz-sz /bin/bashz-c) rAr2r3r4CAGEFS_ENTER_PATHr6r7shlexjoin)rFrGs r&build_command_for_userrMhs+---- 7>>+ , ,  rw2 2  "*      4  r'domain_to_excludecxKtd{V}||g}fd|DS)z Get all domains associated with a given document root, excluding one domain. It's panel-agnostic and uses a cached mapping. Nc g|] }|k| SrDrD).0r#rNs r& z+get_domains_for_docroot..s$ L L Lv:K0K0KF0K0K0Kr')rget)r%rNr" all_domainss ` r&get_domains_for_docrootrUsS)********K//'2..K L L L L L L LLr'sitecP Kddlm}m}|| dtdttf fd }||j}|r|St |j|jd{V}|D]}||}|r|cStd|jd ) z/Determine PHP binary path for the given WPSite.r)get_domains_php_infoget_installed_php_versionsr#rc|}|r|dkrdS|d}|sdSD]2}|d|kr|dcS3dS)NrFdisplay_version identifierbin)rS)r# domain_infophp_display_version php_versiondomains_php_infoinstalled_php_versionsrFs r&find_php_binary_for_domainz7get_php_binary_path..find_php_binary_for_domains&**622  kooj99XEE4)oo.?@@" 41 . .K|,,0CCC"u-----Dtr')rNNz+PHP binary was not identified for docroot: z , username: ) clcommon.cpapirXrYr*rr#rUr%r) rVrFrXrYrcphp_binary_pathdomainsr#rarbs ` @@r&get_php_binary_pathrgsX ,+--7799 3 8C=        10==O,  G##44V<<  #" " " " #  dl       r'c6tj|\}}|S)z Get malware history for the specified user. This is an equivalent of calling `imunify360-agent malware history list --user {username}`. `` )user)rmalicious_list)rF max_counthitss r&get_malware_historyrms!#1x@@@Y Kr'cKt|}tj|j|hd{V\}}|siStj|dd}|dS)z Get the last scan for the specified user. This is an equivalent of calling `imunify360-agent malware user list --user {username}`. )matchN scan_dateT)descr) ScanQueuerfetch_user_listget_scans_from_pathssort)sinkrFqueue_userss r& get_last_scanrzs dOOE. "8*HAu  N5+D 9 9 9E 8Or'c h tj}|tjkrF||ddd}||kr|t dz }|S|tjkrt||dzdzz dzdz}|dkr |j |krd}|t |z}||dddS|tj krddl m  fd}|j |kp5|j |ko |j |kp| |j|jdk} | r7||j|j|\} } ||| | |ddd}n|||ddd }|Sd S) a Calculate the next scan timestamp based on schedule configuration. Args: interval: Scan interval (DAY, WEEK, MONTH, or NONE) hour: Hour of day to run scan (0-23) day_of_month: Day of month to run scan (1-31) day_of_week: Day of week to run scan (0-6, where 0=Sunday) Returns: Timestamp of next scan, or None if interval is NONE r)hourminutesecond microsecondr,)days) monthrangec||}}|dz }|dkrd}|dz } ||d}||kr||fS|dz }|dkrd}|dz }/)z;Find the next month that has at least given number of days.r, rD)yearmonthr current_year current_month days_in_monthrs r&find_next_suitable_monthz?calculate_next_scan_timestamp..find_next_suitable_months*.-L Q Mr!! ! !  & * < G G J =(('66"  2%%$%M A%L &r')dayrrr|r}r~r)rr|r}r~rN)rutcnowIntervalDAYreplacer timestampWEEKweekdayr|MONTHcalendarrrrr) intervalr| day_of_month day_of_weektoday next_scan days_aheadnext_scan_datershould_advance_month next_year next_monthrs @r&calculate_next_scan_timestamprs9 O  E8<MM "  I   *** *I""$$$8=  "U]]__q%8A$==AQF ??uzT11J !;!;!;;%%aq&  )++ 8>!!'''''' & & & & &0 I $ E \)@ejD.@ EjjU[AA!DD   $<$< EK%% !Iz#]]  +NN#]]  +N'')))w"!r'last_scan_timenext_scan_timemalware_by_sitecgd}i}|D]B\}}||vri||< t|||\} } n#t$rd} YnwxYw| |||<C|||||jg|t jdS)a8 Prepare scan data JSON for a WordPress site. Args: last_scan_time: Timestamp of the last scan next_scan_time: Timestamp of the next scheduled scan username: Username of the site owner site: WordPress site object malware_by_site: Dictionary mapping site docroots to their malware hits Returns: dict: JSON data ready to be written to scan_data.php. The response includes: - lastScanTimestamp: Timestamp of the last scan - nextScanTimestamp: Timestamp of the next scheduled scan - username: Username of the site owner - malware: List of malware hits for the site - config: Configuration items for the site - license: License information including status and eligibility for Imunify patch ))MALWARE_SCANNINGenable_scan_cpanel)rdefault_action)PROACTIVE_DEFENCEblamer)rFN)lastScanTimestampnextScanTimestamprFmalwareconfiglicense)r KeyErrorrSr%r license_info) rrrFrVrconfig_sections config_itemssectionoptionvaluerxs r&prepare_scan_datar8s6OL* . . , & &$&L ! /!HE11    EEE (- Wf%%,+"&&t|R88*,,   s . ==contentuidgidc|s|tjtjkrdnd}t ||d|||dS)a  Helper function to write a plugin data file atomically with optional touch. Args: file_path: Path to the file to write content: Content to write to the file uid: User ID for file ownership gid: Group ID for file ownership i F)backuprr permissionsN)existstouchr NAMEr r) file_pathrrrrs r&!write_plugin_data_file_atomicallyrssy     (>>.%*<<%%%K   r'datac^dtj|ddzdzS)al Format a dictionary as a PHP file that returns JSON-decoded data. This creates a WordPress-safe PHP file that: 1. Checks if it's being included from WordPress (WPINC defined) 2. Returns the data as a decoded JSON string Args: data: Dictionary to embed in the PHP file Returns: Formatted PHP file content as a string zB )z .htaccessz index.phpz index.htmlrrN)rrr)rrrprotection_filesfilenamerrs r&#ensure_directory_listing_protectionrsLDD .3355'x' !!  -7    r' user_infoc"Ktj|d{V}tj|rt dt ||st|j ddt |g}t|d{V|s#t dt ||j | dt||j |j|S)a% Ensure the site's data directory exists with correct permissions. Args: site: WordPress site user_info: User information from pwd Returns: Path to data directory Raises: Exception: If the data directory is a symlink or cannot be created Nz)Data directory %s is a symlink, skipping.mkdirz-pz)Failed to create directory %s for user %sir)r get_data_dirr2r3islink Exceptionr*rrMpw_namerchmodrrpw_gid)rVrrcommands r&ensure_site_data_directoryrs. %d++++++++H w~~h  7X    ??  (   dCMM *              ;H !  u(dhI$4 Or')H__doc__rloggingr2pwdrKr9 collectionsrrr functoolsrpathlibrtypingr defence360agent.contracts.configr r r!defence360agent.contracts.licenser +defence360agent.subsys.panels.hosting_panelr #defence360agent.subsys.panels.pleskr defence360agent.utilsrrrimav.malwarelib.modelr*imav.malwarelib.scan.queue_supervisor_syncrrrimav.malwarelib.utilsrimav.model.wordpressrimav.wordpressrrimav.wordpress.exceptionrrJr5 getLogger__name__loggerdictr*rrr+r8rArErMrUrgrmrzrfloatrintrrr struct_passwdrrDr'r&rs{*  ######((((((((988888DDDDDD555555LLLLLLLLLL,,,,,,,+++++''''''.-----1'  8 $ $R S$s)^ 4    99s9t9999  1#"+++ S. M  M%( M #Y M M M M)F)c)hsm))))X#$$a*a*a*H8888  8  8  8888v"%,/ 82#& 8- - .- ------r'