GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ikectl/ikectl.c Lines: 0 155 0.0 %
Date: 2017-11-07 Branches: 0 126 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ikectl.c,v 1.23 2015/12/05 13:11:18 claudio Exp $	*/
2
3
/*
4
 * Copyright (c) 2007-2013 Reyk Floeter <reyk@openbsd.org>
5
 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6
 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
7
 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
#include <sys/types.h>
23
#include <sys/socket.h>
24
#include <sys/queue.h>
25
#include <sys/un.h>
26
#include <sys/tree.h>
27
28
#include <err.h>
29
#include <errno.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <unistd.h>
34
#include <event.h>
35
36
#include "iked.h"
37
#include "parser.h"
38
39
__dead void	 usage(void);
40
41
struct imsgname {
42
	int type;
43
	char *name;
44
	void (*func)(struct imsg *);
45
};
46
47
struct imsgname *monitor_lookup(uint8_t);
48
void		 monitor_id(struct imsg *);
49
int		 monitor(struct imsg *);
50
51
int		 ca_opt(struct parse_result *);
52
53
struct imsgname imsgs[] = {
54
	{ IMSG_CTL_OK,			"ok",			NULL },
55
	{ IMSG_CTL_FAIL,		"fail",			NULL },
56
	{ IMSG_CTL_VERBOSE,		"verbose",		NULL },
57
	{ IMSG_CTL_RELOAD,		"reload",		NULL },
58
	{ IMSG_CTL_RESET,		"reset",		NULL },
59
	{ 0,				NULL,			NULL }
60
61
};
62
struct imsgname imsgunknown = {
63
	-1,				"<unknown>",		NULL
64
};
65
66
struct imsgbuf	*ibuf;
67
68
__dead void
69
usage(void)
70
{
71
	extern char *__progname;
72
73
	fprintf(stderr, "usage: %s [-q] [-s socket] command [arg ...]\n",
74
	    __progname);
75
	exit(1);
76
}
77
78
int
79
ca_opt(struct parse_result *res)
80
{
81
	struct ca	*ca;
82
	size_t		 len;
83
	char		*p;
84
85
	ca = ca_setup(res->caname, (res->action == CA_CREATE),
86
	    res->quiet, res->pass);
87
	if (ca == NULL)
88
		errx(1, "ca_setup failed");
89
90
	/* assume paths are relative to /etc if not absolute */
91
	if (res->path && (res->path[0] != '.') && (res->path[0] != '/')) {
92
		len = 5 + strlen(res->path) + 1;
93
		if ((p = malloc(len)) == NULL)
94
			err(1, "malloc");
95
		snprintf(p, len, "/etc/%s", res->path);
96
		free(res->path);
97
		res->path = p;
98
	}
99
100
	switch (res->action) {
101
	case CA_CREATE:
102
		ca_create(ca);
103
		break;
104
	case CA_DELETE:
105
		ca_delete(ca);
106
		break;
107
	case CA_INSTALL:
108
		ca_install(ca, res->path);
109
		break;
110
	case CA_EXPORT:
111
		ca_export(ca, NULL, res->peer, res->pass);
112
		break;
113
	case CA_CERT_CREATE:
114
	case CA_SERVER:
115
	case CA_CLIENT:
116
	case CA_OCSP:
117
		ca_certificate(ca, res->host, res->htype, res->action);
118
		break;
119
	case CA_CERT_DELETE:
120
		ca_delkey(ca, res->host);
121
		break;
122
	case CA_CERT_INSTALL:
123
		ca_cert_install(ca, res->host, res->path);
124
		break;
125
	case CA_CERT_EXPORT:
126
		ca_export(ca, res->host, res->peer, res->pass);
127
		break;
128
	case CA_CERT_REVOKE:
129
		ca_revoke(ca, res->host);
130
		break;
131
	case SHOW_CA_CERTIFICATES:
132
		ca_show_certs(ca, res->host);
133
		break;
134
	case CA_KEY_CREATE:
135
		ca_key_create(ca, res->host);
136
		break;
137
	case CA_KEY_DELETE:
138
		ca_key_delete(ca, res->host);
139
		break;
140
	case CA_KEY_INSTALL:
141
		ca_key_install(ca, res->host, res->path);
142
		break;
143
	case CA_KEY_IMPORT:
144
		ca_key_import(ca, res->host, res->path);
145
		break;
146
	default:
147
		break;
148
	}
149
150
	return (0);
