Code

Fixed proposal pre-selection
[gosa.git] / gosa-core / include / functions.inc
index cf03a6ae5457419fe0186b3b7f8496ad08a13062..8307b6e63ee5c6996ef2a3821aad4484ccd1dec5 100644 (file)
@@ -2346,11 +2346,7 @@ function clean_smarty_compile_dir($directory)
               msg_dialog::display(_("Internal error"), sprintf(_("File %s cannot be deleted!"), bold($directory."/".$file)), ERROR_DIALOG);
               // This should never be reached
             }
-          } elseif(is_dir($directory."/".$file) &&
-              is_writable($directory."/".$file)) {
-            // Just recursively delete it
-            rmdirRecursive($directory."/".$file);
-          }
+          } 
         }
         // We should now create a fresh revision file
         clean_smarty_compile_dir($directory);
@@ -3001,124 +2997,146 @@ function get_correct_class_name($cls)
  *                    the prehook will then be called witch switched newPassword/oldPassword. 
  * @return  Boolean  TRUE on success else FALSE.
  */
-function change_password ($dn, $password, $mode=FALSE, $hash= "", $old_password = "")
+function change_password ($dn, $password, $mode=FALSE, $hash= "", $old_password = "", &$message = "")
 {
     global $config;
     $newpass= "";
+
+    // Not sure, why this is here, but maybe some encryption methods require it.
     mt_srand((double) microtime()*1000000);
 
     // Get a list of all available password encryption methods.
     $methods = new passwordMethod(session::get('config'),$dn);
     $available = $methods->get_available_methods();
 
-    // Fetch the current object data, to be able to detect the current hashinf method
-    //  and to be able to rollback changes once an error occured.
+    // Fetch the current object data, to be able to detect the current hashing method
+    //  and to be able to rollback changes once has an error occured.
     $ldap = $config->get_ldap_link();
     $ldap->cat ($dn, array("shadowLastChange", "userPassword","sambaNTPassword","sambaLMPassword", "uid"));
     $attrs = $ldap->fetch ();
     $initialAttrs = $attrs;
 
-    // If no hashing method is enforced, then detect if we've currently used a 
-    //  clear-text password for this object.
-    // If it isn't, then let the password methods detect the hashing algorithm.
+    // If no hashing method is enforced, then detect what method we've to use.
     $hash = strtolower($hash);
     if(empty($hash)){
+
+        // Do we need clear-text password for this object?
         if(isset($attrs['userPassword'][0]) && !preg_match ("/^{([^}]+)}(.+)/", $attrs['userPassword'][0])){
             $hash = "clear";
             $test = new $available[$hash]($config,$dn);
             $test->set_hash($hash);
         }
 
-        // If we've still no valid hashing method detected, then try to extract if from the current password hash.
-        if(isset($attrs['userPassword'][0]) && preg_match ("/^{([^}]+)}(.+)/", $attrs['userPassword'][0], $matches)){
+        // If we've still no valid hashing method detected, then try to extract if from the userPassword attribute.
+        elseif(isset($attrs['userPassword'][0]) && preg_match ("/^{([^}]+)}(.+)/", $attrs['userPassword'][0], $matches)){
             $test = passwordMethod::get_method($attrs['userPassword'][0],$dn);
+            $hash = $test->get_hash_name();
         }
+
+        // No current password was found and no hash is enforced, so we've to use the config default here.
+        $hash = $config->get_cfg_value('core','passwordDefaultHash');
+        $test = new $available[$hash]($config,$dn);
+        $test->set_hash($hash);
     }else{
         $test = new $available[$hash]($config,$dn);
         $test->set_hash($hash);
     }
 
-    if($test instanceOf passwordMethod){
-
-        stats::log('global', 'global', array('users'),  $action = 'change_password', $amount = 1, 0, $test->get_hash());
-
-        $deactivated = $test->is_locked($config,$dn);
+    // We've now a valid password-method-handle and can create the new password hash or don't we?
+    if(!$test instanceOf passwordMethod){
+        $message = _("Cannot detect password hash!");
+    }else{
 
-        /* Feed password backends with information */
-        $test->dn= $dn;
-        $test->attrs= $attrs;
+        // Feed password backends with object information. 
+        $test->dn = $dn;
+        $test->attrs = $attrs;
         $newpass= $test->generate_hash($password);
 
-        // Update shadow timestamp?
-        if (isset($attrs["shadowLastChange"][0])){
-            $shadow= (int)(date("U") / 86400);
-        } else {
-            $shadow= 0;
+        // Do we have to append samba attributes too?
+        // - sambaNTPassword / sambaLMPassword
+        $tmp = $config->get_cfg_value('core','sambaHashHook');
+        $attrs= array();
+        if (!$mode && !empty($tmp)){
+            $attrs= generate_smb_nt_hash($password);
+            $shadow = (isset($attrs["shadowLastChange"][0]))?(int)(date("U") / 86400):0;
+            if ($shadow != 0){
+                $attrs['shadowLastChange']= $shadow;
+            }
         }
 
-        // Write back modified entry
+        // Write back the new password hash 
         $ldap->cd($dn);
-        $attrs= array();
-
-        // Not for groups
-        if (!$mode){
-
-            $tmp = $config->get_cfg_value('core','sambaHashHook');
-            if(!empty($tmp)){
-
-                // Create SMB Password
-                $attrs= generate_smb_nt_hash($password);
+        $attrs['userPassword']= $newpass;
 
-                if ($shadow != 0){
-                    $attrs['shadowLastChange']= $shadow;
-                }
-            }
+        // Prepare a special attribute list, which will be used for event hook calls
+        $attrsEvent = array();
+        foreach($initialAttrs as $name => $value){
+            if(!is_numeric($name))
+                $attrsEvent[$name] = escapeshellarg($value[0]);
+        }
+        $attrsEvent['dn'] = escapeshellarg($initialAttrs['dn']);
+        foreach($attrs as $name => $value){
+            $attrsEvent[$name] = escapeshellarg($value);
         }
+        $attrsEvent['current_password'] = escapeshellarg($old_password);
+        $attrsEvent['new_password'] = escapeshellarg($password);
 
-        $attrs['userPassword']= array();
-        $attrs['userPassword']= $newpass;
+        // Call the premodify hook now
+        $passwordPlugin = new password($config,$dn);
+        plugin::callHook($passwordPlugin, 'PREMODIFY', $attrsEvent, $output,$retCode,$error, $directlyPrintError = FALSE);
+        if($retCode === 0 && count($output)){
+            $message = sprintf(_("Pre-event hook reported a problem: %s. Password change canceled!"),implode($output));
+            return(FALSE);
+        }
 
+        // Perform ldap operations
         $ldap->modify($attrs);
 
-        /* Read ! if user was deactivated */
+        // Check if the object was locked before, if it was, lock it again!
+        $deactivated = $test->is_locked($config,$dn);
         if($deactivated){
             $test->lock_account($config,$dn);
         }
 
-        new log("modify","users/passwordMethod",$dn,array_keys($attrs),$ldap->get_error());
-
-        $passwordPlugin = new password($config,$dn);
-
-
-        // Try to write changes to the ldap
+        // Check if everything went fine and then call the post event hooks.
+        // If an error occures, then try to rollback the complete actions done.
         $preRollback = FALSE;
         $ldapRollback = FALSE;
         $success = TRUE;
         if (!$ldap->success()) {
-            msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD, ERROR_DIALOG));
-            $preRollback = TRUE;
+            new log("modify","users/passwordMethod",$dn,array(),"Password change - ldap modifications! - FAILED");
             $success =FALSE;
+            $message = msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD);
+            $preRollback  =TRUE;
         } else {
 
             // Now call the passwordMethod change mechanism.
             if(!$test->set_password($password)){
-                $preRollback = TRUE;
+                $ldapRollback = TRUE;
+                $preRollback  =TRUE;
                 $success = FALSE;
+                new log("modify","users/passwordMethod",$dn,array(),"Password change - set_password! - FAILED");
+                $message = _("Password change failed!");
             }else{
         
                 // Execute the password hook
-                plugin::callHook($passwordPlugin, 'PREMODIFY', $attrs, $output,$retCode,$error, $directlyPrintError = FALSE);
-                if($retCode === 0 && count($output)){
-                    $attrs = array();
-                    $attrs['userPassword'] = escapeshellarg($password);
-                    $attrs['current_password'] = escapeshellarg($password);
-                    $attrs['old_password'] = escapeshellarg($old_password);
-                    $message = sprintf(_("Pre-event hook reported a problem: %s. Password change canceled!"),implode($output));
-                    msg_dialog::displayChecks(array($message));
+                plugin::callHook($passwordPlugin, 'POSTMODIFY', $attrsEvent, $output,$retCode,$error, $directlyPrintError = FALSE);
+                if($retCode === 0){
+                    if(count($output)){
+                        new log("modify","users/passwordMethod",$dn,array(),"Password change - Post modify hook reported! - FAILED!");
+                        $message = sprintf(_("Post-event hook reported a problem: %s. Password change canceled!"),implode($output));
+                        $ldapRollback = TRUE;
+                        $preRollback = TRUE;
+                        $success = FALSE;
+                    }else{
+                        #new log("modify","users/passwordMethod",$dn,array(),"Password change - successfull!");
+                    }
                 }else{
-                    $preRollback = TRUE;
                     $ldapRollback = TRUE;
+                    $preRollback = TRUE;
                     $success = FALSE;
+                    new log("modify","users/passwordMethod",$dn,array(),"Password change - postmodify hook execution! - FAILED");
+                    new log("modify","users/passwordMethod",$dn,array(),$error);
 
                     // Call password method again and send in old password to 
                     //  keep the database consistency
@@ -3127,35 +3145,50 @@ function change_password ($dn, $password, $mode=FALSE, $hash= "", $old_password
             }
         }
 
-        // Setting password in the ldap database or further operation failed, we should now execute 
-        //  the plugins pre-event hook, using switched passwords new/old password.
+        // Setting the password in the ldap database or further operation failed, we should now execute 
+        //  the plugins pre-event hook, using switched passwords, new/old password.
         // This ensures that passwords which were set outside of GOsa, will be reset to its 
         //  starting value.
-        if($preRollback && !empty($old_password)){
-            $attrs = array();
-            $attrs['current_password'] = escapeshellarg($password);
-            $attrs['new_password'] = escapeshellarg($old_password);
-            plugin::callHook($passwordPlugin, 'PREMODIFY', $attrs, $output,$retCode,$error, $directlyPrintError = FALSE);
+        if($preRollback){
+            new log("modify","users/passwordMethod",$dn,array(),"Rolling back premodify hook!");
+            $oldpass= $test->generate_hash($old_password);
+            $attrsEvent['current_password'] = escapeshellarg($password);
+            $attrsEvent['new_password'] = escapeshellarg($old_password);
+            foreach(array("userPassword","sambaNTPassword","sambaLMPassword") as $attr){
+                if(isset($initialAttrs[$attr][0])) $attrsEvent[$attr] = $initialAttrs[$attr][0];
+            }
+            
+            plugin::callHook($passwordPlugin, 'PREMODIFY', $attrsEvent, $output,$retCode,$error, $directlyPrintError = FALSE);
             if($retCode === 0 && count($output)){
                 $message = sprintf(_("Pre-event hook reported a problem: %s. Password change canceled!"),implode($output));
-                msg_dialog::displayChecks(array($message));
+                new log("modify","users/passwordMethod",$dn,array(),"Rolling back premodify hook! - FAILED!");
             }
         }
         
         // We've written the password to the ldap database, but executing the postmodify hook failed.
         // Now, we've to rollback all password related ldap operations.
         if($ldapRollback){
+            new log("modify","users/passwordMethod",$dn,array(),"Rolling back ldap modifications!");
             $attrs = array();
             foreach(array("userPassword","sambaNTPassword","sambaLMPassword") as $attr){
-                $attrs[$attr] = $initialAttrs[$attr][0];
+                if(isset($initialAttrs[$attr][0])) $attrs[$attr] = $initialAttrs[$attr][0];
             }
             $ldap->cd($dn);
             $ldap->modify($attrs);
             if(!$ldap->success()){
-                msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD, ERROR_DIALOG));
+                $message = msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD);
+                new log("modify","users/passwordMethod",$dn,array(),"Rolling back ldap modifications! - FAILED");
             }
         }
 
+        // Log action.
+        if($success){
+            stats::log('global', 'global', array('users'),  $action = 'change_password', $amount = 1, 0, $test->get_hash());
+            new log("modify","users/passwordMethod",$dn,array(),"Password change - successfull!");
+        }else{
+            new log("modify","users/passwordMethod",$dn,array(),"Password change - FAILED!");
+        }
+
         return($success);
     }
 }