Annotation of embedaddon/ipsec-tools/src/racoon/policy.c, revision 1.1.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>