Annotation of embedaddon/ipsec-tools/src/racoon/policy.c, revision 1.1

1.1     ! misho       1: /*     $NetBSD: policy.c,v 1.12 2011/03/14 17:18:13 tteras Exp $       */
        !             2: 
        !             3: /*     $KAME: policy.c,v 1.46 2001/11/16 04:08:10 sakane Exp $ */
        !             4: 
        !             5: /*
        !             6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
        !             7:  * All rights reserved.
        !             8:  * 
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            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.
        !            20:  * 
        !            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
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33: 
        !            34: #include "config.h"
        !            35: 
        !            36: #include <sys/param.h>
        !            37: #include <sys/types.h>
        !            38: #include <sys/socket.h>
        !            39: #include <sys/queue.h>
        !            40: 
        !            41: #include <netinet/in.h>
        !            42: #include PATH_IPSEC_H
        !            43: 
        !            44: #include <stdlib.h>
        !            45: #include <stdio.h>
        !            46: #include <string.h>
        !            47: #include <errno.h>
        !            48: 
        !            49: #include "var.h"
        !            50: #include "misc.h"
        !            51: #include "vmbuf.h"
        !            52: #include "plog.h"
        !            53: #include "sockmisc.h"
        !            54: #include "debug.h"
        !            55: 
        !            56: #include "policy.h"
        !            57: #include "localconf.h"
        !            58: #include "isakmp_var.h"
        !            59: #include "isakmp.h"
        !            60: #include "oakley.h"
        !            61: #include "handler.h"
        !            62: #include "strnames.h"
        !            63: #include "gcmalloc.h"
        !            64: 
        !            65: static TAILQ_HEAD(_sptree, secpolicy) sptree;
        !            66: 
        !            67: /* perform exact match against security policy table. */
        !            68: struct secpolicy *
        !            69: getsp(spidx)
        !            70:        struct policyindex *spidx;
        !            71: {
        !            72:        struct secpolicy *p;
        !            73: 
        !            74:        for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
        !            75:                if (!cmpspidxstrict(spidx, &p->spidx))
        !            76:                        return p;
        !            77:        }
        !            78: 
        !            79:        return NULL;
        !            80: }
        !            81: 
        !            82: /*
        !            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.
        !            87:  */
        !            88: #if 1
        !            89: struct secpolicy *
        !            90: getsp_r(spidx)
        !            91:        struct policyindex *spidx;
        !            92: {
        !            93:        struct secpolicy *p;
        !            94:        struct secpolicy *found = NULL;
        !            95: 
        !            96:        for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
        !            97:                if (!cmpspidxstrict(spidx, &p->spidx))
        !            98:                        return p;
        !            99: 
        !           100:                if (!found && !cmpspidxwild(spidx, &p->spidx))
        !           101:                        found = p;
        !           102:        }
        !           103: 
        !           104:        return found;
        !           105: }
        !           106: #else
        !           107: struct secpolicy *
        !           108: getsp_r(spidx, iph2)
        !           109:        struct policyindex *spidx;
        !           110:        struct ph2handle *iph2;
        !           111: {
        !           112:        struct secpolicy *p;
        !           113:        u_int8_t prefixlen;
        !           114: 
        !           115:        plog(LLV_DEBUG, LOCATION, NULL, "checking for transport mode\n");
        !           116: 
        !           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);
        !           122:                return NULL;
        !           123:        }
        !           124:        switch (spidx->src.ss_family) {
        !           125:        case AF_INET:
        !           126:                prefixlen = sizeof(struct in_addr) << 3;
        !           127:                break;
        !           128: #ifdef INET6
        !           129:        case AF_INET6:
        !           130:                prefixlen = sizeof(struct in6_addr) << 3;
        !           131:                break;
        !           132: #endif
        !           133:        default:
        !           134:                plog(LLV_ERROR, LOCATION, NULL,
        !           135:                        "invalid family: %d\n", spidx->src.ss_family);
        !           136:                return NULL;
        !           137:        }
        !           138: 
        !           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));
        !           144: 
        !           145:        if (cmpsaddr(iph2->src, (struct sockaddr *) &spidx->src) != CMPSADDR_MATCH ||
        !           146:            spidx->prefs != prefixlen)
        !           147:                return NULL;
        !           148: 
        !           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));
        !           153: 
        !           154:        if (cmpsaddr(iph2->dst, (struct sockaddr *) &spidx->dst) != CMPSADDR_MATCH ||
        !           155:            spidx->prefd != prefixlen)
        !           156:                return NULL;
        !           157: 
        !           158:        plog(LLV_DEBUG, LOCATION, NULL, "looks to be transport mode\n");
        !           159: 
        !           160:        for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
        !           161:                if (!cmpspidx_wild(spidx, &p->spidx))
        !           162:                        return p;
        !           163:        }
        !           164: 
        !           165:        return NULL;
        !           166: }
        !           167: #endif
        !           168: 
        !           169: struct secpolicy *
        !           170: getspbyspid(spid)
        !           171:        u_int32_t spid;
        !           172: {
        !           173:        struct secpolicy *p;
        !           174: 
        !           175:        for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
        !           176:                if (p->id == spid)
        !           177:                        return p;
        !           178:        }
        !           179: 
        !           180:        return NULL;
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * compare policyindex.
        !           185:  * a: subject b: db
        !           186:  * OUT:        0:      equal
        !           187:  *     1:      not equal
        !           188:  */
        !           189: int
        !           190: cmpspidxstrict(a, b)
        !           191:        struct policyindex *a, *b;
        !           192: {
        !           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));
        !           195: 
        !           196:        /* XXX don't check direction now, but it's to be checked carefully. */
        !           197:        if (a->dir != b->dir
        !           198:         || a->prefs != b->prefs
        !           199:         || a->prefd != b->prefd
        !           200:         || a->ul_proto != b->ul_proto)
        !           201:                return 1;
        !           202: 
        !           203:        if (cmpsaddr((struct sockaddr *) &a->src,
        !           204:                     (struct sockaddr *) &b->src) != CMPSADDR_MATCH)
        !           205:                return 1;
        !           206:        if (cmpsaddr((struct sockaddr *) &a->dst,
        !           207:                     (struct sockaddr *) &b->dst) != CMPSADDR_MATCH)
        !           208:                return 1;
        !           209: 
        !           210: #ifdef HAVE_SECCTX
        !           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))
        !           214:                return 1;
        !           215: #endif
        !           216:        return 0;
        !           217: }
        !           218: 
        !           219: /*
        !           220:  * compare policyindex, with wildcard address/protocol match.
        !           221:  * a: subject b: db, can contain wildcard things.
        !           222:  * OUT:        0:      equal
        !           223:  *     1:      not equal
        !           224:  */
        !           225: int
        !           226: cmpspidxwild(a, b)
        !           227:        struct policyindex *a, *b;
        !           228: {
        !           229:        struct sockaddr_storage sa1, sa2;
        !           230: 
        !           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));
        !           233: 
        !           234:        if (!(b->dir == IPSEC_DIR_ANY || a->dir == b->dir))
        !           235:                return 1;
        !           236: 
        !           237:        if (!(b->ul_proto == IPSEC_ULPROTO_ANY ||
        !           238:              a->ul_proto == b->ul_proto))
        !           239:                return 1;
        !           240: 
        !           241:        if (a->src.ss_family != b->src.ss_family)
        !           242:                return 1;
        !           243:        if (a->dst.ss_family != b->dst.ss_family)
        !           244:                return 1;
        !           245: 
        !           246: #ifndef __linux__
        !           247:        /* compare src address */
        !           248:        if (sizeof(sa1) < a->src.ss_len || sizeof(sa2) < b->src.ss_len) {
        !           249:                plog(LLV_ERROR, LOCATION, NULL,
        !           250:                        "unexpected error: "
        !           251:                        "src.ss_len:%d dst.ss_len:%d\n",
        !           252:                        a->src.ss_len, b->src.ss_len);
        !           253:                return 1;
        !           254:        }
        !           255: #endif
        !           256:        mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->src,
        !           257:                b->prefs);
        !           258:        mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->src,
        !           259:                b->prefs);
        !           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) > CMPSADDR_WILDPORT_MATCH)
        !           265:                return 1;
        !           266: 
        !           267: #ifndef __linux__
        !           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");
        !           271:                exit(1);
        !           272:        }
        !           273: #endif
        !           274:        mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->dst,
        !           275:                b->prefd);
        !           276:        mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->dst,
        !           277:                b->prefd);
        !           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) > CMPSADDR_WILDPORT_MATCH)
        !           283:                return 1;
        !           284: 
        !           285: #ifdef HAVE_SECCTX
        !           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))
        !           289:                return 1;
        !           290: #endif
        !           291:        return 0;
        !           292: }
        !           293: 
        !           294: struct secpolicy *
        !           295: newsp()
        !           296: {
        !           297:        struct secpolicy *new;
        !           298: 
        !           299:        new = racoon_calloc(1, sizeof(*new));
        !           300:        if (new == NULL)
        !           301:                return NULL;
        !           302: 
        !           303:        return new;
        !           304: }
        !           305: 
        !           306: void
        !           307: delsp(sp)
        !           308:        struct secpolicy *sp;
        !           309: {
        !           310:        struct ipsecrequest *req = NULL, *next;
        !           311: 
        !           312:        for (req = sp->req; req; req = next) {
        !           313:                next = req->next;
        !           314:                racoon_free(req);
        !           315:        }
        !           316:        
        !           317:        if (sp->local)
        !           318:                racoon_free(sp->local);
        !           319:        if (sp->remote)
        !           320:                racoon_free(sp->remote);
        !           321: 
        !           322:        racoon_free(sp);
        !           323: }
        !           324: 
        !           325: void
        !           326: delsp_bothdir(spidx0)
        !           327:        struct policyindex *spidx0;
        !           328: {
        !           329:        struct policyindex spidx;
        !           330:        struct secpolicy *sp;
        !           331:        struct sockaddr_storage src, dst;
        !           332:        u_int8_t prefs, prefd;
        !           333: 
        !           334:        memcpy(&spidx, spidx0, sizeof(spidx));
        !           335:        switch (spidx.dir) {
        !           336:        case IPSEC_DIR_INBOUND:
        !           337: #ifdef HAVE_POLICY_FWD
        !           338:        case IPSEC_DIR_FWD:
        !           339: #endif
        !           340:                src   = spidx.src;
        !           341:                dst   = spidx.dst;
        !           342:                prefs = spidx.prefs;
        !           343:                prefd = spidx.prefd;
        !           344:                break;
        !           345:        case IPSEC_DIR_OUTBOUND:
        !           346:                src   = spidx.dst;
        !           347:                dst   = spidx.src;
        !           348:                prefs = spidx.prefd;
        !           349:                prefd = spidx.prefs;
        !           350:                break;
        !           351:        default:
        !           352:                return;
        !           353:        }
        !           354: 
        !           355:        spidx.src   = src;
        !           356:        spidx.dst   = dst;
        !           357:        spidx.prefs = prefs;
        !           358:        spidx.prefd = prefd;
        !           359:        spidx.dir   = IPSEC_DIR_INBOUND;
        !           360: 
        !           361:        sp = getsp(&spidx);
        !           362:        if (sp) {
        !           363:                remsp(sp);
        !           364:                delsp(sp);
        !           365:        }
        !           366: 
        !           367: #ifdef HAVE_POLICY_FWD
        !           368:        spidx.dir   = IPSEC_DIR_FWD;
        !           369: 
        !           370:        sp = getsp(&spidx);
        !           371:        if (sp) {
        !           372:                remsp(sp);
        !           373:                delsp(sp);
        !           374:        }
        !           375: #endif
        !           376: 
        !           377:        spidx.src   = dst;
        !           378:        spidx.dst   = src;
        !           379:        spidx.prefs = prefd;
        !           380:        spidx.prefd = prefs;
        !           381:        spidx.dir   = IPSEC_DIR_OUTBOUND;
        !           382: 
        !           383:        sp = getsp(&spidx);
        !           384:        if (sp) {
        !           385:                remsp(sp);
        !           386:                delsp(sp);
        !           387:        }
        !           388: }
        !           389: 
        !           390: void
        !           391: inssp(new)
        !           392:        struct secpolicy *new;
        !           393: {
        !           394: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           395:        struct secpolicy *p;
        !           396: 
        !           397:        TAILQ_FOREACH(p, &sptree, chain) {
        !           398:                if (new->spidx.priority < p->spidx.priority) {
        !           399:                        TAILQ_INSERT_BEFORE(p, new, chain);
        !           400:                        return;
        !           401:                }
        !           402:        }
        !           403:        if (p == NULL)
        !           404: #endif
        !           405:                TAILQ_INSERT_TAIL(&sptree, new, chain);
        !           406: 
        !           407:        return;
        !           408: }
        !           409: 
        !           410: void
        !           411: remsp(sp)
        !           412:        struct secpolicy *sp;
        !           413: {
        !           414:        TAILQ_REMOVE(&sptree, sp, chain);
        !           415: }
        !           416: 
        !           417: void
        !           418: flushsp()
        !           419: {
        !           420:        struct secpolicy *p, *next;
        !           421: 
        !           422:        for (p = TAILQ_FIRST(&sptree); p; p = next) {
        !           423:                next = TAILQ_NEXT(p, chain);
        !           424:                remsp(p);
        !           425:                delsp(p);
        !           426:        }
        !           427: }
        !           428: 
        !           429: void
        !           430: initsp()
        !           431: {
        !           432:        TAILQ_INIT(&sptree);
        !           433: }
        !           434: 
        !           435: struct ipsecrequest *
        !           436: newipsecreq()
        !           437: {
        !           438:        struct ipsecrequest *new;
        !           439: 
        !           440:        new = racoon_calloc(1, sizeof(*new));
        !           441:        if (new == NULL)
        !           442:                return NULL;
        !           443: 
        !           444:        return new;
        !           445: }
        !           446: 
        !           447: const char *
        !           448: spidx2str(spidx)
        !           449:        const struct policyindex *spidx;
        !           450: {
        !           451:        /* addr/pref[port] addr/pref[port] ul dir act */
        !           452:        static char buf[256];
        !           453:        char *p, *a, *b;
        !           454:        int blen, i;
        !           455: 
        !           456:        blen = sizeof(buf) - 1;
        !           457:        p = buf;
        !           458: 
        !           459:        a = saddr2str((const struct sockaddr *)&spidx->src);
        !           460:        for (b = a; *b != '\0'; b++)
        !           461:                if (*b == '[') {
        !           462:                        *b = '\0';
        !           463:                        b++;
        !           464:                        break;
        !           465:                }
        !           466:        i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefs, b);
        !           467:        if (i < 0 || i >= blen)
        !           468:                return NULL;
        !           469:        p += i;
        !           470:        blen -= i;
        !           471: 
        !           472:        a = saddr2str((const struct sockaddr *)&spidx->dst);
        !           473:        for (b = a; *b != '\0'; b++)
        !           474:                if (*b == '[') {
        !           475:                        *b = '\0';
        !           476:                        b++;
        !           477:                        break;
        !           478:                }
        !           479:        i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefd, b);
        !           480:        if (i < 0 || i >= blen)
        !           481:                return NULL;
        !           482:        p += i;
        !           483:        blen -= i;
        !           484: 
        !           485:        i = snprintf(p, blen, "proto=%s dir=%s",
        !           486:                s_proto(spidx->ul_proto), s_direction(spidx->dir));
        !           487: 
        !           488: #ifdef HAVE_SECCTX
        !           489:        if (spidx->sec_ctx.ctx_strlen) {
        !           490:                p += i;
        !           491:                blen -= i;
        !           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);
        !           495:        }
        !           496: #endif
        !           497:        return buf;
        !           498: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>