1package ProFTPD::Tests::Modules::mod_snmp::ban;
2
3use lib qw(t/lib);
4use base qw(ProFTPD::TestSuite::Child);
5use strict;
6
7use Data::Dumper;
8use File::Spec;
9use IO::Handle;
10
11use ProFTPD::TestSuite::FTP;
12use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
13
14$| = 1;
15
16my $order = 0;
17
18my $TESTS = {
19  snmp_ban_v1_get_conn_info => {
20    order => ++$order,
21    test_class => [qw(forking ban snmp)],
22  },
23
24  snmp_ban_v1_get_ban_info => {
25    order => ++$order,
26    test_class => [qw(forking ban snmp)],
27  },
28
29};
30
31sub new {
32  return shift()->SUPER::new(@_);
33}
34
35sub list_tests {
36  # Check for the required Perl modules:
37  #
38  #  Net-SNMP
39
40  my $required = [qw(
41    Net::SNMP
42  )];
43
44  foreach my $req (@$required) {
45    eval "use $req";
46    if ($@) {
47      print STDERR "\nWARNING:\n + Module '$req' not found, skipping all tests\n
48";
49
50      if ($ENV{TEST_VERBOSE}) {
51        print STDERR "Unable to load $req: $@\n";
52      }
53
54      return qw(testsuite_empty_test);
55    }
56  }
57
58  return testsuite_get_runnable_tests($TESTS);
59}
60
61# Support routines
62
63sub get_ban_conn_info {
64  my $agent_port = shift;
65  my $snmp_community = shift;
66
67  my ($snmp_sess, $snmp_err) = Net::SNMP->session(
68    -hostname => '127.0.0.1',
69    -port => $agent_port,
70    -version => 'snmpv1',
71    -community => $snmp_community,
72    -retries => 1,
73    -timeout => 3,
74    -translate => 1,
75  );
76  unless ($snmp_sess) {
77    die("Unable to create Net::SNMP session: $snmp_err");
78  }
79
80  if ($ENV{TEST_VERBOSE}) {
81    # From the Net::SNMP debug perldocs
82    my $debug_mask = (0x02|0x10|0x20);
83    $snmp_sess->debug($debug_mask);
84  }
85
86  # ban.connections.connectionBannedTotal
87  my $conn_banned_total_oid = '1.3.6.1.4.1.17852.2.2.9.1.1.0';
88
89  # ban.connections.userBannedTotal
90  my $user_banned_total_oid = '1.3.6.1.4.1.17852.2.2.9.1.2.0';
91
92  # ban.connections.hostBannedTotal
93  my $host_banned_total_oid = '1.3.6.1.4.1.17852.2.2.9.1.3.0';
94
95  # ban.connections.classBannedTotal
96  my $class_banned_total_oid = '1.3.6.1.4.1.17852.2.2.9.1.4.0';
97
98  my $oids = [
99    $conn_banned_total_oid,
100    $user_banned_total_oid,
101    $host_banned_total_oid,
102    $class_banned_total_oid,
103  ];
104
105  my $snmp_resp = $snmp_sess->get_request(
106    -varbindList => $oids,
107  );
108  unless ($snmp_resp) {
109    die("No SNMP response received: " . $snmp_sess->error());
110  }
111
112  my ($conn_banned_total, $user_banned_total, $host_banned_total, $class_banned_total);
113
114  # Do we have the requested OIDs in the response?
115
116  foreach my $oid (@$oids) {
117    unless (defined($snmp_resp->{$oid})) {
118      die("Missing required OID $oid in response");
119    }
120
121    my $value = $snmp_resp->{$oid};
122    if ($ENV{TEST_VERBOSE}) {
123      print STDERR "Requested OID $oid = $value\n";
124    }
125
126    if ($oid eq $conn_banned_total_oid) {
127      $conn_banned_total = $value;
128
129    } elsif ($oid eq $user_banned_total_oid) {
130      $user_banned_total = $value;
131
132    } elsif ($oid eq $host_banned_total_oid) {
133      $host_banned_total = $value;
134
135    } elsif ($oid eq $class_banned_total_oid) {
136      $class_banned_total = $value;
137    }
138  }
139
140  $snmp_sess->close();
141  $snmp_sess = undef;
142
143  return ($conn_banned_total, $user_banned_total, $host_banned_total, $class_banned_total);
144}
145
146sub get_ban_ban_info {
147  my $agent_port = shift;
148  my $snmp_community = shift;
149
150  my ($snmp_sess, $snmp_err) = Net::SNMP->session(
151    -hostname => '127.0.0.1',
152    -port => $agent_port,
153    -version => 'snmpv1',
154    -community => $snmp_community,
155    -retries => 1,
156    -timeout => 3,
157    -translate => 1,
158  );
159  unless ($snmp_sess) {
160    die("Unable to create Net::SNMP session: $snmp_err");
161  }
162
163  if ($ENV{TEST_VERBOSE}) {
164    # From the Net::SNMP debug perldocs
165    my $debug_mask = (0x02|0x10|0x20);
166    $snmp_sess->debug($debug_mask);
167  }
168
169  # ban.bans.banCount
170  my $ban_count_oid = '1.3.6.1.4.1.17852.2.2.9.2.1.0';
171
172  # ban.bans.banTotal
173  my $ban_total_oid = '1.3.6.1.4.1.17852.2.2.9.2.2.0';
174
175  # ban.bans.userBanCount
176  my $user_ban_count_oid = '1.3.6.1.4.1.17852.2.2.9.2.3.0';
177
178  # ban.bans.userBanTotal
179  my $user_ban_total_oid = '1.3.6.1.4.1.17852.2.2.9.2.4.0';
180
181  # ban.bans.hostBanCount
182  my $host_ban_count_oid = '1.3.6.1.4.1.17852.2.2.9.2.5.0';
183
184  # ban.bans.hostBanTotal
185  my $host_ban_total_oid = '1.3.6.1.4.1.17852.2.2.9.2.6.0';
186
187  # ban.bans.classBanCount
188  my $class_ban_count_oid = '1.3.6.1.4.1.17852.2.2.9.2.7.0';
189
190  # ban.bans.classBanTotal
191  my $class_ban_total_oid = '1.3.6.1.4.1.17852.2.2.9.2.8.0';
192
193  my $oids = [
194    $ban_count_oid,
195    $ban_total_oid,
196    $user_ban_count_oid,
197    $user_ban_total_oid,
198    $host_ban_count_oid,
199    $host_ban_total_oid,
200    $class_ban_count_oid,
201    $class_ban_total_oid,
202  ];
203
204  my $snmp_resp = $snmp_sess->get_request(
205    -varbindList => $oids,
206  );
207  unless ($snmp_resp) {
208    die("No SNMP response received: " . $snmp_sess->error());
209  }
210
211  my ($ban_count, $ban_total);
212  my ($user_ban_count, $user_ban_total);
213  my ($host_ban_count, $host_ban_total);
214  my ($class_ban_count, $class_ban_total);
215
216  # Do we have the requested OIDs in the response?
217
218  foreach my $oid (@$oids) {
219    unless (defined($snmp_resp->{$oid})) {
220      die("Missing required OID $oid in response");
221    }
222
223    my $value = $snmp_resp->{$oid};
224    if ($ENV{TEST_VERBOSE}) {
225      print STDERR "Requested OID $oid = $value\n";
226    }
227
228    if ($oid eq $ban_count_oid) {
229      $ban_count = $value;
230
231    } elsif ($oid eq $ban_total_oid) {
232      $ban_total = $value;
233
234    } elsif ($oid eq $user_ban_count_oid) {
235      $user_ban_count = $value;
236
237    } elsif ($oid eq $user_ban_total_oid) {
238      $user_ban_total = $value;
239
240    } elsif ($oid eq $host_ban_count_oid) {
241      $host_ban_count = $value;
242
243    } elsif ($oid eq $host_ban_total_oid) {
244      $host_ban_total = $value;
245
246    } elsif ($oid eq $class_ban_count_oid) {
247      $class_ban_count = $value;
248
249    } elsif ($oid eq $class_ban_total_oid) {
250      $class_ban_total = $value;
251    }
252  }
253
254  $snmp_sess->close();
255  $snmp_sess = undef;
256
257  return {
258    ban_count => $ban_count,
259    ban_total => $ban_total,
260    user_ban_count => $user_ban_count,
261    user_ban_total => $user_ban_total,
262    host_ban_count => $host_ban_count,
263    host_ban_total => $host_ban_total,
264    class_ban_count => $class_ban_count,
265    class_ban_total => $class_ban_total,
266  };
267}
268
269# Test cases
270
271sub snmp_ban_v1_get_conn_info {
272  my $self = shift;
273  my $tmpdir = $self->{tmpdir};
274
275  my $config_file = "$tmpdir/snmp.conf";
276  my $pid_file = File::Spec->rel2abs("$tmpdir/snmp.pid");
277  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/snmp.scoreboard");
278
279  my $log_file = test_get_logfile();
280
281  my $auth_user_file = File::Spec->rel2abs("$tmpdir/snmp.passwd");
282  my $auth_group_file = File::Spec->rel2abs("$tmpdir/snmp.group");
283
284  my $user = 'proftpd';
285  my $passwd = 'test';
286  my $group = 'ftpd';
287  my $home_dir = File::Spec->rel2abs($tmpdir);
288  my $uid = 500;
289  my $gid = 500;
290
291  my $ban_tab = File::Spec->rel2abs("$tmpdir/ban.tab");
292  my $table_dir = File::Spec->rel2abs("$tmpdir/var/snmp");
293
294  # Make sure that, if we're running as root, that the home directory has
295  # permissions/privs set for the account we create
296  if ($< == 0) {
297    unless (chmod(0755, $home_dir, $table_dir)) {
298      die("Can't set perms on $home_dir to 0755: $!");
299    }
300
301    unless (chown($uid, $gid, $home_dir, $table_dir)) {
302      die("Can't set owner of $home_dir to $uid/$gid: $!");
303    }
304  }
305
306  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
307    '/bin/bash');
308  auth_group_write($auth_group_file, $group, $gid, $user);
309
310  my $agent_port = ProFTPD::TestSuite::Utils::get_high_numbered_port();
311  my $snmp_community = "public";
312
313  my $ban_expiry_secs = 5;
314  my $timeout_idle = 20;
315
316  my $config = {
317    TraceLog => $log_file,
318    Trace => 'event:10 snmp:20 snmp.asn1:20 snmp.db:20 snmp.msg:20 snmp.pdu:20 snmp.smi:20',
319    PidFile => $pid_file,
320    ScoreboardFile => $scoreboard_file,
321    SystemLog => $log_file,
322
323    AuthUserFile => $auth_user_file,
324    AuthGroupFile => $auth_group_file,
325
326    MaxLoginAttempts => 2,
327
328    IfModules => {
329      'mod_ban.c' => {
330        BanEngine => 'on',
331        BanLog => $log_file,
332
333        # This says to ban a client which exceeds the MaxLoginAttempts
334        # limit once within the last 1 minute will be banned for 5 secs
335        BanOnEvent => 'MaxLoginAttempts 1/00:01:00 00:00:05',
336
337        BanTable => $ban_tab,
338      },
339
340      'mod_delay.c' => {
341        DelayEngine => 'off',
342      },
343
344      'mod_snmp.c' => {
345        SNMPAgent => "master 127.0.0.1:$agent_port",
346        SNMPCommunity => $snmp_community,
347        SNMPEngine => 'on',
348        SNMPLog => $log_file,
349        SNMPTables => $table_dir,
350      },
351    },
352  };
353
354  my ($port, $config_user, $config_group) = config_write($config_file, $config);
355
356  # Open pipes, for use between the parent and child processes.  Specifically,
357  # the child will indicate when it's done with its test by writing a message
358  # to the parent.
359  my ($rfh, $wfh);
360  unless (pipe($rfh, $wfh)) {
361    die("Can't open pipe: $!");
362  }
363
364  require Net::SNMP;
365
366  my $ex;
367
368  # Fork child
369  $self->handle_sigchld();
370  defined(my $pid = fork()) or die("Can't fork: $!");
371  if ($pid) {
372    eval {
373      # Give the server time to start up
374      sleep(1);
375
376      my $expected;
377
378      # First, get the conn stats
379      my ($conn_banned, $user_banned, $host_banned, $class_banned) = get_ban_conn_info($agent_port, $snmp_community);
380
381      $expected = 0;
382      $self->assert($conn_banned == $expected,
383        test_msg("Expected connection banned total $expected, got $conn_banned"));
384
385      $expected = 0;
386      $self->assert($user_banned == $expected,
387        test_msg("Expected user banned total $expected, got $user_banned"));
388
389      $expected = 0;
390      $self->assert($host_banned == $expected,
391        test_msg("Expected host banned total $expected, got $host_banned"));
392
393      $expected = 0;
394      $self->assert($class_banned == $expected,
395        test_msg("Expected class banned total $expected, got $class_banned"));
396
397      # Now connect, and trigger a ban
398      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
399      eval { $client->login($user, 'foo') };
400      unless ($@) {
401        die("Login succeeded unexpectedly");
402      }
403
404      my $resp_code = $client->response_code();
405      my $resp_msg = $client->response_msg();
406
407      $expected = 530;
408      $self->assert($expected == $resp_code,
409        test_msg("Expected response code $expected, got $resp_code"));
410
411      $expected = "Login incorrect.";
412      $self->assert($expected eq $resp_msg,
413        test_msg("Expected response message '$expected', got '$resp_msg'"));
414
415      eval { $client->login($user, 'foo') };
416      unless ($@) {
417        die("Login succeeded unexpectedly");
418      }
419
420      $resp_code = $client->response_code();
421      $resp_msg = $client->response_msg();
422
423      $expected = 530;
424      $self->assert($expected == $resp_code,
425        test_msg("Expected response code $expected, got $resp_code"));
426
427      $expected = "Login incorrect.";
428      $self->assert($expected eq $resp_msg,
429        test_msg("Expected response message '$expected', got '$resp_msg'"));
430
431      # Now try again with the correct info; we should be banned.  Note
432      # that we have to create a separate connection for this.
433      eval { $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port,
434        undef, 0) };
435      unless ($@) {
436        die("Connect succeeded unexpectedly");
437      }
438
439      # Double-check that the conn stats are now what we expect
440      ($conn_banned, $user_banned, $host_banned, $class_banned) = get_ban_conn_info($agent_port, $snmp_community);
441
442      $expected = 1;
443      $self->assert($conn_banned == $expected,
444        test_msg("Expected connection banned total $expected, got $conn_banned"));
445
446      $expected = 0;
447      $self->assert($user_banned == $expected,
448        test_msg("Expected user banned total $expected, got $user_banned"));
449
450      $expected = 1;
451      $self->assert($host_banned == $expected,
452        test_msg("Expected host banned total $expected, got $host_banned"));
453
454      $expected = 0;
455      $self->assert($class_banned == $expected,
456        test_msg("Expected class banned total $expected, got $class_banned"));
457
458      # Now wait for the ban to expire, then try again (and check stats)
459      sleep($ban_expiry_secs + 1);
460
461      $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
462      eval { $client->login($user, 'foo') };
463      unless ($@) {
464        die("Login succeeded unexpectedly");
465      }
466
467      $resp_code = $client->response_code();
468      $resp_msg = $client->response_msg();
469
470      $expected = 530;
471      $self->assert($expected == $resp_code,
472        test_msg("Expected response code $expected, got $resp_code"));
473
474      $expected = "Login incorrect.";
475      $self->assert($expected eq $resp_msg,
476        test_msg("Expected response message '$expected', got '$resp_msg'"));
477
478      ($conn_banned, $user_banned, $host_banned, $class_banned) = get_ban_conn_info($agent_port, $snmp_community);
479
480      $expected = 1;
481      $self->assert($conn_banned == $expected,
482        test_msg("Expected connection banned total $expected, got $conn_banned"));
483
484      $expected = 0;
485      $self->assert($user_banned == $expected,
486        test_msg("Expected user banned total $expected, got $user_banned"));
487
488      $expected = 1;
489      $self->assert($host_banned == $expected,
490        test_msg("Expected host banned total $expected, got $host_banned"));
491
492      $expected = 0;
493      $self->assert($class_banned == $expected,
494        test_msg("Expected class banned total $expected, got $class_banned"));
495
496    };
497
498    if ($@) {
499      $ex = $@;
500    }
501
502    $wfh->print("done\n");
503    $wfh->flush();
504
505  } else {
506    eval { server_wait($config_file, $rfh, $timeout_idle) };
507    if ($@) {
508      warn($@);
509      exit 1;
510    }
511
512    exit 0;
513  }
514
515  # Stop server
516  server_stop($pid_file);
517
518  $self->assert_child_ok($pid);
519
520  if ($ex) {
521    test_append_logfile($log_file, $ex);
522    unlink($log_file);
523
524    die($ex);
525  }
526
527  unlink($log_file);
528}
529
530sub snmp_ban_v1_get_ban_info {
531  my $self = shift;
532  my $tmpdir = $self->{tmpdir};
533
534  my $config_file = "$tmpdir/snmp.conf";
535  my $pid_file = File::Spec->rel2abs("$tmpdir/snmp.pid");
536  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/snmp.scoreboard");
537
538  my $log_file = test_get_logfile();
539
540  my $auth_user_file = File::Spec->rel2abs("$tmpdir/snmp.passwd");
541  my $auth_group_file = File::Spec->rel2abs("$tmpdir/snmp.group");
542
543  my $user = 'proftpd';
544  my $passwd = 'test';
545  my $group = 'ftpd';
546  my $home_dir = File::Spec->rel2abs($tmpdir);
547  my $uid = 500;
548  my $gid = 500;
549
550  my $ban_tab = File::Spec->rel2abs("$tmpdir/ban.tab");
551  my $table_dir = File::Spec->rel2abs("$tmpdir/var/snmp");
552
553  # Make sure that, if we're running as root, that the home directory has
554  # permissions/privs set for the account we create
555  if ($< == 0) {
556    unless (chmod(0755, $home_dir, $table_dir)) {
557      die("Can't set perms on $home_dir to 0755: $!");
558    }
559
560    unless (chown($uid, $gid, $home_dir, $table_dir)) {
561      die("Can't set owner of $home_dir to $uid/$gid: $!");
562    }
563  }
564
565  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
566    '/bin/bash');
567  auth_group_write($auth_group_file, $group, $gid, $user);
568
569  my $agent_port = ProFTPD::TestSuite::Utils::get_high_numbered_port();
570  my $snmp_community = "public";
571
572  my $ban_expiry_secs = 5;
573  my $timeout_idle = 45;
574
575  my $config = {
576    TraceLog => $log_file,
577    Trace => 'event:10 snmp:20 snmp.asn1:20 snmp.db:20 snmp.msg:20 snmp.pdu:20 snmp.smi:20',
578    PidFile => $pid_file,
579    ScoreboardFile => $scoreboard_file,
580    SystemLog => $log_file,
581
582    AuthUserFile => $auth_user_file,
583    AuthGroupFile => $auth_group_file,
584
585    MaxClientsPerHost => 1,
586
587    IfModules => {
588      'mod_ban.c' => {
589        BanEngine => 'on',
590        BanLog => $log_file,
591
592        # This says to ban a client which exceeds the MaxClientsPerHost
593        # limit once within the last 2 minutes will be banned for 5 secs
594        BanOnEvent => 'MaxClientsPerHost 1/00:02:00 00:00:05',
595
596        BanTable => $ban_tab,
597      },
598
599      'mod_delay.c' => {
600        DelayEngine => 'off',
601      },
602
603      'mod_snmp.c' => {
604        SNMPAgent => "master 127.0.0.1:$agent_port",
605        SNMPCommunity => $snmp_community,
606        SNMPEngine => 'on',
607        SNMPLog => $log_file,
608        SNMPTables => $table_dir,
609      },
610    },
611  };
612
613  my ($port, $config_user, $config_group) = config_write($config_file, $config);
614
615  # Open pipes, for use between the parent and child processes.  Specifically,
616  # the child will indicate when it's done with its test by writing a message
617  # to the parent.
618  my ($rfh, $wfh);
619  unless (pipe($rfh, $wfh)) {
620    die("Can't open pipe: $!");
621  }
622
623  require Net::SNMP;
624
625  my $ex;
626
627  # Fork child
628  $self->handle_sigchld();
629  defined(my $pid = fork()) or die("Can't fork: $!");
630  if ($pid) {
631    eval {
632      # Give the server time to start up
633      sleep(1);
634
635      my $expected;
636
637      # First, get the ban stats
638      my $ban_info = get_ban_ban_info($agent_port, $snmp_community);
639
640      $expected = 0;
641      $self->assert($ban_info->{ban_count} == $expected,
642        test_msg("Expected ban count $expected, got $ban_info->{ban_count}"));
643
644      $expected = 0;
645      $self->assert($ban_info->{ban_total} == $expected,
646        test_msg("Expected ban total $expected, got $ban_info->{ban_total}"));
647
648      $expected = 0;
649      $self->assert($ban_info->{user_ban_count} == $expected,
650        test_msg("Expected user ban count $expected, got $ban_info->{user_ban_count}"));
651
652      $expected = 0;
653      $self->assert($ban_info->{user_ban_total} == $expected,
654        test_msg("Expected user ban total $expected, got $ban_info->{user_ban_total}"));
655
656      $expected = 0;
657      $self->assert($ban_info->{host_ban_count} == $expected,
658        test_msg("Expected host ban count $expected, got $ban_info->{host_ban_count}"));
659
660      $expected = 0;
661      $self->assert($ban_info->{host_ban_total} == $expected,
662        test_msg("Expected host ban total $expected, got $ban_info->{host_ban_total}"));
663
664      $expected = 0;
665      $self->assert($ban_info->{class_ban_count} == $expected,
666        test_msg("Expected class ban count $expected, got $ban_info->{class_ban_count}"));
667
668      $expected = 0;
669      $self->assert($ban_info->{class_ban_total} == $expected,
670        test_msg("Expected class ban total $expected, got $ban_info->{class_ban_total}"));
671
672      # Now connect, and trigger a ban
673      my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
674      $client1->login($user, $passwd);
675
676      my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
677      eval { $client2->login($user, $passwd) };
678
679      # Now try again with the correct info; we should be banned.  Note
680      # that we have to create a separate connection for this.
681      eval { my $client3 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port,
682        undef, 0) };
683      unless ($@) {
684        die("Connect succeeded unexpectedly");
685      }
686
687      # Double-check that the ban stats are now what we expect
688      $ban_info = get_ban_ban_info($agent_port, $snmp_community);
689
690      $expected = 1;
691      $self->assert($ban_info->{ban_count} == $expected,
692        test_msg("Expected ban count $expected, got $ban_info->{ban_count}"));
693
694      $expected = 1;
695      $self->assert($ban_info->{ban_total} == $expected,
696        test_msg("Expected ban total $expected, got $ban_info->{ban_total}"));
697
698      $expected = 0;
699      $self->assert($ban_info->{user_ban_count} == $expected,
700        test_msg("Expected user ban count $expected, got $ban_info->{user_ban_count}"));
701
702      $expected = 0;
703      $self->assert($ban_info->{user_ban_total} == $expected,
704        test_msg("Expected user ban total $expected, got $ban_info->{user_ban_total}"));
705
706      $expected = 1;
707      $self->assert($ban_info->{host_ban_count} == $expected,
708        test_msg("Expected host ban count $expected, got $ban_info->{host_ban_count}"));
709
710      $expected = 1;
711      $self->assert($ban_info->{host_ban_total} == $expected,
712        test_msg("Expected host ban total $expected, got $ban_info->{host_ban_total}"));
713
714      $expected = 0;
715      $self->assert($ban_info->{class_ban_count} == $expected,
716        test_msg("Expected class ban count $expected, got $ban_info->{class_ban_count}"));
717
718      $expected = 0;
719      $self->assert($ban_info->{class_ban_total} == $expected,
720        test_msg("Expected class ban total $expected, got $ban_info->{class_ban_total}"));
721
722      # Now wait for the ban to expire, then try again (and check stats)
723      sleep($ban_expiry_secs + 2);
724
725      $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
726      $client1->login($user, $passwd);
727      $client1->quit();
728
729      # And check the ban stats one more time
730      $ban_info = get_ban_ban_info($agent_port, $snmp_community);
731
732      $expected = 0;
733      $self->assert($ban_info->{ban_count} == $expected,
734        test_msg("Expected ban count $expected, got $ban_info->{ban_count}"));
735
736      $expected = 1;
737      $self->assert($ban_info->{ban_total} == $expected,
738        test_msg("Expected ban total $expected, got $ban_info->{ban_total}"));
739
740      $expected = 0;
741      $self->assert($ban_info->{user_ban_count} == $expected,
742        test_msg("Expected user ban count $expected, got $ban_info->{user_ban_count}"));
743
744      $expected = 0;
745      $self->assert($ban_info->{user_ban_total} == $expected,
746        test_msg("Expected user ban total $expected, got $ban_info->{user_ban_total}"));
747
748      $expected = 0;
749      $self->assert($ban_info->{host_ban_count} == $expected,
750        test_msg("Expected host ban count $expected, got $ban_info->{host_ban_count}"));
751
752      $expected = 1;
753      $self->assert($ban_info->{host_ban_total} == $expected,
754        test_msg("Expected host ban total $expected, got $ban_info->{host_ban_total}"));
755
756      $expected = 0;
757      $self->assert($ban_info->{class_ban_count} == $expected,
758        test_msg("Expected class ban count $expected, got $ban_info->{class_ban_count}"));
759
760      $expected = 0;
761      $self->assert($ban_info->{class_ban_total} == $expected,
762        test_msg("Expected class ban total $expected, got $ban_info->{class_ban_total}"));
763    };
764
765    if ($@) {
766      $ex = $@;
767    }
768
769    $wfh->print("done\n");
770    $wfh->flush();
771
772  } else {
773    eval { server_wait($config_file, $rfh, $timeout_idle) };
774    if ($@) {
775      warn($@);
776      exit 1;
777    }
778
779    exit 0;
780  }
781
782  # Stop server
783  server_stop($pid_file);
784
785  $self->assert_child_ok($pid);
786
787  if ($ex) {
788    test_append_logfile($log_file, $ex);
789    unlink($log_file);
790
791    die($ex);
792  }
793
794  unlink($log_file);
795}
796
7971;
798