1 /*
2 * verify.c -- running verifiers and serving the zone to be verified.
3 *
4 * Copyright (c) 2012-2020, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 */
9
10 #include "config.h"
11
12 #include <assert.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #ifdef HAVE_SYSLOG_H
20 #include <syslog.h>
21 #endif /* HAVE_SYSLOG_H */
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/wait.h>
25
26 #include "region-allocator.h"
27 #include "namedb.h"
28 #include "nsd.h"
29 #include "options.h"
30 #include "difffile.h"
31 #include "verify.h"
32 #include "popen3.h"
33
verify_next_zone(struct nsd * nsd,struct zone * zone)34 struct zone *verify_next_zone(struct nsd *nsd, struct zone *zone)
35 {
36 int verify;
37 struct radnode *node;
38
39 if(zone != NULL) {
40 node = radix_next(zone->node);
41 } else {
42 node = radix_first(nsd->db->zonetree);
43 }
44
45 while(node != NULL) {
46 zone = (struct zone *)node->elem;
47 verify = zone->opts->pattern->verify_zone;
48 if(verify == VERIFY_ZONE_INHERIT) {
49 verify = nsd->options->verify_zones;
50 }
51 if(verify && zone->is_updated && !zone->is_checked) {
52 return zone;
53 }
54 node = radix_next(node);
55 }
56
57 return NULL;
58 }
59
fill_buffer(struct verifier_stream * stream)60 static inline ssize_t fill_buffer(struct verifier_stream *stream)
61 {
62 ssize_t cnt = 0;
63
64 assert(stream);
65 assert(stream->fd != -1);
66 assert(stream->cnt <= LOGBUFSIZE);
67 assert(stream->off <= stream->cnt);
68
69 // move data to start of buffer assuming all complete lines are printed
70 if (stream->off) {
71 size_t len = stream->cnt - stream->off;
72 memmove(stream->buf, stream->buf + stream->off, len);
73 stream->off = 0;
74 stream->cnt = len;
75 stream->buf[stream->cnt] = '\0'; // always null-terminate
76 }
77
78 // read data if space is available
79 cnt = read(stream->fd, stream->buf + stream->cnt, LOGBUFSIZE - stream->cnt);
80 if (cnt > 0)
81 stream->cnt += (size_t)cnt;
82 assert(stream->cnt <= LOGBUFSIZE);
83 assert(stream->off <= stream->cnt);
84 stream->buf[stream->cnt] = '\0'; // always null-terminate
85
86 return cnt;
87 }
88
print_line(struct verifier_stream * stream,int eof)89 static inline size_t print_line(struct verifier_stream *stream, int eof)
90 {
91 char *eol = NULL;
92 size_t len;
93 const char *fmt;
94
95 if (stream->cnt == 0)
96 return 0;
97 assert(stream->off <= stream->cnt);
98 if (stream->off == stream->cnt)
99 return 0;
100
101 // try to locate natural line break
102 assert(stream->buf[stream->cnt] == '\0');
103 if ((eol = strchr(stream->buf + stream->off, '\n'))) {
104 len = eol - (stream->buf + stream->off);
105 } else {
106 len = stream->cnt - stream->off;
107 }
108
109 assert(len <= (stream->cnt - stream->off));
110 // wait for buffer to contain a full line except on eof
111 if (len < LOGLINELEN && !eol && !eof)
112 return 0;
113
114 if (len > LOGLINELEN) {
115 fmt = stream->cut ? "verifier: .. %.*s .." : "verifier: %.*s ..";
116 len = LOGLINELEN; // remainder printed next iteration
117 stream->cut = 1;
118 } else {
119 fmt = stream->cut ? "verifier: .. %.*s" : "verifier: %.*s";
120 stream->cut = 0;
121 }
122 log_msg(stream->priority, fmt, len, stream->buf + stream->off);
123
124 stream->off += len + (eol != NULL);
125 assert(stream->off <= stream->cnt);
126 return len;
127 }
128
129 /*
130 * Log verifier output on STDOUT and STDERR. Lines longer than LOGLINELEN are
131 * split over multiple lines. Line-breaks are indicated in the log with "...".
132 */
verify_handle_stream(int fd,short event,void * arg)133 static void verify_handle_stream(int fd, short event, void *arg)
134 {
135 int eof = 0;
136 ssize_t cnt;
137 struct verifier *verifier;
138 struct verifier_stream *stream;
139
140 assert(event & EV_READ);
141 assert(arg != NULL);
142
143 verifier = (struct verifier *)arg;
144 if (fd == verifier->output_stream.fd) {
145 stream = &verifier->output_stream;
146 } else {
147 assert(fd == verifier->error_stream.fd);
148 stream = &verifier->error_stream;
149 }
150
151 assert(stream);
152 assert(stream->fd != -1);
153
154 do {
155 cnt = fill_buffer(stream);
156 eof = !cnt || (cnt < 0 && errno != EAGAIN && errno != EINTR);
157 while (print_line(stream, eof)) ;
158 } while (cnt > 0);
159
160 if(eof) {
161 event_del(&stream->event);
162 close(stream->fd);
163 stream->fd = -1;
164 }
165 }
166
kill_verifier(struct verifier * verifier)167 static void kill_verifier(struct verifier *verifier)
168 {
169 assert(verifier != NULL);
170 assert(verifier->zone != NULL);
171
172 if(kill(verifier->pid, SIGTERM) == -1) {
173 log_msg(LOG_ERR, "verify: cannot kill verifier for "
174 "zone %s (pid %d): %s",
175 verifier->zone->opts->name,
176 verifier->pid,
177 strerror(errno));
178 }
179 }
180
close_stream(struct verifier * verifier,struct verifier_stream * stream)181 static void close_stream(struct verifier *verifier, struct verifier_stream *stream)
182 {
183 if (stream->fd == -1)
184 return;
185 verify_handle_stream(stream->fd, EV_READ, verifier);
186 if (stream->fd == -1)
187 return;
188 event_del(&stream->event);
189 close(stream->fd);
190 stream->fd = -1;
191 }
192
close_verifier(struct verifier * verifier)193 static void close_verifier(struct verifier *verifier)
194 {
195 /* unregister events and close streams (in that order) */
196 if(verifier->timeout.tv_sec > 0) {
197 event_del(&verifier->timeout_event);
198 verifier->timeout.tv_sec = 0;
199 verifier->timeout.tv_usec = 0;
200 }
201
202 if(verifier->zone_feed.fh != NULL) {
203 event_del(&verifier->zone_feed.event);
204 fclose(verifier->zone_feed.fh);
205 verifier->zone_feed.fh = NULL;
206 region_destroy(verifier->zone_feed.region);
207 }
208
209 close_stream(verifier, &verifier->error_stream);
210 close_stream(verifier, &verifier->output_stream);
211
212 verifier->zone->is_ok = verifier->was_ok;
213 verifier->pid = -1;
214 verifier->zone = NULL;
215 }
216
217 /*
218 * Feed zone to verifier over STDIN as it becomes available.
219 */
verify_handle_feed(int fd,short event,void * arg)220 static void verify_handle_feed(int fd, short event, void *arg)
221 {
222 struct verifier *verifier;
223 struct rr *rr;
224
225 (void)fd;
226 assert(event == EV_WRITE);
227 assert(arg != NULL);
228
229 verifier = (struct verifier *)arg;
230 if((rr = zone_rr_iter_next(&verifier->zone_feed.rriter)) != NULL) {
231 print_rr(verifier->zone_feed.fh,
232 verifier->zone_feed.rrprinter,
233 rr,
234 verifier->zone_feed.region,
235 verifier->zone_feed.buffer);
236 } else {
237 event_del(&verifier->zone_feed.event);
238 fclose(verifier->zone_feed.fh);
239 verifier->zone_feed.fh = NULL;
240 region_destroy(verifier->zone_feed.region);
241 }
242 }
243
244 /*
245 * This handler will be called when a verifier-timeout alarm goes off. It just
246 * kills the verifier. server_verify_zones will make sure the zone will be
247 * considered bad.
248 */
verify_handle_timeout(int fd,short event,void * arg)249 void verify_handle_timeout(int fd, short event, void *arg)
250 {
251 struct verifier *verifier;
252
253 (void)fd;
254 assert(event & EV_TIMEOUT);
255 assert(arg != NULL);
256
257 verifier = (struct verifier *)arg;
258 verifier->zone->is_bad = 1;
259
260 log_msg(LOG_ERR, "verify: verifier for zone %s (pid %d) timed out",
261 verifier->zone->opts->name, verifier->pid);
262
263 /* kill verifier, process reaped by exit handler */
264 kill_verifier(verifier);
265 }
266
verify_handle_signal(int sig,short event,void * arg)267 void verify_handle_signal(int sig, short event, void *arg)
268 {
269 char buf[1] = { '\0' };
270 struct nsd *nsd;
271
272 assert(sig == SIGCHLD);
273 assert(event & EV_SIGNAL);
274 assert(arg != NULL);
275
276 nsd = (struct nsd *)arg;
277 if(write(nsd->verifier_pipe[1], buf, sizeof(buf)) == -1) {
278 log_msg(LOG_ERR, "verify_handle_signal: write failed: %s",
279 strerror(errno));
280 }
281 }
282
283 /*
284 * Reap process and update status of respective zone based on the exit code
285 * of a verifier. Everything from STDOUT and STDERR still available is read and
286 * written to the log as it might contain valuable information.
287 *
288 * NOTE: A timeout might have caused the verifier to be terminated.
289 */
verify_handle_exit(int fd,short event,void * arg)290 void verify_handle_exit(int fd, short event, void *arg)
291 {
292 int wstatus;
293 pid_t pid;
294 struct nsd *nsd;
295 char buf[1];
296
297 assert(event & EV_READ);
298 assert(arg != NULL);
299
300 nsd = (struct nsd *)arg;
301
302 if(read(fd, buf, sizeof(buf)) == -1) {
303 if(errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK)
304 log_msg(LOG_ERR, "verify_handle_exit: read failed: %s",
305 strerror(errno));
306 }
307
308 while(((pid = waitpid(-1, &wstatus, WNOHANG)) == -1 && errno == EINTR)
309 || (pid > 0))
310 {
311 struct verifier *verifier = NULL;
312
313 for(size_t i = 0; !verifier && i < nsd->verifier_limit; i++) {
314 if(nsd->verifiers[i].zone != NULL &&
315 nsd->verifiers[i].pid == pid)
316 {
317 verifier = &nsd->verifiers[i];
318 }
319 }
320
321 if(verifier == NULL) {
322 continue;
323 }
324
325 if(!WIFEXITED(wstatus)) {
326 log_msg(LOG_ERR, "verify: verifier for zone %s "
327 "(pid %d) exited abnormally",
328 verifier->zone->opts->name, pid);
329 } else {
330 int priority = LOG_INFO;
331 int status = WEXITSTATUS(wstatus);
332 if(status != 0) {
333 priority = LOG_ERR;
334 verifier->zone->is_bad = 1;
335 }
336 log_msg(priority, "verify: verifier for zone %s "
337 "(pid %d) exited with %d",
338 verifier->zone->opts->name, pid, status);
339 }
340
341 close_verifier(verifier);
342 nsd->verifier_count--;
343 }
344
345 while(nsd->mode == NSD_RUN &&
346 nsd->verifier_count < nsd->verifier_limit &&
347 nsd->next_zone_to_verify != NULL)
348 {
349 verify_zone(nsd, nsd->next_zone_to_verify);
350 nsd->next_zone_to_verify
351 = verify_next_zone(nsd, nsd->next_zone_to_verify);
352 }
353
354 if(nsd->next_zone_to_verify == NULL && nsd->verifier_count == 0) {
355 event_base_loopexit(nsd->event_base, NULL);
356 return;
357 }
358 }
359
360 /*
361 * A parent may be terminated (by the NSD_QUIT signal (nsdc stop command)).
362 * When a reload server process is running, the parent will then send a
363 * NSD_QUIT command to that server. This handler makes sure that this command
364 * is not neglected and that the reload server process will exit (gracefully).
365 */
366 void
verify_handle_command(int fd,short event,void * arg)367 verify_handle_command(int fd, short event, void *arg)
368 {
369 struct nsd *nsd = (struct nsd *)arg;
370 int len;
371 sig_atomic_t mode;
372
373 assert(nsd != NULL);
374 assert(event & (EV_READ
375 #ifdef EV_CLOSED
376 | EV_CLOSED
377 #endif
378 ));
379
380 if((len = read(fd, &mode, sizeof(mode))) == -1) {
381 log_msg(LOG_ERR, "verify: verify_handle_command: read: %s",
382 strerror(errno));
383 return;
384 } else if(len == 0) {
385 log_msg(LOG_INFO, "verify: command channel closed");
386 mode = NSD_QUIT;
387 } else if(mode != NSD_QUIT) {
388 log_msg(LOG_ERR, "verify: bad command: %d", (int)mode);
389 return;
390 }
391
392 nsd->mode = mode;
393
394 if(nsd->verifier_count == 0) {
395 event_base_loopexit(nsd->event_base, NULL);
396 return; /* exit early if no verifiers are executing */
397 }
398
399 /* kill verifiers, processes reaped elsewhere */
400 for(size_t i = 0; i < nsd->verifier_limit; i++) {
401 if(nsd->verifiers[i].zone != NULL) {
402 kill_verifier(&nsd->verifiers[i]);
403 }
404 }
405 }
406
407 /*
408 * A verifier is executed for the specified zone (if a verifier is configured
409 * and the zone has not been verified before). If one of the verifiers exits
410 * with non-zero, the zone is marked bad and nsd drops the zone update and
411 * reloads again.
412 */
verify_zone(struct nsd * nsd,struct zone * zone)413 void verify_zone(struct nsd *nsd, struct zone *zone)
414 {
415 struct verifier *verifier = NULL;
416 int32_t timeout;
417 char **command;
418 FILE *fin;
419 int fdin, fderr, fdout, flags;
420
421 assert(nsd != NULL);
422 assert(nsd->verifier_count < nsd->verifier_limit);
423 assert(zone != NULL);
424
425 fin = NULL;
426 fdin = fdout = fderr = -1;
427
428 /* search for available verifier slot */
429 for(size_t i = 0; i < nsd->verifier_limit && !verifier; i++) {
430 if(nsd->verifiers[i].zone == NULL) {
431 verifier = &nsd->verifiers[i];
432 }
433 }
434
435 assert(verifier != NULL);
436
437 if(zone->opts->pattern->verifier != NULL) {
438 command = zone->opts->pattern->verifier;
439 } else if (nsd->options->verifier != NULL) {
440 command = nsd->options->verifier;
441 } else {
442 log_msg(LOG_ERR, "verify: no verifier for zone %s",
443 zone->opts->name);
444 return;
445 }
446
447 if(zone->opts->pattern->verifier_timeout
448 != VERIFIER_TIMEOUT_INHERIT)
449 {
450 timeout = zone->opts->pattern->verifier_timeout;
451 } else {
452 timeout = nsd->options->verifier_timeout;
453 }
454
455 if(zone->opts->pattern->verifier_feed_zone
456 != VERIFIER_FEED_ZONE_INHERIT)
457 {
458 fdin = zone->opts->pattern->verifier_feed_zone ? -2 : -1;
459 } else {
460 fdin = nsd->options->verifier_feed_zone ? -2 : -1;
461 }
462
463 assert(timeout >= 0);
464
465 setenv("VERIFY_ZONE", zone->opts->name, 1);
466 setenv("VERIFY_ZONE_ON_STDIN", fdin == -2 ? "yes" : "no", 1);
467
468 verifier->pid = popen3(
469 command, fdin == -2 ? &fdin : NULL, &fdout, &fderr);
470 if(verifier->pid == -1) {
471 log_msg(LOG_ERR, "verify: could not start verifier for zone "
472 "%s: %s", zone->opts->name, strerror(errno));
473 goto fail_popen3;
474 }
475 flags = fcntl(fderr, F_GETFL, 0);
476 if (fcntl(fderr, F_SETFL, flags | O_NONBLOCK) == -1) {
477 log_msg(LOG_ERR, "verify: fcntl(stderr, ..., O_NONBLOCK) for "
478 "zone %s: %s",
479 zone->opts->name, strerror(errno));
480 goto fail_fcntl;
481 }
482 flags = fcntl(fdout, F_GETFL, 0);
483 if(fcntl(fdout, F_SETFL, flags | O_NONBLOCK) == -1) {
484 log_msg(LOG_ERR, "verify: fcntl(stdout, ..., O_NONBLOCK) for "
485 "zone %s: %s",
486 zone->opts->name, strerror(errno));
487 goto fail_fcntl;
488 }
489 if (fdin >= 0) {
490 if ((fin = fdopen(fdin, "w")) == NULL) {
491 log_msg(LOG_ERR, "verify: fdopen(stdin, ...) for "
492 "zone %s: %s",
493 zone->opts->name, strerror(errno));
494 goto fail_fcntl;
495 }
496 /* write unbuffered */
497 setbuf(fin, NULL);
498 }
499
500 verifier->zone = zone;
501 verifier->was_ok = zone->is_ok;
502
503 unsetenv("VERIFY_ZONE");
504 unsetenv("VERIFY_ZONE_ON_STDIN");
505
506 verifier->error_stream.fd = fderr;
507 verifier->error_stream.cnt = 0;
508 verifier->error_stream.off = 0;
509 verifier->error_stream.buf[0] = '\0';
510 event_set(&verifier->error_stream.event,
511 verifier->error_stream.fd,
512 EV_READ|EV_PERSIST,
513 verify_handle_stream,
514 verifier);
515 event_base_set(nsd->event_base, &verifier->error_stream.event);
516 if(event_add(&verifier->error_stream.event, NULL) != 0) {
517 log_msg(LOG_ERR, "verify: could not add error event for "
518 "zone %s", zone->opts->name);
519 goto fail_stderr;
520 }
521
522 verifier->output_stream.fd = fdout;
523 verifier->output_stream.cnt = 0;
524 verifier->output_stream.off = 0;
525 verifier->output_stream.buf[0] = '\0';
526 event_set(&verifier->output_stream.event,
527 verifier->output_stream.fd,
528 EV_READ|EV_PERSIST,
529 verify_handle_stream,
530 verifier);
531 event_base_set(nsd->event_base, &verifier->output_stream.event);
532 if(event_add(&verifier->output_stream.event, NULL) != 0) {
533 log_msg(LOG_ERR, "verify: could not add output event for "
534 "zone %s", zone->opts->name);
535 goto fail_stdout;
536 }
537
538 if(fin != NULL) {
539 verifier->zone_feed.fh = fin;
540
541 zone_rr_iter_init(&verifier->zone_feed.rriter, zone);
542
543 verifier->zone_feed.rrprinter
544 = create_pretty_rr(nsd->server_region);
545 verifier->zone_feed.region
546 = region_create(xalloc, free);
547 verifier->zone_feed.buffer
548 = buffer_create(nsd->server_region, MAX_RDLENGTH);
549
550 event_set(&verifier->zone_feed.event,
551 fileno(verifier->zone_feed.fh),
552 EV_WRITE|EV_PERSIST,
553 &verify_handle_feed,
554 verifier);
555 event_base_set(nsd->event_base, &verifier->zone_feed.event);
556 if(event_add(&verifier->zone_feed.event, NULL) != 0) {
557 log_msg(LOG_ERR, "verify: could not add input event "
558 "for zone %s", zone->opts->name);
559 goto fail_stdin;
560 }
561 }
562
563 if(timeout > 0) {
564 verifier->timeout.tv_sec = timeout;
565 verifier->timeout.tv_usec = 0;
566 event_set(&verifier->timeout_event,
567 -1,
568 EV_TIMEOUT,
569 verify_handle_timeout,
570 verifier);
571 event_base_set(nsd->event_base, &verifier->timeout_event);
572 if(event_add(&verifier->timeout_event, &verifier->timeout) != 0) {
573 log_msg(LOG_ERR, "verify: could not add timeout event "
574 "for zone %s", zone->opts->name);
575 goto fail_timeout;
576 }
577
578 log_msg(LOG_INFO, "verify: started verifier for zone %s "
579 "(pid %d), timeout is %d seconds",
580 zone->opts->name, verifier->pid, timeout);
581 } else {
582 log_msg(LOG_INFO, "verify: started verifier for zone %s "
583 "(pid %d)", zone->opts->name, verifier->pid);
584 }
585
586 zone->is_ok = 1;
587 nsd->verifier_count++;
588 return;
589
590 fail_timeout:
591 verifier->timeout.tv_sec = 0;
592 verifier->timeout.tv_usec = 0;
593 if(fin != NULL) {
594 event_del(&verifier->zone_feed.event);
595 }
596 fail_stdin:
597 verifier->zone_feed.fh = NULL;
598 event_del(&verifier->output_stream.event);
599 fail_stdout:
600 verifier->output_stream.fd = -1;
601 event_del(&verifier->error_stream.event);
602 fail_stderr:
603 verifier->error_stream.fd = -1;
604 fail_fcntl:
605 kill_verifier(verifier);
606 if(fin != NULL) {
607 fclose(fin);
608 } else if (fdin >= 0) {
609 close(fdin);
610 }
611 close(fdout);
612 close(fderr);
613 fail_popen3:
614 zone->is_bad = 1;
615 verifier->pid = -1;
616 verifier->zone = NULL;
617 }
618