3 # ssh-host-config, Copyright 2000, 2001, 2002, 2003 Red Hat Inc.
5 # This file is part of the Cygwin port of OpenSSH.
7 # Subdirectory where the new package is being installed
10 # Directory where the config files are stored
25 if [ "${auto_answer}" = "yes" ]
27 echo "$1 (yes/no) yes"
29 elif [ "${auto_answer}" = "no" ]
36 while [ "X${answer}" != "Xyes" -a "X${answer}" != "Xno" ]
38 echo -n "$1 (yes/no) "
41 if [ "X${answer}" = "Xyes" ]
91 echo "usage: ${progname} [OPTION]..."
93 echo "This script creates an OpenSSH host configuration."
96 echo " --debug -d Enable shell's debug output."
97 echo " --yes -y Answer all questions with \"yes\" automatically."
98 echo " --no -n Answer all questions with \"no\" automatically."
99 echo " --cygwin -c <options> Use \"options\" as value for CYGWIN environment var."
100 echo " --port -p <n> sshd listens on port n."
101 echo " --pwd -w <passwd> Use \"pwd\" as password for user 'sshd_server'."
109 # Check if running on NT
111 _nt=`expr "${_sys}" : "CYGWIN_NT"`
112 # If running on NT, check if running under 2003 Server or later
115 _nt2003=`uname | awk -F- '{print ( $2 >= 5.2 ) ? 1 : 0;}'`
118 # Check for running ssh/sshd processes first. Refuse to do anything while
119 # some ssh processes are still running
121 if ps -ef | grep -v grep | grep -q ssh
124 echo "There are still ssh processes running. Please shut them down first."
129 # Check for ${SYSCONFDIR} directory
131 if [ -e "${SYSCONFDIR}" -a ! -d "${SYSCONFDIR}" ]
134 echo "${SYSCONFDIR} exists but is not a directory."
135 echo "Cannot create global configuration files."
140 # Create it if necessary
142 if [ ! -e "${SYSCONFDIR}" ]
144 mkdir "${SYSCONFDIR}"
145 if [ ! -e "${SYSCONFDIR}" ]
148 echo "Creating ${SYSCONFDIR} directory failed"
154 # Create /var/log and /var/log/lastlog if not already existing
156 if [ -e ${LOCALSTATEDIR}/log -a ! -d ${LOCALSTATEDIR}/log ]
159 echo "${LOCALSTATEDIR}/log exists but is not a directory."
160 echo "Cannot create ssh host configuration."
164 if [ ! -e ${LOCALSTATEDIR}/log ]
166 mkdir -p ${LOCALSTATEDIR}/log
169 if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ]
172 echo "${LOCALSTATEDIR}/log/lastlog exists, but is not a file."
173 echo "Cannot create ssh host configuration."
177 if [ ! -e ${LOCALSTATEDIR}/log/lastlog ]
179 cat /dev/null > ${LOCALSTATEDIR}/log/lastlog
180 chmod 644 ${LOCALSTATEDIR}/log/lastlog
183 # Create /var/empty file used as chroot jail for privilege separation
184 if [ -e ${LOCALSTATEDIR}/empty -a ! -d ${LOCALSTATEDIR}/empty ]
187 echo "${LOCALSTATEDIR}/empty exists but is not a directory."
188 echo "Cannot create ssh host configuration."
191 if [ ! -e ${LOCALSTATEDIR}/empty ]
193 if ! mkdir -p ${LOCALSTATEDIR}/empty
196 echo "Creating ${LOCALSTATEDIR}/empty directory failed."
197 echo "Cannot create ssh host configuration."
203 chmod 755 ${LOCALSTATEDIR}/empty
207 # First generate host keys if not already existing
209 if [ ! -f "${SYSCONFDIR}/ssh_host_key" ]
211 echo "Generating ${SYSCONFDIR}/ssh_host_key"
212 ssh-keygen -t rsa1 -f ${SYSCONFDIR}/ssh_host_key -N '' > /dev/null
215 if [ ! -f "${SYSCONFDIR}/ssh_host_rsa_key" ]
217 echo "Generating ${SYSCONFDIR}/ssh_host_rsa_key"
218 ssh-keygen -t rsa -f ${SYSCONFDIR}/ssh_host_rsa_key -N '' > /dev/null
221 if [ ! -f "${SYSCONFDIR}/ssh_host_dsa_key" ]
223 echo "Generating ${SYSCONFDIR}/ssh_host_dsa_key"
224 ssh-keygen -t dsa -f ${SYSCONFDIR}/ssh_host_dsa_key -N '' > /dev/null
227 # Check if ssh_config exists. If yes, ask for overwriting
229 if [ -f "${SYSCONFDIR}/ssh_config" ]
231 if request "Overwrite existing ${SYSCONFDIR}/ssh_config file?"
233 rm -f "${SYSCONFDIR}/ssh_config"
234 if [ -f "${SYSCONFDIR}/ssh_config" ]
236 echo "Can't overwrite. ${SYSCONFDIR}/ssh_config is write protected."
241 # Create default ssh_config from skeleton file in /etc/defaults/etc
243 if [ ! -f "${SYSCONFDIR}/ssh_config" ]
245 echo "Generating ${SYSCONFDIR}/ssh_config file"
246 cp ${SYSCONFDIR}/defaults/etc/ssh_config ${SYSCONFDIR}/ssh_config
247 if [ "${port_number}" != "22" ]
249 echo "Host localhost" >> ${SYSCONFDIR}/ssh_config
250 echo " Port ${port_number}" >> ${SYSCONFDIR}/ssh_config
254 # Check if sshd_config exists. If yes, ask for overwriting
256 if [ -f "${SYSCONFDIR}/sshd_config" ]
258 if request "Overwrite existing ${SYSCONFDIR}/sshd_config file?"
260 rm -f "${SYSCONFDIR}/sshd_config"
261 if [ -f "${SYSCONFDIR}/sshd_config" ]
263 echo "Can't overwrite. ${SYSCONFDIR}/sshd_config is write protected."
266 grep -q UsePrivilegeSeparation ${SYSCONFDIR}/sshd_config && privsep_configured=yes
270 # Prior to creating or modifying sshd_config, care for privilege separation
272 if [ "${privsep_configured}" != "yes" ]
276 echo "Privilege separation is set to yes by default since OpenSSH 3.3."
277 echo "However, this requires a non-privileged account called 'sshd'."
278 echo "For more info on privilege separation read /usr/share/doc/openssh/README.privsep."
280 if request "Should privilege separation be used?"
283 grep -q '^sshd:' ${SYSCONFDIR}/passwd && sshd_in_passwd=yes
284 net user sshd >/dev/null 2>&1 && sshd_in_sam=yes
285 if [ "${sshd_in_passwd}" != "yes" ]
287 if [ "${sshd_in_sam}" != "yes" ]
289 echo "Warning: The following function requires administrator privileges!"
290 if request "Should this script create a local user 'sshd' on this machine?"
292 dos_var_empty=`cygpath -w ${LOCALSTATEDIR}/empty`
293 net user sshd /add /fullname:"sshd privsep" "/homedir:${dos_var_empty}" /active:no > /dev/null 2>&1 && sshd_in_sam=yes
294 if [ "${sshd_in_sam}" != "yes" ]
296 echo "Warning: Creating the user 'sshd' failed!"
300 if [ "${sshd_in_sam}" != "yes" ]
302 echo "Warning: Can't create user 'sshd' in ${SYSCONFDIR}/passwd!"
303 echo " Privilege separation set to 'no' again!"
304 echo " Check your ${SYSCONFDIR}/sshd_config file!"
307 mkpasswd -l -u sshd | sed -e 's/bash$/false/' >> ${SYSCONFDIR}/passwd
314 # On 9x don't use privilege separation. Since security isn't
315 # available it just adds useless additional processes.
320 # Create default sshd_config from skeleton files in /etc/defaults/etc or
321 # modify to add the missing privsep configuration option
323 if [ ! -f "${SYSCONFDIR}/sshd_config" ]
325 echo "Generating ${SYSCONFDIR}/sshd_config file"
326 sed -e "s/^#UsePrivilegeSeparation yes/UsePrivilegeSeparation ${privsep_used}/
327 s/^#Port 22/Port ${port_number}/
328 s/^#StrictModes yes/StrictModes no/" \
329 < ${SYSCONFDIR}/defaults/etc/sshd_config \
330 > ${SYSCONFDIR}/sshd_config
331 elif [ "${privsep_configured}" != "yes" ]
333 echo >> ${SYSCONFDIR}/sshd_config
334 echo "UsePrivilegeSeparation ${privsep_used}" >> ${SYSCONFDIR}/sshd_config
337 # Care for services file
338 _my_etcdir="/ssh-host-config.$$"
341 _win_etcdir="${SYSTEMROOT}\\system32\\drivers\\etc"
342 _services="${_my_etcdir}/services"
343 # On NT, 27 spaces, no space after the hash
346 _win_etcdir="${WINDIR}"
347 _services="${_my_etcdir}/SERVICES"
348 # On 9x, 18 spaces (95 is very touchy), a space after the hash
351 _serv_tmp="${_my_etcdir}/srv.out.$$"
353 mount -t -f "${_win_etcdir}" "${_my_etcdir}"
355 # Depends on the above mount
356 _wservices=`cygpath -w "${_services}"`
358 # Remove sshd 22/port from services
359 if [ `grep -q 'sshd[ \t][ \t]*22' "${_services}"; echo $?` -eq 0 ]
361 grep -v 'sshd[ \t][ \t]*22' "${_services}" > "${_serv_tmp}"
362 if [ -f "${_serv_tmp}" ]
364 if mv "${_serv_tmp}" "${_services}"
366 echo "Removing sshd from ${_wservices}"
368 echo "Removing sshd from ${_wservices} failed!"
372 echo "Removing sshd from ${_wservices} failed!"
376 # Add ssh 22/tcp and ssh 22/udp to services
377 if [ `grep -q 'ssh[ \t][ \t]*22' "${_services}"; echo $?` -ne 0 ]
379 if 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}"
381 if mv "${_serv_tmp}" "${_services}"
383 echo "Added ssh to ${_wservices}"
385 echo "Adding ssh to ${_wservices} failed!"
389 echo "WARNING: Adding ssh to ${_wservices} failed!"
393 umount "${_my_etcdir}"
395 # Care for inetd.conf file
396 _inetcnf="${SYSCONFDIR}/inetd.conf"
397 _inetcnf_tmp="${SYSCONFDIR}/inetd.conf.$$"
399 if [ -f "${_inetcnf}" ]
401 # Check if ssh service is already in use as sshd
403 grep -q '^[ \t]*sshd' "${_inetcnf}" && with_comment=0
404 # Remove sshd line from inetd.conf
405 if [ `grep -q '^[# \t]*sshd' "${_inetcnf}"; echo $?` -eq 0 ]
407 grep -v '^[# \t]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}"
408 if [ -f "${_inetcnf_tmp}" ]
410 if mv "${_inetcnf_tmp}" "${_inetcnf}"
412 echo "Removed sshd from ${_inetcnf}"
414 echo "Removing sshd from ${_inetcnf} failed!"
416 rm -f "${_inetcnf_tmp}"
418 echo "Removing sshd from ${_inetcnf} failed!"
422 # Add ssh line to inetd.conf
423 if [ `grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -ne 0 ]
425 if [ "${with_comment}" -eq 0 ]
427 echo 'ssh stream tcp nowait root /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
429 echo '# ssh stream tcp nowait root /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
431 echo "Added ssh to ${_inetcnf}"
435 # On NT ask if sshd should be installed as service
438 # But only if it is not already installed
439 if ! cygrunsrv -Q sshd > /dev/null 2>&1
443 echo "Warning: The following functions require administrator privileges!"
445 echo "Do you want to install sshd as service?"
446 if request "(Say \"no\" if it's already installed as service)"
448 if [ $_nt2003 -gt 0 ]
450 grep -q '^sshd_server:' ${SYSCONFDIR}/passwd && sshd_server_in_passwd=yes
451 if [ "${sshd_server_in_passwd}" = "yes" ]
453 # Drop sshd_server from passwd since it could have wrong settings
454 grep -v '^sshd_server:' ${SYSCONFDIR}/passwd > ${SYSCONFDIR}/passwd.$$
455 rm -f ${SYSCONFDIR}/passwd
456 mv ${SYSCONFDIR}/passwd.$$ ${SYSCONFDIR}/passwd
457 chmod g-w,o-w ${SYSCONFDIR}/passwd
459 net user sshd_server >/dev/null 2>&1 && sshd_server_in_sam=yes
460 if [ "${sshd_server_in_sam}" != "yes" ]
463 echo "You appear to be running Windows 2003 Server or later. On 2003 and"
464 echo "later systems, it's not possible to use the LocalSystem account"
465 echo "if sshd should allow passwordless logon (e. g. public key authentication)."
466 echo "If you want to enable that functionality, it's required to create a new"
467 echo "account 'sshd_server' with special privileges, which is then used to run"
468 echo "the sshd service under."
470 echo "Should this script create a new local account 'sshd_server' which has"
471 if request "the required privileges?"
473 _admingroup=`mkgroup -l | awk -F: '{if ( $2 == "S-1-5-32-544" ) print $1;}' `
474 if [ -z "${_admingroup}" ]
476 echo "mkgroup -l produces no group with SID S-1-5-32-544 (Local administrators group)."
479 dos_var_empty=`cygpath -w ${LOCALSTATEDIR}/empty`
480 while [ "${sshd_server_in_sam}" != "yes" ]
482 if [ -n "${password_value}" ]
484 _password="${password_value}"
485 # Allow to ask for password if first try fails
489 echo "Please enter a password for new user 'sshd_server'. Please be sure that"
490 echo "this password matches the password rules given on your system."
491 echo -n "Entering no password will exit the configuration. PASSWORD="
493 if [ -z "${_password}" ]
496 echo "Exiting configuration. No user sshd_server has been created,"
497 echo "no sshd service installed."
501 net user sshd_server "${_password}" /add /fullname:"sshd server account" "/homedir:${dos_var_empty}" /yes > /tmp/nu.$$ 2>&1 && sshd_server_in_sam=yes
502 if [ "${sshd_server_in_sam}" != "yes" ]
504 echo "Creating the user 'sshd_server' failed! Reason:"
509 net localgroup "${_admingroup}" sshd_server /add > /dev/null 2>&1 && sshd_server_in_admingroup=yes
510 if [ "${sshd_server_in_admingroup}" != "yes" ]
512 echo "WARNING: Adding user sshd_server to local group ${_admingroup} failed!"
513 echo "Please add sshd_server to local group ${_admingroup} before"
514 echo "starting the sshd service!"
517 passwd_has_expiry_flags=`passwd -v | awk '/^passwd /{print ( $3 >= 1.5 ) ? "yes" : "no";}'`
518 if [ "${passwd_has_expiry_flags}" != "yes" ]
521 echo "WARNING: User sshd_server has password expiry set to system default."
522 echo "Please check that password never expires or set it to your needs."
523 elif ! passwd -e sshd_server
526 echo "WARNING: Setting password expiry for user sshd_server failed!"
527 echo "Please check that password never expires or set it to your needs."
529 editrights -a SeAssignPrimaryTokenPrivilege -u sshd_server &&
530 editrights -a SeCreateTokenPrivilege -u sshd_server &&
531 editrights -a SeTcbPrivilege -u sshd_server &&
532 editrights -a SeDenyInteractiveLogonRight -u sshd_server &&
533 editrights -a SeDenyNetworkLogonRight -u sshd_server &&
534 editrights -a SeDenyRemoteInteractiveLogonRight -u sshd_server &&
535 editrights -a SeIncreaseQuotaPrivilege -u sshd_server &&
536 editrights -a SeServiceLogonRight -u sshd_server &&
537 sshd_server_got_all_rights="yes"
538 if [ "${sshd_server_got_all_rights}" != "yes" ]
541 echo "Assigning the appropriate privileges to user 'sshd_server' failed!"
542 echo "Can't create sshd service!"
546 echo "User 'sshd_server' has been created with password '${_password}'."
547 echo "If you change the password, please keep in mind to change the password"
548 echo "for the sshd service, too."
550 echo "Also keep in mind that the user sshd_server needs read permissions on all"
551 echo "users' .ssh/authorized_keys file to allow public key authentication for"
552 echo "these users!. (Re-)running ssh-user-config for each user will set the"
553 echo "required permissions correctly."
557 if [ "${sshd_server_in_sam}" = "yes" ]
559 mkpasswd -l -u sshd_server | sed -e 's/bash$/false/' >> ${SYSCONFDIR}/passwd
562 if [ -n "${cygwin_value}" ]
564 _cygwin="${cygwin_value}"
567 echo "Which value should the environment variable CYGWIN have when"
568 echo "sshd starts? It's recommended to set at least \"ntsec\" to be"
569 echo "able to change user context without password."
570 echo -n "Default is \"ntsec\". CYGWIN="
573 [ -z "${_cygwin}" ] && _cygwin="ntsec"
574 if [ $_nt2003 -gt 0 -a "${sshd_server_in_sam}" = "yes" ]
576 if cygrunsrv -I sshd -d "CYGWIN sshd" -p /usr/sbin/sshd -a -D -u sshd_server -w "${_password}" -e "CYGWIN=${_cygwin}" -y tcpip
579 echo "The service has been installed under sshd_server account."
580 echo "To start the service, call \`net start sshd' or \`cygrunsrv -S sshd'."
583 if cygrunsrv -I sshd -d "CYGWIN sshd" -p /usr/sbin/sshd -a -D -e "CYGWIN=${_cygwin}" -y tcpip
586 echo "The service has been installed under LocalSystem account."
587 echo "To start the service, call \`net start sshd' or \`cygrunsrv -S sshd'."
591 # Now check if sshd has been successfully installed. This allows to
592 # set the ownership of the affected files correctly.
593 if cygrunsrv -Q sshd > /dev/null 2>&1
595 if [ $_nt2003 -gt 0 -a "${sshd_server_in_sam}" = "yes" ]
601 chown "${_user}" ${SYSCONFDIR}/ssh*
602 chown "${_user}".544 ${LOCALSTATEDIR}/empty
603 chown "${_user}".544 ${LOCALSTATEDIR}/log/lastlog
604 if [ -f ${LOCALSTATEDIR}/log/sshd.log ]
606 chown "${_user}".544 ${LOCALSTATEDIR}/log/sshd.log
609 if ! ( mount | egrep -q 'on /(|usr/(bin|lib)) type system' )
612 echo "Warning: It appears that you have user mode mounts (\"Just me\""
613 echo "chosen during install.) Any daemons installed as services will"
614 echo "fail to function unless system mounts are used. To change this,"
615 echo "re-run setup.exe and choose \"All users\"."
617 echo "For more information, see http://cygwin.com/faq/faq0.html#TOC33"
623 echo "Host configuration finished. Have fun!"