MOON
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4
System: Linux csr818.wilogic.com 2.6.18-419.el5xen #1 SMP Fri Feb 24 22:50:37 UTC 2017 x86_64
User: digitals (531)
PHP: 5.4.45
Disabled: NONE
Upload Files
File: //scripts.20110531.215904.25158/securetmp
#!/usr/bin/perl
# cpanel - securetmp                              Copyright(c) 2010 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

BEGIN { unshift @INC, '/usr/local/cpanel'; }

use strict;
use Cpanel::SafeFile ();
use Cpanel::OSSys  ();
use Getopt::Long;
use Cpanel::Logger          ();
use Cpanel::SafeRun::Errors ();
use Cpanel::SafeRun::Simple ();

my $logger = Cpanel::Logger->new();

$| = 1;

if ( -e '/var/cpanel/version/securetmp_disabled' ) {
    print "[securetmp] Disabled per /var/cpanel/version/securetmp_disabled\n";
    exit;
}

my $system          = $^O;
my $has_loop_device = 0;

# do check for loopback module for Linux based VPS

if ( $system =~ m/Linux/i ) {
    my @modules = Cpanel::SafeRun::Errors::saferunallerrors('lsmod');
    my $loopdev = 0;
    $has_loop_device = check_loop_device();

    if ( !grep /loop/, @modules ) {
        print "*** Notice *** No loop module detected\n";    # could be built into kernel, so don't bail out yet
        print "If the loopback block device is built as a module, try running `modprobe loop` as root via ssh and running this script again.\n";
        print "If the loopback block device is built into the kernel itself, you can ignore this message.\n";
    }
    if ( !$has_loop_device ) {
        print "*** Notice *** No working loopback device files found. Try running `modprobe loop` as root via ssh and running this script again.\n";
        exit(0);
    }
}

my $install   = 0;                                           # Add securetmp to system startup
my $uninstall = 0;                                           # Remove from system startup
my $auto      = 0;                                           # Secure /tmp and /var/tmp

# Get command line options
GetOptions( 'auto' => \$auto, 'install' => \$install, 'uninstall' => \$uninstall );

# Start interactive setup
if ( !$auto && !$install && !$uninstall && -t STDIN ) {
    print 'Would you like to secure /tmp & /var/tmp at boot time? (y/n) ';
    my $answer;
    chomp( $answer = <STDIN> );
    if ( $answer =~ m/^y/i ) {
        $install = 1;
    }
    else {
        print "securetmp will not be added to system startup at this time.\n";
    }
    undef $answer;

    if ( !$install ) {
        print 'Would you like to disable securetmp from the system startup? (y/n) ';
        chomp( $answer = <STDIN> );
        if ( $answer =~ m/^y/i ) {
            $uninstall = 1;
        }
        else {
            print "securetmp will not be removed from system startup.\n";
        }
        undef $answer;
    }

    print 'Would you like to secure /tmp & /var/tmp now? (y/n) ';
    chomp( $answer = <STDIN> );
    if ( $answer =~ m/^y/i ) {
        $auto = 1;
    }
    else {
        print "/tmp & /var/tmp will not be secured at this time.\n";
    }

    exit if ( !$install && !$auto && !$uninstall );
}
elsif ( !$auto && !$install && !$uninstall ) {
    exit 1;
}

## ADD/REMOVE from startup
#-----------------------------------------------------------------

if ( !-x '/scripts/cpservice' ) {
    $logger->warn("cpservice is not available. Please check its status.");
}
else {

    # Remove securetmp from system startup
    if ($uninstall) {
        Cpanel::SafeRun::Simple::saferun( '/scripts/cpservice', 'securetmp', 'stop' );
        Cpanel::SafeRun::Simple::saferun( '/scripts/cpservice', 'securetmp', 'disable', '2345' );
        Cpanel::SafeRun::Simple::saferun( '/scripts/cpservice', 'securetmp', 'uninstall' );
    }

    # Add securetmp to system startup
    if ($install) {
        Cpanel::SafeRun::Simple::saferun( '/scripts/cpservice', 'securetmp', 'install' );
        Cpanel::SafeRun::Simple::saferun( '/scripts/cpservice', 'securetmp', 'enable', '35' );
        Cpanel::SafeRun::Simple::saferun( '/scripts/cpservice', 'securetmp', 'start' );
    }

}

#-----------------------------------------------------------------

