diff --git a/lam/help/help.inc b/lam/help/help.inc index a051b145..163e1ec2 100644 --- a/lam/help/help.inc +++ b/lam/help/help.inc @@ -130,6 +130,10 @@ $helpArray = array ( "Text" => _("Every account type needs exactly one base module. This module provides a structural object class.")), "238" => array ("ext" => "FALSE", "Headline" => _("Session timeout"), "Text" => _("This is the time (in minutes) of inactivity after which a user is automatically logged off.")), + "239" => array ("ext" => "FALSE", "Headline" => _("Log level"), + "Text" => _("Please select your prefered log level. Messages with a lower level will not be logged.")), + "240" => array ("ext" => "FALSE", "Headline" => _("Log destination"), + "Text" => _("Here you can select where LAM should save its log messages. System logging will go to Syslog on Unix systems and event log on Windows. You can also select an extra file.")), "250" => array ("ext" => "FALSE", "Headline" => _("Account lists - Filters"), "Text" => _("Here you can input small filter expressions (e.g. 'value' or 'v*'). LAM will filter case-insensitive.")), // 300 - 399 diff --git a/lam/lib/config.inc b/lam/lib/config.inc index 9e837a2d..81e06f30 100644 --- a/lam/lib/config.inc +++ b/lam/lib/config.inc @@ -721,12 +721,24 @@ class CfgMain { /** Time of inactivity before session times out (minutes) */ var $sessionTimeout; - + + /** log level */ + var $logLevel; + + /** log destination ("SYSLOG":syslog, "/...":file, "NONE":none) */ + var $logDestination; + + /** list of data fields to save in config file */ + var $settings = array("password", "default", "sessionTimeout", "logLevel", "logDestination"); + /** * Loads preferences from config file */ function CfgMain() { + // set default values $this->sessionTimeout = 30; + $this->logLevel = LOG_NOTICE; + $this->logDestination = "SYSLOG"; $this->reload(); } @@ -745,17 +757,13 @@ class CfgMain { $line = trim($line); // remove spaces at the beginning and end if (($line == "")||($line[0] == "#")) continue; // ignore comments // search keywords - if (substr($line, 0, 10) == "password: ") { - $this->password = substr($line, 10, strlen($line) - 10); - continue; - } - if (substr($line, 0, 9) == "default: ") { - $this->default = substr($line, 9, strlen($line) - 9); - continue; - } - if (substr($line, 0, 16) == "sessionTimeout: ") { - $this->sessionTimeout = intval(substr($line, 16, strlen($line) - 16)); - continue; + for ($i = 0; $i < sizeof($this->settings); $i++) { + $keyword = $this->settings[$i]; + $keylen = strlen($keyword); + if (strtolower(substr($line, 0, $keylen + 2)) == strtolower($keyword . ": ")) { + $this->$keyword = substr($line, $keylen + 2, strlen($line) - $keylen - 2); + break; + } } } fclose($file); @@ -779,30 +787,28 @@ class CfgMain { } fclose($file); // generate new configuration file + $saved = array(); for ($i = 0; $i < sizeof($file_array); $i++) { - if (($file_array[$i] == "\n")||($file_array[$i][0] == "#")) continue; // ignore comments - // search for keywords - if (substr($file_array[$i], 0, 10) == "password: ") { - $file_array[$i] = "password: " . $this->password . "\n"; - $save_password = True; - continue; - } - if (substr($file_array[$i], 0, 9) == "default: ") { - $file_array[$i] = "default: " . $this->default . "\n"; - $save_default = True; - continue; - } - if (substr($file_array[$i], 0, 16) == "sessionTimeout: ") { - $file_array[$i] = "sessionTimeout: " . $this->sessionTimeout . "\n"; - $save_sessionTimeout = True; - continue; + $line = trim($file_array[$i]); + if (($line == "")||($line[0] == "#")) continue; // ignore comments and empty lines + // search keywords + for ($k = 0; $k < sizeof($this->settings); $k++) { + $keyword = $this->settings[$k]; + $keylen = strlen($keyword); + if (strtolower(substr($line, 0, $keylen + 1)) == strtolower($keyword . ":")) { + $file_array[$i] = $keyword . ": " . $this->$keyword . "\n"; + $saved[] = $keyword; // mark keyword as saved + break; + } } } } // check if we have to add new entries (e.g. if user upgraded LAM and has an old config file) - if (!$save_password == True) array_push($file_array, "\n\n# password to add/delete/rename configuration profiles\n" . "password: " . $this->password); - if (!$save_default == True) array_push($file_array, "\n\n# default profile, without \".conf\"\n" . "default: " . $this->default); - if (!$save_sessionTimeout == True) array_push($file_array, "\n\n# session timeout in minutes\n" . "sessionTimeout: " . $this->sessionTimeout); + if (!in_array("password", $saved)) array_push($file_array, "\n\n# password to add/delete/rename configuration profiles\n" . "password: " . $this->password); + if (!in_array("default", $saved)) array_push($file_array, "\n\n# default profile, without \".conf\"\n" . "default: " . $this->default); + if (!in_array("sessionTimeout", $saved)) array_push($file_array, "\n\n# session timeout in minutes\n" . "sessionTimeout: " . $this->sessionTimeout); + if (!in_array("logLevel", $saved)) array_push($file_array, "\n\n# log level\n" . "logLevel: " . $this->logLevel); + if (!in_array("logDestination", $saved)) array_push($file_array, "\n\n# log destination\n" . "logDestination: " . $this->logDestination); $file = @fopen($conffile, "w"); if ($file) { for ($i = 0; $i < sizeof($file_array); $i++) fputs($file, $file_array[$i]); @@ -813,7 +819,7 @@ class CfgMain { exit; } } - + } ?> diff --git a/lam/lib/modules.inc b/lam/lib/modules.inc index f7d962eb..d5a01033 100644 --- a/lam/lib/modules.inc +++ b/lam/lib/modules.inc @@ -41,6 +41,8 @@ include_once("baseModule.inc"); include_once("ldap.inc"); /** lamdaemon functions */ include_once("lamdaemon.inc"); +/** security functions */ +include_once("security.inc"); /** * This includes all module files. diff --git a/lam/lib/security.inc b/lam/lib/security.inc index f3a07545..77fc99cc 100644 --- a/lam/lib/security.inc +++ b/lam/lib/security.inc @@ -30,6 +30,8 @@ $Id$ /** configuration options */ include_once('config.inc'); +/** ldap connection */ +include_once('ldap.inc'); /** * Starts a session and checks the environment. @@ -98,6 +100,9 @@ function getValidUserDNs($dn) { * */ function logoffAndBackToLoginPage() { + // log message + $ldapUser = $_SESSION['ldap']->decrypt_login(); + logNewMessage(LOG_WARNING, 'Session of user ' . $ldapUser[0] . ' expired.'); // delete key and iv in cookie if (function_exists('mcrypt_create_iv')) { setcookie("Key", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 0, "/"); @@ -134,4 +139,42 @@ function logoffAndBackToLoginPage() { die(); } +/** + * Puts a new message in the log file. + * + * @param string $level log level (LOG_NOTICE, LOG_WARNING, LOG_ERR) + * @param string $message log message + */ +function logNewMessage($level, $message) { + $possibleLevels = array(LOG_NOTICE => 'NOTICE', LOG_WARNING => 'WARNING', LOG_ERR => 'ERROR'); + if (!in_array($level, array_keys($possibleLevels))) StatusMessage('ERROR', 'Invalid log level!', $level); + if (isset($_SESSION['cfgMain'])) $cfg = $_SESSION['cfgMain']; + else $cfg = new CfgMain(); + // check if logging is disabled + if ($cfg->logDestination == 'NONE') return; + // check if log level is high enough + elseif ($cfg->logLevel < $level) return; + // ok to log, build log message + $prefix = "LDAP Account Manager - " . $possibleLevels[$level] . ": "; + $message = $prefix . $message; + // Syslog logging + if ($cfg->logDestination == 'SYSLOG') { + syslog($level, $message); + } + // log to file + else { + touch($cfg->logDestination); + if (is_writable($cfg->logDestination)) { + $file = fopen($cfg->logDestination, 'a'); + if ($file) { + fwrite($file, $message . "\n"); + fclose($file); + } + } + else { + StatusMessage('ERROR', 'Unable to write to log file!', $cfg->logDestination); + } + } +} + ?> \ No newline at end of file diff --git a/lam/templates/config/mainmanage.php b/lam/templates/config/mainmanage.php index 77fcb1b8..924fbf4d 100644 --- a/lam/templates/config/mainmanage.php +++ b/lam/templates/config/mainmanage.php @@ -70,6 +70,13 @@ echo $_SESSION['header']; // check if submit button was pressed if ($_POST['submit']) { + // remove double slashes if magic quotes are on + if (get_magic_quotes_gpc() == 1) { + $postKeys = array_keys($_POST); + for ($i = 0; $i < sizeof($postKeys); $i++) { + if (is_string($_POST[$postKeys[$i]])) $_POST[$postKeys[$i]] = stripslashes($_POST[$postKeys[$i]]); + } + } $errors = array(); // set master password if (isset($_POST['masterpassword']) && ($_POST['masterpassword'] != "")) { @@ -82,6 +89,17 @@ if ($_POST['submit']) { } // set session timeout $cfg->sessionTimeout = $_POST['sessionTimeout']; + // set log level + $cfg->logLevel = $_POST['logLevel']; + // set log destination + if ($_POST['logDestination'] == "none") $cfg->logDestination = "NONE"; + elseif ($_POST['logDestination'] == "syslog") $cfg->logDestination = "SYSLOG"; + else { + if (isset($_POST['logFile']) && ($_POST['logFile'] != "") && eregi("^[a-z0-9/\\\:\\._-]+$", $_POST['logFile'])) { + $cfg->logDestination = $_POST['logFile']; + } + else $errors[] = _("The log file is empty or contains invalid characters! Valid characters are: a-z, A-Z, 0-9, /, \\, ., :, _ and -."); + } // save settings $cfg->save(); // print messages @@ -136,6 +154,97 @@ if ($_POST['submit']) {
+
+ +

