1package ProFTPD::Tests::Config::Order; 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 # The single "allow,deny" parameter form 19 order_allowdeny_ok => { 20 order => ++$order, 21 test_class => [qw(forking)], 22 }, 23 24 # The double "allow, deny" parameter form with a space 25 order_allow_deny_ok => { 26 order => ++$order, 27 test_class => [qw(forking)], 28 }, 29 30 # The single "deny,allow" parameter form 31 order_denyallow_ok => { 32 order => ++$order, 33 test_class => [qw(forking)], 34 }, 35 36 # The double "deny, allow" parameter form with a space 37 order_deny_allow_ok => { 38 order => ++$order, 39 test_class => [qw(forking)], 40 }, 41 42}; 43 44sub new { 45 return shift()->SUPER::new(@_); 46} 47 48sub list_tests { 49 return testsuite_get_runnable_tests($TESTS); 50} 51 52sub order_allowdeny_ok { 53 my $self = shift; 54 my $tmpdir = $self->{tmpdir}; 55 56 my $config_file = "$tmpdir/config.conf"; 57 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 58 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 59 60 my $log_file = File::Spec->rel2abs('tests.log'); 61 62 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 63 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 64 65 my $user = 'proftpd'; 66 my $passwd = 'test'; 67 my $home_dir = File::Spec->rel2abs($tmpdir); 68 my $uid = 500; 69 my $gid = 500; 70 71 # Make sure that, if we're running as root, that the home directory has 72 # permissions/privs set for the account we create 73 if ($< == 0) { 74 unless (chmod(0755, $home_dir)) { 75 die("Can't set perms on $home_dir to 0755: $!"); 76 } 77 78 unless (chown($uid, $gid, $home_dir)) { 79 die("Can't set owner of $home_dir to $uid/$gid: $!"); 80 } 81 } 82 83 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 84 '/bin/bash'); 85 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 86 87 my $config = { 88 PidFile => $pid_file, 89 ScoreboardFile => $scoreboard_file, 90 SystemLog => $log_file, 91 TraceLog => $log_file, 92 Trace => 'config:20', 93 94 AuthUserFile => $auth_user_file, 95 AuthGroupFile => $auth_group_file, 96 DefaultChdir => '~', 97 98 Limit => { 99 ALL => { 100 Order => 'allow,deny', 101 AllowUser => $user, 102 DenyAll => '', 103 }, 104 }, 105 106 IfModules => { 107 'mod_delay.c' => { 108 DelayEngine => 'off', 109 }, 110 }, 111 }; 112 113 my ($port, $config_user, $config_group) = config_write($config_file, $config); 114 115 # Open pipes, for use between the parent and child processes. Specifically, 116 # the child will indicate when it's done with its test by writing a message 117 # to the parent. 118 my ($rfh, $wfh); 119 unless (pipe($rfh, $wfh)) { 120 die("Can't open pipe: $!"); 121 } 122 123 my $ex; 124 125 # Fork child 126 $self->handle_sigchld(); 127 defined(my $pid = fork()) or die("Can't fork: $!"); 128 if ($pid) { 129 eval { 130 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 131 $client->login($user, $passwd); 132 133 my $conn = $client->stor_raw('test.txt'); 134 unless ($conn) { 135 die("Failed to STOR test.txt: " . $client->response_code() . " " . 136 $client->response_msg()); 137 } 138 139 my $buf = "Hello, World!\n"; 140 $conn->write($buf, length($buf)); 141 $conn->close(); 142 143 my $resp_code = $client->response_code(); 144 my $resp_msg = $client->response_msg(); 145 146 my $expected; 147 148 $expected = 226; 149 $self->assert($expected == $resp_code, 150 test_msg("Expected $expected, got $resp_code")); 151 152 $expected = "Transfer complete"; 153 $self->assert($expected eq $resp_msg, 154 test_msg("Expected '$expected', got '$resp_msg'")); 155 156 $client->quit(); 157 }; 158 159 if ($@) { 160 $ex = $@; 161 } 162 163 $wfh->print("done\n"); 164 $wfh->flush(); 165 166 } else { 167 eval { server_wait($config_file, $rfh) }; 168 if ($@) { 169 warn($@); 170 exit 1; 171 } 172 173 exit 0; 174 } 175 176 # Stop server 177 server_stop($pid_file); 178 179 $self->assert_child_ok($pid); 180 181 if ($ex) { 182 die($ex); 183 } 184 185 unlink($log_file); 186} 187 188sub order_allow_deny_ok { 189 my $self = shift; 190 my $tmpdir = $self->{tmpdir}; 191 192 my $config_file = "$tmpdir/config.conf"; 193 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 194 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 195 196 my $log_file = File::Spec->rel2abs('tests.log'); 197 198 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 199 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 200 201 my $user = 'proftpd'; 202 my $passwd = 'test'; 203 my $home_dir = File::Spec->rel2abs($tmpdir); 204 my $uid = 500; 205 my $gid = 500; 206 207 # Make sure that, if we're running as root, that the home directory has 208 # permissions/privs set for the account we create 209 if ($< == 0) { 210 unless (chmod(0755, $home_dir)) { 211 die("Can't set perms on $home_dir to 0755: $!"); 212 } 213 214 unless (chown($uid, $gid, $home_dir)) { 215 die("Can't set owner of $home_dir to $uid/$gid: $!"); 216 } 217 } 218 219 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 220 '/bin/bash'); 221 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 222 223 my $config = { 224 PidFile => $pid_file, 225 ScoreboardFile => $scoreboard_file, 226 SystemLog => $log_file, 227 228 AuthUserFile => $auth_user_file, 229 AuthGroupFile => $auth_group_file, 230 DefaultChdir => '~', 231 232 Limit => { 233 ALL => { 234 Order => 'allow, deny', 235 AllowUser => $user, 236 DenyAll => '', 237 }, 238 }, 239 240 IfModules => { 241 'mod_delay.c' => { 242 DelayEngine => 'off', 243 }, 244 }, 245 }; 246 247 my ($port, $config_user, $config_group) = config_write($config_file, $config); 248 249 # Open pipes, for use between the parent and child processes. Specifically, 250 # the child will indicate when it's done with its test by writing a message 251 # to the parent. 252 my ($rfh, $wfh); 253 unless (pipe($rfh, $wfh)) { 254 die("Can't open pipe: $!"); 255 } 256 257 my $ex; 258 259 # Fork child 260 $self->handle_sigchld(); 261 defined(my $pid = fork()) or die("Can't fork: $!"); 262 if ($pid) { 263 eval { 264 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 265 $client->login($user, $passwd); 266 267 my $conn = $client->stor_raw('test.txt'); 268 unless ($conn) { 269 die("Failed to STOR test.txt: " . $client->response_code() . " " . 270 $client->response_msg()); 271 } 272 273 my $buf = "Hello, World!\n"; 274 $conn->write($buf, length($buf)); 275 $conn->close(); 276 277 my $resp_code = $client->response_code(); 278 my $resp_msg = $client->response_msg(); 279 280 my $expected; 281 282 $expected = 226; 283 $self->assert($expected == $resp_code, 284 test_msg("Expected $expected, got $resp_code")); 285 286 $expected = "Transfer complete"; 287 $self->assert($expected eq $resp_msg, 288 test_msg("Expected '$expected', got '$resp_msg'")); 289 290 $client->quit(); 291 }; 292 293 if ($@) { 294 $ex = $@; 295 } 296 297 $wfh->print("done\n"); 298 $wfh->flush(); 299 300 } else { 301 eval { server_wait($config_file, $rfh) }; 302 if ($@) { 303 warn($@); 304 exit 1; 305 } 306 307 exit 0; 308 } 309 310 # Stop server 311 server_stop($pid_file); 312 313 $self->assert_child_ok($pid); 314 315 if ($ex) { 316 die($ex); 317 } 318 319 unlink($log_file); 320} 321 322sub order_denyallow_ok { 323 my $self = shift; 324 my $tmpdir = $self->{tmpdir}; 325 326 my $config_file = "$tmpdir/config.conf"; 327 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 328 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 329 330 my $log_file = File::Spec->rel2abs('tests.log'); 331 332 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 333 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 334 335 my $user = 'proftpd'; 336 my $passwd = 'test'; 337 my $home_dir = File::Spec->rel2abs($tmpdir); 338 my $uid = 500; 339 my $gid = 500; 340 341 # Make sure that, if we're running as root, that the home directory has 342 # permissions/privs set for the account we create 343 if ($< == 0) { 344 unless (chmod(0755, $home_dir)) { 345 die("Can't set perms on $home_dir to 0755: $!"); 346 } 347 348 unless (chown($uid, $gid, $home_dir)) { 349 die("Can't set owner of $home_dir to $uid/$gid: $!"); 350 } 351 } 352 353 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 354 '/bin/bash'); 355 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 356 357 my $config = { 358 PidFile => $pid_file, 359 ScoreboardFile => $scoreboard_file, 360 SystemLog => $log_file, 361 362 AuthUserFile => $auth_user_file, 363 AuthGroupFile => $auth_group_file, 364 DefaultChdir => '~', 365 366 Limit => { 367 ALL => { 368 Order => 'deny,allow', 369 AllowUser => $user, 370 DenyAll => '', 371 }, 372 }, 373 374 IfModules => { 375 'mod_delay.c' => { 376 DelayEngine => 'off', 377 }, 378 }, 379 }; 380 381 my ($port, $config_user, $config_group) = config_write($config_file, $config); 382 383 # Open pipes, for use between the parent and child processes. Specifically, 384 # the child will indicate when it's done with its test by writing a message 385 # to the parent. 386 my ($rfh, $wfh); 387 unless (pipe($rfh, $wfh)) { 388 die("Can't open pipe: $!"); 389 } 390 391 my $ex; 392 393 # Fork child 394 $self->handle_sigchld(); 395 defined(my $pid = fork()) or die("Can't fork: $!"); 396 if ($pid) { 397 eval { 398 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 399 $client->login($user, $passwd); 400 401 my $conn = $client->stor_raw('test.txt'); 402 if ($conn) { 403 die("STOR test.txt succeeded unexpectedly"); 404 } 405 406 my $resp_code = $client->response_code(); 407 my $resp_msg = $client->response_msg(); 408 409 my $expected; 410 411 $expected = 550; 412 $self->assert($expected == $resp_code, 413 test_msg("Expected $expected, got $resp_code")); 414 415 $expected = "test.txt: Operation not permitted"; 416 $self->assert($expected eq $resp_msg, 417 test_msg("Expected '$expected', got '$resp_msg'")); 418 419 $client->quit(); 420 }; 421 422 if ($@) { 423 $ex = $@; 424 } 425 426 $wfh->print("done\n"); 427 $wfh->flush(); 428 429 } else { 430 eval { server_wait($config_file, $rfh) }; 431 if ($@) { 432 warn($@); 433 exit 1; 434 } 435 436 exit 0; 437 } 438 439 # Stop server 440 server_stop($pid_file); 441 442 $self->assert_child_ok($pid); 443 444 if ($ex) { 445 die($ex); 446 } 447 448 unlink($log_file); 449} 450 451sub order_deny_allow_ok { 452 my $self = shift; 453 my $tmpdir = $self->{tmpdir}; 454 455 my $config_file = "$tmpdir/config.conf"; 456 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 457 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 458 459 my $log_file = File::Spec->rel2abs('tests.log'); 460 461 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 462 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 463 464 my $user = 'proftpd'; 465 my $passwd = 'test'; 466 my $home_dir = File::Spec->rel2abs($tmpdir); 467 my $uid = 500; 468 my $gid = 500; 469 470 # Make sure that, if we're running as root, that the home directory has 471 # permissions/privs set for the account we create 472 if ($< == 0) { 473 unless (chmod(0755, $home_dir)) { 474 die("Can't set perms on $home_dir to 0755: $!"); 475 } 476 477 unless (chown($uid, $gid, $home_dir)) { 478 die("Can't set owner of $home_dir to $uid/$gid: $!"); 479 } 480 } 481 482 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 483 '/bin/bash'); 484 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 485 486 my $config = { 487 PidFile => $pid_file, 488 ScoreboardFile => $scoreboard_file, 489 SystemLog => $log_file, 490 491 AuthUserFile => $auth_user_file, 492 AuthGroupFile => $auth_group_file, 493 DefaultChdir => '~', 494 495 Limit => { 496 ALL => { 497 Order => 'deny, allow', 498 AllowUser => $user, 499 DenyAll => '', 500 }, 501 }, 502 503 IfModules => { 504 'mod_delay.c' => { 505 DelayEngine => 'off', 506 }, 507 }, 508 }; 509 510 my ($port, $config_user, $config_group) = config_write($config_file, $config); 511 512 # Open pipes, for use between the parent and child processes. Specifically, 513 # the child will indicate when it's done with its test by writing a message 514 # to the parent. 515 my ($rfh, $wfh); 516 unless (pipe($rfh, $wfh)) { 517 die("Can't open pipe: $!"); 518 } 519 520 my $ex; 521 522 # Fork child 523 $self->handle_sigchld(); 524 defined(my $pid = fork()) or die("Can't fork: $!"); 525 if ($pid) { 526 eval { 527 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 528 $client->login($user, $passwd); 529 530 my $conn = $client->stor_raw('test.txt'); 531 if ($conn) { 532 die("STOR test.txt succeeded unexpectedly"); 533 } 534 535 my $resp_code = $client->response_code(); 536 my $resp_msg = $client->response_msg(); 537 538 my $expected; 539 540 $expected = 550; 541 $self->assert($expected == $resp_code, 542 test_msg("Expected $expected, got $resp_code")); 543 544 $expected = "test.txt: Operation not permitted"; 545 $self->assert($expected eq $resp_msg, 546 test_msg("Expected '$expected', got '$resp_msg'")); 547 548 $client->quit(); 549 }; 550 551 if ($@) { 552 $ex = $@; 553 } 554 555 $wfh->print("done\n"); 556 $wfh->flush(); 557 558 } else { 559 eval { server_wait($config_file, $rfh) }; 560 if ($@) { 561 warn($@); 562 exit 1; 563 } 564 565 exit 0; 566 } 567 568 # Stop server 569 server_stop($pid_file); 570 571 $self->assert_child_ok($pid); 572 573 if ($ex) { 574 die($ex); 575 } 576 577 unlink($log_file); 578} 579 5801; 581