diff --git a/include/password-methods/class_password-methods-crypt.inc b/include/password-methods/class_password-methods-crypt.inc
index 0e44832dd4d4cb2f3483a4801580fe5ee142b168..5b98a605c4c0d797a4c47f0baa81f07d9413637a 100644
--- a/include/password-methods/class_password-methods-crypt.inc
+++ b/include/password-methods/class_password-methods-crypt.inc
@@ -151,7 +151,7 @@ class passwordMethodCrypt extends passwordMethod
    *
    * \param string $password_hash
    */
-  static function _extract_method($classname, $password_hash)
+  static function _extract_method($password_hash)
   {
     if (!preg_match('/^{crypt}/i', $password_hash)) {
       return "";
diff --git a/include/password-methods/class_password-methods-empty.inc b/include/password-methods/class_password-methods-empty.inc
index 14f43e4e07ead6743c9dbdd448c4f144affb5135..38361352cbc71ca0bb300b677b64bb529aaf8b75 100644
--- a/include/password-methods/class_password-methods-empty.inc
+++ b/include/password-methods/class_password-methods-empty.inc
@@ -30,10 +30,12 @@
  */
 class passwordMethodEmpty extends passwordMethod
 {
-  protected $lockable = FALSE;
+  protected $lockable   = TRUE;
 
   public $hash = 'empty';
 
+  const LOCKVALUE  = '{CRYPT}!';
+
   /*!
    * \brief passwordMethodClear Constructor
    */
@@ -78,5 +80,14 @@ class passwordMethodEmpty extends passwordMethod
   {
     return FALSE;
   }
+
+  static function _extract_method($password_hash)
+  {
+    if (empty($password_hash) || ($password_hash == static::LOCKVALUE)) {
+      return static::get_hash_name();
+    }
+
+    return '';
+  }
 }
 ?>
diff --git a/include/password-methods/class_password-methods.inc b/include/password-methods/class_password-methods.inc
index 0582f523f180fd711d0f0fa8454a30abf4228a2e..342e717b7cf3d7d3c2a0f4038dbba3533c84aa12 100644
--- a/include/password-methods/class_password-methods.inc
+++ b/include/password-methods/class_password-methods.inc
@@ -147,56 +147,60 @@ class passwordMethod
       }
     }
 
-    /* We can only lock/unlock non-empty passwords */
-    if (!empty($pwd)) {
-      /* Check if this entry is already locked. */
-      if (!preg_match("/^[^\}]*+\}!/", $pwd)) {
-        if ($mode == 'UNLOCK') {
-          return TRUE;
-        }
-      } elseif ($mode == 'LOCK') {
+    /* Check if this entry is already locked. */
+    if (!preg_match("/^[^\}]*+\}!/", $pwd)) {
+      if ($mode == 'UNLOCK') {
         return TRUE;
       }
+    } elseif ($mode == 'LOCK') {
+      return TRUE;
+    }
 
-      // (Un)lock the samba account
-      $modify = lock_samba_account($mode, $attrs);
+    // (Un)lock the samba account
+    $modify = lock_samba_account($mode, $attrs);
 
-      // (Un)lock SSH keys
-      lock_ssh_account($mode, $attrs, $modify);
+    // (Un)lock SSH keys
+    lock_ssh_account($mode, $attrs, $modify);
 
-      // Call pre hooks
-      $userClass = new user($dn);
-      $errors = $userClass->callHook('PRE'.$mode, array(), $ret);
-      if (!empty($errors)) {
-        msg_dialog::displayChecks($errors);
-        return FALSE;
-      }
+    // Call pre hooks
+    $userClass = new user($dn);
+    $errors = $userClass->callHook('PRE'.$mode, array(), $ret);
+    if (!empty($errors)) {
+      msg_dialog::displayChecks($errors);
+      return FALSE;
+    }
 
-      // (Un)lock the account by modifying the password hash.
-      if ($mode == 'LOCK') {
-        /* Lock entry */
+    // (Un)lock the account by modifying the password hash.
+    if ($mode == 'LOCK') {
+      /* Lock entry */
+      if (empty($pwd)) {
+        $pwd = passwordMethodEmpty::LOCKVALUE;
+      } else {
         $pwd = preg_replace("/(^[^\}]+\})(.*$)/",   "\\1!\\2",  $pwd);
+      }
+    } else {
+      /* Unlock entry */
+      if ($pwd == passwordMethodEmpty::LOCKVALUE) {
+        $pwd = array();
       } else {
-        /* Unlock entry */
         $pwd = preg_replace("/(^[^\}]+\})!(.*$)/",  "\\1\\2",   $pwd);
       }
-      $modify['userPassword'] = $pwd;
-      $ldap->cd($dn);
-      $ldap->modify($modify);
-
-      // Call the password post-lock hook, if defined.
-      if ($ldap->success()) {
-        $userClass = new user($dn);
-        $errors = $userClass->callHook('POST'.$mode, array(), $ret);
-        if (!empty($errors)) {
-          msg_dialog::displayChecks($errors);
-        }
-      } else {
-        msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD), LDAP_ERROR);
+    }
+    $modify['userPassword'] = $pwd;
+    $ldap->cd($dn);
+    $ldap->modify($modify);
+
+    // Call the password post-lock hook, if defined.
+    if ($ldap->success()) {
+      $userClass = new user($dn);
+      $errors = $userClass->callHook('POST'.$mode, array(), $ret);
+      if (!empty($errors)) {
+        msg_dialog::displayChecks($errors);
       }
-      return $ldap->success();
+    } else {
+      msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD), LDAP_ERROR);
     }
