Re: Checking for most recent Solaris Security Patches

From: Ronan Waide (waiderat_private)
Date: Thu Jan 07 1999 - 01:41:00 PST

  • Next message: Ian R. Justman: "setuid vs. setgid (was Re: Anonymous Qmail Denial of Service)"

    --wXN96xPRKk
    Content-Type: text/plain; charset=us-ascii
    Content-Description: message body text
    Content-Transfer-Encoding: 7bit
    
    On January 6, spamhaterat_private said:
    > Enclosed is a script that checks if your Solaris system has the
    > latest security patches applied.
    >
    > It FTP's the status file from Sun's site, caches a local copy, does a
    > "showrev -a", compares the two, and reports out-of-date patches.
    > This is not a perfect test, but it is quick and easy, and some might find
    > it useful.
    >
    > If the local copy is old, you either get a warning, or a forced update
    > of the patch information file. (A configuration option).
    >
    > The package requires expect and perl 5 (no perl modules need be
    > installed).
    
    Funnily enough... :)
    
    I've a version of a similar program sitting on one of the Solaris
    boxen here for the last few months, which I hacked together after
    getting fed up with doing the job manually. It's almost purely perl;
    no expect, no variable settings. It's not got commandline switches
    either, since I wrote it for my own use.
    
    Module-wise, it uses Net::FTP to do the fetching, and POSIX (part of
    the core distribution anyway) to get your OS details.
    
    Anyway, here it is. YMMV. It's only been used on 2.4 and 2.6, so if it
    catches fire, lemme know what broke.
    
    Cheers,
    Waider.
    
    --wXN96xPRKk
    Content-Type: text/plain
    Content-Description: patch checker in Perl
    Content-Disposition: inline;
            filename="patchcheck.pl"
    Content-Transfer-Encoding: 7bit
    
    #!/usr/local/bin/perl -w
    
    use Net::FTP;
    use POSIX; # for uname
    
    $ftp = undef;
    
    # You may wish to edit these
    $PATCHHOST='sunsolve1.Sun.COM';
    $PATCHDIR='/pub/patches';
    $SHOWREV='/usr/bin/showrev -p';
    
    # Check OS version
    $os = (uname)[0];
    $osver = (uname)[2];
    
    # Gah. SunOS $osver is 5.x instead of Solaris' 2.x. I guess subtract 3...
    $osver = $osver - 3 if ( $os eq 'SunOS' );
    
    $RECOMMENDED=$osver.'_Recommended.README';
    
    $|=1;
    
    print "Fetching $RECOMMENDED from Sun...";
    maybe_fetch_file( $RECOMMENDED );
    print "done.\n";
    
    open( PLIST, "$SHOWREV|" ) || die $!;
    open( RECOM, "<$RECOMMENDED" ) || die $!;
    
    while( <PLIST> )
    {
            (undef, $patch, undef) = split;
            ($id, $rev) = split(/-/, $patch);
            $erev = $installed{ $id };
            $erev ||= '00';
            print STDERR "already: $erev\n";
            $installed{ $id } = $rev if $rev > $erev;
    }
    %recommended = map
    {
            if ( /^[0-9][0-9][0-9][0-9][0-9][0-9]\-[0-9][0-9]\s+/ )
            {
                    chomp;
                    ($patch, undef) = split;
                    ($id, $rev) = split(/-/, $patch);
                    $id => $rev ;
            }
            else
            {
                    'dud' => 'dud';
            }
    } <RECOM>;
    
    close( RECOM );
    close( PLIST );
    
    %patches = map { $_ => $_ } keys %installed;
    for( keys %recommended )
    {
            $patches{ $_ } = $_ unless $_ =~ /dud/;
    }
    @patches = keys %patches;
    
    print "Patch Report\nID\tInstalled\tRecommended\tAction\n";
    
    for( @patches )
    {
            $inst = $installed{ $_ };
            $rec = $recommended{ $_ };
            $inst ||= '00';
            $rec ||= '00';
    
            $action = ( $inst < $rec ) ? "fetching..." : "installed\n";
    
            printf "$_ \t%s\t\t%s\t\t%s", $inst, $rec, $action;
            if ( $action eq "fetching..." )
            {
                    maybe_fetch_file( "$_-$rec.tar.Z" );
                    print "done.\n";
            }
    }
    
    if ( $ftp )
    {
            $ftp->close();
    }
    
    sub maybe_fetch_file()
    {
            $file = shift;
    
            # check for local copy of the file
            if ( -r $file )
            {
                    # stat local copy, get mtime & size
                    (undef, undef, undef, undef, undef, undef, undef, $locsz,
                     undef, $loctm, undef, undef, undef ) = stat( $file );
            }
            else
            {
                    $locsz = 0;
                    $loctm = 0;
            }
    
            # check if ftp connection is live, reopen if necessary
            if ( !defined( $ftp ) || !ref( $ftp ) || !$ftp->pwd )
            {
                    $ftp = Net::FTP->new( $PATCHHOST );
                    $ftp->login( 'anonymous', 'waiderat_private' );
                    $ftp->cwd( $PATCHDIR );
                    $ftp->pasv();
                    $ftp->binary();
            }
    
            # check mtime & size of remote copy
            $remsz = $ftp->size( $file ) || die $!;
    
            # if mtime of local is more recent & sizes match, return
            if ( $remsz == $locsz )
            {
                    $remtm = $ftp->mdtm( $file );
                    if ( $remtm <= $loctm )
                    {
                            return;
                    }
            }
    
            # fetch file
            $ftp->get( $file );
    }
    
    --wXN96xPRKk
    Content-Type: text/plain; charset=us-ascii
    Content-Description: .signature
    Content-Transfer-Encoding: 7bit
    
    
    --
    waiderat_private / Scope Communications / +353-1-8303455 / +353-1-8300888 (Fax)
    "When you say `I wrote a program that crashed Windows', people just stare
     at you blankly and say `Hey, I got those with the system, *for free*'"
                                                       - Linus Torvalds
    
    --wXN96xPRKk--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:27:54 PDT