1package ProFTPD::Tests::Config::Limit::SubDirectories; 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 subdirs_mkd_denied_pwd_allowed_bug3077 => { 19 order => ++$order, 20 test_class => [qw(bug forking)], 21 }, 22 23 subdirs_mkd_denied_limit_xmkd_bug3077 => { 24 order => ++$order, 25 test_class => [qw(bug forking)], 26 }, 27 28 subdirs_xmkd_allowed_limit_mkd_bug3077 => { 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 subdirs_mkd_denied_pwd_allowed_bug3077 { 44 my $self = shift; 45 my $tmpdir = $self->{tmpdir}; 46 47 my $config_file = "$tmpdir/limit.conf"; 48 my $pid_file = File::Spec->rel2abs("$tmpdir/limit.pid"); 49 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/limit.scoreboard"); 50 51 my $log_file = File::Spec->rel2abs('tests.log'); 52 53 my $auth_user_file = File::Spec->rel2abs("$tmpdir/limit.passwd"); 54 my $auth_group_file = File::Spec->rel2abs("$tmpdir/limit.group"); 55 56 my $user = 'proftpd'; 57 my $passwd = 'test'; 58 my $home_dir = File::Spec->rel2abs($tmpdir); 59 my $uid = 500; 60 my $gid = 500; 61 62 my $sub_dir = File::Spec->rel2abs("$tmpdir/foo"); 63 64 # Make sure that, if we're running as root, that the home directory has 65 # permissions/privs set for the account we create 66 if ($< == 0) { 67 unless (chmod(0755, $home_dir)) { 68 die("Can't set perms on $home_dir to 0755: $!"); 69 } 70 71 unless (chown($uid, $gid, $home_dir)) { 72 die("Can't set owner of $home_dir to $uid/$gid: $!"); 73 } 74 } 75 76 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 77 '/bin/bash'); 78 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 79 80 my $config = { 81 PidFile => $pid_file, 82 ScoreboardFile => $scoreboard_file, 83 SystemLog => $log_file, 84 85 AuthUserFile => $auth_user_file, 86 AuthGroupFile => $auth_group_file, 87 88 IfModules => { 89 'mod_delay.c' => { 90 DelayEngine => 'off', 91 }, 92 }, 93 94 Limit => { 95 'ALL' => { 96 DenyAll => '', 97 }, 98 99 'CDUP CWD PWD LIST NLST RNFR RNTO TYPE' => { 100 AllowAll => '', 101 }, 102 }, 103 }; 104 105 my ($port, $config_user, $config_group) = config_write($config_file, $config); 106 107 if (open(my $fh, ">> $config_file")) { 108 print $fh <<EOT; 109<Directory $home_dir> 110 <Limit STOR STOU RETR DELE PWD RMD> 111 AllowAll 112 </Limit> 113</Directory> 114EOT 115 unless (close($fh)) { 116 die("Can't write $config_file: $!"); 117 } 118 119 } else { 120 die("Can't open $config_file: $!"); 121 } 122 123 # Open pipes, for use between the parent and child processes. Specifically, 124 # the child will indicate when it's done with its test by writing a message 125 # to the parent. 126 my ($rfh, $wfh); 127 unless (pipe($rfh, $wfh)) { 128 die("Can't open pipe: $!"); 129 } 130 131 my $ex; 132 133 # Fork child 134 $self->handle_sigchld(); 135 defined(my $pid = fork()) or die("Can't fork: $!"); 136 if ($pid) { 137 eval { 138 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 139 $client->login($user, $passwd); 140 141 my ($resp_code, $resp_msg); 142 eval { $client->mkd($sub_dir) }; 143 unless ($@) { 144 die("MKD succeeded unexpectedly"); 145 } 146 147 $resp_code = $client->response_code(); 148 $resp_msg = $client->response_msg(); 149 150 my $expected; 151 152 $expected = 550; 153 $self->assert($expected == $resp_code, 154 test_msg("Expected $expected, got $resp_code")); 155 156 $expected = "$sub_dir: Permission denied"; 157 $self->assert($expected eq $resp_msg, 158 test_msg("Expected '$expected', got '$resp_msg'")); 159 160 ($resp_code, $resp_msg) = $client->pwd(); 161 162 $expected = 257; 163 $self->assert($expected == $resp_code, 164 test_msg("Expected $expected, got $resp_code")); 165 166 $expected = "\"$home_dir\" is the current directory"; 167 $self->assert($expected eq $resp_msg, 168 test_msg("Expected '$expected', got '$resp_msg'")); 169 }; 170 171 if ($@) { 172 $ex = $@; 173 } 174 175 $wfh->print("done\n"); 176 $wfh->flush(); 177 178 } else { 179 eval { server_wait($config_file, $rfh) }; 180 if ($@) { 181 warn($@); 182 exit 1; 183 } 184 185 exit 0; 186 } 187 188 # Stop server 189 server_stop($pid_file); 190 191 $self->assert_child_ok($pid); 192 193 if ($ex) { 194 die($ex); 195 } 196 197 unlink($log_file); 198} 199 200sub subdirs_mkd_denied_limit_xmkd_bug3077 { 201 my $self = shift; 202 my $tmpdir = $self->{tmpdir}; 203 204 my $config_file = "$tmpdir/limit.conf"; 205 my $pid_file = File::Spec->rel2abs("$tmpdir/limit.pid"); 206 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/limit.scoreboard"); 207 208 my $log_file = File::Spec->rel2abs('tests.log'); 209 210 my $auth_user_file = File::Spec->rel2abs("$tmpdir/limit.passwd"); 211 my $auth_group_file = File::Spec->rel2abs("$tmpdir/limit.group"); 212 213 my $user = 'proftpd'; 214 my $passwd = 'test'; 215 my $home_dir = File::Spec->rel2abs($tmpdir); 216 my $uid = 500; 217 my $gid = 500; 218 219 my $sub_dir = File::Spec->rel2abs("$tmpdir/foo"); 220 221 # Make sure that, if we're running as root, that the home directory has 222 # permissions/privs set for the account we create 223 if ($< == 0) { 224 unless (chmod(0755, $home_dir)) { 225 die("Can't set perms on $home_dir to 0755: $!"); 226 } 227 228 unless (chown($uid, $gid, $home_dir)) { 229 die("Can't set owner of $home_dir to $uid/$gid: $!"); 230 } 231 } 232 233 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 234 '/bin/bash'); 235 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 236 237 my $config = { 238 PidFile => $pid_file, 239 ScoreboardFile => $scoreboard_file, 240 SystemLog => $log_file, 241 242 AuthUserFile => $auth_user_file, 243 AuthGroupFile => $auth_group_file, 244 245 IfModules => { 246 'mod_delay.c' => { 247 DelayEngine => 'off', 248 }, 249 }, 250 251 }; 252 253 my ($port, $config_user, $config_group) = config_write($config_file, $config); 254 255 if (open(my $fh, ">> $config_file")) { 256 print $fh <<EOT; 257<Directory $home_dir> 258 <Limit XMKD> 259 DenyAll 260 </Limit> 261</Directory> 262EOT 263 unless (close($fh)) { 264 die("Can't write $config_file: $!"); 265 } 266 267 } else { 268 die("Can't open $config_file: $!"); 269 } 270 271 # Open pipes, for use between the parent and child processes. Specifically, 272 # the child will indicate when it's done with its test by writing a message 273 # to the parent. 274 my ($rfh, $wfh); 275 unless (pipe($rfh, $wfh)) { 276 die("Can't open pipe: $!"); 277 } 278 279 my $ex; 280 281 # Fork child 282 $self->handle_sigchld(); 283 defined(my $pid = fork()) or die("Can't fork: $!"); 284 if ($pid) { 285 eval { 286 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 287 $client->login($user, $passwd); 288 289 my ($resp_code, $resp_msg); 290 eval { $client->mkd($sub_dir) }; 291 unless ($@) { 292 die("MKD succeeded unexpectedly"); 293 } 294 295 $resp_code = $client->response_code(); 296 $resp_msg = $client->response_msg(); 297 298 my $expected; 299 300 $expected = 550; 301 $self->assert($expected == $resp_code, 302 test_msg("Expected $expected, got $resp_code")); 303 304 $expected = "$sub_dir: Permission denied"; 305 $self->assert($expected eq $resp_msg, 306 test_msg("Expected '$expected', got '$resp_msg'")); 307 308 ($resp_code, $resp_msg) = $client->pwd(); 309 310 $expected = 257; 311 $self->assert($expected == $resp_code, 312 test_msg("Expected $expected, got $resp_code")); 313 314 $expected = "\"$home_dir\" is the current directory"; 315 $self->assert($expected eq $resp_msg, 316 test_msg("Expected '$expected', got '$resp_msg'")); 317 }; 318 319 if ($@) { 320 $ex = $@; 321 } 322 323 $wfh->print("done\n"); 324 $wfh->flush(); 325 326 } else { 327 eval { server_wait($config_file, $rfh) }; 328 if ($@) { 329 warn($@); 330 exit 1; 331 } 332 333 exit 0; 334 } 335 336 # Stop server 337 server_stop($pid_file); 338 339 $self->assert_child_ok($pid); 340 341 if ($ex) { 342 die($ex); 343 } 344 345 unlink($log_file); 346} 347 348sub subdirs_xmkd_allowed_limit_mkd_bug3077 { 349 my $self = shift; 350 my $tmpdir = $self->{tmpdir}; 351 352 my $config_file = "$tmpdir/limit.conf"; 353 my $pid_file = File::Spec->rel2abs("$tmpdir/limit.pid"); 354 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/limit.scoreboard"); 355 356 my $log_file = File::Spec->rel2abs('tests.log'); 357 358 my $auth_user_file = File::Spec->rel2abs("$tmpdir/limit.passwd"); 359 my $auth_group_file = File::Spec->rel2abs("$tmpdir/limit.group"); 360 361 my $user = 'proftpd'; 362 my $passwd = 'test'; 363 my $home_dir = File::Spec->rel2abs($tmpdir); 364 my $uid = 500; 365 my $gid = 500; 366 367 my $sub_dir = File::Spec->rel2abs("$tmpdir/foo"); 368 369 # Make sure that, if we're running as root, that the home directory has 370 # permissions/privs set for the account we create 371 if ($< == 0) { 372 unless (chmod(0755, $home_dir)) { 373 die("Can't set perms on $home_dir to 0755: $!"); 374 } 375 376 unless (chown($uid, $gid, $home_dir)) { 377 die("Can't set owner of $home_dir to $uid/$gid: $!"); 378 } 379 } 380 381 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 382 '/bin/bash'); 383 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 384 385 my $config = { 386 PidFile => $pid_file, 387 ScoreboardFile => $scoreboard_file, 388 SystemLog => $log_file, 389 390 AuthUserFile => $auth_user_file, 391 AuthGroupFile => $auth_group_file, 392 393 IfModules => { 394 'mod_delay.c' => { 395 DelayEngine => 'off', 396 }, 397 }, 398 399 }; 400 401 my ($port, $config_user, $config_group) = config_write($config_file, $config); 402 403 if (open(my $fh, ">> $config_file")) { 404 print $fh <<EOT; 405<Directory $home_dir> 406 <Limit WRITE> 407 DenyAll 408 </Limit> 409 410 <Limit MKD> 411 AllowAll 412 </Limit> 413</Directory> 414EOT 415 unless (close($fh)) { 416 die("Can't write $config_file: $!"); 417 } 418 419 } else { 420 die("Can't open $config_file: $!"); 421 } 422 423 # Open pipes, for use between the parent and child processes. Specifically, 424 # the child will indicate when it's done with its test by writing a message 425 # to the parent. 426 my ($rfh, $wfh); 427 unless (pipe($rfh, $wfh)) { 428 die("Can't open pipe: $!"); 429 } 430 431 my $ex; 432 433 # Fork child 434 $self->handle_sigchld(); 435 defined(my $pid = fork()) or die("Can't fork: $!"); 436 if ($pid) { 437 eval { 438 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 439 $client->login($user, $passwd); 440 441 my ($resp_code, $resp_msg); 442 ($resp_code, $resp_msg) = $client->xmkd($sub_dir); 443 444 my $expected; 445 446 $expected = 257; 447 $self->assert($expected == $resp_code, 448 test_msg("Expected $expected, got $resp_code")); 449 450 $expected = "\"$sub_dir\" - Directory successfully created"; 451 $self->assert($expected eq $resp_msg, 452 test_msg("Expected '$expected', got '$resp_msg'")); 453 }; 454 455 if ($@) { 456 $ex = $@; 457 } 458 459 $wfh->print("done\n"); 460 $wfh->flush(); 461 462 } else { 463 eval { server_wait($config_file, $rfh) }; 464 if ($@) { 465 warn($@); 466 exit 1; 467 } 468 469 exit 0; 470 } 471 472 # Stop server 473 server_stop($pid_file); 474 475 $self->assert_child_ok($pid); 476 477 if ($ex) { 478 die($ex); 479 } 480 481 unlink($log_file); 482} 483 4841; 485