1 /* $Id: proposal.c,v 1.13.8.5 2005/07/28 05:05:52 manubsd 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/param.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/queue.h>
39 #include <netinet/in.h>
40 #ifdef HAVE_NETINET6_IPSEC
41 # include <netinet6/ipsec.h>
43 # include <netinet/ipsec.h>
60 #include "isakmp_var.h"
62 #include "ipsec_doi.h"
63 #include "algorithm.h"
66 #include "localconf.h"
67 #include "remoteconf.h"
73 #include "nattraversal.h"
75 #include "ikev2_rfc.h"
78 * modules for ipsec sa spec
85 new = racoon_calloc(1, sizeof(*new));
97 new = racoon_calloc(1, sizeof(*new));
104 /* set saprop to last part of the prop tree */
107 struct saprop
**head
;
117 for (p
= *head
; p
->next
; p
= p
->next
)
124 /* set saproto to the end of the proto tree in saprop */
132 for (p
= pp
->head
; p
&& p
->next
; p
= p
->next
)
142 /* set saproto to the top of the proto tree in saprop */
144 inssaprotorev(pp
, new)
148 new->next
= pp
->head
;
159 new = racoon_calloc(1, sizeof(*new));
166 /* set saproto to last part of the proto tree in saprop */
174 for (tr
= pr
->head
; tr
&& tr
->next
; tr
= tr
->next
)
185 satrns_remove_from_list(struct satrns
**listptr
, struct satrns
*trns
)
188 struct satrns
**ptr
= listptr
;
200 ptr
= &((*ptr
)->next
);
207 saprop_udp_encap (struct saproto
*pr
)
209 switch (pr
->encmode
) {
210 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
211 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
212 pr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TUNNEL
;
215 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
216 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
217 pr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TRNS
;
224 saprop_adjust_encmode (struct saproto
*pr2
, struct saproto
*pr1
)
228 if (natt_udp_encap(pr2
->encmode
)) {
230 saprop_udp_encap(pr2
);
231 plog(ASL_LEVEL_INFO
, "Adjusting my encmode %s(%d)->%s(%d)\n",
232 s_ipsecdoi_encmode(prev
),
234 s_ipsecdoi_encmode(pr2
->encmode
),
237 if (natt_udp_encap(pr1
->encmode
)) {
239 saprop_udp_encap(pr1
);
240 plog(ASL_LEVEL_INFO
, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
241 s_ipsecdoi_encmode(prev
),
243 s_ipsecdoi_encmode(pr1
->encmode
),
247 #endif // ENABLE_NATT
250 * take a single match between saprop. allocate a new proposal and return it
251 * for future use (like picking single proposal from a bundle).
252 * pp1: peer's proposal.
254 * NOTE: In the case of initiator, must be ensured that there is no
255 * modification of the proposal by calling cmp_aproppair_i() before
257 * XXX cannot understand the comment!
260 cmpsaprop_alloc(ph1
, pp1
, pp2
, side
)
261 phase1_handle_t
*ph1
;
262 const struct saprop
*pp1
, *pp2
;
265 struct saprop
*newpp
= NULL
;
266 struct saproto
*pr1
, *pr2
, *newpr
= NULL
;
267 struct satrns
*tr1
, *tr2
, *newtr
;
268 const int ordermatters
= 0;
275 "failed to allocate saprop.\n");
278 newpp
->prop_no
= pp1
->prop_no
;
280 /* see proposal.h about lifetime/key length and PFS selection. */
282 /* check time/bytes lifetime and PFS */
283 switch (ph1
->rmconf
->pcheck_level
) {
284 case PROP_CHECK_OBEY
:
285 newpp
->lifetime
= pp1
->lifetime
;
286 newpp
->lifebyte
= pp1
->lifebyte
;
287 newpp
->pfs_group
= pp1
->pfs_group
;
290 case PROP_CHECK_STRICT
:
291 if (pp1
->lifetime
> pp2
->lifetime
) {
293 "long lifetime proposed: "
295 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
298 if (pp1
->lifebyte
> pp2
->lifebyte
) {
300 "long lifebyte proposed: "
302 pp2
->lifebyte
, pp1
->lifebyte
);
305 newpp
->lifetime
= pp1
->lifetime
;
306 newpp
->lifebyte
= pp1
->lifebyte
;
309 if (pp2
->pfs_group
!= 0 && pp1
->pfs_group
!= pp2
->pfs_group
) {
311 "pfs group mismatched: "
313 pp2
->pfs_group
, pp1
->pfs_group
);
316 newpp
->pfs_group
= pp1
->pfs_group
;
319 case PROP_CHECK_CLAIM
:
321 if (pp1
->lifetime
<= pp2
->lifetime
) {
322 newpp
->lifetime
= pp1
->lifetime
;
324 newpp
->lifetime
= pp2
->lifetime
;
325 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
326 plog(ASL_LEVEL_NOTICE
,
329 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
333 if (pp1
->lifebyte
> pp2
->lifebyte
) {
334 newpp
->lifebyte
= pp2
->lifebyte
;
335 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
336 plog(ASL_LEVEL_NOTICE
,
339 pp2
->lifebyte
, pp1
->lifebyte
);
341 newpp
->lifebyte
= pp1
->lifebyte
;
346 case PROP_CHECK_EXACT
:
347 if (pp1
->lifetime
!= pp2
->lifetime
) {
349 "lifetime mismatched: "
351 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
355 if (pp1
->lifebyte
!= pp2
->lifebyte
) {
357 "lifebyte mismatched: "
359 pp2
->lifebyte
, pp1
->lifebyte
);
362 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
364 "pfs group mismatched: "
366 pp2
->pfs_group
, pp1
->pfs_group
);
369 newpp
->lifetime
= pp1
->lifetime
;
370 newpp
->lifebyte
= pp1
->lifebyte
;
371 newpp
->pfs_group
= pp1
->pfs_group
;
376 "invalid pcheck_level why?.\n");
381 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
)
383 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
)
388 /* check protocol order */
395 * XXX does not work if we have multiple proposals
396 * with the same proto_id
402 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
) {
403 if (pr1
->proto_id
== pr2
->proto_id
)
410 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
) {
411 if (pr2
->proto_id
== pr1
->proto_id
)
420 if (pr1
->proto_id
!= pr2
->proto_id
) {
422 "proto_id mismatched: "
424 s_ipsecdoi_proto(pr2
->proto_id
),
425 s_ipsecdoi_proto(pr1
->proto_id
));
429 if (pr1
->spisize
== pr2
->spisize
)
431 else if (pr1
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
433 * draft-shacham-ippcp-rfc2393bis-05.txt:
434 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
436 if (pr1
->spisize
== sizeof(u_int16_t
) &&
437 pr2
->spisize
== sizeof(u_int32_t
)) {
439 } else if (pr2
->spisize
== sizeof(u_int16_t
) &&
440 pr1
->spisize
== sizeof(u_int32_t
)) {
445 "IPComp SPI size promoted "
446 "from 16bit to 32bit\n");
451 "spisize mismatched: "
453 (int)pr2
->spisize
, (int)pr1
->spisize
);
458 if (ph1
->natt_flags
& NAT_DETECTED
) {
459 saprop_adjust_encmode(pr2
, pr1
);
463 if (pr1
->encmode
!= pr2
->encmode
) {
465 "encmode mismatched: "
467 s_ipsecdoi_encmode(pr2
->encmode
),
468 s_ipsecdoi_encmode(pr1
->encmode
));
472 for (tr1
= pr1
->head
; tr1
; tr1
= tr1
->next
) {
473 for (tr2
= pr2
->head
; tr2
; tr2
= tr2
->next
) {
474 if (cmpsatrns(pr1
->proto_id
, tr1
, tr2
) == 0)
482 newpr
= newsaproto();
485 "failed to allocate saproto.\n");
488 newpr
->proto_id
= pr1
->proto_id
;
489 newpr
->spisize
= pr1
->spisize
;
490 newpr
->encmode
= pr1
->encmode
;
491 newpr
->spi
= pr2
->spi
; /* copy my SPI */
492 newpr
->spi_p
= pr1
->spi
; /* copy peer's SPI */
493 newpr
->reqid_in
= pr2
->reqid_in
;
494 newpr
->reqid_out
= pr2
->reqid_out
;
496 newpr
->udp_encap
= pr1
->udp_encap
| pr2
->udp_encap
;
502 "failed to allocate satrns.\n");
506 newtr
->trns_no
= tr1
->trns_no
;
507 newtr
->trns_id
= tr1
->trns_id
;
508 newtr
->encklen
= tr1
->encklen
;
509 newtr
->authtype
= tr1
->authtype
;
511 inssatrns(newpr
, newtr
);
512 inssaproto(newpp
, newpr
);
518 /* XXX should check if we have visited all items or not */
532 /* should be matched all protocols in a proposal */
533 if (pr1
!= NULL
|| pr2
!= NULL
)
543 /* take a single match between saprop. returns 0 if pp1 equals to pp2. */
546 const struct saprop
*pp1
, *pp2
;
548 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
549 plog(ASL_LEVEL_WARNING
,
550 "pfs_group mismatch. mine:%d peer:%d\n",
551 pp1
->pfs_group
, pp2
->pfs_group
);
555 if (pp1
->lifetime
> pp2
->lifetime
) {
556 plog(ASL_LEVEL_WARNING
,
557 "less lifetime proposed. mine:%d peer:%d\n",
558 (int)pp1
->lifetime
, (int)pp2
->lifetime
);
561 if (pp1
->lifebyte
> pp2
->lifebyte
) {
562 plog(ASL_LEVEL_WARNING
,
563 "less lifebyte proposed. mine:%d peer:%d\n",
564 pp1
->lifebyte
, pp2
->lifebyte
);
572 * take a single match between satrns. returns 0 if tr1 equals to tr2.
577 cmpsatrns(proto_id
, tr1
, tr2
)
579 const struct satrns
*tr1
, *tr2
;
581 if (tr1
->trns_id
!= tr2
->trns_id
) {
582 plog(ASL_LEVEL_DEBUG
,
583 "trns_id mismatched: "
585 s_ipsecdoi_trns(proto_id
, tr2
->trns_id
),
586 s_ipsecdoi_trns(proto_id
, tr1
->trns_id
));
590 if (tr1
->authtype
!= tr2
->authtype
) {
591 plog(ASL_LEVEL_DEBUG
,
592 "authtype mismatched: "
594 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr2
->authtype
),
595 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr1
->authtype
));
600 * At this moment for interoperability, the responder obey
601 * the initiator. It should be defined a notify message.
603 if (tr1
->encklen
> tr2
->encklen
) {
604 plog(ASL_LEVEL_WARNING
,
605 "less key length proposed, "
606 "mine:%d peer:%d. Use initiaotr's one.\n",
607 tr2
->encklen
, tr1
->encklen
);
615 set_satrnsbysainfo(struct saproto
*pr
, struct sainfo
*sainfo
, u_int8_t ike_version
, int pfs_group
)
617 struct sainfoalg
*a
, *b
;
618 struct satrns
*newtr
;
621 switch (pr
->proto_id
) {
622 case IPSECDOI_PROTO_IPSEC_AH
:
623 if (sainfo
->algs
[algclass_ipsec_auth
] == NULL
) {
625 "no auth algorithm found\n");
629 for (a
= sainfo
->algs
[algclass_ipsec_auth
]; a
; a
= a
->next
) {
631 if (a
->alg
== IPSECDOI_ATTR_AUTH_NONE
)
634 /* allocate satrns */
638 "failed to allocate satrns.\n");
642 newtr
->trns_no
= t
++;
643 newtr
->trns_id
= ipsecdoi_authalg2trnsid(a
->alg
); // IKEv1 only
644 newtr
->authtype
= a
->alg
;
646 inssatrns(pr
, newtr
);
649 case IPSECDOI_PROTO_IPSEC_ESP
:
650 if (sainfo
->algs
[algclass_ipsec_enc
] == NULL
) {
652 "no encryption algorithm found\n");
656 if (ike_version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
657 for (a
= sainfo
->algs
[algclass_ipsec_enc
]; a
; a
= a
->next
) {
658 for (b
= sainfo
->algs
[algclass_ipsec_auth
]; b
; b
= b
->next
) {
659 /* allocate satrns */
663 "failed to allocate satrns.\n");
667 newtr
->trns_no
= t
++;
668 newtr
->trns_id
= a
->alg
;
669 newtr
->encklen
= a
->encklen
;
670 newtr
->authtype
= b
->alg
;
672 inssatrns(pr
, newtr
);
677 case IPSECDOI_PROTO_IPCOMP
:
678 if (sainfo
->algs
[algclass_ipsec_comp
] == NULL
) {
680 "no ipcomp algorithm found\n");
684 for (a
= sainfo
->algs
[algclass_ipsec_comp
]; a
; a
= a
->next
) {
686 /* allocate satrns */
690 "failed to allocate satrns.\n");
694 newtr
->trns_no
= t
++;
695 newtr
->trns_id
= a
->alg
;
696 newtr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
; /*no auth*/
698 inssatrns(pr
, newtr
);
703 "unknown proto_id (%d).\n", pr
->proto_id
);
707 /* no proposal found */
708 if (pr
->head
== NULL
) {
709 plog(ASL_LEVEL_ERR
, "no algorithms found.\n");
716 flushsatrns(pr
->head
);
722 struct prop_pair
*p0
;
724 struct prop_pair
*p
, *t
;
725 struct saprop
*newpp
;
726 struct saproto
*newpr
;
727 struct satrns
*newtr
;
733 /* allocate ipsec a sa proposal */
737 "failed to allocate saprop.\n");
740 newpp
->prop_no
= p0
->prop
->p_no
;
741 /* lifetime & lifebyte must be updated later */
743 for (p
= p0
; p
; p
= p
->next
) {
745 /* allocate ipsec sa protocol */
746 newpr
= newsaproto();
749 "failed to allocate saproto.\n");
754 /* XXX should be handled isakmp cookie */
755 if (sizeof(newpr
->spi
) < p
->prop
->spi_size
) {
757 "invalid spi size %d.\n", p
->prop
->spi_size
);
763 * XXX SPI bits are left-filled, for use with IPComp.
764 * we should be switching to variable-length spi field...
766 newpr
->proto_id
= p
->prop
->proto_id
;
767 newpr
->spisize
= p
->prop
->spi_size
;
768 memset(&newpr
->spi
, 0, sizeof(newpr
->spi
));
769 spi
= (u_int8_t
*)&newpr
->spi
;
770 spi
+= sizeof(newpr
->spi
);
771 spi
-= p
->prop
->spi_size
;
772 memcpy(spi
, p
->prop
+ 1, p
->prop
->spi_size
);
774 newpr
->reqid_out
= 0;
776 for (t
= p
; t
; t
= t
->tnext
) {
778 plog(ASL_LEVEL_DEBUG
,
779 "prop#=%d prot-id=%s spi-size=%d "
780 "#trns=%d trns#=%d trns-id=%s\n",
782 s_ipsecdoi_proto(t
->prop
->proto_id
),
783 t
->prop
->spi_size
, t
->prop
->num_t
,
785 s_ipsecdoi_trns(t
->prop
->proto_id
,
788 /* allocate ipsec sa transform */
792 "failed to allocate satrns.\n");
797 if (ipsecdoi_t2satrns(t
->trns
,
798 newpp
, newpr
, newtr
) < 0) {
805 inssatrns(newpr
, newtr
);
809 * If the peer does not specify encryption mode, use
810 * transport mode by default. This is to conform to
811 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
812 * that unspecified == transport), as well as RFC2407
813 * (unspecified == implementation dependent default).
815 if (newpr
->encmode
== 0)
816 newpr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TRNS
;
818 inssaproto(newpp
, newpr
);
832 struct saprop
*p
, *save
;
834 for (p
= head
; p
!= NULL
; p
= save
) {
836 flushsaproto(p
->head
);
845 struct saproto
*head
;
847 struct saproto
*p
, *save
;
849 for (p
= head
; p
!= NULL
; p
= save
) {
851 flushsatrns(p
->head
);
864 struct satrns
*p
, *save
;
866 for (p
= head
; p
!= NULL
; p
= save
) {
875 * print multiple proposals
880 const struct saprop
*pp
;
882 const struct saprop
*p
;
889 for (p
= pp
; p
; p
= p
->next
) {
890 printsaprop0(pri
, p
);
897 * print one proposal.
900 printsaprop0(pri
, pp
)
902 const struct saprop
*pp
;
904 const struct saproto
*p
;
909 for (p
= pp
->head
; p
; p
= p
->next
) {
910 printsaproto(pri
, p
);
917 printsaproto(pri
, pr
)
919 const struct saproto
*pr
;
927 " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
928 "encmode=%s reqid=%d:%d)\n",
929 s_ipsecdoi_proto(pr
->proto_id
),
931 (unsigned long)ntohl(pr
->spi
),
932 (unsigned long)ntohl(pr
->spi_p
),
933 s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
),
934 (int)pr
->reqid_in
, (int)pr
->reqid_out
);
936 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
937 printsatrns(pri
, pr
->proto_id
, tr
);
944 printsatrns(pri
, proto_id
, tr
)
947 const struct satrns
*tr
;
953 case IPSECDOI_PROTO_IPSEC_AH
:
955 " (trns_id=%s authtype=%s)\n",
956 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
957 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
959 case IPSECDOI_PROTO_IPSEC_ESP
:
961 " (trns_id=%s encklen=%d authtype=%s)\n",
962 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
964 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
966 case IPSECDOI_PROTO_IPCOMP
:
969 s_ipsecdoi_trns(proto_id
, tr
->trns_id
));
973 "(unknown proto_id %d)\n", proto_id
);
980 print_proppair0(pri
, p
, level
)
987 memset(spc
, ' ', sizeof(spc
));
988 spc
[sizeof(spc
) - 1] = '\0';
994 "%s%p: next=%p tnext=%p\n", spc
, p
, p
->next
, p
->tnext
);
996 print_proppair0(pri
, p
->next
, level
+ 1);
998 print_proppair0(pri
, p
->tnext
, level
+ 1);
1002 print_proppair(pri
, p
)
1004 struct prop_pair
*p
;
1006 print_proppair0(pri
, p
, 1);
1010 set_proposal_from_policy(iph2
, sp_main
, sp_sub
)
1011 phase2_handle_t
*iph2
;
1012 struct secpolicy
*sp_main
, *sp_sub
;
1014 struct saprop
*newpp
;
1015 struct ipsecrequest
*req
;
1016 int encmodesv
= IPSEC_MODE_TRANSPORT
; /* use only when complex_bundle */
1018 newpp
= newsaprop();
1019 if (newpp
== NULL
) {
1021 "failed to allocate saprop.\n");
1025 newpp
->lifetime
= iph2
->sainfo
->lifetime
;
1026 newpp
->lifebyte
= iph2
->sainfo
->lifebyte
;
1027 newpp
->pfs_group
= iph2
->sainfo
->pfs_group
;
1029 //%%%% to do - verify DH group is OK - tried that here and iphone failed to connect
1031 if (lcconf
->complex_bundle
)
1035 * decide the encryption mode of this SA bundle.
1036 * the mode becomes tunnel mode when there is even one policy
1037 * of tunnel mode in the SPD. otherwise the mode becomes
1040 encmodesv
= IPSEC_MODE_TRANSPORT
;
1041 for (req
= sp_main
->req
; req
; req
= req
->next
) {
1042 if (req
->saidx
.mode
== IPSEC_MODE_TUNNEL
) {
1043 encmodesv
= pfkey2ipsecdoi_mode(req
->saidx
.mode
);
1045 if (iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED
))
1046 encmodesv
+= iph2
->ph1
->natt_options
->mode_udp_diff
;
1053 //%%%%%%s IKEv2 - no support for bundle - fix this - return error if bundle ???
1054 // %%%% need special handling for ipcomp
1055 for (req
= sp_main
->req
; req
; req
= req
->next
) {
1056 struct saproto
*newpr
;
1057 caddr_t paddr
= NULL
;
1060 * check if SA bundle ?
1061 * nested SAs negotiation is NOT supported.
1062 * me +--- SA1 ---+ peer1
1063 * me +--- SA2 --------------+ peer2
1065 if (req
->saidx
.src
.ss_len
&& req
->saidx
.dst
.ss_len
) {
1066 /* check the end of ip addresses of SA */
1067 if (iph2
->side
== INITIATOR
)
1068 paddr
= (caddr_t
)&req
->saidx
.dst
;
1070 paddr
= (caddr_t
)&req
->saidx
.src
;
1073 /* allocate ipsec sa protocol */
1074 newpr
= newsaproto();
1075 if (newpr
== NULL
) {
1077 "failed to allocate saproto.\n");
1081 newpr
->proto_id
= ipproto2doi(req
->saidx
.proto
);
1082 if (newpr
->proto_id
== IPSECDOI_PROTO_IPCOMP
)
1086 if (lcconf
->complex_bundle
) {
1087 encmodesv
= newpr
->encmode
= pfkey2ipsecdoi_mode(req
->saidx
.mode
);
1089 if (iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED
))
1090 newpr
->encmode
+= iph2
->ph1
->natt_options
->mode_udp_diff
;
1094 encmodesv
= newpr
->encmode
= encmodesv
;
1095 if (iph2
->side
== INITIATOR
)
1096 newpr
->reqid_out
= req
->saidx
.reqid
;
1098 newpr
->reqid_in
= req
->saidx
.reqid
;
1100 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
, iph2
->version
, newpp
->pfs_group
) < 0) {
1102 "failed to get algorithms.\n");
1107 /* set new saproto */
1108 inssaprotorev(newpp
, newpr
);
1111 /* get reqid_in from inbound policy */
1118 if (iph2
->side
== INITIATOR
)
1119 pr
->reqid_in
= req
->saidx
.reqid
;
1121 pr
->reqid_out
= req
->saidx
.reqid
;
1126 plog(ASL_LEVEL_NOTICE
,
1127 "There is a difference "
1128 "between the in/out bound policies in SPD.\n");
1132 iph2
->proposal
= newpp
;
1134 ike_session_update_mode(iph2
);
1136 printsaprop0(ASL_LEVEL_DEBUG
, newpp
);
1146 * generate a policy from peer's proposal.
1147 * this function unconditionally chooses the first proposal the in SA payload
1151 set_proposal_from_proposal(iph2
)
1152 phase2_handle_t
*iph2
;
1154 struct saprop
*newpp
= NULL
, *pp0
, *pp_peer
= NULL
;
1155 struct saproto
*newpr
= NULL
, *pr
;
1156 struct prop_pair
**pair
;
1160 /* get proposal pair */
1161 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
1162 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
1167 * make my proposal according as the client proposal.
1168 * XXX assumed there is only one proposal even if it's the SA bundle.
1170 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1171 if (pair
[i
] == NULL
)
1174 if (pp_peer
!= NULL
)
1175 flushsaprop(pp_peer
);
1177 pp_peer
= aproppair2saprop(pair
[i
]);
1178 if (pp_peer
== NULL
)
1184 "failed to allocate saprop.\n");
1188 pp0
->lifetime
= iph2
->sainfo
->lifetime
;
1189 pp0
->lifebyte
= iph2
->sainfo
->lifebyte
;
1190 pp0
->pfs_group
= iph2
->sainfo
->pfs_group
;
1192 if (pp_peer
->next
!= NULL
) {
1194 "pp_peer is inconsistency, ignore it.\n");
1198 for (pr
= pp_peer
->head
; pr
; pr
= pr
->next
) {
1200 newpr
= newsaproto();
1201 if (newpr
== NULL
) {
1203 "failed to allocate saproto.\n");
1207 newpr
->proto_id
= pr
->proto_id
;
1208 newpr
->spisize
= pr
->spisize
;
1209 newpr
->encmode
= pr
->encmode
;
1211 newpr
->spi_p
= pr
->spi
; /* copy peer's SPI */
1212 newpr
->reqid_in
= 0;
1213 newpr
->reqid_out
= 0;
1215 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
, iph2
->version
, 0) < 0) {
1217 "failed to get algorithms.\n");
1222 inssaproto(pp0
, newpr
);
1225 inssaprop(&newpp
, pp0
);
1228 plog(ASL_LEVEL_DEBUG
, "make a proposal from peer's:\n");
1229 printsaprop0(ASL_LEVEL_DEBUG
, newpp
);
1231 iph2
->proposal
= newpp
;
1233 ike_session_update_mode(iph2
);
1242 flushsaprop(pp_peer
);
1244 free_proppair(pair
);
1254 for (pr
= p
->head
; pr
; pr
= pr
->next
)
1255 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TUNNEL
)
1261 dupsatrns_1(struct satrns
*tr
)
1263 struct satrns
*newtr
;
1265 newtr
= racoon_calloc(1, sizeof(*newtr
));
1268 newtr
->trns_no
= tr
->trns_no
;
1269 newtr
->trns_type
= tr
->trns_type
;
1270 newtr
->trns_id
= tr
->trns_id
;
1271 newtr
->encklen
= tr
->encklen
;
1272 newtr
->authtype
= tr
->authtype
;
1278 dupsatrns(newpr
, head
)
1279 struct saproto
*newpr
;
1280 struct satrns
*head
;
1282 struct satrns
*p
, *newtr
;
1284 for (p
= head
; p
!= NULL
; p
= p
->next
) {
1285 newtr
= newsatrns();
1287 newtr
->trns_no
= p
->trns_no
;
1288 newtr
->trns_type
= p
->trns_type
;
1289 newtr
->trns_id
= p
->trns_id
;
1290 newtr
->encklen
= p
->encklen
;
1291 newtr
->authtype
= p
->authtype
;
1292 inssatrns(newpr
, newtr
);
1303 dupsaproto(newpp
, head
, ignore_spis
)
1304 struct saprop
*newpp
;
1305 struct saproto
*head
;
1308 struct saproto
*p
, *newpr
;
1310 for (p
= head
; p
!= NULL
; p
= p
->next
) {
1311 newpr
= newsaproto();
1313 newpr
->proto_id
= p
->proto_id
;
1314 newpr
->spisize
= p
->spisize
;
1315 newpr
->encmode
= p
->encmode
;
1316 newpr
->udp_encap
= p
->udp_encap
;
1318 newpr
->spi
= p
->spi
;
1319 newpr
->spi_p
= p
->spi_p
;
1320 newpr
->reqid_in
= p
->reqid_in
;
1321 newpr
->reqid_out
= p
->reqid_out
;
1323 dupsatrns(newpr
, p
->head
);
1324 inssaproto(newpp
, newpr
);
1335 dupsaprop(head
, ignore_spis
)
1336 struct saprop
*head
;
1339 struct saprop
*p
, *newpp
;
1341 for (p
= head
, newpp
= NULL
; p
!= NULL
; p
= p
->next
) {
1342 struct saprop
*tmp
= newsaprop();
1344 tmp
->prop_no
= p
->prop_no
;
1345 tmp
->lifetime
= p
->lifetime
;
1346 tmp
->lifebyte
= p
->lifebyte
;
1347 tmp
->pfs_group
= p
->pfs_group
;
1348 tmp
->claim
= p
->claim
;
1349 dupsaproto(tmp
, p
->head
, ignore_spis
);
1350 inssaprop(&newpp
, tmp
);