[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/auth/cas/ -> auth.php (source)

   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  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1