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