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"
89 #include "ikev2_rfc.h"
92 static int switch_authmethod(int);
95 int verbose_proposal_check
= 1;
97 static vchar_t
*get_ph1approval (phase1_handle_t
*, struct prop_pair
**);
98 void print_ph1mismatched (struct prop_pair
*, struct isakmpsa
*);
99 static int t2isakmpsa (struct isakmp_pl_t
*, struct isakmpsa
*);
100 static int cmp_aproppair_i (struct prop_pair
*, struct prop_pair
*);
101 static struct prop_pair
*get_ph2approval (phase2_handle_t
*,
102 struct prop_pair
**);
103 static struct prop_pair
*get_ph2approvalx (phase2_handle_t
*,
105 static void free_proppair0 (struct prop_pair
*);
107 static int get_transform (struct isakmp_pl_p
*, struct prop_pair
**, int *);
108 static u_int32_t
ipsecdoi_set_ld (vchar_t
*);
110 static int check_doi (u_int32_t
);
111 static int check_situation (u_int32_t
);
113 static int check_prot_main (int);
114 static int check_prot_quick (int);
115 static int (*check_protocol
[]) (int) = {
116 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
117 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
118 NULL
, /* IPSECDOI_TYPE_IKEV2_PH1 */
119 NULL
, /* IPSECDOI_TYPE_IKEV2_PH2 */
122 int check_spi_size (int, int);
124 static int check_trns_isakmp (int);
125 static int check_trns_ah (int);
126 static int check_trns_esp (int);
127 static int check_trns_ipcomp (int);
128 static int (*check_transform
[]) (int) = {
130 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
131 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
132 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
133 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
136 static int check_attr_isakmp (struct isakmp_pl_t
*);
137 static int check_attr_ah (struct isakmp_pl_t
*);
138 static int check_attr_esp (struct isakmp_pl_t
*);
139 static int check_attr_ipsec (int, struct isakmp_pl_t
*);
140 static int check_attr_ipcomp (struct isakmp_pl_t
*);
141 static int (*check_attributes
[]) (struct isakmp_pl_t
*) = {
143 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
144 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
145 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
146 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
149 int setph1prop (phase1_handle_t
*, caddr_t
);
150 static int setph1trns (struct isakmpsa
*, caddr_t
);
151 static int setph1attr (struct isakmpsa
*, caddr_t
);
152 static vchar_t
*setph2proposal0 (const phase2_handle_t
*,
153 const struct saprop
*, const struct saproto
*);
155 static vchar_t
*getidval (int, vchar_t
*);
160 * check phase 1 SA payload.
161 * make new SA payload to be replyed not including general header.
162 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
164 * positive: the pointer to new buffer of SA payload.
165 * network byte order.
166 * NULL : error occurd.
169 ipsecdoi_checkph1proposal(sa
, iph1
)
171 phase1_handle_t
*iph1
;
173 vchar_t
*newsa
; /* new SA payload approved. */
174 struct prop_pair
**pair
;
176 /* get proposal pair */
177 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
181 /* check and get one SA for use */
182 newsa
= get_ph1approval(iph1
, pair
);
189 iph1
->sa_ret
= newsa
;
195 * acceptable check for remote configuration.
196 * return a new SA payload to be reply to peer.
199 get_ph1approval(iph1
, pair
)
200 phase1_handle_t
*iph1
;
201 struct prop_pair
**pair
;
204 struct isakmpsa
*sa
, tsa
;
205 struct prop_pair
*s
, *p
;
209 if (iph1
->approval
) {
210 delisakmpsa(iph1
->approval
);
211 iph1
->approval
= NULL
;
214 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
217 for (s
= pair
[i
]; s
; s
= s
->next
) {
219 sizeof(struct isakmp_pl_p
) + s
->prop
->spi_size
;
221 /* compare proposal and select one */
222 for (p
= s
; p
; p
= p
->tnext
) {
223 if ((sa
= get_ph1approvalx(p
,
224 iph1
->rmconf
->proposal
, &tsa
,
225 iph1
->rmconf
->pcheck_level
)) != NULL
)
232 * if there is no suitable proposal, racoon complains about all of
233 * mismatched items in those proposal.
235 if (verbose_proposal_check
) {
236 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
239 for (s
= pair
[i
]; s
; s
= s
->next
) {
240 prophlen
= sizeof(struct isakmp_pl_p
)
242 for (p
= s
; p
; p
= p
->tnext
) {
243 print_ph1mismatched(p
,
244 iph1
->rmconf
->proposal
);
249 plog(ASL_LEVEL_ERR
, "no suitable proposal found.\n");
254 plog(ASL_LEVEL_DEBUG
, "an acceptable proposal found.\n");
256 /* check DH group settings */
258 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
262 plog(ASL_LEVEL_WARNING
,
263 "invalid DH parameter found, use default.\n");
264 oakley_dhgrp_free(sa
->dhgrp
);
268 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
277 plog(ASL_LEVEL_DEBUG
, "agreed on %s auth.\n",
278 s_oakley_attr_method(iph1
->approval
->authmethod
));
281 newsa
= get_sabyproppair(p
, iph1
);
283 delisakmpsa(iph1
->approval
);
284 iph1
->approval
= NULL
;
291 * compare peer's single proposal and all of my proposal.
292 * and select one if suiatable.
293 * p : one of peer's proposal.
294 * proposal: my proposals.
297 get_ph1approvalx(p
, proposal
, sap
, check_level
)
299 struct isakmpsa
*proposal
, *sap
;
302 struct isakmp_pl_p
*prop
= p
->prop
;
303 struct isakmp_pl_t
*trns
= p
->trns
;
304 struct isakmpsa sa
, *s
, *tsap
;
308 plog(ASL_LEVEL_DEBUG
,
309 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
310 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
311 prop
->spi_size
, prop
->num_t
);
313 plog(ASL_LEVEL_DEBUG
,
314 "trns#=%d, trns-id=%s\n",
316 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
318 tsap
= sap
!= NULL
? sap
: &sa
;
320 memset(tsap
, 0, sizeof(*tsap
));
321 if (t2isakmpsa(trns
, tsap
) < 0)
323 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
325 authmethod
= switch_authmethod(s
->authmethod
);
326 tsap_authmethod
= switch_authmethod(tsap
->authmethod
);
328 authmethod
= s
->authmethod
;
329 tsap_authmethod
= tsap
->authmethod
;
331 plog(ASL_LEVEL_DEBUG
, "Compared: DB:Peer\n");
332 plog(ASL_LEVEL_DEBUG
, "(version = %d:%d)\n",
333 s
->version
, tsap
->version
);
334 plog(ASL_LEVEL_DEBUG
, "(lifetime = %ld:%ld)\n",
335 (long)s
->lifetime
, (long)tsap
->lifetime
);
336 plog(ASL_LEVEL_DEBUG
, "(lifebyte = %zu:%zu)\n",
337 s
->lifebyte
, tsap
->lifebyte
);
338 plog(ASL_LEVEL_DEBUG
, "enctype = %s:%s\n",
339 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
341 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
343 plog(ASL_LEVEL_DEBUG
, "(encklen = %d:%d)\n",
344 s
->encklen
, tsap
->encklen
);
345 plog(ASL_LEVEL_DEBUG
, "hashtype = %s:%s\n",
346 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
348 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
350 plog(ASL_LEVEL_DEBUG
, "authmethod = %s:%s\n",
351 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
353 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
355 plog(ASL_LEVEL_DEBUG
, "dh_group = %s:%s\n",
356 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
358 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
361 /* XXX to be considered ? */
362 if (tsap
->lifebyte
> s
->lifebyte
) ;
365 * if responder side and peer's key length in proposal
366 * is bigger than mine, it might be accepted.
368 if(tsap
->enctype
== s
->enctype
&&
369 (tsap
->authmethod
== authmethod
|| tsap_authmethod
== authmethod
) &&
370 tsap
->hashtype
== s
->hashtype
&&
371 tsap
->dh_group
== s
->dh_group
&&
372 tsap
->encklen
== s
->encklen
&&
373 tsap
->version
== s
->version
) {
374 switch(check_level
) {
375 case PROP_CHECK_IKEV2
:
376 case PROP_CHECK_OBEY
:
380 case PROP_CHECK_STRICT
:
381 if ((tsap
->lifetime
> s
->lifetime
) ||
382 (tsap
->lifebyte
> s
->lifebyte
))
387 case PROP_CHECK_CLAIM
:
388 if (tsap
->lifetime
< s
->lifetime
)
389 s
->lifetime
= tsap
->lifetime
;
390 if (tsap
->lifebyte
< s
->lifebyte
)
391 s
->lifebyte
= tsap
->lifebyte
;
395 case PROP_CHECK_EXACT
:
396 if ((tsap
->lifetime
!= s
->lifetime
) ||
397 (tsap
->lifebyte
!= s
->lifebyte
))
404 "Unexpected proposal_check value\n");
412 if (tsap
->dhgrp
!= NULL
){
413 oakley_dhgrp_free(tsap
->dhgrp
);
417 if ((s
= dupisakmpsa(s
)) != NULL
) {
418 switch(check_level
) {
419 case PROP_CHECK_OBEY
:
420 s
->lifetime
= tsap
->lifetime
;
421 s
->lifebyte
= tsap
->lifebyte
;
424 case PROP_CHECK_STRICT
:
425 s
->lifetime
= tsap
->lifetime
;
426 s
->lifebyte
= tsap
->lifebyte
;
429 case PROP_CHECK_CLAIM
:
430 if (tsap
->lifetime
< s
->lifetime
)
431 s
->lifetime
= tsap
->lifetime
;
432 if (tsap
->lifebyte
< s
->lifebyte
)
433 s
->lifebyte
= tsap
->lifebyte
;
439 // hack to get around cisco rekeys
440 if (tsap
->authmethod
!= authmethod
&& tsap_authmethod
== authmethod
) {
441 s
->authmethod
= tsap
->authmethod
;
448 * print all of items in peer's proposal which are mismatched to my proposal.
449 * p : one of peer's proposal.
450 * proposal: my proposals.
453 print_ph1mismatched(p
, proposal
)
455 struct isakmpsa
*proposal
;
457 struct isakmpsa sa
, *s
;
459 memset(&sa
, 0, sizeof(sa
));
460 if (t2isakmpsa(p
->trns
, &sa
) < 0)
462 for (s
= proposal
; s
; s
= s
->next
) {
463 if (sa
.enctype
!= s
->enctype
) {
466 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
468 s
->prop_no
, s
->trns_no
,
469 p
->prop
->p_no
, p
->trns
->t_no
,
470 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
472 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
475 if (sa
.authmethod
!= s
->authmethod
) {
477 "rejected authmethod: "
478 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
480 s
->prop_no
, s
->trns_no
,
481 p
->prop
->p_no
, p
->trns
->t_no
,
482 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
484 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
487 if (sa
.hashtype
!= s
->hashtype
) {
489 "rejected hashtype: "
490 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
492 s
->prop_no
, s
->trns_no
,
493 p
->prop
->p_no
, p
->trns
->t_no
,
494 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
496 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
499 if (sa
.prf
!= s
->prf
||
500 sa
.prfklen
!= s
->prfklen
) {
503 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
505 s
->prop_no
, s
->trns_no
,
506 p
->prop
->p_no
, p
->trns
->t_no
,
507 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
510 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
514 if (sa
.dh_group
!= s
->dh_group
) {
516 "rejected dh_group: "
517 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
519 s
->prop_no
, s
->trns_no
,
520 p
->prop
->p_no
, p
->trns
->t_no
,
521 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
523 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
528 if (sa
.dhgrp
!= NULL
){
529 oakley_dhgrp_free(sa
.dhgrp
);
535 * get ISAKMP data attributes
539 struct isakmp_pl_t
*trns
;
542 struct isakmp_data
*d
, *prev
;
551 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
552 prev
= (struct isakmp_data
*)NULL
;
553 d
= (struct isakmp_data
*)(trns
+ 1);
556 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
557 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
559 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
565 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
566 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
568 plog(ASL_LEVEL_DEBUG
,
569 "type=%s, flag=0x%04x, lorv=%s\n",
570 s_oakley_attr(type
), flag
,
571 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
573 /* get variable-sized item */
575 case OAKLEY_ATTR_GRP_PI
:
576 case OAKLEY_ATTR_GRP_GEN_ONE
:
577 case OAKLEY_ATTR_GRP_GEN_TWO
:
578 case OAKLEY_ATTR_GRP_CURVE_A
:
579 case OAKLEY_ATTR_GRP_CURVE_B
:
580 case OAKLEY_ATTR_SA_LD
:
581 case OAKLEY_ATTR_GRP_ORDER
:
584 p
= (u_char
*)&d
->lorv
;
586 len
= ntohs(d
->lorv
);
589 "invalid ISAKMP-SA attr, attr-len %d, overall-len %d\n",
593 p
= (u_char
*)(d
+ 1);
598 memcpy(val
->v
, p
, len
);
606 case OAKLEY_ATTR_ENC_ALG
:
607 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
610 case OAKLEY_ATTR_HASH_ALG
:
611 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
614 case OAKLEY_ATTR_AUTH_METHOD
:
615 sa
->authmethod
= ntohs(d
->lorv
);
618 case OAKLEY_ATTR_GRP_DESC
:
619 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
622 case OAKLEY_ATTR_GRP_TYPE
:
624 int type
= (int)ntohs(d
->lorv
);
625 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
626 sa
->dhgrp
->type
= type
;
631 case OAKLEY_ATTR_GRP_PI
:
632 sa
->dhgrp
->prime
= val
;
635 case OAKLEY_ATTR_GRP_GEN_ONE
:
638 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
640 int len
= ntohs(d
->lorv
);
644 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
645 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
649 case OAKLEY_ATTR_GRP_GEN_TWO
:
652 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
654 int len
= ntohs(d
->lorv
);
658 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
659 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
663 case OAKLEY_ATTR_GRP_CURVE_A
:
664 sa
->dhgrp
->curve_a
= val
;
667 case OAKLEY_ATTR_GRP_CURVE_B
:
668 sa
->dhgrp
->curve_b
= val
;
671 case OAKLEY_ATTR_SA_LD_TYPE
:
673 int type
= (int)ntohs(d
->lorv
);
675 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
676 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
680 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
685 case OAKLEY_ATTR_SA_LD
:
687 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
688 OAKLEY_ATTR_SA_LD_TYPE
) {
690 "life duration must follow ltype\n");
695 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
696 sa
->lifetime
= ipsecdoi_set_ld(val
);
698 if (sa
->lifetime
== 0) {
700 "invalid life duration.\n");
704 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
705 sa
->lifebyte
= ipsecdoi_set_ld(val
);
707 if (sa
->lifebyte
== 0) {
709 "invalid life duration.\n");
716 "invalid life type: %d\n", life_t
);
721 case OAKLEY_ATTR_KEY_LEN
:
723 int len
= ntohs(d
->lorv
);
726 "keylen %d: not multiple of 8\n",
730 sa
->encklen
= (u_int16_t
)len
;
734 case OAKLEY_ATTR_PRF
:
735 case OAKLEY_ATTR_FIELD_SIZE
:
739 case OAKLEY_ATTR_GRP_ORDER
:
740 sa
->dhgrp
->order
= val
;
750 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
752 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
753 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
757 /* key length must not be specified on some algorithms */
759 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
760 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
762 "keylen must not be specified "
763 "for encryption algorithm %d\n",
776 * check phase 2 SA payload and select single proposal.
777 * make new SA payload to be replyed not including general header.
778 * This function is called by responder only.
784 ipsecdoi_selectph2proposal(iph2
)
785 phase2_handle_t
*iph2
;
787 struct prop_pair
**pair
;
788 struct prop_pair
*ret
;
790 /* get proposal pair */
791 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
795 /* check and select a proposal. */
796 ret
= get_ph2approval(iph2
, pair
);
801 /* make a SA to be replayed. */
802 /* SPI must be updated later. */
803 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
805 if (iph2
->sa_ret
== NULL
)
812 * check phase 2 SA payload returned from responder.
813 * This function is called by initiator only.
819 ipsecdoi_checkph2proposal(iph2
)
820 phase2_handle_t
*iph2
;
822 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
826 vchar_t
*sa_ret
= NULL
;
828 /* get proposal pair of SA sent. */
829 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
832 "failed to get prop pair.\n");
836 /* XXX should check the number of transform */
838 /* get proposal pair of SA replayed */
839 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
842 "failed to get prop pair.\n");
846 /* check proposal is only one ? */
849 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
857 "no proposal received.\n");
862 "some proposals received.\n");
866 if (spair
[n
] == NULL
) {
867 plog(ASL_LEVEL_WARNING
,
868 "invalid proposal number:%d received.\n", i
);
872 if (rpair
[n
]->tnext
!= NULL
) {
874 "multi transforms replyed.\n");
878 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
880 "proposal mismathed.\n");
885 * check and select a proposal.
886 * ensure that there is no modification of the proposal by
889 p
= get_ph2approval(iph2
, rpair
);
893 /* make a SA to be replayed. */
894 sa_ret
= iph2
->sa_ret
;
895 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
897 if (iph2
->sa_ret
== NULL
)
904 free_proppair(rpair
);
906 free_proppair(spair
);
914 * compare two prop_pair which is assumed to have same proposal number.
915 * the case of bundle or single SA, NOT multi transforms.
916 * a: a proposal that is multi protocols and single transform, usually replyed.
917 * b: a proposal that is multi protocols and multi transform, usually sent.
918 * NOTE: this function is for initiator.
922 * XXX cannot understand the comment!
925 cmp_aproppair_i(a
, b
)
926 struct prop_pair
*a
, *b
;
928 struct prop_pair
*p
, *q
, *r
;
931 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
932 for (r
= q
; r
; r
= r
->tnext
) {
934 if (p
->trns
->t_no
== r
->trns
->t_no
)
938 /* no suitable transform found */
940 "no suitable transform found.\n");
945 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
946 plog(ASL_LEVEL_WARNING
,
947 "proposal #%d mismatched, "
949 r
->prop
->p_no
, p
->prop
->p_no
);
953 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
955 "proto_id mismathed: my:%d peer:%d\n",
956 r
->prop
->proto_id
, p
->prop
->proto_id
);
960 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
962 "invalid spi size: %d.\n",
967 /* check #of transforms */
968 if (p
->prop
->num_t
!= 1) {
969 plog(ASL_LEVEL_WARNING
,
970 "#of transform is %d, "
971 "but expected 1.\n", p
->prop
->num_t
);
975 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
976 plog(ASL_LEVEL_WARNING
,
977 "transform number has been modified.\n");
980 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
981 plog(ASL_LEVEL_WARNING
,
982 "reserved field should be zero.\n");
986 /* compare attribute */
987 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
988 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
989 plog(ASL_LEVEL_WARNING
,
990 "attribute has been modified.\n");
994 if ((p
&& !q
) || (!p
&& q
)) {
995 /* # of protocols mismatched */
997 "#of protocols mismatched.\n");
1005 * acceptable check for policy configuration.
1006 * return a new SA payload to be reply to peer.
1008 static struct prop_pair
*
1009 get_ph2approval(iph2
, pair
)
1010 phase2_handle_t
*iph2
;
1011 struct prop_pair
**pair
;
1013 struct prop_pair
*ret
;
1016 iph2
->approval
= NULL
;
1018 plog(ASL_LEVEL_DEBUG
,
1019 "begin compare proposals.\n");
1021 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1022 if (pair
[i
] == NULL
)
1024 plog(ASL_LEVEL_DEBUG
,
1025 "pair[%d]: %p\n", i
, pair
[i
]);
1026 print_proppair(ASL_LEVEL_DEBUG
, pair
[i
]);;
1028 /* compare proposal and select one */
1029 ret
= get_ph2approvalx(iph2
, pair
[i
]);
1036 plog(ASL_LEVEL_ERR
, "no suitable policy found.\n");
1042 * compare my proposal and peers just one proposal.
1045 static struct prop_pair
*
1046 get_ph2approvalx(iph2
, pp
)
1047 phase2_handle_t
*iph2
;
1048 struct prop_pair
*pp
;
1050 struct prop_pair
*ret
= NULL
;
1051 struct saprop
*pr0
, *pr
= NULL
;
1052 struct saprop
*q1
, *q2
;
1054 pr0
= aproppair2saprop(pp
);
1058 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1059 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1060 plog(ASL_LEVEL_DEBUG
,
1061 "peer's single bundle:\n");
1062 printsaprop0(ASL_LEVEL_DEBUG
, q1
);
1063 plog(ASL_LEVEL_DEBUG
,
1064 "my single bundle:\n");
1065 printsaprop0(ASL_LEVEL_DEBUG
, q2
);
1067 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1075 /* no proposal matching */
1082 plog(ASL_LEVEL_DEBUG
, "matched\n");
1083 iph2
->approval
= pr
;
1087 struct prop_pair
*p
, *x
;
1088 struct prop_pair
*n
= NULL
;
1092 for (p
= pp
; p
; p
= p
->next
) {
1094 * find a proposal with matching proto_id.
1095 * we have analyzed validity already, in cmpsaprop_alloc().
1097 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1098 if (sp
->proto_id
== p
->prop
->proto_id
)
1106 for (x
= p
; x
; x
= x
->tnext
)
1107 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1112 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1115 "failed to get buffer.\n");
1122 /* need to preserve the order */
1123 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1125 if (x
&& x
->prop
== n
->prop
) {
1126 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1137 /* #of transforms should be updated ? */
1146 struct prop_pair
**pair
;
1150 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1151 free_proppair0(pair
[i
]);
1158 free_proppair0(pair
)
1159 struct prop_pair
*pair
;
1161 struct prop_pair
*p
, *q
, *r
, *s
;
1177 * get proposal pairs from SA payload.
1178 * tiny check for proposal payload.
1181 get_proppair(sa
, mode
)
1185 struct prop_pair
**pair
= NULL
;
1186 int num_p
= 0; /* number of proposal for use */
1191 //plogdump(ASL_LEVEL_DEBUG, sa->v, sa->l, "total SA len=%zu\n", sa->l);
1193 if (mode
== IPSECDOI_TYPE_PH1
|| mode
== IPSECDOI_TYPE_PH2
) {
1195 struct ipsecdoi_sa_b
*sab
= ALIGNED_CAST(__typeof__(sab
))sa
->v
;
1198 /* check SA payload size */
1199 if (sa
->l
< sizeof(*sab
)) {
1201 "Invalid SA length = %zu.\n", sa
->l
);
1206 if (check_doi(ntohl(sab
->doi
)) < 0)
1209 /* check SITUATION */
1210 if (check_situation(ntohl(sab
->sit
)) < 0)
1213 bp
= (caddr_t
)(sab
+ 1);
1214 tlen
= sa
->l
- sizeof(*sab
);
1216 bp
= (__typeof__(bp
))sa
->v
;
1220 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1223 "failed to get buffer.\n");
1228 struct isakmp_pl_p
*prop
;
1230 vchar_t
*pbuf
= NULL
;
1231 struct isakmp_parse_t
*pa
;
1233 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1237 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1238 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1240 /* check the value of next payload */
1241 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1243 "Invalid payload type=%u\n", pa
->type
);
1248 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1251 plog(ASL_LEVEL_DEBUG
,
1252 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1256 "invalid proposal with length %d\n", proplen
);
1261 /* check Protocol ID */
1262 if (!check_protocol
[mode
]) {
1264 "unsupported mode %d\n", mode
);
1268 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1271 /* check SPI length when IKE. */
1272 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1276 if (get_transform(prop
, pair
, &num_p
) < 0) {
1287 struct prop_pair
*p
, *q
;
1289 /* check for proposals with no transforms */
1290 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1294 plog(ASL_LEVEL_DEBUG
, "pair %d:\n", i
);
1295 print_proppair(ASL_LEVEL_DEBUG
, pair
[i
]);
1297 notrans
= nprop
= 0;
1298 for (p
= pair
[i
]; p
; p
= p
->next
) {
1299 if (p
->trns
== NULL
) {
1303 for (q
= p
; q
; q
= q
->tnext
)
1309 * XXX at this moment, we cannot accept proposal group
1310 * with multiple proposals. this should be fixed.
1312 if (pair
[i
]->next
) {
1313 plog(ASL_LEVEL_WARNING
,
1314 "proposal #%u ignored "
1315 "(multiple proposal not supported)\n",
1316 pair
[i
]->prop
->p_no
);
1322 for (p
= pair
[i
]; p
; p
= q
) {
1329 plog(ASL_LEVEL_DEBUG
,
1330 "proposal #%u: %d transform\n",
1331 pair
[i
]->prop
->p_no
, nprop
);
1336 /* bark if no proposal is found. */
1339 "no Proposal found.\n");
1351 * check transform payload.
1353 * positive: return the pointer to the payload of valid transform.
1354 * 0 : No valid transform found.
1357 get_transform(prop
, pair
, num_p
)
1358 struct isakmp_pl_p
*prop
;
1359 struct prop_pair
**pair
;
1362 int tlen
; /* total length of all transform in a proposal */
1364 struct isakmp_pl_t
*trns
;
1366 vchar_t
*pbuf
= NULL
;
1367 struct isakmp_parse_t
*pa
;
1368 struct prop_pair
*p
= NULL
, *q
;
1371 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1372 tlen
= ntohs(prop
->h
.len
)
1373 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1374 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1378 /* check and get transform for use */
1380 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1381 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1386 /* check the value of next payload */
1387 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1389 "Invalid payload type=%u\n", pa
->type
);
1393 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1396 plog(ASL_LEVEL_DEBUG
,
1397 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1399 /* check transform ID */
1400 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1401 plog(ASL_LEVEL_WARNING
,
1402 "unsupported proto_id %u\n",
1406 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1407 plog(ASL_LEVEL_WARNING
,
1408 "unsupported proto_id %u\n",
1413 if (!check_transform
[prop
->proto_id
]
1414 || !check_attributes
[prop
->proto_id
]) {
1415 plog(ASL_LEVEL_WARNING
,
1416 "unsupported proto_id %u\n",
1420 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1423 /* check data attributes */
1424 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1427 p
= racoon_calloc(1, sizeof(*p
));
1430 "failed to get buffer.\n");
1437 /* need to preserve the order */
1438 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1440 if (q
&& q
->prop
== p
->prop
) {
1441 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1448 pair
[prop
->p_no
] = p
;
1460 * make a new SA payload from prop_pair.
1461 * NOTE: this function clears the spi value.
1464 get_sabyproppair(pair
, iph1
)
1465 struct prop_pair
*pair
;
1466 phase1_handle_t
*iph1
;
1470 u_int8_t
*np_p
= NULL
;
1471 struct prop_pair
*p
;
1472 int prophlen
, trnslen
;
1475 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
1476 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1480 for (p
= pair
; p
; p
= p
->next
) {
1481 newtlen
+= sizeof(struct isakmp_pl_p
);
1482 newtlen
+= p
->prop
->spi_size
;
1483 newtlen
+= ntohs(p
->trns
->h
.len
);
1486 newsa
= vmalloc(newtlen
);
1487 if (newsa
== NULL
) {
1488 plog(ASL_LEVEL_ERR
, "failed to get newsa.\n");
1493 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1495 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
1496 /* update some of values in SA header */
1497 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1498 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1499 bp
+= sizeof(struct ipsecdoi_sa_b
);
1502 /* create proposal payloads */
1503 for (p
= pair
; p
; p
= p
->next
) {
1504 prophlen
= sizeof(struct isakmp_pl_p
)
1505 + p
->prop
->spi_size
;
1506 trnslen
= ntohs(p
->trns
->h
.len
);
1509 *np_p
= ISAKMP_NPTYPE_P
;
1511 /* create proposal */
1513 memcpy(bp
, p
->prop
, prophlen
);
1514 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1515 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1516 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1517 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1518 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1521 /* create transform */
1522 memcpy(bp
, p
->trns
, trnslen
);
1523 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1524 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1532 * update responder's spi
1535 ipsecdoi_updatespi(iph2
)
1536 phase2_handle_t
*iph2
;
1538 struct prop_pair
**pair
, *p
;
1545 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1548 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1552 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1553 /* multiple transform must be filtered by selectph2proposal.*/
1557 pp
= iph2
->approval
;
1559 /* create proposal payloads */
1560 for (p
= pair
[i
]; p
; p
= p
->next
) {
1562 * find a proposal/transform with matching proto_id/t_id.
1563 * we have analyzed validity already, in cmpsaprop_alloc().
1565 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1566 if (p
->prop
->proto_id
== pr
->proto_id
&&
1567 p
->trns
->t_id
== pr
->head
->trns_id
) {
1575 * XXX SPI bits are left-filled, for use with IPComp.
1576 * we should be switching to variable-length spi field...
1578 spi
= (u_int8_t
*)&pr
->spi
;
1579 spi
+= sizeof(pr
->spi
);
1581 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1586 free_proppair(pair
);
1591 * make a new SA payload from prop_pair.
1594 get_sabysaprop(pp0
, sa0
)
1598 struct prop_pair
**pair
= NULL
;
1599 vchar_t
*newsa
= NULL
;
1601 u_int8_t
*np_p
= NULL
;
1602 struct prop_pair
*p
= NULL
;
1606 int prophlen
, trnslen
;
1610 /* get proposal pair */
1611 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1615 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1616 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1618 if (pair
[pp
->prop_no
] == NULL
)
1621 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1622 newtlen
+= (sizeof(struct isakmp_pl_p
)
1625 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1626 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1627 if (tr
->trns_no
== p
->trns
->t_no
)
1633 newtlen
+= ntohs(p
->trns
->h
.len
);
1638 newsa
= vmalloc(newtlen
);
1639 if (newsa
== NULL
) {
1640 plog(ASL_LEVEL_ERR
, "failed to get newsa.\n");
1645 /* some of values of SA must be updated in the out of this function */
1646 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1647 bp
+= sizeof(struct ipsecdoi_sa_b
);
1649 /* create proposal payloads */
1650 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1652 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1653 prophlen
= sizeof(struct isakmp_pl_p
)
1654 + p
->prop
->spi_size
;
1656 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1657 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1658 if (tr
->trns_no
== p
->trns
->t_no
)
1664 trnslen
= ntohs(p
->trns
->h
.len
);
1667 *np_p
= ISAKMP_NPTYPE_P
;
1669 /* create proposal */
1671 memcpy(bp
, p
->prop
, prophlen
);
1672 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1673 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1674 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1675 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1678 /* create transform */
1679 memcpy(bp
, p
->trns
, trnslen
);
1680 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1681 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1693 if (newsa
!= NULL
) {
1703 * If some error happens then return 0. Although 0 means that lifetime is zero,
1704 * such a value should not be accepted.
1705 * Also 0 of lifebyte should not be included in a packet although 0 means not
1709 ipsecdoi_set_ld(buf
)
1719 ld
= ntohs(*ALIGNED_CAST(u_int16_t
*)buf
->v
);
1722 ld
= ntohl(*ALIGNED_CAST(u_int32_t
*)buf
->v
);
1726 "length %zu of life duration "
1727 "isn't supported.\n", buf
->l
);
1747 "invalid value of DOI 0x%08x.\n", doi
);
1757 check_situation(sit
)
1761 case IPSECDOI_SIT_IDENTITY_ONLY
:
1764 case IPSECDOI_SIT_SECRECY
:
1765 case IPSECDOI_SIT_INTEGRITY
:
1767 "situation 0x%08x unsupported yet.\n", sit
);
1772 "invalid situation 0x%08x.\n", sit
);
1779 * check protocol id in main mode
1782 check_prot_main(proto_id
)
1786 case IPSECDOI_PROTO_ISAKMP
:
1791 "Illegal protocol id=%u.\n", proto_id
);
1798 * check protocol id in quick mode
1801 check_prot_quick(proto_id
)
1805 case IPSECDOI_PROTO_IPSEC_AH
:
1806 case IPSECDOI_PROTO_IPSEC_ESP
:
1809 case IPSECDOI_PROTO_IPCOMP
:
1814 "invalid protocol id %d.\n", proto_id
);
1821 check_spi_size(proto_id
, size
)
1825 case IPSECDOI_PROTO_ISAKMP
:
1828 plog(ASL_LEVEL_WARNING
,
1829 "SPI size isn't zero, but IKE proposal.\n");
1833 case IPSECDOI_PROTO_IPSEC_AH
:
1834 case IPSECDOI_PROTO_IPSEC_ESP
:
1837 "invalid SPI size=%d for IPSEC proposal.\n",
1843 case IPSECDOI_PROTO_IPCOMP
:
1844 if (size
!= 2 && size
!= 4) {
1846 "invalid SPI size=%d for IPCOMP proposal.\n",
1860 * check transform ID in ISAKMP.
1863 check_trns_isakmp(t_id
)
1867 case IPSECDOI_KEY_IKE
:
1871 "invalid transform-id=%u in proto_id=%u.\n",
1872 t_id
, IPSECDOI_KEY_IKE
);
1879 * check transform ID in AH.
1886 case IPSECDOI_AH_MD5
:
1887 case IPSECDOI_AH_SHA
:
1888 case IPSECDOI_AH_SHA256
:
1889 case IPSECDOI_AH_SHA384
:
1890 case IPSECDOI_AH_SHA512
:
1892 case IPSECDOI_AH_DES
:
1894 "not support transform-id=%u in AH.\n", t_id
);
1898 "invalid transform-id=%u in AH.\n", t_id
);
1905 * check transform ID in ESP.
1908 check_trns_esp(t_id
)
1912 case IPSECDOI_ESP_DES
:
1913 case IPSECDOI_ESP_3DES
:
1914 case IPSECDOI_ESP_NULL
:
1915 case IPSECDOI_ESP_RC5
:
1916 case IPSECDOI_ESP_CAST
:
1917 case IPSECDOI_ESP_BLOWFISH
:
1918 case IPSECDOI_ESP_AES
:
1919 case IPSECDOI_ESP_TWOFISH
:
1921 case IPSECDOI_ESP_DES_IV32
:
1922 case IPSECDOI_ESP_DES_IV64
:
1923 case IPSECDOI_ESP_IDEA
:
1924 case IPSECDOI_ESP_3IDEA
:
1925 case IPSECDOI_ESP_RC4
:
1927 "not support transform-id=%u in ESP.\n", t_id
);
1931 "invalid transform-id=%u in ESP.\n", t_id
);
1938 * check transform ID in IPCOMP.
1941 check_trns_ipcomp(t_id
)
1945 case IPSECDOI_IPCOMP_OUI
:
1946 case IPSECDOI_IPCOMP_DEFLATE
:
1947 case IPSECDOI_IPCOMP_LZS
:
1951 "invalid transform-id=%u in IPCOMP.\n", t_id
);
1958 * check data attributes in IKE.
1961 check_attr_isakmp(trns
)
1962 struct isakmp_pl_t
*trns
;
1964 struct isakmp_data
*d
;
1969 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
1970 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
1973 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
1974 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
1975 lorv
= ntohs(d
->lorv
);
1977 plog(ASL_LEVEL_DEBUG
,
1978 "type=%s, flag=0x%04x, lorv=%s\n",
1979 s_oakley_attr(type
), flag
,
1980 s_oakley_attr_v(type
, lorv
));
1983 * some of the attributes must be encoded in TV.
1984 * see RFC2409 Appendix A "Attribute Classes".
1987 case OAKLEY_ATTR_ENC_ALG
:
1988 case OAKLEY_ATTR_HASH_ALG
:
1989 case OAKLEY_ATTR_AUTH_METHOD
:
1990 case OAKLEY_ATTR_GRP_DESC
:
1991 case OAKLEY_ATTR_GRP_TYPE
:
1992 case OAKLEY_ATTR_SA_LD_TYPE
:
1993 case OAKLEY_ATTR_PRF
:
1994 case OAKLEY_ATTR_KEY_LEN
:
1995 case OAKLEY_ATTR_FIELD_SIZE
:
1996 if (!flag
) { /* TLV*/
1998 "oakley attribute %d must be TV.\n",
2005 /* sanity check for TLV. length must be specified. */
2006 if (!flag
&& lorv
== 0) { /*TLV*/
2008 "invalid length %d for TLV attribute %d.\n",
2014 case OAKLEY_ATTR_ENC_ALG
:
2015 if (!alg_oakley_encdef_ok(lorv
)) {
2017 "invalied encryption algorithm=%d.\n",
2023 case OAKLEY_ATTR_HASH_ALG
:
2024 if (!alg_oakley_hashdef_ok(lorv
)) {
2026 "invalied hash algorithm=%d.\n",
2032 case OAKLEY_ATTR_AUTH_METHOD
:
2034 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2035 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2036 #ifdef ENABLE_HYBRID
2037 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2038 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
:
2039 #if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2040 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
:
2042 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
2044 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
2046 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2047 #ifdef ENABLE_HYBRID
2048 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2049 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
2050 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2051 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2052 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
:
2053 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
2054 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
:
2055 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
2056 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
:
2057 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
2059 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2060 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2062 "auth method %s isn't supported.\n",
2063 s_oakley_attr_method(lorv
));
2067 "invalid auth method %d.\n",
2073 case OAKLEY_ATTR_GRP_DESC
:
2074 if (!alg_oakley_dhdef_ok(lorv
)) {
2076 "invalid DH group %d.\n",
2082 case OAKLEY_ATTR_GRP_TYPE
:
2084 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2088 "unsupported DH group type %d.\n",
2094 case OAKLEY_ATTR_GRP_PI
:
2095 case OAKLEY_ATTR_GRP_GEN_ONE
:
2096 /* sanity checks? */
2099 case OAKLEY_ATTR_GRP_GEN_TWO
:
2100 case OAKLEY_ATTR_GRP_CURVE_A
:
2101 case OAKLEY_ATTR_GRP_CURVE_B
:
2103 "attr type=%u isn't supported.\n", type
);
2106 case OAKLEY_ATTR_SA_LD_TYPE
:
2108 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2109 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2113 "invalid life type %d.\n", lorv
);
2118 case OAKLEY_ATTR_SA_LD
:
2119 /* should check the value */
2122 case OAKLEY_ATTR_PRF
:
2123 case OAKLEY_ATTR_KEY_LEN
:
2126 case OAKLEY_ATTR_FIELD_SIZE
:
2128 "attr type=%u isn't supported.\n", type
);
2131 case OAKLEY_ATTR_GRP_ORDER
:
2134 case OAKLEY_ATTR_GSS_ID
:
2139 "invalid attribute type %d.\n", type
);
2145 d
= (struct isakmp_data
*)((char *)d
2148 tlen
-= (sizeof(*d
) + lorv
);
2149 d
= (struct isakmp_data
*)((char *)d
2150 + sizeof(*d
) + lorv
);
2158 * check data attributes in IPSEC AH/ESP.
2162 struct isakmp_pl_t
*trns
;
2164 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2168 check_attr_esp(trns
)
2169 struct isakmp_pl_t
*trns
;
2171 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2175 check_attr_ipsec(proto_id
, trns
)
2177 struct isakmp_pl_t
*trns
;
2179 struct isakmp_data
*d
;
2183 int attrseen
[16]; /* XXX magic number */
2185 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2186 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2187 memset(attrseen
, 0, sizeof(attrseen
));
2190 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2191 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2192 lorv
= ntohs(d
->lorv
);
2194 plog(ASL_LEVEL_DEBUG
,
2195 "type=%s, flag=0x%04x, lorv=%s\n",
2196 s_ipsecdoi_attr(type
), flag
,
2197 s_ipsecdoi_attr_v(type
, lorv
));
2199 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2203 case IPSECDOI_ATTR_ENC_MODE
:
2206 "must be TV when ENC_MODE.\n");
2211 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2212 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2215 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2216 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2217 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2218 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2219 plog(ASL_LEVEL_DEBUG
,
2220 "UDP encapsulation requested\n");
2225 "invalid encryption mode=%u.\n",
2231 case IPSECDOI_ATTR_AUTH
:
2234 "must be TV when AUTH.\n");
2239 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2240 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2241 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2244 "auth algorithm %u conflicts "
2245 "with transform %u.\n",
2250 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2251 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2252 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2256 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2257 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2258 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2262 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2263 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2264 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2268 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2269 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2270 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2274 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2275 case IPSECDOI_ATTR_AUTH_KPDK
:
2277 "auth algorithm %u isn't supported.\n",
2282 "invalid auth algorithm=%u.\n",
2288 case IPSECDOI_ATTR_SA_LD_TYPE
:
2291 "must be TV when LD_TYPE.\n");
2296 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2297 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2301 "invalid life type %d.\n", lorv
);
2306 case IPSECDOI_ATTR_SA_LD
:
2308 /* i.e. ISAKMP_GEN_TV */
2309 plog(ASL_LEVEL_DEBUG
,
2310 "life duration was in TLV.\n");
2312 /* i.e. ISAKMP_GEN_TLV */
2315 "invalid length of LD\n");
2321 case IPSECDOI_ATTR_GRP_DESC
:
2324 "must be TV when GRP_DESC.\n");
2328 if (!alg_oakley_dhdef_ok(lorv
)) {
2330 "invalid group description=%u.\n",
2336 case IPSECDOI_ATTR_KEY_LENGTH
:
2339 "must be TV when KEY_LENGTH.\n");
2344 case IPSECDOI_ATTR_KEY_ROUNDS
:
2345 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2346 case IPSECDOI_ATTR_COMP_PRIVALG
:
2348 "attr type=%u isn't supported.\n", type
);
2353 "invalid attribute type %d.\n", type
);
2359 d
= (struct isakmp_data
*)((char *)d
2362 tlen
-= (sizeof(*d
) + lorv
);
2363 d
= (struct isakmp_data
*)((caddr_t
)d
2364 + sizeof(*d
) + lorv
);
2368 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2369 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2371 "attr AUTH must be present for AH.\n");
2375 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2376 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2377 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2379 "attr AUTH must be present for ESP NULL encryption.\n");
2387 check_attr_ipcomp(trns
)
2388 struct isakmp_pl_t
*trns
;
2390 struct isakmp_data
*d
;
2394 int attrseen
[16]; /* XXX magic number */
2396 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2397 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2398 memset(attrseen
, 0, sizeof(attrseen
));
2401 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2402 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2403 lorv
= ntohs(d
->lorv
);
2405 plog(ASL_LEVEL_DEBUG
,
2406 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2409 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2413 case IPSECDOI_ATTR_ENC_MODE
:
2416 "must be TV when ENC_MODE.\n");
2421 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2422 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2425 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2426 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2427 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2428 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2429 plog(ASL_LEVEL_DEBUG
,
2430 "UDP encapsulation requested\n");
2435 "invalid encryption mode=%u.\n",
2441 case IPSECDOI_ATTR_SA_LD_TYPE
:
2444 "must be TV when LD_TYPE.\n");
2449 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2450 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2454 "invalid life type %d.\n", lorv
);
2459 case IPSECDOI_ATTR_SA_LD
:
2461 /* i.e. ISAKMP_GEN_TV */
2462 plog(ASL_LEVEL_DEBUG
,
2463 "life duration was in TLV.\n");
2465 /* i.e. ISAKMP_GEN_TLV */
2468 "invalid length of LD\n");
2474 case IPSECDOI_ATTR_GRP_DESC
:
2477 "must be TV when GRP_DESC.\n");
2481 if (!alg_oakley_dhdef_ok(lorv
)) {
2483 "invalid group description=%u.\n",
2489 case IPSECDOI_ATTR_AUTH
:
2491 "invalid attr type=%u.\n", type
);
2494 case IPSECDOI_ATTR_KEY_LENGTH
:
2495 case IPSECDOI_ATTR_KEY_ROUNDS
:
2496 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2497 case IPSECDOI_ATTR_COMP_PRIVALG
:
2499 "attr type=%u isn't supported.\n", type
);
2504 "invalid attribute type %d.\n", type
);
2510 d
= (struct isakmp_data
*)((char *)d
2513 tlen
-= (sizeof(*d
) + lorv
);
2514 d
= (struct isakmp_data
*)((caddr_t
)d
2515 + sizeof(*d
) + lorv
);
2520 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2521 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2523 "attr AUTH must be present for AH.\n", type
);
2533 * create phase1 proposal from remote configuration.
2534 * NOT INCLUDING isakmp general header of SA payload
2537 ipsecdoi_setph1proposal (phase1_handle_t
*iph1
)
2542 if (!iph1
) return NULL
;
2544 struct isakmpsa
*props
= iph1
->rmconf
->proposal
;
2545 unsigned int version
= iph1
->version
;
2547 /* count total size of SA minus isakmp general header */
2548 /* not including isakmp general header of SA payload */
2549 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2550 sablen
= sizeof(struct ipsecdoi_sa_b
);
2554 sablen
+= setph1prop(iph1
, NULL
);
2556 mysa
= vmalloc(sablen
);
2559 "failed to allocate my sa buffer\n");
2563 /* create SA payload */
2564 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2565 /* not including isakmp general header */
2566 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2567 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2569 (void)setph1prop(iph1
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2571 (void)setph1prop(iph1
, mysa
->v
);
2578 setph1prop (phase1_handle_t
*iph1
,
2581 struct isakmpsa
*props
= iph1
->rmconf
->proposal
;
2582 unsigned int version
= iph1
->version
;
2584 struct isakmp_pl_p
*prop
= NULL
;
2585 struct isakmpsa
*s
= NULL
;
2586 int proplen
, trnslen
;
2587 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2592 cookie_t
*my_cookie
= (iph1
->side
== INITIATOR
) ? &iph1
->index
.i_ck
: &iph1
->index
.r_ck
;
2595 proplen
= sizeof(*prop
) + spi_size
;
2597 /* create proposal */
2598 prop
= (struct isakmp_pl_p
*)p
;
2599 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2600 prop
->h
.reserved
= 0;
2601 prop
->p_no
= props
->prop_no
;
2602 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2603 prop
->spi_size
= spi_size
;
2610 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2613 *np_t
= ISAKMP_NPTYPE_T
;
2615 trnslen
= setph1trns(s
, p
);
2618 /* save buffer to pre-next payload */
2619 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2622 /* count up transform length */
2628 /* update proposal length */
2630 prop
->h
.len
= htons(proplen
);
2631 prop
->num_t
= trns_num
;
2638 setph1trns (struct isakmpsa
*sa
,
2641 struct isakmp_pl_t
*trns
= NULL
;
2642 int trnslen
, attrlen
;
2645 trnslen
= sizeof(*trns
);
2647 /* create transform */
2648 trns
= (struct isakmp_pl_t
*)p
;
2649 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2650 trns
->t_no
= sa
->trns_no
;
2651 trns
->t_id
= IPSECDOI_KEY_IKE
;
2655 attrlen
= setph1attr(sa
, p
);
2661 trns
->h
.len
= htons(trnslen
);
2667 setph1attr (struct isakmpsa
*sa
,
2674 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2676 attrlen
+= sizeof(struct isakmp_data
)
2677 + sizeof(struct isakmp_data
);
2678 if (sa
->lifetime
> 0xffff)
2679 attrlen
+= sizeof(lifetime
);
2681 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2682 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2683 if (sa
->lifetime
> 0xffff) {
2684 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2688 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2695 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2697 attrlen
+= sizeof(struct isakmp_data
)
2698 + sizeof(struct isakmp_data
);
2699 if (sa
->lifebyte
> 0xffff)
2700 attrlen
+= sizeof(lifebyte
);
2702 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2703 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2704 if (sa
->lifebyte
> 0xffff) {
2705 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2709 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2716 attrlen
+= sizeof(struct isakmp_data
);
2718 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2721 attrlen
+= sizeof(struct isakmp_data
);
2723 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2725 if (sa
->authmethod
) {
2728 #ifdef ENABLE_HYBRID
2729 authmethod
= switch_authmethod(sa
->authmethod
);
2731 authmethod
= sa
->authmethod
;
2733 attrlen
+= sizeof(struct isakmp_data
);
2735 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2738 attrlen
+= sizeof(struct isakmp_data
);
2740 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2742 switch (sa
->dh_group
) {
2743 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2744 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2745 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2746 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2747 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2748 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2749 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2750 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2751 /* don't attach group type for known groups */
2752 attrlen
+= sizeof(struct isakmp_data
);
2754 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2758 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2759 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2760 /* don't attach group type for known groups */
2761 attrlen
+= sizeof(struct isakmp_data
);
2763 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2764 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2776 setph2proposal0(iph2
, pp
, pr
)
2777 const phase2_handle_t
*iph2
;
2778 const struct saprop
*pp
;
2779 const struct saproto
*pr
;
2782 struct isakmp_pl_p
*prop
;
2783 struct isakmp_pl_t
*trns
;
2788 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2789 const u_int8_t
*spi
;
2791 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2795 /* create proposal */
2796 prop
= (struct isakmp_pl_p
*)p
->v
;
2797 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2798 prop
->p_no
= pp
->prop_no
;
2799 prop
->proto_id
= pr
->proto_id
;
2802 spi
= (const u_int8_t
*)&pr
->spi
;
2803 switch (pr
->proto_id
) {
2804 case IPSECDOI_PROTO_IPCOMP
:
2806 * draft-shacham-ippcp-rfc2393bis-05.txt:
2807 * construct 16bit SPI (CPI).
2808 * XXX we may need to provide a configuration option to
2809 * generate 32bit SPI. otherwise we cannot interoeprate
2810 * with nodes that uses 32bit SPI, in case we are initiator.
2812 prop
->spi_size
= sizeof(u_int16_t
);
2813 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2814 p
->l
-= sizeof(pr
->spi
);
2815 p
->l
+= sizeof(u_int16_t
);
2818 prop
->spi_size
= sizeof(pr
->spi
);
2821 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2823 /* create transform */
2824 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2827 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2829 switch (pr
->proto_id
) {
2830 case IPSECDOI_PROTO_IPSEC_ESP
:
2832 * don't build a null encryption
2833 * with no authentication transform.
2835 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2836 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
2842 *np_t
= ISAKMP_NPTYPE_T
;
2846 /* get attribute length */
2849 attrlen
+= sizeof(struct isakmp_data
)
2850 + sizeof(struct isakmp_data
);
2851 if (pp
->lifetime
> 0xffff)
2852 attrlen
+= sizeof(u_int32_t
);
2854 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2855 attrlen
+= sizeof(struct isakmp_data
)
2856 + sizeof(struct isakmp_data
);
2857 if (pp
->lifebyte
> 0xffff)
2858 attrlen
+= sizeof(u_int32_t
);
2860 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2862 attrlen
+= sizeof(struct isakmp_data
);
2864 switch (pr
->proto_id
) {
2865 case IPSECDOI_PROTO_IPSEC_ESP
:
2866 /* non authentication mode ? */
2867 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2868 attrlen
+= sizeof(struct isakmp_data
);
2870 case IPSECDOI_PROTO_IPSEC_AH
:
2871 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2873 "no authentication algorithm found "
2874 "but protocol is AH.\n");
2878 attrlen
+= sizeof(struct isakmp_data
);
2880 case IPSECDOI_PROTO_IPCOMP
:
2884 "invalid protocol: %d\n", pr
->proto_id
);
2889 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2890 attrlen
+= sizeof(struct isakmp_data
);
2892 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2895 prop
= (struct isakmp_pl_p
*)p
->v
;
2897 /* set transform's values */
2898 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2899 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2900 trns
->t_no
= tr
->trns_no
;
2901 trns
->t_id
= tr
->trns_id
;
2903 /* set attributes */
2904 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
2907 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2908 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
2909 if (pp
->lifetime
> 0xffff) {
2910 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
2911 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2912 (caddr_t
)&v
, sizeof(v
));
2914 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2919 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2920 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2921 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
2922 if (pp
->lifebyte
> 0xffff) {
2923 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
2924 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2925 (caddr_t
)&v
, sizeof(v
));
2927 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2932 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
2935 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
2937 /* mandatory check has done above. */
2938 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2939 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
2940 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
2942 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2943 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
2944 iph2
->sainfo
->pfs_group
);
2946 /* update length of this transform. */
2947 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2948 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
2950 /* save buffer to pre-next payload */
2953 trnsoff
+= (sizeof(*trns
) + attrlen
);
2958 "no suitable proposal was created.\n");
2962 /* update length of this protocol. */
2963 prop
->h
.len
= htons(p
->l
);
2970 * create phase2 proposal from policy configuration.
2971 * NOT INCLUDING isakmp general header of SA payload.
2972 * This function is called by initiator only.
2975 ipsecdoi_setph2proposal(phase2_handle_t
*iph2
, int return_sa
)
2977 struct saprop
*proposal
, *a
;
2978 struct saproto
*b
= NULL
;
2979 vchar_t
*q
, *sa
= NULL
;
2980 struct isakmp_pl_p
*prop
;
2981 size_t propoff
; /* for previous field of type of next payload. */
2984 proposal
= iph2
->approval
;
2986 proposal
= iph2
->proposal
;
2988 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2989 struct ipsecdoi_sa_b
*sab
;
2991 sa
= vmalloc(sizeof(*sab
));
2994 "failed to allocate my sa buffer\n");
2998 /* create SA payload */
2999 sab
= ALIGNED_CAST(struct ipsecdoi_sa_b
*)sa
->v
;
3000 sab
->doi
= htonl(IPSEC_DOI
);
3001 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3007 for (a
= proposal
; a
; a
= a
->next
) {
3008 for (b
= a
->head
; b
; b
= b
->next
) {
3009 if (b
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
3010 // %%%%% todo - IKEv2 uses ipcomp notification
3011 // skip this - not specified in the SA
3012 // Need to set this in iph2 ???
3015 // IKEv1 sends encode mode in SA - uses diferent codes when NATT being used
3016 // IKEv2 does not send encode mode in SA
3018 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3019 plog (ASL_LEVEL_INFO
, "NAT detected -> UDP encapsulation\n");
3021 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
3022 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3023 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3024 b
->encmode
+= udp_diff
;
3028 switch (iph2
->version
) {
3029 case ISAKMP_VERSION_NUMBER_IKEV1
:
3030 q
= setph2proposal0(iph2
, a
, b
);
3033 plog(ASL_LEVEL_ERR
, "Invalid IKE version detected\n");
3042 sa
= vrealloc(sa
, sa
->l
+ q
->l
);
3048 "failed to allocate my sa buffer\n");
3053 memcpy(sa
->v
+ sa
->l
- q
->l
, q
->v
, q
->l
);
3055 prop
= (struct isakmp_pl_p
*)(sa
->v
+
3057 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
3058 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3060 propoff
= sa
->l
- q
->l
;
3073 * return 1 if all of the given protocols are tunnel mode.
3076 ipsecdoi_tunnelmode(iph2
)
3077 phase2_handle_t
*iph2
;
3080 struct saproto
*pr
= NULL
;
3082 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
3083 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3084 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
3085 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
3086 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
3095 * return 1 if any of the given protocols are transport mode.
3098 ipsecdoi_any_transportmode(pp
)
3101 struct saproto
*pr
= NULL
;
3103 for (; pp
; pp
= pp
->next
) {
3104 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3105 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TRNS
||
3106 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
||
3107 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
3116 * return 1 if all of the given protocols are transport mode.
3119 ipsecdoi_transportmode(pp
)
3122 struct saproto
*pr
= NULL
;
3124 for (; pp
; pp
= pp
->next
) {
3125 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3126 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
3135 ipsecdoi_get_defaultlifetime()
3137 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3141 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3142 int proto_id
, enc
, auth
, comp
;
3144 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3146 case IPSECDOI_PROTO_IPSEC_ESP
:
3147 if (enc
== 0 || comp
!= 0) {
3149 "illegal algorithm defined "
3150 "ESP enc=%s auth=%s comp=%s.\n",
3151 TMPALGTYPE2STR(enc
),
3152 TMPALGTYPE2STR(auth
),
3153 TMPALGTYPE2STR(comp
));
3157 case IPSECDOI_PROTO_IPSEC_AH
:
3158 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3160 "illegal algorithm defined "
3161 "AH enc=%s auth=%s comp=%s.\n",
3162 TMPALGTYPE2STR(enc
),
3163 TMPALGTYPE2STR(auth
),
3164 TMPALGTYPE2STR(comp
));
3168 case IPSECDOI_PROTO_IPCOMP
:
3169 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3171 "illegal algorithm defined "
3172 "IPcomp enc=%s auth=%s comp=%s.\n",
3173 TMPALGTYPE2STR(enc
),
3174 TMPALGTYPE2STR(auth
),
3175 TMPALGTYPE2STR(comp
));
3181 "invalid ipsec protocol %d\n", proto_id
);
3184 #undef TMPALGTYPE2STR
3194 return IPSECDOI_PROTO_IPSEC_AH
;
3196 return IPSECDOI_PROTO_IPSEC_ESP
;
3197 case IPPROTO_IPCOMP
:
3198 return IPSECDOI_PROTO_IPCOMP
;
3200 return -1; /* XXX */
3208 case IPSECDOI_PROTO_IPSEC_AH
:
3210 case IPSECDOI_PROTO_IPSEC_ESP
:
3212 case IPSECDOI_PROTO_IPCOMP
:
3213 return IPPROTO_IPCOMP
;
3215 return -1; /* XXX */
3219 * Check if a subnet id is valid for comparison
3220 * with an address id ( address length mask )
3228 ipsecdoi_subnetisaddr_v4( subnet
, address
)
3229 const vchar_t
*subnet
;
3230 const vchar_t
*address
;
3232 struct in_addr
*mask
;
3234 if (address
->l
!= sizeof(struct in_addr
))
3237 if (subnet
->l
!= (sizeof(struct in_addr
)*2))
3240 mask
= ALIGNED_CAST(struct in_addr
*)(subnet
->v
+ sizeof(struct in_addr
));
3242 if (mask
->s_addr
!=0xffffffff)
3245 return memcmp(subnet
->v
,address
->v
,address
->l
);
3251 ipsecdoi_subnetisaddr_v6( subnet
, address
)
3252 const vchar_t
*subnet
;
3253 const vchar_t
*address
;
3255 struct in6_addr
*mask
;
3258 if (address
->l
!= sizeof(struct in6_addr
))
3261 if (subnet
->l
!= (sizeof(struct in6_addr
)*2))
3264 mask
= ALIGNED_CAST(struct in6_addr
*)(subnet
->v
+ sizeof(struct in6_addr
));
3266 for (i
=0; i
<16; i
++)
3267 if(mask
->s6_addr
[i
]!=0xff)
3270 return memcmp(subnet
->v
,address
->v
,address
->l
);
3277 * Check and Compare two IDs
3278 * - specify 0 for exact if wildcards are allowed
3282 * = -1 for integrity error
3286 ipsecdoi_chkcmpids( idt
, ids
, exact
)
3287 const vchar_t
*idt
; /* id cmp target */
3288 const vchar_t
*ids
; /* id cmp source */
3291 struct ipsecdoi_id_b
*id_bt
;
3292 struct ipsecdoi_id_b
*id_bs
;
3297 /* handle wildcard IDs */
3299 if (idt
== NULL
|| ids
== NULL
)
3303 plog(ASL_LEVEL_DEBUG
,
3304 "check and compare ids : values matched (ANONYMOUS)\n" );
3309 plog(ASL_LEVEL_DEBUG
,
3310 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3315 /* make sure the ids are of the same type */
3317 id_bt
= (struct ipsecdoi_id_b
*) idt
->v
;
3318 id_bs
= (struct ipsecdoi_id_b
*) ids
->v
;
3320 ident_t
.v
= idt
->v
+ sizeof(*id_bt
);
3321 ident_t
.l
= idt
->l
- sizeof(*id_bt
);
3322 ident_s
.v
= ids
->v
+ sizeof(*id_bs
);
3323 ident_s
.l
= ids
->l
- sizeof(*id_bs
);
3325 if (id_bs
->type
!= id_bt
->type
)
3328 * special exception for comparing
3329 * address to subnet id types when
3330 * the netmask is address length
3333 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR
)&&
3334 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)) {
3335 result
= ipsecdoi_subnetisaddr_v4(&ident_t
,&ident_s
);
3339 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)&&
3340 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR
)) {
3341 result
= ipsecdoi_subnetisaddr_v4(&ident_s
,&ident_t
);
3346 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR
)&&
3347 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)) {
3348 result
= ipsecdoi_subnetisaddr_v6(&ident_t
,&ident_s
);
3352 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)&&
3353 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR
)) {
3354 result
= ipsecdoi_subnetisaddr_v6(&ident_s
,&ident_t
);
3358 plog(ASL_LEVEL_DEBUG
,
3359 "check and compare ids : id type mismatch %s != %s\n",
3360 s_ipsecdoi_ident(id_bs
->type
),
3361 s_ipsecdoi_ident(id_bt
->type
));
3366 if(id_bs
->proto_id
!= id_bt
->proto_id
){
3367 plog(ASL_LEVEL_DEBUG
,
3368 "check and compare ids : proto_id mismatch %d != %d\n",
3369 id_bs
->proto_id
, id_bt
->proto_id
);
3374 /* compare the ID data. */
3376 switch (id_bt
->type
) {
3377 case IPSECDOI_ID_DER_ASN1_DN
:
3378 case IPSECDOI_ID_DER_ASN1_GN
:
3379 /* compare asn1 ids */
3380 result
= eay_cmp_asn1dn(&ident_t
, &ident_s
);
3383 case IPSECDOI_ID_IPV4_ADDR
:
3384 /* validate lengths */
3385 if ((ident_t
.l
!= sizeof(struct in_addr
))||
3386 (ident_s
.l
!= sizeof(struct in_addr
)))
3390 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3391 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3392 /* validate lengths */
3393 if ((ident_t
.l
!= (sizeof(struct in_addr
)*2))||
3394 (ident_s
.l
!= (sizeof(struct in_addr
)*2)))
3399 case IPSECDOI_ID_IPV6_ADDR
:
3400 /* validate lengths */
3401 if ((ident_t
.l
!= sizeof(struct in6_addr
))||
3402 (ident_s
.l
!= sizeof(struct in6_addr
)))
3406 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3407 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3408 /* validate lengths */
3409 if ((ident_t
.l
!= (sizeof(struct in6_addr
)*2))||
3410 (ident_s
.l
!= (sizeof(struct in6_addr
)*2)))
3414 case IPSECDOI_ID_FQDN
:
3415 case IPSECDOI_ID_USER_FQDN
:
3416 case IPSECDOI_ID_KEY_ID
:
3421 "Unhandled id type %i specified for comparison\n",
3426 /* validate matching data and length */
3427 if (ident_t
.l
== ident_s
.l
)
3428 result
= memcmp(ident_t
.v
,ident_s
.v
,ident_t
.l
);
3434 /* debug level output */
3435 if(loglevel
>= ASL_LEVEL_DEBUG
) {
3436 char *idstrt
= ipsecdoi_id2str(idt
);
3437 char *idstrs
= ipsecdoi_id2str(ids
);
3440 plog(ASL_LEVEL_DEBUG
,
3441 "check and compare ids : values matched (%s)\n",
3442 s_ipsecdoi_ident(id_bs
->type
) );
3444 plog(ASL_LEVEL_DEBUG
,
3445 "check and compare ids : value mismatch (%s)\n",
3446 s_ipsecdoi_ident(id_bs
->type
));
3448 plog(ASL_LEVEL_DEBUG
, "cmpid target: \'%s\'\n", idstrt
);
3449 plog(ASL_LEVEL_DEBUG
, "cmpid source: \'%s\'\n", idstrs
);
3451 racoon_free(idstrs
);
3452 racoon_free(idstrt
);
3463 /* id integrity error */
3464 plog(ASL_LEVEL_DEBUG
, "check and compare ids : %s integrity error\n",
3465 s_ipsecdoi_ident(id_bs
->type
));
3466 plog(ASL_LEVEL_DEBUG
, "cmpid target: length = \'%zu\'\n", ident_t
.l
);
3467 plog(ASL_LEVEL_DEBUG
, "cmpid source: length = \'%zu\'\n", ident_s
.l
);
3474 * check the following:
3475 * - In main mode with pre-shared key, only address type can be used.
3476 * - if proper type for phase 1 ?
3477 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3478 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3479 * - if ID payload sent from peer is equal to the ID expected by me.
3481 * both of "id" and "id_p" should be ID payload without general header,
3484 ipsecdoi_checkid1(iph1
)
3485 phase1_handle_t
*iph1
;
3487 struct ipsecdoi_id_b
*id_b
;
3488 struct sockaddr_storage
*sa
;
3491 if (iph1
->id_p
== NULL
) {
3493 "invalid iph1 passed id_p == NULL\n");
3494 return ISAKMP_INTERNAL_ERROR
;
3496 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3498 "invalid value passed as \"ident\" (len=%lu)\n",
3499 (u_long
)iph1
->id_p
->l
);
3500 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3503 id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3505 /* In main mode with pre-shared key, only address type can be used.
3506 * If NAT Traversal being used and peer is behind nat and
3507 * natt version = 02 - allow non-address ID type.
3509 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
3510 && iph1
->etype
== ISAKMP_ETYPE_IDENT
3511 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3513 && (iph1
->natt_flags
& NAT_DETECTED_PEER
) == 0
3516 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3517 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3519 "Expecting IP address type in main mode, "
3520 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3521 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3525 /* if proper type for phase 1 ? */
3526 switch (id_b
->type
) {
3527 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3528 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3529 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3530 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3531 plog(ASL_LEVEL_WARNING
,
3532 "such ID type %s is not proper.\n",
3533 s_ipsecdoi_ident(id_b
->type
));
3537 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3538 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
||
3539 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3541 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3542 plog(ASL_LEVEL_WARNING
,
3543 "protocol ID and Port mismatched. "
3544 "proto_id:%d port:%d\n",
3545 id_b
->proto_id
, ntohs(id_b
->port
));
3548 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3550 * copmaring with expected port.
3551 * always permit if port is equal to PORT_ISAKMP
3553 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3557 switch (iph1
->remote
->ss_family
) {
3559 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3563 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3568 "invalid family: %d\n",
3569 iph1
->remote
->ss_family
);
3570 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3572 if (ntohs(id_b
->port
) != port
) {
3573 plog(ASL_LEVEL_WARNING
,
3574 "port %d expected, but %d\n",
3575 port
, ntohs(id_b
->port
));
3582 /* compare with the ID if specified. */
3583 if (genlist_next(iph1
->rmconf
->idvl_p
, 0)) {
3584 vchar_t
*ident0
= NULL
;
3589 struct genlist_entry
*gpb
;
3591 for (id
= genlist_next (iph1
->rmconf
->idvl_p
, &gpb
); id
; id
= genlist_next (0, &gpb
)) {
3592 /* check the type of both IDs */
3593 if (id
->idtype
!= doi2idtype(id_b
->type
))
3594 continue; /* ID type mismatch */
3598 /* compare defined ID with the ID sent by peer. */
3601 ident0
= getidval(id
->idtype
, id
->id
);
3603 switch (id
->idtype
) {
3606 ident
.v
= iph1
->id_p
->v
+ sizeof(*id_b
);
3607 ident
.l
= iph1
->id_p
->l
- sizeof(*id_b
);
3608 if (eay_cmp_asn1dn(ident0
, &ident
) == 0)
3611 plog(ASL_LEVEL_WARNING
, "ASN1DN ID matching not implemented - passed.\n");
3612 goto matched
; //%%%%%% hack for now until we have code to do this.
3615 case IDTYPE_ADDRESS
:
3616 sa
= ALIGNED_CAST(struct sockaddr_storage
*)ident0
->v
;
3617 sa2
= (caddr_t
)(id_b
+ 1);
3618 switch (sa
->ss_family
) {
3620 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3621 continue; /* ID value mismatch */
3622 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3623 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) == 0)
3628 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3629 continue; /* ID value mismatch */
3630 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3631 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) == 0)
3640 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
) == 0)
3645 if (ident0
!= NULL
) {
3649 plog(ASL_LEVEL_DEBUG
, "No ID match.\n");
3650 if (iph1
->rmconf
->verify_identifier
)
3651 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3652 matched
: /* ID value match */
3660 /* HACK!!! - temporary until this prototype gets moved */
3661 extern CFDataRef
SecCertificateCopySubjectSequence( SecCertificateRef certificate
);
3664 * create ID payload for phase 1 and set into iph1->id.
3665 * NOT INCLUDING isakmp general header.
3666 * see, RFC2407 4.6.2.1
3669 ipsecdoi_setid1(iph1
)
3670 phase1_handle_t
*iph1
;
3672 vchar_t
*ret
= NULL
;
3673 struct ipsecdoi_id_b id_b
;
3674 vchar_t
*ident
= NULL
;
3675 struct sockaddr_storage
*ipid
= NULL
;
3678 bzero(&id_b
, sizeof(id_b
));
3680 switch (iph1
->rmconf
->idvtype
) {
3682 id_b
.type
= IPSECDOI_ID_FQDN
;
3683 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3685 case IDTYPE_USERFQDN
:
3686 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3687 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3690 case IDTYPE_KEYIDUSE
:
3691 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3692 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3695 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3696 if (iph1
->rmconf
->idv
) {
3697 /* XXX it must be encoded to asn1dn. */
3698 ident
= vdup(iph1
->rmconf
->idv
);
3700 if (oakley_getmycert(iph1
) < 0) {
3702 "failed to get own CERT.\n");
3706 SecCertificateRef certificate
;
3711 certificate
= crypto_cssm_x509cert_CreateSecCertificateRef(&iph1
->cert
->cert
);
3712 if (certificate
== NULL
) {
3714 "failed to get SecCertificateRef\n");
3717 subject
= crypto_cssm_CopySubjectSequence(certificate
);
3718 if (subject
== NULL
) {
3720 "failed to get subjectName\n");
3721 CFRelease(certificate
);
3724 len
= CFDataGetLength(subject
);
3725 namePtr
= (UInt8
*)CFDataGetBytePtr(subject
);
3726 ident
= vmalloc(len
);
3727 if (ident
== NULL
) {
3729 "failed to get subjectName\n");
3730 CFRelease(certificate
);
3734 memcpy(ident
->v
, namePtr
, len
);
3735 CFRelease(certificate
);
3739 case IDTYPE_ADDRESS
:
3741 * if the value of the id type was set by the configuration
3742 * file, then use it. otherwise the value is get from local
3743 * ip address by using ike negotiation.
3745 if (iph1
->rmconf
->idv
)
3746 ipid
= ALIGNED_CAST(struct sockaddr_storage
*)iph1
->rmconf
->idv
->v
;
3756 /* use IP address */
3757 switch (ipid
->ss_family
) {
3759 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3760 l
= sizeof(struct in_addr
);
3761 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3765 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3766 l
= sizeof(struct in6_addr
);
3767 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3772 "invalid address family.\n");
3775 if(iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
){
3776 id_b
.proto_id
= IPPROTO_UDP
;
3777 id_b
.port
= htons(PORT_ISAKMP
);
3783 "failed to get ID buffer.\n");
3786 memcpy(ident
->v
, p
, ident
->l
);
3791 "failed to get ID buffer.\n");
3795 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3798 "failed to get ID buffer.\n");
3802 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3803 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3807 plogdump(ASL_LEVEL_DEBUG
, iph1
->id
->v
, iph1
->id
->l
, "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3815 plog(ASL_LEVEL_ERR
, "failed get my ID\n");
3824 vchar_t
*new = NULL
;
3828 else if (lcconf
->ident
[type
])
3829 new = vdup(lcconf
->ident
[type
]);
3834 /* it's only called by cfparse.y. */
3836 set_identifier(vpp
, type
, value
)
3837 vchar_t
**vpp
, *value
;
3840 return set_identifier_qual(vpp
, type
, value
, IDQUAL_UNSPEC
);
3844 set_identifier_qual(vpp
, type
, value
, qual
)
3845 vchar_t
**vpp
, *value
;
3849 vchar_t
*new = NULL
;
3851 /* simply return if value is null. */
3853 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3855 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3863 case IDTYPE_USERFQDN
:
3866 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3869 case IDTYPE_KEYIDUSE
:
3870 #ifdef ENABLE_HYBRID
3873 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3874 new = vmalloc(value
->l
- 1);
3877 memcpy(new->v
, value
->v
, new->l
);
3881 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3882 * to use a file for backward compatibility sake.
3886 case IDQUAL_UNSPEC
: {
3891 fp
= fopen(value
->v
, "r");
3894 "can not open %s\n", value
->v
);
3898 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3899 new = vrealloc(new, tlen
+ len
);
3904 memcpy(new->v
+ tlen
, b
, len
);
3912 new = vmalloc(value
->l
- 1);
3915 "can not allocate memory");
3918 memcpy(new->v
, value
->v
, new->l
);
3923 "unknown qualifier");
3928 case IDTYPE_ADDRESS
: {
3929 struct sockaddr_storage
*sa
;
3931 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3935 sa
= str2saddr(value
->v
, NULL
);
3938 "invalid ip address %s\n", value
->v
);
3942 new = vmalloc(sysdep_sa_len((struct sockaddr
*)sa
));
3947 memcpy(new->v
, sa
, new->l
);
3952 plog(ASL_LEVEL_DEBUG
, "Setting ID type ASN1DN from string not supported\n");
3964 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3965 * NOT INCLUDING isakmp general header.
3966 * this function is for initiator. responder will get to copy from payload.
3967 * responder ID type is always address type.
3968 * see, RFC2407 4.6.2.1
3971 ipsecdoi_setid2(iph2
)
3972 phase2_handle_t
*iph2
;
3974 struct secpolicy
*sp
;
3976 /* check there is phase 2 handler ? */
3977 sp
= getspbyspid(iph2
->spid
);
3980 "no policy found for spid:%u.\n", iph2
->spid
);
3984 iph2
->id
= ipsecdoi_sockaddr2id(&sp
->spidx
.src
,
3985 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
3986 if (iph2
->id
== NULL
) {
3988 "failed to get ID for %s\n",
3989 spidx2str(&sp
->spidx
));
3993 if (((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR
||
3994 (ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
) &&
3995 iph2
->side
== RESPONDER
&&
3996 iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED_ME
) &&
3997 lcconf
->ext_nat_id
) {
3999 if (!(iph2
->id
= vdup(lcconf
->ext_nat_id
))) {
4004 plogdump(ASL_LEVEL_DEBUG
, iph2
->id
->v
, iph2
->id
->l
, "use local ID type %s\n",
4005 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
4008 iph2
->id_p
= ipsecdoi_sockaddr2id(&sp
->spidx
.dst
,
4009 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
4010 if (iph2
->id_p
== NULL
) {
4012 "failed to get ID for %s\n",
4013 spidx2str(&sp
->spidx
));
4017 plogdump(ASL_LEVEL_DEBUG
, iph2
->id
->v
, iph2
->id
->l
, "use remote ID type %s\n",
4018 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
4024 * set address type of ID.
4025 * NOT INCLUDING general header.
4028 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
4029 struct sockaddr_storage
*saddr
;
4034 int type
, len1
, len2
;
4039 * Q. When type is SUBNET, is it allowed to be ::1/128.
4040 * A. Yes. (consensus at bake-off)
4042 switch (saddr
->ss_family
) {
4044 len1
= sizeof(struct in_addr
);
4045 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
4046 type
= IPSECDOI_ID_IPV4_ADDR
;
4049 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
4050 len2
= sizeof(struct in_addr
);
4052 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
4053 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
4057 len1
= sizeof(struct in6_addr
);
4058 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
4059 type
= IPSECDOI_ID_IPV6_ADDR
;
4062 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
4063 len2
= sizeof(struct in6_addr
);
4065 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
4066 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
4071 "invalid family: %d.\n", saddr
->ss_family
);
4076 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4079 "failed to get ID buffer.\n");
4083 memset(new->v
, 0, new->l
);
4085 /* set the part of header. */
4086 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4088 /* set ul_proto and port */
4090 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4091 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4093 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4094 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4095 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4096 port
== IPSEC_PORT_ANY
? 0 : port
;
4097 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
4103 u_char
*p
= (unsigned char *) new->v
+
4104 sizeof(struct ipsecdoi_id_b
) + len1
;
4105 u_int bits
= prefixlen
;
4113 *p
= ~((1 << (8 - bits
)) - 1);
4120 ipsecdoi_sockrange2id(laddr
, haddr
, ul_proto
)
4121 struct sockaddr_storage
*laddr
, *haddr
;
4125 int type
, len1
, len2
;
4128 if (laddr
->ss_family
!= haddr
->ss_family
) {
4129 plog(ASL_LEVEL_ERR
, "Address family mismatch\n");
4133 switch (laddr
->ss_family
) {
4135 type
= IPSECDOI_ID_IPV4_ADDR_RANGE
;
4136 len1
= sizeof(struct in_addr
);
4137 len2
= sizeof(struct in_addr
);
4141 type
= IPSECDOI_ID_IPV6_ADDR_RANGE
;
4142 len1
= sizeof(struct in6_addr
);
4143 len2
= sizeof(struct in6_addr
);
4148 "invalid family: %d.\n", laddr
->ss_family
);
4153 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4156 "failed to get ID buffer.\n");
4160 memset(new->v
, 0, new->l
);
4161 /* set the part of header. */
4162 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4164 /* set ul_proto and port */
4166 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4167 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4169 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4170 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4171 port
= ((struct sockaddr_in
*)(laddr
))->sin_port
;
4172 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4173 port
== IPSEC_PORT_ANY
? 0 : port
;
4174 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
),
4175 (caddr_t
)&((struct sockaddr_in
*)(laddr
))->sin_addr
,
4177 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
,
4178 (caddr_t
)&((struct sockaddr_in
*)haddr
)->sin_addr
,
4185 * create sockaddr_storage structure from ID payload (buf).
4186 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4187 * see, RFC2407 4.6.2.1
4190 ipsecdoi_id2sockaddr(vchar_t
*buf
,
4191 struct sockaddr_storage
*saddr
,
4192 u_int8_t
*prefixlen
,
4193 u_int16_t
*ul_proto
,
4196 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)buf
->v
;
4200 * When a ID payload of subnet type with a IP address of full bit
4201 * masked, it has to be processed as host address.
4202 * e.g. below 2 type are same.
4203 * type = ipv6 subnet, data = 2001::1/128
4204 * type = ipv6 address, data = 2001::1
4206 switch (id_b
->type
) {
4207 case IPSECDOI_ID_IPV4_ADDR
:
4208 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4209 saddr
->ss_len
= sizeof(struct sockaddr_in
);
4210 saddr
->ss_family
= AF_INET
;
4211 ((struct sockaddr_in
*)saddr
)->sin_port
=
4214 : id_b
->port
); /* see sockaddr2id() */
4215 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
4216 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4219 case IPSECDOI_ID_IPV6_ADDR
:
4220 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4221 saddr
->ss_len
= sizeof(struct sockaddr_in6
);
4222 saddr
->ss_family
= AF_INET6
;
4223 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
4226 : id_b
->port
); /* see sockaddr2id() */
4227 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
4228 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4233 "unsupported ID type %d\n", id_b
->type
);
4234 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
4237 /* get prefix length */
4238 switch (id_b
->type
) {
4239 case IPSECDOI_ID_IPV4_ADDR
:
4240 plen
= sizeof(struct in_addr
) << 3;
4243 case IPSECDOI_ID_IPV6_ADDR
:
4244 plen
= sizeof(struct in6_addr
) << 3;
4247 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4249 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4254 int alen
= sizeof(struct in_addr
);
4256 switch (id_b
->type
) {
4257 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4258 alen
= sizeof(struct in_addr
);
4261 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4262 alen
= sizeof(struct in6_addr
);
4269 return ISAKMP_INTERNAL_ERROR
;
4271 /* get subnet mask length */
4275 p
= (unsigned char *) buf
->v
4276 + sizeof(struct ipsecdoi_id_b
)
4279 for (; *p
== 0xff; p
++) {
4302 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
4303 *ul_proto
= id_b
->proto_id
== 0 ? IPSEC_ULPROTO_ANY
: id_b
->proto_id
; /* see sockaddr2id() */
4310 * make printable string from ID payload except of general header.
4320 static char buf
[BUFLEN
];
4321 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)id
->v
;
4322 struct sockaddr_storage saddr
;
4325 bzero(&saddr
, sizeof(saddr
));
4327 switch (id_b
->type
) {
4328 case IPSECDOI_ID_IPV4_ADDR
:
4329 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4330 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4332 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4333 saddr
.ss_family
= AF_INET
;
4334 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4335 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4336 id
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4339 case IPSECDOI_ID_IPV6_ADDR
:
4340 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4341 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4342 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4343 saddr
.ss_family
= AF_INET6
;
4344 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4345 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4346 id
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4347 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4348 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4349 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4355 switch (id_b
->type
) {
4356 case IPSECDOI_ID_IPV4_ADDR
:
4358 case IPSECDOI_ID_IPV6_ADDR
:
4360 len
= snprintf( buf
, sizeof(buf
), "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4363 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4365 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4370 int alen
= sizeof(struct in_addr
);
4372 switch (id_b
->type
) {
4373 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4374 alen
= sizeof(struct in_addr
);
4377 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4378 alen
= sizeof(struct in6_addr
);
4389 /* get subnet mask length */
4393 p
= (unsigned char *) id
->v
4394 + sizeof(struct ipsecdoi_id_b
)
4397 for (; *p
== 0xff; p
++) {
4416 len
= snprintf( buf
, sizeof(buf
), "%s/%i", saddrwop2str((struct sockaddr
*)&saddr
), plen
);
4420 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4422 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4424 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4425 saddr
.ss_family
= AF_INET
;
4426 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4427 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4428 id
->v
+ sizeof(*id_b
) + sizeof(struct in_addr
),
4429 sizeof(struct in_addr
));
4432 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4438 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4440 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4442 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4443 saddr
.ss_family
= AF_INET6
;
4444 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4445 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4446 id
->v
+ sizeof(*id_b
) + sizeof(struct in6_addr
),
4447 sizeof(struct in6_addr
));
4448 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4449 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4450 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4454 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4460 case IPSECDOI_ID_FQDN
:
4461 case IPSECDOI_ID_USER_FQDN
:
4462 len
= id
->l
- sizeof(*id_b
);
4465 memcpy(buf
, id
->v
+ sizeof(*id_b
), len
);
4468 case IPSECDOI_ID_DER_ASN1_DN
:
4469 case IPSECDOI_ID_DER_ASN1_GN
:
4472 X509_NAME
*xn
= NULL
;
4475 dat
= id
->v
+ sizeof(*id_b
);
4476 len
= id
->l
- sizeof(*id_b
);
4478 if (d2i_X509_NAME(&xn
, (void*) &dat
, len
) != NULL
) {
4479 BIO
*bio
= BIO_new(BIO_s_mem());
4480 X509_NAME_print_ex(bio
, xn
, 0, 0);
4481 len
= BIO_get_mem_data(bio
, &dat
);
4484 memcpy(buf
,dat
,len
);
4492 "unable to extract asn1dn from id\n");
4494 len
= snprintf(buf
, sizeof(buf
), "<ASN1-DN>");
4500 /* currently unhandled id types */
4501 case IPSECDOI_ID_KEY_ID
:
4502 len
= snprintf( buf
, sizeof(buf
), "<KEY-ID>");
4507 "unknown ID type %d\n", id_b
->type
);
4511 len
= snprintf( buf
, sizeof(buf
), "<?>");
4513 ret
= racoon_malloc(len
+1);
4515 memcpy(ret
,buf
,len
);
4523 * set IPsec data attributes into a proposal.
4524 * NOTE: MUST called per a transform.
4527 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4528 struct isakmp_pl_t
*t
;
4533 struct isakmp_data
*d
, *prev
;
4539 tr
->trns_no
= t
->t_no
;
4540 tr
->trns_id
= t
->t_id
;
4542 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4543 prev
= (struct isakmp_data
*)NULL
;
4544 d
= (struct isakmp_data
*)(t
+ 1);
4547 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4548 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4550 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4554 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4555 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4557 plog(ASL_LEVEL_DEBUG
,
4558 "type=%s, flag=0x%04x, lorv=%s\n",
4559 s_ipsecdoi_attr(type
), flag
,
4560 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4563 case IPSECDOI_ATTR_SA_LD_TYPE
:
4565 int type
= ntohs(d
->lorv
);
4567 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4568 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4572 plog(ASL_LEVEL_WARNING
,
4573 "invalid life duration type. "
4575 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4580 case IPSECDOI_ATTR_SA_LD
:
4582 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4583 IPSECDOI_ATTR_SA_LD_TYPE
) {
4585 "life duration must follow ltype\n");
4591 vchar_t
*ld_buf
= NULL
;
4594 /* i.e. ISAKMP_GEN_TV */
4595 ld_buf
= vmalloc(sizeof(d
->lorv
));
4596 if (ld_buf
== NULL
) {
4598 "failed to get LD buffer.\n");
4601 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4603 int len
= ntohs(d
->lorv
);
4604 /* i.e. ISAKMP_GEN_TLV */
4605 ld_buf
= vmalloc(len
);
4606 if (ld_buf
== NULL
) {
4608 "failed to get LD buffer.\n");
4611 memcpy(ld_buf
->v
, d
+ 1, len
);
4614 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4615 t
= ipsecdoi_set_ld(ld_buf
);
4619 "invalid life duration.\n");
4622 /* lifetime must be equal in a proposal. */
4623 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4625 else if (pp
->lifetime
!= t
) {
4627 "lifetime mismatched "
4629 "prev:%ld curr:%u.\n",
4630 (long)pp
->lifetime
, t
);
4634 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4635 t
= ipsecdoi_set_ld(ld_buf
);
4639 "invalid life duration.\n");
4642 /* lifebyte must be equal in a proposal. */
4643 if (pp
->lifebyte
== 0)
4645 else if (pp
->lifebyte
!= t
) {
4647 "lifebyte mismatched "
4649 "prev:%d curr:%u.\n",
4657 "invalid life type: %d\n", life_t
);
4663 case IPSECDOI_ATTR_GRP_DESC
:
4665 * RFC2407: 4.5 IPSEC Security Association Attributes
4666 * Specifies the Oakley Group to be used in a PFS QM
4667 * negotiation. For a list of supported values, see
4668 * Appendix A of [IKE].
4670 if (pp
->pfs_group
== 0)
4671 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4672 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4674 "pfs_group mismatched "
4675 "in a proposal.\n");
4680 case IPSECDOI_ATTR_ENC_MODE
:
4682 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4684 "multiple encmode exist "
4685 "in a transform.\n");
4688 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4691 case IPSECDOI_ATTR_AUTH
:
4692 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4694 "multiple authtype exist "
4695 "in a transform.\n");
4698 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4701 case IPSECDOI_ATTR_KEY_LENGTH
:
4702 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4704 "key length defined but not ESP");
4707 tr
->encklen
= ntohs(d
->lorv
);
4710 case IPSECDOI_ATTR_KEY_ROUNDS
:
4711 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4712 case IPSECDOI_ATTR_COMP_PRIVALG
:
4720 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4722 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4723 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4733 ipsecdoi_authalg2trnsid(alg
)
4737 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4738 return IPSECDOI_AH_MD5
;
4739 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4740 return IPSECDOI_AH_SHA
;
4741 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4742 return IPSECDOI_AH_SHA256
;
4743 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4744 return IPSECDOI_AH_SHA384
;
4745 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4746 return IPSECDOI_AH_SHA512
;
4747 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4748 return IPSECDOI_AH_DES
;
4749 case IPSECDOI_ATTR_AUTH_KPDK
:
4750 return IPSECDOI_AH_MD5
; /* XXX */
4753 "invalid authentication algorithm:%d\n", alg
);
4758 static int rm_idtype2doi
[] = {
4759 255, /* IDTYPE_UNDEFINED, 0 */
4760 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4761 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4762 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4763 255, /* IDTYPE_ADDRESS, 4
4764 * it expands into 4 types by another function. */
4765 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4769 * convert idtype to DOI value.
4777 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4778 return rm_idtype2doi
[idtype
];
4787 case IPSECDOI_ID_FQDN
:
4788 return(IDTYPE_FQDN
);
4789 case IPSECDOI_ID_USER_FQDN
:
4790 return(IDTYPE_USERFQDN
);
4791 case IPSECDOI_ID_KEY_ID
:
4792 return(IDTYPE_KEYID
);
4793 case IPSECDOI_ID_DER_ASN1_DN
:
4794 return(IDTYPE_ASN1DN
);
4795 case IPSECDOI_ID_IPV4_ADDR
:
4796 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4797 case IPSECDOI_ID_IPV6_ADDR
:
4798 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4799 return(IDTYPE_ADDRESS
);
4801 plog(ASL_LEVEL_WARNING
,
4802 "Inproper idtype:%s in this function.\n",
4803 s_ipsecdoi_ident(doi
));
4804 return(IDTYPE_ADDRESS
); /* XXX */
4809 #ifdef ENABLE_HYBRID
4811 switch_authmethod(authmethod
)
4814 switch(authmethod
) {
4815 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
4816 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
;
4818 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
4819 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
;
4821 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
4822 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
;
4824 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
4825 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
;
4827 /* Those are not implemented */
4828 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
4829 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
;
4831 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
4832 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
;
4834 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
4835 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
;