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

1.1     ! misho       1: /*     $NetBSD: proposal.c,v 1.17 2008/09/19 11:14:49 tteras Exp $     */
        !             2: 
        !             3: /* $Id: proposal.c,v 1.17 2008/09/19 11:14:49 tteras 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 "pfkey.h"
        !            58: #include "isakmp_var.h"
        !            59: #include "isakmp.h"
        !            60: #include "ipsec_doi.h"
        !            61: #include "algorithm.h"
        !            62: #include "proposal.h"
        !            63: #include "sainfo.h"
        !            64: #include "localconf.h"
        !            65: #include "remoteconf.h"
        !            66: #include "oakley.h"
        !            67: #include "handler.h"
        !            68: #include "strnames.h"
        !            69: #include "gcmalloc.h"
        !            70: #ifdef ENABLE_NATT
        !            71: #include "nattraversal.h"
        !            72: #endif
        !            73: 
        !            74: static uint g_nextreqid = 1;
        !            75: 
        !            76: /* %%%
        !            77:  * modules for ipsec sa spec
        !            78:  */
        !            79: struct saprop *
        !            80: newsaprop()
        !            81: {
        !            82:        struct saprop *new;
        !            83: 
        !            84:        new = racoon_calloc(1, sizeof(*new));
        !            85:        if (new == NULL)
        !            86:                return NULL;
        !            87: 
        !            88:        return new;
        !            89: }
        !            90: 
        !            91: struct saproto *
        !            92: newsaproto()
        !            93: {
        !            94:        struct saproto *new;
        !            95: 
        !            96:        new = racoon_calloc(1, sizeof(*new));
        !            97:        if (new == NULL)
        !            98:                return NULL;
        !            99: 
        !           100:        return new;
        !           101: }
        !           102: 
        !           103: /* set saprop to last part of the prop tree */
        !           104: void
        !           105: inssaprop(head, new)
        !           106:        struct saprop **head;
        !           107:        struct saprop *new;
        !           108: {
        !           109:        struct saprop *p;
        !           110: 
        !           111:        if (*head == NULL) {
        !           112:                *head = new;
        !           113:                return;
        !           114:        }
        !           115: 
        !           116:        for (p = *head; p->next; p = p->next)
        !           117:                ;
        !           118:        p->next = new;
        !           119: 
        !           120:        return;
        !           121: }
        !           122: 
        !           123: /* set saproto to the end of the proto tree in saprop */
        !           124: void
        !           125: inssaproto(pp, new)
        !           126:        struct saprop *pp;
        !           127:        struct saproto *new;
        !           128: {
        !           129:        struct saproto *p;
        !           130: 
        !           131:        for (p = pp->head; p && p->next; p = p->next)
        !           132:                ;
        !           133:        if (p == NULL)
        !           134:                pp->head = new;
        !           135:        else
        !           136:                p->next = new;
        !           137: 
        !           138:        return;
        !           139: }
        !           140: 
        !           141: /* set saproto to the top of the proto tree in saprop */
        !           142: void
        !           143: inssaprotorev(pp, new)
        !           144:       struct saprop *pp;
        !           145:       struct saproto *new;
        !           146: {
        !           147:       new->next = pp->head;
        !           148:       pp->head = new;
        !           149: 
        !           150:       return;
        !           151: }
        !           152: 
        !           153: struct satrns *
        !           154: newsatrns()
        !           155: {
        !           156:        struct satrns *new;
        !           157: 
        !           158:        new = racoon_calloc(1, sizeof(*new));
        !           159:        if (new == NULL)
        !           160:                return NULL;
        !           161: 
        !           162:        return new;
        !           163: }
        !           164: 
        !           165: /* set saproto to last part of the proto tree in saprop */
        !           166: void
        !           167: inssatrns(pr, new)
        !           168:        struct saproto *pr;
        !           169:        struct satrns *new;
        !           170: {
        !           171:        struct satrns *tr;
        !           172: 
        !           173:        for (tr = pr->head; tr && tr->next; tr = tr->next)
        !           174:                ;
        !           175:        if (tr == NULL)
        !           176:                pr->head = new;
        !           177:        else
        !           178:                tr->next = new;
        !           179: 
        !           180:        return;
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * take a single match between saprop.  allocate a new proposal and return it
        !           185:  * for future use (like picking single proposal from a bundle).
        !           186:  *     pp1: peer's proposal.
        !           187:  *     pp2: my proposal.
        !           188:  * NOTE: In the case of initiator, must be ensured that there is no
        !           189:  * modification of the proposal by calling cmp_aproppair_i() before
        !           190:  * this function.
        !           191:  * XXX cannot understand the comment!
        !           192:  */
        !           193: struct saprop *
        !           194: cmpsaprop_alloc(ph1, pp1, pp2, side)
        !           195:        struct ph1handle *ph1;
        !           196:        const struct saprop *pp1, *pp2;
        !           197:        int side;
        !           198: {
        !           199:        struct saprop *newpp = NULL;
        !           200:        struct saproto *pr1, *pr2, *newpr = NULL;
        !           201:        struct satrns *tr1, *tr2, *newtr;
        !           202:        const int ordermatters = 0;
        !           203:        int npr1, npr2;
        !           204:        int spisizematch;
        !           205: 
        !           206:        newpp = newsaprop();
        !           207:        if (newpp == NULL) {
        !           208:                plog(LLV_ERROR, LOCATION, NULL,
        !           209:                        "failed to allocate saprop.\n");
        !           210:                return NULL;
        !           211:        }
        !           212:        newpp->prop_no = pp1->prop_no;
        !           213: 
        !           214:        /* see proposal.h about lifetime/key length and PFS selection. */
        !           215: 
        !           216:        /* check time/bytes lifetime and PFS */
        !           217:        switch (ph1->rmconf->pcheck_level) {
        !           218:        case PROP_CHECK_OBEY:
        !           219:                newpp->lifetime = pp1->lifetime;
        !           220:                newpp->lifebyte = pp1->lifebyte;
        !           221:                newpp->pfs_group = pp1->pfs_group;
        !           222:                break;
        !           223: 
        !           224:        case PROP_CHECK_STRICT:
        !           225:                if (pp1->lifetime > pp2->lifetime) {
        !           226:                        plog(LLV_ERROR, LOCATION, NULL,
        !           227:                                "long lifetime proposed: "
        !           228:                                "my:%d peer:%d\n",
        !           229:                                (int)pp2->lifetime, (int)pp1->lifetime);
        !           230:                        goto err;
        !           231:                }
        !           232:                if (pp1->lifebyte > pp2->lifebyte) {
        !           233:                        plog(LLV_ERROR, LOCATION, NULL,
        !           234:                                "long lifebyte proposed: "
        !           235:                                "my:%d peer:%d\n",
        !           236:                                pp2->lifebyte, pp1->lifebyte);
        !           237:                        goto err;
        !           238:                }
        !           239:                newpp->lifetime = pp1->lifetime;
        !           240:                newpp->lifebyte = pp1->lifebyte;
        !           241: 
        !           242:     prop_pfs_check:
        !           243:                if (pp2->pfs_group != 0 && pp1->pfs_group != pp2->pfs_group) {
        !           244:                        plog(LLV_ERROR, LOCATION, NULL,
        !           245:                                "pfs group mismatched: "
        !           246:                                "my:%d peer:%d\n",
        !           247:                                pp2->pfs_group, pp1->pfs_group);
        !           248:                        goto err;
        !           249:                }
        !           250:                newpp->pfs_group = pp1->pfs_group;
        !           251:                break;
        !           252: 
        !           253:        case PROP_CHECK_CLAIM:
        !           254:                /* lifetime */
        !           255:                if (pp1->lifetime <= pp2->lifetime) {
        !           256:                        newpp->lifetime = pp1->lifetime;
        !           257:                } else {
        !           258:                        newpp->lifetime = pp2->lifetime;
        !           259:                        newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
        !           260:                        plog(LLV_NOTIFY, LOCATION, NULL,
        !           261:                                "use own lifetime: "
        !           262:                                "my:%d peer:%d\n",
        !           263:                                (int)pp2->lifetime, (int)pp1->lifetime);
        !           264:                }
        !           265: 
        !           266:                /* lifebyte */
        !           267:                if (pp1->lifebyte > pp2->lifebyte) {
        !           268:                        newpp->lifebyte = pp2->lifebyte;
        !           269:                        newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
        !           270:                        plog(LLV_NOTIFY, LOCATION, NULL,
        !           271:                                "use own lifebyte: "
        !           272:                                "my:%d peer:%d\n",
        !           273:                                pp2->lifebyte, pp1->lifebyte);
        !           274:                }
        !           275:                newpp->lifebyte = pp1->lifebyte;
        !           276: 
        !           277:                goto prop_pfs_check;
        !           278:                break;
        !           279: 
        !           280:        case PROP_CHECK_EXACT:
        !           281:                if (pp1->lifetime != pp2->lifetime) {
        !           282:                        plog(LLV_ERROR, LOCATION, NULL,
        !           283:                                "lifetime mismatched: "
        !           284:                                "my:%d peer:%d\n",
        !           285:                                (int)pp2->lifetime, (int)pp1->lifetime);
        !           286:                        goto err;
        !           287:                }
        !           288: 
        !           289:                if (pp1->lifebyte != pp2->lifebyte) {
        !           290:                        plog(LLV_ERROR, LOCATION, NULL,
        !           291:                                "lifebyte mismatched: "
        !           292:                                "my:%d peer:%d\n",
        !           293:                                pp2->lifebyte, pp1->lifebyte);
        !           294:                        goto err;
        !           295:                }
        !           296:                if (pp1->pfs_group != pp2->pfs_group) {
        !           297:                        plog(LLV_ERROR, LOCATION, NULL,
        !           298:                                "pfs group mismatched: "
        !           299:                                "my:%d peer:%d\n",
        !           300:                                pp2->pfs_group, pp1->pfs_group);
        !           301:                        goto err;
        !           302:                }
        !           303:                newpp->lifetime = pp1->lifetime;
        !           304:                newpp->lifebyte = pp1->lifebyte;
        !           305:                newpp->pfs_group = pp1->pfs_group;
        !           306:                break;
        !           307: 
        !           308:        default:
        !           309:                plog(LLV_ERROR, LOCATION, NULL,
        !           310:                        "invalid pcheck_level why?.\n");
        !           311:                goto err;
        !           312:        }
        !           313: 
        !           314: #ifdef HAVE_SECCTX
        !           315:        /* check the security_context properties.
        !           316:         * It is possible for one side to have a security context
        !           317:         * and the other side doesn't. If so, this is an error.
        !           318:         */
        !           319: 
        !           320:        if (*pp1->sctx.ctx_str && !(*pp2->sctx.ctx_str)) {
        !           321:                plog(LLV_ERROR, LOCATION, NULL,
        !           322:                     "My proposal missing security context\n");
        !           323:                goto err;
        !           324:        }
        !           325:        if (!(*pp1->sctx.ctx_str) && *pp2->sctx.ctx_str) {
        !           326:                plog(LLV_ERROR, LOCATION, NULL, 
        !           327:                     "Peer is missing security context\n");
        !           328:                goto err;
        !           329:        }
        !           330: 
        !           331:        if (*pp1->sctx.ctx_str && *pp2->sctx.ctx_str) {
        !           332:                if (pp1->sctx.ctx_doi == pp2->sctx.ctx_doi)
        !           333:                        newpp->sctx.ctx_doi = pp1->sctx.ctx_doi;
        !           334:                else {
        !           335:                        plog(LLV_ERROR, LOCATION, NULL, 
        !           336:                             "sec doi mismatched: my:%d peer:%d\n",
        !           337:                             pp2->sctx.ctx_doi, pp1->sctx.ctx_doi);
        !           338:                             goto err;
        !           339:                }
        !           340: 
        !           341:                if (pp1->sctx.ctx_alg == pp2->sctx.ctx_alg)
        !           342:                        newpp->sctx.ctx_alg = pp1->sctx.ctx_alg;
        !           343:                else {
        !           344:                        plog(LLV_ERROR, LOCATION, NULL,
        !           345:                             "sec alg mismatched: my:%d peer:%d\n",
        !           346:                             pp2->sctx.ctx_alg, pp1->sctx.ctx_alg);
        !           347:                        goto err;
        !           348:                }
        !           349: 
        !           350:                if ((pp1->sctx.ctx_strlen != pp2->sctx.ctx_strlen) ||
        !           351:                     memcmp(pp1->sctx.ctx_str, pp2->sctx.ctx_str,
        !           352:                     pp1->sctx.ctx_strlen) != 0) {
        !           353:                        plog(LLV_ERROR, LOCATION, NULL,
        !           354:                             "sec ctx string mismatched: my:%s peer:%s\n",
        !           355:                             pp2->sctx.ctx_str, pp1->sctx.ctx_str);
        !           356:                                goto err;
        !           357:                } else {
        !           358:                        newpp->sctx.ctx_strlen = pp1->sctx.ctx_strlen;
        !           359:                        memcpy(newpp->sctx.ctx_str, pp1->sctx.ctx_str,
        !           360:                                pp1->sctx.ctx_strlen);
        !           361:                }
        !           362:        }
        !           363: #endif /* HAVE_SECCTX */
        !           364: 
        !           365:        npr1 = npr2 = 0;
        !           366:        for (pr1 = pp1->head; pr1; pr1 = pr1->next)
        !           367:                npr1++;
        !           368:        for (pr2 = pp2->head; pr2; pr2 = pr2->next)
        !           369:                npr2++;
        !           370:        if (npr1 != npr2)
        !           371:                goto err;
        !           372: 
        !           373:        /* check protocol order */
        !           374:        pr1 = pp1->head;
        !           375:        pr2 = pp2->head;
        !           376: 
        !           377:        while (1) {
        !           378:                if (!ordermatters) {
        !           379:                        /*
        !           380:                         * XXX does not work if we have multiple proposals
        !           381:                         * with the same proto_id
        !           382:                         */
        !           383:                        switch (side) {
        !           384:                        case RESPONDER:
        !           385:                                if (!pr2)
        !           386:                                        break;
        !           387:                                for (pr1 = pp1->head; pr1; pr1 = pr1->next) {
        !           388:                                        if (pr1->proto_id == pr2->proto_id)
        !           389:                                                break;
        !           390:                                }
        !           391:                                break;
        !           392:                        case INITIATOR:
        !           393:                                if (!pr1)
        !           394:                                        break;
        !           395:                                for (pr2 = pp2->head; pr2; pr2 = pr2->next) {
        !           396:                                        if (pr2->proto_id == pr1->proto_id)
        !           397:                                                break;
        !           398:                                }
        !           399:                                break;
        !           400:                        }
        !           401:                }
        !           402:                if (!pr1 || !pr2)
        !           403:                        break;
        !           404: 
        !           405:                if (pr1->proto_id != pr2->proto_id) {
        !           406:                        plog(LLV_ERROR, LOCATION, NULL,
        !           407:                                "proto_id mismatched: "
        !           408:                                "my:%s peer:%s\n",
        !           409:                                s_ipsecdoi_proto(pr2->proto_id),
        !           410:                                s_ipsecdoi_proto(pr1->proto_id));
        !           411:                        goto err;
        !           412:                }
        !           413:                spisizematch = 0;
        !           414:                if (pr1->spisize == pr2->spisize)
        !           415:                        spisizematch = 1;
        !           416:                else if (pr1->proto_id == IPSECDOI_PROTO_IPCOMP) {
        !           417:                        /*
        !           418:                         * draft-shacham-ippcp-rfc2393bis-05.txt:
        !           419:                         * need to accept 16bit and 32bit SPI (CPI) for IPComp.
        !           420:                         */
        !           421:                        if (pr1->spisize == sizeof(u_int16_t) &&
        !           422:                            pr2->spisize == sizeof(u_int32_t)) {
        !           423:                                spisizematch = 1;
        !           424:                        } else if (pr2->spisize == sizeof(u_int16_t) &&
        !           425:                                 pr1->spisize == sizeof(u_int32_t)) {
        !           426:                                spisizematch = 1;
        !           427:                        }
        !           428:                        if (spisizematch) {
        !           429:                                plog(LLV_ERROR, LOCATION, NULL,
        !           430:                                    "IPComp SPI size promoted "
        !           431:                                    "from 16bit to 32bit\n");
        !           432:                        }
        !           433:                }
        !           434:                if (!spisizematch) {
        !           435:                        plog(LLV_ERROR, LOCATION, NULL,
        !           436:                                "spisize mismatched: "
        !           437:                                "my:%d peer:%d\n",
        !           438:                                (int)pr2->spisize, (int)pr1->spisize);
        !           439:                        goto err;
        !           440:                }
        !           441: 
        !           442: #ifdef ENABLE_NATT
        !           443:                if ((ph1->natt_flags & NAT_DETECTED) && 
        !           444:                    natt_udp_encap (pr2->encmode))
        !           445:                {
        !           446:                        plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s->%s\n",
        !           447:                             s_ipsecdoi_encmode(pr2->encmode),
        !           448:                             s_ipsecdoi_encmode(pr2->encmode - ph1->natt_options->mode_udp_diff));
        !           449:                        pr2->encmode -= ph1->natt_options->mode_udp_diff;
        !           450:                        pr2->udp_encap = 1;
        !           451:                }
        !           452: 
        !           453:                if ((ph1->natt_flags & NAT_DETECTED) &&
        !           454:                    natt_udp_encap (pr1->encmode))
        !           455:                {
        !           456:                        plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
        !           457:                             s_ipsecdoi_encmode(pr1->encmode),
        !           458:                             pr1->encmode,
        !           459:                             s_ipsecdoi_encmode(pr1->encmode - ph1->natt_options->mode_udp_diff),
        !           460:                             pr1->encmode - ph1->natt_options->mode_udp_diff);
        !           461:                        pr1->encmode -= ph1->natt_options->mode_udp_diff;
        !           462:                        pr1->udp_encap = 1;
        !           463:                }
        !           464: #endif
        !           465: 
        !           466:                if (pr1->encmode != pr2->encmode) {
        !           467:                        plog(LLV_ERROR, LOCATION, NULL,
        !           468:                                "encmode mismatched: "
        !           469:                                "my:%s peer:%s\n",
        !           470:                                s_ipsecdoi_encmode(pr2->encmode),
        !           471:                                s_ipsecdoi_encmode(pr1->encmode));
        !           472:                        goto err;
        !           473:                }
        !           474: 
        !           475:                for (tr1 = pr1->head; tr1; tr1 = tr1->next) {
        !           476:                        for (tr2 = pr2->head; tr2; tr2 = tr2->next) {
        !           477:                                if (cmpsatrns(pr1->proto_id, tr1, tr2, ph1->rmconf->pcheck_level) == 0)
        !           478:                                        goto found;
        !           479:                        }
        !           480:                }
        !           481: 
        !           482:                goto err;
        !           483: 
        !           484:            found:
        !           485:                newpr = newsaproto();
        !           486:                if (newpr == NULL) {
        !           487:                        plog(LLV_ERROR, LOCATION, NULL,
        !           488:                                "failed to allocate saproto.\n");
        !           489:                        goto err;
        !           490:                }
        !           491:                newpr->proto_id = pr1->proto_id;
        !           492:                newpr->spisize = pr1->spisize;
        !           493:                newpr->encmode = pr1->encmode;
        !           494:                newpr->spi = pr2->spi;          /* copy my SPI */
        !           495:                newpr->spi_p = pr1->spi;        /* copy peer's SPI */
        !           496:                newpr->reqid_in = pr2->reqid_in;
        !           497:                newpr->reqid_out = pr2->reqid_out;
        !           498: #ifdef ENABLE_NATT
        !           499:                newpr->udp_encap = pr1->udp_encap | pr2->udp_encap;
        !           500: #endif
        !           501: 
        !           502:                newtr = newsatrns();
        !           503:                if (newtr == NULL) {
        !           504:                        plog(LLV_ERROR, LOCATION, NULL,
        !           505:                                "failed to allocate satrns.\n");
        !           506:                        racoon_free(newpr);
        !           507:                        goto err;
        !           508:                }
        !           509:                newtr->trns_no = tr1->trns_no;
        !           510:                newtr->trns_id = tr1->trns_id;
        !           511:                newtr->encklen = tr1->encklen;
        !           512:                newtr->authtype = tr1->authtype;
        !           513: 
        !           514:                inssatrns(newpr, newtr);
        !           515:                inssaproto(newpp, newpr);
        !           516: 
        !           517:                pr1 = pr1->next;
        !           518:                pr2 = pr2->next;
        !           519:        }
        !           520: 
        !           521:        /* XXX should check if we have visited all items or not */
        !           522:        if (!ordermatters) {
        !           523:                switch (side) {
        !           524:                case RESPONDER:
        !           525:                        if (!pr2)
        !           526:                                pr1 = NULL;
        !           527:                        break;
        !           528:                case INITIATOR:
        !           529:                        if (!pr1)
        !           530:                                pr2 = NULL;
        !           531:                        break;
        !           532:                }
        !           533:        }
        !           534: 
        !           535:        /* should be matched all protocols in a proposal */
        !           536:        if (pr1 != NULL || pr2 != NULL)
        !           537:                goto err;
        !           538: 
        !           539:        return newpp;
        !           540: 
        !           541: err:
        !           542:        flushsaprop(newpp);
        !           543:        return NULL;
        !           544: }
        !           545: 
        !           546: /* take a single match between saprop.  returns 0 if pp1 equals to pp2. */
        !           547: int
        !           548: cmpsaprop(pp1, pp2)
        !           549:        const struct saprop *pp1, *pp2;
        !           550: {
        !           551:        if (pp1->pfs_group != pp2->pfs_group) {
        !           552:                plog(LLV_WARNING, LOCATION, NULL,
        !           553:                        "pfs_group mismatch. mine:%d peer:%d\n",
        !           554:                        pp1->pfs_group, pp2->pfs_group);
        !           555:                /* FALLTHRU */
        !           556:        }
        !           557: 
        !           558:        if (pp1->lifetime > pp2->lifetime) {
        !           559:                plog(LLV_WARNING, LOCATION, NULL,
        !           560:                        "less lifetime proposed. mine:%d peer:%d\n",
        !           561:                        (int)pp1->lifetime, (int)pp2->lifetime);
        !           562:                /* FALLTHRU */
        !           563:        }
        !           564:        if (pp1->lifebyte > pp2->lifebyte) {
        !           565:                plog(LLV_WARNING, LOCATION, NULL,
        !           566:                        "less lifebyte proposed. mine:%d peer:%d\n",
        !           567:                        pp1->lifebyte, pp2->lifebyte);
        !           568:                /* FALLTHRU */
        !           569:        }
        !           570: 
        !           571:        return 0;
        !           572: }
        !           573: 
        !           574: /*
        !           575:  * take a single match between satrns.  returns 0 if tr1 equals to tr2.
        !           576:  * tr1: peer's satrns
        !           577:  * tr2: my satrns
        !           578:  */
        !           579: int
        !           580: cmpsatrns(proto_id, tr1, tr2, check_level)
        !           581:        int proto_id;
        !           582:        const struct satrns *tr1, *tr2;
        !           583:        int check_level;
        !           584: {
        !           585:        if (tr1->trns_id != tr2->trns_id) {
        !           586:                plog(LLV_WARNING, LOCATION, NULL,
        !           587:                        "trns_id mismatched: "
        !           588:                        "my:%s peer:%s\n",
        !           589:                        s_ipsecdoi_trns(proto_id, tr2->trns_id),
        !           590:                        s_ipsecdoi_trns(proto_id, tr1->trns_id));
        !           591:                return 1;
        !           592:        }
        !           593: 
        !           594:        if (tr1->authtype != tr2->authtype) {
        !           595:                plog(LLV_WARNING, LOCATION, NULL,
        !           596:                        "authtype mismatched: "
        !           597:                        "my:%s peer:%s\n",
        !           598:                        s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr2->authtype),
        !           599:                        s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr1->authtype));
        !           600:                return 1;
        !           601:        }
        !           602: 
        !           603:        /* Check key length regarding checkmode
        !           604:         * XXX Shall we send some kind of notify message when key length rejected ?
        !           605:         */
        !           606:        switch(check_level){
        !           607:        case PROP_CHECK_OBEY:
        !           608:                return 0;
        !           609:                break;
        !           610: 
        !           611:        case PROP_CHECK_STRICT:
        !           612:                /* FALLTHROUGH */
        !           613:        case PROP_CHECK_CLAIM:
        !           614:                if (tr1->encklen < tr2->encklen) {
        !           615:                plog(LLV_WARNING, LOCATION, NULL,
        !           616:                                 "low key length proposed, "
        !           617:                                 "mine:%d peer:%d.\n",
        !           618:                        tr2->encklen, tr1->encklen);
        !           619:                        return 1;
        !           620:                }
        !           621:                break;
        !           622:        case PROP_CHECK_EXACT:
        !           623:                if (tr1->encklen != tr2->encklen) {
        !           624:                        plog(LLV_WARNING, LOCATION, NULL,
        !           625:                                 "key length mismatched, "
        !           626:                                 "mine:%d peer:%d.\n",
        !           627:                                 tr2->encklen, tr1->encklen);
        !           628:                        return 1;
        !           629:                }
        !           630:                break;
        !           631:        }
        !           632: 
        !           633:        return 0;
        !           634: }
        !           635: 
        !           636: int
        !           637: set_satrnsbysainfo(pr, sainfo)
        !           638:        struct saproto *pr;
        !           639:        struct sainfo *sainfo;
        !           640: {
        !           641:        struct sainfoalg *a, *b;
        !           642:        struct satrns *newtr;
        !           643:        int t;
        !           644: 
        !           645:        switch (pr->proto_id) {
        !           646:        case IPSECDOI_PROTO_IPSEC_AH:
        !           647:                if (sainfo->algs[algclass_ipsec_auth] == NULL) {
        !           648:                        plog(LLV_ERROR, LOCATION, NULL,
        !           649:                                "no auth algorithm found\n");
        !           650:                        goto err;
        !           651:                }
        !           652:                t = 1;
        !           653:                for (a = sainfo->algs[algclass_ipsec_auth]; a; a = a->next) {
        !           654: 
        !           655:                        if (a->alg == IPSECDOI_ATTR_AUTH_NONE)
        !           656:                                continue;
        !           657:                                
        !           658:                        /* allocate satrns */
        !           659:                        newtr = newsatrns();
        !           660:                        if (newtr == NULL) {
        !           661:                                plog(LLV_ERROR, LOCATION, NULL,
        !           662:                                        "failed to allocate satrns.\n");
        !           663:                                goto err;
        !           664:                        }
        !           665: 
        !           666:                        newtr->trns_no = t++;
        !           667:                        newtr->trns_id = ipsecdoi_authalg2trnsid(a->alg);
        !           668:                        newtr->authtype = a->alg;
        !           669: 
        !           670:                        inssatrns(pr, newtr);
        !           671:                }
        !           672:                break;
        !           673:        case IPSECDOI_PROTO_IPSEC_ESP:
        !           674:                if (sainfo->algs[algclass_ipsec_enc] == NULL) {
        !           675:                        plog(LLV_ERROR, LOCATION, NULL,
        !           676:                                "no encryption algorithm found\n");
        !           677:                        goto err;
        !           678:                }
        !           679:                t = 1;
        !           680:                for (a = sainfo->algs[algclass_ipsec_enc]; a; a = a->next) {
        !           681:                        for (b = sainfo->algs[algclass_ipsec_auth]; b; b = b->next) {
        !           682:                                /* allocate satrns */
        !           683:                                newtr = newsatrns();
        !           684:                                if (newtr == NULL) {
        !           685:                                        plog(LLV_ERROR, LOCATION, NULL,
        !           686:                                                "failed to allocate satrns.\n");
        !           687:                                        goto err;
        !           688:                                }
        !           689: 
        !           690:                                newtr->trns_no = t++;
        !           691:                                newtr->trns_id = a->alg;
        !           692:                                newtr->encklen = a->encklen;
        !           693:                                newtr->authtype = b->alg;
        !           694: 
        !           695:                                inssatrns(pr, newtr);
        !           696:                        }
        !           697:                }
        !           698:                break;
        !           699:        case IPSECDOI_PROTO_IPCOMP:
        !           700:                if (sainfo->algs[algclass_ipsec_comp] == NULL) {
        !           701:                        plog(LLV_ERROR, LOCATION, NULL,
        !           702:                                "no ipcomp algorithm found\n");
        !           703:                        goto err;
        !           704:                }
        !           705:                t = 1;
        !           706:                for (a = sainfo->algs[algclass_ipsec_comp]; a; a = a->next) {
        !           707: 
        !           708:                        /* allocate satrns */
        !           709:                        newtr = newsatrns();
        !           710:                        if (newtr == NULL) {
        !           711:                                plog(LLV_ERROR, LOCATION, NULL,
        !           712:                                        "failed to allocate satrns.\n");
        !           713:                                goto err;
        !           714:                        }
        !           715: 
        !           716:                        newtr->trns_no = t++;
        !           717:                        newtr->trns_id = a->alg;
        !           718:                        newtr->authtype = IPSECDOI_ATTR_AUTH_NONE; /*no auth*/
        !           719: 
        !           720:                        inssatrns(pr, newtr);
        !           721:                }
        !           722:                break;
        !           723:        default:
        !           724:                plog(LLV_ERROR, LOCATION, NULL,
        !           725:                        "unknown proto_id (%d).\n", pr->proto_id);
        !           726:                goto err;
        !           727:        }
        !           728: 
        !           729:        /* no proposal found */
        !           730:        if (pr->head == NULL) {
        !           731:                plog(LLV_ERROR, LOCATION, NULL, "no algorithms found.\n");
        !           732:                return -1;
        !           733:        }
        !           734: 
        !           735:        return 0;
        !           736: 
        !           737: err:
        !           738:        flushsatrns(pr->head);
        !           739:        return -1;
        !           740: }
        !           741: 
        !           742: struct saprop *
        !           743: aproppair2saprop(p0)
        !           744:        struct prop_pair *p0;
        !           745: {
        !           746:        struct prop_pair *p, *t;
        !           747:        struct saprop *newpp;
        !           748:        struct saproto *newpr;
        !           749:        struct satrns *newtr;
        !           750:        u_int8_t *spi;
        !           751: 
        !           752:        if (p0 == NULL)
        !           753:                return NULL;
        !           754: 
        !           755:        /* allocate ipsec a sa proposal */
        !           756:        newpp = newsaprop();
        !           757:        if (newpp == NULL) {
        !           758:                plog(LLV_ERROR, LOCATION, NULL,
        !           759:                        "failed to allocate saprop.\n");
        !           760:                return NULL;
        !           761:        }
        !           762:        newpp->prop_no = p0->prop->p_no;
        !           763:        /* lifetime & lifebyte must be updated later */
        !           764: 
        !           765:        for (p = p0; p; p = p->next) {
        !           766: 
        !           767:                /* allocate ipsec sa protocol */
        !           768:                newpr = newsaproto();
        !           769:                if (newpr == NULL) {
        !           770:                        plog(LLV_ERROR, LOCATION, NULL,
        !           771:                                "failed to allocate saproto.\n");
        !           772:                        goto err;
        !           773:                }
        !           774: 
        !           775:                /* check spi size */
        !           776:                /* XXX should be handled isakmp cookie */
        !           777:                if (sizeof(newpr->spi) < p->prop->spi_size) {
        !           778:                        plog(LLV_ERROR, LOCATION, NULL,
        !           779:                                "invalid spi size %d.\n", p->prop->spi_size);
        !           780:                        racoon_free(newpr);
        !           781:                        goto err;
        !           782:                }
        !           783: 
        !           784:                /*
        !           785:                 * XXX SPI bits are left-filled, for use with IPComp.
        !           786:                 * we should be switching to variable-length spi field...
        !           787:                 */
        !           788:                newpr->proto_id = p->prop->proto_id;
        !           789:                newpr->spisize = p->prop->spi_size;
        !           790:                memset(&newpr->spi, 0, sizeof(newpr->spi));
        !           791:                spi = (u_int8_t *)&newpr->spi;
        !           792:                spi += sizeof(newpr->spi);
        !           793:                spi -= p->prop->spi_size;
        !           794:                memcpy(spi, p->prop + 1, p->prop->spi_size);
        !           795:                newpr->reqid_in = 0;
        !           796:                newpr->reqid_out = 0;
        !           797: 
        !           798:                for (t = p; t; t = t->tnext) {
        !           799: 
        !           800:                        plog(LLV_DEBUG, LOCATION, NULL,
        !           801:                                "prop#=%d prot-id=%s spi-size=%d "
        !           802:                                "#trns=%d trns#=%d trns-id=%s\n",
        !           803:                                t->prop->p_no,
        !           804:                                s_ipsecdoi_proto(t->prop->proto_id),
        !           805:                                t->prop->spi_size, t->prop->num_t,
        !           806:                                t->trns->t_no,
        !           807:                                s_ipsecdoi_trns(t->prop->proto_id,
        !           808:                                t->trns->t_id));
        !           809: 
        !           810:                        /* allocate ipsec sa transform */
        !           811:                        newtr = newsatrns();
        !           812:                        if (newtr == NULL) {
        !           813:                                plog(LLV_ERROR, LOCATION, NULL,
        !           814:                                        "failed to allocate satrns.\n");
        !           815:                                racoon_free(newpr);
        !           816:                                goto err;
        !           817:                        }
        !           818: 
        !           819:                        if (ipsecdoi_t2satrns(t->trns, 
        !           820:                            newpp, newpr, newtr) < 0) {
        !           821:                                flushsaprop(newpp);
        !           822:                                racoon_free(newtr);
        !           823:                                racoon_free(newpr);
        !           824:                                return NULL;
        !           825:                        }
        !           826: 
        !           827:                        inssatrns(newpr, newtr);
        !           828:                }
        !           829: 
        !           830:                /*
        !           831:                 * If the peer does not specify encryption mode, use 
        !           832:                 * transport mode by default.  This is to conform to
        !           833:                 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
        !           834:                 * that unspecified == transport), as well as RFC2407
        !           835:                 * (unspecified == implementation dependent default).
        !           836:                 */
        !           837:                if (newpr->encmode == 0)
        !           838:                        newpr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS;
        !           839: 
        !           840:                inssaproto(newpp, newpr);
        !           841:        }
        !           842: 
        !           843:        return newpp;
        !           844: 
        !           845: err:
        !           846:        flushsaprop(newpp);
        !           847:        return NULL;
        !           848: }
        !           849: 
        !           850: void
        !           851: flushsaprop(head)
        !           852:        struct saprop *head;
        !           853: {
        !           854:        struct saprop *p, *save;
        !           855: 
        !           856:        for (p = head; p != NULL; p = save) {
        !           857:                save = p->next;
        !           858:                flushsaproto(p->head);
        !           859:                racoon_free(p);
        !           860:        }
        !           861: 
        !           862:        return;
        !           863: }
        !           864: 
        !           865: void
        !           866: flushsaproto(head)
        !           867:        struct saproto *head;
        !           868: {
        !           869:        struct saproto *p, *save;
        !           870: 
        !           871:        for (p = head; p != NULL; p = save) {
        !           872:                save = p->next;
        !           873:                flushsatrns(p->head);
        !           874:                vfree(p->keymat);
        !           875:                vfree(p->keymat_p);
        !           876:                racoon_free(p);
        !           877:        }
        !           878: 
        !           879:        return;
        !           880: }
        !           881: 
        !           882: void
        !           883: flushsatrns(head)
        !           884:        struct satrns *head;
        !           885: {
        !           886:        struct satrns *p, *save;
        !           887: 
        !           888:        for (p = head; p != NULL; p = save) {
        !           889:                save = p->next;
        !           890:                racoon_free(p);
        !           891:        }
        !           892: 
        !           893:        return;
        !           894: }
        !           895: 
        !           896: /*
        !           897:  * print multiple proposals
        !           898:  */
        !           899: void
        !           900: printsaprop(pri, pp)
        !           901:        const int pri;
        !           902:        const struct saprop *pp;
        !           903: {
        !           904:        const struct saprop *p;
        !           905: 
        !           906:        if (pp == NULL) {
        !           907:                plog(pri, LOCATION, NULL, "(null)");
        !           908:                return;
        !           909:        }
        !           910: 
        !           911:        for (p = pp; p; p = p->next) {
        !           912:                printsaprop0(pri, p);
        !           913:        }
        !           914: 
        !           915:        return;
        !           916: }
        !           917: 
        !           918: /*
        !           919:  * print one proposal.
        !           920:  */
        !           921: void
        !           922: printsaprop0(pri, pp)
        !           923:        int pri;
        !           924:        const struct saprop *pp;
        !           925: {
        !           926:        const struct saproto *p;
        !           927: 
        !           928:        if (pp == NULL)
        !           929:                return;
        !           930: 
        !           931:        for (p = pp->head; p; p = p->next) {
        !           932:                printsaproto(pri, p);
        !           933:        }
        !           934: 
        !           935:        return;
        !           936: }
        !           937: 
        !           938: void
        !           939: printsaproto(pri, pr)
        !           940:        const int pri;
        !           941:        const struct saproto *pr;
        !           942: {
        !           943:        struct satrns *tr;
        !           944: 
        !           945:        if (pr == NULL)
        !           946:                return;
        !           947: 
        !           948:        plog(pri, LOCATION, NULL,
        !           949:                " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
        !           950:                "encmode=%s reqid=%d:%d)\n",
        !           951:                s_ipsecdoi_proto(pr->proto_id),
        !           952:                (int)pr->spisize,
        !           953:                (unsigned long)ntohl(pr->spi),
        !           954:                (unsigned long)ntohl(pr->spi_p),
        !           955:                s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE, pr->encmode),
        !           956:                (int)pr->reqid_in, (int)pr->reqid_out);
        !           957: 
        !           958:        for (tr = pr->head; tr; tr = tr->next) {
        !           959:                printsatrns(pri, pr->proto_id, tr);
        !           960:        }
        !           961: 
        !           962:        return;
        !           963: }
        !           964: 
        !           965: void
        !           966: printsatrns(pri, proto_id, tr)
        !           967:        const int pri;
        !           968:        const int proto_id;
        !           969:        const struct satrns *tr;
        !           970: {
        !           971:        if (tr == NULL)
        !           972:                return;
        !           973: 
        !           974:        switch (proto_id) {
        !           975:        case IPSECDOI_PROTO_IPSEC_AH:
        !           976:                plog(pri, LOCATION, NULL,
        !           977:                        "  (trns_id=%s authtype=%s)\n",
        !           978:                        s_ipsecdoi_trns(proto_id, tr->trns_id),
        !           979:                        s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
        !           980:                break;
        !           981:        case IPSECDOI_PROTO_IPSEC_ESP:
        !           982:                plog(pri, LOCATION, NULL,
        !           983:                        "  (trns_id=%s encklen=%d authtype=%s)\n",
        !           984:                        s_ipsecdoi_trns(proto_id, tr->trns_id),
        !           985:                        tr->encklen,
        !           986:                        s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
        !           987:                break;
        !           988:        case IPSECDOI_PROTO_IPCOMP:
        !           989:                plog(pri, LOCATION, NULL,
        !           990:                        "  (trns_id=%s)\n",
        !           991:                        s_ipsecdoi_trns(proto_id, tr->trns_id));
        !           992:                break;
        !           993:        default:
        !           994:                plog(pri, LOCATION, NULL,
        !           995:                        "(unknown proto_id %d)\n", proto_id);
        !           996:        }
        !           997: 
        !           998:        return;
        !           999: }
        !          1000: 
        !          1001: void
        !          1002: print_proppair0(pri, p, level)
        !          1003:        int pri; 
        !          1004:        struct prop_pair *p;
        !          1005:        int level;
        !          1006: {
        !          1007:        char spc[21];
        !          1008: 
        !          1009:        memset(spc, ' ', sizeof(spc));
        !          1010:        spc[sizeof(spc) - 1] = '\0';
        !          1011:        if (level < 20) {
        !          1012:                spc[level] = '\0';
        !          1013:        }
        !          1014: 
        !          1015:        plog(pri, LOCATION, NULL,
        !          1016:                "%s%p: next=%p tnext=%p\n", spc, p, p->next, p->tnext);
        !          1017:        if (p->next)
        !          1018:                print_proppair0(pri, p->next, level + 1);
        !          1019:        if (p->tnext)
        !          1020:                print_proppair0(pri, p->tnext, level + 1);
        !          1021: }
        !          1022: 
        !          1023: void
        !          1024: print_proppair(pri, p)
        !          1025:        int pri;
        !          1026:        struct prop_pair *p;
        !          1027: {
        !          1028:        print_proppair0(pri, p, 1);
        !          1029: }
        !          1030: 
        !          1031: int
        !          1032: set_proposal_from_policy(iph2, sp_main, sp_sub)
        !          1033:        struct ph2handle *iph2;
        !          1034:        struct secpolicy *sp_main, *sp_sub;
        !          1035: {
        !          1036:        struct saprop *newpp;
        !          1037:        struct ipsecrequest *req;
        !          1038:        int encmodesv = IPSECDOI_ATTR_ENC_MODE_TRNS; /* use only when complex_bundle */
        !          1039: 
        !          1040:        newpp = newsaprop();
        !          1041:        if (newpp == NULL) {
        !          1042:                plog(LLV_ERROR, LOCATION, NULL,
        !          1043:                        "failed to allocate saprop.\n");
        !          1044:                goto err;
        !          1045:        }
        !          1046:        newpp->prop_no = 1;
        !          1047:        newpp->lifetime = iph2->sainfo->lifetime;
        !          1048:        newpp->lifebyte = iph2->sainfo->lifebyte;
        !          1049:        newpp->pfs_group = iph2->sainfo->pfs_group;
        !          1050: 
        !          1051:        if (lcconf->complex_bundle)
        !          1052:                goto skip1;
        !          1053: 
        !          1054:        /*
        !          1055:         * decide the encryption mode of this SA bundle.
        !          1056:         * the mode becomes tunnel mode when there is even one policy
        !          1057:         * of tunnel mode in the SPD.  otherwise the mode becomes
        !          1058:         * transport mode.
        !          1059:         */
        !          1060:        for (req = sp_main->req; req; req = req->next) {
        !          1061:                if (req->saidx.mode == IPSEC_MODE_TUNNEL) {
        !          1062:                        encmodesv = pfkey2ipsecdoi_mode(req->saidx.mode);
        !          1063: #ifdef ENABLE_NATT
        !          1064:                        if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
        !          1065:                                encmodesv += iph2->ph1->natt_options->mode_udp_diff;
        !          1066: #endif
        !          1067:                        break;
        !          1068:                }
        !          1069:        }
        !          1070: 
        !          1071:     skip1:
        !          1072:        for (req = sp_main->req; req; req = req->next) {
        !          1073:                struct saproto *newpr;
        !          1074:                caddr_t paddr = NULL;
        !          1075: 
        !          1076:                /*
        !          1077:                 * check if SA bundle ?
        !          1078:                 * nested SAs negotiation is NOT supported.
        !          1079:                 *       me +--- SA1 ---+ peer1
        !          1080:                 *       me +--- SA2 --------------+ peer2
        !          1081:                 */
        !          1082: #ifdef __linux__
        !          1083:                if (req->saidx.src.ss_family && req->saidx.dst.ss_family) {
        !          1084: #else
        !          1085:                if (req->saidx.src.ss_len && req->saidx.dst.ss_len) {
        !          1086: #endif
        !          1087:                        /* check the end of ip addresses of SA */
        !          1088:                        if (iph2->side == INITIATOR)
        !          1089:                                paddr = (caddr_t)&req->saidx.dst;
        !          1090:                        else
        !          1091:                                paddr = (caddr_t)&req->saidx.src;
        !          1092:                }
        !          1093: 
        !          1094:                /* allocate ipsec sa protocol */
        !          1095:                newpr = newsaproto();
        !          1096:                if (newpr == NULL) {
        !          1097:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1098:                                "failed to allocate saproto.\n");
        !          1099:                        goto err;
        !          1100:                }
        !          1101: 
        !          1102:                newpr->proto_id = ipproto2doi(req->saidx.proto);
        !          1103:                if (newpr->proto_id == IPSECDOI_PROTO_IPCOMP)
        !          1104:                        newpr->spisize = 2;
        !          1105:                else
        !          1106:                        newpr->spisize = 4;
        !          1107:                if (lcconf->complex_bundle) {
        !          1108:                        newpr->encmode = pfkey2ipsecdoi_mode(req->saidx.mode);
        !          1109: #ifdef ENABLE_NATT
        !          1110:                        if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
        !          1111:                                newpr->encmode += 
        !          1112:                                    iph2->ph1->natt_options->mode_udp_diff;
        !          1113: #endif
        !          1114:                }
        !          1115:                else
        !          1116:                        newpr->encmode = encmodesv;
        !          1117: 
        !          1118:                if (iph2->side == INITIATOR)
        !          1119:                        newpr->reqid_out = req->saidx.reqid;
        !          1120:                else
        !          1121:                        newpr->reqid_in = req->saidx.reqid;
        !          1122: 
        !          1123:                if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0) {
        !          1124:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1125:                                "failed to get algorithms.\n");
        !          1126:                        racoon_free(newpr);
        !          1127:                        goto err;
        !          1128:                }
        !          1129: 
        !          1130:                /* set new saproto */
        !          1131:                inssaprotorev(newpp, newpr);
        !          1132:        }
        !          1133: 
        !          1134:        /* get reqid_in from inbound policy */
        !          1135:        if (sp_sub) {
        !          1136:                struct saproto *pr;
        !          1137: 
        !          1138:                req = sp_sub->req;
        !          1139:                pr = newpp->head;
        !          1140:                while (req && pr) {
        !          1141:                        if (iph2->side == INITIATOR)
        !          1142:                                pr->reqid_in = req->saidx.reqid;
        !          1143:                        else
        !          1144:                                pr->reqid_out = req->saidx.reqid;
        !          1145:                        pr = pr->next;
        !          1146:                        req = req->next;
        !          1147:                }
        !          1148:                if (pr || req) {
        !          1149:                        plog(LLV_NOTIFY, LOCATION, NULL,
        !          1150:                                "There is a difference "
        !          1151:                                "between the in/out bound policies in SPD.\n");
        !          1152:                }
        !          1153:        }
        !          1154: 
        !          1155:        iph2->proposal = newpp;
        !          1156: 
        !          1157:        printsaprop0(LLV_DEBUG, newpp);
        !          1158: 
        !          1159:        return 0;
        !          1160: err:
        !          1161:        flushsaprop(newpp);
        !          1162:        return -1;
        !          1163: }
        !          1164: 
        !          1165: /*
        !          1166:  * generate a policy from peer's proposal.
        !          1167:  * this function unconditionally choices first proposal in SA payload
        !          1168:  * passed by peer.
        !          1169:  */
        !          1170: int
        !          1171: set_proposal_from_proposal(iph2)
        !          1172:        struct ph2handle *iph2;
        !          1173: {
        !          1174:         struct saprop *newpp = NULL, *pp0, *pp_peer = NULL;
        !          1175:        struct saproto *newpr = NULL, *pr;
        !          1176:        struct prop_pair **pair;
        !          1177:        int error = -1;
        !          1178:        int i;
        !          1179: 
        !          1180:        /* get proposal pair */
        !          1181:        pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
        !          1182:        if (pair == NULL)
        !          1183:                goto end;
        !          1184: 
        !          1185:        /*
        !          1186:         * make my proposal according as the client proposal.
        !          1187:         * XXX assumed there is only one proposal even if it's the SA bundle.
        !          1188:         */
        !          1189:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !          1190:                if (pair[i] == NULL)
        !          1191:                        continue;
        !          1192:                
        !          1193:                if (pp_peer != NULL)
        !          1194:                        flushsaprop(pp_peer);
        !          1195: 
        !          1196:                pp_peer = aproppair2saprop(pair[i]);
        !          1197:                if (pp_peer == NULL)
        !          1198:                        goto end;
        !          1199: 
        !          1200:                pp0 = newsaprop();
        !          1201:                if (pp0 == NULL) {
        !          1202:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1203:                                "failed to allocate saprop.\n");
        !          1204:                        goto end;
        !          1205:                }
        !          1206:                pp0->prop_no = 1;
        !          1207:                pp0->lifetime = iph2->sainfo->lifetime;
        !          1208:                pp0->lifebyte = iph2->sainfo->lifebyte;
        !          1209:                pp0->pfs_group = iph2->sainfo->pfs_group;
        !          1210: 
        !          1211: #ifdef HAVE_SECCTX
        !          1212:                if (*pp_peer->sctx.ctx_str) {
        !          1213:                        pp0->sctx.ctx_doi = pp_peer->sctx.ctx_doi;
        !          1214:                        pp0->sctx.ctx_alg = pp_peer->sctx.ctx_alg;
        !          1215:                        pp0->sctx.ctx_strlen = pp_peer->sctx.ctx_strlen;
        !          1216:                        memcpy(pp0->sctx.ctx_str, pp_peer->sctx.ctx_str,
        !          1217:                               pp_peer->sctx.ctx_strlen);
        !          1218:                }
        !          1219: #endif /* HAVE_SECCTX */
        !          1220: 
        !          1221:                if (pp_peer->next != NULL) {
        !          1222:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1223:                                "pp_peer is inconsistency, ignore it.\n");
        !          1224:                        /*FALLTHROUGH*/
        !          1225:                }
        !          1226: 
        !          1227:                for (pr = pp_peer->head; pr; pr = pr->next)
        !          1228:                {
        !          1229:                        newpr = newsaproto();
        !          1230:                        if (newpr == NULL)
        !          1231:                        {
        !          1232:                                plog(LLV_ERROR, LOCATION, NULL,
        !          1233:                                        "failed to allocate saproto.\n");
        !          1234:                                racoon_free(pp0);
        !          1235:                                goto end;
        !          1236:                        }
        !          1237:                        newpr->proto_id = pr->proto_id;
        !          1238:                        newpr->spisize = pr->spisize;
        !          1239:                        newpr->encmode = pr->encmode;
        !          1240:                        newpr->spi = 0;
        !          1241:                        newpr->spi_p = pr->spi;     /* copy peer's SPI */
        !          1242:                        newpr->reqid_in = 0;
        !          1243:                        newpr->reqid_out = 0;
        !          1244: 
        !          1245:                        if (iph2->ph1->rmconf->gen_policy == GENERATE_POLICY_UNIQUE){
        !          1246:                                newpr->reqid_in = g_nextreqid ;
        !          1247:                                newpr->reqid_out = g_nextreqid ++;
        !          1248:                                /* 
        !          1249:                                 * XXX there is a (very limited) 
        !          1250:                                 * risk of reusing the same reqid
        !          1251:                                 * as another SP entry for the same peer
        !          1252:                                 */
        !          1253:                                if(g_nextreqid >= IPSEC_MANUAL_REQID_MAX)
        !          1254:                                        g_nextreqid = 1;
        !          1255:                        }else{
        !          1256:                                newpr->reqid_in = 0;
        !          1257:                                newpr->reqid_out = 0;
        !          1258:                        }
        !          1259:  
        !          1260:                        if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0)
        !          1261:                        {
        !          1262:                                plog(LLV_ERROR, LOCATION, NULL,
        !          1263:                                        "failed to get algorithms.\n");
        !          1264:                                racoon_free(newpr);
        !          1265:                                racoon_free(pp0);
        !          1266:                                goto end;
        !          1267:                        }
        !          1268:                        inssaproto(pp0, newpr);
        !          1269:                }
        !          1270: 
        !          1271:                inssaprop(&newpp, pp0);
        !          1272:         }
        !          1273: 
        !          1274:        plog(LLV_DEBUG, LOCATION, NULL, "make a proposal from peer's:\n");
        !          1275:        printsaprop0(LLV_DEBUG, newpp);  
        !          1276: 
        !          1277:        iph2->proposal = newpp;
        !          1278: 
        !          1279:        error = 0;
        !          1280: 
        !          1281: end:
        !          1282:        if (error && newpp)
        !          1283:                flushsaprop(newpp);
        !          1284: 
        !          1285:        if (pp_peer)
        !          1286:                flushsaprop(pp_peer);
        !          1287:        if (pair)
        !          1288:                free_proppair(pair);
        !          1289:        return error;
        !          1290: }

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