GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/iked/iked.c Lines: 0 186 0.0 %
Date: 2017-11-07 Branches: 0 105 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: iked.c,v 1.34 2017/03/23 05:29:48 jsg 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_setverbose(verbose);
144
145
	if (opts & IKED_OPT_NOACTION)
146
		ps->ps_noaction = 1;
147
148
	if (!debug && daemon(0, 0) == -1)
149
		err(1, "failed to daemonize");
150
151
	group_init();
152
153
	ps->ps_ninstances = 1;
154
	proc_init(ps, procs, nitems(procs));
155
156
	setproctitle("parent");
157
	log_procinit("parent");
158
159
	event_init();
160
161
	signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
162
	signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
163
	signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps);
164
	signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
165
	signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
166
	signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps);
167
168
	signal_add(&ps->ps_evsigint, NULL);
169
	signal_add(&ps->ps_evsigterm, NULL);
170
	signal_add(&ps->ps_evsigchld, NULL);
171
	signal_add(&ps->ps_evsighup, NULL);
172
	signal_add(&ps->ps_evsigpipe, NULL);
173
	signal_add(&ps->ps_evsigusr1, NULL);
174
175
	proc_listen(ps, procs, nitems(procs));
176
177
	if (parent_configure(env) == -1)
178
		fatalx("configuration failed");
179
180
	event_dispatch();
181
182
	log_debug("%d parent exiting", getpid());
183
184
	return (0);
