From 536c44aeb0beab95096bda1890ed482297a1ee53 Mon Sep 17 00:00:00 2001 From: hickert Date: Tue, 6 Jul 2010 12:22:31 +0000 Subject: [PATCH] Updated password expiration handling git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@18940 594d385d-05f5-0310-b6e9-bd551577e9d8 --- gosa-core/html/index.php | 14 +- gosa-core/html/main.php | 44 +++- gosa-core/ihtml/themes/default/framework.tpl | 20 +- gosa-core/include/functions.inc | 203 ++++++++++-------- .../plugins/personal/myaccount/changed.tpl | 13 ++ .../plugins/personal/myaccount/nochange.tpl | 14 ++ .../personal/password/class_password.inc | 4 +- .../plugins/personal/password/nochange.tpl | 9 +- .../plugins/personal/password/password.tpl | 6 + 9 files changed, 204 insertions(+), 123 deletions(-) create mode 100644 gosa-core/plugins/personal/myaccount/changed.tpl create mode 100644 gosa-core/plugins/personal/myaccount/nochange.tpl diff --git a/gosa-core/html/index.php b/gosa-core/html/index.php index f8a84e876..4f017779b 100644 --- a/gosa-core/html/index.php +++ b/gosa-core/html/index.php @@ -355,20 +355,12 @@ if (($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['login'])) || $htacces if ($config->get_cfg_value("core","handleExpiredAccounts") == "true") { $expired= ldap_expired_account($config, $ui->dn, $ui->username); - if ($expired == 1) { + if ($expired == POSIX_ACCOUNT_EXPIRED) { $message= _("Account locked. Please contact your system administrator!"); $smarty->assign ('nextfield', 'password'); new log("security","login","",array(),"Account for user \"$username\" has expired") ; - } elseif ($expired == 3) { - $plist= new pluglist($config, $ui); - foreach ($plist->dirlist as $key => $value) { - if (preg_match("/\bpassword\b/i",$value)) { - $plug=$key; - new log("security","login","",array(),"User \"$username\" password forced to change") ; - header ("Location: main.php?plug=$plug&reset=1"); - exit; - } - } + displayLogin(); + exit(); } } diff --git a/gosa-core/html/main.php b/gosa-core/html/main.php index a801af378..4b7baf12c 100644 --- a/gosa-core/html/main.php +++ b/gosa-core/html/main.php @@ -190,6 +190,40 @@ if (session::global_is_set('plugin_dir')){ } else { $old_plugin_dir= ""; } + +// Generate menus +$plist->gen_headlines(); +$plist->gen_menu(); +$plist->genPathMenu(); + +/* check if we are using account expiration */ +$smarty->assign("hideMenus", FALSE); +if ($config->get_cfg_value("core","handleExpiredAccounts") == "true"){ + $expired= ldap_expired_account($config, $ui->dn, $ui->username); + + if ($expired == POSIX_WARN_ABOUT_EXPIRATION && !session::is_set('POSIX_WARN_ABOUT_EXPIRATION__DONE')){ + + // The users password is about to xpire soon, display a warning message. + new log("security","gosa","",array(),"password for user \"$ui->username\" is about to expire") ; + msg_dialog::display(_("Password change"), _("Your password is about to expire, please change your password!"), INFO_DIALOG); + session::set('POSIX_WARN_ABOUT_EXPIRATION__DONE', TRUE); + + } elseif ($expired == POSIX_FORCE_PASSWORD_CHANGE){ + + // The password is expired, we are now going to enforce a new one from the user. + + // Hide the GOsa menus to avoid leaving the enforced password change dialog. + $smarty->assign("hideMenus", TRUE); + $plug = (isset($_GET['plug'])) ? $_GET['plug'] : null; + + // Detect password plugin id: + $passId = array_search('password', $plist->pluginList); + if($passId !== FALSE){ + $_GET['plug'] = $passId; + } + } +} + if (isset($_GET['plug']) && $plist->plugin_access_allowed($_GET['plug'])){ $plug= validate($_GET['plug']); $plugin_dir= $plist->get_path($plug); @@ -340,16 +374,6 @@ if ($_SERVER["REQUEST_METHOD"] == "POST"){ } } -/* check if we are using account expiration */ -if ($config->get_cfg_value("core","handleExpiredAccounts") == "true"){ - $expired= ldap_expired_account($config, $ui->dn, $ui->username); - - if ($expired == 2){ - new log("security","gosa","",array(),"password for user \"$ui->username\" is about to expire") ; - msg_dialog::display(_("Password change"), _("Your password is about to expire, please change your password!"), INFO_DIALOG); - } -} - /* Load plugin */ if (is_file("$plugin_dir/main.inc")){ $display =""; diff --git a/gosa-core/ihtml/themes/default/framework.tpl b/gosa-core/ihtml/themes/default/framework.tpl index 835591644..fd87bcead 100644 --- a/gosa-core/ihtml/themes/default/framework.tpl +++ b/gosa-core/ihtml/themes/default/framework.tpl @@ -25,12 +25,20 @@
- {$menu} - {$msg_dialogs} -
- {$pathMenu} - {$contents} -
+ + {if $hideMenus} + + {$contents} + + {else} + + {$menu} + {$msg_dialogs} +
+ {$pathMenu} + {$contents} +
+ {/if} {if $channel != ""} diff --git a/gosa-core/include/functions.inc b/gosa-core/include/functions.inc index aa2ef6467..8a20988b0 100644 --- a/gosa-core/include/functions.inc +++ b/gosa-core/include/functions.inc @@ -91,6 +91,12 @@ define ("DEBUG_MAIL", 512); /*! Debug level for all about mail (mailAccounts, define ("DEBUG_FAI", 1024); // FAI (incomplete) define ("DEBUG_RPC", 2048); /*! Debug level for communication with remote procedures */ +// Define shadow states +define ("POSIX_ACCOUNT_EXPIRED", 1); +define ("POSIX_WARN_ABOUT_EXPIRATION", 2); +define ("POSIX_FORCE_PASSWORD_CHANGE", 4); +define ("POSIX_DISALLOW_PASSWORD_CHANGE", 8); + /* Rewrite german 'umlauts' and spanish 'accents' to get better results */ $REWRITE= array( "ä" => "ae", @@ -659,111 +665,128 @@ function ldap_login_user ($username, $password) } -/*! \brief Test if account is about to expire +/*! \brief Checks the posixAccount status by comparing the shadow attributes. * - * \param string 'userdn' the DN of the user - * \param string 'username' the username - * \return int Can be one of the following values: - * - 1 the account is locked - * - 2 warn the user that the password is about to expire and he should change - * his password - * - 3 force the user to change his password - * - 4 user should not be able to change his password - * */ -function ldap_expired_account($config, $userdn, $username) + * @param Object The GOsa configuration object. + * @param String The 'dn' of the user to test the account status for. + * @param String The 'uid' of the user we're going to test. + * @return Const + * POSIX_ACCOUNT_EXPIRED - If the account is expired. + * POSIX_WARN_ABOUT_EXPIRATION - If the account is going to expire. + * POSIX_FORCE_PASSWORD_CHANGE - The password has to be changed. + * POSIX_DISALLOW_PASSWORD_CHANGE - The password cannot be changed right now. + * + * + * + * shadowLastChange + * | + * |---- shadowMin ---> | <-- shadowMax -- + * | | | + * |------- shadowWarning -> | + * |-- shadowInactive --> DEACTIVATED + * | + * EXPIRED + * + */ +function ldap_expired_account($config, $userdn, $uid) { + // Skip this for the admin account, we do not want to lock him out. +# if($uid == 'admin') return(0); + $ldap= $config->get_ldap_link(); + $ldap->cd($config->current['BASE']); $ldap->cat($userdn); $attrs= $ldap->fetch(); - - /* default value no errors */ - $expired = 0; - - $sExpire = 0; - $sLastChange = 0; - $sMax = 0; - $sMin = 0; - $sInactive = 0; - $sWarning = 0; - - $current= date("U"); - - $current= floor($current /60 /60 /24); - - /* special case of the admin, should never been locked */ - /* FIXME should allow any name as user admin */ - if($username != "admin") - { + $current= floor(date("U") /60 /60 /24); - if(isset($attrs['shadowExpire'][0])){ - $sExpire= $attrs['shadowExpire'][0]; - } else { - $sExpire = 0; - } - - if(isset($attrs['shadowLastChange'][0])){ - $sLastChange= $attrs['shadowLastChange'][0]; - } else { - $sLastChange = 0; - } - - if(isset($attrs['shadowMax'][0])){ - $sMax= $attrs['shadowMax'][0]; - } else { - $smax = 0; - } + // Fetch required attributes + foreach(array('shadowExpire','shadowLastChange','shadowMax','shadowMin', + 'shadowInactive','shadowWarning') as $attr){ + $$attr = (isset($attrs[$attr][0]))? $attrs[$attr][0] : null; + } - if(isset($attrs['shadowMin'][0])){ - $sMin= $attrs['shadowMin'][0]; - } else { - $sMin = 0; - } - - if(isset($attrs['shadowInactive'][0])){ - $sInactive= $attrs['shadowInactive'][0]; - } else { - $sInactive = 0; - } - - if(isset($attrs['shadowWarning'][0])){ - $sWarning= $attrs['shadowWarning'][0]; - } else { - $sWarning = 0; - } - - /* is the account locked */ - /* shadowExpire + shadowInactive (option) */ - if($sExpire >0){ - if($current >= ($sExpire+$sInactive)){ - return(1); + + // Check if the account has expired. + // --------------------------------- + // An account is locked/expired once its expiration date has reached (shadowExpire). + // If the optional attribute (shadowInactive) is set, we've to postpone + // the account expiration by the amount of days specified in (shadowInactive). + if($shadowExpire != null && $shadowExpire >= $current){ + + // The account seems to be expired, but we've to check 'shadowInactive' additionally. + // ShadowInactive specifies an amount of days we've to reprieve the user. + // It some kind of x days' grace. + if($shadowInactive == null || $current > $shadowExpire + $shadowInactive){ + + // Finally we've detect that the account is deactivated. + return(POSIX_ACCOUNT_EXPIRED); } - } - - /* the user should be warned to change is password */ - if((($sExpire >0) && ($sWarning >0)) && ($sExpire >= $current)){ - if (($sExpire - $current) < $sWarning){ - return(2); + } + + // The users password is going to expire. + // -------------------------------------- + // We've to warn the user in the case of an expiring account. + // An account is going to expire when it reaches its expiration date (shadowExpire). + // The user has to be warned, if the days left till expiration, match the + // configured warning period (shadowWarning) + // --> shadowWarning: Warn x days before account expiration. + if($shadowExpire != null && $shadowWarning != null){ + + // Check if the account is still active and not already expired. + if($shadowExpire >= $current){ + + // Check if we've to warn the user by comparing the remaining + // number of days till expiration with the configured amount + // of days in shadowWarning. + if(($shadowExpire - $current) <= $shadowWarning){ + return(POSIX_WARN_ABOUT_EXPIRATION); + } } - } - - /* force user to change password */ - if(($sLastChange >0) && ($sMax) >0){ - if($current >= ($sLastChange+$sMax)){ - return(3); + } + + // -- I guess this is the correct detection, isn't it? + if($shadowLastChange != null && $shadowWarning != null && $shadowMax != null){ + $daysRemaining = ($shadowLastChange + $shadowMax) - $current ; + if($daysRemaining > 0 && $daysRemaining <= $shadowWarning){ + return(POSIX_WARN_ABOUT_EXPIRATION); } - } - - /* the user should not be able to change is password */ - if(($sLastChange >0) && ($sMin >0)){ - if (($sLastChange + $sMin) >= $current){ - return(4); + } + + + // Check if we've to force the user to change his password. + // -------------------------------------------------------- + // A password change is enforced when the password is older than + // the configured amount of days (shadowMax). + // The age of the current password (shadowLastChange) plus the maximum + // amount amount of days (shadowMax) has to be smaller than the + // current timestamp. + if($shadowLastChange != null && $shadowMax != null){ + + // Check if we've an outdated password. + if($current >= ($shadowLastChange + $shadowMax)){ + return(POSIX_FORCE_PASSWORD_CHANGE); } - } } - return($expired); + + + // Check if we've to freeze the users password. + // -------------------------------------------- + // Once a user has changed his password, he cannot change it again + // for a given amount of days (shadowMin). + // We should not allow to change the password within GOsa too. + if($shadowLastChange != null && $shadowMin != null){ + + // Check if we've an outdated password. + if(($shadowLastChange + $shadowMin) >= $current){ + return(POSIX_DISALLOW_PASSWORD_CHANGE); + } + } + + return(0); } + /*! \brief Add a lock for object(s) * * Adds a lock by the specified user for one ore multiple objects. diff --git a/gosa-core/plugins/personal/myaccount/changed.tpl b/gosa-core/plugins/personal/myaccount/changed.tpl new file mode 100644 index 000000000..b01866fa8 --- /dev/null +++ b/gosa-core/plugins/personal/myaccount/changed.tpl @@ -0,0 +1,13 @@ + +

+ {t}You've successfully changed your password. Remember to change all programms configured to use it as well.{/t} +

+ +
+ +
+
+ +
+ + diff --git a/gosa-core/plugins/personal/myaccount/nochange.tpl b/gosa-core/plugins/personal/myaccount/nochange.tpl new file mode 100644 index 000000000..49fa3151a --- /dev/null +++ b/gosa-core/plugins/personal/myaccount/nochange.tpl @@ -0,0 +1,14 @@ +

+ {t}You have no permission to change your password at this time{/t} +

+

+ {t}Your password hash method will not be changed!{/t} +

+ +
+ +
+
+ +
+ diff --git a/gosa-core/plugins/personal/password/class_password.inc b/gosa-core/plugins/personal/password/class_password.inc index d72adf268..2aa7e0eaa 100644 --- a/gosa-core/plugins/personal/password/class_password.inc +++ b/gosa-core/plugins/personal/password/class_password.inc @@ -70,9 +70,11 @@ class password extends plugin $smarty->assign("NotAllowed" , !preg_match("/w/i",$password_ACLS)); /* Display expiration template */ + $smarty->assign("passwordExpired", FALSE); if ($this->config->get_cfg_value("core","handleExpiredAccounts") == "true"){ $expired= ldap_expired_account($this->config, $ui->dn, $ui->username); - if($expired == 4){ + $smarty->assign("passwordExpired", $expired & POSIX_FORCE_PASSWORD_CHANGE); + if($expired == POSIX_DISALLOW_PASSWORD_CHANGE){ return($smarty->fetch(get_template_path("nochange.tpl", TRUE))); } } diff --git a/gosa-core/plugins/personal/password/nochange.tpl b/gosa-core/plugins/personal/password/nochange.tpl index 6ba35f5be..fd77908ef 100644 --- a/gosa-core/plugins/personal/password/nochange.tpl +++ b/gosa-core/plugins/personal/password/nochange.tpl @@ -1,12 +1,11 @@ -
- {image path="images/error.png"}{t}Password change not allowed{/t} - -
-

{t}You have no permission to change your password at this time{/t}


+
+
+ +
diff --git a/gosa-core/plugins/personal/password/password.tpl b/gosa-core/plugins/personal/password/password.tpl index 2e53c9a3f..35e189643 100644 --- a/gosa-core/plugins/personal/password/password.tpl +++ b/gosa-core/plugins/personal/password/password.tpl @@ -6,6 +6,12 @@
+{if $passwordExpired} + {t}Your Password has expired. Please choose a new password.{/t} +
+{/if} + + {if !$proposalEnabled} -- 2.30.2