summaryrefslogtreecommitdiff
path: root/lib/Kolab/DAV/Auth/HTTPBasic.php
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2013-05-29 10:50:02 (GMT)
committerAleksander Machniak <alec@alec.pl>2013-05-29 10:50:02 (GMT)
commitabb7ec1a168ac313c45c14a8bbd1477206bd8d71 (patch)
tree71c33a9ef5f05b1466266f9aef1a8dd6f1a24ca5 /lib/Kolab/DAV/Auth/HTTPBasic.php
parentad9b5530aad39c81d7f978acf192382930e75462 (diff)
downloadiRony-abb7ec1a168ac313c45c14a8bbd1477206bd8d71.tar.gz
Replace CacheAPC with rcube_cache_shared (Bug #1894)
Improve login process, do not require kolab_auth plugin
Diffstat (limited to 'lib/Kolab/DAV/Auth/HTTPBasic.php')
-rw-r--r--lib/Kolab/DAV/Auth/HTTPBasic.php219
1 files changed, 152 insertions, 67 deletions
diff --git a/lib/Kolab/DAV/Auth/HTTPBasic.php b/lib/Kolab/DAV/Auth/HTTPBasic.php
index e16c894..1f841e9 100644
--- a/lib/Kolab/DAV/Auth/HTTPBasic.php
+++ b/lib/Kolab/DAV/Auth/HTTPBasic.php
@@ -50,83 +50,40 @@ class HTTPBasic extends \Sabre\DAV\Auth\Backend\AbstractBasic
protected function validateUserPass($username, $password)
{
$rcube = rcube::get_instance();
- $cache = CacheAPC::get_instance('kolabdav:auth');
- // Here we need IDNA ASCII
- $host = rcube_utils::idn_to_ascii($rcube->config->get('default_host', 'localhost'));
- $user = rcube_utils::idn_to_ascii($username);
- $port = $rcube->config->get('default_port', 143);
-
- $_host = parse_url($host);
- if ($_host['host']) {
- $host = $_host['host'];
- $ssl = (isset($_host['scheme']) && in_array($_host['scheme'], array('ssl','imaps','tls'))) ? $_host['scheme'] : null;
- if (!empty($_host['port']))
- $port = $_host['port'];
- else if ($ssl && $ssl != 'tls' && (!$port || $port == 143))
- $port = 993;
- }
-
- // check if we already canonified this username
- if ($auth_user = $cache->get($user)) {
- $user = $auth_user;
- }
- else { // load kolab_auth plugin to resolve the canonical username
- $rcube->plugins->load_plugin('kolab_auth');
+ // use shared cache for kolab_auth plugin result (username canonification)
+ $cache = $rcube->get_cache_shared('kolabdav_auth');
+ $cache_key = md5($username . '::' . $password);
+
+ if (!$cache || !($auth = $cache->get($cache_key))) {
+ $auth = $rcube->plugins->exec_hook('authenticate', array(
+ 'host' => $this->_select_host($username),
+ 'user' => $username,
+ 'pass' => $password,
+ ));
+
+ if ($cache) {
+ $cache->set($cache_key, array(
+ 'user' => $auth['user'],
+ 'host' => $auth['host'],
+ ));
+ }
}
-
- // let plugins do their work
- $auth = $rcube->plugins->exec_hook('authenticate', array(
- 'host' => $host,
- 'user' => $user,
- 'pass' => $password,
- ));
-
- // user already registered?
- if ($user_object = rcube_user::query($auth['user'], $auth['host'])) {
- $auth['user'] = $user_object->data['username'];
+ else {
+ $auth['pass'] = $password;
}
// authenticate user against the IMAP server
- $imap = $rcube->get_storage();
- $success = $imap->connect($auth['host'], $auth['user'], $auth['pass'], $port, $ssl);
-
- if ($success) {
- // No user in database, but IMAP auth works
- if (!is_object($user_object)) {
- if ($rcube->config->get('auto_create_user')) {
- // create a new user record
- $user_object = rcube_user::create($auth['user'], $auth['host']);
-
- if (!$user_object) {
- rcube::raise_error(array(
- 'code' => 620, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Failed to create a user record",
- ), true, false);
- return false;
- }
- }
- else {
- rcube::raise_error(array(
- 'code' => 620, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Access denied for new user $user. 'auto_create_user' is disabled",
- ), true, false);
- return false;
- }
- }
+ $user_id = $this->_login($auth['user'], $auth['pass'], $auth['host']);
+ if ($user_id) {
self::$current_user = $auth['user'];
- self::$current_pass = $rcube->password = $password;
- if (!$auth_user) {
- $cache->set($user, $auth['user']);
- }
+ self::$current_pass = $auth['pass'];
- // register a rcube_user object for global access
- $rcube->user = $user_object;
- $_SESSION['imap_host'] = $auth['host'];
+ return true;
}
- return $success;
+ return false;
}
/**
@@ -141,4 +98,132 @@ class HTTPBasic extends \Sabre\DAV\Auth\Backend\AbstractBasic
// return the canonic user name
return self::$current_user;
}
+
+ /**
+ * Storage host selection
+ */
+ protected function _select_host($username)
+ {
+ // Get IMAP host
+ $rcube = rcube::get_instance();
+ $host = $rcube->config->get('default_host', 'localhost');
+
+ if (is_array($host)) {
+ list($user, $domain) = explode('@', $username);
+
+ // try to select host by mail domain
+ if (!empty($domain)) {
+ foreach ($host as $storage_host => $mail_domains) {
+ if (is_array($mail_domains) && in_array_nocase($domain, $mail_domains)) {
+ $host = $storage_host;
+ break;
+ }
+ else if (stripos($storage_host, $domain) !== false || stripos(strval($mail_domains), $domain) !== false) {
+ $host = is_numeric($storage_host) ? $mail_domains : $storage_host;
+ break;
+ }
+ }
+ }
+
+ // take the first entry if $host is not found
+ if (is_array($host)) {
+ list($key, $val) = each($default_host);
+ $host = is_numeric($key) ? $val : $key;
+ }
+ }
+
+ return rcube_utils::parse_host($host);
+ }
+
+ /**
+ * Authenticates a user in IMAP and returns Roundcube user ID.
+ */
+ protected function _login($username, $password, $host)
+ {
+ if (empty($username)) {
+ return null;
+ }
+
+ $rcube = rcube::get_instance();
+ $storage = $rcube->get_storage();
+ $login_lc = $rcube->config->get('login_lc');
+ $default_port = $rcube->config->get('default_port', 143);
+
+ // parse $host
+ $a_host = parse_url($host);
+ if ($a_host['host']) {
+ $host = $a_host['host'];
+ $ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
+ if (!empty($a_host['port'])) {
+ $port = $a_host['port'];
+ }
+ else if ($ssl && $ssl != 'tls' && (!$default_port || $default_port == 143)) {
+ $port = 993;
+ }
+ }
+
+ if (!$port) {
+ $port = $default_port;
+ }
+
+ // Convert username to lowercase. If storage backend
+ // is case-insensitive we need to store always the same username
+ if ($login_lc) {
+ if ($login_lc == 2 || $login_lc === true) {
+ $username = mb_strtolower($username);
+ }
+ else if (strpos($username, '@')) {
+ // lowercase domain name
+ list($local, $domain) = explode('@', $username);
+ $username = $local . '@' . mb_strtolower($domain);
+ }
+ }
+
+ // Here we need IDNA ASCII
+ // Only rcube_contacts class is using domain names in Unicode
+ $host = rcube_utils::idn_to_ascii($host);
+ $username = rcube_utils::idn_to_ascii($username);
+
+ // user already registered?
+ if ($user = rcube_user::query($username, $host)) {
+ $username = $user->data['username'];
+ }
+
+ // authenticate user in IMAP
+ if (!$storage->connect($host, $username, $password, $port, $ssl)) {
+ return null;
+ }
+
+ // No user in database, but IMAP auth works
+ if (!is_object($user)) {
+ if ($rcube->config->get('auto_create_user')) {
+ // create a new user record
+ $user = rcube_user::create($username, $host);
+
+ if (!$user) {
+ rcube::raise_error(array(
+ 'code' => 620, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Failed to create a user record",
+ ), true, false);
+ return null;
+ }
+ }
+ else {
+ rcube::raise_error(array(
+ 'code' => 620, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Access denied for new user $username. 'auto_create_user' is disabled",
+ ), true, false);
+ return null;
+ }
+ }
+
+ // overwrite config with user preferences
+ $rcube->user = $user;
+ $rcube->config->set_user_prefs((array)$rcube->user->get_prefs());
+ $rcube->password = $password;
+
+ setlocale(LC_ALL, 'en_US.utf8', 'en_US.UTF-8');
+
+ return $user->ID;
+ }
}