Skip to content

Commit

Permalink
Update to 1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
san4op committed Jul 20, 2017
1 parent 103f773 commit a18af7c
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 93 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGELOG
=========

RELEASE 1.3
-----------
* Configuration moved to local config.inc.php.
* Added global list: use * (asterisk) as username.
* Small refactoring.
* Update translations.

RELEASE 1.2
-----------
* Rename plugin
Expand Down
30 changes: 4 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
Login Control (Roundcube Webmail Plugin)
==========

========================================
Plugin to add whitelist and blacklist for login.

Configuration Options
---------------------

Set the following options directly in Roundcube's config file (example):
```php
$config['login_control_mode'] = 'whitelist';
$config['login_control_list'] = array(
'[email protected]' => array(
'192.0.2.74',
'192.0.2.212',
'198.51.100.12/30',
),
'[email protected]' => array(
'198.51.100.1',
'198.51.100.1',
'198.51.100.12/30',
),
);
```

Translation
-----------

https://www.transifex.com/san4op/roundcube-login-control-plugin/
Configuration
-------------
Rename config.inc.php.dist to config.inc.php and edit it.
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"description": "Plugin to add whitelist and blacklist for login.",
"keywords": ["login", "control", "restriction", "whitelist", "blacklist"],
"homepage": "https://github.com/san4op/roundcube_login_control",
"license": "GPL-3.0+",
"version": "1.2",
"license": "GPL-3.0",
"version": "1.3",
"authors": [
{
"name": "Alexander Pushkin",
"email": "[email protected]",
"homepage": "https://github.com/san4op",
"homepage": "https://github.com/san4op/",
"role": "Developer"
}
],
Expand All @@ -29,4 +29,4 @@
"min-version": "1.0.0"
}
}
}
}
13 changes: 11 additions & 2 deletions config.inc.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@
// List mode: 'whitelist' or 'blacklist'
$config['login_control_mode'] = 'whitelist';

// List of IP addresses
// Format: array(username => array(IPs, NETWORKs, ...), ...)
// List of IPV4 addresses
// Format:
// array(
// 'username' => 'IPV4 or NETWORK',
// 'username' => array(
// 'IPV4 or NETWORK',
// 'IPV4 or NETWORK',
// ...
// ),
// ...
// )
$config['login_control_list'] = array();

?>
7 changes: 7 additions & 0 deletions config.inc.php.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

