From 66553fb8574a9d2578f423f4db0461efe49ea099 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Wed, 10 Aug 2011 16:14:45 +0200 Subject: [PATCH 01/11] [ticket/9297] Add support for Extended Passive Mode (EPSV) in ftp_fsock class. PHPBB3-9297 --- phpBB/includes/functions_transfer.php | 55 +++++++++++++++++++++------ 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index 046abede8e..5ab7a87efd 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -808,23 +808,56 @@ class ftp_fsock extends transfer */ function _open_data_connection() { - $this->_send_command('PASV', '', false); - - if (!$ip_port = $this->_check_command(true)) + // Try to find out whether we have a IPv4 or IPv6 (control) connection + if (function_exists('stream_socket_get_name')) { - return false; + $socket_name = stream_socket_get_name($this->connection, true); + $server_ip = substr($socket_name, 0, strrpos($socket_name, ':')); } - // open the connection to start sending the file - if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) + if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip)) { - // bad ip and port - return false; + // Passive mode + $this->_send_command('PASV', '', false); + + if (!$ip_port = $this->_check_command(true)) + { + return false; + } + + // open the connection to start sending the file + if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) + { + // bad ip and port + return false; + } + + $temp = explode(',', $temp[0]); + $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; + $server_port = $temp[4] * 256 + $temp[5]; + } + else + { + // Extended Passive Mode - RFC2428 + $this->_send_command('EPSV', '', false); + + if (!$epsv_response = $this->_check_command(true)) + { + return false; + } + + // Response looks like "229 Entering Extended Passive Mode (|||12345|)" + // where 12345 is the tcp port for the data connection + if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match)) + { + return false; + } + $server_port = (int) $match[1]; + + // fsockopen expects IPv6 address in square brackets + $server_ip = "[$server_ip]"; } - $temp = explode(',', $temp[0]); - $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; - $server_port = $temp[4] * 256 + $temp[5]; $errno = 0; $errstr = ''; From 18f19b03ab703d0eb09627dcd162ba556316a451 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Wed, 10 Aug 2011 16:43:43 +0200 Subject: [PATCH 02/11] [ticket/9297] Unit tests for ftp_fsock PASV and EPSV. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/network/ftp_fsock_test.php diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php new file mode 100644 index 0000000000..c6364f7383 --- /dev/null +++ b/tests/network/ftp_fsock_test.php @@ -0,0 +1,48 @@ +assert_ls_contains_debian($ipv4); + $this->assert_ls_contains_debian("[$ipv6]"); + } + + protected function assert_ls_contains_debian($hostname) + { + $o = $this->get_object($hostname); + $o->_init(); + $this->assertContains('debian', $o->_ls()); + $o->_close(); + } + + protected function get_object($hostname) + { + return new ftp_fsock($hostname, 'anonymous', 'anonymous@localost.tld', '/'); + } +} From 83fa6cffc3be5e89c9c5a992f02366d79aaf0406 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 11 Aug 2011 23:10:53 +0200 Subject: [PATCH 03/11] [ticket/9297] Make EPSV unit tests work without IPv6. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php index c6364f7383..8b97a1c59d 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_test.php @@ -17,20 +17,19 @@ class phpbb_ftp_fsock_test extends phpbb_test_case { public function test_pasv_epsv() { - foreach (dns_get_record('ftp.debian.org', DNS_A | DNS_AAAA) as $row) + $hostname = 'ftp.debian.org.'; + $ipv4 = gethostbyname($hostname); + + if ($ipv4 == $hostname) { - if (isset($row['ip'])) - { - $ipv4 = $row['ip']; - } - else if (isset($row['ipv6'])) - { - $ipv6 = $row['ipv6']; - } + $this->markTestSkipped("Got no A record back from DNS query for $hostname"); } + // PASV $this->assert_ls_contains_debian($ipv4); - $this->assert_ls_contains_debian("[$ipv6]"); + + // EPSV + $this->assert_ls_contains_debian("[::ffff:$ipv4]"); } protected function assert_ls_contains_debian($hostname) From 7a40ab8f7a520ee5d446ce3cdebe130338c74fd5 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sun, 14 Aug 2011 18:17:16 +0200 Subject: [PATCH 04/11] [ticket/9297] Update copyright year of unit test file. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php index 8b97a1c59d..0470e63126 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_test.php @@ -2,7 +2,7 @@ /** * * @package testing -* @copyright (c) 2010 phpBB Group +* @copyright (c) 2011 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License * */ From 386883cda1b0be64a77ddeaff1b5a52acaa97648 Mon Sep 17 00:00:00 2001 From: Oleg Pudeyev Date: Sun, 14 Aug 2011 13:19:09 -0400 Subject: [PATCH 05/11] [ticket/9297] Separate ipv4 and ipv6 tests into separate functions. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php index 0470e63126..ab45c0202b 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_test.php @@ -15,19 +15,28 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php'; */ class phpbb_ftp_fsock_test extends phpbb_test_case { - public function test_pasv_epsv() + static protected $ipv4; + + static public function setUpBeforeClass() { $hostname = 'ftp.debian.org.'; - $ipv4 = gethostbyname($hostname); + self::$ipv4 = gethostbyname($hostname); - if ($ipv4 == $hostname) + if (self::$ipv4 == $hostname) { $this->markTestSkipped("Got no A record back from DNS query for $hostname"); } + } + public function test_pasv() + { // PASV - $this->assert_ls_contains_debian($ipv4); + $this->assert_ls_contains_debian(self::$ipv4); + } + public function test_epsv() + { + $ipv4 = self::$ipv4; // EPSV $this->assert_ls_contains_debian("[::ffff:$ipv4]"); } From 2973ccbd48f9cc8a16cfad8f3ab0e9fc36b36763 Mon Sep 17 00:00:00 2001 From: Oleg Pudeyev Date: Sun, 14 Aug 2011 14:11:58 -0400 Subject: [PATCH 06/11] [ticket/9297] Skip FTP PASV/EPSV test if FTP connection fails. It is possible to configure PHP without IPv6, in which case IPv6-encapsulated IPv4 addresses won't be accepted by PHP. Instead of failing the test suite on such setups, skip the offending test. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php index ab45c0202b..93b15074db 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_test.php @@ -44,7 +44,16 @@ class phpbb_ftp_fsock_test extends phpbb_test_case protected function assert_ls_contains_debian($hostname) { $o = $this->get_object($hostname); - $o->_init(); + $result = $o->_init(); + // PHP can connect to IPv6 addresses which are IPv6-encapsulated + // IPv4 addresses on systems that don't have IPv6 connectivity, + // provided that PHP was built with IPv6 support. + // If this test fails on such an IPv6-encapsulated IPv4 address, + // check whether you disabled IPv6 support in your PHP. + if ($result !== true) + { + $this->markTestSkipped("Failed to connect to $hostname: $result"); + } $this->assertContains('debian', $o->_ls()); $o->_close(); } From c2114920925d753e7286145c01c7ef7486362619 Mon Sep 17 00:00:00 2001 From: Oleg Pudeyev Date: Sun, 14 Aug 2011 14:33:00 -0400 Subject: [PATCH 07/11] [ticket/9297] Fix markTestSkipped call in setUpBeforeClass. Need to use the static version here. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php index 93b15074db..b801ae4037 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_test.php @@ -24,7 +24,7 @@ class phpbb_ftp_fsock_test extends phpbb_test_case if (self::$ipv4 == $hostname) { - $this->markTestSkipped("Got no A record back from DNS query for $hostname"); + self::markTestSkipped("Got no A record back from DNS query for $hostname"); } } From 2a0c9e4026d3f8e1f5bcfc9e00319ba4515f0b2f Mon Sep 17 00:00:00 2001 From: Oleg Pudeyev Date: Sun, 14 Aug 2011 14:42:53 -0400 Subject: [PATCH 08/11] [ticket/9297] Adjust comment - IPv6 is needed for IPv6 connections to work. Looks like IPv6-encapsulated IPv4 addresses do not actually work if the host has no IPv6 connectivity. PHPBB3-9297 --- tests/network/ftp_fsock_test.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_test.php index b801ae4037..cfffe8fd67 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_test.php @@ -45,11 +45,9 @@ class phpbb_ftp_fsock_test extends phpbb_test_case { $o = $this->get_object($hostname); $result = $o->_init(); - // PHP can connect to IPv6 addresses which are IPv6-encapsulated - // IPv4 addresses on systems that don't have IPv6 connectivity, - // provided that PHP was built with IPv6 support. - // If this test fails on such an IPv6-encapsulated IPv4 address, - // check whether you disabled IPv6 support in your PHP. + // This test may fail on IPv6 addresses if IPv6 support is + // not available. PHP must be compiled with IPv6 support enabled, + // and your operating system must be configured for IPv6 as well. if ($result !== true) { $this->markTestSkipped("Failed to connect to $hostname: $result"); From a7e709d92092de1eb9b0e35f45f1679ee10ce39b Mon Sep 17 00:00:00 2001 From: Oleg Pudeyev Date: Sun, 14 Aug 2011 14:47:16 -0400 Subject: [PATCH 09/11] [ticket/9297] Rename test class to reflect its contents. setUpBeforeClass logic makes this test specific to PASV/EPSV tests. PHPBB3-9297 --- .../{ftp_fsock_test.php => ftp_fsock_pasv_epsv_test.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/network/{ftp_fsock_test.php => ftp_fsock_pasv_epsv_test.php} (95%) diff --git a/tests/network/ftp_fsock_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php similarity index 95% rename from tests/network/ftp_fsock_test.php rename to tests/network/ftp_fsock_pasv_epsv_test.php index cfffe8fd67..af45fc2d61 100644 --- a/tests/network/ftp_fsock_test.php +++ b/tests/network/ftp_fsock_pasv_epsv_test.php @@ -13,7 +13,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php'; /** * @group slow */ -class phpbb_ftp_fsock_test extends phpbb_test_case +class phpbb_ftp_fsock_pasv_epsv_test extends phpbb_test_case { static protected $ipv4; From 702985c9279eb9b4704deb9e4356fe37e60b68a2 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sun, 14 Aug 2011 20:55:21 +0200 Subject: [PATCH 10/11] [ticket/9297] Fix typo in localhost. PHPBB3-9297 --- tests/network/ftp_fsock_pasv_epsv_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/network/ftp_fsock_pasv_epsv_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php index af45fc2d61..110bd702a5 100644 --- a/tests/network/ftp_fsock_pasv_epsv_test.php +++ b/tests/network/ftp_fsock_pasv_epsv_test.php @@ -58,6 +58,6 @@ class phpbb_ftp_fsock_pasv_epsv_test extends phpbb_test_case protected function get_object($hostname) { - return new ftp_fsock($hostname, 'anonymous', 'anonymous@localost.tld', '/'); + return new ftp_fsock($hostname, 'anonymous', 'anonymous@localhost.tld', '/'); } } From 02a8cebd65111442f63d4819b74e27c8cbd61006 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sun, 14 Aug 2011 21:40:02 +0200 Subject: [PATCH 11/11] [ticket/9297] Add network to class name of unit tests. PHPBB3-9297 --- tests/network/ftp_fsock_pasv_epsv_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/network/ftp_fsock_pasv_epsv_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php index 110bd702a5..6ad811e3ca 100644 --- a/tests/network/ftp_fsock_pasv_epsv_test.php +++ b/tests/network/ftp_fsock_pasv_epsv_test.php @@ -13,7 +13,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php'; /** * @group slow */ -class phpbb_ftp_fsock_pasv_epsv_test extends phpbb_test_case +class phpbb_network_ftp_fsock_pasv_epsv_test extends phpbb_test_case { static protected $ipv4;