1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
19: $plugin_is_filter = 100 | CLASS_PLUGIN;
20: $plugin_description = gettext('Logs selected security events.');
21: $plugin_author = "Stephen Billard (sbillard)";
22:
23: $option_interface = 'security_logger';
24:
25: if (getOption('logger_log_admin')) {
26: zp_register_filter('admin_login_attempt', 'security_logger::adminLoginLogger');
27: zp_register_filter('federated_login_attempt', 'security_logger::federatedLoginLogger');
28: }
29: if (getOption('logger_log_guests')) {
30: zp_register_filter('guest_login_attempt', 'security_logger::guestLoginLogger');
31: }
32: zp_register_filter('admin_allow_access', 'security_logger::adminGate');
33: zp_register_filter('authorization_cookie', 'security_logger::adminCookie', 0);
34: zp_register_filter('admin_managed_albums_access', 'security_logger::adminAlbumGate');
35: zp_register_filter('save_user', 'security_logger::UserSave');
36: zp_register_filter('admin_XSRF_access', 'security_logger::admin_XSRF_access');
37: zp_register_filter('admin_log_actions', 'security_logger::log_action');
38: zp_register_filter('log_setup', 'security_logger::log_setup');
39: zp_register_filter('security_misc', 'security_logger::security_misc');
40:
41: 42: 43: 44:
45: class security_logger {
46:
47: 48: 49: 50: 51:
52: function __construct() {
53: global $plugin_is_filter;
54: if (OFFSET_PATH == 2) {
55: setOptionDefault('zp_plugin_security-logger', $plugin_is_filter);
56: setOptionDefault('logger_log_guests', 1);
57: setOptionDefault('logger_log_admin', 1);
58: setOptionDefault('logger_log_type', 'all');
59: setOptionDefault('logge_access_log_type', 'all_user');
60: setOptionDefault('security_log_size', 5000000);
61: }
62: }
63:
64: 65: 66: 67: 68:
69: function getOptionsSupported() {
70: return array(gettext('Record logon attempts of') => array('key' => 'logger_log_allowed', 'type' => OPTION_TYPE_CHECKBOX_ARRAY,
71: 'checkboxes' => array(gettext('Administrators') => 'logger_log_admin', gettext('Guests') => 'logger_log_guests'),
72: 'desc' => gettext('If checked login attempts will be logged.')),
73: gettext('Record failed admin access') => array('key' => 'logge_access_log_type', 'type' => OPTION_TYPE_RADIO,
74: 'buttons' => array(gettext('All attempts') => 'all', gettext('Only user attempts') => 'all_user'),
75: 'desc' => gettext('Record admin page access failures.')),
76: gettext('Record logon') => array('key' => 'logger_log_type', 'type' => OPTION_TYPE_RADIO,
77: 'buttons' => array(gettext('All attempts') => 'all', gettext('Successful attempts') => 'success', gettext('unsuccessful attempts') => 'fail'),
78: 'desc' => gettext('Record login failures, successes, or all attempts.'))
79: );
80: }
81:
82: function handleOption($option, $currentValue) {
83:
84: }
85:
86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96:
97: private static function Logger($success, $user, $name, $action, $authority, $addl = NULL) {
98: global $_zp_authority, $_zp_mutex;
99: $pattern = '~^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$~';
100: $forwardedIP = NULL;
101: $ip = sanitize($_SERVER['REMOTE_ADDR']);
102: if (!preg_match($pattern, $ip)) {
103: $ip = NULL;
104: }
105: if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
106: $forwardedIP = sanitize($_SERVER['HTTP_X_FORWARDED_FOR']);
107: if (preg_match($pattern, $forwardedIP)) {
108: $ip .= ' {' . $forwardedIP . '}';
109: }
110: }
111: $admin = $_zp_authority->getMasterUser();
112: $locale = $admin->getLanguage();
113: if (empty($locale)) {
114: $locale = 'en_US';
115: }
116: $cur_locale = getUserLocale();
117: setupCurrentLocale($locale);
118: switch ($action) {
119: case 'clear_log':
120: $type = gettext('Log reset');
121: break;
122: case 'delete_log':
123: $type = gettext('Log deleted');
124: break;
125: case 'download_log':
126: $type = gettext('Log downloaded');
127: break;
128: case 'setup_install':
129: $type = gettext('Install');
130: $addl = gettext('version') . ' ' . ZENPHOTO_VERSION . '[' . ZENPHOTO_RELEASE . "]";
131: if (!zpFunctions::hasPrimaryScripts()) {
132: $addl .= ' ' . gettext('clone');
133: }
134: break;
135: case 'setup_proptect':
136: $type = gettext('Protect setup scripts');
137: break;
138: case 'user_new':
139: $type = gettext('Request add user');
140: break;
141: case 'user_update':
142: $type = gettext('Request update user');
143: break;
144: case 'user_delete':
145: $type = gettext('Request delete user');
146: break;
147: case 'XSRF_blocked':
148: $type = gettext('Cross Site Reference');
149: break;
150: case 'blocked_album':
151: $type = gettext('Album access');
152: break;
153: case 'blocked_access':
154: $type = gettext('Admin access');
155: break;
156: case 'Front-end':
157: $type = gettext('Guest login');
158: break;
159: case 'Back-end':
160: $type = gettext('Admin login');
161: break;
162: case 'auth_cookie':
163: $type = gettext('Authorization cookie check');
164: break;
165: default:
166: $type = $action;
167: break;
168: }
169:
170: $file = SERVERPATH . '/' . DATA_FOLDER . '/security.log';
171: $max = getOption('security_log_size');
172: $_zp_mutex->lock();
173: if ($max && @filesize($file) > $max) {
174: switchLog('security');
175: }
176: $preexists = file_exists($file) && filesize($file) > 0;
177: $f = fopen($file, 'a');
178: if ($f) {
179: if (!$preexists) {
180: fwrite($f, gettext('date' . "\t" . 'requestor’s IP' . "\t" . 'type' . "\t" . 'user ID' . "\t" . 'user name' . "\t" . 'outcome' . "\t" . 'authority' . "\tadditional information\n"));
181: }
182: $message = date('Y-m-d H:i:s') . "\t";
183: $message .= $ip . "\t";
184: $message .= $type . "\t";
185: $message .= $user . "\t";
186: $message .= $name . "\t";
187: switch ($success) {
188: case 0:
189: $message .= gettext("Failed") . "\t";
190: break;
191: case 1:
192: $message .= gettext("Success") . "\t";
193: $message .= substr($authority, 0, strrpos($authority, '_auth'));
194: break;
195: case 2:
196: $message .= gettext("Blocked") . "\t";
197: break;
198: default:
199: $message .= $success . "\t";
200: }
201: if ($addl) {
202: $message .= "\t" . $addl;
203: }
204: fwrite($f, $message . "\n");
205: fclose($f);
206: clearstatcache();
207: if (!$preexists) {
208: @chmod($file, 0660 & CHMOD_VALUE);
209: if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
210: $permission = fileperms($file) & 0700;
211: $check = $permission != 0600 & CHMOD_VALUE;
212: } else {
213: $permission = fileperms($file) & 0777;
214: $check = $permission != 0660 & CHMOD_VALUE;
215: }
216: if ($check) {
217: $f = fopen($file, 'a');
218: fwrite($f, "\t\t" . gettext('Set Security log permissions') . "\t\t\t" . gettext('Failed') . "\t\t" . sprintf(gettext('File permissions of Security log are %04o'), $permission) . "\n");
219: fclose($f);
220: clearstatcache();
221: }
222: }
223: }
224: $_zp_mutex->unlock();
225: setupCurrentLocale($cur_locale);
226: }
227:
228: 229: 230:
231: private static function populate_user() {
232: global $_zp_current_admin_obj;
233: if (is_object($_zp_current_admin_obj)) {
234: $user = $_zp_current_admin_obj->getUser();
235: $name = $_zp_current_admin_obj->getName();
236: } else {
237: $user = $name = '';
238: }
239: return array($user, $name);
240: }
241:
242: 243: 244: 245: 246: 247: 248: 249: 250:
251: static function adminLoginLogger($success, $user, $pass, $auth = 'zp_admin_auth') {
252: switch (getOption('logger_log_type')) {
253: case 'all':
254: break;
255: case 'success':
256: if (!$success)
257: return false;
258: break;
259: case 'fail':
260: if ($success)
261: return true;
262: break;
263: }
264: $name = '';
265: if ($success) {
266: $admin = Zenphoto_Authority::getAnAdmin(array('`user`=' => $user, '`valid`=' => 1));
267: $pass = '';
268: if (is_object($admin)) {
269: $name = $admin->getName();
270: }
271: }
272: security_logger::Logger((int) ($success && true), $user, $name, 'Back-end', $auth, null);
273: return $success;
274: }
275:
276: 277: 278: 279: 280: 281: 282: 283: 284:
285: static function federatedLoginLogger($success, $user) {
286: return security_logger::adminLoginLogger($success, $user, 'n/a', 'federated_logon_auth');
287: }
288:
289: 290: 291: 292: 293: 294: 295: 296: 297: 298:
299: static function guestLoginLogger($success, $user, $pass, $athority) {
300: switch (getOption('logger_log_type')) {
301: case 'all':
302: break;
303: case 'success':
304: if (!$success)
305: return false;
306: break;
307: case 'fail':
308: if ($success)
309: return true;
310: break;
311: }
312: $name = '';
313: if ($success) {
314: $admin = Zenphoto_Authority::getAnAdmin(array('`user`=' => $user, '`valid`=' => 1));
315: $pass = '';
316: if (is_object($admin)) {
317: $name = $admin->getName();
318: }
319: }
320: security_logger::Logger((int) ($success && true), $user, $name, 'Front-end', $athority, null);
321: return $success;
322: }
323:
324: 325: 326: 327: 328:
329: static function adminGate($allow, $page) {
330: list($user, $name) = security_logger::populate_user();
331: switch (getOption('logger_log_type')) {
332: case 'all':
333: break;
334: case 'all_user':
335: if (!$user)
336: return $allow;
337: break;
338: }
339: security_logger::Logger(0, $user, $name, 'blocked_access', '', $page);
340: return $allow;
341: }
342:
343: static function adminCookie($allow, $auth, $id) {
344: if (!$allow && $auth) {
345: switch (getOption('logger_log_type')) {
346: case 'all':
347: case 'fail':
348: security_logger::Logger(0, NULL, NULL, 'auth_cookie', '', $id . ':' . $auth);
349: }
350: }
351: return $allow;
352: }
353:
354: 355: 356: 357: 358:
359: static function adminAlbumGate($allow, $page) {
360: list($user, $name) = security_logger::populate_user();
361: switch (getOption('logger_log_type')) {
362: case 'all':
363: break;
364: case 'all_user':
365: if (!$user)
366: return $allow;
367: break;
368: }
369: if (!$allow)
370: security_logger::Logger(2, $user, $name, 'blocked_album', '', $page);
371: return $allow;
372: }
373:
374: 375: 376: 377: 378: 379:
380: static function UserSave($discard, $userobj, $class) {
381: list($user, $name) = security_logger::populate_user();
382: security_logger::Logger(1, $user, $name, 'user_' . $class, 'zp_admin_auth', $userobj->getUser());
383: return $discard;
384: }
385:
386: 387: 388: 389: 390: 391: 392:
393: static function admin_XSRF_access($discard, $token) {
394: list($user, $name) = security_logger::populate_user();
395: security_logger::Logger(2, $user, $name, 'XSRF_blocked', '', $token);
396: return false;
397: }
398:
399: 400: 401: 402: 403: 404:
405: static function log_action($allow, $log, $action) {
406: list($user, $name) = security_logger::populate_user();
407: security_logger::Logger((int) ($allow && true), $user, $name, $action, 'zp_admin_auth', basename($log));
408: return $allow;
409: }
410:
411: 412: 413: 414: 415: 416:
417: static function log_setup($success, $action, $txt) {
418: list($user, $name) = security_logger::populate_user();
419: security_logger::Logger((int) ($success && true), $user, $name, 'setup_' . $action, 'zp_admin_auth', $txt);
420: return $success;
421: }
422:
423: 424: 425: 426: 427: 428: 429:
430: static function security_misc($success, $requestor, $auth, $txt) {
431: security_logger::Logger((int) ($success && true), NULL, NULL, $requestor, 'zp_admin_auth', $txt);
432: return $success;
433: }
434:
435: }
436:
437: ?>