Merge pull request #37 from sebastiansterk/master
Add Prosody XMPP MySQL DB authentication
This commit is contained in:
24
README.md
24
README.md
@@ -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:
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
102
lib/xmpp.php
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user