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 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * NOTE:I'm trying to use "struct sadb_foo" instead of "sadb_foo_t" 28 * as a maximal PF_KEY portability test. 29 * 30 * Also, this is a deliberately single-threaded app, also for portability 31 * to systems without POSIX threads. 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" 35 36 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <sys/socket.h> 40 #include <sys/sysmacros.h> 41 #include <sys/fcntl.h> 42 #include <net/pfkeyv2.h> 43 #include <arpa/inet.h> 44 #include <netinet/in.h> 45 #include <sys/uio.h> 46 47 #include <syslog.h> 48 #include <signal.h> 49 #include <unistd.h> 50 #include <limits.h> 51 #include <stdlib.h> 52 #include <stdio.h> 53 #include <stdarg.h> 54 #include <netdb.h> 55 #include <pwd.h> 56 #include <errno.h> 57 #include <libintl.h> 58 #include <locale.h> 59 #include <fcntl.h> 60 #include <strings.h> 61 #include <ctype.h> 62 63 #include <ipsec_util.h> 64 65 static int keysock; 66 static uint32_t seq; 67 static pid_t mypid; 68 static boolean_t vflag = B_FALSE; /* Verbose? */ 69 static boolean_t cflag = B_FALSE; /* Check Only */ 70 71 char *my_fmri = NULL; 72 FILE *debugfile = stdout; 73 74 #define MAX_GET_SIZE 1024 75 /* 76 * WARN() and ERROR() do the same thing really, with ERROR() the function 77 * that prints the error buffer needs to be called at the end of a code block 78 * This will print out all accumulated errors before bailing. The WARN() 79 * macro calls handle_errors() in such a way that it prints the message 80 * then continues. 81 * If the FATAL() macro used call handle_errors() immediately. 82 */ 83 #define ERROR(x, y, z) x = record_error(x, y, z) 84 #define ERROR1(w, x, y, z) w = record_error(w, x, y, z) 85 #define ERROR2(v, w, x, y, z) v = record_error(v, w, x, y, z) 86 #define WARN(x, y, z) ERROR(x, y, z);\ 87 handle_errors(x, NULL, B_FALSE, B_FALSE); x = NULL 88 #define WARN1(w, x, y, z) ERROR1(w, x, y, z);\ 89 handle_errors(w, NULL, B_FALSE, B_FALSE); w = NULL 90 #define WARN2(v, w, x, y, z) ERROR2(v, w, x, y, z);\ 91 handle_errors(v, NULL, B_FALSE, B_FALSE); v = NULL 92 #define FATAL(x, y, z) ERROR(x, y, z);\ 93 handle_errors(x, y, B_TRUE, B_TRUE) 94 #define FATAL1(w, x, y, z) ERROR1(w, x, y, z);\ 95 handle_errors(w, x, B_TRUE, B_TRUE) 96 97 /* Defined as a uint64_t array for alignment purposes. */ 98 static uint64_t get_buffer[MAX_GET_SIZE]; 99 100 /* 101 * Create/Grow a buffer large enough to hold error messages. If *ebuf 102 * is not NULL then it will contain a copy of the command line that 103 * triggered the error/warning, copy this into a new buffer or 104 * append new messages to the existing buffer. 105 */ 106 /*PRINTFLIKE1*/ 107 char * 108 record_error(char *ep, char *ebuf, char *fmt, ...) 109 { 110 char *err_ptr; 111 char tmp_buff[1024]; 112 va_list ap; 113 int length = 0; 114 err_ptr = ep; 115 116 va_start(ap, fmt); 117 length = vsnprintf(tmp_buff, sizeof (tmp_buff), fmt, ap); 118 va_end(ap); 119 120 /* There is a new line character */ 121 length++; 122 123 if (ep == NULL) { 124 if (ebuf != NULL) 125 length += strlen(ebuf); 126 } else { 127 length += strlen(ep); 128 } 129 130 if (err_ptr == NULL) 131 err_ptr = calloc(length, sizeof (char)); 132 else 133 err_ptr = realloc(err_ptr, length); 134 135 if (err_ptr == NULL) 136 Bail("realloc() failure"); 137 138 /* 139 * If (ep == NULL) then this is the first error to record, 140 * copy in the command line that triggered this error/warning. 141 */ 142 if (ep == NULL && ebuf != NULL) 143 (void) strlcpy(err_ptr, ebuf, length); 144 145 /* 146 * Now the actual error. 147 */ 148 (void) strlcat(err_ptr, tmp_buff, length); 149 return (err_ptr); 150 } 151 152 /* 153 * Print usage message. 154 */ 155 static void 156 usage(void) 157 { 158 if (!interactive) { 159 (void) fprintf(stderr, gettext("Usage:\t" 160 "ipseckey [ -nvp ] | cmd [sa_type] [extfield value]*\n")); 161 (void) fprintf(stderr, 162 gettext("\tipseckey [ -nvp ] -f infile\n")); 163 (void) fprintf(stderr, 164 gettext("\tipseckey [ -nvp ] -s outfile\n")); 165 } 166 EXIT_FATAL(NULL); 167 } 168 169 170 /* 171 * Print out any errors, tidy up as required. 172 * error pointer ep will be free()'d 173 */ 174 void 175 handle_errors(char *ep, char *ebuf, boolean_t fatal, boolean_t done) 176 { 177 if (ep != NULL) { 178 if (my_fmri == NULL) { 179 /* 180 * For now suppress the errors when run from smf(5) 181 * because potentially sensitive information could 182 * end up in a publicly readable logfile. 183 */ 184 (void) fprintf(stdout, "%s\n", ep); 185 (void) fflush(stdout); 186 } 187 free(ep); 188 if (fatal) { 189 if (ebuf != NULL) { 190 free(ebuf); 191 } 192 /* reset command buffer */ 193 if (interactive) 194 longjmp(env, 1); 195 } else { 196 return; 197 } 198 } else { 199 /* 200 * No errors, if this is the last time that this function 201 * is called, free(ebuf) and reset command buffer. 202 */ 203 if (done) { 204 if (ebuf != NULL) { 205 free(ebuf); 206 } 207 /* reset command buffer */ 208 if (interactive) 209 longjmp(env, 1); 210 } 211 return; 212 } 213 EXIT_FATAL(NULL); 214 } 215 216 /* 217 * Initialize a PF_KEY base message. 218 */ 219 static void 220 msg_init(struct sadb_msg *msg, uint8_t type, uint8_t satype) 221 { 222 msg->sadb_msg_version = PF_KEY_V2; 223 msg->sadb_msg_type = type; 224 msg->sadb_msg_errno = 0; 225 msg->sadb_msg_satype = satype; 226 /* For starters... */ 227 msg->sadb_msg_len = SADB_8TO64(sizeof (*msg)); 228 msg->sadb_msg_reserved = 0; 229 msg->sadb_msg_seq = ++seq; 230 msg->sadb_msg_pid = mypid; 231 } 232 233 /* 234 * parseXXX and rparseXXX commands parse input and convert them to PF_KEY 235 * field values, or do the reverse for the purposes of saving the SA tables. 236 * (See the save_XXX functions.) 237 */ 238 239 #define CMD_NONE 0 240 #define CMD_UPDATE 2 241 #define CMD_ADD 3 242 #define CMD_DELETE 4 243 #define CMD_GET 5 244 #define CMD_FLUSH 9 245 #define CMD_DUMP 10 246 #define CMD_MONITOR 11 247 #define CMD_PMONITOR 12 248 #define CMD_QUIT 13 249 #define CMD_SAVE 14 250 #define CMD_HELP 15 251 252 /* 253 * Parse the command. 254 */ 255 static int 256 parsecmd(char *cmdstr) 257 { 258 static struct cmdtable { 259 char *cmd; 260 int token; 261 } table[] = { 262 /* 263 * Q: Do we want to do GETSPI? 264 * A: No, it's for automated key mgmt. only. Either that, 265 * or it isn't relevant until we support non IPsec SA types. 266 */ 267 {"update", CMD_UPDATE}, 268 {"add", CMD_ADD}, 269 {"delete", CMD_DELETE}, 270 {"get", CMD_GET}, 271 /* 272 * Q: And ACQUIRE and REGISTER and EXPIRE? 273 * A: not until we support non IPsec SA types. 274 */ 275 {"flush", CMD_FLUSH}, 276 {"dump", CMD_DUMP}, 277 {"monitor", CMD_MONITOR}, 278 {"passive_monitor", CMD_PMONITOR}, 279 {"pmonitor", CMD_PMONITOR}, 280 {"quit", CMD_QUIT}, 281 {"exit", CMD_QUIT}, 282 {"save", CMD_SAVE}, 283 {"help", CMD_HELP}, 284 {"?", CMD_HELP}, 285 {NULL, CMD_NONE} 286 }; 287 struct cmdtable *ct = table; 288 289 while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0) 290 ct++; 291 return (ct->token); 292 } 293 294 /* 295 * Convert a number from a command line. I picked "u_longlong_t" for the 296 * number because we need the largest number available. Also, the strto<num> 297 * calls don't deal in units of uintNN_t. 298 */ 299 static u_longlong_t 300 parsenum(char *num, boolean_t bail, char *ebuf) 301 { 302 u_longlong_t rc = 0; 303 char *end = NULL; 304 char *ep = NULL; 305 306 if (num == NULL) { 307 FATAL(ep, ebuf, gettext("Unexpected end of command line," 308 " was expecting a number.\n")); 309 /* NOTREACHED */ 310 } 311 312 errno = 0; 313 rc = strtoull(num, &end, 0); 314 if (errno != 0 || end == num || *end != '\0') { 315 if (bail) { 316 ERROR1(ep, ebuf, gettext( 317 "Expecting a number, not \"%s\"!\n"), num); 318 } else { 319 /* 320 * -1, while not optimal, is sufficiently out of range 321 * for most of this function's applications when 322 * we don't just bail. 323 */ 324 return ((u_longlong_t)-1); 325 } 326 } 327 handle_errors(ep, NULL, B_FALSE, B_FALSE); 328 return (rc); 329 } 330 331 /* 332 * Parse and reverse parse a specific SA type (AH, ESP, etc.). 333 */ 334 static struct typetable { 335 char *type; 336 int token; 337 } type_table[] = { 338 {"all", SADB_SATYPE_UNSPEC}, 339 {"ah", SADB_SATYPE_AH}, 340 {"esp", SADB_SATYPE_ESP}, 341 /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */ 342 {NULL, 0} /* Token value is irrelevant for this entry. */ 343 }; 344 345 346 static int 347 parsesatype(char *type, char *ebuf) 348 { 349 struct typetable *tt = type_table; 350 char *ep = NULL; 351 352 if (type == NULL) 353 return (SADB_SATYPE_UNSPEC); 354 355 while (tt->type != NULL && strcasecmp(tt->type, type) != 0) 356 tt++; 357 358 /* 359 * New SA types (including ones keysock maintains for user-land 360 * protocols) may be added, so parse a numeric value if possible. 361 */ 362 if (tt->type == NULL) { 363 tt->token = (int)parsenum(type, B_FALSE, ebuf); 364 if (tt->token == -1) { 365 ERROR1(ep, ebuf, gettext( 366 "Unknown SA type (%s).\n"), type); 367 tt->token = SADB_SATYPE_UNSPEC; 368 } 369 } 370 handle_errors(ep, NULL, B_FALSE, B_FALSE); 371 return (tt->token); 372 } 373 374 #define NEXTEOF 0 375 #define NEXTNONE 1 376 #define NEXTNUM 2 377 #define NEXTSTR 3 378 #define NEXTNUMSTR 4 379 #define NEXTADDR 5 380 #define NEXTHEX 6 381 #define NEXTIDENT 7 382 #define NEXTADDR4 8 383 #define NEXTADDR6 9 384 385 #define TOK_EOF 0 386 #define TOK_UNKNOWN 1 387 #define TOK_SPI 2 388 #define TOK_REPLAY 3 389 #define TOK_STATE 4 390 #define TOK_AUTHALG 5 391 #define TOK_ENCRALG 6 392 #define TOK_FLAGS 7 393 #define TOK_SOFT_ALLOC 8 394 #define TOK_SOFT_BYTES 9 395 #define TOK_SOFT_ADDTIME 10 396 #define TOK_SOFT_USETIME 11 397 #define TOK_HARD_ALLOC 12 398 #define TOK_HARD_BYTES 13 399 #define TOK_HARD_ADDTIME 14 400 #define TOK_HARD_USETIME 15 401 #define TOK_CURRENT_ALLOC 16 402 #define TOK_CURRENT_BYTES 17 403 #define TOK_CURRENT_ADDTIME 18 404 #define TOK_CURRENT_USETIME 19 405 #define TOK_SRCADDR 20 406 #define TOK_DSTADDR 21 407 #define TOK_PROXYADDR 22 408 #define TOK_AUTHKEY 23 409 #define TOK_ENCRKEY 24 410 #define TOK_SRCIDTYPE 25 411 #define TOK_DSTIDTYPE 26 412 #define TOK_DPD 27 413 #define TOK_SENS_LEVEL 28 414 #define TOK_SENS_MAP 29 415 #define TOK_INTEG_LEVEL 30 416 #define TOK_INTEG_MAP 31 417 #define TOK_SRCADDR6 32 418 #define TOK_DSTADDR6 33 419 #define TOK_PROXYADDR6 34 420 #define TOK_SRCPORT 35 421 #define TOK_DSTPORT 36 422 #define TOK_PROTO 37 423 #define TOK_ENCAP 38 424 #define TOK_NATLOC 39 425 #define TOK_NATREM 40 426 #define TOK_NATLPORT 41 427 #define TOK_NATRPORT 42 428 #define TOK_IPROTO 43 429 #define TOK_IDSTADDR 44 430 #define TOK_IDSTADDR6 45 431 #define TOK_ISRCPORT 46 432 #define TOK_IDSTPORT 47 433 434 static struct toktable { 435 char *string; 436 int token; 437 int next; 438 } tokens[] = { 439 /* "String", token value, next arg is */ 440 {"spi", TOK_SPI, NEXTNUM}, 441 {"replay", TOK_REPLAY, NEXTNUM}, 442 {"state", TOK_STATE, NEXTNUMSTR}, 443 {"auth_alg", TOK_AUTHALG, NEXTNUMSTR}, 444 {"authalg", TOK_AUTHALG, NEXTNUMSTR}, 445 {"encr_alg", TOK_ENCRALG, NEXTNUMSTR}, 446 {"encralg", TOK_ENCRALG, NEXTNUMSTR}, 447 {"flags", TOK_FLAGS, NEXTNUM}, 448 {"soft_alloc", TOK_SOFT_ALLOC, NEXTNUM}, 449 {"soft_bytes", TOK_SOFT_BYTES, NEXTNUM}, 450 {"soft_addtime", TOK_SOFT_ADDTIME, NEXTNUM}, 451 {"soft_usetime", TOK_SOFT_USETIME, NEXTNUM}, 452 {"hard_alloc", TOK_HARD_ALLOC, NEXTNUM}, 453 {"hard_bytes", TOK_HARD_BYTES, NEXTNUM}, 454 {"hard_addtime", TOK_HARD_ADDTIME, NEXTNUM}, 455 {"hard_usetime", TOK_HARD_USETIME, NEXTNUM}, 456 {"current_alloc", TOK_CURRENT_ALLOC, NEXTNUM}, 457 {"current_bytes", TOK_CURRENT_BYTES, NEXTNUM}, 458 {"current_addtime", TOK_CURRENT_ADDTIME, NEXTNUM}, 459 {"current_usetime", TOK_CURRENT_USETIME, NEXTNUM}, 460 461 {"saddr", TOK_SRCADDR, NEXTADDR}, 462 {"srcaddr", TOK_SRCADDR, NEXTADDR}, 463 {"src", TOK_SRCADDR, NEXTADDR}, 464 {"daddr", TOK_DSTADDR, NEXTADDR}, 465 {"dstaddr", TOK_DSTADDR, NEXTADDR}, 466 {"dst", TOK_DSTADDR, NEXTADDR}, 467 {"proxyaddr", TOK_PROXYADDR, NEXTADDR}, 468 {"proxy", TOK_PROXYADDR, NEXTADDR}, 469 {"innersrc", TOK_PROXYADDR, NEXTADDR}, 470 {"isrc", TOK_PROXYADDR, NEXTADDR}, 471 {"innerdst", TOK_IDSTADDR, NEXTADDR}, 472 {"idst", TOK_IDSTADDR, NEXTADDR}, 473 474 {"sport", TOK_SRCPORT, NEXTNUM}, 475 {"dport", TOK_DSTPORT, NEXTNUM}, 476 {"innersport", TOK_ISRCPORT, NEXTNUM}, 477 {"isport", TOK_ISRCPORT, NEXTNUM}, 478 {"innerdport", TOK_IDSTPORT, NEXTNUM}, 479 {"idport", TOK_IDSTPORT, NEXTNUM}, 480 {"proto", TOK_PROTO, NEXTNUM}, 481 {"ulp", TOK_PROTO, NEXTNUM}, 482 {"iproto", TOK_IPROTO, NEXTNUM}, 483 {"iulp", TOK_IPROTO, NEXTNUM}, 484 485 {"saddr6", TOK_SRCADDR6, NEXTADDR}, 486 {"srcaddr6", TOK_SRCADDR6, NEXTADDR}, 487 {"src6", TOK_SRCADDR6, NEXTADDR}, 488 {"daddr6", TOK_DSTADDR6, NEXTADDR}, 489 {"dstaddr6", TOK_DSTADDR6, NEXTADDR}, 490 {"dst6", TOK_DSTADDR6, NEXTADDR}, 491 {"proxyaddr6", TOK_PROXYADDR6, NEXTADDR}, 492 {"proxy6", TOK_PROXYADDR6, NEXTADDR}, 493 {"innersrc6", TOK_PROXYADDR6, NEXTADDR}, 494 {"isrc6", TOK_PROXYADDR6, NEXTADDR}, 495 {"innerdst6", TOK_IDSTADDR6, NEXTADDR}, 496 {"idst6", TOK_IDSTADDR6, NEXTADDR}, 497 498 {"authkey", TOK_AUTHKEY, NEXTHEX}, 499 {"encrkey", TOK_ENCRKEY, NEXTHEX}, 500 {"srcidtype", TOK_SRCIDTYPE, NEXTIDENT}, 501 {"dstidtype", TOK_DSTIDTYPE, NEXTIDENT}, 502 {"dpd", TOK_DPD, NEXTNUM}, 503 {"sens_level", TOK_SENS_LEVEL, NEXTNUM}, 504 {"sens_map", TOK_SENS_MAP, NEXTHEX}, 505 {"integ_level", TOK_INTEG_LEVEL, NEXTNUM}, 506 {"integ_map", TOK_INTEG_MAP, NEXTHEX}, 507 {"nat_loc", TOK_NATLOC, NEXTADDR}, 508 {"nat_rem", TOK_NATREM, NEXTADDR}, 509 {"nat_lport", TOK_NATLPORT, NEXTNUM}, 510 {"nat_rport", TOK_NATRPORT, NEXTNUM}, 511 {"encap", TOK_ENCAP, NEXTNUMSTR}, 512 {NULL, TOK_UNKNOWN, NEXTEOF} 513 }; 514 515 /* 516 * Q: Do I need stuff for proposals, combinations, supported algorithms, 517 * or SPI ranges? 518 * 519 * A: Probably not, but you never know. 520 * 521 * Parse out extension header type values. 522 */ 523 static int 524 parseextval(char *value, int *next) 525 { 526 struct toktable *tp; 527 528 if (value == NULL) 529 return (TOK_EOF); 530 531 for (tp = tokens; tp->string != NULL; tp++) 532 if (strcmp(value, tp->string) == 0) 533 break; 534 535 /* 536 * Since the OS controls what extensions are available, we don't have 537 * to parse numeric values here. 538 */ 539 540 *next = tp->next; 541 return (tp->token); 542 } 543 544 /* 545 * Parse possible state values. 546 */ 547 static uint8_t 548 parsestate(char *state, char *ebuf) 549 { 550 struct states { 551 char *state; 552 uint8_t retval; 553 } states[] = { 554 {"larval", SADB_SASTATE_LARVAL}, 555 {"mature", SADB_SASTATE_MATURE}, 556 {"dying", SADB_SASTATE_DYING}, 557 {"dead", SADB_SASTATE_DEAD}, 558 {NULL, 0} 559 }; 560 struct states *sp; 561 char *ep = NULL; 562 563 if (state == NULL) { 564 FATAL(ep, ebuf, "Unexpected end of command line " 565 "was expecting a state.\n"); 566 } 567 568 for (sp = states; sp->state != NULL; sp++) { 569 if (strcmp(sp->state, state) == 0) 570 return (sp->retval); 571 } 572 ERROR1(ep, ebuf, gettext("Unknown state type \"%s\"\n"), state); 573 handle_errors(ep, NULL, B_FALSE, B_FALSE); 574 return (0); 575 } 576 577 /* 578 * Return the numerical algorithm identifier corresponding to the specified 579 * algorithm name. 580 */ 581 static uint8_t 582 parsealg(char *alg, int proto_num, char *ebuf) 583 { 584 u_longlong_t invalue; 585 struct ipsecalgent *algent; 586 char *ep = NULL; 587 588 if (alg == NULL) { 589 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 590 "was expecting an algorithm name.\n")); 591 } 592 593 algent = getipsecalgbyname(alg, proto_num, NULL); 594 if (algent != NULL) { 595 uint8_t alg_num; 596 597 alg_num = algent->a_alg_num; 598 freeipsecalgent(algent); 599 600 return (alg_num); 601 } 602 603 /* 604 * Since algorithms can be loaded during kernel run-time, check for 605 * numeric algorithm values too. PF_KEY can catch bad ones with EINVAL. 606 */ 607 invalue = parsenum(alg, B_FALSE, ebuf); 608 if (invalue != (u_longlong_t)-1 && 609 (u_longlong_t)(invalue & (u_longlong_t)0xff) == invalue) 610 return ((uint8_t)invalue); 611 612 if (proto_num == IPSEC_PROTO_ESP) { 613 ERROR1(ep, ebuf, gettext( 614 "Unknown encryption algorithm type \"%s\"\n"), alg); 615 } else { 616 ERROR1(ep, ebuf, gettext( 617 "Unknown authentication algorithm type \"%s\"\n"), alg); 618 } 619 handle_errors(ep, NULL, B_FALSE, B_FALSE); 620 return (0); 621 } 622 623 /* 624 * Parse and reverse parse out a source/destination ID type. 625 */ 626 static struct idtypes { 627 char *idtype; 628 uint8_t retval; 629 } idtypes[] = { 630 {"prefix", SADB_IDENTTYPE_PREFIX}, 631 {"fqdn", SADB_IDENTTYPE_FQDN}, 632 {"domain", SADB_IDENTTYPE_FQDN}, 633 {"domainname", SADB_IDENTTYPE_FQDN}, 634 {"user_fqdn", SADB_IDENTTYPE_USER_FQDN}, 635 {"mailbox", SADB_IDENTTYPE_USER_FQDN}, 636 {"der_dn", SADB_X_IDENTTYPE_DN}, 637 {"der_gn", SADB_X_IDENTTYPE_GN}, 638 {NULL, 0} 639 }; 640 641 static uint16_t 642 parseidtype(char *type, char *ebuf) 643 { 644 struct idtypes *idp; 645 u_longlong_t invalue; 646 char *ep = NULL; 647 648 if (type == NULL) { 649 /* Shouldn't reach here, see callers for why. */ 650 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 651 "was expecting a type.\n")); 652 } 653 654 for (idp = idtypes; idp->idtype != NULL; idp++) { 655 if (strcasecmp(idp->idtype, type) == 0) 656 return (idp->retval); 657 } 658 /* 659 * Since identity types are almost arbitrary, check for numeric 660 * algorithm values too. PF_KEY can catch bad ones with EINVAL. 661 */ 662 invalue = parsenum(type, B_FALSE, ebuf); 663 if (invalue != (u_longlong_t)-1 && 664 (u_longlong_t)(invalue & (u_longlong_t)0xffff) == invalue) 665 return ((uint16_t)invalue); 666 667 668 ERROR1(ep, ebuf, gettext("Unknown identity type \"%s\"\n"), type); 669 670 handle_errors(ep, NULL, B_FALSE, B_FALSE); 671 return (0); 672 } 673 674 /* 675 * Parse an address off the command line. Return length of sockaddr, 676 * and either return a hostent pointer (caller frees). The new 677 * getipnodebyname() call does the Right Thing (TM), even with 678 * raw addresses (colon-separated IPv6 or dotted decimal IPv4). 679 */ 680 681 static struct { 682 struct hostent he; 683 char *addtl[2]; 684 } dummy; 685 static union { 686 struct in6_addr ipv6; 687 struct in_addr ipv4; 688 uint64_t aligner; 689 } addr1; 690 691 static int 692 parseaddr(char *addr, struct hostent **hpp, boolean_t v6only, char *ebuf) 693 { 694 int hp_errno; 695 struct hostent *hp = NULL; 696 char *ep = NULL; 697 698 if (addr == NULL) { 699 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 700 "was expecting an address.\n")); 701 } 702 703 if (!nflag) { 704 /* 705 * Try name->address first. Assume AF_INET6, and 706 * get IPv4's, plus IPv6's if and only if IPv6 is configured. 707 * This means to add IPv6 SAs, you must have IPv6 708 * up-and-running. (AI_DEFAULT works here.) 709 */ 710 hp = getipnodebyname(addr, AF_INET6, 711 (v6only ? AI_ADDRCONFIG : (AI_DEFAULT | AI_ALL)), 712 &hp_errno); 713 } else { 714 /* 715 * Try a normal address conversion only. Use "dummy" 716 * to construct a fake hostent. Caller will know not 717 * to free this one. 718 */ 719 if (inet_pton(AF_INET6, addr, &addr1) == 1) { 720 dummy.he.h_addr_list = dummy.addtl; 721 dummy.addtl[0] = (char *)&addr1; 722 dummy.addtl[1] = NULL; 723 hp = &dummy.he; 724 dummy.he.h_addrtype = AF_INET6; 725 dummy.he.h_length = sizeof (struct in6_addr); 726 } else if (inet_pton(AF_INET, addr, &addr1) == 1) { 727 /* 728 * Remap to AF_INET6 anyway. 729 */ 730 dummy.he.h_addr_list = dummy.addtl; 731 dummy.addtl[0] = (char *)&addr1; 732 dummy.addtl[1] = NULL; 733 hp = &dummy.he; 734 dummy.he.h_addrtype = AF_INET6; 735 dummy.he.h_length = sizeof (struct in6_addr); 736 /* 737 * NOTE: If macro changes to disallow in-place 738 * conversion, rewhack this. 739 */ 740 IN6_INADDR_TO_V4MAPPED(&addr1.ipv4, &addr1.ipv6); 741 } else { 742 hp = NULL; 743 } 744 } 745 746 if (hp == NULL) 747 WARN1(ep, ebuf, gettext("Unknown address %s."), addr); 748 749 *hpp = hp; 750 /* Always return sockaddr_in6 for now. */ 751 handle_errors(ep, NULL, B_FALSE, B_FALSE); 752 return (sizeof (struct sockaddr_in6)); 753 } 754 755 /* 756 * Parse a hex character for a key. A string will take the form: 757 * xxxxxxxxx/nn 758 * where 759 * xxxxxxxxx == a string of hex characters ([0-9][a-f][A-F]) 760 * nn == an optional decimal "mask". If it is not present, it 761 * is assumed that the hex string will be rounded to the nearest 762 * byte, where odd nibbles, like 123 will become 0x0123. 763 * 764 * NOTE:Unlike the expression of IP addresses, I will not allow an 765 * excessive "mask". For example 2112/50 is very illegal. 766 * NOTE2: This key should be in canonical order. Consult your man 767 * pages per algorithm about said order. 768 */ 769 770 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \ 771 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10))) 772 773 static struct sadb_key * 774 parsekey(char *input, char *ebuf) 775 { 776 struct sadb_key *retval; 777 uint_t i, hexlen = 0, bits, alloclen; 778 uint8_t *key; 779 char *ep = NULL; 780 781 if (input == NULL) { 782 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 783 "was expecting a key.\n")); 784 } 785 /* Allow hex values prepended with 0x convention */ 786 if ((strnlen(input, sizeof (hexlen)) > 2) && 787 (strncasecmp(input, "0x", 2) == 0)) 788 input += 2; 789 790 for (i = 0; input[i] != '\0' && input[i] != '/'; i++) 791 hexlen++; 792 793 if (input[i] == '\0') { 794 bits = 0; 795 } else { 796 /* Have /nn. */ 797 input[i] = '\0'; 798 if (sscanf((input + i + 1), "%u", &bits) != 1) { 799 FATAL1(ep, ebuf, gettext( 800 "\"%s\" is not a bit specifier.\n"), 801 (input + i + 1)); 802 } 803 /* hexlen in nibbles */ 804 if (((bits + 3) >> 2) > hexlen) { 805 ERROR2(ep, ebuf, gettext( 806 "bit length %d is too big for %s.\n"), bits, input); 807 } 808 /* 809 * Adjust hexlen down if user gave us too small of a bit 810 * count. 811 */ 812 if ((hexlen << 2) > bits + 3) { 813 WARN2(ep, ebuf, gettext( 814 "WARNING: Lower bits will be truncated " 815 "for:\n\t%s/%d.\n"), input, bits); 816 hexlen = (bits + 3) >> 2; 817 input[hexlen] = '\0'; 818 } 819 } 820 821 /* 822 * Allocate. Remember, hexlen is in nibbles. 823 */ 824 825 alloclen = sizeof (*retval) + roundup((hexlen/2 + (hexlen & 0x1)), 8); 826 retval = malloc(alloclen); 827 828 if (retval == NULL) 829 Bail("malloc(parsekey)"); 830 retval->sadb_key_len = SADB_8TO64(alloclen); 831 retval->sadb_key_reserved = 0; 832 if (bits == 0) 833 retval->sadb_key_bits = (hexlen + (hexlen & 0x1)) << 2; 834 else 835 retval->sadb_key_bits = bits; 836 837 /* 838 * Read in nibbles. Read in odd-numbered as shifted high. 839 * (e.g. 123 becomes 0x1230). 840 */ 841 842 key = (uint8_t *)(retval + 1); 843 for (i = 0; input[i] != '\0'; i += 2) { 844 boolean_t second = (input[i + 1] != '\0'); 845 846 if (!isxdigit(input[i]) || 847 (!isxdigit(input[i + 1]) && second)) { 848 ERROR1(ep, ebuf, gettext( 849 "string '%s' not a hex value.\n"), input); 850 free(retval); 851 retval = NULL; 852 break; 853 } 854 *key = (hd2num(input[i]) << 4); 855 if (second) 856 *key |= hd2num(input[i + 1]); 857 else 858 break; /* out of for loop. */ 859 key++; 860 } 861 862 /* bzero the remaining bits if we're a non-octet amount. */ 863 if (bits & 0x7) 864 *((input[i] == '\0') ? key - 1 : key) &= 865 0xff << (8 - (bits & 0x7)); 866 867 handle_errors(ep, NULL, B_FALSE, B_FALSE); 868 return (retval); 869 } 870 871 /* 872 * Write a message to the PF_KEY socket. If verbose, print the message 873 * heading into the kernel. 874 */ 875 static int 876 key_write(int fd, void *msg, size_t len) 877 { 878 if (vflag) { 879 (void) printf( 880 gettext("VERBOSE ON: Message to kernel looks like:\n")); 881 (void) printf("==========================================\n"); 882 print_samsg(stdout, msg, B_FALSE, vflag, nflag); 883 (void) printf("==========================================\n"); 884 } 885 886 return (write(fd, msg, len)); 887 } 888 889 /* 890 * SIGALRM handler for time_critical_enter. 891 */ 892 static void 893 time_critical_catch(int signal) 894 { 895 if (signal == SIGALRM) { 896 errx(1, gettext("Reply message from PF_KEY timed out.")); 897 } else { 898 errx(1, gettext("Caught signal %d while trying to receive" 899 "PF_KEY reply message"), signal); 900 } 901 /* errx() calls exit. */ 902 } 903 904 #define TIME_CRITICAL_TIME 10 /* In seconds */ 905 906 /* 907 * Enter a "time critical" section where key is waiting for a return message. 908 */ 909 static void 910 time_critical_enter(void) 911 { 912 (void) signal(SIGALRM, time_critical_catch); 913 (void) alarm(TIME_CRITICAL_TIME); 914 } 915 916 /* 917 * Exit the "time critical" section after getting an appropriate return 918 * message. 919 */ 920 static void 921 time_critical_exit(void) 922 { 923 (void) alarm(0); 924 (void) signal(SIGALRM, SIG_DFL); 925 } 926 927 /* 928 * Construct a PF_KEY FLUSH message for the SA type specified. 929 */ 930 static void 931 doflush(int satype) 932 { 933 struct sadb_msg msg; 934 int rc; 935 936 msg_init(&msg, SADB_FLUSH, (uint8_t)satype); 937 rc = key_write(keysock, &msg, sizeof (msg)); 938 if (rc == -1) 939 Bail("write() to PF_KEY socket failed (in doflush)"); 940 941 time_critical_enter(); 942 do { 943 rc = read(keysock, &msg, sizeof (msg)); 944 if (rc == -1) 945 Bail("read (in doflush)"); 946 } while (msg.sadb_msg_seq != seq || msg.sadb_msg_pid != mypid); 947 time_critical_exit(); 948 949 /* 950 * I should _never_ hit the following unless: 951 * 952 * 1. There is a kernel bug. 953 * 2. There is another process filling in its pid with mine, and 954 * issuing a different message that would cause a different result. 955 */ 956 if (msg.sadb_msg_type != SADB_FLUSH || 957 msg.sadb_msg_satype != (uint8_t)satype) { 958 syslog((LOG_NOTICE|LOG_AUTH), 959 gettext("doflush: Return message not of type SADB_FLUSH!")); 960 Bail("doflush: Return message not of type SADB_FLUSH!"); 961 } 962 963 if (msg.sadb_msg_errno != 0) { 964 errno = msg.sadb_msg_errno; 965 if (errno == EINVAL) { 966 print_diagnostic(stderr, msg.sadb_x_msg_diagnostic); 967 warnx(gettext("Cannot flush SA type %d."), satype); 968 } 969 Bail("return message (in doflush)"); 970 } 971 } 972 973 /* 974 * save_XXX functions are used when "saving" the SA tables to either a 975 * file or standard output. They use the dump_XXX functions where needed, 976 * but mostly they use the rparseXXX functions. 977 */ 978 979 /* 980 * Because "save" and "dump" both use the SADB_DUMP message, fold both 981 * into the same function. 982 */ 983 static void 984 dodump(int satype, FILE *ofile) 985 { 986 struct sadb_msg *msg = (struct sadb_msg *)get_buffer; 987 int rc; 988 989 if (ofile != NULL) { 990 (void) fprintf(ofile, 991 gettext("# This key file was generated by the")); 992 (void) fprintf(ofile, 993 gettext(" ipseckey(1m) command's 'save' feature.\n\n")); 994 } 995 msg_init(msg, SADB_DUMP, (uint8_t)satype); 996 rc = key_write(keysock, msg, sizeof (*msg)); 997 if (rc == -1) 998 Bail("write to PF_KEY socket failed (in dodump)"); 999 1000 do { 1001 /* 1002 * For DUMP, do only the read as a time critical section. 1003 */ 1004 time_critical_enter(); 1005 rc = read(keysock, get_buffer, sizeof (get_buffer)); 1006 time_critical_exit(); 1007 if (rc == -1) 1008 Bail("read (in dodump)"); 1009 if (msg->sadb_msg_pid == mypid && 1010 msg->sadb_msg_type == SADB_DUMP && 1011 msg->sadb_msg_seq != 0 && 1012 msg->sadb_msg_errno == 0) { 1013 if (ofile == NULL) { 1014 print_samsg(stdout, get_buffer, B_FALSE, vflag, 1015 nflag); 1016 (void) putchar('\n'); 1017 } else { 1018 save_assoc(get_buffer, ofile); 1019 } 1020 } 1021 } while (msg->sadb_msg_pid != mypid || 1022 (msg->sadb_msg_errno == 0 && msg->sadb_msg_seq != 0)); 1023 1024 if (ofile != NULL && ofile != stdout) 1025 (void) fclose(ofile); 1026 1027 if (msg->sadb_msg_errno == 0) { 1028 if (ofile == NULL) 1029 (void) printf( 1030 gettext("Dump succeeded for SA type %d.\n"), 1031 satype); 1032 } else { 1033 print_diagnostic(stderr, msg->sadb_x_msg_diagnostic); 1034 errno = msg->sadb_msg_errno; 1035 Bail("Dump failed"); 1036 } 1037 } 1038 1039 #define SCOPE_UNSPEC 0 1040 #define SCOPE_LINKLOCAL 1 1041 #define SCOPE_SITELOCAL 2 1042 #define SCOPE_GLOBAL 3 1043 #define SCOPE_V4COMPAT 4 1044 #define SCOPE_LOOPBACK 5 /* Pedantic, yes, but necessary. */ 1045 1046 static int 1047 ipv6_addr_scope(struct in6_addr *addr) 1048 { 1049 /* Don't return anything regarding multicast for now... */ 1050 1051 if (IN6_IS_ADDR_UNSPECIFIED(addr)) 1052 return (SCOPE_UNSPEC); 1053 1054 if (IN6_IS_ADDR_LINKLOCAL(addr)) 1055 return (SCOPE_LINKLOCAL); 1056 1057 if (IN6_IS_ADDR_SITELOCAL(addr)) 1058 return (SCOPE_SITELOCAL); 1059 1060 if (IN6_IS_ADDR_V4COMPAT(addr)) 1061 return (SCOPE_V4COMPAT); 1062 1063 if (IN6_IS_ADDR_LOOPBACK(addr)) 1064 return (SCOPE_LOOPBACK); 1065 1066 /* For now, return global by default. */ 1067 return (SCOPE_GLOBAL); 1068 } 1069 1070 /* 1071 * doaddresses(): 1072 * 1073 * Used by doaddup() and dodelget() to create new SA's based on the 1074 * provided source and destination addresses hostent. 1075 * 1076 * sadb_msg_type: expected PF_KEY reply message type 1077 * sadb_msg_satype: expected PF_KEY reply satype 1078 * cmd: user command 1079 * srchp: hostent for the source address(es) 1080 * dsthp: hostent for the destination address(es) 1081 * src: points to the SADB source address extension 1082 * dst: points to the SADB destination address extension 1083 * unspec_src: indicates an unspecified source address. 1084 * buffer: pointer to the SADB buffer to use with PF_KEY 1085 * buffer_size: size of buffer 1086 * spi: spi for this message (set by caller) 1087 * srcport: source port if specified 1088 * dstport: destination port if specified 1089 * proto: IP protocol number if specified 1090 * iproto: Inner (tunnel mode) IP protocol number if specified 1091 * NATT note: we are going to assume a semi-sane world where NAT 1092 * boxen don't explode to multiple addresses. 1093 */ 1094 static void 1095 doaddresses(uint8_t sadb_msg_type, uint8_t sadb_msg_satype, int cmd, 1096 struct hostent *srchp, struct hostent *dsthp, 1097 struct sadb_address *src, struct sadb_address *dst, 1098 boolean_t unspec_src, uint64_t *buffer, int buffer_size, uint32_t spi, 1099 char *ebuf) 1100 { 1101 boolean_t single_dst; 1102 struct sockaddr_in6 *sin6; 1103 struct sadb_msg *msgp; 1104 int i, rc; 1105 char **walker; /* For the SRC and PROXY walking functions. */ 1106 char *first_match; 1107 uint64_t savebuf[MAX_GET_SIZE]; 1108 uint16_t srcport = 0, dstport = 0; 1109 char *ep = NULL; 1110 1111 /* 1112 * Okay, now we have "src", "dst", and maybe "proxy" reassigned 1113 * to point into the buffer to be written to PF_KEY, we can do 1114 * potentially several writes based on destination address. 1115 * 1116 * First, obtain port numbers from passed-in extensions. 1117 */ 1118 1119 if (src != NULL) { 1120 sin6 = (struct sockaddr_in6 *)(src + 1); 1121 srcport = ntohs(sin6->sin6_port); 1122 } 1123 if (dst != NULL) { 1124 sin6 = (struct sockaddr_in6 *)(dst + 1); 1125 dstport = ntohs(sin6->sin6_port); 1126 } 1127 1128 /* 1129 * The rules for ADD, GET, and UPDATE: (NOTE: This assumes IPsec. 1130 * If other consumers of PF_KEY happen, this will have to be 1131 * rewhacked.): 1132 * 1133 * Do a message for every possible DST address. 1134 * 1135 * If a source or proxy address explodes, keep unspecified 1136 * (and mention unspecified). 1137 * 1138 * If dsthp is == dummy.he, then go through the loop once. 1139 * If any other hp is == dummy.he, then you don't have to apply any 1140 * silly rules. 1141 * 1142 * DELETE is different, because you can leave either "src" or "dst" 1143 * blank! You need to explode if one of them is full, and not assume 1144 * that the other is set. 1145 */ 1146 1147 if (dsthp == NULL) { 1148 /* 1149 * No destination address specified. 1150 * With extended diagnostics, we don't have to bail the 1151 * non-DELETE cases here. The EINVAL diagnostics will be 1152 * enough to inform the user(s) what happened. 1153 */ 1154 i = 0; 1155 do { 1156 if (srchp == &dummy.he) { 1157 /* Just to be sure... */ 1158 srchp->h_addr_list[1] = NULL; 1159 } else if (srchp != NULL) { 1160 /* Degenerate case, h_addr_list[0] == NULL. */ 1161 if (srchp->h_addr_list[i] == NULL) 1162 Bail("Empty source address list"); 1163 1164 /* 1165 * Fill in the src sockaddr. 1166 */ 1167 sin6 = (struct sockaddr_in6 *)(src + 1); 1168 bzero(sin6, sizeof (*sin6)); 1169 bcopy(srchp->h_addr_list[i], &sin6->sin6_addr, 1170 sizeof (struct in6_addr)); 1171 sin6->sin6_family = AF_INET6; 1172 sin6->sin6_port = htons(srcport); 1173 } 1174 1175 /* Save off a copy for later writing... */ 1176 msgp = (struct sadb_msg *)buffer; 1177 bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len)); 1178 1179 rc = key_write(keysock, buffer, 1180 SADB_64TO8(msgp->sadb_msg_len)); 1181 if (rc == -1) 1182 Bail("write() to PF_KEY socket " 1183 "(in doaddresses)"); 1184 1185 time_critical_enter(); 1186 do { 1187 rc = read(keysock, buffer, buffer_size); 1188 if (rc == -1) 1189 Bail("read (in doaddresses)"); 1190 } while (msgp->sadb_msg_seq != seq || 1191 msgp->sadb_msg_pid != mypid); 1192 time_critical_exit(); 1193 1194 if (msgp->sadb_msg_type != sadb_msg_type || 1195 msgp->sadb_msg_satype != sadb_msg_satype) { 1196 syslog((LOG_NOTICE|LOG_AUTH), gettext( 1197 "doaddresses: Unexpected returned message " 1198 "(%d exp %d)\n"), msgp->sadb_msg_type, 1199 sadb_msg_type); 1200 Bail("doaddresses: Unexpected returned " 1201 "message"); 1202 } 1203 1204 errno = msgp->sadb_msg_errno; 1205 if (errno != 0) { 1206 if (errno == EINVAL) { 1207 WARN(ep, ebuf, gettext( 1208 "One of the entered " 1209 "values is incorrect.")); 1210 print_diagnostic(stderr, 1211 msgp->sadb_x_msg_diagnostic); 1212 } else { 1213 Bail("return message (in doaddresses)"); 1214 } 1215 } 1216 1217 /* ...and then restore the saved buffer. */ 1218 msgp = (struct sadb_msg *)savebuf; 1219 bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len)); 1220 } while (srchp != NULL && srchp->h_addr_list[++i] != NULL); 1221 return; 1222 } 1223 1224 single_dst = (dsthp == &dummy.he || dsthp->h_addr_list[1] == NULL); 1225 1226 for (i = 0; dsthp->h_addr_list[i] != NULL; i++) { 1227 if (dsthp == &dummy.he) { 1228 /* Just to be sure... */ 1229 dsthp->h_addr_list[1] = NULL; 1230 } else { 1231 /* 1232 * Fill in the dst sockaddr. 1233 */ 1234 sin6 = (struct sockaddr_in6 *)(dst + 1); 1235 bzero(sin6, sizeof (*sin6)); 1236 bcopy(dsthp->h_addr_list[i], &sin6->sin6_addr, 1237 sizeof (struct in6_addr)); 1238 sin6->sin6_family = AF_INET6; 1239 sin6->sin6_port = htons(dstport); 1240 } 1241 1242 /* 1243 * Try and assign src, if there's any ambiguity. 1244 */ 1245 if (!unspec_src && srchp != &dummy.he) { 1246 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1247 /* 1248 * IPv4 address. Find an IPv4 address, then 1249 * keep looking for a second one. If a second 1250 * exists, print a message, and fill in the 1251 * unspecified address. 1252 */ 1253 first_match = NULL; 1254 1255 for (walker = srchp->h_addr_list; 1256 *walker != NULL; walker++) { 1257 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1258 if (IN6_IS_ADDR_V4MAPPED( 1259 (struct in6_addr *)*walker)) { 1260 if (first_match != NULL) 1261 break; 1262 else 1263 first_match = *walker; 1264 } 1265 } 1266 sin6 = (struct sockaddr_in6 *)(src + 1); 1267 bzero(sin6, sizeof (*sin6)); 1268 1269 if (first_match == NULL) { 1270 /* 1271 * No IPv4 hits. Is this a single 1272 * dest? 1273 */ 1274 WARN1(ep, ebuf, gettext( 1275 "No IPv4 source address " 1276 "for name %s.\n"), srchp->h_name); 1277 if (single_dst) { 1278 ERROR(ep, ebuf, gettext( 1279 "Only single destination " 1280 "IP address.\n")); 1281 } else { 1282 /* Continue, but do I print? */ 1283 continue; /* for loop */ 1284 } 1285 1286 /* I should never reach here. */ 1287 } 1288 1289 sin6->sin6_family = AF_INET6; 1290 sin6->sin6_port = htons(srcport); 1291 if (*walker != NULL) { 1292 /* 1293 * Early loop exit. It must've been 1294 * multiple hits... 1295 * 1296 * Issue a null-source warning? 1297 */ 1298 WARN1(ep, ebuf, gettext( 1299 "Multiple IPv4 source addresses " 1300 "for %s, using unspecified source " 1301 "instead."), srchp->h_name); 1302 } else { 1303 /* 1304 * If I reach here w/o hitting the 1305 * previous if statements, I have a 1306 * single source address for this 1307 * destination. 1308 */ 1309 bcopy(first_match, &sin6->sin6_addr, 1310 sizeof (struct in6_addr)); 1311 } 1312 } else { 1313 /* 1314 * IPv6 address. Find an IPv6 address. 1315 * Unlike IPv4 addresses, things can get a 1316 * little more sticky with scopes, etc. 1317 */ 1318 int dst_scope, src_scope; 1319 1320 dst_scope = ipv6_addr_scope(&sin6->sin6_addr); 1321 1322 first_match = NULL; 1323 for (walker = srchp->h_addr_list; 1324 *walker != NULL; walker++) { 1325 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1326 if (!IN6_IS_ADDR_V4MAPPED( 1327 (struct in6_addr *)*walker)) { 1328 /* 1329 * Set first-match, etc. 1330 * Take into account scopes, 1331 * and other IPv6 thingies. 1332 */ 1333 src_scope = ipv6_addr_scope( 1334 /* LINTED E_BAD_PTR_CAST */ 1335 (struct in6_addr *)*walker); 1336 if (src_scope == SCOPE_UNSPEC || 1337 src_scope == dst_scope) { 1338 if (first_match != 1339 NULL) 1340 break; 1341 else 1342 first_match = 1343 *walker; 1344 } 1345 } 1346 } 1347 1348 sin6 = (struct sockaddr_in6 *)(src + 1); 1349 bzero(sin6, sizeof (*sin6)); 1350 sin6->sin6_port = htons(srcport); 1351 if (first_match == NULL) { 1352 /* 1353 * No IPv6 hits. Is this a single 1354 * dest? 1355 */ 1356 WARN1(ep, ebuf, gettext( 1357 "No IPv6 source address of " 1358 "matching scope for name %s.\n"), 1359 srchp->h_name); 1360 if (single_dst) { 1361 ERROR(ep, ebuf, gettext( 1362 "Only a single IPV6 " 1363 "destination " 1364 "address.\n")); 1365 } else { 1366 /* Continue, but do I print? */ 1367 continue; /* for loop */ 1368 } 1369 1370 /* I should never reach here. */ 1371 } 1372 sin6->sin6_family = AF_INET6; 1373 if (*walker != NULL) { 1374 /* 1375 * Early loop exit. Issue a 1376 * null-source warning? 1377 */ 1378 WARN1(ep, ebuf, gettext( 1379 "Multiple IPv6 source addresses " 1380 "for %s of the same scope, using " 1381 "unspecified source instead.\n"), 1382 srchp->h_name); 1383 } else { 1384 /* 1385 * If I reach here w/o hitting the 1386 * previous if statements, I have a 1387 * single source address for this 1388 * destination. 1389 */ 1390 bcopy(first_match, &sin6->sin6_addr, 1391 sizeof (struct in6_addr)); 1392 } 1393 } 1394 } 1395 1396 /* 1397 * If there are errors at this point there is no 1398 * point sending anything to PF_KEY. 1399 */ 1400 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 1401 1402 /* Save off a copy for later writing... */ 1403 msgp = (struct sadb_msg *)buffer; 1404 bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len)); 1405 1406 rc = key_write(keysock, buffer, SADB_64TO8(msgp->sadb_msg_len)); 1407 if (rc == -1) 1408 Bail("write() to PF_KEY socket (in doaddresses)"); 1409 1410 /* Blank the key for paranoia's sake. */ 1411 bzero(buffer, buffer_size); 1412 time_critical_enter(); 1413 do { 1414 rc = read(keysock, buffer, buffer_size); 1415 if (rc == -1) 1416 Bail("read (in doaddresses)"); 1417 } while (msgp->sadb_msg_seq != seq || 1418 msgp->sadb_msg_pid != mypid); 1419 time_critical_exit(); 1420 1421 /* 1422 * I should _never_ hit the following unless: 1423 * 1424 * 1. There is a kernel bug. 1425 * 2. Another process is mistakenly using my pid in a PF_KEY 1426 * message. 1427 */ 1428 if (msgp->sadb_msg_type != sadb_msg_type || 1429 msgp->sadb_msg_satype != sadb_msg_satype) { 1430 syslog((LOG_NOTICE|LOG_AUTH), gettext( 1431 "doaddresses: Unexpected returned message " 1432 "(%d exp %d)\n"), msgp->sadb_msg_type, 1433 sadb_msg_type); 1434 Bail("doaddresses: Unexpected returned message"); 1435 } 1436 1437 if (msgp->sadb_msg_errno != 0) { 1438 char addrprint[INET6_ADDRSTRLEN]; 1439 int on_errno = 0; 1440 char *on_errno_msg; 1441 1442 /* 1443 * Print different error messages depending 1444 * on the SADB message type being processed. 1445 * If we get a ESRCH error for a GET/DELETE 1446 * messages, we report that the SA does not 1447 * exist. If we get a EEXIST error for a 1448 * ADD/UPDATE message, we report that the 1449 * SA already exists. 1450 */ 1451 if (sadb_msg_type == SADB_GET || 1452 sadb_msg_type == SADB_DELETE) { 1453 on_errno = ESRCH; 1454 on_errno_msg = "does not exist"; 1455 } else if (sadb_msg_type == SADB_ADD || 1456 sadb_msg_type == SADB_UPDATE) { 1457 on_errno = EEXIST; 1458 on_errno_msg = "already exists"; 1459 } 1460 1461 errno = msgp->sadb_msg_errno; 1462 if (errno == on_errno) { 1463 ERROR2(ep, ebuf, gettext( 1464 "Association (type = %s) " 1465 "with spi 0x%x and addr\n"), 1466 rparsesatype(msgp->sadb_msg_satype), 1467 ntohl(spi)); 1468 ERROR2(ep, ebuf, "%s %s.\n", 1469 do_inet_ntop(dsthp->h_addr_list[i], 1470 addrprint, sizeof (addrprint)), 1471 on_errno_msg); 1472 msgp = (struct sadb_msg *)savebuf; 1473 bcopy(savebuf, buffer, 1474 SADB_64TO8(msgp->sadb_msg_len)); 1475 continue; 1476 } else { 1477 if (errno == EINVAL) { 1478 ERROR2(ep, ebuf, gettext( 1479 "PF_KEY Diagnostic code %u: %s.\n"), 1480 msgp->sadb_x_msg_diagnostic, 1481 keysock_diag( 1482 msgp->sadb_x_msg_diagnostic)); 1483 } else { 1484 Bail("return message (in doaddresses)"); 1485 } 1486 } 1487 } 1488 1489 if (cmd == CMD_GET) { 1490 if (msgp->sadb_msg_len > MAX_GET_SIZE) { 1491 WARN1(ep, ebuf, gettext("WARNING: " 1492 "SA information bigger than %d bytes.\n"), 1493 SADB_64TO8(MAX_GET_SIZE)); 1494 } 1495 print_samsg(stdout, buffer, B_FALSE, vflag, nflag); 1496 } 1497 1498 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 1499 1500 /* ...and then restore the saved buffer. */ 1501 msgp = (struct sadb_msg *)savebuf; 1502 bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len)); 1503 lines_added++; 1504 } 1505 1506 /* Degenerate case, h_addr_list[0] == NULL. */ 1507 if (i == 0) 1508 Bail("Empty destination address list"); 1509 1510 /* 1511 * free(ebuf) even if there are no errors. 1512 * handle_errors() won't return here. 1513 */ 1514 handle_errors(ep, ebuf, B_TRUE, B_TRUE); 1515 } 1516 1517 /* 1518 * Perform an add or an update. ADD and UPDATE are similar in the extensions 1519 * they need. 1520 */ 1521 static void 1522 doaddup(int cmd, int satype, char *argv[], char *ebuf) 1523 { 1524 uint64_t *buffer, *nexthdr; 1525 struct sadb_msg msg; 1526 struct sadb_sa *assoc = NULL; 1527 struct sadb_address *src = NULL, *dst = NULL; 1528 struct sadb_address *isrc = NULL, *idst = NULL; 1529 struct sadb_address *natt_local = NULL, *natt_remote = NULL; 1530 struct sadb_key *encrypt = NULL, *auth = NULL; 1531 struct sadb_ident *srcid = NULL, *dstid = NULL; 1532 struct sadb_lifetime *hard = NULL, *soft = NULL; /* Current? */ 1533 struct sockaddr_in6 *sin6; 1534 /* MLS TODO: Need sensitivity eventually. */ 1535 int next, token, sa_len, alloclen, totallen = sizeof (msg), prefix; 1536 uint32_t spi; 1537 char *thiscmd, *pstr; 1538 boolean_t readstate = B_FALSE, unspec_src = B_FALSE; 1539 boolean_t alloc_inner = B_FALSE, use_natt = B_FALSE; 1540 struct hostent *srchp = NULL, *dsthp = NULL, *isrchp = NULL, 1541 *idsthp = NULL; 1542 struct hostent *natt_lhp = NULL, *natt_rhp = NULL; 1543 uint16_t srcport = 0, dstport = 0, natt_lport = 0, natt_rport = 0, 1544 isrcport = 0, idstport = 0; 1545 uint8_t proto = 0, iproto = 0; 1546 char *ep = NULL; 1547 1548 thiscmd = (cmd == CMD_ADD) ? "add" : "update"; 1549 1550 msg_init(&msg, ((cmd == CMD_ADD) ? SADB_ADD : SADB_UPDATE), 1551 (uint8_t)satype); 1552 1553 /* Assume last element in argv is set to NULL. */ 1554 do { 1555 token = parseextval(*argv, &next); 1556 argv++; 1557 switch (token) { 1558 case TOK_EOF: 1559 /* Do nothing, I'm done. */ 1560 break; 1561 case TOK_UNKNOWN: 1562 ERROR1(ep, ebuf, gettext( 1563 "Unknown extension field \"%s\" \n"), *(argv - 1)); 1564 break; 1565 case TOK_SPI: 1566 case TOK_REPLAY: 1567 case TOK_STATE: 1568 case TOK_AUTHALG: 1569 case TOK_ENCRALG: 1570 case TOK_ENCAP: 1571 /* 1572 * May want to place this chunk of code in a function. 1573 * 1574 * This code checks for duplicate entries on a command 1575 * line. 1576 */ 1577 1578 /* Allocate the SADB_EXT_SA extension. */ 1579 if (assoc == NULL) { 1580 assoc = malloc(sizeof (*assoc)); 1581 if (assoc == NULL) 1582 Bail("malloc(assoc)"); 1583 bzero(assoc, sizeof (*assoc)); 1584 assoc->sadb_sa_exttype = SADB_EXT_SA; 1585 assoc->sadb_sa_len = 1586 SADB_8TO64(sizeof (*assoc)); 1587 totallen += sizeof (*assoc); 1588 } 1589 switch (token) { 1590 case TOK_SPI: 1591 /* 1592 * If some cretin types in "spi 0" then he/she 1593 * can type in another SPI. 1594 */ 1595 if (assoc->sadb_sa_spi != 0) { 1596 ERROR(ep, ebuf, gettext( 1597 "Can only specify " 1598 "single SPI value.\n")); 1599 break; 1600 } 1601 /* Must convert SPI to network order! */ 1602 assoc->sadb_sa_spi = 1603 htonl((uint32_t)parsenum(*argv, B_TRUE, 1604 ebuf)); 1605 if (assoc->sadb_sa_spi == 0) { 1606 ERROR(ep, ebuf, gettext( 1607 "Invalid SPI value \"0\" .\n")); 1608 } 1609 break; 1610 case TOK_REPLAY: 1611 /* 1612 * That same cretin can do the same with 1613 * replay. 1614 */ 1615 if (assoc->sadb_sa_replay != 0) { 1616 ERROR(ep, ebuf, gettext( 1617 "Can only specify " 1618 "single replay window size.\n")); 1619 break; 1620 } 1621 assoc->sadb_sa_replay = 1622 (uint8_t)parsenum(*argv, B_TRUE, ebuf); 1623 if (assoc->sadb_sa_replay != 0) { 1624 WARN(ep, ebuf, gettext( 1625 "WARNING: Replay with manual" 1626 " keying considered harmful.\n")); 1627 } 1628 break; 1629 case TOK_STATE: 1630 /* 1631 * 0 is an actual state value, LARVAL. This 1632 * means that one can type in the larval state 1633 * and then type in another state on the same 1634 * command line. 1635 */ 1636 if (assoc->sadb_sa_state != 0) { 1637 ERROR(ep, ebuf, gettext( 1638 "Can only specify " 1639 "single SA state.\n")); 1640 break; 1641 } 1642 assoc->sadb_sa_state = parsestate(*argv, 1643 ebuf); 1644 readstate = B_TRUE; 1645 break; 1646 case TOK_AUTHALG: 1647 if (assoc->sadb_sa_auth != 0) { 1648 ERROR(ep, ebuf, gettext( 1649 "Can only specify " 1650 "single auth algorithm.\n")); 1651 break; 1652 } 1653 assoc->sadb_sa_auth = parsealg(*argv, 1654 IPSEC_PROTO_AH, ebuf); 1655 break; 1656 case TOK_ENCRALG: 1657 if (satype == SADB_SATYPE_AH) { 1658 ERROR(ep, ebuf, gettext("Cannot specify" 1659 " encryption with SA type ah.\n")); 1660 break; 1661 } 1662 if (assoc->sadb_sa_encrypt != 0) { 1663 ERROR(ep, ebuf, gettext( 1664 "Can only specify " 1665 "single encryption algorithm.\n")); 1666 break; 1667 } 1668 assoc->sadb_sa_encrypt = parsealg(*argv, 1669 IPSEC_PROTO_ESP, ebuf); 1670 break; 1671 case TOK_ENCAP: 1672 if (use_natt) { 1673 ERROR(ep, ebuf, gettext( 1674 "Can only specify single" 1675 " encapsulation.\n")); 1676 break; 1677 } 1678 if (strncmp(*argv, "udp", 3)) { 1679 ERROR(ep, ebuf, gettext( 1680 "Can only specify udp" 1681 " encapsulation.\n")); 1682 break; 1683 } 1684 use_natt = B_TRUE; 1685 /* set assoc flags later */ 1686 break; 1687 } 1688 argv++; 1689 break; 1690 case TOK_SRCPORT: 1691 if (srcport != 0) { 1692 ERROR(ep, ebuf, gettext("Can only specify " 1693 "single source port.\n")); 1694 break; 1695 } 1696 srcport = parsenum(*argv, B_TRUE, ebuf); 1697 argv++; 1698 break; 1699 case TOK_DSTPORT: 1700 if (dstport != 0) { 1701 ERROR(ep, ebuf, gettext("Can only specify " 1702 "single destination port.\n")); 1703 break; 1704 } 1705 dstport = parsenum(*argv, B_TRUE, ebuf); 1706 argv++; 1707 break; 1708 case TOK_ISRCPORT: 1709 alloc_inner = B_TRUE; 1710 if (isrcport != 0) { 1711 ERROR(ep, ebuf, gettext( 1712 "Can only specify " 1713 "single inner-source port.\n")); 1714 break; 1715 } 1716 isrcport = parsenum(*argv, B_TRUE, ebuf); 1717 argv++; 1718 break; 1719 case TOK_IDSTPORT: 1720 alloc_inner = B_TRUE; 1721 if (idstport != 0) { 1722 ERROR(ep, ebuf, gettext( 1723 "Can only specify " 1724 "single inner-destination port.\n")); 1725 break; 1726 } 1727 idstport = parsenum(*argv, B_TRUE, ebuf); 1728 argv++; 1729 break; 1730 case TOK_NATLPORT: 1731 if (natt_lport != 0) { 1732 ERROR(ep, ebuf, gettext( 1733 "Can only specify " 1734 "single NAT-T local port.\n")); 1735 break; 1736 } 1737 natt_lport = parsenum(*argv, B_TRUE, ebuf); 1738 argv++; 1739 break; 1740 case TOK_NATRPORT: 1741 if (natt_rport != 0) { 1742 ERROR(ep, ebuf, gettext( 1743 "Can only specify " 1744 "single NAT-T remote port.\n")); 1745 break; 1746 } 1747 natt_rport = parsenum(*argv, B_TRUE, ebuf); 1748 argv++; 1749 break; 1750 1751 case TOK_PROTO: 1752 if (proto != 0) { 1753 ERROR(ep, ebuf, gettext( 1754 "Can only specify " 1755 "single protocol.\n")); 1756 break; 1757 } 1758 proto = parsenum(*argv, B_TRUE, ebuf); 1759 argv++; 1760 break; 1761 case TOK_IPROTO: 1762 alloc_inner = B_TRUE; 1763 if (iproto != 0) { 1764 ERROR(ep, ebuf, gettext( 1765 "Can only specify " 1766 "single inner protocol.\n")); 1767 break; 1768 } 1769 iproto = parsenum(*argv, B_TRUE, ebuf); 1770 argv++; 1771 break; 1772 case TOK_SRCADDR: 1773 case TOK_SRCADDR6: 1774 if (src != NULL) { 1775 ERROR(ep, ebuf, gettext( 1776 "Can only specify " 1777 "single source address.\n")); 1778 break; 1779 } 1780 sa_len = parseaddr(*argv, &srchp, 1781 (token == TOK_SRCADDR6), ebuf); 1782 if (srchp == NULL) { 1783 ERROR1(ep, ebuf, gettext( 1784 "Unknown src address \"%s\"\n"), *argv); 1785 break; 1786 } 1787 argv++; 1788 /* 1789 * Round of the sockaddr length to an 8 byte 1790 * boundary to make PF_KEY happy. 1791 */ 1792 alloclen = sizeof (*src) + roundup(sa_len, 8); 1793 src = malloc(alloclen); 1794 if (src == NULL) 1795 Bail("malloc(src)"); 1796 totallen += alloclen; 1797 src->sadb_address_len = SADB_8TO64(alloclen); 1798 src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 1799 src->sadb_address_reserved = 0; 1800 src->sadb_address_prefixlen = 0; 1801 src->sadb_address_proto = 0; 1802 if (srchp == &dummy.he) { 1803 /* 1804 * Single address with -n flag. 1805 */ 1806 sin6 = (struct sockaddr_in6 *)(src + 1); 1807 bzero(sin6, sizeof (*sin6)); 1808 sin6->sin6_family = AF_INET6; 1809 bcopy(srchp->h_addr_list[0], &sin6->sin6_addr, 1810 sizeof (struct in6_addr)); 1811 } 1812 break; 1813 case TOK_DSTADDR: 1814 case TOK_DSTADDR6: 1815 if (dst != NULL) { 1816 ERROR(ep, ebuf, gettext( 1817 "Can only specify single " 1818 "destination address.\n")); 1819 break; 1820 } 1821 sa_len = parseaddr(*argv, &dsthp, 1822 (token == TOK_DSTADDR6), ebuf); 1823 if (dsthp == NULL) { 1824 ERROR1(ep, ebuf, gettext( 1825 "Unknown dst address \"%s\"\n"), *argv); 1826 break; 1827 } 1828 argv++; 1829 alloclen = sizeof (*dst) + roundup(sa_len, 8); 1830 dst = malloc(alloclen); 1831 if (dst == NULL) 1832 Bail("malloc(dst)"); 1833 totallen += alloclen; 1834 dst->sadb_address_len = SADB_8TO64(alloclen); 1835 dst->sadb_address_exttype = SADB_EXT_ADDRESS_DST; 1836 dst->sadb_address_reserved = 0; 1837 dst->sadb_address_prefixlen = 0; 1838 dst->sadb_address_proto = 0; 1839 if (dsthp == &dummy.he) { 1840 /* 1841 * Single address with -n flag. 1842 */ 1843 sin6 = (struct sockaddr_in6 *)(dst + 1); 1844 bzero(sin6, sizeof (*sin6)); 1845 sin6->sin6_family = AF_INET6; 1846 bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr, 1847 sizeof (struct in6_addr)); 1848 } 1849 break; 1850 case TOK_PROXYADDR: 1851 case TOK_PROXYADDR6: 1852 if (isrc != NULL) { 1853 ERROR(ep, ebuf, gettext( 1854 "Can only specify single " 1855 "proxy/inner-source address.\n")); 1856 break; 1857 } 1858 if ((pstr = strchr(*argv, '/')) != NULL) { 1859 /* Parse out the prefix. */ 1860 errno = 0; 1861 prefix = strtol(pstr + 1, NULL, 10); 1862 if (errno != 0) { 1863 ERROR1(ep, ebuf, gettext( 1864 "Invalid prefix %s."), pstr); 1865 break; 1866 } 1867 /* Recycle pstr */ 1868 alloclen = (int)(pstr - *argv); 1869 pstr = malloc(alloclen + 1); 1870 if (pstr == NULL) { 1871 Bail("malloc(pstr)"); 1872 } 1873 (void) strlcpy(pstr, *argv, alloclen + 1); 1874 } else { 1875 pstr = *argv; 1876 /* 1877 * Assume mapping to AF_INET6, and we're a host. 1878 * XXX some miscreants may still make classful 1879 * assumptions. If this is a problem, fix it 1880 * here. 1881 */ 1882 prefix = 128; 1883 } 1884 sa_len = parseaddr(pstr, &isrchp, 1885 (token == TOK_PROXYADDR6), ebuf); 1886 if (isrchp == NULL) { 1887 ERROR1(ep, ebuf, gettext( 1888 "Unknown proxy/inner-source address " 1889 "\"%s\"\n"), *argv); 1890 break; 1891 } 1892 if (pstr != *argv) 1893 free(pstr); 1894 argv++; 1895 alloclen = sizeof (*isrc) + roundup(sa_len, 8); 1896 isrc = malloc(alloclen); 1897 if (isrc == NULL) 1898 Bail("malloc(isrc)"); 1899 totallen += alloclen; 1900 isrc->sadb_address_len = SADB_8TO64(alloclen); 1901 isrc->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; 1902 isrc->sadb_address_reserved = 0; 1903 isrc->sadb_address_prefixlen = prefix; 1904 isrc->sadb_address_proto = 0; 1905 if (isrchp == &dummy.he || 1906 isrchp->h_addr_list[1] == NULL) { 1907 /* 1908 * Single address with -n flag or single name. 1909 */ 1910 sin6 = (struct sockaddr_in6 *)(isrc + 1); 1911 bzero(sin6, sizeof (*sin6)); 1912 sin6->sin6_family = AF_INET6; 1913 bcopy(isrchp->h_addr_list[0], &sin6->sin6_addr, 1914 sizeof (struct in6_addr)); 1915 /* 1916 * normalize prefixlen for IPv4-mapped 1917 * addresses. 1918 */ 1919 if (prefix <= 32 && 1920 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 1921 isrc->sadb_address_prefixlen += 96; 1922 alloc_inner = B_TRUE; 1923 } else { 1924 /* 1925 * If the proxy/isrc address is vague, don't 1926 * bother. 1927 */ 1928 totallen -= alloclen; 1929 free(isrc); 1930 isrc = NULL; 1931 WARN1(ep, ebuf, gettext( 1932 "Proxy/inner-source address %s " 1933 "is vague, not using.\n"), isrchp->h_name); 1934 freehostent(isrchp); 1935 isrchp = NULL; 1936 break; 1937 } 1938 break; 1939 case TOK_IDSTADDR: 1940 case TOK_IDSTADDR6: 1941 if (idst != NULL) { 1942 ERROR(ep, ebuf, gettext( 1943 "Can only specify single " 1944 "inner-destination address.\n")); 1945 break; 1946 } 1947 if ((pstr = strchr(*argv, '/')) != NULL) { 1948 /* Parse out the prefix. */ 1949 errno = 0; 1950 prefix = strtol(pstr + 1, NULL, 10); 1951 if (errno != 0) { 1952 ERROR1(ep, ebuf, gettext( 1953 "Invalid prefix %s.\n"), pstr); 1954 break; 1955 } 1956 /* Recycle pstr */ 1957 alloclen = (int)(pstr - *argv); 1958 pstr = malloc(alloclen + 1); 1959 if (pstr == NULL) { 1960 Bail("malloc(pstr)"); 1961 } 1962 (void) strlcpy(pstr, *argv, alloclen + 1); 1963 } else { 1964 pstr = *argv; 1965 /* 1966 * Assume mapping to AF_INET6, and we're a host. 1967 * XXX some miscreants may still make classful 1968 * assumptions. If this is a problem, fix it 1969 * here. 1970 */ 1971 prefix = 128; 1972 } 1973 sa_len = parseaddr(pstr, &idsthp, 1974 (token == TOK_IDSTADDR6), ebuf); 1975 if (idsthp == NULL) { 1976 ERROR1(ep, ebuf, gettext( 1977 "Unknown Inner Src address " 1978 " \"%s\"\n"), *argv); 1979 break; 1980 } 1981 if (pstr != *argv) 1982 free(pstr); 1983 argv++; 1984 alloclen = sizeof (*idst) + roundup(sa_len, 8); 1985 idst = malloc(alloclen); 1986 if (idst == NULL) 1987 Bail("malloc(idst)"); 1988 totallen += alloclen; 1989 idst->sadb_address_len = SADB_8TO64(alloclen); 1990 idst->sadb_address_exttype = 1991 SADB_X_EXT_ADDRESS_INNER_DST; 1992 idst->sadb_address_reserved = 0; 1993 idst->sadb_address_prefixlen = prefix; 1994 idst->sadb_address_proto = 0; 1995 if (idsthp == &dummy.he || 1996 idsthp->h_addr_list[1] == NULL) { 1997 /* 1998 * Single address with -n flag or single name. 1999 */ 2000 sin6 = (struct sockaddr_in6 *)(idst + 1); 2001 bzero(sin6, sizeof (*sin6)); 2002 sin6->sin6_family = AF_INET6; 2003 bcopy(idsthp->h_addr_list[0], &sin6->sin6_addr, 2004 sizeof (struct in6_addr)); 2005 /* 2006 * normalize prefixlen for IPv4-mapped 2007 * addresses. 2008 */ 2009 if (prefix <= 32 && 2010 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 2011 idst->sadb_address_prefixlen += 96; 2012 alloc_inner = B_TRUE; 2013 } else { 2014 /* 2015 * If the idst address is vague, don't bother. 2016 */ 2017 totallen -= alloclen; 2018 free(idst); 2019 idst = NULL; 2020 WARN1(ep, ebuf, gettext( 2021 "Inner destination address %s " 2022 "is vague, not using.\n"), idsthp->h_name); 2023 freehostent(idsthp); 2024 idsthp = NULL; 2025 break; 2026 } 2027 break; 2028 case TOK_NATLOC: 2029 if (natt_local != NULL) { 2030 ERROR(ep, ebuf, gettext( 2031 "Can only specify " 2032 "single NAT-T local address.\n")); 2033 break; 2034 } 2035 sa_len = parseaddr(*argv, &natt_lhp, 0, ebuf); 2036 if (natt_lhp == NULL) { 2037 ERROR1(ep, ebuf, gettext( 2038 "Unknown NAT-T local address \"%s\"\n"), 2039 *argv); 2040 break; 2041 } 2042 argv++; 2043 /* 2044 * Round of the sockaddr length to an 8 byte 2045 * boundary to make PF_KEY happy. 2046 */ 2047 alloclen = sizeof (*natt_local) + roundup(sa_len, 8); 2048 natt_local = malloc(alloclen); 2049 if (natt_local == NULL) 2050 Bail("malloc(natt_local)"); 2051 totallen += alloclen; 2052 natt_local->sadb_address_len = SADB_8TO64(alloclen); 2053 natt_local->sadb_address_exttype = 2054 SADB_X_EXT_ADDRESS_NATT_LOC; 2055 natt_local->sadb_address_reserved = 0; 2056 natt_local->sadb_address_prefixlen = 0; 2057 natt_local->sadb_address_proto = 0; 2058 if (natt_lhp == &dummy.he || 2059 natt_lhp->h_addr_list[1] == NULL) { 2060 /* 2061 * Single address with -n flag or single name. 2062 */ 2063 sin6 = (struct sockaddr_in6 *)(natt_local + 1); 2064 bzero(sin6, sizeof (*sin6)); 2065 sin6->sin6_family = AF_INET6; 2066 bcopy(natt_lhp->h_addr_list[0], 2067 &sin6->sin6_addr, sizeof (struct in6_addr)); 2068 } else { 2069 /* 2070 * If the nat-local address is vague, don't 2071 * bother. 2072 */ 2073 totallen -= alloclen; 2074 free(natt_local); 2075 natt_local = NULL; 2076 WARN1(ep, ebuf, gettext( 2077 "NAT-T local address %s " 2078 "is vague, not using.\n"), 2079 natt_lhp->h_name); 2080 freehostent(natt_lhp); 2081 natt_lhp = NULL; 2082 break; 2083 } 2084 break; 2085 case TOK_NATREM: 2086 if (natt_remote != NULL) { 2087 ERROR(ep, ebuf, gettext( 2088 "Can only specify " 2089 "single NAT-T remote address.\n")); 2090 break; 2091 } 2092 sa_len = parseaddr(*argv, &natt_rhp, 0, ebuf); 2093 if (natt_rhp == NULL) { 2094 ERROR1(ep, ebuf, gettext( 2095 "Unknown NAT-T remote address \"%s\"\n"), 2096 *argv); 2097 break; 2098 } 2099 argv++; 2100 /* 2101 * Round of the sockaddr length to an 8 byte 2102 * boundary to make PF_KEY happy. 2103 */ 2104 alloclen = sizeof (*natt_remote) + roundup(sa_len, 8); 2105 natt_remote = malloc(alloclen); 2106 if (natt_remote == NULL) 2107 Bail("malloc(natt_remote)"); 2108 totallen += alloclen; 2109 natt_remote->sadb_address_len = SADB_8TO64(alloclen); 2110 natt_remote->sadb_address_exttype = 2111 SADB_X_EXT_ADDRESS_NATT_REM; 2112 natt_remote->sadb_address_reserved = 0; 2113 natt_remote->sadb_address_prefixlen = 0; 2114 natt_remote->sadb_address_proto = 0; 2115 if (natt_rhp == &dummy.he || 2116 natt_rhp->h_addr_list[1] == NULL) { 2117 /* 2118 * Single address with -n flag or single name. 2119 */ 2120 sin6 = (struct sockaddr_in6 *)(natt_remote + 1); 2121 bzero(sin6, sizeof (*sin6)); 2122 sin6->sin6_family = AF_INET6; 2123 bcopy(natt_rhp->h_addr_list[0], 2124 &sin6->sin6_addr, sizeof (struct in6_addr)); 2125 } else { 2126 /* 2127 * If the nat-renote address is vague, don't 2128 * bother. 2129 */ 2130 totallen -= alloclen; 2131 free(natt_remote); 2132 natt_remote = NULL; 2133 WARN1(ep, ebuf, gettext( 2134 "NAT-T remote address %s " 2135 "is vague, not using.\n"), 2136 natt_rhp->h_name); 2137 freehostent(natt_rhp); 2138 natt_rhp = NULL; 2139 break; 2140 } 2141 break; 2142 case TOK_ENCRKEY: 2143 if (encrypt != NULL) { 2144 ERROR(ep, ebuf, gettext( 2145 "Can only specify " 2146 "single encryption key.\n")); 2147 break; 2148 } 2149 if (assoc->sadb_sa_encrypt == SADB_EALG_NULL) { 2150 FATAL(ep, ebuf, gettext( 2151 "Cannot specify a key with NULL " 2152 "encryption algorithm.\n")); 2153 break; 2154 } 2155 encrypt = parsekey(*argv, ebuf); 2156 argv++; 2157 if (encrypt == NULL) { 2158 ERROR(ep, ebuf, gettext( 2159 "Invalid encryption key.\n")); 2160 break; 2161 } 2162 totallen += SADB_64TO8(encrypt->sadb_key_len); 2163 encrypt->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; 2164 break; 2165 case TOK_AUTHKEY: 2166 if (auth != NULL) { 2167 ERROR(ep, ebuf, gettext( 2168 "Can only specify single" 2169 " authentication key.\n")); 2170 break; 2171 } 2172 auth = parsekey(*argv, ebuf); 2173 argv++; 2174 if (auth == NULL) { 2175 ERROR(ep, ebuf, gettext( 2176 "Invalid authentication key.\n")); 2177 break; 2178 } 2179 totallen += SADB_64TO8(auth->sadb_key_len); 2180 auth->sadb_key_exttype = SADB_EXT_KEY_AUTH; 2181 break; 2182 case TOK_SRCIDTYPE: 2183 if (*argv == NULL || *(argv + 1) == NULL) { 2184 FATAL(ep, ebuf, gettext( 2185 "Unexpected end of command " 2186 "line - Expecting Src Type.\n")); 2187 /* NOTREACHED */ 2188 break; 2189 } 2190 if (srcid != NULL) { 2191 ERROR(ep, ebuf, gettext( 2192 "Can only specify single" 2193 " source certificate identity.\n")); 2194 break; 2195 } 2196 alloclen = sizeof (*srcid) + 2197 roundup(strlen(*(argv + 1)) + 1, 8); 2198 srcid = malloc(alloclen); 2199 if (srcid == NULL) 2200 Bail("malloc(srcid)"); 2201 totallen += alloclen; 2202 srcid->sadb_ident_type = parseidtype(*argv, ebuf); 2203 argv++; 2204 srcid->sadb_ident_len = SADB_8TO64(alloclen); 2205 srcid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; 2206 srcid->sadb_ident_reserved = 0; 2207 srcid->sadb_ident_id = 0; /* Not useful here. */ 2208 (void) strlcpy((char *)(srcid + 1), *argv, alloclen); 2209 argv++; 2210 break; 2211 case TOK_DSTIDTYPE: 2212 if (*argv == NULL || *(argv + 1) == NULL) { 2213 ERROR(ep, ebuf, gettext( 2214 "Unexpected end of command" 2215 " line - expecting dst type.\n")); 2216 break; 2217 } 2218 if (dstid != NULL) { 2219 ERROR(ep, ebuf, gettext( 2220 "Can only specify single destination " 2221 "certificate identity.\n")); 2222 break; 2223 } 2224 alloclen = sizeof (*dstid) + 2225 roundup(strlen(*(argv + 1)) + 1, 8); 2226 dstid = malloc(alloclen); 2227 if (dstid == NULL) 2228 Bail("malloc(dstid)"); 2229 totallen += alloclen; 2230 dstid->sadb_ident_type = parseidtype(*argv, ebuf); 2231 argv++; 2232 dstid->sadb_ident_len = SADB_8TO64(alloclen); 2233 dstid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; 2234 dstid->sadb_ident_reserved = 0; 2235 dstid->sadb_ident_id = 0; /* Not useful here. */ 2236 (void) strlcpy((char *)(dstid + 1), *argv, alloclen); 2237 argv++; 2238 break; 2239 case TOK_HARD_ALLOC: 2240 case TOK_HARD_BYTES: 2241 case TOK_HARD_ADDTIME: 2242 case TOK_HARD_USETIME: 2243 if (hard == NULL) { 2244 hard = malloc(sizeof (*hard)); 2245 if (hard == NULL) 2246 Bail("malloc(hard_lifetime)"); 2247 bzero(hard, sizeof (*hard)); 2248 hard->sadb_lifetime_exttype = 2249 SADB_EXT_LIFETIME_HARD; 2250 hard->sadb_lifetime_len = 2251 SADB_8TO64(sizeof (*hard)); 2252 totallen += sizeof (*hard); 2253 } 2254 switch (token) { 2255 case TOK_HARD_ALLOC: 2256 if (hard->sadb_lifetime_allocations != 0) { 2257 ERROR(ep, ebuf, gettext( 2258 "Can only specify single" 2259 " hard allocation limit.\n")); 2260 break; 2261 } 2262 hard->sadb_lifetime_allocations = 2263 (uint32_t)parsenum(*argv, B_TRUE, ebuf); 2264 break; 2265 case TOK_HARD_BYTES: 2266 if (hard->sadb_lifetime_bytes != 0) { 2267 ERROR(ep, ebuf, gettext( 2268 "Can only specify " 2269 "single hard byte limit.\n")); 2270 break; 2271 } 2272 hard->sadb_lifetime_bytes = parsenum(*argv, 2273 B_TRUE, ebuf); 2274 break; 2275 case TOK_HARD_ADDTIME: 2276 if (hard->sadb_lifetime_addtime != 0) { 2277 ERROR(ep, ebuf, gettext( 2278 "Can only specify " 2279 "single past-add lifetime.\n")); 2280 break; 2281 } 2282 hard->sadb_lifetime_addtime = parsenum(*argv, 2283 B_TRUE, ebuf); 2284 break; 2285 case TOK_HARD_USETIME: 2286 if (hard->sadb_lifetime_usetime != 0) { 2287 ERROR(ep, ebuf, gettext( 2288 "Can only specify " 2289 "single past-use lifetime.\n")); 2290 break; 2291 } 2292 hard->sadb_lifetime_usetime = parsenum(*argv, 2293 B_TRUE, ebuf); 2294 break; 2295 } 2296 argv++; 2297 break; 2298 case TOK_SOFT_ALLOC: 2299 case TOK_SOFT_BYTES: 2300 case TOK_SOFT_ADDTIME: 2301 case TOK_SOFT_USETIME: 2302 if (soft == NULL) { 2303 soft = malloc(sizeof (*soft)); 2304 if (soft == NULL) 2305 Bail("malloc(soft_lifetime)"); 2306 bzero(soft, sizeof (*soft)); 2307 soft->sadb_lifetime_exttype = 2308 SADB_EXT_LIFETIME_SOFT; 2309 soft->sadb_lifetime_len = 2310 SADB_8TO64(sizeof (*soft)); 2311 totallen += sizeof (*soft); 2312 } 2313 switch (token) { 2314 case TOK_SOFT_ALLOC: 2315 if (soft->sadb_lifetime_allocations != 0) { 2316 ERROR(ep, ebuf, gettext( 2317 "Can only specify single" 2318 " soft allocation limit.\n")); 2319 break; 2320 } 2321 soft->sadb_lifetime_allocations = 2322 (uint32_t)parsenum(*argv, B_TRUE, ebuf); 2323 break; 2324 case TOK_SOFT_BYTES: 2325 if (soft->sadb_lifetime_bytes != 0) { 2326 ERROR(ep, ebuf, gettext( 2327 "Can only specify single" 2328 " soft byte limit.\n")); 2329 break; 2330 } 2331 soft->sadb_lifetime_bytes = parsenum(*argv, 2332 B_TRUE, ebuf); 2333 break; 2334 case TOK_SOFT_ADDTIME: 2335 if (soft->sadb_lifetime_addtime != 0) { 2336 ERROR(ep, ebuf, gettext( 2337 "Can only specify single" 2338 " past-add lifetime.\n")); 2339 break; 2340 } 2341 soft->sadb_lifetime_addtime = parsenum(*argv, 2342 B_TRUE, ebuf); 2343 break; 2344 case TOK_SOFT_USETIME: 2345 if (soft->sadb_lifetime_usetime != 0) { 2346 ERROR(ep, ebuf, gettext( 2347 "Can only specify single" 2348 " past-use lifetime.\n")); 2349 break; 2350 } 2351 soft->sadb_lifetime_usetime = parsenum(*argv, 2352 B_TRUE, ebuf); 2353 break; 2354 } 2355 argv++; 2356 break; 2357 default: 2358 ERROR1(ep, ebuf, gettext( 2359 "Don't use extension %s for add/update.\n"), 2360 *(argv - 1)); 2361 break; 2362 } 2363 } while (token != TOK_EOF); 2364 2365 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 2366 2367 #define PORT_ONLY_ALLOCATE(af, socktype, exttype, extvar, port) { \ 2368 alloclen = sizeof (sadb_address_t) + roundup(sizeof (socktype), 8); \ 2369 (extvar) = calloc(1, alloclen); \ 2370 if ((extvar) == NULL) { \ 2371 Bail("malloc(implicit port)"); \ 2372 } \ 2373 totallen += alloclen; \ 2374 (extvar)->sadb_address_len = SADB_8TO64(alloclen); \ 2375 (extvar)->sadb_address_exttype = (exttype); \ 2376 /* sin/sin6 has equivalent offsets for ports! */ \ 2377 sin6 = (struct sockaddr_in6 *)((extvar) + 1); \ 2378 sin6->sin6_family = (af); \ 2379 sin6->sin6_port = (port); \ 2380 } 2381 2382 /* 2383 * If we specify inner ports or NAT ports w/o addresses, we still need 2384 * to allocate. Also, if we have one inner address, we need the 2385 * other, even if we don't specify anything. 2386 */ 2387 if (use_natt) { 2388 if (natt_lport != 0 && natt_local == NULL) { 2389 PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in, 2390 SADB_X_EXT_ADDRESS_NATT_LOC, natt_local, 2391 natt_lport); 2392 } 2393 2394 if (natt_rport != 0 && natt_remote == NULL) { 2395 PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in, 2396 SADB_X_EXT_ADDRESS_NATT_REM, natt_remote, 2397 natt_rport); 2398 } 2399 } else { 2400 if (natt_lport != 0 || natt_rport != 0) { 2401 ERROR(ep, ebuf, gettext("Must specify 'encap udp' " 2402 "with any NAT-T port.\n")); 2403 } else if (natt_local != NULL || natt_remote != NULL) { 2404 ERROR(ep, ebuf, gettext("Must specify 'encap udp' " 2405 "with any NAT-T address.\n")); 2406 } 2407 } 2408 2409 if (alloc_inner && idst == NULL) { 2410 PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6, 2411 SADB_X_EXT_ADDRESS_INNER_DST, idst, 0); 2412 } 2413 2414 if (alloc_inner && isrc == NULL) { 2415 PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6, 2416 SADB_X_EXT_ADDRESS_INNER_SRC, isrc, 0); 2417 } 2418 #undef PORT_ONLY_ALLOCATE 2419 2420 /* 2421 * Okay, so now I have all of the potential extensions! 2422 * Allocate a single contiguous buffer. Keep in mind that it'll 2423 * be enough because the key itself will be yanked. 2424 */ 2425 2426 if (src == NULL && dst != NULL) { 2427 /* 2428 * Set explicit unspecified source address. 2429 */ 2430 size_t lenbytes = SADB_64TO8(dst->sadb_address_len); 2431 2432 unspec_src = B_TRUE; 2433 totallen += lenbytes; 2434 src = malloc(lenbytes); 2435 if (src == NULL) 2436 Bail("malloc(implicit src)"); 2437 /* Confusing, but we're copying from DST to SRC. :) */ 2438 bcopy(dst, src, lenbytes); 2439 src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 2440 sin6 = (struct sockaddr_in6 *)(src + 1); 2441 bzero(sin6, sizeof (*sin6)); 2442 sin6->sin6_family = AF_INET6; 2443 } 2444 2445 msg.sadb_msg_len = SADB_8TO64(totallen); 2446 2447 buffer = malloc(totallen); 2448 nexthdr = buffer; 2449 bcopy(&msg, nexthdr, sizeof (msg)); 2450 nexthdr += SADB_8TO64(sizeof (msg)); 2451 if (assoc != NULL) { 2452 if (assoc->sadb_sa_spi == 0) { 2453 ERROR1(ep, ebuf, gettext( 2454 "The SPI value is missing for " 2455 "the association you wish to %s.\n"), thiscmd); 2456 } 2457 if (assoc->sadb_sa_auth == 0 && assoc->sadb_sa_encrypt == 0 && 2458 cmd == CMD_ADD) { 2459 free(assoc); 2460 FATAL(ep, ebuf, gettext( 2461 "Select at least one algorithm " 2462 "for this add.\n")); 2463 } 2464 2465 /* Hack to let user specify NULL ESP implicitly. */ 2466 if (msg.sadb_msg_satype == SADB_SATYPE_ESP && 2467 assoc->sadb_sa_encrypt == 0) 2468 assoc->sadb_sa_encrypt = SADB_EALG_NULL; 2469 2470 /* 0 is an actual value. Print a warning if it was entered. */ 2471 if (assoc->sadb_sa_state == 0) { 2472 if (readstate) { 2473 ERROR(ep, ebuf, gettext( 2474 "WARNING: Cannot set LARVAL SA state.\n")); 2475 } 2476 assoc->sadb_sa_state = SADB_SASTATE_MATURE; 2477 } 2478 2479 if (use_natt) { 2480 if (natt_remote != NULL) 2481 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_REM; 2482 if (natt_local != NULL) 2483 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_LOC; 2484 } 2485 2486 if (alloc_inner) { 2487 /* 2488 * For now, assume RFC 3884's dream of transport-mode 2489 * SAs with inner IP address selectors will not 2490 * happen. 2491 */ 2492 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL; 2493 if (proto != 0 && proto != IPPROTO_ENCAP && 2494 proto != IPPROTO_IPV6) { 2495 ERROR1(ep, ebuf, gettext( 2496 "WARNING: Protocol type %d not " 2497 "for use with Tunnel-Mode SA.\n"), proto); 2498 /* Continue and let PF_KEY scream... */ 2499 } 2500 } 2501 2502 bcopy(assoc, nexthdr, SADB_64TO8(assoc->sadb_sa_len)); 2503 nexthdr += assoc->sadb_sa_len; 2504 /* Save the SPI for the case of an error. */ 2505 spi = assoc->sadb_sa_spi; 2506 free(assoc); 2507 } else { 2508 ERROR1(ep, ebuf, gettext( 2509 "Need SA parameters for %s.\n"), thiscmd); 2510 } 2511 2512 if (hard != NULL) { 2513 bcopy(hard, nexthdr, SADB_64TO8(hard->sadb_lifetime_len)); 2514 nexthdr += hard->sadb_lifetime_len; 2515 free(hard); 2516 } 2517 2518 if (soft != NULL) { 2519 bcopy(soft, nexthdr, SADB_64TO8(soft->sadb_lifetime_len)); 2520 nexthdr += soft->sadb_lifetime_len; 2521 free(soft); 2522 } 2523 2524 if (encrypt == NULL && auth == NULL && cmd == CMD_ADD) { 2525 ERROR(ep, ebuf, gettext( 2526 "Must have at least one key for an add.\n")); 2527 } 2528 2529 if (encrypt != NULL) { 2530 bcopy(encrypt, nexthdr, SADB_64TO8(encrypt->sadb_key_len)); 2531 nexthdr += encrypt->sadb_key_len; 2532 bzero(encrypt, SADB_64TO8(encrypt->sadb_key_len)); 2533 free(encrypt); 2534 } 2535 2536 if (auth != NULL) { 2537 bcopy(auth, nexthdr, SADB_64TO8(auth->sadb_key_len)); 2538 nexthdr += auth->sadb_key_len; 2539 bzero(auth, SADB_64TO8(auth->sadb_key_len)); 2540 free(auth); 2541 } 2542 2543 if (srcid != NULL) { 2544 bcopy(srcid, nexthdr, SADB_64TO8(srcid->sadb_ident_len)); 2545 nexthdr += srcid->sadb_ident_len; 2546 free(srcid); 2547 } 2548 2549 if (dstid != NULL) { 2550 bcopy(dstid, nexthdr, SADB_64TO8(dstid->sadb_ident_len)); 2551 nexthdr += dstid->sadb_ident_len; 2552 free(dstid); 2553 } 2554 2555 if (dst != NULL) { 2556 bcopy(dst, nexthdr, SADB_64TO8(dst->sadb_address_len)); 2557 free(dst); 2558 dst = (struct sadb_address *)nexthdr; 2559 dst->sadb_address_proto = proto; 2560 ((struct sockaddr_in6 *)(dst + 1))->sin6_port = htons(dstport); 2561 nexthdr += dst->sadb_address_len; 2562 } else { 2563 FATAL1(ep, ebuf, gettext( 2564 "Need destination address for %s.\n"), thiscmd); 2565 } 2566 2567 if (use_natt) { 2568 if (natt_remote == NULL && natt_local == NULL) { 2569 ERROR(ep, ebuf, gettext( 2570 "Must specify NAT-T remote or local address " 2571 "for UDP encapsulation.\n")); 2572 } 2573 2574 if (natt_remote != NULL) { 2575 bcopy(natt_remote, nexthdr, 2576 SADB_64TO8(natt_remote->sadb_address_len)); 2577 free(natt_remote); 2578 natt_remote = (struct sadb_address *)nexthdr; 2579 nexthdr += natt_remote->sadb_address_len; 2580 ((struct sockaddr_in6 *)(natt_remote + 1))->sin6_port = 2581 htons(natt_rport); 2582 } 2583 2584 if (natt_local != NULL) { 2585 bcopy(natt_local, nexthdr, 2586 SADB_64TO8(natt_local->sadb_address_len)); 2587 free(natt_local); 2588 natt_local = (struct sadb_address *)nexthdr; 2589 nexthdr += natt_local->sadb_address_len; 2590 ((struct sockaddr_in6 *)(natt_local + 1))->sin6_port = 2591 htons(natt_lport); 2592 } 2593 } 2594 2595 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 2596 2597 /* 2598 * PF_KEY requires a source address extension, even if the source 2599 * address itself is unspecified. (See "Set explicit unspecified..." 2600 * code fragment above. Destination reality check was above.) 2601 */ 2602 bcopy(src, nexthdr, SADB_64TO8(src->sadb_address_len)); 2603 free(src); 2604 src = (struct sadb_address *)nexthdr; 2605 src->sadb_address_proto = proto; 2606 ((struct sockaddr_in6 *)(src + 1))->sin6_port = htons(srcport); 2607 nexthdr += src->sadb_address_len; 2608 2609 if (isrc != NULL) { 2610 bcopy(isrc, nexthdr, SADB_64TO8(isrc->sadb_address_len)); 2611 free(isrc); 2612 isrc = (struct sadb_address *)nexthdr; 2613 isrc->sadb_address_proto = iproto; 2614 ((struct sockaddr_in6 *)(isrc + 1))->sin6_port = 2615 htons(isrcport); 2616 nexthdr += isrc->sadb_address_len; 2617 } 2618 2619 if (idst != NULL) { 2620 bcopy(idst, nexthdr, SADB_64TO8(idst->sadb_address_len)); 2621 free(idst); 2622 idst = (struct sadb_address *)nexthdr; 2623 idst->sadb_address_proto = iproto; 2624 ((struct sockaddr_in6 *)(idst + 1))->sin6_port = 2625 htons(idstport); 2626 nexthdr += idst->sadb_address_len; 2627 } 2628 2629 if (cflag) { 2630 /* 2631 * Assume the checked cmd would have worked if it was actually 2632 * used. doaddresses() will increment lines_added if it 2633 * succeeds. 2634 */ 2635 lines_added++; 2636 } else { 2637 doaddresses((cmd == CMD_ADD) ? SADB_ADD : SADB_UPDATE, satype, 2638 cmd, srchp, dsthp, src, dst, unspec_src, buffer, totallen, 2639 spi, ebuf); 2640 } 2641 2642 if (isrchp != NULL && isrchp != &dummy.he) 2643 freehostent(isrchp); 2644 if (idsthp != NULL && idsthp != &dummy.he) 2645 freehostent(idsthp); 2646 if (srchp != NULL && srchp != &dummy.he) 2647 freehostent(srchp); 2648 if (dsthp != NULL && dsthp != &dummy.he) 2649 freehostent(dsthp); 2650 if (natt_lhp != NULL && natt_lhp != &dummy.he) 2651 freehostent(natt_lhp); 2652 if (natt_rhp != NULL && natt_rhp != &dummy.he) 2653 freehostent(natt_rhp); 2654 2655 free(ebuf); 2656 free(buffer); 2657 } 2658 2659 /* 2660 * DELETE and GET are similar, in that they only need the extensions 2661 * required to _find_ an SA, and then either delete it or obtain its 2662 * information. 2663 */ 2664 static void 2665 dodelget(int cmd, int satype, char *argv[], char *ebuf) 2666 { 2667 struct sadb_msg *msg = (struct sadb_msg *)get_buffer; 2668 uint64_t *nextext; 2669 struct sadb_sa *assoc = NULL; 2670 struct sadb_address *src = NULL, *dst = NULL; 2671 int next, token, sa_len; 2672 char *thiscmd; 2673 uint32_t spi; 2674 struct hostent *srchp = NULL, *dsthp = NULL; 2675 struct sockaddr_in6 *sin6; 2676 boolean_t unspec_src = B_TRUE; 2677 uint16_t srcport = 0, dstport = 0; 2678 uint8_t proto = 0; 2679 char *ep = NULL; 2680 2681 msg_init(msg, ((cmd == CMD_GET) ? SADB_GET : SADB_DELETE), 2682 (uint8_t)satype); 2683 /* Set the first extension header to right past the base message. */ 2684 nextext = (uint64_t *)(msg + 1); 2685 bzero(nextext, sizeof (get_buffer) - sizeof (*msg)); 2686 2687 thiscmd = (cmd == CMD_GET) ? "get" : "delete"; 2688 2689 #define ALLOC_ADDR_EXT(ext, exttype) \ 2690 (ext) = (struct sadb_address *)nextext; \ 2691 nextext = (uint64_t *)((ext) + 1); \ 2692 nextext += SADB_8TO64(roundup(sa_len, 8)); \ 2693 (ext)->sadb_address_exttype = exttype; \ 2694 (ext)->sadb_address_len = nextext - ((uint64_t *)ext); 2695 2696 /* Assume last element in argv is set to NULL. */ 2697 do { 2698 token = parseextval(*argv, &next); 2699 argv++; 2700 switch (token) { 2701 case TOK_EOF: 2702 /* Do nothing, I'm done. */ 2703 break; 2704 case TOK_UNKNOWN: 2705 ERROR1(ep, ebuf, gettext( 2706 "Unknown extension field \"%s\"\n"), *(argv - 1)); 2707 break; 2708 case TOK_SPI: 2709 if (assoc != NULL) { 2710 ERROR(ep, ebuf, gettext( 2711 "Can only specify single SPI value.\n")); 2712 break; 2713 } 2714 assoc = (struct sadb_sa *)nextext; 2715 nextext = (uint64_t *)(assoc + 1); 2716 assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc)); 2717 assoc->sadb_sa_exttype = SADB_EXT_SA; 2718 assoc->sadb_sa_spi = htonl((uint32_t)parsenum(*argv, 2719 B_TRUE, ebuf)); 2720 spi = assoc->sadb_sa_spi; 2721 argv++; 2722 break; 2723 case TOK_SRCPORT: 2724 if (srcport != 0) { 2725 ERROR(ep, ebuf, gettext( 2726 "Can only specify single source port.\n")); 2727 break; 2728 } 2729 srcport = parsenum(*argv, B_TRUE, ebuf); 2730 argv++; 2731 break; 2732 case TOK_DSTPORT: 2733 if (dstport != 0) { 2734 ERROR(ep, ebuf, gettext( 2735 "Can only " 2736 "specify single destination port.\n")); 2737 break; 2738 } 2739 dstport = parsenum(*argv, B_TRUE, ebuf); 2740 argv++; 2741 break; 2742 case TOK_PROTO: 2743 if (proto != 0) { 2744 ERROR(ep, ebuf, gettext( 2745 "Can only specify single protocol.\n")); 2746 break; 2747 } 2748 proto = parsenum(*argv, B_TRUE, ebuf); 2749 argv++; 2750 break; 2751 case TOK_SRCADDR: 2752 case TOK_SRCADDR6: 2753 if (src != NULL) { 2754 ERROR(ep, ebuf, gettext( 2755 "Can only specify single source addr.\n")); 2756 break; 2757 } 2758 sa_len = parseaddr(*argv, &srchp, 2759 (token == TOK_SRCADDR6), ebuf); 2760 if (srchp == NULL) { 2761 ERROR1(ep, ebuf, gettext( 2762 "Unknown source address \"%s\"\n"), *argv); 2763 break; 2764 } 2765 argv++; 2766 2767 unspec_src = B_FALSE; 2768 2769 ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC); 2770 2771 if (srchp == &dummy.he) { 2772 /* 2773 * Single address with -n flag. 2774 */ 2775 sin6 = (struct sockaddr_in6 *)(src + 1); 2776 bzero(sin6, sizeof (*sin6)); 2777 sin6->sin6_family = AF_INET6; 2778 bcopy(srchp->h_addr_list[0], &sin6->sin6_addr, 2779 sizeof (struct in6_addr)); 2780 } 2781 /* The rest is pre-bzeroed for us. */ 2782 break; 2783 case TOK_DSTADDR: 2784 case TOK_DSTADDR6: 2785 if (dst != NULL) { 2786 ERROR(ep, ebuf, gettext( 2787 "Can only specify single destination " 2788 "address.\n")); 2789 break; 2790 } 2791 sa_len = parseaddr(*argv, &dsthp, 2792 (token == TOK_SRCADDR6), ebuf); 2793 if (dsthp == NULL) { 2794 ERROR1(ep, ebuf, gettext( 2795 "Unknown destination address \"%s\"\n"), 2796 *argv); 2797 break; 2798 } 2799 argv++; 2800 2801 ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST); 2802 2803 if (dsthp == &dummy.he) { 2804 /* 2805 * Single address with -n flag. 2806 */ 2807 sin6 = (struct sockaddr_in6 *)(dst + 1); 2808 bzero(sin6, sizeof (*sin6)); 2809 sin6->sin6_family = AF_INET6; 2810 bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr, 2811 sizeof (struct in6_addr)); 2812 } 2813 /* The rest is pre-bzeroed for us. */ 2814 break; 2815 default: 2816 ERROR2(ep, ebuf, gettext( 2817 "Don't use extension %s for '%s' command.\n"), 2818 *(argv - 1), thiscmd); 2819 break; 2820 } 2821 } while (token != TOK_EOF); 2822 2823 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 2824 2825 if ((srcport != 0) && (src == NULL)) { 2826 ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC); 2827 sin6 = (struct sockaddr_in6 *)(src + 1); 2828 src->sadb_address_proto = proto; 2829 bzero(sin6, sizeof (*sin6)); 2830 sin6->sin6_family = AF_INET6; 2831 sin6->sin6_port = htons(srcport); 2832 } 2833 2834 if ((dstport != 0) && (dst == NULL)) { 2835 ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST); 2836 sin6 = (struct sockaddr_in6 *)(dst + 1); 2837 src->sadb_address_proto = proto; 2838 bzero(sin6, sizeof (*sin6)); 2839 sin6->sin6_family = AF_INET6; 2840 sin6->sin6_port = htons(dstport); 2841 } 2842 2843 /* So I have enough of the message to send it down! */ 2844 msg->sadb_msg_len = nextext - get_buffer; 2845 2846 if (assoc == NULL) { 2847 FATAL1(ep, ebuf, gettext( 2848 "Need SA parameters for %s.\n"), thiscmd); 2849 } 2850 2851 if (cflag) { 2852 /* 2853 * Assume the checked cmd would have worked if it was actually 2854 * used. doaddresses() will increment lines_added if it 2855 * succeeds. 2856 */ 2857 lines_added++; 2858 } else { 2859 doaddresses((cmd == CMD_GET) ? SADB_GET : SADB_DELETE, satype, 2860 cmd, srchp, dsthp, src, dst, unspec_src, get_buffer, 2861 sizeof (get_buffer), spi, NULL); 2862 } 2863 2864 if (srchp != NULL && srchp != &dummy.he) 2865 freehostent(srchp); 2866 if (dsthp != NULL && dsthp != &dummy.he) 2867 freehostent(dsthp); 2868 } 2869 2870 /* 2871 * "ipseckey monitor" should exit very gracefully if ^C is tapped. 2872 */ 2873 static void 2874 monitor_catch(int signal) 2875 { 2876 errx(signal, gettext("Bailing on signal %d."), signal); 2877 } 2878 2879 /* 2880 * Loop forever, listening on PF_KEY messages. 2881 */ 2882 static void 2883 domonitor(boolean_t passive) 2884 { 2885 struct sadb_msg *samsg; 2886 int rc; 2887 2888 /* Catch ^C. */ 2889 (void) signal(SIGINT, monitor_catch); 2890 2891 samsg = (struct sadb_msg *)get_buffer; 2892 if (!passive) { 2893 (void) printf(gettext("Actively")); 2894 msg_init(samsg, SADB_X_PROMISC, 1); /* Turn ON promisc. */ 2895 rc = key_write(keysock, samsg, sizeof (*samsg)); 2896 if (rc == -1) 2897 Bail("write (SADB_X_PROMISC)"); 2898 } else { 2899 (void) printf(gettext("Passively")); 2900 } 2901 (void) printf(gettext(" monitoring the PF_KEY socket.\n")); 2902 2903 for (; ; ) { 2904 /* 2905 * I assume that read() is non-blocking, and will never 2906 * return 0. 2907 */ 2908 rc = read(keysock, samsg, sizeof (get_buffer)); 2909 if (rc == -1) 2910 Bail("read (in domonitor)"); 2911 (void) printf(gettext("Read %d bytes.\n"), rc); 2912 /* 2913 * Q: Should I use the same method of printing as GET does? 2914 * A: For now, yes. 2915 */ 2916 print_samsg(stdout, get_buffer, B_TRUE, vflag, nflag); 2917 (void) putchar('\n'); 2918 } 2919 } 2920 2921 /* 2922 * Either mask or unmask all relevant signals. 2923 */ 2924 static void 2925 mask_signals(boolean_t unmask) 2926 { 2927 sigset_t set; 2928 static sigset_t oset; 2929 2930 if (unmask) { 2931 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 2932 } else { 2933 (void) sigfillset(&set); 2934 (void) sigprocmask(SIG_SETMASK, &set, &oset); 2935 } 2936 } 2937 2938 /* 2939 * Assorted functions to print help text. 2940 */ 2941 #define puts_tr(s) (void) puts(gettext(s)) 2942 2943 static void 2944 doattrhelp() 2945 { 2946 int i; 2947 2948 puts_tr("\nSA attributes:"); 2949 2950 for (i = 0; tokens[i].string != NULL; i++) { 2951 if (i%3 == 0) 2952 (void) printf("\n"); 2953 (void) printf(" %-15.15s", tokens[i].string); 2954 } 2955 (void) printf("\n"); 2956 } 2957 2958 static void 2959 dohelpcmd(char *cmds) 2960 { 2961 int cmd; 2962 2963 if (strcmp(cmds, "attr") == 0) { 2964 doattrhelp(); 2965 return; 2966 } 2967 2968 cmd = parsecmd(cmds); 2969 switch (cmd) { 2970 case CMD_UPDATE: 2971 puts_tr("update - Update an existing SA"); 2972 break; 2973 case CMD_ADD: 2974 puts_tr("add - Add a new security association (SA)"); 2975 break; 2976 case CMD_DELETE: 2977 puts_tr("delete - Delete an SA"); 2978 break; 2979 case CMD_GET: 2980 puts_tr("get - Display an SA"); 2981 break; 2982 case CMD_FLUSH: 2983 puts_tr("flush - Delete all SAs"); 2984 break; 2985 case CMD_DUMP: 2986 puts_tr("dump - Display all SAs"); 2987 break; 2988 case CMD_MONITOR: 2989 puts_tr("monitor - Monitor all PF_KEY reply messages."); 2990 break; 2991 case CMD_PMONITOR: 2992 puts_tr( 2993 "pmonitor, passive_monitor - Monitor PF_KEY messages that"); 2994 puts_tr( 2995 " reply to all PF_KEY sockets."); 2996 break; 2997 2998 case CMD_QUIT: 2999 puts_tr("quit, exit - Exit the program"); 3000 break; 3001 case CMD_SAVE: 3002 puts_tr("save - Saves all SAs to a file"); 3003 break; 3004 case CMD_HELP: 3005 puts_tr("help - Display list of commands"); 3006 puts_tr("help <cmd> - Display help for command"); 3007 puts_tr("help attr - Display possible SA attributes"); 3008 break; 3009 default: 3010 (void) printf(gettext("%s: Unknown command\n"), cmds); 3011 break; 3012 } 3013 } 3014 3015 3016 static void 3017 dohelp(char *cmds) 3018 { 3019 if (cmds != NULL) { 3020 dohelpcmd(cmds); 3021 return; 3022 } 3023 puts_tr("Commands"); 3024 puts_tr("--------"); 3025 puts_tr("?, help - Display this list"); 3026 puts_tr("help <cmd> - Display help for command"); 3027 puts_tr("help attr - Display possible SA attributes"); 3028 puts_tr("quit, exit - Exit the program"); 3029 puts_tr("monitor - Monitor all PF_KEY reply messages."); 3030 puts_tr("pmonitor, passive_monitor - Monitor PF_KEY messages that"); 3031 puts_tr(" reply to all PF_KEY sockets."); 3032 puts_tr(""); 3033 puts_tr("The following commands are of the form:"); 3034 puts_tr(" <command> {SA type} {attribute value}*"); 3035 puts_tr(""); 3036 puts_tr("add (interactive only) - Add a new security association (SA)"); 3037 puts_tr("update (interactive only) - Update an existing SA"); 3038 puts_tr("delete - Delete an SA"); 3039 puts_tr("get - Display an SA"); 3040 puts_tr("flush - Delete all SAs"); 3041 puts_tr("dump - Display all SAs"); 3042 puts_tr("save - Saves all SAs to a file"); 3043 } 3044 3045 /* 3046 * "Parse" a command line from argv. 3047 */ 3048 static void 3049 parseit(int argc, char *argv[], char *ebuf, boolean_t read_cmdfile) 3050 { 3051 int cmd, satype; 3052 char *ep = NULL; 3053 3054 if (argc == 0) 3055 return; 3056 cmd = parsecmd(*argv++); 3057 3058 /* 3059 * Some commands loop forever and should only be run from the command 3060 * line, they should never be run from a command file as this may 3061 * be used at boot time. 3062 */ 3063 switch (cmd) { 3064 case CMD_HELP: 3065 if (read_cmdfile) 3066 ERROR(ep, ebuf, gettext("Help not appropriate in " 3067 "config file.")); 3068 else 3069 dohelp(*argv); 3070 return; 3071 case CMD_MONITOR: 3072 if (read_cmdfile) 3073 ERROR(ep, ebuf, gettext("Monitor not appropriate in " 3074 "config file.")); 3075 else 3076 domonitor(B_FALSE); 3077 break; 3078 case CMD_PMONITOR: 3079 if (read_cmdfile) 3080 ERROR(ep, ebuf, gettext("Monitor not appropriate in " 3081 "config file.")); 3082 else 3083 domonitor(B_TRUE); 3084 break; 3085 case CMD_QUIT: 3086 EXIT_OK(NULL); 3087 } 3088 3089 handle_errors(ep, ebuf, B_FALSE, B_FALSE); 3090 3091 satype = parsesatype(*argv, ebuf); 3092 3093 if (satype != SADB_SATYPE_UNSPEC) { 3094 argv++; 3095 } else { 3096 /* 3097 * You must specify either "all" or a specific SA type 3098 * for the "save" command. 3099 */ 3100 if (cmd == CMD_SAVE) 3101 if (*argv == NULL) { 3102 FATAL(ep, ebuf, gettext( 3103 "Must specify a specific " 3104 "SA type for save.\n")); 3105 } else { 3106 argv++; 3107 } 3108 } 3109 3110 switch (cmd) { 3111 case CMD_FLUSH: 3112 if (!cflag) 3113 doflush(satype); 3114 /* 3115 * If this was called because of an entry in a cmd file 3116 * then this action needs to be counted to prevent 3117 * do_interactive() treating this as an error. 3118 */ 3119 lines_added++; 3120 break; 3121 case CMD_ADD: 3122 case CMD_UPDATE: 3123 /* 3124 * NOTE: Shouldn't allow ADDs or UPDATEs with keying material 3125 * from the command line. 3126 */ 3127 if (!interactive) { 3128 errx(1, gettext( 3129 "can't do ADD or UPDATE from the command line.\n")); 3130 } 3131 if (satype == SADB_SATYPE_UNSPEC) { 3132 FATAL(ep, ebuf, gettext( 3133 "Must specify a specific SA type.")); 3134 /* NOTREACHED */ 3135 } 3136 /* Parse for extensions, including keying material. */ 3137 doaddup(cmd, satype, argv, ebuf); 3138 break; 3139 case CMD_DELETE: 3140 case CMD_GET: 3141 if (satype == SADB_SATYPE_UNSPEC) { 3142 FATAL(ep, ebuf, gettext( 3143 "Must specify a single SA type.")); 3144 /* NOTREACHED */ 3145 } 3146 /* Parse for bare minimum to locate an SA. */ 3147 dodelget(cmd, satype, argv, ebuf); 3148 break; 3149 case CMD_DUMP: 3150 if (read_cmdfile) 3151 ERROR(ep, ebuf, gettext("Dump not appropriate in " 3152 "config file.")); 3153 else 3154 dodump(satype, NULL); 3155 break; 3156 case CMD_SAVE: 3157 if (read_cmdfile) { 3158 ERROR(ep, ebuf, gettext("Save not appropriate in " 3159 "config file.")); 3160 } else { 3161 mask_signals(B_FALSE); /* Mask signals */ 3162 dodump(satype, opensavefile(argv[0])); 3163 mask_signals(B_TRUE); /* Unmask signals */ 3164 } 3165 break; 3166 default: 3167 warnx(gettext("Unknown command (%s).\n"), 3168 *(argv - ((satype == SADB_SATYPE_UNSPEC) ? 1 : 2))); 3169 usage(); 3170 } 3171 handle_errors(ep, ebuf, B_FALSE, B_FALSE); 3172 } 3173 3174 int 3175 main(int argc, char *argv[]) 3176 { 3177 int ch; 3178 FILE *infile = stdin, *savefile; 3179 boolean_t dosave = B_FALSE, readfile = B_FALSE; 3180 char *configfile = NULL; 3181 3182 (void) setlocale(LC_ALL, ""); 3183 #if !defined(TEXT_DOMAIN) 3184 #define TEXT_DOMAIN "SYS_TEST" 3185 #endif 3186 (void) textdomain(TEXT_DOMAIN); 3187 3188 /* 3189 * Check to see if the command is being run from smf(5). 3190 */ 3191 my_fmri = getenv("SMF_FMRI"); 3192 3193 openlog("ipseckey", LOG_CONS, LOG_AUTH); 3194 if (getuid() != 0) { 3195 errx(1, "Insufficient privileges to run ipseckey."); 3196 } 3197 3198 /* umask me to paranoid, I only want to create files read-only */ 3199 (void) umask((mode_t)00377); 3200 3201 while ((ch = getopt(argc, argv, "pnvf:s:c:")) != EOF) 3202 switch (ch) { 3203 case 'p': 3204 pflag = B_TRUE; 3205 break; 3206 case 'n': 3207 nflag = B_TRUE; 3208 break; 3209 case 'v': 3210 vflag = B_TRUE; 3211 break; 3212 case 'c': 3213 cflag = B_TRUE; 3214 /* FALLTHRU */ 3215 case 'f': 3216 if (dosave) 3217 usage(); 3218 infile = fopen(optarg, "r"); 3219 if (infile == NULL) { 3220 EXIT_BADCONFIG2("Unable to open configuration " 3221 "file: %s\n", optarg); 3222 } 3223 configfile = strdup(optarg); 3224 readfile = B_TRUE; 3225 break; 3226 case 's': 3227 if (readfile) 3228 usage(); 3229 dosave = B_TRUE; 3230 savefile = opensavefile(optarg); 3231 break; 3232 default: 3233 usage(); 3234 } 3235 3236 argc -= optind; 3237 argv += optind; 3238 3239 mypid = getpid(); 3240 3241 keysock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 3242 3243 if (keysock == -1) { 3244 if (errno == EPERM) { 3245 EXIT_BADPERM("Insufficient privileges to open " 3246 "PF_KEY socket.\n"); 3247 } else { 3248 /* some other reason */ 3249 EXIT_FATAL("Opening PF_KEY socket"); 3250 } 3251 } 3252 3253 if (dosave) { 3254 mask_signals(B_FALSE); /* Mask signals */ 3255 dodump(SADB_SATYPE_UNSPEC, savefile); 3256 mask_signals(B_TRUE); /* Unmask signals */ 3257 EXIT_OK(NULL); 3258 } 3259 3260 /* 3261 * When run from smf(5) flush any existing SA's first 3262 * otherwise you will end up in maintenance mode. 3263 */ 3264 if ((my_fmri != NULL) && readfile) { 3265 (void) fprintf(stdout, gettext( 3266 "Flushing existing SA's before adding new SA's\n")); 3267 (void) fflush(stdout); 3268 doflush(SADB_SATYPE_UNSPEC); 3269 } 3270 if (infile != stdin || *argv == NULL) { 3271 /* Go into interactive mode here. */ 3272 do_interactive(infile, configfile, "ipseckey> ", my_fmri, 3273 parseit); 3274 } 3275 parseit(argc, argv, NULL, B_FALSE); 3276 3277 return (0); 3278 } 3279