1 /* $NetBSD: racoonctl.c,v 1.10 2008/03/06 00:46:04 mgrooms Exp $ */ 2 3 /* Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */ 4 5 /* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * Copyright (C) 2008 Timo Teras. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the project nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "config.h" 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/socket.h> 40 #include <sys/un.h> 41 42 #include <netinet/in.h> 43 #include <arpa/inet.h> 44 #include <net/pfkeyv2.h> 45 46 #include <stdlib.h> 47 #include <stdio.h> 48 #include <string.h> 49 #include <errno.h> 50 #if TIME_WITH_SYS_TIME 51 # include <sys/time.h> 52 # include <time.h> 53 #else 54 # if HAVE_SYS_TIME_H 55 # include <sys/time.h> 56 # else 57 # include <time.h> 58 # endif 59 #endif 60 #include <netdb.h> 61 #ifdef HAVE_UNISTD_H 62 #include <unistd.h> 63 #endif 64 #include <err.h> 65 #include <sys/ioctl.h> 66 #include <resolv.h> 67 68 #include "var.h" 69 #include "vmbuf.h" 70 #include "misc.h" 71 #include "gcmalloc.h" 72 73 #include "racoonctl.h" 74 #include "admin.h" 75 #include "schedule.h" 76 #include "handler.h" 77 #include "sockmisc.h" 78 #include "vmbuf.h" 79 #include "plog.h" 80 #include "isakmp_var.h" 81 #include "isakmp.h" 82 #include "isakmp_xauth.h" 83 #include "isakmp_cfg.h" 84 #include "isakmp_unity.h" 85 #include "ipsec_doi.h" 86 #include "evt.h" 87 88 char *adminsock_path = ADMINSOCK_PATH; 89 90 static void usage __P((void)); 91 static vchar_t *get_combuf __P((int, char **)); 92 static int handle_recv __P((vchar_t *)); 93 static vchar_t *f_reload __P((int, char **)); 94 static vchar_t *f_getsched __P((int, char **)); 95 static vchar_t *f_getsa __P((int, char **)); 96 static vchar_t *f_flushsa __P((int, char **)); 97 static vchar_t *f_deletesa __P((int, char **)); 98 static vchar_t *f_exchangesa __P((int, char **)); 99 static vchar_t *f_vpnc __P((int, char **)); 100 static vchar_t *f_vpnd __P((int, char **)); 101 static vchar_t *f_getevt __P((int, char **)); 102 #ifdef ENABLE_HYBRID 103 static vchar_t *f_logoutusr __P((int, char **)); 104 #endif 105 106 struct cmd_tag { 107 vchar_t *(*func) __P((int, char **)); 108 int cmd; 109 char *str; 110 } cmdtab[] = { 111 { f_reload, ADMIN_RELOAD_CONF, "reload-config" }, 112 { f_reload, ADMIN_RELOAD_CONF, "rc" }, 113 { f_getsched, ADMIN_SHOW_SCHED, "show-schedule" }, 114 { f_getsched, ADMIN_SHOW_SCHED, "sc" }, 115 { f_getsa, ADMIN_SHOW_SA, "show-sa" }, 116 { f_getsa, ADMIN_SHOW_SA, "ss" }, 117 { f_flushsa, ADMIN_FLUSH_SA, "flush-sa" }, 118 { f_flushsa, ADMIN_FLUSH_SA, "fs" }, 119 { f_deletesa, ADMIN_DELETE_SA, "delete-sa" }, 120 { f_deletesa, ADMIN_DELETE_SA, "ds" }, 121 { f_exchangesa, ADMIN_ESTABLISH_SA, "establish-sa" }, 122 { f_exchangesa, ADMIN_ESTABLISH_SA, "es" }, 123 { f_vpnc, ADMIN_ESTABLISH_SA, "vpn-connect" }, 124 { f_vpnc, ADMIN_ESTABLISH_SA, "vc" }, 125 { f_vpnd, ADMIN_DELETE_ALL_SA_DST,"vpn-disconnect" }, 126 { f_vpnd, ADMIN_DELETE_ALL_SA_DST,"vd" }, 127 { f_getevt, ADMIN_SHOW_EVT, "show-event" }, 128 { f_getevt, ADMIN_SHOW_EVT, "se" }, 129 #ifdef ENABLE_HYBRID 130 { f_logoutusr, ADMIN_LOGOUT_USER, "logout-user" }, 131 { f_logoutusr, ADMIN_LOGOUT_USER, "lu" }, 132 #endif 133 { NULL, 0, NULL }, 134 }; 135 136 struct evtmsg { 137 int type; 138 char *msg; 139 } evtmsg[] = { 140 { EVT_RACOON_QUIT, "Racoon terminated" }, 141 142 { EVT_PHASE1_UP, "Phase 1 established" }, 143 { EVT_PHASE1_DOWN, "Phase 1 deleted" }, 144 { EVT_PHASE1_NO_RESPONSE, "Phase 1 error: peer not responding" }, 145 { EVT_PHASE1_NO_PROPOSAL, "Phase 1 error: no proposal chosen" }, 146 { EVT_PHASE1_AUTH_FAILED, 147 "Phase 1 error: authentication failed (bad certificate?)" }, 148 { EVT_PHASE1_DPD_TIMEOUT, "Phase 1 error: dead peer detected" }, 149 { EVT_PHASE1_MODE_CFG, "Phase 1 mode configuration done" }, 150 { EVT_PHASE1_XAUTH_SUCCESS, "Phase 1 Xauth succeeded" }, 151 { EVT_PHASE1_XAUTH_FAILED, "Phase 1 Xauth failed" }, 152 153 { EVT_PHASE2_NO_PHASE1, "Phase 2 error: no suitable phase 1" }, 154 { EVT_PHASE2_UP, "Phase 2 established" }, 155 { EVT_PHASE2_DOWN, "Phase 2 deleted" }, 156 { EVT_PHASE2_NO_RESPONSE, "Phase 2 error: no response" }, 157 }; 158 159 static int get_proto __P((char *)); 160 static vchar_t *get_index __P((int, char **)); 161 static int get_family __P((char *)); 162 static vchar_t *get_comindexes __P((int, int, char **)); 163 static int get_comindex __P((char *, char **, char **, char **)); 164 static int get_ulproto __P((char *)); 165 166 struct proto_tag { 167 int proto; 168 char *str; 169 } prototab[] = { 170 { ADMIN_PROTO_ISAKMP, "isakmp" }, 171 { ADMIN_PROTO_IPSEC, "ipsec" }, 172 { ADMIN_PROTO_AH, "ah" }, 173 { ADMIN_PROTO_ESP, "esp" }, 174 { ADMIN_PROTO_INTERNAL, "internal" }, 175 { 0, NULL }, 176 }; 177 178 struct ulproto_tag { 179 int ul_proto; 180 char *str; 181 } ulprototab[] = { 182 { 0, "any" }, 183 { IPPROTO_ICMP, "icmp" }, 184 { IPPROTO_TCP, "tcp" }, 185 { IPPROTO_UDP, "udp" }, 186 { IPPROTO_GRE, "gre" }, 187 { 0, NULL }, 188 }; 189 190 int so; 191 192 static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST]; 193 194 char *pname; 195 int long_format = 0; 196 int evt_quit_event = 0; 197 198 void dump_isakmp_sa __P((char *, int)); 199 void dump_internal __P((char *, int)); 200 char *pindex_isakmp __P((isakmp_index *)); 201 void print_schedule __P((caddr_t, int)); 202 void print_evt __P((struct evt_async *)); 203 char * fixed_addr __P((char *, char *, int)); 204 205 static void 206 usage() 207 { 208 printf( 209 "Usage:\n" 210 " %s reload-config\n" 211 " %s show-schedule\n" 212 " %s [-l [-l]] show-sa [protocol]\n" 213 " %s flush-sa [protocol]\n" 214 " %s delete-sa <saopts>\n" 215 " %s establish-sa [-u identity] [-w] <saopts>\n" 216 " %s vpn-connect [-u identity] vpn_gateway\n" 217 " %s vpn-disconnect vpn_gateway\n" 218 " %s show-event\n" 219 " %s logout-user login\n" 220 "\n" 221 " <protocol>: \"isakmp\", \"esp\" or \"ah\".\n" 222 " In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n" 223 "\n" 224 " <saopts>: \"isakmp\" <family> <src> <dst>\n" 225 " : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n" 226 " <ul_proto>\n" 227 " <family>: \"inet\" or \"inet6\"\n" 228 " <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n", 229 pname, pname, pname, pname, pname, pname, pname, pname, pname, pname); 230 } 231 232 /* 233 * Check for proper racoonctl interface 234 */ 235 #if ((RACOONCTL_INTERFACE_MAJOR != 1) || (RACOONCTL_INTERFACE < 20041230)) 236 #error "Incompatible racoonctl interface" 237 #endif 238 239 int 240 main(ac, av) 241 int ac; 242 char **av; 243 { 244 vchar_t *combuf; 245 int c; 246 247 pname = *av; 248 249 /* 250 * Check for proper racoonctl interface 251 */ 252 if ((racoonctl_interface_major != RACOONCTL_INTERFACE_MAJOR) || 253 (racoonctl_interface < RACOONCTL_INTERFACE)) 254 errx(1, "Incompatible racoonctl interface"); 255 256 #ifdef __linux__ 257 /* 258 * Disable GNU extensions that will prevent racoonct vc -u login 259 * from working (GNU getopt(3) does not like options after vc) 260 */ 261 setenv("POSIXLY_CORRECT", "1", 0); 262 #endif 263 while ((c = getopt(ac, av, "lds:")) != -1) { 264 switch(c) { 265 case 'l': 266 long_format++; 267 break; 268 269 case 'd': 270 loglevel++; 271 break; 272 273 case 's': 274 adminsock_path = optarg; 275 break; 276 277 default: 278 usage(); 279 exit(0); 280 } 281 } 282 283 ac -= optind; 284 av += optind; 285 286 combuf = get_combuf(ac, av); 287 if (!combuf) 288 err(1, "kmpstat"); 289 290 if (loglevel) 291 hexdump(combuf, ((struct admin_com *)combuf)->ac_len); 292 293 com_init(); 294 295 if (com_send(combuf) != 0) 296 goto bad; 297 298 vfree(combuf); 299 300 do { 301 if (com_recv(&combuf) != 0) 302 goto bad; 303 if (handle_recv(combuf) != 0) 304 goto bad; 305 vfree(combuf); 306 } while (evt_quit_event != 0); 307 308 close(so); 309 exit(0); 310 311 bad: 312 close(so); 313 if (errno == EEXIST) 314 exit(0); 315 exit(1); 316 } 317 318 /* %%% */ 319 /* 320 * return command buffer. 321 */ 322 static vchar_t * 323 get_combuf(ac, av) 324 int ac; 325 char **av; 326 { 327 struct cmd_tag *cp; 328 329 if (ac == 0) { 330 usage(); 331 exit(0); 332 } 333 334 /* checking the string of command. */ 335 for (cp = &cmdtab[0]; cp->str; cp++) { 336 if (strcmp(*av, cp->str) == 0) { 337 break; 338 } 339 } 340 if (!cp->str) { 341 printf("Invalid command [%s]\n", *av); 342 errno = EINVAL; 343 return NULL; 344 } 345 346 ac--; 347 av++; 348 return (cp->func)(ac, av); 349 } 350 351 static vchar_t * 352 make_request(u_int16_t cmd, u_int16_t proto, size_t len) 353 { 354 vchar_t *buf; 355 struct admin_com *head; 356 357 buf = vmalloc(sizeof(struct admin_com) + len); 358 if (buf == NULL) 359 errx(1, "not enough core"); 360 361 head = (struct admin_com *) buf->v; 362 head->ac_len = buf->l; 363 head->ac_cmd = ADMIN_FLAG_VERSION | cmd; 364 head->ac_version = 1; 365 head->ac_proto = proto; 366 367 return buf; 368 } 369 370 static vchar_t * 371 f_reload(ac, av) 372 int ac; 373 char **av; 374 { 375 return make_request(ADMIN_RELOAD_CONF, 0, 0); 376 } 377 378 static vchar_t * 379 f_getevt(ac, av) 380 int ac; 381 char **av; 382 { 383 evt_quit_event = -1; 384 if (ac >= 1) 385 errx(1, "too many arguments"); 386 387 return make_request(ADMIN_SHOW_EVT, 0, 0); 388 } 389 390 static vchar_t * 391 f_getsched(ac, av) 392 int ac; 393 char **av; 394 { 395 return make_request(ADMIN_SHOW_SCHED, 0, 0); 396 } 397 398 static vchar_t * 399 f_getsa(ac, av) 400 int ac; 401 char **av; 402 { 403 int proto; 404 405 /* need protocol */ 406 if (ac != 1) 407 errx(1, "insufficient arguments"); 408 proto = get_proto(*av); 409 if (proto == -1) 410 errx(1, "unknown protocol %s", *av); 411 412 return make_request(ADMIN_SHOW_SA, proto, 0); 413 } 414 415 static vchar_t * 416 f_flushsa(ac, av) 417 int ac; 418 char **av; 419 { 420 vchar_t *buf; 421 struct admin_com *head; 422 int proto; 423 424 /* need protocol */ 425 if (ac != 1) 426 errx(1, "insufficient arguments"); 427 proto = get_proto(*av); 428 if (proto == -1) 429 errx(1, "unknown protocol %s", *av); 430 431 return make_request(ADMIN_FLUSH_SA, proto, 0); 432 } 433 434 static vchar_t * 435 f_deletesa(ac, av) 436 int ac; 437 char **av; 438 { 439 vchar_t *buf, *index; 440 int proto; 441 442 /* need protocol */ 443 if (ac < 1) 444 errx(1, "insufficient arguments"); 445 proto = get_proto(*av); 446 if (proto == -1) 447 errx(1, "unknown protocol %s", *av); 448 449 /* get index(es) */ 450 av++; 451 ac--; 452 switch (proto) { 453 case ADMIN_PROTO_ISAKMP: 454 index = get_index(ac, av); 455 if (index == NULL) 456 return NULL; 457 break; 458 case ADMIN_PROTO_AH: 459 case ADMIN_PROTO_ESP: 460 index = get_index(ac, av); 461 if (index == NULL) 462 return NULL; 463 break; 464 default: 465 errno = EPROTONOSUPPORT; 466 return NULL; 467 } 468 469 buf = make_request(ADMIN_DELETE_SA, proto, index->l); 470 if (buf == NULL) 471 goto out; 472 473 memcpy(buf->v + sizeof(struct admin_com), index->v, index->l); 474 475 out: 476 if (index != NULL) 477 vfree(index); 478 479 return buf; 480 } 481 482 static vchar_t * 483 f_deleteallsadst(ac, av) 484 int ac; 485 char **av; 486 { 487 vchar_t *buf, *index; 488 int proto; 489 490 /* need protocol */ 491 if (ac < 1) 492 errx(1, "insufficient arguments"); 493 proto = get_proto(*av); 494 if (proto == -1) 495 errx(1, "unknown protocol %s", *av); 496 497 /* get index(es) */ 498 av++; 499 ac--; 500 switch (proto) { 501 case ADMIN_PROTO_ISAKMP: 502 index = get_index(ac, av); 503 if (index == NULL) 504 return NULL; 505 break; 506 case ADMIN_PROTO_AH: 507 case ADMIN_PROTO_ESP: 508 index = get_index(ac, av); 509 if (index == NULL) 510 return NULL; 511 break; 512 default: 513 errno = EPROTONOSUPPORT; 514 return NULL; 515 } 516 517 buf = make_request(ADMIN_DELETE_ALL_SA_DST, proto, index->l); 518 if (buf == NULL) 519 goto out; 520 521 memcpy(buf->v+sizeof(struct admin_com), index->v, index->l); 522 523 out: 524 if (index != NULL) 525 vfree(index); 526 527 return buf; 528 } 529 530 static vchar_t * 531 f_exchangesa(ac, av) 532 int ac; 533 char **av; 534 { 535 vchar_t *buf, *index; 536 int proto; 537 int cmd = ADMIN_ESTABLISH_SA; 538 size_t com_len = 0; 539 char *id = NULL; 540 char *key = NULL; 541 struct admin_com_psk *acp; 542 int wait = 0; 543 544 if (ac < 1) 545 errx(1, "insufficient arguments"); 546 547 /* Optional -u identity */ 548 if (strcmp(av[0], "-u") == 0) { 549 if (ac < 2) 550 errx(1, "-u require an argument"); 551 552 id = av[1]; 553 if ((key = getpass("Password: ")) == NULL) 554 errx(1, "getpass() failed: %s", strerror(errno)); 555 556 com_len += sizeof(*acp) + strlen(id) + 1 + strlen(key) + 1; 557 cmd = ADMIN_ESTABLISH_SA_PSK; 558 559 av += 2; 560 ac -= 2; 561 } 562 563 if (ac >= 1 && strcmp(av[0], "-w") == 0) { 564 wait = 1; 565 av++; 566 ac--; 567 } 568 569 /* need protocol */ 570 if (ac < 1) 571 errx(1, "insufficient arguments"); 572 if ((proto = get_proto(*av)) == -1) 573 errx(1, "unknown protocol %s", *av); 574 575 /* get index(es) */ 576 av++; 577 ac--; 578 switch (proto) { 579 case ADMIN_PROTO_ISAKMP: 580 index = get_index(ac, av); 581 if (index == NULL) 582 return NULL; 583 if (wait) 584 evt_quit_event = EVT_PHASE1_MODE_CFG; 585 break; 586 case ADMIN_PROTO_AH: 587 case ADMIN_PROTO_ESP: 588 index = get_index(ac, av); 589 if (index == NULL) 590 return NULL; 591 if (wait) 592 evt_quit_event = EVT_PHASE2_UP; 593 break; 594 default: 595 errno = EPROTONOSUPPORT; 596 return NULL; 597 } 598 599 com_len += index->l; 600 buf = make_request(cmd, proto, com_len); 601 if (buf == NULL) 602 errx(1, "Cannot allocate buffer"); 603 604 memcpy(buf->v+sizeof(struct admin_com), index->v, index->l); 605 606 if (id && key) { 607 char *data; 608 acp = (struct admin_com_psk *) 609 (buf->v + sizeof(struct admin_com) + index->l); 610 611 acp->id_type = IDTYPE_USERFQDN; 612 acp->id_len = strlen(id) + 1; 613 acp->key_len = strlen(key) + 1; 614 615 data = (char *)(acp + 1); 616 strcpy(data, id); 617 618 data = (char *)(data + acp->id_len); 619 strcpy(data, key); 620 } 621 622 vfree(index); 623 624 return buf; 625 } 626 627 static vchar_t * 628 f_vpnc(ac, av) 629 int ac; 630 char **av; 631 { 632 char *nav[] = {NULL, NULL, NULL, NULL, NULL, NULL}; 633 int nac = 0; 634 char *isakmp = "isakmp"; 635 char *inet = "inet"; 636 char *srcaddr; 637 struct addrinfo hints, *res; 638 struct sockaddr *src; 639 char *idx; 640 641 if (ac < 1) 642 errx(1, "insufficient arguments"); 643 644 evt_quit_event = EVT_PHASE1_MODE_CFG; 645 646 /* Optional -u identity */ 647 if (strcmp(av[0], "-u") == 0) { 648 if (ac < 2) 649 errx(1, "-u require an argument"); 650 651 nav[nac++] = av[0]; 652 nav[nac++] = av[1]; 653 654 ac -= 2; 655 av += 2; 656 } 657 658 if (ac < 1) 659 errx(1, "VPN gateway required"); 660 if (ac > 1) 661 warnx("Extra arguments"); 662 663 /* 664 * Find the source address 665 */ 666 memset(&hints, 0, sizeof(hints)); 667 hints.ai_family = PF_UNSPEC; 668 hints.ai_socktype = SOCK_DGRAM; 669 if (getaddrinfo(av[0], "4500", &hints, &res) != 0) 670 errx(1, "Cannot resolve destination address"); 671 672 if ((src = getlocaladdr(res->ai_addr)) == NULL) 673 errx(1, "cannot find source address"); 674 675 if ((srcaddr = saddr2str(src)) == NULL) 676 errx(1, "cannot read source address"); 677 678 /* We get "ip[port]" strip the port */ 679 if ((idx = index(srcaddr, '[')) == NULL) 680 errx(1, "unexpected source address format"); 681 *idx = '\0'; 682 683 nav[nac++] = isakmp; 684 nav[nac++] = inet; 685 nav[nac++] = srcaddr; 686 nav[nac++] = av[0]; 687 688 return f_exchangesa(nac, nav); 689 } 690 691 static vchar_t * 692 f_vpnd(ac, av) 693 int ac; 694 char **av; 695 { 696 char *nav[] = {NULL, NULL, NULL, NULL}; 697 int nac = 0; 698 char *isakmp = "isakmp"; 699 char *inet = "inet"; 700 char *anyaddr = "0.0.0.0"; 701 char *idx; 702 703 if (ac < 1) 704 errx(1, "VPN gateway required"); 705 if (ac > 1) 706 warnx("Extra arguments"); 707 708 evt_quit_event = EVT_PHASE1_DOWN; 709 710 nav[nac++] = isakmp; 711 nav[nac++] = inet; 712 nav[nac++] = anyaddr; 713 nav[nac++] = av[0]; 714 715 return f_deleteallsadst(nac, nav); 716 } 717 718 #ifdef ENABLE_HYBRID 719 static vchar_t * 720 f_logoutusr(ac, av) 721 int ac; 722 char **av; 723 { 724 vchar_t *buf; 725 char *user; 726 727 /* need username */ 728 if (ac < 1) 729 errx(1, "insufficient arguments"); 730 user = av[0]; 731 if ((user == NULL) || (strlen(user) > LOGINLEN)) 732 errx(1, "bad login (too long?)"); 733 734 buf = make_request(ADMIN_LOGOUT_USER, 0, 0); 735 if (buf == NULL) 736 return NULL; 737 738 strncpy(buf->v + sizeof(struct admin_com), user, LOGINLEN); 739 740 return buf; 741 } 742 #endif /* ENABLE_HYBRID */ 743 744 745 static int 746 get_proto(str) 747 char *str; 748 { 749 struct proto_tag *cp; 750 751 if (str == NULL) { 752 errno = EINVAL; 753 return -1; 754 } 755 756 /* checking the string of command. */ 757 for (cp = &prototab[0]; cp->str; cp++) { 758 if (strcmp(str, cp->str) == 0) 759 return cp->proto; 760 } 761 762 errno = EINVAL; 763 return -1; 764 } 765 766 static vchar_t * 767 get_index(ac, av) 768 int ac; 769 char **av; 770 { 771 int family; 772 773 if (ac != 3 && ac != 4) { 774 errno = EINVAL; 775 return NULL; 776 } 777 778 /* checking the string of family */ 779 family = get_family(*av); 780 if (family == -1) 781 return NULL; 782 av++; 783 ac--; 784 785 return get_comindexes(family, ac, av); 786 } 787 788 static int 789 get_family(str) 790 char *str; 791 { 792 if (strcmp("inet", str) == 0) 793 return AF_INET; 794 #ifdef INET6 795 else if (strcmp("inet6", str) == 0) 796 return AF_INET6; 797 #endif 798 errno = EAFNOSUPPORT; 799 return -1; 800 } 801 802 static vchar_t * 803 get_comindexes(family, ac, av) 804 int family; 805 int ac; 806 char **av; 807 { 808 vchar_t *buf; 809 struct admin_com_indexes *ci; 810 char *p_name = NULL, *p_port = NULL; 811 char *p_prefs = NULL, *p_prefd = NULL; 812 struct sockaddr *src = NULL, *dst = NULL; 813 int ulproto; 814 815 if (ac != 2 && ac != 3) { 816 errno = EINVAL; 817 return NULL; 818 } 819 820 if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1) 821 goto bad; 822 src = get_sockaddr(family, p_name, p_port); 823 if (p_name) { 824 racoon_free(p_name); 825 p_name = NULL; 826 } 827 if (p_port) { 828 racoon_free(p_port); 829 p_port = NULL; 830 } 831 if (src == NULL) 832 goto bad; 833 av++; 834 ac--; 835 if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1) 836 goto bad; 837 dst = get_sockaddr(family, p_name, p_port); 838 if (p_name) { 839 racoon_free(p_name); 840 p_name = NULL; 841 } 842 if (p_port) { 843 racoon_free(p_port); 844 p_port = NULL; 845 } 846 if (dst == NULL) 847 goto bad; 848 849 buf = vmalloc(sizeof(*ci)); 850 if (buf == NULL) 851 goto bad; 852 853 av++; 854 ac--; 855 if(ac){ 856 ulproto = get_ulproto(*av); 857 if (ulproto == -1) 858 goto bad; 859 }else 860 ulproto=0; 861 862 ci = (struct admin_com_indexes *)buf->v; 863 if(p_prefs) 864 ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */ 865 else 866 ci->prefs = 32; 867 if(p_prefd) 868 ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */ 869 else 870 ci->prefd = 32; 871 ci->ul_proto = ulproto; 872 memcpy(&ci->src, src, sysdep_sa_len(src)); 873 memcpy(&ci->dst, dst, sysdep_sa_len(dst)); 874 875 if (p_name) 876 racoon_free(p_name); 877 878 return buf; 879 880 bad: 881 if (p_name) 882 racoon_free(p_name); 883 if (p_port) 884 racoon_free(p_port); 885 if (p_prefs) 886 racoon_free(p_prefs); 887 if (p_prefd) 888 racoon_free(p_prefd); 889 return NULL; 890 } 891 892 static int 893 get_comindex(str, name, port, pref) 894 char *str, **name, **port, **pref; 895 { 896 char *p; 897 898 *name = *port = *pref = NULL; 899 900 *name = racoon_strdup(str); 901 STRDUP_FATAL(*name); 902 p = strpbrk(*name, "/["); 903 if (p != NULL) { 904 if (*(p + 1) == '\0') 905 goto bad; 906 if (*p == '/') { 907 *p = '\0'; 908 *pref = racoon_strdup(p + 1); 909 STRDUP_FATAL(*pref); 910 p = strchr(*pref, '['); 911 if (p != NULL) { 912 if (*(p + 1) == '\0') 913 goto bad; 914 *p = '\0'; 915 *port = racoon_strdup(p + 1); 916 STRDUP_FATAL(*port); 917 p = strchr(*pref, ']'); 918 if (p == NULL) 919 goto bad; 920 *p = '\0'; 921 } 922 } else if (*p == '[') { 923 if (*pref == NULL) 924 goto bad; 925 *p = '\0'; 926 *port = racoon_strdup(p + 1); 927 STRDUP_FATAL(*port); 928 p = strchr(*pref, ']'); 929 if (p == NULL) 930 goto bad; 931 *p = '\0'; 932 } else { 933 /* XXX */ 934 } 935 } 936 937 return 0; 938 939 bad: 940 941 if (*name) 942 racoon_free(*name); 943 if (*port) 944 racoon_free(*port); 945 if (*pref) 946 racoon_free(*pref); 947 *name = *port = *pref = NULL; 948 return -1; 949 } 950 951 static int 952 get_ulproto(str) 953 char *str; 954 { 955 struct ulproto_tag *cp; 956 957 if(str == NULL){ 958 errno = EINVAL; 959 return -1; 960 } 961 962 /* checking the string of upper layer protocol. */ 963 for (cp = &ulprototab[0]; cp->str; cp++) { 964 if (strcmp(str, cp->str) == 0) 965 return cp->ul_proto; 966 } 967 968 errno = EINVAL; 969 return -1; 970 } 971 972 /* %%% */ 973 void 974 dump_isakmp_sa(buf, len) 975 char *buf; 976 int len; 977 { 978 struct ph1dump *pd; 979 struct tm *tm; 980 char tbuf[56]; 981 caddr_t p = NULL; 982 983 /* isakmp status header */ 984 /* short header; 985 1234567890123456789012 0000000000000000:0000000000000000 000000000000 986 */ 987 char *header1 = 988 "Destination Cookies Created"; 989 990 /* semi long header; 991 1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000 992 */ 993 char *header2 = 994 "Destination Cookies ST S V E Created Phase2"; 995 996 /* long header; 997 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000 998 */ 999 char *header3 = 1000 "Source Destination Cookies ST S V E Created Phase2"; 1001 1002 /* phase status header */ 1003 /* short format; 1004 side stats source address destination address 1005 xxx xxxxx 1234567890123456789012 1234567890123456789012 1006 */ 1007 1008 static char *estr[] = { "", "B", "M", "U", "A", "I", }; 1009 1010 switch (long_format) { 1011 case 0: 1012 printf("%s\n", header1); 1013 break; 1014 case 1: 1015 printf("%s\n", header2); 1016 break; 1017 case 2: 1018 default: 1019 printf("%s\n", header3); 1020 break; 1021 } 1022 1023 if (len % sizeof(*pd)) 1024 printf("invalid length %d\n", len); 1025 len /= sizeof(*pd); 1026 1027 pd = (struct ph1dump *)buf; 1028 1029 while (len-- > 0) { 1030 /* source address */ 1031 if (long_format >= 2) { 1032 GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_); 1033 switch (long_format) { 1034 case 0: 1035 break; 1036 case 1: 1037 p = fixed_addr(_addr1_, _addr2_, 22); 1038 break; 1039 case 2: 1040 default: 1041 p = fixed_addr(_addr1_, _addr2_, 45); 1042 break; 1043 } 1044 printf("%s ", p); 1045 } 1046 1047 /* destination address */ 1048 GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_); 1049 switch (long_format) { 1050 case 0: 1051 case 1: 1052 p = fixed_addr(_addr1_, _addr2_, 22); 1053 break; 1054 case 2: 1055 default: 1056 p = fixed_addr(_addr1_, _addr2_, 45); 1057 break; 1058 } 1059 printf("%s ", p); 1060 1061 printf("%s ", pindex_isakmp(&pd->index)); 1062 1063 /* statuc, side and version */ 1064 if (long_format >= 1) { 1065 printf("%2d %c %2x ", 1066 pd->status, 1067 pd->side == INITIATOR ? 'I' : 'R', 1068 pd->version); 1069 if (ARRAYLEN(estr) > pd->etype) 1070 printf("%s ", estr[pd->etype]); 1071 } 1072 1073 /* created date */ 1074 if (pd->created) { 1075 tm = localtime(&pd->created); 1076 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm); 1077 } else 1078 snprintf(tbuf, sizeof(tbuf), " "); 1079 printf("%s ", tbuf); 1080 1081 /* counter of phase 2 */ 1082 if (long_format >= 1) 1083 printf("%6d ", pd->ph2cnt); 1084 1085 printf("\n"); 1086 1087 pd++; 1088 } 1089 1090 return; 1091 } 1092 1093 /* %%% */ 1094 void 1095 dump_internal(buf, tlen) 1096 char *buf; 1097 int tlen; 1098 { 1099 struct ph2handle *iph2; 1100 struct sockaddr *addr; 1101 1102 /* 1103 short header; 1104 source address destination address 1105 1234567890123456789012 1234567890123456789012 1106 */ 1107 char *short_h1 = 1108 "Source Destination "; 1109 1110 /* 1111 long header; 1112 source address destination address 1113 123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345 1114 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 1115 */ 1116 char *long_h1 = 1117 "Source Destination "; 1118 1119 printf("%s\n", long_format ? long_h1 : short_h1); 1120 1121 while (tlen > 0) { 1122 iph2 = (struct ph2handle *)buf; 1123 addr = (struct sockaddr *)(++iph2); 1124 1125 GETNAMEINFO(addr, _addr1_, _addr2_); 1126 printf("%s ", long_format ? 1127 fixed_addr(_addr1_, _addr2_, 45) 1128 : fixed_addr(_addr1_, _addr2_, 22)); 1129 addr++; 1130 tlen -= sysdep_sa_len(addr); 1131 1132 GETNAMEINFO(addr, _addr1_, _addr2_); 1133 printf("%s ", long_format ? 1134 fixed_addr(_addr1_, _addr2_, 45) 1135 : fixed_addr(_addr1_, _addr2_, 22)); 1136 addr++; 1137 tlen -= sysdep_sa_len(addr); 1138 1139 printf("\n"); 1140 } 1141 1142 return; 1143 } 1144 1145 /* %%% */ 1146 char * 1147 pindex_isakmp(index) 1148 isakmp_index *index; 1149 { 1150 static char buf[64]; 1151 u_char *p; 1152 int i, j; 1153 1154 memset(buf, 0, sizeof(buf)); 1155 1156 /* copy index */ 1157 p = (u_char *)index; 1158 for (j = 0, i = 0; i < sizeof(isakmp_index); i++) { 1159 snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]); 1160 j += 2; 1161 switch (i) { 1162 case 7: 1163 #if 0 1164 case 15: 1165 #endif 1166 buf[j++] = ':'; 1167 } 1168 } 1169 1170 return buf; 1171 } 1172 1173 /* print schedule */ 1174 char *str_sched_stat[] = { 1175 "off", 1176 "on", 1177 "dead", 1178 }; 1179 1180 char *str_sched_id[] = { 1181 "PH1resend", 1182 "PH1lifetime", 1183 "PH2resend", 1184 "PSTacquire", 1185 "PSTlifetime", 1186 }; 1187 1188 void 1189 print_schedule(buf, len) 1190 caddr_t buf; 1191 int len; 1192 { 1193 struct scheddump *sc = (struct scheddump *)buf; 1194 struct tm *tm; 1195 char tbuf[56]; 1196 1197 if (len % sizeof(*sc)) 1198 printf("invalid length %d\n", len); 1199 len /= sizeof(*sc); 1200 1201 /* 00000000 00000000 00000000 xxx........*/ 1202 printf("index tick xtime created\n"); 1203 1204 while (len-- > 0) { 1205 tm = localtime(&sc->created); 1206 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm); 1207 1208 printf("%-8ld %-8ld %-8ld %s\n", 1209 sc->id, 1210 (long)sc->tick, 1211 (long)sc->xtime, 1212 tbuf); 1213 sc++; 1214 } 1215 1216 return; 1217 } 1218 1219 1220 void 1221 print_evt(evtdump) 1222 struct evt_async *evtdump; 1223 { 1224 int i; 1225 char *srcstr; 1226 char *dststr; 1227 1228 for (i = 0; i < sizeof(evtmsg) / sizeof(evtmsg[0]); i++) 1229 if (evtmsg[i].type == evtdump->ec_type) 1230 break; 1231 1232 if (evtmsg[i].msg == NULL) 1233 printf("Event %d: ", evtdump->ec_type); 1234 else 1235 printf("%s : ", evtmsg[i].msg); 1236 1237 if ((srcstr = saddr2str((struct sockaddr *)&evtdump->ec_ph1src)) == NULL) 1238 printf("unknown"); 1239 else 1240 printf("%s", srcstr); 1241 printf(" -> "); 1242 if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL) 1243 printf("unknown"); 1244 else 1245 printf("%s", dststr); 1246 printf("\n"); 1247 } 1248 1249 /* 1250 * Print ISAKMP mode config info (IP and banner) 1251 */ 1252 void 1253 print_cfg(buf, len) 1254 caddr_t buf; 1255 int len; 1256 { 1257 struct evt_async *evtdump = (struct evt_async *)buf; 1258 struct isakmp_data *attr; 1259 char *banner = NULL; 1260 struct in_addr addr4; 1261 1262 memset(&addr4, 0, sizeof(addr4)); 1263 1264 if (evtdump->ec_type != EVT_PHASE1_MODE_CFG) 1265 return; 1266 1267 len -= sizeof(*evtdump); 1268 attr = (struct isakmp_data *)(evtdump + 1); 1269 1270 while (len > 0) { 1271 if (len < sizeof(*attr)) { 1272 printf("short attribute too short\n"); 1273 break; 1274 } 1275 1276 if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) { 1277 /* Short attribute, skip */ 1278 len -= sizeof(*attr); 1279 attr++; 1280 } else { /* Long attribute */ 1281 char *n; 1282 1283 if (len < (sizeof(*attr) + ntohs(attr->lorv))) { 1284 printf("long attribute too long\n"); 1285 break; 1286 } 1287 1288 switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) { 1289 case INTERNAL_IP4_ADDRESS: 1290 if (ntohs(attr->lorv) < sizeof(addr4)) { 1291 printf("addr4 attribute too short\n"); 1292 break; 1293 } 1294 memcpy(&addr4, attr + 1, sizeof(addr4)); 1295 break; 1296 1297 case UNITY_BANNER: 1298 banner = racoon_malloc(ntohs(attr->lorv) + 1); 1299 if (banner == NULL) { 1300 printf("malloc failed\n"); 1301 break; 1302 } 1303 memcpy(banner, attr + 1, ntohs(attr->lorv)); 1304 banner[ntohs(attr->lorv)] = '\0'; 1305 break; 1306 1307 default: 1308 break; 1309 } 1310 1311 len -= (sizeof(*attr) + ntohs(attr->lorv)); 1312 n = (char *)attr; 1313 attr = (struct isakmp_data *) 1314 (n + sizeof(*attr) + ntohs(attr->lorv)); 1315 } 1316 } 1317 1318 if (len > 0) 1319 printf("Bound to address %s\n", inet_ntoa(addr4)); 1320 else 1321 printf("VPN connexion established\n"); 1322 1323 if (banner) { 1324 struct winsize win; 1325 int col = 0; 1326 int i; 1327 1328 if (ioctl(1, TIOCGWINSZ, &win) != 1) 1329 col = win.ws_col; 1330 1331 for (i = 0; i < col; i++) 1332 printf("%c", '='); 1333 printf("\n%s\n", banner); 1334 for (i = 0; i < col; i++) 1335 printf("%c", '='); 1336 printf("\n"); 1337 racoon_free(banner); 1338 } 1339 } 1340 1341 1342 char * 1343 fixed_addr(addr, port, len) 1344 char *addr, *port; 1345 int len; 1346 { 1347 static char _addr_buf_[BUFSIZ]; 1348 char *p; 1349 int plen, i; 1350 1351 /* initialize */ 1352 memset(_addr_buf_, ' ', sizeof(_addr_buf_)); 1353 1354 plen = strlen(port); 1355 if (len < plen + 1) 1356 return NULL; 1357 1358 p = _addr_buf_; 1359 for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/) 1360 *p++ = addr[i++]; 1361 *p++ = '.'; 1362 1363 for (i = 0; i < plen && port[i] != '\0'; /*noting*/) 1364 *p++ = port[i++]; 1365 1366 _addr_buf_[len] = '\0'; 1367 1368 return _addr_buf_; 1369 } 1370 1371 static int 1372 handle_recv(combuf) 1373 vchar_t *combuf; 1374 { 1375 struct admin_com *com; 1376 caddr_t buf; 1377 int len; 1378 1379 com = (struct admin_com *)combuf->v; 1380 len = com->ac_len - sizeof(*com); 1381 buf = combuf->v + sizeof(*com); 1382 1383 switch (com->ac_cmd) { 1384 case ADMIN_SHOW_SCHED: 1385 print_schedule(buf, len); 1386 break; 1387 1388 case ADMIN_SHOW_EVT: { 1389 struct evt_async *ec; 1390 1391 /* We got no event? */ 1392 if (len == 0) 1393 break; 1394 1395 if (len < sizeof(struct evt_async)) 1396 errx(1, "Short buffer\n"); 1397 1398 ec = (struct evt_async *) buf; 1399 if (evt_quit_event <= 0) 1400 print_evt(ec); 1401 else if (evt_quit_event == ec->ec_type) { 1402 switch (ec->ec_type) { 1403 case EVT_PHASE1_MODE_CFG: 1404 print_cfg(ec, len); 1405 break; 1406 default: 1407 print_evt(ec); 1408 break; 1409 } 1410 evt_quit_event = 0; 1411 } 1412 break; 1413 } 1414 1415 case ADMIN_SHOW_SA: 1416 { 1417 switch (com->ac_proto) { 1418 case ADMIN_PROTO_ISAKMP: 1419 dump_isakmp_sa(buf, len); 1420 break; 1421 case ADMIN_PROTO_IPSEC: 1422 case ADMIN_PROTO_AH: 1423 case ADMIN_PROTO_ESP: 1424 { 1425 struct sadb_msg *msg = (struct sadb_msg *)buf; 1426 1427 switch (msg->sadb_msg_errno) { 1428 case ENOENT: 1429 switch (msg->sadb_msg_type) { 1430 case SADB_DELETE: 1431 case SADB_GET: 1432 printf("No entry.\n"); 1433 break; 1434 case SADB_DUMP: 1435 printf("No SAD entries.\n"); 1436 break; 1437 } 1438 break; 1439 case 0: 1440 while (1) { 1441 pfkey_sadump(msg); 1442 if (msg->sadb_msg_seq == 0) 1443 break; 1444 msg = (struct sadb_msg *)((caddr_t)msg + 1445 PFKEY_UNUNIT64(msg->sadb_msg_len)); 1446 } 1447 break; 1448 default: 1449 printf("%s.\n", strerror(msg->sadb_msg_errno)); 1450 } 1451 } 1452 break; 1453 case ADMIN_PROTO_INTERNAL: 1454 dump_internal(buf, len); 1455 break; 1456 default: 1457 printf("Invalid proto [%d]\n", com->ac_proto); 1458 } 1459 1460 } 1461 break; 1462 1463 default: 1464 /* IGNORE */ 1465 break; 1466 } 1467 1468 return 0; 1469 1470 bad: 1471 return -1; 1472 } 1473