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