1 /* $OpenBSD: ntp.c,v 1.36 2020/01/09 19:37:56 tb 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 if (pledge("stdio inet", NULL) == -1) 140 err(1, "pledge"); 141 142 corrleaps = leapflag; 143 if (corrleaps) 144 ntpleaps_init(); 145 146 s = -1; 147 for (res = res0; res; res = res->ai_next) { 148 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 149 if (s == -1) 150 continue; 151 152 ret = sync_ntp(s, res->ai_addr, &offset, &error); 153 if (ret < 0) { 154 #ifdef DEBUG 155 fprintf(stderr, "try the next address\n"); 156 #endif 157 close(s); 158 s = -1; 159 continue; 160 } 161 162 accept++; 163 break; 164 } 165 freeaddrinfo(res0); 166 167 #ifdef DEBUG 168 fprintf(stderr, "Correction: %.6f +/- %.6f\n", offset, error); 169 #endif 170 171 if (accept < 1) 172 errx(1, "Unable to get a reasonable time estimate"); 173 174 create_timeval(offset, new, adjust); 175 } 176 177 int 178 sync_ntp(int fd, const struct sockaddr *peer, double *offset, double *error) 179 { 180 int accepts = 0, rejects = 0; 181 int delay = MAX_DELAY, ret; 182 double deadline; 183 double a, b, x, y; 184 double minerr = 0.1; /* Maximum ignorable variation */ 185 struct ntp_data data; 186 187 deadline = current_time(JAN_1970) + delay; 188 *offset = 0.0; 189 *error = NTP_INSANITY; 190 191 if (connect(fd, peer, SA_LEN(peer)) == -1) { 192 warn("Failed to connect to server"); 193 return (-1); 194 } 195 196 while (accepts < MAX_QUERIES) { 197 memset(&data, 0, sizeof(data)); 198 199 if (current_time(JAN_1970) > deadline) { 200 warnx("Not enough valid responses received in time"); 201 return (-1); 202 } 203 204 if (write_packet(fd, &data) < 0) 205 return (-1); 206 207 ret = read_packet(fd, &data, &x, &y); 208 209 if (ret < 0) 210 return (-1); 211 else if (ret > 0) { 212 #ifdef DEBUG 213 print_packet(&data); 214 #endif 215 216 if (++rejects > MAX_QUERIES) { 217 warnx("Too many bad or lost packets"); 218 return (-1); 219 } else 220 continue; 221 } else 222 ++accepts; 223 224 #ifdef DEBUG 225 fprintf(stderr, "Offset: %.6f +/- %.6f\n", x, y); 226 #endif 227 228 if ((a = x - *offset) < 0.0) 229 a = -a; 230 if (accepts <= 1) 231 a = 0.0; 232 b = *error + y; 233 if (y < *error) { 234 *offset = x; 235 *error = y; 236 } 237 238 #ifdef DEBUG 239 fprintf(stderr, "Best: %.6f +/- %.6f\n", *offset, *error); 240 #endif 241 242 if (a > b) { 243 warnx("Inconsistent times received from NTP server"); 244 return (-1); 245 } 246 247 if ((data.status & STATUS_ALARM) == STATUS_ALARM) { 248 warnx("Ignoring NTP server with alarm flag set"); 249 return (-1); 250 } 251 252 if (*error <= minerr) 253 break; 254 } 255 256 return (accepts); 257 } 258 259 /* Send out NTP packet. */ 260 int 261 write_packet(int fd, struct ntp_data *data) 262 { 263 u_char packet[NTP_PACKET_MIN]; 264 ssize_t length; 265 266 memset(packet, 0, sizeof(packet)); 267 268 packet[0] = (NTP_VERSION << 3) | (NTP_MODE_CLIENT); 269 270 arc4random_buf(&data->xmitck, sizeof(data->xmitck)); 271 272 /* 273 * Send out a random 64-bit number as our transmit time. The NTP 274 * server will copy said number into the originate field on the 275 * response that it sends us. This is totally legal per the SNTP spec. 276 * 277 * The impact of this is two fold: we no longer send out the current 278 * system time for the world to see (which may aid an attacker), and 279 * it gives us a (not very secure) way of knowing that we're not 280 * getting spoofed by an attacker that can't capture our traffic 281 * but can spoof packets from the NTP server we're communicating with. 282 * 283 * No endian concerns here. Since we're running as a strict 284 * unicast client, we don't have to worry about anyone else finding 285 * the transmit field intelligible. 286 */ 287 288 bcopy(&data->xmitck, (packet + NTP_TRANSMIT), sizeof(data->xmitck)); 289 290 data->originate = current_time(JAN_1970); 291 292 length = write(fd, packet, sizeof(packet)); 293 294 if (length != sizeof(packet)) { 295 warn("Unable to send NTP packet to server"); 296 return (-1); 297 } 298 299 return (0); 300 } 301 302 /* 303 * Check the packet and work out the offset and optionally the error. 304 * Note that this contains more checking than xntp does. Return 0 for 305 * success, 1 for failure. Note that it must not change its arguments 306 * if it fails. 307 */ 308 int 309 read_packet(int fd, struct ntp_data *data, double *off, double *error) 310 { 311 u_char receive[NTP_PACKET_MAX]; 312 struct pollfd pfd[1]; 313 double x, y; 314 int length, r; 315 316 pfd[0].fd = fd; 317 pfd[0].events = POLLIN; 318 319 retry: 320 r = poll(pfd, 1, 1000 * MAX_DELAY / MAX_QUERIES); 321 if (r == -1) { 322 if (errno == EINTR) 323 goto retry; 324 warn("select"); 325 return (r); 326 } 327 328 if (r != 1) 329 return (1); 330 if ((pfd[0].revents & POLLIN) == 0) 331 return (1); 332 333 length = read(fd, receive, NTP_PACKET_MAX); 334 if (length == -1) { 335 warn("Unable to receive NTP packet from server"); 336 return (-1); 337 } 338 339 if (length < NTP_PACKET_MIN || length > NTP_PACKET_MAX) { 340 warnx("Invalid NTP packet size, packet rejected"); 341 return (1); 342 } 343 344 unpack_ntp(data, receive); 345 346 if (data->recvck != data->xmitck) { 347 warnx("Invalid cookie received, packet rejected"); 348 return (1); 349 } 350 351 if (data->version < NTP_VERSION_MIN || 352 data->version > NTP_VERSION_MAX) { 353 warnx("Received NTP version %u, need %u or lower", 354 data->version, NTP_VERSION); 355 return (1); 356 } 357 358 if (data->mode != NTP_MODE_SERVER) { 359 warnx("Invalid NTP server mode, packet rejected"); 360 return (1); 361 } 362 363 if (data->stratum > NTP_STRATUM_MAX) { 364 warnx("Invalid stratum received, packet rejected"); 365 return (1); 366 } 367 368 if (data->transmit == 0.0) { 369 warnx("Server clock invalid, packet rejected"); 370 return (1); 371 } 372 373 x = data->receive - data->originate; 374 y = data->transmit - data->current; 375 376 *off = (x + y) / 2; 377 *error = x - y; 378 379 x = (data->current - data->originate) / 2; 380 381 if (x > *error) 382 *error = x; 383 384 return (0); 385 } 386 387 /* 388 * Unpack the essential data from an NTP packet, bypassing struct 389 * layout and endian problems. Note that it ignores fields irrelevant 390 * to SNTP. 391 */ 392 void 393 unpack_ntp(struct ntp_data *data, u_char *packet) 394 { 395 int i; 396 double d; 397 398 data->current = current_time(JAN_1970); 399 400 data->status = (packet[0] >> 6); 401 data->version = (packet[0] >> 3) & 0x07; 402 data->mode = packet[0] & 0x07; 403 data->stratum = packet[1]; 404 405 for (i = 0, d = 0.0; i < 8; ++i) 406 d = 256.0*d+packet[NTP_RECEIVE+i]; 407 408 data->receive = d / NTP_SCALE; 409 410 for (i = 0, d = 0.0; i < 8; ++i) 411 d = 256.0*d+packet[NTP_TRANSMIT+i]; 412 413 data->transmit = d / NTP_SCALE; 414 415 /* See write_packet for why this isn't an endian problem. */ 416 bcopy((packet + NTP_ORIGINATE), &data->recvck, sizeof(data->recvck)); 417 } 418 419 /* 420 * Get the current UTC time in seconds since the Epoch plus an offset 421 * (usually the time from the beginning of the century to the Epoch) 422 */ 423 double 424 current_time(double offset) 425 { 426 struct timeval current; 427 u_int64_t t; 428 429 if (gettimeofday(¤t, NULL)) 430 err(1, "Could not get local time of day"); 431 432 /* 433 * At this point, current has the current TAI time. 434 * Now subtract leap seconds to set the posix tick. 435 */ 436 437 t = SEC_TO_TAI64(current.tv_sec); 438 if (corrleaps) 439 ntpleaps_sub(&t); 440 441 return (offset + TAI64_TO_SEC(t) + 1.0e-6 * current.tv_usec); 442 } 443 444 /* 445 * Change offset into current UTC time. This is portable, even if 446 * struct timeval uses an unsigned long for tv_sec. 447 */ 448 void 449 create_timeval(double difference, struct timeval *new, struct timeval *adjust) 450 { 451 struct timeval old; 452 long n; 453 454 /* Start by converting to timeval format. Note that we have to 455 * cater for negative, unsigned values. */ 456 if ((n = (long) difference) > difference) 457 --n; 458 adjust->tv_sec = n; 459 adjust->tv_usec = (long) (MILLION_D * (difference-n)); 460 errno = 0; 461 if (gettimeofday(&old, NULL)) 462 err(1, "Could not get local time of day"); 463 new->tv_sec = old.tv_sec + adjust->tv_sec; 464 new->tv_usec = (n = (long) old.tv_usec + (long) adjust->tv_usec); 465 466 if (n < 0) { 467 new->tv_usec += MILLION_L; 468 --new->tv_sec; 469 } else if (n >= MILLION_L) { 470 new->tv_usec -= MILLION_L; 471 ++new->tv_sec; 472 } 473 } 474 475 #ifdef DEBUG 476 void 477 print_packet(const struct ntp_data *data) 478 { 479 printf("status: %u\n", data->status); 480 printf("version: %u\n", data->version); 481 printf("mode: %u\n", data->mode); 482 printf("stratum: %u\n", data->stratum); 483 printf("originate: %f\n", data->originate); 484 printf("receive: %f\n", data->receive); 485 printf("transmit: %f\n", data->transmit); 486 printf("current: %f\n", data->current); 487 printf("xmitck: 0x%0llX\n", data->xmitck); 488 printf("recvck: 0x%0llX\n", data->recvck); 489 }; 490 #endif 491