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