Blob


1 /*
2 * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
3 * Copyright (c) 2014 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/tree.h>
21 #include <sys/socket.h>
22 #include <sys/uio.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
27 #include <errno.h>
28 #include <event.h>
29 #include <limits.h>
30 #include <locale.h>
31 #include <pwd.h>
32 #include <signal.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <syslog.h>
38 #include <unistd.h>
39 #include <imsg.h>
41 #include "log.h"
42 #include "proc.h"
43 #include "xmalloc.h"
45 #include "galileo.h"
47 static int parent_configure(struct galileo *);
48 static void parent_configure_done(struct galileo *);
49 static void parent_reload(struct galileo *);
50 static void parent_sig_handler(int, short, void *);
51 static int parent_dispatch_proxy(int, struct privsep_proc *,
52 struct imsg *);
53 static __dead void parent_shutdown(struct galileo *);
55 static struct privsep_proc procs[] = {
56 { "proxy", PROC_PROXY, parent_dispatch_proxy, proxy },
57 };
59 int privsep_process;
61 const char *conffile = GALILEO_CONF;
63 static __dead void
64 usage(void)
65 {
66 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
67 getprogname());
68 exit(1);
69 }
71 int
72 main(int argc, char **argv)
73 {
74 struct galileo *env;
75 struct privsep *ps;
76 const char *errstr;
77 const char *title = NULL;
78 size_t i;
79 int conftest = 0, debug = 0, verbose = 0;
80 int argc0 = argc, ch;
81 int proc_id = PROC_PARENT;
82 int proc_instance = 0;
84 setlocale(LC_CTYPE, "");
86 /* log to stderr until daemonized */
87 log_init(1, LOG_DAEMON);
88 log_setverbose(verbose);
90 while ((ch = getopt(argc, argv, "D:df:I:nP:v")) != -1) {
91 switch (ch) {
92 case 'D':
93 if (cmdline_symset(optarg) < 0)
94 log_warnx("could not parse macro definition %s",
95 optarg);
96 break;
97 case 'd':
98 debug = 1;
99 break;
100 case 'f':
101 conffile = optarg;
102 break;
103 case 'I':
104 proc_instance = strtonum(optarg, 0, PROC_MAX_INSTANCES,
105 &errstr);
106 if (errstr != NULL)
107 fatalx("invalid process instance");
108 break;
109 case 'n':
110 conftest = 1;
111 break;
112 case 'P':
113 title = optarg;
114 proc_id = proc_getid(procs, nitems(procs), title);
115 if (proc_id == PROC_MAX)
116 fatalx("invalid process name");
117 break;
118 case 'v':
119 verbose = 1;
120 break;
121 default:
122 usage();
125 argc -= optind;
126 if (argc != 0)
127 usage();
129 if (geteuid())
130 fatalx("need root privileges");
132 log_setverbose(verbose);
134 env = xcalloc(1, sizeof(*env));
135 config_init(env);
136 if (parse_config(conffile, env) == -1)
137 return (1);
139 if (conftest) {
140 fprintf(stderr, "configuration OK\n");
141 return (0);
144 ps = xcalloc(1, sizeof(*ps));
145 ps->ps_env = env;
146 env->sc_ps = ps;
147 if ((ps->ps_pw = getpwnam(GALILEO_USER)) == NULL)
148 fatalx("unknown user %s", GALILEO_USER);
150 ps->ps_instances[PROC_PROXY] = env->sc_prefork;
151 ps->ps_instance = proc_instance;
152 if (title != NULL)
153 ps->ps_title[proc_id] = title;
155 if (*env->sc_chroot == '\0') {
156 if (strlcpy(env->sc_chroot, ps->ps_pw->pw_dir,
157 sizeof(env->sc_chroot)) >= sizeof(env->sc_chroot))
158 fatalx("chroot path too long!");
161 for (i = 0; i < nitems(procs); ++i)
162 procs[i].p_chroot = env->sc_chroot;
164 /* only the parent returns */
165 proc_init(ps, procs, nitems(procs), debug, argc0, argv, proc_id);
167 log_procinit("parent");
168 if (!debug && daemon(0, 0) == -1)
169 fatal("failed to daemonize");
171 log_init(debug, LOG_DAEMON);
173 log_info("startup");
175 if (pledge("stdio rpath wpath cpath chown unix fattr sendfd", NULL)
176 == -1)
177 fatal("pledge");
179 event_init();
181 signal(SIGPIPE, SIG_IGN);
183 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
184 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
185 signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps);
186 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
188 signal_add(&ps->ps_evsigint, NULL);
189 signal_add(&ps->ps_evsigterm, NULL);
190 signal_add(&ps->ps_evsigchld, NULL);
191 signal_add(&ps->ps_evsighup, NULL);
193 proc_connect(ps);
195 if (parent_configure(env) == -1)
196 fatalx("configuration failed");
198 event_dispatch();
200 parent_shutdown(env);
201 /* NOTREACHED */
203 return (0);
206 static int
207 parent_configure(struct galileo *env)
209 struct proxy *proxy;
210 int id;
212 TAILQ_FOREACH(proxy, &env->sc_proxies, pr_entry) {
213 if (config_setproxy(env, proxy) == -1)
214 fatal("send proxy");
217 /* XXX: eventually they will be more than just one */
218 if (config_setsock(env) == -1)
219 fatal("send socket");
221 /* The proxiess need to reload their config. */
222 env->sc_reload = env->sc_prefork;
224 for (id = 0; id < PROC_MAX; id++) {
225 if (id == privsep_process)
226 continue;
227 proc_compose(env->sc_ps, id, IMSG_CFG_DONE, env, sizeof(env));
230 config_purge(env);
231 return (0);
234 static void
235 parent_configure_done(struct galileo *env)
237 int id;
239 if (env->sc_reload == 0) {
240 log_warnx("configuration already finished");
241 return;
244 env->sc_reload--;
245 if (env->sc_reload == 0) {
246 for (id = 0; id < PROC_MAX; ++id) {
247 if (id == privsep_process)
248 continue;
250 proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL, 0);
255 static void
256 parent_reload(struct galileo *env)
258 if (env->sc_reload) {
259 log_debug("%s: already in progress: %d pending",
260 __func__, env->sc_reload);
263 log_debug("%s: config file %s", __func__, conffile);
265 config_purge(env);
267 if (parse_config(conffile, env) == -1) {
268 log_warnx("failed to load config file: %s", conffile);
269 return;
272 config_setreset(env);
273 parent_configure(env);
276 static void
277 parent_sig_handler(int sig, short ev, void *arg)
279 struct privsep *ps = arg;
281 /*
282 * Normal signal handler rules don't apply because libevent
283 * decouples for us.
284 */
286 switch (sig) {
287 case SIGHUP:
288 if (privsep_process != PROC_PARENT)
289 return;
290 log_info("reload requested with SIGHUP");
291 parent_reload(ps->ps_env);
292 break;
293 case SIGCHLD:
294 log_warnx("one child died, quitting.");
295 /* fallthrough */
296 case SIGTERM:
297 case SIGINT:
298 parent_shutdown(ps->ps_env);
299 break;
300 default:
301 fatalx("unexpected signal %d", sig);
305 static int
306 parent_dispatch_proxy(int fd, struct privsep_proc *p, struct imsg *imsg)
308 struct privsep *ps = p->p_ps;
309 struct galileo *env = ps->ps_env;
311 switch (imsg->hdr.type) {
312 case IMSG_CFG_DONE:
313 parent_configure_done(env);
314 break;
315 default:
316 return (-1);
319 return (0);
322 static __dead void
323 parent_shutdown(struct galileo *env)
325 config_purge(env);
327 proc_kill(env->sc_ps);
329 free(env->sc_ps);
330 free(env);
332 log_info("parent terminating, pid %d", getpid());
333 exit(0);
336 int
337 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
338 int reserve, volatile int *counter)
340 int ret;
341 if (getdtablecount() + reserve +
342 *counter >= getdtablesize()) {
343 errno = EMFILE;
344 return (-1);
347 if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) {
348 (*counter)++;
349 log_debug("%s: inflight incremented, now %d",__func__, *counter);
351 return (ret);