App-Fetchware
view release on metacpan or search on metacpan
t/App-Fetchware-Util.t view on Meta::CPAN
# Cleanup $temp_dir, because this one won't automatically be cleaned up.
unlink 'fetchware.sem' or fail("Failed to delete 'fetchware.sem'! [$!]");
chdir original_cwd() or fail("Failed to chdir back to original_cwd()!");
rmdir $temp_dir or fail("Failed to delete temp_dir[$temp_dir]! [$!]");
# Test create_tempdir() successes with a custom temp_dir set.
$temp_dir = create_tempdir(TempDir => tmpdir());
ok(-e $temp_dir, 'checked create_tempdir() success.');
# Cleanup $temp_dir, because this one won't automatically be cleaned up.
unlink 'fetchware.sem' or fail("Failed to delete 'fetchware.sem'! [$!]");
chdir original_cwd() or fail("Failed to chdir back to original_cwd()!");
rmdir $temp_dir or fail("Failed to delete temp_dir[$temp_dir]! [$!]");
$temp_dir = create_tempdir(KeepTempDir => 1);
ok(-e $temp_dir, 'checked create_tempdir() KeepTempDir success.');
ok(-e 'fetchware.sem', 'checked fetchware semaphore creation.');
note "TEMPDIR[$temp_dir]";
# Cleanup $temp_dir, because this one won't automatically be cleaned up.
unlink 'fetchware.sem' or fail("Failed to delete 'fetchware.sem'! [$!]");
chdir original_cwd() or fail("Failed to chdir back to original_cwd()!");
rmdir $temp_dir or fail("Failed to delete temp_dir[$temp_dir]! [$!]");
# Test create_tempdir() failure
eval_ok( sub {create_tempdir(
TempDir => 'doesnotexist' . int(rand(238378290)))},
<<EOE, 'tested create_tempdir() temp_dir does not exist failure.');
App-Fetchware: run-time error. Fetchware tried to use File::Temp's tempdir()
subroutine to create a temporary file, but tempdir() threw an exception. That
exception was []. See perldoc App::Fetchware.
EOE
#chdir back to $original_cwd, so that File::Temp's END block can delete
#this last temp_dir. Otherwise, a warning is printed from File::Temp about
#this.
chdir original_cwd() or fail("Failed to chdir back to [@{[original_cwd]}]!");
};
subtest 'test cleanup_tempdir()' => sub {
# Create a tempdir to test cleaning it up.
my $temp_dir = create_tempdir();
ok(-e $temp_dir, 'checked create_tempdir() success.');
ok(-e 'fetchware.sem', 'checked fetchware semaphore creation.');
# Now test cleaning it up by see if the fetchware semaphore lock file has
# had its lock released or not.
cleanup_tempdir();
ok(open(my $fh_sem, '>', catfile($temp_dir, 'fetchware.sem')),
'checked cleanup_tempdir() open fetchware lock file success.');
ok( flock($fh_sem, LOCK_EX | LOCK_NB),
'checked cleanup_tempdir() success.');
ok(close $fh_sem,
'checked cleanup_tempdir() released fetchware lock file success.');
};
subtest 'test drop_privs()' => sub {
plan skip_all => 'Test suite not being run on Unix.' unless do {
if (is_os_type('Unix')) {
note('ISUNIX');
1
} else {
# Return false
note('ISNOTUNIX');
0
}
};
# If we're not running as root.
if ($< != 0) {
my $previous_uid = $<;
my $previous_euid = $>;
drop_privs_ok(
sub {
my $fh = shift;
# Write our real and effective uids to the tempfile.
print $fh "$$\n";
print $fh "$<\n";
print $fh "$>\n";
}, sub {
my $rfh = shift;
chomp(my $child_pid = <$rfh>);
chomp(my $new_uid = <$rfh>);
chomp(my $new_euid = <$rfh>);
# Due to the if above we're nonroot, so check that we did not
# fork, because only root is supposed to fork.
ok($child_pid == $$,
'checked drop_privs() didnt fork success.');
is($new_uid, $previous_uid,
'checked drop_privs() success.');
is($new_euid, $previous_euid,
'checked drop_privs() success.');
}
);
# If we're running as root.
} elsif ($< == 0) {
my $previous_uid = $<;
my $previous_euid = $>;
# Check drop_privs() with no extra args.
drop_privs_ok(
sub {
my $fh = shift;
# Write our real and effective uids to the tempfile.
print $fh "$$\n";
print $fh "$<\n";
print $fh "$>\n";
}, sub {
my $rfh = shift;
chomp(my $child_pid = <$rfh>);
chomp(my $new_uid = <$rfh>);
chomp(my $new_euid = <$rfh>);
t/App-Fetchware-Util.t view on Meta::CPAN
'checked drop_privs() nobody euid success.');
}, 'nobody'
);
# Test drop_privs()'s SkipTempDirCreation option.
my $previous_cwd = cwd();
drop_privs_ok(
sub {
my $fh = shift;
# Just share our cwd() with the parent tester...
my $cwd = cwd();
print $fh "$cwd\n";
}, sub {
my $rfh = shift;
chomp(my $child_cwd = <$rfh>);
ok(! dir($previous_cwd)->subsumes(dir($child_cwd)),
'checked drop_privs() SkipTempDirCreation success');
}, undef, SkipTempDirCreation => 1 # Need the undef placeholder.
);
# Set stay_root to true to disable priv dropping.
config(stay_root => 1);
# Test drop_privs() stay_root.
drop_privs_ok(
sub {
my $fh = shift;
# Write our real and effective uids to the tempfile.
print $fh "$$\n";
print $fh "$<\n";
print $fh "$>\n";
}, sub {
my $rfh = shift;
chomp(my $child_pid = <$rfh>);
chomp(my $new_uid = <$rfh>);
chomp(my $new_euid = <$rfh>);
# Due to the if above we're nonroot, so check that we did not
# fork, because only root is supposed to fork.
ok($child_pid == $$,
'checked drop_privs() stay_root no fork success.');
ok($new_uid == $previous_uid,
'checked drop_privs() stay_root uid success.');
ok($new_euid == $previous_euid,
'checked drop_privs() stay_root euid success.');
}
);
# clear stay_root to avoid messing up other tests.
config_delete('stay_root');
} else {
fail('Uhmmmm...this shouldn\'t happen...!?!');
}
if (is_os_type('Unix')) {
subtest 'test pipe_{write,read}_newline()' => sub {
my @expected = qw(Did it work ?);
pipe (READONLY, WRITEONLY)
or fail("Failed to create pipe??? Os error [$!]");
for (scalar fork) {
fail("Fork failed??? OS error [$!]") if not defined;
# For worked. parent goes here.
if (my $kidpid = $_) {
close WRITEONLY
or fail("parent writeonly pipe close failed??? [$!].");
my $readonly = *READONLY;
my $output;
$output .= $_ while (<$readonly>);
# Parent test goes here.
my @got = read_dropprivs_pipe(\$output);
for my $i (0..$#expected) {
is($got[$i], $expected[$i],
"checked pipe_{write,read}_newline() success [$i]");
}
fail("Got more than we expected [@got] [@expected]!")
if $#got > 3;
# End test start fork and pipe boilerplate.
close READONLY
or fail("parent readonly pipe close failed??? [$!].");
waitpid($kidpid, 0);
fail("Chil exited with nonzero exit code!")
if (($? >>8) != 0);
# For worked. child goes here.
} else {
close READONLY
or fail("child readonly pipe close failed??? [$!].");
my $write_pipe = *WRITEONLY;
# Test goes here.
# Finally test write_dropprivs_pipe().
write_dropprivs_pipe($write_pipe, @expected);
# End test start fork and pipe boilerplate.
close WRITEONLY
or fail("child writeonly pipe close failed??? [$!].");
exit 0;
}
}
};
} else {
note("Should be skipped, because you're not running this on Unix! [$^O]");
}
};
# Share these variables with safe_open()'s tests as root below in the SKIP
# block.
my $tempdir;
my ($fh, $filename);
subtest 'test safe_open()' => sub {
# Save $original_cwd so I can chdir back to where I came from later on.
my $original_cwd = cwd();
# create tempdir
$tempdir = tempdir("fetchware-test-$$-XXXXXXXXXXXX",
TMPDIR => 1, CLEANUP => 1);
# And chdir to it.
ok(chdir($tempdir), "checked safe_open() changed directory to [$tempdir]");
# Test open a file in tempdir check it with safe permu
# DIR is cwd(), because create_tempdir() creates a tempdir and
#chdir()s to it.
($fh, $filename) = tempfile("fetchware-test-$$-XXXXXXXXXXXXXXX", DIR => cwd());
note("FILENAME[$filename]");
close($fh);
my $safe_fh = safe_open($filename);
is_fh($safe_fh, 'checked safe_open() success');
close ($safe_fh);
# Test opening the file for writing.
# The undef is a placeholder for the second arg. The error mesage is not a
# named argument like WRITE is, because despite being optional, it's always
# going to be used in fetchware for more helpful error messages.
is_fh(safe_open($filename, undef,MODE => '>'),
'checked safe_open write success');
chmod 0640, $filename;
is_fh(safe_open($filename), 'checked safe_open() group readable success');
chmod 0604, $filename;
is_fh(safe_open($filename), 'checked safe_open() other readable success');
chmod 0644, $filename;
is_fh(safe_open($filename),
'checked safe_open() group and other readable success');
# Change perms to bad perms and check both group and owner
chmod 0660, $filename;
eval_ok(sub {safe_open($filename)},
qr/App-Fetchware-Util: The file fetchware attempted to open \[/,
'checked safe_open() file group perms unsafe');
# Make a directory inside the tempdir.
mkdir ('testdir') or fail ('Failed to make testing directory [testdir]');
# create a file inside the tempdir.
my ($sdfh, $subdirfilename)
= tempfile("fetchware-test-$$-XXXXXXXXXXXXXXX", DIR => cwd());
note("FILENAME[$subdirfilename]");
# Check for success on the file.
close($sdfh);
my $sfh = safe_open($subdirfilename);
is_fh($sfh, 'checked safe_open() success');
close ($sfh);
# Change perms for group and owner and recheck.
chmod 0640, $subdirfilename;
is_fh(safe_open($subdirfilename), 'checked safe_open() group readable success');
chmod 0604, $subdirfilename;
is_fh(safe_open($subdirfilename), 'checked safe_open() other readable success');
chmod 0644, $subdirfilename;
is_fh(safe_open($subdirfilename),
'checked safe_open() group and other readable success');
# change perms for group and owner of the containing directory you made, and
# recheck.
chmod 0660, $subdirfilename;
eval_ok(sub {safe_open($subdirfilename)},
qr/App-Fetchware-Util: The file fetchware attempted to open \[/,
'checked safe_open() file group perms unsafe');
# chdir back to $original_cwd so File::Temp can delete temp files.
chdir $original_cwd;
};
subtest 'test safe_open() needs root' => sub {
skip_all_unless_release_testing();
plan skip_all => 'Test suite not being run as root.' unless do {
if (is_os_type('Unix')) {
if ($< == 0 or $> == 0) {
# Return true
note('ISUNIXANDROOT');
1
} else {
# Return false
note('ISUNIXNOTROOT!!!');
0
}
} else {
# Return false
note('ISNOTUNIX');
0
}
};
if ($< == 0 or $> == 0) {
# Use dir from above. #$tempdir and $filename.
# Change group and owner perms on nobody owned dir.
my $parent_dir = dir($filename)->parent();
chmod 0640, $parent_dir;
is_fh(safe_open($parent_dir),
'checked safe_open() group directory readable success');
chmod 0604, $parent_dir;
is_fh(safe_open($parent_dir),
'checked safe_open() other directory readable success');
chmod 0644, $parent_dir;
is_fh(safe_open($parent_dir),
'checked safe_open() group and other directory readable success');
# Repeat for file too.
chmod 0640, $filename;
is_fh(safe_open($filename),
'checked safe_open() group file readable success');
chmod 0604, $filename;
is_fh(safe_open($filename),
'checked safe_open() other file readable success');
chmod 0644, $filename;
is_fh(safe_open($filename),
'checked safe_open() group and other file readable success');
# chown the tempdir to nobody, and check for diff owner.
# This call must happen after other checks, because it will make all
# checks for $filename fail with the expected exception below, and
# that change should just be isolated to this one test; therefore it
# is last.
chown(scalar getpwnam('nobody'), -1, $filename)
or fail("Failed to chown [$filename]!");
# Test it for failure.
my $error_string = <<EOE;
App-Fetchware-Util: The file fetchware attempted to open is not owned by root or
the person who ran fetchware. This means the file could have been dangerously
altered, or it's a simple permissions problem. Do not simly change the
ownership, and rerun fetchware. Please check that the file.*
EOE
eval_ok(sub {safe_open($filename)},
qr/$error_string/,
'checked safe_open() wrong owner failure');
# Make a custom tempdir in / the root directory.
( run in 0.771 second using v1.01-cache-2.11-cpan-64ef6c95b5d )