2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
21 * @subpackage security
22 * @copyright 2008 petr Skoda
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die;
29 define('REPORT_SECURITY_OK', 'ok');
30 define('REPORT_SECURITY_INFO', 'info');
31 define('REPORT_SECURITY_WARNING', 'warning');
32 define('REPORT_SECURITY_SERIOUS', 'serious');
33 define('REPORT_SECURITY_CRITICAL', 'critical');
35 function report_security_hide_timearning() {
37 $PAGE->requires
->js_init_code("Y.one('#timewarning').addClass('timewarninghidden')");
40 function report_security_get_issue_list() {
42 'report_security_check_unsecuredataroot',
43 'report_security_check_displayerrors',
44 'report_security_check_noauth',
45 'report_security_check_embed',
46 'report_security_check_mediafilterswf',
47 'report_security_check_openprofiles',
48 'report_security_check_google',
49 'report_security_check_passwordpolicy',
50 'report_security_check_emailchangeconfirmation',
51 'report_security_check_cookiesecure',
52 'report_security_check_configrw',
53 'report_security_check_riskxss',
54 'report_security_check_riskadmin',
55 'report_security_check_riskbackup',
56 'report_security_check_defaultuserrole',
57 'report_security_check_guestrole',
58 'report_security_check_frontpagerole',
59 'report_security_check_webcron',
64 function report_security_doc_link($issue, $name) {
67 if (empty($CFG->docroot
)) {
71 return $OUTPUT->doc_link('report/security/'.$issue, $name);
74 ///=============================================
76 ///=============================================
80 * Verifies unsupported noauth setting
81 * @param bool $detailed
82 * @return object result
84 function report_security_check_noauth($detailed=false) {
87 $result = new stdClass();
88 $result->issue
= 'report_security_check_noauth';
89 $result->name
= get_string('check_noauth_name', 'report_security');
91 $result->details
= null;
92 $result->status
= null;
94 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths\">".get_string('authsettings', 'admin').'</a>';
96 if (is_enabled_auth('none')) {
97 $result->status
= REPORT_SECURITY_CRITICAL
;
98 $result->info
= get_string('check_noauth_error', 'report_security');
100 $result->status
= REPORT_SECURITY_OK
;
101 $result->info
= get_string('check_noauth_ok', 'report_security');
105 $result->details
= get_string('check_noauth_details', 'report_security');
112 * Verifies if password policy set
113 * @param bool $detailed
114 * @return object result
116 function report_security_check_passwordpolicy($detailed=false) {
119 $result = new stdClass();
120 $result->issue
= 'report_security_check_passwordpolicy';
121 $result->name
= get_string('check_passwordpolicy_name', 'report_security');
122 $result->info
= null;
123 $result->details
= null;
124 $result->status
= null;
125 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>';
127 if (empty($CFG->passwordpolicy
)) {
128 $result->status
= REPORT_SECURITY_WARNING
;
129 $result->info
= get_string('check_passwordpolicy_error', 'report_security');
131 $result->status
= REPORT_SECURITY_OK
;
132 $result->info
= get_string('check_passwordpolicy_ok', 'report_security');
136 $result->details
= get_string('check_passwordpolicy_details', 'report_security');
143 * Verifies sloppy embedding - this should have been removed long ago!!
144 * @param bool $detailed
145 * @return object result
147 function report_security_check_embed($detailed=false) {
150 $result = new stdClass();
151 $result->issue
= 'report_security_check_embed';
152 $result->name
= get_string('check_embed_name', 'report_security');
153 $result->info
= null;
154 $result->details
= null;
155 $result->status
= null;
156 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>';
158 if (!empty($CFG->allowobjectembed
)) {
159 $result->status
= REPORT_SECURITY_CRITICAL
;
160 $result->info
= get_string('check_embed_error', 'report_security');
162 $result->status
= REPORT_SECURITY_OK
;
163 $result->info
= get_string('check_embed_ok', 'report_security');
167 $result->details
= get_string('check_embed_details', 'report_security');
174 * Verifies sloppy swf embedding - this should have been removed long ago!!
175 * @param bool $detailed
176 * @return object result
178 function report_security_check_mediafilterswf($detailed=false) {
181 $result = new stdClass();
182 $result->issue
= 'report_security_check_mediafilterswf';
183 $result->name
= get_string('check_mediafilterswf_name', 'report_security');
184 $result->info
= null;
185 $result->details
= null;
186 $result->status
= null;
187 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=filtersettingfiltermediaplugin\">".get_string('filtersettings', 'admin').'</a>';
189 $activefilters = filter_get_globally_enabled();
191 if (array_search('mediaplugin', $activefilters) !== false and !empty($CFG->filter_mediaplugin_enable_swf
)) {
192 $result->status
= REPORT_SECURITY_CRITICAL
;
193 $result->info
= get_string('check_mediafilterswf_error', 'report_security');
195 $result->status
= REPORT_SECURITY_OK
;
196 $result->info
= get_string('check_mediafilterswf_ok', 'report_security');
200 $result->details
= get_string('check_mediafilterswf_details', 'report_security');
207 * Verifies fatal misconfiguration of dataroot
208 * @param bool $detailed
209 * @return object result
211 function report_security_check_unsecuredataroot($detailed=false) {
214 $result = new stdClass();
215 $result->issue
= 'report_security_check_unsecuredataroot';
216 $result->name
= get_string('check_unsecuredataroot_name', 'report_security');
217 $result->info
= null;
218 $result->details
= null;
219 $result->status
= null;
220 $result->link
= null;
222 $insecuredataroot = is_dataroot_insecure(true);
224 if ($insecuredataroot == INSECURE_DATAROOT_WARNING
) {
225 $result->status
= REPORT_SECURITY_SERIOUS
;
226 $result->info
= get_string('check_unsecuredataroot_warning', 'report_security', $CFG->dataroot
);
228 } else if ($insecuredataroot == INSECURE_DATAROOT_ERROR
) {
229 $result->status
= REPORT_SECURITY_CRITICAL
;
230 $result->info
= get_string('check_unsecuredataroot_error', 'report_security', $CFG->dataroot
);
233 $result->status
= REPORT_SECURITY_OK
;
234 $result->info
= get_string('check_unsecuredataroot_ok', 'report_security');
238 $result->details
= get_string('check_unsecuredataroot_details', 'report_security');
245 * Verifies displaying of errors - problem for lib files and 3rd party code
246 * because we can not disable debugging in these scripts (they do not include config.php)
247 * @param bool $detailed
248 * @return object result
250 function report_security_check_displayerrors($detailed=false) {
251 $result = new stdClass();
252 $result->issue
= 'report_security_check_displayerrors';
253 $result->name
= get_string('check_displayerrors_name', 'report_security');
254 $result->info
= null;
255 $result->details
= null;
256 $result->status
= null;
257 $result->link
= null;
259 if (defined('WARN_DISPLAY_ERRORS_ENABLED')) {
260 $result->status
= REPORT_SECURITY_WARNING
;
261 $result->info
= get_string('check_displayerrors_error', 'report_security');
263 $result->status
= REPORT_SECURITY_OK
;
264 $result->info
= get_string('check_displayerrors_ok', 'report_security');
268 $result->details
= get_string('check_displayerrors_details', 'report_security');
275 * Verifies open profiles - originally open by default, not anymore because spammer abused it a lot
276 * @param bool $detailed
277 * @return object result
279 function report_security_check_openprofiles($detailed=false) {
282 $result = new stdClass();
283 $result->issue
= 'report_security_check_openprofiles';
284 $result->name
= get_string('check_openprofiles_name', 'report_security');
285 $result->info
= null;
286 $result->details
= null;
287 $result->status
= null;
288 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>';
290 if (empty($CFG->forcelogin
) and empty($CFG->forceloginforprofiles
)) {
291 $result->status
= REPORT_SECURITY_WARNING
;
292 $result->info
= get_string('check_openprofiles_error', 'report_security');
294 $result->status
= REPORT_SECURITY_OK
;
295 $result->info
= get_string('check_openprofiles_ok', 'report_security');
299 $result->details
= get_string('check_openprofiles_details', 'report_security');
306 * Verifies google access not combined with disabled guest access
307 * because attackers might gain guest access by modifying browser signature.
308 * @param bool $detailed
309 * @return object result
311 function report_security_check_google($detailed=false) {
314 $result = new stdClass();
315 $result->issue
= 'report_security_check_google';
316 $result->name
= get_string('check_google_name', 'report_security');
317 $result->info
= null;
318 $result->details
= null;
319 $result->status
= null;
320 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>';
322 if (empty($CFG->opentogoogle
)) {
323 $result->status
= REPORT_SECURITY_OK
;
324 $result->info
= get_string('check_google_ok', 'report_security');
325 } else if (!empty($CFG->guestloginbutton
)) {
326 $result->status
= REPORT_SECURITY_INFO
;
327 $result->info
= get_string('check_google_info', 'report_security');
329 $result->status
= REPORT_SECURITY_SERIOUS
;
330 $result->info
= get_string('check_google_error', 'report_security');
334 $result->details
= get_string('check_google_details', 'report_security');
341 * Verifies email confirmation - spammers were changing mails very often
342 * @param bool $detailed
343 * @return object result
345 function report_security_check_emailchangeconfirmation($detailed=false) {
348 $result = new stdClass();
349 $result->issue
= 'report_security_check_emailchangeconfirmation';
350 $result->name
= get_string('check_emailchangeconfirmation_name', 'report_security');
351 $result->info
= null;
352 $result->details
= null;
353 $result->status
= null;
354 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>';
356 if (empty($CFG->emailchangeconfirmation
)) {
357 if (empty($CFG->allowemailaddresses
)) {
358 $result->status
= REPORT_SECURITY_WARNING
;
359 $result->info
= get_string('check_emailchangeconfirmation_error', 'report_security');
361 $result->status
= REPORT_SECURITY_INFO
;
362 $result->info
= get_string('check_emailchangeconfirmation_info', 'report_security');
365 $result->status
= REPORT_SECURITY_OK
;
366 $result->info
= get_string('check_emailchangeconfirmation_ok', 'report_security');
370 $result->details
= get_string('check_emailchangeconfirmation_details', 'report_security');
377 * Verifies if https enabled only secure cookies allowed,
378 * this prevents redirections and sending of cookies to unsecure port.
379 * @param bool $detailed
380 * @return object result
382 function report_security_check_cookiesecure($detailed=false) {
389 $result = new stdClass();
390 $result->issue
= 'report_security_check_cookiesecure';
391 $result->name
= get_string('check_cookiesecure_name', 'report_security');
392 $result->info
= null;
393 $result->details
= null;
394 $result->status
= null;
395 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=httpsecurity\">".get_string('httpsecurity', 'admin').'</a>';
397 if (!is_moodle_cookie_secure()) {
398 $result->status
= REPORT_SECURITY_SERIOUS
;
399 $result->info
= get_string('check_cookiesecure_error', 'report_security');
401 $result->status
= REPORT_SECURITY_OK
;
402 $result->info
= get_string('check_cookiesecure_ok', 'report_security');
406 $result->details
= get_string('check_cookiesecure_details', 'report_security');
413 * Verifies config.php is not writable anymore after installation,
414 * config files were changed on several outdated server.
415 * @param bool $detailed
416 * @return object result
418 function report_security_check_configrw($detailed=false) {
421 $result = new stdClass();
422 $result->issue
= 'report_security_check_configrw';
423 $result->name
= get_string('check_configrw_name', 'report_security');
424 $result->info
= null;
425 $result->details
= null;
426 $result->status
= null;
427 $result->link
= null;
429 if (is_writable($CFG->dirroot
.'/config.php')) {
430 $result->status
= REPORT_SECURITY_WARNING
;
431 $result->info
= get_string('check_configrw_warning', 'report_security');
433 $result->status
= REPORT_SECURITY_OK
;
434 $result->info
= get_string('check_configrw_ok', 'report_security');
438 $result->details
= get_string('check_configrw_details', 'report_security');
446 * Lists all users with XSS risk, it would be great to combine this with risk trusts in user table,
447 * unfortunately nobody implemented user trust UI yet :-(
448 * @param bool $detailed
449 * @return object result
451 function report_security_check_riskxss($detailed=false) {
454 $result = new stdClass();
455 $result->issue
= 'report_security_check_riskxss';
456 $result->name
= get_string('check_riskxss_name', 'report_security');
457 $result->info
= null;
458 $result->details
= null;
459 $result->status
= REPORT_SECURITY_WARNING
;
460 $result->link
= null;
462 $params = array('capallow'=>CAP_ALLOW
);
464 $sqlfrom = "FROM (SELECT rcx.*
465 FROM {role_capabilities} rcx
466 JOIN {capabilities} cap ON (cap.name = rcx.capability AND ".$DB->sql_bitand('cap.riskbitmask', RISK_XSS
)." <> 0)
467 WHERE rcx.permission = :capallow) rc,
470 {role_assignments} ra,
472 WHERE c.id = rc.contextid
473 AND (sc.path = c.path OR sc.path LIKE ".$DB->sql_concat('c.path', "'/%'")." OR c.path LIKE ".$DB->sql_concat('sc.path', "'/%'").")
474 AND u.id = ra.userid AND u.deleted = 0
475 AND ra.contextid = sc.id AND ra.roleid = rc.roleid";
477 $count = $DB->count_records_sql("SELECT COUNT(DISTINCT u.id) $sqlfrom", $params);
479 $result->info
= get_string('check_riskxss_warning', 'report_security', $count);
482 $userfields = user_picture
::fields('u');
483 $users = $DB->get_records_sql("SELECT DISTINCT $userfields $sqlfrom", $params);
484 foreach ($users as $uid=>$user) {
485 $users[$uid] = fullname($user);
487 $users = implode(', ', $users);
488 $result->details
= get_string('check_riskxss_details', 'report_security', $users);
495 * Verifies sanity of default user role.
496 * @param bool $detailed
497 * @return object result
499 function report_security_check_defaultuserrole($detailed=false) {
502 $result = new stdClass();
503 $result->issue
= 'report_security_check_defaultuserrole';
504 $result->name
= get_string('check_defaultuserrole_name', 'report_security');
505 $result->info
= null;
506 $result->details
= null;
507 $result->status
= null;
508 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=userpolicies\">".get_string('userpolicies', 'admin').'</a>';
510 if (!$default_role = $DB->get_record('role', array('id'=>$CFG->defaultuserroleid
))) {
511 $result->status
= REPORT_SECURITY_WARNING
;
512 $result->info
= get_string('check_defaultuserrole_notset', 'report_security');
513 $result->details
= $result->info
;
518 // risky caps - usually very dangerous
519 $params = array('capallow'=>CAP_ALLOW
, 'roleid'=>$default_role->id
);
520 $sql = "SELECT COUNT(DISTINCT rc.contextid)
521 FROM {role_capabilities} rc
522 JOIN {capabilities} cap ON cap.name = rc.capability
523 WHERE ".$DB->sql_bitand('cap.riskbitmask', (RISK_XSS | RISK_CONFIG | RISK_DATALOSS
))." <> 0
524 AND rc.permission = :capallow
525 AND rc.roleid = :roleid";
527 $riskycount = $DB->count_records_sql($sql, $params);
529 // it may have either none or 'user' archetype - nothing else, or else it would break during upgrades badly
530 if ($default_role->archetype
=== '' or $default_role->archetype
=== 'user') {
536 if ($riskycount or !$legacyok) {
537 $result->status
= REPORT_SECURITY_CRITICAL
;
538 $result->info
= get_string('check_defaultuserrole_error', 'report_security', role_get_name($default_role));
541 $result->status
= REPORT_SECURITY_OK
;
542 $result->info
= get_string('check_defaultuserrole_ok', 'report_security');
546 $result->details
= get_string('check_defaultuserrole_details', 'report_security');
553 * Verifies sanity of guest role
554 * @param bool $detailed
555 * @return object result
557 function report_security_check_guestrole($detailed=false) {
560 $result = new stdClass();
561 $result->issue
= 'report_security_check_guestrole';
562 $result->name
= get_string('check_guestrole_name', 'report_security');
563 $result->info
= null;
564 $result->details
= null;
565 $result->status
= null;
566 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=userpolicies\">".get_string('userpolicies', 'admin').'</a>';
568 if (!$guest_role = $DB->get_record('role', array('id'=>$CFG->guestroleid
))) {
569 $result->status
= REPORT_SECURITY_WARNING
;
570 $result->info
= get_string('check_guestrole_notset', 'report_security');
571 $result->details
= $result->info
;
576 // risky caps - usually very dangerous
577 $params = array('capallow'=>CAP_ALLOW
, 'roleid'=>$guest_role->id
);
578 $sql = "SELECT COUNT(DISTINCT rc.contextid)
579 FROM {role_capabilities} rc
580 JOIN {capabilities} cap ON cap.name = rc.capability
581 WHERE ".$DB->sql_bitand('cap.riskbitmask', (RISK_XSS | RISK_CONFIG | RISK_DATALOSS
))." <> 0
582 AND rc.permission = :capallow
583 AND rc.roleid = :roleid";
585 $riskycount = $DB->count_records_sql($sql, $params);
587 // it may have either no or 'guest' archetype - nothing else, or else it would break during upgrades badly
588 if ($guest_role->archetype
=== '' or $guest_role->archetype
=== 'guest') {
594 if ($riskycount or !$legacyok) {
595 $result->status
= REPORT_SECURITY_CRITICAL
;
596 $result->info
= get_string('check_guestrole_error', 'report_security', format_string($guest_role->name
));
599 $result->status
= REPORT_SECURITY_OK
;
600 $result->info
= get_string('check_guestrole_ok', 'report_security');
604 $result->details
= get_string('check_guestrole_details', 'report_security');
611 * Verifies sanity of frontpage role
612 * @param bool $detailed
613 * @return object result
615 function report_security_check_frontpagerole($detailed=false) {
618 $result = new stdClass();
619 $result->issue
= 'report_security_check_frontpagerole';
620 $result->name
= get_string('check_frontpagerole_name', 'report_security');
621 $result->info
= null;
622 $result->details
= null;
623 $result->status
= null;
624 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=frontpagesettings\">".get_string('frontpagesettings','admin').'</a>';
626 if (!$frontpage_role = $DB->get_record('role', array('id'=>$CFG->defaultfrontpageroleid
))) {
627 $result->status
= REPORT_SECURITY_INFO
;
628 $result->info
= get_string('check_frontpagerole_notset', 'report_security');
629 $result->details
= get_string('check_frontpagerole_details', 'report_security');
634 // risky caps - usually very dangerous
635 $params = array('capallow'=>CAP_ALLOW
, 'roleid'=>$frontpage_role->id
);
636 $sql = "SELECT COUNT(DISTINCT rc.contextid)
637 FROM {role_capabilities} rc
638 JOIN {capabilities} cap ON cap.name = rc.capability
639 WHERE ".$DB->sql_bitand('cap.riskbitmask', (RISK_XSS | RISK_CONFIG | RISK_DATALOSS
))." <> 0
640 AND rc.permission = :capallow
641 AND rc.roleid = :roleid";
643 $riskycount = $DB->count_records_sql($sql, $params);
645 // there is no legacy role type for frontpage yet - anyway we can not allow teachers or admins there!
646 if ($frontpage_role->archetype
=== 'teacher' or $frontpage_role->archetype
=== 'editingteacher'
647 or $frontpage_role->archetype
=== 'coursecreator' or $frontpage_role->archetype
=== 'manager') {
653 if ($riskycount or !$legacyok) {
654 $result->status
= REPORT_SECURITY_CRITICAL
;
655 $result->info
= get_string('check_frontpagerole_error', 'report_security', format_string($frontpage_role->name
));
658 $result->status
= REPORT_SECURITY_OK
;
659 $result->info
= get_string('check_frontpagerole_ok', 'report_security');
663 $result->details
= get_string('check_frontpagerole_details', 'report_security');
671 * @param bool $detailed
672 * @return object result
674 function report_security_check_riskadmin($detailed=false) {
677 $result = new stdClass();
678 $result->issue
= 'report_security_check_riskadmin';
679 $result->name
= get_string('check_riskadmin_name', 'report_security');
680 $result->info
= null;
681 $result->details
= null;
682 $result->status
= null;
683 $result->link
= null;
685 $userfields = user_picture
::fields('u');
686 $sql = "SELECT $userfields
688 WHERE u.id IN ($CFG->siteadmins)";
690 $admins = $DB->get_records_sql($sql);
691 $admincount = count($admins);
694 foreach ($admins as $uid=>$user) {
695 $url = "$CFG->wwwroot/user/view.php?id=$user->id";
696 $admins[$uid] = '<li><a href="'.$url.'">'.fullname($user).' ('.$user->email
.')</a></li>';
698 $admins = '<ul>'.implode('', $admins).'</ul>';
701 $result->status
= REPORT_SECURITY_OK
;
702 $result->info
= get_string('check_riskadmin_ok', 'report_security', $admincount);
705 $result->details
= get_string('check_riskadmin_detailsok', 'report_security', $admins);
712 * Lists all roles that have the ability to backup user data, as well as users
713 * @param bool $detailed
714 * @return object result
716 function report_security_check_riskbackup($detailed=false) {
719 $result = new stdClass();
720 $result->issue
= 'report_security_check_riskbackup';
721 $result->name
= get_string('check_riskbackup_name', 'report_security');
722 $result->info
= null;
723 $result->details
= null;
724 $result->status
= null;
725 $result->link
= null;
727 $syscontext = context_system
::instance();
729 $params = array('capability'=>'moodle/backup:userinfo', 'permission'=>CAP_ALLOW
, 'contextid'=>$syscontext->id
);
730 $sql = "SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder, r.archetype
732 JOIN {role_capabilities} rc ON rc.roleid = r.id
733 WHERE rc.capability = :capability
734 AND rc.contextid = :contextid
735 AND rc.permission = :permission";
736 $systemroles = $DB->get_records_sql($sql, $params);
738 $params = array('capability'=>'moodle/backup:userinfo', 'permission'=>CAP_ALLOW
, 'contextid'=>$syscontext->id
);
739 $sql = "SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder, r.archetype, rc.contextid
741 JOIN {role_capabilities} rc ON rc.roleid = r.id
742 WHERE rc.capability = :capability
743 AND rc.contextid <> :contextid
744 AND rc.permission = :permission";
745 $overriddenroles = $DB->get_records_sql($sql, $params);
747 // list of users that are able to backup personal info
748 // note: "sc" is context where is role assigned,
749 // "c" is context where is role overridden or system context if in role definition
750 $params = array('capability'=>'moodle/backup:userinfo', 'permission'=>CAP_ALLOW
, 'context1'=>CONTEXT_COURSE
, 'context2'=>CONTEXT_COURSE
);
754 FROM {role_capabilities} rcx
755 WHERE rcx.permission = :permission AND rcx.capability = :capability) rc,
758 {role_assignments} ra,
760 WHERE c.id = rc.contextid
761 AND (sc.path = c.path OR sc.path LIKE ".$DB->sql_concat('c.path', "'/%'")." OR c.path LIKE ".$DB->sql_concat('sc.path', "'/%'").")
762 AND u.id = ra.userid AND u.deleted = 0
763 AND ra.contextid = sc.id AND ra.roleid = rc.roleid
764 AND sc.contextlevel <= :context1 AND c.contextlevel <= :context2";
766 $usercount = $DB->count_records_sql("SELECT COUNT('x') FROM (SELECT DISTINCT u.id $sqluserinfo) userinfo", $params);
767 $systemrolecount = empty($systemroles) ?
0 : count($systemroles);
768 $overriddenrolecount = empty($overriddenroles) ?
0 : count($overriddenroles);
770 if (max($usercount, $systemrolecount, $overriddenrolecount) > 0) {
771 $result->status
= REPORT_SECURITY_WARNING
;
773 $result->status
= REPORT_SECURITY_OK
;
776 $a = (object)array('rolecount'=>$systemrolecount,'overridecount'=>$overriddenrolecount,'usercount'=>$usercount);
777 $result->info
= get_string('check_riskbackup_warning', 'report_security', $a);
781 $result->details
= ''; // Will be added to later
783 // Make a list of roles
786 foreach ($systemroles as $role) {
787 $role->name
= role_get_name($role);
788 $role->url
= "$CFG->wwwroot/$CFG->admin/roles/manage.php?action=edit&roleid=$role->id";
789 $links[] = '<li>'.get_string('check_riskbackup_editrole', 'report_security', $role).'</li>';
791 $links = '<ul>'.implode($links).'</ul>';
792 $result->details
.= get_string('check_riskbackup_details_systemroles', 'report_security', $links);
795 // Make a list of overrides to roles
796 $rolelinks2 = array();
797 if ($overriddenroles) {
799 foreach ($overriddenroles as $role) {
800 $role->name
= $role->localname
;
801 $context = context
::instance_by_id($role->contextid
);
802 $role->name
= role_get_name($role, $context, ROLENAME_BOTH
);
803 $role->contextname
= $context->get_context_name();
804 $role->url
= "$CFG->wwwroot/$CFG->admin/roles/override.php?contextid=$role->contextid&roleid=$role->id";
805 $links[] = '<li>'.get_string('check_riskbackup_editoverride', 'report_security', $role).'</li>';
807 $links = '<ul>'.implode('', $links).'</ul>';
808 $result->details
.= get_string('check_riskbackup_details_overriddenroles', 'report_security', $links);
811 // Get a list of affected users as well
814 list($sort, $sortparams) = users_order_by_sql('u');
815 $userfields = user_picture
::fields('u');
816 $rs = $DB->get_recordset_sql("SELECT DISTINCT $userfields, ra.contextid, ra.roleid
817 $sqluserinfo ORDER BY $sort", array_merge($params, $sortparams));
819 foreach ($rs as $user) {
820 $context = context
::instance_by_id($user->contextid
);
821 $url = "$CFG->wwwroot/$CFG->admin/roles/assign.php?contextid=$user->contextid&roleid=$user->roleid";
822 $a = (object)array('fullname'=>fullname($user), 'url'=>$url, 'email'=>$user->email
,
823 'contextname'=>$context->get_context_name());
824 $users[] = '<li>'.get_string('check_riskbackup_unassign', 'report_security', $a).'</li>';
826 if (!empty($users)) {
827 $users = '<ul>'.implode('', $users).'</ul>';
828 $result->details
.= get_string('check_riskbackup_details_users', 'report_security', $users);
836 * Verifies the status of web cron
838 * @param bool $detailed
839 * @return object result
841 function report_security_check_webcron($detailed = false) {
844 $croncli = $CFG->cronclionly
;
845 $cronremotepassword = $CFG->cronremotepassword
;
847 $result = new stdClass();
848 $result->issue
= 'report_security_check_webcron';
849 $result->name
= get_string('check_webcron_name', 'report_security');
850 $result->details
= null;
851 $result->link
= "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">"
852 .get_string('sitepolicies', 'admin').'</a>';
854 if (empty($croncli) && empty($cronremotepassword)) {
855 $result->status
= REPORT_SECURITY_WARNING
;
856 $result->info
= get_string('check_webcron_warning', 'report_security');
858 $result->status
= REPORT_SECURITY_OK
;
859 $result->info
= get_string('check_webcron_ok', 'report_security');
863 $result->details
= get_string('check_webcron_details', 'report_security');