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