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