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