]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/policy.c
1 /* $KAME: policy.c,v 1.46 2001/11/16 04:08:10 sakane Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/queue.h>
39 #include <netinet/in.h>
40 #ifdef HAVE_NETINET6_IPSEC
41 # include <netinet6/ipsec.h>
43 # include <netinet/ipsec.h>
59 #include "localconf.h"
60 #include "isakmp_var.h"
68 static TAILQ_HEAD(_sptree
, secpolicy
) sptree
;
70 /* perform exact match against security policy table. */
73 struct policyindex
*spidx
;
77 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
78 if (!cmpspidxstrict(spidx
, &p
->spidx
))
86 * perform non-exact match against security policy table, only if this is
87 * transport mode SA negotiation. for example, 0.0.0.0/0 -> 0.0.0.0/0
88 * entry in policy.txt can be returned when we're negotiating transport
89 * mode SA. this is how the kernel works.
94 struct policyindex
*spidx
;
95 phase2_handle_t
*iph2
;
98 int mismatched_outer_addr
= 0;
100 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
101 if (!cmpspidxwild(spidx
, &p
->spidx
)) {
102 if (spidx
->dir
!= IPSEC_DIR_ANY
) {
103 struct ipsecrequest
*isr
;
104 for (isr
= p
->req
; isr
!= NULL
; isr
= isr
->next
) {
105 if (isr
->saidx
.mode
!= IPSEC_MODE_TUNNEL
) {
106 plog(ASL_LEVEL_DEBUG
, "%s, skipping policy. dir %d, mode %d\n",
107 __FUNCTION__
, spidx
->dir
, isr
->saidx
.mode
);
111 // for tunnel mode: verify the outer ip addresses match the phase2's addresses
112 if (spidx
->dir
== IPSEC_DIR_INBOUND
) {
113 // TODO: look out for wildcards
114 if (!cmpsaddrwop(iph2
->dst
, &isr
->saidx
.src
) &&
115 !cmpsaddrwop(iph2
->src
, &isr
->saidx
.dst
)) {
116 plog(ASL_LEVEL_DEBUG
, "%s, inbound policy outer addresses matched Phase 2 addresses\n",
120 mismatched_outer_addr
= 1;
122 } else if (spidx
->dir
== IPSEC_DIR_OUTBOUND
) {
123 // TODO: look out for wildcards
124 if (!cmpsaddrwop(iph2
->src
, &isr
->saidx
.src
) &&
125 !cmpsaddrwop(iph2
->dst
, &isr
->saidx
.dst
)) {
126 plog(ASL_LEVEL_DEBUG
, "%s, outbound policy outer addresses matched Phase 2 addresses\n",
130 mismatched_outer_addr
= 1;
133 mismatched_outer_addr
= 1;
135 if (mismatched_outer_addr
) {
136 plog(ASL_LEVEL_DEBUG
, "%s, policy outer addresses matched Phase 2 addresses: dir %d\n",
137 __FUNCTION__
, spidx
->dir
);
138 plog(ASL_LEVEL_DEBUG
, "src1: %s\n",
139 saddr2str((struct sockaddr
*)iph2
->src
));
140 plog(ASL_LEVEL_DEBUG
, "src2: %s\n",
141 saddr2str((struct sockaddr
*)&isr
->saidx
.src
));
142 plog(ASL_LEVEL_DEBUG
, "dst1: %s\n",
143 saddr2str((struct sockaddr
*)iph2
->dst
));
144 plog(ASL_LEVEL_DEBUG
, "dst2: %s\n",
145 saddr2str((struct sockaddr
*)&isr
->saidx
.dst
));
149 if (!mismatched_outer_addr
) {
160 struct policyindex
*spidx
;
161 phase2_handle_t
*iph2
;
166 plog(ASL_LEVEL_DEBUG
, "checking for transport mode\n");
168 if (spidx
->src
.ss_family
!= spidx
->dst
.ss_family
) {
170 "address family mismatch, src:%d dst:%d\n",
171 spidx
->src
.ss_family
,
172 spidx
->dst
.ss_family
);
175 switch (spidx
->src
.ss_family
) {
177 prefixlen
= sizeof(struct in_addr
) << 3;
181 prefixlen
= sizeof(struct in6_addr
) << 3;
186 "invalid family: %d\n", spidx
->src
.ss_family
);
190 /* is it transport mode SA negotiation? */
191 plog(ASL_LEVEL_DEBUG
, "src1: %s\n",
192 saddr2str(iph2
->src
));
193 plog(ASL_LEVEL_DEBUG
, "src2: %s\n",
194 saddr2str(&spidx
->src
));
195 if (cmpsaddrwop(iph2
->src
, &spidx
->src
)
196 || spidx
->prefs
!= prefixlen
)
199 plog(ASL_LEVEL_DEBUG
, "dst1: %s\n",
200 saddr2str(iph2
->dst
));
201 plog(ASL_LEVEL_DEBUG
, "dst2: %s\n",
202 saddr2str(&spidx
->dst
));
203 if (cmpsaddrwop(iph2
->dst
, &spidx
->dst
)
204 || spidx
->prefd
!= prefixlen
)
207 plog(ASL_LEVEL_DEBUG
, "looks to be transport mode\n");
209 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
210 if (!cmpspidx_wild(spidx
, &p
->spidx
))
224 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
233 * compare policyindex.
240 struct policyindex
*a
, *b
;
243 /* XXX don't check direction now, but it's to be checked carefully. */
245 || a
->prefs
!= b
->prefs
246 || a
->prefd
!= b
->prefd
247 || a
->ul_proto
!= b
->ul_proto
)
250 if (cmpsaddrstrict(&a
->src
, &b
->src
))
252 if (cmpsaddrstrict(&a
->dst
, &b
->dst
))
259 * compare policyindex, with wildcard address/protocol match.
260 * a: subject b: db, can contain wildcard things.
266 struct policyindex
*a
, *b
;
268 struct sockaddr_storage sa1
, sa2
;
270 if (!(b
->dir
== IPSEC_DIR_ANY
|| a
->dir
== b
->dir
))
273 if (!(a
->ul_proto
== IPSEC_ULPROTO_ANY
||
274 b
->ul_proto
== IPSEC_ULPROTO_ANY
||
275 a
->ul_proto
== b
->ul_proto
))
278 if (a
->src
.ss_family
!= b
->src
.ss_family
)
280 if (a
->dst
.ss_family
!= b
->dst
.ss_family
)
283 /* compare src address */
284 if (sizeof(sa1
) < a
->src
.ss_len
|| sizeof(sa2
) < b
->src
.ss_len
) {
287 "src.ss_len:%d dst.ss_len:%d\n",
288 a
->src
.ss_len
, b
->src
.ss_len
);
291 mask_sockaddr(&sa1
, &a
->src
, b
->prefs
);
292 mask_sockaddr(&sa2
, &b
->src
, b
->prefs
);
293 plog(ASL_LEVEL_DEBUG
, "%p masked with /%d: %s\n",
294 a
, b
->prefs
, saddr2str((struct sockaddr
*)&sa1
));
295 plog(ASL_LEVEL_DEBUG
, "%p masked with /%d: %s\n",
296 b
, b
->prefs
, saddr2str((struct sockaddr
*)&sa2
));
297 if (cmpsaddrwild(&sa1
, &sa2
))
300 /* compare dst address */
301 if (sizeof(sa1
) < a
->dst
.ss_len
|| sizeof(sa2
) < b
->dst
.ss_len
) {
302 plog(ASL_LEVEL_ERR
, "unexpected error\n");
305 mask_sockaddr(&sa1
, &a
->dst
, b
->prefd
);
306 mask_sockaddr(&sa2
, &b
->dst
, b
->prefd
);
307 plog(ASL_LEVEL_DEBUG
, "%p masked with /%d: %s\n",
308 a
, b
->prefd
, saddr2str((struct sockaddr
*)&sa1
));
309 plog(ASL_LEVEL_DEBUG
, "%p masked with /%d: %s\n",
310 b
, b
->prefd
, saddr2str((struct sockaddr
*)&sa2
));
311 if (cmpsaddrwild(&sa1
, &sa2
))
320 struct secpolicy
*new;
322 new = racoon_calloc(1, sizeof(*new));
331 struct secpolicy
*sp
;
333 struct ipsecrequest
*req
= NULL
, *next
;
335 for (req
= sp
->req
; req
; req
= next
) {
344 delsp_bothdir(spidx0
)
345 struct policyindex
*spidx0
;
347 struct policyindex spidx
;
348 struct secpolicy
*sp
;
349 struct sockaddr_storage src
, dst
;
350 u_int8_t prefs
, prefd
;
352 memcpy(&spidx
, spidx0
, sizeof(spidx
));
354 case IPSEC_DIR_INBOUND
:
355 #ifdef HAVE_POLICY_FWD
363 case IPSEC_DIR_OUTBOUND
:
377 spidx
.dir
= IPSEC_DIR_INBOUND
;
385 #ifdef HAVE_POLICY_FWD
386 spidx
.dir
= IPSEC_DIR_FWD
;
399 spidx
.dir
= IPSEC_DIR_OUTBOUND
;
410 struct secpolicy
*new;
412 #ifdef HAVE_PFKEY_POLICY_PRIORITY
415 TAILQ_FOREACH(p
, &sptree
, chain
) {
416 if (new->spidx
.priority
< p
->spidx
.priority
) {
417 TAILQ_INSERT_BEFORE(p
, new, chain
);
423 TAILQ_INSERT_HEAD(&sptree
, new, chain
);
431 struct secpolicy
*sp
;
433 TAILQ_REMOVE(&sptree
, sp
, chain
);
440 struct secpolicy
*p
, *next
;
442 for (p
= TAILQ_FIRST(&sptree
); p
; p
= next
) {
443 next
= TAILQ_NEXT(p
, chain
);
450 policies_installed(void)
452 if (TAILQ_EMPTY(&sptree
))
464 struct ipsecrequest
*
467 struct ipsecrequest
*new;
469 new = racoon_calloc(1, sizeof(*new));
478 const struct policyindex
*spidx
;
480 /* addr/pref[port] addr/pref[port] ul dir act */
481 static char buf
[256];
485 blen
= sizeof(buf
) - 1;
488 a
= saddr2str((const struct sockaddr
*)&spidx
->src
);
489 for (b
= a
; *b
!= '\0'; b
++)
495 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefs
, b
);
496 if (i
< 0 || i
>= blen
)
501 a
= saddr2str((const struct sockaddr
*)&spidx
->dst
);
502 for (b
= a
; *b
!= '\0'; b
++)
508 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefd
, b
);
509 if (i
< 0 || i
>= blen
)
514 snprintf(p
, blen
, "proto=%s dir=%s",
515 s_proto(spidx
->ul_proto
), s_direction(spidx
->dir
));