r35849 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r35848‎ | r35849 | r35850 >
Date:06:52, 4 June 2008
Author:werdna
Status:old
Tags:
Comment:
TorBlock extension updates:
* Some code quality stuff. Merge some functions, fix up some vertical whitespace, use real methods instead of obsolete ones.
* Add the maintenance script described in the TorBlock.php file.
* Try to avoid DoSing tor with a race condition upon exit node list expiry.
Modified paths:
  • /trunk/extensions/TorBlock/TorBlock.class.php (modified) (history)
  • /trunk/extensions/TorBlock/TorBlock.php (modified) (history)
  • /trunk/extensions/TorBlock/loadExitNodes.php (added) (history)

Diff [purge]

Index: trunk/extensions/TorBlock/TorBlock.php
@@ -36,7 +36,7 @@
3737 * Permission keys that bypass Tor blocks.
3838 * Array of permission keys.
3939 */
40 -$wgTorBypassPermissions = array( /*'autoconfirmed', 'proxyunbannable'*/ );
 40+$wgTorBypassPermissions = array( 'user', /*'autoconfirmed', 'proxyunbannable'*/ );
4141
4242 /**
4343 * Whether to load Tor blocks if they aren't stored in memcached.
Index: trunk/extensions/TorBlock/loadExitNodes.php
@@ -0,0 +1,10 @@
 2+<?php
 3+/*
 4+ * Updates the tor exit node list in
 5+ */
 6+
 7+require_once ( getenv('MW_INSTALL_PATH') !== false
 8+ ? getenv('MW_INSTALL_PATH')."/maintenance/commandLine.inc"
 9+ : dirname( __FILE__ ) . '/../../maintenance/commandLine.inc' );
 10+
 11+TorBlock::loadExitNodes();
