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 )