1 /* $OpenBSD: ntp.c,v 1.30 2010/08/16 11:09:26 krw 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/param.h> 33 #include <sys/socket.h> 34 #include <sys/time.h> 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 38 #include <ctype.h> 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <float.h> 43 #include <limits.h> 44 #include <math.h> 45 #include <netdb.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <time.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 minum 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 data->xmitck = (u_int64_t)arc4random() << 32 | arc4random(); 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 timeval tv; 310 double x, y; 311 int length, r; 312 fd_set *rfds; 313 314 rfds = calloc(howmany(fd + 1, NFDBITS), sizeof(fd_mask)); 315 if (rfds == NULL) 316 err(1, "calloc"); 317 318 FD_SET(fd, rfds); 319 320 retry: 321 tv.tv_sec = 0; 322 tv.tv_usec = 1000000 * MAX_DELAY / MAX_QUERIES; 323 324 r = select(fd + 1, rfds, NULL, NULL, &tv); 325 326 if (r < 0) { 327 if (errno == EINTR) 328 goto retry; 329 else 330 warn("select"); 331 332 free(rfds); 333 return (r); 334 } 335 336 if (r != 1 || !FD_ISSET(fd, rfds)) { 337 free(rfds); 338 return (1); 339 } 340 341 free(rfds); 342 343 length = read(fd, receive, NTP_PACKET_MAX); 344 345 if (length < 0) { 346 warn("Unable to receive NTP packet from server"); 347 return (-1); 348 } 349 350 if (length < NTP_PACKET_MIN || length > NTP_PACKET_MAX) { 351 warnx("Invalid NTP packet size, packet rejected"); 352 return (1); 353 } 354 355 unpack_ntp(data, receive); 356 357 if (data->recvck != data->xmitck) { 358 warnx("Invalid cookie received, packet rejected"); 359 return (1); 360 } 361 362 if (data->version < NTP_VERSION_MIN || 363 data->version > NTP_VERSION_MAX) { 364 warnx("Received NTP version %u, need %u or lower", 365 data->version, NTP_VERSION); 366 return (1); 367 } 368 369 if (data->mode != NTP_MODE_SERVER) { 370 warnx("Invalid NTP server mode, packet rejected"); 371 return (1); 372 } 373 374 if (data->stratum > NTP_STRATUM_MAX) { 375 warnx("Invalid stratum received, packet rejected"); 376 return (1); 377 } 378 379 if (data->transmit == 0.0) { 380 warnx("Server clock invalid, packet rejected"); 381 return (1); 382 } 383 384 x = data->receive - data->originate; 385 y = data->transmit - data->current; 386 387 *off = (x + y) / 2; 388 *error = x - y; 389 390 x = (data->current - data->originate) / 2; 391 392 if (x > *error) 393 *error = x; 394 395 return (0); 396 } 397 398 /* 399 * Unpack the essential data from an NTP packet, bypassing struct 400 * layout and endian problems. Note that it ignores fields irrelevant 401 * to SNTP. 402 */ 403 void 404 unpack_ntp(struct ntp_data *data, u_char *packet) 405 { 406 int i; 407 double d; 408 409 data->current = current_time(JAN_1970); 410 411 data->status = (packet[0] >> 6); 412 data->version = (packet[0] >> 3) & 0x07; 413 data->mode = packet[0] & 0x07; 414 data->stratum = packet[1]; 415 416 for (i = 0, d = 0.0; i < 8; ++i) 417 d = 256.0*d+packet[NTP_RECEIVE+i]; 418 419 data->receive = d / NTP_SCALE; 420 421 for (i = 0, d = 0.0; i < 8; ++i) 422 d = 256.0*d+packet[NTP_TRANSMIT+i]; 423 424 data->transmit = d / NTP_SCALE; 425 426 /* See write_packet for why this isn't an endian problem. */ 427 bcopy((packet + NTP_ORIGINATE), &data->recvck, sizeof(data->recvck)); 428 } 429 430 /* 431 * Get the current UTC time in seconds since the Epoch plus an offset 432 * (usually the time from the beginning of the century to the Epoch) 433 */ 434 double 435 current_time(double offset) 436 { 437 struct timeval current; 438 u_int64_t t; 439 440 if (gettimeofday(¤t, NULL)) 441 err(1, "Could not get local time of day"); 442 443 /* 444 * At this point, current has the current TAI time. 445 * Now subtract leap seconds to set the posix tick. 446 */ 447 448 t = SEC_TO_TAI64(current.tv_sec); 449 if (corrleaps) 450 ntpleaps_sub(&t); 451 452 return (offset + TAI64_TO_SEC(t) + 1.0e-6 * current.tv_usec); 453 } 454 455 /* 456 * Change offset into current UTC time. This is portable, even if 457 * struct timeval uses an unsigned long for tv_sec. 458 */ 459 void 460 create_timeval(double difference, struct timeval *new, struct timeval *adjust) 461 { 462 struct timeval old; 463 long n; 464 465 /* Start by converting to timeval format. Note that we have to 466 * cater for negative, unsigned values. */ 467 if ((n = (long) difference) > difference) 468 --n; 469 adjust->tv_sec = n; 470 adjust->tv_usec = (long) (MILLION_D * (difference-n)); 471 errno = 0; 472 if (gettimeofday(&old, NULL)) 473 err(1, "Could not get local time of day"); 474 new->tv_sec = old.tv_sec + adjust->tv_sec; 475 new->tv_usec = (n = (long) old.tv_usec + (long) adjust->tv_usec); 476 477 if (n < 0) { 478 new->tv_usec += MILLION_L; 479 --new->tv_sec; 480 } else if (n >= MILLION_L) { 481 new->tv_usec -= MILLION_L; 482 ++new->tv_sec; 483 } 484 } 485 486 #ifdef DEBUG 487 void 488 print_packet(const struct ntp_data *data) 489 { 490 printf("status: %u\n", data->status); 491 printf("version: %u\n", data->version); 492 printf("mode: %u\n", data->mode); 493 printf("stratum: %u\n", data->stratum); 494 printf("originate: %f\n", data->originate); 495 printf("receive: %f\n", data->receive); 496 printf("transmit: %f\n", data->transmit); 497 printf("current: %f\n", data->current); 498 printf("xmitck: 0x%0llX\n", data->xmitck); 499 printf("recvck: 0x%0llX\n", data->recvck); 500 }; 501 #endif 502