1:5.8.1p1-3
[openssh.git] / debian / openssh-server.postinst
1 #!/bin/sh -e
2
3 action="$1"
4 oldversion="$2"
5
6 . /usr/share/debconf/confmodule
7 db_version 2.0
8
9 umask 022
10
11 if [ "$action" != configure ]
12   then
13   exit 0
14 fi
15
16
17 fix_doc_symlink() {
18         if [ ! -L /usr/share/doc/openssh-server ] && \
19            dpkg --compare-versions "$oldversion" lt-nl 1:4.1p1-5; then
20                 rm -rf /usr/share/doc/openssh-server
21                 ln -s openssh-client /usr/share/doc/openssh-server
22         fi
23 }
24
25
26 get_config_option() {
27         option="$1"
28
29         [ -f /etc/ssh/sshd_config ] || return
30
31         # TODO: actually only one '=' allowed after option
32         perl -lne 's/\s+/ /g; print if s/^\s*'"$option"'[[:space:]=]+//i' \
33            /etc/ssh/sshd_config
34 }
35
36
37 set_config_option() {
38         option="$1"
39         value="$2"
40
41         perl -le '
42                 $option = $ARGV[0]; $value = $ARGV[1]; $done = 0;
43                 while (<STDIN>) {
44                         chomp;
45                         (my $match = $_) =~ s/\s+/ /g;
46                         if ($match =~ s/^\s*\Q$option\E\s+.*/$option $value/) {
47                                 $_ = $match;
48                                 $done = 1;
49                         }
50                         print;
51                 }
52                 print "$option $value" unless $done;' \
53                 "$option" "$value" \
54                 < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
55         chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
56         chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
57         mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
58 }
59
60
61 disable_config_option() {
62         option="$1"
63
64         value="$(get_config_option "$option")"
65         [ "$value" ] || return 0
66
67         perl -le '
68                 $option = $ARGV[0];
69                 while (<STDIN>) {
70                         chomp;
71                         (my $match = $_) =~ s/\s+/ /g;
72                         # TODO: actually only one "=" allowed after option
73                         if ($match =~ s/^(\s*\Q$option\E[[:space:]=]+.*)/#$1/i) {
74                                 $_ = $match;
75                         }
76                         print;
77                 }' \
78                 "$option" \
79                 < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
80         chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
81         chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
82         mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
83 }
84
85
86 rename_config_option() {
87         oldoption="$1"
88         newoption="$2"
89
90         value="$(get_config_option "$oldoption")"
91         [ "$value" ] || return 0
92
93         perl -le '
94                 $oldoption = $ARGV[0]; $newoption = $ARGV[1];
95                 while (<STDIN>) {
96                         chomp;
97                         (my $match = $_) =~ s/\s+/ /g;
98                         # TODO: actually only one "=" allowed after option
99                         if ($match =~ s/^(\s*)\Q$oldoption\E([[:space:]=]+)/$1$newoption$2/i) {
100                                 $_ = $match;
101                         }
102                         print;
103                 }' \
104                 "$oldoption" "$newoption" \
105                 < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
106         chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
107         chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
108         mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
109 }
110
111
112 remove_obsolete_gssapi() {
113         disable_config_option GSSAPINoMICAuthentication
114         disable_config_option GSSUseSessionCCache
115         disable_config_option GSSAPIUseSessionCredCache
116 }
117
118
119 host_keys_required() {
120         hostkeys="$(get_config_option HostKey)"
121         if [ "$hostkeys" ]; then
122                 echo "$hostkeys"
123         else
124                 # No HostKey directives at all, so the server picks some
125                 # defaults depending on the setting of Protocol.
126                 protocol="$(get_config_option Protocol)"
127                 [ "$protocol" ] || protocol=1,2
128                 if echo "$protocol" | grep 1 >/dev/null; then
129                         echo /etc/ssh/ssh_host_key
130                 fi
131                 if echo "$protocol" | grep 2 >/dev/null; then
132                         echo /etc/ssh/ssh_host_rsa_key
133                         echo /etc/ssh/ssh_host_dsa_key
134                         echo /etc/ssh/ssh_host_ecdsa_key
135                 fi
136         fi
137 }
138
139
140 create_key() {
141         msg="$1"
142         shift
143         hostkeys="$1"
144         shift
145         file="$1"
146         shift
147
148         if echo "$hostkeys" | grep -x "$file" >/dev/null && \
149            [ ! -f "$file" ] ; then
150                 echo -n $msg
151                 ssh-keygen -q -f "$file" -N '' "$@"
152                 echo
153                 if which restorecon >/dev/null 2>&1; then
154                         restorecon "$file.pub"
155                 fi
156         fi
157 }
158
159
160 create_keys() {
161         hostkeys="$(host_keys_required)"
162
163         create_key "Creating SSH1 key; this may take some time ..." \
164                 "$hostkeys" /etc/ssh/ssh_host_key -t rsa1
165
166         create_key "Creating SSH2 RSA key; this may take some time ..." \
167                 "$hostkeys" /etc/ssh/ssh_host_rsa_key -t rsa
168         create_key "Creating SSH2 DSA key; this may take some time ..." \
169                 "$hostkeys" /etc/ssh/ssh_host_dsa_key -t dsa
170         create_key "Creating SSH2 ECDSA key; this may take some time ..." \
171                 "$hostkeys" /etc/ssh/ssh_host_ecdsa_key -t ecdsa
172 }
173
174
175 vulnerable_host_keys() {
176         # If the admin has explicitly put the vulnerable keys back, we
177         # assume they can look after themselves.
178         db_fget ssh/vulnerable_host_keys seen
179         if [ "$RET" = true ]; then
180                 return 0
181         fi
182
183         hostkeys="$(host_keys_required)"
184         vulnerable=
185         for hostkey in $hostkeys; do
186                 [ -f "$hostkey" ] || continue
187                 if ssh-vulnkey -q "$hostkey"; then
188                         vulnerable="${vulnerable:+$vulnerable }$hostkey"
189                 fi
190         done
191         if [ "$vulnerable" ]; then
192                 db_subst ssh/vulnerable_host_keys HOST_KEYS "$vulnerable"
193                 db_input critical ssh/vulnerable_host_keys || true
194                 db_go
195                 for hostkey in $vulnerable; do
196                         mv "$hostkey" "$hostkey.broken" || true
197                         mv "$hostkey.pub" "$hostkey.pub.broken" || true
198                 done
199                 create_keys
200         fi
201 }
202
203
204 check_password_auth() {
205         passwordauth="$(get_config_option PasswordAuthentication)"
206         crauth="$(get_config_option ChallengeResponseAuthentication)"
207         if [ "$passwordauth" = no ] && \
208            ([ -z "$crauth" ] || [ "$crauth" = yes ]); then
209                 db_get ssh/disable_cr_auth
210                 if [ "$RET" = true ]; then
211                         set_config_option ChallengeResponseAuthentication no
212                 fi
213         fi
214 }
215
216
217 move_subsystem_sftp() {
218         subsystem_sftp="$(get_config_option 'Subsystem sftp')"
219         if [ "$subsystem_sftp" = /usr/lib/sftp-server ] || \
220            [ "$subsystem_sftp" = /usr/libexec/sftp-server ]; then
221                 set_config_option 'Subsystem sftp' /usr/lib/openssh/sftp-server
222         fi
223 }
224
225
226 fix_loglevel_silent() {
227         if [ "$(get_config_option LogLevel)" = SILENT ]; then
228                 set_config_option LogLevel QUIET
229         fi
230 }
231
232
233 create_sshdconfig() {
234         if [ -e /etc/ssh/sshd_config ] ; then
235             # Upgrade an existing sshd configuration.
236
237             if (dpkg --compare-versions "$oldversion" lt-nl 1:3.8p1-1 && \
238                 ! grep -iq ^UsePAM /etc/ssh/sshd_config) || \
239                grep -Eiq '^(PAMAuthenticationViaKbdInt|RhostsAuthentication)' \
240                  /etc/ssh/sshd_config ; then
241                 # Upgrade from pre-3.7: UsePAM needed to maintain standard
242                 # Debian configuration.
243                 # Note that --compare-versions is sadly not reliable enough
244                 # here due to the package split of ssh into openssh-client
245                 # and openssh-server. The extra grep for some deprecated
246                 # options should with any luck be a good enough heuristic.
247                 echo -n 'Upgrading sshd_config (old version in .dpkg-old) ...'
248                 cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-old
249                 perl -pe 's/^(PAMAuthenticationViaKbdInt|RhostsAuthentication)\b/#$1/i' \
250                     /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
251                 echo >> /etc/ssh/sshd_config.dpkg-new
252                 echo 'UsePAM yes' >> /etc/ssh/sshd_config.dpkg-new
253                 chown --reference /etc/ssh/sshd_config \
254                                   /etc/ssh/sshd_config.dpkg-new
255                 chmod --reference /etc/ssh/sshd_config \
256                                   /etc/ssh/sshd_config.dpkg-new
257                 mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
258                 echo
259             fi
260
261             # An empty version means we're upgrading from before the
262             # package split, so check.
263             if dpkg --compare-versions "$oldversion" lt 1:3.8.1p1-11; then
264                 check_password_auth
265             fi
266
267             # libexecdir changed, so fix up 'Subsystem sftp'.
268             if dpkg --compare-versions "$oldversion" lt 1:4.1p1-1; then
269                 move_subsystem_sftp
270             fi
271
272             # Remove obsolete GSSAPI options.
273             if dpkg --compare-versions "$oldversion" lt 1:4.3p2-8; then
274                 remove_obsolete_gssapi
275             fi
276
277             # This option was renamed in 3.8p1, but we never took care
278             # of adjusting the configuration file until now.
279             if dpkg --compare-versions "$oldversion" lt 1:4.7p1-8; then
280                 rename_config_option KeepAlive TCPKeepAlive
281             fi
282
283             # 'LogLevel SILENT' is now equivalent to QUIET.
284             if dpkg --compare-versions "$oldversion" lt 1:5.4p1-1; then
285                 fix_loglevel_silent
286             fi
287
288             return 0
289         fi
290
291         #Preserve old sshd_config before generating a new one
292         if [ -e /etc/ssh/sshd_config ] ; then 
293             mv /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-old
294         fi
295
296         cat <<EOF > /etc/ssh/sshd_config
297 # Package generated configuration file
298 # See the sshd_config(5) manpage for details
299
300 # What ports, IPs and protocols we listen for
301 Port 22
302 # Use these options to restrict which interfaces/protocols sshd will bind to
303 #ListenAddress ::
304 #ListenAddress 0.0.0.0
305 Protocol 2
306 # HostKeys for protocol version 2
307 HostKey /etc/ssh/ssh_host_rsa_key
308 HostKey /etc/ssh/ssh_host_dsa_key
309 HostKey /etc/ssh/ssh_host_ecdsa_key
310 #Privilege Separation is turned on for security
311 UsePrivilegeSeparation yes
312
313 # Lifetime and size of ephemeral version 1 server key
314 KeyRegenerationInterval 3600
315 ServerKeyBits 768
316
317 # Logging
318 SyslogFacility AUTH
319 LogLevel INFO
320
321 # Authentication:
322 LoginGraceTime 120
323 PermitRootLogin yes
324 StrictModes yes
325
326 RSAAuthentication yes
327 PubkeyAuthentication yes
328 #AuthorizedKeysFile     %h/.ssh/authorized_keys
329
330 # Don't read the user's ~/.rhosts and ~/.shosts files
331 IgnoreRhosts yes
332 # For this to work you will also need host keys in /etc/ssh_known_hosts
333 RhostsRSAAuthentication no
334 # similar for protocol version 2
335 HostbasedAuthentication no
336 # Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
337 #IgnoreUserKnownHosts yes
338
339 # To enable empty passwords, change to yes (NOT RECOMMENDED)
340 PermitEmptyPasswords no
341
342 # Change to yes to enable challenge-response passwords (beware issues with
343 # some PAM modules and threads)
344 ChallengeResponseAuthentication no
345
346 # Change to no to disable tunnelled clear text passwords
347 #PasswordAuthentication yes
348
349 # Kerberos options
350 #KerberosAuthentication no
351 #KerberosGetAFSToken no
352 #KerberosOrLocalPasswd yes
353 #KerberosTicketCleanup yes
354
355 # GSSAPI options
356 #GSSAPIAuthentication no
357 #GSSAPICleanupCredentials yes
358
359 X11Forwarding yes
360 X11DisplayOffset 10
361 PrintMotd no
362 PrintLastLog yes
363 TCPKeepAlive yes
364 #UseLogin no
365
366 #MaxStartups 10:30:60
367 #Banner /etc/issue.net
368
369 # Allow client to pass locale environment variables
370 AcceptEnv LANG LC_*
371
372 Subsystem sftp /usr/lib/openssh/sftp-server
373
374 # Set this to 'yes' to enable PAM authentication, account processing,
375 # and session processing. If this is enabled, PAM authentication will
376 # be allowed through the ChallengeResponseAuthentication and
377 # PasswordAuthentication.  Depending on your PAM configuration,
378 # PAM authentication via ChallengeResponseAuthentication may bypass
379 # the setting of "PermitRootLogin without-password".
380 # If you just want the PAM account and session checks to run without
381 # PAM authentication, then enable this but set PasswordAuthentication
382 # and ChallengeResponseAuthentication to 'no'.
383 UsePAM yes
384 EOF
385 }
386
387 fix_statoverride() {
388 # Remove an erronous override for sshd (we should have overridden ssh)
389         if [ -x /usr/sbin/dpkg-statoverride ]; then
390                 if dpkg-statoverride --list /usr/sbin/sshd >/dev/null ; then
391                         dpkg-statoverride --remove /usr/sbin/sshd
392                 fi
393         fi
394 }
395
396 fix_sshd_shell() {
397         if getent passwd sshd | grep -q ':/bin/false$'; then
398                 usermod -s /usr/sbin/nologin sshd || true
399         fi
400 }
401
402 setup_sshd_user() {
403         if ! getent passwd sshd >/dev/null; then
404                 adduser --quiet --system --no-create-home --home /var/run/sshd --shell /usr/sbin/nologin sshd
405         fi
406 }
407
408 fix_conffile_permissions() {
409         # Clean up after executable /etc/default/ssh in 1:3.5p1-5. dpkg
410         # doesn't do this for us; see bug #192981.
411         chmod 644 /etc/default/ssh
412 }
413
414 remove_old_init_links() {
415         # Yes, this only works with the SysV init script layout. I know.
416         # The important thing is that it doesn't actually *break* with
417         # file-rc ...
418         if [ -e /etc/rc2.d/S20ssh ]; then
419                 update-rc.d -f ssh remove >/dev/null 2>&1
420         fi
421         rm -f /etc/rc0.d/K??ssh /etc/rc1.d/K??ssh /etc/rc6.d/K??ssh
422 }
423
424 setup_init() {
425         if [ -x /etc/init.d/ssh ]; then
426                 update-rc.d ssh start 16 2 3 4 5 . >/dev/null
427                 if [ -x /usr/sbin/invoke-rc.d ]; then
428                         invoke-rc.d ssh restart
429                 else
430                         /etc/init.d/ssh restart
431                 fi
432         fi
433 }
434
435 commit_transfer_conffile () {
436         CONFFILE="$1"
437         if [ -e "$CONFFILE.moved-by-preinst" ]; then
438                 rm -f "$CONFFILE.moved-by-preinst"
439         fi
440 }
441
442 commit_mv_conffile () {
443         OLDCONFFILE="$1"
444         NEWCONFFILE="$2"
445
446         if [ -e "$OLDCONFFILE.moving" ]; then
447                 echo "Preserving user changes to $NEWCONFFILE ..."
448                 mv -f "$NEWCONFFILE" "$NEWCONFFILE.dpkg-new"
449                 mv -f "$OLDCONFFILE.moving" "$NEWCONFFILE"
450         elif [ -e "$OLDCONFFILE.dpkg-old" ]; then
451                 rm -f "$OLDCONFFILE.dpkg-old"
452         fi
453 }
454
455
456 fix_doc_symlink
457 create_sshdconfig
458 create_keys
459 vulnerable_host_keys
460 fix_statoverride
461 if dpkg --compare-versions "$2" lt 1:4.3p2-3; then
462     fix_sshd_shell
463 fi
464 setup_sshd_user
465 if dpkg --compare-versions "$2" lt 1:3.6.1p2-2; then
466     fix_conffile_permissions
467 fi
468 if dpkg --compare-versions "$2" lt 1:5.2p1-1; then
469     remove_old_init_links
470 fi
471 setup_init
472 commit_transfer_conffile /etc/default/ssh
473 commit_transfer_conffile /etc/init.d/ssh
474 commit_transfer_conffile /etc/pam.d/ssh
475 commit_mv_conffile /etc/pam.d/ssh /etc/pam.d/sshd
476 # Renamed to /etc/ssh/moduli in 2.9.9 (!)
477 if dpkg --compare-versions "$2" lt 1:4.7p1-1; then
478     rm -f /etc/ssh/primes
479 fi
480 if dpkg --compare-versions "$2" lt 1:5.5p1-6; then
481     rm -f /var/run/sshd/.placeholder
482 fi
483
484
485 db_stop
486
487 exit 0