Blob


1 /*
2 * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
3 * Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <sys/tree.h>
23 #include <sys/time.h>
24 #include <sys/uio.h>
26 #include <sys/stat.h> /* umask */
27 #include <sys/un.h> /* sockaddr_un */
29 #include <errno.h>
30 #include <event.h>
31 #include <limits.h>
32 #include <pwd.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <imsg.h>
39 #include "proc.h"
40 #include "log.h"
41 #include "xmalloc.h"
43 #include "galileo.h"
45 int
46 config_init(struct galileo *env)
47 {
48 /* Global configuration */
49 if (privsep_process == PROC_PARENT)
50 env->sc_prefork = PROXY_NUMPROC;
52 /* Other configuration. */
53 TAILQ_INIT(&env->sc_proxies);
55 env->sc_sock_fd = -1;
57 return (0);
58 }
60 void
61 config_purge(struct galileo *env)
62 {
63 struct proxy *p;
64 struct fcgi *fcgi;
65 struct client *clt;
67 while ((fcgi = SPLAY_MIN(fcgi_tree, &env->sc_fcgi_socks))) {
68 while ((clt = SPLAY_MIN(client_tree, &fcgi->fcg_clients))) {
69 if (fcgi_abort_request(clt) == -1) {
70 fcgi = NULL;
71 break;
72 }
73 }
75 if (fcgi == NULL)
76 continue;
78 SPLAY_REMOVE(fcgi_tree, &env->sc_fcgi_socks, fcgi);
79 fcgi_free(fcgi);
80 }
82 if (env->sc_sock_fd != -1) {
83 event_del(&env->sc_evsock);
84 event_del(&env->sc_evpause);
85 close(env->sc_sock_fd);
86 env->sc_sock_fd = -1;
87 }
89 while ((p = TAILQ_FIRST(&env->sc_proxies)) != NULL) {
90 TAILQ_REMOVE(&env->sc_proxies, p, pr_entry);
91 proxy_purge(p);
92 }
93 }
95 int
96 config_setproxy(struct galileo *env, struct proxy *p)
97 {
98 struct privsep *ps = env->sc_ps;
100 if (proc_compose(ps, PROC_PROXY, IMSG_CFG_SRV, p, sizeof(*p)) == -1)
101 fatal("proc_compose");
102 return (0);
105 int
106 config_getproxy(struct galileo *env, struct imsg *imsg)
108 struct proxy *proxy;
110 proxy = xcalloc(1, sizeof(*proxy));
111 if (IMSG_DATA_SIZE(imsg) != sizeof(*proxy))
112 fatalx("%s: bad imsg size", __func__);
114 memcpy(proxy, imsg->data, sizeof(*proxy));
116 log_debug("%s: proxy=%s -> %s:%s (%s)", __func__,
117 proxy->pr_conf.host, proxy->pr_conf.proxy_addr,
118 proxy->pr_conf.proxy_port, proxy->pr_conf.proxy_name);
120 TAILQ_INSERT_TAIL(&env->sc_proxies, proxy, pr_entry);
122 return (0);
125 int
126 config_setsock(struct galileo *env)
128 struct privsep *ps = env->sc_ps;
129 struct passwd *pw = ps->ps_pw;
130 struct sockaddr_un sun;
131 const char *path = GALILEO_SOCK;
132 int id, fd, old_umask;
134 /*
135 * open listening socket.
137 * XXX: move to server.c as server_privinit like httpd once we
138 * support more than one listening socket.
139 */
140 if ((fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) {
141 log_warn("%s: socket", __func__);
142 return (-1);
145 memset(&sun, 0, sizeof(sun));
146 sun.sun_family = AF_UNIX;
147 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
149 if (unlink(path) == -1)
150 if (errno != ENOENT) {
151 log_warn("%s: unlink %s", __func__, path);
152 close(fd);
153 return (-1);
156 old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
157 if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
158 log_warn("%s: bind: %s (%d)", __func__, path, geteuid());
159 close(fd);
160 umask(old_umask);
161 return (-1);
163 umask(old_umask);
165 if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
166 log_warn("%s: chmod", __func__);
167 close(fd);
168 (void)unlink(path);
169 return (-1);
172 if (chown(path, pw->pw_uid, pw->pw_gid) == -1) {
173 log_warn("%s: chown", __func__);
174 close(fd);
175 (void)unlink(path);
176 return (-1);
179 if (listen(fd, 5) == -1) {
180 log_warn("%s: listen", __func__);
181 close(fd);
182 (void)unlink(path);
183 return (-1);
186 for (id = 0; id < PROC_MAX; ++id) {
187 int n, m;
189 if (id == privsep_process || id != PROC_PROXY)
190 continue;
192 n = -1;
193 proc_range(ps, id, &n, &m);
194 for (n = 0; n < m; ++n) {
195 int d;
197 if ((d = dup(fd)) == -1) {
198 log_warn("%s: dup", __func__);
199 close(fd);
200 return (-1);
203 if (proc_compose_imsg(ps, id, n, IMSG_CFG_SOCK,
204 -1, d, NULL, 0) == -1) {
205 log_warn("%s: failed to compose "
206 "IMSG_CFG_SOCK", __func__);
207 close(fd);
208 return (-1);
210 if (proc_flush_imsg(ps, id, n) == -1) {
211 log_warn("%s: failed to flush", __func__);
212 close(fd);
213 return (-1);
218 close(fd);
219 return (0);
222 int
223 config_getsock(struct galileo *env, struct imsg *imsg)
225 /* XXX: make it more like httpd/gotwebd' one */
226 return (imsg->fd);
229 int
230 config_setreset(struct galileo *env)
232 struct privsep *ps = env->sc_ps;
233 int id;
235 for (id = 0; id < PROC_MAX; ++id)
236 if (id != PROC_PARENT)
237 proc_compose(ps, id, IMSG_CTL_RESET, NULL, 0);
239 return (0);
242 int
243 config_getreset(struct galileo *env, struct imsg *imsg)
245 config_purge(env);
247 return (0);
250 int
251 config_getcfg(struct galileo *env, struct imsg *imsg)
253 if (privsep_process != PROC_PARENT)
254 proc_compose(env->sc_ps, PROC_PARENT,
255 IMSG_CFG_DONE, NULL, 0);
257 return (0);