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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 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 598 constraint_add(struct constraint *cstr) 599 { 600 TAILQ_INSERT_TAIL(&conf->constraints, cstr, entry); 601 } 602 603 void 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 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 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 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 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 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 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 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 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 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 * 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 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 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 * 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 * 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 * 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