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

1.1.1.2 ! misho       1: /*     $NetBSD: ipsec_doi.c,v 1.46.4.1 2013/06/18 05:40:36 tteras Exp $        */
1.1       misho       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: 
                   1187:        bp = (caddr_t)(sab + 1);
                   1188:        tlen = sa->l - sizeof(*sab);
                   1189: 
                   1190:     {
                   1191:        struct isakmp_pl_p *prop;
                   1192:        int proplen;
                   1193:        vchar_t *pbuf = NULL;
                   1194:        struct isakmp_parse_t *pa;
                   1195: 
                   1196:        pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
                   1197:        if (pbuf == NULL)
                   1198:                goto bad;
                   1199: 
                   1200:        for (pa = (struct isakmp_parse_t *)pbuf->v;
                   1201:             pa->type != ISAKMP_NPTYPE_NONE;
                   1202:             pa++) {
                   1203:                /* check the value of next payload */
                   1204:                if (pa->type != ISAKMP_NPTYPE_P) {
                   1205:                        plog(LLV_ERROR, LOCATION, NULL,
                   1206:                                "Invalid payload type=%u\n", pa->type);
                   1207:                        vfree(pbuf);
                   1208:                        goto bad;
                   1209:                }
                   1210: 
                   1211:                prop = (struct isakmp_pl_p *)pa->ptr;
                   1212:                proplen = pa->len;
                   1213: 
                   1214:                plog(LLV_DEBUG, LOCATION, NULL,
                   1215:                        "proposal #%u len=%d\n", prop->p_no, proplen);
                   1216: 
                   1217:                if (proplen == 0) {
                   1218:                        plog(LLV_ERROR, LOCATION, NULL,
                   1219:                                "invalid proposal with length %d\n", proplen);
                   1220:                        vfree(pbuf);
                   1221:                        goto bad;
                   1222:                }
                   1223: 
                   1224:                /* check Protocol ID */
                   1225:                if (!check_protocol[mode]) {
                   1226:                        plog(LLV_ERROR, LOCATION, NULL,
                   1227:                                "unsupported mode %d\n", mode);
                   1228:                        continue;
                   1229:                }
                   1230: 
                   1231:                if (check_protocol[mode](prop->proto_id) < 0)
                   1232:                        continue;
                   1233: 
                   1234:                /* check SPI length when IKE. */
                   1235:                if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
                   1236:                        continue;
                   1237: 
                   1238:                /* get transform */
                   1239:                if (get_transform(prop, pair, &num_p) < 0) {
                   1240:                        vfree(pbuf);
                   1241:                        goto bad;
                   1242:                }
                   1243:        }
                   1244:        vfree(pbuf);
                   1245:        pbuf = NULL;
                   1246:     }
                   1247: 
                   1248:     {
                   1249:        int notrans, nprop;
                   1250:        struct prop_pair *p, *q;
                   1251: 
                   1252:        /* check for proposals with no transforms */
                   1253:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
                   1254:                if (!pair[i])
                   1255:                        continue;
                   1256: 
                   1257:                plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
                   1258:                print_proppair(LLV_DEBUG, pair[i]);
                   1259: 
                   1260:                notrans = nprop = 0;
                   1261:                for (p = pair[i]; p; p = p->next) {
                   1262:                        if (p->trns == NULL) {
                   1263:                                notrans++;
                   1264:                                break;
                   1265:                        }
                   1266:                        for (q = p; q; q = q->tnext)
                   1267:                                nprop++;
                   1268:                }
                   1269: 
                   1270: #if 0
                   1271:                /*
                   1272:                 * XXX at this moment, we cannot accept proposal group
                   1273:                 * with multiple proposals.  this should be fixed.
                   1274:                 */
                   1275:                if (pair[i]->next) {
                   1276:                        plog(LLV_WARNING, LOCATION, NULL,
                   1277:                                "proposal #%u ignored "
                   1278:                                "(multiple proposal not supported)\n",
                   1279:                                pair[i]->prop->p_no);
                   1280:                        notrans++;
                   1281:                }
                   1282: #endif
                   1283: 
                   1284:                if (notrans) {
                   1285:                        for (p = pair[i]; p; p = q) {
                   1286:                                q = p->next;
                   1287:                                racoon_free(p);
                   1288:                        }
                   1289:                        pair[i] = NULL;
                   1290:                        num_p--;
                   1291:                } else {
                   1292:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1293:                                "proposal #%u: %d transform\n",
                   1294:                                pair[i]->prop->p_no, nprop);
                   1295:                }
                   1296:        }
                   1297:     }
                   1298: 
                   1299:        /* bark if no proposal is found. */
                   1300:        if (num_p <= 0) {
                   1301:                plog(LLV_ERROR, LOCATION, NULL,
                   1302:                        "no Proposal found.\n");
                   1303:                goto bad;
                   1304:        }
                   1305: 
                   1306:        return pair;
                   1307: bad:
                   1308:        if (pair != NULL)
                   1309:                racoon_free(pair);
                   1310:        return NULL;
                   1311: }
                   1312: 
                   1313: struct prop_pair **
                   1314: get_proppair(sa, mode)
                   1315:        vchar_t *sa;
                   1316:        int mode;
                   1317: {
                   1318:        return get_proppair_and_doi_sit(sa, mode, NULL, NULL);
                   1319: }
                   1320: 
                   1321: 
                   1322: /*
                   1323:  * check transform payload.
                   1324:  * OUT:
                   1325:  *     positive: return the pointer to the payload of valid transform.
                   1326:  *     0       : No valid transform found.
                   1327:  */
                   1328: static int
                   1329: get_transform(prop, pair, num_p)
                   1330:        struct isakmp_pl_p *prop;
                   1331:        struct prop_pair **pair;
                   1332:        int *num_p;
                   1333: {
                   1334:        int tlen; /* total length of all transform in a proposal */
                   1335:        caddr_t bp;
                   1336:        struct isakmp_pl_t *trns;
                   1337:        int trnslen;
                   1338:        vchar_t *pbuf = NULL;
                   1339:        struct isakmp_parse_t *pa;
                   1340:        struct prop_pair *p = NULL, *q;
                   1341:        int num_t;
                   1342: 
                   1343:        bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
                   1344:        tlen = ntohs(prop->h.len)
                   1345:                - (sizeof(struct isakmp_pl_p) + prop->spi_size);
                   1346:        pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
                   1347:        if (pbuf == NULL)
                   1348:                return -1;
                   1349: 
                   1350:        /* check and get transform for use */
                   1351:        num_t = 0;
                   1352:        for (pa = (struct isakmp_parse_t *)pbuf->v;
                   1353:             pa->type != ISAKMP_NPTYPE_NONE;
                   1354:             pa++) {
                   1355: 
                   1356:                num_t++;
                   1357: 
                   1358:                /* check the value of next payload */
                   1359:                if (pa->type != ISAKMP_NPTYPE_T) {
                   1360:                        plog(LLV_ERROR, LOCATION, NULL,
                   1361:                                "Invalid payload type=%u\n", pa->type);
                   1362:                        break;
                   1363:                }
                   1364: 
                   1365:                trns = (struct isakmp_pl_t *)pa->ptr;
                   1366:                trnslen = pa->len;
                   1367: 
                   1368:                plog(LLV_DEBUG, LOCATION, NULL,
                   1369:                        "transform #%u len=%u\n", trns->t_no, trnslen);
                   1370: 
                   1371:                /* check transform ID */
                   1372:                if (prop->proto_id >= ARRAYLEN(check_transform)) {
                   1373:                        plog(LLV_WARNING, LOCATION, NULL,
                   1374:                                "unsupported proto_id %u\n",
                   1375:                                prop->proto_id);
                   1376:                        continue;
                   1377:                }
                   1378:                if (prop->proto_id >= ARRAYLEN(check_attributes)) {
                   1379:                        plog(LLV_WARNING, LOCATION, NULL,
                   1380:                                "unsupported proto_id %u\n",
                   1381:                                prop->proto_id);
                   1382:                        continue;
                   1383:                }
                   1384: 
                   1385:                if (!check_transform[prop->proto_id]
                   1386:                 || !check_attributes[prop->proto_id]) {
                   1387:                        plog(LLV_WARNING, LOCATION, NULL,
                   1388:                                "unsupported proto_id %u\n",
                   1389:                                prop->proto_id);
                   1390:                        continue;
                   1391:                }
                   1392:                if (check_transform[prop->proto_id](trns->t_id) < 0)
                   1393:                        continue;
                   1394: 
                   1395:                /* check data attributes */
                   1396:                if (check_attributes[prop->proto_id](trns) != 0)
                   1397:                        continue;
                   1398: 
                   1399:                p = racoon_calloc(1, sizeof(*p));
                   1400:                if (p == NULL) {
                   1401:                        plog(LLV_ERROR, LOCATION, NULL,
                   1402:                                "failed to get buffer.\n");
                   1403:                        vfree(pbuf);
                   1404:                        return -1;
                   1405:                }
                   1406:                p->prop = prop;
                   1407:                p->trns = trns;
                   1408: 
                   1409:                /* need to preserve the order */
                   1410:                for (q = pair[prop->p_no]; q && q->next; q = q->next)
                   1411:                        ;
                   1412:                if (q && q->prop == p->prop) {
                   1413:                        for (/*nothing*/; q && q->tnext; q = q->tnext)
                   1414:                                ;
                   1415:                        q->tnext = p;
                   1416:                } else {
                   1417:                        if (q)
                   1418:                                q->next = p;
                   1419:                        else {
                   1420:                                pair[prop->p_no] = p;
                   1421:                                (*num_p)++;
                   1422:                        }
                   1423:                }
                   1424:        }
                   1425: 
                   1426:        vfree(pbuf);
                   1427: 
                   1428:        return 0;
                   1429: }
                   1430: 
                   1431: /*
                   1432:  * make a new SA payload from prop_pair.
                   1433:  * NOTE: this function make spi value clear.
                   1434:  */
                   1435: vchar_t *
                   1436: get_sabyproppair(doitype, sittype, pair)
                   1437:        u_int32_t doitype, sittype;
                   1438:        struct prop_pair *pair;
                   1439: {
                   1440:        vchar_t *newsa;
                   1441:        int newtlen;
                   1442:        u_int8_t *np_p = NULL;
                   1443:        struct prop_pair *p;
                   1444:        int prophlen, trnslen;
                   1445:        caddr_t bp;
                   1446: 
                   1447:        newtlen = sizeof(struct ipsecdoi_sa_b);
                   1448:        for (p = pair; p; p = p->next) {
                   1449:                newtlen += sizeof(struct isakmp_pl_p);
                   1450:                newtlen += p->prop->spi_size;
                   1451:                newtlen += ntohs(p->trns->h.len);
                   1452:        }
                   1453: 
                   1454:        newsa = vmalloc(newtlen);
                   1455:        if (newsa == NULL) {
                   1456:                plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
                   1457:                return NULL;
                   1458:        }
                   1459:        bp = newsa->v;
                   1460: 
                   1461:        ((struct isakmp_gen *)bp)->len = htons(newtlen);
                   1462: 
                   1463:        /* update some of values in SA header */
                   1464:        ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype);
                   1465:        ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype);
                   1466:        bp += sizeof(struct ipsecdoi_sa_b);
                   1467: 
                   1468:        /* create proposal payloads */
                   1469:        for (p = pair; p; p = p->next) {
                   1470:                prophlen = sizeof(struct isakmp_pl_p)
                   1471:                                + p->prop->spi_size;
                   1472:                trnslen = ntohs(p->trns->h.len);
                   1473: 
                   1474:                if (np_p)
                   1475:                        *np_p = ISAKMP_NPTYPE_P;
                   1476: 
                   1477:                /* create proposal */
                   1478: 
                   1479:                memcpy(bp, p->prop, prophlen);
                   1480:                ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
                   1481:                ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
                   1482:                ((struct isakmp_pl_p *)bp)->num_t = 1;
                   1483:                np_p = &((struct isakmp_pl_p *)bp)->h.np;
                   1484:                memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
                   1485:                bp += prophlen;
                   1486: 
                   1487:                /* create transform */
                   1488:                memcpy(bp, p->trns, trnslen);
                   1489:                ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
                   1490:                ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
                   1491:                bp += trnslen;
                   1492:        }
                   1493: 
                   1494:        return newsa;
                   1495: }
                   1496: 
                   1497: /*
                   1498:  * update responder's spi
                   1499:  */
                   1500: int
                   1501: ipsecdoi_updatespi(iph2)
                   1502:        struct ph2handle *iph2;
                   1503: {
                   1504:        struct prop_pair **pair, *p;
                   1505:        struct saprop *pp;
                   1506:        struct saproto *pr;
                   1507:        int i;
                   1508:        int error = -1;
                   1509:        u_int8_t *spi;
                   1510: 
                   1511:        pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
                   1512:        if (pair == NULL)
                   1513:                return -1;
                   1514:        for (i = 0; i < MAXPROPPAIRLEN; i++) {
                   1515:                if (pair[i])
                   1516:                        break;
                   1517:        }
                   1518:        if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
                   1519:                /* multiple transform must be filtered by selectph2proposal.*/
                   1520:                goto end;
                   1521:        }
                   1522: 
                   1523:        pp = iph2->approval;
                   1524: 
                   1525:        /* create proposal payloads */
                   1526:        for (p = pair[i]; p; p = p->next) {
                   1527:                /*
                   1528:                 * find a proposal/transform with matching proto_id/t_id.
                   1529:                 * we have analyzed validity already, in cmpsaprop_alloc().
                   1530:                 */
                   1531:                for (pr = pp->head; pr; pr = pr->next) {
                   1532:                        if (p->prop->proto_id == pr->proto_id &&
                   1533:                            p->trns->t_id == pr->head->trns_id) {
                   1534:                                break;
                   1535:                        }
                   1536:                }
                   1537:                if (!pr)
                   1538:                        goto end;
                   1539: 
                   1540:                /*
                   1541:                 * XXX SPI bits are left-filled, for use with IPComp.
                   1542:                 * we should be switching to variable-length spi field...
                   1543:                 */
                   1544:                spi = (u_int8_t *)&pr->spi;
                   1545:                spi += sizeof(pr->spi);
                   1546:                spi -= pr->spisize;
                   1547:                memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
                   1548:        }
                   1549: 
                   1550:        error = 0;
                   1551: end:
                   1552:        free_proppair(pair);
                   1553:        return error;
                   1554: }
                   1555: 
                   1556: /*
                   1557:  * make a new SA payload from prop_pair.
                   1558:  */
                   1559: vchar_t *
                   1560: get_sabysaprop(pp0, sa0)
                   1561:        struct saprop *pp0;
                   1562:        vchar_t *sa0;
                   1563: {
                   1564:        struct prop_pair **pair = NULL;
                   1565:        vchar_t *newsa = NULL;
                   1566:        int newtlen;
                   1567:        u_int8_t *np_p = NULL;
                   1568:        struct prop_pair *p = NULL;
                   1569:        struct saprop *pp;
                   1570:        struct saproto *pr;
                   1571:        struct satrns *tr;
                   1572:        int prophlen, trnslen;
                   1573:        caddr_t bp;
                   1574:        int error = -1;
                   1575: 
                   1576:        /* get proposal pair */
                   1577:        pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
                   1578:        if (pair == NULL)
                   1579:                goto out;
                   1580: 
                   1581:        newtlen = sizeof(struct ipsecdoi_sa_b);
                   1582:        for (pp = pp0; pp; pp = pp->next) {
                   1583: 
                   1584:                if (pair[pp->prop_no] == NULL)
                   1585:                        goto out;
                   1586: 
                   1587:                for (pr = pp->head; pr; pr = pr->next) {
                   1588:                        newtlen += (sizeof(struct isakmp_pl_p)
                   1589:                                + pr->spisize);
                   1590: 
                   1591:                        for (tr = pr->head; tr; tr = tr->next) {
                   1592:                                for (p = pair[pp->prop_no]; p; p = p->tnext) {
                   1593:                                        if (tr->trns_no == p->trns->t_no)
                   1594:                                                break;
                   1595:                                }
                   1596:                                if (p == NULL)
                   1597:                                        goto out;
                   1598: 
                   1599:                                newtlen += ntohs(p->trns->h.len);
                   1600:                        }
                   1601:                }
                   1602:        }
                   1603: 
                   1604:        newsa = vmalloc(newtlen);
                   1605:        if (newsa == NULL) {
                   1606:                plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
                   1607:                goto out;
                   1608:        }
                   1609:        bp = newsa->v;
                   1610: 
                   1611:        /* some of values of SA must be updated in the out of this function */
                   1612:        ((struct isakmp_gen *)bp)->len = htons(newtlen);
                   1613:        bp += sizeof(struct ipsecdoi_sa_b);
                   1614: 
                   1615:        /* create proposal payloads */
                   1616:        for (pp = pp0; pp; pp = pp->next) {
                   1617: 
                   1618:                for (pr = pp->head; pr; pr = pr->next) {
                   1619:                        prophlen = sizeof(struct isakmp_pl_p)
                   1620:                                        + p->prop->spi_size;
                   1621: 
                   1622:                        for (tr = pr->head; tr; tr = tr->next) {
                   1623:                                for (p = pair[pp->prop_no]; p; p = p->tnext) {
                   1624:                                        if (tr->trns_no == p->trns->t_no)
                   1625:                                                break;
                   1626:                                }
                   1627:                                if (p == NULL)
                   1628:                                        goto out;
                   1629: 
                   1630:                                trnslen = ntohs(p->trns->h.len);
                   1631: 
                   1632:                                if (np_p)
                   1633:                                        *np_p = ISAKMP_NPTYPE_P;
                   1634: 
                   1635:                                /* create proposal */
                   1636: 
                   1637:                                memcpy(bp, p->prop, prophlen);
                   1638:                                ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
                   1639:                                ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
                   1640:                                ((struct isakmp_pl_p *)bp)->num_t = 1;
                   1641:                                np_p = &((struct isakmp_pl_p *)bp)->h.np;
                   1642:                                bp += prophlen;
                   1643: 
                   1644:                                /* create transform */
                   1645:                                memcpy(bp, p->trns, trnslen);
                   1646:                                ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
                   1647:                                ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
                   1648:                                bp += trnslen;
                   1649:                        }
                   1650:                }
                   1651:        }
                   1652: 
                   1653:        error = 0;
                   1654: out:
                   1655:        if (pair != NULL)
                   1656:                racoon_free(pair);
                   1657: 
                   1658:        if (error != 0) {
                   1659:                if (newsa != NULL) {
                   1660:                        vfree(newsa);
                   1661:                        newsa = NULL;
                   1662:                }
                   1663:        }
                   1664: 
                   1665:        return newsa;
                   1666: }
                   1667: 
                   1668: /*
                   1669:  * If some error happens then return 0.  Although 0 means that lifetime is zero,
                   1670:  * such a value should not be accepted.
                   1671:  * Also 0 of lifebyte should not be included in a packet although 0 means not
                   1672:  * to care of it.
                   1673:  */
                   1674: static u_int32_t
                   1675: ipsecdoi_set_ld(buf)
                   1676:        vchar_t *buf;
                   1677: {
                   1678:        u_int32_t ld;
                   1679: 
                   1680:        if (buf == 0)
                   1681:                return 0;
                   1682: 
                   1683:        switch (buf->l) {
                   1684:        case 2:
                   1685:                ld = ntohs(*(u_int16_t *)buf->v);
                   1686:                break;
                   1687:        case 4:
                   1688:                ld = ntohl(*(u_int32_t *)buf->v);
                   1689:                break;
                   1690:        default:
                   1691:                plog(LLV_ERROR, LOCATION, NULL,
                   1692:                        "length %zu of life duration "
                   1693:                        "isn't supported.\n", buf->l);
                   1694:                return 0;
                   1695:        }
                   1696: 
                   1697:        return ld;
                   1698: }
                   1699: 
                   1700: /*
                   1701:  * parse responder-lifetime attributes from payload
                   1702:  */
                   1703: int
                   1704: ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb)
                   1705:        struct isakmp_pl_n *notify;
                   1706:        u_int32_t *lifetime_sec;
                   1707:        u_int32_t *lifetime_kb;
                   1708: {
                   1709:        struct isakmp_data *d;
                   1710:        int flag, type, tlen, ld_type = -1;
                   1711:        u_int16_t lorv;
                   1712:        u_int32_t value;
                   1713: 
                   1714:        tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
                   1715:         d = (struct isakmp_data *)((char *)(notify + 1) +
                   1716:                notify->spi_size);
                   1717: 
                   1718:        while (tlen >= sizeof(struct isakmp_data)) {
                   1719:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
                   1720:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
                   1721:                lorv = ntohs(d->lorv);
                   1722: 
                   1723:                plog(LLV_DEBUG, LOCATION, NULL,
                   1724:                        "type=%s, flag=0x%04x, lorv=%s\n",
                   1725:                        s_ipsecdoi_attr(type), flag,
                   1726:                        s_ipsecdoi_attr_v(type, lorv));
                   1727: 
                   1728:                switch (type) {
                   1729:                case IPSECDOI_ATTR_SA_LD_TYPE:
                   1730:                        if (! flag) {
                   1731:                                plog(LLV_ERROR, LOCATION, NULL,
                   1732:                                        "must be TV when LD_TYPE.\n");
                   1733:                                return -1;
                   1734:                        }
                   1735:                        ld_type = lorv;
                   1736:                        break;
                   1737:                case IPSECDOI_ATTR_SA_LD:
                   1738:                        if (flag)
                   1739:                                value = lorv;
                   1740:                        else if (lorv == 2)
                   1741:                                value = ntohs(*(u_int16_t *)(d + 1));
                   1742:                        else if (lorv == 4)
                   1743:                                value = ntohl(*(u_int32_t *)(d + 1));
                   1744:                        else {
                   1745:                                plog(LLV_ERROR, LOCATION, NULL,
                   1746:                                        "payload length %d for lifetime "
                   1747:                                        "data length is unsupported.\n", lorv);
                   1748:                                return -1;
                   1749:                        }
                   1750: 
                   1751:                        switch (ld_type) {
                   1752:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
                   1753:                                if (lifetime_sec != NULL)
                   1754:                                        *lifetime_sec = value;
                   1755:                                plog(LLV_INFO, LOCATION, NULL,
                   1756:                                        "received RESPONDER-LIFETIME: %d "
                   1757:                                        "seconds\n", value);
                   1758:                                break;
                   1759:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
                   1760:                                if (lifetime_kb != NULL)
                   1761:                                        *lifetime_kb = value;
                   1762:                                plog(LLV_INFO, LOCATION, NULL,
                   1763:                                        "received RESPONDER-LIFETIME: %d "
                   1764:                                        "kbytes\n", value);
                   1765:                                break;
                   1766:                        default:
                   1767:                                plog(LLV_ERROR, LOCATION, NULL,
                   1768:                                        "lifetime data received without "
                   1769:                                        "lifetime data type.\n");
                   1770:                                return -1;
                   1771:                        }
                   1772:                        break;
                   1773:                }
                   1774: 
                   1775:                if (flag) {
                   1776:                        tlen -= sizeof(*d);
                   1777:                        d = (struct isakmp_data *)((char *)d
                   1778:                                + sizeof(*d));
                   1779:                } else {
                   1780:                        tlen -= (sizeof(*d) + lorv);
                   1781:                        d = (struct isakmp_data *)((char *)d
                   1782:                                + sizeof(*d) + lorv);
                   1783:                }
                   1784:        }
                   1785: 
                   1786:        return 0;
                   1787: }
                   1788: 
                   1789: 
                   1790: /*%%%*/
                   1791: /*
                   1792:  * check DOI
                   1793:  */
                   1794: static int
                   1795: check_doi(doi)
                   1796:        u_int32_t doi;
                   1797: {
                   1798:        switch (doi) {
                   1799:        case IPSEC_DOI:
                   1800:                return 0;
                   1801:        default:
                   1802:                plog(LLV_ERROR, LOCATION, NULL,
                   1803:                        "invalid value of DOI 0x%08x.\n", doi);
                   1804:                return -1;
                   1805:        }
                   1806:        /* NOT REACHED */
                   1807: }
                   1808: 
                   1809: /*
                   1810:  * check situation
                   1811:  */
                   1812: static int
                   1813: check_situation(sit)
                   1814:        u_int32_t sit;
                   1815: {
                   1816:        switch (sit) {
                   1817:        case IPSECDOI_SIT_IDENTITY_ONLY:
                   1818:                return 0;
                   1819: 
                   1820:        case IPSECDOI_SIT_SECRECY:
                   1821:        case IPSECDOI_SIT_INTEGRITY:
                   1822:                plog(LLV_ERROR, LOCATION, NULL,
                   1823:                        "situation 0x%08x unsupported yet.\n", sit);
                   1824:                return -1;
                   1825: 
                   1826:        default:
                   1827:                plog(LLV_ERROR, LOCATION, NULL,
                   1828:                        "invalid situation 0x%08x.\n", sit);
                   1829:                return -1;
                   1830:        }
                   1831:        /* NOT REACHED */
                   1832: }
                   1833: 
                   1834: /*
                   1835:  * check protocol id in main mode
                   1836:  */
                   1837: static int
                   1838: check_prot_main(proto_id)
                   1839:        int proto_id;
                   1840: {
                   1841:        switch (proto_id) {
                   1842:        case IPSECDOI_PROTO_ISAKMP:
                   1843:                return 0;
                   1844: 
                   1845:        default:
                   1846:                plog(LLV_ERROR, LOCATION, NULL,
                   1847:                        "Illegal protocol id=%u.\n", proto_id);
                   1848:                return -1;
                   1849:        }
                   1850:        /* NOT REACHED */
                   1851: }
                   1852: 
                   1853: /*
                   1854:  * check protocol id in quick mode
                   1855:  */
                   1856: static int
                   1857: check_prot_quick(proto_id)
                   1858:        int proto_id;
                   1859: {
                   1860:        switch (proto_id) {
                   1861:        case IPSECDOI_PROTO_IPSEC_AH:
                   1862:        case IPSECDOI_PROTO_IPSEC_ESP:
                   1863:                return 0;
                   1864: 
                   1865:        case IPSECDOI_PROTO_IPCOMP:
                   1866:                return 0;
                   1867: 
                   1868:        default:
                   1869:                plog(LLV_ERROR, LOCATION, NULL,
                   1870:                        "invalid protocol id %d.\n", proto_id);
                   1871:                return -1;
                   1872:        }
                   1873:        /* NOT REACHED */
                   1874: }
                   1875: 
                   1876: static int
                   1877: check_spi_size(proto_id, size)
                   1878:        int proto_id, size;
                   1879: {
                   1880:        switch (proto_id) {
                   1881:        case IPSECDOI_PROTO_ISAKMP:
                   1882:                if (size != 0) {
                   1883:                        /* WARNING */
                   1884:                        plog(LLV_WARNING, LOCATION, NULL,
                   1885:                                "SPI size isn't zero, but IKE proposal.\n");
                   1886:                }
                   1887:                return 0;
                   1888: 
                   1889:        case IPSECDOI_PROTO_IPSEC_AH:
                   1890:        case IPSECDOI_PROTO_IPSEC_ESP:
                   1891:                if (size != 4) {
                   1892:                        plog(LLV_ERROR, LOCATION, NULL,
                   1893:                                "invalid SPI size=%d for IPSEC proposal.\n",
                   1894:                                size);
                   1895:                        return -1;
                   1896:                }
                   1897:                return 0;
                   1898: 
                   1899:        case IPSECDOI_PROTO_IPCOMP:
                   1900:                if (size != 2 && size != 4) {
                   1901:                        plog(LLV_ERROR, LOCATION, NULL,
                   1902:                                "invalid SPI size=%d for IPCOMP proposal.\n",
                   1903:                                size);
                   1904:                        return -1;
                   1905:                }
                   1906:                return 0;
                   1907: 
                   1908:        default:
                   1909:                /* ??? */
                   1910:                return -1;
                   1911:        }
                   1912:        /* NOT REACHED */
                   1913: }
                   1914: 
                   1915: /*
                   1916:  * check transform ID in ISAKMP.
                   1917:  */
                   1918: static int
                   1919: check_trns_isakmp(t_id)
                   1920:        int t_id;
                   1921: {
                   1922:        switch (t_id) {
                   1923:        case IPSECDOI_KEY_IKE:
                   1924:                return 0;
                   1925:        default:
                   1926:                plog(LLV_ERROR, LOCATION, NULL,
                   1927:                        "invalid transform-id=%u in proto_id=%u.\n",
                   1928:                        t_id, IPSECDOI_KEY_IKE);
                   1929:                return -1;
                   1930:        }
                   1931:        /* NOT REACHED */
                   1932: }
                   1933: 
                   1934: /*
                   1935:  * check transform ID in AH.
                   1936:  */
                   1937: static int
                   1938: check_trns_ah(t_id)
                   1939:        int t_id;
                   1940: {
                   1941:        switch (t_id) {
                   1942:        case IPSECDOI_AH_MD5:
                   1943:        case IPSECDOI_AH_SHA:
                   1944:        case IPSECDOI_AH_SHA256:
                   1945:        case IPSECDOI_AH_SHA384:
                   1946:        case IPSECDOI_AH_SHA512:
                   1947:                return 0;
                   1948:        case IPSECDOI_AH_DES:
                   1949:                plog(LLV_ERROR, LOCATION, NULL,
                   1950:                        "not support transform-id=%u in AH.\n", t_id);
                   1951:                return -1;
                   1952:        default:
                   1953:                plog(LLV_ERROR, LOCATION, NULL,
                   1954:                        "invalid transform-id=%u in AH.\n", t_id);
                   1955:                return -1;
                   1956:        }
                   1957:        /* NOT REACHED */
                   1958: }
                   1959: 
                   1960: /*
                   1961:  * check transform ID in ESP.
                   1962:  */
                   1963: static int
                   1964: check_trns_esp(t_id)
                   1965:        int t_id;
                   1966: {
                   1967:        switch (t_id) {
                   1968:        case IPSECDOI_ESP_DES:
                   1969:        case IPSECDOI_ESP_3DES:
                   1970:        case IPSECDOI_ESP_NULL:
                   1971:        case IPSECDOI_ESP_RC5:
                   1972:        case IPSECDOI_ESP_CAST:
                   1973:        case IPSECDOI_ESP_BLOWFISH:
                   1974:        case IPSECDOI_ESP_AES:
                   1975:        case IPSECDOI_ESP_TWOFISH:
                   1976:        case IPSECDOI_ESP_CAMELLIA:
                   1977:                return 0;
                   1978:        case IPSECDOI_ESP_DES_IV32:
                   1979:        case IPSECDOI_ESP_DES_IV64:
                   1980:        case IPSECDOI_ESP_IDEA:
                   1981:        case IPSECDOI_ESP_3IDEA:
                   1982:        case IPSECDOI_ESP_RC4:
                   1983:                plog(LLV_ERROR, LOCATION, NULL,
                   1984:                        "not support transform-id=%u in ESP.\n", t_id);
                   1985:                return -1;
                   1986:        default:
                   1987:                plog(LLV_ERROR, LOCATION, NULL,
                   1988:                        "invalid transform-id=%u in ESP.\n", t_id);
                   1989:                return -1;
                   1990:        }
                   1991:        /* NOT REACHED */
                   1992: }
                   1993: 
                   1994: /*
                   1995:  * check transform ID in IPCOMP.
                   1996:  */
                   1997: static int
                   1998: check_trns_ipcomp(t_id)
                   1999:        int t_id;
                   2000: {
                   2001:        switch (t_id) {
                   2002:        case IPSECDOI_IPCOMP_OUI:
                   2003:        case IPSECDOI_IPCOMP_DEFLATE:
                   2004:        case IPSECDOI_IPCOMP_LZS:
                   2005:                return 0;
                   2006:        default:
                   2007:                plog(LLV_ERROR, LOCATION, NULL,
                   2008:                        "invalid transform-id=%u in IPCOMP.\n", t_id);
                   2009:                return -1;
                   2010:        }
                   2011:        /* NOT REACHED */
                   2012: }
                   2013: 
                   2014: /*
                   2015:  * check data attributes in IKE.
                   2016:  */
                   2017: static int
                   2018: check_attr_isakmp(trns)
                   2019:        struct isakmp_pl_t *trns;
                   2020: {
                   2021:        struct isakmp_data *d;
                   2022:        int tlen;
                   2023:        int flag, type;
                   2024:        u_int16_t lorv;
                   2025: 
                   2026:        tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
                   2027:        d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
                   2028: 
                   2029:        while (tlen > 0) {
                   2030:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
                   2031:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
                   2032:                lorv = ntohs(d->lorv);
                   2033: 
                   2034:                plog(LLV_DEBUG, LOCATION, NULL,
                   2035:                        "type=%s, flag=0x%04x, lorv=%s\n",
                   2036:                        s_oakley_attr(type), flag,
                   2037:                        s_oakley_attr_v(type, lorv));
                   2038: 
                   2039:                /*
                   2040:                 * some of the attributes must be encoded in TV.
                   2041:                 * see RFC2409 Appendix A "Attribute Classes".
                   2042:                 */
                   2043:                switch (type) {
                   2044:                case OAKLEY_ATTR_ENC_ALG:
                   2045:                case OAKLEY_ATTR_HASH_ALG:
                   2046:                case OAKLEY_ATTR_AUTH_METHOD:
                   2047:                case OAKLEY_ATTR_GRP_DESC:
                   2048:                case OAKLEY_ATTR_GRP_TYPE:
                   2049:                case OAKLEY_ATTR_SA_LD_TYPE:
                   2050:                case OAKLEY_ATTR_PRF:
                   2051:                case OAKLEY_ATTR_KEY_LEN:
                   2052:                case OAKLEY_ATTR_FIELD_SIZE:
                   2053:                        if (!flag) {    /* TLV*/
                   2054:                                plog(LLV_ERROR, LOCATION, NULL,
                   2055:                                        "oakley attribute %d must be TV.\n",
                   2056:                                        type);
                   2057:                                return -1;
                   2058:                        }
                   2059:                        break;
                   2060:                }
                   2061: 
                   2062:                /* sanity check for TLV.  length must be specified. */
                   2063:                if (!flag && lorv == 0) {       /*TLV*/
                   2064:                        plog(LLV_ERROR, LOCATION, NULL,
                   2065:                                "invalid length %d for TLV attribute %d.\n",
                   2066:                                lorv, type);
                   2067:                        return -1;
                   2068:                }
                   2069: 
                   2070:                switch (type) {
                   2071:                case OAKLEY_ATTR_ENC_ALG:
                   2072:                        if (!alg_oakley_encdef_ok(lorv)) {
                   2073:                                plog(LLV_ERROR, LOCATION, NULL,
                   2074:                                        "invalied encryption algorithm=%d.\n",
                   2075:                                        lorv);
                   2076:                                return -1;
                   2077:                        }
                   2078:                        break;
                   2079: 
                   2080:                case OAKLEY_ATTR_HASH_ALG:
                   2081:                        if (!alg_oakley_hashdef_ok(lorv)) {
                   2082:                                plog(LLV_ERROR, LOCATION, NULL,
                   2083:                                        "invalied hash algorithm=%d.\n",
                   2084:                                        lorv);
                   2085:                                return -1;
                   2086:                        }
                   2087:                        break;
                   2088: 
                   2089:                case OAKLEY_ATTR_AUTH_METHOD:
                   2090:                        switch (lorv) {
                   2091:                        case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
                   2092:                        case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
                   2093: #ifdef ENABLE_HYBRID
                   2094:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
                   2095:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
                   2096: #endif
                   2097: #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
                   2098:                                /* These two authentication method IDs overlap. */
                   2099:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
                   2100:                        /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
                   2101: #endif
                   2102:                                break;
                   2103:                        case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
                   2104: #ifdef ENABLE_HYBRID
                   2105:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
                   2106:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
                   2107:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
                   2108:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
                   2109:                        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
                   2110:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
                   2111:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
                   2112:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
                   2113:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
                   2114:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
                   2115:                        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
                   2116: #endif
                   2117:                        case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
                   2118:                        case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
                   2119:                                plog(LLV_ERROR, LOCATION, NULL,
                   2120:                                        "auth method %s isn't supported.\n",
                   2121:                                        s_oakley_attr_method(lorv));
                   2122:                                return -1;
                   2123:                        default:
                   2124:                                plog(LLV_ERROR, LOCATION, NULL,
                   2125:                                        "invalid auth method %d.\n",
                   2126:                                        lorv);
                   2127:                                return -1;
                   2128:                        }
                   2129:                        break;
                   2130: 
                   2131:                case OAKLEY_ATTR_GRP_DESC:
                   2132:                        if (!alg_oakley_dhdef_ok(lorv)) {
                   2133:                                plog(LLV_ERROR, LOCATION, NULL,
                   2134:                                        "invalid DH group %d.\n",
                   2135:                                        lorv);
                   2136:                                return -1;
                   2137:                        }
                   2138:                        break;
                   2139: 
                   2140:                case OAKLEY_ATTR_GRP_TYPE:
                   2141:                        switch (lorv) {
                   2142:                        case OAKLEY_ATTR_GRP_TYPE_MODP:
                   2143:                                break;
                   2144:                        default:
                   2145:                                plog(LLV_ERROR, LOCATION, NULL,
                   2146:                                        "unsupported DH group type %d.\n",
                   2147:                                        lorv);
                   2148:                                return -1;
                   2149:                        }
                   2150:                        break;
                   2151: 
                   2152:                case OAKLEY_ATTR_GRP_PI:
                   2153:                case OAKLEY_ATTR_GRP_GEN_ONE:
                   2154:                        /* sanity checks? */
                   2155:                        break;
                   2156: 
                   2157:                case OAKLEY_ATTR_GRP_GEN_TWO:
                   2158:                case OAKLEY_ATTR_GRP_CURVE_A:
                   2159:                case OAKLEY_ATTR_GRP_CURVE_B:
                   2160:                        plog(LLV_ERROR, LOCATION, NULL,
                   2161:                                "attr type=%u isn't supported.\n", type);
                   2162:                        return -1;
                   2163: 
                   2164:                case OAKLEY_ATTR_SA_LD_TYPE:
                   2165:                        switch (lorv) {
                   2166:                        case OAKLEY_ATTR_SA_LD_TYPE_SEC:
                   2167:                        case OAKLEY_ATTR_SA_LD_TYPE_KB:
                   2168:                                break;
                   2169:                        default:
                   2170:                                plog(LLV_ERROR, LOCATION, NULL,
                   2171:                                        "invalid life type %d.\n", lorv);
                   2172:                                return -1;
                   2173:                        }
                   2174:                        break;
                   2175: 
                   2176:                case OAKLEY_ATTR_SA_LD:
                   2177:                        /* should check the value */
                   2178:                        break;
                   2179: 
                   2180:                case OAKLEY_ATTR_PRF:
                   2181:                case OAKLEY_ATTR_KEY_LEN:
                   2182:                        break;
                   2183: 
                   2184:                case OAKLEY_ATTR_FIELD_SIZE:
                   2185:                        plog(LLV_ERROR, LOCATION, NULL,
                   2186:                                "attr type=%u isn't supported.\n", type);
                   2187:                        return -1;
                   2188: 
                   2189:                case OAKLEY_ATTR_GRP_ORDER:
                   2190:                        break;
                   2191: 
                   2192:                case OAKLEY_ATTR_GSS_ID:
                   2193:                        break;
                   2194: 
                   2195:                default:
                   2196:                        plog(LLV_ERROR, LOCATION, NULL,
                   2197:                                "invalid attribute type %d.\n", type);
                   2198:                        return -1;
                   2199:                }
                   2200: 
                   2201:                if (flag) {
                   2202:                        tlen -= sizeof(*d);
                   2203:                        d = (struct isakmp_data *)((char *)d
                   2204:                                + sizeof(*d));
                   2205:                } else {
                   2206:                        tlen -= (sizeof(*d) + lorv);
                   2207:                        d = (struct isakmp_data *)((char *)d
                   2208:                                + sizeof(*d) + lorv);
                   2209:                }
                   2210:        }
                   2211: 
                   2212:        return 0;
                   2213: }
                   2214: 
                   2215: /*
                   2216:  * check data attributes in IPSEC AH/ESP.
                   2217:  */
                   2218: static int
                   2219: check_attr_ah(trns)
                   2220:        struct isakmp_pl_t *trns;
                   2221: {
                   2222:        return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
                   2223: }
                   2224: 
                   2225: static int
                   2226: check_attr_esp(trns)
                   2227:        struct isakmp_pl_t *trns;
                   2228: {
                   2229:        return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
                   2230: }
                   2231: 
                   2232: static int
                   2233: check_attr_ipsec(proto_id, trns)
                   2234:        int proto_id;
                   2235:        struct isakmp_pl_t *trns;
                   2236: {
                   2237:        struct isakmp_data *d;
                   2238:        int tlen;
                   2239:        int flag, type = 0;
                   2240:        u_int16_t lorv;
                   2241:        int attrseen[16];       /* XXX magic number */
                   2242: 
                   2243:        tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
                   2244:        d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
                   2245:        memset(attrseen, 0, sizeof(attrseen));
                   2246: 
                   2247:        while (tlen > 0) {
                   2248:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
                   2249:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
                   2250:                lorv = ntohs(d->lorv);
                   2251: 
                   2252:                plog(LLV_DEBUG, LOCATION, NULL,
                   2253:                        "type=%s, flag=0x%04x, lorv=%s\n",
                   2254:                        s_ipsecdoi_attr(type), flag,
                   2255:                        s_ipsecdoi_attr_v(type, lorv));
                   2256: 
                   2257:                if (type < sizeof(attrseen)/sizeof(attrseen[0]))
                   2258:                        attrseen[type]++;
                   2259: 
                   2260:                switch (type) {
                   2261:                case IPSECDOI_ATTR_ENC_MODE:
                   2262:                        if (! flag) {
                   2263:                                plog(LLV_ERROR, LOCATION, NULL,
                   2264:                                        "must be TV when ENC_MODE.\n");
                   2265:                                return -1;
                   2266:                        }
                   2267: 
                   2268:                        switch (lorv) {
                   2269:                        case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
                   2270:                        case IPSECDOI_ATTR_ENC_MODE_TRNS:
                   2271:                                break;
                   2272: #ifdef ENABLE_NATT
                   2273:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
                   2274:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
                   2275:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
                   2276:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
                   2277:                                plog(LLV_DEBUG, LOCATION, NULL,
                   2278:                                     "UDP encapsulation requested\n");
                   2279:                                break;
                   2280: #endif
                   2281:                        default:
                   2282:                                plog(LLV_ERROR, LOCATION, NULL,
                   2283:                                        "invalid encryption mode=%u.\n",
                   2284:                                        lorv);
                   2285:                                return -1;
                   2286:                        }
                   2287:                        break;
                   2288: 
                   2289:                case IPSECDOI_ATTR_AUTH:
                   2290:                        if (! flag) {
                   2291:                                plog(LLV_ERROR, LOCATION, NULL,
                   2292:                                        "must be TV when AUTH.\n");
                   2293:                                return -1;
                   2294:                        }
                   2295: 
                   2296:                        switch (lorv) {
                   2297:                        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
                   2298:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
                   2299:                                    trns->t_id != IPSECDOI_AH_MD5) {
                   2300: ahmismatch:
                   2301:                                        plog(LLV_ERROR, LOCATION, NULL,
                   2302:                                                "auth algorithm %u conflicts "
                   2303:                                                "with transform %u.\n",
                   2304:                                                lorv, trns->t_id);
                   2305:                                        return -1;
                   2306:                                }
                   2307:                                break;
                   2308:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
                   2309:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
                   2310:                                        if (trns->t_id != IPSECDOI_AH_SHA)
                   2311:                                                goto ahmismatch;
                   2312:                                }
                   2313:                                break;
                   2314:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
                   2315:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
                   2316:                                        if (trns->t_id != IPSECDOI_AH_SHA256)
                   2317:                                                goto ahmismatch;
                   2318:                                }
                   2319:                                break;
                   2320:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
                   2321:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
                   2322:                                        if (trns->t_id != IPSECDOI_AH_SHA384)
                   2323:                                                goto ahmismatch;
                   2324:                                }
                   2325:                                break;
                   2326:                        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
                   2327:                                if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
                   2328:                                        if (trns->t_id != IPSECDOI_AH_SHA512)
                   2329:                                        goto ahmismatch;
                   2330:                                }
                   2331:                                break;
                   2332:                        case IPSECDOI_ATTR_AUTH_DES_MAC:
                   2333:                        case IPSECDOI_ATTR_AUTH_KPDK:
                   2334:                                plog(LLV_ERROR, LOCATION, NULL,
                   2335:                                        "auth algorithm %u isn't supported.\n",
                   2336:                                        lorv);
                   2337:                                return -1;
                   2338:                        default:
                   2339:                                plog(LLV_ERROR, LOCATION, NULL,
                   2340:                                        "invalid auth algorithm=%u.\n",
                   2341:                                        lorv);
                   2342:                                return -1;
                   2343:                        }
                   2344:                        break;
                   2345: 
                   2346:                case IPSECDOI_ATTR_SA_LD_TYPE:
                   2347:                        if (! flag) {
                   2348:                                plog(LLV_ERROR, LOCATION, NULL,
                   2349:                                        "must be TV when LD_TYPE.\n");
                   2350:                                return -1;
                   2351:                        }
                   2352: 
                   2353:                        switch (lorv) {
                   2354:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
                   2355:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
                   2356:                                break;
                   2357:                        default:
                   2358:                                plog(LLV_ERROR, LOCATION, NULL,
                   2359:                                        "invalid life type %d.\n", lorv);
                   2360:                                return -1;
                   2361:                        }
                   2362:                        break;
                   2363: 
                   2364:                case IPSECDOI_ATTR_SA_LD:
                   2365:                        if (flag) {
                   2366:                                /* i.e. ISAKMP_GEN_TV */
                   2367:                                plog(LLV_DEBUG, LOCATION, NULL,
                   2368:                                        "life duration was in TLV.\n");
                   2369:                        } else {
                   2370:                                /* i.e. ISAKMP_GEN_TLV */
                   2371:                                if (lorv == 0) {
                   2372:                                        plog(LLV_ERROR, LOCATION, NULL,
                   2373:                                                "invalid length of LD\n");
                   2374:                                        return -1;
                   2375:                                }
                   2376:                        }
                   2377:                        break;
                   2378: 
                   2379:                case IPSECDOI_ATTR_GRP_DESC:
                   2380:                        if (! flag) {
                   2381:                                plog(LLV_ERROR, LOCATION, NULL,
                   2382:                                        "must be TV when GRP_DESC.\n");
                   2383:                                return -1;
                   2384:                        }
                   2385: 
                   2386:                        if (!alg_oakley_dhdef_ok(lorv)) {
                   2387:                                plog(LLV_ERROR, LOCATION, NULL,
                   2388:                                        "invalid group description=%u.\n",
                   2389:                                        lorv);
                   2390:                                return -1;
                   2391:                        }
                   2392:                        break;
                   2393: 
                   2394:                case IPSECDOI_ATTR_KEY_LENGTH:
                   2395:                        if (! flag) {
                   2396:                                plog(LLV_ERROR, LOCATION, NULL,
                   2397:                                        "must be TV when KEY_LENGTH.\n");
                   2398:                                return -1;
                   2399:                        }
                   2400:                        break;
                   2401: 
                   2402: #ifdef HAVE_SECCTX
                   2403:                case IPSECDOI_ATTR_SECCTX:
                   2404:                        if (flag) {
                   2405:                                plog(LLV_ERROR, LOCATION, NULL,
                   2406:                                        "SECCTX must be in TLV.\n");
                   2407:                                return -1;
                   2408:                        }
                   2409:                break;
                   2410: #endif
                   2411: 
                   2412:                case IPSECDOI_ATTR_KEY_ROUNDS:
                   2413:                case IPSECDOI_ATTR_COMP_DICT_SIZE:
                   2414:                case IPSECDOI_ATTR_COMP_PRIVALG:
                   2415:                        plog(LLV_ERROR, LOCATION, NULL,
                   2416:                                "attr type=%u isn't supported.\n", type);
                   2417:                        return -1;
                   2418: 
                   2419:                default:
                   2420:                        plog(LLV_ERROR, LOCATION, NULL,
                   2421:                                "invalid attribute type %d.\n", type);
                   2422:                        return -1;
                   2423:                }
                   2424: 
                   2425:                if (flag) {
                   2426:                        tlen -= sizeof(*d);
                   2427:                        d = (struct isakmp_data *)((char *)d
                   2428:                                + sizeof(*d));
                   2429:                } else {
                   2430:                        tlen -= (sizeof(*d) + lorv);
                   2431:                        d = (struct isakmp_data *)((caddr_t)d
                   2432:                                + sizeof(*d) + lorv);
                   2433:                }
                   2434:        }
                   2435: 
                   2436:        if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
                   2437:            !attrseen[IPSECDOI_ATTR_AUTH]) {
                   2438:                plog(LLV_ERROR, LOCATION, NULL,
                   2439:                        "attr AUTH must be present for AH.\n");
                   2440:                return -1;
                   2441:        }
                   2442: 
                   2443:        if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
                   2444:            trns->t_id == IPSECDOI_ESP_NULL &&
                   2445:            !attrseen[IPSECDOI_ATTR_AUTH]) {
                   2446:                plog(LLV_ERROR, LOCATION, NULL,
                   2447:                    "attr AUTH must be present for ESP NULL encryption.\n");
                   2448:                return -1;
                   2449:        }
                   2450: 
                   2451:        return 0;
                   2452: }
                   2453: 
                   2454: static int
                   2455: check_attr_ipcomp(trns)
                   2456:        struct isakmp_pl_t *trns;
                   2457: {
                   2458:        struct isakmp_data *d;
                   2459:        int tlen;
                   2460:        int flag, type = 0;
                   2461:        u_int16_t lorv;
                   2462:        int attrseen[16];       /* XXX magic number */
                   2463: 
                   2464:        tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
                   2465:        d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
                   2466:        memset(attrseen, 0, sizeof(attrseen));
                   2467: 
                   2468:        while (tlen > 0) {
                   2469:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
                   2470:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
                   2471:                lorv = ntohs(d->lorv);
                   2472: 
                   2473:                plog(LLV_DEBUG, LOCATION, NULL,
                   2474:                        "type=%d, flag=0x%04x, lorv=0x%04x\n",
                   2475:                        type, flag, lorv);
                   2476: 
                   2477:                if (type < sizeof(attrseen)/sizeof(attrseen[0]))
                   2478:                        attrseen[type]++;
                   2479: 
                   2480:                switch (type) {
                   2481:                case IPSECDOI_ATTR_ENC_MODE:
                   2482:                        if (! flag) {
                   2483:                                plog(LLV_ERROR, LOCATION, NULL,
                   2484:                                        "must be TV when ENC_MODE.\n");
                   2485:                                return -1;
                   2486:                        }
                   2487: 
                   2488:                        switch (lorv) {
                   2489:                        case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
                   2490:                        case IPSECDOI_ATTR_ENC_MODE_TRNS:
                   2491:                                break;
                   2492: #ifdef ENABLE_NATT
                   2493:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
                   2494:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
                   2495:                        case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
                   2496:                        case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
                   2497:                                plog(LLV_DEBUG, LOCATION, NULL,
                   2498:                                     "UDP encapsulation requested\n");
                   2499:                                break;
                   2500: #endif
                   2501:                        default:
                   2502:                                plog(LLV_ERROR, LOCATION, NULL,
                   2503:                                        "invalid encryption mode=%u.\n",
                   2504:                                        lorv);
                   2505:                                return -1;
                   2506:                        }
                   2507:                        break;
                   2508: 
                   2509:                case IPSECDOI_ATTR_SA_LD_TYPE:
                   2510:                        if (! flag) {
                   2511:                                plog(LLV_ERROR, LOCATION, NULL,
                   2512:                                        "must be TV when LD_TYPE.\n");
                   2513:                                return -1;
                   2514:                        }
                   2515: 
                   2516:                        switch (lorv) {
                   2517:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
                   2518:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
                   2519:                                break;
                   2520:                        default:
                   2521:                                plog(LLV_ERROR, LOCATION, NULL,
                   2522:                                        "invalid life type %d.\n", lorv);
                   2523:                                return -1;
                   2524:                        }
                   2525:                        break;
                   2526: 
                   2527:                case IPSECDOI_ATTR_SA_LD:
                   2528:                        if (flag) {
                   2529:                                /* i.e. ISAKMP_GEN_TV */
                   2530:                                plog(LLV_DEBUG, LOCATION, NULL,
                   2531:                                        "life duration was in TLV.\n");
                   2532:                        } else {
                   2533:                                /* i.e. ISAKMP_GEN_TLV */
                   2534:                                if (lorv == 0) {
                   2535:                                        plog(LLV_ERROR, LOCATION, NULL,
                   2536:                                                "invalid length of LD\n");
                   2537:                                        return -1;
                   2538:                                }
                   2539:                        }
                   2540:                        break;
                   2541: 
                   2542:                case IPSECDOI_ATTR_GRP_DESC:
                   2543:                        if (! flag) {
                   2544:                                plog(LLV_ERROR, LOCATION, NULL,
                   2545:                                        "must be TV when GRP_DESC.\n");
                   2546:                                return -1;
                   2547:                        }
                   2548: 
                   2549:                        if (!alg_oakley_dhdef_ok(lorv)) {
                   2550:                                plog(LLV_ERROR, LOCATION, NULL,
                   2551:                                        "invalid group description=%u.\n",
                   2552:                                        lorv);
                   2553:                                return -1;
                   2554:                        }
                   2555:                        break;
                   2556: 
                   2557:                case IPSECDOI_ATTR_AUTH:
                   2558:                        plog(LLV_ERROR, LOCATION, NULL,
                   2559:                                "invalid attr type=%u.\n", type);
                   2560:                        return -1;
                   2561: 
                   2562:                case IPSECDOI_ATTR_KEY_LENGTH:
                   2563:                case IPSECDOI_ATTR_KEY_ROUNDS:
                   2564:                case IPSECDOI_ATTR_COMP_DICT_SIZE:
                   2565:                case IPSECDOI_ATTR_COMP_PRIVALG:
                   2566:                        plog(LLV_ERROR, LOCATION, NULL,
                   2567:                                "attr type=%u isn't supported.\n", type);
                   2568:                        return -1;
                   2569: 
                   2570:                default:
                   2571:                        plog(LLV_ERROR, LOCATION, NULL,
                   2572:                                "invalid attribute type %d.\n", type);
                   2573:                        return -1;
                   2574:                }
                   2575: 
                   2576:                if (flag) {
                   2577:                        tlen -= sizeof(*d);
                   2578:                        d = (struct isakmp_data *)((char *)d
                   2579:                                + sizeof(*d));
                   2580:                } else {
                   2581:                        tlen -= (sizeof(*d) + lorv);
                   2582:                        d = (struct isakmp_data *)((caddr_t)d
                   2583:                                + sizeof(*d) + lorv);
                   2584:                }
                   2585:        }
                   2586: 
                   2587: #if 0
                   2588:        if (proto_id == IPSECDOI_PROTO_IPCOMP &&
                   2589:            !attrseen[IPSECDOI_ATTR_AUTH]) {
                   2590:                plog(LLV_ERROR, LOCATION, NULL,
                   2591:                        "attr AUTH must be present for AH.\n", type);
                   2592:                return -1;
                   2593:        }
                   2594: #endif
                   2595: 
                   2596:        return 0;
                   2597: }
                   2598: 
                   2599: /* %%% */
                   2600: /*
                   2601:  * create phase1 proposal from remote configuration.
                   2602:  * NOT INCLUDING isakmp general header of SA payload
                   2603:  */
                   2604: vchar_t *
                   2605: ipsecdoi_setph1proposal(rmconf, props)
                   2606:        struct remoteconf *rmconf;
                   2607:        struct isakmpsa *props;
                   2608: {
                   2609:        vchar_t *mysa;
                   2610:        int sablen;
                   2611: 
                   2612:        /* count total size of SA minus isakmp general header */
                   2613:        /* not including isakmp general header of SA payload */
                   2614:        sablen = sizeof(struct ipsecdoi_sa_b);
                   2615:        sablen += setph1prop(props, NULL);
                   2616: 
                   2617:        mysa = vmalloc(sablen);
                   2618:        if (mysa == NULL) {
                   2619:                plog(LLV_ERROR, LOCATION, NULL,
                   2620:                        "failed to allocate my sa buffer\n");
                   2621:                return NULL;
                   2622:        }
                   2623: 
                   2624:        /* create SA payload */
                   2625:        /* not including isakmp general header */
                   2626:        ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
                   2627:        ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
                   2628: 
                   2629:        (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
                   2630: 
                   2631:        return mysa;
                   2632: }
                   2633: 
                   2634: static int
                   2635: setph1prop(props, buf)
                   2636:        struct isakmpsa *props;
                   2637:        caddr_t buf;
                   2638: {
                   2639:        struct isakmp_pl_p *prop = NULL;
                   2640:        struct isakmpsa *s = NULL;
                   2641:        int proplen, trnslen;
                   2642:        u_int8_t *np_t; /* pointer next trns type in previous header */
                   2643:        int trns_num;
                   2644:        caddr_t p = buf;
                   2645: 
                   2646:        proplen = sizeof(*prop);
                   2647:        if (buf) {
                   2648:                /* create proposal */
                   2649:                prop = (struct isakmp_pl_p *)p;
                   2650:                prop->h.np = ISAKMP_NPTYPE_NONE;
                   2651:                prop->p_no = props->prop_no;
                   2652:                prop->proto_id = IPSECDOI_PROTO_ISAKMP;
                   2653:                prop->spi_size = 0;
                   2654:                p += sizeof(*prop);
                   2655:        }
                   2656: 
                   2657:        np_t = NULL;
                   2658:        trns_num = 0;
                   2659: 
                   2660:        for (s = props; s != NULL; s = s->next) {
                   2661:                if (np_t)
                   2662:                        *np_t = ISAKMP_NPTYPE_T;
                   2663: 
                   2664:                trnslen = setph1trns(s, p);
                   2665:                proplen += trnslen;
                   2666:                if (buf) {
                   2667:                        /* save buffer to pre-next payload */
                   2668:                        np_t = &((struct isakmp_pl_t *)p)->h.np;
                   2669:                        p += trnslen;
                   2670: 
                   2671:                        /* count up transform length */
                   2672:                        trns_num++;
                   2673:                }
                   2674:        }
                   2675: 
                   2676:        /* update proposal length */
                   2677:        if (buf) {
                   2678:                prop->h.len = htons(proplen);
                   2679:                prop->num_t = trns_num;
                   2680:        }
                   2681: 
                   2682:        return proplen;
                   2683: }
                   2684: 
                   2685: static int
                   2686: setph1trns(sa, buf)
                   2687:        struct isakmpsa *sa;
                   2688:        caddr_t buf;
                   2689: {
                   2690:        struct isakmp_pl_t *trns = NULL;
                   2691:        int trnslen, attrlen;
                   2692:        caddr_t p = buf;
                   2693: 
                   2694:        trnslen = sizeof(*trns);
                   2695:        if (buf) {
                   2696:                /* create transform */
                   2697:                trns = (struct isakmp_pl_t *)p;
                   2698:                trns->h.np  = ISAKMP_NPTYPE_NONE;
                   2699:                trns->t_no  = sa->trns_no;
                   2700:                trns->t_id  = IPSECDOI_KEY_IKE;
                   2701:                p += sizeof(*trns);
                   2702:        }
                   2703: 
                   2704:        attrlen = setph1attr(sa, p);
                   2705:        trnslen += attrlen;
                   2706:        if (buf)
                   2707:                p += attrlen;
                   2708: 
                   2709:        if (buf)
                   2710:                trns->h.len = htons(trnslen);
                   2711: 
                   2712:        return trnslen;
                   2713: }
                   2714: 
                   2715: static int
                   2716: setph1attr(sa, buf)
                   2717:        struct isakmpsa *sa;
                   2718:        caddr_t buf;
                   2719: {
                   2720:        caddr_t p = buf;
                   2721:        int attrlen = 0;
                   2722: 
                   2723:        if (sa->lifetime) {
                   2724:                u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
                   2725: 
                   2726:                attrlen += sizeof(struct isakmp_data)
                   2727:                        + sizeof(struct isakmp_data);
                   2728:                if (sa->lifetime > 0xffff)
                   2729:                        attrlen += sizeof(lifetime);
                   2730:                if (buf) {
                   2731:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
                   2732:                                                OAKLEY_ATTR_SA_LD_TYPE_SEC);
                   2733:                        if (sa->lifetime > 0xffff) {
                   2734:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
                   2735:                                                (caddr_t)&lifetime,
                   2736:                                                sizeof(lifetime));
                   2737:                        } else {
                   2738:                                p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
                   2739:                                                        sa->lifetime);
                   2740:                        }
                   2741:                }
                   2742:        }
                   2743: 
                   2744:        if (sa->lifebyte) {
                   2745:                u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
                   2746: 
                   2747:                attrlen += sizeof(struct isakmp_data)
                   2748:                        + sizeof(struct isakmp_data);
                   2749:                if (sa->lifebyte > 0xffff)
                   2750:                        attrlen += sizeof(lifebyte);
                   2751:                if (buf) {
                   2752:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
                   2753:                                                OAKLEY_ATTR_SA_LD_TYPE_KB);
                   2754:                        if (sa->lifebyte > 0xffff) {
                   2755:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
                   2756:                                                        (caddr_t)&lifebyte,
                   2757:                                                        sizeof(lifebyte));
                   2758:                        } else {
                   2759:                                p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
                   2760:                                                        sa->lifebyte);
                   2761:                        }
                   2762:                }
                   2763:        }
                   2764: 
                   2765:        if (sa->enctype) {
                   2766:                attrlen += sizeof(struct isakmp_data);
                   2767:                if (buf)
                   2768:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
                   2769:        }
                   2770:        if (sa->encklen) {
                   2771:                attrlen += sizeof(struct isakmp_data);
                   2772:                if (buf)
                   2773:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
                   2774:        }
                   2775:        if (sa->authmethod) {
                   2776:                int authmethod;
                   2777: 
                   2778:                authmethod = isakmpsa_switch_authmethod(sa->authmethod);
                   2779:                authmethod &= 0xffff;
                   2780:                attrlen += sizeof(struct isakmp_data);
                   2781:                if (buf)
                   2782:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
                   2783:        }
                   2784:        if (sa->hashtype) {
                   2785:                attrlen += sizeof(struct isakmp_data);
                   2786:                if (buf)
                   2787:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
                   2788:        }
                   2789:        switch (sa->dh_group) {
                   2790:        case OAKLEY_ATTR_GRP_DESC_MODP768:
                   2791:        case OAKLEY_ATTR_GRP_DESC_MODP1024:
                   2792:        case OAKLEY_ATTR_GRP_DESC_MODP1536:
                   2793:        case OAKLEY_ATTR_GRP_DESC_MODP2048:
                   2794:        case OAKLEY_ATTR_GRP_DESC_MODP3072:
                   2795:        case OAKLEY_ATTR_GRP_DESC_MODP4096:
                   2796:        case OAKLEY_ATTR_GRP_DESC_MODP6144:
                   2797:        case OAKLEY_ATTR_GRP_DESC_MODP8192:
                   2798:                /* don't attach group type for known groups */
                   2799:                attrlen += sizeof(struct isakmp_data);
                   2800:                if (buf) {
                   2801:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
                   2802:                                sa->dh_group);
                   2803:                }
                   2804:                break;
                   2805:        case OAKLEY_ATTR_GRP_DESC_EC2N155:
                   2806:        case OAKLEY_ATTR_GRP_DESC_EC2N185:
                   2807:                /* don't attach group type for known groups */
                   2808:                attrlen += sizeof(struct isakmp_data);
                   2809:                if (buf) {
                   2810:                        p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
                   2811:                                OAKLEY_ATTR_GRP_TYPE_EC2N);
                   2812:                }
                   2813:                break;
                   2814:        case 0:
                   2815:        default:
                   2816:                break;
                   2817:        }
                   2818: 
                   2819: #ifdef HAVE_GSSAPI
                   2820:        if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
                   2821:            sa->gssid != NULL) {
                   2822:                attrlen += sizeof(struct isakmp_data);
                   2823:                /*
                   2824:                 * Older versions of racoon just placed the ISO-Latin-1
                   2825:                 * string on the wire directly.  Check to see if we are
                   2826:                 * configured to be compatible with this behavior.  Otherwise,
                   2827:                 * we encode the GSS ID as UTF-16LE for Windows 2000
                   2828:                 * compatibility, which requires twice the number of octets.
                   2829:                 */
                   2830:                if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
                   2831:                        attrlen += sa->gssid->l;
                   2832:                else
                   2833:                        attrlen += sa->gssid->l * 2;
                   2834:                if (buf) {
                   2835:                        plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
                   2836:                            "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
                   2837:                            sa->gssid->v);
                   2838:                        if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
                   2839:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
                   2840:                                        (caddr_t)sa->gssid->v,
                   2841:                                        sa->gssid->l);
                   2842:                        } else {
                   2843:                                size_t dstleft = sa->gssid->l * 2;
                   2844:                                size_t srcleft = sa->gssid->l;
                   2845:                                const char *src = (const char *)sa->gssid->v;
                   2846:                                char *odst, *dst = racoon_malloc(dstleft);
                   2847:                                iconv_t cd;
                   2848:                                size_t rv;
                   2849: 
                   2850:                                cd = iconv_open("utf-16le", "latin1");
                   2851:                                if (cd == (iconv_t) -1) {
                   2852:                                        plog(LLV_ERROR, LOCATION, NULL,
                   2853:                                            "unable to initialize "
                   2854:                                            "latin1 -> utf-16le "
                   2855:                                            "converstion descriptor: %s\n",
                   2856:                                            strerror(errno));
                   2857:                                        attrlen -= sa->gssid->l * 2;
                   2858:                                        goto gssid_done;
                   2859:                                }
                   2860:                                odst = dst;
                   2861:                                rv = iconv(cd, (__iconv_const char **)&src,
                   2862:                                    &srcleft, &dst, &dstleft);
                   2863:                                if (rv != 0) {
                   2864:                                        if (rv == -1) {
                   2865:                                                plog(LLV_ERROR, LOCATION, NULL,
                   2866:                                                    "unable to convert GSS ID "
                   2867:                                                    "from latin1 -> utf-16le: "
                   2868:                                                    "%s\n", strerror(errno));
                   2869:                                        } else {
                   2870:                                                /* should never happen */
                   2871:                                                plog(LLV_ERROR, LOCATION, NULL,
                   2872:                                                    "%zd character%s in GSS ID "
                   2873:                                                    "cannot be represented "
                   2874:                                                    "in utf-16le\n",
                   2875:                                                    rv, rv == 1 ? "" : "s");
                   2876:                                        }
                   2877:                                        (void) iconv_close(cd);
                   2878:                                        attrlen -= sa->gssid->l * 2;
                   2879:                                        goto gssid_done;
                   2880:                                }
                   2881:                                (void) iconv_close(cd);
                   2882: 
                   2883:                                /* XXX Check srcleft and dstleft? */
                   2884: 
                   2885:                                p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
                   2886:                                        odst, sa->gssid->l * 2);
                   2887: 
                   2888:                                racoon_free(odst);
                   2889:                        }
                   2890:                }
                   2891:        }
                   2892:  gssid_done:
                   2893: #endif /* HAVE_GSSAPI */
                   2894: 
                   2895:        return attrlen;
                   2896: }
                   2897: 
                   2898: static vchar_t *
                   2899: setph2proposal0(iph2, pp, pr)
                   2900:        const struct ph2handle *iph2;
                   2901:        const struct saprop *pp;
                   2902:        const struct saproto *pr;
                   2903: {
                   2904:        vchar_t *p;
                   2905:        struct isakmp_pl_p *prop;
                   2906:        struct isakmp_pl_t *trns;
                   2907:        struct satrns *tr;
                   2908:        int attrlen;
                   2909:        size_t trnsoff;
                   2910:        caddr_t x0, x;
                   2911:        u_int8_t *np_t; /* pointer next trns type in previous header */
                   2912:        const u_int8_t *spi;
                   2913: #ifdef HAVE_SECCTX
                   2914:        int truectxlen = 0;
                   2915: #endif
                   2916: 
                   2917:        p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
                   2918:        if (p == NULL)
                   2919:                return NULL;
                   2920: 
                   2921:        /* create proposal */
                   2922:        prop = (struct isakmp_pl_p *)p->v;
                   2923:        prop->h.np = ISAKMP_NPTYPE_NONE;
                   2924:        prop->p_no = pp->prop_no;
                   2925:        prop->proto_id = pr->proto_id;
                   2926:        prop->num_t = 1;
                   2927: 
                   2928:        spi = (const u_int8_t *)&pr->spi;
                   2929:        switch (pr->proto_id) {
                   2930:        case IPSECDOI_PROTO_IPCOMP:
                   2931:                /*
                   2932:                 * draft-shacham-ippcp-rfc2393bis-05.txt:
                   2933:                 * construct 16bit SPI (CPI).
                   2934:                 * XXX we may need to provide a configuration option to
                   2935:                 * generate 32bit SPI.  otherwise we cannot interoeprate
                   2936:                 * with nodes that uses 32bit SPI, in case we are initiator.
                   2937:                 */
                   2938:                prop->spi_size = sizeof(u_int16_t);
                   2939:                spi += sizeof(pr->spi) - sizeof(u_int16_t);
                   2940:                p->l -= sizeof(pr->spi);
                   2941:                p->l += sizeof(u_int16_t);
                   2942:                break;
                   2943:        default:
                   2944:                prop->spi_size = sizeof(pr->spi);
                   2945:                break;
                   2946:        }
                   2947:        memcpy(prop + 1, spi, prop->spi_size);
                   2948: 
                   2949:        /* create transform */
                   2950:        trnsoff = sizeof(*prop) + prop->spi_size;
                   2951:        np_t = NULL;
                   2952: 
                   2953:        for (tr = pr->head; tr; tr = tr->next) {
                   2954: 
                   2955:                switch (pr->proto_id) {
                   2956:                case IPSECDOI_PROTO_IPSEC_ESP:
                   2957:                        /*
                   2958:                         * don't build a null encryption
                   2959:                         * with no authentication transform.
                   2960:                         */
                   2961:                        if (tr->trns_id == IPSECDOI_ESP_NULL &&
                   2962:                            tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
                   2963:                                continue;
                   2964:                        break;
                   2965:                }
                   2966: 
                   2967:                if (np_t) {
                   2968:                        *np_t = ISAKMP_NPTYPE_T;
                   2969:                        prop->num_t++;
                   2970:                }
                   2971: 
                   2972:                /* get attribute length */
                   2973:                attrlen = 0;
                   2974:                if (pp->lifetime) {
                   2975:                        attrlen += sizeof(struct isakmp_data)
                   2976:                                + sizeof(struct isakmp_data);
                   2977:                        if (pp->lifetime > 0xffff)
                   2978:                                attrlen += sizeof(u_int32_t);
                   2979:                }
                   2980:                if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
                   2981:                        attrlen += sizeof(struct isakmp_data)
                   2982:                                + sizeof(struct isakmp_data);
                   2983:                        if (pp->lifebyte > 0xffff)
                   2984:                                attrlen += sizeof(u_int32_t);
                   2985:                }
                   2986:                attrlen += sizeof(struct isakmp_data);  /* enc mode */
                   2987:                if (tr->encklen)
                   2988:                        attrlen += sizeof(struct isakmp_data);
                   2989: 
                   2990:                switch (pr->proto_id) {
                   2991:                case IPSECDOI_PROTO_IPSEC_ESP:
                   2992:                        /* non authentication mode ? */
                   2993:                        if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
                   2994:                                attrlen += sizeof(struct isakmp_data);
                   2995:                        break;
                   2996:                case IPSECDOI_PROTO_IPSEC_AH:
                   2997:                        if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
                   2998:                                plog(LLV_ERROR, LOCATION, NULL,
                   2999:                                        "no authentication algorithm found "
                   3000:                                        "but protocol is AH.\n");
                   3001:                                vfree(p);
                   3002:                                return NULL;
                   3003:                        }
                   3004:                        attrlen += sizeof(struct isakmp_data);
                   3005:                        break;
                   3006:                case IPSECDOI_PROTO_IPCOMP:
                   3007:                        break;
                   3008:                default:
                   3009:                        plog(LLV_ERROR, LOCATION, NULL,
                   3010:                                "invalid protocol: %d\n", pr->proto_id);
                   3011:                        vfree(p);
                   3012:                        return NULL;
                   3013:                }
                   3014: 
                   3015:                if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
                   3016:                        attrlen += sizeof(struct isakmp_data);
                   3017: 
                   3018: #ifdef HAVE_SECCTX
                   3019:                /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
                   3020:                 * The string may be smaller than MAX_CTXSTR_SIZ.
                   3021:                 */
                   3022:                if (*pp->sctx.ctx_str) {
                   3023:                        truectxlen = sizeof(struct security_ctx) -
                   3024:                                     (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
                   3025:                        attrlen += sizeof(struct isakmp_data) + truectxlen;
                   3026:                }
                   3027: #endif /* HAVE_SECCTX */
                   3028: 
                   3029:                p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
                   3030:                if (p == NULL)
                   3031:                        return NULL;
                   3032:                prop = (struct isakmp_pl_p *)p->v;
                   3033: 
                   3034:                /* set transform's values */
                   3035:                trns = (struct isakmp_pl_t *)(p->v + trnsoff);
                   3036:                trns->h.np  = ISAKMP_NPTYPE_NONE;
                   3037:                trns->t_no  = tr->trns_no;
                   3038:                trns->t_id  = tr->trns_id;
                   3039: 
                   3040:                /* set attributes */
                   3041:                x = x0 = p->v + trnsoff + sizeof(*trns);
                   3042: 
                   3043:                if (pp->lifetime) {
                   3044:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
                   3045:                                                IPSECDOI_ATTR_SA_LD_TYPE_SEC);
                   3046:                        if (pp->lifetime > 0xffff) {
                   3047:                                u_int32_t v = htonl((u_int32_t)pp->lifetime);
                   3048:                                x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
                   3049:                                                        (caddr_t)&v, sizeof(v));
                   3050:                        } else {
                   3051:                                x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
                   3052:                                                        pp->lifetime);
                   3053:                        }
                   3054:                }
                   3055: 
                   3056:                if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
                   3057:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
                   3058:                                                IPSECDOI_ATTR_SA_LD_TYPE_KB);
                   3059:                        if (pp->lifebyte > 0xffff) {
                   3060:                                u_int32_t v = htonl((u_int32_t)pp->lifebyte);
                   3061:                                x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
                   3062:                                                        (caddr_t)&v, sizeof(v));
                   3063:                        } else {
                   3064:                                x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
                   3065:                                                        pp->lifebyte);
                   3066:                        }
                   3067:                }
                   3068: 
                   3069:                x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
                   3070: 
                   3071:                if (tr->encklen)
                   3072:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
                   3073: 
                   3074:                /* mandatory check has done above. */
                   3075:                if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
                   3076:                 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
                   3077:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
                   3078: 
                   3079:                if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
                   3080:                        x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
                   3081:                                iph2->sainfo->pfs_group);
                   3082: 
                   3083: #ifdef HAVE_SECCTX
                   3084:                if (*pp->sctx.ctx_str) {
                   3085:                        struct security_ctx secctx;
                   3086:                        secctx = pp->sctx;
                   3087:                        secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
                   3088:                        x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
                   3089:                                             (caddr_t)&secctx, truectxlen);
                   3090:                }
                   3091: #endif
                   3092:                /* update length of this transform. */
                   3093:                trns = (struct isakmp_pl_t *)(p->v + trnsoff);
                   3094:                trns->h.len = htons(sizeof(*trns) + attrlen);
                   3095: 
                   3096:                /* save buffer to pre-next payload */
                   3097:                np_t = &trns->h.np;
                   3098: 
                   3099:                trnsoff += (sizeof(*trns) + attrlen);
                   3100:        }
                   3101: 
                   3102:        if (np_t == NULL) {
                   3103:                plog(LLV_ERROR, LOCATION, NULL,
                   3104:                        "no suitable proposal was created.\n");
                   3105:                return NULL;
                   3106:        }
                   3107: 
                   3108:        /* update length of this protocol. */
                   3109:        prop->h.len = htons(p->l);
                   3110: 
                   3111:        return p;
                   3112: }
                   3113: 
                   3114: /*
                   3115:  * create phase2 proposal from policy configuration.
                   3116:  * NOT INCLUDING isakmp general header of SA payload.
                   3117:  * This function is called by initiator only.
                   3118:  */
                   3119: int
                   3120: ipsecdoi_setph2proposal(iph2)
                   3121:        struct ph2handle *iph2;
                   3122: {
                   3123:        struct saprop *proposal, *a;
                   3124:        struct saproto *b = NULL;
                   3125:        vchar_t *q;
                   3126:        struct ipsecdoi_sa_b *sab;
                   3127:        struct isakmp_pl_p *prop;
                   3128:        size_t propoff; /* for previous field of type of next payload. */
                   3129: 
                   3130:        proposal = iph2->proposal;
                   3131: 
                   3132:        iph2->sa = vmalloc(sizeof(*sab));
                   3133:        if (iph2->sa == NULL) {
                   3134:                plog(LLV_ERROR, LOCATION, NULL,
                   3135:                        "failed to allocate my sa buffer\n");
                   3136:                return -1;
                   3137:        }
                   3138: 
                   3139:        /* create SA payload */
                   3140:        sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
                   3141:        sab->doi = htonl(IPSEC_DOI);
                   3142:        sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY);   /* XXX configurable ? */
                   3143: 
                   3144:        prop = NULL;
                   3145:        propoff = 0;
                   3146:        for (a = proposal; a; a = a->next) {
                   3147:                for (b = a->head; b; b = b->next) {
                   3148: #ifdef ENABLE_NATT
                   3149:                        if (iph2->ph1->natt_flags & NAT_DETECTED) {
                   3150:                          int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
                   3151:                          plog (LLV_INFO, LOCATION, NULL,
                   3152:                                "NAT detected -> UDP encapsulation "
                   3153:                                "(ENC_MODE %d->%d).\n",
                   3154:                                b->encmode,
                   3155:                                b->encmode+udp_diff);
                   3156:                          /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
                   3157:                          b->encmode += udp_diff;
                   3158:                          b->udp_encap = 1;
                   3159:                        }
                   3160: #endif
                   3161: 
                   3162:                        q = setph2proposal0(iph2, a, b);
                   3163:                        if (q == NULL) {
                   3164:                                VPTRINIT(iph2->sa);
                   3165:                                return -1;
                   3166:                        }
                   3167: 
                   3168:                        iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
                   3169:                        if (iph2->sa == NULL) {
                   3170:                                plog(LLV_ERROR, LOCATION, NULL,
                   3171:                                        "failed to allocate my sa buffer\n");
                   3172:                                if (q)
                   3173:                                        vfree(q);
                   3174:                                return -1;
                   3175:                        }
                   3176:                        memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
                   3177:                        if (propoff != 0) {
                   3178:                                prop = (struct isakmp_pl_p *)(iph2->sa->v +
                   3179:                                        propoff);
                   3180:                                prop->h.np = ISAKMP_NPTYPE_P;
                   3181:                        }
                   3182:                        propoff = iph2->sa->l - q->l;
                   3183: 
                   3184:                        vfree(q);
                   3185:                }
                   3186:        }
                   3187: 
                   3188:        return 0;
                   3189: }
                   3190: 
                   3191: /*
                   3192:  * return 1 if all of the given protocols are transport mode.
                   3193:  */
                   3194: int
                   3195: ipsecdoi_transportmode(pp)
                   3196:        struct saprop *pp;
                   3197: {
                   3198:        struct saproto *pr = NULL;
                   3199: 
                   3200:        for (; pp; pp = pp->next) {
                   3201:                for (pr = pp->head; pr; pr = pr->next) {
                   3202:                        if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
                   3203:                            pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
                   3204:                            pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
                   3205:                                return 0;
                   3206:                }
                   3207:        }
                   3208: 
                   3209:        return 1;
                   3210: }
                   3211: 
                   3212: int
                   3213: ipsecdoi_get_defaultlifetime()
                   3214: {
                   3215:        return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
                   3216: }
                   3217: 
                   3218: int
                   3219: ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
                   3220:        int proto_id, enc, auth, comp;
                   3221: {
                   3222: #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
                   3223:        switch (proto_id) {
                   3224:        case IPSECDOI_PROTO_IPSEC_ESP:
                   3225:                if (enc == 0 || comp != 0) {
                   3226:                        plog(LLV_ERROR, LOCATION, NULL,
                   3227:                                "illegal algorithm defined "
                   3228:                                "ESP enc=%s auth=%s comp=%s.\n",
                   3229:                                TMPALGTYPE2STR(enc),
                   3230:                                TMPALGTYPE2STR(auth),
                   3231:                                TMPALGTYPE2STR(comp));
                   3232:                        return -1;
                   3233:                }
                   3234:                break;
                   3235:        case IPSECDOI_PROTO_IPSEC_AH:
                   3236:                if (enc != 0 || auth == 0 || comp != 0) {
                   3237:                        plog(LLV_ERROR, LOCATION, NULL,
                   3238:                                "illegal algorithm defined "
                   3239:                                "AH enc=%s auth=%s comp=%s.\n",
                   3240:                                TMPALGTYPE2STR(enc),
                   3241:                                TMPALGTYPE2STR(auth),
                   3242:                                TMPALGTYPE2STR(comp));
                   3243:                        return -1;
                   3244:                }
                   3245:                break;
                   3246:        case IPSECDOI_PROTO_IPCOMP:
                   3247:                if (enc != 0 || auth != 0 || comp == 0) {
                   3248:                        plog(LLV_ERROR, LOCATION, NULL,
                   3249:                                "illegal algorithm defined "
                   3250:                                "IPcomp enc=%s auth=%s comp=%s.\n",
                   3251:                                TMPALGTYPE2STR(enc),
                   3252:                                TMPALGTYPE2STR(auth),
                   3253:                                TMPALGTYPE2STR(comp));
                   3254:                        return -1;
                   3255:                }
                   3256:                break;
                   3257:        default:
                   3258:                plog(LLV_ERROR, LOCATION, NULL,
                   3259:                        "invalid ipsec protocol %d\n", proto_id);
                   3260:                return -1;
                   3261:        }
                   3262: #undef TMPALGTYPE2STR
                   3263:        return 0;
                   3264: }
                   3265: 
                   3266: int
                   3267: ipproto2doi(proto)
                   3268:        int proto;
                   3269: {
                   3270:        switch (proto) {
                   3271:        case IPPROTO_AH:
                   3272:                return IPSECDOI_PROTO_IPSEC_AH;
                   3273:        case IPPROTO_ESP:
                   3274:                return IPSECDOI_PROTO_IPSEC_ESP;
                   3275:        case IPPROTO_IPCOMP:
                   3276:                return IPSECDOI_PROTO_IPCOMP;
                   3277:        }
                   3278:        return -1;      /* XXX */
                   3279: }
                   3280: 
                   3281: int
                   3282: doi2ipproto(proto)
                   3283:        int proto;
                   3284: {
                   3285:        switch (proto) {
                   3286:        case IPSECDOI_PROTO_IPSEC_AH:
                   3287:                return IPPROTO_AH;
                   3288:        case IPSECDOI_PROTO_IPSEC_ESP:
                   3289:                return IPPROTO_ESP;
                   3290:        case IPSECDOI_PROTO_IPCOMP:
                   3291:                return IPPROTO_IPCOMP;
                   3292:        }
                   3293:        return -1;      /* XXX */
                   3294: }
                   3295: 
                   3296: /*
                   3297:  * Check if a subnet id is valid for comparison
                   3298:  * with an address id ( address length mask )
                   3299:  * and compare them
                   3300:  * Return value
                   3301:  * =  0 for match
                   3302:  * =  1 for mismatch
                   3303:  */
                   3304: 
                   3305: int
                   3306: ipsecdoi_subnetisaddr_v4( subnet, address )
                   3307:        const vchar_t *subnet;
                   3308:        const vchar_t *address;
                   3309: {
                   3310:        struct in_addr *mask;
                   3311: 
                   3312:        if (address->l != sizeof(struct in_addr))
                   3313:                return 1;
                   3314: 
                   3315:        if (subnet->l != (sizeof(struct in_addr)*2))
                   3316:                return 1;
                   3317: 
                   3318:        mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
                   3319: 
                   3320:        if (mask->s_addr!=0xffffffff)
                   3321:                return 1;
                   3322: 
                   3323:        return memcmp(subnet->v,address->v,address->l);
                   3324: }
                   3325: 
                   3326: #ifdef INET6
                   3327: 
                   3328: int
                   3329: ipsecdoi_subnetisaddr_v6( subnet, address )
                   3330:        const vchar_t *subnet;
                   3331:        const vchar_t *address;
                   3332: {
                   3333:        struct in6_addr *mask;
                   3334:        int i;
                   3335: 
                   3336:        if (address->l != sizeof(struct in6_addr))
                   3337:                return 1;
                   3338: 
                   3339:        if (subnet->l != (sizeof(struct in6_addr)*2))
                   3340:                return 1;
                   3341: 
                   3342:        mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
                   3343: 
                   3344:        for (i=0; i<16; i++)
                   3345:                if(mask->s6_addr[i]!=0xff)
                   3346:                        return 1;
                   3347: 
                   3348:        return memcmp(subnet->v,address->v,address->l);
                   3349: }
                   3350: 
                   3351: #endif
                   3352: 
                   3353: /*
                   3354:  * Check and Compare two IDs
                   3355:  * - specify 0 for exact if wildcards are allowed
                   3356:  * Return value
                   3357:  * =  0 for match
                   3358:  * =  1 for misatch
                   3359:  * = -1 for integrity error
                   3360:  */
                   3361: 
                   3362: int
                   3363: ipsecdoi_chkcmpids( idt, ids, exact )
                   3364:        const vchar_t *idt; /* id cmp target */
                   3365:        const vchar_t *ids; /* id cmp source */
                   3366:        int exact;
                   3367: {
                   3368:        struct ipsecdoi_id_b *id_bt;
                   3369:        struct ipsecdoi_id_b *id_bs;
                   3370:        vchar_t ident_t;
                   3371:        vchar_t ident_s;
                   3372:        int result;
                   3373: 
                   3374:        /* handle wildcard IDs */
                   3375: 
                   3376:        if (idt == NULL || ids == NULL)
                   3377:        {
                   3378:                if( !exact )
                   3379:                {
                   3380:                        plog(LLV_DEBUG, LOCATION, NULL,
                   3381:                                "check and compare ids : values matched (ANONYMOUS)\n" );
                   3382:                        return 0;
                   3383:                }
                   3384:                else
                   3385:                {
                   3386:                        plog(LLV_DEBUG, LOCATION, NULL,
                   3387:                                "check and compare ids : value mismatch (ANONYMOUS)\n" );
                   3388:                        return -1;
                   3389:                }
                   3390:        }
                   3391: 
                   3392:        /* make sure the ids are of the same type */
                   3393: 
                   3394:        id_bt = (struct ipsecdoi_id_b *) idt->v;
                   3395:        id_bs = (struct ipsecdoi_id_b *) ids->v;
                   3396: 
                   3397:        ident_t.v = idt->v + sizeof(*id_bt);
                   3398:        ident_t.l = idt->l - sizeof(*id_bt);
                   3399:        ident_s.v = ids->v + sizeof(*id_bs);
                   3400:        ident_s.l = ids->l - sizeof(*id_bs);
                   3401: 
                   3402:        if (id_bs->type != id_bt->type)
                   3403:        {
                   3404:                /*
                   3405:                 * special exception for comparing
                   3406:                  * address to subnet id types when
                   3407:                  * the netmask is address length
                   3408:                  */
                   3409: 
                   3410:                if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
                   3411:                    (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
                   3412:                        result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
                   3413:                        goto cmpid_result;
                   3414:                }
                   3415: 
                   3416:                if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
                   3417:                    (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
                   3418:                        result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
                   3419:                        goto cmpid_result;
                   3420:                }
                   3421: 
                   3422: #ifdef INET6
                   3423:                if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
                   3424:                    (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
                   3425:                        result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
                   3426:                        goto cmpid_result;
                   3427:                }
                   3428: 
                   3429:                if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
                   3430:                    (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
                   3431:                        result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
                   3432:                        goto cmpid_result;
                   3433:                }
                   3434: #endif
                   3435:                plog(LLV_DEBUG, LOCATION, NULL,
                   3436:                        "check and compare ids : id type mismatch %s != %s\n",
                   3437:                        s_ipsecdoi_ident(id_bs->type),
                   3438:                        s_ipsecdoi_ident(id_bt->type));
                   3439: 
                   3440:                return 1;
                   3441:        }
                   3442: 
                   3443:        if(id_bs->proto_id != id_bt->proto_id){
                   3444:                plog(LLV_DEBUG, LOCATION, NULL,
                   3445:                        "check and compare ids : proto_id mismatch %d != %d\n",
                   3446:                        id_bs->proto_id, id_bt->proto_id);
                   3447: 
                   3448:                return 1;
                   3449:        }
                   3450: 
                   3451:        /* compare the ID data. */
                   3452: 
                   3453:        switch (id_bt->type) {
                   3454:                case IPSECDOI_ID_DER_ASN1_DN:
                   3455:                case IPSECDOI_ID_DER_ASN1_GN:
                   3456:                        /* compare asn1 ids */
                   3457:                        result = eay_cmp_asn1dn(&ident_t, &ident_s);
                   3458:                        goto cmpid_result;
                   3459: 
                   3460:                case IPSECDOI_ID_IPV4_ADDR:
                   3461:                        /* validate lengths */
                   3462:                        if ((ident_t.l != sizeof(struct in_addr))||
                   3463:                            (ident_s.l != sizeof(struct in_addr)))
                   3464:                                goto cmpid_invalid;
                   3465:                        break;
                   3466: 
                   3467:                case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   3468:                case IPSECDOI_ID_IPV4_ADDR_RANGE:
                   3469:                        /* validate lengths */
                   3470:                        if ((ident_t.l != (sizeof(struct in_addr)*2))||
                   3471:                            (ident_s.l != (sizeof(struct in_addr)*2)))
                   3472:                                goto cmpid_invalid;
                   3473:                        break;
                   3474: 
                   3475: #ifdef INET6
                   3476:                case IPSECDOI_ID_IPV6_ADDR:
                   3477:                        /* validate lengths */
                   3478:                        if ((ident_t.l != sizeof(struct in6_addr))||
                   3479:                            (ident_s.l != sizeof(struct in6_addr)))
                   3480:                                goto cmpid_invalid;
                   3481:                        break;
                   3482: 
                   3483:                case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   3484:                case IPSECDOI_ID_IPV6_ADDR_RANGE:
                   3485:                        /* validate lengths */
                   3486:                        if ((ident_t.l != (sizeof(struct in6_addr)*2))||
                   3487:                            (ident_s.l != (sizeof(struct in6_addr)*2)))
                   3488:                                goto cmpid_invalid;
                   3489:                        break;
                   3490: #endif
                   3491:                case IPSECDOI_ID_FQDN:
                   3492:                case IPSECDOI_ID_USER_FQDN:
                   3493:                case IPSECDOI_ID_KEY_ID:
                   3494:                        break;
                   3495: 
                   3496:                default:
                   3497:                        plog(LLV_ERROR, LOCATION, NULL,
                   3498:                                "Unhandled id type %i specified for comparison\n",
                   3499:                                id_bt->type);
                   3500:                        return -1;
                   3501:        }
                   3502: 
                   3503:        /* validate matching data and length */
                   3504:        if (ident_t.l == ident_s.l)
                   3505:                result = memcmp(ident_t.v,ident_s.v,ident_t.l);
                   3506:        else
                   3507:                result = 1;
                   3508: 
                   3509: cmpid_result:
                   3510: 
                   3511:        /* debug level output */
                   3512:        if(loglevel >= LLV_DEBUG) {
                   3513:                char *idstrt = ipsecdoi_id2str(idt);
                   3514:                char *idstrs = ipsecdoi_id2str(ids);
                   3515: 
                   3516:                if (!result)
                   3517:                        plog(LLV_DEBUG, LOCATION, NULL,
                   3518:                                "check and compare ids : values matched (%s)\n",
                   3519:                                 s_ipsecdoi_ident(id_bs->type) );
                   3520:                else
                   3521:                        plog(LLV_DEBUG, LOCATION, NULL,
                   3522:                                "check and compare ids : value mismatch (%s)\n",
                   3523:                                 s_ipsecdoi_ident(id_bs->type));
                   3524: 
                   3525:                plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
                   3526:                plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
                   3527: 
                   3528:                racoon_free(idstrs);
                   3529:                racoon_free(idstrt);
                   3530:        }
                   3531: 
                   3532:        /* return result */
                   3533:        if( !result )
                   3534:                return 0;
                   3535:        else
                   3536:                return 1;
                   3537: 
                   3538: cmpid_invalid:
                   3539: 
                   3540:        /* id integrity error */
                   3541:        plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
                   3542:                s_ipsecdoi_ident(id_bs->type));
                   3543:        plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
                   3544:        plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
                   3545: 
                   3546:        return -1;
                   3547: }
                   3548: 
                   3549: /*
                   3550:  * check the following:
                   3551:  * - In main mode with pre-shared key, only address type can be used.
                   3552:  * - if proper type for phase 1 ?
                   3553:  * - if phase 1 ID payload conformed RFC2407 4.6.2.
                   3554:  *   (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
                   3555:  * - if ID payload sent from peer is equal to the ID expected by me.
                   3556:  *
                   3557:  * both of "id" and "id_p" should be ID payload without general header,
                   3558:  */
                   3559: int
                   3560: ipsecdoi_checkid1(iph1)
                   3561:        struct ph1handle *iph1;
                   3562: {
                   3563:        struct ipsecdoi_id_b *id_b;
                   3564: 
                   3565:        if (iph1->id_p == NULL) {
                   3566:                plog(LLV_ERROR, LOCATION, NULL,
                   3567:                        "invalid iph1 passed id_p == NULL\n");
                   3568:                return ISAKMP_INTERNAL_ERROR;
                   3569:        }
                   3570:        if (iph1->id_p->l < sizeof(*id_b)) {
                   3571:                plog(LLV_ERROR, LOCATION, NULL,
                   3572:                        "invalid value passed as \"ident\" (len=%lu)\n",
                   3573:                        (u_long)iph1->id_p->l);
                   3574:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
                   3575:        }
                   3576: 
                   3577:        id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
                   3578: 
                   3579:        /* In main mode with pre-shared key, only address type can be used. */
                   3580:        if (iph1->etype == ISAKMP_ETYPE_IDENT &&
                   3581:            iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
                   3582:                 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
                   3583:                  && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
                   3584:                        plog(LLV_ERROR, LOCATION, NULL,
                   3585:                                "Expecting IP address type in main mode, "
                   3586:                                "but %s.\n", s_ipsecdoi_ident(id_b->type));
                   3587:                        return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
                   3588:                }
                   3589:        }
                   3590: 
                   3591:        /* if proper type for phase 1 ? */
                   3592:        switch (id_b->type) {
                   3593:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   3594:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   3595:        case IPSECDOI_ID_IPV4_ADDR_RANGE:
                   3596:        case IPSECDOI_ID_IPV6_ADDR_RANGE:
                   3597:                plog(LLV_WARNING, LOCATION, NULL,
                   3598:                        "such ID type %s is not proper.\n",
                   3599:                        s_ipsecdoi_ident(id_b->type));
                   3600:                /*FALLTHROUGH*/
                   3601:        }
                   3602: 
                   3603:        /* if phase 1 ID payload conformed RFC2407 4.6.2. */
                   3604:        if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
                   3605:            id_b->type == IPSECDOI_ID_IPV6_ADDR) {
                   3606: 
                   3607:                if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
                   3608:                        plog(LLV_WARNING, LOCATION, NULL,
                   3609:                                "protocol ID and Port mismatched. "
                   3610:                                "proto_id:%d port:%d\n",
                   3611:                                id_b->proto_id, ntohs(id_b->port));
                   3612:                        /*FALLTHROUGH*/
                   3613: 
                   3614:                } else if (id_b->proto_id == IPPROTO_UDP) {
                   3615:                        /*
                   3616:                         * copmaring with expecting port.
                   3617:                         * always permit if port is equal to PORT_ISAKMP
                   3618:                         */
                   3619:                        if (ntohs(id_b->port) != PORT_ISAKMP) {
                   3620:                                u_int16_t port;
                   3621: 
                   3622:                                port = extract_port(iph1->remote);
                   3623:                                if (ntohs(id_b->port) != port) {
                   3624:                                        plog(LLV_WARNING, LOCATION, NULL,
                   3625:                                                "port %d expected, but %d\n",
                   3626:                                                port, ntohs(id_b->port));
                   3627:                                        /*FALLTHROUGH*/
                   3628:                                }
                   3629:                        }
                   3630:                }
                   3631:        }
                   3632: 
                   3633:        /* resolve remote configuration if not done yet */
                   3634:        if (resolveph1rmconf(iph1) < 0)
                   3635:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
                   3636: 
                   3637:        if (iph1->rmconf == NULL)
                   3638:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
                   3639: 
                   3640:        return 0;
                   3641: }
                   3642: 
                   3643: /*
                   3644:  * create ID payload for phase 1 and set into iph1->id.
                   3645:  * NOT INCLUDING isakmp general header.
                   3646:  * see, RFC2407 4.6.2.1
                   3647:  */
                   3648: int
                   3649: ipsecdoi_setid1(iph1)
                   3650:        struct ph1handle *iph1;
                   3651: {
                   3652:        vchar_t *ret = NULL;
                   3653:        struct ipsecdoi_id_b id_b;
                   3654:        vchar_t *ident = NULL;
                   3655:        struct sockaddr *ipid = NULL;
                   3656: 
                   3657:        /* init */
                   3658:        id_b.proto_id = 0;
                   3659:        id_b.port = 0;
                   3660:        ident = NULL;
                   3661: 
                   3662:        switch (iph1->rmconf->idvtype) {
                   3663:        case IDTYPE_FQDN:
                   3664:                id_b.type = IPSECDOI_ID_FQDN;
                   3665:                ident = vdup(iph1->rmconf->idv);
                   3666:                break;
                   3667:        case IDTYPE_USERFQDN:
                   3668:                id_b.type = IPSECDOI_ID_USER_FQDN;
                   3669:                ident = vdup(iph1->rmconf->idv);
                   3670:                break;
                   3671:        case IDTYPE_KEYID:
                   3672:                id_b.type = IPSECDOI_ID_KEY_ID;
                   3673:                ident = vdup(iph1->rmconf->idv);
                   3674:                break;
                   3675:        case IDTYPE_ASN1DN:
                   3676:                id_b.type = IPSECDOI_ID_DER_ASN1_DN;
                   3677:                if (iph1->rmconf->idv) {
                   3678:                        /* XXX it must be encoded to asn1dn. */
                   3679:                        ident = vdup(iph1->rmconf->idv);
                   3680:                } else {
                   3681:                        if (oakley_getmycert(iph1) < 0) {
                   3682:                                plog(LLV_ERROR, LOCATION, NULL,
                   3683:                                        "failed to get own CERT.\n");
                   3684:                                goto err;
                   3685:                        }
                   3686:                        ident = eay_get_x509asn1subjectname(iph1->cert);
                   3687:                }
                   3688:                break;
                   3689:        case IDTYPE_ADDRESS:
                   3690:                /*
                   3691:                 * if the value of the id type was set by the configuration
                   3692:                 * file, then use it.  otherwise the value is get from local
                   3693:                 * ip address by using ike negotiation.
                   3694:                 */
                   3695:                if (iph1->rmconf->idv)
                   3696:                        ipid = (struct sockaddr *)iph1->rmconf->idv->v;
                   3697:                /*FALLTHROUGH*/
                   3698:        default:
                   3699:            {
                   3700:                int l;
                   3701:                caddr_t p;
                   3702: 
                   3703:                if (ipid == NULL)
                   3704:                        ipid = iph1->local;
                   3705: 
                   3706:                /* use IP address */
                   3707:                switch (ipid->sa_family) {
                   3708:                case AF_INET:
                   3709:                        id_b.type = IPSECDOI_ID_IPV4_ADDR;
                   3710:                        l = sizeof(struct in_addr);
                   3711:                        p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
                   3712:                        break;
                   3713: #ifdef INET6
                   3714:                case AF_INET6:
                   3715:                        id_b.type = IPSECDOI_ID_IPV6_ADDR;
                   3716:                        l = sizeof(struct in6_addr);
                   3717:                        p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
                   3718:                        break;
                   3719: #endif
                   3720:                default:
                   3721:                        plog(LLV_ERROR, LOCATION, NULL,
                   3722:                                "invalid address family.\n");
                   3723:                        goto err;
                   3724:                }
                   3725:                id_b.proto_id = IPPROTO_UDP;
                   3726:                id_b.port = htons(PORT_ISAKMP);
                   3727:                ident = vmalloc(l);
                   3728:                if (!ident) {
                   3729:                        plog(LLV_ERROR, LOCATION, NULL,
                   3730:                                "failed to get ID buffer.\n");
                   3731:                        return -1;
                   3732:                }
                   3733:                memcpy(ident->v, p, ident->l);
                   3734:            }
                   3735:        }
                   3736:        if (!ident) {
                   3737:                plog(LLV_ERROR, LOCATION, NULL,
                   3738:                        "failed to get ID buffer.\n");
                   3739:                return -1;
                   3740:        }
                   3741: 
                   3742:        ret = vmalloc(sizeof(id_b) + ident->l);
                   3743:        if (ret == NULL) {
                   3744:                plog(LLV_ERROR, LOCATION, NULL,
                   3745:                        "failed to get ID buffer.\n");
                   3746:                goto err;
                   3747:        }
                   3748: 
                   3749:        memcpy(ret->v, &id_b, sizeof(id_b));
                   3750:        memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
                   3751: 
                   3752:        iph1->id = ret;
                   3753: 
                   3754:        plog(LLV_DEBUG, LOCATION, NULL,
                   3755:                "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
                   3756:        if (ident)
                   3757:                vfree(ident);
                   3758:        return 0;
                   3759: 
                   3760: err:
                   3761:        if (ident)
                   3762:                vfree(ident);
                   3763:        plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
                   3764:        return -1;
                   3765: }
                   3766: 
                   3767: /* it's only called by cfparse.y. */
                   3768: int
                   3769: set_identifier(vpp, type, value)
                   3770:        vchar_t **vpp, *value;
                   3771:        int type;
                   3772: {
                   3773:        return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
                   3774: }
                   3775: 
                   3776: int
                   3777: set_identifier_qual(vpp, type, value, qual)
                   3778:        vchar_t **vpp, *value;
                   3779:        int type;
                   3780:        int qual;
                   3781: {
                   3782:        vchar_t *new = NULL;
                   3783: 
                   3784:        /* simply return if value is null. */
                   3785:        if (!value){
                   3786:                if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
                   3787:                        plog(LLV_ERROR, LOCATION, NULL,
                   3788:                                 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
                   3789:                        return -1;
                   3790:                }
                   3791:                return 0;
                   3792:        }
                   3793: 
                   3794:        switch (type) {
                   3795:        case IDTYPE_FQDN:
                   3796:        case IDTYPE_USERFQDN:
                   3797:                if(value->l <= 1){
                   3798:                        plog(LLV_ERROR, LOCATION, NULL,
                   3799:                                 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
                   3800:                        return -1;
                   3801:                }
                   3802:                /* length is adjusted since QUOTEDSTRING teminates NULL. */
                   3803:                new = vmalloc(value->l - 1);
                   3804:                if (new == NULL)
                   3805:                        return -1;
                   3806:                memcpy(new->v, value->v, new->l);
                   3807:                break;
                   3808:        case IDTYPE_KEYID:
                   3809:                /*
                   3810:                 * If no qualifier is specified: IDQUAL_UNSPEC. It means
                   3811:                 * to use a file for backward compatibility sake.
                   3812:                 */
                   3813:                switch(qual) {
                   3814:                case IDQUAL_FILE:
                   3815:                case IDQUAL_UNSPEC: {
                   3816:                        FILE *fp;
                   3817:                        char b[512];
                   3818:                        int tlen, len;
                   3819: 
                   3820:                        fp = fopen(value->v, "r");
                   3821:                        if (fp == NULL) {
                   3822:                                plog(LLV_ERROR, LOCATION, NULL,
                   3823:                                        "can not open %s\n", value->v);
                   3824:                                return -1;
                   3825:                        }
                   3826:                        tlen = 0;
                   3827:                        while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
                   3828:                                new = vrealloc(new, tlen + len);
                   3829:                                if (!new) {
                   3830:                                        fclose(fp);
                   3831:                                        return -1;
                   3832:                                }
                   3833:                                memcpy(new->v + tlen, b, len);
                   3834:                                tlen += len;
                   3835:                        }
                   3836:                        fclose(fp);
                   3837:                        break;
                   3838:                }
                   3839: 
                   3840:                case IDQUAL_TAG:
                   3841:                        new = vmalloc(value->l - 1);
                   3842:                        if (new == NULL) {
                   3843:                                plog(LLV_ERROR, LOCATION, NULL,
                   3844:                                        "can not allocate memory");
                   3845:                                return -1;
                   3846:                        }
                   3847:                        memcpy(new->v, value->v, new->l);
                   3848:                        break;
                   3849: 
                   3850:                default:
                   3851:                        plog(LLV_ERROR, LOCATION, NULL,
                   3852:                                "unknown qualifier");
                   3853:                        return -1;
                   3854:                }
                   3855:                break;
                   3856: 
                   3857:        case IDTYPE_ADDRESS: {
                   3858:                struct sockaddr *sa;
                   3859: 
                   3860:                /* length is adjusted since QUOTEDSTRING teminates NULL. */
                   3861:                if (value->l == 0)
                   3862:                        break;
                   3863: 
                   3864:                sa = str2saddr(value->v, NULL);
                   3865:                if (sa == NULL) {
                   3866:                        plog(LLV_ERROR, LOCATION, NULL,
                   3867:                                "invalid ip address %s\n", value->v);
                   3868:                        return -1;
                   3869:                }
                   3870: 
                   3871:                new = vmalloc(sysdep_sa_len(sa));
                   3872:                if (new == NULL) {
                   3873:                        racoon_free(sa);
                   3874:                        return -1;
                   3875:                }
                   3876:                memcpy(new->v, sa, new->l);
                   3877:                racoon_free(sa);
                   3878:                break;
                   3879:        }
                   3880:        case IDTYPE_ASN1DN:
                   3881:                if (value->v[0] == '~')
                   3882:                        /* Hex-encoded ASN1 strings */
                   3883:                        new = eay_hex2asn1dn(value->v + 1, - 1);
                   3884:                else
                   3885:                        /* DN encoded strings */
                   3886:                        new = eay_str2asn1dn(value->v, value->l - 1);
                   3887: 
                   3888:                if (new == NULL)
                   3889:                        return -1;
                   3890: 
                   3891:                if (loglevel >= LLV_DEBUG) {
                   3892:                        X509_NAME *xn;
                   3893:                        BIO *bio;
                   3894:                        unsigned char *ptr = (unsigned char *) new->v, *buf;
                   3895:                        size_t len;
                   3896:                        char save;
                   3897: 
                   3898:                        xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
                   3899:                        bio = BIO_new(BIO_s_mem());
                   3900: 
                   3901:                        X509_NAME_print_ex(bio, xn, 0, 0);
                   3902:                        len = BIO_get_mem_data(bio, &ptr);
                   3903:                        save = ptr[len];
                   3904:                        ptr[len] = 0;
                   3905:                        plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
                   3906:                        ptr[len] = save;
                   3907:                        X509_NAME_free(xn);
                   3908:                        BIO_free(bio);
                   3909:                }
                   3910: 
                   3911:                break;
                   3912:        }
                   3913: 
                   3914:        *vpp = new;
                   3915: 
                   3916:        return 0;
                   3917: }
                   3918: 
                   3919: /*
                   3920:  * create ID payload for phase 2, and set into iph2->id and id_p.  There are
                   3921:  * NOT INCLUDING isakmp general header.
                   3922:  * this function is for initiator.  responder will get to copy from payload.
                   3923:  * responder ID type is always address type.
                   3924:  * see, RFC2407 4.6.2.1
                   3925:  */
                   3926: int
                   3927: ipsecdoi_setid2(iph2)
                   3928:        struct ph2handle *iph2;
                   3929: {
                   3930:        struct secpolicy *sp;
                   3931: 
                   3932:        /* check there is phase 2 handler ? */
                   3933:        sp = getspbyspid(iph2->spid);
                   3934:        if (sp == NULL) {
                   3935:                plog(LLV_ERROR, LOCATION, NULL,
                   3936:                        "no policy found for spid:%u.\n", iph2->spid);
                   3937:                return -1;
                   3938:        }
                   3939: 
                   3940:        if (!ipsecdoi_transportmode(iph2->proposal))
                   3941:                iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
                   3942:                                sp->spidx.prefs, sp->spidx.ul_proto);
                   3943:        else if (iph2->sa_src != NULL) {
                   3944:                /* He have a specific hint indicating that the transport
                   3945:                 * mode SA will be negotiated using addresses that differ
                   3946:                 * with the one from the SA. We need to indicate that to
                   3947:                 * our peer by setting the SA address as ID.
                   3948:                 * This is typically the case for the bootstrapping of the
                   3949:                 * transport mode SA protecting BU/BA for MIPv6 traffic
                   3950:                 *
                   3951:                 * --arno*/
                   3952:                iph2->id = ipsecdoi_sockaddr2id(iph2->sa_src,
                   3953:                                                IPSECDOI_PREFIX_HOST,
                   3954:                                                sp->spidx.ul_proto);
                   3955:        } else
                   3956:                iph2->id = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
                   3957:                                                sp->spidx.ul_proto);
                   3958: 
                   3959:        if (iph2->id == NULL) {
                   3960:                plog(LLV_ERROR, LOCATION, NULL,
                   3961:                        "failed to get ID for %s\n",
                   3962:                        spidx2str(&sp->spidx));
                   3963:                return -1;
                   3964:        }
                   3965:        plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
                   3966:                s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
                   3967: 
                   3968:        /* remote side */
                   3969:        if (!ipsecdoi_transportmode(iph2->proposal))
                   3970:                iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
                   3971:                                sp->spidx.prefd, sp->spidx.ul_proto);
                   3972:        else if (iph2->sa_dst != NULL) {
                   3973:                /* See comment above for local side. */
                   3974:                iph2->id_p = ipsecdoi_sockaddr2id(iph2->sa_dst,
                   3975:                                                  IPSECDOI_PREFIX_HOST,
                   3976:                                                  sp->spidx.ul_proto);
                   3977:        } else
                   3978:                iph2->id_p = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
                   3979:                        sp->spidx.ul_proto);
                   3980: 
                   3981:        if (iph2->id_p == NULL) {
                   3982:                plog(LLV_ERROR, LOCATION, NULL,
                   3983:                        "failed to get ID for %s\n",
                   3984:                        spidx2str(&sp->spidx));
                   3985:                VPTRINIT(iph2->id);
                   3986:                return -1;
                   3987:        }
                   3988:        plog(LLV_DEBUG, LOCATION, NULL,
                   3989:                "use remote ID type %s\n",
                   3990:                s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
                   3991: 
                   3992:        return 0;
                   3993: }
                   3994: 
                   3995: /*
                   3996:  * set address type of ID.
                   3997:  * NOT INCLUDING general header.
                   3998:  */
                   3999: vchar_t *
                   4000: ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
                   4001:        struct sockaddr *saddr;
                   4002:        u_int prefixlen;
                   4003:        u_int ul_proto;
                   4004: {
                   4005:        vchar_t *new;
                   4006:        int type, len1, len2;
                   4007:        caddr_t sa;
                   4008:        u_short port;
                   4009: 
                   4010:        /*
                   4011:         * Q. When type is SUBNET, is it allowed to be ::1/128.
                   4012:         * A. Yes. (consensus at bake-off)
                   4013:         */
                   4014:        switch (saddr->sa_family) {
                   4015:        case AF_INET:
                   4016:                len1 = sizeof(struct in_addr);
                   4017:                if (prefixlen >= (sizeof(struct in_addr) << 3)) {
                   4018:                        type = IPSECDOI_ID_IPV4_ADDR;
                   4019:                        len2 = 0;
                   4020:                } else {
                   4021:                        type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
                   4022:                        len2 = sizeof(struct in_addr);
                   4023:                }
                   4024:                sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
                   4025:                port = ((struct sockaddr_in *)(saddr))->sin_port;
                   4026:                break;
                   4027: #ifdef INET6
                   4028:        case AF_INET6:
                   4029:                len1 = sizeof(struct in6_addr);
                   4030:                if (prefixlen >= (sizeof(struct in6_addr) << 3)) {
                   4031:                        type = IPSECDOI_ID_IPV6_ADDR;
                   4032:                        len2 = 0;
                   4033:                } else {
                   4034:                        type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
                   4035:                        len2 = sizeof(struct in6_addr);
                   4036:                }
                   4037:                sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
                   4038:                port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
                   4039:                break;
                   4040: #endif
                   4041:        default:
                   4042:                plog(LLV_ERROR, LOCATION, NULL,
                   4043:                        "invalid family: %d.\n", saddr->sa_family);
                   4044:                return NULL;
                   4045:        }
                   4046: 
                   4047:        /* get ID buffer */
                   4048:        new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
                   4049:        if (new == NULL) {
                   4050:                plog(LLV_ERROR, LOCATION, NULL,
                   4051:                        "failed to get ID buffer.\n");
                   4052:                return NULL;
                   4053:        }
                   4054: 
                   4055:        memset(new->v, 0, new->l);
                   4056: 
                   4057:        /* set the part of header. */
                   4058:        ((struct ipsecdoi_id_b *)new->v)->type = type;
                   4059: 
                   4060:        /* set ul_proto and port */
                   4061:        /*
                   4062:         * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
                   4063:         * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
                   4064:         */
                   4065:        ((struct ipsecdoi_id_b *)new->v)->proto_id =
                   4066:                ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
                   4067:        ((struct ipsecdoi_id_b *)new->v)->port =
                   4068:                port == IPSEC_PORT_ANY ? 0 : port;
                   4069:        memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
                   4070: 
                   4071:        /* set address */
                   4072: 
                   4073:        /* set prefix */
                   4074:        if (len2) {
                   4075:                u_char *p = (unsigned char *) new->v +
                   4076:                        sizeof(struct ipsecdoi_id_b) + len1;
                   4077:                u_int bits = prefixlen;
                   4078: 
                   4079:                while (bits >= 8) {
                   4080:                        *p++ = 0xff;
                   4081:                        bits -= 8;
                   4082:                }
                   4083: 
                   4084:                if (bits > 0)
                   4085:                        *p = ~((1 << (8 - bits)) - 1);
                   4086:        }
                   4087: 
                   4088:        return new;
                   4089: }
                   4090: 
                   4091: vchar_t *
                   4092: ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
                   4093:        struct sockaddr *laddr, *haddr;
                   4094:        u_int ul_proto;
                   4095: {
                   4096:        vchar_t *new;
                   4097:        int type, len1, len2;
                   4098:        u_short port;
                   4099: 
                   4100:        if (laddr->sa_family != haddr->sa_family) {
                   4101:            plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
                   4102:            return NULL;
                   4103:        }
                   4104: 
                   4105:        switch (laddr->sa_family) {
                   4106:        case AF_INET:
                   4107:            type = IPSECDOI_ID_IPV4_ADDR_RANGE;
                   4108:            len1 = sizeof(struct in_addr);
                   4109:            len2 = sizeof(struct in_addr);
                   4110:            break;
                   4111: #ifdef INET6
                   4112:        case AF_INET6:
                   4113:                type = IPSECDOI_ID_IPV6_ADDR_RANGE;
                   4114:                len1 = sizeof(struct in6_addr);
                   4115:                len2 = sizeof(struct in6_addr);
                   4116:                break;
                   4117: #endif
                   4118:        default:
                   4119:                plog(LLV_ERROR, LOCATION, NULL,
                   4120:                        "invalid family: %d.\n", laddr->sa_family);
                   4121:                return NULL;
                   4122:        }
                   4123: 
                   4124:        /* get ID buffer */
                   4125:        new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
                   4126:        if (new == NULL) {
                   4127:                plog(LLV_ERROR, LOCATION, NULL,
                   4128:                        "failed to get ID buffer.\n");
                   4129:                return NULL;
                   4130:        }
                   4131: 
                   4132:        memset(new->v, 0, new->l);
                   4133:        /* set the part of header. */
                   4134:        ((struct ipsecdoi_id_b *)new->v)->type = type;
                   4135: 
                   4136:        /* set ul_proto and port */
                   4137:        /*
                   4138:         * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
                   4139:         * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
                   4140:         */
                   4141:        ((struct ipsecdoi_id_b *)new->v)->proto_id =
                   4142:                ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
                   4143:        port = ((struct sockaddr_in *)(laddr))->sin_port;
                   4144:        ((struct ipsecdoi_id_b *)new->v)->port =
                   4145:                port == IPSEC_PORT_ANY ? 0 : port;
                   4146:        memcpy(new->v + sizeof(struct ipsecdoi_id_b),
                   4147:               (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
                   4148:               len1);
                   4149:        memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
                   4150:               (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
                   4151:               len2);
                   4152:        return new;
                   4153: }
                   4154: 
                   4155: 
                   4156: /*
                   4157:  * create sockaddr structure from ID payload (buf).
                   4158:  * buffers (saddr, prefixlen, ul_proto) must be allocated.
                   4159:  * see, RFC2407 4.6.2.1
                   4160:  */
                   4161: int
                   4162: ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
                   4163:        vchar_t *buf;
                   4164:        struct sockaddr *saddr;
                   4165:        u_int8_t *prefixlen;
                   4166:        u_int16_t *ul_proto;
                   4167: {
                   4168:        struct ipsecdoi_id_b *id_b = NULL;
                   4169:        u_int plen = 0;
                   4170: 
                   4171:        if (buf == NULL)
                   4172:                return ISAKMP_INTERNAL_ERROR;
                   4173: 
                   4174:        id_b = (struct ipsecdoi_id_b *)buf->v;
                   4175: 
                   4176:        /*
                   4177:         * When a ID payload of subnet type with a IP address of full bit
                   4178:         * masked, it has to be processed as host address.
                   4179:         * e.g. below 2 type are same.
                   4180:         *      type = ipv6 subnet, data = 2001::1/128
                   4181:         *      type = ipv6 address, data = 2001::1
                   4182:         */
                   4183:        switch (id_b->type) {
                   4184:        case IPSECDOI_ID_IPV4_ADDR:
                   4185:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4186: #ifndef __linux__
                   4187:                saddr->sa_len = sizeof(struct sockaddr_in);
                   4188: #endif
                   4189:                saddr->sa_family = AF_INET;
                   4190:                ((struct sockaddr_in *)saddr)->sin_port =
                   4191:                        (id_b->port == 0
                   4192:                                ? IPSEC_PORT_ANY
                   4193:                                : id_b->port);          /* see sockaddr2id() */
                   4194:                memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
                   4195:                        buf->v + sizeof(*id_b), sizeof(struct in_addr));
                   4196:                break;
                   4197: #ifdef INET6
                   4198:        case IPSECDOI_ID_IPV6_ADDR:
                   4199:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4200: #ifndef __linux__
                   4201:                saddr->sa_len = sizeof(struct sockaddr_in6);
                   4202: #endif
                   4203:                saddr->sa_family = AF_INET6;
                   4204:                ((struct sockaddr_in6 *)saddr)->sin6_port =
                   4205:                        (id_b->port == 0
                   4206:                                ? IPSEC_PORT_ANY
                   4207:                                : id_b->port);          /* see sockaddr2id() */
                   4208:                memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
                   4209:                        buf->v + sizeof(*id_b), sizeof(struct in6_addr));
                   4210:                ((struct sockaddr_in6 *)saddr)->sin6_scope_id =
                   4211:                        (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)saddr)->sin6_addr)
                   4212:                                ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
                   4213:                                : 0);
                   4214: 
                   4215:                break;
                   4216: #endif
                   4217:        default:
                   4218:                plog(LLV_ERROR, LOCATION, NULL,
                   4219:                        "unsupported ID type %d\n", id_b->type);
                   4220:                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
                   4221:        }
                   4222: 
                   4223:        /* get prefix length */
                   4224:        switch (id_b->type) {
                   4225:        case IPSECDOI_ID_IPV4_ADDR:
                   4226:                plen = sizeof(struct in_addr) << 3;
                   4227:                break;
                   4228: #ifdef INET6
                   4229:        case IPSECDOI_ID_IPV6_ADDR:
                   4230:                plen = sizeof(struct in6_addr) << 3;
                   4231:                break;
                   4232: #endif
                   4233:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4234: #ifdef INET6
                   4235:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4236: #endif
                   4237:            {
                   4238:                u_char *p;
                   4239:                u_int max;
                   4240:                int alen = sizeof(struct in_addr);
                   4241: 
                   4242:                switch (id_b->type) {
                   4243:                case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4244:                        alen = sizeof(struct in_addr);
                   4245:                        break;
                   4246: #ifdef INET6
                   4247:                case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4248:                        alen = sizeof(struct in6_addr);
                   4249:                        break;
                   4250: #endif
                   4251:                }
                   4252: 
                   4253:                /* sanity check */
                   4254:                if (buf->l < alen)
                   4255:                        return ISAKMP_INTERNAL_ERROR;
                   4256: 
                   4257:                /* get subnet mask length */
                   4258:                plen = 0;
                   4259:                max = alen <<3;
                   4260: 
                   4261:                p = (unsigned char *) buf->v
                   4262:                        + sizeof(struct ipsecdoi_id_b)
                   4263:                        + alen;
                   4264: 
                   4265:                for (; *p == 0xff; p++) {
                   4266:                        plen += 8;
                   4267:                        if (plen >= max)
                   4268:                                break;
                   4269:                }
                   4270: 
                   4271:                if (plen < max) {
                   4272:                        u_int l = 0;
                   4273:                        u_char b = ~(*p);
                   4274: 
                   4275:                        while (b) {
                   4276:                                b >>= 1;
                   4277:                                l++;
                   4278:                        }
                   4279: 
                   4280:                        l = 8 - l;
                   4281:                        plen += l;
                   4282:                }
                   4283:            }
                   4284:                break;
                   4285:        }
                   4286: 
                   4287:        *prefixlen = plen;
                   4288:        *ul_proto = id_b->proto_id == 0
                   4289:                                ? IPSEC_ULPROTO_ANY
                   4290:                                : id_b->proto_id;       /* see sockaddr2id() */
                   4291: 
                   4292:        return 0;
                   4293: }
                   4294: 
                   4295: /*
                   4296:  * make printable string from ID payload except of general header.
                   4297:  */
                   4298: char *
                   4299: ipsecdoi_id2str(id)
                   4300:        const vchar_t *id;
                   4301: {
                   4302: #define BUFLEN 512
                   4303:        char * ret = NULL;
                   4304:        int len = 0;
                   4305:        char *dat;
                   4306:        static char buf[BUFLEN];
                   4307:        struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
                   4308:        union sockaddr_any saddr;
                   4309:        u_int plen = 0;
                   4310: 
                   4311:        switch (id_b->type) {
                   4312:        case IPSECDOI_ID_IPV4_ADDR:
                   4313:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4314:        case IPSECDOI_ID_IPV4_ADDR_RANGE:
                   4315: 
                   4316: #ifndef __linux__
                   4317:                saddr.sa.sa_len = sizeof(struct sockaddr_in);
                   4318: #endif
                   4319:                saddr.sa.sa_family = AF_INET;
                   4320:                saddr.sin.sin_port = IPSEC_PORT_ANY;
                   4321:                memcpy(&saddr.sin.sin_addr,
                   4322:                        id->v + sizeof(*id_b), sizeof(struct in_addr));
                   4323:                break;
                   4324: #ifdef INET6
                   4325:        case IPSECDOI_ID_IPV6_ADDR:
                   4326:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4327:        case IPSECDOI_ID_IPV6_ADDR_RANGE:
                   4328: 
                   4329: #ifndef __linux__
                   4330:                saddr.sa.sa_len = sizeof(struct sockaddr_in6);
                   4331: #endif
                   4332:                saddr.sa.sa_family = AF_INET6;
                   4333:                saddr.sin6.sin6_port = IPSEC_PORT_ANY;
                   4334:                memcpy(&saddr.sin6.sin6_addr,
                   4335:                        id->v + sizeof(*id_b), sizeof(struct in6_addr));
                   4336:                saddr.sin6.sin6_scope_id =
                   4337:                        (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
                   4338:                                ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
                   4339:                                : 0);
                   4340:                break;
                   4341: #endif
                   4342:        }
                   4343: 
                   4344:        switch (id_b->type) {
                   4345:        case IPSECDOI_ID_IPV4_ADDR:
                   4346: #ifdef INET6
                   4347:        case IPSECDOI_ID_IPV6_ADDR:
                   4348: #endif
                   4349:                len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
                   4350:                break;
                   4351: 
                   4352:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4353: #ifdef INET6
                   4354:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4355: #endif
                   4356:            {
                   4357:                u_char *p;
                   4358:                u_int max;
                   4359:                int alen = sizeof(struct in_addr);
                   4360: 
                   4361:                switch (id_b->type) {
                   4362:                case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4363:                        alen = sizeof(struct in_addr);
                   4364:                        break;
                   4365: #ifdef INET6
                   4366:                case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4367:                        alen = sizeof(struct in6_addr);
                   4368:                        break;
                   4369: #endif
                   4370:                }
                   4371: 
                   4372:                /* sanity check */
                   4373:                if (id->l < alen) {
                   4374:                        len = 0;
                   4375:                        break;
                   4376:                }
                   4377: 
                   4378:                /* get subnet mask length */
                   4379:                plen = 0;
                   4380:                max = alen <<3;
                   4381: 
                   4382:                p = (unsigned char *) id->v
                   4383:                        + sizeof(struct ipsecdoi_id_b)
                   4384:                        + alen;
                   4385: 
                   4386:                for (; *p == 0xff; p++) {
                   4387:                        plen += 8;
                   4388:                        if (plen >= max)
                   4389:                                break;
                   4390:                }
                   4391: 
                   4392:                if (plen < max) {
                   4393:                        u_int l = 0;
                   4394:                        u_char b = ~(*p);
                   4395: 
                   4396:                        while (b) {
                   4397:                                b >>= 1;
                   4398:                                l++;
                   4399:                        }
                   4400: 
                   4401:                        l = 8 - l;
                   4402:                        plen += l;
                   4403:                }
                   4404: 
                   4405:                len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
                   4406:            }
                   4407:                break;
                   4408: 
                   4409:        case IPSECDOI_ID_IPV4_ADDR_RANGE:
                   4410: 
                   4411:                len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
                   4412: 
                   4413: #ifndef __linux__
                   4414:                saddr.sa.sa_len = sizeof(struct sockaddr_in);
                   4415: #endif
                   4416:                saddr.sa.sa_family = AF_INET;
                   4417:                saddr.sin.sin_port = IPSEC_PORT_ANY;
                   4418:                memcpy(&saddr.sin.sin_addr,
                   4419:                        id->v + sizeof(*id_b) + sizeof(struct in_addr),
                   4420:                        sizeof(struct in_addr));
                   4421: 
                   4422:                len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
                   4423:                break;
                   4424: 
                   4425: #ifdef INET6
                   4426:        case IPSECDOI_ID_IPV6_ADDR_RANGE:
                   4427:                len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
                   4428: 
                   4429: #ifndef __linux__
                   4430:                saddr.sa.sa_len = sizeof(struct sockaddr_in6);
                   4431: #endif
                   4432:                saddr.sa.sa_family = AF_INET6;
                   4433:                saddr.sin6.sin6_port = IPSEC_PORT_ANY;
                   4434:                memcpy(&saddr.sin6.sin6_addr,
                   4435:                        id->v + sizeof(*id_b) + sizeof(struct in6_addr),
                   4436:                        sizeof(struct in6_addr));
                   4437:                saddr.sin6.sin6_scope_id =
                   4438:                        (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
                   4439:                                ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
                   4440:                                : 0);
                   4441: 
                   4442:                len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
                   4443:                break;
                   4444: #endif
                   4445: 
                   4446:        case IPSECDOI_ID_FQDN:
                   4447:        case IPSECDOI_ID_USER_FQDN:
                   4448:                len = id->l - sizeof(*id_b);
                   4449:                if (len > BUFLEN)
                   4450:                        len = BUFLEN;
                   4451:                memcpy(buf, id->v + sizeof(*id_b), len);
                   4452:                break;
                   4453: 
                   4454:        case IPSECDOI_ID_DER_ASN1_DN:
                   4455:        case IPSECDOI_ID_DER_ASN1_GN:
                   4456:        {
                   4457:                X509_NAME *xn = NULL;
                   4458: 
                   4459:                dat = id->v + sizeof(*id_b);
                   4460:                len = id->l - sizeof(*id_b);
                   4461: 
                   4462:                if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
                   4463:                        BIO *bio = BIO_new(BIO_s_mem());
                   4464:                        X509_NAME_print_ex(bio, xn, 0, 0);
                   4465:                        len = BIO_get_mem_data(bio, &dat);
                   4466:                        if (len > BUFLEN)
                   4467:                                len = BUFLEN;
                   4468:                        memcpy(buf,dat,len);
                   4469:                        BIO_free(bio);
                   4470:                        X509_NAME_free(xn);
                   4471:                } else {
                   4472:                        plog(LLV_ERROR, LOCATION, NULL,
                   4473:                                "unable to extract asn1dn from id\n");
                   4474: 
                   4475:                        len = sprintf(buf, "<ASN1-DN>");
                   4476:                }
                   4477: 
                   4478:                break;
                   4479:        }
                   4480: 
                   4481:        /* currently unhandled id types */
                   4482:        case IPSECDOI_ID_KEY_ID:
                   4483:                len = sprintf( buf, "<KEY-ID>");
                   4484:                break;
                   4485: 
                   4486:        default:
                   4487:                plog(LLV_ERROR, LOCATION, NULL,
                   4488:                        "unknown ID type %d\n", id_b->type);
                   4489:        }
                   4490: 
                   4491:        if (!len)
                   4492:                len = sprintf( buf, "<?>");
                   4493: 
                   4494:        ret = racoon_malloc(len+1);
                   4495:        if (ret != NULL) {
                   4496:                memcpy(ret,buf,len);
                   4497:                ret[len]=0;
                   4498:        }
                   4499: 
                   4500:        return ret;
                   4501: }
                   4502: 
                   4503: /*
                   4504:  * set IPsec data attributes into a proposal.
                   4505:  * NOTE: MUST called per a transform.
                   4506:  */
                   4507: int
                   4508: ipsecdoi_t2satrns(t, pp, pr, tr)
                   4509:        struct isakmp_pl_t *t;
                   4510:        struct saprop *pp;
                   4511:        struct saproto *pr;
                   4512:        struct satrns *tr;
                   4513: {
                   4514:        struct isakmp_data *d, *prev;
                   4515:        int flag, type;
                   4516:        int error = -1;
                   4517:        int life_t;
                   4518:        int tlen;
                   4519: 
                   4520:        tr->trns_no = t->t_no;
                   4521:        tr->trns_id = t->t_id;
                   4522: 
                   4523:        tlen = ntohs(t->h.len) - sizeof(*t);
                   4524:        prev = (struct isakmp_data *)NULL;
                   4525:        d = (struct isakmp_data *)(t + 1);
                   4526: 
                   4527:        /* default */
                   4528:        life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
                   4529:        pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
                   4530:        pp->lifebyte = 0;
                   4531:        tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
                   4532: 
                   4533:        while (tlen > 0) {
                   4534: 
                   4535:                type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
                   4536:                flag = ntohs(d->type) & ISAKMP_GEN_MASK;
                   4537: 
                   4538:                plog(LLV_DEBUG, LOCATION, NULL,
                   4539:                        "type=%s, flag=0x%04x, lorv=%s\n",
                   4540:                        s_ipsecdoi_attr(type), flag,
                   4541:                        s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
                   4542: 
                   4543:                switch (type) {
                   4544:                case IPSECDOI_ATTR_SA_LD_TYPE:
                   4545:                {
                   4546:                        int type = ntohs(d->lorv);
                   4547:                        switch (type) {
                   4548:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
                   4549:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
                   4550:                                life_t = type;
                   4551:                                break;
                   4552:                        default:
                   4553:                                plog(LLV_WARNING, LOCATION, NULL,
                   4554:                                        "invalid life duration type. "
                   4555:                                        "use default\n");
                   4556:                                life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
                   4557:                                break;
                   4558:                        }
                   4559:                        break;
                   4560:                }
                   4561:                case IPSECDOI_ATTR_SA_LD:
                   4562:                        if (prev == NULL
                   4563:                         || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
                   4564:                                        IPSECDOI_ATTR_SA_LD_TYPE) {
                   4565:                                plog(LLV_ERROR, LOCATION, NULL,
                   4566:                                    "life duration must follow ltype\n");
                   4567:                                break;
                   4568:                        }
                   4569: 
                   4570:                    {
                   4571:                        u_int32_t t;
                   4572:                        vchar_t *ld_buf = NULL;
                   4573: 
                   4574:                        if (flag) {
                   4575:                                /* i.e. ISAKMP_GEN_TV */
                   4576:                                ld_buf = vmalloc(sizeof(d->lorv));
                   4577:                                if (ld_buf == NULL) {
                   4578:                                        plog(LLV_ERROR, LOCATION, NULL,
                   4579:                                            "failed to get LD buffer.\n");
                   4580:                                        goto end;
                   4581:                                }
                   4582:                                memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
                   4583:                        } else {
                   4584:                                int len = ntohs(d->lorv);
                   4585:                                /* i.e. ISAKMP_GEN_TLV */
                   4586:                                ld_buf = vmalloc(len);
                   4587:                                if (ld_buf == NULL) {
                   4588:                                        plog(LLV_ERROR, LOCATION, NULL,
                   4589:                                            "failed to get LD buffer.\n");
                   4590:                                        goto end;
                   4591:                                }
                   4592:                                memcpy(ld_buf->v, d + 1, len);
                   4593:                        }
                   4594:                        switch (life_t) {
                   4595:                        case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
                   4596:                                t = ipsecdoi_set_ld(ld_buf);
                   4597:                                vfree(ld_buf);
                   4598:                                if (t == 0) {
                   4599:                                        plog(LLV_ERROR, LOCATION, NULL,
                   4600:                                                "invalid life duration.\n");
                   4601:                                        goto end;
                   4602:                                }
                   4603:                                /* lifetime must be equal in a proposal. */
                   4604:                                if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
                   4605:                                        pp->lifetime = t;
                   4606:                                else if (pp->lifetime != t) {
                   4607:                                        plog(LLV_ERROR, LOCATION, NULL,
                   4608:                                                "lifetime mismatched "
                   4609:                                                "in a proposal, "
                   4610:                                                "prev:%ld curr:%u.\n",
                   4611:                                                (long)pp->lifetime, t);
                   4612:                                        goto end;
                   4613:                                }
                   4614:                                break;
                   4615:                        case IPSECDOI_ATTR_SA_LD_TYPE_KB:
                   4616:                                t = ipsecdoi_set_ld(ld_buf);
                   4617:                                vfree(ld_buf);
                   4618:                                if (t == 0) {
                   4619:                                        plog(LLV_ERROR, LOCATION, NULL,
                   4620:                                                "invalid life duration.\n");
                   4621:                                        goto end;
                   4622:                                }
                   4623:                                /* lifebyte must be equal in a proposal. */
                   4624:                                if (pp->lifebyte == 0)
                   4625:                                        pp->lifebyte = t;
                   4626:                                else if (pp->lifebyte != t) {
                   4627:                                        plog(LLV_ERROR, LOCATION, NULL,
                   4628:                                                "lifebyte mismatched "
                   4629:                                                "in a proposal, "
                   4630:                                                "prev:%d curr:%u.\n",
                   4631:                                                pp->lifebyte, t);
                   4632:                                        goto end;
                   4633:                                }
                   4634:                                break;
                   4635:                        default:
                   4636:                                vfree(ld_buf);
                   4637:                                plog(LLV_ERROR, LOCATION, NULL,
                   4638:                                        "invalid life type: %d\n", life_t);
                   4639:                                goto end;
                   4640:                        }
                   4641:                    }
                   4642:                        break;
                   4643: 
                   4644:                case IPSECDOI_ATTR_GRP_DESC:
                   4645:                        /*
                   4646:                         * RFC2407: 4.5 IPSEC Security Association Attributes
                   4647:                         *   Specifies the Oakley Group to be used in a PFS QM
                   4648:                         *   negotiation.  For a list of supported values, see
                   4649:                         *   Appendix A of [IKE].
                   4650:                         */
                   4651:                        if (pp->pfs_group == 0)
                   4652:                                pp->pfs_group = (u_int16_t)ntohs(d->lorv);
                   4653:                        else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
                   4654:                                plog(LLV_ERROR, LOCATION, NULL,
                   4655:                                        "pfs_group mismatched "
                   4656:                                        "in a proposal.\n");
                   4657:                                goto end;
                   4658:                        }
                   4659:                        break;
                   4660: 
                   4661:                case IPSECDOI_ATTR_ENC_MODE:
                   4662:                        if (pr->encmode &&
                   4663:                            pr->encmode != (u_int16_t)ntohs(d->lorv)) {
                   4664:                                plog(LLV_ERROR, LOCATION, NULL,
                   4665:                                        "multiple encmode exist "
                   4666:                                        "in a transform.\n");
                   4667:                                goto end;
                   4668:                        }
                   4669:                        pr->encmode = (u_int16_t)ntohs(d->lorv);
                   4670:                        break;
                   4671: 
                   4672:                case IPSECDOI_ATTR_AUTH:
                   4673:                        if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
                   4674:                                plog(LLV_ERROR, LOCATION, NULL,
                   4675:                                        "multiple authtype exist "
                   4676:                                        "in a transform.\n");
                   4677:                                goto end;
                   4678:                        }
                   4679:                        tr->authtype = (u_int16_t)ntohs(d->lorv);
                   4680:                        break;
                   4681: 
                   4682:                case IPSECDOI_ATTR_KEY_LENGTH:
                   4683:                        if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
                   4684:                                plog(LLV_ERROR, LOCATION, NULL,
                   4685:                                        "key length defined but not ESP");
                   4686:                                goto end;
                   4687:                        }
                   4688:                        tr->encklen = ntohs(d->lorv);
                   4689:                        break;
                   4690: #ifdef HAVE_SECCTX
                   4691:                case IPSECDOI_ATTR_SECCTX:
                   4692:                {
                   4693:                        int len = ntohs(d->lorv);
                   4694:                        memcpy(&pp->sctx, d + 1, len);
                   4695:                        pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
                   4696:                        break;
                   4697:                }
                   4698: #endif /* HAVE_SECCTX */
                   4699:                case IPSECDOI_ATTR_KEY_ROUNDS:
                   4700:                case IPSECDOI_ATTR_COMP_DICT_SIZE:
                   4701:                case IPSECDOI_ATTR_COMP_PRIVALG:
                   4702:                default:
                   4703:                        break;
                   4704:                }
                   4705: 
                   4706:                prev = d;
                   4707:                if (flag) {
                   4708:                        tlen -= sizeof(*d);
                   4709:                        d = (struct isakmp_data *)((char *)d + sizeof(*d));
                   4710:                } else {
                   4711:                        tlen -= (sizeof(*d) + ntohs(d->lorv));
                   4712:                        d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
                   4713:                }
                   4714:        }
                   4715: 
                   4716:        error = 0;
                   4717: end:
                   4718:        return error;
                   4719: }
                   4720: 
                   4721: int
                   4722: ipsecdoi_authalg2trnsid(alg)
                   4723:        int alg;
                   4724: {
                   4725:        switch (alg) {
                   4726:         case IPSECDOI_ATTR_AUTH_HMAC_MD5:
                   4727:                return IPSECDOI_AH_MD5;
                   4728:         case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
                   4729:                return IPSECDOI_AH_SHA;
                   4730:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
                   4731:                return IPSECDOI_AH_SHA256;
                   4732:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
                   4733:                return IPSECDOI_AH_SHA384;
                   4734:        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
                   4735:                return IPSECDOI_AH_SHA512;
                   4736:         case IPSECDOI_ATTR_AUTH_DES_MAC:
                   4737:                return IPSECDOI_AH_DES;
                   4738:        case IPSECDOI_ATTR_AUTH_KPDK:
                   4739:                return IPSECDOI_AH_MD5; /* XXX */
                   4740:        default:
                   4741:                plog(LLV_ERROR, LOCATION, NULL,
                   4742:                        "invalid authentication algorithm:%d\n", alg);
                   4743:        }
                   4744:        return -1;
                   4745: }
                   4746: 
                   4747: static int rm_idtype2doi[] = {
                   4748:        255,                            /* IDTYPE_UNDEFINED, 0 */
                   4749:        IPSECDOI_ID_FQDN,               /* IDTYPE_FQDN, 1 */
                   4750:        IPSECDOI_ID_USER_FQDN,          /* IDTYPE_USERFQDN, 2 */
                   4751:        IPSECDOI_ID_KEY_ID,             /* IDTYPE_KEYID, 3 */
                   4752:        255,    /*                         IDTYPE_ADDRESS, 4
                   4753:                 * it expands into 4 types by another function. */
                   4754:        IPSECDOI_ID_DER_ASN1_DN,        /* IDTYPE_ASN1DN, 5 */
                   4755: };
                   4756: 
                   4757: /*
                   4758:  * convert idtype to DOI value.
                   4759:  * OUT 255  : NG
                   4760:  *     other: converted.
                   4761:  */
                   4762: int
                   4763: idtype2doi(idtype)
                   4764:        int idtype;
                   4765: {
                   4766:        if (ARRAYLEN(rm_idtype2doi) > idtype)
                   4767:                return rm_idtype2doi[idtype];
                   4768:        return 255;
                   4769: }
                   4770: 
                   4771: int
                   4772: doi2idtype(doi)
                   4773:        int doi;
                   4774: {
                   4775:        switch(doi) {
                   4776:        case IPSECDOI_ID_FQDN:
                   4777:                return(IDTYPE_FQDN);
                   4778:        case IPSECDOI_ID_USER_FQDN:
                   4779:                return(IDTYPE_USERFQDN);
                   4780:        case IPSECDOI_ID_KEY_ID:
                   4781:                return(IDTYPE_KEYID);
                   4782:        case IPSECDOI_ID_DER_ASN1_DN:
                   4783:                return(IDTYPE_ASN1DN);
                   4784:        case IPSECDOI_ID_IPV4_ADDR:
                   4785:        case IPSECDOI_ID_IPV4_ADDR_SUBNET:
                   4786:        case IPSECDOI_ID_IPV6_ADDR:
                   4787:        case IPSECDOI_ID_IPV6_ADDR_SUBNET:
                   4788:                return(IDTYPE_ADDRESS);
                   4789:        default:
                   4790:                plog(LLV_WARNING, LOCATION, NULL,
                   4791:                        "Inproper idtype:%s in this function.\n",
                   4792:                        s_ipsecdoi_ident(doi));
                   4793:                return(IDTYPE_ADDRESS); /* XXX */
                   4794:        }
                   4795:        /*NOTREACHED*/
                   4796: }

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