xref: /openbsd-src/sbin/iked/iked.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: iked.c,v 1.52 2020/12/17 20:43:07 tobhe Exp $	*/
2 
3 /*
4  * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/wait.h>
23 #include <sys/uio.h>
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <getopt.h>
30 #include <signal.h>
31 #include <syslog.h>
32 #include <errno.h>
33 #include <err.h>
34 #include <pwd.h>
35 #include <event.h>
36 
37 #include "iked.h"
38 #include "ikev2.h"
39 
40 __dead void usage(void);
41 
42 void	 parent_shutdown(struct iked *);
43 void	 parent_sig_handler(int, short, void *);
44 int	 parent_dispatch_ca(int, struct privsep_proc *, struct imsg *);
45 int	 parent_dispatch_control(int, struct privsep_proc *, struct imsg *);
46 int	 parent_configure(struct iked *);
47 
48 static struct privsep_proc procs[] = {
49 	{ "ca",		PROC_CERT,	parent_dispatch_ca, caproc, IKED_CA },
50 	{ "control",	PROC_CONTROL,	parent_dispatch_control, control },
51 	{ "ikev2",	PROC_IKEV2,	NULL, ikev2 }
52 };
53 
54 __dead void
55 usage(void)
56 {
57 	extern char	*__progname;
58 
59 	fprintf(stderr, "usage: %s [-dnSTtv] [-D macro=value] "
60 	    "[-f file] [-p udpencap_port] [-s socket]\n", __progname);
61 	exit(1);
62 }
63 
64 int
65 main(int argc, char *argv[])
66 {
67 	int		 c;
68 	int		 debug = 0, verbose = 0;
69 	int		 opts = 0;
70 	enum natt_mode	 natt_mode = NATT_DEFAULT;
71 	in_port_t	 port = IKED_NATT_PORT;
72 	const char	*conffile = IKED_CONFIG;
73 	const char	*sock = IKED_SOCKET;
74 	const char	*errstr;
75 	struct iked	*env = NULL;
76 	struct privsep	*ps;
77 
78 	log_init(1, LOG_DAEMON);
79 
80 	while ((c = getopt(argc, argv, "6D:df:np:Ss:Ttv")) != -1) {
81 		switch (c) {
82 		case '6':
83 			log_warnx("the -6 option is ignored and will be "
84 			    "removed in the future.");
85 			break;
86 		case 'D':
87 			if (cmdline_symset(optarg) < 0)
88 				log_warnx("could not parse macro definition %s",
89 				    optarg);
90 			break;
91 		case 'd':
92 			debug++;
93 			break;
94 		case 'f':
95 			conffile = optarg;
96 			break;
97 		case 'n':
98 			debug = 1;
99 			opts |= IKED_OPT_NOACTION;
100 			break;
101 		case 'p':
102 			if (natt_mode == NATT_DISABLE)
103 				errx(1, "-T and -p are mutually exclusive");
104 			port = strtonum(optarg, 1, UINT16_MAX, &errstr);
105 			if (errstr != NULL)
106 				errx(1, "port is %s: %s", errstr, optarg);
107 			natt_mode = NATT_FORCE;
108 			break;
109 		case 'S':
110 			opts |= IKED_OPT_PASSIVE;
111 			break;
112 		case 's':
113 			sock = optarg;
114 			break;
115 		case 'T':
116 			if (natt_mode == NATT_FORCE)
117 				errx(1, "-T and -t/-p are mutually exclusive");
118 			natt_mode = NATT_DISABLE;
119 			break;
120 		case 't':
121 			if (natt_mode == NATT_DISABLE)
122 				errx(1, "-T and -t are mutually exclusive");
123 			natt_mode = NATT_FORCE;
124 			break;
125 		case 'v':
126 			verbose++;
127 			opts |= IKED_OPT_VERBOSE;
128 			break;
129 		default:
130 			usage();
131 		}
132 	}
133 
134 	argc -= optind;
135 	argv += optind;
136 	if (argc > 0)
137 		usage();
138 
139 	if ((env = calloc(1, sizeof(*env))) == NULL)
140 		fatal("calloc: env");
141 
142 	env->sc_opts = opts;
143 	env->sc_nattmode = natt_mode;
144 	env->sc_nattport = port;
145 
146 	ps = &env->sc_ps;
147 	ps->ps_env = env;
148 	TAILQ_INIT(&ps->ps_rcsocks);
149 
150 	if (strlcpy(env->sc_conffile, conffile, PATH_MAX) >= PATH_MAX)
151 		errx(1, "config file exceeds PATH_MAX");
152 
153 	ca_sslinit();
154 	policy_init(env);
155 
156 	/* check for root privileges */
157 	if (geteuid())
158 		errx(1, "need root privileges");
159 
160 	if ((ps->ps_pw =  getpwnam(IKED_USER)) == NULL)
161 		errx(1, "unknown user %s", IKED_USER);
162 
163 	/* Configure the control socket */
164 	ps->ps_csock.cs_name = sock;
165 
166 	log_init(debug, LOG_DAEMON);
167 	log_setverbose(verbose);
168 
169 	if (opts & IKED_OPT_NOACTION)
170 		ps->ps_noaction = 1;
171 
172 	if (!debug && daemon(0, 0) == -1)
173 		err(1, "failed to daemonize");
174 
175 	group_init();
176 
177 	ps->ps_ninstances = 1;
178 	proc_init(ps, procs, nitems(procs));
179 
180 	setproctitle("parent");
181 	log_procinit("parent");
182 
183 	event_init();
184 
185 	signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
186 	signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
187 	signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps);
188 	signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
189 	signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
190 	signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps);
191 
192 	signal_add(&ps->ps_evsigint, NULL);
193 	signal_add(&ps->ps_evsigterm, NULL);
194 	signal_add(&ps->ps_evsigchld, NULL);
195 	signal_add(&ps->ps_evsighup, NULL);
196 	signal_add(&ps->ps_evsigpipe, NULL);
197 	signal_add(&ps->ps_evsigusr1, NULL);
198 
199 	proc_listen(ps, procs, nitems(procs));
200 
201 	if (parent_configure(env) == -1)
202 		fatalx("configuration failed");
203 
204 	event_dispatch();
205 
206 	log_debug("%d parent exiting", getpid());
207 
208 	return (0);
209 }
210 
211 int
212 parent_configure(struct iked *env)
213 {
214 	struct sockaddr_storage	 ss;
215 
216 	if (parse_config(env->sc_conffile, env) == -1) {
217 		proc_kill(&env->sc_ps);
218 		exit(1);
219 	}
220 
221 	if (env->sc_opts & IKED_OPT_NOACTION) {
222 		fprintf(stderr, "configuration OK\n");
223 		proc_kill(&env->sc_ps);
224 		exit(0);
225 	}
226 
227 	env->sc_pfkey = -1;
228 	config_setpfkey(env, PROC_IKEV2);
229 
230 	/* Send private and public keys to cert after forking the children */
231 	if (config_setkeys(env) == -1)
232 		fatalx("%s: failed to send keys", __func__);
233 	config_setreset(env, RESET_CA, PROC_CERT);
234 
235 	/* Now compile the policies and calculate skip steps */
236 	config_setcompile(env, PROC_IKEV2);
237 
238 	bzero(&ss, sizeof(ss));
239 	ss.ss_family = AF_INET;
240 
241 	/* see comment on config_setsocket() */
242 	if (env->sc_nattmode != NATT_FORCE)
243 		config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2);
244 	if (env->sc_nattmode != NATT_DISABLE)
245 		config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2);
246 
247 	bzero(&ss, sizeof(ss));
248 	ss.ss_family = AF_INET6;
249 
250 	if (env->sc_nattmode != NATT_FORCE)
251 		config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2);
252 	if (env->sc_nattmode != NATT_DISABLE)
253 		config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2);
254 
255 	/*
256 	 * pledge in the parent process:
257 	 * It has to run fairly late to allow forking the processes and
258 	 * opening the PFKEY socket and the listening UDP sockets (once)
259 	 * that need the bypass ioctls that are never allowed by pledge.
260 	 *
261 	 * Other flags:
262 	 * stdio - for malloc and basic I/O including events.
263 	 * rpath - for reload to open and read the configuration files.
264 	 * proc - run kill to terminate its children safely.
265 	 * dns - for reload and ocsp connect.
266 	 * inet - for ocsp connect.
267 	 * route - for using interfaces in iked.conf (SIOCGIFGMEMB)
268 	 * sendfd - for ocsp sockets.
269 	 */
270 	if (pledge("stdio rpath proc dns inet route sendfd", NULL) == -1)
271 		fatal("pledge");
272 
273 	config_setstatic(env);
274 	config_setcoupled(env, env->sc_decoupled ? 0 : 1);
275 	config_setocsp(env);
276 	config_setcertpartialchain(env);
277 	/* Must be last */
278 	config_setmode(env, env->sc_passive ? 1 : 0);
279 
280 	return (0);
281 }
282 
283 void
284 parent_reload(struct iked *env, int reset, const char *filename)
285 {
286 	/* Switch back to the default config file */
287 	if (filename == NULL || *filename == '\0')
288 		filename = env->sc_conffile;
289 
290 	log_debug("%s: level %d config file %s", __func__, reset, filename);
291 
292 	if (reset == RESET_RELOAD) {
293 		config_setreset(env, RESET_POLICY, PROC_IKEV2);
294 		if (config_setkeys(env) == -1)
295 			fatalx("%s: failed to send keys", __func__);
296 		config_setreset(env, RESET_CA, PROC_CERT);
297 
298 		if (parse_config(filename, env) == -1) {
299 			log_debug("%s: failed to load config file %s",
300 			    __func__, filename);
301 		}
302 
303 		/* Re-compile policies and skip steps */
304 		config_setcompile(env, PROC_IKEV2);
305 
306 		config_setstatic(env);
307 		config_setcoupled(env, env->sc_decoupled ? 0 : 1);
308 		config_setocsp(env);
309 		config_setcertpartialchain(env);
310  		/* Must be last */
311 		config_setmode(env, env->sc_passive ? 1 : 0);
312 	} else {
313 		config_setreset(env, reset, PROC_IKEV2);
314 		config_setreset(env, reset, PROC_CERT);
315 	}
316 }
317 
318 void
319 parent_sig_handler(int sig, short event, void *arg)
320 {
321 	struct privsep	*ps = arg;
322 	int		 die = 0, status, fail, id;
323 	pid_t		 pid;
324 	char		*cause;
325 
326 	switch (sig) {
327 	case SIGHUP:
328 		log_info("%s: reload requested with SIGHUP", __func__);
329 
330 		/*
331 		 * This is safe because libevent uses async signal handlers
332 		 * that run in the event loop and not in signal context.
333 		 */
334 		parent_reload(ps->ps_env, 0, NULL);
335 		break;
336 	case SIGPIPE:
337 		log_info("%s: ignoring SIGPIPE", __func__);
338 		break;
339 	case SIGUSR1:
340 		log_info("%s: ignoring SIGUSR1", __func__);
341 		break;
342 	case SIGTERM:
343 	case SIGINT:
344 		die = 1;
345 		/* FALLTHROUGH */
346 	case SIGCHLD:
347 		do {
348 			int len;
349 
350 			pid = waitpid(-1, &status, WNOHANG);
351 			if (pid <= 0)
352 				continue;
353 
354 			fail = 0;
355 			if (WIFSIGNALED(status)) {
356 				fail = 1;
357 				len = asprintf(&cause, "terminated; signal %d",
358 				    WTERMSIG(status));
359 			} else if (WIFEXITED(status)) {
360 				if (WEXITSTATUS(status) != 0) {
361 					fail = 1;
362 					len = asprintf(&cause,
363 					    "exited abnormally");
364 				} else
365 					len = asprintf(&cause, "exited okay");
366 			} else
367 				fatalx("unexpected cause of SIGCHLD");
368 
369 			if (len == -1)
370 				fatal("asprintf");
371 
372 			die = 1;
373 
374 			for (id = 0; id < PROC_MAX; id++)
375 				if (pid == ps->ps_pid[id]) {
376 					if (fail)
377 						log_warnx("lost child: %s %s",
378 						    ps->ps_title[id], cause);
379 					break;
380 				}
381 
382 			free(cause);
383 		} while (pid > 0 || (pid == -1 && errno == EINTR));
384 
385 		if (die)
386 			parent_shutdown(ps->ps_env);
387 		break;
388 	default:
389 		fatalx("unexpected signal");
390 	}
391 }
392 
393 int
394 parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
395 {
396 	struct iked	*env = p->p_ps->ps_env;
397 
398 	switch (imsg->hdr.type) {
399 	case IMSG_OCSP_FD:
400 		ocsp_connect(env, imsg);
401 		break;
402 	default:
403 		return (-1);
404 	}
405 
406 	return (0);
407 }
408 
409 int
410 parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
411 {
412 	struct iked	*env = p->p_ps->ps_env;
413 	int		 v;
414 	char		*str = NULL;
415 	unsigned int	 type = imsg->hdr.type;
416 
417 	switch (type) {
418 	case IMSG_CTL_RESET:
419 		IMSG_SIZE_CHECK(imsg, &v);
420 		memcpy(&v, imsg->data, sizeof(v));
421 		parent_reload(env, v, NULL);
422 		break;
423 	case IMSG_CTL_COUPLE:
424 	case IMSG_CTL_DECOUPLE:
425 	case IMSG_CTL_ACTIVE:
426 	case IMSG_CTL_PASSIVE:
427 		proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
428 		break;
429 	case IMSG_CTL_RELOAD:
430 		if (IMSG_DATA_SIZE(imsg) > 0)
431 			str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
432 		parent_reload(env, 0, str);
433 		free(str);
434 		break;
435 	case IMSG_CTL_VERBOSE:
436 		proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1);
437 		proc_forward_imsg(&env->sc_ps, imsg, PROC_CERT, -1);
438 
439 		/* return 1 to let proc.c handle it locally */
440 		return (1);
441 	default:
442 		return (-1);
443 	}
444 
445 	return (0);
446 }
447 
448 void
449 parent_shutdown(struct iked *env)
450 {
451 	proc_kill(&env->sc_ps);
452 
453 	free(env);
454 
455 	log_warnx("parent terminating");
456 	exit(0);
457 }
458