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"
77 * modules for ipsec sa spec
84 new = racoon_calloc(1, sizeof(*new));
96 new = racoon_calloc(1, sizeof(*new));
103 /* set saprop to last part of the prop tree */
106 struct saprop
**head
;
116 for (p
= *head
; p
->next
; p
= p
->next
)
123 /* set saproto to the end of the proto tree in saprop */
131 for (p
= pp
->head
; p
&& p
->next
; p
= p
->next
)
141 /* set saproto to the top of the proto tree in saprop */
143 inssaprotorev(pp
, new)
147 new->next
= pp
->head
;
158 new = racoon_calloc(1, sizeof(*new));
165 /* set saproto to last part of the proto tree in saprop */
173 for (tr
= pr
->head
; tr
&& tr
->next
; tr
= tr
->next
)
185 saprop_udp_encap (struct saproto
*pr
)
187 switch (pr
->encmode
) {
188 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
189 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
190 pr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TUNNEL
;
193 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
194 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
195 pr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TRNS
;
202 saprop_adjust_encmode (struct saproto
*pr2
, struct saproto
*pr1
)
206 if (natt_udp_encap(pr2
->encmode
)) {
208 saprop_udp_encap(pr2
);
209 plog(LLV_INFO
, LOCATION
, NULL
, "Adjusting my encmode %s(%d)->%s(%d)\n",
210 s_ipsecdoi_encmode(prev
),
212 s_ipsecdoi_encmode(pr2
->encmode
),
215 if (natt_udp_encap(pr1
->encmode
)) {
217 saprop_udp_encap(pr1
);
218 plog(LLV_INFO
, LOCATION
, NULL
, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
219 s_ipsecdoi_encmode(prev
),
221 s_ipsecdoi_encmode(pr1
->encmode
),
225 #endif // ENABLE_NATT
228 * take a single match between saprop. allocate a new proposal and return it
229 * for future use (like picking single proposal from a bundle).
230 * pp1: peer's proposal.
232 * NOTE: In the case of initiator, must be ensured that there is no
233 * modification of the proposal by calling cmp_aproppair_i() before
235 * XXX cannot understand the comment!
238 cmpsaprop_alloc(ph1
, pp1
, pp2
, side
)
239 struct ph1handle
*ph1
;
240 const struct saprop
*pp1
, *pp2
;
243 struct saprop
*newpp
= NULL
;
244 struct saproto
*pr1
, *pr2
, *newpr
= NULL
;
245 struct satrns
*tr1
, *tr2
, *newtr
;
246 const int ordermatters
= 0;
252 plog(LLV_ERROR
, LOCATION
, NULL
,
253 "failed to allocate saprop.\n");
256 newpp
->prop_no
= pp1
->prop_no
;
258 /* see proposal.h about lifetime/key length and PFS selection. */
260 /* check time/bytes lifetime and PFS */
261 switch (ph1
->rmconf
->pcheck_level
) {
262 case PROP_CHECK_OBEY
:
263 newpp
->lifetime
= pp1
->lifetime
;
264 newpp
->lifebyte
= pp1
->lifebyte
;
265 newpp
->pfs_group
= pp1
->pfs_group
;
268 case PROP_CHECK_STRICT
:
269 if (pp1
->lifetime
> pp2
->lifetime
) {
270 plog(LLV_ERROR
, LOCATION
, NULL
,
271 "long lifetime proposed: "
273 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
276 if (pp1
->lifebyte
> pp2
->lifebyte
) {
277 plog(LLV_ERROR
, LOCATION
, NULL
,
278 "long lifebyte proposed: "
280 pp2
->lifebyte
, pp1
->lifebyte
);
283 newpp
->lifetime
= pp1
->lifetime
;
284 newpp
->lifebyte
= pp1
->lifebyte
;
287 if (pp2
->pfs_group
!= 0 && pp1
->pfs_group
!= pp2
->pfs_group
) {
288 plog(LLV_ERROR
, LOCATION
, NULL
,
289 "pfs group mismatched: "
291 pp2
->pfs_group
, pp1
->pfs_group
);
294 newpp
->pfs_group
= pp1
->pfs_group
;
297 case PROP_CHECK_CLAIM
:
299 if (pp1
->lifetime
<= pp2
->lifetime
) {
300 newpp
->lifetime
= pp1
->lifetime
;
302 newpp
->lifetime
= pp2
->lifetime
;
303 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
304 plog(LLV_NOTIFY
, LOCATION
, NULL
,
307 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
311 if (pp1
->lifebyte
> pp2
->lifebyte
) {
312 newpp
->lifebyte
= pp2
->lifebyte
;
313 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
314 plog(LLV_NOTIFY
, LOCATION
, NULL
,
317 pp2
->lifebyte
, pp1
->lifebyte
);
319 newpp
->lifebyte
= pp1
->lifebyte
;
324 case PROP_CHECK_EXACT
:
325 if (pp1
->lifetime
!= pp2
->lifetime
) {
326 plog(LLV_ERROR
, LOCATION
, NULL
,
327 "lifetime mismatched: "
329 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
333 if (pp1
->lifebyte
!= pp2
->lifebyte
) {
334 plog(LLV_ERROR
, LOCATION
, NULL
,
335 "lifebyte mismatched: "
337 pp2
->lifebyte
, pp1
->lifebyte
);
340 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
341 plog(LLV_ERROR
, LOCATION
, NULL
,
342 "pfs group mismatched: "
344 pp2
->pfs_group
, pp1
->pfs_group
);
347 newpp
->lifetime
= pp1
->lifetime
;
348 newpp
->lifebyte
= pp1
->lifebyte
;
349 newpp
->pfs_group
= pp1
->pfs_group
;
353 plog(LLV_ERROR
, LOCATION
, NULL
,
354 "invalid pcheck_level why?.\n");
359 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
)
361 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
)
366 /* check protocol order */
373 * XXX does not work if we have multiple proposals
374 * with the same proto_id
380 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
) {
381 if (pr1
->proto_id
== pr2
->proto_id
)
388 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
) {
389 if (pr2
->proto_id
== pr1
->proto_id
)
398 if (pr1
->proto_id
!= pr2
->proto_id
) {
399 plog(LLV_ERROR
, LOCATION
, NULL
,
400 "proto_id mismatched: "
402 s_ipsecdoi_proto(pr2
->proto_id
),
403 s_ipsecdoi_proto(pr1
->proto_id
));
407 if (pr1
->spisize
== pr2
->spisize
)
409 else if (pr1
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
411 * draft-shacham-ippcp-rfc2393bis-05.txt:
412 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
414 if (pr1
->spisize
== sizeof(u_int16_t
) &&
415 pr2
->spisize
== sizeof(u_int32_t
)) {
417 } else if (pr2
->spisize
== sizeof(u_int16_t
) &&
418 pr1
->spisize
== sizeof(u_int32_t
)) {
422 plog(LLV_ERROR
, LOCATION
, NULL
,
423 "IPComp SPI size promoted "
424 "from 16bit to 32bit\n");
428 plog(LLV_ERROR
, LOCATION
, NULL
,
429 "spisize mismatched: "
431 (int)pr2
->spisize
, (int)pr1
->spisize
);
436 if (ph1
->natt_flags
& NAT_DETECTED
) {
437 saprop_adjust_encmode(pr2
, pr1
);
441 if (pr1
->encmode
!= pr2
->encmode
) {
442 plog(LLV_ERROR
, LOCATION
, NULL
,
443 "encmode mismatched: "
445 s_ipsecdoi_encmode(pr2
->encmode
),
446 s_ipsecdoi_encmode(pr1
->encmode
));
450 for (tr1
= pr1
->head
; tr1
; tr1
= tr1
->next
) {
451 for (tr2
= pr2
->head
; tr2
; tr2
= tr2
->next
) {
452 if (cmpsatrns(pr1
->proto_id
, tr1
, tr2
) == 0)
460 newpr
= newsaproto();
462 plog(LLV_ERROR
, LOCATION
, NULL
,
463 "failed to allocate saproto.\n");
466 newpr
->proto_id
= pr1
->proto_id
;
467 newpr
->spisize
= pr1
->spisize
;
468 newpr
->encmode
= pr1
->encmode
;
469 newpr
->spi
= pr2
->spi
; /* copy my SPI */
470 newpr
->spi_p
= pr1
->spi
; /* copy peer's SPI */
471 newpr
->reqid_in
= pr2
->reqid_in
;
472 newpr
->reqid_out
= pr2
->reqid_out
;
474 newpr
->udp_encap
= pr1
->udp_encap
| pr2
->udp_encap
;
479 plog(LLV_ERROR
, LOCATION
, NULL
,
480 "failed to allocate satrns.\n");
484 newtr
->trns_no
= tr1
->trns_no
;
485 newtr
->trns_id
= tr1
->trns_id
;
486 newtr
->encklen
= tr1
->encklen
;
487 newtr
->authtype
= tr1
->authtype
;
489 inssatrns(newpr
, newtr
);
490 inssaproto(newpp
, newpr
);
496 /* XXX should check if we have visited all items or not */
510 /* should be matched all protocols in a proposal */
511 if (pr1
!= NULL
|| pr2
!= NULL
)
521 /* take a single match between saprop. returns 0 if pp1 equals to pp2. */
524 const struct saprop
*pp1
, *pp2
;
526 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
527 plog(LLV_WARNING
, LOCATION
, NULL
,
528 "pfs_group mismatch. mine:%d peer:%d\n",
529 pp1
->pfs_group
, pp2
->pfs_group
);
533 if (pp1
->lifetime
> pp2
->lifetime
) {
534 plog(LLV_WARNING
, LOCATION
, NULL
,
535 "less lifetime proposed. mine:%d peer:%d\n",
536 (int)pp1
->lifetime
, (int)pp2
->lifetime
);
539 if (pp1
->lifebyte
> pp2
->lifebyte
) {
540 plog(LLV_WARNING
, LOCATION
, NULL
,
541 "less lifebyte proposed. mine:%d peer:%d\n",
542 pp1
->lifebyte
, pp2
->lifebyte
);
550 * take a single match between satrns. returns 0 if tr1 equals to tr2.
555 cmpsatrns(proto_id
, tr1
, tr2
)
557 const struct satrns
*tr1
, *tr2
;
559 if (tr1
->trns_id
!= tr2
->trns_id
) {
560 plog(LLV_WARNING
, LOCATION
, NULL
,
561 "trns_id mismatched: "
563 s_ipsecdoi_trns(proto_id
, tr2
->trns_id
),
564 s_ipsecdoi_trns(proto_id
, tr1
->trns_id
));
568 if (tr1
->authtype
!= tr2
->authtype
) {
569 plog(LLV_WARNING
, LOCATION
, NULL
,
570 "authtype mismatched: "
572 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr2
->authtype
),
573 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr1
->authtype
));
578 * At this moment for interoperability, the responder obey
579 * the initiator. It should be defined a notify message.
581 if (tr1
->encklen
> tr2
->encklen
) {
582 plog(LLV_WARNING
, LOCATION
, NULL
,
583 "less key length proposed, "
584 "mine:%d peer:%d. Use initiaotr's one.\n",
585 tr2
->encklen
, tr1
->encklen
);
593 set_satrnsbysainfo(pr
, sainfo
)
595 struct sainfo
*sainfo
;
597 struct sainfoalg
*a
, *b
;
598 struct satrns
*newtr
;
601 switch (pr
->proto_id
) {
602 case IPSECDOI_PROTO_IPSEC_AH
:
603 if (sainfo
->algs
[algclass_ipsec_auth
] == NULL
) {
604 plog(LLV_ERROR
, LOCATION
, NULL
,
605 "no auth algorithm found\n");
609 for (a
= sainfo
->algs
[algclass_ipsec_auth
]; a
; a
= a
->next
) {
611 if (a
->alg
== IPSECDOI_ATTR_AUTH_NONE
)
614 /* allocate satrns */
617 plog(LLV_ERROR
, LOCATION
, NULL
,
618 "failed to allocate satrns.\n");
622 newtr
->trns_no
= t
++;
623 newtr
->trns_id
= ipsecdoi_authalg2trnsid(a
->alg
);
624 newtr
->authtype
= a
->alg
;
626 inssatrns(pr
, newtr
);
629 case IPSECDOI_PROTO_IPSEC_ESP
:
630 if (sainfo
->algs
[algclass_ipsec_enc
] == NULL
) {
631 plog(LLV_ERROR
, LOCATION
, NULL
,
632 "no encryption algorithm found\n");
636 for (a
= sainfo
->algs
[algclass_ipsec_enc
]; a
; a
= a
->next
) {
637 for (b
= sainfo
->algs
[algclass_ipsec_auth
]; b
; b
= b
->next
) {
638 /* allocate satrns */
641 plog(LLV_ERROR
, LOCATION
, NULL
,
642 "failed to allocate satrns.\n");
646 newtr
->trns_no
= t
++;
647 newtr
->trns_id
= a
->alg
;
648 newtr
->encklen
= a
->encklen
;
649 newtr
->authtype
= b
->alg
;
651 inssatrns(pr
, newtr
);
655 case IPSECDOI_PROTO_IPCOMP
:
656 if (sainfo
->algs
[algclass_ipsec_comp
] == NULL
) {
657 plog(LLV_ERROR
, LOCATION
, NULL
,
658 "no ipcomp algorithm found\n");
662 for (a
= sainfo
->algs
[algclass_ipsec_comp
]; a
; a
= a
->next
) {
664 /* allocate satrns */
667 plog(LLV_ERROR
, LOCATION
, NULL
,
668 "failed to allocate satrns.\n");
672 newtr
->trns_no
= t
++;
673 newtr
->trns_id
= a
->alg
;
674 newtr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
; /*no auth*/
676 inssatrns(pr
, newtr
);
680 plog(LLV_ERROR
, LOCATION
, NULL
,
681 "unknown proto_id (%d).\n", pr
->proto_id
);
685 /* no proposal found */
686 if (pr
->head
== NULL
) {
687 plog(LLV_ERROR
, LOCATION
, NULL
, "no algorithms found.\n");
694 flushsatrns(pr
->head
);
700 struct prop_pair
*p0
;
702 struct prop_pair
*p
, *t
;
703 struct saprop
*newpp
;
704 struct saproto
*newpr
;
705 struct satrns
*newtr
;
711 /* allocate ipsec a sa proposal */
714 plog(LLV_ERROR
, LOCATION
, NULL
,
715 "failed to allocate saprop.\n");
718 newpp
->prop_no
= p0
->prop
->p_no
;
719 /* lifetime & lifebyte must be updated later */
721 for (p
= p0
; p
; p
= p
->next
) {
723 /* allocate ipsec sa protocol */
724 newpr
= newsaproto();
726 plog(LLV_ERROR
, LOCATION
, NULL
,
727 "failed to allocate saproto.\n");
732 /* XXX should be handled isakmp cookie */
733 if (sizeof(newpr
->spi
) < p
->prop
->spi_size
) {
734 plog(LLV_ERROR
, LOCATION
, NULL
,
735 "invalid spi size %d.\n", p
->prop
->spi_size
);
741 * XXX SPI bits are left-filled, for use with IPComp.
742 * we should be switching to variable-length spi field...
744 newpr
->proto_id
= p
->prop
->proto_id
;
745 newpr
->spisize
= p
->prop
->spi_size
;
746 memset(&newpr
->spi
, 0, sizeof(newpr
->spi
));
747 spi
= (u_int8_t
*)&newpr
->spi
;
748 spi
+= sizeof(newpr
->spi
);
749 spi
-= p
->prop
->spi_size
;
750 memcpy(spi
, p
->prop
+ 1, p
->prop
->spi_size
);
752 newpr
->reqid_out
= 0;
754 for (t
= p
; t
; t
= t
->tnext
) {
756 plog(LLV_DEBUG
, LOCATION
, NULL
,
757 "prop#=%d prot-id=%s spi-size=%d "
758 "#trns=%d trns#=%d trns-id=%s\n",
760 s_ipsecdoi_proto(t
->prop
->proto_id
),
761 t
->prop
->spi_size
, t
->prop
->num_t
,
763 s_ipsecdoi_trns(t
->prop
->proto_id
,
766 /* allocate ipsec sa transform */
769 plog(LLV_ERROR
, LOCATION
, NULL
,
770 "failed to allocate satrns.\n");
775 if (ipsecdoi_t2satrns(t
->trns
,
776 newpp
, newpr
, newtr
) < 0) {
783 inssatrns(newpr
, newtr
);
787 * If the peer does not specify encryption mode, use
788 * transport mode by default. This is to conform to
789 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
790 * that unspecified == transport), as well as RFC2407
791 * (unspecified == implementation dependent default).
793 if (newpr
->encmode
== 0)
794 newpr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TRNS
;
796 inssaproto(newpp
, newpr
);
810 struct saprop
*p
, *save
;
812 for (p
= head
; p
!= NULL
; p
= save
) {
814 flushsaproto(p
->head
);
823 struct saproto
*head
;
825 struct saproto
*p
, *save
;
827 for (p
= head
; p
!= NULL
; p
= save
) {
829 flushsatrns(p
->head
);
842 struct satrns
*p
, *save
;
844 for (p
= head
; p
!= NULL
; p
= save
) {
853 * print multiple proposals
858 const struct saprop
*pp
;
860 const struct saprop
*p
;
863 plog(pri
, LOCATION
, NULL
, "(null)");
867 for (p
= pp
; p
; p
= p
->next
) {
868 printsaprop0(pri
, p
);
875 * print one proposal.
878 printsaprop0(pri
, pp
)
880 const struct saprop
*pp
;
882 const struct saproto
*p
;
887 for (p
= pp
->head
; p
; p
= p
->next
) {
888 printsaproto(pri
, p
);
895 printsaproto(pri
, pr
)
897 const struct saproto
*pr
;
904 plog(pri
, LOCATION
, NULL
,
905 " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
906 "encmode=%s reqid=%d:%d)\n",
907 s_ipsecdoi_proto(pr
->proto_id
),
909 (unsigned long)ntohl(pr
->spi
),
910 (unsigned long)ntohl(pr
->spi_p
),
911 s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
),
912 (int)pr
->reqid_in
, (int)pr
->reqid_out
);
914 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
915 printsatrns(pri
, pr
->proto_id
, tr
);
922 printsatrns(pri
, proto_id
, tr
)
925 const struct satrns
*tr
;
931 case IPSECDOI_PROTO_IPSEC_AH
:
932 plog(pri
, LOCATION
, NULL
,
933 " (trns_id=%s authtype=%s)\n",
934 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
935 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
937 case IPSECDOI_PROTO_IPSEC_ESP
:
938 plog(pri
, LOCATION
, NULL
,
939 " (trns_id=%s encklen=%d authtype=%s)\n",
940 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
942 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
944 case IPSECDOI_PROTO_IPCOMP
:
945 plog(pri
, LOCATION
, NULL
,
947 s_ipsecdoi_trns(proto_id
, tr
->trns_id
));
950 plog(pri
, LOCATION
, NULL
,
951 "(unknown proto_id %d)\n", proto_id
);
958 print_proppair0(pri
, p
, level
)
965 memset(spc
, ' ', sizeof(spc
));
966 spc
[sizeof(spc
) - 1] = '\0';
971 plog(pri
, LOCATION
, NULL
,
972 "%s%p: next=%p tnext=%p\n", spc
, p
, p
->next
, p
->tnext
);
974 print_proppair0(pri
, p
->next
, level
+ 1);
976 print_proppair0(pri
, p
->tnext
, level
+ 1);
980 print_proppair(pri
, p
)
984 print_proppair0(pri
, p
, 1);
988 set_proposal_from_policy(iph2
, sp_main
, sp_sub
)
989 struct ph2handle
*iph2
;
990 struct secpolicy
*sp_main
, *sp_sub
;
992 struct saprop
*newpp
;
993 struct ipsecrequest
*req
;
994 int encmodesv
= IPSEC_MODE_TRANSPORT
; /* use only when complex_bundle */
998 plog(LLV_ERROR
, LOCATION
, NULL
,
999 "failed to allocate saprop.\n");
1003 newpp
->lifetime
= iph2
->sainfo
->lifetime
;
1004 newpp
->lifebyte
= iph2
->sainfo
->lifebyte
;
1005 newpp
->pfs_group
= iph2
->sainfo
->pfs_group
;
1007 if (lcconf
->complex_bundle
)
1011 * decide the encryption mode of this SA bundle.
1012 * the mode becomes tunnel mode when there is even one policy
1013 * of tunnel mode in the SPD. otherwise the mode becomes
1016 encmodesv
= IPSEC_MODE_TRANSPORT
;
1017 for (req
= sp_main
->req
; req
; req
= req
->next
) {
1018 if (req
->saidx
.mode
== IPSEC_MODE_TUNNEL
) {
1019 encmodesv
= pfkey2ipsecdoi_mode(req
->saidx
.mode
);
1021 if (iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED
))
1022 encmodesv
+= iph2
->ph1
->natt_options
->mode_udp_diff
;
1029 for (req
= sp_main
->req
; req
; req
= req
->next
) {
1030 struct saproto
*newpr
;
1031 caddr_t paddr
= NULL
;
1034 * check if SA bundle ?
1035 * nested SAs negotiation is NOT supported.
1036 * me +--- SA1 ---+ peer1
1037 * me +--- SA2 --------------+ peer2
1039 if (req
->saidx
.src
.ss_len
&& req
->saidx
.dst
.ss_len
) {
1040 /* check the end of ip addresses of SA */
1041 if (iph2
->side
== INITIATOR
)
1042 paddr
= (caddr_t
)&req
->saidx
.dst
;
1044 paddr
= (caddr_t
)&req
->saidx
.src
;
1047 /* allocate ipsec sa protocol */
1048 newpr
= newsaproto();
1049 if (newpr
== NULL
) {
1050 plog(LLV_ERROR
, LOCATION
, NULL
,
1051 "failed to allocate saproto.\n");
1055 newpr
->proto_id
= ipproto2doi(req
->saidx
.proto
);
1056 if (newpr
->proto_id
== IPSECDOI_PROTO_IPCOMP
)
1060 if (lcconf
->complex_bundle
) {
1061 newpr
->encmode
= pfkey2ipsecdoi_mode(req
->saidx
.mode
);
1063 if (iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED
))
1064 newpr
->encmode
+= iph2
->ph1
->natt_options
->mode_udp_diff
;
1068 newpr
->encmode
= encmodesv
;
1070 if (iph2
->side
== INITIATOR
)
1071 newpr
->reqid_out
= req
->saidx
.reqid
;
1073 newpr
->reqid_in
= req
->saidx
.reqid
;
1075 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
) < 0) {
1076 plog(LLV_ERROR
, LOCATION
, NULL
,
1077 "failed to get algorithms.\n");
1082 /* set new saproto */
1083 inssaprotorev(newpp
, newpr
);
1086 /* get reqid_in from inbound policy */
1093 if (iph2
->side
== INITIATOR
)
1094 pr
->reqid_in
= req
->saidx
.reqid
;
1096 pr
->reqid_out
= req
->saidx
.reqid
;
1101 plog(LLV_NOTIFY
, LOCATION
, NULL
,
1102 "There is a difference "
1103 "between the in/out bound policies in SPD.\n");
1107 iph2
->proposal
= newpp
;
1109 ike_session_update_mode(iph2
);
1111 printsaprop0(LLV_DEBUG
, newpp
);
1121 * generate a policy from peer's proposal.
1122 * this function unconditionally chooses the first proposal the in SA payload
1126 set_proposal_from_proposal(iph2
)
1127 struct ph2handle
*iph2
;
1129 struct saprop
*newpp
= NULL
, *pp0
, *pp_peer
= NULL
;
1130 struct saproto
*newpr
= NULL
, *pr
;
1131 struct prop_pair
**pair
;
1135 /* get proposal pair */
1136 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
1141 * make my proposal according as the client proposal.
1142 * XXX assumed there is only one proposal even if it's the SA bundle.
1144 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1145 if (pair
[i
] == NULL
)
1148 if (pp_peer
!= NULL
)
1149 flushsaprop(pp_peer
);
1151 pp_peer
= aproppair2saprop(pair
[i
]);
1152 if (pp_peer
== NULL
)
1157 plog(LLV_ERROR
, LOCATION
, NULL
,
1158 "failed to allocate saprop.\n");
1162 pp0
->lifetime
= iph2
->sainfo
->lifetime
;
1163 pp0
->lifebyte
= iph2
->sainfo
->lifebyte
;
1164 pp0
->pfs_group
= iph2
->sainfo
->pfs_group
;
1166 if (pp_peer
->next
!= NULL
) {
1167 plog(LLV_ERROR
, LOCATION
, NULL
,
1168 "pp_peer is inconsistency, ignore it.\n");
1172 for (pr
= pp_peer
->head
; pr
; pr
= pr
->next
) {
1174 newpr
= newsaproto();
1175 if (newpr
== NULL
) {
1176 plog(LLV_ERROR
, LOCATION
, NULL
,
1177 "failed to allocate saproto.\n");
1181 newpr
->proto_id
= pr
->proto_id
;
1182 newpr
->spisize
= pr
->spisize
;
1183 newpr
->encmode
= pr
->encmode
;
1185 newpr
->spi_p
= pr
->spi
; /* copy peer's SPI */
1186 newpr
->reqid_in
= 0;
1187 newpr
->reqid_out
= 0;
1189 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
) < 0) {
1190 plog(LLV_ERROR
, LOCATION
, NULL
,
1191 "failed to get algorithms.\n");
1196 inssaproto(pp0
, newpr
);
1199 inssaprop(&newpp
, pp0
);
1202 plog(LLV_DEBUG
, LOCATION
, NULL
, "make a proposal from peer's:\n");
1203 printsaprop0(LLV_DEBUG
, newpp
);
1205 iph2
->proposal
= newpp
;
1207 ike_session_update_mode(iph2
);
1216 flushsaprop(pp_peer
);
1218 free_proppair(pair
);
1228 for (pr
= p
->head
; pr
; pr
= pr
->next
)
1229 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TUNNEL
)
1235 dupsatrns(newpr
, head
)
1236 struct saproto
*newpr
;
1237 struct satrns
*head
;
1239 struct satrns
*p
, *newtr
;
1241 for (p
= head
; p
!= NULL
; p
= p
->next
) {
1242 newtr
= newsatrns();
1244 newtr
->trns_no
= p
->trns_no
;
1245 newtr
->trns_id
= p
->trns_id
;
1246 newtr
->encklen
= p
->encklen
;
1247 newtr
->authtype
= p
->authtype
;
1248 inssatrns(newpr
, newtr
);
1259 dupsaproto(newpp
, head
, ignore_spis
)
1260 struct saprop
*newpp
;
1261 struct saproto
*head
;
1264 struct saproto
*p
, *newpr
;
1266 for (p
= head
; p
!= NULL
; p
= p
->next
) {
1267 newpr
= newsaproto();
1269 newpr
->proto_id
= p
->proto_id
;
1270 newpr
->spisize
= p
->spisize
;
1271 newpr
->encmode
= p
->encmode
;
1272 newpr
->udp_encap
= p
->udp_encap
;
1274 newpr
->spi
= p
->spi
;
1275 newpr
->spi_p
= p
->spi_p
;
1276 newpr
->reqid_in
= p
->reqid_in
;
1277 newpr
->reqid_out
= p
->reqid_out
;
1279 dupsatrns(newpr
, p
->head
);
1280 inssaproto(newpp
, newpr
);
1291 dupsaprop(head
, ignore_spis
)
1292 struct saprop
*head
;
1295 struct saprop
*p
, *newpp
;
1297 for (p
= head
, newpp
= NULL
; p
!= NULL
; p
= p
->next
) {
1298 struct saprop
*tmp
= newsaprop();
1300 tmp
->prop_no
= p
->prop_no
;
1301 tmp
->lifetime
= p
->lifetime
;
1302 tmp
->lifebyte
= p
->lifebyte
;
1303 tmp
->pfs_group
= p
->pfs_group
;
1304 tmp
->claim
= p
->claim
;
1305 dupsaproto(tmp
, p
->head
, ignore_spis
);
1306 inssaprop(&newpp
, tmp
);