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