update-schlittermann-ssh-keys.pl
changeset 0 cc246ac74f0d
child 50 7aeb74df004b
equal deleted inserted replaced
-1:000000000000 0:cc246ac74f0d
       
     1 #! /usr/bin/perl
       
     2 # $Id: update-schlittermann-ssh-keys.pl 4805 2009-12-03 14:39:57Z foerste $
       
     3 # $URL: https://ssl.schlittermann.de/svn/is/schlittermann-ssh-key/trunk/update-schlittermann-ssh-keys.pl $
       
     4 
       
     5 use strict;
       
     6 use warnings;
       
     7 use File::Basename;
       
     8 use File::Copy;
       
     9 use Getopt::Long;
       
    10 use Term::ReadKey;
       
    11 use Pod::Usage;
       
    12 use if $ENV{DEBUG} => "Smart::Comments";
       
    13 
       
    14 my $ME            = basename $0;
       
    15 my $effective_uid = $>;
       
    16 my $home_dir      = (getpwuid $effective_uid)[7];
       
    17 my $opt_update    = 1;
       
    18 my $opt_help      = 0;
       
    19 my $opt_man       = 0;
       
    20 my $opt_keys_dir  = "/usr/share/schlittermann-ssh-keys";
       
    21 my $opt_force     = 0;
       
    22 
       
    23 my $SSHD_CONF       = "/etc/ssh/sshd_config";
       
    24 my $KEYS_DIR        = undef;                              # set later
       
    25 my $SSH_DIR         = "$home_dir/.ssh";
       
    26 my $AUTH_KEYS       = "$SSH_DIR/authorized_keys";
       
    27 my $AUTH_KEYS_LOCAL = "$SSH_DIR/authorized_keys.local";
       
    28 
       
    29 sub read_keys(@) {
       
    30     local @ARGV = grep -f, @_;
       
    31     my %h;
       
    32     if (@ARGV) {
       
    33         while (<>) { chomp; $h{$_} = 1 }
       
    34     }
       
    35     return %h;
       
    36 }
       
    37 
       
    38 MAIN: {
       
    39 
       
    40     GetOptions(
       
    41         "update!"    => \$opt_update,
       
    42         "help!"      => \$opt_help,
       
    43         "man!"       => \$opt_man,
       
    44         "keys-dir=s" => \$opt_keys_dir,
       
    45         "force!"     => \$opt_force,
       
    46     ) or pod2usage(-exitval => 1, -verbose => 0);
       
    47 
       
    48     $KEYS_DIR = $opt_keys_dir;
       
    49 
       
    50     pod2usage(-exitval => 0, -verbose => 0) if $opt_help;
       
    51     pod2usage(-exitval => 0, -verbose => 2) if $opt_man;
       
    52 
       
    53     # update authorized_keys file
       
    54     if ($opt_update) {
       
    55 
       
    56         # checking Schlittermann keys directory
       
    57         -d $KEYS_DIR
       
    58           or die "\n[$KEYS_DIR] doesn't exist.\n\n";
       
    59 
       
    60         # creating .ssh directory if not exists
       
    61         -d $SSH_DIR
       
    62           or mkdir $SSH_DIR, 0700
       
    63           or die "Can't create directory $SSH_DIR: $!\n";
       
    64 
       
    65         # backup authorized_keys file
       
    66         if (-e $AUTH_KEYS) {
       
    67             my $copy = $opt_force || !-e "$AUTH_KEYS.bak";
       
    68             if (!$copy) {
       
    69                 print
       
    70 "\nWARNING: [$AUTH_KEYS.bak] already exists. Overwrite? [yes/N]: ";
       
    71                 chomp(my $input = <STDIN>);
       
    72                 $copy = lc $input eq "yes";
       
    73             }
       
    74             copy($AUTH_KEYS => "$AUTH_KEYS.bak")
       
    75               or die "Can't copy $AUTH_KEYS: $!\n"
       
    76               if $copy;
       
    77         }
       
    78 
       
    79         # read Schlittermann keys
       
    80         my %schlittermann_keys = read_keys(glob("$KEYS_DIR/*"));
       
    81         my %local_keys         = read_keys($AUTH_KEYS_LOCAL);
       
    82         my %auth_keys          = read_keys($AUTH_KEYS);
       
    83 
       
    84         delete @auth_keys{ keys %schlittermann_keys, keys %local_keys };
       
    85 
       
    86         foreach (keys %auth_keys) {    # die noch unbekannten
       
    87             /^(.* ssh-\S+ ).*? (.*)$/ or /^(.{30}).*?(.{30})$/;
       
    88 			print "Keep unknown: " . ((defined $1 and defined $2) ? "$1 ... $2" : $_) . ": [y/N] ";                                                      
       
    89 			ReadMode "cbreak";
       
    90 			my $answer = lc ReadKey;
       
    91 			ReadMode "restore";
       
    92 
       
    93 			$answer = "n" if not $answer eq "y";
       
    94 			print "$answer\n";
       
    95             next if $answer ne "y";
       
    96             $local_keys{$_} = 1;
       
    97         }
       
    98 
       
    99         my $fh;
       
   100         open $fh, ">$AUTH_KEYS_LOCAL"
       
   101           or die "Can't open $AUTH_KEYS_LOCAL: $!\n";
       
   102         print $fh map { "$_\n" } keys %local_keys;
       
   103         close $fh;
       
   104 
       
   105         open $fh, ">$AUTH_KEYS" or die "Can't open $AUTH_KEYS: $!\n";
       
   106         print $fh map { "$_\n" } keys %schlittermann_keys, keys %local_keys;
       
   107         close $fh;
       
   108 
       
   109     }
       
   110 
       
   111     # check /etc/ssh/sshd_config for the keyword PermitUserEnvironment
       
   112     if (open(my $fh, $SSHD_CONF)) {
       
   113         grep { /^\s*PermitUserEnvironment\s+yes/i } <$fh>
       
   114           and print "$SSHD_CONF is ok\n"
       
   115           and exit 0;
       
   116     }
       
   117     else {
       
   118         warn "Can't check $SSHD_CONF: $!\n";
       
   119         exit 0;
       
   120     }
       
   121 
       
   122     warn "PermitUserEnvironment not set!\n";
       
   123 
       
   124     if (open(my $fh, "+<$SSHD_CONF")) {
       
   125         copy($SSHD_CONF => "$SSHD_CONF.bak")
       
   126           or die "Can't copy $SSHD_CONF -> $SSHD_CONF.bak: $!\n";
       
   127         $_ = join "", <$fh>;
       
   128         s/^(\s*PermitUserEnvironment\s+).*$/# modified by $ME:\n$1yes/im
       
   129           or $_ .= "# inserted by $ME:\nPermitUserEnvironment yes\n";
       
   130 
       
   131         seek($fh, 0, 0);
       
   132         print $fh $_;
       
   133         truncate($fh, tell($fh));
       
   134         close($fh) or rename("$SSHD_CONF.bak" => $SSHD_CONF);
       
   135 
       
   136         system("invoke-rc.d ssh reload");
       
   137 
       
   138         exit 0;
       
   139     }
       
   140     else {
       
   141         warn "Can't modify $SSHD_CONF: $!\n";
       
   142     }
       
   143 }
       
   144 
       
   145 __END__
       
   146 
       
   147 =head1 NAME
       
   148 
       
   149 update-schlittermann-ssh-keys - import public ssh keys from the Schlittermann technician
       
   150 
       
   151 =head1 SYNOPSIS
       
   152 
       
   153 B<update-schlittermann-ssh-keys> [OPTION]
       
   154 
       
   155  Options:
       
   156    -u, --update		update the authorized_keys file
       
   157    -h, --help		display this help and exit
       
   158    -m, --man		display full documentation
       
   159    -f, --force		overwriting backup file
       
   160    --keys-dir		the default keys
       
   161 
       
   162 =head1 DESCRIPION
       
   163 
       
   164 B<update-schlittermann-ssh-keys> make a backup from F<~/.ssh/authorized_keys> and generate a new file which
       
   165 contains the public ssh keys from the Schlittermann technician.
       
   166 
       
   167 If exists the F<~/.ssh/authorized_keys.local> file, the public ssh keys from
       
   168 this file will be appand to the F<~/.ssh/authorized_keys> file too.
       
   169 
       
   170 =cut
       
   171 
       
   172 =head1 OPTIONS
       
   173 
       
   174 =over 8
       
   175 
       
   176 
       
   177 =item B<-u, --update>
       
   178 
       
   179 import the public ssh keys from the Schlittermann technician and the keys from the F<~/.ssh/authorized_keys.local> file
       
   180 
       
   181 =item B<-f, --force>
       
   182 
       
   183 force some actions (e.g. overwriting backup file) (default: 0)
       
   184 
       
   185 =item B<--keys-dir> I<dir>
       
   186 
       
   187 The directory where the "default" keys are stored 
       
   188 (default: F</usr/share/schlittermann-ssh-keys/>)
       
   189 
       
   190 =item B<-h, --help>
       
   191 
       
   192 display this help and exit
       
   193 
       
   194 =item B<-m, --man>
       
   195 
       
   196 display full documentation
       
   197 
       
   198 =back
       
   199 
       
   200 =cut
       
   201 
       
   202 # vim:ts=4 sts=4 sw=4 aw ai sm: