Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
defined('MOODLE_INTERNAL') || die();
18
require_once(__DIR__ . '/fixtures/testable_antivirus.php');
19
 
20
/**
21
 * Tests for antivirus manager.
22
 *
23
 * @package    core_antivirus
24
 * @category   test
25
 * @copyright  2016 Ruslan Kabalin, Lancaster University.
26
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 */
28
class antivirus_test extends advanced_testcase {
29
 
30
    /**
31
     * @var string Path to the tempfile created for use with AV scanner tests
32
     */
33
    protected $tempfile;
34
 
35
    protected function setUp(): void {
36
        global $CFG;
37
        // Use our special testable fixture plugin.
38
        $CFG->antiviruses = 'testable';
39
 
40
        $this->resetAfterTest();
41
 
42
        // Create tempfile.
43
        $tempfolder = make_request_directory(false);
44
        $this->tempfile = $tempfolder . '/' . rand();
45
        touch($this->tempfile);
46
    }
47
 
48
    /**
49
     * Enable logging.
50
     *
51
     * @return void
52
     */
53
    protected function enable_logging() {
54
        $this->preventResetByRollback();
55
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
56
        set_config('buffersize', 0, 'logstore_standard');
57
        set_config('logguests', 1, 'logstore_standard');
58
    }
59
 
60
    /**
61
     * Return check api status for the antivirus check.
62
     *
63
     * @return    string Based on status of \core\check\result.
64
     */
65
    protected function get_check_api_antivirus_status_result() {
66
        $av = new \core\check\environment\antivirus();
67
        return $av->get_result()->get_status();
68
    }
69
 
70
    protected function tearDown(): void {
71
        @unlink($this->tempfile);
72
    }
73
 
74
    public function test_manager_get_antivirus() {
75
        // We are using clamav plugin in the test,
76
        // as the only plugin we know exists for sure.
77
        $antivirusviaget = \core\antivirus\manager::get_antivirus('clamav');
78
        $antivirusdirect = new \antivirus_clamav\scanner();
79
        $this->assertEquals($antivirusdirect, $antivirusviaget);
80
    }
81
 
82
    public function test_manager_scan_file_no_virus() {
83
        // Run mock scanning.
84
        $this->assertFileExists($this->tempfile);
85
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'OK', true));
86
        // File expected to remain in place.
87
        $this->assertFileExists($this->tempfile);
88
    }
89
 
90
    public function test_manager_scan_file_error() {
91
        // Run mock scanning.
92
        $this->assertFileExists($this->tempfile);
93
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'ERROR', true));
94
        // File expected to remain in place.
95
        $this->assertFileExists($this->tempfile);
96
    }
97
 
98
    // Check API for NA status i.e. when no scanners are enabled.
99
    public function test_antivirus_check_na() {
100
        global $CFG;
101
        $CFG->antiviruses = '';
102
        // Enable logs.
103
        $this->enable_logging();
104
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
105
        // Run mock scanning.
106
        $this->assertFileExists($this->tempfile);
107
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'OK', true));
108
        $this->assertEquals(\core\check\result::NA, $this->get_check_api_antivirus_status_result());
109
        // File expected to remain in place.
110
        $this->assertFileExists($this->tempfile);
111
    }
112
 
113
    // Check API for UNKNOWN status i.e. when the system's logstore reader is not '\core\log\sql_internal_table_reader'.
114
    public function test_antivirus_check_unknown() {
115
        // Run mock scanning.
116
        $this->assertFileExists($this->tempfile);
117
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'OK', true));
118
        $this->assertEquals(\core\check\result::UNKNOWN, $this->get_check_api_antivirus_status_result());
119
        // File expected to remain in place.
120
        $this->assertFileExists($this->tempfile);
121
    }
122
 
123
    // Check API for OK status i.e. antivirus enabled, logstore is ok, no scanner issues occurred recently.
124
    public function test_antivirus_check_ok() {
125
        // Enable logs.
126
        $this->enable_logging();
127
        // Run mock scanning.
128
        $this->assertFileExists($this->tempfile);
129
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'OK', true));
130
        $this->assertEquals(\core\check\result::OK, $this->get_check_api_antivirus_status_result());
131
        // File expected to remain in place.
132
        $this->assertFileExists($this->tempfile);
133
    }
134
 
135
    // Check API for ERROR status i.e. scanner issue within a certain timeframe/threshold.
136
    public function test_antivirus_check_error() {
137
        global $USER, $DB;
138
        // Enable logs.
139
        $this->enable_logging();
140
        // Set threshold / lookback.
141
        // Run mock scanning.
142
        $this->assertFileExists($this->tempfile);
143
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'ERROR', true));
144
        $this->assertEquals(\core\check\result::ERROR, $this->get_check_api_antivirus_status_result());
145
        // File expected to remain in place.
146
        $this->assertFileExists($this->tempfile);
147
    }
148
 
149
    public function test_manager_scan_file_virus() {
150
        // Run mock scanning without deleting infected file.
151
        $this->assertFileExists($this->tempfile);
152
        $this->expectException(\core\antivirus\scanner_exception::class);
153
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'FOUND', false));
154
        // File expected to remain in place.
155
        $this->assertFileExists($this->tempfile);
156
 
157
        // Run mock scanning with deleting infected file.
158
        $this->expectException(\core\antivirus\scanner_exception::class);
159
        $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true));
160
        // File expected to be deleted.