# Fork and secure if not called from console
if ( $auto && !-t STDIN ) {
    $SIG{'CHLD'} = \&reaper;
    print "Setting up /tmp & /var/tmp in the background\n";
    exit if fork;
}
elsif ( !$auto ) {
    exit;
}

print "Securing /tmp & /var/tmp\n";

# Secure PATH
$ENV{'PATH'} .= ":/sbin:/usr/sbin";

# Global Variables
my $brokenvartmp   = 0;
my $freebsdversion = '';
my @vnodes         = ();
my $vnodeconfig    = '';
my $vnodesrch      = '';
my $vnodenumber    = 0;
my $tmpmnt         = '';
my $vartmpmnt      = '';
my $tmpopts        = '';
my $vartmpopts     = '';
my $mountkeyword   = '';
my $cpflags        = '';
my $tmpdsksize     = 512000;    # Must be larger than 250000

# FreeBSD Logic
if ( $system =~ m/freebsd/i ) {
    $mountkeyword   = 'update';
    $cpflags        = '-Rpf';
    $freebsdversion = ( Cpanel::OSSys::uname() )[2];
    @vnodes         = ();
    $vnodeconfig    = '';
    $vnodesrch      = '';

    # Set vnode config method
    if ( $freebsdversion =~ m/^4/ ) {
        $vnodeconfig = 'vnconfig';
        $vnodesrch   = 'vn';
    }
    elsif ( $freebsdversion =~ m/^(?:5|6|7|8|9)/ ) {
        $vnodeconfig = 'mdconfig';
        $vnodesrch   = 'md';
    }
    else {
        die "FreeBSD version $freebsdversion is not supported.";
    }

    open( MT, 'mount|' ) || die "Unable to execute mount: $!";
    while ( my $line = <MT> ) {
        if ( $line =~ m/(\S+)\s+on\s+(\S+)\s+\(([^\)]+)/ ) {
            my $device = $1;
            my $mount  = $2;
            my $opts   = $3;
            if ( $mount eq '/tmp' ) {
                $tmpmnt  = $device;
                $tmpopts = $opts;
            }
            elsif ( $mount eq '/var/tmp' ) {
                $vartmpmnt  = $device;
                $vartmpopts = $opts;
            }
            if ( $vnodeconfig eq 'vnconfig' && $device =~ m/^\/dev\/${vnodesrch}\d+/ ) {
                push @vnodes, $device;
            }
        }
    }
    close(MT);

    # Determine next usable vnode (vnconfig)
    if (@vnodes) {
        foreach my $vnode (@vnodes) {
            $vnode =~ /(\d+)/;
            if ( $1 > $vnodenumber ) {
                $vnodenumber = $1;
            }
        }
        $vnodenumber++;
    }
}
else {    # Linux Logic
    $mountkeyword = 'remount';
    $cpflags      = '-af';

    if ( open my $mounts_fh, '<', '/proc/mounts' ) {
        while ( my $line = readline $mounts_fh ) {

            # must detect: /dev/sda1 /var/tmp\040(deleted) ext2 rw,nosuid,noexec,usrquota 0 0
            if ( $line =~ m/^(\S+)\s+([^\s\\\(]+)\S*\s+\S+\s+(\S+)/ ) {
                if ( $2 eq '/tmp' ) {
                    $tmpmnt  = $1;
                    $tmpopts = $3;
                }
                elsif ( $2 eq '/var/tmp' ) {
                    $vartmpmnt  = $1;
                    $vartmpopts = $3;
                }
                if ( $1 =~ /^\/dev\/vn.*/ ) {
                    push @vnodes, $1;
                }
            }

            if ( $line =~ m/\S+\s+\(deleted\)[^\/]*\/var\/tmp\s+/ ) {
                $brokenvartmp = 1;
                $vartmpmnt    = '';
                $vartmpopts   = '';
            }
        }
        close $mounts_fh;
    }
    else {
        die "Unable to read /proc/mounts: $!";
    }
}

# Begin securetmp actions
if ( !$tmpmnt ) {

    # Check loop dev on Linux
    if ( $system =~ m/Linux/i ) {
        if ( !$has_loop_device ) {
            print "The system does not support loop devices.\n";
            if ($brokenvartmp) {
                print 'Unmounting orphaned /var/tmp ...';
                system 'umount', '/var/tmp';
                print "Done\n";
            }
            exit;
        }
    }

    if ( !-e '/usr/tmpDSK' ) {
        print "No separate partition for tmp!\n";
        createtmpdisk($system);
    }
    elsif ( -d '/usr/tmpDSK' ) {
        die "/usr/tmpDSK exists as a directory. Please remove and rerun /scripts/securetmp.\n";
    }

    # ensure that /usr/tmpDSK is large enough
    elsif ( ( -s '/usr/tmpDSK' ) < 250000000 ) {
        system 'rm', '-f', '/usr/tmpDSK';
        createtmpdisk($system);
    }
    print 'Setting up /tmp... ';
    if ( -e '/usr/tmp.secure' ) {
        system 'mv', '-f', '/usr/tmp.secure', '/usr/tmp.secure.cpback';
    }
    mkdir '/usr/tmp.secure';
    archivecopy( '/tmp', '/usr/tmp.secure' );
    system 'rm', '-rf', '/tmp';
    mkdir '/tmp';
    chmod( oct(1777), '/tmp' );
    my $mountresult = mounttmpdsk( $system, $tmpopts );
    archivecopy( '/usr/tmp.secure/tmp/.', '/tmp' );
    chmod( oct(1777), '/tmp' );
    system 'rm', '-rf', '/usr/tmp.secure';

    if ($mountresult) {
        die "There was a problem mounting /tmp: $mountresult";
    }
    print "Done\n";
}
elsif ( $tmpmnt && $tmpopts !~ m/noexec/ ) {
    print 'Securing /tmp... ';
    system 'mount', '-o', $mountkeyword . ',noexec,nosuid', $tmpmnt, '/tmp';
    print "Done\n";
}
else {
    print "/tmp is already secure\n";
}

if ( $brokenvartmp || ( $vartmpmnt && $vartmpopts !~ m/noexec/ ) ) {
    print 'Unmounting insecure /var/tmp... ';
    system 'umount', '/var/tmp';
    $vartmpmnt  = '';
    $vartmpopts = '';
    print "Done\n";
}

if ( !$vartmpmnt ) {
    print 'Setting up /var/tmp... ';

    if ( !-e '/var/tmp' ) {
        mkdir '/var/tmp';
    }
    elsif ( !-d '/var/tmp' ) {
        system 'mv', '/var/tmp', '/var/tmp.cpback';
        mkdir '/var/tmp';
    }

    if ( $system =~ m/freebsd/i ) {
        if ( $freebsdversion =~ m/^(5|6|7|8|9)/ ) {
            system 'mount_nullfs', '-o', 'noexec,nosuid', '/tmp', '/var/tmp';
        }
        else {
            system 'mount_null', '-o', 'noexec,nosuid', '/tmp', '/var/tmp';
        }
    }
    else {
        system 'mount', '-o', 'bind,noexec,nosuid', '/tmp', '/var/tmp';
    }
    print "Done\n";
}
else {
    print "/var/tmp is already secure\n";
}

my $usingTMPDSK = 0;
if ( -e '/usr/tmpDSK' ) {
    my $mount = `mount`;
    if ( $mount =~ m/tmpDSK/ ) {
        $usingTMPDSK = 1;
    }
}

print 'Checking fstab for entries ...';
my $hastmpdsk    = 0;
my $hasvartmpdsk = 0;
my $fslock       = Cpanel::SafeFile::safeopen( \*FSTAB, '+<', '/etc/fstab' );
if ($fslock) {
    while (<FSTAB>) {
        if (/^\s*\/usr\/tmpDSK/)      { $hastmpdsk    = 1; }
        if (/^\s*(\S+)\s*\/var\/tmp/) { $hasvartmpdsk = 1; }
    }

    if ( !$hastmpdsk && $usingTMPDSK ) {
        print "Added fstab entry (/tmp)....";
        if ( $system =~ /freebsd/i ) {
            print FSTAB "/usr/tmpDSK             /tmp                    nullfs   rw,noauto        0 0\n";
        }
        else {
            print FSTAB "/usr/tmpDSK             /tmp                    ext3    defaults,noauto        0 0\n";
        }
    }
    if ( !$hasvartmpdsk && $vartmpmnt ) {
        print "Added fstab entry (/var/tmp)....";
        if ( $system =~ /freebsd/i ) {
            print FSTAB "/tmp             /var/tmp                    nullfs   rw,noauto        0 0\n";
        }
        else {
            print FSTAB "/tmp             /var/tmp                    ext3    defaults,bind,noauto        0 0\n";
        }
    }

    Cpanel::SafeFile::safeclose( \*FSTAB, $fslock );
    print "Done\n";
}
else {
    $logger->die("Could not edit /etc/fstab");
}

my $logrotate = '/etc/cron.daily/logrotate';
if ( -e $logrotate ) {
    my @logrotate_contents;
    my $has_tmpdir = 0;
    if ( open my $logrotate_fh, '<', $logrotate ) {
        while ( my $line = readline $logrotate_fh ) {
            if ( $line =~ m/TMPDIR/ && $line !~ m/^\s*#/ ) {
                $has_tmpdir = 1;
                last;
            }
            push @logrotate_contents, $line;
        }
        close $logrotate_fh;

        if ( !$has_tmpdir ) {
            my $updated_logrotate = 0;
            if ( open my $logrotate_fh, '>', $logrotate ) {
                foreach my $line (@logrotate_contents) {
                    if ( $line =~ m/^#!\/(?:usr|bin)/ ) {
                        print "Adding TMPDIR setting to /etc/cron.daily/logrotate\n";
                        print {$logrotate_fh} $line;
                        print {$logrotate_fh} "export TMPDIR=/var/spool/logrotate/tmp\n";
                        $updated_logrotate = 1;
                    }
                    else {
                        print {$logrotate_fh} $line;
                    }
                }
                close $logrotate_fh;
            }
            if ($updated_logrotate) {
                if ( !-e '/var/spool/logrotate/tmp' ) {
                    system 'mkdir', '-p', '/var/spool/logrotate/tmp';
                }
                if ( !-d '/var/spool/logrotate/tmp' ) {
                    print <<'EOM';
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Logrotate detected and TMPDIR setting updated. The TMPDIR 
directory (/var/spool/logrotate/tmp) does not exist!

Logrotate will need to use this directory for execution of 
its postrotate scripts. This directory is normally /tmp, but
due to /tmp being set as non-executable an alternative 
directory must be specified. Please correct this issue. 

See /etc/cron.daily/logrotate to adjust the TMPDIR value for your system.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
EOM
                }
            }
            else {
                warn "Failed to update /etc/cron.daily/logrotate! Logrotate may be corrupt.";
            }
        }
        else {
            print "Logrotate TMPDIR already configured\n";
        }
    }
}

print "Process Complete\n";

exit;

################################################################################
# createtmpdisk
################################################################################
sub createtmpdisk {
    my $system = shift;

    print "Building /usr/tmpDSK...";
    if ( -e "/usr/tmpDSK" ) {
        unlink("/usr/tmpDSK");
    }
    system( "dd", "if=/dev/zero", "of=/usr/tmpDSK", "bs=1024", "count=${tmpdsksize}" );
    if ( $system !~ /freebsd/i ) {
        open( MKFS, "|-" ) || exec( "/sbin/mkfs", "/usr/tmpDSK" );
        print MKFS "yes\r\n";
        close(MKFS);
        if ( -e "/sbin/tune2fs" ) {
            system( "/sbin/tune2fs", "-j", "/usr/tmpDSK" );
        }
    }
    chmod 0600, '/usr/tmpDSK';
    print "Done\n";
}

################################################################################
# archivecopy
################################################################################
sub archivecopy {
    my ( $origin, $dest ) = @_;

    my $cpflags = '-af';
    if ( $system =~ /freebsd/i ) {
        $cpflags = '-Rpf';
    }
    system( "cp", $cpflags, $origin, $dest );
}

################################################################################
# mounttmpdsk
################################################################################
sub mounttmpdsk {
    my $system         = shift;
    my $currentmntopts = shift;

    if ( $system =~ /freebsd/i ) {
        my $results = `which $vnodeconfig`;
        chomp($results);
        if ( $results eq "" ) {
            return (1);
        }

        if ( $vnodeconfig eq "vnconfig" ) {

            # FreeBSD 4
            print " using vnconfig\n";
            if ( !-e "/dev/vn${vnodenumber}c" ) {
                system("cd /dev; rm -f vn${vnodenumber}*; sh MAKEDEV vn${vnodenumber}");
            }
            system( "vnconfig", "-u", "vn${vnodenumber}" );
            system( "vnconfig", "-s", "labels", "-c", "vn${vnodenumber}", "/usr/tmpDSK" );
            system( "disklabel", "-r", "-w",               "vn${vnodenumber}",       "auto" );
            system( "newfs",     "vn${vnodenumber}c" );
            system( "mount",     "-o", "noexec,nosuid,rw", "/dev/vn${vnodenumber}c", "/tmp" );
        }
        elsif ( $vnodeconfig eq "mdconfig" ) {

            # FreeBSD 5+
            print " using mdconfig.\n";
            $vnodenumber = `mdconfig -a -t vnode -f /usr/tmpDSK`;
            chomp($vnodenumber);
            if ( $vnodenumber !~ /^md\d+/ ) {
                return (1);
            }

            # FreeBSD < 5.1 uses disklabel
            my $label   = "bsdlabel";
            my $results = `which $label`;
            chomp($results);
            if ( $results eq "" ) {
                $label   = "disklabel";
                $results = `which $label`;
                chomp($results);
                if ( $results eq "" ) {
                    return (1);
                }
            }
            if ( $label eq "bsdlabel" ) {
                system( "$label", "-w", "$vnodenumber", "auto" );
            }
            else {
                system( "$label", "-r", "-w", "$vnodenumber", "auto" );
            }

            system( "newfs", "${vnodenumber}a" );
            system( "mount", "-o", "noexec,nosuid,rw", "/dev/${vnodenumber}a", "/tmp" );
        }
        else {
            return (1);
        }
    }
    else {
        if ( $currentmntopts !~ m/loop/ ) {
            system( 'mount', '-o', 'loop,noexec,nosuid,rw', '/usr/tmpDSK', '/tmp' );
        }
    }
    return (0);
}

sub add_securetmp_to_rc {
    my $rc_local = -e '/etc/rc.d/rc.local' ? '/etc/rc.d/rc.local' : '/etc/rc.local';    # Defaults to /etc/rc.local

    if ( open my $rc_fh, '+<', $rc_local ) {
        my $has_securetmp = 0;
        my @lines;
        while ( my $line = readline $rc_fh ) {
            chomp $line;
            if ( $line !~ m/^\s*#/ && $line =~ m/\/scripts\/securetmp/ ) {
                $has_securetmp = 1;
                push @lines, $line;
            }
            elsif ( $line =~ m/securetmp/ ) {
                next;
            }
            else {
                push @lines, $line;
            }
        }

        seek( $rc_fh, 0, 0 );

        print {$rc_fh} join( "\n", @lines ) . "\n";
        if ( !$has_securetmp ) {
            print {$rc_fh} "# Added by /scripts/securetmp\n";
            print {$rc_fh} "/scripts/securetmp --auto\n";
        }

        truncate( $rc_fh, tell($rc_fh) );
        close $rc_fh;
        chmod 0755, $rc_local;
    }
    else {
        print "Unable to update $rc_local\n";
        exit 1;
    }
}

# [Intending for FreeBSD OS]
sub remove_securetmp_from_rc {
    my $rc_local = -e '/etc/rc.d/rc.local' ? '/etc/rc.d/rc.local' : '/etc/rc.local';    # Defaults to /etc/rc.local
    my @lines;
    if ( open my $rc_fh, '+<', $rc_local ) {
        while ( my $line = readline $rc_fh ) {
            chomp $line;
            if ( $line =~ m/securetmp/ ) {
                next;
            }
            else {
                push @lines, $line;
            }
        }

        seek( $rc_fh, 0, 0 );

        print {$rc_fh} join( "\n", @lines ) . "\n";

        truncate( $rc_fh, tell($rc_fh) );
        close $rc_fh;
        chmod 0755, $rc_local;
    }
    else {
        print "Unable to update $rc_local\n";
        exit 1;
    }
}

sub check_loop_device {
    my @loop_devices = glob('/dev/loop*');

    return if !@loop_devices;

    local $ENV{'LANG'} = 'C';

    my $loop_device;
    foreach my $dev ( sort @loop_devices ) {
        my $test = Cpanel::SafeRun::Errors::saferunallerrors( 'losetup', $dev );
        if ( $test =~ m/^loop:/ && $test =~ m/can't\s+open\s+device/i ) {
            next;
        }
        elsif ( $test =~ m/^loop:/ && $test =~ m/can't\s+get\s+info/i ) {
            $loop_device = 1;
            last;
        }
        elsif ( $test =~ m/^$dev:/ ) {
            $loop_device = 1;
            last;
        }
    }
    return $loop_device;
}

################################################################################
# reaper
################################################################################
sub reaper {
    my $thedead;
    while ( ( $thedead = waitpid( -1, 1 ) ) > 0 ) {

        # the dead shall do what ?
    }
    $SIG{CHLD} = \&reaper;
}