2007-04-16 11:58:25 +00:00
< ? php
2009-08-20 22:37:17 +00:00
/*
2008-04-11 06:12:07 +00:00
* Name : IP Ban
* Author : Shish < webmaster @ shishnet . org >
2012-02-08 02:52:11 +00:00
* Link : http :// code . shishnet . org / shimmie2 /
2008-04-11 06:12:07 +00:00
* License : GPLv2
* Description : Ban IP addresses
2009-01-16 08:18:41 +00:00
* Documentation :
* < b > Adding a Ban </ b >
* < br > IP : Can be a single IP ( eg . 123.234 . 210.21 ), or a CIDR block ( eg . 152.23 . 43.0 / 24 )
* < br > Reason : Any text , for the admin to remember why the ban was put in place
* < br > Until : Either a date in YYYY - MM - DD format , or an offset like " 3 days "
2008-04-11 06:12:07 +00:00
*/
2007-04-16 11:58:25 +00:00
// RemoveIPBanEvent {{{
class RemoveIPBanEvent extends Event {
2007-10-21 23:31:23 +00:00
var $id ;
2007-04-16 11:58:25 +00:00
2014-03-22 09:00:59 +00:00
public function __construct ( $id ) {
2007-10-21 23:31:23 +00:00
$this -> id = $id ;
2007-04-16 11:58:25 +00:00
}
}
// }}}
// AddIPBanEvent {{{
2009-01-04 19:18:37 +00:00
class AddIPBanEvent extends Event {
2007-04-16 11:58:25 +00:00
var $ip ;
var $reason ;
2007-05-28 23:22:37 +00:00
var $end ;
2007-04-16 11:58:25 +00:00
2014-03-22 09:00:59 +00:00
public function __construct ( /*string(ip)*/ $ip , /*string*/ $reason , /*string*/ $end ) {
2012-07-28 10:42:07 +00:00
$this -> ip = trim ( $ip );
$this -> reason = trim ( $reason );
$this -> end = trim ( $end );
2007-04-16 11:58:25 +00:00
}
}
// }}}
2012-02-08 12:07:01 +00:00
class IPBan extends Extension {
2012-01-27 18:16:46 +00:00
public function get_priority () { return 10 ;}
2012-02-08 11:24:25 +00:00
public function onInitExt ( InitExtEvent $event ) {
2012-01-30 02:24:22 +00:00
global $config ;
2012-07-28 10:59:11 +00:00
if ( $config -> get_int ( " ext_ipban_version " ) < 8 ) {
2012-01-30 02:24:22 +00:00
$this -> install ();
2007-04-16 11:58:25 +00:00
}
2012-01-30 02:24:22 +00:00
$this -> check_ip_ban ();
}
2007-04-16 11:58:25 +00:00
2012-02-08 11:24:25 +00:00
public function onPageRequest ( PageRequestEvent $event ) {
2012-01-30 02:24:22 +00:00
if ( $event -> page_matches ( " ip_ban " )) {
global $config , $database , $page , $user ;
2012-03-31 11:28:34 +00:00
if ( $user -> can ( " ban_ip " )) {
2010-05-28 13:26:46 +00:00
if ( $event -> get_arg ( 0 ) == " add " && $user -> check_auth_token ()) {
2007-05-28 23:22:37 +00:00
if ( isset ( $_POST [ 'ip' ]) && isset ( $_POST [ 'reason' ]) && isset ( $_POST [ 'end' ])) {
2007-07-24 13:25:11 +00:00
if ( empty ( $_POST [ 'end' ])) $end = null ;
else $end = $_POST [ 'end' ];
send_event ( new AddIPBanEvent ( $_POST [ 'ip' ], $_POST [ 'reason' ], $end ));
2007-04-16 11:58:25 +00:00
2012-06-10 16:49:17 +00:00
flash_message ( " Ban for { $_POST [ 'ip' ] } added " );
2009-05-11 14:04:33 +00:00
$page -> set_mode ( " redirect " );
$page -> set_redirect ( make_link ( " ip_ban/list " ));
2007-04-16 11:58:25 +00:00
}
}
2010-05-28 13:26:46 +00:00
else if ( $event -> get_arg ( 0 ) == " remove " && $user -> check_auth_token ()) {
2007-10-21 23:31:23 +00:00
if ( isset ( $_POST [ 'id' ])) {
send_event ( new RemoveIPBanEvent ( $_POST [ 'id' ]));
2012-06-10 16:49:17 +00:00
flash_message ( " Ban removed " );
2009-05-11 14:04:33 +00:00
$page -> set_mode ( " redirect " );
$page -> set_redirect ( make_link ( " ip_ban/list " ));
2007-04-16 11:58:25 +00:00
}
}
2008-04-11 05:23:11 +00:00
else if ( $event -> get_arg ( 0 ) == " list " ) {
2009-01-17 04:40:51 +00:00
$bans = ( isset ( $_GET [ " all " ])) ? $this -> get_bans () : $this -> get_active_bans ();
2009-05-11 14:04:33 +00:00
$this -> theme -> display_bans ( $page , $bans );
2008-04-11 05:23:11 +00:00
}
}
2008-10-18 06:05:26 +00:00
else {
2012-02-15 08:59:24 +00:00
$this -> theme -> display_permission_denied ();
2008-10-18 06:05:26 +00:00
}
2008-04-11 05:23:11 +00:00
}
2012-01-30 02:24:22 +00:00
}
2008-04-11 05:23:11 +00:00
2012-02-08 11:24:25 +00:00
public function onUserBlockBuilding ( UserBlockBuildingEvent $event ) {
2012-01-30 02:24:22 +00:00
global $user ;
2012-03-30 19:54:33 +00:00
if ( $user -> can ( " ban_ip " )) {
2012-01-30 02:24:22 +00:00
$event -> add_link ( " IP Bans " , make_link ( " ip_ban/list " ));
2007-04-16 11:58:25 +00:00
}
2012-01-30 02:24:22 +00:00
}
2007-04-16 11:58:25 +00:00
2012-02-08 11:24:25 +00:00
public function onAddIPBan ( AddIPBanEvent $event ) {
2012-06-10 16:49:17 +00:00
global $user , $database ;
$sql = " INSERT INTO bans (ip, reason, end_timestamp, banner_id) VALUES (:ip, :reason, :end, :admin_id) " ;
$database -> Execute ( $sql , array ( " ip " => $event -> ip , " reason " => $event -> reason , " end " => strtotime ( $event -> end ), " admin_id " => $user -> id ));
$database -> cache -> delete ( " ip_bans_sorted " );
log_info ( " ipban " , " Banned { $event -> ip } because ' { $event -> reason } ' until { $event -> end } " );
2012-01-30 02:24:22 +00:00
}
2007-04-16 11:58:25 +00:00
2012-02-08 11:24:25 +00:00
public function onRemoveIPBan ( RemoveIPBanEvent $event ) {
2012-01-30 02:24:22 +00:00
global $database ;
2012-06-10 16:49:17 +00:00
$ban = $database -> get_row ( " SELECT * FROM bans WHERE id = :id " , array ( " id " => $event -> id ));
if ( $ban ) {
$database -> Execute ( " DELETE FROM bans WHERE id = :id " , array ( " id " => $event -> id ));
$database -> cache -> delete ( " ip_bans_sorted " );
log_info ( " ipban " , " Removed { $ban [ 'ip' ] } 's ban " );
}
2007-04-16 11:58:25 +00:00
}
2012-01-30 02:24:22 +00:00
2007-04-16 11:58:25 +00:00
// installer {{{
protected function install () {
global $database ;
global $config ;
2009-01-04 19:18:37 +00:00
2008-05-18 02:17:16 +00:00
// shortcut to latest
if ( $config -> get_int ( " ext_ipban_version " ) < 1 ) {
2009-01-22 12:05:55 +00:00
$database -> create_table ( " bans " , "
id SCORE_AIPK ,
banner_id INTEGER NOT NULL ,
ip SCORE_INET NOT NULL ,
end_timestamp INTEGER ,
reason TEXT NOT NULL ,
INDEX ( end_timestamp )
2008-05-18 02:17:16 +00:00
" );
2008-09-07 04:52:40 +00:00
$config -> set_int ( " ext_ipban_version " , 6 );
2008-05-18 02:17:16 +00:00
}
// ===
if ( $config -> get_int ( " ext_ipban_version " ) < 1 ) {
$database -> Execute ( " CREATE TABLE bans (
id int ( 11 ) NOT NULL auto_increment ,
ip char ( 15 ) default NULL ,
2014-03-02 18:50:46 +00:00
date SCORE_DATETIME default NULL ,
end SCORE_DATETIME default NULL ,
2008-05-18 02:17:16 +00:00
reason varchar ( 255 ) default NULL ,
PRIMARY KEY ( id )
) " );
$config -> set_int ( " ext_ipban_version " , 1 );
}
if ( $config -> get_int ( " ext_ipban_version " ) == 1 ) {
$database -> execute ( " ALTER TABLE bans ADD COLUMN banner_id INTEGER NOT NULL AFTER id " );
$config -> set_int ( " ext_ipban_version " , 2 );
}
if ( $config -> get_int ( " ext_ipban_version " ) == 2 ) {
$database -> execute ( " ALTER TABLE bans DROP COLUMN date " );
$database -> execute ( " ALTER TABLE bans CHANGE ip ip CHAR(20) NOT NULL " );
$database -> execute ( " ALTER TABLE bans CHANGE reason reason TEXT NOT NULL " );
$database -> execute ( " CREATE INDEX bans__end ON bans(end) " );
$config -> set_int ( " ext_ipban_version " , 3 );
2007-10-21 23:31:23 +00:00
}
2008-05-18 03:32:28 +00:00
if ( $config -> get_int ( " ext_ipban_version " ) == 3 ) {
$database -> execute ( " ALTER TABLE bans CHANGE end old_end DATE NOT NULL " );
$database -> execute ( " ALTER TABLE bans ADD COLUMN end INTEGER " );
$database -> execute ( " UPDATE bans SET end = UNIX_TIMESTAMP(old_end) " );
$database -> execute ( " ALTER TABLE bans DROP COLUMN old_end " );
$database -> execute ( " CREATE INDEX bans__end ON bans(end) " );
$config -> set_int ( " ext_ipban_version " , 4 );
}
2008-07-25 11:30:47 +00:00
if ( $config -> get_int ( " ext_ipban_version " ) == 4 ) {
$database -> execute ( " ALTER TABLE bans CHANGE end end_timestamp INTEGER " );
$config -> set_int ( " ext_ipban_version " , 5 );
}
2008-09-07 04:52:40 +00:00
if ( $config -> get_int ( " ext_ipban_version " ) == 5 ) {
$database -> execute ( " ALTER TABLE bans CHANGE ip ip VARCHAR(15) " );
$config -> set_int ( " ext_ipban_version " , 6 );
}
2012-03-11 01:04:25 +00:00
if ( $config -> get_int ( " ext_ipban_version " ) == 6 ) {
2012-03-11 01:52:25 +00:00
$database -> Execute ( " ALTER TABLE bans ADD FOREIGN KEY (banner_id) REFERENCES users(id) ON DELETE CASCADE " );
2012-03-11 01:04:25 +00:00
$config -> set_int ( " ext_ipban_version " , 7 );
}
2012-07-28 10:56:55 +00:00
if ( $config -> get_int ( " ext_ipban_version " ) == 7 ) {
$database -> execute ( $database -> scoreql_to_sql ( " ALTER TABLE bans CHANGE ip ip SCORE_INET " ));
$database -> execute ( $database -> scoreql_to_sql ( " ALTER TABLE bans ADD COLUMN added SCORE_DATETIME NOT NULL DEFAULT SCORE_NOW " ));
$config -> set_int ( " ext_ipban_version " , 8 );
}
2007-04-16 11:58:25 +00:00
}
// }}}
// deal with banned person {{{
private function check_ip_ban () {
2012-01-27 11:04:50 +00:00
$remote = $_SERVER [ 'REMOTE_ADDR' ];
$bans = $this -> get_active_bans_sorted ();
// bans[0] = IPs
if ( isset ( $bans [ 0 ][ $remote ])) {
$this -> block ( $remote ); // never returns
}
// bans[1] = CIDR nets
foreach ( $bans [ 1 ] as $ip => $true ) {
if ( ip_in_range ( $remote , $ip )) {
$this -> block ( $remote ); // never returns
}
}
}
2012-02-08 11:24:25 +00:00
private function block ( /*string*/ $remote ) {
2012-01-27 11:04:50 +00:00
global $config , $database ;
2007-04-16 11:58:25 +00:00
2012-06-23 23:57:55 +00:00
$prefix = ( $database -> get_driver_name () == " sqlite " ? " bans. " : " " );
2009-07-17 01:43:57 +00:00
2008-03-31 02:49:40 +00:00
$bans = $this -> get_active_bans ();
2012-01-27 11:04:50 +00:00
2008-03-31 02:49:40 +00:00
foreach ( $bans as $row ) {
2009-07-17 01:43:57 +00:00
$ip = $row [ $prefix . " ip " ];
2008-04-01 10:57:18 +00:00
if (
2009-07-17 01:43:57 +00:00
( strstr ( $ip , '/' ) && ip_in_range ( $remote , $ip )) ||
( $ip == $remote )
2008-04-01 10:57:18 +00:00
) {
2009-07-17 01:43:57 +00:00
$reason = $row [ $prefix . 'reason' ];
$admin = User :: by_id ( $row [ $prefix . 'banner_id' ]);
$date = date ( " Y-m-d " , $row [ $prefix . 'end_timestamp' ]);
2012-02-15 08:51:13 +00:00
header ( " HTTP/1.0 403 Forbidden " );
2012-02-15 08:23:00 +00:00
print " IP <b> $ip </b> has been banned until <b> $date </b> by <b> { $admin -> name } </b> because of <b> $reason </b> \n " ;
print " <p>If you couldn't possibly be guilty of what you're banned for, the person we banned probably had a dynamic IP address and so do you. See <a href='http://whatismyipaddress.com/dynamic-static'>http://whatismyipaddress.com/dynamic-static</a> for more information. \n " ;
2008-03-31 02:49:40 +00:00
$contact_link = $config -> get_string ( " contact_link " );
if ( ! empty ( $contact_link )) {
print " <p><a href=' $contact_link '>Contact The Admin</a> " ;
}
exit ;
2007-04-16 11:58:25 +00:00
}
}
2012-06-17 17:50:46 +00:00
log_error ( " ipban " , " block( $remote ) called but no bans matched " );
2012-06-10 16:49:17 +00:00
exit ;
2007-04-16 11:58:25 +00:00
}
// }}}
// database {{{
2007-10-21 23:31:23 +00:00
private function get_bans () {
2007-04-16 11:58:25 +00:00
global $database ;
2008-07-17 08:13:52 +00:00
$bans = $database -> get_all ( "
SELECT bans .* , users . name as banner_name
FROM bans
JOIN users ON banner_id = users . id
2012-07-28 11:07:55 +00:00
ORDER BY added , end_timestamp , bans . id
2009-01-17 04:40:51 +00:00
" );
2007-04-16 11:58:25 +00:00
if ( $bans ) { return $bans ;}
else { return array ();}
}
2008-03-31 02:49:40 +00:00
private function get_active_bans () {
global $database ;
2009-01-19 18:53:09 +00:00
2008-08-12 01:36:39 +00:00
$bans = $database -> get_all ( "
2010-02-02 11:32:05 +00:00
SELECT bans .* , users . name as banner_name
FROM bans
JOIN users ON banner_id = users . id
2011-01-01 15:28:38 +00:00
WHERE ( end_timestamp > : end_timestamp ) OR ( end_timestamp IS NULL )
2010-02-02 11:32:05 +00:00
ORDER BY end_timestamp , bans . id
2011-01-01 15:28:38 +00:00
" , array( " end_timestamp " =>time()));
2009-01-19 18:53:09 +00:00
2008-03-31 02:49:40 +00:00
if ( $bans ) { return $bans ;}
else { return array ();}
}
2012-01-27 11:04:50 +00:00
// returns [ips, nets]
private function get_active_bans_sorted () {
global $database ;
$cached = $database -> cache -> get ( " ip_bans_sorted " );
if ( $cached ) return $cached ;
$bans = $this -> get_active_bans ();
2012-06-17 17:50:46 +00:00
$ips = array (); # "0.0.0.0" => false);
$nets = array (); # "0.0.0.0/32" => false);
2012-01-27 11:04:50 +00:00
foreach ( $bans as $row ) {
if ( strstr ( $row [ 'ip' ], '/' )) {
$nets [ $row [ 'ip' ]] = true ;
}
else {
$ips [ $row [ 'ip' ]] = true ;
}
}
$sorted = array ( $ips , $nets );
$database -> cache -> set ( " ip_bans_sorted " , $sorted , 600 );
return $sorted ;
}
2007-04-16 11:58:25 +00:00
// }}}
}
2014-04-26 02:54:51 +00:00