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 (void) printf( 1381 gettext("%s Cookies: Initiator 0x%llx Responder 0x%llx\n"), 1382 prefix, ntohll(hdrp->p1hdr_cookies.cky_i), 1383 ntohll(hdrp->p1hdr_cookies.cky_r)); 1384 (void) printf(gettext("%s The local host is the %s.\n"), prefix, 1385 hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder")); 1386 (void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix, 1387 hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg)); 1388 (void) printf(gettext("%s Current state is %s"), prefix, 1389 statestr(hdrp->p1hdr_state)); 1390 (void) printf("\n"); 1391 } 1392 1393 static void 1394 print_lt_limits(char *prefix, ike_p1_xform_t *xfp) 1395 { 1396 (void) printf(gettext("%s Lifetime limits:\n"), prefix); 1397 (void) printf(gettext("%s %u seconds; %u kbytes protected; "), 1398 prefix, xfp->p1xf_max_secs, xfp->p1xf_max_kbytes); 1399 (void) printf(gettext("%u keymat provided.\n"), xfp->p1xf_max_keyuses); 1400 } 1401 1402 #define LT_USAGE_LEN 16 /* 1 uint64 + 2 uint32s */ 1403 static void 1404 print_lt_usage(char *prefix, ike_p1_stats_t *sp) 1405 { 1406 time_t scratch; 1407 char tbuf[TBUF_SIZE]; 1408 1409 (void) printf(gettext("%s Current usage:\n"), prefix); 1410 scratch = (time_t)sp->p1stat_start; 1411 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0) 1412 (void) strlcpy(tbuf, gettext("<time conversion failed>"), 1413 TBUF_SIZE); 1414 (void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf); 1415 (void) printf(gettext("%s %u kbytes protected; %u keymat provided.\n"), 1416 prefix, sp->p1stat_kbytes, sp->p1stat_keyuses); 1417 } 1418 1419 static void 1420 print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes) 1421 { 1422 (void) printf(gettext("%s Authentication method: %s"), prefix, 1423 authmethstr(xfp->p1xf_auth_meth)); 1424 (void) printf(gettext("\n%s Encryption alg: "), prefix); 1425 (void) dump_ealg(xfp->p1xf_encr_alg, stdout); 1426 if (xfp->p1xf_encr_low_bits != 0) { 1427 (void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits, 1428 xfp->p1xf_encr_high_bits); 1429 } else if ((xfp->p1xf_encr_low_bits == 0) && 1430 (xfp->p1xf_encr_high_bits != 0)) { 1431 /* 1432 * High bits is a placeholder for 1433 * negotiated algorithm strength 1434 */ 1435 (void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits); 1436 } 1437 (void) printf(gettext("; Authentication alg: ")); 1438 (void) dump_aalg(xfp->p1xf_auth_alg, stdout); 1439 (void) printf("\n%s ", prefix); 1440 if (xfp->p1xf_prf != 0) 1441 (void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf)); 1442 (void) printf(gettext("Oakley Group: %s\n"), 1443 dhstr(xfp->p1xf_dh_group)); 1444 if (xfp->p1xf_pfs == 0) { 1445 (void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix); 1446 } else { 1447 (void) printf(gettext( 1448 "%s Phase 2 PFS is required (Oakley Group: %s)\n"), 1449 prefix, dhstr(xfp->p1xf_pfs)); 1450 } 1451 1452 if (print_lifetimes) 1453 print_lt_limits(prefix, xfp); 1454 } 1455 1456 static void 1457 print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp, 1458 int statlen) 1459 { 1460 time_t current, remain, exp; 1461 char tbuf[TBUF_SIZE]; 1462 1463 current = time(NULL); 1464 1465 print_lt_limits(prefix, xfp); 1466 1467 /* 1468 * make sure the stats struct we've been passed is as big 1469 * as we expect it to be. The usage stats are at the end, 1470 * so anything less than the size we expect won't work. 1471 */ 1472 if (statlen >= sizeof (ike_p1_stats_t)) { 1473 print_lt_usage(prefix, sp); 1474 } else { 1475 return; 1476 } 1477 1478 (void) printf(gettext("%s Expiration info:\n"), prefix); 1479 1480 if (xfp->p1xf_max_kbytes != 0) 1481 (void) printf(gettext("%s %u more bytes can be protected.\n"), 1482 prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes); 1483 1484 if (xfp->p1xf_max_keyuses != 0) 1485 (void) printf(gettext("%s Keying material can be provided " 1486 "%u more times.\n"), prefix, 1487 xfp->p1xf_max_keyuses - sp->p1stat_keyuses); 1488 1489 if (xfp->p1xf_max_secs != 0) { 1490 exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs; 1491 remain = exp - current; 1492 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0) 1493 (void) strlcpy(tbuf, 1494 gettext("<time conversion failed>"), TBUF_SIZE); 1495 /* 1496 * The SA may have expired but still exist because libike 1497 * has not freed it yet. 1498 */ 1499 if (remain > 0) 1500 (void) printf(gettext( 1501 "%s SA expires in %lu seconds, at %s\n"), 1502 prefix, remain, tbuf); 1503 else 1504 (void) printf(gettext("%s SA Expired at %s\n"), 1505 prefix, tbuf); 1506 } 1507 } 1508 1509 /* used to verify structure lengths... */ 1510 #define COUNTER_32BIT 4 1511 #define COUNTER_PAIR 8 1512 1513 static void 1514 print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen, 1515 boolean_t print_lifetimes) 1516 { 1517 if (statlen < COUNTER_PAIR) 1518 return; 1519 (void) printf(gettext("%s %u Quick Mode SAs created; "), prefix, 1520 sp->p1stat_new_qm_sas); 1521 (void) printf(gettext("%u Quick Mode SAs deleted\n"), 1522 sp->p1stat_del_qm_sas); 1523 statlen -= COUNTER_PAIR; 1524 1525 if ((print_lifetimes) && (statlen >= LT_USAGE_LEN)) 1526 print_lt_usage(prefix, sp); 1527 } 1528 1529 static void 1530 print_errs(char *prefix, ike_p1_errors_t *errp, int errlen) 1531 { 1532 /* 1533 * Don't try to break this one up; it's either all or nothing! 1534 */ 1535 if (errlen < sizeof (ike_p1_errors_t)) 1536 return; 1537 1538 (void) printf(gettext("%s %u RX errors: "), prefix, 1539 errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx); 1540 (void) printf(gettext("%u decryption, %u hash, %u other\n"), 1541 errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx); 1542 (void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx); 1543 } 1544 1545 static void 1546 print_addr_range(char *prefix, ike_addr_pr_t *pr) 1547 { 1548 boolean_t range = B_TRUE; 1549 struct sockaddr_storage *beg, *end; 1550 struct sockaddr_in *bsin, *esin; 1551 struct sockaddr_in6 *bsin6, *esin6; 1552 1553 beg = &pr->beg_iprange; 1554 end = &pr->end_iprange; 1555 1556 if (beg->ss_family != end->ss_family) { 1557 (void) printf(gettext("%s invalid address range\n"), prefix); 1558 return; 1559 } 1560 1561 switch (beg->ss_family) { 1562 case AF_INET: 1563 bsin = (struct sockaddr_in *)beg; 1564 esin = (struct sockaddr_in *)end; 1565 if ((uint32_t)bsin->sin_addr.s_addr == 1566 (uint32_t)esin->sin_addr.s_addr) 1567 range = B_FALSE; 1568 break; 1569 case AF_INET6: 1570 bsin6 = (struct sockaddr_in6 *)beg; 1571 esin6 = (struct sockaddr_in6 *)end; 1572 if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr)) 1573 range = B_FALSE; 1574 break; 1575 default: 1576 (void) printf(gettext("%s invalid address range\n"), prefix); 1577 return; 1578 } 1579 1580 (void) printf("%s ", prefix); 1581 (void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag); 1582 if (range) { 1583 (void) printf(" - "); 1584 (void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout, 1585 nflag); 1586 } 1587 (void) printf("\n"); 1588 1589 } 1590 1591 /* 1592 * used to tell printing function if info should be identified 1593 * as belonging to initiator, responder, or neither 1594 */ 1595 #define IS_INITIATOR 1 1596 #define IS_RESPONDER 2 1597 #define DONT_PRINT_INIT 3 1598 1599 static void 1600 print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr) 1601 { 1602 (void) printf(gettext("%s Address"), prefix); 1603 1604 if (init_instr != DONT_PRINT_INIT) 1605 (void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ? 1606 gettext("Initiator") : gettext("Responder")); 1607 else 1608 (void) printf(":\n"); 1609 1610 (void) printf("%s ", prefix); 1611 (void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag); 1612 } 1613 1614 static void 1615 print_id(char *prefix, sadb_ident_t *idp, int init_instr) 1616 { 1617 boolean_t canprint; 1618 1619 switch (init_instr) { 1620 case IS_INITIATOR: 1621 (void) printf(gettext("%s Initiator identity, "), prefix); 1622 break; 1623 case IS_RESPONDER: 1624 (void) printf(gettext("%s Responder identity, "), prefix); 1625 break; 1626 case DONT_PRINT_INIT: 1627 (void) printf(gettext("%s Identity, "), prefix); 1628 break; 1629 default: 1630 (void) printf(gettext("<invalid identity>\n")); 1631 return; 1632 } 1633 (void) printf(gettext("uid=%d, type "), idp->sadb_ident_id); 1634 canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL); 1635 if (canprint) { 1636 (void) printf("\n%s %s\n", prefix, (char *)(idp + 1)); 1637 } else { 1638 (void) printf(gettext("\n%s "), prefix); 1639 print_asn1_name(stdout, 1640 (const unsigned char *)(idp + 1), 1641 SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t)); 1642 } 1643 } 1644 1645 static void 1646 print_idspec(char *prefix, char *idp, int icnt, int ecnt) 1647 { 1648 int i; 1649 1650 (void) printf(gettext("%s Identity descriptors:\n"), prefix); 1651 1652 for (i = 0; i < icnt; i++) { 1653 if (i == 0) 1654 (void) printf(gettext("%s Includes:\n"), prefix); 1655 (void) printf("%s %s\n", prefix, idp); 1656 idp += strlen(idp) + 1; 1657 } 1658 1659 for (i = 0; i < ecnt; i++) { 1660 if (i == 0) 1661 (void) printf(gettext("%s Excludes:\n"), prefix); 1662 (void) printf("%s %s\n", prefix, idp); 1663 idp += strlen(idp) + 1; 1664 } 1665 } 1666 1667 static void 1668 print_keys(char *prefix, ike_p1_key_t *keyp, int size) 1669 { 1670 uint32_t *curp; 1671 ike_p1_key_t *p; 1672 int ssize; 1673 1674 curp = (uint32_t *)keyp; 1675 1676 ssize = sizeof (ike_p1_key_t); 1677 1678 while ((intptr_t)curp - (intptr_t)keyp < size) { 1679 size_t p1klen, len; 1680 1681 p = (ike_p1_key_t *)curp; 1682 p1klen = p->p1key_len; 1683 len = p1klen - ssize; 1684 1685 p1klen = roundup(p1klen, sizeof (ike_p1_key_t)); 1686 if (p1klen < ssize) { 1687 (void) printf(gettext("Short key\n")); 1688 break; 1689 } 1690 1691 switch (p->p1key_type) { 1692 case IKE_KEY_PRESHARED: 1693 (void) printf(gettext("%s Pre-shared key (%d bytes): "), 1694 prefix, len); 1695 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1696 stdout); 1697 break; 1698 case IKE_KEY_SKEYID: 1699 (void) printf(gettext("%s SKEYID (%d bytes): "), 1700 prefix, len); 1701 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1702 stdout); 1703 break; 1704 case IKE_KEY_SKEYID_D: 1705 (void) printf(gettext("%s SKEYID_d (%d bytes): "), 1706 prefix, len); 1707 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1708 stdout); 1709 break; 1710 case IKE_KEY_SKEYID_A: 1711 (void) printf(gettext("%s SKEYID_a (%d bytes): "), 1712 prefix, len); 1713 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1714 stdout); 1715 break; 1716 case IKE_KEY_SKEYID_E: 1717 (void) printf(gettext("%s SKEYID_e (%d bytes): "), 1718 prefix, len); 1719 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1720 stdout); 1721 break; 1722 case IKE_KEY_ENCR: 1723 (void) printf(gettext("%s Encryption key (%d bytes): "), 1724 prefix, len); 1725 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1726 stdout); 1727 break; 1728 case IKE_KEY_IV: 1729 (void) printf( 1730 gettext("%s Initialization vector (%d bytes): "), 1731 prefix, len); 1732 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 1733 stdout); 1734 break; 1735 default: 1736 (void) printf(gettext("%s Unidentified key info %p %d"), 1737 prefix, p, p1klen); 1738 } 1739 (void) printf("\n"); 1740 assert(IS_P2ALIGNED(p1klen, 8)); 1741 curp += (p1klen >> 2); 1742 } 1743 } 1744 1745 static void 1746 print_p1(ike_p1_sa_t *p1) 1747 { 1748 ike_p1_stats_t *sp; 1749 ike_p1_errors_t *ep; 1750 ike_p1_key_t *kp; 1751 sadb_ident_t *lidp, *ridp; 1752 int lstat, rstat; 1753 1754 (void) printf("\n"); 1755 print_hdr("IKESA:", &p1->p1sa_hdr); 1756 print_xform("XFORM:", &p1->p1sa_xform, B_FALSE); 1757 1758 if (p1->p1sa_hdr.p1hdr_isinit) { 1759 lstat = IS_INITIATOR; 1760 rstat = IS_RESPONDER; 1761 } else { 1762 lstat = IS_RESPONDER; 1763 rstat = IS_INITIATOR; 1764 } 1765 print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat); 1766 print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat); 1767 1768 /* 1769 * the stat len might be 0; but still make the call 1770 * to print_lifetime() to pick up the xform info 1771 */ 1772 sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off); 1773 print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len); 1774 1775 if (p1->p1sa_stat_len > 0) { 1776 print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE); 1777 } 1778 1779 if (p1->p1sa_error_len > 0) { 1780 ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off); 1781 print_errs("ERRS: ", ep, p1->p1sa_error_len); 1782 } 1783 1784 if (p1->p1sa_localid_len > 0) { 1785 lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off); 1786 print_id("LOCID:", lidp, lstat); 1787 } 1788 1789 if (p1->p1sa_remoteid_len > 0) { 1790 ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off); 1791 print_id("REMID:", ridp, rstat); 1792 } 1793 1794 if (p1->p1sa_key_len > 0) { 1795 kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off); 1796 print_keys("KEY: ", kp, p1->p1sa_key_len); 1797 } 1798 } 1799 1800 static void 1801 print_ps(ike_ps_t *ps) 1802 { 1803 sadb_ident_t *lidp, *ridp; 1804 uint8_t *keyp; 1805 1806 (void) printf("\n"); 1807 1808 (void) printf(gettext("PSKEY: For %s exchanges\n"), 1809 xchgstr(ps->ps_ike_mode)); 1810 1811 if (ps->ps_key_len > 0) { 1812 keyp = (uint8_t *)((int)(ps) + ps->ps_key_off); 1813 (void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "), 1814 ps->ps_key_len); 1815 (void) dump_key(keyp, ps->ps_key_bits, stdout); 1816 (void) printf("\n"); 1817 } 1818 1819 /* 1820 * We get *either* and address or an ident, never both. So if 1821 * the ident is there, don't try printing an address. 1822 */ 1823 if (ps->ps_localid_len > 0) { 1824 lidp = (sadb_ident_t *) 1825 ((int)(ps) + ps->ps_localid_off); 1826 print_id("LOCID:", lidp, DONT_PRINT_INIT); 1827 } else { 1828 print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT); 1829 } 1830 1831 if (ps->ps_remoteid_len > 0) { 1832 ridp = (sadb_ident_t *) 1833 ((int)(ps) + ps->ps_remoteid_off); 1834 print_id("REMID:", ridp, DONT_PRINT_INIT); 1835 } else { 1836 print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT); 1837 } 1838 } 1839 1840 #define PREFIXLEN 16 1841 1842 static void 1843 print_rule(ike_rule_t *rp) 1844 { 1845 char prefix[PREFIXLEN]; 1846 int i; 1847 ike_p1_xform_t *xfp; 1848 ike_addr_pr_t *lipp, *ripp; 1849 char *lidp, *ridp; 1850 1851 (void) printf("\n"); 1852 (void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"), 1853 rp->rule_label, rp->rule_kmcookie); 1854 (void) printf(gettext("GLOBL: local_idtype=")); 1855 (void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL); 1856 (void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode)); 1857 (void) printf(gettext( 1858 "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"), 1859 rp->rule_p1_nonce_len, rp->rule_p2_nonce_len, 1860 (rp->rule_p2_pfs) ? gettext("true") : gettext("false"), 1861 rp->rule_p2_pfs); 1862 (void) printf( 1863 gettext("GLOBL: p2_lifetime=%u seconds, p2_softlife=%u seconds\n"), 1864 rp->rule_p2_lifetime_secs, rp->rule_p2_softlife_secs); 1865 (void) printf( 1866 gettext("GLOBL: p2_lifetime_kb=%u seconds," 1867 " p2_softlife_kb=%u seconds\n"), 1868 rp->rule_p2_lifetime_kb, rp->rule_p2_softlife_kb); 1869 1870 if (rp->rule_locip_cnt > 0) { 1871 (void) printf(gettext("LOCIP: IP address range(s):\n")); 1872 lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off); 1873 for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) { 1874 print_addr_range("LOCIP:", lipp); 1875 } 1876 } 1877 1878 if (rp->rule_remip_cnt > 0) { 1879 (void) printf(gettext("REMIP: IP address range(s):\n")); 1880 ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off); 1881 for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) { 1882 print_addr_range("REMIP:", ripp); 1883 } 1884 } 1885 1886 if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) { 1887 lidp = (char *)((int)rp + rp->rule_locid_off); 1888 print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt, 1889 rp->rule_locid_exclcnt); 1890 } 1891 1892 if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) { 1893 ridp = (char *)((int)rp + rp->rule_remid_off); 1894 print_idspec("REMID:", ridp, rp->rule_remid_inclcnt, 1895 rp->rule_remid_exclcnt); 1896 } 1897 1898 if (rp->rule_xform_cnt > 0) { 1899 (void) printf(gettext("XFRMS: Available Transforms:\n")); 1900 xfp = (ike_p1_xform_t *)((int)rp + rp->rule_xform_off); 1901 for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) { 1902 (void) snprintf(prefix, PREFIXLEN, "XF %2u:", i); 1903 print_xform(prefix, xfp, B_TRUE); 1904 } 1905 } 1906 } 1907 1908 #undef PREFIXLEN 1909 1910 #define PRSACNTS(init, resp) \ 1911 (void) printf(gettext("initiator: %10u responder: %10u\n"), \ 1912 (init), (resp)) 1913 1914 static void 1915 print_stats(ike_stats_t *sp, int len) 1916 { 1917 /* 1918 * before printing each line, make sure the structure we were 1919 * given is big enough to include the fields needed. 1920 */ 1921 if (len < COUNTER_PAIR) 1922 return; 1923 (void) printf(gettext("Phase 1 SA counts:\n")); 1924 (void) printf(gettext("Current: ")); 1925 PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current); 1926 len -= COUNTER_PAIR; 1927 1928 if (len < COUNTER_PAIR) 1929 return; 1930 (void) printf(gettext("Total: ")); 1931 PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total); 1932 len -= COUNTER_PAIR; 1933 1934 if (len < COUNTER_PAIR) 1935 return; 1936 (void) printf(gettext("Attempted: ")); 1937 PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts); 1938 len -= COUNTER_PAIR; 1939 1940 if (len < (COUNTER_PAIR + COUNTER_32BIT)) 1941 return; 1942 (void) printf(gettext("Failed: ")); 1943 PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail, 1944 sp->st_resp_p1_fail); 1945 (void) printf( 1946 gettext(" initiator fails include %u time-out(s)\n"), 1947 sp->st_init_p1_noresp); 1948 1949 if (len < PATH_MAX) 1950 return; 1951 if (*(sp->st_pkcs11_libname) != '\0') 1952 (void) printf(gettext("PKCS#11 library linked in from %s\n"), 1953 sp->st_pkcs11_libname); 1954 } 1955 1956 static void 1957 print_defaults(char *label, char *description, char *unit, boolean_t kbytes, 1958 uint_t current, uint_t def) 1959 { 1960 (void) printf("%-18s%-10s%14u%s%-10s%-26s\n", label, 1961 (current != def) ? gettext("config") : gettext("default"), 1962 (current != def) ? current : def, (kbytes) ? "K " : " ", 1963 unit, description); 1964 } 1965 1966 /* 1967 * Print out defaults used by in.iked, the argument is a buffer containing 1968 * two ike_defaults_t's, the first contains the hard coded defaults, the second 1969 * contains the actual values used. If these differ, then the defaults have been 1970 * changed via a config file entry. Note that "-" indicates this default 1971 * is not tunable. 1972 */ 1973 static void 1974 do_print_defaults(ike_defaults_t *dp) 1975 { 1976 ike_defaults_t *ddp; 1977 ddp = (ike_defaults_t *)(dp + 1); 1978 1979 (void) printf(gettext("\nGlobal defaults. Some values can be" 1980 " over-ridden on a per rule basis.\n\n")); 1981 1982 (void) printf("%-18s%-10s%-16s%-10s%-26s\n\n", 1983 gettext("Token:"), gettext("Source:"), gettext("Value:"), 1984 gettext("Unit:"), gettext("Description:")); 1985 1986 print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"), 1987 gettext("seconds"), B_FALSE, ddp->rule_p1_lifetime_secs, 1988 dp->rule_p1_lifetime_secs); 1989 1990 print_defaults("-", gettext("minimum phase 1 lifetime"), 1991 gettext("seconds"), B_FALSE, ddp->rule_p1_minlife, 1992 dp->rule_p1_minlife); 1993 1994 print_defaults("p1_nonce_len", gettext("phase 1 nonce length"), 1995 gettext("bytes"), B_FALSE, ddp->rule_p1_nonce_len, 1996 dp->rule_p1_nonce_len); 1997 1998 print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"), 1999 gettext("seconds"), B_FALSE, ddp->rule_p2_lifetime_secs, 2000 dp->rule_p2_lifetime_secs); 2001 2002 print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"), 2003 gettext("seconds"), B_FALSE, ddp->rule_p2_softlife_secs, 2004 dp->rule_p2_softlife_secs); 2005 2006 print_defaults("-", gettext("system phase 2 lifetime"), 2007 gettext("seconds"), B_FALSE, ddp->sys_p2_lifetime_secs, 2008 dp->sys_p2_lifetime_secs); 2009 2010 print_defaults("-", gettext("system phase 2 soft lifetime"), 2011 gettext("seconds"), B_FALSE, ddp->sys_p2_softlife_secs, 2012 dp->sys_p2_softlife_secs); 2013 2014 print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"), 2015 gettext("bytes"), B_TRUE, ddp->rule_p2_lifetime_kb, 2016 dp->rule_p2_lifetime_kb); 2017 2018 print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"), 2019 gettext("bytes"), B_TRUE, ddp->rule_p2_softlife_kb, 2020 dp->rule_p2_softlife_kb); 2021 2022 print_defaults("-", gettext("system phase 2 lifetime"), 2023 gettext("bytes"), B_FALSE, ddp->sys_p2_lifetime_bytes, 2024 dp->sys_p2_lifetime_bytes); 2025 2026 print_defaults("-", gettext("system phase 2 soft lifetime"), 2027 gettext("bytes"), B_FALSE, ddp->sys_p2_softlife_bytes, 2028 dp->sys_p2_softlife_bytes); 2029 2030 print_defaults("-", gettext("minimum phase 2 lifetime"), 2031 gettext("seconds"), B_FALSE, ddp->rule_p2_minlife, 2032 dp->rule_p2_minlife); 2033 2034 print_defaults("p2_nonce_len", gettext("phase 2 nonce length"), 2035 gettext("bytes"), B_FALSE, ddp->rule_p2_nonce_len, 2036 dp->rule_p2_nonce_len); 2037 2038 print_defaults("-", gettext("default phase 2 lifetime"), 2039 gettext("seconds"), B_FALSE, ddp->rule_p2_def_minlife, 2040 dp->rule_p2_def_minlife); 2041 2042 print_defaults("-", gettext("minimum phase 2 soft delta"), 2043 gettext("seconds"), B_FALSE, ddp->rule_p2_minsoft, 2044 dp->rule_p2_minsoft); 2045 2046 print_defaults("p2_pfs", gettext("phase 2 PFS"), 2047 " ", B_FALSE, ddp->rule_p2_pfs, dp->rule_p2_pfs); 2048 2049 print_defaults("max_certs", gettext("max certificates"), 2050 " ", B_FALSE, ddp->rule_max_certs, dp->rule_max_certs); 2051 2052 print_defaults("-", gettext("IKE port number"), 2053 " ", B_FALSE, ddp->rule_ike_port, dp->rule_ike_port); 2054 2055 print_defaults("-", gettext("NAT-T port number"), 2056 " ", B_FALSE, ddp->rule_natt_port, dp->rule_natt_port); 2057 } 2058 2059 static void 2060 print_categories(int level) 2061 { 2062 int mask; 2063 2064 if (level == 0) { 2065 (void) printf(gettext("No debug categories enabled.\n")); 2066 return; 2067 } 2068 2069 (void) printf(gettext("Debug categories enabled:")); 2070 for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) { 2071 if (level & mask) 2072 (void) printf("\n\t%s", dbgstr(mask)); 2073 } 2074 (void) printf("\n"); 2075 } 2076 2077 /*PRINTFLIKE2*/ 2078 static void 2079 ikeadm_err_exit(ike_err_t *err, char *fmt, ...) 2080 { 2081 va_list ap; 2082 char bailbuf[BUFSIZ]; 2083 2084 va_start(ap, fmt); 2085 (void) vsnprintf(bailbuf, BUFSIZ, fmt, ap); 2086 va_end(ap); 2087 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) { 2088 bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ? 2089 gettext("<unknown error>") : strerror(err->ike_err_unix)); 2090 } else { 2091 bail_msg("%s: %s", bailbuf, (err == NULL) ? 2092 gettext("<unknown error>") : errstr(err->ike_err)); 2093 } 2094 } 2095 2096 /*PRINTFLIKE2*/ 2097 static void 2098 ikeadm_err_msg(ike_err_t *err, char *fmt, ...) 2099 { 2100 va_list ap; 2101 char mbuf[BUFSIZ]; 2102 2103 va_start(ap, fmt); 2104 (void) vsnprintf(mbuf, BUFSIZ, fmt, ap); 2105 va_end(ap); 2106 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) { 2107 message("%s: %s", mbuf, (err->ike_err_unix == 0) ? 2108 gettext("<unknown error>") : 2109 ((err->ike_err_unix == EEXIST) ? 2110 gettext("Duplicate entry") : 2111 strerror(err->ike_err_unix))); 2112 } else { 2113 message("%s: %s", mbuf, (err == NULL) ? 2114 gettext("<unknown error>") : errstr(err->ike_err)); 2115 } 2116 } 2117 2118 2119 /* 2120 * Command functions 2121 */ 2122 2123 /* 2124 * Exploit the fact that ike_dbg_t and ike_priv_t have identical 2125 * formats in the following two functions. 2126 */ 2127 static void 2128 do_getvar(int cmd) 2129 { 2130 ike_service_t req, *rtn; 2131 ike_dbg_t *dreq; 2132 char *varname; 2133 2134 switch (cmd) { 2135 case IKE_SVC_GET_DBG: 2136 varname = gettext("debug"); 2137 break; 2138 case IKE_SVC_GET_PRIV: 2139 varname = gettext("privilege"); 2140 break; 2141 default: 2142 bail_msg(gettext("unrecognized get command (%d)"), cmd); 2143 } 2144 2145 dreq = &req.svc_dbg; 2146 dreq->cmd = cmd; 2147 dreq->dbg_level = 0; 2148 2149 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0); 2150 2151 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2152 ikeadm_err_exit(&rtn->svc_err, 2153 gettext("error getting %s level"), varname); 2154 } 2155 dreq = &rtn->svc_dbg; 2156 (void) printf(gettext("Current %s level is 0x%x"), 2157 varname, dreq->dbg_level); 2158 2159 if (cmd == IKE_SVC_GET_DBG) { 2160 (void) printf("\n"); 2161 print_categories(dreq->dbg_level); 2162 } else { 2163 (void) printf(gettext(", %s enabled\n"), 2164 privstr(dreq->dbg_level)); 2165 } 2166 } 2167 2168 static void 2169 do_setvar(int cmd, int argc, char **argv) 2170 { 2171 ike_service_t req, *rtn; 2172 ike_dbg_t *dreq; 2173 door_desc_t *descp = NULL, desc; 2174 int fd, ndesc = 0; 2175 uint32_t reqlevel; 2176 char *varname; 2177 2178 if (argc < 1) 2179 Bail("unspecified level"); 2180 reqlevel = strtoul(argv[0], NULL, 0); 2181 2182 switch (cmd) { 2183 case IKE_SVC_SET_DBG: 2184 if (argc > 2) 2185 Bail("Too many arguments to \"set debug\""); 2186 varname = gettext("debug"); 2187 if (reqlevel == 0) { 2188 /* check for a string... */ 2189 reqlevel = parsedbgopts(argv[0]); 2190 } 2191 if (reqlevel == D_INVALID) 2192 bail_msg(gettext("Bad debug flag: %s"), argv[0]); 2193 break; 2194 case IKE_SVC_SET_PRIV: 2195 if (argc > 1) 2196 Bail("Too many arguments to \"set priv\""); 2197 2198 varname = gettext("privilege"); 2199 if (reqlevel == 0) { 2200 /* check for a string... */ 2201 reqlevel = privstr2num(argv[0]); 2202 } 2203 if (reqlevel > IKE_PRIV_MAXIMUM) 2204 bail_msg(gettext("Bad privilege flag: %s"), argv[0]); 2205 break; 2206 default: 2207 bail_msg(gettext("unrecognized set command (%d)"), cmd); 2208 } 2209 2210 dreq = &req.svc_dbg; 2211 dreq->cmd = cmd; 2212 dreq->dbg_level = reqlevel; 2213 2214 if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) { 2215 fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND, 2216 S_IRUSR | S_IWUSR); 2217 if (fd < 0) 2218 Bail("open debug file"); 2219 desc.d_data.d_desc.d_descriptor = fd; 2220 desc.d_attributes = DOOR_DESCRIPTOR; 2221 descp = &desc; 2222 ndesc = 1; 2223 } 2224 2225 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc); 2226 2227 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2228 ikeadm_err_exit(&rtn->svc_err, 2229 gettext("error setting %s level"), varname); 2230 } 2231 dreq = &rtn->svc_dbg; 2232 (void) printf( 2233 gettext("Successfully changed %s level from 0x%x to 0x%x\n"), 2234 varname, dreq->dbg_level, reqlevel); 2235 2236 if (cmd == IKE_SVC_SET_DBG) { 2237 print_categories(reqlevel); 2238 } else { 2239 (void) printf(gettext("New privilege level 0x%x enables %s\n"), 2240 reqlevel, privstr(reqlevel)); 2241 } 2242 } 2243 2244 static void 2245 do_getstats(int cmd) 2246 { 2247 ike_service_t *rtn; 2248 ike_statreq_t sreq, *sreqp; 2249 ike_stats_t *sp; 2250 2251 sreq.cmd = cmd; 2252 2253 rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0); 2254 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2255 ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats")); 2256 } 2257 2258 sreqp = &rtn->svc_stats; 2259 sp = (ike_stats_t *)(sreqp + 1); 2260 print_stats(sp, sreqp->stat_len); 2261 } 2262 2263 static void 2264 do_getdefs(int cmd) 2265 { 2266 ike_service_t *rtn; 2267 ike_defreq_t dreq, *dreqp; 2268 ike_defaults_t *dp; 2269 2270 dreq.cmd = cmd; 2271 2272 rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0); 2273 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2274 ikeadm_err_exit(&rtn->svc_err, 2275 gettext("error getting defaults")); 2276 } 2277 2278 dreqp = &rtn->svc_defaults; 2279 dp = (ike_defaults_t *)(dreqp + 1); 2280 2281 /* 2282 * Before printing each line, make sure the structure we were 2283 * given is big enough to include the fields needed. 2284 * Silently bail out of there is a version mismatch. 2285 */ 2286 if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t)) 2287 + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) { 2288 return; 2289 } 2290 do_print_defaults(dp); 2291 } 2292 2293 static void 2294 do_dump(int cmd) 2295 { 2296 char *name; 2297 ike_service_t req, *rtn; 2298 ike_dump_t *dreq, *dump; 2299 2300 switch (cmd) { 2301 case IKE_SVC_DUMP_P1S: 2302 name = gettext("phase 1 SA info"); 2303 break; 2304 case IKE_SVC_DUMP_RULES: 2305 name = gettext("policy rules"); 2306 break; 2307 case IKE_SVC_DUMP_PS: 2308 name = gettext("preshared keys"); 2309 break; 2310 default: 2311 bail_msg(gettext("unrecognized dump command (%d)"), cmd); 2312 } 2313 2314 dreq = &req.svc_dump; 2315 dreq->cmd = cmd; 2316 dreq->dump_len = 0; 2317 dreq->dump_next = 0; 2318 do { 2319 rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t), 2320 NULL, 0); 2321 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2322 if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) { 2323 /* no entries to print */ 2324 break; 2325 } 2326 ikeadm_err_exit(&rtn->svc_err, 2327 gettext("error getting %s"), name); 2328 } 2329 dump = &rtn->svc_dump; 2330 2331 switch (cmd) { 2332 case IKE_SVC_DUMP_P1S: 2333 print_p1((ike_p1_sa_t *)(dump + 1)); 2334 break; 2335 case IKE_SVC_DUMP_RULES: 2336 print_rule((ike_rule_t *)(dump + 1)); 2337 break; 2338 case IKE_SVC_DUMP_PS: 2339 print_ps((ike_ps_t *)(dump + 1)); 2340 break; 2341 } 2342 2343 dreq->dump_next = dump->dump_next; 2344 2345 (void) munmap((char *)rtn, dump->dump_len); 2346 2347 } while (dreq->dump_next); 2348 2349 (void) printf(gettext("\nCompleted dump of %s\n"), name); 2350 } 2351 2352 static void 2353 do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name) 2354 { 2355 int totallen; 2356 char *p; 2357 ike_service_t *reqp, *rtnp; 2358 ike_get_t *getp; 2359 boolean_t getcmd; 2360 2361 getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) || 2362 (cmd == IKE_SVC_GET_PS)); 2363 2364 /* 2365 * WARNING: to avoid being redundant, this code takes advantage 2366 * of the fact that the ike_get_t and ike_del_t structures are 2367 * identical (only the field names differ, their function and 2368 * size are the same). If for some reason those structures 2369 * change, this code will need to be re-written to accomodate 2370 * that difference. 2371 */ 2372 totallen = sizeof (ike_get_t) + idlen; 2373 if ((reqp = (ike_service_t *)malloc(totallen)) == NULL) 2374 Bail("malloc(id)"); 2375 2376 getp = &reqp->svc_get; 2377 getp->cmd = cmd; 2378 getp->get_len = totallen; 2379 getp->get_idtype = idtype; 2380 p = (char *)(getp + 1); 2381 2382 (void) memcpy(p, idp, idlen); 2383 2384 rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0); 2385 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2386 if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) { 2387 message(gettext("Could not find requested %s."), name); 2388 } else { 2389 ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"), 2390 (getcmd) ? gettext("getting") : gettext("deleting"), 2391 name); 2392 } 2393 free(reqp); 2394 return; 2395 } 2396 getp = &rtnp->svc_get; 2397 2398 if (getcmd) { 2399 switch (cmd) { 2400 case IKE_SVC_GET_P1: 2401 print_p1((ike_p1_sa_t *)(getp + 1)); 2402 break; 2403 case IKE_SVC_GET_PS: 2404 print_ps((ike_ps_t *)(getp + 1)); 2405 break; 2406 case IKE_SVC_GET_RULE: 2407 print_rule((ike_rule_t *)(getp + 1)); 2408 break; 2409 } 2410 } else { 2411 message(gettext("Successfully deleted selected %s."), name); 2412 } 2413 2414 (void) munmap((char *)rtnp, getp->get_len); 2415 free(reqp); 2416 } 2417 2418 static void 2419 do_getdel(int cmd, int argc, char **argv) 2420 { 2421 int idlen, idtype = 0, i, j; 2422 int bytelen1, bytelen2; 2423 char *name, *idp, *p, *p1, *p2; 2424 ike_addr_pr_t apr; 2425 ike_cky_pr_t cpr; 2426 sadb_ident_t *sid1p, *sid2p; 2427 struct hostent *he1p, *he2p; 2428 char label[MAX_LABEL_LEN]; 2429 2430 if ((argc < 1) || (argv[0] == NULL)) { 2431 Bail("not enough identification info"); 2432 } 2433 2434 switch (cmd) { 2435 case IKE_SVC_GET_P1: 2436 case IKE_SVC_DEL_P1: 2437 name = gettext("phase 1 SA"); 2438 /* 2439 * The first token must either be an address (or hostname) 2440 * or a cookie. We require cookies to be entered as hex 2441 * numbers, beginning with 0x; so if our token starts with 2442 * that, it's a cookie. 2443 */ 2444 if (strncmp(argv[0], "0x", 2) == 0) { 2445 if (parse_cky_pr(argc, argv, &cpr) >= 0) { 2446 idtype = IKE_ID_CKY_PAIR; 2447 idlen = sizeof (ike_cky_pr_t); 2448 idp = (char *)&cpr; 2449 } 2450 } else { 2451 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) { 2452 idtype = IKE_ID_ADDR_PAIR; 2453 idlen = sizeof (ike_addr_pr_t); 2454 } 2455 } 2456 break; 2457 2458 case IKE_SVC_GET_RULE: 2459 case IKE_SVC_DEL_RULE: 2460 name = gettext("policy rule"); 2461 if (parse_label(argc, argv, label) >= 0) { 2462 idtype = IKE_ID_LABEL; 2463 idlen = MAX_LABEL_LEN; 2464 idp = label; 2465 } 2466 break; 2467 2468 case IKE_SVC_GET_PS: 2469 case IKE_SVC_DEL_PS: 2470 name = gettext("preshared key"); 2471 /* 2472 * The first token must either be an address or an ident 2473 * type. Check for an ident type to determine which it is. 2474 */ 2475 if (parse_idtype(argv[0], NULL) >= 0) { 2476 if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) { 2477 idtype = IKE_ID_IDENT_PAIR; 2478 idlen = SADB_64TO8(sid1p->sadb_ident_len) + 2479 SADB_64TO8(sid2p->sadb_ident_len); 2480 } 2481 } else { 2482 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) { 2483 idtype = IKE_ID_ADDR_PAIR; 2484 idlen = sizeof (ike_addr_pr_t); 2485 } 2486 } 2487 break; 2488 2489 default: 2490 bail_msg(gettext("unrecognized get/del command (%d)"), cmd); 2491 } 2492 2493 switch (idtype) { 2494 case IKE_ID_ADDR_PAIR: 2495 /* 2496 * we might have exploding addrs here; do every possible 2497 * combination. 2498 */ 2499 i = 0; 2500 j = 0; 2501 while ((p1 = he1p->h_addr_list[i++]) != NULL) { 2502 headdr2sa(p1, &apr.loc_addr, he1p->h_length); 2503 2504 while ((p2 = he2p->h_addr_list[j++]) != NULL) { 2505 headdr2sa(p2, &apr.rem_addr, he2p->h_length); 2506 do_getdel_doorcall(cmd, idlen, idtype, 2507 (char *)&apr, name); 2508 } 2509 } 2510 FREE_HE(he1p); 2511 FREE_HE(he2p); 2512 break; 2513 2514 case IKE_ID_IDENT_PAIR: 2515 bytelen1 = SADB_64TO8(sid1p->sadb_ident_len); 2516 bytelen2 = SADB_64TO8(sid2p->sadb_ident_len); 2517 if (idlen != bytelen1 + bytelen2) 2518 Bail("ident syntax error"); 2519 idp = p = (char *)malloc(idlen); 2520 if (p == NULL) 2521 Bail("malloc(id)"); 2522 (void) memcpy(p, (char *)sid1p, bytelen1); 2523 p += bytelen1; 2524 (void) memcpy(p, (char *)sid2p, bytelen2); 2525 do_getdel_doorcall(cmd, idlen, idtype, idp, name); 2526 free(idp); 2527 free(sid1p); 2528 free(sid2p); 2529 break; 2530 2531 case IKE_ID_CKY_PAIR: 2532 case IKE_ID_LABEL: 2533 do_getdel_doorcall(cmd, idlen, idtype, idp, name); 2534 break; 2535 2536 case 0: 2537 default: 2538 bail_msg(gettext("invalid %s identification\n"), name); 2539 } 2540 } 2541 2542 /* 2543 * Copy source into target, inserting an escape character ('\') before 2544 * any quotes that appear. Return true on success, false on failure. 2545 */ 2546 static boolean_t 2547 escapequotes(char *target, char *source, int tlen) 2548 { 2549 int s, t, len = strlen(source) + 1; 2550 2551 if (tlen < len) 2552 return (B_FALSE); 2553 2554 for (s = 0, t = 0; s < len && t < tlen; s++) { 2555 if (source[s] == '\"') 2556 target[t++] = '\\'; 2557 target[t++] = source[s]; 2558 } 2559 2560 if ((t == tlen) && (s < len)) 2561 return (B_FALSE); 2562 2563 return (B_TRUE); 2564 } 2565 2566 /* 2567 * Return true if the arg following the given keyword should 2568 * be in quotes (i.e. is a string), false if not. 2569 */ 2570 static boolean_t 2571 quotedfield(char *keywd) 2572 { 2573 if ((strncmp(keywd, "label", strlen("label") + 1) == 0) || 2574 (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) || 2575 (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0)) 2576 return (B_TRUE); 2577 2578 return (B_FALSE); 2579 } 2580 2581 static void 2582 do_new(int cmd, int argc, char **argv) 2583 { 2584 ike_service_t *rtn; 2585 ike_new_t new, *newp = NULL; 2586 door_desc_t desc, *descp = NULL; 2587 int i, fd, ndesc = 0, buflen; 2588 char *name, tmpfilepath[32]; 2589 FILE *tmpfile; 2590 2591 switch (cmd) { 2592 case IKE_SVC_NEW_PS: 2593 name = gettext("preshared key"); 2594 break; 2595 case IKE_SVC_NEW_RULE: 2596 name = gettext("policy rule"); 2597 break; 2598 default: 2599 bail_msg(gettext("unrecognized new command (%d)"), cmd); 2600 } 2601 2602 if (argc == 1) { 2603 /* We've been given a file to read from */ 2604 fd = open(argv[0], O_RDONLY); 2605 if (fd < 0) 2606 Bail("open source file"); 2607 2608 desc.d_data.d_desc.d_descriptor = fd; 2609 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2610 descp = &desc; 2611 ndesc = 1; 2612 2613 new.cmd = cmd; 2614 new.new_len = 0; 2615 newp = &new; 2616 buflen = sizeof (ike_new_t); 2617 2618 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) { 2619 /* 2620 * This is an alternative to using the tmpfile method 2621 * for preshared keys. It means we're duplicating the 2622 * parsing effort that happens in readps.c; but it 2623 * does avoid having the key sitting in a file. 2624 */ 2625 ike_ps_t *psp; 2626 int pslen; 2627 2628 /* 2629 * must be in interactive mode; don't want keys in 2630 * the process args. 2631 */ 2632 if (!interactive) 2633 Bail("Must be in interactive mode to add key info."); 2634 if (parse_ps(argc, argv, &psp, &pslen) < 0) { 2635 errno = 0; 2636 Bail("invalid preshared key definition"); 2637 } 2638 newp = malloc(sizeof (ike_new_t) + pslen); 2639 if (newp == NULL) 2640 Bail("alloc pskey"); 2641 newp->cmd = cmd; 2642 newp->new_len = sizeof (ike_new_t) + pslen; 2643 (void) memcpy((char *)(newp + 1), psp, pslen); 2644 buflen = newp->new_len; 2645 /* parse_ps allocated the ike_ps_t buffer; free it now */ 2646 free(psp); 2647 2648 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) { 2649 /* 2650 * We've been given the item in argv. However, parsing 2651 * rules can get more than a little messy, and in.iked 2652 * already has a great parser for this stuff! So don't 2653 * fool around with trying to do the parsing here. Just 2654 * write it out to a tempfile, and send the fd to in.iked. 2655 * 2656 * We could conceivably do this for preshared keys, 2657 * rather than duplicating the parsing effort; but that 2658 * would mean the key would be written out to a file, 2659 * which isn't such a good idea. 2660 */ 2661 boolean_t doquotes = B_FALSE; 2662 int rtn; 2663 2664 if ((argv[0][0] != '{') || 2665 (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}')) 2666 bail_msg(gettext("improperly formatted %s"), name); 2667 2668 /* attempt to use a fairly unpredictable file name... */ 2669 (void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime()); 2670 fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL, 2671 S_IRUSR | S_IWUSR); 2672 if (fd < 0) 2673 Bail("cannot open tmpfile"); 2674 2675 /* and make it inaccessible asap */ 2676 if (unlink(tmpfilepath) < 0) { 2677 (void) close(fd); 2678 Bail("tmpfile error"); 2679 } 2680 2681 tmpfile = fdopen(fd, "w"); 2682 if (tmpfile == NULL) { 2683 (void) close(fd); 2684 Bail("cannot write to tmpfile"); 2685 } 2686 2687 for (i = 0; i < argc; i++) { 2688 /* 2689 * We have to do some gyrations with our string here, 2690 * to properly handle quotes. There are two issues: 2691 * - some of the fields of a rule may have embedded 2692 * whitespace, and thus must be quoted on the cmd 2693 * line. The shell removes the quotes, and gives 2694 * us a single argv string; but we need to put the 2695 * quotes back in when we write the string out to 2696 * file. The doquotes boolean is set when we 2697 * process a keyword which will be followed by a 2698 * string value (so the NEXT argv element will be 2699 * quoted). 2700 * - there might be a quote character in a field, 2701 * that was escaped on the cmdline. The shell 2702 * removes the escape char, and leaves the quote 2703 * in the string it gives us. We need to put the 2704 * escape char back in before writing to file. 2705 */ 2706 char field[MAXLINESIZE]; 2707 if (!escapequotes(field, argv[i], MAXLINESIZE)) 2708 Bail("write to tmpfile failed (arg too big)"); 2709 if (doquotes) { 2710 rtn = fprintf(tmpfile, "\"%s\"\n", field); 2711 doquotes = B_FALSE; 2712 } else { 2713 rtn = fprintf(tmpfile, "%s\n", field); 2714 } 2715 if (rtn < 0) 2716 Bail("write to tmpfile failed"); 2717 /* 2718 * check if this is a keyword identifying 2719 * a field that needs to be quoted. 2720 */ 2721 doquotes = quotedfield(argv[i]); 2722 } 2723 if (fflush(tmpfile) == EOF) 2724 Bail("write to tmpfile failed"); 2725 /* rewind so that the daemon will get the beginning */ 2726 rewind(tmpfile); 2727 2728 desc.d_data.d_desc.d_descriptor = fd; 2729 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2730 descp = &desc; 2731 ndesc = 1; 2732 2733 new.cmd = cmd; 2734 new.new_len = 0; 2735 newp = &new; 2736 buflen = sizeof (ike_new_t); 2737 2738 } else { 2739 /* not enough information! */ 2740 bail_msg(gettext("missing %s description or file name"), name); 2741 } 2742 2743 rtn = ikedoor_call((char *)newp, buflen, descp, ndesc); 2744 2745 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) { 2746 ikeadm_err_msg(&rtn->svc_err, 2747 gettext("error creating new %s"), name); 2748 } else { 2749 message(gettext("Successfully created new %s."), name); 2750 } 2751 } 2752 2753 static void 2754 do_flush(int cmd) 2755 { 2756 ike_service_t *rtnp; 2757 ike_flush_t flush; 2758 2759 if (cmd != IKE_SVC_FLUSH_P1S) { 2760 bail_msg(gettext("unrecognized flush command (%d)."), cmd); 2761 } 2762 2763 flush.cmd = cmd; 2764 2765 rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0); 2766 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2767 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush")); 2768 } 2769 message(gettext("Successfully flushed P1 SAs.")); 2770 } 2771 2772 static void 2773 do_rw(int cmd, int argc, char **argv) 2774 { 2775 ike_service_t *rtnp; 2776 ike_rw_t rw; 2777 door_desc_t desc, *descp = NULL; 2778 int oflag, omode, fd, ndesc = 0; 2779 char *op, *obj = NULL; 2780 boolean_t writing = B_FALSE; 2781 2782 switch (cmd) { 2783 case IKE_SVC_READ_PS: 2784 obj = gettext("preshared key"); 2785 /* FALLTHRU */ 2786 case IKE_SVC_READ_RULES: 2787 if (obj == NULL) 2788 obj = gettext("policy rule"); 2789 op = gettext("read"); 2790 oflag = O_RDONLY; 2791 omode = 0; 2792 break; 2793 2794 case IKE_SVC_WRITE_PS: 2795 obj = gettext("preshared key"); 2796 /* FALLTHRU */ 2797 case IKE_SVC_WRITE_RULES: 2798 if (obj == NULL) 2799 obj = gettext("policy rule"); 2800 op = gettext("write"); 2801 oflag = O_RDWR | O_CREAT | O_EXCL; 2802 omode = S_IRUSR | S_IWUSR; 2803 2804 /* for write commands, dest location must be specified */ 2805 if (argc < 1) { 2806 bail_msg(gettext("destination location required " 2807 "to write %ss"), obj); 2808 } 2809 writing = B_TRUE; 2810 break; 2811 2812 default: 2813 bail_msg(gettext("unrecognized read/write command (%d)."), cmd); 2814 } 2815 2816 rw.cmd = cmd; 2817 2818 if (argc >= 1) { 2819 rw.rw_loc = IKE_RW_LOC_USER_SPEC; 2820 fd = open(argv[0], oflag, omode); 2821 if (fd < 0) 2822 Bail("open user-specified file"); 2823 2824 desc.d_data.d_desc.d_descriptor = fd; 2825 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE; 2826 descp = &desc; 2827 ndesc = 1; 2828 } else { 2829 rw.rw_loc = IKE_RW_LOC_DEFAULT; 2830 } 2831 2832 rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc); 2833 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2834 /* 2835 * Need to remove the target file in the 2836 * case of a failed write command. 2837 */ 2838 if (writing) { 2839 /* 2840 * argv[0] must be valid if we're writing; we 2841 * exit before setting this boolean if not. 2842 */ 2843 (void) unlink(argv[0]); 2844 (void) close(fd); 2845 2846 if ((rtnp != NULL) && 2847 (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) { 2848 message(gettext("No %s information to write."), 2849 obj); 2850 return; 2851 } 2852 } 2853 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op); 2854 } 2855 message(gettext("Completed %s of %s configuration information."), 2856 op, obj); 2857 } 2858 2859 static void 2860 do_rbdump() 2861 { 2862 ike_cmd_t req; 2863 ike_service_t *rtnp; 2864 2865 req.cmd = IKE_SVC_DBG_RBDUMP; 2866 2867 rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0); 2868 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) { 2869 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush")); 2870 } 2871 message(gettext("Successfully dumped rulebase; check iked dbg")); 2872 } 2873 2874 #define REQ_ARG_CNT 1 2875 2876 /*ARGSUSED*/ 2877 static void 2878 parseit(int argc, char **argv, char *notused, boolean_t notused_either) 2879 { 2880 int cmd, cmd_obj_args = 1; 2881 char *cmdstr, *objstr; 2882 2883 if (interactive) { 2884 if (argc == 0) 2885 return; 2886 } 2887 2888 if (argc < REQ_ARG_CNT) { 2889 usage(); 2890 } 2891 2892 cmdstr = argv[0]; 2893 if (argc > REQ_ARG_CNT) { 2894 cmd_obj_args++; 2895 objstr = argv[1]; 2896 } else { 2897 objstr = NULL; 2898 } 2899 cmd = parsecmd(cmdstr, objstr); 2900 2901 /* skip over args specifying command/object */ 2902 argc -= cmd_obj_args; 2903 argv += cmd_obj_args; 2904 2905 switch (cmd) { 2906 case IKE_SVC_GET_DEFS: 2907 do_getdefs(cmd); 2908 break; 2909 case IKE_SVC_GET_DBG: 2910 case IKE_SVC_GET_PRIV: 2911 do_getvar(cmd); 2912 break; 2913 case IKE_SVC_GET_STATS: 2914 do_getstats(cmd); 2915 break; 2916 case IKE_SVC_SET_DBG: 2917 case IKE_SVC_SET_PRIV: 2918 do_setvar(cmd, argc, argv); 2919 break; 2920 case IKE_SVC_DUMP_P1S: 2921 case IKE_SVC_DUMP_RULES: 2922 case IKE_SVC_DUMP_PS: 2923 do_dump(cmd); 2924 break; 2925 case IKE_SVC_GET_P1: 2926 case IKE_SVC_GET_RULE: 2927 case IKE_SVC_GET_PS: 2928 case IKE_SVC_DEL_P1: 2929 case IKE_SVC_DEL_RULE: 2930 case IKE_SVC_DEL_PS: 2931 do_getdel(cmd, argc, argv); 2932 break; 2933 case IKE_SVC_NEW_RULE: 2934 case IKE_SVC_NEW_PS: 2935 do_new(cmd, argc, argv); 2936 break; 2937 case IKE_SVC_FLUSH_P1S: 2938 do_flush(cmd); 2939 break; 2940 case IKE_SVC_READ_RULES: 2941 case IKE_SVC_READ_PS: 2942 case IKE_SVC_WRITE_RULES: 2943 case IKE_SVC_WRITE_PS: 2944 do_rw(cmd, argc, argv); 2945 break; 2946 case IKEADM_HELP_GENERAL: 2947 print_help(); 2948 break; 2949 case IKEADM_HELP_GET: 2950 print_get_help(); 2951 break; 2952 case IKEADM_HELP_SET: 2953 print_set_help(); 2954 break; 2955 case IKEADM_HELP_ADD: 2956 print_add_help(); 2957 break; 2958 case IKEADM_HELP_DEL: 2959 print_del_help(); 2960 break; 2961 case IKEADM_HELP_DUMP: 2962 print_dump_help(); 2963 break; 2964 case IKEADM_HELP_FLUSH: 2965 print_flush_help(); 2966 break; 2967 case IKEADM_HELP_READ: 2968 print_read_help(); 2969 break; 2970 case IKEADM_HELP_WRITE: 2971 print_write_help(); 2972 break; 2973 case IKEADM_HELP_HELP: 2974 print_help_help(); 2975 break; 2976 case IKEADM_EXIT: 2977 if (interactive) 2978 exit(0); 2979 break; 2980 case IKE_SVC_DBG_RBDUMP: 2981 do_rbdump(); 2982 break; 2983 case IKE_SVC_ERROR: 2984 usage(); 2985 default: 2986 exit(0); 2987 } 2988 } 2989 2990 int 2991 main(int argc, char **argv) 2992 { 2993 char ch; 2994 2995 (void) setlocale(LC_ALL, ""); 2996 #if !defined(TEXT_DOMAIN) 2997 #define TEXT_DOMAIN "SYS_TEST" 2998 #endif 2999 (void) textdomain(TEXT_DOMAIN); 3000 3001 while ((ch = getopt(argc, argv, "hpn")) != EOF) { 3002 switch (ch) { 3003 case 'h': 3004 print_help(); 3005 return (0); 3006 case 'p': 3007 pflag = B_TRUE; 3008 break; 3009 case 'n': 3010 nflag = B_TRUE; 3011 break; 3012 default: 3013 usage(); 3014 } 3015 } 3016 argc -= optind; 3017 argv += optind; 3018 3019 if (open_door() < 0) { 3020 (void) fprintf(stderr, 3021 gettext("Unable to communicate with in.iked\n")); 3022 Bail("open_door failed"); 3023 } 3024 3025 if (*argv == NULL) { 3026 /* no cmd-line args, do interactive mode */ 3027 do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit); 3028 } 3029 3030 parseit(argc, argv, NULL, B_FALSE); 3031 3032 return (0); 3033 } 3034