1<?php 2/** 3 * Login/Logout logging plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <gohr@cosmocode.de> 7 */ 8 9class action_plugin_loglog extends DokuWiki_Action_Plugin 10{ 11 /** 12 * @var \helper_plugin_loglog_logging 13 */ 14 protected $logHelper; 15 16 /** 17 * @var \helper_plugin_loglog_main 18 */ 19 protected $mainHelper; 20 21 /** 22 * @var \helper_plugin_loglog_alert 23 */ 24 protected $alertHelper; 25 26 public function __construct() 27 { 28 $this->mainHelper = $this->loadHelper('loglog_main'); 29 $this->logHelper = $this->loadHelper('loglog_logging'); 30 $this->alertHelper = $this->loadHelper('loglog_alert'); 31 } 32 33 /** @inheritDoc */ 34 function register(Doku_Event_Handler $controller) 35 { 36 // tasks to perform on login/logoff 37 $controller->register_hook( 38 'ACTION_ACT_PREPROCESS', 39 'BEFORE', 40 $this, 41 'handleAuth' 42 ); 43 44 // allow other plugins to emit logging events 45 $controller->register_hook( 46 'PLUGIN_LOGLOG_LOG', 47 'BEFORE', 48 $this, 49 'handleCustom' 50 ); 51 52 // autologout plugin 53 $controller->register_hook( 54 'ACTION_AUTH_AUTOLOGOUT', 55 'BEFORE', 56 $this, 57 'handleAutologout' 58 ); 59 60 // log admin access 61 $controller->register_hook( 62 'ACTION_ACT_PREPROCESS', 63 'BEFORE', 64 $this, 65 'handleAdminAccess' 66 ); 67 68 // log user modifications 69 $controller->register_hook( 70 'AUTH_USER_CHANGE', 71 'BEFORE', 72 $this, 73 'handleUsermod' 74 ); 75 76 // log admin actions triggered via Ajax 77 $controller->register_hook( 78 'AJAX_CALL_UNKNOWN', 79 'AFTER', 80 $this, 81 'handleAjax' 82 ); 83 84 // log other admin actions 85 $controller->register_hook( 86 'DOKUWIKI_STARTED', 87 'AFTER', 88 $this, 89 'handleOther' 90 ); 91 92 // log other admin actions 93 $controller->register_hook( 94 'INDEXER_TASKS_RUN', 95 'AFTER', 96 $this, 97 'handleReport' 98 ); 99 } 100 101 /** 102 * Log login/logoff actions and optionally trigger alerts 103 * if configured thresholds have just been exceeded 104 * 105 * @param $msg 106 * @param null|string $user 107 */ 108 protected function logAuth($msg, $user = null) 109 { 110 $this->logHelper->writeLine($msg, $user); 111 112 // trigger alert notifications if necessary 113 $this->alertHelper->checkAlertThresholds(); 114 } 115 116 /** 117 * Log usage of admin tools 118 * 119 * @param array $data 120 * @param string $more 121 */ 122 protected function logAdmin(array $data = [], $more = '') 123 { 124 global $INPUT; 125 $msg = 'admin'; 126 $page = $INPUT->str('page'); 127 if ($page) $msg .= " - $page"; 128 if ($more && $more !== $page) $msg .= " - $more"; 129 $this->logHelper->writeLine($msg,null, $data); 130 } 131 132 /** 133 * Handle custom logging events 134 * 135 * @param Doku_Event $event 136 * @param mixed $param data passed to the event handler 137 */ 138 public function handleCustom(Doku_Event $event, $param) 139 { 140 if (isset($event->data['message'])) { 141 $log = $event->data['message']; 142 } else { 143 return; 144 } 145 if (isset($event->data['user'])) { 146 $user = $event->data['user']; 147 } else { 148 $user = null; 149 } 150 151 $this->logHelper->writeLine($log, $user); 152 } 153 154 /** 155 * Handle autologoffs by the autologout plugin 156 * 157 * @param Doku_Event $event 158 * @param mixed $param data passed to the event handler 159 */ 160 public function handleAutologout(Doku_Event $event, $param) 161 { 162 $this->logAuth('has been automatically logged off'); 163 } 164 165 /** 166 * catch standard logins/logouts, check if any alert notifications should be sent 167 * 168 * @param Doku_Event $event 169 * @param mixed $param data passed to the event handler 170 */ 171 public function handleAuth(Doku_Event $event, $param) 172 { 173 // log authentication events 174 $act = act_clean($event->data); 175 if ($act == 'logout') { 176 $this->logAuth('logged off'); 177 } elseif (!empty($_SERVER['REMOTE_USER']) && $act == 'login') { 178 if (isset($_REQUEST['r'])) { 179 $this->logAuth('logged in permanently'); 180 } else { 181 $this->logAuth('logged in temporarily'); 182 } 183 } elseif ($_REQUEST['u'] && empty($_REQUEST['http_credentials']) && empty($_SERVER['REMOTE_USER'])) { 184 $this->logAuth('failed login attempt'); 185 } 186 } 187 188 /** 189 * Log access to admin pages 190 * 191 * @param Doku_Event $event 192 */ 193 public function handleAdminAccess(Doku_Event $event) 194 { 195 global $ACT; 196 if ($ACT === 'admin') { 197 $this->logAdmin(); 198 } 199 } 200 201 /** 202 * Log user modifications 203 * 204 * @param Doku_Event $event 205 */ 206 public function handleUsermod(Doku_Event $event) 207 { 208 $modType = $event->data['type']; 209 $modUser = $event->data['params'][0]; 210 if (is_array($modUser)) $modUser = implode(', ', $modUser); 211 212 // check if admin or user are modifying the data 213 global $ACT; 214 if ($ACT === 'profile') { 215 $this->logHelper->writeLine('user profile',null, [$modType . ' user', $modUser]); 216 } else { 217 $this->logAdmin([$modType . ' user', $modUser]); 218 } 219 } 220 221 /** 222 * Catch admin actions performed via Ajax 223 * 224 * @param Doku_Event $event 225 */ 226 public function handleAjax(Doku_Event $event) 227 { 228 global $INPUT; 229 230 // extension manager 231 if ($event->data === 'plugin_extension') { 232 $this->logAdmin([$INPUT->str('act') . ' ' . $INPUT->str('ext')], 'extension'); 233 } 234 } 235 236 /** 237 * Log activity in select core admin modules 238 * 239 * @param \Doku_Event $event 240 */ 241 public function handleOther(\Doku_Event $event) 242 { 243 global $INPUT; 244 245 // configuration manager 246 if ($INPUT->str('page') === 'config' 247 && $INPUT->bool('save') === true 248 && !empty($INPUT->arr('config')) 249 ) { 250 $this->logAdmin(['save config']); 251 } 252 253 // extension manager 254 if ($INPUT->str('page') === 'extension') { 255 if ($INPUT->post->has('fn')) { 256 $actions = $INPUT->post->arr('fn'); 257 foreach ($actions as $action => $extensions) { 258 foreach ($extensions as $extname => $label) { 259 $this->logAdmin([$action, $extname]); 260 } 261 } 262 } elseif ($INPUT->post->str('installurl')) { 263 $this->logAdmin(['installurl', $INPUT->post->str('installurl')]); 264 } elseif (isset($_FILES['installfile'])) { 265 $this->logAdmin(['installfile', $_FILES['installfile']['name']]); 266 } 267 } 268 269 // ACL manager 270 if ($INPUT->str('page') === 'acl' && $INPUT->has('cmd')) { 271 $cmd = $INPUT->extract('cmd')->str('cmd'); 272 $del = $INPUT->arr('del'); 273 if ($cmd === 'update' && !empty($del)) { 274 $cmd = 'delete'; 275 $rule = $del; 276 } else { 277 $rule = [ 278 'ns' => $INPUT->str('ns'), 279 'acl_t' => $INPUT->str('acl_t'), 280 'acl_w' => $INPUT->str('acl_w'), 281 'acl' => $INPUT->str('acl') 282 ]; 283 } 284 285 $this->logAdmin([$cmd, $rule]); 286 } 287 } 288 289 /** 290 * Handle monthly usage reports 291 * 292 * @param Doku_Event $event 293 */ 294 public function handleReport(Doku_Event $event) 295 { 296 $reportHelper = new helper_plugin_loglog_report(); 297 $reportHelper->handleReport(); 298 } 299} 300 301