1*d10b5556SXylle<?php 2*d10b5556SXylle 3*d10b5556SXylle/** 4*d10b5556SXylle * CAS authentication plugin 5*d10b5556SXylle * 6*d10b5556SXylle * @licence GPL 2 (http://www.gnu.org/licenses/gpl.html) 7*d10b5556SXylle * @author Xylle, Fabian Bircher 8*d10b5556SXylle * @version 0.0.3 9*d10b5556SXylle * 10*d10b5556SXylle */ 11*d10b5556SXylle 12*d10b5556SXylleuse dokuwiki\Extension\AuthPlugin; 13*d10b5556SXylle 14*d10b5556SXylle 15*d10b5556SXylleclass auth_plugin_authssocas extends AuthPlugin 16*d10b5556SXylle{ 17*d10b5556SXylle /** 18*d10b5556SXylle * @var array|mixed 19*d10b5556SXylle */ 20*d10b5556SXylle private array $options = array(); 21*d10b5556SXylle 22*d10b5556SXylle private ?string $logfileuser = null; 23*d10b5556SXylle 24*d10b5556SXylle public function __construct() 25*d10b5556SXylle { 26*d10b5556SXylle global $conf; 27*d10b5556SXylle parent::__construct(); 28*d10b5556SXylle require_once __DIR__ . '/vendor/autoload.php'; 29*d10b5556SXylle 30*d10b5556SXylle // Vérifie si la classe phpCAS existe 31*d10b5556SXylle if (!class_exists('phpCAS')) { 32*d10b5556SXylle msg("CAS err: phpCAS class not found.", -1); 33*d10b5556SXylle $this->success = false; 34*d10b5556SXylle return; 35*d10b5556SXylle } 36*d10b5556SXylle // Vérifie si l'extension curl existe 37*d10b5556SXylle if (!extension_loaded("curl")) { 38*d10b5556SXylle msg("CAS err: CURL php extension not found.", -1); 39*d10b5556SXylle $this->success = false; 40*d10b5556SXylle return; 41*d10b5556SXylle } 42*d10b5556SXylle // Définition des capacités de l'extension d'authentification 43*d10b5556SXylle $this->cando['external'] = true; 44*d10b5556SXylle// $this->cando['login'] = true; 45*d10b5556SXylle// $this->cando['logout'] = true; 46*d10b5556SXylle 47*d10b5556SXylle // Création d'un journal des connexions, si un fichier est défini. 48*d10b5556SXylle if ($this->getConf('logfileuser')) { 49*d10b5556SXylle $this->logfileuser = $conf['logdir'] . "/" . $this->getConf('logfileuser'); 50*d10b5556SXylle } 51*d10b5556SXylle if (!is_null($this->logfileuser) and !@is_readable($this->logfileuser)) { 52*d10b5556SXylle if (!fopen($this->logfileuser, 'a')) { 53*d10b5556SXylle msg("plainCAS: The CAS log users file could not be opened.", -1); 54*d10b5556SXylle $this->success = false; 55*d10b5556SXylle } 56*d10b5556SXylle } 57*d10b5556SXylle 58*d10b5556SXylle 59*d10b5556SXylle // Chargement des options 60*d10b5556SXylle $this->options['debug'] = $this->getConf('debug'); 61*d10b5556SXylle $this->options['group_attribut'] = $this->getConf('group_attribut'); 62*d10b5556SXylle $this->options['handlelogoutrequest'] = $this->getConf('handlelogoutrequest'); 63*d10b5556SXylle $this->options['handlelogoutrequestTrustedHosts'] = $this->getConf('handlelogoutrequestTrustedHosts'); 64*d10b5556SXylle $this->options['mail_attribut'] = $this->getConf('mail_attribut'); 65*d10b5556SXylle $this->options['name_attribut'] = $this->getConf('name_attribut'); 66*d10b5556SXylle $this->options['port'] = $this->getConf('port'); 67*d10b5556SXylle $this->options['samlValidate'] = $this->getConf('samlValidate'); 68*d10b5556SXylle $this->options['server'] = $this->getConf('server'); 69*d10b5556SXylle $this->options['rootcas'] = $this->getConf('rootcas'); 70*d10b5556SXylle $this->options['uid_attribut'] = $this->getConf('uid_attribut'); 71*d10b5556SXylle $this->options['cacert'] = $this->getConf('cacert'); 72*d10b5556SXylle 73*d10b5556SXylle $server_version = CAS_VERSION_2_0; 74*d10b5556SXylle if ($this->getOption("samlValidate")) { 75*d10b5556SXylle $server_version = SAML_VERSION_1_1; 76*d10b5556SXylle } 77*d10b5556SXylle 78*d10b5556SXylle if ($this->getOption("debug")) { 79*d10b5556SXylle phpCAS::setLogger(); 80*d10b5556SXylle phpCAS::setVerbose(true); 81*d10b5556SXylle } 82*d10b5556SXylle 83*d10b5556SXylle if (!DOKU_BASE == "/") { 84*d10b5556SXylle $service_base_url = str_replace(DOKU_BASE, "", DOKU_URL); 85*d10b5556SXylle } else { 86*d10b5556SXylle $service_base_url = DOKU_URL; 87*d10b5556SXylle } 88*d10b5556SXylle 89*d10b5556SXylle // Configuration du client CAS 90*d10b5556SXylle phpCAS::client( 91*d10b5556SXylle $server_version, 92*d10b5556SXylle $this->getOption('server'), 93*d10b5556SXylle (int)$this->getOption('port'), 94*d10b5556SXylle $this->getOption('rootcas'), 95*d10b5556SXylle $service_base_url 96*d10b5556SXylle ); 97*d10b5556SXylle 98*d10b5556SXylle if ($this->getConf('autologin')) { 99*d10b5556SXylle phpCAS::setCacheTimesForAuthRecheck(-1); 100*d10b5556SXylle } else { 101*d10b5556SXylle phpCAS::setCacheTimesForAuthRecheck(1); 102*d10b5556SXylle } 103*d10b5556SXylle 104*d10b5556SXylle // Gestion de l'autorité de certification du certificat du serveur CAS pour la bibliothèque php_curl 105*d10b5556SXylle $cas_cacert_file = DOKU_CONF . 'authssocas.cacert.pem'; 106*d10b5556SXylle if ($this->getOption('cacert')) { 107*d10b5556SXylle if (!io_saveFile($cas_cacert_file, $this->getOption('cacert'))) { 108*d10b5556SXylle msg('The ' . $cas_cacert_file . ' file is not writable. Please inform the Wiki-Admin', -1); 109*d10b5556SXylle } 110*d10b5556SXylle phpCAS::setCasServerCACert($cas_cacert_file); 111*d10b5556SXylle } else { 112*d10b5556SXylle phpCAS::setNoCasServerValidation(); 113*d10b5556SXylle } 114*d10b5556SXylle 115*d10b5556SXylle // Gestion de la déconnexion sur le serveur CAS 116*d10b5556SXylle if ($this->getOption('handlelogoutrequest')) { 117*d10b5556SXylle phpCAS::handleLogoutRequests(true, $this->getOption('handlelogoutrequestTrustedHosts')); 118*d10b5556SXylle } else { 119*d10b5556SXylle phpCAS::handleLogoutRequests(false); 120*d10b5556SXylle } 121*d10b5556SXylle } 122*d10b5556SXylle 123*d10b5556SXylle /** 124*d10b5556SXylle * 125*d10b5556SXylle * Récupère les options 126*d10b5556SXylle * Transforme en tableau les URL de notification de la déconnexion pour les serveurs CAS 127*d10b5556SXylle * 128*d10b5556SXylle * @param $optionName 129*d10b5556SXylle * @return array|mixed|string[]|null 130*d10b5556SXylle */ 131*d10b5556SXylle private function getOption($optionName) 132*d10b5556SXylle { 133*d10b5556SXylle if (isset($this->options[$optionName])) { 134*d10b5556SXylle switch ($optionName) { 135*d10b5556SXylle case 'handlelogoutrequestTrustedHosts': 136*d10b5556SXylle $arr = explode(',', $this->options[$optionName]); 137*d10b5556SXylle foreach ($arr as $key => $item) { 138*d10b5556SXylle $arr[$key] = trim($item); 139*d10b5556SXylle } 140*d10b5556SXylle return $arr; 141*d10b5556SXylle default: 142*d10b5556SXylle return $this->options[$optionName]; 143*d10b5556SXylle } 144*d10b5556SXylle } 145*d10b5556SXylle return NULL; 146*d10b5556SXylle } 147*d10b5556SXylle 148*d10b5556SXylle /** 149*d10b5556SXylle * 150*d10b5556SXylle * Transfert de la demande de connexion au serveur CAS 151*d10b5556SXylle * 152*d10b5556SXylle * @return void 153*d10b5556SXylle * @noinspection PhpUnused 154*d10b5556SXylle */ 155*d10b5556SXylle public function logIn() 156*d10b5556SXylle { 157*d10b5556SXylle global $ID; 158*d10b5556SXylle $login_url = DOKU_URL . 'doku.php?id=' . $ID; 159*d10b5556SXylle 160*d10b5556SXylle phpCAS::setFixedServiceURL($login_url); 161*d10b5556SXylle phpCAS::forceAuthentication(); 162*d10b5556SXylle } 163*d10b5556SXylle 164*d10b5556SXylle /** 165*d10b5556SXylle * 166*d10b5556SXylle * Déconnexion de l'utilisateur avec prise en compte de la déconnexion générale du CAS 167*d10b5556SXylle * 168*d10b5556SXylle * @return void 169*d10b5556SXylle */ 170*d10b5556SXylle public function logOff(): void 171*d10b5556SXylle { 172*d10b5556SXylle global $ID; 173*d10b5556SXylle 174*d10b5556SXylle @session_start(); 175*d10b5556SXylle session_destroy(); 176*d10b5556SXylle if ($this->getOption('handlelogoutrequest')) { 177*d10b5556SXylle $logout_url = DOKU_URL . 'doku.php?id=' . $ID; 178*d10b5556SXylle @phpCAS::logoutWithRedirectService($logout_url); 179*d10b5556SXylle } else { 180*d10b5556SXylle phpCAS::handleLogoutRequests(); 181*d10b5556SXylle unset($_SESSION); 182*d10b5556SXylle } 183*d10b5556SXylle } 184*d10b5556SXylle 185*d10b5556SXylle public function trustExternal($user, $pass, $sticky = false): bool 186*d10b5556SXylle { 187*d10b5556SXylle global $USERINFO; 188*d10b5556SXylle 189*d10b5556SXylle if (!empty($_SESSION[DOKU_COOKIE]['auth']['info'])) { 190*d10b5556SXylle $USERINFO['name'] = $_SESSION[DOKU_COOKIE]['auth']['info']['name']; 191*d10b5556SXylle $USERINFO['mail'] = $_SESSION[DOKU_COOKIE]['auth']['info']['mail']; 192*d10b5556SXylle $USERINFO['grps'] = $_SESSION[DOKU_COOKIE]['auth']['info']['grps']; 193*d10b5556SXylle $_SERVER['REMOTE_USER'] = $_SESSION[DOKU_COOKIE]['auth']['user']; 194*d10b5556SXylle return true; 195*d10b5556SXylle } 196*d10b5556SXylle 197*d10b5556SXylle if (phpCAS::isAuthenticated() or ($this->getOption('autologin') and phpCAS::checkAuthentication())) { 198*d10b5556SXylle 199*d10b5556SXylle $USERINFO = $this->cas_user_attributes(phpCAS::getAttributes()); 200*d10b5556SXylle $this->auth_log($USERINFO['uid']); 201*d10b5556SXylle $_SESSION[DOKU_COOKIE]['auth']['user'] = $USERINFO['uid']; 202*d10b5556SXylle $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 203*d10b5556SXylle $_SERVER['REMOTE_USER'] = $USERINFO['uid']; 204*d10b5556SXylle return true; 205*d10b5556SXylle } 206*d10b5556SXylle 207*d10b5556SXylle return false; 208*d10b5556SXylle } 209*d10b5556SXylle 210*d10b5556SXylle /** 211*d10b5556SXylle * 212*d10b5556SXylle * Renvoi les informations de l'utilisateur fournit par le CAS 213*d10b5556SXylle * 214*d10b5556SXylle * @param $attributes 215*d10b5556SXylle * @return array 216*d10b5556SXylle */ 217*d10b5556SXylle private function cas_user_attributes($attributes): array 218*d10b5556SXylle { 219*d10b5556SXylle return array( 220*d10b5556SXylle 'uid' => $attributes[$this->getOption('uid_attribut')], 221*d10b5556SXylle 'name' => $attributes[$this->getOption('name_attribut')], 222*d10b5556SXylle 'mail' => $attributes[$this->getOption('mail_attribut')], 223*d10b5556SXylle 'grps' => $attributes[$this->getOption('group_attribut')], 224*d10b5556SXylle ); 225*d10b5556SXylle } 226*d10b5556SXylle 227*d10b5556SXylle /** 228*d10b5556SXylle * 229*d10b5556SXylle * Log user connection if the log file is defined 230*d10b5556SXylle * 231*d10b5556SXylle * format : DATE|TIME|USER 232*d10b5556SXylle * 233*d10b5556SXylle * @param $user 234*d10b5556SXylle * @return void 235*d10b5556SXylle */ 236*d10b5556SXylle private function auth_log($user): void 237*d10b5556SXylle { 238*d10b5556SXylle if (!is_null($this->logfileuser)) { 239*d10b5556SXylle 240*d10b5556SXylle $date = (new DateTime('now'))->format('Ymd|H:i:s'); 241*d10b5556SXylle 242*d10b5556SXylle $userline = $date . "|" . $user . PHP_EOL; 243*d10b5556SXylle if (!io_saveFile($this->logfileuser, $userline, true)) { 244*d10b5556SXylle msg($this->getLang('writefail'), -1); 245*d10b5556SXylle } 246*d10b5556SXylle } 247*d10b5556SXylle } 248*d10b5556SXylle 249*d10b5556SXylle} 250