xref: /openbsd/usr.sbin/ikectl/ikectl.c (revision 4bdff4be)
1 /*	$OpenBSD: ikectl.c,v 1.30 2022/12/04 11:54:31 tobhe 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		 show_string(struct imsg *);
52 int		 show_stats(struct imsg *, int);
53 
54 int		 ca_opt(struct parse_result *);
55 
56 struct imsgname imsgs[] = {
57 	{ IMSG_CTL_OK,			"ok",			NULL },
58 	{ IMSG_CTL_FAIL,		"fail",			NULL },
59 	{ IMSG_CTL_VERBOSE,		"verbose",		NULL },
60 	{ IMSG_CTL_RELOAD,		"reload",		NULL },
61 	{ IMSG_CTL_RESET,		"reset",		NULL },
62 	{ IMSG_CTL_SHOW_SA,		"show sa",		NULL },
63 	{ IMSG_CTL_SHOW_CERTSTORE,	"show certstore",	NULL },
64 	{ 0,				NULL,			NULL }
65 
66 };
67 struct imsgname imsgunknown = {
68 	-1,				"<unknown>",		NULL
69 };
70 
71 struct imsgbuf	*ibuf;
72 
73 __dead void
74 usage(void)
75 {
76 	extern char *__progname;
77 
78 	fprintf(stderr, "usage: %s [-q] [-s socket] command [arg ...]\n",
79 	    __progname);
80 	exit(1);
81 }
82 
83 int
84 ca_opt(struct parse_result *res)
85 {
86 	struct ca	*ca;
87 	size_t		 len;
88 	char		*p;
89 
90 	ca = ca_setup(res->caname, (res->action == CA_CREATE),
91 	    res->quiet, res->pass);
92 	if (ca == NULL)
93 		errx(1, "ca_setup failed");
94 
95 	/* assume paths are relative to /etc if not absolute */
96 	if (res->path && (res->path[0] != '.') && (res->path[0] != '/')) {
97 		len = 5 + strlen(res->path) + 1;
98 		if ((p = malloc(len)) == NULL)
99 			err(1, "malloc");
100 		snprintf(p, len, "/etc/%s", res->path);
101 		free(res->path);
102 		res->path = p;
103 	}
104 
105 	switch (res->action) {
106 	case CA_CREATE:
107 		ca_create(ca);
108 		break;
109 	case CA_DELETE:
110 		ca_delete(ca);
111 		break;
112 	case CA_INSTALL:
113 		ca_install(ca, res->path);
114 		break;
115 	case CA_EXPORT:
116 		ca_export(ca, NULL, res->peer, res->pass);
117 		break;
118 	case CA_CERT_CREATE:
119 	case CA_SERVER:
120 	case CA_CLIENT:
121 	case CA_OCSP:
122 		ca_certificate(ca, res->host, res->htype, res->action);
123 		break;
124 	case CA_CERT_DELETE:
125 		ca_delkey(ca, res->host);
126 		break;
127 	case CA_CERT_INSTALL:
128 		ca_cert_install(ca, res->host, res->path);
129 		break;
130 	case CA_CERT_EXPORT:
131 		ca_export(ca, res->host, res->peer, res->pass);
132 		break;
133 	case CA_CERT_REVOKE:
134 		ca_revoke(ca, res->host);
135 		break;
136 	case SHOW_CA_CERTIFICATES:
137 		ca_show_certs(ca, res->host);
138 		break;
139 	case CA_KEY_CREATE:
140 		ca_key_create(ca, res->host);
141 		break;
142 	case CA_KEY_DELETE:
143 		ca_key_delete(ca, res->host);
144 		break;
145 	case CA_KEY_INSTALL:
146 		ca_key_install(ca, res->host, res->path);
147 		break;
148 	case CA_KEY_IMPORT:
149 		ca_key_import(ca, res->host, res->path);
150 		break;
151 	default:
152 		break;
153 	}
154 
155 	return (0);
156 }
157 
158 int
159 main(int argc, char *argv[])
160 {
161 	struct sockaddr_un	 s_un;
162 	struct parse_result	*res;
163 	struct imsg		 imsg;
164 	int			 ctl_sock;
165 	int			 done = 1;
166 	int			 n;
167 	int			 ch;
168 	int			 v = 0;
169 	int			 quiet = 0;
170 	const char		*sock = IKED_SOCKET;
171 
172 	while ((ch = getopt(argc, argv, "qs:")) != -1) {
173 		switch (ch) {
174 		case 'q':
175 			quiet = 1;
176 			break;
177 		case 's':
178 			sock = optarg;
179 			break;
180 		default:
181 			usage();
182 			/* NOTREACHED */
183 		}
184 	}
185 	argc -= optind;
186 	argv += optind;
187 
188 	/* parse options */
189 	if ((res = parse(argc, argv)) == NULL)
190 		exit(1);
191 
192 	res->quiet = quiet;
193 
194 	switch (res->action) {
195 	case CA_CREATE:
196 	case CA_DELETE:
197 	case CA_INSTALL:
198 	case CA_EXPORT:
199 	case CA_CERT_CREATE:
200 	case CA_CLIENT:
201 	case CA_SERVER:
202 	case CA_OCSP:
203 	case CA_CERT_DELETE:
204 	case CA_CERT_INSTALL:
205 	case CA_CERT_EXPORT:
206 	case CA_CERT_REVOKE:
207 	case SHOW_CA:
208 	case SHOW_CA_CERTIFICATES:
209 	case CA_KEY_CREATE:
210 	case CA_KEY_DELETE:
211 	case CA_KEY_INSTALL:
212 	case CA_KEY_IMPORT:
213 		if (pledge("stdio proc exec rpath wpath cpath fattr tty", NULL)
214 		    == -1)
215 			err(1, "pledge");
216 		ca_opt(res);
217 		break;
218 	case NONE:
219 		usage();
220 		break;
221 	default:
222 		goto connect;
223 	}
224 
225 	return (0);
226 
227  connect:
228 	/* connect to iked control socket */
229 	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
230 		err(1, "socket");
231 
232 	bzero(&s_un, sizeof(s_un));
233 	s_un.sun_family = AF_UNIX;
234 	strlcpy(s_un.sun_path, sock, sizeof(s_un.sun_path));
235  reconnect:
236 	if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
237 		/* Keep retrying if running in monitor mode */
238 		if (res->action == MONITOR &&
239 		    (errno == ENOENT || errno == ECONNREFUSED)) {
240 			usleep(100);
241 			goto reconnect;
242 		}
243 		err(1, "connect: %s", sock);
244 	}
245 
246 	if (pledge("stdio", NULL) == -1)
247 		err(1, "pledge");
248 
249 	if (res->ibuf != NULL)
250 		ibuf = res->ibuf;
251 	else
252 		if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
253 			err(1, "malloc");
254 	imsg_init(ibuf, ctl_sock);
255 
256 	/* process user request */
257 	switch (res->action) {
258 	case RESETALL:
259 		v = RESET_ALL;
260 		break;
261 	case RESETCA:
262 		v = RESET_CA;
263 		break;
264 	case RESETPOLICY:
265 		v = RESET_POLICY;
266 		break;
267 	case RESETSA:
268 		v = RESET_SA;
269 		break;
270 	case RESETUSER:
271 		v = RESET_USER;
272 		break;
273 	case LOG_VERBOSE:
274 		v = 2;
275 		break;
276 	case LOG_BRIEF:
277 	default:
278 		v = 0;
279 		break;
280 	}
281 
282 	switch (res->action) {
283 	case NONE:
284 		usage();
285 		/* NOTREACHED */
286 		break;
287 	case RESETALL:
288 	case RESETCA:
289 	case RESETPOLICY:
290 	case RESETSA:
291 	case RESETUSER:
292 		imsg_compose(ibuf, IMSG_CTL_RESET, 0, 0, -1, &v, sizeof(v));
293 		printf("reset request sent.\n");
294 		break;
295 	case LOAD:
296 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1,
297 		    res->path, strlen(res->path));
298 		break;
299 	case RESET_ID:
300 		imsg_compose(ibuf, IMSG_CTL_RESET_ID, 0, 0, -1,
301 		    res->id, strlen(res->id));
302 		break;
303 	case SHOW_SA:
304 		imsg_compose(ibuf, IMSG_CTL_SHOW_SA, 0, 0, -1, NULL, 0);
305 		done = 0;
306 		break;
307 	case SHOW_STATS:
308 		imsg_compose(ibuf, IMSG_CTL_SHOW_STATS, 0, 0, -1, NULL, 0);
309 		done = 0;
310 		break;
311 	case SHOW_CERTSTORE:
312 		imsg_compose(ibuf, IMSG_CTL_SHOW_CERTSTORE, 0, 0, -1, NULL, 0);
313 		done = 0;
314 		break;
315 	case RELOAD:
316 		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
317 		break;
318 	case MONITOR:
319 		imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
320 		done = 0;
321 		break;
322 	case COUPLE:
323 		imsg_compose(ibuf, IMSG_CTL_COUPLE, 0, 0, -1, NULL, 0);
324 		break;
325 	case DECOUPLE:
326 		imsg_compose(ibuf, IMSG_CTL_DECOUPLE, 0, 0, -1, NULL, 0);
327 		break;
328 	case ACTIVE:
329 		imsg_compose(ibuf, IMSG_CTL_ACTIVE, 0, 0, -1, NULL, 0);
330 		break;
331 	case PASSIVE:
332 		imsg_compose(ibuf, IMSG_CTL_PASSIVE, 0, 0, -1, NULL, 0);
333 		break;
334 	case LOG_VERBOSE:
335 	case LOG_BRIEF:
336 		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &v, sizeof(v));
337 		printf("logging request sent.\n");
338 		break;
339 	default:
340 		break;
341 	}
342 
343 	while (ibuf->w.queued)
344 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
345 			err(1, "write error");
346 
347 	while (!done) {
348 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
349 			errx(1, "imsg_read error");
350 		if (n == 0)
351 			errx(1, "pipe closed");
352 
353 		while (!done) {
354 			if ((n = imsg_get(ibuf, &imsg)) == -1)
355 				errx(1, "imsg_get error");
356 			if (n == 0)
357 				break;
358 			switch (res->action) {
359 			case MONITOR:
360 				done = monitor(&imsg);
361 				break;
362 			case SHOW_STATS:
363 				done = show_stats(&imsg, quiet);
364 				break;
365 			case SHOW_SA:
366 			case SHOW_CERTSTORE:
367 				done = show_string(&imsg);
368 				break;
369 			default:
370 				break;
371 			}
372 			imsg_free(&imsg);
373 		}
374 	}
375 	close(ctl_sock);
376 	free(ibuf);
377 
378 	return (0);
379 }
380 
381 struct imsgname *
382 monitor_lookup(uint8_t type)
383 {
384 	int i;
385 
386 	for (i = 0; imsgs[i].name != NULL; i++)
387 		if (imsgs[i].type == type)
388 			return (&imsgs[i]);
389 	return (&imsgunknown);
390 }
391 
392 int
393 monitor(struct imsg *imsg)
394 {
395 	time_t			 now;
396 	int			 done = 0;
397 	struct imsgname		*imn;
398 
399 	now = time(NULL);
400 
401 	imn = monitor_lookup(imsg->hdr.type);
402 	printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name,
403 	    imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid);
404 	printf("\ttimestamp: %lld, %s", (long long)now, ctime(&now));
405 	if (imn->type == -1)
406 		done = 1;
407 	if (imn->func != NULL)
408 		(*imn->func)(imsg);
409 
410 	return (done);
411 }
412 
413 int
414 show_string(struct imsg *imsg)
415 {
416 	int	done = 0;
417 
418 	switch (imsg->hdr.type) {
419 	case IMSG_CTL_SHOW_SA:
420 	case IMSG_CTL_SHOW_CERTSTORE:
421 		break;
422 	default:
423 		return (done);
424 	}
425 	if (IMSG_DATA_SIZE(imsg) > 0)
426 		printf("%s", (char *)imsg->data);
427 	else
428 		done = 1;
429 
430 	return (done);
431 }
432 
433 static char *
434 plural(uint64_t n)
435 {
436         return (n != 1 ? "s" : "");
437 }
438 
439 /*
440  * Dump IKE statistics structure.
441  */
442 int
443 show_stats(struct imsg *imsg, int quiet)
444 {
445 	struct iked_stats *stat;
446 	int		 done = 1;
447 
448 	if (IMSG_DATA_SIZE(imsg) != sizeof(*stat))
449 		return (done);
450 	stat = imsg->data;
451 	printf("ike:\n");
452 #define p(f, m) if (stat->f || !quiet) \
453 	printf(m, stat->f, plural(stat->f))
454 
455 	p(ikes_sa_created, "\t%llu IKE SA%s created\n");
456 	p(ikes_sa_established_total, "\t%llu IKE SA%s established\n");
457 	p(ikes_sa_established_current, "\t%llu IKE SA%s currently established\n");
458 	p(ikes_sa_established_failures, "\t%llu IKE SA%s failed to establish\n");
459 	p(ikes_sa_proposals_negotiate_failures, "\t%llu failed proposal negotiation%s\n");
460 	p(ikes_sa_rekeyed, "\t%llu IKE SA%s rekeyed\n");
461 	p(ikes_sa_removed, "\t%llu IKE SA%s removed\n");
462 	p(ikes_csa_created, "\t%llu Child SA%s created\n");
463 	p(ikes_csa_removed, "\t%llu Child SA%s removed\n");
464 	p(ikes_msg_sent, "\t%llu message%s sent\n");
465 	p(ikes_msg_send_failures, "\t%llu message%s could not be sent\n");
466 	p(ikes_msg_rcvd, "\t%llu message%s received\n");
467 	p(ikes_msg_rcvd_dropped, "\t%llu message%s dropped\n");
468 	p(ikes_msg_rcvd_busy, "\t%llu request%s dropped, response being worked on\n");
469 	p(ikes_retransmit_response, "\t%llu response%s retransmitted\n");
470 	p(ikes_retransmit_request, "\t%llu request%s retransmitted\n");
471 	p(ikes_retransmit_limit, "\t%llu request%s timed out\n");
472 	p(ikes_frag_sent, "\t%llu fragment%s sent\n");
473 	p(ikes_frag_send_failures, "\t%llu fragment%s could not be sent\n");
474 	p(ikes_frag_rcvd, "\t%llu fragment%s received\n");
475 	p(ikes_frag_rcvd_drop, "\t%llu fragment%s dropped\n");
476 	p(ikes_frag_reass_ok, "\t%llu fragment%s reassembled\n");
477 	p(ikes_frag_reass_drop, "\t%llu fragment%s could not be reassembled\n");
478 	p(ikes_update_addresses_sent, "\t%llu update addresses request%s sent\n");
479 	p(ikes_dpd_sent, "\t%llu dpd request%s sent\n");
480 	p(ikes_keepalive_sent, "\t%llu keepalive message%s sent\n");
481 #undef p
482 	return (done);
483 }
484