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