Skip to content

Commit 316e57c

Browse files
Merge pull request #96 from nextcloud/issue-93
Add plaintext password authentication for prosody xmpp
2 parents 6cf5a55 + 5dc9b1d commit 316e57c

2 files changed

Lines changed: 63 additions & 27 deletions

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ Requires the php-ssh2 PECL module installed.
180180
XMPP (Prosody)
181181
----
182182
Authenticate Nextcloud users against a Prosody XMPP MySQL database.
183-
Prosody user and password need to be given for the Nextcloud login
183+
Prosody user and password need to be given for the Nextcloud login.
184184

185185

186186
### Configuration
@@ -195,10 +195,20 @@ Add the following to your `config.php`:
195195
2 => 'dbuser',
196196
3 => 'dbuserpassword',
197197
4 => 'xmppdomain',
198+
5 => true,
198199
),
199200
),
200201
),
201202

203+
0 - Database Host
204+
1 - Prosody Database Name
205+
2 - Database User
206+
3 - Database User Password
207+
4 - XMPP Domain
208+
5 - Hashed Passwords in Database (true) / Plaintext Passwords in Database (false)
209+
210+
**⚠⚠ 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. ⚠⚠
211+
202212

203213
Alternatives
204214
------------

lib/xmpp.php

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ class OC_User_XMPP extends \OCA\user_external\Base {
2020
private $xmppDbUser;
2121
private $xmppDbPassword;
2222
private $xmppDomain;
23+
private $passwordHashed;
2324

24-
public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain) {
25+
public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain, $passwordHashed = true) {
2526
parent::__construct($host);
2627
$this->host = $host;
2728
$this->xmppDb = $xmppDb;
2829
$this->xmppDbUser = $xmppDbUser;
2930
$this->xmppDbPassword = $xmppDbPassword;
3031
$this->xmppDomain = $xmppDomain;
32+
$this->passwordHashed = $passwordHashed;
3133
}
3234

3335
public function hmacSha1($key, $data) {
@@ -48,6 +50,51 @@ public function hmacSha1($key, $data) {
4850
return sha1($oPad.sha1($iPad.$data, true));
4951
}
5052

53+
public function validateHashedPassword($user, $uid, $submittedPassword){
54+
foreach ($user as $key){
55+
if($key[3] === "salt") {
56+
$internalSalt = $key['value'];
57+
}
58+
if($key[3] === "server_key") {
59+
$internalServerKey = $key['value'];
60+
}
61+
if($key[3] === "stored_key") {
62+
$internalStoredKey = $key['value'];
63+
}
64+
}
65+
unset($user);
66+
$internalIteration = '4096';
67+
$newSaltedPassword = hash_pbkdf2('sha1', $submittedPassword, $internalSalt, $internalIteration, 0, true);
68+
$newServerKey = $this->hmacSha1($newSaltedPassword, 'Server Key');
69+
$newClientKey = $this->hmacSha1($newSaltedPassword, 'Client Key');
70+
$newStoredKey = sha1(hex2bin($newClientKey));
71+
72+
if ($newServerKey === $internalServerKey
73+
&& $newStoredKey === $internalStoredKey) {
74+
$uid = mb_strtolower($uid);
75+
$this->storeUser($uid);
76+
return $uid;
77+
} else {
78+
return false;
79+
}
80+
}
81+
82+
public function validatePlainPassword($user, $uid, $submittedPassword) {
83+
foreach ($user as $key) {
84+
if($key[3] === "password") {
85+
$internalPlainPassword = $key['value'];
86+
}
87+
}
88+
unset($user);
89+
if ($submittedPassword === $internalPlainPassword) {
90+
$uid = mb_strtolower($uid);
91+
$this->storeUser($uid);
92+
return $uid;
93+
} else {
94+
return false;
95+
}
96+
}
97+
5198
public function checkPassword($uid, $password){
5299
$pdo = new PDO("mysql:host=$this->host;dbname=$this->xmppDb", $this->xmppDbUser, $this->xmppDbPassword);
53100
if(isset($uid)
@@ -70,32 +117,11 @@ public function checkPassword($uid, $password){
70117
if(empty($user)) {
71118
return false;
72119
}
73-
foreach ($user as $key){
74-
if($key[3] === "salt") {
75-
$internalSalt = $key['value'];
76-
}
77-
if($key[3] === "server_key") {
78-
$internalServerKey = $key['value'];
79-
}
80-
if($key[3] === "stored_key") {
81-
$internalStoredKey = $key['value'];
82-
}
83-
}
84-
unset($user);
85-
$internalIteration = '4096';
86-
87-
$newSaltedPassword = hash_pbkdf2('sha1', $submittedPassword, $internalSalt, $internalIteration, 0, true);
88-
$newServerKey = $this->hmacSha1($newSaltedPassword, 'Server Key');
89-
$newClientKey = $this->hmacSha1($newSaltedPassword, 'Client Key');
90-
$newStoredKey = sha1(hex2bin($newClientKey));
91-
92-
if ($newServerKey === $internalServerKey
93-
&& $newStoredKey === $internalStoredKey) {
94-
$uid = mb_strtolower($uid);
95-
$this->storeUser($uid);
96-
return $uid;
120+
121+
if ($this->passwordHashed === true) {
122+
return $this->validateHashedPassword($user, $uid, $submittedPassword);
97123
} else {
98-
return false;
124+
return $this->validatePlainPassword($user, $uid, $submittedPassword);
99125
}
100126
}
101127
}

0 commit comments

Comments
 (0)