diff options
author | Jakob Schlyter <jakob@cvs.openbsd.org> | 2004-05-26 16:38:45 +0000 |
---|---|---|
committer | Jakob Schlyter <jakob@cvs.openbsd.org> | 2004-05-26 16:38:45 +0000 |
commit | 4f22c400434365c1af3c92ce2e09b772225c198d (patch) | |
tree | 0c6352d51732c532e0911a4defe7d9f333397a0d /usr.sbin/rdate/ntp.c | |
parent | db7a478765ea71220fc55a148ee45a61b2ee1126 (diff) |
Send out a random 64-bit number as our transmit time. The NTP
server will copy said number into the originate field on the
response that it sends us. This is totally legal per the SNTP spec.
The impact of this is two fold: we no longer send out the current
system time for the world to see (which may aid an attacker), and
it gives us a (not very secure) way of knowing that we're not
getting spoofed by an attacker that can't capture our traffic
but can spoof packets from the NTP server we're communicating with.
code by Alexander Guy. ok deraadt@
Diffstat (limited to 'usr.sbin/rdate/ntp.c')
-rw-r--r-- | usr.sbin/rdate/ntp.c | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/usr.sbin/rdate/ntp.c b/usr.sbin/rdate/ntp.c index e12218f5a0e..9763a0780d6 100644 --- a/usr.sbin/rdate/ntp.c +++ b/usr.sbin/rdate/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.16 2004/05/18 17:25:18 jakob Exp $ */ +/* $OpenBSD: ntp.c,v 1.17 2004/05/26 16:38:44 jakob Exp $ */ /* * Copyright (c) 1996, 1997 by N.M. Maclaren. All rights reserved. @@ -99,6 +99,9 @@ struct ntp_data { double receive; double transmit; double current; + + u_int64_t xmitck; + u_int64_t recvck; }; void ntp_client(const char *, int, struct timeval *, struct timeval *, int); @@ -234,8 +237,26 @@ make_packet(struct ntp_data *data) data->polling = 0; data->precision = 0; data->reference = data->dispersion = 0.0; - data->receive = data->originate = 0.0; + data->receive = 0.0; data->current = data->transmit = current_time(JAN_1970); + data->originate = data->transmit; + + + /* + * Send out a random 64-bit number as our transmit time. The NTP + * server will copy said number into the originate field on the + * response that it sends us. This is totally legal per the SNTP spec. + * + * The impact of this is two fold: we no longer send out the current + * system time for the world to see (which may aid an attacker), and + * it gives us a (not very secure) way of knowing that we're not + * getting spoofed by an attacker that can't capture our traffic + * but can spoof packets from the NTP server we're communicating with. + * + */ + + data->xmitck = ((u_int64_t)arc4random() << 32) | arc4random(); + data->recvck = 0; } int @@ -265,7 +286,7 @@ read_packet(int fd, struct ntp_data *data, double *off, double *error, double *dispersion) { u_char receive[NTP_PACKET_MAX+1]; - double delay1, delay2, x, y; + double delay, x, y; int length, r; fd_set *rfds; struct timeval tv; @@ -308,6 +329,11 @@ retry: unpack_ntp(data, receive, length); + if (data->recvck != data->xmitck) { + warnx("Invalid cookie received"); + return 1; + } + if (data->version < NTP_VERSION_MIN || data->version > NTP_VERSION_MAX) { warnx("Invalid NTP version, packet rejected"); @@ -325,17 +351,14 @@ retry: * completely unsynchronised packets is an abomination, anyway, so * reject it. */ - delay1 = data->transmit - data->receive; - delay2 = data->current - data->originate; + delay = data->transmit - data->receive; if (data->reference == 0.0 || data->transmit == 0.0 || data->receive == 0.0 || (data->reference != 0.0 && data->receive < data->reference) || - delay1 < 0.0 || - delay1 > NTP_INSANITY || - delay2 < 0.0 || - delay2 > NTP_INSANITY || + delay < 0.0 || + delay > NTP_INSANITY || data->dispersion > NTP_INSANITY) { warnx("Incomprehensible NTP packet rejected"); return 1; @@ -373,13 +396,6 @@ pack_ntp(u_char *packet, int length, struct ntp_data *data) packet[2] = data->polling; packet[3] = data->precision; - d = data->originate/NTP_SCALE; - for (i = 0; i < 8; ++i) { - if ((k = (int)(d *= 256.0)) >= 256) k = 255; - packet[NTP_ORIGINATE+i] = k; - d -= k; - } - d = data->receive/NTP_SCALE; for (i = 0; i < 8; ++i) { if ((k = (int)(d *= 256.0)) >= 256) k = 255; @@ -387,12 +403,13 @@ pack_ntp(u_char *packet, int length, struct ntp_data *data) d -= k; } - d = data->transmit/NTP_SCALE; - for (i = 0; i < 8; ++i) { - if ((k = (int)(d *= 256.0)) >= 256) k = 255; - packet[NTP_TRANSMIT+i] = k; - d -= k; - } + /* + * No endian concerns here. Since we're running as a strict + * unicast client, we don't have to worry about anyone else finding + * this field intelligible. + */ + + *(u_int64_t *)(packet + NTP_TRANSMIT) = data->xmitck; } /* @@ -424,16 +441,15 @@ unpack_ntp(struct ntp_data *data, u_char *packet, int length) data->reference = d/NTP_SCALE; for (i = 0, d = 0.0; i < 8; ++i) - d = 256.0*d+packet[NTP_ORIGINATE+i]; - data->originate = d/NTP_SCALE; - - for (i = 0, d = 0.0; i < 8; ++i) d = 256.0*d+packet[NTP_RECEIVE+i]; data->receive = d/NTP_SCALE; for (i = 0, d = 0.0; i < 8; ++i) d = 256.0*d+packet[NTP_TRANSMIT+i]; data->transmit = d/NTP_SCALE; + + /* See unpack_ntp for why there is no byte-order change. */ + data->recvck = *(u_int64_t *)(packet + NTP_ORIGINATE); } /* @@ -508,5 +524,7 @@ print_packet(const struct ntp_data *data) printf("receive: %e\n", data->receive); printf("transmit: %e\n", data->transmit); printf("current: %e\n", data->current); + printf("xmitck: 0x%0llX\n", data->xmitck); + printf("recvck: 0x%0llX\n", data->recvck); }; #endif |