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", 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", 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 } 384