isWhite/Blacklisted(), function comments

develop
Steve Allison 2013-02-21 14:54:10 +00:00
parent b91e7aa171
commit 19c22f9164
1 changed files with 101 additions and 31 deletions

View File

@ -31,14 +31,16 @@ class defense extends rcube_plugin {
// Remote client IP address // Remote client IP address
private $ipaddr; private $ipaddr;
// Logfile
// Debug log
private $logfile = 'defense.log'; private $logfile = 'defense.log';
private $debugEnabled; private $debugEnabled;
/** /**
* Output text to log file: $this->logfile * Output text to log file: $this->logfile
* *
* @param string text for log * @param string
* text for log
*/ */
private function debug($string) { private function debug($string) {
if (!$this->debugEnabled) { return; } if (!$this->debugEnabled) { return; }
@ -48,8 +50,10 @@ class defense extends rcube_plugin {
* Check if IP is matched against all IPs in array, * Check if IP is matched against all IPs in array,
* including CIDR matches * including CIDR matches
* *
* @param string ip address * @param string
* @param array ip/cidr addresses to match against * ip address
* @param array
* ip/cidr addresses to match against
* @return bool * @return bool
*/ */
private function isIPinArray($ip, $array) { private function isIPinArray($ip, $array) {
@ -66,8 +70,10 @@ class defense extends rcube_plugin {
/** /**
* Check if IPv4 is within stated CIDR address * Check if IPv4 is within stated CIDR address
* *
* @param string ip address * @param string
* @param string cidr address * ip address
* @param string
* cidr address
* @return bool * @return bool
*/ */
private function isIPv4inCIDR($ip, $cidr) { private function isIPv4inCIDR($ip, $cidr) {
@ -77,8 +83,9 @@ class defense extends rcube_plugin {
/** /**
* Convert IPv6 mask to bytearray * Convert IPv6 mask to bytearray
* *
* @param string subnet mask * @param string
* @return string byte array * subnet mask
* @return string
*/ */
private function IPv6MaskToByteArray($subnetMask) { private function IPv6MaskToByteArray($subnetMask) {
$addr = str_repeat("f", $subnetMask / 4); $addr = str_repeat("f", $subnetMask / 4);
@ -102,8 +109,9 @@ class defense extends rcube_plugin {
/** /**
* Check if IPv6 is within stated CIDR address * Check if IPv6 is within stated CIDR address
* *
* @param string subnet mask * @param string
* @return string byte array * subnet mask
* @return bool
*/ */
private function isIPv6inCIDR($ip, $cidr) { private function isIPv6inCIDR($ip, $cidr) {
list($subnet, $mask) = explode('/', $cidr); list($subnet, $mask) = explode('/', $cidr);
@ -113,7 +121,8 @@ class defense extends rcube_plugin {
/** /**
* Check string if it is IPv6 * Check string if it is IPv6
* *
* @param string ip address * @param string
* ip address
* @return bool * @return bool
*/ */
private function isIPv6($ip) { private function isIPv6($ip) {
@ -122,7 +131,8 @@ class defense extends rcube_plugin {
/** /**
* Check string if it is IPv6 * Check string if it is IPv6
* *
* @param string ip address * @param string
* ip address
* @return bool * @return bool
*/ */
private function isIPv4($ip) { private function isIPv4($ip) {
@ -138,6 +148,39 @@ class defense extends rcube_plugin {
$this->debug($string); $this->debug($string);
write_log('error', 'plugin::defense: ' . $string); write_log('error', 'plugin::defense: ' . $string);
} }
/**
* Return true if IP matches config whitelist
*
* @param string
* ip address
* @return bool
*/
private function isWhitelisted($ip) {
$this->whitelist = $this->rc->config->get('defense_whitelist', array('127.0.0.1'));
// If IP is listed in whitelist, return true
if ($this->isIPinArray($this->ipaddr, $this->whitelist)) {
$this->debug("whitelisted");
return $true;
}
return false;
}
/**
* Return true if IP matches config blacklist
*
* @param string
* ip address
* @return bool
*/
private function isBlacklisted($ip) {
$this->blacklist = $this->rc->config->get('defense_blacklist', array());
// If IP is listed in blacklist, return true
if ($this->isIPinArray($this->ipaddr, $this->blacklist)) {
$this->debug("blacklisted");
return $true;
}
return false;
}
/** /**
* Constructor, initialization * Constructor, initialization
* *
@ -163,7 +206,7 @@ class defense extends rcube_plugin {
$this->db_expire = $this->rc->config->get('defense_db_expire', 40); $this->db_expire = $this->rc->config->get('defense_db_expire', 40);
$this->log_pwd = $this->rc->config->get('defense_log_pwd', false); $this->log_pwd = $this->rc->config->get('defense_log_pwd', false);
$this->debug_enabled = $this->rc->config->get('defense_debug_enabled', false); $this->debugEnabled = $this->rc->config->get('defense_debug_enabled', false);
// set client ip // set client ip
$this->ipaddr = rcmail_remote_ip(); $this->ipaddr = rcmail_remote_ip();
@ -180,38 +223,34 @@ class defense extends rcube_plugin {
* Hooked function: login_form($content) * Hooked function: login_form($content)
* Process whitelist and blacklist * Process whitelist and blacklist
* *
* @param string Login form HTML * @param string
* @return string Login form HTML * Login form HTML content
* @return string
* Login form HTML content
*/ */
public function hookLoginForm($content) { public function hookLoginForm($content) {
// set config variables, set defaults
$this->whitelist = $this->rc->config->get('defense_whitelist', array('127.0.0.1'));
$this->blacklist = $this->rc->config->get('defense_blacklist', array());
// If IP is listed in whitelist, return unmodified $content // If IP is listed in whitelist, return unmodified $content
if ($this->isIPinArray($this->ipaddr, $this->whitelist)) { if ($this->isWhitelisted($this->ipaddr)) {
$this->debug("whitelisted");
return $content; return $content;
} }
// If IP is listed in blacklist, deny access // If IP is listed in blacklist, deny access
if ($this->isIPinArray($this->ipaddr, $this->blacklist)) { if ($this->isBlacklisted($this->ipaddr)) {
$this->debug("blacklisted");
header('HTTP/1.1 403 Forbidden'); header('HTTP/1.1 403 Forbidden');
die(); die();
} }
$this->debug("Sending login form"); $this->debug("Sending login form");
return $content return $content;
} }
/** /**
* Hooked function: login_failed($host, $user, $code) * Hooked function: login_failed($host, $user, $code)
* Log event to database * Log event to database
* *
* @param array args [ code, host, user, abort ] * @param array
* @param int code * [code, host, user, abort]
* *
*/ */
public function hookLoginFailed($args) { public function hookLoginFailed($args) {
@ -238,7 +277,7 @@ class defense extends rcube_plugin {
$repeat = 0; $repeat = 0;
// Check if its been banned before // Check if its been banned before
$query = sprintf("SELECT epoch, data FROM %s WHERE ipaddr = '%s' AND type = %d ORDER BY id DESC LIMIT 1", $this->db_table, $this->ipaddr, 1); $query = sprintf("SELECT * FROM %s WHERE ipaddr = '%s' AND type = %d ORDER BY id DESC LIMIT 1", $this->db_table, $this->ipaddr, 1);
$result = $this->rc->db->query($query); $result = $this->rc->db->query($query);
if (!$result) { $this->dbError($query); return; } if (!$result) { $this->dbError($query); return; }
$this->debug($query . " [" . $result->rowCount() . "]"); $this->debug($query . " [" . $result->rowCount() . "]");
@ -249,7 +288,8 @@ class defense extends rcube_plugin {
$this->debug("IP previous ban data: " . $row['data']); $this->debug("IP previous ban data: " . $row['data']);
// Classed as a repeate offender if IP is banned again after the previous ban duration // Classed as a repeate offender if IP is banned again after the previous ban duration
// multiplied by <repeat_multiplier> // multiplied by <repeat_multiplier>
if (time() <= (($data['duration'] * $this->repeat_multiplier) + $row['epoch'])) { $bTime = (($data['duration'] * $this->repeat_multiplier) + $row['epoch']); // Multiply previous bantime by multiplier
if (time() <= ($bTime > $this->repeat_reset ? $bTime : $this->repeat_reset)) {
// Repeat offender, increase repeat // Repeat offender, increase repeat
$repeat = $data['repeat'] +1; $repeat = $data['repeat'] +1;
$this->debug("Repeat offender. Repeat set to " . $repeat); $this->debug("Repeat offender. Repeat set to " . $repeat);
@ -270,15 +310,45 @@ class defense extends rcube_plugin {
} }
/**
* Fetch and return last ban for $ip
*
* @param string
* ip address
* @return mixed
* Return array with record matched, or bool(false) if no match
*/
private function getPreviousBan($ip) {
$query = sprintf("SELECT * FROM %s WHERE ipaddr = '%s' AND type = %d ORDER BY id DESC LIMIT 1", $this->db_table, $ip, 1);
$result = $this->rc->db->query($query);
if (!$result) { $this->dbError($query); return; }
$this->debug($query . " [" . $result->rowCount() . "]");
return ($result->rowCount() > 0 ? $result->fetch() : false);
}
/** /**
* Hooked function: authenticate($host, $user, $cookiecheck, $valid) * Hooked function: authenticate($host, $user, $cookiecheck, $valid)
* Login attempt intercepted if IP is banned. * Login attempt intercepted if IP is banned.
* *
* @param var (untouched) * @param mixed
* @return var (untouched) * @return mixed
*/ */
public function hookAuthenticate($args) { public function hookAuthenticate($args) {
// Check whitelist/blacklist again, in case login form was bypassed somehow
// If IP is listed in whitelist, return unmodified $args
if ($this->isWhitelisted($this->ipaddr)) {
return $args;
}
// If IP is listed in blacklist, deny access
if ($this->isBlacklisted($this->ipaddr)) {
header('HTTP/1.1 403 Forbidden');
die();
}
$this->debug("Login form submitted, username: " . $args['user']);
return $args; return $args;
} }