xref: /openbsd-src/usr.sbin/ntpd/client.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: client.c,v 1.81 2008/06/10 03:51:53 naddy Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/param.h>
21 #include <errno.h>
22 #include <md5.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <unistd.h>
27 
28 #include "ntpd.h"
29 
30 int	client_update(struct ntp_peer *);
31 void	set_deadline(struct ntp_peer *, time_t);
32 
33 void
34 set_next(struct ntp_peer *p, time_t t)
35 {
36 	p->next = getmonotime() + t;
37 	p->deadline = 0;
38 }
39 
40 void
41 set_deadline(struct ntp_peer *p, time_t t)
42 {
43 	p->deadline = getmonotime() + t;
44 	p->next = 0;
45 }
46 
47 int
48 client_peer_init(struct ntp_peer *p)
49 {
50 	if ((p->query = calloc(1, sizeof(struct ntp_query))) == NULL)
51 		fatal("client_peer_init calloc");
52 	p->query->fd = -1;
53 	p->query->msg.status = MODE_CLIENT | (NTP_VERSION << 3);
54 	p->state = STATE_NONE;
55 	p->shift = 0;
56 	p->trustlevel = TRUSTLEVEL_PATHETIC;
57 	p->lasterror = 0;
58 	p->senderrors = 0;
59 
60 	return (client_addr_init(p));
61 }
62 
63 int
64 client_addr_init(struct ntp_peer *p)
65 {
66 	struct sockaddr_in	*sa_in;
67 	struct sockaddr_in6	*sa_in6;
68 	struct ntp_addr		*h;
69 
70 	for (h = p->addr; h != NULL; h = h->next) {
71 		switch (h->ss.ss_family) {
72 		case AF_INET:
73 			sa_in = (struct sockaddr_in *)&h->ss;
74 			if (ntohs(sa_in->sin_port) == 0)
75 				sa_in->sin_port = htons(123);
76 			p->state = STATE_DNS_DONE;
77 			break;
78 		case AF_INET6:
79 			sa_in6 = (struct sockaddr_in6 *)&h->ss;
80 			if (ntohs(sa_in6->sin6_port) == 0)
81 				sa_in6->sin6_port = htons(123);
82 			p->state = STATE_DNS_DONE;
83 			break;
84 		default:
85 			fatalx("king bula sez: wrong AF in client_addr_init");
86 			/* not reached */
87 		}
88 	}
89 
90 	p->query->fd = -1;
91 	set_next(p, 0);
92 
93 	return (0);
94 }
95 
96 int
97 client_nextaddr(struct ntp_peer *p)
98 {
99 	if (p->query->fd != -1) {
100 		close(p->query->fd);
101 		p->query->fd = -1;
102 	}
103 
104 	if (p->state == STATE_DNS_INPROGRESS)
105 		return (-1);
106 
107 	if (p->addr_head.a == NULL) {
108 		priv_host_dns(p->addr_head.name, p->id);
109 		p->state = STATE_DNS_INPROGRESS;
110 		return (-1);
111 	}
112 
113 	if ((p->addr = p->addr->next) == NULL)
114 		p->addr = p->addr_head.a;
115 
116 	p->shift = 0;
117 	p->trustlevel = TRUSTLEVEL_PATHETIC;
118 
119 	return (0);
120 }
121 
122 int
123 client_query(struct ntp_peer *p)
124 {
125 	int	tos = IPTOS_LOWDELAY;
126 
127 	if (p->addr == NULL && client_nextaddr(p) == -1) {
128 		set_next(p, MAX(SETTIME_TIMEOUT,
129 		    scale_interval(INTERVAL_QUERY_AGGRESSIVE)));
130 		return (0);
131 	}
132 
133 	if (p->state < STATE_DNS_DONE || p->addr == NULL)
134 		return (-1);
135 
136 	if (p->query->fd == -1) {
137 		struct sockaddr *sa = (struct sockaddr *)&p->addr->ss;
138 
139 		if ((p->query->fd = socket(p->addr->ss.ss_family, SOCK_DGRAM,
140 		    0)) == -1)
141 			fatal("client_query socket");
142 		if (connect(p->query->fd, sa, SA_LEN(sa)) == -1) {
143 			if (errno == ECONNREFUSED || errno == ENETUNREACH ||
144 			    errno == EHOSTUNREACH || errno == EADDRNOTAVAIL) {
145 				client_nextaddr(p);
146 				set_next(p, MAX(SETTIME_TIMEOUT,
147 				    scale_interval(INTERVAL_QUERY_AGGRESSIVE)));
148 				return (-1);
149 			} else
150 				fatal("client_query connect");
151 		}
152 		if (p->addr->ss.ss_family == AF_INET && setsockopt(p->query->fd,
153 		    IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1)
154 			log_warn("setsockopt IPTOS_LOWDELAY");
155 	}
156 
157 	/*
158 	 * Send out a random 64-bit number as our transmit time.  The NTP
159 	 * server will copy said number into the originate field on the
160 	 * response that it sends us.  This is totally legal per the SNTP spec.
161 	 *
162 	 * The impact of this is two fold: we no longer send out the current
163 	 * system time for the world to see (which may aid an attacker), and
164 	 * it gives us a (not very secure) way of knowing that we're not
165 	 * getting spoofed by an attacker that can't capture our traffic
166 	 * but can spoof packets from the NTP server we're communicating with.
167 	 *
168 	 * Save the real transmit timestamp locally.
169 	 */
170 
171 	p->query->msg.xmttime.int_partl = arc4random();
172 	p->query->msg.xmttime.fractionl = arc4random();
173 	p->query->xmttime = gettime_corrected();
174 
175 	if (ntp_sendmsg(p->query->fd, NULL, &p->query->msg,
176 	    NTP_MSGSIZE_NOAUTH, 0) == -1) {
177 		p->senderrors++;
178 		set_next(p, INTERVAL_QUERY_PATHETIC);
179 		p->trustlevel = TRUSTLEVEL_PATHETIC;
180 		return (-1);
181 	}
182 
183 	p->senderrors = 0;
184 	p->state = STATE_QUERY_SENT;
185 	set_deadline(p, QUERYTIME_MAX);
186 
187 	return (0);
188 }
189 
190 int
191 client_dispatch(struct ntp_peer *p, u_int8_t settime)
192 {
193 	char			 buf[NTP_MSGSIZE];
194 	ssize_t			 size;
195 	struct ntp_msg		 msg;
196 	double			 T1, T2, T3, T4;
197 	time_t			 interval;
198 
199 	if ((size = recvfrom(p->query->fd, &buf, sizeof(buf), 0,
200 	    NULL, NULL)) == -1) {
201 		if (errno == EHOSTUNREACH || errno == EHOSTDOWN ||
202 		    errno == ENETUNREACH || errno == ENETDOWN ||
203 		    errno == ECONNREFUSED || errno == EADDRNOTAVAIL) {
204 			client_log_error(p, "recvfrom", errno);
205 			set_next(p, error_interval());
206 			return (0);
207 		} else
208 			fatal("recvfrom");
209 	}
210 
211 	T4 = gettime_corrected();
212 
213 	ntp_getmsg((struct sockaddr *)&p->addr->ss, buf, size, &msg);
214 
215 	if (msg.orgtime.int_partl != p->query->msg.xmttime.int_partl ||
216 	    msg.orgtime.fractionl != p->query->msg.xmttime.fractionl)
217 		return (0);
218 
219 	if ((msg.status & LI_ALARM) == LI_ALARM || msg.stratum == 0 ||
220 	    msg.stratum > NTP_MAXSTRATUM) {
221 		interval = error_interval();
222 		set_next(p, interval);
223 		log_info("reply from %s: not synced, next query %ds",
224 		    log_sockaddr((struct sockaddr *)&p->addr->ss), interval);
225 		return (0);
226 	}
227 
228 	/*
229 	 * From RFC 2030 (with a correction to the delay math):
230 	 *
231 	 *     Timestamp Name          ID   When Generated
232 	 *     ------------------------------------------------------------
233 	 *     Originate Timestamp     T1   time request sent by client
234 	 *     Receive Timestamp       T2   time request received by server
235 	 *     Transmit Timestamp      T3   time reply sent by server
236 	 *     Destination Timestamp   T4   time reply received by client
237 	 *
238 	 *  The roundtrip delay d and local clock offset t are defined as
239 	 *
240 	 *    d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2.
241 	 */
242 
243 	T1 = p->query->xmttime;
244 	T2 = lfp_to_d(msg.rectime);
245 	T3 = lfp_to_d(msg.xmttime);
246 
247 	p->reply[p->shift].offset = ((T2 - T1) + (T3 - T4)) / 2;
248 	p->reply[p->shift].delay = (T4 - T1) - (T3 - T2);
249 	if (p->reply[p->shift].delay < 0) {
250 		interval = error_interval();
251 		set_next(p, interval);
252 		log_info("reply from %s: negative delay %fs, "
253 		    "next query %ds",
254 		    log_sockaddr((struct sockaddr *)&p->addr->ss),
255 		    p->reply[p->shift].delay, interval);
256 		return (0);
257 	}
258 	p->reply[p->shift].error = (T2 - T1) - (T3 - T4);
259 	p->reply[p->shift].rcvd = getmonotime();
260 	p->reply[p->shift].good = 1;
261 
262 	p->reply[p->shift].status.leap = (msg.status & LIMASK);
263 	p->reply[p->shift].status.precision = msg.precision;
264 	p->reply[p->shift].status.rootdelay = sfp_to_d(msg.rootdelay);
265 	p->reply[p->shift].status.rootdispersion = sfp_to_d(msg.dispersion);
266 	p->reply[p->shift].status.refid = ntohl(msg.refid);
267 	p->reply[p->shift].status.reftime = lfp_to_d(msg.reftime);
268 	p->reply[p->shift].status.poll = msg.ppoll;
269 	p->reply[p->shift].status.stratum = msg.stratum;
270 
271 	if (p->addr->ss.ss_family == AF_INET) {
272 		p->reply[p->shift].status.send_refid =
273 		    ((struct sockaddr_in *)&p->addr->ss)->sin_addr.s_addr;
274 	} else if (p->addr->ss.ss_family == AF_INET6) {
275 		MD5_CTX		context;
276 		u_int8_t	digest[MD5_DIGEST_LENGTH];
277 
278 		MD5Init(&context);
279 		MD5Update(&context, ((struct sockaddr_in6 *)&p->addr->ss)->
280 		    sin6_addr.s6_addr, sizeof(struct in6_addr));
281 		MD5Final(digest, &context);
282 		memcpy((char *)&p->reply[p->shift].status.send_refid, digest,
283 		    sizeof(u_int32_t));
284 	} else
285 		p->reply[p->shift].status.send_refid = msg.xmttime.fractionl;
286 
287 	if (p->trustlevel < TRUSTLEVEL_PATHETIC)
288 		interval = scale_interval(INTERVAL_QUERY_PATHETIC);
289 	else if (p->trustlevel < TRUSTLEVEL_AGGRESSIVE)
290 		interval = scale_interval(INTERVAL_QUERY_AGGRESSIVE);
291 	else
292 		interval = scale_interval(INTERVAL_QUERY_NORMAL);
293 
294 	set_next(p, interval);
295 	p->state = STATE_REPLY_RECEIVED;
296 
297 	/* every received reply which we do not discard increases trust */
298 	if (p->trustlevel < TRUSTLEVEL_MAX) {
299 		if (p->trustlevel < TRUSTLEVEL_BADPEER &&
300 		    p->trustlevel + 1 >= TRUSTLEVEL_BADPEER)
301 			log_info("peer %s now valid",
302 			    log_sockaddr((struct sockaddr *)&p->addr->ss));
303 		p->trustlevel++;
304 	}
305 
306 	log_debug("reply from %s: offset %f delay %f, "
307 	    "next query %ds", log_sockaddr((struct sockaddr *)&p->addr->ss),
308 	    p->reply[p->shift].offset, p->reply[p->shift].delay, interval);
309 
310 	client_update(p);
311 	if (settime)
312 		priv_settime(p->reply[p->shift].offset);
313 
314 	if (++p->shift >= OFFSET_ARRAY_SIZE)
315 		p->shift = 0;
316 
317 	return (0);
318 }
319 
320 int
321 client_update(struct ntp_peer *p)
322 {
323 	int	i, best = 0, good = 0;
324 
325 	/*
326 	 * clock filter
327 	 * find the offset which arrived with the lowest delay
328 	 * use that as the peer update
329 	 * invalidate it and all older ones
330 	 */
331 
332 	for (i = 0; good == 0 && i < OFFSET_ARRAY_SIZE; i++)
333 		if (p->reply[i].good) {
334 			good++;
335 			best = i;
336 		}
337 
338 	for (; i < OFFSET_ARRAY_SIZE; i++)
339 		if (p->reply[i].good) {
340 			good++;
341 			if (p->reply[i].delay < p->reply[best].delay)
342 				best = i;
343 		}
344 
345 	if (good < 8)
346 		return (-1);
347 
348 	memcpy(&p->update, &p->reply[best], sizeof(p->update));
349 	if (priv_adjtime() == 0) {
350 		for (i = 0; i < OFFSET_ARRAY_SIZE; i++)
351 			if (p->reply[i].rcvd <= p->reply[best].rcvd)
352 				p->reply[i].good = 0;
353 	}
354 	return (0);
355 }
356 
357 void
358 client_log_error(struct ntp_peer *peer, const char *operation, int error)
359 {
360 	const char *address;
361 
362 	address = log_sockaddr((struct sockaddr *)&peer->addr->ss);
363 	if (peer->lasterror == error) {
364 		log_debug("%s %s: %s", operation, address, strerror(error));
365 		return;
366 	}
367 	peer->lasterror = error;
368 	log_warn("%s %s", operation, address);
369 }
370