openpkg/lint-fsl.pl

Thu, 04 Oct 2012 20:30:05 +0200

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 04 Oct 2012 20:30:05 +0200
changeset 715
c10fb90893b9
permissions
-rw-r--r--

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.

     1 ##
     2 ##  lint-fsl.pl -- OpenPKG fsl.* File Checker
     3 ##  Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/>
     4 ##
     5 ##  This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
     6 ##  All rights reserved. Licenses which grant limited permission to use,
     7 ##  copy, modify and distribute this software are available from the
     8 ##  OpenPKG GmbH.
     9 ##
    10 ##  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
    11 ##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    12 ##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    13 ##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
    14 ##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    15 ##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    16 ##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    17 ##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    18 ##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    19 ##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    20 ##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    21 ##  SUCH DAMAGE.
    22 ##
    24 #   Perl run-time requirement
    25 require 5;
    26 BEGIN {
    27     eval "use Getopt::Long; use IO;";
    28     if ($@) {
    29         print STDERR
    30             "lint-fsl: ERROR: This command requires a full-size Perl installation!\n" .
    31             "lint-fsl: HINT:  Install OpenPKG \"perl\" package to use this command.\n";
    32         exit(1);
    33     }
    34 }
    36 #   OpenPKG instance prefix
    37 my $my_prefix = $ENV{'OPENPKG_PREFIX'};
    38 delete $ENV{'OPENPKG_PREFIX'};
    40 #   program information
    41 my $progname = "lint-fsl";
    42 my $progvers = "1.0.0";
    44 #   parameters (defaults)
    45 my $version  = 0;
    46 my $verbose  = 0;
    47 my $help     = 0;
    48 my $check    = 'all';
    49 my $tmpdir   = ($ENV{TMPDIR} || $ENV{TEMPDIR} || "/tmp") . "/$progname";
    50 my $rpm      = "$my_prefix/bin/openpkg rpm";
    52 #   exception handling support
    53 $SIG{__DIE__} = sub {
    54     my ($err) = @_;
    55     $err =~ s|\s+at\s+.*||s if (not $verbose);
    56     print STDERR "$progname:ERROR: $err ". ($! ? "($!)" : "") . "\n";
    57     exit(1);
    58 };
    60 #   command line parsing
    61 Getopt::Long::Configure("bundling");
    62 my $result = GetOptions(
    63     'V|version'     => \$version,
    64     'v|verbose'     => \$verbose,
    65     'h|help'        => \$help,
    66     'c|check=s'     => \$check,
    67     't|tmpdir=s'    => \$tmpdir,
    68     'r|rpm=s'       => \$rpm,
    69 ) || die "option parsing failed";
    70 if ($help) {
    71     print "Usage: $progname [options] [RPMFILE ...]\n" .
    72           "Available options:\n" .
    73           " -v,--verbose       enable verbose run-time mode\n" .
    74           " -h,--help          print out this usage page\n" .
    75           " -c,--check=CHECKS  select checks to perform (default='all')\n" .
    76           " -r,--rpm=FILE      filesystem path to RPM program\n" .
    77           " -t,--tmpdir=PATH   filesystem path to temporary directory\n" .
    78           " -V,--version       print program version\n";
    79     exit(0);
    80 }
    81 if ($version) {
    82     print "OpenPKG $progname $progvers\n";
    83     exit(0);
    84 }
    86 #   verbose message printing
    87 sub msg_verbose {
    88     my ($msg) = @_;
    89     print STDERR "$msg\n" if ($verbose);
    90 }
    92 #   warning message printing
    93 sub msg_warning {
    94     my ($msg) = @_;
    95     print STDERR "$progname:WARNING: $msg\n";
    96 }
    98 #   error message printing
    99 sub msg_error {
   100     my ($msg) = @_;
   101     print STDERR "$progname:ERROR: $msg\n";
   102 }
   104 #   determine check list
   105 my @check_list = (qw(
   106     blank
   107     comment
   108     ident
   109 ));
   110 my @checks = ();
   111 if ($check eq 'all') {
   112     @checks = @check_list;
   113 }
   114 else {
   115     foreach my $c (split(/,/, $check)) {
   116         if (not grep(/^$c$/, @check_list)) {
   117             die "invalid check \"$c\"";
   118         }
   119         push(@checks, $c);
   120     }
   121 }
   123 #   global return code
   124 $main::GRC = 0;
   126 #   environment preparation
   127 system("rm -rf $tmpdir");
   128 system("mkdir -p $tmpdir");
   130 #   iterate over all fsl. files
   131 foreach my $filename (@ARGV) {
   132     my $io = new IO::File "<$filename"
   133         or die "unable to open file \"$filename\" for reading";
   134     my $spec; { local $/ = undef; $spec = <$io>; }
   135     $io->close;
   136     foreach my $check (@checks) {
   137         eval "\&check_$check(\$filename, \$spec);";
   138     }
   139 }
   141 #   environment cleanup
   142 system("rm -rf $tmpdir");
   144 #   die gracefully
   145 exit($main::GRC);
   147 ##  _________________________________________________________________
   148 ##
   149 ##  COMMON SUBROUTINES
   150 ##  _________________________________________________________________
   151 ##
   153 sub lines {
   154     my ($txt) = @_;
   155     my $l = 0;
   156     $txt =~ s|\n|$l++, ''|sge;
   157     return $l;
   158 }
   160 sub lint_message {
   161     my ($type, $file, $done, $this, $msg) = @_;
   162     if (defined($done) and defined($this)) {
   163         my $start = &lines($done) + 1;
   164         my $end = $start + &lines($this);
   165         my $pos = $start;
   166         $pos .= "-". $end if ($end > $start);
   167         printf("%s:%s: %s:%s: %s\n", $progname, $type, $file, $pos, $msg);
   168     }
   169     else {
   170         printf("%s:%s: %s: %s\n", $progname, $type, $file, $msg);
   171     }
   172 }
   174 sub lint_warning {
   175     my ($file, $done, $this, $msg) = @_;
   176     &lint_message("WARNING", $file, $done, $this, $msg);
   177     $main::GRC = 1 if ($main::GRC < 1);
   178 }
   180 sub lint_error {
   181     my ($file, $done, $this, $msg) = @_;
   182     &lint_message("ERROR", $file, $done, $this, $msg);
   183     $main::GRC = 2 if ($main::GRC < 2);
   184 }
   186 ##  _________________________________________________________________
   187 ##
   188 ##  CHECK "blank": whitespace and blank lines
   189 ##  _________________________________________________________________
   190 ##
   192 sub check_blank {
   193     my ($file, $spec) = @_;
   195     #   check for CR-LF combination
   196     my $done = ''; my $this = ''; my $todo = $spec;
   197     while ($todo =~ m/\r\n/s) {
   198         $done .= $`; $this = $&; $todo = $';
   199         &lint_warning($file, $done, $this, "carriage-return (CR, 0x0d) line-feed (NL, 0x0a) combination (expected just line-feed)");
   200         $done .= $this;
   201     }
   203     #   check for multiple blank lines
   204     $done = ''; $this = ''; $todo = $spec;
   205     while ($todo =~ m/(\r?\n[ \t]*){3,}/s) {
   206         $done .= $`; $this = $&; $todo = $';
   207         &lint_warning($file, $done, $this, "multiple subsequent blank lines (expected single blank line)");
   208         $done .= $this;
   209     }
   211     #   check for trailing whitespaces
   212     $done = ''; $this = ''; $todo = $spec;
   213     while ($todo =~ m/[ \t]+\r?\n/s) {
   214         $done .= $`; $this = $&; $todo = $';
   215         if ($done eq '' or $done =~ m|\n$|s) {
   216             &lint_warning($file, $done, $this, "whitespace on empty line (expected none)");
   217         }
   218         else {
   219             &lint_warning($file, $done, $this, "trailing whitespace (expected none)");
   220         }
   221         $done .= $this;
   222     }
   224     #   check for bogus line continuations
   225     $done = ''; $this = ''; $todo = $spec;
   226     while ($todo =~ m/\\[ \t]*\r?\n(?=[ \t]*\r?\n)/s) {
   227         $done .= $`; $this = $&; $todo = $';
   228         &lint_warning($file, $done, $this, "bogus line continuation for following empty line (expect no line continuation)");
   229         $done .= $this;
   230     }
   232     #   check for leading whitespaces before line continuations
   233     $done = ''; $this = ''; $todo = $spec;
   234     while ($todo =~ m/[ \t]{2,}\\[ \t]*\r?\n/s) {
   235         $done .= $`; $this = $&; $todo = $';
   236         &lint_warning($file, $done, $this, "multiple leading whitespace before line continuation (expected just a single space)");
   237         $done .= $this;
   238     }
   240     #   check for leading tabs
   241     $done = ''; $this = ''; $todo = $spec;
   242     while ($todo =~ m/^ *\t+ *[^ \t]/m) {
   243         $done .= $`; $this = $&; $todo = $';
   244         &lint_warning($file, $done, $this, "leading tabs (expected spaces)");
   245         $done .= $this;
   246     }
   248     #   check for mandatory/wished trailing blank line
   249     if ($spec !~ m|\n\n$|) {
   250         &lint_warning($file, $done, "", "mandatory/wished trailing blank line missing (expected one)");
   251     }
   252 }
   254 ##  _________________________________________________________________
   255 ##
   256 ##  CHECK "comment": sharp-comments
   257 ##  _________________________________________________________________
   258 ##
   260 sub check_comment {
   261     my ($file, $spec) = @_;
   262     my ($pkg);
   264     #   determine package name
   265     $pkg = $file;
   266     $pkg =~ s|^.+/||;
   267     $pkg =~ s|^fsl\.||;
   269     #   check comment header
   270     my $re = "";
   271     $re .= "##\\n##  fsl.$pkg -- OSSP fsl configuration\\n##\\n\\n";
   272     if ($spec !~ m|^$re|os) {
   273         &lint_warning($file, "", "", "invalid comment header (expected $re)");
   274     }
   276     #   check for comment indentation
   277     my $done .= $`; my $this = $&; my $todo = $';
   278     while ($todo =~ m/^([ \t]*)(#+)([ \t]*)(.*?)$/m) {
   279         $done .= $`; $this = $&; $todo = $';
   280         my ($lead, $sharp, $pad, $text) = ($1, $2, $3, $4);
   281         if (length($lead) % 2 != 0) {
   282             &lint_warning($file, $done, $this, "incorrect comment indentation (expected a multiple of 2 spaces)");
   283         }
   284         if (length($lead) > 1 && length($sharp) > 1) {
   285             &lint_warning($file, $done, $this, "indented comment has introduced with multiple sharps (expected single sharp character)");
   286         }
   287         if (length($pad.$text) > 0 && length($sharp.$pad) % 4 != 0) {
   288             &lint_warning($file, $done, $this, "incorrect comment text padding (expected a multiple of 4 sharps or spaces)");
   289         }
   290         if (length($pad) == 0 && length($text) > 0) {
   291             &lint_warning($file, $done, $this, "missing leading space before comment text (expected padding spaces)");
   292         }
   293         if (length($pad) > 0 && length($text) == 0) {
   294             &lint_warning($file, $done, $this, "empty comment text (expected a reasonable text)");
   295         }
   296         $done .= $this;
   297     }
   298 }
   300 ##  _________________________________________________________________
   301 ##
   302 ##  CHECK "ident"
   303 ##  _________________________________________________________________
   304 ##
   306 sub check_ident {
   307     my ($file, $spec) = @_;
   308     my ($pkg, $section);
   310     #   determine package name
   311     $pkg = $file;
   312     $pkg =~ s|^.+/||;
   313     $pkg =~ s|^fsl\.||;
   315     #   check sections with ident/facility regex
   316     my $done .= ""; my $this = ""; my $todo = $spec;
   317     while ($todo =~ m:\n(\w+)(\s+)(\S+)/(\S+)(\s+)q\{(.*?)\};:s) {
   318         $done .= $`; $this = $&; $todo = $';
   319         my ($section, $ws1, $ident, $facility, $ws2, $body) = ($1, $2, $3, $4, $5, $6);
   321         if ($pkg eq "fsl") {
   322             #   enforce default section for fsl
   323             if ($section ne "default") {
   324                 &lint_warning($file, "", "", "section \"$section\" not allowed for package $pkg (expected default)");
   325             }
   326         }
   327         else {
   328             #   enforce ident section for any package othen than fsl
   329             if ($section ne "ident") {
   330                 &lint_warning($file, "", "", "section \"$section\" not allowed for package $pkg (expected ident)");
   331             }
   333             #   ident and facility wildcard-only would be a catch-all
   334             if ($ident =~ m/^[(]?\.[\+\*][)]?$/ and $facility =~ m/^[(]?\.[\+\*][)]?$/) {
   335                 &lint_warning($file, "", "", "wildcard not allowed for both ident and facility (found $ident/$facility");
   336             }
   337         }
   339         #   enforce a single space
   340         if (length($ws1) != 1) {
   341             &lint_warning($file, "", "", "whitespace count wrong between section ($section) and ident ($ident)");
   342         }
   344         #   enforce a single space
   345         if (length($ws2) != 1) {
   346             &lint_warning($file, "", "", "whitespace count wrong between facility ($facility) and end of line");
   347         }
   349         #   ident same as facility is likely to be a typo
   350         if ($ident eq $facility) {
   351             &lint_warning($file, "", "", "unusual constellation ident equal to facility (found $ident/$facility");
   352         }
   354         #   FIXME MTAs hardcoded here for /mail
   355         if ($facility eq "mail" and $pkg !~ m/^(sendmail|ssmtp|postfix|exim)$/) {
   356             &lint_warning($file, "", "", "only MTAs may match facility mail");
   357         }
   359         #   FIXME inn hardcoded here for /news
   360         if ($facility eq "news" and $pkg !~ m/^(inn)$/) {
   361             &lint_warning($file, "", "", "only inn may match facility news");
   362         }
   364         #   check prefix channel
   365         if ($body =~ m/\n([ ]*)prefix(\s*?)\((.*?)\)/s) {
   366             my ($ws1, $ws2, $options) = ($1, $2, $3);
   368             #   enforce eight spaces
   369             if (length($ws1) != 4) {
   370                 &lint_warning($file, "", "", "prefix channel whitespace count at start of line");
   371             }
   373             #   enforce zero spaces
   374             if (length($ws2) != 0) {
   375                 &lint_warning($file, "", "", "whitespace not allowed between prefix channel and round open bracket");
   376             }
   378             #   enforce prefix options in prefix channel
   379             if ($options !~ m/\sprefix="%b %d %H:%M:%S %N (<%L> )?\$1(\[%P\])?: "/) {
   380                 &lint_warning($file, "", "", "prefix option in prefix channel invalid or missing");
   381             }
   382             $options = $';
   383             $options =~ s/,//;
   385             #   detect superflous options in prefix channel
   386             if ($options =~ m/\S+/s) {
   387                 $options =~ s/\n/\\n/;
   388                 &lint_warning($file, "", "", "superflous option in prefix channel unseparated line detected: $options");
   389             }
   390         }
   391         else {
   392             &lint_warning($file, "", "", "prefix channel missing");
   393         }
   395         #   check path branch
   396         if ($body !~ m/\n([ ]*)->(\s*?)\{(.*)\}\n/s) {
   397             &lint_warning($file, "", "", "no path branch found");
   398             return;
   399         }
   400         my ($ws1, $ws2, $body) = ($1, $2, $3); #FIXME check ws1/ws2
   402         #   check path channel
   403         while ($body =~ m/\n([ ]*)(\w+):(\s+?)file(\s*?)\((.*?)\);/s) {
   404             my ($ws1, $level, $ws2, $ws3, $options) = ($1, $2, $3, $4, $5);
   405             $body = $';
   407             #   enforce eight spaces
   408             if (length($ws1) != 8) {
   409                 &lint_warning($file, "", "", "path channel whitespace count at start of line");
   410             }
   412             #   enforce spaces
   413             if (length($ws2) < 1) {
   414                 &lint_warning($file, "", "", "whitespace required between level and file");
   415             }
   417             #   enforce zero spaces
   418             if (length($ws3) != 0) {
   419                 &lint_warning($file, "", "", "path channel whitespace not allowed between file channel and round open bracket");
   420             }
   422             #   check for legal l2 level
   423             if ($level !~ m/^(panic|critical|error|warning|notice|info|trace|debug)$/) {
   424                 &lint_warning($file, "", "", "illegal l2 level $level detected");
   425             }
   427             #   enforce file option in file channel
   428             if ($options !~ m;path="\@l_prefix\@/var/$pkg/(log\S+|$pkg\.log)";) {
   429                 &lint_warning($file, "", "", "path option in file channel invalid or missing");
   430             }
   431             $options = $';
   432             $options =~ s/,//;
   434             #   enforce perm option in file channel
   435             if ($options !~ m;perm=0[0-7]{3};) {
   436                 &lint_warning($file, "", "", "perm option in file channel invalid or missing");
   437             }
   438             $options = $';
   439             $options =~ s/,//;
   441             #   detect superflous options in file channel
   442             if ($options =~ m/\S+/s) {
   443                 $options =~ s/\n/\\n/;
   444                 &lint_warning($file, "", "", "superflous option in prefix channel detected: $options");
   445             }
   446         }
   448         #   check path channel
   449         if ($body =~ m/\n([ ]*)(\w+):(\s*?)file(\s*?)\((.*?)\)/s) {
   450             my ($ws1, $level, $ws2, $ws3, $options) = ($1, $2, $3, $4, $5);
   452             #   enforce eight spaces
   453             if (length($ws1) != 8) {
   454                 &lint_warning($file, "", "", "path channel whitespace count at start of unseparated line");
   455             }
   457             #   enforce spaces
   458             if (length($ws2) < 1) {
   459                 &lint_warning($file, "", "", "path channel whitespace required between level and file of unseparated line");
   460             }
   462             #   enforce zero spaces
   463             if (length($ws3) != 0) {
   464                 &lint_warning($file, "", "", "whitespace not allowed between file channel and round open bracket");
   465             }
   467             #   check for legal l2 level
   468             if ($level !~ m/^(panic|critical|error|warning|notice|info|trace|debug)$/) {
   469                 &lint_warning($file, "", "", "illegal l2 level $level detected on unseparated line");
   470             }
   472             #   enforce file option in file channel
   473             if ($options !~ m;path="\@l_prefix\@/var/$pkg/(log\S+|$pkg\.log)";) {
   474                 &lint_warning($file, "", "", "XXX path option in file channel invalid or missing on unseparated line");
   475             }
   476             $options = $';
   477             $options =~ s/,//;
   479             #   enforce perm option in file channel
   480             if ($options !~ m;perm=0[0-7]{3};) {
   481                 &lint_warning($file, "", "", "perm option in file channel invalid or missing on unseparated line");
   482             }
   484             $options = $';
   485             $options =~ s/, jitter=[0-9]+//;
   486             $options =~ s/, monitor=[0-9]+//;
   487             $options =~ s/,//;
   489             #   detect superflous options in file channel
   490             if ($options =~ m/\S+/s) {
   491                 $options =~ s/\n/\\n/;
   492                 &lint_warning($file, "", "", "superflous option in file channel unseparated line detected: $options");
   493             }
   494         }
   495         else {
   496             &lint_warning($file, "", "", "file channel missing");
   497         }
   499         $done .= $this;
   500     }
   501     return;
   502 }

mercurial