From aa523eadf183c78a43864af710891afaeb57d91a Mon Sep 17 00:00:00 2001 From: Patrick Webster Date: Mon, 16 Jan 2023 17:23:24 -0600 Subject: [PATCH] [ticket/17092] Check for Spamhaus error codes Switches to using callbacks for each DNSBL so that special cases can be handled when needed. Adds support for Spamhaus error codes and disables DNSBL checking if errors are encountered since they probably won't be resolved in a timely manner by the owner or host. PHPBB3-17092 --- phpBB/language/en/acp/common.php | 4 ++ phpBB/phpbb/session.php | 115 +++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 64096bbed3..1bc0cf11af 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -738,6 +738,10 @@ $lang = array_merge($lang, array( 'LOG_SEARCH_INDEX_CREATED' => 'Created search index for
» %s', 'LOG_SEARCH_INDEX_REMOVED' => 'Removed search index for
» %s', 'LOG_SPHINX_ERROR' => 'Sphinx Error
» %s', + + 'LOG_SPAMHAUS_OPEN_RESOLVER' => 'Spamhaus does not allow queries using an open resolver. Blacklist checking has been disabled. For more information, see https://www.spamhaus.com/product/help-for-spamhaus-public-mirror-users/.', + 'LOG_SPAMHAUS_VOLUME_LIMIT' => 'Spamhaus query volume limit has been exceeded. Blacklist checking has been disabled. For more information, see https://www.spamhaus.com/product/help-for-spamhaus-public-mirror-users/.', + 'LOG_STYLE_ADD' => 'Added new style
» %s', 'LOG_STYLE_DELETE' => 'Deleted style
» %s', 'LOG_STYLE_EDIT_DETAILS' => 'Edited style
» %s', diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 6f25d3b650..0e016962bd 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1346,6 +1346,110 @@ class session } } + /** + * Check if ip is blacklisted by Spamhaus SBL + * + * Disables DNSBL setting if errors are returned by Spamhaus due to a policy violation. + * https://www.spamhaus.com/product/help-for-spamhaus-public-mirror-users/ + * + * @param string $dnsbl the blacklist to check against + * @param string|false $ip the IPv4 address to check + * + * @return true if listed in spamhaus database + */ + function check_dnsbl_spamhaus($dnsbl, $ip = false) + { + global $config, $phpbb_log; + + if ($ip === false) + { + $ip = $this->ip; + } + + // Spamhaus does not support IPv6 addresses. + if (strpos($ip, ':') !== false) + { + return false; + } + + if ($ip) + { + $quads = explode('.', $ip); + $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0]; + + $records = dns_get_record($reverse_ip . '.' . $dnsbl . '.', DNS_A); + if ($records === false || empty($records)) + { + return false; + } + else + { + $error = false; + foreach ($records as $record) + { + if ($record['ip'] == '127.255.255.254') + { + $error = 'LOG_SPAMHAUS_OPEN_RESOLVER'; + break; + } + else if ($record['ip'] == '127.255.255.255') + { + $error = 'LOG_SPAMHAUS_VOLUME_LIMIT'; + break; + } + } + + if ($error !== false) + { + echo 'Error encountered
'; + $config->set('check_dnsbl', 0); + $phpbb_log->add('critical', $this->data['user_id'], $ip, $error); + } + else + { + // The existence of a non-error A record means it's a hit + return true; + } + } + } + + return false; + } + + /** + * Checks if an IPv4 address is in a specified DNS blacklist + * + * Only checks if a record is returned or not. + * + * @param string $dnsbl the blacklist to check against + * @param string|false $ip the IPv4 address to check + * + * @return true if record is returned + */ + function check_dnsbl_ipv4_generic($dnsbl, $ip = false) + { + if ($ip === false) + { + $ip = $this->ip; + } + + // This function does not support IPv6 addresses. + if (strpos($ip, ':') !== false) + { + return false; + } + + $quads = explode('.', $ip); + $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0]; + + if (checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true) + { + return true; + } + + return false; + } + /** * Check if ip is blacklisted * This should be called only where absolutely necessary @@ -1372,28 +1476,25 @@ class session } $dnsbl_check = array( - 'sbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=', + 'sbl.spamhaus.org' => ['http://www.spamhaus.org/query/bl?ip=', 'check_dnsbl_spamhaus'], ); if ($mode == 'register') { - $dnsbl_check['bl.spamcop.net'] = 'http://spamcop.net/bl.shtml?'; + $dnsbl_check['bl.spamcop.net'] = ['http://spamcop.net/bl.shtml?', 'check_dnsbl_ipv4_generic']; } if ($ip) { - $quads = explode('.', $ip); - $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0]; - // Need to be listed on all servers... $listed = true; $info = array(); foreach ($dnsbl_check as $dnsbl => $lookup) { - if (checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true) + if (call_user_func(array($this, $lookup[1]), $dnsbl, $ip) === true) { - $info = array($dnsbl, $lookup . $ip); + $info = array($dnsbl, $lookup[0] . $ip); } else {