From b05e2d68b2118db4dcdd39697cf9b7793a40bbdd Mon Sep 17 00:00:00 2001 From: Sebastian Sterk Date: Thu, 18 Jul 2019 21:39:09 +0200 Subject: [PATCH 1/3] Add plaintext password authenticaion for prosody mysql Signed-off-by: Sebastian Sterk --- lib/xmpp.php | 78 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/lib/xmpp.php b/lib/xmpp.php index 4bfe92c..7e718a7 100644 --- a/lib/xmpp.php +++ b/lib/xmpp.php @@ -20,14 +20,16 @@ class OC_User_XMPP extends \OCA\user_external\Base { private $xmppDbUser; private $xmppDbPassword; private $xmppDomain; + private $passwordHashed; - public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain) { + public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain, $passwordHashed) { parent::__construct($host); $this->host = $host; $this->xmppDb = $xmppDb; $this->xmppDbUser = $xmppDbUser; $this->xmppDbPassword = $xmppDbPassword; $this->xmppDomain = $xmppDomain; + $this->passwordHashed = $passwordHashed; } public function hmacSha1($key, $data) { @@ -48,6 +50,51 @@ class OC_User_XMPP extends \OCA\user_external\Base { return sha1($oPad.sha1($iPad.$data, true)); } + public function validateHashedPassword($user, $uid, $submittedPassword){ + foreach ($user as $key){ + if($key[3] === "salt") { + $internalSalt = $key['value']; + } + if($key[3] === "server_key") { + $internalServerKey = $key['value']; + } + if($key[3] === "stored_key") { + $internalStoredKey = $key['value']; + } + } + unset($user); + $internalIteration = '4096'; + $newSaltedPassword = hash_pbkdf2('sha1', $submittedPassword, $internalSalt, $internalIteration, 0, true); + $newServerKey = $this->hmacSha1($newSaltedPassword, 'Server Key'); + $newClientKey = $this->hmacSha1($newSaltedPassword, 'Client Key'); + $newStoredKey = sha1(hex2bin($newClientKey)); + + if ($newServerKey === $internalServerKey + && $newStoredKey === $internalStoredKey) { + $uid = mb_strtolower($uid); + $this->storeUser($uid); + return $uid; + } else { + return false; + } + } + + public function validatePlainPassword($user, $uid, $submittedPassword) { + foreach ($user as $key) { + if($key[3] === "password") { + $internalPlainPassword = $key['value']; + } + } + unset($user); + if ($submittedPassword === $internalPlainPassword) { + $uid = mb_strtolower($uid); + $this->storeUser($uid); + return $uid; + } else { + return false; + } + } + public function checkPassword($uid, $password){ $pdo = new PDO("mysql:host=$this->host;dbname=$this->xmppDb", $this->xmppDbUser, $this->xmppDbPassword); if(isset($uid) @@ -70,32 +117,11 @@ class OC_User_XMPP extends \OCA\user_external\Base { if(empty($user)) { return false; } - foreach ($user as $key){ - if($key[3] === "salt") { - $internalSalt = $key['value']; - } - if($key[3] === "server_key") { - $internalServerKey = $key['value']; - } - if($key[3] === "stored_key") { - $internalStoredKey = $key['value']; - } - } - unset($user); - $internalIteration = '4096'; - - $newSaltedPassword = hash_pbkdf2('sha1', $submittedPassword, $internalSalt, $internalIteration, 0, true); - $newServerKey = $this->hmacSha1($newSaltedPassword, 'Server Key'); - $newClientKey = $this->hmacSha1($newSaltedPassword, 'Client Key'); - $newStoredKey = sha1(hex2bin($newClientKey)); - - if ($newServerKey === $internalServerKey - && $newStoredKey === $internalStoredKey) { - $uid = mb_strtolower($uid); - $this->storeUser($uid); - return $uid; + + if ($this->passwordHashed === true) { + return $this->validateHashedPassword($user, $uid, $submittedPassword); } else { - return false; + return $this->validatePlainPassword($user, $uid, $submittedPassword); } } } From 66747dbaa9084a9ddbe92635070207f16f61cb4f Mon Sep 17 00:00:00 2001 From: Sebastian Sterk Date: Thu, 18 Jul 2019 21:39:40 +0200 Subject: [PATCH 2/3] Update Prosody section Signed-off-by: Sebastian Sterk --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fbc2e6..bf62121 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Requires the php-ssh2 PECL module installed. XMPP (Prosody) ---- Authenticate Nextcloud users against a Prosody XMPP MySQL database. -Prosody user and password need to be given for the Nextcloud login +Prosody user and password need to be given for the Nextcloud login. ### Configuration @@ -195,10 +195,17 @@ Add the following to your `config.php`: 2 => 'dbuser', 3 => 'dbuserpassword', 4 => 'xmppdomain', + 5 => true, ), ), ), +0 - Database Host +1 - Prosody Database Name +2 - Database User +3 - Database User Password +4 - XMPP Domain +5 - Hashed Passwords in Database (true) / Plaintext Passwords in Database (false) Alternatives ------------ From 5dc9b1db12c1f2df52a31c1e783c0705bad6007b Mon Sep 17 00:00:00 2001 From: Sebastian Sterk Date: Thu, 1 Aug 2019 12:53:46 +0200 Subject: [PATCH 3/3] Add warning for plaintext passwords, set default password mode to secure Signed-off-by: Sebastian Sterk --- README.md | 5 ++++- lib/xmpp.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf62121..85e886c 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ Add the following to your `config.php`: 2 => 'dbuser', 3 => 'dbuserpassword', 4 => 'xmppdomain', - 5 => true, + 5 => true, ), ), ), @@ -207,6 +207,9 @@ Add the following to your `config.php`: 4 - XMPP Domain 5 - Hashed Passwords in Database (true) / Plaintext Passwords in Database (false) +**⚠⚠ Warning:** If you need to set *5 (Hashed Password in Database)* to false, your Prosody Instance is storing passwords in plaintext. This is insecure and not recommended. We highly recommend that you change your Prosody configuration to protect the passwords of your Prosody users. ⚠⚠ + + Alternatives ------------ Other extensions allow connecting to external user databases directly via SQL, which may be faster: diff --git a/lib/xmpp.php b/lib/xmpp.php index 7e718a7..3d787ce 100644 --- a/lib/xmpp.php +++ b/lib/xmpp.php @@ -22,7 +22,7 @@ class OC_User_XMPP extends \OCA\user_external\Base { private $xmppDomain; private $passwordHashed; - public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain, $passwordHashed) { + public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain, $passwordHashed = true) { parent::__construct($host); $this->host = $host; $this->xmppDb = $xmppDb;