Add Prosody XMPP MySQL authentication

Signed-off-by: Sebastian <sebastian@wiuwiu.de>

Change class name

Signed-off-by: Sebastian <sebastian@wiuwiu.de>

add prosody to title name

Signed-off-by: Sebastian <sebastian@wiuwiu.de>

integrate nextcloud code style guidelines

Signed-off-by: Sebastian <sebastian@wiuwiu.de>

clean up

Signed-off-by: Sebastian <sebastian@wiuwiu.de>

Applied nc code style

Signed-off-by: Sebastian <sebastian@wiuwiu.de>
This commit is contained in:
Sebastian
2019-02-10 11:24:02 +01:00
committed by Jonas Sulzer
parent 566a30859f
commit 104e409e83
4 changed files with 129 additions and 2 deletions

View File

@@ -146,6 +146,30 @@ Add the following to your `config.php`:
[BasicAuth_0]: https://en.wikipedia.org/wiki/Basic_access_authentication
XMPP (Prosody)
----
Authenticate Nextcloud users against a Prosody XMPP MySQL database.
Prosody user and password need to be given for the Nextcloud login
### Configuration
Add the following to your `config.php`:
'user_backends' => array (
0 => array (
'class' => 'OC_User_XMPP',
'arguments' => array (
0 => 'dbhost',
1 => 'prosodydb',
2 => 'dbuser',
3 => 'dbuserpassword',
4 => 'xmppdomain',
),
),
),
Alternatives
------------
Other extensions allow connecting to external user databases directly via SQL, which may be faster:

View File

@@ -3,3 +3,4 @@ OC::$CLASSPATH['OC_User_IMAP']='user_external/lib/imap.php';
OC::$CLASSPATH['OC_User_SMB']='user_external/lib/smb.php';
OC::$CLASSPATH['OC_User_FTP']='user_external/lib/ftp.php';
OC::$CLASSPATH['OC_User_BasicAuth']='user_external/lib/basicauth.php';
OC::$CLASSPATH['OC_User_XMPP']='user_external/lib/xmpp.php';

View File

@@ -3,8 +3,8 @@
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
<id>user_external</id>
<name>External user support</name>
<summary>Use external user authentication methods like IMAP, SMB and FTP</summary>
<description>Use external user authentication methods like IMAP, SMB and FTP</description>
<summary>Use external user authentication methods like IMAP, SMB, FTP, WebDAV, HTTP BasicAuth and XMPP</summary>
<description>Use external user authentication methods like IMAP, SMB, FTP, WebDAV, HTTP BasicAuth and XMPP</description>
<version>0.6.0</version>
<licence>agpl</licence>
<author>Robin Appelman</author>

102
lib/xmpp.php Normal file
View File

@@ -0,0 +1,102 @@
<?php
/**
* Copyright (c) 2019 Sebastian Sterk <sebastian@wiuwiu.de>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* User authentication against a XMPP Prosody MySQL database
*
* @category Apps
* @package UserExternal
* @author Sebastian Sterk https://wiuwiu.de/Imprint
* @license http://www.gnu.org/licenses/agpl AGPL
*/
class OC_User_XMPP extends \OCA\user_external\Base {
private $host;
private $xmppDb;
private $xmppDbUser;
private $xmppDbPassword;
private $xmppDomain;
public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain) {
parent::__construct($host);
$this->host = $host;
$this->xmppDb = $xmppDb;
$this->xmppDbUser = $xmppDbUser;
$this->xmppDbPassword = $xmppDbPassword;
$this->xmppDomain = $xmppDomain;
}
public function hmacSha1($key, $data) {
if (strlen($key) > 64) {
$key = str_pad(sha1($key, true), 64, chr(0));
}
if (strlen($key) < 64) {
$key = str_pad($key, 64, chr(0));
}
$oPad = str_repeat(chr(0x5C), 64);
$iPad = str_repeat(chr(0x36), 64);
for ($i = 0; $i < strlen($key); $i++) {
$oPad[$i] = $oPad[$i] ^ $key[$i];
$iPad[$i] = $iPad[$i] ^ $key[$i];
}
return sha1($oPad.sha1($iPad.$data, true));
}
public function checkPassword($uid, $password){
$pdo = new PDO("mysql:host=$this->host;dbname=$this->xmppDb", $this->xmppDbUser, $this->xmppDbPassword);
if(isset($uid)
&& isset($password)) {
if(!filter_var($uid, FILTER_VALIDATE_EMAIL)
|| !strpos($uid, $this->xmppDomain)
|| substr($uid, -strlen($this->xmppDomain)) !== $this->xmppDomain
) {
return false;
}
$user = explode("@", $uid);
$userName = strtolower($user[0]);
$submittedPassword = $password;
$statement = $pdo->prepare("SELECT * FROM prosody WHERE user = :user AND host = :xmppDomain AND store = 'accounts'");
$result = $statement->execute(array(
'user' => $userName,
'xmppDomain' => $this->xmppDomain
));
$user = $statement->fetchAll();
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;
} else {
return false;
}
}
}
}