|
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: |