Blame


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