185
}
186
187
int
188
parent_configure(struct iked *env)
189
{
190
	struct sockaddr_storage	 ss;
191
192
	if (parse_config(env->sc_conffile, env) == -1) {
193
		proc_kill(&env->sc_ps);
194
		exit(1);
195
	}
196
197
	if (env->sc_opts & IKED_OPT_NOACTION) {
198
		fprintf(stderr, "configuration OK\n");
199
		proc_kill(&env->sc_ps);
200
		exit(0);
201
	}
202
203
	env->sc_pfkey = -1;
204
	config_setpfkey(env, PROC_IKEV2);
205
206
	/* Send private and public keys to cert after forking the children */
207
	if (config_setkeys(env) == -1)
208
		fatalx("%s: failed to send keys", __func__);
209
	config_setreset(env, RESET_CA, PROC_CERT);
210
211
	/* Now compile the policies and calculate skip steps */
212
	config_setcompile(env, PROC_IKEV2);
213
214
	bzero(&ss, sizeof(ss));
215
	ss.ss_family = AF_INET;
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
	bzero(&ss, sizeof(ss));
223
	ss.ss_family = AF_INET6;
224
225
	if ((env->sc_opts & IKED_OPT_NATT) == 0)
226
		config_setsocket(env, &ss, ntohs(IKED_IKE_PORT), PROC_IKEV2);
227
	if ((env->sc_opts & IKED_OPT_NONATT) == 0)
228
		config_setsocket(env, &ss, ntohs(IKED_NATT_PORT), PROC_IKEV2);
229
230
	/*
231
	 * pledge in the parent process:
232
	 * It has to run fairly late to allow forking the processes and
233
	 * opening the PFKEY socket and the listening UDP sockets (once)
234
	 * that need the bypass ioctls that are never allowed by pledge.
235
	 *
236
	 * Other flags:
237
	 * stdio - for malloc and basic I/O including events.
238
	 * rpath - for reload to open and read the configuration files.
239
	 * proc - run kill to terminate its children safely.
240
	 * dns - for reload and ocsp connect.
241
	 * inet - for ocsp connect.
242
	 * route - for using interfaces in iked.conf (SIOCGIFGMEMB)
243
	 * sendfd - for ocsp sockets.
244
	 */
245
	if (pledge("stdio rpath proc dns inet route sendfd flock cpath wpath", NULL) == -1)
246
		fatal("pledge");
247
248
	config_setcoupled(env, env->sc_decoupled ? 0 : 1);
249
	config_setmode(env, env->sc_passive ? 1 : 0);
250
	config_setocsp(env);
251
252
	return (0);
253
}
254
255
void
256
parent_reload(struct iked *env, int reset, const char *filename)
257
{
258
	/* Switch back to the default config file */
259
	if (filename == NULL || *filename == '\0')
260
		filename = env->sc_conffile;
261
262
	log_debug("%s: level %d config file %s", __func__, reset, filename);
263
264
	if (reset == RESET_RELOAD) {
265
		config_setreset(env, RESET_POLICY, PROC_IKEV2);
266
		if (config_setkeys(env) == -1)
267
			fatalx("%s: failed to send keys", __func__);
268
		config_setreset(env, RESET_CA, PROC_CERT);
269
270
		if (parse_config(filename, env) == -1) {
271
			log_debug("%s: failed to load config file %s",
272
			    __func__, filename);
273
		}
274
275
		/* Re-compile policies and skip steps */
276
		config_setcompile(env, PROC_IKEV2);
277
278
		config_setcoupled(env, env->sc_decoupled ? 0 : 1);
279
		config_setmode(env, env->sc_passive ? 1 : 0);
280
		config_setocsp(env);
281
	} else {
282
		config_setreset(env, reset, PROC_IKEV2);
283
		config_setreset(env, reset, PROC_CERT);
284
	}
285
}
286
287
void
288
parent_sig_handler(int sig, short event, void *arg)
289
{
290
	struct privsep	*ps = arg;
291
	int		 die = 0, status, fail, id;
292
	pid_t		 pid;
293
	char		*cause;
294
295
	switch (sig) {
296
	case SIGHUP:
297
		log_info("%s: reload requested with SIGHUP", __func__);
298
299
		/*
300
		 * This is safe because libevent uses async signal handlers
301
		 * that run in the event loop and not in signal context.
302
		 */
303
		parent_reload(ps->ps_env, 0, NULL);
304
		break;
305
	case SIGPIPE:
306
		log_info("%s: ignoring SIGPIPE", __func__);
307
		break;
308
	case SIGUSR1:
309
		log_info("%s: ignoring SIGUSR1", __func__);
310
		break;
311
	case SIGTERM:
312
	case SIGINT:
313
		die = 1;
314
		/* FALLTHROUGH */
315
	case SIGCHLD:
316
		do {
317
			int len;
318
319
			pid = waitpid(-1, &status, WNOHANG);
320
			if (pid <= 0)
321
				continue;
322
323
			fail = 0;
324
			if (WIFSIGNALED(status)) {
325
				fail = 1;
326
				len = asprintf(&cause, "terminated; signal %d",
327
				    WTERMSIG(status));
328
			} else if (WIFEXITED(status)) {
329
				if (WEXITSTATUS(status) != 0) {
330
					fail = 1;
331
					len = asprintf(&cause,
332
					    "exited abnormally");
333
				} else
334
					len = asprintf(&cause, "exited okay");
335
			} else
336
				fatalx("unexpected cause of SIGCHLD");
337
338
			if (len == -1)
339
				fatal("asprintf");
340
341
			die = 1;
342
343
			for (id = 0; id < PROC_MAX; id++)
344
				if (pid == ps->ps_pid[id]) {
345
					if (fail)
346
						log_warnx("lost child: %s %s",
347
						    ps->ps_title[id], cause);
348
					break;
349
				}
350
351
			free(cause);
352
		} while (pid > 0 || (pid == -1 && errno == EINTR));
353
354
		if (die)
355
			parent_shutdown(ps->ps_env);
356
		break;
357
	default:
358
		fatalx("unexpected signal");
359
	}
360
}
361
362
int
363
parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
364
{
365
	struct iked	*env = p->p_ps->ps_env;
366
367
	switch (imsg->hdr.type) {
368
	case IMSG_OCSP_FD:
369
		ocsp_connect(env);
370
		break;
371
	default:
372
		return (-1);
373
	}
374
375
	return (0);
376
}
377
378
int
379
parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
380
{
381
	struct iked	*env = p->p_ps->ps_env;
382
	int		 v;
383
	char		*str = NULL;
384
	unsigned int	 type = imsg->hdr.type;
385
386
	switch (type) {
387
	case IMSG_CTL_RESET:
388
		IMSG_SIZE_CHECK(imsg, &v);
389
		memcpy(&v, imsg->data, sizeof(v));
390
		parent_reload(env, v, NULL);
391
		break;
392
	case IMSG_CTL_COUPLE:
393
	case IMSG_CTL_DECOUPLE:
394
	case IMSG_CTL_ACTIVE:
395
	case IMSG_CTL_PASSIVE:
396
		proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0);
397
		break;
398
	case IMSG_CTL_RELOAD:
399
		if (IMSG_DATA_SIZE(imsg) > 0)
400
			str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
401
		parent_reload(env, 0, str);
402
		free(str);
403
		break;
404
	case IMSG_CTL_VERBOSE:
405
		proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1);
406
		proc_forward_imsg(&env->sc_ps, imsg, PROC_CERT, -1);
407
408
		/* return 1 to let proc.c handle it locally */
409
		return (1);
410
	default:
411
		return (-1);
412
	}
413
414
	return (0);
415
}
416
417
void
418
parent_shutdown(struct iked *env)
419
{
420
	proc_kill(&env->sc_ps);
421
422
	free(env);
423
424
	log_warnx("parent terminating");
425
	exit(0);
426
}