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