Blame


1 a596b957 2022-07-14 tracey /*
2 a596b957 2022-07-14 tracey * Copyright (c) 2016, 2019, 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/param.h>
19 a596b957 2022-07-14 tracey #include <sys/queue.h>
20 a596b957 2022-07-14 tracey #include <sys/socket.h>
21 a596b957 2022-07-14 tracey #include <sys/wait.h>
22 a596b957 2022-07-14 tracey #include <sys/cdefs.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 <string.h>
30 a596b957 2022-07-14 tracey #include <termios.h>
31 a596b957 2022-07-14 tracey #include <err.h>
32 a596b957 2022-07-14 tracey #include <errno.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 <imsg.h>
36 a596b957 2022-07-14 tracey #include <pwd.h>
37 a596b957 2022-07-14 tracey #include <signal.h>
38 a596b957 2022-07-14 tracey #include <syslog.h>
39 a596b957 2022-07-14 tracey #include <unistd.h>
40 a596b957 2022-07-14 tracey #include <ctype.h>
41 a596b957 2022-07-14 tracey #include <util.h>
42 a596b957 2022-07-14 tracey
43 a596b957 2022-07-14 tracey #include "got_opentemp.h"
44 df2d3cd2 2023-03-11 op #include "got_reference.h"
45 a596b957 2022-07-14 tracey
46 a596b957 2022-07-14 tracey #include "proc.h"
47 a596b957 2022-07-14 tracey #include "gotwebd.h"
48 a596b957 2022-07-14 tracey
49 a596b957 2022-07-14 tracey __dead void usage(void);
50 a596b957 2022-07-14 tracey
51 a596b957 2022-07-14 tracey int main(int, char **);
52 a596b957 2022-07-14 tracey int gotwebd_configure(struct gotwebd *);
53 a596b957 2022-07-14 tracey void gotwebd_configure_done(struct gotwebd *);
54 a596b957 2022-07-14 tracey void gotwebd_sighdlr(int sig, short event, void *arg);
55 a596b957 2022-07-14 tracey void gotwebd_shutdown(void);
56 a596b957 2022-07-14 tracey int gotwebd_dispatch_sockets(int, struct privsep_proc *, struct imsg *);
57 a596b957 2022-07-14 tracey
58 a596b957 2022-07-14 tracey struct gotwebd *gotwebd_env;
59 a596b957 2022-07-14 tracey
60 a596b957 2022-07-14 tracey static struct privsep_proc procs[] = {
61 a596b957 2022-07-14 tracey { "sockets", PROC_SOCKS, gotwebd_dispatch_sockets, sockets,
62 a596b957 2022-07-14 tracey sockets_shutdown },
63 a596b957 2022-07-14 tracey };
64 a596b957 2022-07-14 tracey
65 a596b957 2022-07-14 tracey int
66 a596b957 2022-07-14 tracey gotwebd_dispatch_sockets(int fd, struct privsep_proc *p, struct imsg *imsg)
67 a596b957 2022-07-14 tracey {
68 a596b957 2022-07-14 tracey struct privsep *ps = p->p_ps;
69 a596b957 2022-07-14 tracey struct gotwebd *env = ps->ps_env;
70 a596b957 2022-07-14 tracey
71 a596b957 2022-07-14 tracey switch (imsg->hdr.type) {
72 a596b957 2022-07-14 tracey case IMSG_CFG_DONE:
73 a596b957 2022-07-14 tracey gotwebd_configure_done(env);
74 a596b957 2022-07-14 tracey break;
75 a596b957 2022-07-14 tracey default:
76 a596b957 2022-07-14 tracey return (-1);
77 a596b957 2022-07-14 tracey }
78 a596b957 2022-07-14 tracey
79 a596b957 2022-07-14 tracey return (0);
80 a596b957 2022-07-14 tracey }
81 a596b957 2022-07-14 tracey
82 a596b957 2022-07-14 tracey void
83 a596b957 2022-07-14 tracey gotwebd_sighdlr(int sig, short event, void *arg)
84 a596b957 2022-07-14 tracey {
85 a596b957 2022-07-14 tracey /* struct privsep *ps = arg; */
86 a596b957 2022-07-14 tracey
87 a596b957 2022-07-14 tracey if (privsep_process != PROC_GOTWEBD)
88 a596b957 2022-07-14 tracey return;
89 a596b957 2022-07-14 tracey
90 a596b957 2022-07-14 tracey switch (sig) {
91 a596b957 2022-07-14 tracey case SIGHUP:
92 a596b957 2022-07-14 tracey log_info("%s: ignoring SIGHUP", __func__);
93 a596b957 2022-07-14 tracey break;
94 a596b957 2022-07-14 tracey case SIGPIPE:
95 a596b957 2022-07-14 tracey log_info("%s: ignoring SIGPIPE", __func__);
96 a596b957 2022-07-14 tracey break;
97 a596b957 2022-07-14 tracey case SIGUSR1:
98 a596b957 2022-07-14 tracey log_info("%s: ignoring SIGUSR1", __func__);
99 a596b957 2022-07-14 tracey break;
100 a596b957 2022-07-14 tracey case SIGTERM:
101 a596b957 2022-07-14 tracey case SIGINT:
102 a596b957 2022-07-14 tracey gotwebd_shutdown();
103 a596b957 2022-07-14 tracey break;
104 a596b957 2022-07-14 tracey default:
105 a596b957 2022-07-14 tracey fatalx("unexpected signal");
106 a596b957 2022-07-14 tracey }
107 a596b957 2022-07-14 tracey }
108 a596b957 2022-07-14 tracey
109 a596b957 2022-07-14 tracey __dead void
110 a596b957 2022-07-14 tracey usage(void)
111 a596b957 2022-07-14 tracey {
112 a596b957 2022-07-14 tracey fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
113 a596b957 2022-07-14 tracey getprogname());
114 a596b957 2022-07-14 tracey exit(1);
115 a596b957 2022-07-14 tracey }
116 a596b957 2022-07-14 tracey
117 a596b957 2022-07-14 tracey int
118 a596b957 2022-07-14 tracey main(int argc, char **argv)
119 a596b957 2022-07-14 tracey {
120 a596b957 2022-07-14 tracey struct gotwebd *env;
121 a596b957 2022-07-14 tracey struct privsep *ps;
122 a596b957 2022-07-14 tracey unsigned int proc;
123 a596b957 2022-07-14 tracey int ch;
124 a596b957 2022-07-14 tracey const char *conffile = GOTWEBD_CONF;
125 a596b957 2022-07-14 tracey enum privsep_procid proc_id = PROC_GOTWEBD;
126 a596b957 2022-07-14 tracey int proc_instance = 0;
127 a596b957 2022-07-14 tracey const char *errp, *title = NULL;
128 a596b957 2022-07-14 tracey int argc0 = argc;
129 a596b957 2022-07-14 tracey
130 a596b957 2022-07-14 tracey env = calloc(1, sizeof(*env));
131 a596b957 2022-07-14 tracey if (env == NULL)
132 a596b957 2022-07-14 tracey fatal("%s: calloc", __func__);
133 a596b957 2022-07-14 tracey
134 a596b957 2022-07-14 tracey /* XXX: add s and S for both sockets */
135 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "D:df:I:nP:v")) != -1) {
136 a596b957 2022-07-14 tracey switch (ch) {
137 a596b957 2022-07-14 tracey case 'D':
138 a596b957 2022-07-14 tracey if (cmdline_symset(optarg) < 0)
139 a596b957 2022-07-14 tracey log_warnx("could not parse macro definition %s",
140 a596b957 2022-07-14 tracey optarg);
141 a596b957 2022-07-14 tracey break;
142 a596b957 2022-07-14 tracey case 'd':
143 a596b957 2022-07-14 tracey env->gotwebd_debug = 2;
144 a596b957 2022-07-14 tracey break;
145 a596b957 2022-07-14 tracey case 'f':
146 a596b957 2022-07-14 tracey conffile = optarg;
147 a596b957 2022-07-14 tracey break;
148 6f319063 2022-10-27 stsp case 'I':
149 6f319063 2022-10-27 stsp proc_instance = strtonum(optarg, 0,
150 6f319063 2022-10-27 stsp PROC_MAX_INSTANCES, &errp);
151 6f319063 2022-10-27 stsp if (errp)
152 6f319063 2022-10-27 stsp fatalx("invalid process instance");
153 a596b957 2022-07-14 tracey break;
154 a596b957 2022-07-14 tracey case 'n':
155 a596b957 2022-07-14 tracey env->gotwebd_debug = 2;
156 a596b957 2022-07-14 tracey env->gotwebd_noaction = 1;
157 a596b957 2022-07-14 tracey break;
158 a596b957 2022-07-14 tracey case 'P':
159 a596b957 2022-07-14 tracey title = optarg;
160 a596b957 2022-07-14 tracey proc_id = proc_getid(procs, nitems(procs), title);
161 a596b957 2022-07-14 tracey if (proc_id == PROC_MAX)
162 a596b957 2022-07-14 tracey fatalx("invalid process name");
163 a596b957 2022-07-14 tracey break;
164 6f319063 2022-10-27 stsp case 'v':
165 6f319063 2022-10-27 stsp env->gotwebd_verbose++;
166 a596b957 2022-07-14 tracey break;
167 a596b957 2022-07-14 tracey default:
168 a596b957 2022-07-14 tracey usage();
169 a596b957 2022-07-14 tracey }
170 a596b957 2022-07-14 tracey }
171 a596b957 2022-07-14 tracey
172 a596b957 2022-07-14 tracey /* log to stderr until daemonized */
173 a596b957 2022-07-14 tracey log_init(env->gotwebd_debug ? env->gotwebd_debug : 1, LOG_DAEMON);
174 a596b957 2022-07-14 tracey
175 a596b957 2022-07-14 tracey argc -= optind;
176 a596b957 2022-07-14 tracey if (argc > 0)
177 a596b957 2022-07-14 tracey usage();
178 a596b957 2022-07-14 tracey
179 a596b957 2022-07-14 tracey ps = calloc(1, sizeof(*ps));
180 a596b957 2022-07-14 tracey if (ps == NULL)
181 a596b957 2022-07-14 tracey fatal("%s: calloc:", __func__);
182 a596b957 2022-07-14 tracey
183 a596b957 2022-07-14 tracey gotwebd_env = env;
184 a596b957 2022-07-14 tracey env->gotwebd_ps = ps;
185 a596b957 2022-07-14 tracey ps->ps_env = env;
186 a596b957 2022-07-14 tracey env->gotwebd_conffile = conffile;
187 a596b957 2022-07-14 tracey
188 a596b957 2022-07-14 tracey if (parse_config(env->gotwebd_conffile, env) == -1)
189 a596b957 2022-07-14 tracey exit(1);
190 a596b957 2022-07-14 tracey
191 a596b957 2022-07-14 tracey if (env->gotwebd_noaction && !env->gotwebd_debug)
192 a596b957 2022-07-14 tracey env->gotwebd_debug = 1;
193 a596b957 2022-07-14 tracey
194 a596b957 2022-07-14 tracey /* check for root privileges */
195 a596b957 2022-07-14 tracey if (env->gotwebd_noaction == 0) {
196 a596b957 2022-07-14 tracey if (geteuid())
197 a596b957 2022-07-14 tracey fatalx("need root privileges");
198 a596b957 2022-07-14 tracey }
199 a596b957 2022-07-14 tracey
200 a596b957 2022-07-14 tracey ps->ps_pw = getpwnam(GOTWEBD_USER);
201 a596b957 2022-07-14 tracey if (ps->ps_pw == NULL)
202 a596b957 2022-07-14 tracey fatalx("unknown user %s", GOTWEBD_USER);
203 a596b957 2022-07-14 tracey
204 a596b957 2022-07-14 tracey log_init(env->gotwebd_debug, LOG_DAEMON);
205 a596b957 2022-07-14 tracey log_setverbose(env->gotwebd_verbose);
206 a596b957 2022-07-14 tracey
207 a596b957 2022-07-14 tracey if (env->gotwebd_noaction)
208 a596b957 2022-07-14 tracey ps->ps_noaction = 1;
209 a596b957 2022-07-14 tracey
210 a596b957 2022-07-14 tracey ps->ps_instances[PROC_SOCKS] = env->prefork_gotwebd;
211 a596b957 2022-07-14 tracey ps->ps_instance = proc_instance;
212 a596b957 2022-07-14 tracey if (title != NULL)
213 a596b957 2022-07-14 tracey ps->ps_title[proc_id] = title;
214 a596b957 2022-07-14 tracey
215 a596b957 2022-07-14 tracey for (proc = 0; proc < nitems(procs); proc++)
216 a596b957 2022-07-14 tracey procs[proc].p_chroot = strlen(env->httpd_chroot) ?
217 a596b957 2022-07-14 tracey env->httpd_chroot : D_HTTPD_CHROOT;
218 a596b957 2022-07-14 tracey
219 a596b957 2022-07-14 tracey /* only the gotwebd returns */
220 a596b957 2022-07-14 tracey proc_init(ps, procs, nitems(procs), argc0, argv, proc_id);
221 a596b957 2022-07-14 tracey
222 a596b957 2022-07-14 tracey log_procinit("gotwebd");
223 a596b957 2022-07-14 tracey if (!env->gotwebd_debug && daemon(0, 0) == -1)
224 a596b957 2022-07-14 tracey fatal("can't daemonize");
225 a596b957 2022-07-14 tracey
226 a596b957 2022-07-14 tracey if (ps->ps_noaction == 0)
227 a596b957 2022-07-14 tracey log_info("%s startup", getprogname());
228 a596b957 2022-07-14 tracey
229 a596b957 2022-07-14 tracey event_init();
230 a596b957 2022-07-14 tracey
231 a596b957 2022-07-14 tracey signal_set(&ps->ps_evsigint, SIGINT, gotwebd_sighdlr, ps);
232 a596b957 2022-07-14 tracey signal_set(&ps->ps_evsigterm, SIGTERM, gotwebd_sighdlr, ps);
233 a596b957 2022-07-14 tracey signal_set(&ps->ps_evsighup, SIGHUP, gotwebd_sighdlr, ps);
234 a596b957 2022-07-14 tracey signal_set(&ps->ps_evsigpipe, SIGPIPE, gotwebd_sighdlr, ps);
235 a596b957 2022-07-14 tracey signal_set(&ps->ps_evsigusr1, SIGUSR1, gotwebd_sighdlr, ps);
236 a596b957 2022-07-14 tracey
237 a596b957 2022-07-14 tracey signal_add(&ps->ps_evsigint, NULL);
238 a596b957 2022-07-14 tracey signal_add(&ps->ps_evsigterm, NULL);
239 a596b957 2022-07-14 tracey signal_add(&ps->ps_evsighup, NULL);
240 a596b957 2022-07-14 tracey signal_add(&ps->ps_evsigpipe, NULL);
241 a596b957 2022-07-14 tracey signal_add(&ps->ps_evsigusr1, NULL);
242 a596b957 2022-07-14 tracey
243 a596b957 2022-07-14 tracey if (!env->gotwebd_noaction)
244 a596b957 2022-07-14 tracey proc_connect(ps);
245 a596b957 2022-07-14 tracey
246 a596b957 2022-07-14 tracey if (gotwebd_configure(env) == -1)
247 a596b957 2022-07-14 tracey fatalx("configuration failed");
248 a596b957 2022-07-14 tracey
249 a596b957 2022-07-14 tracey #ifdef PROFILE
250 a596b957 2022-07-14 tracey if (unveil("gmon.out", "rwc") != 0)
251 a596b957 2022-07-14 tracey err(1, "gmon.out");
252 a596b957 2022-07-14 tracey #endif
253 a596b957 2022-07-14 tracey
254 a596b957 2022-07-14 tracey if (unveil(strlen(env->httpd_chroot) > 0 ? env->httpd_chroot :
255 a596b957 2022-07-14 tracey D_HTTPD_CHROOT, "rwc") == -1)
256 a596b957 2022-07-14 tracey err(1, "unveil");
257 a596b957 2022-07-14 tracey
258 a596b957 2022-07-14 tracey if (unveil(GOT_TMPDIR_STR, "rw") == -1)
259 a596b957 2022-07-14 tracey err(1, "unveil");
260 a596b957 2022-07-14 tracey
261 a596b957 2022-07-14 tracey if (unveil(GOTWEBD_CONF, "r") == -1)
262 a596b957 2022-07-14 tracey err(1, "unveil");
263 a596b957 2022-07-14 tracey
264 a596b957 2022-07-14 tracey if (unveil(NULL, NULL) != 0)
265 a596b957 2022-07-14 tracey err(1, "unveil");
266 a596b957 2022-07-14 tracey
267 a596b957 2022-07-14 tracey #ifndef PROFILE
268 a596b957 2022-07-14 tracey if (pledge("stdio rpath wpath cpath inet unix", NULL) == -1)
269 a596b957 2022-07-14 tracey err(1, "pledge");
270 a596b957 2022-07-14 tracey #endif
271 a596b957 2022-07-14 tracey
272 a596b957 2022-07-14 tracey event_dispatch();
273 a596b957 2022-07-14 tracey
274 a596b957 2022-07-14 tracey log_debug("%s gotwebd exiting", getprogname());
275 a596b957 2022-07-14 tracey
276 a596b957 2022-07-14 tracey return (0);
277 a596b957 2022-07-14 tracey }
278 a596b957 2022-07-14 tracey
279 a596b957 2022-07-14 tracey int
280 a596b957 2022-07-14 tracey gotwebd_configure(struct gotwebd *env)
281 a596b957 2022-07-14 tracey {
282 a596b957 2022-07-14 tracey struct server *srv;
283 a596b957 2022-07-14 tracey struct socket *sock;
284 a596b957 2022-07-14 tracey int id;
285 a596b957 2022-07-14 tracey
286 a596b957 2022-07-14 tracey if (env->gotwebd_noaction) {
287 a596b957 2022-07-14 tracey fprintf(stderr, "configuration OK\n");
288 a596b957 2022-07-14 tracey proc_kill(env->gotwebd_ps);
289 a596b957 2022-07-14 tracey exit(0);
290 a596b957 2022-07-14 tracey }
291 a596b957 2022-07-14 tracey
292 a596b957 2022-07-14 tracey /* gotweb need to reload its config. */
293 a596b957 2022-07-14 tracey env->gotwebd_reload = env->prefork_gotwebd;
294 a596b957 2022-07-14 tracey
295 a596b957 2022-07-14 tracey /* send our gotweb servers */
296 2ad48e9a 2022-08-16 stsp TAILQ_FOREACH(srv, &env->servers, entry) {
297 a596b957 2022-07-14 tracey if (config_setserver(env, srv) == -1)
298 a596b957 2022-07-14 tracey fatalx("%s: send server error", __func__);
299 a596b957 2022-07-14 tracey }
300 a596b957 2022-07-14 tracey
301 a596b957 2022-07-14 tracey /* send our sockets */
302 2ad48e9a 2022-08-16 stsp TAILQ_FOREACH(sock, &env->sockets, entry) {
303 a596b957 2022-07-14 tracey if (config_setsock(env, sock) == -1)
304 a596b957 2022-07-14 tracey fatalx("%s: send socket error", __func__);
305 a596b957 2022-07-14 tracey if (config_setfd(env, sock) == -1)
306 a596b957 2022-07-14 tracey fatalx("%s: send priv_fd error", __func__);
307 a596b957 2022-07-14 tracey }
308 a596b957 2022-07-14 tracey
309 a596b957 2022-07-14 tracey for (id = 0; id < PROC_MAX; id++) {
310 a596b957 2022-07-14 tracey if (id == privsep_process)
311 a596b957 2022-07-14 tracey continue;
312 a596b957 2022-07-14 tracey proc_compose(env->gotwebd_ps, id, IMSG_CFG_DONE, NULL, 0);
313 a596b957 2022-07-14 tracey }
314 a596b957 2022-07-14 tracey
315 a596b957 2022-07-14 tracey return (0);
316 a596b957 2022-07-14 tracey }
317 a596b957 2022-07-14 tracey
318 a596b957 2022-07-14 tracey void
319 a596b957 2022-07-14 tracey gotwebd_configure_done(struct gotwebd *env)
320 a596b957 2022-07-14 tracey {
321 a596b957 2022-07-14 tracey int id;
322 a596b957 2022-07-14 tracey
323 a596b957 2022-07-14 tracey if (env->gotwebd_reload == 0) {
324 a596b957 2022-07-14 tracey log_warnx("%s: configuration already finished", __func__);
325 a596b957 2022-07-14 tracey return;
326 a596b957 2022-07-14 tracey }
327 a596b957 2022-07-14 tracey
328 a596b957 2022-07-14 tracey env->gotwebd_reload--;
329 a596b957 2022-07-14 tracey if (env->gotwebd_reload == 0) {
330 a596b957 2022-07-14 tracey for (id = 0; id < PROC_MAX; id++) {
331 a596b957 2022-07-14 tracey if (id == privsep_process)
332 a596b957 2022-07-14 tracey continue;
333 a596b957 2022-07-14 tracey proc_compose(env->gotwebd_ps, id, IMSG_CTL_START,
334 a596b957 2022-07-14 tracey NULL, 0);
335 a596b957 2022-07-14 tracey }
336 a596b957 2022-07-14 tracey }
337 a596b957 2022-07-14 tracey }
338 a596b957 2022-07-14 tracey
339 a596b957 2022-07-14 tracey void
340 a596b957 2022-07-14 tracey gotwebd_shutdown(void)
341 a596b957 2022-07-14 tracey {
342 a596b957 2022-07-14 tracey proc_kill(gotwebd_env->gotwebd_ps);
343 a596b957 2022-07-14 tracey
344 a596b957 2022-07-14 tracey /* unlink(gotwebd_env->gotweb->gotweb_conf.gotweb_unix_socket_name); */
345 a596b957 2022-07-14 tracey /* free(gotwebd_env->gotweb); */
346 a596b957 2022-07-14 tracey free(gotwebd_env);
347 a596b957 2022-07-14 tracey
348 a596b957 2022-07-14 tracey log_warnx("gotwebd terminating");
349 a596b957 2022-07-14 tracey exit(0);
350 a596b957 2022-07-14 tracey }