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

1.1       misho       1: /*     $NetBSD: handler.c,v 1.39 2011/03/14 17:18:12 tteras Exp $      */
                      2: 
                      3: /* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */
                      4: 
                      5: /*
                      6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. Neither the name of the project nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
                     33: 
                     34: #include "config.h"
                     35: 
                     36: #include <sys/types.h>
                     37: #include <sys/param.h>
                     38: #include <sys/socket.h>
                     39: 
                     40: #include <stdlib.h>
                     41: #include <stdio.h>
                     42: #include <string.h>
                     43: #include <time.h>
                     44: #include <errno.h>
                     45: 
                     46: #include "var.h"
                     47: #include "misc.h"
                     48: #include "vmbuf.h"
                     49: #include "plog.h"
                     50: #include "sockmisc.h"
                     51: #include "debug.h"
                     52: 
                     53: #ifdef ENABLE_HYBRID
                     54: #include <resolv.h>
                     55: #endif
                     56: 
                     57: #include "schedule.h"
                     58: #include "grabmyaddr.h"
                     59: #include "algorithm.h"
                     60: #include "crypto_openssl.h"
                     61: #include "policy.h"
                     62: #include "proposal.h"
                     63: #include "isakmp_var.h"
                     64: #include "evt.h"
                     65: #include "isakmp.h"
                     66: #ifdef ENABLE_HYBRID
                     67: #include "isakmp_xauth.h"
                     68: #include "isakmp_cfg.h"
                     69: #endif
                     70: #include "isakmp_inf.h"
                     71: #include "oakley.h"
                     72: #include "remoteconf.h"
                     73: #include "localconf.h"
                     74: #include "handler.h"
                     75: #include "gcmalloc.h"
                     76: #include "nattraversal.h"
                     77: 
                     78: #include "sainfo.h"
                     79: 
                     80: #ifdef HAVE_GSSAPI
                     81: #include "gssapi.h"
                     82: #endif
                     83: 
                     84: static LIST_HEAD(_ph1tree_, ph1handle) ph1tree;
                     85: static LIST_HEAD(_ph2tree_, ph2handle) ph2tree;
                     86: static LIST_HEAD(_ctdtree_, contacted) ctdtree;
                     87: static LIST_HEAD(_rcptree_, recvdpkt) rcptree;
                     88: static struct sched sc_sweep = SCHED_INITIALIZER();
                     89: 
                     90: static void del_recvdpkt __P((struct recvdpkt *));
                     91: static void rem_recvdpkt __P((struct recvdpkt *));
                     92: 
                     93: /*
                     94:  * functions about management of the isakmp status table
                     95:  */
                     96: /* %%% management phase 1 handler */
                     97: /*
                     98:  * search for isakmpsa handler with isakmp index.
                     99:  */
                    100: 
                    101: extern caddr_t val2str(const char *, size_t);
                    102: 
                    103: /*
                    104:  * Enumerate the Phase 1 tree.
                    105:  * If enum_func() internally return a non-zero value,  this specific
                    106:  * error value is returned. 0 is returned if everything went right.
                    107:  *
                    108:  * Note that it is ok for enum_func() to call insph1(). Those inserted
                    109:  * Phase 1 will not interfere with current enumeration process.
                    110:  */
                    111: int
                    112: enumph1(sel, enum_func, enum_arg)
                    113:        struct ph1selector *sel;
                    114:        int (* enum_func)(struct ph1handle *iph1, void *arg);
                    115:        void *enum_arg;
                    116: {
                    117:        struct ph1handle *p;
                    118:        int ret;
                    119: 
                    120:        LIST_FOREACH(p, &ph1tree, chain) {
                    121:                if (sel != NULL) {
                    122:                        if (sel->local != NULL &&
                    123:                            cmpsaddr(sel->local, p->local) > CMPSADDR_WILDPORT_MATCH)
                    124:                                continue;
                    125: 
                    126:                        if (sel->remote != NULL &&
                    127:                            cmpsaddr(sel->remote, p->remote) > CMPSADDR_WILDPORT_MATCH)
                    128:                                continue;
                    129:                }
                    130: 
                    131:                if ((ret = enum_func(p, enum_arg)) != 0)
                    132:                        return ret;
                    133:        }
                    134: 
                    135:        return 0;
                    136: }
                    137: 
                    138: struct ph1handle *
                    139: getph1byindex(index)
                    140:        isakmp_index *index;
                    141: {
                    142:        struct ph1handle *p;
                    143: 
                    144:        LIST_FOREACH(p, &ph1tree, chain) {
                    145:                if (p->status >= PHASE1ST_EXPIRED)
                    146:                        continue;
                    147:                if (memcmp(&p->index, index, sizeof(*index)) == 0)
                    148:                        return p;
                    149:        }
                    150: 
                    151:        return NULL;
                    152: }
                    153: 
                    154: 
                    155: /*
                    156:  * search for isakmp handler by i_ck in index.
                    157:  */
                    158: struct ph1handle *
                    159: getph1byindex0(index)
                    160:        isakmp_index *index;
                    161: {
                    162:        struct ph1handle *p;
                    163: 
                    164:        LIST_FOREACH(p, &ph1tree, chain) {
                    165:                if (p->status >= PHASE1ST_EXPIRED)
                    166:                        continue;
                    167:                if (memcmp(&p->index, index, sizeof(cookie_t)) == 0)
                    168:                        return p;
                    169:        }
                    170: 
                    171:        return NULL;
                    172: }
                    173: 
                    174: /*
                    175:  * search for isakmpsa handler by source and remote address.
                    176:  * don't use port number to search because this function search
                    177:  * with phase 2's destinaion.
                    178:  */
                    179: struct ph1handle *
                    180: getph1(ph1hint, local, remote, flags)
                    181:        struct ph1handle *ph1hint;
                    182:        struct sockaddr *local, *remote;
                    183:        int flags;
                    184: {
                    185:        struct ph1handle *p;
                    186: 
                    187:        plog(LLV_DEBUG2, LOCATION, NULL, "getph1: start\n");
                    188:        plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local));
                    189:        plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote));
                    190: 
                    191:        LIST_FOREACH(p, &ph1tree, chain) {
                    192:                if (p->status >= PHASE1ST_DYING)
                    193:                        continue;
                    194: 
                    195:                plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local));
                    196:                plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote));
                    197: 
                    198:                if ((flags & GETPH1_F_ESTABLISHED) &&
                    199:                    (p->status != PHASE1ST_ESTABLISHED)) {
                    200:                        plog(LLV_DEBUG2, LOCATION, NULL,
                    201:                             "status %d, skipping\n", p->status);
                    202:                        continue;
                    203:                }
                    204: 
                    205:                if (local != NULL && cmpsaddr(local, p->local) == CMPSADDR_MISMATCH)
                    206:                        continue;
                    207: 
                    208:                if (remote != NULL && cmpsaddr(remote, p->remote) == CMPSADDR_MISMATCH)
                    209:                        continue;
                    210: 
                    211:                if (ph1hint != NULL) {
                    212:                        if (ph1hint->id && ph1hint->id->l && p->id && p->id->l &&
                    213:                            (ph1hint->id->l != p->id->l ||
                    214:                             memcmp(ph1hint->id->v, p->id->v, p->id->l) != 0)) {
                    215:                                plog(LLV_DEBUG2, LOCATION, NULL,
                    216:                                     "local identity does match hint\n");
                    217:                                continue;
                    218:                        }
                    219:                        if (ph1hint->id_p && ph1hint->id_p->l &&
                    220:                            p->id_p && p->id_p->l &&
                    221:                            (ph1hint->id_p->l != p->id_p->l ||
                    222:                             memcmp(ph1hint->id_p->v, p->id_p->v, p->id_p->l) != 0)) {
                    223:                                plog(LLV_DEBUG2, LOCATION, NULL,
                    224:                                     "remote identity does match hint\n");
                    225:                                continue;
                    226:                        }
                    227:                }
                    228: 
                    229:                plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
                    230:                return p;
                    231:        }
                    232: 
                    233:        plog(LLV_DEBUG2, LOCATION, NULL, "no match\n");
                    234: 
                    235:        return NULL;
                    236: }
                    237: 
                    238: int
                    239: resolveph1rmconf(iph1)
                    240:        struct ph1handle *iph1;
                    241: {
                    242:        struct remoteconf *rmconf;
                    243: 
                    244:        /* INITIATOR is always expected to know the exact rmconf. */
                    245:        if (iph1->side == INITIATOR)
                    246:                return 0;
                    247: 
                    248:        rmconf = getrmconf_by_ph1(iph1);
                    249:        if (rmconf == NULL)
                    250:                return -1;
                    251:        if (rmconf == RMCONF_ERR_MULTIPLE)
                    252:                return 1;
                    253: 
                    254:        if (iph1->rmconf != NULL) {
                    255:                if (rmconf != iph1->rmconf) {
                    256:                        plog(LLV_ERROR, LOCATION, NULL,
                    257:                             "unexpected rmconf switch; killing ph1\n");
                    258:                        return -1;
                    259:                }
                    260:        } else {
                    261:                iph1->rmconf = rmconf;
                    262:        }
                    263: 
                    264:        return 0;
                    265: }
                    266: 
                    267: 
                    268: /*
                    269:  * move phase2s from old_iph1 to new_iph1
                    270:  */
                    271: void
                    272: migrate_ph12(old_iph1, new_iph1)
                    273:        struct ph1handle *old_iph1, *new_iph1;
                    274: {
                    275:        struct ph2handle *p, *next;
                    276: 
                    277:        /* Relocate phase2s to better phase1s or request a new phase1. */
                    278:        for (p = LIST_FIRST(&old_iph1->ph2tree); p; p = next) {
                    279:                next = LIST_NEXT(p, ph1bind);
                    280: 
                    281:                if (p->status != PHASE2ST_ESTABLISHED)
                    282:                        continue;
                    283: 
                    284:                unbindph12(p);
                    285:                bindph12(new_iph1, p);
                    286:        }
                    287: }
                    288: 
                    289: /*
                    290:  * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1
                    291:  */
                    292: void migrate_dying_ph12(iph1)
                    293:        struct ph1handle *iph1;
                    294: {
                    295:        struct ph1handle *p;
                    296: 
                    297:        LIST_FOREACH(p, &ph1tree, chain) {
                    298:                if (p == iph1)
                    299:                        continue;
                    300:                if (p->status < PHASE1ST_DYING)
                    301:                        continue;
                    302: 
                    303:                if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH
                    304:                 && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH)
                    305:                        migrate_ph12(p, iph1);
                    306:        }
                    307: }
                    308: 
                    309: 
                    310: /*
                    311:  * dump isakmp-sa
                    312:  */
                    313: vchar_t *
                    314: dumpph1()
                    315: {
                    316:        struct ph1handle *iph1;
                    317:        struct ph1dump *pd;
                    318:        int cnt = 0;
                    319:        vchar_t *buf;
                    320: 
                    321:        /* get length of buffer */
                    322:        LIST_FOREACH(iph1, &ph1tree, chain)
                    323:                cnt++;
                    324: 
                    325:        buf = vmalloc(cnt * sizeof(struct ph1dump));
                    326:        if (buf == NULL) {
                    327:                plog(LLV_ERROR, LOCATION, NULL,
                    328:                        "failed to get buffer\n");
                    329:                return NULL;
                    330:        }
                    331:        pd = (struct ph1dump *)buf->v;
                    332: 
                    333:        LIST_FOREACH(iph1, &ph1tree, chain) {
                    334:                memcpy(&pd->index, &iph1->index, sizeof(iph1->index));
                    335:                pd->status = iph1->status;
                    336:                pd->side = iph1->side;
                    337:                memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote));
                    338:                memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local));
                    339:                pd->version = iph1->version;
                    340:                pd->etype = iph1->etype;
                    341:                pd->created = iph1->created;
                    342:                pd->ph2cnt = iph1->ph2cnt;
                    343:                pd++;
                    344:        }
                    345: 
                    346:        return buf;
                    347: }
                    348: 
                    349: /*
                    350:  * create new isakmp Phase 1 status record to handle isakmp in Phase1
                    351:  */
                    352: struct ph1handle *
                    353: newph1()
                    354: {
                    355:        struct ph1handle *iph1;
                    356: 
                    357:        /* create new iph1 */
                    358:        iph1 = racoon_calloc(1, sizeof(*iph1));
                    359:        if (iph1 == NULL)
                    360:                return NULL;
                    361: 
                    362:        iph1->status = PHASE1ST_SPAWN;
                    363: 
                    364: #ifdef ENABLE_DPD
                    365:        iph1->dpd_support = 0;
                    366:        iph1->dpd_seq = 0;
                    367:        iph1->dpd_fails = 0;
                    368: #endif
                    369:        evt_list_init(&iph1->evt_listeners);
                    370: 
                    371:        return iph1;
                    372: }
                    373: 
                    374: /*
                    375:  * delete new isakmp Phase 1 status record to handle isakmp in Phase1
                    376:  */
                    377: void
                    378: delph1(iph1)
                    379:        struct ph1handle *iph1;
                    380: {
                    381:        if (iph1 == NULL)
                    382:                return;
                    383: 
                    384:        /* SA down shell script hook */
                    385:        script_hook(iph1, SCRIPT_PHASE1_DOWN);
                    386:        evt_list_cleanup(&iph1->evt_listeners);
                    387: 
                    388: #ifdef ENABLE_NATT
                    389:        if (iph1->natt_flags & NAT_KA_QUEUED)
                    390:                natt_keepalive_remove (iph1->local, iph1->remote);
                    391: 
                    392:        if (iph1->natt_options) {
                    393:                racoon_free(iph1->natt_options);
                    394:                iph1->natt_options = NULL;
                    395:        }
                    396: #endif
                    397: 
                    398: #ifdef ENABLE_HYBRID
                    399:        if (iph1->mode_cfg)
                    400:                isakmp_cfg_rmstate(iph1);
                    401: #endif
                    402: 
                    403: #ifdef ENABLE_DPD
                    404:        sched_cancel(&iph1->dpd_r_u);
                    405: #endif
                    406:        sched_cancel(&iph1->sce);
                    407:        sched_cancel(&iph1->scr);
                    408: 
                    409:        if (iph1->remote) {
                    410:                racoon_free(iph1->remote);
                    411:                iph1->remote = NULL;
                    412:        }
                    413:        if (iph1->local) {
                    414:                racoon_free(iph1->local);
                    415:                iph1->local = NULL;
                    416:        }
                    417:        if (iph1->approval) {
                    418:                delisakmpsa(iph1->approval);
                    419:                iph1->approval = NULL;
                    420:        }
                    421: 
                    422:        VPTRINIT(iph1->authstr);
                    423:        VPTRINIT(iph1->sendbuf);
                    424:        VPTRINIT(iph1->dhpriv);
                    425:        VPTRINIT(iph1->dhpub);
                    426:        VPTRINIT(iph1->dhpub_p);
                    427:        VPTRINIT(iph1->dhgxy);
                    428:        VPTRINIT(iph1->nonce);
                    429:        VPTRINIT(iph1->nonce_p);
                    430:        VPTRINIT(iph1->skeyid);
                    431:        VPTRINIT(iph1->skeyid_d);
                    432:        VPTRINIT(iph1->skeyid_a);
                    433:        VPTRINIT(iph1->skeyid_e);
                    434:        VPTRINIT(iph1->key);
                    435:        VPTRINIT(iph1->hash);
                    436:        VPTRINIT(iph1->sig);
                    437:        VPTRINIT(iph1->sig_p);
                    438:        VPTRINIT(iph1->cert);
                    439:        VPTRINIT(iph1->cert_p);
                    440:        VPTRINIT(iph1->crl_p);
                    441:        VPTRINIT(iph1->cr_p);
                    442:        VPTRINIT(iph1->id);
                    443:        VPTRINIT(iph1->id_p);
                    444: 
                    445:        if(iph1->approval != NULL)
                    446:                delisakmpsa(iph1->approval);
                    447: 
                    448:        if (iph1->ivm) {
                    449:                oakley_delivm(iph1->ivm);
                    450:                iph1->ivm = NULL;
                    451:        }
                    452: 
                    453:        VPTRINIT(iph1->sa);
                    454:        VPTRINIT(iph1->sa_ret);
                    455: 
                    456: #ifdef HAVE_GSSAPI
                    457:        VPTRINIT(iph1->gi_i);
                    458:        VPTRINIT(iph1->gi_r);
                    459: 
                    460:        gssapi_free_state(iph1);
                    461: #endif
                    462: 
                    463:        racoon_free(iph1);
                    464: }
                    465: 
                    466: /*
                    467:  * create new isakmp Phase 1 status record to handle isakmp in Phase1
                    468:  */
                    469: int
                    470: insph1(iph1)
                    471:        struct ph1handle *iph1;
                    472: {
                    473:        /* validity check */
                    474:        if (iph1->remote == NULL) {
                    475:                plog(LLV_ERROR, LOCATION, NULL,
                    476:                        "invalid isakmp SA handler. no remote address.\n");
                    477:                return -1;
                    478:        }
                    479:        LIST_INSERT_HEAD(&ph1tree, iph1, chain);
                    480: 
                    481:        return 0;
                    482: }
                    483: 
                    484: void
                    485: remph1(iph1)
                    486:        struct ph1handle *iph1;
                    487: {
                    488:        LIST_REMOVE(iph1, chain);
                    489: }
                    490: 
                    491: /*
                    492:  * flush isakmp-sa
                    493:  */
                    494: void
                    495: flushph1()
                    496: {
                    497:        struct ph1handle *p, *next;
                    498: 
                    499:        for (p = LIST_FIRST(&ph1tree); p; p = next) {
                    500:                next = LIST_NEXT(p, chain);
                    501: 
                    502:                /* send delete information */
                    503:                if (p->status >= PHASE1ST_ESTABLISHED)
                    504:                        isakmp_info_send_d1(p);
                    505: 
                    506:                remph1(p);
                    507:                delph1(p);
                    508:        }
                    509: }
                    510: 
                    511: void
                    512: initph1tree()
                    513: {
                    514:        LIST_INIT(&ph1tree);
                    515: }
                    516: 
                    517: int
                    518: ph1_rekey_enabled(iph1)
                    519:        struct ph1handle *iph1;
                    520: {
                    521:        if (iph1->rmconf == NULL)
                    522:                return 0;
                    523:        if (iph1->rmconf->rekey == REKEY_FORCE)
                    524:                return 1;
                    525: #ifdef ENABLE_DPD
                    526:        if (iph1->rmconf->rekey == REKEY_ON && iph1->dpd_support &&
                    527:            iph1->rmconf->dpd_interval)
                    528:                return 1;
                    529: #endif
                    530:        return 0;
                    531: }
                    532: 
                    533: /* %%% management phase 2 handler */
                    534: 
                    535: int
                    536: enumph2(sel, enum_func, enum_arg)
                    537:        struct ph2selector *sel;
                    538:        int (*enum_func)(struct ph2handle *ph2, void *arg);
                    539:        void *enum_arg;
                    540: {
                    541:        struct ph2handle *p;
                    542:        int ret;
                    543: 
                    544:        LIST_FOREACH(p, &ph2tree, chain) {
                    545:                if (sel != NULL) {
                    546:                        if (sel->spid != 0 && sel->spid != p->spid)
                    547:                                continue;
                    548: 
                    549:                        if (sel->src != NULL &&
                    550:                            cmpsaddr(sel->src, p->src) != CMPSADDR_MATCH)
                    551:                                continue;
                    552: 
                    553:                        if (sel->dst != NULL &&
                    554:                            cmpsaddr(sel->dst, p->dst) != CMPSADDR_MATCH)
                    555:                                continue;
                    556:                }
                    557: 
                    558:                if ((ret = enum_func(p, enum_arg)) != 0)
                    559:                        return ret;
                    560:        }
                    561: 
                    562:        return 0;
                    563: }
                    564: 
                    565: /*
                    566:  * search ph2handle with sequence number.
                    567:  */
                    568: struct ph2handle *
                    569: getph2byseq(seq)
                    570:        u_int32_t seq;
                    571: {
                    572:        struct ph2handle *p;
                    573: 
                    574:        LIST_FOREACH(p, &ph2tree, chain) {
                    575:                if (p->seq == seq)
                    576:                        return p;
                    577:        }
                    578: 
                    579:        return NULL;
                    580: }
                    581: 
                    582: /*
                    583:  * search ph2handle with message id.
                    584:  */
                    585: struct ph2handle *
                    586: getph2bymsgid(iph1, msgid)
                    587:        struct ph1handle *iph1;
                    588:        u_int32_t msgid;
                    589: {
                    590:        struct ph2handle *p;
                    591: 
                    592:        LIST_FOREACH(p, &iph1->ph2tree, ph1bind) {
                    593:                if (p->msgid == msgid && p->ph1 == iph1)
                    594:                        return p;
                    595:        }
                    596: 
                    597:        return NULL;
                    598: }
                    599: 
                    600: /* Note that src and dst are not the selectors of the SP
                    601:  * but the source and destination addresses used for
                    602:  * for SA negotiation (best example is tunnel mode SA
                    603:  * where src and dst are the endpoints). There is at most
                    604:  * a unique match because racoon does not support bundles
                    605:  * which makes that there is at most a single established
                    606:  * SA for a given spid. One could say that src and dst
                    607:  * are in fact useless ...
                    608:  */
                    609: struct ph2handle *
                    610: getph2byid(src, dst, spid)
                    611:        struct sockaddr *src, *dst;
                    612:        u_int32_t spid;
                    613: {
                    614:        struct ph2handle *p;
                    615: 
                    616:        LIST_FOREACH(p, &ph2tree, chain) {
                    617:                if (spid == p->spid &&
                    618:                    cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
                    619:                    cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH){
                    620:                        /* Sanity check to detect zombie handlers
                    621:                         * XXX Sould be done "somewhere" more interesting,
                    622:                         * because we have lots of getph2byxxxx(), but this one
                    623:                         * is called by pk_recvacquire(), so is the most important.
                    624:                         */
                    625:                        if(p->status < PHASE2ST_ESTABLISHED &&
                    626:                           p->retry_counter == 0
                    627:                           && p->sce.func == NULL && p->scr.func == NULL) {
                    628:                                plog(LLV_DEBUG, LOCATION, NULL,
                    629:                                         "Zombie ph2 found, expiring it\n");
                    630:                                isakmp_ph2expire(p);
                    631:                        }else
                    632:                                return p;
                    633:                }
                    634:        }
                    635: 
                    636:        return NULL;
                    637: }
                    638: 
                    639: struct ph2handle *
                    640: getph2bysaddr(src, dst)
                    641:        struct sockaddr *src, *dst;
                    642: {
                    643:        struct ph2handle *p;
                    644: 
                    645:        LIST_FOREACH(p, &ph2tree, chain) {
                    646:                if (cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
                    647:                    cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH)
                    648:                        return p;
                    649:        }
                    650: 
                    651:        return NULL;
                    652: }
                    653: 
                    654: /*
                    655:  * call by pk_recvexpire().
                    656:  */
                    657: struct ph2handle *
                    658: getph2bysaidx(src, dst, proto_id, spi)
                    659:        struct sockaddr *src, *dst;
                    660:        u_int proto_id;
                    661:        u_int32_t spi;
                    662: {
                    663:        struct ph2handle *iph2;
                    664:        struct saproto *pr;
                    665: 
                    666:        LIST_FOREACH(iph2, &ph2tree, chain) {
                    667:                if (iph2->proposal == NULL && iph2->approval == NULL)
                    668:                        continue;
                    669:                if (iph2->approval != NULL) {
                    670:                        for (pr = iph2->approval->head; pr != NULL;
                    671:                             pr = pr->next) {
                    672:                                if (proto_id != pr->proto_id)
                    673:                                        break;
                    674:                                if (spi == pr->spi || spi == pr->spi_p)
                    675:                                        return iph2;
                    676:                        }
                    677:                } else if (iph2->proposal != NULL) {
                    678:                        for (pr = iph2->proposal->head; pr != NULL;
                    679:                             pr = pr->next) {
                    680:                                if (proto_id != pr->proto_id)
                    681:                                        break;
                    682:                                if (spi == pr->spi)
                    683:                                        return iph2;
                    684:                        }
                    685:                }
                    686:        }
                    687: 
                    688:        return NULL;
                    689: }
                    690: 
                    691: /*
                    692:  * create new isakmp Phase 2 status record to handle isakmp in Phase2
                    693:  */
                    694: struct ph2handle *
                    695: newph2()
                    696: {
                    697:        struct ph2handle *iph2 = NULL;
                    698: 
                    699:        /* create new iph2 */
                    700:        iph2 = racoon_calloc(1, sizeof(*iph2));
                    701:        if (iph2 == NULL)
                    702:                return NULL;
                    703: 
                    704:        iph2->status = PHASE1ST_SPAWN;
                    705:        evt_list_init(&iph2->evt_listeners);
                    706: 
                    707:        return iph2;
                    708: }
                    709: 
                    710: /*
                    711:  * initialize ph2handle
                    712:  * NOTE: don't initialize src/dst.
                    713:  *       SPI in the proposal is cleared.
                    714:  */
                    715: void
                    716: initph2(iph2)
                    717:        struct ph2handle *iph2;
                    718: {
                    719:        evt_list_cleanup(&iph2->evt_listeners);
                    720:        unbindph12(iph2);
                    721: 
                    722:        sched_cancel(&iph2->sce);
                    723:        sched_cancel(&iph2->scr);
                    724: 
                    725:        VPTRINIT(iph2->sendbuf);
                    726:        VPTRINIT(iph2->msg1);
                    727: 
                    728:        /* clear spi, keep variables in the proposal */
                    729:        if (iph2->proposal) {
                    730:                struct saproto *pr;
                    731:                for (pr = iph2->proposal->head; pr != NULL; pr = pr->next)
                    732:                        pr->spi = 0;
                    733:        }
                    734: 
                    735:        /* clear approval */
                    736:        if (iph2->approval) {
                    737:                flushsaprop(iph2->approval);
                    738:                iph2->approval = NULL;
                    739:        }
                    740: 
                    741:        /* clear the generated policy */
                    742:        if (iph2->spidx_gen) {
                    743:                delsp_bothdir((struct policyindex *)iph2->spidx_gen);
                    744:                racoon_free(iph2->spidx_gen);
                    745:                iph2->spidx_gen = NULL;
                    746:        }
                    747: 
                    748:        if (iph2->pfsgrp) {
                    749:                oakley_dhgrp_free(iph2->pfsgrp);
                    750:                iph2->pfsgrp = NULL;
                    751:        }
                    752: 
                    753:        VPTRINIT(iph2->dhpriv);
                    754:        VPTRINIT(iph2->dhpub);
                    755:        VPTRINIT(iph2->dhpub_p);
                    756:        VPTRINIT(iph2->dhgxy);
                    757:        VPTRINIT(iph2->id);
                    758:        VPTRINIT(iph2->id_p);
                    759:        VPTRINIT(iph2->nonce);
                    760:        VPTRINIT(iph2->nonce_p);
                    761:        VPTRINIT(iph2->sa);
                    762:        VPTRINIT(iph2->sa_ret);
                    763: 
                    764:        if (iph2->ivm) {
                    765:                oakley_delivm(iph2->ivm);
                    766:                iph2->ivm = NULL;
                    767:        }
                    768: 
                    769: #ifdef ENABLE_NATT
                    770:        if (iph2->natoa_src) {
                    771:                racoon_free(iph2->natoa_src);
                    772:                iph2->natoa_src = NULL;
                    773:        }
                    774:        if (iph2->natoa_dst) {
                    775:                racoon_free(iph2->natoa_dst);
                    776:                iph2->natoa_dst = NULL;
                    777:        }
                    778: #endif
                    779: }
                    780: 
                    781: /*
                    782:  * delete new isakmp Phase 2 status record to handle isakmp in Phase2
                    783:  */
                    784: void
                    785: delph2(iph2)
                    786:        struct ph2handle *iph2;
                    787: {
                    788:        initph2(iph2);
                    789: 
                    790:        if (iph2->src) {
                    791:                racoon_free(iph2->src);
                    792:                iph2->src = NULL;
                    793:        }
                    794:        if (iph2->dst) {
                    795:                racoon_free(iph2->dst);
                    796:                iph2->dst = NULL;
                    797:        }
                    798:        if (iph2->sa_src) {
                    799:                racoon_free(iph2->sa_src);
                    800:                iph2->sa_src = NULL;
                    801:        }
                    802:        if (iph2->sa_dst) {
                    803:                racoon_free(iph2->sa_dst);
                    804:                iph2->sa_dst = NULL;
                    805:        }
                    806: #ifdef ENABLE_NATT
                    807:        if (iph2->natoa_src) {
                    808:                racoon_free(iph2->natoa_src);
                    809:                iph2->natoa_src = NULL;
                    810:        }
                    811:        if (iph2->natoa_dst) {
                    812:                racoon_free(iph2->natoa_dst);
                    813:                iph2->natoa_dst = NULL;
                    814:        }
                    815: #endif
                    816: 
                    817:        if (iph2->proposal) {
                    818:                flushsaprop(iph2->proposal);
                    819:                iph2->proposal = NULL;
                    820:        }
                    821: 
                    822:        racoon_free(iph2);
                    823: }
                    824: 
                    825: /*
                    826:  * create new isakmp Phase 2 status record to handle isakmp in Phase2
                    827:  */
                    828: int
                    829: insph2(iph2)
                    830:        struct ph2handle *iph2;
                    831: {
                    832:        LIST_INSERT_HEAD(&ph2tree, iph2, chain);
                    833: 
                    834:        return 0;
                    835: }
                    836: 
                    837: void
                    838: remph2(iph2)
                    839:        struct ph2handle *iph2;
                    840: {
                    841:        unbindph12(iph2);
                    842:        LIST_REMOVE(iph2, chain);
                    843: }
                    844: 
                    845: void
                    846: initph2tree()
                    847: {
                    848:        LIST_INIT(&ph2tree);
                    849: }
                    850: 
                    851: void
                    852: flushph2()
                    853: {
                    854:        struct ph2handle *p, *next;
                    855: 
                    856:        plog(LLV_DEBUG2, LOCATION, NULL,
                    857:                 "flushing all ph2 handlers...\n");
                    858: 
                    859:        for (p = LIST_FIRST(&ph2tree); p; p = next) {
                    860:                next = LIST_NEXT(p, chain);
                    861: 
                    862:                /* send delete information */
                    863:                if (p->status == PHASE2ST_ESTABLISHED){
                    864:                        plog(LLV_DEBUG2, LOCATION, NULL,
                    865:                                 "got a ph2 handler to flush...\n");
                    866:                        isakmp_info_send_d2(p);
                    867:                }else{
                    868:                        plog(LLV_DEBUG2, LOCATION, NULL,
                    869:                                 "skipping ph2 handler (state %d)\n", p->status);
                    870:                }
                    871: 
                    872:                delete_spd(p, 0);
                    873:                remph2(p);
                    874:                delph2(p);
                    875:        }
                    876: }
                    877: 
                    878: /*
                    879:  * Delete all Phase 2 handlers for this src/dst/proto.  This
                    880:  * is used during INITIAL-CONTACT processing (so no need to
                    881:  * send a message to the peer).
                    882:  */
                    883: void
                    884: deleteallph2(src, dst, proto_id)
                    885:        struct sockaddr *src, *dst;
                    886:        u_int proto_id;
                    887: {
                    888:        struct ph2handle *iph2, *next;
                    889:        struct saproto *pr;
                    890: 
                    891:        for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) {
                    892:                next = LIST_NEXT(iph2, chain);
                    893:                if (iph2->proposal == NULL && iph2->approval == NULL)
                    894:                        continue;
                    895:                if (iph2->approval != NULL) {
                    896:                        for (pr = iph2->approval->head; pr != NULL;
                    897:                             pr = pr->next) {
                    898:                                if (proto_id == pr->proto_id)
                    899:                                        goto zap_it;
                    900:                        }
                    901:                } else if (iph2->proposal != NULL) {
                    902:                        for (pr = iph2->proposal->head; pr != NULL;
                    903:                             pr = pr->next) {
                    904:                                if (proto_id == pr->proto_id)
                    905:                                        goto zap_it;
                    906:                        }
                    907:                }
                    908:                continue;
                    909:  zap_it:
                    910:                remph2(iph2);
                    911:                delph2(iph2);
                    912:        }
                    913: }
                    914: 
                    915: /* %%% */
                    916: void
                    917: bindph12(iph1, iph2)
                    918:        struct ph1handle *iph1;
                    919:        struct ph2handle *iph2;
                    920: {
                    921:        unbindph12(iph2);
                    922: 
                    923:        iph2->ph1 = iph1;
                    924:        iph1->ph2cnt++;
                    925:        LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind);
                    926: }
                    927: 
                    928: void
                    929: unbindph12(iph2)
                    930:        struct ph2handle *iph2;
                    931: {
                    932:        if (iph2->ph1 != NULL) {
                    933:                LIST_REMOVE(iph2, ph1bind);
                    934:                iph2->ph1->ph2cnt--;
                    935:                iph2->ph1 = NULL;
                    936:        }
                    937: }
                    938: 
                    939: /* %%% management contacted list */
                    940: /*
                    941:  * search contacted list.
                    942:  */
                    943: struct contacted *
                    944: getcontacted(remote)
                    945:        struct sockaddr *remote;
                    946: {
                    947:        struct contacted *p;
                    948: 
                    949:        LIST_FOREACH(p, &ctdtree, chain) {
                    950:                if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH)
                    951:                        return p;
                    952:        }
                    953: 
                    954:        return NULL;
                    955: }
                    956: 
                    957: /*
                    958:  * create new isakmp Phase 2 status record to handle isakmp in Phase2
                    959:  */
                    960: int
                    961: inscontacted(remote)
                    962:        struct sockaddr *remote;
                    963: {
                    964:        struct contacted *new;
                    965: 
                    966:        /* create new iph2 */
                    967:        new = racoon_calloc(1, sizeof(*new));
                    968:        if (new == NULL)
                    969:                return -1;
                    970: 
                    971:        new->remote = dupsaddr(remote);
                    972:        if (new->remote == NULL) {
                    973:                plog(LLV_ERROR, LOCATION, NULL,
                    974:                        "failed to allocate buffer.\n");
                    975:                racoon_free(new);
                    976:                return -1;
                    977:        }
                    978: 
                    979:        LIST_INSERT_HEAD(&ctdtree, new, chain);
                    980: 
                    981:        return 0;
                    982: }
                    983: 
                    984: void
                    985: remcontacted(remote)
                    986:        struct sockaddr *remote;
                    987: {
                    988:        struct contacted *p;
                    989: 
                    990:        LIST_FOREACH(p, &ctdtree, chain) {
                    991:                if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH) {
                    992:                        LIST_REMOVE(p, chain);
                    993:                        racoon_free(p->remote);
                    994:                        racoon_free(p);
                    995:                        break;
                    996:                }
                    997:        }       
                    998: }
                    999: 
                   1000: void
                   1001: initctdtree()
                   1002: {
                   1003:        LIST_INIT(&ctdtree);
                   1004: }
                   1005: 
                   1006: /*
                   1007:  * check the response has been sent to the peer.  when not, simply reply
                   1008:  * the buffered packet to the peer.
                   1009:  * OUT:
                   1010:  *      0:     the packet is received at the first time.
                   1011:  *      1:     the packet was processed before.
                   1012:  *      2:     the packet was processed before, but the address mismatches.
                   1013:  *     -1:     error happened.
                   1014:  */
                   1015: int
                   1016: check_recvdpkt(remote, local, rbuf)
                   1017:        struct sockaddr *remote, *local;
                   1018:        vchar_t *rbuf;
                   1019: {
                   1020:        vchar_t *hash;
                   1021:        struct recvdpkt *r;
                   1022:        struct timeval now, diff;
                   1023:        int len, s;
                   1024: 
                   1025:        hash = eay_md5_one(rbuf);
                   1026:        if (!hash) {
                   1027:                plog(LLV_ERROR, LOCATION, NULL,
                   1028:                        "failed to allocate buffer.\n");
                   1029:                return -1;
                   1030:        }
                   1031: 
                   1032:        LIST_FOREACH(r, &rcptree, chain) {
                   1033:                if (memcmp(hash->v, r->hash->v, r->hash->l) == 0)
                   1034:                        break;
                   1035:        }
                   1036:        vfree(hash);
                   1037: 
                   1038:        /* this is the first time to receive the packet */
                   1039:        if (r == NULL)
                   1040:                return 0;
                   1041: 
                   1042:        /*
                   1043:         * the packet was processed before, but the remote address mismatches.
                   1044:         */
                   1045:        if (cmpsaddr(remote, r->remote) != CMPSADDR_MATCH)
                   1046:                return 2;
                   1047: 
                   1048:        /*
                   1049:         * it should not check the local address because the packet
                   1050:         * may arrive at other interface.
                   1051:         */
                   1052: 
                   1053:        /* check the previous time to send */
                   1054:        sched_get_monotonic_time(&now);
                   1055:        timersub(&now, &r->time_send, &diff);
                   1056:        if (diff.tv_sec == 0) {
                   1057:                plog(LLV_WARNING, LOCATION, NULL,
                   1058:                        "the packet retransmitted in a short time from %s\n",
                   1059:                        saddr2str(remote));
                   1060:                /*XXX should it be error ? */
                   1061:        }
                   1062: 
                   1063:        /* select the socket to be sent */
                   1064:        s = myaddr_getfd(r->local);
                   1065:        if (s == -1)
                   1066:                return -1;
                   1067: 
                   1068:        /* resend the packet if needed */
                   1069:        len = sendfromto(s, r->sendbuf->v, r->sendbuf->l,
                   1070:                        r->local, r->remote, lcconf->count_persend);
                   1071:        if (len == -1) {
                   1072:                plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
                   1073:                return -1;
                   1074:        }
                   1075: 
                   1076:        /* check the retry counter */
                   1077:        r->retry_counter--;
                   1078:        if (r->retry_counter <= 0) {
                   1079:                rem_recvdpkt(r);
                   1080:                del_recvdpkt(r);
                   1081:                plog(LLV_DEBUG, LOCATION, NULL,
                   1082:                        "deleted the retransmission packet to %s.\n",
                   1083:                        saddr2str(remote));
                   1084:        } else
                   1085:                r->time_send = now;
                   1086: 
                   1087:        return 1;
                   1088: }
                   1089: 
                   1090: /*
                   1091:  * adding a hash of received packet into the received list.
                   1092:  */
                   1093: int
                   1094: add_recvdpkt(remote, local, sbuf, rbuf)
                   1095:        struct sockaddr *remote, *local;
                   1096:        vchar_t *sbuf, *rbuf;
                   1097: {
                   1098:        struct recvdpkt *new = NULL;
                   1099: 
                   1100:        if (lcconf->retry_counter == 0) {
                   1101:                /* no need to add it */
                   1102:                return 0;
                   1103:        }
                   1104: 
                   1105:        new = racoon_calloc(1, sizeof(*new));
                   1106:        if (!new) {
                   1107:                plog(LLV_ERROR, LOCATION, NULL,
                   1108:                        "failed to allocate buffer.\n");
                   1109:                return -1;
                   1110:        }
                   1111: 
                   1112:        new->hash = eay_md5_one(rbuf);
                   1113:        if (!new->hash) {
                   1114:                plog(LLV_ERROR, LOCATION, NULL,
                   1115:                        "failed to allocate buffer.\n");
                   1116:                del_recvdpkt(new);
                   1117:                return -1;
                   1118:        }
                   1119:        new->remote = dupsaddr(remote);
                   1120:        if (new->remote == NULL) {
                   1121:                plog(LLV_ERROR, LOCATION, NULL,
                   1122:                        "failed to allocate buffer.\n");
                   1123:                del_recvdpkt(new);
                   1124:                return -1;
                   1125:        }
                   1126:        new->local = dupsaddr(local);
                   1127:        if (new->local == NULL) {
                   1128:                plog(LLV_ERROR, LOCATION, NULL,
                   1129:                        "failed to allocate buffer.\n");
                   1130:                del_recvdpkt(new);
                   1131:                return -1;
                   1132:        }
                   1133:        new->sendbuf = vdup(sbuf);
                   1134:        if (new->sendbuf == NULL) {
                   1135:                plog(LLV_ERROR, LOCATION, NULL,
                   1136:                        "failed to allocate buffer.\n");
                   1137:                del_recvdpkt(new);
                   1138:                return -1;
                   1139:        }
                   1140: 
                   1141:        new->retry_counter = lcconf->retry_counter;
                   1142:        sched_get_monotonic_time(&new->time_send);
                   1143: 
                   1144:        LIST_INSERT_HEAD(&rcptree, new, chain);
                   1145: 
                   1146:        return 0;
                   1147: }
                   1148: 
                   1149: void
                   1150: del_recvdpkt(r)
                   1151:        struct recvdpkt *r;
                   1152: {
                   1153:        if (r->remote)
                   1154:                racoon_free(r->remote);
                   1155:        if (r->local)
                   1156:                racoon_free(r->local);
                   1157:        if (r->hash)
                   1158:                vfree(r->hash);
                   1159:        if (r->sendbuf)
                   1160:                vfree(r->sendbuf);
                   1161:        racoon_free(r);
                   1162: }
                   1163: 
                   1164: void
                   1165: rem_recvdpkt(r)
                   1166:        struct recvdpkt *r;
                   1167: {
                   1168:        LIST_REMOVE(r, chain);
                   1169: }
                   1170: 
                   1171: static void
                   1172: sweep_recvdpkt(dummy)
                   1173:        struct sched *dummy;
                   1174: {
                   1175:        struct recvdpkt *r, *next;
                   1176:        struct timeval now, diff, sweep;
                   1177: 
                   1178:        sched_get_monotonic_time(&now);
                   1179: 
                   1180:        /* calculate sweep time; delete entries older than this */
                   1181:        diff.tv_sec = lcconf->retry_counter * lcconf->retry_interval;
                   1182:        diff.tv_usec = 0;
                   1183:        timersub(&now, &diff, &sweep);
                   1184: 
                   1185:        for (r = LIST_FIRST(&rcptree); r; r = next) {
                   1186:                next = LIST_NEXT(r, chain);
                   1187: 
                   1188:                if (timercmp(&r->time_send, &sweep, <)) {
                   1189:                        rem_recvdpkt(r);
                   1190:                        del_recvdpkt(r);
                   1191:                }
                   1192:        }
                   1193: 
                   1194:        sched_schedule(&sc_sweep, diff.tv_sec, sweep_recvdpkt);
                   1195: }
                   1196: 
                   1197: void
                   1198: init_recvdpkt()
                   1199: {
                   1200:        time_t lt = lcconf->retry_counter * lcconf->retry_interval;
                   1201: 
                   1202:        LIST_INIT(&rcptree);
                   1203: 
                   1204:        sched_schedule(&sc_sweep, lt, sweep_recvdpkt);
                   1205: }
                   1206: 
                   1207: #ifdef ENABLE_HYBRID
                   1208: /*
                   1209:  * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
                   1210:  * This should be in isakmp_cfg.c but ph1tree being private, it must be there
                   1211:  */
                   1212: int
                   1213: exclude_cfg_addr(addr)
                   1214:        const struct sockaddr *addr;
                   1215: {
                   1216:        struct ph1handle *p;
                   1217:        struct sockaddr_in *sin;
                   1218: 
                   1219:        LIST_FOREACH(p, &ph1tree, chain) {
                   1220:                if ((p->mode_cfg != NULL) &&
                   1221:                    (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) &&
                   1222:                    (addr->sa_family == AF_INET)) {
                   1223:                        sin = (struct sockaddr_in *)addr;
                   1224:                        if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr)
                   1225:                                return 0;
                   1226:                }
                   1227:        }
                   1228: 
                   1229:        return 1;
                   1230: }
                   1231: #endif
                   1232: 
                   1233: 
                   1234: 
                   1235: /*
                   1236:  * Reload conf code
                   1237:  */
                   1238: static int revalidate_ph2(struct ph2handle *iph2){
                   1239:        struct sainfoalg *alg;
                   1240:        int found, check_level;
                   1241:        struct sainfo *sainfo;
                   1242:        struct saprop *approval;
                   1243:        struct ph1handle *iph1;
                   1244: 
                   1245:        /*
                   1246:         * Get the new sainfo using values of the old one
                   1247:         */
                   1248:        if (iph2->sainfo != NULL) {
                   1249:                iph2->sainfo = getsainfo(iph2->sainfo->idsrc,
                   1250:                                          iph2->sainfo->iddst, iph2->sainfo->id_i,
                   1251:                                          NULL, iph2->sainfo->remoteid);
                   1252:        }
                   1253:        approval = iph2->approval;
                   1254:        sainfo = iph2->sainfo;
                   1255: 
                   1256:        if (sainfo == NULL) {
                   1257:                /*
                   1258:                 * Sainfo has been removed
                   1259:                 */
                   1260:                plog(LLV_DEBUG, LOCATION, NULL,
                   1261:                         "Reload: No sainfo for ph2\n");
                   1262:                return 0;
                   1263:        }
                   1264: 
                   1265:        if (approval == NULL) {
                   1266:                /*
                   1267:                 * XXX why do we have a NULL approval sometimes ???
                   1268:                 */
                   1269:                plog(LLV_DEBUG, LOCATION, NULL,
                   1270:                         "No approval found !\n");
                   1271:                return 0;
                   1272:        }
                   1273: 
                   1274:        /*
                   1275:         * Don't care about proposals, should we do something ?
                   1276:         * We have to keep iph2->proposal valid at least for initiator,
                   1277:         * for pk_sendgetspi()
                   1278:         */
                   1279: 
                   1280:        plog(LLV_DEBUG, LOCATION, NULL, "active single bundle:\n");
                   1281:        printsaprop0(LLV_DEBUG, approval);
                   1282: 
                   1283:        /*
                   1284:         * Validate approval against sainfo
                   1285:         * Note: we must have an updated ph1->rmconf before doing that,
                   1286:         * we'll set check_level to EXACT if we don't have a ph1
                   1287:         * XXX try tu find the new remote section to get the new check level ?
                   1288:         * XXX lifebyte
                   1289:         */
                   1290:        if (iph2->ph1 != NULL)
                   1291:                iph1=iph2->ph1;
                   1292:        else
                   1293:                iph1=getph1byaddr(iph2->src, iph2->dst, 0);
                   1294: 
                   1295:        if(iph1 != NULL && iph1->rmconf != NULL) {
                   1296:                check_level = iph1->rmconf->pcheck_level;
                   1297:        } else {
                   1298:                if(iph1 != NULL)
                   1299:                        plog(LLV_DEBUG, LOCATION, NULL, "No phase1 rmconf found !\n");
                   1300:                else
                   1301:                        plog(LLV_DEBUG, LOCATION, NULL, "No phase1 found !\n");
                   1302:                check_level = PROP_CHECK_EXACT;
                   1303:        }
                   1304: 
                   1305:        switch (check_level) {
                   1306:        case PROP_CHECK_OBEY:
                   1307:                plog(LLV_DEBUG, LOCATION, NULL,
                   1308:                         "Reload: OBEY for ph2, ok\n");
                   1309:                return 1;
                   1310:                break;
                   1311: 
                   1312:        case PROP_CHECK_STRICT:
                   1313:                /* FALLTHROUGH */
                   1314:        case PROP_CHECK_CLAIM:
                   1315:                if (sainfo->lifetime < approval->lifetime) {
                   1316:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1317:                                 "Reload: lifetime mismatch\n");
                   1318:                        return 0;
                   1319:                }
                   1320: 
                   1321: #if 0
                   1322:                /* Lifebyte is deprecated, just ignore it
                   1323:                 */
                   1324:                if (sainfo->lifebyte < approval->lifebyte) {
                   1325:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1326:                                 "Reload: lifebyte mismatch\n");
                   1327:                        return 0;
                   1328:                }
                   1329: #endif
                   1330: 
                   1331:                if (sainfo->pfs_group &&
                   1332:                   sainfo->pfs_group != approval->pfs_group) {
                   1333:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1334:                                 "Reload: PFS group mismatch\n");
                   1335:                        return 0;
                   1336:                }
                   1337:                break;
                   1338: 
                   1339:        case PROP_CHECK_EXACT:
                   1340:                if (sainfo->lifetime != approval->lifetime ||
                   1341: #if 0
                   1342:                        /* Lifebyte is deprecated, just ignore it
                   1343:                         */
                   1344:                    sainfo->lifebyte != approval->lifebyte ||
                   1345: #endif
                   1346:                    sainfo->pfs_group != iph2->approval->pfs_group) {
                   1347:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1348:                            "Reload: lifetime | pfs mismatch\n");
                   1349:                        return 0;
                   1350:                }
                   1351:                break;
                   1352: 
                   1353:        default:
                   1354:                plog(LLV_DEBUG, LOCATION, NULL,
                   1355:                         "Reload: Shouldn't be here !\n");
                   1356:                return 0;
                   1357:                break;
                   1358:        }
                   1359: 
                   1360:        for (alg = sainfo->algs[algclass_ipsec_auth]; alg; alg = alg->next) {
                   1361:                if (alg->alg == approval->head->head->authtype)
                   1362:                        break;
                   1363:        }
                   1364:        if (alg == NULL) {
                   1365:                plog(LLV_DEBUG, LOCATION, NULL,
                   1366:                         "Reload: alg == NULL (auth)\n");
                   1367:                return 0;
                   1368:        }
                   1369: 
                   1370:        found = 0;
                   1371:        for (alg = sainfo->algs[algclass_ipsec_enc];
                   1372:            (found == 0 && alg != NULL); alg = alg->next) {
                   1373:                plog(LLV_DEBUG, LOCATION, NULL,
                   1374:                         "Reload: next ph2 enc alg...\n");
                   1375: 
                   1376:                if (alg->alg != approval->head->head->trns_id){
                   1377:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1378:                                 "Reload: encmode mismatch (%d / %d)\n",
                   1379:                                 alg->alg, approval->head->head->trns_id);
                   1380:                        continue;
                   1381:                }
                   1382: 
                   1383:                switch (check_level){
                   1384:                /* PROP_CHECK_STRICT cannot happen here */
                   1385:                case PROP_CHECK_EXACT:
                   1386:                        if (alg->encklen != approval->head->head->encklen) {
                   1387:                                plog(LLV_DEBUG, LOCATION, NULL,
                   1388:                                         "Reload: enclen mismatch\n");
                   1389:                                continue;
                   1390:                        }
                   1391:                        break;
                   1392: 
                   1393:                case PROP_CHECK_CLAIM:
                   1394:                        /* FALLTHROUGH */
                   1395:                case PROP_CHECK_STRICT:
                   1396:                        if (alg->encklen > approval->head->head->encklen) {
                   1397:                                plog(LLV_DEBUG, LOCATION, NULL,
                   1398:                                         "Reload: enclen mismatch\n");
                   1399:                                continue;
                   1400:                        }
                   1401:                        break;
                   1402: 
                   1403:                default:
                   1404:                        plog(LLV_ERROR, LOCATION, NULL,
                   1405:                            "unexpected check_level\n");
                   1406:                        continue;
                   1407:                        break;
                   1408:                }
                   1409:                found = 1;
                   1410:        }
                   1411: 
                   1412:        if (!found){
                   1413:                plog(LLV_DEBUG, LOCATION, NULL,
                   1414:                         "Reload: No valid enc\n");
                   1415:                return 0;
                   1416:        }
                   1417: 
                   1418:        /*
                   1419:         * XXX comp
                   1420:         */
                   1421:        plog(LLV_DEBUG, LOCATION, NULL,
                   1422:                 "Reload: ph2 check ok\n");
                   1423: 
                   1424:        return 1;
                   1425: }
                   1426: 
                   1427: 
                   1428: static void
                   1429: remove_ph2(struct ph2handle *iph2)
                   1430: {
                   1431:        u_int32_t spis[2];
                   1432: 
                   1433:        if(iph2 == NULL)
                   1434:                return;
                   1435: 
                   1436:        plog(LLV_DEBUG, LOCATION, NULL,
                   1437:                 "Deleting a Ph2...\n");
                   1438: 
                   1439:        if (iph2->status == PHASE2ST_ESTABLISHED)
                   1440:                isakmp_info_send_d2(iph2);
                   1441: 
                   1442:        if(iph2->approval != NULL && iph2->approval->head != NULL){
                   1443:                spis[0]=iph2->approval->head->spi;
                   1444:                spis[1]=iph2->approval->head->spi_p;
                   1445: 
                   1446:                /* purge_ipsec_spi() will do all the work:
                   1447:                 * - delete SPIs in kernel
                   1448:                 * - delete generated SPD
                   1449:                 * - unbind / rem / del ph2
                   1450:                 */
                   1451:                purge_ipsec_spi(iph2->dst, iph2->approval->head->proto_id,
                   1452:                                                spis, 2);
                   1453:        }else{
                   1454:                remph2(iph2);
                   1455:                delph2(iph2);
                   1456:        }
                   1457: }
                   1458: 
                   1459: static void remove_ph1(struct ph1handle *iph1){
                   1460:        struct ph2handle *iph2, *iph2_next;
                   1461: 
                   1462:        if(iph1 == NULL)
                   1463:                return;
                   1464: 
                   1465:        plog(LLV_DEBUG, LOCATION, NULL,
                   1466:                 "Removing PH1...\n");
                   1467: 
                   1468:        if (iph1->status == PHASE1ST_ESTABLISHED ||
                   1469:            iph1->status == PHASE1ST_DYING) {
                   1470:                for (iph2 = LIST_FIRST(&iph1->ph2tree); iph2; iph2 = iph2_next) {
                   1471:                        iph2_next = LIST_NEXT(iph2, ph1bind);
                   1472:                        remove_ph2(iph2);
                   1473:                }
                   1474:                isakmp_info_send_d1(iph1);
                   1475:        }
                   1476:        iph1->status = PHASE1ST_EXPIRED;
                   1477:        /* directly call isakmp_ph1delete to avoid as possible a race
                   1478:         * condition where we'll try to access iph1->rmconf after it has
                   1479:         * freed
                   1480:         */
                   1481:        isakmp_ph1delete(iph1);
                   1482: }
                   1483: 
                   1484: 
                   1485: static int revalidate_ph1tree_rmconf(void)
                   1486: {
                   1487:        struct ph1handle *p, *next;
                   1488:        struct remoteconf *rmconf;
                   1489: 
                   1490:        for (p = LIST_FIRST(&ph1tree); p; p = next) {
                   1491:                next = LIST_NEXT(p, chain);
                   1492: 
                   1493:                if (p->status >= PHASE1ST_EXPIRED)
                   1494:                        continue;
                   1495:                if (p->rmconf == NULL)
                   1496:                        continue;
                   1497: 
                   1498:                rmconf = getrmconf_by_ph1(p);
                   1499:                if (rmconf == NULL || rmconf == RMCONF_ERR_MULTIPLE)
                   1500:                        remove_ph1(p);
                   1501:                else
                   1502:                        p->rmconf = rmconf;
                   1503:        }
                   1504: 
                   1505:        return 1;
                   1506: }
                   1507: 
                   1508: static int revalidate_ph2tree(void){
                   1509:        struct ph2handle *p, *next;
                   1510: 
                   1511:        for (p = LIST_FIRST(&ph2tree); p; p = next) {
                   1512:                next = LIST_NEXT(p, chain);
                   1513: 
                   1514:                if (p->status == PHASE2ST_EXPIRED)
                   1515:                        continue;
                   1516: 
                   1517:                if(!revalidate_ph2(p)){
                   1518:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1519:                                 "PH2 not validated, removing it\n");
                   1520:                        remove_ph2(p);
                   1521:                }
                   1522:        }
                   1523: 
                   1524:        return 1;
                   1525: }
                   1526: 
                   1527: int
                   1528: revalidate_ph12(void)
                   1529: {
                   1530: 
                   1531:        revalidate_ph1tree_rmconf();
                   1532:        revalidate_ph2tree();
                   1533: 
                   1534:        return 1;
                   1535: }
                   1536: 
                   1537: #ifdef ENABLE_HYBRID
                   1538: struct ph1handle *
                   1539: getph1bylogin(login)
                   1540:        char *login;
                   1541: {
                   1542:        struct ph1handle *p;
                   1543: 
                   1544:        LIST_FOREACH(p, &ph1tree, chain) {
                   1545:                if (p->mode_cfg == NULL)
                   1546:                        continue;
                   1547:                if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0)
                   1548:                        return p;
                   1549:        }
                   1550: 
                   1551:        return NULL;
                   1552: }
                   1553: 
                   1554: int
                   1555: purgeph1bylogin(login)
                   1556:        char *login;
                   1557: {
                   1558:        struct ph1handle *p;
                   1559:        int found = 0;
                   1560: 
                   1561:        LIST_FOREACH(p, &ph1tree, chain) {
                   1562:                if (p->mode_cfg == NULL)
                   1563:                        continue;
                   1564:                if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) {
                   1565:                        if (p->status >= PHASE1ST_EXPIRED)
                   1566:                                continue;
                   1567: 
                   1568:                        if (p->status >= PHASE1ST_ESTABLISHED)
                   1569:                                isakmp_info_send_d1(p);
                   1570:                        purge_remote(p);
                   1571:                        found++;
                   1572:                }
                   1573:        }
                   1574: 
                   1575:        return found;
                   1576: }
                   1577: #endif

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