GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/iked/iked.c Lines: 0 179 0.0 %
Date: 2016-12-06 Branches: 0 92 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: iked.c,v 1.30 2015/12/07 12:46:37 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 cpath wpath", 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
	default:
395
		return (-1);
396
	}
397
398
	return (0);
399
}
400
401
void
402
parent_shutdown(struct iked *env)
403
{
404
	proc_kill(&env->sc_ps);
405
406
	free(env);
407
408
	log_warnx("parent terminating");
409
	exit(0);
410
}