*/ /** * Copyright (C) 2012 Iain Hallam, Andreas Gohr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // must be run within DokuWiki if(!defined('DOKU_INC')) die(); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'action.php'); class action_plugin_ssocas extends DokuWiki_Action_Plugin { function getInfo() { return array ( 'author' => 'Iain Hallam', 'email' => 'iain@nineworlds.net', 'date' => '2012-06-16', 'name' => 'SSO CAS Plugin', 'desc' => 'Authenticate DokuWiki users via CAS', 'url' => 'http://www.dokuwiki.org/plugin:ssocas', ); } function register (&$controller) { if ($this->getConf('server') != '') { $controller->register_hook ('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handle_login_form'); $controller->register_hook ('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action'); $controller->register_hook ('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'handle_template'); } } function _self () { global $ID; return wl($ID, '', true, ''); } function _selfdo ($do) { global $ID; return wl($ID, 'do=' . $do, true, '&'); } function _redirect ($url) { header ('Location: ' . $url); exit; } // Log function copied from Andreas Gohr's loglog plugin function _log ($msg) { global $conf; $t = time(); $log = $t."\t".strftime($conf['dformat'],$t)."\t".$_SERVER['REMOTE_ADDR']."\t".$_SERVER['REMOTE_USER']."\t".$msg; io_saveFile($conf['cachedir'].'/ssocas.log',"$log\n",true); } function handle_login_form (&$event, $param) { global $auth; global $conf; global $lang; global $ID; // Remove the register and resendpwd links, if they exist. for ($formPosition = 0; $formPosition < count($event->data->_content); $formPosition++) { $formElement = $event->data->getElementAt($formPosition); if ((! is_array($formElement)) and (substr($formElement, 0, 2) == 'data->replaceElement ($formPosition, NULL); } } $insertElement = 5; if($auth && $auth->canDo('addUser') && actionOK('register')){ $event->data->insertElement($insertElement,'

'.$lang['reghere'].': '.$lang['register'].'

'); $insertElement = 6; } if ($auth && $auth->canDo('modPass') && actionOK('resendpwd')) { $event->data->insertElement($insertElement,'

'.$lang['pwdforget'].': '.$lang['btn_resendpwd'].'

'); } if ($this->getConf('logourl') != '') { $caslogo = ' '; } else { $caslogo = ''; } $event->data->insertElement(0,'
'.$this->getConf('name').''); $event->data->insertElement(1,'

'.$caslogo.'Login

'); $event->data->insertElement(2,'
'); if ($this->getConf('jshidelocal')) { $event->data->insertElement(3,'

Only use this if you cannot use the '.$this->getConf('name').' above.

'); $event->data->replaceElement(4,'
'.$this->getConf('localname').''); } else { $event->data->replaceElement(3,'
'.$this->getConf('localname').''); } } function handle_caslogin () { global $ACT, $auth, $conf, $INFO, $USERINFO; $cas_auth_client = phpCAS::forceAuthentication(); if ($cas_auth_client) { // Successful $casuser = phpCAS::getUser(); if ($this->getConf('logging')) {$this->_log('user '.$casuser.' successfully authenticated');} $USERINFO = $auth->getUserData($casuser); if (empty($USERINFO)) { // Logged in, but no valid account if ($this->getConf('logging')) {$this->_log('user '.$casuser.' has no local account');} $ACT = act_permcheck('show'); msg ('Sorry; your login to '.$this->getConf('name').' succeeded but you don\'t have a valid account here.',-1); } else { // Populate the session variables $_SERVER['REMOTE_USER'] = $casuser; if ($this->getConf('stickysession')) { $stickysession = true; } else { $stickysession = false; } auth_setCookie($casuser,'CAS',$stickysession); // Authentication info has changed: reset the page info $INFO = pageinfo(); // Now logged in, so show the page $ACT = act_permcheck('show'); // Log action if ($this->getConf('logging')) { if ($stickysession) { $this->_log('logged in permanently'); }else{ $this->_log('logged in temporarily'); } } } } else { // Failed, but this should never be reached, because the CAS server shouldn't redirect back to us without a successful login if ($this->getConf('logging')) {$this->_log('forceAuthentication failed');} $ACT = act_permcheck('show'); msg ('Sorry; your login to '.$this->getConf('name').' failed.',-1); } } function handle_caslogout () { // Check CAS authentication and whether to log out of CAS completely, and do a phpCAS::logout if so. if ((isset($_SERVER['REMOTE_USER'])) && ($_SESSION[DOKU_COOKIE]['auth']['pass'] == 'CAS')) { if (($this->getConf('caslogout')) && (phpCAS::checkAuthentication())) { phpCAS::logoutWithRedirectServiceAndUrl($this->_self(), $this->_self()); // Log action if ($this->getConf('logging')) { $this->_log('logged off'); } } } auth_logoff(); } function handle_action (&$event, $param) { global $ACT; require_once ('CAS.php'); phpCAS::client($this->getConf('version').'.0',$this->getConf('server'),(integer) $this->getConf('port'),$this->getConf('uri')); if (! ($this->getConf('servercert') or $this->getConf('servercacert'))) { // Neither Server or CA certificate is set phpCAS::setNoCasServerValidation(); } else { if ($this->getConf('servercert')) { // Server certificate is set phpCAS::setCasServerCert($this->getConf('servercert')); } if ($this->getConf('servercacert')) { // CA certificate is set phpCAS::setCasServerCACert($this->getConf('servercacert')); } } // Handle the case where the CAS session is finished but the user is still logged in to DokuWiki if (! $this->getConf('stickysession')) { if ((isset($_SERVER['REMOTE_USER'])) && ($_SESSION[DOKU_COOKIE]['auth']['pass'] == 'CAS')) { if (! phpCAS::checkAuthentication()) { // Authentication failed $event->preventDefault(); $this->handle_caslogout(); $this->_redirect($this->_self()); } } } if ($event->data == 'caslogin') { $event->preventDefault(); $this->handle_caslogin(); } if ($event->data == 'logout') { $this->handle_caslogout(); } } function handle_template (&$event, $param) { if ($event->data == 'caslogin') { $event->preventDefault(); } } }