1<?php if (!defined('BB2_CWD')) die("I said no cheating!"); 2 3// Bad Behavior entry point is start_bad_behavior(). 4// If you're reading this, you are probably lost. 5// Go read the bad-behavior-generic.php file. 6 7define('BB2_CORE', dirname(__FILE__)); 8define('BB2_COOKIE', 'bb2_screener_'); 9 10require_once(BB2_CORE . "/functions.inc.php"); 11 12// Our log table structure 13function bb2_table_structure($name) 14{ 15 // It's not paranoia if they really are out to get you. 16 $name_escaped = bb2_db_escape($name); 17 return "CREATE TABLE IF NOT EXISTS `$name_escaped` ( 18 `id` INT(11) NOT NULL auto_increment, 19 `ip` TEXT NOT NULL, 20 `date` DATETIME NOT NULL default '0000-00-00 00:00:00', 21 `request_method` TEXT NOT NULL, 22 `request_uri` TEXT NOT NULL, 23 `server_protocol` TEXT NOT NULL, 24 `http_headers` TEXT NOT NULL, 25 `user_agent` TEXT NOT NULL, 26 `request_entity` TEXT NOT NULL, 27 `key` TEXT NOT NULL, 28 INDEX (`ip`(15)), 29 INDEX (`user_agent`(10)), 30 PRIMARY KEY (`id`) );"; // TODO: INDEX might need tuning 31} 32 33// Insert a new record 34function bb2_insert($settings, $package, $key) 35{ 36 $ip = bb2_db_escape($package['ip']); 37 $date = bb2_db_date(); 38 $request_method = bb2_db_escape($package['request_method']); 39 $request_uri = bb2_db_escape($package['request_uri']); 40 $server_protocol = bb2_db_escape($package['server_protocol']); 41 $user_agent = bb2_db_escape($package['user_agent']); 42 $headers = "$request_method $request_uri $server_protocol\n"; 43 foreach ($package['headers'] as $h => $v) { 44 $headers .= bb2_db_escape("$h: $v\n"); 45 } 46 $request_entity = ""; 47 if (!strcasecmp($request_method, "POST")) { 48 foreach ($package['request_entity'] as $h => $v) { 49 $request_entity .= bb2_db_escape("$h: $v\n"); 50 } 51 } 52 return "INSERT INTO `" . bb2_db_escape($settings['log_table']) . "` 53 (`ip`, `date`, `request_method`, `request_uri`, `server_protocol`, `http_headers`, `user_agent`, `request_entity`, `key`) VALUES 54 ('$ip', '$date', '$request_method', '$request_uri', '$server_protocol', '$headers', '$user_agent', '$request_entity', '$key')"; 55} 56 57// Kill 'em all! 58function bb2_banned($settings, $package, $key, $previous_key=false) 59{ 60 // Some spambots hit too hard. Slow them down a bit. 61 sleep(2); 62 63 require_once(BB2_CORE . "/banned.inc.php"); 64 bb2_display_denial($settings, $key, $previous_key); 65 bb2_log_denial($settings, $package, $key, $previous_key); 66 if (is_callable('bb2_banned_callback')) { 67 bb2_banned_callback($settings, $package, $key); 68 } 69 // Penalize the spammers some more 70 require_once(BB2_CORE . "/housekeeping.inc.php"); 71 bb2_housekeeping($settings, $package); 72 die(); 73} 74 75function bb2_approved($settings, $package) 76{ 77 // Dirk wanted this 78 if (is_callable('bb2_approved_callback')) { 79 bb2_approved_callback($settings, $package); 80 } 81 82 // Decide what to log on approved requests. 83 if (($settings['verbose'] && $settings['logging']) || empty($package['user_agent'])) { 84 bb2_db_query(bb2_insert($settings, $package, "00000000")); 85 } 86} 87 88// Check the results of a particular test; see below for usage 89// Returns FALSE if test passed (yes this is backwards) 90function bb2_test($settings, $package, $result) 91{ 92 // Passthrough a value of 1 for whitelisted/bypass items 93 if ($result == 1) { 94 return true; 95 } 96 if ($result !== FALSE) { 97 bb2_banned($settings, $package, $result); 98 return TRUE; 99 } 100 return FALSE; 101} 102 103 104// Let God sort 'em out! 105function bb2_start($settings) 106{ 107 // Gather up all the information we need, first of all. 108 $headers = bb2_load_headers(); 109 // Postprocess the headers to mixed-case 110 // FIXME: get the world to stop using PHP as CGI 111 $headers_mixed = array(); 112 foreach ($headers as $h => $v) { 113 $headers_mixed[uc_all($h)] = $v; 114 } 115 116 // IPv6 - IPv4 compatibility mode hack 117 $_SERVER['REMOTE_ADDR'] = preg_replace("/^::ffff:/", "", $_SERVER['REMOTE_ADDR']); 118 // We use these frequently. Keep a copy close at hand. 119 $ip = $_SERVER['REMOTE_ADDR']; 120 $request_method = $_SERVER['REQUEST_METHOD']; 121 $request_uri = $_SERVER['REQUEST_URI']; 122 if (!$request_uri) $request_uri = $_SERVER['SCRIPT_NAME']; # IIS 123 $server_protocol = $_SERVER['SERVER_PROTOCOL']; 124 @$user_agent = $_SERVER['HTTP_USER_AGENT']; 125 126 // Reconstruct the HTTP entity, if present. 127 $request_entity = array(); 128 if (!strcasecmp($request_method, "POST") || !strcasecmp($request_method, "PUT")) { 129 foreach ($_POST as $h => $v) { 130 $request_entity[$h] = $v; 131 } 132 } 133 134 $package = array('ip' => $ip, 'headers' => $headers, 'headers_mixed' => $headers_mixed, 'request_method' => $request_method, 'request_uri' => $request_uri, 'server_protocol' => $server_protocol, 'request_entity' => $request_entity, 'user_agent' => $user_agent, 'is_browser' => false); 135 136 // Please proceed to the security checkpoint and have your 137 // identification and boarding pass ready. 138 139 // First check the whitelist 140 require_once(BB2_CORE . "/whitelist.inc.php"); 141 if (!bb2_whitelist($package)) { 142 // Now check the blacklist 143 require_once(BB2_CORE . "/blacklist.inc.php"); 144 bb2_test($settings, $package, bb2_blacklist($package)); 145 146 // Check the http:BL 147 // config check added for DokuWiki plugin 148 if(!$settings['skipblackhole']){ 149 require_once(BB2_CORE . "/blackhole.inc.php"); 150 if (bb2_test($settings, $package, bb2_httpbl($settings, $package))) { 151 // Bypass all checks if http:BL says search engine 152 bb2_approved($settings, $package); 153 return true; 154 } 155 } 156 157 // Check for common stuff 158 require_once(BB2_CORE . "/common_tests.inc.php"); 159 bb2_test($settings, $package, bb2_protocol($settings, $package)); 160 bb2_test($settings, $package, bb2_cookies($settings, $package)); 161 bb2_test($settings, $package, bb2_misc_headers($settings, $package)); 162 163 // Specific checks 164 @$ua = $headers_mixed['User-Agent']; 165 // Search engines first 166 if (stripos($ua, "bingbot") !== FALSE || stripos($ua, "msnbot") !== FALSE || stripos($ua, "MS Search") !== FALSE) { 167 require_once(BB2_CORE . "/msnbot.inc.php"); 168 bb2_test($settings, $package, bb2_msnbot($package)); 169 bb2_approved($settings, $package); 170 return true; 171 } elseif (stripos($ua, "Googlebot") !== FALSE || stripos($ua, "Mediapartners-Google") !== FALSE || stripos($ua, "Google Web Preview") !== FALSE) { 172 require_once(BB2_CORE . "/google.inc.php"); 173 bb2_test($settings, $package, bb2_google($package)); 174 bb2_approved($settings, $package); 175 return true; 176 } elseif (stripos($ua, "Yahoo! Slurp") !== FALSE || stripos($ua, "Yahoo! SearchMonkey") !== FALSE) { 177 require_once(BB2_CORE . "/yahoo.inc.php"); 178 bb2_test($settings, $package, bb2_yahoo($package)); 179 bb2_approved($settings, $package); 180 return true; 181 } 182 // MSIE checks 183 if (stripos($ua, "MSIE") !== FALSE) { 184 $package['is_browser'] = true; 185 if (stripos($ua, "Opera") !== FALSE) { 186 require_once(BB2_CORE . "/opera.inc.php"); 187 bb2_test($settings, $package, bb2_opera($package)); 188 } else { 189 require_once(BB2_CORE . "/msie.inc.php"); 190 bb2_test($settings, $package, bb2_msie($package)); 191 } 192 } elseif (stripos($ua, "Konqueror") !== FALSE) { 193 $package['is_browser'] = true; 194 require_once(BB2_CORE . "/konqueror.inc.php"); 195 bb2_test($settings, $package, bb2_konqueror($package)); 196 } elseif (stripos($ua, "Opera") !== FALSE) { 197 $package['is_browser'] = true; 198 require_once(BB2_CORE . "/opera.inc.php"); 199 bb2_test($settings, $package, bb2_opera($package)); 200 } elseif (stripos($ua, "Safari") !== FALSE) { 201 $package['is_browser'] = true; 202 require_once(BB2_CORE . "/safari.inc.php"); 203 bb2_test($settings, $package, bb2_safari($package)); 204 } elseif (stripos($ua, "Lynx") !== FALSE) { 205 $package['is_browser'] = true; 206 require_once(BB2_CORE . "/lynx.inc.php"); 207 bb2_test($settings, $package, bb2_lynx($package)); 208 } elseif (stripos($ua, "MovableType") !== FALSE) { 209 require_once(BB2_CORE . "/movabletype.inc.php"); 210 bb2_test($settings, $package, bb2_movabletype($package)); 211 } elseif (stripos($ua, "Mozilla") !== FALSE && stripos($ua, "Mozilla") == 0) { 212 $package['is_browser'] = true; 213 require_once(BB2_CORE . "/mozilla.inc.php"); 214 bb2_test($settings, $package, bb2_mozilla($package)); 215 } 216 217 // More intensive screening applies to POST requests 218 if (!strcasecmp('POST', $package['request_method'])) { 219 require_once(BB2_CORE . "/post.inc.php"); 220 bb2_test($settings, $package, bb2_post($settings, $package)); 221 } 222 } 223 224 // Last chance screening. 225 require_once(BB2_CORE . "/screener.inc.php"); 226 bb2_screener($settings, $package); 227 228 // And that's about it. 229 bb2_approved($settings, $package); 230 return true; 231} 232?> 233