GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/rdate/ntp.c Lines: 0 153 0.0 %
Date: 2017-11-07 Branches: 0 82 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ntp.c,v 1.33 2015/01/16 06:40:20 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 1996, 1997 by N.M. Maclaren. All rights reserved.
5
 * Copyright (c) 1996, 1997 by University of Cambridge. All rights reserved.
6
 * Copyright (c) 2002 by Thorsten "mirabile" Glaser.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the author nor the university may be used to
17
 *    endorse or promote products derived from this software without
18
 *    specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#include <sys/socket.h>
33
#include <sys/time.h>
34
#include <netinet/in.h>
35
#include <arpa/inet.h>
36
37
#include <ctype.h>
38
#include <err.h>
39
#include <errno.h>
40
#include <fcntl.h>
41
#include <float.h>
42
#include <limits.h>
43
#include <math.h>
44
#include <netdb.h>
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include <string.h>
48
#include <time.h>
49
#include <poll.h>
50
#include <unistd.h>
51
52
#include "ntpleaps.h"
53
54
/*
55
 * NTP definitions.  Note that these assume 8-bit bytes - sigh.  There
56
 * is little point in parameterising everything, as it is neither
57
 * feasible nor useful.  It would be very useful if more fields could
58
 * be defined as unspecified.  The NTP packet-handling routines
59
 * contain a lot of extra assumptions.
60
 */
61
62
#define JAN_1970   2208988800.0		/* 1970 - 1900 in seconds */
63
#define NTP_SCALE  4294967296.0		/* 2^32, of course! */
64
65
#define NTP_MODE_CLIENT       3		/* NTP client mode */
66
#define NTP_MODE_SERVER       4		/* NTP server mode */
67
#define NTP_VERSION           4		/* The current version */
68
#define NTP_VERSION_MIN       1		/* The minimum valid version */
69
#define NTP_VERSION_MAX       4		/* The maximum valid version */
70
#define NTP_STRATUM_MAX      14		/* The maximum valid stratum */
71
#define NTP_INSANITY     3600.0		/* Errors beyond this are hopeless */
72
73
#define NTP_PACKET_MIN       48		/* Without authentication */
74
#define NTP_PACKET_MAX       68		/* With authentication (ignored) */
75
76
#define NTP_DISP_FIELD        8		/* Offset of dispersion field */
77
#define NTP_REFERENCE        16		/* Offset of reference timestamp */
78
#define NTP_ORIGINATE        24		/* Offset of originate timestamp */
79
#define NTP_RECEIVE          32		/* Offset of receive timestamp */
80
#define NTP_TRANSMIT         40		/* Offset of transmit timestamp */
81
82
#define STATUS_NOWARNING      0		/* No Leap Indicator */
83
#define STATUS_LEAPHIGH       1		/* Last Minute Has 61 Seconds */
84
#define STATUS_LEAPLOW        2		/* Last Minute Has 59 Seconds */
85
#define STATUS_ALARM          3		/* Server Clock Not Synchronized */
86
87
#define MAX_QUERIES         25
88
#define MAX_DELAY           15
89
90
#define MILLION_L    1000000l		/* For conversion to/from timeval */
91
#define MILLION_D       1.0e6		/* Must be equal to MILLION_L */
92
93
struct ntp_data {
94
	u_char		status;
95
	u_char		version;
96
	u_char		mode;
97
	u_char		stratum;
98
	double		receive;
99
	double		transmit;
100
	double		current;
101
	u_int64_t	recvck;
102
103
	/* Local State */
104
	double		originate;
105
	u_int64_t	xmitck;
106
};
107
108
void	ntp_client(const char *, int, struct timeval *, struct timeval *, int);
109
int	sync_ntp(int, const struct sockaddr *, double *, double *);
110
int	write_packet(int, struct ntp_data *);
111
int	read_packet(int, struct ntp_data *, double *, double *);
112
void	unpack_ntp(struct ntp_data *, u_char *);
113
double	current_time(double);
114
void	create_timeval(double, struct timeval *, struct timeval *);
115
116
#ifdef DEBUG
117
void	print_packet(const struct ntp_data *);
118
#endif
119
120
int	corrleaps;
121
122
void
123
ntp_client(const char *hostname, int family, struct timeval *new,
124
    struct timeval *adjust, int leapflag)
