Hey guys,
I am currently trying to create an IMAP authentication backend for Baikal/SabreDAV.
The aim is for SabreDAV to authenticate users using an IMAP server (which will make CalDAV and CardDAV authentication a lot easier).
This is the code I have produced so far:
<?php
namespace Sabre\DAV\Auth\Backend;
// Auth Class
class IMAP extends AbstractBasic
{
protected $imap_server;
/**
* Reference to PDO connection
*
* @var PDO
*/
protected $pdo;
/**
* PDO table name we'll be using
*
* @var string
*/
protected $tableName;
/**
* 'modtime' timeout (deprecated)
*
* @var integer
*/
protected $timeout;
public function __construct($imap_server, $pdo, $timeout = null)
{
$this->imap_server = $imap_server;
$this->timeout = $timeout;
$this->constructDb($pdo);
}
/**
* Creates the backend object.
*
* If the filename argument is passed in, it will parse out the specified file fist.
*
* @param PDO $pdo
* @param string $tableName The PDO table name to use
*/
protected function constructDb(\PDO $pdo, $tableName = 'users') {
$this->pdo = $pdo;
$this->tableName = $tableName;
}
protected function validateUserPass($username, $password) {
/* Try logging in to the IMAP server using provided credentials */
try {
$imap = imap_open($this->imap_server, $username, $password, OP_HALFOPEN);
} catch (Exception $e) {
/* Invalid user, or other error, stop here */
return false;
}
/* Check if user exists, if so update password if needed, else create user */
$stmt = $this->pdo->prepare('SELECT username FROM users WHERE username = ?');
$stmt->execute(array($username));
$result = $stmt->fetchAll();
if(count($result)===1) {
/* Check if password is correct */
$logindigest = hash("md5","$username:$password");
$stmt = $this->pdo->prepare('SELECT username FROM users WHERE username = ? AND digesta1 = ?');
$stmt->execute(array($username, $logindigest));
$result = $stmt->fetchAll();
if(count($result)===0) {
/* Old password, update it */
$stmt = $this->pdo->prepare('UPDATE users SET digesta1 = ? WHERE username = ?');
$stmt->execute(array($logindigest, $username));
}
} else if(count($result)===0) {
/* User does not exist in Baikal, create an account */
$this->addImapUser($username, $password);
} else {
/* Unknown error, multiple accs? */
return false;
}
/* User authenticated */
return true;
}
protected function addImapUser($email, $password) {
$logindigest = hash("md5","$email:$password");
$stmt = $this->pdo->prepare('INSERT INTO users (username, digesta1) VALUES (?, ?)');
$stmt->execute($username, $logindigest);
}
}
My cal.php has the following changes:
$authBackend = new \Sabre\DAV\Auth\Backend\IMAP("{localhost:143}",$GLOBALS["DB"]->getPDO(),60);
I am in the process of trying to workout why it does not work. Under normal circumstances, when I open cal.php in the browser I get an XML error (as no request is sent) however using this authentication method I get an error 500.
Also, my script updates the logindigest everytime it does not match (i.e. IMAP password is changed), would it better (performance wise) to not update the login digest and just keep it in the form email:fixedvalue (or just email)?