1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <strings.h> 32 #include <stropts.h> 33 #include <fcntl.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <ctype.h> 38 #include <arpa/inet.h> 39 #include <locale.h> 40 #include <syslog.h> 41 #include <pwd.h> 42 #include <sys/param.h> 43 #include <sys/sysmacros.h> /* MIN, MAX */ 44 #include <sys/sockio.h> 45 #include <net/pfkeyv2.h> 46 #include <net/pfpolicy.h> 47 #include <inet/ipsec_impl.h> 48 #include <signal.h> 49 #include <errno.h> 50 #include <netdb.h> 51 #include <sys/socket.h> 52 #include <sys/systeminfo.h> 53 #include <nss_dbdefs.h> /* NSS_BUFLEN_HOSTS */ 54 #include <netinet/in.h> 55 #include <assert.h> 56 #include <inet/ip.h> 57 #include <ipsec_util.h> 58 #include <netinet/in_systm.h> 59 #include <netinet/ip_icmp.h> 60 #include <netinet/icmp6.h> 61 62 /* 63 * Globals 64 */ 65 int lfd; 66 char *my_fmri; 67 FILE *debugfile = stderr; 68 69 #define USAGE() if (!smf_managed) usage() 70 /* 71 * Buffer length to read in pattern/properties. 72 */ 73 #define MAXLEN 1024 74 75 /* Max length of tunnel interface string identifier */ 76 #define TUNNAMEMAXLEN LIFNAMSIZ 77 78 /* 79 * Used by parse_one and parse/parse_action to communicate 80 * the errors. -1 is failure, which is not defined here. 81 */ 82 enum parse_errors {PARSE_SUCCESS, PARSE_EOF}; 83 84 /* 85 * For spdsock_get_ext() diagnostics. 86 */ 87 #define SPDSOCK_DIAG_BUF_LEN 128 88 static char spdsock_diag_buf[SPDSOCK_DIAG_BUF_LEN]; 89 90 /* 91 * Define CURL here so that while you are reading 92 * this code, it does not affect "vi" in pattern 93 * matching. 94 */ 95 #define CURL_BEGIN '{' 96 #define CURL_END '}' 97 #define BACK_SLASH '\\' 98 #define MAXARGS 20 99 #define NOERROR 0 100 101 /* 102 * IPSEC_CONF_ADD should start with 1, so that when multiple commands 103 * are given, we can fail the request. 104 */ 105 106 enum ipsec_cmds {IPSEC_CONF_ADD = 1, IPSEC_CONF_DEL, IPSEC_CONF_VIEW, 107 IPSEC_CONF_FLUSH, IPSEC_CONF_LIST, IPSEC_CONF_SUB}; 108 109 static const char policy_conf_file[] = "/var/run/ipsecpolicy.conf"; 110 static const char lock_file[] = "/var/run/ipsecconf.lock"; 111 static const char index_tag[] = "#INDEX"; 112 113 #define POLICY_CONF_FILE policy_conf_file 114 #define LOCK_FILE lock_file 115 #define INDEX_TAG index_tag 116 117 /* 118 * Valid algorithm length. 119 */ 120 #define VALID_ALG_LEN 40 121 122 /* Types of Error messages */ 123 typedef enum error_type {BAD_ERROR, DUP_ERROR, REQ_ERROR} error_type_t; 124 125 /* Error message human readable conversions */ 126 static char *sys_error_message(int); 127 static void error_message(error_type_t, int, int); 128 static int get_pf_pol_socket(void); 129 130 static int cmd; 131 static char *filename; 132 static char lo_buf[MAXLEN]; /* Leftover buffer */ 133 134 /* 135 * The new SPD_EXT_TUN_NAME extension has a tunnel name in it. Use the empty 136 * string ("", stored in the char value "all_polheads") for all policy heads 137 * (global and all tunnels). Set interface_name to NULL for global-only, or 138 * specify a name of an IP-in-IP tunnel. 139 */ 140 static char *interface_name; 141 static char all_polheads; /* So we can easily get "". */ 142 143 /* Error reporting stuff */ 144 #define CBUF_LEN 4096 /* Maximum size of the cmd */ 145 /* 146 * Following are used for reporting errors with arguments. 147 * We store the line numbers of each argument as we parse them, 148 * so that the error reporting is more specific. We can have only 149 * (MAXARGS - 1) arguments between any pair of CURL_BEGIN CURL_END. 150 * Because a single command can be made up of multiple action/property 151 * combinations, the maximum command size is (2 * (MAXARGS -1)) for each 152 * of patterns, properties and actions. 153 */ 154 #define ARG_BUF_LEN ((2 * 3 * (MAXARGS - 1)) + 1) 155 static int arg_indices[ARG_BUF_LEN]; 156 static int argindex; 157 static int linecount; 158 static char cbuf[CBUF_LEN]; /* Command buffer */ 159 static int cbuf_offset; 160 161 162 #define BYPASS_POLICY_BOOST 0x00800000 163 #define ESP_POLICY_BOOST 0x00400000 164 #define AH_POLICY_BOOST 0x00200000 165 #define INITIAL_BASE_PRIORITY 0x000fffff 166 167 /* 168 * the number used to order the 169 * rules starts at a certain base and 170 * goes down. i.e. rules earlier in 171 * the file are checked first 172 */ 173 static uint32_t priority = INITIAL_BASE_PRIORITY; 174 175 #define AH_AUTH 0 176 #define ESP_ENCR 1 177 #define ESP_AUTH 2 178 179 180 /* 181 * for deleting adds on error 182 */ 183 184 typedef struct d_list_s 185 { 186 struct d_list_s *next; 187 int index; 188 } d_list_t; 189 190 static d_list_t *d_list = NULL; 191 static d_list_t *d_tail = NULL; 192 193 194 /* 195 * Used for multi-homed source/dest hosts. 196 */ 197 static struct hostent *shp, *dhp; 198 static unsigned int splen, dplen; 199 static char tunif[TUNNAMEMAXLEN]; 200 static boolean_t has_saprefix, has_daprefix; 201 static uint32_t seq_cnt = 0; 202 203 /* lexxed out action and related properties */ 204 typedef struct ap_s 205 { 206 char *act; 207 char *prop[MAXARGS + 1]; 208 } ap_t; 209 210 211 /* one lexxed out rule */ 212 typedef struct act_prop_s { 213 char *pattern[MAXARGS + 1]; 214 ap_t ap[MAXARGS + 1]; 215 } act_prop_t; 216 217 typedef struct 218 { 219 uint8_t alg_id; 220 uint32_t alg_minbits; 221 uint32_t alg_maxbits; 222 } algreq_t; 223 224 /* structure to hold all information for one act_prop_t */ 225 typedef struct ips_act_props_s { 226 struct ips_act_props_s *iap_next; 227 struct ips_conf_s *iap_head; 228 229 /* 230 * IPsec action types (in SPD_ATTR_TYPE attribute) 231 * SPD_ACTTYPE_DROP 0x0001 232 * SPD_ACTTYPE_PASS 0x0002 233 * SPD_ACTTYPE_IPSEC 0x0003 234 */ 235 uint16_t iap_action; 236 uint16_t iap_act_tok; 237 238 /* 239 * Action ATTR flags (in SPD_ATTR_FLAGS attribute) 240 * SPD_APPLY_AH 0x0001 241 * SPD_APPLY_ESP 0x0002 242 * SPD_APPLY_SE 0x0004 * self-encapsulation * 243 * SPD_APPLY_COMP 0x0008 * compression; NYI * 244 * SPD_APPLY_UNIQUE 0x0010 * unique per-flow SA * 245 * SPD_APPLY_BYPASS 0x0020 * bypass policy * 246 */ 247 uint16_t iap_attr; 248 uint16_t iap_attr_tok[5]; 249 250 algreq_t iap_aauth; 251 algreq_t iap_eencr; 252 algreq_t iap_eauth; 253 254 uint32_t iap_life_soft_time; 255 uint32_t iap_life_hard_time; 256 uint32_t iap_life_soft_bytes; 257 uint32_t iap_life_hard_bytes; 258 259 } ips_act_props_t; 260 261 #define V4_PART_OF_V6(v6) v6._S6_un._S6_u32[3] 262 263 typedef struct ips_conf_s { 264 /* selector */ 265 uint16_t patt_tok[8]; 266 uint8_t has_saddr; 267 uint8_t has_daddr; 268 uint8_t has_smask; 269 uint8_t has_dmask; 270 uint8_t has_type; 271 uint8_t has_code; 272 uint8_t has_negotiate; 273 uint8_t has_tunnel; 274 uint16_t swap; 275 276 struct in6_addr ips_src_addr_v6; 277 struct in6_addr ips_src_mask_v6; 278 struct in6_addr ips_dst_addr_v6; 279 struct in6_addr ips_dst_mask_v6; 280 uint8_t ips_src_mask_len; 281 uint8_t ips_dst_mask_len; 282 in_port_t ips_src_port_min; 283 in_port_t ips_src_port_max; 284 in_port_t ips_dst_port_min; 285 in_port_t ips_dst_port_max; 286 uint8_t ips_icmp_type; 287 uint8_t ips_icmp_type_end; 288 uint8_t ips_icmp_code; 289 uint8_t ips_icmp_code_end; 290 uint8_t ips_ulp_prot; 291 uint8_t ips_ipsec_prot; 292 uint8_t ips_isv4; 293 /* 294 * SPD_RULE_FLAG_INBOUND 0x0001 295 * SPD_RULE_FLAG_OUTBOUND 0x0002 296 */ 297 uint8_t ips_dir; 298 /* 299 * Keep track of tunnel separately due to explosion of ways to set 300 * inbound/outbound. 301 */ 302 boolean_t ips_tunnel; 303 uint64_t ips_policy_index; 304 uint32_t ips_act_cnt; 305 ips_act_props_t *ips_acts; 306 } ips_conf_t; 307 308 #define ips_src_addr V4_PART_OF_V6(ips_src_addr_v6) 309 #define ips_dst_addr V4_PART_OF_V6(ips_dst_addr_v6) 310 311 static int ipsecconf_nflag; /* Used only with -l option */ 312 static int ipsecconf_qflag; /* Used only with -a|-r option */ 313 314 typedef struct str_val { 315 const char *string; 316 int value; 317 } str_val_t; 318 319 typedef struct str_tval { 320 const char *string; 321 int tok_val; 322 int value; 323 } str_tval_t; 324 325 static int parse_int(const char *); 326 static int parse_index(const char *, char *); 327 static int attach_tunname(spd_if_t *); 328 static void usage(void); 329 static int ipsec_conf_del(int, boolean_t); 330 static int ipsec_conf_add(boolean_t, boolean_t); 331 static int ipsec_conf_sub(void); 332 static int ipsec_conf_flush(int); 333 static int ipsec_conf_view(void); 334 static int ipsec_conf_list(void); 335 static int lock(void); 336 static int unlock(int); 337 static int parse_one(FILE *, act_prop_t *); 338 static void reconfigure(); 339 static void in_prefixlentomask(unsigned int, uchar_t *); 340 static int in_getprefixlen(char *); 341 static int parse_address(int, char *); 342 #ifdef DEBUG_HEAVY 343 static void pfpol_msg_dump(spd_msg_t *msg, char *); 344 #endif /* DEBUG_HEAVY */ 345 static void print_pfpol_msg(spd_msg_t *); 346 static int pfp_delete_rule(uint64_t); 347 static void ipsec_conf_admin(uint8_t); 348 static void print_bit_range(int, int); 349 static void nuke_adds(); 350 351 #ifdef DEBUG 352 static void dump_conf(ips_conf_t *); 353 #endif 354 355 typedef struct 356 { 357 uint32_t id; 358 uint32_t minkeybits; 359 uint32_t maxkeybits; 360 uint32_t defkeybits; 361 uint32_t incr; 362 } alginfo_t; 363 364 static int ipsec_nalgs[3]; 365 static alginfo_t known_algs[3][256]; 366 367 #define IPS_SRC_MASK SPD_EXT_LCLADDR + 100 368 #define IPS_DST_MASK SPD_EXT_REMADDR + 100 369 370 /* 371 * if inbound, src=remote, dst=local 372 * if outbound, src=local, dst=remote 373 */ 374 375 #define TOK_saddr 1 376 #define TOK_daddr 2 377 #define TOK_sport 3 378 #define TOK_dport 4 379 #define TOK_smask 5 380 #define TOK_dmask 6 381 #define TOK_ulp 7 382 #define TOK_local 8 383 #define TOK_lport 9 384 #define TOK_remote 10 385 #define TOK_rport 11 386 #define TOK_dir 12 387 #define TOK_type 13 388 #define TOK_code 14 389 #define TOK_negotiate 15 390 #define TOK_tunnel 16 391 392 #define IPS_SA SPD_ATTR_END 393 #define IPS_DIR SPD_ATTR_EMPTY 394 #define IPS_NEG SPD_ATTR_NOP 395 396 397 static str_tval_t pattern_table[] = { 398 {"saddr", TOK_saddr, SPD_EXT_LCLADDR}, 399 {"src", TOK_saddr, SPD_EXT_LCLADDR}, 400 {"srcaddr", TOK_saddr, SPD_EXT_LCLADDR}, 401 {"daddr", TOK_daddr, SPD_EXT_REMADDR}, 402 {"dst", TOK_daddr, SPD_EXT_REMADDR}, 403 {"dstaddr", TOK_daddr, SPD_EXT_REMADDR}, 404 {"sport", TOK_sport, SPD_EXT_LCLPORT}, 405 {"dport", TOK_dport, SPD_EXT_REMPORT}, 406 {"smask", TOK_smask, IPS_SRC_MASK}, 407 {"dmask", TOK_dmask, IPS_DST_MASK}, 408 {"ulp", TOK_ulp, SPD_EXT_PROTO}, 409 {"proto", TOK_ulp, SPD_EXT_PROTO}, 410 {"local", TOK_local, SPD_EXT_LCLADDR}, 411 {"laddr", TOK_local, SPD_EXT_LCLADDR}, 412 {"lport", TOK_lport, SPD_EXT_LCLPORT}, 413 {"remote", TOK_remote, SPD_EXT_REMADDR}, 414 {"raddr", TOK_remote, SPD_EXT_REMADDR}, 415 {"rport", TOK_rport, SPD_EXT_REMPORT}, 416 {"dir", TOK_dir, IPS_DIR}, 417 {"type", TOK_type, SPD_EXT_ICMP_TYPECODE}, 418 {"code", TOK_code, SPD_EXT_ICMP_TYPECODE}, 419 {"negotiate", TOK_negotiate, IPS_NEG}, 420 {"tunnel", TOK_tunnel, SPD_EXT_TUN_NAME}, 421 {NULL, 0, 0}, 422 }; 423 424 #define TOK_apply 1 425 #define TOK_permit 2 426 #define TOK_ipsec 3 427 #define TOK_bypass 4 428 #define TOK_drop 5 429 #define TOK_or 6 430 431 static str_tval_t action_table[] = { 432 {"apply", TOK_apply, SPD_ACTTYPE_IPSEC}, 433 {"permit", TOK_permit, SPD_ACTTYPE_IPSEC}, 434 {"ipsec", TOK_ipsec, SPD_ACTTYPE_IPSEC}, 435 {"bypass", TOK_bypass, SPD_ACTTYPE_PASS}, 436 {"pass", TOK_bypass, SPD_ACTTYPE_PASS}, 437 {"drop", TOK_drop, SPD_ACTTYPE_DROP}, 438 {"or", TOK_or, 0}, 439 {NULL, 0, 0}, 440 }; 441 442 static str_val_t property_table[] = { 443 {"auth_algs", SPD_ATTR_AH_AUTH}, 444 {"encr_algs", SPD_ATTR_ESP_ENCR}, 445 {"encr_auth_algs", SPD_ATTR_ESP_AUTH}, 446 {"sa", IPS_SA}, 447 {"dir", IPS_DIR}, 448 {NULL, 0}, 449 }; 450 451 static str_val_t icmp_type_table[] = { 452 {"unreach", ICMP_UNREACH}, 453 {"echo", ICMP_ECHO}, 454 {"echorep", ICMP_ECHOREPLY}, 455 {"squench", ICMP_SOURCEQUENCH}, 456 {"redir", ICMP_REDIRECT}, 457 {"timex", ICMP_TIMXCEED}, 458 {"paramprob", ICMP_PARAMPROB}, 459 {"timest", ICMP_TSTAMP}, 460 {"timestrep", ICMP_TSTAMPREPLY}, 461 {"inforeq", ICMP_IREQ}, 462 {"inforep", ICMP_IREQREPLY}, 463 {"maskreq", ICMP_MASKREQ}, 464 {"maskrep", ICMP_MASKREPLY}, 465 {"unreach6", ICMP6_DST_UNREACH}, 466 {"pkttoobig6", ICMP6_PACKET_TOO_BIG}, 467 {"timex6", ICMP6_TIME_EXCEEDED}, 468 {"paramprob6", ICMP6_PARAM_PROB}, 469 {"echo6", ICMP6_ECHO_REQUEST}, 470 {"echorep6", ICMP6_ECHO_REPLY}, 471 {"router-sol6", ND_ROUTER_SOLICIT}, 472 {"router-ad6", ND_ROUTER_ADVERT}, 473 {"neigh-sol6", ND_NEIGHBOR_SOLICIT}, 474 {"neigh-ad6", ND_NEIGHBOR_ADVERT}, 475 {"redir6", ND_REDIRECT}, 476 {NULL, 0}, 477 }; 478 479 static str_val_t icmp_code_table[] = { 480 {"net-unr", ICMP_UNREACH_NET}, 481 {"host-unr", ICMP_UNREACH_HOST}, 482 {"proto-unr", ICMP_UNREACH_PROTOCOL}, 483 {"port-unr", ICMP_UNREACH_PORT}, 484 {"needfrag", ICMP_UNREACH_NEEDFRAG}, 485 {"srcfail", ICMP_UNREACH_SRCFAIL}, 486 {"net-unk", ICMP_UNREACH_NET_UNKNOWN}, 487 {"host-unk", ICMP_UNREACH_HOST_UNKNOWN}, 488 {"isolate", ICMP_UNREACH_ISOLATED}, 489 {"net-prohib", ICMP_UNREACH_NET_PROHIB}, 490 {"host-prohib", ICMP_UNREACH_HOST_PROHIB}, 491 {"net-tos", ICMP_UNREACH_TOSNET}, 492 {"host-tos", ICMP_UNREACH_TOSHOST}, 493 {"filter-prohib", ICMP_UNREACH_FILTER_PROHIB}, 494 {"host-preced", ICMP_UNREACH_HOST_PRECEDENCE}, 495 {"cutoff-preced", ICMP_UNREACH_PRECEDENCE_CUTOFF}, 496 {"no-route6", ICMP6_DST_UNREACH_NOROUTE}, 497 {"adm-prohib6", ICMP6_DST_UNREACH_ADMIN}, 498 {"addr-unr6", ICMP6_DST_UNREACH_ADDR}, 499 {"port-unr6", ICMP6_DST_UNREACH_NOPORT}, 500 {"hop-limex6", ICMP6_TIME_EXCEED_TRANSIT}, 501 {"frag-re-timex6", ICMP6_TIME_EXCEED_REASSEMBLY}, 502 {"err-head6", ICMP6_PARAMPROB_HEADER}, 503 {"unrec-head6", ICMP6_PARAMPROB_NEXTHEADER}, 504 {"unreq-opt6", ICMP6_PARAMPROB_OPTION}, 505 {NULL, 0}, 506 }; 507 508 static sigset_t set, oset; 509 510 511 static boolean_t 512 add_index(int index) 513 { 514 d_list_t *temp = malloc(sizeof (d_list_t)); 515 516 if (temp == NULL) { 517 warn("malloc"); 518 return (B_TRUE); 519 } 520 521 temp->index = index; 522 temp->next = NULL; 523 524 if (d_tail == NULL) { 525 d_list = d_tail = temp; 526 return (B_FALSE); 527 } 528 529 d_tail->next = temp; 530 d_tail = temp; 531 532 return (B_FALSE); 533 } 534 535 static int 536 block_all_signals() 537 { 538 if (sigfillset(&set) == -1) { 539 warn("sigfillset"); 540 return (-1); 541 } 542 if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) { 543 warn("sigprocmask"); 544 return (-1); 545 } 546 return (0); 547 } 548 549 static int 550 restore_all_signals() 551 { 552 if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) { 553 warn("sigprocmask"); 554 return (-1); 555 } 556 return (0); 557 } 558 559 /* allocate an ips_act_props_t and link it in correctly */ 560 static ips_act_props_t * 561 alloc_iap(ips_conf_t *parent) 562 { 563 ips_act_props_t *ret; 564 ips_act_props_t *next = parent->ips_acts; 565 ips_act_props_t *current = NULL; 566 567 ret = (ips_act_props_t *)calloc(sizeof (ips_act_props_t), 1); 568 569 if (ret == NULL) 570 return (NULL); 571 572 ret->iap_head = parent; 573 574 while (next != NULL) { 575 current = next; 576 next = next->iap_next; 577 } 578 579 if (current != NULL) 580 current->iap_next = ret; 581 else 582 parent->ips_acts = ret; 583 584 parent->ips_act_cnt++; 585 586 return (ret); 587 } 588 589 /* 590 * This function exit()s if it fails. 591 */ 592 static void 593 fetch_algorithms() 594 { 595 struct spd_msg msg; 596 struct spd_ext_actions *actp; 597 struct spd_attribute *attr, *endattr; 598 spd_ext_t *exts[SPD_EXT_MAX+1]; 599 uint64_t reply_buf[256]; 600 int sfd; 601 int cnt, retval; 602 uint64_t *start, *end; 603 alginfo_t alg = {0, 0, 0, 0, 0}; 604 uint_t algtype; 605 static boolean_t has_run = B_FALSE; 606 607 if (has_run) 608 return; 609 else 610 has_run = B_TRUE; 611 612 sfd = get_pf_pol_socket(); 613 if (sfd < 0) { 614 err(-1, gettext("unable to open policy socket")); 615 } 616 617 (void) memset(&msg, 0, sizeof (msg)); 618 msg.spd_msg_version = PF_POLICY_V1; 619 msg.spd_msg_type = SPD_ALGLIST; 620 msg.spd_msg_len = SPD_8TO64(sizeof (msg)); 621 622 cnt = write(sfd, &msg, sizeof (msg)); 623 if (cnt != sizeof (msg)) { 624 if (cnt < 0) { 625 err(-1, gettext("alglist failed: write")); 626 } else { 627 errx(-1, gettext("alglist failed: short write")); 628 } 629 } 630 631 cnt = read(sfd, reply_buf, sizeof (reply_buf)); 632 633 retval = spdsock_get_ext(exts, (spd_msg_t *)reply_buf, SPD_8TO64(cnt), 634 spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN); 635 636 if (retval == KGE_LEN && exts[0]->spd_ext_len == 0) { 637 /* 638 * No algorithms are defined in the kernel, which caused 639 * the extension length to be zero, and spdsock_get_ext() 640 * to fail with a KGE_LEN error. This is not an error 641 * condition, so we return nicely. 642 */ 643 return; 644 } else if (retval != 0) { 645 if (strlen(spdsock_diag_buf) != 0) 646 warnx(spdsock_diag_buf); 647 err(1, gettext("fetch_algorithms failed")); 648 } 649 650 if (!exts[SPD_EXT_ACTION]) { 651 errx(1, gettext("fetch_algorithms: action missing?!")); 652 } 653 654 actp = (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 655 start = (uint64_t *)actp; 656 end = (start + actp->spd_actions_len); 657 endattr = (struct spd_attribute *)end; 658 attr = (struct spd_attribute *)&actp[1]; 659 660 algtype = 0; 661 662 while (attr < endattr) { 663 switch (attr->spd_attr_tag) { 664 case SPD_ATTR_NOP: 665 case SPD_ATTR_EMPTY: 666 break; 667 case SPD_ATTR_END: 668 attr = endattr; 669 /* FALLTHRU */ 670 case SPD_ATTR_NEXT: 671 known_algs[algtype][ipsec_nalgs[algtype]] = alg; 672 ipsec_nalgs[algtype]++; 673 break; 674 675 case SPD_ATTR_ENCR_MINBITS: 676 case SPD_ATTR_AH_MINBITS: 677 case SPD_ATTR_ESPA_MINBITS: 678 alg.minkeybits = attr->spd_attr_value; 679 break; 680 681 case SPD_ATTR_ENCR_MAXBITS: 682 case SPD_ATTR_AH_MAXBITS: 683 case SPD_ATTR_ESPA_MAXBITS: 684 alg.maxkeybits = attr->spd_attr_value; 685 break; 686 687 case SPD_ATTR_ENCR_DEFBITS: 688 case SPD_ATTR_AH_DEFBITS: 689 case SPD_ATTR_ESPA_DEFBITS: 690 alg.defkeybits = attr->spd_attr_value; 691 break; 692 693 case SPD_ATTR_ENCR_INCRBITS: 694 case SPD_ATTR_AH_INCRBITS: 695 case SPD_ATTR_ESPA_INCRBITS: 696 alg.incr = attr->spd_attr_value; 697 break; 698 699 case SPD_ATTR_AH_AUTH: 700 case SPD_ATTR_ESP_AUTH: 701 case SPD_ATTR_ESP_ENCR: 702 alg.id = attr->spd_attr_value; 703 algtype = attr->spd_attr_tag - SPD_ATTR_AH_AUTH; 704 break; 705 } 706 attr++; 707 } 708 709 (void) close(sfd); 710 } 711 712 /* data dependant transform (act_cnt) */ 713 #define ATTR(ap, tag, value) \ 714 do { (ap)->spd_attr_tag = (tag); \ 715 (ap)->spd_attr_value = (value); \ 716 ap++; } while (0) 717 718 static struct spd_attribute * 719 emit_alg(struct spd_attribute *ap, int type, const algreq_t *ar, 720 int algattr, int minbitattr, int maxbitattr) 721 { 722 int id = ar->alg_id; 723 int minbits, i; 724 725 if (id != 0) { 726 /* LINTED E_CONST_COND */ 727 ATTR(ap, algattr, ar->alg_id); 728 729 minbits = ar->alg_minbits; 730 if (minbits == 0) { 731 for (i = 0; i < ipsec_nalgs[type]; i++) { 732 if (known_algs[type][i].id == id) 733 break; 734 } 735 if (i < ipsec_nalgs[type]) 736 minbits = known_algs[type][i].defkeybits; 737 } 738 if (minbits != 0) 739 /* LINTED E_CONST_COND */ 740 ATTR(ap, minbitattr, minbits); 741 if (ar->alg_maxbits != SPD_MAX_MAXBITS) 742 /* LINTED E_CONST_COND */ 743 ATTR(ap, maxbitattr, ar->alg_maxbits); 744 } 745 746 return (ap); 747 } 748 749 750 751 static struct spd_attribute * 752 ips_act_props_to_action(struct spd_attribute *ap, uint32_t *rule_priorityp, 753 const ips_act_props_t *act_ptr) 754 { 755 uint32_t rule_priority = *rule_priorityp; 756 757 /* LINTED E_CONST_COND */ 758 ATTR(ap, SPD_ATTR_EMPTY, 0); 759 760 /* type */ 761 /* LINTED E_CONST_COND */ 762 ATTR(ap, SPD_ATTR_TYPE, act_ptr->iap_action); 763 764 if (act_ptr->iap_action == SPD_ACTTYPE_PASS) 765 rule_priority |= BYPASS_POLICY_BOOST; 766 767 /* flags */ 768 if (act_ptr->iap_attr != 0) 769 /* LINTED E_CONST_COND */ 770 ATTR(ap, SPD_ATTR_FLAGS, act_ptr->iap_attr); 771 772 /* esp */ 773 if (act_ptr->iap_attr & SPD_APPLY_ESP) { 774 rule_priority |= ESP_POLICY_BOOST; 775 776 /* encr */ 777 ap = emit_alg(ap, ESP_ENCR, &act_ptr->iap_eencr, 778 SPD_ATTR_ESP_ENCR, 779 SPD_ATTR_ENCR_MINBITS, SPD_ATTR_ENCR_MAXBITS); 780 781 /* auth */ 782 ap = emit_alg(ap, ESP_AUTH, &act_ptr->iap_eauth, 783 SPD_ATTR_ESP_AUTH, 784 SPD_ATTR_ESPA_MINBITS, SPD_ATTR_ESPA_MAXBITS); 785 } 786 787 /* ah */ 788 if (act_ptr->iap_attr & SPD_APPLY_AH) { 789 rule_priority |= AH_POLICY_BOOST; 790 /* auth */ 791 ap = emit_alg(ap, AH_AUTH, &act_ptr->iap_aauth, 792 SPD_ATTR_AH_AUTH, 793 SPD_ATTR_AH_MINBITS, SPD_ATTR_AH_MAXBITS); 794 } 795 796 /* lifetimes */ 797 if (act_ptr->iap_life_soft_time != 0) 798 /* LINTED E_CONST_COND */ 799 ATTR(ap, SPD_ATTR_LIFE_SOFT_TIME, act_ptr->iap_life_soft_time); 800 if (act_ptr->iap_life_hard_time != 0) 801 /* LINTED E_CONST_COND */ 802 ATTR(ap, SPD_ATTR_LIFE_HARD_TIME, act_ptr->iap_life_hard_time); 803 if (act_ptr->iap_life_soft_bytes != 0) 804 /* LINTED E_CONST_COND */ 805 ATTR(ap, SPD_ATTR_LIFE_SOFT_BYTES, 806 act_ptr->iap_life_soft_bytes); 807 if (act_ptr->iap_life_hard_bytes != 0) 808 /* LINTED E_CONST_COND */ 809 ATTR(ap, SPD_ATTR_LIFE_HARD_BYTES, 810 act_ptr->iap_life_hard_bytes); 811 812 /* LINTED E_CONST_COND */ 813 ATTR(ap, SPD_ATTR_NEXT, 0); 814 815 *rule_priorityp = rule_priority; 816 817 return (ap); 818 } 819 820 static boolean_t 821 alg_rangecheck(uint_t type, uint_t algid, const algreq_t *ar) 822 { 823 int i; 824 uint_t minbits = ar->alg_minbits; 825 uint_t maxbits = ar->alg_maxbits; 826 827 for (i = 0; i < ipsec_nalgs[type]; i++) { 828 if (known_algs[type][i].id == algid) 829 break; 830 } 831 832 if (i >= ipsec_nalgs[type]) { 833 /* 834 * The kernel (where we populate known_algs from) doesn't 835 * return the id's associated with NONE algorithms so we 836 * test here if this was the reason the algorithm wasn't 837 * found before wrongly failing. 838 */ 839 if (((type == ESP_ENCR) && (algid == SADB_EALG_NONE)) || 840 ((type == ESP_AUTH) && (algid == SADB_AALG_NONE)) || 841 ((type == AH_AUTH) && (algid == SADB_AALG_NONE))) { 842 return (B_TRUE); 843 } else { 844 return (B_FALSE); /* not found */ 845 } 846 } 847 848 if ((minbits == 0) && (maxbits == 0)) 849 return (B_TRUE); 850 851 minbits = MAX(minbits, known_algs[type][i].minkeybits); 852 maxbits = MIN(maxbits, known_algs[type][i].maxkeybits); 853 854 /* we could also check key increments here.. */ 855 return (minbits <= maxbits); /* non-null intersection */ 856 } 857 858 /* 859 * Inspired by uts/common/inet/spd.c:ipsec_act_wildcard_expand() 860 */ 861 862 static struct spd_attribute * 863 ips_act_wild_props_to_action(struct spd_attribute *ap, 864 uint32_t *rule_priorityp, uint16_t *act_cntp, 865 const ips_act_props_t *act_ptr) 866 { 867 ips_act_props_t tact = *act_ptr; 868 boolean_t use_ah, use_esp, use_espa; 869 boolean_t wild_auth, wild_encr, wild_eauth; 870 uint_t auth_alg, auth_idx, auth_min, auth_max; 871 uint_t eauth_alg, eauth_idx, eauth_min, eauth_max; 872 uint_t encr_alg, encr_idx, encr_min, encr_max; 873 874 use_ah = !!(act_ptr->iap_attr & SPD_APPLY_AH); 875 use_esp = !!(act_ptr->iap_attr & SPD_APPLY_ESP); 876 use_espa = !!(act_ptr->iap_attr & SPD_APPLY_ESPA); 877 auth_alg = act_ptr->iap_aauth.alg_id; 878 eauth_alg = act_ptr->iap_eauth.alg_id; 879 encr_alg = act_ptr->iap_eencr.alg_id; 880 881 wild_auth = use_ah && (auth_alg == SADB_AALG_NONE); 882 wild_eauth = use_espa && (eauth_alg == SADB_AALG_NONE); 883 wild_encr = use_esp && (encr_alg == SADB_EALG_NONE); 884 885 auth_min = auth_max = auth_alg; 886 eauth_min = eauth_max = eauth_alg; 887 encr_min = encr_max = encr_alg; 888 889 /* 890 * set up for explosion.. for each dimension, expand output 891 * size by the explosion factor. 892 */ 893 if (wild_auth) { 894 auth_min = 0; 895 auth_max = ipsec_nalgs[AH_AUTH] - 1; 896 } 897 if (wild_eauth) { 898 eauth_min = 0; 899 eauth_max = ipsec_nalgs[ESP_AUTH] - 1; 900 } 901 if (wild_encr) { 902 encr_min = 0; 903 encr_max = ipsec_nalgs[ESP_ENCR] - 1; 904 } 905 906 #define WHICH_ALG(type, wild, idx) ((wild)?(known_algs[type][idx].id):(idx)) 907 908 for (encr_idx = encr_min; encr_idx <= encr_max; encr_idx++) { 909 encr_alg = WHICH_ALG(ESP_ENCR, wild_encr, encr_idx); 910 911 if (use_esp && 912 !alg_rangecheck(ESP_ENCR, encr_alg, &act_ptr->iap_eencr)) 913 continue; 914 915 for (auth_idx = auth_min; auth_idx <= auth_max; auth_idx++) { 916 auth_alg = WHICH_ALG(AH_AUTH, wild_auth, auth_idx); 917 918 if (use_ah && 919 !alg_rangecheck(AH_AUTH, auth_alg, 920 &act_ptr->iap_aauth)) 921 continue; 922 923 924 for (eauth_idx = eauth_min; eauth_idx <= eauth_max; 925 eauth_idx++) { 926 eauth_alg = WHICH_ALG(ESP_AUTH, wild_eauth, 927 eauth_idx); 928 929 if (use_espa && 930 !alg_rangecheck(ESP_AUTH, eauth_alg, 931 &act_ptr->iap_eauth)) 932 continue; 933 934 tact.iap_eencr.alg_id = encr_alg; 935 tact.iap_eauth.alg_id = eauth_alg; 936 tact.iap_aauth.alg_id = auth_alg; 937 938 (*act_cntp)++; 939 ap = ips_act_props_to_action(ap, 940 rule_priorityp, &tact); 941 } 942 } 943 } 944 945 #undef WHICH_ALG 946 947 return (ap); 948 } 949 950 /* huge, but not safe since no length checking is done */ 951 #define MAX_POL_MSG_LEN 16384 952 953 954 /* 955 * hand in some ips_conf_t's, get back an 956 * iovec of pfpol messages. 957 * this function converts the internal ips_conf_t into 958 * a form that pf_pol can use. 959 * return 0 on success, 1 on failure 960 */ 961 static int 962 ips_conf_to_pfpol_msg(int ipsec_cmd, ips_conf_t *inConf, int num_ips, 963 struct iovec *msg) 964 { 965 int i; 966 ips_conf_t *conf; 967 uint64_t *scratch = NULL; 968 969 for (i = 0; i < num_ips; i++) { 970 uint16_t *msg_len; 971 uint16_t act_cnt = 0; 972 uint64_t *next = NULL; 973 spd_msg_t *spd_msg; 974 spd_address_t *spd_address; 975 struct spd_rule *spd_rule; 976 struct spd_proto *spd_proto; 977 struct spd_portrange *spd_portrange; 978 struct spd_ext_actions *spd_ext_actions; 979 struct spd_attribute *ap; 980 struct spd_typecode *spd_typecode; 981 spd_if_t *spd_if; 982 ips_act_props_t *act_ptr; 983 uint32_t rule_priority = 0; 984 985 scratch = calloc(1, MAX_POL_MSG_LEN); 986 msg[i].iov_base = (char *)scratch; 987 if (scratch == NULL) { 988 warn(gettext("memory")); 989 return (1); 990 } 991 conf = &(inConf[i]); 992 993 spd_msg = (spd_msg_t *)scratch; 994 next = (uint64_t *)&(spd_msg[1]); 995 996 msg_len = &(spd_msg->spd_msg_len); 997 998 spd_msg->spd_msg_version = PF_POLICY_V1; 999 spd_msg->spd_msg_pid = getpid(); 1000 spd_msg->spd_msg_seq = ++seq_cnt; 1001 1002 switch (ipsec_cmd) { 1003 case SPD_ADDRULE: 1004 spd_msg->spd_msg_type = SPD_ADDRULE; 1005 break; 1006 1007 default: 1008 warnx("%s %d", gettext("bad command:"), ipsec_cmd); 1009 spd_msg->spd_msg_type = SPD_ADDRULE; 1010 break; 1011 } 1012 1013 /* 1014 * SELECTOR 1015 */ 1016 1017 spd_msg->spd_msg_spdid = SPD_STANDBY; 1018 1019 /* rule */ 1020 spd_rule = (struct spd_rule *)next; 1021 1022 spd_rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule)); 1023 spd_rule->spd_rule_type = SPD_EXT_RULE; 1024 spd_rule->spd_rule_flags = conf->ips_dir; 1025 if (conf->ips_tunnel) 1026 spd_rule->spd_rule_flags |= SPD_RULE_FLAG_TUNNEL; 1027 1028 next = (uint64_t *)&(spd_rule[1]); 1029 1030 /* proto */ 1031 if (conf->ips_ulp_prot != 0) { 1032 spd_proto = (struct spd_proto *)next; 1033 spd_proto->spd_proto_len = 1034 SPD_8TO64(sizeof (struct spd_proto)); 1035 spd_proto->spd_proto_exttype = SPD_EXT_PROTO; 1036 spd_proto->spd_proto_number = conf->ips_ulp_prot; 1037 next = (uint64_t *)&(spd_proto[1]); 1038 } 1039 1040 /* tunnel */ 1041 if (conf->has_tunnel != 0) { 1042 spd_if = (spd_if_t *)next; 1043 spd_if->spd_if_len = 1044 SPD_8TO64(P2ROUNDUP(strlen(tunif) + 1, 8) + 1045 sizeof (spd_if_t)); 1046 spd_if->spd_if_exttype = SPD_EXT_TUN_NAME; 1047 (void) strlcpy((char *)spd_if->spd_if_name, tunif, 1048 TUNNAMEMAXLEN); 1049 next = (uint64_t *)(spd_if) + spd_if->spd_if_len; 1050 } 1051 1052 /* icmp type/code */ 1053 if (conf->ips_ulp_prot == IPPROTO_ICMP || 1054 conf->ips_ulp_prot == IPPROTO_ICMPV6) { 1055 if (conf->has_type) { 1056 spd_typecode = (struct spd_typecode *)next; 1057 spd_typecode->spd_typecode_len = 1058 SPD_8TO64(sizeof (struct spd_typecode)); 1059 spd_typecode->spd_typecode_exttype = 1060 SPD_EXT_ICMP_TYPECODE; 1061 spd_typecode->spd_typecode_type = 1062 conf->ips_icmp_type; 1063 spd_typecode->spd_typecode_type_end = 1064 conf->ips_icmp_type_end; 1065 if (conf->has_code) { 1066 spd_typecode->spd_typecode_code = 1067 conf->ips_icmp_code; 1068 spd_typecode->spd_typecode_code_end = 1069 conf->ips_icmp_code_end; 1070 } else { 1071 spd_typecode->spd_typecode_code = 255; 1072 spd_typecode->spd_typecode_code_end 1073 = 255; 1074 } 1075 next = (uint64_t *)&(spd_typecode[1]); 1076 } 1077 } 1078 1079 /* src port */ 1080 if (conf->ips_src_port_min != 0 || 1081 conf->ips_src_port_max != 0) { 1082 spd_portrange = (struct spd_portrange *)next; 1083 spd_portrange->spd_ports_len = 1084 SPD_8TO64(sizeof (struct spd_portrange)); 1085 spd_portrange->spd_ports_exttype = 1086 (conf->swap)?SPD_EXT_REMPORT:SPD_EXT_LCLPORT; 1087 spd_portrange->spd_ports_minport = 1088 conf->ips_src_port_min; 1089 spd_portrange->spd_ports_maxport = 1090 conf->ips_src_port_max; 1091 next = (uint64_t *)&(spd_portrange[1]); 1092 } 1093 /* dst port */ 1094 if (conf->ips_dst_port_min != 0 || 1095 conf->ips_dst_port_max != 0) { 1096 spd_portrange = (struct spd_portrange *)next; 1097 spd_portrange->spd_ports_len = 1098 SPD_8TO64(sizeof (struct spd_portrange)); 1099 spd_portrange->spd_ports_exttype = 1100 (conf->swap)?SPD_EXT_LCLPORT:SPD_EXT_REMPORT; 1101 spd_portrange->spd_ports_minport = 1102 conf->ips_dst_port_min; 1103 spd_portrange->spd_ports_maxport = 1104 conf->ips_dst_port_max; 1105 next = (uint64_t *)&(spd_portrange[1]); 1106 } 1107 1108 /* saddr */ 1109 if (conf->has_saddr) { 1110 spd_address = (spd_address_t *)next; 1111 next = (uint64_t *)(spd_address + 1); 1112 1113 spd_address->spd_address_exttype = 1114 (conf->swap)?SPD_EXT_REMADDR:SPD_EXT_LCLADDR; 1115 spd_address->spd_address_prefixlen = 1116 conf->ips_src_mask_len; 1117 1118 if (conf->ips_isv4) { 1119 spd_address->spd_address_af = AF_INET; 1120 (void) memcpy(next, &(conf->ips_src_addr), 1121 sizeof (ipaddr_t)); 1122 spd_address->spd_address_len = 2; 1123 next += SPD_8TO64(sizeof (ipaddr_t) + 4); 1124 if (!conf->has_smask) 1125 spd_address->spd_address_prefixlen = 32; 1126 } else { 1127 spd_address->spd_address_af = AF_INET6; 1128 (void) memcpy(next, &(conf->ips_src_addr_v6), 1129 sizeof (in6_addr_t)); 1130 spd_address->spd_address_len = 3; 1131 next += SPD_8TO64(sizeof (in6_addr_t)); 1132 if (!conf->has_smask) 1133 spd_address->spd_address_prefixlen 1134 = 128; 1135 } 1136 } 1137 1138 /* daddr */ 1139 if (conf->has_daddr) { 1140 spd_address = (spd_address_t *)next; 1141 1142 next = (uint64_t *)(spd_address + 1); 1143 1144 spd_address->spd_address_exttype = 1145 (conf->swap)?SPD_EXT_LCLADDR:SPD_EXT_REMADDR; 1146 spd_address->spd_address_prefixlen = 1147 conf->ips_dst_mask_len; 1148 1149 if (conf->ips_isv4) { 1150 spd_address->spd_address_af = AF_INET; 1151 (void) memcpy(next, &conf->ips_dst_addr, 1152 sizeof (ipaddr_t)); 1153 spd_address->spd_address_len = 2; 1154 /* "+ 4" below is for padding. */ 1155 next += SPD_8TO64(sizeof (ipaddr_t) + 4); 1156 if (!conf->has_dmask) 1157 spd_address->spd_address_prefixlen = 32; 1158 } else { 1159 spd_address->spd_address_af = AF_INET6; 1160 (void) memcpy(next, &(conf->ips_dst_addr_v6), 1161 sizeof (in6_addr_t)); 1162 spd_address->spd_address_len = 3; 1163 next += SPD_8TO64(sizeof (in6_addr_t)); 1164 if (!conf->has_dmask) 1165 spd_address->spd_address_prefixlen 1166 = 128; 1167 } 1168 } 1169 1170 /* actions */ 1171 spd_ext_actions = (struct spd_ext_actions *)next; 1172 1173 spd_ext_actions->spd_actions_exttype = SPD_EXT_ACTION; 1174 1175 act_ptr = conf->ips_acts; 1176 ap = (struct spd_attribute *)(&spd_ext_actions[1]); 1177 1178 rule_priority = priority--; 1179 1180 for (act_ptr = conf->ips_acts; act_ptr != NULL; 1181 act_ptr = act_ptr->iap_next) { 1182 ap = ips_act_wild_props_to_action(ap, &rule_priority, 1183 &act_cnt, act_ptr); 1184 } 1185 ap[-1].spd_attr_tag = SPD_ATTR_END; 1186 1187 next = (uint64_t *)ap; 1188 1189 spd_rule->spd_rule_priority = rule_priority; 1190 1191 msg[i].iov_len = (uintptr_t)next - (uintptr_t)msg[i].iov_base; 1192 *msg_len = (uint16_t)SPD_8TO64(msg[i].iov_len); 1193 spd_ext_actions->spd_actions_count = act_cnt; 1194 spd_ext_actions->spd_actions_len = 1195 SPD_8TO64((uintptr_t)next - (uintptr_t)spd_ext_actions); 1196 #ifdef DEBUG_HEAVY 1197 printf("pfpol msg len in uint64_t's = %d\n", *msg_len); 1198 printf("pfpol test_len in bytes = %d\n", msg[i].iov_len); 1199 pfpol_msg_dump((spd_msg_t *)scratch, 1200 "ips_conf_to_pfpol_msg"); 1201 #endif 1202 } 1203 1204 #undef ATTR 1205 return (0); 1206 } 1207 1208 static int 1209 get_pf_pol_socket(void) 1210 { 1211 int s = socket(PF_POLICY, SOCK_RAW, PF_POLICY_V1); 1212 if (s < 0) { 1213 if (errno == EPERM) { 1214 EXIT_BADPERM("Insufficient privileges to open " 1215 "PF_POLICY socket."); 1216 } else { 1217 warn(gettext("(loading pf_policy) socket:")); 1218 } 1219 } 1220 1221 return (s); 1222 } 1223 1224 1225 static int 1226 send_pf_pol_message(int ipsec_cmd, ips_conf_t *conf, int *diag) 1227 { 1228 int retval; 1229 int cnt; 1230 int total_len; 1231 struct iovec polmsg; 1232 spd_msg_t *return_buf; 1233 spd_ext_t *exts[SPD_EXT_MAX+1]; 1234 int fd = get_pf_pol_socket(); 1235 1236 *diag = 0; 1237 1238 if (fd < 0) 1239 return (EBADF); 1240 1241 retval = ips_conf_to_pfpol_msg(ipsec_cmd, conf, 1, &polmsg); 1242 1243 if (retval) { 1244 (void) close(fd); 1245 return (ENOMEM); 1246 } 1247 1248 total_len = polmsg.iov_len; 1249 1250 cnt = writev(fd, &polmsg, 1); 1251 1252 #ifdef DEBUG_HEAVY 1253 (void) printf("cnt = %d\n", cnt); 1254 #endif 1255 if (cnt < 0) { 1256 warn(gettext("pf_pol write")); 1257 } else { 1258 return_buf = (spd_msg_t *)calloc(total_len, 1); 1259 1260 if (return_buf == NULL) { 1261 warn(gettext("memory")); 1262 } else { 1263 cnt = read(fd, (void*)return_buf, total_len); 1264 #ifdef DEBUG_HEAVY 1265 (void) printf("pf_pol read: cnt = %d(%d)\n", cnt, 1266 total_len); 1267 #endif 1268 1269 if (cnt > 8 && return_buf->spd_msg_errno) { 1270 *diag = return_buf->spd_msg_diagnostic; 1271 if (!ipsecconf_qflag) { 1272 warnx("%s: %s", 1273 gettext("Kernel returned"), 1274 sys_error_message( 1275 return_buf->spd_msg_errno)); 1276 } 1277 if (*diag != 0) 1278 (void) printf(gettext( 1279 "\t(spdsock diagnostic: %s)\n"), 1280 spdsock_diag(*diag)); 1281 #ifdef DEBUG_HEAVY 1282 pfpol_msg_dump((spd_msg_t *)polmsg.iov_base, 1283 "message in"); 1284 pfpol_msg_dump(return_buf, 1285 "send_pf_pol_message"); 1286 #endif 1287 retval = return_buf->spd_msg_errno; 1288 free(return_buf); 1289 free(polmsg.iov_base); 1290 (void) close(fd); 1291 return (retval); 1292 } 1293 1294 retval = spdsock_get_ext(exts, return_buf, 1295 return_buf->spd_msg_len, NULL, 0); 1296 /* ignore retval */ 1297 1298 if (exts[SPD_EXT_RULE]) { 1299 conf->ips_policy_index = 1300 ((struct spd_rule *) 1301 exts[SPD_EXT_RULE])->spd_rule_index; 1302 1303 if (add_index(conf->ips_policy_index)) { 1304 free(return_buf); 1305 free(polmsg.iov_base); 1306 (void) close(fd); 1307 return (ENOMEM); 1308 } 1309 } 1310 1311 free(return_buf); 1312 } 1313 } 1314 1315 free(polmsg.iov_base); 1316 (void) close(fd); 1317 1318 return (0); 1319 1320 } 1321 1322 int 1323 main(int argc, char *argv[]) 1324 { 1325 int ret, flushret; 1326 int c; 1327 int index; 1328 boolean_t smf_managed; 1329 boolean_t just_check = B_FALSE; 1330 1331 char *smf_warning = gettext( 1332 "\n\tIPsec policy should be managed using smf(5). Modifying\n" 1333 "\tthe IPsec policy from the command line while the 'policy'\n" 1334 "\tservice is enabled could result in an inconsistent\n" 1335 "\tsecurity policy.\n\n"); 1336 1337 flushret = 0; 1338 1339 (void) setlocale(LC_ALL, ""); 1340 #if !defined(TEXT_DOMAIN) 1341 #define TEXT_DOMAIN "SYS_TEST" 1342 #endif 1343 (void) textdomain(TEXT_DOMAIN); 1344 1345 openlog("ipsecconf", LOG_CONS, LOG_AUTH); 1346 1347 /* 1348 * We don't immediately check for privilege here. This is done by IP 1349 * when we open /dev/ip below. 1350 */ 1351 1352 if (argc == 1) { 1353 cmd = IPSEC_CONF_VIEW; 1354 goto done; 1355 } 1356 my_fmri = getenv("SMF_FMRI"); 1357 if (my_fmri == NULL) 1358 smf_managed = B_FALSE; 1359 else 1360 smf_managed = B_TRUE; 1361 1362 while ((c = getopt(argc, argv, "nlfLFa:qd:r:i:c:")) != EOF) { 1363 switch (c) { 1364 case 'F': 1365 if (interface_name != NULL) { 1366 USAGE(); 1367 EXIT_FATAL("interface name not required."); 1368 } 1369 /* Apply to all policy heads - global and tunnels. */ 1370 interface_name = &all_polheads; 1371 /* FALLTHRU */ 1372 case 'f': 1373 /* Only one command at a time */ 1374 if (cmd != 0) { 1375 USAGE(); 1376 EXIT_FATAL("Multiple commands specified"); 1377 } 1378 cmd = IPSEC_CONF_FLUSH; 1379 break; 1380 case 'L': 1381 if (interface_name != NULL) { 1382 USAGE(); 1383 EXIT_FATAL("interface name not required."); 1384 } 1385 /* Apply to all policy heads - global and tunnels. */ 1386 interface_name = &all_polheads; 1387 /* FALLTHRU */ 1388 case 'l': 1389 /* Only one command at a time */ 1390 if (cmd != 0) { 1391 USAGE(); 1392 EXIT_FATAL("Multiple commands specified"); 1393 } 1394 cmd = IPSEC_CONF_LIST; 1395 break; 1396 case 'c': 1397 just_check = B_TRUE; 1398 ipsecconf_qflag++; 1399 /* FALLTHRU */ 1400 case 'a': 1401 /* Only one command at a time, and no interface name */ 1402 if (cmd != 0 || interface_name != NULL) { 1403 USAGE(); 1404 EXIT_FATAL("Multiple commands or interface " 1405 "not required."); 1406 } 1407 cmd = IPSEC_CONF_ADD; 1408 filename = optarg; 1409 break; 1410 case 'd': 1411 /* 1412 * Only one command at a time. Interface name is 1413 * optional. 1414 */ 1415 if (cmd != 0) { 1416 USAGE(); 1417 EXIT_FATAL("Multiple commands specified"); 1418 } 1419 cmd = IPSEC_CONF_DEL; 1420 index = parse_index(optarg, NULL); 1421 break; 1422 case 'n' : 1423 ipsecconf_nflag++; 1424 break; 1425 case 'q' : 1426 ipsecconf_qflag++; 1427 break; 1428 case 'r' : 1429 /* Only one command at a time, and no interface name */ 1430 if (cmd != 0 || interface_name != NULL) { 1431 USAGE(); 1432 EXIT_FATAL("Multiple commands or interface " 1433 "not required."); 1434 } 1435 cmd = IPSEC_CONF_SUB; 1436 filename = optarg; 1437 break; 1438 case 'i': 1439 if (interface_name != NULL) { 1440 EXIT_FATAL("Interface name already selected"); 1441 } 1442 interface_name = optarg; 1443 /* Check for some cretin using the all-polheads name. */ 1444 if (strlen(optarg) == 0) { 1445 USAGE(); 1446 EXIT_FATAL("Invalid interface name."); 1447 } 1448 break; 1449 default : 1450 USAGE(); 1451 EXIT_FATAL("Bad usage."); 1452 } 1453 } 1454 1455 done: 1456 ret = 0; 1457 lfd = lock(); 1458 1459 /* 1460 * ADD, FLUSH, DELETE needs to do two operations. 1461 * 1462 * 1) Update/delete/empty the POLICY_CONF_FILE. 1463 * 2) Make an ioctl and tell IP to update its state. 1464 * 1465 * We already lock()ed so that only one instance of this 1466 * program runs. We also need to make sure that the above 1467 * operations are atomic i.e we don't want to update the file 1468 * and get interrupted before we could tell IP. To make it 1469 * atomic we block all the signals and restore them. 1470 */ 1471 switch (cmd) { 1472 case IPSEC_CONF_LIST: 1473 fetch_algorithms(); 1474 ret = ipsec_conf_list(); 1475 break; 1476 case IPSEC_CONF_FLUSH: 1477 if ((ret = block_all_signals()) == -1) { 1478 break; 1479 } 1480 if (!smf_managed && !ipsecconf_qflag) 1481 (void) fprintf(stdout, "%s", smf_warning); 1482 ret = ipsec_conf_flush(SPD_ACTIVE); 1483 (void) restore_all_signals(); 1484 break; 1485 case IPSEC_CONF_VIEW: 1486 if (interface_name != NULL) { 1487 EXIT_FATAL("Cannot view for one interface only."); 1488 } 1489 ret = ipsec_conf_view(); 1490 break; 1491 case IPSEC_CONF_DEL: 1492 if (index == -1) { 1493 warnx(gettext("Invalid index")); 1494 ret = -1; 1495 break; 1496 } 1497 if ((ret = block_all_signals()) == -1) { 1498 break; 1499 } 1500 if (!smf_managed && !ipsecconf_qflag) 1501 (void) fprintf(stdout, "%s", smf_warning); 1502 ret = ipsec_conf_del(index, B_FALSE); 1503 (void) restore_all_signals(); 1504 flushret = ipsec_conf_flush(SPD_STANDBY); 1505 break; 1506 case IPSEC_CONF_ADD: 1507 /* 1508 * The IPsec kernel modules should only be loaded 1509 * if there is a policy to install, for this 1510 * reason ipsec_conf_add() calls fetch_algorithms() 1511 * and ipsec_conf_flush() only when appropriate. 1512 */ 1513 if ((ret = block_all_signals()) == -1) { 1514 break; 1515 } 1516 if (!smf_managed && !ipsecconf_qflag) 1517 (void) fprintf(stdout, "%s", smf_warning); 1518 ret = ipsec_conf_add(just_check, smf_managed); 1519 (void) restore_all_signals(); 1520 break; 1521 case IPSEC_CONF_SUB: 1522 fetch_algorithms(); 1523 if ((ret = block_all_signals()) == -1) { 1524 break; 1525 } 1526 if (!smf_managed && !ipsecconf_qflag) 1527 (void) fprintf(stdout, "%s", smf_warning); 1528 ret = ipsec_conf_sub(); 1529 (void) restore_all_signals(); 1530 flushret = ipsec_conf_flush(SPD_STANDBY); 1531 break; 1532 default : 1533 /* If no argument is given but a "-" */ 1534 USAGE(); 1535 EXIT_FATAL("Bad usage."); 1536 } 1537 1538 (void) unlock(lfd); 1539 if (ret != 0 || flushret != 0) 1540 ret = 1; 1541 return (ret); 1542 } 1543 1544 static void 1545 perm_check(void) 1546 { 1547 if (errno == EACCES) 1548 EXIT_BADPERM("Insufficient privilege to run ipsecconf."); 1549 else 1550 warn(gettext("Cannot open lock file %s"), LOCK_FILE); 1551 1552 EXIT_BADPERM(NULL); 1553 } 1554 1555 static int 1556 lock() 1557 { 1558 int fd; 1559 struct stat sbuf1; 1560 struct stat sbuf2; 1561 1562 /* 1563 * Open the file with O_CREAT|O_EXCL. If it exists already, it 1564 * will fail. If it already exists, check whether it looks like 1565 * the one we created. 1566 */ 1567 (void) umask(0077); 1568 if ((fd = open(LOCK_FILE, O_EXCL|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) 1569 == -1) { 1570 if (errno != EEXIST) { 1571 /* Some other problem. Will exit. */ 1572 perm_check(); 1573 } 1574 1575 /* 1576 * open() returned an EEXIST error. We don't fail yet 1577 * as it could be a residual from a previous 1578 * execution. 1579 * File exists. make sure it is OK. We need to lstat() 1580 * as fstat() stats the file pointed to by the symbolic 1581 * link. 1582 */ 1583 if (lstat(LOCK_FILE, &sbuf1) == -1) { 1584 EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE); 1585 } 1586 /* 1587 * Check whether it is a regular file and not a symbolic 1588 * link. Its link count should be 1. The owner should be 1589 * root and the file should be empty. 1590 */ 1591 if (!S_ISREG(sbuf1.st_mode) || 1592 sbuf1.st_nlink != 1 || 1593 sbuf1.st_uid != 0 || 1594 sbuf1.st_size != 0) { 1595 EXIT_FATAL2("Bad lock file %s", LOCK_FILE); 1596 } 1597 if ((fd = open(LOCK_FILE, O_CREAT|O_RDWR, 1598 S_IRUSR|S_IWUSR)) == -1) { 1599 /* Will exit */ 1600 perm_check(); 1601 } 1602 /* 1603 * Check whether we opened the file that we lstat()ed. 1604 */ 1605 if (fstat(fd, &sbuf2) == -1) { 1606 EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE); 1607 } 1608 if (sbuf1.st_dev != sbuf2.st_dev || 1609 sbuf1.st_ino != sbuf2.st_ino) { 1610 /* File changed after we did the lstat() above */ 1611 EXIT_FATAL2("Bad lock file %s", LOCK_FILE); 1612 } 1613 } 1614 if (lockf(fd, F_LOCK, 0) == -1) { 1615 EXIT_FATAL2("Cannot lockf %s", LOCK_FILE); 1616 } 1617 return (fd); 1618 } 1619 1620 static int 1621 unlock(int fd) 1622 { 1623 if (lockf(fd, F_ULOCK, 0) == -1) { 1624 warn("lockf"); 1625 return (-1); 1626 } 1627 return (0); 1628 } 1629 1630 /* send in TOK_* */ 1631 static void 1632 print_pattern_string(int type) 1633 { 1634 int j; 1635 1636 for (j = 0; pattern_table[j].string != NULL; j++) { 1637 if (type == pattern_table[j].tok_val) { 1638 (void) printf("%s ", pattern_table[j].string); 1639 return; 1640 } 1641 } 1642 } 1643 1644 static void 1645 print_icmp_typecode(uint8_t type, uint8_t type_end, uint8_t code, 1646 uint8_t code_end) 1647 { 1648 (void) printf("type %d", type); 1649 if (type_end != type) 1650 (void) printf("-%d ", type_end); 1651 else 1652 (void) printf(" "); 1653 if (code != 255) { 1654 (void) printf("code %d", code); 1655 if (code_end != code) 1656 (void) printf("-%d ", code_end); 1657 else 1658 (void) printf(" "); 1659 } 1660 } 1661 1662 1663 static void 1664 print_spd_flags(uint32_t flags) 1665 { 1666 flags &= (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND); 1667 1668 if (flags == SPD_RULE_FLAG_OUTBOUND) 1669 (void) printf("dir out "); 1670 else if (flags == SPD_RULE_FLAG_INBOUND) 1671 (void) printf("dir in "); 1672 else if (flags == (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND)) 1673 (void) printf("dir both "); 1674 } 1675 1676 static void 1677 print_bit_range(int min, int max) 1678 { 1679 if (min != 0 || (max != 0 && max != SPD_MAX_MAXBITS)) { 1680 (void) printf("("); 1681 if (min != 0) 1682 (void) printf("%d", min); 1683 if (min != 0 && max != 0 && min != max) { 1684 (void) printf(".."); 1685 if (max != 0 && max != SPD_MAX_MAXBITS) 1686 (void) printf("%d", max); 1687 } 1688 (void) printf(")"); 1689 } 1690 } 1691 1692 static void 1693 print_alg(const char *tag, algreq_t *algreq, int proto_num) 1694 { 1695 int min = algreq->alg_minbits; 1696 int max = algreq->alg_maxbits; 1697 struct ipsecalgent *alg; 1698 1699 /* 1700 * This function won't be called with alg_id == 0, so we don't 1701 * have to worry about ANY vs. NONE here. 1702 */ 1703 1704 (void) printf("%s ", tag); 1705 1706 alg = getipsecalgbynum(algreq->alg_id, proto_num, NULL); 1707 if (alg == NULL) { 1708 (void) printf("%d", algreq->alg_id); 1709 } else { 1710 (void) printf("%s", alg->a_names[0]); 1711 freeipsecalgent(alg); 1712 } 1713 1714 print_bit_range(min, max); 1715 (void) printf(" "); 1716 } 1717 1718 static void 1719 print_ulp(uint8_t proto) 1720 { 1721 struct protoent *pe; 1722 1723 if (proto == 0) 1724 return; 1725 1726 print_pattern_string(TOK_ulp); 1727 pe = NULL; 1728 if (!ipsecconf_nflag) { 1729 pe = getprotobynumber(proto); 1730 } 1731 if (pe != NULL) 1732 (void) printf("%s ", pe->p_name); 1733 else 1734 (void) printf("%d ", proto); 1735 } 1736 1737 /* needs to do ranges */ 1738 static void 1739 print_port(uint16_t in_port, int type) 1740 { 1741 in_port_t port = ntohs(in_port); 1742 struct servent *sp; 1743 1744 if (port == 0) 1745 return; 1746 1747 print_pattern_string(type); 1748 sp = NULL; 1749 if (!ipsecconf_nflag) 1750 sp = getservbyport(port, NULL); 1751 1752 if (sp != NULL) 1753 (void) printf("%s ", sp->s_name); 1754 else 1755 (void) printf("%d ", port); 1756 } 1757 1758 /* 1759 * Print the address, given as "raw" input via the void pointer. 1760 */ 1761 static void 1762 print_raw_address(void *input, boolean_t isv4) 1763 { 1764 char *cp; 1765 struct hostent *hp; 1766 char domain[MAXHOSTNAMELEN + 1]; 1767 struct in_addr addr; 1768 struct in6_addr addr6; 1769 char abuf[INET6_ADDRSTRLEN]; 1770 int error_num; 1771 struct in6_addr in_addr; 1772 uchar_t *addr_ptr; 1773 sa_family_t af; 1774 int addr_len; 1775 1776 if (isv4) { 1777 af = AF_INET; 1778 (void) memcpy(&V4_PART_OF_V6(in_addr), input, 4); 1779 /* we don't print unspecified addresses */ 1780 IN6_V4MAPPED_TO_INADDR(&in_addr, &addr); 1781 if (addr.s_addr == INADDR_ANY) 1782 return; 1783 addr_ptr = (uchar_t *)&addr.s_addr; 1784 addr_len = IPV4_ADDR_LEN; 1785 } else { 1786 (void) memcpy(&addr6, input, 16); 1787 af = AF_INET6; 1788 /* we don't print unspecified addresses */ 1789 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) 1790 return; 1791 addr_ptr = (uchar_t *)&addr6.s6_addr; 1792 addr_len = sizeof (struct in6_addr); 1793 } 1794 1795 cp = NULL; 1796 if (!ipsecconf_nflag) { 1797 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 && 1798 (cp = strchr(domain, '.')) != NULL) { 1799 (void) strlcpy(domain, cp + 1, sizeof (domain)); 1800 } else { 1801 domain[0] = 0; 1802 } 1803 hp = getipnodebyaddr(addr_ptr, addr_len, af, &error_num); 1804 if (hp) { 1805 if ((cp = strchr(hp->h_name, '.')) != 0 && 1806 strcasecmp(cp + 1, domain) == 0) 1807 *cp = 0; 1808 cp = hp->h_name; 1809 } 1810 } 1811 1812 if (cp) { 1813 (void) printf("%s", cp); 1814 } else { 1815 (void) printf("%s", inet_ntop(af, addr_ptr, abuf, 1816 INET6_ADDRSTRLEN)); 1817 } 1818 } 1819 1820 /* 1821 * Get the next SPD_DUMP message from the PF_POLICY socket. A single 1822 * read may contain multiple messages. This function uses static buffers, 1823 * and is therefore non-reentrant, so if you lift it for an MT application, 1824 * be careful. 1825 * 1826 * Return NULL if there's an error. 1827 */ 1828 static spd_msg_t * 1829 ipsec_read_dump(int pfd) 1830 { 1831 static uint64_t buf[SADB_8TO64(CBUF_LEN)]; 1832 static uint64_t *offset; 1833 static int len; /* In uint64_t units. */ 1834 spd_msg_t *retval; 1835 1836 /* Assume offset and len are initialized to NULL and 0. */ 1837 1838 if ((offset - len == buf) || (offset == NULL)) { 1839 /* read a new block from the socket. */ 1840 len = read(pfd, &buf, sizeof (buf)); 1841 if (len == -1) { 1842 warn(gettext("rule dump: bad read")); 1843 return (NULL); 1844 } 1845 offset = buf; 1846 len = SADB_8TO64(len); 1847 } /* Else I still have more messages from a previous read. */ 1848 1849 retval = (spd_msg_t *)offset; 1850 offset += retval->spd_msg_len; 1851 if (offset > buf + len) { 1852 warnx(gettext("dump read: message corruption," 1853 " %d len exceeds %d boundary."), 1854 SADB_64TO8((uintptr_t)(offset - buf)), 1855 SADB_64TO8((uintptr_t)(buf + len))); 1856 return (NULL); 1857 } 1858 1859 return (retval); 1860 } 1861 1862 /* 1863 * returns 0 on success 1864 * -1 on read error 1865 * >0 on invalid returned message 1866 */ 1867 1868 static int 1869 ipsec_conf_list(void) 1870 { 1871 int ret; 1872 int pfd; 1873 struct spd_msg *msg; 1874 int cnt; 1875 spd_msg_t *rmsg; 1876 spd_ext_t *exts[SPD_EXT_MAX+1]; 1877 /* 1878 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 1879 * issues. 1880 */ 1881 uint64_t buffer[ 1882 SPD_8TO64(sizeof (*msg) + sizeof (spd_if_t) + LIFNAMSIZ) + 1]; 1883 1884 pfd = get_pf_pol_socket(); 1885 1886 if (pfd == -1) { 1887 warnx(gettext("Error getting list of policies from kernel")); 1888 return (-1); 1889 } 1890 1891 (void) memset(buffer, 0, sizeof (buffer)); 1892 msg = (struct spd_msg *)buffer; 1893 msg->spd_msg_version = PF_POLICY_V1; 1894 msg->spd_msg_type = SPD_DUMP; 1895 msg->spd_msg_len = SPD_8TO64(sizeof (*msg)); 1896 1897 msg->spd_msg_len += attach_tunname((spd_if_t *)(msg + 1)); 1898 1899 cnt = write(pfd, msg, SPD_64TO8(msg->spd_msg_len)); 1900 1901 if (cnt < 0) { 1902 warn(gettext("dump: invalid write() return")); 1903 (void) close(pfd); 1904 return (-1); 1905 } 1906 1907 rmsg = ipsec_read_dump(pfd); 1908 1909 if (rmsg == NULL || rmsg->spd_msg_errno != 0) { 1910 warnx("%s: %s", gettext("ruleset dump failed"), 1911 (rmsg == NULL ? 1912 gettext("read error") : 1913 sys_error_message(rmsg->spd_msg_errno))); 1914 (void) close(pfd); 1915 return (-1); 1916 } 1917 1918 1919 for (;;) { 1920 /* read rule */ 1921 rmsg = ipsec_read_dump(pfd); 1922 1923 if (rmsg == NULL) { 1924 (void) close(pfd); 1925 return (-1); 1926 } 1927 1928 if (rmsg->spd_msg_errno != 0) { 1929 warnx("%s: %s", gettext("dump read: bad message"), 1930 sys_error_message(rmsg->spd_msg_errno)); 1931 (void) close(pfd); 1932 return (-1); 1933 } 1934 1935 ret = spdsock_get_ext(exts, rmsg, rmsg->spd_msg_len, 1936 spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN); 1937 if (ret != 0) { 1938 if (strlen(spdsock_diag_buf) != 0) 1939 warnx(spdsock_diag_buf); 1940 warnx("%s: %s", gettext("dump read: bad message"), 1941 sys_error_message(rmsg->spd_msg_errno)); 1942 (void) close(pfd); 1943 return (ret); 1944 } 1945 1946 /* 1947 * End of dump.. 1948 */ 1949 if (exts[SPD_EXT_RULESET] != NULL) 1950 break; /* and return 0. */ 1951 1952 print_pfpol_msg(rmsg); 1953 } 1954 1955 (void) close(pfd); 1956 return (0); 1957 } 1958 1959 static void 1960 print_iap(ips_act_props_t *iap) 1961 { 1962 1963 /* action */ 1964 switch (iap->iap_action) { 1965 case SPD_ACTTYPE_PASS: 1966 (void) printf("pass "); 1967 break; 1968 case SPD_ACTTYPE_DROP: 1969 (void) printf("drop "); 1970 break; 1971 case SPD_ACTTYPE_IPSEC: 1972 (void) printf("ipsec "); 1973 break; 1974 } 1975 1976 /* properties */ 1977 (void) printf("%c ", CURL_BEGIN); 1978 if (iap->iap_action == SPD_ACTTYPE_IPSEC) { 1979 if (iap->iap_attr & SPD_APPLY_AH && 1980 iap->iap_aauth.alg_id != 0) 1981 print_alg("auth_algs", &iap->iap_aauth, 1982 IPSEC_PROTO_AH); 1983 1984 if (iap->iap_attr & SPD_APPLY_ESP) { 1985 print_alg("encr_algs", &iap->iap_eencr, 1986 IPSEC_PROTO_ESP); 1987 if (iap->iap_eauth.alg_id != 0) 1988 print_alg("encr_auth_algs", &iap->iap_eauth, 1989 IPSEC_PROTO_AH); 1990 } 1991 if (iap->iap_attr & SPD_APPLY_UNIQUE) 1992 (void) printf("sa unique "); 1993 else 1994 (void) printf("sa shared "); 1995 } 1996 (void) printf("%c ", CURL_END); 1997 } 1998 1999 2000 static void 2001 print_pfpol_msg(spd_msg_t *msg) 2002 { 2003 spd_ext_t *exts[SPD_EXT_MAX+1]; 2004 spd_address_t *spd_address; 2005 struct spd_rule *spd_rule; 2006 struct spd_proto *spd_proto; 2007 struct spd_portrange *spd_portrange; 2008 struct spd_ext_actions *spd_ext_actions; 2009 struct spd_typecode *spd_typecode; 2010 struct spd_attribute *app; 2011 spd_if_t *spd_if; 2012 uint32_t rv; 2013 uint16_t act_count; 2014 2015 rv = spdsock_get_ext(exts, msg, msg->spd_msg_len, spdsock_diag_buf, 2016 SPDSOCK_DIAG_BUF_LEN); 2017 2018 if (rv == KGE_OK && exts[SPD_EXT_RULE] != NULL) { 2019 spd_if = (spd_if_t *)exts[SPD_EXT_TUN_NAME]; 2020 spd_rule = (struct spd_rule *)exts[SPD_EXT_RULE]; 2021 if (spd_if == NULL) { 2022 (void) printf("%s %lld\n", INDEX_TAG, 2023 spd_rule->spd_rule_index); 2024 } else { 2025 (void) printf("%s %s,%lld\n", INDEX_TAG, 2026 (char *)spd_if->spd_if_name, 2027 spd_rule->spd_rule_index); 2028 } 2029 } else { 2030 if (strlen(spdsock_diag_buf) != 0) 2031 warnx(spdsock_diag_buf); 2032 warnx(gettext("print_pfpol_msg: malformed PF_POLICY message.")); 2033 return; 2034 } 2035 2036 (void) printf("%c ", CURL_BEGIN); 2037 2038 if (spd_if != NULL) { 2039 (void) printf("tunnel %s negotiate %s ", 2040 (char *)spd_if->spd_if_name, 2041 (spd_rule->spd_rule_flags & SPD_RULE_FLAG_TUNNEL) ? 2042 "tunnel" : "transport"); 2043 } 2044 2045 if (exts[SPD_EXT_PROTO] != NULL) { 2046 spd_proto = (struct spd_proto *)exts[SPD_EXT_PROTO]; 2047 print_ulp(spd_proto->spd_proto_number); 2048 } 2049 2050 if (exts[SPD_EXT_LCLADDR] != NULL) { 2051 spd_address = (spd_address_t *)exts[SPD_EXT_LCLADDR]; 2052 2053 (void) printf("laddr "); 2054 print_raw_address((spd_address + 1), 2055 (spd_address->spd_address_len == 2)); 2056 (void) printf("/%d ", spd_address->spd_address_prefixlen); 2057 } 2058 2059 if (exts[SPD_EXT_LCLPORT] != NULL) { 2060 spd_portrange = (struct spd_portrange *)exts[SPD_EXT_LCLPORT]; 2061 if (spd_portrange->spd_ports_minport != 0) { 2062 print_port(spd_portrange->spd_ports_minport, 2063 TOK_lport); 2064 } 2065 } 2066 2067 2068 if (exts[SPD_EXT_REMADDR] != NULL) { 2069 spd_address = (spd_address_t *)exts[SPD_EXT_REMADDR]; 2070 2071 (void) printf("raddr "); 2072 print_raw_address((spd_address + 1), 2073 (spd_address->spd_address_len == 2)); 2074 (void) printf("/%d ", spd_address->spd_address_prefixlen); 2075 } 2076 2077 if (exts[SPD_EXT_REMPORT] != NULL) { 2078 spd_portrange = 2079 (struct spd_portrange *)exts[SPD_EXT_REMPORT]; 2080 if (spd_portrange->spd_ports_minport != 0) { 2081 print_port( 2082 spd_portrange->spd_ports_minport, TOK_rport); 2083 } 2084 } 2085 2086 if (exts[SPD_EXT_ICMP_TYPECODE] != NULL) { 2087 spd_typecode = 2088 (struct spd_typecode *)exts[SPD_EXT_ICMP_TYPECODE]; 2089 print_icmp_typecode(spd_typecode->spd_typecode_type, 2090 spd_typecode->spd_typecode_type_end, 2091 spd_typecode->spd_typecode_code, 2092 spd_typecode->spd_typecode_code_end); 2093 } 2094 2095 if (exts[SPD_EXT_RULE] != NULL) { 2096 spd_rule = (struct spd_rule *)exts[SPD_EXT_RULE]; 2097 print_spd_flags(spd_rule->spd_rule_flags); 2098 } 2099 2100 2101 (void) printf("%c ", CURL_END); 2102 2103 if (exts[SPD_EXT_ACTION] != NULL) { 2104 ips_act_props_t iap; 2105 int or_needed = 0; 2106 2107 (void) memset(&iap, 0, sizeof (iap)); 2108 spd_ext_actions = 2109 (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 2110 app = (struct spd_attribute *)(spd_ext_actions + 1); 2111 2112 for (act_count = 0; 2113 act_count < spd_ext_actions->spd_actions_len -1; 2114 act_count++) { 2115 2116 switch (app->spd_attr_tag) { 2117 2118 case SPD_ATTR_NOP: 2119 break; 2120 2121 case SPD_ATTR_END: 2122 /* print */ 2123 if (or_needed) { 2124 (void) printf("or "); 2125 } else { 2126 or_needed = 1; 2127 } 2128 print_iap(&iap); 2129 break; 2130 2131 case SPD_ATTR_EMPTY: 2132 /* clear */ 2133 (void) memset(&iap, 0, sizeof (iap)); 2134 break; 2135 2136 case SPD_ATTR_NEXT: 2137 /* print */ 2138 if (or_needed) { 2139 (void) printf("or "); 2140 } else { 2141 or_needed = 1; 2142 } 2143 2144 print_iap(&iap); 2145 break; 2146 2147 case SPD_ATTR_TYPE: 2148 iap.iap_action = app->spd_attr_value; 2149 break; 2150 2151 case SPD_ATTR_FLAGS: 2152 iap.iap_attr = app->spd_attr_value; 2153 break; 2154 2155 case SPD_ATTR_AH_AUTH: 2156 iap.iap_aauth.alg_id = app->spd_attr_value; 2157 break; 2158 2159 case SPD_ATTR_ESP_ENCR: 2160 iap.iap_eencr.alg_id = app->spd_attr_value; 2161 break; 2162 2163 case SPD_ATTR_ESP_AUTH: 2164 iap.iap_eauth.alg_id = app->spd_attr_value; 2165 break; 2166 2167 case SPD_ATTR_ENCR_MINBITS: 2168 iap.iap_eencr.alg_minbits = app->spd_attr_value; 2169 break; 2170 2171 case SPD_ATTR_ENCR_MAXBITS: 2172 iap.iap_eencr.alg_maxbits = app->spd_attr_value; 2173 break; 2174 2175 case SPD_ATTR_AH_MINBITS: 2176 iap.iap_aauth.alg_minbits = app->spd_attr_value; 2177 break; 2178 2179 case SPD_ATTR_AH_MAXBITS: 2180 iap.iap_aauth.alg_maxbits = app->spd_attr_value; 2181 break; 2182 2183 case SPD_ATTR_ESPA_MINBITS: 2184 iap.iap_eauth.alg_minbits = app->spd_attr_value; 2185 break; 2186 2187 case SPD_ATTR_ESPA_MAXBITS: 2188 iap.iap_eauth.alg_maxbits = app->spd_attr_value; 2189 break; 2190 2191 case SPD_ATTR_LIFE_SOFT_TIME: 2192 case SPD_ATTR_LIFE_HARD_TIME: 2193 case SPD_ATTR_LIFE_SOFT_BYTES: 2194 case SPD_ATTR_LIFE_HARD_BYTES: 2195 default: 2196 (void) printf("\tattr %d: %X-%d\n", 2197 act_count, 2198 app->spd_attr_tag, 2199 app->spd_attr_value); 2200 break; 2201 } 2202 app++; 2203 } 2204 } 2205 2206 (void) printf("\n"); 2207 } 2208 2209 #ifdef DEBUG_HEAVY 2210 static void 2211 pfpol_msg_dump(spd_msg_t *msg, char *tag) 2212 { 2213 spd_ext_t *exts[SPD_EXT_MAX+1]; 2214 uint32_t i; 2215 spd_address_t *spd_address; 2216 struct spd_rule *spd_rule; 2217 struct spd_proto *spd_proto; 2218 struct spd_portrange *spd_portrange; 2219 struct spd_typecode *spd_typecode; 2220 struct spd_ext_actions *spd_ext_actions; 2221 struct spd_attribute *app; 2222 spd_if_t *spd_if; 2223 char abuf[INET6_ADDRSTRLEN]; 2224 uint32_t rv; 2225 uint16_t act_count; 2226 2227 rv = spdsock_get_ext(exts, msg, msg->spd_msg_len, NULL, 0); 2228 if (rv != KGE_OK) 2229 return; 2230 2231 (void) printf("===========%s==============\n", tag); 2232 (void) printf("pfpol_msg_dump %d\n-------------------\n", rv); 2233 2234 (void) printf("spd_msg_version:%d\n", msg->spd_msg_version); 2235 (void) printf("spd_msg_type:%d\n", msg->spd_msg_type); 2236 (void) printf("spd_msg_errno:%d\n", msg->spd_msg_errno); 2237 (void) printf("spd_msg_spdid:%d\n", msg->spd_msg_spdid); 2238 (void) printf("spd_msg_len:%d\n", msg->spd_msg_len); 2239 (void) printf("spd_msg_diagnostic:%d\n", msg->spd_msg_diagnostic); 2240 (void) printf("spd_msg_seq:%d\n", msg->spd_msg_seq); 2241 (void) printf("spd_msg_pid:%d\n", msg->spd_msg_pid); 2242 2243 for (i = 1; i <= SPD_EXT_MAX; i++) { 2244 if (exts[i] == NULL) { 2245 printf("skipped %d\n", i); 2246 continue; 2247 } 2248 2249 switch (i) { 2250 case SPD_EXT_TUN_NAME: 2251 spd_if = (spd_if_t *)exts[i]; 2252 (void) printf("spd_if = %s\n", spd_if->spd_if_name); 2253 break; 2254 2255 case SPD_EXT_ICMP_TYPECODE: 2256 spd_typecode = (struct spd_typecode *)exts[i]; 2257 (void) printf("icmp type %d-%d code %d-%d\n", 2258 spd_typecode->spd_typecode_type, 2259 spd_typecode->spd_typecode_type_end, 2260 spd_typecode->spd_typecode_code, 2261 spd_typecode->spd_typecode_code_end); 2262 break; 2263 2264 case SPD_EXT_LCLPORT: 2265 spd_portrange = (struct spd_portrange *)exts[i]; 2266 (void) printf("local ports %d-%d\n", 2267 spd_portrange->spd_ports_minport, 2268 spd_portrange->spd_ports_maxport); 2269 2270 break; 2271 2272 case SPD_EXT_REMPORT: 2273 spd_portrange = (struct spd_portrange *)exts[i]; 2274 (void) printf("remote ports %d-%d\n", 2275 spd_portrange->spd_ports_minport, 2276 spd_portrange->spd_ports_maxport); 2277 2278 break; 2279 2280 case SPD_EXT_PROTO: 2281 spd_proto = (struct spd_proto *)exts[i]; 2282 (void) printf("proto:spd_proto_exttype %d\n", 2283 spd_proto->spd_proto_exttype); 2284 (void) printf("proto:spd_proto_number %d\n", 2285 spd_proto->spd_proto_number); 2286 break; 2287 2288 case SPD_EXT_LCLADDR: 2289 case SPD_EXT_REMADDR: 2290 spd_address = (spd_address_t *)exts[i]; 2291 if (i == SPD_EXT_LCLADDR) 2292 (void) printf("local addr "); 2293 else 2294 (void) printf("remote addr "); 2295 2296 2297 (void) printf("%s\n", 2298 inet_ntop(spd_address->spd_address_af, 2299 (void *) (spd_address +1), abuf, 2300 INET6_ADDRSTRLEN)); 2301 2302 (void) printf("prefixlen: %d\n", 2303 spd_address->spd_address_prefixlen); 2304 break; 2305 2306 case SPD_EXT_ACTION: 2307 spd_ext_actions = (struct spd_ext_actions *)exts[i]; 2308 (void) printf("spd_ext_action\n"); 2309 (void) printf("spd_actions_count %d\n", 2310 spd_ext_actions->spd_actions_count); 2311 app = (struct spd_attribute *)(spd_ext_actions + 1); 2312 2313 for (act_count = 0; 2314 act_count < spd_ext_actions->spd_actions_len -1; 2315 act_count++) { 2316 (void) printf("\tattr %d: %X-%d\n", act_count, 2317 app->spd_attr_tag, app->spd_attr_value); 2318 app++; 2319 } 2320 2321 break; 2322 2323 case SPD_EXT_RULE: 2324 spd_rule = (struct spd_rule *)exts[i]; 2325 (void) printf("spd_rule_priority: 0x%x\n", 2326 spd_rule->spd_rule_priority); 2327 (void) printf("spd_rule_flags: %d\n", 2328 spd_rule->spd_rule_flags); 2329 break; 2330 2331 case SPD_EXT_RULESET: 2332 (void) printf("spd_ext_ruleset\n"); 2333 break; 2334 default: 2335 (void) printf("default\n"); 2336 break; 2337 } 2338 } 2339 2340 (void) printf("-------------------\n"); 2341 (void) printf("=========================\n"); 2342 } 2343 #endif /* DEBUG_HEAVY */ 2344 2345 static int 2346 ipsec_conf_view() 2347 { 2348 char buf[MAXLEN]; 2349 FILE *fp; 2350 2351 fp = fopen(POLICY_CONF_FILE, "r"); 2352 if (fp == NULL) { 2353 if (errno == ENOENT) { 2354 /* 2355 * The absence of POLICY_CONF_FILE should 2356 * not cause the command to exit with a 2357 * non-zero status, since this condition 2358 * is valid when no policies were previously 2359 * defined. 2360 */ 2361 return (0); 2362 } 2363 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 2364 return (-1); 2365 } 2366 while (fgets(buf, MAXLEN, fp) != NULL) { 2367 /* Don't print removed entries */ 2368 if (*buf == ';') 2369 continue; 2370 if (strlen(buf) != 0) 2371 buf[strlen(buf) - 1] = '\0'; 2372 (void) puts(buf); 2373 } 2374 return (0); 2375 } 2376 2377 /* 2378 * Delete nlines from start in the POLICY_CONF_FILE. 2379 */ 2380 static int 2381 delete_from_file(int start, int nlines) 2382 { 2383 FILE *fp; 2384 char ibuf[MAXLEN]; 2385 int len; 2386 2387 if ((fp = fopen(POLICY_CONF_FILE, "r+b")) == NULL) { 2388 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 2389 return (-1); 2390 } 2391 2392 /* 2393 * Insert a ";", read the line and discard it. Repeat 2394 * this logic nlines - 1 times. For the last line there 2395 * is just a newline character. We can't just insert a 2396 * single ";" character instead of the newline character 2397 * as it would affect the next line. Thus when we comment 2398 * the last line we seek one less and insert a ";" 2399 * character, which will replace the newline of the 2400 * penultimate line with ; and newline of the last line 2401 * will become part of the previous line. 2402 */ 2403 do { 2404 /* 2405 * It is not enough to seek just once and expect the 2406 * subsequent fgets below to take you to the right 2407 * offset of the next line. fgets below seems to affect 2408 * the offset. Thus we need to seek, replace with ";", 2409 * and discard a line using fgets for every line. 2410 */ 2411 if (fseek(fp, start, SEEK_SET) == -1) { 2412 warn("fseek"); 2413 return (-1); 2414 } 2415 if (fputc(';', fp) < 0) { 2416 warn("fputc"); 2417 return (-1); 2418 } 2419 /* 2420 * Flush the above ";" character before we do the fgets(). 2421 * Without this, fgets() gets confused with offsets. 2422 */ 2423 (void) fflush(fp); 2424 len = 0; 2425 while (fgets(ibuf, MAXLEN, fp) != NULL) { 2426 len += strlen(ibuf); 2427 if (ibuf[len - 1] == '\n') { 2428 /* 2429 * We have read a complete line. 2430 */ 2431 break; 2432 } 2433 } 2434 /* 2435 * We read the line after ";" character has been inserted. 2436 * Thus len does not count ";". To advance to the next line 2437 * increment by 1. 2438 */ 2439 start += (len + 1); 2440 /* 2441 * If nlines == 2, we will be commenting out the last 2442 * line next, which has only one newline character. 2443 * If we blindly replace it with ";", it will be 2444 * read as part of the next line which could have 2445 * a INDEX string and thus confusing ipsec_conf_view. 2446 * Thus, we seek one less and replace the previous 2447 * line's newline character with ";", and the 2448 * last line's newline character will become part of 2449 * the previous line. 2450 */ 2451 if (nlines == 2) 2452 start--; 2453 } while (--nlines != 0); 2454 (void) fclose(fp); 2455 if (nlines != 0) 2456 return (-1); 2457 else 2458 return (0); 2459 } 2460 2461 /* 2462 * Delete an entry from the file by inserting a ";" at the 2463 * beginning of the lines to be removed. 2464 */ 2465 static int 2466 ipsec_conf_del(int policy_index, boolean_t ignore_spd) 2467 { 2468 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 2469 char *buf; 2470 FILE *fp; 2471 char ibuf[MAXLEN]; 2472 int ibuf_len, index_len, index; 2473 int ret = 0; 2474 int offset, prev_offset; 2475 int nlines; 2476 char lifname[LIFNAMSIZ]; 2477 2478 if (act_props == NULL) { 2479 warn(gettext("memory")); 2480 return (-1); 2481 } 2482 2483 fp = fopen(POLICY_CONF_FILE, "r"); 2484 if (fp == NULL) { 2485 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 2486 free(act_props); 2487 return (-1); 2488 } 2489 2490 index_len = strlen(INDEX_TAG); 2491 index = 0; 2492 for (offset = prev_offset = 0; fgets(ibuf, MAXLEN, fp) != NULL; 2493 offset += ibuf_len) { 2494 prev_offset = offset; 2495 ibuf_len = strlen(ibuf); 2496 2497 if (strncmp(ibuf, INDEX_TAG, index_len) != 0) { 2498 continue; 2499 } 2500 2501 /* 2502 * This line contains INDEX_TAG 2503 */ 2504 buf = ibuf + index_len; 2505 buf++; /* Skip the space */ 2506 index = parse_index(buf, lifname); 2507 if (index == -1) { 2508 warnx(gettext("Invalid index in the file")); 2509 free(act_props); 2510 return (-1); 2511 } 2512 if (index == policy_index && 2513 (interface_name == NULL || 2514 strncmp(interface_name, lifname, LIFNAMSIZ) == 0)) { 2515 if (!ignore_spd) { 2516 ret = parse_one(fp, act_props); 2517 if (ret == -1) { 2518 warnx(gettext("Invalid policy entry " 2519 "in the file")); 2520 free(act_props); 2521 return (-1); 2522 } 2523 } 2524 /* 2525 * nlines is the number of lines we should comment 2526 * out. linecount tells us how many lines this command 2527 * spans. And we need to remove the line with INDEX 2528 * and an extra line we added during ipsec_conf_add. 2529 * 2530 * NOTE : If somebody added a policy entry which does 2531 * not have a newline, ipsec_conf_add() fills in the 2532 * newline. Hence, there is always 2 extra lines 2533 * to delete. 2534 */ 2535 nlines = linecount + 2; 2536 goto delete; 2537 } 2538 } 2539 2540 if (!ignore_spd) 2541 ret = pfp_delete_rule(policy_index); 2542 2543 if (ret != 0) { 2544 warnx(gettext("Deletion incomplete. Please " 2545 "flush all the entries and re-configure :")); 2546 reconfigure(); 2547 free(act_props); 2548 return (ret); 2549 } 2550 free(act_props); 2551 return (ret); 2552 2553 delete: 2554 /* Delete nlines from prev_offset */ 2555 (void) fclose(fp); 2556 ret = delete_from_file(prev_offset, nlines); 2557 2558 if (ret != 0) { 2559 warnx(gettext("Deletion incomplete. Please " 2560 "flush all the entries and re-configure :")); 2561 reconfigure(); 2562 free(act_props); 2563 return (ret); 2564 } 2565 2566 if (!ignore_spd) 2567 ret = pfp_delete_rule(policy_index); 2568 2569 if (ret != 0) { 2570 warnx(gettext("Deletion incomplete. Please " 2571 "flush all the entries and re-configure :")); 2572 reconfigure(); 2573 free(act_props); 2574 return (ret); 2575 } 2576 free(act_props); 2577 return (0); 2578 } 2579 2580 static int 2581 pfp_delete_rule(uint64_t index) 2582 { 2583 struct spd_msg *msg; 2584 struct spd_rule *rule; 2585 int sfd; 2586 int cnt, len, alloclen; 2587 2588 sfd = get_pf_pol_socket(); 2589 if (sfd < 0) { 2590 warn(gettext("unable to open policy socket")); 2591 return (-1); 2592 } 2593 2594 /* 2595 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 2596 * issues. 2597 */ 2598 alloclen = sizeof (spd_msg_t) + sizeof (struct spd_rule) + 2599 sizeof (spd_if_t) + LIFNAMSIZ + 8; 2600 msg = (spd_msg_t *)malloc(alloclen); 2601 2602 if (msg == NULL) { 2603 warn("malloc"); 2604 return (-1); 2605 } 2606 2607 rule = (struct spd_rule *)(msg + 1); 2608 2609 (void) memset(msg, 0, alloclen); 2610 msg->spd_msg_version = PF_POLICY_V1; 2611 msg->spd_msg_type = SPD_DELETERULE; 2612 msg->spd_msg_len = SPD_8TO64(sizeof (spd_msg_t) 2613 + sizeof (struct spd_rule)); 2614 2615 rule->spd_rule_type = SPD_EXT_RULE; 2616 rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule)); 2617 rule->spd_rule_index = index; 2618 2619 msg->spd_msg_len += attach_tunname((spd_if_t *)(rule + 1)); 2620 2621 len = SPD_64TO8(msg->spd_msg_len); 2622 cnt = write(sfd, msg, len); 2623 2624 if (cnt != len) { 2625 if (cnt < 0) { 2626 (void) close(sfd); 2627 free(msg); 2628 warn(gettext("Delete failed: write")); 2629 return (-1); 2630 } else { 2631 (void) close(sfd); 2632 free(msg); 2633 warnx(gettext("Delete failed: short write")); 2634 return (-1); 2635 } 2636 } 2637 2638 cnt = read(sfd, msg, len); 2639 if (cnt != len) { 2640 if (cnt < 0) { 2641 (void) close(sfd); 2642 free(msg); 2643 warn(gettext("Delete failed: read")); 2644 return (-1); 2645 } else { 2646 (void) close(sfd); 2647 free(msg); 2648 warnx(gettext("Delete failed while reading reply")); 2649 return (-1); 2650 } 2651 } 2652 (void) close(sfd); 2653 if (msg->spd_msg_errno != 0) { 2654 free(msg); 2655 errno = msg->spd_msg_errno; 2656 warn(gettext("Delete failed: SPD_FLUSH")); 2657 return (-1); 2658 } 2659 2660 free(msg); 2661 return (0); 2662 } 2663 2664 static int 2665 ipsec_conf_flush(int db) 2666 { 2667 int pfd, cnt, len; 2668 int sfd; 2669 struct spd_msg *msg; 2670 /* 2671 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 2672 * issues. 2673 */ 2674 uint64_t buffer[ 2675 SPD_8TO64(sizeof (*msg) + sizeof (spd_if_t) + LIFNAMSIZ) + 1]; 2676 2677 sfd = get_pf_pol_socket(); 2678 if (sfd < 0) { 2679 warn(gettext("unable to open policy socket")); 2680 return (-1); 2681 } 2682 2683 (void) memset(buffer, 0, sizeof (buffer)); 2684 msg = (struct spd_msg *)buffer; 2685 msg->spd_msg_version = PF_POLICY_V1; 2686 msg->spd_msg_type = SPD_FLUSH; 2687 msg->spd_msg_len = SPD_8TO64(sizeof (*msg)); 2688 msg->spd_msg_spdid = db; 2689 2690 msg->spd_msg_len += attach_tunname((spd_if_t *)(msg + 1)); 2691 2692 len = SPD_64TO8(msg->spd_msg_len); 2693 cnt = write(sfd, msg, len); 2694 if (cnt != len) { 2695 if (cnt < 0) { 2696 warn(gettext("Flush failed: write")); 2697 return (-1); 2698 } else { 2699 warnx(gettext("Flush failed: short write")); 2700 return (-1); 2701 } 2702 } 2703 2704 cnt = read(sfd, msg, len); 2705 if (cnt != len) { 2706 if (cnt < 0) { 2707 warn(gettext("Flush failed: read")); 2708 return (-1); 2709 } else { 2710 warnx(gettext("Flush failed while reading reply")); 2711 return (-1); 2712 } 2713 } 2714 (void) close(sfd); 2715 if (msg->spd_msg_errno != 0) { 2716 warnx("%s: %s", gettext("Flush failed: SPD_FLUSH"), 2717 sys_error_message(msg->spd_msg_errno)); 2718 return (-1); 2719 } 2720 2721 /* Truncate the file */ 2722 if (db == SPD_ACTIVE) { 2723 if ((pfd = open(POLICY_CONF_FILE, O_TRUNC|O_RDWR)) == -1) { 2724 if (errno == ENOENT) { 2725 /* 2726 * The absence of POLICY_CONF_FILE should 2727 * not cause the command to exit with a 2728 * non-zero status, since this condition 2729 * is valid when no policies were previously 2730 * defined. 2731 */ 2732 return (0); 2733 } 2734 warn(gettext("%s cannot be truncated"), 2735 POLICY_CONF_FILE); 2736 return (-1); 2737 } 2738 (void) close(pfd); 2739 } 2740 return (0); 2741 } 2742 2743 /* 2744 * function to send SPD_FLIP and SPD_CLONE messages 2745 * Do it for ALL polheads for simplicity's sake. 2746 */ 2747 static void 2748 ipsec_conf_admin(uint8_t type) 2749 { 2750 int cnt; 2751 int sfd; 2752 struct spd_msg *msg; 2753 uint64_t buffer[ 2754 SPD_8TO64(sizeof (struct spd_msg) + sizeof (spd_if_t))]; 2755 char *save_ifname; 2756 2757 sfd = get_pf_pol_socket(); 2758 if (sfd < 0) { 2759 err(-1, gettext("unable to open policy socket")); 2760 } 2761 2762 (void) memset(buffer, 0, sizeof (buffer)); 2763 msg = (struct spd_msg *)buffer; 2764 msg->spd_msg_version = PF_POLICY_V1; 2765 msg->spd_msg_type = type; 2766 msg->spd_msg_len = SPD_8TO64(sizeof (buffer)); 2767 2768 save_ifname = interface_name; 2769 /* Apply to all policy heads - global and tunnels. */ 2770 interface_name = &all_polheads; 2771 (void) attach_tunname((spd_if_t *)(msg + 1)); 2772 interface_name = save_ifname; 2773 2774 cnt = write(sfd, msg, sizeof (buffer)); 2775 if (cnt != sizeof (buffer)) { 2776 if (cnt < 0) { 2777 err(-1, gettext("admin failed: write")); 2778 } else { 2779 errx(-1, gettext("admin failed: short write")); 2780 } 2781 } 2782 2783 cnt = read(sfd, msg, sizeof (buffer)); 2784 if (cnt != sizeof (buffer)) { 2785 if (cnt < 0) { 2786 err(-1, gettext("admin failed: read")); 2787 } else { 2788 errx(-1, gettext("admin failed while reading reply")); 2789 } 2790 } 2791 (void) close(sfd); 2792 if (msg->spd_msg_errno != 0) { 2793 errno = msg->spd_msg_errno; 2794 err(-1, gettext("admin failed")); 2795 } 2796 } 2797 2798 static void 2799 reconfigure() 2800 { 2801 (void) fprintf(stderr, gettext( 2802 "\tipsecconf -f \n " 2803 "\tipsecconf -a policy_file\n")); 2804 } 2805 2806 static void 2807 usage(void) 2808 { 2809 (void) fprintf(stderr, gettext( 2810 "Usage: ipsecconf\n" 2811 "\tipsecconf -a ([-]|<filename>) [-q]\n" 2812 "\tipsecconf -c <filename>\n" 2813 "\tipsecconf -r ([-]|<filename>) [-q]\n" 2814 "\tipsecconf -d [-i tunnel-interface] <index>\n" 2815 "\tipsecconf -d <tunnel-interface,index>\n" 2816 "\tipsecconf -l [-n] [-i tunnel-interface]\n" 2817 "\tipsecconf -f [-i tunnel-interface]\n" 2818 "\tipsecconf -L [-n]\n" 2819 "\tipsecconf -F\n")); 2820 } 2821 2822 /* 2823 * a type consists of 2824 * "type" <int>{ "-" <int>} 2825 * or 2826 * "type" keyword 2827 * 2828 * a code consists of 2829 * "code" <int>{ "-" <int>} 2830 * or 2831 * "code" keyword 2832 */ 2833 2834 2835 static int 2836 parse_type_code(const char *str, const str_val_t *table) 2837 { 2838 char *end1, *end2; 2839 int res1 = 0, res2 = 0; 2840 int i; 2841 2842 if (isdigit(str[0])) { 2843 res1 = strtol(str, &end1, 0); 2844 2845 if (end1 == str) { 2846 return (-1); 2847 } 2848 2849 if (res1 > 255 || res1 < 0) { 2850 return (-1); 2851 } 2852 2853 if (*end1 == '-') { 2854 end1++; 2855 res2 = strtol(end1, &end2, 0); 2856 if (res2 > 255 || res2 < 0) { 2857 return (-1); 2858 } 2859 } else { 2860 end2 = end1; 2861 } 2862 2863 while (isspace(*end2)) 2864 end2++; 2865 2866 if (*end2 != '\0') { 2867 return (-1); 2868 } 2869 2870 return (res1 + (res2 << 8)); 2871 } 2872 2873 for (i = 0; table[i].string; i++) { 2874 if (strcmp(str, table[i].string) == 0) { 2875 return (table[i].value); 2876 } 2877 } 2878 2879 return (-1); 2880 } 2881 2882 static int 2883 parse_int(const char *str) 2884 { 2885 char *end; 2886 int res; 2887 2888 res = strtol(str, &end, 0); 2889 if (end == str) 2890 return (-1); 2891 while (isspace(*end)) 2892 end++; 2893 if (*end != '\0') 2894 return (-1); 2895 return (res); 2896 } 2897 2898 /* 2899 * Parses <interface>,<index>. Sets iname or the global interface_name (if 2900 * iname == NULL) to <interface> and returns <index>. Calls exit() if we have 2901 * an interface_name already set. 2902 */ 2903 static int 2904 parse_index(const char *str, char *iname) 2905 { 2906 char *intf, *num, *copy; 2907 int rc; 2908 2909 copy = strdup(str); 2910 if (copy == NULL) { 2911 EXIT_FATAL("Out of memory."); 2912 } 2913 2914 intf = strtok(copy, ","); 2915 /* Just want the rest of the string unmolested, so use "" for arg2. */ 2916 num = strtok(NULL, ""); 2917 if (num == NULL) { 2918 /* No comma found, just parse it like an int. */ 2919 free(copy); 2920 return (parse_int(str)); 2921 } 2922 2923 if (iname != NULL) { 2924 (void) strlcpy(iname, intf, LIFNAMSIZ); 2925 } else { 2926 if (interface_name != NULL) { 2927 EXIT_FATAL("Interface name already selected"); 2928 } 2929 2930 interface_name = strdup(intf); 2931 if (interface_name == NULL) { 2932 EXIT_FATAL("Out of memory."); 2933 } 2934 } 2935 2936 rc = parse_int(num); 2937 free(copy); 2938 return (rc); 2939 } 2940 2941 /* 2942 * Convert a mask to a prefix length. 2943 * Returns prefix length on success, -1 otherwise. 2944 */ 2945 static int 2946 in_getprefixlen(char *mask) 2947 { 2948 int prefixlen; 2949 char *end; 2950 2951 prefixlen = (int)strtol(mask, &end, 10); 2952 if (prefixlen < 0) { 2953 return (-1); 2954 } 2955 if (mask == end) { 2956 return (-1); 2957 } 2958 if (*end != '\0') { 2959 return (-1); 2960 } 2961 return (prefixlen); 2962 } 2963 2964 /* 2965 * Convert a prefix length to a mask. 2966 * Assumes the mask array is zero'ed by the caller. 2967 */ 2968 static void 2969 in_prefixlentomask(unsigned int prefixlen, uchar_t *mask) 2970 { 2971 while (prefixlen > 0) { 2972 if (prefixlen >= 8) { 2973 *mask++ = 0xFF; 2974 prefixlen -= 8; 2975 continue; 2976 } 2977 *mask |= 1 << (8 - prefixlen); 2978 prefixlen--; 2979 } 2980 } 2981 2982 2983 static int 2984 parse_address(int type, char *addr_str) 2985 { 2986 char *ptr; 2987 int prefix_len = 0; 2988 struct netent *ne = NULL; 2989 struct hostent *hp = NULL; 2990 int h_errno; 2991 struct in_addr netaddr; 2992 struct in6_addr *netaddr6; 2993 struct hostent *ne_hent; 2994 boolean_t has_mask = B_FALSE; 2995 2996 ptr = strchr(addr_str, '/'); 2997 if (ptr != NULL) { 2998 has_mask = B_TRUE; 2999 *ptr++ = NULL; 3000 3001 prefix_len = in_getprefixlen(ptr); 3002 if (prefix_len < 0) 3003 return (-1); 3004 } 3005 3006 /* 3007 * getipnodebyname() is thread safe. This allows us to hold on to the 3008 * returned hostent structure, which is pointed to by the shp and 3009 * dhp globals for the source and destination addresses, respectively. 3010 */ 3011 hp = getipnodebyname(addr_str, AF_INET6, AI_DEFAULT | AI_ALL, &h_errno); 3012 if (hp != NULL) { 3013 /* 3014 * We come here for both a hostname and 3015 * any host address /network address. 3016 */ 3017 assert(hp->h_addrtype == AF_INET6); 3018 } else if ((ne = getnetbyname(addr_str)) != NULL) { 3019 switch (ne->n_addrtype) { 3020 case AF_INET: 3021 /* 3022 * Allocate a struct hostent and initialize 3023 * it with the address corresponding to the 3024 * network number previously returned by 3025 * getnetbyname(). Freed by do_address_adds() 3026 * once the policy is defined. 3027 */ 3028 ne_hent = malloc(sizeof (struct hostent)); 3029 if (ne_hent == NULL) { 3030 warn("malloc"); 3031 return (-1); 3032 } 3033 ne_hent->h_addr_list = malloc(2*sizeof (char *)); 3034 if (ne_hent->h_addr_list == NULL) { 3035 warn("malloc"); 3036 free(ne_hent); 3037 return (-1); 3038 } 3039 netaddr6 = malloc(sizeof (struct in6_addr)); 3040 if (netaddr6 == NULL) { 3041 warn("malloc"); 3042 free(ne_hent->h_addr_list); 3043 free(ne_hent); 3044 return (-1); 3045 } 3046 ne_hent->h_addr_list[0] = (char *)netaddr6; 3047 ne_hent->h_addr_list[1] = NULL; 3048 netaddr = inet_makeaddr(ne->n_net, INADDR_ANY); 3049 IN6_INADDR_TO_V4MAPPED(&netaddr, netaddr6); 3050 hp = ne_hent; 3051 break; 3052 default: 3053 warnx("Address type %d not supported.", ne->n_addrtype); 3054 return (-1); 3055 } 3056 } else { 3057 return (-1); 3058 } 3059 3060 if (type == IPSEC_CONF_SRC_ADDRESS) { 3061 shp = hp; 3062 if (has_mask) 3063 splen = prefix_len; 3064 has_saprefix = has_mask; 3065 } else { 3066 dhp = hp; 3067 if (has_mask) 3068 dplen = prefix_len; 3069 has_daprefix = has_mask; 3070 } 3071 3072 return (0); 3073 } 3074 3075 /* 3076 * Add port-only entries. Make sure to add them in both the V6 and V4 tables! 3077 */ 3078 static int 3079 do_port_adds(ips_conf_t *cptr) 3080 { 3081 int ret, diag; 3082 3083 assert(IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)); 3084 assert(IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_addr_v6)); 3085 3086 #ifdef DEBUG_HEAVY 3087 (void) dump_conf(cptr); 3088 #endif 3089 3090 ret = send_pf_pol_message(SPD_ADDRULE, cptr, &diag); 3091 if (ret != 0 && !ipsecconf_qflag) { 3092 warnx( 3093 gettext("Could not add IPv4 policy for sport %d, dport %d " 3094 "- diagnostic %d - %s"), ntohs(cptr->ips_src_port_min), 3095 ntohs(cptr->ips_dst_port_min), diag, spdsock_diag(diag)); 3096 } 3097 3098 return (ret); 3099 } 3100 3101 /* 3102 * Nuke a list of policy entries. 3103 * rewrite this to use flipping 3104 * d_list isn't freed because we will be 3105 * exiting the program soon. 3106 */ 3107 static void 3108 nuke_adds() 3109 { 3110 d_list_t *temp = d_list; 3111 FILE *policy_fp; 3112 3113 policy_fp = fopen(POLICY_CONF_FILE, "a"); 3114 if (policy_fp == NULL) { 3115 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 3116 } 3117 (void) fprintf(policy_fp, "\n\n"); 3118 (void) fflush(policy_fp); 3119 3120 while (temp != NULL) { 3121 (void) ipsec_conf_del(temp->index, B_TRUE); 3122 temp = temp->next; 3123 } 3124 } 3125 3126 /* 3127 * Set mask info from the specified prefix len. Fail if multihomed. 3128 */ 3129 static int 3130 set_mask_info(struct hostent *hp, unsigned int plen, struct in6_addr *mask_v6) 3131 { 3132 struct in6_addr addr; 3133 struct in_addr mask_v4; 3134 3135 if (hp->h_addr_list[1] != NULL) { 3136 return (EOPNOTSUPP); 3137 } 3138 3139 if (!IN6_IS_ADDR_UNSPECIFIED(mask_v6)) { 3140 return (EBUSY); 3141 } 3142 3143 bcopy(hp->h_addr_list[0], &addr, sizeof (struct in6_addr)); 3144 if (IN6_IS_ADDR_V4MAPPED(&addr)) { 3145 if (plen > IP_ABITS) { 3146 return (ERANGE); 3147 } 3148 (void) memset(&mask_v4, 0, sizeof (mask_v4)); 3149 in_prefixlentomask(plen, (uchar_t *)&mask_v4); 3150 IN6_INADDR_TO_V4MAPPED(&mask_v4, mask_v6); 3151 } else { 3152 if (plen > IPV6_ABITS) { 3153 return (ERANGE); 3154 } 3155 /* mask_v6 is already zero (unspecified), see test above */ 3156 in_prefixlentomask(plen, (uchar_t *)mask_v6); 3157 } 3158 return (0); 3159 } 3160 3161 /* 3162 * Initialize the specified IPv6 address with all f's. 3163 */ 3164 static void 3165 init_addr_wildcard(struct in6_addr *addr_v6, boolean_t isv4) 3166 { 3167 if (isv4) { 3168 uint32_t addr_v4 = 0xffffffff; 3169 IN6_INADDR_TO_V4MAPPED((struct in_addr *)&addr_v4, addr_v6); 3170 } else { 3171 (void) memset(addr_v6, 0xff, sizeof (struct in6_addr)); 3172 } 3173 } 3174 3175 /* 3176 * Called at the end to actually add policy. Handles single and multi-homed 3177 * cases. 3178 */ 3179 static int 3180 do_address_adds(ips_conf_t *cptr, int *diag) 3181 { 3182 int i, j; 3183 int ret = 0; /* For ioctl() call. */ 3184 int rc = 0; /* My own return code. */ 3185 struct in6_addr zeroes = {0, 0, 0, 0}; 3186 char *ptr[2]; 3187 struct hostent hent; 3188 boolean_t isv4; 3189 int add_count = 0; 3190 3191 /* 3192 * dst_hent may not be initialized if a destination 3193 * address was not given. It will be initalized with just 3194 * one address if a destination address was given. In both 3195 * the cases, we initialize here with ipsc_dst_addr and enter 3196 * the loop below. 3197 */ 3198 if (dhp == NULL) { 3199 assert(shp != NULL); 3200 hent.h_addr_list = ptr; 3201 ptr[0] = (char *)&zeroes.s6_addr; 3202 ptr[1] = NULL; 3203 dhp = &hent; 3204 } else if (shp == NULL) { 3205 assert(dhp != NULL); 3206 hent.h_addr_list = ptr; 3207 ptr[0] = (char *)&zeroes.s6_addr; 3208 ptr[1] = NULL; 3209 shp = &hent; 3210 } 3211 3212 /* 3213 * Set mask info here. Bail if multihomed and there's a prefix len. 3214 */ 3215 if (has_saprefix) { 3216 rc = set_mask_info(shp, splen, &cptr->ips_src_mask_v6); 3217 if (rc != 0) 3218 goto bail; 3219 cptr->ips_src_mask_len = splen; 3220 } 3221 3222 if (has_daprefix) { 3223 rc = set_mask_info(dhp, dplen, &cptr->ips_dst_mask_v6); 3224 if (rc != 0) 3225 goto bail; 3226 cptr->ips_dst_mask_len = dplen; 3227 } 3228 3229 for (i = 0; shp->h_addr_list[i] != NULL; i++) { 3230 bcopy(shp->h_addr_list[i], &cptr->ips_src_addr_v6, 3231 sizeof (struct in6_addr)); 3232 isv4 = cptr->ips_isv4 = 3233 IN6_IS_ADDR_V4MAPPED(&cptr->ips_src_addr_v6); 3234 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_mask_v6) && 3235 shp != &hent) { 3236 init_addr_wildcard(&cptr->ips_src_mask_v6, isv4); 3237 } 3238 3239 for (j = 0; dhp->h_addr_list[j] != NULL; j++) { 3240 bcopy(dhp->h_addr_list[j], &cptr->ips_dst_addr_v6, 3241 sizeof (struct in6_addr)); 3242 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)) { 3243 /* 3244 * Src was not specified, so update isv4 flag 3245 * for this policy according to the family 3246 * of the destination address. 3247 */ 3248 isv4 = cptr->ips_isv4 = 3249 IN6_IS_ADDR_V4MAPPED( 3250 &cptr->ips_dst_addr_v6); 3251 } else if ((dhp != &hent) && (isv4 != 3252 IN6_IS_ADDR_V4MAPPED(&cptr->ips_dst_addr_v6))) { 3253 /* v6/v4 mismatch. */ 3254 continue; 3255 } 3256 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_mask_v6) && 3257 dhp != &hent) { 3258 init_addr_wildcard(&cptr->ips_dst_mask_v6, 3259 isv4); 3260 } 3261 3262 ret = send_pf_pol_message(SPD_ADDRULE, cptr, diag); 3263 3264 if (ret == 0) { 3265 add_count++; 3266 } else { 3267 /* For now, allow duplicate/overlap policies. */ 3268 if (ret != EEXIST) { 3269 /* 3270 * We have an error where we added 3271 * some, but had errors with others. 3272 * Undo the previous adds, and 3273 * bail. 3274 */ 3275 rc = ret; 3276 goto bail; 3277 } 3278 } 3279 3280 bzero(&cptr->ips_dst_mask_v6, 3281 sizeof (struct in6_addr)); 3282 } 3283 3284 bzero(&cptr->ips_src_mask_v6, sizeof (struct in6_addr)); 3285 } 3286 3287 bail: 3288 if (shp != &hent) 3289 freehostent(shp); 3290 shp = NULL; 3291 if (dhp != &hent) 3292 freehostent(dhp); 3293 dhp = NULL; 3294 splen = 0; 3295 dplen = 0; 3296 3297 if ((add_count == 0) && (rc == 0)) { 3298 /* 3299 * No entries were added. We failed all adds 3300 * because the entries already existed, or because 3301 * no v4 or v6 src/dst pairs were found. Either way, 3302 * we must fail here with an appropriate error 3303 * to avoid a corresponding entry from being added 3304 * to ipsecpolicy.conf. 3305 */ 3306 if ((ret == EEXIST)) { 3307 /* All adds failed with EEXIST */ 3308 rc = EEXIST; 3309 } else { 3310 /* No matching v4 or v6 src/dst pairs */ 3311 rc = ESRCH; 3312 } 3313 } 3314 3315 return (rc); 3316 } 3317 3318 static int 3319 parse_mask(int type, char *mask_str, ips_conf_t *cptr) 3320 { 3321 struct in_addr mask; 3322 struct in6_addr *mask6; 3323 3324 if (type == IPSEC_CONF_SRC_MASK) { 3325 mask6 = &cptr->ips_src_mask_v6; 3326 } else { 3327 mask6 = &cptr->ips_dst_mask_v6; 3328 } 3329 3330 if ((strncasecmp(mask_str, "0x", 2) == 0) && 3331 (strchr(mask_str, '.') == NULL)) { 3332 /* Is it in the form 0xff000000 ? */ 3333 char *end; 3334 3335 mask.s_addr = strtoul(mask_str, &end, 0); 3336 if (end == mask_str) { 3337 return (-1); 3338 } 3339 if (*end != '\0') { 3340 return (-1); 3341 } 3342 mask.s_addr = htonl(mask.s_addr); 3343 } else { 3344 /* 3345 * Since inet_addr() returns -1 on error, we have 3346 * to convert a broadcast address ourselves. 3347 */ 3348 if (strcmp(mask_str, "255.255.255.255") == 0) { 3349 mask.s_addr = 0xffffffff; 3350 } else { 3351 mask.s_addr = inet_addr(mask_str); 3352 if (mask.s_addr == (unsigned int)-1) 3353 return (-1); 3354 } 3355 } 3356 3357 /* Should we check for non-contiguous masks ? */ 3358 if (mask.s_addr == 0) 3359 return (-1); 3360 IN6_INADDR_TO_V4MAPPED(&mask, mask6); 3361 3362 3363 if (type == IPSEC_CONF_SRC_MASK) { 3364 cptr->ips_src_mask_len = in_masktoprefix(mask6->s6_addr, 3365 B_TRUE); 3366 } else { 3367 cptr->ips_dst_mask_len = in_masktoprefix(mask6->s6_addr, 3368 B_TRUE); 3369 } 3370 3371 return (0); 3372 } 3373 3374 static int 3375 parse_port(int type, char *port_str, ips_conf_t *conf) 3376 { 3377 struct servent *sent; 3378 in_port_t port; 3379 int ret; 3380 3381 sent = getservbyname(port_str, NULL); 3382 if (sent == NULL) { 3383 ret = parse_int(port_str); 3384 if (ret < 0 || ret >= 65536) { 3385 return (-1); 3386 } 3387 port = htons((in_port_t)ret); 3388 } else { 3389 port = sent->s_port; 3390 } 3391 if (type == IPSEC_CONF_SRC_PORT) { 3392 conf->ips_src_port_min = conf->ips_src_port_max = port; 3393 } else { 3394 conf->ips_dst_port_min = conf->ips_dst_port_max = port; 3395 } 3396 return (0); 3397 } 3398 3399 static int 3400 valid_algorithm(int proto_num, const char *str) 3401 { 3402 const char *tmp; 3403 int ret; 3404 struct ipsecalgent *alg; 3405 3406 /* Short-circuit "none" */ 3407 if (strncasecmp("none", str, 5) == 0) 3408 return (-2); 3409 3410 alg = getipsecalgbyname(str, proto_num, NULL); 3411 if (alg != NULL) { 3412 ret = alg->a_alg_num; 3413 freeipsecalgent(alg); 3414 return (ret); 3415 } 3416 3417 /* 3418 * Look whether it could be a valid number. 3419 * We support numbers also so that users can 3420 * load algorithms as they need it. We can't 3421 * check for validity of numbers here. It will 3422 * be checked when the SA is negotiated/looked up. 3423 * parse_int uses strtol(str), which converts 3DES 3424 * to a valid number i.e looks only at initial 3425 * number part. If we come here we should expect 3426 * only a decimal number. 3427 */ 3428 tmp = str; 3429 while (*tmp) { 3430 if (!isdigit(*tmp)) 3431 return (-1); 3432 tmp++; 3433 } 3434 3435 ret = parse_int(str); 3436 if (ret > 0 && ret <= 255) 3437 return (ret); 3438 else 3439 return (-1); 3440 } 3441 3442 static int 3443 parse_ipsec_alg(char *str, ips_act_props_t *iap, int alg_type) 3444 { 3445 int alg_value; 3446 char tstr[VALID_ALG_LEN]; 3447 char *lens = NULL; 3448 char *l1_str; 3449 int l1 = 0; 3450 char *l2_str; 3451 int l2 = SPD_MAX_MAXBITS; 3452 algreq_t *ap; 3453 uint_t a_type; 3454 3455 fetch_algorithms(); 3456 3457 /* 3458 * Make sure that we get a null terminated string. 3459 * For a bad input, we truncate at VALID_ALG_LEN. 3460 */ 3461 (void) strlcpy(tstr, str, VALID_ALG_LEN); 3462 lens = strtok(tstr, "()"); 3463 lens = strtok(NULL, "()"); 3464 3465 if (lens != NULL) { 3466 int len1 = 0; 3467 int len2 = SPD_MAX_MAXBITS; 3468 int len_all = strlen(lens); 3469 int dot_start = (lens[0] == '.'); 3470 l1_str = strtok(lens, "."); 3471 l2_str = strtok(NULL, "."); 3472 if (l1_str != NULL) { 3473 l1 = parse_int(l1_str); 3474 len1 = strlen(l1_str); 3475 if (len1 < 0) 3476 return (1); 3477 } 3478 if (l2_str != NULL) { 3479 l2 = parse_int(l2_str); 3480 len2 = strlen(l2_str); 3481 if (len2 < 0) 3482 return (1); 3483 } 3484 3485 if (len_all == len1) { 3486 /* alg(n) */ 3487 l2 = l1; 3488 } else if (dot_start) { 3489 /* alg(..n) */ 3490 l2 = l1; 3491 l1 = 0; 3492 } else if ((len_all - 2) == len1) { 3493 /* alg(n..) */ 3494 l2 = SPD_MAX_MAXBITS; 3495 } /* else alg(n..m) */ 3496 } 3497 3498 if (alg_type == SPD_ATTR_AH_AUTH || 3499 alg_type == SPD_ATTR_ESP_AUTH) { 3500 alg_value = valid_algorithm(IPSEC_PROTO_AH, tstr); 3501 } else { 3502 alg_value = valid_algorithm(IPSEC_PROTO_ESP, tstr); 3503 } 3504 if (alg_value < 0) { 3505 /* Invalid algorithm or "none" */ 3506 return (alg_value); 3507 } 3508 3509 if (alg_type == SPD_ATTR_AH_AUTH) { 3510 a_type = AH_AUTH; 3511 iap->iap_attr |= SPD_APPLY_AH; 3512 ap = &(iap->iap_aauth); 3513 } else if (alg_type == SPD_ATTR_ESP_AUTH) { 3514 a_type = ESP_AUTH; 3515 iap->iap_attr |= SPD_APPLY_ESP|SPD_APPLY_ESPA; 3516 ap = &(iap->iap_eauth); 3517 } else { 3518 a_type = ESP_ENCR; 3519 iap->iap_attr |= SPD_APPLY_ESP; 3520 ap = &(iap->iap_eencr); 3521 } 3522 3523 ap->alg_id = alg_value; 3524 ap->alg_minbits = l1; 3525 ap->alg_maxbits = l2; 3526 3527 if (!alg_rangecheck(a_type, alg_value, ap)) 3528 return (1); 3529 3530 return (0); 3531 } 3532 3533 static char * 3534 sys_error_message(int syserr) 3535 { 3536 char *mesg; 3537 3538 switch (syserr) { 3539 case EEXIST: 3540 mesg = gettext("Entry already exists"); 3541 break; 3542 case ENOENT: 3543 mesg = gettext("Tunnel not found"); 3544 break; 3545 case EINVAL: 3546 mesg = gettext("Invalid entry"); 3547 break; 3548 default : 3549 mesg = strerror(syserr); 3550 } 3551 return (mesg); 3552 } 3553 3554 static void 3555 error_message(error_type_t error, int type, int line) 3556 { 3557 char *mesg; 3558 3559 switch (type) { 3560 case IPSEC_CONF_SRC_ADDRESS: 3561 mesg = gettext("Source Address"); 3562 break; 3563 case IPSEC_CONF_DST_ADDRESS: 3564 mesg = gettext("Destination Address"); 3565 break; 3566 case IPSEC_CONF_SRC_PORT: 3567 mesg = gettext("Source Port"); 3568 break; 3569 case IPSEC_CONF_DST_PORT: 3570 mesg = gettext("Destination Port"); 3571 break; 3572 case IPSEC_CONF_SRC_MASK: 3573 mesg = gettext("Source Mask"); 3574 break; 3575 case IPSEC_CONF_DST_MASK: 3576 mesg = gettext("Destination Mask"); 3577 break; 3578 case IPSEC_CONF_ULP: 3579 mesg = gettext("Upper Layer Protocol"); 3580 break; 3581 case IPSEC_CONF_IPSEC_AALGS: 3582 mesg = gettext("Authentication Algorithm"); 3583 break; 3584 case IPSEC_CONF_IPSEC_EALGS: 3585 mesg = gettext("Encryption Algorithm"); 3586 break; 3587 case IPSEC_CONF_IPSEC_EAALGS: 3588 mesg = gettext("ESP Authentication Algorithm"); 3589 break; 3590 case IPSEC_CONF_IPSEC_SA: 3591 mesg = gettext("SA"); 3592 break; 3593 case IPSEC_CONF_IPSEC_DIR: 3594 mesg = gettext("Direction"); 3595 break; 3596 case IPSEC_CONF_ICMP_TYPE: 3597 mesg = gettext("ICMP type"); 3598 break; 3599 case IPSEC_CONF_ICMP_CODE: 3600 mesg = gettext("ICMP code"); 3601 break; 3602 case IPSEC_CONF_NEGOTIATE: 3603 mesg = gettext("Negotiate"); 3604 break; 3605 case IPSEC_CONF_TUNNEL: 3606 mesg = gettext("Tunnel"); 3607 break; 3608 default : 3609 return; 3610 } 3611 /* 3612 * If we never read a newline character, we don't want 3613 * to print 0. 3614 */ 3615 warnx(gettext("%s%s%s %s on line: %d"), 3616 (error == BAD_ERROR) ? gettext("Bad") : "", 3617 (error == DUP_ERROR) ? gettext("Duplicate") : "", 3618 (error == REQ_ERROR) ? gettext("Requires") : "", 3619 mesg, 3620 (arg_indices[line] == 0) ? 1 : arg_indices[line]); 3621 } 3622 3623 static int 3624 validate_properties(ips_act_props_t *cptr, boolean_t dir, boolean_t is_alg) 3625 { 3626 if (cptr->iap_action == SPD_ACTTYPE_PASS || 3627 cptr->iap_action == SPD_ACTTYPE_DROP) { 3628 if (!dir) { 3629 warnx(gettext("dir string " 3630 "not found for bypass policy")); 3631 } 3632 3633 if (is_alg) { 3634 warnx(gettext("Algorithms found for bypass policy")); 3635 return (-1); 3636 } 3637 return (0); 3638 } 3639 if (!is_alg) { 3640 warnx(gettext("No IPsec algorithms given")); 3641 return (-1); 3642 } 3643 if (cptr->iap_attr == 0) { 3644 warnx(gettext("No SA attribute")); 3645 return (-1); 3646 } 3647 return (0); 3648 } 3649 3650 /* 3651 * This function is called only to parse a single rule's worth of 3652 * action strings. This is called after parsing pattern and before 3653 * parsing properties. Thus we may have something in the leftover 3654 * buffer while parsing the pattern, which we need to handle here. 3655 */ 3656 static int 3657 parse_action(FILE *fp, char **action, char **leftover) 3658 { 3659 char *cp; 3660 char ibuf[MAXLEN]; 3661 char *tmp_buf; 3662 char *buf; 3663 boolean_t new_stuff; 3664 3665 if (*leftover != NULL) { 3666 buf = *leftover; 3667 new_stuff = B_FALSE; 3668 goto scan; 3669 } 3670 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3671 new_stuff = B_TRUE; 3672 if (ibuf[strlen(ibuf) - 1] == '\n') 3673 linecount++; 3674 buf = ibuf; 3675 scan: 3676 /* Truncate at the beginning of a comment */ 3677 cp = strchr(buf, '#'); 3678 if (cp != NULL) 3679 *cp = NULL; 3680 3681 /* Skip any whitespace */ 3682 while (*buf != NULL && isspace(*buf)) 3683 buf++; 3684 3685 /* Empty line */ 3686 if (*buf == NULL) 3687 continue; 3688 3689 /* 3690 * Store the command for error reporting 3691 * and ipsec_conf_add(). 3692 */ 3693 if (new_stuff) { 3694 /* 3695 * Check for buffer overflow including the null 3696 * terminating character. 3697 */ 3698 int len = strlen(ibuf); 3699 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3700 return (-1); 3701 3702 (void) strcpy(cbuf + cbuf_offset, ibuf); 3703 cbuf_offset += len; 3704 } 3705 /* 3706 * Start of the non-empty non-space character. 3707 */ 3708 tmp_buf = buf; 3709 3710 /* Skip until next whitespace or CURL_BEGIN */ 3711 while (*buf != NULL && !isspace(*buf) && 3712 *buf != CURL_BEGIN) 3713 buf++; 3714 3715 if (*buf != NULL) { 3716 if (tmp_buf == buf) /* No action token */ 3717 goto error; 3718 if (*buf == CURL_BEGIN) { 3719 *buf = NULL; 3720 /* Allocate an extra byte for the null also */ 3721 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3722 NULL) { 3723 warn("malloc"); 3724 return (ENOMEM); 3725 } 3726 (void) strcpy(*action, tmp_buf); 3727 *buf = CURL_BEGIN; 3728 } else { 3729 /* We have hit a space */ 3730 *buf++ = NULL; 3731 /* Allocate an extra byte for the null also */ 3732 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3733 NULL) { 3734 warn("malloc"); 3735 return (ENOMEM); 3736 } 3737 (void) strcpy(*action, tmp_buf); 3738 } 3739 /* 3740 * Copy the rest of the line into the 3741 * leftover buffer. 3742 */ 3743 if (*buf != NULL) { 3744 (void) strlcpy(lo_buf, buf, sizeof (lo_buf)); 3745 *leftover = lo_buf; 3746 } else { 3747 *leftover = NULL; 3748 } 3749 } else { 3750 /* Allocate an extra byte for the null also */ 3751 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3752 NULL) { 3753 warn("malloc"); 3754 return (ENOMEM); 3755 } 3756 (void) strcpy(*action, tmp_buf); 3757 *leftover = NULL; 3758 } 3759 if (argindex >= ARG_BUF_LEN) { 3760 warnx(gettext("(parsing one command) " 3761 "Too many selectors before action.")); 3762 return (-1); 3763 } 3764 arg_indices[argindex++] = linecount; 3765 return (PARSE_SUCCESS); 3766 } 3767 /* 3768 * Return error, on an empty action field. 3769 */ 3770 error: 3771 warnx(gettext("(parsing one command) " 3772 "Missing action token.")); 3773 return (-1); 3774 } 3775 3776 /* 3777 * This is called to parse pattern or properties that is enclosed 3778 * between CURL_BEGIN and CURL_END. 3779 */ 3780 static int 3781 parse_pattern_or_prop(FILE *fp, char *argvec[], char **leftover) 3782 { 3783 char *cp; 3784 int i = 0; 3785 boolean_t curl_begin_seen = B_FALSE; 3786 char ibuf[MAXLEN]; 3787 char *tmp_buf; 3788 char *buf; 3789 boolean_t new_stuff; 3790 3791 /* 3792 * When parsing properties, leftover buffer could have the 3793 * leftovers of the previous fgets(). 3794 */ 3795 if (*leftover != NULL) { 3796 buf = *leftover; 3797 new_stuff = B_FALSE; 3798 goto scan; 3799 } 3800 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3801 new_stuff = B_TRUE; 3802 #ifdef DEBUG_HEAVY 3803 (void) printf("%s\n", ibuf); 3804 #endif 3805 if (ibuf[strlen(ibuf) - 1] == '\n') 3806 linecount++; 3807 buf = ibuf; 3808 scan: 3809 /* Truncate at the beginning of a comment */ 3810 cp = strchr(buf, '#'); 3811 if (cp != NULL) 3812 *cp = NULL; 3813 3814 /* Skip any whitespace */ 3815 while (*buf != NULL && isspace(*buf)) 3816 buf++; 3817 3818 /* Empty line */ 3819 if (*buf == NULL) 3820 continue; 3821 /* 3822 * Store the command for error reporting 3823 * and ipsec_conf_add(). 3824 */ 3825 if (new_stuff) { 3826 /* 3827 * Check for buffer overflow including the null 3828 * terminating character. 3829 */ 3830 int len = strlen(ibuf); 3831 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3832 return (-1); 3833 (void) strcpy(cbuf + cbuf_offset, ibuf); 3834 cbuf_offset += len; 3835 } 3836 /* 3837 * First non-space character should be 3838 * a curly bracket. 3839 */ 3840 if (!curl_begin_seen) { 3841 if (*buf != CURL_BEGIN) { 3842 /* 3843 * If we never read a newline character, 3844 * we don't want to print 0. 3845 */ 3846 warnx(gettext("line %d : pattern must start " 3847 "with \"%c\" character"), 3848 (linecount == 0) ? 1 : linecount, 3849 CURL_BEGIN); 3850 return (-1); 3851 } 3852 buf++; 3853 curl_begin_seen = B_TRUE; 3854 } 3855 /* 3856 * Arguments are separated by white spaces or 3857 * newlines. Scan till you see a CURL_END. 3858 */ 3859 while (*buf != NULL) { 3860 if (*buf == CURL_END) { 3861 ret: 3862 *buf++ = NULL; 3863 /* 3864 * Copy the rest of the line into the 3865 * leftover buffer if any. 3866 */ 3867 if (*buf != NULL) { 3868 (void) strlcpy(lo_buf, buf, 3869 sizeof (lo_buf)); 3870 *leftover = lo_buf; 3871 } else { 3872 *leftover = NULL; 3873 } 3874 return (PARSE_SUCCESS); 3875 } 3876 /* 3877 * Skip any trailing whitespace until we see a 3878 * non white-space character. 3879 */ 3880 while (*buf != NULL && isspace(*buf)) 3881 buf++; 3882 3883 if (*buf == CURL_END) 3884 goto ret; 3885 3886 /* Scan the next line as this buffer is empty */ 3887 if (*buf == NULL) 3888 break; 3889 3890 if (i >= MAXARGS) { 3891 warnx( 3892 gettext("Number of Arguments exceeded %d"), 3893 i); 3894 return (-1); 3895 } 3896 /* 3897 * Non-empty, Non-space buffer. 3898 */ 3899 tmp_buf = buf++; 3900 /* 3901 * Real scan of the argument takes place here. 3902 * Skip past till space or CURL_END. 3903 */ 3904 while (*buf != NULL && !isspace(*buf) && 3905 *buf != CURL_END) { 3906 buf++; 3907 } 3908 /* 3909 * Either a space or we have hit the CURL_END or 3910 * the real end. 3911 */ 3912 if (*buf != NULL) { 3913 if (*buf == CURL_END) { 3914 *buf++ = NULL; 3915 if ((argvec[i] = malloc(strlen(tmp_buf) 3916 + 1)) == NULL) { 3917 warn("malloc"); 3918 return (ENOMEM); 3919 } 3920 if (strlen(tmp_buf) != 0) { 3921 (void) strcpy(argvec[i], 3922 tmp_buf); 3923 if (argindex >= ARG_BUF_LEN) 3924 goto toomanyargs; 3925 arg_indices[argindex++] = 3926 linecount; 3927 } 3928 /* 3929 * Copy the rest of the line into the 3930 * leftover buffer. 3931 */ 3932 if (*buf != NULL) { 3933 (void) strlcpy(lo_buf, buf, 3934 sizeof (lo_buf)); 3935 *leftover = lo_buf; 3936 } else { 3937 *leftover = NULL; 3938 } 3939 return (PARSE_SUCCESS); 3940 } else { 3941 *buf++ = NULL; 3942 } 3943 } 3944 /* 3945 * Copy this argument and scan for the buffer more 3946 * if it is non-empty. If it is empty scan for 3947 * the next line. 3948 */ 3949 if ((argvec[i] = malloc(strlen(tmp_buf) + 1)) == 3950 NULL) { 3951 warn("malloc"); 3952 return (ENOMEM); 3953 } 3954 (void) strcpy(argvec[i++], tmp_buf); 3955 if (argindex >= ARG_BUF_LEN) { 3956 /* 3957 * The number of tokens in a single policy entry 3958 * exceeds the number of buffers available to fully 3959 * parse the policy entry. 3960 */ 3961 toomanyargs: 3962 warnx(gettext("(parsing one command) " 3963 "Too many tokens in single policy entry.")); 3964 return (-1); 3965 } 3966 arg_indices[argindex++] = linecount; 3967 } 3968 } 3969 /* 3970 * If nothing is given in the file, it is okay. 3971 * If something is given in the file and it is 3972 * not CURL_BEGIN, we would have returned error 3973 * above. If curl_begin_seen and we are here, 3974 * something is wrong. 3975 */ 3976 if (curl_begin_seen) { 3977 warnx(gettext("(parsing one command) " 3978 "Pattern or Properties incomplete.")); 3979 return (-1); 3980 } 3981 return (PARSE_EOF); /* Nothing more in the file */ 3982 } 3983 3984 /* 3985 * Parse one command i.e {pattern} action {properties}. 3986 * 3987 * {pattern} ( action {prop} | pass | drop ) (or ...)* 3988 */ 3989 static int 3990 parse_one(FILE *fp, act_prop_t *act_props) 3991 { 3992 char *leftover; 3993 int ret; 3994 int i; 3995 int ap_num = 0; 3996 enum parse_state {pattern, action, prop } pstate; 3997 3998 has_daprefix = has_saprefix = B_FALSE; 3999 4000 (void) memset(act_props, 0, sizeof (act_prop_t)); 4001 pstate = pattern; 4002 4003 ret = 0; 4004 leftover = NULL; 4005 argindex = 0; 4006 cbuf_offset = 0; 4007 assert(shp == NULL && dhp == NULL); 4008 4009 for (;;) { 4010 switch (pstate) { 4011 case pattern: 4012 { 4013 #ifdef DEBUG_HEAVY 4014 (void) printf("pattern\n"); 4015 #endif 4016 ret = parse_pattern_or_prop(fp, 4017 act_props->pattern, &leftover); 4018 if (ret == PARSE_EOF) { 4019 /* EOF reached */ 4020 return (PARSE_EOF); 4021 } 4022 if (ret != 0) { 4023 ret = -1; 4024 goto err; 4025 } 4026 pstate = action; 4027 break; 4028 } 4029 case action: 4030 { 4031 #ifdef DEBUG_HEAVY 4032 (void) printf("action\n"); 4033 #endif 4034 ret = parse_action(fp, 4035 &act_props->ap[ap_num].act, &leftover); 4036 if (ret != 0) { 4037 ret = -1; 4038 goto err; 4039 } 4040 4041 /* 4042 * Validate action now itself so that we don't 4043 * proceed too much into the bad world. 4044 */ 4045 for (i = 0; action_table[i].string; i++) { 4046 if (strcmp(act_props->ap[ap_num].act, 4047 action_table[i].string) == 0) 4048 break; 4049 } 4050 4051 if (action_table[i].tok_val == TOK_or) { 4052 /* hit an or, go again */ 4053 break; 4054 } 4055 4056 if (action_table[i].string == NULL) { 4057 /* 4058 * If we never read a newline 4059 * character, we don't want 4060 * to print 0. 4061 */ 4062 warnx(gettext("(parsing one command) " 4063 "Invalid action on line %d: %s"), 4064 (linecount == 0) ? 1 : linecount, 4065 act_props->ap[ap_num].act); 4066 return (-1); 4067 } 4068 4069 pstate = prop; 4070 break; 4071 } 4072 case prop: 4073 { 4074 #ifdef DEBUG_HEAVY 4075 (void) printf("prop\n"); 4076 #endif 4077 ret = parse_pattern_or_prop(fp, 4078 act_props->ap[ap_num].prop, &leftover); 4079 if (ret != 0) { 4080 if (ret == PARSE_EOF) { 4081 warnx(gettext("(parsing one command) " 4082 "Missing properties.")); 4083 } 4084 ret = -1; 4085 goto err; 4086 } 4087 4088 if (leftover != NULL) { 4089 /* Accomodate spaces at the end */ 4090 while (*leftover != NULL) { 4091 if (*leftover == BACK_SLASH) { 4092 warnx(gettext("Invalid line " 4093 "continuation character.")); 4094 ret = -1; 4095 goto err; 4096 } 4097 if (*leftover == 'o') { 4098 leftover++; 4099 if (*leftover == 'r') { 4100 leftover++; 4101 ap_num++; 4102 pstate = action; 4103 goto again; 4104 } 4105 } 4106 if (!isspace(*leftover)) { 4107 ret = -1; 4108 goto err; 4109 } 4110 leftover++; 4111 } 4112 return (0); 4113 } 4114 ap_num++; 4115 if (ap_num > MAXARGS) 4116 return (0); 4117 pstate = action; /* or */ 4118 break; 4119 } /* case prop: */ 4120 } /* switch(pstate) */ 4121 4122 again: 4123 if (ap_num > MAXARGS) { 4124 warnx(gettext("Too many actions.")); 4125 return (-1); 4126 } 4127 } /* for(;;) */ 4128 err: 4129 if (ret != 0) { 4130 /* 4131 * If we never read a newline character, we don't want 4132 * to print 0. 4133 */ 4134 warnx(gettext("Error before or at line %d"), 4135 (linecount == 0) ? 1 : linecount); 4136 } 4137 return (ret); 4138 } 4139 4140 /* 4141 * convert an act_propts_t to an ips_conf_t 4142 */ 4143 4144 static int 4145 form_ipsec_conf(act_prop_t *act_props, ips_conf_t *cptr) 4146 { 4147 int i, j, k; 4148 int tok_count = 0; 4149 struct protoent *pent; 4150 boolean_t saddr, daddr, ipsec_aalg, ipsec_ealg, ipsec_eaalg, dir; 4151 boolean_t old_style, new_style; 4152 struct in_addr mask; 4153 int line_no; 4154 int ret; 4155 int ap_num = 0; 4156 int type, code, type_end, code_end; 4157 #ifdef DEBUG_HEAVY 4158 /* 4159 * pattern => act_props->pattern 4160 * action => act_props->ap[].act 4161 * properties => act_props->ap[].prop 4162 */ 4163 (void) printf("\npattern\n------------\n"); 4164 for (i = 0; act_props->pattern[i] != NULL; i++) 4165 (void) printf("%s\n", act_props->pattern[i]); 4166 (void) printf("apz\n----------\n"); 4167 for (j = 0; act_props->ap[j].act != NULL; j++) { 4168 4169 (void) printf("act%d->%s\n", j, act_props->ap[j].act); 4170 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 4171 (void) printf("%dprop%d->%s\n", 4172 j, i, act_props->ap[j].prop[i]); 4173 } 4174 (void) printf("------------\n\n"); 4175 #endif 4176 4177 (void) memset(cptr, 0, sizeof (ips_conf_t)); 4178 saddr = daddr = ipsec_aalg = ipsec_ealg = ipsec_eaalg = dir = B_FALSE; 4179 old_style = new_style = B_FALSE; 4180 /* 4181 * Get the Pattern. NULL pattern is valid. 4182 */ 4183 for (i = 0, line_no = 0; act_props->pattern[i]; i++, line_no++) { 4184 for (j = 0; pattern_table[j].string; j++) { 4185 if (strcmp(act_props->pattern[i], 4186 pattern_table[j].string) == 0) 4187 break; 4188 } 4189 4190 if (pattern_table[j].string == NULL) { 4191 /* 4192 * If we never read a newline character, we don't want 4193 * to print 0. 4194 */ 4195 warnx(gettext("Invalid pattern on line %d: %s"), 4196 (arg_indices[line_no] == 0) ? 1 : 4197 arg_indices[line_no], act_props->pattern[i]); 4198 return (-1); 4199 } 4200 4201 cptr->patt_tok[tok_count++] = pattern_table[j].tok_val; 4202 4203 switch (pattern_table[j].tok_val) { 4204 4205 case TOK_dir: 4206 i++, line_no++; 4207 if (act_props->pattern[i] == NULL) { 4208 error_message(BAD_ERROR, 4209 IPSEC_CONF_IPSEC_DIR, line_no); 4210 return (-1); 4211 } 4212 4213 if (strncmp(act_props->pattern[i], "in", 2) == 0) { 4214 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4215 } else if (strncmp( 4216 act_props->pattern[i], "out", 3) == 0) { 4217 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4218 } else if (strncmp( 4219 act_props->pattern[i], "both", 4) == 0) { 4220 if (old_style) { 4221 error_message(BAD_ERROR, 4222 IPSEC_CONF_IPSEC_DIR, line_no); 4223 return (-1); 4224 } 4225 new_style = B_TRUE; 4226 cptr->ips_dir = 4227 SPD_RULE_FLAG_OUTBOUND | 4228 SPD_RULE_FLAG_INBOUND; 4229 } else { 4230 error_message(BAD_ERROR, 4231 IPSEC_CONF_IPSEC_DIR, line_no); 4232 return (-1); 4233 } 4234 dir = B_TRUE; 4235 break; 4236 4237 case TOK_local: 4238 if (old_style) { 4239 error_message(BAD_ERROR, 4240 IPSEC_CONF_SRC_ADDRESS, line_no); 4241 return (-1); 4242 } 4243 new_style = B_TRUE; 4244 4245 if (saddr) { 4246 error_message(DUP_ERROR, 4247 IPSEC_CONF_SRC_ADDRESS, line_no); 4248 return (-1); 4249 } 4250 /* 4251 * Use this to detect duplicates rather 4252 * than 0 like other cases, because 0 for 4253 * address means INADDR_ANY. 4254 */ 4255 saddr = B_TRUE; 4256 cptr->has_saddr = 1; 4257 /* 4258 * Advance to the string containing 4259 * the address. 4260 */ 4261 i++, line_no++; 4262 if (act_props->pattern[i] == NULL) { 4263 error_message(BAD_ERROR, 4264 IPSEC_CONF_SRC_ADDRESS, line_no); 4265 return (-1); 4266 } 4267 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4268 act_props->pattern[i]) != 0) { 4269 error_message(BAD_ERROR, 4270 IPSEC_CONF_SRC_ADDRESS, line_no); 4271 return (-1); 4272 } 4273 if (!cptr->has_smask) 4274 cptr->has_smask = has_saprefix; 4275 4276 break; 4277 case TOK_remote: 4278 if (old_style) { 4279 error_message(BAD_ERROR, 4280 IPSEC_CONF_DST_ADDRESS, line_no); 4281 return (-1); 4282 } 4283 new_style = B_TRUE; 4284 4285 if (daddr) { 4286 error_message(DUP_ERROR, 4287 IPSEC_CONF_DST_ADDRESS, line_no); 4288 return (-1); 4289 } 4290 /* 4291 * Use this to detect duplicates rather 4292 * than 0 like other cases, because 0 for 4293 * address means INADDR_ANY. 4294 */ 4295 daddr = B_TRUE; 4296 cptr->has_daddr = 1; 4297 /* 4298 * Advance to the string containing 4299 * the address. 4300 */ 4301 i++, line_no++; 4302 if (act_props->pattern[i] == NULL) { 4303 error_message(BAD_ERROR, 4304 IPSEC_CONF_DST_ADDRESS, line_no); 4305 return (-1); 4306 } 4307 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4308 act_props->pattern[i]) != 0) { 4309 error_message(BAD_ERROR, 4310 IPSEC_CONF_DST_ADDRESS, line_no); 4311 return (-1); 4312 } 4313 if (!cptr->has_dmask) 4314 cptr->has_dmask = has_daprefix; 4315 break; 4316 4317 case TOK_saddr: 4318 if (new_style) { 4319 error_message(BAD_ERROR, 4320 IPSEC_CONF_SRC_ADDRESS, line_no); 4321 return (-1); 4322 } 4323 old_style = B_TRUE; 4324 4325 if (saddr) { 4326 error_message(DUP_ERROR, 4327 IPSEC_CONF_SRC_ADDRESS, line_no); 4328 return (-1); 4329 } 4330 /* 4331 * Use this to detect duplicates rather 4332 * than 0 like other cases, because 0 for 4333 * address means INADDR_ANY. 4334 */ 4335 saddr = B_TRUE; 4336 cptr->has_saddr = 1; 4337 /* 4338 * Advance to the string containing 4339 * the address. 4340 */ 4341 i++, line_no++; 4342 if (act_props->pattern[i] == NULL) { 4343 error_message(BAD_ERROR, 4344 IPSEC_CONF_SRC_ADDRESS, line_no); 4345 return (-1); 4346 } 4347 4348 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4349 act_props->pattern[i]) != 0) { 4350 error_message(BAD_ERROR, 4351 IPSEC_CONF_SRC_ADDRESS, line_no); 4352 return (-1); 4353 } 4354 /* shp or bhp? */ 4355 if (!cptr->has_smask) 4356 cptr->has_smask = has_saprefix; 4357 break; 4358 4359 case TOK_daddr: 4360 if (new_style) { 4361 error_message(BAD_ERROR, 4362 IPSEC_CONF_DST_ADDRESS, line_no); 4363 return (-1); 4364 } 4365 old_style = B_TRUE; 4366 4367 if (daddr) { 4368 error_message(DUP_ERROR, 4369 IPSEC_CONF_DST_ADDRESS, line_no); 4370 return (-1); 4371 } 4372 /* 4373 * Use this to detect duplicates rather 4374 * than 0 like other cases, because 0 for 4375 * address means INADDR_ANY. 4376 */ 4377 daddr = B_TRUE; 4378 cptr->has_daddr = 1; 4379 /* 4380 * Advance to the string containing 4381 * the address. 4382 */ 4383 i++, line_no++; 4384 if (act_props->pattern[i] == NULL) { 4385 error_message(BAD_ERROR, 4386 IPSEC_CONF_DST_ADDRESS, line_no); 4387 return (-1); 4388 } 4389 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4390 act_props->pattern[i]) != 0) { 4391 error_message(BAD_ERROR, 4392 IPSEC_CONF_DST_ADDRESS, line_no); 4393 return (-1); 4394 } 4395 if (!cptr->has_dmask) 4396 cptr->has_dmask = has_daprefix; 4397 break; 4398 4399 case TOK_sport: 4400 if (new_style) { 4401 error_message(BAD_ERROR, 4402 IPSEC_CONF_SRC_PORT, line_no); 4403 return (-1); 4404 } 4405 old_style = B_TRUE; 4406 4407 if (cptr->ips_src_port_min != 0) { 4408 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4409 line_no); 4410 return (-1); 4411 } 4412 i++, line_no++; 4413 if (act_props->pattern[i] == NULL) { 4414 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4415 line_no); 4416 return (-1); 4417 } 4418 ret = parse_port(IPSEC_CONF_SRC_PORT, 4419 act_props->pattern[i], cptr); 4420 if (ret != 0) { 4421 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4422 line_no); 4423 return (-1); 4424 } 4425 break; 4426 case TOK_dport: 4427 if (new_style) { 4428 error_message(BAD_ERROR, 4429 IPSEC_CONF_DST_PORT, line_no); 4430 return (-1); 4431 } 4432 old_style = B_TRUE; 4433 4434 if (cptr->ips_dst_port_min != 0) { 4435 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4436 line_no); 4437 return (-1); 4438 } 4439 i++, line_no++; 4440 if (act_props->pattern[i] == NULL) { 4441 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4442 line_no); 4443 return (-1); 4444 } 4445 ret = parse_port(IPSEC_CONF_DST_PORT, 4446 act_props->pattern[i], 4447 cptr); 4448 if (ret != 0) { 4449 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4450 line_no); 4451 return (-1); 4452 } 4453 break; 4454 4455 case TOK_lport: 4456 if (old_style) { 4457 error_message(BAD_ERROR, 4458 IPSEC_CONF_SRC_PORT, line_no); 4459 return (-1); 4460 } 4461 new_style = B_TRUE; 4462 4463 if (cptr->ips_src_port_min != 0) { 4464 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4465 line_no); 4466 return (-1); 4467 } 4468 i++, line_no++; 4469 if (act_props->pattern[i] == NULL) { 4470 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4471 line_no); 4472 return (-1); 4473 } 4474 ret = parse_port(IPSEC_CONF_SRC_PORT, 4475 act_props->pattern[i], 4476 cptr); 4477 if (ret != 0) { 4478 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4479 line_no); 4480 return (-1); 4481 } 4482 break; 4483 4484 case TOK_rport: 4485 if (old_style) { 4486 error_message(BAD_ERROR, 4487 IPSEC_CONF_DST_PORT, line_no); 4488 return (-1); 4489 } 4490 new_style = B_TRUE; 4491 4492 if (cptr->ips_dst_port_min != 0) { 4493 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4494 line_no); 4495 return (-1); 4496 } 4497 i++, line_no++; 4498 if (act_props->pattern[i] == NULL) { 4499 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4500 line_no); 4501 return (-1); 4502 } 4503 ret = parse_port(IPSEC_CONF_DST_PORT, 4504 act_props->pattern[i], 4505 cptr); 4506 if (ret != 0) { 4507 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4508 line_no); 4509 return (-1); 4510 } 4511 break; 4512 4513 case TOK_smask: 4514 if (new_style) { 4515 error_message(BAD_ERROR, 4516 IPSEC_CONF_SRC_MASK, line_no); 4517 return (-1); 4518 } 4519 old_style = B_TRUE; 4520 cptr->has_smask = B_TRUE; 4521 4522 IN6_V4MAPPED_TO_INADDR(&cptr->ips_src_mask_v6, &mask); 4523 if (mask.s_addr != 0) { 4524 error_message(DUP_ERROR, IPSEC_CONF_SRC_MASK, 4525 line_no); 4526 return (-1); 4527 } 4528 i++, line_no++; 4529 if (act_props->pattern[i] == NULL) { 4530 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4531 line_no); 4532 return (-1); 4533 } 4534 ret = parse_mask(IPSEC_CONF_SRC_MASK, 4535 act_props->pattern[i], 4536 cptr); 4537 if (ret != 0) { 4538 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4539 line_no); 4540 return (-1); 4541 } 4542 break; 4543 case TOK_dmask: 4544 if (new_style) { 4545 error_message(BAD_ERROR, 4546 IPSEC_CONF_DST_MASK, line_no); 4547 return (-1); 4548 } 4549 old_style = B_TRUE; 4550 cptr->has_dmask = B_TRUE; 4551 4552 IN6_V4MAPPED_TO_INADDR(&cptr->ips_dst_mask_v6, &mask); 4553 if (mask.s_addr != 0) { 4554 error_message(DUP_ERROR, IPSEC_CONF_DST_MASK, 4555 line_no); 4556 return (-1); 4557 } 4558 i++, line_no++; 4559 if (act_props->pattern[i] == NULL) { 4560 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4561 line_no); 4562 return (-1); 4563 } 4564 ret = parse_mask(IPSEC_CONF_DST_MASK, 4565 act_props->pattern[i], 4566 cptr); 4567 if (ret != 0) { 4568 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4569 line_no); 4570 return (-1); 4571 } 4572 break; 4573 case TOK_ulp: 4574 if (cptr->ips_ulp_prot != 0) { 4575 error_message(DUP_ERROR, 4576 IPSEC_CONF_ULP, line_no); 4577 return (-1); 4578 } 4579 i++, line_no++; 4580 if (act_props->pattern[i] == NULL) { 4581 error_message(BAD_ERROR, 4582 IPSEC_CONF_ULP, line_no); 4583 return (-1); 4584 } 4585 pent = getprotobyname(act_props->pattern[i]); 4586 if (pent == NULL) { 4587 int ulp; 4588 ulp = parse_int(act_props->pattern[i]); 4589 if (ulp == -1) { 4590 error_message(BAD_ERROR, 4591 IPSEC_CONF_ULP, line_no); 4592 return (-1); 4593 } 4594 cptr->ips_ulp_prot = ulp; 4595 } else { 4596 cptr->ips_ulp_prot = pent->p_proto; 4597 } 4598 break; 4599 case TOK_type: 4600 if (cptr->has_type) { 4601 error_message(DUP_ERROR, 4602 IPSEC_CONF_ICMP_TYPE, line_no); 4603 return (-1); 4604 } 4605 4606 i++, line_no++; 4607 type = parse_type_code(act_props->pattern[i], 4608 icmp_type_table); 4609 4610 if (type > 65536 || type < 0) { 4611 error_message(BAD_ERROR, 4612 IPSEC_CONF_ICMP_TYPE, line_no); 4613 return (-1); 4614 } 4615 4616 type_end = type / 256; 4617 type = type % 256; 4618 4619 if (type_end < type) 4620 type_end = type; 4621 4622 cptr->has_type = 1; 4623 cptr->ips_icmp_type = (uint8_t)type; 4624 cptr->ips_icmp_type_end = (uint8_t)type_end; 4625 break; 4626 case TOK_code: 4627 if (!cptr->has_type) { 4628 error_message(BAD_ERROR, 4629 IPSEC_CONF_ICMP_CODE, line_no); 4630 return (-1); 4631 } 4632 4633 if (cptr->has_code) { 4634 error_message(DUP_ERROR, 4635 IPSEC_CONF_ICMP_CODE, line_no); 4636 return (-1); 4637 } 4638 4639 i++, line_no++; 4640 4641 code = parse_type_code(act_props->pattern[i], 4642 icmp_code_table); 4643 if (type > 65536 || type < 0) { 4644 error_message(BAD_ERROR, 4645 IPSEC_CONF_ICMP_CODE, line_no); 4646 return (-1); 4647 } 4648 code_end = code / 256; 4649 code = code % 256; 4650 4651 if (code_end < code) 4652 code_end = code; 4653 4654 cptr->has_code = 1; 4655 cptr->ips_icmp_code = (uint8_t)code; 4656 cptr->ips_icmp_code_end = (uint8_t)code_end; 4657 break; 4658 case TOK_tunnel: 4659 if (cptr->has_tunnel == 1) { 4660 error_message(BAD_ERROR, 4661 IPSEC_CONF_TUNNEL, line_no); 4662 return (-1); 4663 } 4664 i++, line_no++; 4665 if (act_props->pattern[i] == NULL) { 4666 error_message(BAD_ERROR, 4667 IPSEC_CONF_TUNNEL, line_no); 4668 return (-1); 4669 } 4670 4671 if (strlcpy(tunif, act_props->pattern[i], 4672 TUNNAMEMAXLEN) >= TUNNAMEMAXLEN) { 4673 error_message(BAD_ERROR, 4674 IPSEC_CONF_TUNNEL, line_no); 4675 return (-1); 4676 } 4677 cptr->has_tunnel = 1; 4678 break; 4679 case TOK_negotiate: 4680 if (cptr->has_negotiate == 1) { 4681 error_message(BAD_ERROR, 4682 IPSEC_CONF_NEGOTIATE, line_no); 4683 return (-1); 4684 } 4685 i++, line_no++; 4686 if (act_props->pattern[i] == NULL) { 4687 error_message(BAD_ERROR, 4688 IPSEC_CONF_NEGOTIATE, line_no); 4689 return (-1); 4690 } 4691 4692 if (strncmp(act_props->pattern[i], "tunnel", 6) == 0) { 4693 cptr->ips_tunnel = B_TRUE; 4694 } else if (strncmp( 4695 act_props->pattern[i], "transport", 9) != 0) { 4696 error_message(BAD_ERROR, 4697 IPSEC_CONF_NEGOTIATE, line_no); 4698 return (-1); 4699 } 4700 cptr->has_negotiate = 1; 4701 break; 4702 } 4703 4704 } 4705 4706 /* Sanity check that certain tokens occur together */ 4707 if (cptr->has_tunnel + cptr->has_negotiate == 1) { 4708 if (cptr->has_negotiate == 0) { 4709 error_message(REQ_ERROR, IPSEC_CONF_NEGOTIATE, line_no); 4710 } else { 4711 error_message(REQ_ERROR, IPSEC_CONF_TUNNEL, line_no); 4712 } 4713 errx(1, gettext( 4714 "tunnel and negotiate tokens must occur together")); 4715 return (-1); 4716 } 4717 4718 /* 4719 * Get the actions. 4720 */ 4721 4722 for (ap_num = 0; act_props->ap[ap_num].act != NULL; ap_num++) { 4723 ips_act_props_t *iap; 4724 4725 if (ap_num > 0) { 4726 /* or's only with new style */ 4727 if (old_style) { 4728 (void) printf("%s\n", gettext( 4729 "or's only with new style")); 4730 return (-1); 4731 } 4732 new_style = B_TRUE; 4733 } 4734 4735 ipsec_aalg = ipsec_ealg = ipsec_eaalg = B_FALSE; 4736 tok_count = 0; 4737 4738 for (k = 0; action_table[k].string; k++) { 4739 if (strcmp(act_props->ap[ap_num].act, 4740 action_table[k].string) == 0) 4741 break; 4742 } 4743 /* 4744 * The following thing should never happen as 4745 * we have already tested for its validity in parse. 4746 */ 4747 if (action_table[k].string == NULL) { 4748 warnx(gettext("(form act)Invalid action on line " 4749 "%d: %s"), (arg_indices[line_no] == 0) ? 1 : 4750 arg_indices[line_no], 4751 act_props->ap[ap_num].act); 4752 warnx("%s", act_props->ap[ap_num].act); 4753 return (-1); 4754 } 4755 4756 /* we have a good action alloc an iap */ 4757 iap = alloc_iap(cptr); 4758 4759 iap->iap_action = action_table[k].value; 4760 iap->iap_act_tok = action_table[k].tok_val; 4761 4762 switch (action_table[k].tok_val) { 4763 case TOK_apply: 4764 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4765 break; 4766 case TOK_permit: 4767 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4768 break; 4769 case TOK_ipsec: 4770 if (old_style) { 4771 /* Using saddr/daddr with ipsec action. */ 4772 if (!dir) { 4773 /* No direction specified */ 4774 error_message(REQ_ERROR, 4775 IPSEC_CONF_IPSEC_DIR, line_no); 4776 return (-1); 4777 } 4778 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 4779 /* 4780 * Need to swap addresses if 4781 * 'dir in' or translation to 4782 * laddr/raddr will be incorrect. 4783 */ 4784 cptr->swap = 1; 4785 } 4786 if (!dir) 4787 cptr->ips_dir = 4788 SPD_RULE_FLAG_INBOUND 4789 |SPD_RULE_FLAG_OUTBOUND; 4790 break; 4791 case TOK_bypass: 4792 /* do something? */ 4793 break; 4794 } 4795 4796 line_no++; 4797 /* 4798 * Get the properties. NULL properties is not valid. 4799 * Later checks will catch it. 4800 */ 4801 for (i = 0; act_props->ap[ap_num].prop[i]; i++, line_no++) { 4802 for (j = 0; property_table[j].string; j++) { 4803 if (strcmp(act_props->ap[ap_num].prop[i], 4804 property_table[j].string) == 0) { 4805 break; 4806 } 4807 } 4808 if (property_table[j].string == NULL) { 4809 warnx(gettext("Invalid properties on line " 4810 "%d: %s"), 4811 (arg_indices[line_no] == 0) ? 4812 1 : arg_indices[line_no], 4813 act_props->ap[ap_num].prop[i]); 4814 return (-1); 4815 } 4816 4817 iap->iap_attr_tok[tok_count++] 4818 = property_table[j].value; 4819 4820 switch (property_table[j].value) { 4821 case SPD_ATTR_AH_AUTH: 4822 if (ipsec_aalg) { 4823 error_message(DUP_ERROR, 4824 IPSEC_CONF_IPSEC_AALGS, line_no); 4825 return (-1); 4826 } 4827 i++, line_no++; 4828 if (act_props->ap[ap_num].prop[i] == NULL) { 4829 error_message(BAD_ERROR, 4830 IPSEC_CONF_IPSEC_AALGS, line_no); 4831 return (-1); 4832 } 4833 ret = parse_ipsec_alg( 4834 act_props->ap[ap_num].prop[i], 4835 iap, SPD_ATTR_AH_AUTH); 4836 if (ret == -2) { 4837 /* "none" - ignore */ 4838 break; 4839 } 4840 if (ret != 0) { 4841 error_message(BAD_ERROR, 4842 IPSEC_CONF_IPSEC_AALGS, line_no); 4843 return (-1); 4844 } 4845 ipsec_aalg = B_TRUE; 4846 break; 4847 case SPD_ATTR_ESP_ENCR: 4848 /* 4849 * If this option was not given 4850 * and encr_auth_algs was given, 4851 * we provide null-encryption. We do the 4852 * setting after we parse all the options. 4853 */ 4854 if (ipsec_ealg) { 4855 error_message(DUP_ERROR, 4856 IPSEC_CONF_IPSEC_EALGS, line_no); 4857 return (-1); 4858 } 4859 i++, line_no++; 4860 if (act_props->ap[ap_num].prop[i] == NULL) { 4861 error_message(BAD_ERROR, 4862 IPSEC_CONF_IPSEC_EALGS, line_no); 4863 return (-1); 4864 } 4865 ret = parse_ipsec_alg( 4866 act_props->ap[ap_num].prop[i], 4867 iap, SPD_ATTR_ESP_ENCR); 4868 if (ret == -2) { 4869 /* "none" - ignore */ 4870 break; 4871 } 4872 if (ret != 0) { 4873 error_message(BAD_ERROR, 4874 IPSEC_CONF_IPSEC_EALGS, line_no); 4875 return (-1); 4876 } 4877 ipsec_ealg = B_TRUE; 4878 break; 4879 case SPD_ATTR_ESP_AUTH: 4880 /* 4881 * If this option was not given and encr_algs 4882 * option was given, we still pass a default 4883 * value in ipsc_esp_auth_algs. This is to 4884 * encourage the use of authentication with 4885 * ESP. 4886 */ 4887 if (ipsec_eaalg) { 4888 error_message(DUP_ERROR, 4889 IPSEC_CONF_IPSEC_EAALGS, line_no); 4890 return (-1); 4891 } 4892 i++, line_no++; 4893 if (act_props->ap[ap_num].prop[i] == NULL) { 4894 error_message(BAD_ERROR, 4895 IPSEC_CONF_IPSEC_EAALGS, line_no); 4896 return (-1); 4897 } 4898 ret = parse_ipsec_alg( 4899 act_props->ap[ap_num].prop[i], 4900 iap, SPD_ATTR_ESP_AUTH); 4901 if (ret == -2) { 4902 /* "none" - ignore */ 4903 break; 4904 } 4905 if (ret != 0) { 4906 error_message(BAD_ERROR, 4907 IPSEC_CONF_IPSEC_EAALGS, line_no); 4908 return (-1); 4909 } 4910 ipsec_eaalg = B_TRUE; 4911 break; 4912 case IPS_SA: 4913 i++, line_no++; 4914 if (act_props->ap[ap_num].prop[i] == NULL) { 4915 error_message(BAD_ERROR, 4916 IPSEC_CONF_IPSEC_SA, line_no); 4917 return (-1); 4918 } 4919 4920 if (strcmp(act_props->ap[ap_num].prop[i], 4921 "unique") == 0) { 4922 iap->iap_attr |= SPD_APPLY_UNIQUE; 4923 } else if (strcmp(act_props->ap[ap_num].prop[i], 4924 "shared") != 0) { 4925 /* "shared" is default. */ 4926 error_message(BAD_ERROR, 4927 IPSEC_CONF_IPSEC_SA, line_no); 4928 return (-1); 4929 } 4930 4931 break; 4932 case IPS_DIR: 4933 if (dir) { 4934 error_message(DUP_ERROR, 4935 IPSEC_CONF_IPSEC_DIR, line_no); 4936 return (-1); 4937 } 4938 if (new_style) { 4939 error_message(BAD_ERROR, 4940 IPSEC_CONF_IPSEC_DIR, line_no); 4941 return (-1); 4942 } 4943 old_style = B_TRUE; 4944 dir = B_TRUE; 4945 i++, line_no++; 4946 if (act_props->ap[ap_num].prop[i] == NULL) { 4947 error_message(BAD_ERROR, 4948 IPSEC_CONF_IPSEC_DIR, line_no); 4949 return (-1); 4950 } 4951 if (strcmp(act_props->ap[ap_num].prop[i], 4952 "out") == 0) { 4953 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4954 } else if (strcmp(act_props->ap[ap_num].prop[i], 4955 "in") == 0) { 4956 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4957 } else { 4958 error_message(BAD_ERROR, 4959 IPSEC_CONF_IPSEC_DIR, line_no); 4960 return (-1); 4961 } 4962 if ((cptr->ips_dir & SPD_RULE_FLAG_INBOUND) && 4963 iap->iap_act_tok == TOK_apply) { 4964 warnx(gettext("Direction" 4965 " in conflict with action")); 4966 return (-1); 4967 } 4968 if ((cptr->ips_dir & SPD_RULE_FLAG_OUTBOUND) && 4969 iap->iap_act_tok == TOK_permit) { 4970 warnx(gettext("Direction" 4971 "in conflict with action")); 4972 return (-1); 4973 } 4974 4975 break; 4976 } 4977 } 4978 4979 if (!ipsec_ealg && ipsec_eaalg) { 4980 /* 4981 * If the user has specified the auth alg to be used 4982 * with encryption and did not provide a encryption 4983 * algorithm, provide null encryption. 4984 */ 4985 iap->iap_eencr.alg_id = SADB_EALG_NULL; 4986 ipsec_ealg = B_TRUE; 4987 } 4988 4989 /* Set the level of IPSEC protection we want */ 4990 if (ipsec_aalg && (ipsec_ealg || ipsec_eaalg)) { 4991 iap->iap_attr |= SPD_APPLY_AH|SPD_APPLY_ESP; 4992 } else if (ipsec_aalg) { 4993 iap->iap_attr |= SPD_APPLY_AH; 4994 } else if (ipsec_ealg || ipsec_eaalg) { 4995 iap->iap_attr |= SPD_APPLY_ESP; 4996 } 4997 4998 /* convert src/dst to local/remote */ 4999 if (!new_style) { 5000 switch (cptr->ips_acts->iap_act_tok) { 5001 case TOK_apply: 5002 /* outbound */ 5003 /* src=local, dst=remote */ 5004 /* this is ok. */ 5005 break; 5006 5007 case TOK_permit: 5008 /* inbound */ 5009 /* src=remote, dst=local */ 5010 /* switch */ 5011 cptr->swap = 1; 5012 break; 5013 case TOK_bypass: 5014 case TOK_drop: 5015 /* check the direction for what to do */ 5016 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 5017 cptr->swap = 1; 5018 break; 5019 default: 5020 break; 5021 } 5022 } 5023 /* Validate the properties */ 5024 if (ret = validate_properties(iap, dir, 5025 (ipsec_aalg || ipsec_ealg || ipsec_eaalg))) { 5026 return (ret); 5027 } 5028 } 5029 5030 return (0); 5031 5032 } 5033 5034 static int 5035 print_cmd_buf(FILE *fp, int error) 5036 { 5037 *(cbuf + cbuf_offset) = '\0'; 5038 5039 if (fp == stderr) { 5040 if (error != EEXIST) { 5041 warnx(gettext("Malformed command (fatal):\n%s"), cbuf); 5042 return (0); 5043 } 5044 if (ipsecconf_qflag) { 5045 return (0); 5046 } 5047 warnx(gettext("Duplicate policy entry (ignored):\n%s"), cbuf); 5048 } else { 5049 if (fprintf(fp, "%s", cbuf) == -1) { 5050 warn("fprintf"); 5051 return (-1); 5052 } 5053 } 5054 5055 return (0); 5056 } 5057 5058 #ifdef DEBUG 5059 5060 static uchar_t * 5061 addr_ptr(int isv4, struct in6_addr *addr6, struct in_addr *addr4) 5062 { 5063 if (isv4) { 5064 IN6_V4MAPPED_TO_INADDR(addr6, addr4); 5065 return ((uchar_t *)&addr4->s_addr); 5066 } else { 5067 return ((uchar_t *)&addr6->s6_addr); 5068 } 5069 } 5070 5071 static void 5072 dump_algreq(const char *tag, algreq_t *alg) 5073 { 5074 (void) printf("%s algid %d, bits %d..%d\n", 5075 tag, alg->alg_id, alg->alg_minbits, alg->alg_maxbits); 5076 } 5077 5078 static void 5079 dump_conf(ips_conf_t *conf) 5080 { 5081 boolean_t isv4 = conf->ips_isv4; 5082 struct in_addr addr; 5083 char buf[INET6_ADDRSTRLEN]; 5084 int af; 5085 ips_act_props_t *iap = conf->ips_acts; 5086 5087 af = isv4 ? AF_INET : AF_INET6; 5088 5089 (void) printf("Source Addr is %s\n", 5090 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_addr_v6, &addr), 5091 buf, INET6_ADDRSTRLEN)); 5092 5093 (void) printf("Dest Addr is %s\n", 5094 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_addr_v6, &addr), 5095 buf, INET6_ADDRSTRLEN)); 5096 5097 (void) printf("Source Mask is %s\n", 5098 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_mask_v6, &addr), 5099 buf, INET6_ADDRSTRLEN)); 5100 5101 (void) printf("Dest Mask is %s\n", 5102 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_mask_v6, &addr), 5103 buf, INET6_ADDRSTRLEN)); 5104 5105 (void) printf("Source port %d\n", ntohs(conf->ips_src_port_min)); 5106 (void) printf("Dest port %d\n", ntohs(conf->ips_dst_port_min)); 5107 (void) printf("ULP %d\n", conf->ips_ulp_prot); 5108 5109 (void) printf("ICMP type %d-%d code %d-%d", conf->ips_icmp_type, 5110 conf->ips_icmp_type_end, 5111 conf->ips_icmp_code, 5112 conf->ips_icmp_code_end); 5113 5114 while (iap != NULL) { 5115 (void) printf("------------------------------------\n"); 5116 (void) printf("IPsec act is %d\n", iap->iap_action); 5117 (void) printf("IPsec attr is %d\n", iap->iap_attr); 5118 dump_algreq("AH authentication", &iap->iap_aauth); 5119 dump_algreq("ESP authentication", &iap->iap_eauth); 5120 dump_algreq("ESP encryption", &iap->iap_eencr); 5121 (void) printf("------------------------------------\n"); 5122 iap = iap->iap_next; 5123 } 5124 5125 (void) fflush(stdout); 5126 } 5127 #endif /* DEBUG */ 5128 5129 5130 static int 5131 ipsec_conf_add(boolean_t just_check, boolean_t smf_managed) 5132 { 5133 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5134 ips_conf_t conf; 5135 FILE *fp, *policy_fp; 5136 int ret, flushret, i, j, diag, num_rules, good_rules; 5137 char *warning = gettext( 5138 "\tWARNING : New policy entries that are being added may\n " 5139 "\taffect the existing connections. Existing connections\n" 5140 "\tthat are not subjected to policy constraints, may be\n" 5141 "\tsubjected to policy constraints because of the new\n" 5142 "\tpolicy. This can disrupt the communication of the\n" 5143 "\texisting connections.\n\n"); 5144 5145 boolean_t first_time = B_TRUE; 5146 num_rules = 0; 5147 good_rules = 0; 5148 5149 if (act_props == NULL) { 5150 warn(gettext("memory")); 5151 return (-1); 5152 } 5153 5154 if (strcmp(filename, "-") == 0) 5155 fp = stdin; 5156 else 5157 fp = fopen(filename, "r"); 5158 5159 /* 5160 * Treat the non-existence of a policy file as a special 5161 * case when ipsecconf is being managed by smf(5). 5162 * The assumption is the administrator has not yet 5163 * created a policy file, this should not force the service 5164 * into maintenance mode. 5165 */ 5166 5167 if (fp == NULL) { 5168 if (smf_managed) { 5169 (void) fprintf(stdout, gettext( 5170 "Policy configuration file (%s) does not exist.\n" 5171 "IPsec policy not configured.\n"), filename); 5172 return (0); 5173 } 5174 warn(gettext("%s : Policy config file cannot be opened"), 5175 filename); 5176 usage(); 5177 return (-1); 5178 } 5179 /* 5180 * This will create the file if it does not exist. 5181 * Make sure the umask is right. 5182 */ 5183 (void) umask(0022); 5184 policy_fp = fopen(POLICY_CONF_FILE, "a"); 5185 if (policy_fp == NULL) { 5186 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5187 return (-1); 5188 } 5189 5190 /* 5191 * Pattern, action, and properties are allocated in 5192 * parse_pattern_or_prop and in parse_action (called by 5193 * parse_one) as we parse arguments. 5194 */ 5195 while ((ret = parse_one(fp, act_props)) != PARSE_EOF) { 5196 num_rules++; 5197 if (ret != 0) { 5198 (void) print_cmd_buf(stderr, NOERROR); 5199 continue; 5200 } 5201 5202 /* 5203 * If there is no action and parse returned success, 5204 * it means that there is nothing to add. 5205 */ 5206 if (act_props->pattern[0] == NULL && 5207 act_props->ap[0].act == NULL) 5208 break; 5209 5210 ret = form_ipsec_conf(act_props, &conf); 5211 if (ret != 0) { 5212 warnx(gettext("form_ipsec_conf error")); 5213 (void) print_cmd_buf(stderr, NOERROR); 5214 /* Reset globals before trying the next rule. */ 5215 if (shp != NULL) { 5216 freehostent(shp); 5217 shp = NULL; 5218 } 5219 if (dhp != NULL) { 5220 freehostent(dhp); 5221 dhp = NULL; 5222 } 5223 splen = 0; 5224 dplen = 0; 5225 continue; 5226 } 5227 5228 good_rules++; 5229 5230 if (first_time) { 5231 /* 5232 * Time to assume that there are valid policy entries. 5233 * If the IPsec kernel modules are not loaded this 5234 * will load them now. 5235 */ 5236 first_time = B_FALSE; 5237 fetch_algorithms(); 5238 ipsec_conf_admin(SPD_CLONE); 5239 } 5240 5241 /* 5242 * shp, dhp, splen, and dplen are globals set by 5243 * form_ipsec_conf() while parsing the addresses. 5244 */ 5245 if (shp == NULL && dhp == NULL) { 5246 switch (do_port_adds(&conf)) { 5247 case 0: 5248 /* no error */ 5249 break; 5250 case EEXIST: 5251 /* duplicate entries, continue adds */ 5252 (void) print_cmd_buf(stderr, EEXIST); 5253 goto next; 5254 default: 5255 /* other error, bail */ 5256 ret = -1; 5257 goto bail; 5258 } 5259 } else { 5260 ret = do_address_adds(&conf, &diag); 5261 switch (ret) { 5262 case 0: 5263 /* no error. */ 5264 break; 5265 case EEXIST: 5266 (void) print_cmd_buf(stderr, EEXIST); 5267 goto next; 5268 case EBUSY: 5269 warnx(gettext( 5270 "Can't set mask and /NN prefix.")); 5271 ret = -1; 5272 break; 5273 case ENOENT: 5274 warnx(gettext("Cannot find tunnel " 5275 "interface %s."), interface_name); 5276 ret = -1; 5277 break; 5278 case EINVAL: 5279 /* 5280 * PF_POLICY didn't like what we sent. We 5281 * can't check all input up here, but we 5282 * do in-kernel. 5283 */ 5284 warnx(gettext("PF_POLICY invalid input:\n\t%s"), 5285 spdsock_diag(diag)); 5286 break; 5287 case EOPNOTSUPP: 5288 warnx(gettext("Can't set /NN" 5289 " prefix on multi-host name.")); 5290 ret = -1; 5291 break; 5292 case ERANGE: 5293 warnx(gettext("/NN prefix is too big!")); 5294 ret = -1; 5295 break; 5296 case ESRCH: 5297 warnx(gettext("No matching IPv4 or " 5298 "IPv6 saddr/daddr pairs")); 5299 ret = -1; 5300 break; 5301 default: 5302 /* Should never get here. */ 5303 errno = ret; 5304 warn(gettext("Misc. error")); 5305 ret = -1; 5306 } 5307 if (ret == -1) 5308 goto bail; 5309 } 5310 5311 /* 5312 * Go ahead and add policy entries to config file. 5313 * The # should help re-using the ipsecpolicy.conf 5314 * for input again as # will be treated as comment. 5315 */ 5316 if (fprintf(policy_fp, "%s %lld \n", INDEX_TAG, 5317 conf.ips_policy_index) == -1) { 5318 warn("fprintf"); 5319 warnx(gettext("Addition incomplete, Please " 5320 "flush all the entries and re-configure :")); 5321 reconfigure(); 5322 ret = -1; 5323 break; 5324 } 5325 if (print_cmd_buf(policy_fp, NOERROR) == -1) { 5326 warnx(gettext("Addition incomplete. Please " 5327 "flush all the entries and re-configure :")); 5328 reconfigure(); 5329 ret = -1; 5330 break; 5331 } 5332 /* 5333 * We add one newline by default to separate out the 5334 * entries. If the last character is not a newline, we 5335 * insert a newline for free. This makes sure that all 5336 * entries look consistent in the file. 5337 */ 5338 if (*(cbuf + cbuf_offset - 1) == '\n') { 5339 if (fprintf(policy_fp, "\n") == -1) { 5340 warn("fprintf"); 5341 warnx(gettext("Addition incomplete. " 5342 "Please flush all the entries and " 5343 "re-configure :")); 5344 reconfigure(); 5345 ret = -1; 5346 break; 5347 } 5348 } else { 5349 if (fprintf(policy_fp, "\n\n") == -1) { 5350 warn("fprintf"); 5351 warnx(gettext("Addition incomplete. " 5352 "Please flush all the entries and " 5353 "re-configure :")); 5354 reconfigure(); 5355 ret = -1; 5356 break; 5357 } 5358 } 5359 next: 5360 /* 5361 * Make sure this gets to the disk before 5362 * we parse the next entry. 5363 */ 5364 (void) fflush(policy_fp); 5365 for (i = 0; act_props->pattern[i] != NULL; i++) 5366 free(act_props->pattern[i]); 5367 for (j = 0; act_props->ap[j].act != NULL; j++) { 5368 free(act_props->ap[j].act); 5369 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5370 free(act_props->ap[j].prop[i]); 5371 } 5372 } 5373 if (ret == PARSE_EOF) 5374 ret = 0; /* Not an error */ 5375 bail: 5376 if (ret == -1) { 5377 (void) print_cmd_buf(stderr, EINVAL); 5378 for (i = 0; act_props->pattern[i] != NULL; i++) 5379 free(act_props->pattern[i]); 5380 for (j = 0; act_props->ap[j].act != NULL; j++) { 5381 free(act_props->ap[j].act); 5382 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5383 free(act_props->ap[j].prop[i]); 5384 } 5385 } 5386 #ifdef DEBUG_HEAVY 5387 (void) printf("ipsec_conf_add: ret val = %d\n", ret); 5388 (void) fflush(stdout); 5389 #endif 5390 if (num_rules == 0 && ret == 0) { 5391 nuke_adds(); 5392 (void) restore_all_signals(); 5393 (void) unlock(lfd); 5394 EXIT_OK("Policy file does not contain any valid rules."); 5395 } 5396 if (num_rules != good_rules) { 5397 /* This is an error */ 5398 nuke_adds(); 5399 (void) restore_all_signals(); 5400 (void) unlock(lfd); 5401 EXIT_BADCONFIG2("%d policy rule(s) contained errors.", 5402 num_rules - good_rules); 5403 } 5404 /* looks good, flip it in */ 5405 if (ret == 0 && !just_check) { 5406 if (!ipsecconf_qflag) { 5407 (void) printf("%s", warning); 5408 } 5409 if (smf_managed) 5410 warnx(gettext("%d policy rules added."), good_rules); 5411 ipsec_conf_admin(SPD_FLIP); 5412 } else { 5413 nuke_adds(); 5414 if (just_check) { 5415 (void) fprintf(stdout, gettext("IPsec configuration " 5416 "does not contain any errors.\n")); 5417 (void) fprintf(stdout, gettext( 5418 "IPsec policy was not modified.\n")); 5419 (void) fflush(stdout); 5420 } 5421 } 5422 flushret = ipsec_conf_flush(SPD_STANDBY); 5423 if (flushret != 0) 5424 return (flushret); 5425 return (ret); 5426 } 5427 5428 5429 static int 5430 ipsec_conf_sub() 5431 { 5432 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5433 FILE *remove_fp, *policy_fp; 5434 char rbuf[MAXLEN], pbuf[MAXLEN], /* remove buffer, and policy buffer */ 5435 *warning = gettext( 5436 "\tWARNING: Policy entries that are being removed may\n" 5437 "\taffect the existing connections. Existing connections\n" 5438 "\tthat are subjected to policy constraints may no longer\n" 5439 "\tbe subjected to policy contraints because of its\n" 5440 "\tremoval. This can compromise security, and disrupt\n" 5441 "\tthe communication of the existing connection.\n" 5442 "\tConnections that are latched will remain unaffected\n" 5443 "\tuntil they close.\n"); 5444 int ret = 0; 5445 int index_len, pindex = 0; /* init value in case of pfile error */ 5446 5447 if (act_props == NULL) { 5448 warn(gettext("memory")); 5449 return (-1); 5450 } 5451 5452 /* clone into standby DB */ 5453 (void) ipsec_conf_admin(SPD_CLONE); 5454 5455 if (strcmp(filename, "-") == 0) 5456 remove_fp = stdin; 5457 else 5458 remove_fp = fopen(filename, "r"); 5459 5460 if (remove_fp == NULL) { 5461 warn(gettext("%s : Input file cannot be opened"), filename); 5462 usage(); 5463 free(act_props); 5464 return (-1); 5465 } 5466 5467 /* open policy file so we can locate the correct policy */ 5468 (void) umask(0022); /* in case it gets created! */ 5469 policy_fp = fopen(POLICY_CONF_FILE, "r+"); 5470 if (policy_fp == NULL) { 5471 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5472 (void) fclose(remove_fp); 5473 free(act_props); 5474 return (-1); 5475 } 5476 5477 /* don't print the warning if we're in q[uiet] mode */ 5478 if (!ipsecconf_qflag) 5479 (void) printf("%s", warning); 5480 5481 /* this bit is done primarily so we can read what we write */ 5482 index_len = strlen(INDEX_TAG); 5483 5484 /* 5485 * We want to look for the policy in rbuf in the policy file. 5486 * Go through the list of policies to remove, locating each one. 5487 */ 5488 while (fgets(rbuf, MAXLEN, remove_fp) != NULL) { 5489 char *buf; 5490 int offset, prev_offset, prev_prev_offset, nlines; 5491 fpos_t ipos; 5492 int pbuf_len = 0; 5493 char *tmp; 5494 /* skip blanks here (so we don't need to do it below)! */ 5495 for (tmp = rbuf; (*tmp != '\0') && isspace(*tmp); ) 5496 tmp++; 5497 5498 if (*tmp == '\0') 5499 continue; /* while(); */ 5500 5501 /* skip the INDEX_TAG lines in the remove buffer */ 5502 if (strncasecmp(rbuf, INDEX_TAG, index_len) == 0) 5503 continue; 5504 5505 /* skip commented lines */ 5506 if (*tmp == '#') 5507 continue; /* while(); */ 5508 5509 /* 5510 * We start by presuming only good policies are in the pfile, 5511 * and so only good policies from the rfile will match them. 5512 * ipsec_conf_del ensures this later by calling parse_one() on 5513 * pfile before it deletes the entry. 5514 */ 5515 for (offset = prev_offset = prev_prev_offset = 0; 5516 fgets(pbuf, MAXLEN, policy_fp) != NULL; 5517 offset += pbuf_len) { 5518 prev_offset = offset; 5519 pbuf_len = strlen(pbuf); 5520 5521 /* skip blank lines which seperate policy entries */ 5522 if (pbuf[0] == '\n') 5523 continue; 5524 5525 /* if we found an index, save it */ 5526 if (strncasecmp(pbuf, INDEX_TAG, index_len) == 0) { 5527 buf = pbuf + index_len; 5528 buf++; 5529 if ((pindex = parse_index(buf, NULL)) == -1) { 5530 /* bad index, we can't continue */ 5531 warnx(gettext( 5532 "Invalid index in the file")); 5533 (void) fclose(remove_fp); 5534 (void) fclose(policy_fp); 5535 free(act_props); 5536 return (-1); 5537 } 5538 5539 /* save this position in case it's the one */ 5540 if (fgetpos(policy_fp, &ipos) != 0) { 5541 (void) fclose(remove_fp); 5542 (void) fclose(policy_fp); 5543 free(act_props); 5544 return (-1); 5545 } 5546 } 5547 5548 /* Does pbuf contain the remove policy? */ 5549 if (strncasecmp(rbuf, pbuf, pbuf_len) == 0) { 5550 /* we found the one to remove! */ 5551 if (pindex == 0) { 5552 warnx(gettext("Didn't find a valid " 5553 "index for policy")); 5554 (void) fclose(remove_fp); 5555 (void) fclose(policy_fp); 5556 free(act_props); 5557 return (-1); 5558 } 5559 5560 /* off it - back up to the last INDEX! */ 5561 if (fsetpos(policy_fp, &ipos) != 0) { 5562 (void) fclose(remove_fp); 5563 (void) fclose(policy_fp); 5564 free(act_props); 5565 return (-1); 5566 } 5567 5568 /* parse_one sets linecount = #lines to off */ 5569 if (parse_one(policy_fp, act_props) == -1) { 5570 warnx(gettext("Invalid policy entry " 5571 "in the file")); 5572 (void) fclose(remove_fp); 5573 (void) fclose(policy_fp); 5574 free(act_props); 5575 return (-1); 5576 } 5577 5578 nlines = linecount + 2; 5579 goto delete; 5580 } 5581 /* 5582 * When we find a match, we want to pass the offset 5583 * of the line that is before it - the INDEX_TAG line. 5584 */ 5585 prev_prev_offset = prev_offset; 5586 } 5587 /* Didn't find a match - look at the next remove policy */ 5588 continue; /* while(); */ 5589 5590 delete: 5591 (void) fclose(policy_fp); 5592 5593 if (delete_from_file(prev_prev_offset, nlines) != 0) { 5594 warnx(gettext("delete_from_file failure. " 5595 "Please flush all entries and re-configure :")); 5596 reconfigure(); 5597 (void) fclose(remove_fp); 5598 free(act_props); 5599 return (-1); 5600 } 5601 5602 if (pfp_delete_rule(pindex) != 0) { 5603 warnx(gettext("Deletion incomplete. Please flush" 5604 "all the entries and re-configure :")); 5605 reconfigure(); 5606 (void) fclose(remove_fp); 5607 free(act_props); 5608 return (-1); 5609 } 5610 5611 /* reset the globals */ 5612 linecount = 0; 5613 pindex = 0; 5614 /* free(NULL) also works. */ 5615 free(interface_name); 5616 interface_name = NULL; 5617 5618 /* reopen for next pass, automagically starting over. */ 5619 policy_fp = fopen(POLICY_CONF_FILE, "r"); 5620 if (policy_fp == NULL) { 5621 warn(gettext("%s cannot be re-opened, can't continue"), 5622 POLICY_CONF_FILE); 5623 (void) fclose(remove_fp); 5624 free(act_props); 5625 return (-1); 5626 } 5627 5628 } /* read next remove policy */ 5629 5630 if ((ret = pfp_delete_rule(pindex)) != 0) { 5631 warnx(gettext("Removal incomplete. Please flush " 5632 "all the entries and re-configure :")); 5633 reconfigure(); 5634 free(act_props); 5635 return (ret); 5636 } 5637 5638 /* nothing left to look for */ 5639 (void) fclose(remove_fp); 5640 free(act_props); 5641 5642 return (0); 5643 } 5644 5645 /* 5646 * Constructs a tunnel interface ID extension. Returns the length 5647 * of the extension in 64-bit-words. 5648 */ 5649 static int 5650 attach_tunname(spd_if_t *tunname) 5651 { 5652 if (tunname == NULL || interface_name == NULL) 5653 return (0); 5654 5655 tunname->spd_if_exttype = SPD_EXT_TUN_NAME; 5656 /* 5657 * Use "-3" because there's 4 bytes in the message itself, and 5658 * we lose one because of the '\0' terminator. 5659 */ 5660 tunname->spd_if_len = SPD_8TO64( 5661 P2ROUNDUP(sizeof (*tunname) + strlen(interface_name) - 3, 8)); 5662 (void) strlcpy((char *)tunname->spd_if_name, interface_name, LIFNAMSIZ); 5663 return (tunname->spd_if_len); 5664 } 5665