125
{
126
	struct addrinfo hints, *res0, *res;
127
	double offset, error;
128
	int accept = 0, ret, s, ierror;
129
130
	memset(&hints, 0, sizeof(hints));
131
	hints.ai_family = family;
132
	hints.ai_socktype = SOCK_DGRAM;
133
	ierror = getaddrinfo(hostname, "ntp", &hints, &res0);
134
	if (ierror) {
135
		errx(1, "%s: %s", hostname, gai_strerror(ierror));
136
		/*NOTREACHED*/
137
	}
138
139
	corrleaps = leapflag;
140
	if (corrleaps)
141
		ntpleaps_init();
142
143
	s = -1;
144
	for (res = res0; res; res = res->ai_next) {
145
		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
146
		if (s < 0)
147
			continue;
148
149
		ret = sync_ntp(s, res->ai_addr, &offset, &error);
150
		if (ret < 0) {
151
#ifdef DEBUG
152
			fprintf(stderr, "try the next address\n");
153
#endif
154
			close(s);
155
			s = -1;
156
			continue;
157
		}
158
159
		accept++;
160
		break;
161
	}
162
	freeaddrinfo(res0);
163
164
#ifdef DEBUG
165
	fprintf(stderr, "Correction: %.6f +/- %.6f\n", offset, error);
166
#endif
167
168
	if (accept < 1)
169
		errx(1, "Unable to get a reasonable time estimate");
170
171
	create_timeval(offset, new, adjust);
172
}
173
174
int
175
sync_ntp(int fd, const struct sockaddr *peer, double *offset, double *error)
176
{
177
	int attempts = 0, accepts = 0, rejects = 0;
178
	int delay = MAX_DELAY, ret;
179
	double deadline;
180
	double a, b, x, y;
181
	double minerr = 0.1;		/* Maximum ignorable variation */
182
	struct ntp_data data;
183
184
	deadline = current_time(JAN_1970) + delay;
185
	*offset = 0.0;
186
	*error = NTP_INSANITY;
187
188
	if (connect(fd, peer, SA_LEN(peer)) < 0) {
189
		warn("Failed to connect to server");
190
		return (-1);
191
	}
192
193
	while (accepts < MAX_QUERIES && attempts < 2 * MAX_QUERIES) {
194
		memset(&data, 0, sizeof(data));
195
196
		if (current_time(JAN_1970) > deadline) {
197
			warnx("Not enough valid responses received in time");
198
			return (-1);
199
		}
200
201
		if (write_packet(fd, &data) < 0)
202
			return (-1);
203
204
		ret = read_packet(fd, &data, &x, &y);
205
206
		if (ret < 0)
207
			return (-1);
208
		else if (ret > 0) {
209
#ifdef DEBUG
210
			print_packet(&data);
211
#endif
212
213
			if (++rejects > MAX_QUERIES) {
214
				warnx("Too many bad or lost packets");
215
				return (-1);
216
			} else
217
				continue;
218
		} else
219
			++accepts;
220
221
#ifdef DEBUG
222
		fprintf(stderr, "Offset: %.6f +/- %.6f\n", x, y);
223
#endif
224
225
		if ((a = x - *offset) < 0.0)
226
			a = -a;
227
		if (accepts <= 1)
228
			a = 0.0;
229
		b = *error + y;
230
		if (y < *error) {
231
			*offset = x;
232
			*error = y;
233
		}
234
235
#ifdef DEBUG
236
		fprintf(stderr, "Best: %.6f +/- %.6f\n", *offset, *error);
237
#endif
238
239
		if (a > b) {
240
			warnx("Inconsistent times received from NTP server");
241
			return (-1);
242
		}
243
244
		if ((data.status & STATUS_ALARM) == STATUS_ALARM) {
245
			warnx("Ignoring NTP server with alarm flag set");
246
			return (-1);
247
		}
248
249
		if (*error <= minerr)
250
			break;
251
	}
252
253
	return (accepts);
254
}
255
256
/* Send out NTP packet. */
257
int
258
write_packet(int fd, struct ntp_data *data)
259
{
260
	u_char	packet[NTP_PACKET_MIN];
261
	ssize_t	length;
262
263
	memset(packet, 0, sizeof(packet));
264
265
	packet[0] = (NTP_VERSION << 3) | (NTP_MODE_CLIENT);
266
267
	arc4random_buf(&data->xmitck, sizeof(data->xmitck));
268
269
	/*
270
	 * Send out a random 64-bit number as our transmit time.  The NTP
271
	 * server will copy said number into the originate field on the
272
	 * response that it sends us.  This is totally legal per the SNTP spec.
273
	 *
274
	 * The impact of this is two fold: we no longer send out the current
275
	 * system time for the world to see (which may aid an attacker), and
276
	 * it gives us a (not very secure) way of knowing that we're not
277
	 * getting spoofed by an attacker that can't capture our traffic
278
	 * but can spoof packets from the NTP server we're communicating with.
279
	 *
280
	 * No endian concerns here.  Since we're running as a strict
281
	 * unicast client, we don't have to worry about anyone else finding
282
	 * the transmit field intelligible.
283
	 */
284
285
	bcopy(&data->xmitck, (packet + NTP_TRANSMIT), sizeof(data->xmitck));
286
287
	data->originate = current_time(JAN_1970);
288
289
	length = write(fd, packet, sizeof(packet));
290
291
	if (length != sizeof(packet)) {
292
		warn("Unable to send NTP packet to server");
293
		return (-1);
294
	}
295
296
	return (0);
297
}
298
299
/*
300
 * Check the packet and work out the offset and optionally the error.
301
 * Note that this contains more checking than xntp does. Return 0 for
302
 * success, 1 for failure. Note that it must not change its arguments
303
 * if it fails.
304
 */
