Browse code

Reverting change to filter; breaks tracker.php

Clarissa Walker authored on 2015/09/14 08:11:59
Showing 1 changed files
... ...
@@ -74,9 +74,9 @@ if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
74 74
 					$info_hash = stripslashes($_GET["info_hash"]);
75 75
 				else
76 76
 					$info_hash = $_GET["info_hash"];
77
-				if (strlen(htmlentities($_GET['hash'], ENT_QUOTES, UTF-8)) == 20)
77
+				if (strlen($info_hash) == 20)
78 78
 					$info_hash = bin2hex($info_hash);
79
-				else if (strlen(htmlentities($_GET['hash'], ENT_QUOTES, UTF-8)) == 40)
79
+				else if (strlen($info_hash) == 40)
80 80
 					verifyHash($info_hash) or showError("Invalid info hash value.");
81 81
 				else
82 82
 					showError("Invalid info hash value.");
Browse code

Continuation of reviewing filtering practices

Clarissa Walker authored on 2015/09/14 07:36:02
Showing 1 changed files
... ...
@@ -74,9 +74,9 @@ if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
74 74
 					$info_hash = stripslashes($_GET["info_hash"]);
75 75
 				else
76 76
 					$info_hash = $_GET["info_hash"];
77
-				if (strlen($info_hash) == 20)
77
+				if (strlen(htmlentities($_GET['hash'], ENT_QUOTES, UTF-8)) == 20)
78 78
 					$info_hash = bin2hex($info_hash);
79
-				else if (strlen($info_hash) == 40)
79
+				else if (strlen(htmlentities($_GET['hash'], ENT_QUOTES, UTF-8)) == 40)
80 80
 					verifyHash($info_hash) or showError("Invalid info hash value.");
81 81
 				else
82 82
 					showError("Invalid info hash value.");
Browse code

This fixes the scrape data issue that has long plagued this software (2012). Filtering other data is fine, but scrape data ends up going to and from the torrent client and the tracker anyway, and they don't like the custom filters. This was confirmed by finding and going through the original PHPBTTracker software code and comparing it with RivetTracker.

Clarissa Walker authored on 2015/09/10 03:10:09
Showing 1 changed files
... ...
@@ -71,13 +71,13 @@ if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
71 71
 			if (isset($_GET["info_hash"]))
72 72
 			{
73 73
 				if (get_magic_quotes_gpc())
74
-					$info_hash = stripslashes(trim(strip_tags($_GET["info_hash"])));
74
+					$info_hash = stripslashes($_GET["info_hash"]);
75 75
 				else
76
-					$info_hash = trim(strip_tags($_GET["info_hash"]));
76
+					$info_hash = $_GET["info_hash"];
77 77
 				if (strlen($info_hash) == 20)
78
-					$info_hash = filterChar(bin2hex($info_hash));
78
+					$info_hash = bin2hex($info_hash);
79 79
 				else if (strlen($info_hash) == 40)
80
-					filterInt(verifyHash($info_hash)) or showError("Invalid info hash value.");
80
+					verifyHash($info_hash) or showError("Invalid info hash value.");
81 81
 				else
82 82
 					showError("Invalid info hash value.");
83 83
 				$usehash = true;
Browse code

Fixed badly handled procedure of clients originally done in the name of security. Initailly, hash/peer handling failed from the first escaping 'fixes'... ...then eventually, tracker responds with HTTP Status 404 after the second validation 'fix'. Finally tracked down after two years... shame.

Clarissa Walker authored on 2015/09/10 01:59:36
Showing 1 changed files
... ...
@@ -22,9 +22,6 @@ if ($hiddentracker == true)
22 22
 		exit();
23 23
 	}
24 24
 }
25
-?>
26
-
27
-<?php
28 25
 
29 26
 header("Content-type: text/plain");
30 27
 header("Pragma: no-cache");
Browse code

Checks added to some files: torrent_functions.php, tracker.php dltorrent.php's check changed to authenticate no matter what Some fixes and modifications from 2014: index.php, funcsv2.php, batch_upload.php, newtorrents.php, install.php, editconfig.php Version bumped up to 1.05

