1 /* $NetBSD: policy.c,v 1.10 2008/12/05 06:02:20 tteras Exp $ */
3 /* $KAME: policy.c,v 1.46 2001/11/16 04:08:10 sakane Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/queue.h>
41 #include <netinet/in.h>
57 #include "localconf.h"
58 #include "isakmp_var.h"
65 static TAILQ_HEAD(_sptree
, secpolicy
) sptree
;
67 /* perform exact match against security policy table. */
70 struct policyindex
*spidx
;
74 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
75 if (!cmpspidxstrict(spidx
, &p
->spidx
))
83 * perform non-exact match against security policy table, only if this is
84 * transport mode SA negotiation. for example, 0.0.0.0/0 -> 0.0.0.0/0
85 * entry in policy.txt can be returned when we're negotiating transport
86 * mode SA. this is how the kernel works.
91 struct policyindex
*spidx
;
94 struct secpolicy
*found
= NULL
;
96 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
97 if (!cmpspidxstrict(spidx
, &p
->spidx
))
100 if (!found
&& !cmpspidxwild(spidx
, &p
->spidx
))
109 struct policyindex
*spidx
;
110 struct ph2handle
*iph2
;
115 plog(LLV_DEBUG
, LOCATION
, NULL
, "checking for transport mode\n");
117 if (spidx
->src
.ss_family
!= spidx
->dst
.ss_family
) {
118 plog(LLV_ERROR
, LOCATION
, NULL
,
119 "address family mismatch, src:%d dst:%d\n",
120 spidx
->src
.ss_family
,
121 spidx
->dst
.ss_family
);
124 switch (spidx
->src
.ss_family
) {
126 prefixlen
= sizeof(struct in_addr
) << 3;
130 prefixlen
= sizeof(struct in6_addr
) << 3;
134 plog(LLV_ERROR
, LOCATION
, NULL
,
135 "invalid family: %d\n", spidx
->src
.ss_family
);
139 /* is it transport mode SA negotiation? */
140 plog(LLV_DEBUG
, LOCATION
, NULL
, "src1: %s\n",
141 saddr2str(iph2
->src
));
142 plog(LLV_DEBUG
, LOCATION
, NULL
, "src2: %s\n",
143 saddr2str((struct sockaddr
*)&spidx
->src
));
145 if (cmpsaddr(iph2
->src
, (struct sockaddr
*) &spidx
->src
) ||
146 spidx
->prefs
!= prefixlen
)
149 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst1: %s\n",
150 saddr2str(iph2
->dst
));
151 plog(LLV_DEBUG
, LOCATION
, NULL
, "dst2: %s\n",
152 saddr2str((struct sockaddr
*)&spidx
->dst
));
154 if (cmpsaddr(iph2
->dst
, (struct sockaddr
*) &spidx
->dst
) ||
155 spidx
->prefd
!= prefixlen
)
158 plog(LLV_DEBUG
, LOCATION
, NULL
, "looks to be transport mode\n");
160 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
161 if (!cmpspidx_wild(spidx
, &p
->spidx
))
175 for (p
= TAILQ_FIRST(&sptree
); p
; p
= TAILQ_NEXT(p
, chain
)) {
184 * compare policyindex.
191 struct policyindex
*a
, *b
;
193 plog(LLV_DEBUG
, LOCATION
, NULL
, "sub:%p: %s\n", a
, spidx2str(a
));
194 plog(LLV_DEBUG
, LOCATION
, NULL
, "db :%p: %s\n", b
, spidx2str(b
));
196 /* XXX don't check direction now, but it's to be checked carefully. */
198 || a
->prefs
!= b
->prefs
199 || a
->prefd
!= b
->prefd
200 || a
->ul_proto
!= b
->ul_proto
)
203 if (cmpsaddr((struct sockaddr
*) &a
->src
,
204 (struct sockaddr
*) &b
->src
))
206 if (cmpsaddr((struct sockaddr
*) &a
->dst
,
207 (struct sockaddr
*) &b
->dst
))
211 if (a
->sec_ctx
.ctx_alg
!= b
->sec_ctx
.ctx_alg
212 || a
->sec_ctx
.ctx_doi
!= b
->sec_ctx
.ctx_doi
213 || !within_range(a
->sec_ctx
.ctx_str
, b
->sec_ctx
.ctx_str
))
220 * compare policyindex, with wildcard address/protocol match.
221 * a: subject b: db, can contain wildcard things.
227 struct policyindex
*a
, *b
;
229 struct sockaddr_storage sa1
, sa2
;
231 plog(LLV_DEBUG
, LOCATION
, NULL
, "sub:%p: %s\n", a
, spidx2str(a
));
232 plog(LLV_DEBUG
, LOCATION
, NULL
, "db: %p: %s\n", b
, spidx2str(b
));
234 if (!(b
->dir
== IPSEC_DIR_ANY
|| a
->dir
== b
->dir
))
237 if (!(b
->ul_proto
== IPSEC_ULPROTO_ANY
||
238 a
->ul_proto
== b
->ul_proto
))
241 if (a
->src
.ss_family
!= b
->src
.ss_family
)
243 if (a
->dst
.ss_family
!= b
->dst
.ss_family
)
247 /* compare src address */
248 if (sizeof(sa1
) < a
->src
.ss_len
|| sizeof(sa2
) < b
->src
.ss_len
) {
249 plog(LLV_ERROR
, LOCATION
, NULL
,
251 "src.ss_len:%d dst.ss_len:%d\n",
252 a
->src
.ss_len
, b
->src
.ss_len
);
256 mask_sockaddr((struct sockaddr
*)&sa1
, (struct sockaddr
*)&a
->src
,
258 mask_sockaddr((struct sockaddr
*)&sa2
, (struct sockaddr
*)&b
->src
,
260 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
261 a
, b
->prefs
, saddr2str((struct sockaddr
*)&sa1
));
262 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
263 b
, b
->prefs
, saddr2str((struct sockaddr
*)&sa2
));
264 if (cmpsaddr((struct sockaddr
*)&sa1
, (struct sockaddr
*)&sa2
))
268 /* compare dst address */
269 if (sizeof(sa1
) < a
->dst
.ss_len
|| sizeof(sa2
) < b
->dst
.ss_len
) {
270 plog(LLV_ERROR
, LOCATION
, NULL
, "unexpected error\n");
274 mask_sockaddr((struct sockaddr
*)&sa1
, (struct sockaddr
*)&a
->dst
,
276 mask_sockaddr((struct sockaddr
*)&sa2
, (struct sockaddr
*)&b
->dst
,
278 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
279 a
, b
->prefd
, saddr2str((struct sockaddr
*)&sa1
));
280 plog(LLV_DEBUG
, LOCATION
, NULL
, "%p masked with /%d: %s\n",
281 b
, b
->prefd
, saddr2str((struct sockaddr
*)&sa2
));
282 if (cmpsaddr((struct sockaddr
*)&sa1
, (struct sockaddr
*)&sa2
))
286 if (a
->sec_ctx
.ctx_alg
!= b
->sec_ctx
.ctx_alg
287 || a
->sec_ctx
.ctx_doi
!= b
->sec_ctx
.ctx_doi
288 || !within_range(a
->sec_ctx
.ctx_str
, b
->sec_ctx
.ctx_str
))
297 struct secpolicy
*new;
299 new = racoon_calloc(1, sizeof(*new));
308 struct secpolicy
*sp
;
310 struct ipsecrequest
*req
= NULL
, *next
;
312 for (req
= sp
->req
; req
; req
= next
) {
318 racoon_free(sp
->local
);
320 racoon_free(sp
->remote
);
326 delsp_bothdir(spidx0
)
327 struct policyindex
*spidx0
;
329 struct policyindex spidx
;
330 struct secpolicy
*sp
;
331 struct sockaddr_storage src
, dst
;
332 u_int8_t prefs
, prefd
;
334 memcpy(&spidx
, spidx0
, sizeof(spidx
));
336 case IPSEC_DIR_INBOUND
:
337 #ifdef HAVE_POLICY_FWD
345 case IPSEC_DIR_OUTBOUND
:
359 spidx
.dir
= IPSEC_DIR_INBOUND
;
367 #ifdef HAVE_POLICY_FWD
368 spidx
.dir
= IPSEC_DIR_FWD
;
381 spidx
.dir
= IPSEC_DIR_OUTBOUND
;
392 struct secpolicy
*new;
394 #ifdef HAVE_PFKEY_POLICY_PRIORITY
397 TAILQ_FOREACH(p
, &sptree
, chain
) {
398 if (new->spidx
.priority
< p
->spidx
.priority
) {
399 TAILQ_INSERT_BEFORE(p
, new, chain
);
405 TAILQ_INSERT_TAIL(&sptree
, new, chain
);
412 struct secpolicy
*sp
;
414 TAILQ_REMOVE(&sptree
, sp
, chain
);
420 struct secpolicy
*p
, *next
;
422 for (p
= TAILQ_FIRST(&sptree
); p
; p
= next
) {
423 next
= TAILQ_NEXT(p
, chain
);
435 struct ipsecrequest
*
438 struct ipsecrequest
*new;
440 new = racoon_calloc(1, sizeof(*new));
449 const struct policyindex
*spidx
;
451 /* addr/pref[port] addr/pref[port] ul dir act */
452 static char buf
[256];
456 blen
= sizeof(buf
) - 1;
459 a
= saddr2str((const struct sockaddr
*)&spidx
->src
);
460 for (b
= a
; *b
!= '\0'; b
++)
466 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefs
, b
);
467 if (i
< 0 || i
>= blen
)
472 a
= saddr2str((const struct sockaddr
*)&spidx
->dst
);
473 for (b
= a
; *b
!= '\0'; b
++)
479 i
= snprintf(p
, blen
, "%s/%d[%s ", a
, spidx
->prefd
, b
);
480 if (i
< 0 || i
>= blen
)
485 i
= snprintf(p
, blen
, "proto=%s dir=%s",
486 s_proto(spidx
->ul_proto
), s_direction(spidx
->dir
));
489 if (spidx
->sec_ctx
.ctx_strlen
) {
492 snprintf(p
, blen
, " sec_ctx:doi=%d,alg=%d,len=%d,str=%s",
493 spidx
->sec_ctx
.ctx_doi
, spidx
->sec_ctx
.ctx_alg
,
494 spidx
->sec_ctx
.ctx_strlen
, spidx
->sec_ctx
.ctx_str
);