305
int
306
read_packet(int fd, struct ntp_data *data, double *off, double *error)
307
{
308
	u_char	receive[NTP_PACKET_MAX];
309
	struct	pollfd pfd[1];
310
	double	x, y;
311
	int	length, r;
312
313
	pfd[0].fd = fd;
314
	pfd[0].events = POLLIN;
315
316
retry:
317
	r = poll(pfd, 1, 1000 * MAX_DELAY / MAX_QUERIES);
318
	if (r < 0) {
319
		if (errno == EINTR)
320
			goto retry;
321
		warn("select");
322
		return (r);
323
	}
324
325
	if (r != 1)
326
		return (1);
327
	if ((pfd[0].revents & POLLIN) == 0)
328
		return (1);
329
330
	length = read(fd, receive, NTP_PACKET_MAX);
331
	if (length < 0) {
332
		warn("Unable to receive NTP packet from server");
333
		return (-1);
334
	}
335
336
	if (length < NTP_PACKET_MIN || length > NTP_PACKET_MAX) {
337
		warnx("Invalid NTP packet size, packet rejected");
338
		return (1);
339
	}
340
341
	unpack_ntp(data, receive);
342
343
	if (data->recvck != data->xmitck) {
344
		warnx("Invalid cookie received, packet rejected");
345
		return (1);
346
	}
347
348
	if (data->version < NTP_VERSION_MIN ||
349
	    data->version > NTP_VERSION_MAX) {
350
		warnx("Received NTP version %u, need %u or lower",
351
		    data->version, NTP_VERSION);
352
		return (1);
353
	}
354
355
	if (data->mode != NTP_MODE_SERVER) {
356
		warnx("Invalid NTP server mode, packet rejected");
357
		return (1);
358
	}
359
360
	if (data->stratum > NTP_STRATUM_MAX) {
361
		warnx("Invalid stratum received, packet rejected");
362
		return (1);
363
	}
364
365
	if (data->transmit == 0.0) {
366
		warnx("Server clock invalid, packet rejected");
367
		return (1);
368
	}
369
370
	x = data->receive - data->originate;
371
	y = data->transmit - data->current;
372
373
	*off = (x + y) / 2;
374
	*error = x - y;
375
376
	x = (data->current - data->originate) / 2;
377
378
	if (x > *error)
379
		*error = x;
380
381
	return (0);
382
}
383
384
/*
385
 * Unpack the essential data from an NTP packet, bypassing struct
386
 * layout and endian problems.  Note that it ignores fields irrelevant
387
 * to SNTP.
388
 */