+ + + + + + + + + + + + + + + + + + + + +
+ + +   + "; + echo "\"""; + echo "\n"; + ?> +
 
+ +   + "; + echo "\"""; + echo "\n"; + ?> +
+ logDestination == "NONE") $noLogChecked = true; + echo "" . _("No logging") . "\n"; + ?> +
+ logDestination == "SYSLOG") { + $syslogChecked = true; + } + echo "" . _("System logging") . "\n"; + ?> +
+ logDestination != "NONE") && ($cfg->logDestination != "SYSLOG")) { + $logFile = $cfg->logDestination; + $logFileChecked = true; + } + echo "" . _("File") . "\n"; + echo "\n"; + ?> +
+

+

diff --git a/lam/templates/login.php b/lam/templates/login.php index 90073a38..c18e31cb 100644 --- a/lam/templates/login.php +++ b/lam/templates/login.php @@ -30,6 +30,8 @@ $Id$ /** status messages */ include_once("../lib/status.inc"); +/** security functions */ +include_once("../lib/security.inc"); // check environment $criticalErrors = array(); @@ -193,7 +195,7 @@ function display_LoginPage($config_object) { @@ -289,7 +291,7 @@ function display_LoginPage($config_object) {
- +
file; } @@ -368,29 +370,31 @@ if(!empty($_POST['checklogin'])) $_SESSION['sec_session_id'] = session_id(); $_SESSION['sec_client_ip'] = $_SERVER['REMOTE_ADDR']; $_SESSION['sec_sessionTime'] = time(); + // logging + logNewMessage(LOG_NOTICE, 'User ' . $_POST['username'] . ' successfully logged in.'); // Load main frame include("./main.php"); } else { - if ($result === False) - { + if ($result === False) { $error_message = _("Cannot connect to specified LDAP server. Please try again."); + logNewMessage(LOG_ERR, 'User ' . $_POST['username'] . ' failed to log in (LDAP error: ' . ldap_err2str($result) . ').'); display_LoginPage($_SESSION['config']); // connection failed } - elseif ($result == 81) - { + elseif ($result == 81) { $error_message = _("Cannot connect to specified LDAP server. Please try again."); + logNewMessage(LOG_ERR, 'User ' . $_POST['username'] . ' failed to log in (LDAP error: ' . ldap_err2str($result) . ').'); display_LoginPage($_SESSION['config']); // connection failed } - elseif ($result == 49) - { + elseif ($result == 49) { $error_message = _("Wrong password/user name combination. Please try again."); + logNewMessage(LOG_ERR, 'User ' . $_POST['username'] . ' failed to log in (wrong password).'); display_LoginPage($_SESSION['config']); // Username/password invalid. Return to login page. } - else - { + else { $error_message = _("LDAP error, server says:") . "\n
($result) " . ldap_err2str($result); + logNewMessage(LOG_ERR, 'User ' . $_POST['username'] . ' failed to log in (LDAP error: ' . ldap_err2str($result) . ').'); display_LoginPage($_SESSION['config']); // other errors } } diff --git a/lam/templates/logout.php b/lam/templates/logout.php index e99ba527..6d173880 100644 --- a/lam/templates/logout.php +++ b/lam/templates/logout.php @@ -45,6 +45,10 @@ include_once("../lib/ldap.inc"); // start session startSecureSession(); +// log message +$ldapUser = $_SESSION['ldap']->decrypt_login(); +logNewMessage(LOG_NOTICE, 'User ' . $ldapUser[0] . ' logged off.'); + // close LDAP connection @$_SESSION["ldap"]->destroy();