[BACK]Return to ipsec_doi.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / crypto / dist / ipsec-tools / src / racoon

Annotation of src/crypto/dist/ipsec-tools/src/racoon/ipsec_doi.c, Revision 1.37

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

CVSweb <webmaster@jp.NetBSD.org>