]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/handler.c
1 /* $Id: handler.c,v 1.13.4.4 2005/07/14 12:00:36 vanhu Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
52 #include "grabmyaddr.h"
53 #include "algorithm.h"
54 #include "crypto_openssl.h"
57 #include "isakmp_var.h"
61 #include "isakmp_xauth.h"
62 #include "isakmp_cfg.h"
64 #include "isakmp_inf.h"
66 #include "remoteconf.h"
67 #include "localconf.h"
70 #include "nattraversal.h"
76 static LIST_HEAD(_ph1tree_
, ph1handle
) ph1tree
;
77 static LIST_HEAD(_ph2tree_
, ph2handle
) ph2tree
;
78 static LIST_HEAD(_ctdtree_
, contacted
) ctdtree
;
79 static LIST_HEAD(_rcptree_
, recvdpkt
) rcptree
;
81 static void del_recvdpkt
__P((struct recvdpkt
*));
82 static void rem_recvdpkt
__P((struct recvdpkt
*));
83 static void sweep_recvdpkt
__P((void *));
86 * functions about management of the isakmp status table
88 /* %%% management phase 1 handler */
90 * search for isakmpsa handler with isakmp index.
93 extern caddr_t
val2str(const char *, size_t);
101 LIST_FOREACH(p
, &ph1tree
, chain
) {
102 if (p
->status
== PHASE1ST_EXPIRED
)
104 if (memcmp(&p
->index
, index
, sizeof(*index
)) == 0)
112 * search for isakmp handler by i_ck in index.
115 getph1byindex0(index
)
120 LIST_FOREACH(p
, &ph1tree
, chain
) {
121 if (p
->status
== PHASE1ST_EXPIRED
)
123 if (memcmp(&p
->index
, index
, sizeof(cookie_t
)) == 0)
131 * search for isakmpsa handler by source and remote address.
132 * don't use port number to search because this function search
133 * with phase 2's destinaion.
136 getph1byaddr(local
, remote
)
137 struct sockaddr
*local
, *remote
;
141 LIST_FOREACH(p
, &ph1tree
, chain
) {
142 if (p
->status
== PHASE1ST_EXPIRED
)
144 if (CMPSADDR(local
, p
->local
) == 0
145 && CMPSADDR(remote
, p
->remote
) == 0)
153 getph1byaddrwop(local
, remote
)
154 struct sockaddr
*local
, *remote
;
158 LIST_FOREACH(p
, &ph1tree
, chain
) {
159 if (p
->status
== PHASE1ST_EXPIRED
)
161 if (cmpsaddrwop(local
, p
->local
) == 0
162 && cmpsaddrwop(remote
, p
->remote
) == 0)
170 * search for isakmpsa handler by remote address.
171 * don't use port number to search because this function search
172 * with phase 2's destinaion.
175 getph1bydstaddrwop(remote
)
176 struct sockaddr
*remote
;
180 LIST_FOREACH(p
, &ph1tree
, chain
) {
181 if (p
->status
== PHASE1ST_EXPIRED
)
183 if (cmpsaddrwop(remote
, p
->remote
) == 0)
196 struct ph1handle
*iph1
;
201 /* get length of buffer */
202 LIST_FOREACH(iph1
, &ph1tree
, chain
)
205 buf
= vmalloc(cnt
* sizeof(struct ph1dump
));
207 plog(LLV_ERROR
, LOCATION
, NULL
,
208 "failed to get buffer\n");
211 pd
= (struct ph1dump
*)buf
->v
;
213 LIST_FOREACH(iph1
, &ph1tree
, chain
) {
214 memcpy(&pd
->index
, &iph1
->index
, sizeof(iph1
->index
));
215 pd
->status
= iph1
->status
;
216 pd
->side
= iph1
->side
;
217 memcpy(&pd
->remote
, iph1
->remote
, sysdep_sa_len(iph1
->remote
));
218 memcpy(&pd
->local
, iph1
->local
, sysdep_sa_len(iph1
->local
));
219 pd
->version
= iph1
->version
;
220 pd
->etype
= iph1
->etype
;
221 pd
->created
= iph1
->created
;
222 pd
->ph2cnt
= iph1
->ph2cnt
;
230 * create new isakmp Phase 1 status record to handle isakmp in Phase1
235 struct ph1handle
*iph1
;
237 /* create new iph1 */
238 iph1
= racoon_calloc(1, sizeof(*iph1
));
242 iph1
->status
= PHASE1ST_SPAWN
;
245 iph1
->dpd_support
= 0;
246 iph1
->dpd_lastack
= 0;
249 iph1
->dpd_r_u
= NULL
;
256 * delete new isakmp Phase 1 status record to handle isakmp in Phase1
260 struct ph1handle
*iph1
;
262 /* SA down shell script hook */
264 script_hook(iph1
, SCRIPT_PHASE1_DOWN
);
266 EVT_PUSH(iph1
->local
, iph1
->remote
, EVTT_PHASE1_DOWN
, NULL
);
270 if (iph1
->natt_flags
& NAT_KA_QUEUED
)
271 natt_keepalive_remove (iph1
->local
, iph1
->remote
);
272 #endif /* __APPLE__ */
273 if (iph1
->natt_options
) {
274 racoon_free(iph1
->natt_options
);
275 iph1
->natt_options
= NULL
;
280 if (iph1
->dpd_r_u
!= NULL
)
281 SCHED_KILL(iph1
->dpd_r_u
);
285 racoon_free(iph1
->remote
);
289 racoon_free(iph1
->local
);
293 if (iph1
->approval
) {
294 delisakmpsa(iph1
->approval
);
295 iph1
->approval
= NULL
;
300 isakmp_cfg_rmstate(iph1
);
303 VPTRINIT(iph1
->authstr
);
305 sched_scrub_param(iph1
);
309 VPTRINIT(iph1
->sendbuf
);
311 VPTRINIT(iph1
->dhpriv
);
312 VPTRINIT(iph1
->dhpub
);
313 VPTRINIT(iph1
->dhpub_p
);
314 VPTRINIT(iph1
->dhgxy
);
315 VPTRINIT(iph1
->nonce
);
316 VPTRINIT(iph1
->nonce_p
);
317 VPTRINIT(iph1
->skeyid
);
318 VPTRINIT(iph1
->skeyid_d
);
319 VPTRINIT(iph1
->skeyid_a
);
320 VPTRINIT(iph1
->skeyid_e
);
322 VPTRINIT(iph1
->hash
);
324 VPTRINIT(iph1
->sig_p
);
325 oakley_delcert(iph1
->cert
);
327 oakley_delcert(iph1
->cert_p
);
329 oakley_delcert(iph1
->crl_p
);
331 oakley_delcert(iph1
->cr_p
);
334 VPTRINIT(iph1
->id_p
);
337 oakley_delivm(iph1
->ivm
);
342 VPTRINIT(iph1
->sa_ret
);
345 VPTRINIT(iph1
->gi_i
);
346 VPTRINIT(iph1
->gi_r
);
348 gssapi_free_state(iph1
);
355 * create new isakmp Phase 1 status record to handle isakmp in Phase1
359 struct ph1handle
*iph1
;
362 if (iph1
->remote
== NULL
) {
363 plog(LLV_ERROR
, LOCATION
, NULL
,
364 "invalid isakmp SA handler. no remote address.\n");
367 LIST_INSERT_HEAD(&ph1tree
, iph1
, chain
);
374 struct ph1handle
*iph1
;
376 LIST_REMOVE(iph1
, chain
);
385 struct ph1handle
*p
, *next
;
387 for (p
= LIST_FIRST(&ph1tree
); p
; p
= next
) {
388 next
= LIST_NEXT(p
, chain
);
390 /* send delete information */
391 if (p
->status
== PHASE1ST_ESTABLISHED
)
392 isakmp_info_send_d1(p
);
405 /* %%% management phase 2 handler */
407 * search ph2handle with policy id.
415 LIST_FOREACH(p
, &ph2tree
, chain
) {
417 * there are ph2handle independent on policy
418 * such like informational exchange.
428 * search ph2handle with sequence number.
436 LIST_FOREACH(p
, &ph2tree
, chain
) {
445 * search ph2handle with message id.
448 getph2bymsgid(iph1
, msgid
)
449 struct ph1handle
*iph1
;
454 LIST_FOREACH(p
, &ph2tree
, chain
) {
455 if (p
->msgid
== msgid
)
463 getph2byid(src
, dst
, spid
)
464 struct sockaddr
*src
, *dst
;
469 LIST_FOREACH(p
, &ph2tree
, chain
) {
470 if (spid
== p
->spid
&&
471 CMPSADDR(src
, p
->src
) == 0 &&
472 CMPSADDR(dst
, p
->dst
) == 0)
480 getph2bysaddr(src
, dst
)
481 struct sockaddr
*src
, *dst
;
485 LIST_FOREACH(p
, &ph2tree
, chain
) {
486 if (cmpsaddrstrict(src
, p
->src
) == 0 &&
487 cmpsaddrstrict(dst
, p
->dst
) == 0)
495 * call by pk_recvexpire().
498 getph2bysaidx(src
, dst
, proto_id
, spi
)
499 struct sockaddr
*src
, *dst
;
503 struct ph2handle
*iph2
;
506 LIST_FOREACH(iph2
, &ph2tree
, chain
) {
507 if (iph2
->proposal
== NULL
&& iph2
->approval
== NULL
)
509 if (iph2
->approval
!= NULL
) {
510 for (pr
= iph2
->approval
->head
; pr
!= NULL
;
512 if (proto_id
!= pr
->proto_id
)
514 if (spi
== pr
->spi
|| spi
== pr
->spi_p
)
517 } else if (iph2
->proposal
!= NULL
) {
518 for (pr
= iph2
->proposal
->head
; pr
!= NULL
;
520 if (proto_id
!= pr
->proto_id
)
532 * create new isakmp Phase 2 status record to handle isakmp in Phase2
537 struct ph2handle
*iph2
= NULL
;
539 /* create new iph2 */
540 iph2
= racoon_calloc(1, sizeof(*iph2
));
544 iph2
->status
= PHASE1ST_SPAWN
;
550 * initialize ph2handle
551 * NOTE: don't initialize src/dst.
552 * SPI in the proposal is cleared.
556 struct ph2handle
*iph2
;
558 sched_scrub_param(iph2
);
562 VPTRINIT(iph2
->sendbuf
);
563 VPTRINIT(iph2
->msg1
);
565 /* clear spi, keep variables in the proposal */
566 if (iph2
->proposal
) {
568 for (pr
= iph2
->proposal
->head
; pr
!= NULL
; pr
= pr
->next
)
573 if (iph2
->approval
) {
574 flushsaprop(iph2
->approval
);
575 iph2
->approval
= NULL
;
578 /* clear the generated policy */
579 if (iph2
->spidx_gen
) {
580 delsp_bothdir((struct policyindex
*)iph2
->spidx_gen
);
581 racoon_free(iph2
->spidx_gen
);
582 iph2
->spidx_gen
= NULL
;
586 oakley_dhgrp_free(iph2
->pfsgrp
);
590 VPTRINIT(iph2
->dhpriv
);
591 VPTRINIT(iph2
->dhpub
);
592 VPTRINIT(iph2
->dhpub_p
);
593 VPTRINIT(iph2
->dhgxy
);
595 VPTRINIT(iph2
->id_p
);
596 VPTRINIT(iph2
->nonce
);
597 VPTRINIT(iph2
->nonce_p
);
599 VPTRINIT(iph2
->sa_ret
);
602 oakley_delivm(iph2
->ivm
);
608 * delete new isakmp Phase 2 status record to handle isakmp in Phase2
612 struct ph2handle
*iph2
;
617 racoon_free(iph2
->src
);
621 racoon_free(iph2
->dst
);
625 racoon_free(iph2
->src_id
);
629 racoon_free(iph2
->dst_id
);
633 if (iph2
->proposal
) {
634 flushsaprop(iph2
->proposal
);
635 iph2
->proposal
= NULL
;
642 * create new isakmp Phase 2 status record to handle isakmp in Phase2
646 struct ph2handle
*iph2
;
648 LIST_INSERT_HEAD(&ph2tree
, iph2
, chain
);
655 struct ph2handle
*iph2
;
657 LIST_REMOVE(iph2
, chain
);
669 struct ph2handle
*p
, *next
;
671 for (p
= LIST_FIRST(&ph2tree
); p
; p
= next
) {
672 next
= LIST_NEXT(p
, chain
);
674 /* send delete information */
675 if (p
->status
== PHASE2ST_ESTABLISHED
)
676 isakmp_info_send_d2(p
);
686 * Delete all Phase 2 handlers for this src/dst/proto. This
687 * is used during INITIAL-CONTACT processing (so no need to
688 * send a message to the peer).
691 deleteallph2(src
, dst
, proto_id
)
692 struct sockaddr
*src
, *dst
;
695 struct ph2handle
*iph2
, *next
;
698 for (iph2
= LIST_FIRST(&ph2tree
); iph2
!= NULL
; iph2
= next
) {
699 next
= LIST_NEXT(iph2
, chain
);
700 if (iph2
->proposal
== NULL
&& iph2
->approval
== NULL
)
702 if (iph2
->approval
!= NULL
) {
703 for (pr
= iph2
->approval
->head
; pr
!= NULL
;
705 if (proto_id
== pr
->proto_id
)
708 } else if (iph2
->proposal
!= NULL
) {
709 for (pr
= iph2
->proposal
->head
; pr
!= NULL
;
711 if (proto_id
== pr
->proto_id
)
726 struct ph1handle
*iph1
;
727 struct ph2handle
*iph2
;
730 LIST_INSERT_HEAD(&iph1
->ph2tree
, iph2
, ph1bind
);
735 struct ph2handle
*iph2
;
737 if (iph2
->ph1
!= NULL
) {
739 LIST_REMOVE(iph2
, ph1bind
);
743 /* %%% management contacted list */
745 * search contacted list.
749 struct sockaddr
*remote
;
753 LIST_FOREACH(p
, &ctdtree
, chain
) {
754 if (cmpsaddrstrict(remote
, p
->remote
) == 0)
762 * create new isakmp Phase 2 status record to handle isakmp in Phase2
766 struct sockaddr
*remote
;
768 struct contacted
*new;
770 /* create new iph2 */
771 new = racoon_calloc(1, sizeof(*new));
775 new->remote
= dupsaddr(remote
);
777 LIST_INSERT_HEAD(&ctdtree
, new, chain
);
786 struct contacted
*c
, *next
;
788 for (c
= LIST_FIRST(&ctdtree
); c
; c
= next
) {
789 next
= LIST_NEXT(c
, chain
);
790 LIST_REMOVE(c
, chain
);
791 racoon_free(c
->remote
);
803 * check the response has been sent to the peer. when not, simply reply
804 * the buffered packet to the peer.
806 * 0: the packet is received at the first time.
807 * 1: the packet was processed before.
808 * 2: the packet was processed before, but the address mismatches.
809 * -1: error happened.
812 check_recvdpkt(remote
, local
, rbuf
)
813 struct sockaddr
*remote
, *local
;
821 /* set current time */
824 hash
= eay_md5_one(rbuf
);
826 plog(LLV_ERROR
, LOCATION
, NULL
,
827 "failed to allocate buffer.\n");
831 LIST_FOREACH(r
, &rcptree
, chain
) {
832 if (memcmp(hash
->v
, r
->hash
->v
, r
->hash
->l
) == 0)
837 /* this is the first time to receive the packet */
842 * the packet was processed before, but the remote address mismatches.
844 if (cmpsaddrstrict(remote
, r
->remote
) != 0)
848 * it should not check the local address because the packet
849 * may arrive at other interface.
852 /* check the previous time to send */
853 if (t
- r
->time_send
< 1) {
854 plog(LLV_WARNING
, LOCATION
, NULL
,
855 "the packet retransmitted in a short time from %s\n",
857 /*XXX should it be error ? */
860 /* select the socket to be sent */
861 s
= getsockmyaddr(r
->local
);
865 /* resend the packet if needed */
866 len
= sendfromto(s
, r
->sendbuf
->v
, r
->sendbuf
->l
,
867 r
->local
, r
->remote
, lcconf
->count_persend
);
869 plog(LLV_ERROR
, LOCATION
, NULL
, "sendfromto failed\n");
873 /* check the retry counter */
875 if (r
->retry_counter
<= 0) {
878 plog(LLV_DEBUG
, LOCATION
, NULL
,
879 "deleted the retransmission packet to %s.\n",
888 * adding a hash of received packet into the received list.
891 add_recvdpkt(remote
, local
, sbuf
, rbuf
)
892 struct sockaddr
*remote
, *local
;
893 vchar_t
*sbuf
, *rbuf
;
895 struct recvdpkt
*new = NULL
;
897 if (lcconf
->retry_counter
== 0) {
898 /* no need to add it */
902 new = racoon_calloc(1, sizeof(*new));
904 plog(LLV_ERROR
, LOCATION
, NULL
,
905 "failed to allocate buffer.\n");
909 new->hash
= eay_md5_one(rbuf
);
911 plog(LLV_ERROR
, LOCATION
, NULL
,
912 "failed to allocate buffer.\n");
916 new->remote
= dupsaddr(remote
);
917 if (new->remote
== NULL
) {
918 plog(LLV_ERROR
, LOCATION
, NULL
,
919 "failed to allocate buffer.\n");
923 new->local
= dupsaddr(local
);
924 if (new->local
== NULL
) {
925 plog(LLV_ERROR
, LOCATION
, NULL
,
926 "failed to allocate buffer.\n");
930 new->sendbuf
= vdup(sbuf
);
931 if (new->sendbuf
== NULL
) {
932 plog(LLV_ERROR
, LOCATION
, NULL
,
933 "failed to allocate buffer.\n");
938 new->retry_counter
= lcconf
->retry_counter
;
940 new->created
= time(NULL
);
942 LIST_INSERT_HEAD(&rcptree
, new, chain
);
952 racoon_free(r
->remote
);
954 racoon_free(r
->local
);
966 LIST_REMOVE(r
, chain
);
970 sweep_recvdpkt(dummy
)
973 struct recvdpkt
*r
, *next
;
976 /* set current time */
979 /* set the lifetime of the retransmission */
980 lt
= lcconf
->retry_counter
* lcconf
->retry_interval
;
982 for (r
= LIST_FIRST(&rcptree
); r
; r
= next
) {
983 next
= LIST_NEXT(r
, chain
);
985 if (t
- r
->created
> lt
) {
991 sched_new(lt
, sweep_recvdpkt
, NULL
);
997 struct recvdpkt
*r
, *next
;
999 for (r
= LIST_FIRST(&rcptree
); r
; r
= next
) {
1000 next
= LIST_NEXT(r
, chain
);
1009 time_t lt
= lcconf
->retry_counter
* lcconf
->retry_interval
;
1011 LIST_INIT(&rcptree
);
1013 sched_new(lt
, sweep_recvdpkt
, NULL
);
1016 #ifdef ENABLE_HYBRID
1018 * Returns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
1019 * This should be in isakmp_cfg.c but ph1tree being private, it must be there
1022 exclude_cfg_addr(addr
)
1023 const struct sockaddr
*addr
;
1025 struct ph1handle
*p
;
1026 struct sockaddr_in
*sin
;
1028 LIST_FOREACH(p
, &ph1tree
, chain
) {
1029 if ((p
->mode_cfg
!= NULL
) &&
1030 (p
->mode_cfg
->flags
& ISAKMP_CFG_GOT_ADDR4
) &&
1031 (addr
->sa_family
== AF_INET
)) {
1032 sin
= (struct sockaddr_in
*)addr
;
1033 if (sin
->sin_addr
.s_addr
== p
->mode_cfg
->addr4
.s_addr
)