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