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