1 /* $OpenBSD: constraint.c,v 1.31 2016/09/14 09:26:10 reyk 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 45 #include "ntpd.h" 46 47 int constraint_addr_init(struct constraint *); 48 struct constraint * 49 constraint_byid(u_int32_t); 50 struct constraint * 51 constraint_byfd(int); 52 struct constraint * 53 constraint_bypid(pid_t); 54 int constraint_close(u_int32_t); 55 void constraint_update(void); 56 void constraint_reset(void); 57 int constraint_cmp(const void *, const void *); 58 59 void priv_constraint_close(int, int); 60 void priv_constraint_child(struct constraint *, struct ntp_addr_msg *, 61 u_int8_t *, int[2], const char *, uid_t, gid_t); 62 63 struct httpsdate * 64 httpsdate_init(const char *, const char *, const char *, 65 const char *, const u_int8_t *, size_t); 66 void httpsdate_free(void *); 67 int httpsdate_request(struct httpsdate *, struct timeval *); 68 void *httpsdate_query(const char *, const char *, const char *, 69 const char *, const u_int8_t *, size_t, 70 struct timeval *, struct timeval *); 71 72 char *tls_readline(struct tls *, size_t *, size_t *, struct timeval *); 73 74 u_int constraint_cnt; 75 extern u_int peer_cnt; 76 extern struct imsgbuf *ibuf; /* priv */ 77 extern struct imsgbuf *ibuf_main; /* chld */ 78 79 struct httpsdate { 80 char *tls_addr; 81 char *tls_port; 82 char *tls_hostname; 83 char *tls_path; 84 char *tls_request; 85 struct tls_config *tls_config; 86 struct tls *tls_ctx; 87 struct tm tls_tm; 88 }; 89 90 int 91 constraint_init(struct constraint *cstr) 92 { 93 cstr->state = STATE_NONE; 94 cstr->fd = -1; 95 cstr->last = getmonotime(); 96 cstr->constraint = 0; 97 cstr->senderrors = 0; 98 99 return (constraint_addr_init(cstr)); 100 } 101 102 int 103 constraint_addr_init(struct constraint *cstr) 104 { 105 struct sockaddr_in *sa_in; 106 struct sockaddr_in6 *sa_in6; 107 struct ntp_addr *h; 108 109 if (cstr->state == STATE_DNS_INPROGRESS) 110 return (0); 111 112 if (cstr->addr_head.a == NULL) { 113 priv_dns(IMSG_CONSTRAINT_DNS, cstr->addr_head.name, cstr->id); 114 cstr->state = STATE_DNS_INPROGRESS; 115 return (0); 116 } 117 118 h = cstr->addr; 119 switch (h->ss.ss_family) { 120 case AF_INET: 121 sa_in = (struct sockaddr_in *)&h->ss; 122 if (ntohs(sa_in->sin_port) == 0) 123 sa_in->sin_port = htons(443); 124 cstr->state = STATE_DNS_DONE; 125 break; 126 case AF_INET6: 127 sa_in6 = (struct sockaddr_in6 *)&h->ss; 128 if (ntohs(sa_in6->sin6_port) == 0) 129 sa_in6->sin6_port = htons(443); 130 cstr->state = STATE_DNS_DONE; 131 break; 132 default: 133 /* XXX king bula sez it? */ 134 fatalx("wrong AF in constraint_addr_init"); 135 /* NOTREACHED */ 136 } 137 138 return (1); 139 } 140 141 int 142 constraint_query(struct constraint *cstr) 143 { 144 time_t now; 145 struct ntp_addr_msg am; 146 struct iovec iov[3]; 147 int iov_cnt = 0; 148 149 now = getmonotime(); 150 151 switch (cstr->state) { 152 case STATE_DNS_DONE: 153 /* Proceed and query the time */ 154 break; 155 case STATE_DNS_TEMPFAIL: 156 /* Retry resolving the address */ 157 constraint_init(cstr); 158 return (-1); 159 case STATE_QUERY_SENT: 160 if (cstr->last + CONSTRAINT_SCAN_TIMEOUT > now) { 161 /* The caller should expect a reply */ 162 return (0); 163 } 164 165 /* Timeout, just kill the process to reset it. */ 166 imsg_compose(ibuf_main, IMSG_CONSTRAINT_KILL, 167 cstr->id, 0, -1, NULL, 0); 168 169 cstr->state = STATE_TIMEOUT; 170 return (-1); 171 case STATE_INVALID: 172 if (cstr->last + CONSTRAINT_SCAN_INTERVAL > now) { 173 /* Nothing to do */ 174 return (-1); 175 } 176 177 /* Reset and retry */ 178 cstr->senderrors = 0; 179 constraint_close(cstr->id); 180 break; 181 case STATE_REPLY_RECEIVED: 182 default: 183 /* Nothing to do */ 184 return (-1); 185 } 186 187 cstr->last = now; 188 cstr->state = STATE_QUERY_SENT; 189 190 memset(&am, 0, sizeof(am)); 191 memcpy(&am.a, cstr->addr, sizeof(am.a)); 192 193 iov[iov_cnt].iov_base = &am; 194 iov[iov_cnt++].iov_len = sizeof(am); 195 if (cstr->addr_head.name) { 196 am.namelen = strlen(cstr->addr_head.name) + 1; 197 iov[iov_cnt].iov_base = cstr->addr_head.name; 198 iov[iov_cnt++].iov_len = am.namelen; 199 } 200 if (cstr->addr_head.path) { 201 am.pathlen = strlen(cstr->addr_head.path) + 1; 202 iov[iov_cnt].iov_base = cstr->addr_head.path; 203 iov[iov_cnt++].iov_len = am.pathlen; 204 } 205 206 imsg_composev(ibuf_main, IMSG_CONSTRAINT_QUERY, 207 cstr->id, 0, -1, iov, iov_cnt); 208 209 return (0); 210 } 211 212 void 213 priv_constraint_msg(u_int32_t id, u_int8_t *data, size_t len, 214 const char *pw_dir, uid_t pw_uid, gid_t pw_gid) 215 { 216 struct ntp_addr_msg am; 217 struct ntp_addr *h; 218 struct constraint *cstr; 219 int pipes[2]; 220 221 if ((cstr = constraint_byid(id)) != NULL) { 222 log_warnx("IMSG_CONSTRAINT_QUERY repeated for id %d", id); 223 return; 224 } 225 226 if (len < sizeof(am)) { 227 log_warnx("invalid IMSG_CONSTRAINT_QUERY received"); 228 return; 229 } 230 memcpy(&am, data, sizeof(am)); 231 if (len != (sizeof(am) + am.namelen + am.pathlen)) { 232 log_warnx("invalid IMSG_CONSTRAINT_QUERY received"); 233 return; 234 } 235 /* Additional imsg data is obtained in the unpriv child */ 236 237 if ((h = calloc(1, sizeof(*h))) == NULL) 238 fatal("calloc ntp_addr"); 239 memcpy(h, &am.a, sizeof(*h)); 240 h->next = NULL; 241 242 cstr = new_constraint(); 243 cstr->id = id; 244 cstr->addr = h; 245 cstr->addr_head.a = h; 246 constraint_add(cstr); 247 constraint_cnt++; 248 249 if (socketpair(AF_UNIX, SOCK_DGRAM, AF_UNSPEC, pipes) == -1) 250 fatal("%s pipes", __func__); 251 252 /* 253 * Fork child handlers and make sure to do any sensitive work in the 254 * the (unprivileged) child. The parent should not do any parsing, 255 * certificate loading etc. 256 */ 257 switch (cstr->pid = fork()) { 258 case -1: 259 cstr->senderrors++; 260 close(pipes[0]); 261 close(pipes[1]); 262 return; 263 case 0: 264 priv_constraint_child(cstr, &am, data + sizeof(am), pipes, 265 pw_dir, pw_uid, pw_gid); 266 267 _exit(0); 268 /* NOTREACHED */ 269 default: 270 /* Parent */ 271 close(pipes[1]); 272 cstr->fd = pipes[0]; 273 274 imsg_init(&cstr->ibuf, cstr->fd); 275 break; 276 } 277 } 278 279 void 280 priv_constraint_child(struct constraint *cstr, struct ntp_addr_msg *am, 281 u_int8_t *data, int pipes[2], const char *pw_dir, uid_t pw_uid, gid_t pw_gid) 282 { 283 static char addr[NI_MAXHOST]; 284 struct timeval rectv, xmttv; 285 struct sigaction sa; 286 void *ctx; 287 struct iovec iov[2]; 288 int i; 289 290 log_procinit("constraint"); 291 292 if (setpriority(PRIO_PROCESS, 0, 0) == -1) 293 log_warn("could not set priority"); 294 295 /* Init TLS and load CA certs before chroot() */ 296 if (tls_init() == -1) 297 fatalx("tls_init"); 298 if ((conf->ca = tls_load_file(CONSTRAINT_CA, 299 &conf->ca_len, NULL)) == NULL) 300 fatalx("failed to load constraint ca"); 301 302 if (chroot(pw_dir) == -1) 303 fatal("chroot"); 304 if (chdir("/") == -1) 305 fatal("chdir(\"/\")"); 306 307 if (setgroups(1, &pw_gid) || 308 setresgid(pw_gid, pw_gid, pw_gid) || 309 setresuid(pw_uid, pw_uid, pw_uid)) 310 fatal("can't drop privileges"); 311 312 /* Reset all signal handlers */ 313 memset(&sa, 0, sizeof(sa)); 314 sigemptyset(&sa.sa_mask); 315 sa.sa_flags = SA_RESTART; 316 sa.sa_handler = SIG_DFL; 317 for (i = 1; i < _NSIG; i++) 318 sigaction(i, &sa, NULL); 319 320 if (pledge("stdio inet", NULL) == -1) 321 fatal("pledge"); 322 323 /* 324 * Get the IP address as name and set the process title accordingly. 325 * This only converts an address into a string and does not trigger 326 * any DNS operation, so it is safe to be called without the dns 327 * pledge. 328 */ 329 if (getnameinfo((struct sockaddr *)&cstr->addr->ss, 330 SA_LEN((struct sockaddr *)&cstr->addr->ss), 331 addr, sizeof(addr), NULL, 0, 332 NI_NUMERICHOST) != 0) 333 fatalx("%s getnameinfo", __func__); 334 335 log_debug("constraint request to %s", addr); 336 setproctitle("constraint from %s", addr); 337 338 /* Set file descriptors */ 339 if (dup2(pipes[1], CONSTRAINT_PASSFD) == -1) 340 fatal("%s dup2 CONSTRAINT_PASSFD", __func__); 341 if (pipes[0] != CONSTRAINT_PASSFD) 342 close(pipes[0]); 343 if (pipes[1] != CONSTRAINT_PASSFD) 344 close(pipes[1]); 345 (void)closefrom(CONSTRAINT_PASSFD + 1); 346 347 /* 348 * Set the close-on-exec flag to prevent leaking the communication 349 * channel to any exec'ed child. In theory this could never happen, 350 * constraints don't exec children and pledge() prevents it, 351 * but we keep it as a safety belt; especially for portability. 352 */ 353 if (fcntl(CONSTRAINT_PASSFD, F_SETFD, FD_CLOEXEC) == -1) 354 fatal("%s fcntl F_SETFD", __func__); 355 356 cstr->fd = CONSTRAINT_PASSFD; 357 imsg_init(&cstr->ibuf, cstr->fd); 358 359 /* Get remaining data from imsg in the unpriv child */ 360 if (am->namelen) { 361 if ((cstr->addr_head.name = 362 get_string(data, am->namelen)) == NULL) 363 fatalx("invalid IMSG_CONSTRAINT_QUERY name"); 364 data += am->namelen; 365 } 366 if (am->pathlen) { 367 if ((cstr->addr_head.path = 368 get_string(data, am->pathlen)) == NULL) 369 fatalx("invalid IMSG_CONSTRAINT_QUERY path"); 370 } 371 372 /* Run! */ 373 if ((ctx = httpsdate_query(addr, 374 CONSTRAINT_PORT, cstr->addr_head.name, cstr->addr_head.path, 375 conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) { 376 /* Abort with failure but without warning */ 377 exit(1); 378 } 379 380 iov[0].iov_base = &rectv; 381 iov[0].iov_len = sizeof(rectv); 382 iov[1].iov_base = &xmttv; 383 iov[1].iov_len = sizeof(xmttv); 384 imsg_composev(&cstr->ibuf, 385 IMSG_CONSTRAINT_RESULT, 0, 0, -1, iov, 2); 386 imsg_flush(&cstr->ibuf); 387 388 /* Tear down the TLS connection after sending the result */ 389 httpsdate_free(ctx); 390 } 391 392 void 393 priv_constraint_check_child(pid_t pid, int status) 394 { 395 struct constraint *cstr; 396 int fail, sig; 397 char *signame; 398 399 fail = sig = 0; 400 if (WIFSIGNALED(status)) { 401 sig = WTERMSIG(status); 402 } else if (WIFEXITED(status)) { 403 if (WEXITSTATUS(status) != 0) 404 fail = 1; 405 } else 406 fatalx("unexpected cause of SIGCHLD"); 407 408 if ((cstr = constraint_bypid(pid)) != NULL) { 409 if (sig) { 410 if (sig != SIGTERM) { 411 signame = strsignal(sig) ? 412 strsignal(sig) : "unknown"; 413 log_warnx("constraint %s; " 414 "terminated with signal %d (%s)", 415 log_sockaddr((struct sockaddr *) 416 &cstr->addr->ss), sig, signame); 417 } 418 fail = 1; 419 } 420 421 priv_constraint_close(cstr->fd, fail); 422 } 423 } 424 425 void 426 priv_constraint_kill(u_int32_t id) 427 { 428 struct constraint *cstr; 429 430 if ((cstr = constraint_byid(id)) == NULL) { 431 log_warnx("IMSG_CONSTRAINT_KILL for invalid id %d", id); 432 return; 433 } 434 435 kill(cstr->pid, SIGTERM); 436 } 437 438 struct constraint * 439 constraint_byid(u_int32_t id) 440 { 441 struct constraint *cstr; 442 443 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 444 if (cstr->id == id) 445 return (cstr); 446 } 447 448 return (NULL); 449 } 450 451 struct constraint * 452 constraint_byfd(int fd) 453 { 454 struct constraint *cstr; 455 456 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 457 if (cstr->fd == fd) 458 return (cstr); 459 } 460 461 return (NULL); 462 } 463 464 struct constraint * 465 constraint_bypid(pid_t pid) 466 { 467 struct constraint *cstr; 468 469 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 470 if (cstr->pid == pid) 471 return (cstr); 472 } 473 474 return (NULL); 475 } 476 477 int 478 constraint_close(u_int32_t id) 479 { 480 struct constraint *cstr; 481 482 if ((cstr = constraint_byid(id)) == NULL) { 483 log_warn("%s: id %d: not found", __func__, id); 484 return (0); 485 } 486 487 cstr->last = getmonotime(); 488 489 if (cstr->addr == NULL || (cstr->addr = cstr->addr->next) == NULL) { 490 /* Either a pool or all addresses have been tried */ 491 cstr->addr = cstr->addr_head.a; 492 if (cstr->senderrors) 493 cstr->state = STATE_INVALID; 494 else if (cstr->state >= STATE_QUERY_SENT) 495 cstr->state = STATE_DNS_DONE; 496 497 return (1); 498 } 499 500 /* Go on and try the next resolved address for this constraint */ 501 return (constraint_init(cstr)); 502 } 503 504 void 505 priv_constraint_close(int fd, int fail) 506 { 507 struct constraint *cstr; 508 u_int32_t id; 509 510 if ((cstr = constraint_byfd(fd)) == NULL) { 511 log_warn("%s: fd %d: not found", __func__, fd); 512 return; 513 } 514 515 id = cstr->id; 516 constraint_remove(cstr); 517 constraint_cnt--; 518 519 imsg_compose(ibuf, IMSG_CONSTRAINT_CLOSE, id, 0, -1, 520 &fail, sizeof(fail)); 521 } 522 523 void 524 constraint_add(struct constraint *cstr) 525 { 526 TAILQ_INSERT_TAIL(&conf->constraints, cstr, entry); 527 } 528 529 void 530 constraint_remove(struct constraint *cstr) 531 { 532 TAILQ_REMOVE(&conf->constraints, cstr, entry); 533 534 msgbuf_clear(&cstr->ibuf.w); 535 if (cstr->fd != -1) 536 close(cstr->fd); 537 free(cstr->addr_head.name); 538 free(cstr->addr_head.path); 539 free(cstr->addr); 540 free(cstr); 541 } 542 543 void 544 constraint_purge(void) 545 { 546 struct constraint *cstr, *ncstr; 547 548 TAILQ_FOREACH_SAFE(cstr, &conf->constraints, entry, ncstr) 549 constraint_remove(cstr); 550 } 551 552 int 553 priv_constraint_dispatch(struct pollfd *pfd) 554 { 555 struct imsg imsg; 556 struct constraint *cstr; 557 ssize_t n; 558 struct timeval tv[2]; 559 560 if ((cstr = constraint_byfd(pfd->fd)) == NULL) 561 return (0); 562 563 if (!(pfd->revents & POLLIN)) 564 return (0); 565 566 if (((n = imsg_read(&cstr->ibuf)) == -1 && errno != EAGAIN) || n == 0) { 567 priv_constraint_close(pfd->fd, 1); 568 return (1); 569 } 570 571 for (;;) { 572 if ((n = imsg_get(&cstr->ibuf, &imsg)) == -1) { 573 priv_constraint_close(pfd->fd, 1); 574 return (1); 575 } 576 if (n == 0) 577 break; 578 579 switch (imsg.hdr.type) { 580 case IMSG_CONSTRAINT_RESULT: 581 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(tv)) 582 fatalx("invalid IMSG_CONSTRAINT received"); 583 584 /* forward imsg to ntp child, don't parse it here */ 585 imsg_compose(ibuf, imsg.hdr.type, 586 cstr->id, 0, -1, imsg.data, sizeof(tv)); 587 break; 588 default: 589 break; 590 } 591 imsg_free(&imsg); 592 } 593 594 return (0); 595 } 596 597 void 598 constraint_msg_result(u_int32_t id, u_int8_t *data, size_t len) 599 { 600 struct constraint *cstr; 601 struct timeval tv[2]; 602 double offset; 603 604 if ((cstr = constraint_byid(id)) == NULL) { 605 log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id"); 606 return; 607 } 608 609 if (len != sizeof(tv)) { 610 log_warnx("invalid IMSG_CONSTRAINT received"); 611 return; 612 } 613 614 memcpy(tv, data, len); 615 616 offset = gettime_from_timeval(&tv[0]) - 617 gettime_from_timeval(&tv[1]); 618 619 log_info("constraint reply from %s: offset %f", 620 log_sockaddr((struct sockaddr *)&cstr->addr->ss), 621 offset); 622 623 cstr->state = STATE_REPLY_RECEIVED; 624 cstr->last = getmonotime(); 625 cstr->constraint = tv[0].tv_sec; 626 627 constraint_update(); 628 } 629 630 void 631 constraint_msg_close(u_int32_t id, u_int8_t *data, size_t len) 632 { 633 struct constraint *cstr; 634 int fail; 635 636 if ((cstr = constraint_byid(id)) == NULL) { 637 log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id"); 638 return; 639 } 640 641 if (len != sizeof(int)) { 642 log_warnx("invalid IMSG_CONSTRAINT_CLOSE received"); 643 return; 644 } 645 646 memcpy(&fail, data, len); 647 648 if (fail) { 649 log_debug("no constraint reply from %s" 650 " received in time, next query %ds", 651 log_sockaddr((struct sockaddr *) 652 &cstr->addr->ss), CONSTRAINT_SCAN_INTERVAL); 653 } 654 655 if (fail || cstr->state < STATE_QUERY_SENT) { 656 cstr->senderrors++; 657 constraint_close(cstr->id); 658 } 659 } 660 661 void 662 constraint_msg_dns(u_int32_t id, u_int8_t *data, size_t len) 663 { 664 struct constraint *cstr, *ncstr = NULL; 665 u_int8_t *p; 666 struct ntp_addr *h; 667 668 if ((cstr = constraint_byid(id)) == NULL) { 669 log_warnx("IMSG_CONSTRAINT_DNS with invalid constraint id"); 670 return; 671 } 672 if (cstr->addr != NULL) { 673 log_warnx("IMSG_CONSTRAINT_DNS but addr != NULL!"); 674 return; 675 } 676 if (len == 0) { 677 log_debug("%s FAILED", __func__); 678 cstr->state = STATE_DNS_TEMPFAIL; 679 return; 680 } 681 682 if ((len % sizeof(struct sockaddr_storage)) != 0) 683 fatalx("IMSG_CONSTRAINT_DNS len"); 684 685 p = data; 686 do { 687 if ((h = calloc(1, sizeof(*h))) == NULL) 688 fatal("calloc ntp_addr"); 689 memcpy(&h->ss, p, sizeof(h->ss)); 690 p += sizeof(h->ss); 691 len -= sizeof(h->ss); 692 693 if (ncstr == NULL || cstr->addr_head.pool) { 694 ncstr = new_constraint(); 695 ncstr->addr = h; 696 ncstr->addr_head.a = h; 697 ncstr->addr_head.name = strdup(cstr->addr_head.name); 698 ncstr->addr_head.path = strdup(cstr->addr_head.path); 699 if (ncstr->addr_head.name == NULL || 700 ncstr->addr_head.path == NULL) 701 fatal("calloc name"); 702 ncstr->addr_head.pool = cstr->addr_head.pool; 703 ncstr->state = STATE_DNS_DONE; 704 constraint_add(ncstr); 705 constraint_cnt += constraint_init(ncstr); 706 } else { 707 h->next = ncstr->addr; 708 ncstr->addr = h; 709 ncstr->addr_head.a = h; 710 } 711 } while (len); 712 713 constraint_remove(cstr); 714 } 715 716 int 717 constraint_cmp(const void *a, const void *b) 718 { 719 return (*(const time_t *)a - *(const time_t *)b); 720 } 721 722 void 723 constraint_update(void) 724 { 725 struct constraint *cstr; 726 int cnt, i; 727 time_t *sum; 728 time_t now; 729 730 now = getmonotime(); 731 732 cnt = 0; 733 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 734 if (cstr->state != STATE_REPLY_RECEIVED) 735 continue; 736 cnt++; 737 } 738 739 if ((sum = calloc(cnt, sizeof(time_t))) == NULL) 740 fatal("calloc"); 741 742 i = 0; 743 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 744 if (cstr->state != STATE_REPLY_RECEIVED) 745 continue; 746 sum[i++] = cstr->constraint + (now - cstr->last); 747 } 748 749 qsort(sum, cnt, sizeof(time_t), constraint_cmp); 750 751 /* calculate median */ 752 i = cnt / 2; 753 if (cnt % 2 == 0) 754 if (sum[i - 1] < sum[i]) 755 i -= 1; 756 757 conf->constraint_last = now; 758 conf->constraint_median = sum[i]; 759 760 free(sum); 761 } 762 763 void 764 constraint_reset(void) 765 { 766 struct constraint *cstr; 767 768 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 769 if (cstr->state == STATE_QUERY_SENT) 770 continue; 771 constraint_close(cstr->id); 772 } 773 conf->constraint_errors = 0; 774 } 775 776 int 777 constraint_check(double val) 778 { 779 struct timeval tv; 780 double constraint; 781 time_t now; 782 783 if (conf->constraint_median == 0) 784 return (0); 785 786 /* Calculate the constraint with the current offset */ 787 now = getmonotime(); 788 tv.tv_sec = conf->constraint_median + (now - conf->constraint_last); 789 tv.tv_usec = 0; 790 constraint = gettime_from_timeval(&tv); 791 792 if (((val - constraint) > CONSTRAINT_MARGIN) || 793 ((constraint - val) > CONSTRAINT_MARGIN)) { 794 /* XXX get new constraint if too many errors happened */ 795 if (conf->constraint_errors++ > 796 (CONSTRAINT_ERROR_MARGIN * peer_cnt)) { 797 constraint_reset(); 798 } 799 800 return (-1); 801 } 802 803 return (0); 804 } 805 806 struct httpsdate * 807 httpsdate_init(const char *addr, const char *port, const char *hostname, 808 const char *path, const u_int8_t *ca, size_t ca_len) 809 { 810 struct httpsdate *httpsdate = NULL; 811 812 if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL) 813 goto fail; 814 815 if (hostname == NULL) 816 hostname = addr; 817 818 if ((httpsdate->tls_addr = strdup(addr)) == NULL || 819 (httpsdate->tls_port = strdup(port)) == NULL || 820 (httpsdate->tls_hostname = strdup(hostname)) == NULL || 821 (httpsdate->tls_path = strdup(path)) == NULL) 822 goto fail; 823 824 if (asprintf(&httpsdate->tls_request, 825 "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", 826 httpsdate->tls_path, httpsdate->tls_hostname) == -1) 827 goto fail; 828 829 if ((httpsdate->tls_config = tls_config_new()) == NULL) 830 goto fail; 831 832 if (tls_config_set_ciphers(httpsdate->tls_config, "all") != 0) 833 goto fail; 834 835 if (ca == NULL || ca_len == 0) 836 tls_config_insecure_noverifycert(httpsdate->tls_config); 837 else 838 tls_config_set_ca_mem(httpsdate->tls_config, ca, ca_len); 839 840 return (httpsdate); 841 842 fail: 843 httpsdate_free(httpsdate); 844 return (NULL); 845 } 846 847 void 848 httpsdate_free(void *arg) 849 { 850 struct httpsdate *httpsdate = arg; 851 if (httpsdate == NULL) 852 return; 853 if (httpsdate->tls_ctx) 854 tls_close(httpsdate->tls_ctx); 855 tls_free(httpsdate->tls_ctx); 856 tls_config_free(httpsdate->tls_config); 857 free(httpsdate->tls_addr); 858 free(httpsdate->tls_port); 859 free(httpsdate->tls_hostname); 860 free(httpsdate->tls_path); 861 free(httpsdate->tls_request); 862 free(httpsdate); 863 } 864 865 int 866 httpsdate_request(struct httpsdate *httpsdate, struct timeval *when) 867 { 868 size_t outlen = 0, maxlength = CONSTRAINT_MAXHEADERLENGTH, len; 869 char *line, *p, *buf; 870 ssize_t ret; 871 872 if ((httpsdate->tls_ctx = tls_client()) == NULL) 873 goto fail; 874 875 if (tls_configure(httpsdate->tls_ctx, httpsdate->tls_config) == -1) 876 goto fail; 877 878 /* 879 * libtls expects an address string, which can also be a DNS name, 880 * but we pass a pre-resolved IP address string in tls_addr so it 881 * does not trigger any DNS operation and is safe to be called 882 * without the dns pledge. 883 */ 884 if (tls_connect_servername(httpsdate->tls_ctx, httpsdate->tls_addr, 885 httpsdate->tls_port, httpsdate->tls_hostname) == -1) { 886 log_debug("tls connect failed: %s (%s): %s", 887 httpsdate->tls_addr, httpsdate->tls_hostname, 888 tls_error(httpsdate->tls_ctx)); 889 goto fail; 890 } 891 892 buf = httpsdate->tls_request; 893 len = strlen(httpsdate->tls_request); 894 while (len > 0) { 895 ret = tls_write(httpsdate->tls_ctx, buf, len); 896 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) 897 continue; 898 if (ret < 0) { 899 log_warnx("tls write failed: %s (%s): %s", 900 httpsdate->tls_addr, httpsdate->tls_hostname, 901 tls_error(httpsdate->tls_ctx)); 902 goto fail; 903 } 904 buf += ret; 905 len -= ret; 906 } 907 908 while ((line = tls_readline(httpsdate->tls_ctx, &outlen, 909 &maxlength, when)) != NULL) { 910 line[strcspn(line, "\r\n")] = '\0'; 911 912 if ((p = strchr(line, ' ')) == NULL || *p == '\0') 913 goto next; 914 *p++ = '\0'; 915 if (strcasecmp("Date:", line) != 0) 916 goto next; 917 918 /* 919 * Expect the date/time format as IMF-fixdate which is 920 * mandated by HTTP/1.1 in the new RFC 7231 and was 921 * preferred by RFC 2616. Other formats would be RFC 850 922 * or ANSI C's asctime() - the latter doesn't include 923 * the timezone which is required here. 924 */ 925 if (strptime(p, "%a, %d %h %Y %T GMT", 926 &httpsdate->tls_tm) == NULL) { 927 log_warnx("unsupported date format"); 928 free(line); 929 return (-1); 930 } 931 932 free(line); 933 break; 934 next: 935 free(line); 936 } 937 938 return (0); 939 940 fail: 941 httpsdate_free(httpsdate); 942 return (-1); 943 } 944 945 void * 946 httpsdate_query(const char *addr, const char *port, const char *hostname, 947 const char *path, const u_int8_t *ca, size_t ca_len, 948 struct timeval *rectv, struct timeval *xmttv) 949 { 950 struct httpsdate *httpsdate; 951 struct timeval when; 952 time_t t; 953 954 if ((httpsdate = httpsdate_init(addr, port, hostname, path, 955 ca, ca_len)) == NULL) 956 return (NULL); 957 958 if (httpsdate_request(httpsdate, &when) == -1) 959 return (NULL); 960 961 /* Return parsed date as local time */ 962 t = timegm(&httpsdate->tls_tm); 963 964 /* Report parsed Date: as "received time" */ 965 rectv->tv_sec = t; 966 rectv->tv_usec = 0; 967 968 /* And add delay as "transmit time" */ 969 xmttv->tv_sec = when.tv_sec; 970 xmttv->tv_usec = when.tv_usec; 971 972 return (httpsdate); 973 } 974 975 /* Based on SSL_readline in ftp/fetch.c */ 976 char * 977 tls_readline(struct tls *tls, size_t *lenp, size_t *maxlength, 978 struct timeval *when) 979 { 980 size_t i, len; 981 char *buf, *q, c; 982 ssize_t ret; 983 984 len = 128; 985 if ((buf = malloc(len)) == NULL) 986 fatal("Can't allocate memory for transfer buffer"); 987 for (i = 0; ; i++) { 988 if (i >= len - 1) { 989 if ((q = reallocarray(buf, len, 2)) == NULL) 990 fatal("Can't expand transfer buffer"); 991 buf = q; 992 len *= 2; 993 } 994 again: 995 ret = tls_read(tls, &c, 1); 996 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) 997 goto again; 998 if (ret < 0) { 999 /* SSL read error, ignore */ 1000 free(buf); 1001 return (NULL); 1002 } 1003 1004 if (maxlength != NULL && (*maxlength)-- == 0) { 1005 log_warnx("maximum length exceeded"); 1006 free(buf); 1007 return (NULL); 1008 } 1009 1010 buf[i] = c; 1011 if (c == '\n') 1012 break; 1013 } 1014 *lenp = i; 1015 if (gettimeofday(when, NULL) == -1) 1016 fatal("gettimeofday"); 1017 return (buf); 1018 } 1019 1020 char * 1021 get_string(u_int8_t *ptr, size_t len) 1022 { 1023 size_t i; 1024 1025 for (i = 0; i < len; i++) 1026 if (!(isprint(ptr[i]) || isspace(ptr[i]))) 1027 break; 1028 1029 return strndup(ptr, i); 1030 } 1031