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