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