]>
git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/handler.c
1 /* $KAME: handler.c,v 1.57 2002/01/21 08:45:54 sakane 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
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
50 #include "grabmyaddr.h"
51 #include "algorithm.h"
52 #include "crypto_openssl.h"
55 #include "isakmp_var.h"
57 #include "isakmp_inf.h"
59 #include "remoteconf.h"
60 #include "localconf.h"
68 static LIST_HEAD(_ph1tree_
, ph1handle
) ph1tree
;
69 static LIST_HEAD(_ph2tree_
, ph2handle
) ph2tree
;
70 static LIST_HEAD(_ctdtree_
, contacted
) ctdtree
;
71 static LIST_HEAD(_rcptree_
, recvdpkt
) rcptree
;
73 static void del_recvdpkt
__P((struct recvdpkt
*));
74 static void rem_recvdpkt
__P((struct recvdpkt
*));
75 static void sweep_recvdpkt
__P((void *));
78 * functions about management of the isakmp status table
80 /* %%% management phase 1 handler */
82 * search for isakmpsa handler with isakmp index.
85 extern caddr_t
val2str(const char *, size_t);
93 LIST_FOREACH(p
, &ph1tree
, chain
) {
94 if (p
->status
== PHASE1ST_EXPIRED
)
96 if (memcmp(&p
->index
, index
, sizeof(*index
)) == 0)
104 * search for isakmp handler by i_ck in index.
107 getph1byindex0(index
)
112 LIST_FOREACH(p
, &ph1tree
, chain
) {
113 if (p
->status
== PHASE1ST_EXPIRED
)
115 if (memcmp(&p
->index
, index
, sizeof(cookie_t
)) == 0)
123 * search for isakmpsa handler by remote address.
124 * don't use port number to search because this function search
125 * with phase 2's destinaion.
128 getph1byaddr(local
, remote
)
129 struct sockaddr
*local
, *remote
;
133 LIST_FOREACH(p
, &ph1tree
, chain
) {
134 if (p
->status
== PHASE1ST_EXPIRED
)
136 if (cmpsaddrwop(local
, p
->local
) == 0
137 && cmpsaddrwop(remote
, p
->remote
) == 0)
150 struct ph1handle
*iph1
;
155 /* get length of buffer */
156 LIST_FOREACH(iph1
, &ph1tree
, chain
)
159 buf
= vmalloc(cnt
* sizeof(struct ph1dump
));
161 plog(LLV_ERROR
, LOCATION
, NULL
,
162 "failed to get buffer\n");
165 pd
= (struct ph1dump
*)buf
->v
;
167 LIST_FOREACH(iph1
, &ph1tree
, chain
) {
168 memcpy(&pd
->index
, &iph1
->index
, sizeof(iph1
->index
));
169 pd
->status
= iph1
->status
;
170 pd
->side
= iph1
->side
;
171 memcpy(&pd
->remote
, iph1
->remote
, iph1
->remote
->sa_len
);
172 memcpy(&pd
->local
, iph1
->local
, iph1
->local
->sa_len
);
173 pd
->version
= iph1
->version
;
174 pd
->etype
= iph1
->etype
;
175 pd
->created
= iph1
->created
;
176 pd
->ph2cnt
= iph1
->ph2cnt
;
184 * create new isakmp Phase 1 status record to handle isakmp in Phase1
189 struct ph1handle
*iph1
;
191 /* create new iph1 */
192 iph1
= racoon_calloc(1, sizeof(*iph1
));
196 iph1
->status
= PHASE1ST_SPAWN
;
202 * delete new isakmp Phase 1 status record to handle isakmp in Phase1
206 struct ph1handle
*iph1
;
209 racoon_free(iph1
->remote
);
213 racoon_free(iph1
->local
);
217 VPTRINIT(iph1
->authstr
);
219 sched_scrub_param(iph1
);
223 VPTRINIT(iph1
->sendbuf
);
225 VPTRINIT(iph1
->dhpriv
);
226 VPTRINIT(iph1
->dhpub
);
227 VPTRINIT(iph1
->dhpub_p
);
228 VPTRINIT(iph1
->dhgxy
);
229 VPTRINIT(iph1
->nonce
);
230 VPTRINIT(iph1
->nonce_p
);
231 VPTRINIT(iph1
->skeyid
);
232 VPTRINIT(iph1
->skeyid_d
);
233 VPTRINIT(iph1
->skeyid_a
);
234 VPTRINIT(iph1
->skeyid_e
);
236 VPTRINIT(iph1
->hash
);
238 VPTRINIT(iph1
->sig_p
);
239 oakley_delcert(iph1
->cert
);
241 oakley_delcert(iph1
->cert_p
);
243 oakley_delcert(iph1
->crl_p
);
245 oakley_delcert(iph1
->cr_p
);
248 VPTRINIT(iph1
->id_p
);
251 oakley_delivm(iph1
->ivm
);
256 VPTRINIT(iph1
->sa_ret
);
259 VPTRINIT(iph1
->gi_i
);
260 VPTRINIT(iph1
->gi_r
);
262 gssapi_free_state(iph1
);
266 VPTRINIT(iph1
->local_natd
);
267 VPTRINIT(iph1
->remote_natd
);
274 * create new isakmp Phase 1 status record to handle isakmp in Phase1
278 struct ph1handle
*iph1
;
281 if (iph1
->remote
== NULL
) {
282 plog(LLV_ERROR
, LOCATION
, NULL
,
283 "invalid isakmp SA handler. no remote address.\n");
286 LIST_INSERT_HEAD(&ph1tree
, iph1
, chain
);
293 struct ph1handle
*iph1
;
295 LIST_REMOVE(iph1
, chain
);
304 struct ph1handle
*p
, *next
;
306 for (p
= LIST_FIRST(&ph1tree
); p
; p
= next
) {
307 next
= LIST_NEXT(p
, chain
);
309 /* send delete information */
310 if (p
->status
== PHASE1ST_ESTABLISHED
)
311 isakmp_info_send_d1(p
);
324 /* %%% management phase 2 handler */
326 * search ph2handle with policy id.
334 LIST_FOREACH(p
, &ph2tree
, chain
) {
336 * there are ph2handle independent on policy
337 * such like informational exchange.
347 * search ph2handle with sequence number.
355 LIST_FOREACH(p
, &ph2tree
, chain
) {
364 * search ph2handle with message id.
367 getph2bymsgid(iph1
, msgid
)
368 struct ph1handle
*iph1
;
373 LIST_FOREACH(p
, &ph2tree
, chain
) {
374 if (p
->msgid
== msgid
)
382 * call by pk_recvexpire().
385 getph2bysaidx(src
, dst
, proto_id
, spi
)
386 struct sockaddr
*src
, *dst
;
390 struct ph2handle
*iph2
;
393 LIST_FOREACH(iph2
, &ph2tree
, chain
) {
394 if (iph2
->proposal
== NULL
&& iph2
->approval
== NULL
)
396 if (iph2
->approval
!= NULL
) {
397 for (pr
= iph2
->approval
->head
; pr
!= NULL
;
399 if (proto_id
!= pr
->proto_id
)
401 if (spi
== pr
->spi
|| spi
== pr
->spi_p
)
404 } else if (iph2
->proposal
!= NULL
) {
405 for (pr
= iph2
->proposal
->head
; pr
!= NULL
;
407 if (proto_id
!= pr
->proto_id
)
419 * create new isakmp Phase 2 status record to handle isakmp in Phase2
424 struct ph2handle
*iph2
= NULL
;
426 /* create new iph2 */
427 iph2
= racoon_calloc(1, sizeof(*iph2
));
431 iph2
->status
= PHASE1ST_SPAWN
;
437 * initialize ph2handle
438 * NOTE: don't initialize src/dst.
439 * SPI in the proposal is cleared.
443 struct ph2handle
*iph2
;
445 sched_scrub_param(iph2
);
449 VPTRINIT(iph2
->sendbuf
);
450 VPTRINIT(iph2
->msg1
);
452 /* clear spi, keep variables in the proposal */
453 if (iph2
->proposal
) {
455 for (pr
= iph2
->proposal
->head
; pr
!= NULL
; pr
= pr
->next
)
460 if (iph2
->approval
) {
461 flushsaprop(iph2
->approval
);
462 iph2
->approval
= NULL
;
465 /* clear the generated policy */
466 if (iph2
->spidx_gen
) {
467 delsp_bothdir((struct policyindex
*)iph2
->spidx_gen
);
468 racoon_free(iph2
->spidx_gen
);
469 iph2
->spidx_gen
= NULL
;
473 oakley_dhgrp_free(iph2
->pfsgrp
);
477 VPTRINIT(iph2
->dhpriv
);
478 VPTRINIT(iph2
->dhpub
);
479 VPTRINIT(iph2
->dhpub_p
);
480 VPTRINIT(iph2
->dhgxy
);
482 VPTRINIT(iph2
->id_p
);
483 VPTRINIT(iph2
->nonce
);
484 VPTRINIT(iph2
->nonce_p
);
486 VPTRINIT(iph2
->sa_ret
);
489 oakley_delivm(iph2
->ivm
);
495 * delete new isakmp Phase 2 status record to handle isakmp in Phase2
499 struct ph2handle
*iph2
;
504 racoon_free(iph2
->src
);
508 racoon_free(iph2
->dst
);
512 racoon_free(iph2
->src_id
);
516 racoon_free(iph2
->dst_id
);
520 if (iph2
->proposal
) {
521 flushsaprop(iph2
->proposal
);
522 iph2
->proposal
= NULL
;
529 * create new isakmp Phase 2 status record to handle isakmp in Phase2
533 struct ph2handle
*iph2
;
535 LIST_INSERT_HEAD(&ph2tree
, iph2
, chain
);
542 struct ph2handle
*iph2
;
544 LIST_REMOVE(iph2
, chain
);
556 struct ph2handle
*p
, *next
;
558 for (p
= LIST_FIRST(&ph2tree
); p
; p
= next
) {
559 next
= LIST_NEXT(p
, chain
);
561 /* send delete information */
562 if (p
->status
== PHASE2ST_ESTABLISHED
)
563 isakmp_info_send_d2(p
);
572 * Delete all Phase 2 handlers for this src/dst/proto. This
573 * is used during INITIAL-CONTACT processing (so no need to
574 * send a message to the peer).
577 deleteallph2(src
, dst
, proto_id
)
578 struct sockaddr
*src
, *dst
;
581 struct ph2handle
*iph2
, *next
;
584 for (iph2
= LIST_FIRST(&ph2tree
); iph2
!= NULL
; iph2
= next
) {
585 next
= LIST_NEXT(iph2
, chain
);
586 if (iph2
->proposal
== NULL
&& iph2
->approval
== NULL
)
588 if (iph2
->approval
!= NULL
) {
589 for (pr
= iph2
->approval
->head
; pr
!= NULL
;
591 if (proto_id
== pr
->proto_id
)
594 } else if (iph2
->proposal
!= NULL
) {
595 for (pr
= iph2
->proposal
->head
; pr
!= NULL
;
597 if (proto_id
== pr
->proto_id
)
612 struct ph1handle
*iph1
;
613 struct ph2handle
*iph2
;
616 LIST_INSERT_HEAD(&iph1
->ph2tree
, iph2
, ph1bind
);
621 struct ph2handle
*iph2
;
623 if (iph2
->ph1
!= NULL
) {
625 LIST_REMOVE(iph2
, ph1bind
);
629 /* %%% management contacted list */
631 * search contacted list.
635 struct sockaddr
*remote
;
639 LIST_FOREACH(p
, &ctdtree
, chain
) {
640 if (cmpsaddrstrict(remote
, p
->remote
) == 0)
648 * create new isakmp Phase 2 status record to handle isakmp in Phase2
652 struct sockaddr
*remote
;
654 struct contacted
*new;
656 /* create new iph2 */
657 new = racoon_calloc(1, sizeof(*new));
661 new->remote
= dupsaddr(remote
);
663 LIST_INSERT_HEAD(&ctdtree
, new, chain
);
675 * check the response has been sent to the peer. when not, simply reply
676 * the buffered packet to the peer.
678 * 0: the packet is received at the first time.
679 * 1: the packet was processed before.
680 * 2: the packet was processed before, but the address mismatches.
681 * -1: error happened.
684 check_recvdpkt(remote
, local
, rbuf
)
685 struct sockaddr
*remote
, *local
;
693 /* set current time */
696 hash
= eay_md5_one(rbuf
);
698 plog(LLV_ERROR
, LOCATION
, NULL
,
699 "failed to allocate buffer.\n");
703 LIST_FOREACH(r
, &rcptree
, chain
) {
704 if (memcmp(hash
->v
, r
->hash
->v
, r
->hash
->l
) == 0)
709 /* this is the first time to receive the packet */
714 * the packet was processed before, but the remote address mismatches.
716 if (cmpsaddrstrict(remote
, r
->remote
) != 0)
720 * it should not check the local address because the packet
721 * may arrive at other interface.
724 /* check the previous time to send */
725 if (t
- r
->time_send
< 1) {
726 plog(LLV_WARNING
, LOCATION
, NULL
,
727 "the packet retransmitted in a short time from %s\n",
729 /*XXX should it be error ? */
732 /* select the socket to be sent */
733 s
= getsockmyaddr(r
->local
);
737 /* resend the packet if needed */
738 len
= sendfromto(s
, r
->sendbuf
->v
, r
->sendbuf
->l
,
739 r
->local
, r
->remote
, lcconf
->count_persend
);
741 plog(LLV_ERROR
, LOCATION
, NULL
, "sendfromto failed\n");
745 /* check the retry counter */
747 if (r
->retry_counter
<= 0) {
750 plog(LLV_DEBUG
, LOCATION
, NULL
,
751 "deleted the retransmission packet to %s.\n",
760 * adding a hash of received packet into the received list.
763 add_recvdpkt(remote
, local
, sbuf
, rbuf
)
764 struct sockaddr
*remote
, *local
;
765 vchar_t
*sbuf
, *rbuf
;
767 struct recvdpkt
*new = NULL
;
769 if (lcconf
->retry_counter
== 0) {
770 /* no need to add it */
774 new = racoon_calloc(1, sizeof(*new));
776 plog(LLV_ERROR
, LOCATION
, NULL
,
777 "failed to allocate buffer.\n");
781 new->hash
= eay_md5_one(rbuf
);
783 plog(LLV_ERROR
, LOCATION
, NULL
,
784 "failed to allocate buffer.\n");
788 new->remote
= dupsaddr(remote
);
789 if (new->remote
== NULL
) {
790 plog(LLV_ERROR
, LOCATION
, NULL
,
791 "failed to allocate buffer.\n");
795 new->local
= dupsaddr(local
);
796 if (new->local
== NULL
) {
797 plog(LLV_ERROR
, LOCATION
, NULL
,
798 "failed to allocate buffer.\n");
802 new->sendbuf
= vdup(sbuf
);
803 if (new->sendbuf
== NULL
) {
804 plog(LLV_ERROR
, LOCATION
, NULL
,
805 "failed to allocate buffer.\n");
810 new->retry_counter
= lcconf
->retry_counter
;
812 new->created
= time(NULL
);
814 LIST_INSERT_HEAD(&rcptree
, new, chain
);
824 racoon_free(r
->remote
);
826 racoon_free(r
->local
);
838 LIST_REMOVE(r
, chain
);
842 sweep_recvdpkt(dummy
)
845 struct recvdpkt
*r
, *next
;
848 /* set current time */
851 /* set the lifetime of the retransmission */
852 lt
= lcconf
->retry_counter
* lcconf
->retry_interval
;
854 for (r
= LIST_FIRST(&rcptree
); r
; r
= next
) {
855 next
= LIST_NEXT(r
, chain
);
857 if (t
- r
->created
> lt
) {
863 sched_new(lt
, sweep_recvdpkt
, NULL
);
869 time_t lt
= lcconf
->retry_counter
* lcconf
->retry_interval
;
873 sched_new(lt
, sweep_recvdpkt
, NULL
);