openpkg/makeproxy.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 ##  makeproxy.pl -- OpenPKG Tool Chain
     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 require 5.003;
    26 #   OpenPKG instance prefix and RPM
    27 my $my_prefix = $ENV{'OPENPKG_PREFIX'};
    28 my $my_rpm    = "$my_prefix/bin/openpkg rpm";
    29 delete $ENV{'OPENPKG_PREFIX'};
    31 #   program identification
    32 my $progname  = "makeproxy";
    33 my $progvers  = "2.1.0";
    35 #   parameters (defaults)
    36 my $help          = 0;
    37 my $version       = 0;
    38 my $verbose       = 0;
    39 my $debug         = 0;
    40 my $slave_prefix  = $my_prefix;
    41 my $master_prefix = '';
    42 my $tmpdir        = ($ENV{TMPDIR} || "/tmp");
    43 my $output        = '.';
    44 my $input         = '-';
    46 #   cleanup support
    47 my @cleanup = ();
    48 sub cleanup_remember {
    49     my ($cmd) = @_;
    50     push(@cleanup, $cmd);
    51 }
    52 sub cleanup_perform {
    53     foreach my $cmd (reverse @cleanup) {
    54         runcmd($cmd);
    55     }
    56 }
    58 #   exception handling support
    59 $SIG{__DIE__} = sub {
    60     my ($err) = @_;
    61     $err =~ s|\s+at\s+.*||s if (not $verbose);
    62     $err =~ s/\n+$//s;
    63     print STDERR "openpkg:$progname:ERROR: $err\n";
    64     cleanup_perform() if (not $verbose);
    65     exit(1);
    66 };
    68 #   verbose message printing
    69 sub verbose {
    70     my ($msg) = @_;
    71     print STDERR "$msg\n" if ($verbose);
    72 }
    74 #   execution of external commands
    75 sub runcmd {
    76     my ($cmd) = @_;
    77     if ($cmd =~ m/^(.+)\|$/s) {
    78         print STDERR "\$ $1\n" if ($debug);
    79         return `$1`;
    80     }
    81     else {
    82         print STDERR "\$ $cmd\n" if ($debug);
    83         $cmd = "($cmd) >/dev/null 2>&1" if (not $debug);
    84         return (system($cmd) == 0);
    85     }
    86 }
    88 #   expand into a full filesystem path
    89 sub fullpath {
    90     my ($prog) = @_;
    91     my $fullprog = '';
    92     foreach my $path (split(/:/, $ENV{PATH})) {
    93         if (-x "$path/$prog") {
    94             $fullprog = "$path/$prog";
    95             last;
    96         }
    97     }
    98     return $fullprog;
    99 }
   101 #   convert a subdirectory (a/b/c/)
   102 #   into a corresponding reverse path (../../../)
   103 sub sub2rev {
   104     my ($sub) = @_;
   105     my $rev = '';
   106     $sub =~ s|^/+||s;
   107     $sub =~ s|/+$||s;
   108     while ($sub =~ s|/[^/]+||) {
   109         $rev .= "../";
   110     }
   111     if ($sub ne '') {
   112         $rev .= "../";
   113     }
   114     $rev =~ s|/$||s;
   115     return $rev;
   116 }
   118 #   create a directory (plus its missing parent dirs)
   119 sub mkdirp {
   120     my ($dir) = @_;
   121     my $pdir = $dir;
   122     $pdir =~ s|/[^/]*$||s;
   123     if (not -d $pdir) {
   124         mkdirp($pdir);
   125     }
   126     if (not -d $dir) {
   127         runcmd("mkdir $dir");
   128     }
   129 }
   131 #   home-brewn getopt(3) style option parser
   132 sub getopts ($) {
   133     my ($opts) = @_;
   134     my (%optf) = map { m/(\w)/; $1 => $_ } $opts =~ m/(\w:|\w)/g;
   135     my (%opts, @argv, $optarg);
   137     foreach (@ARGV) {
   138         if (@argv) {
   139             push @argv, $_;
   140         } elsif (defined $optarg) {
   141             if (exists $opts{$optarg}) {
   142                 $opts{$optarg} .= " $_";
   143             } else {
   144                 $opts{$optarg} = $_;
   145             }
   146             $optarg = undef;
   147         } elsif (!/^[-]/) {
   148             push @argv, $_;
   149         } else {
   150             while (/^\-(\w)(.*)/) {
   151                 if (exists $optf{$1}) {
   152                     if (length($optf{$1}) > 1) {
   153                         if ($2 ne '') {
   154                             if (exists $opts{$1}) {
   155                                 $opts{$1} .= " $2";
   156                             } else {
   157                                 $opts{$1} = $2;
   158                             }
   159                         } else {
   160                             $optarg = $1;
   161                         }
   162                         last;
   163                     } else {
   164                         $opts{$1} = 1;
   165                     }
   166                 } else {
   167                     warn "openpkg:makeproxy:WARNING: unknown option $_\n";
   168                 }
   169                 $_ = "-$2";
   170             }
   171         }
   172     }
   173     if (defined $optarg) {
   174         warn "openpkg:makeproxy:WARNING: option $optarg requires an argument\n";
   175     }
   176     foreach (keys %opts) {
   177         eval '$opt_'.$_.' = "'.quotemeta($opts{$_}).'";';
   178     }
   179     @ARGV = @argv;
   180 }
   182 #   command line parsing
   183 getopts("Vhdvm:s:t:o:");
   184 $version       = $opt_V if (defined $opt_V);
   185 $help          = $opt_h if (defined $opt_h);
   186 $debug         = $opt_d if (defined $opt_d);
   187 $verbose       = $opt_v if (defined $opt_v);
   188 $master_prefix = $opt_m if (defined $opt_m);
   189 $slave_prefix  = $opt_s if (defined $opt_s);
   190 $tmpdir        = $opt_t if (defined $opt_t);
   191 $output        = $opt_o if (defined $opt_o);
   192 if ($help) {
   193     print "Usage: openpkg $progname [options] master-package\n" .
   194           " -h,--help          print this usage page\n" .
   195           " -V,--version       print version\n" .
   196           " -v,--verbose       print verbose run-time information\n" .
   197           " -d,--debug         print debug information\n" .
   198           " -m,--master=DIR    filesystem path to master OpenPKG instance\n" .
   199           " -s,--slave=DIR     filesystem path to slave OpenPKG instance\n" .
   200           " -t,--tmpdir=DIR    filesystem path to temporary directory\n" .
   201           " -o,--output=FILE   filesystem path to output proxy OpenPKG RPM package\n";
   202     exit(0);
   203 }
   204 if ($version) {
   205     print "OpenPKG $progname $progvers\n";
   206     exit(0);
   207 }
   208 if ($#ARGV == 0) {
   209     $input = shift(@ARGV);
   210 }
   211 if ($#ARGV != -1) {
   212     die "invalid number of command line arguments";
   213 }
   215 #   prepare temporary location
   216 verbose("++ prepare temporary directory");
   217 $tmpdir = "$tmpdir/$progname.$$";
   218 if (not -d $tmpdir) {
   219     runcmd("umask 077 && mkdir $tmpdir")
   220         or die "cannot create temporary directory \"$tmpdir\"";
   221     cleanup_remember("rm -rf $tmpdir");
   222 }
   223 verbose("-- temporary directory: $tmpdir");
   225 #   determine input and output RPM
   226 verbose("++ determining OpenPKG RPM package files");
   227 verbose("-- input/master/regular RPM package: $input");
   228 verbose("-- output/slave/proxy   RPM package: $output");
   230 #   ensure input RPM package is available on the filesystem
   231 if ($input eq '-') {
   232     $input = "$tmpdir/input.rpm";
   233     runcmd("cat >$input");
   234 }
   236 #   determine master and slave OpenPKG instance and RPM commands
   237 if ($master_prefix eq '') {
   238     if (not -f $input) {
   239         die "input/master/regular RPM package does not exist: \"$input\"";
   240     }
   241     $master_prefix = runcmd("($my_rpm -qp --qf '%{PREFIXES}' $input 2>/dev/null || true) |");
   242     $master_prefix =~ s/\r?\n$//s;
   243     if ($master_prefix eq '') {
   244         die "unable to determine master OpenPKG instance";
   245     }
   246 }
   247 if ($master_prefix eq $slave_prefix) {
   248     die "master and slave OpenPKG instances have to be different";
   249 }
   250 my $slave_rpm  = (-f "$slave_prefix/bin/openpkg"  ? "$slave_prefix/bin/openpkg rpm"  : $my_rpm);
   251 my $master_rpm = (-f "$master_prefix/bin/openpkg" ? "$master_prefix/bin/openpkg rpm" : $my_rpm);
   252 verbose("-- tool   OpenPKG instance:    $my_prefix");
   253 verbose("-- tool   OpenPKG RPM command: $my_rpm");
   254 verbose("-- master OpenPKG instance:    $master_prefix");
   255 verbose("-- master OpenPKG RPM command: $master_rpm");
   256 verbose("-- slave  OpenPKG instance:    $slave_prefix");
   257 verbose("-- slave  OpenPKG RPM command: $slave_rpm");
   259 #   helper function for parsing RPM query outputs
   260 sub parseresponse {
   261     my ($r, $o) = @_;
   262     sub parseline {
   263         my ($r, $t, $k, $v) = @_;
   264         $v =~ s|^\s+||s;
   265         $v =~ s|\s+$||s;
   266         if ($t eq 'S') {     # single-value results
   267             $r->{$k} = $v;
   268         }
   269         elsif ($t eq 'M') {  # multi-value results
   270             $r->{$k} = [] if (not defined($r->{$k}));
   271             push(@{$r->{$k}}, $v);
   272         }
   273     }
   274     $o =~ s|([SM])-([^:]+):<(.*?)>\n|parseline($r, $1, $2, $3, '')|egs;
   275     return $r;
   276 }
   278 #   query master OpenPKG RPM package
   279 verbose("++ query information from master OpenPKG RPM package");
   280 my $q = '';
   281 foreach my $t (qw(
   282     NAME SUMMARY URL VENDOR PACKAGER DISTRIBUTION CLASS GROUP LICENSE VERSION RELEASE
   283     DESCRIPTION
   284 )) {
   285     $q .= "S-$t:<%{$t}>\\n";
   286 }
   287 $q .= '[M-PREREQ:<%{REQUIRENAME} %|REQUIREFLAGS?{%{REQUIREFLAGS:depflags} %{REQUIREVERSION}}:{}|>\n]';
   288 $q .= '[M-PROVIDES:<%{PROVIDENAME} %|PROVIDEFLAGS?{%{PROVIDEFLAGS:depflags} %{PROVIDEVERSION}}:{}|>\n]';
   289 $q .= '[M-PREFIXES:<%{PREFIXES}>\n]';
   290 my $cmd = sprintf("%s -q %s --qf '$q' %s", $master_rpm, (-f $input ? "-p" : ""), $input);
   291 my $o = runcmd("$cmd|");
   292 if ($o =~ m/package .* is not installed/s) {
   293     die "master package \"$input\" not installed in master OpenPKG instance \"$master_prefix\"";
   294 }
   295 $o =~ s|M-PREREQ:<rpmlib\(.*?\).*?>\n||gs;
   296 my $r = {};
   297 $r = parseresponse($r, $o);
   298 my $BD = '';
   299 my $ID = '';
   300 my $PR = '';
   301 foreach my $d (@{$r->{PREREQ}}) {
   302     if ($d =~ m|^OpenPKG|i) {
   303         $BD .= ", " if ($BD ne '');
   304         $BD .= $d;
   305     }
   306     $ID .= ", " if ($ID ne '');
   307     $ID .= $d;
   308 }
   309 foreach my $d (@{$r->{PROVIDES}}) {
   310     $PR .= ", " if ($PR ne '');
   311     $PR .= $d;
   312 }
   314 #   prepare build environment
   315 verbose("++ establishing temporary OpenPKG RPM environment");
   316 verbose("-- directory: $tmpdir");
   317 runcmd("rm -rf $tmpdir/src; mkdir $tmpdir/src");
   318 runcmd("rm -rf $tmpdir/bld; mkdir $tmpdir/bld");
   319 cleanup_remember("rm -rf $tmpdir/src");
   320 cleanup_remember("rm -rf $tmpdir/tmp");
   321 cleanup_remember("rm -rf $tmpdir/bld");
   322 cleanup_remember("rm -rf $tmpdir/pkg");
   323 runcmd("mkdir $tmpdir/src/.openpkg");
   324 open(MACRO, ">$tmpdir/src/.openpkg/rpmmacros")
   325     or die "unable to write file \"$tmpdir/src/.openpkg/rpmmacros\": $!";
   326 print MACRO "\%openpkg_layout macrosfile=\%{macrosfile} layout=local shared=no\n";
   327 close(MACRO);
   328 $ENV{HOME} = $tmpdir;
   330 #   generate OpenPKG RPM .spec file for proxy OpenPKG RPM package
   331 verbose("++ generating OpenPKG RPM package specification for proxy package");
   332 verbose("-- file: $tmpdir/src/".$r->{NAME}.".spec");
   333 my $S = '';
   334 $S .= "Name:         ".$r->{NAME}."\n";
   335 $S .= "Summary:      ".$r->{SUMMARY}."\n";
   336 $S .= "URL:          ".$r->{URL}."\n";
   337 $S .= "Vendor:       ".$r->{VENDOR}."\n";
   338 $S .= "Packager:     ".$r->{PACKAGER}."\n";
   339 $S .= "Distribution: ".$r->{DISTRIBUTION}."\n";
   340 $S .= "Class:        ".$r->{CLASS}."\n";
   341 $S .= "Group:        ".$r->{GROUP}."\n";
   342 $S .= "License:      ".$r->{LICENSE}."\n";
   343 $S .= "Version:      ".$r->{VERSION}."\n";
   344 $S .= "Release:      ".$r->{RELEASE}."+PROXY\n";
   345 $S .= "\n";
   346 $S .= "BuildPreReq:  $BD\n" if ($BD ne '');
   347 $S .= "PreReq:       $ID\n" if ($ID ne '');
   348 $S .= "Provides:     $PR\n" if ($PR ne '');
   349 $S .= "\n";
   350 $S .= "\%description\n";
   351 $S .= "    ".$r->{DESCRIPTION}."\n";
   352 $S .= "\n";
   353 $S .= "\%install\n";
   354 $S .= "    \%{l_rpmtool} files -v -ofiles -r\$RPM_BUILD_ROOT \%{l_files_std}\n";
   355 $S .= "\n";
   356 $S .= "\%files -f files\n";
   357 $S .= "\n";
   358 open(SPEC, ">$tmpdir/src/".$r->{NAME}.".spec")
   359    or die "unable to write file \"$tmpdir/src/".$r->{NAME}."\": $!";
   360 print SPEC $S;
   361 close(SPEC);
   363 #   creating shadow tree of original contents
   364 verbose("++ creating shadow tree from original package contents");
   365 $q = '[%{FILEMODES:perms} %{FILENAMES}\n]';
   366 $cmd = sprintf("%s -q %s --qf '$q' '%s'", $master_rpm, (-f $input ? "-p" : ""), $input);
   367 my @FL = runcmd("$cmd|");
   368 my $FD = [];
   369 my $FR = [];
   370 foreach my $fl (@FL) {
   371     $fl =~ s|\n$||s;
   372     if ($fl =~ m|^(d\S+)\s+$master_prefix(.*)$|) {
   373         mkdirp("$tmpdir/bld$slave_prefix$2");
   374         verbose("-- | PHYS $1 $slave_prefix$2");
   375     }
   376     elsif ($fl =~ m|^(\S+)\s+$master_prefix(.*?)([^/\s]+)$|) {
   377         my ($subdir, $file) = ($2, $3);
   378         my $target = sub2rev($subdir)."/.prefix-".$r->{NAME}.$subdir.$file;
   379         mkdirp("$tmpdir/bld$slave_prefix$subdir");
   380         runcmd("ln -s $target $tmpdir/bld$slave_prefix$subdir$file");
   381         verbose("-- | VIRT $1 $slave_prefix$subdir$file");
   382     }
   383 }
   385 #   create master-reference symbolic link
   386 runcmd("ln -s $master_prefix $tmpdir/bld$slave_prefix/.prefix-".$r->{NAME});
   388 #   rolling output proxy RPM package
   389 verbose("++ rolling output proxy RPM package");
   390 runcmd(
   391     "cd $tmpdir/src && " .
   392     "$slave_rpm -bb " .
   393     "--define 'buildroot $tmpdir/bld' " .
   394     "--define '__spec_install_pre \%{___build_pre}' " .
   395     "--nodeps ".$r->{NAME}.".spec"
   396 );
   398 #   providing output
   399 verbose("++ providing output: $output");
   400 if ($output eq '-') {
   401     runcmd("cat $tmpdir/src/*.rpm");
   402 }
   403 else {
   404     runcmd("cp $tmpdir/src/*.rpm $output");
   405 }
   407 #   die gracefully...
   408 verbose("++ cleaning up environment");
   409 cleanup_perform();
   410 exit(0);

mercurial