1 /* $OpenBSD: ikectl.c,v 1.18 2013/11/14 20:48:52 deraadt 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/param.h> 23 #include <sys/types.h> 24 #include <sys/socket.h> 25 #include <sys/queue.h> 26 #include <sys/un.h> 27 #include <sys/tree.h> 28 29 #include <err.h> 30 #include <errno.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 #include <event.h> 36 37 #include "iked.h" 38 #include "parser.h" 39 40 __dead void usage(void); 41 42 struct imsgname { 43 int type; 44 char *name; 45 void (*func)(struct imsg *); 46 }; 47 48 struct imsgname *monitor_lookup(u_int8_t); 49 void monitor_id(struct imsg *); 50 int monitor(struct imsg *); 51 52 int ca_opt(struct parse_result *); 53 54 struct imsgname imsgs[] = { 55 { IMSG_CTL_OK, "ok", NULL }, 56 { IMSG_CTL_FAIL, "fail", NULL }, 57 { IMSG_CTL_VERBOSE, "verbose", NULL }, 58 { IMSG_CTL_RELOAD, "reload", NULL }, 59 { IMSG_CTL_RESET, "reset", NULL }, 60 { 0, NULL, NULL } 61 62 }; 63 struct imsgname imsgunknown = { 64 -1, "<unknown>", NULL 65 }; 66 67 struct imsgbuf *ibuf; 68 69 __dead void 70 usage(void) 71 { 72 extern char *__progname; 73 74 fprintf(stderr, "usage: %s [-q] [-s socket] command [arg ...]\n", 75 __progname); 76 exit(1); 77 } 78 79 int 80 ca_opt(struct parse_result *res) 81 { 82 struct ca *ca; 83 size_t len; 84 char *p; 85 86 ca = ca_setup(res->caname, (res->action == CA_CREATE), 87 res->quiet, res->pass); 88 if (ca == NULL) 89 errx(1, "ca_setup failed"); 90 91 /* assume paths are relative to /etc if not absolute */ 92 if (res->path && (res->path[0] != '.') && (res->path[0] != '/')) { 93 len = 5 + strlen(res->path) + 1; 94 if ((p = malloc(len)) == NULL) 95 err(1, "malloc"); 96 snprintf(p, len, "/etc/%s", res->path); 97 free(res->path); 98 res->path = p; 99 } 100 101 switch (res->action) { 102 case CA_CREATE: 103 ca_create(ca); 104 break; 105 case CA_DELETE: 106 ca_delete(ca); 107 break; 108 case CA_INSTALL: 109 ca_install(ca, res->path); 110 break; 111 case CA_EXPORT: 112 ca_export(ca, NULL, res->peer, res->pass); 113 break; 114 case CA_CERT_CREATE: 115 case CA_SERVER: 116 case CA_CLIENT: 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_CERT_DELETE: 198 case CA_CERT_INSTALL: 199 case CA_CERT_EXPORT: 200 case CA_CERT_REVOKE: 201 case SHOW_CA: 202 case SHOW_CA_CERTIFICATES: 203 case CA_KEY_CREATE: 204 case CA_KEY_DELETE: 205 case CA_KEY_INSTALL: 206 case CA_KEY_IMPORT: 207 ca_opt(res); 208 break; 209 case NONE: 210 usage(); 211 break; 212 default: 213 goto connect; 214 } 215 216 return (0); 217 218 connect: 219 /* connect to iked control socket */ 220 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 221 err(1, "socket"); 222 223 bzero(&sun, sizeof(sun)); 224 sun.sun_family = AF_UNIX; 225 strlcpy(sun.sun_path, sock, sizeof(sun.sun_path)); 226 reconnect: 227 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 228 /* Keep retrying if running in monitor mode */ 229 if (res->action == MONITOR && 230 (errno == ENOENT || errno == ECONNREFUSED)) { 231 usleep(100); 232 goto reconnect; 233 } 234 err(1, "connect: %s", sock); 235 } 236 237 if (res->ibuf != NULL) 238 ibuf = res->ibuf; 239 else 240 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 241 err(1, "malloc"); 242 imsg_init(ibuf, ctl_sock); 243 244 /* process user request */ 245 switch (res->action) { 246 case RESETALL: 247 v = RESET_ALL; 248 break; 249 case RESETCA: 250 v = RESET_CA; 251 break; 252 case RESETPOLICY: 253 v = RESET_POLICY; 254 break; 255 case RESETSA: 256 v = RESET_SA; 257 break; 258 case RESETUSER: 259 v = RESET_USER; 260 break; 261 case LOG_VERBOSE: 262 v = 2; 263 break; 264 case LOG_BRIEF: 265 default: 266 v = 0; 267 break; 268 } 269 270 switch (res->action) { 271 case NONE: 272 usage(); 273 /* NOTREACHED */ 274 break; 275 case RESETALL: 276 case RESETCA: 277 case RESETPOLICY: 278 case RESETSA: 279 case RESETUSER: 280 imsg_compose(ibuf, IMSG_CTL_RESET, 0, 0, -1, &v, sizeof(v)); 281 printf("reset request sent.\n"); 282 break; 283 case LOAD: 284 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, 285 res->path, strlen(res->path)); 286 break; 287 case RELOAD: 288 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 289 break; 290 case MONITOR: 291 imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0); 292 done = 0; 293 break; 294 case COUPLE: 295 imsg_compose(ibuf, IMSG_CTL_COUPLE, 0, 0, -1, NULL, 0); 296 break; 297 case DECOUPLE: 298 imsg_compose(ibuf, IMSG_CTL_DECOUPLE, 0, 0, -1, NULL, 0); 299 break; 300 case ACTIVE: 301 imsg_compose(ibuf, IMSG_CTL_ACTIVE, 0, 0, -1, NULL, 0); 302 break; 303 case PASSIVE: 304 imsg_compose(ibuf, IMSG_CTL_PASSIVE, 0, 0, -1, NULL, 0); 305 break; 306 case LOG_VERBOSE: 307 case LOG_BRIEF: 308 imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &v, sizeof(v)); 309 printf("logging request sent.\n"); 310 break; 311 default: 312 break; 313 } 314 315 while (ibuf->w.queued) 316 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) 317 err(1, "write error"); 318 319 while (!done) { 320 if ((n = imsg_read(ibuf)) == -1) 321 errx(1, "imsg_read error"); 322 if (n == 0) 323 errx(1, "pipe closed"); 324 325 while (!done) { 326 if ((n = imsg_get(ibuf, &imsg)) == -1) 327 errx(1, "imsg_get error"); 328 if (n == 0) 329 break; 330 switch (res->action) { 331 case MONITOR: 332 done = monitor(&imsg); 333 break; 334 default: 335 break; 336 } 337 imsg_free(&imsg); 338 } 339 } 340 close(ctl_sock); 341 free(ibuf); 342 343 return (0); 344 } 345 346 struct imsgname * 347 monitor_lookup(u_int8_t type) 348 { 349 int i; 350 351 for (i = 0; imsgs[i].name != NULL; i++) 352 if (imsgs[i].type == type) 353 return (&imsgs[i]); 354 return (&imsgunknown); 355 } 356 357 int 358 monitor(struct imsg *imsg) 359 { 360 time_t now; 361 int done = 0; 362 struct imsgname *imn; 363 364 now = time(NULL); 365 366 imn = monitor_lookup(imsg->hdr.type); 367 printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name, 368 imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid); 369 printf("\ttimestamp: %lld, %s", (long long)now, ctime(&now)); 370 if (imn->type == -1) 371 done = 1; 372 if (imn->func != NULL) 373 (*imn->func)(imsg); 374 375 return (done); 376 } 377