Bug Summary

File:src/usr.sbin/ntpd/constraint.c
Warning:line 1100, column 16
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

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