2234 lines
47 KiB
C
2234 lines
47 KiB
C
|
package ProFTPD::Tests::Modules::mod_proxy_protocol;
|
||
|
|
||
|
use lib qw(t/lib);
|
||
|
use base qw(ProFTPD::TestSuite::Child);
|
||
|
use strict;
|
||
|
|
||
|
use File::Path qw(mkpath);
|
||
|
use File::Spec;
|
||
|
use IO::Handle;
|
||
|
use Net::Cmd qw(CMD_OK);
|
||
|
|
||
|
use ProFTPD::TestSuite::FTP;
|
||
|
use ProFTPD::TestSuite::ProxiedFTP;
|
||
|
use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
|
||
|
|
||
|
$| = 1;
|
||
|
|
||
|
my $order = 0;
|
||
|
|
||
|
my $TESTS = {
|
||
|
proxy_protocol_login_with_proxy => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_login_without_proxy => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_config_denyclass => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_start_of_line => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_end_of_line => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_proto => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_src_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_dns_src_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_dst_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_dns_dst_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_src_port => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_bad_dst_port => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_too_large_src_port => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_too_large_dst_port => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_tcp4_with_ipv6_src_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_tcp4_with_ipv6_dst_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_tcp6_with_ipv4_src_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_tcp6_with_ipv4_dst_addr => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_tcp6_with_useipv6_off => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_matching_src_dst_info => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_unknown_proto => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_active_transfer_with_proxy => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_passive_transfer_with_proxy => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_active_transfer_with_proxy_allowforeignaddress => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
proxy_protocol_passive_transfer_with_proxy_allowforeignaddress => {
|
||
|
order => ++$order,
|
||
|
test_class => [qw(forking mod_proxy_protocol)],
|
||
|
},
|
||
|
|
||
|
};
|
||
|
|
||
|
sub new {
|
||
|
return shift()->SUPER::new(@_);
|
||
|
}
|
||
|
|
||
|
sub list_tests {
|
||
|
return testsuite_get_runnable_tests($TESTS);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_login_with_proxy {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_login_without_proxy {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $proxy_timeout = 1;
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
ProxyProtocolTimeout => $proxy_timeout,
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 1, 1, 1);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, $proxy_timeout + 5) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
if ($ex) {
|
||
|
$ex = undef;
|
||
|
|
||
|
} else {
|
||
|
$ex = "Connection succeeded unexpectedly";
|
||
|
}
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_config_denyclass {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
if (open(my $fh, ">> $setup->{config_file}")) {
|
||
|
print $fh <<EOC;
|
||
|
<Class test>
|
||
|
From 1.1.1.1
|
||
|
</Class>
|
||
|
|
||
|
<Limit LOGIN>
|
||
|
DenyClass test
|
||
|
</Limit>
|
||
|
EOC
|
||
|
unless (close($fh)) {
|
||
|
die("Can't write $setup->{config_file}: $!");
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
die("Can't open $setup->{config_file}: $!");
|
||
|
}
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
eval { $client->login($setup->{user}, $setup->{passwd}) };
|
||
|
unless ($@) {
|
||
|
die("Login succeeded unexpectedly");
|
||
|
}
|
||
|
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_start_of_line {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
"GET /index.html HTTP/1.1.1\r\n")
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_end_of_line {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, '222 ' . 'A' x 128]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_proto {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['IPV4', '1.1.1.1', '2.2.2.2', 111, '222']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_src_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', 'foo', '2.2.2.2', 111, '222']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_dns_src_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', 'localhost', '2.2.2.2', 111, '222']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_dst_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', 'bar', 111, '222']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_dns_dst_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', 'localhost', 111, '222']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_src_port {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 'baz', '222']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_bad_dst_port {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 'quxx']);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_too_large_src_port {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 70000, 222]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_too_large_dst_port {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 70000]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_tcp4_with_ipv6_src_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
UseIPv6 => 'on',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '::1', '2.2.2.2', 111, 222]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_tcp4_with_ipv6_dst_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
UseIPv6 => 'on',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '::2', 111, 222]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_tcp6_with_ipv4_src_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
UseIPv6 => 'on',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP6', '1.1.1.1', '::2', 111, 222]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_tcp6_with_ipv4_dst_addr {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
UseIPv6 => 'on',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP6', '::1', '2.2.2.2', 111, 222]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_tcp6_with_useipv6_off {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
UseIPv6 => 'off',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP6', '::1', '::2', 111, 222]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_matching_src_dst_info {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
eval {
|
||
|
ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '1.1.1.1', 111, 111]);
|
||
|
};
|
||
|
unless ($@) {
|
||
|
die("Connection succeeded unexpectedly");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_unknown_proto {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['UNKNOWN', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_active_transfer_with_proxy {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $test_file = File::Spec->rel2abs("$tmpdir/test.dat");
|
||
|
if (open(my $fh, "> $test_file")) {
|
||
|
print $fh "Hello, World!\n";
|
||
|
|
||
|
unless (close($fh)) {
|
||
|
die("Can't write $test_file: $!");
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
die("Can't open $test_file: $!");
|
||
|
}
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
# Note: If AllowForeignAddress is not allowed, then the PORT command
|
||
|
# will fail with the following e.g. error being logged:
|
||
|
#
|
||
|
# Refused PORT 127,0,0,1,218,225 (address mismatch)
|
||
|
#
|
||
|
AllowForeignAddress => 'off',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
$ENV{FTP_PASSIVE} = 0;
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
|
||
|
if ($client->get('test.dat', '/dev/null')) {
|
||
|
die("RETR test.dat succeeded unexpectedly");
|
||
|
}
|
||
|
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_passive_transfer_with_proxy {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $test_file = File::Spec->rel2abs("$tmpdir/test.dat");
|
||
|
if (open(my $fh, "> $test_file")) {
|
||
|
print $fh "Hello, World!\n";
|
||
|
|
||
|
unless (close($fh)) {
|
||
|
die("Can't write $test_file: $!");
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
die("Can't open $test_file: $!");
|
||
|
}
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
# Note: If AllowForeignAddress is not allowed, then the data transfer
|
||
|
# will fail with the following e.g. error being logged:
|
||
|
#
|
||
|
# SECURITY VIOLATION: Passive connection from 127.0.0.1 rejected.
|
||
|
#
|
||
|
AllowForeignAddress => 'off',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
$ENV{FTP_PASSIVE} = 1;
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
|
||
|
if ($client->get('test.dat', '/dev/null')) {
|
||
|
die("RETR test.dat succeeded unexpectedly");
|
||
|
}
|
||
|
|
||
|
# Note: we should send QUIT here, but because proftpd treated this as
|
||
|
# a security violation, it terminated the control connection as well.
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_active_transfer_with_proxy_allowforeignaddress {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $test_file = File::Spec->rel2abs("$tmpdir/test.dat");
|
||
|
if (open(my $fh, "> $test_file")) {
|
||
|
print $fh "Hello, World!\n";
|
||
|
|
||
|
unless (close($fh)) {
|
||
|
die("Can't write $test_file: $!");
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
die("Can't open $test_file: $!");
|
||
|
}
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
# Note: If AllowForeignAddress is not allowed, then the PORT command
|
||
|
# will fail with the following e.g. error being logged:
|
||
|
#
|
||
|
# Refused PORT 127,0,0,1,218,225 (address mismatch)
|
||
|
#
|
||
|
AllowForeignAddress => 'on',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
$ENV{FTP_PASSIVE} = 0;
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
|
||
|
unless ($client->get('test.dat', '/dev/null')) {
|
||
|
die("RETR test.dat failed: " . $client->code . " " . $client->message);
|
||
|
}
|
||
|
|
||
|
my $resp_code = $client->code;
|
||
|
my $expected = 226;
|
||
|
$self->assert($expected == $resp_code,
|
||
|
test_msg("Expected response code $expected, got $resp_code"));
|
||
|
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
sub proxy_protocol_passive_transfer_with_proxy_allowforeignaddress {
|
||
|
my $self = shift;
|
||
|
my $tmpdir = $self->{tmpdir};
|
||
|
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
||
|
|
||
|
my $test_file = File::Spec->rel2abs("$tmpdir/test.dat");
|
||
|
if (open(my $fh, "> $test_file")) {
|
||
|
print $fh "Hello, World!\n";
|
||
|
|
||
|
unless (close($fh)) {
|
||
|
die("Can't write $test_file: $!");
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
die("Can't open $test_file: $!");
|
||
|
}
|
||
|
|
||
|
my $config = {
|
||
|
PidFile => $setup->{pid_file},
|
||
|
ScoreboardFile => $setup->{scoreboard_file},
|
||
|
SystemLog => $setup->{log_file},
|
||
|
|
||
|
AuthUserFile => $setup->{auth_user_file},
|
||
|
AuthGroupFile => $setup->{auth_group_file},
|
||
|
|
||
|
# Note: If AllowForeignAddress is not allowed, then the data transfer
|
||
|
# will fail with the following e.g. error being logged:
|
||
|
#
|
||
|
# SECURITY VIOLATION: Passive connection from 127.0.0.1 rejected.
|
||
|
#
|
||
|
AllowForeignAddress => 'on',
|
||
|
|
||
|
IfModules => {
|
||
|
'mod_delay.c' => {
|
||
|
DelayEngine => 'off',
|
||
|
},
|
||
|
|
||
|
'mod_proxy_protocol.c' => {
|
||
|
ProxyProtocolEngine => 'on',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
||
|
$config);
|
||
|
|
||
|
# Open pipes, for use between the parent and child processes. Specifically,
|
||
|
# the child will indicate when it's done with its test by writing a message
|
||
|
# to the parent.
|
||
|
my ($rfh, $wfh);
|
||
|
unless (pipe($rfh, $wfh)) {
|
||
|
die("Can't open pipe: $!");
|
||
|
}
|
||
|
|
||
|
my $ex;
|
||
|
|
||
|
# Fork child
|
||
|
$self->handle_sigchld();
|
||
|
defined(my $pid = fork()) or die("Can't fork: $!");
|
||
|
if ($pid) {
|
||
|
eval {
|
||
|
sleep(2);
|
||
|
|
||
|
$ENV{FTP_PASSIVE} = 1;
|
||
|
|
||
|
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
||
|
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
||
|
$client->login($setup->{user}, $setup->{passwd});
|
||
|
|
||
|
unless ($client->get('test.dat', '/dev/null')) {
|
||
|
die("RETR test.dat failed: " . $client->code . " " . $client->message);
|
||
|
}
|
||
|
|
||
|
my $resp_code = $client->code;
|
||
|
my $expected = 226;
|
||
|
$self->assert($expected == $resp_code,
|
||
|
test_msg("Expected response code $expected, got $resp_code"));
|
||
|
|
||
|
$client->quit();
|
||
|
};
|
||
|
|
||
|
if ($@) {
|
||
|
$ex = $@;
|
||
|
}
|
||
|
|
||
|
$wfh->print("done\n");
|
||
|
$wfh->flush();
|
||
|
|
||
|
} else {
|
||
|
eval { server_wait($setup->{config_file}, $rfh) };
|
||
|
if ($@) {
|
||
|
warn($@);
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Stop server
|
||
|
server_stop($setup->{pid_file});
|
||
|
|
||
|
$self->assert_child_ok($pid);
|
||
|
|
||
|
test_cleanup($setup->{log_file}, $ex);
|
||
|
}
|
||
|
|
||
|
1;
|