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

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

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