|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00026 defined('MOODLE_INTERNAL') || die; 00027 00028 00029 define('REPORT_SECURITY_OK', 'ok'); 00030 define('REPORT_SECURITY_INFO', 'info'); 00031 define('REPORT_SECURITY_WARNING', 'warning'); 00032 define('REPORT_SECURITY_SERIOUS', 'serious'); 00033 define('REPORT_SECURITY_CRITICAL', 'critical'); 00034 00035 function report_security_hide_timearning() { 00036 global $PAGE; 00037 $PAGE->requires->js_init_code("Y.one('#timewarning').addClass('timewarninghidden')"); 00038 } 00039 00040 function report_security_get_issue_list() { 00041 return array( 00042 'report_security_check_globals', 00043 'report_security_check_unsecuredataroot', 00044 'report_security_check_displayerrors', 00045 'report_security_check_noauth', 00046 'report_security_check_embed', 00047 'report_security_check_mediafilterswf', 00048 'report_security_check_openprofiles', 00049 'report_security_check_google', 00050 'report_security_check_passwordpolicy', 00051 'report_security_check_passwordsaltmain', 00052 'report_security_check_emailchangeconfirmation', 00053 'report_security_check_cookiesecure', 00054 'report_security_check_configrw', 00055 'report_security_check_riskxss', 00056 'report_security_check_riskadmin', 00057 'report_security_check_riskbackup', 00058 'report_security_check_defaultuserrole', 00059 'report_security_check_guestrole', 00060 'report_security_check_frontpagerole', 00061 00062 ); 00063 } 00064 00065 function report_security_doc_link($issue, $name) { 00066 global $CFG, $OUTPUT; 00067 00068 if (empty($CFG->docroot)) { 00069 return $name; 00070 } 00071 00072 return $OUTPUT->doc_link('report/security/'.$issue, $name); 00073 } 00074 00078 00079 00085 function report_security_check_globals($detailed=false) { 00086 $result = new stdClass(); 00087 $result->issue = 'report_security_check_globals'; 00088 $result->name = get_string('check_globals_name', 'report_security'); 00089 $result->info = null; 00090 $result->details = null; 00091 $result->status = null; 00092 $result->link = null; 00093 00094 if (ini_get_bool('register_globals')) { 00095 $result->status = REPORT_SECURITY_CRITICAL; 00096 $result->info = get_string('check_globals_error', 'report_security'); 00097 } else { 00098 $result->status = REPORT_SECURITY_OK; 00099 $result->info = get_string('check_globals_ok', 'report_security'); 00100 } 00101 00102 if ($detailed) { 00103 $result->details = get_string('check_globals_details', 'report_security'); 00104 } 00105 00106 return $result; 00107 } 00108 00114 function report_security_check_noauth($detailed=false) { 00115 global $CFG; 00116 00117 $result = new stdClass(); 00118 $result->issue = 'report_security_check_noauth'; 00119 $result->name = get_string('check_noauth_name', 'report_security'); 00120 $result->info = null; 00121 $result->details = null; 00122 $result->status = null; 00123 $result->link = null; 00124 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths\">".get_string('authsettings', 'admin').'</a>'; 00125 00126 if (is_enabled_auth('none')) { 00127 $result->status = REPORT_SECURITY_CRITICAL; 00128 $result->info = get_string('check_noauth_error', 'report_security'); 00129 } else { 00130 $result->status = REPORT_SECURITY_OK; 00131 $result->info = get_string('check_noauth_ok', 'report_security'); 00132 } 00133 00134 if ($detailed) { 00135 $result->details = get_string('check_noauth_details', 'report_security'); 00136 } 00137 00138 return $result; 00139 } 00140 00146 function report_security_check_passwordpolicy($detailed=false) { 00147 global $CFG; 00148 00149 $result = new stdClass(); 00150 $result->issue = 'report_security_check_passwordpolicy'; 00151 $result->name = get_string('check_passwordpolicy_name', 'report_security'); 00152 $result->info = null; 00153 $result->details = null; 00154 $result->status = null; 00155 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>'; 00156 00157 if (empty($CFG->passwordpolicy)) { 00158 $result->status = REPORT_SECURITY_WARNING; 00159 $result->info = get_string('check_passwordpolicy_error', 'report_security'); 00160 } else { 00161 $result->status = REPORT_SECURITY_OK; 00162 $result->info = get_string('check_passwordpolicy_ok', 'report_security'); 00163 } 00164 00165 if ($detailed) { 00166 $result->details = get_string('check_passwordpolicy_details', 'report_security'); 00167 } 00168 00169 return $result; 00170 } 00171 00177 function report_security_check_embed($detailed=false) { 00178 global $CFG; 00179 00180 $result = new stdClass(); 00181 $result->issue = 'report_security_check_embed'; 00182 $result->name = get_string('check_embed_name', 'report_security'); 00183 $result->info = null; 00184 $result->details = null; 00185 $result->status = null; 00186 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>'; 00187 00188 if (!empty($CFG->allowobjectembed)) { 00189 $result->status = REPORT_SECURITY_CRITICAL; 00190 $result->info = get_string('check_embed_error', 'report_security'); 00191 } else { 00192 $result->status = REPORT_SECURITY_OK; 00193 $result->info = get_string('check_embed_ok', 'report_security'); 00194 } 00195 00196 if ($detailed) { 00197 $result->details = get_string('check_embed_details', 'report_security'); 00198 } 00199 00200 return $result; 00201 } 00202 00208 function report_security_check_mediafilterswf($detailed=false) { 00209 global $CFG; 00210 00211 $result = new stdClass(); 00212 $result->issue = 'report_security_check_mediafilterswf'; 00213 $result->name = get_string('check_mediafilterswf_name', 'report_security'); 00214 $result->info = null; 00215 $result->details = null; 00216 $result->status = null; 00217 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=filtersettingfiltermediaplugin\">".get_string('filtersettings', 'admin').'</a>'; 00218 00219 $activefilters = filter_get_globally_enabled(); 00220 00221 if (array_search('filter/mediaplugin', $activefilters) !== false and !empty($CFG->filter_mediaplugin_enable_swf)) { 00222 $result->status = REPORT_SECURITY_CRITICAL; 00223 $result->info = get_string('check_mediafilterswf_error', 'report_security'); 00224 } else { 00225 $result->status = REPORT_SECURITY_OK; 00226 $result->info = get_string('check_mediafilterswf_ok', 'report_security'); 00227 } 00228 00229 if ($detailed) { 00230 $result->details = get_string('check_mediafilterswf_details', 'report_security'); 00231 } 00232 00233 return $result; 00234 } 00235 00241 function report_security_check_unsecuredataroot($detailed=false) { 00242 global $CFG; 00243 00244 $result = new stdClass(); 00245 $result->issue = 'report_security_check_unsecuredataroot'; 00246 $result->name = get_string('check_unsecuredataroot_name', 'report_security'); 00247 $result->info = null; 00248 $result->details = null; 00249 $result->status = null; 00250 $result->link = null; 00251 00252 $insecuredataroot = is_dataroot_insecure(true); 00253 00254 if ($insecuredataroot == INSECURE_DATAROOT_WARNING) { 00255 $result->status = REPORT_SECURITY_SERIOUS; 00256 $result->info = get_string('check_unsecuredataroot_warning', 'report_security', $CFG->dataroot); 00257 00258 } else if ($insecuredataroot == INSECURE_DATAROOT_ERROR) { 00259 $result->status = REPORT_SECURITY_CRITICAL; 00260 $result->info = get_string('check_unsecuredataroot_error', 'report_security', $CFG->dataroot); 00261 00262 } else { 00263 $result->status = REPORT_SECURITY_OK; 00264 $result->info = get_string('check_unsecuredataroot_ok', 'report_security'); 00265 } 00266 00267 if ($detailed) { 00268 $result->details = get_string('check_unsecuredataroot_details', 'report_security'); 00269 } 00270 00271 return $result; 00272 } 00273 00280 function report_security_check_displayerrors($detailed=false) { 00281 $result = new stdClass(); 00282 $result->issue = 'report_security_check_displayerrors'; 00283 $result->name = get_string('check_displayerrors_name', 'report_security'); 00284 $result->info = null; 00285 $result->details = null; 00286 $result->status = null; 00287 $result->link = null; 00288 00289 if (defined('WARN_DISPLAY_ERRORS_ENABLED')) { 00290 $result->status = REPORT_SECURITY_WARNING; 00291 $result->info = get_string('check_displayerrors_error', 'report_security'); 00292 } else { 00293 $result->status = REPORT_SECURITY_OK; 00294 $result->info = get_string('check_displayerrors_ok', 'report_security'); 00295 } 00296 00297 if ($detailed) { 00298 $result->details = get_string('check_displayerrors_details', 'report_security'); 00299 } 00300 00301 return $result; 00302 } 00303 00309 function report_security_check_openprofiles($detailed=false) { 00310 global $CFG; 00311 00312 $result = new stdClass(); 00313 $result->issue = 'report_security_check_openprofiles'; 00314 $result->name = get_string('check_openprofiles_name', 'report_security'); 00315 $result->info = null; 00316 $result->details = null; 00317 $result->status = null; 00318 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>'; 00319 00320 if (empty($CFG->forcelogin) and empty($CFG->forceloginforprofiles)) { 00321 $result->status = REPORT_SECURITY_WARNING; 00322 $result->info = get_string('check_openprofiles_error', 'report_security'); 00323 } else { 00324 $result->status = REPORT_SECURITY_OK; 00325 $result->info = get_string('check_openprofiles_ok', 'report_security'); 00326 } 00327 00328 if ($detailed) { 00329 $result->details = get_string('check_openprofiles_details', 'report_security'); 00330 } 00331 00332 return $result; 00333 } 00334 00341 function report_security_check_google($detailed=false) { 00342 global $CFG; 00343 00344 $result = new stdClass(); 00345 $result->issue = 'report_security_check_google'; 00346 $result->name = get_string('check_google_name', 'report_security'); 00347 $result->info = null; 00348 $result->details = null; 00349 $result->status = null; 00350 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>'; 00351 00352 if (empty($CFG->opentogoogle)) { 00353 $result->status = REPORT_SECURITY_OK; 00354 $result->info = get_string('check_google_ok', 'report_security'); 00355 } else if (!empty($CFG->guestloginbutton)) { 00356 $result->status = REPORT_SECURITY_INFO; 00357 $result->info = get_string('check_google_info', 'report_security'); 00358 } else { 00359 $result->status = REPORT_SECURITY_SERIOUS; 00360 $result->info = get_string('check_google_error', 'report_security'); 00361 } 00362 00363 if ($detailed) { 00364 $result->details = get_string('check_google_details', 'report_security'); 00365 } 00366 00367 return $result; 00368 } 00369 00375 function report_security_check_emailchangeconfirmation($detailed=false) { 00376 global $CFG; 00377 00378 $result = new stdClass(); 00379 $result->issue = 'report_security_check_emailchangeconfirmation'; 00380 $result->name = get_string('check_emailchangeconfirmation_name', 'report_security'); 00381 $result->info = null; 00382 $result->details = null; 00383 $result->status = null; 00384 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=sitepolicies\">".get_string('sitepolicies', 'admin').'</a>'; 00385 00386 if (empty($CFG->emailchangeconfirmation)) { 00387 if (empty($CFG->allowemailaddresses)) { 00388 $result->status = REPORT_SECURITY_WARNING; 00389 $result->info = get_string('check_emailchangeconfirmation_error', 'report_security'); 00390 } else { 00391 $result->status = REPORT_SECURITY_INFO; 00392 $result->info = get_string('check_emailchangeconfirmation_info', 'report_security'); 00393 } 00394 } else { 00395 $result->status = REPORT_SECURITY_OK; 00396 $result->info = get_string('check_emailchangeconfirmation_ok', 'report_security'); 00397 } 00398 00399 if ($detailed) { 00400 $result->details = get_string('check_emailchangeconfirmation_details', 'report_security'); 00401 } 00402 00403 return $result; 00404 } 00405 00412 function report_security_check_cookiesecure($detailed=false) { 00413 global $CFG; 00414 00415 if (strpos($CFG->wwwroot, 'https://') !== 0) { 00416 return null; 00417 } 00418 00419 $result = new stdClass(); 00420 $result->issue = 'report_security_check_cookiesecure'; 00421 $result->name = get_string('check_cookiesecure_name', 'report_security'); 00422 $result->info = null; 00423 $result->details = null; 00424 $result->status = null; 00425 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=httpsecurity\">".get_string('httpsecurity', 'admin').'</a>'; 00426 00427 if (empty($CFG->cookiesecure)) { 00428 $result->status = REPORT_SECURITY_SERIOUS; 00429 $result->info = get_string('check_cookiesecure_error', 'report_security'); 00430 } else { 00431 $result->status = REPORT_SECURITY_OK; 00432 $result->info = get_string('check_cookiesecure_ok', 'report_security'); 00433 } 00434 00435 if ($detailed) { 00436 $result->details = get_string('check_cookiesecure_details', 'report_security'); 00437 } 00438 00439 return $result; 00440 } 00441 00448 function report_security_check_configrw($detailed=false) { 00449 global $CFG; 00450 00451 $result = new stdClass(); 00452 $result->issue = 'report_security_check_configrw'; 00453 $result->name = get_string('check_configrw_name', 'report_security'); 00454 $result->info = null; 00455 $result->details = null; 00456 $result->status = null; 00457 $result->link = null; 00458 00459 if (is_writable($CFG->dirroot.'/config.php')) { 00460 $result->status = REPORT_SECURITY_WARNING; 00461 $result->info = get_string('check_configrw_warning', 'report_security'); 00462 } else { 00463 $result->status = REPORT_SECURITY_OK; 00464 $result->info = get_string('check_configrw_ok', 'report_security'); 00465 } 00466 00467 if ($detailed) { 00468 $result->details = get_string('check_configrw_details', 'report_security'); 00469 } 00470 00471 return $result; 00472 } 00473 00474 function report_security_check_passwordsaltmain($detailed=false) { 00475 global $CFG; 00476 00477 $result = new stdClass(); 00478 $result->issue = 'report_security_check_passwordsaltmain'; 00479 $result->name = get_string('check_passwordsaltmain_name', 'report_security'); 00480 $result->info = null; 00481 $result->details = null; 00482 $result->status = null; 00483 $result->link = null; 00484 00485 if (empty($CFG->passwordsaltmain)) { 00486 $result->status = REPORT_SECURITY_WARNING; 00487 $result->info = get_string('check_passwordsaltmain_warning', 'report_security'); 00488 } else if ($CFG->passwordsaltmain === 'some long random string here with lots of characters' 00489 || trim($CFG->passwordsaltmain) === '' || preg_match('/^([a-z0-9]{0,10})$/i', $CFG->passwordsaltmain)) { 00490 $result->status = REPORT_SECURITY_WARNING; 00491 $result->info = get_string('check_passwordsaltmain_weak', 'report_security'); 00492 } else { 00493 $result->status = REPORT_SECURITY_OK; 00494 $result->info = get_string('check_passwordsaltmain_ok', 'report_security'); 00495 } 00496 00497 if ($detailed) { 00498 $result->details = get_string('check_passwordsaltmain_details', 'report_security', get_docs_url('report/security/report_security_check_passwordsaltmain')); 00499 } 00500 00501 return $result; 00502 } 00503 00510 function report_security_check_riskxss($detailed=false) { 00511 global $DB; 00512 00513 $result = new stdClass(); 00514 $result->issue = 'report_security_check_riskxss'; 00515 $result->name = get_string('check_riskxss_name', 'report_security'); 00516 $result->info = null; 00517 $result->details = null; 00518 $result->status = REPORT_SECURITY_WARNING; 00519 $result->link = null; 00520 00521 $params = array('capallow'=>CAP_ALLOW); 00522 00523 $sqlfrom = "FROM (SELECT rcx.* 00524 FROM {role_capabilities} rcx 00525 JOIN {capabilities} cap ON (cap.name = rcx.capability AND ".$DB->sql_bitand('cap.riskbitmask', RISK_XSS)." <> 0) 00526 WHERE rcx.permission = :capallow) rc, 00527 {context} c, 00528 {context} sc, 00529 {role_assignments} ra, 00530 {user} u 00531 WHERE c.id = rc.contextid 00532 AND (sc.path = c.path OR sc.path LIKE ".$DB->sql_concat('c.path', "'/%'")." OR c.path LIKE ".$DB->sql_concat('sc.path', "'/%'").") 00533 AND u.id = ra.userid AND u.deleted = 0 00534 AND ra.contextid = sc.id AND ra.roleid = rc.roleid"; 00535 00536 $count = $DB->count_records_sql("SELECT COUNT(DISTINCT u.id) $sqlfrom", $params); 00537 00538 $result->info = get_string('check_riskxss_warning', 'report_security', $count); 00539 00540 if ($detailed) { 00541 $users = $DB->get_records_sql("SELECT DISTINCT u.id, u.firstname, u.lastname, u.picture, u.imagealt $sqlfrom", $params); 00542 foreach ($users as $uid=>$user) { 00543 $users[$uid] = fullname($user); 00544 } 00545 $users = implode(', ', $users); 00546 $result->details = get_string('check_riskxss_details', 'report_security', $users); 00547 } 00548 00549 return $result; 00550 } 00551 00557 function report_security_check_defaultuserrole($detailed=false) { 00558 global $DB, $CFG; 00559 00560 $result = new stdClass(); 00561 $result->issue = 'report_security_check_defaultuserrole'; 00562 $result->name = get_string('check_defaultuserrole_name', 'report_security'); 00563 $result->info = null; 00564 $result->details = null; 00565 $result->status = null; 00566 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=userpolicies\">".get_string('userpolicies', 'admin').'</a>';; 00567 00568 if (!$default_role = $DB->get_record('role', array('id'=>$CFG->defaultuserroleid))) { 00569 $result->status = REPORT_SECURITY_WARNING; 00570 $result->info = get_string('check_defaultuserrole_notset', 'report_security'); 00571 $result->details = $result->info; 00572 00573 return $result; 00574 } 00575 00576 // risky caps - usually very dangerous 00577 $params = array('capallow'=>CAP_ALLOW, 'roleid'=>$default_role->id); 00578 $sql = "SELECT COUNT(DISTINCT rc.contextid) 00579 FROM {role_capabilities} rc 00580 JOIN {capabilities} cap ON cap.name = rc.capability 00581 WHERE ".$DB->sql_bitand('cap.riskbitmask', (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))." <> 0 00582 AND rc.permission = :capallow 00583 AND rc.roleid = :roleid"; 00584 00585 $riskycount = $DB->count_records_sql($sql, $params); 00586 00587 // it may have either none or 'user' archetype - nothing else, or else it would break during upgrades badly 00588 if ($default_role->archetype === '' or $default_role->archetype === 'user') { 00589 $legacyok = true; 00590 } else { 00591 $legacyok = false; 00592 } 00593 00594 if ($riskycount or !$legacyok) { 00595 $result->status = REPORT_SECURITY_CRITICAL; 00596 $result->info = get_string('check_defaultuserrole_error', 'report_security', format_string($default_role->name)); 00597 00598 } else { 00599 $result->status = REPORT_SECURITY_OK; 00600 $result->info = get_string('check_defaultuserrole_ok', 'report_security'); 00601 } 00602 00603 if ($detailed) { 00604 $result->details = get_string('check_defaultuserrole_details', 'report_security'); 00605 } 00606 00607 return $result; 00608 } 00609 00615 function report_security_check_guestrole($detailed=false) { 00616 global $DB, $CFG; 00617 00618 $result = new stdClass(); 00619 $result->issue = 'report_security_check_guestrole'; 00620 $result->name = get_string('check_guestrole_name', 'report_security'); 00621 $result->info = null; 00622 $result->details = null; 00623 $result->status = null; 00624 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=userpolicies\">".get_string('userpolicies', 'admin').'</a>';; 00625 00626 if (!$guest_role = $DB->get_record('role', array('id'=>$CFG->guestroleid))) { 00627 $result->status = REPORT_SECURITY_WARNING; 00628 $result->info = get_string('check_guestrole_notset', 'report_security'); 00629 $result->details = $result->info; 00630 00631 return $result; 00632 } 00633 00634 // risky caps - usually very dangerous 00635 $params = array('capallow'=>CAP_ALLOW, 'roleid'=>$guest_role->id); 00636 $sql = "SELECT COUNT(DISTINCT rc.contextid) 00637 FROM {role_capabilities} rc 00638 JOIN {capabilities} cap ON cap.name = rc.capability 00639 WHERE ".$DB->sql_bitand('cap.riskbitmask', (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))." <> 0 00640 AND rc.permission = :capallow 00641 AND rc.roleid = :roleid"; 00642 00643 $riskycount = $DB->count_records_sql($sql, $params); 00644 00645 // it may have either no or 'guest' archetype - nothing else, or else it would break during upgrades badly 00646 if ($guest_role->archetype === '' or $guest_role->archetype === 'guest') { 00647 $legacyok = true; 00648 } else { 00649 $legacyok = false; 00650 } 00651 00652 if ($riskycount or !$legacyok) { 00653 $result->status = REPORT_SECURITY_CRITICAL; 00654 $result->info = get_string('check_guestrole_error', 'report_security', format_string($guest_role->name)); 00655 00656 } else { 00657 $result->status = REPORT_SECURITY_OK; 00658 $result->info = get_string('check_guestrole_ok', 'report_security'); 00659 } 00660 00661 if ($detailed) { 00662 $result->details = get_string('check_guestrole_details', 'report_security'); 00663 } 00664 00665 return $result; 00666 } 00667 00673 function report_security_check_frontpagerole($detailed=false) { 00674 global $DB, $CFG; 00675 00676 $result = new stdClass(); 00677 $result->issue = 'report_security_check_frontpagerole'; 00678 $result->name = get_string('check_frontpagerole_name', 'report_security'); 00679 $result->info = null; 00680 $result->details = null; 00681 $result->status = null; 00682 $result->link = "<a href=\"$CFG->wwwroot/$CFG->admin/settings.php?section=frontpagesettings\">".get_string('frontpagesettings','admin').'</a>';; 00683 00684 if (!$frontpage_role = $DB->get_record('role', array('id'=>$CFG->defaultfrontpageroleid))) { 00685 $result->status = REPORT_SECURITY_INFO; 00686 $result->info = get_string('check_frontpagerole_notset', 'report_security'); 00687 $result->details = get_string('check_frontpagerole_details', 'report_security'); 00688 00689 return $result; 00690 } 00691 00692 // risky caps - usually very dangerous 00693 $params = array('capallow'=>CAP_ALLOW, 'roleid'=>$frontpage_role->id); 00694 $sql = "SELECT COUNT(DISTINCT rc.contextid) 00695 FROM {role_capabilities} rc 00696 JOIN {capabilities} cap ON cap.name = rc.capability 00697 WHERE ".$DB->sql_bitand('cap.riskbitmask', (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))." <> 0 00698 AND rc.permission = :capallow 00699 AND rc.roleid = :roleid"; 00700 00701 $riskycount = $DB->count_records_sql($sql, $params); 00702 00703 // there is no legacy role type for frontpage yet - anyway we can not allow teachers or admins there! 00704 if ($frontpage_role->archetype === 'teacher' or $frontpage_role->archetype === 'editingteacher' 00705 or $frontpage_role->archetype === 'coursecreator' or $frontpage_role->archetype === 'manager') { 00706 $legacyok = false; 00707 } else { 00708 $legacyok = true; 00709 } 00710 00711 if ($riskycount or !$legacyok) { 00712 $result->status = REPORT_SECURITY_CRITICAL; 00713 $result->info = get_string('check_frontpagerole_error', 'report_security', format_string($frontpage_role->name)); 00714 00715 } else { 00716 $result->status = REPORT_SECURITY_OK; 00717 $result->info = get_string('check_frontpagerole_ok', 'report_security'); 00718 } 00719 00720 if ($detailed) { 00721 $result->details = get_string('check_frontpagerole_details', 'report_security'); 00722 } 00723 00724 return $result; 00725 } 00726 00732 function report_security_check_riskadmin($detailed=false) { 00733 global $DB, $CFG; 00734 00735 $result = new stdClass(); 00736 $result->issue = 'report_security_check_riskadmin'; 00737 $result->name = get_string('check_riskadmin_name', 'report_security'); 00738 $result->info = null; 00739 $result->details = null; 00740 $result->status = null; 00741 $result->link = null; 00742 00743 $sql = "SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt, u.email 00744 FROM {user} u 00745 WHERE u.id IN ($CFG->siteadmins)"; 00746 00747 $admins = $DB->get_records_sql($sql); 00748 $admincount = count($admins); 00749 00750 if ($detailed) { 00751 foreach ($admins as $uid=>$user) { 00752 $url = "$CFG->wwwroot/user/view.php?id=$user->id"; 00753 $admins[$uid] = '<li><a href="'.$url.'">'.fullname($user).' ('.$user->email.')</a></li>'; 00754 } 00755 $admins = '<ul>'.implode('', $admins).'</ul>'; 00756 } 00757 00758 $result->status = REPORT_SECURITY_OK; 00759 $result->info = get_string('check_riskadmin_ok', 'report_security', $admincount); 00760 00761 if ($detailed) { 00762 $result->details = get_string('check_riskadmin_detailsok', 'report_security', $admins); 00763 } 00764 00765 return $result; 00766 } 00767 00773 function report_security_check_riskbackup($detailed=false) { 00774 global $CFG, $DB; 00775 00776 $result = new stdClass(); 00777 $result->issue = 'report_security_check_riskbackup'; 00778 $result->name = get_string('check_riskbackup_name', 'report_security'); 00779 $result->info = null; 00780 $result->details = null; 00781 $result->status = null; 00782 $result->link = null; 00783 00784 $syscontext = get_context_instance(CONTEXT_SYSTEM); 00785 00786 $params = array('capability'=>'moodle/backup:userinfo', 'permission'=>CAP_ALLOW, 'contextid'=>$syscontext->id); 00787 $sql = "SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder, r.archetype 00788 FROM {role} r 00789 JOIN {role_capabilities} rc ON rc.roleid = r.id 00790 WHERE rc.capability = :capability 00791 AND rc.contextid = :contextid 00792 AND rc.permission = :permission"; 00793 $systemroles = $DB->get_records_sql($sql, $params); 00794 00795 $params = array('capability'=>'moodle/backup:userinfo', 'permission'=>CAP_ALLOW, 'contextid'=>$syscontext->id); 00796 $sql = "SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder, r.archetype, rc.contextid 00797 FROM {role} r 00798 JOIN {role_capabilities} rc ON rc.roleid = r.id 00799 WHERE rc.capability = :capability 00800 AND rc.contextid <> :contextid 00801 AND rc.permission = :permission"; 00802 $overriddenroles = $DB->get_records_sql($sql, $params); 00803 00804 // list of users that are able to backup personal info 00805 // note: "sc" is context where is role assigned, 00806 // "c" is context where is role overridden or system context if in role definition 00807 $params = array('capability'=>'moodle/backup:userinfo', 'permission'=>CAP_ALLOW, 'context1'=>CONTEXT_COURSE, 'context2'=>CONTEXT_COURSE); 00808 00809 $sqluserinfo = " 00810 FROM (SELECT rcx.* 00811 FROM {role_capabilities} rcx 00812 WHERE rcx.permission = :permission AND rcx.capability = :capability) rc, 00813 {context} c, 00814 {context} sc, 00815 {role_assignments} ra, 00816 {user} u 00817 WHERE c.id = rc.contextid 00818 AND (sc.path = c.path OR sc.path LIKE ".$DB->sql_concat('c.path', "'/%'")." OR c.path LIKE ".$DB->sql_concat('sc.path', "'/%'").") 00819 AND u.id = ra.userid AND u.deleted = 0 00820 AND ra.contextid = sc.id AND ra.roleid = rc.roleid 00821 AND sc.contextlevel <= :context1 AND c.contextlevel <= :context2"; 00822 00823 $usercount = $DB->count_records_sql("SELECT COUNT('x') FROM (SELECT DISTINCT u.id $sqluserinfo) userinfo", $params); 00824 $systemrolecount = empty($systemroles) ? 0 : count($systemroles); 00825 $overriddenrolecount = empty($overriddenroles) ? 0 : count($overriddenroles); 00826 00827 $result->status = REPORT_SECURITY_WARNING; // there is always at least one admin 00828 $a = (object)array('rolecount'=>$systemrolecount,'overridecount'=>$overriddenrolecount,'usercount'=>$usercount); 00829 $result->info = get_string('check_riskbackup_warning', 'report_security', $a); 00830 00831 if ($detailed) { 00832 00833 $result->details = ''; // Will be added to later 00834 00835 // Make a list of roles 00836 if ($systemroles) { 00837 $links = array(); 00838 foreach ($systemroles as $role) { 00839 $role->url = "$CFG->wwwroot/$CFG->admin/roles/manage.php?action=edit&roleid=$role->id"; 00840 $links[] = '<li>'.get_string('check_riskbackup_editrole', 'report_security', $role).'</li>'; 00841 } 00842 $links = '<ul>'.implode($links).'</ul>'; 00843 $result->details .= get_string('check_riskbackup_details_systemroles', 'report_security', $links); 00844 } 00845 00846 // Make a list of overrides to roles 00847 $rolelinks2 = array(); 00848 if ($overriddenroles) { 00849 $links = array(); 00850 foreach ($overriddenroles as $role) { 00851 $context = get_context_instance_by_id($role->contextid); 00852 if ($context->contextlevel == CONTEXT_COURSE) { 00853 $role->name = role_get_name($role, $context); 00854 } 00855 $role->contextname = print_context_name($context); 00856 $role->url = "$CFG->wwwroot/$CFG->admin/roles/override.php?contextid=$role->contextid&roleid=$role->id"; 00857 $links[] = '<li>'.get_string('check_riskbackup_editoverride', 'report_security', $role).'</li>'; 00858 } 00859 $links = '<ul>'.implode('', $links).'</ul>'; 00860 $result->details .= get_string('check_riskbackup_details_overriddenroles', 'report_security', $links); 00861 } 00862 00863 // Get a list of affected users as well 00864 $users = array(); 00865 00866 $rs = $DB->get_recordset_sql("SELECT DISTINCT u.id, u.firstname, u.lastname, u.picture, u.imagealt, u.email, ra.contextid, ra.roleid 00867 $sqluserinfo ORDER BY u.lastname, u.firstname", $params); 00868 00869 foreach ($rs as $user) { 00870 $context = get_context_instance_by_id($user->contextid); 00871 $url = "$CFG->wwwroot/$CFG->admin/roles/assign.php?contextid=$user->contextid&roleid=$user->roleid"; 00872 $a = (object)array('fullname'=>fullname($user), 'url'=>$url, 'email'=>$user->email, 00873 'contextname'=>print_context_name($context)); 00874 $users[] = '<li>'.get_string('check_riskbackup_unassign', 'report_security', $a).'</li>'; 00875 } 00876 if (!empty($users)) { 00877 $users = '<ul>'.implode('', $users).'</ul>'; 00878 $result->details .= get_string('check_riskbackup_details_users', 'report_security', $users); 00879 } 00880 } 00881 00882 return $result; 00883 }