summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ntpd/Makefile4
-rw-r--r--usr.sbin/ntpd/client.c129
-rw-r--r--usr.sbin/ntpd/ntp.c50
-rw-r--r--usr.sbin/ntpd/ntp.h14
-rw-r--r--usr.sbin/ntpd/ntpd.c3
-rw-r--r--usr.sbin/ntpd/ntpd.h24
-rw-r--r--usr.sbin/ntpd/parse.y32
7 files changed, 243 insertions, 13 deletions
diff --git a/usr.sbin/ntpd/Makefile b/usr.sbin/ntpd/Makefile
index 96664576ced..0fedc671017 100644
--- a/usr.sbin/ntpd/Makefile
+++ b/usr.sbin/ntpd/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.4 2004/06/02 10:08:59 henning Exp $
+# $OpenBSD: Makefile,v 1.5 2004/06/17 19:17:48 henning Exp $
.PATH: ${.CURDIR}/..
PROG= ntpd
SRCS= ntpd.c buffer.c log.c imsg.c ntp.c ntp_msg.c parse.y config.c \
- server.c
+ server.c client.c
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
diff --git a/usr.sbin/ntpd/client.c b/usr.sbin/ntpd/client.c
new file mode 100644
index 00000000000..c742d1d11fb
--- /dev/null
+++ b/usr.sbin/ntpd/client.c
@@ -0,0 +1,129 @@
+/* $OpenBSD: client.c,v 1.1 2004/06/17 19:17:48 henning Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "ntpd.h"
+
+int
+client_peer_init(struct ntp_peer *p)
+{
+ struct sockaddr_in *sa_in;
+ struct sockaddr_in6 *sa_in6;
+
+ if ((p->query = calloc(1, sizeof(struct ntp_msg))) == NULL)
+ fatal("client_query calloc");
+
+ switch (p->ss.ss_family) {
+ case AF_INET:
+ sa_in = (struct sockaddr_in *)&p->ss;
+ if (ntohs(sa_in->sin_port) == 0)
+ sa_in->sin_port = htons(123);
+ break;
+ case AF_INET6:
+ sa_in6 = (struct sockaddr_in6 *)&p->ss;
+ if (ntohs(sa_in6->sin6_port) == 0)
+ sa_in6->sin6_port = htons(123);
+ break;
+ default:
+ fatal("king bula sez: wrong AF in client_peer_init");
+ /* not reached */
+ }
+
+ if ((p->query->fd = socket(p->ss.ss_family, SOCK_DGRAM, 0)) == -1)
+ fatal("client_query socket");
+
+ p->query->msg.status = MODE_CLIENT | (NTP_VERSION << 3);
+ p->state = STATE_NONE;
+ p->next = time(NULL);
+
+ return (0);
+}
+
+int
+client_query(struct ntp_peer *p)
+{
+ /*
+ * 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.
+ *
+ * Save the real transmit timestamp locally.
+ */
+
+ p->query->msg.xmttime.int_part = arc4random();
+ p->query->msg.xmttime.fraction = arc4random();
+ get_ts(&p->query->xmttime);
+
+ ntp_sendmsg(p->query->fd, (struct sockaddr *)&p->ss, &p->query->msg,
+ NTP_MSGSIZE_NOAUTH, 0);
+ p->state = STATE_QUERY_SENT;
+ p->next = 0;
+ p->deadline = time(NULL) + MAX_QUERYTIME;
+
+ return (0);
+}
+
+int
+client_dispatch(struct ntp_peer *p)
+{
+ struct sockaddr_storage fsa;
+ socklen_t fsa_len;
+ char buf[NTP_MSGSIZE];
+ ssize_t size;
+ struct ntp_msg msg;
+ struct l_fixedpt rtt, t;
+
+ fsa_len = sizeof(fsa);
+ if ((size = recvfrom(p->query->fd, &buf, sizeof(buf), 0,
+ (struct sockaddr *)&fsa, &fsa_len)) == -1)
+ fatal("recvfrom");
+
+ ntp_getmsg(buf, size, &msg);
+
+ if (msg.orgtime.int_part != p->query->msg.xmttime.int_part ||
+ msg.orgtime.fraction != p->query->msg.xmttime.fraction) {
+ log_warn("received packet without correct cookie, discarding");
+ return (0);
+ }
+
+log_debug("reply received");
+
+ /* XXX parse */
+ get_ts(&t);
+ rtt.int_part = (t.int_part - p->query->xmttime.int_part) -
+ (msg.rectime.int_part - msg.xmttime.int_part);
+
+ p->state = STATE_REPLY_RECEIVED;
+ p->next = time(NULL) + QUERY_INTERVAL;
+ p->deadline = 0;
+
+ return (0);
+}
diff --git a/usr.sbin/ntpd/ntp.c b/usr.sbin/ntpd/ntp.c
index 55538d58efa..792337423d1 100644
--- a/usr.sbin/ntpd/ntp.c
+++ b/usr.sbin/ntpd/ntp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntp.c,v 1.6 2004/06/02 10:08:59 henning Exp $ */
+/* $OpenBSD: ntp.c,v 1.7 2004/06/17 19:17:48 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -52,12 +52,15 @@ ntp_sighdlr(int sig)
pid_t
ntp_main(int pipe_prnt[2], struct ntpd_conf *conf)
{
- int nfds, i, j;
+ int nfds, i, j, idx_peers, timeout;
pid_t pid;
struct pollfd pfd[OPEN_MAX];
struct passwd *pw;
struct servent *se;
struct listen_addr *la;
+ struct ntp_peer *p;
+ struct ntp_peer *idx2peer[OPEN_MAX];
+ time_t nextaction;
switch (pid = fork()) {
case -1:
@@ -98,10 +101,15 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *conf)
close(pipe_prnt[0]);
imsg_init(&ibuf_main, pipe_prnt[1]);
+ TAILQ_FOREACH(p, &conf->ntp_peers, entry)
+ client_peer_init(p);
+
log_info("ntp engine ready");
while (ntp_quit == 0) {
bzero(&pfd, sizeof(pfd));
+ bzero(idx2peer, sizeof(idx2peer));
+ nextaction = time(NULL) + 240;
pfd[PFD_PIPE_MAIN].fd = ibuf_main.fd;
pfd[PFD_PIPE_MAIN].events = POLLIN;
if (ibuf_main.w.queued > 0)
@@ -112,14 +120,38 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *conf)
pfd[i].fd = la->fd;
pfd[i].events = POLLIN;
i++;
+ if (i > OPEN_MAX)
+ fatal("i > OPEN_MAX");
+ }
+
+
+ idx_peers = i;
+ TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
+ if (p->next > 0 && p->next < nextaction)
+ nextaction = p->next;
+ if ((p->next > 0 && p->next <= time(NULL)) ||
+ (p->deadline > 0 && p->deadline <= time(NULL)))
+ client_query(p);
+
+ if (p->state == STATE_QUERY_SENT) {
+ pfd[i].fd = p->query->fd;
+ pfd[i].events = POLLIN;
+ idx2peer[i - idx_peers] = p;
+ i++;
+ if (i > OPEN_MAX)
+ fatal("i > OPEN_MAX");
+ }
}
- if ((nfds = poll(pfd, i, INFTIM)) == -1)
+ timeout = nextaction - time(NULL);
+ if (timeout < 0)
+ timeout = 0;
+
+ if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
if (errno != EINTR) {
log_warn("poll error");
ntp_quit = 1;
}
-
if (nfds > 0 && (pfd[PFD_PIPE_MAIN].revents & POLLOUT))
if (msgbuf_write(&ibuf_main.w) < 0) {
log_warn("pipe write error (to parent)");
@@ -132,12 +164,20 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *conf)
ntp_quit = 1;
}
- for (j = 1; nfds > 0 && j < i; j++)
+ for (j = 1; nfds > 0 && j < idx_peers; j++)
if (pfd[j].revents & POLLIN) {
nfds--;
if (ntp_dispatch(pfd[j].fd) == -1)
ntp_quit = 1;
}
+
+ for (; nfds > 0 && j < i; j++)
+ if (pfd[j].revents & POLLIN) {
+ nfds--;
+ if (client_dispatch(idx2peer[j - idx_peers]) ==
+ -1)
+ ntp_quit = 1;
+ }
}
msgbuf_write(&ibuf_main.w);
diff --git a/usr.sbin/ntpd/ntp.h b/usr.sbin/ntpd/ntp.h
index 461de9d8ead..8a63c006904 100644
--- a/usr.sbin/ntpd/ntp.h
+++ b/usr.sbin/ntpd/ntp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntp.h,v 1.4 2004/06/05 12:29:15 alexander Exp $ */
+/* $OpenBSD: ntp.h,v 1.5 2004/06/17 19:17:48 henning Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -109,6 +109,12 @@ struct ntp_msg {
u_int8_t digest[NTP_DIGESTSIZE];
};
+struct ntp_query {
+ int fd;
+ struct ntp_msg msg;
+ struct l_fixedpt xmttime;
+};
+
/*
* Leap Second Codes (high order two bits)
*/
@@ -138,4 +144,8 @@ struct ntp_msg {
#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
-#endif /* _NTP_H_ */
+#define NTP_VERSION 4
+#define MAX_QUERYTIME 30 /* max seconds a single query might take */
+#define QUERY_INTERVAL 60 /* sync with peers every n seconds */
+
+#endif /* _NTP_H_ */
diff --git a/usr.sbin/ntpd/ntpd.c b/usr.sbin/ntpd/ntpd.c
index a60cb153adc..7d6eadac1d9 100644
--- a/usr.sbin/ntpd/ntpd.c
+++ b/usr.sbin/ntpd/ntpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntpd.c,v 1.4 2004/06/01 21:58:08 henning Exp $ */
+/* $OpenBSD: ntpd.c,v 1.5 2004/06/17 19:17:48 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -91,6 +91,7 @@ main(int argc, char *argv[])
bzero(&conf, sizeof(conf));
TAILQ_INIT(&conf.listen_addrs);
+ TAILQ_INIT(&conf.ntp_peers);
log_init(1); /* log to stderr until daemonized */
diff --git a/usr.sbin/ntpd/ntpd.h b/usr.sbin/ntpd/ntpd.h
index 44e75c1f25f..71d309cb8b8 100644
--- a/usr.sbin/ntpd/ntpd.h
+++ b/usr.sbin/ntpd/ntpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntpd.h,v 1.5 2004/06/05 12:29:15 alexander Exp $ */
+/* $OpenBSD: ntpd.h,v 1.6 2004/06/17 19:17:48 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -34,14 +34,30 @@
#define NTPD_OPT_VERBOSE 0x0001
#define NTPD_OPT_VERBOSE2 0x0002
+enum client_state {
+ STATE_NONE,
+ STATE_QUERY_SENT,
+ STATE_REPLY_RECEIVED
+};
+
struct listen_addr {
TAILQ_ENTRY(listen_addr) entry;
struct sockaddr_storage sa;
int fd;
};
+struct ntp_peer {
+ TAILQ_ENTRY(ntp_peer) entry;
+ struct sockaddr_storage ss;
+ struct ntp_query *query;
+ enum client_state state;
+ time_t next;
+ time_t deadline;
+};
+
struct ntpd_conf {
TAILQ_HEAD(listen_addrs, listen_addr) listen_addrs;
+ TAILQ_HEAD(ntp_peers, ntp_peer) ntp_peers;
u_int8_t opts;
};
@@ -103,6 +119,7 @@ void log_info(const char *, ...);
void log_debug(const char *, ...);
void fatal(const char *);
void fatalx(const char *);
+const char * log_sockaddr(struct sockaddr *);
/* buffer.c */
struct buf *buf_open(ssize_t);
@@ -144,3 +161,8 @@ int ntp_sendmsg(int, struct sockaddr *, struct ntp_msg *, ssize_t, int);
/* server.c */
int setup_listeners(struct servent *, struct ntpd_conf *);
int ntp_reply(int, struct sockaddr *, struct ntp_msg *, int);
+
+/* client.c */
+int client_peer_init(struct ntp_peer *);
+int client_query(struct ntp_peer *);
+int client_dispatch(struct ntp_peer *);
diff --git a/usr.sbin/ntpd/parse.y b/usr.sbin/ntpd/parse.y
index 18e3ab37ab9..da13af04bab 100644
--- a/usr.sbin/ntpd/parse.y
+++ b/usr.sbin/ntpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.1 2004/06/01 21:58:09 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.2 2004/06/17 19:17:48 henning Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -77,6 +77,7 @@ typedef struct {
%}
%token LISTEN ON
+%token SERVER
%token ERROR
%token <v.string> STRING
%type <v.number> number
@@ -130,9 +131,23 @@ conf_main : LISTEN ON address {
NULL)
fatal("parse conf_main listen on calloc");
+ la->fd = -1;
memcpy(&la->sa, &$3, sizeof(struct sockaddr_storage));
TAILQ_INSERT_TAIL(&conf->listen_addrs, la, entry);
}
+ | SERVER address {
+ struct ntp_peer *p;
+
+ if (!TAILQ_EMPTY(&conf->ntp_peers)) {
+ yyerror("king bula sez: only on remote server "
+ "supported for now");
+ YYERROR;
+ }
+ if ((p = calloc(1, sizeof(struct listen_addr))) == NULL)
+ fatal("parse conf_mail server on calloc");
+ memcpy(&p->ss, &$2, sizeof(struct sockaddr_storage));
+ TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
+ }
;
address : STRING {
@@ -192,7 +207,8 @@ lookup(char *s)
/* this has to be sorted always */
static const struct keywords keywords[] = {
{ "listen", LISTEN},
- { "on", ON}
+ { "on", ON},
+ { "server", SERVER}
};
const struct keywords *p;
@@ -402,12 +418,14 @@ parse_config(char *filename, struct ntpd_conf *xconf)
{
struct sym *sym, *next;
struct listen_addr *la;
+ struct ntp_peer *p;
if ((conf = calloc(1, sizeof(struct ntpd_conf))) == NULL)
fatal(NULL);
lineno = 1;
errors = 0;
TAILQ_INIT(&conf->listen_addrs);
+ TAILQ_INIT(&conf->ntp_peers);
if ((fin = fopen(filename, "r")) == NULL) {
log_warn("%s", filename);
@@ -444,6 +462,16 @@ parse_config(char *filename, struct ntpd_conf *xconf)
TAILQ_INSERT_TAIL(&xconf->listen_addrs, la, entry);
}
+ while ((p = TAILQ_FIRST(&xconf->ntp_peers)) != NULL) {
+ TAILQ_REMOVE(&xconf->ntp_peers, p, entry);
+ free(p);
+ }
+
+ while ((p = TAILQ_FIRST(&conf->ntp_peers)) != NULL) {
+ TAILQ_REMOVE(&conf->ntp_peers, p, entry);
+ TAILQ_INSERT_TAIL(&xconf->ntp_peers, p, entry);
+ }
+
free(conf);
return (errors ? -1 : 0);