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