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

1.1.1.2 ! misho       1: /*     $NetBSD: handler.c,v 1.39.2.1 2011/11/17 14:46:31 vanhu Exp $   */
1.1       misho       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: {
1.1.1.2 ! misho     614:        struct ph2handle *p, *next;
        !           615: 
        !           616:        for (p = LIST_FIRST(&ph2tree); p; p = next) {
        !           617:                next = LIST_NEXT(p, chain);
1.1       misho     618: 
                    619:                if (spid == p->spid &&
                    620:                    cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
                    621:                    cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH){
                    622:                        /* Sanity check to detect zombie handlers
                    623:                         * XXX Sould be done "somewhere" more interesting,
                    624:                         * because we have lots of getph2byxxxx(), but this one
                    625:                         * is called by pk_recvacquire(), so is the most important.
                    626:                         */
                    627:                        if(p->status < PHASE2ST_ESTABLISHED &&
                    628:                           p->retry_counter == 0
                    629:                           && p->sce.func == NULL && p->scr.func == NULL) {
                    630:                                plog(LLV_DEBUG, LOCATION, NULL,
                    631:                                         "Zombie ph2 found, expiring it\n");
                    632:                                isakmp_ph2expire(p);
                    633:                        }else
                    634:                                return p;
                    635:                }
                    636:        }
                    637: 
                    638:        return NULL;
                    639: }
                    640: 
                    641: struct ph2handle *
                    642: getph2bysaddr(src, dst)
                    643:        struct sockaddr *src, *dst;
                    644: {
                    645:        struct ph2handle *p;
                    646: 
                    647:        LIST_FOREACH(p, &ph2tree, chain) {
                    648:                if (cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
                    649:                    cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH)
                    650:                        return p;
                    651:        }
                    652: 
                    653:        return NULL;
                    654: }
                    655: 
                    656: /*
                    657:  * call by pk_recvexpire().
                    658:  */
                    659: struct ph2handle *
                    660: getph2bysaidx(src, dst, proto_id, spi)
                    661:        struct sockaddr *src, *dst;
                    662:        u_int proto_id;
                    663:        u_int32_t spi;
                    664: {
                    665:        struct ph2handle *iph2;
                    666:        struct saproto *pr;
                    667: 
                    668:        LIST_FOREACH(iph2, &ph2tree, chain) {
                    669:                if (iph2->proposal == NULL && iph2->approval == NULL)
                    670:                        continue;
                    671:                if (iph2->approval != NULL) {
                    672:                        for (pr = iph2->approval->head; pr != NULL;
                    673:                             pr = pr->next) {
                    674:                                if (proto_id != pr->proto_id)
                    675:                                        break;
                    676:                                if (spi == pr->spi || spi == pr->spi_p)
                    677:                                        return iph2;
                    678:                        }
                    679:                } else if (iph2->proposal != NULL) {
                    680:                        for (pr = iph2->proposal->head; pr != NULL;
                    681:                             pr = pr->next) {
                    682:                                if (proto_id != pr->proto_id)
                    683:                                        break;
                    684:                                if (spi == pr->spi)
                    685:                                        return iph2;
                    686:                        }
                    687:                }
                    688:        }
                    689: 
                    690:        return NULL;
                    691: }
                    692: 
                    693: /*
                    694:  * create new isakmp Phase 2 status record to handle isakmp in Phase2
                    695:  */
                    696: struct ph2handle *
                    697: newph2()
                    698: {
                    699:        struct ph2handle *iph2 = NULL;
                    700: 
                    701:        /* create new iph2 */
                    702:        iph2 = racoon_calloc(1, sizeof(*iph2));
                    703:        if (iph2 == NULL)
                    704:                return NULL;
                    705: 
                    706:        iph2->status = PHASE1ST_SPAWN;
                    707:        evt_list_init(&iph2->evt_listeners);
                    708: 
                    709:        return iph2;
                    710: }
                    711: 
                    712: /*
                    713:  * initialize ph2handle
                    714:  * NOTE: don't initialize src/dst.
                    715:  *       SPI in the proposal is cleared.
                    716:  */
                    717: void
                    718: initph2(iph2)
                    719:        struct ph2handle *iph2;
                    720: {
                    721:        evt_list_cleanup(&iph2->evt_listeners);
                    722:        unbindph12(iph2);
                    723: 
                    724:        sched_cancel(&iph2->sce);
                    725:        sched_cancel(&iph2->scr);
                    726: 
                    727:        VPTRINIT(iph2->sendbuf);
                    728:        VPTRINIT(iph2->msg1);
                    729: 
                    730:        /* clear spi, keep variables in the proposal */
                    731:        if (iph2->proposal) {
                    732:                struct saproto *pr;
                    733:                for (pr = iph2->proposal->head; pr != NULL; pr = pr->next)
                    734:                        pr->spi = 0;
                    735:        }
                    736: 
                    737:        /* clear approval */
                    738:        if (iph2->approval) {
                    739:                flushsaprop(iph2->approval);
                    740:                iph2->approval = NULL;
                    741:        }
                    742: 
                    743:        /* clear the generated policy */
                    744:        if (iph2->spidx_gen) {
                    745:                delsp_bothdir((struct policyindex *)iph2->spidx_gen);
                    746:                racoon_free(iph2->spidx_gen);
                    747:                iph2->spidx_gen = NULL;
                    748:        }
                    749: 
                    750:        if (iph2->pfsgrp) {
                    751:                oakley_dhgrp_free(iph2->pfsgrp);
                    752:                iph2->pfsgrp = NULL;
                    753:        }
                    754: 
                    755:        VPTRINIT(iph2->dhpriv);
                    756:        VPTRINIT(iph2->dhpub);
                    757:        VPTRINIT(iph2->dhpub_p);
                    758:        VPTRINIT(iph2->dhgxy);
                    759:        VPTRINIT(iph2->id);
                    760:        VPTRINIT(iph2->id_p);
                    761:        VPTRINIT(iph2->nonce);
                    762:        VPTRINIT(iph2->nonce_p);
                    763:        VPTRINIT(iph2->sa);
                    764:        VPTRINIT(iph2->sa_ret);
                    765: 
                    766:        if (iph2->ivm) {
                    767:                oakley_delivm(iph2->ivm);
                    768:                iph2->ivm = NULL;
                    769:        }
                    770: 
                    771: #ifdef ENABLE_NATT
                    772:        if (iph2->natoa_src) {
                    773:                racoon_free(iph2->natoa_src);
                    774:                iph2->natoa_src = NULL;
                    775:        }
                    776:        if (iph2->natoa_dst) {
                    777:                racoon_free(iph2->natoa_dst);
                    778:                iph2->natoa_dst = NULL;
                    779:        }
                    780: #endif
                    781: }
                    782: 
                    783: /*
                    784:  * delete new isakmp Phase 2 status record to handle isakmp in Phase2
                    785:  */
                    786: void
                    787: delph2(iph2)
                    788:        struct ph2handle *iph2;
                    789: {
                    790:        initph2(iph2);
                    791: 
                    792:        if (iph2->src) {
                    793:                racoon_free(iph2->src);
                    794:                iph2->src = NULL;
                    795:        }
                    796:        if (iph2->dst) {
                    797:                racoon_free(iph2->dst);
                    798:                iph2->dst = NULL;
                    799:        }
                    800:        if (iph2->sa_src) {
                    801:                racoon_free(iph2->sa_src);
                    802:                iph2->sa_src = NULL;
                    803:        }
                    804:        if (iph2->sa_dst) {
                    805:                racoon_free(iph2->sa_dst);
                    806:                iph2->sa_dst = NULL;
                    807:        }
                    808: #ifdef ENABLE_NATT
                    809:        if (iph2->natoa_src) {
                    810:                racoon_free(iph2->natoa_src);
                    811:                iph2->natoa_src = NULL;
                    812:        }
                    813:        if (iph2->natoa_dst) {
                    814:                racoon_free(iph2->natoa_dst);
                    815:                iph2->natoa_dst = NULL;
                    816:        }
                    817: #endif
                    818: 
                    819:        if (iph2->proposal) {
                    820:                flushsaprop(iph2->proposal);
                    821:                iph2->proposal = NULL;
                    822:        }
                    823: 
                    824:        racoon_free(iph2);
                    825: }
                    826: 
                    827: /*
                    828:  * create new isakmp Phase 2 status record to handle isakmp in Phase2
                    829:  */
                    830: int
                    831: insph2(iph2)
                    832:        struct ph2handle *iph2;
                    833: {
                    834:        LIST_INSERT_HEAD(&ph2tree, iph2, chain);
                    835: 
                    836:        return 0;
                    837: }
                    838: 
                    839: void
                    840: remph2(iph2)
                    841:        struct ph2handle *iph2;
                    842: {
                    843:        unbindph12(iph2);
                    844:        LIST_REMOVE(iph2, chain);
                    845: }
                    846: 
                    847: void
                    848: initph2tree()
                    849: {
                    850:        LIST_INIT(&ph2tree);
                    851: }
                    852: 
                    853: void
                    854: flushph2()
                    855: {
                    856:        struct ph2handle *p, *next;
                    857: 
                    858:        plog(LLV_DEBUG2, LOCATION, NULL,
                    859:                 "flushing all ph2 handlers...\n");
                    860: 
                    861:        for (p = LIST_FIRST(&ph2tree); p; p = next) {
                    862:                next = LIST_NEXT(p, chain);
                    863: 
                    864:                /* send delete information */
                    865:                if (p->status == PHASE2ST_ESTABLISHED){
                    866:                        plog(LLV_DEBUG2, LOCATION, NULL,
                    867:                                 "got a ph2 handler to flush...\n");
                    868:                        isakmp_info_send_d2(p);
                    869:                }else{
                    870:                        plog(LLV_DEBUG2, LOCATION, NULL,
                    871:                                 "skipping ph2 handler (state %d)\n", p->status);
                    872:                }
                    873: 
                    874:                delete_spd(p, 0);
                    875:                remph2(p);
                    876:                delph2(p);
                    877:        }
                    878: }
                    879: 
                    880: /*
                    881:  * Delete all Phase 2 handlers for this src/dst/proto.  This
                    882:  * is used during INITIAL-CONTACT processing (so no need to
                    883:  * send a message to the peer).
                    884:  */
                    885: void
                    886: deleteallph2(src, dst, proto_id)
                    887:        struct sockaddr *src, *dst;
                    888:        u_int proto_id;
                    889: {
                    890:        struct ph2handle *iph2, *next;
                    891:        struct saproto *pr;
                    892: 
                    893:        for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) {
                    894:                next = LIST_NEXT(iph2, chain);
                    895:                if (iph2->proposal == NULL && iph2->approval == NULL)
                    896:                        continue;
                    897:                if (iph2->approval != NULL) {
                    898:                        for (pr = iph2->approval->head; pr != NULL;
                    899:                             pr = pr->next) {
                    900:                                if (proto_id == pr->proto_id)
                    901:                                        goto zap_it;
                    902:                        }
                    903:                } else if (iph2->proposal != NULL) {
                    904:                        for (pr = iph2->proposal->head; pr != NULL;
                    905:                             pr = pr->next) {
                    906:                                if (proto_id == pr->proto_id)
                    907:                                        goto zap_it;
                    908:                        }
                    909:                }
                    910:                continue;
                    911:  zap_it:
                    912:                remph2(iph2);
                    913:                delph2(iph2);
                    914:        }
                    915: }
                    916: 
                    917: /* %%% */
                    918: void
                    919: bindph12(iph1, iph2)
                    920:        struct ph1handle *iph1;
                    921:        struct ph2handle *iph2;
                    922: {
                    923:        unbindph12(iph2);
                    924: 
                    925:        iph2->ph1 = iph1;
                    926:        iph1->ph2cnt++;
                    927:        LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind);
                    928: }
                    929: 
                    930: void
                    931: unbindph12(iph2)
                    932:        struct ph2handle *iph2;
                    933: {
                    934:        if (iph2->ph1 != NULL) {
                    935:                LIST_REMOVE(iph2, ph1bind);
                    936:                iph2->ph1->ph2cnt--;
                    937:                iph2->ph1 = NULL;
                    938:        }
                    939: }
                    940: 
                    941: /* %%% management contacted list */
                    942: /*
                    943:  * search contacted list.
                    944:  */
                    945: struct contacted *
                    946: getcontacted(remote)
                    947:        struct sockaddr *remote;
                    948: {
                    949:        struct contacted *p;
                    950: 
                    951:        LIST_FOREACH(p, &ctdtree, chain) {
                    952:                if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH)
                    953:                        return p;
                    954:        }
                    955: 
                    956:        return NULL;
                    957: }
                    958: 
                    959: /*
                    960:  * create new isakmp Phase 2 status record to handle isakmp in Phase2
                    961:  */
                    962: int
                    963: inscontacted(remote)
                    964:        struct sockaddr *remote;
                    965: {
                    966:        struct contacted *new;
                    967: 
                    968:        /* create new iph2 */
                    969:        new = racoon_calloc(1, sizeof(*new));
                    970:        if (new == NULL)
                    971:                return -1;
                    972: 
                    973:        new->remote = dupsaddr(remote);
                    974:        if (new->remote == NULL) {
                    975:                plog(LLV_ERROR, LOCATION, NULL,
                    976:                        "failed to allocate buffer.\n");
                    977:                racoon_free(new);
                    978:                return -1;
                    979:        }
                    980: 
                    981:        LIST_INSERT_HEAD(&ctdtree, new, chain);
                    982: 
                    983:        return 0;
                    984: }
                    985: 
                    986: void
                    987: remcontacted(remote)
                    988:        struct sockaddr *remote;
                    989: {
1.1.1.2 ! misho     990:        struct contacted *p, *next;
        !           991: 
        !           992:        for (p = LIST_FIRST(&ctdtree); p; p = next) {
        !           993:                next = LIST_NEXT(p, chain);
1.1       misho     994: 
                    995:                if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH) {
                    996:                        LIST_REMOVE(p, chain);
                    997:                        racoon_free(p->remote);
                    998:                        racoon_free(p);
                    999:                        break;
                   1000:                }
                   1001:        }       
                   1002: }
                   1003: 
                   1004: void
                   1005: initctdtree()
                   1006: {
                   1007:        LIST_INIT(&ctdtree);
                   1008: }
                   1009: 
                   1010: /*
                   1011:  * check the response has been sent to the peer.  when not, simply reply
                   1012:  * the buffered packet to the peer.
                   1013:  * OUT:
                   1014:  *      0:     the packet is received at the first time.
                   1015:  *      1:     the packet was processed before.
                   1016:  *      2:     the packet was processed before, but the address mismatches.
                   1017:  *     -1:     error happened.
                   1018:  */
                   1019: int
                   1020: check_recvdpkt(remote, local, rbuf)
                   1021:        struct sockaddr *remote, *local;
                   1022:        vchar_t *rbuf;
                   1023: {
                   1024:        vchar_t *hash;
                   1025:        struct recvdpkt *r;
                   1026:        struct timeval now, diff;
                   1027:        int len, s;
                   1028: 
                   1029:        hash = eay_md5_one(rbuf);
                   1030:        if (!hash) {
                   1031:                plog(LLV_ERROR, LOCATION, NULL,
                   1032:                        "failed to allocate buffer.\n");
                   1033:                return -1;
                   1034:        }
                   1035: 
                   1036:        LIST_FOREACH(r, &rcptree, chain) {
                   1037:                if (memcmp(hash->v, r->hash->v, r->hash->l) == 0)
                   1038:                        break;
                   1039:        }
                   1040:        vfree(hash);
                   1041: 
                   1042:        /* this is the first time to receive the packet */
                   1043:        if (r == NULL)
                   1044:                return 0;
                   1045: 
                   1046:        /*
                   1047:         * the packet was processed before, but the remote address mismatches.
                   1048:         */
                   1049:        if (cmpsaddr(remote, r->remote) != CMPSADDR_MATCH)
                   1050:                return 2;
                   1051: 
                   1052:        /*
                   1053:         * it should not check the local address because the packet
                   1054:         * may arrive at other interface.
                   1055:         */
                   1056: 
                   1057:        /* check the previous time to send */
                   1058:        sched_get_monotonic_time(&now);
                   1059:        timersub(&now, &r->time_send, &diff);
                   1060:        if (diff.tv_sec == 0) {
                   1061:                plog(LLV_WARNING, LOCATION, NULL,
                   1062:                        "the packet retransmitted in a short time from %s\n",
                   1063:                        saddr2str(remote));
                   1064:                /*XXX should it be error ? */
                   1065:        }
                   1066: 
                   1067:        /* select the socket to be sent */
                   1068:        s = myaddr_getfd(r->local);
                   1069:        if (s == -1)
                   1070:                return -1;
                   1071: 
                   1072:        /* resend the packet if needed */
                   1073:        len = sendfromto(s, r->sendbuf->v, r->sendbuf->l,
                   1074:                        r->local, r->remote, lcconf->count_persend);
                   1075:        if (len == -1) {
                   1076:                plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
                   1077:                return -1;
                   1078:        }
                   1079: 
                   1080:        /* check the retry counter */
                   1081:        r->retry_counter--;
                   1082:        if (r->retry_counter <= 0) {
                   1083:                rem_recvdpkt(r);
                   1084:                del_recvdpkt(r);
                   1085:                plog(LLV_DEBUG, LOCATION, NULL,
                   1086:                        "deleted the retransmission packet to %s.\n",
                   1087:                        saddr2str(remote));
                   1088:        } else
                   1089:                r->time_send = now;
                   1090: 
                   1091:        return 1;
                   1092: }
                   1093: 
                   1094: /*
                   1095:  * adding a hash of received packet into the received list.
                   1096:  */
                   1097: int
                   1098: add_recvdpkt(remote, local, sbuf, rbuf)
                   1099:        struct sockaddr *remote, *local;
                   1100:        vchar_t *sbuf, *rbuf;
                   1101: {
                   1102:        struct recvdpkt *new = NULL;
                   1103: 
                   1104:        if (lcconf->retry_counter == 0) {
                   1105:                /* no need to add it */
                   1106:                return 0;
                   1107:        }
                   1108: 
                   1109:        new = racoon_calloc(1, sizeof(*new));
                   1110:        if (!new) {
                   1111:                plog(LLV_ERROR, LOCATION, NULL,
                   1112:                        "failed to allocate buffer.\n");
                   1113:                return -1;
                   1114:        }
                   1115: 
                   1116:        new->hash = eay_md5_one(rbuf);
                   1117:        if (!new->hash) {
                   1118:                plog(LLV_ERROR, LOCATION, NULL,
                   1119:                        "failed to allocate buffer.\n");
                   1120:                del_recvdpkt(new);
                   1121:                return -1;
                   1122:        }
                   1123:        new->remote = dupsaddr(remote);
                   1124:        if (new->remote == NULL) {
                   1125:                plog(LLV_ERROR, LOCATION, NULL,
                   1126:                        "failed to allocate buffer.\n");
                   1127:                del_recvdpkt(new);
                   1128:                return -1;
                   1129:        }
                   1130:        new->local = dupsaddr(local);
                   1131:        if (new->local == NULL) {
                   1132:                plog(LLV_ERROR, LOCATION, NULL,
                   1133:                        "failed to allocate buffer.\n");
                   1134:                del_recvdpkt(new);
                   1135:                return -1;
                   1136:        }
                   1137:        new->sendbuf = vdup(sbuf);
                   1138:        if (new->sendbuf == NULL) {
                   1139:                plog(LLV_ERROR, LOCATION, NULL,
                   1140:                        "failed to allocate buffer.\n");
                   1141:                del_recvdpkt(new);
                   1142:                return -1;
                   1143:        }
                   1144: 
                   1145:        new->retry_counter = lcconf->retry_counter;
                   1146:        sched_get_monotonic_time(&new->time_send);
                   1147: 
                   1148:        LIST_INSERT_HEAD(&rcptree, new, chain);
                   1149: 
                   1150:        return 0;
                   1151: }
                   1152: 
                   1153: void
                   1154: del_recvdpkt(r)
                   1155:        struct recvdpkt *r;
                   1156: {
                   1157:        if (r->remote)
                   1158:                racoon_free(r->remote);
                   1159:        if (r->local)
                   1160:                racoon_free(r->local);
                   1161:        if (r->hash)
                   1162:                vfree(r->hash);
                   1163:        if (r->sendbuf)
                   1164:                vfree(r->sendbuf);
                   1165:        racoon_free(r);
                   1166: }
                   1167: 
                   1168: void
                   1169: rem_recvdpkt(r)
                   1170:        struct recvdpkt *r;
                   1171: {
                   1172:        LIST_REMOVE(r, chain);
                   1173: }
                   1174: 
                   1175: static void
                   1176: sweep_recvdpkt(dummy)
                   1177:        struct sched *dummy;
                   1178: {
                   1179:        struct recvdpkt *r, *next;
                   1180:        struct timeval now, diff, sweep;
                   1181: 
                   1182:        sched_get_monotonic_time(&now);
                   1183: 
                   1184:        /* calculate sweep time; delete entries older than this */
                   1185:        diff.tv_sec = lcconf->retry_counter * lcconf->retry_interval;
                   1186:        diff.tv_usec = 0;
                   1187:        timersub(&now, &diff, &sweep);
                   1188: 
                   1189:        for (r = LIST_FIRST(&rcptree); r; r = next) {
                   1190:                next = LIST_NEXT(r, chain);
                   1191: 
                   1192:                if (timercmp(&r->time_send, &sweep, <)) {
                   1193:                        rem_recvdpkt(r);
                   1194:                        del_recvdpkt(r);
                   1195:                }
                   1196:        }
                   1197: 
                   1198:        sched_schedule(&sc_sweep, diff.tv_sec, sweep_recvdpkt);
                   1199: }
                   1200: 
                   1201: void
                   1202: init_recvdpkt()
                   1203: {
                   1204:        time_t lt = lcconf->retry_counter * lcconf->retry_interval;
                   1205: 
                   1206:        LIST_INIT(&rcptree);
                   1207: 
                   1208:        sched_schedule(&sc_sweep, lt, sweep_recvdpkt);
                   1209: }
                   1210: 
                   1211: #ifdef ENABLE_HYBRID
                   1212: /*
                   1213:  * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
                   1214:  * This should be in isakmp_cfg.c but ph1tree being private, it must be there
                   1215:  */
                   1216: int
                   1217: exclude_cfg_addr(addr)
                   1218:        const struct sockaddr *addr;
                   1219: {
                   1220:        struct ph1handle *p;
                   1221:        struct sockaddr_in *sin;
                   1222: 
                   1223:        LIST_FOREACH(p, &ph1tree, chain) {
                   1224:                if ((p->mode_cfg != NULL) &&
                   1225:                    (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) &&
                   1226:                    (addr->sa_family == AF_INET)) {
                   1227:                        sin = (struct sockaddr_in *)addr;
                   1228:                        if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr)
                   1229:                                return 0;
                   1230:                }
                   1231:        }
                   1232: 
                   1233:        return 1;
                   1234: }
                   1235: #endif
                   1236: 
                   1237: 
                   1238: 
                   1239: /*
                   1240:  * Reload conf code
                   1241:  */
                   1242: static int revalidate_ph2(struct ph2handle *iph2){
                   1243:        struct sainfoalg *alg;
                   1244:        int found, check_level;
                   1245:        struct sainfo *sainfo;
                   1246:        struct saprop *approval;
                   1247:        struct ph1handle *iph1;
                   1248: 
                   1249:        /*
                   1250:         * Get the new sainfo using values of the old one
                   1251:         */
                   1252:        if (iph2->sainfo != NULL) {
                   1253:                iph2->sainfo = getsainfo(iph2->sainfo->idsrc,
                   1254:                                          iph2->sainfo->iddst, iph2->sainfo->id_i,
                   1255:                                          NULL, iph2->sainfo->remoteid);
                   1256:        }
                   1257:        approval = iph2->approval;
                   1258:        sainfo = iph2->sainfo;
                   1259: 
                   1260:        if (sainfo == NULL) {
                   1261:                /*
                   1262:                 * Sainfo has been removed
                   1263:                 */
                   1264:                plog(LLV_DEBUG, LOCATION, NULL,
                   1265:                         "Reload: No sainfo for ph2\n");
                   1266:                return 0;
                   1267:        }
                   1268: 
                   1269:        if (approval == NULL) {
                   1270:                /*
                   1271:                 * XXX why do we have a NULL approval sometimes ???
                   1272:                 */
                   1273:                plog(LLV_DEBUG, LOCATION, NULL,
                   1274:                         "No approval found !\n");
                   1275:                return 0;
                   1276:        }
                   1277: 
                   1278:        /*
                   1279:         * Don't care about proposals, should we do something ?
                   1280:         * We have to keep iph2->proposal valid at least for initiator,
                   1281:         * for pk_sendgetspi()
                   1282:         */
                   1283: 
                   1284:        plog(LLV_DEBUG, LOCATION, NULL, "active single bundle:\n");
                   1285:        printsaprop0(LLV_DEBUG, approval);
                   1286: 
                   1287:        /*
                   1288:         * Validate approval against sainfo
                   1289:         * Note: we must have an updated ph1->rmconf before doing that,
                   1290:         * we'll set check_level to EXACT if we don't have a ph1
                   1291:         * XXX try tu find the new remote section to get the new check level ?
                   1292:         * XXX lifebyte
                   1293:         */
                   1294:        if (iph2->ph1 != NULL)
                   1295:                iph1=iph2->ph1;
                   1296:        else
                   1297:                iph1=getph1byaddr(iph2->src, iph2->dst, 0);
                   1298: 
                   1299:        if(iph1 != NULL && iph1->rmconf != NULL) {
                   1300:                check_level = iph1->rmconf->pcheck_level;
                   1301:        } else {
                   1302:                if(iph1 != NULL)
                   1303:                        plog(LLV_DEBUG, LOCATION, NULL, "No phase1 rmconf found !\n");
                   1304:                else
                   1305:                        plog(LLV_DEBUG, LOCATION, NULL, "No phase1 found !\n");
                   1306:                check_level = PROP_CHECK_EXACT;
                   1307:        }
                   1308: 
                   1309:        switch (check_level) {
                   1310:        case PROP_CHECK_OBEY:
                   1311:                plog(LLV_DEBUG, LOCATION, NULL,
                   1312:                         "Reload: OBEY for ph2, ok\n");
                   1313:                return 1;
                   1314:                break;
                   1315: 
                   1316:        case PROP_CHECK_STRICT:
                   1317:                /* FALLTHROUGH */
                   1318:        case PROP_CHECK_CLAIM:
                   1319:                if (sainfo->lifetime < approval->lifetime) {
                   1320:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1321:                                 "Reload: lifetime mismatch\n");
                   1322:                        return 0;
                   1323:                }
                   1324: 
                   1325: #if 0
                   1326:                /* Lifebyte is deprecated, just ignore it
                   1327:                 */
                   1328:                if (sainfo->lifebyte < approval->lifebyte) {
                   1329:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1330:                                 "Reload: lifebyte mismatch\n");
                   1331:                        return 0;
                   1332:                }
                   1333: #endif
                   1334: 
                   1335:                if (sainfo->pfs_group &&
                   1336:                   sainfo->pfs_group != approval->pfs_group) {
                   1337:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1338:                                 "Reload: PFS group mismatch\n");
                   1339:                        return 0;
                   1340:                }
                   1341:                break;
                   1342: 
                   1343:        case PROP_CHECK_EXACT:
                   1344:                if (sainfo->lifetime != approval->lifetime ||
                   1345: #if 0
                   1346:                        /* Lifebyte is deprecated, just ignore it
                   1347:                         */
                   1348:                    sainfo->lifebyte != approval->lifebyte ||
                   1349: #endif
                   1350:                    sainfo->pfs_group != iph2->approval->pfs_group) {
                   1351:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1352:                            "Reload: lifetime | pfs mismatch\n");
                   1353:                        return 0;
                   1354:                }
                   1355:                break;
                   1356: 
                   1357:        default:
                   1358:                plog(LLV_DEBUG, LOCATION, NULL,
                   1359:                         "Reload: Shouldn't be here !\n");
                   1360:                return 0;
                   1361:                break;
                   1362:        }
                   1363: 
                   1364:        for (alg = sainfo->algs[algclass_ipsec_auth]; alg; alg = alg->next) {
                   1365:                if (alg->alg == approval->head->head->authtype)
                   1366:                        break;
                   1367:        }
                   1368:        if (alg == NULL) {
                   1369:                plog(LLV_DEBUG, LOCATION, NULL,
                   1370:                         "Reload: alg == NULL (auth)\n");
                   1371:                return 0;
                   1372:        }
                   1373: 
                   1374:        found = 0;
                   1375:        for (alg = sainfo->algs[algclass_ipsec_enc];
                   1376:            (found == 0 && alg != NULL); alg = alg->next) {
                   1377:                plog(LLV_DEBUG, LOCATION, NULL,
                   1378:                         "Reload: next ph2 enc alg...\n");
                   1379: 
                   1380:                if (alg->alg != approval->head->head->trns_id){
                   1381:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1382:                                 "Reload: encmode mismatch (%d / %d)\n",
                   1383:                                 alg->alg, approval->head->head->trns_id);
                   1384:                        continue;
                   1385:                }
                   1386: 
                   1387:                switch (check_level){
                   1388:                /* PROP_CHECK_STRICT cannot happen here */
                   1389:                case PROP_CHECK_EXACT:
                   1390:                        if (alg->encklen != approval->head->head->encklen) {
                   1391:                                plog(LLV_DEBUG, LOCATION, NULL,
                   1392:                                         "Reload: enclen mismatch\n");
                   1393:                                continue;
                   1394:                        }
                   1395:                        break;
                   1396: 
                   1397:                case PROP_CHECK_CLAIM:
                   1398:                        /* FALLTHROUGH */
                   1399:                case PROP_CHECK_STRICT:
                   1400:                        if (alg->encklen > approval->head->head->encklen) {
                   1401:                                plog(LLV_DEBUG, LOCATION, NULL,
                   1402:                                         "Reload: enclen mismatch\n");
                   1403:                                continue;
                   1404:                        }
                   1405:                        break;
                   1406: 
                   1407:                default:
                   1408:                        plog(LLV_ERROR, LOCATION, NULL,
                   1409:                            "unexpected check_level\n");
                   1410:                        continue;
                   1411:                        break;
                   1412:                }
                   1413:                found = 1;
                   1414:        }
                   1415: 
                   1416:        if (!found){
                   1417:                plog(LLV_DEBUG, LOCATION, NULL,
                   1418:                         "Reload: No valid enc\n");
                   1419:                return 0;
                   1420:        }
                   1421: 
                   1422:        /*
                   1423:         * XXX comp
                   1424:         */
                   1425:        plog(LLV_DEBUG, LOCATION, NULL,
                   1426:                 "Reload: ph2 check ok\n");
                   1427: 
                   1428:        return 1;
                   1429: }
                   1430: 
                   1431: 
                   1432: static void
                   1433: remove_ph2(struct ph2handle *iph2)
                   1434: {
                   1435:        u_int32_t spis[2];
                   1436: 
                   1437:        if(iph2 == NULL)
                   1438:                return;
                   1439: 
                   1440:        plog(LLV_DEBUG, LOCATION, NULL,
                   1441:                 "Deleting a Ph2...\n");
                   1442: 
                   1443:        if (iph2->status == PHASE2ST_ESTABLISHED)
                   1444:                isakmp_info_send_d2(iph2);
                   1445: 
                   1446:        if(iph2->approval != NULL && iph2->approval->head != NULL){
                   1447:                spis[0]=iph2->approval->head->spi;
                   1448:                spis[1]=iph2->approval->head->spi_p;
                   1449: 
                   1450:                /* purge_ipsec_spi() will do all the work:
                   1451:                 * - delete SPIs in kernel
                   1452:                 * - delete generated SPD
                   1453:                 * - unbind / rem / del ph2
                   1454:                 */
                   1455:                purge_ipsec_spi(iph2->dst, iph2->approval->head->proto_id,
                   1456:                                                spis, 2);
                   1457:        }else{
                   1458:                remph2(iph2);
                   1459:                delph2(iph2);
                   1460:        }
                   1461: }
                   1462: 
                   1463: static void remove_ph1(struct ph1handle *iph1){
                   1464:        struct ph2handle *iph2, *iph2_next;
                   1465: 
                   1466:        if(iph1 == NULL)
                   1467:                return;
                   1468: 
                   1469:        plog(LLV_DEBUG, LOCATION, NULL,
                   1470:                 "Removing PH1...\n");
                   1471: 
                   1472:        if (iph1->status == PHASE1ST_ESTABLISHED ||
                   1473:            iph1->status == PHASE1ST_DYING) {
                   1474:                for (iph2 = LIST_FIRST(&iph1->ph2tree); iph2; iph2 = iph2_next) {
                   1475:                        iph2_next = LIST_NEXT(iph2, ph1bind);
                   1476:                        remove_ph2(iph2);
                   1477:                }
                   1478:                isakmp_info_send_d1(iph1);
                   1479:        }
                   1480:        iph1->status = PHASE1ST_EXPIRED;
                   1481:        /* directly call isakmp_ph1delete to avoid as possible a race
                   1482:         * condition where we'll try to access iph1->rmconf after it has
                   1483:         * freed
                   1484:         */
                   1485:        isakmp_ph1delete(iph1);
                   1486: }
                   1487: 
                   1488: 
                   1489: static int revalidate_ph1tree_rmconf(void)
                   1490: {
                   1491:        struct ph1handle *p, *next;
                   1492:        struct remoteconf *rmconf;
                   1493: 
                   1494:        for (p = LIST_FIRST(&ph1tree); p; p = next) {
                   1495:                next = LIST_NEXT(p, chain);
                   1496: 
                   1497:                if (p->status >= PHASE1ST_EXPIRED)
                   1498:                        continue;
                   1499:                if (p->rmconf == NULL)
                   1500:                        continue;
                   1501: 
                   1502:                rmconf = getrmconf_by_ph1(p);
                   1503:                if (rmconf == NULL || rmconf == RMCONF_ERR_MULTIPLE)
                   1504:                        remove_ph1(p);
                   1505:                else
                   1506:                        p->rmconf = rmconf;
                   1507:        }
                   1508: 
                   1509:        return 1;
                   1510: }
                   1511: 
                   1512: static int revalidate_ph2tree(void){
                   1513:        struct ph2handle *p, *next;
                   1514: 
                   1515:        for (p = LIST_FIRST(&ph2tree); p; p = next) {
                   1516:                next = LIST_NEXT(p, chain);
                   1517: 
                   1518:                if (p->status == PHASE2ST_EXPIRED)
                   1519:                        continue;
                   1520: 
                   1521:                if(!revalidate_ph2(p)){
                   1522:                        plog(LLV_DEBUG, LOCATION, NULL,
                   1523:                                 "PH2 not validated, removing it\n");
                   1524:                        remove_ph2(p);
                   1525:                }
                   1526:        }
                   1527: 
                   1528:        return 1;
                   1529: }
                   1530: 
                   1531: int
                   1532: revalidate_ph12(void)
                   1533: {
                   1534: 
                   1535:        revalidate_ph1tree_rmconf();
                   1536:        revalidate_ph2tree();
                   1537: 
                   1538:        return 1;
                   1539: }
                   1540: 
                   1541: #ifdef ENABLE_HYBRID
                   1542: struct ph1handle *
                   1543: getph1bylogin(login)
                   1544:        char *login;
                   1545: {
                   1546:        struct ph1handle *p;
                   1547: 
                   1548:        LIST_FOREACH(p, &ph1tree, chain) {
                   1549:                if (p->mode_cfg == NULL)
                   1550:                        continue;
                   1551:                if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0)
                   1552:                        return p;
                   1553:        }
                   1554: 
                   1555:        return NULL;
                   1556: }
                   1557: 
                   1558: int
                   1559: purgeph1bylogin(login)
                   1560:        char *login;
                   1561: {
1.1.1.2 ! misho    1562:        struct ph1handle *p, *next;
1.1       misho    1563:        int found = 0;
                   1564: 
1.1.1.2 ! misho    1565:        for (p = LIST_FIRST(&ph1tree); p; p = next) {
        !          1566:                next = LIST_NEXT(p, chain);
        !          1567: 
1.1       misho    1568:                if (p->mode_cfg == NULL)
                   1569:                        continue;
                   1570:                if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) {
                   1571:                        if (p->status >= PHASE1ST_EXPIRED)
                   1572:                                continue;
                   1573: 
                   1574:                        if (p->status >= PHASE1ST_ESTABLISHED)
                   1575:                                isakmp_info_send_d1(p);
                   1576:                        purge_remote(p);
                   1577:                        found++;
                   1578:                }
                   1579:        }
                   1580: 
                   1581:        return found;
                   1582: }
                   1583: #endif

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