From 0c04d9885c02371877758c1a728a007ac992698c Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Wed, 22 Nov 2006 23:21:53 +0000 Subject: [PATCH] * Moved Werdna's new IP functions to the IP class * Handle bad input to new IP::isAddressInRange gracefully (return false) * Block::doAutoblock always returns a bool now, as the docs say * Split off Block::isWhitelistedIp from Block::doAutoblock * Put AOL proxy IPs in whitelist, and also one from Singapore that was troublesome on enwiki (more should be added, probably?) * Improve some docs * Fix a bug: check if the passed IP is in the whitelist, not if the request IP is in the whitelist --- includes/Block.php | 84 ++++++++++++++++--------------- includes/GlobalFunctions.php | 31 ------------ includes/IP.php | 33 ++++++++++-- languages/messages/MessagesEn.php | 25 ++++++++- 4 files changed, 96 insertions(+), 77 deletions(-) diff --git a/includes/Block.php b/includes/Block.php index b6e36d85aa..e050474290 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -241,10 +241,10 @@ class Block /** * Determine if a given integer IPv4 address is in a given CIDR network - * @deprecated Use wfIsAddressInRange + * @deprecated Use IP::isAddressInRange */ function isAddressInRange( $addr, $range ) { - return wfIsAddressInRange( $addr, $range ); + return IP::isAddressInRange( $addr, $range ); } function initFromRow( $row ) @@ -275,9 +275,7 @@ class Block $this->mRangeEnd = ''; if ( $this->mUser == 0 ) { - $startend = wfRangeStartEnd($this->mAddress); - $this->mRangeStart = $startend[0]; - $this->mRangeEnd = $startend[1]; + list($this->mRangeStart, $this->mRangeEnd) = IP::parseRange$this->mAddress); } } @@ -430,45 +428,17 @@ class Block /** * Autoblocks the given IP, referring to this Block. - * @param $autoblockip The IP to autoblock. - * @return bool Whether or not an autoblock was inserted. + * @param string $autoblockip The IP to autoblock, dotted-quad. + * @return bool True if an autoblock was inserted OR redundant to preexisting block. */ - function doAutoblock( $autoblockip ) { + public function doAutoblock( $autoblockip ) { # Check if this IP address is already blocked $dbw =& wfGetDb( DB_MASTER ); $dbw->begin(); - # If autoblocks are disabled, go away. - if ( !$this->mEnableAutoblock ) { - return; - } - - # Check for presence on the autoblock whitelist - # TODO cache this? - $lines = explode( "\n", wfMsgForContentNoTrans( 'autoblock_whitelist' ) ); - - $ip = wfGetIp(); - - wfDebug("Checking the autoblock whitelist..\n"); - - foreach( $lines as $line ) { - # List items only - if ( substr( $line, 0, 1 ) !== '*' ) { - continue; - } - - $wlEntry = substr($line, 1); - $wlEntry = trim($wlEntry); - - wfDebug("Checking $wlEntry\n"); - - # Is the IP in this range? - if (wfIsAddressInRange( $ip, $wlEntry )) { - wfDebug("IP $ip matches $wlEntry, not autoblocking\n"); - #$autoblockip = null; # Don't autoblock a whitelisted IP. - return; #This /SHOULD/ introduce a dummy block - but - # I don't know a safe way to do so. -werdna - } + # If autoblocks are disabled, or if this IP is whitelisted, go away. + if ( !$this->mEnableAutoblock || self::isWhitelistedIp( $autoblockip ) ) { + return false; } # It's okay to autoblock. Go ahead and create/insert the block. @@ -480,11 +450,11 @@ class Block # prolong block time if ($this->mExpiry && ($this->mExpiry < Block::getAutoblockExpiry($ipblock->mTimestamp))) { - return; + return true; } # Just update the timestamp $ipblock->updateTimestamp(); - return; + return true; } else { $ipblock = new Block; } @@ -510,6 +480,38 @@ class Block return $ipblock->insert(); } + /** + * Checks whether an IP is whitelisted in the autoblock_whitelist message. + * @todo Cache this? + * + * @param string $ip Dotted quad + * @return bool + */ + private static function isWhitelistedIp( $ip ) { + $lines = explode( "\n", wfMsgForContentNoTrans( 'autoblock_whitelist' ) ); + + wfDebug("Checking the autoblock whitelist..\n"); + + foreach( $lines as $line ) { + # Parse list items only + if ( substr( $line, 0, 1 ) !== '*' ) { + continue; + } + + $wlEntry = substr($line, 1); + $wlEntry = trim($wlEntry); + + wfDebug("Checking $wlEntry\n"); + + # Is the IP in this range? + if (IP::isAddressInRange( $autoblockip, $wlEntry )) { + wfDebug("IP $autoblockip matches $wlEntry, not autoblocking\n"); + return true; #This /SHOULD/ introduce a dummy block - but + # I don't know a safe way to do so. -werdna + } + } + return false; + } function deleteIfExpired() { $fname = 'Block::deleteIfExpired'; diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 14e49ea593..c42dedcb31 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -2037,37 +2037,6 @@ function wfWikiID() { } } -/** - * Get the start and end of a range. - * @param $range The range to get the start and end for. - * @return array An array with the first element as the start of the range, as a long, and the second element as the end of the range, also as a long. - * - */ -function wfRangeStartEnd( $range ) { - list( $network, $bits ) = wfParseCIDR( $range ); - if ( $network !== false ) { - $start = sprintf( '%08X', $network ); - $end = sprintf( '%08X', $network + (1 << (32 - $bits)) - 1 ); - return array($start, $end); - } - return false; -} - -/** - * Determine if a given integer IPv4 address is in a given CIDR network - * @param $addr The address to check against the given range. - * @param $range The range to check the given address against. - * @return bool Whether or not the given address is in the given range. - */ -function wfIsAddressInRange( $addr, $range ) { - $unsignedIP = IP::toUnsigned($addr); - $startend = wfRangeStartEnd($range); - $start = $startend[0]; - $end = $startend[1]; - - return (($unsignedIP >= $start) && ($unsignedip <= $end)); -} - /* * Get a Database object * @param integer $db Index of the connection to get. May be DB_MASTER for the diff --git a/includes/IP.php b/includes/IP.php index f3ff34278a..d6b87043da 100644 --- a/includes/IP.php +++ b/includes/IP.php @@ -20,6 +20,7 @@ class IP { /** * Validate an IP address. + * @param string $ipblock Dotted quad * @return boolean True if it is valid. */ public static function isValid( $ip ) { @@ -28,6 +29,7 @@ class IP { /** * Validate an IP Block. + * @param string $ipblock Dotted quad * @return boolean True if it is valid. */ public static function isValidBlock( $ipblock ) { @@ -38,6 +40,9 @@ class IP { * Determine if an IP address really is an IP address, and if it is public, * i.e. not RFC 1918 or similar * Comes from ProxyTools.php + * + * @param string $ip Dotted quad + * @return bool */ public static function isPublic( $ip ) { $n = IP::toUnsigned( $ip ); @@ -74,10 +79,10 @@ class IP { /** * Split out an IP block as an array of 4 bytes and a mask, - * return false if it cant be determined + * return false if it can't be determined * - * @parameter $ip string A quad dotted IP address - * @return array + * @param string $ipblock A quad dotted IP address + * @return mixed Array or false */ public static function toArray( $ipblock ) { if(! preg_match( '/^' . RE_IP_ADD . '(?:\/(?:'.RE_IP_PREFIX.'))?' . '$/', $ipblock, $matches ) ) { @@ -95,7 +100,8 @@ class IP { * function for an IPv6 address will be prefixed with "v6-", a non- * hexadecimal string which sorts after the IPv4 addresses. * - * @param $ip Quad dotted IP address. + * @param string $ip Quad dotted IP address. + * @return mixed String or false */ public static function toHex( $ip ) { $n = self::toUnsigned( $ip ); @@ -110,6 +116,7 @@ class IP { * Like ip2long() except that it actually works and has a consistent error return value. * Comes from ProxyTools.php * @param $ip Quad dotted IP address. + * @return mixed Int or false */ public static function toUnsigned( $ip ) { if ( $ip == '255.255.255.255' ) { @@ -177,6 +184,8 @@ class IP { * 1.2.3.4/24 CIDR * 1.2.3.4 - 1.2.3.5 Explicit range * 1.2.3.4 Single IP + * @param string $range + * @return array (hex string start, hex string end), or (false, false) if an error occurred */ public static function parseRange( $range ) { if ( strpos( $range, '/' ) !== false ) { @@ -207,5 +216,21 @@ class IP { return array( $start, $end ); } } + + /** + * Determine if a given integer IPv4 address is in a given range + * @param int $addr + * @param string $range (CIDR, hyphenated dotted-quad, or single dotted-quad) + * @return bool Whether or not the given address is in the given range. Returns false on error. + */ + public static function isAddressInRange( $addr, $range ) { + $unsignedIP = IP::toUnsigned($addr); + list($start, $end) = IP::parseRange($range); + + if ($start == false || $end == false) + return false; + else + return (($unsignedIP >= $start) && ($unsignedip <= $end)); // string comparison + } } ?> diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index b3645a735e..247f89c8fd 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -2616,7 +2616,30 @@ Please confirm that really want to recreate this page.', 'autosumm-shortnew' => 'New page: $1', # Autoblock whitelist -'autoblock_whitelist' => '', +'autoblock_whitelist' => "AOL http://webmaster.info.aol.com/proxyinfo.html +*64.12.96.0/19 +*149.174.160.0/20 +*152.163.240.0/21 +*152.163.248.0/22 +*152.163.252.0/23 +*152.163.96.0/22 +*152.163.100.0/23 +*195.93.32.0/22 +*195.93.48.0/22 +*195.93.64.0/19 +*195.93.96.0/19 +*195.93.16.0/20 +*198.81.0.0/22 +*198.81.16.0/20 +*198.81.8.0/23 +*202.67.64.128/25 +*205.188.192.0/20 +*205.188.208.0/23 +*205.188.112.0/20 +*205.188.146.144/30 +*207.200.112.0/21 +StarHub +*202.156.6.54/32", ); -- 2.20.1