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