ILIAS  Release_4_2_x_branch Revision 61807
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilShibboleth.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 
28 include_once("Auth/Auth.php");
29 
37 class ShibAuth extends Auth
38 {
44  var $username;
45 
51  var $_sessionName = '_authsession';
52 
58  var $status = '';
59 
68  var $expire = 0;
69 
80  var $idle = 0;
81 
88  var $idled = false;
89 
94  function ShibAuth($authParams, $updateUserData = false)
95  {
96  if ($authParams["sessionName"] != "") {
97  parent::Auth("", array("sessionName" => $authParams["sessionName"]));
98  }
99  else {
100  parent::Auth("");
101  }
102 
103  $this->updateUserData = $updateUserData;
104 
105 
106  if (!empty($authParams['sessionName'])) {
107  $this->setSessionName($authParams['sessionName']);
108  unset($authParams['sessionName']);
109  }
110 
111  }
112 
118  public function supportsRedirects()
119  {
120  return true;
121  }
122 
123 
124 
132  function setIdle($time, $add = false)
133  {
134  if ($add) {
135  $this->idle += $time;
136  } else {
137  $this->idle = $time;
138  }
139  }
140 
141 
150  function setExpire($time, $add = false)
151  {
152  if ($add) {
153  $this->expire += $time;
154  } else {
155  $this->expire = $time;
156  }
157  }
158 
159 
166  function login()
167  {
168  global $ilias, $rbacadmin, $ilSetting;
169  if (!empty($_SERVER[$ilias->getSetting('shib_login')]))
170  {
171 
172  // Store user's Shibboleth sessionID for logout
173  $this->session['shibboleth_session_id'] = $_SERVER['Shib-Session-ID'];
174 
175  // Get loginname of user, new login name is generated if user is new
176  $username = $this->generateLogin();
177 
178  // Authorize this user
179  $this->setAuth($username);
180 
181  $userObj = new ilObjUser();
182 
183  // Check wether this account exists already, if not create it
185  {
186 
187  $newUser["firstname"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_firstname')]);
188  $newUser["lastname"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_lastname')]);
189  $newUser["login"] = $username;
190 
191  // Password must be random to prevent users from manually log in using the login data from Shibboleth users
192  $newUser["passwd"] = md5(end(ilUtil::generatePasswords(1)));
193  $newUser["passwd_type"] = IL_PASSWD_MD5;
194 
195  if (
196  $ilias->getSetting('shib_update_gender')
197  && ($_SERVER[$ilias->getSetting('shib_gender')] == 'm'
198  || $_SERVER[$ilias->getSetting('shib_gender')] =='f')
199  )
200  {
201  $newUser["gender"] = $_SERVER[$ilias->getSetting('shib_gender')];
202  }
203 
204  // Save mapping between ILIAS user and Shibboleth uniqueID
205  $newUser["ext_account"] = $_SERVER[$ilias->getSetting('shib_login')];
206 
207  // other data
208  $newUser["title"] = $_SERVER[$ilias->getSetting('shib_title')];
209  $newUser["institution"] = $_SERVER[$ilias->getSetting('shib_institution')];
210  $newUser["department"] = $_SERVER[$ilias->getSetting('shib_department')];
211  $newUser["street"] = $_SERVER[$ilias->getSetting('shib_street')];
212  $newUser["city"] = $_SERVER[$ilias->getSetting('shib_city')];
213  $newUser["zipcode"] = $_SERVER[$ilias->getSetting('shib_zipcode')];
214  $newUser["country"] = $_SERVER[$ilias->getSetting('shib_country')];
215  $newUser["phone_office"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_office')]);
216  $newUser["phone_home"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_home')]);
217  $newUser["phone_mobile"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_mobile')]);
218  $newUser["fax"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_fax')]);
219  $newUser["matriculation"] = $_SERVER[$ilias->getSetting('shib_matriculation')];
220  $newUser["email"] = $this->getFirstString($_SERVER[$ilias->getSetting('shib_email')]);
221  $newUser["hobby"] = $_SERVER[$ilias->getSetting('shib_hobby')];
222  $newUser["auth_mode"] = "shibboleth";
223 
224 
225  // system data
226  $userObj->assignData($newUser);
227  $userObj->setTitle($userObj->getFullname());
228  $userObj->setDescription($userObj->getEmail());
229  $userObj->setLanguage($this->getFirstString($_SERVER[$ilias->getSetting('shib_language')]));
230 
231  // Time limit
232  $userObj->setTimeLimitOwner(7);
233  $userObj->setTimeLimitUnlimited(1);
234  $userObj->setTimeLimitFrom(time());
235  $userObj->setTimeLimitUntil(time());
236 
237  // Modify user data before creating the user
238  // Include custom code that can be used to further modify
239  // certain Shibboleth user attributes
240  if ( $ilias->getSetting('shib_data_conv')
241  && $ilias->getSetting('shib_data_conv') != ''
242  && is_readable($ilias->getSetting('shib_data_conv'))
243  )
244  {
245  include($ilias->getSetting('shib_data_conv'));
246  }
247 
248  // Create use in DB
249  $userObj->create();
250  $userObj->setActive(1);
251 
252  $userObj->updateOwner();
253 
254  //insert user data in table user_data
255  $userObj->saveAsNew();
256 
257  // store acceptance of user agreement
258  //$userObj->writeAccepted();
259 
260  // Default prefs
261  $userObj->setPref('hits_per_page',$ilSetting->get('hits_per_page',30));
262  $userObj->setPref('show_users_online',$ilSetting->get('show_users_online','y'));
263 
264  // setup user preferences
265  $userObj->writePrefs();
266 
267  //set role entries
268  #$rbacadmin->assignUser($ilias->getSetting('shib_user_default_role'), $userObj->getId(),true);
269  // New role assignment
270  include_once './Services/AuthShibboleth/classes/class.ilShibbolethRoleAssignmentRules.php';
271  ilShibbolethRoleAssignmentRules::doAssignments($userObj->getId(),$_SERVER);
272 
273  // Authorize this user
274  $this->setAuth($userObj->getLogin());
275 
276  }
277  else
278  {
279  // Update user account
280  $uid = $userObj->checkUserId();
281  $userObj->setId($uid);
282  $userObj->read($uid);
283 
284  if (
285  $ilias->getSetting('shib_update_gender')
286  && ($_SERVER[$ilias->getSetting('shib_gender')] == 'm'
287  || $_SERVER[$ilias->getSetting('shib_gender')] =='f')
288  )
289  $userObj->setGender($_SERVER[$ilias->getSetting('shib_gender')]);
290 
291  if ($ilias->getSetting('shib_update_title'))
292  $userObj->setTitle($_SERVER[$ilias->getSetting('shib_title')]);
293 
294  $userObj->setFirstname($this->getFirstString($_SERVER[$ilias->getSetting('shib_firstname')]));
295  $userObj->setLastname($this->getFirstString($_SERVER[$ilias->getSetting('shib_lastname')]));
296  $userObj->setFullname();
297  if ($ilias->getSetting('shib_update_institution'))
298  $userObj->setInstitution($_SERVER[$ilias->getSetting('shib_institution')]);
299  if ($ilias->getSetting('shib_update_department'))
300  $userObj->setDepartment($_SERVER[$ilias->getSetting('shib_department')]);
301  if ($ilias->getSetting('shib_update_street'))
302  $userObj->setStreet($_SERVER[$ilias->getSetting('shib_street')]);
303  if ($ilias->getSetting('shib_update_city'))
304  $userObj->setCity($_SERVER[$ilias->getSetting('shib_city')]);
305  if ($ilias->getSetting('shib_update_zipcode'))
306  $userObj->setZipcode($_SERVER[$ilias->getSetting('shib_zipcode')]);
307  if ($ilias->getSetting('shib_update_country'))
308  $userObj->setCountry($_SERVER[$ilias->getSetting('shib_country')]);
309  if ($ilias->getSetting('shib_update_phone_office'))
310  $userObj->setPhoneOffice($this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_office')]));
311  if ($ilias->getSetting('shib_update_phone_home'))
312  $userObj->setPhoneHome($this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_home')]));
313  if ($ilias->getSetting('shib_update_phone_mobile'))
314  $userObj->setPhoneMobile($this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_mobile')]));
315  if ($ilias->getSetting('shib_update_fax'))
316  $userObj->setFax($_SERVER[$ilias->getSetting('shib_fax')]);
317  if ($ilias->getSetting('shib_update_matriculation'))
318  $userObj->setMatriculation($_SERVER[$ilias->getSetting('shib_matriculation')]);
319  if ($ilias->getSetting('shib_update_email'))
320  $userObj->setEmail($this->getFirstString($_SERVER[$ilias->getSetting('shib_email')]));
321  if ($ilias->getSetting('shib_update_hobby'))
322  $userObj->setHobby($_SERVER[$ilias->getSetting('shib_hobby')]);
323 
324  if ($ilias->getSetting('shib_update_language'))
325  $userObj->setLanguage($_SERVER[$ilias->getSetting('shib_language')]);
326 
327  // Include custom code that can be used to further modify
328  // certain Shibboleth user attributes
329  if ( $ilias->getSetting('shib_data_conv')
330  && $ilias->getSetting('shib_data_conv') != ''
331  && is_readable($ilias->getSetting('shib_data_conv'))
332  )
333  {
334  include($ilias->getSetting('shib_data_conv'));
335  }
336 
337 
338  $userObj->update();
339 
340  // Update role assignments
341  include_once './Services/AuthShibboleth/classes/class.ilShibbolethRoleAssignmentRules.php';
342  ilShibbolethRoleAssignmentRules::updateAssignments($userObj->getId(),$_SERVER);
343  }
344 
345  // we are authenticated: redirect, if possible
346  if ($_GET["target"] != "")
347  {
348  ilUtil::redirect("goto.php?target=".$_GET["target"]."&client_id=".CLIENT_ID);
349  }
350  }
351  else
352  {
353  // This should never occur unless Shibboleth is not configured properly
354  $this->status = AUTH_WRONG_LOGIN;
355  }
356  }
357 
368  function logout()
369  {
370  parent::logout();
371  }
372 
373 
381  function generateLogin()
382  {
383  global $ilias, $ilDB;
384 
385  $shibID = $_SERVER[$ilias->getSetting('shib_login')];
386  $lastname = $this->getFirstString($_SERVER[$ilias->getSetting('shib_lastname')]);
387  $firstname = $this->getFirstString($_SERVER[$ilias->getSetting('shib_firstname')]);
388 
389  if (trim($shibID) == "")
390  {
391  return;
392  }
393 
394  //***********************************************//
395  // For backwards compatibility with previous versions
396  // We use the passwd field as mapping attribute for Shibboleth users
397  // because they don't need a password
398  $ilias->db->query("UPDATE usr_data SET auth_mode='shibboleth', passwd=".$ilDB->quote(md5(end(ilUtil::generatePasswords(1)))).", ext_account=".$ilDB->quote($shibID)." WHERE passwd=".$ilDB->quote($shibID));
399  //***********************************************//
400 
401  // Let's see if user already is registered
402  $local_user = ilObjUser::_checkExternalAuthAccount("shibboleth", $shibID);
403  if ($local_user)
404  {
405  return $local_user;
406  }
407 
408  // User doesn't seem to exist yet
409 
410  // Generate new username
411  // This can be overruled by the data conversion API but you have
412  // to do it yourself in that case
413 
414  // Generate the username out of the first character of firstname and the
415  // first word in lastname (adding the second one if the login is too short,
416  // avoiding meaningless last names like 'von' or 'd' and eliminating
417  // non-ASCII-characters, spaces, dashes etc.
418 
419  $ln_arr=preg_split("/[ '-;]/", $lastname);
420  $login=substr($this->toAscii($firstname),0,1) . "." . $this->toAscii($ln_arr[0]);
421  if (strlen($login) < 6) $login .= $this->toAscii($ln_arr[1]);
422  $prefix = strtolower($login);
423 
424  // If the user name didn't contain any ASCII characters, assign the
425  // name 'shibboleth' followed by a number, starting with 1.
426  if (strlen($prefix) == 0) {
427  $prefix = 'shibboleth';
428  $number = 1;
429  }
430  else
431  {
432  // Try if the login name is not already taken
433  if (!ilObjUser::getUserIdByLogin($prefix))
434  {
435  return $prefix;
436  }
437 
438  // If the login name is in use, append a number, starting with 2.
439  $number = 2;
440  }
441 
442  // Append a number, if the username is already taken
443  while (ilObjUser::getUserIdByLogin($prefix.$number))
444  {
445  $number++;
446  }
447 
448  return $prefix.$number;
449  }
450 
458  function getFirstString($string){
459 
460  $list = split( ';', $string);
461  $clean_string = rtrim($list[0]);
462 
463  return $clean_string;
464 
465  }
466 
474  function toAscii($string) {
475  require_once('include/Unicode/UtfNormal.php');
476 
477  // Normalize to NFKD.
478  // This separates letters from combining marks.
479  // See http://unicode.org/reports/tr15
480  $string = UtfNormal::toNFKD($string);
481 
482  // Replace german usages of diaeresis by appending an e
483  $string = preg_replace('/([aouAOU])\\xcc\\x88/','\\1e', $string);
484 
485  // Replace the combined ae character by separated a and e
486  $string = preg_replace('/\\xc3\\x86/','AE', $string);
487  $string = preg_replace('/\\xc3\\xa6/','ae', $string);
488 
489  // Replace the combined thorn character by th
490  $string = preg_replace('/\\xc3\\x9e/','TH', $string);
491  $string = preg_replace('/\\xc3\\xbe/','th', $string);
492 
493  // Replace the letter eth by d
494  $string = preg_replace('/\\xc3\\x90/','D', $string);
495  $string = preg_replace('/\\xc4\\x91/','d', $string);
496  $string = preg_replace('/\\xc4\\x90/','D', $string);
497 
498  // Replace the combined ss character
499  $string = preg_replace('/\\xc3\\x9f/','ss', $string);
500 
501  // Get rid of everything except the characters a to z and the hyphen
502  $string = preg_replace('/[^a-zA-Z\-]/i','', $string);
503 
504  return $string;
505  }
506 
507 } // END class.ilShibAuth
508 ?>