1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 #include <unistd.h> 28 #include <stdio.h> 29 #include <stdarg.h> 30 #include <stdlib.h> 31 #include <sys/sysconf.h> 32 #include <string.h> 33 #include <strings.h> 34 #include <libintl.h> 35 #include <locale.h> 36 #include <ctype.h> 37 #include <time.h> 38 #include <sys/sysmacros.h> 39 #include <sys/stat.h> 40 #include <sys/mman.h> 41 #include <fcntl.h> 42 #include <sys/socket.h> 43 #include <netdb.h> 44 #include <errno.h> 45 #include <assert.h> 46 #include <netinet/in.h> 47 #include <arpa/inet.h> 48 #include <door.h> 49 #include <setjmp.h> 50 51 #include <ipsec_util.h> 52 #include <ikedoor.h> 53 54 static int doorfd = -1; 55 56 /* 57 * These are additional return values for the command line parsing 58 * function (parsecmd()). They are specific to this utility, but 59 * need to share the same space as the IKE_SVC_* defs, without conflicts. 60 * So they're defined relative to the end of that range. 61 */ 62 #define IKEADM_HELP_GENERAL IKE_SVC_MAX + 1 63 #define IKEADM_HELP_GET IKE_SVC_MAX + 2 64 #define IKEADM_HELP_SET IKE_SVC_MAX + 3 65 #define IKEADM_HELP_ADD IKE_SVC_MAX + 4 66 #define IKEADM_HELP_DEL IKE_SVC_MAX + 5 67 #define IKEADM_HELP_DUMP IKE_SVC_MAX + 6 68 #define IKEADM_HELP_FLUSH IKE_SVC_MAX + 7 69 #define IKEADM_HELP_READ IKE_SVC_MAX + 8 70 #define IKEADM_HELP_WRITE IKE_SVC_MAX + 9 71 #define IKEADM_HELP_HELP IKE_SVC_MAX + 10 72 #define IKEADM_EXIT IKE_SVC_MAX + 11 73 74 static void 75 command_complete(int s) 76 { 77 if (interactive) { 78 longjmp(env, 1); 79 } else { 80 exit(s); 81 } 82 } 83 84 static void 85 usage() 86 { 87 if (!interactive) { 88 (void) fprintf(stderr, gettext("Usage:\t" 89 "ikeadm [ -hnp ] cmd obj [cmd-specific options]\n")); 90 (void) fprintf(stderr, gettext(" \tikeadm help\n")); 91 } 92 93 command_complete(1); 94 } 95 96 static void 97 print_help() 98 { 99 (void) printf(gettext("Valid commands and objects:\n")); 100 (void) printf( 101 "\tget debug|priv|stats|p1|rule|preshared|defaults [%s]\n", 102 gettext("identifier")); 103 (void) printf("\tset priv %s\n", gettext("level")); 104 (void) printf("\tset debug %s [%s]\n", 105 gettext("level"), gettext("filename")); 106 (void) printf("\tadd rule|preshared {%s}|%s\n", 107 gettext("definition"), gettext("filename")); 108 (void) printf("\tdel p1|rule|preshared %s\n", gettext("identifier")); 109 (void) printf("\tdump p1|rule|preshared\n"); 110 (void) printf("\tflush p1\n"); 111 (void) printf("\tread rule|preshared [%s]\n", gettext("filename")); 112 (void) printf("\twrite rule|preshared %s\n", gettext("filename")); 113 (void) printf( 114 "\thelp [get|set|add|del|dump|flush|read|write|help]\n"); 115 (void) printf("\texit %s\n", gettext("exit the program")); 116 (void) printf("\tquit %s\n", gettext("exit the program")); 117 (void) printf("\n"); 118 119 command_complete(0); 120 } 121 122 static void 123 print_get_help() 124 { 125 (void) printf( 126 gettext("This command gets information from in.iked.\n\n")); 127 (void) printf(gettext("Objects that may be retrieved include:\n")); 128 (void) printf("\tdebug\t\t"); 129 (void) printf(gettext("the current debug level\n")); 130 (void) printf("\tpriv\t\t"); 131 (void) printf(gettext("the current privilege level\n")); 132 (void) printf("\tstats\t\t"); 133 (void) printf(gettext("current usage statistics\n")); 134 (void) printf("\tp1\t\t"); 135 (void) printf(gettext("a phase 1 SA, identified by\n")); 136 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n")); 137 (void) printf(gettext("\t\t\t init_cookie resp_cookie\n")); 138 (void) printf("\trule\t\t"); 139 (void) printf(gettext("a phase 1 rule, identified by its label\n")); 140 (void) printf("\tpreshared\t"); 141 (void) printf(gettext("a preshared key, identified by\n")); 142 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n")); 143 (void) printf(gettext("\t\t\t local_id remote_id\n")); 144 (void) printf("\n"); 145 146 command_complete(0); 147 } 148 149 static void 150 print_set_help() 151 { 152 (void) printf(gettext("This command sets values in in.iked.\n\n")); 153 (void) printf(gettext("Objects that may be set include:\n")); 154 (void) printf("\tdebug\t\t"); 155 (void) printf(gettext("change the debug level\n")); 156 (void) printf("\tpriv\t\t"); 157 (void) printf( 158 gettext("change the privilege level (may only be lowered)\n")); 159 (void) printf("\n"); 160 161 command_complete(0); 162 } 163 164 static void 165 print_add_help() 166 { 167 (void) printf( 168 gettext("This command adds items to in.iked's tables.\n\n")); 169 (void) printf(gettext("Objects that may be set include:\n")); 170 (void) printf("\trule\t\t"); 171 (void) printf(gettext("a phase 1 policy rule\n")); 172 (void) printf("\tpreshared\t"); 173 (void) printf(gettext("a preshared key\n")); 174 (void) printf( 175 gettext("\nObjects may be entered on the command-line, as a\n")); 176 (void) printf( 177 gettext("series of keywords and tokens contained in curly\n")); 178 (void) printf( 179 gettext("braces ('{', '}'); or the name of a file containing\n")); 180 (void) printf(gettext("the object definition may be provided.\n\n")); 181 (void) printf( 182 gettext("For security purposes, preshared keys may only be\n")); 183 (void) printf( 184 gettext("entered on the command-line if ikeadm is running in\n")); 185 (void) printf(gettext("interactive mode.\n")); 186 (void) printf("\n"); 187 188 command_complete(0); 189 } 190 191 static void 192 print_del_help() 193 { 194 (void) printf( 195 gettext("This command deletes an item from in.iked's tables.\n\n")); 196 (void) printf(gettext("Objects that may be deleted include:\n")); 197 (void) printf("\tp1\t\t"); 198 (void) printf(gettext("a phase 1 SA, identified by\n")); 199 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n")); 200 (void) printf(gettext("\t\t\t init_cookie resp_cookie\n")); 201 (void) printf("\trule\t\t"); 202 (void) printf(gettext("a phase 1 rule, identified by its label\n")); 203 (void) printf("\tpreshared\t"); 204 (void) printf(gettext("a preshared key, identified by\n")); 205 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n")); 206 (void) printf(gettext("\t\t\t local_id remote_id\n")); 207 (void) printf("\n"); 208 209 command_complete(0); 210 } 211 212 static void 213 print_dump_help() 214 { 215 (void) printf( 216 gettext("This command dumps one of in.iked's tables.\n\n")); 217 (void) printf(gettext("Tables that may be dumped include:\n")); 218 (void) printf("\tp1\t\t"); 219 (void) printf(gettext("all phase 1 SAs\n")); 220 (void) printf("\trule\t\t"); 221 (void) printf(gettext("all phase 1 rules\n")); 222 (void) printf("\tpreshared\t"); 223 (void) printf(gettext("all preshared keys\n")); 224 (void) printf("\n"); 225 226 command_complete(0); 227 } 228 229 static void 230 print_flush_help() 231 { 232 (void) printf( 233 gettext("This command clears one of in.iked's tables.\n\n")); 234 (void) printf(gettext("Tables that may be flushed include:\n")); 235 (void) printf("\tp1\t\t"); 236 (void) printf(gettext("all phase 1 SAs\n")); 237 (void) printf("\n"); 238 239 command_complete(0); 240 } 241 242 static void 243 print_read_help() 244 { 245 (void) printf( 246 gettext("This command reads a new configuration file into\n")); 247 (void) printf( 248 gettext("in.iked, discarding the old configuration info.\n\n")); 249 (void) printf(gettext("Sets of data that may be read include:\n")); 250 (void) printf("\trule\t\t"); 251 (void) printf(gettext("all phase 1 rules\n")); 252 (void) printf("\tpreshared\t"); 253 (void) printf(gettext("all preshared keys\n\n")); 254 (void) printf( 255 gettext("A filename may be provided to specify a source file\n")); 256 (void) printf(gettext("other than the default.\n")); 257 (void) printf("\n"); 258 259 command_complete(0); 260 } 261 262 static void 263 print_write_help() 264 { 265 (void) printf( 266 gettext("This command writes in.iked's current configuration\n")); 267 (void) printf(gettext("out to a config file.\n\n")); 268 (void) printf(gettext("Sets of data that may be written include:\n")); 269 (void) printf("\trule\t\t"); 270 (void) printf(gettext("all phase 1 rules\n")); 271 (void) printf("\tpreshared\t"); 272 (void) printf(gettext("all preshared keys\n\n")); 273 (void) printf( 274 gettext("A filename must be provided to specify the file to\n")); 275 (void) printf(gettext("which the information should be written.\n")); 276 (void) printf("\n"); 277 278 command_complete(0); 279 } 280 281 static void 282 print_help_help() 283 { 284 (void) printf( 285 gettext("This command provides information about commands.\n\n")); 286 (void) printf( 287 gettext("The 'help' command alone provides a list of valid\n")); 288 (void) printf( 289 gettext("commands, along with the valid objects for each.\n")); 290 (void) printf( 291 gettext("'help' followed by a valid command name provides\n")); 292 (void) printf(gettext("further information about that command.\n")); 293 (void) printf("\n"); 294 295 command_complete(0); 296 } 297 298 /*PRINTFLIKE1*/ 299 static void 300 message(char *fmt, ...) 301 { 302 va_list ap; 303 char msgbuf[BUFSIZ]; 304 305 va_start(ap, fmt); 306 (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap); 307 (void) fprintf(stderr, gettext("ikeadm: %s\n"), msgbuf); 308 va_end(ap); 309 } 310 311 static int 312 open_door(void) 313 { 314 if (doorfd >= 0) 315 (void) close(doorfd); 316 doorfd = open(DOORNM, O_RDWR); 317 return (doorfd); 318 } 319 320 static ike_service_t * 321 ikedoor_call(char *reqp, int size, door_desc_t *descp, int ndesc) 322 { 323 door_arg_t arg; 324 int retries = 0; 325 326 arg.data_ptr = reqp; 327 arg.data_size = size; 328 arg.desc_ptr = descp; 329 arg.desc_num = ndesc; 330 arg.rbuf = (char *)NULL; 331 arg.rsize = 0; 332 333 retry: 334 if (door_call(doorfd, &arg) < 0) { 335 if ((errno == EBADF) && ((++retries < 2) && 336 (open_door() >= 0))) 337 goto retry; 338 (void) fprintf(stderr, 339 gettext("Unable to communicate with in.iked\n")); 340 Bail("door_call failed"); 341 } 342 343 if ((ndesc > 0) && (descp->d_attributes & DOOR_RELEASE) && 344 ((errno == EBADF) || (errno == EFAULT))) { 345 /* callers assume passed fds will be closed no matter what */ 346 (void) close(descp->d_data.d_desc.d_descriptor); 347 } 348 349 /* LINTED E_BAD_PTR_CAST_ALIGN */ 350 return ((ike_service_t *)arg.rbuf); 351 } 352 353 /* 354 * Parsing functions 355 */ 356 357 /* stolen from ipseckey.c, with a second tier added */ 358 static int 359 parsecmd(char *cmdstr, char *objstr) 360 { 361 #define MAXOBJS 10 362 struct objtbl { 363 char *obj; 364 int token; 365 }; 366 static struct cmdtbl { 367 char *cmd; 368 int null_obj_token; 369 struct objtbl objt[MAXOBJS]; 370 } table[] = { 371 {"get", IKE_SVC_ERROR, { 372 {"debug", IKE_SVC_GET_DBG}, 373 {"priv", IKE_SVC_GET_PRIV}, 374 {"stats", IKE_SVC_GET_STATS}, 375 {"p1", IKE_SVC_GET_P1}, 376 {"rule", IKE_SVC_GET_RULE}, 377 {"preshared", IKE_SVC_GET_PS}, 378 {"defaults", IKE_SVC_GET_DEFS}, 379 {NULL, IKE_SVC_ERROR}, 380 } 381 }, 382 {"set", IKE_SVC_ERROR, { 383 {"debug", IKE_SVC_SET_DBG}, 384 {"priv", IKE_SVC_SET_PRIV}, 385 {NULL, IKE_SVC_ERROR}, 386 } 387 }, 388 {"add", IKE_SVC_ERROR, { 389 {"rule", IKE_SVC_NEW_RULE}, 390 {"preshared", IKE_SVC_NEW_PS}, 391 {NULL, IKE_SVC_ERROR}, 392 } 393 }, 394 {"del", IKE_SVC_ERROR, { 395 {"p1", IKE_SVC_DEL_P1}, 396 {"rule", IKE_SVC_DEL_RULE}, 397 {"preshared", IKE_SVC_DEL_PS}, 398 {NULL, IKE_SVC_ERROR}, 399 } 400 }, 401 {"dump", IKE_SVC_ERROR, { 402 {"p1", IKE_SVC_DUMP_P1S}, 403 {"rule", IKE_SVC_DUMP_RULES}, 404 {"preshared", IKE_SVC_DUMP_PS}, 405 {NULL, IKE_SVC_ERROR}, 406 } 407 }, 408 {"flush", IKE_SVC_ERROR, { 409 {"p1", IKE_SVC_FLUSH_P1S}, 410 {NULL, IKE_SVC_ERROR}, 411 } 412 }, 413 {"read", IKE_SVC_ERROR, { 414 {"rule", IKE_SVC_READ_RULES}, 415 {"preshared", IKE_SVC_READ_PS}, 416 {NULL, IKE_SVC_ERROR}, 417 } 418 }, 419 {"write", IKE_SVC_ERROR, { 420 {"rule", IKE_SVC_WRITE_RULES}, 421 {"preshared", IKE_SVC_WRITE_PS}, 422 {NULL, IKE_SVC_ERROR}, 423 } 424 }, 425 {"help", IKEADM_HELP_GENERAL, { 426 {"get", IKEADM_HELP_GET}, 427 {"set", IKEADM_HELP_SET}, 428 {"add", IKEADM_HELP_ADD}, 429 {"del", IKEADM_HELP_DEL}, 430 {"dump", IKEADM_HELP_DUMP}, 431 {"flush", IKEADM_HELP_FLUSH}, 432 {"read", IKEADM_HELP_READ}, 433 {"write", IKEADM_HELP_WRITE}, 434 {"help", IKEADM_HELP_HELP}, 435 {NULL, IKE_SVC_ERROR}, 436 } 437 }, 438 {"exit", IKEADM_EXIT, { 439 {NULL, IKE_SVC_ERROR}, 440 } 441 }, 442 {"quit", IKEADM_EXIT, { 443 {NULL, IKE_SVC_ERROR}, 444 } 445 }, 446 {"dbg", IKE_SVC_ERROR, { 447 {"rbdump", IKE_SVC_DBG_RBDUMP}, 448 {NULL, IKE_SVC_ERROR}, 449 } 450 }, 451 {NULL, IKE_SVC_ERROR, { 452 {NULL, IKE_SVC_ERROR}, 453 } 454 }, 455 }; 456 struct cmdtbl *ct = table; 457 struct objtbl *ot; 458 459 if (cmdstr == NULL) { 460 return (IKE_SVC_ERROR); 461 } 462 463 while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0) 464 ct++; 465 ot = ct->objt; 466 467 if (ct->cmd == NULL) { 468 message(gettext("Unrecognized command '%s'"), cmdstr); 469 return (ot->token); 470 } 471 472 if (objstr == NULL) { 473 return (ct->null_obj_token); 474 } 475 476 while (ot->obj != NULL && strcmp(ot->obj, objstr) != 0) 477 ot++; 478 479 if (ot->obj == NULL) 480 message(gettext("Unrecognized object '%s'"), objstr); 481 482 return (ot->token); 483 } 484 485 /* 486 * Parsing functions: 487 * Parse command-line identification info. All return -1 on failure, 488 * or the number of cmd-line args "consumed" on success (though argc 489 * and argv params are not actually modified). 490 */ 491 492 static int 493 parse_label(int argc, char **argv, char *label) 494 { 495 if ((argc < 1) || (argv == NULL)) 496 return (-1); 497 498 if (strlcpy(label, argv[0], MAX_LABEL_LEN) >= MAX_LABEL_LEN) 499 return (-1); 500 501 return (1); 502 } 503 504 /* 505 * Parse an address off the command line. In the hpp param, either 506 * return a hostent pointer (caller frees) or a pointer to a dummy_he_t 507 * (must also be freed by the caller; both cases are handled by the 508 * macro FREE_HE). The new getipnodebyname() call does the Right Thing 509 * (TM), even with raw addresses (colon-separated IPv6 or dotted decimal 510 * IPv4). 511 * (mostly stolen from ipseckey.c, though some tweaks were made 512 * to better serve our purposes here.) 513 */ 514 515 typedef struct { 516 struct hostent he; 517 char *addtl[2]; 518 } dummy_he_t; 519 520 static int 521 parse_addr(int argc, char **argv, struct hostent **hpp) 522 { 523 int hp_errno; 524 struct hostent *hp = NULL; 525 dummy_he_t *dhp; 526 char *addr1; 527 528 if ((argc < 1) || (argv == NULL) || (argv[0] == NULL)) 529 return (-1); 530 531 if (!nflag) { 532 /* 533 * Try name->address first. Assume AF_INET6, and 534 * get IPV4s, plus IPv6s iff IPv6 is configured. 535 */ 536 hp = getipnodebyname(argv[0], AF_INET6, AI_DEFAULT | AI_ALL, 537 &hp_errno); 538 } else { 539 /* 540 * Try a normal address conversion only. malloc a 541 * dummy_he_t to construct a fake hostent. Caller 542 * will know to free this one using free_he(). 543 */ 544 dhp = (dummy_he_t *)malloc(sizeof (dummy_he_t)); 545 addr1 = (char *)malloc(sizeof (struct in6_addr)); 546 if (inet_pton(AF_INET6, argv[0], addr1) == 1) { 547 dhp->he.h_addr_list = dhp->addtl; 548 dhp->addtl[0] = addr1; 549 dhp->addtl[1] = NULL; 550 hp = &dhp->he; 551 dhp->he.h_addrtype = AF_INET6; 552 dhp->he.h_length = sizeof (struct in6_addr); 553 } else if (inet_pton(AF_INET, argv[0], addr1) == 1) { 554 dhp->he.h_addr_list = dhp->addtl; 555 dhp->addtl[0] = addr1; 556 dhp->addtl[1] = NULL; 557 hp = &dhp->he; 558 dhp->he.h_addrtype = AF_INET; 559 dhp->he.h_length = sizeof (struct in_addr); 560 } else { 561 hp = NULL; 562 } 563 } 564 565 *hpp = hp; 566 567 if (hp == NULL) { 568 message(gettext("Unknown address %s."), argv[0]); 569 return (-1); 570 } 571 572 return (1); 573 } 574 575 /* 576 * Free a dummy_he_t structure that was malloc'd in parse_addr(). 577 * Unfortunately, callers of parse_addr don't want to know about 578 * dummy_he_t structs, so all they have is a pointer to the struct 579 * hostent; so that's what's passed in. To manage this, we make 580 * the assumption that the struct hostent is the first field in 581 * the dummy_he_t, and therefore a pointer to it is a pointer to 582 * the dummy_he_t. 583 */ 584 static void 585 free_he(struct hostent *hep) 586 { 587 dummy_he_t *p = (dummy_he_t *)hep; 588 589 assert(p != NULL); 590 591 if (p->addtl[0]) 592 free(p->addtl[0]); 593 if (p->addtl[1]) 594 free(p->addtl[1]); 595 596 free(p); 597 } 598 599 #define FREE_HE(x) \ 600 if (nflag) \ 601 free_he(x); \ 602 else \ 603 freehostent(x) 604 605 static void 606 headdr2sa(char *hea, struct sockaddr_storage *sa, int len) 607 { 608 struct sockaddr_in *sin; 609 struct sockaddr_in6 *sin6; 610 611 if (len == sizeof (struct in6_addr)) { 612 /* LINTED E_BAD_PTR_CAST_ALIGN */ 613 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)hea)) { 614 sin = (struct sockaddr_in *)sa; 615 (void) memset(sin, 0, sizeof (*sin)); 616 /* LINTED E_BAD_PTR_CAST_ALIGN */ 617 IN6_V4MAPPED_TO_INADDR((struct in6_addr *)hea, 618 &sin->sin_addr); 619 sin->sin_family = AF_INET; 620 } else { 621 sin6 = (struct sockaddr_in6 *)sa; 622 (void) memset(sin6, 0, sizeof (*sin6)); 623 (void) memcpy(&sin6->sin6_addr, hea, 624 sizeof (struct in6_addr)); 625 sin6->sin6_family = AF_INET6; 626 } 627 } else { 628 sin = (struct sockaddr_in *)sa; 629 (void) memset(sin, 0, sizeof (*sin)); 630 (void) memcpy(&sin->sin_addr, hea, sizeof (struct in_addr)); 631 sin->sin_family = AF_INET; 632 } 633 } 634 635 /* 636 * The possible ident-type keywords that might be used on the command 637 * line. This is a superset of the ones supported by ipseckey, those 638 * in the ike config file, and those in ike.preshared. 639 */ 640 static keywdtab_t idtypes[] = { 641 /* ip, ipv4, and ipv6 are valid for preshared keys... */ 642 {SADB_IDENTTYPE_RESERVED, "ip"}, 643 {SADB_IDENTTYPE_RESERVED, "ipv4"}, 644 {SADB_IDENTTYPE_RESERVED, "ipv6"}, 645 {SADB_IDENTTYPE_PREFIX, "prefix"}, 646 {SADB_IDENTTYPE_PREFIX, "ipv4-prefix"}, 647 {SADB_IDENTTYPE_PREFIX, "ipv6-prefix"}, 648 {SADB_IDENTTYPE_PREFIX, "subnet"}, 649 {SADB_IDENTTYPE_PREFIX, "subnetv4"}, 650 {SADB_IDENTTYPE_PREFIX, "subnetv6"}, 651 {SADB_IDENTTYPE_FQDN, "fqdn"}, 652 {SADB_IDENTTYPE_FQDN, "dns"}, 653 {SADB_IDENTTYPE_FQDN, "domain"}, 654 {SADB_IDENTTYPE_FQDN, "domainname"}, 655 {SADB_IDENTTYPE_USER_FQDN, "user_fqdn"}, 656 {SADB_IDENTTYPE_USER_FQDN, "mbox"}, 657 {SADB_IDENTTYPE_USER_FQDN, "mailbox"}, 658 {SADB_X_IDENTTYPE_DN, "dn"}, 659 {SADB_X_IDENTTYPE_DN, "asn1dn"}, 660 {SADB_X_IDENTTYPE_GN, "gn"}, 661 {SADB_X_IDENTTYPE_GN, "asn1gn"}, 662 {SADB_X_IDENTTYPE_ADDR_RANGE, "ipv4-range"}, 663 {SADB_X_IDENTTYPE_ADDR_RANGE, "ipv6-range"}, 664 {SADB_X_IDENTTYPE_ADDR_RANGE, "rangev4"}, 665 {SADB_X_IDENTTYPE_ADDR_RANGE, "rangev6"}, 666 {SADB_X_IDENTTYPE_KEY_ID, "keyid"}, 667 {NULL, 0} 668 }; 669 670 static int 671 parse_idtype(char *type, uint16_t *idnum) 672 { 673 keywdtab_t *idp; 674 675 if (type == NULL) 676 return (-1); 677 678 for (idp = idtypes; idp->kw_str != NULL; idp++) { 679 if (strcasecmp(idp->kw_str, type) == 0) { 680 if (idnum != NULL) 681 *idnum = idp->kw_tag; 682 return (1); 683 } 684 } 685 686 return (-1); 687 } 688 689 /* 690 * The sadb_ident_t is malloc'd, since its length varies; 691 * so the caller must free() it when done with the data. 692 */ 693 static int 694 parse_ident(int argc, char **argv, sadb_ident_t **idpp) 695 { 696 int alloclen, consumed; 697 sadb_ident_t *idp; 698 if ((argc < 2) || (argv == NULL) || (argv[0] == NULL) || 699 (argv[1] == NULL)) 700 return (-1); 701 702 alloclen = sizeof (sadb_ident_t) + IKEDOORROUNDUP(strlen(argv[1]) + 1); 703 *idpp = idp = (sadb_ident_t *)malloc(alloclen); 704 if (idp == NULL) 705 Bail("parsing identity"); 706 707 if ((consumed = parse_idtype(argv[0], &idp->sadb_ident_type)) < 0) { 708 message(gettext("unknown identity type %s."), argv[0]); 709 return (-1); 710 } 711 712 idp->sadb_ident_len = SADB_8TO64(alloclen); 713 idp->sadb_ident_reserved = 0; 714 idp->sadb_ident_id = 0; 715 716 /* now copy in identity param */ 717 (void) strlcpy((char *)(idp + 1), argv[1], 718 alloclen - (sizeof (sadb_ident_t))); 719 720 return (++consumed); 721 } 722 723 static int 724 parse_cky(int argc, char **argv, uint64_t *ckyp) 725 { 726 u_longlong_t arg; 727 728 if ((argc < 1) || (argv[0] == NULL)) 729 return (-1); 730 731 errno = 0; 732 arg = strtoull(argv[0], NULL, 0); 733 if (errno != 0) { 734 message(gettext("failed to parse cookie %s."), argv[0]); 735 return (-1); 736 } 737 738 *ckyp = (uint64_t)arg; 739 740 return (1); 741 } 742 743 static int 744 parse_addr_pr(int argc, char **argv, struct hostent **h1pp, 745 struct hostent **h2pp) 746 { 747 int rtn, consumed = 0; 748 749 if ((rtn = parse_addr(argc, argv, h1pp)) < 0) { 750 return (-1); 751 } 752 consumed = rtn; 753 argc -= rtn; 754 argv += rtn; 755 756 if ((rtn = parse_addr(argc, argv, h2pp)) < 0) { 757 FREE_HE(*h1pp); 758 return (-1); 759 } 760 consumed += rtn; 761 762 return (consumed); 763 } 764 765 /* 766 * The sadb_ident_ts are malloc'd, since their length varies; 767 * so the caller must free() them when done with the data. 768 */ 769 static int 770 parse_ident_pr(int argc, char **argv, sadb_ident_t **id1pp, 771 sadb_ident_t **id2pp) 772 { 773 int rtn, consumed = 0; 774 775 if ((rtn = parse_ident(argc, argv, id1pp)) < 0) { 776 return (-1); 777 } 778 consumed = rtn; 779 argc -= rtn; 780 argv += rtn; 781 782 (*id1pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; 783 784 if ((rtn = parse_ident(argc, argv, id2pp)) < 0) { 785 free(*id1pp); 786 return (-1); 787 } 788 consumed += rtn; 789 790 (*id2pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; 791 792 return (consumed); 793 } 794 795 static int 796 parse_cky_pr(int argc, char **argv, ike_cky_pr_t *cpr) 797 { 798 int rtn, consumed = 0; 799 800 if ((rtn = parse_cky(argc, argv, &cpr->cky_i)) < 0) { 801 return (-1); 802 } 803 consumed = rtn; 804 argc -= rtn; 805 argv += rtn; 806 807 if ((rtn = parse_cky(argc, argv, &cpr->cky_r)) < 0) { 808 return (-1); 809 } 810 consumed += rtn; 811 812 return (consumed); 813 } 814 815 /* 816 * Preshared key field types...used for parsing preshared keys that 817 * have been entered on the command line. The code to parse preshared 818 * keys (parse_ps, parse_key, parse_psfldid, parse_ikmtype, ...) is 819 * mostly duplicated from in.iked's readps.c. 820 */ 821 #define PSFLD_LOCID 1 822 #define PSFLD_LOCIDTYPE 2 823 #define PSFLD_REMID 3 824 #define PSFLD_REMIDTYPE 4 825 #define PSFLD_MODE 5 826 #define PSFLD_KEY 6 827 828 static keywdtab_t psfldtypes[] = { 829 {PSFLD_LOCID, "localid"}, 830 {PSFLD_LOCIDTYPE, "localidtype"}, 831 {PSFLD_REMID, "remoteid"}, 832 {PSFLD_REMIDTYPE, "remoteidtype"}, 833 {PSFLD_MODE, "ike_mode"}, 834 {PSFLD_KEY, "key"}, 835 {NULL, 0} 836 }; 837 838 static int 839 parse_psfldid(char *type, uint16_t *idnum) 840 { 841 keywdtab_t *pfp; 842 843 if (type == NULL) 844 return (-1); 845 846 for (pfp = psfldtypes; pfp->kw_str != NULL; pfp++) { 847 if (strcasecmp(pfp->kw_str, type) == 0) { 848 if (idnum != NULL) 849 *idnum = pfp->kw_tag; 850 return (1); 851 } 852 } 853 854 return (-1); 855 } 856 857 static keywdtab_t ikemodes[] = { 858 {IKE_XCHG_IDENTITY_PROTECT, "main"}, 859 {IKE_XCHG_AGGRESSIVE, "aggressive"}, 860 {IKE_XCHG_IP_AND_AGGR, "both"}, 861 {NULL, 0} 862 }; 863 864 static int 865 parse_ikmtype(char *mode, uint16_t *modenum) 866 { 867 keywdtab_t *ikmp; 868 869 if (mode == NULL) 870 return (-1); 871 872 for (ikmp = ikemodes; ikmp->kw_str != NULL; ikmp++) { 873 if (strcasecmp(ikmp->kw_str, mode) == 0) { 874 if (modenum != NULL) 875 *modenum = ikmp->kw_tag; 876 return (1); 877 } 878 } 879 880 return (-1); 881 } 882 883 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \ 884 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10))) 885 886 static uint8_t * 887 parse_key(char *input, uint_t *keybuflen, uint_t *lbits) 888 { 889 uint8_t *keyp, *keybufp; 890 uint_t i, hexlen = 0, bits, alloclen; 891 892 for (i = 0; input[i] != '\0' && input[i] != '/'; i++) 893 hexlen++; 894 895 if (input[i] == '\0') { 896 bits = 0; 897 } else { 898 /* Have /nn. */ 899 input[i] = '\0'; 900 if (sscanf((input + i + 1), "%u", &bits) != 1) 901 return (NULL); 902 903 /* hexlen is in nibbles */ 904 if (((bits + 3) >> 2) > hexlen) 905 return (NULL); 906 907 /* 908 * Adjust hexlen down if user gave us too small of a bit 909 * count. 910 */ 911 if ((hexlen << 2) > bits + 3) { 912 hexlen = (bits + 3) >> 2; 913 input[hexlen] = '\0'; 914 } 915 } 916 917 /* 918 * Allocate. Remember, hexlen is in nibbles. 919 */ 920 921 alloclen = (hexlen/2 + (hexlen & 0x1)); 922 keyp = malloc(alloclen); 923 924 if (keyp == NULL) 925 return (NULL); 926 927 keybufp = keyp; 928 *keybuflen = alloclen; 929 if (bits == 0) 930 *lbits = (hexlen + (hexlen & 0x1)) << 2; 931 else 932 *lbits = bits; 933 934 /* 935 * Read in nibbles. Read in odd-numbered as shifted high. 936 * (e.g. 123 becomes 0x1230). 937 */ 938 for (i = 0; input[i] != '\0'; i += 2) { 939 boolean_t second = (input[i + 1] != '\0'); 940 941 if (!isxdigit(input[i]) || 942 (!isxdigit(input[i + 1]) && second)) { 943 free(keyp); 944 return (NULL); 945 } 946 *keyp = (hd2num(input[i]) << 4); 947 if (second) 948 *keyp |= hd2num(input[i + 1]); 949 else 950 break; /* out of for loop. */ 951 keyp++; 952 } 953 954 /* zero the remaining bits if we're a non-octet amount. */ 955 if (bits & 0x7) 956 *((input[i] == '\0') ? keyp - 1 : keyp) &= 957 0xff << (8 - (bits & 0x7)); 958 return (keybufp); 959 } 960 961 /* 962 * the ike_ps_t struct (plus trailing data) will be allocated here, 963 * so it will need to be freed by the caller. 964 */ 965 static int 966 parse_ps(int argc, char **argv, ike_ps_t **presharedpp, int *len) 967 { 968 uint_t c = 0, locidlen, remidlen, keylen, keybits; 969 uint_t a_locidtotal = 0, a_remidtotal = 0; 970 char *locid, *remid; 971 uint8_t *keyp = NULL; 972 uint16_t fldid, locidtype, remidtype, mtype; 973 struct hostent *loche = NULL, *remhe = NULL; 974 ike_ps_t *psp = NULL; 975 sadb_ident_t *sidp; 976 boolean_t whacked = B_FALSE; 977 978 if ((argv[c] == NULL) || (argv[c][0] != '{')) 979 return (-1); 980 if (argv[c][1] != 0) { 981 /* no space between '{' and first token */ 982 argv[c]++; 983 } else { 984 c++; 985 } 986 if ((argv[argc - 1][strlen(argv[argc - 1]) - 1] == '}') && 987 (argv[argc - 1][0] != '}')) { 988 /* 989 * whack '}' without a space before it or parsers break. 990 * Remember this trailing character for later 991 */ 992 argv[argc - 1][strlen(argv[argc - 1]) - 1] = '\0'; 993 whacked = B_TRUE; 994 } 995 996 while ((c < argc) && (argv[c] != NULL) && (argv[c][0] != '}')) { 997 if ((argv[c + 1] == NULL) || (argv[c + 1][0] == '}')) 998 goto bail; 999 if (parse_psfldid(argv[c++], &fldid) < 0) 1000 goto bail; 1001 switch (fldid) { 1002 case PSFLD_LOCID: 1003 locid = argv[c++]; 1004 locidlen = strlen(locid) + 1; 1005 break; 1006 case PSFLD_LOCIDTYPE: 1007 if (parse_idtype(argv[c++], &locidtype) < 0) 1008 goto bail; 1009 break; 1010 case PSFLD_REMID: 1011 remid = argv[c++]; 1012 remidlen = strlen(remid) + 1; 1013 break; 1014 case PSFLD_REMIDTYPE: 1015 if (parse_idtype(argv[c++], &remidtype) < 0) 1016 goto bail; 1017 break; 1018 case PSFLD_MODE: 1019 if (parse_ikmtype(argv[c++], &mtype) < 0) 1020 goto bail; 1021 break; 1022 case PSFLD_KEY: 1023 keyp = parse_key(argv[c++], &keylen, &keybits); 1024 if (keyp == NULL) 1025 goto bail; 1026 break; 1027 } 1028 } 1029 1030 /* Make sure the line was terminated with '}' */ 1031 if (argv[c] == NULL) { 1032 if (!whacked) 1033 goto bail; 1034 } else if (argv[c][0] != '}') { 1035 goto bail; 1036 } 1037 1038 /* 1039 * make sure we got all the required fields. If no idtype, assume 1040 * ip addr; if that translation fails, we'll catch the error then. 1041 */ 1042 if (locid == NULL || remid == NULL || keyp == NULL || mtype == 0) 1043 goto bail; 1044 1045 /* figure out the size buffer we need */ 1046 *len = sizeof (ike_ps_t); 1047 if (locidtype != SADB_IDENTTYPE_RESERVED) { 1048 a_locidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + locidlen); 1049 *len += a_locidtotal; 1050 } 1051 if (remidtype != SADB_IDENTTYPE_RESERVED) { 1052 a_remidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + remidlen); 1053 *len += a_remidtotal; 1054 } 1055 *len += keylen; 1056 1057 psp = malloc(*len); 1058 if (psp == NULL) 1059 goto bail; 1060 (void) memset(psp, 0, *len); 1061 1062 psp->ps_ike_mode = mtype; 1063 1064 psp->ps_localid_off = sizeof (ike_ps_t); 1065 if (locidtype == SADB_IDENTTYPE_RESERVED) { 1066 /* 1067 * this is an ip address, store in the sockaddr field; 1068 * we won't use an sadb_ident_t. 1069 */ 1070 psp->ps_localid_len = 0; 1071 if (parse_addr(1, &locid, &loche) < 0) 1072 goto bail; 1073 if (loche->h_addr_list[1] != NULL) { 1074 message(gettext("preshared key identifier cannot " 1075 "match multiple IP addresses")); 1076 goto bail; 1077 } 1078 headdr2sa(loche->h_addr_list[0], &psp->ps_ipaddrs.loc_addr, 1079 loche->h_length); 1080 FREE_HE(loche); 1081 } else { 1082 psp->ps_localid_len = sizeof (sadb_ident_t) + locidlen; 1083 sidp = (sadb_ident_t *)((int)psp + psp->ps_localid_off); 1084 sidp->sadb_ident_len = psp->ps_localid_len; 1085 sidp->sadb_ident_type = locidtype; 1086 (void) strlcpy((char *)(sidp + 1), locid, a_locidtotal); 1087 } 1088 1089 psp->ps_remoteid_off = psp->ps_localid_off + a_locidtotal; 1090 if (remidtype == SADB_IDENTTYPE_RESERVED) { 1091 /* 1092 * this is an ip address, store in the sockaddr field; 1093 * we won't use an sadb_ident_t. 1094 */ 1095 psp->ps_remoteid_len = 0; 1096 if (parse_addr(1, &remid, &remhe) < 0) 1097 goto bail; 1098 if (remhe->h_addr_list[1] != NULL) { 1099 message(gettext("preshared key identifier cannot " 1100 "match multiple IP addresses")); 1101 goto bail; 1102 } 1103 headdr2sa(remhe->h_addr_list[0], &psp->ps_ipaddrs.rem_addr, 1104 remhe->h_length); 1105 FREE_HE(remhe); 1106 } else { 1107 /* make sure we have at least 16-bit alignment */ 1108 if (remidlen & 0x1) 1109 remidlen++; 1110 psp->ps_remoteid_len = sizeof (sadb_ident_t) + remidlen; 1111 sidp = (sadb_ident_t *)((int)psp + psp->ps_remoteid_off); 1112 sidp->sadb_ident_len = psp->ps_remoteid_len; 1113 sidp->sadb_ident_type = remidtype; 1114 (void) strlcpy((char *)(sidp + 1), remid, a_remidtotal); 1115 } 1116 1117 psp->ps_key_off = psp->ps_remoteid_off + a_remidtotal; 1118 psp->ps_key_len = keylen; 1119 psp->ps_key_bits = keybits; 1120 (void) memcpy((uint8_t *)((int)psp + psp->ps_key_off), keyp, keylen); 1121 1122 *presharedpp = psp; 1123 1124 return (c); 1125 1126 bail: 1127 if (loche != NULL) 1128 FREE_HE(loche); 1129 if (remhe != NULL) 1130 FREE_HE(remhe); 1131 if (keyp != NULL) 1132 free(keyp); 1133 if (psp != NULL) 1134 free(psp); 1135 1136 *presharedpp = NULL; 1137 1138 return (-1); 1139 } 1140 1141 /* stolen from libdhcputil (dhcp_inittab.c) */ 1142 static uint64_t 1143 ike_ntohll(uint64_t nll) 1144 { 1145 #ifdef _LITTLE_ENDIAN 1146 return ((uint64_t)ntohl(nll & 0xffffffff) << 32 | ntohl(nll >> 32)); 1147 #else 1148 return (nll); 1149 #endif 1150 } 1151 1152 /* 1153 * Printing functions 1154 * 1155 * A potential point of confusion here is that the ikeadm-specific string- 1156 * producing functions do not match the ipsec_util.c versions in style: the 1157 * ikeadm-specific functions return a string (and are named foostr), while 1158 * the ipsec_util.c functions actually print the string to the file named 1159 * in the second arg to the function (and are named dump_foo). 1160 * 1161 * The reason for this is that in the context of the ikeadm output, it 1162 * seemed like the localization of the text would be more straightforward 1163 * (and could more easily accomodate non-english grammar!) if more complete 1164 * phrases were being translated, rather than a bit of a phrase followed by 1165 * a call to dump_foo() followed by more of the phrase. 1166 */ 1167 1168 static char * 1169 errstr(int err) 1170 { 1171 static char rtn[MAXLINESIZE]; 1172 1173 switch (err) { 1174 case IKE_ERR_NO_OBJ: 1175 return (gettext("No data returned")); 1176 case IKE_ERR_NO_DESC: 1177 return (gettext("No destination provided")); 1178 case IKE_ERR_ID_INVALID: 1179 return (gettext("Id info invalid")); 1180 case IKE_ERR_LOC_INVALID: 1181 return (gettext("Destination invalid")); 1182 case IKE_ERR_CMD_INVALID: 1183 return (gettext("Command invalid")); 1184 case IKE_ERR_DATA_INVALID: 1185 return (gettext("Supplied data invalid")); 1186 case IKE_ERR_CMD_NOTSUP: 1187 return (gettext("Unknown command")); 1188 case IKE_ERR_REQ_INVALID: 1189 return (gettext("Request invalid")); 1190 case IKE_ERR_NO_PRIV: 1191 return (gettext("Not allowed at current privilege level")); 1192 case IKE_ERR_SYS_ERR: 1193 return (gettext("System error")); 1194 case IKE_ERR_DUP_IGNORED: 1195 return (gettext("One or more duplicate entries ignored")); 1196 default: 1197 (void) snprintf(rtn, MAXLINESIZE, 1198 gettext("<unknown error %d>"), err); 1199 return (rtn); 1200 } 1201 } 1202 1203 static char * 1204 dbgstr(int bit) 1205 { 1206 static char rtn[MAXLINESIZE]; 1207 1208 switch (bit) { 1209 case D_CERT: 1210 return (gettext("Certificate management")); 1211 case D_KEY: 1212 return (gettext("Key management")); 1213 case D_OP: 1214 return (gettext("Operational")); 1215 case D_P1: 1216 return (gettext("Phase 1 SA creation")); 1217 case D_P2: 1218 return (gettext("Phase 2 SA creation")); 1219 case D_PFKEY: 1220 return (gettext("PF_KEY interface")); 1221 case D_POL: 1222 return (gettext("Policy management")); 1223 case D_PROP: 1224 return (gettext("Proposal construction")); 1225 case D_DOOR: 1226 return (gettext("Door interface")); 1227 case D_CONFIG: 1228 return (gettext("Config file processing")); 1229 default: 1230 (void) snprintf(rtn, MAXLINESIZE, 1231 gettext("<unknown flag 0x%x>"), bit); 1232 return (rtn); 1233 } 1234 } 1235 1236 static char * 1237 privstr(int priv) 1238 { 1239 static char rtn[MAXLINESIZE]; 1240 1241 switch (priv) { 1242 case IKE_PRIV_MINIMUM: 1243 return (gettext("base privileges")); 1244 case IKE_PRIV_MODKEYS: 1245 return (gettext("access to preshared key information")); 1246 case IKE_PRIV_KEYMAT: 1247 return (gettext("access to keying material")); 1248 default: 1249 (void) snprintf(rtn, MAXLINESIZE, 1250 gettext("<unknown level %d>"), priv); 1251 return (rtn); 1252 } 1253 } 1254 1255 static char * 1256 xchgstr(int xchg) 1257 { 1258 static char rtn[MAXLINESIZE]; 1259 1260 switch (xchg) { 1261 case IKE_XCHG_NONE: 1262 return (gettext("<unspecified>")); 1263 case IKE_XCHG_BASE: 1264 return (gettext("base")); 1265 case IKE_XCHG_IDENTITY_PROTECT: 1266 return (gettext("main mode (identity protect)")); 1267 case IKE_XCHG_AUTH_ONLY: 1268 return (gettext("authentication only")); 1269 case IKE_XCHG_AGGRESSIVE: 1270 return (gettext("aggressive mode")); 1271 case IKE_XCHG_IP_AND_AGGR: 1272 return (gettext("main and aggressive mode")); 1273 case IKE_XCHG_ANY: 1274 return (gettext("any mode")); 1275 default: 1276 (void) snprintf(rtn, MAXLINESIZE, 1277 gettext("<unknown %d>"), xchg); 1278 return (rtn); 1279 } 1280 } 1281 1282 static char * 1283 statestr(int state) 1284 { 1285 static char rtn[MAXLINESIZE]; 1286 1287 switch (state) { 1288 case IKE_SA_STATE_INIT: 1289 return (gettext("INITIALIZING")); 1290 case IKE_SA_STATE_SENT_SA: 1291 return (gettext("SENT FIRST MSG (SA)")); 1292 case IKE_SA_STATE_SENT_KE: 1293 return (gettext("SENT SECOND MSG (KE)")); 1294 case IKE_SA_STATE_SENT_LAST: 1295 return (gettext("SENT FINAL MSG")); 1296 case IKE_SA_STATE_DONE: 1297 return (gettext("ACTIVE")); 1298 case IKE_SA_STATE_DELETED: 1299 return (gettext("DELETED")); 1300 case IKE_SA_STATE_INVALID: 1301 return (gettext("<invalid>")); 1302 default: 1303 (void) snprintf(rtn, MAXLINESIZE, 1304 gettext("<unknown %d>"), state); 1305 return (rtn); 1306 } 1307 } 1308 1309 static char * 1310 authmethstr(int meth) 1311 { 1312 static char rtn[MAXLINESIZE]; 1313 1314 switch (meth) { 1315 case IKE_AUTH_METH_PRE_SHARED_KEY: 1316 return (gettext("pre-shared key")); 1317 case IKE_AUTH_METH_DSS_SIG: 1318 return (gettext("DSS signatures")); 1319 case IKE_AUTH_METH_RSA_SIG: 1320 return (gettext("RSA signatures")); 1321 case IKE_AUTH_METH_RSA_ENCR: 1322 return (gettext("RSA Encryption")); 1323 case IKE_AUTH_METH_RSA_ENCR_REVISED: 1324 return (gettext("Revised RSA Encryption")); 1325 default: 1326 (void) snprintf(rtn, MAXLINESIZE, 1327 gettext("<unknown %d>"), meth); 1328 return (rtn); 1329 } 1330 } 1331 1332 static char * 1333 prfstr(int prf) 1334 { 1335 static char rtn[MAXLINESIZE]; 1336 1337 switch (prf) { 1338 case IKE_PRF_NONE: 1339 return (gettext("<none/unavailable>")); 1340 case IKE_PRF_HMAC_MD5: 1341 return ("HMAC MD5"); 1342 case IKE_PRF_HMAC_SHA1: 1343 return ("HMAC SHA1"); 1344 case IKE_PRF_HMAC_SHA256: 1345 return ("HMAC SHA256"); 1346 case IKE_PRF_HMAC_SHA384: 1347 return ("HMAC SHA384"); 1348 case IKE_PRF_HMAC_SHA512: 1349 return ("HMAC SHA512"); 1350 default: 1351 (void) snprintf(rtn, MAXLINESIZE, 1352 gettext("<unknown %d>"), prf); 1353 return (rtn); 1354 } 1355 } 1356 1357 static char * 1358 dhstr(int grp) 1359 { 1360 static char rtn[MAXLINESIZE]; 1361 1362 switch (grp) { 1363 case 0: 1364 return (gettext("<unavailable>")); 1365 case IKE_GRP_DESC_MODP_768: 1366 return (gettext("768-bit MODP (group 1)")); 1367 case IKE_GRP_DESC_MODP_1024: 1368 return (gettext("1024-bit MODP (group 2)")); 1369 case IKE_GRP_DESC_EC2N_155: 1370 return (gettext("EC2N group on GP[2^155]")); 1371 case IKE_GRP_DESC_EC2N_185: 1372 return (gettext("EC2N group on GP[2^185]")); 1373 case IKE_GRP_DESC_MODP_1536: 1374 return (gettext("1536-bit MODP (group 5)")); 1375 case IKE_GRP_DESC_MODP_2048: 1376 return (gettext("2048-bit MODP (group 14)")); 1377 case IKE_GRP_DESC_MODP_3072: 1378 return (gettext("3072-bit MODP (group 15)")); 1379 case IKE_GRP_DESC_MODP_4096: 1380 return (gettext("4096-bit MODP (group 16)")); 1381 case IKE_GRP_DESC_MODP_6144: 1382 return (gettext("6144-bit MODP (group 17)")); 1383 case IKE_GRP_DESC_MODP_8192: 1384 return (gettext("8192-bit MODP (group 18)")); 1385 default: 1386 (void) snprintf(rtn, MAXLINESIZE, gettext("<unknown %d>"), grp); 1387 return (rtn); 1388 } 1389 } 1390 1391 static void 1392 print_hdr(char *prefix, ike_p1_hdr_t *hdrp) 1393 { 1394 (void) printf( 1395 gettext("%s Cookies: Initiator 0x%llx Responder 0x%llx\n"), 1396 prefix, ike_ntohll(hdrp->p1hdr_cookies.cky_i), 1397 ike_ntohll(hdrp->p1hdr_cookies.cky_r)); 1398 (void) printf(gettext("%s The local host is the %s.\n"), prefix, 1399 hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder")); 1400 (void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix, 1401 hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg)); 1402 (void) printf(gettext("%s Current state is %s"), prefix, 1403 statestr(hdrp->p1hdr_state)); 1404 (void) printf("\n"); 1405 } 1406 1407 static void 1408 print_lt_limits(char *prefix, ike_p1_xform_t *xfp) 1409 { 1410 (void) printf(gettext("%s Lifetime limits:\n"), prefix); 1411 (void) printf(gettext("%s %u seconds; %u kbytes protected; "), 1412 prefix, xfp->p1xf_max_secs, xfp->p1xf_max_kbytes); 1413 (void) printf(gettext("%u keymat provided.\n"), xfp->p1xf_max_keyuses); 1414 } 1415 1416 #define LT_USAGE_LEN 16 /* 1 uint64 + 2 uint32s */ 1417 static void 1418 print_lt_usage(char *prefix, ike_p1_stats_t *sp) 1419 { 1420 time_t scratch; 1421 char tbuf[TBUF_SIZE]; 1422 1423 (void) printf(gettext("%s Current usage:\n"), prefix); 1424 scratch = (time_t)sp->p1stat_start; 1425 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0) 1426 (void) strlcpy(tbuf, gettext("<time conversion failed>"), 1427 TBUF_SIZE); 1428 (void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf); 1429 (void) printf(gettext("%s %u kbytes protected; %u keymat provided.\n"), 1430 prefix, sp->p1stat_kbytes, sp->p1stat_keyuses); 1431 } 1432 1433 static void 1434 print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes) 1435 { 1436 (void) printf(gettext("%s Authentication method: %s"), prefix, 1437 authmethstr(xfp->p1xf_auth_meth)); 1438 (void) printf(gettext("\n%s Encryption alg: "), prefix); 1439 (void) dump_ealg(xfp->p1xf_encr_alg, stdout); 1440 if (xfp->p1xf_encr_low_bits != 0) { 1441 (void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits, 1442 xfp->p1xf_encr_high_bits); 1443 } else if ((xfp->p1xf_encr_low_bits == 0) && 1444 (xfp->p1xf_encr_high_bits != 0)) { 1445 /* 1446 * High bits is a placeholder for 1447 * negotiated algorithm strength 1448 */ 1449 (void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits); 1450 } 1451 (void) printf(gettext("; Authentication alg: ")); 1452 (void) dump_aalg(xfp->p1xf_auth_alg, stdout); 1453 (void) printf("\n%s ", prefix); 1454 if (xfp->p1xf_prf != 0) 1455 (void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf)); 1456 (void) printf(gettext("Oakley Group: %s\n"), 1457 dhstr(xfp->p1xf_dh_group)); 1458 if (xfp->p1xf_pfs == 0) { 1459 (void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix); 1460 } else { 1461 (void) printf(gettext( 1462 "%s Phase 2 PFS is required (Oakley Group: %s)\n"), 1463 prefix, dhstr(xfp->p1xf_pfs)); 1464 } 1465 1466 if (print_lifetimes) 1467 print_lt_limits(prefix, xfp); 1468 } 1469 1470 static void 1471 print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp, 1472 int statlen) 1473 { 1474 time_t current, remain, exp; 1475 char tbuf[TBUF_SIZE]; 1476 1477 current = time(NULL); 1478 1479 print_lt_limits(prefix, xfp); 1480 1481 /* 1482 * make sure the stats struct we've been passed is as big 1483 * as we expect it to be. The usage stats are at the end, 1484 * so anything less than the size we expect won't work. 1485 */ 1486 if (statlen >= sizeof (ike_p1_stats_t)) { 1487 print_lt_usage(prefix, sp); 1488 } else { 1489 return; 1490 } 1491 1492 (void) printf(gettext("%s Expiration info:\n"), prefix); 1493 1494 if (xfp->p1xf_max_kbytes != 0) 1495 (void) printf(gettext("%s %u more bytes can be protected.\n"), 1496 prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes); 1497 1498 if (xfp->p1xf_max_keyuses != 0) 1499 (void) printf(gettext("%s Keying material can be provided " 1500 "%u more times.\n"), prefix, 1501 xfp->p1xf_max_keyuses - sp->p1stat_keyuses); 1502 1503 if (xfp->p1xf_max_secs != 0) { 1504 exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs; 1505 remain = exp - current; 1506 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0) 1507 (void) strlcpy(tbuf, 1508 gettext("<time conversion failed>"), TBUF_SIZE); 1509 /* 1510 * The SA may have expired but still exist because libike 1511 * has not freed it yet. 1512 */ 1513 if (remain > 0) 1514 (void) printf(gettext( 1515 "%s SA expires in %lu seconds, at %s\n"), 1516 prefix, remain, tbuf); 1517 else 1518 (void) printf(gettext("%s SA Expired at %s\n"), 1519 prefix, tbuf); 1520 } 1521 } 1522 1523 /* used to verify structure lengths... */ 1524 #define COUNTER_32BIT 4 1525 #define COUNTER_PAIR 8 1526 1527 static void 1528 print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen, 1529 boolean_t print_lifetimes) 1530 { 1531 if (statlen < COUNTER_PAIR) 1532 return; 1533 (void) printf(gettext("%s %u Quick Mode SAs created; "), prefix, 1534 sp->p1stat_new_qm_sas); 1535 (void) printf(gettext("%u Quick Mode SAs deleted\n"), 1536 sp->p1stat_del_qm_sas); 1537 statlen -= COUNTER_PAIR; 1538 1539 if ((print_lifetimes) && (statlen >= LT_USAGE_LEN)) 1540 print_lt_usage(prefix, sp); 1541 } 1542 1543 static void 1544 print_errs(char *prefix, ike_p1_errors_t *errp, int errlen) 1545 { 1546 /* 1547 * Don't try to break this one up; it's either all or nothing! 1548 */ 1549 if (errlen < sizeof (ike_p1_errors_t)) 1550 return; 1551 1552 (void) printf(gettext("%s %u RX errors: "), prefix, 1553 errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx); 1554 (void) printf(gettext("%u decryption, %u hash, %u other\n"), 1555 errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx); 1556 (void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx); 1557 } 1558 1559 static void 1560 print_addr_range(char *prefix, ike_addr_pr_t *pr) 1561 { 1562 boolean_t range = B_TRUE; 1563 struct sockaddr_storage *beg, *end; 1564 struct sockaddr_in *bsin, *esin; 1565 struct sockaddr_in6 *bsin6, *esin6; 1566 1567 beg = &pr->beg_iprange; 1568 end = &pr->end_iprange; 1569 1570 if (beg->ss_family != end->ss_family) { 1571 (void) printf(gettext("%s invalid address range\n"), prefix); 1572 return; 1573 } 1574 1575 switch (beg->ss_family) { 1576 case AF_INET: 1577 bsin = (struct sockaddr_in *)beg; 1578 esin = (struct sockaddr_in *)end; 1579 if ((uint32_t)bsin->sin_addr.s_addr == 1580 (uint32_t)esin->sin_addr.s_addr) 1581 range = B_FALSE; 1582 break; 1583 case AF_INET6: 1584 bsin6 = (struct sockaddr_in6 *)beg; 1585 esin6 = (struct sockaddr_in6 *)end; 1586 if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr)) 1587 range = B_FALSE; 1588 break; 1589 default: 1590 (void) printf(gettext("%s invalid address range\n"), prefix); 1591 return; 1592 } 1593 1594 (void) printf("%s ", prefix); 1595 (void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag); 1596 if (range) { 1597 (void) printf(" - "); 1598 (void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout, 1599 nflag); 1600 } 1601 (void) printf("\n"); 1602 1603 } 1604 1605 /* 1606 * used to tell printing function if info should be identified 1607 * as belonging to initiator, responder, or neither 1608 */ 1609 #define IS_INITIATOR 1 1610 #define IS_RESPONDER 2 1611 #define DONT_PRINT_INIT 3 1612 1613 static void 1614 print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr) 1615 { 1616 (void) printf(gettext("%s Address"), prefix); 1617 1618 if (init_instr != DONT_PRINT_INIT) 1619 (void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ? 1620 gettext("Initiator") : gettext("Responder")); 1621 else 1622 (void) printf(":\n"); 1623 1624 (void) printf("%s ", prefix); 1625 (void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag); 1626 } 1627 1628 static void 1629 print_id(char *prefix, sadb_ident_t *idp, int init_instr) 1630 { 1631 boolean_t canprint; 1632 1633 switch (init_instr) { 1634 case IS_INITIATOR: 1635 (void) printf(gettext("%s Initiator identity, "), prefix); 1636 break; 1637 case IS_RESPONDER: 1638 (void) printf(gettext("%s Responder identity, "), prefix); 1639 break; 1640 case DONT_PRINT_INIT: 1641 (void) printf(gettext("%s Identity, "), prefix); 1642 break; 1643 default: 1644 (void) printf(gettext("<invalid identity>\n")); 1645 return; 1646 } 1647 (void) printf(gettext("uid=%d, type "), idp->sadb_ident_id); 1648 canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL); 1649 if (canprint) { 1650 (void) printf("\n%s %s\n", prefix, (char *)(idp + 1)); 1651 } else { 1652 (void) printf(gettext("\n%s "), prefix); 1653 print_asn1_name(stdout, 1654 (const unsigned char *)(idp + 1), 1655 SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t)); 1656 } 1657 } 1658 1659 static void 1660 print_idspec(char *prefix, char *idp, int icnt, int ecnt) 1661 { 1662 int i; 1663 1664 (void) printf(gettext("%s Identity descriptors:\n"), prefix); 1665 1666 for (i = 0; i < icnt; i++) { 1667 if (i == 0) 1668 (void) printf(gettext("%s Includes:\n"), prefix); 1669 (void) printf("%s %s\n", prefix, idp); 1670 idp += strlen(idp) + 1; 1671 } 1672 1673 for (i = 0; i < ecnt; i++) { 1674 if (i == 0) 1675 (void) printf(gettext("%s Excludes:\n"), prefix); 1676 (void) printf("%s %s\n", prefix, idp); 1677 idp += strlen(idp) + 1; 1678 } 1679 } 1680 1681 static void 1682 print_keys(char *prefix, ike_p1_key_t *keyp, int size) 1683 { 1684 uint32_t *curp; 1685 ike_p1_key_t *p; 1686 int ssize; 1687 1688 curp = (uint32_t *)keyp; 1689 1690 ssize = sizeof (ike_p1_key_t); 1691 1692 while ((intptr_t)curp - (intptr_t)keyp < size) { 1693 size_t p1klen, len; 1694 1695 p = (ike_p1_key_t *)curp; 1696 p1klen = p->p1key_len; 1697 len = p1klen - ssize; 1698 1699 p1klen = roundup(p1klen, sizeof (ike_p1_key_t)); 1700 if (p1klen < ssize) { 1701 (void) printf(gettext("Short key\n")); 1702 break; 1703 } 1704 1705 switch (p->p1key_type) { 1706 case IKE_KEY_PRESHARED: 1707 (void) printf(gettext("%s Pre-shared key (%d bytes): "), 1708 prefix, len); 1709 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1710 stdout); 1711 break; 1712 case IKE_KEY_SKEYID: 1713 (void) printf(gettext("%s SKEYID (%d bytes): "), 1714 prefix, len); 1715 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1716 stdout); 1717 break; 1718 case IKE_KEY_SKEYID_D: 1719 (void) printf(gettext("%s SKEYID_d (%d bytes): "), 1720 prefix, len); 1721 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1722 stdout); 1723 break; 1724 case IKE_KEY_SKEYID_A: 1725 (void) printf(gettext("%s SKEYID_a (%d bytes): "), 1726 prefix, len); 1727 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1728 stdout); 1729 break; 1730 case IKE_KEY_SKEYID_E: 1731 (void) printf(gettext("%s SKEYID_e (%d bytes): "), 1732 prefix, len); 1733 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1734 stdout); 1735 break; 1736 case IKE_KEY_ENCR: 1737 (void) printf(gettext("%s Encryption key (%d bytes): "), 1738 prefix, len); 1739 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1740 stdout); 1741 break; 1742 case IKE_KEY_IV: 1743 (void) printf( 1744 gettext("%s Initialization vector (%d bytes): "), 1745 prefix, len); 1746 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1747 stdout); 1748 break; 1749 default: 1750 (void) printf(gettext("%s Unidentified key info %p %d"), 1751 prefix, p, p1klen); 1752 } 1753 (void) printf("\n"); 1754 assert(IS_P2ALIGNED(p1klen, 8)); 1755 curp += (p1klen >> 2); 1756 } 1757 } 1758 1759 static void 1760 print_p1(ike_p1_sa_t *p1) 1761 { 1762 ike_p1_stats_t *sp; 1763 ike_p1_errors_t *ep; 1764 ike_p1_key_t *kp; 1765 sadb_ident_t *lidp, *ridp; 1766 int lstat, rstat; 1767 1768 (void) printf("\n"); 1769 print_hdr("IKESA:", &p1->p1sa_hdr); 1770 print_xform("XFORM:", &p1->p1sa_xform, B_FALSE); 1771 1772 if (p1->p1sa_hdr.p1hdr_isinit) { 1773 lstat = IS_INITIATOR; 1774 rstat = IS_RESPONDER; 1775 } else { 1776 lstat = IS_RESPONDER; 1777 rstat = IS_INITIATOR; 1778 } 1779 print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat); 1780 print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat); 1781 1782 /* 1783 * the stat len might be 0; but still make the call 1784 * to print_lifetime() to pick up the xform info 1785 */ 1786 sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off); 1787 print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len); 1788 1789 if (p1->p1sa_stat_len > 0) { 1790 print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE); 1791 } 1792 1793 if (p1->p1sa_error_len > 0) { 1794 ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off); 1795 print_errs("ERRS: ", ep, p1->p1sa_error_len); 1796 } 1797 1798 if (p1->p1sa_localid_len > 0) { 1799 lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off); 1800 print_id("LOCID:", lidp, lstat); 1801 } 1802 1803 if (p1->p1sa_remoteid_len > 0) { 1804 ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off); 1805 print_id("REMID:", ridp, rstat); 1806 } 1807 1808 if (p1->p1sa_key_len > 0) { 1809 kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off); 1810 print_keys("KEY: ", kp, p1->p1sa_key_len); 1811 } 1812 } 1813 1814 static void 1815 print_ps(ike_ps_t *ps) 1816 { 1817 sadb_ident_t *lidp, *ridp; 1818 uint8_t *keyp; 1819 1820 (void) printf("\n"); 1821 1822 (void) printf(gettext("PSKEY: For %s exchanges\n"), 1823 xchgstr(ps->ps_ike_mode)); 1824 1825 if (ps->ps_key_len > 0) { 1826 keyp = (uint8_t *)((int)(ps) + ps->ps_key_off); 1827 (void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "), 1828 ps->ps_key_len); 1829 (void) dump_key(keyp, ps->ps_key_bits, stdout); 1830 (void) printf("\n"); 1831 } 1832 1833 /* 1834 * We get *either* and address or an ident, never both. So if 1835 * the ident is there, don't try printing an address. 1836 */ 1837 if (ps->ps_localid_len > 0) { 1838 lidp = (sadb_ident_t *) 1839 ((int)(ps) + ps->ps_localid_off); 1840 print_id("LOCID:", lidp, DONT_PRINT_INIT); 1841 } else { 1842 print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT); 1843 } 1844 1845 if (ps->ps_remoteid_len > 0) { 1846 ridp = (sadb_ident_t *) 1847 ((int)(ps) + ps->ps_remoteid_off); 1848 print_id("REMID:", ridp, DONT_PRINT_INIT); 1849 } else { 1850 print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT); 1851 } 1852 } 1853 1854 #define PREFIXLEN 16 1855 1856 static void 1857 print_rule(ike_rule_t *rp) 1858 { 1859 char prefix[PREFIXLEN]; 1860 int i; 1861 ike_p1_xform_t *xfp; 1862 ike_addr_pr_t *lipp, *ripp; 1863 char *lidp, *ridp; 1864 1865 (void) printf("\n"); 1866 (void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"), 1867 rp->rule_label, rp->rule_kmcookie); 1868 (void) printf(gettext("GLOBL: local_idtype=")); 1869 (void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL); 1870 (void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode)); 1871 (void) printf(gettext( 1872 "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"), 1873 rp->rule_p1_nonce_len, rp->rule_p2_nonce_len, 1874 (rp->rule_p2_pfs) ? gettext("true") : gettext("false"), 1875 rp->rule_p2_pfs); 1876 (void) printf( 1877 gettext("GLOBL: p2_lifetime=%u seconds, p2_softlife=%u seconds\n"), 1878 rp->rule_p2_lifetime_secs, rp->rule_p2_softlife_secs); 1879 (void) printf( 1880 gettext("GLOBL: p2_lifetime_kb=%u seconds," 1881 " p2_softlife_kb=%u seconds\n"), 1882 rp->rule_p2_lifetime_kb, rp->rule_p2_softlife_kb); 1883 1884 if (rp->rule_locip_cnt > 0) { 1885 (void) printf(gettext("LOCIP: IP address range(s):\n")); 1886 lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off); 1887 for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) { 1888 print_addr_range("LOCIP:", lipp); 1889 } 1890 } 1891 1892 if (rp->rule_remip_cnt > 0) { 1893 (void) printf(gettext("REMIP: IP address range(s):\n")); 1894 ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off); 1895 for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) { 1896 print_addr_range("REMIP:", ripp); 1897 } 1898 } 1899 1900 if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) { 1901 lidp = (char *)((int)rp + rp->rule_locid_off); 1902 print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt, 1903 rp->rule_locid_exclcnt); 1904 } 1905 1906 if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) { 1907 ridp = (char *)((int)rp + rp->rule_remid_off); 1908 print_idspec("REMID:", ridp, rp->rule_remid_inclcnt, 1909 rp->rule_remid_exclcnt); 1910 } 1911 1912 if (rp->rule_xform_cnt > 0) { 1913 (void) printf(gettext("XFRMS: Available Transforms:\n")); 1914 xfp = (ike_p1_xform_t *)((int)rp + rp->rule_xform_off); 1915 for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) { 1916 (void) snprintf(prefix, PREFIXLEN, "XF %2u:", i); 1917 print_xform(prefix, xfp, B_TRUE); 1918 } 1919 } 1920 } 1921 1922 #undef PREFIXLEN 1923 1924 #define PRSACNTS(init, resp) \ 1925 (void) printf(gettext("initiator: %10u responder: %10u\n"), \ 1926 (init), (resp)) 1927 1928 static void 1929 print_stats(ike_stats_t *sp, int len) 1930 { 1931 /* 1932 * before printing each line, make sure the structure we were 1933 * given is big enough to include the fields needed. 1934 */ 1935 if (len < COUNTER_PAIR) 1936 return; 1937 (void) printf(gettext("Phase 1 SA counts:\n")); 1938 (void) printf(gettext("Current: ")); 1939 PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current); 1940 len -= COUNTER_PAIR; 1941 1942 if (len < COUNTER_PAIR) 1943 return; 1944 (void) printf(gettext("Total: ")); 1945 PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total); 1946 len -= COUNTER_PAIR; 1947 1948 if (len < COUNTER_PAIR) 1949 return; 1950 (void) printf(gettext("Attempted: ")); 1951 PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts); 1952 len -= COUNTER_PAIR; 1953 1954 if (len < (COUNTER_PAIR + COUNTER_32BIT)) 1955 return; 1956 (void) printf(gettext("Failed: ")); 1957 PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail, 1958 sp->st_resp_p1_fail); 1959 (void) printf( 1960 gettext(" initiator fails include %u time-out(s)\n"), 1961 sp->st_init_p1_noresp); 1962 1963 if (len < PATH_MAX) 1964 return; 1965 if (*(sp->st_pkcs11_libname) != '\0') 1966 (void) printf(gettext("PKCS#11 library linked in from %s\n"), 1967 sp->st_pkcs11_libname); 1968 } 1969 1970 static void 1971 print_defaults(char *label, char *description, char *unit, boolean_t kbytes, 1972 uint_t current, uint_t def) 1973 { 1974 (void) printf("%-18s%-10s%14u%s%-10s%-26s\n", label, 1975 (current != def) ? gettext("config") : gettext("default"), 1976 (current != def) ? current : def, (kbytes) ? "K " : " ", 1977 unit, description); 1978 } 1979 1980 /* 1981 * Print out defaults used by in.iked, the argument is a buffer containing 1982 * two ike_defaults_t's, the first contains the hard coded defaults, the second 1983 * contains the actual values used. If these differ, then the defaults have been 1984 * changed via a config file entry. Note that "-" indicates this default 1985 * is not tunable. 1986 */ 1987 static void 1988 do_print_defaults(ike_defaults_t *dp) 1989 { 1990 ike_defaults_t *ddp; 1991 ddp = (ike_defaults_t *)(dp + 1); 1992 1993 (void) printf(gettext("\nGlobal defaults. Some values can be" 1994 " over-ridden on a per rule basis.\n\n")); 1995 1996 (void) printf("%-18s%-10s%-16s%-10s%-26s\n\n", 1997 gettext("Token:"), gettext("Source:"), gettext("Value:"), 1998 gettext("Unit:"), gettext("Description:")); 1999 2000 print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"), 2001 gettext("seconds"), B_FALSE, ddp->rule_p1_lifetime_secs, 2002 dp->rule_p1_lifetime_secs); 2003 2004 print_defaults("-", gettext("minimum phase 1 lifetime"), 2005 gettext("seconds"), B_FALSE, ddp->rule_p1_minlife, 2006 dp->rule_p1_minlife); 2007 2008 print_defaults("p1_nonce_len", gettext("phase 1 nonce length"), 2009 gettext("bytes"), B_FALSE, ddp->rule_p1_nonce_len, 2010 dp->rule_p1_nonce_len); 2011 2012 print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"), 2013 gettext("seconds"), B_FALSE, ddp->rule_p2_lifetime_secs, 2014 dp->rule_p2_lifetime_secs); 2015 2016 print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"), 2017 gettext("seconds"), B_FALSE, ddp->rule_p2_softlife_secs, 2018 dp->rule_p2_softlife_secs); 2019 2020 print_defaults("-", gettext("system phase 2 lifetime"), 2021 gettext("seconds"), B_FALSE, ddp->sys_p2_lifetime_secs, 2022 dp->sys_p2_lifetime_secs); 2023 2024 print_defaults("-", gettext("system phase 2 soft lifetime"), 2025 gettext("seconds"), B_FALSE, ddp->sys_p2_softlife_secs, 2026 dp->sys_p2_softlife_secs); 2027 2028 print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"), 2029 gettext("bytes"), B_TRUE, ddp->rule_p2_lifetime_kb, 2030 dp->rule_p2_lifetime_kb); 2031 2032 print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"), 2033 gettext("bytes"), B_TRUE, ddp->rule_p2_softlife_kb, 2034 dp->rule_p2_softlife_kb); 2035 2036 print_defaults("-", gettext("system phase 2 lifetime"), 2037 gettext("bytes"), B_FALSE, ddp->sys_p2_lifetime_bytes, 2038 dp->sys_p2_lifetime_bytes); 2039 2040 print_defaults("-", gettext("system phase 2 soft lifetime"), 2041 gettext("bytes"), B_FALSE, ddp->sys_p2_softlife_bytes, 2042 dp->sys_p2_softlife_bytes); 2043 2044 print_defaults("-", gettext("minimum phase 2 lifetime"), 2045 gettext("seconds"), B_FALSE, ddp->rule_p2_minlife, 2046 dp->rule_p2_minlife); 2047 2048 print_defaults("p2_nonce_len", gettext("phase 2 nonce length"), 2049 gettext("bytes"), B_FALSE, ddp->rule_p2_nonce_len, 2050 dp->rule_p2_nonce_len); 2051 2052 print_defaults("-", gettext("default phase 2 lifetime"), 2053 gettext("seconds"), B_FALSE, ddp->rule_p2_def_minlife, 2054 dp->rule_p2_def_minlife); 2055 2056 print_defaults("-", gettext("minimum phase 2 soft delta"), 2057 gettext("seconds"), B_FALSE, ddp->rule_p2_minsoft, 2058 dp->rule_p2_minsoft); 2059 2060 print_defaults("p2_pfs", gettext("phase 2 PFS"), 2061 " ", B_FALSE, ddp->rule_p2_pfs, dp->rule_p2_pfs); 2062 2063 print_defaults("max_certs", gettext("max certificates"), 2064 " ", B_FALSE, ddp->rule_max_certs, dp->rule_max_certs); 2065 2066 print_defaults("-", gettext("IKE port number"), 2067 " ", B_FALSE, ddp->rule_ike_port, dp->rule_ike_port); 2068 2069 print_defaults("-", gettext("NAT-T port number"), 2070 " ", B_FALSE, ddp->rule_natt_port, dp->rule_natt_port); 2071 } 2072 2073 static void 2074 print_categories(int level) 2075 { 2076 int mask; 2077 2078 if (level == 0) { 2079 (void) printf(gettext("No debug categories enabled.\n")); 2080 return; 2081 } 2082 2083 (void) printf(gettext("Debug categories enabled:")); 2084 for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) { 2085 if (level & mask) 2086 (void) printf("\n\t%s", dbgstr(mask)); 2087 } 2088 (void) printf("\n"); 2089 } 2090 2091 /*PRINTFLIKE2*/ 2092 static void 2093 ikeadm_err_exit(ike_err_t *err, char *fmt, ...) 2094 { 2095 va_list ap; 2096 char bailbuf[BUFSIZ]; 2097 2098 va_start(ap, fmt); 2099 (void) vsnprintf(bailbuf, BUFSIZ, fmt, ap); 2100 va_end(ap); 2101 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) { 2102 bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ? 2103 gettext("<unknown error>") : strerror(err->ike_err_unix)); 2104 } else { 2105 bail_msg("%s: %s", bailbuf, (err == NULL) ? 2106 gettext("<unknown error>") : errstr(err->ike_err)); 2107 } 2108 } 2109 2110 /*PRINTFLIKE2*/ 2111 static void 2112 ikeadm_err_msg(ike_err_t *err, char *fmt, ...) 2113 { 2114 va_list ap; 2115 char mbuf[BUFSIZ]; 2116 2117 va_start(ap, fmt); 2118 (void) vsnprintf(mbuf, BUFSIZ, fmt, ap); 2119 va_end(ap); 2120 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) { 2121 message("%s: %s", mbuf, (err->ike_err_unix == 0) ? 2122 gettext("<unknown error>") : 2123 ((err->ike_err_unix == EEXIST) ? 2124 gettext("Duplicate entry") : 2125 strerror(err->ike_err_unix))); 2126 } else { 2127 message("%s: %s", mbuf, (err == NULL) ? 2128 gettext("<unknown error>") : errstr(err->ike_err)); 2129 } 2130 } 2131 2132 2133 /* 2134 * Command functions 2135 */ 2136 2137 /* 2138 * Exploit the fact that ike_dbg_t and ike_priv_t have identical 2139 * formats in the following two functions. 2140 */ 2141 static void 2142 do_getvar(int cmd) 2143 { 2144 ike_service_t req, *rtn; 2145 ike_dbg_t *dreq; 2146 char *varname; 2147 2148 switch (cmd) { 2149 case IKE_SVC_GET_DBG: 2150 varname = gettext("debug"); 2151 break; 2152 case IKE_SVC_GET_PRIV: 2153 varname = gettext("privilege"); 2154 break; 2155 default: 2156 bail_msg(gettext("unrecognized get command (%d)"), cmd); 2157 } 2158 2159 dreq = &req.svc_dbg; 2160 dreq->cmd = cmd; 2161 dreq->dbg_level = 0; 2162 2163 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0); 2164 2165 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2166 ikeadm_err_exit(&rtn->svc_err, 2167 gettext("error getting %s level"), varname); 2168 } 2169 dreq = &rtn->svc_dbg; 2170 (void) printf(gettext("Current %s level is 0x%x"), 2171 varname, dreq->dbg_level); 2172 2173 if (cmd == IKE_SVC_GET_DBG) { 2174 (void) printf("\n"); 2175 print_categories(dreq->dbg_level); 2176 } else { 2177 (void) printf(gettext(", %s enabled\n"), 2178 privstr(dreq->dbg_level)); 2179 } 2180 } 2181 2182 static void 2183 do_setvar(int cmd, int argc, char **argv) 2184 { 2185 ike_service_t req, *rtn; 2186 ike_dbg_t *dreq; 2187 door_desc_t *descp = NULL, desc; 2188 int fd, ndesc = 0; 2189 uint32_t reqlevel; 2190 char *varname; 2191 2192 if (argc < 1) 2193 Bail("unspecified level"); 2194 reqlevel = strtoul(argv[0], NULL, 0); 2195 2196 switch (cmd) { 2197 case IKE_SVC_SET_DBG: 2198 if (argc > 2) 2199 Bail("Too many arguments to \"set debug\""); 2200 varname = gettext("debug"); 2201 if (reqlevel == 0) { 2202 /* check for a string... */ 2203 reqlevel = parsedbgopts(argv[0]); 2204 } 2205 if (reqlevel == D_INVALID) 2206 bail_msg(gettext("Bad debug flag: %s"), argv[0]); 2207 break; 2208 case IKE_SVC_SET_PRIV: 2209 if (argc > 1) 2210 Bail("Too many arguments to \"set priv\""); 2211 2212 varname = gettext("privilege"); 2213 if (reqlevel == 0) { 2214 /* check for a string... */ 2215 reqlevel = privstr2num(argv[0]); 2216 } 2217 if (reqlevel > IKE_PRIV_MAXIMUM) 2218 bail_msg(gettext("Bad privilege flag: %s"), argv[0]); 2219 break; 2220 default: 2221 bail_msg(gettext("unrecognized set command (%d)"), cmd); 2222 } 2223 2224 dreq = &req.svc_dbg; 2225 dreq->cmd = cmd; 2226 dreq->dbg_level = reqlevel; 2227 2228 if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) { 2229 fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND, 2230 S_IRUSR | S_IWUSR); 2231 if (fd < 0) 2232 Bail("open debug file"); 2233 desc.d_data.d_desc.d_descriptor = fd; 2234 desc.d_attributes = DOOR_DESCRIPTOR; 2235 descp = &desc; 2236 ndesc = 1; 2237 } 2238 2239 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc); 2240 2241 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2242 ikeadm_err_exit(&rtn->svc_err, 2243 gettext("error setting %s level"), varname); 2244 } 2245 dreq = &rtn->svc_dbg; 2246 (void) printf( 2247 gettext("Successfully changed %s level from 0x%x to 0x%x\n"), 2248 varname, dreq->dbg_level, reqlevel); 2249 2250 if (cmd == IKE_SVC_SET_DBG) { 2251 print_categories(reqlevel); 2252 } else { 2253 (void) printf(gettext("New privilege level 0x%x enables %s\n"), 2254 reqlevel, privstr(reqlevel)); 2255 } 2256 } 2257 2258 static void 2259 do_getstats(int cmd) 2260 { 2261 ike_service_t *rtn; 2262 ike_statreq_t sreq, *sreqp; 2263 ike_stats_t *sp; 2264 2265 sreq.cmd = cmd; 2266 2267 rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0); 2268 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2269 ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats")); 2270 } 2271 2272 sreqp = &rtn->svc_stats; 2273 sp = (ike_stats_t *)(sreqp + 1); 2274 print_stats(sp, sreqp->stat_len); 2275 } 2276 2277 static void 2278 do_getdefs(int cmd) 2279 { 2280 ike_service_t *rtn; 2281 ike_defreq_t dreq, *dreqp; 2282 ike_defaults_t *dp; 2283 2284 dreq.cmd = cmd; 2285 2286 rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0); 2287 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2288 ikeadm_err_exit(&rtn->svc_err, 2289 gettext("error getting defaults")); 2290 } 2291 2292 dreqp = &rtn->svc_defaults; 2293 dp = (ike_defaults_t *)(dreqp + 1); 2294 2295 /* 2296 * Before printing each line, make sure the structure we were 2297 * given is big enough to include the fields needed. 2298 * Silently bail out of there is a version mismatch. 2299 */ 2300 if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t)) 2301 + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) { 2302 return; 2303 } 2304 do_print_defaults(dp); 2305 } 2306 2307 static void 2308 do_dump(int cmd) 2309 { 2310 char *name; 2311 ike_service_t req, *rtn; 2312 ike_dump_t *dreq, *dump; 2313 2314 switch (cmd) { 2315 case IKE_SVC_DUMP_P1S: 2316 name = gettext("phase 1 SA info"); 2317 break; 2318 case IKE_SVC_DUMP_RULES: 2319 name = gettext("policy rules"); 2320 break; 2321 case IKE_SVC_DUMP_PS: 2322 name = gettext("preshared keys"); 2323 break; 2324 default: 2325 bail_msg(gettext("unrecognized dump command (%d)"), cmd); 2326 } 2327 2328 dreq = &req.svc_dump; 2329 dreq->cmd = cmd; 2330 dreq->dump_len = 0; 2331 dreq->dump_next = 0; 2332 do { 2333 rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t), 2334 NULL, 0); 2335 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2336 if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) { 2337 /* no entries to print */ 2338 break; 2339 } 2340 ikeadm_err_exit(&rtn->svc_err, 2341 gettext("error getting %s"), name); 2342 } 2343 dump = &rtn->svc_dump; 2344 2345 switch (cmd) { 2346 case IKE_SVC_DUMP_P1S: 2347 print_p1((ike_p1_sa_t *)(dump + 1)); 2348 break; 2349 case IKE_SVC_DUMP_RULES: 2350 print_rule((ike_rule_t *)(dump + 1)); 2351 break; 2352 case IKE_SVC_DUMP_PS: 2353 print_ps((ike_ps_t *)(dump + 1)); 2354 break; 2355 } 2356 2357 dreq->dump_next = dump->dump_next; 2358 2359 (void) munmap((char *)rtn, dump->dump_len); 2360 2361 } while (dreq->dump_next); 2362 2363 (void) printf(gettext("\nCompleted dump of %s\n"), name); 2364 } 2365 2366 static void 2367 do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name) 2368 { 2369 int totallen; 2370 char *p; 2371 ike_service_t *reqp, *rtnp; 2372 ike_get_t *getp; 2373 boolean_t getcmd; 2374 2375 getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) || 2376 (cmd == IKE_SVC_GET_PS)); 2377 2378 /* 2379 * WARNING: to avoid being redundant, this code takes advantage 2380 * of the fact that the ike_get_t and ike_del_t structures are 2381 * identical (only the field names differ, their function and 2382 * size are the same). If for some reason those structures 2383 * change, this code will need to be re-written to accomodate 2384 * that difference. 2385 */ 2386 totallen = sizeof (ike_get_t) + idlen; 2387 if ((reqp = (ike_service_t *)malloc(totallen)) == NULL) 2388 Bail("malloc(id)"); 2389 2390 getp = &reqp->svc_get; 2391 getp->cmd = cmd; 2392 getp->get_len = totallen; 2393 getp->get_idtype = idtype; 2394 p = (char *)(getp + 1); 2395 2396 (void) memcpy(p, idp, idlen); 2397 2398 rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0); 2399 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2400 if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) { 2401 message(gettext("Could not find requested %s."), name); 2402 } else { 2403 ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"), 2404 (getcmd) ? gettext("getting") : gettext("deleting"), 2405 name); 2406 } 2407 free(reqp); 2408 return; 2409 } 2410 getp = &rtnp->svc_get; 2411 2412 if (getcmd) { 2413 switch (cmd) { 2414 case IKE_SVC_GET_P1: 2415 print_p1((ike_p1_sa_t *)(getp + 1)); 2416 break; 2417 case IKE_SVC_GET_PS: 2418 print_ps((ike_ps_t *)(getp + 1)); 2419 break; 2420 case IKE_SVC_GET_RULE: 2421 print_rule((ike_rule_t *)(getp + 1)); 2422 break; 2423 } 2424 } else { 2425 message(gettext("Successfully deleted selected %s."), name); 2426 } 2427 2428 (void) munmap((char *)rtnp, getp->get_len); 2429 free(reqp); 2430 } 2431 2432 static void 2433 do_getdel(int cmd, int argc, char **argv) 2434 { 2435 int idlen, idtype = 0, i, j; 2436 int bytelen1, bytelen2; 2437 char *name, *idp, *p, *p1, *p2; 2438 ike_addr_pr_t apr; 2439 ike_cky_pr_t cpr; 2440 sadb_ident_t *sid1p, *sid2p; 2441 struct hostent *he1p, *he2p; 2442 char label[MAX_LABEL_LEN]; 2443 2444 if ((argc < 1) || (argv[0] == NULL)) { 2445 Bail("not enough identification info"); 2446 } 2447 2448 switch (cmd) { 2449 case IKE_SVC_GET_P1: 2450 case IKE_SVC_DEL_P1: 2451 name = gettext("phase 1 SA"); 2452 /* 2453 * The first token must either be an address (or hostname) 2454 * or a cookie. We require cookies to be entered as hex 2455 * numbers, beginning with 0x; so if our token starts with 2456 * that, it's a cookie. 2457 */ 2458 if (strncmp(argv[0], "0x", 2) == 0) { 2459 if (parse_cky_pr(argc, argv, &cpr) >= 0) { 2460 idtype = IKE_ID_CKY_PAIR; 2461 idlen = sizeof (ike_cky_pr_t); 2462 idp = (char *)&cpr; 2463 } 2464 } else { 2465 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) { 2466 idtype = IKE_ID_ADDR_PAIR; 2467 idlen = sizeof (ike_addr_pr_t); 2468 } 2469 } 2470 break; 2471 2472 case IKE_SVC_GET_RULE: 2473 case IKE_SVC_DEL_RULE: 2474 name = gettext("policy rule"); 2475 if (parse_label(argc, argv, label) >= 0) { 2476 idtype = IKE_ID_LABEL; 2477 idlen = MAX_LABEL_LEN; 2478 idp = label; 2479 } 2480 break; 2481 2482 case IKE_SVC_GET_PS: 2483 case IKE_SVC_DEL_PS: 2484 name = gettext("preshared key"); 2485 /* 2486 * The first token must either be an address or an ident 2487 * type. Check for an ident type to determine which it is. 2488 */ 2489 if (parse_idtype(argv[0], NULL) >= 0) { 2490 if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) { 2491 idtype = IKE_ID_IDENT_PAIR; 2492 idlen = SADB_64TO8(sid1p->sadb_ident_len) + 2493 SADB_64TO8(sid2p->sadb_ident_len); 2494 } 2495 } else { 2496 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) { 2497 idtype = IKE_ID_ADDR_PAIR; 2498 idlen = sizeof (ike_addr_pr_t); 2499 } 2500 } 2501 break; 2502 2503 default: 2504 bail_msg(gettext("unrecognized get/del command (%d)"), cmd); 2505 } 2506 2507 switch (idtype) { 2508 case IKE_ID_ADDR_PAIR: 2509 /* 2510 * we might have exploding addrs here; do every possible 2511 * combination. 2512 */ 2513 i = 0; 2514 j = 0; 2515 while ((p1 = he1p->h_addr_list[i++]) != NULL) { 2516 headdr2sa(p1, &apr.loc_addr, he1p->h_length); 2517 2518 while ((p2 = he2p->h_addr_list[j++]) != NULL) { 2519 headdr2sa(p2, &apr.rem_addr, he2p->h_length); 2520 do_getdel_doorcall(cmd, idlen, idtype, 2521 (char *)&apr, name); 2522 } 2523 } 2524 FREE_HE(he1p); 2525 FREE_HE(he2p); 2526 break; 2527 2528 case IKE_ID_IDENT_PAIR: 2529 bytelen1 = SADB_64TO8(sid1p->sadb_ident_len); 2530 bytelen2 = SADB_64TO8(sid2p->sadb_ident_len); 2531 if (idlen != bytelen1 + bytelen2) 2532 Bail("ident syntax error"); 2533 idp = p = (char *)malloc(idlen); 2534 if (p == NULL) 2535 Bail("malloc(id)"); 2536 (void) memcpy(p, (char *)sid1p, bytelen1); 2537 p += bytelen1; 2538 (void) memcpy(p, (char *)sid2p, bytelen2); 2539 do_getdel_doorcall(cmd, idlen, idtype, idp, name); 2540 free(idp); 2541 free(sid1p); 2542 free(sid2p); 2543 break; 2544 2545 case IKE_ID_CKY_PAIR: 2546 case IKE_ID_LABEL: 2547 do_getdel_doorcall(cmd, idlen, idtype, idp, name); 2548 break; 2549 2550 case 0: 2551 default: 2552 bail_msg(gettext("invalid %s identification\n"), name); 2553 } 2554 } 2555 2556 /* 2557 * Copy source into target, inserting an escape character ('\') before 2558 * any quotes that appear. Return true on success, false on failure. 2559 */ 2560 static boolean_t 2561 escapequotes(char *target, char *source, int tlen) 2562 { 2563 int s, t, len = strlen(source) + 1; 2564 2565 if (tlen < len) 2566 return (B_FALSE); 2567 2568 for (s = 0, t = 0; s < len && t < tlen; s++) { 2569 if (source[s] == '\"') 2570 target[t++] = '\\'; 2571 target[t++] = source[s]; 2572 } 2573 2574 if ((t == tlen) && (s < len)) 2575 return (B_FALSE); 2576 2577 return (B_TRUE); 2578 } 2579 2580 /* 2581 * Return true if the arg following the given keyword should 2582 * be in quotes (i.e. is a string), false if not. 2583 */ 2584 static boolean_t 2585 quotedfield(char *keywd) 2586 { 2587 if ((strncmp(keywd, "label", strlen("label") + 1) == 0) || 2588 (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) || 2589 (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0)) 2590 return (B_TRUE); 2591 2592 return (B_FALSE); 2593 } 2594 2595 static void 2596 do_new(int cmd, int argc, char **argv) 2597 { 2598 ike_service_t *rtn; 2599 ike_new_t new, *newp = NULL; 2600 door_desc_t desc, *descp = NULL; 2601 int i, fd, ndesc = 0, buflen; 2602 char *name, tmpfilepath[32]; 2603 FILE *tmpfile; 2604 2605 switch (cmd) { 2606 case IKE_SVC_NEW_PS: 2607 name = gettext("preshared key"); 2608 break; 2609 case IKE_SVC_NEW_RULE: 2610 name = gettext("policy rule"); 2611 break; 2612 default: 2613 bail_msg(gettext("unrecognized new command (%d)"), cmd); 2614 } 2615 2616 if (argc == 1) { 2617 /* We've been given a file to read from */ 2618 fd = open(argv[0], O_RDONLY); 2619 if (fd < 0) 2620 Bail("open source file"); 2621 2622 desc.d_data.d_desc.d_descriptor = fd; 2623 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2624 descp = &desc; 2625 ndesc = 1; 2626 2627 new.cmd = cmd; 2628 new.new_len = 0; 2629 newp = &new; 2630 buflen = sizeof (ike_new_t); 2631 2632 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) { 2633 /* 2634 * This is an alternative to using the tmpfile method 2635 * for preshared keys. It means we're duplicating the 2636 * parsing effort that happens in readps.c; but it 2637 * does avoid having the key sitting in a file. 2638 */ 2639 ike_ps_t *psp; 2640 int pslen; 2641 2642 /* 2643 * must be in interactive mode; don't want keys in 2644 * the process args. 2645 */ 2646 if (!interactive) 2647 Bail("Must be in interactive mode to add key info."); 2648 if (parse_ps(argc, argv, &psp, &pslen) < 0) { 2649 errno = 0; 2650 Bail("invalid preshared key definition"); 2651 } 2652 newp = malloc(sizeof (ike_new_t) + pslen); 2653 if (newp == NULL) 2654 Bail("alloc pskey"); 2655 newp->cmd = cmd; 2656 newp->new_len = sizeof (ike_new_t) + pslen; 2657 (void) memcpy((char *)(newp + 1), psp, pslen); 2658 buflen = newp->new_len; 2659 /* parse_ps allocated the ike_ps_t buffer; free it now */ 2660 free(psp); 2661 2662 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) { 2663 /* 2664 * We've been given the item in argv. However, parsing 2665 * rules can get more than a little messy, and in.iked 2666 * already has a great parser for this stuff! So don't 2667 * fool around with trying to do the parsing here. Just 2668 * write it out to a tempfile, and send the fd to in.iked. 2669 * 2670 * We could conceivably do this for preshared keys, 2671 * rather than duplicating the parsing effort; but that 2672 * would mean the key would be written out to a file, 2673 * which isn't such a good idea. 2674 */ 2675 boolean_t doquotes = B_FALSE; 2676 int rtn; 2677 2678 if ((argv[0][0] != '{') || 2679 (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}')) 2680 bail_msg(gettext("improperly formatted %s"), name); 2681 2682 /* attempt to use a fairly unpredictable file name... */ 2683 (void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime()); 2684 fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL, 2685 S_IRUSR | S_IWUSR); 2686 if (fd < 0) 2687 Bail("cannot open tmpfile"); 2688 2689 /* and make it inaccessible asap */ 2690 if (unlink(tmpfilepath) < 0) { 2691 (void) close(fd); 2692 Bail("tmpfile error"); 2693 } 2694 2695 tmpfile = fdopen(fd, "w"); 2696 if (tmpfile == NULL) { 2697 (void) close(fd); 2698 Bail("cannot write to tmpfile"); 2699 } 2700 2701 for (i = 0; i < argc; i++) { 2702 /* 2703 * We have to do some gyrations with our string here, 2704 * to properly handle quotes. There are two issues: 2705 * - some of the fields of a rule may have embedded 2706 * whitespace, and thus must be quoted on the cmd 2707 * line. The shell removes the quotes, and gives 2708 * us a single argv string; but we need to put the 2709 * quotes back in when we write the string out to 2710 * file. The doquotes boolean is set when we 2711 * process a keyword which will be followed by a 2712 * string value (so the NEXT argv element will be 2713 * quoted). 2714 * - there might be a quote character in a field, 2715 * that was escaped on the cmdline. The shell 2716 * removes the escape char, and leaves the quote 2717 * in the string it gives us. We need to put the 2718 * escape char back in before writing to file. 2719 */ 2720 char field[MAXLINESIZE]; 2721 if (!escapequotes(field, argv[i], MAXLINESIZE)) 2722 Bail("write to tmpfile failed (arg too big)"); 2723 if (doquotes) { 2724 rtn = fprintf(tmpfile, "\"%s\"\n", field); 2725 doquotes = B_FALSE; 2726 } else { 2727 rtn = fprintf(tmpfile, "%s\n", field); 2728 } 2729 if (rtn < 0) 2730 Bail("write to tmpfile failed"); 2731 /* 2732 * check if this is a keyword identifying 2733 * a field that needs to be quoted. 2734 */ 2735 doquotes = quotedfield(argv[i]); 2736 } 2737 if (fflush(tmpfile) == EOF) 2738 Bail("write to tmpfile failed"); 2739 /* rewind so that the daemon will get the beginning */ 2740 rewind(tmpfile); 2741 2742 desc.d_data.d_desc.d_descriptor = fd; 2743 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2744 descp = &desc; 2745 ndesc = 1; 2746 2747 new.cmd = cmd; 2748 new.new_len = 0; 2749 newp = &new; 2750 buflen = sizeof (ike_new_t); 2751 2752 } else { 2753 /* not enough information! */ 2754 bail_msg(gettext("missing %s description or file name"), name); 2755 } 2756 2757 rtn = ikedoor_call((char *)newp, buflen, descp, ndesc); 2758 2759 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2760 ikeadm_err_msg(&rtn->svc_err, 2761 gettext("error creating new %s"), name); 2762 } else { 2763 message(gettext("Successfully created new %s."), name); 2764 } 2765 } 2766 2767 static void 2768 do_flush(int cmd) 2769 { 2770 ike_service_t *rtnp; 2771 ike_flush_t flush; 2772 2773 if (cmd != IKE_SVC_FLUSH_P1S) { 2774 bail_msg(gettext("unrecognized flush command (%d)."), cmd); 2775 } 2776 2777 flush.cmd = cmd; 2778 2779 rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0); 2780 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2781 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush")); 2782 } 2783 message(gettext("Successfully flushed P1 SAs.")); 2784 } 2785 2786 static void 2787 do_rw(int cmd, int argc, char **argv) 2788 { 2789 ike_service_t *rtnp; 2790 ike_rw_t rw; 2791 door_desc_t desc, *descp = NULL; 2792 int oflag, omode, fd, ndesc = 0; 2793 char *op, *obj = NULL; 2794 boolean_t writing = B_FALSE; 2795 2796 switch (cmd) { 2797 case IKE_SVC_READ_PS: 2798 obj = gettext("preshared key"); 2799 /* FALLTHRU */ 2800 case IKE_SVC_READ_RULES: 2801 if (obj == NULL) 2802 obj = gettext("policy rule"); 2803 op = gettext("read"); 2804 oflag = O_RDONLY; 2805 omode = 0; 2806 break; 2807 2808 case IKE_SVC_WRITE_PS: 2809 obj = gettext("preshared key"); 2810 /* FALLTHRU */ 2811 case IKE_SVC_WRITE_RULES: 2812 if (obj == NULL) 2813 obj = gettext("policy rule"); 2814 op = gettext("write"); 2815 oflag = O_RDWR | O_CREAT | O_EXCL; 2816 omode = S_IRUSR | S_IWUSR; 2817 2818 /* for write commands, dest location must be specified */ 2819 if (argc < 1) { 2820 bail_msg(gettext("destination location required " 2821 "to write %ss"), obj); 2822 } 2823 writing = B_TRUE; 2824 break; 2825 2826 default: 2827 bail_msg(gettext("unrecognized read/write command (%d)."), cmd); 2828 } 2829 2830 rw.cmd = cmd; 2831 2832 if (argc >= 1) { 2833 rw.rw_loc = IKE_RW_LOC_USER_SPEC; 2834 fd = open(argv[0], oflag, omode); 2835 if (fd < 0) 2836 Bail("open user-specified file"); 2837 2838 desc.d_data.d_desc.d_descriptor = fd; 2839 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2840 descp = &desc; 2841 ndesc = 1; 2842 } else { 2843 rw.rw_loc = IKE_RW_LOC_DEFAULT; 2844 } 2845 2846 rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc); 2847 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2848 /* 2849 * Need to remove the target file in the 2850 * case of a failed write command. 2851 */ 2852 if (writing) { 2853 /* 2854 * argv[0] must be valid if we're writing; we 2855 * exit before setting this boolean if not. 2856 */ 2857 (void) unlink(argv[0]); 2858 (void) close(fd); 2859 2860 if ((rtnp != NULL) && 2861 (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) { 2862 message(gettext("No %s information to write."), 2863 obj); 2864 return; 2865 } 2866 } 2867 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op); 2868 } 2869 message(gettext("Completed %s of %s configuration information."), 2870 op, obj); 2871 } 2872 2873 static void 2874 do_rbdump() 2875 { 2876 ike_cmd_t req; 2877 ike_service_t *rtnp; 2878 2879 req.cmd = IKE_SVC_DBG_RBDUMP; 2880 2881 rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0); 2882 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2883 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush")); 2884 } 2885 message(gettext("Successfully dumped rulebase; check iked dbg")); 2886 } 2887 2888 #define REQ_ARG_CNT 1 2889 2890 /*ARGSUSED*/ 2891 static void 2892 parseit(int argc, char **argv, char *notused, boolean_t notused_either) 2893 { 2894 int cmd, cmd_obj_args = 1; 2895 char *cmdstr, *objstr; 2896 2897 if (interactive) { 2898 if (argc == 0) 2899 return; 2900 } 2901 2902 if (argc < REQ_ARG_CNT) { 2903 usage(); 2904 } 2905 2906 cmdstr = argv[0]; 2907 if (argc > REQ_ARG_CNT) { 2908 cmd_obj_args++; 2909 objstr = argv[1]; 2910 } else { 2911 objstr = NULL; 2912 } 2913 cmd = parsecmd(cmdstr, objstr); 2914 2915 /* skip over args specifying command/object */ 2916 argc -= cmd_obj_args; 2917 argv += cmd_obj_args; 2918 2919 switch (cmd) { 2920 case IKE_SVC_GET_DEFS: 2921 do_getdefs(cmd); 2922 break; 2923 case IKE_SVC_GET_DBG: 2924 case IKE_SVC_GET_PRIV: 2925 do_getvar(cmd); 2926 break; 2927 case IKE_SVC_GET_STATS: 2928 do_getstats(cmd); 2929 break; 2930 case IKE_SVC_SET_DBG: 2931 case IKE_SVC_SET_PRIV: 2932 do_setvar(cmd, argc, argv); 2933 break; 2934 case IKE_SVC_DUMP_P1S: 2935 case IKE_SVC_DUMP_RULES: 2936 case IKE_SVC_DUMP_PS: 2937 do_dump(cmd); 2938 break; 2939 case IKE_SVC_GET_P1: 2940 case IKE_SVC_GET_RULE: 2941 case IKE_SVC_GET_PS: 2942 case IKE_SVC_DEL_P1: 2943 case IKE_SVC_DEL_RULE: 2944 case IKE_SVC_DEL_PS: 2945 do_getdel(cmd, argc, argv); 2946 break; 2947 case IKE_SVC_NEW_RULE: 2948 case IKE_SVC_NEW_PS: 2949 do_new(cmd, argc, argv); 2950 break; 2951 case IKE_SVC_FLUSH_P1S: 2952 do_flush(cmd); 2953 break; 2954 case IKE_SVC_READ_RULES: 2955 case IKE_SVC_READ_PS: 2956 case IKE_SVC_WRITE_RULES: 2957 case IKE_SVC_WRITE_PS: 2958 do_rw(cmd, argc, argv); 2959 break; 2960 case IKEADM_HELP_GENERAL: 2961 print_help(); 2962 break; 2963 case IKEADM_HELP_GET: 2964 print_get_help(); 2965 break; 2966 case IKEADM_HELP_SET: 2967 print_set_help(); 2968 break; 2969 case IKEADM_HELP_ADD: 2970 print_add_help(); 2971 break; 2972 case IKEADM_HELP_DEL: 2973 print_del_help(); 2974 break; 2975 case IKEADM_HELP_DUMP: 2976 print_dump_help(); 2977 break; 2978 case IKEADM_HELP_FLUSH: 2979 print_flush_help(); 2980 break; 2981 case IKEADM_HELP_READ: 2982 print_read_help(); 2983 break; 2984 case IKEADM_HELP_WRITE: 2985 print_write_help(); 2986 break; 2987 case IKEADM_HELP_HELP: 2988 print_help_help(); 2989 break; 2990 case IKEADM_EXIT: 2991 if (interactive) 2992 exit(0); 2993 break; 2994 case IKE_SVC_DBG_RBDUMP: 2995 do_rbdump(); 2996 break; 2997 case IKE_SVC_ERROR: 2998 usage(); 2999 default: 3000 exit(0); 3001 } 3002 } 3003 3004 int 3005 main(int argc, char **argv) 3006 { 3007 char ch; 3008 3009 (void) setlocale(LC_ALL, ""); 3010 #if !defined(TEXT_DOMAIN) 3011 #define TEXT_DOMAIN "SYS_TEST" 3012 #endif 3013 (void) textdomain(TEXT_DOMAIN); 3014 3015 while ((ch = getopt(argc, argv, "hpn")) != EOF) { 3016 switch (ch) { 3017 case 'h': 3018 print_help(); 3019 return (0); 3020 case 'p': 3021 pflag = B_TRUE; 3022 break; 3023 case 'n': 3024 nflag = B_TRUE; 3025 break; 3026 default: 3027 usage(); 3028 } 3029 } 3030 argc -= optind; 3031 argv += optind; 3032 3033 if (open_door() < 0) { 3034 (void) fprintf(stderr, 3035 gettext("Unable to communicate with in.iked\n")); 3036 Bail("open_door failed"); 3037 } 3038 3039 if (*argv == NULL) { 3040 /* no cmd-line args, do interactive mode */ 3041 do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit); 3042 } 3043 3044 parseit(argc, argv, NULL, B_FALSE); 3045 3046 return (0); 3047 } 3048