1#!/bin/sh 2# 3# 4 5# PROVIDE: ntpd 6# REQUIRE: DAEMON ntpdate FILESYSTEMS devfs 7# BEFORE: LOGIN 8# KEYWORD: nojail resume shutdown 9 10. /etc/rc.subr 11 12name="ntpd" 13desc="Network Time Protocol daemon" 14rcvar="ntpd_enable" 15command="/usr/sbin/${name}" 16extra_commands="fetch needfetch resume" 17fetch_cmd="ntpd_fetch_leapfile" 18needfetch_cmd="ntpd_needfetch_leapfile" 19resume_cmd="ntpd_resume" 20start_precmd="ntpd_precmd" 21 22_ntp_tmp_leapfile="/var/run/ntpd.leap-seconds.list" 23_ntp_default_dir="/var/db/ntp" 24_ntp_default_driftfile="${_ntp_default_dir}/ntpd.drift" 25_ntp_old_driftfile="/var/db/ntpd.drift" 26 27pidfile="${_ntp_default_dir}/${name}.pid" 28 29load_rc_config $name 30 31# doesn't make sense to run in a svcj: nojail keyword 32ntpd_svcj="NO" 33 34leapfile_is_disabled() { 35 # Return true (0) if automatic leapfile handling is disabled. 36 case "$ntp_db_leapfile" in 37 [Nn][Oo] | [Nn][Oo][Nn][Ee] ) 38 return 0;; 39 * ) 40 return 1;; 41 esac 42} 43 44can_run_nonroot() 45{ 46 # If the admin set what uid to use, we don't change it. 47 if [ -n "${ntpd_user}" ]; then 48 return 1 49 fi 50 51 # If the admin set any command line options involving files, we 52 # may not be able to access them as user ntpd. 53 case "${rc_flags}" in 54 *-f* | *--driftfile* | *-i* | *--jaildir* | \ 55 *-k* | *--keyfile* | *-l* | *--logfile* | \ 56 *-p* | *--pidfile* | *-s* | *--statsdir* ) 57 return 1;; 58 esac 59 60 # If the admin set any options in ntp.conf involving files, 61 # we may not be able to access them as user ntpd. 62 local fileopts="^[ \t]*crypto|^[ \t]*driftfile|^[ \t]*key|^[ \t]*logfile|^[ \t]*statsdir" 63 grep -E -q "${fileopts}" "${ntpd_config}" && return 1 64 65 # Try to set up the MAC ntpd policy so ntpd can run with reduced 66 # privileges. Detect whether MAC is compiled into the kernel, load 67 # the policy module if not already present, then check whether the 68 # policy has been disabled via tunable or sysctl. 69 [ -n "$(sysctl -qn security.mac.version)" ] || return 1 70 sysctl -qn security.mac.ntpd >/dev/null || kldload -qn mac_ntpd || return 1 71 [ "$(sysctl -qn security.mac.ntpd.enabled)" == "1" ] || return 1 72 73 # On older existing systems, the ntp dir may by owned by root, change 74 # it to ntpd to give the daemon create/write access to the driftfile. 75 if [ "$(stat -f %u ${_ntp_default_dir})" = "0" ]; then 76 chown ntpd:ntpd "${_ntp_default_dir}" || return 1 77 chmod 0755 "${_ntp_default_dir}" || return 1 78 logger -s -t "rc.d/ntpd" -p daemon.notice \ 79 "${_ntp_default_dir} updated to owner ntpd:ntpd, mode 0755" 80 fi 81 82 # If the driftfile exists in the standard location for older existing 83 # systems, move it into the ntp dir and fix the ownership if we can. 84 if [ -f "${_ntp_old_driftfile}" ] && [ ! -L "${_ntp_old_driftfile}" ]; then 85 mv "${_ntp_old_driftfile}" "${_ntp_default_driftfile}" && 86 chown ntpd:ntpd "${_ntp_default_driftfile}" || return 1 87 logger -s -t "rc.d/ntpd" -p daemon.notice \ 88 "${_ntp_default_driftfile} updated to owner ntpd:ntpd" 89 logger -s -t "rc.d/ntpd" -p daemon.notice \ 90 "${_ntp_old_driftfile} moved to ${_ntp_default_driftfile}" 91 fi 92} 93 94ntpd_precmd() 95{ 96 local driftopt 97 98 # If we can run as a non-root user, switch uid to ntpd and use the 99 # new default location for the driftfile inside the ntpd-owned dir. 100 # Otherwise, figure out what to do about the driftfile option. If set 101 # by the admin, we don't add the option. If the file exists in the old 102 # default location we use that, else we use the new default location. 103 if can_run_nonroot; then 104 driftopt="-f ${_ntp_default_driftfile}" 105 elif grep -q "^[ \t]*driftfile" "${ntpd_config}" || 106 [ -n "${rc_flags}" ] && 107 ( [ -z "${rc_flags##*-f*}" ] || 108 [ -z "${rc_flags##*--driftfile*}" ] ); then 109 driftopt="" # admin set the option, we don't need to add it. 110 elif [ -f "${_ntp_old_driftfile}" ]; then 111 driftopt="-f ${_ntp_old_driftfile}" 112 else 113 driftopt="-f ${_ntp_default_driftfile}" 114 fi 115 116 # Set command_args based on the various config vars. 117 command_args="-p ${pidfile} -c ${ntpd_config} ${driftopt} -u ${ntpd_user:=ntpd:ntpd}" 118 119 # Unset ntpd_user because rc.subr uses $${name}_user to determine 120 # whether to invoke su(1) to setuid() to $ntpd_user for us. We want 121 # ntpd to do the setuid() itself through the -u argument, above. 122 unset ntpd_user 123 124 if checkyesno ntpd_sync_on_start; then 125 command_args="${command_args} -g" 126 fi 127 128 # Make sure the leapfile is ready to use, unless leapfile 129 # handling is disabled. 130 if leapfile_is_disabled; then 131 return 132 fi 133 134 ntpd_init_leapfile 135 if [ ! -f "${ntp_db_leapfile}" ]; then 136 ntpd_fetch_leapfile 137 fi 138} 139 140current_ntp_ts() { 141 # Seconds between 1900-01-01 and 1970-01-01 142 # echo $(((70*365+17)*86400)) 143 ntp_to_unix=2208988800 144 145 echo $(($(date -u +%s)+$ntp_to_unix)) 146} 147 148get_ntp_leapfile_ver() { 149 # Leapfile update date (version number). 150 expr "$(awk '$1 == "#$" { print $2 }' "$1" 2>/dev/null)" : \ 151 '^\([1-9][0-9]*\)$' \| 0 152} 153 154get_ntp_leapfile_expiry() { 155 # Leapfile expiry date. 156 expr "$(awk '$1 == "#@" { print $2 }' "$1" 2>/dev/null)" : \ 157 '^\([1-9][0-9]*\)$' \| 0 158} 159 160ntpd_init_leapfile() { 161 162 if leapfile_is_disabled; then 163 return 164 fi 165 166 # Refresh working leapfile with an invalid hash due to 167 # FreeBSD id header. Ntpd will ignore leapfiles with a 168 # mismatch hash. The file must be the virgin file from 169 # the source. 170 if [ ! -f $ntp_db_leapfile ]; then 171 cp -p $ntp_src_leapfile $ntp_db_leapfile 172 fi 173} 174 175ntpd_needfetch_leapfile() { 176 local rc verbose 177 178 if leapfile_is_disabled; then 179 # Return code 1: ntp leapfile fetch not needed 180 return 1 181 fi 182 183 if checkyesno ntp_leapfile_fetch_verbose; then 184 verbose=echo 185 else 186 verbose=: 187 fi 188 189 ntp_ver_no_src=$(get_ntp_leapfile_ver $ntp_src_leapfile) 190 ntp_expiry_src=$(get_ntp_leapfile_expiry $ntp_src_leapfile) 191 ntp_ver_no_db=$(get_ntp_leapfile_ver $ntp_db_leapfile) 192 ntp_expiry_db=$(get_ntp_leapfile_expiry $ntp_db_leapfile) 193 $verbose ntp_src_leapfile version is $ntp_ver_no_src expires $ntp_expiry_src 194 $verbose ntp_db_leapfile version is $ntp_ver_no_db expires $ntp_expiry_db 195 196 if [ "$ntp_ver_no_src" -gt "$ntp_ver_no_db" -o \ 197 "$ntp_ver_no_src" -eq "$ntp_ver_no_db" -a \ 198 "$ntp_expiry_src" -gt "$ntp_expiry_db" ]; then 199 $verbose replacing $ntp_db_leapfile with $ntp_src_leapfile 200 cp -p $ntp_src_leapfile $ntp_db_leapfile 201 ntp_ver_no_db=$ntp_ver_no_src 202 else 203 $verbose not replacing $ntp_db_leapfile with $ntp_src_leapfile 204 fi 205 ntp_leapfile_expiry_seconds=$((ntp_leapfile_expiry_days*86400)) 206 ntp_leap_expiry=$(get_ntp_leapfile_expiry $ntp_db_leapfile) 207 ntp_leap_fetch_date=$((ntp_leap_expiry-ntp_leapfile_expiry_seconds)) 208 if [ $(current_ntp_ts) -ge $ntp_leap_fetch_date ]; then 209 $verbose Within ntp leapfile expiry limit, initiating fetch 210 # Return code 0: ntp leapfile fetch needed 211 return 0 212 fi 213 # Return code 1: ntp leapfile fetch not needed 214 return 1 215} 216 217ntpd_fetch_leapfile() { 218 219 if leapfile_is_disabled; then 220 return 221 fi 222 223 if checkyesno ntp_leapfile_fetch_verbose; then 224 verbose=echo 225 else 226 verbose=: 227 fi 228 229 if ntpd_needfetch_leapfile ; then 230 for url in $ntp_leapfile_sources ; do 231 $verbose fetching $url 232 # Circumvent umask 027 and 077 in login.conf(5) 233 umask 022 234 fetch $ntp_leapfile_fetch_opts -o $_ntp_tmp_leapfile $url && break 235 done 236 ntp_ver_no_tmp=$(get_ntp_leapfile_ver $_ntp_tmp_leapfile) 237 ntp_expiry_tmp=$(get_ntp_leapfile_expiry $_ntp_tmp_leapfile) 238 if [ "$ntp_expiry_tmp" -gt "$ntp_expiry_db" -o \ 239 "$ntp_expiry_tmp" -eq "$ntp_expiry_db" -a \ 240 "$ntp_ver_no_tmp" -gt "$ntp_ver_no_db" ]; then 241 $verbose using $url as $ntp_db_leapfile 242 mv -f $_ntp_tmp_leapfile $ntp_db_leapfile || 243 $verbose "warning: cannot replace $ntp_db_leapfile (read-only fs?)" 244 else 245 $verbose using existing $ntp_db_leapfile 246 fi 247 fi 248} 249 250ntpd_resume() 251{ 252 run_rc_command restart 253} 254 255run_rc_command "$1" 256