httpbl.module in http:BL 6.2
Same filename and directory in other branches
Implementation of http:BL for Drupal. It provides IP-based blacklisting through http:BL and allows linking to a honeypot.
@author Mark Janssen (praseodym) @link http://drupal.org/project/httpbl @link http://httpbl.org/
File
httpbl.moduleView source
<?php
/**
* @file
* Implementation of http:BL for Drupal. It provides IP-based
* blacklisting through http:BL and allows linking to a honeypot.
*
* @author Mark Janssen (praseodym)
* @link http://drupal.org/project/httpbl
* @link http://httpbl.org/
*/
/**
*
* Version 6.x-2.x-dev
* Contact: Bryan Lewellen (bryrock) (http://drupal.org/user/346823)
*
*/
/**
*
* Version 6.x-dev
* Contact: praseodym (at) gmail (dot) com
*
* Feel free to improve this module, but please contact the author with any
* changes you make so they can be implemented into the 'official' version.
*
*/
/**
* Cache levels.
*/
define('HTTPBL_CACHE_OFF', 0);
// Cache is off
define('HTTPBL_CACHE_DB', 1);
// Only database cache
define('HTTPBL_CACHE_DBDRUPAL', 2);
// Both database cache and Drupal access table
/**
* Blacklist levels.
*/
define('HTTPBL_LIST_SAFE', 0);
// Not listed (or very low threat)
define('HTTPBL_LIST_GREY', 2);
// Greylisted: session whitelist request permitted
define('HTTPBL_LIST_BLACK', 1);
// Blacklisted: all requests blocked.
/**
* Threshold levels.
*/
define('HTTPBL_THRESHOLD_GREY', 1);
// Default threshold under which a user is allowed, above which a user is greylisted
define('HTTPBL_THRESHOLD_BLACK', 50);
// Default threshold, above which a user is blacklisted
/**
* Check levels.
*/
define('HTTPBL_CHECK_NONE', 0);
// No Checking
define('HTTPBL_CHECK_COMMENTS', 1);
// Check only comments
define('HTTPBL_CHECK_ALL', 2);
// Check all requests
/**
* Implementation of hook_menu().
*/
function httpbl_menu() {
$items['httpbl/whitelist'] = array(
'title' => 'Request whitelisting',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'httpbl_request_whitelist',
),
'access callback' => 'httpbl_whitelist_access',
'access arguments' => array(),
'type' => MENU_CALLBACK,
);
$items['admin/settings/httpbl'] = array(
'title' => 'http:BL',
'description' => 'Manage http:BL settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'httpbl_admin_settings',
),
'access arguments' => array(
'administer site configuration',
),
);
return $items;
}
/**
* Implementation of hook_boot().
*/
function httpbl_boot() {
// Only continue when checks are enabled
if (variable_get('httpbl_check', HTTPBL_CHECK_NONE) != HTTPBL_CHECK_ALL) {
return;
}
$result = httpbl_check();
if ($result) {
if ($result == HTTPBL_LIST_GREY) {
if (isset($_GET['q']) && $_GET['q'] == 'httpbl/whitelist') {
return;
}
$message = variable_get('httpbl_message_grey', 'Sorry, %ip has been greylisted by <a href="%ipurl">http:BL</a>.<br>You may try whitelisting on <a href="%whitelisturl">%whitelisturl</a>.%honeypot');
}
else {
if ($result == HTTPBL_LIST_BLACK) {
$message = variable_get('httpbl_message_black', 'Sorry, %ip has been blacklisted by <a href="%ipurl">http:BL</a>.%honeypot');
}
}
if ($link = variable_get('httpbl_link', NULL)) {
$word = variable_get('httpbl_word', 'randomness');
$link = httpbl_honeylink($link, $word);
}
$message = strtr($message, array(
'%ip' => ip_address(),
'%ipurl' => _httpbl_ipdata(ip_address(), FALSE),
'%honeypot' => $link,
'%whitelisturl' => _httpbl_url('/httpbl/whitelist'),
));
header('HTTP/1.1 403 Forbidden');
echo $message;
exit;
}
}
/**
* Implementation of hook_comment().
*/
function httpbl_comment($comment, $op) {
if (variable_get('httpbl_check', HTTPBL_CHECK_NONE) != HTTPBL_CHECK_COMMENTS) {
return;
}
switch ($op) {
case 'insert':
case 'update':
$comment = (object) $comment;
if (httpbl_check()) {
// Unpublish and inform the user.
$operation = comment_operations('unpublish');
$query = $operation['unpublish'][1];
db_query($query, $comment->cid);
drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
// Add to our statistics
if (variable_get('httpbl_stats', TRUE)) {
variable_set('httpbl_stat_comment', variable_get('httpbl_stat_comment', 0) + 1);
}
}
return;
}
}
/**
* Check if an IP should be banned
*
* @return constant: HTTP_LIST_*
*/
function httpbl_check() {
static $result;
// Result was already calculated -- return.
if (is_int($result)) {
return $result;
}
$ip = ip_address();
// $ip = '127.1.40.1'; // simulate greylist response for testing
// $ip = '127.1.80.1'; // simulate blacklist response for testing
// Check if user is whitelisted in any way
if (_httpbl_whitelisted($ip)) {
$result = HTTPBL_LIST_SAFE;
}
else {
if ($cache = variable_get('httpbl_cache', HTTPBL_CACHE_DBDRUPAL)) {
$result = _httpbl_cache_get($ip);
}
}
if (!is_numeric($result)) {
// Do a DNS lookup, and continue if lookup was succesful
if ($response = httpbl_dnslookup($ip)) {
$stats = variable_get('httpbl_stats', TRUE);
// Blacklist?
if ($response['threat'] > variable_get('httpbl_black_threshold', HTTPBL_THRESHOLD_BLACK) && $response['type']) {
if (variable_get('httpbl_log', FALSE)) {
include_once "includes/bootstrap.inc";
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// This is needed for logs to work
watchdog('httpbl', '%ip was blacklisted (%response)', array(
'%ip' => $ip,
'%response' => $response['raw'],
), WATCHDOG_WARNING, _httpbl_ipdata($ip));
}
if ($stats) {
variable_set('httpbl_stat_black', variable_get('httpbl_stat_black', 0) + 1);
}
$result = HTTPBL_LIST_BLACK;
}
else {
if ($response['threat'] > variable_get('httpbl_grey_threshold', HTTPBL_THRESHOLD_GREY) && $response['type']) {
include_once "includes/bootstrap.inc";
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// This is needed for whitelisting and logs
if (variable_get('httpbl_log', FALSE)) {
watchdog('httpbl', '%ip was greylisted (%response)', array(
'%ip' => $ip,
'%response' => $response['raw'],
), WATCHDOG_WARNING, _httpbl_ipdata($ip));
}
if ($stats) {
variable_set('httpbl_stat_grey', variable_get('httpbl_stat_grey', 0) + 1);
}
$result = HTTPBL_LIST_GREY;
}
else {
$result = HTTPBL_LIST_SAFE;
}
}
// Cache results - Use Blacklist offset settings (default 1 year)
// or Greylist offset settings (default 1 day)
if ($cache) {
if ($result == HTTPBL_LIST_BLACK) {
_httpbl_cache_set($ip, $result, variable_get('httpbl_blacklist_offset', 31536000));
}
else {
if ($result == HTTPBL_LIST_GREY) {
_httpbl_cache_set($ip, $result, variable_get('httpbl_greylist_offset', 86400));
}
}
}
}
else {
if ($cache) {
_httpbl_cache_set($ip, HTTPBL_LIST_SAFE, variable_get('httpbl_safe_offset', 10800));
}
$result = HTTPBL_LIST_SAFE;
}
}
return $result;
}
/**
* Implementation of hook_settings().
*/
function httpbl_admin_settings() {
if (!$_POST && (!variable_get('httpbl_accesskey', NULL) || !variable_get('httpbl_check', HTTPBL_CHECK_NONE))) {
drupal_set_message(t('Blacklist lookups are currently disabled; enter your access key below and enable checks to enable blacklist lookups.'), 'error');
}
$form['core'] = array(
'#type' => 'fieldset',
'#title' => t('http:BL'),
'#description' => t('For more information about http:BL, see the <a href="http://www.projecthoneypot.org/httpbl.php">http:BL homepage</a>.'),
'#collapsible' => TRUE,
);
$form['core']['httpbl_accesskey'] = array(
'#type' => 'textfield',
'#title' => t('http:BL Access Key'),
'#default_value' => variable_get('httpbl_accesskey', NULL),
'#description' => t('Your http:BL <a href="http://www.projecthoneypot.org/httpbl_configure.php">Access Key</a>.'),
'#size' => 20,
'#maxlength' => 12,
);
$form['core']['httpbl_check'] = array(
'#type' => 'radios',
'#title' => t('Blacklist checks'),
'#default_value' => variable_get('httpbl_check', HTTPBL_CHECK_NONE),
'#options' => array(
t('Disabled'),
t('Only on comment submissions'),
t('On all page requests'),
),
'#description' => t('At what times the blacklist should be checked.'),
);
$form['honeypot'] = array(
'#type' => 'fieldset',
'#title' => t('Honeypot'),
'#description' => t('Your Honeypot (spam trap) settings. For more information, see the <a href="http://www.projecthoneypot.org/">Project Honey Pot homepage</a>.'),
'#collapsible' => TRUE,
);
$form['honeypot']['httpbl_footer'] = array(
'#type' => 'checkbox',
'#title' => t('Add link to footer'),
'#default_value' => variable_get('httpbl_footer', FALSE),
'#description' => t('Whether to add your honeypot link to the footer of every page.'),
);
$form['honeypot']['httpbl_link'] = array(
'#type' => 'textfield',
'#title' => t('Honeypot link'),
'#default_value' => variable_get('httpbl_link', NULL),
'#description' => t('Your Honeypot (spam trap) link. This can be one of your <a href="http://www.projecthoneypot.org/manage_honey_pots.php">own Honey Pots</a> or a <a href="http://www.projecthoneypot.org/manage_quicklink.php">QuickLink</a>.'),
);
$form['honeypot']['httpbl_word'] = array(
'#type' => 'textfield',
'#title' => t('Link word'),
'#default_value' => variable_get('httpbl_word', 'randomness'),
'#description' => t('A random word which will be used as a link.'),
);
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['advanced']['httpbl_log'] = array(
'#type' => 'checkbox',
'#title' => t('Positive watchdog logging'),
// Not really all that verbose
'#default_value' => variable_get('httpbl_log', FALSE),
'#description' => t('Logs all positive lookups in the watchdog.'),
);
$form['advanced']['httpbl_stats'] = array(
'#type' => 'checkbox',
'#title' => t('Enable statistics'),
'#default_value' => variable_get('httpbl_stats', TRUE),
'#description' => t('Whether to enable counting of positive lookups. Statistics are show on the Drupal <a href="@statusreport">Status report page</a>.', array(
'@statusreport' => url('admin/reports/status'),
)),
);
$form['advanced']['httpbl_cache'] = array(
'#type' => 'radios',
'#title' => t('Caching'),
'#default_value' => variable_get('httpbl_cache', HTTPBL_CACHE_DBDRUPAL),
'#options' => array(
t('Off'),
t('Database cache'),
t('Database cache and Drupal access table'),
),
'#description' => t('Whether to enable database-based caching. Note that when this is disabled, IPs that fail the session whitelist test cannot be banned. The Drupal access table allows visitors to be blocked in the early stages of the bootstrap.'),
);
$blacklist_threshold_options = drupal_map_assoc(array(
50,
55,
60,
65,
70,
75,
80,
85,
90,
95,
100,
200,
255,
));
$form['advanced']['httpbl_black_threshold'] = array(
'#type' => 'select',
'#title' => t('Blacklisting Threshhold'),
'#default_value' => variable_get('httpbl_black_threshold', HTTPBL_THRESHOLD_BLACK),
'#options' => $blacklist_threshold_options,
'#description' => t('Threshold above which a user is blacklisted. Use this to fine-tune the Honeypot threat-levels for Black-listing. Note that threat levels at 100 or more effectively turns off Blacklisting (they are extremely rare). If you want to stop blacklisting altogether, set this to 255.'),
);
$form['advanced']['httpbl_message_black'] = array(
'#type' => 'textarea',
'#title' => t('Blacklist message'),
'#default_value' => variable_get('httpbl_message_black', "Sorry, %ip has been blacklisted by <a href=\"%ipurl\">http:BL</a>.\n%honeypot"),
'#description' => t("The message visitors will see when their IP is blacklisted. <em>%ip</em> will be replaced with the visitor's IP, <em>%ipurl</em> with a link to the Project Honeypot information page for that IP, <em>%honeypot</em> with your Honeypot link."),
);
$greylist_threshold_options = drupal_map_assoc(array(
1,
2,
3,
4,
5,
10,
15,
20,
25,
30,
35,
40,
45,
));
$form['advanced']['httpbl_grey_threshold'] = array(
'#type' => 'select',
'#title' => t('Greylisting Threshhold'),
'#default_value' => variable_get('httpbl_grey_threshold', HTTPBL_THRESHOLD_GREY),
'#options' => $greylist_threshold_options,
'#description' => t('Threshold at which a user is allowed, above which a user is greylisted. Use this to fine-tune the Honeypot threat-levels that you are willing to permit for access to your site.'),
);
$form['advanced']['httpbl_message_grey'] = array(
'#type' => 'textarea',
'#title' => t('Greylist message'),
'#default_value' => variable_get('httpbl_message_grey', "Sorry, %ip has been greylisted by <a href=\"%ipurl\">http:BL</a>.\nYou may try whitelisting on <a href=\"%whitelisturl\">%whitelisturl</a>.\n%honeypot"),
'#description' => t("The message visitors will see when their IP is greylisted. <em>%ip</em> will be replaced with the visitor's IP, <em>%ipurl</em> with a link to the Project Honeypot information page for that IP, <em>%honeypot</em> with your Honeypot link, <em>%whitelisturl</em> with the internal whitelist request URL."),
);
$cache_period = drupal_map_assoc(array(
10800,
21600,
32400,
43200,
86400,
172800,
259200,
604800,
1209600,
2419200,
), 'format_interval');
$form['advanced']['httpbl_safe_offset'] = array(
'#type' => 'select',
'#title' => t('Safe Visitor Cache Expires in...'),
'#default_value' => variable_get('httpbl_safe_offset', 10800),
'#options' => $cache_period,
'#description' => t('How long to keep safe or white-listed IPs in cache.'),
);
$cache_period2 = drupal_map_assoc(array(
43200,
86400,
172800,
259200,
604800,
1209600,
1814400,
2419200,
), 'format_interval');
$form['advanced']['httpbl_greylist_offset'] = array(
'#type' => 'select',
'#title' => t('Grey Listed Visitor Cache Expires in...'),
'#default_value' => variable_get('httpbl_greylist_offset', 86400),
'#options' => $cache_period2,
'#description' => t('How long to keep grey-listed IPs in cache.'),
);
$cache_period3 = drupal_map_assoc(array(
604800,
1209600,
1814400,
2419200,
7257600,
15724800,
31536000,
63072000,
94608000,
), 'format_interval');
$form['advanced']['httpbl_blacklist_offset'] = array(
'#type' => 'select',
'#title' => t('Black Listed Visitor Cache Expires in...'),
'#default_value' => variable_get('httpbl_blacklist_offset', 31536000),
'#options' => $cache_period3,
'#description' => t('How long to keep black-listed IPs in cache (and also banned in Access table, when applicable).'),
);
return system_settings_form($form);
}
/**
* Form API callback to validate the httpbl settings form.
*/
function httpbl_admin_settings_validate($form, &$form_state) {
$key = $form_state['values']['httpbl_accesskey'];
if ($form_state['values']['httpbl_check'] && !$key) {
form_set_error('httpbl_accesskey', t('You must enter an access key to enable blacklist checks.'));
}
if ($form_state['values']['httpbl_footer'] && !$form_state['values']['httpbl_link']) {
form_set_error('httpbl_link', t('You must enter a link to be able to add it to the footer.'));
}
if ($key) {
// Key should be 12 lowercase alpha characters.
// There's no unicode allowed, so we're not using drupal_strlen().
if (ereg('[^a-z]', $key) || strlen($key) != 12) {
form_set_error('httpbl_accesskey', t('Your access key is formatted incorrectly.'));
}
else {
if (!count(form_get_errors())) {
// Do a test lookup (with known result).
$lookup = httpbl_dnslookup('127.1.80.1', $key);
if (!$lookup || $lookup['threat'] != 80) {
form_set_error('httpbl_accesskey', t('Testcase failed. This either means that your access key is incorrect or that there is a problem in your DNS system.'));
}
else {
drupal_set_message('http:BL test completed successfully.');
}
}
}
}
}
/**
* Implementation of hook_footer().
*
* Adds a Project Honeypot link to the footer.
*/
function httpbl_footer($main = 0) {
if (variable_get('httpbl_footer', FALSE)) {
$link = variable_get('httpbl_link', NULL);
$word = variable_get('httpbl_word', 'randomness');
return httpbl_honeylink($link, $word);
}
}
/**
* Implementation of hook_requirements().
*
* Shows some basic usage statistics for the module.
*/
function httpbl_requirements($phase) {
$requirements = array();
if ($phase == 'runtime') {
if (!variable_get('httpbl_accesskey', NULL) || !variable_get('httpbl_check', HTTPBL_CHECK_NONE)) {
$requirements['httpbl'] = array(
'description' => t('IP blacklist lookups are currently disabled; enter your access key <a href="@settings">on the settings page</a> and enable checks to enable blacklist lookups.', array(
'@settings' => url('admin/settings/httpbl'),
)),
'severity' => REQUIREMENT_ERROR,
'value' => t('Disabled'),
);
if (variable_get('httpbl_footer', FALSE)) {
$requirements['httpbl']['severity'] = REQUIREMENT_WARNING;
}
}
else {
$stat_black = variable_get('httpbl_stat_black', 0);
$stat_comment = variable_get('httpbl_stat_comment', 0);
$stat_grey = variable_get('httpbl_stat_grey', 0);
if (!variable_get('httpbl_stats', TRUE)) {
$requirements['httpbl'] = array(
'description' => t('http:BL is enabled.'),
'severity' => REQUIREMENT_OK,
'value' => t('Enabled'),
);
}
else {
if (variable_get('httpbl_check', HTTPBL_CHECK_NONE) == HTTPBL_CHECK_COMMENTS) {
$requirements['httpbl'] = array(
'description' => t('http:BL is enabled and has blocked @c comments.', array(
'@c' => $stat_comment,
)),
'severity' => REQUIREMENT_OK,
'value' => t('Enabled'),
);
}
else {
if (variable_get('httpbl_check', HTTPBL_CHECK_NONE) == HTTPBL_CHECK_ALL) {
$requirements['httpbl'] = array(
'description' => t('http:BL is enabled and has blocked @t visits (@b blacklisted and @g greylisted).', array(
'@t' => $stat_grey + $stat_black,
'@b' => $stat_black,
'@g' => $stat_grey,
)),
'severity' => REQUIREMENT_OK,
'value' => t('Enabled'),
);
}
}
}
if (!variable_get('httpbl_footer', FALSE)) {
$requirements['httpbl']['severity'] = REQUIREMENT_WARNING;
$requirements['httpbl']['description'] .= ' ' . t('However, the honeypot link is not enabled.');
}
}
$requirements['httpbl']['title'] = t('http:BL');
}
return $requirements;
}
/**
* Implementation of hook_cron().
*
* Cleans old results from the cache table and also Drupal access table if appropriate.
*/
function httpbl_cron() {
// Only continue when caching is enabled
if (variable_get('httpbl_cache', HTTPBL_CACHE_OFF)) {
if (variable_get('httpbl_cache', HTTPBL_CACHE_OFF) == HTTPBL_CACHE_DBDRUPAL) {
// Also check status so that we do not accidentally delete the site's custom access rules.
db_query("DELETE FROM {access} WHERE mask IN (SELECT hostname FROM {httpbl} WHERE status > 0 AND expire <= %d)", time());
}
db_query("DELETE FROM {httpbl} WHERE expire <= %d", time());
}
}
/**
* Return HTML code with hidden Honeypot link
* in one of the many styles.
*
* @param string $link
* @param string $word
* @return string
*/
function httpbl_honeylink($link, $word) {
if (!$link) {
return;
}
switch (mt_rand(0, 6)) {
case 0:
return '<div><a rel="nofollow" href="' . $link . '"><!-- ' . $word . ' --></a></div>';
case 1:
return '<div><a rel="nofollow" href="' . $link . '" style="display: none;">' . $word . '</a></div>';
case 2:
return '<div style="display: none;"><a rel="nofollow" href="' . $link . '">' . $word . '</a></div>';
case 3:
return '<div><a rel="nofollow" href="' . $link . '"></a></div>';
case 4:
return '<!-- <a href="' . $link . '">' . $word . '</a> -->';
case 5:
return '<div style="position: absolute; top: -250px; left: -250px;"><a rel="nofollow" href="' . $link . '">' . $word . '</a></div>';
case 6:
return '<div><a rel="nofollow" href="' . $link . '"><span style="display: none;">' . $word . '</span></a></div>';
}
}
/**
* Check if an IP is known to belong to a search engine
*
* @param string $ip
* @return bool
*/
function httpbl_se($ip = NULL) {
if ($response = httpbl_dnslookup($ip)) {
$iplink = _httpbl_ipdata($ip);
return $response['search_engine'] === TRUE;
}
else {
return FALSE;
}
}
/**
* Reverse IP octets
*
* @param string $ip
* @return string
*/
function _httpbl_reverse_ip($ip) {
if (!is_numeric(str_replace('.', '', $ip))) {
return NULL;
}
$ip = explode('.', $ip);
if (count($ip) != 4) {
return NULL;
}
return $ip[3] . '.' . $ip[2] . '.' . $ip[1] . '.' . $ip[0];
}
/**
* Determine whether a user has access to the session whitelist functionality.
*/
function httpbl_whitelist_access() {
return httpbl_check() == HTTPBL_LIST_GREY;
}
/**
* Form to request a session whitelist.
*/
function httpbl_request_whitelist() {
$form['#redirect'] = 'node';
$form['reason'] = array(
'#type' => 'textarea',
'#title' => t('Reason you were blocked (any answer accepted)'),
'#size' => 60,
'#required' => TRUE,
);
$form['block'] = array(
'#type' => 'textfield',
'#title' => t('Leave this blank'),
'#size' => 15,
);
$form['leave'] = array(
'#type' => 'textfield',
'#size' => 30,
'#attributes' => array(
'style' => 'display: none',
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Whitelist request'),
);
return $form;
}
/**
* Validate session whitelist request.
* Ban the user if one of the 'forbidden' fields were filled.
*/
function httpbl_request_whitelist_validate($form, &$form_state) {
$ip = ip_address();
$iplink = _httpbl_ipdata($ip);
if ($form_state['values']['block'] || $form_state['values']['leave']) {
if (variable_get('httpbl_cache', HTTPBL_CACHE_OFF)) {
_httpbl_cache_update($ip, HTTPBL_LIST_BLACK, variable_get('httpbl_blacklist_offset', 31536000));
$return_date = format_interval(variable_get('httpbl_blacklist_offset', 31536000), $granularity = 2, $langcode = NULL);
watchdog('httpbl', '%ip failed session whitelist request, blacklisted for %return_date.', array(
'%ip' => $ip,
'%return_date' => $return_date,
), WATCHDOG_WARNING, $iplink);
print t('Whitelist request failed; your IP has been blacklisted for ' . $return_date . '.');
exit;
}
else {
watchdog('httpbl', '%ip failed session whitelist request.', array(
'%ip' => $ip,
), WATCHDOG_WARNING, $iplink);
print t('Whitelist request failed.');
exit;
}
}
if (variable_get('httpbl_log', FALSE)) {
watchdog('httpbl', '%ip tried a whitelist request', array(
'%ip' => $ip,
), WATCHDOG_NOTICE, $iplink);
}
}
/**
* Grant the session whitelist.
*/
function httpbl_request_whitelist_submit($form, &$form_state) {
$ip = ip_address();
$iplink = _httpbl_ipdata($ip);
watchdog('httpbl', 'Session from %ip whitelisted. Reason for block: @reason', array(
'%ip' => $ip,
'@reason' => check_plain($form_state['values']['reason']),
), WATCHDOG_WARNING, $iplink);
drupal_set_message(t('The current session has been whitelisted.'));
$_SESSION['httpbl_status'] = 'white';
drupal_goto('/');
}
/**
* Do http:BL DNS lookup
*
* @param string $ip
* @param string $key
* @return array
*/
function httpbl_dnslookup($ip, $key = NULL) {
// Thanks to J.Wesley2 at
// http://www.projecthoneypot.org/board/read.php?f=10&i=1&t=1
if (!($ip = _httpbl_reverse_ip($ip))) {
return FALSE;
}
if (!$key && !($key = variable_get('httpbl_accesskey', NULL))) {
return FALSE;
}
$query = $key . '.' . $ip . '.dnsbl.httpbl.org.';
$response = gethostbyname($query);
if ($response == $query) {
// if the domain does not resolve then it will be the same thing we passed to gethostbyname
return FALSE;
}
$values = array();
$values['raw'] = $response;
$response = explode('.', $response);
if ($response[0] != '127') {
// if the first octet is not 127, the response should be considered invalid
include_once "includes/bootstrap.inc";
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// Critically needed for logging, or else we won't know this failed!
watchdog('httpbl', 'Lookup failed for %ip, response was %response', array(
'%ip' => $ip,
'%response' => $values['raw'],
), WATCHDOG_ERROR);
return FALSE;
}
$values['last_activity'] = $response[1];
$values['threat'] = $response[2];
$values['type'] = $response[3];
if ($response[3] == 0) {
//if it's 0 then there's only one thing it can be
$values['search_engine'] = TRUE;
}
if ($response[3] & 1) {
//does it have the same bits as 1 set
$values['suspicious'] = TRUE;
}
if ($response[3] & 2) {
//does it have the same bits as 2 set
$values['harvester'] = TRUE;
}
if ($response[3] & 4) {
//does it have the same bits as 4 set
$values['comment_spammer'] = TRUE;
}
return $values;
}
/**
* Check if an IP is whitelisted through the access table or a session whitelist.
*/
function _httpbl_whitelisted($ip) {
return isset($_SESSION['httpbl_status']) && $_SESSION['httpbl_status'] == 'white' || db_result(db_query_range("SELECT status FROM {access} WHERE type = 'host' AND LOWER('%s') LIKE LOWER(mask) ORDER BY status DESC", $ip, 0, 1)) == '1';
}
/**
* Write status value into cache table
*/
function _httpbl_cache_set($ip, $status, $offset = 0) {
// http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-postgresql/6527838#6527838
db_query("UPDATE {httpbl} SET hostname= '%s', status= %d, expire= %d WHERE hostname= '%s'", $ip, $status, time() + $offset);
db_query("INSERT INTO {httpbl} (hostname, status, expire) SELECT '%s', %d, %d FROM (SELECT 1) AS foo WHERE NOT EXISTS (SELECT 1 FROM {httpbl} WHERE hostname = '%s')", $ip, $status, time() + $offset, $ip);
if ($status == HTTPBL_LIST_BLACK && variable_get('httpbl_cache', HTTPBL_CACHE_DBDRUPAL)) {
db_query("INSERT INTO {access} (mask, type, status) VALUES ('%s', '%s', %d)", $ip, 'host', 0);
}
}
/**
* Update cache table
*/
function _httpbl_cache_update($ip, $status, $offset = 0) {
db_query("UPDATE {httpbl} SET status = %d, expire = %d WHERE hostname = '%s'", $status, time() + $offset, $ip);
// Note that IP addresses will not be deleted from the {access} table, but this is currently not needed.
// TODO: check for duplicates
if ($status == HTTPBL_LIST_BLACK && variable_get('httpbl_cache', HTTPBL_CACHE_DBDRUPAL)) {
db_query("INSERT INTO {access} (mask, type, status) VALUES ('%s', '%s', %d)", $ip, 'host', 0);
}
}
/**
* Get status value from cache table
*/
function _httpbl_cache_get($ip) {
return db_result(db_query("SELECT status FROM {httpbl} WHERE hostname = '%s'", $ip));
}
/**
* Generate a link with Project Honeypot information for a given IP address.
*/
function _httpbl_ipdata($ip, $anchor = TRUE) {
if ($anchor) {
return '<a href="http://www.projecthoneypot.org/search_ip.php?ip=' . $ip . '">IP data</a>';
}
else {
return 'http://www.projecthoneypot.org/search_ip.php?ip=' . $ip;
}
}
/**
* Lightweight url function, since url() isn't available yet.
*/
function _httpbl_url($path = NULL) {
global $base_url;
$script = strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE ? 'index.php' : '';
if (variable_get('clean_url', '0')) {
return $base_url . $path;
}
else {
return $base_url . $script . '?q=' . $path;
}
}
/**
* Implementation of hook_views_api().
*/
function httpbl_views_api() {
return array(
'api' => 2,
'path' => drupal_get_path('module', 'httpbl') . '/views',
);
}
Functions
Name![]() |
Description |
---|---|
httpbl_admin_settings | Implementation of hook_settings(). |
httpbl_admin_settings_validate | Form API callback to validate the httpbl settings form. |
httpbl_boot | Implementation of hook_boot(). |
httpbl_check | Check if an IP should be banned |
httpbl_comment | Implementation of hook_comment(). |
httpbl_cron | Implementation of hook_cron(). |
httpbl_dnslookup | Do http:BL DNS lookup |
httpbl_footer | Implementation of hook_footer(). |
httpbl_honeylink | Return HTML code with hidden Honeypot link in one of the many styles. |
httpbl_menu | Implementation of hook_menu(). |
httpbl_request_whitelist | Form to request a session whitelist. |
httpbl_request_whitelist_submit | Grant the session whitelist. |
httpbl_request_whitelist_validate | Validate session whitelist request. Ban the user if one of the 'forbidden' fields were filled. |
httpbl_requirements | Implementation of hook_requirements(). |
httpbl_se | Check if an IP is known to belong to a search engine |
httpbl_views_api | Implementation of hook_views_api(). |
httpbl_whitelist_access | Determine whether a user has access to the session whitelist functionality. |
_httpbl_cache_get | Get status value from cache table |
_httpbl_cache_set | Write status value into cache table |
_httpbl_cache_update | Update cache table |
_httpbl_ipdata | Generate a link with Project Honeypot information for a given IP address. |
_httpbl_reverse_ip | Reverse IP octets |
_httpbl_url | Lightweight url function, since url() isn't available yet. |
_httpbl_whitelisted | Check if an IP is whitelisted through the access table or a session whitelist. |
Constants
Name![]() |
Description |
---|---|
HTTPBL_CACHE_DB | |
HTTPBL_CACHE_DBDRUPAL | |
HTTPBL_CACHE_OFF | Cache levels. |
HTTPBL_CHECK_ALL | |
HTTPBL_CHECK_COMMENTS | |
HTTPBL_CHECK_NONE | Check levels. |
HTTPBL_LIST_BLACK | |
HTTPBL_LIST_GREY | |
HTTPBL_LIST_SAFE | Blacklist levels. |
HTTPBL_THRESHOLD_BLACK | |
HTTPBL_THRESHOLD_GREY | Threshold levels. |