#!/usr/bin/perl -w #$Header: sunfingerprint,v0.9 2000/12 afb$ #$! sunfingerprint: checks file list against Suns md5 database # reads input file/stdin, of the format: # /usr/bin/ls # /usr/bin/cat # that is, one file per line, md5's the files and fetches the results of # a search against Sun's md5 executable db. # Relies on some formatting of Sun's results page, which may vary someday. # Always tests the md5 executable, also. # fixed 20/0 matches oops - multiple matches appear for same exe in multiple # Sol versions # added -l libs flag so you can check lib files (not executables) require LWP::UserAgent; use Getopt::Std; use strict; my $debug = 0; my $md5 = "/usr2/local/bin/md5"; my $request; my $output_all = 0; my $errors_only = 0; my $un_html = 1; # Sun's fingerprint site my $request_http = "http://sunsolve.Sun.COM/pub-cgi/fileFingerprints.pl"; my $Usage = "Usage: $0 [-d X|-l|-e|-h|-o X] file_list file_list: a text file w/ full path names for the files to be viewed use - to use stdin, e.g.: find /bin -print | $0 -d X debug level X -h leave html tags in output -e errors only -l libs, ignore executable status -o X output level X (0 matches only, 1 Sun results, 2 full text, 3 full html page) "; my %opts; # must have a file list die "$Usage" unless @ARGV; getopts('lho:d:e',\%opts) or die "$Usage"; $debug = $opts{d} ? $opts{d} : 0; $errors_only = 1 if $opts{e}; $un_html = 0 if $opts{h}; $output_all = $opts{o} ? $opts{o} : 0; $output_all = 0 if $errors_only; my $mdlist; my %mdlist; my %matches; my $mdhash; # read input, check file's existence/executable while (<>) { chomp; next unless /^\s+\//; $mdlist{$_} = "Not Found!"; if ( -s $_ ) { $mdlist .= "$_ " ; $mdlist{$_} = "Found"; if ( ! -x $_ ) { $mdlist{$_} .= ", Not Executable" unless $opts{l}; } # if ! -x } # if -s } # while <> # add md5 exe to list $mdlist .= "$md5"; # ugly hack $mdlist{$md5} = "Found"; # md5 the files open(MD5, "$md5 $mdlist | ") or die "can't open md5 $md5: $!"; while () { $mdhash .= "$_"; } close MD5; # fetch the cgi results from sun my $ua = LWP::UserAgent->new; print STDERR "POSTing $mdhash to $request_http\n" if $debug > 20; if ( $mdhash ) { #$request = new HTTP::Request POST => $request_http; $request = HTTP::Request->new('POST', $request_http); $request->content_type('application/x-www-form-urlencoded'); $request->content("md5list=$mdhash"); } else { die "$Usage"; } print STDERR "Request: ", $request->content, "\n" if $debug > 20; my $response = $ua->request($request); # actually fetch the doc if ( $response->is_success ) { # split up the html return and process the lines between the # "Results ..." line and the end of the list my $pr = 0; my $file_path; print STDERR "Success\n" if $debug > 10; foreach ( split(/\n/, $response->content) ) { next if /^\s*$/; if ( $pr ) { last if /<\/DL>/; s/<[ =#\/\w]+>//g if $un_html; # line w/ sun's response: # 36e7b0c2c6b2b391722c2471688a060b - (/usr/bin/ls) - 1 match(es) if ( /match/ ) { print STDERR "match: $_\n" if $debug > 2; # get file name and matches /\((\S+)\) - (.*)/; $file_path = $1; # add Sun's response $mdlist{$file_path} .= ", $2 w/ Sun"; $matches{$file_path} = "$_\n" if $output_all; } else { $matches{$file_path} .= "$_\n" if $output_all > 1 and $file_path; } } # if pr # start printing $pr++ if /Results of Last Search/i; } # foreach content # output the final data, input files and any results if ( $output_all != 3 ) { foreach my $file ( sort keys %mdlist ) { if ( $errors_only ) { $_ = $mdlist{$file}; print "$file: $mdlist{$file}\n" if /Not/ or / 0 match/; } else { if ( $matches{$file} ) { print "$file: $matches{$file}\n"; } else { print "$file: $mdlist{$file}\n\n"; } # if matches } # if errors_only } # foreach file } else { # dump the whole page, if wanted print "Content: ", $response->content, "\n"; } # if output_all == 3 } else { print STDERR "Result: cgi request failed! $request_http\n"; }