From f54e5e65c97147b29600bc377d67ebbb4013ac30 Mon Sep 17 00:00:00 2001 From: panigrc Date: Wed, 24 Jun 2020 00:49:11 +0200 Subject: [PATCH] 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.']'); + } +}