1 /* $Id: ipsec_doi.c,v 1.26.2.16 2006/02/02 14:37:17 vanhu Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
38 #include <netinet/in.h>
40 #ifndef HAVE_NETINET6_IPSEC
41 #include <netinet/ipsec.h>
43 #include <netinet6/ipsec.h>
51 #if TIME_WITH_SYS_TIME
52 # include <sys/time.h>
56 # include <sys/time.h>
68 #include "cfparse_proto.h"
69 #include "isakmp_var.h"
71 #include "ipsec_doi.h"
73 #include "remoteconf.h"
74 #include "localconf.h"
78 #include "algorithm.h"
81 #include "crypto_openssl.h"
82 #include "crypto_cssm.h"
87 #include "nattraversal.h"
91 static int switch_authmethod(int);
94 int verbose_proposal_check
= 1;
96 static vchar_t
*get_ph1approval (phase1_handle_t
*, struct prop_pair
**);
97 void print_ph1mismatched (struct prop_pair
*, struct isakmpsa
*);
98 static int t2isakmpsa (struct isakmp_pl_t
*, struct isakmpsa
*);
99 static int cmp_aproppair_i (struct prop_pair
*, struct prop_pair
*);
100 static struct prop_pair
*get_ph2approval (phase2_handle_t
*,
101 struct prop_pair
**);
102 static struct prop_pair
*get_ph2approvalx (phase2_handle_t
*,
104 static void free_proppair0 (struct prop_pair
*);
106 static int get_transform (struct isakmp_pl_p
*, struct prop_pair
**, int *);
107 static u_int32_t
ipsecdoi_set_ld (vchar_t
*);
109 static int check_doi (u_int32_t
);
110 static int check_situation (u_int32_t
);
112 static int check_prot_main (int);
113 static int check_prot_quick (int);
114 static int (*check_protocol
[]) (int) = {
115 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
116 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
117 NULL
, /* IPSECDOI_TYPE_IKEV2_PH1 */
118 NULL
, /* IPSECDOI_TYPE_IKEV2_PH2 */
121 int check_spi_size (int, int);
123 static int check_trns_isakmp (int);
124 static int check_trns_ah (int);
125 static int check_trns_esp (int);
126 static int check_trns_ipcomp (int);
127 static int (*check_transform
[]) (int) = {
129 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
130 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
131 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
132 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
135 static int check_attr_isakmp (struct isakmp_pl_t
*);
136 static int check_attr_ah (struct isakmp_pl_t
*);
137 static int check_attr_esp (struct isakmp_pl_t
*);
138 static int check_attr_ipsec (int, struct isakmp_pl_t
*);
139 static int check_attr_ipcomp (struct isakmp_pl_t
*);
140 static int (*check_attributes
[]) (struct isakmp_pl_t
*) = {
142 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
143 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
144 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
145 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
148 int setph1prop (phase1_handle_t
*, caddr_t
);
149 static int setph1trns (struct isakmpsa
*, caddr_t
);
150 static int setph1attr (struct isakmpsa
*, caddr_t
);
151 static vchar_t
*setph2proposal0 (const phase2_handle_t
*,
152 const struct saprop
*, const struct saproto
*);
154 static vchar_t
*getidval (int, vchar_t
*);
159 * check phase 1 SA payload.
160 * make new SA payload to be replyed not including general header.
161 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
163 * positive: the pointer to new buffer of SA payload.
164 * network byte order.
165 * NULL : error occurd.
168 ipsecdoi_checkph1proposal(sa
, iph1
)
170 phase1_handle_t
*iph1
;
172 vchar_t
*newsa
; /* new SA payload approved. */
173 struct prop_pair
**pair
;
175 /* get proposal pair */
176 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
180 /* check and get one SA for use */
181 newsa
= get_ph1approval(iph1
, pair
);
188 iph1
->sa_ret
= newsa
;
194 * acceptable check for remote configuration.
195 * return a new SA payload to be reply to peer.
198 get_ph1approval(iph1
, pair
)
199 phase1_handle_t
*iph1
;
200 struct prop_pair
**pair
;
203 struct isakmpsa
*sa
, tsa
;
204 struct prop_pair
*s
, *p
;
208 if (iph1
->approval
) {
209 delisakmpsa(iph1
->approval
);
210 iph1
->approval
= NULL
;
213 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
216 for (s
= pair
[i
]; s
; s
= s
->next
) {
218 sizeof(struct isakmp_pl_p
) + s
->prop
->spi_size
;
220 /* compare proposal and select one */
221 for (p
= s
; p
; p
= p
->tnext
) {
222 if ((sa
= get_ph1approvalx(p
,
223 iph1
->rmconf
->proposal
, &tsa
,
224 iph1
->rmconf
->pcheck_level
)) != NULL
)
231 * if there is no suitable proposal, racoon complains about all of
232 * mismatched items in those proposal.
234 if (verbose_proposal_check
) {
235 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
238 for (s
= pair
[i
]; s
; s
= s
->next
) {
239 prophlen
= sizeof(struct isakmp_pl_p
)
241 for (p
= s
; p
; p
= p
->tnext
) {
242 print_ph1mismatched(p
,
243 iph1
->rmconf
->proposal
);
248 plog(ASL_LEVEL_ERR
, "no suitable proposal found.\n");
253 plog(ASL_LEVEL_DEBUG
, "an acceptable proposal found.\n");
255 /* check DH group settings */
257 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
261 plog(ASL_LEVEL_WARNING
,
262 "invalid DH parameter found, use default.\n");
263 oakley_dhgrp_free(sa
->dhgrp
);
267 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
276 plog(ASL_LEVEL_DEBUG
, "agreed on %s auth.\n",
277 s_oakley_attr_method(iph1
->approval
->authmethod
));
280 newsa
= get_sabyproppair(p
, iph1
);
282 delisakmpsa(iph1
->approval
);
283 iph1
->approval
= NULL
;
290 * compare peer's single proposal and all of my proposal.
291 * and select one if suiatable.
292 * p : one of peer's proposal.
293 * proposal: my proposals.
296 get_ph1approvalx(p
, proposal
, sap
, check_level
)
298 struct isakmpsa
*proposal
, *sap
;
301 struct isakmp_pl_p
*prop
= p
->prop
;
302 struct isakmp_pl_t
*trns
= p
->trns
;
303 struct isakmpsa sa
, *s
, *tsap
;
307 plog(ASL_LEVEL_DEBUG
,
308 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
309 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
310 prop
->spi_size
, prop
->num_t
);
312 plog(ASL_LEVEL_DEBUG
,
313 "trns#=%d, trns-id=%s\n",
315 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
317 tsap
= sap
!= NULL
? sap
: &sa
;
319 memset(tsap
, 0, sizeof(*tsap
));
320 if (t2isakmpsa(trns
, tsap
) < 0)
322 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
324 authmethod
= switch_authmethod(s
->authmethod
);
325 tsap_authmethod
= switch_authmethod(tsap
->authmethod
);
327 authmethod
= s
->authmethod
;
328 tsap_authmethod
= tsap
->authmethod
;
330 plog(ASL_LEVEL_DEBUG
, "Compared: DB:Peer\n");
331 plog(ASL_LEVEL_DEBUG
, "(version = %d:%d)\n",
332 s
->version
, tsap
->version
);
333 plog(ASL_LEVEL_DEBUG
, "(lifetime = %ld:%ld)\n",
334 (long)s
->lifetime
, (long)tsap
->lifetime
);
335 plog(ASL_LEVEL_DEBUG
, "(lifebyte = %zu:%zu)\n",
336 s
->lifebyte
, tsap
->lifebyte
);
337 plog(ASL_LEVEL_DEBUG
, "enctype = %s:%s\n",
338 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
340 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
342 plog(ASL_LEVEL_DEBUG
, "(encklen = %d:%d)\n",
343 s
->encklen
, tsap
->encklen
);
344 plog(ASL_LEVEL_DEBUG
, "hashtype = %s:%s\n",
345 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
347 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
349 plog(ASL_LEVEL_DEBUG
, "authmethod = %s:%s\n",
350 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
352 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
354 plog(ASL_LEVEL_DEBUG
, "dh_group = %s:%s\n",
355 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
357 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
360 /* XXX to be considered ? */
361 if (tsap
->lifebyte
> s
->lifebyte
) ;
364 * if responder side and peer's key length in proposal
365 * is bigger than mine, it might be accepted.
367 if(tsap
->enctype
== s
->enctype
&&
368 (tsap
->authmethod
== authmethod
|| tsap_authmethod
== authmethod
) &&
369 tsap
->hashtype
== s
->hashtype
&&
370 tsap
->dh_group
== s
->dh_group
&&
371 tsap
->encklen
== s
->encklen
&&
372 tsap
->version
== s
->version
) {
373 switch(check_level
) {
374 case PROP_CHECK_OBEY
:
378 case PROP_CHECK_STRICT
:
379 if ((tsap
->lifetime
> s
->lifetime
) ||
380 (tsap
->lifebyte
> s
->lifebyte
))
385 case PROP_CHECK_CLAIM
:
386 if (tsap
->lifetime
< s
->lifetime
)
387 s
->lifetime
= tsap
->lifetime
;
388 if (tsap
->lifebyte
< s
->lifebyte
)
389 s
->lifebyte
= tsap
->lifebyte
;
393 case PROP_CHECK_EXACT
:
394 if ((tsap
->lifetime
!= s
->lifetime
) ||
395 (tsap
->lifebyte
!= s
->lifebyte
))
402 "Unexpected proposal_check value\n");
410 if (tsap
->dhgrp
!= NULL
){
411 oakley_dhgrp_free(tsap
->dhgrp
);
415 if ((s
= dupisakmpsa(s
)) != NULL
) {
416 switch(check_level
) {
417 case PROP_CHECK_OBEY
:
418 s
->lifetime
= tsap
->lifetime
;
419 s
->lifebyte
= tsap
->lifebyte
;
422 case PROP_CHECK_STRICT
:
423 s
->lifetime
= tsap
->lifetime
;
424 s
->lifebyte
= tsap
->lifebyte
;
427 case PROP_CHECK_CLAIM
:
428 if (tsap
->lifetime
< s
->lifetime
)
429 s
->lifetime
= tsap
->lifetime
;
430 if (tsap
->lifebyte
< s
->lifebyte
)
431 s
->lifebyte
= tsap
->lifebyte
;
437 // hack to get around cisco rekeys
438 if (tsap
->authmethod
!= authmethod
&& tsap_authmethod
== authmethod
) {
439 s
->authmethod
= tsap
->authmethod
;
446 * print all of items in peer's proposal which are mismatched to my proposal.
447 * p : one of peer's proposal.
448 * proposal: my proposals.
451 print_ph1mismatched(p
, proposal
)
453 struct isakmpsa
*proposal
;
455 struct isakmpsa sa
, *s
;
457 memset(&sa
, 0, sizeof(sa
));
458 if (t2isakmpsa(p
->trns
, &sa
) < 0)
460 for (s
= proposal
; s
; s
= s
->next
) {
461 if (sa
.enctype
!= s
->enctype
) {
464 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
466 s
->prop_no
, s
->trns_no
,
467 p
->prop
->p_no
, p
->trns
->t_no
,
468 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
470 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
473 if (sa
.authmethod
!= s
->authmethod
) {
475 "rejected authmethod: "
476 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
478 s
->prop_no
, s
->trns_no
,
479 p
->prop
->p_no
, p
->trns
->t_no
,
480 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
482 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
485 if (sa
.hashtype
!= s
->hashtype
) {
487 "rejected hashtype: "
488 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
490 s
->prop_no
, s
->trns_no
,
491 p
->prop
->p_no
, p
->trns
->t_no
,
492 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
494 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
497 if (sa
.prf
!= s
->prf
||
498 sa
.prfklen
!= s
->prfklen
) {
501 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
503 s
->prop_no
, s
->trns_no
,
504 p
->prop
->p_no
, p
->trns
->t_no
,
505 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
508 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
512 if (sa
.dh_group
!= s
->dh_group
) {
514 "rejected dh_group: "
515 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
517 s
->prop_no
, s
->trns_no
,
518 p
->prop
->p_no
, p
->trns
->t_no
,
519 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
521 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
526 if (sa
.dhgrp
!= NULL
){
527 oakley_dhgrp_free(sa
.dhgrp
);
533 * get ISAKMP data attributes
537 struct isakmp_pl_t
*trns
;
540 struct isakmp_data
*d
, *prev
;
549 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
550 prev
= (struct isakmp_data
*)NULL
;
551 d
= (struct isakmp_data
*)(trns
+ 1);
554 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
555 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
557 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
563 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
564 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
566 plog(ASL_LEVEL_DEBUG
,
567 "type=%s, flag=0x%04x, lorv=%s\n",
568 s_oakley_attr(type
), flag
,
569 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
571 /* get variable-sized item */
573 case OAKLEY_ATTR_GRP_PI
:
574 case OAKLEY_ATTR_GRP_GEN_ONE
:
575 case OAKLEY_ATTR_GRP_GEN_TWO
:
576 case OAKLEY_ATTR_GRP_CURVE_A
:
577 case OAKLEY_ATTR_GRP_CURVE_B
:
578 case OAKLEY_ATTR_SA_LD
:
579 case OAKLEY_ATTR_GRP_ORDER
:
582 p
= (u_char
*)&d
->lorv
;
584 len
= ntohs(d
->lorv
);
587 "invalid ISAKMP-SA attr, attr-len %d, overall-len %d\n",
591 p
= (u_char
*)(d
+ 1);
596 memcpy(val
->v
, p
, len
);
604 case OAKLEY_ATTR_ENC_ALG
:
605 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
608 case OAKLEY_ATTR_HASH_ALG
:
609 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
612 case OAKLEY_ATTR_AUTH_METHOD
:
613 sa
->authmethod
= ntohs(d
->lorv
);
616 case OAKLEY_ATTR_GRP_DESC
:
617 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
620 case OAKLEY_ATTR_GRP_TYPE
:
622 int type
= (int)ntohs(d
->lorv
);
623 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
624 sa
->dhgrp
->type
= type
;
629 case OAKLEY_ATTR_GRP_PI
:
630 sa
->dhgrp
->prime
= val
;
633 case OAKLEY_ATTR_GRP_GEN_ONE
:
636 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
638 int len
= ntohs(d
->lorv
);
642 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
643 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
647 case OAKLEY_ATTR_GRP_GEN_TWO
:
650 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
652 int len
= ntohs(d
->lorv
);
656 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
657 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
661 case OAKLEY_ATTR_GRP_CURVE_A
:
662 sa
->dhgrp
->curve_a
= val
;
665 case OAKLEY_ATTR_GRP_CURVE_B
:
666 sa
->dhgrp
->curve_b
= val
;
669 case OAKLEY_ATTR_SA_LD_TYPE
:
671 int type
= (int)ntohs(d
->lorv
);
673 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
674 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
678 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
683 case OAKLEY_ATTR_SA_LD
:
685 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
686 OAKLEY_ATTR_SA_LD_TYPE
) {
688 "life duration must follow ltype\n");
693 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
694 sa
->lifetime
= ipsecdoi_set_ld(val
);
696 if (sa
->lifetime
== 0) {
698 "invalid life duration.\n");
702 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
703 sa
->lifebyte
= ipsecdoi_set_ld(val
);
705 if (sa
->lifebyte
== 0) {
707 "invalid life duration.\n");
714 "invalid life type: %d\n", life_t
);
719 case OAKLEY_ATTR_KEY_LEN
:
721 int len
= ntohs(d
->lorv
);
724 "keylen %d: not multiple of 8\n",
728 sa
->encklen
= (u_int16_t
)len
;
732 case OAKLEY_ATTR_PRF
:
733 case OAKLEY_ATTR_FIELD_SIZE
:
737 case OAKLEY_ATTR_GRP_ORDER
:
738 sa
->dhgrp
->order
= val
;
748 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
750 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
751 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
755 /* key length must not be specified on some algorithms */
757 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
758 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
760 "keylen must not be specified "
761 "for encryption algorithm %d\n",
774 * check phase 2 SA payload and select single proposal.
775 * make new SA payload to be replyed not including general header.
776 * This function is called by responder only.
782 ipsecdoi_selectph2proposal(iph2
)
783 phase2_handle_t
*iph2
;
785 struct prop_pair
**pair
;
786 struct prop_pair
*ret
;
788 /* get proposal pair */
789 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
793 /* check and select a proposal. */
794 ret
= get_ph2approval(iph2
, pair
);
799 /* make a SA to be replayed. */
800 /* SPI must be updated later. */
801 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
803 if (iph2
->sa_ret
== NULL
)
810 * check phase 2 SA payload returned from responder.
811 * This function is called by initiator only.
817 ipsecdoi_checkph2proposal(iph2
)
818 phase2_handle_t
*iph2
;
820 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
824 vchar_t
*sa_ret
= NULL
;
826 /* get proposal pair of SA sent. */
827 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
830 "failed to get prop pair.\n");
834 /* XXX should check the number of transform */
836 /* get proposal pair of SA replayed */
837 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
840 "failed to get prop pair.\n");
844 /* check proposal is only one ? */
847 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
855 "no proposal received.\n");
860 "some proposals received.\n");
864 if (spair
[n
] == NULL
) {
865 plog(ASL_LEVEL_WARNING
,
866 "invalid proposal number:%d received.\n", i
);
870 if (rpair
[n
]->tnext
!= NULL
) {
872 "multi transforms replyed.\n");
876 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
878 "proposal mismathed.\n");
883 * check and select a proposal.
884 * ensure that there is no modification of the proposal by
887 p
= get_ph2approval(iph2
, rpair
);
891 /* make a SA to be replayed. */
892 sa_ret
= iph2
->sa_ret
;
893 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
895 if (iph2
->sa_ret
== NULL
)
902 free_proppair(rpair
);
904 free_proppair(spair
);
912 * compare two prop_pair which is assumed to have same proposal number.
913 * the case of bundle or single SA, NOT multi transforms.
914 * a: a proposal that is multi protocols and single transform, usually replyed.
915 * b: a proposal that is multi protocols and multi transform, usually sent.
916 * NOTE: this function is for initiator.
920 * XXX cannot understand the comment!
923 cmp_aproppair_i(a
, b
)
924 struct prop_pair
*a
, *b
;
926 struct prop_pair
*p
, *q
, *r
;
929 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
930 for (r
= q
; r
; r
= r
->tnext
) {
932 if (p
->trns
->t_no
== r
->trns
->t_no
)
936 /* no suitable transform found */
938 "no suitable transform found.\n");
943 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
944 plog(ASL_LEVEL_WARNING
,
945 "proposal #%d mismatched, "
947 r
->prop
->p_no
, p
->prop
->p_no
);
951 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
953 "proto_id mismathed: my:%d peer:%d\n",
954 r
->prop
->proto_id
, p
->prop
->proto_id
);
958 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
960 "invalid spi size: %d.\n",
965 /* check #of transforms */
966 if (p
->prop
->num_t
!= 1) {
967 plog(ASL_LEVEL_WARNING
,
968 "#of transform is %d, "
969 "but expected 1.\n", p
->prop
->num_t
);
973 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
974 plog(ASL_LEVEL_WARNING
,
975 "transform number has been modified.\n");
978 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
979 plog(ASL_LEVEL_WARNING
,
980 "reserved field should be zero.\n");
984 /* compare attribute */
985 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
986 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
987 plog(ASL_LEVEL_WARNING
,
988 "attribute has been modified.\n");
992 if ((p
&& !q
) || (!p
&& q
)) {
993 /* # of protocols mismatched */
995 "#of protocols mismatched.\n");
1003 * acceptable check for policy configuration.
1004 * return a new SA payload to be reply to peer.
1006 static struct prop_pair
*
1007 get_ph2approval(iph2
, pair
)
1008 phase2_handle_t
*iph2
;
1009 struct prop_pair
**pair
;
1011 struct prop_pair
*ret
;
1014 iph2
->approval
= NULL
;
1016 plog(ASL_LEVEL_DEBUG
,
1017 "begin compare proposals.\n");
1019 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1020 if (pair
[i
] == NULL
)
1022 plog(ASL_LEVEL_DEBUG
,
1023 "pair[%d]: %p\n", i
, pair
[i
]);
1024 print_proppair(ASL_LEVEL_DEBUG
, pair
[i
]);;
1026 /* compare proposal and select one */
1027 ret
= get_ph2approvalx(iph2
, pair
[i
]);
1034 plog(ASL_LEVEL_ERR
, "no suitable policy found.\n");
1040 * compare my proposal and peers just one proposal.
1043 static struct prop_pair
*
1044 get_ph2approvalx(iph2
, pp
)
1045 phase2_handle_t
*iph2
;
1046 struct prop_pair
*pp
;
1048 struct prop_pair
*ret
= NULL
;
1049 struct saprop
*pr0
, *pr
= NULL
;
1050 struct saprop
*q1
, *q2
;
1052 pr0
= aproppair2saprop(pp
);
1056 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1057 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1058 plog(ASL_LEVEL_DEBUG
,
1059 "peer's single bundle:\n");
1060 printsaprop0(ASL_LEVEL_DEBUG
, q1
);
1061 plog(ASL_LEVEL_DEBUG
,
1062 "my single bundle:\n");
1063 printsaprop0(ASL_LEVEL_DEBUG
, q2
);
1065 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1073 /* no proposal matching */
1086 plog(ASL_LEVEL_DEBUG
, "matched\n");
1087 iph2
->approval
= pr
;
1091 struct prop_pair
*p
, *x
;
1092 struct prop_pair
*n
= NULL
;
1096 for (p
= pp
; p
; p
= p
->next
) {
1098 * find a proposal with matching proto_id.
1099 * we have analyzed validity already, in cmpsaprop_alloc().
1101 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1102 if (sp
->proto_id
== p
->prop
->proto_id
)
1110 for (x
= p
; x
; x
= x
->tnext
)
1111 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1116 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1119 "failed to get buffer.\n");
1126 /* need to preserve the order */
1127 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1129 if (x
&& x
->prop
== n
->prop
) {
1130 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1141 /* #of transforms should be updated ? */
1150 struct prop_pair
**pair
;
1154 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1155 free_proppair0(pair
[i
]);
1162 free_proppair0(pair
)
1163 struct prop_pair
*pair
;
1165 struct prop_pair
*p
, *q
, *r
, *s
;
1181 * get proposal pairs from SA payload.
1182 * tiny check for proposal payload.
1185 get_proppair(sa
, mode
)
1189 struct prop_pair
**pair
= NULL
;
1190 int num_p
= 0; /* number of proposal for use */
1195 //plogdump(ASL_LEVEL_DEBUG, sa->v, sa->l, "total SA len=%zu\n", sa->l);
1197 if (mode
== IPSECDOI_TYPE_PH1
|| mode
== IPSECDOI_TYPE_PH2
) {
1199 struct ipsecdoi_sa_b
*sab
= ALIGNED_CAST(__typeof__(sab
))sa
->v
;
1202 /* check SA payload size */
1203 if (sa
->l
< sizeof(*sab
)) {
1205 "Invalid SA length = %zu.\n", sa
->l
);
1210 if (check_doi(ntohl(sab
->doi
)) < 0)
1213 /* check SITUATION */
1214 if (check_situation(ntohl(sab
->sit
)) < 0)
1217 bp
= (caddr_t
)(sab
+ 1);
1218 tlen
= sa
->l
- sizeof(*sab
);
1220 bp
= (__typeof__(bp
))sa
->v
;
1224 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1227 "failed to get buffer.\n");
1232 struct isakmp_pl_p
*prop
;
1234 vchar_t
*pbuf
= NULL
;
1235 struct isakmp_parse_t
*pa
;
1237 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1241 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1242 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1244 /* check the value of next payload */
1245 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1247 "Invalid payload type=%u\n", pa
->type
);
1252 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1255 plog(ASL_LEVEL_DEBUG
,
1256 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1260 "invalid proposal with length %d\n", proplen
);
1265 /* check Protocol ID */
1266 if (!check_protocol
[mode
]) {
1268 "unsupported mode %d\n", mode
);
1272 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1275 /* check SPI length when IKE. */
1276 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1280 if (get_transform(prop
, pair
, &num_p
) < 0) {
1291 struct prop_pair
*p
, *q
;
1293 /* check for proposals with no transforms */
1294 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1298 plog(ASL_LEVEL_DEBUG
, "pair %d:\n", i
);
1299 print_proppair(ASL_LEVEL_DEBUG
, pair
[i
]);
1301 notrans
= nprop
= 0;
1302 for (p
= pair
[i
]; p
; p
= p
->next
) {
1303 if (p
->trns
== NULL
) {
1307 for (q
= p
; q
; q
= q
->tnext
)
1313 * XXX at this moment, we cannot accept proposal group
1314 * with multiple proposals. this should be fixed.
1316 if (pair
[i
]->next
) {
1317 plog(ASL_LEVEL_WARNING
,
1318 "proposal #%u ignored "
1319 "(multiple proposal not supported)\n",
1320 pair
[i
]->prop
->p_no
);
1326 for (p
= pair
[i
]; p
; p
= q
) {
1333 plog(ASL_LEVEL_DEBUG
,
1334 "proposal #%u: %d transform\n",
1335 pair
[i
]->prop
->p_no
, nprop
);
1340 /* bark if no proposal is found. */
1343 "no Proposal found.\n");
1355 * check transform payload.
1357 * positive: return the pointer to the payload of valid transform.
1358 * 0 : No valid transform found.
1361 get_transform(prop
, pair
, num_p
)
1362 struct isakmp_pl_p
*prop
;
1363 struct prop_pair
**pair
;
1366 int tlen
; /* total length of all transform in a proposal */
1368 struct isakmp_pl_t
*trns
;
1370 vchar_t
*pbuf
= NULL
;
1371 struct isakmp_parse_t
*pa
;
1372 struct prop_pair
*p
= NULL
, *q
;
1375 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1376 tlen
= ntohs(prop
->h
.len
)
1377 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1378 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1382 /* check and get transform for use */
1384 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1385 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1390 /* check the value of next payload */
1391 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1393 "Invalid payload type=%u\n", pa
->type
);
1397 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1400 plog(ASL_LEVEL_DEBUG
,
1401 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1403 /* check transform ID */
1404 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1405 plog(ASL_LEVEL_WARNING
,
1406 "unsupported proto_id %u\n",
1410 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1411 plog(ASL_LEVEL_WARNING
,
1412 "unsupported proto_id %u\n",
1417 if (!check_transform
[prop
->proto_id
]
1418 || !check_attributes
[prop
->proto_id
]) {
1419 plog(ASL_LEVEL_WARNING
,
1420 "unsupported proto_id %u\n",
1424 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1427 /* check data attributes */
1428 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1431 p
= racoon_calloc(1, sizeof(*p
));
1434 "failed to get buffer.\n");
1441 /* need to preserve the order */
1442 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1444 if (q
&& q
->prop
== p
->prop
) {
1445 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1452 pair
[prop
->p_no
] = p
;
1464 * make a new SA payload from prop_pair.
1465 * NOTE: this function clears the spi value.
1468 get_sabyproppair(pair
, iph1
)
1469 struct prop_pair
*pair
;
1470 phase1_handle_t
*iph1
;
1474 u_int8_t
*np_p
= NULL
;
1475 struct prop_pair
*p
;
1476 int prophlen
, trnslen
;
1479 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
1480 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1484 for (p
= pair
; p
; p
= p
->next
) {
1485 newtlen
+= sizeof(struct isakmp_pl_p
);
1486 newtlen
+= p
->prop
->spi_size
;
1487 newtlen
+= ntohs(p
->trns
->h
.len
);
1490 newsa
= vmalloc(newtlen
);
1491 if (newsa
== NULL
) {
1492 plog(ASL_LEVEL_ERR
, "failed to get newsa.\n");
1497 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1499 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
1500 /* update some of values in SA header */
1501 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1502 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1503 bp
+= sizeof(struct ipsecdoi_sa_b
);
1506 /* create proposal payloads */
1507 for (p
= pair
; p
; p
= p
->next
) {
1508 prophlen
= sizeof(struct isakmp_pl_p
)
1509 + p
->prop
->spi_size
;
1510 trnslen
= ntohs(p
->trns
->h
.len
);
1513 *np_p
= ISAKMP_NPTYPE_P
;
1515 /* create proposal */
1517 memcpy(bp
, p
->prop
, prophlen
);
1518 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1519 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1520 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1521 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1522 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1525 /* create transform */
1526 memcpy(bp
, p
->trns
, trnslen
);
1527 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1528 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1536 * update responder's spi
1539 ipsecdoi_updatespi(iph2
)
1540 phase2_handle_t
*iph2
;
1542 struct prop_pair
**pair
, *p
;
1549 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1552 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1556 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1557 /* multiple transform must be filtered by selectph2proposal.*/
1561 pp
= iph2
->approval
;
1563 /* create proposal payloads */
1564 for (p
= pair
[i
]; p
; p
= p
->next
) {
1566 * find a proposal/transform with matching proto_id/t_id.
1567 * we have analyzed validity already, in cmpsaprop_alloc().
1569 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1570 if (p
->prop
->proto_id
== pr
->proto_id
&&
1571 p
->trns
->t_id
== pr
->head
->trns_id
) {
1579 * XXX SPI bits are left-filled, for use with IPComp.
1580 * we should be switching to variable-length spi field...
1582 spi
= (u_int8_t
*)&pr
->spi
;
1583 spi
+= sizeof(pr
->spi
);
1585 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1590 free_proppair(pair
);
1595 * make a new SA payload from prop_pair.
1598 get_sabysaprop(pp0
, sa0
)
1602 struct prop_pair
**pair
= NULL
;
1603 vchar_t
*newsa
= NULL
;
1605 u_int8_t
*np_p
= NULL
;
1606 struct prop_pair
*p
= NULL
;
1610 int prophlen
, trnslen
;
1614 /* get proposal pair */
1615 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1619 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1620 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1622 if (pair
[pp
->prop_no
] == NULL
)
1625 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1626 newtlen
+= (sizeof(struct isakmp_pl_p
)
1629 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1630 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1631 if (tr
->trns_no
== p
->trns
->t_no
)
1637 newtlen
+= ntohs(p
->trns
->h
.len
);
1642 newsa
= vmalloc(newtlen
);
1643 if (newsa
== NULL
) {
1644 plog(ASL_LEVEL_ERR
, "failed to get newsa.\n");
1649 /* some of values of SA must be updated in the out of this function */
1650 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1651 bp
+= sizeof(struct ipsecdoi_sa_b
);
1653 /* create proposal payloads */
1654 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1656 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1657 prophlen
= sizeof(struct isakmp_pl_p
)
1658 + p
->prop
->spi_size
;
1660 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1661 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1662 if (tr
->trns_no
== p
->trns
->t_no
)
1668 trnslen
= ntohs(p
->trns
->h
.len
);
1671 *np_p
= ISAKMP_NPTYPE_P
;
1673 /* create proposal */
1675 memcpy(bp
, p
->prop
, prophlen
);
1676 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1677 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1678 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1679 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1682 /* create transform */
1683 memcpy(bp
, p
->trns
, trnslen
);
1684 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1685 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1697 if (newsa
!= NULL
) {
1707 * If some error happens then return 0. Although 0 means that lifetime is zero,
1708 * such a value should not be accepted.
1709 * Also 0 of lifebyte should not be included in a packet although 0 means not
1713 ipsecdoi_set_ld(buf
)
1723 ld
= ntohs(*ALIGNED_CAST(u_int16_t
*)buf
->v
);
1726 ld
= ntohl(*ALIGNED_CAST(u_int32_t
*)buf
->v
);
1730 "length %zu of life duration "
1731 "isn't supported.\n", buf
->l
);
1751 "invalid value of DOI 0x%08x.\n", doi
);
1761 check_situation(sit
)
1765 case IPSECDOI_SIT_IDENTITY_ONLY
:
1768 case IPSECDOI_SIT_SECRECY
:
1769 case IPSECDOI_SIT_INTEGRITY
:
1771 "situation 0x%08x unsupported yet.\n", sit
);
1776 "invalid situation 0x%08x.\n", sit
);
1783 * check protocol id in main mode
1786 check_prot_main(proto_id
)
1790 case IPSECDOI_PROTO_ISAKMP
:
1795 "Illegal protocol id=%u.\n", proto_id
);
1802 * check protocol id in quick mode
1805 check_prot_quick(proto_id
)
1809 case IPSECDOI_PROTO_IPSEC_AH
:
1810 case IPSECDOI_PROTO_IPSEC_ESP
:
1813 case IPSECDOI_PROTO_IPCOMP
:
1818 "invalid protocol id %d.\n", proto_id
);
1825 check_spi_size(proto_id
, size
)
1829 case IPSECDOI_PROTO_ISAKMP
:
1832 plog(ASL_LEVEL_WARNING
,
1833 "SPI size isn't zero, but IKE proposal.\n");
1837 case IPSECDOI_PROTO_IPSEC_AH
:
1838 case IPSECDOI_PROTO_IPSEC_ESP
:
1841 "invalid SPI size=%d for IPSEC proposal.\n",
1847 case IPSECDOI_PROTO_IPCOMP
:
1848 if (size
!= 2 && size
!= 4) {
1850 "invalid SPI size=%d for IPCOMP proposal.\n",
1864 * check transform ID in ISAKMP.
1867 check_trns_isakmp(t_id
)
1871 case IPSECDOI_KEY_IKE
:
1875 "invalid transform-id=%u in proto_id=%u.\n",
1876 t_id
, IPSECDOI_KEY_IKE
);
1883 * check transform ID in AH.
1890 case IPSECDOI_AH_MD5
:
1891 case IPSECDOI_AH_SHA
:
1892 case IPSECDOI_AH_SHA256
:
1893 case IPSECDOI_AH_SHA384
:
1894 case IPSECDOI_AH_SHA512
:
1896 case IPSECDOI_AH_DES
:
1898 "not support transform-id=%u in AH.\n", t_id
);
1902 "invalid transform-id=%u in AH.\n", t_id
);
1909 * check transform ID in ESP.
1912 check_trns_esp(t_id
)
1916 case IPSECDOI_ESP_DES
:
1917 case IPSECDOI_ESP_3DES
:
1918 case IPSECDOI_ESP_NULL
:
1919 case IPSECDOI_ESP_RC5
:
1920 case IPSECDOI_ESP_CAST
:
1921 case IPSECDOI_ESP_BLOWFISH
:
1922 case IPSECDOI_ESP_AES
:
1923 case IPSECDOI_ESP_TWOFISH
:
1925 case IPSECDOI_ESP_DES_IV32
:
1926 case IPSECDOI_ESP_DES_IV64
:
1927 case IPSECDOI_ESP_IDEA
:
1928 case IPSECDOI_ESP_3IDEA
:
1929 case IPSECDOI_ESP_RC4
:
1931 "not support transform-id=%u in ESP.\n", t_id
);
1935 "invalid transform-id=%u in ESP.\n", t_id
);
1942 * check transform ID in IPCOMP.
1945 check_trns_ipcomp(t_id
)
1949 case IPSECDOI_IPCOMP_OUI
:
1950 case IPSECDOI_IPCOMP_DEFLATE
:
1951 case IPSECDOI_IPCOMP_LZS
:
1955 "invalid transform-id=%u in IPCOMP.\n", t_id
);
1962 * check data attributes in IKE.
1965 check_attr_isakmp(trns
)
1966 struct isakmp_pl_t
*trns
;
1968 struct isakmp_data
*d
;
1973 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
1974 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
1977 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
1978 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
1979 lorv
= ntohs(d
->lorv
);
1981 plog(ASL_LEVEL_DEBUG
,
1982 "type=%s, flag=0x%04x, lorv=%s\n",
1983 s_oakley_attr(type
), flag
,
1984 s_oakley_attr_v(type
, lorv
));
1987 * some of the attributes must be encoded in TV.
1988 * see RFC2409 Appendix A "Attribute Classes".
1991 case OAKLEY_ATTR_ENC_ALG
:
1992 case OAKLEY_ATTR_HASH_ALG
:
1993 case OAKLEY_ATTR_AUTH_METHOD
:
1994 case OAKLEY_ATTR_GRP_DESC
:
1995 case OAKLEY_ATTR_GRP_TYPE
:
1996 case OAKLEY_ATTR_SA_LD_TYPE
:
1997 case OAKLEY_ATTR_PRF
:
1998 case OAKLEY_ATTR_KEY_LEN
:
1999 case OAKLEY_ATTR_FIELD_SIZE
:
2000 if (!flag
) { /* TLV*/
2002 "oakley attribute %d must be TV.\n",
2009 /* sanity check for TLV. length must be specified. */
2010 if (!flag
&& lorv
== 0) { /*TLV*/
2012 "invalid length %d for TLV attribute %d.\n",
2018 case OAKLEY_ATTR_ENC_ALG
:
2019 if (!alg_oakley_encdef_ok(lorv
)) {
2021 "invalied encryption algorithm=%d.\n",
2027 case OAKLEY_ATTR_HASH_ALG
:
2028 if (!alg_oakley_hashdef_ok(lorv
)) {
2030 "invalied hash algorithm=%d.\n",
2036 case OAKLEY_ATTR_AUTH_METHOD
:
2038 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2039 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2040 #ifdef ENABLE_HYBRID
2041 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2042 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
:
2043 #if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2044 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
:
2046 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
2048 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
2050 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2051 #ifdef ENABLE_HYBRID
2052 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2053 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
2054 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2055 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2056 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
:
2057 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
2058 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
:
2059 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
2060 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
:
2061 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
2063 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2064 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2066 "auth method %s isn't supported.\n",
2067 s_oakley_attr_method(lorv
));
2071 "invalid auth method %d.\n",
2077 case OAKLEY_ATTR_GRP_DESC
:
2078 if (!alg_oakley_dhdef_ok(lorv
)) {
2080 "invalid DH group %d.\n",
2086 case OAKLEY_ATTR_GRP_TYPE
:
2088 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2092 "unsupported DH group type %d.\n",
2098 case OAKLEY_ATTR_GRP_PI
:
2099 case OAKLEY_ATTR_GRP_GEN_ONE
:
2100 /* sanity checks? */
2103 case OAKLEY_ATTR_GRP_GEN_TWO
:
2104 case OAKLEY_ATTR_GRP_CURVE_A
:
2105 case OAKLEY_ATTR_GRP_CURVE_B
:
2107 "attr type=%u isn't supported.\n", type
);
2110 case OAKLEY_ATTR_SA_LD_TYPE
:
2112 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2113 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2117 "invalid life type %d.\n", lorv
);
2122 case OAKLEY_ATTR_SA_LD
:
2123 /* should check the value */
2126 case OAKLEY_ATTR_PRF
:
2127 case OAKLEY_ATTR_KEY_LEN
:
2130 case OAKLEY_ATTR_FIELD_SIZE
:
2132 "attr type=%u isn't supported.\n", type
);
2135 case OAKLEY_ATTR_GRP_ORDER
:
2138 case OAKLEY_ATTR_GSS_ID
:
2143 "invalid attribute type %d.\n", type
);
2149 d
= (struct isakmp_data
*)((char *)d
2152 tlen
-= (sizeof(*d
) + lorv
);
2153 d
= (struct isakmp_data
*)((char *)d
2154 + sizeof(*d
) + lorv
);
2162 * check data attributes in IPSEC AH/ESP.
2166 struct isakmp_pl_t
*trns
;
2168 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2172 check_attr_esp(trns
)
2173 struct isakmp_pl_t
*trns
;
2175 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2179 check_attr_ipsec(proto_id
, trns
)
2181 struct isakmp_pl_t
*trns
;
2183 struct isakmp_data
*d
;
2187 int attrseen
[16]; /* XXX magic number */
2189 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2190 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2191 memset(attrseen
, 0, sizeof(attrseen
));
2194 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2195 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2196 lorv
= ntohs(d
->lorv
);
2198 plog(ASL_LEVEL_DEBUG
,
2199 "type=%s, flag=0x%04x, lorv=%s\n",
2200 s_ipsecdoi_attr(type
), flag
,
2201 s_ipsecdoi_attr_v(type
, lorv
));
2203 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2207 case IPSECDOI_ATTR_ENC_MODE
:
2210 "must be TV when ENC_MODE.\n");
2215 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2216 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2219 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2220 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2221 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2222 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2223 plog(ASL_LEVEL_DEBUG
,
2224 "UDP encapsulation requested\n");
2229 "invalid encryption mode=%u.\n",
2235 case IPSECDOI_ATTR_AUTH
:
2238 "must be TV when AUTH.\n");
2243 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2244 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2245 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2248 "auth algorithm %u conflicts "
2249 "with transform %u.\n",
2254 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2255 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2256 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2260 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2261 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2262 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2266 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2267 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2268 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2272 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2273 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2274 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2278 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2279 case IPSECDOI_ATTR_AUTH_KPDK
:
2281 "auth algorithm %u isn't supported.\n",
2286 "invalid auth algorithm=%u.\n",
2292 case IPSECDOI_ATTR_SA_LD_TYPE
:
2295 "must be TV when LD_TYPE.\n");
2300 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2301 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2305 "invalid life type %d.\n", lorv
);
2310 case IPSECDOI_ATTR_SA_LD
:
2312 /* i.e. ISAKMP_GEN_TV */
2313 plog(ASL_LEVEL_DEBUG
,
2314 "life duration was in TLV.\n");
2316 /* i.e. ISAKMP_GEN_TLV */
2319 "invalid length of LD\n");
2325 case IPSECDOI_ATTR_GRP_DESC
:
2328 "must be TV when GRP_DESC.\n");
2332 if (!alg_oakley_dhdef_ok(lorv
)) {
2334 "invalid group description=%u.\n",
2340 case IPSECDOI_ATTR_KEY_LENGTH
:
2343 "must be TV when KEY_LENGTH.\n");
2348 case IPSECDOI_ATTR_KEY_ROUNDS
:
2349 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2350 case IPSECDOI_ATTR_COMP_PRIVALG
:
2352 "attr type=%u isn't supported.\n", type
);
2357 "invalid attribute type %d.\n", type
);
2363 d
= (struct isakmp_data
*)((char *)d
2366 tlen
-= (sizeof(*d
) + lorv
);
2367 d
= (struct isakmp_data
*)((caddr_t
)d
2368 + sizeof(*d
) + lorv
);
2372 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2373 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2375 "attr AUTH must be present for AH.\n");
2379 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2380 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2381 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2383 "attr AUTH must be present for ESP NULL encryption.\n");
2391 check_attr_ipcomp(trns
)
2392 struct isakmp_pl_t
*trns
;
2394 struct isakmp_data
*d
;
2398 int attrseen
[16]; /* XXX magic number */
2400 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2401 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2402 memset(attrseen
, 0, sizeof(attrseen
));
2405 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2406 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2407 lorv
= ntohs(d
->lorv
);
2409 plog(ASL_LEVEL_DEBUG
,
2410 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2413 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2417 case IPSECDOI_ATTR_ENC_MODE
:
2420 "must be TV when ENC_MODE.\n");
2425 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2426 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2429 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2430 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2431 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2432 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2433 plog(ASL_LEVEL_DEBUG
,
2434 "UDP encapsulation requested\n");
2439 "invalid encryption mode=%u.\n",
2445 case IPSECDOI_ATTR_SA_LD_TYPE
:
2448 "must be TV when LD_TYPE.\n");
2453 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2454 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2458 "invalid life type %d.\n", lorv
);
2463 case IPSECDOI_ATTR_SA_LD
:
2465 /* i.e. ISAKMP_GEN_TV */
2466 plog(ASL_LEVEL_DEBUG
,
2467 "life duration was in TLV.\n");
2469 /* i.e. ISAKMP_GEN_TLV */
2472 "invalid length of LD\n");
2478 case IPSECDOI_ATTR_GRP_DESC
:
2481 "must be TV when GRP_DESC.\n");
2485 if (!alg_oakley_dhdef_ok(lorv
)) {
2487 "invalid group description=%u.\n",
2493 case IPSECDOI_ATTR_AUTH
:
2495 "invalid attr type=%u.\n", type
);
2498 case IPSECDOI_ATTR_KEY_LENGTH
:
2499 case IPSECDOI_ATTR_KEY_ROUNDS
:
2500 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2501 case IPSECDOI_ATTR_COMP_PRIVALG
:
2503 "attr type=%u isn't supported.\n", type
);
2508 "invalid attribute type %d.\n", type
);
2514 d
= (struct isakmp_data
*)((char *)d
2517 tlen
-= (sizeof(*d
) + lorv
);
2518 d
= (struct isakmp_data
*)((caddr_t
)d
2519 + sizeof(*d
) + lorv
);
2524 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2525 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2527 "attr AUTH must be present for AH.\n", type
);
2537 * create phase1 proposal from remote configuration.
2538 * NOT INCLUDING isakmp general header of SA payload
2541 ipsecdoi_setph1proposal (phase1_handle_t
*iph1
)
2546 if (!iph1
) return NULL
;
2548 struct isakmpsa
*props
= iph1
->rmconf
->proposal
;
2549 unsigned int version
= iph1
->version
;
2551 /* count total size of SA minus isakmp general header */
2552 /* not including isakmp general header of SA payload */
2553 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2554 sablen
= sizeof(struct ipsecdoi_sa_b
);
2558 sablen
+= setph1prop(iph1
, NULL
);
2560 mysa
= vmalloc(sablen
);
2563 "failed to allocate my sa buffer\n");
2567 /* create SA payload */
2568 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2569 /* not including isakmp general header */
2570 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2571 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2573 (void)setph1prop(iph1
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2580 setph1prop (phase1_handle_t
*iph1
,
2583 struct isakmpsa
*props
= iph1
->rmconf
->proposal
;
2585 struct isakmp_pl_p
*prop
= NULL
;
2586 struct isakmpsa
*s
= NULL
;
2587 int proplen
, trnslen
;
2588 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2593 proplen
= sizeof(*prop
) + spi_size
;
2595 /* create proposal */
2596 prop
= (struct isakmp_pl_p
*)p
;
2597 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2598 prop
->h
.reserved
= 0;
2599 prop
->p_no
= props
->prop_no
;
2600 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2601 prop
->spi_size
= spi_size
;
2608 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2611 *np_t
= ISAKMP_NPTYPE_T
;
2613 trnslen
= setph1trns(s
, p
);
2616 /* save buffer to pre-next payload */
2617 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2620 /* count up transform length */
2626 /* update proposal length */
2628 prop
->h
.len
= htons(proplen
);
2629 prop
->num_t
= trns_num
;
2636 setph1trns (struct isakmpsa
*sa
,
2639 struct isakmp_pl_t
*trns
= NULL
;
2640 int trnslen
, attrlen
;
2643 trnslen
= sizeof(*trns
);
2645 /* create transform */
2646 trns
= (struct isakmp_pl_t
*)p
;
2647 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2648 trns
->t_no
= sa
->trns_no
;
2649 trns
->t_id
= IPSECDOI_KEY_IKE
;
2653 attrlen
= setph1attr(sa
, p
);
2659 trns
->h
.len
= htons(trnslen
);
2665 setph1attr (struct isakmpsa
*sa
,
2672 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2674 attrlen
+= sizeof(struct isakmp_data
)
2675 + sizeof(struct isakmp_data
);
2676 if (sa
->lifetime
> 0xffff)
2677 attrlen
+= sizeof(lifetime
);
2679 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2680 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2681 if (sa
->lifetime
> 0xffff) {
2682 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2686 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2693 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2695 attrlen
+= sizeof(struct isakmp_data
)
2696 + sizeof(struct isakmp_data
);
2697 if (sa
->lifebyte
> 0xffff)
2698 attrlen
+= sizeof(lifebyte
);
2700 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2701 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2702 if (sa
->lifebyte
> 0xffff) {
2703 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2707 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2714 attrlen
+= sizeof(struct isakmp_data
);
2716 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2719 attrlen
+= sizeof(struct isakmp_data
);
2721 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2723 if (sa
->authmethod
) {
2726 #ifdef ENABLE_HYBRID
2727 authmethod
= switch_authmethod(sa
->authmethod
);
2729 authmethod
= sa
->authmethod
;
2731 attrlen
+= sizeof(struct isakmp_data
);
2733 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2736 attrlen
+= sizeof(struct isakmp_data
);
2738 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2740 switch (sa
->dh_group
) {
2741 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2742 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2743 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2744 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2745 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2746 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2747 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2748 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2749 /* don't attach group type for known groups */
2750 attrlen
+= sizeof(struct isakmp_data
);
2752 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2756 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2757 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2758 /* don't attach group type for known groups */
2759 attrlen
+= sizeof(struct isakmp_data
);
2761 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2762 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2774 setph2proposal0(iph2
, pp
, pr
)
2775 const phase2_handle_t
*iph2
;
2776 const struct saprop
*pp
;
2777 const struct saproto
*pr
;
2780 struct isakmp_pl_p
*prop
;
2781 struct isakmp_pl_t
*trns
;
2786 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2787 const u_int8_t
*spi
;
2789 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2793 /* create proposal */
2794 prop
= (struct isakmp_pl_p
*)p
->v
;
2795 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2796 prop
->p_no
= pp
->prop_no
;
2797 prop
->proto_id
= pr
->proto_id
;
2800 spi
= (const u_int8_t
*)&pr
->spi
;
2801 switch (pr
->proto_id
) {
2802 case IPSECDOI_PROTO_IPCOMP
:
2804 * draft-shacham-ippcp-rfc2393bis-05.txt:
2805 * construct 16bit SPI (CPI).
2806 * XXX we may need to provide a configuration option to
2807 * generate 32bit SPI. otherwise we cannot interoeprate
2808 * with nodes that uses 32bit SPI, in case we are initiator.
2810 prop
->spi_size
= sizeof(u_int16_t
);
2811 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2812 p
->l
-= sizeof(pr
->spi
);
2813 p
->l
+= sizeof(u_int16_t
);
2816 prop
->spi_size
= sizeof(pr
->spi
);
2819 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2821 /* create transform */
2822 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2825 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2827 switch (pr
->proto_id
) {
2828 case IPSECDOI_PROTO_IPSEC_ESP
:
2830 * don't build a null encryption
2831 * with no authentication transform.
2833 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2834 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
2840 *np_t
= ISAKMP_NPTYPE_T
;
2844 /* get attribute length */
2847 attrlen
+= sizeof(struct isakmp_data
)
2848 + sizeof(struct isakmp_data
);
2849 if (pp
->lifetime
> 0xffff)
2850 attrlen
+= sizeof(u_int32_t
);
2852 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2853 attrlen
+= sizeof(struct isakmp_data
)
2854 + sizeof(struct isakmp_data
);
2855 if (pp
->lifebyte
> 0xffff)
2856 attrlen
+= sizeof(u_int32_t
);
2858 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2860 attrlen
+= sizeof(struct isakmp_data
);
2862 switch (pr
->proto_id
) {
2863 case IPSECDOI_PROTO_IPSEC_ESP
:
2864 /* non authentication mode ? */
2865 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2866 attrlen
+= sizeof(struct isakmp_data
);
2868 case IPSECDOI_PROTO_IPSEC_AH
:
2869 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2871 "no authentication algorithm found "
2872 "but protocol is AH.\n");
2876 attrlen
+= sizeof(struct isakmp_data
);
2878 case IPSECDOI_PROTO_IPCOMP
:
2882 "invalid protocol: %d\n", pr
->proto_id
);
2887 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2888 attrlen
+= sizeof(struct isakmp_data
);
2890 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2893 prop
= (struct isakmp_pl_p
*)p
->v
;
2895 /* set transform's values */
2896 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2897 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2898 trns
->t_no
= tr
->trns_no
;
2899 trns
->t_id
= tr
->trns_id
;
2901 /* set attributes */
2902 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
2905 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2906 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
2907 if (pp
->lifetime
> 0xffff) {
2908 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
2909 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2910 (caddr_t
)&v
, sizeof(v
));
2912 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2917 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2918 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2919 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
2920 if (pp
->lifebyte
> 0xffff) {
2921 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
2922 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2923 (caddr_t
)&v
, sizeof(v
));
2925 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2930 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
2933 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
2935 /* mandatory check has done above. */
2936 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2937 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
2938 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
2940 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2941 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
2942 iph2
->sainfo
->pfs_group
);
2944 /* update length of this transform. */
2945 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2946 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
2948 /* save buffer to pre-next payload */
2951 trnsoff
+= (sizeof(*trns
) + attrlen
);
2956 "no suitable proposal was created.\n");
2960 /* update length of this protocol. */
2961 prop
->h
.len
= htons(p
->l
);
2967 * create phase2 proposal from policy configuration.
2968 * NOT INCLUDING isakmp general header of SA payload.
2969 * This function is called by initiator only.
2972 ipsecdoi_setph2proposal(phase2_handle_t
*iph2
, int return_sa
)
2974 struct saprop
*proposal
, *a
;
2975 struct saproto
*b
= NULL
;
2976 vchar_t
*q
, *sa
= NULL
;
2977 struct isakmp_pl_p
*prop
;
2978 size_t propoff
; /* for previous field of type of next payload. */
2981 proposal
= iph2
->approval
;
2983 proposal
= iph2
->proposal
;
2985 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2986 struct ipsecdoi_sa_b
*sab
;
2988 sa
= vmalloc(sizeof(*sab
));
2991 "failed to allocate my sa buffer\n");
2995 /* create SA payload */
2996 sab
= ALIGNED_CAST(struct ipsecdoi_sa_b
*)sa
->v
;
2997 sab
->doi
= htonl(IPSEC_DOI
);
2998 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3004 for (a
= proposal
; a
; a
= a
->next
) {
3005 for (b
= a
->head
; b
; b
= b
->next
) {
3006 if (b
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
3007 // skip this - not specified in the SA
3008 // Need to set this in iph2 ???
3011 // IKEv1 sends encode mode in SA - uses diferent codes when NATT being used
3013 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3014 plog (ASL_LEVEL_NOTICE
, "NAT detected -> UDP encapsulation\n");
3016 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
3017 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3018 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3019 b
->encmode
+= udp_diff
;
3023 switch (iph2
->version
) {
3024 case ISAKMP_VERSION_NUMBER_IKEV1
:
3025 q
= setph2proposal0(iph2
, a
, b
);
3028 plog(ASL_LEVEL_ERR
, "Invalid IKE version detected\n");
3037 sa
= vrealloc(sa
, sa
->l
+ q
->l
);
3043 "failed to allocate my sa buffer\n");
3048 memcpy(sa
->v
+ sa
->l
- q
->l
, q
->v
, q
->l
);
3050 prop
= (struct isakmp_pl_p
*)(sa
->v
+
3052 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
3053 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3055 propoff
= sa
->l
- q
->l
;
3068 * return 1 if all of the given protocols are tunnel mode.
3071 ipsecdoi_tunnelmode(iph2
)
3072 phase2_handle_t
*iph2
;
3075 struct saproto
*pr
= NULL
;
3077 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
3078 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3079 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
3080 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
3081 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
3090 * return 1 if any of the given protocols are transport mode.
3093 ipsecdoi_any_transportmode(pp
)
3096 struct saproto
*pr
= NULL
;
3098 for (; pp
; pp
= pp
->next
) {
3099 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3100 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TRNS
||
3101 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
||
3102 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
3111 * return 1 if all of the given protocols are transport mode.
3114 ipsecdoi_transportmode(pp
)
3117 struct saproto
*pr
= NULL
;
3119 for (; pp
; pp
= pp
->next
) {
3120 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3121 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
3130 ipsecdoi_get_defaultlifetime()
3132 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3136 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3137 int proto_id
, enc
, auth
, comp
;
3139 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3141 case IPSECDOI_PROTO_IPSEC_ESP
:
3142 if (enc
== 0 || comp
!= 0) {
3144 "illegal algorithm defined "
3145 "ESP enc=%s auth=%s comp=%s.\n",
3146 TMPALGTYPE2STR(enc
),
3147 TMPALGTYPE2STR(auth
),
3148 TMPALGTYPE2STR(comp
));
3152 case IPSECDOI_PROTO_IPSEC_AH
:
3153 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3155 "illegal algorithm defined "
3156 "AH enc=%s auth=%s comp=%s.\n",
3157 TMPALGTYPE2STR(enc
),
3158 TMPALGTYPE2STR(auth
),
3159 TMPALGTYPE2STR(comp
));
3163 case IPSECDOI_PROTO_IPCOMP
:
3164 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3166 "illegal algorithm defined "
3167 "IPcomp enc=%s auth=%s comp=%s.\n",
3168 TMPALGTYPE2STR(enc
),
3169 TMPALGTYPE2STR(auth
),
3170 TMPALGTYPE2STR(comp
));
3176 "invalid ipsec protocol %d\n", proto_id
);
3179 #undef TMPALGTYPE2STR
3189 return IPSECDOI_PROTO_IPSEC_AH
;
3191 return IPSECDOI_PROTO_IPSEC_ESP
;
3192 case IPPROTO_IPCOMP
:
3193 return IPSECDOI_PROTO_IPCOMP
;
3195 return -1; /* XXX */
3203 case IPSECDOI_PROTO_IPSEC_AH
:
3205 case IPSECDOI_PROTO_IPSEC_ESP
:
3207 case IPSECDOI_PROTO_IPCOMP
:
3208 return IPPROTO_IPCOMP
;
3210 return -1; /* XXX */
3214 * Check if a subnet id is valid for comparison
3215 * with an address id ( address length mask )
3223 ipsecdoi_subnetisaddr_v4( subnet
, address
)
3224 const vchar_t
*subnet
;
3225 const vchar_t
*address
;
3227 struct in_addr
*mask
;
3229 if (address
->l
!= sizeof(struct in_addr
))
3232 if (subnet
->l
!= (sizeof(struct in_addr
)*2))
3235 mask
= ALIGNED_CAST(struct in_addr
*)(subnet
->v
+ sizeof(struct in_addr
));
3237 if (mask
->s_addr
!=0xffffffff)
3240 return memcmp(subnet
->v
,address
->v
,address
->l
);
3246 ipsecdoi_subnetisaddr_v6( subnet
, address
)
3247 const vchar_t
*subnet
;
3248 const vchar_t
*address
;
3250 struct in6_addr
*mask
;
3253 if (address
->l
!= sizeof(struct in6_addr
))
3256 if (subnet
->l
!= (sizeof(struct in6_addr
)*2))
3259 mask
= ALIGNED_CAST(struct in6_addr
*)(subnet
->v
+ sizeof(struct in6_addr
));
3261 for (i
=0; i
<16; i
++)
3262 if(mask
->s6_addr
[i
]!=0xff)
3265 return memcmp(subnet
->v
,address
->v
,address
->l
);
3272 * Check and Compare two IDs
3273 * - specify 0 for exact if wildcards are allowed
3277 * = -1 for integrity error
3281 ipsecdoi_chkcmpids( idt
, ids
, exact
)
3282 const vchar_t
*idt
; /* id cmp target */
3283 const vchar_t
*ids
; /* id cmp source */
3286 struct ipsecdoi_id_b
*id_bt
;
3287 struct ipsecdoi_id_b
*id_bs
;
3292 /* handle wildcard IDs */
3294 if (idt
== NULL
|| ids
== NULL
)
3298 plog(ASL_LEVEL_DEBUG
,
3299 "check and compare ids : values matched (ANONYMOUS)\n" );
3304 plog(ASL_LEVEL_DEBUG
,
3305 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3310 /* make sure the ids are of the same type */
3312 id_bt
= (struct ipsecdoi_id_b
*) idt
->v
;
3313 id_bs
= (struct ipsecdoi_id_b
*) ids
->v
;
3315 ident_t
.v
= idt
->v
+ sizeof(*id_bt
);
3316 ident_t
.l
= idt
->l
- sizeof(*id_bt
);
3317 ident_s
.v
= ids
->v
+ sizeof(*id_bs
);
3318 ident_s
.l
= ids
->l
- sizeof(*id_bs
);
3320 if (id_bs
->type
!= id_bt
->type
)
3323 * special exception for comparing
3324 * address to subnet id types when
3325 * the netmask is address length
3328 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR
)&&
3329 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)) {
3330 result
= ipsecdoi_subnetisaddr_v4(&ident_t
,&ident_s
);
3334 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)&&
3335 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR
)) {
3336 result
= ipsecdoi_subnetisaddr_v4(&ident_s
,&ident_t
);
3341 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR
)&&
3342 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)) {
3343 result
= ipsecdoi_subnetisaddr_v6(&ident_t
,&ident_s
);
3347 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)&&
3348 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR
)) {
3349 result
= ipsecdoi_subnetisaddr_v6(&ident_s
,&ident_t
);
3353 plog(ASL_LEVEL_DEBUG
,
3354 "check and compare ids : id type mismatch %s != %s\n",
3355 s_ipsecdoi_ident(id_bs
->type
),
3356 s_ipsecdoi_ident(id_bt
->type
));
3361 if(id_bs
->proto_id
!= id_bt
->proto_id
){
3362 plog(ASL_LEVEL_DEBUG
,
3363 "check and compare ids : proto_id mismatch %d != %d\n",
3364 id_bs
->proto_id
, id_bt
->proto_id
);
3369 /* compare the ID data. */
3371 switch (id_bt
->type
) {
3372 case IPSECDOI_ID_DER_ASN1_DN
:
3373 case IPSECDOI_ID_DER_ASN1_GN
:
3374 /* compare asn1 ids */
3375 result
= eay_cmp_asn1dn(&ident_t
, &ident_s
);
3378 case IPSECDOI_ID_IPV4_ADDR
:
3379 /* validate lengths */
3380 if ((ident_t
.l
!= sizeof(struct in_addr
))||
3381 (ident_s
.l
!= sizeof(struct in_addr
)))
3385 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3386 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3387 /* validate lengths */
3388 if ((ident_t
.l
!= (sizeof(struct in_addr
)*2))||
3389 (ident_s
.l
!= (sizeof(struct in_addr
)*2)))
3394 case IPSECDOI_ID_IPV6_ADDR
:
3395 /* validate lengths */
3396 if ((ident_t
.l
!= sizeof(struct in6_addr
))||
3397 (ident_s
.l
!= sizeof(struct in6_addr
)))
3401 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3402 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3403 /* validate lengths */
3404 if ((ident_t
.l
!= (sizeof(struct in6_addr
)*2))||
3405 (ident_s
.l
!= (sizeof(struct in6_addr
)*2)))
3409 case IPSECDOI_ID_FQDN
:
3410 case IPSECDOI_ID_USER_FQDN
:
3411 case IPSECDOI_ID_KEY_ID
:
3416 "Unhandled id type %i specified for comparison\n",
3421 /* validate matching data and length */
3422 if (ident_t
.l
== ident_s
.l
)
3423 result
= memcmp(ident_t
.v
,ident_s
.v
,ident_t
.l
);
3429 /* debug level output */
3430 if(loglevel
>= ASL_LEVEL_DEBUG
) {
3431 char *idstrt
= ipsecdoi_id2str(idt
);
3432 char *idstrs
= ipsecdoi_id2str(ids
);
3435 plog(ASL_LEVEL_DEBUG
,
3436 "check and compare ids : values matched (%s)\n",
3437 s_ipsecdoi_ident(id_bs
->type
) );
3439 plog(ASL_LEVEL_DEBUG
,
3440 "check and compare ids : value mismatch (%s)\n",
3441 s_ipsecdoi_ident(id_bs
->type
));
3443 plog(ASL_LEVEL_DEBUG
, "cmpid target: \'%s\'\n", idstrt
);
3444 plog(ASL_LEVEL_DEBUG
, "cmpid source: \'%s\'\n", idstrs
);
3446 racoon_free(idstrs
);
3447 racoon_free(idstrt
);
3458 /* id integrity error */
3459 plog(ASL_LEVEL_DEBUG
, "check and compare ids : %s integrity error\n",
3460 s_ipsecdoi_ident(id_bs
->type
));
3461 plog(ASL_LEVEL_DEBUG
, "cmpid target: length = \'%zu\'\n", ident_t
.l
);
3462 plog(ASL_LEVEL_DEBUG
, "cmpid source: length = \'%zu\'\n", ident_s
.l
);
3469 * check the following:
3470 * - In main mode with pre-shared key, only address type can be used.
3471 * - if proper type for phase 1 ?
3472 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3473 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3474 * - if ID payload sent from peer is equal to the ID expected by me.
3476 * both of "id" and "id_p" should be ID payload without general header,
3479 ipsecdoi_checkid1(iph1
)
3480 phase1_handle_t
*iph1
;
3482 struct ipsecdoi_id_b
*id_b
;
3483 struct sockaddr_storage
*sa
;
3486 if (iph1
->id_p
== NULL
) {
3488 "invalid iph1 passed id_p == NULL\n");
3489 return ISAKMP_INTERNAL_ERROR
;
3491 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3493 "invalid value passed as \"ident\" (len=%lu)\n",
3494 (u_long
)iph1
->id_p
->l
);
3495 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3498 id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3500 /* In main mode with pre-shared key, only address type can be used.
3501 * If NAT Traversal being used and peer is behind nat and
3502 * natt version = 02 - allow non-address ID type.
3504 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
3505 && iph1
->etype
== ISAKMP_ETYPE_IDENT
3506 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3508 && (iph1
->natt_flags
& NAT_DETECTED_PEER
) == 0
3511 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3512 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3514 "Expecting IP address type in main mode, "
3515 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3516 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3520 /* if proper type for phase 1 ? */
3521 switch (id_b
->type
) {
3522 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3523 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3524 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3525 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3526 plog(ASL_LEVEL_WARNING
,
3527 "such ID type %s is not proper.\n",
3528 s_ipsecdoi_ident(id_b
->type
));
3532 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3533 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
||
3534 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3536 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3537 plog(ASL_LEVEL_WARNING
,
3538 "protocol ID and Port mismatched. "
3539 "proto_id:%d port:%d\n",
3540 id_b
->proto_id
, ntohs(id_b
->port
));
3543 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3545 * copmaring with expected port.
3546 * always permit if port is equal to PORT_ISAKMP
3548 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3552 switch (iph1
->remote
->ss_family
) {
3554 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3558 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3563 "invalid family: %d\n",
3564 iph1
->remote
->ss_family
);
3565 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3567 if (ntohs(id_b
->port
) != port
) {
3568 plog(ASL_LEVEL_WARNING
,
3569 "port %d expected, but %d\n",
3570 port
, ntohs(id_b
->port
));
3577 /* compare with the ID if specified. */
3578 if (genlist_next(iph1
->rmconf
->idvl_p
, 0)) {
3579 vchar_t
*ident0
= NULL
;
3584 struct genlist_entry
*gpb
;
3586 for (id
= genlist_next (iph1
->rmconf
->idvl_p
, &gpb
); id
; id
= genlist_next (0, &gpb
)) {
3587 /* check the type of both IDs */
3588 if (id
->idtype
!= doi2idtype(id_b
->type
))
3589 continue; /* ID type mismatch */
3593 /* compare defined ID with the ID sent by peer. */
3596 ident0
= getidval(id
->idtype
, id
->id
);
3598 switch (id
->idtype
) {
3601 ident
.v
= iph1
->id_p
->v
+ sizeof(*id_b
);
3602 ident
.l
= iph1
->id_p
->l
- sizeof(*id_b
);
3603 if (eay_cmp_asn1dn(ident0
, &ident
) == 0)
3606 plog(ASL_LEVEL_WARNING
, "ASN1DN ID matching not implemented - passed.\n");
3607 goto matched
; //%%%%%% hack for now until we have code to do this.
3610 case IDTYPE_ADDRESS
:
3611 sa
= ALIGNED_CAST(struct sockaddr_storage
*)ident0
->v
;
3612 sa2
= (caddr_t
)(id_b
+ 1);
3613 switch (sa
->ss_family
) {
3615 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3616 continue; /* ID value mismatch */
3617 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3618 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) == 0)
3623 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3624 continue; /* ID value mismatch */
3625 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3626 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) == 0)
3635 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
) == 0)
3640 if (ident0
!= NULL
) {
3644 plog(ASL_LEVEL_DEBUG
, "No ID match.\n");
3645 if (iph1
->rmconf
->verify_identifier
)
3646 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3647 matched
: /* ID value match */
3655 /* HACK!!! - temporary until this prototype gets moved */
3656 extern CFDataRef
SecCertificateCopySubjectSequence( SecCertificateRef certificate
);
3659 * create ID payload for phase 1 and set into iph1->id.
3660 * NOT INCLUDING isakmp general header.
3661 * see, RFC2407 4.6.2.1
3664 ipsecdoi_setid1(iph1
)
3665 phase1_handle_t
*iph1
;
3667 vchar_t
*ret
= NULL
;
3668 struct ipsecdoi_id_b id_b
;
3669 vchar_t
*ident
= NULL
;
3670 struct sockaddr_in v4_address
;
3671 struct sockaddr_storage
*ipid
= NULL
;
3674 bzero(&id_b
, sizeof(id_b
));
3676 switch (iph1
->rmconf
->idvtype
) {
3678 id_b
.type
= IPSECDOI_ID_FQDN
;
3679 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3681 case IDTYPE_USERFQDN
:
3682 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3683 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3686 case IDTYPE_KEYIDUSE
:
3687 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3688 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3691 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3692 if (iph1
->rmconf
->idv
) {
3693 /* XXX it must be encoded to asn1dn. */
3694 ident
= vdup(iph1
->rmconf
->idv
);
3696 if (oakley_getmycert(iph1
) < 0) {
3698 "failed to get own CERT.\n");
3702 SecCertificateRef certificate
;
3707 certificate
= crypto_cssm_x509cert_CreateSecCertificateRef(&iph1
->cert
->cert
);
3708 if (certificate
== NULL
) {
3710 "failed to get SecCertificateRef\n");
3713 subject
= crypto_cssm_CopySubjectSequence(certificate
);
3714 if (subject
== NULL
) {
3716 "failed to get subjectName\n");
3717 CFRelease(certificate
);
3720 len
= CFDataGetLength(subject
);
3721 namePtr
= (UInt8
*)CFDataGetBytePtr(subject
);
3722 ident
= vmalloc(len
);
3723 if (ident
== NULL
) {
3725 "failed to get subjectName\n");
3726 CFRelease(certificate
);
3730 memcpy(ident
->v
, namePtr
, len
);
3731 CFRelease(certificate
);
3735 case IDTYPE_ADDRESS
:
3737 * if the value of the id type was set by the configuration
3738 * file, then use it. otherwise the value is get from local
3739 * ip address by using ike negotiation.
3741 if (iph1
->rmconf
->idv
)
3742 ipid
= ALIGNED_CAST(struct sockaddr_storage
*)iph1
->rmconf
->idv
->v
;
3753 if (ipid
->ss_family
== AF_INET6
&&
3754 iph1
->nat64_prefix
.length
) {
3755 memset(&v4_address
, 0, sizeof(v4_address
));
3756 v4_address
.sin_len
= sizeof(struct sockaddr_in
);
3757 v4_address
.sin_family
= AF_INET
;
3758 v4_address
.sin_port
= ((struct sockaddr_in6
*)ipid
)->sin6_port
;
3759 v4_address
.sin_addr
.s_addr
= 0;
3761 ipid
= ALIGNED_CAST(struct sockaddr_storage
*)&v4_address
;
3765 /* use IP address */
3766 switch (ipid
->ss_family
) {
3768 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3769 l
= sizeof(struct in_addr
);
3770 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3774 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3775 l
= sizeof(struct in6_addr
);
3776 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3781 "invalid address family.\n");
3784 if(iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
){
3785 id_b
.proto_id
= IPPROTO_UDP
;
3786 id_b
.port
= htons(PORT_ISAKMP
);
3792 "failed to get ID buffer.\n");
3795 memcpy(ident
->v
, p
, ident
->l
);
3800 "failed to get ID buffer.\n");
3804 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3807 "failed to get ID buffer.\n");
3811 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3812 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3816 plogdump(ASL_LEVEL_DEBUG
, iph1
->id
->v
, iph1
->id
->l
, "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3824 plog(ASL_LEVEL_ERR
, "failed get my ID\n");
3833 vchar_t
*new = NULL
;
3837 else if (lcconf
->ident
[type
])
3838 new = vdup(lcconf
->ident
[type
]);
3843 /* it's only called by cfparse.y. */
3845 set_identifier(vpp
, type
, value
)
3846 vchar_t
**vpp
, *value
;
3849 return set_identifier_qual(vpp
, type
, value
, IDQUAL_UNSPEC
);
3853 set_identifier_qual(vpp
, type
, value
, qual
)
3854 vchar_t
**vpp
, *value
;
3858 vchar_t
*new = NULL
;
3860 /* simply return if value is null. */
3862 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3864 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3872 case IDTYPE_USERFQDN
:
3875 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3878 case IDTYPE_KEYIDUSE
:
3879 #ifdef ENABLE_HYBRID
3882 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3883 new = vmalloc(value
->l
- 1);
3886 memcpy(new->v
, value
->v
, new->l
);
3890 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3891 * to use a file for backward compatibility sake.
3895 case IDQUAL_UNSPEC
: {
3900 fp
= fopen(value
->v
, "r");
3903 "can not open %s\n", value
->v
);
3907 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3908 new = vrealloc(new, tlen
+ len
);
3913 memcpy(new->v
+ tlen
, b
, len
);
3921 new = vmalloc(value
->l
- 1);
3924 "can not allocate memory");
3927 memcpy(new->v
, value
->v
, new->l
);
3932 "unknown qualifier");
3937 case IDTYPE_ADDRESS
: {
3938 struct sockaddr_storage
*sa
;
3940 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3944 sa
= str2saddr(value
->v
, NULL
);
3947 "invalid ip address %s\n", value
->v
);
3951 new = vmalloc(sysdep_sa_len((struct sockaddr
*)sa
));
3956 memcpy(new->v
, sa
, new->l
);
3961 plog(ASL_LEVEL_DEBUG
, "Setting ID type ASN1DN from string not supported\n");
3973 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3974 * NOT INCLUDING isakmp general header.
3975 * this function is for initiator. responder will get to copy from payload.
3976 * responder ID type is always address type.
3977 * see, RFC2407 4.6.2.1
3980 ipsecdoi_setid2(iph2
)
3981 phase2_handle_t
*iph2
;
3983 struct secpolicy
*sp
;
3985 /* check there is phase 2 handler ? */
3986 sp
= getspbyspid(iph2
->spid
);
3989 "no policy found for spid:%u.\n", iph2
->spid
);
3993 struct sockaddr_in local_v4_address
;
3994 struct sockaddr_storage
*srcaddr
= &sp
->spidx
.src
;
3995 u_int8_t prefs
= sp
->spidx
.prefs
;
3996 if (sp
->spidx
.dst
.ss_family
== AF_INET6
&&
3997 iph2
->nat64_prefix
.length
) {
3998 memset(&local_v4_address
, 0, sizeof(local_v4_address
));
3999 local_v4_address
.sin_len
= sizeof(struct sockaddr_in
);
4000 local_v4_address
.sin_family
= AF_INET
;
4001 local_v4_address
.sin_port
= ((struct sockaddr_in6
*)&sp
->spidx
.src
)->sin6_port
;
4002 local_v4_address
.sin_addr
.s_addr
= 0;
4004 srcaddr
= ALIGNED_CAST(struct sockaddr_storage
*)&local_v4_address
;
4007 iph2
->id
= ipsecdoi_sockaddr2id(srcaddr
,
4008 prefs
, sp
->spidx
.ul_proto
);
4009 if (iph2
->id
== NULL
) {
4011 "failed to get ID for %s\n",
4012 spidx2str(&sp
->spidx
));
4016 if (((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR
||
4017 (ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
) &&
4018 iph2
->side
== RESPONDER
&&
4019 iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED_ME
) &&
4020 lcconf
->ext_nat_id
) {
4022 if (!(iph2
->id
= vdup(lcconf
->ext_nat_id
))) {
4027 plogdump(ASL_LEVEL_DEBUG
, iph2
->id
->v
, iph2
->id
->l
, "use local ID type %s\n",
4028 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
4031 struct sockaddr_in v4_address
;
4032 struct sockaddr_storage
*dstaddr
= &sp
->spidx
.dst
;
4033 u_int8_t prefd
= sp
->spidx
.prefd
;
4034 if (sp
->spidx
.dst
.ss_family
== AF_INET6
&&
4035 iph2
->nat64_prefix
.length
) {
4036 memset(&v4_address
, 0, sizeof(v4_address
));
4037 v4_address
.sin_len
= sizeof(struct sockaddr_in
);
4038 v4_address
.sin_family
= AF_INET
;
4039 v4_address
.sin_port
= ((struct sockaddr_in6
*)&sp
->spidx
.dst
)->sin6_port
;
4040 nw_nat64_extract_v4(&iph2
->nat64_prefix
, &((struct sockaddr_in6
*)&sp
->spidx
.dst
)->sin6_addr
, &v4_address
.sin_addr
);
4042 dstaddr
= ALIGNED_CAST(struct sockaddr_storage
*)&v4_address
;
4045 iph2
->id_p
= ipsecdoi_sockaddr2id(dstaddr
,
4046 prefd
, sp
->spidx
.ul_proto
);
4047 if (iph2
->id_p
== NULL
) {
4049 "failed to get ID for %s\n",
4050 spidx2str(&sp
->spidx
));
4054 plogdump(ASL_LEVEL_DEBUG
, iph2
->id_p
->v
, iph2
->id_p
->l
, "use remote ID type %s\n",
4055 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
4061 * set address type of ID.
4062 * NOT INCLUDING general header.
4065 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
4066 struct sockaddr_storage
*saddr
;
4071 int type
, len1
, len2
;
4076 * Q. When type is SUBNET, is it allowed to be ::1/128.
4077 * A. Yes. (consensus at bake-off)
4079 switch (saddr
->ss_family
) {
4081 len1
= sizeof(struct in_addr
);
4082 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
4083 type
= IPSECDOI_ID_IPV4_ADDR
;
4085 } else if (prefixlen
< (sizeof(struct in_addr
) << 3)) {
4086 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
4087 len2
= sizeof(struct in_addr
);
4090 "invalid prefix length: %d.\n", prefixlen
);
4093 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
4094 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
4098 len1
= sizeof(struct in6_addr
);
4099 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
4100 type
= IPSECDOI_ID_IPV6_ADDR
;
4102 } else if (prefixlen
< (sizeof(struct in6_addr
) << 3)) {
4103 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
4104 len2
= sizeof(struct in6_addr
);
4107 "invalid prefix length: %d.\n", prefixlen
);
4110 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
4111 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
4116 "invalid family: %d.\n", saddr
->ss_family
);
4121 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4124 "failed to get ID buffer.\n");
4128 memset(new->v
, 0, new->l
);
4130 /* set the part of header. */
4131 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4133 /* set ul_proto and port */
4135 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4136 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4138 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4139 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4140 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4141 port
== IPSEC_PORT_ANY
? 0 : port
;
4142 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
4148 u_char
*p
= (unsigned char *) new->v
+
4149 sizeof(struct ipsecdoi_id_b
) + len1
;
4150 u_int bits
= prefixlen
;
4158 *p
= ~((1 << (8 - bits
)) - 1);
4165 ipsecdoi_sockrange2id(laddr
, haddr
, ul_proto
)
4166 struct sockaddr_storage
*laddr
, *haddr
;
4170 int type
, len1
, len2
;
4173 if (laddr
->ss_family
!= haddr
->ss_family
) {
4174 plog(ASL_LEVEL_ERR
, "Address family mismatch\n");
4178 switch (laddr
->ss_family
) {
4180 type
= IPSECDOI_ID_IPV4_ADDR_RANGE
;
4181 len1
= sizeof(struct in_addr
);
4182 len2
= sizeof(struct in_addr
);
4186 type
= IPSECDOI_ID_IPV6_ADDR_RANGE
;
4187 len1
= sizeof(struct in6_addr
);
4188 len2
= sizeof(struct in6_addr
);
4193 "invalid family: %d.\n", laddr
->ss_family
);
4198 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4201 "failed to get ID buffer.\n");
4205 memset(new->v
, 0, new->l
);
4206 /* set the part of header. */
4207 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4209 /* set ul_proto and port */
4211 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4212 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4214 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4215 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4216 port
= ((struct sockaddr_in
*)(laddr
))->sin_port
;
4217 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4218 port
== IPSEC_PORT_ANY
? 0 : port
;
4219 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
),
4220 (caddr_t
)&((struct sockaddr_in
*)(laddr
))->sin_addr
,
4222 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
,
4223 (caddr_t
)&((struct sockaddr_in
*)haddr
)->sin_addr
,
4230 * create sockaddr_storage structure from ID payload (buf).
4231 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4232 * see, RFC2407 4.6.2.1
4235 ipsecdoi_id2sockaddr(vchar_t
*buf
,
4236 struct sockaddr_storage
*saddr
,
4237 u_int8_t
*prefixlen
,
4238 u_int16_t
*ul_proto
,
4241 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)buf
->v
;
4245 * When a ID payload of subnet type with a IP address of full bit
4246 * masked, it has to be processed as host address.
4247 * e.g. below 2 type are same.
4248 * type = ipv6 subnet, data = 2001::1/128
4249 * type = ipv6 address, data = 2001::1
4251 switch (id_b
->type
) {
4252 case IPSECDOI_ID_IPV4_ADDR
:
4253 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4254 saddr
->ss_len
= sizeof(struct sockaddr_in
);
4255 saddr
->ss_family
= AF_INET
;
4256 ((struct sockaddr_in
*)saddr
)->sin_port
=
4259 : id_b
->port
); /* see sockaddr2id() */
4260 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
4261 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4264 case IPSECDOI_ID_IPV6_ADDR
:
4265 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4266 saddr
->ss_len
= sizeof(struct sockaddr_in6
);
4267 saddr
->ss_family
= AF_INET6
;
4268 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
4271 : id_b
->port
); /* see sockaddr2id() */
4272 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
4273 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4278 "unsupported ID type %d\n", id_b
->type
);
4279 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
4282 /* get prefix length */
4283 switch (id_b
->type
) {
4284 case IPSECDOI_ID_IPV4_ADDR
:
4285 plen
= sizeof(struct in_addr
) << 3;
4288 case IPSECDOI_ID_IPV6_ADDR
:
4289 plen
= sizeof(struct in6_addr
) << 3;
4292 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4294 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4299 int alen
= sizeof(struct in_addr
);
4301 switch (id_b
->type
) {
4302 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4303 alen
= sizeof(struct in_addr
);
4306 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4307 alen
= sizeof(struct in6_addr
);
4314 return ISAKMP_INTERNAL_ERROR
;
4316 /* get subnet mask length */
4320 p
= (unsigned char *) buf
->v
4321 + sizeof(struct ipsecdoi_id_b
)
4324 for (; *p
== 0xff; p
++) {
4347 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
4348 *ul_proto
= id_b
->proto_id
== 0 ? IPSEC_ULPROTO_ANY
: id_b
->proto_id
; /* see sockaddr2id() */
4355 * make printable string from ID payload except of general header.
4365 static char buf
[BUFLEN
];
4366 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)id
->v
;
4367 struct sockaddr_storage saddr
;
4370 bzero(&saddr
, sizeof(saddr
));
4372 switch (id_b
->type
) {
4373 case IPSECDOI_ID_IPV4_ADDR
:
4374 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4375 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4377 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4378 saddr
.ss_family
= AF_INET
;
4379 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4380 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4381 id
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4384 case IPSECDOI_ID_IPV6_ADDR
:
4385 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4386 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4387 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4388 saddr
.ss_family
= AF_INET6
;
4389 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4390 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4391 id
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4392 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4393 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4394 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4400 switch (id_b
->type
) {
4401 case IPSECDOI_ID_IPV4_ADDR
:
4403 case IPSECDOI_ID_IPV6_ADDR
:
4405 len
= snprintf( buf
, sizeof(buf
), "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4408 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4410 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4415 int alen
= sizeof(struct in_addr
);
4417 switch (id_b
->type
) {
4418 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4419 alen
= sizeof(struct in_addr
);
4422 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4423 alen
= sizeof(struct in6_addr
);
4434 /* get subnet mask length */
4438 p
= (unsigned char *) id
->v
4439 + sizeof(struct ipsecdoi_id_b
)
4442 for (; *p
== 0xff; p
++) {
4461 len
= snprintf( buf
, sizeof(buf
), "%s/%i", saddrwop2str((struct sockaddr
*)&saddr
), plen
);
4465 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4467 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4469 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4470 saddr
.ss_family
= AF_INET
;
4471 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4472 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4473 id
->v
+ sizeof(*id_b
) + sizeof(struct in_addr
),
4474 sizeof(struct in_addr
));
4477 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4483 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4485 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4487 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4488 saddr
.ss_family
= AF_INET6
;
4489 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4490 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4491 id
->v
+ sizeof(*id_b
) + sizeof(struct in6_addr
),
4492 sizeof(struct in6_addr
));
4493 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4494 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4495 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4499 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4505 case IPSECDOI_ID_FQDN
:
4506 case IPSECDOI_ID_USER_FQDN
:
4507 len
= id
->l
- sizeof(*id_b
);
4510 memcpy(buf
, id
->v
+ sizeof(*id_b
), len
);
4513 case IPSECDOI_ID_DER_ASN1_DN
:
4514 case IPSECDOI_ID_DER_ASN1_GN
:
4517 X509_NAME
*xn
= NULL
;
4520 dat
= id
->v
+ sizeof(*id_b
);
4521 len
= id
->l
- sizeof(*id_b
);
4523 if (d2i_X509_NAME(&xn
, (void*) &dat
, len
) != NULL
) {
4524 BIO
*bio
= BIO_new(BIO_s_mem());
4525 X509_NAME_print_ex(bio
, xn
, 0, 0);
4526 len
= BIO_get_mem_data(bio
, &dat
);
4529 memcpy(buf
,dat
,len
);
4537 "unable to extract asn1dn from id\n");
4539 len
= snprintf(buf
, sizeof(buf
), "<ASN1-DN>");
4545 /* currently unhandled id types */
4546 case IPSECDOI_ID_KEY_ID
:
4547 len
= snprintf( buf
, sizeof(buf
), "<KEY-ID>");
4552 "unknown ID type %d\n", id_b
->type
);
4556 len
= snprintf( buf
, sizeof(buf
), "<?>");
4558 ret
= racoon_malloc(len
+1);
4560 memcpy(ret
,buf
,len
);
4568 * set IPsec data attributes into a proposal.
4569 * NOTE: MUST called per a transform.
4572 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4573 struct isakmp_pl_t
*t
;
4578 struct isakmp_data
*d
, *prev
;
4584 tr
->trns_no
= t
->t_no
;
4585 tr
->trns_id
= t
->t_id
;
4587 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4588 prev
= (struct isakmp_data
*)NULL
;
4589 d
= (struct isakmp_data
*)(t
+ 1);
4592 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4593 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4595 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4599 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4600 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4602 plog(ASL_LEVEL_DEBUG
,
4603 "type=%s, flag=0x%04x, lorv=%s\n",
4604 s_ipsecdoi_attr(type
), flag
,
4605 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4608 case IPSECDOI_ATTR_SA_LD_TYPE
:
4610 int type
= ntohs(d
->lorv
);
4612 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4613 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4617 plog(ASL_LEVEL_WARNING
,
4618 "invalid life duration type. "
4620 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4625 case IPSECDOI_ATTR_SA_LD
:
4627 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4628 IPSECDOI_ATTR_SA_LD_TYPE
) {
4630 "life duration must follow ltype\n");
4636 vchar_t
*ld_buf
= NULL
;
4639 /* i.e. ISAKMP_GEN_TV */
4640 ld_buf
= vmalloc(sizeof(d
->lorv
));
4641 if (ld_buf
== NULL
) {
4643 "failed to get LD buffer.\n");
4646 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4648 int len
= ntohs(d
->lorv
);
4649 /* i.e. ISAKMP_GEN_TLV */
4650 ld_buf
= vmalloc(len
);
4651 if (ld_buf
== NULL
) {
4653 "failed to get LD buffer.\n");
4656 memcpy(ld_buf
->v
, d
+ 1, len
);
4659 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4660 t
= ipsecdoi_set_ld(ld_buf
);
4664 "invalid life duration.\n");
4667 /* lifetime must be equal in a proposal. */
4668 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4670 else if (pp
->lifetime
!= t
) {
4672 "lifetime mismatched "
4674 "prev:%ld curr:%u.\n",
4675 (long)pp
->lifetime
, t
);
4679 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4680 t
= ipsecdoi_set_ld(ld_buf
);
4684 "invalid life duration.\n");
4687 /* lifebyte must be equal in a proposal. */
4688 if (pp
->lifebyte
== 0)
4690 else if (pp
->lifebyte
!= t
) {
4692 "lifebyte mismatched "
4694 "prev:%d curr:%u.\n",
4702 "invalid life type: %d\n", life_t
);
4708 case IPSECDOI_ATTR_GRP_DESC
:
4710 * RFC2407: 4.5 IPSEC Security Association Attributes
4711 * Specifies the Oakley Group to be used in a PFS QM
4712 * negotiation. For a list of supported values, see
4713 * Appendix A of [IKE].
4715 if (pp
->pfs_group
== 0)
4716 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4717 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4719 "pfs_group mismatched "
4720 "in a proposal.\n");
4725 case IPSECDOI_ATTR_ENC_MODE
:
4727 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4729 "multiple encmode exist "
4730 "in a transform.\n");
4733 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4736 case IPSECDOI_ATTR_AUTH
:
4737 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4739 "multiple authtype exist "
4740 "in a transform.\n");
4743 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4746 case IPSECDOI_ATTR_KEY_LENGTH
:
4747 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4749 "key length defined but not ESP");
4752 tr
->encklen
= ntohs(d
->lorv
);
4755 case IPSECDOI_ATTR_KEY_ROUNDS
:
4756 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4757 case IPSECDOI_ATTR_COMP_PRIVALG
:
4765 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4767 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4768 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4778 ipsecdoi_authalg2trnsid(alg
)
4782 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4783 return IPSECDOI_AH_MD5
;
4784 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4785 return IPSECDOI_AH_SHA
;
4786 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4787 return IPSECDOI_AH_SHA256
;
4788 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4789 return IPSECDOI_AH_SHA384
;
4790 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4791 return IPSECDOI_AH_SHA512
;
4792 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4793 return IPSECDOI_AH_DES
;
4794 case IPSECDOI_ATTR_AUTH_KPDK
:
4795 return IPSECDOI_AH_MD5
; /* XXX */
4798 "invalid authentication algorithm:%d\n", alg
);
4803 static int rm_idtype2doi
[] = {
4804 255, /* IDTYPE_UNDEFINED, 0 */
4805 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4806 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4807 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4808 255, /* IDTYPE_ADDRESS, 4
4809 * it expands into 4 types by another function. */
4810 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4814 * convert idtype to DOI value.
4822 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4823 return rm_idtype2doi
[idtype
];
4832 case IPSECDOI_ID_FQDN
:
4833 return(IDTYPE_FQDN
);
4834 case IPSECDOI_ID_USER_FQDN
:
4835 return(IDTYPE_USERFQDN
);
4836 case IPSECDOI_ID_KEY_ID
:
4837 return(IDTYPE_KEYID
);
4838 case IPSECDOI_ID_DER_ASN1_DN
:
4839 return(IDTYPE_ASN1DN
);
4840 case IPSECDOI_ID_IPV4_ADDR
:
4841 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4842 case IPSECDOI_ID_IPV6_ADDR
:
4843 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4844 return(IDTYPE_ADDRESS
);
4846 plog(ASL_LEVEL_WARNING
,
4847 "Inproper idtype:%s in this function.\n",
4848 s_ipsecdoi_ident(doi
));
4849 return(IDTYPE_ADDRESS
); /* XXX */
4854 #ifdef ENABLE_HYBRID
4856 switch_authmethod(authmethod
)
4859 switch(authmethod
) {
4860 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
4861 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
;
4863 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
4864 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
;
4866 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
4867 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
;
4869 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
4870 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
;
4872 /* Those are not implemented */
4873 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
4874 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
;
4876 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
4877 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
;
4879 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
4880 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
;