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 *
getph1byindex(index)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 *
getph1byindex0(index)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 *
getph1byaddr(local,remote,established)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 *
getph1byaddrwop(local,remote)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 *
getph1bydstaddrwop(remote)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 *
dumpph1()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 *
newph1()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
delph1(iph1)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
insph1(iph1)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
remph1(iph1)400 remph1(iph1)
401 struct ph1handle *iph1;
402 {
403 LIST_REMOVE(iph1, chain);
404 }
405
406 /*
407 * flush isakmp-sa
408 */
409 void
flushph1()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
initph1tree()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 *
getph2byspid(spid)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 *
getph2byseq(seq)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 *
getph2bymsgid(iph1,msgid)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 *
getph2byid(src,dst,spid)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 *
getph2bysaddr(src,dst)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 *
getph2bysaidx(src,dst,proto_id,spi)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 *
newph2()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
initph2(iph2)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
delph2(iph2)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
insph2(iph2)685 insph2(iph2)
686 struct ph2handle *iph2;
687 {
688 LIST_INSERT_HEAD(&ph2tree, iph2, chain);
689
690 return 0;
691 }
692
693 void
remph2(iph2)694 remph2(iph2)
695 struct ph2handle *iph2;
696 {
697 LIST_REMOVE(iph2, chain);
698 }
699
700 void
initph2tree()701 initph2tree()
702 {
703 LIST_INIT(&ph2tree);
704 }
705
706 void
flushph2()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
deleteallph2(src,dst,proto_id)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
bindph12(iph1,iph2)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
unbindph12(iph2)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 *
getcontacted(remote)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
inscontacted(remote)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
initctdtree()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
check_recvdpkt(remote,local,rbuf)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
add_recvdpkt(remote,local,sbuf,rbuf)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
del_recvdpkt(r)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
rem_recvdpkt(r)1004 rem_recvdpkt(r)
1005 struct recvdpkt *r;
1006 {
1007 LIST_REMOVE(r, chain);
1008 }
1009
1010 void
sweep_recvdpkt(dummy)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
init_recvdpkt()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
exclude_cfg_addr(addr)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 */
revalidate_ph2(struct ph2handle * iph2)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
remove_ph2(struct ph2handle * iph2)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
remove_ph1(struct ph1handle * iph1)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
revalidate_ph1tree_rmconf(void)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 */
revalidate_ph1(struct ph1handle * iph1)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
revalidate_ph1tree(void)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
revalidate_ph2tree(void)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
revalidate_ph12(void)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 *
getph1bylogin(login)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
purgeph1bylogin(login)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