389
void
390
unpack_ntp(struct ntp_data *data, u_char *packet)
391
{
392
	int i;
393
	double d;
394
395
	data->current = current_time(JAN_1970);
396
397
	data->status = (packet[0] >> 6);
398
	data->version = (packet[0] >> 3) & 0x07;
399
	data->mode = packet[0] & 0x07;
400
	data->stratum = packet[1];
401
402
	for (i = 0, d = 0.0; i < 8; ++i)
403
	    d = 256.0*d+packet[NTP_RECEIVE+i];
404
405
	data->receive = d / NTP_SCALE;
406
407
	for (i = 0, d = 0.0; i < 8; ++i)
408
	    d = 256.0*d+packet[NTP_TRANSMIT+i];
409
410
	data->transmit = d / NTP_SCALE;
411
412
	/* See write_packet for why this isn't an endian problem. */
413
	bcopy((packet + NTP_ORIGINATE), &data->recvck, sizeof(data->recvck));
414
}
415
416
/*
417
 * Get the current UTC time in seconds since the Epoch plus an offset
418
 * (usually the time from the beginning of the century to the Epoch)
419
 */
420
double
421
current_time(double offset)
422
{
423
	struct timeval current;
424
	u_int64_t t;
425
426
	if (gettimeofday(&current, NULL))
427
		err(1, "Could not get local time of day");
428
429
	/*
430
	 * At this point, current has the current TAI time.
431
	 * Now subtract leap seconds to set the posix tick.
432
	 */
433
434
	t = SEC_TO_TAI64(current.tv_sec);
435
	if (corrleaps)
436
		ntpleaps_sub(&t);
437
438
	return (offset + TAI64_TO_SEC(t) + 1.0e-6 * current.tv_usec);
439
}
440
441
/*
442
 * Change offset into current UTC time. This is portable, even if
443
 * struct timeval uses an unsigned long for tv_sec.
444
 */
445
void
446
create_timeval(double difference, struct timeval *new, struct timeval *adjust)
447
{
448
	struct timeval old;
449
	long n;
450
451
	/* Start by converting to timeval format. Note that we have to
452
	 * cater for negative, unsigned values. */
453
	if ((n = (long) difference) > difference)
454
		--n;
455
	adjust->tv_sec = n;
456
	adjust->tv_usec = (long) (MILLION_D * (difference-n));
457
	errno = 0;
458
	if (gettimeofday(&old, NULL))
459
		err(1, "Could not get local time of day");
460
	new->tv_sec = old.tv_sec + adjust->tv_sec;
461
	new->tv_usec = (n = (long) old.tv_usec + (long) adjust->tv_usec);
462
463
	if (n < 0) {
464
		new->tv_usec += MILLION_L;
465
		--new->tv_sec;
466
	} else if (n >= MILLION_L) {
467
		new->tv_usec -= MILLION_L;
468
		++new->tv_sec;
469
	}
470
}
471
472
#ifdef DEBUG
473
void
474
print_packet(const struct ntp_data *data)
475
{
476
	printf("status:      %u\n", data->status);
477
	printf("version:     %u\n", data->version);
478
	printf("mode:        %u\n", data->mode);
479
	printf("stratum:     %u\n", data->stratum);
480
	printf("originate:   %f\n", data->originate);
481
	printf("receive:     %f\n", data->receive);
482
	printf("transmit:    %f\n", data->transmit);
483
	printf("current:     %f\n", data->current);
484
	printf("xmitck:      0x%0llX\n", data->xmitck);
485
	printf("recvck:      0x%0llX\n", data->recvck);
486
};
487
#endif