From f54e5e65c97147b29600bc377d67ebbb4013ac30 Mon Sep 17 00:00:00 2001 From: panigrc Date: Wed, 24 Jun 2020 00:49:11 +0200 Subject: [PATCH 1/3] Add Feature IMAP authentication ### Added - Add IMAP Authentication Plugin which stores the IMAP server to a DB field and handles the registration and authentication of IMAP users. ### Changed - Add extra plugin hooks `beforeVerifyUser` & `afterVerifyUser` in `60.plugins.php`. - Change the `login.class.php` by calling the `beforeVerifyUser` & `afterVerifyUser` hooks in order to support more authentication methods. --- bl-kernel/boot/rules/60.plugins.php | 3 + bl-kernel/login.class.php | 21 ++- .../imap-authentication/languages/de.json | 8 + .../imap-authentication/languages/en.json | 8 + bl-plugins/imap-authentication/metadata.json | 10 ++ bl-plugins/imap-authentication/plugin.php | 137 ++++++++++++++++++ 6 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 bl-plugins/imap-authentication/languages/de.json create mode 100644 bl-plugins/imap-authentication/languages/en.json create mode 100644 bl-plugins/imap-authentication/metadata.json create mode 100644 bl-plugins/imap-authentication/plugin.php diff --git a/bl-kernel/boot/rules/60.plugins.php b/bl-kernel/boot/rules/60.plugins.php index 7918123b..5abe0421 100644 --- a/bl-kernel/boot/rules/60.plugins.php +++ b/bl-kernel/boot/rules/60.plugins.php @@ -37,6 +37,9 @@ $plugins = array( 'loginBodyBegin'=>array(), 'loginBodyEnd'=>array(), + 'beforeVerifyUser'=>array(), + 'afterVerifyUser'=>array(), + 'all'=>array() ); diff --git a/bl-kernel/login.class.php b/bl-kernel/login.class.php index 5b92bada..72747192 100644 --- a/bl-kernel/login.class.php +++ b/bl-kernel/login.class.php @@ -104,6 +104,13 @@ class Login { return false; } + try { + Theme::plugins('beforeVerifyUser'); + } catch (Exception $e) { + Log::set($e->getFile().LOG_SEP.$e->getLine().LOG_SEP.$e->getMessage()); + return false; + } + try { $user = new User($username); } catch (Exception $e) { @@ -117,7 +124,17 @@ class Login { return true; } - Log::set(__METHOD__.LOG_SEP.'Password incorrect.'); + try { + Theme::plugins('afterVerifyUser'); + } catch (Exception $e) { + Log::set($e->getFile().LOG_SEP.$e->getLine().LOG_SEP.$e->getMessage()); + return false; + } + if ($this->isLogged()) { + return true; + } + + Log::set(__METHOD__.LOG_SEP.'Password incorrect.'); return false; } @@ -171,4 +188,4 @@ class Login { Session::destroy(); return true; } -} \ No newline at end of file +} diff --git a/bl-plugins/imap-authentication/languages/de.json b/bl-plugins/imap-authentication/languages/de.json new file mode 100644 index 00000000..b5218a2c --- /dev/null +++ b/bl-plugins/imap-authentication/languages/de.json @@ -0,0 +1,8 @@ +{ + "plugin-data": + { + "name": "IMAP-Authentifizierung", + "description": "Dieses Plugin ermöglicht die Authentifizierung von Benutzern mit Hilfe eines IMAP-Servers.", + "imap-server": "IMAP Server" + } +} diff --git a/bl-plugins/imap-authentication/languages/en.json b/bl-plugins/imap-authentication/languages/en.json new file mode 100644 index 00000000..7225dba2 --- /dev/null +++ b/bl-plugins/imap-authentication/languages/en.json @@ -0,0 +1,8 @@ +{ + "plugin-data": + { + "name": "IMAP Authentication", + "description": "This plugin enables the authentication of users, using an IMAP server.", + "imap-server": "IMAP Server" + } +} diff --git a/bl-plugins/imap-authentication/metadata.json b/bl-plugins/imap-authentication/metadata.json new file mode 100644 index 00000000..90994528 --- /dev/null +++ b/bl-plugins/imap-authentication/metadata.json @@ -0,0 +1,10 @@ +{ + "author": "LeineLab", + "email": "", + "website": "https://leinelab.org", + "version": "0.1.0", + "releaseDate": "2020-06-15", + "license": "MIT", + "compatible": "3.12.0", + "notes": "" +} diff --git a/bl-plugins/imap-authentication/plugin.php b/bl-plugins/imap-authentication/plugin.php new file mode 100644 index 00000000..dce7d5d6 --- /dev/null +++ b/bl-plugins/imap-authentication/plugin.php @@ -0,0 +1,137 @@ +dbFields = array( + self::IMAP_SERVER_DB_FIELD=>'', + ); + } + + public function form() + { + global $L; + + $html = ''; + + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= '
'; + + return $html; + } + + /** + * Before validating user, check if exists. + * If not and the user name is an email + * and has an IMAP account create one. + * @throws Exception + */ + public function beforeVerifyUser() + { + $username = $_POST['username']; + $password = $_POST['password']; + + if (false === filter_var($username, FILTER_VALIDATE_EMAIL)) { + return; + } + + try { + new User($username); + } catch (Exception $e) { + $this->createUser($username, $password); + } + } + + /** + * Validate user using IMAP + * @throws Exception + */ + public function afterVerifyUser() + { + $username = $_POST['username']; + $password = $_POST['password']; + + if (!$this->authenticateUser($this->getValue(self::IMAP_SERVER_DB_FIELD), $username, $password)) { + return; + } + + $user = new User($username); + + $loginClass = new login(); + $loginClass->setLogin($username, $user->role()); + Log::set(__METHOD__.LOG_SEP.'Successful user login using IMAP - Username ['.$username.']'); + } + + /** + * @param $mailbox + * @param $username User's mail address + * @param $password + * @return bool + */ + private function authenticateUser($mailbox, $username, $password) + { + if (!function_exists('imap_open')) { + Log::set(__METHOD__.LOG_SEP.'ERROR: PHP imap extension is not installed'); + } + + // Replace escaped @ symbol in uid (which is a mail address) + // but only if there is no @ symbol and if there is a %40 inside the uid + if (!(strpos($username, '@') !== false) && (strpos($username, '%40') !== false)) { + $username = str_replace("%40","@",$username); + } + + $imapConnection = @imap_open("{{$mailbox}/imap/ssl}INBOX", $username, $password, OP_HALFOPEN, 1); + $imapErrors = imap_errors(); + $imapAlerts = imap_alerts(); + if (!empty($imapErrors)) { + Log::set(__METHOD__.LOG_SEP."IMAP Error:\n".print_r($imapErrors, true)); + } + if (!empty($imapAlerts)) { + Log::set(__METHOD__.LOG_SEP."WARNING: IMAP Warning:\n".print_r($imapAlerts, true)); + } + if($imapConnection !== false) { + imap_close($imapConnection); + + return true; + } + + return false; + } + + /** + * @param $username User's mail address + * @param $password + * @throws Exception + */ + private function createUser($username, $password) + { + global $users; + + if (!$this->authenticateUser($this->getValue(self::IMAP_SERVER_DB_FIELD), $username, $password)) { + return; + } + + $usersClass = new Users(); + $usersClass->add(array( + 'username' => $username, + 'password' => '', + 'email' => $username, + 'nickname' => explode('@', $username)[0] + )); + + $users = new Users(); + + $user = new User($username); + + $loginClass = new Login(); + $loginClass->setLogin($username, $user->role()); + Log::set(__METHOD__.LOG_SEP.'Successful user creation using IMAP - Username ['.$username.']'); + } +} From 95b822f0003b86455a52d63e03778f2ff85c45b0 Mon Sep 17 00:00:00 2001 From: panigrc Date: Sun, 5 Jul 2020 22:11:00 +0200 Subject: [PATCH 2/3] Use TLS instead of SSL authentication in IMAP connection --- bl-plugins/imap-authentication/plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bl-plugins/imap-authentication/plugin.php b/bl-plugins/imap-authentication/plugin.php index dce7d5d6..47fd2f1e 100644 --- a/bl-plugins/imap-authentication/plugin.php +++ b/bl-plugins/imap-authentication/plugin.php @@ -87,7 +87,7 @@ class pluginImapAuthentication extends Plugin { $username = str_replace("%40","@",$username); } - $imapConnection = @imap_open("{{$mailbox}/imap/ssl}INBOX", $username, $password, OP_HALFOPEN, 1); + $imapConnection = @imap_open("{{$mailbox}/imap/tls}INBOX", $username, $password, OP_HALFOPEN, 1); $imapErrors = imap_errors(); $imapAlerts = imap_alerts(); if (!empty($imapErrors)) { From 44dd2435ecd9ac3bacde698d1aa19a701df3fb0f Mon Sep 17 00:00:00 2001 From: panigrc Date: Mon, 12 Oct 2020 22:53:54 +0200 Subject: [PATCH 3/3] Add dynamic selection of the TLS/SSL encryption method --- .../imap-authentication/languages/de.json | 3 ++- .../imap-authentication/languages/en.json | 3 ++- bl-plugins/imap-authentication/plugin.php | 19 +++++++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/bl-plugins/imap-authentication/languages/de.json b/bl-plugins/imap-authentication/languages/de.json index b5218a2c..9c7d8beb 100644 --- a/bl-plugins/imap-authentication/languages/de.json +++ b/bl-plugins/imap-authentication/languages/de.json @@ -3,6 +3,7 @@ { "name": "IMAP-Authentifizierung", "description": "Dieses Plugin ermöglicht die Authentifizierung von Benutzern mit Hilfe eines IMAP-Servers.", - "imap-server": "IMAP Server" + "imap-server": "IMAP Server", + "encryption": "Verschlüsselung" } } diff --git a/bl-plugins/imap-authentication/languages/en.json b/bl-plugins/imap-authentication/languages/en.json index 7225dba2..2c551de1 100644 --- a/bl-plugins/imap-authentication/languages/en.json +++ b/bl-plugins/imap-authentication/languages/en.json @@ -3,6 +3,7 @@ { "name": "IMAP Authentication", "description": "This plugin enables the authentication of users, using an IMAP server.", - "imap-server": "IMAP Server" + "imap-server": "IMAP Server", + "encryption": "Encryption" } } diff --git a/bl-plugins/imap-authentication/plugin.php b/bl-plugins/imap-authentication/plugin.php index 47fd2f1e..78754310 100644 --- a/bl-plugins/imap-authentication/plugin.php +++ b/bl-plugins/imap-authentication/plugin.php @@ -3,11 +3,13 @@ class pluginImapAuthentication extends Plugin { const IMAP_SERVER_DB_FIELD = 'imapServer'; + const IMAP_ENCRYPTION_DB_FIELD = 'imapEncryption'; public function init() { $this->dbFields = array( self::IMAP_SERVER_DB_FIELD=>'', + self::IMAP_ENCRYPTION_DB_FIELD=>'ssl', ); } @@ -24,6 +26,14 @@ class pluginImapAuthentication extends Plugin { $html .= ''; $html .= ''; + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= '
'; + return $html; } @@ -58,7 +68,7 @@ class pluginImapAuthentication extends Plugin { $username = $_POST['username']; $password = $_POST['password']; - if (!$this->authenticateUser($this->getValue(self::IMAP_SERVER_DB_FIELD), $username, $password)) { + if (!$this->authenticateUser($this->getValue(self::IMAP_SERVER_DB_FIELD), $this->getValue(self::IMAP_ENCRYPTION_DB_FIELD), $username, $password)) { return; } @@ -71,11 +81,12 @@ class pluginImapAuthentication extends Plugin { /** * @param $mailbox + * @param $encryption * @param $username User's mail address * @param $password * @return bool */ - private function authenticateUser($mailbox, $username, $password) + private function authenticateUser($mailbox, $encryption, $username, $password) { if (!function_exists('imap_open')) { Log::set(__METHOD__.LOG_SEP.'ERROR: PHP imap extension is not installed'); @@ -87,7 +98,7 @@ class pluginImapAuthentication extends Plugin { $username = str_replace("%40","@",$username); } - $imapConnection = @imap_open("{{$mailbox}/imap/tls}INBOX", $username, $password, OP_HALFOPEN, 1); + $imapConnection = @imap_open("{{$mailbox}/imap/{$encryption}}INBOX", $username, $password, OP_HALFOPEN, 1); $imapErrors = imap_errors(); $imapAlerts = imap_alerts(); if (!empty($imapErrors)) { @@ -114,7 +125,7 @@ class pluginImapAuthentication extends Plugin { { global $users; - if (!$this->authenticateUser($this->getValue(self::IMAP_SERVER_DB_FIELD), $username, $password)) { + if (!$this->authenticateUser($this->getValue(self::IMAP_SERVER_DB_FIELD), $this->getValue(self::IMAP_ENCRYPTION_DB_FIELD), $username, $password)) { return; }