1 /* $OpenBSD: ikectl.c,v 1.13 2012/05/02 18:01:25 gsoares Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> 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 struct snmpd *env; 69 70 __dead void 71 usage(void) 72 { 73 extern char *__progname; 74 75 fprintf(stderr, "usage: %s [-q] [-s socket] command [arg ...]\n", 76 __progname); 77 exit(1); 78 } 79 80 int 81 ca_opt(struct parse_result *res) 82 { 83 struct ca *ca; 84 size_t len; 85 char *p; 86 87 ca = ca_setup(res->caname, (res->action == CA_CREATE), 88 res->quiet, res->pass); 89 if (ca == NULL) 90 errx(1, "ca_setup failed"); 91 92 /* assume paths are relative to /etc if not absolute */ 93 if (res->path && (res->path[0] != '.') && (res->path[0] != '/')) { 94 len = 5 + strlen(res->path) + 1; 95 if ((p = malloc(len)) == NULL) 96 err(1, "malloc"); 97 snprintf(p, len, "/etc/%s", res->path); 98 free(res->path); 99 res->path = p; 100 } 101 102 switch (res->action) { 103 case CA_CREATE: 104 ca_create(ca); 105 break; 106 case CA_DELETE: 107 ca_delete(ca); 108 break; 109 case CA_INSTALL: 110 ca_install(ca, res->path); 111 break; 112 case CA_EXPORT: 113 ca_export(ca, NULL, res->peer, res->pass); 114 break; 115 case CA_CERT_CREATE: 116 case CA_SERVER: 117 case CA_CLIENT: 118 ca_certificate(ca, res->host, res->htype, res->action); 119 break; 120 case CA_CERT_DELETE: 121 ca_delkey(ca, res->host); 122 break; 123 case CA_CERT_INSTALL: 124 ca_cert_install(ca, res->host, res->path); 125 break; 126 case CA_CERT_EXPORT: 127 ca_export(ca, res->host, res->peer, res->pass); 128 break; 129 case CA_CERT_REVOKE: 130 ca_revoke(ca, res->host); 131 break; 132 case SHOW_CA_CERTIFICATES: 133 ca_show_certs(ca, res->host); 134 break; 135 case CA_KEY_CREATE: 136 ca_key_create(ca, res->host); 137 break; 138 case CA_KEY_DELETE: 139 ca_key_delete(ca, res->host); 140 break; 141 case CA_KEY_INSTALL: 142 ca_key_install(ca, res->host, res->path); 143 break; 144 case CA_KEY_IMPORT: 145 ca_key_import(ca, res->host, res->path); 146 break; 147 default: 148 break; 149 } 150 151 return (0); 152 } 153 154 int 155 main(int argc, char *argv[]) 156 { 157 struct sockaddr_un sun; 158 struct parse_result *res; 159 struct imsg imsg; 160 int ctl_sock; 161 int done = 1; 162 int n; 163 int ch; 164 int v = 0; 165 int quiet = 0; 166 const char *sock = IKED_SOCKET; 167 168 if ((env = calloc(1, sizeof(struct snmpd *))) == NULL) 169 err(1, "calloc"); 170 171 while ((ch = getopt(argc, argv, "qs:")) != -1) { 172 switch (ch) { 173 case 'q': 174 quiet = 1; 175 break; 176 case 's': 177 sock = optarg; 178 break; 179 default: 180 usage(); 181 /* NOTREACHED */ 182 } 183 } 184 argc -= optind; 185 argv += optind; 186 187 /* parse options */ 188 if ((res = parse(argc, argv)) == NULL) 189 exit(1); 190 191 res->quiet = quiet; 192 193 switch (res->action) { 194 case CA_CREATE: 195 case CA_DELETE: 196 case CA_INSTALL: 197 case CA_EXPORT: 198 case CA_CERT_CREATE: 199 case CA_CLIENT: 200 case CA_SERVER: 201 case CA_CERT_DELETE: 202 case CA_CERT_INSTALL: 203 case CA_CERT_EXPORT: 204 case CA_CERT_REVOKE: 205 case SHOW_CA: 206 case SHOW_CA_CERTIFICATES: 207 case CA_KEY_CREATE: 208 case CA_KEY_DELETE: 209 case CA_KEY_INSTALL: 210 case CA_KEY_IMPORT: 211 ca_opt(res); 212 break; 213 case NONE: 214 usage(); 215 break; 216 default: 217 goto connect; 218 } 219 220 free(env); 221 return (0); 222 223 connect: 224 /* connect to iked control socket */ 225 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 226 err(1, "socket"); 227 228 bzero(&sun, sizeof(sun)); 229 sun.sun_family = AF_UNIX; 230 strlcpy(sun.sun_path, sock, sizeof(sun.sun_path)); 231 reconnect: 232 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 233 /* Keep retrying if running in monitor mode */ 234 if (res->action == MONITOR && 235 (errno == ENOENT || errno == ECONNREFUSED)) { 236 usleep(100); 237 goto reconnect; 238 } 239 err(1, "connect: %s", sock); 240 } 241 242 if (res->ibuf != NULL) 243 ibuf = res->ibuf; 244 else 245 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 246 err(1, "malloc"); 247 imsg_init(ibuf, ctl_sock); 248 249 /* process user request */ 250 switch (res->action) { 251 case RESETALL: 252 v = RESET_ALL; 253 break; 254 case RESETCA: 255 v = RESET_CA; 256 break; 257 case RESETPOLICY: 258 v = RESET_POLICY; 259 break; 260 case RESETSA: 261 v = RESET_SA; 262 break; 263 case RESETUSER: 264 v = RESET_USER; 265 break; 266 case LOG_VERBOSE: 267 v = 2; 268 break; 269 case LOG_BRIEF: 270 default: 271 v = 0; 272 break; 273 } 274 275 switch (res->action) { 276 case NONE: 277 usage(); 278 /* NOTREACHED */ 279 break; 280 case RESETALL: 281 case RESETCA: 282 case RESETPOLICY: 283 case RESETSA: 284 case RESETUSER: 285 imsg_compose(ibuf, IMSG_CTL_RESET, 0, 0, -1, &v, sizeof(v)); 286 printf("reset request sent.\n"); 287 break; 288 case LOAD: 289 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, 290 res->path, strlen(res->path)); 291 break; 292 case RELOAD: 293 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 294 break; 295 case MONITOR: 296 imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0); 297 done = 0; 298 break; 299 case COUPLE: 300 imsg_compose(ibuf, IMSG_CTL_COUPLE, 0, 0, -1, NULL, 0); 301 break; 302 case DECOUPLE: 303 imsg_compose(ibuf, IMSG_CTL_DECOUPLE, 0, 0, -1, NULL, 0); 304 break; 305 case ACTIVE: 306 imsg_compose(ibuf, IMSG_CTL_ACTIVE, 0, 0, -1, NULL, 0); 307 break; 308 case PASSIVE: 309 imsg_compose(ibuf, IMSG_CTL_PASSIVE, 0, 0, -1, NULL, 0); 310 break; 311 case LOG_VERBOSE: 312 case LOG_BRIEF: 313 imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &v, sizeof(v)); 314 printf("logging request sent.\n"); 315 break; 316 default: 317 break; 318 } 319 320 while (ibuf->w.queued) 321 if (msgbuf_write(&ibuf->w) < 0) 322 err(1, "write error"); 323 324 while (!done) { 325 if ((n = imsg_read(ibuf)) == -1) 326 errx(1, "imsg_read error"); 327 if (n == 0) 328 errx(1, "pipe closed"); 329 330 while (!done) { 331 if ((n = imsg_get(ibuf, &imsg)) == -1) 332 errx(1, "imsg_get error"); 333 if (n == 0) 334 break; 335 switch (res->action) { 336 case MONITOR: 337 done = monitor(&imsg); 338 break; 339 default: 340 break; 341 } 342 imsg_free(&imsg); 343 } 344 } 345 close(ctl_sock); 346 free(ibuf); 347 348 return (0); 349 } 350 351 struct imsgname * 352 monitor_lookup(u_int8_t type) 353 { 354 int i; 355 356 for (i = 0; imsgs[i].name != NULL; i++) 357 if (imsgs[i].type == type) 358 return (&imsgs[i]); 359 return (&imsgunknown); 360 } 361 362 int 363 monitor(struct imsg *imsg) 364 { 365 time_t now; 366 int done = 0; 367 struct imsgname *imn; 368 369 now = time(NULL); 370 371 imn = monitor_lookup(imsg->hdr.type); 372 printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name, 373 imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid); 374 printf("\ttimestamp: %u, %s", now, ctime(&now)); 375 if (imn->type == -1) 376 done = 1; 377 if (imn->func != NULL) 378 (*imn->func)(imsg); 379 380 return (done); 381 } 382