--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/update-schlittermann-ssh-keys.pl Mon Jan 31 12:40:15 2011 +0100
@@ -0,0 +1,202 @@
+#! /usr/bin/perl
+# $Id: update-schlittermann-ssh-keys.pl 4805 2009-12-03 14:39:57Z foerste $
+# $URL: https://ssl.schlittermann.de/svn/is/schlittermann-ssh-key/trunk/update-schlittermann-ssh-keys.pl $
+
+use strict;
+use warnings;
+use File::Basename;
+use File::Copy;
+use Getopt::Long;
+use Term::ReadKey;
+use Pod::Usage;
+use if $ENV{DEBUG} => "Smart::Comments";
+
+my $ME = basename $0;
+my $effective_uid = $>;
+my $home_dir = (getpwuid $effective_uid)[7];
+my $opt_update = 1;
+my $opt_help = 0;
+my $opt_man = 0;
+my $opt_keys_dir = "/usr/share/schlittermann-ssh-keys";
+my $opt_force = 0;
+
+my $SSHD_CONF = "/etc/ssh/sshd_config";
+my $KEYS_DIR = undef; # set later
+my $SSH_DIR = "$home_dir/.ssh";
+my $AUTH_KEYS = "$SSH_DIR/authorized_keys";
+my $AUTH_KEYS_LOCAL = "$SSH_DIR/authorized_keys.local";
+
+sub read_keys(@) {
+ local @ARGV = grep -f, @_;
+ my %h;
+ if (@ARGV) {
+ while (<>) { chomp; $h{$_} = 1 }
+ }
+ return %h;
+}
+
+MAIN: {
+
+ GetOptions(
+ "update!" => \$opt_update,
+ "help!" => \$opt_help,
+ "man!" => \$opt_man,
+ "keys-dir=s" => \$opt_keys_dir,
+ "force!" => \$opt_force,
+ ) or pod2usage(-exitval => 1, -verbose => 0);
+
+ $KEYS_DIR = $opt_keys_dir;
+
+ pod2usage(-exitval => 0, -verbose => 0) if $opt_help;
+ pod2usage(-exitval => 0, -verbose => 2) if $opt_man;
+
+ # update authorized_keys file
+ if ($opt_update) {
+
+ # checking Schlittermann keys directory
+ -d $KEYS_DIR
+ or die "\n[$KEYS_DIR] doesn't exist.\n\n";
+
+ # creating .ssh directory if not exists
+ -d $SSH_DIR
+ or mkdir $SSH_DIR, 0700
+ or die "Can't create directory $SSH_DIR: $!\n";
+
+ # backup authorized_keys file
+ if (-e $AUTH_KEYS) {
+ my $copy = $opt_force || !-e "$AUTH_KEYS.bak";
+ if (!$copy) {
+ print
+"\nWARNING: [$AUTH_KEYS.bak] already exists. Overwrite? [yes/N]: ";
+ chomp(my $input = <STDIN>);
+ $copy = lc $input eq "yes";
+ }
+ copy($AUTH_KEYS => "$AUTH_KEYS.bak")
+ or die "Can't copy $AUTH_KEYS: $!\n"
+ if $copy;
+ }
+
+ # read Schlittermann keys
+ my %schlittermann_keys = read_keys(glob("$KEYS_DIR/*"));
+ my %local_keys = read_keys($AUTH_KEYS_LOCAL);
+ my %auth_keys = read_keys($AUTH_KEYS);
+
+ delete @auth_keys{ keys %schlittermann_keys, keys %local_keys };
+
+ foreach (keys %auth_keys) { # die noch unbekannten
+ /^(.* ssh-\S+ ).*? (.*)$/ or /^(.{30}).*?(.{30})$/;
+ print "Keep unknown: " . ((defined $1 and defined $2) ? "$1 ... $2" : $_) . ": [y/N] ";
+ ReadMode "cbreak";
+ my $answer = lc ReadKey;
+ ReadMode "restore";
+
+ $answer = "n" if not $answer eq "y";
+ print "$answer\n";
+ next if $answer ne "y";
+ $local_keys{$_} = 1;
+ }
+
+ my $fh;
+ open $fh, ">$AUTH_KEYS_LOCAL"
+ or die "Can't open $AUTH_KEYS_LOCAL: $!\n";
+ print $fh map { "$_\n" } keys %local_keys;
+ close $fh;
+
+ open $fh, ">$AUTH_KEYS" or die "Can't open $AUTH_KEYS: $!\n";
+ print $fh map { "$_\n" } keys %schlittermann_keys, keys %local_keys;
+ close $fh;
+
+ }
+
+ # check /etc/ssh/sshd_config for the keyword PermitUserEnvironment
+ if (open(my $fh, $SSHD_CONF)) {
+ grep { /^\s*PermitUserEnvironment\s+yes/i } <$fh>
+ and print "$SSHD_CONF is ok\n"
+ and exit 0;
+ }
+ else {
+ warn "Can't check $SSHD_CONF: $!\n";
+ exit 0;
+ }
+
+ warn "PermitUserEnvironment not set!\n";
+
+ if (open(my $fh, "+<$SSHD_CONF")) {
+ copy($SSHD_CONF => "$SSHD_CONF.bak")
+ or die "Can't copy $SSHD_CONF -> $SSHD_CONF.bak: $!\n";
+ $_ = join "", <$fh>;
+ s/^(\s*PermitUserEnvironment\s+).*$/# modified by $ME:\n$1yes/im
+ or $_ .= "# inserted by $ME:\nPermitUserEnvironment yes\n";
+
+ seek($fh, 0, 0);
+ print $fh $_;
+ truncate($fh, tell($fh));
+ close($fh) or rename("$SSHD_CONF.bak" => $SSHD_CONF);
+
+ system("invoke-rc.d ssh reload");
+
+ exit 0;
+ }
+ else {
+ warn "Can't modify $SSHD_CONF: $!\n";
+ }
+}
+
+__END__
+
+=head1 NAME
+
+update-schlittermann-ssh-keys - import public ssh keys from the Schlittermann technician
+
+=head1 SYNOPSIS
+
+B<update-schlittermann-ssh-keys> [OPTION]
+
+ Options:
+ -u, --update update the authorized_keys file
+ -h, --help display this help and exit
+ -m, --man display full documentation
+ -f, --force overwriting backup file
+ --keys-dir the default keys
+
+=head1 DESCRIPION
+
+B<update-schlittermann-ssh-keys> make a backup from F<~/.ssh/authorized_keys> and generate a new file which
+contains the public ssh keys from the Schlittermann technician.
+
+If exists the F<~/.ssh/authorized_keys.local> file, the public ssh keys from
+this file will be appand to the F<~/.ssh/authorized_keys> file too.
+
+=cut
+
+=head1 OPTIONS
+
+=over 8
+
+
+=item B<-u, --update>
+
+import the public ssh keys from the Schlittermann technician and the keys from the F<~/.ssh/authorized_keys.local> file
+
+=item B<-f, --force>
+
+force some actions (e.g. overwriting backup file) (default: 0)
+
+=item B<--keys-dir> I<dir>
+
+The directory where the "default" keys are stored
+(default: F</usr/share/schlittermann-ssh-keys/>)
+
+=item B<-h, --help>
+
+display this help and exit
+
+=item B<-m, --man>
+
+display full documentation
+
+=back
+
+=cut
+
+# vim:ts=4 sts=4 sw=4 aw ai sm: