xref: /freebsd/crypto/openssh/contrib/cygwin/ssh-host-config (revision c98323078dede7579020518ec84cdcb478e5c142)
1#!/bin/bash
2#
3# ssh-host-config, Copyright 2000, 2001, 2002, 2003 Red Hat Inc.
4#
5# This file is part of the Cygwin port of OpenSSH.
6
7# Subdirectory where the new package is being installed
8PREFIX=/usr
9
10# Directory where the config files are stored
11SYSCONFDIR=/etc
12LOCALSTATEDIR=/var
13
14progname=$0
15auto_answer=""
16port_number=22
17
18privsep_configured=no
19privsep_used=yes
20sshd_in_passwd=no
21sshd_in_sam=no
22
23request()
24{
25  if [ "${auto_answer}" = "yes" ]
26  then
27    echo "$1 (yes/no) yes"
28    return 0
29  elif [ "${auto_answer}" = "no" ]
30  then
31    echo "$1 (yes/no) no"
32    return 1
33  fi
34
35  answer=""
36  while [ "X${answer}" != "Xyes" -a "X${answer}" != "Xno" ]
37  do
38    echo -n "$1 (yes/no) "
39    read -e answer
40  done
41  if [ "X${answer}" = "Xyes" ]
42  then
43    return 0
44  else
45    return 1
46  fi
47}
48
49# Check options
50
51while :
52do
53  case $# in
54  0)
55    break
56    ;;
57  esac
58
59  option=$1
60  shift
61
62  case "${option}" in
63  -d | --debug )
64    set -x
65    ;;
66
67  -y | --yes )
68    auto_answer=yes
69    ;;
70
71  -n | --no )
72    auto_answer=no
73    ;;
74
75  -c | --cygwin )
76    cygwin_value="$1"
77    shift
78    ;;
79
80  -p | --port )
81    port_number=$1
82    shift
83    ;;
84
85  -w | --pwd )
86    password_value="$1"
87    shift
88    ;;
89
90  *)
91    echo "usage: ${progname} [OPTION]..."
92    echo
93    echo "This script creates an OpenSSH host configuration."
94    echo
95    echo "Options:"
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'."
102    echo
103    exit 1
104    ;;
105
106  esac
107done
108
109# Check if running on NT
110_sys="`uname`"
111_nt=`expr "${_sys}" : "CYGWIN_NT"`
112# If running on NT, check if running under 2003 Server or later
113if [ ${_nt} -gt 0 ]
114then
115  _nt2003=`uname | awk -F- '{print ( $2 >= 5.2 ) ? 1 : 0;}'`
116fi
117
118# Check for running ssh/sshd processes first. Refuse to do anything while
119# some ssh processes are still running
120
121if ps -ef | grep -v grep | grep -q ssh
122then
123  echo
124  echo "There are still ssh processes running. Please shut them down first."
125  echo
126  exit 1
127fi
128
129# Check for ${SYSCONFDIR} directory
130
131if [ -e "${SYSCONFDIR}" -a ! -d "${SYSCONFDIR}" ]
132then
133  echo
134  echo "${SYSCONFDIR} is existant but not a directory."
135  echo "Cannot create global configuration files."
136  echo
137  exit 1
138fi
139
140# Create it if necessary
141
142if [ ! -e "${SYSCONFDIR}" ]
143then
144  mkdir "${SYSCONFDIR}"
145  if [ ! -e "${SYSCONFDIR}" ]
146  then
147    echo
148    echo "Creating ${SYSCONFDIR} directory failed"
149    echo
150    exit 1
151  fi
152fi
153
154# Create /var/log and /var/log/lastlog if not already existing
155
156if [ -f ${LOCALSTATEDIR}/log ]
157then
158  echo "Creating ${LOCALSTATEDIR}/log failed!"
159else
160  if [ ! -d ${LOCALSTATEDIR}/log ]
161  then
162    mkdir -p ${LOCALSTATEDIR}/log
163  fi
164  if [ -d ${LOCALSTATEDIR}/log/lastlog ]
165  then
166    chmod 777 ${LOCALSTATEDIR}/log/lastlog
167  elif [ ! -f ${LOCALSTATEDIR}/log/lastlog ]
168  then
169    cat /dev/null > ${LOCALSTATEDIR}/log/lastlog
170    chmod 666 ${LOCALSTATEDIR}/log/lastlog
171  fi
172fi
173
174# Create /var/empty file used as chroot jail for privilege separation
175if [ -f ${LOCALSTATEDIR}/empty ]
176then
177  echo "Creating ${LOCALSTATEDIR}/empty failed!"
178else
179  mkdir -p ${LOCALSTATEDIR}/empty
180  if [ ${_nt} -gt 0 ]
181  then
182    chmod 755 ${LOCALSTATEDIR}/empty
183  fi
184fi
185
186# First generate host keys if not already existing
187
188if [ ! -f "${SYSCONFDIR}/ssh_host_key" ]
189then
190  echo "Generating ${SYSCONFDIR}/ssh_host_key"
191  ssh-keygen -t rsa1 -f ${SYSCONFDIR}/ssh_host_key -N '' > /dev/null
192fi
193
194if [ ! -f "${SYSCONFDIR}/ssh_host_rsa_key" ]
195then
196  echo "Generating ${SYSCONFDIR}/ssh_host_rsa_key"
197  ssh-keygen -t rsa -f ${SYSCONFDIR}/ssh_host_rsa_key -N '' > /dev/null
198fi
199
200if [ ! -f "${SYSCONFDIR}/ssh_host_dsa_key" ]
201then
202  echo "Generating ${SYSCONFDIR}/ssh_host_dsa_key"
203  ssh-keygen -t dsa -f ${SYSCONFDIR}/ssh_host_dsa_key -N '' > /dev/null
204fi
205
206# Check if ssh_config exists. If yes, ask for overwriting
207
208if [ -f "${SYSCONFDIR}/ssh_config" ]
209then
210  if request "Overwrite existing ${SYSCONFDIR}/ssh_config file?"
211  then
212    rm -f "${SYSCONFDIR}/ssh_config"
213    if [ -f "${SYSCONFDIR}/ssh_config" ]
214    then
215      echo "Can't overwrite. ${SYSCONFDIR}/ssh_config is write protected."
216    fi
217  fi
218fi
219
220# Create default ssh_config from skeleton file in /etc/defaults/etc
221
222if [ ! -f "${SYSCONFDIR}/ssh_config" ]
223then
224  echo "Generating ${SYSCONFDIR}/ssh_config file"
225  cp ${SYSCONFDIR}/defaults/etc/ssh_config ${SYSCONFDIR}/ssh_config
226  if [ "${port_number}" != "22" ]
227  then
228    echo "Host localhost" >> ${SYSCONFDIR}/ssh_config
229    echo "    Port ${port_number}" >> ${SYSCONFDIR}/ssh_config
230  fi
231fi
232
233# Check if sshd_config exists. If yes, ask for overwriting
234
235if [ -f "${SYSCONFDIR}/sshd_config" ]
236then
237  if request "Overwrite existing ${SYSCONFDIR}/sshd_config file?"
238  then
239    rm -f "${SYSCONFDIR}/sshd_config"
240    if [ -f "${SYSCONFDIR}/sshd_config" ]
241    then
242      echo "Can't overwrite. ${SYSCONFDIR}/sshd_config is write protected."
243    fi
244  else
245    grep -q UsePrivilegeSeparation ${SYSCONFDIR}/sshd_config && privsep_configured=yes
246  fi
247fi
248
249# Prior to creating or modifying sshd_config, care for privilege separation
250
251if [ "${privsep_configured}" != "yes" ]
252then
253  if [ ${_nt} -gt 0 ]
254  then
255    echo "Privilege separation is set to yes by default since OpenSSH 3.3."
256    echo "However, this requires a non-privileged account called 'sshd'."
257    echo "For more info on privilege separation read /usr/share/doc/openssh/README.privsep."
258    echo
259    if request "Should privilege separation be used?"
260    then
261      privsep_used=yes
262      grep -q '^sshd:' ${SYSCONFDIR}/passwd && sshd_in_passwd=yes
263      net user sshd >/dev/null 2>&1 && sshd_in_sam=yes
264      if [ "${sshd_in_passwd}" != "yes" ]
265      then
266	if [ "${sshd_in_sam}" != "yes" ]
267	then
268	  echo "Warning: The following function requires administrator privileges!"
269	  if request "Should this script create a local user 'sshd' on this machine?"
270	  then
271	    dos_var_empty=`cygpath -w ${LOCALSTATEDIR}/empty`
272	    net user sshd /add /fullname:"sshd privsep" "/homedir:${dos_var_empty}" /active:no > /dev/null 2>&1 && sshd_in_sam=yes
273	    if [ "${sshd_in_sam}" != "yes" ]
274	    then
275	      echo "Warning: Creating the user 'sshd' failed!"
276	    fi
277	  fi
278	fi
279	if [ "${sshd_in_sam}" != "yes" ]
280	then
281	  echo "Warning: Can't create user 'sshd' in ${SYSCONFDIR}/passwd!"
282	  echo "         Privilege separation set to 'no' again!"
283	  echo "         Check your ${SYSCONFDIR}/sshd_config file!"
284	  privsep_used=no
285	else
286	  mkpasswd -l -u sshd | sed -e 's/bash$/false/' >> ${SYSCONFDIR}/passwd
287	fi
288      fi
289    else
290      privsep_used=no
291    fi
292  else
293    # On 9x don't use privilege separation.  Since security isn't
294    # available it just adds useless additional processes.
295    privsep_used=no
296  fi
297fi
298
299# Create default sshd_config from skeleton files in /etc/defaults/etc or
300# modify to add the missing privsep configuration option
301
302if [ ! -f "${SYSCONFDIR}/sshd_config" ]
303then
304  echo "Generating ${SYSCONFDIR}/sshd_config file"
305  sed -e "s/^#UsePrivilegeSeparation yes/UsePrivilegeSeparation ${privsep_used}/
306	  s/^#Port 22/Port ${port_number}/
307	  s/^#StrictModes yes/StrictModes no/" \
308      < ${SYSCONFDIR}/defaults/etc/sshd_config \
309      > ${SYSCONFDIR}/sshd_config
310elif [ "${privsep_configured}" != "yes" ]
311then
312  echo >> ${SYSCONFDIR}/sshd_config
313  echo "UsePrivilegeSeparation ${privsep_used}" >> ${SYSCONFDIR}/sshd_config
314fi
315
316# Care for services file
317_my_etcdir="/ssh-host-config.$$"
318if [ ${_nt} -gt 0 ]
319then
320  _win_etcdir="${SYSTEMROOT}\\system32\\drivers\\etc"
321  _services="${_my_etcdir}/services"
322  # On NT, 27 spaces, no space after the hash
323  _spaces="                           #"
324else
325  _win_etcdir="${WINDIR}"
326  _services="${_my_etcdir}/SERVICES"
327  # On 9x, 18 spaces (95 is very touchy), a space after the hash
328  _spaces="                  # "
329fi
330_serv_tmp="${_my_etcdir}/srv.out.$$"
331
332mount -t -f "${_win_etcdir}" "${_my_etcdir}"
333
334# Depends on the above mount
335_wservices=`cygpath -w "${_services}"`
336
337# Remove sshd 22/port from services
338if [ `grep -q 'sshd[ \t][ \t]*22' "${_services}"; echo $?` -eq 0 ]
339then
340  grep -v 'sshd[ \t][ \t]*22' "${_services}" > "${_serv_tmp}"
341  if [ -f "${_serv_tmp}" ]
342  then
343    if mv "${_serv_tmp}" "${_services}"
344    then
345      echo "Removing sshd from ${_wservices}"
346    else
347      echo "Removing sshd from ${_wservices} failed!"
348    fi
349    rm -f "${_serv_tmp}"
350  else
351    echo "Removing sshd from ${_wservices} failed!"
352  fi
353fi
354
355# Add ssh 22/tcp  and ssh 22/udp to services
356if [ `grep -q 'ssh[ \t][ \t]*22' "${_services}"; echo $?` -ne 0 ]
357then
358  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}"
359  then
360    if mv "${_serv_tmp}" "${_services}"
361    then
362      echo "Added ssh to ${_wservices}"
363    else
364      echo "Adding ssh to ${_wservices} failed!"
365    fi
366    rm -f "${_serv_tmp}"
367  else
368    echo "WARNING: Adding ssh to ${_wservices} failed!"
369  fi
370fi
371
372umount "${_my_etcdir}"
373
374# Care for inetd.conf file
375_inetcnf="${SYSCONFDIR}/inetd.conf"
376_inetcnf_tmp="${SYSCONFDIR}/inetd.conf.$$"
377
378if [ -f "${_inetcnf}" ]
379then
380  # Check if ssh service is already in use as sshd
381  with_comment=1
382  grep -q '^[ \t]*sshd' "${_inetcnf}" && with_comment=0
383  # Remove sshd line from inetd.conf
384  if [ `grep -q '^[# \t]*sshd' "${_inetcnf}"; echo $?` -eq 0 ]
385  then
386    grep -v '^[# \t]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}"
387    if [ -f "${_inetcnf_tmp}" ]
388    then
389      if mv "${_inetcnf_tmp}" "${_inetcnf}"
390      then
391	echo "Removed sshd from ${_inetcnf}"
392      else
393	echo "Removing sshd from ${_inetcnf} failed!"
394      fi
395      rm -f "${_inetcnf_tmp}"
396    else
397      echo "Removing sshd from ${_inetcnf} failed!"
398    fi
399  fi
400
401  # Add ssh line to inetd.conf
402  if [ `grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -ne 0 ]
403  then
404    if [ "${with_comment}" -eq 0 ]
405    then
406      echo 'ssh  stream  tcp     nowait  root    /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
407    else
408      echo '# ssh  stream  tcp     nowait  root    /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
409    fi
410    echo "Added ssh to ${_inetcnf}"
411  fi
412fi
413
414# On NT ask if sshd should be installed as service
415if [ ${_nt} -gt 0 ]
416then
417  # But only if it is not already installed
418  if ! cygrunsrv -Q sshd > /dev/null 2>&1
419  then
420    echo
421    echo
422    echo "Warning: The following functions require administrator privileges!"
423    echo
424    echo "Do you want to install sshd as service?"
425    if request "(Say \"no\" if it's already installed as service)"
426    then
427      if [ $_nt2003 -gt 0 ]
428      then
429	grep -q '^sshd_server:' ${SYSCONFDIR}/passwd && sshd_server_in_passwd=yes
430	if [ "${sshd_server_in_passwd}" = "yes" ]
431	then
432	  # Drop sshd_server from passwd since it could have wrong settings
433	  grep -v '^sshd_server:' ${SYSCONFDIR}/passwd > ${SYSCONFDIR}/passwd.$$
434	  rm -f ${SYSCONFDIR}/passwd
435	  mv ${SYSCONFDIR}/passwd.$$ ${SYSCONFDIR}/passwd
436	  chmod g-w,o-w ${SYSCONFDIR}/passwd
437	fi
438	net user sshd_server >/dev/null 2>&1 && sshd_server_in_sam=yes
439	if [ "${sshd_server_in_sam}" != "yes" ]
440	then
441	  echo
442	  echo "You appear to be running Windows 2003 Server or later.  On 2003 and"
443	  echo "later systems, it's not possible to use the LocalSystem account"
444	  echo "if sshd should allow passwordless logon (e. g. public key authentication)."
445	  echo "If you want to enable that functionality, it's required to create a new"
446	  echo "account 'sshd_server' with special privileges, which is then used to run"
447	  echo "the sshd service under."
448	  echo
449	  echo "Should this script create a new local account 'sshd_server' which has"
450	  if request "the required privileges?"
451	  then
452	    _admingroup=`awk -F: '{if ( $2 == "S-1-5-32-544" ) print $1;}' ${SYSCONFDIR}/group`
453	    if [ -z "${_admingroup}" ]
454	    then
455	      echo "There's no group with SID S-1-5-32-544 (Local administrators group) in"
456	      echo "your ${SYSCONFDIR}/group file.  Please regenerate this entry using 'mkgroup -l'"
457	      echo "and restart this script."
458	      exit 1
459	    fi
460	    dos_var_empty=`cygpath -w ${LOCALSTATEDIR}/empty`
461	    while [ "${sshd_server_in_sam}" != "yes" ]
462	    do
463	      if [ -n "${password_value}" ]
464	      then
465		_password="${password_value}"
466		# Allow to ask for password if first try fails
467		password_value=""
468	      else
469		echo
470		echo "Please enter a password for new user 'sshd_server'.  Please be sure that"
471		echo "this password matches the password rules given on your system."
472		echo -n "Entering no password will exit the configuration.  PASSWORD="
473		read -e _password
474		if [ -z "${_password}" ]
475		then
476		  echo
477		  echo "Exiting configuration.  No user sshd_server has been created,"
478		  echo "no sshd service installed."
479		  exit 1
480		fi
481	      fi
482	      net user sshd_server "${_password}" /add /fullname:"sshd server account" "/homedir:${dos_var_empty}" /yes > /tmp/nu.$$ 2>&1 && sshd_server_in_sam=yes
483	      if [ "${sshd_server_in_sam}" != "yes" ]
484	      then
485		echo "Creating the user 'sshd_server' failed!  Reason:"
486		cat /tmp/nu.$$
487		rm /tmp/nu.$$
488	      fi
489	    done
490	    net localgroup "${_admingroup}" sshd_server /add > /dev/null 2>&1 && sshd_server_in_admingroup=yes
491	    if [ "${sshd_server_in_admingroup}" != "yes" ]
492	    then
493	      echo "WARNING: Adding user sshd_server to local group ${_admingroup} failed!"
494	      echo "Please add sshd_server to local group ${_admingroup} before"
495	      echo "starting the sshd service!"
496	      echo
497	    fi
498	    passwd_has_expiry_flags=`passwd -v | awk '/^passwd /{print ( $3 >= 1.5 ) ? "yes" : "no";}'`
499	    if [ "${passwd_has_expiry_flags}" != "yes" ]
500	    then
501	      echo
502	      echo "WARNING: User sshd_server has password expiry set to system default."
503	      echo "Please check that password never expires or set it to your needs."
504	    elif ! passwd -e sshd_server
505	    then
506	      echo
507	      echo "WARNING: Setting password expiry for user sshd_server failed!"
508	      echo "Please check that password never expires or set it to your needs."
509	    fi
510	    editrights -a SeAssignPrimaryTokenPrivilege -u sshd_server &&
511	    editrights -a SeCreateTokenPrivilege -u sshd_server &&
512	    editrights -a SeDenyInteractiveLogonRight -u sshd_server &&
513	    editrights -a SeDenyNetworkLogonRight -u sshd_server &&
514	    editrights -a SeDenyRemoteInteractiveLogonRight -u sshd_server &&
515	    editrights -a SeIncreaseQuotaPrivilege -u sshd_server &&
516	    editrights -a SeServiceLogonRight -u sshd_server &&
517	    sshd_server_got_all_rights="yes"
518	    if [ "${sshd_server_got_all_rights}" != "yes" ]
519	    then
520	      echo
521	      echo "Assigning the appropriate privileges to user 'sshd_server' failed!"
522	      echo "Can't create sshd service!"
523	      exit 1
524	    fi
525	    echo
526	    echo "User 'sshd_server' has been created with password '${_password}'."
527	    echo "If you change the password, please keep in mind to change the password"
528	    echo "for the sshd service, too."
529	    echo
530	    echo "Also keep in mind that the user sshd_server needs read permissions on all"
531	    echo "users' .ssh/authorized_keys file to allow public key authentication for"
532	    echo "these users!.  (Re-)running ssh-user-config for each user will set the"
533	    echo "required permissions correctly."
534	    echo
535	  fi
536	fi
537	if [ "${sshd_server_in_sam}" = "yes" ]
538	then
539	  mkpasswd -l -u sshd_server | sed -e 's/bash$/false/' >> ${SYSCONFDIR}/passwd
540	fi
541      fi
542      if [ -n "${cygwin_value}" ]
543      then
544	_cygwin="${cygwin_value}"
545      else
546	echo
547	echo "Which value should the environment variable CYGWIN have when"
548	echo "sshd starts? It's recommended to set at least \"ntsec\" to be"
549	echo "able to change user context without password."
550	echo -n "Default is \"ntsec\".  CYGWIN="
551	read -e _cygwin
552      fi
553      [ -z "${_cygwin}" ] && _cygwin="ntsec"
554      if [ $_nt2003 -gt 0 -a "${sshd_server_in_sam}" = "yes" ]
555      then
556	if cygrunsrv -I sshd -d "CYGWIN sshd" -p /usr/sbin/sshd -a -D -u sshd_server -w "${_password}" -e "CYGWIN=${_cygwin}"
557	then
558	  echo
559	  echo "The service has been installed under sshd_server account."
560	  echo "To start the service, call \`net start sshd' or \`cygrunsrv -S sshd'."
561	fi
562      else
563	if cygrunsrv -I sshd -d "CYGWIN sshd" -p /usr/sbin/sshd -a -D -e "CYGWIN=${_cygwin}"
564	then
565	  echo
566	  echo "The service has been installed under LocalSystem account."
567	  echo "To start the service, call \`net start sshd' or \`cygrunsrv -S sshd'."
568	fi
569      fi
570    fi
571    # Now check if sshd has been successfully installed.  This allows to
572    # set the ownership of the affected files correctly.
573    if cygrunsrv -Q sshd > /dev/null 2>&1
574    then
575      if [ $_nt2003 -gt 0 -a "${sshd_server_in_sam}" = "yes" ]
576      then
577	_user="sshd_server"
578      else
579	_user="system"
580      fi
581      chown "${_user}" ${SYSCONFDIR}/ssh*
582      chown "${_user}".544 ${LOCALSTATEDIR}/empty
583      if [ -f ${LOCALSTATEDIR}/log/sshd.log ]
584      then
585	chown "${_user}".544 ${LOCALSTATEDIR}/log/sshd.log
586      fi
587    fi
588  fi
589fi
590
591echo
592echo "Host configuration finished. Have fun!"
593