[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.22.2.3

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

CVSweb <webmaster@jp.NetBSD.org>