summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/rdate/ntp.c70
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