#!/usr/bin/perl -CA
# ssh_access v1.0  (c) 6.8.2019 by Andreas Ley  (u) 6.8.2019
# Add ssh access for known identities to selected accounts

use strict;
#no strict 'vars';
use warnings;
no warnings 'uninitialized';
use sigtrap;
use diagnostics;

# The script itself may use utf-8 encoded identifiers and literals
use utf8;
# Latin-1 codepoints are considered characters
use feature 'unicode_strings';
#use locale;
# Enable UTF-8 encoding for all files (but not already open handles)
use open ':encoding(utf8)';

use Getopt::Long;
use File::Basename;
use File::Spec::Functions;

use Term::Cap;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Terse = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Deepcopy = 1;
#warn Data::Dumper->Dump([\%hash],['*']) if ($debug{'file'}>0);
#warn Data::Dumper->new([\%hash],['*'])->Indent(0)->Dump if ($debug{'file'}>0);

sub usage
{
	my $image = $0;
	$image =~ s!.*/!!;
	print  STDERR  "Usage: $image [options] identity account\n";
	print  STDERR  "-v, --verbose	Verbose mode\n";
	exit(1);
}

my %opt;
@_ = @ARGV;
$Getopt::Long::ignorecase = 0;
GetOptions (\%opt,'debug|D:s','help|h','trace|x','verbose|v+','dry-run|n');
exec($^X,'-d:Trace',$0,@_) if (defined($opt{'trace'}) && !defined($Devel::Trace::TRACE));

&usage() if (defined($opt{'help'}) || @ARGV!=2);

if (defined($opt{'verbose'}) || defined($opt{'debug'})) {
	$|=1;
	select((select(STDERR),$|=1)[0]);
}

my (%debug,$on,$off);

sub debug
{
	my $file = shift;
	my $line = shift;
	my $prefix = defined($debug{'path'})?$file:defined($debug{'file'})?basename($file):'';
	if (defined($debug{'line'})) {
		$prefix .= ':' if (length($prefix));
		$prefix .= $line;
	}
	$prefix .= '  ' if (length($prefix));
	warn $prefix.(scalar(@_)>1 ? join(', ',map("\"$_\"",@_))."\n" : "@_\n");
}
$debug{undef} = \&debug;

if (defined($opt{'debug'})) {
	for (split(',',$opt{'debug'})) {
		if (/=/) {
			$debug{$`} = $';
		}
		else {
			$debug{$_} = 1;
		}
	}
	&debug(__FILE__,__LINE__,'%debug = '.Data::Dumper->Dump([\%debug],['*debug'])) if ($debug{'debug'}>0);
	&debug(__FILE__,__LINE__,'%opt = '.Data::Dumper->Dump([\%opt],['*opt'])) if ($debug{'opt'}>0);
	my $term = Tgetent Term::Cap { 'OSPEED'=>9600 };
	$on = $term->Tputs('md');
	$off = $term->Tputs('me');
}

# Enable UTF-8 encoding for already open handles
# ":utf8" would enable perl native coding which happens to be UTF-8 only on ASCII platforms
binmode(STDIN,':encoding(utf8)');
binmode(STDOUT,':encoding(utf8)');
binmode(STDERR,':encoding(utf8)') unless (defined($Devel::Trace::TRACE));

my $identity = shift;
my $account = shift;

my ($user,$comment,$rsa1,$dsa,$rsa,$ecdsa,$ed25519);

################################################################################
#
# Red Dot
#
if ($identity =~ /^(?:Red\s*Dot|Open\s+Text|CMS)$/i) {
	$user = 'scc-reddot';
	$rsa1 = '1024 35 158712823850538744542013742552281926213255768637100167727310486722223249611898748485255830740996970051666394206771526678625148941879349456084916769801107441822037852677394236335780102278649262258711773717501130905360860223621075278611394063374914918266921800920701949323722154337370682370360460493947048974861';
	$dsa = 'AAAAB3NzaC1kc3MAAACBAP6hA/z0l59qK0QOwp+GsIPnWuMxvFNdjlQca7kMXbDYi2yBvOIUB2z74+nhic3kwejp9fcvPRrw0mzT9H1GYadwsaYTE+Tok914o+EdZNklvxzJ2jDjykCJqnNRfxqBxb5aodDd0kxo7AcSuvNGFBLBFkcRCZMHjwOmriyG/qMBAAAAFQDeVCBUPCDtdju1SprLiAdcHcdStQAAAIA2BNNPTo8+iFBD7jyIueYdYNh0ZTHajPgJzrGtqvpLE30iQGsFJhMZ9a2cByNJZHEFk6YNuvP4kBj/yQU4N9Mcdu/4uHLDM7GXCeBsVF0M3VeieTHcbwT0AqRsPJgl2tyqv3ddojyhOxaX92TTrwSxOSOBBXOXTq1YWBOsrVUqaQAAAIEAzhUTsiRPsB1bkzjYDo3WYWT01Ck+w73S16NXl8YCtumXvMQiL9NoMHl2Hub1kJzyqoDsfbhNhRh9iPsPzfmtVHVMPX5/ke6sKE8mJ5ItNzaigI5NbYAomewhxyHgCC6iLYz9ed3Fy2hAVatOfj48Ro5Js8XVryQ32YInur589uo=';
	$rsa = 'AAAAB3NzaC1yc2EAAAABIwAAAIEApk4ewDHIfBu2If/kGh1GIwS947BuKQDytU80wIROfU1r3CPlL+oQO1TiTARdU2o5k1jMI1QYJnxjIaljafGhFBEhSGFhOUqF5clry9rnVDSTwevNbIQHUUsPcRoUWXlSbzuOJE00OPx7OXeDGPiB5zsuAT0RGjvZ3PNazJb7C88=';
}

die "Unknown identity: $identity\n" unless (defined($user));

$comment = $user.'@sysmail.kit.edu' unless (defined($comment));

my ($name,$passwd,$uid,$gid,$quota,$_comment,$gcos,$dir,$shell,$expire) = getpwnam($account);

die "No such user: $user\n" unless (defined($name));

die "No such directory: $dir\n" unless (-d $dir);

$) = $gid;
$> = $uid;
#system('/usr/bin/id');

my $mode = (stat($dir))[2];
$mode |= 0700;
$mode &= ~022;
chmod($mode,$dir);

my $ssh = catdir($dir,'.ssh');
mkdir($ssh,0700) unless (-d $ssh);

$mode = (stat($ssh))[2];
$mode |= 0700;
$mode &= ~077;
chmod($mode,$ssh);

my $ak = catfile($ssh,'authorized_keys');
if (-f $ak) {
	$mode = (stat($ak))[2];
	$mode |= 0600;
	chmod($mode,$ak);
}

my %seen;
if (open(AK,'<',$ak)) {
	while (<AK>) {
		chomp;
		$seen{$_}++;
	}
	close(AK);
}

my $remoteuser = "environment=\"REMOTEUSER=${user}\" ";

&add("${remoteuser}ssh-rsa ${rsa} ${comment}") if (defined($rsa));
#&add("${remoteuser}ecdsa-sha2-nistp256 ${ecdsa} ${comment}") if (defined($ecdsa));
&add("${remoteuser}ssh-ed25519 ${ed25519} ${comment}") if (defined($ed25519));

sub add
{
	my ($line) = @_;

	unless (defined($seen{$line})) {
		open(AK,'>>',$ak) or die "Can't write to $ak: $!\n";
		print AK $line,"\n";
		close(AK);
	}
}

$mode = (stat($ak))[2];
$mode &= ~022;
chmod($mode,$ak);
