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