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