1 /* $OpenBSD: constraint.c,v 1.29 2016/06/01 16:35:58 deraadt 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 /* Get name and set process title */ 324 if (getnameinfo((struct sockaddr *)&cstr->addr->ss, 325 SA_LEN((struct sockaddr *)&cstr->addr->ss), 326 addr, sizeof(addr), NULL, 0, 327 NI_NUMERICHOST) != 0) 328 fatalx("%s getnameinfo", __func__); 329 330 log_debug("constraint request to %s", addr); 331 setproctitle("constraint from %s", addr); 332 333 /* Set file descriptors */ 334 if (dup2(pipes[1], CONSTRAINT_PASSFD) == -1) 335 fatal("%s dup2 CONSTRAINT_PASSFD", __func__); 336 if (pipes[0] != CONSTRAINT_PASSFD) 337 close(pipes[0]); 338 if (pipes[1] != CONSTRAINT_PASSFD) 339 close(pipes[1]); 340 (void)closefrom(CONSTRAINT_PASSFD + 1); 341 342 if (fcntl(CONSTRAINT_PASSFD, F_SETFD, FD_CLOEXEC) == -1) 343 fatal("%s fcntl F_SETFD", __func__); 344 345 cstr->fd = CONSTRAINT_PASSFD; 346 imsg_init(&cstr->ibuf, cstr->fd); 347 348 /* Get remaining data from imsg in the unpriv child */ 349 if (am->namelen) { 350 if ((cstr->addr_head.name = 351 get_string(data, am->namelen)) == NULL) 352 fatalx("invalid IMSG_CONSTRAINT_QUERY name"); 353 data += am->namelen; 354 } 355 if (am->pathlen) { 356 if ((cstr->addr_head.path = 357 get_string(data, am->pathlen)) == NULL) 358 fatalx("invalid IMSG_CONSTRAINT_QUERY path"); 359 } 360 361 /* Run! */ 362 if ((ctx = httpsdate_query(addr, 363 CONSTRAINT_PORT, cstr->addr_head.name, cstr->addr_head.path, 364 conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) { 365 /* Abort with failure but without warning */ 366 exit(1); 367 } 368 369 iov[0].iov_base = &rectv; 370 iov[0].iov_len = sizeof(rectv); 371 iov[1].iov_base = &xmttv; 372 iov[1].iov_len = sizeof(xmttv); 373 imsg_composev(&cstr->ibuf, 374 IMSG_CONSTRAINT_RESULT, 0, 0, -1, iov, 2); 375 imsg_flush(&cstr->ibuf); 376 377 /* Tear down the TLS connection after sending the result */ 378 httpsdate_free(ctx); 379 } 380 381 void 382 priv_constraint_check_child(pid_t pid, int status) 383 { 384 struct constraint *cstr; 385 int fail, sig; 386 char *signame; 387 388 fail = sig = 0; 389 if (WIFSIGNALED(status)) { 390 sig = WTERMSIG(status); 391 } else if (WIFEXITED(status)) { 392 if (WEXITSTATUS(status) != 0) 393 fail = 1; 394 } else 395 fatalx("unexpected cause of SIGCHLD"); 396 397 if ((cstr = constraint_bypid(pid)) != NULL) { 398 if (sig) { 399 if (sig != SIGTERM) { 400 signame = strsignal(sig) ? 401 strsignal(sig) : "unknown"; 402 log_warnx("constraint %s; " 403 "terminated with signal %d (%s)", 404 log_sockaddr((struct sockaddr *) 405 &cstr->addr->ss), sig, signame); 406 } 407 fail = 1; 408 } 409 410 priv_constraint_close(cstr->fd, fail); 411 } 412 } 413 414 void 415 priv_constraint_kill(u_int32_t id) 416 { 417 struct constraint *cstr; 418 419 if ((cstr = constraint_byid(id)) == NULL) { 420 log_warnx("IMSG_CONSTRAINT_KILL for invalid id %d", id); 421 return; 422 } 423 424 kill(cstr->pid, SIGTERM); 425 } 426 427 struct constraint * 428 constraint_byid(u_int32_t id) 429 { 430 struct constraint *cstr; 431 432 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 433 if (cstr->id == id) 434 return (cstr); 435 } 436 437 return (NULL); 438 } 439 440 struct constraint * 441 constraint_byfd(int fd) 442 { 443 struct constraint *cstr; 444 445 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 446 if (cstr->fd == fd) 447 return (cstr); 448 } 449 450 return (NULL); 451 } 452 453 struct constraint * 454 constraint_bypid(pid_t pid) 455 { 456 struct constraint *cstr; 457 458 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 459 if (cstr->pid == pid) 460 return (cstr); 461 } 462 463 return (NULL); 464 } 465 466 int 467 constraint_close(u_int32_t id) 468 { 469 struct constraint *cstr; 470 471 if ((cstr = constraint_byid(id)) == NULL) { 472 log_warn("%s: id %d: not found", __func__, id); 473 return (0); 474 } 475 476 cstr->last = getmonotime(); 477 478 if (cstr->addr == NULL || (cstr->addr = cstr->addr->next) == NULL) { 479 /* Either a pool or all addresses have been tried */ 480 cstr->addr = cstr->addr_head.a; 481 if (cstr->senderrors) 482 cstr->state = STATE_INVALID; 483 else if (cstr->state >= STATE_QUERY_SENT) 484 cstr->state = STATE_DNS_DONE; 485 486 return (1); 487 } 488 489 /* Go on and try the next resolved address for this constraint */ 490 return (constraint_init(cstr)); 491 } 492 493 void 494 priv_constraint_close(int fd, int fail) 495 { 496 struct constraint *cstr; 497 u_int32_t id; 498 499 if ((cstr = constraint_byfd(fd)) == NULL) { 500 log_warn("%s: fd %d: not found", __func__, fd); 501 return; 502 } 503 504 id = cstr->id; 505 constraint_remove(cstr); 506 constraint_cnt--; 507 508 imsg_compose(ibuf, IMSG_CONSTRAINT_CLOSE, id, 0, -1, 509 &fail, sizeof(fail)); 510 } 511 512 void 513 constraint_add(struct constraint *cstr) 514 { 515 TAILQ_INSERT_TAIL(&conf->constraints, cstr, entry); 516 } 517 518 void 519 constraint_remove(struct constraint *cstr) 520 { 521 TAILQ_REMOVE(&conf->constraints, cstr, entry); 522 523 msgbuf_clear(&cstr->ibuf.w); 524 if (cstr->fd != -1) 525 close(cstr->fd); 526 free(cstr->addr_head.name); 527 free(cstr->addr_head.path); 528 free(cstr->addr); 529 free(cstr); 530 } 531 532 void 533 constraint_purge(void) 534 { 535 struct constraint *cstr, *ncstr; 536 537 TAILQ_FOREACH_SAFE(cstr, &conf->constraints, entry, ncstr) 538 constraint_remove(cstr); 539 } 540 541 int 542 priv_constraint_dispatch(struct pollfd *pfd) 543 { 544 struct imsg imsg; 545 struct constraint *cstr; 546 ssize_t n; 547 struct timeval tv[2]; 548 549 if ((cstr = constraint_byfd(pfd->fd)) == NULL) 550 return (0); 551 552 if (!(pfd->revents & POLLIN)) 553 return (0); 554 555 if (((n = imsg_read(&cstr->ibuf)) == -1 && errno != EAGAIN) || n == 0) { 556 priv_constraint_close(pfd->fd, 1); 557 return (1); 558 } 559 560 for (;;) { 561 if ((n = imsg_get(&cstr->ibuf, &imsg)) == -1) { 562 priv_constraint_close(pfd->fd, 1); 563 return (1); 564 } 565 if (n == 0) 566 break; 567 568 switch (imsg.hdr.type) { 569 case IMSG_CONSTRAINT_RESULT: 570 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(tv)) 571 fatalx("invalid IMSG_CONSTRAINT received"); 572 573 /* forward imsg to ntp child, don't parse it here */ 574 imsg_compose(ibuf, imsg.hdr.type, 575 cstr->id, 0, -1, imsg.data, sizeof(tv)); 576 break; 577 default: 578 break; 579 } 580 imsg_free(&imsg); 581 } 582 583 return (0); 584 } 585 586 void 587 constraint_msg_result(u_int32_t id, u_int8_t *data, size_t len) 588 { 589 struct constraint *cstr; 590 struct timeval tv[2]; 591 double offset; 592 593 if ((cstr = constraint_byid(id)) == NULL) { 594 log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id"); 595 return; 596 } 597 598 if (len != sizeof(tv)) { 599 log_warnx("invalid IMSG_CONSTRAINT received"); 600 return; 601 } 602 603 memcpy(tv, data, len); 604 605 offset = gettime_from_timeval(&tv[0]) - 606 gettime_from_timeval(&tv[1]); 607 608 log_info("constraint reply from %s: offset %f", 609 log_sockaddr((struct sockaddr *)&cstr->addr->ss), 610 offset); 611 612 cstr->state = STATE_REPLY_RECEIVED; 613 cstr->last = getmonotime(); 614 cstr->constraint = tv[0].tv_sec; 615 616 constraint_update(); 617 } 618 619 void 620 constraint_msg_close(u_int32_t id, u_int8_t *data, size_t len) 621 { 622 struct constraint *cstr; 623 int fail; 624 625 if ((cstr = constraint_byid(id)) == NULL) { 626 log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id"); 627 return; 628 } 629 630 if (len != sizeof(int)) { 631 log_warnx("invalid IMSG_CONSTRAINT_CLOSE received"); 632 return; 633 } 634 635 memcpy(&fail, data, len); 636 637 if (fail) { 638 log_debug("no constraint reply from %s" 639 " received in time, next query %ds", 640 log_sockaddr((struct sockaddr *) 641 &cstr->addr->ss), CONSTRAINT_SCAN_INTERVAL); 642 } 643 644 if (fail || cstr->state < STATE_QUERY_SENT) { 645 cstr->senderrors++; 646 constraint_close(cstr->id); 647 } 648 } 649 650 void 651 constraint_msg_dns(u_int32_t id, u_int8_t *data, size_t len) 652 { 653 struct constraint *cstr, *ncstr = NULL; 654 u_int8_t *p; 655 struct ntp_addr *h; 656 657 if ((cstr = constraint_byid(id)) == NULL) { 658 log_warnx("IMSG_CONSTRAINT_DNS with invalid constraint id"); 659 return; 660 } 661 if (cstr->addr != NULL) { 662 log_warnx("IMSG_CONSTRAINT_DNS but addr != NULL!"); 663 return; 664 } 665 if (len == 0) { 666 log_debug("%s FAILED", __func__); 667 cstr->state = STATE_DNS_TEMPFAIL; 668 return; 669 } 670 671 if ((len % sizeof(struct sockaddr_storage)) != 0) 672 fatalx("IMSG_CONSTRAINT_DNS len"); 673 674 p = data; 675 do { 676 if ((h = calloc(1, sizeof(*h))) == NULL) 677 fatal("calloc ntp_addr"); 678 memcpy(&h->ss, p, sizeof(h->ss)); 679 p += sizeof(h->ss); 680 len -= sizeof(h->ss); 681 682 if (ncstr == NULL || cstr->addr_head.pool) { 683 ncstr = new_constraint(); 684 ncstr->addr = h; 685 ncstr->addr_head.a = h; 686 ncstr->addr_head.name = strdup(cstr->addr_head.name); 687 ncstr->addr_head.path = strdup(cstr->addr_head.path); 688 if (ncstr->addr_head.name == NULL || 689 ncstr->addr_head.path == NULL) 690 fatal("calloc name"); 691 ncstr->addr_head.pool = cstr->addr_head.pool; 692 ncstr->state = STATE_DNS_DONE; 693 constraint_add(ncstr); 694 constraint_cnt += constraint_init(ncstr); 695 } else { 696 h->next = ncstr->addr; 697 ncstr->addr = h; 698 ncstr->addr_head.a = h; 699 } 700 } while (len); 701 702 constraint_remove(cstr); 703 } 704 705 int 706 constraint_cmp(const void *a, const void *b) 707 { 708 return (*(const time_t *)a - *(const time_t *)b); 709 } 710 711 void 712 constraint_update(void) 713 { 714 struct constraint *cstr; 715 int cnt, i; 716 time_t *sum; 717 time_t now; 718 719 now = getmonotime(); 720 721 cnt = 0; 722 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 723 if (cstr->state != STATE_REPLY_RECEIVED) 724 continue; 725 cnt++; 726 } 727 728 if ((sum = calloc(cnt, sizeof(time_t))) == NULL) 729 fatal("calloc"); 730 731 i = 0; 732 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 733 if (cstr->state != STATE_REPLY_RECEIVED) 734 continue; 735 sum[i++] = cstr->constraint + (now - cstr->last); 736 } 737 738 qsort(sum, cnt, sizeof(time_t), constraint_cmp); 739 740 /* calculate median */ 741 i = cnt / 2; 742 if (cnt % 2 == 0) 743 if (sum[i - 1] < sum[i]) 744 i -= 1; 745 746 conf->constraint_last = now; 747 conf->constraint_median = sum[i]; 748 749 free(sum); 750 } 751 752 void 753 constraint_reset(void) 754 { 755 struct constraint *cstr; 756 757 TAILQ_FOREACH(cstr, &conf->constraints, entry) { 758 if (cstr->state == STATE_QUERY_SENT) 759 continue; 760 constraint_close(cstr->id); 761 } 762 conf->constraint_errors = 0; 763 } 764 765 int 766 constraint_check(double val) 767 { 768 struct timeval tv; 769 double constraint; 770 time_t now; 771 772 if (conf->constraint_median == 0) 773 return (0); 774 775 /* Calculate the constraint with the current offset */ 776 now = getmonotime(); 777 tv.tv_sec = conf->constraint_median + (now - conf->constraint_last); 778 tv.tv_usec = 0; 779 constraint = gettime_from_timeval(&tv); 780 781 if (((val - constraint) > CONSTRAINT_MARGIN) || 782 ((constraint - val) > CONSTRAINT_MARGIN)) { 783 /* XXX get new constraint if too many errors happened */ 784 if (conf->constraint_errors++ > 785 (CONSTRAINT_ERROR_MARGIN * peer_cnt)) { 786 constraint_reset(); 787 } 788 789 return (-1); 790 } 791 792 return (0); 793 } 794 795 struct httpsdate * 796 httpsdate_init(const char *addr, const char *port, const char *hostname, 797 const char *path, const u_int8_t *ca, size_t ca_len) 798 { 799 struct httpsdate *httpsdate = NULL; 800 801 if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL) 802 goto fail; 803 804 if (hostname == NULL) 805 hostname = addr; 806 807 if ((httpsdate->tls_addr = strdup(addr)) == NULL || 808 (httpsdate->tls_port = strdup(port)) == NULL || 809 (httpsdate->tls_hostname = strdup(hostname)) == NULL || 810 (httpsdate->tls_path = strdup(path)) == NULL) 811 goto fail; 812 813 if (asprintf(&httpsdate->tls_request, 814 "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", 815 httpsdate->tls_path, httpsdate->tls_hostname) == -1) 816 goto fail; 817 818 if ((httpsdate->tls_config = tls_config_new()) == NULL) 819 goto fail; 820 821 if (tls_config_set_ciphers(httpsdate->tls_config, "compat") != 0) 822 goto fail; 823 824 if (ca == NULL || ca_len == 0) 825 tls_config_insecure_noverifycert(httpsdate->tls_config); 826 else 827 tls_config_set_ca_mem(httpsdate->tls_config, ca, ca_len); 828 829 return (httpsdate); 830 831 fail: 832 httpsdate_free(httpsdate); 833 return (NULL); 834 } 835 836 void 837 httpsdate_free(void *arg) 838 { 839 struct httpsdate *httpsdate = arg; 840 if (httpsdate == NULL) 841 return; 842 if (httpsdate->tls_ctx) 843 tls_close(httpsdate->tls_ctx); 844 tls_free(httpsdate->tls_ctx); 845 tls_config_free(httpsdate->tls_config); 846 free(httpsdate->tls_addr); 847 free(httpsdate->tls_port); 848 free(httpsdate->tls_hostname); 849 free(httpsdate->tls_path); 850 free(httpsdate->tls_request); 851 free(httpsdate); 852 } 853 854 int 855 httpsdate_request(struct httpsdate *httpsdate, struct timeval *when) 856 { 857 size_t outlen = 0, maxlength = CONSTRAINT_MAXHEADERLENGTH, len; 858 char *line, *p, *buf; 859 ssize_t ret; 860 861 if ((httpsdate->tls_ctx = tls_client()) == NULL) 862 goto fail; 863 864 if (tls_configure(httpsdate->tls_ctx, httpsdate->tls_config) == -1) 865 goto fail; 866 867 if (tls_connect_servername(httpsdate->tls_ctx, httpsdate->tls_addr, 868 httpsdate->tls_port, httpsdate->tls_hostname) == -1) { 869 log_debug("tls connect failed: %s (%s): %s", 870 httpsdate->tls_addr, httpsdate->tls_hostname, 871 tls_error(httpsdate->tls_ctx)); 872 goto fail; 873 } 874 875 buf = httpsdate->tls_request; 876 len = strlen(httpsdate->tls_request); 877 while (len > 0) { 878 ret = tls_write(httpsdate->tls_ctx, buf, len); 879 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) 880 continue; 881 if (ret < 0) { 882 log_warnx("tls write failed: %s (%s): %s", 883 httpsdate->tls_addr, httpsdate->tls_hostname, 884 tls_error(httpsdate->tls_ctx)); 885 goto fail; 886 } 887 buf += ret; 888 len -= ret; 889 } 890 891 while ((line = tls_readline(httpsdate->tls_ctx, &outlen, 892 &maxlength, when)) != NULL) { 893 line[strcspn(line, "\r\n")] = '\0'; 894 895 if ((p = strchr(line, ' ')) == NULL || *p == '\0') 896 goto next; 897 *p++ = '\0'; 898 if (strcasecmp("Date:", line) != 0) 899 goto next; 900 901 /* 902 * Expect the date/time format as IMF-fixdate which is 903 * mandated by HTTP/1.1 in the new RFC 7231 and was 904 * preferred by RFC 2616. Other formats would be RFC 850 905 * or ANSI C's asctime() - the latter doesn't include 906 * the timezone which is required here. 907 */ 908 if (strptime(p, "%a, %d %h %Y %T GMT", 909 &httpsdate->tls_tm) == NULL) { 910 log_warnx("unsupported date format"); 911 free(line); 912 return (-1); 913 } 914 915 free(line); 916 break; 917 next: 918 free(line); 919 } 920 921 return (0); 922 923 fail: 924 httpsdate_free(httpsdate); 925 return (-1); 926 } 927 928 void * 929 httpsdate_query(const char *addr, const char *port, const char *hostname, 930 const char *path, const u_int8_t *ca, size_t ca_len, 931 struct timeval *rectv, struct timeval *xmttv) 932 { 933 struct httpsdate *httpsdate; 934 struct timeval when; 935 time_t t; 936 937 if ((httpsdate = httpsdate_init(addr, port, hostname, path, 938 ca, ca_len)) == NULL) 939 return (NULL); 940 941 if (httpsdate_request(httpsdate, &when) == -1) 942 return (NULL); 943 944 /* Return parsed date as local time */ 945 t = timegm(&httpsdate->tls_tm); 946 947 /* Report parsed Date: as "received time" */ 948 rectv->tv_sec = t; 949 rectv->tv_usec = 0; 950 951 /* And add delay as "transmit time" */ 952 xmttv->tv_sec = when.tv_sec; 953 xmttv->tv_usec = when.tv_usec; 954 955 return (httpsdate); 956 } 957 958 /* Based on SSL_readline in ftp/fetch.c */ 959 char * 960 tls_readline(struct tls *tls, size_t *lenp, size_t *maxlength, 961 struct timeval *when) 962 { 963 size_t i, len; 964 char *buf, *q, c; 965 ssize_t ret; 966 967 len = 128; 968 if ((buf = malloc(len)) == NULL) 969 fatal("Can't allocate memory for transfer buffer"); 970 for (i = 0; ; i++) { 971 if (i >= len - 1) { 972 if ((q = reallocarray(buf, len, 2)) == NULL) 973 fatal("Can't expand transfer buffer"); 974 buf = q; 975 len *= 2; 976 } 977 again: 978 ret = tls_read(tls, &c, 1); 979 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) 980 goto again; 981 if (ret < 0) { 982 /* SSL read error, ignore */ 983 free(buf); 984 return (NULL); 985 } 986 987 if (maxlength != NULL && (*maxlength)-- == 0) { 988 log_warnx("maximum length exceeded"); 989 free(buf); 990 return (NULL); 991 } 992 993 buf[i] = c; 994 if (c == '\n') 995 break; 996 } 997 *lenp = i; 998 if (gettimeofday(when, NULL) == -1) 999 fatal("gettimeofday"); 1000 return (buf); 1001 } 1002 1003 char * 1004 get_string(u_int8_t *ptr, size_t len) 1005 { 1006 size_t i; 1007 1008 for (i = 0; i < len; i++) 1009 if (!(isprint(ptr[i]) || isspace(ptr[i]))) 1010 break; 1011 1012 return strndup(ptr, i); 1013 } 1014