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 boolean_t 3401 combined_mode(ips_act_props_t *iap) 3402 { 3403 struct ipsecalgent *alg; 3404 3405 alg = getipsecalgbynum(iap->iap_eencr.alg_id, IPSEC_PROTO_ESP, NULL); 3406 if (alg != NULL) 3407 freeipsecalgent(alg); 3408 3409 return (ALG_FLAG_COMBINED & alg->a_alg_flags); 3410 } 3411 3412 static int 3413 valid_algorithm(int proto_num, const char *str) 3414 { 3415 const char *tmp; 3416 int ret; 3417 struct ipsecalgent *alg; 3418 3419 /* Short-circuit "none" */ 3420 if (strncasecmp("none", str, 5) == 0) 3421 return (-2); 3422 3423 alg = getipsecalgbyname(str, proto_num, NULL); 3424 if (alg != NULL) { 3425 ret = alg->a_alg_num; 3426 freeipsecalgent(alg); 3427 return (ret); 3428 } 3429 3430 /* 3431 * Look whether it could be a valid number. 3432 * We support numbers also so that users can 3433 * load algorithms as they need it. We can't 3434 * check for validity of numbers here. It will 3435 * be checked when the SA is negotiated/looked up. 3436 * parse_int uses strtol(str), which converts 3DES 3437 * to a valid number i.e looks only at initial 3438 * number part. If we come here we should expect 3439 * only a decimal number. 3440 */ 3441 tmp = str; 3442 while (*tmp) { 3443 if (!isdigit(*tmp)) 3444 return (-1); 3445 tmp++; 3446 } 3447 3448 ret = parse_int(str); 3449 if (ret > 0 && ret <= 255) 3450 return (ret); 3451 else 3452 return (-1); 3453 } 3454 3455 static int 3456 parse_ipsec_alg(char *str, ips_act_props_t *iap, int alg_type) 3457 { 3458 int alg_value; 3459 char tstr[VALID_ALG_LEN]; 3460 char *lens = NULL; 3461 char *l1_str; 3462 int l1 = 0; 3463 char *l2_str; 3464 int l2 = SPD_MAX_MAXBITS; 3465 algreq_t *ap; 3466 uint_t a_type; 3467 3468 fetch_algorithms(); 3469 3470 /* 3471 * Make sure that we get a null terminated string. 3472 * For a bad input, we truncate at VALID_ALG_LEN. 3473 */ 3474 (void) strlcpy(tstr, str, VALID_ALG_LEN); 3475 lens = strtok(tstr, "()"); 3476 lens = strtok(NULL, "()"); 3477 3478 if (lens != NULL) { 3479 int len1 = 0; 3480 int len2 = SPD_MAX_MAXBITS; 3481 int len_all = strlen(lens); 3482 int dot_start = (lens[0] == '.'); 3483 l1_str = strtok(lens, "."); 3484 l2_str = strtok(NULL, "."); 3485 if (l1_str != NULL) { 3486 l1 = parse_int(l1_str); 3487 len1 = strlen(l1_str); 3488 if (len1 < 0) 3489 return (1); 3490 } 3491 if (l2_str != NULL) { 3492 l2 = parse_int(l2_str); 3493 len2 = strlen(l2_str); 3494 if (len2 < 0) 3495 return (1); 3496 } 3497 3498 if (len_all == len1) { 3499 /* alg(n) */ 3500 l2 = l1; 3501 } else if (dot_start) { 3502 /* alg(..n) */ 3503 l2 = l1; 3504 l1 = 0; 3505 } else if ((len_all - 2) == len1) { 3506 /* alg(n..) */ 3507 l2 = SPD_MAX_MAXBITS; 3508 } /* else alg(n..m) */ 3509 } 3510 3511 if (alg_type == SPD_ATTR_AH_AUTH || 3512 alg_type == SPD_ATTR_ESP_AUTH) { 3513 alg_value = valid_algorithm(IPSEC_PROTO_AH, tstr); 3514 } else { 3515 alg_value = valid_algorithm(IPSEC_PROTO_ESP, tstr); 3516 } 3517 if (alg_value < 0) { 3518 /* Invalid algorithm or "none" */ 3519 return (alg_value); 3520 } 3521 3522 if (alg_type == SPD_ATTR_AH_AUTH) { 3523 a_type = AH_AUTH; 3524 iap->iap_attr |= SPD_APPLY_AH; 3525 ap = &(iap->iap_aauth); 3526 } else if (alg_type == SPD_ATTR_ESP_AUTH) { 3527 a_type = ESP_AUTH; 3528 iap->iap_attr |= SPD_APPLY_ESP|SPD_APPLY_ESPA; 3529 ap = &(iap->iap_eauth); 3530 } else { 3531 a_type = ESP_ENCR; 3532 iap->iap_attr |= SPD_APPLY_ESP; 3533 ap = &(iap->iap_eencr); 3534 } 3535 3536 ap->alg_id = alg_value; 3537 ap->alg_minbits = l1; 3538 ap->alg_maxbits = l2; 3539 3540 if (!alg_rangecheck(a_type, alg_value, ap)) 3541 return (1); 3542 3543 return (0); 3544 } 3545 3546 static char * 3547 sys_error_message(int syserr) 3548 { 3549 char *mesg; 3550 3551 switch (syserr) { 3552 case EEXIST: 3553 mesg = gettext("Entry already exists"); 3554 break; 3555 case ENOENT: 3556 mesg = gettext("Tunnel not found"); 3557 break; 3558 case EINVAL: 3559 mesg = gettext("Invalid entry"); 3560 break; 3561 default : 3562 mesg = strerror(syserr); 3563 } 3564 return (mesg); 3565 } 3566 3567 static void 3568 error_message(error_type_t error, int type, int line) 3569 { 3570 char *mesg; 3571 3572 switch (type) { 3573 case IPSEC_CONF_SRC_ADDRESS: 3574 mesg = gettext("Source Address"); 3575 break; 3576 case IPSEC_CONF_DST_ADDRESS: 3577 mesg = gettext("Destination Address"); 3578 break; 3579 case IPSEC_CONF_SRC_PORT: 3580 mesg = gettext("Source Port"); 3581 break; 3582 case IPSEC_CONF_DST_PORT: 3583 mesg = gettext("Destination Port"); 3584 break; 3585 case IPSEC_CONF_SRC_MASK: 3586 mesg = gettext("Source Mask"); 3587 break; 3588 case IPSEC_CONF_DST_MASK: 3589 mesg = gettext("Destination Mask"); 3590 break; 3591 case IPSEC_CONF_ULP: 3592 mesg = gettext("Upper Layer Protocol"); 3593 break; 3594 case IPSEC_CONF_IPSEC_AALGS: 3595 mesg = gettext("Authentication Algorithm"); 3596 break; 3597 case IPSEC_CONF_IPSEC_EALGS: 3598 mesg = gettext("Encryption Algorithm"); 3599 break; 3600 case IPSEC_CONF_IPSEC_EAALGS: 3601 mesg = gettext("ESP Authentication Algorithm"); 3602 break; 3603 case IPSEC_CONF_IPSEC_SA: 3604 mesg = gettext("SA"); 3605 break; 3606 case IPSEC_CONF_IPSEC_DIR: 3607 mesg = gettext("Direction"); 3608 break; 3609 case IPSEC_CONF_ICMP_TYPE: 3610 mesg = gettext("ICMP type"); 3611 break; 3612 case IPSEC_CONF_ICMP_CODE: 3613 mesg = gettext("ICMP code"); 3614 break; 3615 case IPSEC_CONF_NEGOTIATE: 3616 mesg = gettext("Negotiate"); 3617 break; 3618 case IPSEC_CONF_TUNNEL: 3619 mesg = gettext("Tunnel"); 3620 break; 3621 default : 3622 return; 3623 } 3624 /* 3625 * If we never read a newline character, we don't want 3626 * to print 0. 3627 */ 3628 warnx(gettext("%s%s%s %s on line: %d"), 3629 (error == BAD_ERROR) ? gettext("Bad") : "", 3630 (error == DUP_ERROR) ? gettext("Duplicate") : "", 3631 (error == REQ_ERROR) ? gettext("Requires") : "", 3632 mesg, 3633 (arg_indices[line] == 0) ? 1 : arg_indices[line]); 3634 } 3635 3636 static int 3637 validate_properties(ips_act_props_t *cptr, boolean_t dir, boolean_t is_alg) 3638 { 3639 if (cptr->iap_action == SPD_ACTTYPE_PASS || 3640 cptr->iap_action == SPD_ACTTYPE_DROP) { 3641 if (!dir) { 3642 warnx(gettext("dir string " 3643 "not found for bypass policy")); 3644 } 3645 3646 if (is_alg) { 3647 warnx(gettext("Algorithms found for bypass policy")); 3648 return (-1); 3649 } 3650 return (0); 3651 } 3652 if (!is_alg) { 3653 warnx(gettext("No IPsec algorithms given")); 3654 return (-1); 3655 } 3656 if (cptr->iap_attr == 0) { 3657 warnx(gettext("No SA attribute")); 3658 return (-1); 3659 } 3660 return (0); 3661 } 3662 3663 /* 3664 * This function is called only to parse a single rule's worth of 3665 * action strings. This is called after parsing pattern and before 3666 * parsing properties. Thus we may have something in the leftover 3667 * buffer while parsing the pattern, which we need to handle here. 3668 */ 3669 static int 3670 parse_action(FILE *fp, char **action, char **leftover) 3671 { 3672 char *cp; 3673 char ibuf[MAXLEN]; 3674 char *tmp_buf; 3675 char *buf; 3676 boolean_t new_stuff; 3677 3678 if (*leftover != NULL) { 3679 buf = *leftover; 3680 new_stuff = B_FALSE; 3681 goto scan; 3682 } 3683 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3684 new_stuff = B_TRUE; 3685 if (ibuf[strlen(ibuf) - 1] == '\n') 3686 linecount++; 3687 buf = ibuf; 3688 scan: 3689 /* Truncate at the beginning of a comment */ 3690 cp = strchr(buf, '#'); 3691 if (cp != NULL) 3692 *cp = NULL; 3693 3694 /* Skip any whitespace */ 3695 while (*buf != NULL && isspace(*buf)) 3696 buf++; 3697 3698 /* Empty line */ 3699 if (*buf == NULL) 3700 continue; 3701 3702 /* 3703 * Store the command for error reporting 3704 * and ipsec_conf_add(). 3705 */ 3706 if (new_stuff) { 3707 /* 3708 * Check for buffer overflow including the null 3709 * terminating character. 3710 */ 3711 int len = strlen(ibuf); 3712 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3713 return (-1); 3714 3715 (void) strcpy(cbuf + cbuf_offset, ibuf); 3716 cbuf_offset += len; 3717 } 3718 /* 3719 * Start of the non-empty non-space character. 3720 */ 3721 tmp_buf = buf; 3722 3723 /* Skip until next whitespace or CURL_BEGIN */ 3724 while (*buf != NULL && !isspace(*buf) && 3725 *buf != CURL_BEGIN) 3726 buf++; 3727 3728 if (*buf != NULL) { 3729 if (tmp_buf == buf) /* No action token */ 3730 goto error; 3731 if (*buf == CURL_BEGIN) { 3732 *buf = NULL; 3733 /* Allocate an extra byte for the null also */ 3734 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3735 NULL) { 3736 warn("malloc"); 3737 return (ENOMEM); 3738 } 3739 (void) strcpy(*action, tmp_buf); 3740 *buf = CURL_BEGIN; 3741 } else { 3742 /* We have hit a space */ 3743 *buf++ = NULL; 3744 /* Allocate an extra byte for the null also */ 3745 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3746 NULL) { 3747 warn("malloc"); 3748 return (ENOMEM); 3749 } 3750 (void) strcpy(*action, tmp_buf); 3751 } 3752 /* 3753 * Copy the rest of the line into the 3754 * leftover buffer. 3755 */ 3756 if (*buf != NULL) { 3757 (void) strlcpy(lo_buf, buf, sizeof (lo_buf)); 3758 *leftover = lo_buf; 3759 } else { 3760 *leftover = NULL; 3761 } 3762 } else { 3763 /* Allocate an extra byte for the null also */ 3764 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3765 NULL) { 3766 warn("malloc"); 3767 return (ENOMEM); 3768 } 3769 (void) strcpy(*action, tmp_buf); 3770 *leftover = NULL; 3771 } 3772 if (argindex >= ARG_BUF_LEN) { 3773 warnx(gettext("(parsing one command) " 3774 "Too many selectors before action.")); 3775 return (-1); 3776 } 3777 arg_indices[argindex++] = linecount; 3778 return (PARSE_SUCCESS); 3779 } 3780 /* 3781 * Return error, on an empty action field. 3782 */ 3783 error: 3784 warnx(gettext("(parsing one command) " 3785 "Missing action token.")); 3786 return (-1); 3787 } 3788 3789 /* 3790 * This is called to parse pattern or properties that is enclosed 3791 * between CURL_BEGIN and CURL_END. 3792 */ 3793 static int 3794 parse_pattern_or_prop(FILE *fp, char *argvec[], char **leftover) 3795 { 3796 char *cp; 3797 int i = 0; 3798 boolean_t curl_begin_seen = B_FALSE; 3799 char ibuf[MAXLEN]; 3800 char *tmp_buf; 3801 char *buf; 3802 boolean_t new_stuff; 3803 3804 /* 3805 * When parsing properties, leftover buffer could have the 3806 * leftovers of the previous fgets(). 3807 */ 3808 if (*leftover != NULL) { 3809 buf = *leftover; 3810 new_stuff = B_FALSE; 3811 goto scan; 3812 } 3813 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3814 new_stuff = B_TRUE; 3815 #ifdef DEBUG_HEAVY 3816 (void) printf("%s\n", ibuf); 3817 #endif 3818 if (ibuf[strlen(ibuf) - 1] == '\n') 3819 linecount++; 3820 buf = ibuf; 3821 scan: 3822 /* Truncate at the beginning of a comment */ 3823 cp = strchr(buf, '#'); 3824 if (cp != NULL) 3825 *cp = NULL; 3826 3827 /* Skip any whitespace */ 3828 while (*buf != NULL && isspace(*buf)) 3829 buf++; 3830 3831 /* Empty line */ 3832 if (*buf == NULL) 3833 continue; 3834 /* 3835 * Store the command for error reporting 3836 * and ipsec_conf_add(). 3837 */ 3838 if (new_stuff) { 3839 /* 3840 * Check for buffer overflow including the null 3841 * terminating character. 3842 */ 3843 int len = strlen(ibuf); 3844 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3845 return (-1); 3846 (void) strcpy(cbuf + cbuf_offset, ibuf); 3847 cbuf_offset += len; 3848 } 3849 /* 3850 * First non-space character should be 3851 * a curly bracket. 3852 */ 3853 if (!curl_begin_seen) { 3854 if (*buf != CURL_BEGIN) { 3855 /* 3856 * If we never read a newline character, 3857 * we don't want to print 0. 3858 */ 3859 warnx(gettext("line %d : pattern must start " 3860 "with \"%c\" character"), 3861 (linecount == 0) ? 1 : linecount, 3862 CURL_BEGIN); 3863 return (-1); 3864 } 3865 buf++; 3866 curl_begin_seen = B_TRUE; 3867 } 3868 /* 3869 * Arguments are separated by white spaces or 3870 * newlines. Scan till you see a CURL_END. 3871 */ 3872 while (*buf != NULL) { 3873 if (*buf == CURL_END) { 3874 ret: 3875 *buf++ = NULL; 3876 /* 3877 * Copy the rest of the line into the 3878 * leftover buffer if any. 3879 */ 3880 if (*buf != NULL) { 3881 (void) strlcpy(lo_buf, buf, 3882 sizeof (lo_buf)); 3883 *leftover = lo_buf; 3884 } else { 3885 *leftover = NULL; 3886 } 3887 return (PARSE_SUCCESS); 3888 } 3889 /* 3890 * Skip any trailing whitespace until we see a 3891 * non white-space character. 3892 */ 3893 while (*buf != NULL && isspace(*buf)) 3894 buf++; 3895 3896 if (*buf == CURL_END) 3897 goto ret; 3898 3899 /* Scan the next line as this buffer is empty */ 3900 if (*buf == NULL) 3901 break; 3902 3903 if (i >= MAXARGS) { 3904 warnx( 3905 gettext("Number of Arguments exceeded %d"), 3906 i); 3907 return (-1); 3908 } 3909 /* 3910 * Non-empty, Non-space buffer. 3911 */ 3912 tmp_buf = buf++; 3913 /* 3914 * Real scan of the argument takes place here. 3915 * Skip past till space or CURL_END. 3916 */ 3917 while (*buf != NULL && !isspace(*buf) && 3918 *buf != CURL_END) { 3919 buf++; 3920 } 3921 /* 3922 * Either a space or we have hit the CURL_END or 3923 * the real end. 3924 */ 3925 if (*buf != NULL) { 3926 if (*buf == CURL_END) { 3927 *buf++ = NULL; 3928 if ((argvec[i] = malloc(strlen(tmp_buf) 3929 + 1)) == NULL) { 3930 warn("malloc"); 3931 return (ENOMEM); 3932 } 3933 if (strlen(tmp_buf) != 0) { 3934 (void) strcpy(argvec[i], 3935 tmp_buf); 3936 if (argindex >= ARG_BUF_LEN) 3937 goto toomanyargs; 3938 arg_indices[argindex++] = 3939 linecount; 3940 } 3941 /* 3942 * Copy the rest of the line into the 3943 * leftover buffer. 3944 */ 3945 if (*buf != NULL) { 3946 (void) strlcpy(lo_buf, buf, 3947 sizeof (lo_buf)); 3948 *leftover = lo_buf; 3949 } else { 3950 *leftover = NULL; 3951 } 3952 return (PARSE_SUCCESS); 3953 } else { 3954 *buf++ = NULL; 3955 } 3956 } 3957 /* 3958 * Copy this argument and scan for the buffer more 3959 * if it is non-empty. If it is empty scan for 3960 * the next line. 3961 */ 3962 if ((argvec[i] = malloc(strlen(tmp_buf) + 1)) == 3963 NULL) { 3964 warn("malloc"); 3965 return (ENOMEM); 3966 } 3967 (void) strcpy(argvec[i++], tmp_buf); 3968 if (argindex >= ARG_BUF_LEN) { 3969 /* 3970 * The number of tokens in a single policy entry 3971 * exceeds the number of buffers available to fully 3972 * parse the policy entry. 3973 */ 3974 toomanyargs: 3975 warnx(gettext("(parsing one command) " 3976 "Too many tokens in single policy entry.")); 3977 return (-1); 3978 } 3979 arg_indices[argindex++] = linecount; 3980 } 3981 } 3982 /* 3983 * If nothing is given in the file, it is okay. 3984 * If something is given in the file and it is 3985 * not CURL_BEGIN, we would have returned error 3986 * above. If curl_begin_seen and we are here, 3987 * something is wrong. 3988 */ 3989 if (curl_begin_seen) { 3990 warnx(gettext("(parsing one command) " 3991 "Pattern or Properties incomplete.")); 3992 return (-1); 3993 } 3994 return (PARSE_EOF); /* Nothing more in the file */ 3995 } 3996 3997 /* 3998 * Parse one command i.e {pattern} action {properties}. 3999 * 4000 * {pattern} ( action {prop} | pass | drop ) (or ...)* 4001 */ 4002 static int 4003 parse_one(FILE *fp, act_prop_t *act_props) 4004 { 4005 char *leftover; 4006 int ret; 4007 int i; 4008 int ap_num = 0; 4009 enum parse_state {pattern, action, prop } pstate; 4010 4011 has_daprefix = has_saprefix = B_FALSE; 4012 4013 (void) memset(act_props, 0, sizeof (act_prop_t)); 4014 pstate = pattern; 4015 4016 ret = 0; 4017 leftover = NULL; 4018 argindex = 0; 4019 cbuf_offset = 0; 4020 assert(shp == NULL && dhp == NULL); 4021 4022 for (;;) { 4023 switch (pstate) { 4024 case pattern: 4025 { 4026 #ifdef DEBUG_HEAVY 4027 (void) printf("pattern\n"); 4028 #endif 4029 ret = parse_pattern_or_prop(fp, 4030 act_props->pattern, &leftover); 4031 if (ret == PARSE_EOF) { 4032 /* EOF reached */ 4033 return (PARSE_EOF); 4034 } 4035 if (ret != 0) { 4036 ret = -1; 4037 goto err; 4038 } 4039 pstate = action; 4040 break; 4041 } 4042 case action: 4043 { 4044 #ifdef DEBUG_HEAVY 4045 (void) printf("action\n"); 4046 #endif 4047 ret = parse_action(fp, 4048 &act_props->ap[ap_num].act, &leftover); 4049 if (ret != 0) { 4050 ret = -1; 4051 goto err; 4052 } 4053 4054 /* 4055 * Validate action now itself so that we don't 4056 * proceed too much into the bad world. 4057 */ 4058 for (i = 0; action_table[i].string; i++) { 4059 if (strcmp(act_props->ap[ap_num].act, 4060 action_table[i].string) == 0) 4061 break; 4062 } 4063 4064 if (action_table[i].tok_val == TOK_or) { 4065 /* hit an or, go again */ 4066 break; 4067 } 4068 4069 if (action_table[i].string == NULL) { 4070 /* 4071 * If we never read a newline 4072 * character, we don't want 4073 * to print 0. 4074 */ 4075 warnx(gettext("(parsing one command) " 4076 "Invalid action on line %d: %s"), 4077 (linecount == 0) ? 1 : linecount, 4078 act_props->ap[ap_num].act); 4079 return (-1); 4080 } 4081 4082 pstate = prop; 4083 break; 4084 } 4085 case prop: 4086 { 4087 #ifdef DEBUG_HEAVY 4088 (void) printf("prop\n"); 4089 #endif 4090 ret = parse_pattern_or_prop(fp, 4091 act_props->ap[ap_num].prop, &leftover); 4092 if (ret != 0) { 4093 if (ret == PARSE_EOF) { 4094 warnx(gettext("(parsing one command) " 4095 "Missing properties.")); 4096 } 4097 ret = -1; 4098 goto err; 4099 } 4100 4101 if (leftover != NULL) { 4102 /* Accomodate spaces at the end */ 4103 while (*leftover != NULL) { 4104 if (*leftover == BACK_SLASH) { 4105 warnx(gettext("Invalid line " 4106 "continuation character.")); 4107 ret = -1; 4108 goto err; 4109 } 4110 if (*leftover == 'o') { 4111 leftover++; 4112 if (*leftover == 'r') { 4113 leftover++; 4114 ap_num++; 4115 pstate = action; 4116 goto again; 4117 } 4118 } 4119 if (!isspace(*leftover)) { 4120 ret = -1; 4121 goto err; 4122 } 4123 leftover++; 4124 } 4125 return (0); 4126 } 4127 ap_num++; 4128 if (ap_num > MAXARGS) 4129 return (0); 4130 pstate = action; /* or */ 4131 break; 4132 } /* case prop: */ 4133 } /* switch(pstate) */ 4134 4135 again: 4136 if (ap_num > MAXARGS) { 4137 warnx(gettext("Too many actions.")); 4138 return (-1); 4139 } 4140 } /* for(;;) */ 4141 err: 4142 if (ret != 0) { 4143 /* 4144 * If we never read a newline character, we don't want 4145 * to print 0. 4146 */ 4147 warnx(gettext("Error before or at line %d"), 4148 (linecount == 0) ? 1 : linecount); 4149 } 4150 return (ret); 4151 } 4152 4153 /* 4154 * convert an act_propts_t to an ips_conf_t 4155 */ 4156 4157 static int 4158 form_ipsec_conf(act_prop_t *act_props, ips_conf_t *cptr) 4159 { 4160 int i, j, k; 4161 int tok_count = 0; 4162 struct protoent *pent; 4163 boolean_t saddr, daddr, ipsec_aalg, ipsec_ealg, ipsec_eaalg, dir; 4164 boolean_t old_style, new_style, auth_covered, is_no_alg; 4165 boolean_t is_combined_mode; 4166 struct in_addr mask; 4167 int line_no; 4168 int ret; 4169 int ap_num = 0; 4170 int type, code, type_end, code_end; 4171 #ifdef DEBUG_HEAVY 4172 /* 4173 * pattern => act_props->pattern 4174 * action => act_props->ap[].act 4175 * properties => act_props->ap[].prop 4176 */ 4177 (void) printf("\npattern\n------------\n"); 4178 for (i = 0; act_props->pattern[i] != NULL; i++) 4179 (void) printf("%s\n", act_props->pattern[i]); 4180 (void) printf("apz\n----------\n"); 4181 for (j = 0; act_props->ap[j].act != NULL; j++) { 4182 4183 (void) printf("act%d->%s\n", j, act_props->ap[j].act); 4184 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 4185 (void) printf("%dprop%d->%s\n", 4186 j, i, act_props->ap[j].prop[i]); 4187 } 4188 (void) printf("------------\n\n"); 4189 #endif 4190 4191 (void) memset(cptr, 0, sizeof (ips_conf_t)); 4192 saddr = daddr = ipsec_aalg = ipsec_ealg = ipsec_eaalg = dir = B_FALSE; 4193 old_style = new_style = is_no_alg = is_combined_mode = B_FALSE; 4194 /* 4195 * Get the Pattern. NULL pattern is valid. 4196 */ 4197 for (i = 0, line_no = 0; act_props->pattern[i]; i++, line_no++) { 4198 for (j = 0; pattern_table[j].string; j++) { 4199 if (strcmp(act_props->pattern[i], 4200 pattern_table[j].string) == 0) 4201 break; 4202 } 4203 4204 if (pattern_table[j].string == NULL) { 4205 /* 4206 * If we never read a newline character, we don't want 4207 * to print 0. 4208 */ 4209 warnx(gettext("Invalid pattern on line %d: %s"), 4210 (arg_indices[line_no] == 0) ? 1 : 4211 arg_indices[line_no], act_props->pattern[i]); 4212 return (-1); 4213 } 4214 4215 cptr->patt_tok[tok_count++] = pattern_table[j].tok_val; 4216 4217 switch (pattern_table[j].tok_val) { 4218 4219 case TOK_dir: 4220 i++, line_no++; 4221 if (act_props->pattern[i] == NULL) { 4222 error_message(BAD_ERROR, 4223 IPSEC_CONF_IPSEC_DIR, line_no); 4224 return (-1); 4225 } 4226 4227 if (strncmp(act_props->pattern[i], "in", 2) == 0) { 4228 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4229 } else if (strncmp( 4230 act_props->pattern[i], "out", 3) == 0) { 4231 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4232 } else if (strncmp( 4233 act_props->pattern[i], "both", 4) == 0) { 4234 if (old_style) { 4235 error_message(BAD_ERROR, 4236 IPSEC_CONF_IPSEC_DIR, line_no); 4237 return (-1); 4238 } 4239 new_style = B_TRUE; 4240 cptr->ips_dir = 4241 SPD_RULE_FLAG_OUTBOUND | 4242 SPD_RULE_FLAG_INBOUND; 4243 } else { 4244 error_message(BAD_ERROR, 4245 IPSEC_CONF_IPSEC_DIR, line_no); 4246 return (-1); 4247 } 4248 dir = B_TRUE; 4249 break; 4250 4251 case TOK_local: 4252 if (old_style) { 4253 error_message(BAD_ERROR, 4254 IPSEC_CONF_SRC_ADDRESS, line_no); 4255 return (-1); 4256 } 4257 new_style = B_TRUE; 4258 4259 if (saddr) { 4260 error_message(DUP_ERROR, 4261 IPSEC_CONF_SRC_ADDRESS, line_no); 4262 return (-1); 4263 } 4264 /* 4265 * Use this to detect duplicates rather 4266 * than 0 like other cases, because 0 for 4267 * address means INADDR_ANY. 4268 */ 4269 saddr = B_TRUE; 4270 cptr->has_saddr = 1; 4271 /* 4272 * Advance to the string containing 4273 * the address. 4274 */ 4275 i++, line_no++; 4276 if (act_props->pattern[i] == NULL) { 4277 error_message(BAD_ERROR, 4278 IPSEC_CONF_SRC_ADDRESS, line_no); 4279 return (-1); 4280 } 4281 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4282 act_props->pattern[i]) != 0) { 4283 error_message(BAD_ERROR, 4284 IPSEC_CONF_SRC_ADDRESS, line_no); 4285 return (-1); 4286 } 4287 if (!cptr->has_smask) 4288 cptr->has_smask = has_saprefix; 4289 4290 break; 4291 case TOK_remote: 4292 if (old_style) { 4293 error_message(BAD_ERROR, 4294 IPSEC_CONF_DST_ADDRESS, line_no); 4295 return (-1); 4296 } 4297 new_style = B_TRUE; 4298 4299 if (daddr) { 4300 error_message(DUP_ERROR, 4301 IPSEC_CONF_DST_ADDRESS, line_no); 4302 return (-1); 4303 } 4304 /* 4305 * Use this to detect duplicates rather 4306 * than 0 like other cases, because 0 for 4307 * address means INADDR_ANY. 4308 */ 4309 daddr = B_TRUE; 4310 cptr->has_daddr = 1; 4311 /* 4312 * Advance to the string containing 4313 * the address. 4314 */ 4315 i++, line_no++; 4316 if (act_props->pattern[i] == NULL) { 4317 error_message(BAD_ERROR, 4318 IPSEC_CONF_DST_ADDRESS, line_no); 4319 return (-1); 4320 } 4321 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4322 act_props->pattern[i]) != 0) { 4323 error_message(BAD_ERROR, 4324 IPSEC_CONF_DST_ADDRESS, line_no); 4325 return (-1); 4326 } 4327 if (!cptr->has_dmask) 4328 cptr->has_dmask = has_daprefix; 4329 break; 4330 4331 case TOK_saddr: 4332 if (new_style) { 4333 error_message(BAD_ERROR, 4334 IPSEC_CONF_SRC_ADDRESS, line_no); 4335 return (-1); 4336 } 4337 old_style = B_TRUE; 4338 4339 if (saddr) { 4340 error_message(DUP_ERROR, 4341 IPSEC_CONF_SRC_ADDRESS, line_no); 4342 return (-1); 4343 } 4344 /* 4345 * Use this to detect duplicates rather 4346 * than 0 like other cases, because 0 for 4347 * address means INADDR_ANY. 4348 */ 4349 saddr = B_TRUE; 4350 cptr->has_saddr = 1; 4351 /* 4352 * Advance to the string containing 4353 * the address. 4354 */ 4355 i++, line_no++; 4356 if (act_props->pattern[i] == NULL) { 4357 error_message(BAD_ERROR, 4358 IPSEC_CONF_SRC_ADDRESS, line_no); 4359 return (-1); 4360 } 4361 4362 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4363 act_props->pattern[i]) != 0) { 4364 error_message(BAD_ERROR, 4365 IPSEC_CONF_SRC_ADDRESS, line_no); 4366 return (-1); 4367 } 4368 /* shp or bhp? */ 4369 if (!cptr->has_smask) 4370 cptr->has_smask = has_saprefix; 4371 break; 4372 4373 case TOK_daddr: 4374 if (new_style) { 4375 error_message(BAD_ERROR, 4376 IPSEC_CONF_DST_ADDRESS, line_no); 4377 return (-1); 4378 } 4379 old_style = B_TRUE; 4380 4381 if (daddr) { 4382 error_message(DUP_ERROR, 4383 IPSEC_CONF_DST_ADDRESS, line_no); 4384 return (-1); 4385 } 4386 /* 4387 * Use this to detect duplicates rather 4388 * than 0 like other cases, because 0 for 4389 * address means INADDR_ANY. 4390 */ 4391 daddr = B_TRUE; 4392 cptr->has_daddr = 1; 4393 /* 4394 * Advance to the string containing 4395 * the address. 4396 */ 4397 i++, line_no++; 4398 if (act_props->pattern[i] == NULL) { 4399 error_message(BAD_ERROR, 4400 IPSEC_CONF_DST_ADDRESS, line_no); 4401 return (-1); 4402 } 4403 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4404 act_props->pattern[i]) != 0) { 4405 error_message(BAD_ERROR, 4406 IPSEC_CONF_DST_ADDRESS, line_no); 4407 return (-1); 4408 } 4409 if (!cptr->has_dmask) 4410 cptr->has_dmask = has_daprefix; 4411 break; 4412 4413 case TOK_sport: 4414 if (new_style) { 4415 error_message(BAD_ERROR, 4416 IPSEC_CONF_SRC_PORT, line_no); 4417 return (-1); 4418 } 4419 old_style = B_TRUE; 4420 4421 if (cptr->ips_src_port_min != 0) { 4422 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4423 line_no); 4424 return (-1); 4425 } 4426 i++, line_no++; 4427 if (act_props->pattern[i] == NULL) { 4428 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4429 line_no); 4430 return (-1); 4431 } 4432 ret = parse_port(IPSEC_CONF_SRC_PORT, 4433 act_props->pattern[i], cptr); 4434 if (ret != 0) { 4435 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4436 line_no); 4437 return (-1); 4438 } 4439 break; 4440 case TOK_dport: 4441 if (new_style) { 4442 error_message(BAD_ERROR, 4443 IPSEC_CONF_DST_PORT, line_no); 4444 return (-1); 4445 } 4446 old_style = B_TRUE; 4447 4448 if (cptr->ips_dst_port_min != 0) { 4449 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4450 line_no); 4451 return (-1); 4452 } 4453 i++, line_no++; 4454 if (act_props->pattern[i] == NULL) { 4455 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4456 line_no); 4457 return (-1); 4458 } 4459 ret = parse_port(IPSEC_CONF_DST_PORT, 4460 act_props->pattern[i], 4461 cptr); 4462 if (ret != 0) { 4463 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4464 line_no); 4465 return (-1); 4466 } 4467 break; 4468 4469 case TOK_lport: 4470 if (old_style) { 4471 error_message(BAD_ERROR, 4472 IPSEC_CONF_SRC_PORT, line_no); 4473 return (-1); 4474 } 4475 new_style = B_TRUE; 4476 4477 if (cptr->ips_src_port_min != 0) { 4478 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4479 line_no); 4480 return (-1); 4481 } 4482 i++, line_no++; 4483 if (act_props->pattern[i] == NULL) { 4484 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4485 line_no); 4486 return (-1); 4487 } 4488 ret = parse_port(IPSEC_CONF_SRC_PORT, 4489 act_props->pattern[i], 4490 cptr); 4491 if (ret != 0) { 4492 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4493 line_no); 4494 return (-1); 4495 } 4496 break; 4497 4498 case TOK_rport: 4499 if (old_style) { 4500 error_message(BAD_ERROR, 4501 IPSEC_CONF_DST_PORT, line_no); 4502 return (-1); 4503 } 4504 new_style = B_TRUE; 4505 4506 if (cptr->ips_dst_port_min != 0) { 4507 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4508 line_no); 4509 return (-1); 4510 } 4511 i++, line_no++; 4512 if (act_props->pattern[i] == NULL) { 4513 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4514 line_no); 4515 return (-1); 4516 } 4517 ret = parse_port(IPSEC_CONF_DST_PORT, 4518 act_props->pattern[i], 4519 cptr); 4520 if (ret != 0) { 4521 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4522 line_no); 4523 return (-1); 4524 } 4525 break; 4526 4527 case TOK_smask: 4528 if (new_style) { 4529 error_message(BAD_ERROR, 4530 IPSEC_CONF_SRC_MASK, line_no); 4531 return (-1); 4532 } 4533 old_style = B_TRUE; 4534 cptr->has_smask = B_TRUE; 4535 4536 IN6_V4MAPPED_TO_INADDR(&cptr->ips_src_mask_v6, &mask); 4537 if (mask.s_addr != 0) { 4538 error_message(DUP_ERROR, IPSEC_CONF_SRC_MASK, 4539 line_no); 4540 return (-1); 4541 } 4542 i++, line_no++; 4543 if (act_props->pattern[i] == NULL) { 4544 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4545 line_no); 4546 return (-1); 4547 } 4548 ret = parse_mask(IPSEC_CONF_SRC_MASK, 4549 act_props->pattern[i], 4550 cptr); 4551 if (ret != 0) { 4552 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4553 line_no); 4554 return (-1); 4555 } 4556 break; 4557 case TOK_dmask: 4558 if (new_style) { 4559 error_message(BAD_ERROR, 4560 IPSEC_CONF_DST_MASK, line_no); 4561 return (-1); 4562 } 4563 old_style = B_TRUE; 4564 cptr->has_dmask = B_TRUE; 4565 4566 IN6_V4MAPPED_TO_INADDR(&cptr->ips_dst_mask_v6, &mask); 4567 if (mask.s_addr != 0) { 4568 error_message(DUP_ERROR, IPSEC_CONF_DST_MASK, 4569 line_no); 4570 return (-1); 4571 } 4572 i++, line_no++; 4573 if (act_props->pattern[i] == NULL) { 4574 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4575 line_no); 4576 return (-1); 4577 } 4578 ret = parse_mask(IPSEC_CONF_DST_MASK, 4579 act_props->pattern[i], 4580 cptr); 4581 if (ret != 0) { 4582 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4583 line_no); 4584 return (-1); 4585 } 4586 break; 4587 case TOK_ulp: 4588 if (cptr->ips_ulp_prot != 0) { 4589 error_message(DUP_ERROR, 4590 IPSEC_CONF_ULP, line_no); 4591 return (-1); 4592 } 4593 i++, line_no++; 4594 if (act_props->pattern[i] == NULL) { 4595 error_message(BAD_ERROR, 4596 IPSEC_CONF_ULP, line_no); 4597 return (-1); 4598 } 4599 pent = getprotobyname(act_props->pattern[i]); 4600 if (pent == NULL) { 4601 int ulp; 4602 ulp = parse_int(act_props->pattern[i]); 4603 if (ulp == -1) { 4604 error_message(BAD_ERROR, 4605 IPSEC_CONF_ULP, line_no); 4606 return (-1); 4607 } 4608 cptr->ips_ulp_prot = ulp; 4609 } else { 4610 cptr->ips_ulp_prot = pent->p_proto; 4611 } 4612 break; 4613 case TOK_type: 4614 if (cptr->has_type) { 4615 error_message(DUP_ERROR, 4616 IPSEC_CONF_ICMP_TYPE, line_no); 4617 return (-1); 4618 } 4619 4620 i++, line_no++; 4621 type = parse_type_code(act_props->pattern[i], 4622 icmp_type_table); 4623 4624 if (type > 65536 || type < 0) { 4625 error_message(BAD_ERROR, 4626 IPSEC_CONF_ICMP_TYPE, line_no); 4627 return (-1); 4628 } 4629 4630 type_end = type / 256; 4631 type = type % 256; 4632 4633 if (type_end < type) 4634 type_end = type; 4635 4636 cptr->has_type = 1; 4637 cptr->ips_icmp_type = (uint8_t)type; 4638 cptr->ips_icmp_type_end = (uint8_t)type_end; 4639 break; 4640 case TOK_code: 4641 if (!cptr->has_type) { 4642 error_message(BAD_ERROR, 4643 IPSEC_CONF_ICMP_CODE, line_no); 4644 return (-1); 4645 } 4646 4647 if (cptr->has_code) { 4648 error_message(DUP_ERROR, 4649 IPSEC_CONF_ICMP_CODE, line_no); 4650 return (-1); 4651 } 4652 4653 i++, line_no++; 4654 4655 code = parse_type_code(act_props->pattern[i], 4656 icmp_code_table); 4657 if (type > 65536 || type < 0) { 4658 error_message(BAD_ERROR, 4659 IPSEC_CONF_ICMP_CODE, line_no); 4660 return (-1); 4661 } 4662 code_end = code / 256; 4663 code = code % 256; 4664 4665 if (code_end < code) 4666 code_end = code; 4667 4668 cptr->has_code = 1; 4669 cptr->ips_icmp_code = (uint8_t)code; 4670 cptr->ips_icmp_code_end = (uint8_t)code_end; 4671 break; 4672 case TOK_tunnel: 4673 if (cptr->has_tunnel == 1) { 4674 error_message(BAD_ERROR, 4675 IPSEC_CONF_TUNNEL, line_no); 4676 return (-1); 4677 } 4678 i++, line_no++; 4679 if (act_props->pattern[i] == NULL) { 4680 error_message(BAD_ERROR, 4681 IPSEC_CONF_TUNNEL, line_no); 4682 return (-1); 4683 } 4684 4685 if (strlcpy(tunif, act_props->pattern[i], 4686 TUNNAMEMAXLEN) >= TUNNAMEMAXLEN) { 4687 error_message(BAD_ERROR, 4688 IPSEC_CONF_TUNNEL, line_no); 4689 return (-1); 4690 } 4691 cptr->has_tunnel = 1; 4692 break; 4693 case TOK_negotiate: 4694 if (cptr->has_negotiate == 1) { 4695 error_message(BAD_ERROR, 4696 IPSEC_CONF_NEGOTIATE, line_no); 4697 return (-1); 4698 } 4699 i++, line_no++; 4700 if (act_props->pattern[i] == NULL) { 4701 error_message(BAD_ERROR, 4702 IPSEC_CONF_NEGOTIATE, line_no); 4703 return (-1); 4704 } 4705 4706 if (strncmp(act_props->pattern[i], "tunnel", 6) == 0) { 4707 cptr->ips_tunnel = B_TRUE; 4708 } else if (strncmp( 4709 act_props->pattern[i], "transport", 9) != 0) { 4710 error_message(BAD_ERROR, 4711 IPSEC_CONF_NEGOTIATE, line_no); 4712 return (-1); 4713 } 4714 cptr->has_negotiate = 1; 4715 break; 4716 } 4717 4718 } 4719 4720 /* Sanity check that certain tokens occur together */ 4721 if (cptr->has_tunnel + cptr->has_negotiate == 1) { 4722 if (cptr->has_negotiate == 0) { 4723 error_message(REQ_ERROR, IPSEC_CONF_NEGOTIATE, line_no); 4724 } else { 4725 error_message(REQ_ERROR, IPSEC_CONF_TUNNEL, line_no); 4726 } 4727 errx(1, gettext( 4728 "tunnel and negotiate tokens must occur together")); 4729 return (-1); 4730 } 4731 4732 /* 4733 * Get the actions. 4734 */ 4735 4736 for (ap_num = 0; act_props->ap[ap_num].act != NULL; ap_num++) { 4737 ips_act_props_t *iap; 4738 4739 if (ap_num > 0) { 4740 /* or's only with new style */ 4741 if (old_style) { 4742 (void) printf("%s\n", gettext( 4743 "or's only with new style")); 4744 return (-1); 4745 } 4746 new_style = B_TRUE; 4747 } 4748 4749 ipsec_aalg = ipsec_ealg = ipsec_eaalg = auth_covered = B_FALSE; 4750 tok_count = 0; 4751 4752 for (k = 0; action_table[k].string; k++) { 4753 if (strcmp(act_props->ap[ap_num].act, 4754 action_table[k].string) == 0) 4755 break; 4756 } 4757 /* 4758 * The following thing should never happen as 4759 * we have already tested for its validity in parse. 4760 */ 4761 if (action_table[k].string == NULL) { 4762 warnx(gettext("(form act)Invalid action on line " 4763 "%d: %s"), (arg_indices[line_no] == 0) ? 1 : 4764 arg_indices[line_no], 4765 act_props->ap[ap_num].act); 4766 warnx("%s", act_props->ap[ap_num].act); 4767 return (-1); 4768 } 4769 4770 /* we have a good action alloc an iap */ 4771 iap = alloc_iap(cptr); 4772 4773 iap->iap_action = action_table[k].value; 4774 iap->iap_act_tok = action_table[k].tok_val; 4775 4776 switch (action_table[k].tok_val) { 4777 case TOK_apply: 4778 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4779 break; 4780 case TOK_permit: 4781 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4782 break; 4783 case TOK_ipsec: 4784 if (old_style) { 4785 /* Using saddr/daddr with ipsec action. */ 4786 if (!dir) { 4787 /* No direction specified */ 4788 error_message(REQ_ERROR, 4789 IPSEC_CONF_IPSEC_DIR, line_no); 4790 return (-1); 4791 } 4792 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 4793 /* 4794 * Need to swap addresses if 4795 * 'dir in' or translation to 4796 * laddr/raddr will be incorrect. 4797 */ 4798 cptr->swap = 1; 4799 } 4800 if (!dir) 4801 cptr->ips_dir = 4802 SPD_RULE_FLAG_INBOUND 4803 |SPD_RULE_FLAG_OUTBOUND; 4804 break; 4805 case TOK_bypass: 4806 case TOK_drop: 4807 is_no_alg = B_TRUE; 4808 break; 4809 } 4810 4811 line_no++; 4812 /* 4813 * Get the properties. NULL properties is not valid. 4814 * Later checks will catch it. 4815 */ 4816 for (i = 0; act_props->ap[ap_num].prop[i]; i++, line_no++) { 4817 for (j = 0; property_table[j].string; j++) { 4818 if (strcmp(act_props->ap[ap_num].prop[i], 4819 property_table[j].string) == 0) { 4820 break; 4821 } 4822 } 4823 if (property_table[j].string == NULL) { 4824 warnx(gettext("Invalid properties on line " 4825 "%d: %s"), 4826 (arg_indices[line_no] == 0) ? 4827 1 : arg_indices[line_no], 4828 act_props->ap[ap_num].prop[i]); 4829 return (-1); 4830 } 4831 4832 iap->iap_attr_tok[tok_count++] 4833 = property_table[j].value; 4834 4835 switch (property_table[j].value) { 4836 case SPD_ATTR_AH_AUTH: 4837 if (ipsec_aalg) { 4838 error_message(DUP_ERROR, 4839 IPSEC_CONF_IPSEC_AALGS, line_no); 4840 return (-1); 4841 } 4842 i++, line_no++; 4843 if (act_props->ap[ap_num].prop[i] == NULL) { 4844 error_message(BAD_ERROR, 4845 IPSEC_CONF_IPSEC_AALGS, line_no); 4846 return (-1); 4847 } 4848 ret = parse_ipsec_alg( 4849 act_props->ap[ap_num].prop[i], 4850 iap, SPD_ATTR_AH_AUTH); 4851 if (ret == -2) { 4852 /* "none" - ignore */ 4853 break; 4854 } 4855 if (ret != 0) { 4856 error_message(BAD_ERROR, 4857 IPSEC_CONF_IPSEC_AALGS, line_no); 4858 return (-1); 4859 } 4860 ipsec_aalg = B_TRUE; 4861 auth_covered = B_TRUE; 4862 break; 4863 case SPD_ATTR_ESP_ENCR: 4864 /* 4865 * If this option was not given 4866 * and encr_auth_algs was given, 4867 * we provide null-encryption. We do the 4868 * setting after we parse all the options. 4869 */ 4870 if (ipsec_ealg) { 4871 error_message(DUP_ERROR, 4872 IPSEC_CONF_IPSEC_EALGS, line_no); 4873 return (-1); 4874 } 4875 i++, line_no++; 4876 if (act_props->ap[ap_num].prop[i] == NULL) { 4877 error_message(BAD_ERROR, 4878 IPSEC_CONF_IPSEC_EALGS, line_no); 4879 return (-1); 4880 } 4881 ret = parse_ipsec_alg( 4882 act_props->ap[ap_num].prop[i], 4883 iap, SPD_ATTR_ESP_ENCR); 4884 if (ret == -2) { 4885 /* "none" - ignore */ 4886 break; 4887 } 4888 if (ret != 0) { 4889 error_message(BAD_ERROR, 4890 IPSEC_CONF_IPSEC_EALGS, line_no); 4891 return (-1); 4892 } 4893 is_combined_mode = combined_mode(iap); 4894 ipsec_ealg = B_TRUE; 4895 break; 4896 case SPD_ATTR_ESP_AUTH: 4897 /* 4898 * If this option was not given and encr_algs 4899 * option was given, we still pass a default 4900 * value in ipsc_esp_auth_algs. This is to 4901 * encourage the use of authentication with 4902 * ESP. 4903 */ 4904 if (ipsec_eaalg) { 4905 error_message(DUP_ERROR, 4906 IPSEC_CONF_IPSEC_EAALGS, line_no); 4907 return (-1); 4908 } 4909 i++, line_no++; 4910 if (act_props->ap[ap_num].prop[i] == NULL) { 4911 error_message(BAD_ERROR, 4912 IPSEC_CONF_IPSEC_EAALGS, line_no); 4913 return (-1); 4914 } 4915 ret = parse_ipsec_alg( 4916 act_props->ap[ap_num].prop[i], 4917 iap, SPD_ATTR_ESP_AUTH); 4918 if (ret == -2) { 4919 /* "none" - ignore */ 4920 break; 4921 } 4922 if (ret != 0) { 4923 error_message(BAD_ERROR, 4924 IPSEC_CONF_IPSEC_EAALGS, line_no); 4925 return (-1); 4926 } 4927 ipsec_eaalg = B_TRUE; 4928 auth_covered = B_TRUE; 4929 break; 4930 case IPS_SA: 4931 i++, line_no++; 4932 if (act_props->ap[ap_num].prop[i] == NULL) { 4933 error_message(BAD_ERROR, 4934 IPSEC_CONF_IPSEC_SA, line_no); 4935 return (-1); 4936 } 4937 4938 if (strcmp(act_props->ap[ap_num].prop[i], 4939 "unique") == 0) { 4940 iap->iap_attr |= SPD_APPLY_UNIQUE; 4941 } else if (strcmp(act_props->ap[ap_num].prop[i], 4942 "shared") != 0) { 4943 /* "shared" is default. */ 4944 error_message(BAD_ERROR, 4945 IPSEC_CONF_IPSEC_SA, line_no); 4946 return (-1); 4947 } 4948 4949 break; 4950 case IPS_DIR: 4951 if (dir) { 4952 error_message(DUP_ERROR, 4953 IPSEC_CONF_IPSEC_DIR, line_no); 4954 return (-1); 4955 } 4956 if (new_style) { 4957 error_message(BAD_ERROR, 4958 IPSEC_CONF_IPSEC_DIR, line_no); 4959 return (-1); 4960 } 4961 old_style = B_TRUE; 4962 dir = B_TRUE; 4963 i++, line_no++; 4964 if (act_props->ap[ap_num].prop[i] == NULL) { 4965 error_message(BAD_ERROR, 4966 IPSEC_CONF_IPSEC_DIR, line_no); 4967 return (-1); 4968 } 4969 if (strcmp(act_props->ap[ap_num].prop[i], 4970 "out") == 0) { 4971 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4972 } else if (strcmp(act_props->ap[ap_num].prop[i], 4973 "in") == 0) { 4974 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4975 } else { 4976 error_message(BAD_ERROR, 4977 IPSEC_CONF_IPSEC_DIR, line_no); 4978 return (-1); 4979 } 4980 if ((cptr->ips_dir & SPD_RULE_FLAG_INBOUND) && 4981 iap->iap_act_tok == TOK_apply) { 4982 warnx(gettext("Direction" 4983 " in conflict with action")); 4984 return (-1); 4985 } 4986 if ((cptr->ips_dir & SPD_RULE_FLAG_OUTBOUND) && 4987 iap->iap_act_tok == TOK_permit) { 4988 warnx(gettext("Direction" 4989 "in conflict with action")); 4990 return (-1); 4991 } 4992 4993 break; 4994 } 4995 } 4996 4997 if (is_combined_mode) { 4998 if (ipsec_eaalg) { 4999 warnx(gettext("ERROR: Rule on line %d: " 5000 "Combined mode and esp authentication not " 5001 "supported together."), 5002 arg_indices[line_no] == 0 ? 1 : 5003 arg_indices[line_no]); 5004 return (-1); 5005 } 5006 auth_covered = B_TRUE; 5007 } 5008 /* Warn here about no authentication! */ 5009 if (!auth_covered && !is_no_alg) { 5010 warnx(gettext("DANGER: Rule on line %d " 5011 "has encryption with no authentication."), 5012 arg_indices[line_no] == 0 ? 1 : 5013 arg_indices[line_no]); 5014 } 5015 5016 if (!ipsec_ealg && ipsec_eaalg) { 5017 /* 5018 * If the user has specified the auth alg to be used 5019 * with encryption and did not provide a encryption 5020 * algorithm, provide null encryption. 5021 */ 5022 iap->iap_eencr.alg_id = SADB_EALG_NULL; 5023 ipsec_ealg = B_TRUE; 5024 } 5025 5026 /* Set the level of IPSEC protection we want */ 5027 if (ipsec_aalg && (ipsec_ealg || ipsec_eaalg)) { 5028 iap->iap_attr |= SPD_APPLY_AH|SPD_APPLY_ESP; 5029 } else if (ipsec_aalg) { 5030 iap->iap_attr |= SPD_APPLY_AH; 5031 } else if (ipsec_ealg || ipsec_eaalg) { 5032 iap->iap_attr |= SPD_APPLY_ESP; 5033 } 5034 5035 /* convert src/dst to local/remote */ 5036 if (!new_style) { 5037 switch (cptr->ips_acts->iap_act_tok) { 5038 case TOK_apply: 5039 /* outbound */ 5040 /* src=local, dst=remote */ 5041 /* this is ok. */ 5042 break; 5043 5044 case TOK_permit: 5045 /* inbound */ 5046 /* src=remote, dst=local */ 5047 /* switch */ 5048 cptr->swap = 1; 5049 break; 5050 case TOK_bypass: 5051 case TOK_drop: 5052 /* check the direction for what to do */ 5053 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 5054 cptr->swap = 1; 5055 break; 5056 default: 5057 break; 5058 } 5059 } 5060 /* Validate the properties */ 5061 if (ret = validate_properties(iap, dir, 5062 (ipsec_aalg || ipsec_ealg || ipsec_eaalg))) { 5063 return (ret); 5064 } 5065 } 5066 5067 return (0); 5068 5069 } 5070 5071 static int 5072 print_cmd_buf(FILE *fp, int error) 5073 { 5074 *(cbuf + cbuf_offset) = '\0'; 5075 5076 if (fp == stderr) { 5077 if (error != EEXIST) { 5078 warnx(gettext("Malformed command (fatal):\n%s"), cbuf); 5079 return (0); 5080 } 5081 if (ipsecconf_qflag) { 5082 return (0); 5083 } 5084 warnx(gettext("Duplicate policy entry (ignored):\n%s"), cbuf); 5085 } else { 5086 if (fprintf(fp, "%s", cbuf) == -1) { 5087 warn("fprintf"); 5088 return (-1); 5089 } 5090 } 5091 5092 return (0); 5093 } 5094 5095 #ifdef DEBUG 5096 5097 static uchar_t * 5098 addr_ptr(int isv4, struct in6_addr *addr6, struct in_addr *addr4) 5099 { 5100 if (isv4) { 5101 IN6_V4MAPPED_TO_INADDR(addr6, addr4); 5102 return ((uchar_t *)&addr4->s_addr); 5103 } else { 5104 return ((uchar_t *)&addr6->s6_addr); 5105 } 5106 } 5107 5108 static void 5109 dump_algreq(const char *tag, algreq_t *alg) 5110 { 5111 (void) printf("%s algid %d, bits %d..%d\n", 5112 tag, alg->alg_id, alg->alg_minbits, alg->alg_maxbits); 5113 } 5114 5115 static void 5116 dump_conf(ips_conf_t *conf) 5117 { 5118 boolean_t isv4 = conf->ips_isv4; 5119 struct in_addr addr; 5120 char buf[INET6_ADDRSTRLEN]; 5121 int af; 5122 ips_act_props_t *iap = conf->ips_acts; 5123 5124 af = isv4 ? AF_INET : AF_INET6; 5125 5126 (void) printf("Source Addr is %s\n", 5127 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_addr_v6, &addr), 5128 buf, INET6_ADDRSTRLEN)); 5129 5130 (void) printf("Dest Addr is %s\n", 5131 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_addr_v6, &addr), 5132 buf, INET6_ADDRSTRLEN)); 5133 5134 (void) printf("Source Mask is %s\n", 5135 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_mask_v6, &addr), 5136 buf, INET6_ADDRSTRLEN)); 5137 5138 (void) printf("Dest Mask is %s\n", 5139 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_mask_v6, &addr), 5140 buf, INET6_ADDRSTRLEN)); 5141 5142 (void) printf("Source port %d\n", ntohs(conf->ips_src_port_min)); 5143 (void) printf("Dest port %d\n", ntohs(conf->ips_dst_port_min)); 5144 (void) printf("ULP %d\n", conf->ips_ulp_prot); 5145 5146 (void) printf("ICMP type %d-%d code %d-%d", conf->ips_icmp_type, 5147 conf->ips_icmp_type_end, 5148 conf->ips_icmp_code, 5149 conf->ips_icmp_code_end); 5150 5151 while (iap != NULL) { 5152 (void) printf("------------------------------------\n"); 5153 (void) printf("IPsec act is %d\n", iap->iap_action); 5154 (void) printf("IPsec attr is %d\n", iap->iap_attr); 5155 dump_algreq("AH authentication", &iap->iap_aauth); 5156 dump_algreq("ESP authentication", &iap->iap_eauth); 5157 dump_algreq("ESP encryption", &iap->iap_eencr); 5158 (void) printf("------------------------------------\n"); 5159 iap = iap->iap_next; 5160 } 5161 5162 (void) fflush(stdout); 5163 } 5164 #endif /* DEBUG */ 5165 5166 5167 static int 5168 ipsec_conf_add(boolean_t just_check, boolean_t smf_managed) 5169 { 5170 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5171 ips_conf_t conf; 5172 FILE *fp, *policy_fp; 5173 int ret, flushret, i, j, diag, num_rules, good_rules; 5174 char *warning = gettext( 5175 "\tWARNING : New policy entries that are being added may\n " 5176 "\taffect the existing connections. Existing connections\n" 5177 "\tthat are not subjected to policy constraints, may be\n" 5178 "\tsubjected to policy constraints because of the new\n" 5179 "\tpolicy. This can disrupt the communication of the\n" 5180 "\texisting connections.\n\n"); 5181 5182 boolean_t first_time = B_TRUE; 5183 num_rules = 0; 5184 good_rules = 0; 5185 5186 if (act_props == NULL) { 5187 warn(gettext("memory")); 5188 return (-1); 5189 } 5190 5191 if (strcmp(filename, "-") == 0) 5192 fp = stdin; 5193 else 5194 fp = fopen(filename, "r"); 5195 5196 /* 5197 * Treat the non-existence of a policy file as a special 5198 * case when ipsecconf is being managed by smf(5). 5199 * The assumption is the administrator has not yet 5200 * created a policy file, this should not force the service 5201 * into maintenance mode. 5202 */ 5203 5204 if (fp == NULL) { 5205 if (smf_managed) { 5206 (void) fprintf(stdout, gettext( 5207 "Policy configuration file (%s) does not exist.\n" 5208 "IPsec policy not configured.\n"), filename); 5209 return (0); 5210 } 5211 warn(gettext("%s : Policy config file cannot be opened"), 5212 filename); 5213 usage(); 5214 return (-1); 5215 } 5216 /* 5217 * This will create the file if it does not exist. 5218 * Make sure the umask is right. 5219 */ 5220 (void) umask(0022); 5221 policy_fp = fopen(POLICY_CONF_FILE, "a"); 5222 if (policy_fp == NULL) { 5223 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5224 return (-1); 5225 } 5226 5227 /* 5228 * Pattern, action, and properties are allocated in 5229 * parse_pattern_or_prop and in parse_action (called by 5230 * parse_one) as we parse arguments. 5231 */ 5232 while ((ret = parse_one(fp, act_props)) != PARSE_EOF) { 5233 num_rules++; 5234 if (ret != 0) { 5235 (void) print_cmd_buf(stderr, NOERROR); 5236 continue; 5237 } 5238 5239 /* 5240 * If there is no action and parse returned success, 5241 * it means that there is nothing to add. 5242 */ 5243 if (act_props->pattern[0] == NULL && 5244 act_props->ap[0].act == NULL) 5245 break; 5246 5247 ret = form_ipsec_conf(act_props, &conf); 5248 if (ret != 0) { 5249 warnx(gettext("form_ipsec_conf error")); 5250 (void) print_cmd_buf(stderr, NOERROR); 5251 /* Reset globals before trying the next rule. */ 5252 if (shp != NULL) { 5253 freehostent(shp); 5254 shp = NULL; 5255 } 5256 if (dhp != NULL) { 5257 freehostent(dhp); 5258 dhp = NULL; 5259 } 5260 splen = 0; 5261 dplen = 0; 5262 continue; 5263 } 5264 5265 good_rules++; 5266 5267 if (first_time) { 5268 /* 5269 * Time to assume that there are valid policy entries. 5270 * If the IPsec kernel modules are not loaded this 5271 * will load them now. 5272 */ 5273 first_time = B_FALSE; 5274 fetch_algorithms(); 5275 ipsec_conf_admin(SPD_CLONE); 5276 } 5277 5278 /* 5279 * shp, dhp, splen, and dplen are globals set by 5280 * form_ipsec_conf() while parsing the addresses. 5281 */ 5282 if (shp == NULL && dhp == NULL) { 5283 switch (do_port_adds(&conf)) { 5284 case 0: 5285 /* no error */ 5286 break; 5287 case EEXIST: 5288 /* duplicate entries, continue adds */ 5289 (void) print_cmd_buf(stderr, EEXIST); 5290 goto next; 5291 default: 5292 /* other error, bail */ 5293 ret = -1; 5294 goto bail; 5295 } 5296 } else { 5297 ret = do_address_adds(&conf, &diag); 5298 switch (ret) { 5299 case 0: 5300 /* no error. */ 5301 break; 5302 case EEXIST: 5303 (void) print_cmd_buf(stderr, EEXIST); 5304 goto next; 5305 case EBUSY: 5306 warnx(gettext( 5307 "Can't set mask and /NN prefix.")); 5308 ret = -1; 5309 break; 5310 case ENOENT: 5311 warnx(gettext("Cannot find tunnel " 5312 "interface %s."), interface_name); 5313 ret = -1; 5314 break; 5315 case EINVAL: 5316 /* 5317 * PF_POLICY didn't like what we sent. We 5318 * can't check all input up here, but we 5319 * do in-kernel. 5320 */ 5321 warnx(gettext("PF_POLICY invalid input:\n\t%s"), 5322 spdsock_diag(diag)); 5323 break; 5324 case EOPNOTSUPP: 5325 warnx(gettext("Can't set /NN" 5326 " prefix on multi-host name.")); 5327 ret = -1; 5328 break; 5329 case ERANGE: 5330 warnx(gettext("/NN prefix is too big!")); 5331 ret = -1; 5332 break; 5333 case ESRCH: 5334 warnx(gettext("No matching IPv4 or " 5335 "IPv6 saddr/daddr pairs")); 5336 ret = -1; 5337 break; 5338 default: 5339 /* Should never get here. */ 5340 errno = ret; 5341 warn(gettext("Misc. error")); 5342 ret = -1; 5343 } 5344 if (ret == -1) 5345 goto bail; 5346 } 5347 5348 /* 5349 * Go ahead and add policy entries to config file. 5350 * The # should help re-using the ipsecpolicy.conf 5351 * for input again as # will be treated as comment. 5352 */ 5353 if (fprintf(policy_fp, "%s %lld \n", INDEX_TAG, 5354 conf.ips_policy_index) == -1) { 5355 warn("fprintf"); 5356 warnx(gettext("Addition incomplete, Please " 5357 "flush all the entries and re-configure :")); 5358 reconfigure(); 5359 ret = -1; 5360 break; 5361 } 5362 if (print_cmd_buf(policy_fp, NOERROR) == -1) { 5363 warnx(gettext("Addition incomplete. Please " 5364 "flush all the entries and re-configure :")); 5365 reconfigure(); 5366 ret = -1; 5367 break; 5368 } 5369 /* 5370 * We add one newline by default to separate out the 5371 * entries. If the last character is not a newline, we 5372 * insert a newline for free. This makes sure that all 5373 * entries look consistent in the file. 5374 */ 5375 if (*(cbuf + cbuf_offset - 1) == '\n') { 5376 if (fprintf(policy_fp, "\n") == -1) { 5377 warn("fprintf"); 5378 warnx(gettext("Addition incomplete. " 5379 "Please flush all the entries and " 5380 "re-configure :")); 5381 reconfigure(); 5382 ret = -1; 5383 break; 5384 } 5385 } else { 5386 if (fprintf(policy_fp, "\n\n") == -1) { 5387 warn("fprintf"); 5388 warnx(gettext("Addition incomplete. " 5389 "Please flush all the entries and " 5390 "re-configure :")); 5391 reconfigure(); 5392 ret = -1; 5393 break; 5394 } 5395 } 5396 next: 5397 /* 5398 * Make sure this gets to the disk before 5399 * we parse the next entry. 5400 */ 5401 (void) fflush(policy_fp); 5402 for (i = 0; act_props->pattern[i] != NULL; i++) 5403 free(act_props->pattern[i]); 5404 for (j = 0; act_props->ap[j].act != NULL; j++) { 5405 free(act_props->ap[j].act); 5406 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5407 free(act_props->ap[j].prop[i]); 5408 } 5409 } 5410 if (ret == PARSE_EOF) 5411 ret = 0; /* Not an error */ 5412 bail: 5413 if (ret == -1) { 5414 (void) print_cmd_buf(stderr, EINVAL); 5415 for (i = 0; act_props->pattern[i] != NULL; i++) 5416 free(act_props->pattern[i]); 5417 for (j = 0; act_props->ap[j].act != NULL; j++) { 5418 free(act_props->ap[j].act); 5419 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5420 free(act_props->ap[j].prop[i]); 5421 } 5422 } 5423 #ifdef DEBUG_HEAVY 5424 (void) printf("ipsec_conf_add: ret val = %d\n", ret); 5425 (void) fflush(stdout); 5426 #endif 5427 if (num_rules == 0 && ret == 0) { 5428 nuke_adds(); 5429 (void) restore_all_signals(); 5430 (void) unlock(lfd); 5431 EXIT_OK("Policy file does not contain any valid rules."); 5432 } 5433 if (num_rules != good_rules) { 5434 /* This is an error */ 5435 nuke_adds(); 5436 (void) restore_all_signals(); 5437 (void) unlock(lfd); 5438 EXIT_BADCONFIG2("%d policy rule(s) contained errors.", 5439 num_rules - good_rules); 5440 } 5441 /* looks good, flip it in */ 5442 if (ret == 0 && !just_check) { 5443 if (!ipsecconf_qflag) { 5444 (void) printf("%s", warning); 5445 } 5446 if (smf_managed) 5447 warnx(gettext("%d policy rules added."), good_rules); 5448 ipsec_conf_admin(SPD_FLIP); 5449 } else { 5450 nuke_adds(); 5451 if (just_check) { 5452 (void) fprintf(stdout, gettext("IPsec configuration " 5453 "does not contain any errors.\n")); 5454 (void) fprintf(stdout, gettext( 5455 "IPsec policy was not modified.\n")); 5456 (void) fflush(stdout); 5457 } 5458 } 5459 flushret = ipsec_conf_flush(SPD_STANDBY); 5460 if (flushret != 0) 5461 return (flushret); 5462 return (ret); 5463 } 5464 5465 5466 static int 5467 ipsec_conf_sub() 5468 { 5469 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5470 FILE *remove_fp, *policy_fp; 5471 char rbuf[MAXLEN], pbuf[MAXLEN], /* remove buffer, and policy buffer */ 5472 *warning = gettext( 5473 "\tWARNING: Policy entries that are being removed may\n" 5474 "\taffect the existing connections. Existing connections\n" 5475 "\tthat are subjected to policy constraints may no longer\n" 5476 "\tbe subjected to policy contraints because of its\n" 5477 "\tremoval. This can compromise security, and disrupt\n" 5478 "\tthe communication of the existing connection.\n" 5479 "\tConnections that are latched will remain unaffected\n" 5480 "\tuntil they close.\n"); 5481 int ret = 0; 5482 int index_len, pindex = 0; /* init value in case of pfile error */ 5483 5484 if (act_props == NULL) { 5485 warn(gettext("memory")); 5486 return (-1); 5487 } 5488 5489 /* clone into standby DB */ 5490 (void) ipsec_conf_admin(SPD_CLONE); 5491 5492 if (strcmp(filename, "-") == 0) 5493 remove_fp = stdin; 5494 else 5495 remove_fp = fopen(filename, "r"); 5496 5497 if (remove_fp == NULL) { 5498 warn(gettext("%s : Input file cannot be opened"), filename); 5499 usage(); 5500 free(act_props); 5501 return (-1); 5502 } 5503 5504 /* open policy file so we can locate the correct policy */ 5505 (void) umask(0022); /* in case it gets created! */ 5506 policy_fp = fopen(POLICY_CONF_FILE, "r+"); 5507 if (policy_fp == NULL) { 5508 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5509 (void) fclose(remove_fp); 5510 free(act_props); 5511 return (-1); 5512 } 5513 5514 /* don't print the warning if we're in q[uiet] mode */ 5515 if (!ipsecconf_qflag) 5516 (void) printf("%s", warning); 5517 5518 /* this bit is done primarily so we can read what we write */ 5519 index_len = strlen(INDEX_TAG); 5520 5521 /* 5522 * We want to look for the policy in rbuf in the policy file. 5523 * Go through the list of policies to remove, locating each one. 5524 */ 5525 while (fgets(rbuf, MAXLEN, remove_fp) != NULL) { 5526 char *buf; 5527 int offset, prev_offset, prev_prev_offset, nlines; 5528 fpos_t ipos; 5529 int pbuf_len = 0; 5530 char *tmp; 5531 /* skip blanks here (so we don't need to do it below)! */ 5532 for (tmp = rbuf; (*tmp != '\0') && isspace(*tmp); ) 5533 tmp++; 5534 5535 if (*tmp == '\0') 5536 continue; /* while(); */ 5537 5538 /* skip the INDEX_TAG lines in the remove buffer */ 5539 if (strncasecmp(rbuf, INDEX_TAG, index_len) == 0) 5540 continue; 5541 5542 /* skip commented lines */ 5543 if (*tmp == '#') 5544 continue; /* while(); */ 5545 5546 /* 5547 * We start by presuming only good policies are in the pfile, 5548 * and so only good policies from the rfile will match them. 5549 * ipsec_conf_del ensures this later by calling parse_one() on 5550 * pfile before it deletes the entry. 5551 */ 5552 for (offset = prev_offset = prev_prev_offset = 0; 5553 fgets(pbuf, MAXLEN, policy_fp) != NULL; 5554 offset += pbuf_len) { 5555 prev_offset = offset; 5556 pbuf_len = strlen(pbuf); 5557 5558 /* skip blank lines which seperate policy entries */ 5559 if (pbuf[0] == '\n') 5560 continue; 5561 5562 /* if we found an index, save it */ 5563 if (strncasecmp(pbuf, INDEX_TAG, index_len) == 0) { 5564 buf = pbuf + index_len; 5565 buf++; 5566 if ((pindex = parse_index(buf, NULL)) == -1) { 5567 /* bad index, we can't continue */ 5568 warnx(gettext( 5569 "Invalid index in the file")); 5570 (void) fclose(remove_fp); 5571 (void) fclose(policy_fp); 5572 free(act_props); 5573 return (-1); 5574 } 5575 5576 /* save this position in case it's the one */ 5577 if (fgetpos(policy_fp, &ipos) != 0) { 5578 (void) fclose(remove_fp); 5579 (void) fclose(policy_fp); 5580 free(act_props); 5581 return (-1); 5582 } 5583 } 5584 5585 /* Does pbuf contain the remove policy? */ 5586 if (strncasecmp(rbuf, pbuf, pbuf_len) == 0) { 5587 /* we found the one to remove! */ 5588 if (pindex == 0) { 5589 warnx(gettext("Didn't find a valid " 5590 "index for policy")); 5591 (void) fclose(remove_fp); 5592 (void) fclose(policy_fp); 5593 free(act_props); 5594 return (-1); 5595 } 5596 5597 /* off it - back up to the last INDEX! */ 5598 if (fsetpos(policy_fp, &ipos) != 0) { 5599 (void) fclose(remove_fp); 5600 (void) fclose(policy_fp); 5601 free(act_props); 5602 return (-1); 5603 } 5604 5605 /* parse_one sets linecount = #lines to off */ 5606 if (parse_one(policy_fp, act_props) == -1) { 5607 warnx(gettext("Invalid policy entry " 5608 "in the file")); 5609 (void) fclose(remove_fp); 5610 (void) fclose(policy_fp); 5611 free(act_props); 5612 return (-1); 5613 } 5614 5615 nlines = linecount + 2; 5616 goto delete; 5617 } 5618 /* 5619 * When we find a match, we want to pass the offset 5620 * of the line that is before it - the INDEX_TAG line. 5621 */ 5622 prev_prev_offset = prev_offset; 5623 } 5624 /* Didn't find a match - look at the next remove policy */ 5625 continue; /* while(); */ 5626 5627 delete: 5628 (void) fclose(policy_fp); 5629 5630 if (delete_from_file(prev_prev_offset, nlines) != 0) { 5631 warnx(gettext("delete_from_file failure. " 5632 "Please flush all entries and re-configure :")); 5633 reconfigure(); 5634 (void) fclose(remove_fp); 5635 free(act_props); 5636 return (-1); 5637 } 5638 5639 if (pfp_delete_rule(pindex) != 0) { 5640 warnx(gettext("Deletion incomplete. Please flush" 5641 "all the entries and re-configure :")); 5642 reconfigure(); 5643 (void) fclose(remove_fp); 5644 free(act_props); 5645 return (-1); 5646 } 5647 5648 /* reset the globals */ 5649 linecount = 0; 5650 pindex = 0; 5651 /* free(NULL) also works. */ 5652 free(interface_name); 5653 interface_name = NULL; 5654 5655 /* reopen for next pass, automagically starting over. */ 5656 policy_fp = fopen(POLICY_CONF_FILE, "r"); 5657 if (policy_fp == NULL) { 5658 warn(gettext("%s cannot be re-opened, can't continue"), 5659 POLICY_CONF_FILE); 5660 (void) fclose(remove_fp); 5661 free(act_props); 5662 return (-1); 5663 } 5664 5665 } /* read next remove policy */ 5666 5667 if ((ret = pfp_delete_rule(pindex)) != 0) { 5668 warnx(gettext("Removal incomplete. Please flush " 5669 "all the entries and re-configure :")); 5670 reconfigure(); 5671 free(act_props); 5672 return (ret); 5673 } 5674 5675 /* nothing left to look for */ 5676 (void) fclose(remove_fp); 5677 free(act_props); 5678 5679 return (0); 5680 } 5681 5682 /* 5683 * Constructs a tunnel interface ID extension. Returns the length 5684 * of the extension in 64-bit-words. 5685 */ 5686 static int 5687 attach_tunname(spd_if_t *tunname) 5688 { 5689 if (tunname == NULL || interface_name == NULL) 5690 return (0); 5691 5692 tunname->spd_if_exttype = SPD_EXT_TUN_NAME; 5693 /* 5694 * Use "-3" because there's 4 bytes in the message itself, and 5695 * we lose one because of the '\0' terminator. 5696 */ 5697 tunname->spd_if_len = SPD_8TO64( 5698 P2ROUNDUP(sizeof (*tunname) + strlen(interface_name) - 3, 8)); 5699 (void) strlcpy((char *)tunname->spd_if_name, interface_name, LIFNAMSIZ); 5700 return (tunname->spd_if_len); 5701 } 5702