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"
67 static TAILQ_HEAD(_sptree, secpolicy) sptree;
69 /* perform exact match against security policy table. */
72 struct policyindex *spidx;
76 for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
77 if (!cmpspidxstrict(spidx, &p->spidx))
85 * perform non-exact match against security policy table, only if this is
86 * transport mode SA negotiation. for example, 0.0.0.0/0 -> 0.0.0.0/0
87 * entry in policy.txt can be returned when we're negotiating transport
88 * mode SA. this is how the kernel works.
93 struct policyindex *spidx;
97 for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
98 if (!cmpspidxwild(spidx, &p->spidx))
107 struct policyindex *spidx;
108 struct ph2handle *iph2;
113 plog(LLV_DEBUG, LOCATION, NULL, "checking for transport mode\n");
115 if (spidx->src.ss_family != spidx->dst.ss_family) {
116 plog(LLV_ERROR, LOCATION, NULL,
117 "address family mismatch, src:%d dst:%d\n",
118 spidx->src.ss_family,
119 spidx->dst.ss_family);
122 switch (spidx->src.ss_family) {
124 prefixlen = sizeof(struct in_addr) << 3;
128 prefixlen = sizeof(struct in6_addr) << 3;
132 plog(LLV_ERROR, LOCATION, NULL,
133 "invalid family: %d\n", spidx->src.ss_family);
137 /* is it transport mode SA negotiation? */
138 plog(LLV_DEBUG, LOCATION, NULL, "src1: %s\n",
139 saddr2str(iph2->src));
140 plog(LLV_DEBUG, LOCATION, NULL, "src2: %s\n",
141 saddr2str((struct sockaddr *)&spidx->src));
142 if (cmpsaddrwop(iph2->src, (struct sockaddr *)&spidx->src)
143 || spidx->prefs != prefixlen)
146 plog(LLV_DEBUG, LOCATION, NULL, "dst1: %s\n",
147 saddr2str(iph2->dst));
148 plog(LLV_DEBUG, LOCATION, NULL, "dst2: %s\n",
149 saddr2str((struct sockaddr *)&spidx->dst));
150 if (cmpsaddrwop(iph2->dst, (struct sockaddr *)&spidx->dst)
151 || spidx->prefd != prefixlen)
154 plog(LLV_DEBUG, LOCATION, NULL, "looks to be transport mode\n");
156 for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
157 if (!cmpspidx_wild(spidx, &p->spidx))
171 for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
180 * compare policyindex.
187 struct policyindex *a, *b;
189 plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
190 plog(LLV_DEBUG, LOCATION, NULL, "db :%p: %s\n", b, spidx2str(b));
192 /* XXX don't check direction now, but it's to be checked carefully. */
194 || a->prefs != b->prefs
195 || a->prefd != b->prefd
196 || a->ul_proto != b->ul_proto)
199 if (cmpsaddrstrict((struct sockaddr *)&a->src,
200 (struct sockaddr *)&b->src))
202 if (cmpsaddrstrict((struct sockaddr *)&a->dst,
203 (struct sockaddr *)&b->dst))
210 * compare policyindex, with wildcard address/protocol match.
211 * a: subject b: db, can contain wildcard things.
217 struct policyindex *a, *b;
219 struct sockaddr_storage sa1, sa2;
221 plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
222 plog(LLV_DEBUG, LOCATION, NULL, "db: %p: %s\n", b, spidx2str(b));
224 if (!(b->dir == IPSEC_DIR_ANY || a->dir == b->dir))
227 if (!(a->ul_proto == IPSEC_ULPROTO_ANY ||
228 b->ul_proto == IPSEC_ULPROTO_ANY ||
229 a->ul_proto == b->ul_proto))
232 if (a->src.ss_family != b->src.ss_family)
234 if (a->dst.ss_family != b->dst.ss_family)
238 /* compare src address */
239 if (sizeof(sa1) < a->src.ss_len || sizeof(sa2) < b->src.ss_len) {
240 plog(LLV_ERROR, LOCATION, NULL,
242 "src.ss_len:%d dst.ss_len:%d\n",
243 a->src.ss_len, b->src.ss_len);
247 mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->src,
249 mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->src,
251 plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
252 a, b->prefs, saddr2str((struct sockaddr *)&sa1));
253 plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
254 b, b->prefs, saddr2str((struct sockaddr *)&sa2));
255 if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
259 /* compare dst address */
260 if (sizeof(sa1) < a->dst.ss_len || sizeof(sa2) < b->dst.ss_len) {
261 plog(LLV_ERROR, LOCATION, NULL, "unexpected error\n");
265 mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->dst,
267 mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->dst,
269 plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
270 a, b->prefd, saddr2str((struct sockaddr *)&sa1));
271 plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
272 b, b->prefd, saddr2str((struct sockaddr *)&sa2));
273 if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
282 struct secpolicy *new;
284 new = racoon_calloc(1, sizeof(*new));
293 struct secpolicy *sp;
295 struct ipsecrequest *req = NULL, *next;
297 for (req = sp->req; req; req = next) {
306 delsp_bothdir(spidx0)
307 struct policyindex *spidx0;
309 struct policyindex spidx;
310 struct secpolicy *sp;
311 struct sockaddr_storage src, dst;
312 u_int8_t prefs, prefd;
314 memcpy(&spidx, spidx0, sizeof(spidx));
316 case IPSEC_DIR_INBOUND:
317 #ifdef HAVE_POLICY_FWD
325 case IPSEC_DIR_OUTBOUND:
339 spidx.dir = IPSEC_DIR_INBOUND;
347 #ifdef HAVE_POLICY_FWD
348 spidx.dir = IPSEC_DIR_FWD;
361 spidx.dir = IPSEC_DIR_OUTBOUND;
372 struct secpolicy *new;
376 TAILQ_FOREACH(p, &sptree, chain) {
377 if (new->spidx.priority < p->spidx.priority) {
378 TAILQ_INSERT_BEFORE(p, new, chain);
383 TAILQ_INSERT_TAIL(&sptree, new, chain);
390 struct secpolicy *sp;
392 TAILQ_REMOVE(&sptree, sp, chain);
398 struct secpolicy *p, *next;
400 for (p = TAILQ_FIRST(&sptree); p; p = next) {
401 next = TAILQ_NEXT(p, chain);
413 struct ipsecrequest *
416 struct ipsecrequest *new;
418 new = racoon_calloc(1, sizeof(*new));
427 const struct policyindex *spidx;
429 /* addr/pref[port] addr/pref[port] ul dir act */
430 static char buf[256];
434 blen = sizeof(buf) - 1;
437 a = saddr2str((const struct sockaddr *)&spidx->src);
438 for (b = a; *b != '\0'; b++)
444 i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefs, b);
445 if (i < 0 || i >= blen)
450 a = saddr2str((const struct sockaddr *)&spidx->dst);
451 for (b = a; *b != '\0'; b++)
457 i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefd, b);
458 if (i < 0 || i >= blen)
463 snprintf(p, blen, "proto=%s dir=%s",
464 s_proto(spidx->ul_proto), s_direction(spidx->dir));