1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #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 cp = NULL; 1805 hp = getipnodebyaddr(addr_ptr, addr_len, af, &error_num); 1806 if (hp) { 1807 if ((cp = strchr(hp->h_name, '.')) != 0 && 1808 strcasecmp(cp + 1, domain) == 0) 1809 *cp = 0; 1810 cp = hp->h_name; 1811 } 1812 } 1813 1814 if (cp) { 1815 (void) printf("%s", cp); 1816 } else { 1817 (void) printf("%s", inet_ntop(af, addr_ptr, abuf, 1818 INET6_ADDRSTRLEN)); 1819 } 1820 } 1821 1822 /* 1823 * Get the next SPD_DUMP message from the PF_POLICY socket. A single 1824 * read may contain multiple messages. This function uses static buffers, 1825 * and is therefore non-reentrant, so if you lift it for an MT application, 1826 * be careful. 1827 * 1828 * Return NULL if there's an error. 1829 */ 1830 static spd_msg_t * 1831 ipsec_read_dump(int pfd) 1832 { 1833 static uint64_t buf[SADB_8TO64(CBUF_LEN)]; 1834 static uint64_t *offset; 1835 static int len; /* In uint64_t units. */ 1836 spd_msg_t *retval; 1837 1838 /* Assume offset and len are initialized to NULL and 0. */ 1839 1840 if ((offset - len == buf) || (offset == NULL)) { 1841 /* read a new block from the socket. */ 1842 len = read(pfd, &buf, sizeof (buf)); 1843 if (len == -1) { 1844 warn(gettext("rule dump: bad read")); 1845 return (NULL); 1846 } 1847 offset = buf; 1848 len = SADB_8TO64(len); 1849 } /* Else I still have more messages from a previous read. */ 1850 1851 retval = (spd_msg_t *)offset; 1852 offset += retval->spd_msg_len; 1853 if (offset > buf + len) { 1854 warnx(gettext("dump read: message corruption," 1855 " %d len exceeds %d boundary."), 1856 SADB_64TO8((uintptr_t)(offset - buf)), 1857 SADB_64TO8((uintptr_t)(buf + len))); 1858 return (NULL); 1859 } 1860 1861 return (retval); 1862 } 1863 1864 /* 1865 * returns 0 on success 1866 * -1 on read error 1867 * >0 on invalid returned message 1868 */ 1869 1870 static int 1871 ipsec_conf_list(void) 1872 { 1873 int ret; 1874 int pfd; 1875 struct spd_msg *msg; 1876 int cnt; 1877 spd_msg_t *rmsg; 1878 spd_ext_t *exts[SPD_EXT_MAX+1]; 1879 /* 1880 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 1881 * issues. 1882 */ 1883 uint64_t buffer[ 1884 SPD_8TO64(sizeof (*msg) + sizeof (spd_if_t) + LIFNAMSIZ) + 1]; 1885 1886 pfd = get_pf_pol_socket(); 1887 1888 if (pfd == -1) { 1889 warnx(gettext("Error getting list of policies from kernel")); 1890 return (-1); 1891 } 1892 1893 (void) memset(buffer, 0, sizeof (buffer)); 1894 msg = (struct spd_msg *)buffer; 1895 msg->spd_msg_version = PF_POLICY_V1; 1896 msg->spd_msg_type = SPD_DUMP; 1897 msg->spd_msg_len = SPD_8TO64(sizeof (*msg)); 1898 1899 msg->spd_msg_len += attach_tunname((spd_if_t *)(msg + 1)); 1900 1901 cnt = write(pfd, msg, SPD_64TO8(msg->spd_msg_len)); 1902 1903 if (cnt < 0) { 1904 warn(gettext("dump: invalid write() return")); 1905 (void) close(pfd); 1906 return (-1); 1907 } 1908 1909 rmsg = ipsec_read_dump(pfd); 1910 1911 if (rmsg == NULL || rmsg->spd_msg_errno != 0) { 1912 warnx("%s: %s", gettext("ruleset dump failed"), 1913 (rmsg == NULL ? 1914 gettext("read error") : 1915 sys_error_message(rmsg->spd_msg_errno))); 1916 (void) close(pfd); 1917 return (-1); 1918 } 1919 1920 1921 for (;;) { 1922 /* read rule */ 1923 rmsg = ipsec_read_dump(pfd); 1924 1925 if (rmsg == NULL) { 1926 (void) close(pfd); 1927 return (-1); 1928 } 1929 1930 if (rmsg->spd_msg_errno != 0) { 1931 warnx("%s: %s", gettext("dump read: bad message"), 1932 sys_error_message(rmsg->spd_msg_errno)); 1933 (void) close(pfd); 1934 return (-1); 1935 } 1936 1937 ret = spdsock_get_ext(exts, rmsg, rmsg->spd_msg_len, 1938 spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN); 1939 if (ret != 0) { 1940 if (strlen(spdsock_diag_buf) != 0) 1941 warnx(spdsock_diag_buf); 1942 warnx("%s: %s", gettext("dump read: bad message"), 1943 sys_error_message(rmsg->spd_msg_errno)); 1944 (void) close(pfd); 1945 return (ret); 1946 } 1947 1948 /* 1949 * End of dump.. 1950 */ 1951 if (exts[SPD_EXT_RULESET] != NULL) 1952 break; /* and return 0. */ 1953 1954 print_pfpol_msg(rmsg); 1955 } 1956 1957 (void) close(pfd); 1958 return (0); 1959 } 1960 1961 static void 1962 print_iap(ips_act_props_t *iap) 1963 { 1964 1965 /* action */ 1966 switch (iap->iap_action) { 1967 case SPD_ACTTYPE_PASS: 1968 (void) printf("pass "); 1969 break; 1970 case SPD_ACTTYPE_DROP: 1971 (void) printf("drop "); 1972 break; 1973 case SPD_ACTTYPE_IPSEC: 1974 (void) printf("ipsec "); 1975 break; 1976 } 1977 1978 /* properties */ 1979 (void) printf("%c ", CURL_BEGIN); 1980 if (iap->iap_action == SPD_ACTTYPE_IPSEC) { 1981 if (iap->iap_attr & SPD_APPLY_AH && 1982 iap->iap_aauth.alg_id != 0) 1983 print_alg("auth_algs", &iap->iap_aauth, 1984 IPSEC_PROTO_AH); 1985 1986 if (iap->iap_attr & SPD_APPLY_ESP) { 1987 print_alg("encr_algs", &iap->iap_eencr, 1988 IPSEC_PROTO_ESP); 1989 if (iap->iap_eauth.alg_id != 0) 1990 print_alg("encr_auth_algs", &iap->iap_eauth, 1991 IPSEC_PROTO_AH); 1992 } 1993 if (iap->iap_attr & SPD_APPLY_UNIQUE) 1994 (void) printf("sa unique "); 1995 else 1996 (void) printf("sa shared "); 1997 } 1998 (void) printf("%c ", CURL_END); 1999 } 2000 2001 2002 static void 2003 print_pfpol_msg(spd_msg_t *msg) 2004 { 2005 spd_ext_t *exts[SPD_EXT_MAX+1]; 2006 spd_address_t *spd_address; 2007 struct spd_rule *spd_rule; 2008 struct spd_proto *spd_proto; 2009 struct spd_portrange *spd_portrange; 2010 struct spd_ext_actions *spd_ext_actions; 2011 struct spd_typecode *spd_typecode; 2012 struct spd_attribute *app; 2013 spd_if_t *spd_if; 2014 uint32_t rv; 2015 uint16_t act_count; 2016 2017 rv = spdsock_get_ext(exts, msg, msg->spd_msg_len, spdsock_diag_buf, 2018 SPDSOCK_DIAG_BUF_LEN); 2019 2020 if (rv == KGE_OK && exts[SPD_EXT_RULE] != NULL) { 2021 spd_if = (spd_if_t *)exts[SPD_EXT_TUN_NAME]; 2022 spd_rule = (struct spd_rule *)exts[SPD_EXT_RULE]; 2023 if (spd_if == NULL) { 2024 (void) printf("%s %lld\n", INDEX_TAG, 2025 spd_rule->spd_rule_index); 2026 } else { 2027 (void) printf("%s %s,%lld\n", INDEX_TAG, 2028 (char *)spd_if->spd_if_name, 2029 spd_rule->spd_rule_index); 2030 } 2031 } else { 2032 if (strlen(spdsock_diag_buf) != 0) 2033 warnx(spdsock_diag_buf); 2034 warnx(gettext("print_pfpol_msg: malformed PF_POLICY message.")); 2035 return; 2036 } 2037 2038 (void) printf("%c ", CURL_BEGIN); 2039 2040 if (spd_if != NULL) { 2041 (void) printf("tunnel %s negotiate %s ", 2042 (char *)spd_if->spd_if_name, 2043 (spd_rule->spd_rule_flags & SPD_RULE_FLAG_TUNNEL) ? 2044 "tunnel" : "transport"); 2045 } 2046 2047 if (exts[SPD_EXT_PROTO] != NULL) { 2048 spd_proto = (struct spd_proto *)exts[SPD_EXT_PROTO]; 2049 print_ulp(spd_proto->spd_proto_number); 2050 } 2051 2052 if (exts[SPD_EXT_LCLADDR] != NULL) { 2053 spd_address = (spd_address_t *)exts[SPD_EXT_LCLADDR]; 2054 2055 (void) printf("laddr "); 2056 print_raw_address((spd_address + 1), 2057 (spd_address->spd_address_len == 2)); 2058 (void) printf("/%d ", spd_address->spd_address_prefixlen); 2059 } 2060 2061 if (exts[SPD_EXT_LCLPORT] != NULL) { 2062 spd_portrange = (struct spd_portrange *)exts[SPD_EXT_LCLPORT]; 2063 if (spd_portrange->spd_ports_minport != 0) { 2064 print_port(spd_portrange->spd_ports_minport, 2065 TOK_lport); 2066 } 2067 } 2068 2069 2070 if (exts[SPD_EXT_REMADDR] != NULL) { 2071 spd_address = (spd_address_t *)exts[SPD_EXT_REMADDR]; 2072 2073 (void) printf("raddr "); 2074 print_raw_address((spd_address + 1), 2075 (spd_address->spd_address_len == 2)); 2076 (void) printf("/%d ", spd_address->spd_address_prefixlen); 2077 } 2078 2079 if (exts[SPD_EXT_REMPORT] != NULL) { 2080 spd_portrange = 2081 (struct spd_portrange *)exts[SPD_EXT_REMPORT]; 2082 if (spd_portrange->spd_ports_minport != 0) { 2083 print_port( 2084 spd_portrange->spd_ports_minport, TOK_rport); 2085 } 2086 } 2087 2088 if (exts[SPD_EXT_ICMP_TYPECODE] != NULL) { 2089 spd_typecode = 2090 (struct spd_typecode *)exts[SPD_EXT_ICMP_TYPECODE]; 2091 print_icmp_typecode(spd_typecode->spd_typecode_type, 2092 spd_typecode->spd_typecode_type_end, 2093 spd_typecode->spd_typecode_code, 2094 spd_typecode->spd_typecode_code_end); 2095 } 2096 2097 if (exts[SPD_EXT_RULE] != NULL) { 2098 spd_rule = (struct spd_rule *)exts[SPD_EXT_RULE]; 2099 print_spd_flags(spd_rule->spd_rule_flags); 2100 } 2101 2102 2103 (void) printf("%c ", CURL_END); 2104 2105 if (exts[SPD_EXT_ACTION] != NULL) { 2106 ips_act_props_t iap; 2107 int or_needed = 0; 2108 2109 (void) memset(&iap, 0, sizeof (iap)); 2110 spd_ext_actions = 2111 (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 2112 app = (struct spd_attribute *)(spd_ext_actions + 1); 2113 2114 for (act_count = 0; 2115 act_count < spd_ext_actions->spd_actions_len -1; 2116 act_count++) { 2117 2118 switch (app->spd_attr_tag) { 2119 2120 case SPD_ATTR_NOP: 2121 break; 2122 2123 case SPD_ATTR_END: 2124 /* print */ 2125 if (or_needed) { 2126 (void) printf("or "); 2127 } else { 2128 or_needed = 1; 2129 } 2130 print_iap(&iap); 2131 break; 2132 2133 case SPD_ATTR_EMPTY: 2134 /* clear */ 2135 (void) memset(&iap, 0, sizeof (iap)); 2136 break; 2137 2138 case SPD_ATTR_NEXT: 2139 /* print */ 2140 if (or_needed) { 2141 (void) printf("or "); 2142 } else { 2143 or_needed = 1; 2144 } 2145 2146 print_iap(&iap); 2147 break; 2148 2149 case SPD_ATTR_TYPE: 2150 iap.iap_action = app->spd_attr_value; 2151 break; 2152 2153 case SPD_ATTR_FLAGS: 2154 iap.iap_attr = app->spd_attr_value; 2155 break; 2156 2157 case SPD_ATTR_AH_AUTH: 2158 iap.iap_aauth.alg_id = app->spd_attr_value; 2159 break; 2160 2161 case SPD_ATTR_ESP_ENCR: 2162 iap.iap_eencr.alg_id = app->spd_attr_value; 2163 break; 2164 2165 case SPD_ATTR_ESP_AUTH: 2166 iap.iap_eauth.alg_id = app->spd_attr_value; 2167 break; 2168 2169 case SPD_ATTR_ENCR_MINBITS: 2170 iap.iap_eencr.alg_minbits = app->spd_attr_value; 2171 break; 2172 2173 case SPD_ATTR_ENCR_MAXBITS: 2174 iap.iap_eencr.alg_maxbits = app->spd_attr_value; 2175 break; 2176 2177 case SPD_ATTR_AH_MINBITS: 2178 iap.iap_aauth.alg_minbits = app->spd_attr_value; 2179 break; 2180 2181 case SPD_ATTR_AH_MAXBITS: 2182 iap.iap_aauth.alg_maxbits = app->spd_attr_value; 2183 break; 2184 2185 case SPD_ATTR_ESPA_MINBITS: 2186 iap.iap_eauth.alg_minbits = app->spd_attr_value; 2187 break; 2188 2189 case SPD_ATTR_ESPA_MAXBITS: 2190 iap.iap_eauth.alg_maxbits = app->spd_attr_value; 2191 break; 2192 2193 case SPD_ATTR_LIFE_SOFT_TIME: 2194 case SPD_ATTR_LIFE_HARD_TIME: 2195 case SPD_ATTR_LIFE_SOFT_BYTES: 2196 case SPD_ATTR_LIFE_HARD_BYTES: 2197 default: 2198 (void) printf("\tattr %d: %X-%d\n", 2199 act_count, 2200 app->spd_attr_tag, 2201 app->spd_attr_value); 2202 break; 2203 } 2204 app++; 2205 } 2206 } 2207 2208 (void) printf("\n"); 2209 } 2210 2211 #ifdef DEBUG_HEAVY 2212 static void 2213 pfpol_msg_dump(spd_msg_t *msg, char *tag) 2214 { 2215 spd_ext_t *exts[SPD_EXT_MAX+1]; 2216 uint32_t i; 2217 spd_address_t *spd_address; 2218 struct spd_rule *spd_rule; 2219 struct spd_proto *spd_proto; 2220 struct spd_portrange *spd_portrange; 2221 struct spd_typecode *spd_typecode; 2222 struct spd_ext_actions *spd_ext_actions; 2223 struct spd_attribute *app; 2224 spd_if_t *spd_if; 2225 char abuf[INET6_ADDRSTRLEN]; 2226 uint32_t rv; 2227 uint16_t act_count; 2228 2229 rv = spdsock_get_ext(exts, msg, msg->spd_msg_len, NULL, 0); 2230 if (rv != KGE_OK) 2231 return; 2232 2233 (void) printf("===========%s==============\n", tag); 2234 (void) printf("pfpol_msg_dump %d\n-------------------\n", rv); 2235 2236 (void) printf("spd_msg_version:%d\n", msg->spd_msg_version); 2237 (void) printf("spd_msg_type:%d\n", msg->spd_msg_type); 2238 (void) printf("spd_msg_errno:%d\n", msg->spd_msg_errno); 2239 (void) printf("spd_msg_spdid:%d\n", msg->spd_msg_spdid); 2240 (void) printf("spd_msg_len:%d\n", msg->spd_msg_len); 2241 (void) printf("spd_msg_diagnostic:%d\n", msg->spd_msg_diagnostic); 2242 (void) printf("spd_msg_seq:%d\n", msg->spd_msg_seq); 2243 (void) printf("spd_msg_pid:%d\n", msg->spd_msg_pid); 2244 2245 for (i = 1; i <= SPD_EXT_MAX; i++) { 2246 if (exts[i] == NULL) { 2247 printf("skipped %d\n", i); 2248 continue; 2249 } 2250 2251 switch (i) { 2252 case SPD_EXT_TUN_NAME: 2253 spd_if = (spd_if_t *)exts[i]; 2254 (void) printf("spd_if = %s\n", spd_if->spd_if_name); 2255 break; 2256 2257 case SPD_EXT_ICMP_TYPECODE: 2258 spd_typecode = (struct spd_typecode *)exts[i]; 2259 (void) printf("icmp type %d-%d code %d-%d\n", 2260 spd_typecode->spd_typecode_type, 2261 spd_typecode->spd_typecode_type_end, 2262 spd_typecode->spd_typecode_code, 2263 spd_typecode->spd_typecode_code_end); 2264 break; 2265 2266 case SPD_EXT_LCLPORT: 2267 spd_portrange = (struct spd_portrange *)exts[i]; 2268 (void) printf("local ports %d-%d\n", 2269 spd_portrange->spd_ports_minport, 2270 spd_portrange->spd_ports_maxport); 2271 2272 break; 2273 2274 case SPD_EXT_REMPORT: 2275 spd_portrange = (struct spd_portrange *)exts[i]; 2276 (void) printf("remote ports %d-%d\n", 2277 spd_portrange->spd_ports_minport, 2278 spd_portrange->spd_ports_maxport); 2279 2280 break; 2281 2282 case SPD_EXT_PROTO: 2283 spd_proto = (struct spd_proto *)exts[i]; 2284 (void) printf("proto:spd_proto_exttype %d\n", 2285 spd_proto->spd_proto_exttype); 2286 (void) printf("proto:spd_proto_number %d\n", 2287 spd_proto->spd_proto_number); 2288 break; 2289 2290 case SPD_EXT_LCLADDR: 2291 case SPD_EXT_REMADDR: 2292 spd_address = (spd_address_t *)exts[i]; 2293 if (i == SPD_EXT_LCLADDR) 2294 (void) printf("local addr "); 2295 else 2296 (void) printf("remote addr "); 2297 2298 2299 (void) printf("%s\n", 2300 inet_ntop(spd_address->spd_address_af, 2301 (void *) (spd_address +1), abuf, 2302 INET6_ADDRSTRLEN)); 2303 2304 (void) printf("prefixlen: %d\n", 2305 spd_address->spd_address_prefixlen); 2306 break; 2307 2308 case SPD_EXT_ACTION: 2309 spd_ext_actions = (struct spd_ext_actions *)exts[i]; 2310 (void) printf("spd_ext_action\n"); 2311 (void) printf("spd_actions_count %d\n", 2312 spd_ext_actions->spd_actions_count); 2313 app = (struct spd_attribute *)(spd_ext_actions + 1); 2314 2315 for (act_count = 0; 2316 act_count < spd_ext_actions->spd_actions_len -1; 2317 act_count++) { 2318 (void) printf("\tattr %d: %X-%d\n", act_count, 2319 app->spd_attr_tag, app->spd_attr_value); 2320 app++; 2321 } 2322 2323 break; 2324 2325 case SPD_EXT_RULE: 2326 spd_rule = (struct spd_rule *)exts[i]; 2327 (void) printf("spd_rule_priority: 0x%x\n", 2328 spd_rule->spd_rule_priority); 2329 (void) printf("spd_rule_flags: %d\n", 2330 spd_rule->spd_rule_flags); 2331 break; 2332 2333 case SPD_EXT_RULESET: 2334 (void) printf("spd_ext_ruleset\n"); 2335 break; 2336 default: 2337 (void) printf("default\n"); 2338 break; 2339 } 2340 } 2341 2342 (void) printf("-------------------\n"); 2343 (void) printf("=========================\n"); 2344 } 2345 #endif /* DEBUG_HEAVY */ 2346 2347 static int 2348 ipsec_conf_view() 2349 { 2350 char buf[MAXLEN]; 2351 FILE *fp; 2352 2353 fp = fopen(POLICY_CONF_FILE, "r"); 2354 if (fp == NULL) { 2355 if (errno == ENOENT) { 2356 /* 2357 * The absence of POLICY_CONF_FILE should 2358 * not cause the command to exit with a 2359 * non-zero status, since this condition 2360 * is valid when no policies were previously 2361 * defined. 2362 */ 2363 return (0); 2364 } 2365 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 2366 return (-1); 2367 } 2368 while (fgets(buf, MAXLEN, fp) != NULL) { 2369 /* Don't print removed entries */ 2370 if (*buf == ';') 2371 continue; 2372 if (strlen(buf) != 0) 2373 buf[strlen(buf) - 1] = '\0'; 2374 (void) puts(buf); 2375 } 2376 return (0); 2377 } 2378 2379 /* 2380 * Delete nlines from start in the POLICY_CONF_FILE. 2381 */ 2382 static int 2383 delete_from_file(int start, int nlines) 2384 { 2385 FILE *fp; 2386 char ibuf[MAXLEN]; 2387 int len; 2388 2389 if ((fp = fopen(POLICY_CONF_FILE, "r+b")) == NULL) { 2390 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 2391 return (-1); 2392 } 2393 2394 /* 2395 * Insert a ";", read the line and discard it. Repeat 2396 * this logic nlines - 1 times. For the last line there 2397 * is just a newline character. We can't just insert a 2398 * single ";" character instead of the newline character 2399 * as it would affect the next line. Thus when we comment 2400 * the last line we seek one less and insert a ";" 2401 * character, which will replace the newline of the 2402 * penultimate line with ; and newline of the last line 2403 * will become part of the previous line. 2404 */ 2405 do { 2406 /* 2407 * It is not enough to seek just once and expect the 2408 * subsequent fgets below to take you to the right 2409 * offset of the next line. fgets below seems to affect 2410 * the offset. Thus we need to seek, replace with ";", 2411 * and discard a line using fgets for every line. 2412 */ 2413 if (fseek(fp, start, SEEK_SET) == -1) { 2414 warn("fseek"); 2415 return (-1); 2416 } 2417 if (fputc(';', fp) < 0) { 2418 warn("fputc"); 2419 return (-1); 2420 } 2421 /* 2422 * Flush the above ";" character before we do the fgets(). 2423 * Without this, fgets() gets confused with offsets. 2424 */ 2425 (void) fflush(fp); 2426 len = 0; 2427 while (fgets(ibuf, MAXLEN, fp) != NULL) { 2428 len += strlen(ibuf); 2429 if (ibuf[len - 1] == '\n') { 2430 /* 2431 * We have read a complete line. 2432 */ 2433 break; 2434 } 2435 } 2436 /* 2437 * We read the line after ";" character has been inserted. 2438 * Thus len does not count ";". To advance to the next line 2439 * increment by 1. 2440 */ 2441 start += (len + 1); 2442 /* 2443 * If nlines == 2, we will be commenting out the last 2444 * line next, which has only one newline character. 2445 * If we blindly replace it with ";", it will be 2446 * read as part of the next line which could have 2447 * a INDEX string and thus confusing ipsec_conf_view. 2448 * Thus, we seek one less and replace the previous 2449 * line's newline character with ";", and the 2450 * last line's newline character will become part of 2451 * the previous line. 2452 */ 2453 if (nlines == 2) 2454 start--; 2455 } while (--nlines != 0); 2456 (void) fclose(fp); 2457 if (nlines != 0) 2458 return (-1); 2459 else 2460 return (0); 2461 } 2462 2463 /* 2464 * Delete an entry from the file by inserting a ";" at the 2465 * beginning of the lines to be removed. 2466 */ 2467 static int 2468 ipsec_conf_del(int policy_index, boolean_t ignore_spd) 2469 { 2470 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 2471 char *buf; 2472 FILE *fp; 2473 char ibuf[MAXLEN]; 2474 int ibuf_len, index_len, index; 2475 int ret = 0; 2476 int offset, prev_offset; 2477 int nlines; 2478 char lifname[LIFNAMSIZ]; 2479 2480 if (act_props == NULL) { 2481 warn(gettext("memory")); 2482 return (-1); 2483 } 2484 2485 fp = fopen(POLICY_CONF_FILE, "r"); 2486 if (fp == NULL) { 2487 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 2488 free(act_props); 2489 return (-1); 2490 } 2491 2492 index_len = strlen(INDEX_TAG); 2493 index = 0; 2494 for (offset = prev_offset = 0; fgets(ibuf, MAXLEN, fp) != NULL; 2495 offset += ibuf_len) { 2496 prev_offset = offset; 2497 ibuf_len = strlen(ibuf); 2498 2499 if (strncmp(ibuf, INDEX_TAG, index_len) != 0) { 2500 continue; 2501 } 2502 2503 /* 2504 * This line contains INDEX_TAG 2505 */ 2506 buf = ibuf + index_len; 2507 buf++; /* Skip the space */ 2508 index = parse_index(buf, lifname); 2509 if (index == -1) { 2510 warnx(gettext("Invalid index in the file")); 2511 free(act_props); 2512 return (-1); 2513 } 2514 if (index == policy_index && 2515 (interface_name == NULL || 2516 strncmp(interface_name, lifname, LIFNAMSIZ) == 0)) { 2517 if (!ignore_spd) { 2518 ret = parse_one(fp, act_props); 2519 if (ret == -1) { 2520 warnx(gettext("Invalid policy entry " 2521 "in the file")); 2522 free(act_props); 2523 return (-1); 2524 } 2525 } 2526 /* 2527 * nlines is the number of lines we should comment 2528 * out. linecount tells us how many lines this command 2529 * spans. And we need to remove the line with INDEX 2530 * and an extra line we added during ipsec_conf_add. 2531 * 2532 * NOTE : If somebody added a policy entry which does 2533 * not have a newline, ipsec_conf_add() fills in the 2534 * newline. Hence, there is always 2 extra lines 2535 * to delete. 2536 */ 2537 nlines = linecount + 2; 2538 goto delete; 2539 } 2540 } 2541 2542 if (!ignore_spd) 2543 ret = pfp_delete_rule(policy_index); 2544 2545 if (ret != 0) { 2546 warnx(gettext("Deletion incomplete. Please " 2547 "flush all the entries and re-configure :")); 2548 reconfigure(); 2549 free(act_props); 2550 return (ret); 2551 } 2552 free(act_props); 2553 return (ret); 2554 2555 delete: 2556 /* Delete nlines from prev_offset */ 2557 (void) fclose(fp); 2558 ret = delete_from_file(prev_offset, nlines); 2559 2560 if (ret != 0) { 2561 warnx(gettext("Deletion incomplete. Please " 2562 "flush all the entries and re-configure :")); 2563 reconfigure(); 2564 free(act_props); 2565 return (ret); 2566 } 2567 2568 if (!ignore_spd) 2569 ret = pfp_delete_rule(policy_index); 2570 2571 if (ret != 0) { 2572 warnx(gettext("Deletion incomplete. Please " 2573 "flush all the entries and re-configure :")); 2574 reconfigure(); 2575 free(act_props); 2576 return (ret); 2577 } 2578 free(act_props); 2579 return (0); 2580 } 2581 2582 static int 2583 pfp_delete_rule(uint64_t index) 2584 { 2585 struct spd_msg *msg; 2586 struct spd_rule *rule; 2587 int sfd; 2588 int cnt, len, alloclen; 2589 2590 sfd = get_pf_pol_socket(); 2591 if (sfd < 0) { 2592 warn(gettext("unable to open policy socket")); 2593 return (-1); 2594 } 2595 2596 /* 2597 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 2598 * issues. 2599 */ 2600 alloclen = sizeof (spd_msg_t) + sizeof (struct spd_rule) + 2601 sizeof (spd_if_t) + LIFNAMSIZ + 8; 2602 msg = (spd_msg_t *)malloc(alloclen); 2603 2604 if (msg == NULL) { 2605 warn("malloc"); 2606 return (-1); 2607 } 2608 2609 rule = (struct spd_rule *)(msg + 1); 2610 2611 (void) memset(msg, 0, alloclen); 2612 msg->spd_msg_version = PF_POLICY_V1; 2613 msg->spd_msg_type = SPD_DELETERULE; 2614 msg->spd_msg_len = SPD_8TO64(sizeof (spd_msg_t) 2615 + sizeof (struct spd_rule)); 2616 2617 rule->spd_rule_type = SPD_EXT_RULE; 2618 rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule)); 2619 rule->spd_rule_index = index; 2620 2621 msg->spd_msg_len += attach_tunname((spd_if_t *)(rule + 1)); 2622 2623 len = SPD_64TO8(msg->spd_msg_len); 2624 cnt = write(sfd, msg, len); 2625 2626 if (cnt != len) { 2627 if (cnt < 0) { 2628 (void) close(sfd); 2629 free(msg); 2630 warn(gettext("Delete failed: write")); 2631 return (-1); 2632 } else { 2633 (void) close(sfd); 2634 free(msg); 2635 warnx(gettext("Delete failed: short write")); 2636 return (-1); 2637 } 2638 } 2639 2640 cnt = read(sfd, msg, len); 2641 if (cnt != len) { 2642 if (cnt < 0) { 2643 (void) close(sfd); 2644 free(msg); 2645 warn(gettext("Delete failed: read")); 2646 return (-1); 2647 } else { 2648 (void) close(sfd); 2649 free(msg); 2650 warnx(gettext("Delete failed while reading reply")); 2651 return (-1); 2652 } 2653 } 2654 (void) close(sfd); 2655 if (msg->spd_msg_errno != 0) { 2656 free(msg); 2657 errno = msg->spd_msg_errno; 2658 warn(gettext("Delete failed: SPD_FLUSH")); 2659 return (-1); 2660 } 2661 2662 free(msg); 2663 return (0); 2664 } 2665 2666 static int 2667 ipsec_conf_flush(int db) 2668 { 2669 int pfd, cnt, len; 2670 int sfd; 2671 struct spd_msg *msg; 2672 /* 2673 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 2674 * issues. 2675 */ 2676 uint64_t buffer[ 2677 SPD_8TO64(sizeof (*msg) + sizeof (spd_if_t) + LIFNAMSIZ) + 1]; 2678 2679 sfd = get_pf_pol_socket(); 2680 if (sfd < 0) { 2681 warn(gettext("unable to open policy socket")); 2682 return (-1); 2683 } 2684 2685 (void) memset(buffer, 0, sizeof (buffer)); 2686 msg = (struct spd_msg *)buffer; 2687 msg->spd_msg_version = PF_POLICY_V1; 2688 msg->spd_msg_type = SPD_FLUSH; 2689 msg->spd_msg_len = SPD_8TO64(sizeof (*msg)); 2690 msg->spd_msg_spdid = db; 2691 2692 msg->spd_msg_len += attach_tunname((spd_if_t *)(msg + 1)); 2693 2694 len = SPD_64TO8(msg->spd_msg_len); 2695 cnt = write(sfd, msg, len); 2696 if (cnt != len) { 2697 if (cnt < 0) { 2698 warn(gettext("Flush failed: write")); 2699 return (-1); 2700 } else { 2701 warnx(gettext("Flush failed: short write")); 2702 return (-1); 2703 } 2704 } 2705 2706 cnt = read(sfd, msg, len); 2707 if (cnt != len) { 2708 if (cnt < 0) { 2709 warn(gettext("Flush failed: read")); 2710 return (-1); 2711 } else { 2712 warnx(gettext("Flush failed while reading reply")); 2713 return (-1); 2714 } 2715 } 2716 (void) close(sfd); 2717 if (msg->spd_msg_errno != 0) { 2718 warnx("%s: %s", gettext("Flush failed: SPD_FLUSH"), 2719 sys_error_message(msg->spd_msg_errno)); 2720 return (-1); 2721 } 2722 2723 /* Truncate the file */ 2724 if (db == SPD_ACTIVE) { 2725 if ((pfd = open(POLICY_CONF_FILE, O_TRUNC|O_RDWR)) == -1) { 2726 if (errno == ENOENT) { 2727 /* 2728 * The absence of POLICY_CONF_FILE should 2729 * not cause the command to exit with a 2730 * non-zero status, since this condition 2731 * is valid when no policies were previously 2732 * defined. 2733 */ 2734 return (0); 2735 } 2736 warn(gettext("%s cannot be truncated"), 2737 POLICY_CONF_FILE); 2738 return (-1); 2739 } 2740 (void) close(pfd); 2741 } 2742 return (0); 2743 } 2744 2745 /* 2746 * function to send SPD_FLIP and SPD_CLONE messages 2747 * Do it for ALL polheads for simplicity's sake. 2748 */ 2749 static void 2750 ipsec_conf_admin(uint8_t type) 2751 { 2752 int cnt; 2753 int sfd; 2754 struct spd_msg *msg; 2755 uint64_t buffer[ 2756 SPD_8TO64(sizeof (struct spd_msg) + sizeof (spd_if_t))]; 2757 char *save_ifname; 2758 2759 sfd = get_pf_pol_socket(); 2760 if (sfd < 0) { 2761 err(-1, gettext("unable to open policy socket")); 2762 } 2763 2764 (void) memset(buffer, 0, sizeof (buffer)); 2765 msg = (struct spd_msg *)buffer; 2766 msg->spd_msg_version = PF_POLICY_V1; 2767 msg->spd_msg_type = type; 2768 msg->spd_msg_len = SPD_8TO64(sizeof (buffer)); 2769 2770 save_ifname = interface_name; 2771 /* Apply to all policy heads - global and tunnels. */ 2772 interface_name = &all_polheads; 2773 (void) attach_tunname((spd_if_t *)(msg + 1)); 2774 interface_name = save_ifname; 2775 2776 cnt = write(sfd, msg, sizeof (buffer)); 2777 if (cnt != sizeof (buffer)) { 2778 if (cnt < 0) { 2779 err(-1, gettext("admin failed: write")); 2780 } else { 2781 errx(-1, gettext("admin failed: short write")); 2782 } 2783 } 2784 2785 cnt = read(sfd, msg, sizeof (buffer)); 2786 if (cnt != sizeof (buffer)) { 2787 if (cnt < 0) { 2788 err(-1, gettext("admin failed: read")); 2789 } else { 2790 errx(-1, gettext("admin failed while reading reply")); 2791 } 2792 } 2793 (void) close(sfd); 2794 if (msg->spd_msg_errno != 0) { 2795 errno = msg->spd_msg_errno; 2796 err(-1, gettext("admin failed")); 2797 } 2798 } 2799 2800 static void 2801 reconfigure() 2802 { 2803 (void) fprintf(stderr, gettext( 2804 "\tipsecconf -f \n " 2805 "\tipsecconf -a policy_file\n")); 2806 } 2807 2808 static void 2809 usage(void) 2810 { 2811 (void) fprintf(stderr, gettext( 2812 "Usage: ipsecconf\n" 2813 "\tipsecconf -a ([-]|<filename>) [-q]\n" 2814 "\tipsecconf -c <filename>\n" 2815 "\tipsecconf -r ([-]|<filename>) [-q]\n" 2816 "\tipsecconf -d [-i tunnel-interface] <index>\n" 2817 "\tipsecconf -d <tunnel-interface,index>\n" 2818 "\tipsecconf -l [-n] [-i tunnel-interface]\n" 2819 "\tipsecconf -f [-i tunnel-interface]\n" 2820 "\tipsecconf -L [-n]\n" 2821 "\tipsecconf -F\n")); 2822 } 2823 2824 /* 2825 * a type consists of 2826 * "type" <int>{ "-" <int>} 2827 * or 2828 * "type" keyword 2829 * 2830 * a code consists of 2831 * "code" <int>{ "-" <int>} 2832 * or 2833 * "code" keyword 2834 */ 2835 2836 2837 static int 2838 parse_type_code(const char *str, const str_val_t *table) 2839 { 2840 char *end1, *end2; 2841 int res1 = 0, res2 = 0; 2842 int i; 2843 2844 if (isdigit(str[0])) { 2845 res1 = strtol(str, &end1, 0); 2846 2847 if (end1 == str) { 2848 return (-1); 2849 } 2850 2851 if (res1 > 255 || res1 < 0) { 2852 return (-1); 2853 } 2854 2855 if (*end1 == '-') { 2856 end1++; 2857 res2 = strtol(end1, &end2, 0); 2858 if (res2 > 255 || res2 < 0) { 2859 return (-1); 2860 } 2861 } else { 2862 end2 = end1; 2863 } 2864 2865 while (isspace(*end2)) 2866 end2++; 2867 2868 if (*end2 != '\0') { 2869 return (-1); 2870 } 2871 2872 return (res1 + (res2 << 8)); 2873 } 2874 2875 for (i = 0; table[i].string; i++) { 2876 if (strcmp(str, table[i].string) == 0) { 2877 return (table[i].value); 2878 } 2879 } 2880 2881 return (-1); 2882 } 2883 2884 static int 2885 parse_int(const char *str) 2886 { 2887 char *end; 2888 int res; 2889 2890 res = strtol(str, &end, 0); 2891 if (end == str) 2892 return (-1); 2893 while (isspace(*end)) 2894 end++; 2895 if (*end != '\0') 2896 return (-1); 2897 return (res); 2898 } 2899 2900 /* 2901 * Parses <interface>,<index>. Sets iname or the global interface_name (if 2902 * iname == NULL) to <interface> and returns <index>. Calls exit() if we have 2903 * an interface_name already set. 2904 */ 2905 static int 2906 parse_index(const char *str, char *iname) 2907 { 2908 char *intf, *num, *copy; 2909 int rc; 2910 2911 copy = strdup(str); 2912 if (copy == NULL) { 2913 EXIT_FATAL("Out of memory."); 2914 } 2915 2916 intf = strtok(copy, ","); 2917 /* Just want the rest of the string unmolested, so use "" for arg2. */ 2918 num = strtok(NULL, ""); 2919 if (num == NULL) { 2920 /* No comma found, just parse it like an int. */ 2921 free(copy); 2922 return (parse_int(str)); 2923 } 2924 2925 if (iname != NULL) { 2926 (void) strlcpy(iname, intf, LIFNAMSIZ); 2927 } else { 2928 if (interface_name != NULL) { 2929 EXIT_FATAL("Interface name already selected"); 2930 } 2931 2932 interface_name = strdup(intf); 2933 if (interface_name == NULL) { 2934 EXIT_FATAL("Out of memory."); 2935 } 2936 } 2937 2938 rc = parse_int(num); 2939 free(copy); 2940 return (rc); 2941 } 2942 2943 /* 2944 * Convert a mask to a prefix length. 2945 * Returns prefix length on success, -1 otherwise. 2946 */ 2947 static int 2948 in_getprefixlen(char *mask) 2949 { 2950 int prefixlen; 2951 char *end; 2952 2953 prefixlen = (int)strtol(mask, &end, 10); 2954 if (prefixlen < 0) { 2955 return (-1); 2956 } 2957 if (mask == end) { 2958 return (-1); 2959 } 2960 if (*end != '\0') { 2961 return (-1); 2962 } 2963 return (prefixlen); 2964 } 2965 2966 /* 2967 * Convert a prefix length to a mask. 2968 * Assumes the mask array is zero'ed by the caller. 2969 */ 2970 static void 2971 in_prefixlentomask(unsigned int prefixlen, uchar_t *mask) 2972 { 2973 while (prefixlen > 0) { 2974 if (prefixlen >= 8) { 2975 *mask++ = 0xFF; 2976 prefixlen -= 8; 2977 continue; 2978 } 2979 *mask |= 1 << (8 - prefixlen); 2980 prefixlen--; 2981 } 2982 } 2983 2984 2985 static int 2986 parse_address(int type, char *addr_str) 2987 { 2988 char *ptr; 2989 int prefix_len = 0; 2990 struct netent *ne = NULL; 2991 struct hostent *hp = NULL; 2992 int h_errno; 2993 struct in_addr netaddr; 2994 struct in6_addr *netaddr6; 2995 struct hostent *ne_hent; 2996 boolean_t has_mask = B_FALSE; 2997 2998 ptr = strchr(addr_str, '/'); 2999 if (ptr != NULL) { 3000 has_mask = B_TRUE; 3001 *ptr++ = NULL; 3002 3003 prefix_len = in_getprefixlen(ptr); 3004 if (prefix_len < 0) 3005 return (-1); 3006 } 3007 3008 /* 3009 * getipnodebyname() is thread safe. This allows us to hold on to the 3010 * returned hostent structure, which is pointed to by the shp and 3011 * dhp globals for the source and destination addresses, respectively. 3012 */ 3013 hp = getipnodebyname(addr_str, AF_INET6, AI_DEFAULT | AI_ALL, &h_errno); 3014 if (hp != NULL) { 3015 /* 3016 * We come here for both a hostname and 3017 * any host address /network address. 3018 */ 3019 assert(hp->h_addrtype == AF_INET6); 3020 } else if ((ne = getnetbyname(addr_str)) != NULL) { 3021 switch (ne->n_addrtype) { 3022 case AF_INET: 3023 /* 3024 * Allocate a struct hostent and initialize 3025 * it with the address corresponding to the 3026 * network number previously returned by 3027 * getnetbyname(). Freed by do_address_adds() 3028 * once the policy is defined. 3029 */ 3030 ne_hent = malloc(sizeof (struct hostent)); 3031 if (ne_hent == NULL) { 3032 warn("malloc"); 3033 return (-1); 3034 } 3035 ne_hent->h_addr_list = malloc(2*sizeof (char *)); 3036 if (ne_hent->h_addr_list == NULL) { 3037 warn("malloc"); 3038 free(ne_hent); 3039 return (-1); 3040 } 3041 netaddr6 = malloc(sizeof (struct in6_addr)); 3042 if (netaddr6 == NULL) { 3043 warn("malloc"); 3044 free(ne_hent->h_addr_list); 3045 free(ne_hent); 3046 return (-1); 3047 } 3048 ne_hent->h_addr_list[0] = (char *)netaddr6; 3049 ne_hent->h_addr_list[1] = NULL; 3050 netaddr = inet_makeaddr(ne->n_net, INADDR_ANY); 3051 IN6_INADDR_TO_V4MAPPED(&netaddr, netaddr6); 3052 hp = ne_hent; 3053 break; 3054 default: 3055 warnx("Address type %d not supported.", ne->n_addrtype); 3056 return (-1); 3057 } 3058 } else { 3059 return (-1); 3060 } 3061 3062 if (type == IPSEC_CONF_SRC_ADDRESS) { 3063 shp = hp; 3064 if (has_mask) 3065 splen = prefix_len; 3066 has_saprefix = has_mask; 3067 } else { 3068 dhp = hp; 3069 if (has_mask) 3070 dplen = prefix_len; 3071 has_daprefix = has_mask; 3072 } 3073 3074 return (0); 3075 } 3076 3077 /* 3078 * Add port-only entries. Make sure to add them in both the V6 and V4 tables! 3079 */ 3080 static int 3081 do_port_adds(ips_conf_t *cptr) 3082 { 3083 int ret, diag; 3084 3085 assert(IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)); 3086 assert(IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_addr_v6)); 3087 3088 #ifdef DEBUG_HEAVY 3089 (void) dump_conf(cptr); 3090 #endif 3091 3092 ret = send_pf_pol_message(SPD_ADDRULE, cptr, &diag); 3093 if (ret != 0 && !ipsecconf_qflag) { 3094 warnx( 3095 gettext("Could not add IPv4 policy for sport %d, dport %d " 3096 "- diagnostic %d - %s"), ntohs(cptr->ips_src_port_min), 3097 ntohs(cptr->ips_dst_port_min), diag, spdsock_diag(diag)); 3098 } 3099 3100 return (ret); 3101 } 3102 3103 /* 3104 * Nuke a list of policy entries. 3105 * rewrite this to use flipping 3106 * d_list isn't freed because we will be 3107 * exiting the program soon. 3108 */ 3109 static void 3110 nuke_adds() 3111 { 3112 d_list_t *temp = d_list; 3113 FILE *policy_fp; 3114 3115 policy_fp = fopen(POLICY_CONF_FILE, "a"); 3116 if (policy_fp == NULL) { 3117 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 3118 } else { 3119 (void) fprintf(policy_fp, "\n\n"); 3120 (void) fflush(policy_fp); 3121 } 3122 3123 while (temp != NULL) { 3124 (void) ipsec_conf_del(temp->index, B_TRUE); 3125 temp = temp->next; 3126 } 3127 } 3128 3129 /* 3130 * Set mask info from the specified prefix len. Fail if multihomed. 3131 */ 3132 static int 3133 set_mask_info(struct hostent *hp, unsigned int plen, struct in6_addr *mask_v6) 3134 { 3135 struct in6_addr addr; 3136 struct in_addr mask_v4; 3137 3138 if (hp->h_addr_list[1] != NULL) { 3139 return (EOPNOTSUPP); 3140 } 3141 3142 if (!IN6_IS_ADDR_UNSPECIFIED(mask_v6)) { 3143 return (EBUSY); 3144 } 3145 3146 bcopy(hp->h_addr_list[0], &addr, sizeof (struct in6_addr)); 3147 if (IN6_IS_ADDR_V4MAPPED(&addr)) { 3148 if (plen > IP_ABITS) { 3149 return (ERANGE); 3150 } 3151 (void) memset(&mask_v4, 0, sizeof (mask_v4)); 3152 in_prefixlentomask(plen, (uchar_t *)&mask_v4); 3153 IN6_INADDR_TO_V4MAPPED(&mask_v4, mask_v6); 3154 } else { 3155 if (plen > IPV6_ABITS) { 3156 return (ERANGE); 3157 } 3158 /* mask_v6 is already zero (unspecified), see test above */ 3159 in_prefixlentomask(plen, (uchar_t *)mask_v6); 3160 } 3161 return (0); 3162 } 3163 3164 /* 3165 * Initialize the specified IPv6 address with all f's. 3166 */ 3167 static void 3168 init_addr_wildcard(struct in6_addr *addr_v6, boolean_t isv4) 3169 { 3170 if (isv4) { 3171 uint32_t addr_v4 = 0xffffffff; 3172 IN6_INADDR_TO_V4MAPPED((struct in_addr *)&addr_v4, addr_v6); 3173 } else { 3174 (void) memset(addr_v6, 0xff, sizeof (struct in6_addr)); 3175 } 3176 } 3177 3178 /* 3179 * Called at the end to actually add policy. Handles single and multi-homed 3180 * cases. 3181 */ 3182 static int 3183 do_address_adds(ips_conf_t *cptr, int *diag) 3184 { 3185 int i, j; 3186 int ret = 0; /* For ioctl() call. */ 3187 int rc = 0; /* My own return code. */ 3188 struct in6_addr zeroes = {0, 0, 0, 0}; 3189 char *ptr[2]; 3190 struct hostent hent; 3191 boolean_t isv4; 3192 int add_count = 0; 3193 3194 /* 3195 * dst_hent may not be initialized if a destination 3196 * address was not given. It will be initalized with just 3197 * one address if a destination address was given. In both 3198 * the cases, we initialize here with ipsc_dst_addr and enter 3199 * the loop below. 3200 */ 3201 if (dhp == NULL) { 3202 assert(shp != NULL); 3203 hent.h_addr_list = ptr; 3204 ptr[0] = (char *)&zeroes.s6_addr; 3205 ptr[1] = NULL; 3206 dhp = &hent; 3207 } else if (shp == NULL) { 3208 assert(dhp != NULL); 3209 hent.h_addr_list = ptr; 3210 ptr[0] = (char *)&zeroes.s6_addr; 3211 ptr[1] = NULL; 3212 shp = &hent; 3213 } 3214 3215 /* 3216 * Set mask info here. Bail if multihomed and there's a prefix len. 3217 */ 3218 if (has_saprefix) { 3219 rc = set_mask_info(shp, splen, &cptr->ips_src_mask_v6); 3220 if (rc != 0) 3221 goto bail; 3222 cptr->ips_src_mask_len = splen; 3223 } 3224 3225 if (has_daprefix) { 3226 rc = set_mask_info(dhp, dplen, &cptr->ips_dst_mask_v6); 3227 if (rc != 0) 3228 goto bail; 3229 cptr->ips_dst_mask_len = dplen; 3230 } 3231 3232 for (i = 0; shp->h_addr_list[i] != NULL; i++) { 3233 bcopy(shp->h_addr_list[i], &cptr->ips_src_addr_v6, 3234 sizeof (struct in6_addr)); 3235 isv4 = cptr->ips_isv4 = 3236 IN6_IS_ADDR_V4MAPPED(&cptr->ips_src_addr_v6); 3237 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_mask_v6) && 3238 shp != &hent) { 3239 init_addr_wildcard(&cptr->ips_src_mask_v6, isv4); 3240 } 3241 3242 for (j = 0; dhp->h_addr_list[j] != NULL; j++) { 3243 bcopy(dhp->h_addr_list[j], &cptr->ips_dst_addr_v6, 3244 sizeof (struct in6_addr)); 3245 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)) { 3246 /* 3247 * Src was not specified, so update isv4 flag 3248 * for this policy according to the family 3249 * of the destination address. 3250 */ 3251 isv4 = cptr->ips_isv4 = 3252 IN6_IS_ADDR_V4MAPPED( 3253 &cptr->ips_dst_addr_v6); 3254 } else if ((dhp != &hent) && (isv4 != 3255 IN6_IS_ADDR_V4MAPPED(&cptr->ips_dst_addr_v6))) { 3256 /* v6/v4 mismatch. */ 3257 continue; 3258 } 3259 if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_mask_v6) && 3260 dhp != &hent) { 3261 init_addr_wildcard(&cptr->ips_dst_mask_v6, 3262 isv4); 3263 } 3264 3265 ret = send_pf_pol_message(SPD_ADDRULE, cptr, diag); 3266 3267 if (ret == 0) { 3268 add_count++; 3269 } else { 3270 /* For now, allow duplicate/overlap policies. */ 3271 if (ret != EEXIST) { 3272 /* 3273 * We have an error where we added 3274 * some, but had errors with others. 3275 * Undo the previous adds, and 3276 * bail. 3277 */ 3278 rc = ret; 3279 goto bail; 3280 } 3281 } 3282 3283 bzero(&cptr->ips_dst_mask_v6, 3284 sizeof (struct in6_addr)); 3285 } 3286 3287 bzero(&cptr->ips_src_mask_v6, sizeof (struct in6_addr)); 3288 } 3289 3290 bail: 3291 if (shp != &hent) 3292 freehostent(shp); 3293 shp = NULL; 3294 if (dhp != &hent) 3295 freehostent(dhp); 3296 dhp = NULL; 3297 splen = 0; 3298 dplen = 0; 3299 3300 if ((add_count == 0) && (rc == 0)) { 3301 /* 3302 * No entries were added. We failed all adds 3303 * because the entries already existed, or because 3304 * no v4 or v6 src/dst pairs were found. Either way, 3305 * we must fail here with an appropriate error 3306 * to avoid a corresponding entry from being added 3307 * to ipsecpolicy.conf. 3308 */ 3309 if ((ret == EEXIST)) { 3310 /* All adds failed with EEXIST */ 3311 rc = EEXIST; 3312 } else { 3313 /* No matching v4 or v6 src/dst pairs */ 3314 rc = ESRCH; 3315 } 3316 } 3317 3318 return (rc); 3319 } 3320 3321 static int 3322 parse_mask(int type, char *mask_str, ips_conf_t *cptr) 3323 { 3324 struct in_addr mask; 3325 struct in6_addr *mask6; 3326 3327 if (type == IPSEC_CONF_SRC_MASK) { 3328 mask6 = &cptr->ips_src_mask_v6; 3329 } else { 3330 mask6 = &cptr->ips_dst_mask_v6; 3331 } 3332 3333 if ((strncasecmp(mask_str, "0x", 2) == 0) && 3334 (strchr(mask_str, '.') == NULL)) { 3335 /* Is it in the form 0xff000000 ? */ 3336 char *end; 3337 3338 mask.s_addr = strtoul(mask_str, &end, 0); 3339 if (end == mask_str) { 3340 return (-1); 3341 } 3342 if (*end != '\0') { 3343 return (-1); 3344 } 3345 mask.s_addr = htonl(mask.s_addr); 3346 } else { 3347 /* 3348 * Since inet_addr() returns -1 on error, we have 3349 * to convert a broadcast address ourselves. 3350 */ 3351 if (strcmp(mask_str, "255.255.255.255") == 0) { 3352 mask.s_addr = 0xffffffff; 3353 } else { 3354 mask.s_addr = inet_addr(mask_str); 3355 if (mask.s_addr == (unsigned int)-1) 3356 return (-1); 3357 } 3358 } 3359 3360 /* Should we check for non-contiguous masks ? */ 3361 if (mask.s_addr == 0) 3362 return (-1); 3363 IN6_INADDR_TO_V4MAPPED(&mask, mask6); 3364 3365 3366 if (type == IPSEC_CONF_SRC_MASK) { 3367 cptr->ips_src_mask_len = in_masktoprefix(mask6->s6_addr, 3368 B_TRUE); 3369 } else { 3370 cptr->ips_dst_mask_len = in_masktoprefix(mask6->s6_addr, 3371 B_TRUE); 3372 } 3373 3374 return (0); 3375 } 3376 3377 static int 3378 parse_port(int type, char *port_str, ips_conf_t *conf) 3379 { 3380 struct servent *sent; 3381 in_port_t port; 3382 int ret; 3383 3384 sent = getservbyname(port_str, NULL); 3385 if (sent == NULL) { 3386 ret = parse_int(port_str); 3387 if (ret < 0 || ret >= 65536) { 3388 return (-1); 3389 } 3390 port = htons((in_port_t)ret); 3391 } else { 3392 port = sent->s_port; 3393 } 3394 if (type == IPSEC_CONF_SRC_PORT) { 3395 conf->ips_src_port_min = conf->ips_src_port_max = port; 3396 } else { 3397 conf->ips_dst_port_min = conf->ips_dst_port_max = port; 3398 } 3399 return (0); 3400 } 3401 3402 static int 3403 valid_algorithm(int proto_num, const char *str) 3404 { 3405 const char *tmp; 3406 int ret; 3407 struct ipsecalgent *alg; 3408 3409 /* Short-circuit "none" */ 3410 if (strncasecmp("none", str, 5) == 0) 3411 return (-2); 3412 3413 alg = getipsecalgbyname(str, proto_num, NULL); 3414 if (alg != NULL) { 3415 ret = alg->a_alg_num; 3416 freeipsecalgent(alg); 3417 return (ret); 3418 } 3419 3420 /* 3421 * Look whether it could be a valid number. 3422 * We support numbers also so that users can 3423 * load algorithms as they need it. We can't 3424 * check for validity of numbers here. It will 3425 * be checked when the SA is negotiated/looked up. 3426 * parse_int uses strtol(str), which converts 3DES 3427 * to a valid number i.e looks only at initial 3428 * number part. If we come here we should expect 3429 * only a decimal number. 3430 */ 3431 tmp = str; 3432 while (*tmp) { 3433 if (!isdigit(*tmp)) 3434 return (-1); 3435 tmp++; 3436 } 3437 3438 ret = parse_int(str); 3439 if (ret > 0 && ret <= 255) 3440 return (ret); 3441 else 3442 return (-1); 3443 } 3444 3445 static int 3446 parse_ipsec_alg(char *str, ips_act_props_t *iap, int alg_type) 3447 { 3448 int alg_value; 3449 char tstr[VALID_ALG_LEN]; 3450 char *lens = NULL; 3451 char *l1_str; 3452 int l1 = 0; 3453 char *l2_str; 3454 int l2 = SPD_MAX_MAXBITS; 3455 algreq_t *ap; 3456 uint_t a_type; 3457 3458 fetch_algorithms(); 3459 3460 /* 3461 * Make sure that we get a null terminated string. 3462 * For a bad input, we truncate at VALID_ALG_LEN. 3463 */ 3464 (void) strlcpy(tstr, str, VALID_ALG_LEN); 3465 lens = strtok(tstr, "()"); 3466 lens = strtok(NULL, "()"); 3467 3468 if (lens != NULL) { 3469 int len1 = 0; 3470 int len2 = SPD_MAX_MAXBITS; 3471 int len_all = strlen(lens); 3472 int dot_start = (lens[0] == '.'); 3473 l1_str = strtok(lens, "."); 3474 l2_str = strtok(NULL, "."); 3475 if (l1_str != NULL) { 3476 l1 = parse_int(l1_str); 3477 len1 = strlen(l1_str); 3478 if (len1 < 0) 3479 return (1); 3480 } 3481 if (l2_str != NULL) { 3482 l2 = parse_int(l2_str); 3483 len2 = strlen(l2_str); 3484 if (len2 < 0) 3485 return (1); 3486 } 3487 3488 if (len_all == len1) { 3489 /* alg(n) */ 3490 l2 = l1; 3491 } else if (dot_start) { 3492 /* alg(..n) */ 3493 l2 = l1; 3494 l1 = 0; 3495 } else if ((len_all - 2) == len1) { 3496 /* alg(n..) */ 3497 l2 = SPD_MAX_MAXBITS; 3498 } /* else alg(n..m) */ 3499 } 3500 3501 if (alg_type == SPD_ATTR_AH_AUTH || 3502 alg_type == SPD_ATTR_ESP_AUTH) { 3503 alg_value = valid_algorithm(IPSEC_PROTO_AH, tstr); 3504 } else { 3505 alg_value = valid_algorithm(IPSEC_PROTO_ESP, tstr); 3506 } 3507 if (alg_value < 0) { 3508 /* Invalid algorithm or "none" */ 3509 return (alg_value); 3510 } 3511 3512 if (alg_type == SPD_ATTR_AH_AUTH) { 3513 a_type = AH_AUTH; 3514 iap->iap_attr |= SPD_APPLY_AH; 3515 ap = &(iap->iap_aauth); 3516 } else if (alg_type == SPD_ATTR_ESP_AUTH) { 3517 a_type = ESP_AUTH; 3518 iap->iap_attr |= SPD_APPLY_ESP|SPD_APPLY_ESPA; 3519 ap = &(iap->iap_eauth); 3520 } else { 3521 a_type = ESP_ENCR; 3522 iap->iap_attr |= SPD_APPLY_ESP; 3523 ap = &(iap->iap_eencr); 3524 } 3525 3526 ap->alg_id = alg_value; 3527 ap->alg_minbits = l1; 3528 ap->alg_maxbits = l2; 3529 3530 if (!alg_rangecheck(a_type, alg_value, ap)) 3531 return (1); 3532 3533 return (0); 3534 } 3535 3536 static char * 3537 sys_error_message(int syserr) 3538 { 3539 char *mesg; 3540 3541 switch (syserr) { 3542 case EEXIST: 3543 mesg = gettext("Entry already exists"); 3544 break; 3545 case ENOENT: 3546 mesg = gettext("Tunnel not found"); 3547 break; 3548 case EINVAL: 3549 mesg = gettext("Invalid entry"); 3550 break; 3551 default : 3552 mesg = strerror(syserr); 3553 } 3554 return (mesg); 3555 } 3556 3557 static void 3558 error_message(error_type_t error, int type, int line) 3559 { 3560 char *mesg; 3561 3562 switch (type) { 3563 case IPSEC_CONF_SRC_ADDRESS: 3564 mesg = gettext("Source Address"); 3565 break; 3566 case IPSEC_CONF_DST_ADDRESS: 3567 mesg = gettext("Destination Address"); 3568 break; 3569 case IPSEC_CONF_SRC_PORT: 3570 mesg = gettext("Source Port"); 3571 break; 3572 case IPSEC_CONF_DST_PORT: 3573 mesg = gettext("Destination Port"); 3574 break; 3575 case IPSEC_CONF_SRC_MASK: 3576 mesg = gettext("Source Mask"); 3577 break; 3578 case IPSEC_CONF_DST_MASK: 3579 mesg = gettext("Destination Mask"); 3580 break; 3581 case IPSEC_CONF_ULP: 3582 mesg = gettext("Upper Layer Protocol"); 3583 break; 3584 case IPSEC_CONF_IPSEC_AALGS: 3585 mesg = gettext("Authentication Algorithm"); 3586 break; 3587 case IPSEC_CONF_IPSEC_EALGS: 3588 mesg = gettext("Encryption Algorithm"); 3589 break; 3590 case IPSEC_CONF_IPSEC_EAALGS: 3591 mesg = gettext("ESP Authentication Algorithm"); 3592 break; 3593 case IPSEC_CONF_IPSEC_SA: 3594 mesg = gettext("SA"); 3595 break; 3596 case IPSEC_CONF_IPSEC_DIR: 3597 mesg = gettext("Direction"); 3598 break; 3599 case IPSEC_CONF_ICMP_TYPE: 3600 mesg = gettext("ICMP type"); 3601 break; 3602 case IPSEC_CONF_ICMP_CODE: 3603 mesg = gettext("ICMP code"); 3604 break; 3605 case IPSEC_CONF_NEGOTIATE: 3606 mesg = gettext("Negotiate"); 3607 break; 3608 case IPSEC_CONF_TUNNEL: 3609 mesg = gettext("Tunnel"); 3610 break; 3611 default : 3612 return; 3613 } 3614 /* 3615 * If we never read a newline character, we don't want 3616 * to print 0. 3617 */ 3618 warnx(gettext("%s%s%s %s on line: %d"), 3619 (error == BAD_ERROR) ? gettext("Bad") : "", 3620 (error == DUP_ERROR) ? gettext("Duplicate") : "", 3621 (error == REQ_ERROR) ? gettext("Requires") : "", 3622 mesg, 3623 (arg_indices[line] == 0) ? 1 : arg_indices[line]); 3624 } 3625 3626 static int 3627 validate_properties(ips_act_props_t *cptr, boolean_t dir, boolean_t is_alg) 3628 { 3629 if (cptr->iap_action == SPD_ACTTYPE_PASS || 3630 cptr->iap_action == SPD_ACTTYPE_DROP) { 3631 if (!dir) { 3632 warnx(gettext("dir string " 3633 "not found for bypass policy")); 3634 } 3635 3636 if (is_alg) { 3637 warnx(gettext("Algorithms found for bypass policy")); 3638 return (-1); 3639 } 3640 return (0); 3641 } 3642 if (!is_alg) { 3643 warnx(gettext("No IPsec algorithms given")); 3644 return (-1); 3645 } 3646 if (cptr->iap_attr == 0) { 3647 warnx(gettext("No SA attribute")); 3648 return (-1); 3649 } 3650 return (0); 3651 } 3652 3653 /* 3654 * This function is called only to parse a single rule's worth of 3655 * action strings. This is called after parsing pattern and before 3656 * parsing properties. Thus we may have something in the leftover 3657 * buffer while parsing the pattern, which we need to handle here. 3658 */ 3659 static int 3660 parse_action(FILE *fp, char **action, char **leftover) 3661 { 3662 char *cp; 3663 char ibuf[MAXLEN]; 3664 char *tmp_buf; 3665 char *buf; 3666 boolean_t new_stuff; 3667 3668 if (*leftover != NULL) { 3669 buf = *leftover; 3670 new_stuff = B_FALSE; 3671 goto scan; 3672 } 3673 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3674 new_stuff = B_TRUE; 3675 if (ibuf[strlen(ibuf) - 1] == '\n') 3676 linecount++; 3677 buf = ibuf; 3678 scan: 3679 /* Truncate at the beginning of a comment */ 3680 cp = strchr(buf, '#'); 3681 if (cp != NULL) 3682 *cp = NULL; 3683 3684 /* Skip any whitespace */ 3685 while (*buf != NULL && isspace(*buf)) 3686 buf++; 3687 3688 /* Empty line */ 3689 if (*buf == NULL) 3690 continue; 3691 3692 /* 3693 * Store the command for error reporting 3694 * and ipsec_conf_add(). 3695 */ 3696 if (new_stuff) { 3697 /* 3698 * Check for buffer overflow including the null 3699 * terminating character. 3700 */ 3701 int len = strlen(ibuf); 3702 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3703 return (-1); 3704 3705 (void) strcpy(cbuf + cbuf_offset, ibuf); 3706 cbuf_offset += len; 3707 } 3708 /* 3709 * Start of the non-empty non-space character. 3710 */ 3711 tmp_buf = buf; 3712 3713 /* Skip until next whitespace or CURL_BEGIN */ 3714 while (*buf != NULL && !isspace(*buf) && 3715 *buf != CURL_BEGIN) 3716 buf++; 3717 3718 if (*buf != NULL) { 3719 if (tmp_buf == buf) /* No action token */ 3720 goto error; 3721 if (*buf == CURL_BEGIN) { 3722 *buf = NULL; 3723 /* Allocate an extra byte for the null also */ 3724 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3725 NULL) { 3726 warn("malloc"); 3727 return (ENOMEM); 3728 } 3729 (void) strcpy(*action, tmp_buf); 3730 *buf = CURL_BEGIN; 3731 } else { 3732 /* We have hit a space */ 3733 *buf++ = NULL; 3734 /* Allocate an extra byte for the null also */ 3735 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3736 NULL) { 3737 warn("malloc"); 3738 return (ENOMEM); 3739 } 3740 (void) strcpy(*action, tmp_buf); 3741 } 3742 /* 3743 * Copy the rest of the line into the 3744 * leftover buffer. 3745 */ 3746 if (*buf != NULL) { 3747 (void) strlcpy(lo_buf, buf, sizeof (lo_buf)); 3748 *leftover = lo_buf; 3749 } else { 3750 *leftover = NULL; 3751 } 3752 } else { 3753 /* Allocate an extra byte for the null also */ 3754 if ((*action = malloc(strlen(tmp_buf) + 1)) == 3755 NULL) { 3756 warn("malloc"); 3757 return (ENOMEM); 3758 } 3759 (void) strcpy(*action, tmp_buf); 3760 *leftover = NULL; 3761 } 3762 if (argindex >= ARG_BUF_LEN) { 3763 warnx(gettext("(parsing one command) " 3764 "Too many selectors before action.")); 3765 return (-1); 3766 } 3767 arg_indices[argindex++] = linecount; 3768 return (PARSE_SUCCESS); 3769 } 3770 /* 3771 * Return error, on an empty action field. 3772 */ 3773 error: 3774 warnx(gettext("(parsing one command) " 3775 "Missing action token.")); 3776 return (-1); 3777 } 3778 3779 /* 3780 * This is called to parse pattern or properties that is enclosed 3781 * between CURL_BEGIN and CURL_END. 3782 */ 3783 static int 3784 parse_pattern_or_prop(FILE *fp, char *argvec[], char **leftover) 3785 { 3786 char *cp; 3787 int i = 0; 3788 boolean_t curl_begin_seen = B_FALSE; 3789 char ibuf[MAXLEN]; 3790 char *tmp_buf; 3791 char *buf; 3792 boolean_t new_stuff; 3793 3794 /* 3795 * When parsing properties, leftover buffer could have the 3796 * leftovers of the previous fgets(). 3797 */ 3798 if (*leftover != NULL) { 3799 buf = *leftover; 3800 new_stuff = B_FALSE; 3801 goto scan; 3802 } 3803 while (fgets(ibuf, MAXLEN, fp) != NULL) { 3804 new_stuff = B_TRUE; 3805 #ifdef DEBUG_HEAVY 3806 (void) printf("%s\n", ibuf); 3807 #endif 3808 if (ibuf[strlen(ibuf) - 1] == '\n') 3809 linecount++; 3810 buf = ibuf; 3811 scan: 3812 /* Truncate at the beginning of a comment */ 3813 cp = strchr(buf, '#'); 3814 if (cp != NULL) 3815 *cp = NULL; 3816 3817 /* Skip any whitespace */ 3818 while (*buf != NULL && isspace(*buf)) 3819 buf++; 3820 3821 /* Empty line */ 3822 if (*buf == NULL) 3823 continue; 3824 /* 3825 * Store the command for error reporting 3826 * and ipsec_conf_add(). 3827 */ 3828 if (new_stuff) { 3829 /* 3830 * Check for buffer overflow including the null 3831 * terminating character. 3832 */ 3833 int len = strlen(ibuf); 3834 if ((cbuf_offset + len + 1) >= CBUF_LEN) 3835 return (-1); 3836 (void) strcpy(cbuf + cbuf_offset, ibuf); 3837 cbuf_offset += len; 3838 } 3839 /* 3840 * First non-space character should be 3841 * a curly bracket. 3842 */ 3843 if (!curl_begin_seen) { 3844 if (*buf != CURL_BEGIN) { 3845 /* 3846 * If we never read a newline character, 3847 * we don't want to print 0. 3848 */ 3849 warnx(gettext("line %d : pattern must start " 3850 "with \"%c\" character"), 3851 (linecount == 0) ? 1 : linecount, 3852 CURL_BEGIN); 3853 return (-1); 3854 } 3855 buf++; 3856 curl_begin_seen = B_TRUE; 3857 } 3858 /* 3859 * Arguments are separated by white spaces or 3860 * newlines. Scan till you see a CURL_END. 3861 */ 3862 while (*buf != NULL) { 3863 if (*buf == CURL_END) { 3864 ret: 3865 *buf++ = NULL; 3866 /* 3867 * Copy the rest of the line into the 3868 * leftover buffer if any. 3869 */ 3870 if (*buf != NULL) { 3871 (void) strlcpy(lo_buf, buf, 3872 sizeof (lo_buf)); 3873 *leftover = lo_buf; 3874 } else { 3875 *leftover = NULL; 3876 } 3877 return (PARSE_SUCCESS); 3878 } 3879 /* 3880 * Skip any trailing whitespace until we see a 3881 * non white-space character. 3882 */ 3883 while (*buf != NULL && isspace(*buf)) 3884 buf++; 3885 3886 if (*buf == CURL_END) 3887 goto ret; 3888 3889 /* Scan the next line as this buffer is empty */ 3890 if (*buf == NULL) 3891 break; 3892 3893 if (i >= MAXARGS) { 3894 warnx( 3895 gettext("Number of Arguments exceeded %d"), 3896 i); 3897 return (-1); 3898 } 3899 /* 3900 * Non-empty, Non-space buffer. 3901 */ 3902 tmp_buf = buf++; 3903 /* 3904 * Real scan of the argument takes place here. 3905 * Skip past till space or CURL_END. 3906 */ 3907 while (*buf != NULL && !isspace(*buf) && 3908 *buf != CURL_END) { 3909 buf++; 3910 } 3911 /* 3912 * Either a space or we have hit the CURL_END or 3913 * the real end. 3914 */ 3915 if (*buf != NULL) { 3916 if (*buf == CURL_END) { 3917 *buf++ = NULL; 3918 if ((argvec[i] = malloc(strlen(tmp_buf) 3919 + 1)) == NULL) { 3920 warn("malloc"); 3921 return (ENOMEM); 3922 } 3923 if (strlen(tmp_buf) != 0) { 3924 (void) strcpy(argvec[i], 3925 tmp_buf); 3926 if (argindex >= ARG_BUF_LEN) 3927 goto toomanyargs; 3928 arg_indices[argindex++] = 3929 linecount; 3930 } 3931 /* 3932 * Copy the rest of the line into the 3933 * leftover buffer. 3934 */ 3935 if (*buf != NULL) { 3936 (void) strlcpy(lo_buf, buf, 3937 sizeof (lo_buf)); 3938 *leftover = lo_buf; 3939 } else { 3940 *leftover = NULL; 3941 } 3942 return (PARSE_SUCCESS); 3943 } else { 3944 *buf++ = NULL; 3945 } 3946 } 3947 /* 3948 * Copy this argument and scan for the buffer more 3949 * if it is non-empty. If it is empty scan for 3950 * the next line. 3951 */ 3952 if ((argvec[i] = malloc(strlen(tmp_buf) + 1)) == 3953 NULL) { 3954 warn("malloc"); 3955 return (ENOMEM); 3956 } 3957 (void) strcpy(argvec[i++], tmp_buf); 3958 if (argindex >= ARG_BUF_LEN) { 3959 /* 3960 * The number of tokens in a single policy entry 3961 * exceeds the number of buffers available to fully 3962 * parse the policy entry. 3963 */ 3964 toomanyargs: 3965 warnx(gettext("(parsing one command) " 3966 "Too many tokens in single policy entry.")); 3967 return (-1); 3968 } 3969 arg_indices[argindex++] = linecount; 3970 } 3971 } 3972 /* 3973 * If nothing is given in the file, it is okay. 3974 * If something is given in the file and it is 3975 * not CURL_BEGIN, we would have returned error 3976 * above. If curl_begin_seen and we are here, 3977 * something is wrong. 3978 */ 3979 if (curl_begin_seen) { 3980 warnx(gettext("(parsing one command) " 3981 "Pattern or Properties incomplete.")); 3982 return (-1); 3983 } 3984 return (PARSE_EOF); /* Nothing more in the file */ 3985 } 3986 3987 /* 3988 * Parse one command i.e {pattern} action {properties}. 3989 * 3990 * {pattern} ( action {prop} | pass | drop ) (or ...)* 3991 */ 3992 static int 3993 parse_one(FILE *fp, act_prop_t *act_props) 3994 { 3995 char *leftover; 3996 int ret; 3997 int i; 3998 int ap_num = 0; 3999 enum parse_state {pattern, action, prop } pstate; 4000 4001 has_daprefix = has_saprefix = B_FALSE; 4002 4003 (void) memset(act_props, 0, sizeof (act_prop_t)); 4004 pstate = pattern; 4005 4006 ret = 0; 4007 leftover = NULL; 4008 argindex = 0; 4009 cbuf_offset = 0; 4010 assert(shp == NULL && dhp == NULL); 4011 4012 for (;;) { 4013 switch (pstate) { 4014 case pattern: 4015 { 4016 #ifdef DEBUG_HEAVY 4017 (void) printf("pattern\n"); 4018 #endif 4019 ret = parse_pattern_or_prop(fp, 4020 act_props->pattern, &leftover); 4021 if (ret == PARSE_EOF) { 4022 /* EOF reached */ 4023 return (PARSE_EOF); 4024 } 4025 if (ret != 0) { 4026 ret = -1; 4027 goto err; 4028 } 4029 pstate = action; 4030 break; 4031 } 4032 case action: 4033 { 4034 #ifdef DEBUG_HEAVY 4035 (void) printf("action\n"); 4036 #endif 4037 ret = parse_action(fp, 4038 &act_props->ap[ap_num].act, &leftover); 4039 if (ret != 0) { 4040 ret = -1; 4041 goto err; 4042 } 4043 4044 /* 4045 * Validate action now itself so that we don't 4046 * proceed too much into the bad world. 4047 */ 4048 for (i = 0; action_table[i].string; i++) { 4049 if (strcmp(act_props->ap[ap_num].act, 4050 action_table[i].string) == 0) 4051 break; 4052 } 4053 4054 if (action_table[i].tok_val == TOK_or) { 4055 /* hit an or, go again */ 4056 break; 4057 } 4058 4059 if (action_table[i].string == NULL) { 4060 /* 4061 * If we never read a newline 4062 * character, we don't want 4063 * to print 0. 4064 */ 4065 warnx(gettext("(parsing one command) " 4066 "Invalid action on line %d: %s"), 4067 (linecount == 0) ? 1 : linecount, 4068 act_props->ap[ap_num].act); 4069 return (-1); 4070 } 4071 4072 pstate = prop; 4073 break; 4074 } 4075 case prop: 4076 { 4077 #ifdef DEBUG_HEAVY 4078 (void) printf("prop\n"); 4079 #endif 4080 ret = parse_pattern_or_prop(fp, 4081 act_props->ap[ap_num].prop, &leftover); 4082 if (ret != 0) { 4083 if (ret == PARSE_EOF) { 4084 warnx(gettext("(parsing one command) " 4085 "Missing properties.")); 4086 } 4087 ret = -1; 4088 goto err; 4089 } 4090 4091 if (leftover != NULL) { 4092 /* Accomodate spaces at the end */ 4093 while (*leftover != NULL) { 4094 if (*leftover == BACK_SLASH) { 4095 warnx(gettext("Invalid line " 4096 "continuation character.")); 4097 ret = -1; 4098 goto err; 4099 } 4100 if (*leftover == 'o') { 4101 leftover++; 4102 if (*leftover == 'r') { 4103 leftover++; 4104 ap_num++; 4105 pstate = action; 4106 goto again; 4107 } 4108 } 4109 if (!isspace(*leftover)) { 4110 ret = -1; 4111 goto err; 4112 } 4113 leftover++; 4114 } 4115 return (0); 4116 } 4117 ap_num++; 4118 if (ap_num > MAXARGS) 4119 return (0); 4120 pstate = action; /* or */ 4121 break; 4122 } /* case prop: */ 4123 } /* switch(pstate) */ 4124 4125 again: 4126 if (ap_num > MAXARGS) { 4127 warnx(gettext("Too many actions.")); 4128 return (-1); 4129 } 4130 } /* for(;;) */ 4131 err: 4132 if (ret != 0) { 4133 /* 4134 * If we never read a newline character, we don't want 4135 * to print 0. 4136 */ 4137 warnx(gettext("Error before or at line %d"), 4138 (linecount == 0) ? 1 : linecount); 4139 } 4140 return (ret); 4141 } 4142 4143 /* 4144 * convert an act_propts_t to an ips_conf_t 4145 */ 4146 4147 static int 4148 form_ipsec_conf(act_prop_t *act_props, ips_conf_t *cptr) 4149 { 4150 int i, j, k; 4151 int tok_count = 0; 4152 struct protoent *pent; 4153 boolean_t saddr, daddr, ipsec_aalg, ipsec_ealg, ipsec_eaalg, dir; 4154 boolean_t old_style, new_style; 4155 struct in_addr mask; 4156 int line_no; 4157 int ret; 4158 int ap_num = 0; 4159 int type, code, type_end, code_end; 4160 #ifdef DEBUG_HEAVY 4161 /* 4162 * pattern => act_props->pattern 4163 * action => act_props->ap[].act 4164 * properties => act_props->ap[].prop 4165 */ 4166 (void) printf("\npattern\n------------\n"); 4167 for (i = 0; act_props->pattern[i] != NULL; i++) 4168 (void) printf("%s\n", act_props->pattern[i]); 4169 (void) printf("apz\n----------\n"); 4170 for (j = 0; act_props->ap[j].act != NULL; j++) { 4171 4172 (void) printf("act%d->%s\n", j, act_props->ap[j].act); 4173 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 4174 (void) printf("%dprop%d->%s\n", 4175 j, i, act_props->ap[j].prop[i]); 4176 } 4177 (void) printf("------------\n\n"); 4178 #endif 4179 4180 (void) memset(cptr, 0, sizeof (ips_conf_t)); 4181 saddr = daddr = ipsec_aalg = ipsec_ealg = ipsec_eaalg = dir = B_FALSE; 4182 old_style = new_style = B_FALSE; 4183 /* 4184 * Get the Pattern. NULL pattern is valid. 4185 */ 4186 for (i = 0, line_no = 0; act_props->pattern[i]; i++, line_no++) { 4187 for (j = 0; pattern_table[j].string; j++) { 4188 if (strcmp(act_props->pattern[i], 4189 pattern_table[j].string) == 0) 4190 break; 4191 } 4192 4193 if (pattern_table[j].string == NULL) { 4194 /* 4195 * If we never read a newline character, we don't want 4196 * to print 0. 4197 */ 4198 warnx(gettext("Invalid pattern on line %d: %s"), 4199 (arg_indices[line_no] == 0) ? 1 : 4200 arg_indices[line_no], act_props->pattern[i]); 4201 return (-1); 4202 } 4203 4204 cptr->patt_tok[tok_count++] = pattern_table[j].tok_val; 4205 4206 switch (pattern_table[j].tok_val) { 4207 4208 case TOK_dir: 4209 i++, line_no++; 4210 if (act_props->pattern[i] == NULL) { 4211 error_message(BAD_ERROR, 4212 IPSEC_CONF_IPSEC_DIR, line_no); 4213 return (-1); 4214 } 4215 4216 if (strncmp(act_props->pattern[i], "in", 2) == 0) { 4217 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4218 } else if (strncmp( 4219 act_props->pattern[i], "out", 3) == 0) { 4220 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4221 } else if (strncmp( 4222 act_props->pattern[i], "both", 4) == 0) { 4223 if (old_style) { 4224 error_message(BAD_ERROR, 4225 IPSEC_CONF_IPSEC_DIR, line_no); 4226 return (-1); 4227 } 4228 new_style = B_TRUE; 4229 cptr->ips_dir = 4230 SPD_RULE_FLAG_OUTBOUND | 4231 SPD_RULE_FLAG_INBOUND; 4232 } else { 4233 error_message(BAD_ERROR, 4234 IPSEC_CONF_IPSEC_DIR, line_no); 4235 return (-1); 4236 } 4237 dir = B_TRUE; 4238 break; 4239 4240 case TOK_local: 4241 if (old_style) { 4242 error_message(BAD_ERROR, 4243 IPSEC_CONF_SRC_ADDRESS, line_no); 4244 return (-1); 4245 } 4246 new_style = B_TRUE; 4247 4248 if (saddr) { 4249 error_message(DUP_ERROR, 4250 IPSEC_CONF_SRC_ADDRESS, line_no); 4251 return (-1); 4252 } 4253 /* 4254 * Use this to detect duplicates rather 4255 * than 0 like other cases, because 0 for 4256 * address means INADDR_ANY. 4257 */ 4258 saddr = B_TRUE; 4259 cptr->has_saddr = 1; 4260 /* 4261 * Advance to the string containing 4262 * the address. 4263 */ 4264 i++, line_no++; 4265 if (act_props->pattern[i] == NULL) { 4266 error_message(BAD_ERROR, 4267 IPSEC_CONF_SRC_ADDRESS, line_no); 4268 return (-1); 4269 } 4270 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4271 act_props->pattern[i]) != 0) { 4272 error_message(BAD_ERROR, 4273 IPSEC_CONF_SRC_ADDRESS, line_no); 4274 return (-1); 4275 } 4276 if (!cptr->has_smask) 4277 cptr->has_smask = has_saprefix; 4278 4279 break; 4280 case TOK_remote: 4281 if (old_style) { 4282 error_message(BAD_ERROR, 4283 IPSEC_CONF_DST_ADDRESS, line_no); 4284 return (-1); 4285 } 4286 new_style = B_TRUE; 4287 4288 if (daddr) { 4289 error_message(DUP_ERROR, 4290 IPSEC_CONF_DST_ADDRESS, line_no); 4291 return (-1); 4292 } 4293 /* 4294 * Use this to detect duplicates rather 4295 * than 0 like other cases, because 0 for 4296 * address means INADDR_ANY. 4297 */ 4298 daddr = B_TRUE; 4299 cptr->has_daddr = 1; 4300 /* 4301 * Advance to the string containing 4302 * the address. 4303 */ 4304 i++, line_no++; 4305 if (act_props->pattern[i] == NULL) { 4306 error_message(BAD_ERROR, 4307 IPSEC_CONF_DST_ADDRESS, line_no); 4308 return (-1); 4309 } 4310 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4311 act_props->pattern[i]) != 0) { 4312 error_message(BAD_ERROR, 4313 IPSEC_CONF_DST_ADDRESS, line_no); 4314 return (-1); 4315 } 4316 if (!cptr->has_dmask) 4317 cptr->has_dmask = has_daprefix; 4318 break; 4319 4320 case TOK_saddr: 4321 if (new_style) { 4322 error_message(BAD_ERROR, 4323 IPSEC_CONF_SRC_ADDRESS, line_no); 4324 return (-1); 4325 } 4326 old_style = B_TRUE; 4327 4328 if (saddr) { 4329 error_message(DUP_ERROR, 4330 IPSEC_CONF_SRC_ADDRESS, line_no); 4331 return (-1); 4332 } 4333 /* 4334 * Use this to detect duplicates rather 4335 * than 0 like other cases, because 0 for 4336 * address means INADDR_ANY. 4337 */ 4338 saddr = B_TRUE; 4339 cptr->has_saddr = 1; 4340 /* 4341 * Advance to the string containing 4342 * the address. 4343 */ 4344 i++, line_no++; 4345 if (act_props->pattern[i] == NULL) { 4346 error_message(BAD_ERROR, 4347 IPSEC_CONF_SRC_ADDRESS, line_no); 4348 return (-1); 4349 } 4350 4351 if (parse_address(IPSEC_CONF_SRC_ADDRESS, 4352 act_props->pattern[i]) != 0) { 4353 error_message(BAD_ERROR, 4354 IPSEC_CONF_SRC_ADDRESS, line_no); 4355 return (-1); 4356 } 4357 /* shp or bhp? */ 4358 if (!cptr->has_smask) 4359 cptr->has_smask = has_saprefix; 4360 break; 4361 4362 case TOK_daddr: 4363 if (new_style) { 4364 error_message(BAD_ERROR, 4365 IPSEC_CONF_DST_ADDRESS, line_no); 4366 return (-1); 4367 } 4368 old_style = B_TRUE; 4369 4370 if (daddr) { 4371 error_message(DUP_ERROR, 4372 IPSEC_CONF_DST_ADDRESS, line_no); 4373 return (-1); 4374 } 4375 /* 4376 * Use this to detect duplicates rather 4377 * than 0 like other cases, because 0 for 4378 * address means INADDR_ANY. 4379 */ 4380 daddr = B_TRUE; 4381 cptr->has_daddr = 1; 4382 /* 4383 * Advance to the string containing 4384 * the address. 4385 */ 4386 i++, line_no++; 4387 if (act_props->pattern[i] == NULL) { 4388 error_message(BAD_ERROR, 4389 IPSEC_CONF_DST_ADDRESS, line_no); 4390 return (-1); 4391 } 4392 if (parse_address(IPSEC_CONF_DST_ADDRESS, 4393 act_props->pattern[i]) != 0) { 4394 error_message(BAD_ERROR, 4395 IPSEC_CONF_DST_ADDRESS, line_no); 4396 return (-1); 4397 } 4398 if (!cptr->has_dmask) 4399 cptr->has_dmask = has_daprefix; 4400 break; 4401 4402 case TOK_sport: 4403 if (new_style) { 4404 error_message(BAD_ERROR, 4405 IPSEC_CONF_SRC_PORT, line_no); 4406 return (-1); 4407 } 4408 old_style = B_TRUE; 4409 4410 if (cptr->ips_src_port_min != 0) { 4411 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4412 line_no); 4413 return (-1); 4414 } 4415 i++, line_no++; 4416 if (act_props->pattern[i] == NULL) { 4417 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4418 line_no); 4419 return (-1); 4420 } 4421 ret = parse_port(IPSEC_CONF_SRC_PORT, 4422 act_props->pattern[i], cptr); 4423 if (ret != 0) { 4424 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4425 line_no); 4426 return (-1); 4427 } 4428 break; 4429 case TOK_dport: 4430 if (new_style) { 4431 error_message(BAD_ERROR, 4432 IPSEC_CONF_DST_PORT, line_no); 4433 return (-1); 4434 } 4435 old_style = B_TRUE; 4436 4437 if (cptr->ips_dst_port_min != 0) { 4438 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4439 line_no); 4440 return (-1); 4441 } 4442 i++, line_no++; 4443 if (act_props->pattern[i] == NULL) { 4444 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4445 line_no); 4446 return (-1); 4447 } 4448 ret = parse_port(IPSEC_CONF_DST_PORT, 4449 act_props->pattern[i], 4450 cptr); 4451 if (ret != 0) { 4452 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4453 line_no); 4454 return (-1); 4455 } 4456 break; 4457 4458 case TOK_lport: 4459 if (old_style) { 4460 error_message(BAD_ERROR, 4461 IPSEC_CONF_SRC_PORT, line_no); 4462 return (-1); 4463 } 4464 new_style = B_TRUE; 4465 4466 if (cptr->ips_src_port_min != 0) { 4467 error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 4468 line_no); 4469 return (-1); 4470 } 4471 i++, line_no++; 4472 if (act_props->pattern[i] == NULL) { 4473 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4474 line_no); 4475 return (-1); 4476 } 4477 ret = parse_port(IPSEC_CONF_SRC_PORT, 4478 act_props->pattern[i], 4479 cptr); 4480 if (ret != 0) { 4481 error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 4482 line_no); 4483 return (-1); 4484 } 4485 break; 4486 4487 case TOK_rport: 4488 if (old_style) { 4489 error_message(BAD_ERROR, 4490 IPSEC_CONF_DST_PORT, line_no); 4491 return (-1); 4492 } 4493 new_style = B_TRUE; 4494 4495 if (cptr->ips_dst_port_min != 0) { 4496 error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 4497 line_no); 4498 return (-1); 4499 } 4500 i++, line_no++; 4501 if (act_props->pattern[i] == NULL) { 4502 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4503 line_no); 4504 return (-1); 4505 } 4506 ret = parse_port(IPSEC_CONF_DST_PORT, 4507 act_props->pattern[i], 4508 cptr); 4509 if (ret != 0) { 4510 error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 4511 line_no); 4512 return (-1); 4513 } 4514 break; 4515 4516 case TOK_smask: 4517 if (new_style) { 4518 error_message(BAD_ERROR, 4519 IPSEC_CONF_SRC_MASK, line_no); 4520 return (-1); 4521 } 4522 old_style = B_TRUE; 4523 cptr->has_smask = B_TRUE; 4524 4525 IN6_V4MAPPED_TO_INADDR(&cptr->ips_src_mask_v6, &mask); 4526 if (mask.s_addr != 0) { 4527 error_message(DUP_ERROR, IPSEC_CONF_SRC_MASK, 4528 line_no); 4529 return (-1); 4530 } 4531 i++, line_no++; 4532 if (act_props->pattern[i] == NULL) { 4533 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4534 line_no); 4535 return (-1); 4536 } 4537 ret = parse_mask(IPSEC_CONF_SRC_MASK, 4538 act_props->pattern[i], 4539 cptr); 4540 if (ret != 0) { 4541 error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 4542 line_no); 4543 return (-1); 4544 } 4545 break; 4546 case TOK_dmask: 4547 if (new_style) { 4548 error_message(BAD_ERROR, 4549 IPSEC_CONF_DST_MASK, line_no); 4550 return (-1); 4551 } 4552 old_style = B_TRUE; 4553 cptr->has_dmask = B_TRUE; 4554 4555 IN6_V4MAPPED_TO_INADDR(&cptr->ips_dst_mask_v6, &mask); 4556 if (mask.s_addr != 0) { 4557 error_message(DUP_ERROR, IPSEC_CONF_DST_MASK, 4558 line_no); 4559 return (-1); 4560 } 4561 i++, line_no++; 4562 if (act_props->pattern[i] == NULL) { 4563 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4564 line_no); 4565 return (-1); 4566 } 4567 ret = parse_mask(IPSEC_CONF_DST_MASK, 4568 act_props->pattern[i], 4569 cptr); 4570 if (ret != 0) { 4571 error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 4572 line_no); 4573 return (-1); 4574 } 4575 break; 4576 case TOK_ulp: 4577 if (cptr->ips_ulp_prot != 0) { 4578 error_message(DUP_ERROR, 4579 IPSEC_CONF_ULP, line_no); 4580 return (-1); 4581 } 4582 i++, line_no++; 4583 if (act_props->pattern[i] == NULL) { 4584 error_message(BAD_ERROR, 4585 IPSEC_CONF_ULP, line_no); 4586 return (-1); 4587 } 4588 pent = getprotobyname(act_props->pattern[i]); 4589 if (pent == NULL) { 4590 int ulp; 4591 ulp = parse_int(act_props->pattern[i]); 4592 if (ulp == -1) { 4593 error_message(BAD_ERROR, 4594 IPSEC_CONF_ULP, line_no); 4595 return (-1); 4596 } 4597 cptr->ips_ulp_prot = ulp; 4598 } else { 4599 cptr->ips_ulp_prot = pent->p_proto; 4600 } 4601 break; 4602 case TOK_type: 4603 if (cptr->has_type) { 4604 error_message(DUP_ERROR, 4605 IPSEC_CONF_ICMP_TYPE, line_no); 4606 return (-1); 4607 } 4608 4609 i++, line_no++; 4610 type = parse_type_code(act_props->pattern[i], 4611 icmp_type_table); 4612 4613 if (type > 65536 || type < 0) { 4614 error_message(BAD_ERROR, 4615 IPSEC_CONF_ICMP_TYPE, line_no); 4616 return (-1); 4617 } 4618 4619 type_end = type / 256; 4620 type = type % 256; 4621 4622 if (type_end < type) 4623 type_end = type; 4624 4625 cptr->has_type = 1; 4626 cptr->ips_icmp_type = (uint8_t)type; 4627 cptr->ips_icmp_type_end = (uint8_t)type_end; 4628 break; 4629 case TOK_code: 4630 if (!cptr->has_type) { 4631 error_message(BAD_ERROR, 4632 IPSEC_CONF_ICMP_CODE, line_no); 4633 return (-1); 4634 } 4635 4636 if (cptr->has_code) { 4637 error_message(DUP_ERROR, 4638 IPSEC_CONF_ICMP_CODE, line_no); 4639 return (-1); 4640 } 4641 4642 i++, line_no++; 4643 4644 code = parse_type_code(act_props->pattern[i], 4645 icmp_code_table); 4646 if (type > 65536 || type < 0) { 4647 error_message(BAD_ERROR, 4648 IPSEC_CONF_ICMP_CODE, line_no); 4649 return (-1); 4650 } 4651 code_end = code / 256; 4652 code = code % 256; 4653 4654 if (code_end < code) 4655 code_end = code; 4656 4657 cptr->has_code = 1; 4658 cptr->ips_icmp_code = (uint8_t)code; 4659 cptr->ips_icmp_code_end = (uint8_t)code_end; 4660 break; 4661 case TOK_tunnel: 4662 if (cptr->has_tunnel == 1) { 4663 error_message(BAD_ERROR, 4664 IPSEC_CONF_TUNNEL, line_no); 4665 return (-1); 4666 } 4667 i++, line_no++; 4668 if (act_props->pattern[i] == NULL) { 4669 error_message(BAD_ERROR, 4670 IPSEC_CONF_TUNNEL, line_no); 4671 return (-1); 4672 } 4673 4674 if (strlcpy(tunif, act_props->pattern[i], 4675 TUNNAMEMAXLEN) >= TUNNAMEMAXLEN) { 4676 error_message(BAD_ERROR, 4677 IPSEC_CONF_TUNNEL, line_no); 4678 return (-1); 4679 } 4680 cptr->has_tunnel = 1; 4681 break; 4682 case TOK_negotiate: 4683 if (cptr->has_negotiate == 1) { 4684 error_message(BAD_ERROR, 4685 IPSEC_CONF_NEGOTIATE, line_no); 4686 return (-1); 4687 } 4688 i++, line_no++; 4689 if (act_props->pattern[i] == NULL) { 4690 error_message(BAD_ERROR, 4691 IPSEC_CONF_NEGOTIATE, line_no); 4692 return (-1); 4693 } 4694 4695 if (strncmp(act_props->pattern[i], "tunnel", 6) == 0) { 4696 cptr->ips_tunnel = B_TRUE; 4697 } else if (strncmp( 4698 act_props->pattern[i], "transport", 9) != 0) { 4699 error_message(BAD_ERROR, 4700 IPSEC_CONF_NEGOTIATE, line_no); 4701 return (-1); 4702 } 4703 cptr->has_negotiate = 1; 4704 break; 4705 } 4706 4707 } 4708 4709 /* Sanity check that certain tokens occur together */ 4710 if (cptr->has_tunnel + cptr->has_negotiate == 1) { 4711 if (cptr->has_negotiate == 0) { 4712 error_message(REQ_ERROR, IPSEC_CONF_NEGOTIATE, line_no); 4713 } else { 4714 error_message(REQ_ERROR, IPSEC_CONF_TUNNEL, line_no); 4715 } 4716 errx(1, gettext( 4717 "tunnel and negotiate tokens must occur together")); 4718 return (-1); 4719 } 4720 4721 /* 4722 * Get the actions. 4723 */ 4724 4725 for (ap_num = 0; act_props->ap[ap_num].act != NULL; ap_num++) { 4726 ips_act_props_t *iap; 4727 4728 if (ap_num > 0) { 4729 /* or's only with new style */ 4730 if (old_style) { 4731 (void) printf("%s\n", gettext( 4732 "or's only with new style")); 4733 return (-1); 4734 } 4735 new_style = B_TRUE; 4736 } 4737 4738 ipsec_aalg = ipsec_ealg = ipsec_eaalg = B_FALSE; 4739 tok_count = 0; 4740 4741 for (k = 0; action_table[k].string; k++) { 4742 if (strcmp(act_props->ap[ap_num].act, 4743 action_table[k].string) == 0) 4744 break; 4745 } 4746 /* 4747 * The following thing should never happen as 4748 * we have already tested for its validity in parse. 4749 */ 4750 if (action_table[k].string == NULL) { 4751 warnx(gettext("(form act)Invalid action on line " 4752 "%d: %s"), (arg_indices[line_no] == 0) ? 1 : 4753 arg_indices[line_no], 4754 act_props->ap[ap_num].act); 4755 warnx("%s", act_props->ap[ap_num].act); 4756 return (-1); 4757 } 4758 4759 /* we have a good action alloc an iap */ 4760 iap = alloc_iap(cptr); 4761 4762 iap->iap_action = action_table[k].value; 4763 iap->iap_act_tok = action_table[k].tok_val; 4764 4765 switch (action_table[k].tok_val) { 4766 case TOK_apply: 4767 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4768 break; 4769 case TOK_permit: 4770 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4771 break; 4772 case TOK_ipsec: 4773 if (old_style) { 4774 /* Using saddr/daddr with ipsec action. */ 4775 if (!dir) { 4776 /* No direction specified */ 4777 error_message(REQ_ERROR, 4778 IPSEC_CONF_IPSEC_DIR, line_no); 4779 return (-1); 4780 } 4781 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 4782 /* 4783 * Need to swap addresses if 4784 * 'dir in' or translation to 4785 * laddr/raddr will be incorrect. 4786 */ 4787 cptr->swap = 1; 4788 } 4789 if (!dir) 4790 cptr->ips_dir = 4791 SPD_RULE_FLAG_INBOUND 4792 |SPD_RULE_FLAG_OUTBOUND; 4793 break; 4794 case TOK_bypass: 4795 /* do something? */ 4796 break; 4797 } 4798 4799 line_no++; 4800 /* 4801 * Get the properties. NULL properties is not valid. 4802 * Later checks will catch it. 4803 */ 4804 for (i = 0; act_props->ap[ap_num].prop[i]; i++, line_no++) { 4805 for (j = 0; property_table[j].string; j++) { 4806 if (strcmp(act_props->ap[ap_num].prop[i], 4807 property_table[j].string) == 0) { 4808 break; 4809 } 4810 } 4811 if (property_table[j].string == NULL) { 4812 warnx(gettext("Invalid properties on line " 4813 "%d: %s"), 4814 (arg_indices[line_no] == 0) ? 4815 1 : arg_indices[line_no], 4816 act_props->ap[ap_num].prop[i]); 4817 return (-1); 4818 } 4819 4820 iap->iap_attr_tok[tok_count++] 4821 = property_table[j].value; 4822 4823 switch (property_table[j].value) { 4824 case SPD_ATTR_AH_AUTH: 4825 if (ipsec_aalg) { 4826 error_message(DUP_ERROR, 4827 IPSEC_CONF_IPSEC_AALGS, line_no); 4828 return (-1); 4829 } 4830 i++, line_no++; 4831 if (act_props->ap[ap_num].prop[i] == NULL) { 4832 error_message(BAD_ERROR, 4833 IPSEC_CONF_IPSEC_AALGS, line_no); 4834 return (-1); 4835 } 4836 ret = parse_ipsec_alg( 4837 act_props->ap[ap_num].prop[i], 4838 iap, SPD_ATTR_AH_AUTH); 4839 if (ret == -2) { 4840 /* "none" - ignore */ 4841 break; 4842 } 4843 if (ret != 0) { 4844 error_message(BAD_ERROR, 4845 IPSEC_CONF_IPSEC_AALGS, line_no); 4846 return (-1); 4847 } 4848 ipsec_aalg = B_TRUE; 4849 break; 4850 case SPD_ATTR_ESP_ENCR: 4851 /* 4852 * If this option was not given 4853 * and encr_auth_algs was given, 4854 * we provide null-encryption. We do the 4855 * setting after we parse all the options. 4856 */ 4857 if (ipsec_ealg) { 4858 error_message(DUP_ERROR, 4859 IPSEC_CONF_IPSEC_EALGS, line_no); 4860 return (-1); 4861 } 4862 i++, line_no++; 4863 if (act_props->ap[ap_num].prop[i] == NULL) { 4864 error_message(BAD_ERROR, 4865 IPSEC_CONF_IPSEC_EALGS, line_no); 4866 return (-1); 4867 } 4868 ret = parse_ipsec_alg( 4869 act_props->ap[ap_num].prop[i], 4870 iap, SPD_ATTR_ESP_ENCR); 4871 if (ret == -2) { 4872 /* "none" - ignore */ 4873 break; 4874 } 4875 if (ret != 0) { 4876 error_message(BAD_ERROR, 4877 IPSEC_CONF_IPSEC_EALGS, line_no); 4878 return (-1); 4879 } 4880 ipsec_ealg = B_TRUE; 4881 break; 4882 case SPD_ATTR_ESP_AUTH: 4883 /* 4884 * If this option was not given and encr_algs 4885 * option was given, we still pass a default 4886 * value in ipsc_esp_auth_algs. This is to 4887 * encourage the use of authentication with 4888 * ESP. 4889 */ 4890 if (ipsec_eaalg) { 4891 error_message(DUP_ERROR, 4892 IPSEC_CONF_IPSEC_EAALGS, line_no); 4893 return (-1); 4894 } 4895 i++, line_no++; 4896 if (act_props->ap[ap_num].prop[i] == NULL) { 4897 error_message(BAD_ERROR, 4898 IPSEC_CONF_IPSEC_EAALGS, line_no); 4899 return (-1); 4900 } 4901 ret = parse_ipsec_alg( 4902 act_props->ap[ap_num].prop[i], 4903 iap, SPD_ATTR_ESP_AUTH); 4904 if (ret == -2) { 4905 /* "none" - ignore */ 4906 break; 4907 } 4908 if (ret != 0) { 4909 error_message(BAD_ERROR, 4910 IPSEC_CONF_IPSEC_EAALGS, line_no); 4911 return (-1); 4912 } 4913 ipsec_eaalg = B_TRUE; 4914 break; 4915 case IPS_SA: 4916 i++, line_no++; 4917 if (act_props->ap[ap_num].prop[i] == NULL) { 4918 error_message(BAD_ERROR, 4919 IPSEC_CONF_IPSEC_SA, line_no); 4920 return (-1); 4921 } 4922 4923 if (strcmp(act_props->ap[ap_num].prop[i], 4924 "unique") == 0) { 4925 iap->iap_attr |= SPD_APPLY_UNIQUE; 4926 } else if (strcmp(act_props->ap[ap_num].prop[i], 4927 "shared") != 0) { 4928 /* "shared" is default. */ 4929 error_message(BAD_ERROR, 4930 IPSEC_CONF_IPSEC_SA, line_no); 4931 return (-1); 4932 } 4933 4934 break; 4935 case IPS_DIR: 4936 if (dir) { 4937 error_message(DUP_ERROR, 4938 IPSEC_CONF_IPSEC_DIR, line_no); 4939 return (-1); 4940 } 4941 if (new_style) { 4942 error_message(BAD_ERROR, 4943 IPSEC_CONF_IPSEC_DIR, line_no); 4944 return (-1); 4945 } 4946 old_style = B_TRUE; 4947 dir = B_TRUE; 4948 i++, line_no++; 4949 if (act_props->ap[ap_num].prop[i] == NULL) { 4950 error_message(BAD_ERROR, 4951 IPSEC_CONF_IPSEC_DIR, line_no); 4952 return (-1); 4953 } 4954 if (strcmp(act_props->ap[ap_num].prop[i], 4955 "out") == 0) { 4956 cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 4957 } else if (strcmp(act_props->ap[ap_num].prop[i], 4958 "in") == 0) { 4959 cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 4960 } else { 4961 error_message(BAD_ERROR, 4962 IPSEC_CONF_IPSEC_DIR, line_no); 4963 return (-1); 4964 } 4965 if ((cptr->ips_dir & SPD_RULE_FLAG_INBOUND) && 4966 iap->iap_act_tok == TOK_apply) { 4967 warnx(gettext("Direction" 4968 " in conflict with action")); 4969 return (-1); 4970 } 4971 if ((cptr->ips_dir & SPD_RULE_FLAG_OUTBOUND) && 4972 iap->iap_act_tok == TOK_permit) { 4973 warnx(gettext("Direction" 4974 "in conflict with action")); 4975 return (-1); 4976 } 4977 4978 break; 4979 } 4980 } 4981 4982 if (!ipsec_ealg && ipsec_eaalg) { 4983 /* 4984 * If the user has specified the auth alg to be used 4985 * with encryption and did not provide a encryption 4986 * algorithm, provide null encryption. 4987 */ 4988 iap->iap_eencr.alg_id = SADB_EALG_NULL; 4989 ipsec_ealg = B_TRUE; 4990 } 4991 4992 /* Set the level of IPSEC protection we want */ 4993 if (ipsec_aalg && (ipsec_ealg || ipsec_eaalg)) { 4994 iap->iap_attr |= SPD_APPLY_AH|SPD_APPLY_ESP; 4995 } else if (ipsec_aalg) { 4996 iap->iap_attr |= SPD_APPLY_AH; 4997 } else if (ipsec_ealg || ipsec_eaalg) { 4998 iap->iap_attr |= SPD_APPLY_ESP; 4999 } 5000 5001 /* convert src/dst to local/remote */ 5002 if (!new_style) { 5003 switch (cptr->ips_acts->iap_act_tok) { 5004 case TOK_apply: 5005 /* outbound */ 5006 /* src=local, dst=remote */ 5007 /* this is ok. */ 5008 break; 5009 5010 case TOK_permit: 5011 /* inbound */ 5012 /* src=remote, dst=local */ 5013 /* switch */ 5014 cptr->swap = 1; 5015 break; 5016 case TOK_bypass: 5017 case TOK_drop: 5018 /* check the direction for what to do */ 5019 if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 5020 cptr->swap = 1; 5021 break; 5022 default: 5023 break; 5024 } 5025 } 5026 /* Validate the properties */ 5027 if (ret = validate_properties(iap, dir, 5028 (ipsec_aalg || ipsec_ealg || ipsec_eaalg))) { 5029 return (ret); 5030 } 5031 } 5032 5033 return (0); 5034 5035 } 5036 5037 static int 5038 print_cmd_buf(FILE *fp, int error) 5039 { 5040 *(cbuf + cbuf_offset) = '\0'; 5041 5042 if (fp == stderr) { 5043 if (error != EEXIST) { 5044 warnx(gettext("Malformed command (fatal):\n%s"), cbuf); 5045 return (0); 5046 } 5047 if (ipsecconf_qflag) { 5048 return (0); 5049 } 5050 warnx(gettext("Duplicate policy entry (ignored):\n%s"), cbuf); 5051 } else { 5052 if (fprintf(fp, "%s", cbuf) == -1) { 5053 warn("fprintf"); 5054 return (-1); 5055 } 5056 } 5057 5058 return (0); 5059 } 5060 5061 #ifdef DEBUG 5062 5063 static uchar_t * 5064 addr_ptr(int isv4, struct in6_addr *addr6, struct in_addr *addr4) 5065 { 5066 if (isv4) { 5067 IN6_V4MAPPED_TO_INADDR(addr6, addr4); 5068 return ((uchar_t *)&addr4->s_addr); 5069 } else { 5070 return ((uchar_t *)&addr6->s6_addr); 5071 } 5072 } 5073 5074 static void 5075 dump_algreq(const char *tag, algreq_t *alg) 5076 { 5077 (void) printf("%s algid %d, bits %d..%d\n", 5078 tag, alg->alg_id, alg->alg_minbits, alg->alg_maxbits); 5079 } 5080 5081 static void 5082 dump_conf(ips_conf_t *conf) 5083 { 5084 boolean_t isv4 = conf->ips_isv4; 5085 struct in_addr addr; 5086 char buf[INET6_ADDRSTRLEN]; 5087 int af; 5088 ips_act_props_t *iap = conf->ips_acts; 5089 5090 af = isv4 ? AF_INET : AF_INET6; 5091 5092 (void) printf("Source Addr is %s\n", 5093 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_addr_v6, &addr), 5094 buf, INET6_ADDRSTRLEN)); 5095 5096 (void) printf("Dest Addr is %s\n", 5097 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_addr_v6, &addr), 5098 buf, INET6_ADDRSTRLEN)); 5099 5100 (void) printf("Source Mask is %s\n", 5101 inet_ntop(af, addr_ptr(isv4, &conf->ips_src_mask_v6, &addr), 5102 buf, INET6_ADDRSTRLEN)); 5103 5104 (void) printf("Dest Mask is %s\n", 5105 inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_mask_v6, &addr), 5106 buf, INET6_ADDRSTRLEN)); 5107 5108 (void) printf("Source port %d\n", ntohs(conf->ips_src_port_min)); 5109 (void) printf("Dest port %d\n", ntohs(conf->ips_dst_port_min)); 5110 (void) printf("ULP %d\n", conf->ips_ulp_prot); 5111 5112 (void) printf("ICMP type %d-%d code %d-%d", conf->ips_icmp_type, 5113 conf->ips_icmp_type_end, 5114 conf->ips_icmp_code, 5115 conf->ips_icmp_code_end); 5116 5117 while (iap != NULL) { 5118 (void) printf("------------------------------------\n"); 5119 (void) printf("IPsec act is %d\n", iap->iap_action); 5120 (void) printf("IPsec attr is %d\n", iap->iap_attr); 5121 dump_algreq("AH authentication", &iap->iap_aauth); 5122 dump_algreq("ESP authentication", &iap->iap_eauth); 5123 dump_algreq("ESP encryption", &iap->iap_eencr); 5124 (void) printf("------------------------------------\n"); 5125 iap = iap->iap_next; 5126 } 5127 5128 (void) fflush(stdout); 5129 } 5130 #endif /* DEBUG */ 5131 5132 5133 static int 5134 ipsec_conf_add(boolean_t just_check, boolean_t smf_managed) 5135 { 5136 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5137 ips_conf_t conf; 5138 FILE *fp, *policy_fp; 5139 int ret, flushret, i, j, diag, num_rules, good_rules; 5140 char *warning = gettext( 5141 "\tWARNING : New policy entries that are being added may\n " 5142 "\taffect the existing connections. Existing connections\n" 5143 "\tthat are not subjected to policy constraints, may be\n" 5144 "\tsubjected to policy constraints because of the new\n" 5145 "\tpolicy. This can disrupt the communication of the\n" 5146 "\texisting connections.\n\n"); 5147 5148 boolean_t first_time = B_TRUE; 5149 num_rules = 0; 5150 good_rules = 0; 5151 5152 if (act_props == NULL) { 5153 warn(gettext("memory")); 5154 return (-1); 5155 } 5156 5157 if (strcmp(filename, "-") == 0) 5158 fp = stdin; 5159 else 5160 fp = fopen(filename, "r"); 5161 5162 /* 5163 * Treat the non-existence of a policy file as a special 5164 * case when ipsecconf is being managed by smf(5). 5165 * The assumption is the administrator has not yet 5166 * created a policy file, this should not force the service 5167 * into maintenance mode. 5168 */ 5169 5170 if (fp == NULL) { 5171 if (smf_managed) { 5172 (void) fprintf(stdout, gettext( 5173 "Policy configuration file (%s) does not exist.\n" 5174 "IPsec policy not configured.\n"), filename); 5175 return (0); 5176 } 5177 warn(gettext("%s : Policy config file cannot be opened"), 5178 filename); 5179 usage(); 5180 return (-1); 5181 } 5182 /* 5183 * This will create the file if it does not exist. 5184 * Make sure the umask is right. 5185 */ 5186 (void) umask(0022); 5187 policy_fp = fopen(POLICY_CONF_FILE, "a"); 5188 if (policy_fp == NULL) { 5189 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5190 return (-1); 5191 } 5192 5193 /* 5194 * Pattern, action, and properties are allocated in 5195 * parse_pattern_or_prop and in parse_action (called by 5196 * parse_one) as we parse arguments. 5197 */ 5198 while ((ret = parse_one(fp, act_props)) != PARSE_EOF) { 5199 num_rules++; 5200 if (ret != 0) { 5201 (void) print_cmd_buf(stderr, NOERROR); 5202 continue; 5203 } 5204 5205 /* 5206 * If there is no action and parse returned success, 5207 * it means that there is nothing to add. 5208 */ 5209 if (act_props->pattern[0] == NULL && 5210 act_props->ap[0].act == NULL) 5211 break; 5212 5213 ret = form_ipsec_conf(act_props, &conf); 5214 if (ret != 0) { 5215 warnx(gettext("form_ipsec_conf error")); 5216 (void) print_cmd_buf(stderr, NOERROR); 5217 /* Reset globals before trying the next rule. */ 5218 if (shp != NULL) { 5219 freehostent(shp); 5220 shp = NULL; 5221 } 5222 if (dhp != NULL) { 5223 freehostent(dhp); 5224 dhp = NULL; 5225 } 5226 splen = 0; 5227 dplen = 0; 5228 continue; 5229 } 5230 5231 good_rules++; 5232 5233 if (first_time) { 5234 /* 5235 * Time to assume that there are valid policy entries. 5236 * If the IPsec kernel modules are not loaded this 5237 * will load them now. 5238 */ 5239 first_time = B_FALSE; 5240 fetch_algorithms(); 5241 ipsec_conf_admin(SPD_CLONE); 5242 } 5243 5244 /* 5245 * shp, dhp, splen, and dplen are globals set by 5246 * form_ipsec_conf() while parsing the addresses. 5247 */ 5248 if (shp == NULL && dhp == NULL) { 5249 switch (do_port_adds(&conf)) { 5250 case 0: 5251 /* no error */ 5252 break; 5253 case EEXIST: 5254 /* duplicate entries, continue adds */ 5255 (void) print_cmd_buf(stderr, EEXIST); 5256 goto next; 5257 default: 5258 /* other error, bail */ 5259 ret = -1; 5260 goto bail; 5261 } 5262 } else { 5263 ret = do_address_adds(&conf, &diag); 5264 switch (ret) { 5265 case 0: 5266 /* no error. */ 5267 break; 5268 case EEXIST: 5269 (void) print_cmd_buf(stderr, EEXIST); 5270 goto next; 5271 case EBUSY: 5272 warnx(gettext( 5273 "Can't set mask and /NN prefix.")); 5274 ret = -1; 5275 break; 5276 case ENOENT: 5277 warnx(gettext("Cannot find tunnel " 5278 "interface %s."), interface_name); 5279 ret = -1; 5280 break; 5281 case EINVAL: 5282 /* 5283 * PF_POLICY didn't like what we sent. We 5284 * can't check all input up here, but we 5285 * do in-kernel. 5286 */ 5287 warnx(gettext("PF_POLICY invalid input:\n\t%s"), 5288 spdsock_diag(diag)); 5289 break; 5290 case EOPNOTSUPP: 5291 warnx(gettext("Can't set /NN" 5292 " prefix on multi-host name.")); 5293 ret = -1; 5294 break; 5295 case ERANGE: 5296 warnx(gettext("/NN prefix is too big!")); 5297 ret = -1; 5298 break; 5299 case ESRCH: 5300 warnx(gettext("No matching IPv4 or " 5301 "IPv6 saddr/daddr pairs")); 5302 ret = -1; 5303 break; 5304 default: 5305 /* Should never get here. */ 5306 errno = ret; 5307 warn(gettext("Misc. error")); 5308 ret = -1; 5309 } 5310 if (ret == -1) 5311 goto bail; 5312 } 5313 5314 /* 5315 * Go ahead and add policy entries to config file. 5316 * The # should help re-using the ipsecpolicy.conf 5317 * for input again as # will be treated as comment. 5318 */ 5319 if (fprintf(policy_fp, "%s %lld \n", INDEX_TAG, 5320 conf.ips_policy_index) == -1) { 5321 warn("fprintf"); 5322 warnx(gettext("Addition incomplete, Please " 5323 "flush all the entries and re-configure :")); 5324 reconfigure(); 5325 ret = -1; 5326 break; 5327 } 5328 if (print_cmd_buf(policy_fp, NOERROR) == -1) { 5329 warnx(gettext("Addition incomplete. Please " 5330 "flush all the entries and re-configure :")); 5331 reconfigure(); 5332 ret = -1; 5333 break; 5334 } 5335 /* 5336 * We add one newline by default to separate out the 5337 * entries. If the last character is not a newline, we 5338 * insert a newline for free. This makes sure that all 5339 * entries look consistent in the file. 5340 */ 5341 if (*(cbuf + cbuf_offset - 1) == '\n') { 5342 if (fprintf(policy_fp, "\n") == -1) { 5343 warn("fprintf"); 5344 warnx(gettext("Addition incomplete. " 5345 "Please flush all the entries and " 5346 "re-configure :")); 5347 reconfigure(); 5348 ret = -1; 5349 break; 5350 } 5351 } else { 5352 if (fprintf(policy_fp, "\n\n") == -1) { 5353 warn("fprintf"); 5354 warnx(gettext("Addition incomplete. " 5355 "Please flush all the entries and " 5356 "re-configure :")); 5357 reconfigure(); 5358 ret = -1; 5359 break; 5360 } 5361 } 5362 next: 5363 /* 5364 * Make sure this gets to the disk before 5365 * we parse the next entry. 5366 */ 5367 (void) fflush(policy_fp); 5368 for (i = 0; act_props->pattern[i] != NULL; i++) 5369 free(act_props->pattern[i]); 5370 for (j = 0; act_props->ap[j].act != NULL; j++) { 5371 free(act_props->ap[j].act); 5372 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5373 free(act_props->ap[j].prop[i]); 5374 } 5375 } 5376 if (ret == PARSE_EOF) 5377 ret = 0; /* Not an error */ 5378 bail: 5379 if (ret == -1) { 5380 (void) print_cmd_buf(stderr, EINVAL); 5381 for (i = 0; act_props->pattern[i] != NULL; i++) 5382 free(act_props->pattern[i]); 5383 for (j = 0; act_props->ap[j].act != NULL; j++) { 5384 free(act_props->ap[j].act); 5385 for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 5386 free(act_props->ap[j].prop[i]); 5387 } 5388 } 5389 #ifdef DEBUG_HEAVY 5390 (void) printf("ipsec_conf_add: ret val = %d\n", ret); 5391 (void) fflush(stdout); 5392 #endif 5393 if (num_rules == 0 && ret == 0) { 5394 nuke_adds(); 5395 (void) restore_all_signals(); 5396 (void) unlock(lfd); 5397 EXIT_OK("Policy file does not contain any valid rules."); 5398 } 5399 if (num_rules != good_rules) { 5400 /* This is an error */ 5401 nuke_adds(); 5402 (void) restore_all_signals(); 5403 (void) unlock(lfd); 5404 EXIT_BADCONFIG2("%d policy rule(s) contained errors.", 5405 num_rules - good_rules); 5406 } 5407 /* looks good, flip it in */ 5408 if (ret == 0 && !just_check) { 5409 if (!ipsecconf_qflag) { 5410 (void) printf("%s", warning); 5411 } 5412 if (smf_managed) 5413 warnx(gettext("%d policy rules added."), good_rules); 5414 ipsec_conf_admin(SPD_FLIP); 5415 } else { 5416 nuke_adds(); 5417 if (just_check) { 5418 (void) fprintf(stdout, gettext("IPsec configuration " 5419 "does not contain any errors.\n")); 5420 (void) fprintf(stdout, gettext( 5421 "IPsec policy was not modified.\n")); 5422 (void) fflush(stdout); 5423 } 5424 } 5425 flushret = ipsec_conf_flush(SPD_STANDBY); 5426 if (flushret != 0) 5427 return (flushret); 5428 return (ret); 5429 } 5430 5431 5432 static int 5433 ipsec_conf_sub() 5434 { 5435 act_prop_t *act_props = malloc(sizeof (act_prop_t)); 5436 FILE *remove_fp, *policy_fp; 5437 char rbuf[MAXLEN], pbuf[MAXLEN], /* remove buffer, and policy buffer */ 5438 *warning = gettext( 5439 "\tWARNING: Policy entries that are being removed may\n" 5440 "\taffect the existing connections. Existing connections\n" 5441 "\tthat are subjected to policy constraints may no longer\n" 5442 "\tbe subjected to policy contraints because of its\n" 5443 "\tremoval. This can compromise security, and disrupt\n" 5444 "\tthe communication of the existing connection.\n" 5445 "\tConnections that are latched will remain unaffected\n" 5446 "\tuntil they close.\n"); 5447 int ret = 0; 5448 int index_len, pindex = 0; /* init value in case of pfile error */ 5449 5450 if (act_props == NULL) { 5451 warn(gettext("memory")); 5452 return (-1); 5453 } 5454 5455 /* clone into standby DB */ 5456 (void) ipsec_conf_admin(SPD_CLONE); 5457 5458 if (strcmp(filename, "-") == 0) 5459 remove_fp = stdin; 5460 else 5461 remove_fp = fopen(filename, "r"); 5462 5463 if (remove_fp == NULL) { 5464 warn(gettext("%s : Input file cannot be opened"), filename); 5465 usage(); 5466 free(act_props); 5467 return (-1); 5468 } 5469 5470 /* open policy file so we can locate the correct policy */ 5471 (void) umask(0022); /* in case it gets created! */ 5472 policy_fp = fopen(POLICY_CONF_FILE, "r+"); 5473 if (policy_fp == NULL) { 5474 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 5475 (void) fclose(remove_fp); 5476 free(act_props); 5477 return (-1); 5478 } 5479 5480 /* don't print the warning if we're in q[uiet] mode */ 5481 if (!ipsecconf_qflag) 5482 (void) printf("%s", warning); 5483 5484 /* this bit is done primarily so we can read what we write */ 5485 index_len = strlen(INDEX_TAG); 5486 5487 /* 5488 * We want to look for the policy in rbuf in the policy file. 5489 * Go through the list of policies to remove, locating each one. 5490 */ 5491 while (fgets(rbuf, MAXLEN, remove_fp) != NULL) { 5492 char *buf; 5493 int offset, prev_offset, prev_prev_offset, nlines; 5494 fpos_t ipos; 5495 int pbuf_len = 0; 5496 char *tmp; 5497 /* skip blanks here (so we don't need to do it below)! */ 5498 for (tmp = rbuf; (*tmp != '\0') && isspace(*tmp); ) 5499 tmp++; 5500 5501 if (*tmp == '\0') 5502 continue; /* while(); */ 5503 5504 /* skip the INDEX_TAG lines in the remove buffer */ 5505 if (strncasecmp(rbuf, INDEX_TAG, index_len) == 0) 5506 continue; 5507 5508 /* skip commented lines */ 5509 if (*tmp == '#') 5510 continue; /* while(); */ 5511 5512 /* 5513 * We start by presuming only good policies are in the pfile, 5514 * and so only good policies from the rfile will match them. 5515 * ipsec_conf_del ensures this later by calling parse_one() on 5516 * pfile before it deletes the entry. 5517 */ 5518 for (offset = prev_offset = prev_prev_offset = 0; 5519 fgets(pbuf, MAXLEN, policy_fp) != NULL; 5520 offset += pbuf_len) { 5521 prev_offset = offset; 5522 pbuf_len = strlen(pbuf); 5523 5524 /* skip blank lines which seperate policy entries */ 5525 if (pbuf[0] == '\n') 5526 continue; 5527 5528 /* if we found an index, save it */ 5529 if (strncasecmp(pbuf, INDEX_TAG, index_len) == 0) { 5530 buf = pbuf + index_len; 5531 buf++; 5532 if ((pindex = parse_index(buf, NULL)) == -1) { 5533 /* bad index, we can't continue */ 5534 warnx(gettext( 5535 "Invalid index in the file")); 5536 (void) fclose(remove_fp); 5537 (void) fclose(policy_fp); 5538 free(act_props); 5539 return (-1); 5540 } 5541 5542 /* save this position in case it's the one */ 5543 if (fgetpos(policy_fp, &ipos) != 0) { 5544 (void) fclose(remove_fp); 5545 (void) fclose(policy_fp); 5546 free(act_props); 5547 return (-1); 5548 } 5549 } 5550 5551 /* Does pbuf contain the remove policy? */ 5552 if (strncasecmp(rbuf, pbuf, pbuf_len) == 0) { 5553 /* we found the one to remove! */ 5554 if (pindex == 0) { 5555 warnx(gettext("Didn't find a valid " 5556 "index for policy")); 5557 (void) fclose(remove_fp); 5558 (void) fclose(policy_fp); 5559 free(act_props); 5560 return (-1); 5561 } 5562 5563 /* off it - back up to the last INDEX! */ 5564 if (fsetpos(policy_fp, &ipos) != 0) { 5565 (void) fclose(remove_fp); 5566 (void) fclose(policy_fp); 5567 free(act_props); 5568 return (-1); 5569 } 5570 5571 /* parse_one sets linecount = #lines to off */ 5572 if (parse_one(policy_fp, act_props) == -1) { 5573 warnx(gettext("Invalid policy entry " 5574 "in the file")); 5575 (void) fclose(remove_fp); 5576 (void) fclose(policy_fp); 5577 free(act_props); 5578 return (-1); 5579 } 5580 5581 nlines = linecount + 2; 5582 goto delete; 5583 } 5584 /* 5585 * When we find a match, we want to pass the offset 5586 * of the line that is before it - the INDEX_TAG line. 5587 */ 5588 prev_prev_offset = prev_offset; 5589 } 5590 /* Didn't find a match - look at the next remove policy */ 5591 continue; /* while(); */ 5592 5593 delete: 5594 (void) fclose(policy_fp); 5595 5596 if (delete_from_file(prev_prev_offset, nlines) != 0) { 5597 warnx(gettext("delete_from_file failure. " 5598 "Please flush all entries and re-configure :")); 5599 reconfigure(); 5600 (void) fclose(remove_fp); 5601 free(act_props); 5602 return (-1); 5603 } 5604 5605 if (pfp_delete_rule(pindex) != 0) { 5606 warnx(gettext("Deletion incomplete. Please flush" 5607 "all the entries and re-configure :")); 5608 reconfigure(); 5609 (void) fclose(remove_fp); 5610 free(act_props); 5611 return (-1); 5612 } 5613 5614 /* reset the globals */ 5615 linecount = 0; 5616 pindex = 0; 5617 /* free(NULL) also works. */ 5618 free(interface_name); 5619 interface_name = NULL; 5620 5621 /* reopen for next pass, automagically starting over. */ 5622 policy_fp = fopen(POLICY_CONF_FILE, "r"); 5623 if (policy_fp == NULL) { 5624 warn(gettext("%s cannot be re-opened, can't continue"), 5625 POLICY_CONF_FILE); 5626 (void) fclose(remove_fp); 5627 free(act_props); 5628 return (-1); 5629 } 5630 5631 } /* read next remove policy */ 5632 5633 if ((ret = pfp_delete_rule(pindex)) != 0) { 5634 warnx(gettext("Removal incomplete. Please flush " 5635 "all the entries and re-configure :")); 5636 reconfigure(); 5637 free(act_props); 5638 return (ret); 5639 } 5640 5641 /* nothing left to look for */ 5642 (void) fclose(remove_fp); 5643 free(act_props); 5644 5645 return (0); 5646 } 5647 5648 /* 5649 * Constructs a tunnel interface ID extension. Returns the length 5650 * of the extension in 64-bit-words. 5651 */ 5652 static int 5653 attach_tunname(spd_if_t *tunname) 5654 { 5655 if (tunname == NULL || interface_name == NULL) 5656 return (0); 5657 5658 tunname->spd_if_exttype = SPD_EXT_TUN_NAME; 5659 /* 5660 * Use "-3" because there's 4 bytes in the message itself, and 5661 * we lose one because of the '\0' terminator. 5662 */ 5663 tunname->spd_if_len = SPD_8TO64( 5664 P2ROUNDUP(sizeof (*tunname) + strlen(interface_name) - 3, 8)); 5665 (void) strlcpy((char *)tunname->spd_if_name, interface_name, LIFNAMSIZ); 5666 return (tunname->spd_if_len); 5667 } 5668