4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
35 #include <arpa/inet.h>
39 #include <sys/param.h>
40 #include <sys/sysmacros.h> /* MIN, MAX */
41 #include <sys/sockio.h>
42 #include <net/pfkeyv2.h>
43 #include <net/pfpolicy.h>
44 #include <inet/ipsec_impl.h>
48 #include <sys/socket.h>
49 #include <sys/systeminfo.h>
50 #include <nss_dbdefs.h> /* NSS_BUFLEN_HOSTS */
51 #include <netinet/in.h>
54 #include <ipsec_util.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/ip_icmp.h>
57 #include <netinet/icmp6.h>
66 #define USAGE() if (!smf_managed) usage()
68 * Buffer length to read in pattern/properties.
72 /* Max length of tunnel interface string identifier */
73 #define TUNNAMEMAXLEN LIFNAMSIZ
76 * Used by parse_one and parse/parse_action to communicate
77 * the errors. -1 is failure, which is not defined here.
79 enum parse_errors
{PARSE_SUCCESS
, PARSE_EOF
};
82 * For spdsock_get_ext() diagnostics.
84 #define SPDSOCK_DIAG_BUF_LEN 128
85 static char spdsock_diag_buf
[SPDSOCK_DIAG_BUF_LEN
];
88 * Define CURL here so that while you are reading
89 * this code, it does not affect "vi" in pattern
92 #define CURL_BEGIN '{'
94 #define BACK_SLASH '\\'
99 * IPSEC_CONF_ADD should start with 1, so that when multiple commands
100 * are given, we can fail the request.
103 enum ipsec_cmds
{IPSEC_CONF_ADD
= 1, IPSEC_CONF_DEL
, IPSEC_CONF_VIEW
,
104 IPSEC_CONF_FLUSH
, IPSEC_CONF_LIST
, IPSEC_CONF_SUB
, IPSEC_CONF_REPLACE
};
106 static const char policy_conf_file
[] = "/var/run/ipsecpolicy.conf";
107 static const char lock_file
[] = "/var/run/ipsecconf.lock";
108 static const char index_tag
[] = "#INDEX";
110 #define POLICY_CONF_FILE policy_conf_file
111 #define LOCK_FILE lock_file
112 #define INDEX_TAG index_tag
115 * Valid algorithm length.
117 #define VALID_ALG_LEN 40
119 /* Types of Error messages */
120 typedef enum error_type
{BAD_ERROR
, DUP_ERROR
, REQ_ERROR
} error_type_t
;
122 /* Error message human readable conversions */
123 static char *sys_error_message(int);
124 static void error_message(error_type_t
, int, int);
125 static int get_pf_pol_socket(void);
128 static char *filename
;
129 static char lo_buf
[MAXLEN
]; /* Leftover buffer */
132 * The new SPD_EXT_TUN_NAME extension has a tunnel name in it. Use the empty
133 * string ("", stored in the char value "all_polheads") for all policy heads
134 * (global and all tunnels). Set interface_name to NULL for global-only, or
135 * specify a name of an IP-in-IP tunnel.
137 static char *interface_name
;
138 static char all_polheads
; /* So we can easily get "". */
140 /* Error reporting stuff */
141 #define CBUF_LEN 8192 /* Maximum size of the cmd */
143 * Following are used for reporting errors with arguments.
144 * We store the line numbers of each argument as we parse them,
145 * so that the error reporting is more specific. We can have only
146 * (MAXARGS - 1) arguments between any pair of CURL_BEGIN CURL_END.
147 * Because a single command can be made up of multiple action/property
148 * combinations, the maximum command size is (2 * (MAXARGS -1)) for each
149 * of patterns, properties and actions.
151 #define ARG_BUF_LEN ((2 * 3 * (MAXARGS - 1)) + 1)
152 static int arg_indices
[ARG_BUF_LEN
];
154 static int linecount
;
155 static char cbuf
[CBUF_LEN
]; /* Command buffer */
156 static int cbuf_offset
;
159 #define BYPASS_POLICY_BOOST 0x00800000
160 #define ESP_POLICY_BOOST 0x00400000
161 #define AH_POLICY_BOOST 0x00200000
162 #define INITIAL_BASE_PRIORITY 0x000fffff
165 * the number used to order the
166 * rules starts at a certain base and
167 * goes down. i.e. rules earlier in
168 * the file are checked first
170 static uint32_t priority
= INITIAL_BASE_PRIORITY
;
178 * for deleting adds on error
181 typedef struct d_list_s
183 struct d_list_s
*next
;
187 static d_list_t
*d_list
= NULL
;
188 static d_list_t
*d_tail
= NULL
;
192 * Used for multi-homed source/dest hosts.
194 static struct hostent
*shp
, *dhp
;
195 static unsigned int splen
, dplen
;
196 static char tunif
[TUNNAMEMAXLEN
];
197 static boolean_t has_saprefix
, has_daprefix
;
198 static uint32_t seq_cnt
= 0;
200 /* lexxed out action and related properties */
204 char *prop
[MAXARGS
+ 1];
208 /* one lexxed out rule */
209 typedef struct act_prop_s
{
210 char *pattern
[MAXARGS
+ 1];
211 ap_t ap
[MAXARGS
+ 1];
217 uint32_t alg_minbits
;
218 uint32_t alg_maxbits
;
221 /* structure to hold all information for one act_prop_t */
222 typedef struct ips_act_props_s
{
223 struct ips_act_props_s
*iap_next
;
224 struct ips_conf_s
*iap_head
;
227 * IPsec action types (in SPD_ATTR_TYPE attribute)
228 * SPD_ACTTYPE_DROP 0x0001
229 * SPD_ACTTYPE_PASS 0x0002
230 * SPD_ACTTYPE_IPSEC 0x0003
233 uint16_t iap_act_tok
;
236 * Action ATTR flags (in SPD_ATTR_FLAGS attribute)
237 * SPD_APPLY_AH 0x0001
238 * SPD_APPLY_ESP 0x0002
239 * SPD_APPLY_SE 0x0004 * self-encapsulation *
240 * SPD_APPLY_COMP 0x0008 * compression; NYI *
241 * SPD_APPLY_UNIQUE 0x0010 * unique per-flow SA *
242 * SPD_APPLY_BYPASS 0x0020 * bypass policy *
245 uint16_t iap_attr_tok
[5];
251 uint32_t iap_life_soft_time
;
252 uint32_t iap_life_hard_time
;
253 uint32_t iap_life_soft_bytes
;
254 uint32_t iap_life_hard_bytes
;
258 #define V4_PART_OF_V6(v6) v6._S6_un._S6_u32[3]
260 typedef struct ips_conf_s
{
262 uint16_t patt_tok
[8];
269 uint8_t has_negotiate
;
273 struct in6_addr ips_src_addr_v6
;
274 struct in6_addr ips_src_mask_v6
;
275 struct in6_addr ips_dst_addr_v6
;
276 struct in6_addr ips_dst_mask_v6
;
277 uint8_t ips_src_mask_len
;
278 uint8_t ips_dst_mask_len
;
279 in_port_t ips_src_port_min
;
280 in_port_t ips_src_port_max
;
281 in_port_t ips_dst_port_min
;
282 in_port_t ips_dst_port_max
;
283 uint8_t ips_icmp_type
;
284 uint8_t ips_icmp_type_end
;
285 uint8_t ips_icmp_code
;
286 uint8_t ips_icmp_code_end
;
287 uint8_t ips_ulp_prot
;
288 uint8_t ips_ipsec_prot
;
291 * SPD_RULE_FLAG_INBOUND 0x0001
292 * SPD_RULE_FLAG_OUTBOUND 0x0002
296 * Keep track of tunnel separately due to explosion of ways to set
299 boolean_t ips_tunnel
;
300 uint64_t ips_policy_index
;
301 uint32_t ips_act_cnt
;
302 ips_act_props_t
*ips_acts
;
305 #define ips_src_addr V4_PART_OF_V6(ips_src_addr_v6)
306 #define ips_dst_addr V4_PART_OF_V6(ips_dst_addr_v6)
308 static int ipsecconf_nflag
; /* Used only with -l option */
309 static int ipsecconf_qflag
; /* Used only with -a|-r option */
311 typedef struct str_val
{
316 typedef struct str_tval
{
322 static int parse_int(const char *);
323 static int parse_index(const char *, char *);
324 static int attach_tunname(spd_if_t
*);
325 static void usage(void);
326 static int ipsec_conf_del(int, boolean_t
);
327 static int ipsec_conf_add(boolean_t
, boolean_t
, boolean_t
);
328 static int ipsec_conf_sub(void);
329 static int ipsec_conf_flush(int);
330 static int ipsec_conf_view(void);
331 static int ipsec_conf_list(void);
332 static int lock(void);
333 static int unlock(int);
334 static int parse_one(FILE *, act_prop_t
*);
335 static void reconfigure();
336 static void in_prefixlentomask(unsigned int, uchar_t
*);
337 static int in_getprefixlen(char *);
338 static int parse_address(int, char *);
340 static void pfpol_msg_dump(spd_msg_t
*msg
, char *);
341 #endif /* DEBUG_HEAVY */
342 static void print_pfpol_msg(spd_msg_t
*);
343 static int pfp_delete_rule(uint64_t);
344 static void ipsec_conf_admin(uint8_t);
345 static void print_bit_range(int, int);
346 static void nuke_adds();
347 static boolean_t
combined_mode(uint_t
);
350 static void dump_conf(ips_conf_t
*);
362 static int ipsec_nalgs
[3];
363 static alginfo_t known_algs
[3][256];
365 #define IPS_SRC_MASK SPD_EXT_LCLADDR + 100
366 #define IPS_DST_MASK SPD_EXT_REMADDR + 100
369 * if inbound, src=remote, dst=local
370 * if outbound, src=local, dst=remote
382 #define TOK_remote 10
387 #define TOK_negotiate 15
388 #define TOK_tunnel 16
390 #define IPS_SA SPD_ATTR_END
391 #define IPS_DIR SPD_ATTR_EMPTY
392 #define IPS_NEG SPD_ATTR_NOP
395 static str_tval_t pattern_table
[] = {
396 {"saddr", TOK_saddr
, SPD_EXT_LCLADDR
},
397 {"src", TOK_saddr
, SPD_EXT_LCLADDR
},
398 {"srcaddr", TOK_saddr
, SPD_EXT_LCLADDR
},
399 {"daddr", TOK_daddr
, SPD_EXT_REMADDR
},
400 {"dst", TOK_daddr
, SPD_EXT_REMADDR
},
401 {"dstaddr", TOK_daddr
, SPD_EXT_REMADDR
},
402 {"sport", TOK_sport
, SPD_EXT_LCLPORT
},
403 {"dport", TOK_dport
, SPD_EXT_REMPORT
},
404 {"smask", TOK_smask
, IPS_SRC_MASK
},
405 {"dmask", TOK_dmask
, IPS_DST_MASK
},
406 {"ulp", TOK_ulp
, SPD_EXT_PROTO
},
407 {"proto", TOK_ulp
, SPD_EXT_PROTO
},
408 {"local", TOK_local
, SPD_EXT_LCLADDR
},
409 {"laddr", TOK_local
, SPD_EXT_LCLADDR
},
410 {"lport", TOK_lport
, SPD_EXT_LCLPORT
},
411 {"remote", TOK_remote
, SPD_EXT_REMADDR
},
412 {"raddr", TOK_remote
, SPD_EXT_REMADDR
},
413 {"rport", TOK_rport
, SPD_EXT_REMPORT
},
414 {"dir", TOK_dir
, IPS_DIR
},
415 {"type", TOK_type
, SPD_EXT_ICMP_TYPECODE
},
416 {"code", TOK_code
, SPD_EXT_ICMP_TYPECODE
},
417 {"negotiate", TOK_negotiate
, IPS_NEG
},
418 {"tunnel", TOK_tunnel
, SPD_EXT_TUN_NAME
},
429 static str_tval_t action_table
[] = {
430 {"apply", TOK_apply
, SPD_ACTTYPE_IPSEC
},
431 {"permit", TOK_permit
, SPD_ACTTYPE_IPSEC
},
432 {"ipsec", TOK_ipsec
, SPD_ACTTYPE_IPSEC
},
433 {"bypass", TOK_bypass
, SPD_ACTTYPE_PASS
},
434 {"pass", TOK_bypass
, SPD_ACTTYPE_PASS
},
435 {"drop", TOK_drop
, SPD_ACTTYPE_DROP
},
440 static str_val_t property_table
[] = {
441 {"auth_algs", SPD_ATTR_AH_AUTH
},
442 {"encr_algs", SPD_ATTR_ESP_ENCR
},
443 {"encr_auth_algs", SPD_ATTR_ESP_AUTH
},
449 static str_val_t icmp_type_table
[] = {
450 {"unreach", ICMP_UNREACH
},
452 {"echorep", ICMP_ECHOREPLY
},
453 {"squench", ICMP_SOURCEQUENCH
},
454 {"redir", ICMP_REDIRECT
},
455 {"timex", ICMP_TIMXCEED
},
456 {"paramprob", ICMP_PARAMPROB
},
457 {"timest", ICMP_TSTAMP
},
458 {"timestrep", ICMP_TSTAMPREPLY
},
459 {"inforeq", ICMP_IREQ
},
460 {"inforep", ICMP_IREQREPLY
},
461 {"maskreq", ICMP_MASKREQ
},
462 {"maskrep", ICMP_MASKREPLY
},
463 {"unreach6", ICMP6_DST_UNREACH
},
464 {"pkttoobig6", ICMP6_PACKET_TOO_BIG
},
465 {"timex6", ICMP6_TIME_EXCEEDED
},
466 {"paramprob6", ICMP6_PARAM_PROB
},
467 {"echo6", ICMP6_ECHO_REQUEST
},
468 {"echorep6", ICMP6_ECHO_REPLY
},
469 {"router-sol6", ND_ROUTER_SOLICIT
},
470 {"router-ad6", ND_ROUTER_ADVERT
},
471 {"neigh-sol6", ND_NEIGHBOR_SOLICIT
},
472 {"neigh-ad6", ND_NEIGHBOR_ADVERT
},
473 {"redir6", ND_REDIRECT
},
477 static str_val_t icmp_code_table
[] = {
478 {"net-unr", ICMP_UNREACH_NET
},
479 {"host-unr", ICMP_UNREACH_HOST
},
480 {"proto-unr", ICMP_UNREACH_PROTOCOL
},
481 {"port-unr", ICMP_UNREACH_PORT
},
482 {"needfrag", ICMP_UNREACH_NEEDFRAG
},
483 {"srcfail", ICMP_UNREACH_SRCFAIL
},
484 {"net-unk", ICMP_UNREACH_NET_UNKNOWN
},
485 {"host-unk", ICMP_UNREACH_HOST_UNKNOWN
},
486 {"isolate", ICMP_UNREACH_ISOLATED
},
487 {"net-prohib", ICMP_UNREACH_NET_PROHIB
},
488 {"host-prohib", ICMP_UNREACH_HOST_PROHIB
},
489 {"net-tos", ICMP_UNREACH_TOSNET
},
490 {"host-tos", ICMP_UNREACH_TOSHOST
},
491 {"filter-prohib", ICMP_UNREACH_FILTER_PROHIB
},
492 {"host-preced", ICMP_UNREACH_HOST_PRECEDENCE
},
493 {"cutoff-preced", ICMP_UNREACH_PRECEDENCE_CUTOFF
},
494 {"no-route6", ICMP6_DST_UNREACH_NOROUTE
},
495 {"adm-prohib6", ICMP6_DST_UNREACH_ADMIN
},
496 {"addr-unr6", ICMP6_DST_UNREACH_ADDR
},
497 {"port-unr6", ICMP6_DST_UNREACH_NOPORT
},
498 {"hop-limex6", ICMP6_TIME_EXCEED_TRANSIT
},
499 {"frag-re-timex6", ICMP6_TIME_EXCEED_REASSEMBLY
},
500 {"err-head6", ICMP6_PARAMPROB_HEADER
},
501 {"unrec-head6", ICMP6_PARAMPROB_NEXTHEADER
},
502 {"unreq-opt6", ICMP6_PARAMPROB_OPTION
},
506 static sigset_t set
, oset
;
512 d_list_t
*temp
= malloc(sizeof (d_list_t
));
522 if (d_tail
== NULL
) {
523 d_list
= d_tail
= temp
;
536 if (sigfillset(&set
) == -1) {
540 if (sigprocmask(SIG_SETMASK
, &set
, &oset
) == -1) {
548 restore_all_signals()
550 if (sigprocmask(SIG_SETMASK
, &oset
, NULL
) == -1) {
557 /* allocate an ips_act_props_t and link it in correctly */
558 static ips_act_props_t
*
559 alloc_iap(ips_conf_t
*parent
)
561 ips_act_props_t
*ret
;
562 ips_act_props_t
*next
= parent
->ips_acts
;
563 ips_act_props_t
*current
= NULL
;
565 ret
= (ips_act_props_t
*)calloc(sizeof (ips_act_props_t
), 1);
570 ret
->iap_head
= parent
;
572 while (next
!= NULL
) {
574 next
= next
->iap_next
;
578 current
->iap_next
= ret
;
580 parent
->ips_acts
= ret
;
582 parent
->ips_act_cnt
++;
588 * This function exit()s if it fails.
594 struct spd_ext_actions
*actp
;
595 struct spd_attribute
*attr
, *endattr
;
596 spd_ext_t
*exts
[SPD_EXT_MAX
+1];
597 uint64_t reply_buf
[256];
600 uint64_t *start
, *end
;
601 alginfo_t alg
= {0, 0, 0, 0, 0};
603 static boolean_t has_run
= B_FALSE
;
610 sfd
= get_pf_pol_socket();
612 err(-1, gettext("unable to open policy socket"));
615 (void) memset(&msg
, 0, sizeof (msg
));
616 msg
.spd_msg_version
= PF_POLICY_V1
;
617 msg
.spd_msg_type
= SPD_ALGLIST
;
618 msg
.spd_msg_len
= SPD_8TO64(sizeof (msg
));
620 cnt
= write(sfd
, &msg
, sizeof (msg
));
621 if (cnt
!= sizeof (msg
)) {
623 err(-1, gettext("alglist failed: write"));
625 errx(-1, gettext("alglist failed: short write"));
629 cnt
= read(sfd
, reply_buf
, sizeof (reply_buf
));
631 retval
= spdsock_get_ext(exts
, (spd_msg_t
*)reply_buf
, SPD_8TO64(cnt
),
632 spdsock_diag_buf
, SPDSOCK_DIAG_BUF_LEN
);
634 if (retval
== KGE_LEN
&& exts
[0]->spd_ext_len
== 0) {
636 * No algorithms are defined in the kernel, which caused
637 * the extension length to be zero, and spdsock_get_ext()
638 * to fail with a KGE_LEN error. This is not an error
639 * condition, so we return nicely.
643 } else if (retval
!= 0) {
644 if (strlen(spdsock_diag_buf
) != 0)
645 warnx(spdsock_diag_buf
);
646 err(1, gettext("fetch_algorithms failed"));
649 if (!exts
[SPD_EXT_ACTION
]) {
650 errx(1, gettext("fetch_algorithms: action missing?!"));
653 actp
= (struct spd_ext_actions
*)exts
[SPD_EXT_ACTION
];
654 start
= (uint64_t *)actp
;
655 end
= (start
+ actp
->spd_actions_len
);
656 endattr
= (struct spd_attribute
*)end
;
657 attr
= (struct spd_attribute
*)&actp
[1];
661 while (attr
< endattr
) {
662 switch (attr
->spd_attr_tag
) {
670 known_algs
[algtype
][ipsec_nalgs
[algtype
]] = alg
;
671 ipsec_nalgs
[algtype
]++;
674 case SPD_ATTR_ENCR_MINBITS
:
675 case SPD_ATTR_AH_MINBITS
:
676 case SPD_ATTR_ESPA_MINBITS
:
677 alg
.minkeybits
= attr
->spd_attr_value
;
680 case SPD_ATTR_ENCR_MAXBITS
:
681 case SPD_ATTR_AH_MAXBITS
:
682 case SPD_ATTR_ESPA_MAXBITS
:
683 alg
.maxkeybits
= attr
->spd_attr_value
;
686 case SPD_ATTR_ENCR_DEFBITS
:
687 case SPD_ATTR_AH_DEFBITS
:
688 case SPD_ATTR_ESPA_DEFBITS
:
689 alg
.defkeybits
= attr
->spd_attr_value
;
692 case SPD_ATTR_ENCR_INCRBITS
:
693 case SPD_ATTR_AH_INCRBITS
:
694 case SPD_ATTR_ESPA_INCRBITS
:
695 alg
.incr
= attr
->spd_attr_value
;
698 case SPD_ATTR_AH_AUTH
:
699 case SPD_ATTR_ESP_AUTH
:
700 case SPD_ATTR_ESP_ENCR
:
701 alg
.id
= attr
->spd_attr_value
;
702 algtype
= attr
->spd_attr_tag
- SPD_ATTR_AH_AUTH
;
711 /* data dependant transform (act_cnt) */
712 #define ATTR(ap, tag, value) \
713 do { (ap)->spd_attr_tag = (tag); \
714 (ap)->spd_attr_value = (value); \
717 static struct spd_attribute
*
718 emit_alg(struct spd_attribute
*ap
, int type
, const algreq_t
*ar
,
719 int algattr
, int minbitattr
, int maxbitattr
)
725 /* LINTED E_CONST_COND */
726 ATTR(ap
, algattr
, ar
->alg_id
);
728 minbits
= ar
->alg_minbits
;
730 for (i
= 0; i
< ipsec_nalgs
[type
]; i
++) {
731 if (known_algs
[type
][i
].id
== id
)
734 if (i
< ipsec_nalgs
[type
])
735 minbits
= known_algs
[type
][i
].defkeybits
;
738 /* LINTED E_CONST_COND */
739 ATTR(ap
, minbitattr
, minbits
);
740 if (ar
->alg_maxbits
!= SPD_MAX_MAXBITS
)
741 /* LINTED E_CONST_COND */
742 ATTR(ap
, maxbitattr
, ar
->alg_maxbits
);
750 static struct spd_attribute
*
751 ips_act_props_to_action(struct spd_attribute
*ap
, uint32_t *rule_priorityp
,
752 const ips_act_props_t
*act_ptr
)
754 uint32_t rule_priority
= *rule_priorityp
;
756 /* LINTED E_CONST_COND */
757 ATTR(ap
, SPD_ATTR_EMPTY
, 0);
760 /* LINTED E_CONST_COND */
761 ATTR(ap
, SPD_ATTR_TYPE
, act_ptr
->iap_action
);
763 if (act_ptr
->iap_action
== SPD_ACTTYPE_PASS
)
764 rule_priority
|= BYPASS_POLICY_BOOST
;
767 if (act_ptr
->iap_attr
!= 0)
768 /* LINTED E_CONST_COND */
769 ATTR(ap
, SPD_ATTR_FLAGS
, act_ptr
->iap_attr
);
772 if (act_ptr
->iap_attr
& SPD_APPLY_ESP
) {
773 rule_priority
|= ESP_POLICY_BOOST
;
776 ap
= emit_alg(ap
, ESP_ENCR
, &act_ptr
->iap_eencr
,
778 SPD_ATTR_ENCR_MINBITS
, SPD_ATTR_ENCR_MAXBITS
);
781 ap
= emit_alg(ap
, ESP_AUTH
, &act_ptr
->iap_eauth
,
783 SPD_ATTR_ESPA_MINBITS
, SPD_ATTR_ESPA_MAXBITS
);
787 if (act_ptr
->iap_attr
& SPD_APPLY_AH
) {
788 rule_priority
|= AH_POLICY_BOOST
;
790 ap
= emit_alg(ap
, AH_AUTH
, &act_ptr
->iap_aauth
,
792 SPD_ATTR_AH_MINBITS
, SPD_ATTR_AH_MAXBITS
);
796 if (act_ptr
->iap_life_soft_time
!= 0)
797 /* LINTED E_CONST_COND */
798 ATTR(ap
, SPD_ATTR_LIFE_SOFT_TIME
, act_ptr
->iap_life_soft_time
);
799 if (act_ptr
->iap_life_hard_time
!= 0)
800 /* LINTED E_CONST_COND */
801 ATTR(ap
, SPD_ATTR_LIFE_HARD_TIME
, act_ptr
->iap_life_hard_time
);
802 if (act_ptr
->iap_life_soft_bytes
!= 0)
803 /* LINTED E_CONST_COND */
804 ATTR(ap
, SPD_ATTR_LIFE_SOFT_BYTES
,
805 act_ptr
->iap_life_soft_bytes
);
806 if (act_ptr
->iap_life_hard_bytes
!= 0)
807 /* LINTED E_CONST_COND */
808 ATTR(ap
, SPD_ATTR_LIFE_HARD_BYTES
,
809 act_ptr
->iap_life_hard_bytes
);
811 /* LINTED E_CONST_COND */
812 ATTR(ap
, SPD_ATTR_NEXT
, 0);
814 *rule_priorityp
= rule_priority
;
820 alg_rangecheck(uint_t type
, uint_t algid
, const algreq_t
*ar
)
823 uint_t minbits
= ar
->alg_minbits
;
824 uint_t maxbits
= ar
->alg_maxbits
;
826 for (i
= 0; i
< ipsec_nalgs
[type
]; i
++) {
827 if (known_algs
[type
][i
].id
== algid
)
831 if (i
>= ipsec_nalgs
[type
]) {
833 * The kernel (where we populate known_algs from) doesn't
834 * return the id's associated with NONE algorithms so we
835 * test here if this was the reason the algorithm wasn't
836 * found before wrongly failing.
838 if (((type
== ESP_ENCR
) && (algid
== SADB_EALG_NONE
)) ||
839 ((type
== ESP_AUTH
) && (algid
== SADB_AALG_NONE
)) ||
840 ((type
== AH_AUTH
) && (algid
== SADB_AALG_NONE
))) {
843 return (B_FALSE
); /* not found */
847 if ((minbits
== 0) && (maxbits
== 0))
850 minbits
= MAX(minbits
, known_algs
[type
][i
].minkeybits
);
851 maxbits
= MIN(maxbits
, known_algs
[type
][i
].maxkeybits
);
853 /* we could also check key increments here.. */
854 return (minbits
<= maxbits
); /* non-null intersection */
858 * Inspired by kernel/net/spd.c:ipsec_act_wildcard_expand()
861 static struct spd_attribute
*
862 ips_act_wild_props_to_action(struct spd_attribute
*ap
,
863 uint32_t *rule_priorityp
, uint16_t *act_cntp
,
864 const ips_act_props_t
*act_ptr
)
866 ips_act_props_t tact
= *act_ptr
;
867 boolean_t use_ah
, use_esp
, use_espa
, combined
;
868 boolean_t wild_auth
, wild_encr
, wild_eauth
;
869 uint_t auth_alg
, auth_idx
, auth_min
, auth_max
;
870 uint_t eauth_alg
, eauth_idx
, eauth_min
, eauth_max
;
871 uint_t encr_alg
, encr_idx
, encr_min
, encr_max
;
873 use_ah
= !!(act_ptr
->iap_attr
& SPD_APPLY_AH
);
874 use_esp
= !!(act_ptr
->iap_attr
& SPD_APPLY_ESP
);
875 use_espa
= !!(act_ptr
->iap_attr
& SPD_APPLY_ESPA
);
876 auth_alg
= act_ptr
->iap_aauth
.alg_id
;
877 eauth_alg
= act_ptr
->iap_eauth
.alg_id
;
878 encr_alg
= act_ptr
->iap_eencr
.alg_id
;
880 wild_auth
= use_ah
&& (auth_alg
== SADB_AALG_NONE
);
881 wild_eauth
= use_espa
&& (eauth_alg
== SADB_AALG_NONE
);
882 wild_encr
= use_esp
&& (encr_alg
== SADB_EALG_NONE
);
884 auth_min
= auth_max
= auth_alg
;
885 eauth_min
= eauth_max
= eauth_alg
;
886 encr_min
= encr_max
= encr_alg
;
889 * set up for explosion.. for each dimension, expand output
890 * size by the explosion factor.
894 auth_max
= ipsec_nalgs
[AH_AUTH
] - 1;
898 eauth_max
= ipsec_nalgs
[ESP_AUTH
] - 1;
902 encr_max
= ipsec_nalgs
[ESP_ENCR
] - 1;
905 #define WHICH_ALG(type, wild, idx) ((wild)?(known_algs[type][idx].id):(idx))
907 for (encr_idx
= encr_min
; encr_idx
<= encr_max
; encr_idx
++) {
908 encr_alg
= WHICH_ALG(ESP_ENCR
, wild_encr
, encr_idx
);
911 !alg_rangecheck(ESP_ENCR
, encr_alg
, &act_ptr
->iap_eencr
))
914 combined
= combined_mode(encr_alg
);
916 for (auth_idx
= auth_min
; auth_idx
<= auth_max
; auth_idx
++) {
917 auth_alg
= WHICH_ALG(AH_AUTH
, wild_auth
, auth_idx
);
920 !alg_rangecheck(AH_AUTH
, auth_alg
,
921 &act_ptr
->iap_aauth
))
925 for (eauth_idx
= eauth_min
; eauth_idx
<= eauth_max
;
927 eauth_alg
= WHICH_ALG(ESP_AUTH
, wild_eauth
,
930 if (!combined
&& use_espa
&&
931 !alg_rangecheck(ESP_AUTH
, eauth_alg
,
932 &act_ptr
->iap_eauth
))
935 tact
.iap_eencr
.alg_id
= encr_alg
;
936 tact
.iap_aauth
.alg_id
= auth_alg
;
939 * If the cipher is combined-mode don't do any
940 * ESP authentication.
942 tact
.iap_eauth
.alg_id
=
943 combined
? SADB_AALG_NONE
: eauth_alg
;
946 ap
= ips_act_props_to_action(ap
,
947 rule_priorityp
, &tact
);
949 /* Stop now if the cipher is combined-mode. */
951 break; /* Out of for loop. */
961 /* huge, but not safe since no length checking is done */
962 #define MAX_POL_MSG_LEN 16384
966 * hand in some ips_conf_t's, get back an
967 * iovec of pfpol messages.
968 * this function converts the internal ips_conf_t into
969 * a form that pf_pol can use.
970 * return 0 on success, 1 on failure
973 ips_conf_to_pfpol_msg(int ipsec_cmd
, ips_conf_t
*inConf
, int num_ips
,
978 uint64_t *scratch
= NULL
;
980 for (i
= 0; i
< num_ips
; i
++) {
982 uint16_t act_cnt
= 0;
983 uint64_t *next
= NULL
;
985 spd_address_t
*spd_address
;
986 struct spd_rule
*spd_rule
;
987 struct spd_proto
*spd_proto
;
988 struct spd_portrange
*spd_portrange
;
989 struct spd_ext_actions
*spd_ext_actions
;
990 struct spd_attribute
*ap
;
991 struct spd_typecode
*spd_typecode
;
993 ips_act_props_t
*act_ptr
;
994 uint32_t rule_priority
= 0;
996 scratch
= calloc(1, MAX_POL_MSG_LEN
);
997 msg
[i
].iov_base
= (char *)scratch
;
998 if (scratch
== NULL
) {
999 warn(gettext("memory"));
1002 conf
= &(inConf
[i
]);
1004 spd_msg
= (spd_msg_t
*)scratch
;
1005 next
= (uint64_t *)&(spd_msg
[1]);
1007 msg_len
= &(spd_msg
->spd_msg_len
);
1009 spd_msg
->spd_msg_version
= PF_POLICY_V1
;
1010 spd_msg
->spd_msg_pid
= getpid();
1011 spd_msg
->spd_msg_seq
= ++seq_cnt
;
1013 switch (ipsec_cmd
) {
1015 spd_msg
->spd_msg_type
= SPD_ADDRULE
;
1019 warnx("%s %d", gettext("bad command:"), ipsec_cmd
);
1020 spd_msg
->spd_msg_type
= SPD_ADDRULE
;
1028 spd_msg
->spd_msg_spdid
= SPD_STANDBY
;
1031 spd_rule
= (struct spd_rule
*)next
;
1033 spd_rule
->spd_rule_len
= SPD_8TO64(sizeof (struct spd_rule
));
1034 spd_rule
->spd_rule_type
= SPD_EXT_RULE
;
1035 spd_rule
->spd_rule_flags
= conf
->ips_dir
;
1036 if (conf
->ips_tunnel
)
1037 spd_rule
->spd_rule_flags
|= SPD_RULE_FLAG_TUNNEL
;
1039 next
= (uint64_t *)&(spd_rule
[1]);
1042 if (conf
->ips_ulp_prot
!= 0) {
1043 spd_proto
= (struct spd_proto
*)next
;
1044 spd_proto
->spd_proto_len
=
1045 SPD_8TO64(sizeof (struct spd_proto
));
1046 spd_proto
->spd_proto_exttype
= SPD_EXT_PROTO
;
1047 spd_proto
->spd_proto_number
= conf
->ips_ulp_prot
;
1048 next
= (uint64_t *)&(spd_proto
[1]);
1052 if (conf
->has_tunnel
!= 0) {
1053 spd_if
= (spd_if_t
*)next
;
1054 spd_if
->spd_if_len
=
1055 SPD_8TO64(P2ROUNDUP(strlen(tunif
) + 1, 8) +
1057 spd_if
->spd_if_exttype
= SPD_EXT_TUN_NAME
;
1058 (void) strlcpy((char *)spd_if
->spd_if_name
, tunif
,
1060 next
= (uint64_t *)(spd_if
) + spd_if
->spd_if_len
;
1063 /* icmp type/code */
1064 if (conf
->ips_ulp_prot
== IPPROTO_ICMP
||
1065 conf
->ips_ulp_prot
== IPPROTO_ICMPV6
) {
1066 if (conf
->has_type
) {
1067 spd_typecode
= (struct spd_typecode
*)next
;
1068 spd_typecode
->spd_typecode_len
=
1069 SPD_8TO64(sizeof (struct spd_typecode
));
1070 spd_typecode
->spd_typecode_exttype
=
1071 SPD_EXT_ICMP_TYPECODE
;
1072 spd_typecode
->spd_typecode_type
=
1073 conf
->ips_icmp_type
;
1074 spd_typecode
->spd_typecode_type_end
=
1075 conf
->ips_icmp_type_end
;
1076 if (conf
->has_code
) {
1077 spd_typecode
->spd_typecode_code
=
1078 conf
->ips_icmp_code
;
1079 spd_typecode
->spd_typecode_code_end
=
1080 conf
->ips_icmp_code_end
;
1082 spd_typecode
->spd_typecode_code
= 255;
1083 spd_typecode
->spd_typecode_code_end
1086 next
= (uint64_t *)&(spd_typecode
[1]);
1091 if (conf
->ips_src_port_min
!= 0 ||
1092 conf
->ips_src_port_max
!= 0) {
1093 spd_portrange
= (struct spd_portrange
*)next
;
1094 spd_portrange
->spd_ports_len
=
1095 SPD_8TO64(sizeof (struct spd_portrange
));
1096 spd_portrange
->spd_ports_exttype
=
1097 (conf
->swap
)?SPD_EXT_REMPORT
:SPD_EXT_LCLPORT
;
1098 spd_portrange
->spd_ports_minport
=
1099 conf
->ips_src_port_min
;
1100 spd_portrange
->spd_ports_maxport
=
1101 conf
->ips_src_port_max
;
1102 next
= (uint64_t *)&(spd_portrange
[1]);
1105 if (conf
->ips_dst_port_min
!= 0 ||
1106 conf
->ips_dst_port_max
!= 0) {
1107 spd_portrange
= (struct spd_portrange
*)next
;
1108 spd_portrange
->spd_ports_len
=
1109 SPD_8TO64(sizeof (struct spd_portrange
));
1110 spd_portrange
->spd_ports_exttype
=
1111 (conf
->swap
)?SPD_EXT_LCLPORT
:SPD_EXT_REMPORT
;
1112 spd_portrange
->spd_ports_minport
=
1113 conf
->ips_dst_port_min
;
1114 spd_portrange
->spd_ports_maxport
=
1115 conf
->ips_dst_port_max
;
1116 next
= (uint64_t *)&(spd_portrange
[1]);
1120 if (conf
->has_saddr
) {
1121 spd_address
= (spd_address_t
*)next
;
1122 next
= (uint64_t *)(spd_address
+ 1);
1124 spd_address
->spd_address_exttype
=
1125 (conf
->swap
)?SPD_EXT_REMADDR
:SPD_EXT_LCLADDR
;
1126 spd_address
->spd_address_prefixlen
=
1127 conf
->ips_src_mask_len
;
1129 if (conf
->ips_isv4
) {
1130 spd_address
->spd_address_af
= AF_INET
;
1131 (void) memcpy(next
, &(conf
->ips_src_addr
),
1133 spd_address
->spd_address_len
= 2;
1134 next
+= SPD_8TO64(sizeof (ipaddr_t
) + 4);
1135 if (!conf
->has_smask
)
1136 spd_address
->spd_address_prefixlen
= 32;
1138 spd_address
->spd_address_af
= AF_INET6
;
1139 (void) memcpy(next
, &(conf
->ips_src_addr_v6
),
1140 sizeof (in6_addr_t
));
1141 spd_address
->spd_address_len
= 3;
1142 next
+= SPD_8TO64(sizeof (in6_addr_t
));
1143 if (!conf
->has_smask
)
1144 spd_address
->spd_address_prefixlen
1150 if (conf
->has_daddr
) {
1151 spd_address
= (spd_address_t
*)next
;
1153 next
= (uint64_t *)(spd_address
+ 1);
1155 spd_address
->spd_address_exttype
=
1156 (conf
->swap
)?SPD_EXT_LCLADDR
:SPD_EXT_REMADDR
;
1157 spd_address
->spd_address_prefixlen
=
1158 conf
->ips_dst_mask_len
;
1160 if (conf
->ips_isv4
) {
1161 spd_address
->spd_address_af
= AF_INET
;
1162 (void) memcpy(next
, &conf
->ips_dst_addr
,
1164 spd_address
->spd_address_len
= 2;
1165 /* "+ 4" below is for padding. */
1166 next
+= SPD_8TO64(sizeof (ipaddr_t
) + 4);
1167 if (!conf
->has_dmask
)
1168 spd_address
->spd_address_prefixlen
= 32;
1170 spd_address
->spd_address_af
= AF_INET6
;
1171 (void) memcpy(next
, &(conf
->ips_dst_addr_v6
),
1172 sizeof (in6_addr_t
));
1173 spd_address
->spd_address_len
= 3;
1174 next
+= SPD_8TO64(sizeof (in6_addr_t
));
1175 if (!conf
->has_dmask
)
1176 spd_address
->spd_address_prefixlen
1182 spd_ext_actions
= (struct spd_ext_actions
*)next
;
1184 spd_ext_actions
->spd_actions_exttype
= SPD_EXT_ACTION
;
1186 act_ptr
= conf
->ips_acts
;
1187 ap
= (struct spd_attribute
*)(&spd_ext_actions
[1]);
1189 rule_priority
= priority
--;
1191 for (act_ptr
= conf
->ips_acts
; act_ptr
!= NULL
;
1192 act_ptr
= act_ptr
->iap_next
) {
1193 ap
= ips_act_wild_props_to_action(ap
, &rule_priority
,
1196 ap
[-1].spd_attr_tag
= SPD_ATTR_END
;
1198 next
= (uint64_t *)ap
;
1200 spd_rule
->spd_rule_priority
= rule_priority
;
1202 msg
[i
].iov_len
= (uintptr_t)next
- (uintptr_t)msg
[i
].iov_base
;
1203 *msg_len
= (uint16_t)SPD_8TO64(msg
[i
].iov_len
);
1204 spd_ext_actions
->spd_actions_count
= act_cnt
;
1205 spd_ext_actions
->spd_actions_len
=
1206 SPD_8TO64((uintptr_t)next
- (uintptr_t)spd_ext_actions
);
1208 printf("pfpol msg len in uint64_t's = %d\n", *msg_len
);
1209 printf("pfpol test_len in bytes = %d\n", msg
[i
].iov_len
);
1210 pfpol_msg_dump((spd_msg_t
*)scratch
,
1211 "ips_conf_to_pfpol_msg");
1220 get_pf_pol_socket(void)
1222 int s
= socket(PF_POLICY
, SOCK_RAW
, PF_POLICY_V1
);
1224 if (errno
== EPERM
) {
1225 EXIT_BADPERM("Insufficient privileges to open "
1226 "PF_POLICY socket.");
1228 warn(gettext("(loading pf_policy) socket:"));
1237 send_pf_pol_message(int ipsec_cmd
, ips_conf_t
*conf
, int *diag
)
1242 struct iovec polmsg
;
1243 spd_msg_t
*return_buf
;
1244 spd_ext_t
*exts
[SPD_EXT_MAX
+1];
1245 int fd
= get_pf_pol_socket();
1252 retval
= ips_conf_to_pfpol_msg(ipsec_cmd
, conf
, 1, &polmsg
);
1259 total_len
= polmsg
.iov_len
;
1261 cnt
= writev(fd
, &polmsg
, 1);
1264 (void) printf("cnt = %d\n", cnt
);
1267 warn(gettext("pf_pol write"));
1269 return_buf
= (spd_msg_t
*)calloc(total_len
, 1);
1271 if (return_buf
== NULL
) {
1272 warn(gettext("memory"));
1274 cnt
= read(fd
, (void*)return_buf
, total_len
);
1276 (void) printf("pf_pol read: cnt = %d(%d)\n", cnt
,
1280 if (cnt
> 8 && return_buf
->spd_msg_errno
) {
1281 *diag
= return_buf
->spd_msg_diagnostic
;
1282 if (!ipsecconf_qflag
) {
1284 gettext("Kernel returned"),
1286 return_buf
->spd_msg_errno
));
1289 (void) printf(gettext(
1290 "\t(spdsock diagnostic: %s)\n"),
1291 spdsock_diag(*diag
));
1293 pfpol_msg_dump((spd_msg_t
*)polmsg
.iov_base
,
1295 pfpol_msg_dump(return_buf
,
1296 "send_pf_pol_message");
1298 retval
= return_buf
->spd_msg_errno
;
1300 free(polmsg
.iov_base
);
1305 retval
= spdsock_get_ext(exts
, return_buf
,
1306 return_buf
->spd_msg_len
, NULL
, 0);
1309 if (exts
[SPD_EXT_RULE
]) {
1310 conf
->ips_policy_index
=
1311 ((struct spd_rule
*)
1312 exts
[SPD_EXT_RULE
])->spd_rule_index
;
1314 if (add_index(conf
->ips_policy_index
)) {
1316 free(polmsg
.iov_base
);
1326 free(polmsg
.iov_base
);
1334 main(int argc
, char *argv
[])
1339 boolean_t smf_managed
;
1340 boolean_t just_check
= B_FALSE
;
1341 boolean_t replace_policy
= B_FALSE
;
1345 char *smf_warning
= gettext(
1346 "\n\tIPsec policy should be managed using smf(5). Modifying\n"
1347 "\tthe IPsec policy from the command line while the 'policy'\n"
1348 "\tservice is enabled could result in an inconsistent\n"
1349 "\tsecurity policy.\n\n");
1354 (void) setlocale(LC_ALL
, "");
1355 #if !defined(TEXT_DOMAIN)
1356 #define TEXT_DOMAIN "SYS_TEST"
1358 (void) textdomain(TEXT_DOMAIN
);
1360 openlog("ipsecconf", LOG_CONS
, LOG_AUTH
);
1363 * We don't immediately check for privilege here. This is done by IP
1364 * when we open /dev/ip below.
1368 cmd
= IPSEC_CONF_VIEW
;
1371 my_fmri
= getenv("SMF_FMRI");
1372 if (my_fmri
== NULL
)
1373 smf_managed
= B_FALSE
;
1375 smf_managed
= B_TRUE
;
1377 while ((c
= getopt(argc
, argv
, "nlfLFa:qd:r:i:c:")) != EOF
) {
1380 if (interface_name
!= NULL
) {
1382 EXIT_FATAL("interface name not required.");
1384 /* Apply to all policy heads - global and tunnels. */
1385 interface_name
= &all_polheads
;
1389 * The policy flush command can be specified with -a
1390 * to perform an atomic policy replace. It can't be
1391 * specified with any other flags.
1393 if (cmd
== IPSEC_CONF_ADD
) {
1394 cmd
= IPSEC_CONF_REPLACE
;
1399 EXIT_FATAL("Multiple commands specified");
1401 cmd
= IPSEC_CONF_FLUSH
;
1404 if (interface_name
!= NULL
) {
1406 EXIT_FATAL("interface name not required.");
1408 /* Apply to all policy heads - global and tunnels. */
1409 interface_name
= &all_polheads
;
1412 /* Only one command at a time */
1415 EXIT_FATAL("Multiple commands specified");
1417 cmd
= IPSEC_CONF_LIST
;
1420 just_check
= B_TRUE
;
1424 if (cmd
== IPSEC_CONF_FLUSH
) {
1425 cmd
= IPSEC_CONF_REPLACE
;
1429 /* Only one command at a time, and no interface name */
1430 if (cmd
!= 0 || interface_name
!= NULL
) {
1432 EXIT_FATAL("Multiple commands or interface "
1435 cmd
= IPSEC_CONF_ADD
;
1440 * Only one command at a time. Interface name is
1445 EXIT_FATAL("Multiple commands specified");
1447 cmd
= IPSEC_CONF_DEL
;
1448 index
= parse_index(optarg
, NULL
);
1457 /* Only one command at a time, and no interface name */
1458 if (cmd
!= 0 || interface_name
!= NULL
) {
1460 EXIT_FATAL("Multiple commands or interface "
1463 cmd
= IPSEC_CONF_SUB
;
1467 if (interface_name
!= NULL
) {
1468 EXIT_FATAL("Interface name already selected");
1470 interface_name
= optarg
;
1471 /* Check for some cretin using the all-polheads name. */
1472 if (strlen(optarg
) == 0) {
1474 EXIT_FATAL("Invalid interface name.");
1479 EXIT_FATAL("Bad usage.");
1488 * ADD, FLUSH, DELETE needs to do two operations.
1490 * 1) Update/delete/empty the POLICY_CONF_FILE.
1491 * 2) Make an ioctl and tell IP to update its state.
1493 * We already lock()ed so that only one instance of this
1494 * program runs. We also need to make sure that the above
1495 * operations are atomic i.e we don't want to update the file
1496 * and get interrupted before we could tell IP. To make it
1497 * atomic we block all the signals and restore them.
1500 case IPSEC_CONF_LIST
:
1502 ret
= ipsec_conf_list();
1504 case IPSEC_CONF_FLUSH
:
1505 if ((ret
= block_all_signals()) == -1) {
1508 if (!smf_managed
&& !ipsecconf_qflag
)
1509 (void) fprintf(stdout
, "%s", smf_warning
);
1510 ret
= ipsec_conf_flush(SPD_ACTIVE
);
1511 (void) restore_all_signals();
1513 case IPSEC_CONF_VIEW
:
1514 if (interface_name
!= NULL
) {
1515 EXIT_FATAL("Cannot view for one interface only.");
1517 ret
= ipsec_conf_view();
1519 case IPSEC_CONF_DEL
:
1521 warnx(gettext("Invalid index"));
1525 if ((ret
= block_all_signals()) == -1) {
1528 if (!smf_managed
&& !ipsecconf_qflag
)
1529 (void) fprintf(stdout
, "%s", smf_warning
);
1530 ret
= ipsec_conf_del(index
, B_FALSE
);
1531 (void) restore_all_signals();
1532 flushret
= ipsec_conf_flush(SPD_STANDBY
);
1534 case IPSEC_CONF_REPLACE
:
1535 replace_policy
= B_TRUE
;
1537 case IPSEC_CONF_ADD
:
1539 * The IPsec kernel modules should only be loaded
1540 * if there is a policy to install, for this
1541 * reason ipsec_conf_add() calls fetch_algorithms()
1542 * and ipsec_conf_flush() only when appropriate.
1544 if ((ret
= block_all_signals()) == -1) {
1547 if (!smf_managed
&& !ipsecconf_qflag
)
1548 (void) fprintf(stdout
, "%s", smf_warning
);
1549 ret
= ipsec_conf_add(just_check
, smf_managed
, replace_policy
);
1550 (void) restore_all_signals();
1552 case IPSEC_CONF_SUB
:
1554 if ((ret
= block_all_signals()) == -1) {
1557 if (!smf_managed
&& !ipsecconf_qflag
)
1558 (void) fprintf(stdout
, "%s", smf_warning
);
1559 ret
= ipsec_conf_sub();
1560 (void) restore_all_signals();
1561 flushret
= ipsec_conf_flush(SPD_STANDBY
);
1564 /* If no argument is given but a "-" */
1566 EXIT_FATAL("Bad usage.");
1570 if (ret
!= 0 || flushret
!= 0)
1578 if (errno
== EACCES
)
1579 EXIT_BADPERM("Insufficient privilege to run ipsecconf.");
1581 warn(gettext("Cannot open lock file %s"), LOCK_FILE
);
1594 * Open the file with O_CREAT|O_EXCL. If it exists already, it
1595 * will fail. If it already exists, check whether it looks like
1596 * the one we created.
1599 if ((fd
= open(LOCK_FILE
, O_EXCL
|O_CREAT
|O_RDWR
, S_IRUSR
|S_IWUSR
))
1601 if (errno
!= EEXIST
) {
1602 /* Some other problem. Will exit. */
1607 * open() returned an EEXIST error. We don't fail yet
1608 * as it could be a residual from a previous
1610 * File exists. make sure it is OK. We need to lstat()
1611 * as fstat() stats the file pointed to by the symbolic
1614 if (lstat(LOCK_FILE
, &sbuf1
) == -1) {
1615 EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE
);
1618 * Check whether it is a regular file and not a symbolic
1619 * link. Its link count should be 1. The owner should be
1620 * root and the file should be empty.
1622 if (!S_ISREG(sbuf1
.st_mode
) ||
1623 sbuf1
.st_nlink
!= 1 ||
1624 sbuf1
.st_uid
!= 0 ||
1625 sbuf1
.st_size
!= 0) {
1626 EXIT_FATAL2("Bad lock file %s", LOCK_FILE
);
1628 if ((fd
= open(LOCK_FILE
, O_CREAT
|O_RDWR
,
1629 S_IRUSR
|S_IWUSR
)) == -1) {
1634 * Check whether we opened the file that we lstat()ed.
1636 if (fstat(fd
, &sbuf2
) == -1) {
1637 EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE
);
1639 if (sbuf1
.st_dev
!= sbuf2
.st_dev
||
1640 sbuf1
.st_ino
!= sbuf2
.st_ino
) {
1641 /* File changed after we did the lstat() above */
1642 EXIT_FATAL2("Bad lock file %s", LOCK_FILE
);
1645 if (lockf(fd
, F_LOCK
, 0) == -1) {
1646 EXIT_FATAL2("Cannot lockf %s", LOCK_FILE
);
1654 if (lockf(fd
, F_ULOCK
, 0) == -1) {
1663 print_pattern_string(int type
)
1667 for (j
= 0; pattern_table
[j
].string
!= NULL
; j
++) {
1668 if (type
== pattern_table
[j
].tok_val
) {
1669 (void) printf("%s ", pattern_table
[j
].string
);
1676 print_icmp_typecode(uint8_t type
, uint8_t type_end
, uint8_t code
,
1679 (void) printf("type %d", type
);
1680 if (type_end
!= type
)
1681 (void) printf("-%d ", type_end
);
1685 (void) printf("code %d", code
);
1686 if (code_end
!= code
)
1687 (void) printf("-%d ", code_end
);
1695 print_spd_flags(uint32_t flags
)
1697 flags
&= (SPD_RULE_FLAG_INBOUND
|SPD_RULE_FLAG_OUTBOUND
);
1699 if (flags
== SPD_RULE_FLAG_OUTBOUND
)
1700 (void) printf("dir out ");
1701 else if (flags
== SPD_RULE_FLAG_INBOUND
)
1702 (void) printf("dir in ");
1703 else if (flags
== (SPD_RULE_FLAG_INBOUND
|SPD_RULE_FLAG_OUTBOUND
))
1704 (void) printf("dir both ");
1708 print_bit_range(int min
, int max
)
1710 if (min
!= 0 || (max
!= 0 && max
!= SPD_MAX_MAXBITS
)) {
1713 (void) printf("%d", min
);
1714 if (min
!= 0 && max
!= 0 && min
!= max
) {
1715 (void) printf("..");
1716 if (max
!= 0 && max
!= SPD_MAX_MAXBITS
)
1717 (void) printf("%d", max
);
1724 print_alg(const char *tag
, algreq_t
*algreq
, int proto_num
)
1726 int min
= algreq
->alg_minbits
;
1727 int max
= algreq
->alg_maxbits
;
1728 struct ipsecalgent
*alg
;
1731 * This function won't be called with alg_id == 0, so we don't
1732 * have to worry about ANY vs. NONE here.
1735 (void) printf("%s ", tag
);
1737 alg
= getipsecalgbynum(algreq
->alg_id
, proto_num
, NULL
);
1739 (void) printf("%d", algreq
->alg_id
);
1741 (void) printf("%s", alg
->a_names
[0]);
1742 freeipsecalgent(alg
);
1745 print_bit_range(min
, max
);
1750 print_ulp(uint8_t proto
)
1752 struct protoent
*pe
;
1757 print_pattern_string(TOK_ulp
);
1759 if (!ipsecconf_nflag
) {
1760 pe
= getprotobynumber(proto
);
1763 (void) printf("%s ", pe
->p_name
);
1765 (void) printf("%d ", proto
);
1768 /* needs to do ranges */
1770 print_port(uint16_t in_port
, int type
)
1772 in_port_t port
= ntohs(in_port
);
1778 print_pattern_string(type
);
1780 if (!ipsecconf_nflag
)
1781 sp
= getservbyport(port
, NULL
);
1784 (void) printf("%s ", sp
->s_name
);
1786 (void) printf("%d ", port
);
1790 * Print the address, given as "raw" input via the void pointer.
1793 print_raw_address(void *input
, boolean_t isv4
)
1797 char domain
[MAXHOSTNAMELEN
+ 1];
1798 struct in_addr addr
;
1799 struct in6_addr addr6
;
1800 char abuf
[INET6_ADDRSTRLEN
];
1802 struct in6_addr in_addr
;
1809 (void) memcpy(&V4_PART_OF_V6(in_addr
), input
, 4);
1810 /* we don't print unspecified addresses */
1811 IN6_V4MAPPED_TO_INADDR(&in_addr
, &addr
);
1812 if (addr
.s_addr
== INADDR_ANY
)
1814 addr_ptr
= (uchar_t
*)&addr
.s_addr
;
1815 addr_len
= IPV4_ADDR_LEN
;
1817 (void) memcpy(&addr6
, input
, 16);
1819 /* we don't print unspecified addresses */
1820 if (IN6_IS_ADDR_UNSPECIFIED(&addr6
))
1822 addr_ptr
= (uchar_t
*)&addr6
.s6_addr
;
1823 addr_len
= sizeof (struct in6_addr
);
1827 if (!ipsecconf_nflag
) {
1828 if (sysinfo(SI_HOSTNAME
, domain
, MAXHOSTNAMELEN
) != -1 &&
1829 (cp
= strchr(domain
, '.')) != NULL
) {
1830 (void) strlcpy(domain
, cp
+ 1, sizeof (domain
));
1835 hp
= getipnodebyaddr(addr_ptr
, addr_len
, af
, &error_num
);
1837 if ((cp
= strchr(hp
->h_name
, '.')) != 0 &&
1838 strcasecmp(cp
+ 1, domain
) == 0)
1845 (void) printf("%s", cp
);
1847 (void) printf("%s", inet_ntop(af
, addr_ptr
, abuf
,
1853 * Get the next SPD_DUMP message from the PF_POLICY socket. A single
1854 * read may contain multiple messages. This function uses static buffers,
1855 * and is therefore non-reentrant, so if you lift it for an MT application,
1858 * Return NULL if there's an error.
1861 ipsec_read_dump(int pfd
)
1863 static uint64_t buf
[SADB_8TO64(CBUF_LEN
)];
1864 static uint64_t *offset
;
1865 static int len
; /* In uint64_t units. */
1868 /* Assume offset and len are initialized to NULL and 0. */
1870 if ((offset
- len
== buf
) || (offset
== NULL
)) {
1871 /* read a new block from the socket. */
1872 len
= read(pfd
, &buf
, sizeof (buf
));
1874 warn(gettext("rule dump: bad read"));
1878 len
= SADB_8TO64(len
);
1879 } /* Else I still have more messages from a previous read. */
1881 retval
= (spd_msg_t
*)offset
;
1882 offset
+= retval
->spd_msg_len
;
1883 if (offset
> buf
+ len
) {
1884 warnx(gettext("dump read: message corruption,"
1885 " %d len exceeds %d boundary."),
1886 SADB_64TO8((uintptr_t)(offset
- buf
)),
1887 SADB_64TO8((uintptr_t)(len
)));
1895 * returns 0 on success
1897 * >0 on invalid returned message
1901 ipsec_conf_list(void)
1905 struct spd_msg
*msg
;
1908 spd_ext_t
*exts
[SPD_EXT_MAX
+1];
1910 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation
1914 SPD_8TO64(sizeof (*msg
) + sizeof (spd_if_t
) + LIFNAMSIZ
) + 1];
1916 pfd
= get_pf_pol_socket();
1919 warnx(gettext("Error getting list of policies from kernel"));
1923 (void) memset(buffer
, 0, sizeof (buffer
));
1924 msg
= (struct spd_msg
*)buffer
;
1925 msg
->spd_msg_version
= PF_POLICY_V1
;
1926 msg
->spd_msg_type
= SPD_DUMP
;
1927 msg
->spd_msg_len
= SPD_8TO64(sizeof (*msg
));
1929 msg
->spd_msg_len
+= attach_tunname((spd_if_t
*)(msg
+ 1));
1931 cnt
= write(pfd
, msg
, SPD_64TO8(msg
->spd_msg_len
));
1934 warn(gettext("dump: invalid write() return"));
1939 rmsg
= ipsec_read_dump(pfd
);
1941 if (rmsg
== NULL
|| rmsg
->spd_msg_errno
!= 0) {
1942 warnx("%s: %s", gettext("ruleset dump failed"),
1944 gettext("read error") :
1945 sys_error_message(rmsg
->spd_msg_errno
)));
1953 rmsg
= ipsec_read_dump(pfd
);
1960 if (rmsg
->spd_msg_errno
!= 0) {
1961 warnx("%s: %s", gettext("dump read: bad message"),
1962 sys_error_message(rmsg
->spd_msg_errno
));
1967 ret
= spdsock_get_ext(exts
, rmsg
, rmsg
->spd_msg_len
,
1968 spdsock_diag_buf
, SPDSOCK_DIAG_BUF_LEN
);
1970 if (strlen(spdsock_diag_buf
) != 0)
1971 warnx(spdsock_diag_buf
);
1972 warnx("%s: %s", gettext("dump read: bad message"),
1973 sys_error_message(rmsg
->spd_msg_errno
));
1981 if (exts
[SPD_EXT_RULESET
] != NULL
)
1982 break; /* and return 0. */
1984 print_pfpol_msg(rmsg
);
1992 print_iap(ips_act_props_t
*iap
)
1996 switch (iap
->iap_action
) {
1997 case SPD_ACTTYPE_PASS
:
1998 (void) printf("pass ");
2000 case SPD_ACTTYPE_DROP
:
2001 (void) printf("drop ");
2003 case SPD_ACTTYPE_IPSEC
:
2004 (void) printf("ipsec ");
2009 (void) printf("%c ", CURL_BEGIN
);
2010 if (iap
->iap_action
== SPD_ACTTYPE_IPSEC
) {
2011 if (iap
->iap_attr
& SPD_APPLY_AH
&&
2012 iap
->iap_aauth
.alg_id
!= 0)
2013 print_alg("auth_algs", &iap
->iap_aauth
,
2016 if (iap
->iap_attr
& SPD_APPLY_ESP
) {
2017 print_alg("encr_algs", &iap
->iap_eencr
,
2019 if (iap
->iap_eauth
.alg_id
!= 0)
2020 print_alg("encr_auth_algs", &iap
->iap_eauth
,
2023 if (iap
->iap_attr
& SPD_APPLY_UNIQUE
)
2024 (void) printf("sa unique ");
2026 (void) printf("sa shared ");
2028 (void) printf("%c ", CURL_END
);
2033 print_pfpol_msg(spd_msg_t
*msg
)
2035 spd_ext_t
*exts
[SPD_EXT_MAX
+1];
2036 spd_address_t
*spd_address
;
2037 struct spd_rule
*spd_rule
;
2038 struct spd_proto
*spd_proto
;
2039 struct spd_portrange
*spd_portrange
;
2040 struct spd_ext_actions
*spd_ext_actions
;
2041 struct spd_typecode
*spd_typecode
;
2042 struct spd_attribute
*app
;
2047 rv
= spdsock_get_ext(exts
, msg
, msg
->spd_msg_len
, spdsock_diag_buf
,
2048 SPDSOCK_DIAG_BUF_LEN
);
2050 if (rv
== KGE_OK
&& exts
[SPD_EXT_RULE
] != NULL
) {
2051 spd_if
= (spd_if_t
*)exts
[SPD_EXT_TUN_NAME
];
2052 spd_rule
= (struct spd_rule
*)exts
[SPD_EXT_RULE
];
2053 if (spd_if
== NULL
) {
2054 (void) printf("%s %lld\n", INDEX_TAG
,
2055 spd_rule
->spd_rule_index
);
2057 (void) printf("%s %s,%lld\n", INDEX_TAG
,
2058 (char *)spd_if
->spd_if_name
,
2059 spd_rule
->spd_rule_index
);
2062 if (strlen(spdsock_diag_buf
) != 0)
2063 warnx(spdsock_diag_buf
);
2064 warnx(gettext("print_pfpol_msg: malformed PF_POLICY message."));
2068 (void) printf("%c ", CURL_BEGIN
);
2070 if (spd_if
!= NULL
) {
2071 (void) printf("tunnel %s negotiate %s ",
2072 (char *)spd_if
->spd_if_name
,
2073 (spd_rule
->spd_rule_flags
& SPD_RULE_FLAG_TUNNEL
) ?
2074 "tunnel" : "transport");
2077 if (exts
[SPD_EXT_PROTO
] != NULL
) {
2078 spd_proto
= (struct spd_proto
*)exts
[SPD_EXT_PROTO
];
2079 print_ulp(spd_proto
->spd_proto_number
);
2082 if (exts
[SPD_EXT_LCLADDR
] != NULL
) {
2083 spd_address
= (spd_address_t
*)exts
[SPD_EXT_LCLADDR
];
2085 (void) printf("laddr ");
2086 print_raw_address((spd_address
+ 1),
2087 (spd_address
->spd_address_len
== 2));
2088 (void) printf("/%d ", spd_address
->spd_address_prefixlen
);
2091 if (exts
[SPD_EXT_LCLPORT
] != NULL
) {
2092 spd_portrange
= (struct spd_portrange
*)exts
[SPD_EXT_LCLPORT
];
2093 if (spd_portrange
->spd_ports_minport
!= 0) {
2094 print_port(spd_portrange
->spd_ports_minport
,
2100 if (exts
[SPD_EXT_REMADDR
] != NULL
) {
2101 spd_address
= (spd_address_t
*)exts
[SPD_EXT_REMADDR
];
2103 (void) printf("raddr ");
2104 print_raw_address((spd_address
+ 1),
2105 (spd_address
->spd_address_len
== 2));
2106 (void) printf("/%d ", spd_address
->spd_address_prefixlen
);
2109 if (exts
[SPD_EXT_REMPORT
] != NULL
) {
2111 (struct spd_portrange
*)exts
[SPD_EXT_REMPORT
];
2112 if (spd_portrange
->spd_ports_minport
!= 0) {
2114 spd_portrange
->spd_ports_minport
, TOK_rport
);
2118 if (exts
[SPD_EXT_ICMP_TYPECODE
] != NULL
) {
2120 (struct spd_typecode
*)exts
[SPD_EXT_ICMP_TYPECODE
];
2121 print_icmp_typecode(spd_typecode
->spd_typecode_type
,
2122 spd_typecode
->spd_typecode_type_end
,
2123 spd_typecode
->spd_typecode_code
,
2124 spd_typecode
->spd_typecode_code_end
);
2127 if (exts
[SPD_EXT_RULE
] != NULL
) {
2128 spd_rule
= (struct spd_rule
*)exts
[SPD_EXT_RULE
];
2129 print_spd_flags(spd_rule
->spd_rule_flags
);
2133 (void) printf("%c ", CURL_END
);
2135 if (exts
[SPD_EXT_ACTION
] != NULL
) {
2136 ips_act_props_t iap
;
2139 (void) memset(&iap
, 0, sizeof (iap
));
2141 (struct spd_ext_actions
*)exts
[SPD_EXT_ACTION
];
2142 app
= (struct spd_attribute
*)(spd_ext_actions
+ 1);
2145 act_count
< spd_ext_actions
->spd_actions_len
-1;
2148 switch (app
->spd_attr_tag
) {
2156 (void) printf("or ");
2163 case SPD_ATTR_EMPTY
:
2165 (void) memset(&iap
, 0, sizeof (iap
));
2171 (void) printf("or ");
2180 iap
.iap_action
= app
->spd_attr_value
;
2183 case SPD_ATTR_FLAGS
:
2184 iap
.iap_attr
= app
->spd_attr_value
;
2187 case SPD_ATTR_AH_AUTH
:
2188 iap
.iap_aauth
.alg_id
= app
->spd_attr_value
;
2191 case SPD_ATTR_ESP_ENCR
:
2192 iap
.iap_eencr
.alg_id
= app
->spd_attr_value
;
2195 case SPD_ATTR_ESP_AUTH
:
2196 iap
.iap_eauth
.alg_id
= app
->spd_attr_value
;
2199 case SPD_ATTR_ENCR_MINBITS
:
2200 iap
.iap_eencr
.alg_minbits
= app
->spd_attr_value
;
2203 case SPD_ATTR_ENCR_MAXBITS
:
2204 iap
.iap_eencr
.alg_maxbits
= app
->spd_attr_value
;
2207 case SPD_ATTR_AH_MINBITS
:
2208 iap
.iap_aauth
.alg_minbits
= app
->spd_attr_value
;
2211 case SPD_ATTR_AH_MAXBITS
:
2212 iap
.iap_aauth
.alg_maxbits
= app
->spd_attr_value
;
2215 case SPD_ATTR_ESPA_MINBITS
:
2216 iap
.iap_eauth
.alg_minbits
= app
->spd_attr_value
;
2219 case SPD_ATTR_ESPA_MAXBITS
:
2220 iap
.iap_eauth
.alg_maxbits
= app
->spd_attr_value
;
2223 case SPD_ATTR_LIFE_SOFT_TIME
:
2224 case SPD_ATTR_LIFE_HARD_TIME
:
2225 case SPD_ATTR_LIFE_SOFT_BYTES
:
2226 case SPD_ATTR_LIFE_HARD_BYTES
:
2228 (void) printf("\tattr %d: %X-%d\n",
2231 app
->spd_attr_value
);
2238 (void) printf("\n");
2243 pfpol_msg_dump(spd_msg_t
*msg
, char *tag
)
2245 spd_ext_t
*exts
[SPD_EXT_MAX
+1];
2247 spd_address_t
*spd_address
;
2248 struct spd_rule
*spd_rule
;
2249 struct spd_proto
*spd_proto
;
2250 struct spd_portrange
*spd_portrange
;
2251 struct spd_typecode
*spd_typecode
;
2252 struct spd_ext_actions
*spd_ext_actions
;
2253 struct spd_attribute
*app
;
2255 char abuf
[INET6_ADDRSTRLEN
];
2259 rv
= spdsock_get_ext(exts
, msg
, msg
->spd_msg_len
, NULL
, 0);
2263 (void) printf("===========%s==============\n", tag
);
2264 (void) printf("pfpol_msg_dump %d\n-------------------\n", rv
);
2266 (void) printf("spd_msg_version:%d\n", msg
->spd_msg_version
);
2267 (void) printf("spd_msg_type:%d\n", msg
->spd_msg_type
);
2268 (void) printf("spd_msg_errno:%d\n", msg
->spd_msg_errno
);
2269 (void) printf("spd_msg_spdid:%d\n", msg
->spd_msg_spdid
);
2270 (void) printf("spd_msg_len:%d\n", msg
->spd_msg_len
);
2271 (void) printf("spd_msg_diagnostic:%d\n", msg
->spd_msg_diagnostic
);
2272 (void) printf("spd_msg_seq:%d\n", msg
->spd_msg_seq
);
2273 (void) printf("spd_msg_pid:%d\n", msg
->spd_msg_pid
);
2275 for (i
= 1; i
<= SPD_EXT_MAX
; i
++) {
2276 if (exts
[i
] == NULL
) {
2277 printf("skipped %d\n", i
);
2282 case SPD_EXT_TUN_NAME
:
2283 spd_if
= (spd_if_t
*)exts
[i
];
2284 (void) printf("spd_if = %s\n", spd_if
->spd_if_name
);
2287 case SPD_EXT_ICMP_TYPECODE
:
2288 spd_typecode
= (struct spd_typecode
*)exts
[i
];
2289 (void) printf("icmp type %d-%d code %d-%d\n",
2290 spd_typecode
->spd_typecode_type
,
2291 spd_typecode
->spd_typecode_type_end
,
2292 spd_typecode
->spd_typecode_code
,
2293 spd_typecode
->spd_typecode_code_end
);
2296 case SPD_EXT_LCLPORT
:
2297 spd_portrange
= (struct spd_portrange
*)exts
[i
];
2298 (void) printf("local ports %d-%d\n",
2299 spd_portrange
->spd_ports_minport
,
2300 spd_portrange
->spd_ports_maxport
);
2304 case SPD_EXT_REMPORT
:
2305 spd_portrange
= (struct spd_portrange
*)exts
[i
];
2306 (void) printf("remote ports %d-%d\n",
2307 spd_portrange
->spd_ports_minport
,
2308 spd_portrange
->spd_ports_maxport
);
2313 spd_proto
= (struct spd_proto
*)exts
[i
];
2314 (void) printf("proto:spd_proto_exttype %d\n",
2315 spd_proto
->spd_proto_exttype
);
2316 (void) printf("proto:spd_proto_number %d\n",
2317 spd_proto
->spd_proto_number
);
2320 case SPD_EXT_LCLADDR
:
2321 case SPD_EXT_REMADDR
:
2322 spd_address
= (spd_address_t
*)exts
[i
];
2323 if (i
== SPD_EXT_LCLADDR
)
2324 (void) printf("local addr ");
2326 (void) printf("remote addr ");
2329 (void) printf("%s\n",
2330 inet_ntop(spd_address
->spd_address_af
,
2331 (void *) (spd_address
+1), abuf
,
2334 (void) printf("prefixlen: %d\n",
2335 spd_address
->spd_address_prefixlen
);
2338 case SPD_EXT_ACTION
:
2339 spd_ext_actions
= (struct spd_ext_actions
*)exts
[i
];
2340 (void) printf("spd_ext_action\n");
2341 (void) printf("spd_actions_count %d\n",
2342 spd_ext_actions
->spd_actions_count
);
2343 app
= (struct spd_attribute
*)(spd_ext_actions
+ 1);
2346 act_count
< spd_ext_actions
->spd_actions_len
-1;
2348 (void) printf("\tattr %d: %X-%d\n", act_count
,
2349 app
->spd_attr_tag
, app
->spd_attr_value
);
2356 spd_rule
= (struct spd_rule
*)exts
[i
];
2357 (void) printf("spd_rule_priority: 0x%x\n",
2358 spd_rule
->spd_rule_priority
);
2359 (void) printf("spd_rule_flags: %d\n",
2360 spd_rule
->spd_rule_flags
);
2363 case SPD_EXT_RULESET
:
2364 (void) printf("spd_ext_ruleset\n");
2367 (void) printf("default\n");
2372 (void) printf("-------------------\n");
2373 (void) printf("=========================\n");
2375 #endif /* DEBUG_HEAVY */
2383 fp
= fopen(POLICY_CONF_FILE
, "r");
2385 if (errno
== ENOENT
) {
2387 * The absence of POLICY_CONF_FILE should
2388 * not cause the command to exit with a
2389 * non-zero status, since this condition
2390 * is valid when no policies were previously
2395 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE
);
2398 while (fgets(buf
, MAXLEN
, fp
) != NULL
) {
2399 /* Don't print removed entries */
2402 if (strlen(buf
) != 0)
2403 buf
[strlen(buf
) - 1] = '\0';
2410 * Delete nlines from start in the POLICY_CONF_FILE.
2413 delete_from_file(int start
, int nlines
)
2419 if ((fp
= fopen(POLICY_CONF_FILE
, "r+b")) == NULL
) {
2420 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE
);
2425 * Insert a ";", read the line and discard it. Repeat
2426 * this logic nlines - 1 times. For the last line there
2427 * is just a newline character. We can't just insert a
2428 * single ";" character instead of the newline character
2429 * as it would affect the next line. Thus when we comment
2430 * the last line we seek one less and insert a ";"
2431 * character, which will replace the newline of the
2432 * penultimate line with ; and newline of the last line
2433 * will become part of the previous line.
2437 * It is not enough to seek just once and expect the
2438 * subsequent fgets below to take you to the right
2439 * offset of the next line. fgets below seems to affect
2440 * the offset. Thus we need to seek, replace with ";",
2441 * and discard a line using fgets for every line.
2443 if (fseek(fp
, start
, SEEK_SET
) == -1) {
2447 if (fputc(';', fp
) < 0) {
2452 * Flush the above ";" character before we do the fgets().
2453 * Without this, fgets() gets confused with offsets.
2457 while (fgets(ibuf
, MAXLEN
, fp
) != NULL
) {
2458 len
+= strlen(ibuf
);
2459 if (ibuf
[len
- 1] == '\n') {
2461 * We have read a complete line.
2467 * We read the line after ";" character has been inserted.
2468 * Thus len does not count ";". To advance to the next line
2473 * If nlines == 2, we will be commenting out the last
2474 * line next, which has only one newline character.
2475 * If we blindly replace it with ";", it will be
2476 * read as part of the next line which could have
2477 * a INDEX string and thus confusing ipsec_conf_view.
2478 * Thus, we seek one less and replace the previous
2479 * line's newline character with ";", and the
2480 * last line's newline character will become part of
2481 * the previous line.
2485 } while (--nlines
!= 0);
2494 * Delete an entry from the file by inserting a ";" at the
2495 * beginning of the lines to be removed.
2498 ipsec_conf_del(int policy_index
, boolean_t ignore_spd
)
2500 act_prop_t
*act_props
= malloc(sizeof (act_prop_t
));
2504 int ibuf_len
, index_len
, index
;
2506 int offset
, prev_offset
;
2508 char lifname
[LIFNAMSIZ
];
2510 if (act_props
== NULL
) {
2511 warn(gettext("memory"));
2515 fp
= fopen(POLICY_CONF_FILE
, "r");
2517 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE
);
2522 index_len
= strlen(INDEX_TAG
);
2524 for (offset
= prev_offset
= 0; fgets(ibuf
, MAXLEN
, fp
) != NULL
;
2525 offset
+= ibuf_len
) {
2526 prev_offset
= offset
;
2527 ibuf_len
= strlen(ibuf
);
2529 if (strncmp(ibuf
, INDEX_TAG
, index_len
) != 0) {
2534 * This line contains INDEX_TAG
2536 buf
= ibuf
+ index_len
;
2537 buf
++; /* Skip the space */
2538 index
= parse_index(buf
, lifname
);
2540 warnx(gettext("Invalid index in the file"));
2544 if (index
== policy_index
&&
2545 (interface_name
== NULL
||
2546 strncmp(interface_name
, lifname
, LIFNAMSIZ
) == 0)) {
2548 ret
= parse_one(fp
, act_props
);
2550 warnx(gettext("Invalid policy entry "
2557 * nlines is the number of lines we should comment
2558 * out. linecount tells us how many lines this command
2559 * spans. And we need to remove the line with INDEX
2560 * and an extra line we added during ipsec_conf_add.
2562 * NOTE : If somebody added a policy entry which does
2563 * not have a newline, ipsec_conf_add() fills in the
2564 * newline. Hence, there is always 2 extra lines
2567 nlines
= linecount
+ 2;
2573 ret
= pfp_delete_rule(policy_index
);
2576 warnx(gettext("Deletion incomplete. Please "
2577 "flush all the entries and re-configure :"));
2586 /* Delete nlines from prev_offset */
2588 ret
= delete_from_file(prev_offset
, nlines
);
2591 warnx(gettext("Deletion incomplete. Please "
2592 "flush all the entries and re-configure :"));
2599 ret
= pfp_delete_rule(policy_index
);
2602 warnx(gettext("Deletion incomplete. Please "
2603 "flush all the entries and re-configure :"));
2613 pfp_delete_rule(uint64_t index
)
2615 struct spd_msg
*msg
;
2616 struct spd_rule
*rule
;
2618 int cnt
, len
, alloclen
;
2620 sfd
= get_pf_pol_socket();
2622 warn(gettext("unable to open policy socket"));
2627 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation
2630 alloclen
= sizeof (spd_msg_t
) + sizeof (struct spd_rule
) +
2631 sizeof (spd_if_t
) + LIFNAMSIZ
+ 8;
2632 msg
= (spd_msg_t
*)malloc(alloclen
);
2639 rule
= (struct spd_rule
*)(msg
+ 1);
2641 (void) memset(msg
, 0, alloclen
);
2642 msg
->spd_msg_version
= PF_POLICY_V1
;
2643 msg
->spd_msg_type
= SPD_DELETERULE
;
2644 msg
->spd_msg_len
= SPD_8TO64(sizeof (spd_msg_t
)
2645 + sizeof (struct spd_rule
));
2647 rule
->spd_rule_type
= SPD_EXT_RULE
;
2648 rule
->spd_rule_len
= SPD_8TO64(sizeof (struct spd_rule
));
2649 rule
->spd_rule_index
= index
;
2651 msg
->spd_msg_len
+= attach_tunname((spd_if_t
*)(rule
+ 1));
2653 len
= SPD_64TO8(msg
->spd_msg_len
);
2654 cnt
= write(sfd
, msg
, len
);
2658 warn(gettext("Delete failed: write"));
2665 warnx(gettext("Delete failed: short write"));
2670 cnt
= read(sfd
, msg
, len
);
2673 warn(gettext("Delete failed: read"));
2680 warnx(gettext("Delete failed while reading reply"));
2685 if (msg
->spd_msg_errno
!= 0) {
2686 errno
= msg
->spd_msg_errno
;
2687 warn(gettext("Delete failed: SPD_FLUSH"));
2697 ipsec_conf_flush(int db
)
2701 struct spd_msg
*msg
;
2703 * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation
2707 SPD_8TO64(sizeof (*msg
) + sizeof (spd_if_t
) + LIFNAMSIZ
) + 1];
2709 sfd
= get_pf_pol_socket();
2711 warn(gettext("unable to open policy socket"));
2715 (void) memset(buffer
, 0, sizeof (buffer
));
2716 msg
= (struct spd_msg
*)buffer
;
2717 msg
->spd_msg_version
= PF_POLICY_V1
;
2718 msg
->spd_msg_type
= SPD_FLUSH
;
2719 msg
->spd_msg_len
= SPD_8TO64(sizeof (*msg
));
2720 msg
->spd_msg_spdid
= db
;
2722 msg
->spd_msg_len
+= attach_tunname((spd_if_t
*)(msg
+ 1));
2724 len
= SPD_64TO8(msg
->spd_msg_len
);
2725 cnt
= write(sfd
, msg
, len
);
2728 warn(gettext("Flush failed: write"));
2731 warnx(gettext("Flush failed: short write"));
2736 cnt
= read(sfd
, msg
, len
);
2739 warn(gettext("Flush failed: read"));
2742 warnx(gettext("Flush failed while reading reply"));
2747 if (msg
->spd_msg_errno
!= 0) {
2748 warnx("%s: %s", gettext("Flush failed: SPD_FLUSH"),
2749 sys_error_message(msg
->spd_msg_errno
));
2753 /* Truncate the file */
2754 if (db
== SPD_ACTIVE
) {
2755 if ((pfd
= open(POLICY_CONF_FILE
, O_TRUNC
|O_RDWR
)) == -1) {
2756 if (errno
== ENOENT
) {
2758 * The absence of POLICY_CONF_FILE should
2759 * not cause the command to exit with a
2760 * non-zero status, since this condition
2761 * is valid when no policies were previously
2766 warn(gettext("%s cannot be truncated"),
2776 * function to send SPD_FLIP and SPD_CLONE messages
2777 * Do it for ALL polheads for simplicity's sake.
2780 ipsec_conf_admin(uint8_t type
)
2784 struct spd_msg
*msg
;
2786 SPD_8TO64(sizeof (struct spd_msg
) + sizeof (spd_if_t
))];
2789 sfd
= get_pf_pol_socket();
2791 err(-1, gettext("unable to open policy socket"));
2794 (void) memset(buffer
, 0, sizeof (buffer
));
2795 msg
= (struct spd_msg
*)buffer
;
2796 msg
->spd_msg_version
= PF_POLICY_V1
;
2797 msg
->spd_msg_type
= type
;
2798 msg
->spd_msg_len
= SPD_8TO64(sizeof (buffer
));
2800 save_ifname
= interface_name
;
2801 /* Apply to all policy heads - global and tunnels. */
2802 interface_name
= &all_polheads
;
2803 (void) attach_tunname((spd_if_t
*)(msg
+ 1));
2804 interface_name
= save_ifname
;
2806 cnt
= write(sfd
, msg
, sizeof (buffer
));
2807 if (cnt
!= sizeof (buffer
)) {
2809 err(-1, gettext("admin failed: write"));
2811 errx(-1, gettext("admin failed: short write"));
2815 cnt
= read(sfd
, msg
, sizeof (buffer
));
2816 if (cnt
!= sizeof (buffer
)) {
2818 err(-1, gettext("admin failed: read"));
2820 errx(-1, gettext("admin failed while reading reply"));
2824 if (msg
->spd_msg_errno
!= 0) {
2825 errno
= msg
->spd_msg_errno
;
2826 err(-1, gettext("admin failed"));
2833 (void) fprintf(stderr
, gettext(
2834 "\tipsecconf -f \n "
2835 "\tipsecconf -a policy_file\n"));
2841 (void) fprintf(stderr
, gettext(
2842 "Usage: ipsecconf\n"
2843 "\tipsecconf -a ([-]|<filename>) [-q]\n"
2844 "\tipsecconf -c <filename>\n"
2845 "\tipsecconf -r ([-]|<filename>) [-q]\n"
2846 "\tipsecconf -d [-i tunnel-interface] <index>\n"
2847 "\tipsecconf -d <tunnel-interface,index>\n"
2848 "\tipsecconf -l [-n] [-i tunnel-interface]\n"
2849 "\tipsecconf -f [-i tunnel-interface]\n"
2850 "\tipsecconf -L [-n]\n"
2851 "\tipsecconf -F\n"));
2855 * a type consists of
2856 * "type" <int>{ "-" <int>}
2860 * a code consists of
2861 * "code" <int>{ "-" <int>}
2868 parse_type_code(const char *str
, const str_val_t
*table
)
2871 int res1
= 0, res2
= 0;
2874 if (isdigit(str
[0])) {
2875 res1
= strtol(str
, &end1
, 0);
2881 if (res1
> 255 || res1
< 0) {
2887 res2
= strtol(end1
, &end2
, 0);
2888 if (res2
> 255 || res2
< 0) {
2895 while (isspace(*end2
))
2898 if (*end2
!= '\0') {
2902 return (res1
+ (res2
<< 8));
2905 for (i
= 0; table
[i
].string
; i
++) {
2906 if (strcmp(str
, table
[i
].string
) == 0) {
2907 return (table
[i
].value
);
2915 parse_int(const char *str
)
2920 res
= strtol(str
, &end
, 0);
2923 while (isspace(*end
))
2931 * Parses <interface>,<index>. Sets iname or the global interface_name (if
2932 * iname == NULL) to <interface> and returns <index>. Calls exit() if we have
2933 * an interface_name already set.
2936 parse_index(const char *str
, char *iname
)
2938 char *intf
, *num
, *copy
;
2943 EXIT_FATAL("Out of memory.");
2946 intf
= strtok(copy
, ",");
2947 /* Just want the rest of the string unmolested, so use "" for arg2. */
2948 num
= strtok(NULL
, "");
2950 /* No comma found, just parse it like an int. */
2952 return (parse_int(str
));
2955 if (iname
!= NULL
) {
2956 (void) strlcpy(iname
, intf
, LIFNAMSIZ
);
2958 if (interface_name
!= NULL
) {
2959 EXIT_FATAL("Interface name already selected");
2962 interface_name
= strdup(intf
);
2963 if (interface_name
== NULL
) {
2964 EXIT_FATAL("Out of memory.");
2968 rc
= parse_int(num
);
2974 * Convert a mask to a prefix length.
2975 * Returns prefix length on success, -1 otherwise.
2978 in_getprefixlen(char *mask
)
2983 prefixlen
= (int)strtol(mask
, &end
, 10);
2984 if (prefixlen
< 0) {
2997 * Convert a prefix length to a mask.
2998 * Assumes the mask array is zero'ed by the caller.
3001 in_prefixlentomask(unsigned int prefixlen
, uchar_t
*mask
)
3003 while (prefixlen
> 0) {
3004 if (prefixlen
>= 8) {
3009 *mask
|= 1 << (8 - prefixlen
);
3016 parse_address(int type
, char *addr_str
)
3020 struct netent
*ne
= NULL
;
3021 struct hostent
*hp
= NULL
;
3023 struct in_addr netaddr
;
3024 struct in6_addr
*netaddr6
;
3025 struct hostent
*ne_hent
;
3026 boolean_t has_mask
= B_FALSE
;
3028 ptr
= strchr(addr_str
, '/');
3033 prefix_len
= in_getprefixlen(ptr
);
3034 if (prefix_len
< 0) {
3035 warnx(gettext("Unparseable prefix: '%s'."), ptr
);
3041 * getipnodebyname() is thread safe. This allows us to hold on to the
3042 * returned hostent structure, which is pointed to by the shp and
3043 * dhp globals for the source and destination addresses, respectively.
3045 hp
= getipnodebyname(addr_str
, AF_INET6
, AI_DEFAULT
| AI_ALL
, &h_errno
);
3048 * We come here for both a hostname and
3049 * any host address /network address.
3051 assert(hp
->h_addrtype
== AF_INET6
);
3052 } else if ((ne
= getnetbyname(addr_str
)) != NULL
) {
3053 switch (ne
->n_addrtype
) {
3056 * Allocate a struct hostent and initialize
3057 * it with the address corresponding to the
3058 * network number previously returned by
3059 * getnetbyname(). Freed by do_address_adds()
3060 * once the policy is defined.
3062 ne_hent
= malloc(sizeof (struct hostent
));
3063 if (ne_hent
== NULL
) {
3067 ne_hent
->h_addr_list
= malloc(2*sizeof (char *));
3068 if (ne_hent
->h_addr_list
== NULL
) {
3073 netaddr6
= malloc(sizeof (struct in6_addr
));
3074 if (netaddr6
== NULL
) {
3076 free(ne_hent
->h_addr_list
);
3080 ne_hent
->h_addr_list
[0] = (char *)netaddr6
;
3081 ne_hent
->h_addr_list
[1] = NULL
;
3082 netaddr
= inet_makeaddr(ne
->n_net
, INADDR_ANY
);
3083 IN6_INADDR_TO_V4MAPPED(&netaddr
, netaddr6
);
3087 warnx(gettext("Address type %d not supported."),
3092 warnx(gettext("Could not resolve address %s."), addr_str
);
3096 if (type
== IPSEC_CONF_SRC_ADDRESS
) {
3100 has_saprefix
= has_mask
;
3105 has_daprefix
= has_mask
;
3112 * Add port-only entries. Make sure to add them in both the V6 and V4 tables!
3115 do_port_adds(ips_conf_t
*cptr
)
3119 assert(IN6_IS_ADDR_UNSPECIFIED(&cptr
->ips_src_addr_v6
));
3120 assert(IN6_IS_ADDR_UNSPECIFIED(&cptr
->ips_dst_addr_v6
));
3123 (void) dump_conf(cptr
);
3126 ret
= send_pf_pol_message(SPD_ADDRULE
, cptr
, &diag
);
3127 if (ret
!= 0 && !ipsecconf_qflag
) {
3129 gettext("Could not add IPv4 policy for sport %d, dport %d "
3130 "- diagnostic %d - %s"), ntohs(cptr
->ips_src_port_min
),
3131 ntohs(cptr
->ips_dst_port_min
), diag
, spdsock_diag(diag
));
3138 * Nuke a list of policy entries.
3139 * rewrite this to use flipping
3140 * d_list isn't freed because we will be
3141 * exiting the program soon.
3146 d_list_t
*temp
= d_list
;
3149 policy_fp
= fopen(POLICY_CONF_FILE
, "a");
3150 if (policy_fp
== NULL
) {
3151 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE
);
3153 (void) fprintf(policy_fp
, "\n\n");
3154 (void) fflush(policy_fp
);
3157 while (temp
!= NULL
) {
3158 (void) ipsec_conf_del(temp
->index
, B_TRUE
);
3164 * Set mask info from the specified prefix len. Fail if multihomed.
3167 set_mask_info(struct hostent
*hp
, unsigned int plen
, struct in6_addr
*mask_v6
)
3169 struct in6_addr addr
;
3170 struct in_addr mask_v4
;
3172 if (hp
->h_addr_list
[1] != NULL
) {
3173 return (EOPNOTSUPP
);
3176 if (!IN6_IS_ADDR_UNSPECIFIED(mask_v6
)) {
3180 bcopy(hp
->h_addr_list
[0], &addr
, sizeof (struct in6_addr
));
3181 if (IN6_IS_ADDR_V4MAPPED(&addr
)) {
3182 if (plen
> IP_ABITS
) {
3185 (void) memset(&mask_v4
, 0, sizeof (mask_v4
));
3186 in_prefixlentomask(plen
, (uchar_t
*)&mask_v4
);
3187 IN6_INADDR_TO_V4MAPPED(&mask_v4
, mask_v6
);
3189 if (plen
> IPV6_ABITS
) {
3192 /* mask_v6 is already zero (unspecified), see test above */
3193 in_prefixlentomask(plen
, (uchar_t
*)mask_v6
);
3199 * Initialize the specified IPv6 address with all f's.
3202 init_addr_wildcard(struct in6_addr
*addr_v6
, boolean_t isv4
)
3205 uint32_t addr_v4
= 0xffffffff;
3206 IN6_INADDR_TO_V4MAPPED((struct in_addr
*)&addr_v4
, addr_v6
);
3208 (void) memset(addr_v6
, 0xff, sizeof (struct in6_addr
));
3213 * Called at the end to actually add policy. Handles single and multi-homed
3217 do_address_adds(ips_conf_t
*cptr
, int *diag
)
3220 int ret
= 0; /* For ioctl() call. */
3221 int rc
= 0; /* My own return code. */
3222 struct in6_addr zeroes
= { { { 0, 0, 0, 0, 0, 0, 0, 0,
3223 0, 0, 0, 0, 0, 0, 0, 0 } } };
3225 struct hostent hent
;
3230 * dst_hent may not be initialized if a destination
3231 * address was not given. It will be initalized with just
3232 * one address if a destination address was given. In both
3233 * the cases, we initialize here with ipsc_dst_addr and enter
3237 assert(shp
!= NULL
);
3238 hent
.h_addr_list
= ptr
;
3239 ptr
[0] = (char *)&zeroes
.s6_addr
;
3242 } else if (shp
== NULL
) {
3243 assert(dhp
!= NULL
);
3244 hent
.h_addr_list
= ptr
;
3245 ptr
[0] = (char *)&zeroes
.s6_addr
;
3251 * Set mask info here. Bail if multihomed and there's a prefix len.
3254 rc
= set_mask_info(shp
, splen
, &cptr
->ips_src_mask_v6
);
3257 cptr
->ips_src_mask_len
= splen
;
3261 rc
= set_mask_info(dhp
, dplen
, &cptr
->ips_dst_mask_v6
);
3264 cptr
->ips_dst_mask_len
= dplen
;
3267 for (i
= 0; shp
->h_addr_list
[i
] != NULL
; i
++) {
3268 bcopy(shp
->h_addr_list
[i
], &cptr
->ips_src_addr_v6
,
3269 sizeof (struct in6_addr
));
3270 isv4
= cptr
->ips_isv4
=
3271 IN6_IS_ADDR_V4MAPPED(&cptr
->ips_src_addr_v6
);
3272 if (IN6_IS_ADDR_UNSPECIFIED(&cptr
->ips_src_mask_v6
) &&
3274 init_addr_wildcard(&cptr
->ips_src_mask_v6
, isv4
);
3277 for (j
= 0; dhp
->h_addr_list
[j
] != NULL
; j
++) {
3278 bcopy(dhp
->h_addr_list
[j
], &cptr
->ips_dst_addr_v6
,
3279 sizeof (struct in6_addr
));
3280 if (IN6_IS_ADDR_UNSPECIFIED(&cptr
->ips_src_addr_v6
)) {
3282 * Src was not specified, so update isv4 flag
3283 * for this policy according to the family
3284 * of the destination address.
3286 isv4
= cptr
->ips_isv4
=
3287 IN6_IS_ADDR_V4MAPPED(
3288 &cptr
->ips_dst_addr_v6
);
3289 } else if ((dhp
!= &hent
) && (isv4
!=
3290 IN6_IS_ADDR_V4MAPPED(&cptr
->ips_dst_addr_v6
))) {
3291 /* v6/v4 mismatch. */
3294 if (IN6_IS_ADDR_UNSPECIFIED(&cptr
->ips_dst_mask_v6
) &&
3296 init_addr_wildcard(&cptr
->ips_dst_mask_v6
,
3300 ret
= send_pf_pol_message(SPD_ADDRULE
, cptr
, diag
);
3305 /* For now, allow duplicate/overlap policies. */
3306 if (ret
!= EEXIST
) {
3308 * We have an error where we added
3309 * some, but had errors with others.
3310 * Undo the previous adds, and
3318 bzero(&cptr
->ips_dst_mask_v6
,
3319 sizeof (struct in6_addr
));
3322 bzero(&cptr
->ips_src_mask_v6
, sizeof (struct in6_addr
));
3335 if ((add_count
== 0) && (rc
== 0)) {
3337 * No entries were added. We failed all adds
3338 * because the entries already existed, or because
3339 * no v4 or v6 src/dst pairs were found. Either way,
3340 * we must fail here with an appropriate error
3341 * to avoid a corresponding entry from being added
3342 * to ipsecpolicy.conf.
3344 if ((ret
== EEXIST
)) {
3345 /* All adds failed with EEXIST */
3348 /* No matching v4 or v6 src/dst pairs */
3357 parse_mask(int type
, char *mask_str
, ips_conf_t
*cptr
)
3359 struct in_addr mask
;
3360 struct in6_addr
*mask6
;
3362 if (type
== IPSEC_CONF_SRC_MASK
) {
3363 mask6
= &cptr
->ips_src_mask_v6
;
3365 mask6
= &cptr
->ips_dst_mask_v6
;
3368 if ((strncasecmp(mask_str
, "0x", 2) == 0) &&
3369 (strchr(mask_str
, '.') == NULL
)) {
3370 /* Is it in the form 0xff000000 ? */
3373 mask
.s_addr
= strtoul(mask_str
, &end
, 0);
3374 if (end
== mask_str
) {
3380 mask
.s_addr
= htonl(mask
.s_addr
);
3383 * Since inet_addr() returns -1 on error, we have
3384 * to convert a broadcast address ourselves.
3386 if (strcmp(mask_str
, "255.255.255.255") == 0) {
3387 mask
.s_addr
= 0xffffffff;
3389 mask
.s_addr
= inet_addr(mask_str
);
3390 if (mask
.s_addr
== (unsigned int)-1)
3395 /* Should we check for non-contiguous masks ? */
3396 if (mask
.s_addr
== 0)
3398 IN6_INADDR_TO_V4MAPPED(&mask
, mask6
);
3401 if (type
== IPSEC_CONF_SRC_MASK
) {
3402 cptr
->ips_src_mask_len
= in_masktoprefix(mask6
->s6_addr
,
3405 cptr
->ips_dst_mask_len
= in_masktoprefix(mask6
->s6_addr
,
3413 parse_port(int type
, char *port_str
, ips_conf_t
*conf
)
3415 struct servent
*sent
;
3419 sent
= getservbyname(port_str
, NULL
);
3421 ret
= parse_int(port_str
);
3422 if (ret
< 0 || ret
>= 65536) {
3425 port
= htons((in_port_t
)ret
);
3427 port
= sent
->s_port
;
3429 if (type
== IPSEC_CONF_SRC_PORT
) {
3430 conf
->ips_src_port_min
= conf
->ips_src_port_max
= port
;
3432 conf
->ips_dst_port_min
= conf
->ips_dst_port_max
= port
;
3438 combined_mode(uint_t alg_id
)
3440 struct ipsecalgent
*alg
;
3443 alg
= getipsecalgbynum(alg_id
, IPSEC_PROTO_ESP
, NULL
);
3445 rc
= (ALG_FLAG_COMBINED
& alg
->a_alg_flags
);
3446 freeipsecalgent(alg
);
3455 valid_algorithm(int proto_num
, const char *str
)
3459 struct ipsecalgent
*alg
;
3461 /* Short-circuit "none" */
3462 if (strncasecmp("none", str
, 5) == 0)
3465 alg
= getipsecalgbyname(str
, proto_num
, NULL
);
3467 ret
= alg
->a_alg_num
;
3468 freeipsecalgent(alg
);
3473 * Look whether it could be a valid number.
3474 * We support numbers also so that users can
3475 * load algorithms as they need it. We can't
3476 * check for validity of numbers here. It will
3477 * be checked when the SA is negotiated/looked up.
3478 * parse_int uses strtol(str), which converts 3DES
3479 * to a valid number i.e looks only at initial
3480 * number part. If we come here we should expect
3481 * only a decimal number.
3490 ret
= parse_int(str
);
3491 if (ret
> 0 && ret
<= 255)
3498 parse_ipsec_alg(char *str
, ips_act_props_t
*iap
, int alg_type
)
3502 char tstr
[VALID_ALG_LEN
];
3507 int l2
= SPD_MAX_MAXBITS
;
3514 * Make sure that we get a null terminated string.
3515 * For a bad input, we truncate at VALID_ALG_LEN.
3517 remainder
= strlen(str
);
3518 (void) strlcpy(tstr
, str
, VALID_ALG_LEN
);
3519 lens
= strtok(tstr
, "()");
3520 remainder
-= strlen(lens
);
3521 lens
= strtok(NULL
, "()");
3525 int len2
= SPD_MAX_MAXBITS
;
3526 int len_all
= strlen(lens
);
3527 int dot_start
= (lens
[0] == '.');
3530 * Check to see if the keylength arg is at the end of the
3531 * token, the "()" is 2 characters.
3533 remainder
-= strlen(lens
);
3537 l1_str
= strtok(lens
, ".");
3538 l2_str
= strtok(NULL
, ".");
3539 if (l1_str
!= NULL
) {
3540 l1
= parse_int(l1_str
);
3541 len1
= strlen(l1_str
);
3545 if (l2_str
!= NULL
) {
3546 l2
= parse_int(l2_str
);
3547 len2
= strlen(l2_str
);
3552 if (len_all
== len1
) {
3555 } else if (dot_start
) {
3559 } else if ((len_all
- 2) == len1
) {
3561 l2
= SPD_MAX_MAXBITS
;
3562 } /* else alg(n..m) */
3565 if (alg_type
== SPD_ATTR_AH_AUTH
||
3566 alg_type
== SPD_ATTR_ESP_AUTH
) {
3567 alg_value
= valid_algorithm(IPSEC_PROTO_AH
, tstr
);
3569 alg_value
= valid_algorithm(IPSEC_PROTO_ESP
, tstr
);
3571 if (alg_value
< 0) {
3572 /* Invalid algorithm or "none" */
3576 if (alg_type
== SPD_ATTR_AH_AUTH
) {
3578 iap
->iap_attr
|= SPD_APPLY_AH
;
3579 ap
= &(iap
->iap_aauth
);
3580 } else if (alg_type
== SPD_ATTR_ESP_AUTH
) {
3582 iap
->iap_attr
|= SPD_APPLY_ESP
|SPD_APPLY_ESPA
;
3583 ap
= &(iap
->iap_eauth
);
3586 iap
->iap_attr
|= SPD_APPLY_ESP
;
3587 ap
= &(iap
->iap_eencr
);
3590 ap
->alg_id
= alg_value
;
3591 ap
->alg_minbits
= l1
;
3592 ap
->alg_maxbits
= l2
;
3594 if (!alg_rangecheck(a_type
, alg_value
, ap
))
3601 sys_error_message(int syserr
)
3607 mesg
= gettext("Entry already exists");
3610 mesg
= gettext("Tunnel not found");
3613 mesg
= gettext("Invalid entry");
3616 mesg
= strerror(syserr
);
3622 error_message(error_type_t error
, int type
, int line
)
3627 case IPSEC_CONF_SRC_ADDRESS
:
3628 mesg
= gettext("Source Address");
3630 case IPSEC_CONF_DST_ADDRESS
:
3631 mesg
= gettext("Destination Address");
3633 case IPSEC_CONF_SRC_PORT
:
3634 mesg
= gettext("Source Port");
3636 case IPSEC_CONF_DST_PORT
:
3637 mesg
= gettext("Destination Port");
3639 case IPSEC_CONF_SRC_MASK
:
3640 mesg
= gettext("Source Mask");
3642 case IPSEC_CONF_DST_MASK
:
3643 mesg
= gettext("Destination Mask");
3645 case IPSEC_CONF_ULP
:
3646 mesg
= gettext("Upper Layer Protocol");
3648 case IPSEC_CONF_IPSEC_AALGS
:
3649 mesg
= gettext("Authentication Algorithm");
3651 case IPSEC_CONF_IPSEC_EALGS
:
3652 mesg
= gettext("Encryption Algorithm");
3654 case IPSEC_CONF_IPSEC_EAALGS
:
3655 mesg
= gettext("ESP Authentication Algorithm");
3657 case IPSEC_CONF_IPSEC_SA
:
3658 mesg
= gettext("SA");
3660 case IPSEC_CONF_IPSEC_DIR
:
3661 mesg
= gettext("Direction");
3663 case IPSEC_CONF_ICMP_TYPE
:
3664 mesg
= gettext("ICMP type");
3666 case IPSEC_CONF_ICMP_CODE
:
3667 mesg
= gettext("ICMP code");
3669 case IPSEC_CONF_NEGOTIATE
:
3670 mesg
= gettext("Negotiate");
3672 case IPSEC_CONF_TUNNEL
:
3673 mesg
= gettext("Tunnel");
3679 * If we never read a newline character, we don't want
3682 warnx(gettext("%s%s%s %s on line: %d"),
3683 (error
== BAD_ERROR
) ? gettext("Bad") : "",
3684 (error
== DUP_ERROR
) ? gettext("Duplicate") : "",
3685 (error
== REQ_ERROR
) ? gettext("Requires") : "",
3687 (arg_indices
[line
] == 0) ? 1 : arg_indices
[line
]);
3691 validate_properties(ips_act_props_t
*cptr
, boolean_t dir
, boolean_t is_alg
)
3693 if (cptr
->iap_action
== SPD_ACTTYPE_PASS
||
3694 cptr
->iap_action
== SPD_ACTTYPE_DROP
) {
3696 warnx(gettext("dir string "
3697 "not found for bypass policy"));
3701 warnx(gettext("Algorithms found for bypass policy"));
3707 warnx(gettext("No IPsec algorithms given"));
3710 if (cptr
->iap_attr
== 0) {
3711 warnx(gettext("No SA attribute"));
3718 * This function is called only to parse a single rule's worth of
3719 * action strings. This is called after parsing pattern and before
3720 * parsing properties. Thus we may have something in the leftover
3721 * buffer while parsing the pattern, which we need to handle here.
3724 parse_action(FILE *fp
, char **action
, char **leftover
)
3730 boolean_t new_stuff
;
3732 if (*leftover
!= NULL
) {
3734 new_stuff
= B_FALSE
;
3737 while (fgets(ibuf
, MAXLEN
, fp
) != NULL
) {
3739 if (ibuf
[strlen(ibuf
) - 1] == '\n')
3743 /* Truncate at the beginning of a comment */
3744 cp
= strchr(buf
, '#');
3748 /* Skip any whitespace */
3749 while (*buf
!= '\0' && isspace(*buf
))
3757 * Store the command for error reporting
3758 * and ipsec_conf_add().
3762 * Check for buffer overflow including the null
3763 * terminating character.
3765 int len
= strlen(ibuf
);
3766 if ((cbuf_offset
+ len
+ 1) >= CBUF_LEN
)
3769 (void) strcpy(cbuf
+ cbuf_offset
, ibuf
);
3773 * Start of the non-empty non-space character.
3777 /* Skip until next whitespace or CURL_BEGIN */
3778 while (*buf
!= '\0' && !isspace(*buf
) &&
3783 if (tmp_buf
== buf
) /* No action token */
3785 if (*buf
== CURL_BEGIN
) {
3787 /* Allocate an extra byte for the null also */
3788 if ((*action
= malloc(strlen(tmp_buf
) + 1)) ==
3793 (void) strcpy(*action
, tmp_buf
);
3796 /* We have hit a space */
3798 /* Allocate an extra byte for the null also */
3799 if ((*action
= malloc(strlen(tmp_buf
) + 1)) ==
3804 (void) strcpy(*action
, tmp_buf
);
3807 * Copy the rest of the line into the
3811 (void) strlcpy(lo_buf
, buf
, sizeof (lo_buf
));
3817 /* Allocate an extra byte for the null also */
3818 if ((*action
= malloc(strlen(tmp_buf
) + 1)) ==
3823 (void) strcpy(*action
, tmp_buf
);
3826 if (argindex
>= ARG_BUF_LEN
) {
3827 warnx(gettext("(parsing one command) "
3828 "Too many selectors before action."));
3831 arg_indices
[argindex
++] = linecount
;
3832 return (PARSE_SUCCESS
);
3835 * Return error, on an empty action field.
3838 warnx(gettext("(parsing one command) "
3839 "Missing action token."));
3844 * This is called to parse pattern or properties that is enclosed
3845 * between CURL_BEGIN and CURL_END.
3848 parse_pattern_or_prop(FILE *fp
, char *argvec
[], char **leftover
)
3852 boolean_t curl_begin_seen
= B_FALSE
;
3856 boolean_t new_stuff
;
3859 * When parsing properties, leftover buffer could have the
3860 * leftovers of the previous fgets().
3862 if (*leftover
!= NULL
) {
3864 new_stuff
= B_FALSE
;
3867 while (fgets(ibuf
, MAXLEN
, fp
) != NULL
) {
3870 (void) printf("%s\n", ibuf
);
3872 if (ibuf
[strlen(ibuf
) - 1] == '\n')
3876 /* Truncate at the beginning of a comment */
3877 cp
= strchr(buf
, '#');
3881 /* Skip any whitespace */
3882 while (*buf
!= '\0' && isspace(*buf
))
3889 * Store the command for error reporting
3890 * and ipsec_conf_add().
3894 * Check for buffer overflow including the null
3895 * terminating character.
3897 int len
= strlen(ibuf
);
3898 if ((cbuf_offset
+ len
+ 1) >= CBUF_LEN
)
3900 (void) strcpy(cbuf
+ cbuf_offset
, ibuf
);
3904 * First non-space character should be
3907 if (!curl_begin_seen
) {
3908 if (*buf
!= CURL_BEGIN
) {
3910 * If we never read a newline character,
3911 * we don't want to print 0.
3913 warnx(gettext("line %d : pattern must start "
3914 "with \"%c\" character"),
3915 (linecount
== 0) ? 1 : linecount
,
3920 curl_begin_seen
= B_TRUE
;
3923 * Arguments are separated by white spaces or
3924 * newlines. Scan till you see a CURL_END.
3926 while (*buf
!= '\0') {
3927 if (*buf
== CURL_END
) {
3931 * Copy the rest of the line into the
3932 * leftover buffer if any.
3935 (void) strlcpy(lo_buf
, buf
,
3941 return (PARSE_SUCCESS
);
3944 * Skip any trailing whitespace until we see a
3945 * non white-space character.
3947 while (*buf
!= '\0' && isspace(*buf
))
3950 if (*buf
== CURL_END
)
3953 /* Scan the next line as this buffer is empty */
3959 gettext("Number of Arguments exceeded %d"),
3964 * Non-empty, Non-space buffer.
3968 * Real scan of the argument takes place here.
3969 * Skip past till space or CURL_END.
3971 while (*buf
!= '\0' && !isspace(*buf
) &&
3976 * Either a space or we have hit the CURL_END or
3980 if (*buf
== CURL_END
) {
3982 if ((argvec
[i
] = malloc(strlen(tmp_buf
)
3987 if (strlen(tmp_buf
) != 0) {
3988 (void) strcpy(argvec
[i
],
3990 if (argindex
>= ARG_BUF_LEN
)
3992 arg_indices
[argindex
++] =
3996 * Copy the rest of the line into the
4000 (void) strlcpy(lo_buf
, buf
,
4006 return (PARSE_SUCCESS
);
4012 * Copy this argument and scan for the buffer more
4013 * if it is non-empty. If it is empty scan for
4016 if ((argvec
[i
] = malloc(strlen(tmp_buf
) + 1)) ==
4021 (void) strcpy(argvec
[i
++], tmp_buf
);
4022 if (argindex
>= ARG_BUF_LEN
) {
4024 * The number of tokens in a single policy entry
4025 * exceeds the number of buffers available to fully
4026 * parse the policy entry.
4029 warnx(gettext("(parsing one command) "
4030 "Too many tokens in single policy entry."));
4033 arg_indices
[argindex
++] = linecount
;
4037 * If nothing is given in the file, it is okay.
4038 * If something is given in the file and it is
4039 * not CURL_BEGIN, we would have returned error
4040 * above. If curl_begin_seen and we are here,
4041 * something is wrong.
4043 if (curl_begin_seen
) {
4044 warnx(gettext("(parsing one command) "
4045 "Pattern or Properties incomplete."));
4048 return (PARSE_EOF
); /* Nothing more in the file */
4052 * Parse one command i.e {pattern} action {properties}.
4054 * {pattern} ( action {prop} | pass | drop ) (or ...)*
4057 parse_one(FILE *fp
, act_prop_t
*act_props
)
4063 enum parse_state
{pattern
, action
, prop
} pstate
;
4065 has_daprefix
= has_saprefix
= B_FALSE
;
4067 (void) memset(act_props
, 0, sizeof (act_prop_t
));
4074 assert(shp
== NULL
&& dhp
== NULL
);
4081 (void) printf("pattern\n");
4083 ret
= parse_pattern_or_prop(fp
,
4084 act_props
->pattern
, &leftover
);
4085 if (ret
== PARSE_EOF
) {
4099 (void) printf("action\n");
4101 ret
= parse_action(fp
,
4102 &act_props
->ap
[ap_num
].act
, &leftover
);
4109 * Validate action now itself so that we don't
4110 * proceed too much into the bad world.
4112 for (i
= 0; action_table
[i
].string
; i
++) {
4113 if (strcmp(act_props
->ap
[ap_num
].act
,
4114 action_table
[i
].string
) == 0)
4118 if (action_table
[i
].tok_val
== TOK_or
) {
4119 /* hit an or, go again */
4123 if (action_table
[i
].string
== NULL
) {
4125 * If we never read a newline
4126 * character, we don't want
4129 warnx(gettext("(parsing one command) "
4130 "Invalid action on line %d: %s"),
4131 (linecount
== 0) ? 1 : linecount
,
4132 act_props
->ap
[ap_num
].act
);
4142 (void) printf("prop\n");
4144 ret
= parse_pattern_or_prop(fp
,
4145 act_props
->ap
[ap_num
].prop
, &leftover
);
4147 if (ret
== PARSE_EOF
) {
4148 warnx(gettext("(parsing one command) "
4149 "Missing properties."));
4155 if (leftover
!= NULL
) {
4156 /* Accomodate spaces at the end */
4157 while (*leftover
!= '\0') {
4158 if (*leftover
== BACK_SLASH
) {
4159 warnx(gettext("Invalid line "
4160 "continuation character."));
4164 if (*leftover
== 'o') {
4166 if (*leftover
== 'r') {
4173 if (!isspace(*leftover
)) {
4182 if (ap_num
> MAXARGS
)
4184 pstate
= action
; /* or */
4187 } /* switch(pstate) */
4190 if (ap_num
> MAXARGS
) {
4191 warnx(gettext("Too many actions."));
4198 * If we never read a newline character, we don't want
4201 warnx(gettext("Error before or at line %d"),
4202 (linecount
== 0) ? 1 : linecount
);
4208 * convert an act_propts_t to an ips_conf_t
4212 form_ipsec_conf(act_prop_t
*act_props
, ips_conf_t
*cptr
)
4216 struct protoent
*pent
;
4217 boolean_t saddr
, daddr
, ipsec_aalg
, ipsec_ealg
, ipsec_eaalg
, dir
;
4218 boolean_t old_style
, new_style
, auth_covered
, is_no_alg
;
4219 boolean_t is_combined_mode
;
4220 struct in_addr mask
;
4224 int type
, code
, type_end
, code_end
;
4227 * pattern => act_props->pattern
4228 * action => act_props->ap[].act
4229 * properties => act_props->ap[].prop
4231 (void) printf("\npattern\n------------\n");
4232 for (i
= 0; act_props
->pattern
[i
] != NULL
; i
++)
4233 (void) printf("%s\n", act_props
->pattern
[i
]);
4234 (void) printf("apz\n----------\n");
4235 for (j
= 0; act_props
->ap
[j
].act
!= NULL
; j
++) {
4237 (void) printf("act%d->%s\n", j
, act_props
->ap
[j
].act
);
4238 for (i
= 0; act_props
->ap
[j
].prop
[i
] != NULL
; i
++)
4239 (void) printf("%dprop%d->%s\n",
4240 j
, i
, act_props
->ap
[j
].prop
[i
]);
4242 (void) printf("------------\n\n");
4245 (void) memset(cptr
, 0, sizeof (ips_conf_t
));
4246 saddr
= daddr
= ipsec_aalg
= ipsec_ealg
= ipsec_eaalg
= dir
= B_FALSE
;
4247 old_style
= new_style
= is_no_alg
= is_combined_mode
= B_FALSE
;
4249 * Get the Pattern. NULL pattern is valid.
4251 for (i
= 0, line_no
= 0; act_props
->pattern
[i
]; i
++, line_no
++) {
4252 for (j
= 0; pattern_table
[j
].string
; j
++) {
4253 if (strcmp(act_props
->pattern
[i
],
4254 pattern_table
[j
].string
) == 0)
4258 if (pattern_table
[j
].string
== NULL
) {
4260 * If we never read a newline character, we don't want
4263 warnx(gettext("Invalid pattern on line %d: %s"),
4264 (arg_indices
[line_no
] == 0) ? 1 :
4265 arg_indices
[line_no
], act_props
->pattern
[i
]);
4269 cptr
->patt_tok
[tok_count
++] = pattern_table
[j
].tok_val
;
4271 switch (pattern_table
[j
].tok_val
) {
4275 if (act_props
->pattern
[i
] == NULL
) {
4276 error_message(BAD_ERROR
,
4277 IPSEC_CONF_IPSEC_DIR
, line_no
);
4281 if (strncmp(act_props
->pattern
[i
], "in", 2) == 0) {
4282 cptr
->ips_dir
= SPD_RULE_FLAG_INBOUND
;
4284 act_props
->pattern
[i
], "out", 3) == 0) {
4285 cptr
->ips_dir
= SPD_RULE_FLAG_OUTBOUND
;
4287 act_props
->pattern
[i
], "both", 4) == 0) {
4289 error_message(BAD_ERROR
,
4290 IPSEC_CONF_IPSEC_DIR
, line_no
);
4295 SPD_RULE_FLAG_OUTBOUND
|
4296 SPD_RULE_FLAG_INBOUND
;
4298 error_message(BAD_ERROR
,
4299 IPSEC_CONF_IPSEC_DIR
, line_no
);
4307 error_message(BAD_ERROR
,
4308 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4314 error_message(DUP_ERROR
,
4315 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4319 * Use this to detect duplicates rather
4320 * than 0 like other cases, because 0 for
4321 * address means INADDR_ANY.
4324 cptr
->has_saddr
= 1;
4326 * Advance to the string containing
4330 if (act_props
->pattern
[i
] == NULL
) {
4331 error_message(BAD_ERROR
,
4332 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4335 if (parse_address(IPSEC_CONF_SRC_ADDRESS
,
4336 act_props
->pattern
[i
]) != 0) {
4337 error_message(BAD_ERROR
,
4338 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4341 if (!cptr
->has_smask
)
4342 cptr
->has_smask
= has_saprefix
;
4347 error_message(BAD_ERROR
,
4348 IPSEC_CONF_DST_ADDRESS
, line_no
);
4354 error_message(DUP_ERROR
,
4355 IPSEC_CONF_DST_ADDRESS
, line_no
);
4359 * Use this to detect duplicates rather
4360 * than 0 like other cases, because 0 for
4361 * address means INADDR_ANY.
4364 cptr
->has_daddr
= 1;
4366 * Advance to the string containing
4370 if (act_props
->pattern
[i
] == NULL
) {
4371 error_message(BAD_ERROR
,
4372 IPSEC_CONF_DST_ADDRESS
, line_no
);
4375 if (parse_address(IPSEC_CONF_DST_ADDRESS
,
4376 act_props
->pattern
[i
]) != 0) {
4377 error_message(BAD_ERROR
,
4378 IPSEC_CONF_DST_ADDRESS
, line_no
);
4381 if (!cptr
->has_dmask
)
4382 cptr
->has_dmask
= has_daprefix
;
4387 error_message(BAD_ERROR
,
4388 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4394 error_message(DUP_ERROR
,
4395 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4399 * Use this to detect duplicates rather
4400 * than 0 like other cases, because 0 for
4401 * address means INADDR_ANY.
4404 cptr
->has_saddr
= 1;
4406 * Advance to the string containing
4410 if (act_props
->pattern
[i
] == NULL
) {
4411 error_message(BAD_ERROR
,
4412 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4416 if (parse_address(IPSEC_CONF_SRC_ADDRESS
,
4417 act_props
->pattern
[i
]) != 0) {
4418 error_message(BAD_ERROR
,
4419 IPSEC_CONF_SRC_ADDRESS
, line_no
);
4423 if (!cptr
->has_smask
)
4424 cptr
->has_smask
= has_saprefix
;
4429 error_message(BAD_ERROR
,
4430 IPSEC_CONF_DST_ADDRESS
, line_no
);
4436 error_message(DUP_ERROR
,
4437 IPSEC_CONF_DST_ADDRESS
, line_no
);
4441 * Use this to detect duplicates rather
4442 * than 0 like other cases, because 0 for
4443 * address means INADDR_ANY.
4446 cptr
->has_daddr
= 1;
4448 * Advance to the string containing
4452 if (act_props
->pattern
[i
] == NULL
) {
4453 error_message(BAD_ERROR
,
4454 IPSEC_CONF_DST_ADDRESS
, line_no
);
4457 if (parse_address(IPSEC_CONF_DST_ADDRESS
,
4458 act_props
->pattern
[i
]) != 0) {
4459 error_message(BAD_ERROR
,
4460 IPSEC_CONF_DST_ADDRESS
, line_no
);
4463 if (!cptr
->has_dmask
)
4464 cptr
->has_dmask
= has_daprefix
;
4469 error_message(BAD_ERROR
,
4470 IPSEC_CONF_SRC_PORT
, line_no
);
4475 if (cptr
->ips_src_port_min
!= 0) {
4476 error_message(DUP_ERROR
, IPSEC_CONF_SRC_PORT
,
4481 if (act_props
->pattern
[i
] == NULL
) {
4482 error_message(BAD_ERROR
, IPSEC_CONF_SRC_PORT
,
4486 ret
= parse_port(IPSEC_CONF_SRC_PORT
,
4487 act_props
->pattern
[i
], cptr
);
4489 error_message(BAD_ERROR
, IPSEC_CONF_SRC_PORT
,
4496 error_message(BAD_ERROR
,
4497 IPSEC_CONF_DST_PORT
, line_no
);
4502 if (cptr
->ips_dst_port_min
!= 0) {
4503 error_message(DUP_ERROR
, IPSEC_CONF_DST_PORT
,
4508 if (act_props
->pattern
[i
] == NULL
) {
4509 error_message(BAD_ERROR
, IPSEC_CONF_DST_PORT
,
4513 ret
= parse_port(IPSEC_CONF_DST_PORT
,
4514 act_props
->pattern
[i
],
4517 error_message(BAD_ERROR
, IPSEC_CONF_DST_PORT
,
4525 error_message(BAD_ERROR
,
4526 IPSEC_CONF_SRC_PORT
, line_no
);
4531 if (cptr
->ips_src_port_min
!= 0) {
4532 error_message(DUP_ERROR
, IPSEC_CONF_SRC_PORT
,
4537 if (act_props
->pattern
[i
] == NULL
) {
4538 error_message(BAD_ERROR
, IPSEC_CONF_SRC_PORT
,
4542 ret
= parse_port(IPSEC_CONF_SRC_PORT
,
4543 act_props
->pattern
[i
],
4546 error_message(BAD_ERROR
, IPSEC_CONF_SRC_PORT
,
4554 error_message(BAD_ERROR
,
4555 IPSEC_CONF_DST_PORT
, line_no
);
4560 if (cptr
->ips_dst_port_min
!= 0) {
4561 error_message(DUP_ERROR
, IPSEC_CONF_DST_PORT
,
4566 if (act_props
->pattern
[i
] == NULL
) {
4567 error_message(BAD_ERROR
, IPSEC_CONF_DST_PORT
,
4571 ret
= parse_port(IPSEC_CONF_DST_PORT
,
4572 act_props
->pattern
[i
],
4575 error_message(BAD_ERROR
, IPSEC_CONF_DST_PORT
,
4583 error_message(BAD_ERROR
,
4584 IPSEC_CONF_SRC_MASK
, line_no
);
4588 cptr
->has_smask
= B_TRUE
;
4590 IN6_V4MAPPED_TO_INADDR(&cptr
->ips_src_mask_v6
, &mask
);
4591 if (mask
.s_addr
!= 0) {
4592 error_message(DUP_ERROR
, IPSEC_CONF_SRC_MASK
,
4597 if (act_props
->pattern
[i
] == NULL
) {
4598 error_message(BAD_ERROR
, IPSEC_CONF_SRC_MASK
,
4602 ret
= parse_mask(IPSEC_CONF_SRC_MASK
,
4603 act_props
->pattern
[i
],
4606 error_message(BAD_ERROR
, IPSEC_CONF_SRC_MASK
,
4613 error_message(BAD_ERROR
,
4614 IPSEC_CONF_DST_MASK
, line_no
);
4618 cptr
->has_dmask
= B_TRUE
;
4620 IN6_V4MAPPED_TO_INADDR(&cptr
->ips_dst_mask_v6
, &mask
);
4621 if (mask
.s_addr
!= 0) {
4622 error_message(DUP_ERROR
, IPSEC_CONF_DST_MASK
,
4627 if (act_props
->pattern
[i
] == NULL
) {
4628 error_message(BAD_ERROR
, IPSEC_CONF_DST_MASK
,
4632 ret
= parse_mask(IPSEC_CONF_DST_MASK
,
4633 act_props
->pattern
[i
],
4636 error_message(BAD_ERROR
, IPSEC_CONF_DST_MASK
,
4642 if (cptr
->ips_ulp_prot
!= 0) {
4643 error_message(DUP_ERROR
,
4644 IPSEC_CONF_ULP
, line_no
);
4648 if (act_props
->pattern
[i
] == NULL
) {
4649 error_message(BAD_ERROR
,
4650 IPSEC_CONF_ULP
, line_no
);
4653 pent
= getprotobyname(act_props
->pattern
[i
]);
4656 ulp
= parse_int(act_props
->pattern
[i
]);
4658 error_message(BAD_ERROR
,
4659 IPSEC_CONF_ULP
, line_no
);
4662 cptr
->ips_ulp_prot
= ulp
;
4664 cptr
->ips_ulp_prot
= pent
->p_proto
;
4668 if (cptr
->has_type
) {
4669 error_message(DUP_ERROR
,
4670 IPSEC_CONF_ICMP_TYPE
, line_no
);
4675 type
= parse_type_code(act_props
->pattern
[i
],
4678 if (type
> 65536 || type
< 0) {
4679 error_message(BAD_ERROR
,
4680 IPSEC_CONF_ICMP_TYPE
, line_no
);
4684 type_end
= type
/ 256;
4687 if (type_end
< type
)
4691 cptr
->ips_icmp_type
= (uint8_t)type
;
4692 cptr
->ips_icmp_type_end
= (uint8_t)type_end
;
4695 if (!cptr
->has_type
) {
4696 error_message(BAD_ERROR
,
4697 IPSEC_CONF_ICMP_CODE
, line_no
);
4701 if (cptr
->has_code
) {
4702 error_message(DUP_ERROR
,
4703 IPSEC_CONF_ICMP_CODE
, line_no
);
4709 code
= parse_type_code(act_props
->pattern
[i
],
4711 if (type
> 65536 || type
< 0) {
4712 error_message(BAD_ERROR
,
4713 IPSEC_CONF_ICMP_CODE
, line_no
);
4716 code_end
= code
/ 256;
4719 if (code_end
< code
)
4723 cptr
->ips_icmp_code
= (uint8_t)code
;
4724 cptr
->ips_icmp_code_end
= (uint8_t)code_end
;
4727 if (cptr
->has_tunnel
== 1) {
4728 error_message(BAD_ERROR
,
4729 IPSEC_CONF_TUNNEL
, line_no
);
4733 if (act_props
->pattern
[i
] == NULL
) {
4734 error_message(BAD_ERROR
,
4735 IPSEC_CONF_TUNNEL
, line_no
);
4739 if (strlcpy(tunif
, act_props
->pattern
[i
],
4740 TUNNAMEMAXLEN
) >= TUNNAMEMAXLEN
) {
4741 error_message(BAD_ERROR
,
4742 IPSEC_CONF_TUNNEL
, line_no
);
4745 cptr
->has_tunnel
= 1;
4748 if (cptr
->has_negotiate
== 1) {
4749 error_message(BAD_ERROR
,
4750 IPSEC_CONF_NEGOTIATE
, line_no
);
4754 if (act_props
->pattern
[i
] == NULL
) {
4755 error_message(BAD_ERROR
,
4756 IPSEC_CONF_NEGOTIATE
, line_no
);
4760 if (strncmp(act_props
->pattern
[i
], "tunnel", 6) == 0) {
4761 cptr
->ips_tunnel
= B_TRUE
;
4763 act_props
->pattern
[i
], "transport", 9) != 0) {
4764 error_message(BAD_ERROR
,
4765 IPSEC_CONF_NEGOTIATE
, line_no
);
4768 cptr
->has_negotiate
= 1;
4774 /* Sanity check that certain tokens occur together */
4775 if (cptr
->has_tunnel
+ cptr
->has_negotiate
== 1) {
4776 if (cptr
->has_negotiate
== 0) {
4777 error_message(REQ_ERROR
, IPSEC_CONF_NEGOTIATE
, line_no
);
4779 error_message(REQ_ERROR
, IPSEC_CONF_TUNNEL
, line_no
);
4782 "tunnel and negotiate tokens must occur together"));
4790 for (ap_num
= 0; act_props
->ap
[ap_num
].act
!= NULL
; ap_num
++) {
4791 ips_act_props_t
*iap
;
4794 /* or's only with new style */
4796 (void) printf("%s\n", gettext(
4797 "or's only with new style"));
4803 ipsec_aalg
= ipsec_ealg
= ipsec_eaalg
= auth_covered
= B_FALSE
;
4806 for (k
= 0; action_table
[k
].string
; k
++) {
4807 if (strcmp(act_props
->ap
[ap_num
].act
,
4808 action_table
[k
].string
) == 0)
4812 * The following thing should never happen as
4813 * we have already tested for its validity in parse.
4815 if (action_table
[k
].string
== NULL
) {
4816 warnx(gettext("(form act)Invalid action on line "
4817 "%d: %s"), (arg_indices
[line_no
] == 0) ? 1 :
4818 arg_indices
[line_no
],
4819 act_props
->ap
[ap_num
].act
);
4820 warnx("%s", act_props
->ap
[ap_num
].act
);
4824 /* we have a good action alloc an iap */
4825 iap
= alloc_iap(cptr
);
4827 iap
->iap_action
= action_table
[k
].value
;
4828 iap
->iap_act_tok
= action_table
[k
].tok_val
;
4830 switch (action_table
[k
].tok_val
) {
4832 cptr
->ips_dir
= SPD_RULE_FLAG_OUTBOUND
;
4835 cptr
->ips_dir
= SPD_RULE_FLAG_INBOUND
;
4839 /* Using saddr/daddr with ipsec action. */
4841 /* No direction specified */
4842 error_message(REQ_ERROR
,
4843 IPSEC_CONF_IPSEC_DIR
, line_no
);
4846 if (cptr
->ips_dir
== SPD_RULE_FLAG_INBOUND
)
4848 * Need to swap addresses if
4849 * 'dir in' or translation to
4850 * laddr/raddr will be incorrect.
4856 SPD_RULE_FLAG_INBOUND
4857 |SPD_RULE_FLAG_OUTBOUND
;
4867 * Get the properties. NULL properties is not valid.
4868 * Later checks will catch it.
4870 for (i
= 0; act_props
->ap
[ap_num
].prop
[i
]; i
++, line_no
++) {
4871 for (j
= 0; property_table
[j
].string
; j
++) {
4872 if (strcmp(act_props
->ap
[ap_num
].prop
[i
],
4873 property_table
[j
].string
) == 0) {
4877 if (property_table
[j
].string
== NULL
) {
4878 warnx(gettext("Invalid properties on line "
4880 (arg_indices
[line_no
] == 0) ?
4881 1 : arg_indices
[line_no
],
4882 act_props
->ap
[ap_num
].prop
[i
]);
4886 iap
->iap_attr_tok
[tok_count
++]
4887 = property_table
[j
].value
;
4889 switch (property_table
[j
].value
) {
4890 case SPD_ATTR_AH_AUTH
:
4892 error_message(DUP_ERROR
,
4893 IPSEC_CONF_IPSEC_AALGS
, line_no
);
4897 if (act_props
->ap
[ap_num
].prop
[i
] == NULL
) {
4898 error_message(BAD_ERROR
,
4899 IPSEC_CONF_IPSEC_AALGS
, line_no
);
4902 ret
= parse_ipsec_alg(
4903 act_props
->ap
[ap_num
].prop
[i
],
4904 iap
, SPD_ATTR_AH_AUTH
);
4906 /* "none" - ignore */
4910 error_message(BAD_ERROR
,
4911 IPSEC_CONF_IPSEC_AALGS
, line_no
);
4914 ipsec_aalg
= B_TRUE
;
4915 auth_covered
= B_TRUE
;
4917 case SPD_ATTR_ESP_ENCR
:
4919 * If this option was not given
4920 * and encr_auth_algs was given,
4921 * we provide null-encryption. We do the
4922 * setting after we parse all the options.
4925 error_message(DUP_ERROR
,
4926 IPSEC_CONF_IPSEC_EALGS
, line_no
);
4930 if (act_props
->ap
[ap_num
].prop
[i
] == NULL
) {
4931 error_message(BAD_ERROR
,
4932 IPSEC_CONF_IPSEC_EALGS
, line_no
);
4935 ret
= parse_ipsec_alg(
4936 act_props
->ap
[ap_num
].prop
[i
],
4937 iap
, SPD_ATTR_ESP_ENCR
);
4939 /* "none" - ignore */
4943 error_message(BAD_ERROR
,
4944 IPSEC_CONF_IPSEC_EALGS
, line_no
);
4948 combined_mode(iap
->iap_eencr
.alg_id
);
4949 ipsec_ealg
= B_TRUE
;
4951 case SPD_ATTR_ESP_AUTH
:
4953 * If this option was not given and encr_algs
4954 * option was given, we still pass a default
4955 * value in ipsc_esp_auth_algs. This is to
4956 * encourage the use of authentication with
4960 error_message(DUP_ERROR
,
4961 IPSEC_CONF_IPSEC_EAALGS
, line_no
);
4965 if (act_props
->ap
[ap_num
].prop
[i
] == NULL
) {
4966 error_message(BAD_ERROR
,
4967 IPSEC_CONF_IPSEC_EAALGS
, line_no
);
4970 ret
= parse_ipsec_alg(
4971 act_props
->ap
[ap_num
].prop
[i
],
4972 iap
, SPD_ATTR_ESP_AUTH
);
4974 /* "none" - ignore */
4978 error_message(BAD_ERROR
,
4979 IPSEC_CONF_IPSEC_EAALGS
, line_no
);
4982 ipsec_eaalg
= B_TRUE
;
4983 auth_covered
= B_TRUE
;
4987 if (act_props
->ap
[ap_num
].prop
[i
] == NULL
) {
4988 error_message(BAD_ERROR
,
4989 IPSEC_CONF_IPSEC_SA
, line_no
);
4993 if (strcmp(act_props
->ap
[ap_num
].prop
[i
],
4995 iap
->iap_attr
|= SPD_APPLY_UNIQUE
;
4996 } else if (strcmp(act_props
->ap
[ap_num
].prop
[i
],
4998 /* "shared" is default. */
4999 error_message(BAD_ERROR
,
5000 IPSEC_CONF_IPSEC_SA
, line_no
);
5007 error_message(DUP_ERROR
,
5008 IPSEC_CONF_IPSEC_DIR
, line_no
);
5012 error_message(BAD_ERROR
,
5013 IPSEC_CONF_IPSEC_DIR
, line_no
);
5019 if (act_props
->ap
[ap_num
].prop
[i
] == NULL
) {
5020 error_message(BAD_ERROR
,
5021 IPSEC_CONF_IPSEC_DIR
, line_no
);
5024 if (strcmp(act_props
->ap
[ap_num
].prop
[i
],
5026 cptr
->ips_dir
= SPD_RULE_FLAG_OUTBOUND
;
5027 } else if (strcmp(act_props
->ap
[ap_num
].prop
[i
],
5029 cptr
->ips_dir
= SPD_RULE_FLAG_INBOUND
;
5031 error_message(BAD_ERROR
,
5032 IPSEC_CONF_IPSEC_DIR
, line_no
);
5035 if ((cptr
->ips_dir
& SPD_RULE_FLAG_INBOUND
) &&
5036 iap
->iap_act_tok
== TOK_apply
) {
5037 warnx(gettext("Direction"
5038 " in conflict with action"));
5041 if ((cptr
->ips_dir
& SPD_RULE_FLAG_OUTBOUND
) &&
5042 iap
->iap_act_tok
== TOK_permit
) {
5043 warnx(gettext("Direction"
5044 "in conflict with action"));
5052 if (is_combined_mode
) {
5054 warnx(gettext("ERROR: Rule on line %d: "
5055 "Combined mode and esp authentication not "
5056 "supported together."),
5057 arg_indices
[line_no
] == 0 ? 1 :
5058 arg_indices
[line_no
]);
5061 auth_covered
= B_TRUE
;
5063 /* Warn here about no authentication! */
5064 if (!auth_covered
&& !is_no_alg
) {
5065 warnx(gettext("DANGER: Rule on line %d "
5066 "has encryption with no authentication."),
5067 arg_indices
[line_no
] == 0 ? 1 :
5068 arg_indices
[line_no
]);
5071 if (!ipsec_ealg
&& ipsec_eaalg
) {
5073 * If the user has specified the auth alg to be used
5074 * with encryption and did not provide a encryption
5075 * algorithm, provide null encryption.
5077 iap
->iap_eencr
.alg_id
= SADB_EALG_NULL
;
5078 ipsec_ealg
= B_TRUE
;
5081 /* Set the level of IPSEC protection we want */
5082 if (ipsec_aalg
&& (ipsec_ealg
|| ipsec_eaalg
)) {
5083 iap
->iap_attr
|= SPD_APPLY_AH
|SPD_APPLY_ESP
;
5084 } else if (ipsec_aalg
) {
5085 iap
->iap_attr
|= SPD_APPLY_AH
;
5086 } else if (ipsec_ealg
|| ipsec_eaalg
) {
5087 iap
->iap_attr
|= SPD_APPLY_ESP
;
5090 /* convert src/dst to local/remote */
5092 switch (cptr
->ips_acts
->iap_act_tok
) {
5095 /* src=local, dst=remote */
5101 /* src=remote, dst=local */
5107 /* check the direction for what to do */
5108 if (cptr
->ips_dir
== SPD_RULE_FLAG_INBOUND
)
5115 /* Validate the properties */
5116 if (ret
= validate_properties(iap
, dir
,
5117 (ipsec_aalg
|| ipsec_ealg
|| ipsec_eaalg
))) {
5127 print_cmd_buf(FILE *fp
, int error
)
5129 *(cbuf
+ cbuf_offset
) = '\0';
5132 if (error
!= EEXIST
) {
5133 warnx(gettext("Malformed command (fatal):\n%s"), cbuf
);
5136 if (ipsecconf_qflag
) {
5139 warnx(gettext("Duplicate policy entry (ignored):\n%s"), cbuf
);
5141 if (fprintf(fp
, "%s", cbuf
) == -1) {
5153 addr_ptr(int isv4
, struct in6_addr
*addr6
, struct in_addr
*addr4
)
5156 IN6_V4MAPPED_TO_INADDR(addr6
, addr4
);
5157 return ((uchar_t
*)&addr4
->s_addr
);
5159 return ((uchar_t
*)&addr6
->s6_addr
);
5164 dump_algreq(const char *tag
, algreq_t
*alg
)
5166 (void) printf("%s algid %d, bits %d..%d\n",
5167 tag
, alg
->alg_id
, alg
->alg_minbits
, alg
->alg_maxbits
);
5171 dump_conf(ips_conf_t
*conf
)
5173 boolean_t isv4
= conf
->ips_isv4
;
5174 struct in_addr addr
;
5175 char buf
[INET6_ADDRSTRLEN
];
5177 ips_act_props_t
*iap
= conf
->ips_acts
;
5179 af
= isv4
? AF_INET
: AF_INET6
;
5181 (void) printf("Source Addr is %s\n",
5182 inet_ntop(af
, addr_ptr(isv4
, &conf
->ips_src_addr_v6
, &addr
),
5183 buf
, INET6_ADDRSTRLEN
));
5185 (void) printf("Dest Addr is %s\n",
5186 inet_ntop(af
, addr_ptr(isv4
, &conf
->ips_dst_addr_v6
, &addr
),
5187 buf
, INET6_ADDRSTRLEN
));
5189 (void) printf("Source Mask is %s\n",
5190 inet_ntop(af
, addr_ptr(isv4
, &conf
->ips_src_mask_v6
, &addr
),
5191 buf
, INET6_ADDRSTRLEN
));
5193 (void) printf("Dest Mask is %s\n",
5194 inet_ntop(af
, addr_ptr(isv4
, &conf
->ips_dst_mask_v6
, &addr
),
5195 buf
, INET6_ADDRSTRLEN
));
5197 (void) printf("Source port %d\n", ntohs(conf
->ips_src_port_min
));
5198 (void) printf("Dest port %d\n", ntohs(conf
->ips_dst_port_min
));
5199 (void) printf("ULP %d\n", conf
->ips_ulp_prot
);
5201 (void) printf("ICMP type %d-%d code %d-%d", conf
->ips_icmp_type
,
5202 conf
->ips_icmp_type_end
,
5203 conf
->ips_icmp_code
,
5204 conf
->ips_icmp_code_end
);
5206 while (iap
!= NULL
) {
5207 (void) printf("------------------------------------\n");
5208 (void) printf("IPsec act is %d\n", iap
->iap_action
);
5209 (void) printf("IPsec attr is %d\n", iap
->iap_attr
);
5210 dump_algreq("AH authentication", &iap
->iap_aauth
);
5211 dump_algreq("ESP authentication", &iap
->iap_eauth
);
5212 dump_algreq("ESP encryption", &iap
->iap_eencr
);
5213 (void) printf("------------------------------------\n");
5214 iap
= iap
->iap_next
;
5217 (void) fflush(stdout
);
5223 ipsec_conf_add(boolean_t just_check
, boolean_t smf_managed
, boolean_t replace
)
5225 act_prop_t
*act_props
= malloc(sizeof (act_prop_t
));
5227 FILE *fp
, *policy_fp
;
5228 int ret
, flushret
, i
, j
, diag
, num_rules
, good_rules
;
5229 char *warning
= gettext(
5230 "\tWARNING : New policy entries that are being added may\n "
5231 "\taffect the existing connections. Existing connections\n"
5232 "\tthat are not subjected to policy constraints, may be\n"
5233 "\tsubjected to policy constraints because of the new\n"
5234 "\tpolicy. This can disrupt the communication of the\n"
5235 "\texisting connections.\n\n");
5237 boolean_t first_time
= B_TRUE
;
5241 if (act_props
== NULL
) {
5242 warn(gettext("memory"));
5246 if (strcmp(filename
, "-") == 0)
5249 fp
= fopen(filename
, "r");
5252 * Treat the non-existence of a policy file as a special
5253 * case when ipsecconf is being managed by smf(5).
5254 * The assumption is the administrator has not yet
5255 * created a policy file, this should not force the service
5256 * into maintenance mode.
5261 (void) fprintf(stdout
, gettext(
5262 "Policy configuration file (%s) does not exist.\n"
5263 "IPsec policy not configured.\n"), filename
);
5266 warn(gettext("%s : Policy config file cannot be opened"),
5272 * This will create the file if it does not exist.
5273 * Make sure the umask is right.
5276 policy_fp
= fopen(POLICY_CONF_FILE
, "a");
5277 if (policy_fp
== NULL
) {
5278 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE
);
5283 * Pattern, action, and properties are allocated in
5284 * parse_pattern_or_prop and in parse_action (called by
5285 * parse_one) as we parse arguments.
5287 while ((ret
= parse_one(fp
, act_props
)) != PARSE_EOF
) {
5290 (void) print_cmd_buf(stderr
, NOERROR
);
5295 * If there is no action and parse returned success,
5296 * it means that there is nothing to add.
5298 if (act_props
->pattern
[0] == NULL
&&
5299 act_props
->ap
[0].act
== NULL
)
5302 ret
= form_ipsec_conf(act_props
, &conf
);
5304 warnx(gettext("form_ipsec_conf error"));
5305 (void) print_cmd_buf(stderr
, NOERROR
);
5306 /* Reset globals before trying the next rule. */
5324 * Time to assume that there are valid policy entries.
5325 * If the IPsec kernel modules are not loaded this
5326 * will load them now.
5328 first_time
= B_FALSE
;
5330 ipsec_conf_admin(SPD_CLONE
);
5333 * The default behaviour for IPSEC_CONF_ADD is to append
5334 * the new rules to the existing policy. If a new rule
5335 * collides with an existing rule, the new rule won't be
5338 * To perform an atomic policy replace, we really don't
5339 * care what the existing policy was, just replace it
5340 * with the new one. Remove all rules from the SPD_CLONE
5341 * policy before checking the new rules.
5344 flushret
= ipsec_conf_flush(SPD_STANDBY
);
5351 * shp, dhp, splen, and dplen are globals set by
5352 * form_ipsec_conf() while parsing the addresses.
5354 if (shp
== NULL
&& dhp
== NULL
) {
5355 switch (do_port_adds(&conf
)) {
5360 /* duplicate entries, continue adds */
5361 (void) print_cmd_buf(stderr
, EEXIST
);
5364 /* other error, bail */
5369 ret
= do_address_adds(&conf
, &diag
);
5375 (void) print_cmd_buf(stderr
, EEXIST
);
5379 "Can't set mask and /NN prefix."));
5383 warnx(gettext("Cannot find tunnel "
5384 "interface %s."), interface_name
);
5389 * PF_POLICY didn't like what we sent. We
5390 * can't check all input up here, but we
5393 warnx(gettext("PF_POLICY invalid input:\n\t%s"),
5394 spdsock_diag(diag
));
5397 warnx(gettext("Can't set /NN"
5398 " prefix on multi-host name."));
5402 warnx(gettext("/NN prefix is too big!"));
5406 warnx(gettext("No matching IPv4 or "
5407 "IPv6 saddr/daddr pairs"));
5411 /* Should never get here. */
5413 warn(gettext("Misc. error"));
5421 * Go ahead and add policy entries to config file.
5422 * The # should help re-using the ipsecpolicy.conf
5423 * for input again as # will be treated as comment.
5425 if (fprintf(policy_fp
, "%s %lld \n", INDEX_TAG
,
5426 conf
.ips_policy_index
) == -1) {
5428 warnx(gettext("Addition incomplete, Please "
5429 "flush all the entries and re-configure :"));
5434 if (print_cmd_buf(policy_fp
, NOERROR
) == -1) {
5435 warnx(gettext("Addition incomplete. Please "
5436 "flush all the entries and re-configure :"));
5442 * We add one newline by default to separate out the
5443 * entries. If the last character is not a newline, we
5444 * insert a newline for free. This makes sure that all
5445 * entries look consistent in the file.
5447 if (*(cbuf
+ cbuf_offset
- 1) == '\n') {
5448 if (fprintf(policy_fp
, "\n") == -1) {
5450 warnx(gettext("Addition incomplete. "
5451 "Please flush all the entries and "
5458 if (fprintf(policy_fp
, "\n\n") == -1) {
5460 warnx(gettext("Addition incomplete. "
5461 "Please flush all the entries and "
5470 * Make sure this gets to the disk before
5471 * we parse the next entry.
5473 (void) fflush(policy_fp
);
5474 for (i
= 0; act_props
->pattern
[i
] != NULL
; i
++)
5475 free(act_props
->pattern
[i
]);
5476 for (j
= 0; act_props
->ap
[j
].act
!= NULL
; j
++) {
5477 free(act_props
->ap
[j
].act
);
5478 for (i
= 0; act_props
->ap
[j
].prop
[i
] != NULL
; i
++)
5479 free(act_props
->ap
[j
].prop
[i
]);
5482 if (ret
== PARSE_EOF
)
5483 ret
= 0; /* Not an error */
5486 (void) print_cmd_buf(stderr
, EINVAL
);
5487 for (i
= 0; act_props
->pattern
[i
] != NULL
; i
++)
5488 free(act_props
->pattern
[i
]);
5489 for (j
= 0; act_props
->ap
[j
].act
!= NULL
; j
++) {
5490 free(act_props
->ap
[j
].act
);
5491 for (i
= 0; act_props
->ap
[j
].prop
[i
] != NULL
; i
++)
5492 free(act_props
->ap
[j
].prop
[i
]);
5496 (void) printf("ipsec_conf_add: ret val = %d\n", ret
);
5497 (void) fflush(stdout
);
5499 if (num_rules
== 0 && ret
== 0) {
5501 (void) restore_all_signals();
5503 EXIT_OK("Policy file does not contain any valid rules.");
5505 if (num_rules
!= good_rules
) {
5506 /* This is an error */
5508 (void) restore_all_signals();
5510 EXIT_BADCONFIG2("%d policy rule(s) contained errors.",
5511 num_rules
- good_rules
);
5513 /* looks good, flip it in */
5514 if (ret
== 0 && !just_check
) {
5515 if (!ipsecconf_qflag
) {
5516 (void) printf("%s", warning
);
5519 warnx(gettext("%d policy rules added."), good_rules
);
5520 ipsec_conf_admin(SPD_FLIP
);
5524 (void) fprintf(stdout
, gettext("IPsec configuration "
5525 "does not contain any errors.\n"));
5526 (void) fprintf(stdout
, gettext(
5527 "IPsec policy was not modified.\n"));
5528 (void) fflush(stdout
);
5531 flushret
= ipsec_conf_flush(SPD_STANDBY
);
5541 act_prop_t
*act_props
= malloc(sizeof (act_prop_t
));
5542 FILE *remove_fp
, *policy_fp
;
5543 char rbuf
[MAXLEN
], pbuf
[MAXLEN
], /* remove buffer, and policy buffer */
5545 "\tWARNING: Policy entries that are being removed may\n"
5546 "\taffect the existing connections. Existing connections\n"
5547 "\tthat are subjected to policy constraints may no longer\n"
5548 "\tbe subjected to policy contraints because of its\n"
5549 "\tremoval. This can compromise security, and disrupt\n"
5550 "\tthe communication of the existing connection.\n"
5551 "\tConnections that are latched will remain unaffected\n"
5552 "\tuntil they close.\n");
5554 int index_len
, pindex
= 0; /* init value in case of pfile error */
5556 if (act_props
== NULL
) {
5557 warn(gettext("memory"));
5561 /* clone into standby DB */
5562 (void) ipsec_conf_admin(SPD_CLONE
);
5564 if (strcmp(filename
, "-") == 0)
5567 remove_fp
= fopen(filename
, "r");
5569 if (remove_fp
== NULL
) {
5570 warn(gettext("%s : Input file cannot be opened"), filename
);
5576 /* open policy file so we can locate the correct policy */
5577 (void) umask(0022); /* in case it gets created! */
5578 policy_fp
= fopen(POLICY_CONF_FILE
, "r+");
5579 if (policy_fp
== NULL
) {
5580 warn(gettext("%s cannot be opened"), POLICY_CONF_FILE
);
5581 (void) fclose(remove_fp
);
5586 /* don't print the warning if we're in q[uiet] mode */
5587 if (!ipsecconf_qflag
)
5588 (void) printf("%s", warning
);
5590 /* this bit is done primarily so we can read what we write */
5591 index_len
= strlen(INDEX_TAG
);
5594 * We want to look for the policy in rbuf in the policy file.
5595 * Go through the list of policies to remove, locating each one.
5597 while (fgets(rbuf
, MAXLEN
, remove_fp
) != NULL
) {
5599 int offset
, prev_offset
, prev_prev_offset
, nlines
;
5603 /* skip blanks here (so we don't need to do it below)! */
5604 for (tmp
= rbuf
; (*tmp
!= '\0') && isspace(*tmp
); )
5608 continue; /* while(); */
5610 /* skip the INDEX_TAG lines in the remove buffer */
5611 if (strncasecmp(rbuf
, INDEX_TAG
, index_len
) == 0)
5614 /* skip commented lines */
5616 continue; /* while(); */
5619 * We start by presuming only good policies are in the pfile,
5620 * and so only good policies from the rfile will match them.
5621 * ipsec_conf_del ensures this later by calling parse_one() on
5622 * pfile before it deletes the entry.
5624 for (offset
= prev_offset
= prev_prev_offset
= 0;
5625 fgets(pbuf
, MAXLEN
, policy_fp
) != NULL
;
5626 offset
+= pbuf_len
) {
5627 prev_offset
= offset
;
5628 pbuf_len
= strlen(pbuf
);
5630 /* skip blank lines which seperate policy entries */
5631 if (pbuf
[0] == '\n')
5634 /* if we found an index, save it */
5635 if (strncasecmp(pbuf
, INDEX_TAG
, index_len
) == 0) {
5636 buf
= pbuf
+ index_len
;
5638 if ((pindex
= parse_index(buf
, NULL
)) == -1) {
5639 /* bad index, we can't continue */
5641 "Invalid index in the file"));
5642 (void) fclose(remove_fp
);
5643 (void) fclose(policy_fp
);
5648 /* save this position in case it's the one */
5649 if (fgetpos(policy_fp
, &ipos
) != 0) {
5650 (void) fclose(remove_fp
);
5651 (void) fclose(policy_fp
);
5657 /* Does pbuf contain the remove policy? */
5658 if (strncasecmp(rbuf
, pbuf
, pbuf_len
) == 0) {
5659 /* we found the one to remove! */
5661 warnx(gettext("Didn't find a valid "
5662 "index for policy"));
5663 (void) fclose(remove_fp
);
5664 (void) fclose(policy_fp
);
5669 /* off it - back up to the last INDEX! */
5670 if (fsetpos(policy_fp
, &ipos
) != 0) {
5671 (void) fclose(remove_fp
);
5672 (void) fclose(policy_fp
);
5677 /* parse_one sets linecount = #lines to off */
5678 if (parse_one(policy_fp
, act_props
) == -1) {
5679 warnx(gettext("Invalid policy entry "
5681 (void) fclose(remove_fp
);
5682 (void) fclose(policy_fp
);
5687 nlines
= linecount
+ 2;
5691 * When we find a match, we want to pass the offset
5692 * of the line that is before it - the INDEX_TAG line.
5694 prev_prev_offset
= prev_offset
;
5696 /* Didn't find a match - look at the next remove policy */
5697 continue; /* while(); */
5700 (void) fclose(policy_fp
);
5702 if (delete_from_file(prev_prev_offset
, nlines
) != 0) {
5703 warnx(gettext("delete_from_file failure. "
5704 "Please flush all entries and re-configure :"));
5706 (void) fclose(remove_fp
);
5711 if (pfp_delete_rule(pindex
) != 0) {
5712 warnx(gettext("Deletion incomplete. Please flush"
5713 "all the entries and re-configure :"));
5715 (void) fclose(remove_fp
);
5720 /* reset the globals */
5723 /* free(NULL) also works. */
5724 free(interface_name
);
5725 interface_name
= NULL
;
5727 /* reopen for next pass, automagically starting over. */
5728 policy_fp
= fopen(POLICY_CONF_FILE
, "r");
5729 if (policy_fp
== NULL
) {
5730 warn(gettext("%s cannot be re-opened, can't continue"),
5732 (void) fclose(remove_fp
);
5737 } /* read next remove policy */
5739 if ((ret
= pfp_delete_rule(pindex
)) != 0) {
5740 warnx(gettext("Removal incomplete. Please flush "
5741 "all the entries and re-configure :"));
5747 /* nothing left to look for */
5748 (void) fclose(remove_fp
);
5755 * Constructs a tunnel interface ID extension. Returns the length
5756 * of the extension in 64-bit-words.
5759 attach_tunname(spd_if_t
*tunname
)
5761 if (tunname
== NULL
|| interface_name
== NULL
)
5764 tunname
->spd_if_exttype
= SPD_EXT_TUN_NAME
;
5766 * Use "-3" because there's 4 bytes in the message itself, and
5767 * we lose one because of the '\0' terminator.
5769 tunname
->spd_if_len
= SPD_8TO64(
5770 P2ROUNDUP(sizeof (*tunname
) + strlen(interface_name
) - 3, 8));
5771 (void) strlcpy((char *)tunname
->spd_if_name
, interface_name
, LIFNAMSIZ
);
5772 return (tunname
->spd_if_len
);