xref: /openbsd/usr.sbin/acme-client/dnsproc.c (revision 28f2fbe8)
1*28f2fbe8Sjca /*	$Id: dnsproc.c,v 1.12 2021/12/13 13:30:39 jca Exp $ */
2de579d12Sflorian /*
3de579d12Sflorian  * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
4de579d12Sflorian  *
5de579d12Sflorian  * Permission to use, copy, modify, and distribute this software for any
6de579d12Sflorian  * purpose with or without fee is hereby granted, provided that the above
7de579d12Sflorian  * copyright notice and this permission notice appear in all copies.
8de579d12Sflorian  *
9de579d12Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
10de579d12Sflorian  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11de579d12Sflorian  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
12de579d12Sflorian  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13de579d12Sflorian  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14de579d12Sflorian  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15de579d12Sflorian  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16de579d12Sflorian  */
17de579d12Sflorian 
18de579d12Sflorian #include <sys/socket.h>
19de579d12Sflorian #include <arpa/inet.h>
20de579d12Sflorian 
21de579d12Sflorian #include <err.h>
22de579d12Sflorian #include <netdb.h>
23de579d12Sflorian #include <stdio.h>
24de579d12Sflorian #include <stdlib.h>
25de579d12Sflorian #include <string.h>
26de579d12Sflorian #include <unistd.h>
27de579d12Sflorian 
28de579d12Sflorian #include "extern.h"
29de579d12Sflorian 
30de579d12Sflorian struct	addr {
31de579d12Sflorian 	int	 family; /* 4 for PF_INET, 6 for PF_INET6 */
32de579d12Sflorian 	char	 ip[INET6_ADDRSTRLEN];
33de579d12Sflorian };
34de579d12Sflorian 
35de579d12Sflorian /*
36de579d12Sflorian  * This is a modified version of host_dns in config.c of OpenBSD's ntpd.
37de579d12Sflorian  */
38de579d12Sflorian /*
39de579d12Sflorian  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
40de579d12Sflorian  *
41de579d12Sflorian  * Permission to use, copy, modify, and distribute this software for any
42de579d12Sflorian  * purpose with or without fee is hereby granted, provided that the above
43de579d12Sflorian  * copyright notice and this permission notice appear in all copies.
44de579d12Sflorian  *
45de579d12Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
46de579d12Sflorian  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
47de579d12Sflorian  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
48de579d12Sflorian  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
49de579d12Sflorian  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
50de579d12Sflorian  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
51de579d12Sflorian  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
52de579d12Sflorian  */
53de579d12Sflorian static ssize_t
host_dns(const char * s,struct addr * vec)54de579d12Sflorian host_dns(const char *s, struct addr *vec)
55de579d12Sflorian {
56de579d12Sflorian 	struct addrinfo		 hints, *res0, *res;
57de579d12Sflorian 	int			 error;
58de579d12Sflorian 	ssize_t			 vecsz;
59de579d12Sflorian 	struct sockaddr		*sa;
60de579d12Sflorian 
61de579d12Sflorian 	memset(&hints, 0, sizeof(hints));
62de579d12Sflorian 	hints.ai_family = PF_UNSPEC;
63de579d12Sflorian 	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
64e93086b0Sflorian 	hints.ai_flags = AI_ADDRCONFIG;
65de579d12Sflorian 
66de579d12Sflorian 	error = getaddrinfo(s, NULL, &hints, &res0);
67de579d12Sflorian 
68de579d12Sflorian 	if (error == EAI_AGAIN ||
69de579d12Sflorian 		/* FIXME */
70de579d12Sflorian #ifndef __FreeBSD__
71de579d12Sflorian 	    error == EAI_NODATA ||
72de579d12Sflorian #endif
73de579d12Sflorian 	    error == EAI_NONAME)
7434335c11Sjsing 		return 0;
75de579d12Sflorian 
76de579d12Sflorian 	if (error) {
77de579d12Sflorian 		warnx("%s: parse error: %s",
78de579d12Sflorian 		    s, gai_strerror(error));
7934335c11Sjsing 		return -1;
80de579d12Sflorian 	}
81de579d12Sflorian 
82de579d12Sflorian 	for (vecsz = 0, res = res0;
837cd8f039Sjsing 	    res != NULL && vecsz < MAX_SERVERS_DNS;
84de579d12Sflorian 	    res = res->ai_next) {
85de579d12Sflorian 		if (res->ai_family != AF_INET &&
86de579d12Sflorian 		    res->ai_family != AF_INET6)
87de579d12Sflorian 			continue;
88de579d12Sflorian 
89de579d12Sflorian 		sa = res->ai_addr;
90de579d12Sflorian 
917cd8f039Sjsing 		if (res->ai_family == AF_INET) {
92de579d12Sflorian 			vec[vecsz].family = 4;
93de579d12Sflorian 			inet_ntop(AF_INET,
94de579d12Sflorian 			    &(((struct sockaddr_in *)sa)->sin_addr),
95de579d12Sflorian 				vec[vecsz].ip, INET6_ADDRSTRLEN);
96de579d12Sflorian 		} else {
97de579d12Sflorian 			vec[vecsz].family = 6;
98de579d12Sflorian 			inet_ntop(AF_INET6,
99de579d12Sflorian 			    &(((struct sockaddr_in6 *)sa)->sin6_addr),
100de579d12Sflorian 			    vec[vecsz].ip, INET6_ADDRSTRLEN);
101de579d12Sflorian 		}
102de579d12Sflorian 
103de579d12Sflorian 		dodbg("%s: DNS: %s", s, vec[vecsz].ip);
104de579d12Sflorian 		vecsz++;
105de579d12Sflorian 	}
106de579d12Sflorian 
107de579d12Sflorian 	freeaddrinfo(res0);
10834335c11Sjsing 	return vecsz;
109de579d12Sflorian }
110de579d12Sflorian 
111de579d12Sflorian int
dnsproc(int nfd)112de579d12Sflorian dnsproc(int nfd)
113de579d12Sflorian {
1147bce6888Sderaadt 	char		*look = NULL, *last = NULL;
115de579d12Sflorian 	struct addr	 v[MAX_SERVERS_DNS];
1167bce6888Sderaadt 	int		 rc = 0, cc;
117de579d12Sflorian 	long		 lval;
1187bce6888Sderaadt 	ssize_t		 vsz = 0;
119de579d12Sflorian 	size_t		 i;
120de579d12Sflorian 	enum dnsop	 op;
121de579d12Sflorian 
122ec0d8c8bSderaadt 	if (pledge("stdio dns", NULL) == -1) {
123ec0d8c8bSderaadt 		warn("pledge");
124de579d12Sflorian 		goto out;
125ec0d8c8bSderaadt 	}
126de579d12Sflorian 
127de579d12Sflorian 	/*
128de579d12Sflorian 	 * This is simple: just loop on a request operation, and each
129de579d12Sflorian 	 * time we write back zero or more entries.
130de579d12Sflorian 	 * Also do a simple trick and cache the last lookup.
131de579d12Sflorian 	 */
132de579d12Sflorian 
133de579d12Sflorian 	for (;;) {
134de579d12Sflorian 		op = DNS__MAX;
1357cd8f039Sjsing 		if ((lval = readop(nfd, COMM_DNS)) == 0)
136de579d12Sflorian 			op = DNS_STOP;
1377cd8f039Sjsing 		else if (lval == DNS_LOOKUP)
138de579d12Sflorian 			op = lval;
139de579d12Sflorian 
1404de82fa3Sderaadt 		if (op == DNS__MAX) {
141de579d12Sflorian 			warnx("unknown operation from netproc");
142de579d12Sflorian 			goto out;
1434de82fa3Sderaadt 		} else if (op == DNS_STOP)
144de579d12Sflorian 			break;
145de579d12Sflorian 
1467cd8f039Sjsing 		if ((look = readstr(nfd, COMM_DNSQ)) == NULL)
147de579d12Sflorian 			goto out;
148de579d12Sflorian 
149de579d12Sflorian 		/*
150de579d12Sflorian 		 * Check if we're asked to repeat the lookup.
151de579d12Sflorian 		 * If not, request it from host_dns().
152de579d12Sflorian 		 */
153de579d12Sflorian 
1547cd8f039Sjsing 		if (last == NULL || strcmp(look, last)) {
155de579d12Sflorian 			if ((vsz = host_dns(look, v)) < 0)
156de579d12Sflorian 				goto out;
157de579d12Sflorian 
158de579d12Sflorian 			free(last);
159de579d12Sflorian 			last = look;
160de579d12Sflorian 			look = NULL;
161de579d12Sflorian 		} else {
162de579d12Sflorian 			free(look);
163de579d12Sflorian 			look = NULL;
164de579d12Sflorian 		}
165de579d12Sflorian 
1667cd8f039Sjsing 		if ((cc = writeop(nfd, COMM_DNSLEN, vsz)) == 0)
167de579d12Sflorian 			break;
168de579d12Sflorian 		else if (cc < 0)
169de579d12Sflorian 			goto out;
170de579d12Sflorian 		for (i = 0; i < (size_t)vsz; i++) {
171de579d12Sflorian 			if (writeop(nfd, COMM_DNSF, v[i].family) <= 0)
172de579d12Sflorian 				goto out;
173de579d12Sflorian 			if (writestr(nfd, COMM_DNSA, v[i].ip) <= 0)
174de579d12Sflorian 				goto out;
175de579d12Sflorian 		}
176de579d12Sflorian 	}
177de579d12Sflorian 
178de579d12Sflorian 	rc = 1;
179de579d12Sflorian out:
180de579d12Sflorian 	close(nfd);
181de579d12Sflorian 	free(look);
182de579d12Sflorian 	free(last);
18334335c11Sjsing 	return rc;
184de579d12Sflorian }
185