xref: /openbsd-src/usr.sbin/ypldap/ypldap_dns.c (revision f1b790a5738b7375271fee81f99119b1f82f2cfd)
1*f1b790a5Sclaudio /*	$OpenBSD: ypldap_dns.c,v 1.21 2024/11/21 13:38:15 claudio Exp $ */
2db474592Saschrijver 
3db474592Saschrijver /*
4db474592Saschrijver  * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org>
5db474592Saschrijver  *
6db474592Saschrijver  * Permission to use, copy, modify, and distribute this software for any
7db474592Saschrijver  * purpose with or without fee is hereby granted, provided that the above
8db474592Saschrijver  * copyright notice and this permission notice appear in all copies.
9db474592Saschrijver  *
10db474592Saschrijver  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11db474592Saschrijver  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12db474592Saschrijver  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13db474592Saschrijver  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14db474592Saschrijver  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15db474592Saschrijver  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16db474592Saschrijver  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17db474592Saschrijver  */
18db474592Saschrijver 
19db474592Saschrijver #include <sys/types.h>
20db474592Saschrijver #include <sys/socket.h>
21db474592Saschrijver #include <sys/stat.h>
22db474592Saschrijver #include <sys/time.h>
23db474592Saschrijver #include <sys/tree.h>
24db474592Saschrijver #include <sys/queue.h>
25db474592Saschrijver 
26db474592Saschrijver #include <netinet/in.h>
27db474592Saschrijver 
28db474592Saschrijver #include <netdb.h>
29db474592Saschrijver #include <pwd.h>
30db474592Saschrijver #include <errno.h>
31db474592Saschrijver #include <event.h>
32db474592Saschrijver #include <resolv.h>
33db474592Saschrijver #include <poll.h>
34db474592Saschrijver #include <signal.h>
35db474592Saschrijver #include <stdlib.h>
36db474592Saschrijver #include <string.h>
37db474592Saschrijver #include <unistd.h>
38b9fc9a72Sderaadt #include <limits.h>
39db474592Saschrijver 
40db474592Saschrijver #include "ypldap.h"
4173492e0cSclaudio #include "log.h"
42db474592Saschrijver 
43db474592Saschrijver volatile sig_atomic_t	 quit_dns = 0;
44d46aeb19Seric struct imsgev		*iev_dns;
45db474592Saschrijver 
46db474592Saschrijver void	dns_dispatch_imsg(int, short, void *);
47db474592Saschrijver void	dns_sig_handler(int, short, void *);
48db474592Saschrijver void	dns_shutdown(void);
49441150e0Sjmatthew int	host_dns(const char *, struct ypldap_addr_list *);
50db474592Saschrijver 
51db474592Saschrijver void
52db474592Saschrijver dns_sig_handler(int sig, short event, void *p)
53db474592Saschrijver {
54db474592Saschrijver 	switch (sig) {
55db474592Saschrijver 	case SIGINT:
56db474592Saschrijver 	case SIGTERM:
57db474592Saschrijver 		dns_shutdown();
58db474592Saschrijver 		break;
5973492e0cSclaudio 	case SIGHUP:
6073492e0cSclaudio 		/* ignore */
6173492e0cSclaudio 		break;
62db474592Saschrijver 	default:
63db474592Saschrijver 		fatalx("unexpected signal");
64db474592Saschrijver 	}
65db474592Saschrijver }
66db474592Saschrijver 
67db474592Saschrijver void
68db474592Saschrijver dns_shutdown(void)
69db474592Saschrijver {
70db474592Saschrijver 	log_info("dns engine exiting");
71db474592Saschrijver 	_exit(0);
72db474592Saschrijver }
73db474592Saschrijver 
74db474592Saschrijver pid_t
75db474592Saschrijver ypldap_dns(int pipe_ntp[2], struct passwd *pw)
76db474592Saschrijver {
77db474592Saschrijver 	pid_t		 pid;
78db474592Saschrijver 	struct event	 ev_sigint;
79db474592Saschrijver 	struct event	 ev_sigterm;
80db474592Saschrijver 	struct event	 ev_sighup;
81db474592Saschrijver 	struct env	 env;
82db474592Saschrijver 
83db474592Saschrijver 	switch (pid = fork()) {
84db474592Saschrijver 	case -1:
85db474592Saschrijver 		fatal("cannot fork");
86db474592Saschrijver 		break;
87db474592Saschrijver 	case 0:
88db474592Saschrijver 		break;
89db474592Saschrijver 	default:
90db474592Saschrijver 		return (pid);
91db474592Saschrijver 	}
92db474592Saschrijver 
93db474592Saschrijver 	setproctitle("dns engine");
94db474592Saschrijver 	close(pipe_ntp[0]);
95db474592Saschrijver 
96db474592Saschrijver 	if (setgroups(1, &pw->pw_gid) ||
97db474592Saschrijver 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
98db474592Saschrijver 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
99db474592Saschrijver 		fatal("can't drop privileges");
100db474592Saschrijver 	endservent();
101db474592Saschrijver 
10230135bcbSjmatthew 	if (pledge("stdio dns", NULL) == -1)
10330135bcbSjmatthew 		fatal("pledge");
10430135bcbSjmatthew 
105db474592Saschrijver 	event_init();
106db474592Saschrijver 	signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL);
107db474592Saschrijver 	signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL);
108db474592Saschrijver 	signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL);
109db474592Saschrijver 	signal_add(&ev_sigint, NULL);
110db474592Saschrijver 	signal_add(&ev_sigterm, NULL);
111db474592Saschrijver 	signal_add(&ev_sighup, NULL);
112db474592Saschrijver 
113d46aeb19Seric 	if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
114db474592Saschrijver 		fatal(NULL);
115db474592Saschrijver 
116d46aeb19Seric 	env.sc_iev->events = EV_READ;
117d46aeb19Seric 	env.sc_iev->data = &env;
118*f1b790a5Sclaudio 	if (imsgbuf_init(&env.sc_iev->ibuf, pipe_ntp[1]) == -1)
119*f1b790a5Sclaudio 		fatal(NULL);
120d46aeb19Seric 	env.sc_iev->handler = dns_dispatch_imsg;
121d46aeb19Seric 	event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
122d46aeb19Seric 	    env.sc_iev->handler, &env);
123d46aeb19Seric 	event_add(&env.sc_iev->ev, NULL);
124db474592Saschrijver 
125db474592Saschrijver 	event_dispatch();
126db474592Saschrijver 	dns_shutdown();
127db474592Saschrijver 
128db474592Saschrijver 	return (0);
129db474592Saschrijver }
130db474592Saschrijver 
131db474592Saschrijver void
132f485ae0dSkrw dns_dispatch_imsg(int fd, short events, void *p)
133db474592Saschrijver {
134db474592Saschrijver 	struct imsg		 imsg;
135db474592Saschrijver 	int			 n, cnt;
136db474592Saschrijver 	char			*name;
137441150e0Sjmatthew 	struct ypldap_addr_list	 hn = TAILQ_HEAD_INITIALIZER(hn);
138441150e0Sjmatthew 	struct ypldap_addr	*h;
139e39620e5Snicm 	struct ibuf		*buf;
140db474592Saschrijver 	struct env		*env = p;
141d46aeb19Seric 	struct imsgev		*iev = env->sc_iev;
142d46aeb19Seric 	struct imsgbuf		*ibuf = &iev->ibuf;
143db474592Saschrijver 	int			 shut = 0;
144a6c6f2c9Sotto 	size_t			 len;
145db474592Saschrijver 
146f485ae0dSkrw 	if ((events & (EV_READ | EV_WRITE)) == 0)
147f485ae0dSkrw 		fatalx("unknown event");
148f485ae0dSkrw 
149f485ae0dSkrw 	if (events & EV_READ) {
150668e5ba9Sclaudio 		if ((n = imsgbuf_read(ibuf)) == -1)
151dd7efffeSclaudio 			fatal("imsgbuf_read error");
152db474592Saschrijver 		if (n == 0)
153db474592Saschrijver 			shut = 1;
154f485ae0dSkrw 	}
155f485ae0dSkrw 	if (events & EV_WRITE) {
156dd7efffeSclaudio 		if (imsgbuf_write(ibuf) == -1) {
157c1aa9554Sclaudio 			if (errno == EPIPE)	/* connection closed */
15842a8b0bcSkrw 				shut = 1;
159c1aa9554Sclaudio 			else
160dd7efffeSclaudio 				fatal("imsgbuf_write");
161c1aa9554Sclaudio 		}
162db474592Saschrijver 	}
163db474592Saschrijver 
164db474592Saschrijver 	for (;;) {
165db474592Saschrijver 		if ((n = imsg_get(ibuf, &imsg)) == -1)
166fdca1675Szinovik 			fatal("client_dispatch_imsg: imsg_get error");
167db474592Saschrijver 		if (n == 0)
168db474592Saschrijver 			break;
169db474592Saschrijver 
170db474592Saschrijver 		switch (imsg.hdr.type) {
171db474592Saschrijver 		case IMSG_HOST_DNS:
172db474592Saschrijver 			name = imsg.data;
173db474592Saschrijver 			if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
174db474592Saschrijver 				fatalx("invalid IMSG_HOST_DNS received");
175a6c6f2c9Sotto 			len = imsg.hdr.len - 1 - IMSG_HEADER_SIZE;
176a6c6f2c9Sotto 			if (name[len] != '\0' ||
177a6c6f2c9Sotto 			    strlen(name) != len)
178db474592Saschrijver 				fatalx("invalid IMSG_HOST_DNS received");
179db474592Saschrijver 			if ((cnt = host_dns(name, &hn)) == -1)
180db474592Saschrijver 				break;
181db474592Saschrijver 			buf = imsg_create(ibuf, IMSG_HOST_DNS,
182db474592Saschrijver 			    imsg.hdr.peerid, 0,
183db474592Saschrijver 			    cnt * sizeof(struct sockaddr_storage));
184db474592Saschrijver 			if (buf == NULL)
185db474592Saschrijver 				break;
1864251153aSjmatthew 			if (cnt > 0) {
187441150e0Sjmatthew 				while (!TAILQ_EMPTY(&hn)) {
188441150e0Sjmatthew 					h = TAILQ_FIRST(&hn);
189441150e0Sjmatthew 					TAILQ_REMOVE(&hn, h, next);
190db474592Saschrijver 					imsg_add(buf, &h->ss, sizeof(h->ss));
1914251153aSjmatthew 					free(h);
1924251153aSjmatthew 				}
1934251153aSjmatthew 			}
194db474592Saschrijver 
195db474592Saschrijver 			imsg_close(ibuf, buf);
196db474592Saschrijver 			break;
197db474592Saschrijver 		default:
198db474592Saschrijver 			break;
199db474592Saschrijver 		}
200db474592Saschrijver 		imsg_free(&imsg);
201db474592Saschrijver 	}
20242a8b0bcSkrw 
203db474592Saschrijver 	if (!shut)
204d46aeb19Seric 		imsg_event_add(iev);
205db474592Saschrijver 	else {
206db474592Saschrijver 		/* this pipe is dead, so remove the event handler */
207d46aeb19Seric 		event_del(&iev->ev);
208db474592Saschrijver 		event_loopexit(NULL);
209db474592Saschrijver 	}
210db474592Saschrijver }
211db474592Saschrijver 
212db474592Saschrijver int
213441150e0Sjmatthew host_dns(const char *s, struct ypldap_addr_list *hn)
214db474592Saschrijver {
215db474592Saschrijver 	struct addrinfo		 hints, *res0, *res;
216db474592Saschrijver 	int			 error, cnt = 0;
217db474592Saschrijver 	struct sockaddr_in	*sa_in;
218db474592Saschrijver 	struct sockaddr_in6	*sa_in6;
219441150e0Sjmatthew 	struct ypldap_addr	*h;
220db474592Saschrijver 
22144aaf217Smestre 	memset(&hints, 0, sizeof(hints));
222db474592Saschrijver 	hints.ai_family = PF_UNSPEC;
223db474592Saschrijver 	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
224db474592Saschrijver 	error = getaddrinfo(s, NULL, &hints, &res0);
2253d0e367aSjmatthew 	if (error != 0) {
2263d0e367aSjmatthew 		log_warnx("could not resolve \"%s\": %s", s,
227db474592Saschrijver 		    gai_strerror(error));
2283d0e367aSjmatthew 		if (error == EAI_AGAIN || error == EAI_NODATA ||
2293d0e367aSjmatthew 		    error == EAI_NONAME)
2303d0e367aSjmatthew 			return (0);
231db474592Saschrijver 		return (-1);
232db474592Saschrijver 	}
233db474592Saschrijver 
234db474592Saschrijver 	for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) {
235db474592Saschrijver 		if (res->ai_family != AF_INET &&
236db474592Saschrijver 		    res->ai_family != AF_INET6)
237db474592Saschrijver 			continue;
238db474592Saschrijver 		if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL)
239db474592Saschrijver 			fatal(NULL);
240db474592Saschrijver 		h->ss.ss_family = res->ai_family;
241db474592Saschrijver 		if (res->ai_family == AF_INET) {
242db474592Saschrijver 			sa_in = (struct sockaddr_in *)&h->ss;
243db474592Saschrijver 			sa_in->sin_len = sizeof(struct sockaddr_in);
244db474592Saschrijver 			sa_in->sin_addr.s_addr = ((struct sockaddr_in *)
245db474592Saschrijver 			    res->ai_addr)->sin_addr.s_addr;
246db474592Saschrijver 		} else {
247db474592Saschrijver 			sa_in6 = (struct sockaddr_in6 *)&h->ss;
248db474592Saschrijver 			sa_in6->sin6_len = sizeof(struct sockaddr_in6);
249db474592Saschrijver 			memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *)
250db474592Saschrijver 			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
251db474592Saschrijver 		}
252db474592Saschrijver 
253441150e0Sjmatthew 		TAILQ_INSERT_HEAD(hn, h, next);
254db474592Saschrijver 		cnt++;
255db474592Saschrijver 	}
256db474592Saschrijver 	freeaddrinfo(res0);
257db474592Saschrijver 	return (cnt);
258db474592Saschrijver }
259