\ No newline at end of file
Property changes on: trunk/extensions/TorBlock/loadExitNodes.php
___________________________________________________________________
Added: svn:eol-style
112 + native
Index: trunk/extensions/TorBlock/TorBlock.class.php
@@ -4,18 +4,18 @@
55
66 class TorBlock {
77 public static $mExitNodes;
8 -
 8+
99 public static function onGetUserPermissionsErrorsExpensive( &$title, &$user, &$action, &$result ) {
1010 global $wgTorAllowedActions;
1111 if (in_array( $action, $wgTorAllowedActions)) {
1212 return true;
1313 }
14 -
 14+
1515 wfDebug( "Checking Tor status\n" );
16 -
 16+
1717 if (self::isExitNode()) {
1818 wfDebug( "-User detected as editing through tor.\n" );
19 -
 19+
2020 global $wgTorBypassPermissions;
2121 foreach( $wgTorBypassPermissions as $perm) {
2222 if ($user->isAllowed( $perm )) {
@@ -23,21 +23,20 @@
2424 return true;
2525 }
2626 }
27 -
 27+
2828 $ip = wfGetIp();
2929 wfDebug( "-User detected as editing from Tor node. Adding Tor block to permissions errors\n" );
3030 wfLoadExtensionMessages( 'TorBlock' );
31 -
 31+
3232 $result[] = array('torblock-blocked', $ip);
33 -
 33+
3434 return false;
3535 }
36 -
 36+
3737 return true;
3838 }
3939
4040 public static function getExitNodes() {
41 -
4241 if (is_array(self::$mExitNodes)) {
4342 wfDebug( "Loading Tor exit node list from memory.\n" );
4443 return self::$mExitNodes;
@@ -51,9 +50,12 @@
5251 wfDebug( "Loading Tor exit node list from memcached.\n" );
5352 // Lucky.
5453 return self::$mExitNodes = $nodes;
 54+ } elseif ($nodes == 'loading') {
 55+ // Somebody else is loading it.
 56+ return array();
5557 }
5658
57 - // We have to actually load them.
 59+ // We have to actually load from the server.
5860
5961 if (!$wgTorLoadNodes) {
6062 // Disabled.
@@ -62,82 +64,93 @@
6365 }
6466
6567 wfDebug( "Loading Tor exit node list cold.\n" );
66 -
67 - return self::$mExitNodes = self::loadExitNodes();
 68+
 69+ return self::loadExitNodes();
6870 }
69 -
 71+
7072 public static function loadExitNodes() {
71 - $nodes = array();
 73+ wfProfileIn( __METHOD__ );
 74+
 75+ global $wgTorIPs, $wgMemc;
 76+
 77+ // Set loading key, to prevent DoS of server.
7278
73 - global $wgTorIPs;
 79+ $wgMemc->set( 'mw-tor-exit-nodes', 'loading', 300 );
7480
 81+ $nodes = array();
7582 foreach( $wgTorIPs as $ip ) {
76 - $nodes = array_unique( array_merge( $nodes, self::getExitList( $ip ) ) );
 83+ $nodes = array_unique( array_merge( $nodes, self::loadNodesForIP( $ip ) ) );
7784 }
78 -
79 - global $wgMemc;
80 -
 85+
 86+ // Save to cache.
8187 $wgMemc->set( 'mw-tor-exit-nodes', $nodes, 1800 ); // Store for half an hour.
82 -
83 - return $nodes;
 88+
 89+ wfProfileOut( __METHOD__ );
 90+
 91+ return self::$mExitNodes = $nodes;
8492 }
85 -
86 - public static function getExitList( $ip ) {
 93+
 94+ public static function loadNodesForIP( $ip ) {
8795 $url = 'https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip='.$ip;
88 -
8996 $data = Http::get( $url );
90 -
91 - $lines = split("\n", $data);
92 -
 97+ $lines = explode("\n", $data);
 98+
9399 $nodes = array();
94 -
95100 foreach( $lines as $line ) {
96101 if (strpos( $line, '#' )===false) {
97102 $nodes[] = trim($line);
98103 }
99104 }
100 -
 105+
101106 return $nodes;
102107 }
103 -
 108+
104109 public static function isExitNode($ip = null) {
105110 #return true; ## FOR DEBUGGING
106111 if ($ip == null) {
107112 $ip = wfGetIp();
108113 }
109 -
 114+
110115 $nodes = self::getExitNodes();
111 -
 116+
112117 return in_array( $ip, $nodes );
113118 }
114 -
 119+
115120 public static function onGetBlockedStatus( &$user ) {
116121 if (self::isExitNode() && $user->mBlock && !$user->mBlock->mUser) {
117122 wfDebug( "User using Tor node. Disabling IP block as it was probably targetted at the tor node." );
118123 // Node is probably blocked for being a Tor node. Remove block.
119124 $user->mBlockedBy = 0;
120125 }
121 -
 126+
122127 return true;
123128 }
124 -
 129+
125130 public static function onAbortAutoblock( $autoblockip, &$block ) {
126131 return !self::isExitNode( $autoblockip );
127132 }
128 -
 133+
129134 public static function onGetAutoPromoteGroups( $user, &$promote ) {
130 - if (self::isExitNode()) {
131 - // Check against stricter requirements.
132 - $age = time() - wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
133 -
134 - global $wgTorAutoConfirmAge, $wgTorAutoConfirmCount;
135 -
136 - if ($age < $wgTorAutoConfirmAge || $user->getEditCount() < $wgTorAutoConfirmCount) {
137 - // No!
138 - $promote = array();
139 - }
 135+ // Check against stricter requirements for tor nodes.
 136+ // Counterintuitively, we do the requirement checks first.
 137+ // This is so that we don't have to hit memcached to get the
 138+ // exit list, unnecessarily.
 139+
 140+ if (!count($promote)) {
 141+ return true; // No groups to promote to anyway
140142 }
141 -
 143+
 144+ $age = time() - wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
 145+ global $wgTorAutoConfirmAge, $wgTorAutoConfirmCount;
 146+
 147+ if ($age >= $wgTorAutoConfirmAge && $user->getEditCount() >= $wgTorAutoConfirmCount) {
 148+ return true; // Does match requirements. Don't bother checking if we're an exit node.
 149+ }
 150+
 151+ if (self::isExitNode()) { // Tor user, doesn't match the expanded requirements.
 152+ $promote = array();
 153+ }
 154+
142155 return true;
143156 }
144 -}
 157+}
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r35852Remove trailing whitespace introduced in r35849siebrand07:42, 4 June 2008

Status & tagging log