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