|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00026 if (!defined('MOODLE_INTERNAL')) { 00027 die('Direct access to this script is forbidden.'); 00028 } 00029 00030 require_once($CFG->libdir.'/authlib.php'); 00031 00035 class auth_plugin_shibboleth extends auth_plugin_base { 00036 00040 function auth_plugin_shibboleth() { 00041 $this->authtype = 'shibboleth'; 00042 $this->config = get_config('auth/shibboleth'); 00043 } 00044 00053 function user_login($username, $password) { 00054 global $SESSION; 00055 00056 // If we are in the shibboleth directory then we trust the server var 00057 if (!empty($_SERVER[$this->config->user_attribute])) { 00058 // Associate Shibboleth session with user for SLO preparation 00059 $sessionkey = ''; 00060 if (isset($_SERVER['Shib-Session-ID'])){ 00061 // This is only available for Shibboleth 2.x SPs 00062 $sessionkey = $_SERVER['Shib-Session-ID']; 00063 } else { 00064 // Try to find out using the user's cookie 00065 foreach ($_COOKIE as $name => $value){ 00066 if (preg_match('/_shibsession_/i', $name)){ 00067 $sessionkey = $value; 00068 } 00069 } 00070 } 00071 00072 // Set shibboleth session ID for logout 00073 $SESSION->shibboleth_session_id = $sessionkey; 00074 00075 return (strtolower($_SERVER[$this->config->user_attribute]) == strtolower($username)); 00076 } else { 00077 // If we are not, the user has used the manual login and the login name is 00078 // unknown, so we return false. 00079 return false; 00080 } 00081 } 00082 00083 00084 00091 function get_userinfo($username) { 00092 // reads user information from shibboleth attributes and return it in array() 00093 global $CFG; 00094 00095 // Check whether we have got all the essential attributes 00096 if ( empty($_SERVER[$this->config->user_attribute]) ) { 00097 print_error( 'shib_not_all_attributes_error', 'auth_shibboleth' , '', "'".$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]."')"); 00098 } 00099 00100 $attrmap = $this->get_attributes(); 00101 00102 $result = array(); 00103 $search_attribs = array(); 00104 00105 foreach ($attrmap as $key=>$value) { 00106 // Check if attribute is present 00107 if (!isset($_SERVER[$value])){ 00108 $result[$key] = ''; 00109 continue; 00110 } 00111 00112 // Make usename lowercase 00113 if ($key == 'username'){ 00114 $result[$key] = strtolower($this->get_first_string($_SERVER[$value])); 00115 } else { 00116 $result[$key] = $this->get_first_string($_SERVER[$value]); 00117 } 00118 } 00119 00120 // Provide an API to modify the information to fit the Moodle internal 00121 // data representation 00122 if ( 00123 $this->config->convert_data 00124 && $this->config->convert_data != '' 00125 && is_readable($this->config->convert_data) 00126 ) { 00127 00128 // Include a custom file outside the Moodle dir to 00129 // modify the variable $moodleattributes 00130 include($this->config->convert_data); 00131 } 00132 00133 return $result; 00134 } 00135 00141 function get_attributes() { 00142 $configarray = (array) $this->config; 00143 00144 $moodleattributes = array(); 00145 foreach ($this->userfields as $field) { 00146 if (isset($configarray["field_map_$field"])) { 00147 $moodleattributes[$field] = $configarray["field_map_$field"]; 00148 } 00149 } 00150 $moodleattributes['username'] = $configarray["user_attribute"]; 00151 00152 return $moodleattributes; 00153 } 00154 00155 function prevent_local_passwords() { 00156 return true; 00157 } 00158 00164 function is_internal() { 00165 return false; 00166 } 00167 00174 function can_change_password() { 00175 return false; 00176 } 00177 00182 function loginpage_hook() { 00183 global $SESSION, $CFG; 00184 00185 // Prevent username from being shown on login page after logout 00186 $CFG->nolastloggedin = true; 00187 00188 return; 00189 } 00190 00195 function logoutpage_hook() { 00196 global $SESSION, $redirect; 00197 00198 // Only do this if logout handler is defined, and if the user is actually logged in via Shibboleth 00199 $logouthandlervalid = isset($this->config->logout_handler) && !empty($this->config->logout_handler); 00200 if (isset($SESSION->shibboleth_session_id) && $logouthandlervalid ) { 00201 // Check if there is an alternative logout return url defined 00202 if (isset($this->config->logout_return_url) && !empty($this->config->logout_return_url)) { 00203 // Set temp_redirect to alternative return url 00204 $temp_redirect = $this->config->logout_return_url; 00205 } else { 00206 // Backup old redirect url 00207 $temp_redirect = $redirect; 00208 } 00209 00210 // Overwrite redirect in order to send user to Shibboleth logout page and let him return back 00211 $redirect = $this->config->logout_handler.'?return='.urlencode($temp_redirect); 00212 } 00213 } 00214 00215 00216 00225 function config_form($config, $err, $user_fields) { 00226 include "config.html"; 00227 } 00228 00235 function process_config($config) { 00236 global $CFG; 00237 00238 // set to defaults if undefined 00239 if (!isset($config->auth_instructions) or empty($config->user_attribute)) { 00240 $config->auth_instructions = get_string('auth_shib_instructions', 'auth_shibboleth', $CFG->wwwroot.'/auth/shibboleth/index.php'); 00241 } 00242 if (!isset ($config->user_attribute)) { 00243 $config->user_attribute = ''; 00244 } 00245 if (!isset ($config->convert_data)) { 00246 $config->convert_data = ''; 00247 } 00248 00249 if (!isset($config->changepasswordurl)) { 00250 $config->changepasswordurl = ''; 00251 } 00252 00253 if (!isset($config->login_name)) { 00254 $config->login_name = 'Shibboleth Login'; 00255 } 00256 00257 // Clean idp list 00258 if (isset($config->organization_selection) && !empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on') { 00259 $idp_list = get_idp_list($config->organization_selection); 00260 if (count($idp_list) < 1){ 00261 return false; 00262 } 00263 $config->organization_selection = ''; 00264 foreach ($idp_list as $idp => $value){ 00265 $config->organization_selection .= $idp.', '.$value[0].', '.$value[1]."\n"; 00266 } 00267 } 00268 00269 00270 // save settings 00271 set_config('user_attribute', $config->user_attribute, 'auth/shibboleth'); 00272 00273 if (isset($config->organization_selection) && !empty($config->organization_selection)) { 00274 set_config('organization_selection', $config->organization_selection, 'auth/shibboleth'); 00275 } 00276 set_config('logout_handler', $config->logout_handler, 'auth/shibboleth'); 00277 set_config('logout_return_url', $config->logout_return_url, 'auth/shibboleth'); 00278 set_config('login_name', $config->login_name, 'auth/shibboleth'); 00279 set_config('convert_data', $config->convert_data, 'auth/shibboleth'); 00280 set_config('auth_instructions', $config->auth_instructions, 'auth/shibboleth'); 00281 set_config('changepasswordurl', $config->changepasswordurl, 'auth/shibboleth'); 00282 00283 // Overwrite alternative login URL if integrated WAYF is used 00284 if (isset($config->alt_login) && $config->alt_login == 'on'){ 00285 set_config('alt_login', $config->alt_login, 'auth/shibboleth'); 00286 set_config('alternateloginurl', $CFG->wwwroot.'/auth/shibboleth/login.php'); 00287 } else { 00288 // Check if integrated WAYF was enabled and is now turned off 00289 // If it was and only then, reset the Moodle alternate URL 00290 if (isset($this->config->alt_login) and $this->config->alt_login == 'on'){ 00291 set_config('alt_login', 'off', 'auth/shibboleth'); 00292 set_config('alternateloginurl', ''); 00293 } 00294 $config->alt_login = 'off'; 00295 } 00296 00297 // Check values and return false if something is wrong 00298 // Patch Anyware Technologies (14/05/07) 00299 if (($config->convert_data != '')&&(!file_exists($config->convert_data) || !is_readable($config->convert_data))){ 00300 return false; 00301 } 00302 00303 // Check if there is at least one entry in the IdP list 00304 if (isset($config->organization_selection) && empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on'){ 00305 return false; 00306 } 00307 00308 return true; 00309 } 00310 00316 function get_first_string($string) { 00317 $list = explode( ';', $string); 00318 $clean_string = rtrim($list[0]); 00319 00320 return $clean_string; 00321 } 00322 } 00323 00324 00331 function set_saml_cookie($selectedIDP) { 00332 if (isset($_COOKIE['_saml_idp'])) 00333 { 00334 $IDPArray = generate_cookie_array($_COOKIE['_saml_idp']); 00335 } 00336 else 00337 { 00338 $IDPArray = array(); 00339 } 00340 $IDPArray = appendCookieValue($selectedIDP, $IDPArray); 00341 setcookie ('_saml_idp', generate_cookie_value($IDPArray), time() + (100*24*3600)); 00342 } 00343 00348 function print_idp_list(){ 00349 $config = get_config('auth/shibboleth'); 00350 00351 $IdPs = get_idp_list($config->organization_selection); 00352 if (isset($_COOKIE['_saml_idp'])){ 00353 $idp_cookie = generate_cookie_array($_COOKIE['_saml_idp']); 00354 do { 00355 $selectedIdP = array_pop($idp_cookie); 00356 } while (!isset($IdPs[$selectedIdP]) && count($idp_cookie) > 0); 00357 00358 } else { 00359 $selectedIdP = '-'; 00360 } 00361 00362 foreach($IdPs as $IdP => $data){ 00363 if ($IdP == $selectedIdP){ 00364 echo '<option value="'.$IdP.'" selected="selected">'.$data[0].'</option>'; 00365 } else { 00366 echo '<option value="'.$IdP.'">'.$data[0].'</option>'; 00367 } 00368 } 00369 } 00370 00371 00379 function get_idp_list($organization_selection) { 00380 $idp_list = array(); 00381 00382 $idp_raw_list = explode("\n", $organization_selection); 00383 00384 foreach ($idp_raw_list as $idp_line){ 00385 $idp_data = explode(',', $idp_line); 00386 if (isset($idp_data[2])) 00387 { 00388 $idp_list[trim($idp_data[0])] = array(trim($idp_data[1]),trim($idp_data[2])); 00389 } 00390 elseif(isset($idp_data[1])) 00391 { 00392 $idp_list[trim($idp_data[0])] = array(trim($idp_data[1])); 00393 } 00394 } 00395 00396 return $idp_list; 00397 } 00398 00405 function generate_cookie_array($value) { 00406 00407 // Decodes and splits cookie value 00408 $CookieArray = explode(' ', $value); 00409 $CookieArray = array_map('base64_decode', $CookieArray); 00410 00411 return $CookieArray; 00412 } 00413 00420 function generate_cookie_value($CookieArray) { 00421 00422 // Merges cookie content and encodes it 00423 $CookieArray = array_map('base64_encode', $CookieArray); 00424 $value = implode(' ', $CookieArray); 00425 return $value; 00426 } 00427 00435 function appendCookieValue($value, $CookieArray) { 00436 00437 array_push($CookieArray, $value); 00438 $CookieArray = array_reverse($CookieArray); 00439 $CookieArray = array_unique($CookieArray); 00440 $CookieArray = array_reverse($CookieArray); 00441 00442 return $CookieArray; 00443 } 00444 00445 00446