App-Fetchware
view release on metacpan or search on metacpan
t/App-Fetchware-Util.t view on Meta::CPAN
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.
my ($fh, $root_filename) =
tempfile("fetchware-root-test-$$-XXXXXXXXXXXXXXX",
DIR => rootdir(),
UNLINK => 1
);
# Test it on a root dir that won't recurse into subdirs, because they're
# arn't any.
chmod 0640, $root_filename;
is_fh(safe_open($root_filename),
'checked safe_open() group file readable success');
chmod 0604, $root_filename;
is_fh(safe_open($root_filename),
'checked safe_open() other file readable success');
chmod 0644, $root_filename;
is_fh(safe_open($root_filename),
'checked safe_open() group and other file readable success');
} else {
note("Should be skipped, because you're not root! [$<] [$>]");
}
};
sub is_fh {
my $fh = shift;
my $test_name = shift;
ok(ref($fh) eq 'GLOB', $test_name);
}
# Allows me to test drop_privs() more than once without shitloads of copying and
# pasting the same stupid code over and over again.
# $writer_code is a coderef that does something, and prints values to its one
# argument $fh.
# Then $tester_code, which is a coderef, gets passed $rfh, which is a read-only
# file handle of the same file that $writer_code wrote to, and then $tester_code
# reads from $rfh, and compares the values it gets to what it expects using
# standard Test::More stuff such as is().
# @drop_privs_args is an optional array of options that are passed to
# drop_privs(), but the only option drop_privs() cares about is $regular_user.
sub drop_privs_ok {
my $writer_code = shift;
my $tester_code = shift;
my @drop_privs_args = @_;
# Switch to a directory that will pass File::Temp's HIGH safe_level(), which
# is a system wide tempdir().
my $original_cwd = cwd();
chdir tmpdir()
or fail("Failed to chdir to [@{[tmpdir()]}]. OS error [$!]");
my $output = drop_privs(sub {
my $write_pipe = shift;
$writer_code->($write_pipe);
}, @drop_privs_args);
# Open $output as a scalar ref to use perl to parse the output.
open my $output_fh, '<', $output
or fail("Failed to open [$output] [$$output]. OS error [$!]");
$tester_code->($output_fh);
# chdir back to $orignal_cwd like we were there the whole time.
chdir $original_cwd
or fail("Failed to chdir to [@{[tmpdir()]}]. OS error [$!]");
}
# Remove this or comment it out, and specify the number of tests, because doing
# so is more robust than using this, but this is better than no_plan.
#done_testing();
( run in 0.905 second using v1.01-cache-2.11-cpan-39bf76dae61 )