Code

Updated password expiration handling
authorhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Tue, 6 Jul 2010 12:22:31 +0000 (12:22 +0000)
committerhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Tue, 6 Jul 2010 12:22:31 +0000 (12:22 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@18940 594d385d-05f5-0310-b6e9-bd551577e9d8

gosa-core/html/index.php
gosa-core/html/main.php
gosa-core/ihtml/themes/default/framework.tpl
gosa-core/include/functions.inc
gosa-core/plugins/personal/myaccount/changed.tpl [new file with mode: 0644]
gosa-core/plugins/personal/myaccount/nochange.tpl [new file with mode: 0644]
gosa-core/plugins/personal/password/class_password.inc
gosa-core/plugins/personal/password/nochange.tpl
gosa-core/plugins/personal/password/password.tpl

index f8a84e87681c7fcb251b70f75773fe085504d779..4f017779bc9e5484dfce953474840da24328e8a6 100644 (file)
@@ -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&amp;reset=1");
-                            exit;
-                        }
-                    }
+                    displayLogin();
+                    exit();
                 }
             }
 
index a801af37847b7076dd8080b65cd53aac11409833..4b7baf12c56de24d68ed1ae6fbc06a129915d058 100644 (file)
@@ -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 ="";
index 835591644b79917c7f8251da5084d9fd3b8cbb9f..fd87bcead395f220d40d65b34ca12a939105fa0f 100644 (file)
     </ul>
    </div>
    <form action='main.php{$plug}' id='mainform' name='mainform' method='post' enctype='multipart/form-data'>
-   {$menu}
-   {$msg_dialogs}
-   <div class='plugin-area'>
-     {$pathMenu}
-     {$contents}
-   </div>
+
+   {if $hideMenus}
+
+    {$contents}
+
+   {else}
+
+    {$menu}
+    {$msg_dialogs}
+    <div class='plugin-area'>
+      {$pathMenu}
+      {$contents}
+    </div>
+   {/if}
 
    {if $channel != ""}
    <input type="hidden" name="_channel_" value="{$channel}">
index aa2ef6467cf3ab27035e8656fb3f038519149dbf..8a20988b069a7da01f1a5903b477152f9cca4a18 100644 (file)
@@ -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 (file)
index 0000000..b01866f
--- /dev/null
@@ -0,0 +1,13 @@
+
+<p>
+ <b>{t}You've successfully changed your password. Remember to change all programms configured to use it as well.{/t}</b>
+</p>
+
+<br>
+
+<hr>
+<div class="plugin-actions">
+  <button type='submit' name='password_changed'>{msgPool type=backButton}</button>
+</div>
+
+<input type="hidden" name="ignore">
diff --git a/gosa-core/plugins/personal/myaccount/nochange.tpl b/gosa-core/plugins/personal/myaccount/nochange.tpl
new file mode 100644 (file)
index 0000000..49fa315
--- /dev/null
@@ -0,0 +1,14 @@
+<p>
+ <b>{t}You have no permission to change your password at this time{/t}</b>
+</p>
+<p>
+ {t}Your password hash method will not be changed!{/t}
+</p>
+
+<br>
+
+<hr>
+<div class="plugin-actions">
+  <button type='submit' name='password_back'>{msgPool type=backButton}</button>
+</div>
+<input type="hidden" name="ignore">
index d72adf268c09c9c883c23e7b3fc783da1d502ff6..2aa7e0eaaf87487d2a16b15d078a690f503129e4 100644 (file)
@@ -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)));
             }
         }
index 6ba35f5bee17fa146edaddbbc7ccb7c7cf988fa4..fd77908ef4b33fffd599c7b8a144bf1394aea5dd 100644 (file)
@@ -1,12 +1,11 @@
-<div class="plugtop">
-  {image path="images/error.png"}{t}Password change not allowed{/t}
-
-</div>
-
 <p>
  <b>{t}You have no permission to change your password at this time{/t}</b>
 </p>
 
 <br>
 
+<hr>
+<div class="plugin-actions">
+  <button type='submit' name='password_back'>{msgPool type=backButton}</button>
+</div>
 <input type="hidden" name="ignore">
index 2e53c9a3fe4a594ce0b393d65106cf7d62ce1216..35e189643012cdc1e6e3bcf2c4281346bfc08971 100644 (file)
@@ -6,6 +6,12 @@
 
 <hr>
 
+{if $passwordExpired}
+    <b><font color='red'>{t}Your Password has expired. Please choose a new password.{/t}</font></b>
+<hr>
+{/if}
+
+
 {if !$proposalEnabled}
   <table cellpadding=4 border=0 summary="{t}Password change dialog{/t}">
     <tr>