Thu, 04 Oct 2012 20:30:05 +0200
Correct out of date build configuration, porting to Solaris 11 network
link infrastructure and new libpcap logic. This additionally allows for
device drivers in subdirectories of /dev. Correct packaged nmap
personalities and signatures to work out of the box. Finally, hack
arpd logic to properly close sockets and quit on TERM by repeating
signaling in the run command script. Sadly, all this fails to correct
the run time behaviour of honeyd which fails to bind to the IP layer.
michael@428 | 1 | ## |
michael@428 | 2 | ## lint-rpm.pl -- OpenPKG *.rpm File Checker |
michael@428 | 3 | ## Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/> |
michael@428 | 4 | ## |
michael@428 | 5 | ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
michael@428 | 6 | ## All rights reserved. Licenses which grant limited permission to use, |
michael@428 | 7 | ## copy, modify and distribute this software are available from the |
michael@428 | 8 | ## OpenPKG GmbH. |
michael@428 | 9 | ## |
michael@428 | 10 | ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
michael@428 | 11 | ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
michael@428 | 12 | ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
michael@428 | 13 | ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
michael@428 | 14 | ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@428 | 15 | ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@428 | 16 | ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
michael@428 | 17 | ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
michael@428 | 18 | ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
michael@428 | 19 | ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
michael@428 | 20 | ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
michael@428 | 21 | ## SUCH DAMAGE. |
michael@428 | 22 | ## |
michael@428 | 23 | |
michael@428 | 24 | # Perl run-time requirement |
michael@428 | 25 | require 5; |
michael@428 | 26 | BEGIN { |
michael@428 | 27 | eval "use Getopt::Long; use IO;"; |
michael@428 | 28 | if ($@) { |
michael@428 | 29 | print STDERR |
michael@428 | 30 | "lint-rpm: ERROR: This command requires a full-size Perl installation!\n" . |
michael@428 | 31 | "lint-rpm: HINT: Install OpenPKG \"perl\" package to use this command.\n"; |
michael@428 | 32 | exit(1); |
michael@428 | 33 | } |
michael@428 | 34 | } |
michael@428 | 35 | |
michael@428 | 36 | # OpenPKG instance prefix |
michael@428 | 37 | my $my_prefix = $ENV{'OPENPKG_PREFIX'}; |
michael@428 | 38 | delete $ENV{'OPENPKG_PREFIX'}; |
michael@428 | 39 | |
michael@428 | 40 | # program information |
michael@428 | 41 | my $progname = "lint-rpm"; |
michael@428 | 42 | my $progvers = "1.0.0"; |
michael@428 | 43 | |
michael@428 | 44 | # parameters (defaults) |
michael@428 | 45 | my $version = 0; |
michael@428 | 46 | my $verbose = 0; |
michael@428 | 47 | my $help = 0; |
michael@428 | 48 | my $check = 'all'; |
michael@428 | 49 | my $tmpdir = ($ENV{TMPDIR} || $ENV{TEMPDIR} || "/tmp") . "/$progname"; |
michael@428 | 50 | my $rpm = "$my_prefix/bin/openpkg rpm"; |
michael@428 | 51 | my $rpm2cpio = "$my_prefix/bin/openpkg rpm2cpio"; |
michael@428 | 52 | |
michael@428 | 53 | # exception handling support |
michael@428 | 54 | $SIG{__DIE__} = sub { |
michael@428 | 55 | my ($err) = @_; |
michael@428 | 56 | $err =~ s|\s+at\s+.*||s if (not $verbose); |
michael@428 | 57 | print STDERR "$progname:ERROR: $err ". ($! ? "($!)" : "") . "\n"; |
michael@428 | 58 | exit(1); |
michael@428 | 59 | }; |
michael@428 | 60 | |
michael@428 | 61 | # command line parsing |
michael@428 | 62 | Getopt::Long::Configure("bundling"); |
michael@428 | 63 | my $result = GetOptions( |
michael@428 | 64 | 'V|version' => \$version, |
michael@428 | 65 | 'v|verbose' => \$verbose, |
michael@428 | 66 | 'h|help' => \$help, |
michael@428 | 67 | 'c|check=s' => \$check, |
michael@428 | 68 | 't|tmpdir=s' => \$tmpdir, |
michael@428 | 69 | 'r|rpm=s' => \$rpm, |
michael@428 | 70 | ) || die "option parsing failed"; |
michael@428 | 71 | if ($help) { |
michael@428 | 72 | print "Usage: $progname [options] [RPMFILE ...]\n" . |
michael@428 | 73 | "Available options:\n" . |
michael@428 | 74 | " -v,--verbose enable verbose run-time mode\n" . |
michael@428 | 75 | " -h,--help print out this usage page\n" . |
michael@428 | 76 | " -c,--check=CHECKS select checks to perform (default='all')\n" . |
michael@428 | 77 | " -r,--rpm=FILE filesystem path to RPM program\n" . |
michael@428 | 78 | " -t,--tmpdir=PATH filesystem path to temporary directory\n" . |
michael@428 | 79 | " -V,--version print program version\n"; |
michael@428 | 80 | exit(0); |
michael@428 | 81 | } |
michael@428 | 82 | if ($version) { |
michael@428 | 83 | print "OpenPKG $progname $progvers\n"; |
michael@428 | 84 | exit(0); |
michael@428 | 85 | } |
michael@428 | 86 | |
michael@428 | 87 | # verbose message printing |
michael@428 | 88 | sub msg_verbose { |
michael@428 | 89 | my ($msg) = @_; |
michael@428 | 90 | print STDERR "$msg\n" if ($verbose); |
michael@428 | 91 | } |
michael@428 | 92 | |
michael@428 | 93 | # warning message printing |
michael@428 | 94 | sub msg_warning { |
michael@428 | 95 | my ($msg) = @_; |
michael@428 | 96 | print STDERR "$progname:WARNING: $msg\n"; |
michael@428 | 97 | } |
michael@428 | 98 | |
michael@428 | 99 | # error message printing |
michael@428 | 100 | sub msg_error { |
michael@428 | 101 | my ($msg) = @_; |
michael@428 | 102 | print STDERR "$progname:ERROR: $msg\n"; |
michael@428 | 103 | } |
michael@428 | 104 | |
michael@428 | 105 | # determine check list |
michael@428 | 106 | my @check_list = (qw( |
michael@428 | 107 | layout |
michael@428 | 108 | attrib |
michael@428 | 109 | content |
michael@428 | 110 | )); |
michael@428 | 111 | my @checks = (); |
michael@428 | 112 | if ($check eq 'all') { |
michael@428 | 113 | @checks = @check_list; |
michael@428 | 114 | } |
michael@428 | 115 | else { |
michael@428 | 116 | foreach my $c (split(/,/, $check)) { |
michael@428 | 117 | if (not grep(/^$c$/, @check_list)) { |
michael@428 | 118 | die "invalid check \"$c\""; |
michael@428 | 119 | } |
michael@428 | 120 | push(@checks, $c); |
michael@428 | 121 | } |
michael@428 | 122 | } |
michael@428 | 123 | |
michael@428 | 124 | # global return code |
michael@428 | 125 | $main::GRC = 0; |
michael@428 | 126 | |
michael@428 | 127 | # environment preparation |
michael@428 | 128 | system("rm -rf $tmpdir"); |
michael@428 | 129 | system("mkdir -p $tmpdir"); |
michael@428 | 130 | |
michael@428 | 131 | # iterate over all .rpm files |
michael@428 | 132 | foreach my $filename (@ARGV) { |
michael@428 | 133 | die "unable to open file \"$filename\" for reading" |
michael@428 | 134 | if (not -f $filename); |
michael@428 | 135 | my $info = &rpm_info($filename, \@checks); |
michael@428 | 136 | foreach my $check (@checks) { |
michael@428 | 137 | eval "\&check_$check(\$filename, \$info);"; |
michael@428 | 138 | } |
michael@428 | 139 | &rpm_info_cleanup($filename, \@checks, $info); |
michael@428 | 140 | } |
michael@428 | 141 | |
michael@428 | 142 | # environment cleanup |
michael@428 | 143 | system("rm -rf $tmpdir"); |
michael@428 | 144 | |
michael@428 | 145 | # die gracefully |
michael@428 | 146 | exit($main::GRC); |
michael@428 | 147 | |
michael@428 | 148 | ## _________________________________________________________________ |
michael@428 | 149 | ## |
michael@428 | 150 | ## COMMON SUBROUTINES |
michael@428 | 151 | ## _________________________________________________________________ |
michael@428 | 152 | ## |
michael@428 | 153 | |
michael@428 | 154 | sub lint_message { |
michael@428 | 155 | my ($type, $file, $msg) = @_; |
michael@428 | 156 | $file =~ s|^.+?/([^/]+)$|$1|s; |
michael@428 | 157 | printf(STDERR "%s:%s: %s: %s\n", $progname, $type, $file, $msg); |
michael@428 | 158 | } |
michael@428 | 159 | |
michael@428 | 160 | sub lint_warning { |
michael@428 | 161 | my ($file, $msg) = @_; |
michael@428 | 162 | &lint_message("WARNING", $file, $msg); |
michael@428 | 163 | $main::GRC = 1 if ($main::GRC < 1); |
michael@428 | 164 | } |
michael@428 | 165 | |
michael@428 | 166 | sub lint_error { |
michael@428 | 167 | my ($file, $msg) = @_; |
michael@428 | 168 | &lint_message("ERROR", $file, $msg); |
michael@428 | 169 | $main::GRC = 2 if ($main::GRC < 2); |
michael@428 | 170 | } |
michael@428 | 171 | |
michael@428 | 172 | ## _________________________________________________________________ |
michael@428 | 173 | ## |
michael@428 | 174 | ## RPM INFORMATION GATHERING |
michael@428 | 175 | ## _________________________________________________________________ |
michael@428 | 176 | ## |
michael@428 | 177 | |
michael@428 | 178 | sub rpm_info { |
michael@428 | 179 | my ($filename, $checks) = @_; |
michael@428 | 180 | my $info = {}; |
michael@428 | 181 | |
michael@428 | 182 | # query package name |
michael@428 | 183 | &msg_verbose("++ querying RPM package name"); |
michael@428 | 184 | $info->{name} = `$rpm -qp --qf '%{NAME}' $filename`; |
michael@428 | 185 | |
michael@428 | 186 | # query prefix |
michael@428 | 187 | &msg_verbose("++ querying RPM package installation prefix"); |
michael@428 | 188 | $info->{prefix} = `$rpm -qp --qf '%{PREFIXES}' $filename`; |
michael@428 | 189 | |
michael@428 | 190 | # query file listing |
michael@428 | 191 | &msg_verbose("++ querying RPM package file listing"); |
michael@428 | 192 | my @list = `$rpm -qplv $filename`; |
michael@428 | 193 | my @config = `$rpm -qplc $filename`; |
michael@428 | 194 | |
michael@428 | 195 | # process file listing |
michael@428 | 196 | $info->{ls} = {}; |
michael@428 | 197 | foreach my $entry (@list) { |
michael@428 | 198 | if ($entry =~ m|^\(contains no files\)\s*$|s) { |
michael@428 | 199 | next; |
michael@428 | 200 | } |
michael@428 | 201 | elsif ($entry =~ m|^(\S+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(.{12})\s+(.+)\s*$|s) { |
michael@428 | 202 | my ($perm, $links, $owner, $group, $size, $mtime, $path) = ($1, $2, $3, $4, $5, $6, $7); |
michael@428 | 203 | my $symlink = ""; |
michael@428 | 204 | if ($path =~ m|^(\S+)\s+->\s+(\S+)$|) { |
michael@428 | 205 | ($path, $symlink) = ($1, $2); |
michael@428 | 206 | } |
michael@428 | 207 | $path =~ s|\s+$||s; |
michael@428 | 208 | my $config = 0; |
michael@428 | 209 | if (grep(m|^$path$|, @config)) { |
michael@428 | 210 | $config = 1; |
michael@428 | 211 | } |
michael@428 | 212 | $info->{ls}->{$path} = { |
michael@428 | 213 | 'perm' => $perm, |
michael@428 | 214 | 'links' => $links, |
michael@428 | 215 | 'owner' => $owner, |
michael@428 | 216 | 'group' => $group, |
michael@428 | 217 | 'size' => $size, |
michael@428 | 218 | 'time' => $mtime, |
michael@428 | 219 | 'path' => $path, |
michael@428 | 220 | 'symlink' => $symlink, |
michael@428 | 221 | 'config' => $config, |
michael@428 | 222 | }; |
michael@428 | 223 | } |
michael@428 | 224 | else { |
michael@428 | 225 | &lint_error($filename, "invalid file listing entry: \"$entry\""); |
michael@428 | 226 | } |
michael@428 | 227 | } |
michael@428 | 228 | |
michael@428 | 229 | # unpacking files |
michael@428 | 230 | if (grep(/^content$/, @{$checks})) { |
michael@428 | 231 | &msg_verbose("++ unpacking RPM package files"); |
michael@428 | 232 | $info->{root} = "$tmpdir/root"; |
michael@428 | 233 | system("mkdir -p ".$info->{root}); |
michael@428 | 234 | system("$rpm2cpio $filename | (cd ".$info->{root}." && cpio -idmu 2>/dev/null)"); |
michael@428 | 235 | } |
michael@428 | 236 | |
michael@428 | 237 | return $info; |
michael@428 | 238 | } |
michael@428 | 239 | |
michael@428 | 240 | sub rpm_info_cleanup { |
michael@428 | 241 | my ($filename, $checks, $info) = @_; |
michael@428 | 242 | |
michael@428 | 243 | if (grep(/^content$/, @{$checks})) { |
michael@428 | 244 | system("rm -rf ".$info->{root}) if ($info->{root} =~ m/^\/.+/ and -d $info->{root}); |
michael@428 | 245 | } |
michael@428 | 246 | } |
michael@428 | 247 | |
michael@428 | 248 | ## _________________________________________________________________ |
michael@428 | 249 | ## |
michael@428 | 250 | ## CHECK "layout": file path layout |
michael@428 | 251 | ## _________________________________________________________________ |
michael@428 | 252 | ## |
michael@428 | 253 | |
michael@428 | 254 | sub check_layout { |
michael@428 | 255 | my ($rpm, $info) = @_; |
michael@428 | 256 | |
michael@428 | 257 | # no need to check 'openpkg' package because it |
michael@428 | 258 | # has a hard-coded file list! |
michael@428 | 259 | return if ($rpm =~ m|^(.+?/)?openpkg-\d[^/]+$|); |
michael@428 | 260 | |
michael@428 | 261 | # check prefix |
michael@428 | 262 | if ($info->{prefix} !~ m|^/.+$|) { |
michael@428 | 263 | &lint_error($rpm, "invalid installation prefix ".$info->{prefix}. |
michael@428 | 264 | " (expected to match \"^/.+\$\")"); |
michael@428 | 265 | return; |
michael@428 | 266 | } |
michael@428 | 267 | |
michael@428 | 268 | # check top-level path (all-in-one) |
michael@428 | 269 | my @topdirs = (qw( |
michael@428 | 270 | bin cgi etc include info lib libexec |
michael@428 | 271 | local man pub sbin share usr var |
michael@428 | 272 | )); |
michael@428 | 273 | my $topdirs = "{".join(",", @topdirs)."}"; |
michael@428 | 274 | if (not keys(%{$info->{ls}})) { |
michael@428 | 275 | &lint_error($rpm, "invalid empty package (expected at least one file)"); |
michael@428 | 276 | return; |
michael@428 | 277 | } |
michael@428 | 278 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 279 | my $ok = 0; |
michael@428 | 280 | foreach my $topdir (@topdirs) { |
michael@428 | 281 | my $prefix = quotemeta($info->{prefix} . "/" . $topdir); |
michael@428 | 282 | if ($path =~ m/^$prefix$/ && $rpm !~ m|^openpkg-\d+|) { |
michael@428 | 283 | &lint_error($rpm, "top-level directory \"$topdir\" provided" . |
michael@428 | 284 | " (expected none except for 'openpkg' package)"); |
michael@428 | 285 | } |
michael@428 | 286 | if ($path =~ m/^$prefix/) { |
michael@428 | 287 | $ok = 1; |
michael@428 | 288 | last; |
michael@428 | 289 | } |
michael@428 | 290 | } |
michael@428 | 291 | if (not $ok) { |
michael@428 | 292 | &lint_error($rpm, "invalid top-level directory in path \"$path\"". |
michael@428 | 293 | " (expected one of $topdirs)"); |
michael@428 | 294 | } |
michael@428 | 295 | } |
michael@428 | 296 | |
michael@428 | 297 | # check for second-level path (all-in-one) |
michael@428 | 298 | my @topdirs_subdir_no = (qw(bin cgi info sbin)); |
michael@428 | 299 | my @topdirs_subdir_yes = (qw(etc libexec share var)); |
michael@428 | 300 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 301 | foreach my $topdir (@topdirs_subdir_yes) { |
michael@428 | 302 | my $prefix = quotemeta($info->{prefix} . "/" . $topdir); |
michael@428 | 303 | if ($path =~ m/^$prefix\/[^\/]+$/) { |
michael@428 | 304 | if ($info->{ls}->{$path}->{perm} !~ m|^d|) { |
michael@428 | 305 | &lint_error($rpm, "invalid positioned file \"$path\" under topdir \"$topdir\" (expected directory)"); |
michael@428 | 306 | } |
michael@428 | 307 | } |
michael@428 | 308 | } |
michael@428 | 309 | foreach my $topdir (@topdirs_subdir_no) { |
michael@428 | 310 | my $prefix = quotemeta($info->{prefix} . "/" . $topdir); |
michael@428 | 311 | if ($path =~ m/^$prefix\/[^\/]+$/) { |
michael@428 | 312 | if ($info->{ls}->{$path}->{perm} =~ m|^d|) { |
michael@428 | 313 | &lint_error($rpm, "invalid positioned directory \"$path\" under topdir \"$topdir\" (expected file)"); |
michael@428 | 314 | } |
michael@428 | 315 | } |
michael@428 | 316 | } |
michael@428 | 317 | } |
michael@428 | 318 | |
michael@428 | 319 | # check "bin" and "sbin" directories |
michael@428 | 320 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 321 | foreach my $topdir (qw(bin sbin)) { |
michael@428 | 322 | my $prefix = quotemeta($info->{prefix} . "/" . $topdir); |
michael@428 | 323 | if ($path =~ m/^$prefix\/(.+)$/) { |
michael@428 | 324 | my $file = $1; |
michael@428 | 325 | if ($file =~ m|^[^/]+\.[^/.]+$|) { |
michael@428 | 326 | &lint_warning($rpm, "strange executable filename \"$path\" containing an extension (expected no extension)"); |
michael@428 | 327 | } |
michael@428 | 328 | my $perm = $info->{ls}->{$path}->{'perm'}; |
michael@428 | 329 | if ($perm =~ m|^-| && $perm !~ m|^-[-r][-w][sx][-r][-w][-sx][-r][-w][-tx]$|) { |
michael@428 | 330 | &lint_error($rpm, "non-executable file \"$path\" (with permissions \"$perm\" under topdir \"$topdir\" (expected to be executable)"); |
michael@428 | 331 | } |
michael@428 | 332 | } |
michael@428 | 333 | } |
michael@428 | 334 | } |
michael@428 | 335 | |
michael@428 | 336 | # check for symbolic link targets (outside absolute, dangling) |
michael@428 | 337 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 338 | my $symlink = $info->{ls}->{$path}->{'symlink'}; |
michael@428 | 339 | if ($symlink ne '') { |
michael@428 | 340 | # check for outside absolute target |
michael@428 | 341 | my $prefix = quotemeta($info->{prefix}); |
michael@428 | 342 | if ($symlink =~ m|^/.*| and $symlink !~ m|^$prefix|s) { |
michael@428 | 343 | &lint_warning($rpm, "symbolic link \"$path\" points to absolute path \"$symlink\" outside prefix \"$info->{prefix}\" (expected it to be under prefix only)"); |
michael@428 | 344 | } |
michael@428 | 345 | # check for dangling target |
michael@428 | 346 | my $resolved = &resolve($info, $path); |
michael@428 | 347 | sub resolve { |
michael@428 | 348 | my ($info, $path) = @_; |
michael@428 | 349 | if (not defined($info->{ls}->{$path})) { |
michael@428 | 350 | return $path; |
michael@428 | 351 | } |
michael@428 | 352 | my $symlink = $info->{ls}->{$path}->{'symlink'}; |
michael@428 | 353 | if ($symlink eq '') { |
michael@428 | 354 | return $path; |
michael@428 | 355 | } |
michael@428 | 356 | else { |
michael@428 | 357 | my $resolved; |
michael@428 | 358 | if ($symlink =~ m|^/|) { |
michael@428 | 359 | $resolved = $symlink; |
michael@428 | 360 | } |
michael@428 | 361 | else { |
michael@428 | 362 | $resolved = $path; |
michael@428 | 363 | $resolved =~ s|/[^/]+$||s; |
michael@428 | 364 | $resolved .= "/" . $symlink; |
michael@428 | 365 | $resolved =~ s|/{2,}|/|sg; |
michael@428 | 366 | $resolved =~ s|/\.(?=/)||sg; |
michael@428 | 367 | $resolved =~ s|/\.$||sg; |
michael@428 | 368 | 1 while ($resolved =~ s|/[^/]+/\.\./|/|s); |
michael@428 | 369 | $resolved =~ s|/[^/]+/\.\.$||s; |
michael@428 | 370 | $resolved =~ s|(.)/$|$1|s; |
michael@428 | 371 | } |
michael@428 | 372 | return &resolve($info, $resolved); |
michael@428 | 373 | } |
michael@428 | 374 | } |
michael@428 | 375 | if (not defined($info->{ls}->{$resolved})) { |
michael@428 | 376 | &lint_error($rpm, "symbolic link \"$path\" points to not existing target path \"$resolved\" (expected existing target path)"); |
michael@428 | 377 | } |
michael@428 | 378 | } |
michael@428 | 379 | } |
michael@428 | 380 | } |
michael@428 | 381 | |
michael@428 | 382 | ## _________________________________________________________________ |
michael@428 | 383 | ## |
michael@428 | 384 | ## CHECK "attrib": file attributes |
michael@428 | 385 | ## _________________________________________________________________ |
michael@428 | 386 | ## |
michael@428 | 387 | |
michael@428 | 388 | sub check_attrib { |
michael@428 | 389 | my ($rpm, $info) = @_; |
michael@428 | 390 | |
michael@428 | 391 | # check for empty files |
michael@428 | 392 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 393 | if ( $info->{ls}->{$path}->{'size'} == 0 |
michael@428 | 394 | and $info->{ls}->{$path}->{'perm'} !~ m|^d| |
michael@428 | 395 | and $path !~ m/^.*\/lib\/perl\/.+\.bs$/ |
michael@428 | 396 | and $rpm !~ m/\bopenpkg-[0-9]+/) { |
michael@428 | 397 | &lint_warning($rpm, "empty file \"$path\" found (expected no empty files)"); |
michael@428 | 398 | } |
michael@428 | 399 | } |
michael@428 | 400 | |
michael@428 | 401 | # check for %config flagged files |
michael@428 | 402 | my $prefix = quotemeta($info->{'prefix'}); |
michael@428 | 403 | my $name = quotemeta($info->{'name'}); |
michael@428 | 404 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 405 | my $config = $info->{ls}->{$path}->{'config'}; |
michael@428 | 406 | my $path = $info->{ls}->{$path}->{'path'}; |
michael@428 | 407 | if ($rpm !~ m/\bopenpkg-[0-9]+/ and $config and $path !~ m/^$prefix\/etc\/($name\d*|fsl)\/.+/) { |
michael@428 | 408 | &lint_warning($rpm, "non-config file \"$path\" flagged as \%config (expected only \"$prefix/etc/$name/*\" files to be \%config files)"); |
michael@428 | 409 | } |
michael@428 | 410 | if ($config and $path =~ m/^$prefix\/s?bin\/[^\/]+$/) { |
michael@428 | 411 | &lint_error($rpm, "executable file \"$path\" flagged as \%config"); |
michael@428 | 412 | } |
michael@428 | 413 | if ($config and $path =~ m/^$prefix\/etc\/rc\.d\/rc\.$name$/) { |
michael@428 | 414 | &lint_error($rpm, "run-command file \"$path\" flagged as \%config"); |
michael@428 | 415 | } |
michael@428 | 416 | } |
michael@428 | 417 | |
michael@428 | 418 | # check for permissions |
michael@428 | 419 | foreach my $path (keys(%{$info->{ls}})) { |
michael@428 | 420 | my $perm = $info->{ls}->{$path}->{'perm'}; |
michael@428 | 421 | if ($path =~ m/^$prefix\/(bin|sbin)\/[^\/]+$/) { |
michael@428 | 422 | if ($perm !~ m|^[^d]..[xs]..[xs]..[xt]$|) { |
michael@428 | 423 | &lint_warning($rpm, "executable file \"$path\" has permissions \"$perm\" only (expected it to be executable by everyone)"); |
michael@428 | 424 | } |
michael@428 | 425 | } |
michael@428 | 426 | } |
michael@428 | 427 | |
michael@428 | 428 | # TODO: user/group? |
michael@428 | 429 | } |
michael@428 | 430 | |
michael@428 | 431 | ## _________________________________________________________________ |
michael@428 | 432 | ## |
michael@428 | 433 | ## CHECK "content": file content |
michael@428 | 434 | ## _________________________________________________________________ |
michael@428 | 435 | ## |
michael@428 | 436 | |
michael@428 | 437 | sub check_content { |
michael@428 | 438 | my ($rpm, $info) = @_; |
michael@428 | 439 | |
michael@428 | 440 | # TODO: stripped (file) |
michael@428 | 441 | # TODO: syslibs (ldd) |
michael@428 | 442 | # TODO: hard-coded paths pointing outside instance |
michael@428 | 443 | # TODO: sanity check for shebang-lines |
michael@428 | 444 | # TODO: contained temporary path |
michael@428 | 445 | # TODO: bad-files: .po |
michael@428 | 446 | } |
michael@428 | 447 |