#!/bin/sh -e action="$1" oldversion="$2" . /usr/share/debconf/confmodule db_version 2.0 umask 022 get_config_option() { option="$1" [ -f /etc/ssh/sshd_config ] || return # TODO: actually only one '=' allowed after option perl -lne 's/\s+/ /g; print if s/^\s*'"$option"'[[:space:]=]+//i' \ /etc/ssh/sshd_config } set_config_option() { option="$1" value="$2" perl -le ' $option = $ARGV[0]; $value = $ARGV[1]; $done = 0; while () { chomp; (my $match = $_) =~ s/\s+/ /g; if ($match =~ s/^\s*\Q$option\E\s+.*/$option $value/) { $_ = $match; $done = 1; } print; } print "$option $value" unless $done;' \ "$option" "$value" \ < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config } rename_config_option() { oldoption="$1" newoption="$2" value="$(get_config_option "$oldoption")" [ "$value" ] || return 0 perl -le ' $oldoption = $ARGV[0]; $newoption = $ARGV[1]; while () { chomp; (my $match = $_) =~ s/\s+/ /g; # TODO: actually only one "=" allowed after option if ($match =~ s/^(\s*)\Q$oldoption\E([[:space:]=]+)/$1$newoption$2/i) { $_ = $match; } print; }' \ "$oldoption" "$newoption" \ < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config } host_keys_required() { hostkeys="$(get_config_option HostKey)" if [ "$hostkeys" ]; then echo "$hostkeys" else # No HostKey directives at all, so the server picks some # defaults depending on the setting of Protocol. protocol="$(get_config_option Protocol)" [ "$protocol" ] || protocol=1,2 if echo "$protocol" | grep 1 >/dev/null; then echo /etc/ssh/ssh_host_key fi if echo "$protocol" | grep 2 >/dev/null; then echo /etc/ssh/ssh_host_rsa_key echo /etc/ssh/ssh_host_dsa_key echo /etc/ssh/ssh_host_ecdsa_key fi fi } create_key() { msg="$1" shift hostkeys="$1" shift file="$1" shift if echo "$hostkeys" | grep -x "$file" >/dev/null && \ [ ! -f "$file" ] ; then echo -n $msg ssh-keygen -q -f "$file" -N '' "$@" echo if which restorecon >/dev/null 2>&1; then restorecon "$file.pub" fi fi } create_keys() { hostkeys="$(host_keys_required)" create_key "Creating SSH1 key; this may take some time ..." \ "$hostkeys" /etc/ssh/ssh_host_key -t rsa1 create_key "Creating SSH2 RSA key; this may take some time ..." \ "$hostkeys" /etc/ssh/ssh_host_rsa_key -t rsa create_key "Creating SSH2 DSA key; this may take some time ..." \ "$hostkeys" /etc/ssh/ssh_host_dsa_key -t dsa create_key "Creating SSH2 ECDSA key; this may take some time ..." \ "$hostkeys" /etc/ssh/ssh_host_ecdsa_key -t ecdsa } vulnerable_host_keys() { # If the admin has explicitly put the vulnerable keys back, we # assume they can look after themselves. db_fget ssh/vulnerable_host_keys seen if [ "$RET" = true ]; then return 0 fi hostkeys="$(host_keys_required)" vulnerable= for hostkey in $hostkeys; do [ -f "$hostkey" ] || continue if ssh-vulnkey -q "$hostkey"; then vulnerable="${vulnerable:+$vulnerable }$hostkey" fi done if [ "$vulnerable" ]; then db_subst ssh/vulnerable_host_keys HOST_KEYS "$vulnerable" db_input critical ssh/vulnerable_host_keys || true db_go for hostkey in $vulnerable; do mv "$hostkey" "$hostkey.broken" || true mv "$hostkey.pub" "$hostkey.pub.broken" || true done create_keys fi } fix_loglevel_silent() { if [ "$(get_config_option LogLevel)" = SILENT ]; then set_config_option LogLevel QUIET fi } create_sshdconfig() { if [ -e /etc/ssh/sshd_config ] ; then # Upgrade an existing sshd configuration. # This option was renamed in 3.8p1, but we never took care # of adjusting the configuration file until now. if dpkg --compare-versions "$oldversion" lt 1:4.7p1-8; then rename_config_option KeepAlive TCPKeepAlive fi # 'LogLevel SILENT' is now equivalent to QUIET. if dpkg --compare-versions "$oldversion" lt 1:5.4p1-1; then fix_loglevel_silent fi return 0 fi cat < /etc/ssh/sshd_config # Package generated configuration file # See the sshd_config(5) manpage for details # What ports, IPs and protocols we listen for Port 22 # Use these options to restrict which interfaces/protocols sshd will bind to #ListenAddress :: #ListenAddress 0.0.0.0 Protocol 2 # HostKeys for protocol version 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key HostKey /etc/ssh/ssh_host_ecdsa_key #Privilege Separation is turned on for security UsePrivilegeSeparation yes # Lifetime and size of ephemeral version 1 server key KeyRegenerationInterval 3600 ServerKeyBits 768 # Logging SyslogFacility AUTH LogLevel INFO # Authentication: LoginGraceTime 120 PermitRootLogin yes StrictModes yes RSAAuthentication yes PubkeyAuthentication yes #AuthorizedKeysFile %h/.ssh/authorized_keys # Don't read the user's ~/.rhosts and ~/.shosts files IgnoreRhosts yes # For this to work you will also need host keys in /etc/ssh_known_hosts RhostsRSAAuthentication no # similar for protocol version 2 HostbasedAuthentication no # Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication #IgnoreUserKnownHosts yes # To enable empty passwords, change to yes (NOT RECOMMENDED) PermitEmptyPasswords no # Change to yes to enable challenge-response passwords (beware issues with # some PAM modules and threads) ChallengeResponseAuthentication no # Change to no to disable tunnelled clear text passwords #PasswordAuthentication yes # Kerberos options #KerberosAuthentication no #KerberosGetAFSToken no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes X11Forwarding yes X11DisplayOffset 10 PrintMotd no PrintLastLog yes TCPKeepAlive yes #UseLogin no #MaxStartups 10:30:60 #Banner /etc/issue.net # Allow client to pass locale environment variables AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the ChallengeResponseAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via ChallengeResponseAuthentication may bypass # the setting of "PermitRootLogin without-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. UsePAM yes EOF } fix_statoverride() { # Remove an erronous override for sshd (we should have overridden ssh) if [ -x /usr/sbin/dpkg-statoverride ]; then if dpkg-statoverride --list /usr/sbin/sshd >/dev/null ; then dpkg-statoverride --remove /usr/sbin/sshd fi fi } setup_sshd_user() { if ! getent passwd sshd >/dev/null; then adduser --quiet --system --no-create-home --home /var/run/sshd --shell /usr/sbin/nologin sshd fi } remove_old_init_links() { # Yes, this only works with the SysV init script layout. I know. # The important thing is that it doesn't actually *break* with # file-rc ... if [ -e /etc/rc2.d/S20ssh ]; then update-rc.d -f ssh remove >/dev/null 2>&1 fi rm -f /etc/rc0.d/K??ssh /etc/rc1.d/K??ssh /etc/rc6.d/K??ssh } if [ "$action" = configure ]; then create_sshdconfig create_keys vulnerable_host_keys fix_statoverride setup_sshd_user if dpkg --compare-versions "$2" lt 1:5.2p1-1; then remove_old_init_links fi # Renamed to /etc/ssh/moduli in 2.9.9 (!) if dpkg --compare-versions "$2" lt 1:4.7p1-1; then rm -f /etc/ssh/primes fi if dpkg --compare-versions "$2" lt 1:5.5p1-6; then rm -f /var/run/sshd/.placeholder fi # Clean up old debconf templates. db_unregister ssh/use_old_init_script db_unregister ssh/encrypted_host_key_but_no_keygen db_unregister ssh/disable_cr_auth fi #DEBHELPER# db_stop exit 0