Blame


1 8a35f56c 2022-07-16 thomas /*
2 8a35f56c 2022-07-16 thomas * Copyright (c) 2016, 2019, 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 8a35f56c 2022-07-16 thomas * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
4 8a35f56c 2022-07-16 thomas *
5 8a35f56c 2022-07-16 thomas * Permission to use, copy, modify, and distribute this software for any
6 8a35f56c 2022-07-16 thomas * purpose with or without fee is hereby granted, provided that the above
7 8a35f56c 2022-07-16 thomas * copyright notice and this permission notice appear in all copies.
8 8a35f56c 2022-07-16 thomas *
9 8a35f56c 2022-07-16 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 8a35f56c 2022-07-16 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 8a35f56c 2022-07-16 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 8a35f56c 2022-07-16 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 8a35f56c 2022-07-16 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 8a35f56c 2022-07-16 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 8a35f56c 2022-07-16 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 8a35f56c 2022-07-16 thomas */
17 8a35f56c 2022-07-16 thomas
18 8a35f56c 2022-07-16 thomas #include <sys/param.h>
19 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
20 8a35f56c 2022-07-16 thomas #include <sys/socket.h>
21 8a35f56c 2022-07-16 thomas #include <sys/wait.h>
22 8a35f56c 2022-07-16 thomas
23 8a35f56c 2022-07-16 thomas #include <net/if.h>
24 8a35f56c 2022-07-16 thomas #include <netinet/in.h>
25 8a35f56c 2022-07-16 thomas
26 8a35f56c 2022-07-16 thomas #include <stdio.h>
27 8a35f56c 2022-07-16 thomas #include <stdlib.h>
28 8a35f56c 2022-07-16 thomas #include <string.h>
29 8a35f56c 2022-07-16 thomas #include <termios.h>
30 8a35f56c 2022-07-16 thomas #include <err.h>
31 8a35f56c 2022-07-16 thomas #include <errno.h>
32 8a35f56c 2022-07-16 thomas #include <event.h>
33 8a35f56c 2022-07-16 thomas #include <fcntl.h>
34 8a35f56c 2022-07-16 thomas #include <pwd.h>
35 8a35f56c 2022-07-16 thomas #include <signal.h>
36 8a35f56c 2022-07-16 thomas #include <syslog.h>
37 8a35f56c 2022-07-16 thomas #include <unistd.h>
38 8a35f56c 2022-07-16 thomas #include <ctype.h>
39 8a35f56c 2022-07-16 thomas
40 4fccd2fe 2023-03-08 thomas #include "got_compat.h"
41 8a35f56c 2022-07-16 thomas #include "got_opentemp.h"
42 161663e7 2023-03-11 thomas #include "got_reference.h"
43 8a35f56c 2022-07-16 thomas
44 8a35f56c 2022-07-16 thomas #include "gotwebd.h"
45 8a35f56c 2022-07-16 thomas
46 8a35f56c 2022-07-16 thomas __dead void usage(void);
47 8a35f56c 2022-07-16 thomas
48 8a35f56c 2022-07-16 thomas int main(int, char **);
49 8a35f56c 2022-07-16 thomas int gotwebd_configure(struct gotwebd *);
50 8a35f56c 2022-07-16 thomas void gotwebd_configure_done(struct gotwebd *);
51 8a35f56c 2022-07-16 thomas void gotwebd_sighdlr(int sig, short event, void *arg);
52 8a35f56c 2022-07-16 thomas void gotwebd_shutdown(void);
53 f85c939f 2023-11-22 thomas void gotwebd_dispatch_sockets(int, short, void *);
54 8a35f56c 2022-07-16 thomas
55 8a35f56c 2022-07-16 thomas struct gotwebd *gotwebd_env;
56 8a35f56c 2022-07-16 thomas
57 f85c939f 2023-11-22 thomas void
58 f85c939f 2023-11-22 thomas imsg_event_add(struct imsgev *iev)
59 f85c939f 2023-11-22 thomas {
60 f85c939f 2023-11-22 thomas if (iev->handler == NULL) {
61 f85c939f 2023-11-22 thomas imsg_flush(&iev->ibuf);
62 f85c939f 2023-11-22 thomas return;
63 f85c939f 2023-11-22 thomas }
64 8a35f56c 2022-07-16 thomas
65 f85c939f 2023-11-22 thomas iev->events = EV_READ;
66 f85c939f 2023-11-22 thomas if (iev->ibuf.w.queued)
67 f85c939f 2023-11-22 thomas iev->events |= EV_WRITE;
68 f85c939f 2023-11-22 thomas
69 f85c939f 2023-11-22 thomas event_del(&iev->ev);
70 f85c939f 2023-11-22 thomas event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
71 f85c939f 2023-11-22 thomas event_add(&iev->ev, NULL);
72 f85c939f 2023-11-22 thomas }
73 f85c939f 2023-11-22 thomas
74 8a35f56c 2022-07-16 thomas int
75 f85c939f 2023-11-22 thomas imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
76 f85c939f 2023-11-22 thomas pid_t pid, int fd, const void *data, uint16_t datalen)
77 8a35f56c 2022-07-16 thomas {
78 f85c939f 2023-11-22 thomas int ret;
79 8a35f56c 2022-07-16 thomas
80 f85c939f 2023-11-22 thomas ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, datalen);
81 f85c939f 2023-11-22 thomas if (ret == -1)
82 f85c939f 2023-11-22 thomas return (ret);
83 f85c939f 2023-11-22 thomas imsg_event_add(iev);
84 f85c939f 2023-11-22 thomas return (ret);
85 f85c939f 2023-11-22 thomas }
86 f85c939f 2023-11-22 thomas
87 f85c939f 2023-11-22 thomas int
88 f85c939f 2023-11-22 thomas main_compose_sockets(struct gotwebd *env, uint32_t type, int fd,
89 f85c939f 2023-11-22 thomas const void *data, uint16_t len)
90 f85c939f 2023-11-22 thomas {
91 f85c939f 2023-11-22 thomas size_t i;
92 f85c939f 2023-11-22 thomas int ret, d;
93 f85c939f 2023-11-22 thomas
94 f85c939f 2023-11-22 thomas for (i = 0; i < env->nserver; ++i) {
95 f85c939f 2023-11-22 thomas d = -1;
96 f85c939f 2023-11-22 thomas if (fd != -1 && (d = dup(fd)) == -1)
97 3bb657ab 2023-11-22 thomas goto err;
98 f85c939f 2023-11-22 thomas
99 f85c939f 2023-11-22 thomas ret = imsg_compose_event(&env->iev_server[i], type, 0, -1,
100 f85c939f 2023-11-22 thomas d, data, len);
101 f85c939f 2023-11-22 thomas if (ret == -1)
102 3bb657ab 2023-11-22 thomas goto err;
103 f85c939f 2023-11-22 thomas
104 f85c939f 2023-11-22 thomas /* prevent fd exhaustion */
105 f85c939f 2023-11-22 thomas if (d != -1) {
106 f85c939f 2023-11-22 thomas do {
107 f85c939f 2023-11-22 thomas ret = imsg_flush(&env->iev_server[i].ibuf);
108 f85c939f 2023-11-22 thomas } while (ret == -1 && errno == EAGAIN);
109 f85c939f 2023-11-22 thomas if (ret == -1)
110 3bb657ab 2023-11-22 thomas goto err;
111 f85c939f 2023-11-22 thomas imsg_event_add(&env->iev_server[i]);
112 f85c939f 2023-11-22 thomas }
113 8a35f56c 2022-07-16 thomas }
114 8a35f56c 2022-07-16 thomas
115 f85c939f 2023-11-22 thomas if (fd != -1)
116 f85c939f 2023-11-22 thomas close(fd);
117 f85c939f 2023-11-22 thomas return 0;
118 3bb657ab 2023-11-22 thomas
119 3bb657ab 2023-11-22 thomas err:
120 3bb657ab 2023-11-22 thomas if (fd != -1)
121 3bb657ab 2023-11-22 thomas close(fd);
122 3bb657ab 2023-11-22 thomas return -1;
123 8a35f56c 2022-07-16 thomas }
124 8a35f56c 2022-07-16 thomas
125 f85c939f 2023-11-22 thomas int
126 f85c939f 2023-11-22 thomas sockets_compose_main(struct gotwebd *env, uint32_t type, const void *d,
127 f85c939f 2023-11-22 thomas uint16_t len)
128 f85c939f 2023-11-22 thomas {
129 f85c939f 2023-11-22 thomas return (imsg_compose_event(env->iev_parent, type, 0, -1, -1, d, len));
130 f85c939f 2023-11-22 thomas }
131 f85c939f 2023-11-22 thomas
132 8a35f56c 2022-07-16 thomas void
133 f85c939f 2023-11-22 thomas gotwebd_dispatch_sockets(int fd, short event, void *arg)
134 f85c939f 2023-11-22 thomas {
135 f85c939f 2023-11-22 thomas struct imsgev *iev = arg;
136 f85c939f 2023-11-22 thomas struct imsgbuf *ibuf;
137 f85c939f 2023-11-22 thomas struct imsg imsg;
138 f85c939f 2023-11-22 thomas struct gotwebd *env = gotwebd_env;
139 f85c939f 2023-11-22 thomas ssize_t n;
140 f85c939f 2023-11-22 thomas int shut = 0;
141 f85c939f 2023-11-22 thomas
142 f85c939f 2023-11-22 thomas ibuf = &iev->ibuf;
143 f85c939f 2023-11-22 thomas
144 f85c939f 2023-11-22 thomas if (event & EV_READ) {
145 f85c939f 2023-11-22 thomas if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
146 f85c939f 2023-11-22 thomas fatal("imsg_read error");
147 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
148 f85c939f 2023-11-22 thomas shut = 1;
149 f85c939f 2023-11-22 thomas }
150 f85c939f 2023-11-22 thomas if (event & EV_WRITE) {
151 f85c939f 2023-11-22 thomas if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
152 f85c939f 2023-11-22 thomas fatal("msgbuf_write");
153 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
154 f85c939f 2023-11-22 thomas shut = 1;
155 f85c939f 2023-11-22 thomas }
156 f85c939f 2023-11-22 thomas
157 f85c939f 2023-11-22 thomas for (;;) {
158 f85c939f 2023-11-22 thomas if ((n = imsg_get(ibuf, &imsg)) == -1)
159 f85c939f 2023-11-22 thomas fatal("imsg_get");
160 f85c939f 2023-11-22 thomas if (n == 0) /* No more messages. */
161 f85c939f 2023-11-22 thomas break;
162 f85c939f 2023-11-22 thomas
163 f85c939f 2023-11-22 thomas switch (imsg.hdr.type) {
164 f85c939f 2023-11-22 thomas case IMSG_CFG_DONE:
165 f85c939f 2023-11-22 thomas gotwebd_configure_done(env);
166 f85c939f 2023-11-22 thomas break;
167 f85c939f 2023-11-22 thomas default:
168 f85c939f 2023-11-22 thomas fatalx("%s: unknown imsg type %d", __func__,
169 f85c939f 2023-11-22 thomas imsg.hdr.type);
170 f85c939f 2023-11-22 thomas }
171 f85c939f 2023-11-22 thomas
172 f85c939f 2023-11-22 thomas imsg_free(&imsg);
173 f85c939f 2023-11-22 thomas }
174 f85c939f 2023-11-22 thomas
175 f85c939f 2023-11-22 thomas if (!shut)
176 f85c939f 2023-11-22 thomas imsg_event_add(iev);
177 f85c939f 2023-11-22 thomas else {
178 f85c939f 2023-11-22 thomas /* This pipe is dead. Remove its event handler */
179 f85c939f 2023-11-22 thomas event_del(&iev->ev);
180 f85c939f 2023-11-22 thomas event_loopexit(NULL);
181 f85c939f 2023-11-22 thomas }
182 f85c939f 2023-11-22 thomas }
183 f85c939f 2023-11-22 thomas
184 f85c939f 2023-11-22 thomas void
185 8a35f56c 2022-07-16 thomas gotwebd_sighdlr(int sig, short event, void *arg)
186 8a35f56c 2022-07-16 thomas {
187 8a35f56c 2022-07-16 thomas /* struct privsep *ps = arg; */
188 8a35f56c 2022-07-16 thomas
189 8a35f56c 2022-07-16 thomas switch (sig) {
190 8a35f56c 2022-07-16 thomas case SIGHUP:
191 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGHUP", __func__);
192 8a35f56c 2022-07-16 thomas break;
193 8a35f56c 2022-07-16 thomas case SIGPIPE:
194 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGPIPE", __func__);
195 8a35f56c 2022-07-16 thomas break;
196 8a35f56c 2022-07-16 thomas case SIGUSR1:
197 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGUSR1", __func__);
198 8a35f56c 2022-07-16 thomas break;
199 8a35f56c 2022-07-16 thomas case SIGTERM:
200 8a35f56c 2022-07-16 thomas case SIGINT:
201 8a35f56c 2022-07-16 thomas gotwebd_shutdown();
202 8a35f56c 2022-07-16 thomas break;
203 8a35f56c 2022-07-16 thomas default:
204 8a35f56c 2022-07-16 thomas fatalx("unexpected signal");
205 8a35f56c 2022-07-16 thomas }
206 8a35f56c 2022-07-16 thomas }
207 8a35f56c 2022-07-16 thomas
208 f85c939f 2023-11-22 thomas static int
209 f85c939f 2023-11-22 thomas spawn_socket_process(struct gotwebd *env, const char *argv0, int n)
210 f85c939f 2023-11-22 thomas {
211 f85c939f 2023-11-22 thomas const char *argv[5];
212 f85c939f 2023-11-22 thomas int argc = 0;
213 f85c939f 2023-11-22 thomas int p[2];
214 f85c939f 2023-11-22 thomas pid_t pid;
215 f85c939f 2023-11-22 thomas
216 f85c939f 2023-11-22 thomas if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) == -1)
217 f85c939f 2023-11-22 thomas fatal("socketpair");
218 f85c939f 2023-11-22 thomas
219 f85c939f 2023-11-22 thomas switch (pid = fork()) {
220 f85c939f 2023-11-22 thomas case -1:
221 f85c939f 2023-11-22 thomas fatal("fork");
222 f85c939f 2023-11-22 thomas case 0: /* child */
223 f85c939f 2023-11-22 thomas break;
224 f85c939f 2023-11-22 thomas default: /* parent */
225 f85c939f 2023-11-22 thomas close(p[0]);
226 f85c939f 2023-11-22 thomas imsg_init(&env->iev_server[n].ibuf, p[1]);
227 f85c939f 2023-11-22 thomas env->iev_server[n].handler = gotwebd_dispatch_sockets;
228 f85c939f 2023-11-22 thomas env->iev_server[n].data = &env->iev_server[n];
229 f85c939f 2023-11-22 thomas event_set(&env->iev_server[n].ev, p[1], EV_READ,
230 f85c939f 2023-11-22 thomas gotwebd_dispatch_sockets, &env->iev_server[n]);
231 f85c939f 2023-11-22 thomas event_add(&env->iev_server[n].ev, NULL);
232 f85c939f 2023-11-22 thomas return 0;
233 f85c939f 2023-11-22 thomas }
234 f85c939f 2023-11-22 thomas
235 f85c939f 2023-11-22 thomas close(p[1]);
236 f85c939f 2023-11-22 thomas
237 f85c939f 2023-11-22 thomas argv[argc++] = argv0;
238 f85c939f 2023-11-22 thomas argv[argc++] = "-S";
239 f85c939f 2023-11-22 thomas if (env->gotwebd_debug)
240 f85c939f 2023-11-22 thomas argv[argc++] = "-d";
241 f85c939f 2023-11-22 thomas if (env->gotwebd_verbose)
242 f85c939f 2023-11-22 thomas argv[argc++] = "-v";
243 f85c939f 2023-11-22 thomas argv[argc] = NULL;
244 f85c939f 2023-11-22 thomas
245 f1e20d01 2023-11-22 thomas if (p[0] != GOTWEBD_SOCK_FILENO) {
246 f1e20d01 2023-11-22 thomas if (dup2(p[0], GOTWEBD_SOCK_FILENO) == -1)
247 f85c939f 2023-11-22 thomas fatal("dup2");
248 f85c939f 2023-11-22 thomas } else if (fcntl(p[0], F_SETFD, 0) == -1)
249 f85c939f 2023-11-22 thomas fatal("fcntl");
250 f85c939f 2023-11-22 thomas
251 f85c939f 2023-11-22 thomas /* obnoxious cast */
252 f85c939f 2023-11-22 thomas execvp(argv0, (char * const *)argv);
253 f85c939f 2023-11-22 thomas fatal("execvp %s", argv0);
254 f85c939f 2023-11-22 thomas }
255 f85c939f 2023-11-22 thomas
256 8a35f56c 2022-07-16 thomas __dead void
257 8a35f56c 2022-07-16 thomas usage(void)
258 8a35f56c 2022-07-16 thomas {
259 8a35f56c 2022-07-16 thomas fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
260 8a35f56c 2022-07-16 thomas getprogname());
261 8a35f56c 2022-07-16 thomas exit(1);
262 8a35f56c 2022-07-16 thomas }
263 8a35f56c 2022-07-16 thomas
264 8a35f56c 2022-07-16 thomas int
265 8a35f56c 2022-07-16 thomas main(int argc, char **argv)
266 8a35f56c 2022-07-16 thomas {
267 f85c939f 2023-11-22 thomas struct event sigint, sigterm, sighup, sigpipe, sigusr1;
268 f85c939f 2023-11-22 thomas struct gotwebd *env;
269 f85c939f 2023-11-22 thomas struct passwd *pw;
270 f85c939f 2023-11-22 thomas int ch, i;
271 f85c939f 2023-11-22 thomas int no_action = 0;
272 f85c939f 2023-11-22 thomas int server_proc = 0;
273 f85c939f 2023-11-22 thomas const char *conffile = GOTWEBD_CONF;
274 f85c939f 2023-11-22 thomas const char *argv0;
275 8a35f56c 2022-07-16 thomas
276 f85c939f 2023-11-22 thomas if ((argv0 = argv[0]) == NULL)
277 f85c939f 2023-11-22 thomas argv0 = "gotwebd";
278 aada9b03 2023-11-22 thomas
279 aada9b03 2023-11-22 thomas /* log to stderr until daemonized */
280 aada9b03 2023-11-22 thomas log_init(1, LOG_DAEMON);
281 f85c939f 2023-11-22 thomas
282 8a35f56c 2022-07-16 thomas env = calloc(1, sizeof(*env));
283 8a35f56c 2022-07-16 thomas if (env == NULL)
284 8a35f56c 2022-07-16 thomas fatal("%s: calloc", __func__);
285 f85c939f 2023-11-22 thomas config_init(env);
286 b9c7eb91 2023-11-16 thomas
287 f85c939f 2023-11-22 thomas while ((ch = getopt(argc, argv, "D:df:nSv")) != -1) {
288 8a35f56c 2022-07-16 thomas switch (ch) {
289 8a35f56c 2022-07-16 thomas case 'D':
290 8a35f56c 2022-07-16 thomas if (cmdline_symset(optarg) < 0)
291 8a35f56c 2022-07-16 thomas log_warnx("could not parse macro definition %s",
292 8a35f56c 2022-07-16 thomas optarg);
293 8a35f56c 2022-07-16 thomas break;
294 8a35f56c 2022-07-16 thomas case 'd':
295 f85c939f 2023-11-22 thomas env->gotwebd_debug = 1;
296 8a35f56c 2022-07-16 thomas break;
297 8a35f56c 2022-07-16 thomas case 'f':
298 8a35f56c 2022-07-16 thomas conffile = optarg;
299 8a35f56c 2022-07-16 thomas break;
300 8a35f56c 2022-07-16 thomas case 'n':
301 f85c939f 2023-11-22 thomas no_action = 1;
302 8a35f56c 2022-07-16 thomas break;
303 f85c939f 2023-11-22 thomas case 'S':
304 f85c939f 2023-11-22 thomas server_proc = 1;
305 8a35f56c 2022-07-16 thomas break;
306 f7065961 2022-10-27 thomas case 'v':
307 f7065961 2022-10-27 thomas env->gotwebd_verbose++;
308 8a35f56c 2022-07-16 thomas break;
309 8a35f56c 2022-07-16 thomas default:
310 8a35f56c 2022-07-16 thomas usage();
311 8a35f56c 2022-07-16 thomas }
312 8a35f56c 2022-07-16 thomas }
313 8a35f56c 2022-07-16 thomas
314 8a35f56c 2022-07-16 thomas argc -= optind;
315 8a35f56c 2022-07-16 thomas if (argc > 0)
316 8a35f56c 2022-07-16 thomas usage();
317 8a35f56c 2022-07-16 thomas
318 8a35f56c 2022-07-16 thomas gotwebd_env = env;
319 8a35f56c 2022-07-16 thomas env->gotwebd_conffile = conffile;
320 8a35f56c 2022-07-16 thomas
321 8a35f56c 2022-07-16 thomas if (parse_config(env->gotwebd_conffile, env) == -1)
322 8a35f56c 2022-07-16 thomas exit(1);
323 8a35f56c 2022-07-16 thomas
324 f85c939f 2023-11-22 thomas if (no_action) {
325 f85c939f 2023-11-22 thomas fprintf(stderr, "configuration OK\n");
326 f85c939f 2023-11-22 thomas exit(0);
327 f85c939f 2023-11-22 thomas }
328 8a35f56c 2022-07-16 thomas
329 8a35f56c 2022-07-16 thomas /* check for root privileges */
330 f85c939f 2023-11-22 thomas if (geteuid())
331 f85c939f 2023-11-22 thomas fatalx("need root privileges");
332 8a35f56c 2022-07-16 thomas
333 f85c939f 2023-11-22 thomas pw = getpwnam(GOTWEBD_USER);
334 f85c939f 2023-11-22 thomas if (pw == NULL)
335 8a35f56c 2022-07-16 thomas fatalx("unknown user %s", GOTWEBD_USER);
336 f85c939f 2023-11-22 thomas env->pw = pw;
337 8a35f56c 2022-07-16 thomas
338 8a35f56c 2022-07-16 thomas log_init(env->gotwebd_debug, LOG_DAEMON);
339 8a35f56c 2022-07-16 thomas log_setverbose(env->gotwebd_verbose);
340 8a35f56c 2022-07-16 thomas
341 f85c939f 2023-11-22 thomas if (server_proc) {
342 f85c939f 2023-11-22 thomas setproctitle("sockets");
343 f85c939f 2023-11-22 thomas log_procinit("sockets");
344 8a35f56c 2022-07-16 thomas
345 f85c939f 2023-11-22 thomas if (chroot(pw->pw_dir) == -1)
346 f85c939f 2023-11-22 thomas fatal("chroot %s", pw->pw_dir);
347 f85c939f 2023-11-22 thomas if (chdir("/") == -1)
348 f85c939f 2023-11-22 thomas fatal("chdir /");
349 f85c939f 2023-11-22 thomas if (setgroups(1, &pw->pw_gid) == -1 ||
350 f85c939f 2023-11-22 thomas setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
351 f85c939f 2023-11-22 thomas setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
352 f85c939f 2023-11-22 thomas fatal("failed to drop privileges");
353 8a35f56c 2022-07-16 thomas
354 f1e20d01 2023-11-22 thomas sockets(env, GOTWEBD_SOCK_FILENO);
355 f85c939f 2023-11-22 thomas return 1;
356 f85c939f 2023-11-22 thomas }
357 8a35f56c 2022-07-16 thomas
358 1962c340 2023-11-22 thomas if (!env->gotwebd_debug && daemon(1, 0) == -1)
359 f85c939f 2023-11-22 thomas fatal("daemon");
360 8a35f56c 2022-07-16 thomas
361 8a35f56c 2022-07-16 thomas event_init();
362 8a35f56c 2022-07-16 thomas
363 f85c939f 2023-11-22 thomas env->nserver = env->prefork_gotwebd;
364 f85c939f 2023-11-22 thomas env->iev_server = calloc(env->nserver, sizeof(*env->iev_server));
365 f85c939f 2023-11-22 thomas if (env->iev_server == NULL)
366 f85c939f 2023-11-22 thomas fatal("calloc");
367 8a35f56c 2022-07-16 thomas
368 f85c939f 2023-11-22 thomas for (i = 0; i < env->nserver; ++i) {
369 f85c939f 2023-11-22 thomas if (spawn_socket_process(env, argv0, i) == -1)
370 f85c939f 2023-11-22 thomas fatal("spawn_socket_process");
371 f85c939f 2023-11-22 thomas }
372 8a35f56c 2022-07-16 thomas
373 1962c340 2023-11-22 thomas if (chdir("/") == -1)
374 1962c340 2023-11-22 thomas fatal("chdir /");
375 1962c340 2023-11-22 thomas
376 f85c939f 2023-11-22 thomas log_procinit("gotwebd");
377 8a35f56c 2022-07-16 thomas
378 f85c939f 2023-11-22 thomas log_info("%s startup", getprogname());
379 f85c939f 2023-11-22 thomas
380 f85c939f 2023-11-22 thomas signal_set(&sigint, SIGINT, gotwebd_sighdlr, env);
381 f85c939f 2023-11-22 thomas signal_set(&sigterm, SIGTERM, gotwebd_sighdlr, env);
382 f85c939f 2023-11-22 thomas signal_set(&sighup, SIGHUP, gotwebd_sighdlr, env);
383 f85c939f 2023-11-22 thomas signal_set(&sigpipe, SIGPIPE, gotwebd_sighdlr, env);
384 f85c939f 2023-11-22 thomas signal_set(&sigusr1, SIGUSR1, gotwebd_sighdlr, env);
385 f85c939f 2023-11-22 thomas
386 f85c939f 2023-11-22 thomas signal_add(&sigint, NULL);
387 f85c939f 2023-11-22 thomas signal_add(&sigterm, NULL);
388 f85c939f 2023-11-22 thomas signal_add(&sighup, NULL);
389 f85c939f 2023-11-22 thomas signal_add(&sigpipe, NULL);
390 f85c939f 2023-11-22 thomas signal_add(&sigusr1, NULL);
391 f85c939f 2023-11-22 thomas
392 8a35f56c 2022-07-16 thomas if (gotwebd_configure(env) == -1)
393 8a35f56c 2022-07-16 thomas fatalx("configuration failed");
394 8a35f56c 2022-07-16 thomas
395 8a35f56c 2022-07-16 thomas #ifdef PROFILE
396 8a35f56c 2022-07-16 thomas if (unveil("gmon.out", "rwc") != 0)
397 8a35f56c 2022-07-16 thomas err(1, "gmon.out");
398 8a35f56c 2022-07-16 thomas #endif
399 8a35f56c 2022-07-16 thomas
400 79e60db6 2023-11-14 thomas if (unveil(env->httpd_chroot, "r") == -1)
401 8a35f56c 2022-07-16 thomas err(1, "unveil");
402 8a35f56c 2022-07-16 thomas
403 8a35f56c 2022-07-16 thomas if (unveil(GOTWEBD_CONF, "r") == -1)
404 8a35f56c 2022-07-16 thomas err(1, "unveil");
405 8a35f56c 2022-07-16 thomas
406 8a35f56c 2022-07-16 thomas if (unveil(NULL, NULL) != 0)
407 8a35f56c 2022-07-16 thomas err(1, "unveil");
408 8a35f56c 2022-07-16 thomas
409 8a35f56c 2022-07-16 thomas #ifndef PROFILE
410 9cfaa638 2023-11-14 thomas if (pledge("stdio", NULL) == -1)
411 8a35f56c 2022-07-16 thomas err(1, "pledge");
412 8a35f56c 2022-07-16 thomas #endif
413 8a35f56c 2022-07-16 thomas
414 8a35f56c 2022-07-16 thomas event_dispatch();
415 8a35f56c 2022-07-16 thomas
416 8a35f56c 2022-07-16 thomas log_debug("%s gotwebd exiting", getprogname());
417 8a35f56c 2022-07-16 thomas
418 8a35f56c 2022-07-16 thomas return (0);
419 8a35f56c 2022-07-16 thomas }
420 8a35f56c 2022-07-16 thomas
421 8a35f56c 2022-07-16 thomas int
422 8a35f56c 2022-07-16 thomas gotwebd_configure(struct gotwebd *env)
423 8a35f56c 2022-07-16 thomas {
424 8a35f56c 2022-07-16 thomas struct server *srv;
425 8a35f56c 2022-07-16 thomas struct socket *sock;
426 8a35f56c 2022-07-16 thomas
427 8a35f56c 2022-07-16 thomas /* gotweb need to reload its config. */
428 8a35f56c 2022-07-16 thomas env->gotwebd_reload = env->prefork_gotwebd;
429 8a35f56c 2022-07-16 thomas
430 8a35f56c 2022-07-16 thomas /* send our gotweb servers */
431 90d63d47 2022-08-16 thomas TAILQ_FOREACH(srv, &env->servers, entry) {
432 8a35f56c 2022-07-16 thomas if (config_setserver(env, srv) == -1)
433 8a35f56c 2022-07-16 thomas fatalx("%s: send server error", __func__);
434 8a35f56c 2022-07-16 thomas }
435 8a35f56c 2022-07-16 thomas
436 8a35f56c 2022-07-16 thomas /* send our sockets */
437 90d63d47 2022-08-16 thomas TAILQ_FOREACH(sock, &env->sockets, entry) {
438 8a35f56c 2022-07-16 thomas if (config_setsock(env, sock) == -1)
439 8a35f56c 2022-07-16 thomas fatalx("%s: send socket error", __func__);
440 8a35f56c 2022-07-16 thomas if (config_setfd(env, sock) == -1)
441 8a35f56c 2022-07-16 thomas fatalx("%s: send priv_fd error", __func__);
442 8a35f56c 2022-07-16 thomas }
443 8a35f56c 2022-07-16 thomas
444 f85c939f 2023-11-22 thomas if (main_compose_sockets(env, IMSG_CFG_DONE, -1, NULL, 0) == -1)
445 f85c939f 2023-11-22 thomas fatal("main_compose_sockets IMSG_CFG_DONE");
446 8a35f56c 2022-07-16 thomas
447 8a35f56c 2022-07-16 thomas return (0);
448 8a35f56c 2022-07-16 thomas }
449 8a35f56c 2022-07-16 thomas
450 8a35f56c 2022-07-16 thomas void
451 8a35f56c 2022-07-16 thomas gotwebd_configure_done(struct gotwebd *env)
452 8a35f56c 2022-07-16 thomas {
453 8a35f56c 2022-07-16 thomas if (env->gotwebd_reload == 0) {
454 8a35f56c 2022-07-16 thomas log_warnx("%s: configuration already finished", __func__);
455 8a35f56c 2022-07-16 thomas return;
456 8a35f56c 2022-07-16 thomas }
457 8a35f56c 2022-07-16 thomas
458 8a35f56c 2022-07-16 thomas env->gotwebd_reload--;
459 f85c939f 2023-11-22 thomas if (env->gotwebd_reload == 0 &&
460 f85c939f 2023-11-22 thomas main_compose_sockets(env, IMSG_CTL_START, -1, NULL, 0) == -1)
461 f85c939f 2023-11-22 thomas fatal("main_compose_sockets IMSG_CTL_START");
462 8a35f56c 2022-07-16 thomas }
463 8a35f56c 2022-07-16 thomas
464 8a35f56c 2022-07-16 thomas void
465 8a35f56c 2022-07-16 thomas gotwebd_shutdown(void)
466 8a35f56c 2022-07-16 thomas {
467 f85c939f 2023-11-22 thomas struct gotwebd *env = gotwebd_env;
468 f85c939f 2023-11-22 thomas pid_t pid;
469 f85c939f 2023-11-22 thomas int i, status;
470 8a35f56c 2022-07-16 thomas
471 f85c939f 2023-11-22 thomas for (i = 0; i < env->nserver; ++i) {
472 f85c939f 2023-11-22 thomas event_del(&env->iev_server[i].ev);
473 f85c939f 2023-11-22 thomas imsg_clear(&env->iev_server[i].ibuf);
474 f85c939f 2023-11-22 thomas close(env->iev_server[i].ibuf.fd);
475 f85c939f 2023-11-22 thomas env->iev_server[i].ibuf.fd = -1;
476 f85c939f 2023-11-22 thomas }
477 f85c939f 2023-11-22 thomas
478 f85c939f 2023-11-22 thomas do {
479 f85c939f 2023-11-22 thomas pid = waitpid(WAIT_ANY, &status, 0);
480 f85c939f 2023-11-22 thomas if (pid <= 0)
481 f85c939f 2023-11-22 thomas continue;
482 f85c939f 2023-11-22 thomas
483 f85c939f 2023-11-22 thomas if (WIFSIGNALED(status))
484 f85c939f 2023-11-22 thomas log_warnx("lost child: pid %u terminated; signal %d",
485 f85c939f 2023-11-22 thomas pid, WTERMSIG(status));
486 f85c939f 2023-11-22 thomas else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
487 f85c939f 2023-11-22 thomas log_warnx("lost child: pid %u exited abnormally",
488 f85c939f 2023-11-22 thomas pid);
489 f85c939f 2023-11-22 thomas } while (pid != -1 || (pid == -1 && errno == EINTR));
490 f85c939f 2023-11-22 thomas
491 8a35f56c 2022-07-16 thomas free(gotwebd_env);
492 8a35f56c 2022-07-16 thomas
493 8a35f56c 2022-07-16 thomas log_warnx("gotwebd terminating");
494 8a35f56c 2022-07-16 thomas exit(0);
495 8a35f56c 2022-07-16 thomas }