1 /* $NetBSD: proposal.c,v 1.16 2008/07/22 13:25:18 vanhu Exp $ */
3 /* $Id: proposal.c,v 1.17 2008/09/19 11:14:49 tteras Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/queue.h>
41 #include <netinet/in.h>
58 #include "isakmp_var.h"
60 #include "ipsec_doi.h"
61 #include "algorithm.h"
64 #include "localconf.h"
65 #include "remoteconf.h"
71 #include "nattraversal.h"
74 static uint g_nextreqid
= 1;
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
)
184 * take a single match between saprop. allocate a new proposal and return it
185 * for future use (like picking single proposal from a bundle).
186 * pp1: peer's proposal.
188 * NOTE: In the case of initiator, must be ensured that there is no
189 * modification of the proposal by calling cmp_aproppair_i() before
191 * XXX cannot understand the comment!
194 cmpsaprop_alloc(ph1
, pp1
, pp2
, side
)
195 struct ph1handle
*ph1
;
196 const struct saprop
*pp1
, *pp2
;
199 struct saprop
*newpp
= NULL
;
200 struct saproto
*pr1
, *pr2
, *newpr
= NULL
;
201 struct satrns
*tr1
, *tr2
, *newtr
;
202 const int ordermatters
= 0;
208 plog(LLV_ERROR
, LOCATION
, NULL
,
209 "failed to allocate saprop.\n");
212 newpp
->prop_no
= pp1
->prop_no
;
214 /* see proposal.h about lifetime/key length and PFS selection. */
216 /* check time/bytes lifetime and PFS */
217 switch (ph1
->rmconf
->pcheck_level
) {
218 case PROP_CHECK_OBEY
:
219 newpp
->lifetime
= pp1
->lifetime
;
220 newpp
->lifebyte
= pp1
->lifebyte
;
221 newpp
->pfs_group
= pp1
->pfs_group
;
224 case PROP_CHECK_STRICT
:
225 if (pp1
->lifetime
> pp2
->lifetime
) {
226 plog(LLV_ERROR
, LOCATION
, NULL
,
227 "long lifetime proposed: "
229 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
232 if (pp1
->lifebyte
> pp2
->lifebyte
) {
233 plog(LLV_ERROR
, LOCATION
, NULL
,
234 "long lifebyte proposed: "
236 pp2
->lifebyte
, pp1
->lifebyte
);
239 newpp
->lifetime
= pp1
->lifetime
;
240 newpp
->lifebyte
= pp1
->lifebyte
;
243 if (pp2
->pfs_group
!= 0 && pp1
->pfs_group
!= pp2
->pfs_group
) {
244 plog(LLV_ERROR
, LOCATION
, NULL
,
245 "pfs group mismatched: "
247 pp2
->pfs_group
, pp1
->pfs_group
);
250 newpp
->pfs_group
= pp1
->pfs_group
;
253 case PROP_CHECK_CLAIM
:
255 if (pp1
->lifetime
<= pp2
->lifetime
) {
256 newpp
->lifetime
= pp1
->lifetime
;
258 newpp
->lifetime
= pp2
->lifetime
;
259 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
260 plog(LLV_NOTIFY
, LOCATION
, NULL
,
263 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
267 if (pp1
->lifebyte
> pp2
->lifebyte
) {
268 newpp
->lifebyte
= pp2
->lifebyte
;
269 newpp
->claim
|= IPSECDOI_ATTR_SA_LD_TYPE_SEC
;
270 plog(LLV_NOTIFY
, LOCATION
, NULL
,
273 pp2
->lifebyte
, pp1
->lifebyte
);
275 newpp
->lifebyte
= pp1
->lifebyte
;
280 case PROP_CHECK_EXACT
:
281 if (pp1
->lifetime
!= pp2
->lifetime
) {
282 plog(LLV_ERROR
, LOCATION
, NULL
,
283 "lifetime mismatched: "
285 (int)pp2
->lifetime
, (int)pp1
->lifetime
);
289 if (pp1
->lifebyte
!= pp2
->lifebyte
) {
290 plog(LLV_ERROR
, LOCATION
, NULL
,
291 "lifebyte mismatched: "
293 pp2
->lifebyte
, pp1
->lifebyte
);
296 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
297 plog(LLV_ERROR
, LOCATION
, NULL
,
298 "pfs group mismatched: "
300 pp2
->pfs_group
, pp1
->pfs_group
);
303 newpp
->lifetime
= pp1
->lifetime
;
304 newpp
->lifebyte
= pp1
->lifebyte
;
305 newpp
->pfs_group
= pp1
->pfs_group
;
309 plog(LLV_ERROR
, LOCATION
, NULL
,
310 "invalid pcheck_level why?.\n");
315 /* check the security_context properties.
316 * It is possible for one side to have a security context
317 * and the other side doesn't. If so, this is an error.
320 if (*pp1
->sctx
.ctx_str
&& !(*pp2
->sctx
.ctx_str
)) {
321 plog(LLV_ERROR
, LOCATION
, NULL
,
322 "My proposal missing security context\n");
325 if (!(*pp1
->sctx
.ctx_str
) && *pp2
->sctx
.ctx_str
) {
326 plog(LLV_ERROR
, LOCATION
, NULL
,
327 "Peer is missing security context\n");
331 if (*pp1
->sctx
.ctx_str
&& *pp2
->sctx
.ctx_str
) {
332 if (pp1
->sctx
.ctx_doi
== pp2
->sctx
.ctx_doi
)
333 newpp
->sctx
.ctx_doi
= pp1
->sctx
.ctx_doi
;
335 plog(LLV_ERROR
, LOCATION
, NULL
,
336 "sec doi mismatched: my:%d peer:%d\n",
337 pp2
->sctx
.ctx_doi
, pp1
->sctx
.ctx_doi
);
341 if (pp1
->sctx
.ctx_alg
== pp2
->sctx
.ctx_alg
)
342 newpp
->sctx
.ctx_alg
= pp1
->sctx
.ctx_alg
;
344 plog(LLV_ERROR
, LOCATION
, NULL
,
345 "sec alg mismatched: my:%d peer:%d\n",
346 pp2
->sctx
.ctx_alg
, pp1
->sctx
.ctx_alg
);
350 if ((pp1
->sctx
.ctx_strlen
!= pp2
->sctx
.ctx_strlen
) ||
351 memcmp(pp1
->sctx
.ctx_str
, pp2
->sctx
.ctx_str
,
352 pp1
->sctx
.ctx_strlen
) != 0) {
353 plog(LLV_ERROR
, LOCATION
, NULL
,
354 "sec ctx string mismatched: my:%s peer:%s\n",
355 pp2
->sctx
.ctx_str
, pp1
->sctx
.ctx_str
);
358 newpp
->sctx
.ctx_strlen
= pp1
->sctx
.ctx_strlen
;
359 memcpy(newpp
->sctx
.ctx_str
, pp1
->sctx
.ctx_str
,
360 pp1
->sctx
.ctx_strlen
);
363 #endif /* HAVE_SECCTX */
366 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
)
368 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
)
373 /* check protocol order */
380 * XXX does not work if we have multiple proposals
381 * with the same proto_id
387 for (pr1
= pp1
->head
; pr1
; pr1
= pr1
->next
) {
388 if (pr1
->proto_id
== pr2
->proto_id
)
395 for (pr2
= pp2
->head
; pr2
; pr2
= pr2
->next
) {
396 if (pr2
->proto_id
== pr1
->proto_id
)
405 if (pr1
->proto_id
!= pr2
->proto_id
) {
406 plog(LLV_ERROR
, LOCATION
, NULL
,
407 "proto_id mismatched: "
409 s_ipsecdoi_proto(pr2
->proto_id
),
410 s_ipsecdoi_proto(pr1
->proto_id
));
414 if (pr1
->spisize
== pr2
->spisize
)
416 else if (pr1
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
418 * draft-shacham-ippcp-rfc2393bis-05.txt:
419 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
421 if (pr1
->spisize
== sizeof(u_int16_t
) &&
422 pr2
->spisize
== sizeof(u_int32_t
)) {
424 } else if (pr2
->spisize
== sizeof(u_int16_t
) &&
425 pr1
->spisize
== sizeof(u_int32_t
)) {
429 plog(LLV_ERROR
, LOCATION
, NULL
,
430 "IPComp SPI size promoted "
431 "from 16bit to 32bit\n");
435 plog(LLV_ERROR
, LOCATION
, NULL
,
436 "spisize mismatched: "
438 (int)pr2
->spisize
, (int)pr1
->spisize
);
443 if ((ph1
->natt_flags
& NAT_DETECTED
) &&
444 natt_udp_encap (pr2
->encmode
))
446 plog(LLV_INFO
, LOCATION
, NULL
, "Adjusting my encmode %s->%s\n",
447 s_ipsecdoi_encmode(pr2
->encmode
),
448 s_ipsecdoi_encmode(pr2
->encmode
- ph1
->natt_options
->mode_udp_diff
));
449 pr2
->encmode
-= ph1
->natt_options
->mode_udp_diff
;
453 if ((ph1
->natt_flags
& NAT_DETECTED
) &&
454 natt_udp_encap (pr1
->encmode
))
456 plog(LLV_INFO
, LOCATION
, NULL
, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
457 s_ipsecdoi_encmode(pr1
->encmode
),
459 s_ipsecdoi_encmode(pr1
->encmode
- ph1
->natt_options
->mode_udp_diff
),
460 pr1
->encmode
- ph1
->natt_options
->mode_udp_diff
);
461 pr1
->encmode
-= ph1
->natt_options
->mode_udp_diff
;
466 if (pr1
->encmode
!= pr2
->encmode
) {
467 plog(LLV_ERROR
, LOCATION
, NULL
,
468 "encmode mismatched: "
470 s_ipsecdoi_encmode(pr2
->encmode
),
471 s_ipsecdoi_encmode(pr1
->encmode
));
475 for (tr1
= pr1
->head
; tr1
; tr1
= tr1
->next
) {
476 for (tr2
= pr2
->head
; tr2
; tr2
= tr2
->next
) {
477 if (cmpsatrns(pr1
->proto_id
, tr1
, tr2
, ph1
->rmconf
->pcheck_level
) == 0)
485 newpr
= newsaproto();
487 plog(LLV_ERROR
, LOCATION
, NULL
,
488 "failed to allocate saproto.\n");
491 newpr
->proto_id
= pr1
->proto_id
;
492 newpr
->spisize
= pr1
->spisize
;
493 newpr
->encmode
= pr1
->encmode
;
494 newpr
->spi
= pr2
->spi
; /* copy my SPI */
495 newpr
->spi_p
= pr1
->spi
; /* copy peer's SPI */
496 newpr
->reqid_in
= pr2
->reqid_in
;
497 newpr
->reqid_out
= pr2
->reqid_out
;
499 newpr
->udp_encap
= pr1
->udp_encap
| pr2
->udp_encap
;
504 plog(LLV_ERROR
, LOCATION
, NULL
,
505 "failed to allocate satrns.\n");
509 newtr
->trns_no
= tr1
->trns_no
;
510 newtr
->trns_id
= tr1
->trns_id
;
511 newtr
->encklen
= tr1
->encklen
;
512 newtr
->authtype
= tr1
->authtype
;
514 inssatrns(newpr
, newtr
);
515 inssaproto(newpp
, newpr
);
521 /* XXX should check if we have visited all items or not */
535 /* should be matched all protocols in a proposal */
536 if (pr1
!= NULL
|| pr2
!= NULL
)
546 /* take a single match between saprop. returns 0 if pp1 equals to pp2. */
549 const struct saprop
*pp1
, *pp2
;
551 if (pp1
->pfs_group
!= pp2
->pfs_group
) {
552 plog(LLV_WARNING
, LOCATION
, NULL
,
553 "pfs_group mismatch. mine:%d peer:%d\n",
554 pp1
->pfs_group
, pp2
->pfs_group
);
558 if (pp1
->lifetime
> pp2
->lifetime
) {
559 plog(LLV_WARNING
, LOCATION
, NULL
,
560 "less lifetime proposed. mine:%d peer:%d\n",
561 (int)pp1
->lifetime
, (int)pp2
->lifetime
);
564 if (pp1
->lifebyte
> pp2
->lifebyte
) {
565 plog(LLV_WARNING
, LOCATION
, NULL
,
566 "less lifebyte proposed. mine:%d peer:%d\n",
567 pp1
->lifebyte
, pp2
->lifebyte
);
575 * take a single match between satrns. returns 0 if tr1 equals to tr2.
580 cmpsatrns(proto_id
, tr1
, tr2
, check_level
)
582 const struct satrns
*tr1
, *tr2
;
585 if (tr1
->trns_id
!= tr2
->trns_id
) {
586 plog(LLV_WARNING
, LOCATION
, NULL
,
587 "trns_id mismatched: "
589 s_ipsecdoi_trns(proto_id
, tr2
->trns_id
),
590 s_ipsecdoi_trns(proto_id
, tr1
->trns_id
));
594 if (tr1
->authtype
!= tr2
->authtype
) {
595 plog(LLV_WARNING
, LOCATION
, NULL
,
596 "authtype mismatched: "
598 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr2
->authtype
),
599 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr1
->authtype
));
603 /* Check key length regarding checkmode
604 * XXX Shall we send some kind of notify message when key length rejected ?
607 case PROP_CHECK_OBEY
:
611 case PROP_CHECK_STRICT
:
613 case PROP_CHECK_CLAIM
:
614 if (tr1
->encklen
< tr2
->encklen
) {
615 plog(LLV_WARNING
, LOCATION
, NULL
,
616 "low key length proposed, "
617 "mine:%d peer:%d.\n",
618 tr2
->encklen
, tr1
->encklen
);
622 case PROP_CHECK_EXACT
:
623 if (tr1
->encklen
!= tr2
->encklen
) {
624 plog(LLV_WARNING
, LOCATION
, NULL
,
625 "key length mismatched, "
626 "mine:%d peer:%d.\n",
627 tr2
->encklen
, tr1
->encklen
);
637 set_satrnsbysainfo(pr
, sainfo
)
639 struct sainfo
*sainfo
;
641 struct sainfoalg
*a
, *b
;
642 struct satrns
*newtr
;
645 switch (pr
->proto_id
) {
646 case IPSECDOI_PROTO_IPSEC_AH
:
647 if (sainfo
->algs
[algclass_ipsec_auth
] == NULL
) {
648 plog(LLV_ERROR
, LOCATION
, NULL
,
649 "no auth algorithm found\n");
653 for (a
= sainfo
->algs
[algclass_ipsec_auth
]; a
; a
= a
->next
) {
655 if (a
->alg
== IPSECDOI_ATTR_AUTH_NONE
)
658 /* allocate satrns */
661 plog(LLV_ERROR
, LOCATION
, NULL
,
662 "failed to allocate satrns.\n");
666 newtr
->trns_no
= t
++;
667 newtr
->trns_id
= ipsecdoi_authalg2trnsid(a
->alg
);
668 newtr
->authtype
= a
->alg
;
670 inssatrns(pr
, newtr
);
673 case IPSECDOI_PROTO_IPSEC_ESP
:
674 if (sainfo
->algs
[algclass_ipsec_enc
] == NULL
) {
675 plog(LLV_ERROR
, LOCATION
, NULL
,
676 "no encryption algorithm found\n");
680 for (a
= sainfo
->algs
[algclass_ipsec_enc
]; a
; a
= a
->next
) {
681 for (b
= sainfo
->algs
[algclass_ipsec_auth
]; b
; b
= b
->next
) {
682 /* allocate satrns */
685 plog(LLV_ERROR
, LOCATION
, NULL
,
686 "failed to allocate satrns.\n");
690 newtr
->trns_no
= t
++;
691 newtr
->trns_id
= a
->alg
;
692 newtr
->encklen
= a
->encklen
;
693 newtr
->authtype
= b
->alg
;
695 inssatrns(pr
, newtr
);
699 case IPSECDOI_PROTO_IPCOMP
:
700 if (sainfo
->algs
[algclass_ipsec_comp
] == NULL
) {
701 plog(LLV_ERROR
, LOCATION
, NULL
,
702 "no ipcomp algorithm found\n");
706 for (a
= sainfo
->algs
[algclass_ipsec_comp
]; a
; a
= a
->next
) {
708 /* allocate satrns */
711 plog(LLV_ERROR
, LOCATION
, NULL
,
712 "failed to allocate satrns.\n");
716 newtr
->trns_no
= t
++;
717 newtr
->trns_id
= a
->alg
;
718 newtr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
; /*no auth*/
720 inssatrns(pr
, newtr
);
724 plog(LLV_ERROR
, LOCATION
, NULL
,
725 "unknown proto_id (%d).\n", pr
->proto_id
);
729 /* no proposal found */
730 if (pr
->head
== NULL
) {
731 plog(LLV_ERROR
, LOCATION
, NULL
, "no algorithms found.\n");
738 flushsatrns(pr
->head
);
744 struct prop_pair
*p0
;
746 struct prop_pair
*p
, *t
;
747 struct saprop
*newpp
;
748 struct saproto
*newpr
;
749 struct satrns
*newtr
;
755 /* allocate ipsec a sa proposal */
758 plog(LLV_ERROR
, LOCATION
, NULL
,
759 "failed to allocate saprop.\n");
762 newpp
->prop_no
= p0
->prop
->p_no
;
763 /* lifetime & lifebyte must be updated later */
765 for (p
= p0
; p
; p
= p
->next
) {
767 /* allocate ipsec sa protocol */
768 newpr
= newsaproto();
770 plog(LLV_ERROR
, LOCATION
, NULL
,
771 "failed to allocate saproto.\n");
776 /* XXX should be handled isakmp cookie */
777 if (sizeof(newpr
->spi
) < p
->prop
->spi_size
) {
778 plog(LLV_ERROR
, LOCATION
, NULL
,
779 "invalid spi size %d.\n", p
->prop
->spi_size
);
785 * XXX SPI bits are left-filled, for use with IPComp.
786 * we should be switching to variable-length spi field...
788 newpr
->proto_id
= p
->prop
->proto_id
;
789 newpr
->spisize
= p
->prop
->spi_size
;
790 memset(&newpr
->spi
, 0, sizeof(newpr
->spi
));
791 spi
= (u_int8_t
*)&newpr
->spi
;
792 spi
+= sizeof(newpr
->spi
);
793 spi
-= p
->prop
->spi_size
;
794 memcpy(spi
, p
->prop
+ 1, p
->prop
->spi_size
);
796 newpr
->reqid_out
= 0;
798 for (t
= p
; t
; t
= t
->tnext
) {
800 plog(LLV_DEBUG
, LOCATION
, NULL
,
801 "prop#=%d prot-id=%s spi-size=%d "
802 "#trns=%d trns#=%d trns-id=%s\n",
804 s_ipsecdoi_proto(t
->prop
->proto_id
),
805 t
->prop
->spi_size
, t
->prop
->num_t
,
807 s_ipsecdoi_trns(t
->prop
->proto_id
,
810 /* allocate ipsec sa transform */
813 plog(LLV_ERROR
, LOCATION
, NULL
,
814 "failed to allocate satrns.\n");
819 if (ipsecdoi_t2satrns(t
->trns
,
820 newpp
, newpr
, newtr
) < 0) {
827 inssatrns(newpr
, newtr
);
831 * If the peer does not specify encryption mode, use
832 * transport mode by default. This is to conform to
833 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
834 * that unspecified == transport), as well as RFC2407
835 * (unspecified == implementation dependent default).
837 if (newpr
->encmode
== 0)
838 newpr
->encmode
= IPSECDOI_ATTR_ENC_MODE_TRNS
;
840 inssaproto(newpp
, newpr
);
854 struct saprop
*p
, *save
;
856 for (p
= head
; p
!= NULL
; p
= save
) {
858 flushsaproto(p
->head
);
867 struct saproto
*head
;
869 struct saproto
*p
, *save
;
871 for (p
= head
; p
!= NULL
; p
= save
) {
873 flushsatrns(p
->head
);
886 struct satrns
*p
, *save
;
888 for (p
= head
; p
!= NULL
; p
= save
) {
897 * print multiple proposals
902 const struct saprop
*pp
;
904 const struct saprop
*p
;
907 plog(pri
, LOCATION
, NULL
, "(null)");
911 for (p
= pp
; p
; p
= p
->next
) {
912 printsaprop0(pri
, p
);
919 * print one proposal.
922 printsaprop0(pri
, pp
)
924 const struct saprop
*pp
;
926 const struct saproto
*p
;
931 for (p
= pp
->head
; p
; p
= p
->next
) {
932 printsaproto(pri
, p
);
939 printsaproto(pri
, pr
)
941 const struct saproto
*pr
;
948 plog(pri
, LOCATION
, NULL
,
949 " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
950 "encmode=%s reqid=%d:%d)\n",
951 s_ipsecdoi_proto(pr
->proto_id
),
953 (unsigned long)ntohl(pr
->spi
),
954 (unsigned long)ntohl(pr
->spi_p
),
955 s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
),
956 (int)pr
->reqid_in
, (int)pr
->reqid_out
);
958 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
959 printsatrns(pri
, pr
->proto_id
, tr
);
966 printsatrns(pri
, proto_id
, tr
)
969 const struct satrns
*tr
;
975 case IPSECDOI_PROTO_IPSEC_AH
:
976 plog(pri
, LOCATION
, NULL
,
977 " (trns_id=%s authtype=%s)\n",
978 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
979 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
981 case IPSECDOI_PROTO_IPSEC_ESP
:
982 plog(pri
, LOCATION
, NULL
,
983 " (trns_id=%s encklen=%d authtype=%s)\n",
984 s_ipsecdoi_trns(proto_id
, tr
->trns_id
),
986 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH
, tr
->authtype
));
988 case IPSECDOI_PROTO_IPCOMP
:
989 plog(pri
, LOCATION
, NULL
,
991 s_ipsecdoi_trns(proto_id
, tr
->trns_id
));
994 plog(pri
, LOCATION
, NULL
,
995 "(unknown proto_id %d)\n", proto_id
);
1002 print_proppair0(pri
, p
, level
)
1004 struct prop_pair
*p
;
1009 memset(spc
, ' ', sizeof(spc
));
1010 spc
[sizeof(spc
) - 1] = '\0';
1015 plog(pri
, LOCATION
, NULL
,
1016 "%s%p: next=%p tnext=%p\n", spc
, p
, p
->next
, p
->tnext
);
1018 print_proppair0(pri
, p
->next
, level
+ 1);
1020 print_proppair0(pri
, p
->tnext
, level
+ 1);
1024 print_proppair(pri
, p
)
1026 struct prop_pair
*p
;
1028 print_proppair0(pri
, p
, 1);
1032 set_proposal_from_policy(iph2
, sp_main
, sp_sub
)
1033 struct ph2handle
*iph2
;
1034 struct secpolicy
*sp_main
, *sp_sub
;
1036 struct saprop
*newpp
;
1037 struct ipsecrequest
*req
;
1038 int encmodesv
= IPSECDOI_ATTR_ENC_MODE_TRNS
; /* use only when complex_bundle */
1040 newpp
= newsaprop();
1041 if (newpp
== NULL
) {
1042 plog(LLV_ERROR
, LOCATION
, NULL
,
1043 "failed to allocate saprop.\n");
1047 newpp
->lifetime
= iph2
->sainfo
->lifetime
;
1048 newpp
->lifebyte
= iph2
->sainfo
->lifebyte
;
1049 newpp
->pfs_group
= iph2
->sainfo
->pfs_group
;
1051 if (lcconf
->complex_bundle
)
1055 * decide the encryption mode of this SA bundle.
1056 * the mode becomes tunnel mode when there is even one policy
1057 * of tunnel mode in the SPD. otherwise the mode becomes
1060 for (req
= sp_main
->req
; req
; req
= req
->next
) {
1061 if (req
->saidx
.mode
== IPSEC_MODE_TUNNEL
) {
1062 encmodesv
= pfkey2ipsecdoi_mode(req
->saidx
.mode
);
1064 if (iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED
))
1065 encmodesv
+= iph2
->ph1
->natt_options
->mode_udp_diff
;
1072 for (req
= sp_main
->req
; req
; req
= req
->next
) {
1073 struct saproto
*newpr
;
1074 caddr_t paddr
= NULL
;
1077 * check if SA bundle ?
1078 * nested SAs negotiation is NOT supported.
1079 * me +--- SA1 ---+ peer1
1080 * me +--- SA2 --------------+ peer2
1083 if (req
->saidx
.src
.ss_family
&& req
->saidx
.dst
.ss_family
) {
1085 if (req
->saidx
.src
.ss_len
&& req
->saidx
.dst
.ss_len
) {
1087 /* check the end of ip addresses of SA */
1088 if (iph2
->side
== INITIATOR
)
1089 paddr
= (caddr_t
)&req
->saidx
.dst
;
1091 paddr
= (caddr_t
)&req
->saidx
.src
;
1094 /* allocate ipsec sa protocol */
1095 newpr
= newsaproto();
1096 if (newpr
== NULL
) {
1097 plog(LLV_ERROR
, LOCATION
, NULL
,
1098 "failed to allocate saproto.\n");
1102 newpr
->proto_id
= ipproto2doi(req
->saidx
.proto
);
1103 if (newpr
->proto_id
== IPSECDOI_PROTO_IPCOMP
)
1107 if (lcconf
->complex_bundle
) {
1108 newpr
->encmode
= pfkey2ipsecdoi_mode(req
->saidx
.mode
);
1110 if (iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED
))
1112 iph2
->ph1
->natt_options
->mode_udp_diff
;
1116 newpr
->encmode
= encmodesv
;
1118 if (iph2
->side
== INITIATOR
)
1119 newpr
->reqid_out
= req
->saidx
.reqid
;
1121 newpr
->reqid_in
= req
->saidx
.reqid
;
1123 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
) < 0) {
1124 plog(LLV_ERROR
, LOCATION
, NULL
,
1125 "failed to get algorithms.\n");
1130 /* set new saproto */
1131 inssaprotorev(newpp
, newpr
);
1134 /* get reqid_in from inbound policy */
1141 if (iph2
->side
== INITIATOR
)
1142 pr
->reqid_in
= req
->saidx
.reqid
;
1144 pr
->reqid_out
= req
->saidx
.reqid
;
1149 plog(LLV_NOTIFY
, LOCATION
, NULL
,
1150 "There is a difference "
1151 "between the in/out bound policies in SPD.\n");
1155 iph2
->proposal
= newpp
;
1157 printsaprop0(LLV_DEBUG
, newpp
);
1166 * generate a policy from peer's proposal.
1167 * this function unconditionally choices first proposal in SA payload
1171 set_proposal_from_proposal(iph2
)
1172 struct ph2handle
*iph2
;
1174 struct saprop
*newpp
= NULL
, *pp0
, *pp_peer
= NULL
;
1175 struct saproto
*newpr
= NULL
, *pr
;
1176 struct prop_pair
**pair
;
1180 /* get proposal pair */
1181 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
1186 * make my proposal according as the client proposal.
1187 * XXX assumed there is only one proposal even if it's the SA bundle.
1189 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1190 if (pair
[i
] == NULL
)
1193 if (pp_peer
!= NULL
)
1194 flushsaprop(pp_peer
);
1196 pp_peer
= aproppair2saprop(pair
[i
]);
1197 if (pp_peer
== NULL
)
1202 plog(LLV_ERROR
, LOCATION
, NULL
,
1203 "failed to allocate saprop.\n");
1207 pp0
->lifetime
= iph2
->sainfo
->lifetime
;
1208 pp0
->lifebyte
= iph2
->sainfo
->lifebyte
;
1209 pp0
->pfs_group
= iph2
->sainfo
->pfs_group
;
1212 if (*pp_peer
->sctx
.ctx_str
) {
1213 pp0
->sctx
.ctx_doi
= pp_peer
->sctx
.ctx_doi
;
1214 pp0
->sctx
.ctx_alg
= pp_peer
->sctx
.ctx_alg
;
1215 pp0
->sctx
.ctx_strlen
= pp_peer
->sctx
.ctx_strlen
;
1216 memcpy(pp0
->sctx
.ctx_str
, pp_peer
->sctx
.ctx_str
,
1217 pp_peer
->sctx
.ctx_strlen
);
1219 #endif /* HAVE_SECCTX */
1221 if (pp_peer
->next
!= NULL
) {
1222 plog(LLV_ERROR
, LOCATION
, NULL
,
1223 "pp_peer is inconsistency, ignore it.\n");
1227 for (pr
= pp_peer
->head
; pr
; pr
= pr
->next
)
1229 newpr
= newsaproto();
1232 plog(LLV_ERROR
, LOCATION
, NULL
,
1233 "failed to allocate saproto.\n");
1237 newpr
->proto_id
= pr
->proto_id
;
1238 newpr
->spisize
= pr
->spisize
;
1239 newpr
->encmode
= pr
->encmode
;
1241 newpr
->spi_p
= pr
->spi
; /* copy peer's SPI */
1242 newpr
->reqid_in
= 0;
1243 newpr
->reqid_out
= 0;
1245 if (iph2
->ph1
->rmconf
->gen_policy
== GENERATE_POLICY_UNIQUE
){
1246 newpr
->reqid_in
= g_nextreqid
;
1247 newpr
->reqid_out
= g_nextreqid
++;
1249 * XXX there is a (very limited)
1250 * risk of reusing the same reqid
1251 * as another SP entry for the same peer
1253 if(g_nextreqid
>= IPSEC_MANUAL_REQID_MAX
)
1256 newpr
->reqid_in
= 0;
1257 newpr
->reqid_out
= 0;
1260 if (set_satrnsbysainfo(newpr
, iph2
->sainfo
) < 0)
1262 plog(LLV_ERROR
, LOCATION
, NULL
,
1263 "failed to get algorithms.\n");
1268 inssaproto(pp0
, newpr
);
1271 inssaprop(&newpp
, pp0
);
1274 plog(LLV_DEBUG
, LOCATION
, NULL
, "make a proposal from peer's:\n");
1275 printsaprop0(LLV_DEBUG
, newpp
);
1277 iph2
->proposal
= newpp
;
1286 flushsaprop(pp_peer
);
1288 free_proppair(pair
);