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