Browse Source

[Web] Verify additional password hashes (only SHA512-CRYPT is supported today)

André 7 years ago
parent
commit
2f270f3b9b
2 changed files with 32 additions and 22 deletions
  1. 2 2
      data/web/inc/functions.domain_admin.inc.php
  2. 30 20
      data/web/inc/functions.inc.php

+ 2 - 2
data/web/inc/functions.domain_admin.inc.php

@@ -318,7 +318,7 @@ function domain_admin($_action, $_data = null) {
             WHERE `username` = :user");
             WHERE `username` = :user");
         $stmt->execute(array(':user' => $username));
         $stmt->execute(array(':user' => $username));
         $row = $stmt->fetch(PDO::FETCH_ASSOC);
         $row = $stmt->fetch(PDO::FETCH_ASSOC);
-        if (!verify_ssha256($row['password'], $password_old)) {
+        if (!verify_hash($row['password'], $password_old)) {
           $_SESSION['return'] = array(
           $_SESSION['return'] = array(
             'type' => 'danger',
             'type' => 'danger',
             'msg' => sprintf($lang['danger']['access_denied'])
             'msg' => sprintf($lang['danger']['access_denied'])
@@ -504,4 +504,4 @@ function domain_admin($_action, $_data = null) {
       return $domainadmindata;
       return $domainadmindata;
     break;
     break;
   }
   }
-}
+}

+ 30 - 20
data/web/inc/functions.inc.php

@@ -128,22 +128,32 @@ function generate_tlsa_digest($hostname, $port, $starttls = null) {
     return 'Error: Cannot read peer certificate';
     return 'Error: Cannot read peer certificate';
   }
   }
 }
 }
-function verify_ssha256($hash, $password) {
-	// Remove tag if any
+//function verify_hash($hash, $password) {
+function verify_hash($hash, $password) {
+  // Remove tag if any
   $hash = preg_replace('/^{SSHA256}/i', '', $hash);
   $hash = preg_replace('/^{SSHA256}/i', '', $hash);
-	// Decode hash
-	$dhash = base64_decode($hash);
-	// Get first 32 bytes of binary which equals a SHA256 hash
-	$ohash = substr($dhash, 0, 32);
-	// Remove SHA256 hash from decoded hash to get original salt string
-	$osalt = str_replace($ohash, '', $dhash);
-	// Check single salted SHA256 hash against extracted hash
-	if (hash('sha256', $password . $osalt, true) == $ohash) {
-		return true;
-	}
-	else {
-		return false;
-	}
+  // Decode hash
+  $dhash = base64_decode($hash);
+  // Get first 32 bytes of binary which equals a SHA256 hash
+  $ohash = substr($dhash, 0, 32);
+  // Remove SHA256 hash from decoded hash to get original salt string
+  $osalt = str_replace($ohash, '', $dhash);
+  // Check single salted SHA256 hash against extracted hash
+  if (hash_equals(hash('sha256', $password . $osalt, true), $ohash)) {
+    return true;
+  }
+  else {
+    // Remove tag if any
+    $hash = preg_replace('/^{SHA512-CRYPT}/i', '', $hash);
+    // Decode hash
+    preg_match('/\\$6\\$(.*)\\$(.*)/i', $hash, $hash_array);
+    $osalt = $hash_array[1];
+    $ohash = $hash_array[2];
+    if (hash_equals(crypt($password, '$6$' . $osalt . '$'), $hash)) {
+      return true;
+    }
+  }
+  return false;
 }
 }
 function check_login($user, $pass) {
 function check_login($user, $pass) {
 	global $pdo;
 	global $pdo;
@@ -158,7 +168,7 @@ function check_login($user, $pass) {
 	$stmt->execute(array(':user' => $user));
 	$stmt->execute(array(':user' => $user));
 	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
 	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
 	foreach ($rows as $row) {
 	foreach ($rows as $row) {
-		if (verify_ssha256($row['password'], $pass)) {
+		if (verify_hash($row['password'], $pass)) {
       if (get_tfa($user)['name'] != "none") {
       if (get_tfa($user)['name'] != "none") {
         $_SESSION['pending_mailcow_cc_username'] = $user;
         $_SESSION['pending_mailcow_cc_username'] = $user;
         $_SESSION['pending_mailcow_cc_role'] = "admin";
         $_SESSION['pending_mailcow_cc_role'] = "admin";
@@ -179,7 +189,7 @@ function check_login($user, $pass) {
 	$stmt->execute(array(':user' => $user));
 	$stmt->execute(array(':user' => $user));
 	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
 	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
 	foreach ($rows as $row) {
 	foreach ($rows as $row) {
-		if (verify_ssha256($row['password'], $pass) !== false) {
+		if (verify_hash($row['password'], $pass) !== false) {
       if (get_tfa($user)['name'] != "none") {
       if (get_tfa($user)['name'] != "none") {
         $_SESSION['pending_mailcow_cc_username'] = $user;
         $_SESSION['pending_mailcow_cc_username'] = $user;
         $_SESSION['pending_mailcow_cc_role'] = "domainadmin";
         $_SESSION['pending_mailcow_cc_role'] = "domainadmin";
@@ -202,7 +212,7 @@ function check_login($user, $pass) {
 	$stmt->execute(array(':user' => $user));
 	$stmt->execute(array(':user' => $user));
 	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
 	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
 	foreach ($rows as $row) {
 	foreach ($rows as $row) {
-		if (verify_ssha256($row['password'], $pass) !== false) {
+		if (verify_hash($row['password'], $pass) !== false) {
 			unset($_SESSION['ldelay']);
 			unset($_SESSION['ldelay']);
 			return "user";
 			return "user";
 		}
 		}
@@ -388,7 +398,7 @@ function edit_user_account($postarray) {
         AND `username` = :user");
         AND `username` = :user");
 	$stmt->execute(array(':user' => $username));
 	$stmt->execute(array(':user' => $username));
 	$row = $stmt->fetch(PDO::FETCH_ASSOC);
 	$row = $stmt->fetch(PDO::FETCH_ASSOC);
-  if (!verify_ssha256($row['password'], $password_old)) {
+  if (!verify_hash($row['password'], $password_old)) {
     $_SESSION['return'] = array(
     $_SESSION['return'] = array(
       'type' => 'danger',
       'type' => 'danger',
       'msg' => sprintf($lang['danger']['access_denied'])
       'msg' => sprintf($lang['danger']['access_denied'])
@@ -538,7 +548,7 @@ function set_tfa($postarray) {
       WHERE `username` = :user");
       WHERE `username` = :user");
   $stmt->execute(array(':user' => $username));
   $stmt->execute(array(':user' => $username));
   $row = $stmt->fetch(PDO::FETCH_ASSOC);
   $row = $stmt->fetch(PDO::FETCH_ASSOC);
-  if (!verify_ssha256($row['password'], $postarray["confirm_password"])) {
+  if (!verify_hash($row['password'], $postarray["confirm_password"])) {
     $_SESSION['return'] = array(
     $_SESSION['return'] = array(
       'type' => 'danger',
       'type' => 'danger',
       'msg' => sprintf($lang['danger']['access_denied'])
       'msg' => sprintf($lang['danger']['access_denied'])