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