Clarissa Walker authored on 2015/08/30 00:06:28
Showing 1 changed files
... ...
@@ -1,3 +1,29 @@
1
+<?php
2
+//if config.php file not available, error out
3
+if (!file_exists("config.php"))
4
+{
5
+	echo "<font color=red><strong>Error: config.php file is not available.  Did you forget to upload it?" .
6
+	" If you haven't run the installer yet, please do so <a href=\"install.php\">here.</a></strong></font>";
7
+	exit();
8
+}
9
+
10
+require_once ("config.php");
11
+require_once ("funcsv2.php");
12
+
13
+//Check session only if hiddentracker is TRUE
14
+if ($hiddentracker == true)
15
+{
16
+	session_start();
17
+	
18
+	if (!$_SESSION['admin_logged_in'] && !$_SESSION['upload_logged_in'])
19
+	{
20
+		//check fails
21
+		header("Location: authenticate.php?status=indexlogin");
22
+		exit();
23
+	}
24
+}
25
+?>
26
+
1 27
 <?php
2 28
 
3 29
 header("Content-type: text/plain");
... ...
@@ -125,7 +151,7 @@ if (!isset($_GET["port"]) || !isset($_GET["downloaded"]) || !isset($_GET["upload
125 151
 }
126 152
 
127 153
 $port = filterInt($_GET["port"]);
128
-$ip = filterFloat(str_replace("::ffff:", "", $_SERVER["REMOTE_ADDR"]));
154
+$ip = filterChar(str_replace("::ffff:", "", $_SERVER["REMOTE_ADDR"]));
129 155
 $downloaded = filterFloat($_GET["downloaded"]);
130 156
 $uploaded = filterFloat($_GET["uploaded"]);
131 157
 $left = filterFloat($_GET["left"]);
... ...
@@ -196,13 +222,17 @@ function start($info_hash, $ip, $port, $peer_id, $left)
196 222
 		}
197 223
 	  }
198 224
 	}
225
+	
226
+//	if (preg_match("/^[a-f]+$/i", $ip)) { // Disable compact announce with IPv6
227
+//		$compact = 0;
228
+//	}
199 229
 
200 230
 	if (isset($_GET["ip"]) && $GLOBALS["ip_override"])
201 231
 	{
202 232
 		// compact check: valid IP address:
203 233
 		if (ip2long($_GET["ip"]) == -1)
204 234
 			showError("Invalid IP address. Must be standard dotted decimal (hostnames not allowed)");
205
-		$ip = filterFloat($_GET["ip"]);
235
+		$ip = filterChar($_GET["ip"]);
206 236
 	}
207 237
 
208 238
 	if ($left == 0)
Browse code

Import from the old rivettracker git repository at sourceforge (amisaph/amisapphire branch)