-    return FALSE;
+    return $ldap->success();
   }
 
 
@@ -299,14 +303,15 @@ class passwordMethod
   {
     $methods = passwordMethod::get_available_methods();
 
-    if (empty($password_hash) && passwordMethodEmpty::is_available()) {
+    if (isset($methods['class']['passwordMethodEmpty']) && (passwordMethodEmpty::_extract_method($password_hash) != '')) {
+      /* Test empty method first as it gets priority */
       $method = new passwordMethodEmpty($dn);
       return $method;
     }
 
     foreach ($methods['class'] as $class) {
-      $method = $class::_extract_method($class, $password_hash);
-      if ($method != "") {
+      $method = $class::_extract_method($password_hash);
+      if ($method != '') {
         $test = new $class($dn);
         $test->set_hash($method);
         return $test;
@@ -324,9 +329,9 @@ class passwordMethod
    *
    * \param string $password_hash
    */
-  static function _extract_method($classname, $password_hash)
+  static function _extract_method($password_hash)
   {
-    $hash = $classname::get_hash_name();
+    $hash = static::get_hash_name();
     if (preg_match("/^\{$hash\}/i", $password_hash)) {
       return $hash;
     }
diff --git a/plugins/admin/users/class_userManagement.inc b/plugins/admin/users/class_userManagement.inc
index 2ad4f6b44cfadb00e9881da93643ff1ad79b155b..02ad2d1eebac3133bade6538ae17362703f4e96e 100644
--- a/plugins/admin/users/class_userManagement.inc
+++ b/plugins/admin/users/class_userManagement.inc
@@ -37,6 +37,9 @@ class LockAction extends Action
   {
     if (isset($entry['userPassword']) && preg_match('/^\{[^\}]/', $entry['userPassword'])) {
       return (preg_match('/^[^\}]*+\}!/', $entry['userPassword']) === 1);
+    } elseif ((strtolower($entry->type) == 'user') && !isset($entry['userPassword'])) {
+      /* Empty lockable password */
+      return FALSE;
     }
     return NULL;
   }
@@ -170,9 +173,6 @@ class userManagement extends management
     foreach ($allowed as $dn) {
       // We can't lock empty passwords.
       $entry = $this->listing->getEntry($dn);
-      if (!isset($entry['userPassword'])) {
-        continue;
-      }
 
       // Detect the password method and try to lock/unlock.
       $pwd      = $entry['userPassword'];
diff --git a/plugins/personal/generic/class_UserPasswordAttribute.inc b/plugins/personal/generic/class_UserPasswordAttribute.inc
index a89e924fdb4f0764b78c0d3f8d80e20d51ebdeec..5b6e3ce80586abd748abeb7cf77770af85d4bd1c 100644
--- a/plugins/personal/generic/class_UserPasswordAttribute.inc
+++ b/plugins/personal/generic/class_UserPasswordAttribute.inc
@@ -198,7 +198,7 @@ class UserPasswordAttribute extends CompositeAttribute
     if ($this->plugin->is_template && ($values[0] == '%askme%')) {
       return '%askme%';
     }
-    if (!$this->plugin->is_template && $this->needPassword[$values[0]] && ($values[1] == '')) {
+    if (!$this->plugin->is_template && ($this->needPassword[$values[0]] || ($values[0] == 'empty')) && ($values[1] == '')) {
       return $values[3];
     }
     $temp = passwordMethod::get_available_methods();