Home | History | Annotate | Download | only in cygwin
      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 
     23 CSIH_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.
     28 declare -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 )
     48 csih_sanity_check_server=yes
     49 source ${CSIH_SCRIPT}
     50 
     51 PROGNAME=$(/usr/bin/basename $0)
     52 _tdir=$(/usr/bin/dirname $0)
     53 PROGDIR=$(cd $_tdir && pwd)
     54 
     55 # Subdirectory where the new package is being installed
     56 PREFIX=/usr
     57 
     58 # Directory where the config files are stored
     59 SYSCONFDIR=/etc
     60 LOCALSTATEDIR=/var
     61 
     62 sshd_config_configured=no
     63 port_number=22
     64 service_name=sshd
     65 strictmodes=yes
     66 privsep_used=yes
     67 cygwin_value=""
     68 user_account=
     69 password_value=
     70 opt_force=no
     71 
     72 # ======================================================================
     73 # Routine: update_services_file
     74 # ======================================================================
     75 update_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 # ======================================================================
    120 sshd_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 # ======================================================================
    145 sshd_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 # ======================================================================
    178 sshd_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 # ======================================================================
    223 update_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 # ======================================================================
    329 check_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 # ======================================================================
    406 install_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.
    517 if [ "$PROGDIR" = "/etc/postinstall" ]
    518 then
    519   csih_auto_answer="no"
    520   csih_disable_color
    521   opt_force=yes
    522 fi
    523 if [ -n "${SSH_HOST_CONFIG_AUTO_ANSWER_NO}" ]
    524 then
    525   csih_auto_answer="no"
    526   csih_disable_color
    527   opt_force=yes
    528 fi
    529 
    530 # ======================================================================
    531 # Parse options
    532 # ======================================================================
    533 while :
    534 do
    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
    610 done
    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
    618 if /usr/bin/ps -ef | /usr/bin/grep -q '/sshd\?$'
    619 then
    620   echo
    621   csih_error "There are still ssh processes running. Please shut them down first."
    622 fi
    623 
    624 # Make sure the user is running in an administrative context
    625 admin=$(/usr/bin/id -G | /usr/bin/grep -Eq '\<544\>' && echo yes || echo no)
    626 if [ "${admin}" != "yes" ]
    627 then
    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
    649 fi
    650 
    651 echo
    652 
    653 warning_cnt=0
    654 
    655 # Create /var/log/lastlog if not already exists
    656 if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ]
    657 then
    658   echo
    659   csih_error_multi "${LOCALSTATEDIR}/log/lastlog exists, but is not a file." \
    660 		   "Cannot create ssh host configuration."
    661 fi
    662 if [ ! -e ${LOCALSTATEDIR}/log/lastlog ]
    663 then
    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
    670 fi
    671 
    672 # Create /var/empty file used as chroot jail for privilege separation
    673 csih_make_dir "${LOCALSTATEDIR}/empty" "Cannot create ${LOCALSTATEDIR}/empty directory."
    674 if ! /usr/bin/chmod 755 "${LOCALSTATEDIR}/empty" >/dev/null 2>&1
    675 then
    676   csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!"
    677   let ++warning_cnt
    678 fi
    679 
    680 # generate missing host keys
    681 csih_inform "Generating missing SSH host keys"
    682 /usr/bin/ssh-keygen -A || let warning_cnt+=$?
    683 
    684 # handle ssh_config
    685 csih_install_config "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
    686 if /usr/bin/cmp "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/ssh_config" >/dev/null 2>&1
    687 then
    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
    694 fi
    695 
    696 # handle sshd_config (and privsep)
    697 csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
    698 if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1
    699 then
    700   sshd_config_configured=yes
    701 fi
    702 sshd_strictmodes || let warning_cnt+=$?
    703 sshd_privsep || let warning_cnt+=$?
    704 sshd_config_tweak || let warning_cnt+=$?
    705 update_services_file || let warning_cnt+=$?
    706 update_inetd_conf || let warning_cnt+=$?
    707 install_service || let warning_cnt+=$?
    708 
    709 echo
    710 if [ $warning_cnt -eq 0 ]
    711 then
    712   csih_inform "Host configuration finished. Have fun!"
    713 else
    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."
    717 fi
    718 exit $warning_cnt
    719