xref: /openbsd-src/sbin/iked/iked.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
1 /*	$OpenBSD: iked.c,v 1.64 2023/03/05 22:17:22 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 #include "version.h"
40 
41 __dead void usage(void);
42 
43 void	 parent_shutdown(struct iked *);
44 void	 parent_sig_handler(int, short, void *);
45 int	 parent_dispatch_ca(int, struct privsep_proc *, struct imsg *);
46 int	 parent_dispatch_control(int, struct privsep_proc *, struct imsg *);
47 int	 parent_dispatch_ikev2(int, struct privsep_proc *, struct imsg *);
48 int	 parent_configure(struct iked *);
49 
50 struct iked	*iked_env;
51 
52 static struct privsep_proc procs[] = {
53 	{ "ca",		PROC_CERT,	parent_dispatch_ca, caproc, IKED_CA },
54 	{ "control",	PROC_CONTROL,	parent_dispatch_control, control },
55 	{ "ikev2",	PROC_IKEV2,	parent_dispatch_ikev2, ikev2 }
56 };
57 
58 __dead void
59 usage(void)
60 {
61 	extern char	*__progname;
62 
63 	fprintf(stderr, "usage: %s [-dnSTtVv] [-D macro=value] "
64 	    "[-f file] [-p udpencap_port] [-s socket]\n", __progname);
65 	exit(1);
66 }
67 
68 int
69 main(int argc, char *argv[])
70 {
71 	int			 c;
72 	int			 debug = 0, verbose = 0;
73 	int			 opts = 0;
74 	enum natt_mode		 natt_mode = NATT_DEFAULT;
75 	in_port_t		 port = IKED_NATT_PORT;
76 	const char		*conffile = IKED_CONFIG;
77 	const char		*sock = IKED_SOCKET;
78 	const char		*errstr, *title = NULL;
79 	struct iked		*env = NULL;
80 	struct privsep		*ps;
81 	enum privsep_procid	 proc_id = PROC_PARENT;
82 	int			 proc_instance = 0;
83 	int			 argc0 = argc;
84 
85 	log_init(1, LOG_DAEMON);
86 
87 	while ((c = getopt(argc, argv, "6D:df:I:nP:p:Ss:TtvV")) != -1) {
88 		switch (c) {
89 		case '6':
90 			log_warnx("the -6 option is ignored and will be "
91 			    "removed in the future.");
92 			break;
93 		case 'D':
94 			if (cmdline_symset(optarg) < 0)
95 				log_warnx("could not parse macro definition %s",
96 				    optarg);
97 			break;
98 		case 'd':
99 			debug++;
100 			break;
101 		case 'f':
102 			conffile = optarg;
103 			break;
104 		case 'I':
105 			proc_instance = strtonum(optarg, 0,
106 			    PROC_MAX_INSTANCES, &errstr);
107 			if (errstr)
108 				fatalx("invalid process instance");
109 			break;
110 		case 'n':
111 			debug = 1;
112 			opts |= IKED_OPT_NOACTION;
113 			break;
114 		case 'P':
115 			title = optarg;
116 			proc_id = proc_getid(procs, nitems(procs), title);
117 			if (proc_id == PROC_MAX)
118 				fatalx("invalid process name");
119 			break;
120 		case 'p':
121 			if (natt_mode == NATT_DISABLE)
122 				errx(1, "-T and -p are mutually exclusive");
123 			port = strtonum(optarg, 1, UINT16_MAX, &errstr);
124 			if (errstr != NULL)
125 				errx(1, "port is %s: %s", errstr, optarg);
126 			natt_mode = NATT_FORCE;
127 			break;
128 		case 'S':
129 			opts |= IKED_OPT_PASSIVE;
130 			break;
131 		case 's':
132 			sock = optarg;
133 			break;
134 		case 'T':
135 			if (natt_mode == NATT_FORCE)
136 				errx(1, "-T and -t/-p are mutually exclusive");
137 			natt_mode = NATT_DISABLE;
138 			break;
139 		case 't':
140 			if (natt_mode == NATT_DISABLE)
141 				errx(1, "-T and -t are mutually exclusive");
142 			natt_mode = NATT_FORCE;
143 			break;
144 		case 'v':
145 			verbose++;
146 			opts |= IKED_OPT_VERBOSE;
147 			break;
148 		case 'V':
149 			fprintf(stderr, "OpenIKED %s\n", IKED_VERSION);
150 			return 0;
151 		default:
152 			usage();
153 		}
154 	}
155 
156 	/* log to stderr until daemonized */
157 	log_init(debug ? debug : 1, LOG_DAEMON);
158 
159 	argc -= optind;
160 	if (argc > 0)
161 		usage();
162 
163 	if ((env = calloc(1, sizeof(*env))) == NULL)
164 		fatal("calloc: env");
165 
166 	iked_env = env;
167 	env->sc_opts = opts;
168 	env->sc_nattmode = natt_mode;
169 	env->sc_nattport = port;
170 
171 	ps = &env->sc_ps;
172 	ps->ps_env = env;
173 	TAILQ_INIT(&ps->ps_rcsocks);
174 
175 	if (strlcpy(env->sc_conffile, conffile, PATH_MAX) >= PATH_MAX)
176 		errx(1, "config file exceeds PATH_MAX");
177 
178 	ca_sslinit();
179 	group_init();
180 	policy_init(env);
181 
182 	/* check for root privileges */
183 	if (geteuid())
184 		errx(1, "need root privileges");
185 
186 	if ((ps->ps_pw =  getpwnam(IKED_USER)) == NULL)
187 		errx(1, "unknown user %s", IKED_USER);
188 
189 	/* Configure the control socket */
190 	ps->ps_csock.cs_name = sock;
191 
192 	log_init(debug, LOG_DAEMON);
193 	log_setverbose(verbose);
194 
195 	if (opts & IKED_OPT_NOACTION)
196 		ps->ps_noaction = 1;
197 
198 	ps->ps_instance = proc_instance;
199 	if (title != NULL)
200 		ps->ps_title[proc_id] = title;
201 
202 	/* only the parent returns */
203 	proc_init(ps, procs, nitems(procs), debug, argc0, argv, proc_id);
204 
205 	setproctitle("parent");
206 	log_procinit("parent");
207 	if (!debug && daemon(0, 0) == -1)
208 		err(1, "failed to daemonize");
209 
210 	event_init();
211 
212 	signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
213 	signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
214 	signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps);
215 	signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
216 	signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
217 	signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps);
218 
219 	signal_add(&ps->ps_evsigint, NULL);
220 	signal_add(&ps->ps_evsigterm, NULL);
221 	signal_add(&ps->ps_evsigchld, NULL);
222 	signal_add(&ps->ps_evsighup, NULL);
223 	signal_add(&ps->ps_evsigpipe, NULL);
224 	signal_add(&ps->ps_evsigusr1, NULL);
225 
226 	proc_connect(ps);
227 
228 	vroute_init(env);
229 
230 	if (parent_configure(env) == -1)
231 		fatalx("configuration failed");
232 
233 	event_dispatch();
234 
235 	log_debug("%d parent exiting", getpid());
236 	parent_shutdown(env);
237 
238 	return (0);
239 }
240 
241 int
242 parent_configure(struct iked *env)
243 {
244 	struct sockaddr_storage	 ss;
245 
246 	if (parse_config(env->sc_conffile, env) == -1) {
247 		proc_kill(&env->sc_ps);
248 		exit(1);
249 	}
250 
251 	if (env->sc_opts & IKED_OPT_NOACTION) {
252 		fprintf(stderr, "configuration OK\n");
253 		proc_kill(&env->sc_ps);
254 		exit(0);
255 	}
256 
257 	env->sc_pfkey = -1;
258 	config_setpfkey(env);
259 
260 	/* Send private and public keys to cert after forking the children */
261 	if (config_setkeys(env) == -1)
262 		fatalx("%s: failed to send keys", __func__);
263 	config_setreset(env, RESET_CA, PROC_CERT);
264 
265 	/* Now compile the policies and calculate skip steps */
266 	config_setcompile(env, PROC_IKEV2);
267 
268 	bzero(&ss, sizeof(ss));
269 	ss.ss_family = AF_INET;
270 
271 	/* see comment on config_setsocket() */
272 	if (env->sc_nattmode != NATT_FORCE)
273 		config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2);
274 	if (env->sc_nattmode != NATT_DISABLE)
275 		config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2);
276 
277 	bzero(&ss, sizeof(ss));
278 	ss.ss_family = AF_INET6;
279 
280 	if (env->sc_nattmode != NATT_FORCE)
281 		config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2);
282 	if (env->sc_nattmode != NATT_DISABLE)
283 		config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2);
284 
285 	/*
286 	 * pledge in the parent process:
287 	 * It has to run fairly late to allow forking the processes and
288 	 * opening the PFKEY socket and the listening UDP sockets (once)
289 	 * that need the bypass ioctls that are never allowed by pledge.
290 	 *
291 	 * Other flags:
292 	 * stdio - for malloc and basic I/O including events.
293 	 * rpath - for reload to open and read the configuration files.
294 	 * proc - run kill to terminate its children safely.
295 	 * dns - for reload and ocsp connect.
296 	 * inet - for ocsp connect.
297 	 * route - for using interfaces in iked.conf (SIOCGIFGMEMB)
298 	 * wroute - for adding and removing addresses (SIOCAIFGMEMB)
299 	 * sendfd - for ocsp sockets.
300 	 */
301 	if (pledge("stdio rpath proc dns inet route wroute sendfd", NULL) == -1)
302 		fatal("pledge");
303 
304 	config_setstatic(env);
305 	config_setcoupled(env, env->sc_decoupled ? 0 : 1);
306 	config_setocsp(env);
307 	config_setcertpartialchain(env);
308 	/* Must be last */
309 	config_setmode(env, env->sc_passive ? 1 : 0);
310 
311 	return (0);
312 }
313 
314 void
315 parent_reload(struct iked *env, int reset, const char *filename)
316 {
317 	/* Switch back to the default config file */
318 	if (filename == NULL || *filename == '\0')
319 		filename = env->sc_conffile;
320 
321 	log_debug("%s: level %d config file %s", __func__, reset, filename);
322 
323 	if (reset == RESET_RELOAD) {
324 		config_setreset(env, RESET_POLICY, PROC_IKEV2);
325 		if (config_setkeys(env) == -1)
326 			fatalx("%s: failed to send keys", __func__);
327 		config_setreset(env, RESET_CA, PROC_CERT);
328 
329 		if (parse_config(filename, env) == -1) {
330 			log_debug("%s: failed to load config file %s",
331 			    __func__, filename);
332 		}
333 
334 		/* Re-compile policies and skip steps */
335 		config_setcompile(env, PROC_IKEV2);
336 
337 		config_setstatic(env);
338 		config_setcoupled(env, env->sc_decoupled ? 0 : 1);
339 		config_setocsp(env);
340 		config_setcertpartialchain(env);
341 		/* Must be last */
342 		config_setmode(env, env->sc_passive ? 1 : 0);
343 	} else {
344 		config_setreset(env, reset, PROC_IKEV2);
345 		config_setreset(env, reset, PROC_CERT);
346 	}
347 }
348 
349 void
350 parent_sig_handler(int sig, short event, void *arg)
351 {
352 	struct privsep	*ps = arg;
353 	int		 die = 0, status, fail, id;
354 	pid_t		 pid;
355 	char		*cause;
356 
357 	switch (sig) {
358 	case SIGHUP:
359 		log_info("%s: reload requested with SIGHUP", __func__);
360 
361 		/*
362 		 * This is safe because libevent uses async signal handlers
363 		 * that run in the event loop and not in signal context.
364 		 */
365 		parent_reload(ps->ps_env, 0, NULL);
366 		break;
367 	case SIGPIPE:
368 		log_info("%s: ignoring SIGPIPE", __func__);
369 		break;
370 	case SIGUSR1:
371 		log_info("%s: ignoring SIGUSR1", __func__);
372 		break;
373 	case SIGTERM:
374 	case SIGINT:
375 		die = 1;
376 		/* FALLTHROUGH */
377 	case SIGCHLD:
378 		do {
379 			int len = 0;
380 
381 			pid = waitpid(-1, &status, WNOHANG);
382 			if (pid <= 0)
383 				continue;
384 
385 			fail = 0;
386 			if (WIFSIGNALED(status)) {
387 				fail = 1;
388 				len = asprintf(&cause, "terminated; signal %d",
389 				    WTERMSIG(status));
390 			} else if (WIFEXITED(status)) {
391 				if (WEXITSTATUS(status) != 0) {
392 					fail = 1;
393 					len = asprintf(&cause,
394 					    "exited abnormally");
395 				} else
396 					len = asprintf(&cause, "exited okay");
397 			} else
398 				fatalx("unexpected cause of SIGCHLD");
399 
400 			if (len == -1)
401 				fatal("asprintf");
402 
403 			die = 1;
404 
405 			for (id = 0; id < PROC_MAX; id++)
406 				if (pid == ps->ps_pid[id]) {
407 					if (fail)
408 						log_warnx("lost child: %s %s",
409 						    ps->ps_title[id], cause);
410 					break;
411 				}
412 
413 			free(cause);
414 		} while (pid > 0 || (pid == -1 && errno == EINTR));
415 
416 		if (die)
417 			parent_shutdown(ps->ps_env);
418 		break;
419 	default:
420 		fatalx("unexpected signal");
421 	}
422 }
423 
424 int
425 parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
426 {
427 	struct iked	*env = iked_env;
428 
429 	switch (imsg->hdr.type) {
430 	case IMSG_OCSP_FD:
431 		ocsp_connect(env, imsg);
432 		break;
433 	default:
434 		return (-1);
435 	}
436 
437 	return (0);
438 }
439 
440 int
441 parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
442 {
443 	struct iked	*env = iked_env;
444 	int		 v;
445 	char		*str = NULL;
446 	unsigned int	 type = imsg->hdr.type;
447 
448 	switch (type) {
449 	case IMSG_CTL_RESET:
450 		IMSG_SIZE_CHECK(imsg, &v);
451 		memcpy(&v, imsg->data, sizeof(v));
452 		parent_reload(env, v, NULL);
453 		break;
454 	case IMSG_CTL_COUPLE:
455 	case IMSG_CTL_DECOUPLE:
456 	case IMSG_CTL_ACTIVE:
457 	case IMSG_CTL_PASSIVE:
458 		proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
459 		break;
460 	case IMSG_CTL_RELOAD:
461 		if (IMSG_DATA_SIZE(imsg) > 0)
462 			str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
463 		parent_reload(env, 0, str);
464 		free(str);
465 		break;
466 	case IMSG_CTL_VERBOSE:
467 		proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1);
468 		proc_forward_imsg(&env->sc_ps, imsg, PROC_CERT, -1);
469 
470 		/* return 1 to let proc.c handle it locally */
471 		return (1);
472 	default:
473 		return (-1);
474 	}
475 
476 	return (0);
477 }
478 
479 int
480 parent_dispatch_ikev2(int fd, struct privsep_proc *p, struct imsg *imsg)
481 {
482 	struct iked	*env = iked_env;
483 
484 	switch (imsg->hdr.type) {
485 	case IMSG_IF_ADDADDR:
486 	case IMSG_IF_DELADDR:
487 		return (vroute_getaddr(env, imsg));
488 	case IMSG_VDNS_ADD:
489 	case IMSG_VDNS_DEL:
490 		return (vroute_getdns(env, imsg));
491 	case IMSG_VROUTE_ADD:
492 	case IMSG_VROUTE_DEL:
493 		return (vroute_getroute(env, imsg));
494 	case IMSG_VROUTE_CLONE:
495 		return (vroute_getcloneroute(env, imsg));
496 	default:
497 		return (-1);
498 	}
499 
500 	return (0);
501 }
502 
503 void
504 parent_shutdown(struct iked *env)
505 {
506 	proc_kill(&env->sc_ps);
507 
508 	vroute_cleanup(env);
509 	free(env->sc_vroute);
510 	free(env);
511 
512 	log_warnx("parent terminating");
513 	exit(0);
514 }
515