Merge pull request #96 from nextcloud/issue-93

Add plaintext password authentication for prosody xmpp
This commit is contained in:
violoncello.ch
2019-08-02 17:37:03 +02:00
committed by GitHub
2 changed files with 63 additions and 27 deletions

View File

@@ -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,20 @@ 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)
**⚠⚠ 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
------------

View File

@@ -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 = true) {
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);
}
}
}