1# $OpenBSD: rc,v 1.532 2019/01/26 10:59:07 florian Exp $ 2 3# System startup script run by init on autoboot or after single-user. 4# Output and error are redirected to console by init, and the console is the 5# controlling terminal. 6 7# Turn off Strict Bourne shell. 8set +o sh 9 10# Subroutines (have to come first). 11 12# Strip in- and whole-line comments from a file. 13# Strip leading and trailing whitespace if IFS is set. 14# Usage: stripcom /path/to/file 15stripcom() { 16 local _file=$1 _line 17 18 [[ -s $_file ]] || return 19 20 while read _line ; do 21 _line=${_line%%#*} 22 [[ -n $_line ]] && print -r -- "$_line" 23 done <$_file 24} 25 26# Update resource limits based on login.conf settings. 27# Usage: update_limit -flag capability 28update_limit() { 29 local _flag=$1 # ulimit flag 30 local _cap=$2 _val # login.conf capability and its value 31 local _suffix 32 33 for _suffix in {,-max,-cur}; do 34 _val=$(getcap -f /etc/login.conf -s ${_cap}${_suffix} daemon 2>/dev/null) 35 [[ -n $_val ]] || continue 36 [[ $_val == infinity ]] && _val=unlimited 37 38 case $_suffix in 39 -cur) ulimit -S $_flag $_val 40 ;; 41 -max) ulimit -H $_flag $_val 42 ;; 43 *) ulimit $_flag $_val 44 return 45 ;; 46 esac 47 done 48} 49 50# Apply sysctl.conf(5) settings. 51sysctl_conf() { 52 # do not use a pipe as limits would only be applied to the subshell 53 set -- $(stripcom /etc/sysctl.conf) 54 while [[ $# > 0 ]] ; do 55 sysctl "$1" 56 57 case "$1" in 58 kern.maxproc=*) 59 update_limit -p maxproc 60 ;; 61 kern.maxfiles=*) 62 update_limit -n openfiles 63 ;; 64 esac 65 shift 66 done 67} 68 69# Apply mixerctl.conf(5) settings. 70mixerctl_conf() { 71 stripcom /etc/mixerctl.conf | 72 while read _line; do 73 mixerctl -q "$_line" 2>/dev/null 74 done 75} 76 77# Apply wsconsctl.conf(5) settings. 78wsconsctl_conf() { 79 [[ -x /sbin/wsconsctl ]] || return 80 81 stripcom /etc/wsconsctl.conf | 82 while read _line; do 83 eval "wsconsctl $_line" 84 done 85} 86 87# Push the old seed into the kernel, create a future seed and create a seed 88# file for the boot-loader. 89random_seed() { 90 dd if=/var/db/host.random of=/dev/random bs=65536 count=1 status=none 91 chmod 600 /var/db/host.random 92 dd if=/dev/random of=/var/db/host.random bs=65536 count=1 status=none 93 dd if=/dev/random of=/etc/random.seed bs=512 count=1 status=none 94 chmod 600 /etc/random.seed 95} 96 97# Populate net.inet.(tcp|udp).baddynamic with the contents of /etc/services so 98# as to avoid randomly allocating source ports that correspond to well-known 99# services. 100# Usage: fill_baddynamic tcp|udp 101fill_baddynamic() { 102 local _service=$1 103 local _sysctl="net.inet.${_service}.baddynamic" 104 105 stripcom /etc/services | 106 { 107 _ban= 108 while IFS=" /" read _name _port _srv _junk; do 109 [[ $_srv == $_service ]] || continue 110 111 _ban="${_ban:+$_ban,}+$_port" 112 113 # Flush before argv gets too long 114 if ((${#_ban} > 1024)); then 115 sysctl -q "$_sysctl=$_ban" 116 _ban= 117 fi 118 done 119 [[ -n $_ban ]] && sysctl -q "$_sysctl=$_ban" 120 } 121} 122 123# Start daemon using the rc.d daemon control scripts. 124# Usage: start_daemon daemon1 daemon2 daemon3 125start_daemon() { 126 local _daemon 127 128 for _daemon; do 129 eval "_do=\${${_daemon}_flags}" 130 [[ $_do != NO ]] && /etc/rc.d/${_daemon} start 131 done 132} 133 134# Generate keys for isakmpd, iked and sshd if they don't exist yet. 135make_keys() { 136 local _isakmpd_key=/etc/isakmpd/private/local.key 137 local _isakmpd_pub=/etc/isakmpd/local.pub 138 local _iked_key=/etc/iked/private/local.key 139 local _iked_pub=/etc/iked/local.pub 140 141 if [[ ! -f $_isakmpd_key ]]; then 142 echo -n "openssl: generating isakmpd/iked RSA keys... " 143 if openssl genrsa -out $_isakmpd_key 2048 >/dev/null 2>&1 && 144 chmod 600 $_isakmpd_key && 145 openssl rsa -out $_isakmpd_pub -in $_isakmpd_key \ 146 -pubout >/dev/null 2>&1; then 147 echo done. 148 else 149 echo failed. 150 fi 151 fi 152 153 if [[ ! -f $_iked_key ]]; then 154 # Just copy the generated isakmpd key 155 cp $_isakmpd_key $_iked_key 156 chmod 600 $_iked_key 157 cp $_isakmpd_pub $_iked_pub 158 fi 159 160 ssh-keygen -A 161 162 if [[ ! -f /etc/soii.key ]]; then 163 openssl rand -hex 16 > /etc/soii.key && 164 chmod 600 /etc/soii.key && sysctl -q \ 165 "net.inet6.ip6.soiikey=$(</etc/soii.key)" 166 fi 167} 168 169# Re-link libraries, placing the objects in a random order. 170reorder_libs() { 171 local _error=false _dkdev _liba _libas _mp _ro_list _tmpdir 172 local _relink=/usr/share/relink 173 174 [[ $library_aslr == NO ]] && return 175 176 # Skip if /usr/lib, /usr/libexec or /usr/share/relink are on nfs mounted 177 # filesystems, otherwise record which ones are mounted read-only. 178 for _d in /usr/{lib,libexec,share/relink}; do 179 _dkdev=$(df $_d | sed '1d;s/ .*//') 180 _mp=$(mount | grep "^$_dkdev") 181 [[ $_mp == *" type nfs "* ]] && return 182 if [[ $_mp == *" type ffs "*"read-only"* && 183 $_ro_list != *${_mp%% *}* ]]; then 184 _ro_list="$_ro_list ${_mp%% *}" 185 fi 186 done 187 188 echo -n 'reordering libraries:' 189 190 # Remount the (read-only) filessystems in _ro_list as read-write. 191 for _mp in $_ro_list; do 192 if ! mount -u -w $_mp; then 193 echo ' failed.' 194 return 195 fi 196 done 197 198 # Only choose the latest version of the libraries. 199 for _liba in $_relink/usr/lib/lib{c,crypto}; do 200 _libas="$_libas $(ls $_liba.so.+([0-9.]).a | sort -rV | head -1)" 201 done 202 203 for _liba in $_relink/usr/libexec/ld.so.a $_libas; do 204 _tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) && 205 ( 206 set -o errexit 207 _install='install -F -S -o root -g bin -m 0444' 208 _lib=${_liba##*/} 209 _lib=${_lib%.a} 210 _lib_dir=${_liba#$_relink} 211 _lib_dir=${_lib_dir%/*} 212 cd $_tmpdir 213 ar x $_liba 214 if [[ $_lib == ld.so ]]; then 215 ld -g -x -e _dl_start \ 216 --version-script=Symbols.map --shared -Bsymbolic \ 217 --no-undefined -o ld.so.test $(ls *.o | sort -R) 218 chmod u+x test-ld.so 219 [[ $(./test-ld.so ok) == './test-ld.so: ok!' ]] 220 $_install /usr/libexec/ld.so /usr/libexec/ld.so.save 221 $_install ld.so.test $_lib_dir/ld.so 222 else 223 cc -shared -o $_lib $(ls *.so | sort -R) $(cat .ldadd) 224 [[ -s $_lib ]] && file $_lib | fgrep -q 'shared object' 225 LD_BIND_NOW=1 LD_LIBRARY_PATH=$_tmpdir awk 'BEGIN {exit 0}' 226 LD_BIND_NOW=1 LD_LIBRARY_PATH=$_tmpdir openssl \ 227 x509 -in /etc/ssl/cert.pem -out /dev/null 228 $_install $_lib $_lib_dir/$_lib 229 fi 230 ) || { _error=true; break; } 231 done 232 233 rm -rf $_relink/_rebuild.* 234 235 # Restore previous mount state if it was changed. 236 for _mp in $_ro_list; do 237 mount -u -r $_mp || _error=true 238 done 239 240 if $_error; then 241 echo ' failed.' 242 else 243 echo ' done.' 244 fi 245} 246 247# Run rc.* script and email output to root. 248# Usage: run_upgrade_script firsttime|sysmerge 249run_upgrade_script() { 250 local _suffix=$1 251 252 [[ -n $_suffix ]] || return 1 253 254 if [[ -f /etc/rc.$_suffix ]]; then 255 echo "running rc.$_suffix" 256 mv /etc/rc.$_suffix /etc/rc.$_suffix.run 257 . /etc/rc.$_suffix.run 2>&1 | tee /dev/tty | 258 mail -Es "$(hostname) rc.$_suffix output" root >/dev/null 259 fi 260 rm -f /etc/rc.$_suffix.run 261} 262 263# Check filesystems, optionally by using a fsck(8) flag. 264# Usage: do_fsck [-flag] 265do_fsck() { 266 fsck -p "$@" 267 case $? in 268 0) ;; 269 2) exit 1 270 ;; 271 4) echo "Rebooting..." 272 reboot 273 echo "Reboot failed; help!" 274 exit 1 275 ;; 276 8) echo "Automatic file system check failed; help!" 277 exit 1 278 ;; 279 12) echo "Boot interrupted." 280 exit 1 281 ;; 282 130) # Interrupt before catcher installed. 283 exit 1 284 ;; 285 *) echo "Unknown error; help!" 286 exit 1 287 ;; 288 esac 289} 290 291# End subroutines. 292 293stty status '^T' 294 295# Set shell to ignore SIGINT (2), but not children; shell catches SIGQUIT (3) 296# and returns to single user after fsck. 297trap : 2 298trap : 3 # Shouldn't be needed. 299 300export HOME=/ 301export INRC=1 302export PATH=/sbin:/bin:/usr/sbin:/usr/bin 303 304# Must set the domainname before rc.conf, so YP startup choices can be made. 305if [[ -s /etc/defaultdomain ]]; then 306 domainname "$(stripcom /etc/defaultdomain)" 307fi 308 309# Get local functions from rc.subr to load rc.conf into scope. 310FUNCS_ONLY=1 . /etc/rc.d/rc.subr 311_rc_parse_conf 312 313# If executed with the 'shutdown' parameter by the halt, reboot or shutdown: 314# - update seed files 315# - execute the rc.d scripts specified by $pkg_scripts in reverse order 316# - bring carp interfaces down gracefully 317if [[ $1 == shutdown ]]; then 318 if echo 2>/dev/null >>/var/db/host.random || 319 echo 2>/dev/null >>/etc/random.seed; then 320 random_seed 321 else 322 echo warning: cannot write random seed to disk 323 fi 324 325 # If we are in secure level 0, assume single user mode. 326 if (($(sysctl -n kern.securelevel) == 0)); then 327 echo 'single user: not running shutdown scripts' 328 else 329 set -A _d -- $pkg_scripts 330 _i=${#_d[*]} 331 if ((_i)); then 332 echo -n 'stopping package daemons:' 333 while ((--_i >= 0)); do 334 [[ -x /etc/rc.d/${_d[_i]} ]] && 335 /etc/rc.d/${_d[_i]} stop 336 done 337 echo '.' 338 fi 339 340 if /etc/rc.d/vmd check > /dev/null; then 341 echo -n 'stopping VMs' 342 /etc/rc.d/vmd stop > /dev/null 343 echo '.' 344 fi 345 346 [[ -f /etc/rc.shutdown ]] && sh /etc/rc.shutdown 347 fi 348 349 ifconfig | while read _if _junk; do 350 [[ $_if == carp+([0-9]): ]] && ifconfig ${_if%:} down 351 done 352 353 exit 0 354fi 355 356# Add swap block-devices. 357swapctl -A -t blk 358 359# Run filesystem check unless a /fastboot file exists. 360if [[ -e /fastboot ]]; then 361 echo "Fast boot: skipping disk checks." 362elif [[ $1 == autoboot ]]; then 363 echo "Automatic boot in progress: starting file system checks." 364 do_fsck 365fi 366 367# From now on, allow user to interrupt (^C) the boot process. 368trap "echo 'Boot interrupted.'; exit 1" 3 369 370# Unmount all filesystems except root. 371umount -a >/dev/null 2>&1 372 373# Mount all filesystems except those of type NFS and VND. 374mount -a -t nonfs,vnd 375 376# Re-mount the root filesystem read/writeable. (root on nfs requires this, 377# others aren't hurt.) 378mount -uw / 379chmod og-rwx /bsd 380ln -fh /bsd /bsd.booted 381 382rm -f /fastboot 383 384# Set flags on ttys. 385ttyflags -a 386 387# Set keyboard encoding. 388if [[ -x /sbin/kbd && -s /etc/kbdtype ]]; then 389 kbd "$(cat /etc/kbdtype)" 390fi 391 392wsconsctl_conf 393 394# Set initial temporary pf rule set. 395if [[ $pf != NO ]]; then 396 RULES=" 397 block all 398 pass on lo0 399 pass in proto tcp from any to any port ssh keep state 400 pass out proto { tcp, udp } from any to any port domain keep state 401 pass out inet proto icmp all icmp-type echoreq keep state 402 pass out inet proto udp from any port bootpc to any port bootps 403 pass in inet proto udp from any port bootps to any port bootpc" 404 405 if ifconfig lo0 inet6 >/dev/null 2>&1; then 406 RULES="$RULES 407 pass out inet6 proto icmp6 all icmp6-type neighbrsol 408 pass in inet6 proto icmp6 all icmp6-type neighbradv 409 pass out inet6 proto icmp6 all icmp6-type routersol 410 pass in inet6 proto icmp6 all icmp6-type routeradv 411 pass out inet6 proto udp from any port dhcpv6-client to any port dhcpv6-server 412 pass in inet6 proto udp from any port dhcpv6-server to any port dhcpv6-client" 413 fi 414 415 RULES="$RULES 416 pass in proto carp keep state (no-sync) 417 pass out proto carp !received-on any keep state (no-sync)" 418 419 if (($(sysctl -n vfs.mounts.nfs 2>/dev/null) > 0)); then 420 # Don't kill NFS. 421 RULES="set reassemble yes no-df 422 $RULES 423 pass in proto { tcp, udp } from any port { sunrpc, nfsd } to any 424 pass out proto { tcp, udp } from any to any port { sunrpc, nfsd } !received-on any" 425 fi 426 427 print -- "$RULES" | pfctl -f - 428 pfctl -e 429fi 430 431fill_baddynamic udp 432fill_baddynamic tcp 433 434sysctl_conf 435 436start_daemon slaacd >/dev/null 2>&1 437 438echo 'starting network' 439 440# Set carp interlock by increasing the demotion counter. 441# Prevents carp from preempting until the system is booted. 442ifconfig -g carp carpdemote 128 443 444sh /etc/netstart 445 446# Any write triggers a rekey. 447dmesg >/dev/random 448 449# Load pf rules and bring up pfsync interface. 450if [[ $pf != NO ]]; then 451 if [[ -f /etc/pf.conf ]]; then 452 pfctl -f /etc/pf.conf 453 fi 454 if [[ -f /etc/hostname.pfsync0 ]]; then 455 sh /etc/netstart pfsync0 456 fi 457fi 458 459mount -s /usr >/dev/null 2>&1 460mount -s /var >/dev/null 2>&1 461 462random_seed 463 464reorder_libs 465 466# Clean up left-over files. 467rm -f /etc/nologin /var/spool/lock/LCK.* 468(cd /var/run && { rm -rf -- *; install -c -m 664 -g utmp /dev/null utmp; }) 469(cd /var/authpf && rm -rf -- *) 470 471# Save a copy of the boot messages. 472dmesg >/var/run/dmesg.boot 473 474make_keys 475 476echo -n 'starting early daemons:' 477start_daemon syslogd ldattach pflogd nsd rebound unwind unbound ntpd 478start_daemon iscsid isakmpd iked sasyncd ldapd npppd 479echo '.' 480 481# Load IPsec rules. 482if [[ $ipsec != NO && -f /etc/ipsec.conf ]]; then 483 ipsecctl -f /etc/ipsec.conf 484fi 485 486echo -n 'starting RPC daemons:' 487start_daemon portmap ypldap 488rm -f /var/run/ypbind.lock 489if [[ -n $(domainname) ]]; then 490 start_daemon ypserv ypbind 491fi 492start_daemon mountd nfsd lockd statd amd 493echo '.' 494 495# Check and mount remaining file systems and enable additional swap. 496mount -a 497swapctl -A -t noblk 498do_fsck -N 499mount -a -N 500 501# /var/crash should be a directory or a symbolic link to the crash directory 502# if core dumps are to be saved. 503if [[ -d /var/crash ]]; then 504 savecore $savecore_flags /var/crash 505fi 506 507# Store ACPI tables in /var/db/acpi to be used by sendbug(1). 508if [[ -x /usr/sbin/acpidump ]]; then 509 acpidump -q -o /var/db/acpi/ 510fi 511 512if [[ $check_quotas == YES ]]; then 513 echo -n 'checking quotas:' 514 quotacheck -a 515 echo ' done.' 516 quotaon -a 517fi 518 519# Build kvm(3) and /dev databases. 520kvm_mkdb 521dev_mkdb 522 523# Set proper permission for the tty device files. 524chmod 666 /dev/tty[pqrstuvwxyzPQRST]* 525chown root:wheel /dev/tty[pqrstuvwxyzPQRST]* 526 527# Check for the password temp/lock file. 528if [[ -f /etc/ptmp ]]; then 529 logger -s -p auth.err \ 530 'password file may be incorrect -- /etc/ptmp exists' 531fi 532 533echo clearing /tmp 534 535# Prune quickly with one rm, then use find to clean up /tmp/[lqv]* 536# (not needed with mfs /tmp, but doesn't hurt there...). 537(cd /tmp && rm -rf [a-km-pr-uw-zA-Z]*) 538(cd /tmp && 539 find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \ 540 ! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;) 541 542# Create Unix sockets directories for X if needed and make sure they have 543# correct permissions. 544[[ -d /usr/X11R6/lib ]] && mkdir -m 1777 /tmp/.{X11,ICE}-unix 545 546[[ -f /etc/rc.securelevel ]] && sh /etc/rc.securelevel 547 548# rc.securelevel did not specifically set -1 or 2, so select the default: 1. 549(($(sysctl -n kern.securelevel) == 0)) && sysctl kern.securelevel=1 550 551 552# Patch /etc/motd. 553if [[ ! -f /etc/motd ]]; then 554 install -c -o root -g wheel -m 664 /dev/null /etc/motd 555fi 556if T=$(mktemp /tmp/_motd.XXXXXXXXXX); then 557 sysctl -n kern.version | sed 1q >$T 558 sed -n '/^$/,$p' </etc/motd >>$T 559 cmp -s $T /etc/motd || cp $T /etc/motd 560 rm -f $T 561fi 562 563if [[ $accounting == YES ]]; then 564 [[ ! -f /var/account/acct ]] && touch /var/account/acct 565 echo 'turning on accounting' 566 accton /var/account/acct 567fi 568 569if [[ -x /sbin/ldconfig ]]; then 570 echo 'creating runtime link editor directory cache.' 571 [[ -d /usr/local/lib ]] && shlib_dirs="/usr/local/lib $shlib_dirs" 572 [[ -d /usr/X11R6/lib ]] && shlib_dirs="/usr/X11R6/lib $shlib_dirs" 573 ldconfig $shlib_dirs 574fi 575 576echo 'preserving editor files.'; /usr/libexec/vi.recover 577 578# If rc.sysmerge exists, run it just once, and make sure it is deleted. 579run_upgrade_script sysmerge 580 581echo -n 'starting network daemons:' 582start_daemon ldomd sshd switchd snmpd ldpd ripd ospfd ospf6d bgpd ifstated 583start_daemon relayd dhcpd dhcrelay mrouted dvmrpd radiusd eigrpd route6d 584start_daemon rad hostapd lpd smtpd slowcgi httpd ftpd 585start_daemon ftpproxy ftpproxy6 tftpd tftpproxy identd inetd rarpd bootparamd 586start_daemon rbootd mopd vmd spamd spamlogd sndiod 587echo '.' 588 589# If rc.firsttime exists, run it just once, and make sure it is deleted. 590run_upgrade_script firsttime 591 592# Run rc.d(8) scripts from packages. 593if [[ -n $pkg_scripts ]]; then 594 echo -n 'starting package daemons:' 595 for _daemon in $pkg_scripts; do 596 if [[ -x /etc/rc.d/$_daemon ]]; then 597 start_daemon $_daemon 598 else 599 echo -n " ${_daemon}(absent)" 600 fi 601 done 602 echo '.' 603fi 604 605[[ -f /etc/rc.local ]] && sh /etc/rc.local 606 607# Disable carp interlock. 608ifconfig -g carp -carpdemote 128 609 610mixerctl_conf 611 612echo -n 'starting local daemons:' 613start_daemon apmd sensorsd hotplugd watchdogd cron wsmoused xenodm 614echo '.' 615 616# Re-link the kernel, placing the objects in a random order. 617# Replace current with relinked kernel and inform root about it. 618/usr/libexec/reorder_kernel & 619 620date 621exit 0 622