diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2012-05-29 17:47:46 +1200 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2012-05-29 17:47:46 +1200 |
commit | e0176ca7c974e7bb9867f491ad28f08e4531fde2 (patch) | |
tree | 21d7b726eea0ebbc28fca809a7e9123fa7b96ce2 | |
parent | Update README with requirements and better paths (diff) | |
download | clubber-e0176ca7c974e7bb9867f491ad28f08e4531fde2.tar.gz clubber-e0176ca7c974e7bb9867f491ad28f08e4531fde2.zip |
Add actual script, seems to work nicely
-rwxr-xr-x | clubber | 186 |
1 files changed, 185 insertions, 1 deletions
@@ -2,7 +2,8 @@ # # Clubber -- Less painful chroot environment building and verification. Please -# see README.markdown for documentation. +# see README.markdown for documentation. Be sure you trust your binaries! This +# script won't protect you from ldd exploits. # # @author Tom Ryder <tom@sanctum.geek.nz> # @copyright 2012 Sanctum @@ -10,4 +11,187 @@ use strict; use warnings; +use Cwd qw(abs_path); +use File::Basename; +use Getopt::Long; + +# +# Bail if we're not root. +# +if ($< != 0 || $> != 0) { + error("You must have root permissions to use this script."); +} + +# +# Check ldd is available. +# +chomp(my $ldd = `which ldd`); +if (!$ldd) { + error("Couldn't find ldd in your \$PATH."); +} + +# +# Check md5sum is available. +# +chomp(my $md5sum = `which md5sum`); +if (!$md5sum) { + error("Couldn't find md5sum in your \$PATH."); +} + +# +# Check options. +# +my ($chroot, $dry, $verify) = ("", 0, 0, 0); +my $config = GetOptions("chroot=s" => \$chroot, + "dry" => \$dry); +if ($chroot) { + $chroot = abs_path($chroot); + if (!-d $chroot) { + error("Nominated chroot %s doesn't seem to be a directory.", $chroot); + } +} elsif ($dry) { + error("Doesn't make sense to specify --dry without --chroot."); +} + +# +# Check we were passed at least one parameter, otherwise print a helpful +# message. +# +if (!@ARGV) { + printf STDOUT "USAGE: ${0} [--chroot] [--verify] [--dry] binary1 binary2 ... \n"; + exit 0; +} + +# +# Check that all our parameters are real files, or point to one. +# +my $binaries = []; +foreach my $argument (@ARGV) { + $argument = abs_path($argument); + if (-f $argument) { + push @$binaries, $argument; + } else { + error("File %s doesn't seem to exist.", $argument); + } +} + +# +# Run ldd on all the files and slurp all the absolute paths; put them into a +# hash to keep things unique. +# +my $libraries = {}; +foreach my $binary (@$binaries) { + my $output = [qx/${ldd} ${binary}/]; + foreach my $line (@$output) { + if ($line =~ m#(/\S*lib\S+)#) { + $libraries->{$1} = 1; + } + } +} + +# +# If we have a chroot, we need to figure out what libraries require importing +# and which directories require creating. +# +if ($chroot) { + my ($directories, $imports) = ({}, {}); + + # + # First we'll recurse through the list of libraries and flag any + # directories that require creation. We won't complicate things by + # reproducing any symbolic link structures. + # + # If the directory does exist, we'll make sure the library is in place + # too, and if it is that its md5sum is the same as our root system + # library. If it doesn't exist or if it's different, we'll flag it for + # overwriting. + # + foreach my $library (keys(%$libraries)) { + my $directory = dirname($library); + if (!-d "${chroot}${directory}") { + $directories->{$directory} = 1; + } + if (-f "${chroot}{$library}") { + if (qx/${md5sum} ${library}/ ne qx/${md5sum} ${chroot}${library}/) { + $imports->{$library} = 1; + } + } else { + $imports->{$library} = 1; + } + } + + # + # Check there's something for us to do. + # + if (keys %$directories || keys %$imports) { + + # + # If we're just supposed to print what we do, all the better, do + # that and then quit. + # + if ($dry) { + if (keys %$directories) { + printf STDOUT "Create directories:\n"; + foreach my $directory (keys(%$directories)) { + printf STDOUT " %s\n", "${chroot}${directory}"; + } + } + if (keys %$imports) { + printf STDOUT "Copy libraries:\n"; + foreach my $import (keys(%$imports)) { + printf STDOUT " %s -> %s\n", $import, "${chroot}${import}"; + } + } + + # + # Otherwise, we'd best get started. + # + } else { + foreach my $directory (keys(%$directories)) { + system("mkdir -pv ${chroot}${directory}"); + } + foreach my $import (keys(%$imports)) { + system("cp -pv ${import} ${chroot}${import}"); + } + } + + # + # If there's nothing we need to do, say so. + # + } else { + printf STDOUT "Nothing to do.\n"; + } + +# +# If we don't have a chroot, we can just print the list of libraries, and we're +# done. +# +} else { + foreach my $library (keys(%$libraries)) { + printf "%s\n", $library; + } +} + +# +# And one way or another, we're done. +# +exit 0; + +# +# Print a usage message and exit with non-zero. +# +sub usage { + my $message = shift @_; + printf STDERR "USAGE: ${message}\n", @_; + exit 1; +} + +# +# Print a usage message and exit with non-zero. +# +sub error { + my $message = shift @_; + printf STDERR "ERROR: ${message}\n", @_; + exit 1; +} |