]>
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 struct ph2handle
*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(LLV_DEBUG2
, LOCATION
, NULL
, "%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(LLV_DEBUG2
, LOCATION
, NULL
, "%s, inbound policy outer addresses matched phase2's 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(LLV_DEBUG2
, LOCATION
, NULL
, "%s, outbound policy outer addresses matched phase2's addresses\n",
130 mismatched_outer_addr
= 1;
133 mismatched_outer_addr
= 1;
135 if (mismatched_outer_addr
) {
136 plog(LLV_DEBUG2
, LOCATION
, NULL
, "%s, policy outer addresses matched phase2's addresses: dir %d\n",
137 __FUNCTION__
, spidx
->dir
);
138 plog(LLV_DEBUG
, LOCATION
, NULL
, "src1: %s\n",
139 saddr2str((struct sockaddr
*)iph2
->src
));
140 plog(LLV_DEBUG
, LOCATION
, NULL
, "src2: %s\n",
141 saddr2str((struct sockaddr
*)&isr
->saidx
.src
));
142 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst1: %s\n",
143 saddr2str((struct sockaddr
*)iph2
->dst
));
144 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst2: %s\n",
145 saddr2str((struct sockaddr
*)&isr
->saidx
.dst
));
149 if (!mismatched_outer_addr
) {
160 struct policyindex
*spidx
;
161 struct ph2handle
*iph2
;
166 plog(LLV_DEBUG
, LOCATION
, NULL
, "checking for transport mode\n");
168 if (spidx
->src
.ss_family
!= spidx
->dst
.ss_family
) {
169 plog(LLV_ERROR
, LOCATION
, NULL
,
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;
185 plog(LLV_ERROR
, LOCATION
, NULL
,
186 "invalid family: %d\n", spidx
->src
.ss_family
);
190 /* is it transport mode SA negotiation? */
191 plog(LLV_DEBUG
, LOCATION
, NULL
, "src1: %s\n",
192 saddr2str(iph2
->src
));
193 plog(LLV_DEBUG
, LOCATION
, NULL
, "src2: %s\n",
194 saddr2str(&spidx
->src
));
195 if (cmpsaddrwop(iph2
->src
, &spidx
->src
)
196 || spidx
->prefs
!= prefixlen
)
199 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst1: %s\n",
200 saddr2str(iph2
->dst
));
201 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst2: %s\n",
202 saddr2str(&spidx
->dst
));
203 if (cmpsaddrwop(iph2
->dst
, &spidx
->dst
)
204 || spidx
->prefd
!= prefixlen
)
207 plog(LLV_DEBUG
, LOCATION
, NULL
, "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
;
242 //plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
243 //plog(LLV_DEBUG, LOCATION, NULL, "db :%p: %s\n", b, spidx2str(b));
245 /* XXX don't check direction now, but it's to be checked carefully. */
247 || a
->prefs
!= b
->prefs
248 || a
->prefd
!= b
->prefd
249 || a
->ul_proto
!= b
->ul_proto
)
252 if (cmpsaddrstrict(&a
->src
, &b
->src
))
254 if (cmpsaddrstrict(&a
->dst
, &b
->dst
))
261 * compare policyindex, with wildcard address/protocol match.
262 * a: subject b: db, can contain wildcard things.
268 struct policyindex
*a
, *b
;
270 struct sockaddr_storage sa1
, sa2
;
272 //plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
273 //plog(LLV_DEBUG, LOCATION, NULL, "db: %p: %s\n", b, spidx2str(b));
275 if (!(b
->dir
== IPSEC_DIR_ANY
|| a
->dir
== b
->dir
))
278 if (!(a
->ul_proto
== IPSEC_ULPROTO_ANY
||
279 b
->ul_proto
== IPSEC_ULPROTO_ANY
||
280 a
->ul_proto
== b
->ul_proto
))
283 if (a
->src
.ss_family
!= b
->src
.ss_family
)
285 if (a
->dst
.ss_family
!= b
->dst
.ss_family
)
288 /* compare src address */
289 if (sizeof(sa1
) < a
->src
.ss_len
|| sizeof(sa2
) < b
->src
.ss_len
) {
290 plog(LLV_ERROR
, LOCATION
, NULL
,
292 "src.ss_len:%d dst.ss_len:%d\n",
293 a
->src
.ss_len
, b
->src
.ss_len
);
296 mask_sockaddr(&sa1
, &a
->src
, b
->prefs
);
297 mask_sockaddr(&sa2
, &b
->src
, b
->prefs
);
298 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
299 a
, b
->prefs
, saddr2str((struct sockaddr
*)&sa1
));
300 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
301 b
, b
->prefs
, saddr2str((struct sockaddr
*)&sa2
));
302 if (cmpsaddrwild(&sa1
, &sa2
))
305 /* compare dst address */
306 if (sizeof(sa1
) < a
->dst
.ss_len
|| sizeof(sa2
) < b
->dst
.ss_len
) {
307 plog(LLV_ERROR
, LOCATION
, NULL
, "unexpected error\n");
310 mask_sockaddr(&sa1
, &a
->dst
, b
->prefd
);
311 mask_sockaddr(&sa2
, &b
->dst
, b
->prefd
);
312 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
313 a
, b
->prefd
, saddr2str((struct sockaddr
*)&sa1
));
314 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
315 b
, b
->prefd
, saddr2str((struct sockaddr
*)&sa2
));
316 if (cmpsaddrwild(&sa1
, &sa2
))
325 struct secpolicy
*new;
327 new = racoon_calloc(1, sizeof(*new));
336 struct secpolicy
*sp
;
338 struct ipsecrequest
*req
= NULL
, *next
;
340 for (req
= sp
->req
; req
; req
= next
) {
349 delsp_bothdir(spidx0
)
350 struct policyindex
*spidx0
;
352 struct policyindex spidx
;
353 struct secpolicy
*sp
;
354 struct sockaddr_storage src
, dst
;
355 u_int8_t prefs
, prefd
;
357 memcpy(&spidx
, spidx0
, sizeof(spidx
));
359 case IPSEC_DIR_INBOUND
:
360 #ifdef HAVE_POLICY_FWD
368 case IPSEC_DIR_OUTBOUND
:
382 spidx
.dir
= IPSEC_DIR_INBOUND
;
390 #ifdef HAVE_POLICY_FWD
391 spidx
.dir
= IPSEC_DIR_FWD
;
404 spidx
.dir
= IPSEC_DIR_OUTBOUND
;
415 struct secpolicy
*new;
417 #ifdef HAVE_PFKEY_POLICY_PRIORITY
420 TAILQ_FOREACH(p
, &sptree
, chain
) {
421 if (new->spidx
.priority
< p
->spidx
.priority
) {
422 TAILQ_INSERT_BEFORE(p
, new, chain
);
428 TAILQ_INSERT_HEAD(&sptree
, new, chain
);
436 struct secpolicy
*sp
;
438 TAILQ_REMOVE(&sptree
, sp
, chain
);
445 struct secpolicy
*p
, *next
;
447 for (p
= TAILQ_FIRST(&sptree
); p
; p
= next
) {
448 next
= TAILQ_NEXT(p
, chain
);
455 policies_installed(void)
457 if (TAILQ_EMPTY(&sptree
))
469 struct ipsecrequest
*
472 struct ipsecrequest
*new;
474 new = racoon_calloc(1, sizeof(*new));
483 const struct policyindex
*spidx
;
485 /* addr/pref[port] addr/pref[port] ul dir act */
486 static char buf
[256];
490 blen
= sizeof(buf
) - 1;
493 a
= saddr2str((const struct sockaddr
*)&spidx
->src
);
494 for (b
= a
; *b
!= '\0'; b
++)
500 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefs
, b
);
501 if (i
< 0 || i
>= blen
)
506 a
= saddr2str((const struct sockaddr
*)&spidx
->dst
);
507 for (b
= a
; *b
!= '\0'; b
++)
513 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefd
, b
);
514 if (i
< 0 || i
>= blen
)
519 snprintf(p
, blen
, "proto=%s dir=%s",
520 s_proto(spidx
->ul_proto
), s_direction(spidx
->dir
));