1 /* $NetBSD: ipsec_doi.c,v 1.42 2009/05/18 17:40:38 tteras Exp $ */
3 /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu 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/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
40 #include <netinet/in.h>
49 #if TIME_WITH_SYS_TIME
50 # include <sys/time.h>
54 # include <sys/time.h>
66 #include "cfparse_proto.h"
67 #include "isakmp_var.h"
69 #include "ipsec_doi.h"
71 #include "remoteconf.h"
72 #include "localconf.h"
76 #include "algorithm.h"
79 #include "crypto_openssl.h"
84 #include "nattraversal.h"
90 #ifdef HAVE_ICONV_2ND_CONST
91 #define __iconv_const const
97 static vchar_t
*get_ph1approval
__P((struct ph1handle
*, u_int32_t
, u_int32_t
,
98 struct prop_pair
**));
99 static int get_ph1approvalx
__P((struct remoteconf
*, void *));
101 static int t2isakmpsa
__P((struct isakmp_pl_t
*, struct isakmpsa
*, u_int32_t
));
102 static int cmp_aproppair_i
__P((struct prop_pair
*, struct prop_pair
*));
103 static struct prop_pair
*get_ph2approval
__P((struct ph2handle
*,
104 struct prop_pair
**));
105 static struct prop_pair
*get_ph2approvalx
__P((struct ph2handle
*,
106 struct prop_pair
*));
107 static void free_proppair0
__P((struct prop_pair
*));
108 static struct prop_pair
** get_proppair_and_doi_sit
__P((vchar_t
*, int,
109 u_int32_t
*, u_int32_t
*));
111 static int get_transform
112 __P((struct isakmp_pl_p
*, struct prop_pair
**, int *));
113 static u_int32_t ipsecdoi_set_ld
__P((vchar_t
*));
115 static int check_doi
__P((u_int32_t
));
116 static int check_situation
__P((u_int32_t
));
118 static int check_prot_main
__P((int));
119 static int check_prot_quick
__P((int));
120 static int (*check_protocol
[]) __P((int)) = {
121 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
122 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
125 static int check_spi_size
__P((int, int));
127 static int check_trns_isakmp
__P((int));
128 static int check_trns_ah
__P((int));
129 static int check_trns_esp
__P((int));
130 static int check_trns_ipcomp
__P((int));
131 static int (*check_transform
[]) __P((int)) = {
133 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
134 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
135 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
136 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
139 static int check_attr_isakmp
__P((struct isakmp_pl_t
*));
140 static int check_attr_ah
__P((struct isakmp_pl_t
*));
141 static int check_attr_esp
__P((struct isakmp_pl_t
*));
142 static int check_attr_ipsec
__P((int, struct isakmp_pl_t
*));
143 static int check_attr_ipcomp
__P((struct isakmp_pl_t
*));
144 static int (*check_attributes
[]) __P((struct isakmp_pl_t
*)) = {
146 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
147 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
148 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
149 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
152 static int setph1prop
__P((struct isakmpsa
*, caddr_t
));
153 static int setph1trns
__P((struct isakmpsa
*, caddr_t
));
154 static int setph1attr
__P((struct isakmpsa
*, caddr_t
));
155 static vchar_t
*setph2proposal0
__P((const struct ph2handle
*,
156 const struct saprop
*, const struct saproto
*));
158 struct ph1approvalx_ctx
{
165 * check phase 1 SA payload.
166 * make new SA payload to be replyed not including general header.
167 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
169 * positive: the pointer to new buffer of SA payload.
170 * network byte order.
171 * NULL : error occurd.
174 ipsecdoi_checkph1proposal(sa
, iph1
)
176 struct ph1handle
*iph1
;
178 vchar_t
*newsa
; /* new SA payload approved. */
179 struct prop_pair
**pair
;
180 u_int32_t doitype
, sittype
;
182 /* get proposal pair */
183 pair
= get_proppair_and_doi_sit(sa
, IPSECDOI_TYPE_PH1
,
188 /* check and get one SA for use */
189 newsa
= get_ph1approval(iph1
, doitype
, sittype
, pair
);
195 iph1
->sa_ret
= newsa
;
200 print_ph1proposal(pair
, s
)
201 struct prop_pair
*pair
;
204 struct isakmp_pl_p
*prop
= pair
->prop
;
205 struct isakmp_pl_t
*trns
= pair
->trns
;
207 plog(LLV_DEBUG
, LOCATION
, NULL
,
208 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
209 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
210 prop
->spi_size
, prop
->num_t
);
211 plog(LLV_DEBUG
, LOCATION
, NULL
,
212 "trns#=%d, trns-id=%s\n",
213 trns
->t_no
, s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
214 plog(LLV_DEBUG
, LOCATION
, NULL
,
215 " lifetime = %ld\n", (long) s
->lifetime
);
216 plog(LLV_DEBUG
, LOCATION
, NULL
,
217 " lifebyte = %zu\n", s
->lifebyte
);
218 plog(LLV_DEBUG
, LOCATION
, NULL
,
220 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
, s
->enctype
));
221 plog(LLV_DEBUG
, LOCATION
, NULL
,
222 " encklen = %d\n", s
->encklen
);
223 plog(LLV_DEBUG
, LOCATION
, NULL
,
225 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
, s
->hashtype
));
226 plog(LLV_DEBUG
, LOCATION
, NULL
,
227 " authmethod = %s\n",
228 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
, s
->authmethod
));
229 plog(LLV_DEBUG
, LOCATION
, NULL
,
231 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
, s
->dh_group
));
236 * acceptable check for remote configuration.
237 * return a new SA payload to be reply to peer.
241 get_ph1approval(iph1
, doitype
, sittype
, pair
)
242 struct ph1handle
*iph1
;
243 u_int32_t doitype
, sittype
;
244 struct prop_pair
**pair
;
247 struct ph1approvalx_ctx ctx
;
248 struct prop_pair
*s
, *p
;
249 struct rmconfselector rmsel
;
253 memset(&rmsel
, 0, sizeof(rmsel
));
254 rmsel
.remote
= iph1
->remote
;
256 if (iph1
->approval
) {
257 delisakmpsa(iph1
->approval
);
258 iph1
->approval
= NULL
;
261 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
264 for (s
= pair
[i
]; s
; s
= s
->next
) {
265 /* compare proposal and select one */
266 for (p
= s
; p
; p
= p
->tnext
) {
267 struct isakmp_pl_p
*prop
= p
->prop
;
272 if (t2isakmpsa(p
->trns
, sa
,
273 iph1
->vendorid_mask
) < 0)
275 print_ph1proposal(p
, sa
);
276 if (iph1
->rmconf
!= NULL
) {
277 if (get_ph1approvalx(iph1
->rmconf
, &ctx
))
280 if (enumrmconf(&rmsel
, get_ph1approvalx
, &ctx
))
288 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable proposal found.\n");
294 plog(LLV_DEBUG
, LOCATION
, NULL
, "an acceptable proposal found.\n");
296 /* check DH group settings */
298 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
302 plog(LLV_WARNING
, LOCATION
, NULL
,
303 "invalid DH parameter found, use default.\n");
304 oakley_dhgrp_free(sa
->dhgrp
);
308 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
316 if (sa
->gssid
!= NULL
)
317 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id in new sa '%.*s'\n",
318 (int)sa
->gssid
->l
, sa
->gssid
->v
);
319 if (iph1
->side
== INITIATOR
) {
320 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
321 iph1
->gi_i
= vdup(iph1
->rmconf
->proposal
->gssid
);
322 if (sa
->gssid
!= NULL
)
323 iph1
->gi_r
= vdup(sa
->gssid
);
325 if (sa
->gssid
!= NULL
) {
326 iph1
->gi_r
= vdup(sa
->gssid
);
327 iph1
->gi_i
= gssapi_get_id(iph1
);
330 if (iph1
->gi_i
!= NULL
)
331 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIi is %.*s\n",
332 (int)iph1
->gi_i
->l
, iph1
->gi_i
->v
);
333 if (iph1
->gi_r
!= NULL
)
334 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIr is %.*s\n",
335 (int)iph1
->gi_r
->l
, iph1
->gi_r
->v
);
337 plog(LLV_DEBUG
, LOCATION
, NULL
, "agreed on %s auth.\n",
338 s_oakley_attr_method(sa
->authmethod
));
340 newsa
= get_sabyproppair(doitype
, sittype
, p
);
350 * compare peer's single proposal and all of my proposal.
351 * and select one if suiatable.
354 get_ph1approvalx(rmconf
, ctx
)
355 struct remoteconf
*rmconf
;
358 struct ph1approvalx_ctx
*pctx
= (struct ph1approvalx_ctx
*) ctx
;
361 /* do the hard work */
362 sa
= checkisakmpsa(rmconf
->pcheck_level
, pctx
->sa
, rmconf
->proposal
);
366 /* duplicate and modify the found SA to match proposal */
367 sa
= dupisakmpsa(sa
);
369 switch (rmconf
->pcheck_level
) {
370 case PROP_CHECK_OBEY
:
371 sa
->lifetime
= pctx
->sa
->lifetime
;
372 sa
->lifebyte
= pctx
->sa
->lifebyte
;
374 case PROP_CHECK_CLAIM
:
375 if (pctx
->sa
->lifetime
< sa
->lifetime
)
376 sa
->lifetime
= pctx
->sa
->lifetime
;
377 if (pctx
->sa
->lifebyte
< sa
->lifebyte
)
378 sa
->lifebyte
= pctx
->sa
->lifebyte
;
384 /* replace the proposal with our approval sa */
385 delisakmpsa(pctx
->sa
);
392 * get ISAKMP data attributes
395 t2isakmpsa(trns
, sa
, vendorid_mask
)
396 struct isakmp_pl_t
*trns
;
398 u_int32_t vendorid_mask
;
400 struct isakmp_data
*d
, *prev
;
409 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
410 prev
= (struct isakmp_data
*)NULL
;
411 d
= (struct isakmp_data
*)(trns
+ 1);
414 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
415 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
417 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
423 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
424 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
426 plog(LLV_DEBUG
, LOCATION
, NULL
,
427 "type=%s, flag=0x%04x, lorv=%s\n",
428 s_oakley_attr(type
), flag
,
429 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
431 /* get variable-sized item */
433 case OAKLEY_ATTR_GRP_PI
:
434 case OAKLEY_ATTR_GRP_GEN_ONE
:
435 case OAKLEY_ATTR_GRP_GEN_TWO
:
436 case OAKLEY_ATTR_GRP_CURVE_A
:
437 case OAKLEY_ATTR_GRP_CURVE_B
:
438 case OAKLEY_ATTR_SA_LD
:
439 case OAKLEY_ATTR_GRP_ORDER
:
442 p
= (u_char
*)&d
->lorv
;
444 len
= ntohs(d
->lorv
);
445 p
= (u_char
*)(d
+ 1);
450 memcpy(val
->v
, p
, len
);
458 case OAKLEY_ATTR_ENC_ALG
:
459 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
462 case OAKLEY_ATTR_HASH_ALG
:
463 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
466 case OAKLEY_ATTR_AUTH_METHOD
:
467 sa
->authmethod
= ntohs(d
->lorv
);
469 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL
&&
470 (vendorid_mask
& VENDORID_GSSAPI_MASK
))
471 sa
->authmethod
= OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
;
475 case OAKLEY_ATTR_GRP_DESC
:
476 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
479 case OAKLEY_ATTR_GRP_TYPE
:
481 int type
= (int)ntohs(d
->lorv
);
482 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
483 sa
->dhgrp
->type
= type
;
488 case OAKLEY_ATTR_GRP_PI
:
489 sa
->dhgrp
->prime
= val
;
492 case OAKLEY_ATTR_GRP_GEN_ONE
:
495 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
497 int len
= ntohs(d
->lorv
);
501 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
502 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
506 case OAKLEY_ATTR_GRP_GEN_TWO
:
509 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
511 int len
= ntohs(d
->lorv
);
515 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
516 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
520 case OAKLEY_ATTR_GRP_CURVE_A
:
521 sa
->dhgrp
->curve_a
= val
;
524 case OAKLEY_ATTR_GRP_CURVE_B
:
525 sa
->dhgrp
->curve_b
= val
;
528 case OAKLEY_ATTR_SA_LD_TYPE
:
530 int type
= (int)ntohs(d
->lorv
);
532 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
533 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
537 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
542 case OAKLEY_ATTR_SA_LD
:
544 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
545 OAKLEY_ATTR_SA_LD_TYPE
) {
546 plog(LLV_ERROR
, LOCATION
, NULL
,
547 "life duration must follow ltype\n");
552 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
553 sa
->lifetime
= ipsecdoi_set_ld(val
);
555 if (sa
->lifetime
== 0) {
556 plog(LLV_ERROR
, LOCATION
, NULL
,
557 "invalid life duration.\n");
561 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
562 sa
->lifebyte
= ipsecdoi_set_ld(val
);
564 if (sa
->lifebyte
== 0) {
565 plog(LLV_ERROR
, LOCATION
, NULL
,
566 "invalid life duration.\n");
572 plog(LLV_ERROR
, LOCATION
, NULL
,
573 "invalid life type: %d\n", life_t
);
578 case OAKLEY_ATTR_KEY_LEN
:
580 int len
= ntohs(d
->lorv
);
582 plog(LLV_ERROR
, LOCATION
, NULL
,
583 "keylen %d: not multiple of 8\n",
587 sa
->encklen
= (u_int16_t
)len
;
591 case OAKLEY_ATTR_PRF
:
592 case OAKLEY_ATTR_FIELD_SIZE
:
596 case OAKLEY_ATTR_GRP_ORDER
:
597 sa
->dhgrp
->order
= val
;
600 case OAKLEY_ATTR_GSS_ID
:
603 iconv_t cd
= (iconv_t
) -1;
604 size_t srcleft
, dstleft
, rv
;
605 __iconv_const
char *src
;
607 int len
= ntohs(d
->lorv
);
610 * Older verions of racoon just placed the
611 * ISO-Latin-1 string on the wire directly.
612 * Check to see if we are configured to be
613 * compatible with this behavior.
615 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
616 if ((sa
->gssid
= vmalloc(len
)) == NULL
) {
617 plog(LLV_ERROR
, LOCATION
, NULL
,
618 "failed to allocate memory\n");
621 memcpy(sa
->gssid
->v
, d
+ 1, len
);
622 plog(LLV_DEBUG
, LOCATION
, NULL
,
623 "received old-style gss "
624 "id '%.*s' (len %zu)\n",
625 (int)sa
->gssid
->l
, sa
->gssid
->v
,
632 * For Windows 2000 compatibility, we expect
633 * the GSS ID attribute on the wire to be
634 * encoded in UTF-16LE. Internally, we work
635 * in ISO-Latin-1. Therefore, we should need
636 * 1/2 the specified length, which should always
637 * be a multiple of 2 octets.
639 cd
= iconv_open("latin1", "utf-16le");
640 if (cd
== (iconv_t
) -1) {
641 plog(LLV_ERROR
, LOCATION
, NULL
,
642 "unable to initialize utf-16le -> latin1 "
643 "conversion descriptor: %s\n",
648 if ((sa
->gssid
= vmalloc(len
/ 2)) == NULL
) {
649 plog(LLV_ERROR
, LOCATION
, NULL
,
650 "failed to allocate memory\n");
654 src
= (__iconv_const
char *)(d
+ 1);
660 rv
= iconv(cd
, (__iconv_const
char **)&src
, &srcleft
,
664 plog(LLV_ERROR
, LOCATION
, NULL
,
665 "unable to convert GSS ID from "
666 "utf-16le -> latin1: %s\n",
669 plog(LLV_ERROR
, LOCATION
, NULL
,
670 "%zd character%s in GSS ID cannot "
671 "be represented in latin1\n",
672 rv
, rv
== 1 ? "" : "s");
677 /* XXX dstleft should always be 0; assert it? */
678 sa
->gssid
->l
= (len
/ 2) - dstleft
;
680 plog(LLV_DEBUG
, LOCATION
, NULL
,
681 "received gss id '%.*s' (len %zu)\n",
682 (int)sa
->gssid
->l
, sa
->gssid
->v
, sa
->gssid
->l
);
686 if (cd
!= (iconv_t
)-1)
687 (void)iconv_close(cd
);
689 if ((error
!= 0) && (sa
->gssid
!= NULL
)) {
695 #endif /* HAVE_GSSAPI */
704 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
706 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
707 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
711 /* key length must not be specified on some algorithms */
713 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
714 #ifdef HAVE_OPENSSL_IDEA_H
715 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_IDEA
717 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
718 plog(LLV_ERROR
, LOCATION
, NULL
,
719 "keylen must not be specified "
720 "for encryption algorithm %d\n",
733 * check phase 2 SA payload and select single proposal.
734 * make new SA payload to be replyed not including general header.
735 * This function is called by responder only.
741 ipsecdoi_selectph2proposal(iph2
)
742 struct ph2handle
*iph2
;
744 struct prop_pair
**pair
;
745 struct prop_pair
*ret
;
746 u_int32_t doitype
, sittype
;
748 /* get proposal pair */
749 pair
= get_proppair_and_doi_sit(iph2
->sa
, IPSECDOI_TYPE_PH2
,
754 /* check and select a proposal. */
755 ret
= get_ph2approval(iph2
, pair
);
760 /* make a SA to be replayed. */
761 /* SPI must be updated later. */
762 iph2
->sa_ret
= get_sabyproppair(doitype
, sittype
, ret
);
764 if (iph2
->sa_ret
== NULL
)
771 * check phase 2 SA payload returned from responder.
772 * This function is called by initiator only.
778 ipsecdoi_checkph2proposal(iph2
)
779 struct ph2handle
*iph2
;
781 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
785 vchar_t
*sa_ret
= NULL
;
786 u_int32_t doitype
, sittype
;
788 /* get proposal pair of SA sent. */
789 spair
= get_proppair_and_doi_sit(iph2
->sa
, IPSECDOI_TYPE_PH2
,
792 plog(LLV_ERROR
, LOCATION
, NULL
,
793 "failed to get prop pair.\n");
797 /* XXX should check the number of transform */
799 /* get proposal pair of SA replayed */
800 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
802 plog(LLV_ERROR
, LOCATION
, NULL
,
803 "failed to get prop pair.\n");
807 /* check proposal is only one ? */
810 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
817 plog(LLV_ERROR
, LOCATION
, NULL
,
818 "no proposal received.\n");
822 plog(LLV_ERROR
, LOCATION
, NULL
,
823 "some proposals received.\n");
827 if (spair
[n
] == NULL
) {
828 plog(LLV_WARNING
, LOCATION
, NULL
,
829 "invalid proposal number:%d received.\n", i
);
833 if (rpair
[n
]->tnext
!= NULL
) {
834 plog(LLV_ERROR
, LOCATION
, NULL
,
835 "multi transforms replyed.\n");
839 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
840 plog(LLV_ERROR
, LOCATION
, NULL
,
841 "proposal mismathed.\n");
846 * check and select a proposal.
847 * ensure that there is no modification of the proposal by
850 p
= get_ph2approval(iph2
, rpair
);
854 /* make a SA to be replayed. */
855 sa_ret
= iph2
->sa_ret
;
856 iph2
->sa_ret
= get_sabyproppair(doitype
, sittype
, p
);
858 if (iph2
->sa_ret
== NULL
)
865 free_proppair(rpair
);
867 free_proppair(spair
);
875 * compare two prop_pair which is assumed to have same proposal number.
876 * the case of bundle or single SA, NOT multi transforms.
877 * a: a proposal that is multi protocols and single transform, usually replyed.
878 * b: a proposal that is multi protocols and multi transform, usually sent.
879 * NOTE: this function is for initiator.
883 * XXX cannot understand the comment!
886 cmp_aproppair_i(a
, b
)
887 struct prop_pair
*a
, *b
;
889 struct prop_pair
*p
, *q
, *r
;
892 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
893 for (r
= q
; r
; r
= r
->tnext
) {
895 if (p
->trns
->t_no
== r
->trns
->t_no
)
899 /* no suitable transform found */
900 plog(LLV_ERROR
, LOCATION
, NULL
,
901 "no suitable transform found.\n");
906 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
907 plog(LLV_WARNING
, LOCATION
, NULL
,
908 "proposal #%d mismatched, "
910 r
->prop
->p_no
, p
->prop
->p_no
);
914 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
915 plog(LLV_ERROR
, LOCATION
, NULL
,
916 "proto_id mismathed: my:%d peer:%d\n",
917 r
->prop
->proto_id
, p
->prop
->proto_id
);
921 if (p
->prop
->spi_size
!= r
->prop
->spi_size
) {
922 plog(LLV_ERROR
, LOCATION
, NULL
,
923 "invalid spi size: %d.\n",
928 /* check #of transforms */
929 if (p
->prop
->num_t
!= 1) {
930 plog(LLV_WARNING
, LOCATION
, NULL
,
931 "#of transform is %d, "
932 "but expected 1.\n", p
->prop
->num_t
);
936 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
937 plog(LLV_WARNING
, LOCATION
, NULL
,
938 "transform number has been modified.\n");
941 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
942 plog(LLV_WARNING
, LOCATION
, NULL
,
943 "reserved field should be zero.\n");
947 /* compare attribute */
948 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
949 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
950 plog(LLV_WARNING
, LOCATION
, NULL
,
951 "attribute has been modified.\n");
955 if ((p
&& !q
) || (!p
&& q
)) {
956 /* # of protocols mismatched */
957 plog(LLV_ERROR
, LOCATION
, NULL
,
958 "#of protocols mismatched.\n");
966 * acceptable check for policy configuration.
967 * return a new SA payload to be reply to peer.
969 static struct prop_pair
*
970 get_ph2approval(iph2
, pair
)
971 struct ph2handle
*iph2
;
972 struct prop_pair
**pair
;
974 struct prop_pair
*ret
;
977 iph2
->approval
= NULL
;
979 plog(LLV_DEBUG
, LOCATION
, NULL
,
980 "begin compare proposals.\n");
982 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
985 plog(LLV_DEBUG
, LOCATION
, NULL
,
986 "pair[%d]: %p\n", i
, pair
[i
]);
987 print_proppair(LLV_DEBUG
, pair
[i
]);;
989 /* compare proposal and select one */
990 ret
= get_ph2approvalx(iph2
, pair
[i
]);
997 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable policy found.\n");
1003 * compare my proposal and peers just one proposal.
1006 static struct prop_pair
*
1007 get_ph2approvalx(iph2
, pp
)
1008 struct ph2handle
*iph2
;
1009 struct prop_pair
*pp
;
1011 struct prop_pair
*ret
= NULL
;
1012 struct saprop
*pr0
, *pr
= NULL
;
1013 struct saprop
*q1
, *q2
;
1015 pr0
= aproppair2saprop(pp
);
1019 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1020 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1021 plog(LLV_DEBUG
, LOCATION
, NULL
,
1022 "peer's single bundle:\n");
1023 printsaprop0(LLV_DEBUG
, q1
);
1024 plog(LLV_DEBUG
, LOCATION
, NULL
,
1025 "my single bundle:\n");
1026 printsaprop0(LLV_DEBUG
, q2
);
1028 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1032 plog(LLV_ERROR
, LOCATION
, NULL
,
1036 /* no proposal matching */
1043 plog(LLV_DEBUG
, LOCATION
, NULL
, "matched\n");
1044 iph2
->approval
= pr
;
1048 struct prop_pair
*p
, *x
;
1049 struct prop_pair
*n
= NULL
;
1053 for (p
= pp
; p
; p
= p
->next
) {
1055 * find a proposal with matching proto_id.
1056 * we have analyzed validity already, in cmpsaprop_alloc().
1058 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1059 if (sp
->proto_id
== p
->prop
->proto_id
)
1067 for (x
= p
; x
; x
= x
->tnext
)
1068 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1073 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1075 plog(LLV_ERROR
, LOCATION
, NULL
,
1076 "failed to get buffer.\n");
1083 /* need to preserve the order */
1084 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1086 if (x
&& x
->prop
== n
->prop
) {
1087 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1098 /* #of transforms should be updated ? */
1107 struct prop_pair
**pair
;
1111 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1112 free_proppair0(pair
[i
]);
1119 free_proppair0(pair
)
1120 struct prop_pair
*pair
;
1122 struct prop_pair
*p
, *q
, *r
, *s
;
1138 * get proposal pairs from SA payload.
1139 * tiny check for proposal payload.
1141 static struct prop_pair
**
1142 get_proppair_and_doi_sit(sa
, mode
, doitype
, sittype
)
1145 u_int32_t
*doitype
, *sittype
;
1147 struct prop_pair
**pair
= NULL
;
1148 int num_p
= 0; /* number of proposal for use */
1152 struct ipsecdoi_sa_b
*sab
= (struct ipsecdoi_sa_b
*)sa
->v
;
1154 plog(LLV_DEBUG
, LOCATION
, NULL
, "total SA len=%zu\n", sa
->l
);
1155 plogdump(LLV_DEBUG
, sa
->v
, sa
->l
);
1157 /* check SA payload size */
1158 if (sa
->l
< sizeof(*sab
)) {
1159 plog(LLV_ERROR
, LOCATION
, NULL
,
1160 "Invalid SA length = %zu.\n", sa
->l
);
1165 if (check_doi(ntohl(sab
->doi
)) < 0)
1167 if (doitype
!= NULL
)
1168 *doitype
= ntohl(sab
->doi
);
1170 /* check SITUATION */
1171 if (check_situation(ntohl(sab
->sit
)) < 0)
1173 if (sittype
!= NULL
)
1174 *sittype
= ntohl(sab
->sit
);
1176 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1178 plog(LLV_ERROR
, LOCATION
, NULL
,
1179 "failed to get buffer.\n");
1182 memset(pair
, 0, sizeof(pair
));
1184 bp
= (caddr_t
)(sab
+ 1);
1185 tlen
= sa
->l
- sizeof(*sab
);
1188 struct isakmp_pl_p
*prop
;
1190 vchar_t
*pbuf
= NULL
;
1191 struct isakmp_parse_t
*pa
;
1193 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1197 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1198 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1200 /* check the value of next payload */
1201 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1202 plog(LLV_ERROR
, LOCATION
, NULL
,
1203 "Invalid payload type=%u\n", pa
->type
);
1208 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1211 plog(LLV_DEBUG
, LOCATION
, NULL
,
1212 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1215 plog(LLV_ERROR
, LOCATION
, NULL
,
1216 "invalid proposal with length %d\n", proplen
);
1221 /* check Protocol ID */
1222 if (!check_protocol
[mode
]) {
1223 plog(LLV_ERROR
, LOCATION
, NULL
,
1224 "unsupported mode %d\n", mode
);
1228 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1231 /* check SPI length when IKE. */
1232 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1236 if (get_transform(prop
, pair
, &num_p
) < 0) {
1247 struct prop_pair
*p
, *q
;
1249 /* check for proposals with no transforms */
1250 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1254 plog(LLV_DEBUG
, LOCATION
, NULL
, "pair %d:\n", i
);
1255 print_proppair(LLV_DEBUG
, pair
[i
]);
1257 notrans
= nprop
= 0;
1258 for (p
= pair
[i
]; p
; p
= p
->next
) {
1259 if (p
->trns
== NULL
) {
1263 for (q
= p
; q
; q
= q
->tnext
)
1269 * XXX at this moment, we cannot accept proposal group
1270 * with multiple proposals. this should be fixed.
1272 if (pair
[i
]->next
) {
1273 plog(LLV_WARNING
, LOCATION
, NULL
,
1274 "proposal #%u ignored "
1275 "(multiple proposal not supported)\n",
1276 pair
[i
]->prop
->p_no
);
1282 for (p
= pair
[i
]; p
; p
= q
) {
1289 plog(LLV_DEBUG
, LOCATION
, NULL
,
1290 "proposal #%u: %d transform\n",
1291 pair
[i
]->prop
->p_no
, nprop
);
1296 /* bark if no proposal is found. */
1298 plog(LLV_ERROR
, LOCATION
, NULL
,
1299 "no Proposal found.\n");
1311 get_proppair(sa
, mode
)
1315 return get_proppair_and_doi_sit(sa
, mode
, NULL
, NULL
);
1320 * check transform payload.
1322 * positive: return the pointer to the payload of valid transform.
1323 * 0 : No valid transform found.
1326 get_transform(prop
, pair
, num_p
)
1327 struct isakmp_pl_p
*prop
;
1328 struct prop_pair
**pair
;
1331 int tlen
; /* total length of all transform in a proposal */
1333 struct isakmp_pl_t
*trns
;
1335 vchar_t
*pbuf
= NULL
;
1336 struct isakmp_parse_t
*pa
;
1337 struct prop_pair
*p
= NULL
, *q
;
1340 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1341 tlen
= ntohs(prop
->h
.len
)
1342 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1343 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1347 /* check and get transform for use */
1349 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1350 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1355 /* check the value of next payload */
1356 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1357 plog(LLV_ERROR
, LOCATION
, NULL
,
1358 "Invalid payload type=%u\n", pa
->type
);
1362 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1365 plog(LLV_DEBUG
, LOCATION
, NULL
,
1366 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1368 /* check transform ID */
1369 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1370 plog(LLV_WARNING
, LOCATION
, NULL
,
1371 "unsupported proto_id %u\n",
1375 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1376 plog(LLV_WARNING
, LOCATION
, NULL
,
1377 "unsupported proto_id %u\n",
1382 if (!check_transform
[prop
->proto_id
]
1383 || !check_attributes
[prop
->proto_id
]) {
1384 plog(LLV_WARNING
, LOCATION
, NULL
,
1385 "unsupported proto_id %u\n",
1389 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1392 /* check data attributes */
1393 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1396 p
= racoon_calloc(1, sizeof(*p
));
1398 plog(LLV_ERROR
, LOCATION
, NULL
,
1399 "failed to get buffer.\n");
1406 /* need to preserve the order */
1407 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1409 if (q
&& q
->prop
== p
->prop
) {
1410 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1417 pair
[prop
->p_no
] = p
;
1429 * make a new SA payload from prop_pair.
1430 * NOTE: this function make spi value clear.
1433 get_sabyproppair(doitype
, sittype
, pair
)
1434 u_int32_t doitype
, sittype
;
1435 struct prop_pair
*pair
;
1439 u_int8_t
*np_p
= NULL
;
1440 struct prop_pair
*p
;
1441 int prophlen
, trnslen
;
1444 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1445 for (p
= pair
; p
; p
= p
->next
) {
1446 newtlen
+= sizeof(struct isakmp_pl_p
);
1447 newtlen
+= p
->prop
->spi_size
;
1448 newtlen
+= ntohs(p
->trns
->h
.len
);
1451 newsa
= vmalloc(newtlen
);
1452 if (newsa
== NULL
) {
1453 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1458 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1460 /* update some of values in SA header */
1461 ((struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(doitype
);
1462 ((struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(sittype
);
1463 bp
+= sizeof(struct ipsecdoi_sa_b
);
1465 /* create proposal payloads */
1466 for (p
= pair
; p
; p
= p
->next
) {
1467 prophlen
= sizeof(struct isakmp_pl_p
)
1468 + p
->prop
->spi_size
;
1469 trnslen
= ntohs(p
->trns
->h
.len
);
1472 *np_p
= ISAKMP_NPTYPE_P
;
1474 /* create proposal */
1476 memcpy(bp
, p
->prop
, prophlen
);
1477 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1478 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1479 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1480 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1481 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1484 /* create transform */
1485 memcpy(bp
, p
->trns
, trnslen
);
1486 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1487 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1495 * update responder's spi
1498 ipsecdoi_updatespi(iph2
)
1499 struct ph2handle
*iph2
;
1501 struct prop_pair
**pair
, *p
;
1508 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1511 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1515 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1516 /* multiple transform must be filtered by selectph2proposal.*/
1520 pp
= iph2
->approval
;
1522 /* create proposal payloads */
1523 for (p
= pair
[i
]; p
; p
= p
->next
) {
1525 * find a proposal/transform with matching proto_id/t_id.
1526 * we have analyzed validity already, in cmpsaprop_alloc().
1528 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1529 if (p
->prop
->proto_id
== pr
->proto_id
&&
1530 p
->trns
->t_id
== pr
->head
->trns_id
) {
1538 * XXX SPI bits are left-filled, for use with IPComp.
1539 * we should be switching to variable-length spi field...
1541 spi
= (u_int8_t
*)&pr
->spi
;
1542 spi
+= sizeof(pr
->spi
);
1544 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1549 free_proppair(pair
);
1554 * make a new SA payload from prop_pair.
1557 get_sabysaprop(pp0
, sa0
)
1561 struct prop_pair
**pair
= NULL
;
1562 vchar_t
*newsa
= NULL
;
1564 u_int8_t
*np_p
= NULL
;
1565 struct prop_pair
*p
= NULL
;
1569 int prophlen
, trnslen
;
1573 /* get proposal pair */
1574 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1578 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1579 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1581 if (pair
[pp
->prop_no
] == NULL
)
1584 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1585 newtlen
+= (sizeof(struct isakmp_pl_p
)
1588 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1589 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1590 if (tr
->trns_no
== p
->trns
->t_no
)
1596 newtlen
+= ntohs(p
->trns
->h
.len
);
1601 newsa
= vmalloc(newtlen
);
1602 if (newsa
== NULL
) {
1603 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1608 /* some of values of SA must be updated in the out of this function */
1609 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1610 bp
+= sizeof(struct ipsecdoi_sa_b
);
1612 /* create proposal payloads */
1613 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1615 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1616 prophlen
= sizeof(struct isakmp_pl_p
)
1617 + p
->prop
->spi_size
;
1619 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1620 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1621 if (tr
->trns_no
== p
->trns
->t_no
)
1627 trnslen
= ntohs(p
->trns
->h
.len
);
1630 *np_p
= ISAKMP_NPTYPE_P
;
1632 /* create proposal */
1634 memcpy(bp
, p
->prop
, prophlen
);
1635 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1636 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1637 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1638 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1641 /* create transform */
1642 memcpy(bp
, p
->trns
, trnslen
);
1643 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1644 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1656 if (newsa
!= NULL
) {
1666 * If some error happens then return 0. Although 0 means that lifetime is zero,
1667 * such a value should not be accepted.
1668 * Also 0 of lifebyte should not be included in a packet although 0 means not
1672 ipsecdoi_set_ld(buf
)
1682 ld
= ntohs(*(u_int16_t
*)buf
->v
);
1685 ld
= ntohl(*(u_int32_t
*)buf
->v
);
1688 plog(LLV_ERROR
, LOCATION
, NULL
,
1689 "length %zu of life duration "
1690 "isn't supported.\n", buf
->l
);
1698 * parse responder-lifetime attributes from payload
1701 ipsecdoi_parse_responder_lifetime(notify
, lifetime_sec
, lifetime_kb
)
1702 struct isakmp_pl_n
*notify
;
1703 u_int32_t
*lifetime_sec
;
1704 u_int32_t
*lifetime_kb
;
1706 struct isakmp_data
*d
;
1707 int flag
, type
, tlen
, ld_type
= -1;
1711 tlen
= ntohs(notify
->h
.len
) - sizeof(*notify
) - notify
->spi_size
;
1712 d
= (struct isakmp_data
*)((char *)(notify
+ 1) +
1715 while (tlen
>= sizeof(struct isakmp_data
)) {
1716 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
1717 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
1718 lorv
= ntohs(d
->lorv
);
1720 plog(LLV_DEBUG
, LOCATION
, NULL
,
1721 "type=%s, flag=0x%04x, lorv=%s\n",
1722 s_ipsecdoi_attr(type
), flag
,
1723 s_ipsecdoi_attr_v(type
, lorv
));
1726 case IPSECDOI_ATTR_SA_LD_TYPE
:
1728 plog(LLV_ERROR
, LOCATION
, NULL
,
1729 "must be TV when LD_TYPE.\n");
1734 case IPSECDOI_ATTR_SA_LD
:
1738 value
= ntohs(*(u_int16_t
*)(d
+ 1));
1740 value
= ntohl(*(u_int32_t
*)(d
+ 1));
1742 plog(LLV_ERROR
, LOCATION
, NULL
,
1743 "payload length %d for lifetime "
1744 "data length is unsupported.\n", lorv
);
1749 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
1750 if (lifetime_sec
!= NULL
)
1751 *lifetime_sec
= value
;
1752 plog(LLV_INFO
, LOCATION
, NULL
,
1753 "received RESPONDER-LIFETIME: %d "
1754 "seconds\n", value
);
1756 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
1757 if (lifetime_kb
!= NULL
)
1758 *lifetime_kb
= value
;
1759 plog(LLV_INFO
, LOCATION
, NULL
,
1760 "received RESPONDER-LIFETIME: %d "
1764 plog(LLV_ERROR
, LOCATION
, NULL
,
1765 "lifetime data received without "
1766 "lifetime data type.\n");
1774 d
= (struct isakmp_data
*)((char *)d
1777 tlen
-= (sizeof(*d
) + lorv
);
1778 d
= (struct isakmp_data
*)((char *)d
1779 + sizeof(*d
) + lorv
);
1799 plog(LLV_ERROR
, LOCATION
, NULL
,
1800 "invalid value of DOI 0x%08x.\n", doi
);
1810 check_situation(sit
)
1814 case IPSECDOI_SIT_IDENTITY_ONLY
:
1817 case IPSECDOI_SIT_SECRECY
:
1818 case IPSECDOI_SIT_INTEGRITY
:
1819 plog(LLV_ERROR
, LOCATION
, NULL
,
1820 "situation 0x%08x unsupported yet.\n", sit
);
1824 plog(LLV_ERROR
, LOCATION
, NULL
,
1825 "invalid situation 0x%08x.\n", sit
);
1832 * check protocol id in main mode
1835 check_prot_main(proto_id
)
1839 case IPSECDOI_PROTO_ISAKMP
:
1843 plog(LLV_ERROR
, LOCATION
, NULL
,
1844 "Illegal protocol id=%u.\n", proto_id
);
1851 * check protocol id in quick mode
1854 check_prot_quick(proto_id
)
1858 case IPSECDOI_PROTO_IPSEC_AH
:
1859 case IPSECDOI_PROTO_IPSEC_ESP
:
1862 case IPSECDOI_PROTO_IPCOMP
:
1866 plog(LLV_ERROR
, LOCATION
, NULL
,
1867 "invalid protocol id %d.\n", proto_id
);
1874 check_spi_size(proto_id
, size
)
1878 case IPSECDOI_PROTO_ISAKMP
:
1881 plog(LLV_WARNING
, LOCATION
, NULL
,
1882 "SPI size isn't zero, but IKE proposal.\n");
1886 case IPSECDOI_PROTO_IPSEC_AH
:
1887 case IPSECDOI_PROTO_IPSEC_ESP
:
1889 plog(LLV_ERROR
, LOCATION
, NULL
,
1890 "invalid SPI size=%d for IPSEC proposal.\n",
1896 case IPSECDOI_PROTO_IPCOMP
:
1897 if (size
!= 2 && size
!= 4) {
1898 plog(LLV_ERROR
, LOCATION
, NULL
,
1899 "invalid SPI size=%d for IPCOMP proposal.\n",
1913 * check transform ID in ISAKMP.
1916 check_trns_isakmp(t_id
)
1920 case IPSECDOI_KEY_IKE
:
1923 plog(LLV_ERROR
, LOCATION
, NULL
,
1924 "invalid transform-id=%u in proto_id=%u.\n",
1925 t_id
, IPSECDOI_KEY_IKE
);
1932 * check transform ID in AH.
1939 case IPSECDOI_AH_MD5
:
1940 case IPSECDOI_AH_SHA
:
1941 case IPSECDOI_AH_SHA256
:
1942 case IPSECDOI_AH_SHA384
:
1943 case IPSECDOI_AH_SHA512
:
1945 case IPSECDOI_AH_DES
:
1946 plog(LLV_ERROR
, LOCATION
, NULL
,
1947 "not support transform-id=%u in AH.\n", t_id
);
1950 plog(LLV_ERROR
, LOCATION
, NULL
,
1951 "invalid transform-id=%u in AH.\n", t_id
);
1958 * check transform ID in ESP.
1961 check_trns_esp(t_id
)
1965 case IPSECDOI_ESP_DES
:
1966 case IPSECDOI_ESP_3DES
:
1967 case IPSECDOI_ESP_NULL
:
1968 case IPSECDOI_ESP_RC5
:
1969 case IPSECDOI_ESP_CAST
:
1970 case IPSECDOI_ESP_BLOWFISH
:
1971 case IPSECDOI_ESP_AES
:
1972 case IPSECDOI_ESP_TWOFISH
:
1973 case IPSECDOI_ESP_CAMELLIA
:
1975 case IPSECDOI_ESP_DES_IV32
:
1976 case IPSECDOI_ESP_DES_IV64
:
1977 case IPSECDOI_ESP_IDEA
:
1978 case IPSECDOI_ESP_3IDEA
:
1979 case IPSECDOI_ESP_RC4
:
1980 plog(LLV_ERROR
, LOCATION
, NULL
,
1981 "not support transform-id=%u in ESP.\n", t_id
);
1984 plog(LLV_ERROR
, LOCATION
, NULL
,
1985 "invalid transform-id=%u in ESP.\n", t_id
);
1992 * check transform ID in IPCOMP.
1995 check_trns_ipcomp(t_id
)
1999 case IPSECDOI_IPCOMP_OUI
:
2000 case IPSECDOI_IPCOMP_DEFLATE
:
2001 case IPSECDOI_IPCOMP_LZS
:
2004 plog(LLV_ERROR
, LOCATION
, NULL
,
2005 "invalid transform-id=%u in IPCOMP.\n", t_id
);
2012 * check data attributes in IKE.
2015 check_attr_isakmp(trns
)
2016 struct isakmp_pl_t
*trns
;
2018 struct isakmp_data
*d
;
2023 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2024 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2027 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2028 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2029 lorv
= ntohs(d
->lorv
);
2031 plog(LLV_DEBUG
, LOCATION
, NULL
,
2032 "type=%s, flag=0x%04x, lorv=%s\n",
2033 s_oakley_attr(type
), flag
,
2034 s_oakley_attr_v(type
, lorv
));
2037 * some of the attributes must be encoded in TV.
2038 * see RFC2409 Appendix A "Attribute Classes".
2041 case OAKLEY_ATTR_ENC_ALG
:
2042 case OAKLEY_ATTR_HASH_ALG
:
2043 case OAKLEY_ATTR_AUTH_METHOD
:
2044 case OAKLEY_ATTR_GRP_DESC
:
2045 case OAKLEY_ATTR_GRP_TYPE
:
2046 case OAKLEY_ATTR_SA_LD_TYPE
:
2047 case OAKLEY_ATTR_PRF
:
2048 case OAKLEY_ATTR_KEY_LEN
:
2049 case OAKLEY_ATTR_FIELD_SIZE
:
2050 if (!flag
) { /* TLV*/
2051 plog(LLV_ERROR
, LOCATION
, NULL
,
2052 "oakley attribute %d must be TV.\n",
2059 /* sanity check for TLV. length must be specified. */
2060 if (!flag
&& lorv
== 0) { /*TLV*/
2061 plog(LLV_ERROR
, LOCATION
, NULL
,
2062 "invalid length %d for TLV attribute %d.\n",
2068 case OAKLEY_ATTR_ENC_ALG
:
2069 if (!alg_oakley_encdef_ok(lorv
)) {
2070 plog(LLV_ERROR
, LOCATION
, NULL
,
2071 "invalied encryption algorithm=%d.\n",
2077 case OAKLEY_ATTR_HASH_ALG
:
2078 if (!alg_oakley_hashdef_ok(lorv
)) {
2079 plog(LLV_ERROR
, LOCATION
, NULL
,
2080 "invalied hash algorithm=%d.\n",
2086 case OAKLEY_ATTR_AUTH_METHOD
:
2088 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2089 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2090 #ifdef ENABLE_HYBRID
2091 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2092 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
:
2094 #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
2095 /* These two authentication method IDs overlap. */
2096 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
:
2097 /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
2100 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2101 #ifdef ENABLE_HYBRID
2102 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
2103 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2104 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
2105 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2106 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2107 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
:
2108 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
2109 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
:
2110 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
2111 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
:
2112 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
2114 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2115 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2116 plog(LLV_ERROR
, LOCATION
, NULL
,
2117 "auth method %s isn't supported.\n",
2118 s_oakley_attr_method(lorv
));
2121 plog(LLV_ERROR
, LOCATION
, NULL
,
2122 "invalid auth method %d.\n",
2128 case OAKLEY_ATTR_GRP_DESC
:
2129 if (!alg_oakley_dhdef_ok(lorv
)) {
2130 plog(LLV_ERROR
, LOCATION
, NULL
,
2131 "invalid DH group %d.\n",
2137 case OAKLEY_ATTR_GRP_TYPE
:
2139 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2142 plog(LLV_ERROR
, LOCATION
, NULL
,
2143 "unsupported DH group type %d.\n",
2149 case OAKLEY_ATTR_GRP_PI
:
2150 case OAKLEY_ATTR_GRP_GEN_ONE
:
2151 /* sanity checks? */
2154 case OAKLEY_ATTR_GRP_GEN_TWO
:
2155 case OAKLEY_ATTR_GRP_CURVE_A
:
2156 case OAKLEY_ATTR_GRP_CURVE_B
:
2157 plog(LLV_ERROR
, LOCATION
, NULL
,
2158 "attr type=%u isn't supported.\n", type
);
2161 case OAKLEY_ATTR_SA_LD_TYPE
:
2163 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2164 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2167 plog(LLV_ERROR
, LOCATION
, NULL
,
2168 "invalid life type %d.\n", lorv
);
2173 case OAKLEY_ATTR_SA_LD
:
2174 /* should check the value */
2177 case OAKLEY_ATTR_PRF
:
2178 case OAKLEY_ATTR_KEY_LEN
:
2181 case OAKLEY_ATTR_FIELD_SIZE
:
2182 plog(LLV_ERROR
, LOCATION
, NULL
,
2183 "attr type=%u isn't supported.\n", type
);
2186 case OAKLEY_ATTR_GRP_ORDER
:
2189 case OAKLEY_ATTR_GSS_ID
:
2193 plog(LLV_ERROR
, LOCATION
, NULL
,
2194 "invalid attribute type %d.\n", type
);
2200 d
= (struct isakmp_data
*)((char *)d
2203 tlen
-= (sizeof(*d
) + lorv
);
2204 d
= (struct isakmp_data
*)((char *)d
2205 + sizeof(*d
) + lorv
);
2213 * check data attributes in IPSEC AH/ESP.
2217 struct isakmp_pl_t
*trns
;
2219 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2223 check_attr_esp(trns
)
2224 struct isakmp_pl_t
*trns
;
2226 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2230 check_attr_ipsec(proto_id
, trns
)
2232 struct isakmp_pl_t
*trns
;
2234 struct isakmp_data
*d
;
2238 int attrseen
[16]; /* XXX magic number */
2240 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2241 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2242 memset(attrseen
, 0, sizeof(attrseen
));
2245 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2246 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2247 lorv
= ntohs(d
->lorv
);
2249 plog(LLV_DEBUG
, LOCATION
, NULL
,
2250 "type=%s, flag=0x%04x, lorv=%s\n",
2251 s_ipsecdoi_attr(type
), flag
,
2252 s_ipsecdoi_attr_v(type
, lorv
));
2254 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2258 case IPSECDOI_ATTR_ENC_MODE
:
2260 plog(LLV_ERROR
, LOCATION
, NULL
,
2261 "must be TV when ENC_MODE.\n");
2266 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2267 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2270 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2271 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2272 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2273 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2274 plog(LLV_DEBUG
, LOCATION
, NULL
,
2275 "UDP encapsulation requested\n");
2279 plog(LLV_ERROR
, LOCATION
, NULL
,
2280 "invalid encryption mode=%u.\n",
2286 case IPSECDOI_ATTR_AUTH
:
2288 plog(LLV_ERROR
, LOCATION
, NULL
,
2289 "must be TV when AUTH.\n");
2294 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2295 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2296 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2298 plog(LLV_ERROR
, LOCATION
, NULL
,
2299 "auth algorithm %u conflicts "
2300 "with transform %u.\n",
2305 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2306 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2307 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2311 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2312 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2313 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2317 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2318 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2319 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2323 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2324 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2325 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2329 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2330 case IPSECDOI_ATTR_AUTH_KPDK
:
2331 plog(LLV_ERROR
, LOCATION
, NULL
,
2332 "auth algorithm %u isn't supported.\n",
2336 plog(LLV_ERROR
, LOCATION
, NULL
,
2337 "invalid auth algorithm=%u.\n",
2343 case IPSECDOI_ATTR_SA_LD_TYPE
:
2345 plog(LLV_ERROR
, LOCATION
, NULL
,
2346 "must be TV when LD_TYPE.\n");
2351 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2352 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2355 plog(LLV_ERROR
, LOCATION
, NULL
,
2356 "invalid life type %d.\n", lorv
);
2361 case IPSECDOI_ATTR_SA_LD
:
2363 /* i.e. ISAKMP_GEN_TV */
2364 plog(LLV_DEBUG
, LOCATION
, NULL
,
2365 "life duration was in TLV.\n");
2367 /* i.e. ISAKMP_GEN_TLV */
2369 plog(LLV_ERROR
, LOCATION
, NULL
,
2370 "invalid length of LD\n");
2376 case IPSECDOI_ATTR_GRP_DESC
:
2378 plog(LLV_ERROR
, LOCATION
, NULL
,
2379 "must be TV when GRP_DESC.\n");
2383 if (!alg_oakley_dhdef_ok(lorv
)) {
2384 plog(LLV_ERROR
, LOCATION
, NULL
,
2385 "invalid group description=%u.\n",
2391 case IPSECDOI_ATTR_KEY_LENGTH
:
2393 plog(LLV_ERROR
, LOCATION
, NULL
,
2394 "must be TV when KEY_LENGTH.\n");
2400 case IPSECDOI_ATTR_SECCTX
:
2402 plog(LLV_ERROR
, LOCATION
, NULL
,
2403 "SECCTX must be in TLV.\n");
2409 case IPSECDOI_ATTR_KEY_ROUNDS
:
2410 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2411 case IPSECDOI_ATTR_COMP_PRIVALG
:
2412 plog(LLV_ERROR
, LOCATION
, NULL
,
2413 "attr type=%u isn't supported.\n", type
);
2417 plog(LLV_ERROR
, LOCATION
, NULL
,
2418 "invalid attribute type %d.\n", type
);
2424 d
= (struct isakmp_data
*)((char *)d
2427 tlen
-= (sizeof(*d
) + lorv
);
2428 d
= (struct isakmp_data
*)((caddr_t
)d
2429 + sizeof(*d
) + lorv
);
2433 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2434 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2435 plog(LLV_ERROR
, LOCATION
, NULL
,
2436 "attr AUTH must be present for AH.\n");
2440 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2441 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2442 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2443 plog(LLV_ERROR
, LOCATION
, NULL
,
2444 "attr AUTH must be present for ESP NULL encryption.\n");
2452 check_attr_ipcomp(trns
)
2453 struct isakmp_pl_t
*trns
;
2455 struct isakmp_data
*d
;
2459 int attrseen
[16]; /* XXX magic number */
2461 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2462 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2463 memset(attrseen
, 0, sizeof(attrseen
));
2466 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2467 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2468 lorv
= ntohs(d
->lorv
);
2470 plog(LLV_DEBUG
, LOCATION
, NULL
,
2471 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2474 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2478 case IPSECDOI_ATTR_ENC_MODE
:
2480 plog(LLV_ERROR
, LOCATION
, NULL
,
2481 "must be TV when ENC_MODE.\n");
2486 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2487 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2490 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2491 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2492 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2493 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2494 plog(LLV_DEBUG
, LOCATION
, NULL
,
2495 "UDP encapsulation requested\n");
2499 plog(LLV_ERROR
, LOCATION
, NULL
,
2500 "invalid encryption mode=%u.\n",
2506 case IPSECDOI_ATTR_SA_LD_TYPE
:
2508 plog(LLV_ERROR
, LOCATION
, NULL
,
2509 "must be TV when LD_TYPE.\n");
2514 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2515 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2518 plog(LLV_ERROR
, LOCATION
, NULL
,
2519 "invalid life type %d.\n", lorv
);
2524 case IPSECDOI_ATTR_SA_LD
:
2526 /* i.e. ISAKMP_GEN_TV */
2527 plog(LLV_DEBUG
, LOCATION
, NULL
,
2528 "life duration was in TLV.\n");
2530 /* i.e. ISAKMP_GEN_TLV */
2532 plog(LLV_ERROR
, LOCATION
, NULL
,
2533 "invalid length of LD\n");
2539 case IPSECDOI_ATTR_GRP_DESC
:
2541 plog(LLV_ERROR
, LOCATION
, NULL
,
2542 "must be TV when GRP_DESC.\n");
2546 if (!alg_oakley_dhdef_ok(lorv
)) {
2547 plog(LLV_ERROR
, LOCATION
, NULL
,
2548 "invalid group description=%u.\n",
2554 case IPSECDOI_ATTR_AUTH
:
2555 plog(LLV_ERROR
, LOCATION
, NULL
,
2556 "invalid attr type=%u.\n", type
);
2559 case IPSECDOI_ATTR_KEY_LENGTH
:
2560 case IPSECDOI_ATTR_KEY_ROUNDS
:
2561 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2562 case IPSECDOI_ATTR_COMP_PRIVALG
:
2563 plog(LLV_ERROR
, LOCATION
, NULL
,
2564 "attr type=%u isn't supported.\n", type
);
2568 plog(LLV_ERROR
, LOCATION
, NULL
,
2569 "invalid attribute type %d.\n", type
);
2575 d
= (struct isakmp_data
*)((char *)d
2578 tlen
-= (sizeof(*d
) + lorv
);
2579 d
= (struct isakmp_data
*)((caddr_t
)d
2580 + sizeof(*d
) + lorv
);
2585 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2586 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2587 plog(LLV_ERROR
, LOCATION
, NULL
,
2588 "attr AUTH must be present for AH.\n", type
);
2598 * create phase1 proposal from remote configuration.
2599 * NOT INCLUDING isakmp general header of SA payload
2602 ipsecdoi_setph1proposal(rmconf
, props
)
2603 struct remoteconf
*rmconf
;
2604 struct isakmpsa
*props
;
2609 /* count total size of SA minus isakmp general header */
2610 /* not including isakmp general header of SA payload */
2611 sablen
= sizeof(struct ipsecdoi_sa_b
);
2612 sablen
+= setph1prop(props
, NULL
);
2614 mysa
= vmalloc(sablen
);
2616 plog(LLV_ERROR
, LOCATION
, NULL
,
2617 "failed to allocate my sa buffer\n");
2621 /* create SA payload */
2622 /* not including isakmp general header */
2623 ((struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(rmconf
->doitype
);
2624 ((struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(rmconf
->sittype
);
2626 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2632 setph1prop(props
, buf
)
2633 struct isakmpsa
*props
;
2636 struct isakmp_pl_p
*prop
= NULL
;
2637 struct isakmpsa
*s
= NULL
;
2638 int proplen
, trnslen
;
2639 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2643 proplen
= sizeof(*prop
);
2645 /* create proposal */
2646 prop
= (struct isakmp_pl_p
*)p
;
2647 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2648 prop
->p_no
= props
->prop_no
;
2649 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2657 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2659 *np_t
= ISAKMP_NPTYPE_T
;
2661 trnslen
= setph1trns(s
, p
);
2664 /* save buffer to pre-next payload */
2665 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2668 /* count up transform length */
2673 /* update proposal length */
2675 prop
->h
.len
= htons(proplen
);
2676 prop
->num_t
= trns_num
;
2684 struct isakmpsa
*sa
;
2687 struct isakmp_pl_t
*trns
= NULL
;
2688 int trnslen
, attrlen
;
2691 trnslen
= sizeof(*trns
);
2693 /* create transform */
2694 trns
= (struct isakmp_pl_t
*)p
;
2695 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2696 trns
->t_no
= sa
->trns_no
;
2697 trns
->t_id
= IPSECDOI_KEY_IKE
;
2701 attrlen
= setph1attr(sa
, p
);
2707 trns
->h
.len
= htons(trnslen
);
2714 struct isakmpsa
*sa
;
2721 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2723 attrlen
+= sizeof(struct isakmp_data
)
2724 + sizeof(struct isakmp_data
);
2725 if (sa
->lifetime
> 0xffff)
2726 attrlen
+= sizeof(lifetime
);
2728 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2729 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2730 if (sa
->lifetime
> 0xffff) {
2731 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2735 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2742 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2744 attrlen
+= sizeof(struct isakmp_data
)
2745 + sizeof(struct isakmp_data
);
2746 if (sa
->lifebyte
> 0xffff)
2747 attrlen
+= sizeof(lifebyte
);
2749 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2750 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2751 if (sa
->lifebyte
> 0xffff) {
2752 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2756 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2763 attrlen
+= sizeof(struct isakmp_data
);
2765 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2768 attrlen
+= sizeof(struct isakmp_data
);
2770 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2772 if (sa
->authmethod
) {
2775 authmethod
= isakmpsa_switch_authmethod(sa
->authmethod
);
2776 authmethod
&= 0xffff;
2777 attrlen
+= sizeof(struct isakmp_data
);
2779 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2782 attrlen
+= sizeof(struct isakmp_data
);
2784 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2786 switch (sa
->dh_group
) {
2787 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2788 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2789 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2790 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2791 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2792 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2793 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2794 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2795 /* don't attach group type for known groups */
2796 attrlen
+= sizeof(struct isakmp_data
);
2798 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2802 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2803 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2804 /* don't attach group type for known groups */
2805 attrlen
+= sizeof(struct isakmp_data
);
2807 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2808 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2817 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2818 sa
->gssid
!= NULL
) {
2819 attrlen
+= sizeof(struct isakmp_data
);
2821 * Older versions of racoon just placed the ISO-Latin-1
2822 * string on the wire directly. Check to see if we are
2823 * configured to be compatible with this behavior. Otherwise,
2824 * we encode the GSS ID as UTF-16LE for Windows 2000
2825 * compatibility, which requires twice the number of octets.
2827 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
)
2828 attrlen
+= sa
->gssid
->l
;
2830 attrlen
+= sa
->gssid
->l
* 2;
2832 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %zu, "
2833 "val '%.*s'\n", sa
->gssid
->l
, (int)sa
->gssid
->l
,
2835 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
2836 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2837 (caddr_t
)sa
->gssid
->v
,
2840 size_t dstleft
= sa
->gssid
->l
* 2;
2841 size_t srcleft
= sa
->gssid
->l
;
2842 const char *src
= (const char *)sa
->gssid
->v
;
2843 char *odst
, *dst
= racoon_malloc(dstleft
);
2847 cd
= iconv_open("utf-16le", "latin1");
2848 if (cd
== (iconv_t
) -1) {
2849 plog(LLV_ERROR
, LOCATION
, NULL
,
2850 "unable to initialize "
2851 "latin1 -> utf-16le "
2852 "converstion descriptor: %s\n",
2854 attrlen
-= sa
->gssid
->l
* 2;
2858 rv
= iconv(cd
, (__iconv_const
char **)&src
,
2859 &srcleft
, &dst
, &dstleft
);
2862 plog(LLV_ERROR
, LOCATION
, NULL
,
2863 "unable to convert GSS ID "
2864 "from latin1 -> utf-16le: "
2865 "%s\n", strerror(errno
));
2867 /* should never happen */
2868 plog(LLV_ERROR
, LOCATION
, NULL
,
2869 "%zd character%s in GSS ID "
2870 "cannot be represented "
2872 rv
, rv
== 1 ? "" : "s");
2874 (void) iconv_close(cd
);
2875 attrlen
-= sa
->gssid
->l
* 2;
2878 (void) iconv_close(cd
);
2880 /* XXX Check srcleft and dstleft? */
2882 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2883 odst
, sa
->gssid
->l
* 2);
2890 #endif /* HAVE_GSSAPI */
2896 setph2proposal0(iph2
, pp
, pr
)
2897 const struct ph2handle
*iph2
;
2898 const struct saprop
*pp
;
2899 const struct saproto
*pr
;
2902 struct isakmp_pl_p
*prop
;
2903 struct isakmp_pl_t
*trns
;
2908 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2909 const u_int8_t
*spi
;
2914 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2918 /* create proposal */
2919 prop
= (struct isakmp_pl_p
*)p
->v
;
2920 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2921 prop
->p_no
= pp
->prop_no
;
2922 prop
->proto_id
= pr
->proto_id
;
2925 spi
= (const u_int8_t
*)&pr
->spi
;
2926 switch (pr
->proto_id
) {
2927 case IPSECDOI_PROTO_IPCOMP
:
2929 * draft-shacham-ippcp-rfc2393bis-05.txt:
2930 * construct 16bit SPI (CPI).
2931 * XXX we may need to provide a configuration option to
2932 * generate 32bit SPI. otherwise we cannot interoeprate
2933 * with nodes that uses 32bit SPI, in case we are initiator.
2935 prop
->spi_size
= sizeof(u_int16_t
);
2936 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2937 p
->l
-= sizeof(pr
->spi
);
2938 p
->l
+= sizeof(u_int16_t
);
2941 prop
->spi_size
= sizeof(pr
->spi
);
2944 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2946 /* create transform */
2947 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2950 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2952 switch (pr
->proto_id
) {
2953 case IPSECDOI_PROTO_IPSEC_ESP
:
2955 * don't build a null encryption
2956 * with no authentication transform.
2958 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2959 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
2965 *np_t
= ISAKMP_NPTYPE_T
;
2969 /* get attribute length */
2972 attrlen
+= sizeof(struct isakmp_data
)
2973 + sizeof(struct isakmp_data
);
2974 if (pp
->lifetime
> 0xffff)
2975 attrlen
+= sizeof(u_int32_t
);
2977 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2978 attrlen
+= sizeof(struct isakmp_data
)
2979 + sizeof(struct isakmp_data
);
2980 if (pp
->lifebyte
> 0xffff)
2981 attrlen
+= sizeof(u_int32_t
);
2983 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2985 attrlen
+= sizeof(struct isakmp_data
);
2987 switch (pr
->proto_id
) {
2988 case IPSECDOI_PROTO_IPSEC_ESP
:
2989 /* non authentication mode ? */
2990 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2991 attrlen
+= sizeof(struct isakmp_data
);
2993 case IPSECDOI_PROTO_IPSEC_AH
:
2994 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2995 plog(LLV_ERROR
, LOCATION
, NULL
,
2996 "no authentication algorithm found "
2997 "but protocol is AH.\n");
3001 attrlen
+= sizeof(struct isakmp_data
);
3003 case IPSECDOI_PROTO_IPCOMP
:
3006 plog(LLV_ERROR
, LOCATION
, NULL
,
3007 "invalid protocol: %d\n", pr
->proto_id
);
3012 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3013 attrlen
+= sizeof(struct isakmp_data
);
3016 /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
3017 * The string may be smaller than MAX_CTXSTR_SIZ.
3019 if (*pp
->sctx
.ctx_str
) {
3020 truectxlen
= sizeof(struct security_ctx
) -
3021 (MAX_CTXSTR_SIZE
- pp
->sctx
.ctx_strlen
);
3022 attrlen
+= sizeof(struct isakmp_data
) + truectxlen
;
3024 #endif /* HAVE_SECCTX */
3026 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
3029 prop
= (struct isakmp_pl_p
*)p
->v
;
3031 /* set transform's values */
3032 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3033 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
3034 trns
->t_no
= tr
->trns_no
;
3035 trns
->t_id
= tr
->trns_id
;
3037 /* set attributes */
3038 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
3041 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3042 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
3043 if (pp
->lifetime
> 0xffff) {
3044 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
3045 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3046 (caddr_t
)&v
, sizeof(v
));
3048 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3053 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3054 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3055 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
3056 if (pp
->lifebyte
> 0xffff) {
3057 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
3058 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3059 (caddr_t
)&v
, sizeof(v
));
3061 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3066 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
3069 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
3071 /* mandatory check has done above. */
3072 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3073 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
3074 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
3076 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3077 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
3078 iph2
->sainfo
->pfs_group
);
3081 if (*pp
->sctx
.ctx_str
) {
3082 struct security_ctx secctx
;
3084 secctx
.ctx_strlen
= htons(pp
->sctx
.ctx_strlen
);
3085 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SECCTX
,
3086 (caddr_t
)&secctx
, truectxlen
);
3089 /* update length of this transform. */
3090 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3091 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
3093 /* save buffer to pre-next payload */
3096 trnsoff
+= (sizeof(*trns
) + attrlen
);
3100 plog(LLV_ERROR
, LOCATION
, NULL
,
3101 "no suitable proposal was created.\n");
3105 /* update length of this protocol. */
3106 prop
->h
.len
= htons(p
->l
);
3112 * create phase2 proposal from policy configuration.
3113 * NOT INCLUDING isakmp general header of SA payload.
3114 * This function is called by initiator only.
3117 ipsecdoi_setph2proposal(iph2
)
3118 struct ph2handle
*iph2
;
3120 struct saprop
*proposal
, *a
;
3121 struct saproto
*b
= NULL
;
3123 struct ipsecdoi_sa_b
*sab
;
3124 struct isakmp_pl_p
*prop
;
3125 size_t propoff
; /* for previous field of type of next payload. */
3127 proposal
= iph2
->proposal
;
3129 iph2
->sa
= vmalloc(sizeof(*sab
));
3130 if (iph2
->sa
== NULL
) {
3131 plog(LLV_ERROR
, LOCATION
, NULL
,
3132 "failed to allocate my sa buffer\n");
3136 /* create SA payload */
3137 sab
= (struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
3138 sab
->doi
= htonl(IPSEC_DOI
);
3139 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3143 for (a
= proposal
; a
; a
= a
->next
) {
3144 for (b
= a
->head
; b
; b
= b
->next
) {
3146 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3147 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3148 plog (LLV_INFO
, LOCATION
, NULL
,
3149 "NAT detected -> UDP encapsulation "
3150 "(ENC_MODE %d->%d).\n",
3152 b
->encmode
+udp_diff
);
3153 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3154 b
->encmode
+= udp_diff
;
3159 q
= setph2proposal0(iph2
, a
, b
);
3165 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
3166 if (iph2
->sa
== NULL
) {
3167 plog(LLV_ERROR
, LOCATION
, NULL
,
3168 "failed to allocate my sa buffer\n");
3173 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
3175 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
3177 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3179 propoff
= iph2
->sa
->l
- q
->l
;
3189 * return 1 if all of the given protocols are transport mode.
3192 ipsecdoi_transportmode(pp
)
3195 struct saproto
*pr
= NULL
;
3197 for (; pp
; pp
= pp
->next
) {
3198 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3199 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
&&
3200 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
&&
3201 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
3210 ipsecdoi_get_defaultlifetime()
3212 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3216 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3217 int proto_id
, enc
, auth
, comp
;
3219 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3221 case IPSECDOI_PROTO_IPSEC_ESP
:
3222 if (enc
== 0 || comp
!= 0) {
3223 plog(LLV_ERROR
, LOCATION
, NULL
,
3224 "illegal algorithm defined "
3225 "ESP enc=%s auth=%s comp=%s.\n",
3226 TMPALGTYPE2STR(enc
),
3227 TMPALGTYPE2STR(auth
),
3228 TMPALGTYPE2STR(comp
));
3232 case IPSECDOI_PROTO_IPSEC_AH
:
3233 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3234 plog(LLV_ERROR
, LOCATION
, NULL
,
3235 "illegal algorithm defined "
3236 "AH enc=%s auth=%s comp=%s.\n",
3237 TMPALGTYPE2STR(enc
),
3238 TMPALGTYPE2STR(auth
),
3239 TMPALGTYPE2STR(comp
));
3243 case IPSECDOI_PROTO_IPCOMP
:
3244 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3245 plog(LLV_ERROR
, LOCATION
, NULL
,
3246 "illegal algorithm defined "
3247 "IPcomp enc=%s auth=%s comp=%s.\n",
3248 TMPALGTYPE2STR(enc
),
3249 TMPALGTYPE2STR(auth
),
3250 TMPALGTYPE2STR(comp
));
3255 plog(LLV_ERROR
, LOCATION
, NULL
,
3256 "invalid ipsec protocol %d\n", proto_id
);
3259 #undef TMPALGTYPE2STR
3269 return IPSECDOI_PROTO_IPSEC_AH
;
3271 return IPSECDOI_PROTO_IPSEC_ESP
;
3272 case IPPROTO_IPCOMP
:
3273 return IPSECDOI_PROTO_IPCOMP
;
3275 return -1; /* XXX */
3283 case IPSECDOI_PROTO_IPSEC_AH
:
3285 case IPSECDOI_PROTO_IPSEC_ESP
:
3287 case IPSECDOI_PROTO_IPCOMP
:
3288 return IPPROTO_IPCOMP
;
3290 return -1; /* XXX */
3294 * Check if a subnet id is valid for comparison
3295 * with an address id ( address length mask )
3303 ipsecdoi_subnetisaddr_v4( subnet
, address
)
3304 const vchar_t
*subnet
;
3305 const vchar_t
*address
;
3307 struct in_addr
*mask
;
3309 if (address
->l
!= sizeof(struct in_addr
))
3312 if (subnet
->l
!= (sizeof(struct in_addr
)*2))
3315 mask
= (struct in_addr
*)(subnet
->v
+ sizeof(struct in_addr
));
3317 if (mask
->s_addr
!=0xffffffff)
3320 return memcmp(subnet
->v
,address
->v
,address
->l
);
3326 ipsecdoi_subnetisaddr_v6( subnet
, address
)
3327 const vchar_t
*subnet
;
3328 const vchar_t
*address
;
3330 struct in6_addr
*mask
;
3333 if (address
->l
!= sizeof(struct in6_addr
))
3336 if (subnet
->l
!= (sizeof(struct in6_addr
)*2))
3339 mask
= (struct in6_addr
*)(subnet
->v
+ sizeof(struct in6_addr
));
3341 for (i
=0; i
<16; i
++)
3342 if(mask
->s6_addr
[i
]!=0xff)
3345 return memcmp(subnet
->v
,address
->v
,address
->l
);
3351 * Check and Compare two IDs
3352 * - specify 0 for exact if wildcards are allowed
3356 * = -1 for integrity error
3360 ipsecdoi_chkcmpids( idt
, ids
, exact
)
3361 const vchar_t
*idt
; /* id cmp target */
3362 const vchar_t
*ids
; /* id cmp source */
3365 struct ipsecdoi_id_b
*id_bt
;
3366 struct ipsecdoi_id_b
*id_bs
;
3371 /* handle wildcard IDs */
3373 if (idt
== NULL
|| ids
== NULL
)
3377 plog(LLV_DEBUG
, LOCATION
, NULL
,
3378 "check and compare ids : values matched (ANONYMOUS)\n" );
3383 plog(LLV_DEBUG
, LOCATION
, NULL
,
3384 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3389 /* make sure the ids are of the same type */
3391 id_bt
= (struct ipsecdoi_id_b
*) idt
->v
;
3392 id_bs
= (struct ipsecdoi_id_b
*) ids
->v
;
3394 ident_t
.v
= idt
->v
+ sizeof(*id_bt
);
3395 ident_t
.l
= idt
->l
- sizeof(*id_bt
);
3396 ident_s
.v
= ids
->v
+ sizeof(*id_bs
);
3397 ident_s
.l
= ids
->l
- sizeof(*id_bs
);
3399 if (id_bs
->type
!= id_bt
->type
)
3402 * special exception for comparing
3403 * address to subnet id types when
3404 * the netmask is address length
3407 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR
)&&
3408 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)) {
3409 result
= ipsecdoi_subnetisaddr_v4(&ident_t
,&ident_s
);
3413 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)&&
3414 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR
)) {
3415 result
= ipsecdoi_subnetisaddr_v4(&ident_s
,&ident_t
);
3420 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR
)&&
3421 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)) {
3422 result
= ipsecdoi_subnetisaddr_v6(&ident_t
,&ident_s
);
3426 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)&&
3427 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR
)) {
3428 result
= ipsecdoi_subnetisaddr_v6(&ident_s
,&ident_t
);
3432 plog(LLV_DEBUG
, LOCATION
, NULL
,
3433 "check and compare ids : id type mismatch %s != %s\n",
3434 s_ipsecdoi_ident(id_bs
->type
),
3435 s_ipsecdoi_ident(id_bt
->type
));
3440 if(id_bs
->proto_id
!= id_bt
->proto_id
){
3441 plog(LLV_DEBUG
, LOCATION
, NULL
,
3442 "check and compare ids : proto_id mismatch %d != %d\n",
3443 id_bs
->proto_id
, id_bt
->proto_id
);
3448 /* compare the ID data. */
3450 switch (id_bt
->type
) {
3451 case IPSECDOI_ID_DER_ASN1_DN
:
3452 case IPSECDOI_ID_DER_ASN1_GN
:
3453 /* compare asn1 ids */
3454 result
= eay_cmp_asn1dn(&ident_t
, &ident_s
);
3457 case IPSECDOI_ID_IPV4_ADDR
:
3458 /* validate lengths */
3459 if ((ident_t
.l
!= sizeof(struct in_addr
))||
3460 (ident_s
.l
!= sizeof(struct in_addr
)))
3464 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3465 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3466 /* validate lengths */
3467 if ((ident_t
.l
!= (sizeof(struct in_addr
)*2))||
3468 (ident_s
.l
!= (sizeof(struct in_addr
)*2)))
3473 case IPSECDOI_ID_IPV6_ADDR
:
3474 /* validate lengths */
3475 if ((ident_t
.l
!= sizeof(struct in6_addr
))||
3476 (ident_s
.l
!= sizeof(struct in6_addr
)))
3480 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3481 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3482 /* validate lengths */
3483 if ((ident_t
.l
!= (sizeof(struct in6_addr
)*2))||
3484 (ident_s
.l
!= (sizeof(struct in6_addr
)*2)))
3488 case IPSECDOI_ID_FQDN
:
3489 case IPSECDOI_ID_USER_FQDN
:
3490 case IPSECDOI_ID_KEY_ID
:
3494 plog(LLV_ERROR
, LOCATION
, NULL
,
3495 "Unhandled id type %i specified for comparison\n",
3500 /* validate matching data and length */
3501 if (ident_t
.l
== ident_s
.l
)
3502 result
= memcmp(ident_t
.v
,ident_s
.v
,ident_t
.l
);
3508 /* debug level output */
3509 if(loglevel
>= LLV_DEBUG
) {
3510 char *idstrt
= ipsecdoi_id2str(idt
);
3511 char *idstrs
= ipsecdoi_id2str(ids
);
3514 plog(LLV_DEBUG
, LOCATION
, NULL
,
3515 "check and compare ids : values matched (%s)\n",
3516 s_ipsecdoi_ident(id_bs
->type
) );
3518 plog(LLV_DEBUG
, LOCATION
, NULL
,
3519 "check and compare ids : value mismatch (%s)\n",
3520 s_ipsecdoi_ident(id_bs
->type
));
3522 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid target: \'%s\'\n", idstrt
);
3523 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid source: \'%s\'\n", idstrs
);
3525 racoon_free(idstrs
);
3526 racoon_free(idstrt
);
3537 /* id integrity error */
3538 plog(LLV_DEBUG
, LOCATION
, NULL
, "check and compare ids : %s integrity error\n",
3539 s_ipsecdoi_ident(id_bs
->type
));
3540 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid target: length = \'%zu\'\n", ident_t
.l
);
3541 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid source: length = \'%zu\'\n", ident_s
.l
);
3547 * check the following:
3548 * - In main mode with pre-shared key, only address type can be used.
3549 * - if proper type for phase 1 ?
3550 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3551 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3552 * - if ID payload sent from peer is equal to the ID expected by me.
3554 * both of "id" and "id_p" should be ID payload without general header,
3557 ipsecdoi_checkid1(iph1
)
3558 struct ph1handle
*iph1
;
3560 struct ipsecdoi_id_b
*id_b
;
3562 if (iph1
->id_p
== NULL
) {
3563 plog(LLV_ERROR
, LOCATION
, NULL
,
3564 "invalid iph1 passed id_p == NULL\n");
3565 return ISAKMP_INTERNAL_ERROR
;
3567 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3568 plog(LLV_ERROR
, LOCATION
, NULL
,
3569 "invalid value passed as \"ident\" (len=%lu)\n",
3570 (u_long
)iph1
->id_p
->l
);
3571 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3574 id_b
= (struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3576 /* In main mode with pre-shared key, only address type can be used. */
3577 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
&&
3578 iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
) {
3579 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3580 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3581 plog(LLV_ERROR
, LOCATION
, NULL
,
3582 "Expecting IP address type in main mode, "
3583 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3584 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3588 /* if proper type for phase 1 ? */
3589 switch (id_b
->type
) {
3590 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3591 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3592 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3593 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3594 plog(LLV_WARNING
, LOCATION
, NULL
,
3595 "such ID type %s is not proper.\n",
3596 s_ipsecdoi_ident(id_b
->type
));
3600 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3601 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
||
3602 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3604 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3605 plog(LLV_WARNING
, LOCATION
, NULL
,
3606 "protocol ID and Port mismatched. "
3607 "proto_id:%d port:%d\n",
3608 id_b
->proto_id
, ntohs(id_b
->port
));
3611 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3613 * copmaring with expecting port.
3614 * always permit if port is equal to PORT_ISAKMP
3616 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3619 port
= extract_port(iph1
->remote
);
3620 if (ntohs(id_b
->port
) != port
) {
3621 plog(LLV_WARNING
, LOCATION
, NULL
,
3622 "port %d expected, but %d\n",
3623 port
, ntohs(id_b
->port
));
3630 /* resolve remote configuration if not done yet */
3631 if (resolveph1rmconf(iph1
) < 0)
3632 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3634 if (iph1
->rmconf
== NULL
)
3635 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3641 * create ID payload for phase 1 and set into iph1->id.
3642 * NOT INCLUDING isakmp general header.
3643 * see, RFC2407 4.6.2.1
3646 ipsecdoi_setid1(iph1
)
3647 struct ph1handle
*iph1
;
3649 vchar_t
*ret
= NULL
;
3650 struct ipsecdoi_id_b id_b
;
3651 vchar_t
*ident
= NULL
;
3652 struct sockaddr
*ipid
= NULL
;
3659 switch (iph1
->rmconf
->idvtype
) {
3661 id_b
.type
= IPSECDOI_ID_FQDN
;
3662 ident
= vdup(iph1
->rmconf
->idv
);
3664 case IDTYPE_USERFQDN
:
3665 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3666 ident
= vdup(iph1
->rmconf
->idv
);
3669 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3670 ident
= vdup(iph1
->rmconf
->idv
);
3673 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3674 if (iph1
->rmconf
->idv
) {
3675 /* XXX it must be encoded to asn1dn. */
3676 ident
= vdup(iph1
->rmconf
->idv
);
3678 if (oakley_getmycert(iph1
) < 0) {
3679 plog(LLV_ERROR
, LOCATION
, NULL
,
3680 "failed to get own CERT.\n");
3683 ident
= eay_get_x509asn1subjectname(iph1
->cert
);
3686 case IDTYPE_ADDRESS
:
3688 * if the value of the id type was set by the configuration
3689 * file, then use it. otherwise the value is get from local
3690 * ip address by using ike negotiation.
3692 if (iph1
->rmconf
->idv
)
3693 ipid
= (struct sockaddr
*)iph1
->rmconf
->idv
->v
;
3703 /* use IP address */
3704 switch (ipid
->sa_family
) {
3706 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3707 l
= sizeof(struct in_addr
);
3708 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3712 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3713 l
= sizeof(struct in6_addr
);
3714 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3718 plog(LLV_ERROR
, LOCATION
, NULL
,
3719 "invalid address family.\n");
3722 id_b
.proto_id
= IPPROTO_UDP
;
3723 id_b
.port
= htons(PORT_ISAKMP
);
3726 plog(LLV_ERROR
, LOCATION
, NULL
,
3727 "failed to get ID buffer.\n");
3730 memcpy(ident
->v
, p
, ident
->l
);
3734 plog(LLV_ERROR
, LOCATION
, NULL
,
3735 "failed to get ID buffer.\n");
3739 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3741 plog(LLV_ERROR
, LOCATION
, NULL
,
3742 "failed to get ID buffer.\n");
3746 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3747 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3751 plog(LLV_DEBUG
, LOCATION
, NULL
,
3752 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3760 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3764 /* it's only called by cfparse.y. */
3766 set_identifier(vpp
, type
, value
)
3767 vchar_t
**vpp
, *value
;
3770 return set_identifier_qual(vpp
, type
, value
, IDQUAL_UNSPEC
);
3774 set_identifier_qual(vpp
, type
, value
, qual
)
3775 vchar_t
**vpp
, *value
;
3779 vchar_t
*new = NULL
;
3781 /* simply return if value is null. */
3783 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3784 plog(LLV_ERROR
, LOCATION
, NULL
,
3785 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3793 case IDTYPE_USERFQDN
:
3795 plog(LLV_ERROR
, LOCATION
, NULL
,
3796 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3799 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3800 new = vmalloc(value
->l
- 1);
3803 memcpy(new->v
, value
->v
, new->l
);
3807 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3808 * to use a file for backward compatibility sake.
3812 case IDQUAL_UNSPEC
: {
3817 fp
= fopen(value
->v
, "r");
3819 plog(LLV_ERROR
, LOCATION
, NULL
,
3820 "can not open %s\n", value
->v
);
3824 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3825 new = vrealloc(new, tlen
+ len
);
3830 memcpy(new->v
+ tlen
, b
, len
);
3837 new = vmalloc(value
->l
- 1);
3839 plog(LLV_ERROR
, LOCATION
, NULL
,
3840 "can not allocate memory");
3843 memcpy(new->v
, value
->v
, new->l
);
3847 plog(LLV_ERROR
, LOCATION
, NULL
,
3848 "unknown qualifier");
3853 case IDTYPE_ADDRESS
: {
3854 struct sockaddr
*sa
;
3856 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3860 sa
= str2saddr(value
->v
, NULL
);
3862 plog(LLV_ERROR
, LOCATION
, NULL
,
3863 "invalid ip address %s\n", value
->v
);
3867 new = vmalloc(sysdep_sa_len(sa
));
3872 memcpy(new->v
, sa
, new->l
);
3877 if (value
->v
[0] == '~')
3878 /* Hex-encoded ASN1 strings */
3879 new = eay_hex2asn1dn(value
->v
+ 1, - 1);
3881 /* DN encoded strings */
3882 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
3887 if (loglevel
>= LLV_DEBUG
) {
3890 unsigned char *ptr
= (unsigned char *) new->v
, *buf
;
3894 xn
= d2i_X509_NAME(NULL
, (void *)&ptr
, new->l
);
3895 bio
= BIO_new(BIO_s_mem());
3897 X509_NAME_print_ex(bio
, xn
, 0, 0);
3898 len
= BIO_get_mem_data(bio
, &ptr
);
3901 plog(LLV_DEBUG
, LOCATION
, NULL
, "Parsed DN: %s\n", ptr
);
3916 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3917 * NOT INCLUDING isakmp general header.
3918 * this function is for initiator. responder will get to copy from payload.
3919 * responder ID type is always address type.
3920 * see, RFC2407 4.6.2.1
3923 ipsecdoi_setid2(iph2
)
3924 struct ph2handle
*iph2
;
3926 struct secpolicy
*sp
;
3928 /* check there is phase 2 handler ? */
3929 sp
= getspbyspid(iph2
->spid
);
3931 plog(LLV_ERROR
, LOCATION
, NULL
,
3932 "no policy found for spid:%u.\n", iph2
->spid
);
3936 if (!ipsecdoi_transportmode(iph2
->proposal
))
3937 iph2
->id
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.src
,
3938 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
3939 else if (iph2
->sa_src
!= NULL
) {
3940 /* He have a specific hint indicating that the transport
3941 * mode SA will be negotiated using addresses that differ
3942 * with the one from the SA. We need to indicate that to
3943 * our peer by setting the SA address as ID.
3944 * This is typically the case for the bootstrapping of the
3945 * transport mode SA protecting BU/BA for MIPv6 traffic
3948 iph2
->id
= ipsecdoi_sockaddr2id(iph2
->sa_src
,
3949 IPSECDOI_PREFIX_HOST
,
3950 sp
->spidx
.ul_proto
);
3952 iph2
->id
= ipsecdoi_sockaddr2id(iph2
->src
, IPSECDOI_PREFIX_HOST
,
3953 sp
->spidx
.ul_proto
);
3955 if (iph2
->id
== NULL
) {
3956 plog(LLV_ERROR
, LOCATION
, NULL
,
3957 "failed to get ID for %s\n",
3958 spidx2str(&sp
->spidx
));
3961 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
3962 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
3965 if (!ipsecdoi_transportmode(iph2
->proposal
))
3966 iph2
->id_p
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.dst
,
3967 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
3968 else if (iph2
->sa_dst
!= NULL
) {
3969 /* See comment above for local side. */
3970 iph2
->id_p
= ipsecdoi_sockaddr2id(iph2
->sa_dst
,
3971 IPSECDOI_PREFIX_HOST
,
3972 sp
->spidx
.ul_proto
);
3974 iph2
->id_p
= ipsecdoi_sockaddr2id(iph2
->dst
, IPSECDOI_PREFIX_HOST
,
3975 sp
->spidx
.ul_proto
);
3977 if (iph2
->id_p
== NULL
) {
3978 plog(LLV_ERROR
, LOCATION
, NULL
,
3979 "failed to get ID for %s\n",
3980 spidx2str(&sp
->spidx
));
3984 plog(LLV_DEBUG
, LOCATION
, NULL
,
3985 "use remote ID type %s\n",
3986 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
3992 * set address type of ID.
3993 * NOT INCLUDING general header.
3996 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
3997 struct sockaddr
*saddr
;
4002 int type
, len1
, len2
;
4007 * Q. When type is SUBNET, is it allowed to be ::1/128.
4008 * A. Yes. (consensus at bake-off)
4010 switch (saddr
->sa_family
) {
4012 len1
= sizeof(struct in_addr
);
4013 if (prefixlen
>= (sizeof(struct in_addr
) << 3)) {
4014 type
= IPSECDOI_ID_IPV4_ADDR
;
4017 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
4018 len2
= sizeof(struct in_addr
);
4020 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
4021 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
4025 len1
= sizeof(struct in6_addr
);
4026 if (prefixlen
>= (sizeof(struct in6_addr
) << 3)) {
4027 type
= IPSECDOI_ID_IPV6_ADDR
;
4030 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
4031 len2
= sizeof(struct in6_addr
);
4033 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
4034 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
4038 plog(LLV_ERROR
, LOCATION
, NULL
,
4039 "invalid family: %d.\n", saddr
->sa_family
);
4044 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4046 plog(LLV_ERROR
, LOCATION
, NULL
,
4047 "failed to get ID buffer.\n");
4051 memset(new->v
, 0, new->l
);
4053 /* set the part of header. */
4054 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4056 /* set ul_proto and port */
4058 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4059 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4061 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4062 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4063 ((struct ipsecdoi_id_b
*)new->v
)->port
=
4064 port
== IPSEC_PORT_ANY
? 0 : port
;
4065 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
4071 u_char
*p
= (unsigned char *) new->v
+
4072 sizeof(struct ipsecdoi_id_b
) + len1
;
4073 u_int bits
= prefixlen
;
4081 *p
= ~((1 << (8 - bits
)) - 1);
4088 ipsecdoi_sockrange2id(laddr
, haddr
, ul_proto
)
4089 struct sockaddr
*laddr
, *haddr
;
4093 int type
, len1
, len2
;
4096 if (laddr
->sa_family
!= haddr
->sa_family
) {
4097 plog(LLV_ERROR
, LOCATION
, NULL
, "Address family mismatch\n");
4101 switch (laddr
->sa_family
) {
4103 type
= IPSECDOI_ID_IPV4_ADDR_RANGE
;
4104 len1
= sizeof(struct in_addr
);
4105 len2
= sizeof(struct in_addr
);
4109 type
= IPSECDOI_ID_IPV6_ADDR_RANGE
;
4110 len1
= sizeof(struct in6_addr
);
4111 len2
= sizeof(struct in6_addr
);
4115 plog(LLV_ERROR
, LOCATION
, NULL
,
4116 "invalid family: %d.\n", laddr
->sa_family
);
4121 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4123 plog(LLV_ERROR
, LOCATION
, NULL
,
4124 "failed to get ID buffer.\n");
4128 memset(new->v
, 0, new->l
);
4129 /* set the part of header. */
4130 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4132 /* set ul_proto and port */
4134 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4135 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4137 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4138 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4139 port
= ((struct sockaddr_in
*)(laddr
))->sin_port
;
4140 ((struct ipsecdoi_id_b
*)new->v
)->port
=
4141 port
== IPSEC_PORT_ANY
? 0 : port
;
4142 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
),
4143 (caddr_t
)&((struct sockaddr_in
*)(laddr
))->sin_addr
,
4145 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
,
4146 (caddr_t
)&((struct sockaddr_in
*)haddr
)->sin_addr
,
4153 * create sockaddr structure from ID payload (buf).
4154 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4155 * see, RFC2407 4.6.2.1
4158 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
4160 struct sockaddr
*saddr
;
4161 u_int8_t
*prefixlen
;
4162 u_int16_t
*ul_proto
;
4164 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)buf
->v
;
4168 * When a ID payload of subnet type with a IP address of full bit
4169 * masked, it has to be processed as host address.
4170 * e.g. below 2 type are same.
4171 * type = ipv6 subnet, data = 2001::1/128
4172 * type = ipv6 address, data = 2001::1
4174 switch (id_b
->type
) {
4175 case IPSECDOI_ID_IPV4_ADDR
:
4176 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4178 saddr
->sa_len
= sizeof(struct sockaddr_in
);
4180 saddr
->sa_family
= AF_INET
;
4181 ((struct sockaddr_in
*)saddr
)->sin_port
=
4184 : id_b
->port
); /* see sockaddr2id() */
4185 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
4186 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4189 case IPSECDOI_ID_IPV6_ADDR
:
4190 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4192 saddr
->sa_len
= sizeof(struct sockaddr_in6
);
4194 saddr
->sa_family
= AF_INET6
;
4195 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
4198 : id_b
->port
); /* see sockaddr2id() */
4199 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
4200 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4201 ((struct sockaddr_in6
*)saddr
)->sin6_scope_id
=
4202 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)saddr
)->sin6_addr
)
4203 ? ((struct sockaddr_in6
*)id_b
)->sin6_scope_id
4209 plog(LLV_ERROR
, LOCATION
, NULL
,
4210 "unsupported ID type %d\n", id_b
->type
);
4211 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
4214 /* get prefix length */
4215 switch (id_b
->type
) {
4216 case IPSECDOI_ID_IPV4_ADDR
:
4217 plen
= sizeof(struct in_addr
) << 3;
4220 case IPSECDOI_ID_IPV6_ADDR
:
4221 plen
= sizeof(struct in6_addr
) << 3;
4224 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4226 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4231 int alen
= sizeof(struct in_addr
);
4233 switch (id_b
->type
) {
4234 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4235 alen
= sizeof(struct in_addr
);
4238 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4239 alen
= sizeof(struct in6_addr
);
4246 return ISAKMP_INTERNAL_ERROR
;
4248 /* get subnet mask length */
4252 p
= (unsigned char *) buf
->v
4253 + sizeof(struct ipsecdoi_id_b
)
4256 for (; *p
== 0xff; p
++) {
4279 *ul_proto
= id_b
->proto_id
== 0
4281 : id_b
->proto_id
; /* see sockaddr2id() */
4287 * make printable string from ID payload except of general header.
4297 static char buf
[BUFLEN
];
4298 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)id
->v
;
4299 union sockaddr_any saddr
;
4302 switch (id_b
->type
) {
4303 case IPSECDOI_ID_IPV4_ADDR
:
4304 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4305 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4308 saddr
.sa
.sa_len
= sizeof(struct sockaddr_in
);
4310 saddr
.sa
.sa_family
= AF_INET
;
4311 saddr
.sin
.sin_port
= IPSEC_PORT_ANY
;
4312 memcpy(&saddr
.sin
.sin_addr
,
4313 id
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4316 case IPSECDOI_ID_IPV6_ADDR
:
4317 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4318 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4321 saddr
.sa
.sa_len
= sizeof(struct sockaddr_in6
);
4323 saddr
.sa
.sa_family
= AF_INET6
;
4324 saddr
.sin6
.sin6_port
= IPSEC_PORT_ANY
;
4325 memcpy(&saddr
.sin6
.sin6_addr
,
4326 id
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4327 saddr
.sin6
.sin6_scope_id
=
4328 (IN6_IS_ADDR_LINKLOCAL(&saddr
.sin6
.sin6_addr
)
4329 ? ((struct sockaddr_in6
*)id_b
)->sin6_scope_id
4335 switch (id_b
->type
) {
4336 case IPSECDOI_ID_IPV4_ADDR
:
4338 case IPSECDOI_ID_IPV6_ADDR
:
4340 len
= snprintf( buf
, BUFLEN
, "%s", saddrwop2str(&saddr
.sa
));
4343 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4345 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4350 int alen
= sizeof(struct in_addr
);
4352 switch (id_b
->type
) {
4353 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4354 alen
= sizeof(struct in_addr
);
4357 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4358 alen
= sizeof(struct in6_addr
);
4369 /* get subnet mask length */
4373 p
= (unsigned char *) id
->v
4374 + sizeof(struct ipsecdoi_id_b
)
4377 for (; *p
== 0xff; p
++) {
4396 len
= snprintf( buf
, BUFLEN
, "%s/%i", saddrwop2str(&saddr
.sa
), plen
);
4400 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4402 len
= snprintf( buf
, BUFLEN
, "%s-", saddrwop2str(&saddr
.sa
));
4405 saddr
.sa
.sa_len
= sizeof(struct sockaddr_in
);
4407 saddr
.sa
.sa_family
= AF_INET
;
4408 saddr
.sin
.sin_port
= IPSEC_PORT_ANY
;
4409 memcpy(&saddr
.sin
.sin_addr
,
4410 id
->v
+ sizeof(*id_b
) + sizeof(struct in_addr
),
4411 sizeof(struct in_addr
));
4413 len
+= snprintf(buf
+ len
, BUFLEN
- len
, "%s", saddrwop2str(&saddr
.sa
));
4417 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4418 len
= snprintf( buf
, BUFLEN
, "%s-", saddrwop2str(&saddr
.sa
));
4421 saddr
.sa
.sa_len
= sizeof(struct sockaddr_in6
);
4423 saddr
.sa
.sa_family
= AF_INET6
;
4424 saddr
.sin6
.sin6_port
= IPSEC_PORT_ANY
;
4425 memcpy(&saddr
.sin6
.sin6_addr
,
4426 id
->v
+ sizeof(*id_b
) + sizeof(struct in6_addr
),
4427 sizeof(struct in6_addr
));
4428 saddr
.sin6
.sin6_scope_id
=
4429 (IN6_IS_ADDR_LINKLOCAL(&saddr
.sin6
.sin6_addr
)
4430 ? ((struct sockaddr_in6
*)id_b
)->sin6_scope_id
4433 len
+= snprintf(buf
+ len
, BUFLEN
- len
, "%s", saddrwop2str(&saddr
.sa
));
4437 case IPSECDOI_ID_FQDN
:
4438 case IPSECDOI_ID_USER_FQDN
:
4439 len
= id
->l
- sizeof(*id_b
);
4442 memcpy(buf
, id
->v
+ sizeof(*id_b
), len
);
4445 case IPSECDOI_ID_DER_ASN1_DN
:
4446 case IPSECDOI_ID_DER_ASN1_GN
:
4448 X509_NAME
*xn
= NULL
;
4450 dat
= id
->v
+ sizeof(*id_b
);
4451 len
= id
->l
- sizeof(*id_b
);
4453 if (d2i_X509_NAME(&xn
, (void*) &dat
, len
) != NULL
) {
4454 BIO
*bio
= BIO_new(BIO_s_mem());
4455 X509_NAME_print_ex(bio
, xn
, 0, 0);
4456 len
= BIO_get_mem_data(bio
, &dat
);
4459 memcpy(buf
,dat
,len
);
4463 plog(LLV_ERROR
, LOCATION
, NULL
,
4464 "unable to extract asn1dn from id\n");
4466 len
= sprintf(buf
, "<ASN1-DN>");
4472 /* currently unhandled id types */
4473 case IPSECDOI_ID_KEY_ID
:
4474 len
= sprintf( buf
, "<KEY-ID>");
4478 plog(LLV_ERROR
, LOCATION
, NULL
,
4479 "unknown ID type %d\n", id_b
->type
);
4483 len
= sprintf( buf
, "<?>");
4485 ret
= racoon_malloc(len
+1);
4487 memcpy(ret
,buf
,len
);
4495 * set IPsec data attributes into a proposal.
4496 * NOTE: MUST called per a transform.
4499 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4500 struct isakmp_pl_t
*t
;
4505 struct isakmp_data
*d
, *prev
;
4511 tr
->trns_no
= t
->t_no
;
4512 tr
->trns_id
= t
->t_id
;
4514 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4515 prev
= (struct isakmp_data
*)NULL
;
4516 d
= (struct isakmp_data
*)(t
+ 1);
4519 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4520 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4522 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4526 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4527 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4529 plog(LLV_DEBUG
, LOCATION
, NULL
,
4530 "type=%s, flag=0x%04x, lorv=%s\n",
4531 s_ipsecdoi_attr(type
), flag
,
4532 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4535 case IPSECDOI_ATTR_SA_LD_TYPE
:
4537 int type
= ntohs(d
->lorv
);
4539 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4540 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4544 plog(LLV_WARNING
, LOCATION
, NULL
,
4545 "invalid life duration type. "
4547 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4552 case IPSECDOI_ATTR_SA_LD
:
4554 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4555 IPSECDOI_ATTR_SA_LD_TYPE
) {
4556 plog(LLV_ERROR
, LOCATION
, NULL
,
4557 "life duration must follow ltype\n");
4563 vchar_t
*ld_buf
= NULL
;
4566 /* i.e. ISAKMP_GEN_TV */
4567 ld_buf
= vmalloc(sizeof(d
->lorv
));
4568 if (ld_buf
== NULL
) {
4569 plog(LLV_ERROR
, LOCATION
, NULL
,
4570 "failed to get LD buffer.\n");
4573 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4575 int len
= ntohs(d
->lorv
);
4576 /* i.e. ISAKMP_GEN_TLV */
4577 ld_buf
= vmalloc(len
);
4578 if (ld_buf
== NULL
) {
4579 plog(LLV_ERROR
, LOCATION
, NULL
,
4580 "failed to get LD buffer.\n");
4583 memcpy(ld_buf
->v
, d
+ 1, len
);
4586 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4587 t
= ipsecdoi_set_ld(ld_buf
);
4590 plog(LLV_ERROR
, LOCATION
, NULL
,
4591 "invalid life duration.\n");
4594 /* lifetime must be equal in a proposal. */
4595 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4597 else if (pp
->lifetime
!= t
) {
4598 plog(LLV_ERROR
, LOCATION
, NULL
,
4599 "lifetime mismatched "
4601 "prev:%ld curr:%u.\n",
4602 (long)pp
->lifetime
, t
);
4606 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4607 t
= ipsecdoi_set_ld(ld_buf
);
4610 plog(LLV_ERROR
, LOCATION
, NULL
,
4611 "invalid life duration.\n");
4614 /* lifebyte must be equal in a proposal. */
4615 if (pp
->lifebyte
== 0)
4617 else if (pp
->lifebyte
!= t
) {
4618 plog(LLV_ERROR
, LOCATION
, NULL
,
4619 "lifebyte mismatched "
4621 "prev:%d curr:%u.\n",
4628 plog(LLV_ERROR
, LOCATION
, NULL
,
4629 "invalid life type: %d\n", life_t
);
4635 case IPSECDOI_ATTR_GRP_DESC
:
4637 * RFC2407: 4.5 IPSEC Security Association Attributes
4638 * Specifies the Oakley Group to be used in a PFS QM
4639 * negotiation. For a list of supported values, see
4640 * Appendix A of [IKE].
4642 if (pp
->pfs_group
== 0)
4643 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4644 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4645 plog(LLV_ERROR
, LOCATION
, NULL
,
4646 "pfs_group mismatched "
4647 "in a proposal.\n");
4652 case IPSECDOI_ATTR_ENC_MODE
:
4654 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4655 plog(LLV_ERROR
, LOCATION
, NULL
,
4656 "multiple encmode exist "
4657 "in a transform.\n");
4660 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4663 case IPSECDOI_ATTR_AUTH
:
4664 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4665 plog(LLV_ERROR
, LOCATION
, NULL
,
4666 "multiple authtype exist "
4667 "in a transform.\n");
4670 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4673 case IPSECDOI_ATTR_KEY_LENGTH
:
4674 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4675 plog(LLV_ERROR
, LOCATION
, NULL
,
4676 "key length defined but not ESP");
4679 tr
->encklen
= ntohs(d
->lorv
);
4682 case IPSECDOI_ATTR_SECCTX
:
4684 int len
= ntohs(d
->lorv
);
4685 memcpy(&pp
->sctx
, d
+ 1, len
);
4686 pp
->sctx
.ctx_strlen
= ntohs(pp
->sctx
.ctx_strlen
);
4689 #endif /* HAVE_SECCTX */
4690 case IPSECDOI_ATTR_KEY_ROUNDS
:
4691 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4692 case IPSECDOI_ATTR_COMP_PRIVALG
:
4700 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4702 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4703 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4713 ipsecdoi_authalg2trnsid(alg
)
4717 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4718 return IPSECDOI_AH_MD5
;
4719 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4720 return IPSECDOI_AH_SHA
;
4721 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4722 return IPSECDOI_AH_SHA256
;
4723 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4724 return IPSECDOI_AH_SHA384
;
4725 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4726 return IPSECDOI_AH_SHA512
;
4727 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4728 return IPSECDOI_AH_DES
;
4729 case IPSECDOI_ATTR_AUTH_KPDK
:
4730 return IPSECDOI_AH_MD5
; /* XXX */
4732 plog(LLV_ERROR
, LOCATION
, NULL
,
4733 "invalid authentication algorithm:%d\n", alg
);
4738 static int rm_idtype2doi
[] = {
4739 255, /* IDTYPE_UNDEFINED, 0 */
4740 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4741 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4742 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4743 255, /* IDTYPE_ADDRESS, 4
4744 * it expands into 4 types by another function. */
4745 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4749 * convert idtype to DOI value.
4757 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4758 return rm_idtype2doi
[idtype
];
4767 case IPSECDOI_ID_FQDN
:
4768 return(IDTYPE_FQDN
);
4769 case IPSECDOI_ID_USER_FQDN
:
4770 return(IDTYPE_USERFQDN
);
4771 case IPSECDOI_ID_KEY_ID
:
4772 return(IDTYPE_KEYID
);
4773 case IPSECDOI_ID_DER_ASN1_DN
:
4774 return(IDTYPE_ASN1DN
);
4775 case IPSECDOI_ID_IPV4_ADDR
:
4776 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4777 case IPSECDOI_ID_IPV6_ADDR
:
4778 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4779 return(IDTYPE_ADDRESS
);
4781 plog(LLV_WARNING
, LOCATION
, NULL
,
4782 "Inproper idtype:%s in this function.\n",
4783 s_ipsecdoi_ident(doi
));
4784 return(IDTYPE_ADDRESS
); /* XXX */