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.

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

mercurial