1 /* $NetBSD: handler.c,v 1.41 2012/01/01 15:57:31 tteras Exp $ */ 2 3 /* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */ 4 5 /* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "config.h" 35 36 #include <sys/types.h> 37 #include <sys/param.h> 38 #include <sys/socket.h> 39 40 #include <stdlib.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <time.h> 44 #include <errno.h> 45 46 #include "var.h" 47 #include "misc.h" 48 #include "vmbuf.h" 49 #include "plog.h" 50 #include "sockmisc.h" 51 #include "debug.h" 52 53 #ifdef ENABLE_HYBRID 54 #include <resolv.h> 55 #endif 56 57 #include "schedule.h" 58 #include "grabmyaddr.h" 59 #include "algorithm.h" 60 #include "crypto_openssl.h" 61 #include "policy.h" 62 #include "proposal.h" 63 #include "isakmp_var.h" 64 #include "evt.h" 65 #include "isakmp.h" 66 #ifdef ENABLE_HYBRID 67 #include "isakmp_xauth.h" 68 #include "isakmp_cfg.h" 69 #endif 70 #include "isakmp_inf.h" 71 #include "oakley.h" 72 #include "remoteconf.h" 73 #include "localconf.h" 74 #include "handler.h" 75 #include "gcmalloc.h" 76 #include "nattraversal.h" 77 78 #include "sainfo.h" 79 80 #ifdef HAVE_GSSAPI 81 #include "gssapi.h" 82 #endif 83 84 static LIST_HEAD(_ph1tree_, ph1handle) ph1tree; 85 static LIST_HEAD(_ph2tree_, ph2handle) ph2tree; 86 static LIST_HEAD(_ctdtree_, contacted) ctdtree; 87 static LIST_HEAD(_rcptree_, recvdpkt) rcptree; 88 static struct sched sc_sweep = SCHED_INITIALIZER(); 89 90 static void del_recvdpkt __P((struct recvdpkt *)); 91 static void rem_recvdpkt __P((struct recvdpkt *)); 92 93 /* 94 * functions about management of the isakmp status table 95 */ 96 /* %%% management phase 1 handler */ 97 /* 98 * search for isakmpsa handler with isakmp index. 99 */ 100 101 extern caddr_t val2str(const char *, size_t); 102 103 /* 104 * Enumerate the Phase 1 tree. 105 * If enum_func() internally return a non-zero value, this specific 106 * error value is returned. 0 is returned if everything went right. 107 * 108 * Note that it is ok for enum_func() to call insph1(). Those inserted 109 * Phase 1 will not interfere with current enumeration process. 110 */ 111 int 112 enumph1(sel, enum_func, enum_arg) 113 struct ph1selector *sel; 114 int (* enum_func)(struct ph1handle *iph1, void *arg); 115 void *enum_arg; 116 { 117 struct ph1handle *p; 118 int ret; 119 120 LIST_FOREACH(p, &ph1tree, chain) { 121 if (sel != NULL) { 122 if (sel->local != NULL && 123 cmpsaddr(sel->local, p->local) > CMPSADDR_WILDPORT_MATCH) 124 continue; 125 126 if (sel->remote != NULL && 127 cmpsaddr(sel->remote, p->remote) > CMPSADDR_WILDPORT_MATCH) 128 continue; 129 } 130 131 if ((ret = enum_func(p, enum_arg)) != 0) 132 return ret; 133 } 134 135 return 0; 136 } 137 138 struct ph1handle * 139 getph1byindex(index) 140 isakmp_index *index; 141 { 142 struct ph1handle *p; 143 144 LIST_FOREACH(p, &ph1tree, chain) { 145 if (p->status >= PHASE1ST_EXPIRED) 146 continue; 147 if (memcmp(&p->index, index, sizeof(*index)) == 0) 148 return p; 149 } 150 151 return NULL; 152 } 153 154 155 /* 156 * search for isakmp handler by i_ck in index. 157 */ 158 struct ph1handle * 159 getph1byindex0(index) 160 isakmp_index *index; 161 { 162 struct ph1handle *p; 163 164 LIST_FOREACH(p, &ph1tree, chain) { 165 if (p->status >= PHASE1ST_EXPIRED) 166 continue; 167 if (memcmp(&p->index, index, sizeof(cookie_t)) == 0) 168 return p; 169 } 170 171 return NULL; 172 } 173 174 /* 175 * search for isakmpsa handler by source and remote address. 176 * don't use port number to search because this function search 177 * with phase 2's destinaion. 178 */ 179 struct ph1handle * 180 getph1(ph1hint, local, remote, flags) 181 struct ph1handle *ph1hint; 182 struct sockaddr *local, *remote; 183 int flags; 184 { 185 struct ph1handle *p; 186 187 plog(LLV_DEBUG2, LOCATION, NULL, "getph1: start\n"); 188 plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local)); 189 plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote)); 190 191 LIST_FOREACH(p, &ph1tree, chain) { 192 if (p->status >= PHASE1ST_DYING) 193 continue; 194 195 plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local)); 196 plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote)); 197 198 if ((flags & GETPH1_F_ESTABLISHED) && 199 (p->status != PHASE1ST_ESTABLISHED)) { 200 plog(LLV_DEBUG2, LOCATION, NULL, 201 "status %d, skipping\n", p->status); 202 continue; 203 } 204 205 if (local != NULL && cmpsaddr(local, p->local) == CMPSADDR_MISMATCH) 206 continue; 207 208 if (remote != NULL && cmpsaddr(remote, p->remote) == CMPSADDR_MISMATCH) 209 continue; 210 211 if (ph1hint != NULL) { 212 if (ph1hint->id && ph1hint->id->l && p->id && p->id->l && 213 (ph1hint->id->l != p->id->l || 214 memcmp(ph1hint->id->v, p->id->v, p->id->l) != 0)) { 215 plog(LLV_DEBUG2, LOCATION, NULL, 216 "local identity does not 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 not match hint\n"); 225 continue; 226 } 227 } 228 229 plog(LLV_DEBUG2, LOCATION, NULL, "matched\n"); 230 return p; 231 } 232 233 plog(LLV_DEBUG2, LOCATION, NULL, "no match\n"); 234 235 return NULL; 236 } 237 238 int 239 resolveph1rmconf(iph1) 240 struct ph1handle *iph1; 241 { 242 struct remoteconf *rmconf; 243 244 /* INITIATOR is always expected to know the exact rmconf. */ 245 if (iph1->side == INITIATOR) 246 return 0; 247 248 rmconf = getrmconf_by_ph1(iph1); 249 if (rmconf == NULL) 250 return -1; 251 if (rmconf == RMCONF_ERR_MULTIPLE) 252 return 1; 253 254 if (iph1->rmconf != NULL) { 255 if (rmconf != iph1->rmconf) { 256 plog(LLV_ERROR, LOCATION, NULL, 257 "unexpected rmconf switch; killing ph1\n"); 258 return -1; 259 } 260 } else { 261 iph1->rmconf = rmconf; 262 } 263 264 return 0; 265 } 266 267 268 /* 269 * move phase2s from old_iph1 to new_iph1 270 */ 271 void 272 migrate_ph12(old_iph1, new_iph1) 273 struct ph1handle *old_iph1, *new_iph1; 274 { 275 struct ph2handle *p, *next; 276 277 /* Relocate phase2s to better phase1s or request a new phase1. */ 278 for (p = LIST_FIRST(&old_iph1->ph2tree); p; p = next) { 279 next = LIST_NEXT(p, ph1bind); 280 281 if (p->status != PHASE2ST_ESTABLISHED) 282 continue; 283 284 unbindph12(p); 285 bindph12(new_iph1, p); 286 } 287 } 288 289 /* 290 * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1 291 */ 292 void migrate_dying_ph12(iph1) 293 struct ph1handle *iph1; 294 { 295 struct ph1handle *p; 296 297 LIST_FOREACH(p, &ph1tree, chain) { 298 if (p == iph1) 299 continue; 300 if (p->status < PHASE1ST_DYING) 301 continue; 302 303 if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH 304 && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH) 305 migrate_ph12(p, iph1); 306 } 307 } 308 309 310 /* 311 * dump isakmp-sa 312 */ 313 vchar_t * 314 dumpph1() 315 { 316 struct ph1handle *iph1; 317 struct ph1dump *pd; 318 int cnt = 0; 319 vchar_t *buf; 320 321 /* get length of buffer */ 322 LIST_FOREACH(iph1, &ph1tree, chain) 323 cnt++; 324 325 buf = vmalloc(cnt * sizeof(struct ph1dump)); 326 if (buf == NULL) { 327 plog(LLV_ERROR, LOCATION, NULL, 328 "failed to get buffer\n"); 329 return NULL; 330 } 331 pd = (struct ph1dump *)buf->v; 332 333 LIST_FOREACH(iph1, &ph1tree, chain) { 334 memcpy(&pd->index, &iph1->index, sizeof(iph1->index)); 335 pd->status = iph1->status; 336 pd->side = iph1->side; 337 memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote)); 338 memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local)); 339 pd->version = iph1->version; 340 pd->etype = iph1->etype; 341 pd->created = iph1->created; 342 pd->ph2cnt = iph1->ph2cnt; 343 pd++; 344 } 345 346 return buf; 347 } 348 349 /* 350 * create new isakmp Phase 1 status record to handle isakmp in Phase1 351 */ 352 struct ph1handle * 353 newph1() 354 { 355 struct ph1handle *iph1; 356 357 /* create new iph1 */ 358 iph1 = racoon_calloc(1, sizeof(*iph1)); 359 if (iph1 == NULL) 360 return NULL; 361 362 iph1->status = PHASE1ST_SPAWN; 363 364 #ifdef ENABLE_DPD 365 iph1->dpd_support = 0; 366 iph1->dpd_seq = 0; 367 iph1->dpd_fails = 0; 368 #endif 369 evt_list_init(&iph1->evt_listeners); 370 371 return iph1; 372 } 373 374 /* 375 * delete new isakmp Phase 1 status record to handle isakmp in Phase1 376 */ 377 void 378 delph1(iph1) 379 struct ph1handle *iph1; 380 { 381 if (iph1 == NULL) 382 return; 383 384 /* SA down shell script hook */ 385 script_hook(iph1, SCRIPT_PHASE1_DOWN); 386 evt_list_cleanup(&iph1->evt_listeners); 387 388 #ifdef ENABLE_NATT 389 if (iph1->natt_flags & NAT_KA_QUEUED) 390 natt_keepalive_remove (iph1->local, iph1->remote); 391 392 if (iph1->natt_options) { 393 racoon_free(iph1->natt_options); 394 iph1->natt_options = NULL; 395 } 396 #endif 397 398 #ifdef ENABLE_HYBRID 399 if (iph1->mode_cfg) 400 isakmp_cfg_rmstate(iph1); 401 #endif 402 403 #ifdef ENABLE_DPD 404 sched_cancel(&iph1->dpd_r_u); 405 #endif 406 sched_cancel(&iph1->sce); 407 sched_cancel(&iph1->scr); 408 409 if (iph1->remote) { 410 racoon_free(iph1->remote); 411 iph1->remote = NULL; 412 } 413 if (iph1->local) { 414 racoon_free(iph1->local); 415 iph1->local = NULL; 416 } 417 if (iph1->approval) { 418 delisakmpsa(iph1->approval); 419 iph1->approval = NULL; 420 } 421 422 VPTRINIT(iph1->authstr); 423 VPTRINIT(iph1->sendbuf); 424 VPTRINIT(iph1->dhpriv); 425 VPTRINIT(iph1->dhpub); 426 VPTRINIT(iph1->dhpub_p); 427 VPTRINIT(iph1->dhgxy); 428 VPTRINIT(iph1->nonce); 429 VPTRINIT(iph1->nonce_p); 430 VPTRINIT(iph1->skeyid); 431 VPTRINIT(iph1->skeyid_d); 432 VPTRINIT(iph1->skeyid_a); 433 VPTRINIT(iph1->skeyid_e); 434 VPTRINIT(iph1->key); 435 VPTRINIT(iph1->hash); 436 VPTRINIT(iph1->sig); 437 VPTRINIT(iph1->sig_p); 438 VPTRINIT(iph1->cert); 439 VPTRINIT(iph1->cert_p); 440 VPTRINIT(iph1->crl_p); 441 VPTRINIT(iph1->cr_p); 442 VPTRINIT(iph1->id); 443 VPTRINIT(iph1->id_p); 444 445 if(iph1->approval != NULL) 446 delisakmpsa(iph1->approval); 447 448 if (iph1->ivm) { 449 oakley_delivm(iph1->ivm); 450 iph1->ivm = NULL; 451 } 452 453 VPTRINIT(iph1->sa); 454 VPTRINIT(iph1->sa_ret); 455 456 #ifdef HAVE_GSSAPI 457 VPTRINIT(iph1->gi_i); 458 VPTRINIT(iph1->gi_r); 459 460 gssapi_free_state(iph1); 461 #endif 462 463 racoon_free(iph1); 464 } 465 466 /* 467 * create new isakmp Phase 1 status record to handle isakmp in Phase1 468 */ 469 int 470 insph1(iph1) 471 struct ph1handle *iph1; 472 { 473 /* validity check */ 474 if (iph1->remote == NULL) { 475 plog(LLV_ERROR, LOCATION, NULL, 476 "invalid isakmp SA handler. no remote address.\n"); 477 return -1; 478 } 479 LIST_INSERT_HEAD(&ph1tree, iph1, chain); 480 481 return 0; 482 } 483 484 void 485 remph1(iph1) 486 struct ph1handle *iph1; 487 { 488 LIST_REMOVE(iph1, chain); 489 } 490 491 /* 492 * flush isakmp-sa 493 */ 494 void 495 flushph1() 496 { 497 struct ph1handle *p, *next; 498 499 for (p = LIST_FIRST(&ph1tree); p; p = next) { 500 next = LIST_NEXT(p, chain); 501 502 /* send delete information */ 503 if (p->status >= PHASE1ST_ESTABLISHED) 504 isakmp_info_send_d1(p); 505 506 remph1(p); 507 delph1(p); 508 } 509 } 510 511 void 512 initph1tree() 513 { 514 LIST_INIT(&ph1tree); 515 } 516 517 int 518 ph1_rekey_enabled(iph1) 519 struct ph1handle *iph1; 520 { 521 if (iph1->rmconf == NULL) 522 return 0; 523 if (iph1->rmconf->rekey == REKEY_FORCE) 524 return 1; 525 #ifdef ENABLE_DPD 526 if (iph1->rmconf->rekey == REKEY_ON && iph1->dpd_support && 527 iph1->rmconf->dpd_interval) 528 return 1; 529 #endif 530 return 0; 531 } 532 533 /* %%% management phase 2 handler */ 534 535 int 536 enumph2(sel, enum_func, enum_arg) 537 struct ph2selector *sel; 538 int (*enum_func)(struct ph2handle *ph2, void *arg); 539 void *enum_arg; 540 { 541 struct ph2handle *p; 542 int ret; 543 544 LIST_FOREACH(p, &ph2tree, chain) { 545 if (sel != NULL) { 546 if (sel->spid != 0 && sel->spid != p->spid) 547 continue; 548 549 if (sel->src != NULL && 550 cmpsaddr(sel->src, p->src) != CMPSADDR_MATCH) 551 continue; 552 553 if (sel->dst != NULL && 554 cmpsaddr(sel->dst, p->dst) != CMPSADDR_MATCH) 555 continue; 556 } 557 558 if ((ret = enum_func(p, enum_arg)) != 0) 559 return ret; 560 } 561 562 return 0; 563 } 564 565 /* 566 * search ph2handle with sequence number. 567 */ 568 struct ph2handle * 569 getph2byseq(seq) 570 u_int32_t seq; 571 { 572 struct ph2handle *p; 573 574 LIST_FOREACH(p, &ph2tree, chain) { 575 if (p->seq == seq) 576 return p; 577 } 578 579 return NULL; 580 } 581 582 /* 583 * search ph2handle with message id. 584 */ 585 struct ph2handle * 586 getph2bymsgid(iph1, msgid) 587 struct ph1handle *iph1; 588 u_int32_t msgid; 589 { 590 struct ph2handle *p; 591 592 LIST_FOREACH(p, &iph1->ph2tree, ph1bind) { 593 if (p->msgid == msgid && p->ph1 == iph1) 594 return p; 595 } 596 597 return NULL; 598 } 599 600 /* Note that src and dst are not the selectors of the SP 601 * but the source and destination addresses used for 602 * for SA negotiation (best example is tunnel mode SA 603 * where src and dst are the endpoints). There is at most 604 * a unique match because racoon does not support bundles 605 * which makes that there is at most a single established 606 * SA for a given spid. One could say that src and dst 607 * are in fact useless ... 608 */ 609 struct ph2handle * 610 getph2byid(src, dst, spid) 611 struct sockaddr *src, *dst; 612 u_int32_t spid; 613 { 614 struct ph2handle *p, *next; 615 616 for (p = LIST_FIRST(&ph2tree); p; p = next) { 617 next = LIST_NEXT(p, chain); 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 { 990 struct contacted *p, *next; 991 992 for (p = LIST_FIRST(&ctdtree); p; p = next) { 993 next = LIST_NEXT(p, chain); 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 { 1562 struct ph1handle *p, *next; 1563 int found = 0; 1564 1565 for (p = LIST_FIRST(&ph1tree); p; p = next) { 1566 next = LIST_NEXT(p, chain); 1567 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 1584