Upgrade
=======

Option "-e" added in ibd-ban invocations, implying suitable configuration
of /etc/ipqbdb-connkill.cmd.


Apache Authentication
=====================

Apache can run custom PHP scripts for various error codes.  Authentication is
related to response code 401, thus you may have your script invoked by setting

	ErrorDocument 401 /my_401_handler.php

along with directives like Require, AuthType, etcetera.  The handler code may
be like in the following snippet, if PHP runs as an Apache module.

-----8<-----
<?php

function first_of($ar)
{
	foreach ($ar as $i)
		if (!empty($_SERVER[$i]))
			return $_SERVER[$i];
	return '';
}

	header('Status: 401 Authorization Required');

	$adjective = 'Required';
	$user = 'Unknown';
	$do_ban = 0;

	# PHP sets these when the client sends an 'Authorization' header,
	# so the user is trying a password (as opposed to just hitting cancel)
	if (isset($_SERVER['PHP_AUTH_DIGEST']))
	{
		$data = array();
		$matches = array();
		preg_match_all('/(\w+)=(?:(?>"((?>[^"\\\\]|\\\\.)+)")|([^"\s,=]+))/',
			$_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);

		foreach ($matches as $m)
			$data[strtolower($m[1])] =
				empty($m[3])? preg_replace('/\\\\(.)/', '$1', $m[2]): $m[3];

		if (isset($data['username']) && isset($data['response']))
		{
			$do_ban = 1;
			$user = $data['username'];
		}
	}
	else if (isset($_SERVER['PHP_AUTH_USER']) &&
		isset($_SERVER['PHP_AUTH_PW']))
	{
		$do_ban = 1;
		$user = $_SERVER['PHP_AUTH_USER'];
	}
	
	if ($do_ban)
	{
		$adjective = 'Failed';
		$msg = 'Failed access to '.
			first_of(array('REDIRECT_SCRIPT_URI', 'SCRIPT_URI',
				'REDIRECT_SCRIPT_URL', 'SCRIPT_URL', 'SERVER_NAME')) .
			' by '. $user;

		$addr = first_of(array('REDIRECT_REMOTE_ADDR', 'REMOTE_ADDR'));			
		if (!empty($addr))
		{
			$msg .= ' at '. $addr;
			$rtc = 0;
			$nu = array();
			exec("/usr/local/bin/ibd-ban -e -i ". $addr .
				" --reason=\"Apache login\" --log-syslog",
				$nu,
				$rtc);
			$msg .= " ibd-ban rtc: $rtc";
		}
		syslog(LOG_AUTH|LOG_WARNING, $msg);
	}

	echo '<html><head><title>401 Authorization '. $adjective .'</title></head>'.
		'<body><h1>401 Authorization '. $adjective .'</h1>';

	if ($do_ban)
		echo '<p>Failed attempt from user '. $user .' has been logged.</p>';
	else
		echo '<p>Please submit credentials.</p>';

	echo '<p>'.
		first_of(array('SERVER_ADMIN', 'SERVER_SIGNATURE', 'SERVER_NAME'));
	echo '</p></body></html>';
?>
----->8-----


MediaWiki
=========

Add the following snippet near the end of your LocalSettings.php

-----8<-----
# catch dictionary attacks
function myBanDictionaryAttack($user, $passwd, $retval)
{
        if ($retval && isset($_SERVER['REMOTE_ADDR']))
        {
                $msg = "wiki user ".
                        $user->GetName() ." rtc: $retval from ".
                        $_SERVER['REMOTE_ADDR'];
                if ($retval != LoginForm::SUCCESS ||
                        $retval != LoginForm::RESET_PASS ||
                        $retval != LoginForm::ABORTED)
                {
                        $rtc = 0;
                        $nu = array();
                        exec("/usr/local/bin/ibd-ban -e -i ".
                                $_SERVER['REMOTE_ADDR']
                                ." --reason=\"my wiki login\" --log-syslog",
                                $nu,
                                $rtc);
                        $msg .= " ibd-ban rtc: $rtc";
                }
                syslog(LOG_AUTH|LOG_WARNING, $msg);
        }
        return true;
}

$wgHooks['LoginAuthenticateAudit'][] = 'myBanDictionaryAttack';
----->8-----