151
}
152
153
int
154
main(int argc, char *argv[])
155
{
156
	struct sockaddr_un	 sun;
157
	struct parse_result	*res;
158
	struct imsg		 imsg;
159
	int			 ctl_sock;
160
	int			 done = 1;
161
	int			 n;
162
	int			 ch;
163
	int			 v = 0;
164
	int			 quiet = 0;
165
	const char		*sock = IKED_SOCKET;
166
167
	while ((ch = getopt(argc, argv, "qs:")) != -1) {
168
		switch (ch) {
169
		case 'q':
170
			quiet = 1;
171
			break;
172
		case 's':
173
			sock = optarg;
174
			break;
175
		default:
176
			usage();
177
			/* NOTREACHED */
178
		}
179
	}
180
	argc -= optind;
181
	argv += optind;
182
183
	/* parse options */
184
	if ((res = parse(argc, argv)) == NULL)
185
		exit(1);
186
187
	res->quiet = quiet;
188
189
	switch (res->action) {
190
	case CA_CREATE:
191
	case CA_DELETE:
192
	case CA_INSTALL:
193
	case CA_EXPORT:
194
	case CA_CERT_CREATE:
195
	case CA_CLIENT:
196
	case CA_SERVER:
197
	case CA_OCSP:
198
	case CA_CERT_DELETE:
199
	case CA_CERT_INSTALL:
200
	case CA_CERT_EXPORT:
201
	case CA_CERT_REVOKE:
202
	case SHOW_CA:
203
	case SHOW_CA_CERTIFICATES:
204
	case CA_KEY_CREATE:
205
	case CA_KEY_DELETE:
206
	case CA_KEY_INSTALL:
207
	case CA_KEY_IMPORT:
208
		if (pledge("stdio proc exec rpath wpath cpath fattr tty flock", NULL)
209
		    == -1)
210
			err(1, "pledge");
211
		ca_opt(res);
212
		break;
213
	case NONE:
214
		usage();
215
		break;
216
	default:
217
		goto connect;
218
	}
219
220
	return (0);
221
222
 connect:
223
	/* connect to iked control socket */
224
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
225
		err(1, "socket");
226
227
	bzero(&sun, sizeof(sun));
228
	sun.sun_family = AF_UNIX;
229
	strlcpy(sun.sun_path, sock, sizeof(sun.sun_path));
230
 reconnect:
231
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
232
		/* Keep retrying if running in monitor mode */
233
		if (res->action == MONITOR &&
234
		    (errno == ENOENT || errno == ECONNREFUSED)) {
235
			usleep(100);
236
			goto reconnect;
237
		}
238
		err(1, "connect: %s", sock);
239
	}
240
241
	if (pledge("stdio flock rpath cpath wpath", NULL) == -1)
242
		err(1, "pledge");
243
244
	if (res->ibuf != NULL)
245
		ibuf = res->ibuf;
246
	else
247
		if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
248
			err(1, "malloc");
249
	imsg_init(ibuf, ctl_sock);
250
251
	/* process user request */
252
	switch (res->action) {
253
	case RESETALL:
254
		v = RESET_ALL;
255
		break;
256
	case RESETCA:
257
		v = RESET_CA;
258
		break;
259
	case RESETPOLICY:
260
		v = RESET_POLICY;
261
		break;
262
	case RESETSA:
263
		v = RESET_SA;
264
		break;
265
	case RESETUSER:
266
		v = RESET_USER;
267
		break;
268
	case LOG_VERBOSE:
269
		v = 2;
270
		break;
271
	case LOG_BRIEF:
272
	default:
273
		v = 0;
274
		break;
275
	}
276
277
	switch (res->action) {
278
	case NONE:
279
		usage();
280
		/* NOTREACHED */
281
		break;
282
	case RESETALL:
283
	case RESETCA:
284
	case RESETPOLICY:
285
	case RESETSA:
286
	case RESETUSER:
287
		imsg_compose(ibuf, IMSG_CTL_RESET, 0, 0, -1, &v, sizeof(v));
288
		printf("reset request sent.\n");
289
		break;
290
	case LOAD:
291
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1,
292
		    res->path, strlen(res->path));
293
		break;
294
	case RELOAD:
295
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
296
		break;
297
	case MONITOR:
298
		imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
299
		done = 0;
300
		break;
301
	case COUPLE:
302
		imsg_compose(ibuf, IMSG_CTL_COUPLE, 0, 0, -1, NULL, 0);
303
		break;
304
	case DECOUPLE:
305
		imsg_compose(ibuf, IMSG_CTL_DECOUPLE, 0, 0, -1, NULL, 0);
306
		break;
307
	case ACTIVE:
308
		imsg_compose(ibuf, IMSG_CTL_ACTIVE, 0, 0, -1, NULL, 0);
309
		break;
310
	case PASSIVE:
311
		imsg_compose(ibuf, IMSG_CTL_PASSIVE, 0, 0, -1, NULL, 0);
312
		break;
313
	case LOG_VERBOSE:
314
	case LOG_BRIEF:
315
		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &v, sizeof(v));
316
		printf("logging request sent.\n");
317
		break;
318
	default:
319
		break;
320
	}
321
322
	while (ibuf->w.queued)
323
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
324
			err(1, "write error");
325
326
	while (!done) {
327
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
328
			errx(1, "imsg_read error");
329
		if (n == 0)
330
			errx(1, "pipe closed");
331
332
		while (!done) {
333
			if ((n = imsg_get(ibuf, &imsg)) == -1)
334
				errx(1, "imsg_get error");
335
			if (n == 0)
336
				break;
337
			switch (res->action) {
338
			case MONITOR:
339
				done = monitor(&imsg);
340
				break;
341
			default:
342
				break;
343
			}
344
			imsg_free(&imsg);
345
		}
346
	}
347
	close(ctl_sock);
348
	free(ibuf);
349
350
	return (0);
351
}
352
353
struct imsgname *
354
monitor_lookup(uint8_t type)
355
{
356
	int i;
357
358
	for (i = 0; imsgs[i].name != NULL; i++)
359
		if (imsgs[i].type == type)
360
			return (&imsgs[i]);
361
	return (&imsgunknown);
362
}
363
364
int
365
monitor(struct imsg *imsg)
366
{
367
	time_t			 now;
368
	int			 done = 0;
369
	struct imsgname		*imn;
370
371
	now = time(NULL);
372
373
	imn = monitor_lookup(imsg->hdr.type);
374
	printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name,
375
	    imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid);
376
	printf("\ttimestamp: %lld, %s", (long long)now, ctime(&now));
377
	if (imn->type == -1)
378
		done = 1;
379
	if (imn->func != NULL)
380
		(*imn->func)(imsg);
381
382
	return (done);
383
}