1<?php 2// must be run within Dokuwiki 3if(!defined('DOKU_INC')) die(); 4 5/** 6 * Authentication backend using generic SSO 7 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 8 * @author Dominique Launay <dominique.launay AT cru.fr> 9 * @author Olivier Salaun <olivier.salaun AT cru.fr> 10 * @author Yoann Lecuyer <yoann.lecuyer AT cru.fr> 11 * @author Etienne Meleard <etienne.meleard AT renater.fr> 12 **/ 13 14class auth_plugin_genericsso extends DokuWiki_Auth_Plugin { 15 private $users = array(); 16 17 public function __construct() { 18 parent::__construct(); 19 20 $this->loadConfig(); 21 22 $this->cando['external'] = true; 23 $this->cando['logout'] = true; 24 $this->success = false; 25 26 // check if the server configuration has correctly been done 27 $missing_conf = array(); 28 foreach(array('emailAttribute', 'loginURL', 'logoutURL') as $k) 29 if(!array_key_exists($k, $this->conf) || !$this->conf[$k]) 30 $missing_conf[] = $k; 31 32 if($missing_conf) { 33 msg('Your genericsso configuration is not fully set, missing parameters : '.implode(', ', $missing_conf), -1, '', '', MSG_ADMINS_ONLY); 34 return; 35 } 36 37 if(!array_key_exists('alwaysCheck', $this->conf)) 38 $this->conf['alwaysCheck'] = false; 39 40 $this->success = true; 41 } 42 43 // Required 44 public function checkPass($user, $pass) {} 45 46 /** 47 * Return user info 48 **/ 49 public function getUserData($user) { 50 if(is_null($this->users)) $this->loadUsers(); 51 if(array_key_exists($user, $this->users)) return $this->users[$user]; // Cache 52 $this->users[$user] = array('name' => $user, 'mail' => $user, 'grps' => array()); 53 return $this->users[$user]; 54 } 55 56 /** 57 * Do all authentication 58 * @param string $user Username 59 * @param string $pass Cleartext Password 60 * @param bool $sticky Cookie should not expire 61 * @return bool true on successful auth 62 */ 63 public function trustExternal($user, $pass, $sticky=false) { 64 global $USERINFO; 65 global $ACT; 66 global $conf; 67 68 $do = array_key_exists('do', $_REQUEST) ? $_REQUEST['do'] : null; 69 $user = $this->getSSOEMail(); 70 71 //Got a session already ? 72 if($this->hasSession()) { 73 if($this->conf['alwaysCheck'] && !$user) { 74 auth_logoff(); 75 return false; 76 } 77 if($do == 'logout') $this->logOff(false); // Logout request ? 78 return true; 79 }else{ // No session, do the stuff 80 if($user) { 81 if($do == 'logout') $this->logOff(false); // Logout request ? 82 83 $data = $this->getUserData($user); 84 $this->setSession($user, $data['grps'], $data['mail'], $data['name']); 85 error_log('genericsso : authenticated user'); 86 return true; 87 }else{ 88 if($do == 'login') $this->logIn(); 89 //error_log('genericsso : no email address to log in'); 90 auth_logoff(); 91 return false; 92 } 93 } 94 } 95 96 private function hasSession() { 97 if(is_null($_SESSION[DOKU_COOKIE])) return false; 98 if(!array_key_exists('auth', $_SESSION[DOKU_COOKIE]) || !$_SESSION[DOKU_COOKIE]['auth']) return false; 99 if(!array_key_exists('user', $_SESSION[DOKU_COOKIE]['auth']) || !$_SESSION[DOKU_COOKIE]['auth']['user']) return false; 100 global $USERINFO; 101 $USERINFO = $_SESSION[DOKU_COOKIE]['auth']['info']; 102 $_SERVER['REMOTE_USER'] = $_SESSION[DOKU_COOKIE]['auth']['user']; 103 return true; 104 } 105 106 // Create user session 107 private function setSession($user, $grps = null, $mail = null, $name = null) { 108 global $USERINFO; 109 $USERINFO['name'] = $name ? $name : $user; 110 $USERINFO['mail'] = $mail ? $mail : (mail_isvalid($user) ? $user : null); 111 $USERINFO['grps'] = is_array($grps) ? $grps : array(); 112 $_SESSION[DOKU_COOKIE]['auth']['user'] = $user; 113 $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 114 $_SERVER['REMOTE_USER'] = $user; 115 return $_SESSION[DOKU_COOKIE]; 116 } 117 118 // Get EMail from Shib env 119 private function getSSOEMail() { 120 if(!array_key_exists($this->conf['emailAttribute'], $_SERVER)) return null; 121 $mail = $_SERVER[$this->conf['emailAttribute']]; 122 if(!$mail || !mail_isvalid($mail)) return null; 123 return $mail; 124 } 125 126 // Redirect for login 127 public function logIn() { 128 error_log('genericsso : redirect user for login to '.$this->conf['loginURL']); 129 header('Location: '.str_replace('{target}', wl(getId()), $this->conf['loginURL'])); 130 exit; 131 } 132 133 // Redirect for logout 134 public function logOff($ignore = true) { 135 if($ignore) return; 136 auth_logoff(); 137 error_log('genericsso : authenticated user redirected for logout to '.$this->conf['logoutURL']); 138 header('Location: '.str_replace('{target}', $_SERVER['HTTP_REFERER'], $this->conf['logoutURL'])); 139 exit; 140 } 141 142 /** 143 * Load local user data 144 */ 145 private function loadUsers(){ 146 $this->users = array(); 147 if(!@file_exists(DOKU_CONF.'users.auth.php')) return; 148 foreach(file(DOKU_CONF.'users.auth.php') as $line){ 149 $line = trim(preg_replace('/#.*$/', '', $line)); //ignore comments 150 if(!$line) continue; 151 $row = split(':', $line,5); 152 $this->users[$row[0]] = array( 153 'pass' => $row[1], 154 'name' => urldecode($row[2]), 155 'mail' => $row[3], 156 'grps' => split(',', $row[4]) 157 ); 158 } 159 } 160} 161