$config['login_control_mode'] = 'whitelist';
$config['login_control_list'] = array(
'*' => array(
'10.11.12.0/26',
'172.16.33.0/16',
),
'[email protected]' => array(
'192.0.2.74',
'192.0.2.212',
Expand All @@ -15,6 +19,9 @@ $config['login_control_list'] = array(
'198.51.100.1',
'198.51.100.12/30',
),
'[email protected]' => '192.168.0.0/24',
'[email protected]' => '192.168.0.0/24',
'[email protected]' => '192.168.0.0/24',
);

?>
4 changes: 2 additions & 2 deletions localization/en_US.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

$labels = array();
$labels['access_restricted'] = 'Access from this IP address for this user denied!';
$messages = array();
$messages['access_restricted'] = 'Access from your IP-address $ipaddr is denied!';

?>
4 changes: 2 additions & 2 deletions localization/ru_RU.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

$labels = array();
$labels['access_restricted'] = 'Доступ с данного IP адреса для указанного пользователя запрещен!';
$messages = array();
$messages['access_restricted'] = 'Доступ с вашего IP-адреса $ipaddr запрещен!';

?>
18 changes: 11 additions & 7 deletions login_control.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/**
* Login Control plugin script
* Roundcube Plugin Login Control
* Plugin to add whitelist and blacklist for login.
*
* @version 1.2
* @version 1.3
* @author Alexander Pushkin
* @url https://github.com/san4op/roundcube_login_control
* @licence GNU GPLv3
* @copyright Copyright (c) 2017, Alexander Pushkin
* @link https://github.com/san4op/roundcube_login_control
* @license GNU General Public License, version 3
*/

rcmail.addEventListener('plugin.access_restricted', function(response){
rcmail.command('logout');
});
if (window.rcmail) {
rcmail.addEventListener('plugin.access_restricted', function(response) {
rcmail.command('switch-task', 'logout');
});
}
2 changes: 1 addition & 1 deletion login_control.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

142 changes: 93 additions & 49 deletions login_control.php
Original file line number Diff line number Diff line change
@@ -1,114 +1,158 @@
<?php
/**
* Login Control
*
* Roundcube Plugin Login Control
* Plugin to add whitelist and blacklist for login.
*
* @date 2017-04-03
* @version 1.2
* @version 1.3
* @author Alexander Pushkin
* @url https://github.com/san4op/roundcube_login_control
* @licence GNU GPLv3
* @copyright Copyright (c) 2017, Alexander Pushkin
* @link https://github.com/san4op/roundcube_login_control
* @license GNU General Public License, version 3
*/

define('IPADDR_REGEXP', '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-2]?[0-9]|3[0-2]))?$');

class login_control extends rcube_plugin
{
private $rcmail;
private $rc;
private $mode = 'whitelist';
private $list = array();
private $username;
private $ipaddr;

function init()
public function init()
{
$this->rcmail = rcube::get_instance();
$this->mode = $this->rcmail->config->get('login_control_mode', 'whitelist');
$this->list = $this->rcmail->config->get('login_control_list', array());
$this->rc = rcube::get_instance();
$this->username = $this->rc->user->get_username();
$this->ipaddr = rcube_utils::remote_addr();

// load config
$this->load_config();
$this->mode = $this->rc->config->get('login_control_mode', 'whitelist');
$this->list = $this->rc->config->get('login_control_list', array());

if ($this->mode != 'whitelist' && $this->mode != 'blacklist') {
$this->mode = 'whitelist';
}

$this->add_texts('localization/', true);
// load localization
$this->add_texts('localization/');

$this->add_hook('refresh', array($this, 'refresh'));

if ($this->rcmail->task == 'login') {
$this->add_hook('authenticate', array($this, 'authenticate'));
// include scripts
if ($this->rc->task != 'login' && $this->rc->task != 'logout') {
$this->include_script('login_control.js');
}

if ($this->rcmail->task == 'logout') {
$this->add_hook('logout_after', array($this, 'logout_after'));
}

if (!preg_match('/^(login|logout)$/i', $this->rcmail->task)) {
$this->include_script('login_control.min.js');
}
// add hooks
$this->add_hook('ready', array($this, 'page_ready'));
$this->add_hook('authenticate', array($this, 'user_login'));
$this->add_hook('session_destroy', array($this, 'user_logout'));
}

function refresh($args)
public function page_ready($args)
{
$username = $this->rcmail->user->get_username();

if (!empty($username) && !$this->check($username)) {
$this->rcmail->session->write('access_restricted', '1');
$this->rcmail->write_log('userlogins', sprintf("Login Control: access denied for %s from %s.", $username, rcube_utils::remote_addr()));
$this->rcmail->output->command('plugin.access_restricted');
if (!$this->check($this->username)) {
$this->rc->session->write('login_control.access_restricted', '1');
$this->rc->write_log('userlogins', sprintf("Login Control: access denied for %s from %s.", $this->username, $this->ipaddr));
if ($this->rc->output->ajax_call) {
$this->rc->output->command('plugin.access_restricted');
} else {
header('Location: '.$this->rc->url(array('task' => 'logout'), false, false, true));
}
}

return $args;
}

function authenticate($args)
public function user_login($args)
{
if (!$this->check($args['user'])) {
$this->rcmail->write_log('userlogins', sprintf("Login Control: access denied for %s from %s.", $args['user'], rcube_utils::remote_addr()));
$this->rc->write_log('userlogins', sprintf("Login Control: access denied for %s from %s.", $args['user'], $this->ipaddr));
$args['abort'] = true;
$args['error'] = $this->gettext('access_restricted');
$args['error'] = $this->gettext(array('name' => 'access_restricted', 'vars' => array('ipaddr' => $this->ipaddr)));
}

return $args;
}

function logout_after($args)
public function user_logout($args)
{
if ($this->rcmail->session->read('access_restricted') == '1') {
$this->rcmail->session->destroy('access_restricted');
if (!$this->check($args['user'])) {
$this->rcmail->output->show_message($this->gettext('access_restricted'), 'warning');
if ($this->rc->session->read('login_control.access_restricted') == '1') {
$this->rc->session->destroy('login_control.access_restricted');
if (!$this->check($this->username)) {
$this->rc->output->show_message($this->gettext(array('name' => 'access_restricted', 'vars' => array('ipaddr' => $this->ipaddr))), 'warning', null, true, 600);
}
}

return $args;
}

/**
* Check if given username in white/blacklist
* @param string $username Username to check
* @return boolean For non-blocked users return True, otherwise False
*/
private function check($username)
{
if (empty($username) || !is_string($username)) {
return true;
}

if (isset($this->list[$username]) && !empty($this->list[$username])) {
if (isset($this->list['*']) && !empty($this->list['*']) || isset($this->list[$username]) && !empty($this->list[$username])) {
$found = false;
$user_ip = rcube_utils::remote_addr();
$user_list =& $this->list[$username];

// get global list
$user_list = (isset($this->list['*']) ? $this->list['*'] : array());

// check format of list
if (!is_string($user_list) && !is_array($user_list)) {
rcmail::raise_error(array(
'code' => 600, 'type' => 'php',
'line' => __LINE__, 'file' => __FILE__,
'message' => 'Login Control plugin: Invalid format of list of IP addresses for all users, must be string or array.'), true, false);
$user_list = array();
}

// check and append a list for user specified
if (isset($this->list[$username])) {
// check format of list
if (!is_string($this->list[$username]) && !is_array($this->list[$username])) {
rcmail::raise_error(array(
'code' => 600, 'type' => 'php',
'line' => __LINE__, 'file' => __FILE__,
'message' => 'Login Control plugin: Invalid format of list of IP addresses for '.$username.', must be string or array.'), true, false);
$this->list[$username] = array();
}

// append a list
$user_list = array_merge((is_string($user_list) ? array($user_list) : $user_list), (is_string($this->list[$username]) ? array($this->list[$username]) : $this->list[$username]));
}

// for string format
if (is_string($user_list)) {
if (preg_match('/'.IPADDR_REGEXP.'/', $user_list) && $this->ip_in_range($user_ip, $user_list)) {
if (preg_match('/'.IPADDR_REGEXP.'/', $user_list) && $this->ip_in_range($this->ipaddr, $user_list)) {
$found = true;
}
}

// for array format
elseif (is_array($user_list)) {
for ($i=0,$a=count($user_list); $i<$a; $i++) {
if (preg_match('/'.IPADDR_REGEXP.'/', $user_list[$i]) && $this->ip_in_range($user_ip, $user_list[$i])) {
if (!is_string($user_list[$i])) {
rcmail::raise_error(array(
'code' => 600, 'type' => 'php',
'line' => __LINE__, 'file' => __FILE__,
'message' => 'Login Control plugin: Invalid format of list of IP addresses, must be string.'), true, false);
break;
}
if (preg_match('/'.IPADDR_REGEXP.'/', $user_list[$i]) && $this->ip_in_range($this->ipaddr, $user_list[$i])) {
$found = true;
break;
}
}
}

if ($this->mode == 'whitelist') {
return $found;
}
elseif ($this->mode == 'blacklist') {
return !$found;
}
return ($this->mode == 'blacklist' ? !$found : $found);
}

return true;
Expand Down

0 comments on commit a18af7c

Please sign in to comment.