[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

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

   1  <?php
   2  /**
   3   * @author Martin Dougiamas
   4   * @author Lukas Haemmerle
   5   * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
   6   * @package moodle multiauth
   7   *
   8   * Authentication Plugin: Shibboleth Authentication
   9   *
  10   * Authentication using Shibboleth.
  11   *
  12   * Distributed under GPL (c)Markus Hagman 2004-2006
  13   *
  14   * 10.2004     SHIBBOLETH Authentication functions v.0.1
  15   * 05.2005     Various extensions and fixes by Lukas Haemmerle
  16   * 10.2005     Added better error messags
  17   * 05.2006     Added better handling of mutli-valued attributes
  18   * 2006-08-28  File created, code imported from lib.php
  19   * 2006-10-27  Upstream 1.7 changes merged in, added above credits from lib.php :-)
  20   * 2007-03-09  Fixed authentication but may need some other changes
  21   * 2007-10-03  Removed requirement for email address, surname and given name on request of Markus Hagman
  22    * 2008-01-21 Added WAYF functionality
  23  
  24   */
  25  
  26  if (!defined('MOODLE_INTERNAL')) {
  27      die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
  28  }
  29  
  30  require_once($CFG->libdir.'/authlib.php');
  31  
  32  /**
  33   * Shibboleth authentication plugin.
  34   */
  35  class auth_plugin_shibboleth extends auth_plugin_base {
  36  
  37      /**
  38       * Constructor.
  39       */
  40      function auth_plugin_shibboleth() {
  41          $this->authtype = 'shibboleth';
  42          $this->config = get_config('auth/shibboleth');
  43      }
  44  
  45      /**
  46       * Returns true if the username and password work and false if they are
  47       * wrong or don't exist.
  48       *
  49       * @param string $username The username (with system magic quotes)
  50       * @param string $password The password (with system magic quotes)
  51       * @return bool Authentication success or failure.
  52       */
  53      function user_login($username, $password) {
  54          
  55          // If we are in the shibboleth directory then we trust the server var
  56          if (!empty($_SERVER[$this->config->user_attribute])) {
  57              return (strtolower($_SERVER[$this->config->user_attribute]) == strtolower($username));
  58          } else {
  59              // If we are not, the user has used the manual login and the login name is
  60              // unknown, so we return false.
  61              return false;
  62          }
  63      }
  64  
  65  
  66      
  67      /**
  68       * Returns the user information for 'external' users. In this case the
  69       * attributes provided by Shibboleth
  70       *
  71       * @return array $result Associative array of user data
  72       */
  73      function get_userinfo($username) {
  74      // reads user information from shibboleth attributes and return it in array()
  75          global $CFG;
  76  
  77          // Check whether we have got all the essential attributes
  78          if ( empty($_SERVER[$this->config->user_attribute]) ) {
  79              print_error( 'shib_not_all_attributes_error', 'auth' , '', "'".$this->config->user_attribute."' ('".$_SERVER[$this->config->user_attribute]."'), '".$this->config->field_map_firstname."' ('".$_SERVER[$this->config->field_map_firstname]."'), '".$this->config->field_map_lastname."' ('".$_SERVER[$this->config->field_map_lastname]."') and '".$this->config->field_map_email."' ('".$_SERVER[$this->config->field_map_email]."')");
  80          }
  81  
  82          $attrmap = $this->get_attributes();
  83  
  84          $result = array();
  85          $search_attribs = array();
  86  
  87          foreach ($attrmap as $key=>$value) {
  88              // Check if attribute is present  
  89              if (!isset($_SERVER[$value])){
  90                  $result[$key] = '';
  91                  continue;
  92              }
  93  
  94              // Make usename lowercase
  95              if ($key == 'username'){
  96                  $result[$key] = strtolower($this->get_first_string($_SERVER[$value]));
  97              } else {
  98                  $result[$key] = $this->get_first_string($_SERVER[$value]);
  99              }
 100          }
 101  
 102           // Provide an API to modify the information to fit the Moodle internal
 103          // data representation
 104          if (
 105                $this->config->convert_data
 106                && $this->config->convert_data != ''
 107                && is_readable($this->config->convert_data)
 108              ) {
 109  
 110              // Include a custom file outside the Moodle dir to
 111              // modify the variable $moodleattributes
 112              include($this->config->convert_data);
 113          }
 114  
 115          return $result;
 116      }
 117  
 118      /**
 119       * Returns array containg attribute mappings between Moodle and Shibboleth.
 120       *
 121       * @return array
 122       */
 123      function get_attributes() {
 124          $configarray = (array) $this->config;
 125  
 126          $moodleattributes = array();
 127          foreach ($this->userfields as $field) {
 128              if (isset($configarray["field_map_$field"])) {
 129                  $moodleattributes[$field] = $configarray["field_map_$field"];
 130              }
 131          }
 132          $moodleattributes['username'] = $configarray["user_attribute"];
 133  
 134          return $moodleattributes;
 135      }
 136  
 137      /**
 138       * Returns true if this authentication plugin is 'internal'.
 139       *
 140       * @return bool
 141       */
 142      function is_internal() {
 143          return false;
 144      }
 145  
 146      /**
 147       * Returns true if this authentication plugin can change the user's
 148       * password.
 149       *
 150       * @return bool
 151       */
 152      function can_change_password() {
 153          return false;
 154      }
 155  
 156       /**
 157       * Hook for login page
 158       *
 159       */
 160      function loginpage_hook() {
 161          global $SESSION, $CFG;
 162  
 163          // Prevent username from being shown on login page after logout
 164          $CFG->nolastloggedin = true;
 165  
 166          return;
 167      }
 168  
 169      /**
 170       * Prints a form for configuring this authentication plugin.
 171       *
 172       * This function is called from admin/auth.php, and outputs a full page with
 173       * a form for configuring this plugin.
 174       *
 175       * @param array $page An object containing all the data for this page.
 176       */
 177      function config_form($config, $err, $user_fields) {
 178          include  "config.html";
 179      }
 180  
 181      /**
 182       * Processes and stores configuration data for this authentication plugin.
 183       *
 184       *
 185       * @param object $config Configuration object
 186       */
 187      function process_config($config) {
 188          global $CFG;
 189  
 190          // set to defaults if undefined
 191          if (!isset($config->auth_instructions) or empty($config->user_attribute)) {
 192              $config->auth_instructions = get_string('shibboleth_instructions', 'auth', $CFG->wwwroot.'/auth/shibboleth/index.php');
 193          }
 194          if (!isset ($config->user_attribute)) {
 195              $config->user_attribute = '';
 196          }
 197          if (!isset ($config->convert_data)) {
 198              $config->convert_data = '';
 199          }
 200          
 201          if (!isset($config->changepasswordurl)) {
 202              $config->changepasswordurl = '';
 203          }
 204          
 205          if (!isset($config->login_name)) {
 206              $config->login_name = 'Shibboleth Login';
 207          }
 208          
 209          // Clean idp list
 210          if (isset($config->organization_selection) && !empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on') {
 211              $idp_list = get_idp_list($config->organization_selection);
 212              if (count($idp_list) < 1){
 213                  return false;
 214              }
 215              $config->organization_selection = '';
 216              foreach ($idp_list as $idp => $value){
 217                  $config->organization_selection .= $idp.', '.$value[0].', '.$value[1]."\n";
 218              }
 219          }
 220          
 221  
 222          // save settings
 223          set_config('user_attribute',    $config->user_attribute,    'auth/shibboleth');
 224          
 225          if (isset($config->organization_selection) && !empty($config->organization_selection)) {
 226              set_config('organization_selection',    $config->organization_selection,    'auth/shibboleth');
 227          }
 228          set_config('login_name',    $config->login_name,    'auth/shibboleth');
 229          set_config('convert_data',      $config->convert_data,      'auth/shibboleth');
 230          set_config('auth_instructions', $config->auth_instructions, 'auth/shibboleth');
 231          set_config('changepasswordurl', $config->changepasswordurl, 'auth/shibboleth');
 232          
 233          if (isset($config->alt_login) && $config->alt_login == 'on'){
 234              set_config('alt_login',    $config->alt_login,    'auth/shibboleth');
 235              set_config('alternateloginurl', $CFG->wwwroot.'/auth/shibboleth/login.php');
 236          } else {
 237              set_config('alt_login',    'off',    'auth/shibboleth');
 238              set_config('alternateloginurl', '');
 239              $config->alt_login = 'off';
 240          }
 241          
 242          // Check values and return false if something is wrong
 243          // Patch Anyware Technologies (14/05/07)
 244          if (($config->convert_data != '')&&(!file_exists($config->convert_data) || !is_readable($config->convert_data))){
 245              return false;
 246          }
 247          
 248          // Check if there is at least one entry in the IdP list
 249          if (isset($config->organization_selection) && empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on'){
 250              return false;
 251          }
 252  
 253          return true;
 254      }
 255  
 256      /**
 257       * Cleans and returns first of potential many values (multi-valued attributes)
 258       *
 259       * @param string $string Possibly multi-valued attribute from Shibboleth
 260       */
 261      function get_first_string($string) {
 262          $list = split( ';', $string);
 263          $clean_string = rtrim($list[0]);
 264  
 265          return $clean_string;
 266      }
 267  }
 268  
 269      
 270      /**
 271       * Sets the standard SAML domain cookie that is also used to preselect
 272       * the right entry on the local wayf
 273       *
 274       * @param IdP identifiere
 275       */
 276      function set_saml_cookie($selectedIDP) {
 277          if (isset($_COOKIE['_saml_idp']))
 278          {
 279              $IDPArray = generate_cookie_array($_COOKIE['_saml_idp']);
 280          }
 281          else
 282          {
 283              $IDPArray = array();
 284          }
 285          $IDPArray = appendCookieValue($selectedIDP, $IDPArray);
 286          setcookie ('_saml_idp', generate_cookie_value($IDPArray), time() + (100*24*3600));
 287      }
 288      
 289       /**
 290       * Prints the option elements for the select element of the drop down list 
 291       *
 292       */
 293      function print_idp_list(){
 294          $config = get_config('auth/shibboleth');
 295          
 296          $IdPs = get_idp_list($config->organization_selection);
 297          if (isset($_COOKIE['_saml_idp'])){
 298              $idp_cookie = generate_cookie_array($_COOKIE['_saml_idp']);
 299              do {
 300                  $selectedIdP = array_pop($idp_cookie);
 301              } while (!isset($IdPs[$selectedIdP]) && count($idp_cookie) > 0);
 302              
 303          } else {
 304              $selectedIdP = '-';
 305          }
 306          
 307          foreach($IdPs as $IdP => $data){
 308              if ($IdP == $selectedIdP){
 309                  echo '<option value="'.$IdP.'" selected="selected">'.$data[0].'</option>';
 310              } else {
 311                  echo '<option value="'.$IdP.'">'.$data[0].'</option>';
 312              }
 313          }
 314      }
 315      
 316      
 317       /**
 318       * Generate array of IdPs from Moodle Shibboleth settings
 319       *
 320       * @param string Text containing tuble/triple of IdP entityId, name and (optionally) session initiator
 321       * @return array Identifier of IdPs and their name/session initiator 
 322       */
 323  
 324      function get_idp_list($organization_selection) {
 325          $idp_list = array();
 326          
 327          $idp_raw_list = split("\n",  $organization_selection);
 328          
 329          foreach ($idp_raw_list as $idp_line){
 330              $idp_data = split(',', $idp_line);
 331              if (isset($idp_data[2]))
 332              {
 333                  $idp_list[trim($idp_data[0])] = array(trim($idp_data[1]),trim($idp_data[2])); 
 334              }
 335              elseif(isset($idp_data[1]))
 336              {
 337                  $idp_list[trim($idp_data[0])] = array(trim($idp_data[1]));
 338              }
 339          }
 340          
 341          return $idp_list;
 342      }
 343      
 344      /**
 345       * Generates an array of IDPs using the cookie value
 346       *
 347       * @param string Value of SAML domain cookie 
 348       * @return array Identifiers of IdPs 
 349       */
 350      function generate_cookie_array($value) {
 351          
 352          // Decodes and splits cookie value
 353          $CookieArray = split(' ', $value);
 354          $CookieArray = array_map('base64_decode', $CookieArray);
 355          
 356          return $CookieArray;
 357      }
 358      
 359      /**
 360       * Generate the value that is stored in the cookie using the list of IDPs
 361       *
 362       * @param array IdP identifiers 
 363       * @return string SAML domain cookie value
 364       */
 365      function generate_cookie_value($CookieArray) {
 366      
 367          // Merges cookie content and encodes it
 368          $CookieArray = array_map('base64_encode', $CookieArray);
 369          $value = implode(' ', $CookieArray);
 370          return $value;
 371      }
 372      
 373      /**
 374       * Append a value to the array of IDPs
 375       *
 376       * @param string IdP identifier
 377       * @param array IdP identifiers
 378       * @return array IdP identifiers with appended IdP 
 379       */
 380      function appendCookieValue($value, $CookieArray) {
 381          
 382          array_push($CookieArray, $value);
 383          $CookieArray = array_reverse($CookieArray);
 384          $CookieArray = array_unique($CookieArray);
 385          $CookieArray = array_reverse($CookieArray);
 386          
 387          return $CookieArray;
 388      }
 389  
 390  
 391  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7