ssh-host-config revision 295367
1#!/bin/bash
2#
3# ssh-host-config, Copyright 2000-2014 Red Hat Inc.
4#
5# This file is part of the Cygwin port of OpenSSH.
6#
7# Permission to use, copy, modify, and distribute this software for any
8# purpose with or without fee is hereby granted, provided that the above
9# copyright notice and this permission notice appear in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  
12# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               
13# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   
14# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   
15# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    
16# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    
17# THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               
18
19# ======================================================================
20# Initialization
21# ======================================================================
22
23CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh
24
25# List of apps used.  This is checkad for existance in csih_sanity_check
26# Don't use *any* transient commands before sourcing the csih helper script,
27# otherwise the sanity checks are short-circuited.
28declare -a csih_required_commands=(
29  /usr/bin/basename coreutils
30  /usr/bin/cat coreutils
31  /usr/bin/chmod coreutils
32  /usr/bin/dirname coreutils
33  /usr/bin/id coreutils
34  /usr/bin/mv coreutils
35  /usr/bin/rm coreutils
36  /usr/bin/cygpath cygwin
37  /usr/bin/mkpasswd cygwin
38  /usr/bin/mount cygwin
39  /usr/bin/ps cygwin
40  /usr/bin/umount cygwin
41  /usr/bin/cmp diffutils
42  /usr/bin/grep grep
43  /usr/bin/awk gawk
44  /usr/bin/ssh-keygen openssh
45  /usr/sbin/sshd openssh
46  /usr/bin/sed sed
47)
48csih_sanity_check_server=yes
49source ${CSIH_SCRIPT}
50
51PROGNAME=$(/usr/bin/basename $0)
52_tdir=$(/usr/bin/dirname $0)
53PROGDIR=$(cd $_tdir && pwd)
54
55# Subdirectory where the new package is being installed
56PREFIX=/usr
57
58# Directory where the config files are stored
59SYSCONFDIR=/etc
60LOCALSTATEDIR=/var
61
62sshd_config_configured=no
63port_number=22
64service_name=sshd
65strictmodes=yes
66privsep_used=yes
67cygwin_value=""
68user_account=
69password_value=
70opt_force=no
71
72# ======================================================================
73# Routine: update_services_file
74# ======================================================================
75update_services_file() {
76  local _my_etcdir="/ssh-host-config.$$"
77  local _win_etcdir
78  local _services
79  local _spaces
80  local _serv_tmp
81  local _wservices
82  local ret=0
83
84  _win_etcdir="${SYSTEMROOT}\\system32\\drivers\\etc"
85  _services="${_my_etcdir}/services"
86  _spaces="                           #"
87  _serv_tmp="${_my_etcdir}/srv.out.$$"
88
89  /usr/bin/mount -o text,posix=0,noacl -f "${_win_etcdir}" "${_my_etcdir}"
90
91  # Depends on the above mount
92  _wservices=`cygpath -w "${_services}"`
93
94  # Add ssh 22/tcp  and ssh 22/udp to services
95  if [ `/usr/bin/grep -q 'ssh[[:space:]][[:space:]]*22' "${_services}"; echo $?` -ne 0 ]
96  then
97    if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh                22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh                22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}"
98    then
99      if /usr/bin/mv "${_serv_tmp}" "${_services}"
100      then
101	csih_inform "Added ssh to ${_wservices}"
102      else
103	csih_warning "Adding ssh to ${_wservices} failed!"
104	let ++ret
105      fi
106      /usr/bin/rm -f "${_serv_tmp}"
107    else
108      csih_warning "Adding ssh to ${_wservices} failed!"
109      let ++ret
110    fi
111  fi
112  /usr/bin/umount "${_my_etcdir}"
113  return $ret
114} # --- End of update_services_file --- #
115
116# ======================================================================
117# Routine: sshd_strictmodes
118#  MODIFIES: strictmodes
119# ======================================================================
120sshd_strictmodes() {
121  if [ "${sshd_config_configured}" != "yes" ]
122  then
123    echo
124    csih_inform "StrictModes is set to 'yes' by default."
125    csih_inform "This is the recommended setting, but it requires that the POSIX"
126    csih_inform "permissions of the user's home directory, the user's .ssh"
127    csih_inform "directory, and the user's ssh key files are tight so that"
128    csih_inform "only the user has write permissions."
129    csih_inform "On the other hand, StrictModes don't work well with default"
130    csih_inform "Windows permissions of a home directory mounted with the"
131    csih_inform "'noacl' option, and they don't work at all if the home"
132    csih_inform "directory is on a FAT or FAT32 partition."
133    if ! csih_request "Should StrictModes be used?"
134    then
135      strictmodes=no
136    fi
137  fi
138  return 0
139}
140
141# ======================================================================
142# Routine: sshd_privsep
143#  MODIFIES: privsep_used
144# ======================================================================
145sshd_privsep() {
146  local ret=0
147
148  if [ "${sshd_config_configured}" != "yes" ]
149  then
150    echo
151    csih_inform "Privilege separation is set to 'sandbox' by default since"
152    csih_inform "OpenSSH 6.1.  This is unsupported by Cygwin and has to be set"
153    csih_inform "to 'yes' or 'no'."
154    csih_inform "However, using privilege separation requires a non-privileged account"
155    csih_inform "called 'sshd'."
156    csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep."
157    if csih_request "Should privilege separation be used?"
158    then
159      privsep_used=yes
160      if ! csih_create_unprivileged_user sshd
161      then
162	csih_error_recoverable "Couldn't create user 'sshd'!"
163	csih_error_recoverable "Privilege separation set to 'no' again!"
164	csih_error_recoverable "Check your ${SYSCONFDIR}/sshd_config file!"
165	let ++ret
166	privsep_used=no
167      fi
168    else
169      privsep_used=no
170    fi
171  fi
172  return $ret
173} # --- End of sshd_privsep --- #
174
175# ======================================================================
176# Routine: sshd_config_tweak
177# ======================================================================
178sshd_config_tweak() {
179  local ret=0
180
181  # Modify sshd_config
182  csih_inform "Updating ${SYSCONFDIR}/sshd_config file"
183  if [ "${port_number}" -ne 22 ]
184  then
185    /usr/bin/sed -i -e "s/^#\?[[:space:]]*Port[[:space:]].*/Port ${port_number}/" \
186      ${SYSCONFDIR}/sshd_config
187    if [ $? -ne 0 ]
188    then
189      csih_warning "Setting listening port to ${port_number} failed!"
190      csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
191      let ++ret
192    fi
193  fi
194  if [ "${strictmodes}" = "no" ]
195  then
196    /usr/bin/sed -i -e "s/^#\?[[:space:]]*StrictModes[[:space:]].*/StrictModes no/" \
197      ${SYSCONFDIR}/sshd_config
198    if [ $? -ne 0 ]
199    then
200      csih_warning "Setting StrictModes to 'no' failed!"
201      csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
202      let ++ret
203    fi
204  fi
205  if [ "${sshd_config_configured}" != "yes" ]
206  then
207    /usr/bin/sed -i -e "
208      s/^#\?UsePrivilegeSeparation .*/UsePrivilegeSeparation ${privsep_used}/" \
209      ${SYSCONFDIR}/sshd_config
210    if [ $? -ne 0 ]
211    then
212      csih_warning "Setting privilege separation failed!"
213      csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
214      let ++ret
215    fi
216  fi
217  return $ret
218} # --- End of sshd_config_tweak --- #
219
220# ======================================================================
221# Routine: update_inetd_conf
222# ======================================================================
223update_inetd_conf() {
224  local _inetcnf="${SYSCONFDIR}/inetd.conf"
225  local _inetcnf_tmp="${SYSCONFDIR}/inetd.conf.$$"
226  local _inetcnf_dir="${SYSCONFDIR}/inetd.d"
227  local _sshd_inetd_conf="${_inetcnf_dir}/sshd-inetd"
228  local _sshd_inetd_conf_tmp="${_inetcnf_dir}/sshd-inetd.$$"
229  local _with_comment=1
230  local ret=0
231
232  if [ -d "${_inetcnf_dir}" ]
233  then
234    # we have inetutils-1.5 inetd.d support
235    if [ -f "${_inetcnf}" ]
236    then
237      /usr/bin/grep -q '^[[:space:]]*ssh' "${_inetcnf}" && _with_comment=0
238
239      # check for sshd OR ssh in top-level inetd.conf file, and remove
240      # will be replaced by a file in inetd.d/
241      if [ $(/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?) -eq 0 ]
242      then
243	/usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}"
244	if [ -f "${_inetcnf_tmp}" ]
245	then
246	  if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}"
247	  then
248  	    csih_inform "Removed ssh[d] from ${_inetcnf}"
249	  else
250  	    csih_warning "Removing ssh[d] from ${_inetcnf} failed!"
251	    let ++ret
252	  fi
253	  /usr/bin/rm -f "${_inetcnf_tmp}"
254	else
255	  csih_warning "Removing ssh[d] from ${_inetcnf} failed!"
256	  let ++ret
257	fi
258      fi
259    fi
260
261    csih_install_config "${_sshd_inetd_conf}"   "${SYSCONFDIR}/defaults"
262    if /usr/bin/cmp "${SYSCONFDIR}/defaults${_sshd_inetd_conf}" "${_sshd_inetd_conf}" >/dev/null 2>&1
263    then
264      if [ "${_with_comment}" -eq 0 ]
265      then
266	/usr/bin/sed -e 's/@COMMENT@[[:space:]]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}"
267      else
268	/usr/bin/sed -e 's/@COMMENT@[[:space:]]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}"
269      fi
270      if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}"
271      then
272	csih_inform "Updated ${_sshd_inetd_conf}"
273      else
274	csih_warning "Updating ${_sshd_inetd_conf} failed!"
275	let ++ret
276      fi
277    fi
278
279  elif [ -f "${_inetcnf}" ]
280  then
281    /usr/bin/grep -q '^[[:space:]]*sshd' "${_inetcnf}" && _with_comment=0
282
283    # check for sshd in top-level inetd.conf file, and remove
284    # will be replaced by a file in inetd.d/
285    if [ `/usr/bin/grep -q '^#\?[[:space:]]*sshd' "${_inetcnf}"; echo $?` -eq 0 ]
286    then
287      /usr/bin/grep -v '^#\?[[:space:]]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}"
288      if [ -f "${_inetcnf_tmp}" ]
289      then
290	if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}"
291	then
292	    csih_inform "Removed sshd from ${_inetcnf}"
293	else
294	    csih_warning "Removing sshd from ${_inetcnf} failed!"
295	    let ++ret
296	fi
297	/usr/bin/rm -f "${_inetcnf_tmp}"
298      else
299	csih_warning "Removing sshd from ${_inetcnf} failed!"
300	let ++ret
301      fi
302    fi
303
304    # Add ssh line to inetd.conf
305    if [ `/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -ne 0 ]
306    then
307      if [ "${_with_comment}" -eq 0 ]
308      then
309	echo 'ssh  stream  tcp     nowait  root    /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
310      else
311	echo '# ssh  stream  tcp     nowait  root    /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
312      fi
313      if [ $? -eq 0 ]
314      then
315	csih_inform "Added ssh to ${_inetcnf}"
316      else
317	csih_warning "Adding ssh to ${_inetcnf} failed!"
318	let ++ret
319      fi
320    fi
321  fi
322  return $ret
323} # --- End of update_inetd_conf --- #
324
325# ======================================================================
326# Routine: check_service_files_ownership
327#   Checks that the files in /etc and /var belong to the right owner
328# ======================================================================
329check_service_files_ownership() {
330  local run_service_as=$1
331  local ret=0
332
333  if [ -z "${run_service_as}" ]
334  then
335    accnt_name=$(/usr/bin/cygrunsrv -VQ sshd |
336    		 /usr/bin/sed -ne 's/^Account *: *//gp')
337    if [ "${accnt_name}" = "LocalSystem" ]
338    then
339      # Convert "LocalSystem" to "SYSTEM" as is the correct account name
340      run_service_as="SYSTEM"
341    else
342      dom="${accnt_name%%\\*}"
343      accnt_name="${accnt_name#*\\}"
344      if [ "${dom}" = '.' ]
345      then
346	# Check local account
347	run_service_as=$(/usr/bin/mkpasswd -l -u "${accnt_name}" |
348			 /usr/bin/awk -F: '{print $1;}')
349      else
350      	# Check domain
351	run_service_as=$(/usr/bin/mkpasswd -d "${dom}" -u "${accnt_name}" |
352			 /usr/bin/awk -F: '{print $1;}')
353      fi
354    fi
355    if [ -z "${run_service_as}" ]
356    then
357      csih_warning "Couldn't determine name of user running sshd service from account database!"
358      csih_warning "As a result, this script cannot make sure that the files used"
359      csih_warning "by the sshd service belong to the user running the service."
360      return 1
361    fi
362  fi
363  for i in "${SYSCONFDIR}"/ssh_config "${SYSCONFDIR}"/sshd_config "${SYSCONFDIR}"/ssh_host_*key "${SYSCONFDIR}"/ssh_host_*key.pub
364  do
365    if [ -f "$i" ]
366    then
367      if ! chown "${run_service_as}".544 "$i" >/dev/null 2>&1
368      then
369	csih_warning "Couldn't change owner of $i!"
370	let ++ret
371      fi
372    fi
373  done
374  if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/empty >/dev/null 2>&1
375  then
376    csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/empty!"
377    let ++ret
378  fi
379  if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/log/lastlog >/dev/null 2>&1
380  then
381    csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/log/lastlog!"
382    let ++ret
383  fi
384  if [ -f ${LOCALSTATEDIR}/log/sshd.log ]
385  then
386    if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/log/sshd.log >/dev/null 2>&1
387    then
388      csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/log/sshd.log!"
389      let ++ret
390    fi
391  fi
392  if [ $ret -ne 0 ]
393  then
394    csih_warning "Couldn't change owner of important files to ${run_service_as}!"
395    csih_warning "This may cause the sshd service to fail!  Please make sure that"
396    csih_warning "you have suufficient permissions to change the ownership of files"
397    csih_warning "and try to run the ssh-host-config script again."
398  fi
399  return $ret
400} # --- End of check_service_files_ownership --- #
401
402# ======================================================================
403# Routine: install_service
404#   Install sshd as a service
405# ======================================================================
406install_service() {
407  local run_service_as
408  local password
409  local ret=0
410
411  echo
412  if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1
413  then
414    csih_inform "Sshd service is already installed."
415    check_service_files_ownership "" || let ret+=$?
416  else
417    echo -e "${_csih_QUERY_STR} Do you want to install sshd as a service?"
418    if csih_request "(Say \"no\" if it is already installed as a service)"
419    then
420      csih_get_cygenv "${cygwin_value}"
421
422      if ( csih_is_nt2003 || [ "$csih_FORCE_PRIVILEGED_USER" = "yes" ] )
423      then
424	csih_inform "On Windows Server 2003, Windows Vista, and above, the"
425	csih_inform "SYSTEM account cannot setuid to other users -- a capability"
426	csih_inform "sshd requires.  You need to have or to create a privileged"
427	csih_inform "account.  This script will help you do so."
428	echo
429
430	[ "${opt_force}" = "yes" ] && opt_f=-f
431	[ -n "${user_account}" ] && opt_u="-u ""${user_account}"""
432	csih_select_privileged_username ${opt_f} ${opt_u} sshd
433
434	if ! csih_create_privileged_user "${password_value}"
435	then
436	  csih_error_recoverable "There was a serious problem creating a privileged user."
437	  csih_request "Do you want to proceed anyway?" || exit 1
438	  let ++ret
439	fi
440      fi
441
442      # Never returns empty if NT or above
443      run_service_as=$(csih_service_should_run_as)
444
445      if [ "${run_service_as}" = "${csih_PRIVILEGED_USERNAME}" ]
446      then
447	password="${csih_PRIVILEGED_PASSWORD}"
448	if [ -z "${password}" ]
449	then
450	  csih_get_value "Please enter the password for user '${run_service_as}':" "-s"
451	  password="${csih_value}"
452	fi
453      fi
454
455      # At this point, we either have $run_service_as = "system" and
456      # $password is empty, or $run_service_as is some privileged user and
457      # (hopefully) $password contains the correct password.  So, from here
458      # out, we use '-z "${password}"' to discriminate the two cases.
459
460      csih_check_user "${run_service_as}"
461
462      if [ -n "${csih_cygenv}" ]
463      then
464	cygwin_env=( -e "CYGWIN=${csih_cygenv}" )
465      fi
466      if [ -z "${password}" ]
467      then
468	if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \
469			      -a "-D" -y tcpip "${cygwin_env[@]}"
470	then
471	  echo
472	  csih_inform "The sshd service has been installed under the LocalSystem"
473	  csih_inform "account (also known as SYSTEM). To start the service now, call"
474	  csih_inform "\`net start sshd' or \`cygrunsrv -S sshd'.  Otherwise, it"
475	  csih_inform "will start automatically after the next reboot."
476	fi
477      else
478	if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \
479			      -a "-D" -y tcpip "${cygwin_env[@]}" \
480			      -u "${run_service_as}" -w "${password}"
481	then
482	  /usr/bin/editrights -u "${run_service_as}" -a SeServiceLogonRight
483	  echo
484	  csih_inform "The sshd service has been installed under the '${run_service_as}'"
485	  csih_inform "account.  To start the service now, call \`net start ${service_name}' or"
486	  csih_inform "\`cygrunsrv -S ${service_name}'.  Otherwise, it will start automatically"
487	  csih_inform "after the next reboot."
488	fi
489      fi
490
491      if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1
492      then
493	check_service_files_ownership "${run_service_as}" || let ret+=$?
494      else
495	csih_error_recoverable "Installing sshd as a service failed!"
496	let ++ret
497      fi
498    fi # user allowed us to install as service
499  fi # service not yet installed
500  return $ret
501} # --- End of install_service --- #
502
503# ======================================================================
504# Main Entry Point
505# ======================================================================
506
507# Check how the script has been started.  If
508#   (1) it has been started by giving the full path and
509#       that path is /etc/postinstall, OR
510#   (2) Otherwise, if the environment variable
511#       SSH_HOST_CONFIG_AUTO_ANSWER_NO is set
512# then set auto_answer to "no".  This allows automatic
513# creation of the config files in /etc w/o overwriting
514# them if they already exist.  In both cases, color
515# escape sequences are suppressed, so as to prevent
516# cluttering setup's logfiles.
517if [ "$PROGDIR" = "/etc/postinstall" ]
518then
519  csih_auto_answer="no"
520  csih_disable_color
521  opt_force=yes
522fi
523if [ -n "${SSH_HOST_CONFIG_AUTO_ANSWER_NO}" ]
524then
525  csih_auto_answer="no"
526  csih_disable_color
527  opt_force=yes
528fi
529
530# ======================================================================
531# Parse options
532# ======================================================================
533while :
534do
535  case $# in
536  0)
537    break
538    ;;
539  esac
540
541  option=$1
542  shift
543
544  case "${option}" in
545  -d | --debug )
546    set -x
547    csih_trace_on
548    ;;
549
550  -y | --yes )
551    csih_auto_answer=yes
552    opt_force=yes
553    ;;
554
555  -n | --no )
556    csih_auto_answer=no
557    opt_force=yes
558    ;;
559
560  -c | --cygwin )
561    cygwin_value="$1"
562    shift
563    ;;
564
565  -N | --name )
566    service_name=$1
567    shift
568    ;;
569
570  -p | --port )
571    port_number=$1
572    shift
573    ;;
574
575  -u | --user )
576    user_account="$1"
577    shift
578    ;;
579    
580  -w | --pwd )
581    password_value="$1"
582    shift
583    ;;
584
585  --privileged )
586    csih_FORCE_PRIVILEGED_USER=yes
587    ;;
588
589  *)
590    echo "usage: ${progname} [OPTION]..."
591    echo
592    echo "This script creates an OpenSSH host configuration."
593    echo
594    echo "Options:"
595    echo "  --debug  -d            Enable shell's debug output."
596    echo "  --yes    -y            Answer all questions with \"yes\" automatically."
597    echo "  --no     -n            Answer all questions with \"no\" automatically."
598    echo "  --cygwin -c <options>  Use \"options\" as value for CYGWIN environment var."
599    echo "  --name   -N <name>     sshd windows service name."
600    echo "  --port   -p <n>        sshd listens on port n."
601    echo "  --user   -u <account>  privileged user for service, default 'cyg_server'."
602    echo "  --pwd    -w <passwd>   Use \"pwd\" as password for privileged user."
603    echo "  --privileged           On Windows XP, require privileged user"
604    echo "                         instead of LocalSystem for sshd service."
605    echo
606    exit 1
607    ;;
608
609  esac
610done
611
612# ======================================================================
613# Action!
614# ======================================================================
615
616# Check for running ssh/sshd processes first. Refuse to do anything while
617# some ssh processes are still running
618if /usr/bin/ps -ef | /usr/bin/grep -q '/sshd\?$'
619then
620  echo
621  csih_error "There are still ssh processes running. Please shut them down first."
622fi
623
624# Make sure the user is running in an administrative context
625admin=$(/usr/bin/id -G | /usr/bin/grep -Eq '\<544\>' && echo yes || echo no)
626if [ "${admin}" != "yes" ]
627then
628  echo
629  csih_warning "Running this script typically requires administrator privileges!"
630  csih_warning "However, it seems your account does not have these privileges."
631  csih_warning "Here's the list of groups in your user token:"
632  echo
633  /usr/bin/id -Gnz | xargs -0n1 echo "   "
634  echo
635  csih_warning "This usually means you're running this script from a non-admin"
636  csih_warning "desktop session, or in a non-elevated shell under UAC control."
637  echo
638  csih_warning "Make sure you have the appropriate privileges right now,"
639  csih_warning "otherwise parts of this script will probably fail!"
640  echo
641  echo -e "${_csih_QUERY_STR} Are you sure you want to continue?  (Say \"no\" if you're not sure"
642  if ! csih_request "you have the required privileges)"
643  then
644    echo
645    csih_inform "Ok.  Exiting.  Make sure to switch to an administrative account"
646    csih_inform "or to start this script from an elevated shell."
647    exit 1
648  fi
649fi
650
651echo
652
653warning_cnt=0
654
655# Create /var/log/lastlog if not already exists
656if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ]
657then
658  echo
659  csih_error_multi "${LOCALSTATEDIR}/log/lastlog exists, but is not a file." \
660		   "Cannot create ssh host configuration."
661fi
662if [ ! -e ${LOCALSTATEDIR}/log/lastlog ]
663then
664  /usr/bin/cat /dev/null > ${LOCALSTATEDIR}/log/lastlog
665  if ! /usr/bin/chmod 644 ${LOCALSTATEDIR}/log/lastlog >/dev/null 2>&1
666  then
667    csih_warning "Can't set permissions on ${LOCALSTATEDIR}/log/lastlog!"
668    let ++warning_cnt
669  fi
670fi
671
672# Create /var/empty file used as chroot jail for privilege separation
673csih_make_dir "${LOCALSTATEDIR}/empty" "Cannot create ${LOCALSTATEDIR}/empty directory."
674if ! /usr/bin/chmod 755 "${LOCALSTATEDIR}/empty" >/dev/null 2>&1
675then
676  csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!"
677  let ++warning_cnt
678fi
679
680# generate missing host keys
681csih_inform "Generating missing SSH host keys"
682/usr/bin/ssh-keygen -A || let warning_cnt+=$?
683
684# handle ssh_config
685csih_install_config "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
686if /usr/bin/cmp "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/ssh_config" >/dev/null 2>&1
687then
688  if [ "${port_number}" != "22" ]
689  then
690    csih_inform "Updating ${SYSCONFDIR}/ssh_config file with requested port"
691    echo "Host localhost" >> ${SYSCONFDIR}/ssh_config
692    echo "    Port ${port_number}" >> ${SYSCONFDIR}/ssh_config
693  fi
694fi
695
696# handle sshd_config (and privsep)
697csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
698if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1
699then
700  sshd_config_configured=yes
701fi
702sshd_strictmodes || let warning_cnt+=$?
703sshd_privsep || let warning_cnt+=$?
704sshd_config_tweak || let warning_cnt+=$?
705update_services_file || let warning_cnt+=$?
706update_inetd_conf || let warning_cnt+=$?
707install_service || let warning_cnt+=$?
708
709echo
710if [ $warning_cnt -eq 0 ]
711then
712  csih_inform "Host configuration finished. Have fun!"
713else
714  csih_warning "Host configuration exited with ${warning_cnt} errors or warnings!"
715  csih_warning "Make sure that all problems reported are fixed,"
716  csih_warning "then re-run ssh-host-config."
717fi
718exit $warning_cnt
719