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