Clarissa Walker (ami-sapphire) authored on 2014/01/24 14:02:23
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,381 @@
1
+<?php
2
+
3
+header("Content-type: text/plain");
4
+header("Pragma: no-cache");
5
+
6
+ignore_user_abort(1);
7
+
8
+$GLOBALS["peer_id"] = "";
9
+$summaryupdate = array();
10
+
11
+require_once("config.php");
12
+require_once("funcsv2.php");
13
+
14
+
15
+// Prep database
16
+if ($GLOBALS["persist"])
17
+	$db = @mysql_pconnect($dbhost, $dbuser, $dbpass) or showError("Tracker error: can't connect to database. Contact the webmaster.");
18
+else
19
+	$db = @mysql_connect($dbhost, $dbuser, $dbpass) or showError("Tracker error: can't connect to database. Contact the webmaster.");
20
+@mysql_select_db($database) or showError("Tracker error: can't open database. Contact the webmaster");
21
+
22
+
23
+if (isset ($_SERVER["PATH_INFO"]) )
24
+{
25
+	// Scrape interface
26
+
27
+// Error: no web browsers allowed
28
+	if (!isset($_GET["info_hash"]))
29
+	{
30
+		header("HTTP/1.0 400 Bad Request");
31
+		die("This file is for BitTorrent clients.\n");
32
+	}
33
+
34
+// Deny access made with a browser...
35
+$agent = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
36
+
37
+if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
38
+{
39
+    header("HTTP/1.0 400 Bad Request");
40
+    die("This file is for BitTorrent clients.\n");
41
+}
42
+
43
+	if (substr($_SERVER["PATH_INFO"],-7) == '/scrape')
44
+	{
45
+		if ($scrape == true)
46
+		{
47
+			$usehash = false;
48
+			if (isset($_GET["info_hash"]))
49
+			{
50
+				if (get_magic_quotes_gpc())
51
+					$info_hash = stripslashes(trim(strip_tags($_GET["info_hash"])));
52
+				else
53
+					$info_hash = trim(strip_tags($_GET["info_hash"]));
54
+				if (strlen($info_hash) == 20)
55
+					$info_hash = filterChar(bin2hex($info_hash));
56
+				else if (strlen($info_hash) == 40)
57
+					filterInt(verifyHash($info_hash)) or showError("Invalid info hash value.");
58
+				else
59
+					showError("Invalid info hash value.");
60
+				$usehash = true;
61
+			}
62
+			if ($usehash)
63
+				$query = mysql_query("SELECT info_hash, filename FROM ".$prefix."namemap WHERE info_hash='$info_hash'");
64
+			else
65
+				$query = mysql_query("SELECT info_hash, filename FROM ".$prefix."namemap");
66
+			$namemap = array();
67
+			while ($row = mysql_fetch_row($query))
68
+				$namemap[$row[0]] = $row[1];
69
+	
70
+			if ($usehash)
71
+				$query = mysql_query("SELECT info_hash, seeds, leechers, finished FROM ".$prefix."summary WHERE info_hash='$info_hash'") or showError("Database error. Cannot complete request.");
72
+			else
73
+				$query = mysql_query("SELECT info_hash, seeds, leechers, finished FROM ".$prefix."summary ORDER BY info_hash") or showError("Database error. Cannot complete request.");
74
+
75
+			echo "d5:filesd";
76
+
77
+			while ($row = mysql_fetch_row($query))
78
+			{
79
+				$hash = hex2bin($row[0]);
80
+				echo "20:".$hash."d";
81
+				echo "8:completei".$row[1]."e";
82
+				echo "10:downloadedi".$row[3]."e";
83
+				echo "10:incompletei".$row[2]."e";
84
+				if (isset($namemap[$row[0]]))
85
+					echo "4:name".strlen($namemap[$row[0]]).":".$namemap[$row[0]];
86
+				echo "e";
87
+			}
88
+
89
+			echo "ee";
90
+			exit();
91
+		}
92
+		else
93
+			//client tried scraping but scraping has been disabled by the tracker
94
+			showError("Scraping has been disabled by this tracker.");
95
+	}
96
+}
97
+
98
+
99
+///////////////////////////////////////////////////////////////////
100
+// Handling of parameters from the URL and other setup
101
+
102
+
103
+// Error: no web browsers allowed
104
+if (!isset($_GET["info_hash"]) || !isset($_GET["peer_id"]))
105
+{
106
+	header("HTTP/1.0 400 Bad Request");
107
+	die("This file is for BitTorrent clients.\n");
108
+}
109
+$agent = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
110
+// Deny access made with a browser...
111
+
112
+if (preg_match("/^Mozilla|^Opera|^Links|^Lynx/i", $agent))
113
+{
114
+    header("HTTP/1.0 400 Bad Request");
115
+    die("This file is for BitTorrent clients.\n");
116
+}
117
+
118
+
119
+$info_hash = bin2hex(clean($_GET["info_hash"]));
120
+$peer_id = filterChar(bin2hex($_GET["peer_id"]));
121
+
122
+
123
+if (!isset($_GET["port"]) || !isset($_GET["downloaded"]) || !isset($_GET["uploaded"]) || !isset($_GET["left"])) {
124
+	showError("Invalid information received from BitTorrent client");
125
+}
126
+
127
+$port = filterInt($_GET["port"]);
128
+$ip = filterFloat(str_replace("::ffff:", "", $_SERVER["REMOTE_ADDR"]));
129
+$downloaded = filterFloat($_GET["downloaded"]);
130
+$uploaded = filterFloat($_GET["uploaded"]);
131
+$left = filterFloat($_GET["left"]);
132
+
133
+
134
+if (isset($_GET["event"]))
135
+	$event = filterData($_GET["event"]);
136
+else
137
+	$event = "";
138
+
139
+if (!isset($GLOBALS["ip_override"]))
140
+	$GLOBALS["ip_override"] = true;
141
+
142
+if (isset($_GET["numwant"]))
143
+	if ($_GET["numwant"] < $GLOBALS["maxpeers"] && $_GET["numwant"] >= 0)
144
+		$GLOBALS["maxpeers"] = filterFloat($_GET["numwant"]);
145
+
146
+if (isset($_GET["trackerid"]))
147
+{	
148
+	if (is_numeric($_GET["trackerid"]))
149
+		$GLOBALS["trackerid"] = filterInt($_GET["trackerid"]);
150
+}
151
+if (!is_numeric($port) || !is_numeric($downloaded) || !is_numeric($uploaded) || !is_numeric($left))
152
+	showError("Invalid numerical field(s) from client");
153
+
154
+
155
+
156
+/////////////////////////////////////////////////////
157
+// Any section of code might need to make a new peer, so this is a function here.
158
+// I don't want to put it into funcsv2, even though it should, just for consistency's sake.
159
+
160
+function start($info_hash, $ip, $port, $peer_id, $left)
161
+{
162
+	require("config.php"); //need prefix value...
163
+	if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
164
+	{
165
+      foreach(explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $address)
166
+      {
167
+		$addr = ip2long(trim($address));
168
+		if ($addr != -1)
169
+		{
170
+			if ($addr >= -1062731776 && $addr <= -1062666241)
171
+			{
172
+				// 192.168.x.x
173
+			}
174
+			else if ($addr >= -1442971648 && $addr <= -1442906113)
175
+			{
176
+				// 169.254.x.x
177
+			}
178
+			else if ($addr >= 167772160 && $addr <= 184549375)
179
+			{
180
+				// 10.x.x.x
181
+			}
182
+			else if ($addr >= 2130706432 && $addr <= 2147483647)
183
+			{
184
+				// 127.0.0.1
185
+			}
186
+			else if ($addr >= -1408237568 && $addr <= -1407188993)
187
+			{
188
+				// 172.[16-31].x.x
189
+			}
190
+			else
191
+			{
192
+				// Finally, we can accept it as a "real" ip address.
193
+				$ip = mysql_real_escape_string(trim($address));
194
+				break;
195
+			}
196
+		}
197
+	  }
198
+	}
199
+
200
+	if (isset($_GET["ip"]) && $GLOBALS["ip_override"])
201
+	{
202
+		// compact check: valid IP address:
203
+		if (ip2long($_GET["ip"]) == -1)
204
+			showError("Invalid IP address. Must be standard dotted decimal (hostnames not allowed)");
205
+		$ip = filterFloat($_GET["ip"]);
206
+	}
207
+
208
+	if ($left == 0)
209
+		$status = "seeder";
210
+	else
211
+		$status = "leecher";
212
+	if (@isFireWalled($info_hash, $peer_id, $ip, $port))
213
+		$nat = "'Y'";
214
+	else
215
+		$nat = "'N'";
216
+	
217
+	$results = @mysql_query("INSERT INTO ".$prefix."x$info_hash SET peer_id='$peer_id', port='$port', ip='$ip', lastupdate=UNIX_TIMESTAMP(), bytes='$left', status='$status', natuser=$nat");
218
+
219
+	// Special case: duplicated peer_id. 
220
+	if (!$results)
221
+	{
222
+		$error = mysql_error();
223
+		if (stristr($error, "key"))
224
+		{
225
+			// Duplicate peer_id! Check IP address
226
+			$peer = getPeerInfo($peer_id, $info_hash);
227
+			if ($ip == $peer["ip"])
228
+			{
229
+				// Same IP address. Tolerate this error.
230
+				return "WHERE natuser='N'";
231
+			}
232
+			//showError("Duplicated peer_id or changed IP address. Please restart BitTorrent.");
233
+			// Different IP address. Assume they were disconnected, and alter the IP address.
234
+			quickQuery("UPDATE ".$prefix."x$info_hash SET ip='$ip' WHERE peer_id='$peer_id'");
235
+			return "WHERE natuser='N'";
236
+		}
237
+		error_log("RivetTracker: start: ".$error);
238
+		showError("Tracker/database error. The details are in the error log.");
239
+	}
240
+	$GLOBALS["trackerid"] = mysql_insert_id();
241
+
242
+	$compact = mysql_real_escape_string(pack('Nn', ip2long($ip), $port));
243
+	$peerid = mysql_real_escape_string('2:ip' . strlen($ip) . ':' . $ip . '7:peer id20:' . hex2bin($peer_id) . "4:porti{$port}e");
244
+	$no_peerid = mysql_real_escape_string('2:ip' . strlen($ip) . ':' . $ip . "4:porti{$port}e");
245
+	@mysql_query("INSERT INTO ".$prefix."y$info_hash SET sequence='{$GLOBALS["trackerid"]}', compact='$compact', with_peerid='$peerid', without_peerid='$no_peerid'");
246
+
247
+	if ($left == 0)
248
+	{
249
+		summaryAdd("seeds", 1);
250
+		return "WHERE status='leecher' AND natuser='N'";
251
+	}
252
+	else
253
+	{
254
+		summaryAdd("leechers", 1);
255
+		return "WHERE natuser='N'";
256
+	}
257
+}
258
+
259
+// End of function start
260
+
261
+
262
+
263
+////////////////////////////////////////////////////////////////////////////////////////
264
+// Actual work. Depends on value of $event. (Missing event is mapped to '' above)
265
+
266
+if ($event == '')
267
+{
268
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
269
+	$peer_exists = getPeerInfo($peer_id, $info_hash);
270
+	$where = "WHERE natuser='N'";
271
+
272
+	if (!is_array($peer_exists))
273
+		$where = start($info_hash, $ip, $port, $peer_id, $left);
274
+
275
+	if ($peer_exists["bytes"] != 0 && $left == 0)
276
+	{
277
+
278
+		quickQuery("UPDATE ".$prefix."x$info_hash SET bytes=0, status='seeder' WHERE sequence='${GLOBALS["trackerid"]}'");
279
+		if (mysql_affected_rows() == 1)
280
+		{
281
+			summaryAdd("leechers", -1);
282
+			summaryAdd("seeds", 1);
283
+			summaryAdd("finished", 1);
284
+		}
285
+	}
286
+	collectBytes($peer_exists, $info_hash, $left);
287
+	sendRandomPeers($info_hash);
288
+}
289
+else if ($event == "started")
290
+{
291
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
292
+
293
+	$start = start($info_hash, $ip, $port, $peer_id, $left);
294
+	
295
+	// Don't send the tracker id for newly started clients. Send it next time. Make sure
296
+	// they get a good random list of peers to begin with.
297
+	sendRandomPeers($info_hash);
298
+}
299
+else if ($event == "stopped")
300
+{
301
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
302
+	killPeer($peer_id, $info_hash, $left);	
303
+
304
+	// I don't know why, but the real tracker returns peers on event=stopped
305
+	// but I'll just send an empty list. On the other hand, 
306
+	// TheSHADOW asked for this.
307
+	if (isset($_GET["tracker"]))
308
+		$peers = getRandomPeers($info_hash);
309
+	else
310
+		$peers = array("size" => 0);
311
+
312
+	sendPeerList($peers);
313
+}
314
+else if ($event == "completed") // now the same as an empty string
315
+{
316
+	verifyTorrent($info_hash) or evilReject($ip, $peer_id,$port);
317
+	$peer_exists = getPeerInfo($peer_id, $info_hash);
318
+
319
+	if (!is_array($peer_exists))
320
+		start($info_hash, $ip, $port, $peer_id, $left);
321
+	else
322
+	{
323
+		quickQuery("UPDATE ".$prefix."x$info_hash SET bytes=0, status='seeder' WHERE sequence='${GLOBALS["trackerid"]}'");
324
+
325
+		// Race check
326
+		if (mysql_affected_rows() == 1)
327
+		{
328
+			summaryAdd("leechers", -1);
329
+			summaryAdd("seeds", 1);
330
+			summaryAdd("finished", 1);
331
+		}
332
+	}
333
+	collectBytes($peer_exists, $info_hash, $left);
334
+	$peers=getRandomPeers($info_hash);
335
+
336
+	sendPeerList($peers);
337
+
338
+}
339
+else
340
+	showError("Invalid event= from client.");
341
+
342
+
343
+if ($GLOBALS["countbytes"])
344
+{
345
+	// Once every minute or so, we run the speed update checker.
346
+	// This is still not very accurate... :/
347
+	//@ symbol suppresses errors
348
+	$query = @mysql_query("SELECT UNIX_TIMESTAMP() - lastSpeedCycle FROM ".$prefix."summary WHERE info_hash='$info_hash'");
349
+	$results = mysql_fetch_row($query);
350
+	if ($results[0] >= 60 || $event == "completed")
351
+	{
352
+		if (Lock("SPEED:$info_hash"))
353
+		{
354
+			@runSpeed($info_hash, $results[0]);
355
+			Unlock("SPEED:$info_hash");
356
+		}
357
+	}
358
+}
359
+
360
+
361
+
362
+/* 
363
+ * Under heavy loads, this will lighten the load slightly... very slightly...
364
+ */
365
+//if (mt_rand(1,10) == 4)
366
+  trashCollector($info_hash, $report_interval);
367
+
368
+
369
+
370
+// Finally, it's time to do stuff to the summary table.
371
+if (!empty($summaryupdate))
372
+{
373
+	$stuff = "";
374
+	foreach ($summaryupdate as $column => $value)
375
+	{
376
+		$stuff .= ', '.$column. ($value[1] ? "=" : "=$column+") . $value[0];
377
+	}
378
+	mysql_query("UPDATE ".$prefix."summary SET ".substr($stuff, 1)." WHERE info_hash='$info_hash'");
379
+}
380
+
381
+?>
0 382
\ No newline at end of file