mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-02 22:17:03 +03:00
Remote Synchronization (CardDAV) improvements:
now it supports address book url auto detection (and works with Google contacts, icloud and etc.)
This commit is contained in:
parent
92f2caf700
commit
1fb553e77e
249 changed files with 1338 additions and 1453 deletions
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth\Backend;
|
||||
|
||||
use SabreForRainLoop\DAV;
|
||||
use SabreForRainLoop\HTTP;
|
||||
|
||||
/**
|
||||
* HTTP Basic authentication backend class
|
||||
*
|
||||
* This class can be used by authentication objects wishing to use HTTP Basic
|
||||
* Most of the digest logic is handled, implementors just need to worry about
|
||||
* the validateUserPass method.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author James David Low (http://jameslow.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
abstract class AbstractBasic implements BackendInterface {
|
||||
|
||||
/**
|
||||
* This variable holds the currently logged in username.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Validates a username and password
|
||||
*
|
||||
* This method should return true or false depending on if login
|
||||
* succeeded.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function validateUserPass($username, $password);
|
||||
|
||||
/**
|
||||
* Returns information about the currently logged in username.
|
||||
*
|
||||
* If nobody is currently logged in, this method should return null.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCurrentUser() {
|
||||
return $this->currentUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Authenticates the user based on the current request.
|
||||
*
|
||||
* If authentication is successful, true must be returned.
|
||||
* If authentication fails, an exception must be thrown.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param string $realm
|
||||
* @throws DAV\Exception\NotAuthenticated
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(DAV\Server $server, $realm) {
|
||||
|
||||
$auth = new HTTP\BasicAuth();
|
||||
$auth->setHTTPRequest($server->httpRequest);
|
||||
$auth->setHTTPResponse($server->httpResponse);
|
||||
$auth->setRealm($realm);
|
||||
$userpass = $auth->getUserPass();
|
||||
if (!$userpass) {
|
||||
$auth->requireLogin();
|
||||
throw new DAV\Exception\NotAuthenticated('No basic authentication headers were found');
|
||||
}
|
||||
|
||||
// Authenticates the user
|
||||
if (!$this->validateUserPass($userpass[0],$userpass[1])) {
|
||||
$auth->requireLogin();
|
||||
throw new DAV\Exception\NotAuthenticated('Username or password does not match');
|
||||
}
|
||||
$this->currentUser = $userpass[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth\Backend;
|
||||
|
||||
use SabreForRainLoop\HTTP;
|
||||
use SabreForRainLoop\DAV;
|
||||
|
||||
/**
|
||||
* HTTP Digest authentication backend class
|
||||
*
|
||||
* This class can be used by authentication objects wishing to use HTTP Digest
|
||||
* Most of the digest logic is handled, implementors just need to worry about
|
||||
* the getDigestHash method
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
abstract class AbstractDigest implements BackendInterface {
|
||||
|
||||
/**
|
||||
* This variable holds the currently logged in username.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Returns a users digest hash based on the username and realm.
|
||||
*
|
||||
* If the user was not known, null must be returned.
|
||||
*
|
||||
* @param string $realm
|
||||
* @param string $username
|
||||
* @return string|null
|
||||
*/
|
||||
abstract public function getDigestHash($realm, $username);
|
||||
|
||||
/**
|
||||
* Authenticates the user based on the current request.
|
||||
*
|
||||
* If authentication is successful, true must be returned.
|
||||
* If authentication fails, an exception must be thrown.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param string $realm
|
||||
* @throws DAV\Exception\NotAuthenticated
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(DAV\Server $server, $realm) {
|
||||
|
||||
$digest = new HTTP\DigestAuth();
|
||||
|
||||
// Hooking up request and response objects
|
||||
$digest->setHTTPRequest($server->httpRequest);
|
||||
$digest->setHTTPResponse($server->httpResponse);
|
||||
|
||||
$digest->setRealm($realm);
|
||||
$digest->init();
|
||||
|
||||
$username = $digest->getUsername();
|
||||
|
||||
// No username was given
|
||||
if (!$username) {
|
||||
$digest->requireLogin();
|
||||
throw new DAV\Exception\NotAuthenticated('No digest authentication headers were found');
|
||||
}
|
||||
|
||||
$hash = $this->getDigestHash($realm, $username);
|
||||
// If this was false, the user account didn't exist
|
||||
if ($hash===false || is_null($hash)) {
|
||||
$digest->requireLogin();
|
||||
throw new DAV\Exception\NotAuthenticated('The supplied username was not on file');
|
||||
}
|
||||
if (!is_string($hash)) {
|
||||
throw new DAV\Exception('The returned value from getDigestHash must be a string or null');
|
||||
}
|
||||
|
||||
// If this was false, the password or part of the hash was incorrect.
|
||||
if (!$digest->validateA1($hash)) {
|
||||
$digest->requireLogin();
|
||||
throw new DAV\Exception\NotAuthenticated('Incorrect username');
|
||||
}
|
||||
|
||||
$this->currentUser = $username;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently logged in username.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCurrentUser() {
|
||||
|
||||
return $this->currentUser;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth\Backend;
|
||||
use SabreForRainLoop\DAV;
|
||||
|
||||
/**
|
||||
* Apache authenticator
|
||||
*
|
||||
* This authentication backend assumes that authentication has been
|
||||
* configured in apache, rather than within SabreDAV.
|
||||
*
|
||||
* Make sure apache is properly configured for this to work.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Apache implements BackendInterface {
|
||||
|
||||
/**
|
||||
* Current apache user
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $remoteUser;
|
||||
|
||||
/**
|
||||
* Authenticates the user based on the current request.
|
||||
*
|
||||
* If authentication is successful, true must be returned.
|
||||
* If authentication fails, an exception must be thrown.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param string $realm
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(DAV\Server $server, $realm) {
|
||||
|
||||
$remoteUser = $server->httpRequest->getRawServerValue('REMOTE_USER');
|
||||
if (is_null($remoteUser)) {
|
||||
throw new DAV\Exception('We did not receive the $_SERVER[REMOTE_USER] property. This means that apache might have been misconfigured');
|
||||
}
|
||||
|
||||
$this->remoteUser = $remoteUser;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the currently logged in user.
|
||||
*
|
||||
* If nobody is currently logged in, this method should return null.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getCurrentUser() {
|
||||
|
||||
return $this->remoteUser;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth\Backend;
|
||||
|
||||
/**
|
||||
* This is the base class for any authentication object.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface BackendInterface {
|
||||
|
||||
/**
|
||||
* Authenticates the user based on the current request.
|
||||
*
|
||||
* If authentication is successful, true must be returned.
|
||||
* If authentication fails, an exception must be thrown.
|
||||
*
|
||||
* @param \SabreForRainLoop\DAV\Server $server
|
||||
* @param string $realm
|
||||
* @return bool
|
||||
*/
|
||||
function authenticate(\SabreForRainLoop\DAV\Server $server,$realm);
|
||||
|
||||
/**
|
||||
* Returns information about the currently logged in username.
|
||||
*
|
||||
* If nobody is currently logged in, this method should return null.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getCurrentUser();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth\Backend;
|
||||
|
||||
use SabreForRainLoop\DAV;
|
||||
|
||||
/**
|
||||
* This is an authentication backend that uses a file to manage passwords.
|
||||
*
|
||||
* The backend file must conform to Apache's htdigest format
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class File extends AbstractDigest {
|
||||
|
||||
/**
|
||||
* List of users
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $users = array();
|
||||
|
||||
/**
|
||||
* Creates the backend object.
|
||||
*
|
||||
* If the filename argument is passed in, it will parse out the specified file fist.
|
||||
*
|
||||
* @param string|null $filename
|
||||
*/
|
||||
public function __construct($filename=null) {
|
||||
|
||||
if (!is_null($filename))
|
||||
$this->loadFile($filename);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an htdigest-formatted file. This method can be called multiple times if
|
||||
* more than 1 file is used.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
*/
|
||||
public function loadFile($filename) {
|
||||
|
||||
foreach(file($filename,FILE_IGNORE_NEW_LINES) as $line) {
|
||||
|
||||
if (substr_count($line, ":") !== 2)
|
||||
throw new DAV\Exception('Malformed htdigest file. Every line should contain 2 colons');
|
||||
|
||||
list($username,$realm,$A1) = explode(':',$line);
|
||||
|
||||
if (!preg_match('/^[a-zA-Z0-9]{32}$/', $A1))
|
||||
throw new DAV\Exception('Malformed htdigest file. Invalid md5 hash');
|
||||
|
||||
$this->users[$realm . ':' . $username] = $A1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a users' information
|
||||
*
|
||||
* @param string $realm
|
||||
* @param string $username
|
||||
* @return string
|
||||
*/
|
||||
public function getDigestHash($realm, $username) {
|
||||
|
||||
return isset($this->users[$realm . ':' . $username])?$this->users[$realm . ':' . $username]:false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth\Backend;
|
||||
|
||||
/**
|
||||
* This is an authentication backend that uses a file to manage passwords.
|
||||
*
|
||||
* The backend file must conform to Apache's htdigest format
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class PDO extends AbstractDigest {
|
||||
|
||||
/**
|
||||
* Reference to PDO connection
|
||||
*
|
||||
* @var PDO
|
||||
*/
|
||||
protected $pdo;
|
||||
|
||||
/**
|
||||
* PDO table name we'll be using
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function __construct(\PDO $pdo, $tableName = 'users') {
|
||||
|
||||
$this->pdo = $pdo;
|
||||
$this->tableName = $tableName;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the digest hash for a user.
|
||||
*
|
||||
* @param string $realm
|
||||
* @param string $username
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDigestHash($realm,$username) {
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT username, digesta1 FROM '.$this->tableName.' WHERE username = ?');
|
||||
$stmt->execute(array($username));
|
||||
$result = $stmt->fetchAll();
|
||||
|
||||
if (!count($result)) return;
|
||||
|
||||
return $result[0]['digesta1'];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace SabreForRainLoop\DAV\Auth;
|
||||
use SabreForRainLoop\DAV;
|
||||
|
||||
/**
|
||||
* This plugin provides Authentication for a WebDAV server.
|
||||
*
|
||||
* It relies on a Backend object, which provides user information.
|
||||
*
|
||||
* Additionally, it provides support for:
|
||||
* * {DAV:}current-user-principal property from RFC5397
|
||||
* * {DAV:}principal-collection-set property from RFC3744
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Plugin extends DAV\ServerPlugin {
|
||||
|
||||
/**
|
||||
* Reference to main server object
|
||||
*
|
||||
* @var SabreForRainLoop\DAV\Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* Authentication backend
|
||||
*
|
||||
* @var Backend\BackendInterface
|
||||
*/
|
||||
protected $authBackend;
|
||||
|
||||
/**
|
||||
* The authentication realm.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $realm;
|
||||
|
||||
/**
|
||||
* __construct
|
||||
*
|
||||
* @param Backend\BackendInterface $authBackend
|
||||
* @param string $realm
|
||||
*/
|
||||
public function __construct(Backend\BackendInterface $authBackend, $realm) {
|
||||
|
||||
$this->authBackend = $authBackend;
|
||||
$this->realm = $realm;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the plugin. This function is automatically called by the server
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(DAV\Server $server) {
|
||||
|
||||
$this->server = $server;
|
||||
$this->server->subscribeEvent('beforeMethod',array($this,'beforeMethod'),10);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a plugin name.
|
||||
*
|
||||
* Using this name other plugins will be able to access other plugins
|
||||
* using DAV\Server::getPlugin
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginName() {
|
||||
|
||||
return 'auth';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current users' principal uri.
|
||||
*
|
||||
* If nobody is logged in, this will return null.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCurrentUser() {
|
||||
|
||||
$userInfo = $this->authBackend->getCurrentUser();
|
||||
if (!$userInfo) return null;
|
||||
|
||||
return $userInfo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called before any HTTP method and forces users to be authenticated
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
* @throws SabreForRainLoop\DAV\Exception\NotAuthenticated
|
||||
* @return bool
|
||||
*/
|
||||
public function beforeMethod($method, $uri) {
|
||||
|
||||
$this->authBackend->authenticate($this->server,$this->realm);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue