ILIAS  Release_4_1_x_branch Revision 61804
 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  unset($userObj);
274 
275  // Authorize this user
276  $this->setAuth($username);
277 
278  }
279  else
280  {
281  // Update user account
282  $uid = $userObj->checkUserId();
283  $userObj->setId($uid);
284  $userObj->read($uid);
285 
286  if (
287  $ilias->getSetting('shib_update_gender')
288  && ($_SERVER[$ilias->getSetting('shib_gender')] == 'm'
289  || $_SERVER[$ilias->getSetting('shib_gender')] =='f')
290  )
291  $userObj->setGender($_SERVER[$ilias->getSetting('shib_gender')]);
292 
293  if ($ilias->getSetting('shib_update_title'))
294  $userObj->setTitle($_SERVER[$ilias->getSetting('shib_title')]);
295 
296  $userObj->setFirstname($this->getFirstString($_SERVER[$ilias->getSetting('shib_firstname')]));
297  $userObj->setLastname($this->getFirstString($_SERVER[$ilias->getSetting('shib_lastname')]));
298  $userObj->setFullname();
299  if ($ilias->getSetting('shib_update_institution'))
300  $userObj->setInstitution($_SERVER[$ilias->getSetting('shib_institution')]);
301  if ($ilias->getSetting('shib_update_department'))
302  $userObj->setDepartment($_SERVER[$ilias->getSetting('shib_department')]);
303  if ($ilias->getSetting('shib_update_street'))
304  $userObj->setStreet($_SERVER[$ilias->getSetting('shib_street')]);
305  if ($ilias->getSetting('shib_update_city'))
306  $userObj->setCity($_SERVER[$ilias->getSetting('shib_city')]);
307  if ($ilias->getSetting('shib_update_zipcode'))
308  $userObj->setZipcode($_SERVER[$ilias->getSetting('shib_zipcode')]);
309  if ($ilias->getSetting('shib_update_country'))
310  $userObj->setCountry($_SERVER[$ilias->getSetting('shib_country')]);
311  if ($ilias->getSetting('shib_update_phone_office'))
312  $userObj->setPhoneOffice($this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_office')]));
313  if ($ilias->getSetting('shib_update_phone_home'))
314  $userObj->setPhoneHome($this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_home')]));
315  if ($ilias->getSetting('shib_update_phone_mobile'))
316  $userObj->setPhoneMobile($this->getFirstString($_SERVER[$ilias->getSetting('shib_phone_mobile')]));
317  if ($ilias->getSetting('shib_update_fax'))
318  $userObj->setFax($_SERVER[$ilias->getSetting('shib_fax')]);
319  if ($ilias->getSetting('shib_update_matriculation'))
320  $userObj->setMatriculation($_SERVER[$ilias->getSetting('shib_matriculation')]);
321  if ($ilias->getSetting('shib_update_email'))
322  $userObj->setEmail($this->getFirstString($_SERVER[$ilias->getSetting('shib_email')]));
323  if ($ilias->getSetting('shib_update_hobby'))
324  $userObj->setHobby($_SERVER[$ilias->getSetting('shib_hobby')]);
325 
326  if ($ilias->getSetting('shib_update_language'))
327  $userObj->setLanguage($_SERVER[$ilias->getSetting('shib_language')]);
328 
329  // Include custom code that can be used to further modify
330  // certain Shibboleth user attributes
331  if ( $ilias->getSetting('shib_data_conv')
332  && $ilias->getSetting('shib_data_conv') != ''
333  && is_readable($ilias->getSetting('shib_data_conv'))
334  )
335  {
336  include($ilias->getSetting('shib_data_conv'));
337  }
338 
339 
340  $userObj->update();
341 
342  // Update role assignments
343  include_once './Services/AuthShibboleth/classes/class.ilShibbolethRoleAssignmentRules.php';
344  ilShibbolethRoleAssignmentRules::updateAssignments($userObj->getId(),$_SERVER);
345  }
346 
347  // we are authenticated: redirect, if possible
348  if ($_GET["target"] != "")
349  {
350  ilUtil::redirect("goto.php?target=".$_GET["target"]."&client_id=".CLIENT_ID);
351  }
352  }
353  else
354  {
355  // This should never occur unless Shibboleth is not configured properly
356  $this->status = AUTH_WRONG_LOGIN;
357  }
358  }
359 
370  function logout()
371  {
372  parent::logout();
373  }
374 
375 
383  function generateLogin()
384  {
385  global $ilias, $ilDB;
386 
387  $shibID = $_SERVER[$ilias->getSetting('shib_login')];
388  $lastname = $this->getFirstString($_SERVER[$ilias->getSetting('shib_lastname')]);
389  $firstname = $this->getFirstString($_SERVER[$ilias->getSetting('shib_firstname')]);
390 
391  if (trim($shibID) == "")
392  {
393  return;
394  }
395 
396  //***********************************************//
397  // For backwards compatibility with previous versions
398  // We use the passwd field as mapping attribute for Shibboleth users
399  // because they don't need a password
400  $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));
401  //***********************************************//
402 
403  // Let's see if user already is registered
404  $local_user = ilObjUser::_checkExternalAuthAccount("shibboleth", $shibID);
405  if ($local_user)
406  {
407  return $local_user;
408  }
409 
410  // User doesn't seem to exist yet
411 
412  // Generate new username
413  // This can be overruled by the data conversion API but you have
414  // to do it yourself in that case
415 
416  // Generate the username out of the first character of firstname and the
417  // first word in lastname (adding the second one if the login is too short,
418  // avoiding meaningless last names like 'von' or 'd' and eliminating
419  // non-ASCII-characters, spaces, dashes etc.
420 
421  $ln_arr=preg_split("/[ '-;]/", $lastname);
422  $login=substr($this->toAscii($firstname),0,1) . "." . $this->toAscii($ln_arr[0]);
423  if (strlen($login) < 6) $login .= $this->toAscii($ln_arr[1]);
424  $prefix = strtolower($login);
425 
426  // If the user name didn't contain any ASCII characters, assign the
427  // name 'shibboleth' followed by a number, starting with 1.
428  if (strlen($prefix) == 0) {
429  $prefix = 'shibboleth';
430  $number = 1;
431  }
432  else
433  {
434  // Try if the login name is not already taken
435  if (!ilObjUser::getUserIdByLogin($prefix))
436  {
437  return $prefix;
438  }
439 
440  // If the login name is in use, append a number, starting with 2.
441  $number = 2;
442  }
443 
444  // Append a number, if the username is already taken
445  while (ilObjUser::getUserIdByLogin($prefix.$number))
446  {
447  $number++;
448  }
449 
450  return $prefix.$number;
451  }
452 
460  function getFirstString($string){
461 
462  $list = split( ';', $string);
463  $clean_string = rtrim($list[0]);
464 
465  return $clean_string;
466 
467  }
468 
476  function toAscii($string) {
477  require_once('include/Unicode/UtfNormal.php');
478 
479  // Normalize to NFKD.
480  // This separates letters from combining marks.
481  // See http://unicode.org/reports/tr15
482  $string = UtfNormal::toNFKD($string);
483 
484  // Replace german usages of diaeresis by appending an e
485  $string = preg_replace('/([aouAOU])\\xcc\\x88/','\\1e', $string);
486 
487  // Replace the combined ae character by separated a and e
488  $string = preg_replace('/\\xc3\\x86/','AE', $string);
489  $string = preg_replace('/\\xc3\\xa6/','ae', $string);
490 
491  // Replace the combined thorn character by th
492  $string = preg_replace('/\\xc3\\x9e/','TH', $string);
493  $string = preg_replace('/\\xc3\\xbe/','th', $string);
494 
495  // Replace the letter eth by d
496  $string = preg_replace('/\\xc3\\x90/','D', $string);
497  $string = preg_replace('/\\xc4\\x91/','d', $string);
498  $string = preg_replace('/\\xc4\\x90/','D', $string);
499 
500  // Replace the combined ss character
501  $string = preg_replace('/\\xc3\\x9f/','ss', $string);
502 
503  // Get rid of everything except the characters a to z and the hyphen
504  $string = preg_replace('/[^a-zA-Z\-]/i','', $string);
505 
506  return $string;
507  }
508 
509 } // END class.ilShibAuth
510 ?>