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>
37 #include <arpa/inet.h>
39 #include <netinet/in.h>
41 #ifndef HAVE_NETINET6_IPSEC
42 #include <netinet/ipsec.h>
44 #include <netinet6/ipsec.h>
52 #if TIME_WITH_SYS_TIME
53 # include <sys/time.h>
57 # include <sys/time.h>
69 #include "cfparse_proto.h"
70 #include "isakmp_var.h"
72 #include "ipsec_doi.h"
74 #include "remoteconf.h"
75 #include "localconf.h"
79 #include "algorithm.h"
82 #include "crypto_openssl.h"
83 #include "crypto_cssm.h"
88 #include "nattraversal.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 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_ah (struct isakmp_pl_t
*);
136 static int check_attr_esp (struct isakmp_pl_t
*);
137 static int (*check_attributes
[]) (struct isakmp_pl_t
*) = {
139 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
140 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
141 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
142 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
145 int setph1prop (phase1_handle_t
*, caddr_t
);
146 static int setph1trns (struct isakmpsa
*, caddr_t
);
147 static int setph1attr (struct isakmpsa
*, caddr_t
);
148 static vchar_t
*setph2proposal0 (const phase2_handle_t
*,
149 const struct saprop
*, const struct saproto
*);
151 static vchar_t
*getidval (int, vchar_t
*);
156 * check phase 1 SA payload.
157 * make new SA payload to be replyed not including general header.
158 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
160 * positive: the pointer to new buffer of SA payload.
161 * network byte order.
162 * NULL : error occurd.
165 ipsecdoi_checkph1proposal(sa
, iph1
)
167 phase1_handle_t
*iph1
;
169 vchar_t
*newsa
; /* new SA payload approved. */
170 struct prop_pair
**pair
;
172 /* get proposal pair */
173 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
177 /* check and get one SA for use */
178 newsa
= get_ph1approval(iph1
, pair
);
185 iph1
->sa_ret
= newsa
;
191 * acceptable check for remote configuration.
192 * return a new SA payload to be reply to peer.
195 get_ph1approval(iph1
, pair
)
196 phase1_handle_t
*iph1
;
197 struct prop_pair
**pair
;
200 struct isakmpsa
*sa
, tsa
;
201 struct prop_pair
*s
, *p
;
205 if (iph1
->approval
) {
206 delisakmpsa(iph1
->approval
);
207 iph1
->approval
= NULL
;
210 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
213 for (s
= pair
[i
]; s
; s
= s
->next
) {
215 sizeof(struct isakmp_pl_p
) + s
->prop
->spi_size
;
217 /* compare proposal and select one */
218 for (p
= s
; p
; p
= p
->tnext
) {
219 if ((sa
= get_ph1approvalx(p
,
220 iph1
->rmconf
->proposal
, &tsa
,
221 iph1
->rmconf
->pcheck_level
)) != NULL
)
228 * if there is no suitable proposal, racoon complains about all of
229 * mismatched items in those proposal.
231 if (verbose_proposal_check
) {
232 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
235 for (s
= pair
[i
]; s
; s
= s
->next
) {
236 prophlen
= sizeof(struct isakmp_pl_p
)
238 for (p
= s
; p
; p
= p
->tnext
) {
239 print_ph1mismatched(p
,
240 iph1
->rmconf
->proposal
);
245 plog(ASL_LEVEL_ERR
, "no suitable proposal found.\n");
250 plog(ASL_LEVEL_DEBUG
, "an acceptable proposal found.\n");
252 /* check DH group settings */
254 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
258 plog(ASL_LEVEL_WARNING
,
259 "invalid DH parameter found, use default.\n");
260 oakley_dhgrp_free(sa
->dhgrp
);
264 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
273 plog(ASL_LEVEL_DEBUG
, "agreed on %s auth.\n",
274 s_oakley_attr_method(iph1
->approval
->authmethod
));
277 newsa
= get_sabyproppair(p
, iph1
);
279 delisakmpsa(iph1
->approval
);
280 iph1
->approval
= NULL
;
287 * compare peer's single proposal and all of my proposal.
288 * and select one if suiatable.
289 * p : one of peer's proposal.
290 * proposal: my proposals.
293 get_ph1approvalx(p
, proposal
, sap
, check_level
)
295 struct isakmpsa
*proposal
, *sap
;
298 struct isakmp_pl_p
*prop
= p
->prop
;
299 struct isakmp_pl_t
*trns
= p
->trns
;
300 struct isakmpsa sa
, *s
, *tsap
;
304 plog(ASL_LEVEL_DEBUG
,
305 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
306 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
307 prop
->spi_size
, prop
->num_t
);
309 plog(ASL_LEVEL_DEBUG
,
310 "trns#=%d, trns-id=%s\n",
312 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
314 tsap
= sap
!= NULL
? sap
: &sa
;
316 memset(tsap
, 0, sizeof(*tsap
));
317 if (t2isakmpsa(trns
, tsap
) < 0)
319 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
321 authmethod
= switch_authmethod(s
->authmethod
);
322 tsap_authmethod
= switch_authmethod(tsap
->authmethod
);
324 authmethod
= s
->authmethod
;
325 tsap_authmethod
= tsap
->authmethod
;
327 plog(ASL_LEVEL_DEBUG
, "Compared: DB:Peer\n");
328 plog(ASL_LEVEL_DEBUG
, "(version = %d:%d)\n",
329 s
->version
, tsap
->version
);
330 plog(ASL_LEVEL_DEBUG
, "(lifetime = %ld:%ld)\n",
331 (long)s
->lifetime
, (long)tsap
->lifetime
);
332 plog(ASL_LEVEL_DEBUG
, "(lifebyte = %zu:%zu)\n",
333 s
->lifebyte
, tsap
->lifebyte
);
334 plog(ASL_LEVEL_DEBUG
, "enctype = %s:%s\n",
335 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
337 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
339 plog(ASL_LEVEL_DEBUG
, "(encklen = %d:%d)\n",
340 s
->encklen
, tsap
->encklen
);
341 plog(ASL_LEVEL_DEBUG
, "hashtype = %s:%s\n",
342 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
344 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
346 plog(ASL_LEVEL_DEBUG
, "authmethod = %s:%s\n",
347 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
349 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
351 plog(ASL_LEVEL_DEBUG
, "dh_group = %s:%s\n",
352 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
354 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
357 /* XXX to be considered ? */
358 if (tsap
->lifebyte
> s
->lifebyte
) ;
361 * if responder side and peer's key length in proposal
362 * is bigger than mine, it might be accepted.
364 if(tsap
->enctype
== s
->enctype
&&
365 (tsap
->authmethod
== authmethod
|| tsap_authmethod
== authmethod
) &&
366 tsap
->hashtype
== s
->hashtype
&&
367 tsap
->dh_group
== s
->dh_group
&&
368 tsap
->encklen
== s
->encklen
&&
369 tsap
->version
== s
->version
) {
370 switch(check_level
) {
371 case PROP_CHECK_OBEY
:
375 case PROP_CHECK_STRICT
:
376 if ((tsap
->lifetime
> s
->lifetime
) ||
377 (tsap
->lifebyte
> s
->lifebyte
))
382 case PROP_CHECK_CLAIM
:
383 if (tsap
->lifetime
< s
->lifetime
)
384 s
->lifetime
= tsap
->lifetime
;
385 if (tsap
->lifebyte
< s
->lifebyte
)
386 s
->lifebyte
= tsap
->lifebyte
;
390 case PROP_CHECK_EXACT
:
391 if ((tsap
->lifetime
!= s
->lifetime
) ||
392 (tsap
->lifebyte
!= s
->lifebyte
))
399 "Unexpected proposal_check value\n");
407 if (tsap
->dhgrp
!= NULL
){
408 oakley_dhgrp_free(tsap
->dhgrp
);
412 if ((s
= dupisakmpsa(s
)) != NULL
) {
413 switch(check_level
) {
414 case PROP_CHECK_OBEY
:
415 s
->lifetime
= tsap
->lifetime
;
416 s
->lifebyte
= tsap
->lifebyte
;
419 case PROP_CHECK_STRICT
:
420 s
->lifetime
= tsap
->lifetime
;
421 s
->lifebyte
= tsap
->lifebyte
;
424 case PROP_CHECK_CLAIM
:
425 if (tsap
->lifetime
< s
->lifetime
)
426 s
->lifetime
= tsap
->lifetime
;
427 if (tsap
->lifebyte
< s
->lifebyte
)
428 s
->lifebyte
= tsap
->lifebyte
;
434 // hack to get around cisco rekeys
435 if (tsap
->authmethod
!= authmethod
&& tsap_authmethod
== authmethod
) {
436 s
->authmethod
= tsap
->authmethod
;
443 * print all of items in peer's proposal which are mismatched to my proposal.
444 * p : one of peer's proposal.
445 * proposal: my proposals.
448 print_ph1mismatched(p
, proposal
)
450 struct isakmpsa
*proposal
;
452 struct isakmpsa sa
, *s
;
454 memset(&sa
, 0, sizeof(sa
));
455 if (t2isakmpsa(p
->trns
, &sa
) < 0)
457 for (s
= proposal
; s
; s
= s
->next
) {
458 if (sa
.enctype
!= s
->enctype
) {
461 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
463 s
->prop_no
, s
->trns_no
,
464 p
->prop
->p_no
, p
->trns
->t_no
,
465 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
467 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
470 if (sa
.authmethod
!= s
->authmethod
) {
472 "rejected authmethod: "
473 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
475 s
->prop_no
, s
->trns_no
,
476 p
->prop
->p_no
, p
->trns
->t_no
,
477 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
479 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
482 if (sa
.hashtype
!= s
->hashtype
) {
484 "rejected hashtype: "
485 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
487 s
->prop_no
, s
->trns_no
,
488 p
->prop
->p_no
, p
->trns
->t_no
,
489 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
491 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
494 if (sa
.prf
!= s
->prf
||
495 sa
.prfklen
!= s
->prfklen
) {
498 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
500 s
->prop_no
, s
->trns_no
,
501 p
->prop
->p_no
, p
->trns
->t_no
,
502 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
505 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
509 if (sa
.dh_group
!= s
->dh_group
) {
511 "rejected dh_group: "
512 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
514 s
->prop_no
, s
->trns_no
,
515 p
->prop
->p_no
, p
->trns
->t_no
,
516 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
518 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
523 if (sa
.dhgrp
!= NULL
){
524 oakley_dhgrp_free(sa
.dhgrp
);
530 * get ISAKMP data attributes
534 struct isakmp_pl_t
*trns
;
537 struct isakmp_data
*d
, *prev
;
546 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
547 prev
= (struct isakmp_data
*)NULL
;
548 d
= (struct isakmp_data
*)(trns
+ 1);
551 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
552 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
554 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
559 if (tlen
< sizeof(struct isakmp_data
)) {
561 "t2isakmpsa invalid length of isakmp data, expected %zu actual %d\n",
562 sizeof(struct isakmp_data
), tlen
);
566 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
567 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
569 plog(ASL_LEVEL_DEBUG
,
570 "type=%s, flag=0x%04x, lorv=%s\n",
571 s_oakley_attr(type
), flag
,
572 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
574 /* get variable-sized item */
576 case OAKLEY_ATTR_GRP_PI
:
577 case OAKLEY_ATTR_GRP_GEN_ONE
:
578 case OAKLEY_ATTR_GRP_GEN_TWO
:
579 case OAKLEY_ATTR_GRP_CURVE_A
:
580 case OAKLEY_ATTR_GRP_CURVE_B
:
581 case OAKLEY_ATTR_SA_LD
:
582 case OAKLEY_ATTR_GRP_ORDER
:
585 p
= (u_char
*)&d
->lorv
;
587 len
= ntohs(d
->lorv
);
588 if ((len
+ sizeof(struct isakmp_data
)) > tlen
) {
590 "invalid ISAKMP-SA attr(%d), attr-len %d, overall-len %lu\n",
591 type
, len
, (tlen
- sizeof(struct isakmp_data
)));
594 p
= (u_char
*)(d
+ 1);
599 memcpy(val
->v
, p
, len
);
607 case OAKLEY_ATTR_ENC_ALG
:
608 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
611 case OAKLEY_ATTR_HASH_ALG
:
612 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
615 case OAKLEY_ATTR_AUTH_METHOD
:
616 sa
->authmethod
= ntohs(d
->lorv
);
619 case OAKLEY_ATTR_GRP_DESC
:
620 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
623 case OAKLEY_ATTR_GRP_TYPE
:
625 int type
= (int)ntohs(d
->lorv
);
626 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
627 sa
->dhgrp
->type
= type
;
632 case OAKLEY_ATTR_GRP_PI
:
633 sa
->dhgrp
->prime
= val
;
636 case OAKLEY_ATTR_GRP_GEN_ONE
:
639 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
641 int len
= ntohs(d
->lorv
);
646 if ((len
+ sizeof(struct isakmp_data
)) > tlen
) {
648 "invalid ISAKMP-SA attr - OAKLEY_ATTR_GRP_GEN_ONE, attr-len %d, overall-len %lu\n",
649 len
, (tlen
- sizeof(struct isakmp_data
)));
653 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
654 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
658 case OAKLEY_ATTR_GRP_GEN_TWO
:
661 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
663 int len
= ntohs(d
->lorv
);
668 if ((len
+ sizeof(struct isakmp_data
)) > tlen
) {
670 "invalid ISAKMP-SA attr - OAKLEY_ATTR_GRP_GEN_TWO, attr-len %d, overall-len %lu\n",
671 len
, (tlen
- sizeof(struct isakmp_data
)));
675 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
676 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
680 case OAKLEY_ATTR_GRP_CURVE_A
:
681 sa
->dhgrp
->curve_a
= val
;
684 case OAKLEY_ATTR_GRP_CURVE_B
:
685 sa
->dhgrp
->curve_b
= val
;
688 case OAKLEY_ATTR_SA_LD_TYPE
:
690 int type
= (int)ntohs(d
->lorv
);
692 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
693 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
697 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
702 case OAKLEY_ATTR_SA_LD
:
704 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
705 OAKLEY_ATTR_SA_LD_TYPE
) {
707 "life duration must follow ltype\n");
712 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
713 sa
->lifetime
= ipsecdoi_set_ld(val
);
715 if (sa
->lifetime
== 0) {
717 "invalid life duration.\n");
721 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
722 sa
->lifebyte
= ipsecdoi_set_ld(val
);
724 if (sa
->lifebyte
== 0) {
726 "invalid life duration.\n");
733 "invalid life type: %d\n", life_t
);
738 case OAKLEY_ATTR_KEY_LEN
:
740 int len
= ntohs(d
->lorv
);
743 "keylen %d: not multiple of 8\n",
747 sa
->encklen
= (u_int16_t
)len
;
751 case OAKLEY_ATTR_PRF
:
752 case OAKLEY_ATTR_FIELD_SIZE
:
756 case OAKLEY_ATTR_GRP_ORDER
:
757 sa
->dhgrp
->order
= val
;
767 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
769 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
772 "t2isakmpsa: packet too short - attr length %u for type %d\n",
773 ntohs(d
->lorv
), type
);
777 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
781 /* key length must not be specified on some algorithms */
783 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
784 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
786 "keylen must not be specified "
787 "for encryption algorithm %d\n",
800 * check phase 2 SA payload and select single proposal.
801 * make new SA payload to be replyed not including general header.
802 * This function is called by responder only.
808 ipsecdoi_selectph2proposal(iph2
)
809 phase2_handle_t
*iph2
;
811 struct prop_pair
**pair
;
812 struct prop_pair
*ret
;
814 /* get proposal pair */
815 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
819 /* check and select a proposal. */
820 ret
= get_ph2approval(iph2
, pair
);
825 /* make a SA to be replayed. */
826 /* SPI must be updated later. */
827 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
829 if (iph2
->sa_ret
== NULL
)
836 * check phase 2 SA payload returned from responder.
837 * This function is called by initiator only.
843 ipsecdoi_checkph2proposal(iph2
)
844 phase2_handle_t
*iph2
;
846 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
850 vchar_t
*sa_ret
= NULL
;
852 /* get proposal pair of SA sent. */
853 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
856 "failed to get prop pair.\n");
860 /* XXX should check the number of transform */
862 /* get proposal pair of SA replayed */
863 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
866 "failed to get prop pair.\n");
870 /* check proposal is only one ? */
873 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
881 "no proposal received.\n");
886 "some proposals received.\n");
890 if (spair
[n
] == NULL
) {
891 plog(ASL_LEVEL_WARNING
,
892 "invalid proposal number:%d received.\n", i
);
896 if (rpair
[n
]->tnext
!= NULL
) {
898 "multi transforms replyed.\n");
902 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
904 "proposal mismathed.\n");
909 * check and select a proposal.
910 * ensure that there is no modification of the proposal by
913 p
= get_ph2approval(iph2
, rpair
);
917 /* make a SA to be replayed. */
918 sa_ret
= iph2
->sa_ret
;
919 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
921 if (iph2
->sa_ret
== NULL
)
928 free_proppair(rpair
);
930 free_proppair(spair
);
938 * compare two prop_pair which is assumed to have same proposal number.
939 * the case of bundle or single SA, NOT multi transforms.
940 * a: a proposal that is multi protocols and single transform, usually replyed.
941 * b: a proposal that is multi protocols and multi transform, usually sent.
942 * NOTE: this function is for initiator.
946 * XXX cannot understand the comment!
949 cmp_aproppair_i(a
, b
)
950 struct prop_pair
*a
, *b
;
952 struct prop_pair
*p
, *q
, *r
;
955 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
956 for (r
= q
; r
; r
= r
->tnext
) {
958 if (p
->trns
->t_no
== r
->trns
->t_no
)
962 /* no suitable transform found */
964 "no suitable transform found.\n");
969 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
970 plog(ASL_LEVEL_WARNING
,
971 "proposal #%d mismatched, "
973 r
->prop
->p_no
, p
->prop
->p_no
);
977 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
979 "proto_id mismathed: my:%d peer:%d\n",
980 r
->prop
->proto_id
, p
->prop
->proto_id
);
984 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
986 "invalid spi size: %d.\n",
991 /* check #of transforms */
992 if (p
->prop
->num_t
!= 1) {
993 plog(ASL_LEVEL_WARNING
,
994 "#of transform is %d, "
995 "but expected 1.\n", p
->prop
->num_t
);
999 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
1000 plog(ASL_LEVEL_WARNING
,
1001 "transform number has been modified.\n");
1004 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
1005 plog(ASL_LEVEL_WARNING
,
1006 "reserved field should be zero.\n");
1010 /* compare attribute */
1011 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
1012 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
1013 plog(ASL_LEVEL_WARNING
,
1014 "attribute has been modified.\n");
1018 if ((p
&& !q
) || (!p
&& q
)) {
1019 /* # of protocols mismatched */
1021 "#of protocols mismatched.\n");
1029 * acceptable check for policy configuration.
1030 * return a new SA payload to be reply to peer.
1032 static struct prop_pair
*
1033 get_ph2approval(iph2
, pair
)
1034 phase2_handle_t
*iph2
;
1035 struct prop_pair
**pair
;
1037 struct prop_pair
*ret
;
1040 iph2
->approval
= NULL
;
1042 plog(ASL_LEVEL_DEBUG
,
1043 "begin compare proposals.\n");
1045 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1046 if (pair
[i
] == NULL
)
1048 plog(ASL_LEVEL_DEBUG
,
1049 "pair[%d]: %p\n", i
, pair
[i
]);
1050 print_proppair(ASL_LEVEL_DEBUG
, pair
[i
]);;
1052 /* compare proposal and select one */
1053 ret
= get_ph2approvalx(iph2
, pair
[i
]);
1060 plog(ASL_LEVEL_ERR
, "no suitable policy found.\n");
1066 * compare my proposal and peers just one proposal.
1069 static struct prop_pair
*
1070 get_ph2approvalx(iph2
, pp
)
1071 phase2_handle_t
*iph2
;
1072 struct prop_pair
*pp
;
1074 struct prop_pair
*ret
= NULL
;
1075 struct saprop
*pr0
, *pr
= NULL
;
1076 struct saprop
*q1
, *q2
;
1078 pr0
= aproppair2saprop(pp
);
1082 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1083 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1084 plog(ASL_LEVEL_DEBUG
,
1085 "peer's single bundle:\n");
1086 printsaprop0(ASL_LEVEL_DEBUG
, q1
);
1087 plog(ASL_LEVEL_DEBUG
,
1088 "my single bundle:\n");
1089 printsaprop0(ASL_LEVEL_DEBUG
, q2
);
1091 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1099 /* no proposal matching */
1112 plog(ASL_LEVEL_DEBUG
, "matched\n");
1113 iph2
->approval
= pr
;
1117 struct prop_pair
*p
, *x
;
1118 struct prop_pair
*n
= NULL
;
1122 for (p
= pp
; p
; p
= p
->next
) {
1124 * find a proposal with matching proto_id.
1125 * we have analyzed validity already, in cmpsaprop_alloc().
1127 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1128 if (sp
->proto_id
== p
->prop
->proto_id
)
1136 for (x
= p
; x
; x
= x
->tnext
)
1137 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1142 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1145 "failed to get buffer.\n");
1152 /* need to preserve the order */
1153 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1155 if (x
&& x
->prop
== n
->prop
) {
1156 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1167 /* #of transforms should be updated ? */
1176 struct prop_pair
**pair
;
1180 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1181 free_proppair0(pair
[i
]);
1188 free_proppair0(pair
)
1189 struct prop_pair
*pair
;
1191 struct prop_pair
*p
, *q
, *r
, *s
;
1207 * get proposal pairs from SA payload.
1208 * tiny check for proposal payload.
1211 get_proppair(sa
, mode
)
1215 struct prop_pair
**pair
= NULL
;
1216 int num_p
= 0; /* number of proposal for use */
1221 //plogdump(ASL_LEVEL_DEBUG, sa->v, sa->l, "total SA len=%zu\n", sa->l);
1223 if (mode
== IPSECDOI_TYPE_PH1
|| mode
== IPSECDOI_TYPE_PH2
) {
1225 struct ipsecdoi_sa_b
*sab
= ALIGNED_CAST(__typeof__(sab
))sa
->v
;
1228 /* check SA payload size */
1229 if (sa
->l
< sizeof(*sab
)) {
1231 "Invalid SA length = %zu.\n", sa
->l
);
1236 if (check_doi(ntohl(sab
->doi
)) < 0)
1239 /* check SITUATION */
1240 if (check_situation(ntohl(sab
->sit
)) < 0)
1243 bp
= (caddr_t
)(sab
+ 1);
1244 tlen
= sa
->l
- sizeof(*sab
);
1246 bp
= (__typeof__(bp
))sa
->v
;
1250 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1253 "failed to get buffer.\n");
1258 struct isakmp_pl_p
*prop
;
1260 vchar_t
*pbuf
= NULL
;
1261 struct isakmp_parse_t
*pa
;
1263 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1267 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1268 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1270 /* check the value of next payload */
1271 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1273 "Invalid payload type=%u\n", pa
->type
);
1278 if (pa
->len
< sizeof(struct isakmp_pl_p
)) {
1280 "get_proppair invalid length of proposal, expected %lu actual %d\n",
1281 sizeof(struct isakmp_pl_p
), pa
->len
);
1286 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1289 plog(ASL_LEVEL_DEBUG
,
1290 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1294 "invalid proposal with length %d\n", proplen
);
1299 /* check Protocol ID */
1300 if (!check_protocol
[mode
]) {
1302 "unsupported mode %d\n", mode
);
1306 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1309 /* check SPI length when IKE. */
1310 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1313 if (pa
->len
< (sizeof(struct isakmp_pl_p
) + prop
->spi_size
)) {
1315 "get_proppair invalid length of proposal spi size, expected %u actual %zu\n",
1316 prop
->spi_size
, (pa
->len
- sizeof(struct isakmp_pl_p
)));
1322 if (get_transform(prop
, pair
, &num_p
) < 0) {
1333 struct prop_pair
*p
, *q
;
1335 /* check for proposals with no transforms */
1336 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1340 plog(ASL_LEVEL_DEBUG
, "pair %d:\n", i
);
1341 print_proppair(ASL_LEVEL_DEBUG
, pair
[i
]);
1343 notrans
= nprop
= 0;
1344 for (p
= pair
[i
]; p
; p
= p
->next
) {
1345 if (p
->trns
== NULL
) {
1349 for (q
= p
; q
; q
= q
->tnext
)
1355 * XXX at this moment, we cannot accept proposal group
1356 * with multiple proposals. this should be fixed.
1358 if (pair
[i
]->next
) {
1359 plog(ASL_LEVEL_WARNING
,
1360 "proposal #%u ignored "
1361 "(multiple proposal not supported)\n",
1362 pair
[i
]->prop
->p_no
);
1368 for (p
= pair
[i
]; p
; p
= q
) {
1375 plog(ASL_LEVEL_DEBUG
,
1376 "proposal #%u: %d transform\n",
1377 pair
[i
]->prop
->p_no
, nprop
);
1382 /* bark if no proposal is found. */
1385 "no Proposal found.\n");
1397 * check transform payload.
1399 * positive: return the pointer to the payload of valid transform.
1400 * 0 : No valid transform found.
1403 get_transform(prop
, pair
, num_p
)
1404 struct isakmp_pl_p
*prop
;
1405 struct prop_pair
**pair
;
1408 int tlen
; /* total length of all transform in a proposal */
1410 struct isakmp_pl_t
*trns
;
1412 vchar_t
*pbuf
= NULL
;
1413 struct isakmp_parse_t
*pa
;
1414 struct prop_pair
*p
= NULL
, *q
;
1417 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1418 tlen
= ntohs(prop
->h
.len
)
1419 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1420 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1424 /* check and get transform for use */
1426 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1427 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1432 /* check the value of next payload */
1433 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1435 "Invalid payload type=%u\n", pa
->type
);
1439 if (pa
->len
< sizeof(struct isakmp_pl_t
)) {
1441 "get_transform invalid length of transform, expected %lu actual %d\n",
1442 sizeof(struct isakmp_pl_t
), pa
->len
);
1446 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1449 plog(ASL_LEVEL_DEBUG
,
1450 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1452 /* check transform ID */
1453 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1454 plog(ASL_LEVEL_WARNING
,
1455 "unsupported proto_id %u\n",
1459 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1460 plog(ASL_LEVEL_WARNING
,
1461 "unsupported proto_id %u\n",
1466 if (!check_transform
[prop
->proto_id
]
1467 || !check_attributes
[prop
->proto_id
]) {
1468 plog(ASL_LEVEL_WARNING
,
1469 "unsupported proto_id %u\n",
1473 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1476 /* check data attributes */
1477 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1480 p
= racoon_calloc(1, sizeof(*p
));
1483 "failed to get buffer.\n");
1490 /* need to preserve the order */
1491 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1493 if (q
&& q
->prop
== p
->prop
) {
1494 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1501 pair
[prop
->p_no
] = p
;
1513 * make a new SA payload from prop_pair.
1514 * NOTE: this function clears the spi value.
1517 get_sabyproppair(pair
, iph1
)
1518 struct prop_pair
*pair
;
1519 phase1_handle_t
*iph1
;
1523 u_int8_t
*np_p
= NULL
;
1524 struct prop_pair
*p
;
1525 int prophlen
, trnslen
;
1528 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
1529 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1533 for (p
= pair
; p
; p
= p
->next
) {
1534 newtlen
+= sizeof(struct isakmp_pl_p
);
1535 newtlen
+= p
->prop
->spi_size
;
1536 newtlen
+= ntohs(p
->trns
->h
.len
);
1539 newsa
= vmalloc(newtlen
);
1540 if (newsa
== NULL
) {
1541 plog(ASL_LEVEL_ERR
, "failed to get newsa.\n");
1546 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1548 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
1549 /* update some of values in SA header */
1550 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1551 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1552 bp
+= sizeof(struct ipsecdoi_sa_b
);
1555 /* create proposal payloads */
1556 for (p
= pair
; p
; p
= p
->next
) {
1557 prophlen
= sizeof(struct isakmp_pl_p
)
1558 + p
->prop
->spi_size
;
1559 trnslen
= ntohs(p
->trns
->h
.len
);
1562 *np_p
= ISAKMP_NPTYPE_P
;
1564 /* create proposal */
1566 memcpy(bp
, p
->prop
, prophlen
);
1567 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1568 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1569 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1570 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1571 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1574 /* create transform */
1575 memcpy(bp
, p
->trns
, trnslen
);
1576 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1577 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1585 * update responder's spi
1588 ipsecdoi_updatespi(iph2
)
1589 phase2_handle_t
*iph2
;
1591 struct prop_pair
**pair
, *p
;
1598 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1601 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1605 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1606 /* multiple transform must be filtered by selectph2proposal.*/
1610 pp
= iph2
->approval
;
1612 /* create proposal payloads */
1613 for (p
= pair
[i
]; p
; p
= p
->next
) {
1615 * find a proposal/transform with matching proto_id/t_id.
1616 * we have analyzed validity already, in cmpsaprop_alloc().
1618 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1619 if (p
->prop
->proto_id
== pr
->proto_id
&&
1620 p
->trns
->t_id
== pr
->head
->trns_id
) {
1628 * XXX SPI bits are left-filled, for use with IPComp.
1629 * we should be switching to variable-length spi field...
1631 spi
= (u_int8_t
*)&pr
->spi
;
1632 spi
+= sizeof(pr
->spi
);
1634 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1639 free_proppair(pair
);
1644 * make a new SA payload from prop_pair.
1647 get_sabysaprop(pp0
, sa0
)
1651 struct prop_pair
**pair
= NULL
;
1652 vchar_t
*newsa
= NULL
;
1654 u_int8_t
*np_p
= NULL
;
1655 struct prop_pair
*p
= NULL
;
1659 int prophlen
, trnslen
;
1663 /* get proposal pair */
1664 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1668 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1669 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1671 if (pair
[pp
->prop_no
] == NULL
)
1674 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1675 newtlen
+= (sizeof(struct isakmp_pl_p
)
1678 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1679 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1680 if (tr
->trns_no
== p
->trns
->t_no
)
1686 newtlen
+= ntohs(p
->trns
->h
.len
);
1691 newsa
= vmalloc(newtlen
);
1692 if (newsa
== NULL
) {
1693 plog(ASL_LEVEL_ERR
, "failed to get newsa.\n");
1698 /* some of values of SA must be updated in the out of this function */
1699 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1700 bp
+= sizeof(struct ipsecdoi_sa_b
);
1702 /* create proposal payloads */
1703 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1705 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1706 prophlen
= sizeof(struct isakmp_pl_p
)
1707 + p
->prop
->spi_size
;
1709 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1710 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1711 if (tr
->trns_no
== p
->trns
->t_no
)
1717 trnslen
= ntohs(p
->trns
->h
.len
);
1720 *np_p
= ISAKMP_NPTYPE_P
;
1722 /* create proposal */
1724 memcpy(bp
, p
->prop
, prophlen
);
1725 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1726 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1727 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1728 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1731 /* create transform */
1732 memcpy(bp
, p
->trns
, trnslen
);
1733 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1734 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1746 if (newsa
!= NULL
) {
1756 * If some error happens then return 0. Although 0 means that lifetime is zero,
1757 * such a value should not be accepted.
1758 * Also 0 of lifebyte should not be included in a packet although 0 means not
1762 ipsecdoi_set_ld(buf
)
1772 ld
= ntohs(*ALIGNED_CAST(u_int16_t
*)buf
->v
);
1775 ld
= ntohl(*ALIGNED_CAST(u_int32_t
*)buf
->v
);
1779 "length %zu of life duration "
1780 "isn't supported.\n", buf
->l
);
1800 "invalid value of DOI 0x%08x.\n", doi
);
1810 check_situation(sit
)
1814 case IPSECDOI_SIT_IDENTITY_ONLY
:
1817 case IPSECDOI_SIT_SECRECY
:
1818 case IPSECDOI_SIT_INTEGRITY
:
1820 "situation 0x%08x unsupported yet.\n", sit
);
1825 "invalid situation 0x%08x.\n", sit
);
1832 * check protocol id in main mode
1835 check_prot_main(proto_id
)
1839 case IPSECDOI_PROTO_ISAKMP
:
1844 "Illegal protocol id=%u.\n", proto_id
);
1851 * check protocol id in quick mode
1854 check_prot_quick(proto_id
)
1858 case IPSECDOI_PROTO_IPSEC_AH
:
1859 case IPSECDOI_PROTO_IPSEC_ESP
:
1862 case IPSECDOI_PROTO_IPCOMP
:
1867 "invalid protocol id %d.\n", proto_id
);
1874 check_spi_size(proto_id
, size
)
1878 case IPSECDOI_PROTO_ISAKMP
:
1881 plog(ASL_LEVEL_WARNING
,
1882 "SPI size isn't zero, but IKE proposal.\n");
1886 case IPSECDOI_PROTO_IPSEC_AH
:
1887 case IPSECDOI_PROTO_IPSEC_ESP
:
1890 "invalid SPI size=%d for IPSEC proposal.\n",
1896 case IPSECDOI_PROTO_IPCOMP
:
1897 if (size
!= 2 && size
!= 4) {
1899 "invalid SPI size=%d for IPCOMP proposal.\n",
1913 * check transform ID in ISAKMP.
1916 check_trns_isakmp(t_id
)
1920 case IPSECDOI_KEY_IKE
:
1924 "invalid transform-id=%u in proto_id=%u.\n",
1925 t_id
, IPSECDOI_KEY_IKE
);
1932 * check transform ID in AH.
1939 case IPSECDOI_AH_MD5
:
1940 case IPSECDOI_AH_SHA
:
1941 case IPSECDOI_AH_SHA256
:
1942 case IPSECDOI_AH_SHA384
:
1943 case IPSECDOI_AH_SHA512
:
1945 case IPSECDOI_AH_DES
:
1947 "not support transform-id=%u in AH.\n", t_id
);
1951 "invalid transform-id=%u in AH.\n", t_id
);
1958 * check transform ID in ESP.
1961 check_trns_esp(t_id
)
1965 case IPSECDOI_ESP_DES
:
1966 case IPSECDOI_ESP_3DES
:
1967 case IPSECDOI_ESP_NULL
:
1968 case IPSECDOI_ESP_RC5
:
1969 case IPSECDOI_ESP_CAST
:
1970 case IPSECDOI_ESP_BLOWFISH
:
1971 case IPSECDOI_ESP_AES
:
1972 case IPSECDOI_ESP_TWOFISH
:
1974 case IPSECDOI_ESP_DES_IV32
:
1975 case IPSECDOI_ESP_DES_IV64
:
1976 case IPSECDOI_ESP_IDEA
:
1977 case IPSECDOI_ESP_3IDEA
:
1978 case IPSECDOI_ESP_RC4
:
1980 "not support transform-id=%u in ESP.\n", t_id
);
1984 "invalid transform-id=%u in ESP.\n", t_id
);
1991 * check transform ID in IPCOMP.
1994 check_trns_ipcomp(t_id
)
1998 case IPSECDOI_IPCOMP_OUI
:
1999 case IPSECDOI_IPCOMP_DEFLATE
:
2000 case IPSECDOI_IPCOMP_LZS
:
2004 "invalid transform-id=%u in IPCOMP.\n", t_id
);
2011 * check data attributes in IKE.
2014 check_attr_isakmp(trns
)
2015 struct isakmp_pl_t
*trns
;
2017 struct isakmp_data
*d
;
2022 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2023 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2026 if (tlen
< sizeof(struct isakmp_data
)) {
2028 "check_attr_isakmp invalid length of isakmp data, expected %zu actual %d\n",
2029 sizeof(struct isakmp_data
), tlen
);
2033 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2034 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2035 lorv
= ntohs(d
->lorv
);
2037 plog(ASL_LEVEL_DEBUG
,
2038 "type=%s, flag=0x%04x, lorv=%s\n",
2039 s_oakley_attr(type
), flag
,
2040 s_oakley_attr_v(type
, lorv
));
2043 * some of the attributes must be encoded in TV.
2044 * see RFC2409 Appendix A "Attribute Classes".
2047 case OAKLEY_ATTR_ENC_ALG
:
2048 case OAKLEY_ATTR_HASH_ALG
:
2049 case OAKLEY_ATTR_AUTH_METHOD
:
2050 case OAKLEY_ATTR_GRP_DESC
:
2051 case OAKLEY_ATTR_GRP_TYPE
:
2052 case OAKLEY_ATTR_SA_LD_TYPE
:
2053 case OAKLEY_ATTR_PRF
:
2054 case OAKLEY_ATTR_KEY_LEN
:
2055 case OAKLEY_ATTR_FIELD_SIZE
:
2056 if (!flag
) { /* TLV*/
2058 "oakley attribute %d must be TV.\n",
2065 /* sanity check for TLV. length must be specified. */
2066 if (!flag
&& lorv
== 0) { /*TLV*/
2068 "invalid length %d for TLV attribute %d.\n",
2074 case OAKLEY_ATTR_ENC_ALG
:
2075 if (!alg_oakley_encdef_ok(lorv
)) {
2077 "invalied encryption algorithm=%d.\n",
2083 case OAKLEY_ATTR_HASH_ALG
:
2084 if (!alg_oakley_hashdef_ok(lorv
)) {
2086 "invalied hash algorithm=%d.\n",
2092 case OAKLEY_ATTR_AUTH_METHOD
:
2094 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2095 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2096 #ifdef ENABLE_HYBRID
2097 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2098 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
:
2099 #if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2100 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
:
2102 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
2104 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
2106 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2107 #ifdef ENABLE_HYBRID
2108 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2109 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
2110 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2111 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2112 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
:
2113 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
2114 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
:
2115 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
2116 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
:
2117 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
2119 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2120 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2122 "auth method %s isn't supported.\n",
2123 s_oakley_attr_method(lorv
));
2127 "invalid auth method %d.\n",
2133 case OAKLEY_ATTR_GRP_DESC
:
2134 if (!alg_oakley_dhdef_ok(lorv
)) {
2136 "invalid DH group %d.\n",
2142 case OAKLEY_ATTR_GRP_TYPE
:
2144 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2148 "unsupported DH group type %d.\n",
2154 case OAKLEY_ATTR_GRP_PI
:
2155 case OAKLEY_ATTR_GRP_GEN_ONE
:
2156 /* sanity checks? */
2159 case OAKLEY_ATTR_GRP_GEN_TWO
:
2160 case OAKLEY_ATTR_GRP_CURVE_A
:
2161 case OAKLEY_ATTR_GRP_CURVE_B
:
2163 "attr type=%u isn't supported.\n", type
);
2166 case OAKLEY_ATTR_SA_LD_TYPE
:
2168 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2169 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2173 "invalid life type %d.\n", lorv
);
2178 case OAKLEY_ATTR_SA_LD
:
2179 /* should check the value */
2182 case OAKLEY_ATTR_PRF
:
2183 case OAKLEY_ATTR_KEY_LEN
:
2186 case OAKLEY_ATTR_FIELD_SIZE
:
2188 "attr type=%u isn't supported.\n", type
);
2191 case OAKLEY_ATTR_GRP_ORDER
:
2194 case OAKLEY_ATTR_GSS_ID
:
2199 "invalid attribute type %d.\n", type
);
2205 d
= (struct isakmp_data
*)((char *)d
2208 tlen
-= (sizeof(*d
) + lorv
);
2209 d
= (struct isakmp_data
*)((char *)d
2210 + sizeof(*d
) + lorv
);
2213 "check_attr_isakmp: packet too short - attr length %u for type %d\n",
2224 * check data attributes in IPSEC AH/ESP.
2228 struct isakmp_pl_t
*trns
;
2230 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2234 check_attr_esp(trns
)
2235 struct isakmp_pl_t
*trns
;
2237 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2241 check_attr_ipsec(proto_id
, trns
)
2243 struct isakmp_pl_t
*trns
;
2245 struct isakmp_data
*d
;
2249 int attrseen
[16]; /* XXX magic number */
2251 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2252 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2253 memset(attrseen
, 0, sizeof(attrseen
));
2256 if (tlen
< sizeof(struct isakmp_data
)) {
2258 "check_attr_ipsec invalid length of isakmp data, expected %zu actual %d\n",
2259 sizeof(struct isakmp_data
), tlen
);
2263 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2264 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2265 lorv
= ntohs(d
->lorv
);
2267 plog(ASL_LEVEL_DEBUG
,
2268 "type=%s, flag=0x%04x, lorv=%s\n",
2269 s_ipsecdoi_attr(type
), flag
,
2270 s_ipsecdoi_attr_v(type
, lorv
));
2272 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2276 case IPSECDOI_ATTR_ENC_MODE
:
2279 "must be TV when ENC_MODE.\n");
2284 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2285 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2288 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2289 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2290 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2291 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2292 plog(ASL_LEVEL_DEBUG
,
2293 "UDP encapsulation requested\n");
2298 "invalid encryption mode=%u.\n",
2304 case IPSECDOI_ATTR_AUTH
:
2307 "must be TV when AUTH.\n");
2312 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2313 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2314 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2317 "auth algorithm %u conflicts "
2318 "with transform %u.\n",
2323 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2324 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2325 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2329 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2330 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2331 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2335 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2336 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2337 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2341 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2342 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2343 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2347 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2348 case IPSECDOI_ATTR_AUTH_KPDK
:
2350 "auth algorithm %u isn't supported.\n",
2355 "invalid auth algorithm=%u.\n",
2361 case IPSECDOI_ATTR_SA_LD_TYPE
:
2364 "must be TV when LD_TYPE.\n");
2369 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2370 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2374 "invalid life type %d.\n", lorv
);
2379 case IPSECDOI_ATTR_SA_LD
:
2381 /* i.e. ISAKMP_GEN_TV */
2382 plog(ASL_LEVEL_DEBUG
,
2383 "life duration was in TLV.\n");
2385 /* i.e. ISAKMP_GEN_TLV */
2388 "invalid length of LD\n");
2394 case IPSECDOI_ATTR_GRP_DESC
:
2397 "must be TV when GRP_DESC.\n");
2401 if (!alg_oakley_dhdef_ok(lorv
)) {
2403 "invalid group description=%u.\n",
2409 case IPSECDOI_ATTR_KEY_LENGTH
:
2412 "must be TV when KEY_LENGTH.\n");
2417 case IPSECDOI_ATTR_KEY_ROUNDS
:
2418 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2419 case IPSECDOI_ATTR_COMP_PRIVALG
:
2421 "attr type=%u isn't supported.\n", type
);
2426 "invalid attribute type %d.\n", type
);
2432 d
= (struct isakmp_data
*)((char *)d
2435 tlen
-= (sizeof(*d
) + lorv
);
2436 d
= (struct isakmp_data
*)((caddr_t
)d
2437 + sizeof(*d
) + lorv
);
2440 "check_attr_ipsec: packet too short - attr length %u for type %d\n",
2447 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2448 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2450 "attr AUTH must be present for AH.\n");
2454 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2455 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2456 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2458 "attr AUTH must be present for ESP NULL encryption.\n");
2466 check_attr_ipcomp(trns
)
2467 struct isakmp_pl_t
*trns
;
2469 struct isakmp_data
*d
;
2473 int attrseen
[16]; /* XXX magic number */
2475 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2476 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2477 memset(attrseen
, 0, sizeof(attrseen
));
2480 if (tlen
< sizeof(struct isakmp_data
)) {
2482 "check_attr_ipcomp: invalid length of isakmp data, expected %zu actual %d\n",
2483 sizeof(struct isakmp_data
), tlen
);
2487 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2488 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2489 lorv
= ntohs(d
->lorv
);
2491 plog(ASL_LEVEL_DEBUG
,
2492 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2495 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2499 case IPSECDOI_ATTR_ENC_MODE
:
2502 "must be TV when ENC_MODE.\n");
2507 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2508 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2511 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2512 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2513 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2514 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2515 plog(ASL_LEVEL_DEBUG
,
2516 "UDP encapsulation requested\n");
2521 "invalid encryption mode=%u.\n",
2527 case IPSECDOI_ATTR_SA_LD_TYPE
:
2530 "must be TV when LD_TYPE.\n");
2535 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2536 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2540 "invalid life type %d.\n", lorv
);
2545 case IPSECDOI_ATTR_SA_LD
:
2547 /* i.e. ISAKMP_GEN_TV */
2548 plog(ASL_LEVEL_DEBUG
,
2549 "life duration was in TLV.\n");
2551 /* i.e. ISAKMP_GEN_TLV */
2554 "invalid length of LD\n");
2560 case IPSECDOI_ATTR_GRP_DESC
:
2563 "must be TV when GRP_DESC.\n");
2567 if (!alg_oakley_dhdef_ok(lorv
)) {
2569 "invalid group description=%u.\n",
2575 case IPSECDOI_ATTR_AUTH
:
2577 "invalid attr type=%u.\n", type
);
2580 case IPSECDOI_ATTR_KEY_LENGTH
:
2581 case IPSECDOI_ATTR_KEY_ROUNDS
:
2582 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2583 case IPSECDOI_ATTR_COMP_PRIVALG
:
2585 "attr type=%u isn't supported.\n", type
);
2590 "invalid attribute type %d.\n", type
);
2596 d
= (struct isakmp_data
*)((char *)d
2599 tlen
-= (sizeof(*d
) + lorv
);
2600 d
= (struct isakmp_data
*)((caddr_t
)d
2601 + sizeof(*d
) + lorv
);
2604 "check_attr_ipcomp: packet too short - attr length %u for type %d\n",
2612 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2613 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2615 "attr AUTH must be present for AH.\n", type
);
2625 * create phase1 proposal from remote configuration.
2626 * NOT INCLUDING isakmp general header of SA payload
2629 ipsecdoi_setph1proposal (phase1_handle_t
*iph1
)
2634 if (!iph1
) return NULL
;
2636 struct isakmpsa
*props
= iph1
->rmconf
->proposal
;
2637 unsigned int version
= iph1
->version
;
2639 /* count total size of SA minus isakmp general header */
2640 /* not including isakmp general header of SA payload */
2641 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2642 sablen
= sizeof(struct ipsecdoi_sa_b
);
2646 sablen
+= setph1prop(iph1
, NULL
);
2648 mysa
= vmalloc(sablen
);
2651 "failed to allocate my sa buffer\n");
2655 /* create SA payload */
2656 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
2657 /* not including isakmp general header */
2658 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2659 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2661 (void)setph1prop(iph1
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2668 setph1prop (phase1_handle_t
*iph1
,
2671 struct isakmpsa
*props
= iph1
->rmconf
->proposal
;
2673 struct isakmp_pl_p
*prop
= NULL
;
2674 struct isakmpsa
*s
= NULL
;
2675 int proplen
, trnslen
;
2676 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2681 proplen
= sizeof(*prop
) + spi_size
;
2683 /* create proposal */
2684 prop
= (struct isakmp_pl_p
*)p
;
2685 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2686 prop
->h
.reserved
= 0;
2687 prop
->p_no
= props
->prop_no
;
2688 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2689 prop
->spi_size
= spi_size
;
2696 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2699 *np_t
= ISAKMP_NPTYPE_T
;
2701 trnslen
= setph1trns(s
, p
);
2704 /* save buffer to pre-next payload */
2705 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2708 /* count up transform length */
2714 /* update proposal length */
2716 prop
->h
.len
= htons(proplen
);
2717 prop
->num_t
= trns_num
;
2724 setph1trns (struct isakmpsa
*sa
,
2727 struct isakmp_pl_t
*trns
= NULL
;
2728 int trnslen
, attrlen
;
2731 trnslen
= sizeof(*trns
);
2733 /* create transform */
2734 trns
= (struct isakmp_pl_t
*)p
;
2735 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2736 trns
->t_no
= sa
->trns_no
;
2737 trns
->t_id
= IPSECDOI_KEY_IKE
;
2741 attrlen
= setph1attr(sa
, p
);
2747 trns
->h
.len
= htons(trnslen
);
2753 setph1attr (struct isakmpsa
*sa
,
2760 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2762 attrlen
+= sizeof(struct isakmp_data
)
2763 + sizeof(struct isakmp_data
);
2764 if (sa
->lifetime
> 0xffff)
2765 attrlen
+= sizeof(lifetime
);
2767 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2768 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2769 if (sa
->lifetime
> 0xffff) {
2770 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2774 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2781 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2783 attrlen
+= sizeof(struct isakmp_data
)
2784 + sizeof(struct isakmp_data
);
2785 if (sa
->lifebyte
> 0xffff)
2786 attrlen
+= sizeof(lifebyte
);
2788 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2789 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2790 if (sa
->lifebyte
> 0xffff) {
2791 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2795 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2802 attrlen
+= sizeof(struct isakmp_data
);
2804 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2807 attrlen
+= sizeof(struct isakmp_data
);
2809 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2811 if (sa
->authmethod
) {
2814 #ifdef ENABLE_HYBRID
2815 authmethod
= switch_authmethod(sa
->authmethod
);
2817 authmethod
= sa
->authmethod
;
2819 attrlen
+= sizeof(struct isakmp_data
);
2821 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2824 attrlen
+= sizeof(struct isakmp_data
);
2826 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2828 switch (sa
->dh_group
) {
2829 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2830 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2831 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2832 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2833 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2834 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2835 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2836 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2837 /* don't attach group type for known groups */
2838 attrlen
+= sizeof(struct isakmp_data
);
2840 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2844 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2845 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2846 /* don't attach group type for known groups */
2847 attrlen
+= sizeof(struct isakmp_data
);
2849 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2850 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2862 setph2proposal0(iph2
, pp
, pr
)
2863 const phase2_handle_t
*iph2
;
2864 const struct saprop
*pp
;
2865 const struct saproto
*pr
;
2868 struct isakmp_pl_p
*prop
;
2869 struct isakmp_pl_t
*trns
;
2874 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2875 const u_int8_t
*spi
;
2877 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2881 /* create proposal */
2882 prop
= (struct isakmp_pl_p
*)p
->v
;
2883 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2884 prop
->p_no
= pp
->prop_no
;
2885 prop
->proto_id
= pr
->proto_id
;
2888 spi
= (const u_int8_t
*)&pr
->spi
;
2889 switch (pr
->proto_id
) {
2890 case IPSECDOI_PROTO_IPCOMP
:
2892 * draft-shacham-ippcp-rfc2393bis-05.txt:
2893 * construct 16bit SPI (CPI).
2894 * XXX we may need to provide a configuration option to
2895 * generate 32bit SPI. otherwise we cannot interoeprate
2896 * with nodes that uses 32bit SPI, in case we are initiator.
2898 prop
->spi_size
= sizeof(u_int16_t
);
2899 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2900 p
->l
-= sizeof(pr
->spi
);
2901 p
->l
+= sizeof(u_int16_t
);
2904 prop
->spi_size
= sizeof(pr
->spi
);
2907 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2909 /* create transform */
2910 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2913 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2915 switch (pr
->proto_id
) {
2916 case IPSECDOI_PROTO_IPSEC_ESP
:
2918 * don't build a null encryption
2919 * with no authentication transform.
2921 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2922 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
2928 *np_t
= ISAKMP_NPTYPE_T
;
2932 /* get attribute length */
2935 attrlen
+= sizeof(struct isakmp_data
)
2936 + sizeof(struct isakmp_data
);
2937 if (pp
->lifetime
> 0xffff)
2938 attrlen
+= sizeof(u_int32_t
);
2940 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2941 attrlen
+= sizeof(struct isakmp_data
)
2942 + sizeof(struct isakmp_data
);
2943 if (pp
->lifebyte
> 0xffff)
2944 attrlen
+= sizeof(u_int32_t
);
2946 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2948 attrlen
+= sizeof(struct isakmp_data
);
2950 switch (pr
->proto_id
) {
2951 case IPSECDOI_PROTO_IPSEC_ESP
:
2952 /* non authentication mode ? */
2953 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2954 attrlen
+= sizeof(struct isakmp_data
);
2956 case IPSECDOI_PROTO_IPSEC_AH
:
2957 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2959 "no authentication algorithm found "
2960 "but protocol is AH.\n");
2964 attrlen
+= sizeof(struct isakmp_data
);
2966 case IPSECDOI_PROTO_IPCOMP
:
2970 "invalid protocol: %d\n", pr
->proto_id
);
2975 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2976 attrlen
+= sizeof(struct isakmp_data
);
2978 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2981 prop
= (struct isakmp_pl_p
*)p
->v
;
2983 /* set transform's values */
2984 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2985 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2986 trns
->t_no
= tr
->trns_no
;
2987 trns
->t_id
= tr
->trns_id
;
2989 /* set attributes */
2990 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
2993 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2994 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
2995 if (pp
->lifetime
> 0xffff) {
2996 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
2997 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2998 (caddr_t
)&v
, sizeof(v
));
3000 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3005 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3006 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3007 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
3008 if (pp
->lifebyte
> 0xffff) {
3009 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
3010 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3011 (caddr_t
)&v
, sizeof(v
));
3013 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3018 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
3021 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
3023 /* mandatory check has done above. */
3024 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3025 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
3026 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
3028 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3029 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
3030 iph2
->sainfo
->pfs_group
);
3032 /* update length of this transform. */
3033 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3034 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
3036 /* save buffer to pre-next payload */
3039 trnsoff
+= (sizeof(*trns
) + attrlen
);
3044 "no suitable proposal was created.\n");
3048 /* update length of this protocol. */
3049 prop
->h
.len
= htons(p
->l
);
3055 * create phase2 proposal from policy configuration.
3056 * NOT INCLUDING isakmp general header of SA payload.
3057 * This function is called by initiator only.
3060 ipsecdoi_setph2proposal(phase2_handle_t
*iph2
, int return_sa
)
3062 struct saprop
*proposal
, *a
;
3063 struct saproto
*b
= NULL
;
3064 vchar_t
*q
, *sa
= NULL
;
3065 struct isakmp_pl_p
*prop
;
3066 size_t propoff
; /* for previous field of type of next payload. */
3069 proposal
= iph2
->approval
;
3071 proposal
= iph2
->proposal
;
3073 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
3074 struct ipsecdoi_sa_b
*sab
;
3076 sa
= vmalloc(sizeof(*sab
));
3079 "failed to allocate my sa buffer\n");
3083 /* create SA payload */
3084 sab
= ALIGNED_CAST(struct ipsecdoi_sa_b
*)sa
->v
;
3085 sab
->doi
= htonl(IPSEC_DOI
);
3086 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3092 for (a
= proposal
; a
; a
= a
->next
) {
3093 for (b
= a
->head
; b
; b
= b
->next
) {
3094 if (b
->proto_id
== IPSECDOI_PROTO_IPCOMP
) {
3095 // skip this - not specified in the SA
3096 // Need to set this in iph2 ???
3099 // IKEv1 sends encode mode in SA - uses diferent codes when NATT being used
3101 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3102 plog (ASL_LEVEL_NOTICE
, "NAT detected -> UDP encapsulation\n");
3104 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
3105 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3106 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3107 b
->encmode
+= udp_diff
;
3111 switch (iph2
->version
) {
3112 case ISAKMP_VERSION_NUMBER_IKEV1
:
3113 q
= setph2proposal0(iph2
, a
, b
);
3116 plog(ASL_LEVEL_ERR
, "Invalid IKE version detected\n");
3125 sa
= vrealloc(sa
, sa
->l
+ q
->l
);
3131 "failed to allocate my sa buffer\n");
3136 memcpy(sa
->v
+ sa
->l
- q
->l
, q
->v
, q
->l
);
3138 prop
= (struct isakmp_pl_p
*)(sa
->v
+
3140 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
3141 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3143 propoff
= sa
->l
- q
->l
;
3156 * return 1 if all of the given protocols are tunnel mode.
3159 ipsecdoi_tunnelmode(iph2
)
3160 phase2_handle_t
*iph2
;
3163 struct saproto
*pr
= NULL
;
3165 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
3166 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3167 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
3168 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
3169 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
3178 * return 1 if any of the given protocols are transport mode.
3181 ipsecdoi_any_transportmode(pp
)
3184 struct saproto
*pr
= NULL
;
3186 for (; pp
; pp
= pp
->next
) {
3187 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3188 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TRNS
||
3189 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
||
3190 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
3199 * return 1 if all of the given protocols are transport mode.
3202 ipsecdoi_transportmode(pp
)
3205 struct saproto
*pr
= NULL
;
3207 for (; pp
; pp
= pp
->next
) {
3208 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3209 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
3218 ipsecdoi_get_defaultlifetime()
3220 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3224 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3225 int proto_id
, enc
, auth
, comp
;
3227 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3229 case IPSECDOI_PROTO_IPSEC_ESP
:
3230 if (enc
== 0 || comp
!= 0) {
3232 "illegal algorithm defined "
3233 "ESP enc=%s auth=%s comp=%s.\n",
3234 TMPALGTYPE2STR(enc
),
3235 TMPALGTYPE2STR(auth
),
3236 TMPALGTYPE2STR(comp
));
3240 case IPSECDOI_PROTO_IPSEC_AH
:
3241 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3243 "illegal algorithm defined "
3244 "AH enc=%s auth=%s comp=%s.\n",
3245 TMPALGTYPE2STR(enc
),
3246 TMPALGTYPE2STR(auth
),
3247 TMPALGTYPE2STR(comp
));
3251 case IPSECDOI_PROTO_IPCOMP
:
3252 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3254 "illegal algorithm defined "
3255 "IPcomp enc=%s auth=%s comp=%s.\n",
3256 TMPALGTYPE2STR(enc
),
3257 TMPALGTYPE2STR(auth
),
3258 TMPALGTYPE2STR(comp
));
3264 "invalid ipsec protocol %d\n", proto_id
);
3267 #undef TMPALGTYPE2STR
3277 return IPSECDOI_PROTO_IPSEC_AH
;
3279 return IPSECDOI_PROTO_IPSEC_ESP
;
3280 case IPPROTO_IPCOMP
:
3281 return IPSECDOI_PROTO_IPCOMP
;
3283 return -1; /* XXX */
3291 case IPSECDOI_PROTO_IPSEC_AH
:
3293 case IPSECDOI_PROTO_IPSEC_ESP
:
3295 case IPSECDOI_PROTO_IPCOMP
:
3296 return IPPROTO_IPCOMP
;
3298 return -1; /* XXX */
3302 * Check if a subnet id is valid for comparison
3303 * with an address id ( address length mask )
3311 ipsecdoi_subnetisaddr_v4( subnet
, address
)
3312 const vchar_t
*subnet
;
3313 const vchar_t
*address
;
3315 struct in_addr
*mask
;
3317 if (address
->l
!= sizeof(struct in_addr
))
3320 if (subnet
->l
!= (sizeof(struct in_addr
)*2))
3323 mask
= ALIGNED_CAST(struct in_addr
*)(subnet
->v
+ sizeof(struct in_addr
));
3325 if (mask
->s_addr
!=0xffffffff)
3328 return memcmp(subnet
->v
,address
->v
,address
->l
);
3334 ipsecdoi_subnetisaddr_v6( subnet
, address
)
3335 const vchar_t
*subnet
;
3336 const vchar_t
*address
;
3338 struct in6_addr
*mask
;
3341 if (address
->l
!= sizeof(struct in6_addr
))
3344 if (subnet
->l
!= (sizeof(struct in6_addr
)*2))
3347 mask
= ALIGNED_CAST(struct in6_addr
*)(subnet
->v
+ sizeof(struct in6_addr
));
3349 for (i
=0; i
<16; i
++)
3350 if(mask
->s6_addr
[i
]!=0xff)
3353 return memcmp(subnet
->v
,address
->v
,address
->l
);
3360 * Check and Compare two IDs
3361 * - specify 0 for exact if wildcards are allowed
3365 * = -1 for integrity error
3369 ipsecdoi_chkcmpids( idt
, ids
, exact
)
3370 const vchar_t
*idt
; /* id cmp target */
3371 const vchar_t
*ids
; /* id cmp source */
3374 struct ipsecdoi_id_b
*id_bt
;
3375 struct ipsecdoi_id_b
*id_bs
;
3380 /* handle wildcard IDs */
3382 if (idt
== NULL
|| ids
== NULL
)
3386 plog(ASL_LEVEL_DEBUG
,
3387 "check and compare ids : values matched (ANONYMOUS)\n" );
3392 plog(ASL_LEVEL_DEBUG
,
3393 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3398 /* make sure the ids are of the same type */
3400 id_bt
= (struct ipsecdoi_id_b
*) idt
->v
;
3401 id_bs
= (struct ipsecdoi_id_b
*) ids
->v
;
3403 ident_t
.v
= idt
->v
+ sizeof(*id_bt
);
3404 ident_t
.l
= idt
->l
- sizeof(*id_bt
);
3405 ident_s
.v
= ids
->v
+ sizeof(*id_bs
);
3406 ident_s
.l
= ids
->l
- sizeof(*id_bs
);
3408 if (id_bs
->type
!= id_bt
->type
)
3411 * special exception for comparing
3412 * address to subnet id types when
3413 * the netmask is address length
3416 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR
)&&
3417 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)) {
3418 result
= ipsecdoi_subnetisaddr_v4(&ident_t
,&ident_s
);
3422 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)&&
3423 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR
)) {
3424 result
= ipsecdoi_subnetisaddr_v4(&ident_s
,&ident_t
);
3429 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR
)&&
3430 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)) {
3431 result
= ipsecdoi_subnetisaddr_v6(&ident_t
,&ident_s
);
3435 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)&&
3436 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR
)) {
3437 result
= ipsecdoi_subnetisaddr_v6(&ident_s
,&ident_t
);
3441 plog(ASL_LEVEL_DEBUG
,
3442 "check and compare ids : id type mismatch %s != %s\n",
3443 s_ipsecdoi_ident(id_bs
->type
),
3444 s_ipsecdoi_ident(id_bt
->type
));
3449 if(id_bs
->proto_id
!= id_bt
->proto_id
){
3450 plog(ASL_LEVEL_DEBUG
,
3451 "check and compare ids : proto_id mismatch %d != %d\n",
3452 id_bs
->proto_id
, id_bt
->proto_id
);
3457 /* compare the ID data. */
3459 switch (id_bt
->type
) {
3460 case IPSECDOI_ID_DER_ASN1_DN
:
3461 case IPSECDOI_ID_DER_ASN1_GN
:
3462 /* compare asn1 ids */
3463 result
= eay_cmp_asn1dn(&ident_t
, &ident_s
);
3466 case IPSECDOI_ID_IPV4_ADDR
:
3467 /* validate lengths */
3468 if ((ident_t
.l
!= sizeof(struct in_addr
))||
3469 (ident_s
.l
!= sizeof(struct in_addr
)))
3473 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3474 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3475 /* validate lengths */
3476 if ((ident_t
.l
!= (sizeof(struct in_addr
)*2))||
3477 (ident_s
.l
!= (sizeof(struct in_addr
)*2)))
3482 case IPSECDOI_ID_IPV6_ADDR
:
3483 /* validate lengths */
3484 if ((ident_t
.l
!= sizeof(struct in6_addr
))||
3485 (ident_s
.l
!= sizeof(struct in6_addr
)))
3489 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3490 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3491 /* validate lengths */
3492 if ((ident_t
.l
!= (sizeof(struct in6_addr
)*2))||
3493 (ident_s
.l
!= (sizeof(struct in6_addr
)*2)))
3497 case IPSECDOI_ID_FQDN
:
3498 case IPSECDOI_ID_USER_FQDN
:
3499 case IPSECDOI_ID_KEY_ID
:
3504 "Unhandled id type %i specified for comparison\n",
3509 /* validate matching data and length */
3510 if (ident_t
.l
== ident_s
.l
)
3511 result
= memcmp(ident_t
.v
,ident_s
.v
,ident_t
.l
);
3517 /* debug level output */
3518 if(loglevel
>= ASL_LEVEL_DEBUG
) {
3519 char *idstrt
= ipsecdoi_id2str(idt
);
3520 char *idstrs
= ipsecdoi_id2str(ids
);
3523 plog(ASL_LEVEL_DEBUG
,
3524 "check and compare ids : values matched (%s)\n",
3525 s_ipsecdoi_ident(id_bs
->type
) );
3527 plog(ASL_LEVEL_DEBUG
,
3528 "check and compare ids : value mismatch (%s)\n",
3529 s_ipsecdoi_ident(id_bs
->type
));
3531 plog(ASL_LEVEL_DEBUG
, "cmpid target: \'%s\'\n", idstrt
);
3532 plog(ASL_LEVEL_DEBUG
, "cmpid source: \'%s\'\n", idstrs
);
3534 racoon_free(idstrs
);
3535 racoon_free(idstrt
);
3546 /* id integrity error */
3547 plog(ASL_LEVEL_DEBUG
, "check and compare ids : %s integrity error\n",
3548 s_ipsecdoi_ident(id_bs
->type
));
3549 plog(ASL_LEVEL_DEBUG
, "cmpid target: length = \'%zu\'\n", ident_t
.l
);
3550 plog(ASL_LEVEL_DEBUG
, "cmpid source: length = \'%zu\'\n", ident_s
.l
);
3557 * check the following:
3558 * - In main mode with pre-shared key, only address type can be used.
3559 * - if proper type for phase 1 ?
3560 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3561 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3562 * - if ID payload sent from peer is equal to the ID expected by me.
3564 * both of "id" and "id_p" should be ID payload without general header,
3567 ipsecdoi_checkid1(iph1
)
3568 phase1_handle_t
*iph1
;
3570 struct ipsecdoi_id_b
*id_b
;
3571 struct sockaddr_storage
*sa
;
3574 if (iph1
->id_p
== NULL
) {
3576 "invalid iph1 passed id_p == NULL\n");
3577 return ISAKMP_INTERNAL_ERROR
;
3579 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3581 "invalid value passed as \"ident\" (len=%lu)\n",
3582 (u_long
)iph1
->id_p
->l
);
3583 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3586 id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3588 /* In main mode with pre-shared key, only address type can be used.
3589 * If NAT Traversal being used and peer is behind nat and
3590 * natt version = 02 - allow non-address ID type.
3592 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
3593 && iph1
->etype
== ISAKMP_ETYPE_IDENT
3594 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3596 && (iph1
->natt_flags
& NAT_DETECTED_PEER
) == 0
3599 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3600 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3602 "Expecting IP address type in main mode, "
3603 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3604 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3608 /* if proper type for phase 1 ? */
3609 switch (id_b
->type
) {
3610 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3611 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3612 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3613 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3614 plog(ASL_LEVEL_WARNING
,
3615 "such ID type %s is not proper.\n",
3616 s_ipsecdoi_ident(id_b
->type
));
3620 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3621 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
||
3622 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3624 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3625 plog(ASL_LEVEL_WARNING
,
3626 "protocol ID and Port mismatched. "
3627 "proto_id:%d port:%d\n",
3628 id_b
->proto_id
, ntohs(id_b
->port
));
3631 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3633 * copmaring with expected port.
3634 * always permit if port is equal to PORT_ISAKMP
3636 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3640 switch (iph1
->remote
->ss_family
) {
3642 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3646 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3651 "invalid family: %d\n",
3652 iph1
->remote
->ss_family
);
3653 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3655 if (ntohs(id_b
->port
) != port
) {
3656 plog(ASL_LEVEL_WARNING
,
3657 "port %d expected, but %d\n",
3658 port
, ntohs(id_b
->port
));
3665 /* compare with the ID if specified. */
3666 if (genlist_next(iph1
->rmconf
->idvl_p
, 0)) {
3667 vchar_t
*ident0
= NULL
;
3672 struct genlist_entry
*gpb
;
3674 for (id
= genlist_next (iph1
->rmconf
->idvl_p
, &gpb
); id
; id
= genlist_next (0, &gpb
)) {
3675 /* check the type of both IDs */
3676 if (id
->idtype
!= doi2idtype(id_b
->type
))
3677 continue; /* ID type mismatch */
3681 /* compare defined ID with the ID sent by peer. */
3684 ident0
= getidval(id
->idtype
, id
->id
);
3686 switch (id
->idtype
) {
3689 ident
.v
= iph1
->id_p
->v
+ sizeof(*id_b
);
3690 ident
.l
= iph1
->id_p
->l
- sizeof(*id_b
);
3691 if (eay_cmp_asn1dn(ident0
, &ident
) == 0)
3694 plog(ASL_LEVEL_WARNING
, "ASN1DN ID matching not implemented - passed.\n");
3695 goto matched
; //%%%%%% hack for now until we have code to do this.
3698 case IDTYPE_ADDRESS
:
3699 sa
= ALIGNED_CAST(struct sockaddr_storage
*)ident0
->v
;
3700 sa2
= (caddr_t
)(id_b
+ 1);
3701 switch (sa
->ss_family
) {
3703 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3704 continue; /* ID value mismatch */
3705 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3706 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) == 0)
3711 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3712 continue; /* ID value mismatch */
3713 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3714 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) == 0)
3723 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
) == 0)
3728 if (ident0
!= NULL
) {
3732 plog(ASL_LEVEL_DEBUG
, "No ID match.\n");
3733 if (iph1
->rmconf
->verify_identifier
)
3734 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3735 matched
: /* ID value match */
3743 /* HACK!!! - temporary until this prototype gets moved */
3744 extern CFDataRef
SecCertificateCopySubjectSequence( SecCertificateRef certificate
);
3747 * create ID payload for phase 1 and set into iph1->id.
3748 * NOT INCLUDING isakmp general header.
3749 * see, RFC2407 4.6.2.1
3752 ipsecdoi_setid1(iph1
)
3753 phase1_handle_t
*iph1
;
3755 vchar_t
*ret
= NULL
;
3756 struct ipsecdoi_id_b id_b
;
3757 vchar_t
*ident
= NULL
;
3758 struct sockaddr_in v4_address
;
3759 struct sockaddr_storage
*ipid
= NULL
;
3762 bzero(&id_b
, sizeof(id_b
));
3764 switch (iph1
->rmconf
->idvtype
) {
3766 id_b
.type
= IPSECDOI_ID_FQDN
;
3767 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3769 case IDTYPE_USERFQDN
:
3770 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3771 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3774 case IDTYPE_KEYIDUSE
:
3775 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3776 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3779 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3780 if (iph1
->rmconf
->idv
) {
3781 /* XXX it must be encoded to asn1dn. */
3782 ident
= vdup(iph1
->rmconf
->idv
);
3784 if (oakley_getmycert(iph1
) < 0) {
3786 "failed to get own CERT.\n");
3790 SecCertificateRef certificate
;
3795 certificate
= crypto_cssm_x509cert_CreateSecCertificateRef(&iph1
->cert
->cert
);
3796 if (certificate
== NULL
) {
3798 "failed to get SecCertificateRef\n");
3801 subject
= crypto_cssm_CopySubjectSequence(certificate
);
3802 if (subject
== NULL
) {
3804 "failed to get subjectName\n");
3805 CFRelease(certificate
);
3808 len
= CFDataGetLength(subject
);
3809 namePtr
= (UInt8
*)CFDataGetBytePtr(subject
);
3810 ident
= vmalloc(len
);
3811 if (ident
== NULL
) {
3813 "failed to get subjectName\n");
3814 CFRelease(certificate
);
3818 memcpy(ident
->v
, namePtr
, len
);
3819 CFRelease(certificate
);
3823 case IDTYPE_ADDRESS
:
3825 * if the value of the id type was set by the configuration
3826 * file, then use it. otherwise the value is get from local
3827 * ip address by using ike negotiation.
3829 if (iph1
->rmconf
->idv
)
3830 ipid
= ALIGNED_CAST(struct sockaddr_storage
*)iph1
->rmconf
->idv
->v
;
3841 if (ipid
->ss_family
== AF_INET6
&&
3842 iph1
->nat64_prefix
.length
) {
3843 memset(&v4_address
, 0, sizeof(v4_address
));
3844 v4_address
.sin_len
= sizeof(struct sockaddr_in
);
3845 v4_address
.sin_family
= AF_INET
;
3846 v4_address
.sin_port
= ((struct sockaddr_in6
*)ipid
)->sin6_port
;
3847 v4_address
.sin_addr
.s_addr
= 0;
3849 ipid
= ALIGNED_CAST(struct sockaddr_storage
*)&v4_address
;
3853 /* use IP address */
3854 switch (ipid
->ss_family
) {
3856 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3857 l
= sizeof(struct in_addr
);
3858 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3862 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3863 l
= sizeof(struct in6_addr
);
3864 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3869 "invalid address family.\n");
3872 if(iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
){
3873 id_b
.proto_id
= IPPROTO_UDP
;
3874 id_b
.port
= htons(PORT_ISAKMP
);
3880 "failed to get ID buffer.\n");
3883 memcpy(ident
->v
, p
, ident
->l
);
3888 "failed to get ID buffer.\n");
3892 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3895 "failed to get ID buffer.\n");
3899 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3900 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3904 plogdump(ASL_LEVEL_DEBUG
, iph1
->id
->v
, iph1
->id
->l
, "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3912 plog(ASL_LEVEL_ERR
, "failed get my ID\n");
3921 vchar_t
*new = NULL
;
3925 else if (lcconf
->ident
[type
])
3926 new = vdup(lcconf
->ident
[type
]);
3931 /* it's only called by cfparse.y. */
3933 set_identifier(vpp
, type
, value
)
3934 vchar_t
**vpp
, *value
;
3937 return set_identifier_qual(vpp
, type
, value
, IDQUAL_UNSPEC
);
3941 set_identifier_qual(vpp
, type
, value
, qual
)
3942 vchar_t
**vpp
, *value
;
3946 vchar_t
*new = NULL
;
3948 /* simply return if value is null. */
3950 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3952 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3960 case IDTYPE_USERFQDN
:
3963 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3966 case IDTYPE_KEYIDUSE
:
3967 #ifdef ENABLE_HYBRID
3970 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3971 new = vmalloc(value
->l
- 1);
3974 memcpy(new->v
, value
->v
, new->l
);
3978 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3979 * to use a file for backward compatibility sake.
3983 case IDQUAL_UNSPEC
: {
3988 fp
= fopen(value
->v
, "r");
3991 "can not open %s\n", value
->v
);
3995 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3996 new = vrealloc(new, tlen
+ len
);
4001 memcpy(new->v
+ tlen
, b
, len
);
4009 new = vmalloc(value
->l
- 1);
4012 "can not allocate memory");
4015 memcpy(new->v
, value
->v
, new->l
);
4020 "unknown qualifier");
4025 case IDTYPE_ADDRESS
: {
4026 struct sockaddr_storage
*sa
;
4028 /* length is adjusted since QUOTEDSTRING teminates NULL. */
4032 sa
= str2saddr(value
->v
, NULL
);
4035 "invalid ip address %s\n", value
->v
);
4039 new = vmalloc(sysdep_sa_len((struct sockaddr
*)sa
));
4044 memcpy(new->v
, sa
, new->l
);
4049 plog(ASL_LEVEL_DEBUG
, "Setting ID type ASN1DN from string not supported\n");
4061 * create ID payload for phase 2, and set into iph2->id and id_p. There are
4062 * NOT INCLUDING isakmp general header.
4063 * this function is for initiator. responder will get to copy from payload.
4064 * responder ID type is always address type.
4065 * see, RFC2407 4.6.2.1
4068 ipsecdoi_setid2(iph2
)
4069 phase2_handle_t
*iph2
;
4071 struct secpolicy
*sp
;
4073 /* check there is phase 2 handler ? */
4074 sp
= getspbyspid(iph2
->spid
);
4077 "no policy found for spid:%u.\n", iph2
->spid
);
4081 struct sockaddr_in local_v4_address
;
4082 struct sockaddr_storage
*srcaddr
= &sp
->spidx
.src
;
4083 u_int8_t prefs
= sp
->spidx
.prefs
;
4084 if (sp
->spidx
.dst
.ss_family
== AF_INET6
&&
4085 iph2
->nat64_prefix
.length
) {
4086 memset(&local_v4_address
, 0, sizeof(local_v4_address
));
4087 local_v4_address
.sin_len
= sizeof(struct sockaddr_in
);
4088 local_v4_address
.sin_family
= AF_INET
;
4089 local_v4_address
.sin_port
= ((struct sockaddr_in6
*)&sp
->spidx
.src
)->sin6_port
;
4090 // Setting a fixed IPv4 address to avoid FATAL-ID issue with 0.0.0.0 IPv4 address
4091 inet_pton(AF_INET
, "192.168.2.2", &local_v4_address
.sin_addr
);
4092 srcaddr
= ALIGNED_CAST(struct sockaddr_storage
*)&local_v4_address
;
4095 iph2
->id
= ipsecdoi_sockaddr2id(srcaddr
,
4096 prefs
, sp
->spidx
.ul_proto
);
4097 if (iph2
->id
== NULL
) {
4099 "failed to get ID for %s\n",
4100 spidx2str(&sp
->spidx
));
4104 if (((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR
||
4105 (ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
) &&
4106 iph2
->side
== RESPONDER
&&
4107 iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED_ME
) &&
4108 lcconf
->ext_nat_id
) {
4110 if (!(iph2
->id
= vdup(lcconf
->ext_nat_id
))) {
4115 plogdump(ASL_LEVEL_DEBUG
, iph2
->id
->v
, iph2
->id
->l
, "use local ID type %s\n",
4116 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
4119 struct sockaddr_in v4_address
;
4120 struct sockaddr_storage
*dstaddr
= &sp
->spidx
.dst
;
4121 u_int8_t prefd
= sp
->spidx
.prefd
;
4122 if (sp
->spidx
.dst
.ss_family
== AF_INET6
&&
4123 iph2
->nat64_prefix
.length
) {
4124 memset(&v4_address
, 0, sizeof(v4_address
));
4125 v4_address
.sin_len
= sizeof(struct sockaddr_in
);
4126 v4_address
.sin_family
= AF_INET
;
4127 v4_address
.sin_port
= ((struct sockaddr_in6
*)&sp
->spidx
.dst
)->sin6_port
;
4128 nw_nat64_extract_v4(&iph2
->nat64_prefix
, &((struct sockaddr_in6
*)&sp
->spidx
.dst
)->sin6_addr
, &v4_address
.sin_addr
);
4130 dstaddr
= ALIGNED_CAST(struct sockaddr_storage
*)&v4_address
;
4133 iph2
->id_p
= ipsecdoi_sockaddr2id(dstaddr
,
4134 prefd
, sp
->spidx
.ul_proto
);
4135 if (iph2
->id_p
== NULL
) {
4137 "failed to get ID for %s\n",
4138 spidx2str(&sp
->spidx
));
4142 plogdump(ASL_LEVEL_DEBUG
, iph2
->id_p
->v
, iph2
->id_p
->l
, "use remote ID type %s\n",
4143 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
4149 * set address type of ID.
4150 * NOT INCLUDING general header.
4153 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
4154 struct sockaddr_storage
*saddr
;
4159 int type
, len1
, len2
;
4164 * Q. When type is SUBNET, is it allowed to be ::1/128.
4165 * A. Yes. (consensus at bake-off)
4167 switch (saddr
->ss_family
) {
4169 len1
= sizeof(struct in_addr
);
4170 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
4171 type
= IPSECDOI_ID_IPV4_ADDR
;
4173 } else if (prefixlen
< (sizeof(struct in_addr
) << 3)) {
4174 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
4175 len2
= sizeof(struct in_addr
);
4178 "invalid prefix length: %d.\n", prefixlen
);
4181 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
4182 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
4186 len1
= sizeof(struct in6_addr
);
4187 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
4188 type
= IPSECDOI_ID_IPV6_ADDR
;
4190 } else if (prefixlen
< (sizeof(struct in6_addr
) << 3)) {
4191 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
4192 len2
= sizeof(struct in6_addr
);
4195 "invalid prefix length: %d.\n", prefixlen
);
4198 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
4199 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
4204 "invalid family: %d.\n", saddr
->ss_family
);
4209 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4212 "failed to get ID buffer.\n");
4216 memset(new->v
, 0, new->l
);
4218 /* set the part of header. */
4219 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4221 /* set ul_proto and port */
4223 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4224 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4226 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4227 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4228 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4229 port
== IPSEC_PORT_ANY
? 0 : port
;
4230 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
4236 u_char
*p
= (unsigned char *) new->v
+
4237 sizeof(struct ipsecdoi_id_b
) + len1
;
4238 u_int bits
= prefixlen
;
4246 *p
= ~((1 << (8 - bits
)) - 1);
4253 ipsecdoi_sockrange2id(laddr
, haddr
, ul_proto
)
4254 struct sockaddr_storage
*laddr
, *haddr
;
4258 int type
, len1
, len2
;
4261 if (laddr
->ss_family
!= haddr
->ss_family
) {
4262 plog(ASL_LEVEL_ERR
, "Address family mismatch\n");
4266 switch (laddr
->ss_family
) {
4268 type
= IPSECDOI_ID_IPV4_ADDR_RANGE
;
4269 len1
= sizeof(struct in_addr
);
4270 len2
= sizeof(struct in_addr
);
4274 type
= IPSECDOI_ID_IPV6_ADDR_RANGE
;
4275 len1
= sizeof(struct in6_addr
);
4276 len2
= sizeof(struct in6_addr
);
4281 "invalid family: %d.\n", laddr
->ss_family
);
4286 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4289 "failed to get ID buffer.\n");
4293 memset(new->v
, 0, new->l
);
4294 /* set the part of header. */
4295 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4297 /* set ul_proto and port */
4299 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4300 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4302 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4303 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4304 port
= ((struct sockaddr_in
*)(laddr
))->sin_port
;
4305 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4306 port
== IPSEC_PORT_ANY
? 0 : port
;
4307 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
),
4308 (caddr_t
)&((struct sockaddr_in
*)(laddr
))->sin_addr
,
4310 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
,
4311 (caddr_t
)&((struct sockaddr_in
*)haddr
)->sin_addr
,
4318 * create sockaddr_storage structure from ID payload (buf).
4319 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4320 * see, RFC2407 4.6.2.1
4323 ipsecdoi_id2sockaddr(vchar_t
*buf
,
4324 struct sockaddr_storage
*saddr
,
4325 u_int8_t
*prefixlen
,
4326 u_int16_t
*ul_proto
,
4329 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)buf
->v
;
4333 * When a ID payload of subnet type with a IP address of full bit
4334 * masked, it has to be processed as host address.
4335 * e.g. below 2 type are same.
4336 * type = ipv6 subnet, data = 2001::1/128
4337 * type = ipv6 address, data = 2001::1
4339 switch (id_b
->type
) {
4340 case IPSECDOI_ID_IPV4_ADDR
:
4341 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4342 saddr
->ss_len
= sizeof(struct sockaddr_in
);
4343 saddr
->ss_family
= AF_INET
;
4344 ((struct sockaddr_in
*)saddr
)->sin_port
=
4347 : id_b
->port
); /* see sockaddr2id() */
4348 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
4349 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4352 case IPSECDOI_ID_IPV6_ADDR
:
4353 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4354 saddr
->ss_len
= sizeof(struct sockaddr_in6
);
4355 saddr
->ss_family
= AF_INET6
;
4356 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
4359 : id_b
->port
); /* see sockaddr2id() */
4360 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
4361 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4366 "unsupported ID type %d\n", id_b
->type
);
4367 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
4370 /* get prefix length */
4371 switch (id_b
->type
) {
4372 case IPSECDOI_ID_IPV4_ADDR
:
4373 plen
= sizeof(struct in_addr
) << 3;
4376 case IPSECDOI_ID_IPV6_ADDR
:
4377 plen
= sizeof(struct in6_addr
) << 3;
4380 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4382 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4387 int alen
= sizeof(struct in_addr
);
4389 switch (id_b
->type
) {
4390 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4391 alen
= sizeof(struct in_addr
);
4394 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4395 alen
= sizeof(struct in6_addr
);
4402 return ISAKMP_INTERNAL_ERROR
;
4404 /* get subnet mask length */
4408 p
= (unsigned char *) buf
->v
4409 + sizeof(struct ipsecdoi_id_b
)
4412 for (; *p
== 0xff; p
++) {
4435 if (version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
4436 *ul_proto
= id_b
->proto_id
== 0 ? IPSEC_ULPROTO_ANY
: id_b
->proto_id
; /* see sockaddr2id() */
4443 * make printable string from ID payload except of general header.
4453 static char buf
[BUFLEN
];
4454 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)id
->v
;
4455 struct sockaddr_storage saddr
;
4458 bzero(&saddr
, sizeof(saddr
));
4460 switch (id_b
->type
) {
4461 case IPSECDOI_ID_IPV4_ADDR
:
4462 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4463 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4465 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4466 saddr
.ss_family
= AF_INET
;
4467 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4468 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4469 id
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4472 case IPSECDOI_ID_IPV6_ADDR
:
4473 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4474 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4475 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4476 saddr
.ss_family
= AF_INET6
;
4477 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4478 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4479 id
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4480 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4481 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4482 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4488 switch (id_b
->type
) {
4489 case IPSECDOI_ID_IPV4_ADDR
:
4491 case IPSECDOI_ID_IPV6_ADDR
:
4493 len
= snprintf( buf
, sizeof(buf
), "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4496 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4498 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4503 int alen
= sizeof(struct in_addr
);
4505 switch (id_b
->type
) {
4506 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4507 alen
= sizeof(struct in_addr
);
4510 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4511 alen
= sizeof(struct in6_addr
);
4522 /* get subnet mask length */
4526 p
= (unsigned char *) id
->v
4527 + sizeof(struct ipsecdoi_id_b
)
4530 for (; *p
== 0xff; p
++) {
4549 len
= snprintf( buf
, sizeof(buf
), "%s/%i", saddrwop2str((struct sockaddr
*)&saddr
), plen
);
4553 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4555 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4557 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4558 saddr
.ss_family
= AF_INET
;
4559 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4560 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4561 id
->v
+ sizeof(*id_b
) + sizeof(struct in_addr
),
4562 sizeof(struct in_addr
));
4565 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4571 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4573 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4575 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4576 saddr
.ss_family
= AF_INET6
;
4577 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4578 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4579 id
->v
+ sizeof(*id_b
) + sizeof(struct in6_addr
),
4580 sizeof(struct in6_addr
));
4581 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4582 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4583 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4587 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4593 case IPSECDOI_ID_FQDN
:
4594 case IPSECDOI_ID_USER_FQDN
:
4595 len
= id
->l
- sizeof(*id_b
);
4598 memcpy(buf
, id
->v
+ sizeof(*id_b
), len
);
4601 case IPSECDOI_ID_DER_ASN1_DN
:
4602 case IPSECDOI_ID_DER_ASN1_GN
:
4605 X509_NAME
*xn
= NULL
;
4608 dat
= id
->v
+ sizeof(*id_b
);
4609 len
= id
->l
- sizeof(*id_b
);
4611 if (d2i_X509_NAME(&xn
, (void*) &dat
, len
) != NULL
) {
4612 BIO
*bio
= BIO_new(BIO_s_mem());
4613 X509_NAME_print_ex(bio
, xn
, 0, 0);
4614 len
= BIO_get_mem_data(bio
, &dat
);
4617 memcpy(buf
,dat
,len
);
4625 "unable to extract asn1dn from id\n");
4627 len
= snprintf(buf
, sizeof(buf
), "<ASN1-DN>");
4633 /* currently unhandled id types */
4634 case IPSECDOI_ID_KEY_ID
:
4635 len
= snprintf( buf
, sizeof(buf
), "<KEY-ID>");
4640 "unknown ID type %d\n", id_b
->type
);
4644 len
= snprintf( buf
, sizeof(buf
), "<?>");
4646 ret
= racoon_malloc(len
+1);
4648 memcpy(ret
,buf
,len
);
4656 * set IPsec data attributes into a proposal.
4657 * NOTE: MUST called per a transform.
4660 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4661 struct isakmp_pl_t
*t
;
4666 struct isakmp_data
*d
, *prev
;
4672 tr
->trns_no
= t
->t_no
;
4673 tr
->trns_id
= t
->t_id
;
4675 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4676 prev
= (struct isakmp_data
*)NULL
;
4677 d
= (struct isakmp_data
*)(t
+ 1);
4680 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4681 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4683 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4686 if (tlen
< sizeof(struct isakmp_data
)) {
4688 "ipsecdoi_t2satrns invalid length of isakmp data, expected %zu actual %d\n",
4689 sizeof(struct isakmp_data
), tlen
);
4693 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4694 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4696 plog(ASL_LEVEL_DEBUG
,
4697 "type=%s, flag=0x%04x, lorv=%s\n",
4698 s_ipsecdoi_attr(type
), flag
,
4699 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4702 case IPSECDOI_ATTR_SA_LD_TYPE
:
4704 int type
= ntohs(d
->lorv
);
4706 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4707 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4711 plog(ASL_LEVEL_WARNING
,
4712 "invalid life duration type. "
4714 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4719 case IPSECDOI_ATTR_SA_LD
:
4721 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4722 IPSECDOI_ATTR_SA_LD_TYPE
) {
4724 "life duration must follow ltype\n");
4730 vchar_t
*ld_buf
= NULL
;
4733 /* i.e. ISAKMP_GEN_TV */
4734 ld_buf
= vmalloc(sizeof(d
->lorv
));
4735 if (ld_buf
== NULL
) {
4737 "failed to get LD buffer.\n");
4740 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4742 int len
= ntohs(d
->lorv
);
4743 if ((len
+ sizeof(struct isakmp_data
)) > tlen
) {
4745 "invalid IPsec attr(%d), attr-len %d, overall-len %lu\n",
4746 type
, len
, (tlen
- sizeof(struct isakmp_data
)));
4749 /* i.e. ISAKMP_GEN_TLV */
4750 ld_buf
= vmalloc(len
);
4751 if (ld_buf
== NULL
) {
4753 "failed to get LD buffer.\n");
4756 memcpy(ld_buf
->v
, d
+ 1, len
);
4759 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4760 t
= ipsecdoi_set_ld(ld_buf
);
4764 "invalid life duration.\n");
4767 /* lifetime must be equal in a proposal. */
4768 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4770 else if (pp
->lifetime
!= t
) {
4772 "lifetime mismatched "
4774 "prev:%ld curr:%u.\n",
4775 (long)pp
->lifetime
, t
);
4779 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4780 t
= ipsecdoi_set_ld(ld_buf
);
4784 "invalid life duration.\n");
4787 /* lifebyte must be equal in a proposal. */
4788 if (pp
->lifebyte
== 0)
4790 else if (pp
->lifebyte
!= t
) {
4792 "lifebyte mismatched "
4794 "prev:%d curr:%u.\n",
4802 "invalid life type: %d\n", life_t
);
4808 case IPSECDOI_ATTR_GRP_DESC
:
4810 * RFC2407: 4.5 IPSEC Security Association Attributes
4811 * Specifies the Oakley Group to be used in a PFS QM
4812 * negotiation. For a list of supported values, see
4813 * Appendix A of [IKE].
4815 if (pp
->pfs_group
== 0)
4816 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4817 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4819 "pfs_group mismatched "
4820 "in a proposal.\n");
4825 case IPSECDOI_ATTR_ENC_MODE
:
4827 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4829 "multiple encmode exist "
4830 "in a transform.\n");
4833 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4836 case IPSECDOI_ATTR_AUTH
:
4837 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4839 "multiple authtype exist "
4840 "in a transform.\n");
4843 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4846 case IPSECDOI_ATTR_KEY_LENGTH
:
4847 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4849 "key length defined but not ESP");
4852 tr
->encklen
= ntohs(d
->lorv
);
4855 case IPSECDOI_ATTR_KEY_ROUNDS
:
4856 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4857 case IPSECDOI_ATTR_COMP_PRIVALG
:
4865 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4867 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4868 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4871 "ipsecdoi_t2satrns: packet too short - attr length %u for type %d\n",
4872 ntohs(d
->lorv
), type
);
4884 ipsecdoi_authalg2trnsid(alg
)
4888 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4889 return IPSECDOI_AH_MD5
;
4890 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4891 return IPSECDOI_AH_SHA
;
4892 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4893 return IPSECDOI_AH_SHA256
;
4894 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4895 return IPSECDOI_AH_SHA384
;
4896 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4897 return IPSECDOI_AH_SHA512
;
4898 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4899 return IPSECDOI_AH_DES
;
4900 case IPSECDOI_ATTR_AUTH_KPDK
:
4901 return IPSECDOI_AH_MD5
; /* XXX */
4904 "invalid authentication algorithm:%d\n", alg
);
4909 static int rm_idtype2doi
[] = {
4910 255, /* IDTYPE_UNDEFINED, 0 */
4911 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4912 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4913 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4914 255, /* IDTYPE_ADDRESS, 4
4915 * it expands into 4 types by another function. */
4916 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4920 * convert idtype to DOI value.
4928 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4929 return rm_idtype2doi
[idtype
];
4938 case IPSECDOI_ID_FQDN
:
4939 return(IDTYPE_FQDN
);
4940 case IPSECDOI_ID_USER_FQDN
:
4941 return(IDTYPE_USERFQDN
);
4942 case IPSECDOI_ID_KEY_ID
:
4943 return(IDTYPE_KEYID
);
4944 case IPSECDOI_ID_DER_ASN1_DN
:
4945 return(IDTYPE_ASN1DN
);
4946 case IPSECDOI_ID_IPV4_ADDR
:
4947 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4948 case IPSECDOI_ID_IPV6_ADDR
:
4949 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4950 return(IDTYPE_ADDRESS
);
4952 plog(ASL_LEVEL_WARNING
,
4953 "Inproper idtype:%s in this function.\n",
4954 s_ipsecdoi_ident(doi
));
4955 return(IDTYPE_ADDRESS
); /* XXX */
4960 #ifdef ENABLE_HYBRID
4962 switch_authmethod(authmethod
)
4965 switch(authmethod
) {
4966 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
4967 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
;
4969 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
4970 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
;
4972 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
4973 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
;
4975 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
4976 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
;
4978 /* Those are not implemented */
4979 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
4980 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
;
4982 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
4983 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
;
4985 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
4986 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
;