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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <unistd.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <stdarg.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <sys/sysconf.h> 37 #include <strings.h> 38 #include <ctype.h> 39 #include <errno.h> 40 #include <sys/socket.h> 41 #include <netdb.h> 42 #include <netinet/in.h> 43 #include <arpa/inet.h> 44 #include <net/pfkeyv2.h> 45 #include <net/pfpolicy.h> 46 #include <libintl.h> 47 #include <setjmp.h> 48 #include <libgen.h> 49 50 #include "ipsec_util.h" 51 #include "ikedoor.h" 52 53 /* 54 * This file contains support functions that are shared by the ipsec 55 * utilities including ipseckey(1m) and ikeadm(1m). 56 */ 57 58 /* Set standard default/initial values for globals... */ 59 boolean_t pflag = B_FALSE; /* paranoid w.r.t. printing keying material */ 60 boolean_t nflag = B_FALSE; /* avoid nameservice? */ 61 boolean_t interactive = B_FALSE; /* util not running on cmdline */ 62 boolean_t readfile = B_FALSE; /* cmds are being read from a file */ 63 uint_t lineno = 0; /* track location if reading cmds from file */ 64 jmp_buf env; /* for error recovery in interactive/readfile modes */ 65 66 /* 67 * Print errno and exit if cmdline or readfile, reset state if interactive 68 */ 69 void 70 bail(char *what) 71 { 72 if (errno != 0) 73 warn(what); 74 else 75 warnx(gettext("Error: %s"), what); 76 if (readfile) { 77 warnx(gettext("System error on line %u."), lineno); 78 } 79 if (interactive && !readfile) 80 longjmp(env, 2); 81 exit(1); 82 } 83 84 /* 85 * Print caller-supplied variable-arg error msg, then exit if cmdline or 86 * readfile, or reset state if interactive. 87 */ 88 /*PRINTFLIKE1*/ 89 void 90 bail_msg(char *fmt, ...) 91 { 92 va_list ap; 93 char msgbuf[BUFSIZ]; 94 95 va_start(ap, fmt); 96 (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap); 97 va_end(ap); 98 if (readfile) 99 warnx(gettext("ERROR on line %u:\n%s\n"), lineno, msgbuf); 100 else 101 warnx(gettext("ERROR: %s\n"), msgbuf); 102 103 if (interactive && !readfile) 104 longjmp(env, 1); 105 106 exit(1); 107 } 108 109 110 /* 111 * dump_XXX functions produce ASCII output from various structures. 112 * 113 * Because certain errors need to do this to stderr, dump_XXX functions 114 * take a FILE pointer. 115 * 116 * If an error occured while writing to the specified file, these 117 * functions return -1, zero otherwise. 118 */ 119 120 int 121 dump_sockaddr(struct sockaddr *sa, boolean_t addr_only, FILE *where) 122 { 123 struct sockaddr_in *sin; 124 struct sockaddr_in6 *sin6; 125 char *printable_addr, *protocol; 126 uint8_t *addrptr; 127 char storage[INET6_ADDRSTRLEN]; 128 uint16_t port; 129 boolean_t unspec; 130 struct hostent *hp; 131 int getipnode_errno, addrlen; 132 133 switch (sa->sa_family) { 134 case AF_INET: 135 /* LINTED E_BAD_PTR_CAST_ALIGN */ 136 sin = (struct sockaddr_in *)sa; 137 addrptr = (uint8_t *)&sin->sin_addr; 138 port = sin->sin_port; 139 protocol = "AF_INET"; 140 unspec = (sin->sin_addr.s_addr == 0); 141 addrlen = sizeof (sin->sin_addr); 142 break; 143 case AF_INET6: 144 /* LINTED E_BAD_PTR_CAST_ALIGN */ 145 sin6 = (struct sockaddr_in6 *)sa; 146 addrptr = (uint8_t *)&sin6->sin6_addr; 147 port = sin6->sin6_port; 148 protocol = "AF_INET6"; 149 unspec = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr); 150 addrlen = sizeof (sin6->sin6_addr); 151 break; 152 default: 153 return (0); 154 } 155 156 if (inet_ntop(sa->sa_family, addrptr, storage, INET6_ADDRSTRLEN) == 157 NULL) { 158 printable_addr = gettext("<inet_ntop() failed>"); 159 } else { 160 printable_addr = storage; 161 } 162 if (addr_only) { 163 if (fprintf(where, "%s", printable_addr) < 0) 164 return (-1); 165 } else { 166 if (fprintf(where, gettext("%s: port %d, %s"), protocol, 167 ntohs(port), printable_addr) < 0) 168 return (-1); 169 if (!nflag) { 170 /* 171 * Do AF_independent reverse hostname lookup here. 172 */ 173 if (unspec) { 174 if (fprintf(where, 175 gettext(" <unspecified>")) < 0) 176 return (-1); 177 } else { 178 hp = getipnodebyaddr((char *)addrptr, addrlen, 179 sa->sa_family, &getipnode_errno); 180 if (hp != NULL) { 181 if (fprintf(where, 182 " (%s)", hp->h_name) < 0) 183 return (-1); 184 freehostent(hp); 185 } else { 186 if (fprintf(where, 187 gettext(" <unknown>")) < 0) 188 return (-1); 189 } 190 } 191 } 192 if (fputs(".\n", where) == EOF) 193 return (-1); 194 } 195 return (0); 196 } 197 198 /* 199 * Dump a key and bitlen 200 */ 201 int 202 dump_key(uint8_t *keyp, uint_t bitlen, FILE *where) 203 { 204 int numbytes; 205 206 numbytes = SADB_1TO8(bitlen); 207 /* The & 0x7 is to check for leftover bits. */ 208 if ((bitlen & 0x7) != 0) 209 numbytes++; 210 while (numbytes-- != 0) { 211 if (pflag) { 212 /* Print no keys if paranoid */ 213 if (fprintf(where, "XX") < 0) 214 return (-1); 215 } else { 216 if (fprintf(where, "%02x", *keyp++) < 0) 217 return (-1); 218 } 219 } 220 if (fprintf(where, "/%u", bitlen) < 0) 221 return (-1); 222 return (0); 223 } 224 225 /* 226 * Print an authentication or encryption algorithm 227 */ 228 static int 229 dump_generic_alg(uint8_t alg_num, int proto_num, FILE *where) 230 { 231 struct ipsecalgent *alg; 232 233 alg = getipsecalgbynum(alg_num, proto_num, NULL); 234 if (alg == NULL) { 235 if (fprintf(where, gettext("<unknown %u>"), alg_num) < 0) 236 return (-1); 237 return (0); 238 } 239 240 /* 241 * Special-case <none> for backward output compat. 242 * Assume that SADB_AALG_NONE == SADB_EALG_NONE. 243 */ 244 if (alg_num == SADB_AALG_NONE) { 245 if (fputs(gettext("<none>"), where) == EOF) 246 return (-1); 247 } else { 248 if (fputs(alg->a_names[0], where) == EOF) 249 return (-1); 250 } 251 252 freeipsecalgent(alg); 253 return (0); 254 } 255 256 int 257 dump_aalg(uint8_t aalg, FILE *where) 258 { 259 return (dump_generic_alg(aalg, IPSEC_PROTO_AH, where)); 260 } 261 262 int 263 dump_ealg(uint8_t ealg, FILE *where) 264 { 265 return (dump_generic_alg(ealg, IPSEC_PROTO_ESP, where)); 266 } 267 268 /* 269 * Print an SADB_IDENTTYPE string 270 * 271 * Also return TRUE if the actual ident may be printed, FALSE if not. 272 * 273 * If rc is not NULL, set its value to -1 if an error occured while writing 274 * to the specified file, zero otherwise. 275 */ 276 boolean_t 277 dump_sadb_idtype(uint8_t idtype, FILE *where, int *rc) 278 { 279 boolean_t canprint = B_TRUE; 280 int rc_val = 0; 281 282 switch (idtype) { 283 case SADB_IDENTTYPE_PREFIX: 284 if (fputs(gettext("prefix"), where) == EOF) 285 rc_val = -1; 286 break; 287 case SADB_IDENTTYPE_FQDN: 288 if (fputs(gettext("FQDN"), where) == EOF) 289 rc_val = -1; 290 break; 291 case SADB_IDENTTYPE_USER_FQDN: 292 if (fputs(gettext("user-FQDN (mbox)"), where) == EOF) 293 rc_val = -1; 294 break; 295 case SADB_X_IDENTTYPE_DN: 296 if (fputs(gettext("ASN.1 DER Distinguished Name"), 297 where) == EOF) 298 rc_val = -1; 299 canprint = B_FALSE; 300 break; 301 case SADB_X_IDENTTYPE_GN: 302 if (fputs(gettext("ASN.1 DER Generic Name"), where) == EOF) 303 rc_val = -1; 304 canprint = B_FALSE; 305 break; 306 case SADB_X_IDENTTYPE_KEY_ID: 307 if (fputs(gettext("Generic key id"), where) == EOF) 308 rc_val = -1; 309 break; 310 case SADB_X_IDENTTYPE_ADDR_RANGE: 311 if (fputs(gettext("Address range"), where) == EOF) 312 rc_val = -1; 313 break; 314 default: 315 if (fprintf(where, gettext("<unknown %u>"), idtype) < 0) 316 rc_val = -1; 317 break; 318 } 319 320 if (rc != NULL) 321 *rc = rc_val; 322 323 return (canprint); 324 } 325 326 /* 327 * Slice an argv/argc vector from an interactive line or a read-file line. 328 */ 329 static int 330 create_argv(char *ibuf, int *newargc, char ***thisargv) 331 { 332 unsigned int argvlen = START_ARG; 333 char **current; 334 boolean_t firstchar = B_TRUE; 335 boolean_t inquotes = B_FALSE; 336 337 *thisargv = malloc(sizeof (char *) * argvlen); 338 if ((*thisargv) == NULL) 339 return (MEMORY_ALLOCATION); 340 current = *thisargv; 341 *current = NULL; 342 343 for (; *ibuf != '\0'; ibuf++) { 344 if (isspace(*ibuf)) { 345 if (inquotes) { 346 continue; 347 } 348 if (*current != NULL) { 349 *ibuf = '\0'; 350 current++; 351 if (*thisargv + argvlen == current) { 352 /* Regrow ***thisargv. */ 353 if (argvlen == TOO_MANY_ARGS) { 354 free(*thisargv); 355 return (TOO_MANY_TOKENS); 356 } 357 /* Double the allocation. */ 358 current = realloc(*thisargv, 359 sizeof (char *) * (argvlen << 1)); 360 if (current == NULL) { 361 free(*thisargv); 362 return (MEMORY_ALLOCATION); 363 } 364 *thisargv = current; 365 current += argvlen; 366 argvlen <<= 1; /* Double the size. */ 367 } 368 *current = NULL; 369 } 370 } else { 371 if (firstchar) { 372 firstchar = B_FALSE; 373 if (*ibuf == COMMENT_CHAR) { 374 free(*thisargv); 375 return (COMMENT_LINE); 376 } 377 } 378 if (*ibuf == QUOTE_CHAR) { 379 if (inquotes) { 380 inquotes = B_FALSE; 381 *ibuf = '\0'; 382 } else { 383 inquotes = B_TRUE; 384 } 385 continue; 386 } 387 if (*current == NULL) { 388 *current = ibuf; 389 (*newargc)++; 390 } 391 } 392 } 393 394 /* 395 * Tricky corner case... 396 * I've parsed _exactly_ the amount of args as I have space. It 397 * won't return NULL-terminated, and bad things will happen to 398 * the caller. 399 */ 400 if (argvlen == *newargc) { 401 current = realloc(*thisargv, sizeof (char *) * (argvlen + 1)); 402 if (current == NULL) { 403 free(*thisargv); 404 return (MEMORY_ALLOCATION); 405 } 406 *thisargv = current; 407 current[argvlen] = NULL; 408 } 409 410 return (SUCCESS); 411 } 412 413 /* 414 * Enter a mode where commands are read from a file. Treat stdin special. 415 */ 416 void 417 do_interactive(FILE *infile, char *promptstring, parse_cmdln_fn parseit) 418 { 419 char ibuf[IBUF_SIZE], holder[IBUF_SIZE]; 420 char *hptr, **thisargv; 421 int thisargc; 422 boolean_t continue_in_progress = B_FALSE; 423 424 (void) setjmp(env); 425 426 interactive = B_TRUE; 427 bzero(ibuf, IBUF_SIZE); 428 429 if (infile == stdin) { 430 (void) printf("%s", promptstring); 431 (void) fflush(stdout); 432 } else { 433 readfile = B_TRUE; 434 } 435 436 while (fgets(ibuf, IBUF_SIZE, infile) != NULL) { 437 if (readfile) 438 lineno++; 439 thisargc = 0; 440 thisargv = NULL; 441 442 /* 443 * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will 444 * be null-terminated because of fgets(). 445 */ 446 if (ibuf[IBUF_SIZE - 2] != '\0') { 447 (void) fprintf(stderr, 448 gettext("Line %d too big.\n"), lineno); 449 exit(1); 450 } 451 452 if (!continue_in_progress) { 453 /* Use -2 because of \n from fgets. */ 454 if (ibuf[strlen(ibuf) - 2] == CONT_CHAR) { 455 /* 456 * Can use strcpy here, I've checked the 457 * length already. 458 */ 459 (void) strcpy(holder, ibuf); 460 hptr = &(holder[strlen(holder)]); 461 462 /* Remove the CONT_CHAR from the string. */ 463 hptr[-2] = ' '; 464 465 continue_in_progress = B_TRUE; 466 bzero(ibuf, IBUF_SIZE); 467 continue; 468 } 469 } else { 470 /* Handle continuations... */ 471 (void) strncpy(hptr, ibuf, 472 (size_t)(&(holder[IBUF_SIZE]) - hptr)); 473 if (holder[IBUF_SIZE - 1] != '\0') { 474 (void) fprintf(stderr, 475 gettext("Command buffer overrun.\n")); 476 exit(1); 477 } 478 /* Use - 2 because of \n from fgets. */ 479 if (hptr[strlen(hptr) - 2] == CONT_CHAR) { 480 bzero(ibuf, IBUF_SIZE); 481 hptr += strlen(hptr); 482 483 /* Remove the CONT_CHAR from the string. */ 484 hptr[-2] = ' '; 485 486 continue; 487 } else { 488 continue_in_progress = B_FALSE; 489 /* 490 * I've already checked the length... 491 */ 492 (void) strcpy(ibuf, holder); 493 } 494 } 495 496 switch (create_argv(ibuf, &thisargc, &thisargv)) { 497 case TOO_MANY_TOKENS: 498 (void) fprintf(stderr, 499 gettext("Too many input tokens.\n")); 500 exit(1); 501 break; 502 case MEMORY_ALLOCATION: 503 (void) fprintf(stderr, 504 gettext("Memory allocation error.\n")); 505 exit(1); 506 break; 507 case COMMENT_LINE: 508 /* Comment line. */ 509 break; 510 default: 511 parseit(thisargc, thisargv); 512 free(thisargv); 513 if (infile == stdin) { 514 (void) printf("%s", promptstring); 515 (void) fflush(stdout); 516 } 517 break; 518 } 519 bzero(ibuf, IBUF_SIZE); 520 } 521 if (!readfile) { 522 (void) putchar('\n'); 523 (void) fflush(stdout); 524 } 525 exit(0); 526 } 527 528 /* 529 * Functions to parse strings that represent a debug or privilege level. 530 * These functions are copied from main.c and door.c in usr.lib/in.iked/common. 531 * If this file evolves into a common library that may be used by in.iked 532 * as well as the usr.sbin utilities, those duplicate functions should be 533 * deleted. 534 * 535 * A privilege level may be represented by a simple keyword, corresponding 536 * to one of the possible levels. A debug level may be represented by a 537 * series of keywords, separated by '+' or '-', indicating categories to 538 * be added or removed from the set of categories in the debug level. 539 * For example, +all-op corresponds to level 0xfffffffb (all flags except 540 * for D_OP set); while p1+p2+pfkey corresponds to level 0x38. Note that 541 * the leading '+' is implicit; the first keyword in the list must be for 542 * a category that is to be added. 543 * 544 * These parsing functions make use of a local version of strtok, strtok_d, 545 * which includes an additional parameter, char *delim. This param is filled 546 * in with the character which ends the returned token. In other words, 547 * this version of strtok, in addition to returning the token, also returns 548 * the single character delimiter from the original string which marked the 549 * end of the token. 550 */ 551 static char * 552 strtok_d(char *string, const char *sepset, char *delim) 553 { 554 static char *lasts; 555 char *q, *r; 556 557 /* first or subsequent call */ 558 if (string == NULL) 559 string = lasts; 560 561 if (string == 0) /* return if no tokens remaining */ 562 return (NULL); 563 564 q = string + strspn(string, sepset); /* skip leading separators */ 565 566 if (*q == '\0') /* return if no tokens remaining */ 567 return (NULL); 568 569 if ((r = strpbrk(q, sepset)) == NULL) { /* move past token */ 570 lasts = 0; /* indicate that this is last token */ 571 } else { 572 *delim = *r; /* save delimitor */ 573 *r = '\0'; 574 lasts = r + 1; 575 } 576 return (q); 577 } 578 579 static keywdtab_t privtab[] = { 580 { IKE_PRIV_MINIMUM, "base" }, 581 { IKE_PRIV_MODKEYS, "modkeys" }, 582 { IKE_PRIV_KEYMAT, "keymat" }, 583 { IKE_PRIV_MINIMUM, "0" }, 584 }; 585 586 int 587 privstr2num(char *str) 588 { 589 keywdtab_t *pp; 590 char *endp; 591 int priv; 592 593 for (pp = privtab; pp < A_END(privtab); pp++) { 594 if (strcasecmp(str, pp->kw_str) == 0) 595 return (pp->kw_tag); 596 } 597 598 priv = strtol(str, &endp, 0); 599 if (*endp == '\0') 600 return (priv); 601 602 return (-1); 603 } 604 605 static keywdtab_t dbgtab[] = { 606 { D_CERT, "cert" }, 607 { D_KEY, "key" }, 608 { D_OP, "op" }, 609 { D_P1, "p1" }, 610 { D_P1, "phase1" }, 611 { D_P2, "p2" }, 612 { D_P2, "phase2" }, 613 { D_PFKEY, "pfkey" }, 614 { D_POL, "pol" }, 615 { D_POL, "policy" }, 616 { D_PROP, "prop" }, 617 { D_DOOR, "door" }, 618 { D_CONFIG, "config" }, 619 { D_ALL, "all" }, 620 { 0, "0" }, 621 }; 622 623 int 624 dbgstr2num(char *str) 625 { 626 keywdtab_t *dp; 627 628 for (dp = dbgtab; dp < A_END(dbgtab); dp++) { 629 if (strcasecmp(str, dp->kw_str) == 0) 630 return (dp->kw_tag); 631 } 632 return (D_INVALID); 633 } 634 635 int 636 parsedbgopts(char *optarg) 637 { 638 char *argp, *endp, op, nextop; 639 int mask = 0, new; 640 641 mask = strtol(optarg, &endp, 0); 642 if (*endp == '\0') 643 return (mask); 644 645 op = optarg[0]; 646 if (op != '-') 647 op = '+'; 648 argp = strtok_d(optarg, "+-", &nextop); 649 do { 650 new = dbgstr2num(argp); 651 if (new == D_INVALID) { 652 /* we encountered an invalid keywd */ 653 return (new); 654 } 655 if (op == '+') { 656 mask |= new; 657 } else { 658 mask &= ~new; 659 } 660 op = nextop; 661 } while ((argp = strtok_d(NULL, "+-", &nextop)) != NULL); 662 663 return (mask); 664 } 665 666 667 /* 668 * functions to manipulate the kmcookie-label mapping file 669 */ 670 671 /* 672 * Open, lockf, fdopen the given file, returning a FILE * on success, 673 * or NULL on failure. 674 */ 675 FILE * 676 kmc_open_and_lock(char *name) 677 { 678 int fd, rtnerr; 679 FILE *fp; 680 681 if ((fd = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { 682 return (NULL); 683 } 684 if (lockf(fd, F_LOCK, 0) < 0) { 685 return (NULL); 686 } 687 if ((fp = fdopen(fd, "a+")) == NULL) { 688 return (NULL); 689 } 690 if (fseek(fp, 0, SEEK_SET) < 0) { 691 /* save errno in case fclose changes it */ 692 rtnerr = errno; 693 (void) fclose(fp); 694 errno = rtnerr; 695 return (NULL); 696 } 697 return (fp); 698 } 699 700 /* 701 * Extract an integer cookie and string label from a line from the 702 * kmcookie-label file. Return -1 on failure, 0 on success. 703 */ 704 int 705 kmc_parse_line(char *line, int *cookie, char **label) 706 { 707 char *cookiestr; 708 709 *cookie = 0; 710 *label = NULL; 711 712 cookiestr = strtok(line, " \t\n"); 713 if (cookiestr == NULL) { 714 return (-1); 715 } 716 717 /* Everything that follows, up to the newline, is the label. */ 718 *label = strtok(NULL, "\n"); 719 if (*label == NULL) { 720 return (-1); 721 } 722 723 *cookie = atoi(cookiestr); 724 return (0); 725 } 726 727 /* 728 * Insert a mapping into the file (if it's not already there), given the 729 * new label. Return the assigned cookie, or -1 on error. 730 */ 731 int 732 kmc_insert_mapping(char *label) 733 { 734 FILE *map; 735 char linebuf[MAXLINESIZE]; 736 char *cur_label; 737 int max_cookie = 0, cur_cookie, rtn_cookie; 738 int rtnerr = 0; 739 boolean_t found = B_FALSE; 740 741 /* open and lock the file; will sleep until lock is available */ 742 if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 743 /* kmc_open_and_lock() sets errno appropriately */ 744 return (-1); 745 } 746 747 while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 748 749 if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 750 rtnerr = EINVAL; 751 goto error; 752 } 753 754 if (cur_cookie > max_cookie) 755 max_cookie = cur_cookie; 756 757 if ((!found) && (strcmp(cur_label, label) == 0)) { 758 found = B_TRUE; 759 rtn_cookie = cur_cookie; 760 } 761 } 762 763 if (!found) { 764 rtn_cookie = ++max_cookie; 765 if ((fprintf(map, "%u\t%s\n", rtn_cookie, label) < 0) || 766 (fflush(map) < 0)) { 767 rtnerr = errno; 768 goto error; 769 } 770 } 771 (void) fclose(map); 772 773 return (rtn_cookie); 774 775 error: 776 (void) fclose(map); 777 errno = rtnerr; 778 return (-1); 779 } 780 781 /* 782 * Lookup the given cookie and return its corresponding label. Return 783 * a pointer to the label on success, NULL on error (or if the label is 784 * not found). Note that the returned label pointer points to a static 785 * string, so the label will be overwritten by a subsequent call to the 786 * function; the function is also not thread-safe as a result. 787 */ 788 char * 789 kmc_lookup_by_cookie(int cookie) 790 { 791 FILE *map; 792 static char linebuf[MAXLINESIZE]; 793 char *cur_label; 794 int cur_cookie; 795 796 if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 797 return (NULL); 798 } 799 800 while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 801 802 if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 803 (void) fclose(map); 804 return (NULL); 805 } 806 807 if (cookie == cur_cookie) { 808 (void) fclose(map); 809 return (cur_label); 810 } 811 } 812 (void) fclose(map); 813 814 return (NULL); 815 } 816 817 /* 818 * Parse basic extension headers and return in the passed-in pointer vector. 819 * Return values include: 820 * 821 * KGE_OK Everything's nice and parsed out. 822 * If there are no extensions, place NULL in extv[0]. 823 * KGE_DUP There is a duplicate extension. 824 * First instance in appropriate bin. First duplicate in 825 * extv[0]. 826 * KGE_UNK Unknown extension type encountered. extv[0] contains 827 * unknown header. 828 * KGE_LEN Extension length error. 829 * KGE_CHK High-level reality check failed on specific extension. 830 * 831 * My apologies for some of the pointer arithmetic in here. I'm thinking 832 * like an assembly programmer, yet trying to make the compiler happy. 833 */ 834 int 835 spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize, 836 char *diag_buf, uint_t diag_buf_len) 837 { 838 int i; 839 840 if (diag_buf != NULL) 841 diag_buf[0] = '\0'; 842 843 for (i = 1; i <= SPD_EXT_MAX; i++) 844 extv[i] = NULL; 845 846 i = 0; 847 /* Use extv[0] as the "current working pointer". */ 848 849 extv[0] = (spd_ext_t *)(basehdr + 1); 850 msgsize = SPD_64TO8(msgsize); 851 852 while ((char *)extv[0] < ((char *)basehdr + msgsize)) { 853 /* Check for unknown headers. */ 854 i++; 855 856 if (extv[0]->spd_ext_type == 0 || 857 extv[0]->spd_ext_type > SPD_EXT_MAX) { 858 if (diag_buf != NULL) { 859 (void) snprintf(diag_buf, diag_buf_len, 860 "spdsock ext 0x%X unknown: 0x%X", 861 i, extv[0]->spd_ext_type); 862 } 863 return (KGE_UNK); 864 } 865 866 /* 867 * Check length. Use uint64_t because extlen is in units 868 * of 64-bit words. If length goes beyond the msgsize, 869 * return an error. (Zero length also qualifies here.) 870 */ 871 if (extv[0]->spd_ext_len == 0 || 872 (uint8_t *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) > 873 (uint8_t *)((uint8_t *)basehdr + msgsize)) 874 return (KGE_LEN); 875 876 /* Check for redundant headers. */ 877 if (extv[extv[0]->spd_ext_type] != NULL) 878 return (KGE_DUP); 879 880 /* If I make it here, assign the appropriate bin. */ 881 extv[extv[0]->spd_ext_type] = extv[0]; 882 883 /* Advance pointer (See above for uint64_t ptr reasoning.) */ 884 extv[0] = (spd_ext_t *) 885 ((uint64_t *)extv[0] + extv[0]->spd_ext_len); 886 } 887 888 /* Everything's cool. */ 889 890 /* 891 * If extv[0] == NULL, then there are no extension headers in this 892 * message. Ensure that this is the case. 893 */ 894 if (extv[0] == (spd_ext_t *)(basehdr + 1)) 895 extv[0] = NULL; 896 897 return (KGE_OK); 898 } 899 900 const char * 901 spdsock_diag(int diagnostic) 902 { 903 switch (diagnostic) { 904 case SPD_DIAGNOSTIC_NONE: 905 return (gettext("no error")); 906 case SPD_DIAGNOSTIC_UNKNOWN_EXT: 907 return (gettext("unknown extension")); 908 case SPD_DIAGNOSTIC_BAD_EXTLEN: 909 return (gettext("bad extension length")); 910 case SPD_DIAGNOSTIC_NO_RULE_EXT: 911 return (gettext("no rule extension")); 912 case SPD_DIAGNOSTIC_BAD_ADDR_LEN: 913 return (gettext("bad address len")); 914 case SPD_DIAGNOSTIC_MIXED_AF: 915 return (gettext("mixed address family")); 916 case SPD_DIAGNOSTIC_ADD_NO_MEM: 917 return (gettext("add: no memory")); 918 case SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT: 919 return (gettext("add: wrong action count")); 920 case SPD_DIAGNOSTIC_ADD_BAD_TYPE: 921 return (gettext("add: bad type")); 922 case SPD_DIAGNOSTIC_ADD_BAD_FLAGS: 923 return (gettext("add: bad flags")); 924 case SPD_DIAGNOSTIC_ADD_INCON_FLAGS: 925 return (gettext("add: inconsistent flags")); 926 case SPD_DIAGNOSTIC_MALFORMED_LCLPORT: 927 return (gettext("malformed local port")); 928 case SPD_DIAGNOSTIC_DUPLICATE_LCLPORT: 929 return (gettext("duplicate local port")); 930 case SPD_DIAGNOSTIC_MALFORMED_REMPORT: 931 return (gettext("malformed remote port")); 932 case SPD_DIAGNOSTIC_DUPLICATE_REMPORT: 933 return (gettext("duplicate remote port")); 934 case SPD_DIAGNOSTIC_MALFORMED_PROTO: 935 return (gettext("malformed proto")); 936 case SPD_DIAGNOSTIC_DUPLICATE_PROTO: 937 return (gettext("duplicate proto")); 938 case SPD_DIAGNOSTIC_MALFORMED_LCLADDR: 939 return (gettext("malformed local address")); 940 case SPD_DIAGNOSTIC_DUPLICATE_LCLADDR: 941 return (gettext("duplicate local address")); 942 case SPD_DIAGNOSTIC_MALFORMED_REMADDR: 943 return (gettext("malformed remote address")); 944 case SPD_DIAGNOSTIC_DUPLICATE_REMADDR: 945 return (gettext("duplicate remote address")); 946 case SPD_DIAGNOSTIC_MALFORMED_ACTION: 947 return (gettext("malformed action")); 948 case SPD_DIAGNOSTIC_DUPLICATE_ACTION: 949 return (gettext("duplicate action")); 950 case SPD_DIAGNOSTIC_MALFORMED_RULE: 951 return (gettext("malformed rule")); 952 case SPD_DIAGNOSTIC_DUPLICATE_RULE: 953 return (gettext("duplicate rule")); 954 case SPD_DIAGNOSTIC_MALFORMED_RULESET: 955 return (gettext("malformed ruleset")); 956 case SPD_DIAGNOSTIC_DUPLICATE_RULESET: 957 return (gettext("duplicate ruleset")); 958 case SPD_DIAGNOSTIC_INVALID_RULE_INDEX: 959 return (gettext("invalid rule index")); 960 case SPD_DIAGNOSTIC_BAD_SPDID: 961 return (gettext("bad spdid")); 962 case SPD_DIAGNOSTIC_BAD_MSG_TYPE: 963 return (gettext("bad message type")); 964 case SPD_DIAGNOSTIC_UNSUPP_AH_ALG: 965 return (gettext("unsupported AH algorithm")); 966 case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG: 967 return (gettext("unsupported ESP encryption algorithm")); 968 case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG: 969 return (gettext("unsupported ESP authentication algorithm")); 970 case SPD_DIAGNOSTIC_UNSUPP_AH_KEYSIZE: 971 return (gettext("unsupported AH key size")); 972 case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_KEYSIZE: 973 return (gettext("unsupported ESP encryption key size")); 974 case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_KEYSIZE: 975 return (gettext("unsupported ESP authentication key size")); 976 case SPD_DIAGNOSTIC_NO_ACTION_EXT: 977 return (gettext("No ACTION extension")); 978 case SPD_DIAGNOSTIC_ALG_ID_RANGE: 979 return (gettext("invalid algorithm identifer")); 980 case SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES: 981 return (gettext("number of key sizes inconsistent")); 982 case SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES: 983 return (gettext("number of block sizes inconsistent")); 984 case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN: 985 return (gettext("invalid mechanism name length")); 986 default: 987 return (gettext("unknown diagnostic")); 988 } 989 } 990 991 /* 992 * PF_KEY Diagnostic table. 993 * 994 * PF_KEY NOTE: If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is 995 * where you need to add new messages. 996 */ 997 998 const char * 999 keysock_diag(int diagnostic) 1000 { 1001 switch (diagnostic) { 1002 case SADB_X_DIAGNOSTIC_NONE: 1003 return (gettext("No diagnostic")); 1004 case SADB_X_DIAGNOSTIC_UNKNOWN_MSG: 1005 return (gettext("Unknown message type")); 1006 case SADB_X_DIAGNOSTIC_UNKNOWN_EXT: 1007 return (gettext("Unknown extension type")); 1008 case SADB_X_DIAGNOSTIC_BAD_EXTLEN: 1009 return (gettext("Bad extension length")); 1010 case SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE: 1011 return (gettext("Unknown Security Association type")); 1012 case SADB_X_DIAGNOSTIC_SATYPE_NEEDED: 1013 return (gettext("Specific Security Association type needed")); 1014 case SADB_X_DIAGNOSTIC_NO_SADBS: 1015 return (gettext("No Security Association Databases present")); 1016 case SADB_X_DIAGNOSTIC_NO_EXT: 1017 return (gettext("No extensions needed for message")); 1018 case SADB_X_DIAGNOSTIC_BAD_SRC_AF: 1019 return (gettext("Bad source address family")); 1020 case SADB_X_DIAGNOSTIC_BAD_DST_AF: 1021 return (gettext("Bad destination address family")); 1022 case SADB_X_DIAGNOSTIC_BAD_PROXY_AF: 1023 return (gettext("Bad proxy address family")); 1024 case SADB_X_DIAGNOSTIC_AF_MISMATCH: 1025 return (gettext("Source/destination address family mismatch")); 1026 case SADB_X_DIAGNOSTIC_BAD_SRC: 1027 return (gettext("Bad source address value")); 1028 case SADB_X_DIAGNOSTIC_BAD_DST: 1029 return (gettext("Bad destination address value")); 1030 case SADB_X_DIAGNOSTIC_ALLOC_HSERR: 1031 return (gettext("Soft allocations limit more than hard limit")); 1032 case SADB_X_DIAGNOSTIC_BYTES_HSERR: 1033 return (gettext("Soft bytes limit more than hard limit")); 1034 case SADB_X_DIAGNOSTIC_ADDTIME_HSERR: 1035 return (gettext("Soft add expiration time later " 1036 "than hard expiration time")); 1037 case SADB_X_DIAGNOSTIC_USETIME_HSERR: 1038 return (gettext("Soft use expiration time later " 1039 "than hard expiration time")); 1040 case SADB_X_DIAGNOSTIC_MISSING_SRC: 1041 return (gettext("Missing source address")); 1042 case SADB_X_DIAGNOSTIC_MISSING_DST: 1043 return (gettext("Missing destination address")); 1044 case SADB_X_DIAGNOSTIC_MISSING_SA: 1045 return (gettext("Missing SA extension")); 1046 case SADB_X_DIAGNOSTIC_MISSING_EKEY: 1047 return (gettext("Missing encryption key")); 1048 case SADB_X_DIAGNOSTIC_MISSING_AKEY: 1049 return (gettext("Missing authentication key")); 1050 case SADB_X_DIAGNOSTIC_MISSING_RANGE: 1051 return (gettext("Missing SPI range")); 1052 case SADB_X_DIAGNOSTIC_DUPLICATE_SRC: 1053 return (gettext("Duplicate source address")); 1054 case SADB_X_DIAGNOSTIC_DUPLICATE_DST: 1055 return (gettext("Duplicate destination address")); 1056 case SADB_X_DIAGNOSTIC_DUPLICATE_SA: 1057 return (gettext("Duplicate SA extension")); 1058 case SADB_X_DIAGNOSTIC_DUPLICATE_EKEY: 1059 return (gettext("Duplicate encryption key")); 1060 case SADB_X_DIAGNOSTIC_DUPLICATE_AKEY: 1061 return (gettext("Duplicate authentication key")); 1062 case SADB_X_DIAGNOSTIC_DUPLICATE_RANGE: 1063 return (gettext("Duplicate SPI range")); 1064 case SADB_X_DIAGNOSTIC_MALFORMED_SRC: 1065 return (gettext("Malformed source address")); 1066 case SADB_X_DIAGNOSTIC_MALFORMED_DST: 1067 return (gettext("Malformed destination address")); 1068 case SADB_X_DIAGNOSTIC_MALFORMED_SA: 1069 return (gettext("Malformed SA extension")); 1070 case SADB_X_DIAGNOSTIC_MALFORMED_EKEY: 1071 return (gettext("Malformed encryption key")); 1072 case SADB_X_DIAGNOSTIC_MALFORMED_AKEY: 1073 return (gettext("Malformed authentication key")); 1074 case SADB_X_DIAGNOSTIC_MALFORMED_RANGE: 1075 return (gettext("Malformed SPI range")); 1076 case SADB_X_DIAGNOSTIC_AKEY_PRESENT: 1077 return (gettext("Authentication key not needed")); 1078 case SADB_X_DIAGNOSTIC_EKEY_PRESENT: 1079 return (gettext("Encryption key not needed")); 1080 case SADB_X_DIAGNOSTIC_PROP_PRESENT: 1081 return (gettext("Proposal extension not needed")); 1082 case SADB_X_DIAGNOSTIC_SUPP_PRESENT: 1083 return (gettext("Supported algorithms extension not needed")); 1084 case SADB_X_DIAGNOSTIC_BAD_AALG: 1085 return (gettext("Unsupported authentication algorithm")); 1086 case SADB_X_DIAGNOSTIC_BAD_EALG: 1087 return (gettext("Unsupported encryption algorithm")); 1088 case SADB_X_DIAGNOSTIC_BAD_SAFLAGS: 1089 return (gettext("Invalid SA flags")); 1090 case SADB_X_DIAGNOSTIC_BAD_SASTATE: 1091 return (gettext("Invalid SA state")); 1092 case SADB_X_DIAGNOSTIC_BAD_AKEYBITS: 1093 return (gettext("Bad number of authentication bits")); 1094 case SADB_X_DIAGNOSTIC_BAD_EKEYBITS: 1095 return (gettext("Bad number of encryption bits")); 1096 case SADB_X_DIAGNOSTIC_ENCR_NOTSUPP: 1097 return (gettext("Encryption not supported for this SA type")); 1098 case SADB_X_DIAGNOSTIC_WEAK_EKEY: 1099 return (gettext("Weak encryption key")); 1100 case SADB_X_DIAGNOSTIC_WEAK_AKEY: 1101 return (gettext("Weak authentication key")); 1102 case SADB_X_DIAGNOSTIC_DUPLICATE_KMP: 1103 return (gettext("Duplicate key management protocol")); 1104 case SADB_X_DIAGNOSTIC_DUPLICATE_KMC: 1105 return (gettext("Duplicate key management cookie")); 1106 case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC: 1107 return (gettext("Missing NATT local address")); 1108 case SADB_X_DIAGNOSTIC_MISSING_NATT_REM: 1109 return (gettext("Missing NATT remote address")); 1110 case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC: 1111 return (gettext("Duplicate NATT local address")); 1112 case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM: 1113 return (gettext("Duplicate NATT remote address")); 1114 case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC: 1115 return (gettext("Malformed NATT local address")); 1116 case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM: 1117 return (gettext("Malformed NATT remote address")); 1118 case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS: 1119 return (gettext("Duplicate NATT ports")); 1120 default: 1121 return (gettext("Unknown diagnostic code")); 1122 } 1123 } 1124