Preliminary server chroot installation
Configures a chroot with Perl and bin/pgen-server to run a shell. ssh to 'pgen@localhost' successful shows pgen-server test message then logs out. 'add_key' and 'remove_server' functions also work. Recursive path builder function 'dig_dirs' also works well within the latter.
This commit is contained in:
parent
aedd59b759
commit
e3bdcdb5ae
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
print("Testing server\n");
|
|
@ -0,0 +1,218 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $server_dir = '/var/pgen';
|
||||
use File::Which;
|
||||
|
||||
if (scalar(@ARGV) != 1) {
|
||||
usage("Requires exactly 1 argument:");
|
||||
} elsif ($ARGV[0] eq '-h' || $ARGV[0] eq '--help') {
|
||||
usage("Usage: $0 <option>");
|
||||
} elsif ($ARGV[0] eq 'server') {
|
||||
if (-d $server_dir) {
|
||||
print("Installation appears to already exist. Would you like it to be removed and
|
||||
replaced? All existing password information will be lost. ");
|
||||
my $selection;
|
||||
do {
|
||||
print("[y/N]? ");
|
||||
$selection = <STDIN>;
|
||||
chomp($selection);
|
||||
} while (!defined($selection) || $selection !~ m/^[yYnN]?$/);
|
||||
unless ($selection eq 'y' || $selection eq 'Y') {
|
||||
die("Abandoning installation\n");
|
||||
}
|
||||
remove_server();
|
||||
}
|
||||
install_server();
|
||||
} elsif ($ARGV[0] eq 'client') {
|
||||
install_client();
|
||||
} elsif ($ARGV[0] eq 'remove') {
|
||||
my %removed = (
|
||||
'server' => undef,
|
||||
'client' => undef
|
||||
);
|
||||
if (detect_server()) {
|
||||
$removed{'server'} = remove_server();
|
||||
}
|
||||
if (detect_client()) {
|
||||
$removed{'client'} = remove_client();
|
||||
}
|
||||
foreach (keys(%removed)) {
|
||||
if (defined($removed{$_})) {
|
||||
if ($removed{$_}) {
|
||||
print("Received error '$removed{$_}' while removing $_\n");
|
||||
} else {
|
||||
print("Successfully removed $_\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} elsif ($ARGV[0] eq 'add') {
|
||||
add_key();
|
||||
} else {
|
||||
usage("Invalid argument '$ARGV[0]'. Requires one of:");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
sub detect_server
|
||||
{
|
||||
my $dir = (getpwnam('pgen'))[7] || return undef;
|
||||
if (-d $dir) {
|
||||
return($dir);
|
||||
}
|
||||
return(undef);
|
||||
|
||||
}
|
||||
|
||||
sub detect_client
|
||||
{
|
||||
return(which('pgen'));
|
||||
}
|
||||
|
||||
sub install_server
|
||||
{
|
||||
my $perl = which('perl') || die "Missing dependency: perl\n";
|
||||
chomp($perl);
|
||||
my ($perl_dir) = $perl =~ m/^((?:\/[^\/]*)*)\/perl$/;
|
||||
my @perl_path = ( $server_dir );
|
||||
foreach (split('/',$perl_dir)) {
|
||||
unless($_ eq '') {
|
||||
if (scalar(@perl_path)) {
|
||||
$_ = $perl_path[scalar(@perl_path)-1].'/'.$_;
|
||||
}
|
||||
push(@perl_path,$_);
|
||||
}
|
||||
}
|
||||
foreach (@perl_path, $server_dir."/.ssh", $server_dir."/bin", $server_dir."/lib", $server_dir."/lib64") {
|
||||
print "Creating directory '$_'\n";
|
||||
mkdir($_) || die "Failed to mkdir '$_': $!\n";
|
||||
}
|
||||
use File::Copy;
|
||||
print("Installing Perl...\n");
|
||||
copy($perl,"${server_dir}${perl}");
|
||||
chmod(0755, "${server_dir}${perl}");
|
||||
my $libs = `ldd ${server_dir}${perl}`;
|
||||
foreach (split("\n",$libs)) {
|
||||
if ($_ =~ m#^\s+([^\ ]+)\ =>\ (\/[^\/]+)((?:\/[^\/]*)*)\/([^\/]+) \(.*#) {
|
||||
print "Copying ${2}${3}/${4} to ${server_dir}${2}/${4}\n";
|
||||
copy("${2}${3}/${4}","${server_dir}${2}/${4}");
|
||||
} elsif ($_ =~ m#^\s+(\/[^\/]+)((?:\/[^\/]*)*)\/([^\/]+) \(.*#) {
|
||||
print "Copying ${1}${2}/${3} to ${server_dir}${1}/${3}\n";
|
||||
copy("${1}${2}/${3}","${server_dir}${1}/${3}");
|
||||
} else {
|
||||
print "skipping $_\n";
|
||||
}
|
||||
}
|
||||
my $src = $0;
|
||||
$src =~ s/(.*)\/([^\/]*)/$1\/bin\/pgen-server/;
|
||||
print("Installing $src to ${server_dir}/bin/pgen\n");
|
||||
copy($src,"${server_dir}/bin/pgen") || die("Failed to install: $!\n");
|
||||
chmod(0755, "${server_dir}/bin/pgen");
|
||||
print("Configuring user 'pgen'\n");
|
||||
system("useradd -d $server_dir pgen");
|
||||
system("usermod -s $server_dir/bin/pgen pgen");
|
||||
add_key();
|
||||
print("Server installation complete\n");
|
||||
}
|
||||
|
||||
sub install_client
|
||||
{
|
||||
if (detect_client()) {
|
||||
die("Client is already installed. If necessary, uninstall it with 'remove'\n");
|
||||
}
|
||||
print("TODO: Here I would install the client\n");
|
||||
}
|
||||
|
||||
sub remove_server
|
||||
{
|
||||
if (detect_server()) {
|
||||
system("userdel pgen");
|
||||
}
|
||||
my @paths;
|
||||
my $paths_ref = \@paths;
|
||||
dig_dirs($paths_ref, $server_dir);
|
||||
unless (scalar(@paths)) {
|
||||
die("No chroot installation present at $server_dir\n");
|
||||
}
|
||||
while (scalar(@paths)) {
|
||||
my $target = pop(@paths);
|
||||
print "Removing $target...\n";
|
||||
if (-d $target) {
|
||||
rmdir($target) || die("Failed to remove directory '$target': $!\n");
|
||||
} else {
|
||||
unlink($target) || die("Failed to delete '$target': $!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub dig_dirs
|
||||
{
|
||||
my $paths_ref = shift;
|
||||
my $path = shift;
|
||||
unless (-e $path) {
|
||||
return(undef);
|
||||
}
|
||||
if ($path =~ m/\/\.\.?$/) {
|
||||
return;
|
||||
}
|
||||
push(@$paths_ref, $path);
|
||||
foreach (glob("$path/*"), glob("$path/.*")) {
|
||||
if ($path =~ m/\/\.\.?$/) {
|
||||
next();
|
||||
}
|
||||
if (-d $_) {
|
||||
dig_dirs($paths_ref,$_);
|
||||
} else {
|
||||
push(@$paths_ref, $_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub remove_client
|
||||
{
|
||||
unless (detect_client()) {
|
||||
return "Client is not installed.\n";
|
||||
}
|
||||
print("TODO: Here I would remove the client\n");
|
||||
}
|
||||
|
||||
sub add_key
|
||||
{
|
||||
unless (detect_server()) {
|
||||
die("This must be run on a host with the server installed");
|
||||
}
|
||||
my $file = "$server_dir/.ssh/authorized_keys";
|
||||
my $msg = "Paste the SSH public key of the user. 'Q' to";
|
||||
if (-e $file) {
|
||||
print("Adding new user. $msg abort ");
|
||||
} else {
|
||||
print("Initializing with first user. $msg skip ");
|
||||
}
|
||||
my $key;
|
||||
do {
|
||||
print("[<key>/Q]: ");
|
||||
$key = <STDIN>;
|
||||
chomp($key);
|
||||
} while (!defined($key) || ($key ne 'Q' && $key ne 'q' && $key !~ m/^ssh\-(dsa|ecdsa|ecdsa\sk|ed25519|ed25519-sk|rsa)\ [a-zA-Z0-9\+\/]{50,}/));
|
||||
open(my $fh, '>>', $file) || die("Failed to open '$file': $!\n");
|
||||
unless ($key eq 'Q' && $key ne 'q') {
|
||||
print $fh $key."\n";
|
||||
}
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
my $error = shift;
|
||||
if (!defined($error)) {
|
||||
$error = "Unknown failure. Try running with one of these options:";
|
||||
}
|
||||
die($error . "
|
||||
server - install server application
|
||||
client - install client application
|
||||
remove - uninstall client and server (as necessary)
|
||||
add - add a user key (SSH public key)\n");
|
||||
exit(1);
|
||||
}
|
Loading…
Reference in New Issue