1 /* $KAME: proposal.c,v 1.48 2002/05/07 09:32:50 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/param.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/queue.h>
37 #include <netkey/key_var.h>
38 #include <netinet/in.h>
39 #include <netinet6/ipsec.h>
55 #include "isakmp_var.h"
57 #include "isakmp_natd.h"
58 #include "ipsec_doi.h"
59 #include "algorithm.h"
62 #include "localconf.h"
63 #include "remoteconf.h"
70 * modules for ipsec sa spec
77 new = racoon_calloc(1, sizeof(*new));
89 new = racoon_calloc(1, sizeof(*new));
96 /* set saprop to last part of the prop tree */
109 for (p
= *head
; p
->next
; p
= p
->next
)
116 /* set saproto to the end of the proto tree in saprop */
124 for (p
= pp
->head
; p
&& p
->next
; p
= p
->next
)
134 /* set saproto to the top of the proto tree in saprop */
136 inssaprotorev(pp
, new)
140 new->next
= pp
->head
;
151 new = racoon_calloc(1, sizeof(*new));
158 /* set saproto to last part of the proto tree in saprop */
166 for (tr
= pr
->head
; tr
&& tr
->next
; tr
= tr
->next
)
177 * take a single match between saprop. allocate a new proposal and return it
178 * for future use (like picking single proposal from a bundle).
179 * pp1: peer's proposal.
181 * NOTE: In the case of initiator, must be ensured that there is no
182 * modification of the proposal by calling cmp_aproppair_i() before
184 * XXX cannot understand the comment!
187 cmpsaprop_alloc(ph1
, pp1
, pp2
, side
)
188 struct ph1handle
*ph1
;
189 const struct saprop
*pp1
, *pp2
;
192 struct saprop
*newpp
= NULL
;
193 struct saproto
*pr1
, *pr2
, *newpr
= NULL
;
194 struct satrns
*tr1
, *tr2
, *newtr
;
195 const int ordermatters
= 0;
201 plog(LLV_ERROR
, LOCATION
, NULL
,
202 "failed to allocate saprop.\n");
205 newpp
->prop_no
= pp1
->prop_no
;
207 /* see proposal.h about lifetime/key length and PFS selection. */
209 /* check time/bytes lifetime and PFS */
210 switch (ph1
->rmconf
->pcheck_level
) {
211 case PROP_CHECK_OBEY
:
212 newpp
->lifetime
= pp1
->lifetime
;
213 newpp
->lifebyte
= pp1
->lifebyte
;
214 newpp
->pfs_group
= pp1
->pfs_group
;
216 case PROP_CHECK_STRICT
:
217 if (pp1
->lifetime
> pp2
->lifetime
) {
218 plog(LLV_ERROR
, LOCATION
, NULL
,
219 "long lifetime proposed: "
221 pp2
->lifetime
, pp1
->lifetime
);
224 if (pp1
->lifebyte
> pp2
->lifebyte
) {
225 plog(LLV_ERROR
, LOCATION
, NULL
,
226 "long lifebyte proposed: "
228 pp2
->lifebyte
, pp1
->lifebyte
);
231 newpp
->lifetime
= pp1
->lifetime
;
232 newpp
->lifebyte
= pp1
->lifebyte
;
235 if (pp2
->pfs_group
!= 0 && pp1
->pfs_group
!= pp2
->pfs_group
) {
236 plog(LLV_ERROR
, LOCATION
, NULL
,
237 "pfs group mismatched: "
239 pp2
->pfs_group
, pp1
->pfs_group
);
242 newpp
->pfs_group
= pp1
->pfs_group
;
244 case PROP_CHECK_CLAIM
:
246 if (pp1
->lifetime
<= pp2
->lifetime
) {
247 newpp
->lifetime
= pp1
->lifetime
;
249 newpp
->lifetime
= pp2
->lifetime
;
250 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
251 plog(LLV_NOTIFY
, LOCATION
, NULL
,
254 pp2
->lifetime
, pp1
->lifetime
);
258 if (pp1
->lifebyte
> pp2
->lifebyte
) {
259 newpp
->lifebyte
= pp2
->lifebyte
;
260 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
261 plog(LLV_NOTIFY
, LOCATION
, NULL
,
264 pp2
->lifebyte
, pp1
->lifebyte
);
266 newpp
->lifebyte
= pp1
->lifebyte
;
270 case PROP_CHECK_EXACT
:
271 if (pp1
->lifetime
!= pp2
->lifetime
) {
272 plog(LLV_ERROR
, LOCATION
, NULL
,
273 "lifetime mismatched: "
275 pp2
->lifetime
, pp1
->lifetime
);
278 if (pp1
->lifebyte
!= pp2
->lifebyte
) {
279 plog(LLV_ERROR
, LOCATION
, NULL
,
280 "lifebyte mismatched: "
282 pp2
->lifebyte
, pp1
->lifebyte
);
285 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
286 plog(LLV_ERROR
, LOCATION
, NULL
,
287 "pfs group mismatched: "
289 pp2
->pfs_group
, pp1
->pfs_group
);
292 newpp
->lifebyte
= pp1
->lifebyte
;
293 newpp
->lifebyte
= pp1
->lifebyte
;
294 newpp
->pfs_group
= pp1
->pfs_group
;
297 plog(LLV_ERROR
, LOCATION
, NULL
,
298 "invalid pcheck_level why?.\n");
303 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
)
305 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
)
310 /* check protocol order */
317 * XXX does not work if we have multiple proposals
318 * with the same proto_id
324 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
) {
325 if (pr1
->proto_id
== pr2
->proto_id
)
332 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
) {
333 if (pr2
->proto_id
== pr1
->proto_id
)
342 if (pr1
->proto_id
!= pr2
->proto_id
) {
343 plog(LLV_ERROR
, LOCATION
, NULL
,
344 "proto_id mismatched: "
346 pr2
->proto_id
, pr1
->proto_id
);
350 if (pr1
->spisize
== pr2
->spisize
)
352 else if (pr1
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
354 * draft-shacham-ippcp-rfc2393bis-05.txt:
355 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
357 if (pr1
->spisize
== sizeof(u_int16_t
) &&
358 pr2
->spisize
== sizeof(u_int32_t
)) {
360 } else if (pr1
->spisize
== sizeof(u_int16_t
) &&
361 pr2
->spisize
== sizeof(u_int32_t
)) {
365 plog(LLV_ERROR
, LOCATION
, NULL
,
366 "IPComp SPI size promoted "
367 "from 16bit to 32bit\n");
371 plog(LLV_ERROR
, LOCATION
, NULL
,
372 "spisize mismatched: "
374 pr2
->spisize
, pr1
->spisize
);
377 if (pr1
->encmode
!= pr2
->encmode
) {
378 plog(LLV_ERROR
, LOCATION
, NULL
,
379 "encmode mismatched: "
381 pr2
->encmode
, pr1
->encmode
);
385 for (tr1
= pr1
->head
; tr1
; tr1
= tr1
->next
) {
386 for (tr2
= pr2
->head
; tr2
; tr2
= tr2
->next
) {
387 if (cmpsatrns(tr1
, tr2
) == 0)
395 newpr
= newsaproto();
397 plog(LLV_ERROR
, LOCATION
, NULL
,
398 "failed to allocate saproto.\n");
401 newpr
->proto_id
= pr1
->proto_id
;
402 newpr
->spisize
= pr1
->spisize
;
403 newpr
->encmode
= pr1
->encmode
;
404 newpr
->spi
= pr2
->spi
; /* copy my SPI */
405 newpr
->spi_p
= pr1
->spi
; /* copy peer's SPI */
406 newpr
->reqid_in
= pr2
->reqid_in
;
407 newpr
->reqid_out
= pr2
->reqid_out
;
411 plog(LLV_ERROR
, LOCATION
, NULL
,
412 "failed to allocate satrns.\n");
415 newtr
->trns_no
= tr1
->trns_no
;
416 newtr
->trns_id
= tr1
->trns_id
;
417 newtr
->encklen
= tr1
->encklen
;
418 newtr
->authtype
= tr1
->authtype
;
420 inssatrns(newpr
, newtr
);
421 inssaproto(newpp
, newpr
);
427 /* XXX should check if we have visited all items or not */
441 /* should be matched all protocols in a proposal */
442 if (pr1
!= NULL
|| pr2
!= NULL
)
452 /* take a single match between saprop. returns 0 if pp1 equals to pp2. */
455 const struct saprop
*pp1
, *pp2
;
457 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
458 plog(LLV_WARNING
, LOCATION
, NULL
,
459 "pfs_group mismatch. mine:%d peer:%d\n",
460 pp1
->pfs_group
, pp2
->pfs_group
);
464 if (pp1
->lifetime
> pp2
->lifetime
) {
465 plog(LLV_WARNING
, LOCATION
, NULL
,
466 "less lifetime proposed. mine:%d peer:%d\n",
467 pp1
->lifetime
, pp2
->lifetime
);
470 if (pp1
->lifebyte
> pp2
->lifebyte
) {
471 plog(LLV_WARNING
, LOCATION
, NULL
,
472 "less lifebyte proposed. mine:%d peer:%d\n",
473 pp1
->lifebyte
, pp2
->lifebyte
);
481 * take a single match between satrns. returns 0 if tr1 equals to tr2.
487 const struct satrns
*tr1
, *tr2
;
489 if (tr1
->trns_id
!= tr2
->trns_id
) {
490 plog(LLV_ERROR
, LOCATION
, NULL
,
491 "trns_id mismatched: "
493 tr2
->trns_id
, tr1
->trns_id
);
496 if (tr1
->authtype
!= tr2
->authtype
) {
497 plog(LLV_ERROR
, LOCATION
, NULL
,
498 "authtype mismatched: "
500 tr2
->authtype
, tr1
->authtype
);
505 * At this moment for interoperability, the responder obey
506 * the initiator. It should be defined a notify message.
508 if (tr1
->encklen
> tr2
->encklen
) {
509 plog(LLV_WARNING
, LOCATION
, NULL
,
510 "less key length proposed, "
511 "mine:%d peer:%d. Use initiaotr's one.\n",
512 tr2
->encklen
, tr1
->encklen
);
520 set_satrnsbysainfo(pr
, sainfo
)
522 struct sainfo
*sainfo
;
524 struct sainfoalg
*a
, *b
;
525 struct satrns
*newtr
;
528 switch (pr
->proto_id
) {
529 case IPSECDOI_PROTO_IPSEC_AH
:
530 if (sainfo
->algs
[algclass_ipsec_auth
] == NULL
) {
531 plog(LLV_ERROR
, LOCATION
, NULL
,
532 "no auth algorithm found\n");
536 for (a
= sainfo
->algs
[algclass_ipsec_auth
]; a
; a
= a
->next
) {
538 if (a
->alg
== IPSECDOI_ATTR_AUTH_NONE
)
541 /* allocate satrns */
544 plog(LLV_ERROR
, LOCATION
, NULL
,
545 "failed to allocate satrns.\n");
549 newtr
->trns_no
= t
++;
550 newtr
->trns_id
= ipsecdoi_authalg2trnsid(a
->alg
);
551 newtr
->authtype
= a
->alg
;
553 inssatrns(pr
, newtr
);
556 case IPSECDOI_PROTO_IPSEC_ESP
:
557 if (sainfo
->algs
[algclass_ipsec_enc
] == NULL
) {
558 plog(LLV_ERROR
, LOCATION
, NULL
,
559 "no encryption algorithm found\n");
563 for (a
= sainfo
->algs
[algclass_ipsec_enc
]; a
; a
= a
->next
) {
564 for (b
= sainfo
->algs
[algclass_ipsec_auth
]; b
; b
= b
->next
) {
565 /* allocate satrns */
568 plog(LLV_ERROR
, LOCATION
, NULL
,
569 "failed to allocate satrns.\n");
573 newtr
->trns_no
= t
++;
574 newtr
->trns_id
= a
->alg
;
575 newtr
->encklen
= a
->encklen
;
576 newtr
->authtype
= b
->alg
;
578 inssatrns(pr
, newtr
);
582 case IPSECDOI_PROTO_IPCOMP
:
583 if (sainfo
->algs
[algclass_ipsec_comp
] == NULL
) {
584 plog(LLV_ERROR
, LOCATION
, NULL
,
585 "no ipcomp algorithm found\n");
589 for (a
= sainfo
->algs
[algclass_ipsec_comp
]; a
; a
= a
->next
) {
591 /* allocate satrns */
594 plog(LLV_ERROR
, LOCATION
, NULL
,
595 "failed to allocate satrns.\n");
599 newtr
->trns_no
= t
++;
600 newtr
->trns_id
= a
->alg
;
601 newtr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
; /*no auth*/
603 inssatrns(pr
, newtr
);
607 plog(LLV_ERROR
, LOCATION
, NULL
,
608 "unknown proto_id (%d).\n", pr
->proto_id
);
612 /* no proposal found */
613 if (pr
->head
== NULL
) {
614 plog(LLV_ERROR
, LOCATION
, NULL
, "no algorithms found.\n");
621 flushsatrns(pr
->head
);
627 struct prop_pair
*p0
;
629 struct prop_pair
*p
, *t
;
630 struct saprop
*newpp
;
631 struct saproto
*newpr
;
632 struct satrns
*newtr
;
638 /* allocate ipsec a sa proposal */
641 plog(LLV_ERROR
, LOCATION
, NULL
,
642 "failed to allocate saprop.\n");
645 newpp
->prop_no
= p0
->prop
->p_no
;
646 /* lifetime & lifebyte must be updated later */
648 for (p
= p0
; p
; p
= p
->next
) {
650 /* allocate ipsec sa protocol */
651 newpr
= newsaproto();
653 plog(LLV_ERROR
, LOCATION
, NULL
,
654 "failed to allocate saproto.\n");
659 /* XXX should be handled isakmp cookie */
660 if (sizeof(newpr
->spi
) < p
->prop
->spi_size
) {
661 plog(LLV_ERROR
, LOCATION
, NULL
,
662 "invalid spi size %d.\n", p
->prop
->spi_size
);
667 * XXX SPI bits are left-filled, for use with IPComp.
668 * we should be switching to variable-length spi field...
670 newpr
->proto_id
= p
->prop
->proto_id
;
671 newpr
->spisize
= p
->prop
->spi_size
;
672 memset(&newpr
->spi
, 0, sizeof(newpr
->spi
));
673 spi
= (u_int8_t
*)&newpr
->spi
;
674 spi
+= sizeof(newpr
->spi
);
675 spi
-= p
->prop
->spi_size
;
676 memcpy(spi
, p
->prop
+ 1, p
->prop
->spi_size
);
678 newpr
->reqid_out
= 0;
680 for (t
= p
; t
; t
= t
->tnext
) {
682 plog(LLV_DEBUG
, LOCATION
, NULL
,
683 "prop#=%d prot-id=%s spi-size=%d "
684 "#trns=%d trns#=%d trns-id=%s\n",
686 s_ipsecdoi_proto(t
->prop
->proto_id
),
687 t
->prop
->spi_size
, t
->prop
->num_t
,
689 s_ipsecdoi_trns(t
->prop
->proto_id
,
692 /* allocate ipsec sa transform */
695 plog(LLV_ERROR
, LOCATION
, NULL
,
696 "failed to allocate satrns.\n");
700 if (ipsecdoi_t2satrns(t
->trns
, newpp
, newpr
, newtr
) < 0) {
705 inssatrns(newpr
, newtr
);
709 * If the peer does not specify encryption mode, use
710 * transport mode by default. This is to conform to
711 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
712 * that unspecified == transport), as well as RFC2407
713 * (unspecified == implementation dependent default).
715 if (newpr
->encmode
== 0)
716 newpr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TRNS
;
718 inssaproto(newpp
, newpr
);
732 struct saprop
*p
, *save
;
734 for (p
= head
; p
!= NULL
; p
= save
) {
736 flushsaproto(p
->head
);
745 struct saproto
*head
;
747 struct saproto
*p
, *save
;
749 for (p
= head
; p
!= NULL
; p
= save
) {
751 flushsatrns(p
->head
);
764 struct satrns
*p
, *save
;
766 for (p
= head
; p
!= NULL
; p
= save
) {
775 * print multiple proposals
780 const struct saprop
*pp
;
782 const struct saprop
*p
;
785 plog(pri
, LOCATION
, NULL
, "(null)");
789 for (p
= pp
; p
; p
= p
->next
) {
790 printsaprop0(pri
, p
);
797 * print one proposal.
800 printsaprop0(pri
, pp
)
802 const struct saprop
*pp
;
804 const struct saproto
*p
;
809 for (p
= pp
->head
; p
; p
= p
->next
) {
810 printsaproto(pri
, p
);
817 printsaproto(pri
, pr
)
819 const struct saproto
*pr
;
826 plog(pri
, LOCATION
, NULL
,
827 " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
828 "encmode=%s reqid=%d:%d)\n",
829 s_ipsecdoi_proto(pr
->proto_id
),
831 (unsigned long)ntohl(pr
->spi
),
832 (unsigned long)ntohl(pr
->spi_p
),
833 s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
),
834 pr
->reqid_in
, pr
->reqid_out
);
836 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
837 printsatrns(pri
, pr
->proto_id
, tr
);
844 printsatrns(pri
, proto_id
, tr
)
847 const struct satrns
*tr
;
853 case IPSECDOI_PROTO_IPSEC_AH
:
854 plog(pri
, LOCATION
, NULL
,
855 " (trns_id=%s authtype=%s)\n",
856 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
857 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
859 case IPSECDOI_PROTO_IPSEC_ESP
:
860 plog(pri
, LOCATION
, NULL
,
861 " (trns_id=%s encklen=%d authtype=%s)\n",
862 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
864 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
866 case IPSECDOI_PROTO_IPCOMP
:
867 plog(pri
, LOCATION
, NULL
,
869 s_ipsecdoi_trns(proto_id
, tr
->trns_id
));
872 plog(pri
, LOCATION
, NULL
,
873 "(unknown proto_id %d)\n", proto_id
);
880 print_proppair0(pri
, p
, level
)
887 memset(spc
, ' ', sizeof(spc
));
888 spc
[sizeof(spc
) - 1] = '\0';
893 plog(pri
, LOCATION
, NULL
,
894 "%s%p: next=%p tnext=%p\n", spc
, p
, p
->next
, p
->tnext
);
896 print_proppair0(pri
, p
->next
, level
+ 1);
898 print_proppair0(pri
, p
->tnext
, level
+ 1);
902 print_proppair(pri
, p
)
906 print_proppair0(pri
, p
, 1);
910 set_proposal_from_policy(iph2
, sp_main
, sp_sub
)
911 struct ph2handle
*iph2
;
912 struct secpolicy
*sp_main
, *sp_sub
;
914 struct saprop
*newpp
;
915 struct ipsecrequest
*req
;
916 int encmodesv
= IPSEC_MODE_TRANSPORT
; /* use only when complex_bundle */
920 plog(LLV_ERROR
, LOCATION
, NULL
,
921 "failed to allocate saprop.\n");
925 newpp
->lifetime
= iph2
->sainfo
->lifetime
;
926 newpp
->lifebyte
= iph2
->sainfo
->lifebyte
;
927 newpp
->pfs_group
= iph2
->sainfo
->pfs_group
;
929 if (lcconf
->complex_bundle
)
933 * decide the encryption mode of this SA bundle.
934 * the mode becomes tunnel mode when there is even one policy
935 * of tunnel mode in the SPD. otherwise the mode becomes
938 encmodesv
= IPSEC_MODE_TRANSPORT
;
939 for (req
= sp_main
->req
; req
; req
= req
->next
) {
940 if (req
->saidx
.mode
== IPSEC_MODE_TUNNEL
) {
941 encmodesv
= pfkey2ipsecdoi_mode(req
->saidx
.mode
,
942 iph2
->ph1
? natd_hasnat(iph2
->ph1
) : 0);
948 for (req
= sp_main
->req
; req
; req
= req
->next
) {
949 struct saproto
*newpr
;
950 caddr_t paddr
= NULL
;
953 * check if SA bundle ?
954 * nested SAs negotiation is NOT supported.
955 * me +--- SA1 ---+ peer1
956 * me +--- SA2 --------------+ peer2
958 if (req
->saidx
.src
.ss_len
&& req
->saidx
.dst
.ss_len
) {
960 /* check the end of ip addresses of SA */
961 if (iph2
->side
== INITIATOR
)
962 paddr
= (caddr_t
)&req
->saidx
.dst
;
964 paddr
= (caddr_t
)&req
->saidx
.src
;
966 if (memcmp(iph2
->dst
, paddr
, iph2
->dst
->sa_len
)){
967 plog(LLV_ERROR
, LOCATION
, NULL
,
968 "not supported nested SA.");
973 /* allocate ipsec sa protocol */
974 newpr
= newsaproto();
976 plog(LLV_ERROR
, LOCATION
, NULL
,
977 "failed to allocate saproto.\n");
981 newpr
->proto_id
= ipproto2doi(req
->saidx
.proto
);
983 if (lcconf
->complex_bundle
)
984 newpr
->encmode
= pfkey2ipsecdoi_mode(req
->saidx
.mode
,
985 iph2
->ph1
? natd_hasnat(iph2
->ph1
) : 0);
987 newpr
->encmode
= encmodesv
;
989 if (iph2
->side
== INITIATOR
)
990 newpr
->reqid_out
= req
->saidx
.reqid
;
992 newpr
->reqid_in
= req
->saidx
.reqid
;
994 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
) < 0) {
995 plog(LLV_ERROR
, LOCATION
, NULL
,
996 "failed to get algorithms.\n");
1000 /* set new saproto */
1001 inssaprotorev(newpp
, newpr
);
1004 /* get reqid_in from inbound policy */
1011 if (iph2
->side
== INITIATOR
)
1012 pr
->reqid_in
= req
->saidx
.reqid
;
1014 pr
->reqid_out
= req
->saidx
.reqid
;
1019 plog(LLV_NOTIFY
, LOCATION
, NULL
,
1020 "There is a difference "
1021 "between the in/out bound policies in SPD.\n");
1025 iph2
->proposal
= newpp
;
1027 printsaprop0(LLV_DEBUG
, newpp
);
1035 * generate a policy from peer's proposal.
1036 * this function unconditionally choices first proposal in SA payload
1040 set_proposal_from_proposal(iph2
)
1041 struct ph2handle
*iph2
;
1043 struct saprop
*newpp
= NULL
, *pp0
, *pp_peer
= NULL
;
1044 struct saproto
*newpr
= NULL
, *pr
;
1045 struct prop_pair
**pair
;
1049 /* get proposal pair */
1050 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
1055 * make my proposal according as the client proposal.
1056 * XXX assumed there is only one proposal even if it's the SA bundle.
1058 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1059 if (pair
[i
] == NULL
)
1061 pp_peer
= aproppair2saprop(pair
[i
]);
1062 if (pp_peer
== NULL
)
1067 plog(LLV_ERROR
, LOCATION
, NULL
,
1068 "failed to allocate saprop.\n");
1072 pp0
->lifetime
= iph2
->sainfo
->lifetime
;
1073 pp0
->lifebyte
= iph2
->sainfo
->lifebyte
;
1074 pp0
->pfs_group
= iph2
->sainfo
->pfs_group
;
1076 if (pp_peer
->next
!= NULL
) {
1077 plog(LLV_ERROR
, LOCATION
, NULL
,
1078 "pp_peer is inconsistency, ignore it.\n");
1082 for (pr
= pp_peer
->head
; pr
; pr
= pr
->next
) {
1084 newpr
= newsaproto();
1085 if (newpr
== NULL
) {
1086 plog(LLV_ERROR
, LOCATION
, NULL
,
1087 "failed to allocate saproto.\n");
1090 newpr
->proto_id
= pr
->proto_id
;
1091 newpr
->spisize
= pr
->spisize
;
1092 newpr
->encmode
= pr
->encmode
;
1094 newpr
->spi_p
= pr
->spi
; /* copy peer's SPI */
1095 newpr
->reqid_in
= 0;
1096 newpr
->reqid_out
= 0;
1099 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
) < 0) {
1100 plog(LLV_ERROR
, LOCATION
, NULL
,
1101 "failed to get algorithms.\n");
1105 inssaproto(pp0
, newpr
);
1106 inssaprop(&newpp
, pp0
);
1109 plog(LLV_DEBUG
, LOCATION
, NULL
, "make a proposal from peer's:\n");
1110 printsaprop0(LLV_DEBUG
, newpp
);
1112 iph2
->proposal
= newpp
;
1121 flushsaprop(pp_peer
);
1122 free_proppair(pair
);