161
        $this->assertFileDoesNotExist($this->tempfile);
162
    }
163
 
164
    public function test_manager_send_message_to_user_email_scan_file_virus() {
165
        $sink = $this->redirectEmails();
166
        $exception = null;
167
        try {
168
            set_config('notifyemail', 'fake@example.com', 'antivirus');
169
            \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
170
        } catch (\core\antivirus\scanner_exception $ex) {
171
            $exception = $ex;
172
        }
173
        $this->assertNotEmpty($exception);
174
        $result = $sink->get_messages();
175
        $this->assertCount(1, $result);
176
        $this->assertStringContainsString('fake@example.com', $result[0]->to);
177
        $sink->close();
178
    }
179
 
180
    public function test_manager_send_message_to_admin_email_scan_file_virus() {
181
        $sink = $this->redirectMessages();
182
        $exception = null;
183
        try {
184
            \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
185
        } catch (\core\antivirus\scanner_exception $ex) {
186
            $exception = $ex;
187
        }
188
        $this->assertNotEmpty($exception);
189
        $result = $sink->get_messages();
190
        $admins = array_keys(get_admins());
191
        $this->assertCount(1, $admins);
192
        $this->assertCount(1, $result);
193
        $this->assertEquals($result[0]->useridto, reset($admins));
194
        $sink->close();
195
    }
196
 
197
    public function test_manager_quarantine_file_virus() {
198
        try {
199
            set_config('enablequarantine', true, 'antivirus');
200
            \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
201
        } catch (\core\antivirus\scanner_exception $ex) {
202
            $exception = $ex;
203
        }
204
        $this->assertNotEmpty($exception);
205
        // Quarantined files.
206
        $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
207
        $this->assertEquals(1, count($quarantinedfiles));
208
        // Clean up.
209
        \core\antivirus\quarantine::clean_up_quarantine_folder(time());
210
        $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
211
        $this->assertEquals(0, count($quarantinedfiles));
212
    }
213
 
214
    public function test_manager_none_quarantine_file_virus() {
215
        try {
216
            \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
217
        } catch (\core\antivirus\scanner_exception $ex) {
218
            $exception = $ex;
219
        }
220
        $this->assertNotEmpty($exception);
221
        $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
222
        $this->assertEquals(0, count($quarantinedfiles));
223
    }
224
 
225
    public function test_manager_scan_data_no_virus() {
226
        // Run mock scanning.
227
        $this->assertEmpty(\core\antivirus\manager::scan_data('OK'));
228
    }
229
 
230
    public function test_manager_scan_data_error() {
231
        // Run mock scanning.
232
        $this->assertEmpty(\core\antivirus\manager::scan_data('ERROR'));
233
    }
234
 
235
    public function test_manager_scan_data_virus() {
236
        // Run mock scanning.
237
        $this->expectException(\core\antivirus\scanner_exception::class);
238
        $this->assertEmpty(\core\antivirus\manager::scan_data('FOUND'));
239
    }
240
 
241
    public function test_manager_send_message_to_user_email_scan_data_virus() {
242
        $sink = $this->redirectEmails();
243
        set_config('notifyemail', 'fake@example.com', 'antivirus');
244
        $exception = null;
245
        try {
246
            \core\antivirus\manager::scan_data('FOUND');
247
        } catch (\core\antivirus\scanner_exception $ex) {
248
            $exception = $ex;
249
        }
250
        $this->assertNotEmpty($exception);
251
        $result = $sink->get_messages();
252
        $this->assertCount(1, $result);
253
        $this->assertStringContainsString('fake@example.com', $result[0]->to);
254
        $sink->close();
255
    }
256
 
257
    public function test_manager_send_message_to_admin_email_scan_data_virus() {
258
        $sink = $this->redirectMessages();
259
        $exception = null;
260
        try {
261
            \core\antivirus\manager::scan_data('FOUND');
262
        } catch (\core\antivirus\scanner_exception $ex) {
263
            $exception = $ex;
264
        }
265
        $this->assertNotEmpty($exception);
266
        $result = $sink->get_messages();
267
        $admins = array_keys(get_admins());
268
        $this->assertCount(1, $admins);
269
        $this->assertCount(1, $result);
270
        $this->assertEquals($result[0]->useridto, reset($admins));
271
        $sink->close();
272
    }
273
 
274
    public function test_manager_quarantine_data_virus() {
275
        set_config('enablequarantine', true, 'antivirus');
276
        $exception = null;
277
        try {
278
            \core\antivirus\manager::scan_data('FOUND');
279
        } catch (\core\antivirus\scanner_exception $ex) {
280
            $exception = $ex;
281
        }
282
        $this->assertNotEmpty($exception);
283
        // Quarantined files.
284
        $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
285
        $this->assertEquals(1, count($quarantinedfiles));
286
        // Clean up.
287
        \core\antivirus\quarantine::clean_up_quarantine_folder(time());
288
        $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
289
        $this->assertEquals(0, count($quarantinedfiles));
290
    }
291
 
292
 
293
    public function test_manager_none_quarantine_data_virus() {
294
        $exception = null;
295
        try {
296
            \core\antivirus\manager::scan_data('FOUND');
297
        } catch (\core\antivirus\scanner_exception $ex) {
298
            $exception = $ex;
299
        }
300
        $this->assertNotEmpty($exception);
301
        // No Quarantined files.
302
        $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
303
        $this->assertEquals(0, count($quarantinedfiles));
304
    }
305
}