]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/handler.c
9dc7f92da8216d3db08009d5e5d3e5a02d87dd19
[apple/ipsec.git] / ipsec-tools / racoon / handler.c
1 /* $NetBSD: handler.c,v 1.9.6.6 2007/06/06 09:20:12 vanhu 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 #include "ike_session.h"
78
79 #include "sainfo.h"
80
81 #ifdef HAVE_GSSAPI
82 #include "gssapi.h"
83 #endif
84
85 static LIST_HEAD(_ph1tree_, ph1handle) ph1tree;
86 static LIST_HEAD(_ph2tree_, ph2handle) ph2tree;
87 static LIST_HEAD(_ctdtree_, contacted) ctdtree;
88 static LIST_HEAD(_rcptree_, recvdpkt) rcptree;
89
90 static void del_recvdpkt __P((struct recvdpkt *));
91 static void rem_recvdpkt __P((struct recvdpkt *));
92 static void sweep_recvdpkt __P((void *));
93
94 /*
95 * functions about management of the isakmp status table
96 */
97 /* %%% management phase 1 handler */
98 /*
99 * search for isakmpsa handler with isakmp index.
100 */
101
102 extern caddr_t val2str(const char *, size_t);
103
104 struct ph1handle *
105 getph1byindex(index)
106 isakmp_index *index;
107 {
108 struct ph1handle *p;
109
110 LIST_FOREACH(p, &ph1tree, chain) {
111 if (p->status == PHASE1ST_EXPIRED)
112 continue;
113 if (memcmp(&p->index, index, sizeof(*index)) == 0)
114 return p;
115 }
116
117 return NULL;
118 }
119
120 /*
121 * search for isakmp handler by i_ck in index.
122 */
123 struct ph1handle *
124 getph1byindex0(index)
125 isakmp_index *index;
126 {
127 struct ph1handle *p;
128
129 LIST_FOREACH(p, &ph1tree, chain) {
130 if (p->status == PHASE1ST_EXPIRED)
131 continue;
132 if (memcmp(&p->index, index, sizeof(cookie_t)) == 0)
133 return p;
134 }
135
136 return NULL;
137 }
138
139 /*
140 * search for isakmpsa handler by source and remote address.
141 * don't use port number to search because this function search
142 * with phase 2's destinaion.
143 */
144 struct ph1handle *
145 getph1byaddr(local, remote)
146 struct sockaddr *local, *remote;
147 {
148 struct ph1handle *p;
149
150 plog(LLV_DEBUG2, LOCATION, NULL, "getph1byaddr: start\n");
151 plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local));
152 plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote));
153
154 LIST_FOREACH(p, &ph1tree, chain) {
155 if (p->status == PHASE1ST_EXPIRED)
156 continue;
157 plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local));
158 plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote));
159 if (CMPSADDR(local, p->local) == 0
160 && CMPSADDR(remote, p->remote) == 0){
161 plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
162 return p;
163 }
164 }
165
166 plog(LLV_DEBUG2, LOCATION, NULL, "no match\n");
167
168 return NULL;
169 }
170
171 struct ph1handle *
172 getph1byaddrwop(local, remote)
173 struct sockaddr *local, *remote;
174 {
175 struct ph1handle *p;
176
177 LIST_FOREACH(p, &ph1tree, chain) {
178 if (p->status == PHASE1ST_EXPIRED)
179 continue;
180 if (cmpsaddrwop(local, p->local) == 0
181 && cmpsaddrwop(remote, p->remote) == 0)
182 return p;
183 }
184
185 return NULL;
186 }
187
188 /*
189 * search for isakmpsa handler by remote address.
190 * don't use port number to search because this function search
191 * with phase 2's destinaion.
192 */
193 struct ph1handle *
194 getph1bydstaddrwop(remote)
195 struct sockaddr *remote;
196 {
197 struct ph1handle *p;
198
199 LIST_FOREACH(p, &ph1tree, chain) {
200 if (p->status == PHASE1ST_EXPIRED)
201 continue;
202 if (cmpsaddrwop(remote, p->remote) == 0)
203 return p;
204 }
205
206 return NULL;
207 }
208
209 int
210 islast_ph1(ph1)
211 struct ph1handle *ph1;
212 {
213 struct ph1handle *p;
214
215 LIST_FOREACH(p, &ph1tree, chain) {
216 if (p->status == PHASE1ST_EXPIRED)
217 continue;
218 if (CMPSADDR(ph1->remote, p->remote) == 0) {
219 if (p == ph1)
220 continue;
221 return 0;
222 }
223 }
224 return 1;
225 }
226
227 /*
228 * dump isakmp-sa
229 */
230 vchar_t *
231 dumpph1()
232 {
233 struct ph1handle *iph1;
234 struct ph1dump *pd;
235 int cnt = 0;
236 vchar_t *buf;
237
238 /* get length of buffer */
239 LIST_FOREACH(iph1, &ph1tree, chain)
240 cnt++;
241
242 buf = vmalloc(cnt * sizeof(struct ph1dump));
243 if (buf == NULL) {
244 plog(LLV_ERROR, LOCATION, NULL,
245 "failed to get buffer\n");
246 return NULL;
247 }
248 pd = (struct ph1dump *)buf->v;
249
250 LIST_FOREACH(iph1, &ph1tree, chain) {
251 memcpy(&pd->index, &iph1->index, sizeof(iph1->index));
252 pd->status = iph1->status;
253 pd->side = iph1->side;
254 memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote));
255 memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local));
256 pd->version = iph1->version;
257 pd->etype = iph1->etype;
258 pd->created = iph1->created;
259 pd->ph2cnt = iph1->ph2cnt;
260 pd++;
261 }
262
263 return buf;
264 }
265
266 /*
267 * create new isakmp Phase 1 status record to handle isakmp in Phase1
268 */
269 struct ph1handle *
270 newph1()
271 {
272 struct ph1handle *iph1;
273
274 /* create new iph1 */
275 iph1 = racoon_calloc(1, sizeof(*iph1));
276 if (iph1 == NULL)
277 return NULL;
278
279 iph1->status = PHASE1ST_SPAWN;
280
281 #ifdef ENABLE_DPD
282 iph1->dpd_support = 0;
283 iph1->dpd_lastack = 0;
284 iph1->dpd_seq = 0;
285 iph1->dpd_fails = 0;
286 iph1->peer_sent_ike = 0;
287 iph1->dpd_r_u = NULL;
288 #endif
289 #ifdef ENABLE_VPNCONTROL_PORT
290 iph1->ping_sched = NULL;
291 #endif
292 iph1->is_dying = 0;
293 return iph1;
294 }
295
296 /*
297 * delete new isakmp Phase 1 status record to handle isakmp in Phase1
298 */
299 void
300 delph1(iph1)
301 struct ph1handle *iph1;
302 {
303 if (iph1 == NULL)
304 return;
305
306 /* SA down shell script hook */
307 script_hook(iph1, SCRIPT_PHASE1_DOWN);
308
309 EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL);
310
311 #ifdef ENABLE_NATT
312 #ifndef __APPLE__
313 if (iph1->natt_flags & NAT_KA_QUEUED)
314 natt_keepalive_remove (iph1->local, iph1->remote);
315 #endif /* __APPLE__ */
316 if (iph1->natt_options) {
317 racoon_free(iph1->natt_options);
318 iph1->natt_options = NULL;
319 }
320 #endif
321
322 #ifdef ENABLE_HYBRID
323 if (iph1->mode_cfg)
324 isakmp_cfg_rmstate(iph1);
325 VPTRINIT(iph1->xauth_awaiting_userinput_msg);
326 #endif
327
328 #ifdef ENABLE_DPD
329 if (iph1->dpd_r_u != NULL)
330 SCHED_KILL(iph1->dpd_r_u);
331 #endif
332 #ifdef ENABLE_VPNCONTROL_PORT
333 if (iph1->ping_sched != NULL)
334 SCHED_KILL(iph1->ping_sched);
335 #endif
336
337 if (iph1->remote) {
338 racoon_free(iph1->remote);
339 iph1->remote = NULL;
340 }
341 if (iph1->local) {
342 racoon_free(iph1->local);
343 iph1->local = NULL;
344 }
345
346 if (iph1->approval) {
347 delisakmpsa(iph1->approval);
348 iph1->approval = NULL;
349 }
350
351 VPTRINIT(iph1->authstr);
352
353 sched_scrub_param(iph1);
354 iph1->sce = NULL;
355 iph1->sce_rekey = NULL;
356 iph1->scr = NULL;
357
358 VPTRINIT(iph1->sendbuf);
359
360 VPTRINIT(iph1->dhpriv);
361 VPTRINIT(iph1->dhpub);
362 VPTRINIT(iph1->dhpub_p);
363 VPTRINIT(iph1->dhgxy);
364 VPTRINIT(iph1->nonce);
365 VPTRINIT(iph1->nonce_p);
366 VPTRINIT(iph1->skeyid);
367 VPTRINIT(iph1->skeyid_d);
368 VPTRINIT(iph1->skeyid_a);
369 VPTRINIT(iph1->skeyid_e);
370 VPTRINIT(iph1->key);
371 VPTRINIT(iph1->hash);
372 VPTRINIT(iph1->sig);
373 VPTRINIT(iph1->sig_p);
374 oakley_delcert(iph1->cert);
375 iph1->cert = NULL;
376 oakley_delcert(iph1->cert_p);
377 iph1->cert_p = NULL;
378 oakley_delcert(iph1->crl_p);
379 iph1->crl_p = NULL;
380 oakley_delcert(iph1->cr_p);
381 iph1->cr_p = NULL;
382 VPTRINIT(iph1->id);
383 VPTRINIT(iph1->id_p);
384
385 if(iph1->approval != NULL)
386 delisakmpsa(iph1->approval);
387
388 if (iph1->ivm) {
389 oakley_delivm(iph1->ivm);
390 iph1->ivm = NULL;
391 }
392
393 VPTRINIT(iph1->sa);
394 VPTRINIT(iph1->sa_ret);
395
396 #ifdef HAVE_GSSAPI
397 VPTRINIT(iph1->gi_i);
398 VPTRINIT(iph1->gi_r);
399
400 gssapi_free_state(iph1);
401 #endif
402
403 #ifdef __APPLE__
404 if (iph1->parent_session) {
405 ike_session_unlink_ph1_from_session(iph1);
406 }
407 if (iph1->rmconf) {
408 unlink_rmconf_from_ph1(iph1->rmconf);
409 iph1->rmconf = NULL;
410 }
411 #endif
412
413 racoon_free(iph1);
414 }
415
416 /*
417 * create new isakmp Phase 1 status record to handle isakmp in Phase1
418 */
419 int
420 insph1(iph1)
421 struct ph1handle *iph1;
422 {
423 /* validity check */
424 if (iph1->remote == NULL) {
425 plog(LLV_ERROR, LOCATION, NULL,
426 "invalid isakmp SA handler. no remote address.\n");
427 return -1;
428 }
429 LIST_INSERT_HEAD(&ph1tree, iph1, chain);
430
431 return 0;
432 }
433
434 void
435 remph1(iph1)
436 struct ph1handle *iph1;
437 {
438 LIST_REMOVE(iph1, chain);
439 }
440
441 /*
442 * flush isakmp-sa
443 */
444 void
445 flushph1(int ignore_established_handles)
446 {
447 struct ph1handle *p, *next;
448
449 for (p = LIST_FIRST(&ph1tree); p; p = next) {
450 next = LIST_NEXT(p, chain);
451
452 /* send delete information */
453 if (p->status == PHASE1ST_ESTABLISHED) {
454 if (ignore_established_handles &&
455 (ike_session_has_negoing_ph2(p->parent_session) ||
456 p->mode_cfg->flags)) {
457 plog(LLV_DEBUG2, LOCATION, NULL,
458 "skipping ph1 handler that's established... because it's needed by children phase2s\n");
459 continue;
460 }
461 /* send delete information */
462 plog(LLV_DEBUG2, LOCATION, NULL,
463 "got a ph1 handler to flush...\n");
464 isakmp_info_send_d1(p);
465 }
466
467 ike_session_stopped_by_controller(p->parent_session,
468 ike_session_stopped_by_flush);
469 remph1(p);
470 delph1(p);
471 }
472 }
473
474 void
475 initph1tree()
476 {
477 LIST_INIT(&ph1tree);
478 }
479
480 /* %%% management phase 2 handler */
481 /*
482 * search ph2handle with policy id.
483 */
484 struct ph2handle *
485 getph2byspid(spid)
486 u_int32_t spid;
487 {
488 struct ph2handle *p;
489
490 LIST_FOREACH(p, &ph2tree, chain) {
491 /*
492 * there are ph2handle independent on policy
493 * such like informational exchange.
494 */
495 if (p->spid == spid)
496 return p;
497 }
498
499 return NULL;
500 }
501
502 /*
503 * search ph2handle with sequence number.
504 */
505 struct ph2handle *
506 getph2byseq(seq)
507 u_int32_t seq;
508 {
509 struct ph2handle *p;
510
511 LIST_FOREACH(p, &ph2tree, chain) {
512 if (p->seq == seq)
513 return p;
514 }
515
516 return NULL;
517 }
518
519 /*
520 * search ph2handle with message id.
521 */
522 struct ph2handle *
523 getph2bymsgid(iph1, msgid)
524 struct ph1handle *iph1;
525 u_int32_t msgid;
526 {
527 struct ph2handle *p;
528
529 LIST_FOREACH(p, &ph2tree, chain) {
530 if (p->msgid == msgid)
531 return p;
532 }
533
534 return NULL;
535 }
536
537 struct ph2handle *
538 getph2byid(src, dst, spid)
539 struct sockaddr *src, *dst;
540 u_int32_t spid;
541 {
542 struct ph2handle *p;
543
544 LIST_FOREACH(p, &ph2tree, chain) {
545 if (spid == p->spid &&
546 CMPSADDR(src, p->src) == 0 &&
547 CMPSADDR(dst, p->dst) == 0){
548 /* Sanity check to detect zombie handlers
549 * XXX Sould be done "somewhere" more interesting,
550 * because we have lots of getph2byxxxx(), but this one
551 * is called by pk_recvacquire(), so is the most important.
552 */
553 if(p->status < PHASE2ST_ESTABLISHED &&
554 p->retry_counter == 0
555 && p->sce == NULL && p->scr == NULL){
556 plog(LLV_DEBUG, LOCATION, NULL,
557 "Zombie ph2 found, expiring it\n");
558 isakmp_ph2expire(p);
559 }else
560 return p;
561 }
562 }
563
564 return NULL;
565 }
566
567 struct ph2handle *
568 getph2bysaddr(src, dst)
569 struct sockaddr *src, *dst;
570 {
571 struct ph2handle *p;
572
573 LIST_FOREACH(p, &ph2tree, chain) {
574 if (cmpsaddrstrict(src, p->src) == 0 &&
575 cmpsaddrstrict(dst, p->dst) == 0)
576 return p;
577 }
578
579 return NULL;
580 }
581
582 /*
583 * call by pk_recvexpire().
584 */
585 struct ph2handle *
586 getph2bysaidx(src, dst, proto_id, spi)
587 struct sockaddr *src, *dst;
588 u_int proto_id;
589 u_int32_t spi;
590 {
591 struct ph2handle *iph2;
592 struct saproto *pr;
593
594 LIST_FOREACH(iph2, &ph2tree, chain) {
595 if (iph2->proposal == NULL && iph2->approval == NULL)
596 continue;
597 if (iph2->approval != NULL) {
598 for (pr = iph2->approval->head; pr != NULL;
599 pr = pr->next) {
600 if (proto_id != pr->proto_id)
601 break;
602 if (spi == pr->spi || spi == pr->spi_p)
603 return iph2;
604 }
605 } else if (iph2->proposal != NULL) {
606 for (pr = iph2->proposal->head; pr != NULL;
607 pr = pr->next) {
608 if (proto_id != pr->proto_id)
609 break;
610 if (spi == pr->spi)
611 return iph2;
612 }
613 }
614 }
615
616 return NULL;
617 }
618
619 /*
620 * create new isakmp Phase 2 status record to handle isakmp in Phase2
621 */
622 struct ph2handle *
623 newph2()
624 {
625 struct ph2handle *iph2 = NULL;
626
627 /* create new iph2 */
628 iph2 = racoon_calloc(1, sizeof(*iph2));
629 if (iph2 == NULL)
630 return NULL;
631
632 iph2->status = PHASE1ST_SPAWN;
633 iph2->is_dying = 0;
634
635 return iph2;
636 }
637
638 /*
639 * initialize ph2handle
640 * NOTE: don't initialize src/dst.
641 * SPI in the proposal is cleared.
642 */
643 void
644 initph2(iph2)
645 struct ph2handle *iph2;
646 {
647 sched_scrub_param(iph2);
648 iph2->sce = NULL;
649 iph2->scr = NULL;
650
651 VPTRINIT(iph2->sendbuf);
652 VPTRINIT(iph2->msg1);
653
654 /* clear spi, keep variables in the proposal */
655 if (iph2->proposal) {
656 struct saproto *pr;
657 for (pr = iph2->proposal->head; pr != NULL; pr = pr->next)
658 pr->spi = 0;
659 }
660
661 /* clear approval */
662 if (iph2->approval) {
663 flushsaprop(iph2->approval);
664 iph2->approval = NULL;
665 }
666
667 /* clear the generated policy */
668 if (iph2->spidx_gen) {
669 delsp_bothdir((struct policyindex *)iph2->spidx_gen);
670 racoon_free(iph2->spidx_gen);
671 iph2->spidx_gen = NULL;
672 }
673
674 if (iph2->pfsgrp) {
675 oakley_dhgrp_free(iph2->pfsgrp);
676 iph2->pfsgrp = NULL;
677 }
678
679 VPTRINIT(iph2->dhpriv);
680 VPTRINIT(iph2->dhpub);
681 VPTRINIT(iph2->dhpub_p);
682 VPTRINIT(iph2->dhgxy);
683 VPTRINIT(iph2->id);
684 VPTRINIT(iph2->id_p);
685 VPTRINIT(iph2->nonce);
686 VPTRINIT(iph2->nonce_p);
687 VPTRINIT(iph2->sa);
688 VPTRINIT(iph2->sa_ret);
689
690 if (iph2->ivm) {
691 oakley_delivm(iph2->ivm);
692 iph2->ivm = NULL;
693 }
694 }
695
696 /*
697 * delete new isakmp Phase 2 status record to handle isakmp in Phase2
698 */
699 void
700 delph2(iph2)
701 struct ph2handle *iph2;
702 {
703 initph2(iph2);
704
705 if (iph2->src) {
706 racoon_free(iph2->src);
707 iph2->src = NULL;
708 }
709 if (iph2->dst) {
710 racoon_free(iph2->dst);
711 iph2->dst = NULL;
712 }
713 if (iph2->src_id) {
714 racoon_free(iph2->src_id);
715 iph2->src_id = NULL;
716 }
717 if (iph2->dst_id) {
718 racoon_free(iph2->dst_id);
719 iph2->dst_id = NULL;
720 }
721
722 if (iph2->proposal) {
723 flushsaprop(iph2->proposal);
724 iph2->proposal = NULL;
725 }
726
727 #ifdef __APPLE__
728 if (iph2->parent_session) {
729 ike_session_unlink_ph2_from_session(iph2);
730 }
731 if (iph2->sainfo) {
732 unlink_sainfo_from_ph2(iph2->sainfo);
733 iph2->sainfo = NULL;
734 }
735 if (iph2->ext_nat_id) {
736 vfree(iph2->ext_nat_id);
737 iph2->ext_nat_id = NULL;
738 }
739 if (iph2->ext_nat_id_p) {
740 vfree(iph2->ext_nat_id_p);
741 iph2->ext_nat_id_p = NULL;
742 }
743 #endif
744
745 racoon_free(iph2);
746 }
747
748 /*
749 * create new isakmp Phase 2 status record to handle isakmp in Phase2
750 */
751 int
752 insph2(iph2)
753 struct ph2handle *iph2;
754 {
755 LIST_INSERT_HEAD(&ph2tree, iph2, chain);
756
757 return 0;
758 }
759
760 void
761 remph2(iph2)
762 struct ph2handle *iph2;
763 {
764 LIST_REMOVE(iph2, chain);
765 }
766
767 void
768 initph2tree()
769 {
770 LIST_INIT(&ph2tree);
771 }
772
773 void
774 flushph2(int ignore_established_handles)
775 {
776 struct ph2handle *p, *next;
777
778 plog(LLV_DEBUG2, LOCATION, NULL,
779 "flushing all ph2 handlers...\n");
780
781 for (p = LIST_FIRST(&ph2tree); p; p = next) {
782 next = LIST_NEXT(p, chain);
783
784 if (p->status == PHASE2ST_ESTABLISHED){
785 if (ignore_established_handles) {
786 plog(LLV_DEBUG2, LOCATION, NULL,
787 "skipping ph2 handler that's established...\n");
788 continue;
789 }
790 /* send delete information */
791 plog(LLV_DEBUG2, LOCATION, NULL,
792 "got an established ph2 handler to flush...\n");
793 isakmp_info_send_d2(p);
794 }else{
795 plog(LLV_DEBUG2, LOCATION, NULL,
796 "got a ph2 handler to flush (state %d)\n", p->status);
797 }
798
799 ike_session_stopped_by_controller(p->parent_session,
800 ike_session_stopped_by_flush);
801 delete_spd(p);
802 unbindph12(p);
803 remph2(p);
804 delph2(p);
805 }
806 }
807
808 /*
809 * Delete all Phase 2 handlers for this src/dst/proto. This
810 * is used during INITIAL-CONTACT processing (so no need to
811 * send a message to the peer).
812 */
813 void
814 deleteallph2(src, dst, proto_id)
815 struct sockaddr *src, *dst;
816 u_int proto_id;
817 {
818 struct ph2handle *iph2, *next;
819 struct saproto *pr;
820
821 for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) {
822 next = LIST_NEXT(iph2, chain);
823 if (iph2->proposal == NULL && iph2->approval == NULL)
824 continue;
825 if (cmpsaddrwop(src, iph2->src) != 0 ||
826 cmpsaddrwop(dst, iph2->dst) != 0) {
827 continue;
828 }
829 if (iph2->approval != NULL) {
830 for (pr = iph2->approval->head; pr != NULL;
831 pr = pr->next) {
832 if (proto_id == pr->proto_id)
833 goto zap_it;
834 }
835 } else if (iph2->proposal != NULL) {
836 for (pr = iph2->proposal->head; pr != NULL;
837 pr = pr->next) {
838 if (proto_id == pr->proto_id)
839 goto zap_it;
840 }
841 }
842 continue;
843 zap_it:
844 plog(LLV_DEBUG2, LOCATION, NULL,
845 "deleteallph2: got a ph2 handler...\n");
846 if (iph2->status == PHASE2ST_ESTABLISHED)
847 isakmp_info_send_d2(iph2);
848 ike_session_stopped_by_controller(iph2->parent_session,
849 ike_session_stopped_by_flush);
850 unbindph12(iph2);
851 remph2(iph2);
852 delph2(iph2);
853 }
854 }
855
856 /*
857 * Delete all Phase 1 handlers for this src/dst.
858 */
859 void
860 deleteallph1(src, dst)
861 struct sockaddr *src, *dst;
862 {
863 struct ph1handle *iph1, *next;
864
865 for (iph1 = LIST_FIRST(&ph1tree); iph1 != NULL; iph1 = next) {
866 next = LIST_NEXT(iph1, chain);
867 if (cmpsaddrwop(src, iph1->local) != 0 ||
868 cmpsaddrwop(dst, iph1->remote) != 0) {
869 continue;
870 }
871 plog(LLV_DEBUG2, LOCATION, NULL,
872 "deleteallph1: got a ph1 handler...\n");
873 if (iph1->status == PHASE2ST_ESTABLISHED)
874 isakmp_info_send_d1(iph1);
875
876 ike_session_stopped_by_controller(iph1->parent_session,
877 ike_session_stopped_by_flush);
878 remph1(iph1);
879 delph1(iph1);
880 }
881 }
882
883 /* %%% */
884 void
885 bindph12(iph1, iph2)
886 struct ph1handle *iph1;
887 struct ph2handle *iph2;
888 {
889 if (iph2->ph1 && (struct ph1handle *)iph2->ph1bind.le_next == iph1) {
890 plog(LLV_ERROR, LOCATION, NULL, "duplicate %s.\n", __FUNCTION__);
891 }
892 iph2->ph1 = iph1;
893 LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind);
894 }
895
896 void
897 unbindph12(iph2)
898 struct ph2handle *iph2;
899 {
900 if (iph2->ph1 != NULL) {
901 plog(LLV_DEBUG, LOCATION, NULL, "unbindph12.\n");
902 iph2->ph1 = NULL;
903 LIST_REMOVE(iph2, ph1bind);
904 }
905 }
906
907 void
908 rebindph12(new_ph1, iph2)
909 struct ph1handle *new_ph1;
910 struct ph2handle *iph2;
911 {
912 if (!new_ph1) {
913 return;
914 }
915
916 // reconcile the ph1-to-ph2 binding
917 plog(LLV_DEBUG, LOCATION, NULL, "rebindph12.\n");
918 unbindph12(iph2);
919 bindph12(new_ph1, iph2);
920 // recalculate ivm since ph1 binding has changed
921 if (iph2->ivm != NULL) {
922 oakley_delivm(iph2->ivm);
923 if (new_ph1->status == PHASE1ST_ESTABLISHED) {
924 iph2->ivm = oakley_newiv2(new_ph1, iph2->msgid);
925 plog(LLV_DEBUG, LOCATION, NULL, "ph12 binding changed... recalculated ivm.\n");
926 } else {
927 iph2->ivm = NULL;
928 }
929 }
930 }
931
932 /* %%% management contacted list */
933 /*
934 * search contacted list.
935 */
936 struct contacted *
937 getcontacted(remote)
938 struct sockaddr *remote;
939 {
940 struct contacted *p;
941
942 LIST_FOREACH(p, &ctdtree, chain) {
943 if (cmpsaddrstrict(remote, p->remote) == 0)
944 return p;
945 }
946
947 return NULL;
948 }
949
950 /*
951 * create new isakmp Phase 2 status record to handle isakmp in Phase2
952 */
953 int
954 inscontacted(remote)
955 struct sockaddr *remote;
956 {
957 struct contacted *new;
958
959 /* create new iph2 */
960 new = racoon_calloc(1, sizeof(*new));
961 if (new == NULL)
962 return -1;
963
964 new->remote = dupsaddr(remote);
965 if (new->remote == NULL) {
966 plog(LLV_ERROR, LOCATION, NULL,
967 "failed to allocate buffer.\n");
968 racoon_free(new);
969 return -1;
970 }
971
972 LIST_INSERT_HEAD(&ctdtree, new, chain);
973
974 return 0;
975 }
976
977
978 void
979 clear_contacted()
980 {
981 struct contacted *c, *next;
982
983 for (c = LIST_FIRST(&ctdtree); c; c = next) {
984 next = LIST_NEXT(c, chain);
985 LIST_REMOVE(c, chain);
986 racoon_free(c->remote);
987 racoon_free(c);
988 }
989 }
990
991 void
992 initctdtree()
993 {
994 LIST_INIT(&ctdtree);
995 }
996
997 /*
998 * check the response has been sent to the peer. when not, simply reply
999 * the buffered packet to the peer.
1000 * OUT:
1001 * 0: the packet is received at the first time.
1002 * 1: the packet was processed before.
1003 * 2: the packet was processed before, but the address mismatches.
1004 * -1: error happened.
1005 */
1006 int
1007 check_recvdpkt(remote, local, rbuf)
1008 struct sockaddr *remote, *local;
1009 vchar_t *rbuf;
1010 {
1011 vchar_t *hash;
1012 struct recvdpkt *r;
1013 time_t t;
1014 int len, s;
1015
1016 /* set current time */
1017 t = time(NULL);
1018
1019 hash = eay_md5_one(rbuf);
1020 if (!hash) {
1021 plog(LLV_ERROR, LOCATION, NULL,
1022 "failed to allocate buffer.\n");
1023 return -1;
1024 }
1025
1026 LIST_FOREACH(r, &rcptree, chain) {
1027 if (memcmp(hash->v, r->hash->v, r->hash->l) == 0)
1028 break;
1029 }
1030 vfree(hash);
1031
1032 /* this is the first time to receive the packet */
1033 if (r == NULL)
1034 return 0;
1035
1036 /*
1037 * the packet was processed before, but the remote address mismatches.
1038 * ignore the port to accomodate port changes (e.g. floating).
1039 */
1040 if (cmpsaddrwop(remote, r->remote) != 0) {
1041 return 2;
1042 }
1043
1044 /*
1045 * it should not check the local address because the packet
1046 * may arrive at other interface.
1047 */
1048
1049 /* check the previous time to send */
1050 if (t - r->time_send < 1) {
1051 plog(LLV_WARNING, LOCATION, NULL,
1052 "the packet retransmitted in a short time from %s\n",
1053 saddr2str(remote));
1054 /*XXX should it be error ? */
1055 }
1056
1057 /* select the socket to be sent */
1058 s = getsockmyaddr(r->local);
1059 if (s == -1)
1060 return -1;
1061
1062 /* resend the packet if needed */
1063 len = sendfromto(s, r->sendbuf->v, r->sendbuf->l,
1064 r->local, r->remote, lcconf->count_persend);
1065 if (len == -1) {
1066 plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
1067 return -1;
1068 }
1069
1070 /* check the retry counter */
1071 r->retry_counter--;
1072 if (r->retry_counter <= 0) {
1073 rem_recvdpkt(r);
1074 del_recvdpkt(r);
1075 plog(LLV_DEBUG, LOCATION, NULL,
1076 "deleted the retransmission packet to %s.\n",
1077 saddr2str(remote));
1078 } else
1079 r->time_send = t;
1080
1081 return 1;
1082 }
1083
1084 /*
1085 * adding a hash of received packet into the received list.
1086 */
1087 int
1088 add_recvdpkt(remote, local, sbuf, rbuf, non_esp)
1089 struct sockaddr *remote, *local;
1090 vchar_t *sbuf, *rbuf;
1091 size_t non_esp;
1092 {
1093 struct recvdpkt *new = NULL;
1094
1095 if (lcconf->retry_counter == 0) {
1096 /* no need to add it */
1097 return 0;
1098 }
1099
1100 new = racoon_calloc(1, sizeof(*new));
1101 if (!new) {
1102 plog(LLV_ERROR, LOCATION, NULL,
1103 "failed to allocate buffer.\n");
1104 return -1;
1105 }
1106
1107 new->hash = eay_md5_one(rbuf);
1108 if (!new->hash) {
1109 plog(LLV_ERROR, LOCATION, NULL,
1110 "failed to allocate buffer.\n");
1111 del_recvdpkt(new);
1112 return -1;
1113 }
1114 new->remote = dupsaddr(remote);
1115 if (new->remote == NULL) {
1116 plog(LLV_ERROR, LOCATION, NULL,
1117 "failed to allocate buffer.\n");
1118 del_recvdpkt(new);
1119 return -1;
1120 }
1121 new->local = dupsaddr(local);
1122 if (new->local == NULL) {
1123 plog(LLV_ERROR, LOCATION, NULL,
1124 "failed to allocate buffer.\n");
1125 del_recvdpkt(new);
1126 return -1;
1127 }
1128
1129 if (non_esp) {
1130 plog (LLV_DEBUG, LOCATION, NULL, "Adding NON-ESP marker\n");
1131
1132 /* If NAT-T port floating is in use, 4 zero bytes (non-ESP marker)
1133 must added just before the packet itself. For this we must
1134 allocate a new buffer and release it at the end. */
1135 if ((new->sendbuf = vmalloc (sbuf->l + non_esp)) == NULL) {
1136 plog(LLV_ERROR, LOCATION, NULL,
1137 "failed to allocate extra buf for non-esp\n");
1138 del_recvdpkt(new);
1139 return -1;
1140 }
1141 *(u_int32_t *)new->sendbuf->v = 0;
1142 memcpy(new->sendbuf->v + non_esp, sbuf->v, sbuf->l);
1143 } else {
1144 new->sendbuf = vdup(sbuf);
1145 if (new->sendbuf == NULL) {
1146 plog(LLV_ERROR, LOCATION, NULL,
1147 "failed to allocate buffer.\n");
1148 del_recvdpkt(new);
1149 return -1;
1150 }
1151 }
1152
1153 new->retry_counter = lcconf->retry_counter;
1154 new->time_send = 0;
1155 new->created = time(NULL);
1156
1157 LIST_INSERT_HEAD(&rcptree, new, chain);
1158
1159 return 0;
1160 }
1161
1162 void
1163 del_recvdpkt(r)
1164 struct recvdpkt *r;
1165 {
1166 if (r->remote)
1167 racoon_free(r->remote);
1168 if (r->local)
1169 racoon_free(r->local);
1170 if (r->hash)
1171 vfree(r->hash);
1172 if (r->sendbuf)
1173 vfree(r->sendbuf);
1174 racoon_free(r);
1175 }
1176
1177 void
1178 rem_recvdpkt(r)
1179 struct recvdpkt *r;
1180 {
1181 LIST_REMOVE(r, chain);
1182 }
1183
1184 void
1185 sweep_recvdpkt(dummy)
1186 void *dummy;
1187 {
1188 struct recvdpkt *r, *next;
1189 time_t t, lt;
1190
1191 /* set current time */
1192 t = time(NULL);
1193
1194 /* set the lifetime of the retransmission */
1195 lt = lcconf->retry_counter * lcconf->retry_interval;
1196
1197 for (r = LIST_FIRST(&rcptree); r; r = next) {
1198 next = LIST_NEXT(r, chain);
1199
1200 if (t - r->created > lt) {
1201 rem_recvdpkt(r);
1202 del_recvdpkt(r);
1203 }
1204 }
1205
1206 sched_new(lt, sweep_recvdpkt, &rcptree);
1207 }
1208
1209 void
1210 clear_recvdpkt()
1211 {
1212 struct recvdpkt *r, *next;
1213
1214 for (r = LIST_FIRST(&rcptree); r; r = next) {
1215 next = LIST_NEXT(r, chain);
1216 rem_recvdpkt(r);
1217 del_recvdpkt(r);
1218 }
1219 sched_scrub_param(&rcptree);
1220 }
1221
1222 void
1223 init_recvdpkt()
1224 {
1225 time_t lt = lcconf->retry_counter * lcconf->retry_interval;
1226
1227 LIST_INIT(&rcptree);
1228
1229 sched_new(lt, sweep_recvdpkt, &rcptree);
1230 }
1231
1232 #ifdef ENABLE_HYBRID
1233 /*
1234 * Returns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
1235 * This should be in isakmp_cfg.c but ph1tree being private, it must be there
1236 */
1237 int
1238 exclude_cfg_addr(addr)
1239 const struct sockaddr *addr;
1240 {
1241 struct ph1handle *p;
1242 struct sockaddr_in *sin;
1243
1244 LIST_FOREACH(p, &ph1tree, chain) {
1245 if ((p->mode_cfg != NULL) &&
1246 (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) &&
1247 (addr->sa_family == AF_INET)) {
1248 sin = (struct sockaddr_in *)addr;
1249 if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr)
1250 return 0;
1251 }
1252 }
1253
1254 return 1;
1255 }
1256 #endif
1257
1258 #ifdef ENABLE_HYBRID
1259 struct ph1handle *
1260 getph1bylogin(login)
1261 char *login;
1262 {
1263 struct ph1handle *p;
1264
1265 LIST_FOREACH(p, &ph1tree, chain) {
1266 if (p->mode_cfg == NULL)
1267 continue;
1268 if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0)
1269 return p;
1270 }
1271
1272 return NULL;
1273 }
1274
1275 int
1276 purgeph1bylogin(login)
1277 char *login;
1278 {
1279 struct ph1handle *p;
1280 int found = 0;
1281
1282 LIST_FOREACH(p, &ph1tree, chain) {
1283 if (p->mode_cfg == NULL)
1284 continue;
1285 if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) {
1286 if (p->status == PHASE1ST_ESTABLISHED)
1287 isakmp_info_send_d1(p);
1288 purge_remote(p);
1289 found++;
1290 }
1291 }
1292
1293 return found;
1294 }
1295
1296 int
1297 purgephXbydstaddrwop(remote)
1298 struct sockaddr *remote;
1299 {
1300 int found = 0;
1301 struct ph1handle *p;
1302
1303 LIST_FOREACH(p, &ph1tree, chain) {
1304 if (cmpsaddrwop(remote, p->remote) == 0) {
1305 plog(LLV_WARNING, LOCATION, NULL,
1306 "in %s... purging phase1 and related phase2s\n", __FUNCTION__);
1307 ike_session_purge_ph2s_by_ph1(p);
1308 if (p->status == PHASE1ST_ESTABLISHED)
1309 isakmp_info_send_d1(p);
1310 isakmp_ph1expire(p);
1311 found++;
1312 }
1313 }
1314
1315 return found;
1316 }
1317
1318 void
1319 purgephXbyspid(u_int32_t spid,
1320 int del_boundph1)
1321 {
1322 struct ph2handle *iph2;
1323 struct ph1handle *iph1;
1324
1325 // do ph2's first... we need the ph1s for notifications
1326 LIST_FOREACH(iph2, &ph2tree, chain) {
1327 if (spid == iph2->spid) {
1328 if (iph2->status == PHASE2ST_ESTABLISHED) {
1329 isakmp_info_send_d2(iph2);
1330 }
1331 isakmp_ph2expire(iph2); // iph2 will go down 1 second later.
1332 ike_session_stopped_by_controller(iph2->parent_session,
1333 ike_session_stopped_by_flush);
1334 }
1335 }
1336
1337 // do the ph1s last.
1338 LIST_FOREACH(iph2, &ph2tree, chain) {
1339 if (spid == iph2->spid) {
1340 if (del_boundph1 && iph2->parent_session) {
1341 for (iph1 = LIST_FIRST(&iph2->parent_session->ikev1_state.ph1tree); iph1; iph1 = LIST_NEXT(iph1, ph1ofsession_chain)) {
1342 if (iph1->status == PHASE1ST_ESTABLISHED) {
1343 isakmp_info_send_d1(iph1);
1344 }
1345 isakmp_ph1expire(iph1);
1346 }
1347 }
1348 }
1349 }
1350 }
1351
1352 #endif
1353
1354 #ifdef ENABLE_DPD
1355 int
1356 ph1_force_dpd (struct sockaddr *remote)
1357 {
1358 int status = -1;
1359 struct ph1handle *p;
1360
1361 LIST_FOREACH(p, &ph1tree, chain) {
1362 if (cmpsaddrwop(remote, p->remote) == 0) {
1363 if (p->status == PHASE1ST_ESTABLISHED &&
1364 !p->is_dying &&
1365 p->dpd_support &&
1366 p->rmconf->dpd_interval) {
1367 if(!p->dpd_fails) {
1368 isakmp_info_send_r_u(p);
1369 status = 0;
1370 } else {
1371 plog(LLV_DEBUG2, LOCATION, NULL, "skipping forced-DPD for phase1 (dpd already in progress).\n");
1372 }
1373 } else {
1374 plog(LLV_DEBUG2, LOCATION, NULL, "skipping forced-DPD for phase1 (status %d, dying %d, dpd-support %d, dpd-interval %d).\n",
1375 p->status, p->is_dying, p->dpd_support, p->rmconf->dpd_interval);
1376 }
1377 }
1378 }
1379
1380 return status;
1381 }
1382 #endif