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