Blame


1 56324ebe 2022-07-14 thomas /*
2 56324ebe 2022-07-14 thomas * Copyright (c) 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 56324ebe 2022-07-14 thomas * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
4 56324ebe 2022-07-14 thomas *
5 56324ebe 2022-07-14 thomas * Permission to use, copy, modify, and distribute this software for any
6 56324ebe 2022-07-14 thomas * purpose with or without fee is hereby granted, provided that the above
7 56324ebe 2022-07-14 thomas * copyright notice and this permission notice appear in all copies.
8 56324ebe 2022-07-14 thomas *
9 56324ebe 2022-07-14 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 56324ebe 2022-07-14 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 56324ebe 2022-07-14 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 56324ebe 2022-07-14 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 56324ebe 2022-07-14 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 56324ebe 2022-07-14 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 56324ebe 2022-07-14 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 56324ebe 2022-07-14 thomas */
17 56324ebe 2022-07-14 thomas
18 56324ebe 2022-07-14 thomas #include <sys/types.h>
19 56324ebe 2022-07-14 thomas #include <sys/time.h>
20 56324ebe 2022-07-14 thomas #include <sys/uio.h>
21 56324ebe 2022-07-14 thomas #include <sys/socket.h>
22 56324ebe 2022-07-14 thomas
23 56324ebe 2022-07-14 thomas #include <net/if.h>
24 56324ebe 2022-07-14 thomas #include <netinet/in.h>
25 56324ebe 2022-07-14 thomas
26 56324ebe 2022-07-14 thomas #include <stdio.h>
27 56324ebe 2022-07-14 thomas #include <stdlib.h>
28 56324ebe 2022-07-14 thomas #include <termios.h>
29 56324ebe 2022-07-14 thomas #include <unistd.h>
30 56324ebe 2022-07-14 thomas #include <limits.h>
31 56324ebe 2022-07-14 thomas #include <string.h>
32 56324ebe 2022-07-14 thomas #include <event.h>
33 56324ebe 2022-07-14 thomas #include <fcntl.h>
34 56324ebe 2022-07-14 thomas #include <errno.h>
35 56324ebe 2022-07-14 thomas
36 56324ebe 2022-07-14 thomas #include "got_opentemp.h"
37 56324ebe 2022-07-14 thomas
38 d7cad54e 2022-07-14 thomas #include "got_compat.h"
39 d7cad54e 2022-07-14 thomas
40 56324ebe 2022-07-14 thomas #include "proc.h"
41 56324ebe 2022-07-14 thomas #include "gotwebd.h"
42 56324ebe 2022-07-14 thomas
43 56324ebe 2022-07-14 thomas int
44 56324ebe 2022-07-14 thomas config_init(struct gotwebd *env)
45 56324ebe 2022-07-14 thomas {
46 56324ebe 2022-07-14 thomas struct privsep *ps = env->gotwebd_ps;
47 56324ebe 2022-07-14 thomas unsigned int what;
48 56324ebe 2022-07-14 thomas
49 56324ebe 2022-07-14 thomas /* Global configuration. */
50 56324ebe 2022-07-14 thomas if (privsep_process == PROC_GOTWEBD)
51 56324ebe 2022-07-14 thomas env->prefork_gotwebd = GOTWEBD_NUMPROC;
52 56324ebe 2022-07-14 thomas
53 56324ebe 2022-07-14 thomas ps->ps_what[PROC_GOTWEBD] = CONFIG_ALL;
54 56324ebe 2022-07-14 thomas ps->ps_what[PROC_SOCKS] = CONFIG_SOCKS;
55 56324ebe 2022-07-14 thomas
56 56324ebe 2022-07-14 thomas /* Other configuration. */
57 56324ebe 2022-07-14 thomas what = ps->ps_what[privsep_process];
58 56324ebe 2022-07-14 thomas if (what & CONFIG_SOCKS) {
59 56324ebe 2022-07-14 thomas env->server_cnt = 0;
60 56324ebe 2022-07-14 thomas env->servers = calloc(1, sizeof(*env->servers));
61 56324ebe 2022-07-14 thomas if (env->servers == NULL)
62 56324ebe 2022-07-14 thomas fatalx("%s: calloc", __func__);
63 56324ebe 2022-07-14 thomas env->sockets = calloc(1, sizeof(*env->sockets));
64 56324ebe 2022-07-14 thomas if (env->sockets == NULL)
65 56324ebe 2022-07-14 thomas fatalx("%s: calloc", __func__);
66 56324ebe 2022-07-14 thomas TAILQ_INIT(env->servers);
67 56324ebe 2022-07-14 thomas TAILQ_INIT(env->sockets);
68 56324ebe 2022-07-14 thomas }
69 56324ebe 2022-07-14 thomas return 0;
70 56324ebe 2022-07-14 thomas }
71 56324ebe 2022-07-14 thomas
72 56324ebe 2022-07-14 thomas int
73 56324ebe 2022-07-14 thomas config_getcfg(struct gotwebd *env, struct imsg *imsg)
74 56324ebe 2022-07-14 thomas {
75 56324ebe 2022-07-14 thomas /* nothing to do but tell gotwebd configuration is done */
76 56324ebe 2022-07-14 thomas if (privsep_process != PROC_GOTWEBD)
77 56324ebe 2022-07-14 thomas proc_compose(env->gotwebd_ps, PROC_GOTWEBD,
78 56324ebe 2022-07-14 thomas IMSG_CFG_DONE, NULL, 0);
79 56324ebe 2022-07-14 thomas
80 56324ebe 2022-07-14 thomas return 0;
81 56324ebe 2022-07-14 thomas }
82 56324ebe 2022-07-14 thomas
83 56324ebe 2022-07-14 thomas int
84 56324ebe 2022-07-14 thomas config_setserver(struct gotwebd *env, struct server *srv)
85 56324ebe 2022-07-14 thomas {
86 56324ebe 2022-07-14 thomas struct server ssrv;
87 56324ebe 2022-07-14 thomas struct privsep *ps = env->gotwebd_ps;
88 56324ebe 2022-07-14 thomas
89 56324ebe 2022-07-14 thomas memcpy(&ssrv, srv, sizeof(ssrv));
90 56324ebe 2022-07-14 thomas proc_compose(ps, PROC_SOCKS, IMSG_CFG_SRV, &ssrv, sizeof(ssrv));
91 56324ebe 2022-07-14 thomas return 0;
92 56324ebe 2022-07-14 thomas }
93 56324ebe 2022-07-14 thomas
94 56324ebe 2022-07-14 thomas int
95 56324ebe 2022-07-14 thomas config_getserver(struct gotwebd *env, struct imsg *imsg)
96 56324ebe 2022-07-14 thomas {
97 56324ebe 2022-07-14 thomas struct server *srv;
98 56324ebe 2022-07-14 thomas uint8_t *p = imsg->data;
99 56324ebe 2022-07-14 thomas
100 56324ebe 2022-07-14 thomas IMSG_SIZE_CHECK(imsg, &srv);
101 56324ebe 2022-07-14 thomas
102 56324ebe 2022-07-14 thomas srv = calloc(1, sizeof(*srv));
103 56324ebe 2022-07-14 thomas if (srv == NULL)
104 56324ebe 2022-07-14 thomas fatalx("%s: calloc", __func__);
105 56324ebe 2022-07-14 thomas memcpy(srv, p, sizeof(*srv));
106 56324ebe 2022-07-14 thomas
107 56324ebe 2022-07-14 thomas if (IMSG_DATA_SIZE(imsg) != sizeof(*srv)) {
108 56324ebe 2022-07-14 thomas log_debug("%s: imsg size error", __func__);
109 56324ebe 2022-07-14 thomas free(srv);
110 56324ebe 2022-07-14 thomas return 1;
111 56324ebe 2022-07-14 thomas }
112 56324ebe 2022-07-14 thomas
113 56324ebe 2022-07-14 thomas /* log server info */
114 56324ebe 2022-07-14 thomas log_debug("%s: server=%s fcgi_socket=%s unix_socket=%s", __func__,
115 56324ebe 2022-07-14 thomas srv->name, srv->fcgi_socket ? "yes" : "no", srv->unix_socket ?
116 56324ebe 2022-07-14 thomas "yes" : "no");
117 56324ebe 2022-07-14 thomas
118 56324ebe 2022-07-14 thomas TAILQ_INSERT_TAIL(env->servers, srv, entry);
119 56324ebe 2022-07-14 thomas
120 56324ebe 2022-07-14 thomas return 0;
121 56324ebe 2022-07-14 thomas }
122 56324ebe 2022-07-14 thomas
123 56324ebe 2022-07-14 thomas int
124 56324ebe 2022-07-14 thomas config_setsock(struct gotwebd *env, struct socket *sock)
125 56324ebe 2022-07-14 thomas {
126 56324ebe 2022-07-14 thomas struct privsep *ps = env->gotwebd_ps;
127 56324ebe 2022-07-14 thomas struct socket_conf s;
128 56324ebe 2022-07-14 thomas int id;
129 56324ebe 2022-07-14 thomas int fd = -1, n, m;
130 56324ebe 2022-07-14 thomas struct iovec iov[6];
131 56324ebe 2022-07-14 thomas size_t c;
132 56324ebe 2022-07-14 thomas unsigned int what;
133 56324ebe 2022-07-14 thomas
134 56324ebe 2022-07-14 thomas /* open listening sockets */
135 56324ebe 2022-07-14 thomas if (sockets_privinit(env, sock) == -1)
136 56324ebe 2022-07-14 thomas return -1;
137 56324ebe 2022-07-14 thomas
138 56324ebe 2022-07-14 thomas for (id = 0; id < PROC_MAX; id++) {
139 56324ebe 2022-07-14 thomas what = ps->ps_what[id];
140 56324ebe 2022-07-14 thomas
141 56324ebe 2022-07-14 thomas if ((what & CONFIG_SOCKS) == 0 || id == privsep_process)
142 56324ebe 2022-07-14 thomas continue;
143 56324ebe 2022-07-14 thomas
144 56324ebe 2022-07-14 thomas memcpy(&s, &sock->conf, sizeof(s));
145 56324ebe 2022-07-14 thomas
146 56324ebe 2022-07-14 thomas c = 0;
147 56324ebe 2022-07-14 thomas iov[c].iov_base = &s;
148 56324ebe 2022-07-14 thomas iov[c++].iov_len = sizeof(s);
149 56324ebe 2022-07-14 thomas
150 56324ebe 2022-07-14 thomas if (id == PROC_SOCKS) {
151 56324ebe 2022-07-14 thomas /* XXX imsg code will close the fd after 1st call */
152 56324ebe 2022-07-14 thomas n = -1;
153 56324ebe 2022-07-14 thomas proc_range(ps, id, &n, &m);
154 56324ebe 2022-07-14 thomas for (n = 0; n < m; n++) {
155 56324ebe 2022-07-14 thomas if (sock->fd == -1)
156 56324ebe 2022-07-14 thomas fd = -1;
157 56324ebe 2022-07-14 thomas else if ((fd = dup(sock->fd)) == -1)
158 56324ebe 2022-07-14 thomas return 1;
159 56324ebe 2022-07-14 thomas if (proc_composev_imsg(ps, id, n, IMSG_CFG_SOCK,
160 56324ebe 2022-07-14 thomas -1, fd, iov, c) != 0) {
161 56324ebe 2022-07-14 thomas log_warn("%s: failed to compose "
162 56324ebe 2022-07-14 thomas "IMSG_CFG_SOCK imsg",
163 56324ebe 2022-07-14 thomas __func__);
164 56324ebe 2022-07-14 thomas return 1;
165 56324ebe 2022-07-14 thomas }
166 56324ebe 2022-07-14 thomas if (proc_flush_imsg(ps, id, n) == -1) {
167 56324ebe 2022-07-14 thomas log_warn("%s: failed to flush "
168 56324ebe 2022-07-14 thomas "IMSG_CFG_SOCK imsg",
169 56324ebe 2022-07-14 thomas __func__);
170 56324ebe 2022-07-14 thomas return 1;
171 56324ebe 2022-07-14 thomas }
172 56324ebe 2022-07-14 thomas }
173 56324ebe 2022-07-14 thomas }
174 56324ebe 2022-07-14 thomas }
175 56324ebe 2022-07-14 thomas
176 56324ebe 2022-07-14 thomas /* Close socket early to prevent fd exhaustion in gotwebd. */
177 56324ebe 2022-07-14 thomas if (sock->fd != -1) {
178 56324ebe 2022-07-14 thomas close(sock->fd);
179 56324ebe 2022-07-14 thomas sock->fd = -1;
180 56324ebe 2022-07-14 thomas }
181 56324ebe 2022-07-14 thomas
182 56324ebe 2022-07-14 thomas return 0;
183 56324ebe 2022-07-14 thomas }
184 56324ebe 2022-07-14 thomas
185 56324ebe 2022-07-14 thomas int
186 56324ebe 2022-07-14 thomas config_getsock(struct gotwebd *env, struct imsg *imsg)
187 56324ebe 2022-07-14 thomas {
188 56324ebe 2022-07-14 thomas struct socket *sock = NULL;
189 56324ebe 2022-07-14 thomas struct socket_conf sock_conf;
190 56324ebe 2022-07-14 thomas uint8_t *p = imsg->data;
191 56324ebe 2022-07-14 thomas int i;
192 56324ebe 2022-07-14 thomas
193 56324ebe 2022-07-14 thomas IMSG_SIZE_CHECK(imsg, &sock_conf);
194 56324ebe 2022-07-14 thomas memcpy(&sock_conf, p, sizeof(sock_conf));
195 56324ebe 2022-07-14 thomas
196 56324ebe 2022-07-14 thomas if (IMSG_DATA_SIZE(imsg) != sizeof(sock_conf)) {
197 56324ebe 2022-07-14 thomas log_debug("%s: imsg size error", __func__);
198 56324ebe 2022-07-14 thomas return 1;
199 56324ebe 2022-07-14 thomas }
200 56324ebe 2022-07-14 thomas
201 56324ebe 2022-07-14 thomas /* create a new socket */
202 56324ebe 2022-07-14 thomas if ((sock = calloc(1, sizeof(*sock))) == NULL) {
203 56324ebe 2022-07-14 thomas if (imsg->fd != -1)
204 56324ebe 2022-07-14 thomas close(imsg->fd);
205 56324ebe 2022-07-14 thomas return 1;
206 56324ebe 2022-07-14 thomas }
207 56324ebe 2022-07-14 thomas
208 56324ebe 2022-07-14 thomas memcpy(&sock->conf, &sock_conf, sizeof(sock->conf));
209 56324ebe 2022-07-14 thomas sock->fd = imsg->fd;
210 56324ebe 2022-07-14 thomas
211 56324ebe 2022-07-14 thomas TAILQ_INSERT_TAIL(env->sockets, sock, entry);
212 56324ebe 2022-07-14 thomas
213 56324ebe 2022-07-14 thomas for (i = 0; i < PRIV_FDS__MAX; i++)
214 56324ebe 2022-07-14 thomas sock->priv_fd[i] = -1;
215 56324ebe 2022-07-14 thomas
216 56324ebe 2022-07-14 thomas for (i = 0; i < GOT_PACK_NUM_TEMPFILES; i++)
217 56324ebe 2022-07-14 thomas sock->pack_fds[i] = -1;
218 56324ebe 2022-07-14 thomas
219 56324ebe 2022-07-14 thomas /* log new socket info */
220 56324ebe 2022-07-14 thomas log_debug("%s: name=%s id=%d server=%s child_id=%d parent_id=%d "
221 56324ebe 2022-07-14 thomas "type=%s ipv4=%d ipv6=%d socket_path=%s",
222 56324ebe 2022-07-14 thomas __func__, sock->conf.name, sock->conf.id, sock->conf.srv_name,
223 56324ebe 2022-07-14 thomas sock->conf.child_id, sock->conf.parent_id, sock->conf.type ?
224 56324ebe 2022-07-14 thomas "fcgi" : "unix", sock->conf.ipv4, sock->conf.ipv6,
225 56324ebe 2022-07-14 thomas strlen(sock->conf.unix_socket_name) ?
226 56324ebe 2022-07-14 thomas sock->conf.unix_socket_name : "none");
227 56324ebe 2022-07-14 thomas
228 56324ebe 2022-07-14 thomas return 0;
229 56324ebe 2022-07-14 thomas }
230 56324ebe 2022-07-14 thomas
231 56324ebe 2022-07-14 thomas int
232 56324ebe 2022-07-14 thomas config_setfd(struct gotwebd *env, struct socket *sock)
233 56324ebe 2022-07-14 thomas {
234 56324ebe 2022-07-14 thomas struct privsep *ps = env->gotwebd_ps;
235 56324ebe 2022-07-14 thomas int id, s;
236 56324ebe 2022-07-14 thomas int fd = -1, n, m, j;
237 56324ebe 2022-07-14 thomas struct iovec iov[6];
238 56324ebe 2022-07-14 thomas size_t c;
239 56324ebe 2022-07-14 thomas unsigned int what;
240 56324ebe 2022-07-14 thomas
241 56324ebe 2022-07-14 thomas log_debug("%s: Allocating %d file descriptors",
242 56324ebe 2022-07-14 thomas __func__, PRIV_FDS__MAX + GOT_PACK_NUM_TEMPFILES);
243 56324ebe 2022-07-14 thomas
244 56324ebe 2022-07-14 thomas for (j = 0; j < PRIV_FDS__MAX + GOT_PACK_NUM_TEMPFILES; j++) {
245 56324ebe 2022-07-14 thomas for (id = 0; id < PROC_MAX; id++) {
246 56324ebe 2022-07-14 thomas what = ps->ps_what[id];
247 56324ebe 2022-07-14 thomas
248 56324ebe 2022-07-14 thomas if ((what & CONFIG_SOCKS) == 0 || id == privsep_process)
249 56324ebe 2022-07-14 thomas continue;
250 56324ebe 2022-07-14 thomas
251 56324ebe 2022-07-14 thomas s = sock->conf.id;
252 56324ebe 2022-07-14 thomas c = 0;
253 56324ebe 2022-07-14 thomas iov[c].iov_base = &s;
254 56324ebe 2022-07-14 thomas iov[c++].iov_len = sizeof(s);
255 56324ebe 2022-07-14 thomas
256 56324ebe 2022-07-14 thomas if (id == PROC_SOCKS) {
257 56324ebe 2022-07-14 thomas /*
258 56324ebe 2022-07-14 thomas * XXX imsg code will close the fd
259 56324ebe 2022-07-14 thomas * after 1st call
260 56324ebe 2022-07-14 thomas */
261 56324ebe 2022-07-14 thomas n = -1;
262 56324ebe 2022-07-14 thomas proc_range(ps, id, &n, &m);
263 56324ebe 2022-07-14 thomas for (n = 0; n < m; n++) {
264 56324ebe 2022-07-14 thomas fd = got_opentempfd();
265 56324ebe 2022-07-14 thomas if (fd == -1)
266 56324ebe 2022-07-14 thomas return 1;
267 56324ebe 2022-07-14 thomas if (proc_composev_imsg(ps, id, n,
268 56324ebe 2022-07-14 thomas IMSG_CFG_FD, -1, fd, iov, c) != 0) {
269 56324ebe 2022-07-14 thomas log_warn("%s: failed to compose "
270 56324ebe 2022-07-14 thomas "IMSG_CFG_FD imsg",
271 56324ebe 2022-07-14 thomas __func__);
272 56324ebe 2022-07-14 thomas return 1;
273 56324ebe 2022-07-14 thomas }
274 56324ebe 2022-07-14 thomas if (proc_flush_imsg(ps, id, n) == -1) {
275 56324ebe 2022-07-14 thomas log_warn("%s: failed to flush "
276 56324ebe 2022-07-14 thomas "IMSG_CFG_FD imsg",
277 56324ebe 2022-07-14 thomas __func__);
278 56324ebe 2022-07-14 thomas return 1;
279 56324ebe 2022-07-14 thomas }
280 56324ebe 2022-07-14 thomas }
281 56324ebe 2022-07-14 thomas }
282 56324ebe 2022-07-14 thomas }
283 56324ebe 2022-07-14 thomas
284 56324ebe 2022-07-14 thomas /* Close fd early to prevent fd exhaustion in gotwebd. */
285 56324ebe 2022-07-14 thomas if (fd != -1)
286 56324ebe 2022-07-14 thomas close(fd);
287 56324ebe 2022-07-14 thomas }
288 56324ebe 2022-07-14 thomas return 0;
289 56324ebe 2022-07-14 thomas }
290 56324ebe 2022-07-14 thomas
291 56324ebe 2022-07-14 thomas int
292 56324ebe 2022-07-14 thomas config_getfd(struct gotwebd *env, struct imsg *imsg)
293 56324ebe 2022-07-14 thomas {
294 56324ebe 2022-07-14 thomas struct socket *sock;
295 56324ebe 2022-07-14 thomas uint8_t *p = imsg->data;
296 56324ebe 2022-07-14 thomas int sock_id, match = 0, i;
297 56324ebe 2022-07-14 thomas
298 56324ebe 2022-07-14 thomas IMSG_SIZE_CHECK(imsg, &sock_id);
299 56324ebe 2022-07-14 thomas memcpy(&sock_id, p, sizeof(sock_id));
300 56324ebe 2022-07-14 thomas
301 56324ebe 2022-07-14 thomas TAILQ_FOREACH(sock, env->sockets, entry) {
302 56324ebe 2022-07-14 thomas for (i = 0; i < (GOT_PACK_NUM_TEMPFILES + PRIV_FDS__MAX); i++) {
303 56324ebe 2022-07-14 thomas if (i < PRIV_FDS__MAX && sock->priv_fd[i] == -1) {
304 56324ebe 2022-07-14 thomas log_debug("%s: assigning socket %d priv_fd %d",
305 56324ebe 2022-07-14 thomas __func__, sock_id, imsg->fd);
306 56324ebe 2022-07-14 thomas sock->priv_fd[i] = imsg->fd;
307 56324ebe 2022-07-14 thomas match = 1;
308 56324ebe 2022-07-14 thomas break;
309 56324ebe 2022-07-14 thomas }
310 56324ebe 2022-07-14 thomas if (sock->pack_fds[i - PRIV_FDS__MAX] == -1) {
311 56324ebe 2022-07-14 thomas log_debug("%s: assigning socket %d pack_fd %d",
312 56324ebe 2022-07-14 thomas __func__, sock_id, imsg->fd);
313 56324ebe 2022-07-14 thomas sock->pack_fds[i - PRIV_FDS__MAX] = imsg->fd;
314 56324ebe 2022-07-14 thomas match = 1;
315 56324ebe 2022-07-14 thomas break;
316 56324ebe 2022-07-14 thomas }
317 56324ebe 2022-07-14 thomas }
318 56324ebe 2022-07-14 thomas }
319 56324ebe 2022-07-14 thomas
320 56324ebe 2022-07-14 thomas if (match)
321 56324ebe 2022-07-14 thomas return 0;
322 56324ebe 2022-07-14 thomas else
323 56324ebe 2022-07-14 thomas return 1;
324 56324ebe 2022-07-14 thomas }