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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <strings.h> 30 #include <stropts.h> 31 #include <fcntl.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <string.h> 35 #include <ctype.h> 36 #include <arpa/inet.h> 37 #include <locale.h> 38 #include <syslog.h> 39 #include <pwd.h> 40 #include <sys/param.h> 41 #include <sys/sysmacros.h> /* MIN, MAX */ 42 #include <sys/sockio.h> 43 #include <net/pfkeyv2.h> 44 #include <net/pfpolicy.h> 45 #include <inet/ipsec_impl.h> 46 #include <signal.h> 47 #include <errno.h> 48 #include <netdb.h> 49 #include <sys/socket.h> 50 #include <sys/systeminfo.h> 51 #include <nss_dbdefs.h> /* NSS_BUFLEN_HOSTS */ 52 #include <netinet/in.h> 53 #include <assert.h> 54 #include <inet/ip.h> 55 #include <ipsec_util.h> 56 #include <netinet/in_systm.h> 57 #include <netinet/ip_icmp.h> 58 #include <netinet/icmp6.h> 59 60 /* 61 * Globals 62 */ 63 int lfd; 64 char *my_fmri; 65 FILE *debugfile = stderr; 66 67 #define USAGE() if (!smf_managed) usage() 68 /* 69 * Buffer length to read in pattern/properties. 70 */ 71 #define MAXLEN 1024 72 73 /* Max length of tunnel interface string identifier */ 74 #define TUNNAMEMAXLEN LIFNAMSIZ 75 76 /* 77 * Used by parse_one and parse/parse_action to communicate 78 * the errors. -1 is failure, which is not defined here. 79 */ 80 enum parse_errors {PARSE_SUCCESS, PARSE_EOF}; 81 82 /* 83 * For spdsock_get_ext() diagnostics. 84 */ 85 #define SPDSOCK_DIAG_BUF_LEN 128 86 static char spdsock_diag_buf[SPDSOCK_DIAG_BUF_LEN]; 87 88 /* 89 * Define CURL here so that while you are reading 90 * this code, it does not affect "vi" in pattern 91 * matching. 92 */ 93 #define CURL_BEGIN '{' 94 #define CURL_END '}' 95 #define BACK_SLASH '\\' 96 #define MAXARGS 20 97 #define NOERROR 0 98 99 /* 100 * IPSEC_CONF_ADD should start with 1, so that when multiple commands 101 * are given, we can fail the request. 102 */ 103 104 enum ipsec_cmds {IPSEC_CONF_ADD = 1, IPSEC_CONF_DEL, IPSEC_CONF_VIEW, 105 IPSEC_CONF_FLUSH, IPSEC_CONF_LIST, IPSEC_CONF_SUB}; 106 107 static const char policy_conf_file[] = "/var/run/ipsecpolicy.conf"; 108 static const char lock_file[] = "/var/run/ipsecconf.lock"; 109 static const char index_tag[] = "#INDEX"; 110 111 #define POLICY_CONF_FILE policy_conf_file 112 #define LOCK_FILE lock_file 113 #define INDEX_TAG index_tag 114 115 /* 116 * Valid algorithm length. 117 */ 118 #define VALID_ALG_LEN 40 119 120 /* Types of Error messages */ 121 typedef enum error_type {BAD_ERROR, DUP_ERROR, REQ_ERROR} error_type_t; 122 123 /* Error message human readable conversions */ 124 static char *sys_error_message(int); 125 static void error_message(error_type_t, int, int); 126 static int get_pf_pol_socket(void); 127 128 static int cmd; 129 static char *filename; 130 static char lo_buf[MAXLEN]; /* Leftover buffer */ 131 132 /* 133 * The new SPD_EXT_TUN_NAME extension has a tunnel name in it. Use the empty 134 * string ("", stored in the char value "all_polheads") for all policy heads 135 * (global and all tunnels). Set interface_name to NULL for global-only, or 136 * specify a name of an IP-in-IP tunnel. 137 */ 138 static char *interface_name; 139 static char all_polheads; /* So we can easily get "". */ 140 141 /* Error reporting stuff */ 142 #define CBUF_LEN 4096 /* Maximum size of the cmd */ 143 /* 144 * Following are used for reporting errors with arguments. 145 * We store the line numbers of each argument as we parse them, 146 * so that the error reporting is more specific. We can have only 147 * (MAXARGS - 1) arguments between any pair of CURL_BEGIN CURL_END. 148 * Because a single command can be made up of multiple action/property 149 * combinations, the maximum command size is (2 * (MAXARGS -1)) for each 150 * of patterns, properties and actions. 151 */ 152 #define ARG_BUF_LEN ((2 * 3 * (MAXARGS - 1)) + 1) 153 static int arg_indices[ARG_BUF_LEN]; 154 static int argindex; 155 static int linecount; 156 static char cbuf[CBUF_LEN]; /* Command buffer */ 157 static int cbuf_offset; 158 159 160 #define BYPASS_POLICY_BOOST 0x00800000 161 #define ESP_POLICY_BOOST 0x00400000 162 #define AH_POLICY_BOOST 0x00200000 163 #define INITIAL_BASE_PRIORITY 0x000fffff 164 165 /* 166 * the number used to order the 167 * rules starts at a certain base and 168 * goes down. i.e. rules earlier in 169 * the file are checked first 170 */ 171 static uint32_t priority = INITIAL_BASE_PRIORITY; 172 173 #define AH_AUTH 0 174 #define ESP_ENCR 1 175 #define ESP_AUTH 2 176 177 178 /* 179 * for deleting adds on error 180 */ 181 182 typedef struct d_list_s 183 { 184 struct d_list_s *next; 185 int index; 186 } d_list_t; 187 188 static d_list_t *d_list = NULL; 189 static d_list_t *d_tail = NULL; 190 191 192 /* 193 * Used for multi-homed source/dest hosts. 194 */ 195 static struct hostent *shp, *dhp; 196 static unsigned int splen, dplen; 197 static char tunif[TUNNAMEMAXLEN]; 198 static boolean_t has_saprefix, has_daprefix; 199 static uint32_t seq_cnt = 0; 200 201 /* lexxed out action and related properties */ 202 typedef struct ap_s 203 { 204 char *act; 205 char *prop[MAXARGS + 1]; 206 } ap_t; 207 208 209 /* one lexxed out rule */ 210 typedef struct act_prop_s { 211 char *pattern[MAXARGS + 1]; 212 ap_t ap[MAXARGS + 1]; 213 } act_prop_t; 214 215 typedef struct 216 { 217 uint8_t alg_id; 218 uint32_t alg_minbits; 219 uint32_t alg_maxbits; 220 } algreq_t; 221 222 /* structure to hold all information for one act_prop_t */ 223 typedef struct ips_act_props_s { 224 struct ips_act_props_s *iap_next; 225 struct ips_conf_s *iap_head; 226 227 /* 228 * IPsec action types (in SPD_ATTR_TYPE attribute) 229 * SPD_ACTTYPE_DROP 0x0001 230 * SPD_ACTTYPE_PASS 0x0002 231 * SPD_ACTTYPE_IPSEC 0x0003 232 */ 233 uint16_t iap_action; 234 uint16_t iap_act_tok; 235 236 /* 237 * Action ATTR flags (in SPD_ATTR_FLAGS attribute) 238 * SPD_APPLY_AH 0x0001 239 * SPD_APPLY_ESP 0x0002 240 * SPD_APPLY_SE 0x0004 * self-encapsulation * 241 * SPD_APPLY_COMP 0x0008 * compression; NYI * 242 * SPD_APPLY_UNIQUE 0x0010 * unique per-flow SA * 243 * SPD_APPLY_BYPASS 0x0020 * bypass policy * 244 */ 245 uint16_t iap_attr; 246 uint16_t iap_attr_tok[5]; 247 248 algreq_t iap_aauth; 249 algreq_t iap_eencr; 250 algreq_t iap_eauth; 251 252 uint32_t iap_life_soft_time; 253 uint32_t iap_life_hard_time; 254 uint32_t iap_life_soft_bytes; 255 uint32_t iap_life_hard_bytes; 256 257 } ips_act_props_t; 258 259 #define V4_PART_OF_V6(v6) v6._S6_un._S6_u32[3] 260 261 typedef struct ips_conf_s { 262 /* selector */ 263 uint16_t patt_tok[8]; 264 uint8_t has_saddr; 265 uint8_t has_daddr; 266 uint8_t has_smask; 267 uint8_t has_dmask; 268 uint8_t has_type; 269 uint8_t has_code; 270 uint8_t has_negotiate; 271 uint8_t has_tunnel; 272 uint16_t swap; 273 274 struct in6_addr ips_src_addr_v6; 275 struct in6_addr ips_src_mask_v6; 276 struct in6_addr ips_dst_addr_v6; 277 struct in6_addr ips_dst_mask_v6; 278 uint8_t ips_src_mask_len; 279 uint8_t ips_dst_mask_len; 280 in_port_t ips_src_port_min; 281 in_port_t ips_src_port_max; 282 in_port_t ips_dst_port_min; 283 in_port_t ips_dst_port_max; 284 uint8_t ips_icmp_type; 285 uint8_t ips_icmp_type_end; 286 uint8_t ips_icmp_code; 287 uint8_t ips_icmp_code_end; 288 uint8_t ips_ulp_prot; 289 uint8_t ips_ipsec_prot; 290 uint8_t ips_isv4; 291 /* 292 * SPD_RULE_FLAG_INBOUND 0x0001 293 * SPD_RULE_FLAG_OUTBOUND 0x0002 294 */ 295 uint8_t ips_dir; 296 /* 297 * Keep track of tunnel separately due to explosion of ways to set 298 * inbound/outbound. 299 */ 300 boolean_t ips_tunnel; 301 uint64_t ips_policy_index; 302 uint32_t ips_act_cnt; 303 ips_act_props_t *ips_acts; 304 } ips_conf_t; 305 306 #define ips_src_addr V4_PART_OF_V6(ips_src_addr_v6) 307 #define ips_dst_addr V4_PART_OF_V6(ips_dst_addr_v6) 308 309 static int ipsecconf_nflag; /* Used only with -l option */ 310 static int ipsecconf_qflag; /* Used only with -a|-r option */ 311 312 typedef struct str_val { 313 const char *string; 314 int value; 315 } str_val_t; 316 317 typedef struct str_tval { 318 const char *string; 319 int tok_val; 320 int value; 321 } str_tval_t; 322 323 static int parse_int(const char *); 324 static int parse_index(const char *, char *); 325 static int attach_tunname(spd_if_t *); 326 static void usage(void); 327 static int ipsec_conf_del(int, boolean_t); 328 static int ipsec_conf_add(boolean_t, boolean_t); 329 static int ipsec_conf_sub(void); 330 static int ipsec_conf_flush(int); 331 static int ipsec_conf_view(void); 332 static int ipsec_conf_list(void); 333 static int lock(void); 334 static int unlock(int); 335 static int parse_one(FILE *, act_prop_t *); 336 static void reconfigure(); 337 static void in_prefixlentomask(unsigned int, uchar_t *); 338 static int in_getprefixlen(char *); 339 static int parse_address(int, char *); 340 #ifdef DEBUG_HEAVY 341 static void pfpol_msg_dump(spd_msg_t *msg, char *); 342 #endif /* DEBUG_HEAVY */ 343 static void print_pfpol_msg(spd_msg_t *); 344 static int pfp_delete_rule(uint64_t); 345 static void ipsec_conf_admin(uint8_t); 346 static void print_bit_range(int, int); 347 static void nuke_adds(); 348 349 #ifdef DEBUG 350 static void dump_conf(ips_conf_t *); 351 #endif 352 353 typedef struct 354 { 355 uint32_t id; 356 uint32_t minkeybits; 357 uint32_t maxkeybits; 358 uint32_t defkeybits; 359 uint32_t incr; 360 } alginfo_t; 361 362 static int ipsec_nalgs[3]; 363 static alginfo_t known_algs[3][256]; 364 365 #define IPS_SRC_MASK SPD_EXT_LCLADDR + 100 366 #define IPS_DST_MASK SPD_EXT_REMADDR + 100 367 368 /* 369 * if inbound, src=remote, dst=local 370 * if outbound, src=local, dst=remote 371 */ 372 373 #define TOK_saddr 1 374 #define TOK_daddr 2 375 #define TOK_sport 3 376 #define TOK_dport 4 377 #define TOK_smask 5 378 #define TOK_dmask 6 379 #define TOK_ulp 7 380 #define TOK_local 8 381 #define TOK_lport 9 382 #define TOK_remote 10 383 #define TOK_rport 11 384 #define TOK_dir 12 385 #define TOK_type 13 386 #define TOK_code 14 387 #define TOK_negotiate 15 388 #define TOK_tunnel 16 389 390 #define IPS_SA SPD_ATTR_END 391 #define IPS_DIR SPD_ATTR_EMPTY 392 #define IPS_NEG SPD_ATTR_NOP 393 394 395 static str_tval_t pattern_table[] = { 396 {"saddr", TOK_saddr, SPD_EXT_LCLADDR}, 397 {"src", TOK_saddr, SPD_EXT_LCLADDR}, 398 {"srcaddr", TOK_saddr, SPD_EXT_LCLADDR}, 399 {"daddr", TOK_daddr, SPD_EXT_REMADDR}, 400 {"dst", TOK_daddr, SPD_EXT_REMADDR}, 401 {"dstaddr", TOK_daddr, SPD_EXT_REMADDR}, 402 {"sport", TOK_sport, SPD_EXT_LCLPORT}, 403 {"dport", TOK_dport, SPD_EXT_REMPORT}, 404 {"smask", TOK_smask, IPS_SRC_MASK}, 405 {"dmask", TOK_dmask, IPS_DST_MASK}, 406 {"ulp", TOK_ulp, SPD_EXT_PROTO}, 407 {"proto", TOK_ulp, SPD_EXT_PROTO}, 408 {"local", TOK_local, SPD_EXT_LCLADDR}, 409 {"laddr", TOK_local, SPD_EXT_LCLADDR}, 410 {"lport", TOK_lport, SPD_EXT_LCLPORT}, 411 {"remote", TOK_remote, SPD_EXT_REMADDR}, 412 {"raddr", TOK_remote, SPD_EXT_REMADDR}, 413 {"rport", TOK_rport, SPD_EXT_REMPORT}, 414 {"dir", TOK_dir, IPS_DIR}, 415 {"type", TOK_type, SPD_EXT_ICMP_TYPECODE}, 416 {"code", TOK_code, SPD_EXT_ICMP_TYPECODE}, 417 {"negotiate", TOK_negotiate, IPS_NEG}, 418 {"tunnel", TOK_tunnel, SPD_EXT_TUN_NAME}, 419 {NULL, 0, 0}, 420 }; 421 422 #define TOK_apply 1 423 #define TOK_permit 2 424 #define TOK_ipsec 3 425 #define TOK_bypass 4 426 #define TOK_drop 5 427 #define TOK_or 6 428 429 static str_tval_t action_table[] = { 430 {"apply", TOK_apply, SPD_ACTTYPE_IPSEC}, 431 {"permit", TOK_permit, SPD_ACTTYPE_IPSEC}, 432 {"ipsec", TOK_ipsec, SPD_ACTTYPE_IPSEC}, 433 {"bypass", TOK_bypass, SPD_ACTTYPE_PASS}, 434 {"pass", TOK_bypass, SPD_ACTTYPE_PASS}, 435 {"drop", TOK_drop, SPD_ACTTYPE_DROP}, 436 {"or", TOK_or, 0}, 437 {NULL, 0, 0}, 438 }; 439 440 static str_val_t property_table[] = { 441 {"auth_algs", SPD_ATTR_AH_AUTH}, 442 {"encr_algs", SPD_ATTR_ESP_ENCR}, 443 {"encr_auth_algs", SPD_ATTR_ESP_AUTH}, 444 {"sa", IPS_SA}, 445 {"dir", IPS_DIR}, 446 {NULL, 0}, 447 }; 448 449 static str_val_t icmp_type_table[] = { 450 {"unreach", ICMP_UNREACH}, 451 {"echo", ICMP_ECHO}, 452 {"echorep", ICMP_ECHOREPLY}, 453 {"squench", ICMP_SOURCEQUENCH}, 454 {"redir", ICMP_REDIRECT}, 455 {"timex", ICMP_TIMXCEED}, 456 {"paramprob", ICMP_PARAMPROB}, 457 {"timest", ICMP_TSTAMP}, 458 {"timestrep", ICMP_TSTAMPREPLY}, 459 {"inforeq", ICMP_IREQ}, 460 {"inforep", ICMP_IREQREPLY}, 461 {"maskreq", ICMP_MASKREQ}, 462 {"maskrep", ICMP_MASKREPLY}, 463 {"unreach6", ICMP6_DST_UNREACH}, 464 {"pkttoobig6", ICMP6_PACKET_TOO_BIG}, 465 {"timex6", ICMP6_TIME_EXCEEDED}, 466 {"paramprob6", ICMP6_PARAM_PROB}, 467 {"echo6", ICMP6_ECHO_REQUEST}, 468 {"echorep6", ICMP6_ECHO_REPLY}, 469 {"router-sol6", ND_ROUTER_SOLICIT}, 470 {"router-ad6", ND_ROUTER_ADVERT}, 471 {"neigh-sol6", ND_NEIGHBOR_SOLICIT}, 472 {"neigh-ad6", ND_NEIGHBOR_ADVERT}, 473 {"redir6", ND_REDIRECT}, 474 {NULL, 0}, 475 }; 476 477 static str_val_t icmp_code_table[] = { 478 {"net-unr", ICMP_UNREACH_NET}, 479 {"host-unr", ICMP_UNREACH_HOST}, 480 {"proto-unr", ICMP_UNREACH_PROTOCOL}, 481 {"port-unr", ICMP_UNREACH_PORT}, 482 {"needfrag", ICMP_UNREACH_NEEDFRAG}, 483 {"srcfail", ICMP_UNREACH_SRCFAIL}, 484 {"net-unk", ICMP_UNREACH_NET_UNKNOWN}, 485 {"host-unk", ICMP_UNREACH_HOST_UNKNOWN}, 486 {"isolate", ICMP_UNREACH_ISOLATED}, 487 {"net-prohib", ICMP_UNREACH_NET_PROHIB}, 488 {"host-prohib", ICMP_UNREACH_HOST_PROHIB}, 489 {"net-tos", ICMP_UNREACH_TOSNET}, 490 {"host-tos", ICMP_UNREACH_TOSHOST}, 491 {"filter-prohib", ICMP_UNREACH_FILTER_PROHIB}, 492 {"host-preced", ICMP_UNREACH_HOST_PRECEDENCE}, 493 {"cutoff-preced", ICMP_UNREACH_PRECEDENCE_CUTOFF}, 494 {"no-route6", ICMP6_DST_UNREACH_NOROUTE}, 495 {"adm-prohib6", ICMP6_DST_UNREACH_ADMIN}, 496 {"addr-unr6", ICMP6_DST_UNREACH_ADDR}, 497 {"port-unr6", ICMP6_DST_UNREACH_NOPORT}, 498 {"hop-limex6", ICMP6_TIME_EXCEED_TRANSIT}, 499 {"frag-re-timex6", ICMP6_TIME_EXCEED_REASSEMBLY}, 500 {"err-head6", ICMP6_PARAMPROB_HEADER}, 501 {"unrec-head6", ICMP6_PARAMPROB_NEXTHEADER}, 502 {"unreq-opt6", ICMP6_PARAMPROB_OPTION}, 503 {NULL, 0}, 504 }; 505 506 static sigset_t set, oset; 507 508 509 static boolean_t 510 add_index(int index) 511 { 512 d_list_t *temp = malloc(sizeof (d_list_t)); 513 514 if (temp == NULL) { 515 warn("malloc"); 516 return (B_TRUE); 517 } 518 519 temp->index = index; 520 temp->next = NULL; 521 522 if (d_tail == NULL) { 523 d_list = d_tail = temp; 524 return (B_FALSE); 525 } 526 527 d_tail->next = temp; 528 d_tail = temp; 529 530 return (B_FALSE); 531 } 532 533 static int 534 block_all_signals() 535 { 536 if (sigfillset(&set) == -1) { 537 warn("sigfillset"); 538 return (-1); 539 } 540 if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) { 541 warn("sigprocmask"); 542 return (-1); 543 } 544 return (0); 545 } 546 547 static int 548 restore_all_signals() 549 { 550 if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) { 551 warn("sigprocmask"); 552 return (-1); 553 } 554 return (0); 555 } 556 557 /* allocate an ips_act_props_t and link it in correctly */ 558 static ips_act_props_t * 559 alloc_iap(ips_conf_t *parent) 560 { 561 ips_act_props_t *ret; 562 ips_act_props_t *next = parent->ips_acts; 563 ips_act_props_t *current = NULL; 564 565 ret = (ips_act_props_t *)calloc(sizeof (ips_act_props_t), 1); 566 567 if (ret == NULL) 568 return (NULL); 569 570 ret->iap_head = parent; 571 572 while (next != NULL) { 573 current = next; 574 next = next->iap_next; 575 } 576 577 if (current != NULL) 578 current->iap_next = ret; 579 else 580 parent->ips_acts = ret; 581 582 parent->ips_act_cnt++; 583 584 return (ret); 585 } 586 587 /* 588 * This function exit()s if it fails. 589 */ 590 static void 591 fetch_algorithms() 592 { 593 struct spd_msg msg; 594 struct spd_ext_actions *actp; 595 struct spd_attribute *attr, *endattr; 596 spd_ext_t *exts[SPD_EXT_MAX+1]; 597 uint64_t reply_buf[256]; 598 int sfd; 599 int cnt, retval; 600 uint64_t *start, *end; 601 alginfo_t alg = {0, 0, 0, 0, 0}; 602 uint_t algtype; 603 static boolean_t has_run = B_FALSE; 604 605 if (has_run) 606 return; 607 else 608 has_run = B_TRUE; 609 610 sfd = get_pf_pol_socket(); 611 if (sfd < 0) { 612 err(-1, gettext("unable to open policy socket")); 613 } 614 615 (void) memset(&msg, 0, sizeof (msg)); 616 msg.spd_msg_version = PF_POLICY_V1; 617 msg.spd_msg_type = SPD_ALGLIST; 618 msg.spd_msg_len = SPD_8TO64(sizeof (msg)); 619 620 cnt = write(sfd, &msg, sizeof (msg)); 621 if (cnt != sizeof (msg)) { 622 if (cnt < 0) { 623 err(-1, gettext("alglist failed: write")); 624 } else { 625 errx(-1, gettext("alglist failed: short write")); 626 } 627 } 628 629 cnt = read(sfd, reply_buf, sizeof (reply_buf)); 630 631 retval = spdsock_get_ext(exts, (spd_msg_t *)reply_buf, SPD_8TO64(cnt), 632 spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN); 633 634 if (retval == KGE_LEN && exts[0]->spd_ext_len == 0) { 635 /* 636 * No algorithms are defined in the kernel, which caused 637 * the extension length to be zero, and spdsock_get_ext() 638 * to fail with a KGE_LEN error. This is not an error 639 * condition, so we return nicely. 640 */ 641 (void) close(sfd); 642 return; 643 } else if (retval != 0) { 644 if (strlen(spdsock_diag_buf) != 0) 645 warnx(spdsock_diag_buf); 646 err(1, gettext("fetch_algorithms failed")); 647 } 648 649 if (!exts[SPD_EXT_ACTION]) { 650 errx(1, gettext("fetch_algorithms: action missing?!")); 651 } 652 653 actp = (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 654 start = (uint64_t *)actp; 655 end = (start + actp->spd_actions_len); 656 endattr = (struct spd_attribute *)end; 657 attr = (struct spd_attribute *)&actp[1]; 658 659 algtype = 0; 660 661 while (attr < endattr) { 662 switch (attr->spd_attr_tag) { 663 case SPD_ATTR_NOP: 664 case SPD_ATTR_EMPTY: 665 break; 666 case SPD_ATTR_END: 667 attr = endattr; 668 /* FALLTHRU */ 669 case SPD_ATTR_NEXT: 670 known_algs[algtype][ipsec_nalgs[algtype]] = alg; 671 ipsec_nalgs[algtype]++; 672 break; 673 674 case SPD_ATTR_ENCR_MINBITS: 675 case SPD_ATTR_AH_MINBITS: 676 case SPD_ATTR_ESPA_MINBITS: 677 alg.minkeybits = attr->spd_attr_value; 678 break; 679 680 case SPD_ATTR_ENCR_MAXBITS: 681 case SPD_ATTR_AH_MAXBITS: 682 case SPD_ATTR_ESPA_MAXBITS: 683 alg.maxkeybits = attr->spd_attr_value; 684 break; 685 686 case SPD_ATTR_ENCR_DEFBITS: 687 case SPD_ATTR_AH_DEFBITS: 688 case SPD_ATTR_ESPA_DEFBITS: 689 alg.defkeybits = attr->spd_attr_value; 690 break; 691 692 case SPD_ATTR_ENCR_INCRBITS: 693 case SPD_ATTR_AH_INCRBITS: 694 case SPD_ATTR_ESPA_INCRBITS: 695 alg.incr = attr->spd_attr_value; 696 break; 697 698 case SPD_ATTR_AH_AUTH: 699 case SPD_ATTR_ESP_AUTH: 700 case SPD_ATTR_ESP_ENCR: 701 alg.id = attr->spd_attr_value; 702 algtype = attr->spd_attr_tag - SPD_ATTR_AH_AUTH; 703 break; 704 } 705 attr++; 706 } 707 708 (void) close(sfd); 709 } 710 711 /* data dependant transform (act_cnt) */ 712 #define ATTR(ap, tag, value) \ 713 do { (ap)->spd_attr_tag = (tag); \ 714 (ap)->spd_attr_value = (value); \ 715 ap++; } while (0) 716 717 static struct spd_attribute * 718 emit_alg(struct spd_attribute *ap, int type, const algreq_t *ar, 719 int algattr, int minbitattr, int maxbitattr) 720 { 721 int id = ar->alg_id; 722 int minbits, i; 723 724 if (id != 0) { 725 /* LINTED E_CONST_COND */ 726 ATTR(ap, algattr, ar->alg_id); 727 728 minbits = ar->alg_minbits; 729 if (minbits == 0) { 730 for (i = 0; i < ipsec_nalgs[type]; i++) { 731 if (known_algs[type][i].id == id) 732 break; 733 } 734 if (i < ipsec_nalgs[type]) 735 minbits = known_algs[type][i].defkeybits; 736 } 737 if (minbits != 0) 738 /* LINTED E_CONST_COND */ 739 ATTR(ap, minbitattr, minbits); 740 if (ar->alg_maxbits != SPD_MAX_MAXBITS) 741 /* LINTED E_CONST_COND */ 742 ATTR(ap, maxbitattr, ar->alg_maxbits); 743 } 744 745 return (ap); 746 } 747 748 749 750 static struct spd_attribute * 751 ips_act_props_to_action(struct spd_attribute *ap, uint32_t *rule_priorityp, 752 const ips_act_props_t *act_ptr) 753 { 754 uint32_t rule_priority = *rule_priorityp; 755 756 /* LINTED E_CONST_COND */ 757 ATTR(ap, SPD_ATTR_EMPTY, 0); 758 759 /* type */ 760 /* LINTED E_CONST_COND */ 761 ATTR(ap, SPD_ATTR_TYPE, act_ptr->iap_action); 762 763 if (act_ptr->iap_action == SPD_ACTTYPE_PASS) 764 rule_priority |= BYPASS_POLICY_BOOST; 765 766 /* flags */ 767 if (act_ptr->iap_attr != 0) 768 /* LINTED E_CONST_COND */ 769 ATTR(ap, SPD_ATTR_FLAGS, act_ptr->iap_attr); 770 771 /* esp */ 772 if (act_ptr->iap_attr & SPD_APPLY_ESP) { 773 rule_priority |= ESP_POLICY_BOOST; 774 775 /* encr */ 776 ap = emit_alg(ap, ESP_ENCR, &act_ptr->iap_eencr, 777 SPD_ATTR_ESP_ENCR, 778 SPD_ATTR_ENCR_MINBITS, SPD_ATTR_ENCR_MAXBITS); 779 780 /* auth */ 781 ap = emit_alg(ap, ESP_AUTH, &act_ptr->iap_eauth, 782 SPD_ATTR_ESP_AUTH, 783 SPD_ATTR_ESPA_MINBITS, SPD_ATTR_ESPA_MAXBITS); 784 } 785 786 /* ah */ 787 if (act_ptr->iap_attr & SPD_APPLY_AH) { 788 rule_priority |= AH_POLICY_BOOST; 789 /* auth */ 790 ap = emit_alg(ap, AH_AUTH, &act_ptr->iap_aauth, 791 SPD_ATTR_AH_AUTH, 792 SPD_ATTR_AH_MINBITS, SPD_ATTR_AH_MAXBITS); 793 } 794 795 /* lifetimes */ 796 if (act_ptr->iap_life_soft_time != 0) 797 /* LINTED E_CONST_COND */ 798 ATTR(ap, SPD_ATTR_LIFE_SOFT_TIME, act_ptr->iap_life_soft_time); 799 if (act_ptr->iap_life_hard_time != 0) 800 /* LINTED E_CONST_COND */ 801 ATTR(ap, SPD_ATTR_LIFE_HARD_TIME, act_ptr->iap_life_hard_time); 802 if (act_ptr->iap_life_soft_bytes != 0) 803 /* LINTED E_CONST_COND */ 804 ATTR(ap, SPD_ATTR_LIFE_SOFT_BYTES, 805 act_ptr->iap_life_soft_bytes); 806 if (act_ptr->iap_life_hard_bytes != 0) 807 /* LINTED E_CONST_COND */ 808 ATTR(ap, SPD_ATTR_LIFE_HARD_BYTES, 809 act_ptr->iap_life_hard_bytes); 810 811 /* LINTED E_CONST_COND */ 812 ATTR(ap, SPD_ATTR_NEXT, 0); 813 814 *rule_priorityp = rule_priority; 815 816 return (ap); 817 } 818 819 static boolean_t 820 alg_rangecheck(uint_t type, uint_t algid, const algreq_t *ar) 821 { 822 int i; 823 uint_t minbits = ar->alg_minbits; 824 uint_t maxbits = ar->alg_maxbits; 825 826 for (i = 0; i < ipsec_nalgs[type]; i++) { 827 if (known_algs[type][i].id == algid) 828 break; 829 } 830 831 if (i >= ipsec_nalgs[type]) { 832 /* 833 * The kernel (where we populate known_algs from) doesn't 834 * return the id's associated with NONE algorithms so we 835 * test here if this was the reason the algorithm wasn't 836 * found before wrongly failing. 837 */ 838 if (((type == ESP_ENCR) && (algid == SADB_EALG_NONE)) || 839 ((type == ESP_AUTH) && (algid == SADB_AALG_NONE)) || 840 ((type == AH_AUTH) && (algid == SADB_AALG_NONE))) { 841 return (B_TRUE); 842 } else { 843 return (B_FALSE); /* not found */ 844 } 845 } 846 847 if ((minbits == 0) && (maxbits == 0)) 848 return (B_TRUE); 849 850 minbits = MAX(minbits, known_algs[type][i].minkeybits); 851 maxbits = MIN(maxbits, known_algs[type][i].maxkeybits); 852 853 /* we could also check key increments here.. */ 854 return (minbits <= maxbits); /* non-null intersection */ 855 } 856 857 /* 858 * Inspired by uts/common/inet/spd.c:ipsec_act_wildcard_expand() 859 */ 860 861 static struct spd_attribute * 862 ips_act_wild_props_to_action(struct spd_attribute *ap, 863 uint32_t *rule_priorityp, uint16_t *act_cntp, 864 const ips_act_props_t *act_ptr) 865 { 866 ips_act_props_t tact = *act_ptr; 867 boolean_t use_ah, use_esp, use_espa; 868 boolean_t wild_auth, wild_encr, wild_eauth; 869 uint_t auth_alg, auth_idx, auth_min, auth_max; 870 uint_t eauth_alg, eauth_idx, eauth_min, eauth_max; 871 uint_t encr_alg, encr_idx, encr_min, encr_max; 872 873 use_ah = !!(act_ptr->iap_attr & SPD_APPLY_AH); 874 use_esp = !!(act_ptr->iap_attr & SPD_APPLY_ESP); 875 use_espa = !!(act_ptr->iap_attr & SPD_APPLY_ESPA); 876 auth_alg = act_ptr->iap_aauth.alg_id; 877 eauth_alg = act_ptr->iap_eauth.alg_id; 878 encr_alg = act_ptr->iap_eencr.alg_id; 879 880 wild_auth = use_ah && (auth_alg == SADB_AALG_NONE); 881 wild_eauth = use_espa && (eauth_alg == SADB_AALG_NONE); 882 wild_encr = use_esp && (encr_alg == SADB_EALG_NONE); 883 884 auth_min = auth_max = auth_alg; 885 eauth_min = eauth_max = eauth_alg; 886 encr_min = encr_max = encr_alg; 887 888 /* 889 * set up for explosion.. for each dimension, expand output 890 * size by the explosion factor. 891 */ 892 if (wild_auth) { 893 auth_min = 0; 894 auth_max = ipsec_nalgs[AH_AUTH] - 1; 895 } 896 if (wild_eauth) { 897 eauth_min = 0; 898 eauth_max = ipsec_nalgs[ESP_AUTH] - 1; 899 } 900 if (wild_encr) { 901 encr_min = 0; 902 encr_max = ipsec_nalgs[ESP_ENCR] - 1; 903 } 904 905 #define WHICH_ALG(type, wild, idx) ((wild)?(known_algs[type][idx].id):(idx)) 906 907 for (encr_idx = encr_min; encr_idx <= encr_max; encr_idx++) { 908 encr_alg = WHICH_ALG(ESP_ENCR, wild_encr, encr_idx); 909 910 if (use_esp && 911 !alg_rangecheck(ESP_ENCR, encr_alg, &act_ptr->iap_eencr)) 912 continue; 913 914 for (auth_idx = auth_min; auth_idx <= auth_max; auth_idx++) { 915 auth_alg = WHICH_ALG(AH_AUTH, wild_auth, auth_idx); 916 917 if (use_ah && 918 !alg_rangecheck(AH_AUTH, auth_alg, 919 &act_ptr->iap_aauth)) 920 continue; 921 922 923 for (eauth_idx = eauth_min; eauth_idx <= eauth_max; 924 eauth_idx++) { 925 eauth_alg = WHICH_ALG(ESP_AUTH, wild_eauth, 926 eauth_idx); 927 928 if (use_espa && 929 !alg_rangecheck(ESP_AUTH, eauth_alg, 930 &act_ptr->iap_eauth)) 931 continue; 932 933 tact.iap_eencr.alg_id = encr_alg; 934 tact.iap_eauth.alg_id = eauth_alg; 935 tact.iap_aauth.alg_id = auth_alg; 936 937 (*act_cntp)++; 938 ap = ips_act_props_to_action(ap, 939 rule_priorityp, &tact); 940 } 941 } 942 } 943 944 #undef WHICH_ALG 945 946 return (ap); 947 } 948 949 /* huge, but not safe since no length checking is done */ 950 #define MAX_POL_MSG_LEN 16384 951 952 953 /* 954 * hand in some ips_conf_t's, get back an 955 * iovec of pfpol messages. 956 * this function converts the internal ips_conf_t into 957 * a form that pf_pol can use. 958 * return 0 on success, 1 on failure 959 */ 960 static int 961 ips_conf_to_pfpol_msg(int ipsec_cmd, ips_conf_t *inConf, int num_ips, 962 struct iovec *msg) 963 { 964 int i; 965 ips_conf_t *conf; 966 uint64_t *scratch = NULL; 967 968 for (i = 0; i < num_ips; i++) { 969 uint16_t *msg_len; 970 uint16_t act_cnt = 0; 971 uint64_t *next = NULL; 972 spd_msg_t *spd_msg; 973 spd_address_t *spd_address; 974 struct spd_rule *spd_rule; 975 struct spd_proto *spd_proto; 976 struct spd_portrange *spd_portrange; 977 struct spd_ext_actions *spd_ext_actions; 978 struct spd_attribute *ap; 979 struct spd_typecode *spd_typecode; 980 spd_if_t *spd_if; 981 ips_act_props_t *act_ptr; 982 uint32_t rule_priority = 0; 983 984 scratch = calloc(1, MAX_POL_MSG_LEN); 985 msg[i].iov_base = (char *)scratch; 986 if (scratch == NULL) { 987 warn(gettext("memory")); 988 return (1); 989 } 990 conf = &(inConf[i]); 991 992 spd_msg = (spd_msg_t *)scratch; 993 next = (uint64_t *)&(spd_msg[1]); 994 995 msg_len = &(spd_msg->spd_msg_len); 996 997 spd_msg->spd_msg_version = PF_POLICY_V1; 998 spd_msg->spd_msg_pid = getpid(); 999 spd_msg->spd_msg_seq = ++seq_cnt; 1000 1001 switch (ipsec_cmd) { 1002 case SPD_ADDRULE: 1003 spd_msg->spd_msg_type = SPD_ADDRULE; 1004 break; 1005 1006 default: 1007 warnx("%s %d", gettext("bad command:"), ipsec_cmd); 1008 spd_msg->spd_msg_type = SPD_ADDRULE; 1009 break; 1010 } 1011 1012 /* 1013 * SELECTOR 1014 */ 1015 1016 spd_msg->spd_msg_spdid = SPD_STANDBY; 1017 1018 /* rule */ 1019 spd_rule = (struct spd_rule *)next; 1020 1021 spd_rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule)); 1022 spd_rule->spd_rule_type = SPD_EXT_RULE; 1023 spd_rule->spd_rule_flags = conf->ips_dir; 1024 if (conf->ips_tunnel) 1025 spd_rule->spd_rule_flags |= SPD_RULE_FLAG_TUNNEL; 1026 1027 next = (uint64_t *)&(spd_rule[1]); 1028 1029 /* proto */ 1030 if (conf->ips_ulp_prot != 0) { 1031 spd_proto = (struct spd_proto *)next; 1032 spd_proto->spd_proto_len = 1033 SPD_8TO64(sizeof (struct spd_proto)); 1034 spd_proto->spd_proto_exttype = SPD_EXT_PROTO; 1035 spd_proto->spd_proto_number = conf->ips_ulp_prot; 1036 next = (uint64_t *)&(spd_proto[1]); 1037 } 1038 1039 /* tunnel */ 1040 if (conf->has_tunnel != 0) { 1041 spd_if = (spd_if_t *)next; 1042 spd_if->spd_if_len = 1043 SPD_8TO64(P2ROUNDUP(strlen(tunif) + 1, 8) + 1044 sizeof (spd_if_t)); 1045 spd_if->spd_if_exttype = SPD_EXT_TUN_NAME; 1046 (void) strlcpy((char *)spd_if->spd_if_name, tunif, 1047 TUNNAMEMAXLEN); 1048 next = (uint64_t *)(spd_if) + spd_if->spd_if_len; 1049 } 1050 1051 /* icmp type/code */ 1052 if (conf->ips_ulp_prot == IPPROTO_ICMP || 1053 conf->ips_ulp_prot == IPPROTO_ICMPV6) { 1054 if (conf->has_type) { 1055 spd_typecode = (struct spd_typecode *)next; 1056 spd_typecode->spd_typecode_len = 1057 SPD_8TO64(sizeof (struct spd_typecode)); 1058 spd_typecode->spd_typecode_exttype = 1059 SPD_EXT_ICMP_TYPECODE; 1060 spd_typecode->spd_typecode_type = 1061 conf->ips_icmp_type; 1062 spd_typecode->spd_typecode_type_end = 1063 conf->ips_icmp_type_end; 1064 if (conf->has_code) { 1065 spd_typecode->spd_typecode_code = 1066 conf->ips_icmp_code; 1067 spd_typecode->spd_typecode_code_end = 1068 conf->ips_icmp_code_end; 1069 } else { 1070 spd_typecode->spd_typecode_code = 255; 1071 spd_typecode->spd_typecode_code_end 1072 = 255; 1073 } 1074 next = (uint64_t *)&(spd_typecode[1]); 1075 } 1076 } 1077 1078 /* src port */ 1079 if (conf->ips_src_port_min != 0 || 1080 conf->ips_src_port_max != 0) { 1081 spd_portrange = (struct spd_portrange *)next; 1082 spd_portrange->spd_ports_len = 1083 SPD_8TO64(sizeof (struct spd_portrange)); 1084 spd_portrange->spd_ports_exttype = 1085 (conf->swap)?SPD_EXT_REMPORT:SPD_EXT_LCLPORT; 1086 spd_portrange->spd_ports_minport = 1087 conf->ips_src_port_min; 1088 spd_portrange->spd_ports_maxport = 1089 conf->ips_src_port_max; 1090 next = (uint64_t *)&(spd_portrange[1]); 1091 } 1092 /* dst port */ 1093 if (conf->ips_dst_port_min != 0 || 1094 conf->ips_dst_port_max != 0) { 1095 spd_portrange = (struct spd_portrange *)next; 1096 spd_portrange->spd_ports_len = 1097 SPD_8TO64(sizeof (struct spd_portrange)); 1098 spd_portrange->spd_ports_exttype = 1099 (conf->swap)?SPD_EXT_LCLPORT:SPD_EXT_REMPORT; 1100 spd_portrange->spd_ports_minport = 1101 conf->ips_dst_port_min; 1102 spd_portrange->spd_ports_maxport = 1103 conf->ips_dst_port_max; 1104 next = (uint64_t *)&(spd_portrange[1]); 1105 } 1106 1107 /* saddr */ 1108 if (conf->has_saddr) { 1109 spd_address = (spd_address_t *)next; 1110 next = (uint64_t *)(spd_address + 1); 1111 1112 spd_address->spd_address_exttype = 1113 (conf->swap)?SPD_EXT_REMADDR:SPD_EXT_LCLADDR; 1114 spd_address->spd_address_prefixlen = 1115 conf->ips_src_mask_len; 1116 1117 if (conf->ips_isv4) { 1118 spd_address->spd_address_af = AF_INET; 1119 (void) memcpy(next, &(conf->ips_src_addr), 1120 sizeof (ipaddr_t)); 1121 spd_address->spd_address_len = 2; 1122 next += SPD_8TO64(sizeof (ipaddr_t) + 4); 1123 if (!conf->has_smask) 1124 spd_address->spd_address_prefixlen = 32; 1125 } else { 1126 spd_address->spd_address_af = AF_INET6; 1127 (void) memcpy(next, &(conf->ips_src_addr_v6), 1128 sizeof (in6_addr_t)); 1129 spd_address->spd_address_len = 3; 1130 next += SPD_8TO64(sizeof (in6_addr_t)); 1131 if (!conf->has_smask) 1132 spd_address->spd_address_prefixlen 1133 = 128; 1134 } 1135 } 1136 1137 /* daddr */ 1138 if (conf->has_daddr) { 1139 spd_address = (spd_address_t *)next; 1140 1141 next = (uint64_t *)(spd_address + 1); 1142 1143 spd_address->spd_address_exttype = 1144 (conf->swap)?SPD_EXT_LCLADDR:SPD_EXT_REMADDR; 1145 spd_address->spd_address_prefixlen = 1146 conf->ips_dst_mask_len; 1147 1148 if (conf->ips_isv4) { 1149 spd_address->spd_address_af = AF_INET; 1150 (void) memcpy(next, &conf->ips_dst_addr, 1151 sizeof (ipaddr_t)); 1152 spd_address->spd_address_len = 2; 1153 /* "+ 4" below is for padding. */ 1154 next += SPD_8TO64(sizeof (ipaddr_t) + 4); 1155 if (!conf->has_dmask) 1156 spd_address->spd_address_prefixlen = 32; 1157 } else { 1158 spd_address->spd_address_af = AF_INET6; 1159 (void) memcpy(next, &(conf->ips_dst_addr_v6), 1160 sizeof (in6_addr_t)); 1161 spd_address->spd_address_len = 3; 1162 next += SPD_8TO64(sizeof (in6_addr_t)); 1163 if (!conf->has_dmask) 1164 spd_address->spd_address_prefixlen 1165 = 128; 1166 } 1167 } 1168 1169 /* actions */ 1170 spd_ext_actions = (struct spd_ext_actions *)next; 1171 1172 spd_ext_actions->spd_actions_exttype = SPD_EXT_ACTION; 1173 1174 act_ptr = conf->ips_acts; 1175 ap = (struct spd_attribute *)(&spd_ext_actions[1]); 1176 1177 rule_priority = priority--; 1178 1179 for (act_ptr = conf->ips_acts; act_ptr != NULL; 1180 act_ptr = act_ptr->iap_next) { 1181 ap = ips_act_wild_props_to_action(ap, &rule_priority, 1182 &act_cnt, act_ptr); 1183 } 1184 ap[-1].spd_attr_tag = SPD_ATTR_END; 1185 1186 next = (uint64_t *)ap; 1187 1188 spd_rule->spd_rule_priority = rule_priority; 1189 1190 msg[i].iov_len = (uintptr_t)next - (uintptr_t)msg[i].iov_base; 1191 *msg_len = (uint16_t)SPD_8TO64(msg[i].iov_len); 1192 spd_ext_actions->spd_actions_count = act_cnt; 1193 spd_ext_actions->spd_actions_len = 1194 SPD_8TO64((uintptr_t)next - (uintptr_t)spd_ext_actions); 1195 #ifdef DEBUG_HEAVY 1196 printf("pfpol msg len in uint64_t's = %d\n", *msg_len); 1197 printf("pfpol test_len in bytes = %d\n", msg[i].iov_len); 1198 pfpol_msg_dump((spd_msg_t *)scratch, 1199 "ips_conf_to_pfpol_msg"); 1200 #endif 1201 } 1202 1203 #undef ATTR 1204 return (0); 1205 } 1206 1207 static int 1208 get_pf_pol_socket(void) 1209 { 1210 int s = socket(PF_POLICY, SOCK_RAW, PF_POLICY_V1); 1211 if (s < 0) { 1212 if (errno == EPERM) { 1213 EXIT_BADPERM("Insufficient privileges to open " 1214 "PF_POLICY socket."); 1215 } else { 1216 warn(gettext("(loading pf_policy) socket:")); 1217 } 1218 } 1219 1220 return (s); 1221 } 1222 1223 1224 static int 1225 send_pf_pol_message(int ipsec_cmd, ips_conf_t *conf, int *diag) 1226 { 1227 int retval; 1228 int cnt; 1229 int total_len; 1230 struct iovec polmsg; 1231 spd_msg_t *return_buf; 1232 spd_ext_t *exts[SPD_EXT_MAX+1]; 1233 int fd = get_pf_pol_socket(); 1234 1235 *diag = 0; 1236 1237 if (fd < 0) 1238 return (EBADF); 1239 1240 retval = ips_conf_to_pfpol_msg(ipsec_cmd, conf, 1, &polmsg); 1241 1242 if (retval) { 1243 (void) close(fd); 1244 return (ENOMEM); 1245 } 1246 1247 total_len = polmsg.iov_len; 1248 1249 cnt = writev(fd, &polmsg, 1); 1250 1251 #ifdef DEBUG_HEAVY 1252 (void) printf("cnt = %d\n", cnt); 1253 #endif 1254 if (cnt < 0) { 1255 warn(gettext("pf_pol write")); 1256 } else { 1257 return_buf = (spd_msg_t *)calloc(total_len, 1); 1258 1259 if (return_buf == NULL) { 1260 warn(gettext("memory")); 1261 } else { 1262 cnt = read(fd, (void*)return_buf, total_len); 1263 #ifdef DEBUG_HEAVY 1264 (void) printf("pf_pol read: cnt = %d(%d)\n", cnt, 1265 total_len); 1266 #endif 1267 1268 if (cnt > 8 && return_buf->spd_msg_errno) { 1269 *diag = return_buf->spd_msg_diagnostic; 1270 if (!ipsecconf_qflag) { 1271 warnx("%s: %s", 1272 gettext("Kernel returned"), 1273 sys_error_message( 1274 return_buf->spd_msg_errno)); 1275 } 1276 if (*diag != 0) 1277 (void) printf(gettext( 1278 "\t(spdsock diagnostic: %s)\n"), 1279 spdsock_diag(*diag)); 1280 #ifdef DEBUG_HEAVY 1281 pfpol_msg_dump((spd_msg_t *)polmsg.iov_base, 1282 "message in"); 1283 pfpol_msg_dump(return_buf, 1284 "send_pf_pol_message"); 1285 #endif 1286 retval = return_buf->spd_msg_errno; 1287 free(return_buf); 1288 free(polmsg.iov_base); 1289 (void) close(fd); 1290 return (retval); 1291 } 1292 1293 retval = spdsock_get_ext(exts, return_buf, 1294 return_buf->spd_msg_len, NULL, 0); 1295 /* ignore retval */ 1296 1297 if (exts[SPD_EXT_RULE]) { 1298 conf->ips_policy_index = 1299 ((struct spd_rule *) 1300 exts[SPD_EXT_RULE])->spd_rule_index; 1301 1302 if (add_index(conf->ips_policy_index)) { 1303 free(return_buf); 1304 free(polmsg.iov_base); 1305 (void) close(fd); 1306 return (ENOMEM); 1307 } 1308 } 1309 1310 free(return_buf); 1311 } 1312 } 1313 1314 free(polmsg.iov_base); 1315 (void) close(fd); 1316 1317 return (0); 1318 1319 } 1320 1321 int 1322 main(int argc, char *argv[]) 1323 { 1324 int ret, flushret; 1325 int c; 1326 int index; 1327 boolean_t smf_managed; 1328 boolean_t just_check = B_FALSE; 1329 1330 char *smf_warning = gettext( 1331 "\n\tIPsec policy should be managed using smf(5). Modifying\n" 1332 "\tthe IPsec policy from the command line while the 'policy'\n" 1333 "\tservice is enabled could result in an inconsistent\n" 1334 "\tsecurity policy.\n\n"); 1335 1336 flushret = 0; 1337 1338 (void) setlocale(LC_ALL, ""); 1339 #if !defined(TEXT_DOMAIN) 1340 #define TEXT_DOMAIN "SYS_TEST" 1341 #endif 1342 (void) textdomain(TEXT_DOMAIN); 1343 1344 openlog("ipsecconf", LOG_CONS, LOG_AUTH); 1345 1346 /* 1347 * We don't immediately check for privilege here. This is done by IP 1348 * when we open /dev/ip below. 1349 */ 1350 1351 if (argc == 1) { 1352 cmd = IPSEC_CONF_VIEW; 1353 goto done; 1354 } 1355 my_fmri = getenv("SMF_FMRI"); 1356 if (my_fmri == NULL) 1357 smf_managed = B_FALSE; 1358 else 1359 smf_managed = B_TRUE; 1360 1361 while ((c = getopt(argc, argv, "nlfLFa:qd:r:i:c:")) != EOF) { 1362 switch (c) { 1363 case 'F': 1364 if (interface_name != NULL) { 1365 USAGE(); 1366 EXIT_FATAL("interface name not required."); 1367 } 1368 /* Apply to all policy heads - global and tunnels. */ 1369 interface_name = &all_polheads; 1370 /* FALLTHRU */ 1371 case 'f': 1372 /* Only one command at a time */ 1373 if (cmd != 0) { 1374 USAGE(); 1375 EXIT_FATAL("Multiple commands specified"); 1376 } 1377 cmd = IPSEC_CONF_FLUSH; 1378 break; 1379 case 'L': 1380 if (interface_name != NULL) { 1381 USAGE(); 1382 EXIT_FATAL("interface name not required."); 1383 } 1384 /* Apply to all policy heads - global and tunnels. */ 1385 interface_name = &all_polheads; 1386 /* FALLTHRU */ 1387 case 'l': 1388 /* Only one command at a time */ 1389 if (cmd != 0) { 1390 USAGE(); 1391 EXIT_FATAL("Multiple commands specified"); 1392 } 1393 cmd = IPSEC_CONF_LIST; 1394 break; 1395 case 'c': 1396 just_check = B_TRUE; 1397 ipsecconf_qflag++; 1398 /* FALLTHRU */ 1399 case 'a': 1400 /* Only one command at a time, and no interface name */ 1401 if (cmd != 0 || interface_name != NULL) { 1402 USAGE(); 1403 EXIT_FATAL("Multiple commands or interface " 1404 "not required."); 1405 } 1406 cmd = IPSEC_CONF_ADD; 1407 filename = optarg; 1408 break; 1409 case 'd': 1410 /* 1411 * Only one command at a time. Interface name is 1412 * optional. 1413 */ 1414 if (cmd != 0) { 1415 USAGE(); 1416 EXIT_FATAL("Multiple commands specified"); 1417 } 1418 cmd = IPSEC_CONF_DEL; 1419 index = parse_index(optarg, NULL); 1420 break; 1421 case 'n' : 1422 ipsecconf_nflag++; 1423 break; 1424 case 'q' : 1425 ipsecconf_qflag++; 1426 break; 1427 case 'r' : 1428 /* Only one command at a time, and no interface name */ 1429 if (cmd != 0 || interface_name != NULL) { 1430 USAGE(); 1431 EXIT_FATAL("Multiple commands or interface " 1432 "not required."); 1433 } 1434 cmd = IPSEC_CONF_SUB; 1435 filename = optarg; 1436 break; 1437 case 'i': 1438 if (interface_name != NULL) { 1439 EXIT_FATAL("Interface name already selected"); 1440 } 1441 interface_name = optarg; 1442 /* Check for some cretin using the all-polheads name. */ 1443 if (strlen(optarg) == 0) { 1444 USAGE(); 1445 EXIT_FATAL("Invalid interface name."); 1446 } 1447 break; 1448 default : 1449 USAGE(); 1450 EXIT_FATAL("Bad usage."); 1451 } 1452 } 1453 1454 done: 1455 ret = 0; 1456 lfd = lock(); 1457 1458 /* 1459 * ADD, FLUSH, DELETE needs to do two operations. 1460 * 1461 * 1) Update/delete/empty the POLICY_CONF_FILE. 1462 * 2) Make an ioctl and tell IP to update its state. 1463 * 1464 * We already lock()ed so that only one instance of this 1465 * program runs. We also need to make sure that the above 1466 * operations are atomic i.e we don't want to update the file 1467 * and get interrupted before we could tell IP. To make it 1468 * atomic we block all the signals and restore them. 1469 */ 1470 switch (cmd) { 1471 case IPSEC_CONF_LIST: 1472 fetch_algorithms(); 1473 ret = ipsec_conf_list(); 1474 break; 1475 case IPSEC_CONF_FLUSH: 1476 if ((ret = block_all_signals()) == -1) { 1477 break; 1478 } 1479 if (!smf_managed && !ipsecconf_qflag) 1480 (void) fprintf(stdout, "%s", smf_warning); 1481 ret = ipsec_conf_flush(SPD_ACTIVE); 1482 (void) restore_all_signals(); 1483 break; 1484 case IPSEC_CONF_VIEW: 1485 if (interface_name != NULL) { 1486 EXIT_FATAL("Cannot view for one interface only."); 1487 } 1488 ret = ipsec_conf_view(); 1489 break; 1490 case IPSEC_CONF_DEL: 1491 if (index == -1) { 1492 warnx(gettext("Invalid index")); 1493 ret = -1; 1494 break; 1495 } 1496 if ((ret = block_all_signals()) == -1) { 1497 break; 1498 } 1499 if (!smf_managed && !ipsecconf_qflag) 1500 (void) fprintf(stdout, "%s", smf_warning); 1501 ret = ipsec_conf_del(index, B_FALSE); 1502 (void) restore_all_signals(); 1503 flushret = ipsec_conf_flush(SPD_STANDBY); 1504 break; 1505 case IPSEC_CONF_ADD: 1506 /* 1507 * The IPsec kernel modules should only be loaded 1508 * if there is a policy to install, for this 1509 * reason ipsec_conf_add() calls fetch_algorithms() 1510 * and ipsec_conf_flush() only when appropriate. 1511 */ 1512 if ((ret = block_all_signals()) == -1) { 1513 break; 1514 } 1515 if (!smf_managed && !ipsecconf_qflag) 1516 (void) fprintf(stdout, "%s", smf_warning); 1517 ret = ipsec_conf_add(just_check, smf_managed); 1518 (void) restore_all_signals(); 1519 break; 1520 case IPSEC_CONF_SUB: 1521 fetch_algorithms(); 1522 if ((ret = block_all_signals()) == -1) { 1523 break; 1524 } 1525 if (!smf_managed && !ipsecconf_qflag) 1526 (void) fprintf(stdout, "%s", smf_warning); 1527 ret = ipsec_conf_sub(); 1528 (void) restore_all_signals(); 1529 flushret = ipsec_conf_flush(SPD_STANDBY); 1530 break; 1531 default : 1532 /* If no argument is given but a "-" */ 1533 USAGE(); 1534 EXIT_FATAL("Bad usage."); 1535 } 1536 1537 (void) unlock(lfd); 1538 if (ret != 0 || flushret != 0) 1539 ret = 1; 1540 return (ret); 1541 } 1542 1543 static void 1544 perm_check(void) 1545 { 1546 if (errno == EACCES) 1547 EXIT_BADPERM("Insufficient privilege to run ipsecconf."); 1548 else 1549 warn(gettext("Cannot open lock file %s"), LOCK_FILE); 1550 1551 EXIT_BADPERM(NULL); 1552 } 1553 1554 static int 1555 lock() 1556 { 1557 int fd; 1558 struct stat sbuf1; 1559 struct stat sbuf2; 1560 1561 /* 1562 * Open the file with O_CREAT|O_EXCL. If it exists already, it 1563 * will fail. If it already exists, check whether it looks like 1564 * the one we created. 1565 */ 1566 (void) umask(0077); 1567 if ((fd = open(LOCK_FILE, O_EXCL|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) 1568 == -1) { 1569 if (errno != EEXIST) { 1570 /* Some other problem. Will exit. */ 1571 perm_check(); 1572 } 1573 1574 /* 1575 * open() returned an EEXIST error. We don't fail yet 1576 * as it could be a residual from a previous 1577 * execution. 1578 * File exists. make sure it is OK. We need to lstat() 1579 * as fstat() stats the file pointed to by the symbolic 1580 * link. 1581 */ 1582 if (lstat(LOCK_FILE, &sbuf1) == -1) { 1583 EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE); 1584 } 1585 /* 1586 * Check whether it is a regular file and not a symbolic 1587 * link. Its link count should be 1. The owner should be 1588 * root and the file should be empty. 1589 */ 1590 if (!S_ISREG(sbuf1.st_mode) || 1591 sbuf1.st_nlink != 1 || 1592 sbuf1.st_uid != 0 || 1593 sbuf1.st_size != 0) { 1594 EXIT_FATAL2("Bad lock file %s", LOCK_FILE); 1595 } 1596 if ((fd = open(LOCK_FILE, O_CREAT|O_RDWR, 1597 S_IRUSR|S_IWUSR)) == -1) { 1598 /* Will exit */ 1599 perm_check(); 1600 } 1601 /* 1602 * Check whether we opened the file that we lstat()ed. 1603 */ 1604 if (fstat(fd, &sbuf2) == -1) { 1605 EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE); 1606 } 1607 if (sbuf1.st_dev != sbuf2.st_dev || 1608 sbuf1.st_ino != sbuf2.st_ino) { 1609 /* File changed after we did the lstat() above */ 1610 EXIT_FATAL2("Bad lock file %s", LOCK_FILE); 1611 } 1612 } 1613 if (lockf(fd, F_LOCK, 0) == -1) { 1614 EXIT_FATAL2("Cannot lockf %s", LOCK_FILE); 1615 } 1616 return (fd); 1617 } 1618 1619 static int 1620 unlock(int fd) 1621 { 1622 if (lockf(fd, F_ULOCK, 0) == -1) { 1623 warn("lockf"); 1624 return (-1); 1625 } 1626 return (0); 1627 } 1628 1629 /* send in TOK_* */ 1630 static void 1631 print_pattern_string(int type) 1632 { 1633 int j; 1634 1635 for (j = 0; pattern_table[j].string != NULL; j++) { 1636 if (type == pattern_table[j].tok_val) { 1637 (void) printf("%s ", pattern_table[j].string); 1638 return; 1639 } 1640 } 1641 } 1642 1643 static void 1644 print_icmp_typecode(uint8_t type, uint8_t type_end, uint8_t code, 1645 uint8_t code_end) 1646 { 1647 (void) printf("type %d", type); 1648 if (type_end != type) 1649 (void) printf("-%d ", type_end); 1650 else 1651 (void) printf(" "); 1652 if (code != 255) { 1653 (void) printf("code %d", code); 1654 if (code_end != code) 1655 (void) printf("-%d ", code_end); 1656 else 1657 (void) printf(" "); 1658 } 1659 } 1660 1661 1662 static void 1663 print_spd_flags(uint32_t flags) 1664 { 1665 flags &= (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND); 1666 1667 if (flags == SPD_RULE_FLAG_OUTBOUND) 1668 (void) printf("dir out "); 1669 else if (flags == SPD_RULE_FLAG_INBOUND) 1670 (void) printf("dir in "); 1671 else if (flags == (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND)) 1672 (void) printf("dir both "); 1673 } 1674 1675 static void 1676 print_bit_range(int min, int max) 1677 { 1678 if (min != 0 || (max != 0 && max != SPD_MAX_MAXBITS)) { 1679 (void) printf("("); 1680 if (min != 0) 1681 (void) printf("%d", min); 1682 if (min != 0 && max != 0 && min != max) { 1683 (void) printf(".."); 1684 if (max != 0 && max != SPD_MAX_MAXBITS) 1685 (void) printf("%d", max); 1686 } 1687 (void) printf(")"); 1688 } 1689 } 1690 1691 static void 1692 print_alg(const char *tag, algreq_t *algreq, int proto_num) 1693 { 1694 int min = algreq->alg_minbits; 1695 int max = algreq->alg_maxbits; 1696 struct ipsecalgent *alg; 1697 1698 /* 1699 * This function won't be called with alg_id == 0, so we don't 1700 * have to worry about ANY vs. NONE here. 1701 */ 1702 1703 (void) printf("%s ", tag); 1704 1705 alg = getipsecalgbynum(algreq->alg_id, proto_num, NULL); 1706 if (alg == NULL) { 1707 (void) printf("%d", algreq->alg_id); 1708 } else { 1709 (void) printf("%s", alg->a_names[0]); 1710 freeipsecalgent(alg); 1711 } 1712 1713 print_bit_range(min, max); 1714 (void) printf(" "); 1715 } 1716 1717 static void 1718 print_ulp(uint8_t proto) 1719 { 1720 struct protoent *pe; 1721 1722 if (proto == 0) 1723 return; 1724 1725 print_pattern_string(TOK_ulp); 1726 pe = NULL; 1727 if (!ipsecconf_nflag) { 1728 pe = getprotobynumber(proto); 1729 } 1730 if (pe != NULL) 1731 (void) printf("%s ", pe->p_name); 1732 else 1733 (void) printf("%d ", proto); 1734 } 1735 1736 /* needs to do ranges */ 1737 static void 1738 print_port(uint16_t in_port, int type) 1739 { 1740 in_port_t port = ntohs(in_port); 1741 struct servent *sp; 1742 1743 if (port == 0) 1744 return; 1745 1746 print_pattern_string(type); 1747 sp = NULL; 1748 if (!ipsecconf_nflag) 1749 sp = getservbyport(port, NULL); 1750 1751 if (sp != NULL) 1752 (void) printf("%s ", sp->s_name); 1753 else 1754 (void) printf("%d ", port); 1755 } 1756 1757 /* 1758 * Print the address, given as "raw" input via the void pointer. 1759 */ 1760 static void 1761 print_raw_address(void *input, boolean_t isv4) 1762 { 1763 char *cp; 1764 struct hostent *hp; 1765 char domain[MAXHOSTNAMELEN + 1]; 1766 struct in_addr addr; 1767 struct in6_addr addr6; 1768 char abuf[INET6_ADDRSTRLEN]; 1769 int error_num; 1770 struct in6_addr in_addr; 1771 uchar_t *addr_ptr; 1772 sa_family_t af; 1773 int addr_len; 1774 1775 if (isv4) { 1776 af = AF_INET; 1777 (void) memcpy(&V4_PART_OF_V6(in_addr), input, 4); 1778 /* we don't print unspecified addresses */ 1779 IN6_V4MAPPED_TO_INADDR(&in_addr, &addr); 1780 if (addr.s_addr == INADDR_ANY) 1781 return; 1782 addr_ptr = (uchar_t *)&addr.s_addr; 1783 addr_len = IPV4_ADDR_LEN; 1784 } else { 1785 (void) memcpy(&addr6, input, 16); 1786 af = AF_INET6; 1787 /* we don't print unspecified addresses */ 1788 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) 1789 return; 1790 addr_ptr = (uchar_t *)&addr6.s6_addr; 1791 addr_len = sizeof (struct in6_addr); 1792 } 1793 1794 cp = NULL; 1795 if (!ipsecconf_nflag) { 1796 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 && 1797 (cp = strchr(domain, '.')) != NULL) { 1798 (void) strlcpy(domain, cp + 1, sizeof (domain)); 1799 } else { 1800 domain[0] = 0; 1801 } 1802 cp = NULL; 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 } else { 3117 (void) fprintf(policy_fp, "\n\n"); 3118 (void) fflush(policy_fp); 3119 } 3120 3121 while (temp != NULL) { 3122 (void) ipsec_conf_del(temp->index, B_TRUE); 3123 temp = temp->next; 3124 } 3125 } 3126 3127 /* 3128 * Set mask info from the specified prefix len. Fail if multihomed. 3129 */ 3130 static int 3131 set_mask_info(struct hostent *hp, unsigned int plen, struct in6_addr *mask_v6) 3132 { 3133 struct in6_addr addr; 3134 struct in_addr mask_v4; 3135 3136 if (hp->h_addr_list[1] != NULL) { 3137 return (EOPNOTSUPP); 3138 } 3139 3140 if (!IN6_IS_ADDR_UNSPECIFIED(mask_v6)) { 3141 return (EBUSY); 3142 } 3143 3144 bcopy(hp->h_addr_list[0], &addr, sizeof (struct in6_addr)); 3145 if (IN6_IS_ADDR_V4MAPPED(&addr)) { 3146 if (plen > IP_ABITS) { 3147 return (ERANGE); 3148 } 3149 (void) memset(&mask_v4, 0, sizeof (mask_v4)); 3150 in_prefixlentomask(plen, (uchar_t *)&mask_v4); 3151 IN6_INADDR_TO_V4MAPPED(&mask_v4, mask_v6); 3152 } else { 3153 if (plen > IPV6_ABITS) { 3154 return (ERANGE); 3155 } 3156 /* mask_v6 is already zero (unspecified), see test above */ 3157 in_prefixlentomask(plen, (uchar_t *)mask_v6); 3158 } 3159 return (0); 3160 } 3161 3162 /* 3163 * Initialize the specified IPv6 address with all f's. 3164 */ 3165 static void 3166 init_addr_wildcard(struct in6_addr *addr_v6, boolean_t isv4) 3167 { 3168 if (isv4) { 3169 uint32_t addr_v4 = 0xffffffff; 3170 IN6_INADDR_TO_V4MAPPED((struct in_addr *)&addr_v4, addr_v6); 3171 } else { 3172 (void) memset(addr_v6, 0xff, sizeof (struct in6_addr)); 3173 } 3174 } 3175 3176 /* 3177 * Called at the end to actually add policy. Handles single and multi-homed 3178 * cases. 3179 */ 3180 static int 3181 do_address_adds(ips_conf_t *cptr, int *diag) 3182 { 3183 int i, j; 3184 int ret = 0; /* For ioctl() call. */ 3185 int rc = 0; /* My own return code. */ 3186 struct in6_addr zeroes = {0, 0, 0, 0}; 3187 char *ptr[2]; 3188 struct hostent hent; 3189 boolean_t isv4; 3190 int add_count = 0; 3191 3192 /* 3193 * dst_hent may not be initialized if a destination 3194 * address was not given. It will be initalized with just 3195 * one address if a destination address was given. In both 3196 * the cases, we initialize here with ipsc_dst_addr and enter 3197 * the loop below. 3198 */ 3199 if (dhp == NULL) { 3200 assert(shp != NULL); 3201 hent.h_addr_list = ptr; 3202 ptr[0] = (char *)&zeroes.s6_addr; 3203 ptr[1] = NULL; 3204 dhp = &hent; 3205 } else if (shp == NULL) { 3206 assert(dhp != NULL); 3207 hent.h_addr_list = ptr; 3208 ptr[0] = (char *)&zeroes.s6_addr; 3209 ptr[1] = NULL; 3210 shp = &hent; 3211 } 3212 3213 /* 3214 * Set mask info here. Bail if multihomed and there's a prefix len. 3215 */ 3216 if (has_saprefix) { 3217 rc = set_mask_info(shp, splen, &cptr->ips_src_mask_v6); 3218 if (rc != 0) 3219 goto bail; 3220 cptr->ips_src_mask_len = splen; 3221 } 3222 3223 if (has_daprefix) { 3224 rc = set_mask_info(dhp, dplen, &cptr->ips_dst_mask_v6); 3225 if (rc != 0) 3226 goto bail; 3227 cptr->ips_dst_mask_len = dplen; 3228 } 3229 3230 for (i = 0; shp->h_addr_list[i] != NULL; i++) { 3231 bcopy(shp->h_addr_list[i], &cptr->ips_src_addr_v6, 3232 sizeof (struct in6_addr)); 3233 isv4 = cptr->ips_isv4 = 3234 IN6_IS_ADDR_V4MAPPED(&cptr->ips_src_addr_v6); 3235 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_mask_v6) && 3236 shp != &hent) { 3237 init_addr_wildcard(&cptr->ips_src_mask_v6, isv4); 3238 } 3239 3240 for (j = 0; dhp->h_addr_list[j] != NULL; j++) { 3241 bcopy(dhp->h_addr_list[j], &cptr->ips_dst_addr_v6, 3242 sizeof (struct in6_addr)); 3243 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)) { 3244 /* 3245 * Src was not specified, so update isv4 flag 3246 * for this policy according to the family 3247 * of the destination address. 3248 */ 3249 isv4 = cptr->ips_isv4 = 3250 IN6_IS_ADDR_V4MAPPED( 3251 &cptr->ips_dst_addr_v6); 3252 } else if ((dhp != &hent) && (isv4 != 3253 IN6_IS_ADDR_V4MAPPED(&cptr->ips_dst_addr_v6))) { 3254 /* v6/v4 mismatch. */ 3255 continue; 3256 } 3257 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_mask_v6) && 3258 dhp != &hent) { 3259 init_addr_wildcard(&cptr->ips_dst_mask_v6, 3260 isv4); 3261 } 3262 3263 ret = send_pf_pol_message(SPD_ADDRULE, cptr, diag); 3264 3265 if (ret == 0) { 3266 add_count++; 3267 } else { 3268 /* For now, allow duplicate/overlap policies. */ 3269 if (ret != EEXIST) { 3270 /* 3271 * We have an error where we added 3272 * some, but had errors with others. 3273 * Undo the previous adds, and 3274 * bail. 3275 */ 3276 rc = ret; 3277 goto bail; 3278 } 3279 } 3280 3281 bzero(&cptr->ips_dst_mask_v6, 3282 sizeof (struct in6_addr)); 3283 } 3284 3285 bzero(&cptr->ips_src_mask_v6, sizeof (struct in6_addr)); 3286 } 3287 3288 bail: 3289 if (shp != &hent) 3290 freehostent(shp); 3291 shp = NULL; 3292 if (dhp != &hent) 3293 freehostent(dhp); 3294 dhp = NULL; 3295 splen = 0; 3296 dplen = 0; 3297 3298 if ((add_count == 0) && (rc == 0)) { 3299 /* 3300 * No entries were added. We failed all adds 3301 * because the entries already existed, or because 3302 * no v4 or v6 src/dst pairs were found. Either way, 3303 * we must fail here with an appropriate error 3304 * to avoid a corresponding entry from being added 3305 * to ipsecpolicy.conf. 3306 */ 3307 if ((ret == EEXIST)) { 3308 /* All adds failed with EEXIST */ 3309 rc = EEXIST; 3310 } else { 3311 /* No matching v4 or v6 src/dst pairs */ 3312 rc = ESRCH; 3313 } 3314 } 3315 3316 return (rc); 3317 } 3318 3319 static int 3320 parse_mask(int type, char *mask_str, ips_conf_t *cptr) 3321 { 3322 struct in_addr mask; 3323 struct in6_addr *mask6; 3324 3325 if (type == IPSEC_CONF_SRC_MASK) { 3326 mask6 = &cptr->ips_src_mask_v6; 3327 } else { 3328 mask6 = &cptr->ips_dst_mask_v6; 3329 } 3330 3331 if ((strncasecmp(mask_str, "0x", 2) == 0) && 3332 (strchr(mask_str, '.') == NULL)) { 3333 /* Is it in the form 0xff000000 ? */ 3334 char *end; 3335 3336 mask.s_addr = strtoul(mask_str, &end, 0); 3337 if (end == mask_str) { 3338 return (-1); 3339 } 3340 if (*end != '\0') { 3341 return (-1); 3342 } 3343 mask.s_addr = htonl(mask.s_addr); 3344 } else { 3345 /* 3346 * Since inet_addr() returns -1 on error, we have 3347 * to convert a broadcast address ourselves. 3348 */ 3349 if (strcmp(mask_str, "255.255.255.255") == 0) { 3350 mask.s_addr = 0xffffffff; 3351 } else { 3352 mask.s_addr = inet_addr(mask_str); 3353 if (mask.s_addr == (unsigned int)-1) 3354 return (-1); 3355 } 3356 } 3357 3358 /* Should we check for non-contiguous masks ? */ 3359 if (mask.s_addr == 0) 3360 return (-1); 3361 IN6_INADDR_TO_V4MAPPED(&mask, mask6); 3362 3363 3364 if (type == IPSEC_CONF_SRC_MASK) { 3365 cptr->ips_src_mask_len = in_masktoprefix(mask6->s6_addr, 3366 B_TRUE); 3367 } else { 3368 cptr->ips_dst_mask_len = in_masktoprefix(mask6->s6_addr, 3369 B_TRUE); 3370 } 3371 3372 return (0); 3373 } 3374 3375 static int 3376 parse_port(int type, char *port_str, ips_conf_t *conf) 3377 { 3378 struct servent *sent; 3379 in_port_t port; 3380 int ret; 3381 3382 sent = getservbyname(port_str, NULL); 3383 if (sent == NULL) { 3384 ret = parse_int(port_str); 3385 if (ret < 0 || ret >= 65536) { 3386 return (-1); 3387 } 3388 port = htons((in_port_t)ret); 3389 } else { 3390 port = sent->s_port; 3391 } 3392 if (type == IPSEC_CONF_SRC_PORT) { 3393 conf->ips_src_port_min = conf->ips_src_port_max = port; 3394 } else { 3395 conf->ips_dst_port_min = conf->ips_dst_port_max = port; 3396 } 3397 return (0); 3398 } 3399 3400 static int 3401 valid_algorithm(int proto_num, const char *str) 3402 { 3403 const char *tmp; 3404 int ret; 3405 struct ipsecalgent *alg; 3406 3407 /* Short-circuit "none" */ 3408 if (strncasecmp("none", str, 5) == 0) 3409 return (-2); 3410 3411 alg = getipsecalgbyname(str, proto_num, NULL); 3412 if (alg != NULL) { 3413 ret = alg->a_alg_num; 3414 freeipsecalgent(alg); 3415 return (ret); 3416 } 3417 3418 /* 3419 * Look whether it could be a valid number. 3420 * We support numbers also so that users can 3421 * load algorithms as they need it. We can't 3422 * check for validity of numbers here. It will 3423 * be checked when the SA is negotiated/looked up. 3424 * parse_int uses strtol(str), which converts 3DES 3425 * to a valid number i.e looks only at initial 3426 * number part. If we come here we should expect 3427 * only a decimal number. 3428 */ 3429 tmp = str; 3430 while (*tmp) { 3431 if (!isdigit(*tmp)) 3432 return (-1); 3433 tmp++; 3434 } 3435 3436 ret = parse_int(str); 3437 if (ret > 0 && ret <= 255) 3438 return (ret); 3439 else 3440 return (-1); 3441 } 3442 3443 static int 3444 parse_ipsec_alg(char *str, ips_act_props_t *iap, int alg_type) 3445 { 3446 int alg_value; 3447 char tstr[VALID_ALG_LEN]; 3448 char *lens = NULL; 3449 char *l1_str; 3450 int l1 = 0; 3451 char *l2_str; 3452 int l2 = SPD_MAX_MAXBITS; 3453 algreq_t *ap; 3454 uint_t a_type; 3455 3456 fetch_algorithms(); 3457 3458 /* 3459 * Make sure that we get a null terminated string. 3460 * For a bad input, we truncate at VALID_ALG_LEN. 3461 */ 3462 (void) strlcpy(tstr, str, VALID_ALG_LEN); 3463 lens = strtok(tstr, "()"); 3464 lens = strtok(NULL, "()"); 3465 3466 if (lens != NULL) { 3467 int len1 = 0; 3468 int len2 = SPD_MAX_MAXBITS; 3469 int len_all = strlen(lens); 3470 int dot_start = (lens[0] == '.'); 3471 l1_str = strtok(lens, "."); 3472 l2_str = strtok(NULL, "."); 3473 if (l1_str != NULL) { 3474 l1 = parse_int(l1_str); 3475 len1 = strlen(l1_str); 3476 if (len1 < 0) 3477 return (1); 3478 } 3479 if (l2_str != NULL) { 3480 l2 = parse_int(l2_str); 3481 len2 = strlen(l2_str); 3482 if (len2 < 0) 3483 return (1); 3484 } 3485 3486 if (len_all == len1) { 3487 /* alg(n) */ 3488 l2 = l1; 3489 } else if (dot_start) { 3490 /* alg(..n) */ 3491 l2 = l1; 3492 l1 = 0; 3493 } else if ((len_all - 2) == len1) { 3494 /* alg(n..) */ 3495 l2 = SPD_MAX_MAXBITS; 3496 } /* else alg(n..m) */ 3497 } 3498 3499 if (alg_type == SPD_ATTR_AH_AUTH || 3500 alg_type == SPD_ATTR_ESP_AUTH) { 3501 alg_value = valid_algorithm(IPSEC_PROTO_AH, tstr); 3502 } else { 3503 alg_value = valid_algorithm(IPSEC_PROTO_ESP, tstr); 3504 } 3505 if (alg_value < 0) { 3506 /* Invalid algorithm or "none" */ 3507 return (alg_value); 3508 } 3509 3510 if (alg_type == SPD_ATTR_AH_AUTH) { 3511 a_type = AH_AUTH; 3512 iap->iap_attr |= SPD_APPLY_AH; 3513 ap = &(iap->iap_aauth); 3514 } else if (alg_type == SPD_ATTR_ESP_AUTH) { 3515 a_type = ESP_AUTH; 3516 iap->iap_attr |= SPD_APPLY_ESP|SPD_APPLY_ESPA; 3517 ap = &(iap->iap_eauth); 3518 } else { 3519 a_type = ESP_ENCR; 3520 iap->iap_attr |= SPD_APPLY_ESP; 3521 ap = &(iap->iap_eencr); 3522 } 3523 3524 ap->alg_id = alg_value; 3525 ap->alg_minbits = l1; 3526 ap->alg_maxbits = l2; 3527 3528 if (!alg_rangecheck(a_type, alg_value, ap)) 3529 return (1); 3530 3531 return (0); 3532 } 3533 3534 static char * 3535 sys_error_message(int syserr) 3536 { 3537 char *mesg; 3538 3539 switch (syserr) { 3540 case EEXIST: 3541 mesg = gettext("Entry already exists"); 3542 break; 3543 case ENOENT: 3544 mesg = gettext("Tunnel not found"); 3545 break; 3546 case EINVAL: 3547 mesg = gettext("Invalid entry"); 3548 break; 3549 default : 3550 mesg = strerror(syserr); 3551 } 3552 return (mesg); 3553 } 3554 3555 static void 3556 error_message(error_type_t error, int type, int line) 3557 { 3558 char *mesg; 3559 3560 switch (type) { 3561 case IPSEC_CONF_SRC_ADDRESS: 3562 mesg = gettext("Source Address"); 3563 break; 3564 case IPSEC_CONF_DST_ADDRESS: 3565 mesg = gettext("Destination Address"); 3566 break; 3567 case IPSEC_CONF_SRC_PORT: 3568 mesg = gettext("Source Port"); 3569 break; 3570 case IPSEC_CONF_DST_PORT: 3571 mesg = gettext("Destination Port"); 3572 break; 3573 case IPSEC_CONF_SRC_MASK: 3574 mesg = gettext("Source Mask"); 3575 break; 3576 case IPSEC_CONF_DST_MASK: 3577 mesg = gettext("Destination Mask"); 3578 break; 3579 case IPSEC_CONF_ULP: 3580 mesg = gettext("Upper Layer Protocol"); 3581 break; 3582 case IPSEC_CONF_IPSEC_AALGS: 3583 mesg = gettext("Authentication Algorithm"); 3584 break; 3585 case IPSEC_CONF_IPSEC_EALGS: 3586 mesg = gettext("Encryption Algorithm"); 3587 break; 3588 case IPSEC_CONF_IPSEC_EAALGS: 3589 mesg = gettext("ESP Authentication Algorithm"); 3590 break; 3591 case IPSEC_CONF_IPSEC_SA: 3592 mesg = gettext("SA"); 3593 break; 3594 case IPSEC_CONF_IPSEC_DIR: 3595 mesg = gettext("Direction"); 3596 break; 3597 case IPSEC_CONF_ICMP_TYPE: 3598 mesg = gettext("ICMP type"); 3599 break; 3600 case IPSEC_CONF_ICMP_CODE: 3601 mesg = gettext("ICMP code"); 3602 break; 3603 case IPSEC_CONF_NEGOTIATE: 3604 mesg = gettext("Negotiate"); 3605 break; 3606 case IPSEC_CONF_TUNNEL: 3607 mesg = gettext("Tunnel"); 3608 break; 3609 default : 3610 return; 3611 } 3612 /* 3613 * If we never read a newline character, we don't want 3614 * to print 0. 3615 */ 3616 warnx(gettext("%s%s%s %s on line: %d"), 3617 (error == BAD_ERROR) ? gettext("Bad") : "", 3618 (error == DUP_ERROR) ? gettext("Duplicate") : "", 3619 (error == REQ_ERROR) ? gettext("Requires") : "", 3620 mesg, 3621 (arg_indices[line] == 0) ? 1 : arg_indices[line]); 3622 } 3623 3624 static int 3625 validate_properties(ips_act_props_t *cptr, boolean_t dir, boolean_t is_alg) 3626 { 3627 if (cptr->iap_action == SPD_ACTTYPE_PASS || 3628 cptr->iap_action == SPD_ACTTYPE_DROP) { 3629 if (!dir) { 3630 warnx(gettext("dir string " 3631 "not found for bypass policy")); 3632 } 3633 3634 if (is_alg) { 3635 warnx(gettext("Algorithms found for bypass policy")); 3636 return (-1); 3637 } 3638 return (0); 3639 } 3640 if (!is_alg) { 3641 warnx(gettext("No IPsec algorithms given")); 3642 return (-1); 3643 } 3644 if (cptr->iap_attr == 0) { 3645 warnx(gettext("No SA attribute")); 3646 return (-1); 3647 } 3648 return (0); 3649 } 3650 3651 /* 3652 * This function is called only to parse a single rule's worth of 3653 * action strings. This is called after parsing pattern and before 3654 * parsing properties. Thus we may have something in the leftover 3655 * buffer while parsing the pattern, which we need to handle here. 3656 */ 3657 static int 3658 parse_action(FILE *fp, char **action, char **leftover) 3659 { 3660 char *cp; 3661 char ibuf[MAXLEN]; 3662 char *tmp_buf; 3663 char *buf; 3664 boolean_t new_stuff; 3665 3666 if (*leftover != NULL) { 3667 buf = *leftover; 3668 new_stuff = B_FALSE; 3669 goto scan; 3670 } 3671 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3672 new_stuff = B_TRUE; 3673 if (ibuf[strlen(ibuf) - 1] == '\n') 3674 linecount++; 3675 buf = ibuf; 3676 scan: 3677 /* Truncate at the beginning of a comment */ 3678 cp = strchr(buf, '#'); 3679 if (cp != NULL) 3680 *cp = NULL; 3681 3682 /* Skip any whitespace */ 3683 while (*buf != NULL && isspace(*buf)) 3684 buf++; 3685 3686 /* Empty line */ 3687 if (*buf == NULL) 3688 continue; 3689 3690 /* 3691 * Store the command for error reporting 3692 * and ipsec_conf_add(). 3693 */ 3694 if (new_stuff) { 3695 /* 3696 * Check for buffer overflow including the null 3697 * terminating character. 3698 */ 3699 int len = strlen(ibuf); 3700 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3701 return (-1); 3702 3703 (void) strcpy(cbuf + cbuf_offset, ibuf); 3704 cbuf_offset += len; 3705 } 3706 /* 3707 * Start of the non-empty non-space character. 3708 */ 3709 tmp_buf = buf; 3710 3711 /* Skip until next whitespace or CURL_BEGIN */ 3712 while (*buf != NULL && !isspace(*buf) && 3713 *buf != CURL_BEGIN) 3714 buf++; 3715 3716 if (*buf != NULL) { 3717 if (tmp_buf == buf) /* No action token */ 3718 goto error; 3719 if (*buf == CURL_BEGIN) { 3720 *buf = NULL; 3721 /* Allocate an extra byte for the null also */ 3722 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3723 NULL) { 3724 warn("malloc"); 3725 return (ENOMEM); 3726 } 3727 (void) strcpy(*action, tmp_buf); 3728 *buf = CURL_BEGIN; 3729 } else { 3730 /* We have hit a space */ 3731 *buf++ = NULL; 3732 /* Allocate an extra byte for the null also */ 3733 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3734 NULL) { 3735 warn("malloc"); 3736 return (ENOMEM); 3737 } 3738 (void) strcpy(*action, tmp_buf); 3739 } 3740 /* 3741 * Copy the rest of the line into the 3742 * leftover buffer. 3743 */ 3744 if (*buf != NULL) { 3745 (void) strlcpy(lo_buf, buf, sizeof (lo_buf)); 3746 *leftover = lo_buf; 3747 } else { 3748 *leftover = NULL; 3749 } 3750 } else { 3751 /* Allocate an extra byte for the null also */ 3752 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3753 NULL) { 3754 warn("malloc"); 3755 return (ENOMEM); 3756 } 3757 (void) strcpy(*action, tmp_buf); 3758 *leftover = NULL; 3759 } 3760 if (argindex >= ARG_BUF_LEN) { 3761 warnx(gettext("(parsing one command) " 3762 "Too many selectors before action.")); 3763 return (-1); 3764 } 3765 arg_indices[argindex++] = linecount; 3766 return (PARSE_SUCCESS); 3767 } 3768 /* 3769 * Return error, on an empty action field. 3770 */ 3771 error: 3772 warnx(gettext("(parsing one command) " 3773 "Missing action token.")); 3774 return (-1); 3775 } 3776 3777 /* 3778 * This is called to parse pattern or properties that is enclosed 3779 * between CURL_BEGIN and CURL_END. 3780 */ 3781 static int 3782 parse_pattern_or_prop(FILE *fp, char *argvec[], char **leftover) 3783 { 3784 char *cp; 3785 int i = 0; 3786 boolean_t curl_begin_seen = B_FALSE; 3787 char ibuf[MAXLEN]; 3788 char *tmp_buf; 3789 char *buf; 3790 boolean_t new_stuff; 3791 3792 /* 3793 * When parsing properties, leftover buffer could have the 3794 * leftovers of the previous fgets(). 3795 */ 3796 if (*leftover != NULL) { 3797 buf = *leftover; 3798 new_stuff = B_FALSE; 3799 goto scan; 3800 } 3801 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3802 new_stuff = B_TRUE; 3803 #ifdef DEBUG_HEAVY 3804 (void) printf("%s\n", ibuf); 3805 #endif 3806 if (ibuf[strlen(ibuf) - 1] == '\n') 3807 linecount++; 3808 buf = ibuf; 3809 scan: 3810 /* Truncate at the beginning of a comment */ 3811 cp = strchr(buf, '#'); 3812 if (cp != NULL) 3813 *cp = NULL; 3814 3815 /* Skip any whitespace */ 3816 while (*buf != NULL && isspace(*buf)) 3817 buf++; 3818 3819 /* Empty line */ 3820 if (*buf == NULL) 3821 continue; 3822 /* 3823 * Store the command for error reporting 3824 * and ipsec_conf_add(). 3825 */ 3826 if (new_stuff) { 3827 /* 3828 * Check for buffer overflow including the null 3829 * terminating character. 3830 */ 3831 int len = strlen(ibuf); 3832 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3833 return (-1); 3834 (void) strcpy(cbuf + cbuf_offset, ibuf); 3835 cbuf_offset += len; 3836 } 3837 /* 3838 * First non-space character should be 3839 * a curly bracket. 3840 */ 3841 if (!curl_begin_seen) { 3842 if (*buf != CURL_BEGIN) { 3843 /* 3844 * If we never read a newline character, 3845 * we don't want to print 0. 3846 */ 3847 warnx(gettext("line %d : pattern must start " 3848 "with \"%c\" character"), 3849 (linecount == 0) ? 1 : linecount, 3850 CURL_BEGIN); 3851 return (-1); 3852 } 3853 buf++; 3854 curl_begin_seen = B_TRUE; 3855 } 3856 /* 3857 * Arguments are separated by white spaces or 3858 * newlines. Scan till you see a CURL_END. 3859 */ 3860 while (*buf != NULL) { 3861 if (*buf == CURL_END) { 3862 ret: 3863 *buf++ = NULL; 3864 /* 3865 * Copy the rest of the line into the 3866 * leftover buffer if any. 3867 */ 3868 if (*buf != NULL) { 3869 (void) strlcpy(lo_buf, buf, 3870 sizeof (lo_buf)); 3871 *leftover = lo_buf; 3872 } else { 3873 *leftover = NULL; 3874 } 3875 return (PARSE_SUCCESS); 3876 } 3877 /* 3878 * Skip any trailing whitespace until we see a 3879 * non white-space character. 3880 */ 3881 while (*buf != NULL && isspace(*buf)) 3882 buf++; 3883 3884 if (*buf == CURL_END) 3885 goto ret; 3886 3887 /* Scan the next line as this buffer is empty */ 3888 if (*buf == NULL) 3889 break; 3890 3891 if (i >= MAXARGS) { 3892 warnx( 3893 gettext("Number of Arguments exceeded %d"), 3894 i); 3895 return (-1); 3896 } 3897 /* 3898 * Non-empty, Non-space buffer. 3899 */ 3900 tmp_buf = buf++; 3901 /* 3902 * Real scan of the argument takes place here. 3903 * Skip past till space or CURL_END. 3904 */ 3905 while (*buf != NULL && !isspace(*buf) && 3906 *buf != CURL_END) { 3907 buf++; 3908 } 3909 /* 3910 * Either a space or we have hit the CURL_END or 3911 * the real end. 3912 */ 3913 if (*buf != NULL) { 3914 if (*buf == CURL_END) { 3915 *buf++ = NULL; 3916 if ((argvec[i] = malloc(strlen(tmp_buf) 3917 + 1)) == NULL) { 3918 warn("malloc"); 3919 return (ENOMEM); 3920 } 3921 if (strlen(tmp_buf) != 0) { 3922 (void) strcpy(argvec[i], 3923 tmp_buf); 3924 if (argindex >= ARG_BUF_LEN) 3925 goto toomanyargs; 3926 arg_indices[argindex++] = 3927 linecount; 3928 } 3929 /* 3930 * Copy the rest of the line into the 3931 * leftover buffer. 3932 */ 3933 if (*buf != NULL) { 3934 (void) strlcpy(lo_buf, buf, 3935 sizeof (lo_buf)); 3936 *leftover = lo_buf; 3937 } else { 3938 *leftover = NULL; 3939 } 3940 return (PARSE_SUCCESS); 3941 } else { 3942 *buf++ = NULL; 3943 } 3944 } 3945 /* 3946 * Copy this argument and scan for the buffer more 3947 * if it is non-empty. If it is empty scan for 3948 * the next line. 3949 */ 3950 if ((argvec[i] = malloc(strlen(tmp_buf) + 1)) == 3951 NULL) { 3952 warn("malloc"); 3953 return (ENOMEM); 3954 } 3955 (void) strcpy(argvec[i++], tmp_buf); 3956 if (argindex >= ARG_BUF_LEN) { 3957 /* 3958 * The number of tokens in a single policy entry 3959 * exceeds the number of buffers available to fully 3960 * parse the policy entry. 3961 */ 3962 toomanyargs: 3963 warnx(gettext("(parsing one command) " 3964 "Too many tokens in single policy entry.")); 3965 return (-1); 3966 } 3967 arg_indices[argindex++] = linecount; 3968 } 3969 } 3970 /* 3971 * If nothing is given in the file, it is okay. 3972 * If something is given in the file and it is 3973 * not CURL_BEGIN, we would have returned error 3974 * above. If curl_begin_seen and we are here, 3975 * something is wrong. 3976 */ 3977 if (curl_begin_seen) { 3978 warnx(gettext("(parsing one command) " 3979 "Pattern or Properties incomplete.")); 3980 return (-1); 3981 } 3982 return (PARSE_EOF); /* Nothing more in the file */ 3983 } 3984 3985 /* 3986 * Parse one command i.e {pattern} action {properties}. 3987 * 3988 * {pattern} ( action {prop} | pass | drop ) (or ...)* 3989 */ 3990 static int 3991 parse_one(FILE *fp, act_prop_t *act_props) 3992 { 3993 char *leftover; 3994 int ret; 3995 int i; 3996 int ap_num = 0; 3997 enum parse_state {pattern, action, prop } pstate; 3998 3999 has_daprefix = has_saprefix = B_FALSE; 4000 4001 (void) memset(act_props, 0, sizeof (act_prop_t)); 4002 pstate = pattern; 4003 4004 ret = 0; 4005 leftover = NULL; 4006 argindex = 0; 4007 cbuf_offset = 0; 4008 assert(shp == NULL && dhp == NULL); 4009 4010 for (;;) { 4011 switch (pstate) { 4012 case pattern: 4013 { 4014 #ifdef DEBUG_HEAVY 4015 (void) printf("pattern\n"); 4016 #endif 4017 ret = parse_pattern_or_prop(fp, 4018 act_props->pattern, &leftover); 4019 if (ret == PARSE_EOF) { 4020 /* EOF reached */ 4021 return (PARSE_EOF); 4022 } 4023 if (ret != 0) { 4024 ret = -1; 4025 goto err; 4026 } 4027 pstate = action; 4028 break; 4029 } 4030 case action: 4031 { 4032 #ifdef DEBUG_HEAVY 4033 (void) printf("action\n"); 4034 #endif 4035 ret = parse_action(fp, 4036 &act_props->ap[ap_num].act, &leftover); 4037 if (ret != 0) { 4038 ret = -1; 4039 goto err; 4040 } 4041 4042 /* 4043 * Validate action now itself so that we don't 4044 * proceed too much into the bad world. 4045 */ 4046 for (i = 0; action_table[i].string; i++) { 4047 if (strcmp(act_props->ap[ap_num].act, 4048 action_table[i].string) == 0) 4049 break; 4050 } 4051 4052 if (action_table[i].tok_val == TOK_or) { 4053 /* hit an or, go again */ 4054 break; 4055 } 4056 4057 if (action_table[i].string == NULL) { 4058 /* 4059 * If we never read a newline 4060 * character, we don't want 4061 * to print 0. 4062 */ 4063 warnx(gettext("(parsing one command) " 4064 "Invalid action on line %d: %s"), 4065 (linecount == 0) ? 1 : linecount, 4066 act_props->ap[ap_num].act); 4067 return (-1); 4068 } 4069 4070 pstate = prop; 4071 break; 4072 } 4073 case prop: 4074 { 4075 #ifdef DEBUG_HEAVY 4076 (void) printf("prop\n"); 4077 #endif 4078 ret = parse_pattern_or_prop(fp, 4079 act_props->ap[ap_num].prop, &leftover); 4080 if (ret != 0) { 4081 if (ret == PARSE_EOF) { 4082 warnx(gettext("(parsing one command) " 4083 "Missing properties.")); 4084 } 4085 ret = -1; 4086 goto err; 4087 } 4088 4089 if (leftover != NULL) { 4090 /* Accomodate spaces at the end */ 4091 while (*leftover != NULL) { 4092 if (*leftover == BACK_SLASH) { 4093 warnx(gettext("Invalid line " 4094 "continuation character.")); 4095 ret = -1; 4096 goto err; 4097 } 4098 if (*leftover == 'o') { 4099 leftover++; 4100 if (*leftover == 'r') { 4101 leftover++; 4102 ap_num++; 4103 pstate = action; 4104 goto again; 4105 } 4106 } 4107 if (!isspace(*leftover)) { 4108 ret = -1; 4109 goto err; 4110 } 4111 leftover++; 4112 } 4113 return (0); 4114 } 4115 ap_num++; 4116 if (ap_num > MAXARGS) 4117 return (0); 4118 pstate = action; /* or */ 4119 break; 4120 } /* case prop: */ 4121 } /* switch(pstate) */ 4122 4123 again: 4124 if (ap_num > MAXARGS) { 4125 warnx(gettext("Too many actions.")); 4126 return (-1); 4127 } 4128 } /* for(;;) */ 4129 err: 4130 if (ret != 0) { 4131 /* 4132 * If we never read a newline character, we don't want 4133 * to print 0. 4134 */ 4135 warnx(gettext("Error before or at line %d"), 4136 (linecount == 0) ? 1 : linecount); 4137 } 4138 return (ret); 4139 } 4140 4141 /* 4142 * convert an act_propts_t to an ips_conf_t 4143 */ 4144 4145 static int 4146 form_ipsec_conf(act_prop_t *act_props, ips_conf_t *cptr) 4147 { 4148 int i, j, k; 4149 int tok_count = 0; 4150 struct protoent *pent; 4151 boolean_t saddr, daddr, ipsec_aalg, ipsec_ealg, ipsec_eaalg, dir; 4152 boolean_t old_style, new_style, auth_covered, is_no_alg; 4153 struct in_addr mask; 4154 int line_no; 4155 int ret; 4156 int ap_num = 0; 4157 int type, code, type_end, code_end; 4158 #ifdef DEBUG_HEAVY 4159 /* 4160 * pattern => act_props->pattern 4161 * action => act_props->ap[].act 4162 * properties => act_props->ap[].prop 4163 */ 4164 (void) printf("\npattern\n------------\n"); 4165 for (i = 0; act_props->pattern[i] != NULL; i++) 4166 (void) printf("%s\n", act_props->pattern[i]); 4167 (void) printf("apz\n----------\n"); 4168 for (j = 0; act_props->ap[j].act != NULL; j++) { 4169 4170 (void) printf("act%d->%s\n", j, act_props->ap[j].act); 4171 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 4172 (void) printf("%dprop%d->%s\n", 4173 j, i, act_props->ap[j].prop[i]); 4174 } 4175 (void) printf("------------\n\n"); 4176 #endif 4177 4178 (void) memset(cptr, 0, sizeof (ips_conf_t)); 4179 saddr = daddr = ipsec_aalg = ipsec_ealg = ipsec_eaalg = dir = B_FALSE; 4180 old_style = new_style = is_no_alg = B_FALSE; 4181 /* 4182 * Get the Pattern. NULL pattern is valid. 4183 */ 4184 for (i = 0, line_no = 0; act_props->pattern[i]; i++, line_no++) { 4185 for (j = 0; pattern_table[j].string; j++) { 4186 if (strcmp(act_props->pattern[i], 4187 pattern_table[j].string) == 0) 4188 break; 4189 } 4190 4191 if (pattern_table[j].string == NULL) { 4192 /* 4193 * If we never read a newline character, we don't want 4194 * to print 0. 4195 */ 4196 warnx(gettext("Invalid pattern on line %d: %s"), 4197 (arg_indices[line_no] == 0) ? 1 : 4198 arg_indices[line_no], act_props->pattern[i]); 4199 return (-1); 4200 } 4201 4202 cptr->patt_tok[tok_count++] = pattern_table[j].tok_val; 4203 4204 switch (pattern_table[j].tok_val) { 4205 4206 case TOK_dir: 4207 i++, line_no++; 4208 if (act_props->pattern[i] == NULL) { 4209 error_message(BAD_ERROR, 4210 IPSEC_CONF_IPSEC_DIR, line_no); 4211 return (-1); 4212 } 4213 4214 if (strncmp(act_props->pattern[i], "in", 2) == 0) { 4215 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4216 } else if (strncmp( 4217 act_props->pattern[i], "out", 3) == 0) { 4218 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4219 } else if (strncmp( 4220 act_props->pattern[i], "both", 4) == 0) { 4221 if (old_style) { 4222 error_message(BAD_ERROR, 4223 IPSEC_CONF_IPSEC_DIR, line_no); 4224 return (-1); 4225 } 4226 new_style = B_TRUE; 4227 cptr->ips_dir = 4228 SPD_RULE_FLAG_OUTBOUND | 4229 SPD_RULE_FLAG_INBOUND; 4230 } else { 4231 error_message(BAD_ERROR, 4232 IPSEC_CONF_IPSEC_DIR, line_no); 4233 return (-1); 4234 } 4235 dir = B_TRUE; 4236 break; 4237 4238 case TOK_local: 4239 if (old_style) { 4240 error_message(BAD_ERROR, 4241 IPSEC_CONF_SRC_ADDRESS, line_no); 4242 return (-1); 4243 } 4244 new_style = B_TRUE; 4245 4246 if (saddr) { 4247 error_message(DUP_ERROR, 4248 IPSEC_CONF_SRC_ADDRESS, line_no); 4249 return (-1); 4250 } 4251 /* 4252 * Use this to detect duplicates rather 4253 * than 0 like other cases, because 0 for 4254 * address means INADDR_ANY. 4255 */ 4256 saddr = B_TRUE; 4257 cptr->has_saddr = 1; 4258 /* 4259 * Advance to the string containing 4260 * the address. 4261 */ 4262 i++, line_no++; 4263 if (act_props->pattern[i] == NULL) { 4264 error_message(BAD_ERROR, 4265 IPSEC_CONF_SRC_ADDRESS, line_no); 4266 return (-1); 4267 } 4268 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4269 act_props->pattern[i]) != 0) { 4270 error_message(BAD_ERROR, 4271 IPSEC_CONF_SRC_ADDRESS, line_no); 4272 return (-1); 4273 } 4274 if (!cptr->has_smask) 4275 cptr->has_smask = has_saprefix; 4276 4277 break; 4278 case TOK_remote: 4279 if (old_style) { 4280 error_message(BAD_ERROR, 4281 IPSEC_CONF_DST_ADDRESS, line_no); 4282 return (-1); 4283 } 4284 new_style = B_TRUE; 4285 4286 if (daddr) { 4287 error_message(DUP_ERROR, 4288 IPSEC_CONF_DST_ADDRESS, line_no); 4289 return (-1); 4290 } 4291 /* 4292 * Use this to detect duplicates rather 4293 * than 0 like other cases, because 0 for 4294 * address means INADDR_ANY. 4295 */ 4296 daddr = B_TRUE; 4297 cptr->has_daddr = 1; 4298 /* 4299 * Advance to the string containing 4300 * the address. 4301 */ 4302 i++, line_no++; 4303 if (act_props->pattern[i] == NULL) { 4304 error_message(BAD_ERROR, 4305 IPSEC_CONF_DST_ADDRESS, line_no); 4306 return (-1); 4307 } 4308 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4309 act_props->pattern[i]) != 0) { 4310 error_message(BAD_ERROR, 4311 IPSEC_CONF_DST_ADDRESS, line_no); 4312 return (-1); 4313 } 4314 if (!cptr->has_dmask) 4315 cptr->has_dmask = has_daprefix; 4316 break; 4317 4318 case TOK_saddr: 4319 if (new_style) { 4320 error_message(BAD_ERROR, 4321 IPSEC_CONF_SRC_ADDRESS, line_no); 4322 return (-1); 4323 } 4324 old_style = B_TRUE; 4325 4326 if (saddr) { 4327 error_message(DUP_ERROR, 4328 IPSEC_CONF_SRC_ADDRESS, line_no); 4329 return (-1); 4330 } 4331 /* 4332 * Use this to detect duplicates rather 4333 * than 0 like other cases, because 0 for 4334 * address means INADDR_ANY. 4335 */ 4336 saddr = B_TRUE; 4337 cptr->has_saddr = 1; 4338 /* 4339 * Advance to the string containing 4340 * the address. 4341 */ 4342 i++, line_no++; 4343 if (act_props->pattern[i] == NULL) { 4344 error_message(BAD_ERROR, 4345 IPSEC_CONF_SRC_ADDRESS, line_no); 4346 return (-1); 4347 } 4348 4349 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4350 act_props->pattern[i]) != 0) { 4351 error_message(BAD_ERROR, 4352 IPSEC_CONF_SRC_ADDRESS, line_no); 4353 return (-1); 4354 } 4355 /* shp or bhp? */ 4356 if (!cptr->has_smask) 4357 cptr->has_smask = has_saprefix; 4358 break; 4359 4360 case TOK_daddr: 4361 if (new_style) { 4362 error_message(BAD_ERROR, 4363 IPSEC_CONF_DST_ADDRESS, line_no); 4364 return (-1); 4365 } 4366 old_style = B_TRUE; 4367 4368 if (daddr) { 4369 error_message(DUP_ERROR, 4370 IPSEC_CONF_DST_ADDRESS, line_no); 4371 return (-1); 4372 } 4373 /* 4374 * Use this to detect duplicates rather 4375 * than 0 like other cases, because 0 for 4376 * address means INADDR_ANY. 4377 */ 4378 daddr = B_TRUE; 4379 cptr->has_daddr = 1; 4380 /* 4381 * Advance to the string containing 4382 * the address. 4383 */ 4384 i++, line_no++; 4385 if (act_props->pattern[i] == NULL) { 4386 error_message(BAD_ERROR, 4387 IPSEC_CONF_DST_ADDRESS, line_no); 4388 return (-1); 4389 } 4390 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4391 act_props->pattern[i]) != 0) { 4392 error_message(BAD_ERROR, 4393 IPSEC_CONF_DST_ADDRESS, line_no); 4394 return (-1); 4395 } 4396 if (!cptr->has_dmask) 4397 cptr->has_dmask = has_daprefix; 4398 break; 4399 4400 case TOK_sport: 4401 if (new_style) { 4402 error_message(BAD_ERROR, 4403 IPSEC_CONF_SRC_PORT, line_no); 4404 return (-1); 4405 } 4406 old_style = B_TRUE; 4407 4408 if (cptr->ips_src_port_min != 0) { 4409 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4410 line_no); 4411 return (-1); 4412 } 4413 i++, line_no++; 4414 if (act_props->pattern[i] == NULL) { 4415 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4416 line_no); 4417 return (-1); 4418 } 4419 ret = parse_port(IPSEC_CONF_SRC_PORT, 4420 act_props->pattern[i], cptr); 4421 if (ret != 0) { 4422 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4423 line_no); 4424 return (-1); 4425 } 4426 break; 4427 case TOK_dport: 4428 if (new_style) { 4429 error_message(BAD_ERROR, 4430 IPSEC_CONF_DST_PORT, line_no); 4431 return (-1); 4432 } 4433 old_style = B_TRUE; 4434 4435 if (cptr->ips_dst_port_min != 0) { 4436 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4437 line_no); 4438 return (-1); 4439 } 4440 i++, line_no++; 4441 if (act_props->pattern[i] == NULL) { 4442 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4443 line_no); 4444 return (-1); 4445 } 4446 ret = parse_port(IPSEC_CONF_DST_PORT, 4447 act_props->pattern[i], 4448 cptr); 4449 if (ret != 0) { 4450 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4451 line_no); 4452 return (-1); 4453 } 4454 break; 4455 4456 case TOK_lport: 4457 if (old_style) { 4458 error_message(BAD_ERROR, 4459 IPSEC_CONF_SRC_PORT, line_no); 4460 return (-1); 4461 } 4462 new_style = B_TRUE; 4463 4464 if (cptr->ips_src_port_min != 0) { 4465 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4466 line_no); 4467 return (-1); 4468 } 4469 i++, line_no++; 4470 if (act_props->pattern[i] == NULL) { 4471 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4472 line_no); 4473 return (-1); 4474 } 4475 ret = parse_port(IPSEC_CONF_SRC_PORT, 4476 act_props->pattern[i], 4477 cptr); 4478 if (ret != 0) { 4479 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4480 line_no); 4481 return (-1); 4482 } 4483 break; 4484 4485 case TOK_rport: 4486 if (old_style) { 4487 error_message(BAD_ERROR, 4488 IPSEC_CONF_DST_PORT, line_no); 4489 return (-1); 4490 } 4491 new_style = B_TRUE; 4492 4493 if (cptr->ips_dst_port_min != 0) { 4494 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4495 line_no); 4496 return (-1); 4497 } 4498 i++, line_no++; 4499 if (act_props->pattern[i] == NULL) { 4500 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4501 line_no); 4502 return (-1); 4503 } 4504 ret = parse_port(IPSEC_CONF_DST_PORT, 4505 act_props->pattern[i], 4506 cptr); 4507 if (ret != 0) { 4508 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4509 line_no); 4510 return (-1); 4511 } 4512 break; 4513 4514 case TOK_smask: 4515 if (new_style) { 4516 error_message(BAD_ERROR, 4517 IPSEC_CONF_SRC_MASK, line_no); 4518 return (-1); 4519 } 4520 old_style = B_TRUE; 4521 cptr->has_smask = B_TRUE; 4522 4523 IN6_V4MAPPED_TO_INADDR(&cptr->ips_src_mask_v6, &mask); 4524 if (mask.s_addr != 0) { 4525 error_message(DUP_ERROR, IPSEC_CONF_SRC_MASK, 4526 line_no); 4527 return (-1); 4528 } 4529 i++, line_no++; 4530 if (act_props->pattern[i] == NULL) { 4531 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4532 line_no); 4533 return (-1); 4534 } 4535 ret = parse_mask(IPSEC_CONF_SRC_MASK, 4536 act_props->pattern[i], 4537 cptr); 4538 if (ret != 0) { 4539 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4540 line_no); 4541 return (-1); 4542 } 4543 break; 4544 case TOK_dmask: 4545 if (new_style) { 4546 error_message(BAD_ERROR, 4547 IPSEC_CONF_DST_MASK, line_no); 4548 return (-1); 4549 } 4550 old_style = B_TRUE; 4551 cptr->has_dmask = B_TRUE; 4552 4553 IN6_V4MAPPED_TO_INADDR(&cptr->ips_dst_mask_v6, &mask); 4554 if (mask.s_addr != 0) { 4555 error_message(DUP_ERROR, IPSEC_CONF_DST_MASK, 4556 line_no); 4557 return (-1); 4558 } 4559 i++, line_no++; 4560 if (act_props->pattern[i] == NULL) { 4561 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4562 line_no); 4563 return (-1); 4564 } 4565 ret = parse_mask(IPSEC_CONF_DST_MASK, 4566 act_props->pattern[i], 4567 cptr); 4568 if (ret != 0) { 4569 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4570 line_no); 4571 return (-1); 4572 } 4573 break; 4574 case TOK_ulp: 4575 if (cptr->ips_ulp_prot != 0) { 4576 error_message(DUP_ERROR, 4577 IPSEC_CONF_ULP, line_no); 4578 return (-1); 4579 } 4580 i++, line_no++; 4581 if (act_props->pattern[i] == NULL) { 4582 error_message(BAD_ERROR, 4583 IPSEC_CONF_ULP, line_no); 4584 return (-1); 4585 } 4586 pent = getprotobyname(act_props->pattern[i]); 4587 if (pent == NULL) { 4588 int ulp; 4589 ulp = parse_int(act_props->pattern[i]); 4590 if (ulp == -1) { 4591 error_message(BAD_ERROR, 4592 IPSEC_CONF_ULP, line_no); 4593 return (-1); 4594 } 4595 cptr->ips_ulp_prot = ulp; 4596 } else { 4597 cptr->ips_ulp_prot = pent->p_proto; 4598 } 4599 break; 4600 case TOK_type: 4601 if (cptr->has_type) { 4602 error_message(DUP_ERROR, 4603 IPSEC_CONF_ICMP_TYPE, line_no); 4604 return (-1); 4605 } 4606 4607 i++, line_no++; 4608 type = parse_type_code(act_props->pattern[i], 4609 icmp_type_table); 4610 4611 if (type > 65536 || type < 0) { 4612 error_message(BAD_ERROR, 4613 IPSEC_CONF_ICMP_TYPE, line_no); 4614 return (-1); 4615 } 4616 4617 type_end = type / 256; 4618 type = type % 256; 4619 4620 if (type_end < type) 4621 type_end = type; 4622 4623 cptr->has_type = 1; 4624 cptr->ips_icmp_type = (uint8_t)type; 4625 cptr->ips_icmp_type_end = (uint8_t)type_end; 4626 break; 4627 case TOK_code: 4628 if (!cptr->has_type) { 4629 error_message(BAD_ERROR, 4630 IPSEC_CONF_ICMP_CODE, line_no); 4631 return (-1); 4632 } 4633 4634 if (cptr->has_code) { 4635 error_message(DUP_ERROR, 4636 IPSEC_CONF_ICMP_CODE, line_no); 4637 return (-1); 4638 } 4639 4640 i++, line_no++; 4641 4642 code = parse_type_code(act_props->pattern[i], 4643 icmp_code_table); 4644 if (type > 65536 || type < 0) { 4645 error_message(BAD_ERROR, 4646 IPSEC_CONF_ICMP_CODE, line_no); 4647 return (-1); 4648 } 4649 code_end = code / 256; 4650 code = code % 256; 4651 4652 if (code_end < code) 4653 code_end = code; 4654 4655 cptr->has_code = 1; 4656 cptr->ips_icmp_code = (uint8_t)code; 4657 cptr->ips_icmp_code_end = (uint8_t)code_end; 4658 break; 4659 case TOK_tunnel: 4660 if (cptr->has_tunnel == 1) { 4661 error_message(BAD_ERROR, 4662 IPSEC_CONF_TUNNEL, line_no); 4663 return (-1); 4664 } 4665 i++, line_no++; 4666 if (act_props->pattern[i] == NULL) { 4667 error_message(BAD_ERROR, 4668 IPSEC_CONF_TUNNEL, line_no); 4669 return (-1); 4670 } 4671 4672 if (strlcpy(tunif, act_props->pattern[i], 4673 TUNNAMEMAXLEN) >= TUNNAMEMAXLEN) { 4674 error_message(BAD_ERROR, 4675 IPSEC_CONF_TUNNEL, line_no); 4676 return (-1); 4677 } 4678 cptr->has_tunnel = 1; 4679 break; 4680 case TOK_negotiate: 4681 if (cptr->has_negotiate == 1) { 4682 error_message(BAD_ERROR, 4683 IPSEC_CONF_NEGOTIATE, line_no); 4684 return (-1); 4685 } 4686 i++, line_no++; 4687 if (act_props->pattern[i] == NULL) { 4688 error_message(BAD_ERROR, 4689 IPSEC_CONF_NEGOTIATE, line_no); 4690 return (-1); 4691 } 4692 4693 if (strncmp(act_props->pattern[i], "tunnel", 6) == 0) { 4694 cptr->ips_tunnel = B_TRUE; 4695 } else if (strncmp( 4696 act_props->pattern[i], "transport", 9) != 0) { 4697 error_message(BAD_ERROR, 4698 IPSEC_CONF_NEGOTIATE, line_no); 4699 return (-1); 4700 } 4701 cptr->has_negotiate = 1; 4702 break; 4703 } 4704 4705 } 4706 4707 /* Sanity check that certain tokens occur together */ 4708 if (cptr->has_tunnel + cptr->has_negotiate == 1) { 4709 if (cptr->has_negotiate == 0) { 4710 error_message(REQ_ERROR, IPSEC_CONF_NEGOTIATE, line_no); 4711 } else { 4712 error_message(REQ_ERROR, IPSEC_CONF_TUNNEL, line_no); 4713 } 4714 errx(1, gettext( 4715 "tunnel and negotiate tokens must occur together")); 4716 return (-1); 4717 } 4718 4719 /* 4720 * Get the actions. 4721 */ 4722 4723 for (ap_num = 0; act_props->ap[ap_num].act != NULL; ap_num++) { 4724 ips_act_props_t *iap; 4725 4726 if (ap_num > 0) { 4727 /* or's only with new style */ 4728 if (old_style) { 4729 (void) printf("%s\n", gettext( 4730 "or's only with new style")); 4731 return (-1); 4732 } 4733 new_style = B_TRUE; 4734 } 4735 4736 ipsec_aalg = ipsec_ealg = ipsec_eaalg = auth_covered = B_FALSE; 4737 tok_count = 0; 4738 4739 for (k = 0; action_table[k].string; k++) { 4740 if (strcmp(act_props->ap[ap_num].act, 4741 action_table[k].string) == 0) 4742 break; 4743 } 4744 /* 4745 * The following thing should never happen as 4746 * we have already tested for its validity in parse. 4747 */ 4748 if (action_table[k].string == NULL) { 4749 warnx(gettext("(form act)Invalid action on line " 4750 "%d: %s"), (arg_indices[line_no] == 0) ? 1 : 4751 arg_indices[line_no], 4752 act_props->ap[ap_num].act); 4753 warnx("%s", act_props->ap[ap_num].act); 4754 return (-1); 4755 } 4756 4757 /* we have a good action alloc an iap */ 4758 iap = alloc_iap(cptr); 4759 4760 iap->iap_action = action_table[k].value; 4761 iap->iap_act_tok = action_table[k].tok_val; 4762 4763 switch (action_table[k].tok_val) { 4764 case TOK_apply: 4765 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4766 break; 4767 case TOK_permit: 4768 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4769 break; 4770 case TOK_ipsec: 4771 if (old_style) { 4772 /* Using saddr/daddr with ipsec action. */ 4773 if (!dir) { 4774 /* No direction specified */ 4775 error_message(REQ_ERROR, 4776 IPSEC_CONF_IPSEC_DIR, line_no); 4777 return (-1); 4778 } 4779 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 4780 /* 4781 * Need to swap addresses if 4782 * 'dir in' or translation to 4783 * laddr/raddr will be incorrect. 4784 */ 4785 cptr->swap = 1; 4786 } 4787 if (!dir) 4788 cptr->ips_dir = 4789 SPD_RULE_FLAG_INBOUND 4790 |SPD_RULE_FLAG_OUTBOUND; 4791 break; 4792 case TOK_bypass: 4793 case TOK_drop: 4794 is_no_alg = B_TRUE; 4795 break; 4796 } 4797 4798 line_no++; 4799 /* 4800 * Get the properties. NULL properties is not valid. 4801 * Later checks will catch it. 4802 */ 4803 for (i = 0; act_props->ap[ap_num].prop[i]; i++, line_no++) { 4804 for (j = 0; property_table[j].string; j++) { 4805 if (strcmp(act_props->ap[ap_num].prop[i], 4806 property_table[j].string) == 0) { 4807 break; 4808 } 4809 } 4810 if (property_table[j].string == NULL) { 4811 warnx(gettext("Invalid properties on line " 4812 "%d: %s"), 4813 (arg_indices[line_no] == 0) ? 4814 1 : arg_indices[line_no], 4815 act_props->ap[ap_num].prop[i]); 4816 return (-1); 4817 } 4818 4819 iap->iap_attr_tok[tok_count++] 4820 = property_table[j].value; 4821 4822 switch (property_table[j].value) { 4823 case SPD_ATTR_AH_AUTH: 4824 if (ipsec_aalg) { 4825 error_message(DUP_ERROR, 4826 IPSEC_CONF_IPSEC_AALGS, line_no); 4827 return (-1); 4828 } 4829 i++, line_no++; 4830 if (act_props->ap[ap_num].prop[i] == NULL) { 4831 error_message(BAD_ERROR, 4832 IPSEC_CONF_IPSEC_AALGS, line_no); 4833 return (-1); 4834 } 4835 ret = parse_ipsec_alg( 4836 act_props->ap[ap_num].prop[i], 4837 iap, SPD_ATTR_AH_AUTH); 4838 if (ret == -2) { 4839 /* "none" - ignore */ 4840 break; 4841 } 4842 if (ret != 0) { 4843 error_message(BAD_ERROR, 4844 IPSEC_CONF_IPSEC_AALGS, line_no); 4845 return (-1); 4846 } 4847 ipsec_aalg = B_TRUE; 4848 auth_covered = B_TRUE; 4849 break; 4850 case SPD_ATTR_ESP_ENCR: 4851 /* 4852 * If this option was not given 4853 * and encr_auth_algs was given, 4854 * we provide null-encryption. We do the 4855 * setting after we parse all the options. 4856 */ 4857 if (ipsec_ealg) { 4858 error_message(DUP_ERROR, 4859 IPSEC_CONF_IPSEC_EALGS, line_no); 4860 return (-1); 4861 } 4862 i++, line_no++; 4863 if (act_props->ap[ap_num].prop[i] == NULL) { 4864 error_message(BAD_ERROR, 4865 IPSEC_CONF_IPSEC_EALGS, line_no); 4866 return (-1); 4867 } 4868 ret = parse_ipsec_alg( 4869 act_props->ap[ap_num].prop[i], 4870 iap, SPD_ATTR_ESP_ENCR); 4871 if (ret == -2) { 4872 /* "none" - ignore */ 4873 break; 4874 } 4875 if (ret != 0) { 4876 error_message(BAD_ERROR, 4877 IPSEC_CONF_IPSEC_EALGS, line_no); 4878 return (-1); 4879 } 4880 /* 4881 * XXX FUTURE TODO -- set auth_covered here 4882 * if the encryption algorithm is self- 4883 * authenticating, e.g. AES-CCM/GCM. 4884 */ 4885 ipsec_ealg = B_TRUE; 4886 break; 4887 case SPD_ATTR_ESP_AUTH: 4888 /* 4889 * If this option was not given and encr_algs 4890 * option was given, we still pass a default 4891 * value in ipsc_esp_auth_algs. This is to 4892 * encourage the use of authentication with 4893 * ESP. 4894 */ 4895 if (ipsec_eaalg) { 4896 error_message(DUP_ERROR, 4897 IPSEC_CONF_IPSEC_EAALGS, line_no); 4898 return (-1); 4899 } 4900 /* 4901 * XXX FUTURE QUESTION -- error if 4902 * auth_covered and ipsec_aalg false 4903 * (e.g. AES-CCM/GCM)? 4904 */ 4905 i++, line_no++; 4906 if (act_props->ap[ap_num].prop[i] == NULL) { 4907 error_message(BAD_ERROR, 4908 IPSEC_CONF_IPSEC_EAALGS, line_no); 4909 return (-1); 4910 } 4911 ret = parse_ipsec_alg( 4912 act_props->ap[ap_num].prop[i], 4913 iap, SPD_ATTR_ESP_AUTH); 4914 if (ret == -2) { 4915 /* "none" - ignore */ 4916 break; 4917 } 4918 if (ret != 0) { 4919 error_message(BAD_ERROR, 4920 IPSEC_CONF_IPSEC_EAALGS, line_no); 4921 return (-1); 4922 } 4923 ipsec_eaalg = B_TRUE; 4924 auth_covered = B_TRUE; 4925 break; 4926 case IPS_SA: 4927 i++, line_no++; 4928 if (act_props->ap[ap_num].prop[i] == NULL) { 4929 error_message(BAD_ERROR, 4930 IPSEC_CONF_IPSEC_SA, line_no); 4931 return (-1); 4932 } 4933 4934 if (strcmp(act_props->ap[ap_num].prop[i], 4935 "unique") == 0) { 4936 iap->iap_attr |= SPD_APPLY_UNIQUE; 4937 } else if (strcmp(act_props->ap[ap_num].prop[i], 4938 "shared") != 0) { 4939 /* "shared" is default. */ 4940 error_message(BAD_ERROR, 4941 IPSEC_CONF_IPSEC_SA, line_no); 4942 return (-1); 4943 } 4944 4945 break; 4946 case IPS_DIR: 4947 if (dir) { 4948 error_message(DUP_ERROR, 4949 IPSEC_CONF_IPSEC_DIR, line_no); 4950 return (-1); 4951 } 4952 if (new_style) { 4953 error_message(BAD_ERROR, 4954 IPSEC_CONF_IPSEC_DIR, line_no); 4955 return (-1); 4956 } 4957 old_style = B_TRUE; 4958 dir = B_TRUE; 4959 i++, line_no++; 4960 if (act_props->ap[ap_num].prop[i] == NULL) { 4961 error_message(BAD_ERROR, 4962 IPSEC_CONF_IPSEC_DIR, line_no); 4963 return (-1); 4964 } 4965 if (strcmp(act_props->ap[ap_num].prop[i], 4966 "out") == 0) { 4967 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4968 } else if (strcmp(act_props->ap[ap_num].prop[i], 4969 "in") == 0) { 4970 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4971 } else { 4972 error_message(BAD_ERROR, 4973 IPSEC_CONF_IPSEC_DIR, line_no); 4974 return (-1); 4975 } 4976 if ((cptr->ips_dir & SPD_RULE_FLAG_INBOUND) && 4977 iap->iap_act_tok == TOK_apply) { 4978 warnx(gettext("Direction" 4979 " in conflict with action")); 4980 return (-1); 4981 } 4982 if ((cptr->ips_dir & SPD_RULE_FLAG_OUTBOUND) && 4983 iap->iap_act_tok == TOK_permit) { 4984 warnx(gettext("Direction" 4985 "in conflict with action")); 4986 return (-1); 4987 } 4988 4989 break; 4990 } 4991 } 4992 4993 /* Warn here about no authentication! */ 4994 if (!auth_covered && !is_no_alg) { 4995 warnx(gettext("DANGER: Rule on line %d " 4996 "has encryption with no authentication."), 4997 arg_indices[line_no] == 0 ? 1 : 4998 arg_indices[line_no]); 4999 } 5000 5001 if (!ipsec_ealg && ipsec_eaalg) { 5002 /* 5003 * If the user has specified the auth alg to be used 5004 * with encryption and did not provide a encryption 5005 * algorithm, provide null encryption. 5006 */ 5007 iap->iap_eencr.alg_id = SADB_EALG_NULL; 5008 ipsec_ealg = B_TRUE; 5009 } 5010 5011 /* Set the level of IPSEC protection we want */ 5012 if (ipsec_aalg && (ipsec_ealg || ipsec_eaalg)) { 5013 iap->iap_attr |= SPD_APPLY_AH|SPD_APPLY_ESP; 5014 } else if (ipsec_aalg) { 5015 iap->iap_attr |= SPD_APPLY_AH; 5016 } else if (ipsec_ealg || ipsec_eaalg) { 5017 iap->iap_attr |= SPD_APPLY_ESP; 5018 } 5019 5020 /* convert src/dst to local/remote */ 5021 if (!new_style) { 5022 switch (cptr->ips_acts->iap_act_tok) { 5023 case TOK_apply: 5024 /* outbound */ 5025 /* src=local, dst=remote */ 5026 /* this is ok. */ 5027 break; 5028 5029 case TOK_permit: 5030 /* inbound */ 5031 /* src=remote, dst=local */ 5032 /* switch */ 5033 cptr->swap = 1; 5034 break; 5035 case TOK_bypass: 5036 case TOK_drop: 5037 /* check the direction for what to do */ 5038 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 5039 cptr->swap = 1; 5040 break; 5041 default: 5042 break; 5043 } 5044 } 5045 /* Validate the properties */ 5046 if (ret = validate_properties(iap, dir, 5047 (ipsec_aalg || ipsec_ealg || ipsec_eaalg))) { 5048 return (ret); 5049 } 5050 } 5051 5052 return (0); 5053 5054 } 5055 5056 static int 5057 print_cmd_buf(FILE *fp, int error) 5058 { 5059 *(cbuf + cbuf_offset) = '\0'; 5060 5061 if (fp == stderr) { 5062 if (error != EEXIST) { 5063 warnx(gettext("Malformed command (fatal):\n%s"), cbuf); 5064 return (0); 5065 } 5066 if (ipsecconf_qflag) { 5067 return (0); 5068 } 5069 warnx(gettext("Duplicate policy entry (ignored):\n%s"), cbuf); 5070 } else { 5071 if (fprintf(fp, "%s", cbuf) == -1) { 5072 warn("fprintf"); 5073 return (-1); 5074 } 5075 } 5076 5077 return (0); 5078 } 5079 5080 #ifdef DEBUG 5081 5082 static uchar_t * 5083 addr_ptr(int isv4, struct in6_addr *addr6, struct in_addr *addr4) 5084 { 5085 if (isv4) { 5086 IN6_V4MAPPED_TO_INADDR(addr6, addr4); 5087 return ((uchar_t *)&addr4->s_addr); 5088 } else { 5089 return ((uchar_t *)&addr6->s6_addr); 5090 } 5091 } 5092 5093 static void 5094 dump_algreq(const char *tag, algreq_t *alg) 5095 { 5096 (void) printf("%s algid %d, bits %d..%d\n", 5097 tag, alg->alg_id, alg->alg_minbits, alg->alg_maxbits); 5098 } 5099 5100 static void 5101 dump_conf(ips_conf_t *conf) 5102 { 5103 boolean_t isv4 = conf->ips_isv4; 5104 struct in_addr addr; 5105 char buf[INET6_ADDRSTRLEN]; 5106 int af; 5107 ips_act_props_t *iap = conf->ips_acts; 5108 5109 af = isv4 ? AF_INET : AF_INET6; 5110 5111 (void) printf("Source Addr is %s\n", 5112 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_addr_v6, &addr), 5113 buf, INET6_ADDRSTRLEN)); 5114 5115 (void) printf("Dest Addr is %s\n", 5116 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_addr_v6, &addr), 5117 buf, INET6_ADDRSTRLEN)); 5118 5119 (void) printf("Source Mask is %s\n", 5120 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_mask_v6, &addr), 5121 buf, INET6_ADDRSTRLEN)); 5122 5123 (void) printf("Dest Mask is %s\n", 5124 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_mask_v6, &addr), 5125 buf, INET6_ADDRSTRLEN)); 5126 5127 (void) printf("Source port %d\n", ntohs(conf->ips_src_port_min)); 5128 (void) printf("Dest port %d\n", ntohs(conf->ips_dst_port_min)); 5129 (void) printf("ULP %d\n", conf->ips_ulp_prot); 5130 5131 (void) printf("ICMP type %d-%d code %d-%d", conf->ips_icmp_type, 5132 conf->ips_icmp_type_end, 5133 conf->ips_icmp_code, 5134 conf->ips_icmp_code_end); 5135 5136 while (iap != NULL) { 5137 (void) printf("------------------------------------\n"); 5138 (void) printf("IPsec act is %d\n", iap->iap_action); 5139 (void) printf("IPsec attr is %d\n", iap->iap_attr); 5140 dump_algreq("AH authentication", &iap->iap_aauth); 5141 dump_algreq("ESP authentication", &iap->iap_eauth); 5142 dump_algreq("ESP encryption", &iap->iap_eencr); 5143 (void) printf("------------------------------------\n"); 5144 iap = iap->iap_next; 5145 } 5146 5147 (void) fflush(stdout); 5148 } 5149 #endif /* DEBUG */ 5150 5151 5152 static int 5153 ipsec_conf_add(boolean_t just_check, boolean_t smf_managed) 5154 { 5155 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5156 ips_conf_t conf; 5157 FILE *fp, *policy_fp; 5158 int ret, flushret, i, j, diag, num_rules, good_rules; 5159 char *warning = gettext( 5160 "\tWARNING : New policy entries that are being added may\n " 5161 "\taffect the existing connections. Existing connections\n" 5162 "\tthat are not subjected to policy constraints, may be\n" 5163 "\tsubjected to policy constraints because of the new\n" 5164 "\tpolicy. This can disrupt the communication of the\n" 5165 "\texisting connections.\n\n"); 5166 5167 boolean_t first_time = B_TRUE; 5168 num_rules = 0; 5169 good_rules = 0; 5170 5171 if (act_props == NULL) { 5172 warn(gettext("memory")); 5173 return (-1); 5174 } 5175 5176 if (strcmp(filename, "-") == 0) 5177 fp = stdin; 5178 else 5179 fp = fopen(filename, "r"); 5180 5181 /* 5182 * Treat the non-existence of a policy file as a special 5183 * case when ipsecconf is being managed by smf(5). 5184 * The assumption is the administrator has not yet 5185 * created a policy file, this should not force the service 5186 * into maintenance mode. 5187 */ 5188 5189 if (fp == NULL) { 5190 if (smf_managed) { 5191 (void) fprintf(stdout, gettext( 5192 "Policy configuration file (%s) does not exist.\n" 5193 "IPsec policy not configured.\n"), filename); 5194 return (0); 5195 } 5196 warn(gettext("%s : Policy config file cannot be opened"), 5197 filename); 5198 usage(); 5199 return (-1); 5200 } 5201 /* 5202 * This will create the file if it does not exist. 5203 * Make sure the umask is right. 5204 */ 5205 (void) umask(0022); 5206 policy_fp = fopen(POLICY_CONF_FILE, "a"); 5207 if (policy_fp == NULL) { 5208 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5209 return (-1); 5210 } 5211 5212 /* 5213 * Pattern, action, and properties are allocated in 5214 * parse_pattern_or_prop and in parse_action (called by 5215 * parse_one) as we parse arguments. 5216 */ 5217 while ((ret = parse_one(fp, act_props)) != PARSE_EOF) { 5218 num_rules++; 5219 if (ret != 0) { 5220 (void) print_cmd_buf(stderr, NOERROR); 5221 continue; 5222 } 5223 5224 /* 5225 * If there is no action and parse returned success, 5226 * it means that there is nothing to add. 5227 */ 5228 if (act_props->pattern[0] == NULL && 5229 act_props->ap[0].act == NULL) 5230 break; 5231 5232 ret = form_ipsec_conf(act_props, &conf); 5233 if (ret != 0) { 5234 warnx(gettext("form_ipsec_conf error")); 5235 (void) print_cmd_buf(stderr, NOERROR); 5236 /* Reset globals before trying the next rule. */ 5237 if (shp != NULL) { 5238 freehostent(shp); 5239 shp = NULL; 5240 } 5241 if (dhp != NULL) { 5242 freehostent(dhp); 5243 dhp = NULL; 5244 } 5245 splen = 0; 5246 dplen = 0; 5247 continue; 5248 } 5249 5250 good_rules++; 5251 5252 if (first_time) { 5253 /* 5254 * Time to assume that there are valid policy entries. 5255 * If the IPsec kernel modules are not loaded this 5256 * will load them now. 5257 */ 5258 first_time = B_FALSE; 5259 fetch_algorithms(); 5260 ipsec_conf_admin(SPD_CLONE); 5261 } 5262 5263 /* 5264 * shp, dhp, splen, and dplen are globals set by 5265 * form_ipsec_conf() while parsing the addresses. 5266 */ 5267 if (shp == NULL && dhp == NULL) { 5268 switch (do_port_adds(&conf)) { 5269 case 0: 5270 /* no error */ 5271 break; 5272 case EEXIST: 5273 /* duplicate entries, continue adds */ 5274 (void) print_cmd_buf(stderr, EEXIST); 5275 goto next; 5276 default: 5277 /* other error, bail */ 5278 ret = -1; 5279 goto bail; 5280 } 5281 } else { 5282 ret = do_address_adds(&conf, &diag); 5283 switch (ret) { 5284 case 0: 5285 /* no error. */ 5286 break; 5287 case EEXIST: 5288 (void) print_cmd_buf(stderr, EEXIST); 5289 goto next; 5290 case EBUSY: 5291 warnx(gettext( 5292 "Can't set mask and /NN prefix.")); 5293 ret = -1; 5294 break; 5295 case ENOENT: 5296 warnx(gettext("Cannot find tunnel " 5297 "interface %s."), interface_name); 5298 ret = -1; 5299 break; 5300 case EINVAL: 5301 /* 5302 * PF_POLICY didn't like what we sent. We 5303 * can't check all input up here, but we 5304 * do in-kernel. 5305 */ 5306 warnx(gettext("PF_POLICY invalid input:\n\t%s"), 5307 spdsock_diag(diag)); 5308 break; 5309 case EOPNOTSUPP: 5310 warnx(gettext("Can't set /NN" 5311 " prefix on multi-host name.")); 5312 ret = -1; 5313 break; 5314 case ERANGE: 5315 warnx(gettext("/NN prefix is too big!")); 5316 ret = -1; 5317 break; 5318 case ESRCH: 5319 warnx(gettext("No matching IPv4 or " 5320 "IPv6 saddr/daddr pairs")); 5321 ret = -1; 5322 break; 5323 default: 5324 /* Should never get here. */ 5325 errno = ret; 5326 warn(gettext("Misc. error")); 5327 ret = -1; 5328 } 5329 if (ret == -1) 5330 goto bail; 5331 } 5332 5333 /* 5334 * Go ahead and add policy entries to config file. 5335 * The # should help re-using the ipsecpolicy.conf 5336 * for input again as # will be treated as comment. 5337 */ 5338 if (fprintf(policy_fp, "%s %lld \n", INDEX_TAG, 5339 conf.ips_policy_index) == -1) { 5340 warn("fprintf"); 5341 warnx(gettext("Addition incomplete, Please " 5342 "flush all the entries and re-configure :")); 5343 reconfigure(); 5344 ret = -1; 5345 break; 5346 } 5347 if (print_cmd_buf(policy_fp, NOERROR) == -1) { 5348 warnx(gettext("Addition incomplete. Please " 5349 "flush all the entries and re-configure :")); 5350 reconfigure(); 5351 ret = -1; 5352 break; 5353 } 5354 /* 5355 * We add one newline by default to separate out the 5356 * entries. If the last character is not a newline, we 5357 * insert a newline for free. This makes sure that all 5358 * entries look consistent in the file. 5359 */ 5360 if (*(cbuf + cbuf_offset - 1) == '\n') { 5361 if (fprintf(policy_fp, "\n") == -1) { 5362 warn("fprintf"); 5363 warnx(gettext("Addition incomplete. " 5364 "Please flush all the entries and " 5365 "re-configure :")); 5366 reconfigure(); 5367 ret = -1; 5368 break; 5369 } 5370 } else { 5371 if (fprintf(policy_fp, "\n\n") == -1) { 5372 warn("fprintf"); 5373 warnx(gettext("Addition incomplete. " 5374 "Please flush all the entries and " 5375 "re-configure :")); 5376 reconfigure(); 5377 ret = -1; 5378 break; 5379 } 5380 } 5381 next: 5382 /* 5383 * Make sure this gets to the disk before 5384 * we parse the next entry. 5385 */ 5386 (void) fflush(policy_fp); 5387 for (i = 0; act_props->pattern[i] != NULL; i++) 5388 free(act_props->pattern[i]); 5389 for (j = 0; act_props->ap[j].act != NULL; j++) { 5390 free(act_props->ap[j].act); 5391 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5392 free(act_props->ap[j].prop[i]); 5393 } 5394 } 5395 if (ret == PARSE_EOF) 5396 ret = 0; /* Not an error */ 5397 bail: 5398 if (ret == -1) { 5399 (void) print_cmd_buf(stderr, EINVAL); 5400 for (i = 0; act_props->pattern[i] != NULL; i++) 5401 free(act_props->pattern[i]); 5402 for (j = 0; act_props->ap[j].act != NULL; j++) { 5403 free(act_props->ap[j].act); 5404 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5405 free(act_props->ap[j].prop[i]); 5406 } 5407 } 5408 #ifdef DEBUG_HEAVY 5409 (void) printf("ipsec_conf_add: ret val = %d\n", ret); 5410 (void) fflush(stdout); 5411 #endif 5412 if (num_rules == 0 && ret == 0) { 5413 nuke_adds(); 5414 (void) restore_all_signals(); 5415 (void) unlock(lfd); 5416 EXIT_OK("Policy file does not contain any valid rules."); 5417 } 5418 if (num_rules != good_rules) { 5419 /* This is an error */ 5420 nuke_adds(); 5421 (void) restore_all_signals(); 5422 (void) unlock(lfd); 5423 EXIT_BADCONFIG2("%d policy rule(s) contained errors.", 5424 num_rules - good_rules); 5425 } 5426 /* looks good, flip it in */ 5427 if (ret == 0 && !just_check) { 5428 if (!ipsecconf_qflag) { 5429 (void) printf("%s", warning); 5430 } 5431 if (smf_managed) 5432 warnx(gettext("%d policy rules added."), good_rules); 5433 ipsec_conf_admin(SPD_FLIP); 5434 } else { 5435 nuke_adds(); 5436 if (just_check) { 5437 (void) fprintf(stdout, gettext("IPsec configuration " 5438 "does not contain any errors.\n")); 5439 (void) fprintf(stdout, gettext( 5440 "IPsec policy was not modified.\n")); 5441 (void) fflush(stdout); 5442 } 5443 } 5444 flushret = ipsec_conf_flush(SPD_STANDBY); 5445 if (flushret != 0) 5446 return (flushret); 5447 return (ret); 5448 } 5449 5450 5451 static int 5452 ipsec_conf_sub() 5453 { 5454 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5455 FILE *remove_fp, *policy_fp; 5456 char rbuf[MAXLEN], pbuf[MAXLEN], /* remove buffer, and policy buffer */ 5457 *warning = gettext( 5458 "\tWARNING: Policy entries that are being removed may\n" 5459 "\taffect the existing connections. Existing connections\n" 5460 "\tthat are subjected to policy constraints may no longer\n" 5461 "\tbe subjected to policy contraints because of its\n" 5462 "\tremoval. This can compromise security, and disrupt\n" 5463 "\tthe communication of the existing connection.\n" 5464 "\tConnections that are latched will remain unaffected\n" 5465 "\tuntil they close.\n"); 5466 int ret = 0; 5467 int index_len, pindex = 0; /* init value in case of pfile error */ 5468 5469 if (act_props == NULL) { 5470 warn(gettext("memory")); 5471 return (-1); 5472 } 5473 5474 /* clone into standby DB */ 5475 (void) ipsec_conf_admin(SPD_CLONE); 5476 5477 if (strcmp(filename, "-") == 0) 5478 remove_fp = stdin; 5479 else 5480 remove_fp = fopen(filename, "r"); 5481 5482 if (remove_fp == NULL) { 5483 warn(gettext("%s : Input file cannot be opened"), filename); 5484 usage(); 5485 free(act_props); 5486 return (-1); 5487 } 5488 5489 /* open policy file so we can locate the correct policy */ 5490 (void) umask(0022); /* in case it gets created! */ 5491 policy_fp = fopen(POLICY_CONF_FILE, "r+"); 5492 if (policy_fp == NULL) { 5493 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5494 (void) fclose(remove_fp); 5495 free(act_props); 5496 return (-1); 5497 } 5498 5499 /* don't print the warning if we're in q[uiet] mode */ 5500 if (!ipsecconf_qflag) 5501 (void) printf("%s", warning); 5502 5503 /* this bit is done primarily so we can read what we write */ 5504 index_len = strlen(INDEX_TAG); 5505 5506 /* 5507 * We want to look for the policy in rbuf in the policy file. 5508 * Go through the list of policies to remove, locating each one. 5509 */ 5510 while (fgets(rbuf, MAXLEN, remove_fp) != NULL) { 5511 char *buf; 5512 int offset, prev_offset, prev_prev_offset, nlines; 5513 fpos_t ipos; 5514 int pbuf_len = 0; 5515 char *tmp; 5516 /* skip blanks here (so we don't need to do it below)! */ 5517 for (tmp = rbuf; (*tmp != '\0') && isspace(*tmp); ) 5518 tmp++; 5519 5520 if (*tmp == '\0') 5521 continue; /* while(); */ 5522 5523 /* skip the INDEX_TAG lines in the remove buffer */ 5524 if (strncasecmp(rbuf, INDEX_TAG, index_len) == 0) 5525 continue; 5526 5527 /* skip commented lines */ 5528 if (*tmp == '#') 5529 continue; /* while(); */ 5530 5531 /* 5532 * We start by presuming only good policies are in the pfile, 5533 * and so only good policies from the rfile will match them. 5534 * ipsec_conf_del ensures this later by calling parse_one() on 5535 * pfile before it deletes the entry. 5536 */ 5537 for (offset = prev_offset = prev_prev_offset = 0; 5538 fgets(pbuf, MAXLEN, policy_fp) != NULL; 5539 offset += pbuf_len) { 5540 prev_offset = offset; 5541 pbuf_len = strlen(pbuf); 5542 5543 /* skip blank lines which seperate policy entries */ 5544 if (pbuf[0] == '\n') 5545 continue; 5546 5547 /* if we found an index, save it */ 5548 if (strncasecmp(pbuf, INDEX_TAG, index_len) == 0) { 5549 buf = pbuf + index_len; 5550 buf++; 5551 if ((pindex = parse_index(buf, NULL)) == -1) { 5552 /* bad index, we can't continue */ 5553 warnx(gettext( 5554 "Invalid index in the file")); 5555 (void) fclose(remove_fp); 5556 (void) fclose(policy_fp); 5557 free(act_props); 5558 return (-1); 5559 } 5560 5561 /* save this position in case it's the one */ 5562 if (fgetpos(policy_fp, &ipos) != 0) { 5563 (void) fclose(remove_fp); 5564 (void) fclose(policy_fp); 5565 free(act_props); 5566 return (-1); 5567 } 5568 } 5569 5570 /* Does pbuf contain the remove policy? */ 5571 if (strncasecmp(rbuf, pbuf, pbuf_len) == 0) { 5572 /* we found the one to remove! */ 5573 if (pindex == 0) { 5574 warnx(gettext("Didn't find a valid " 5575 "index for policy")); 5576 (void) fclose(remove_fp); 5577 (void) fclose(policy_fp); 5578 free(act_props); 5579 return (-1); 5580 } 5581 5582 /* off it - back up to the last INDEX! */ 5583 if (fsetpos(policy_fp, &ipos) != 0) { 5584 (void) fclose(remove_fp); 5585 (void) fclose(policy_fp); 5586 free(act_props); 5587 return (-1); 5588 } 5589 5590 /* parse_one sets linecount = #lines to off */ 5591 if (parse_one(policy_fp, act_props) == -1) { 5592 warnx(gettext("Invalid policy entry " 5593 "in the file")); 5594 (void) fclose(remove_fp); 5595 (void) fclose(policy_fp); 5596 free(act_props); 5597 return (-1); 5598 } 5599 5600 nlines = linecount + 2; 5601 goto delete; 5602 } 5603 /* 5604 * When we find a match, we want to pass the offset 5605 * of the line that is before it - the INDEX_TAG line. 5606 */ 5607 prev_prev_offset = prev_offset; 5608 } 5609 /* Didn't find a match - look at the next remove policy */ 5610 continue; /* while(); */ 5611 5612 delete: 5613 (void) fclose(policy_fp); 5614 5615 if (delete_from_file(prev_prev_offset, nlines) != 0) { 5616 warnx(gettext("delete_from_file failure. " 5617 "Please flush all entries and re-configure :")); 5618 reconfigure(); 5619 (void) fclose(remove_fp); 5620 free(act_props); 5621 return (-1); 5622 } 5623 5624 if (pfp_delete_rule(pindex) != 0) { 5625 warnx(gettext("Deletion incomplete. Please flush" 5626 "all the entries and re-configure :")); 5627 reconfigure(); 5628 (void) fclose(remove_fp); 5629 free(act_props); 5630 return (-1); 5631 } 5632 5633 /* reset the globals */ 5634 linecount = 0; 5635 pindex = 0; 5636 /* free(NULL) also works. */ 5637 free(interface_name); 5638 interface_name = NULL; 5639 5640 /* reopen for next pass, automagically starting over. */ 5641 policy_fp = fopen(POLICY_CONF_FILE, "r"); 5642 if (policy_fp == NULL) { 5643 warn(gettext("%s cannot be re-opened, can't continue"), 5644 POLICY_CONF_FILE); 5645 (void) fclose(remove_fp); 5646 free(act_props); 5647 return (-1); 5648 } 5649 5650 } /* read next remove policy */ 5651 5652 if ((ret = pfp_delete_rule(pindex)) != 0) { 5653 warnx(gettext("Removal incomplete. Please flush " 5654 "all the entries and re-configure :")); 5655 reconfigure(); 5656 free(act_props); 5657 return (ret); 5658 } 5659 5660 /* nothing left to look for */ 5661 (void) fclose(remove_fp); 5662 free(act_props); 5663 5664 return (0); 5665 } 5666 5667 /* 5668 * Constructs a tunnel interface ID extension. Returns the length 5669 * of the extension in 64-bit-words. 5670 */ 5671 static int 5672 attach_tunname(spd_if_t *tunname) 5673 { 5674 if (tunname == NULL || interface_name == NULL) 5675 return (0); 5676 5677 tunname->spd_if_exttype = SPD_EXT_TUN_NAME; 5678 /* 5679 * Use "-3" because there's 4 bytes in the message itself, and 5680 * we lose one because of the '\0' terminator. 5681 */ 5682 tunname->spd_if_len = SPD_8TO64( 5683 P2ROUNDUP(sizeof (*tunname) + strlen(interface_name) - 3, 8)); 5684 (void) strlcpy((char *)tunname->spd_if_name, interface_name, LIFNAMSIZ); 5685 return (tunname->spd_if_len); 5686 } 5687