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