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

1.1     ! misho       1: /*     $NetBSD: ipsec_doi.c,v 1.46 2010/12/14 17:57:31 tteras Exp $    */
        !             2: 
        !             3: /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu 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/types.h>
        !            37: #include <sys/param.h>
        !            38: #include <sys/socket.h>
        !            39: 
        !            40: #include <netinet/in.h>
        !            41: 
        !            42: #include PATH_IPSEC_H
        !            43: 
        !            44: #include <stdlib.h>
        !            45: #include <stdio.h>
        !            46: #include <string.h>
        !            47: #include <errno.h>
        !            48: #include <netdb.h>
        !            49: #if TIME_WITH_SYS_TIME
        !            50: # include <sys/time.h>
        !            51: # include <time.h>
        !            52: #else
        !            53: # if HAVE_SYS_TIME_H
        !            54: #  include <sys/time.h>
        !            55: # else
        !            56: #  include <time.h>
        !            57: # endif
        !            58: #endif
        !            59: 
        !            60: #include "var.h"
        !            61: #include "vmbuf.h"
        !            62: #include "misc.h"
        !            63: #include "plog.h"
        !            64: #include "debug.h"
        !            65: 
        !            66: #include "cfparse_proto.h"
        !            67: #include "isakmp_var.h"
        !            68: #include "isakmp.h"
        !            69: #include "ipsec_doi.h"
        !            70: #include "oakley.h"
        !            71: #include "remoteconf.h"
        !            72: #include "localconf.h"
        !            73: #include "sockmisc.h"
        !            74: #include "handler.h"
        !            75: #include "policy.h"
        !            76: #include "algorithm.h"
        !            77: #include "sainfo.h"
        !            78: #include "proposal.h"
        !            79: #include "crypto_openssl.h"
        !            80: #include "strnames.h"
        !            81: #include "gcmalloc.h"
        !            82: 
        !            83: #ifdef ENABLE_NATT
        !            84: #include "nattraversal.h"
        !            85: #endif
        !            86: 
        !            87: #ifdef HAVE_GSSAPI
        !            88: #include <iconv.h>
        !            89: #include "gssapi.h"
        !            90: #ifdef HAVE_ICONV_2ND_CONST
        !            91: #define __iconv_const const
        !            92: #else
        !            93: #define __iconv_const
        !            94: #endif
        !            95: #endif
        !            96: 
        !            97: static vchar_t *get_ph1approval __P((struct ph1handle *, u_int32_t, u_int32_t,
        !            98:                                     struct prop_pair **));
        !            99: static int get_ph1approvalx __P((struct remoteconf *, void *));
        !           100: 
        !           101: static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *, u_int32_t));
        !           102: static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
        !           103: static struct prop_pair *get_ph2approval __P((struct ph2handle *,
        !           104:        struct prop_pair **));
        !           105: static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
        !           106:        struct prop_pair *));
        !           107: static void free_proppair0 __P((struct prop_pair *));
        !           108: static struct prop_pair ** get_proppair_and_doi_sit __P((vchar_t *, int,
        !           109:                                                         u_int32_t *, u_int32_t *));
        !           110: 
        !           111: static int get_transform
        !           112:        __P((struct isakmp_pl_p *, struct prop_pair **, int *));
        !           113: static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
        !           114: 
        !           115: static int check_doi __P((u_int32_t));
        !           116: static int check_situation __P((u_int32_t));
        !           117: 
        !           118: static int check_prot_main __P((int));
        !           119: static int check_prot_quick __P((int));
        !           120: static int (*check_protocol[]) __P((int)) = {
        !           121:        check_prot_main,        /* IPSECDOI_TYPE_PH1 */
        !           122:        check_prot_quick,       /* IPSECDOI_TYPE_PH2 */
        !           123: };
        !           124: 
        !           125: static int check_spi_size __P((int, int));
        !           126: 
        !           127: static int check_trns_isakmp __P((int));
        !           128: static int check_trns_ah __P((int));
        !           129: static int check_trns_esp __P((int));
        !           130: static int check_trns_ipcomp __P((int));
        !           131: static int (*check_transform[]) __P((int)) = {
        !           132:        0,
        !           133:        check_trns_isakmp,      /* IPSECDOI_PROTO_ISAKMP */
        !           134:        check_trns_ah,          /* IPSECDOI_PROTO_IPSEC_AH */
        !           135:        check_trns_esp,         /* IPSECDOI_PROTO_IPSEC_ESP */
        !           136:        check_trns_ipcomp,      /* IPSECDOI_PROTO_IPCOMP */
        !           137: };
        !           138: 
        !           139: static int check_attr_isakmp __P((struct isakmp_pl_t *));
        !           140: static int check_attr_ah __P((struct isakmp_pl_t *));
        !           141: static int check_attr_esp __P((struct isakmp_pl_t *));
        !           142: static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
        !           143: static int check_attr_ipcomp __P((struct isakmp_pl_t *));
        !           144: static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
        !           145:        0,
        !           146:        check_attr_isakmp,      /* IPSECDOI_PROTO_ISAKMP */
        !           147:        check_attr_ah,          /* IPSECDOI_PROTO_IPSEC_AH */
        !           148:        check_attr_esp,         /* IPSECDOI_PROTO_IPSEC_ESP */
        !           149:        check_attr_ipcomp,      /* IPSECDOI_PROTO_IPCOMP */
        !           150: };
        !           151: 
        !           152: static int setph1prop __P((struct isakmpsa *, caddr_t));
        !           153: static int setph1trns __P((struct isakmpsa *, caddr_t));
        !           154: static int setph1attr __P((struct isakmpsa *, caddr_t));
        !           155: static vchar_t *setph2proposal0 __P((const struct ph2handle *,
        !           156:        const struct saprop *, const struct saproto *));
        !           157: 
        !           158: struct ph1approvalx_ctx {
        !           159:        struct prop_pair *p;
        !           160:        struct isakmpsa *sa;
        !           161: };
        !           162: 
        !           163: /*%%%*/
        !           164: /*
        !           165:  * check phase 1 SA payload.
        !           166:  * make new SA payload to be replyed not including general header.
        !           167:  * the pointer to one of isakmpsa in proposal is set into iph1->approval.
        !           168:  * OUT:
        !           169:  *     positive: the pointer to new buffer of SA payload.
        !           170:  *               network byte order.
        !           171:  *     NULL    : error occurd.
        !           172:  */
        !           173: int
        !           174: ipsecdoi_checkph1proposal(sa, iph1)
        !           175:        vchar_t *sa;
        !           176:        struct ph1handle *iph1;
        !           177: {
        !           178:        vchar_t *newsa;         /* new SA payload approved. */
        !           179:        struct prop_pair **pair;
        !           180:        u_int32_t doitype, sittype;
        !           181: 
        !           182:        /* get proposal pair */
        !           183:        pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1,
        !           184:                                        &doitype, &sittype);
        !           185:        if (pair == NULL)
        !           186:                return -1;
        !           187: 
        !           188:        /* check and get one SA for use */
        !           189:        newsa = get_ph1approval(iph1, doitype, sittype, pair);
        !           190:        free_proppair(pair);
        !           191: 
        !           192:        if (newsa == NULL)
        !           193:                return -1;
        !           194: 
        !           195:        iph1->sa_ret = newsa;
        !           196:        return 0;
        !           197: }
        !           198: 
        !           199: static void
        !           200: print_ph1proposal(pair, s)
        !           201:        struct prop_pair *pair;
        !           202:        struct isakmpsa *s;
        !           203: {
        !           204:        struct isakmp_pl_p *prop = pair->prop;
        !           205:        struct isakmp_pl_t *trns = pair->trns;
        !           206: 
        !           207:        plog(LLV_DEBUG, LOCATION, NULL,
        !           208:             "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
        !           209:             prop->p_no, s_ipsecdoi_proto(prop->proto_id),
        !           210:             prop->spi_size, prop->num_t);
        !           211:        plog(LLV_DEBUG, LOCATION, NULL,
        !           212:             "trns#=%d, trns-id=%s\n",
        !           213:             trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id));
        !           214:        plog(LLV_DEBUG, LOCATION, NULL,
        !           215:             "  lifetime = %ld\n", (long) s->lifetime);
        !           216:        plog(LLV_DEBUG, LOCATION, NULL,
        !           217:             "  lifebyte = %zu\n", s->lifebyte);
        !           218:        plog(LLV_DEBUG, LOCATION, NULL,
        !           219:             "  enctype = %s\n",
        !           220:             s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype));
        !           221:        plog(LLV_DEBUG, LOCATION, NULL,
        !           222:             "  encklen = %d\n", s->encklen);
        !           223:        plog(LLV_DEBUG, LOCATION, NULL,
        !           224:             "  hashtype = %s\n",
        !           225:             s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype));
        !           226:        plog(LLV_DEBUG, LOCATION, NULL,
        !           227:             "  authmethod = %s\n",
        !           228:             s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod));
        !           229:        plog(LLV_DEBUG, LOCATION, NULL,
        !           230:             "  dh_group = %s\n",
        !           231:             s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group));
        !           232: }
        !           233: 
        !           234: 
        !           235: /*
        !           236:  * acceptable check for remote configuration.
        !           237:  * return a new SA payload to be reply to peer.
        !           238:  */
        !           239: 
        !           240: static vchar_t *
        !           241: get_ph1approval(iph1, doitype, sittype, pair)
        !           242:        struct ph1handle *iph1;
        !           243:        u_int32_t doitype, sittype;
        !           244:        struct prop_pair **pair;
        !           245: {
        !           246:        vchar_t *newsa;
        !           247:        struct ph1approvalx_ctx ctx;
        !           248:        struct prop_pair *s, *p;
        !           249:        struct rmconfselector rmsel;
        !           250:        struct isakmpsa *sa;
        !           251:        int i;
        !           252: 
        !           253:        memset(&rmsel, 0, sizeof(rmsel));
        !           254:        rmsel.remote = iph1->remote;
        !           255: 
        !           256:        if (iph1->approval) {
        !           257:                delisakmpsa(iph1->approval);
        !           258:                iph1->approval = NULL;
        !           259:        }
        !           260: 
        !           261:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !           262:                if (pair[i] == NULL)
        !           263:                        continue;
        !           264:                for (s = pair[i]; s; s = s->next) {
        !           265:                        /* compare proposal and select one */
        !           266:                        for (p = s; p; p = p->tnext) {
        !           267:                                struct isakmp_pl_p *prop = p->prop;
        !           268: 
        !           269:                                sa = newisakmpsa();
        !           270:                                ctx.p = p;
        !           271:                                ctx.sa = sa;
        !           272:                                if (t2isakmpsa(p->trns, sa,
        !           273:                                               iph1->vendorid_mask) < 0)
        !           274:                                        continue;
        !           275:                                print_ph1proposal(p, sa);
        !           276:                                if (iph1->rmconf != NULL) {
        !           277:                                        if (get_ph1approvalx(iph1->rmconf, &ctx))
        !           278:                                                goto found;
        !           279:                                } else {
        !           280:                                        if (enumrmconf(&rmsel, get_ph1approvalx, &ctx))
        !           281:                                                goto found;
        !           282:                                }
        !           283:                                delisakmpsa(sa);
        !           284:                        }
        !           285:                }
        !           286:        }
        !           287: 
        !           288:        plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
        !           289: 
        !           290:        return NULL;
        !           291: 
        !           292: found:
        !           293:        sa = ctx.sa;
        !           294:        plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
        !           295: 
        !           296:        /* check DH group settings */
        !           297:        if (sa->dhgrp) {
        !           298:                if (sa->dhgrp->prime && sa->dhgrp->gen1) {
        !           299:                        /* it's ok */
        !           300:                        goto saok;
        !           301:                }
        !           302:                plog(LLV_WARNING, LOCATION, NULL,
        !           303:                        "invalid DH parameter found, use default.\n");
        !           304:                oakley_dhgrp_free(sa->dhgrp);
        !           305:                sa->dhgrp=NULL;
        !           306:        }
        !           307: 
        !           308:        if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
        !           309:                sa->dhgrp = NULL;
        !           310:                delisakmpsa(sa);
        !           311:                return NULL;
        !           312:        }
        !           313: 
        !           314: saok:
        !           315: #ifdef HAVE_GSSAPI
        !           316:        if (sa->gssid != NULL)
        !           317:                plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
        !           318:                    (int)sa->gssid->l, sa->gssid->v);
        !           319:        if (iph1->side == INITIATOR) {
        !           320:                if (iph1->rmconf->proposal->gssid != NULL)
        !           321:                        iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
        !           322:                if (sa->gssid != NULL)
        !           323:                        iph1->gi_r = vdup(sa->gssid);
        !           324:        } else {
        !           325:                if (sa->gssid != NULL) {
        !           326:                        iph1->gi_r = vdup(sa->gssid);
        !           327:                        iph1->gi_i = gssapi_get_id(iph1);
        !           328:                }
        !           329:        }
        !           330:        if (iph1->gi_i != NULL)
        !           331:                plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
        !           332:                    (int)iph1->gi_i->l, iph1->gi_i->v);
        !           333:        if (iph1->gi_r != NULL)
        !           334:                plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
        !           335:                    (int)iph1->gi_r->l, iph1->gi_r->v);
        !           336: #endif
        !           337:        plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
        !           338:             s_oakley_attr_method(sa->authmethod));
        !           339: 
        !           340:        newsa = get_sabyproppair(doitype, sittype, p);
        !           341:        if (newsa == NULL)
        !           342:                delisakmpsa(sa);
        !           343:        else
        !           344:                iph1->approval = sa;
        !           345: 
        !           346:        return newsa;
        !           347: }
        !           348: 
        !           349: /*
        !           350:  * compare peer's single proposal and all of my proposal.
        !           351:  * and select one if suiatable.
        !           352:  */
        !           353: static int
        !           354: get_ph1approvalx(rmconf, ctx)
        !           355:        struct remoteconf *rmconf;
        !           356:        void *ctx;
        !           357: {
        !           358:        struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx;
        !           359:        struct isakmpsa *sa;
        !           360: 
        !           361:        /* do the hard work */
        !           362:        sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal);
        !           363:        if (sa == NULL)
        !           364:                return 0;
        !           365: 
        !           366:        /* duplicate and modify the found SA to match proposal */
        !           367:        sa = dupisakmpsa(sa);
        !           368: 
        !           369:        switch (rmconf->pcheck_level) {
        !           370:        case PROP_CHECK_OBEY:
        !           371:                sa->lifetime = pctx->sa->lifetime;
        !           372:                sa->lifebyte = pctx->sa->lifebyte;
        !           373:                sa->encklen = pctx->sa->encklen;
        !           374:                break;
        !           375:        case PROP_CHECK_CLAIM:
        !           376:        case PROP_CHECK_STRICT:
        !           377:                if (pctx->sa->lifetime < sa->lifetime)
        !           378:                        sa->lifetime = pctx->sa->lifetime;
        !           379:                if (pctx->sa->lifebyte < sa->lifebyte)
        !           380:                        sa->lifebyte = pctx->sa->lifebyte;
        !           381:                if (pctx->sa->encklen > sa->encklen)
        !           382:                        sa->encklen = pctx->sa->encklen;
        !           383:                break;
        !           384:        default:
        !           385:                break;
        !           386:        }
        !           387: 
        !           388:        /* replace the proposal with our approval sa */
        !           389:        delisakmpsa(pctx->sa);
        !           390:        pctx->sa = sa;
        !           391: 
        !           392:        return 1;
        !           393: }
        !           394: 
        !           395: /*
        !           396:  * get ISAKMP data attributes
        !           397:  */
        !           398: static int
        !           399: t2isakmpsa(trns, sa, vendorid_mask)
        !           400:        struct isakmp_pl_t *trns;
        !           401:        struct isakmpsa *sa;
        !           402:        u_int32_t vendorid_mask;
        !           403: {
        !           404:        struct isakmp_data *d, *prev;
        !           405:        int flag, type;
        !           406:        int error = -1;
        !           407:        int life_t;
        !           408:        int keylen = 0;
        !           409:        vchar_t *val = NULL;
        !           410:        int len, tlen;
        !           411:        u_char *p;
        !           412: 
        !           413:        tlen = ntohs(trns->h.len) - sizeof(*trns);
        !           414:        prev = (struct isakmp_data *)NULL;
        !           415:        d = (struct isakmp_data *)(trns + 1);
        !           416: 
        !           417:        /* default */
        !           418:        life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
        !           419:        sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
        !           420:        sa->lifebyte = 0;
        !           421:        sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
        !           422:        if (!sa->dhgrp)
        !           423:                goto err;
        !           424: 
        !           425:        while (tlen > 0) {
        !           426: 
        !           427:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
        !           428:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
        !           429: 
        !           430:                plog(LLV_DEBUG, LOCATION, NULL,
        !           431:                        "type=%s, flag=0x%04x, lorv=%s\n",
        !           432:                        s_oakley_attr(type), flag,
        !           433:                        s_oakley_attr_v(type, ntohs(d->lorv)));
        !           434: 
        !           435:                /* get variable-sized item */
        !           436:                switch (type) {
        !           437:                case OAKLEY_ATTR_GRP_PI:
        !           438:                case OAKLEY_ATTR_GRP_GEN_ONE:
        !           439:                case OAKLEY_ATTR_GRP_GEN_TWO:
        !           440:                case OAKLEY_ATTR_GRP_CURVE_A:
        !           441:                case OAKLEY_ATTR_GRP_CURVE_B:
        !           442:                case OAKLEY_ATTR_SA_LD:
        !           443:                case OAKLEY_ATTR_GRP_ORDER:
        !           444:                        if (flag) {     /*TV*/
        !           445:                                len = 2;
        !           446:                                p = (u_char *)&d->lorv;
        !           447:                        } else {        /*TLV*/
        !           448:                                len = ntohs(d->lorv);
        !           449:                                p = (u_char *)(d + 1);
        !           450:                        }
        !           451:                        val = vmalloc(len);
        !           452:                        if (!val)
        !           453:                                return -1;
        !           454:                        memcpy(val->v, p, len);
        !           455:                        break;
        !           456: 
        !           457:                default:
        !           458:                        break;
        !           459:                }
        !           460: 
        !           461:                switch (type) {
        !           462:                case OAKLEY_ATTR_ENC_ALG:
        !           463:                        sa->enctype = (u_int16_t)ntohs(d->lorv);
        !           464:                        break;
        !           465: 
        !           466:                case OAKLEY_ATTR_HASH_ALG:
        !           467:                        sa->hashtype = (u_int16_t)ntohs(d->lorv);
        !           468:                        break;
        !           469: 
        !           470:                case OAKLEY_ATTR_AUTH_METHOD:
        !           471:                        sa->authmethod = ntohs(d->lorv);
        !           472: #ifdef HAVE_GSSAPI
        !           473:                        if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL &&
        !           474:                            (vendorid_mask & VENDORID_GSSAPI_MASK))
        !           475:                                sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB;
        !           476: #endif
        !           477:                        break;
        !           478: 
        !           479:                case OAKLEY_ATTR_GRP_DESC:
        !           480:                        sa->dh_group = (u_int16_t)ntohs(d->lorv);
        !           481:                        break;
        !           482: 
        !           483:                case OAKLEY_ATTR_GRP_TYPE:
        !           484:                {
        !           485:                        int type = (int)ntohs(d->lorv);
        !           486:                        if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
        !           487:                                sa->dhgrp->type = type;
        !           488:                        else
        !           489:                                return -1;
        !           490:                        break;
        !           491:                }
        !           492:                case OAKLEY_ATTR_GRP_PI:
        !           493:                        sa->dhgrp->prime = val;
        !           494:                        break;
        !           495: 
        !           496:                case OAKLEY_ATTR_GRP_GEN_ONE:
        !           497:                        vfree(val);
        !           498:                        if (!flag)
        !           499:                                sa->dhgrp->gen1 = ntohs(d->lorv);
        !           500:                        else {
        !           501:                                int len = ntohs(d->lorv);
        !           502:                                sa->dhgrp->gen1 = 0;
        !           503:                                if (len > 4)
        !           504:                                        return -1;
        !           505:                                memcpy(&sa->dhgrp->gen1, d + 1, len);
        !           506:                                sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
        !           507:                        }
        !           508:                        break;
        !           509: 
        !           510:                case OAKLEY_ATTR_GRP_GEN_TWO:
        !           511:                        vfree(val);
        !           512:                        if (!flag)
        !           513:                                sa->dhgrp->gen2 = ntohs(d->lorv);
        !           514:                        else {
        !           515:                                int len = ntohs(d->lorv);
        !           516:                                sa->dhgrp->gen2 = 0;
        !           517:                                if (len > 4)
        !           518:                                        return -1;
        !           519:                                memcpy(&sa->dhgrp->gen2, d + 1, len);
        !           520:                                sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
        !           521:                        }
        !           522:                        break;
        !           523: 
        !           524:                case OAKLEY_ATTR_GRP_CURVE_A:
        !           525:                        sa->dhgrp->curve_a = val;
        !           526:                        break;
        !           527: 
        !           528:                case OAKLEY_ATTR_GRP_CURVE_B:
        !           529:                        sa->dhgrp->curve_b = val;
        !           530:                        break;
        !           531: 
        !           532:                case OAKLEY_ATTR_SA_LD_TYPE:
        !           533:                {
        !           534:                        int type = (int)ntohs(d->lorv);
        !           535:                        switch (type) {
        !           536:                        case OAKLEY_ATTR_SA_LD_TYPE_SEC:
        !           537:                        case OAKLEY_ATTR_SA_LD_TYPE_KB:
        !           538:                                life_t = type;
        !           539:                                break;
        !           540:                        default:
        !           541:                                life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
        !           542:                                break;
        !           543:                        }
        !           544:                        break;
        !           545:                }
        !           546:                case OAKLEY_ATTR_SA_LD:
        !           547:                        if (!prev
        !           548:                         || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
        !           549:                                        OAKLEY_ATTR_SA_LD_TYPE) {
        !           550:                                plog(LLV_ERROR, LOCATION, NULL,
        !           551:                                    "life duration must follow ltype\n");
        !           552:                                break;
        !           553:                        }
        !           554: 
        !           555:                        switch (life_t) {
        !           556:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
        !           557:                                sa->lifetime = ipsecdoi_set_ld(val);
        !           558:                                vfree(val);
        !           559:                                if (sa->lifetime == 0) {
        !           560:                                        plog(LLV_ERROR, LOCATION, NULL,
        !           561:                                                "invalid life duration.\n");
        !           562:                                        goto err;
        !           563:                                }
        !           564:                                break;
        !           565:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
        !           566:                                sa->lifebyte = ipsecdoi_set_ld(val);
        !           567:                                vfree(val);
        !           568:                                if (sa->lifebyte == 0) {
        !           569:                                        plog(LLV_ERROR, LOCATION, NULL,
        !           570:                                                "invalid life duration.\n");
        !           571:                                        goto err;
        !           572:                                }
        !           573:                                break;
        !           574:                        default:
        !           575:                                vfree(val);
        !           576:                                plog(LLV_ERROR, LOCATION, NULL,
        !           577:                                        "invalid life type: %d\n", life_t);
        !           578:                                goto err;
        !           579:                        }
        !           580:                        break;
        !           581: 
        !           582:                case OAKLEY_ATTR_KEY_LEN:
        !           583:                {
        !           584:                        int len = ntohs(d->lorv);
        !           585:                        if (len % 8 != 0) {
        !           586:                                plog(LLV_ERROR, LOCATION, NULL,
        !           587:                                        "keylen %d: not multiple of 8\n",
        !           588:                                        len);
        !           589:                                goto err;
        !           590:                        }
        !           591:                        sa->encklen = (u_int16_t)len;
        !           592:                        keylen++;
        !           593:                        break;
        !           594:                }
        !           595:                case OAKLEY_ATTR_PRF:
        !           596:                case OAKLEY_ATTR_FIELD_SIZE:
        !           597:                        /* unsupported */
        !           598:                        break;
        !           599: 
        !           600:                case OAKLEY_ATTR_GRP_ORDER:
        !           601:                        sa->dhgrp->order = val;
        !           602:                        break;
        !           603: #ifdef HAVE_GSSAPI
        !           604:                case OAKLEY_ATTR_GSS_ID:
        !           605:                {
        !           606:                        int error = -1;
        !           607:                        iconv_t cd = (iconv_t) -1;
        !           608:                        size_t srcleft, dstleft, rv;
        !           609:                        __iconv_const char *src;
        !           610:                        char *dst;
        !           611:                        int len = ntohs(d->lorv);
        !           612: 
        !           613:                        /*
        !           614:                         * Older verions of racoon just placed the
        !           615:                         * ISO-Latin-1 string on the wire directly.
        !           616:                         * Check to see if we are configured to be
        !           617:                         * compatible with this behavior.
        !           618:                         */
        !           619:                        if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
        !           620:                                if ((sa->gssid = vmalloc(len)) == NULL) {
        !           621:                                        plog(LLV_ERROR, LOCATION, NULL,
        !           622:                                            "failed to allocate memory\n");
        !           623:                                        goto out;
        !           624:                                }
        !           625:                                memcpy(sa->gssid->v, d + 1, len);
        !           626:                                plog(LLV_DEBUG, LOCATION, NULL,
        !           627:                                    "received old-style gss "
        !           628:                                    "id '%.*s' (len %zu)\n",
        !           629:                                    (int)sa->gssid->l, sa->gssid->v,
        !           630:                                    sa->gssid->l);
        !           631:                                error = 0;
        !           632:                                goto out;
        !           633:                        }
        !           634: 
        !           635:                        /*
        !           636:                         * For Windows 2000 compatibility, we expect
        !           637:                         * the GSS ID attribute on the wire to be
        !           638:                         * encoded in UTF-16LE.  Internally, we work
        !           639:                         * in ISO-Latin-1.  Therefore, we should need
        !           640:                         * 1/2 the specified length, which should always
        !           641:                         * be a multiple of 2 octets.
        !           642:                         */
        !           643:                        cd = iconv_open("latin1", "utf-16le");
        !           644:                        if (cd == (iconv_t) -1) {
        !           645:                                plog(LLV_ERROR, LOCATION, NULL,
        !           646:                                    "unable to initialize utf-16le -> latin1 "
        !           647:                                    "conversion descriptor: %s\n",
        !           648:                                    strerror(errno));
        !           649:                                goto out;
        !           650:                        }
        !           651: 
        !           652:                        if ((sa->gssid = vmalloc(len / 2)) == NULL) {
        !           653:                                plog(LLV_ERROR, LOCATION, NULL,
        !           654:                                    "failed to allocate memory\n");
        !           655:                                goto out;
        !           656:                        }
        !           657: 
        !           658:                        src = (__iconv_const char *)(d + 1);
        !           659:                        srcleft = len;
        !           660: 
        !           661:                        dst = sa->gssid->v;
        !           662:                        dstleft = len / 2;
        !           663: 
        !           664:                        rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
        !           665:                                   &dst, &dstleft);
        !           666:                        if (rv != 0) {
        !           667:                                if (rv == -1) {
        !           668:                                        plog(LLV_ERROR, LOCATION, NULL,
        !           669:                                            "unable to convert GSS ID from "
        !           670:                                            "utf-16le -> latin1: %s\n",
        !           671:                                            strerror(errno));
        !           672:                                } else {
        !           673:                                        plog(LLV_ERROR, LOCATION, NULL,
        !           674:                                            "%zd character%s in GSS ID cannot "
        !           675:                                            "be represented in latin1\n",
        !           676:                                            rv, rv == 1 ? "" : "s");
        !           677:                                }
        !           678:                                goto out;
        !           679:                        }
        !           680: 
        !           681:                        /* XXX dstleft should always be 0; assert it? */
        !           682:                        sa->gssid->l = (len / 2) - dstleft;
        !           683: 
        !           684:                        plog(LLV_DEBUG, LOCATION, NULL,
        !           685:                            "received gss id '%.*s' (len %zu)\n",
        !           686:                            (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
        !           687: 
        !           688:                        error = 0;
        !           689: out:
        !           690:                        if (cd != (iconv_t)-1)
        !           691:                                (void)iconv_close(cd);
        !           692: 
        !           693:                        if ((error != 0) && (sa->gssid != NULL)) {
        !           694:                                vfree(sa->gssid);
        !           695:                                sa->gssid = NULL;
        !           696:                        }
        !           697:                        break;
        !           698:                }
        !           699: #endif /* HAVE_GSSAPI */
        !           700: 
        !           701:                default:
        !           702:                        break;
        !           703:                }
        !           704: 
        !           705:                prev = d;
        !           706:                if (flag) {
        !           707:                        tlen -= sizeof(*d);
        !           708:                        d = (struct isakmp_data *)((char *)d + sizeof(*d));
        !           709:                } else {
        !           710:                        tlen -= (sizeof(*d) + ntohs(d->lorv));
        !           711:                        d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
        !           712:                }
        !           713:        }
        !           714: 
        !           715:        /* key length must not be specified on some algorithms */
        !           716:        if (keylen) {
        !           717:                if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
        !           718: #ifdef HAVE_OPENSSL_IDEA_H
        !           719:                 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
        !           720: #endif
        !           721:                 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
        !           722:                        plog(LLV_ERROR, LOCATION, NULL,
        !           723:                                "keylen must not be specified "
        !           724:                                "for encryption algorithm %d\n",
        !           725:                                sa->enctype);
        !           726:                        return -1;
        !           727:                }
        !           728:        }
        !           729: 
        !           730:        return 0;
        !           731: err:
        !           732:        return error;
        !           733: }
        !           734: 
        !           735: /*%%%*/
        !           736: /*
        !           737:  * check phase 2 SA payload and select single proposal.
        !           738:  * make new SA payload to be replyed not including general header.
        !           739:  * This function is called by responder only.
        !           740:  * OUT:
        !           741:  *     0: succeed.
        !           742:  *     -1: error occured.
        !           743:  */
        !           744: int
        !           745: ipsecdoi_selectph2proposal(iph2)
        !           746:        struct ph2handle *iph2;
        !           747: {
        !           748:        struct prop_pair **pair;
        !           749:        struct prop_pair *ret;
        !           750:        u_int32_t doitype, sittype;
        !           751: 
        !           752:        /* get proposal pair */
        !           753:        pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
        !           754:                                        &doitype, &sittype);
        !           755:        if (pair == NULL)
        !           756:                return -1;
        !           757: 
        !           758:        /* check and select a proposal. */
        !           759:        ret = get_ph2approval(iph2, pair);
        !           760:        free_proppair(pair);
        !           761:        if (ret == NULL)
        !           762:                return -1;
        !           763: 
        !           764:        /* make a SA to be replayed. */
        !           765:        /* SPI must be updated later. */
        !           766:        iph2->sa_ret = get_sabyproppair(doitype, sittype, ret);
        !           767:        free_proppair0(ret);
        !           768:        if (iph2->sa_ret == NULL)
        !           769:                return -1;
        !           770: 
        !           771:        return 0;
        !           772: }
        !           773: 
        !           774: /*
        !           775:  * check phase 2 SA payload returned from responder.
        !           776:  * This function is called by initiator only.
        !           777:  * OUT:
        !           778:  *     0: valid.
        !           779:  *     -1: invalid.
        !           780:  */
        !           781: int
        !           782: ipsecdoi_checkph2proposal(iph2)
        !           783:        struct ph2handle *iph2;
        !           784: {
        !           785:        struct prop_pair **rpair = NULL, **spair = NULL;
        !           786:        struct prop_pair *p;
        !           787:        int i, n, num;
        !           788:        int error = -1;
        !           789:        vchar_t *sa_ret = NULL;
        !           790:        u_int32_t doitype, sittype;
        !           791: 
        !           792:        /* get proposal pair of SA sent. */
        !           793:        spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
        !           794:                                         &doitype, &sittype);
        !           795:        if (spair == NULL) {
        !           796:                plog(LLV_ERROR, LOCATION, NULL,
        !           797:                        "failed to get prop pair.\n");
        !           798:                goto end;
        !           799:        }
        !           800: 
        !           801:        /* XXX should check the number of transform */
        !           802: 
        !           803:        /* get proposal pair of SA replayed */
        !           804:        rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
        !           805:        if (rpair == NULL) {
        !           806:                plog(LLV_ERROR, LOCATION, NULL,
        !           807:                        "failed to get prop pair.\n");
        !           808:                goto end;
        !           809:        }
        !           810: 
        !           811:        /* check proposal is only one ? */
        !           812:        n = 0;
        !           813:        num = 0;
        !           814:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !           815:                if (rpair[i]) {
        !           816:                        n = i;
        !           817:                        num++;
        !           818:                }
        !           819:        }
        !           820:        if (num == 0) {
        !           821:                plog(LLV_ERROR, LOCATION, NULL,
        !           822:                        "no proposal received.\n");
        !           823:                goto end;
        !           824:        }
        !           825:        if (num != 1) {
        !           826:                plog(LLV_ERROR, LOCATION, NULL,
        !           827:                        "some proposals received.\n");
        !           828:                goto end;
        !           829:        }
        !           830: 
        !           831:        if (spair[n] == NULL) {
        !           832:                plog(LLV_WARNING, LOCATION, NULL,
        !           833:                        "invalid proposal number:%d received.\n", i);
        !           834:        }
        !           835: 
        !           836: 
        !           837:        if (rpair[n]->tnext != NULL) {
        !           838:                plog(LLV_ERROR, LOCATION, NULL,
        !           839:                        "multi transforms replyed.\n");
        !           840:                goto end;
        !           841:        }
        !           842: 
        !           843:        if (cmp_aproppair_i(rpair[n], spair[n])) {
        !           844:                plog(LLV_ERROR, LOCATION, NULL,
        !           845:                        "proposal mismathed.\n");
        !           846:                goto end;
        !           847:        }
        !           848: 
        !           849:        /*
        !           850:         * check and select a proposal.
        !           851:         * ensure that there is no modification of the proposal by
        !           852:         * cmp_aproppair_i()
        !           853:         */
        !           854:        p = get_ph2approval(iph2, rpair);
        !           855:        if (p == NULL)
        !           856:                goto end;
        !           857: 
        !           858:        /* make a SA to be replayed. */
        !           859:        sa_ret = iph2->sa_ret;
        !           860:        iph2->sa_ret = get_sabyproppair(doitype, sittype, p);
        !           861:        free_proppair0(p);
        !           862:        if (iph2->sa_ret == NULL)
        !           863:                goto end;
        !           864: 
        !           865:        error = 0;
        !           866: 
        !           867: end:
        !           868:        if (rpair)
        !           869:                free_proppair(rpair);
        !           870:        if (spair)
        !           871:                free_proppair(spair);
        !           872:        if (sa_ret)
        !           873:                vfree(sa_ret);
        !           874: 
        !           875:        return error;
        !           876: }
        !           877: 
        !           878: /*
        !           879:  * compare two prop_pair which is assumed to have same proposal number.
        !           880:  * the case of bundle or single SA, NOT multi transforms.
        !           881:  * a: a proposal that is multi protocols and single transform, usually replyed.
        !           882:  * b: a proposal that is multi protocols and multi transform, usually sent.
        !           883:  * NOTE: this function is for initiator.
        !           884:  * OUT
        !           885:  *     0: equal
        !           886:  *     1: not equal
        !           887:  * XXX cannot understand the comment!
        !           888:  */
        !           889: static int
        !           890: cmp_aproppair_i(a, b)
        !           891:        struct prop_pair *a, *b;
        !           892: {
        !           893:        struct prop_pair *p, *q, *r;
        !           894:        int len;
        !           895: 
        !           896:        for (p = a, q = b; p && q; p = p->next, q = q->next) {
        !           897:                for (r = q; r; r = r->tnext) {
        !           898:                        /* compare trns */
        !           899:                        if (p->trns->t_no == r->trns->t_no)
        !           900:                                break;
        !           901:                }
        !           902:                if (!r) {
        !           903:                        /* no suitable transform found */
        !           904:                        plog(LLV_ERROR, LOCATION, NULL,
        !           905:                                "no suitable transform found.\n");
        !           906:                        return -1;
        !           907:                }
        !           908: 
        !           909:                /* compare prop */
        !           910:                if (p->prop->p_no != r->prop->p_no) {
        !           911:                        plog(LLV_WARNING, LOCATION, NULL,
        !           912:                                "proposal #%d mismatched, "
        !           913:                                "expected #%d.\n",
        !           914:                                r->prop->p_no, p->prop->p_no);
        !           915:                        /*FALLTHROUGH*/
        !           916:                }
        !           917: 
        !           918:                if (p->prop->proto_id != r->prop->proto_id) {
        !           919:                        plog(LLV_ERROR, LOCATION, NULL,
        !           920:                                "proto_id mismathed: my:%d peer:%d\n",
        !           921:                                r->prop->proto_id, p->prop->proto_id);
        !           922:                        return -1;
        !           923:                }
        !           924: 
        !           925:                if (p->prop->spi_size != r->prop->spi_size) {
        !           926:                        plog(LLV_ERROR, LOCATION, NULL,
        !           927:                                "invalid spi size: %d.\n",
        !           928:                                p->prop->spi_size);
        !           929:                        return -1;
        !           930:                }
        !           931: 
        !           932:                /* check #of transforms */
        !           933:                if (p->prop->num_t != 1) {
        !           934:                        plog(LLV_WARNING, LOCATION, NULL,
        !           935:                                "#of transform is %d, "
        !           936:                                "but expected 1.\n", p->prop->num_t);
        !           937:                        /*FALLTHROUGH*/
        !           938:                }
        !           939: 
        !           940:                if (p->trns->t_id != r->trns->t_id) {
        !           941:                        plog(LLV_WARNING, LOCATION, NULL,
        !           942:                                "transform number has been modified.\n");
        !           943:                        /*FALLTHROUGH*/
        !           944:                }
        !           945:                if (p->trns->reserved != r->trns->reserved) {
        !           946:                        plog(LLV_WARNING, LOCATION, NULL,
        !           947:                                "reserved field should be zero.\n");
        !           948:                        /*FALLTHROUGH*/
        !           949:                }
        !           950: 
        !           951:                /* compare attribute */
        !           952:                len = ntohs(r->trns->h.len) - sizeof(*p->trns);
        !           953:                if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
        !           954:                        plog(LLV_WARNING, LOCATION, NULL,
        !           955:                                "attribute has been modified.\n");
        !           956:                        /*FALLTHROUGH*/
        !           957:                }
        !           958:        }
        !           959:        if ((p && !q) || (!p && q)) {
        !           960:                /* # of protocols mismatched */
        !           961:                plog(LLV_ERROR, LOCATION, NULL,
        !           962:                        "#of protocols mismatched.\n");
        !           963:                return -1;
        !           964:        }
        !           965: 
        !           966:        return 0;
        !           967: }
        !           968: 
        !           969: /*
        !           970:  * acceptable check for policy configuration.
        !           971:  * return a new SA payload to be reply to peer.
        !           972:  */
        !           973: static struct prop_pair *
        !           974: get_ph2approval(iph2, pair)
        !           975:        struct ph2handle *iph2;
        !           976:        struct prop_pair **pair;
        !           977: {
        !           978:        struct prop_pair *ret;
        !           979:        int i;
        !           980: 
        !           981:        iph2->approval = NULL;
        !           982: 
        !           983:        plog(LLV_DEBUG, LOCATION, NULL,
        !           984:                "begin compare proposals.\n");
        !           985: 
        !           986:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !           987:                if (pair[i] == NULL)
        !           988:                        continue;
        !           989:                plog(LLV_DEBUG, LOCATION, NULL,
        !           990:                        "pair[%d]: %p\n", i, pair[i]);
        !           991:                print_proppair(LLV_DEBUG, pair[i]);;
        !           992: 
        !           993:                /* compare proposal and select one */
        !           994:                ret = get_ph2approvalx(iph2, pair[i]);
        !           995:                if (ret != NULL) {
        !           996:                        /* found */
        !           997:                        return ret;
        !           998:                }
        !           999:        }
        !          1000: 
        !          1001:        plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
        !          1002: 
        !          1003:        return NULL;
        !          1004: }
        !          1005: 
        !          1006: /*
        !          1007:  * compare my proposal and peers just one proposal.
        !          1008:  * set a approval.
        !          1009:  */
        !          1010: static struct prop_pair *
        !          1011: get_ph2approvalx(iph2, pp)
        !          1012:        struct ph2handle *iph2;
        !          1013:        struct prop_pair *pp;
        !          1014: {
        !          1015:        struct prop_pair *ret = NULL;
        !          1016:        struct saprop *pr0, *pr = NULL;
        !          1017:        struct saprop *q1, *q2;
        !          1018: 
        !          1019:        pr0 = aproppair2saprop(pp);
        !          1020:        if (pr0 == NULL)
        !          1021:                return NULL;
        !          1022: 
        !          1023:        for (q1 = pr0; q1; q1 = q1->next) {
        !          1024:                for (q2 = iph2->proposal; q2; q2 = q2->next) {
        !          1025:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1026:                                "peer's single bundle:\n");
        !          1027:                        printsaprop0(LLV_DEBUG, q1);
        !          1028:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1029:                                "my single bundle:\n");
        !          1030:                        printsaprop0(LLV_DEBUG, q2);
        !          1031: 
        !          1032:                        pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
        !          1033:                        if (pr != NULL)
        !          1034:                                goto found;
        !          1035: 
        !          1036:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1037:                                "not matched\n");
        !          1038:                }
        !          1039:        }
        !          1040:        /* no proposal matching */
        !          1041: err:
        !          1042:        flushsaprop(pr0);
        !          1043:        return NULL;
        !          1044: 
        !          1045: found:
        !          1046:        flushsaprop(pr0);
        !          1047:        plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
        !          1048:        iph2->approval = pr;
        !          1049: 
        !          1050:     {
        !          1051:        struct saproto *sp;
        !          1052:        struct prop_pair *p, *x;
        !          1053:        struct prop_pair *n = NULL;
        !          1054: 
        !          1055:        ret = NULL;
        !          1056: 
        !          1057:        for (p = pp; p; p = p->next) {
        !          1058:                /*
        !          1059:                 * find a proposal with matching proto_id.
        !          1060:                 * we have analyzed validity already, in cmpsaprop_alloc().
        !          1061:                 */
        !          1062:                for (sp = pr->head; sp; sp = sp->next) {
        !          1063:                        if (sp->proto_id == p->prop->proto_id)
        !          1064:                                break;
        !          1065:                }
        !          1066:                if (!sp)
        !          1067:                        goto err;
        !          1068:                if (sp->head->next)
        !          1069:                        goto err;       /* XXX */
        !          1070: 
        !          1071:                for (x = p; x; x = x->tnext)
        !          1072:                        if (sp->head->trns_no == x->trns->t_no)
        !          1073:                                break;
        !          1074:                if (!x)
        !          1075:                        goto err;       /* XXX */
        !          1076: 
        !          1077:                n = racoon_calloc(1, sizeof(struct prop_pair));
        !          1078:                if (n == NULL) {
        !          1079:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1080:                                "failed to get buffer.\n");
        !          1081:                        goto err;
        !          1082:                }
        !          1083: 
        !          1084:                n->prop = x->prop;
        !          1085:                n->trns = x->trns;
        !          1086: 
        !          1087:                /* need to preserve the order */
        !          1088:                for (x = ret; x && x->next; x = x->next)
        !          1089:                        ;
        !          1090:                if (x && x->prop == n->prop) {
        !          1091:                        for (/*nothing*/; x && x->tnext; x = x->tnext)
        !          1092:                                ;
        !          1093:                        x->tnext = n;
        !          1094:                } else {
        !          1095:                        if (x)
        !          1096:                                x->next = n;
        !          1097:                        else {
        !          1098:                                ret = n;
        !          1099:                        }
        !          1100:                }
        !          1101: 
        !          1102:                /* #of transforms should be updated ? */
        !          1103:        }
        !          1104:     }
        !          1105: 
        !          1106:        return ret;
        !          1107: }
        !          1108: 
        !          1109: void
        !          1110: free_proppair(pair)
        !          1111:        struct prop_pair **pair;
        !          1112: {
        !          1113:        int i;
        !          1114: 
        !          1115:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !          1116:                free_proppair0(pair[i]);
        !          1117:                pair[i] = NULL;
        !          1118:        }
        !          1119:        racoon_free(pair);
        !          1120: }
        !          1121: 
        !          1122: static void
        !          1123: free_proppair0(pair)
        !          1124:        struct prop_pair *pair;
        !          1125: {
        !          1126:        struct prop_pair *p, *q, *r, *s;
        !          1127: 
        !          1128:        p = pair;
        !          1129:        while (p) {
        !          1130:                q = p->next;
        !          1131:                r = p;
        !          1132:                while (r) {
        !          1133:                        s = r->tnext;
        !          1134:                        racoon_free(r);
        !          1135:                        r = s;
        !          1136:                }
        !          1137:                p = q;
        !          1138:        }
        !          1139: }
        !          1140: 
        !          1141: /*
        !          1142:  * get proposal pairs from SA payload.
        !          1143:  * tiny check for proposal payload.
        !          1144:  */
        !          1145: static struct prop_pair **
        !          1146: get_proppair_and_doi_sit(sa, mode, doitype, sittype)
        !          1147:        vchar_t *sa;
        !          1148:        int mode;
        !          1149:        u_int32_t *doitype, *sittype;
        !          1150: {
        !          1151:        struct prop_pair **pair = NULL;
        !          1152:        int num_p = 0;                  /* number of proposal for use */
        !          1153:        int tlen;
        !          1154:        caddr_t bp;
        !          1155:        int i;
        !          1156:        struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
        !          1157: 
        !          1158:        plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
        !          1159:        plogdump(LLV_DEBUG, sa->v, sa->l);
        !          1160: 
        !          1161:        /* check SA payload size */
        !          1162:        if (sa->l < sizeof(*sab)) {
        !          1163:                plog(LLV_ERROR, LOCATION, NULL,
        !          1164:                        "Invalid SA length = %zu.\n", sa->l);
        !          1165:                goto bad;
        !          1166:        }
        !          1167: 
        !          1168:        /* check DOI */
        !          1169:        if (check_doi(ntohl(sab->doi)) < 0)
        !          1170:                goto bad;
        !          1171:        if (doitype != NULL)
        !          1172:                *doitype = ntohl(sab->doi);
        !          1173: 
        !          1174:        /* check SITUATION */
        !          1175:        if (check_situation(ntohl(sab->sit)) < 0)
        !          1176:                goto bad;
        !          1177:        if (sittype != NULL)
        !          1178:                *sittype = ntohl(sab->sit);
        !          1179: 
        !          1180:        pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
        !          1181:        if (pair == NULL) {
        !          1182:                plog(LLV_ERROR, LOCATION, NULL,
        !          1183:                        "failed to get buffer.\n");
        !          1184:                goto bad;
        !          1185:        }
        !          1186:        memset(pair, 0, sizeof(pair));
        !          1187: 
        !          1188:        bp = (caddr_t)(sab + 1);
        !          1189:        tlen = sa->l - sizeof(*sab);
        !          1190: 
        !          1191:     {
        !          1192:        struct isakmp_pl_p *prop;
        !          1193:        int proplen;
        !          1194:        vchar_t *pbuf = NULL;
        !          1195:        struct isakmp_parse_t *pa;
        !          1196: 
        !          1197:        pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
        !          1198:        if (pbuf == NULL)
        !          1199:                goto bad;
        !          1200: 
        !          1201:        for (pa = (struct isakmp_parse_t *)pbuf->v;
        !          1202:             pa->type != ISAKMP_NPTYPE_NONE;
        !          1203:             pa++) {
        !          1204:                /* check the value of next payload */
        !          1205:                if (pa->type != ISAKMP_NPTYPE_P) {
        !          1206:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1207:                                "Invalid payload type=%u\n", pa->type);
        !          1208:                        vfree(pbuf);
        !          1209:                        goto bad;
        !          1210:                }
        !          1211: 
        !          1212:                prop = (struct isakmp_pl_p *)pa->ptr;
        !          1213:                proplen = pa->len;
        !          1214: 
        !          1215:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1216:                        "proposal #%u len=%d\n", prop->p_no, proplen);
        !          1217: 
        !          1218:                if (proplen == 0) {
        !          1219:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1220:                                "invalid proposal with length %d\n", proplen);
        !          1221:                        vfree(pbuf);
        !          1222:                        goto bad;
        !          1223:                }
        !          1224: 
        !          1225:                /* check Protocol ID */
        !          1226:                if (!check_protocol[mode]) {
        !          1227:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1228:                                "unsupported mode %d\n", mode);
        !          1229:                        continue;
        !          1230:                }
        !          1231: 
        !          1232:                if (check_protocol[mode](prop->proto_id) < 0)
        !          1233:                        continue;
        !          1234: 
        !          1235:                /* check SPI length when IKE. */
        !          1236:                if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
        !          1237:                        continue;
        !          1238: 
        !          1239:                /* get transform */
        !          1240:                if (get_transform(prop, pair, &num_p) < 0) {
        !          1241:                        vfree(pbuf);
        !          1242:                        goto bad;
        !          1243:                }
        !          1244:        }
        !          1245:        vfree(pbuf);
        !          1246:        pbuf = NULL;
        !          1247:     }
        !          1248: 
        !          1249:     {
        !          1250:        int notrans, nprop;
        !          1251:        struct prop_pair *p, *q;
        !          1252: 
        !          1253:        /* check for proposals with no transforms */
        !          1254:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !          1255:                if (!pair[i])
        !          1256:                        continue;
        !          1257: 
        !          1258:                plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
        !          1259:                print_proppair(LLV_DEBUG, pair[i]);
        !          1260: 
        !          1261:                notrans = nprop = 0;
        !          1262:                for (p = pair[i]; p; p = p->next) {
        !          1263:                        if (p->trns == NULL) {
        !          1264:                                notrans++;
        !          1265:                                break;
        !          1266:                        }
        !          1267:                        for (q = p; q; q = q->tnext)
        !          1268:                                nprop++;
        !          1269:                }
        !          1270: 
        !          1271: #if 0
        !          1272:                /*
        !          1273:                 * XXX at this moment, we cannot accept proposal group
        !          1274:                 * with multiple proposals.  this should be fixed.
        !          1275:                 */
        !          1276:                if (pair[i]->next) {
        !          1277:                        plog(LLV_WARNING, LOCATION, NULL,
        !          1278:                                "proposal #%u ignored "
        !          1279:                                "(multiple proposal not supported)\n",
        !          1280:                                pair[i]->prop->p_no);
        !          1281:                        notrans++;
        !          1282:                }
        !          1283: #endif
        !          1284: 
        !          1285:                if (notrans) {
        !          1286:                        for (p = pair[i]; p; p = q) {
        !          1287:                                q = p->next;
        !          1288:                                racoon_free(p);
        !          1289:                        }
        !          1290:                        pair[i] = NULL;
        !          1291:                        num_p--;
        !          1292:                } else {
        !          1293:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          1294:                                "proposal #%u: %d transform\n",
        !          1295:                                pair[i]->prop->p_no, nprop);
        !          1296:                }
        !          1297:        }
        !          1298:     }
        !          1299: 
        !          1300:        /* bark if no proposal is found. */
        !          1301:        if (num_p <= 0) {
        !          1302:                plog(LLV_ERROR, LOCATION, NULL,
        !          1303:                        "no Proposal found.\n");
        !          1304:                goto bad;
        !          1305:        }
        !          1306: 
        !          1307:        return pair;
        !          1308: bad:
        !          1309:        if (pair != NULL)
        !          1310:                racoon_free(pair);
        !          1311:        return NULL;
        !          1312: }
        !          1313: 
        !          1314: struct prop_pair **
        !          1315: get_proppair(sa, mode)
        !          1316:        vchar_t *sa;
        !          1317:        int mode;
        !          1318: {
        !          1319:        return get_proppair_and_doi_sit(sa, mode, NULL, NULL);
        !          1320: }
        !          1321: 
        !          1322: 
        !          1323: /*
        !          1324:  * check transform payload.
        !          1325:  * OUT:
        !          1326:  *     positive: return the pointer to the payload of valid transform.
        !          1327:  *     0       : No valid transform found.
        !          1328:  */
        !          1329: static int
        !          1330: get_transform(prop, pair, num_p)
        !          1331:        struct isakmp_pl_p *prop;
        !          1332:        struct prop_pair **pair;
        !          1333:        int *num_p;
        !          1334: {
        !          1335:        int tlen; /* total length of all transform in a proposal */
        !          1336:        caddr_t bp;
        !          1337:        struct isakmp_pl_t *trns;
        !          1338:        int trnslen;
        !          1339:        vchar_t *pbuf = NULL;
        !          1340:        struct isakmp_parse_t *pa;
        !          1341:        struct prop_pair *p = NULL, *q;
        !          1342:        int num_t;
        !          1343: 
        !          1344:        bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
        !          1345:        tlen = ntohs(prop->h.len)
        !          1346:                - (sizeof(struct isakmp_pl_p) + prop->spi_size);
        !          1347:        pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
        !          1348:        if (pbuf == NULL)
        !          1349:                return -1;
        !          1350: 
        !          1351:        /* check and get transform for use */
        !          1352:        num_t = 0;
        !          1353:        for (pa = (struct isakmp_parse_t *)pbuf->v;
        !          1354:             pa->type != ISAKMP_NPTYPE_NONE;
        !          1355:             pa++) {
        !          1356: 
        !          1357:                num_t++;
        !          1358: 
        !          1359:                /* check the value of next payload */
        !          1360:                if (pa->type != ISAKMP_NPTYPE_T) {
        !          1361:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1362:                                "Invalid payload type=%u\n", pa->type);
        !          1363:                        break;
        !          1364:                }
        !          1365: 
        !          1366:                trns = (struct isakmp_pl_t *)pa->ptr;
        !          1367:                trnslen = pa->len;
        !          1368: 
        !          1369:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1370:                        "transform #%u len=%u\n", trns->t_no, trnslen);
        !          1371: 
        !          1372:                /* check transform ID */
        !          1373:                if (prop->proto_id >= ARRAYLEN(check_transform)) {
        !          1374:                        plog(LLV_WARNING, LOCATION, NULL,
        !          1375:                                "unsupported proto_id %u\n",
        !          1376:                                prop->proto_id);
        !          1377:                        continue;
        !          1378:                }
        !          1379:                if (prop->proto_id >= ARRAYLEN(check_attributes)) {
        !          1380:                        plog(LLV_WARNING, LOCATION, NULL,
        !          1381:                                "unsupported proto_id %u\n",
        !          1382:                                prop->proto_id);
        !          1383:                        continue;
        !          1384:                }
        !          1385: 
        !          1386:                if (!check_transform[prop->proto_id]
        !          1387:                 || !check_attributes[prop->proto_id]) {
        !          1388:                        plog(LLV_WARNING, LOCATION, NULL,
        !          1389:                                "unsupported proto_id %u\n",
        !          1390:                                prop->proto_id);
        !          1391:                        continue;
        !          1392:                }
        !          1393:                if (check_transform[prop->proto_id](trns->t_id) < 0)
        !          1394:                        continue;
        !          1395: 
        !          1396:                /* check data attributes */
        !          1397:                if (check_attributes[prop->proto_id](trns) != 0)
        !          1398:                        continue;
        !          1399: 
        !          1400:                p = racoon_calloc(1, sizeof(*p));
        !          1401:                if (p == NULL) {
        !          1402:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1403:                                "failed to get buffer.\n");
        !          1404:                        vfree(pbuf);
        !          1405:                        return -1;
        !          1406:                }
        !          1407:                p->prop = prop;
        !          1408:                p->trns = trns;
        !          1409: 
        !          1410:                /* need to preserve the order */
        !          1411:                for (q = pair[prop->p_no]; q && q->next; q = q->next)
        !          1412:                        ;
        !          1413:                if (q && q->prop == p->prop) {
        !          1414:                        for (/*nothing*/; q && q->tnext; q = q->tnext)
        !          1415:                                ;
        !          1416:                        q->tnext = p;
        !          1417:                } else {
        !          1418:                        if (q)
        !          1419:                                q->next = p;
        !          1420:                        else {
        !          1421:                                pair[prop->p_no] = p;
        !          1422:                                (*num_p)++;
        !          1423:                        }
        !          1424:                }
        !          1425:        }
        !          1426: 
        !          1427:        vfree(pbuf);
        !          1428: 
        !          1429:        return 0;
        !          1430: }
        !          1431: 
        !          1432: /*
        !          1433:  * make a new SA payload from prop_pair.
        !          1434:  * NOTE: this function make spi value clear.
        !          1435:  */
        !          1436: vchar_t *
        !          1437: get_sabyproppair(doitype, sittype, pair)
        !          1438:        u_int32_t doitype, sittype;
        !          1439:        struct prop_pair *pair;
        !          1440: {
        !          1441:        vchar_t *newsa;
        !          1442:        int newtlen;
        !          1443:        u_int8_t *np_p = NULL;
        !          1444:        struct prop_pair *p;
        !          1445:        int prophlen, trnslen;
        !          1446:        caddr_t bp;
        !          1447: 
        !          1448:        newtlen = sizeof(struct ipsecdoi_sa_b);
        !          1449:        for (p = pair; p; p = p->next) {
        !          1450:                newtlen += sizeof(struct isakmp_pl_p);
        !          1451:                newtlen += p->prop->spi_size;
        !          1452:                newtlen += ntohs(p->trns->h.len);
        !          1453:        }
        !          1454: 
        !          1455:        newsa = vmalloc(newtlen);
        !          1456:        if (newsa == NULL) {
        !          1457:                plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
        !          1458:                return NULL;
        !          1459:        }
        !          1460:        bp = newsa->v;
        !          1461: 
        !          1462:        ((struct isakmp_gen *)bp)->len = htons(newtlen);
        !          1463: 
        !          1464:        /* update some of values in SA header */
        !          1465:        ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype);
        !          1466:        ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype);
        !          1467:        bp += sizeof(struct ipsecdoi_sa_b);
        !          1468: 
        !          1469:        /* create proposal payloads */
        !          1470:        for (p = pair; p; p = p->next) {
        !          1471:                prophlen = sizeof(struct isakmp_pl_p)
        !          1472:                                + p->prop->spi_size;
        !          1473:                trnslen = ntohs(p->trns->h.len);
        !          1474: 
        !          1475:                if (np_p)
        !          1476:                        *np_p = ISAKMP_NPTYPE_P;
        !          1477: 
        !          1478:                /* create proposal */
        !          1479: 
        !          1480:                memcpy(bp, p->prop, prophlen);
        !          1481:                ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
        !          1482:                ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
        !          1483:                ((struct isakmp_pl_p *)bp)->num_t = 1;
        !          1484:                np_p = &((struct isakmp_pl_p *)bp)->h.np;
        !          1485:                memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
        !          1486:                bp += prophlen;
        !          1487: 
        !          1488:                /* create transform */
        !          1489:                memcpy(bp, p->trns, trnslen);
        !          1490:                ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
        !          1491:                ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
        !          1492:                bp += trnslen;
        !          1493:        }
        !          1494: 
        !          1495:        return newsa;
        !          1496: }
        !          1497: 
        !          1498: /*
        !          1499:  * update responder's spi
        !          1500:  */
        !          1501: int
        !          1502: ipsecdoi_updatespi(iph2)
        !          1503:        struct ph2handle *iph2;
        !          1504: {
        !          1505:        struct prop_pair **pair, *p;
        !          1506:        struct saprop *pp;
        !          1507:        struct saproto *pr;
        !          1508:        int i;
        !          1509:        int error = -1;
        !          1510:        u_int8_t *spi;
        !          1511: 
        !          1512:        pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
        !          1513:        if (pair == NULL)
        !          1514:                return -1;
        !          1515:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
        !          1516:                if (pair[i])
        !          1517:                        break;
        !          1518:        }
        !          1519:        if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
        !          1520:                /* multiple transform must be filtered by selectph2proposal.*/
        !          1521:                goto end;
        !          1522:        }
        !          1523: 
        !          1524:        pp = iph2->approval;
        !          1525: 
        !          1526:        /* create proposal payloads */
        !          1527:        for (p = pair[i]; p; p = p->next) {
        !          1528:                /*
        !          1529:                 * find a proposal/transform with matching proto_id/t_id.
        !          1530:                 * we have analyzed validity already, in cmpsaprop_alloc().
        !          1531:                 */
        !          1532:                for (pr = pp->head; pr; pr = pr->next) {
        !          1533:                        if (p->prop->proto_id == pr->proto_id &&
        !          1534:                            p->trns->t_id == pr->head->trns_id) {
        !          1535:                                break;
        !          1536:                        }
        !          1537:                }
        !          1538:                if (!pr)
        !          1539:                        goto end;
        !          1540: 
        !          1541:                /*
        !          1542:                 * XXX SPI bits are left-filled, for use with IPComp.
        !          1543:                 * we should be switching to variable-length spi field...
        !          1544:                 */
        !          1545:                spi = (u_int8_t *)&pr->spi;
        !          1546:                spi += sizeof(pr->spi);
        !          1547:                spi -= pr->spisize;
        !          1548:                memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
        !          1549:        }
        !          1550: 
        !          1551:        error = 0;
        !          1552: end:
        !          1553:        free_proppair(pair);
        !          1554:        return error;
        !          1555: }
        !          1556: 
        !          1557: /*
        !          1558:  * make a new SA payload from prop_pair.
        !          1559:  */
        !          1560: vchar_t *
        !          1561: get_sabysaprop(pp0, sa0)
        !          1562:        struct saprop *pp0;
        !          1563:        vchar_t *sa0;
        !          1564: {
        !          1565:        struct prop_pair **pair = NULL;
        !          1566:        vchar_t *newsa = NULL;
        !          1567:        int newtlen;
        !          1568:        u_int8_t *np_p = NULL;
        !          1569:        struct prop_pair *p = NULL;
        !          1570:        struct saprop *pp;
        !          1571:        struct saproto *pr;
        !          1572:        struct satrns *tr;
        !          1573:        int prophlen, trnslen;
        !          1574:        caddr_t bp;
        !          1575:        int error = -1;
        !          1576: 
        !          1577:        /* get proposal pair */
        !          1578:        pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
        !          1579:        if (pair == NULL)
        !          1580:                goto out;
        !          1581: 
        !          1582:        newtlen = sizeof(struct ipsecdoi_sa_b);
        !          1583:        for (pp = pp0; pp; pp = pp->next) {
        !          1584: 
        !          1585:                if (pair[pp->prop_no] == NULL)
        !          1586:                        goto out;
        !          1587: 
        !          1588:                for (pr = pp->head; pr; pr = pr->next) {
        !          1589:                        newtlen += (sizeof(struct isakmp_pl_p)
        !          1590:                                + pr->spisize);
        !          1591: 
        !          1592:                        for (tr = pr->head; tr; tr = tr->next) {
        !          1593:                                for (p = pair[pp->prop_no]; p; p = p->tnext) {
        !          1594:                                        if (tr->trns_no == p->trns->t_no)
        !          1595:                                                break;
        !          1596:                                }
        !          1597:                                if (p == NULL)
        !          1598:                                        goto out;
        !          1599: 
        !          1600:                                newtlen += ntohs(p->trns->h.len);
        !          1601:                        }
        !          1602:                }
        !          1603:        }
        !          1604: 
        !          1605:        newsa = vmalloc(newtlen);
        !          1606:        if (newsa == NULL) {
        !          1607:                plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
        !          1608:                goto out;
        !          1609:        }
        !          1610:        bp = newsa->v;
        !          1611: 
        !          1612:        /* some of values of SA must be updated in the out of this function */
        !          1613:        ((struct isakmp_gen *)bp)->len = htons(newtlen);
        !          1614:        bp += sizeof(struct ipsecdoi_sa_b);
        !          1615: 
        !          1616:        /* create proposal payloads */
        !          1617:        for (pp = pp0; pp; pp = pp->next) {
        !          1618: 
        !          1619:                for (pr = pp->head; pr; pr = pr->next) {
        !          1620:                        prophlen = sizeof(struct isakmp_pl_p)
        !          1621:                                        + p->prop->spi_size;
        !          1622: 
        !          1623:                        for (tr = pr->head; tr; tr = tr->next) {
        !          1624:                                for (p = pair[pp->prop_no]; p; p = p->tnext) {
        !          1625:                                        if (tr->trns_no == p->trns->t_no)
        !          1626:                                                break;
        !          1627:                                }
        !          1628:                                if (p == NULL)
        !          1629:                                        goto out;
        !          1630: 
        !          1631:                                trnslen = ntohs(p->trns->h.len);
        !          1632: 
        !          1633:                                if (np_p)
        !          1634:                                        *np_p = ISAKMP_NPTYPE_P;
        !          1635: 
        !          1636:                                /* create proposal */
        !          1637: 
        !          1638:                                memcpy(bp, p->prop, prophlen);
        !          1639:                                ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
        !          1640:                                ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
        !          1641:                                ((struct isakmp_pl_p *)bp)->num_t = 1;
        !          1642:                                np_p = &((struct isakmp_pl_p *)bp)->h.np;
        !          1643:                                bp += prophlen;
        !          1644: 
        !          1645:                                /* create transform */
        !          1646:                                memcpy(bp, p->trns, trnslen);
        !          1647:                                ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
        !          1648:                                ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
        !          1649:                                bp += trnslen;
        !          1650:                        }
        !          1651:                }
        !          1652:        }
        !          1653: 
        !          1654:        error = 0;
        !          1655: out:
        !          1656:        if (pair != NULL)
        !          1657:                racoon_free(pair);
        !          1658: 
        !          1659:        if (error != 0) {
        !          1660:                if (newsa != NULL) {
        !          1661:                        vfree(newsa);
        !          1662:                        newsa = NULL;
        !          1663:                }
        !          1664:        }
        !          1665: 
        !          1666:        return newsa;
        !          1667: }
        !          1668: 
        !          1669: /*
        !          1670:  * If some error happens then return 0.  Although 0 means that lifetime is zero,
        !          1671:  * such a value should not be accepted.
        !          1672:  * Also 0 of lifebyte should not be included in a packet although 0 means not
        !          1673:  * to care of it.
        !          1674:  */
        !          1675: static u_int32_t
        !          1676: ipsecdoi_set_ld(buf)
        !          1677:        vchar_t *buf;
        !          1678: {
        !          1679:        u_int32_t ld;
        !          1680: 
        !          1681:        if (buf == 0)
        !          1682:                return 0;
        !          1683: 
        !          1684:        switch (buf->l) {
        !          1685:        case 2:
        !          1686:                ld = ntohs(*(u_int16_t *)buf->v);
        !          1687:                break;
        !          1688:        case 4:
        !          1689:                ld = ntohl(*(u_int32_t *)buf->v);
        !          1690:                break;
        !          1691:        default:
        !          1692:                plog(LLV_ERROR, LOCATION, NULL,
        !          1693:                        "length %zu of life duration "
        !          1694:                        "isn't supported.\n", buf->l);
        !          1695:                return 0;
        !          1696:        }
        !          1697: 
        !          1698:        return ld;
        !          1699: }
        !          1700: 
        !          1701: /*
        !          1702:  * parse responder-lifetime attributes from payload
        !          1703:  */
        !          1704: int
        !          1705: ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb)
        !          1706:        struct isakmp_pl_n *notify;
        !          1707:        u_int32_t *lifetime_sec;
        !          1708:        u_int32_t *lifetime_kb;
        !          1709: {
        !          1710:        struct isakmp_data *d;
        !          1711:        int flag, type, tlen, ld_type = -1;
        !          1712:        u_int16_t lorv;
        !          1713:        u_int32_t value;
        !          1714: 
        !          1715:        tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
        !          1716:         d = (struct isakmp_data *)((char *)(notify + 1) +
        !          1717:                notify->spi_size);
        !          1718: 
        !          1719:        while (tlen >= sizeof(struct isakmp_data)) {
        !          1720:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
        !          1721:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
        !          1722:                lorv = ntohs(d->lorv);
        !          1723: 
        !          1724:                plog(LLV_DEBUG, LOCATION, NULL,
        !          1725:                        "type=%s, flag=0x%04x, lorv=%s\n",
        !          1726:                        s_ipsecdoi_attr(type), flag,
        !          1727:                        s_ipsecdoi_attr_v(type, lorv));
        !          1728: 
        !          1729:                switch (type) {
        !          1730:                case IPSECDOI_ATTR_SA_LD_TYPE:
        !          1731:                        if (! flag) {
        !          1732:                                plog(LLV_ERROR, LOCATION, NULL,
        !          1733:                                        "must be TV when LD_TYPE.\n");
        !          1734:                                return -1;
        !          1735:                        }
        !          1736:                        ld_type = lorv;
        !          1737:                        break;
        !          1738:                case IPSECDOI_ATTR_SA_LD:
        !          1739:                        if (flag)
        !          1740:                                value = lorv;
        !          1741:                        else if (lorv == 2)
        !          1742:                                value = ntohs(*(u_int16_t *)(d + 1));
        !          1743:                        else if (lorv == 4)
        !          1744:                                value = ntohl(*(u_int32_t *)(d + 1));
        !          1745:                        else {
        !          1746:                                plog(LLV_ERROR, LOCATION, NULL,
        !          1747:                                        "payload length %d for lifetime "
        !          1748:                                        "data length is unsupported.\n", lorv);
        !          1749:                                return -1;
        !          1750:                        }
        !          1751: 
        !          1752:                        switch (ld_type) {
        !          1753:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
        !          1754:                                if (lifetime_sec != NULL)
        !          1755:                                        *lifetime_sec = value;
        !          1756:                                plog(LLV_INFO, LOCATION, NULL,
        !          1757:                                        "received RESPONDER-LIFETIME: %d "
        !          1758:                                        "seconds\n", value);
        !          1759:                                break;
        !          1760:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
        !          1761:                                if (lifetime_kb != NULL)
        !          1762:                                        *lifetime_kb = value;
        !          1763:                                plog(LLV_INFO, LOCATION, NULL,
        !          1764:                                        "received RESPONDER-LIFETIME: %d "
        !          1765:                                        "kbytes\n", value);
        !          1766:                                break;
        !          1767:                        default:
        !          1768:                                plog(LLV_ERROR, LOCATION, NULL,
        !          1769:                                        "lifetime data received without "
        !          1770:                                        "lifetime data type.\n");
        !          1771:                                return -1;
        !          1772:                        }
        !          1773:                        break;
        !          1774:                }
        !          1775: 
        !          1776:                if (flag) {
        !          1777:                        tlen -= sizeof(*d);
        !          1778:                        d = (struct isakmp_data *)((char *)d
        !          1779:                                + sizeof(*d));
        !          1780:                } else {
        !          1781:                        tlen -= (sizeof(*d) + lorv);
        !          1782:                        d = (struct isakmp_data *)((char *)d
        !          1783:                                + sizeof(*d) + lorv);
        !          1784:                }
        !          1785:        }
        !          1786: 
        !          1787:        return 0;
        !          1788: }
        !          1789: 
        !          1790: 
        !          1791: /*%%%*/
        !          1792: /*
        !          1793:  * check DOI
        !          1794:  */
        !          1795: static int
        !          1796: check_doi(doi)
        !          1797:        u_int32_t doi;
        !          1798: {
        !          1799:        switch (doi) {
        !          1800:        case IPSEC_DOI:
        !          1801:                return 0;
        !          1802:        default:
        !          1803:                plog(LLV_ERROR, LOCATION, NULL,
        !          1804:                        "invalid value of DOI 0x%08x.\n", doi);
        !          1805:                return -1;
        !          1806:        }
        !          1807:        /* NOT REACHED */
        !          1808: }
        !          1809: 
        !          1810: /*
        !          1811:  * check situation
        !          1812:  */
        !          1813: static int
        !          1814: check_situation(sit)
        !          1815:        u_int32_t sit;
        !          1816: {
        !          1817:        switch (sit) {
        !          1818:        case IPSECDOI_SIT_IDENTITY_ONLY:
        !          1819:                return 0;
        !          1820: 
        !          1821:        case IPSECDOI_SIT_SECRECY:
        !          1822:        case IPSECDOI_SIT_INTEGRITY:
        !          1823:                plog(LLV_ERROR, LOCATION, NULL,
        !          1824:                        "situation 0x%08x unsupported yet.\n", sit);
        !          1825:                return -1;
        !          1826: 
        !          1827:        default:
        !          1828:                plog(LLV_ERROR, LOCATION, NULL,
        !          1829:                        "invalid situation 0x%08x.\n", sit);
        !          1830:                return -1;
        !          1831:        }
        !          1832:        /* NOT REACHED */
        !          1833: }
        !          1834: 
        !          1835: /*
        !          1836:  * check protocol id in main mode
        !          1837:  */
        !          1838: static int
        !          1839: check_prot_main(proto_id)
        !          1840:        int proto_id;
        !          1841: {
        !          1842:        switch (proto_id) {
        !          1843:        case IPSECDOI_PROTO_ISAKMP:
        !          1844:                return 0;
        !          1845: 
        !          1846:        default:
        !          1847:                plog(LLV_ERROR, LOCATION, NULL,
        !          1848:                        "Illegal protocol id=%u.\n", proto_id);
        !          1849:                return -1;
        !          1850:        }
        !          1851:        /* NOT REACHED */
        !          1852: }
        !          1853: 
        !          1854: /*
        !          1855:  * check protocol id in quick mode
        !          1856:  */
        !          1857: static int
        !          1858: check_prot_quick(proto_id)
        !          1859:        int proto_id;
        !          1860: {
        !          1861:        switch (proto_id) {
        !          1862:        case IPSECDOI_PROTO_IPSEC_AH:
        !          1863:        case IPSECDOI_PROTO_IPSEC_ESP:
        !          1864:                return 0;
        !          1865: 
        !          1866:        case IPSECDOI_PROTO_IPCOMP:
        !          1867:                return 0;
        !          1868: 
        !          1869:        default:
        !          1870:                plog(LLV_ERROR, LOCATION, NULL,
        !          1871:                        "invalid protocol id %d.\n", proto_id);
        !          1872:                return -1;
        !          1873:        }
        !          1874:        /* NOT REACHED */
        !          1875: }
        !          1876: 
        !          1877: static int
        !          1878: check_spi_size(proto_id, size)
        !          1879:        int proto_id, size;
        !          1880: {
        !          1881:        switch (proto_id) {
        !          1882:        case IPSECDOI_PROTO_ISAKMP:
        !          1883:                if (size != 0) {
        !          1884:                        /* WARNING */
        !          1885:                        plog(LLV_WARNING, LOCATION, NULL,
        !          1886:                                "SPI size isn't zero, but IKE proposal.\n");
        !          1887:                }
        !          1888:                return 0;
        !          1889: 
        !          1890:        case IPSECDOI_PROTO_IPSEC_AH:
        !          1891:        case IPSECDOI_PROTO_IPSEC_ESP:
        !          1892:                if (size != 4) {
        !          1893:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1894:                                "invalid SPI size=%d for IPSEC proposal.\n",
        !          1895:                                size);
        !          1896:                        return -1;
        !          1897:                }
        !          1898:                return 0;
        !          1899: 
        !          1900:        case IPSECDOI_PROTO_IPCOMP:
        !          1901:                if (size != 2 && size != 4) {
        !          1902:                        plog(LLV_ERROR, LOCATION, NULL,
        !          1903:                                "invalid SPI size=%d for IPCOMP proposal.\n",
        !          1904:                                size);
        !          1905:                        return -1;
        !          1906:                }
        !          1907:                return 0;
        !          1908: 
        !          1909:        default:
        !          1910:                /* ??? */
        !          1911:                return -1;
        !          1912:        }
        !          1913:        /* NOT REACHED */
        !          1914: }
        !          1915: 
        !          1916: /*
        !          1917:  * check transform ID in ISAKMP.
        !          1918:  */
        !          1919: static int
        !          1920: check_trns_isakmp(t_id)
        !          1921:        int t_id;
        !          1922: {
        !          1923:        switch (t_id) {
        !          1924:        case IPSECDOI_KEY_IKE:
        !          1925:                return 0;
        !          1926:        default:
        !          1927:                plog(LLV_ERROR, LOCATION, NULL,
        !          1928:                        "invalid transform-id=%u in proto_id=%u.\n",
        !          1929:                        t_id, IPSECDOI_KEY_IKE);
        !          1930:                return -1;
        !          1931:        }
        !          1932:        /* NOT REACHED */
        !          1933: }
        !          1934: 
        !          1935: /*
        !          1936:  * check transform ID in AH.
        !          1937:  */
        !          1938: static int
        !          1939: check_trns_ah(t_id)
        !          1940:        int t_id;
        !          1941: {
        !          1942:        switch (t_id) {
        !          1943:        case IPSECDOI_AH_MD5:
        !          1944:        case IPSECDOI_AH_SHA:
        !          1945:        case IPSECDOI_AH_SHA256:
        !          1946:        case IPSECDOI_AH_SHA384:
        !          1947:        case IPSECDOI_AH_SHA512:
        !          1948:                return 0;
        !          1949:        case IPSECDOI_AH_DES:
        !          1950:                plog(LLV_ERROR, LOCATION, NULL,
        !          1951:                        "not support transform-id=%u in AH.\n", t_id);
        !          1952:                return -1;
        !          1953:        default:
        !          1954:                plog(LLV_ERROR, LOCATION, NULL,
        !          1955:                        "invalid transform-id=%u in AH.\n", t_id);
        !          1956:                return -1;
        !          1957:        }
        !          1958:        /* NOT REACHED */
        !          1959: }
        !          1960: 
        !          1961: /*
        !          1962:  * check transform ID in ESP.
        !          1963:  */
        !          1964: static int
        !          1965: check_trns_esp(t_id)
        !          1966:        int t_id;
        !          1967: {
        !          1968:        switch (t_id) {
        !          1969:        case IPSECDOI_ESP_DES:
        !          1970:        case IPSECDOI_ESP_3DES:
        !          1971:        case IPSECDOI_ESP_NULL:
        !          1972:        case IPSECDOI_ESP_RC5:
        !          1973:        case IPSECDOI_ESP_CAST:
        !          1974:        case IPSECDOI_ESP_BLOWFISH:
        !          1975:        case IPSECDOI_ESP_AES:
        !          1976:        case IPSECDOI_ESP_TWOFISH:
        !          1977:        case IPSECDOI_ESP_CAMELLIA:
        !          1978:                return 0;
        !          1979:        case IPSECDOI_ESP_DES_IV32:
        !          1980:        case IPSECDOI_ESP_DES_IV64:
        !          1981:        case IPSECDOI_ESP_IDEA:
        !          1982:        case IPSECDOI_ESP_3IDEA:
        !          1983:        case IPSECDOI_ESP_RC4:
        !          1984:                plog(LLV_ERROR, LOCATION, NULL,
        !          1985:                        "not support transform-id=%u in ESP.\n", t_id);
        !          1986:                return -1;
        !          1987:        default:
        !          1988:                plog(LLV_ERROR, LOCATION, NULL,
        !          1989:                        "invalid transform-id=%u in ESP.\n", t_id);
        !          1990:                return -1;
        !          1991:        }
        !          1992:        /* NOT REACHED */
        !          1993: }
        !          1994: 
        !          1995: /*
        !          1996:  * check transform ID in IPCOMP.
        !          1997:  */
        !          1998: static int
        !          1999: check_trns_ipcomp(t_id)
        !          2000:        int t_id;
        !          2001: {
        !          2002:        switch (t_id) {
        !          2003:        case IPSECDOI_IPCOMP_OUI:
        !          2004:        case IPSECDOI_IPCOMP_DEFLATE:
        !          2005:        case IPSECDOI_IPCOMP_LZS:
        !          2006:                return 0;
        !          2007:        default:
        !          2008:                plog(LLV_ERROR, LOCATION, NULL,
        !          2009:                        "invalid transform-id=%u in IPCOMP.\n", t_id);
        !          2010:                return -1;
        !          2011:        }
        !          2012:        /* NOT REACHED */
        !          2013: }
        !          2014: 
        !          2015: /*
        !          2016:  * check data attributes in IKE.
        !          2017:  */
        !          2018: static int
        !          2019: check_attr_isakmp(trns)
        !          2020:        struct isakmp_pl_t *trns;
        !          2021: {
        !          2022:        struct isakmp_data *d;
        !          2023:        int tlen;
        !          2024:        int flag, type;
        !          2025:        u_int16_t lorv;
        !          2026: 
        !          2027:        tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
        !          2028:        d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
        !          2029: 
        !          2030:        while (tlen > 0) {
        !          2031:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
        !          2032:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
        !          2033:                lorv = ntohs(d->lorv);
        !          2034: 
        !          2035:                plog(LLV_DEBUG, LOCATION, NULL,
        !          2036:                        "type=%s, flag=0x%04x, lorv=%s\n",
        !          2037:                        s_oakley_attr(type), flag,
        !          2038:                        s_oakley_attr_v(type, lorv));
        !          2039: 
        !          2040:                /*
        !          2041:                 * some of the attributes must be encoded in TV.
        !          2042:                 * see RFC2409 Appendix A "Attribute Classes".
        !          2043:                 */
        !          2044:                switch (type) {
        !          2045:                case OAKLEY_ATTR_ENC_ALG:
        !          2046:                case OAKLEY_ATTR_HASH_ALG:
        !          2047:                case OAKLEY_ATTR_AUTH_METHOD:
        !          2048:                case OAKLEY_ATTR_GRP_DESC:
        !          2049:                case OAKLEY_ATTR_GRP_TYPE:
        !          2050:                case OAKLEY_ATTR_SA_LD_TYPE:
        !          2051:                case OAKLEY_ATTR_PRF:
        !          2052:                case OAKLEY_ATTR_KEY_LEN:
        !          2053:                case OAKLEY_ATTR_FIELD_SIZE:
        !          2054:                        if (!flag) {    /* TLV*/
        !          2055:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2056:                                        "oakley attribute %d must be TV.\n",
        !          2057:                                        type);
        !          2058:                                return -1;
        !          2059:                        }
        !          2060:                        break;
        !          2061:                }
        !          2062: 
        !          2063:                /* sanity check for TLV.  length must be specified. */
        !          2064:                if (!flag && lorv == 0) {       /*TLV*/
        !          2065:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2066:                                "invalid length %d for TLV attribute %d.\n",
        !          2067:                                lorv, type);
        !          2068:                        return -1;
        !          2069:                }
        !          2070: 
        !          2071:                switch (type) {
        !          2072:                case OAKLEY_ATTR_ENC_ALG:
        !          2073:                        if (!alg_oakley_encdef_ok(lorv)) {
        !          2074:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2075:                                        "invalied encryption algorithm=%d.\n",
        !          2076:                                        lorv);
        !          2077:                                return -1;
        !          2078:                        }
        !          2079:                        break;
        !          2080: 
        !          2081:                case OAKLEY_ATTR_HASH_ALG:
        !          2082:                        if (!alg_oakley_hashdef_ok(lorv)) {
        !          2083:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2084:                                        "invalied hash algorithm=%d.\n",
        !          2085:                                        lorv);
        !          2086:                                return -1;
        !          2087:                        }
        !          2088:                        break;
        !          2089: 
        !          2090:                case OAKLEY_ATTR_AUTH_METHOD:
        !          2091:                        switch (lorv) {
        !          2092:                        case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
        !          2093:                        case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
        !          2094: #ifdef ENABLE_HYBRID
        !          2095:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
        !          2096:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
        !          2097: #endif
        !          2098: #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
        !          2099:                                /* These two authentication method IDs overlap. */
        !          2100:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
        !          2101:                        /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
        !          2102: #endif
        !          2103:                                break;
        !          2104:                        case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
        !          2105: #ifdef ENABLE_HYBRID
        !          2106:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
        !          2107:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
        !          2108:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
        !          2109:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
        !          2110:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
        !          2111:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
        !          2112:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
        !          2113:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
        !          2114:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
        !          2115:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
        !          2116:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
        !          2117: #endif
        !          2118:                        case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
        !          2119:                        case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
        !          2120:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2121:                                        "auth method %s isn't supported.\n",
        !          2122:                                        s_oakley_attr_method(lorv));
        !          2123:                                return -1;
        !          2124:                        default:
        !          2125:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2126:                                        "invalid auth method %d.\n",
        !          2127:                                        lorv);
        !          2128:                                return -1;
        !          2129:                        }
        !          2130:                        break;
        !          2131: 
        !          2132:                case OAKLEY_ATTR_GRP_DESC:
        !          2133:                        if (!alg_oakley_dhdef_ok(lorv)) {
        !          2134:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2135:                                        "invalid DH group %d.\n",
        !          2136:                                        lorv);
        !          2137:                                return -1;
        !          2138:                        }
        !          2139:                        break;
        !          2140: 
        !          2141:                case OAKLEY_ATTR_GRP_TYPE:
        !          2142:                        switch (lorv) {
        !          2143:                        case OAKLEY_ATTR_GRP_TYPE_MODP:
        !          2144:                                break;
        !          2145:                        default:
        !          2146:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2147:                                        "unsupported DH group type %d.\n",
        !          2148:                                        lorv);
        !          2149:                                return -1;
        !          2150:                        }
        !          2151:                        break;
        !          2152: 
        !          2153:                case OAKLEY_ATTR_GRP_PI:
        !          2154:                case OAKLEY_ATTR_GRP_GEN_ONE:
        !          2155:                        /* sanity checks? */
        !          2156:                        break;
        !          2157: 
        !          2158:                case OAKLEY_ATTR_GRP_GEN_TWO:
        !          2159:                case OAKLEY_ATTR_GRP_CURVE_A:
        !          2160:                case OAKLEY_ATTR_GRP_CURVE_B:
        !          2161:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2162:                                "attr type=%u isn't supported.\n", type);
        !          2163:                        return -1;
        !          2164: 
        !          2165:                case OAKLEY_ATTR_SA_LD_TYPE:
        !          2166:                        switch (lorv) {
        !          2167:                        case OAKLEY_ATTR_SA_LD_TYPE_SEC:
        !          2168:                        case OAKLEY_ATTR_SA_LD_TYPE_KB:
        !          2169:                                break;
        !          2170:                        default:
        !          2171:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2172:                                        "invalid life type %d.\n", lorv);
        !          2173:                                return -1;
        !          2174:                        }
        !          2175:                        break;
        !          2176: 
        !          2177:                case OAKLEY_ATTR_SA_LD:
        !          2178:                        /* should check the value */
        !          2179:                        break;
        !          2180: 
        !          2181:                case OAKLEY_ATTR_PRF:
        !          2182:                case OAKLEY_ATTR_KEY_LEN:
        !          2183:                        break;
        !          2184: 
        !          2185:                case OAKLEY_ATTR_FIELD_SIZE:
        !          2186:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2187:                                "attr type=%u isn't supported.\n", type);
        !          2188:                        return -1;
        !          2189: 
        !          2190:                case OAKLEY_ATTR_GRP_ORDER:
        !          2191:                        break;
        !          2192: 
        !          2193:                case OAKLEY_ATTR_GSS_ID:
        !          2194:                        break;
        !          2195: 
        !          2196:                default:
        !          2197:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2198:                                "invalid attribute type %d.\n", type);
        !          2199:                        return -1;
        !          2200:                }
        !          2201: 
        !          2202:                if (flag) {
        !          2203:                        tlen -= sizeof(*d);
        !          2204:                        d = (struct isakmp_data *)((char *)d
        !          2205:                                + sizeof(*d));
        !          2206:                } else {
        !          2207:                        tlen -= (sizeof(*d) + lorv);
        !          2208:                        d = (struct isakmp_data *)((char *)d
        !          2209:                                + sizeof(*d) + lorv);
        !          2210:                }
        !          2211:        }
        !          2212: 
        !          2213:        return 0;
        !          2214: }
        !          2215: 
        !          2216: /*
        !          2217:  * check data attributes in IPSEC AH/ESP.
        !          2218:  */
        !          2219: static int
        !          2220: check_attr_ah(trns)
        !          2221:        struct isakmp_pl_t *trns;
        !          2222: {
        !          2223:        return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
        !          2224: }
        !          2225: 
        !          2226: static int
        !          2227: check_attr_esp(trns)
        !          2228:        struct isakmp_pl_t *trns;
        !          2229: {
        !          2230:        return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
        !          2231: }
        !          2232: 
        !          2233: static int
        !          2234: check_attr_ipsec(proto_id, trns)
        !          2235:        int proto_id;
        !          2236:        struct isakmp_pl_t *trns;
        !          2237: {
        !          2238:        struct isakmp_data *d;
        !          2239:        int tlen;
        !          2240:        int flag, type = 0;
        !          2241:        u_int16_t lorv;
        !          2242:        int attrseen[16];       /* XXX magic number */
        !          2243: 
        !          2244:        tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
        !          2245:        d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
        !          2246:        memset(attrseen, 0, sizeof(attrseen));
        !          2247: 
        !          2248:        while (tlen > 0) {
        !          2249:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
        !          2250:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
        !          2251:                lorv = ntohs(d->lorv);
        !          2252: 
        !          2253:                plog(LLV_DEBUG, LOCATION, NULL,
        !          2254:                        "type=%s, flag=0x%04x, lorv=%s\n",
        !          2255:                        s_ipsecdoi_attr(type), flag,
        !          2256:                        s_ipsecdoi_attr_v(type, lorv));
        !          2257: 
        !          2258:                if (type < sizeof(attrseen)/sizeof(attrseen[0]))
        !          2259:                        attrseen[type]++;
        !          2260: 
        !          2261:                switch (type) {
        !          2262:                case IPSECDOI_ATTR_ENC_MODE:
        !          2263:                        if (! flag) {
        !          2264:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2265:                                        "must be TV when ENC_MODE.\n");
        !          2266:                                return -1;
        !          2267:                        }
        !          2268: 
        !          2269:                        switch (lorv) {
        !          2270:                        case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
        !          2271:                        case IPSECDOI_ATTR_ENC_MODE_TRNS:
        !          2272:                                break;
        !          2273: #ifdef ENABLE_NATT
        !          2274:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
        !          2275:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
        !          2276:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
        !          2277:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
        !          2278:                                plog(LLV_DEBUG, LOCATION, NULL,
        !          2279:                                     "UDP encapsulation requested\n");
        !          2280:                                break;
        !          2281: #endif
        !          2282:                        default:
        !          2283:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2284:                                        "invalid encryption mode=%u.\n",
        !          2285:                                        lorv);
        !          2286:                                return -1;
        !          2287:                        }
        !          2288:                        break;
        !          2289: 
        !          2290:                case IPSECDOI_ATTR_AUTH:
        !          2291:                        if (! flag) {
        !          2292:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2293:                                        "must be TV when AUTH.\n");
        !          2294:                                return -1;
        !          2295:                        }
        !          2296: 
        !          2297:                        switch (lorv) {
        !          2298:                        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
        !          2299:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
        !          2300:                                    trns->t_id != IPSECDOI_AH_MD5) {
        !          2301: ahmismatch:
        !          2302:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          2303:                                                "auth algorithm %u conflicts "
        !          2304:                                                "with transform %u.\n",
        !          2305:                                                lorv, trns->t_id);
        !          2306:                                        return -1;
        !          2307:                                }
        !          2308:                                break;
        !          2309:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
        !          2310:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
        !          2311:                                        if (trns->t_id != IPSECDOI_AH_SHA)
        !          2312:                                                goto ahmismatch;
        !          2313:                                }
        !          2314:                                break;
        !          2315:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
        !          2316:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
        !          2317:                                        if (trns->t_id != IPSECDOI_AH_SHA256)
        !          2318:                                                goto ahmismatch;
        !          2319:                                }
        !          2320:                                break;
        !          2321:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
        !          2322:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
        !          2323:                                        if (trns->t_id != IPSECDOI_AH_SHA384)
        !          2324:                                                goto ahmismatch;
        !          2325:                                }
        !          2326:                                break;
        !          2327:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
        !          2328:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
        !          2329:                                        if (trns->t_id != IPSECDOI_AH_SHA512)
        !          2330:                                        goto ahmismatch;
        !          2331:                                }
        !          2332:                                break;
        !          2333:                        case IPSECDOI_ATTR_AUTH_DES_MAC:
        !          2334:                        case IPSECDOI_ATTR_AUTH_KPDK:
        !          2335:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2336:                                        "auth algorithm %u isn't supported.\n",
        !          2337:                                        lorv);
        !          2338:                                return -1;
        !          2339:                        default:
        !          2340:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2341:                                        "invalid auth algorithm=%u.\n",
        !          2342:                                        lorv);
        !          2343:                                return -1;
        !          2344:                        }
        !          2345:                        break;
        !          2346: 
        !          2347:                case IPSECDOI_ATTR_SA_LD_TYPE:
        !          2348:                        if (! flag) {
        !          2349:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2350:                                        "must be TV when LD_TYPE.\n");
        !          2351:                                return -1;
        !          2352:                        }
        !          2353: 
        !          2354:                        switch (lorv) {
        !          2355:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
        !          2356:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
        !          2357:                                break;
        !          2358:                        default:
        !          2359:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2360:                                        "invalid life type %d.\n", lorv);
        !          2361:                                return -1;
        !          2362:                        }
        !          2363:                        break;
        !          2364: 
        !          2365:                case IPSECDOI_ATTR_SA_LD:
        !          2366:                        if (flag) {
        !          2367:                                /* i.e. ISAKMP_GEN_TV */
        !          2368:                                plog(LLV_DEBUG, LOCATION, NULL,
        !          2369:                                        "life duration was in TLV.\n");
        !          2370:                        } else {
        !          2371:                                /* i.e. ISAKMP_GEN_TLV */
        !          2372:                                if (lorv == 0) {
        !          2373:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          2374:                                                "invalid length of LD\n");
        !          2375:                                        return -1;
        !          2376:                                }
        !          2377:                        }
        !          2378:                        break;
        !          2379: 
        !          2380:                case IPSECDOI_ATTR_GRP_DESC:
        !          2381:                        if (! flag) {
        !          2382:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2383:                                        "must be TV when GRP_DESC.\n");
        !          2384:                                return -1;
        !          2385:                        }
        !          2386: 
        !          2387:                        if (!alg_oakley_dhdef_ok(lorv)) {
        !          2388:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2389:                                        "invalid group description=%u.\n",
        !          2390:                                        lorv);
        !          2391:                                return -1;
        !          2392:                        }
        !          2393:                        break;
        !          2394: 
        !          2395:                case IPSECDOI_ATTR_KEY_LENGTH:
        !          2396:                        if (! flag) {
        !          2397:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2398:                                        "must be TV when KEY_LENGTH.\n");
        !          2399:                                return -1;
        !          2400:                        }
        !          2401:                        break;
        !          2402: 
        !          2403: #ifdef HAVE_SECCTX
        !          2404:                case IPSECDOI_ATTR_SECCTX:
        !          2405:                        if (flag) {
        !          2406:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2407:                                        "SECCTX must be in TLV.\n");
        !          2408:                                return -1;
        !          2409:                        }
        !          2410:                break;
        !          2411: #endif
        !          2412: 
        !          2413:                case IPSECDOI_ATTR_KEY_ROUNDS:
        !          2414:                case IPSECDOI_ATTR_COMP_DICT_SIZE:
        !          2415:                case IPSECDOI_ATTR_COMP_PRIVALG:
        !          2416:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2417:                                "attr type=%u isn't supported.\n", type);
        !          2418:                        return -1;
        !          2419: 
        !          2420:                default:
        !          2421:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2422:                                "invalid attribute type %d.\n", type);
        !          2423:                        return -1;
        !          2424:                }
        !          2425: 
        !          2426:                if (flag) {
        !          2427:                        tlen -= sizeof(*d);
        !          2428:                        d = (struct isakmp_data *)((char *)d
        !          2429:                                + sizeof(*d));
        !          2430:                } else {
        !          2431:                        tlen -= (sizeof(*d) + lorv);
        !          2432:                        d = (struct isakmp_data *)((caddr_t)d
        !          2433:                                + sizeof(*d) + lorv);
        !          2434:                }
        !          2435:        }
        !          2436: 
        !          2437:        if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
        !          2438:            !attrseen[IPSECDOI_ATTR_AUTH]) {
        !          2439:                plog(LLV_ERROR, LOCATION, NULL,
        !          2440:                        "attr AUTH must be present for AH.\n");
        !          2441:                return -1;
        !          2442:        }
        !          2443: 
        !          2444:        if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
        !          2445:            trns->t_id == IPSECDOI_ESP_NULL &&
        !          2446:            !attrseen[IPSECDOI_ATTR_AUTH]) {
        !          2447:                plog(LLV_ERROR, LOCATION, NULL,
        !          2448:                    "attr AUTH must be present for ESP NULL encryption.\n");
        !          2449:                return -1;
        !          2450:        }
        !          2451: 
        !          2452:        return 0;
        !          2453: }
        !          2454: 
        !          2455: static int
        !          2456: check_attr_ipcomp(trns)
        !          2457:        struct isakmp_pl_t *trns;
        !          2458: {
        !          2459:        struct isakmp_data *d;
        !          2460:        int tlen;
        !          2461:        int flag, type = 0;
        !          2462:        u_int16_t lorv;
        !          2463:        int attrseen[16];       /* XXX magic number */
        !          2464: 
        !          2465:        tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
        !          2466:        d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
        !          2467:        memset(attrseen, 0, sizeof(attrseen));
        !          2468: 
        !          2469:        while (tlen > 0) {
        !          2470:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
        !          2471:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
        !          2472:                lorv = ntohs(d->lorv);
        !          2473: 
        !          2474:                plog(LLV_DEBUG, LOCATION, NULL,
        !          2475:                        "type=%d, flag=0x%04x, lorv=0x%04x\n",
        !          2476:                        type, flag, lorv);
        !          2477: 
        !          2478:                if (type < sizeof(attrseen)/sizeof(attrseen[0]))
        !          2479:                        attrseen[type]++;
        !          2480: 
        !          2481:                switch (type) {
        !          2482:                case IPSECDOI_ATTR_ENC_MODE:
        !          2483:                        if (! flag) {
        !          2484:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2485:                                        "must be TV when ENC_MODE.\n");
        !          2486:                                return -1;
        !          2487:                        }
        !          2488: 
        !          2489:                        switch (lorv) {
        !          2490:                        case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
        !          2491:                        case IPSECDOI_ATTR_ENC_MODE_TRNS:
        !          2492:                                break;
        !          2493: #ifdef ENABLE_NATT
        !          2494:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
        !          2495:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
        !          2496:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
        !          2497:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
        !          2498:                                plog(LLV_DEBUG, LOCATION, NULL,
        !          2499:                                     "UDP encapsulation requested\n");
        !          2500:                                break;
        !          2501: #endif
        !          2502:                        default:
        !          2503:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2504:                                        "invalid encryption mode=%u.\n",
        !          2505:                                        lorv);
        !          2506:                                return -1;
        !          2507:                        }
        !          2508:                        break;
        !          2509: 
        !          2510:                case IPSECDOI_ATTR_SA_LD_TYPE:
        !          2511:                        if (! flag) {
        !          2512:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2513:                                        "must be TV when LD_TYPE.\n");
        !          2514:                                return -1;
        !          2515:                        }
        !          2516: 
        !          2517:                        switch (lorv) {
        !          2518:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
        !          2519:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
        !          2520:                                break;
        !          2521:                        default:
        !          2522:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2523:                                        "invalid life type %d.\n", lorv);
        !          2524:                                return -1;
        !          2525:                        }
        !          2526:                        break;
        !          2527: 
        !          2528:                case IPSECDOI_ATTR_SA_LD:
        !          2529:                        if (flag) {
        !          2530:                                /* i.e. ISAKMP_GEN_TV */
        !          2531:                                plog(LLV_DEBUG, LOCATION, NULL,
        !          2532:                                        "life duration was in TLV.\n");
        !          2533:                        } else {
        !          2534:                                /* i.e. ISAKMP_GEN_TLV */
        !          2535:                                if (lorv == 0) {
        !          2536:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          2537:                                                "invalid length of LD\n");
        !          2538:                                        return -1;
        !          2539:                                }
        !          2540:                        }
        !          2541:                        break;
        !          2542: 
        !          2543:                case IPSECDOI_ATTR_GRP_DESC:
        !          2544:                        if (! flag) {
        !          2545:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2546:                                        "must be TV when GRP_DESC.\n");
        !          2547:                                return -1;
        !          2548:                        }
        !          2549: 
        !          2550:                        if (!alg_oakley_dhdef_ok(lorv)) {
        !          2551:                                plog(LLV_ERROR, LOCATION, NULL,
        !          2552:                                        "invalid group description=%u.\n",
        !          2553:                                        lorv);
        !          2554:                                return -1;
        !          2555:                        }
        !          2556:                        break;
        !          2557: 
        !          2558:                case IPSECDOI_ATTR_AUTH:
        !          2559:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2560:                                "invalid attr type=%u.\n", type);
        !          2561:                        return -1;
        !          2562: 
        !          2563:                case IPSECDOI_ATTR_KEY_LENGTH:
        !          2564:                case IPSECDOI_ATTR_KEY_ROUNDS:
        !          2565:                case IPSECDOI_ATTR_COMP_DICT_SIZE:
        !          2566:                case IPSECDOI_ATTR_COMP_PRIVALG:
        !          2567:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2568:                                "attr type=%u isn't supported.\n", type);
        !          2569:                        return -1;
        !          2570: 
        !          2571:                default:
        !          2572:                        plog(LLV_ERROR, LOCATION, NULL,
        !          2573:                                "invalid attribute type %d.\n", type);
        !          2574:                        return -1;
        !          2575:                }
        !          2576: 
        !          2577:                if (flag) {
        !          2578:                        tlen -= sizeof(*d);
        !          2579:                        d = (struct isakmp_data *)((char *)d
        !          2580:                                + sizeof(*d));
        !          2581:                } else {
        !          2582:                        tlen -= (sizeof(*d) + lorv);
        !          2583:                        d = (struct isakmp_data *)((caddr_t)d
        !          2584:                                + sizeof(*d) + lorv);
        !          2585:                }
        !          2586:        }
        !          2587: 
        !          2588: #if 0
        !          2589:        if (proto_id == IPSECDOI_PROTO_IPCOMP &&
        !          2590:            !attrseen[IPSECDOI_ATTR_AUTH]) {
        !          2591:                plog(LLV_ERROR, LOCATION, NULL,
        !          2592:                        "attr AUTH must be present for AH.\n", type);
        !          2593:                return -1;
        !          2594:        }
        !          2595: #endif
        !          2596: 
        !          2597:        return 0;
        !          2598: }
        !          2599: 
        !          2600: /* %%% */
        !          2601: /*
        !          2602:  * create phase1 proposal from remote configuration.
        !          2603:  * NOT INCLUDING isakmp general header of SA payload
        !          2604:  */
        !          2605: vchar_t *
        !          2606: ipsecdoi_setph1proposal(rmconf, props)
        !          2607:        struct remoteconf *rmconf;
        !          2608:        struct isakmpsa *props;
        !          2609: {
        !          2610:        vchar_t *mysa;
        !          2611:        int sablen;
        !          2612: 
        !          2613:        /* count total size of SA minus isakmp general header */
        !          2614:        /* not including isakmp general header of SA payload */
        !          2615:        sablen = sizeof(struct ipsecdoi_sa_b);
        !          2616:        sablen += setph1prop(props, NULL);
        !          2617: 
        !          2618:        mysa = vmalloc(sablen);
        !          2619:        if (mysa == NULL) {
        !          2620:                plog(LLV_ERROR, LOCATION, NULL,
        !          2621:                        "failed to allocate my sa buffer\n");
        !          2622:                return NULL;
        !          2623:        }
        !          2624: 
        !          2625:        /* create SA payload */
        !          2626:        /* not including isakmp general header */
        !          2627:        ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
        !          2628:        ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
        !          2629: 
        !          2630:        (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
        !          2631: 
        !          2632:        return mysa;
        !          2633: }
        !          2634: 
        !          2635: static int
        !          2636: setph1prop(props, buf)
        !          2637:        struct isakmpsa *props;
        !          2638:        caddr_t buf;
        !          2639: {
        !          2640:        struct isakmp_pl_p *prop = NULL;
        !          2641:        struct isakmpsa *s = NULL;
        !          2642:        int proplen, trnslen;
        !          2643:        u_int8_t *np_t; /* pointer next trns type in previous header */
        !          2644:        int trns_num;
        !          2645:        caddr_t p = buf;
        !          2646: 
        !          2647:        proplen = sizeof(*prop);
        !          2648:        if (buf) {
        !          2649:                /* create proposal */
        !          2650:                prop = (struct isakmp_pl_p *)p;
        !          2651:                prop->h.np = ISAKMP_NPTYPE_NONE;
        !          2652:                prop->p_no = props->prop_no;
        !          2653:                prop->proto_id = IPSECDOI_PROTO_ISAKMP;
        !          2654:                prop->spi_size = 0;
        !          2655:                p += sizeof(*prop);
        !          2656:        }
        !          2657: 
        !          2658:        np_t = NULL;
        !          2659:        trns_num = 0;
        !          2660: 
        !          2661:        for (s = props; s != NULL; s = s->next) {
        !          2662:                if (np_t)
        !          2663:                        *np_t = ISAKMP_NPTYPE_T;
        !          2664: 
        !          2665:                trnslen = setph1trns(s, p);
        !          2666:                proplen += trnslen;
        !          2667:                if (buf) {
        !          2668:                        /* save buffer to pre-next payload */
        !          2669:                        np_t = &((struct isakmp_pl_t *)p)->h.np;
        !          2670:                        p += trnslen;
        !          2671: 
        !          2672:                        /* count up transform length */
        !          2673:                        trns_num++;
        !          2674:                }
        !          2675:        }
        !          2676: 
        !          2677:        /* update proposal length */
        !          2678:        if (buf) {
        !          2679:                prop->h.len = htons(proplen);
        !          2680:                prop->num_t = trns_num;
        !          2681:        }
        !          2682: 
        !          2683:        return proplen;
        !          2684: }
        !          2685: 
        !          2686: static int
        !          2687: setph1trns(sa, buf)
        !          2688:        struct isakmpsa *sa;
        !          2689:        caddr_t buf;
        !          2690: {
        !          2691:        struct isakmp_pl_t *trns = NULL;
        !          2692:        int trnslen, attrlen;
        !          2693:        caddr_t p = buf;
        !          2694: 
        !          2695:        trnslen = sizeof(*trns);
        !          2696:        if (buf) {
        !          2697:                /* create transform */
        !          2698:                trns = (struct isakmp_pl_t *)p;
        !          2699:                trns->h.np  = ISAKMP_NPTYPE_NONE;
        !          2700:                trns->t_no  = sa->trns_no;
        !          2701:                trns->t_id  = IPSECDOI_KEY_IKE;
        !          2702:                p += sizeof(*trns);
        !          2703:        }
        !          2704: 
        !          2705:        attrlen = setph1attr(sa, p);
        !          2706:        trnslen += attrlen;
        !          2707:        if (buf)
        !          2708:                p += attrlen;
        !          2709: 
        !          2710:        if (buf)
        !          2711:                trns->h.len = htons(trnslen);
        !          2712: 
        !          2713:        return trnslen;
        !          2714: }
        !          2715: 
        !          2716: static int
        !          2717: setph1attr(sa, buf)
        !          2718:        struct isakmpsa *sa;
        !          2719:        caddr_t buf;
        !          2720: {
        !          2721:        caddr_t p = buf;
        !          2722:        int attrlen = 0;
        !          2723: 
        !          2724:        if (sa->lifetime) {
        !          2725:                u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
        !          2726: 
        !          2727:                attrlen += sizeof(struct isakmp_data)
        !          2728:                        + sizeof(struct isakmp_data);
        !          2729:                if (sa->lifetime > 0xffff)
        !          2730:                        attrlen += sizeof(lifetime);
        !          2731:                if (buf) {
        !          2732:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
        !          2733:                                                OAKLEY_ATTR_SA_LD_TYPE_SEC);
        !          2734:                        if (sa->lifetime > 0xffff) {
        !          2735:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
        !          2736:                                                (caddr_t)&lifetime,
        !          2737:                                                sizeof(lifetime));
        !          2738:                        } else {
        !          2739:                                p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
        !          2740:                                                        sa->lifetime);
        !          2741:                        }
        !          2742:                }
        !          2743:        }
        !          2744: 
        !          2745:        if (sa->lifebyte) {
        !          2746:                u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
        !          2747: 
        !          2748:                attrlen += sizeof(struct isakmp_data)
        !          2749:                        + sizeof(struct isakmp_data);
        !          2750:                if (sa->lifebyte > 0xffff)
        !          2751:                        attrlen += sizeof(lifebyte);
        !          2752:                if (buf) {
        !          2753:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
        !          2754:                                                OAKLEY_ATTR_SA_LD_TYPE_KB);
        !          2755:                        if (sa->lifebyte > 0xffff) {
        !          2756:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
        !          2757:                                                        (caddr_t)&lifebyte,
        !          2758:                                                        sizeof(lifebyte));
        !          2759:                        } else {
        !          2760:                                p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
        !          2761:                                                        sa->lifebyte);
        !          2762:                        }
        !          2763:                }
        !          2764:        }
        !          2765: 
        !          2766:        if (sa->enctype) {
        !          2767:                attrlen += sizeof(struct isakmp_data);
        !          2768:                if (buf)
        !          2769:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
        !          2770:        }
        !          2771:        if (sa->encklen) {
        !          2772:                attrlen += sizeof(struct isakmp_data);
        !          2773:                if (buf)
        !          2774:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
        !          2775:        }
        !          2776:        if (sa->authmethod) {
        !          2777:                int authmethod;
        !          2778: 
        !          2779:                authmethod = isakmpsa_switch_authmethod(sa->authmethod);
        !          2780:                authmethod &= 0xffff;
        !          2781:                attrlen += sizeof(struct isakmp_data);
        !          2782:                if (buf)
        !          2783:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
        !          2784:        }
        !          2785:        if (sa->hashtype) {
        !          2786:                attrlen += sizeof(struct isakmp_data);
        !          2787:                if (buf)
        !          2788:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
        !          2789:        }
        !          2790:        switch (sa->dh_group) {
        !          2791:        case OAKLEY_ATTR_GRP_DESC_MODP768:
        !          2792:        case OAKLEY_ATTR_GRP_DESC_MODP1024:
        !          2793:        case OAKLEY_ATTR_GRP_DESC_MODP1536:
        !          2794:        case OAKLEY_ATTR_GRP_DESC_MODP2048:
        !          2795:        case OAKLEY_ATTR_GRP_DESC_MODP3072:
        !          2796:        case OAKLEY_ATTR_GRP_DESC_MODP4096:
        !          2797:        case OAKLEY_ATTR_GRP_DESC_MODP6144:
        !          2798:        case OAKLEY_ATTR_GRP_DESC_MODP8192:
        !          2799:                /* don't attach group type for known groups */
        !          2800:                attrlen += sizeof(struct isakmp_data);
        !          2801:                if (buf) {
        !          2802:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
        !          2803:                                sa->dh_group);
        !          2804:                }
        !          2805:                break;
        !          2806:        case OAKLEY_ATTR_GRP_DESC_EC2N155:
        !          2807:        case OAKLEY_ATTR_GRP_DESC_EC2N185:
        !          2808:                /* don't attach group type for known groups */
        !          2809:                attrlen += sizeof(struct isakmp_data);
        !          2810:                if (buf) {
        !          2811:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
        !          2812:                                OAKLEY_ATTR_GRP_TYPE_EC2N);
        !          2813:                }
        !          2814:                break;
        !          2815:        case 0:
        !          2816:        default:
        !          2817:                break;
        !          2818:        }
        !          2819: 
        !          2820: #ifdef HAVE_GSSAPI
        !          2821:        if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
        !          2822:            sa->gssid != NULL) {
        !          2823:                attrlen += sizeof(struct isakmp_data);
        !          2824:                /*
        !          2825:                 * Older versions of racoon just placed the ISO-Latin-1
        !          2826:                 * string on the wire directly.  Check to see if we are
        !          2827:                 * configured to be compatible with this behavior.  Otherwise,
        !          2828:                 * we encode the GSS ID as UTF-16LE for Windows 2000
        !          2829:                 * compatibility, which requires twice the number of octets.
        !          2830:                 */
        !          2831:                if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
        !          2832:                        attrlen += sa->gssid->l;
        !          2833:                else
        !          2834:                        attrlen += sa->gssid->l * 2;
        !          2835:                if (buf) {
        !          2836:                        plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
        !          2837:                            "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
        !          2838:                            sa->gssid->v);
        !          2839:                        if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
        !          2840:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
        !          2841:                                        (caddr_t)sa->gssid->v,
        !          2842:                                        sa->gssid->l);
        !          2843:                        } else {
        !          2844:                                size_t dstleft = sa->gssid->l * 2;
        !          2845:                                size_t srcleft = sa->gssid->l;
        !          2846:                                const char *src = (const char *)sa->gssid->v;
        !          2847:                                char *odst, *dst = racoon_malloc(dstleft);
        !          2848:                                iconv_t cd;
        !          2849:                                size_t rv;
        !          2850: 
        !          2851:                                cd = iconv_open("utf-16le", "latin1");
        !          2852:                                if (cd == (iconv_t) -1) {
        !          2853:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          2854:                                            "unable to initialize "
        !          2855:                                            "latin1 -> utf-16le "
        !          2856:                                            "converstion descriptor: %s\n",
        !          2857:                                            strerror(errno));
        !          2858:                                        attrlen -= sa->gssid->l * 2;
        !          2859:                                        goto gssid_done;
        !          2860:                                }
        !          2861:                                odst = dst;
        !          2862:                                rv = iconv(cd, (__iconv_const char **)&src,
        !          2863:                                    &srcleft, &dst, &dstleft);
        !          2864:                                if (rv != 0) {
        !          2865:                                        if (rv == -1) {
        !          2866:                                                plog(LLV_ERROR, LOCATION, NULL,
        !          2867:                                                    "unable to convert GSS ID "
        !          2868:                                                    "from latin1 -> utf-16le: "
        !          2869:                                                    "%s\n", strerror(errno));
        !          2870:                                        } else {
        !          2871:                                                /* should never happen */
        !          2872:                                                plog(LLV_ERROR, LOCATION, NULL,
        !          2873:                                                    "%zd character%s in GSS ID "
        !          2874:                                                    "cannot be represented "
        !          2875:                                                    "in utf-16le\n",
        !          2876:                                                    rv, rv == 1 ? "" : "s");
        !          2877:                                        }
        !          2878:                                        (void) iconv_close(cd);
        !          2879:                                        attrlen -= sa->gssid->l * 2;
        !          2880:                                        goto gssid_done;
        !          2881:                                }
        !          2882:                                (void) iconv_close(cd);
        !          2883: 
        !          2884:                                /* XXX Check srcleft and dstleft? */
        !          2885: 
        !          2886:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
        !          2887:                                        odst, sa->gssid->l * 2);
        !          2888: 
        !          2889:                                racoon_free(odst);
        !          2890:                        }
        !          2891:                }
        !          2892:        }
        !          2893:  gssid_done:
        !          2894: #endif /* HAVE_GSSAPI */
        !          2895: 
        !          2896:        return attrlen;
        !          2897: }
        !          2898: 
        !          2899: static vchar_t *
        !          2900: setph2proposal0(iph2, pp, pr)
        !          2901:        const struct ph2handle *iph2;
        !          2902:        const struct saprop *pp;
        !          2903:        const struct saproto *pr;
        !          2904: {
        !          2905:        vchar_t *p;
        !          2906:        struct isakmp_pl_p *prop;
        !          2907:        struct isakmp_pl_t *trns;
        !          2908:        struct satrns *tr;
        !          2909:        int attrlen;
        !          2910:        size_t trnsoff;
        !          2911:        caddr_t x0, x;
        !          2912:        u_int8_t *np_t; /* pointer next trns type in previous header */
        !          2913:        const u_int8_t *spi;
        !          2914: #ifdef HAVE_SECCTX
        !          2915:        int truectxlen = 0;
        !          2916: #endif
        !          2917: 
        !          2918:        p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
        !          2919:        if (p == NULL)
        !          2920:                return NULL;
        !          2921: 
        !          2922:        /* create proposal */
        !          2923:        prop = (struct isakmp_pl_p *)p->v;
        !          2924:        prop->h.np = ISAKMP_NPTYPE_NONE;
        !          2925:        prop->p_no = pp->prop_no;
        !          2926:        prop->proto_id = pr->proto_id;
        !          2927:        prop->num_t = 1;
        !          2928: 
        !          2929:        spi = (const u_int8_t *)&pr->spi;
        !          2930:        switch (pr->proto_id) {
        !          2931:        case IPSECDOI_PROTO_IPCOMP:
        !          2932:                /*
        !          2933:                 * draft-shacham-ippcp-rfc2393bis-05.txt:
        !          2934:                 * construct 16bit SPI (CPI).
        !          2935:                 * XXX we may need to provide a configuration option to
        !          2936:                 * generate 32bit SPI.  otherwise we cannot interoeprate
        !          2937:                 * with nodes that uses 32bit SPI, in case we are initiator.
        !          2938:                 */
        !          2939:                prop->spi_size = sizeof(u_int16_t);
        !          2940:                spi += sizeof(pr->spi) - sizeof(u_int16_t);
        !          2941:                p->l -= sizeof(pr->spi);
        !          2942:                p->l += sizeof(u_int16_t);
        !          2943:                break;
        !          2944:        default:
        !          2945:                prop->spi_size = sizeof(pr->spi);
        !          2946:                break;
        !          2947:        }
        !          2948:        memcpy(prop + 1, spi, prop->spi_size);
        !          2949: 
        !          2950:        /* create transform */
        !          2951:        trnsoff = sizeof(*prop) + prop->spi_size;
        !          2952:        np_t = NULL;
        !          2953: 
        !          2954:        for (tr = pr->head; tr; tr = tr->next) {
        !          2955: 
        !          2956:                switch (pr->proto_id) {
        !          2957:                case IPSECDOI_PROTO_IPSEC_ESP:
        !          2958:                        /*
        !          2959:                         * don't build a null encryption
        !          2960:                         * with no authentication transform.
        !          2961:                         */
        !          2962:                        if (tr->trns_id == IPSECDOI_ESP_NULL &&
        !          2963:                            tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
        !          2964:                                continue;
        !          2965:                        break;
        !          2966:                }
        !          2967: 
        !          2968:                if (np_t) {
        !          2969:                        *np_t = ISAKMP_NPTYPE_T;
        !          2970:                        prop->num_t++;
        !          2971:                }
        !          2972: 
        !          2973:                /* get attribute length */
        !          2974:                attrlen = 0;
        !          2975:                if (pp->lifetime) {
        !          2976:                        attrlen += sizeof(struct isakmp_data)
        !          2977:                                + sizeof(struct isakmp_data);
        !          2978:                        if (pp->lifetime > 0xffff)
        !          2979:                                attrlen += sizeof(u_int32_t);
        !          2980:                }
        !          2981:                if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
        !          2982:                        attrlen += sizeof(struct isakmp_data)
        !          2983:                                + sizeof(struct isakmp_data);
        !          2984:                        if (pp->lifebyte > 0xffff)
        !          2985:                                attrlen += sizeof(u_int32_t);
        !          2986:                }
        !          2987:                attrlen += sizeof(struct isakmp_data);  /* enc mode */
        !          2988:                if (tr->encklen)
        !          2989:                        attrlen += sizeof(struct isakmp_data);
        !          2990: 
        !          2991:                switch (pr->proto_id) {
        !          2992:                case IPSECDOI_PROTO_IPSEC_ESP:
        !          2993:                        /* non authentication mode ? */
        !          2994:                        if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
        !          2995:                                attrlen += sizeof(struct isakmp_data);
        !          2996:                        break;
        !          2997:                case IPSECDOI_PROTO_IPSEC_AH:
        !          2998:                        if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
        !          2999:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3000:                                        "no authentication algorithm found "
        !          3001:                                        "but protocol is AH.\n");
        !          3002:                                vfree(p);
        !          3003:                                return NULL;
        !          3004:                        }
        !          3005:                        attrlen += sizeof(struct isakmp_data);
        !          3006:                        break;
        !          3007:                case IPSECDOI_PROTO_IPCOMP:
        !          3008:                        break;
        !          3009:                default:
        !          3010:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3011:                                "invalid protocol: %d\n", pr->proto_id);
        !          3012:                        vfree(p);
        !          3013:                        return NULL;
        !          3014:                }
        !          3015: 
        !          3016:                if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
        !          3017:                        attrlen += sizeof(struct isakmp_data);
        !          3018: 
        !          3019: #ifdef HAVE_SECCTX
        !          3020:                /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
        !          3021:                 * The string may be smaller than MAX_CTXSTR_SIZ.
        !          3022:                 */
        !          3023:                if (*pp->sctx.ctx_str) {
        !          3024:                        truectxlen = sizeof(struct security_ctx) -
        !          3025:                                     (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
        !          3026:                        attrlen += sizeof(struct isakmp_data) + truectxlen;
        !          3027:                }
        !          3028: #endif /* HAVE_SECCTX */
        !          3029: 
        !          3030:                p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
        !          3031:                if (p == NULL)
        !          3032:                        return NULL;
        !          3033:                prop = (struct isakmp_pl_p *)p->v;
        !          3034: 
        !          3035:                /* set transform's values */
        !          3036:                trns = (struct isakmp_pl_t *)(p->v + trnsoff);
        !          3037:                trns->h.np  = ISAKMP_NPTYPE_NONE;
        !          3038:                trns->t_no  = tr->trns_no;
        !          3039:                trns->t_id  = tr->trns_id;
        !          3040: 
        !          3041:                /* set attributes */
        !          3042:                x = x0 = p->v + trnsoff + sizeof(*trns);
        !          3043: 
        !          3044:                if (pp->lifetime) {
        !          3045:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
        !          3046:                                                IPSECDOI_ATTR_SA_LD_TYPE_SEC);
        !          3047:                        if (pp->lifetime > 0xffff) {
        !          3048:                                u_int32_t v = htonl((u_int32_t)pp->lifetime);
        !          3049:                                x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
        !          3050:                                                        (caddr_t)&v, sizeof(v));
        !          3051:                        } else {
        !          3052:                                x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
        !          3053:                                                        pp->lifetime);
        !          3054:                        }
        !          3055:                }
        !          3056: 
        !          3057:                if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
        !          3058:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
        !          3059:                                                IPSECDOI_ATTR_SA_LD_TYPE_KB);
        !          3060:                        if (pp->lifebyte > 0xffff) {
        !          3061:                                u_int32_t v = htonl((u_int32_t)pp->lifebyte);
        !          3062:                                x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
        !          3063:                                                        (caddr_t)&v, sizeof(v));
        !          3064:                        } else {
        !          3065:                                x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
        !          3066:                                                        pp->lifebyte);
        !          3067:                        }
        !          3068:                }
        !          3069: 
        !          3070:                x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
        !          3071: 
        !          3072:                if (tr->encklen)
        !          3073:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
        !          3074: 
        !          3075:                /* mandatory check has done above. */
        !          3076:                if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
        !          3077:                 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
        !          3078:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
        !          3079: 
        !          3080:                if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
        !          3081:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
        !          3082:                                iph2->sainfo->pfs_group);
        !          3083: 
        !          3084: #ifdef HAVE_SECCTX
        !          3085:                if (*pp->sctx.ctx_str) {
        !          3086:                        struct security_ctx secctx;
        !          3087:                        secctx = pp->sctx;
        !          3088:                        secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
        !          3089:                        x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
        !          3090:                                             (caddr_t)&secctx, truectxlen);
        !          3091:                }
        !          3092: #endif
        !          3093:                /* update length of this transform. */
        !          3094:                trns = (struct isakmp_pl_t *)(p->v + trnsoff);
        !          3095:                trns->h.len = htons(sizeof(*trns) + attrlen);
        !          3096: 
        !          3097:                /* save buffer to pre-next payload */
        !          3098:                np_t = &trns->h.np;
        !          3099: 
        !          3100:                trnsoff += (sizeof(*trns) + attrlen);
        !          3101:        }
        !          3102: 
        !          3103:        if (np_t == NULL) {
        !          3104:                plog(LLV_ERROR, LOCATION, NULL,
        !          3105:                        "no suitable proposal was created.\n");
        !          3106:                return NULL;
        !          3107:        }
        !          3108: 
        !          3109:        /* update length of this protocol. */
        !          3110:        prop->h.len = htons(p->l);
        !          3111: 
        !          3112:        return p;
        !          3113: }
        !          3114: 
        !          3115: /*
        !          3116:  * create phase2 proposal from policy configuration.
        !          3117:  * NOT INCLUDING isakmp general header of SA payload.
        !          3118:  * This function is called by initiator only.
        !          3119:  */
        !          3120: int
        !          3121: ipsecdoi_setph2proposal(iph2)
        !          3122:        struct ph2handle *iph2;
        !          3123: {
        !          3124:        struct saprop *proposal, *a;
        !          3125:        struct saproto *b = NULL;
        !          3126:        vchar_t *q;
        !          3127:        struct ipsecdoi_sa_b *sab;
        !          3128:        struct isakmp_pl_p *prop;
        !          3129:        size_t propoff; /* for previous field of type of next payload. */
        !          3130: 
        !          3131:        proposal = iph2->proposal;
        !          3132: 
        !          3133:        iph2->sa = vmalloc(sizeof(*sab));
        !          3134:        if (iph2->sa == NULL) {
        !          3135:                plog(LLV_ERROR, LOCATION, NULL,
        !          3136:                        "failed to allocate my sa buffer\n");
        !          3137:                return -1;
        !          3138:        }
        !          3139: 
        !          3140:        /* create SA payload */
        !          3141:        sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
        !          3142:        sab->doi = htonl(IPSEC_DOI);
        !          3143:        sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY);   /* XXX configurable ? */
        !          3144: 
        !          3145:        prop = NULL;
        !          3146:        propoff = 0;
        !          3147:        for (a = proposal; a; a = a->next) {
        !          3148:                for (b = a->head; b; b = b->next) {
        !          3149: #ifdef ENABLE_NATT
        !          3150:                        if (iph2->ph1->natt_flags & NAT_DETECTED) {
        !          3151:                          int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
        !          3152:                          plog (LLV_INFO, LOCATION, NULL,
        !          3153:                                "NAT detected -> UDP encapsulation "
        !          3154:                                "(ENC_MODE %d->%d).\n",
        !          3155:                                b->encmode,
        !          3156:                                b->encmode+udp_diff);
        !          3157:                          /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
        !          3158:                          b->encmode += udp_diff;
        !          3159:                          b->udp_encap = 1;
        !          3160:                        }
        !          3161: #endif
        !          3162: 
        !          3163:                        q = setph2proposal0(iph2, a, b);
        !          3164:                        if (q == NULL) {
        !          3165:                                VPTRINIT(iph2->sa);
        !          3166:                                return -1;
        !          3167:                        }
        !          3168: 
        !          3169:                        iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
        !          3170:                        if (iph2->sa == NULL) {
        !          3171:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3172:                                        "failed to allocate my sa buffer\n");
        !          3173:                                if (q)
        !          3174:                                        vfree(q);
        !          3175:                                return -1;
        !          3176:                        }
        !          3177:                        memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
        !          3178:                        if (propoff != 0) {
        !          3179:                                prop = (struct isakmp_pl_p *)(iph2->sa->v +
        !          3180:                                        propoff);
        !          3181:                                prop->h.np = ISAKMP_NPTYPE_P;
        !          3182:                        }
        !          3183:                        propoff = iph2->sa->l - q->l;
        !          3184: 
        !          3185:                        vfree(q);
        !          3186:                }
        !          3187:        }
        !          3188: 
        !          3189:        return 0;
        !          3190: }
        !          3191: 
        !          3192: /*
        !          3193:  * return 1 if all of the given protocols are transport mode.
        !          3194:  */
        !          3195: int
        !          3196: ipsecdoi_transportmode(pp)
        !          3197:        struct saprop *pp;
        !          3198: {
        !          3199:        struct saproto *pr = NULL;
        !          3200: 
        !          3201:        for (; pp; pp = pp->next) {
        !          3202:                for (pr = pp->head; pr; pr = pr->next) {
        !          3203:                        if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
        !          3204:                            pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
        !          3205:                            pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
        !          3206:                                return 0;
        !          3207:                }
        !          3208:        }
        !          3209: 
        !          3210:        return 1;
        !          3211: }
        !          3212: 
        !          3213: int
        !          3214: ipsecdoi_get_defaultlifetime()
        !          3215: {
        !          3216:        return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
        !          3217: }
        !          3218: 
        !          3219: int
        !          3220: ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
        !          3221:        int proto_id, enc, auth, comp;
        !          3222: {
        !          3223: #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
        !          3224:        switch (proto_id) {
        !          3225:        case IPSECDOI_PROTO_IPSEC_ESP:
        !          3226:                if (enc == 0 || comp != 0) {
        !          3227:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3228:                                "illegal algorithm defined "
        !          3229:                                "ESP enc=%s auth=%s comp=%s.\n",
        !          3230:                                TMPALGTYPE2STR(enc),
        !          3231:                                TMPALGTYPE2STR(auth),
        !          3232:                                TMPALGTYPE2STR(comp));
        !          3233:                        return -1;
        !          3234:                }
        !          3235:                break;
        !          3236:        case IPSECDOI_PROTO_IPSEC_AH:
        !          3237:                if (enc != 0 || auth == 0 || comp != 0) {
        !          3238:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3239:                                "illegal algorithm defined "
        !          3240:                                "AH enc=%s auth=%s comp=%s.\n",
        !          3241:                                TMPALGTYPE2STR(enc),
        !          3242:                                TMPALGTYPE2STR(auth),
        !          3243:                                TMPALGTYPE2STR(comp));
        !          3244:                        return -1;
        !          3245:                }
        !          3246:                break;
        !          3247:        case IPSECDOI_PROTO_IPCOMP:
        !          3248:                if (enc != 0 || auth != 0 || comp == 0) {
        !          3249:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3250:                                "illegal algorithm defined "
        !          3251:                                "IPcomp enc=%s auth=%s comp=%s.\n",
        !          3252:                                TMPALGTYPE2STR(enc),
        !          3253:                                TMPALGTYPE2STR(auth),
        !          3254:                                TMPALGTYPE2STR(comp));
        !          3255:                        return -1;
        !          3256:                }
        !          3257:                break;
        !          3258:        default:
        !          3259:                plog(LLV_ERROR, LOCATION, NULL,
        !          3260:                        "invalid ipsec protocol %d\n", proto_id);
        !          3261:                return -1;
        !          3262:        }
        !          3263: #undef TMPALGTYPE2STR
        !          3264:        return 0;
        !          3265: }
        !          3266: 
        !          3267: int
        !          3268: ipproto2doi(proto)
        !          3269:        int proto;
        !          3270: {
        !          3271:        switch (proto) {
        !          3272:        case IPPROTO_AH:
        !          3273:                return IPSECDOI_PROTO_IPSEC_AH;
        !          3274:        case IPPROTO_ESP:
        !          3275:                return IPSECDOI_PROTO_IPSEC_ESP;
        !          3276:        case IPPROTO_IPCOMP:
        !          3277:                return IPSECDOI_PROTO_IPCOMP;
        !          3278:        }
        !          3279:        return -1;      /* XXX */
        !          3280: }
        !          3281: 
        !          3282: int
        !          3283: doi2ipproto(proto)
        !          3284:        int proto;
        !          3285: {
        !          3286:        switch (proto) {
        !          3287:        case IPSECDOI_PROTO_IPSEC_AH:
        !          3288:                return IPPROTO_AH;
        !          3289:        case IPSECDOI_PROTO_IPSEC_ESP:
        !          3290:                return IPPROTO_ESP;
        !          3291:        case IPSECDOI_PROTO_IPCOMP:
        !          3292:                return IPPROTO_IPCOMP;
        !          3293:        }
        !          3294:        return -1;      /* XXX */
        !          3295: }
        !          3296: 
        !          3297: /*
        !          3298:  * Check if a subnet id is valid for comparison
        !          3299:  * with an address id ( address length mask )
        !          3300:  * and compare them
        !          3301:  * Return value
        !          3302:  * =  0 for match
        !          3303:  * =  1 for mismatch
        !          3304:  */
        !          3305: 
        !          3306: int
        !          3307: ipsecdoi_subnetisaddr_v4( subnet, address )
        !          3308:        const vchar_t *subnet;
        !          3309:        const vchar_t *address;
        !          3310: {
        !          3311:        struct in_addr *mask;
        !          3312: 
        !          3313:        if (address->l != sizeof(struct in_addr))
        !          3314:                return 1;
        !          3315: 
        !          3316:        if (subnet->l != (sizeof(struct in_addr)*2))
        !          3317:                return 1;
        !          3318: 
        !          3319:        mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
        !          3320: 
        !          3321:        if (mask->s_addr!=0xffffffff)
        !          3322:                return 1;
        !          3323: 
        !          3324:        return memcmp(subnet->v,address->v,address->l);
        !          3325: }
        !          3326: 
        !          3327: #ifdef INET6
        !          3328: 
        !          3329: int
        !          3330: ipsecdoi_subnetisaddr_v6( subnet, address )
        !          3331:        const vchar_t *subnet;
        !          3332:        const vchar_t *address;
        !          3333: {
        !          3334:        struct in6_addr *mask;
        !          3335:        int i;
        !          3336: 
        !          3337:        if (address->l != sizeof(struct in6_addr))
        !          3338:                return 1;
        !          3339: 
        !          3340:        if (subnet->l != (sizeof(struct in6_addr)*2))
        !          3341:                return 1;
        !          3342: 
        !          3343:        mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
        !          3344: 
        !          3345:        for (i=0; i<16; i++)
        !          3346:                if(mask->s6_addr[i]!=0xff)
        !          3347:                        return 1;
        !          3348: 
        !          3349:        return memcmp(subnet->v,address->v,address->l);
        !          3350: }
        !          3351: 
        !          3352: #endif
        !          3353: 
        !          3354: /*
        !          3355:  * Check and Compare two IDs
        !          3356:  * - specify 0 for exact if wildcards are allowed
        !          3357:  * Return value
        !          3358:  * =  0 for match
        !          3359:  * =  1 for misatch
        !          3360:  * = -1 for integrity error
        !          3361:  */
        !          3362: 
        !          3363: int
        !          3364: ipsecdoi_chkcmpids( idt, ids, exact )
        !          3365:        const vchar_t *idt; /* id cmp target */
        !          3366:        const vchar_t *ids; /* id cmp source */
        !          3367:        int exact;
        !          3368: {
        !          3369:        struct ipsecdoi_id_b *id_bt;
        !          3370:        struct ipsecdoi_id_b *id_bs;
        !          3371:        vchar_t ident_t;
        !          3372:        vchar_t ident_s;
        !          3373:        int result;
        !          3374: 
        !          3375:        /* handle wildcard IDs */
        !          3376: 
        !          3377:        if (idt == NULL || ids == NULL)
        !          3378:        {
        !          3379:                if( !exact )
        !          3380:                {
        !          3381:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          3382:                                "check and compare ids : values matched (ANONYMOUS)\n" );
        !          3383:                        return 0;
        !          3384:                }
        !          3385:                else
        !          3386:                {
        !          3387:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          3388:                                "check and compare ids : value mismatch (ANONYMOUS)\n" );
        !          3389:                        return -1;
        !          3390:                }
        !          3391:        }
        !          3392: 
        !          3393:        /* make sure the ids are of the same type */
        !          3394: 
        !          3395:        id_bt = (struct ipsecdoi_id_b *) idt->v;
        !          3396:        id_bs = (struct ipsecdoi_id_b *) ids->v;
        !          3397: 
        !          3398:        ident_t.v = idt->v + sizeof(*id_bt);
        !          3399:        ident_t.l = idt->l - sizeof(*id_bt);
        !          3400:        ident_s.v = ids->v + sizeof(*id_bs);
        !          3401:        ident_s.l = ids->l - sizeof(*id_bs);
        !          3402: 
        !          3403:        if (id_bs->type != id_bt->type)
        !          3404:        {
        !          3405:                /*
        !          3406:                 * special exception for comparing
        !          3407:                  * address to subnet id types when
        !          3408:                  * the netmask is address length
        !          3409:                  */
        !          3410: 
        !          3411:                if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
        !          3412:                    (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
        !          3413:                        result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
        !          3414:                        goto cmpid_result;
        !          3415:                }
        !          3416: 
        !          3417:                if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
        !          3418:                    (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
        !          3419:                        result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
        !          3420:                        goto cmpid_result;
        !          3421:                }
        !          3422: 
        !          3423: #ifdef INET6
        !          3424:                if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
        !          3425:                    (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
        !          3426:                        result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
        !          3427:                        goto cmpid_result;
        !          3428:                }
        !          3429: 
        !          3430:                if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
        !          3431:                    (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
        !          3432:                        result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
        !          3433:                        goto cmpid_result;
        !          3434:                }
        !          3435: #endif
        !          3436:                plog(LLV_DEBUG, LOCATION, NULL,
        !          3437:                        "check and compare ids : id type mismatch %s != %s\n",
        !          3438:                        s_ipsecdoi_ident(id_bs->type),
        !          3439:                        s_ipsecdoi_ident(id_bt->type));
        !          3440: 
        !          3441:                return 1;
        !          3442:        }
        !          3443: 
        !          3444:        if(id_bs->proto_id != id_bt->proto_id){
        !          3445:                plog(LLV_DEBUG, LOCATION, NULL,
        !          3446:                        "check and compare ids : proto_id mismatch %d != %d\n",
        !          3447:                        id_bs->proto_id, id_bt->proto_id);
        !          3448: 
        !          3449:                return 1;
        !          3450:        }
        !          3451: 
        !          3452:        /* compare the ID data. */
        !          3453: 
        !          3454:        switch (id_bt->type) {
        !          3455:                case IPSECDOI_ID_DER_ASN1_DN:
        !          3456:                case IPSECDOI_ID_DER_ASN1_GN:
        !          3457:                        /* compare asn1 ids */
        !          3458:                        result = eay_cmp_asn1dn(&ident_t, &ident_s);
        !          3459:                        goto cmpid_result;
        !          3460: 
        !          3461:                case IPSECDOI_ID_IPV4_ADDR:
        !          3462:                        /* validate lengths */
        !          3463:                        if ((ident_t.l != sizeof(struct in_addr))||
        !          3464:                            (ident_s.l != sizeof(struct in_addr)))
        !          3465:                                goto cmpid_invalid;
        !          3466:                        break;
        !          3467: 
        !          3468:                case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          3469:                case IPSECDOI_ID_IPV4_ADDR_RANGE:
        !          3470:                        /* validate lengths */
        !          3471:                        if ((ident_t.l != (sizeof(struct in_addr)*2))||
        !          3472:                            (ident_s.l != (sizeof(struct in_addr)*2)))
        !          3473:                                goto cmpid_invalid;
        !          3474:                        break;
        !          3475: 
        !          3476: #ifdef INET6
        !          3477:                case IPSECDOI_ID_IPV6_ADDR:
        !          3478:                        /* validate lengths */
        !          3479:                        if ((ident_t.l != sizeof(struct in6_addr))||
        !          3480:                            (ident_s.l != sizeof(struct in6_addr)))
        !          3481:                                goto cmpid_invalid;
        !          3482:                        break;
        !          3483: 
        !          3484:                case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          3485:                case IPSECDOI_ID_IPV6_ADDR_RANGE:
        !          3486:                        /* validate lengths */
        !          3487:                        if ((ident_t.l != (sizeof(struct in6_addr)*2))||
        !          3488:                            (ident_s.l != (sizeof(struct in6_addr)*2)))
        !          3489:                                goto cmpid_invalid;
        !          3490:                        break;
        !          3491: #endif
        !          3492:                case IPSECDOI_ID_FQDN:
        !          3493:                case IPSECDOI_ID_USER_FQDN:
        !          3494:                case IPSECDOI_ID_KEY_ID:
        !          3495:                        break;
        !          3496: 
        !          3497:                default:
        !          3498:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3499:                                "Unhandled id type %i specified for comparison\n",
        !          3500:                                id_bt->type);
        !          3501:                        return -1;
        !          3502:        }
        !          3503: 
        !          3504:        /* validate matching data and length */
        !          3505:        if (ident_t.l == ident_s.l)
        !          3506:                result = memcmp(ident_t.v,ident_s.v,ident_t.l);
        !          3507:        else
        !          3508:                result = 1;
        !          3509: 
        !          3510: cmpid_result:
        !          3511: 
        !          3512:        /* debug level output */
        !          3513:        if(loglevel >= LLV_DEBUG) {
        !          3514:                char *idstrt = ipsecdoi_id2str(idt);
        !          3515:                char *idstrs = ipsecdoi_id2str(ids);
        !          3516: 
        !          3517:                if (!result)
        !          3518:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          3519:                                "check and compare ids : values matched (%s)\n",
        !          3520:                                 s_ipsecdoi_ident(id_bs->type) );
        !          3521:                else
        !          3522:                        plog(LLV_DEBUG, LOCATION, NULL,
        !          3523:                                "check and compare ids : value mismatch (%s)\n",
        !          3524:                                 s_ipsecdoi_ident(id_bs->type));
        !          3525: 
        !          3526:                plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
        !          3527:                plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
        !          3528: 
        !          3529:                racoon_free(idstrs);
        !          3530:                racoon_free(idstrt);
        !          3531:        }
        !          3532: 
        !          3533:        /* return result */
        !          3534:        if( !result )
        !          3535:                return 0;
        !          3536:        else
        !          3537:                return 1;
        !          3538: 
        !          3539: cmpid_invalid:
        !          3540: 
        !          3541:        /* id integrity error */
        !          3542:        plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
        !          3543:                s_ipsecdoi_ident(id_bs->type));
        !          3544:        plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
        !          3545:        plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
        !          3546: 
        !          3547:        return -1;
        !          3548: }
        !          3549: 
        !          3550: /*
        !          3551:  * check the following:
        !          3552:  * - In main mode with pre-shared key, only address type can be used.
        !          3553:  * - if proper type for phase 1 ?
        !          3554:  * - if phase 1 ID payload conformed RFC2407 4.6.2.
        !          3555:  *   (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
        !          3556:  * - if ID payload sent from peer is equal to the ID expected by me.
        !          3557:  *
        !          3558:  * both of "id" and "id_p" should be ID payload without general header,
        !          3559:  */
        !          3560: int
        !          3561: ipsecdoi_checkid1(iph1)
        !          3562:        struct ph1handle *iph1;
        !          3563: {
        !          3564:        struct ipsecdoi_id_b *id_b;
        !          3565: 
        !          3566:        if (iph1->id_p == NULL) {
        !          3567:                plog(LLV_ERROR, LOCATION, NULL,
        !          3568:                        "invalid iph1 passed id_p == NULL\n");
        !          3569:                return ISAKMP_INTERNAL_ERROR;
        !          3570:        }
        !          3571:        if (iph1->id_p->l < sizeof(*id_b)) {
        !          3572:                plog(LLV_ERROR, LOCATION, NULL,
        !          3573:                        "invalid value passed as \"ident\" (len=%lu)\n",
        !          3574:                        (u_long)iph1->id_p->l);
        !          3575:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
        !          3576:        }
        !          3577: 
        !          3578:        id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
        !          3579: 
        !          3580:        /* In main mode with pre-shared key, only address type can be used. */
        !          3581:        if (iph1->etype == ISAKMP_ETYPE_IDENT &&
        !          3582:            iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
        !          3583:                 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
        !          3584:                  && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
        !          3585:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3586:                                "Expecting IP address type in main mode, "
        !          3587:                                "but %s.\n", s_ipsecdoi_ident(id_b->type));
        !          3588:                        return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
        !          3589:                }
        !          3590:        }
        !          3591: 
        !          3592:        /* if proper type for phase 1 ? */
        !          3593:        switch (id_b->type) {
        !          3594:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          3595:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          3596:        case IPSECDOI_ID_IPV4_ADDR_RANGE:
        !          3597:        case IPSECDOI_ID_IPV6_ADDR_RANGE:
        !          3598:                plog(LLV_WARNING, LOCATION, NULL,
        !          3599:                        "such ID type %s is not proper.\n",
        !          3600:                        s_ipsecdoi_ident(id_b->type));
        !          3601:                /*FALLTHROUGH*/
        !          3602:        }
        !          3603: 
        !          3604:        /* if phase 1 ID payload conformed RFC2407 4.6.2. */
        !          3605:        if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
        !          3606:            id_b->type == IPSECDOI_ID_IPV6_ADDR) {
        !          3607: 
        !          3608:                if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
        !          3609:                        plog(LLV_WARNING, LOCATION, NULL,
        !          3610:                                "protocol ID and Port mismatched. "
        !          3611:                                "proto_id:%d port:%d\n",
        !          3612:                                id_b->proto_id, ntohs(id_b->port));
        !          3613:                        /*FALLTHROUGH*/
        !          3614: 
        !          3615:                } else if (id_b->proto_id == IPPROTO_UDP) {
        !          3616:                        /*
        !          3617:                         * copmaring with expecting port.
        !          3618:                         * always permit if port is equal to PORT_ISAKMP
        !          3619:                         */
        !          3620:                        if (ntohs(id_b->port) != PORT_ISAKMP) {
        !          3621:                                u_int16_t port;
        !          3622: 
        !          3623:                                port = extract_port(iph1->remote);
        !          3624:                                if (ntohs(id_b->port) != port) {
        !          3625:                                        plog(LLV_WARNING, LOCATION, NULL,
        !          3626:                                                "port %d expected, but %d\n",
        !          3627:                                                port, ntohs(id_b->port));
        !          3628:                                        /*FALLTHROUGH*/
        !          3629:                                }
        !          3630:                        }
        !          3631:                }
        !          3632:        }
        !          3633: 
        !          3634:        /* resolve remote configuration if not done yet */
        !          3635:        if (resolveph1rmconf(iph1) < 0)
        !          3636:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
        !          3637: 
        !          3638:        if (iph1->rmconf == NULL)
        !          3639:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
        !          3640: 
        !          3641:        return 0;
        !          3642: }
        !          3643: 
        !          3644: /*
        !          3645:  * create ID payload for phase 1 and set into iph1->id.
        !          3646:  * NOT INCLUDING isakmp general header.
        !          3647:  * see, RFC2407 4.6.2.1
        !          3648:  */
        !          3649: int
        !          3650: ipsecdoi_setid1(iph1)
        !          3651:        struct ph1handle *iph1;
        !          3652: {
        !          3653:        vchar_t *ret = NULL;
        !          3654:        struct ipsecdoi_id_b id_b;
        !          3655:        vchar_t *ident = NULL;
        !          3656:        struct sockaddr *ipid = NULL;
        !          3657: 
        !          3658:        /* init */
        !          3659:        id_b.proto_id = 0;
        !          3660:        id_b.port = 0;
        !          3661:        ident = NULL;
        !          3662: 
        !          3663:        switch (iph1->rmconf->idvtype) {
        !          3664:        case IDTYPE_FQDN:
        !          3665:                id_b.type = IPSECDOI_ID_FQDN;
        !          3666:                ident = vdup(iph1->rmconf->idv);
        !          3667:                break;
        !          3668:        case IDTYPE_USERFQDN:
        !          3669:                id_b.type = IPSECDOI_ID_USER_FQDN;
        !          3670:                ident = vdup(iph1->rmconf->idv);
        !          3671:                break;
        !          3672:        case IDTYPE_KEYID:
        !          3673:                id_b.type = IPSECDOI_ID_KEY_ID;
        !          3674:                ident = vdup(iph1->rmconf->idv);
        !          3675:                break;
        !          3676:        case IDTYPE_ASN1DN:
        !          3677:                id_b.type = IPSECDOI_ID_DER_ASN1_DN;
        !          3678:                if (iph1->rmconf->idv) {
        !          3679:                        /* XXX it must be encoded to asn1dn. */
        !          3680:                        ident = vdup(iph1->rmconf->idv);
        !          3681:                } else {
        !          3682:                        if (oakley_getmycert(iph1) < 0) {
        !          3683:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3684:                                        "failed to get own CERT.\n");
        !          3685:                                goto err;
        !          3686:                        }
        !          3687:                        ident = eay_get_x509asn1subjectname(iph1->cert);
        !          3688:                }
        !          3689:                break;
        !          3690:        case IDTYPE_ADDRESS:
        !          3691:                /*
        !          3692:                 * if the value of the id type was set by the configuration
        !          3693:                 * file, then use it.  otherwise the value is get from local
        !          3694:                 * ip address by using ike negotiation.
        !          3695:                 */
        !          3696:                if (iph1->rmconf->idv)
        !          3697:                        ipid = (struct sockaddr *)iph1->rmconf->idv->v;
        !          3698:                /*FALLTHROUGH*/
        !          3699:        default:
        !          3700:            {
        !          3701:                int l;
        !          3702:                caddr_t p;
        !          3703: 
        !          3704:                if (ipid == NULL)
        !          3705:                        ipid = iph1->local;
        !          3706: 
        !          3707:                /* use IP address */
        !          3708:                switch (ipid->sa_family) {
        !          3709:                case AF_INET:
        !          3710:                        id_b.type = IPSECDOI_ID_IPV4_ADDR;
        !          3711:                        l = sizeof(struct in_addr);
        !          3712:                        p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
        !          3713:                        break;
        !          3714: #ifdef INET6
        !          3715:                case AF_INET6:
        !          3716:                        id_b.type = IPSECDOI_ID_IPV6_ADDR;
        !          3717:                        l = sizeof(struct in6_addr);
        !          3718:                        p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
        !          3719:                        break;
        !          3720: #endif
        !          3721:                default:
        !          3722:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3723:                                "invalid address family.\n");
        !          3724:                        goto err;
        !          3725:                }
        !          3726:                id_b.proto_id = IPPROTO_UDP;
        !          3727:                id_b.port = htons(PORT_ISAKMP);
        !          3728:                ident = vmalloc(l);
        !          3729:                if (!ident) {
        !          3730:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3731:                                "failed to get ID buffer.\n");
        !          3732:                        return -1;
        !          3733:                }
        !          3734:                memcpy(ident->v, p, ident->l);
        !          3735:            }
        !          3736:        }
        !          3737:        if (!ident) {
        !          3738:                plog(LLV_ERROR, LOCATION, NULL,
        !          3739:                        "failed to get ID buffer.\n");
        !          3740:                return -1;
        !          3741:        }
        !          3742: 
        !          3743:        ret = vmalloc(sizeof(id_b) + ident->l);
        !          3744:        if (ret == NULL) {
        !          3745:                plog(LLV_ERROR, LOCATION, NULL,
        !          3746:                        "failed to get ID buffer.\n");
        !          3747:                goto err;
        !          3748:        }
        !          3749: 
        !          3750:        memcpy(ret->v, &id_b, sizeof(id_b));
        !          3751:        memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
        !          3752: 
        !          3753:        iph1->id = ret;
        !          3754: 
        !          3755:        plog(LLV_DEBUG, LOCATION, NULL,
        !          3756:                "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
        !          3757:        if (ident)
        !          3758:                vfree(ident);
        !          3759:        return 0;
        !          3760: 
        !          3761: err:
        !          3762:        if (ident)
        !          3763:                vfree(ident);
        !          3764:        plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
        !          3765:        return -1;
        !          3766: }
        !          3767: 
        !          3768: /* it's only called by cfparse.y. */
        !          3769: int
        !          3770: set_identifier(vpp, type, value)
        !          3771:        vchar_t **vpp, *value;
        !          3772:        int type;
        !          3773: {
        !          3774:        return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
        !          3775: }
        !          3776: 
        !          3777: int
        !          3778: set_identifier_qual(vpp, type, value, qual)
        !          3779:        vchar_t **vpp, *value;
        !          3780:        int type;
        !          3781:        int qual;
        !          3782: {
        !          3783:        vchar_t *new = NULL;
        !          3784: 
        !          3785:        /* simply return if value is null. */
        !          3786:        if (!value){
        !          3787:                if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
        !          3788:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3789:                                 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
        !          3790:                        return -1;
        !          3791:                }
        !          3792:                return 0;
        !          3793:        }
        !          3794: 
        !          3795:        switch (type) {
        !          3796:        case IDTYPE_FQDN:
        !          3797:        case IDTYPE_USERFQDN:
        !          3798:                if(value->l <= 1){
        !          3799:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3800:                                 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
        !          3801:                        return -1;
        !          3802:                }
        !          3803:                /* length is adjusted since QUOTEDSTRING teminates NULL. */
        !          3804:                new = vmalloc(value->l - 1);
        !          3805:                if (new == NULL)
        !          3806:                        return -1;
        !          3807:                memcpy(new->v, value->v, new->l);
        !          3808:                break;
        !          3809:        case IDTYPE_KEYID:
        !          3810:                /*
        !          3811:                 * If no qualifier is specified: IDQUAL_UNSPEC. It means
        !          3812:                 * to use a file for backward compatibility sake.
        !          3813:                 */
        !          3814:                switch(qual) {
        !          3815:                case IDQUAL_FILE:
        !          3816:                case IDQUAL_UNSPEC: {
        !          3817:                        FILE *fp;
        !          3818:                        char b[512];
        !          3819:                        int tlen, len;
        !          3820: 
        !          3821:                        fp = fopen(value->v, "r");
        !          3822:                        if (fp == NULL) {
        !          3823:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3824:                                        "can not open %s\n", value->v);
        !          3825:                                return -1;
        !          3826:                        }
        !          3827:                        tlen = 0;
        !          3828:                        while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
        !          3829:                                new = vrealloc(new, tlen + len);
        !          3830:                                if (!new) {
        !          3831:                                        fclose(fp);
        !          3832:                                        return -1;
        !          3833:                                }
        !          3834:                                memcpy(new->v + tlen, b, len);
        !          3835:                                tlen += len;
        !          3836:                        }
        !          3837:                        fclose(fp);
        !          3838:                        break;
        !          3839:                }
        !          3840: 
        !          3841:                case IDQUAL_TAG:
        !          3842:                        new = vmalloc(value->l - 1);
        !          3843:                        if (new == NULL) {
        !          3844:                                plog(LLV_ERROR, LOCATION, NULL,
        !          3845:                                        "can not allocate memory");
        !          3846:                                return -1;
        !          3847:                        }
        !          3848:                        memcpy(new->v, value->v, new->l);
        !          3849:                        break;
        !          3850: 
        !          3851:                default:
        !          3852:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3853:                                "unknown qualifier");
        !          3854:                        return -1;
        !          3855:                }
        !          3856:                break;
        !          3857: 
        !          3858:        case IDTYPE_ADDRESS: {
        !          3859:                struct sockaddr *sa;
        !          3860: 
        !          3861:                /* length is adjusted since QUOTEDSTRING teminates NULL. */
        !          3862:                if (value->l == 0)
        !          3863:                        break;
        !          3864: 
        !          3865:                sa = str2saddr(value->v, NULL);
        !          3866:                if (sa == NULL) {
        !          3867:                        plog(LLV_ERROR, LOCATION, NULL,
        !          3868:                                "invalid ip address %s\n", value->v);
        !          3869:                        return -1;
        !          3870:                }
        !          3871: 
        !          3872:                new = vmalloc(sysdep_sa_len(sa));
        !          3873:                if (new == NULL) {
        !          3874:                        racoon_free(sa);
        !          3875:                        return -1;
        !          3876:                }
        !          3877:                memcpy(new->v, sa, new->l);
        !          3878:                racoon_free(sa);
        !          3879:                break;
        !          3880:        }
        !          3881:        case IDTYPE_ASN1DN:
        !          3882:                if (value->v[0] == '~')
        !          3883:                        /* Hex-encoded ASN1 strings */
        !          3884:                        new = eay_hex2asn1dn(value->v + 1, - 1);
        !          3885:                else
        !          3886:                        /* DN encoded strings */
        !          3887:                        new = eay_str2asn1dn(value->v, value->l - 1);
        !          3888: 
        !          3889:                if (new == NULL)
        !          3890:                        return -1;
        !          3891: 
        !          3892:                if (loglevel >= LLV_DEBUG) {
        !          3893:                        X509_NAME *xn;
        !          3894:                        BIO *bio;
        !          3895:                        unsigned char *ptr = (unsigned char *) new->v, *buf;
        !          3896:                        size_t len;
        !          3897:                        char save;
        !          3898: 
        !          3899:                        xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
        !          3900:                        bio = BIO_new(BIO_s_mem());
        !          3901: 
        !          3902:                        X509_NAME_print_ex(bio, xn, 0, 0);
        !          3903:                        len = BIO_get_mem_data(bio, &ptr);
        !          3904:                        save = ptr[len];
        !          3905:                        ptr[len] = 0;
        !          3906:                        plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
        !          3907:                        ptr[len] = save;
        !          3908:                        X509_NAME_free(xn);
        !          3909:                        BIO_free(bio);
        !          3910:                }
        !          3911: 
        !          3912:                break;
        !          3913:        }
        !          3914: 
        !          3915:        *vpp = new;
        !          3916: 
        !          3917:        return 0;
        !          3918: }
        !          3919: 
        !          3920: /*
        !          3921:  * create ID payload for phase 2, and set into iph2->id and id_p.  There are
        !          3922:  * NOT INCLUDING isakmp general header.
        !          3923:  * this function is for initiator.  responder will get to copy from payload.
        !          3924:  * responder ID type is always address type.
        !          3925:  * see, RFC2407 4.6.2.1
        !          3926:  */
        !          3927: int
        !          3928: ipsecdoi_setid2(iph2)
        !          3929:        struct ph2handle *iph2;
        !          3930: {
        !          3931:        struct secpolicy *sp;
        !          3932: 
        !          3933:        /* check there is phase 2 handler ? */
        !          3934:        sp = getspbyspid(iph2->spid);
        !          3935:        if (sp == NULL) {
        !          3936:                plog(LLV_ERROR, LOCATION, NULL,
        !          3937:                        "no policy found for spid:%u.\n", iph2->spid);
        !          3938:                return -1;
        !          3939:        }
        !          3940: 
        !          3941:        if (!ipsecdoi_transportmode(iph2->proposal))
        !          3942:                iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
        !          3943:                                sp->spidx.prefs, sp->spidx.ul_proto);
        !          3944:        else if (iph2->sa_src != NULL) {
        !          3945:                /* He have a specific hint indicating that the transport
        !          3946:                 * mode SA will be negotiated using addresses that differ
        !          3947:                 * with the one from the SA. We need to indicate that to
        !          3948:                 * our peer by setting the SA address as ID.
        !          3949:                 * This is typically the case for the bootstrapping of the
        !          3950:                 * transport mode SA protecting BU/BA for MIPv6 traffic
        !          3951:                 *
        !          3952:                 * --arno*/
        !          3953:                iph2->id = ipsecdoi_sockaddr2id(iph2->sa_src,
        !          3954:                                                IPSECDOI_PREFIX_HOST,
        !          3955:                                                sp->spidx.ul_proto);
        !          3956:        } else
        !          3957:                iph2->id = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
        !          3958:                                                sp->spidx.ul_proto);
        !          3959: 
        !          3960:        if (iph2->id == NULL) {
        !          3961:                plog(LLV_ERROR, LOCATION, NULL,
        !          3962:                        "failed to get ID for %s\n",
        !          3963:                        spidx2str(&sp->spidx));
        !          3964:                return -1;
        !          3965:        }
        !          3966:        plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
        !          3967:                s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
        !          3968: 
        !          3969:        /* remote side */
        !          3970:        if (!ipsecdoi_transportmode(iph2->proposal))
        !          3971:                iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
        !          3972:                                sp->spidx.prefd, sp->spidx.ul_proto);
        !          3973:        else if (iph2->sa_dst != NULL) {
        !          3974:                /* See comment above for local side. */
        !          3975:                iph2->id_p = ipsecdoi_sockaddr2id(iph2->sa_dst,
        !          3976:                                                  IPSECDOI_PREFIX_HOST,
        !          3977:                                                  sp->spidx.ul_proto);
        !          3978:        } else
        !          3979:                iph2->id_p = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
        !          3980:                        sp->spidx.ul_proto);
        !          3981: 
        !          3982:        if (iph2->id_p == NULL) {
        !          3983:                plog(LLV_ERROR, LOCATION, NULL,
        !          3984:                        "failed to get ID for %s\n",
        !          3985:                        spidx2str(&sp->spidx));
        !          3986:                VPTRINIT(iph2->id);
        !          3987:                return -1;
        !          3988:        }
        !          3989:        plog(LLV_DEBUG, LOCATION, NULL,
        !          3990:                "use remote ID type %s\n",
        !          3991:                s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
        !          3992: 
        !          3993:        return 0;
        !          3994: }
        !          3995: 
        !          3996: /*
        !          3997:  * set address type of ID.
        !          3998:  * NOT INCLUDING general header.
        !          3999:  */
        !          4000: vchar_t *
        !          4001: ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
        !          4002:        struct sockaddr *saddr;
        !          4003:        u_int prefixlen;
        !          4004:        u_int ul_proto;
        !          4005: {
        !          4006:        vchar_t *new;
        !          4007:        int type, len1, len2;
        !          4008:        caddr_t sa;
        !          4009:        u_short port;
        !          4010: 
        !          4011:        /*
        !          4012:         * Q. When type is SUBNET, is it allowed to be ::1/128.
        !          4013:         * A. Yes. (consensus at bake-off)
        !          4014:         */
        !          4015:        switch (saddr->sa_family) {
        !          4016:        case AF_INET:
        !          4017:                len1 = sizeof(struct in_addr);
        !          4018:                if (prefixlen >= (sizeof(struct in_addr) << 3)) {
        !          4019:                        type = IPSECDOI_ID_IPV4_ADDR;
        !          4020:                        len2 = 0;
        !          4021:                } else {
        !          4022:                        type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
        !          4023:                        len2 = sizeof(struct in_addr);
        !          4024:                }
        !          4025:                sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
        !          4026:                port = ((struct sockaddr_in *)(saddr))->sin_port;
        !          4027:                break;
        !          4028: #ifdef INET6
        !          4029:        case AF_INET6:
        !          4030:                len1 = sizeof(struct in6_addr);
        !          4031:                if (prefixlen >= (sizeof(struct in6_addr) << 3)) {
        !          4032:                        type = IPSECDOI_ID_IPV6_ADDR;
        !          4033:                        len2 = 0;
        !          4034:                } else {
        !          4035:                        type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
        !          4036:                        len2 = sizeof(struct in6_addr);
        !          4037:                }
        !          4038:                sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
        !          4039:                port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
        !          4040:                break;
        !          4041: #endif
        !          4042:        default:
        !          4043:                plog(LLV_ERROR, LOCATION, NULL,
        !          4044:                        "invalid family: %d.\n", saddr->sa_family);
        !          4045:                return NULL;
        !          4046:        }
        !          4047: 
        !          4048:        /* get ID buffer */
        !          4049:        new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
        !          4050:        if (new == NULL) {
        !          4051:                plog(LLV_ERROR, LOCATION, NULL,
        !          4052:                        "failed to get ID buffer.\n");
        !          4053:                return NULL;
        !          4054:        }
        !          4055: 
        !          4056:        memset(new->v, 0, new->l);
        !          4057: 
        !          4058:        /* set the part of header. */
        !          4059:        ((struct ipsecdoi_id_b *)new->v)->type = type;
        !          4060: 
        !          4061:        /* set ul_proto and port */
        !          4062:        /*
        !          4063:         * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
        !          4064:         * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
        !          4065:         */
        !          4066:        ((struct ipsecdoi_id_b *)new->v)->proto_id =
        !          4067:                ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
        !          4068:        ((struct ipsecdoi_id_b *)new->v)->port =
        !          4069:                port == IPSEC_PORT_ANY ? 0 : port;
        !          4070:        memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
        !          4071: 
        !          4072:        /* set address */
        !          4073: 
        !          4074:        /* set prefix */
        !          4075:        if (len2) {
        !          4076:                u_char *p = (unsigned char *) new->v +
        !          4077:                        sizeof(struct ipsecdoi_id_b) + len1;
        !          4078:                u_int bits = prefixlen;
        !          4079: 
        !          4080:                while (bits >= 8) {
        !          4081:                        *p++ = 0xff;
        !          4082:                        bits -= 8;
        !          4083:                }
        !          4084: 
        !          4085:                if (bits > 0)
        !          4086:                        *p = ~((1 << (8 - bits)) - 1);
        !          4087:        }
        !          4088: 
        !          4089:        return new;
        !          4090: }
        !          4091: 
        !          4092: vchar_t *
        !          4093: ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
        !          4094:        struct sockaddr *laddr, *haddr;
        !          4095:        u_int ul_proto;
        !          4096: {
        !          4097:        vchar_t *new;
        !          4098:        int type, len1, len2;
        !          4099:        u_short port;
        !          4100: 
        !          4101:        if (laddr->sa_family != haddr->sa_family) {
        !          4102:            plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
        !          4103:            return NULL;
        !          4104:        }
        !          4105: 
        !          4106:        switch (laddr->sa_family) {
        !          4107:        case AF_INET:
        !          4108:            type = IPSECDOI_ID_IPV4_ADDR_RANGE;
        !          4109:            len1 = sizeof(struct in_addr);
        !          4110:            len2 = sizeof(struct in_addr);
        !          4111:            break;
        !          4112: #ifdef INET6
        !          4113:        case AF_INET6:
        !          4114:                type = IPSECDOI_ID_IPV6_ADDR_RANGE;
        !          4115:                len1 = sizeof(struct in6_addr);
        !          4116:                len2 = sizeof(struct in6_addr);
        !          4117:                break;
        !          4118: #endif
        !          4119:        default:
        !          4120:                plog(LLV_ERROR, LOCATION, NULL,
        !          4121:                        "invalid family: %d.\n", laddr->sa_family);
        !          4122:                return NULL;
        !          4123:        }
        !          4124: 
        !          4125:        /* get ID buffer */
        !          4126:        new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
        !          4127:        if (new == NULL) {
        !          4128:                plog(LLV_ERROR, LOCATION, NULL,
        !          4129:                        "failed to get ID buffer.\n");
        !          4130:                return NULL;
        !          4131:        }
        !          4132: 
        !          4133:        memset(new->v, 0, new->l);
        !          4134:        /* set the part of header. */
        !          4135:        ((struct ipsecdoi_id_b *)new->v)->type = type;
        !          4136: 
        !          4137:        /* set ul_proto and port */
        !          4138:        /*
        !          4139:         * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
        !          4140:         * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
        !          4141:         */
        !          4142:        ((struct ipsecdoi_id_b *)new->v)->proto_id =
        !          4143:                ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
        !          4144:        port = ((struct sockaddr_in *)(laddr))->sin_port;
        !          4145:        ((struct ipsecdoi_id_b *)new->v)->port =
        !          4146:                port == IPSEC_PORT_ANY ? 0 : port;
        !          4147:        memcpy(new->v + sizeof(struct ipsecdoi_id_b),
        !          4148:               (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
        !          4149:               len1);
        !          4150:        memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
        !          4151:               (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
        !          4152:               len2);
        !          4153:        return new;
        !          4154: }
        !          4155: 
        !          4156: 
        !          4157: /*
        !          4158:  * create sockaddr structure from ID payload (buf).
        !          4159:  * buffers (saddr, prefixlen, ul_proto) must be allocated.
        !          4160:  * see, RFC2407 4.6.2.1
        !          4161:  */
        !          4162: int
        !          4163: ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
        !          4164:        vchar_t *buf;
        !          4165:        struct sockaddr *saddr;
        !          4166:        u_int8_t *prefixlen;
        !          4167:        u_int16_t *ul_proto;
        !          4168: {
        !          4169:        struct ipsecdoi_id_b *id_b = NULL;
        !          4170:        u_int plen = 0;
        !          4171: 
        !          4172:        if (buf == NULL)
        !          4173:                return ISAKMP_INTERNAL_ERROR;
        !          4174: 
        !          4175:        id_b = (struct ipsecdoi_id_b *)buf->v;
        !          4176: 
        !          4177:        /*
        !          4178:         * When a ID payload of subnet type with a IP address of full bit
        !          4179:         * masked, it has to be processed as host address.
        !          4180:         * e.g. below 2 type are same.
        !          4181:         *      type = ipv6 subnet, data = 2001::1/128
        !          4182:         *      type = ipv6 address, data = 2001::1
        !          4183:         */
        !          4184:        switch (id_b->type) {
        !          4185:        case IPSECDOI_ID_IPV4_ADDR:
        !          4186:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4187: #ifndef __linux__
        !          4188:                saddr->sa_len = sizeof(struct sockaddr_in);
        !          4189: #endif
        !          4190:                saddr->sa_family = AF_INET;
        !          4191:                ((struct sockaddr_in *)saddr)->sin_port =
        !          4192:                        (id_b->port == 0
        !          4193:                                ? IPSEC_PORT_ANY
        !          4194:                                : id_b->port);          /* see sockaddr2id() */
        !          4195:                memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
        !          4196:                        buf->v + sizeof(*id_b), sizeof(struct in_addr));
        !          4197:                break;
        !          4198: #ifdef INET6
        !          4199:        case IPSECDOI_ID_IPV6_ADDR:
        !          4200:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4201: #ifndef __linux__
        !          4202:                saddr->sa_len = sizeof(struct sockaddr_in6);
        !          4203: #endif
        !          4204:                saddr->sa_family = AF_INET6;
        !          4205:                ((struct sockaddr_in6 *)saddr)->sin6_port =
        !          4206:                        (id_b->port == 0
        !          4207:                                ? IPSEC_PORT_ANY
        !          4208:                                : id_b->port);          /* see sockaddr2id() */
        !          4209:                memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
        !          4210:                        buf->v + sizeof(*id_b), sizeof(struct in6_addr));
        !          4211:                ((struct sockaddr_in6 *)saddr)->sin6_scope_id =
        !          4212:                        (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)saddr)->sin6_addr)
        !          4213:                                ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
        !          4214:                                : 0);
        !          4215: 
        !          4216:                break;
        !          4217: #endif
        !          4218:        default:
        !          4219:                plog(LLV_ERROR, LOCATION, NULL,
        !          4220:                        "unsupported ID type %d\n", id_b->type);
        !          4221:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
        !          4222:        }
        !          4223: 
        !          4224:        /* get prefix length */
        !          4225:        switch (id_b->type) {
        !          4226:        case IPSECDOI_ID_IPV4_ADDR:
        !          4227:                plen = sizeof(struct in_addr) << 3;
        !          4228:                break;
        !          4229: #ifdef INET6
        !          4230:        case IPSECDOI_ID_IPV6_ADDR:
        !          4231:                plen = sizeof(struct in6_addr) << 3;
        !          4232:                break;
        !          4233: #endif
        !          4234:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4235: #ifdef INET6
        !          4236:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4237: #endif
        !          4238:            {
        !          4239:                u_char *p;
        !          4240:                u_int max;
        !          4241:                int alen = sizeof(struct in_addr);
        !          4242: 
        !          4243:                switch (id_b->type) {
        !          4244:                case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4245:                        alen = sizeof(struct in_addr);
        !          4246:                        break;
        !          4247: #ifdef INET6
        !          4248:                case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4249:                        alen = sizeof(struct in6_addr);
        !          4250:                        break;
        !          4251: #endif
        !          4252:                }
        !          4253: 
        !          4254:                /* sanity check */
        !          4255:                if (buf->l < alen)
        !          4256:                        return ISAKMP_INTERNAL_ERROR;
        !          4257: 
        !          4258:                /* get subnet mask length */
        !          4259:                plen = 0;
        !          4260:                max = alen <<3;
        !          4261: 
        !          4262:                p = (unsigned char *) buf->v
        !          4263:                        + sizeof(struct ipsecdoi_id_b)
        !          4264:                        + alen;
        !          4265: 
        !          4266:                for (; *p == 0xff; p++) {
        !          4267:                        plen += 8;
        !          4268:                        if (plen >= max)
        !          4269:                                break;
        !          4270:                }
        !          4271: 
        !          4272:                if (plen < max) {
        !          4273:                        u_int l = 0;
        !          4274:                        u_char b = ~(*p);
        !          4275: 
        !          4276:                        while (b) {
        !          4277:                                b >>= 1;
        !          4278:                                l++;
        !          4279:                        }
        !          4280: 
        !          4281:                        l = 8 - l;
        !          4282:                        plen += l;
        !          4283:                }
        !          4284:            }
        !          4285:                break;
        !          4286:        }
        !          4287: 
        !          4288:        *prefixlen = plen;
        !          4289:        *ul_proto = id_b->proto_id == 0
        !          4290:                                ? IPSEC_ULPROTO_ANY
        !          4291:                                : id_b->proto_id;       /* see sockaddr2id() */
        !          4292: 
        !          4293:        return 0;
        !          4294: }
        !          4295: 
        !          4296: /*
        !          4297:  * make printable string from ID payload except of general header.
        !          4298:  */
        !          4299: char *
        !          4300: ipsecdoi_id2str(id)
        !          4301:        const vchar_t *id;
        !          4302: {
        !          4303: #define BUFLEN 512
        !          4304:        char * ret = NULL;
        !          4305:        int len = 0;
        !          4306:        char *dat;
        !          4307:        static char buf[BUFLEN];
        !          4308:        struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
        !          4309:        union sockaddr_any saddr;
        !          4310:        u_int plen = 0;
        !          4311: 
        !          4312:        switch (id_b->type) {
        !          4313:        case IPSECDOI_ID_IPV4_ADDR:
        !          4314:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4315:        case IPSECDOI_ID_IPV4_ADDR_RANGE:
        !          4316: 
        !          4317: #ifndef __linux__
        !          4318:                saddr.sa.sa_len = sizeof(struct sockaddr_in);
        !          4319: #endif
        !          4320:                saddr.sa.sa_family = AF_INET;
        !          4321:                saddr.sin.sin_port = IPSEC_PORT_ANY;
        !          4322:                memcpy(&saddr.sin.sin_addr,
        !          4323:                        id->v + sizeof(*id_b), sizeof(struct in_addr));
        !          4324:                break;
        !          4325: #ifdef INET6
        !          4326:        case IPSECDOI_ID_IPV6_ADDR:
        !          4327:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4328:        case IPSECDOI_ID_IPV6_ADDR_RANGE:
        !          4329: 
        !          4330: #ifndef __linux__
        !          4331:                saddr.sa.sa_len = sizeof(struct sockaddr_in6);
        !          4332: #endif
        !          4333:                saddr.sa.sa_family = AF_INET6;
        !          4334:                saddr.sin6.sin6_port = IPSEC_PORT_ANY;
        !          4335:                memcpy(&saddr.sin6.sin6_addr,
        !          4336:                        id->v + sizeof(*id_b), sizeof(struct in6_addr));
        !          4337:                saddr.sin6.sin6_scope_id =
        !          4338:                        (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
        !          4339:                                ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
        !          4340:                                : 0);
        !          4341:                break;
        !          4342: #endif
        !          4343:        }
        !          4344: 
        !          4345:        switch (id_b->type) {
        !          4346:        case IPSECDOI_ID_IPV4_ADDR:
        !          4347: #ifdef INET6
        !          4348:        case IPSECDOI_ID_IPV6_ADDR:
        !          4349: #endif
        !          4350:                len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
        !          4351:                break;
        !          4352: 
        !          4353:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4354: #ifdef INET6
        !          4355:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4356: #endif
        !          4357:            {
        !          4358:                u_char *p;
        !          4359:                u_int max;
        !          4360:                int alen = sizeof(struct in_addr);
        !          4361: 
        !          4362:                switch (id_b->type) {
        !          4363:                case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4364:                        alen = sizeof(struct in_addr);
        !          4365:                        break;
        !          4366: #ifdef INET6
        !          4367:                case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4368:                        alen = sizeof(struct in6_addr);
        !          4369:                        break;
        !          4370: #endif
        !          4371:                }
        !          4372: 
        !          4373:                /* sanity check */
        !          4374:                if (id->l < alen) {
        !          4375:                        len = 0;
        !          4376:                        break;
        !          4377:                }
        !          4378: 
        !          4379:                /* get subnet mask length */
        !          4380:                plen = 0;
        !          4381:                max = alen <<3;
        !          4382: 
        !          4383:                p = (unsigned char *) id->v
        !          4384:                        + sizeof(struct ipsecdoi_id_b)
        !          4385:                        + alen;
        !          4386: 
        !          4387:                for (; *p == 0xff; p++) {
        !          4388:                        plen += 8;
        !          4389:                        if (plen >= max)
        !          4390:                                break;
        !          4391:                }
        !          4392: 
        !          4393:                if (plen < max) {
        !          4394:                        u_int l = 0;
        !          4395:                        u_char b = ~(*p);
        !          4396: 
        !          4397:                        while (b) {
        !          4398:                                b >>= 1;
        !          4399:                                l++;
        !          4400:                        }
        !          4401: 
        !          4402:                        l = 8 - l;
        !          4403:                        plen += l;
        !          4404:                }
        !          4405: 
        !          4406:                len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
        !          4407:            }
        !          4408:                break;
        !          4409: 
        !          4410:        case IPSECDOI_ID_IPV4_ADDR_RANGE:
        !          4411: 
        !          4412:                len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
        !          4413: 
        !          4414: #ifndef __linux__
        !          4415:                saddr.sa.sa_len = sizeof(struct sockaddr_in);
        !          4416: #endif
        !          4417:                saddr.sa.sa_family = AF_INET;
        !          4418:                saddr.sin.sin_port = IPSEC_PORT_ANY;
        !          4419:                memcpy(&saddr.sin.sin_addr,
        !          4420:                        id->v + sizeof(*id_b) + sizeof(struct in_addr),
        !          4421:                        sizeof(struct in_addr));
        !          4422: 
        !          4423:                len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
        !          4424:                break;
        !          4425: 
        !          4426: #ifdef INET6
        !          4427:        case IPSECDOI_ID_IPV6_ADDR_RANGE:
        !          4428:                len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
        !          4429: 
        !          4430: #ifndef __linux__
        !          4431:                saddr.sa.sa_len = sizeof(struct sockaddr_in6);
        !          4432: #endif
        !          4433:                saddr.sa.sa_family = AF_INET6;
        !          4434:                saddr.sin6.sin6_port = IPSEC_PORT_ANY;
        !          4435:                memcpy(&saddr.sin6.sin6_addr,
        !          4436:                        id->v + sizeof(*id_b) + sizeof(struct in6_addr),
        !          4437:                        sizeof(struct in6_addr));
        !          4438:                saddr.sin6.sin6_scope_id =
        !          4439:                        (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
        !          4440:                                ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
        !          4441:                                : 0);
        !          4442: 
        !          4443:                len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
        !          4444:                break;
        !          4445: #endif
        !          4446: 
        !          4447:        case IPSECDOI_ID_FQDN:
        !          4448:        case IPSECDOI_ID_USER_FQDN:
        !          4449:                len = id->l - sizeof(*id_b);
        !          4450:                if (len > BUFLEN)
        !          4451:                        len = BUFLEN;
        !          4452:                memcpy(buf, id->v + sizeof(*id_b), len);
        !          4453:                break;
        !          4454: 
        !          4455:        case IPSECDOI_ID_DER_ASN1_DN:
        !          4456:        case IPSECDOI_ID_DER_ASN1_GN:
        !          4457:        {
        !          4458:                X509_NAME *xn = NULL;
        !          4459: 
        !          4460:                dat = id->v + sizeof(*id_b);
        !          4461:                len = id->l - sizeof(*id_b);
        !          4462: 
        !          4463:                if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
        !          4464:                        BIO *bio = BIO_new(BIO_s_mem());
        !          4465:                        X509_NAME_print_ex(bio, xn, 0, 0);
        !          4466:                        len = BIO_get_mem_data(bio, &dat);
        !          4467:                        if (len > BUFLEN)
        !          4468:                                len = BUFLEN;
        !          4469:                        memcpy(buf,dat,len);
        !          4470:                        BIO_free(bio);
        !          4471:                        X509_NAME_free(xn);
        !          4472:                } else {
        !          4473:                        plog(LLV_ERROR, LOCATION, NULL,
        !          4474:                                "unable to extract asn1dn from id\n");
        !          4475: 
        !          4476:                        len = sprintf(buf, "<ASN1-DN>");
        !          4477:                }
        !          4478: 
        !          4479:                break;
        !          4480:        }
        !          4481: 
        !          4482:        /* currently unhandled id types */
        !          4483:        case IPSECDOI_ID_KEY_ID:
        !          4484:                len = sprintf( buf, "<KEY-ID>");
        !          4485:                break;
        !          4486: 
        !          4487:        default:
        !          4488:                plog(LLV_ERROR, LOCATION, NULL,
        !          4489:                        "unknown ID type %d\n", id_b->type);
        !          4490:        }
        !          4491: 
        !          4492:        if (!len)
        !          4493:                len = sprintf( buf, "<?>");
        !          4494: 
        !          4495:        ret = racoon_malloc(len+1);
        !          4496:        if (ret != NULL) {
        !          4497:                memcpy(ret,buf,len);
        !          4498:                ret[len]=0;
        !          4499:        }
        !          4500: 
        !          4501:        return ret;
        !          4502: }
        !          4503: 
        !          4504: /*
        !          4505:  * set IPsec data attributes into a proposal.
        !          4506:  * NOTE: MUST called per a transform.
        !          4507:  */
        !          4508: int
        !          4509: ipsecdoi_t2satrns(t, pp, pr, tr)
        !          4510:        struct isakmp_pl_t *t;
        !          4511:        struct saprop *pp;
        !          4512:        struct saproto *pr;
        !          4513:        struct satrns *tr;
        !          4514: {
        !          4515:        struct isakmp_data *d, *prev;
        !          4516:        int flag, type;
        !          4517:        int error = -1;
        !          4518:        int life_t;
        !          4519:        int tlen;
        !          4520: 
        !          4521:        tr->trns_no = t->t_no;
        !          4522:        tr->trns_id = t->t_id;
        !          4523: 
        !          4524:        tlen = ntohs(t->h.len) - sizeof(*t);
        !          4525:        prev = (struct isakmp_data *)NULL;
        !          4526:        d = (struct isakmp_data *)(t + 1);
        !          4527: 
        !          4528:        /* default */
        !          4529:        life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
        !          4530:        pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
        !          4531:        pp->lifebyte = 0;
        !          4532:        tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
        !          4533: 
        !          4534:        while (tlen > 0) {
        !          4535: 
        !          4536:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
        !          4537:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
        !          4538: 
        !          4539:                plog(LLV_DEBUG, LOCATION, NULL,
        !          4540:                        "type=%s, flag=0x%04x, lorv=%s\n",
        !          4541:                        s_ipsecdoi_attr(type), flag,
        !          4542:                        s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
        !          4543: 
        !          4544:                switch (type) {
        !          4545:                case IPSECDOI_ATTR_SA_LD_TYPE:
        !          4546:                {
        !          4547:                        int type = ntohs(d->lorv);
        !          4548:                        switch (type) {
        !          4549:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
        !          4550:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
        !          4551:                                life_t = type;
        !          4552:                                break;
        !          4553:                        default:
        !          4554:                                plog(LLV_WARNING, LOCATION, NULL,
        !          4555:                                        "invalid life duration type. "
        !          4556:                                        "use default\n");
        !          4557:                                life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
        !          4558:                                break;
        !          4559:                        }
        !          4560:                        break;
        !          4561:                }
        !          4562:                case IPSECDOI_ATTR_SA_LD:
        !          4563:                        if (prev == NULL
        !          4564:                         || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
        !          4565:                                        IPSECDOI_ATTR_SA_LD_TYPE) {
        !          4566:                                plog(LLV_ERROR, LOCATION, NULL,
        !          4567:                                    "life duration must follow ltype\n");
        !          4568:                                break;
        !          4569:                        }
        !          4570: 
        !          4571:                    {
        !          4572:                        u_int32_t t;
        !          4573:                        vchar_t *ld_buf = NULL;
        !          4574: 
        !          4575:                        if (flag) {
        !          4576:                                /* i.e. ISAKMP_GEN_TV */
        !          4577:                                ld_buf = vmalloc(sizeof(d->lorv));
        !          4578:                                if (ld_buf == NULL) {
        !          4579:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          4580:                                            "failed to get LD buffer.\n");
        !          4581:                                        goto end;
        !          4582:                                }
        !          4583:                                memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
        !          4584:                        } else {
        !          4585:                                int len = ntohs(d->lorv);
        !          4586:                                /* i.e. ISAKMP_GEN_TLV */
        !          4587:                                ld_buf = vmalloc(len);
        !          4588:                                if (ld_buf == NULL) {
        !          4589:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          4590:                                            "failed to get LD buffer.\n");
        !          4591:                                        goto end;
        !          4592:                                }
        !          4593:                                memcpy(ld_buf->v, d + 1, len);
        !          4594:                        }
        !          4595:                        switch (life_t) {
        !          4596:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
        !          4597:                                t = ipsecdoi_set_ld(ld_buf);
        !          4598:                                vfree(ld_buf);
        !          4599:                                if (t == 0) {
        !          4600:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          4601:                                                "invalid life duration.\n");
        !          4602:                                        goto end;
        !          4603:                                }
        !          4604:                                /* lifetime must be equal in a proposal. */
        !          4605:                                if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
        !          4606:                                        pp->lifetime = t;
        !          4607:                                else if (pp->lifetime != t) {
        !          4608:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          4609:                                                "lifetime mismatched "
        !          4610:                                                "in a proposal, "
        !          4611:                                                "prev:%ld curr:%u.\n",
        !          4612:                                                (long)pp->lifetime, t);
        !          4613:                                        goto end;
        !          4614:                                }
        !          4615:                                break;
        !          4616:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
        !          4617:                                t = ipsecdoi_set_ld(ld_buf);
        !          4618:                                vfree(ld_buf);
        !          4619:                                if (t == 0) {
        !          4620:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          4621:                                                "invalid life duration.\n");
        !          4622:                                        goto end;
        !          4623:                                }
        !          4624:                                /* lifebyte must be equal in a proposal. */
        !          4625:                                if (pp->lifebyte == 0)
        !          4626:                                        pp->lifebyte = t;
        !          4627:                                else if (pp->lifebyte != t) {
        !          4628:                                        plog(LLV_ERROR, LOCATION, NULL,
        !          4629:                                                "lifebyte mismatched "
        !          4630:                                                "in a proposal, "
        !          4631:                                                "prev:%d curr:%u.\n",
        !          4632:                                                pp->lifebyte, t);
        !          4633:                                        goto end;
        !          4634:                                }
        !          4635:                                break;
        !          4636:                        default:
        !          4637:                                vfree(ld_buf);
        !          4638:                                plog(LLV_ERROR, LOCATION, NULL,
        !          4639:                                        "invalid life type: %d\n", life_t);
        !          4640:                                goto end;
        !          4641:                        }
        !          4642:                    }
        !          4643:                        break;
        !          4644: 
        !          4645:                case IPSECDOI_ATTR_GRP_DESC:
        !          4646:                        /*
        !          4647:                         * RFC2407: 4.5 IPSEC Security Association Attributes
        !          4648:                         *   Specifies the Oakley Group to be used in a PFS QM
        !          4649:                         *   negotiation.  For a list of supported values, see
        !          4650:                         *   Appendix A of [IKE].
        !          4651:                         */
        !          4652:                        if (pp->pfs_group == 0)
        !          4653:                                pp->pfs_group = (u_int16_t)ntohs(d->lorv);
        !          4654:                        else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
        !          4655:                                plog(LLV_ERROR, LOCATION, NULL,
        !          4656:                                        "pfs_group mismatched "
        !          4657:                                        "in a proposal.\n");
        !          4658:                                goto end;
        !          4659:                        }
        !          4660:                        break;
        !          4661: 
        !          4662:                case IPSECDOI_ATTR_ENC_MODE:
        !          4663:                        if (pr->encmode &&
        !          4664:                            pr->encmode != (u_int16_t)ntohs(d->lorv)) {
        !          4665:                                plog(LLV_ERROR, LOCATION, NULL,
        !          4666:                                        "multiple encmode exist "
        !          4667:                                        "in a transform.\n");
        !          4668:                                goto end;
        !          4669:                        }
        !          4670:                        pr->encmode = (u_int16_t)ntohs(d->lorv);
        !          4671:                        break;
        !          4672: 
        !          4673:                case IPSECDOI_ATTR_AUTH:
        !          4674:                        if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
        !          4675:                                plog(LLV_ERROR, LOCATION, NULL,
        !          4676:                                        "multiple authtype exist "
        !          4677:                                        "in a transform.\n");
        !          4678:                                goto end;
        !          4679:                        }
        !          4680:                        tr->authtype = (u_int16_t)ntohs(d->lorv);
        !          4681:                        break;
        !          4682: 
        !          4683:                case IPSECDOI_ATTR_KEY_LENGTH:
        !          4684:                        if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
        !          4685:                                plog(LLV_ERROR, LOCATION, NULL,
        !          4686:                                        "key length defined but not ESP");
        !          4687:                                goto end;
        !          4688:                        }
        !          4689:                        tr->encklen = ntohs(d->lorv);
        !          4690:                        break;
        !          4691: #ifdef HAVE_SECCTX
        !          4692:                case IPSECDOI_ATTR_SECCTX:
        !          4693:                {
        !          4694:                        int len = ntohs(d->lorv);
        !          4695:                        memcpy(&pp->sctx, d + 1, len);
        !          4696:                        pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
        !          4697:                        break;
        !          4698:                }
        !          4699: #endif /* HAVE_SECCTX */
        !          4700:                case IPSECDOI_ATTR_KEY_ROUNDS:
        !          4701:                case IPSECDOI_ATTR_COMP_DICT_SIZE:
        !          4702:                case IPSECDOI_ATTR_COMP_PRIVALG:
        !          4703:                default:
        !          4704:                        break;
        !          4705:                }
        !          4706: 
        !          4707:                prev = d;
        !          4708:                if (flag) {
        !          4709:                        tlen -= sizeof(*d);
        !          4710:                        d = (struct isakmp_data *)((char *)d + sizeof(*d));
        !          4711:                } else {
        !          4712:                        tlen -= (sizeof(*d) + ntohs(d->lorv));
        !          4713:                        d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
        !          4714:                }
        !          4715:        }
        !          4716: 
        !          4717:        error = 0;
        !          4718: end:
        !          4719:        return error;
        !          4720: }
        !          4721: 
        !          4722: int
        !          4723: ipsecdoi_authalg2trnsid(alg)
        !          4724:        int alg;
        !          4725: {
        !          4726:        switch (alg) {
        !          4727:         case IPSECDOI_ATTR_AUTH_HMAC_MD5:
        !          4728:                return IPSECDOI_AH_MD5;
        !          4729:         case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
        !          4730:                return IPSECDOI_AH_SHA;
        !          4731:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
        !          4732:                return IPSECDOI_AH_SHA256;
        !          4733:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
        !          4734:                return IPSECDOI_AH_SHA384;
        !          4735:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
        !          4736:                return IPSECDOI_AH_SHA512;
        !          4737:         case IPSECDOI_ATTR_AUTH_DES_MAC:
        !          4738:                return IPSECDOI_AH_DES;
        !          4739:        case IPSECDOI_ATTR_AUTH_KPDK:
        !          4740:                return IPSECDOI_AH_MD5; /* XXX */
        !          4741:        default:
        !          4742:                plog(LLV_ERROR, LOCATION, NULL,
        !          4743:                        "invalid authentication algorithm:%d\n", alg);
        !          4744:        }
        !          4745:        return -1;
        !          4746: }
        !          4747: 
        !          4748: static int rm_idtype2doi[] = {
        !          4749:        255,                            /* IDTYPE_UNDEFINED, 0 */
        !          4750:        IPSECDOI_ID_FQDN,               /* IDTYPE_FQDN, 1 */
        !          4751:        IPSECDOI_ID_USER_FQDN,          /* IDTYPE_USERFQDN, 2 */
        !          4752:        IPSECDOI_ID_KEY_ID,             /* IDTYPE_KEYID, 3 */
        !          4753:        255,    /*                         IDTYPE_ADDRESS, 4
        !          4754:                 * it expands into 4 types by another function. */
        !          4755:        IPSECDOI_ID_DER_ASN1_DN,        /* IDTYPE_ASN1DN, 5 */
        !          4756: };
        !          4757: 
        !          4758: /*
        !          4759:  * convert idtype to DOI value.
        !          4760:  * OUT 255  : NG
        !          4761:  *     other: converted.
        !          4762:  */
        !          4763: int
        !          4764: idtype2doi(idtype)
        !          4765:        int idtype;
        !          4766: {
        !          4767:        if (ARRAYLEN(rm_idtype2doi) > idtype)
        !          4768:                return rm_idtype2doi[idtype];
        !          4769:        return 255;
        !          4770: }
        !          4771: 
        !          4772: int
        !          4773: doi2idtype(doi)
        !          4774:        int doi;
        !          4775: {
        !          4776:        switch(doi) {
        !          4777:        case IPSECDOI_ID_FQDN:
        !          4778:                return(IDTYPE_FQDN);
        !          4779:        case IPSECDOI_ID_USER_FQDN:
        !          4780:                return(IDTYPE_USERFQDN);
        !          4781:        case IPSECDOI_ID_KEY_ID:
        !          4782:                return(IDTYPE_KEYID);
        !          4783:        case IPSECDOI_ID_DER_ASN1_DN:
        !          4784:                return(IDTYPE_ASN1DN);
        !          4785:        case IPSECDOI_ID_IPV4_ADDR:
        !          4786:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
        !          4787:        case IPSECDOI_ID_IPV6_ADDR:
        !          4788:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
        !          4789:                return(IDTYPE_ADDRESS);
        !          4790:        default:
        !          4791:                plog(LLV_WARNING, LOCATION, NULL,
        !          4792:                        "Inproper idtype:%s in this function.\n",
        !          4793:                        s_ipsecdoi_ident(doi));
        !          4794:                return(IDTYPE_ADDRESS); /* XXX */
        !          4795:        }
        !          4796:        /*NOTREACHED*/
        !          4797: }

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