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