]>
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
;
98 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
99 if (!cmpspidxwild(spidx
, &p
->spidx
))
108 struct policyindex
*spidx
;
109 struct ph2handle
*iph2
;
114 plog(LLV_DEBUG
, LOCATION
, NULL
, "checking for transport mode\n");
116 if (spidx
->src
.ss_family
!= spidx
->dst
.ss_family
) {
117 plog(LLV_ERROR
, LOCATION
, NULL
,
118 "address family mismatch, src:%d dst:%d\n",
119 spidx
->src
.ss_family
,
120 spidx
->dst
.ss_family
);
123 switch (spidx
->src
.ss_family
) {
125 prefixlen
= sizeof(struct in_addr
) << 3;
129 prefixlen
= sizeof(struct in6_addr
) << 3;
133 plog(LLV_ERROR
, LOCATION
, NULL
,
134 "invalid family: %d\n", spidx
->src
.ss_family
);
138 /* is it transport mode SA negotiation? */
139 plog(LLV_DEBUG
, LOCATION
, NULL
, "src1: %s\n",
140 saddr2str(iph2
->src
));
141 plog(LLV_DEBUG
, LOCATION
, NULL
, "src2: %s\n",
142 saddr2str((struct sockaddr
*)&spidx
->src
));
143 if (cmpsaddrwop(iph2
->src
, (struct sockaddr
*)&spidx
->src
)
144 || spidx
->prefs
!= prefixlen
)
147 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst1: %s\n",
148 saddr2str(iph2
->dst
));
149 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst2: %s\n",
150 saddr2str((struct sockaddr
*)&spidx
->dst
));
151 if (cmpsaddrwop(iph2
->dst
, (struct sockaddr
*)&spidx
->dst
)
152 || spidx
->prefd
!= prefixlen
)
155 plog(LLV_DEBUG
, LOCATION
, NULL
, "looks to be transport mode\n");
157 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
158 if (!cmpspidx_wild(spidx
, &p
->spidx
))
172 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
181 * compare policyindex.
188 struct policyindex
*a
, *b
;
190 plog(LLV_DEBUG
, LOCATION
, NULL
, "sub:%p: %s\n", a
, spidx2str(a
));
191 plog(LLV_DEBUG
, LOCATION
, NULL
, "db :%p: %s\n", b
, spidx2str(b
));
193 /* XXX don't check direction now, but it's to be checked carefully. */
195 || a
->prefs
!= b
->prefs
196 || a
->prefd
!= b
->prefd
197 || a
->ul_proto
!= b
->ul_proto
)
200 if (cmpsaddrstrict((struct sockaddr
*)&a
->src
,
201 (struct sockaddr
*)&b
->src
))
203 if (cmpsaddrstrict((struct sockaddr
*)&a
->dst
,
204 (struct sockaddr
*)&b
->dst
))
211 * compare policyindex, with wildcard address/protocol match.
212 * a: subject b: db, can contain wildcard things.
218 struct policyindex
*a
, *b
;
220 struct sockaddr_storage sa1
, sa2
;
222 plog(LLV_DEBUG
, LOCATION
, NULL
, "sub:%p: %s\n", a
, spidx2str(a
));
223 plog(LLV_DEBUG
, LOCATION
, NULL
, "db: %p: %s\n", b
, spidx2str(b
));
225 if (!(b
->dir
== IPSEC_DIR_ANY
|| a
->dir
== b
->dir
))
228 if (!(a
->ul_proto
== IPSEC_ULPROTO_ANY
||
229 b
->ul_proto
== IPSEC_ULPROTO_ANY
||
230 a
->ul_proto
== b
->ul_proto
))
233 if (a
->src
.ss_family
!= b
->src
.ss_family
)
235 if (a
->dst
.ss_family
!= b
->dst
.ss_family
)
239 /* compare src address */
240 if (sizeof(sa1
) < a
->src
.ss_len
|| sizeof(sa2
) < b
->src
.ss_len
) {
241 plog(LLV_ERROR
, LOCATION
, NULL
,
243 "src.ss_len:%d dst.ss_len:%d\n",
244 a
->src
.ss_len
, b
->src
.ss_len
);
248 mask_sockaddr((struct sockaddr
*)&sa1
, (struct sockaddr
*)&a
->src
,
250 mask_sockaddr((struct sockaddr
*)&sa2
, (struct sockaddr
*)&b
->src
,
252 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
253 a
, b
->prefs
, saddr2str((struct sockaddr
*)&sa1
));
254 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
255 b
, b
->prefs
, saddr2str((struct sockaddr
*)&sa2
));
256 if (cmpsaddrwild((struct sockaddr
*)&sa1
, (struct sockaddr
*)&sa2
))
260 /* compare dst address */
261 if (sizeof(sa1
) < a
->dst
.ss_len
|| sizeof(sa2
) < b
->dst
.ss_len
) {
262 plog(LLV_ERROR
, LOCATION
, NULL
, "unexpected error\n");
266 mask_sockaddr((struct sockaddr
*)&sa1
, (struct sockaddr
*)&a
->dst
,
268 mask_sockaddr((struct sockaddr
*)&sa2
, (struct sockaddr
*)&b
->dst
,
270 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
271 a
, b
->prefd
, saddr2str((struct sockaddr
*)&sa1
));
272 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
273 b
, b
->prefd
, saddr2str((struct sockaddr
*)&sa2
));
274 if (cmpsaddrwild((struct sockaddr
*)&sa1
, (struct sockaddr
*)&sa2
))
283 struct secpolicy
*new;
285 new = racoon_calloc(1, sizeof(*new));
294 struct secpolicy
*sp
;
296 struct ipsecrequest
*req
= NULL
, *next
;
298 for (req
= sp
->req
; req
; req
= next
) {
307 delsp_bothdir(spidx0
)
308 struct policyindex
*spidx0
;
310 struct policyindex spidx
;
311 struct secpolicy
*sp
;
312 struct sockaddr_storage src
, dst
;
313 u_int8_t prefs
, prefd
;
315 memcpy(&spidx
, spidx0
, sizeof(spidx
));
317 case IPSEC_DIR_INBOUND
:
318 #ifdef HAVE_POLICY_FWD
326 case IPSEC_DIR_OUTBOUND
:
340 spidx
.dir
= IPSEC_DIR_INBOUND
;
348 #ifdef HAVE_POLICY_FWD
349 spidx
.dir
= IPSEC_DIR_FWD
;
362 spidx
.dir
= IPSEC_DIR_OUTBOUND
;
373 struct secpolicy
*new;
375 #ifdef HAVE_PFKEY_POLICY_PRIORITY
378 TAILQ_FOREACH(p
, &sptree
, chain
) {
379 if (new->spidx
.priority
< p
->spidx
.priority
) {
380 TAILQ_INSERT_BEFORE(p
, new, chain
);
386 TAILQ_INSERT_HEAD(&sptree
, new, chain
);
394 struct secpolicy
*sp
;
396 TAILQ_REMOVE(&sptree
, sp
, chain
);
403 struct secpolicy
*p
, *next
;
405 for (p
= TAILQ_FIRST(&sptree
); p
; p
= next
) {
406 next
= TAILQ_NEXT(p
, chain
);
413 policies_installed(void)
415 if (TAILQ_EMPTY(&sptree
))
427 struct ipsecrequest
*
430 struct ipsecrequest
*new;
432 new = racoon_calloc(1, sizeof(*new));
441 const struct policyindex
*spidx
;
443 /* addr/pref[port] addr/pref[port] ul dir act */
444 static char buf
[256];
448 blen
= sizeof(buf
) - 1;
451 a
= saddr2str((const struct sockaddr
*)&spidx
->src
);
452 for (b
= a
; *b
!= '\0'; b
++)
458 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefs
, b
);
459 if (i
< 0 || i
>= blen
)
464 a
= saddr2str((const struct sockaddr
*)&spidx
->dst
);
465 for (b
= a
; *b
!= '\0'; b
++)
471 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefd
, b
);
472 if (i
< 0 || i
>= blen
)
477 snprintf(p
, blen
, "proto=%s dir=%s",
478 s_proto(spidx
->ul_proto
), s_direction(spidx
->dir
));