1/*	$OpenBSD: constraint.c,v 1.56 2023/12/20 15:36:36 otto Exp $	*/
2
3/*
4 * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/queue.h>
20#include <sys/socket.h>
21#include <sys/time.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24#include <sys/resource.h>
25#include <sys/uio.h>
26
27#include <netinet/in.h>
28#include <arpa/inet.h>
29
30#include <errno.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <fcntl.h>
34#include <imsg.h>
35#include <netdb.h>
36#include <poll.h>
37#include <signal.h>
38#include <string.h>
39#include <unistd.h>
40#include <time.h>
41#include <ctype.h>
42#include <tls.h>
43#include <pwd.h>
44#include <math.h>
45
46#include "ntpd.h"
47
48#define	IMF_FIXDATE	"%a, %d %h %Y %T GMT"
49#define	X509_DATE	"%Y-%m-%d %T UTC"
50
51int	 constraint_addr_init(struct constraint *);
52void	 constraint_addr_head_clear(struct constraint *);
53struct constraint *
54	 constraint_byid(u_int32_t);
55struct constraint *
56	 constraint_byfd(int);
57struct constraint *
58	 constraint_bypid(pid_t);
59int	 constraint_close(u_int32_t);
60void	 constraint_update(void);
61int	 constraint_cmp(const void *, const void *);
62
63void	 priv_constraint_close(int, int);
64void	 priv_constraint_readquery(struct constraint *, struct ntp_addr_msg *,
65	    uint8_t **);
66
67struct httpsdate *
68	 httpsdate_init(const char *, const char *, const char *,
69	    const char *, const u_int8_t *, size_t, int);
70void	 httpsdate_free(void *);
71int	 httpsdate_request(struct httpsdate *, struct timeval *, int);
72void	*httpsdate_query(const char *, const char *, const char *,
73	    const char *, const u_int8_t *, size_t,
74	    struct timeval *, struct timeval *, int);
75
76char	*tls_readline(struct tls *, size_t *, size_t *, struct timeval *);
77
78u_int constraint_cnt;
79extern u_int peer_cnt;
80extern struct imsgbuf *ibuf;		/* priv */
81extern struct imsgbuf *ibuf_main;	/* chld */
82
83struct httpsdate {
84	char			*tls_addr;
85	char			*tls_port;
86	char			*tls_hostname;
87	char			*tls_path;
88	char			*tls_request;
89	struct tls_config	*tls_config;
90	struct tls		*tls_ctx;
91	struct tm		 tls_tm;
92};
93
94int
95constraint_init(struct constraint *cstr)
96{
97	cstr->state = STATE_NONE;
98	cstr->fd = -1;
99	cstr->last = getmonotime();
100	cstr->constraint = 0;
101	cstr->senderrors = 0;
102
103	return (constraint_addr_init(cstr));
104}
105
106int
107constraint_addr_init(struct constraint *cstr)
108{
109	struct sockaddr_in	*sa_in;
110	struct sockaddr_in6	*sa_in6;
111	struct ntp_addr		*h;
112
113	if (cstr->state == STATE_DNS_INPROGRESS)
114		return (0);
115
116	if (cstr->addr_head.a == NULL) {
117		priv_dns(IMSG_CONSTRAINT_DNS, cstr->addr_head.name, cstr->id);
118		cstr->state = STATE_DNS_INPROGRESS;
119		return (0);
120	}
121
122	h = cstr->addr;
123	switch (h->ss.ss_family) {
124	case AF_INET:
125		sa_in = (struct sockaddr_in *)&h->ss;
126		if (ntohs(sa_in->sin_port) == 0)
127			sa_in->sin_port = htons(443);
128		cstr->state = STATE_DNS_DONE;
129		break;
130	case AF_INET6:
131		sa_in6 = (struct sockaddr_in6 *)&h->ss;
132		if (ntohs(sa_in6->sin6_port) == 0)
133			sa_in6->sin6_port = htons(443);
134		cstr->state = STATE_DNS_DONE;
135		break;
136	default:
137		/* XXX king bula sez it? */
138		fatalx("wrong AF in constraint_addr_init");
139		/* NOTREACHED */
140	}
141
142	return (1);
143}
144
145void
146constraint_addr_head_clear(struct constraint *cstr)
147{
148	host_dns_free(cstr->addr_head.a);
149	cstr->addr_head.a = NULL;
150	cstr->addr = NULL;
151}
152
153int
154constraint_query(struct constraint *cstr, int synced)
155{
156	time_t			 now;
157	struct ntp_addr_msg	 am;
158	struct iovec		 iov[3];
159	int			 iov_cnt = 0;
160
161	now = getmonotime();
162
163	switch (cstr->state) {
164	case STATE_DNS_DONE:
165		/* Proceed and query the time */
166		break;
167	case STATE_DNS_TEMPFAIL:
168		if (now > cstr->last + (cstr->dnstries >= TRIES_AUTO_DNSFAIL ?
169		    CONSTRAINT_RETRY_INTERVAL : INTERVAL_AUIO_DNSFAIL)) {
170			cstr->dnstries++;
171			/* Retry resolving the address */
172			constraint_init(cstr);
173			return 0;
174		}
175		return (-1);
176	case STATE_QUERY_SENT:
177		if (cstr->last + CONSTRAINT_SCAN_TIMEOUT > now) {
178			/* The caller should expect a reply */
179			return (0);
180		}
181
182		/* Timeout, just kill the process to reset it. */
183		imsg_compose(ibuf_main, IMSG_CONSTRAINT_KILL,
184		    cstr->id, 0, -1, NULL, 0);
185
186		cstr->state = STATE_TIMEOUT;
187		return (-1);
188	case STATE_INVALID:
189		if (cstr->last + CONSTRAINT_SCAN_INTERVAL > now) {
190			/* Nothing to do */
191			return (-1);
192		}
193
194		/* Reset and retry */
195		cstr->senderrors = 0;
196		constraint_close(cstr->id);
197		break;
198	case STATE_REPLY_RECEIVED:
199	default:
200		/* Nothing to do */
201		return (-1);
202	}
203
204	cstr->last = now;
205	cstr->state = STATE_QUERY_SENT;
206
207	memset(&am, 0, sizeof(am));
208	memcpy(&am.a, cstr->addr, sizeof(am.a));
209	am.synced = synced;
210
211	iov[iov_cnt].iov_base = &am;
212	iov[iov_cnt++].iov_len = sizeof(am);
213	if (cstr->addr_head.name) {
214		am.namelen = strlen(cstr->addr_head.name) + 1;
215		iov[iov_cnt].iov_base = cstr->addr_head.name;
216		iov[iov_cnt++].iov_len = am.namelen;
217	}
218	if (cstr->addr_head.path) {
219		am.pathlen = strlen(cstr->addr_head.path) + 1;
220		iov[iov_cnt].iov_base = cstr->addr_head.path;
221		iov[iov_cnt++].iov_len = am.pathlen;
222	}
223
224	imsg_composev(ibuf_main, IMSG_CONSTRAINT_QUERY,
225	    cstr->id, 0, -1, iov, iov_cnt);
226
227	return (0);
228}
229
230void
231priv_constraint_msg(u_int32_t id, u_int8_t *data, size_t len, int argc,
232    char **argv)
233{
234	struct ntp_addr_msg	 am;
235	struct ntp_addr		*h;
236	struct constraint	*cstr;
237	int			 pipes[2];
238	int			 rv;
239
240	if ((cstr = constraint_byid(id)) != NULL) {
241		log_warnx("IMSG_CONSTRAINT_QUERY repeated for id %d", id);
242		return;
243	}
244
245	if (len < sizeof(am)) {
246		log_warnx("invalid IMSG_CONSTRAINT_QUERY received");
247		return;
248	}
249	memcpy(&am, data, sizeof(am));
250	if (len != (sizeof(am) + am.namelen + am.pathlen)) {
251		log_warnx("invalid IMSG_CONSTRAINT_QUERY received");
252		return;
253	}
254	/* Additional imsg data is obtained in the unpriv child */
255
256	if ((h = calloc(1, sizeof(*h))) == NULL)
257		fatal("calloc ntp_addr");
258	memcpy(h, &am.a, sizeof(*h));
259	h->next = NULL;
260
261	cstr = new_constraint();
262	cstr->id = id;
263	cstr->addr = h;
264	cstr->addr_head.a = h;
265	constraint_add(cstr);
266	constraint_cnt++;
267
268	if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC,
269	    pipes) == -1)
270		fatal("%s pipes", __func__);
271
272	/* Prepare and send constraint data to child. */
273	cstr->fd = pipes[0];
274	imsg_init(&cstr->ibuf, cstr->fd);
275	if (imsg_compose(&cstr->ibuf, IMSG_CONSTRAINT_QUERY, id, 0, -1,
276	    data, len) == -1)
277		fatal("%s: imsg_compose", __func__);
278	do {
279		rv = imsg_flush(&cstr->ibuf);
280	} while (rv == -1 && errno == EAGAIN);
281	if (rv == -1)
282		fatal("imsg_flush");
283
284	/*
285	 * Fork child handlers and make sure to do any sensitive work in the
286	 * the (unprivileged) child.  The parent should not do any parsing,
287	 * certificate loading etc.
288	 */
289	cstr->pid = start_child(CONSTRAINT_PROC_NAME, pipes[1], argc, argv);
290}
291
292void
293priv_constraint_readquery(struct constraint *cstr, struct ntp_addr_msg *am,
294    uint8_t **data)
295{
296	struct ntp_addr		*h;
297	uint8_t			*dptr;
298	int			 n;
299	struct imsg		 imsg;
300	size_t			 mlen;
301
302	/* Read the message our parent left us. */
303	if (((n = imsg_read(&cstr->ibuf)) == -1 && errno != EAGAIN) || n == 0)
304		fatal("%s: imsg_read", __func__);
305	if (((n = imsg_get(&cstr->ibuf, &imsg)) == -1) || n == 0)
306		fatal("%s: imsg_get", __func__);
307	if (imsg.hdr.type != IMSG_CONSTRAINT_QUERY)
308		fatalx("%s: invalid message type", __func__);
309
310	/*
311	 * Copy the message contents just like our father:
312	 * priv_constraint_msg().
313	 */
314	mlen = imsg.hdr.len - IMSG_HEADER_SIZE;
315	if (mlen < sizeof(*am))
316		fatalx("%s: mlen < sizeof(*am)", __func__);
317
318	memcpy(am, imsg.data, sizeof(*am));
319	if (mlen != (sizeof(*am) + am->namelen + am->pathlen))
320		fatalx("%s: mlen < sizeof(*am) + am->namelen + am->pathlen",
321		    __func__);
322
323	if ((h = calloc(1, sizeof(*h))) == NULL ||
324	    (*data = calloc(1, mlen)) == NULL)
325		fatal("%s: calloc", __func__);
326
327	memcpy(h, &am->a, sizeof(*h));
328	h->next = NULL;
329
330	cstr->id = imsg.hdr.peerid;
331	cstr->addr = h;
332	cstr->addr_head.a = h;
333
334	dptr = imsg.data;
335	memcpy(*data, dptr + sizeof(*am), mlen - sizeof(*am));
336	imsg_free(&imsg);
337}
338
339void
340priv_constraint_child(const char *pw_dir, uid_t pw_uid, gid_t pw_gid)
341{
342	struct constraint	 cstr;
343	struct ntp_addr_msg	 am;
344	uint8_t			*data;
345	static char		 addr[NI_MAXHOST];
346	struct timeval		 rectv, xmttv;
347	struct sigaction	 sa;
348	void			*ctx;
349	struct iovec		 iov[2];
350	int			 i, rv;
351
352	log_procinit("constraint");
353
354	if (setpriority(PRIO_PROCESS, 0, 0) == -1)
355		log_warn("could not set priority");
356
357	/* load CA certs before chroot() */
358	if ((conf->ca = tls_load_file(tls_default_ca_cert_file(),
359	    &conf->ca_len, NULL)) == NULL)
360		fatalx("failed to load constraint ca");
361
362	if (chroot(pw_dir) == -1)
363		fatal("chroot");
364	if (chdir("/") == -1)
365		fatal("chdir(\"/\")");
366
367	if (setgroups(1, &pw_gid) ||
368	    setresgid(pw_gid, pw_gid, pw_gid) ||
369	    setresuid(pw_uid, pw_uid, pw_uid))
370		fatal("can't drop privileges");
371
372	/* Reset all signal handlers */
373	memset(&sa, 0, sizeof(sa));
374	sigemptyset(&sa.sa_mask);
375	sa.sa_flags = SA_RESTART;
376	sa.sa_handler = SIG_DFL;
377	for (i = 1; i < _NSIG; i++)
378		sigaction(i, &sa, NULL);
379
380	if (pledge("stdio inet", NULL) == -1)
381		fatal("pledge");
382
383	cstr.fd = CONSTRAINT_PASSFD;
384	imsg_init(&cstr.ibuf, cstr.fd);
385	priv_constraint_readquery(&cstr, &am, &data);
386
387	/*
388	 * Get the IP address as name and set the process title accordingly.
389	 * This only converts an address into a string and does not trigger
390	 * any DNS operation, so it is safe to be called without the dns
391	 * pledge.
392	 */
393	if (getnameinfo((struct sockaddr *)&cstr.addr->ss,
394	    SA_LEN((struct sockaddr *)&cstr.addr->ss),
395	    addr, sizeof(addr), NULL, 0,
396	    NI_NUMERICHOST) != 0)
397		fatalx("%s getnameinfo", __func__);
398
399	log_debug("constraint request to %s", addr);
400	setproctitle("constraint from %s", addr);
401	(void)closefrom(CONSTRAINT_PASSFD + 1);
402
403	/*
404	 * Set the close-on-exec flag to prevent leaking the communication
405	 * channel to any exec'ed child.  In theory this could never happen,
406	 * constraints don't exec children and pledge() prevents it,
407	 * but we keep it as a safety belt; especially for portability.
408	 */
409	if (fcntl(CONSTRAINT_PASSFD, F_SETFD, FD_CLOEXEC) == -1)
410		fatal("%s fcntl F_SETFD", __func__);
411
412	/* Get remaining data from imsg in the unpriv child */
413	if (am.namelen) {
414		if ((cstr.addr_head.name =
415		    get_string(data, am.namelen)) == NULL)
416			fatalx("invalid IMSG_CONSTRAINT_QUERY name");
417		data += am.namelen;
418	}
419	if (am.pathlen) {
420		if ((cstr.addr_head.path =
421		    get_string(data, am.pathlen)) == NULL)
422			fatalx("invalid IMSG_CONSTRAINT_QUERY path");
423	}
424
425	/* Run! */
426	if ((ctx = httpsdate_query(addr,
427	    CONSTRAINT_PORT, cstr.addr_head.name, cstr.addr_head.path,
428	    conf->ca, conf->ca_len, &rectv, &xmttv, am.synced)) == NULL) {
429		/* Abort with failure but without warning */
430		exit(1);
431	}
432
433	iov[0].iov_base = &rectv;
434	iov[0].iov_len = sizeof(rectv);
435	iov[1].iov_base = &xmttv;
436	iov[1].iov_len = sizeof(xmttv);
437	imsg_composev(&cstr.ibuf,
438	    IMSG_CONSTRAINT_RESULT, 0, 0, -1, iov, 2);
439	do {
440		rv = imsg_flush(&cstr.ibuf);
441	} while (rv == -1 && errno == EAGAIN);
442
443	/* Tear down the TLS connection after sending the result */
444	httpsdate_free(ctx);
445
446	exit(0);
447}
448
449void
450priv_constraint_check_child(pid_t pid, int status)
451{
452	struct constraint	*cstr;
453	int			 fail, sig;
454	char			*signame;
455
456	fail = sig = 0;
457	if (WIFSIGNALED(status)) {
458		sig = WTERMSIG(status);
459	} else if (WIFEXITED(status)) {
460		if (WEXITSTATUS(status) != 0)
461			fail = 1;
462	} else
463		fatalx("unexpected cause of SIGCHLD");
464
465	if ((cstr = constraint_bypid(pid)) != NULL) {
466		if (sig) {
467			if (sig != SIGTERM) {
468				signame = strsignal(sig) ?
469				    strsignal(sig) : "unknown";
470				log_warnx("constraint %s; "
471				    "terminated with signal %d (%s)",
472				    log_ntp_addr(cstr->addr), sig, signame);
473			}
474			fail = 1;
475		}
476
477		priv_constraint_close(cstr->fd, fail);
478	}
479}
480
481void
482priv_constraint_kill(u_int32_t id)
483{
484	struct constraint	*cstr;
485
486	if ((cstr = constraint_byid(id)) == NULL) {
487		log_warnx("IMSG_CONSTRAINT_KILL for invalid id %d", id);
488		return;
489	}
490
491	kill(cstr->pid, SIGTERM);
492}
493
494struct constraint *
495constraint_byid(u_int32_t id)
496{
497	struct constraint	*cstr;
498
499	TAILQ_FOREACH(cstr, &conf->constraints, entry) {
500		if (cstr->id == id)
501			return (cstr);
502	}
503
504	return (NULL);
505}
506
507struct constraint *
508constraint_byfd(int fd)
509{
510	struct constraint	*cstr;
511
512	TAILQ_FOREACH(cstr, &conf->constraints, entry) {
513		if (cstr->fd == fd)
514			return (cstr);
515	}
516
517	return (NULL);
518}
519
520struct constraint *
521constraint_bypid(pid_t pid)
522{
523	struct constraint	*cstr;
524
525	TAILQ_FOREACH(cstr, &conf->constraints, entry) {
526		if (cstr->pid == pid)
527			return (cstr);
528	}
529
530	return (NULL);
531}
532
533int
534constraint_close(u_int32_t id)
535{
536	struct constraint	*cstr;
537
538	if ((cstr = constraint_byid(id)) == NULL) {
539		log_warn("%s: id %d: not found", __func__, id);
540		return (0);
541	}
542
543	cstr->last = getmonotime();
544
545	if (cstr->addr == NULL || (cstr->addr = cstr->addr->next) == NULL) {
546		/* Either a pool or all addresses have been tried */
547		cstr->addr = cstr->addr_head.a;
548		if (cstr->senderrors)
549			cstr->state = STATE_INVALID;
550		else if (cstr->state >= STATE_QUERY_SENT)
551			cstr->state = STATE_DNS_DONE;
552
553		return (1);
554	}
555
556	return (constraint_init(cstr));
557}
558
559void
560priv_constraint_close(int fd, int fail)
561{
562	struct constraint	*cstr;
563	u_int32_t		 id;
564
565	if ((cstr = constraint_byfd(fd)) == NULL) {
566		log_warn("%s: fd %d: not found", __func__, fd);
567		return;
568	}
569
570	id = cstr->id;
571	constraint_remove(cstr);
572	constraint_cnt--;
573
574	imsg_compose(ibuf, IMSG_CONSTRAINT_CLOSE, id, 0, -1,
575	    &fail, sizeof(fail));
576}
577
578void
579constraint_add(struct constraint *cstr)
580{
581	TAILQ_INSERT_TAIL(&conf->constraints, cstr, entry);
582}
583
584void
585constraint_remove(struct constraint *cstr)
586{
587	TAILQ_REMOVE(&conf->constraints, cstr, entry);
588
589	msgbuf_clear(&cstr->ibuf.w);
590	if (cstr->fd != -1)
591		close(cstr->fd);
592	free(cstr->addr_head.name);
593	free(cstr->addr_head.path);
594	free(cstr->addr);
595	free(cstr);
596}
597
598void
599constraint_purge(void)
600{
601	struct constraint	*cstr, *ncstr;
602
603	TAILQ_FOREACH_SAFE(cstr, &conf->constraints, entry, ncstr)
604		constraint_remove(cstr);
605}
606
607int
608priv_constraint_dispatch(struct pollfd *pfd)
609{
610	struct imsg		 imsg;
611	struct constraint	*cstr;
612	ssize_t			 n;
613	struct timeval		 tv[2];
614
615	if ((cstr = constraint_byfd(pfd->fd)) == NULL)
616		return (0);
617
618	if (!(pfd->revents & POLLIN))
619		return (0);
620
621	if (((n = imsg_read(&cstr->ibuf)) == -1 && errno != EAGAIN) || n == 0) {
622		/* there's a race between SIGCHLD delivery and reading imsg
623		   but if we've seen the reply, we're good */
624		priv_constraint_close(pfd->fd, cstr->state !=
625		    STATE_REPLY_RECEIVED);
626		return (1);
627	}
628
629	for (;;) {
630		if ((n = imsg_get(&cstr->ibuf, &imsg)) == -1) {
631			priv_constraint_close(pfd->fd, 1);
632			return (1);
633		}
634		if (n == 0)
635			break;
636
637		switch (imsg.hdr.type) {
638		case IMSG_CONSTRAINT_RESULT:
639			 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(tv))
640				fatalx("invalid IMSG_CONSTRAINT received");
641
642			/* state is maintained by child, but we want to
643			   remember we've seen the result */
644			cstr->state = STATE_REPLY_RECEIVED;
645			/* forward imsg to ntp child, don't parse it here */
646			imsg_compose(ibuf, imsg.hdr.type,
647			    cstr->id, 0, -1, imsg.data, sizeof(tv));
648			break;
649		default:
650			break;
651		}
652		imsg_free(&imsg);
653	}
654
655	return (0);
656}
657
658void
659constraint_msg_result(u_int32_t id, u_int8_t *data, size_t len)
660{
661	struct constraint	*cstr;
662	struct timeval		 tv[2];
663	double			 offset;
664
665	if ((cstr = constraint_byid(id)) == NULL) {
666		log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id");
667		return;
668	}
669
670	if (len != sizeof(tv)) {
671		log_warnx("invalid IMSG_CONSTRAINT received");
672		return;
673	}
674
675	memcpy(tv, data, len);
676
677	offset = gettime_from_timeval(&tv[0]) -
678	    gettime_from_timeval(&tv[1]);
679
680	log_info("constraint reply from %s: offset %f",
681	    log_ntp_addr(cstr->addr),
682	    offset);
683
684	cstr->state = STATE_REPLY_RECEIVED;
685	cstr->last = getmonotime();
686	cstr->constraint = tv[0].tv_sec;
687
688	constraint_update();
689}
690
691void
692constraint_msg_close(u_int32_t id, u_int8_t *data, size_t len)
693{
694	struct constraint	*cstr, *tmp;
695	int			 fail, cnt;
696	static int		 total_fails;
697
698	if ((cstr = constraint_byid(id)) == NULL) {
699		log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id");
700		return;
701	}
702
703	if (len != sizeof(int)) {
704		log_warnx("invalid IMSG_CONSTRAINT_CLOSE received");
705		return;
706	}
707
708	memcpy(&fail, data, len);
709
710	if (fail) {
711		log_debug("no constraint reply from %s"
712		    " received in time, next query %ds",
713		    log_ntp_addr(cstr->addr),
714		    CONSTRAINT_SCAN_INTERVAL);
715
716		cnt = 0;
717		TAILQ_FOREACH(tmp, &conf->constraints, entry)
718			cnt++;
719		if (cnt > 0 && ++total_fails >= cnt &&
720		    conf->constraint_median == 0) {
721			log_warnx("constraints configured but none available");
722			total_fails = 0;
723		}
724	}
725
726	if (fail || cstr->state < STATE_QUERY_SENT) {
727		cstr->senderrors++;
728		constraint_close(cstr->id);
729	}
730}
731
732void
733constraint_msg_dns(u_int32_t id, u_int8_t *data, size_t len)
734{
735	struct constraint	*cstr, *ncstr = NULL;
736	u_int8_t		*p;
737	struct ntp_addr		*h;
738
739	if ((cstr = constraint_byid(id)) == NULL) {
740		log_debug("IMSG_CONSTRAINT_DNS with invalid constraint id");
741		return;
742	}
743	if (cstr->addr != NULL) {
744		log_warnx("IMSG_CONSTRAINT_DNS but addr != NULL!");
745		return;
746	}
747	if (len == 0) {
748		log_debug("%s FAILED", __func__);
749		cstr->state = STATE_DNS_TEMPFAIL;
750		return;
751	}
752
753	if (len % (sizeof(struct sockaddr_storage) + sizeof(int)) != 0)
754		fatalx("IMSG_CONSTRAINT_DNS len");
755
756	if (cstr->addr_head.pool) {
757		struct constraint *n, *tmp;
758		TAILQ_FOREACH_SAFE(n, &conf->constraints, entry, tmp) {
759			if (cstr->id == n->id)
760				continue;
761			if (cstr->addr_head.pool == n->addr_head.pool)
762				constraint_remove(n);
763		}
764	}
765
766	p = data;
767	do {
768		if ((h = calloc(1, sizeof(*h))) == NULL)
769			fatal("calloc ntp_addr");
770		memcpy(&h->ss, p, sizeof(h->ss));
771		p += sizeof(h->ss);
772		len -= sizeof(h->ss);
773		memcpy(&h->notauth, p, sizeof(int));
774		p += sizeof(int);
775		len -= sizeof(int);
776
777		if (ncstr == NULL || cstr->addr_head.pool) {
778			ncstr = new_constraint();
779			ncstr->addr = h;
780			ncstr->addr_head.a = h;
781			ncstr->addr_head.name = strdup(cstr->addr_head.name);
782			ncstr->addr_head.path = strdup(cstr->addr_head.path);
783			if (ncstr->addr_head.name == NULL ||
784			    ncstr->addr_head.path == NULL)
785				fatal("calloc name");
786			ncstr->addr_head.pool = cstr->addr_head.pool;
787			ncstr->state = STATE_DNS_DONE;
788			constraint_add(ncstr);
789			constraint_cnt += constraint_init(ncstr);
790		} else {
791			h->next = ncstr->addr;
792			ncstr->addr = h;
793			ncstr->addr_head.a = h;
794		}
795	} while (len);
796
797	constraint_remove(cstr);
798}
799
800int
801constraint_cmp(const void *a, const void *b)
802{
803	time_t at = *(const time_t *)a;
804	time_t bt = *(const time_t *)b;
805	return at < bt ? -1 : (at > bt ? 1 : 0);
806}
807
808void
809constraint_update(void)
810{
811	struct constraint *cstr;
812	int	 cnt, i;
813	time_t	*values;
814	time_t	 now;
815
816	now = getmonotime();
817
818	cnt = 0;
819	TAILQ_FOREACH(cstr, &conf->constraints, entry) {
820		if (cstr->state != STATE_REPLY_RECEIVED)
821			continue;
822		cnt++;
823	}
824	if (cnt == 0)
825		return;
826
827	if ((values = calloc(cnt, sizeof(time_t))) == NULL)
828		fatal("calloc");
829
830	i = 0;
831	TAILQ_FOREACH(cstr, &conf->constraints, entry) {
832		if (cstr->state != STATE_REPLY_RECEIVED)
833			continue;
834		values[i++] = cstr->constraint + (now - cstr->last);
835	}
836
837	qsort(values, cnt, sizeof(time_t), constraint_cmp);
838
839	/* calculate median */
840	i = cnt / 2;
841	if (cnt % 2 == 0)
842		conf->constraint_median = (values[i - 1] + values[i]) / 2;
843	else
844		conf->constraint_median = values[i];
845
846	conf->constraint_last = now;
847
848	free(values);
849}
850
851void
852constraint_reset(void)
853{
854	struct constraint *cstr;
855
856	TAILQ_FOREACH(cstr, &conf->constraints, entry) {
857		if (cstr->state == STATE_QUERY_SENT)
858			continue;
859		constraint_close(cstr->id);
860		constraint_addr_head_clear(cstr);
861		constraint_init(cstr);
862	}
863	conf->constraint_errors = 0;
864}
865
866int
867constraint_check(double val)
868{
869	struct timeval	tv;
870	double		diff;
871	time_t		now;
872
873	if (conf->constraint_median == 0)
874		return (0);
875
876	/* Calculate the constraint with the current offset */
877	now = getmonotime();
878	tv.tv_sec = conf->constraint_median + (now - conf->constraint_last);
879	tv.tv_usec = 0;
880	diff = fabs(val - gettime_from_timeval(&tv));
881
882	if (diff > CONSTRAINT_MARGIN) {
883		if (conf->constraint_errors++ >
884		    (CONSTRAINT_ERROR_MARGIN * peer_cnt)) {
885			constraint_reset();
886		}
887
888		return (-1);
889	}
890
891	return (0);
892}
893
894struct httpsdate *
895httpsdate_init(const char *addr, const char *port, const char *hostname,
896    const char *path, const u_int8_t *ca, size_t ca_len, int synced)
897{
898	struct httpsdate	*httpsdate = NULL;
899
900	if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL)
901		goto fail;
902
903	if (hostname == NULL)
904		hostname = addr;
905
906	if ((httpsdate->tls_addr = strdup(addr)) == NULL ||
907	    (httpsdate->tls_port = strdup(port)) == NULL ||
908	    (httpsdate->tls_hostname = strdup(hostname)) == NULL ||
909	    (httpsdate->tls_path = strdup(path)) == NULL)
910		goto fail;
911
912	if (asprintf(&httpsdate->tls_request,
913	    "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
914	    httpsdate->tls_path, httpsdate->tls_hostname) == -1)
915		goto fail;
916
917	if ((httpsdate->tls_config = tls_config_new()) == NULL)
918		goto fail;
919	if (tls_config_set_ca_mem(httpsdate->tls_config, ca, ca_len) == -1)
920		goto fail;
921
922	/*
923	 * Due to the fact that we're trying to determine a constraint for time
924	 * we do our own certificate validity checking, since the automatic
925	 * version is based on our wallclock, which may well be inaccurate...
926	 */
927	if (!synced) {
928		log_debug("constraints: using received time in certificate validation");
929		tls_config_insecure_noverifytime(httpsdate->tls_config);
930	}
931
932	return (httpsdate);
933
934 fail:
935	httpsdate_free(httpsdate);
936	return (NULL);
937}
938
939void
940httpsdate_free(void *arg)
941{
942	struct httpsdate *httpsdate = arg;
943	if (httpsdate == NULL)
944		return;
945	if (httpsdate->tls_ctx)
946		tls_close(httpsdate->tls_ctx);
947	tls_free(httpsdate->tls_ctx);
948	tls_config_free(httpsdate->tls_config);
949	free(httpsdate->tls_addr);
950	free(httpsdate->tls_port);
951	free(httpsdate->tls_hostname);
952	free(httpsdate->tls_path);
953	free(httpsdate->tls_request);
954	free(httpsdate);
955}
956
957int
958httpsdate_request(struct httpsdate *httpsdate, struct timeval *when, int synced)
959{
960	char	 timebuf1[32], timebuf2[32];
961	size_t	 outlen = 0, maxlength = CONSTRAINT_MAXHEADERLENGTH, len;
962	char	*line, *p, *buf;
963	time_t	 httptime, notbefore, notafter;
964	struct tm *tm;
965	ssize_t	 ret;
966
967	if ((httpsdate->tls_ctx = tls_client()) == NULL)
968		goto fail;
969
970	if (tls_configure(httpsdate->tls_ctx, httpsdate->tls_config) == -1)
971		goto fail;
972
973	/*
974	 * libtls expects an address string, which can also be a DNS name,
975	 * but we pass a pre-resolved IP address string in tls_addr so it
976	 * does not trigger any DNS operation and is safe to be called
977	 * without the dns pledge.
978	 */
979	if (tls_connect_servername(httpsdate->tls_ctx, httpsdate->tls_addr,
980	    httpsdate->tls_port, httpsdate->tls_hostname) == -1) {
981		log_debug("tls connect failed: %s (%s): %s",
982		    httpsdate->tls_addr, httpsdate->tls_hostname,
983		    tls_error(httpsdate->tls_ctx));
984		goto fail;
985	}
986
987	buf = httpsdate->tls_request;
988	len = strlen(httpsdate->tls_request);
989	while (len > 0) {
990		ret = tls_write(httpsdate->tls_ctx, buf, len);
991		if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
992			continue;
993		if (ret == -1) {
994			log_warnx("tls write failed: %s (%s): %s",
995			    httpsdate->tls_addr, httpsdate->tls_hostname,
996			    tls_error(httpsdate->tls_ctx));
997			goto fail;
998		}
999		buf += ret;
1000		len -= ret;
1001	}
1002
1003	while ((line = tls_readline(httpsdate->tls_ctx, &outlen,
1004	    &maxlength, when)) != NULL) {
1005		line[strcspn(line, "\r\n")] = '\0';
1006
1007		if ((p = strchr(line, ' ')) == NULL || *p == '\0')
1008			goto next;
1009		*p++ = '\0';
1010		if (strcasecmp("Date:", line) != 0)
1011			goto next;
1012
1013		/*
1014		 * Expect the date/time format as IMF-fixdate which is
1015		 * mandated by HTTP/1.1 in the new RFC 7231 and was
1016		 * preferred by RFC 2616.  Other formats would be RFC 850
1017		 * or ANSI C's asctime() - the latter doesn't include
1018		 * the timezone which is required here.
1019		 */
1020		if (strptime(p, IMF_FIXDATE,
1021		    &httpsdate->tls_tm) == NULL) {
1022			log_warnx("unsupported date format");
1023			free(line);
1024			goto fail;
1025		}
1026
1027		free(line);
1028		break;
1029 next:
1030		free(line);
1031	}
1032	if (httpsdate->tls_tm.tm_year == 0)
1033		goto fail;
1034
1035	/* If we are synced, we already checked the certificate validity */
1036	if (synced)
1037		return 0;
1038
1039	/*
1040	 * Now manually check the validity of the certificate presented in the
1041	 * TLS handshake, based on the time specified by the server's HTTP Date:
1042	 * header.
1043	 */
1044	notbefore = tls_peer_cert_notbefore(httpsdate->tls_ctx);
1045	notafter = tls_peer_cert_notafter(httpsdate->tls_ctx);
1046	if ((httptime = timegm(&httpsdate->tls_tm)) == -1)
1047		goto fail;
1048	if (httptime <= notbefore) {
1049		if ((tm = gmtime(&notbefore)) == NULL)
1050			goto fail;
1051		if (strftime(timebuf1, sizeof(timebuf1), X509_DATE, tm) == 0)
1052			goto fail;
1053		if (strftime(timebuf2, sizeof(timebuf2), X509_DATE,
1054		    &httpsdate->tls_tm) == 0)
1055			goto fail;
1056		log_warnx("tls certificate not yet valid: %s (%s): "
1057		    "not before %s, now %s", httpsdate->tls_addr,
1058		    httpsdate->tls_hostname, timebuf1, timebuf2);
1059		goto fail;
1060	}
1061	if (httptime >= notafter) {
1062		if ((tm = gmtime(&notafter)) == NULL)
1063			goto fail;
1064		if (strftime(timebuf1, sizeof(timebuf1), X509_DATE, tm) == 0)
1065			goto fail;
1066		if (strftime(timebuf2, sizeof(timebuf2), X509_DATE,
1067		    &httpsdate->tls_tm) == 0)
1068			goto fail;
1069		log_warnx("tls certificate expired: %s (%s): "
1070		    "not after %s, now %s", httpsdate->tls_addr,
1071		    httpsdate->tls_hostname, timebuf1, timebuf2);
1072		goto fail;
1073	}
1074
1075	return (0);
1076
1077 fail:
1078	httpsdate_free(httpsdate);
1079	return (-1);
1080}
1081
1082void *
1083httpsdate_query(const char *addr, const char *port, const char *hostname,
1084    const char *path, const u_int8_t *ca, size_t ca_len,
1085    struct timeval *rectv, struct timeval *xmttv, int synced)
1086{
1087	struct httpsdate	*httpsdate;
1088	struct timeval		 when;
1089	time_t			 t;
1090
1091	if ((httpsdate = httpsdate_init(addr, port, hostname, path,
1092	    ca, ca_len, synced)) == NULL)
1093		return (NULL);
1094
1095	if (httpsdate_request(httpsdate, &when, synced) == -1)
1096		return (NULL);
1097
1098	/* Return parsed date as local time */
1099	t = timegm(&httpsdate->tls_tm);
1100
1101	/* Report parsed Date: as "received time" */
1102	rectv->tv_sec = t;
1103	rectv->tv_usec = 0;
1104
1105	/* And add delay as "transmit time" */
1106	xmttv->tv_sec = when.tv_sec;
1107	xmttv->tv_usec = when.tv_usec;
1108
1109	return (httpsdate);
1110}
1111
1112/* Based on SSL_readline in ftp/fetch.c */
1113char *
1114tls_readline(struct tls *tls, size_t *lenp, size_t *maxlength,
1115    struct timeval *when)
1116{
1117	size_t i, len;
1118	char *buf, *q, c;
1119	ssize_t ret;
1120
1121	len = 128;
1122	if ((buf = malloc(len)) == NULL)
1123		fatal("Can't allocate memory for transfer buffer");
1124	for (i = 0; ; i++) {
1125		if (i >= len - 1) {
1126			if ((q = reallocarray(buf, len, 2)) == NULL)
1127				fatal("Can't expand transfer buffer");
1128			buf = q;
1129			len *= 2;
1130		}
1131 again:
1132		ret = tls_read(tls, &c, 1);
1133		if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
1134			goto again;
1135		if (ret == -1) {
1136			/* SSL read error, ignore */
1137			free(buf);
1138			return (NULL);
1139		}
1140
1141		if (maxlength != NULL && (*maxlength)-- == 0) {
1142			log_warnx("maximum length exceeded");
1143			free(buf);
1144			return (NULL);
1145		}
1146
1147		buf[i] = c;
1148		if (c == '\n')
1149			break;
1150	}
1151	*lenp = i;
1152	if (gettimeofday(when, NULL) == -1)
1153		fatal("gettimeofday");
1154	return (buf);
1155}
1156
1157char *
1158get_string(u_int8_t *ptr, size_t len)
1159{
1160	size_t	 i;
1161
1162	for (i = 0; i < len; i++)
1163		if (!(isprint(ptr[i]) || isspace(ptr[i])))
1164			break;
1165
1166	return strndup(ptr, i);
1167}
1168