Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace core\check\environment;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  use core\check\check;
  22  use core\check\result;
  23  
  24  /**
  25   * Checks status of antivirus scanners by looking back at any recent scans.
  26   *
  27   * @package    core
  28   * @category   check
  29   * @author     Kevin Pham <kevinpham@catalyst-au.net>
  30   * @copyright  Catalyst IT, 2021
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class antivirus extends check {
  34  
  35      /**
  36       * Get the short check name
  37       *
  38       * @return string
  39       */
  40      public function get_name(): string {
  41          return get_string('check_antivirus_name', 'report_security');
  42      }
  43  
  44      /**
  45       * A link to a place to action this
  46       *
  47       * @return action_link|null
  48       */
  49      public function get_action_link(): ?\action_link {
  50          return new \action_link(
  51              new \moodle_url('/admin/settings.php', ['section' => 'manageantiviruses']),
  52              get_string('antivirussettings', 'antivirus'));
  53      }
  54  
  55      /**
  56       * Return result
  57       * @return result
  58       */
  59      public function get_result(): result {
  60          global $CFG, $DB;
  61          $details = \html_writer::tag('p', get_string('check_antivirus_details', 'report_security'));
  62  
  63          // If no scanners are enabled, then return an NA status since the results do not matter.
  64          if (empty($CFG->antiviruses)) {
  65              $status = result::NA;
  66              $summary = get_string('check_antivirus_info', 'report_security');
  67              return new result($status, $summary, $details);
  68          }
  69  
  70          $logmanager = get_log_manager();
  71          $readers = $logmanager->get_readers('\core\log\sql_internal_table_reader');
  72  
  73          // If reader is not a sql_internal_table_reader return UNKNOWN since we
  74          // aren't able to fetch the required information. Legacy logs are not
  75          // supported here. They do not hold enough adequate information to be
  76          // used for these checks.
  77          if (empty($readers)) {
  78              $status = result::UNKNOWN;
  79              $summary = get_string('check_antivirus_logstore_not_supported', 'report_security');
  80              return new result($status, $summary, $details);
  81          }
  82  
  83          $reader = reset($readers);
  84  
  85          // If there has been a recent timestamp within threshold period, then
  86          // set the status to ERROR and describe the problem, e.g. X issues in
  87          // the last N period.
  88          $threshold = get_config('antivirus', 'threshold');
  89          $params = [];
  90          $params['lookback'] = time() - $threshold;
  91  
  92          // Type of "targets" to include.
  93          list($targetsqlin, $inparams) = $DB->get_in_or_equal([
  94              'antivirus_scan_file',
  95              'antivirus_scan_data',
  96          ], SQL_PARAMS_NAMED);
  97          $params = array_merge($inparams, $params);
  98  
  99          // Specify criteria for search.
 100          $selectwhere = "timecreated > :lookback
 101                          AND target $targetsqlin
 102                          AND action = 'error'";
 103  
 104          $totalerrors = $reader->get_events_select_count($selectwhere, $params);
 105          if (!empty($totalerrors)) {
 106              $status = result::ERROR;
 107              $summary = get_string('check_antivirus_error', 'report_security', [
 108                  'errors' => $totalerrors,
 109                  'lookback' => format_time($threshold)
 110              ]);
 111          } else if (!empty($CFG->antiviruses)) {
 112              $status = result::OK;
 113              // Fetch count of enabled antiviruses (we don't care about which ones).
 114              $totalantiviruses = !empty($CFG->antiviruses) ? count(explode(',', $CFG->antiviruses)) : 0;
 115              $summary = get_string('check_antivirus_ok', 'report_security', [
 116                  'scanners' => $totalantiviruses,
 117                  'lookback' => format_time($threshold)
 118              ]);
 119          }
 120          return new result($status, $summary, $details);
 121      }
 122  }
 123