1package ProFTPD::Tests::Config::RLimitMemory;
2
3use lib qw(t/lib);
4use base qw(ProFTPD::TestSuite::Child);
5use strict;
6
7use File::Spec;
8use IO::Handle;
9
10use ProFTPD::TestSuite::FTP;
11use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
12
13$| = 1;
14
15my $order = 0;
16
17my $TESTS = {
18  rlimitmemory_max_bug3571 => {
19    order => ++$order,
20    test_class => [qw(bug forking)],
21  },
22
23  rlimitmemory_session_max_bug3571 => {
24    order => ++$order,
25    test_class => [qw(bug forking)],
26  },
27
28  rlimitmemory_daemon_max => {
29    order => ++$order,
30    test_class => [qw(bug forking)],
31  },
32
33};
34
35sub new {
36  return shift()->SUPER::new(@_);
37}
38
39sub list_tests {
40  return testsuite_get_runnable_tests($TESTS);
41}
42
43sub rlimitmemory_max_bug3571 {
44  my $self = shift;
45  my $tmpdir = $self->{tmpdir};
46
47  my $config_file = "$tmpdir/config.conf";
48  my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid");
49  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard");
50
51  my $log_file = test_get_logfile();
52
53  my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd");
54  my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group");
55
56  my $user = 'proftpd';
57  my $passwd = 'test';
58  my $group = 'ftpd';
59  my $home_dir = File::Spec->rel2abs($tmpdir);
60  my $uid = 500;
61  my $gid = 500;
62
63  # Make sure that, if we're running as root, that the home directory has
64  # permissions/privs set for the account we create
65  if ($< == 0) {
66    unless (chmod(0755, $home_dir)) {
67      die("Can't set perms on $home_dir to 0755: $!");
68    }
69
70    unless (chown($uid, $gid, $home_dir)) {
71      die("Can't set owner of $home_dir to $uid/$gid: $!");
72    }
73  }
74
75  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
76    '/bin/bash');
77  auth_group_write($auth_group_file, $group, $gid, $user);
78
79  my $config = {
80    PidFile => $pid_file,
81    ScoreboardFile => $scoreboard_file,
82    SystemLog => $log_file,
83
84    AuthUserFile => $auth_user_file,
85    AuthGroupFile => $auth_group_file,
86
87    RLimitMemory => 'max',
88
89    IfModules => {
90      'mod_delay.c' => {
91        DelayEngine => 'off',
92      },
93    },
94  };
95
96  my ($port, $config_user, $config_group) = config_write($config_file, $config);
97
98  # Open pipes, for use between the parent and child processes.  Specifically,
99  # the child will indicate when it's done with its test by writing a message
100  # to the parent.
101  my ($rfh, $wfh);
102  unless (pipe($rfh, $wfh)) {
103    die("Can't open pipe: $!");
104  }
105
106  my $ex;
107
108  # Fork child
109  $self->handle_sigchld();
110  defined(my $pid = fork()) or die("Can't fork: $!");
111  if ($pid) {
112    eval {
113      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
114      $client->login($user, $passwd);
115      $client->quit();
116    };
117
118    if ($@) {
119      $ex = $@;
120    }
121
122    $wfh->print("done\n");
123    $wfh->flush();
124
125  } else {
126    eval { server_wait($config_file, $rfh) };
127    if ($@) {
128      warn($@);
129      exit 1;
130    }
131
132    exit 0;
133  }
134
135  # Stop server
136  server_stop($pid_file);
137
138  $self->assert_child_ok($pid);
139
140  if ($ex) {
141    test_append_logfile($log_file, $ex);
142    unlink($log_file);
143
144    die($ex);
145  }
146
147  unlink($log_file);
148}
149
150sub rlimitmemory_session_max_bug3571 {
151  my $self = shift;
152  my $tmpdir = $self->{tmpdir};
153
154  my $config_file = "$tmpdir/config.conf";
155  my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid");
156  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard");
157
158  my $log_file = test_get_logfile();
159
160  my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd");
161  my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group");
162
163  my $user = 'proftpd';
164  my $passwd = 'test';
165  my $group = 'ftpd';
166  my $home_dir = File::Spec->rel2abs($tmpdir);
167  my $uid = 500;
168  my $gid = 500;
169
170  # Make sure that, if we're running as root, that the home directory has
171  # permissions/privs set for the account we create
172  if ($< == 0) {
173    unless (chmod(0755, $home_dir)) {
174      die("Can't set perms on $home_dir to 0755: $!");
175    }
176
177    unless (chown($uid, $gid, $home_dir)) {
178      die("Can't set owner of $home_dir to $uid/$gid: $!");
179    }
180  }
181
182  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
183    '/bin/bash');
184  auth_group_write($auth_group_file, $group, $gid, $user);
185
186  my $config = {
187    PidFile => $pid_file,
188    ScoreboardFile => $scoreboard_file,
189    SystemLog => $log_file,
190
191    AuthUserFile => $auth_user_file,
192    AuthGroupFile => $auth_group_file,
193
194    RLimitMemory => 'session max',
195
196    IfModules => {
197      'mod_delay.c' => {
198        DelayEngine => 'off',
199      },
200    },
201  };
202
203  my ($port, $config_user, $config_group) = config_write($config_file, $config);
204
205  # Open pipes, for use between the parent and child processes.  Specifically,
206  # the child will indicate when it's done with its test by writing a message
207  # to the parent.
208  my ($rfh, $wfh);
209  unless (pipe($rfh, $wfh)) {
210    die("Can't open pipe: $!");
211  }
212
213  my $ex;
214
215  # Fork child
216  $self->handle_sigchld();
217  defined(my $pid = fork()) or die("Can't fork: $!");
218  if ($pid) {
219    eval {
220      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
221      $client->login($user, $passwd);
222      $client->quit();
223    };
224
225    if ($@) {
226      $ex = $@;
227    }
228
229    $wfh->print("done\n");
230    $wfh->flush();
231
232  } else {
233    eval { server_wait($config_file, $rfh) };
234    if ($@) {
235      warn($@);
236      exit 1;
237    }
238
239    exit 0;
240  }
241
242  # Stop server
243  server_stop($pid_file);
244
245  $self->assert_child_ok($pid);
246
247  if ($ex) {
248    test_append_logfile($log_file, $ex);
249    unlink($log_file);
250
251    die($ex);
252  }
253
254  unlink($log_file);
255}
256
257sub rlimitmemory_daemon_max {
258  my $self = shift;
259  my $tmpdir = $self->{tmpdir};
260
261  my $config_file = "$tmpdir/config.conf";
262  my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid");
263  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard");
264
265  my $log_file = test_get_logfile();
266
267  my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd");
268  my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group");
269
270  my $user = 'proftpd';
271  my $passwd = 'test';
272  my $group = 'ftpd';
273  my $home_dir = File::Spec->rel2abs($tmpdir);
274  my $uid = 500;
275  my $gid = 500;
276
277  # Make sure that, if we're running as root, that the home directory has
278  # permissions/privs set for the account we create
279  if ($< == 0) {
280    unless (chmod(0755, $home_dir)) {
281      die("Can't set perms on $home_dir to 0755: $!");
282    }
283
284    unless (chown($uid, $gid, $home_dir)) {
285      die("Can't set owner of $home_dir to $uid/$gid: $!");
286    }
287  }
288
289  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
290    '/bin/bash');
291  auth_group_write($auth_group_file, $group, $gid, $user);
292
293  my $config = {
294    PidFile => $pid_file,
295    ScoreboardFile => $scoreboard_file,
296    SystemLog => $log_file,
297
298    AuthUserFile => $auth_user_file,
299    AuthGroupFile => $auth_group_file,
300
301    RLimitMemory => 'daemon max',
302
303    IfModules => {
304      'mod_delay.c' => {
305        DelayEngine => 'off',
306      },
307    },
308  };
309
310  my ($port, $config_user, $config_group) = config_write($config_file, $config);
311
312  # Open pipes, for use between the parent and child processes.  Specifically,
313  # the child will indicate when it's done with its test by writing a message
314  # to the parent.
315  my ($rfh, $wfh);
316  unless (pipe($rfh, $wfh)) {
317    die("Can't open pipe: $!");
318  }
319
320  my $ex;
321
322  # Fork child
323  $self->handle_sigchld();
324  defined(my $pid = fork()) or die("Can't fork: $!");
325  if ($pid) {
326    eval {
327      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
328      $client->login($user, $passwd);
329      $client->quit();
330    };
331
332    if ($@) {
333      $ex = $@;
334    }
335
336    $wfh->print("done\n");
337    $wfh->flush();
338
339  } else {
340    eval { server_wait($config_file, $rfh) };
341    if ($@) {
342      warn($@);
343      exit 1;
344    }
345
346    exit 0;
347  }
348
349  # Stop server
350  server_stop($pid_file);
351
352  $self->assert_child_ok($pid);
353
354  if ($ex) {
355    test_append_logfile($log_file, $ex);
356    unlink($log_file);
357
358    die($ex);
359  }
360
361  unlink($log_file);
362}
363
3641;
365