[ 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 * Authentication Plugin: CAS Authentication 19 * 20 * Authentication using CAS (Central Authentication Server). 21 * 22 * @author Martin Dougiamas 23 * @author Jerome GUTIERREZ 24 * @author IƱaki Arenaza 25 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License 26 * @package auth_cas 27 */ 28 29 defined('MOODLE_INTERNAL') || die(); 30 31 require_once($CFG->dirroot.'/auth/ldap/auth.php'); 32 require_once($CFG->dirroot.'/auth/cas/CAS/CAS.php'); 33 34 /** 35 * CAS authentication plugin. 36 */ 37 class auth_plugin_cas extends auth_plugin_ldap { 38 39 /** 40 * Constructor. 41 */ 42 public function __construct() { 43 $this->authtype = 'cas'; 44 $this->roleauth = 'auth_cas'; 45 $this->errorlogtag = '[AUTH CAS] '; 46 $this->init_plugin($this->authtype); 47 } 48 49 /** 50 * Old syntax of class constructor. Deprecated in PHP7. 51 * 52 * @deprecated since Moodle 3.1 53 */ 54 public function auth_plugin_cas() { 55 debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); 56 self::__construct(); 57 } 58 59 function prevent_local_passwords() { 60 return true; 61 } 62 63 /** 64 * Authenticates user against CAS 65 * Returns true if the username and password work and false if they are 66 * wrong or don't exist. 67 * 68 * @param string $username The username (with system magic quotes) 69 * @param string $password The password (with system magic quotes) 70 * @return bool Authentication success or failure. 71 */ 72 function user_login ($username, $password) { 73 $this->connectCAS(); 74 return phpCAS::isAuthenticated() && (trim(core_text::strtolower(phpCAS::getUser())) == $username); 75 } 76 77 /** 78 * Returns true if this authentication plugin is 'internal'. 79 * 80 * @return bool 81 */ 82 function is_internal() { 83 return false; 84 } 85 86 /** 87 * Returns true if this authentication plugin can change the user's 88 * password. 89 * 90 * @return bool 91 */ 92 function can_change_password() { 93 return false; 94 } 95 96 /** 97 * Authentication choice (CAS or other) 98 * Redirection to the CAS form or to login/index.php 99 * for other authentication 100 */ 101 function loginpage_hook() { 102 global $frm; 103 global $CFG; 104 global $SESSION, $OUTPUT, $PAGE; 105 106 $site = get_site(); 107 $CASform = get_string('CASform', 'auth_cas'); 108 $username = optional_param('username', '', PARAM_RAW); 109 $courseid = optional_param('courseid', 0, PARAM_INT); 110 111 if (!empty($username)) { 112 if (isset($SESSION->wantsurl) && (strstr($SESSION->wantsurl, 'ticket') || 113 strstr($SESSION->wantsurl, 'NOCAS'))) { 114 unset($SESSION->wantsurl); 115 } 116 return; 117 } 118 119 // Return if CAS enabled and settings not specified yet 120 if (empty($this->config->hostname)) { 121 return; 122 } 123 124 // If the multi-authentication setting is used, check for the param before connecting to CAS. 125 if ($this->config->multiauth) { 126 127 // If there is an authentication error, stay on the default authentication page. 128 if (!empty($SESSION->loginerrormsg)) { 129 return; 130 } 131 132 $authCAS = optional_param('authCAS', '', PARAM_RAW); 133 if ($authCAS == 'NOCAS') { 134 return; 135 } 136 // Show authentication form for multi-authentication. 137 // Test pgtIou parameter for proxy mode (https connection in background from CAS server to the php server). 138 if ($authCAS != 'CAS' && !isset($_GET['pgtIou'])) { 139 $PAGE->set_url('/login/index.php'); 140 $PAGE->navbar->add($CASform); 141 $PAGE->set_title("$site->fullname: $CASform"); 142 $PAGE->set_heading($site->fullname); 143 echo $OUTPUT->header(); 144 include($CFG->dirroot.'/auth/cas/cas_form.html'); 145 echo $OUTPUT->footer(); 146 exit(); 147 } 148 } 149 150 // Connection to CAS server 151 $this->connectCAS(); 152 153 if (phpCAS::checkAuthentication()) { 154 $frm = new stdClass(); 155 $frm->username = phpCAS::getUser(); 156 $frm->password = 'passwdCas'; 157 158 // Redirect to a course if multi-auth is activated, authCAS is set to CAS and the courseid is specified. 159 if ($this->config->multiauth && !empty($courseid)) { 160 redirect(new moodle_url('/course/view.php', array('id'=>$courseid))); 161 } 162 163 return; 164 } 165 166 if (isset($_GET['loginguest']) && ($_GET['loginguest'] == true)) { 167 $frm = new stdClass(); 168 $frm->username = 'guest'; 169 $frm->password = 'guest'; 170 return; 171 } 172 173 // Force CAS authentication (if needed). 174 if (!phpCAS::isAuthenticated()) { 175 phpCAS::setLang($this->config->language); 176 phpCAS::forceAuthentication(); 177 } 178 } 179 180 181 /** 182 * Connect to the CAS (clientcas connection or proxycas connection) 183 * 184 */ 185 function connectCAS() { 186 global $CFG; 187 static $connected = false; 188 189 if (!$connected) { 190 // Make sure phpCAS doesn't try to start a new PHP session when connecting to the CAS server. 191 if ($this->config->proxycas) { 192 phpCAS::proxy($this->config->casversion, $this->config->hostname, (int) $this->config->port, $this->config->baseuri, false); 193 } else { 194 phpCAS::client($this->config->casversion, $this->config->hostname, (int) $this->config->port, $this->config->baseuri, false); 195 } 196 // Some CAS installs require SSLv3 that should be explicitly set. 197 if (!empty($this->config->curl_ssl_version)) { 198 phpCAS::setExtraCurlOption(CURLOPT_SSLVERSION, $this->config->curl_ssl_version); 199 } 200 201 $connected = true; 202 } 203 204 // If Moodle is configured to use a proxy, phpCAS needs some curl options set. 205 if (!empty($CFG->proxyhost) && !is_proxybypass(phpCAS::getServerLoginURL())) { 206 phpCAS::setExtraCurlOption(CURLOPT_PROXY, $CFG->proxyhost); 207 if (!empty($CFG->proxyport)) { 208 phpCAS::setExtraCurlOption(CURLOPT_PROXYPORT, $CFG->proxyport); 209 } 210 if (!empty($CFG->proxytype)) { 211 // Only set CURLOPT_PROXYTYPE if it's something other than the curl-default http 212 if ($CFG->proxytype == 'SOCKS5') { 213 phpCAS::setExtraCurlOption(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); 214 } 215 } 216 if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) { 217 phpCAS::setExtraCurlOption(CURLOPT_PROXYUSERPWD, $CFG->proxyuser.':'.$CFG->proxypassword); 218 if (defined('CURLOPT_PROXYAUTH')) { 219 // any proxy authentication if PHP 5.1 220 phpCAS::setExtraCurlOption(CURLOPT_PROXYAUTH, CURLAUTH_BASIC | CURLAUTH_NTLM); 221 } 222 } 223 } 224 225 if ($this->config->certificate_check && $this->config->certificate_path){ 226 phpCAS::setCasServerCACert($this->config->certificate_path); 227 } else { 228 // Don't try to validate the server SSL credentials 229 phpCAS::setNoCasServerValidation(); 230 } 231 } 232 233 /** 234 * Prints a form for configuring this authentication plugin. 235 * 236 * This function is called from admin/auth.php, and outputs a full page with 237 * a form for configuring this plugin. 238 * 239 * @param array $page An object containing all the data for this page. 240 */ 241 function config_form($config, $err, $user_fields) { 242 global $CFG, $OUTPUT; 243 244 if (!function_exists('ldap_connect')) { // Is php-ldap really there? 245 echo $OUTPUT->notification(get_string('auth_ldap_noextension', 'auth_ldap')); 246 247 // Don't return here, like we do in auth/ldap. We cas use CAS without LDAP. 248 // So just warn the user (done above) and define the LDAP constants we use 249 // in config.html, to silence the warnings. 250 if (!defined('LDAP_DEREF_NEVER')) { 251 define ('LDAP_DEREF_NEVER', 0); 252 } 253 if (!defined('LDAP_DEREF_ALWAYS')) { 254 define ('LDAP_DEREF_ALWAYS', 3); 255 } 256 } 257 258 include($CFG->dirroot.'/auth/cas/config.html'); 259 } 260 261 /** 262 * A chance to validate form data, and last chance to 263 * do stuff before it is inserted in config_plugin 264 * @param object object with submitted configuration settings (without system magic quotes) 265 * @param array $err array of error messages 266 */ 267 function validate_form($form, &$err) { 268 $certificate_path = trim($form->certificate_path); 269 if ($form->certificate_check && empty($certificate_path)) { 270 $err['certificate_path'] = get_string('auth_cas_certificate_path_empty', 'auth_cas'); 271 } 272 } 273 274 /** 275 * Returns the URL for changing the user's pw, or empty if the default can 276 * be used. 277 * 278 * @return moodle_url 279 */ 280 function change_password_url() { 281 return null; 282 } 283 284 /** 285 * Processes and stores configuration data for this authentication plugin. 286 */ 287 function process_config($config) { 288 289 // CAS settings 290 if (!isset($config->hostname)) { 291 $config->hostname = ''; 292 } 293 if (!isset($config->port)) { 294 $config->port = ''; 295 } 296 if (!isset($config->casversion)) { 297 $config->casversion = ''; 298 } 299 if (!isset($config->baseuri)) { 300 $config->baseuri = ''; 301 } 302 if (!isset($config->language)) { 303 $config->language = ''; 304 } 305 if (!isset($config->proxycas)) { 306 $config->proxycas = ''; 307 } 308 if (!isset($config->logoutcas)) { 309 $config->logoutcas = ''; 310 } 311 if (!isset($config->multiauth)) { 312 $config->multiauth = ''; 313 } 314 if (!isset($config->certificate_check)) { 315 $config->certificate_check = ''; 316 } 317 if (!isset($config->certificate_path)) { 318 $config->certificate_path = ''; 319 } 320 if (!isset($config->curl_ssl_version)) { 321 $config->curl_ssl_version = ''; 322 } 323 if (!isset($config->logout_return_url)) { 324 $config->logout_return_url = ''; 325 } 326 327 // LDAP settings 328 if (!isset($config->host_url)) { 329 $config->host_url = ''; 330 } 331 if (!isset($config->start_tls)) { 332 $config->start_tls = false; 333 } 334 if (empty($config->ldapencoding)) { 335 $config->ldapencoding = 'utf-8'; 336 } 337 if (!isset($config->pagesize)) { 338 $config->pagesize = LDAP_DEFAULT_PAGESIZE; 339 } 340 if (!isset($config->contexts)) { 341 $config->contexts = ''; 342 } 343 if (!isset($config->user_type)) { 344 $config->user_type = 'default'; 345 } 346 if (!isset($config->user_attribute)) { 347 $config->user_attribute = ''; 348 } 349 if (!isset($config->search_sub)) { 350 $config->search_sub = ''; 351 } 352 if (!isset($config->opt_deref)) { 353 $config->opt_deref = LDAP_DEREF_NEVER; 354 } 355 if (!isset($config->bind_dn)) { 356 $config->bind_dn = ''; 357 } 358 if (!isset($config->bind_pw)) { 359 $config->bind_pw = ''; 360 } 361 if (!isset($config->ldap_version)) { 362 $config->ldap_version = '3'; 363 } 364 if (!isset($config->objectclass)) { 365 $config->objectclass = ''; 366 } 367 if (!isset($config->memberattribute)) { 368 $config->memberattribute = ''; 369 } 370 371 if (!isset($config->memberattribute_isdn)) { 372 $config->memberattribute_isdn = ''; 373 } 374 if (!isset($config->attrcreators)) { 375 $config->attrcreators = ''; 376 } 377 if (!isset($config->groupecreators)) { 378 $config->groupecreators = ''; 379 } 380 if (!isset($config->removeuser)) { 381 $config->removeuser = AUTH_REMOVEUSER_KEEP; 382 } 383 384 // save CAS settings 385 set_config('hostname', trim($config->hostname), $this->pluginconfig); 386 set_config('port', trim($config->port), $this->pluginconfig); 387 set_config('casversion', $config->casversion, $this->pluginconfig); 388 set_config('baseuri', trim($config->baseuri), $this->pluginconfig); 389 set_config('language', $config->language, $this->pluginconfig); 390 set_config('proxycas', $config->proxycas, $this->pluginconfig); 391 set_config('logoutcas', $config->logoutcas, $this->pluginconfig); 392 set_config('multiauth', $config->multiauth, $this->pluginconfig); 393 set_config('certificate_check', $config->certificate_check, $this->pluginconfig); 394 set_config('certificate_path', $config->certificate_path, $this->pluginconfig); 395 set_config('curl_ssl_version', $config->curl_ssl_version, $this->pluginconfig); 396 set_config('logout_return_url', $config->logout_return_url, $this->pluginconfig); 397 398 // save LDAP settings 399 set_config('host_url', trim($config->host_url), $this->pluginconfig); 400 set_config('start_tls', $config->start_tls, $this->pluginconfig); 401 set_config('ldapencoding', trim($config->ldapencoding), $this->pluginconfig); 402 set_config('pagesize', (int)trim($config->pagesize), $this->pluginconfig); 403 set_config('contexts', trim($config->contexts), $this->pluginconfig); 404 set_config('user_type', core_text::strtolower(trim($config->user_type)), $this->pluginconfig); 405 set_config('user_attribute', core_text::strtolower(trim($config->user_attribute)), $this->pluginconfig); 406 set_config('search_sub', $config->search_sub, $this->pluginconfig); 407 set_config('opt_deref', $config->opt_deref, $this->pluginconfig); 408 set_config('bind_dn', trim($config->bind_dn), $this->pluginconfig); 409 set_config('bind_pw', $config->bind_pw, $this->pluginconfig); 410 set_config('ldap_version', $config->ldap_version, $this->pluginconfig); 411 set_config('objectclass', trim($config->objectclass), $this->pluginconfig); 412 set_config('memberattribute', core_text::strtolower(trim($config->memberattribute)), $this->pluginconfig); 413 set_config('memberattribute_isdn', $config->memberattribute_isdn, $this->pluginconfig); 414 set_config('attrcreators', trim($config->attrcreators), $this->pluginconfig); 415 set_config('groupecreators', trim($config->groupecreators), $this->pluginconfig); 416 set_config('removeuser', $config->removeuser, $this->pluginconfig); 417 418 return true; 419 } 420 421 /** 422 * Returns true if user should be coursecreator. 423 * 424 * @param mixed $username username (without system magic quotes) 425 * @return boolean result 426 */ 427 function iscreator($username) { 428 if (empty($this->config->host_url) or (empty($this->config->attrcreators) && empty($this->config->groupecreators)) or empty($this->config->memberattribute)) { 429 return false; 430 } 431 432 $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding); 433 434 // Test for group creator 435 if (!empty($this->config->groupecreators)) { 436 $ldapconnection = $this->ldap_connect(); 437 if ($this->config->memberattribute_isdn) { 438 if(!($userid = $this->ldap_find_userdn($ldapconnection, $extusername))) { 439 return false; 440 } 441 } else { 442 $userid = $extusername; 443 } 444 445 $group_dns = explode(';', $this->config->groupecreators); 446 if (ldap_isgroupmember($ldapconnection, $userid, $group_dns, $this->config->memberattribute)) { 447 return true; 448 } 449 } 450 451 // Build filter for attrcreator 452 if (!empty($this->config->attrcreators)) { 453 $attrs = explode(';', $this->config->attrcreators); 454 $filter = '(& ('.$this->config->user_attribute."=$username)(|"; 455 foreach ($attrs as $attr){ 456 if(strpos($attr, '=')) { 457 $filter .= "($attr)"; 458 } else { 459 $filter .= '('.$this->config->memberattribute."=$attr)"; 460 } 461 } 462 $filter .= '))'; 463 464 // Search 465 $result = $this->ldap_get_userlist($filter); 466 if (count($result) != 0) { 467 return true; 468 } 469 } 470 471 return false; 472 } 473 474 /** 475 * Reads user information from LDAP and returns it as array() 476 * 477 * If no LDAP servers are configured, user information has to be 478 * provided via other methods (CSV file, manually, etc.). Return 479 * an empty array so existing user info is not lost. Otherwise, 480 * calls parent class method to get user info. 481 * 482 * @param string $username username 483 * @return mixed array with no magic quotes or false on error 484 */ 485 function get_userinfo($username) { 486 if (empty($this->config->host_url)) { 487 return array(); 488 } 489 return parent::get_userinfo($username); 490 } 491 492 /** 493 * Syncronizes users from LDAP server to moodle user table. 494 * 495 * If no LDAP servers are configured, simply return. Otherwise, 496 * call parent class method to do the work. 497 * 498 * @param bool $do_updates will do pull in data updates from LDAP if relevant 499 * @return nothing 500 */ 501 function sync_users($do_updates=true) { 502 if (empty($this->config->host_url)) { 503 error_log('[AUTH CAS] '.get_string('noldapserver', 'auth_cas')); 504 return; 505 } 506 parent::sync_users($do_updates); 507 } 508 509 /** 510 * Hook for logout page 511 */ 512 function logoutpage_hook() { 513 global $USER, $redirect; 514 515 // Only do this if the user is actually logged in via CAS 516 if ($USER->auth === $this->authtype) { 517 // Check if there is an alternative logout return url defined 518 if (isset($this->config->logout_return_url) && !empty($this->config->logout_return_url)) { 519 // Set redirect to alternative return url 520 $redirect = $this->config->logout_return_url; 521 } 522 } 523 } 524 525 /** 526 * Post logout hook. 527 * 528 * Note: this method replace the prelogout_hook method to avoid redirect to CAS logout 529 * before the event userlogout being triggered. 530 * 531 * @param stdClass $user clone of USER object object before the user session was terminated 532 */ 533 public function postlogout_hook($user) { 534 global $CFG; 535 // Only redirect to CAS logout if the user is logged as a CAS user. 536 if (!empty($this->config->logoutcas) && $user->auth == $this->authtype) { 537 $backurl = !empty($this->config->logout_return_url) ? $this->config->logout_return_url : $CFG->wwwroot; 538 $this->connectCAS(); 539 phpCAS::logoutWithRedirectService($backurl); 540 } 541 } 542 }
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 |