[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 /** 18 * Lib functions 19 * 20 * @package report 21 * @subpackage security 22 * @copyright 2008 petr Skoda 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die; 27 28 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'); 34 35 function report_security_hide_timearning() { 36 global $PAGE; 37 $PAGE->requires->js_init_code("Y.one('#timewarning').addClass('timewarninghidden')"); 38 } 39 40 function report_security_get_issue_list() { 41 return array( 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', 60 61 ); 62 } 63 64 function report_security_doc_link($issue, $name) { 65 global $CFG, $OUTPUT; 66 67 if (empty($CFG->docroot)) { 68 return $name; 69 } 70 71 return $OUTPUT->doc_link('report/security/'.$issue, $name); 72 } 73 74 ///============================================= 75 /// Issue checks 76 ///============================================= 77 78 79 /** 80 * Verifies unsupported noauth setting 81 * @param bool $detailed 82 * @return object result 83 */ 84 function report_security_check_noauth($detailed=false) { 85 global $CFG; 86 87 $result = new stdClass(); 88 $result->issue = 'report_security_check_noauth'; 89 $result->name = get_string('check_noauth_name', 'report_security'); 90 $result->info = null; 91 $result->details = null; 92 $result->status = null; 93 $result->link = null; 94 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths\">".get_string('authsettings', 'admin').'</a>'; 95 96 if (is_enabled_auth('none')) { 97 $result->status = REPORT_SECURITY_CRITICAL; 98 $result->info = get_string('check_noauth_error', 'report_security'); 99 } else { 100 $result->status = REPORT_SECURITY_OK; 101 $result->info = get_string('check_noauth_ok', 'report_security'); 102 } 103 104 if ($detailed) { 105 $result->details = get_string('check_noauth_details', 'report_security'); 106 } 107 108 return $result; 109 } 110 111 /** 112 * Verifies if password policy set 113 * @param bool $detailed 114 * @return object result 115 */ 116 function report_security_check_passwordpolicy($detailed=false) { 117 global $CFG; 118 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>'; 126 127 if (empty($CFG->passwordpolicy)) { 128 $result->status = REPORT_SECURITY_WARNING; 129 $result->info = get_string('check_passwordpolicy_error', 'report_security'); 130 } else { 131 $result->status = REPORT_SECURITY_OK; 132 $result->info = get_string('check_passwordpolicy_ok', 'report_security'); 133 } 134 135 if ($detailed) { 136 $result->details = get_string('check_passwordpolicy_details', 'report_security'); 137 } 138 139 return $result; 140 } 141 142 /** 143 * Verifies sloppy embedding - this should have been removed long ago!! 144 * @param bool $detailed 145 * @return object result 146 */ 147 function report_security_check_embed($detailed=false) { 148 global $CFG; 149 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>'; 157 158 if (!empty($CFG->allowobjectembed)) { 159 $result->status = REPORT_SECURITY_CRITICAL; 160 $result->info = get_string('check_embed_error', 'report_security'); 161 } else { 162 $result->status = REPORT_SECURITY_OK; 163 $result->info = get_string('check_embed_ok', 'report_security'); 164 } 165 166 if ($detailed) { 167 $result->details = get_string('check_embed_details', 'report_security'); 168 } 169 170 return $result; 171 } 172 173 /** 174 * Verifies sloppy swf embedding - this should have been removed long ago!! 175 * @param bool $detailed 176 * @return object result 177 */ 178 function report_security_check_mediafilterswf($detailed=false) { 179 global $CFG; 180 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>'; 188 189 $activefilters = filter_get_globally_enabled(); 190 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'); 194 } else { 195 $result->status = REPORT_SECURITY_OK; 196 $result->info = get_string('check_mediafilterswf_ok', 'report_security'); 197 } 198 199 if ($detailed) { 200 $result->details = get_string('check_mediafilterswf_details', 'report_security'); 201 } 202 203 return $result; 204 } 205 206 /** 207 * Verifies fatal misconfiguration of dataroot 208 * @param bool $detailed 209 * @return object result 210 */ 211 function report_security_check_unsecuredataroot($detailed=false) { 212 global $CFG; 213 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; 221 222 $insecuredataroot = is_dataroot_insecure(true); 223 224 if ($insecuredataroot == INSECURE_DATAROOT_WARNING) { 225 $result->status = REPORT_SECURITY_SERIOUS; 226 $result->info = get_string('check_unsecuredataroot_warning', 'report_security', $CFG->dataroot); 227 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); 231 232 } else { 233 $result->status = REPORT_SECURITY_OK; 234 $result->info = get_string('check_unsecuredataroot_ok', 'report_security'); 235 } 236 237 if ($detailed) { 238 $result->details = get_string('check_unsecuredataroot_details', 'report_security'); 239 } 240 241 return $result; 242 } 243 244 /** 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 249 */ 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; 258 259 if (defined('WARN_DISPLAY_ERRORS_ENABLED')) { 260 $result->status = REPORT_SECURITY_WARNING; 261 $result->info = get_string('check_displayerrors_error', 'report_security'); 262 } else { 263 $result->status = REPORT_SECURITY_OK; 264 $result->info = get_string('check_displayerrors_ok', 'report_security'); 265 } 266 267 if ($detailed) { 268 $result->details = get_string('check_displayerrors_details', 'report_security'); 269 } 270 271 return $result; 272 } 273 274 /** 275 * Verifies open profiles - originally open by default, not anymore because spammer abused it a lot 276 * @param bool $detailed 277 * @return object result 278 */ 279 function report_security_check_openprofiles($detailed=false) { 280 global $CFG; 281 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>'; 289 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'); 293 } else { 294 $result->status = REPORT_SECURITY_OK; 295 $result->info = get_string('check_openprofiles_ok', 'report_security'); 296 } 297 298 if ($detailed) { 299 $result->details = get_string('check_openprofiles_details', 'report_security'); 300 } 301 302 return $result; 303 } 304 305 /** 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 310 */ 311 function report_security_check_google($detailed=false) { 312 global $CFG; 313 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>'; 321 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'); 328 } else { 329 $result->status = REPORT_SECURITY_SERIOUS; 330 $result->info = get_string('check_google_error', 'report_security'); 331 } 332 333 if ($detailed) { 334 $result->details = get_string('check_google_details', 'report_security'); 335 } 336 337 return $result; 338 } 339 340 /** 341 * Verifies email confirmation - spammers were changing mails very often 342 * @param bool $detailed 343 * @return object result 344 */ 345 function report_security_check_emailchangeconfirmation($detailed=false) { 346 global $CFG; 347 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>'; 355 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'); 360 } else { 361 $result->status = REPORT_SECURITY_INFO; 362 $result->info = get_string('check_emailchangeconfirmation_info', 'report_security'); 363 } 364 } else { 365 $result->status = REPORT_SECURITY_OK; 366 $result->info = get_string('check_emailchangeconfirmation_ok', 'report_security'); 367 } 368 369 if ($detailed) { 370 $result->details = get_string('check_emailchangeconfirmation_details', 'report_security'); 371 } 372 373 return $result; 374 } 375 376 /** 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 381 */ 382 function report_security_check_cookiesecure($detailed=false) { 383 global $CFG; 384 385 if (!is_https()) { 386 return null; 387 } 388 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>'; 396 397 if (empty($CFG->cookiesecure)) { 398 $result->status = REPORT_SECURITY_SERIOUS; 399 $result->info = get_string('check_cookiesecure_error', 'report_security'); 400 } else { 401 $result->status = REPORT_SECURITY_OK; 402 $result->info = get_string('check_cookiesecure_ok', 'report_security'); 403 } 404 405 if ($detailed) { 406 $result->details = get_string('check_cookiesecure_details', 'report_security'); 407 } 408 409 return $result; 410 } 411 412 /** 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 417 */ 418 function report_security_check_configrw($detailed=false) { 419 global $CFG; 420 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; 428 429 if (is_writable($CFG->dirroot.'/config.php')) { 430 $result->status = REPORT_SECURITY_WARNING; 431 $result->info = get_string('check_configrw_warning', 'report_security'); 432 } else { 433 $result->status = REPORT_SECURITY_OK; 434 $result->info = get_string('check_configrw_ok', 'report_security'); 435 } 436 437 if ($detailed) { 438 $result->details = get_string('check_configrw_details', 'report_security'); 439 } 440 441 return $result; 442 } 443 444 445 /** 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 450 */ 451 function report_security_check_riskxss($detailed=false) { 452 global $DB; 453 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; 461 462 $params = array('capallow'=>CAP_ALLOW); 463 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, 468 {context} c, 469 {context} sc, 470 {role_assignments} ra, 471 {user} u 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"; 476 477 $count = $DB->count_records_sql("SELECT COUNT(DISTINCT u.id) $sqlfrom", $params); 478 479 $result->info = get_string('check_riskxss_warning', 'report_security', $count); 480 481 if ($detailed) { 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); 486 } 487 $users = implode(', ', $users); 488 $result->details = get_string('check_riskxss_details', 'report_security', $users); 489 } 490 491 return $result; 492 } 493 494 /** 495 * Verifies sanity of default user role. 496 * @param bool $detailed 497 * @return object result 498 */ 499 function report_security_check_defaultuserrole($detailed=false) { 500 global $DB, $CFG; 501 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>'; 509 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; 514 515 return $result; 516 } 517 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"; 526 527 $riskycount = $DB->count_records_sql($sql, $params); 528 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') { 531 $legacyok = true; 532 } else { 533 $legacyok = false; 534 } 535 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)); 539 540 } else { 541 $result->status = REPORT_SECURITY_OK; 542 $result->info = get_string('check_defaultuserrole_ok', 'report_security'); 543 } 544 545 if ($detailed) { 546 $result->details = get_string('check_defaultuserrole_details', 'report_security'); 547 } 548 549 return $result; 550 } 551 552 /** 553 * Verifies sanity of guest role 554 * @param bool $detailed 555 * @return object result 556 */ 557 function report_security_check_guestrole($detailed=false) { 558 global $DB, $CFG; 559 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>'; 567 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; 572 573 return $result; 574 } 575 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"; 584 585 $riskycount = $DB->count_records_sql($sql, $params); 586 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') { 589 $legacyok = true; 590 } else { 591 $legacyok = false; 592 } 593 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)); 597 598 } else { 599 $result->status = REPORT_SECURITY_OK; 600 $result->info = get_string('check_guestrole_ok', 'report_security'); 601 } 602 603 if ($detailed) { 604 $result->details = get_string('check_guestrole_details', 'report_security'); 605 } 606 607 return $result; 608 } 609 610 /** 611 * Verifies sanity of frontpage role 612 * @param bool $detailed 613 * @return object result 614 */ 615 function report_security_check_frontpagerole($detailed=false) { 616 global $DB, $CFG; 617 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>'; 625 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'); 630 631 return $result; 632 } 633 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"; 642 643 $riskycount = $DB->count_records_sql($sql, $params); 644 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') { 648 $legacyok = false; 649 } else { 650 $legacyok = true; 651 } 652 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)); 656 657 } else { 658 $result->status = REPORT_SECURITY_OK; 659 $result->info = get_string('check_frontpagerole_ok', 'report_security'); 660 } 661 662 if ($detailed) { 663 $result->details = get_string('check_frontpagerole_details', 'report_security'); 664 } 665 666 return $result; 667 } 668 669 /** 670 * Lists all admins. 671 * @param bool $detailed 672 * @return object result 673 */ 674 function report_security_check_riskadmin($detailed=false) { 675 global $DB, $CFG; 676 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; 684 685 $userfields = user_picture::fields('u'); 686 $sql = "SELECT $userfields 687 FROM {user} u 688 WHERE u.id IN ($CFG->siteadmins)"; 689 690 $admins = $DB->get_records_sql($sql); 691 $admincount = count($admins); 692 693 if ($detailed) { 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>'; 697 } 698 $admins = '<ul>'.implode('', $admins).'</ul>'; 699 } 700 701 $result->status = REPORT_SECURITY_OK; 702 $result->info = get_string('check_riskadmin_ok', 'report_security', $admincount); 703 704 if ($detailed) { 705 $result->details = get_string('check_riskadmin_detailsok', 'report_security', $admins); 706 } 707 708 return $result; 709 } 710 711 /** 712 * Lists all roles that have the ability to backup user data, as well as users 713 * @param bool $detailed 714 * @return object result 715 */ 716 function report_security_check_riskbackup($detailed=false) { 717 global $CFG, $DB; 718 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; 726 727 $syscontext = context_system::instance(); 728 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 731 FROM {role} r 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); 737 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 740 FROM {role} r 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); 746 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); 751 752 $sqluserinfo = " 753 FROM (SELECT rcx.* 754 FROM {role_capabilities} rcx 755 WHERE rcx.permission = :permission AND rcx.capability = :capability) rc, 756 {context} c, 757 {context} sc, 758 {role_assignments} ra, 759 {user} u 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"; 765 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); 769 770 if (max($usercount, $systemrolecount, $overriddenrolecount) > 0) { 771 $result->status = REPORT_SECURITY_WARNING; 772 } else { 773 $result->status = REPORT_SECURITY_OK; 774 } 775 776 $a = (object)array('rolecount'=>$systemrolecount,'overridecount'=>$overriddenrolecount,'usercount'=>$usercount); 777 $result->info = get_string('check_riskbackup_warning', 'report_security', $a); 778 779 if ($detailed) { 780 781 $result->details = ''; // Will be added to later 782 783 // Make a list of roles 784 if ($systemroles) { 785 $links = array(); 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>'; 790 } 791 $links = '<ul>'.implode($links).'</ul>'; 792 $result->details .= get_string('check_riskbackup_details_systemroles', 'report_security', $links); 793 } 794 795 // Make a list of overrides to roles 796 $rolelinks2 = array(); 797 if ($overriddenroles) { 798 $links = array(); 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>'; 806 } 807 $links = '<ul>'.implode('', $links).'</ul>'; 808 $result->details .= get_string('check_riskbackup_details_overriddenroles', 'report_security', $links); 809 } 810 811 // Get a list of affected users as well 812 $users = array(); 813 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)); 818 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>'; 825 } 826 if (!empty($users)) { 827 $users = '<ul>'.implode('', $users).'</ul>'; 828 $result->details .= get_string('check_riskbackup_details_users', 'report_security', $users); 829 } 830 } 831 832 return $result; 833 } 834 835 /** 836 * Verifies the status of web cron 837 * 838 * @param bool $detailed 839 * @return object result 840 */ 841 function report_security_check_webcron($detailed = false) { 842 global $CFG; 843 844 $croncli = $CFG->cronclionly; 845 $cronremotepassword = $CFG->cronremotepassword; 846 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>'; 853 854 if (empty($croncli) && empty($cronremotepassword)) { 855 $result->status = REPORT_SECURITY_WARNING; 856 $result->info = get_string('check_webcron_warning', 'report_security'); 857 } else { 858 $result->status = REPORT_SECURITY_OK; 859 $result->info = get_string('check_webcron_ok', 'report_security'); 860 } 861 862 if ($detailed) { 863 $result->details = get_string('check_webcron_details', 'report_security'); 864 } 865 866 return $result; 867 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |