Merge pull request #96 from nextcloud/issue-93
Add plaintext password authentication for prosody xmpp
This commit is contained in:
12
README.md
12
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,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
|
||||
------------
|
||||
|
||||
78
lib/xmpp.php
78
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 = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user