xref: /openbsd/usr.sbin/nsd/verify.c (revision 3efee2e1)
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