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