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