1 /* $Id: ipsec_doi.c,v 1.26.2.16 2006/02/02 14:37:17 vanhu Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
38 #include <netinet/in.h>
40 #ifndef HAVE_NETINET6_IPSEC
41 #include <netinet/ipsec.h>
43 #include <netinet6/ipsec.h>
51 #if TIME_WITH_SYS_TIME
52 # include <sys/time.h>
56 # include <sys/time.h>
68 #include "cfparse_proto.h"
69 #include "isakmp_var.h"
71 #include "ipsec_doi.h"
73 #include "remoteconf.h"
74 #include "localconf.h"
78 #include "algorithm.h"
81 #include "crypto_openssl.h"
82 #include "crypto_cssm.h"
87 #include "nattraversal.h"
90 static int switch_authmethod(int);
96 #ifdef HAVE_ICONV_2ND_CONST
97 #define __iconv_const const
103 int verbose_proposal_check
= 1;
105 static vchar_t
*get_ph1approval
__P((struct ph1handle
*, struct prop_pair
**));
106 static struct isakmpsa
*get_ph1approvalx
__P((struct prop_pair
*,
107 struct isakmpsa
*, struct isakmpsa
*, int));
108 static void print_ph1mismatched
__P((struct prop_pair
*, struct isakmpsa
*));
109 static int t2isakmpsa
__P((struct isakmp_pl_t
*, struct isakmpsa
*));
110 static int cmp_aproppair_i
__P((struct prop_pair
*, struct prop_pair
*));
111 static struct prop_pair
*get_ph2approval
__P((struct ph2handle
*,
112 struct prop_pair
**));
113 static struct prop_pair
*get_ph2approvalx
__P((struct ph2handle
*,
114 struct prop_pair
*));
115 static void free_proppair0
__P((struct prop_pair
*));
117 static int get_transform
118 __P((struct isakmp_pl_p
*, struct prop_pair
**, int *));
119 static u_int32_t ipsecdoi_set_ld
__P((vchar_t
*));
121 static int check_doi
__P((u_int32_t
));
122 static int check_situation
__P((u_int32_t
));
124 static int check_prot_main
__P((int));
125 static int check_prot_quick
__P((int));
126 static int (*check_protocol
[]) __P((int)) = {
127 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
128 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
131 static int check_spi_size
__P((int, int));
133 static int check_trns_isakmp
__P((int));
134 static int check_trns_ah
__P((int));
135 static int check_trns_esp
__P((int));
136 static int check_trns_ipcomp
__P((int));
137 static int (*check_transform
[]) __P((int)) = {
139 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
140 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
141 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
142 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
145 static int check_attr_isakmp
__P((struct isakmp_pl_t
*));
146 static int check_attr_ah
__P((struct isakmp_pl_t
*));
147 static int check_attr_esp
__P((struct isakmp_pl_t
*));
148 static int check_attr_ipsec
__P((int, struct isakmp_pl_t
*));
149 static int check_attr_ipcomp
__P((struct isakmp_pl_t
*));
150 static int (*check_attributes
[]) __P((struct isakmp_pl_t
*)) = {
152 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
153 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
154 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
155 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
158 static int setph1prop
__P((struct isakmpsa
*, caddr_t
));
159 static int setph1trns
__P((struct isakmpsa
*, caddr_t
));
160 static int setph1attr
__P((struct isakmpsa
*, caddr_t
));
161 static vchar_t
*setph2proposal0
__P((const struct ph2handle
*,
162 const struct saprop
*, const struct saproto
*));
164 static vchar_t
*getidval
__P((int, vchar_t
*));
167 static struct isakmpsa
*fixup_initiator_sa
__P((struct isakmpsa
*,
173 * check phase 1 SA payload.
174 * make new SA payload to be replyed not including general header.
175 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
177 * positive: the pointer to new buffer of SA payload.
178 * network byte order.
179 * NULL : error occurd.
182 ipsecdoi_checkph1proposal(sa
, iph1
)
184 struct ph1handle
*iph1
;
186 vchar_t
*newsa
; /* new SA payload approved. */
187 struct prop_pair
**pair
;
189 /* get proposal pair */
190 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
194 /* check and get one SA for use */
195 newsa
= get_ph1approval(iph1
, pair
);
202 iph1
->sa_ret
= newsa
;
208 * acceptable check for remote configuration.
209 * return a new SA payload to be reply to peer.
212 get_ph1approval(iph1
, pair
)
213 struct ph1handle
*iph1
;
214 struct prop_pair
**pair
;
217 struct isakmpsa
*sa
, tsa
;
218 struct prop_pair
*s
, *p
;
222 if (iph1
->approval
) {
223 delisakmpsa(iph1
->approval
);
224 iph1
->approval
= NULL
;
227 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
230 for (s
= pair
[i
]; s
; s
= s
->next
) {
232 sizeof(struct isakmp_pl_p
) + s
->prop
->spi_size
;
234 /* compare proposal and select one */
235 for (p
= s
; p
; p
= p
->tnext
) {
236 if ((sa
= get_ph1approvalx(p
,
237 iph1
->rmconf
->proposal
, &tsa
,
238 iph1
->rmconf
->pcheck_level
)) != NULL
)
245 * if there is no suitable proposal, racoon complains about all of
246 * mismatched items in those proposal.
248 if (verbose_proposal_check
) {
249 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
252 for (s
= pair
[i
]; s
; s
= s
->next
) {
253 prophlen
= sizeof(struct isakmp_pl_p
)
255 for (p
= s
; p
; p
= p
->tnext
) {
256 print_ph1mismatched(p
,
257 iph1
->rmconf
->proposal
);
262 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable proposal found.\n");
267 plog(LLV_DEBUG
, LOCATION
, NULL
, "an acceptable proposal found.\n");
269 /* check DH group settings */
271 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
275 plog(LLV_WARNING
, LOCATION
, NULL
,
276 "invalid DH parameter found, use default.\n");
277 oakley_dhgrp_free(sa
->dhgrp
);
281 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
289 if (sa
->gssid
!= NULL
)
290 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id in new sa '%.*s'\n",
291 (int)sa
->gssid
->l
, sa
->gssid
->v
);
292 if (iph1
-> side
== INITIATOR
) {
293 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
294 iph1
->gi_i
= vdup(iph1
->rmconf
->proposal
->gssid
);
295 if (tsa
.gssid
!= NULL
)
296 iph1
->gi_r
= vdup(tsa
.gssid
);
297 iph1
->approval
= fixup_initiator_sa(sa
, &tsa
);
299 if (tsa
.gssid
!= NULL
) {
300 iph1
->gi_r
= vdup(tsa
.gssid
);
301 iph1
->gi_i
= gssapi_get_id(iph1
);
302 if (sa
->gssid
== NULL
&& iph1
->gi_i
!= NULL
)
303 sa
->gssid
= vdup(iph1
->gi_i
);
307 if (iph1
->gi_i
!= NULL
)
308 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIi is %.*s\n",
309 (int)iph1
->gi_i
->l
, iph1
->gi_i
->v
);
310 if (iph1
->gi_r
!= NULL
)
311 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIr is %.*s\n",
312 (int)iph1
->gi_r
->l
, iph1
->gi_r
->v
);
317 plog(LLV_DEBUG
, LOCATION
, NULL
, "agreed on %s auth.\n",
318 s_oakley_attr_method(iph1
->approval
->authmethod
));
321 newsa
= get_sabyproppair(p
, iph1
);
323 delisakmpsa(iph1
->approval
);
324 iph1
->approval
= NULL
;
331 * compare peer's single proposal and all of my proposal.
332 * and select one if suiatable.
333 * p : one of peer's proposal.
334 * proposal: my proposals.
336 static struct isakmpsa
*
337 get_ph1approvalx(p
, proposal
, sap
, check_level
)
339 struct isakmpsa
*proposal
, *sap
;
342 struct isakmp_pl_p
*prop
= p
->prop
;
343 struct isakmp_pl_t
*trns
= p
->trns
;
344 struct isakmpsa sa
, *s
, *tsap
;
348 plog(LLV_DEBUG
, LOCATION
, NULL
,
349 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
350 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
351 prop
->spi_size
, prop
->num_t
);
353 plog(LLV_DEBUG
, LOCATION
, NULL
,
354 "trns#=%d, trns-id=%s\n",
356 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
358 tsap
= sap
!= NULL
? sap
: &sa
;
360 memset(tsap
, 0, sizeof(*tsap
));
361 if (t2isakmpsa(trns
, tsap
) < 0)
363 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
365 authmethod
= switch_authmethod(s
->authmethod
);
366 tsap_authmethod
= switch_authmethod(tsap
->authmethod
);
368 authmethod
= s
->authmethod
;
369 tsap_authmethod
= tsap
->authmethod
;
371 plog(LLV_DEBUG
, LOCATION
, NULL
, "Compared: DB:Peer\n");
372 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifetime = %ld:%ld)\n",
373 (long)s
->lifetime
, (long)tsap
->lifetime
);
374 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifebyte = %zu:%zu)\n",
375 s
->lifebyte
, tsap
->lifebyte
);
376 plog(LLV_DEBUG
, LOCATION
, NULL
, "enctype = %s:%s\n",
377 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
379 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
381 plog(LLV_DEBUG
, LOCATION
, NULL
, "(encklen = %d:%d)\n",
382 s
->encklen
, tsap
->encklen
);
383 plog(LLV_DEBUG
, LOCATION
, NULL
, "hashtype = %s:%s\n",
384 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
386 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
388 plog(LLV_DEBUG
, LOCATION
, NULL
, "authmethod = %s:%s\n",
389 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
391 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
393 plog(LLV_DEBUG
, LOCATION
, NULL
, "dh_group = %s:%s\n",
394 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
396 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
399 /* XXX to be considered ? */
400 if (tsap
->lifebyte
> s
->lifebyte
) ;
403 * if responder side and peer's key length in proposal
404 * is bigger than mine, it might be accepted.
406 if(tsap
->enctype
== s
->enctype
&&
407 (tsap
->authmethod
== authmethod
|| tsap_authmethod
== authmethod
) &&
408 tsap
->hashtype
== s
->hashtype
&&
409 tsap
->dh_group
== s
->dh_group
&&
410 tsap
->encklen
== s
->encklen
) {
411 switch(check_level
) {
412 case PROP_CHECK_OBEY
:
416 case PROP_CHECK_STRICT
:
417 if ((tsap
->lifetime
> s
->lifetime
) ||
418 (tsap
->lifebyte
> s
->lifebyte
))
423 case PROP_CHECK_CLAIM
:
424 if (tsap
->lifetime
< s
->lifetime
)
425 s
->lifetime
= tsap
->lifetime
;
426 if (tsap
->lifebyte
< s
->lifebyte
)
427 s
->lifebyte
= tsap
->lifebyte
;
431 case PROP_CHECK_EXACT
:
432 if ((tsap
->lifetime
!= s
->lifetime
) ||
433 (tsap
->lifebyte
!= s
->lifebyte
))
439 plog(LLV_ERROR
, LOCATION
, NULL
,
440 "Unexpected proposal_check value\n");
448 if (tsap
->dhgrp
!= NULL
){
449 oakley_dhgrp_free(tsap
->dhgrp
);
453 if ((s
= dupisakmpsa(s
)) != NULL
) {
454 switch(check_level
) {
455 case PROP_CHECK_OBEY
:
456 s
->lifetime
= tsap
->lifetime
;
457 s
->lifebyte
= tsap
->lifebyte
;
460 case PROP_CHECK_STRICT
:
461 s
->lifetime
= tsap
->lifetime
;
462 s
->lifebyte
= tsap
->lifebyte
;
465 case PROP_CHECK_CLAIM
:
466 if (tsap
->lifetime
< s
->lifetime
)
467 s
->lifetime
= tsap
->lifetime
;
468 if (tsap
->lifebyte
< s
->lifebyte
)
469 s
->lifebyte
= tsap
->lifebyte
;
475 // hack to get around cisco rekeys
476 if (tsap
->authmethod
!= authmethod
&& tsap_authmethod
== authmethod
) {
477 s
->authmethod
= tsap
->authmethod
;
484 * print all of items in peer's proposal which are mismatched to my proposal.
485 * p : one of peer's proposal.
486 * proposal: my proposals.
489 print_ph1mismatched(p
, proposal
)
491 struct isakmpsa
*proposal
;
493 struct isakmpsa sa
, *s
;
495 memset(&sa
, 0, sizeof(sa
));
496 if (t2isakmpsa(p
->trns
, &sa
) < 0)
498 for (s
= proposal
; s
; s
= s
->next
) {
499 if (sa
.enctype
!= s
->enctype
) {
500 plog(LLV_ERROR
, LOCATION
, NULL
,
502 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
504 s
->prop_no
, s
->trns_no
,
505 p
->prop
->p_no
, p
->trns
->t_no
,
506 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
508 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
511 if (sa
.authmethod
!= s
->authmethod
) {
512 plog(LLV_ERROR
, LOCATION
, NULL
,
513 "rejected authmethod: "
514 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
516 s
->prop_no
, s
->trns_no
,
517 p
->prop
->p_no
, p
->trns
->t_no
,
518 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
520 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
523 if (sa
.hashtype
!= s
->hashtype
) {
524 plog(LLV_ERROR
, LOCATION
, NULL
,
525 "rejected hashtype: "
526 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
528 s
->prop_no
, s
->trns_no
,
529 p
->prop
->p_no
, p
->trns
->t_no
,
530 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
532 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
535 if (sa
.dh_group
!= s
->dh_group
) {
536 plog(LLV_ERROR
, LOCATION
, NULL
,
537 "rejected dh_group: "
538 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
540 s
->prop_no
, s
->trns_no
,
541 p
->prop
->p_no
, p
->trns
->t_no
,
542 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
544 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
549 if (sa
.dhgrp
!= NULL
){
550 oakley_dhgrp_free(sa
.dhgrp
);
556 * get ISAKMP data attributes
560 struct isakmp_pl_t
*trns
;
563 struct isakmp_data
*d
, *prev
;
572 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
573 prev
= (struct isakmp_data
*)NULL
;
574 d
= (struct isakmp_data
*)(trns
+ 1);
577 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
578 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
580 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
586 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
587 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
589 plog(LLV_DEBUG
, LOCATION
, NULL
,
590 "type=%s, flag=0x%04x, lorv=%s\n",
591 s_oakley_attr(type
), flag
,
592 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
594 /* get variable-sized item */
596 case OAKLEY_ATTR_GRP_PI
:
597 case OAKLEY_ATTR_GRP_GEN_ONE
:
598 case OAKLEY_ATTR_GRP_GEN_TWO
:
599 case OAKLEY_ATTR_GRP_CURVE_A
:
600 case OAKLEY_ATTR_GRP_CURVE_B
:
601 case OAKLEY_ATTR_SA_LD
:
602 case OAKLEY_ATTR_GRP_ORDER
:
605 p
= (u_char
*)&d
->lorv
;
607 len
= ntohs(d
->lorv
);
609 plog(LLV_ERROR
, LOCATION
, NULL
,
610 "invalid ISAKMP-SA attr, attr-len %d, overall-len %d\n",
614 p
= (u_char
*)(d
+ 1);
619 memcpy(val
->v
, p
, len
);
627 case OAKLEY_ATTR_ENC_ALG
:
628 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
631 case OAKLEY_ATTR_HASH_ALG
:
632 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
635 case OAKLEY_ATTR_AUTH_METHOD
:
636 sa
->authmethod
= ntohs(d
->lorv
);
639 case OAKLEY_ATTR_GRP_DESC
:
640 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
643 case OAKLEY_ATTR_GRP_TYPE
:
645 int type
= (int)ntohs(d
->lorv
);
646 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
647 sa
->dhgrp
->type
= type
;
652 case OAKLEY_ATTR_GRP_PI
:
653 sa
->dhgrp
->prime
= val
;
656 case OAKLEY_ATTR_GRP_GEN_ONE
:
659 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
661 int len
= ntohs(d
->lorv
);
665 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
666 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
670 case OAKLEY_ATTR_GRP_GEN_TWO
:
673 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
675 int len
= ntohs(d
->lorv
);
679 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
680 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
684 case OAKLEY_ATTR_GRP_CURVE_A
:
685 sa
->dhgrp
->curve_a
= val
;
688 case OAKLEY_ATTR_GRP_CURVE_B
:
689 sa
->dhgrp
->curve_b
= val
;
692 case OAKLEY_ATTR_SA_LD_TYPE
:
694 int type
= (int)ntohs(d
->lorv
);
696 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
697 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
701 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
706 case OAKLEY_ATTR_SA_LD
:
708 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
709 OAKLEY_ATTR_SA_LD_TYPE
) {
710 plog(LLV_ERROR
, LOCATION
, NULL
,
711 "life duration must follow ltype\n");
716 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
717 sa
->lifetime
= ipsecdoi_set_ld(val
);
719 if (sa
->lifetime
== 0) {
720 plog(LLV_ERROR
, LOCATION
, NULL
,
721 "invalid life duration.\n");
725 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
726 sa
->lifebyte
= ipsecdoi_set_ld(val
);
728 if (sa
->lifebyte
== 0) {
729 plog(LLV_ERROR
, LOCATION
, NULL
,
730 "invalid life duration.\n");
736 plog(LLV_ERROR
, LOCATION
, NULL
,
737 "invalid life type: %d\n", life_t
);
742 case OAKLEY_ATTR_KEY_LEN
:
744 int len
= ntohs(d
->lorv
);
746 plog(LLV_ERROR
, LOCATION
, NULL
,
747 "keylen %d: not multiple of 8\n",
751 sa
->encklen
= (u_int16_t
)len
;
755 case OAKLEY_ATTR_PRF
:
756 case OAKLEY_ATTR_FIELD_SIZE
:
760 case OAKLEY_ATTR_GRP_ORDER
:
761 sa
->dhgrp
->order
= val
;
764 case OAKLEY_ATTR_GSS_ID
:
767 iconv_t cd
= (iconv_t
) -1;
768 size_t srcleft
, dstleft
, rv
;
769 __iconv_const
char *src
;
771 int len
= ntohs(d
->lorv
);
774 * Older verions of racoon just placed the
775 * ISO-Latin-1 string on the wire directly.
776 * Check to see if we are configured to be
777 * compatible with this behavior.
779 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
780 if ((sa
->gssid
= vmalloc(len
)) == NULL
) {
781 plog(LLV_ERROR
, LOCATION
, NULL
,
782 "failed to allocate memory\n");
785 memcpy(sa
->gssid
->v
, d
+ 1, len
);
786 plog(LLV_DEBUG
, LOCATION
, NULL
,
787 "received old-style gss "
788 "id '%.*s' (len %zu)\n",
789 (int)sa
->gssid
->l
, sa
->gssid
->v
,
796 * For Windows 2000 compatibility, we expect
797 * the GSS ID attribute on the wire to be
798 * encoded in UTF-16LE. Internally, we work
799 * in ISO-Latin-1. Therefore, we should need
800 * 1/2 the specified length, which should always
801 * be a multiple of 2 octets.
803 cd
= iconv_open("latin1", "utf-16le");
804 if (cd
== (iconv_t
) -1) {
805 plog(LLV_ERROR
, LOCATION
, NULL
,
806 "unable to initialize utf-16le -> latin1 "
807 "conversion descriptor: %s\n",
812 if ((sa
->gssid
= vmalloc(len
/ 2)) == NULL
) {
813 plog(LLV_ERROR
, LOCATION
, NULL
,
814 "failed to allocate memory\n");
818 src
= (__iconv_const
char *)(d
+ 1);
824 rv
= iconv(cd
, (__iconv_const
char **)&src
, &srcleft
,
828 plog(LLV_ERROR
, LOCATION
, NULL
,
829 "unable to convert GSS ID from "
830 "utf-16le -> latin1: %s\n",
833 plog(LLV_ERROR
, LOCATION
, NULL
,
834 "%zd character%s in GSS ID cannot "
835 "be represented in latin1\n",
836 rv
, rv
== 1 ? "" : "s");
841 /* XXX dstleft should always be 0; assert it? */
842 sa
->gssid
->l
= (len
/ 2) - dstleft
;
844 plog(LLV_DEBUG
, LOCATION
, NULL
,
845 "received gss id '%.*s' (len %zu)\n",
846 (int)sa
->gssid
->l
, sa
->gssid
->v
, sa
->gssid
->l
);
850 if (cd
!= (iconv_t
)-1)
851 (void)iconv_close(cd
);
853 if ((error
!= 0) && (sa
->gssid
!= NULL
)) {
859 #endif /* HAVE_GSSAPI */
868 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
870 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
871 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
875 /* key length must not be specified on some algorithms */
877 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
878 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
879 plog(LLV_ERROR
, LOCATION
, NULL
,
880 "keylen must not be specified "
881 "for encryption algorithm %d\n",
894 * check phase 2 SA payload and select single proposal.
895 * make new SA payload to be replyed not including general header.
896 * This function is called by responder only.
902 ipsecdoi_selectph2proposal(iph2
)
903 struct ph2handle
*iph2
;
905 struct prop_pair
**pair
;
906 struct prop_pair
*ret
;
908 /* get proposal pair */
909 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
913 /* check and select a proposal. */
914 ret
= get_ph2approval(iph2
, pair
);
919 /* make a SA to be replayed. */
920 /* SPI must be updated later. */
921 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
923 if (iph2
->sa_ret
== NULL
)
930 * check phase 2 SA payload returned from responder.
931 * This function is called by initiator only.
937 ipsecdoi_checkph2proposal(iph2
)
938 struct ph2handle
*iph2
;
940 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
944 vchar_t
*sa_ret
= NULL
;
946 /* get proposal pair of SA sent. */
947 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
949 plog(LLV_ERROR
, LOCATION
, NULL
,
950 "failed to get prop pair.\n");
954 /* XXX should check the number of transform */
956 /* get proposal pair of SA replayed */
957 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
959 plog(LLV_ERROR
, LOCATION
, NULL
,
960 "failed to get prop pair.\n");
964 /* check proposal is only one ? */
967 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
974 plog(LLV_ERROR
, LOCATION
, NULL
,
975 "no proposal received.\n");
979 plog(LLV_ERROR
, LOCATION
, NULL
,
980 "some proposals received.\n");
984 if (spair
[n
] == NULL
) {
985 plog(LLV_WARNING
, LOCATION
, NULL
,
986 "invalid proposal number:%d received.\n", i
);
990 if (rpair
[n
]->tnext
!= NULL
) {
991 plog(LLV_ERROR
, LOCATION
, NULL
,
992 "multi transforms replyed.\n");
996 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
997 plog(LLV_ERROR
, LOCATION
, NULL
,
998 "proposal mismathed.\n");
1003 * check and select a proposal.
1004 * ensure that there is no modification of the proposal by
1007 p
= get_ph2approval(iph2
, rpair
);
1011 /* make a SA to be replayed. */
1012 sa_ret
= iph2
->sa_ret
;
1013 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
1015 if (iph2
->sa_ret
== NULL
)
1022 free_proppair(rpair
);
1024 free_proppair(spair
);
1032 * compare two prop_pair which is assumed to have same proposal number.
1033 * the case of bundle or single SA, NOT multi transforms.
1034 * a: a proposal that is multi protocols and single transform, usually replyed.
1035 * b: a proposal that is multi protocols and multi transform, usually sent.
1036 * NOTE: this function is for initiator.
1040 * XXX cannot understand the comment!
1043 cmp_aproppair_i(a
, b
)
1044 struct prop_pair
*a
, *b
;
1046 struct prop_pair
*p
, *q
, *r
;
1049 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
1050 for (r
= q
; r
; r
= r
->tnext
) {
1052 if (p
->trns
->t_no
== r
->trns
->t_no
)
1056 /* no suitable transform found */
1057 plog(LLV_ERROR
, LOCATION
, NULL
,
1058 "no suitable transform found.\n");
1063 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
1064 plog(LLV_WARNING
, LOCATION
, NULL
,
1065 "proposal #%d mismatched, "
1067 r
->prop
->p_no
, p
->prop
->p_no
);
1071 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
1072 plog(LLV_ERROR
, LOCATION
, NULL
,
1073 "proto_id mismathed: my:%d peer:%d\n",
1074 r
->prop
->proto_id
, p
->prop
->proto_id
);
1078 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
1079 plog(LLV_ERROR
, LOCATION
, NULL
,
1080 "invalid spi size: %d.\n",
1085 /* check #of transforms */
1086 if (p
->prop
->num_t
!= 1) {
1087 plog(LLV_WARNING
, LOCATION
, NULL
,
1088 "#of transform is %d, "
1089 "but expected 1.\n", p
->prop
->num_t
);
1093 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
1094 plog(LLV_WARNING
, LOCATION
, NULL
,
1095 "transform number has been modified.\n");
1098 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
1099 plog(LLV_WARNING
, LOCATION
, NULL
,
1100 "reserved field should be zero.\n");
1104 /* compare attribute */
1105 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
1106 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
1107 plog(LLV_WARNING
, LOCATION
, NULL
,
1108 "attribute has been modified.\n");
1112 if ((p
&& !q
) || (!p
&& q
)) {
1113 /* # of protocols mismatched */
1114 plog(LLV_ERROR
, LOCATION
, NULL
,
1115 "#of protocols mismatched.\n");
1123 * acceptable check for policy configuration.
1124 * return a new SA payload to be reply to peer.
1126 static struct prop_pair
*
1127 get_ph2approval(iph2
, pair
)
1128 struct ph2handle
*iph2
;
1129 struct prop_pair
**pair
;
1131 struct prop_pair
*ret
;
1134 iph2
->approval
= NULL
;
1136 plog(LLV_DEBUG
, LOCATION
, NULL
,
1137 "begin compare proposals.\n");
1139 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1140 if (pair
[i
] == NULL
)
1142 plog(LLV_DEBUG
, LOCATION
, NULL
,
1143 "pair[%d]: %p\n", i
, pair
[i
]);
1144 print_proppair(LLV_DEBUG
, pair
[i
]);;
1146 /* compare proposal and select one */
1147 ret
= get_ph2approvalx(iph2
, pair
[i
]);
1154 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable policy found.\n");
1160 * compare my proposal and peers just one proposal.
1163 static struct prop_pair
*
1164 get_ph2approvalx(iph2
, pp
)
1165 struct ph2handle
*iph2
;
1166 struct prop_pair
*pp
;
1168 struct prop_pair
*ret
= NULL
;
1169 struct saprop
*pr0
, *pr
= NULL
;
1170 struct saprop
*q1
, *q2
;
1172 pr0
= aproppair2saprop(pp
);
1176 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1177 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1178 plog(LLV_DEBUG
, LOCATION
, NULL
,
1179 "peer's single bundle:\n");
1180 printsaprop0(LLV_DEBUG
, q1
);
1181 plog(LLV_DEBUG
, LOCATION
, NULL
,
1182 "my single bundle:\n");
1183 printsaprop0(LLV_DEBUG
, q2
);
1185 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1189 plog(LLV_ERROR
, LOCATION
, NULL
,
1193 /* no proposal matching */
1200 plog(LLV_DEBUG
, LOCATION
, NULL
, "matched\n");
1201 iph2
->approval
= pr
;
1205 struct prop_pair
*p
, *x
;
1206 struct prop_pair
*n
= NULL
;
1210 for (p
= pp
; p
; p
= p
->next
) {
1212 * find a proposal with matching proto_id.
1213 * we have analyzed validity already, in cmpsaprop_alloc().
1215 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1216 if (sp
->proto_id
== p
->prop
->proto_id
)
1224 for (x
= p
; x
; x
= x
->tnext
)
1225 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1230 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1232 plog(LLV_ERROR
, LOCATION
, NULL
,
1233 "failed to get buffer.\n");
1240 /* need to preserve the order */
1241 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1243 if (x
&& x
->prop
== n
->prop
) {
1244 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1255 /* #of transforms should be updated ? */
1264 struct prop_pair
**pair
;
1268 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1269 free_proppair0(pair
[i
]);
1276 free_proppair0(pair
)
1277 struct prop_pair
*pair
;
1279 struct prop_pair
*p
, *q
, *r
, *s
;
1295 * get proposal pairs from SA payload.
1296 * tiny check for proposal payload.
1299 get_proppair(sa
, mode
)
1303 struct prop_pair
**pair
= NULL
;
1304 int num_p
= 0; /* number of proposal for use */
1308 struct ipsecdoi_sa_b
*sab
= ALIGNED_CAST(struct ipsecdoi_sa_b
*)sa
->v
;
1310 plog(LLV_DEBUG
, LOCATION
, NULL
, "total SA len=%zu\n", sa
->l
);
1311 plogdump(LLV_DEBUG
, sa
->v
, sa
->l
);
1313 /* check SA payload size */
1314 if (sa
->l
< sizeof(*sab
)) {
1315 plog(LLV_ERROR
, LOCATION
, NULL
,
1316 "Invalid SA length = %zu.\n", sa
->l
);
1321 if (check_doi(ntohl(sab
->doi
)) < 0)
1324 /* check SITUATION */
1325 if (check_situation(ntohl(sab
->sit
)) < 0)
1328 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1330 plog(LLV_ERROR
, LOCATION
, NULL
,
1331 "failed to get buffer.\n");
1334 memset(pair
, 0, sizeof(pair
));
1336 bp
= (caddr_t
)(sab
+ 1);
1337 tlen
= sa
->l
- sizeof(*sab
);
1340 struct isakmp_pl_p
*prop
;
1342 vchar_t
*pbuf
= NULL
;
1343 struct isakmp_parse_t
*pa
;
1345 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1349 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1350 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1352 /* check the value of next payload */
1353 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1354 plog(LLV_ERROR
, LOCATION
, NULL
,
1355 "Invalid payload type=%u\n", pa
->type
);
1360 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1363 plog(LLV_DEBUG
, LOCATION
, NULL
,
1364 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1367 plog(LLV_ERROR
, LOCATION
, NULL
,
1368 "invalid proposal with length %d\n", proplen
);
1373 /* check Protocol ID */
1374 if (!check_protocol
[mode
]) {
1375 plog(LLV_ERROR
, LOCATION
, NULL
,
1376 "unsupported mode %d\n", mode
);
1380 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1383 /* check SPI length when IKE. */
1384 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1388 if (get_transform(prop
, pair
, &num_p
) < 0) {
1399 struct prop_pair
*p
, *q
;
1401 /* check for proposals with no transforms */
1402 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1406 plog(LLV_DEBUG
, LOCATION
, NULL
, "pair %d:\n", i
);
1407 print_proppair(LLV_DEBUG
, pair
[i
]);
1409 notrans
= nprop
= 0;
1410 for (p
= pair
[i
]; p
; p
= p
->next
) {
1411 if (p
->trns
== NULL
) {
1415 for (q
= p
; q
; q
= q
->tnext
)
1421 * XXX at this moment, we cannot accept proposal group
1422 * with multiple proposals. this should be fixed.
1424 if (pair
[i
]->next
) {
1425 plog(LLV_WARNING
, LOCATION
, NULL
,
1426 "proposal #%u ignored "
1427 "(multiple proposal not supported)\n",
1428 pair
[i
]->prop
->p_no
);
1434 for (p
= pair
[i
]; p
; p
= q
) {
1441 plog(LLV_DEBUG
, LOCATION
, NULL
,
1442 "proposal #%u: %d transform\n",
1443 pair
[i
]->prop
->p_no
, nprop
);
1448 /* bark if no proposal is found. */
1450 plog(LLV_ERROR
, LOCATION
, NULL
,
1451 "no Proposal found.\n");
1463 * check transform payload.
1465 * positive: return the pointer to the payload of valid transform.
1466 * 0 : No valid transform found.
1469 get_transform(prop
, pair
, num_p
)
1470 struct isakmp_pl_p
*prop
;
1471 struct prop_pair
**pair
;
1474 int tlen
; /* total length of all transform in a proposal */
1476 struct isakmp_pl_t
*trns
;
1478 vchar_t
*pbuf
= NULL
;
1479 struct isakmp_parse_t
*pa
;
1480 struct prop_pair
*p
= NULL
, *q
;
1483 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1484 tlen
= ntohs(prop
->h
.len
)
1485 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1486 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1490 /* check and get transform for use */
1492 for (pa
= ALIGNED_CAST(struct isakmp_parse_t
*)pbuf
->v
;
1493 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1498 /* check the value of next payload */
1499 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1500 plog(LLV_ERROR
, LOCATION
, NULL
,
1501 "Invalid payload type=%u\n", pa
->type
);
1505 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1508 plog(LLV_DEBUG
, LOCATION
, NULL
,
1509 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1511 /* check transform ID */
1512 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1513 plog(LLV_WARNING
, LOCATION
, NULL
,
1514 "unsupported proto_id %u\n",
1518 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1519 plog(LLV_WARNING
, LOCATION
, NULL
,
1520 "unsupported proto_id %u\n",
1525 if (!check_transform
[prop
->proto_id
]
1526 || !check_attributes
[prop
->proto_id
]) {
1527 plog(LLV_WARNING
, LOCATION
, NULL
,
1528 "unsupported proto_id %u\n",
1532 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1535 /* check data attributes */
1536 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1539 p
= racoon_calloc(1, sizeof(*p
));
1541 plog(LLV_ERROR
, LOCATION
, NULL
,
1542 "failed to get buffer.\n");
1549 /* need to preserve the order */
1550 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1552 if (q
&& q
->prop
== p
->prop
) {
1553 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1560 pair
[prop
->p_no
] = p
;
1572 * make a new SA payload from prop_pair.
1573 * NOTE: this function make spi value clear.
1576 get_sabyproppair(pair
, iph1
)
1577 struct prop_pair
*pair
;
1578 struct ph1handle
*iph1
;
1582 u_int8_t
*np_p
= NULL
;
1583 struct prop_pair
*p
;
1584 int prophlen
, trnslen
;
1587 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1588 for (p
= pair
; p
; p
= p
->next
) {
1589 newtlen
+= sizeof(struct isakmp_pl_p
);
1590 newtlen
+= p
->prop
->spi_size
;
1591 newtlen
+= ntohs(p
->trns
->h
.len
);
1594 newsa
= vmalloc(newtlen
);
1595 if (newsa
== NULL
) {
1596 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1601 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1603 /* update some of values in SA header */
1604 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1605 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1606 bp
+= sizeof(struct ipsecdoi_sa_b
);
1608 /* create proposal payloads */
1609 for (p
= pair
; p
; p
= p
->next
) {
1610 prophlen
= sizeof(struct isakmp_pl_p
)
1611 + p
->prop
->spi_size
;
1612 trnslen
= ntohs(p
->trns
->h
.len
);
1615 *np_p
= ISAKMP_NPTYPE_P
;
1617 /* create proposal */
1619 memcpy(bp
, p
->prop
, prophlen
);
1620 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1621 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1622 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1623 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1624 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1627 /* create transform */
1628 memcpy(bp
, p
->trns
, trnslen
);
1629 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1630 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1638 * update responder's spi
1641 ipsecdoi_updatespi(iph2
)
1642 struct ph2handle
*iph2
;
1644 struct prop_pair
**pair
, *p
;
1651 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1654 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1658 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1659 /* multiple transform must be filtered by selectph2proposal.*/
1663 pp
= iph2
->approval
;
1665 /* create proposal payloads */
1666 for (p
= pair
[i
]; p
; p
= p
->next
) {
1668 * find a proposal/transform with matching proto_id/t_id.
1669 * we have analyzed validity already, in cmpsaprop_alloc().
1671 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1672 if (p
->prop
->proto_id
== pr
->proto_id
&&
1673 p
->trns
->t_id
== pr
->head
->trns_id
) {
1681 * XXX SPI bits are left-filled, for use with IPComp.
1682 * we should be switching to variable-length spi field...
1684 spi
= (u_int8_t
*)&pr
->spi
;
1685 spi
+= sizeof(pr
->spi
);
1687 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1692 free_proppair(pair
);
1697 * make a new SA payload from prop_pair.
1700 get_sabysaprop(pp0
, sa0
)
1704 struct prop_pair
**pair
= NULL
;
1705 vchar_t
*newsa
= NULL
;
1707 u_int8_t
*np_p
= NULL
;
1708 struct prop_pair
*p
= NULL
;
1712 int prophlen
, trnslen
;
1716 /* get proposal pair */
1717 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1721 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1722 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1724 if (pair
[pp
->prop_no
] == NULL
)
1727 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1728 newtlen
+= (sizeof(struct isakmp_pl_p
)
1731 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1732 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1733 if (tr
->trns_no
== p
->trns
->t_no
)
1739 newtlen
+= ntohs(p
->trns
->h
.len
);
1744 newsa
= vmalloc(newtlen
);
1745 if (newsa
== NULL
) {
1746 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1751 /* some of values of SA must be updated in the out of this function */
1752 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1753 bp
+= sizeof(struct ipsecdoi_sa_b
);
1755 /* create proposal payloads */
1756 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1758 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1759 prophlen
= sizeof(struct isakmp_pl_p
)
1760 + p
->prop
->spi_size
;
1762 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1763 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1764 if (tr
->trns_no
== p
->trns
->t_no
)
1770 trnslen
= ntohs(p
->trns
->h
.len
);
1773 *np_p
= ISAKMP_NPTYPE_P
;
1775 /* create proposal */
1777 memcpy(bp
, p
->prop
, prophlen
);
1778 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1779 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1780 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1781 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1784 /* create transform */
1785 memcpy(bp
, p
->trns
, trnslen
);
1786 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1787 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1799 if (newsa
!= NULL
) {
1809 * If some error happens then return 0. Although 0 means that lifetime is zero,
1810 * such a value should not be accepted.
1811 * Also 0 of lifebyte should not be included in a packet although 0 means not
1815 ipsecdoi_set_ld(buf
)
1825 ld
= ntohs(*ALIGNED_CAST(u_int16_t
*)buf
->v
);
1828 ld
= ntohl(*ALIGNED_CAST(u_int32_t
*)buf
->v
);
1831 plog(LLV_ERROR
, LOCATION
, NULL
,
1832 "length %zu of life duration "
1833 "isn't supported.\n", buf
->l
);
1852 plog(LLV_ERROR
, LOCATION
, NULL
,
1853 "invalid value of DOI 0x%08x.\n", doi
);
1863 check_situation(sit
)
1867 case IPSECDOI_SIT_IDENTITY_ONLY
:
1870 case IPSECDOI_SIT_SECRECY
:
1871 case IPSECDOI_SIT_INTEGRITY
:
1872 plog(LLV_ERROR
, LOCATION
, NULL
,
1873 "situation 0x%08x unsupported yet.\n", sit
);
1877 plog(LLV_ERROR
, LOCATION
, NULL
,
1878 "invalid situation 0x%08x.\n", sit
);
1885 * check protocol id in main mode
1888 check_prot_main(proto_id
)
1892 case IPSECDOI_PROTO_ISAKMP
:
1896 plog(LLV_ERROR
, LOCATION
, NULL
,
1897 "Illegal protocol id=%u.\n", proto_id
);
1904 * check protocol id in quick mode
1907 check_prot_quick(proto_id
)
1911 case IPSECDOI_PROTO_IPSEC_AH
:
1912 case IPSECDOI_PROTO_IPSEC_ESP
:
1915 case IPSECDOI_PROTO_IPCOMP
:
1919 plog(LLV_ERROR
, LOCATION
, NULL
,
1920 "invalid protocol id %d.\n", proto_id
);
1927 check_spi_size(proto_id
, size
)
1931 case IPSECDOI_PROTO_ISAKMP
:
1934 plog(LLV_WARNING
, LOCATION
, NULL
,
1935 "SPI size isn't zero, but IKE proposal.\n");
1939 case IPSECDOI_PROTO_IPSEC_AH
:
1940 case IPSECDOI_PROTO_IPSEC_ESP
:
1942 plog(LLV_ERROR
, LOCATION
, NULL
,
1943 "invalid SPI size=%d for IPSEC proposal.\n",
1949 case IPSECDOI_PROTO_IPCOMP
:
1950 if (size
!= 2 && size
!= 4) {
1951 plog(LLV_ERROR
, LOCATION
, NULL
,
1952 "invalid SPI size=%d for IPCOMP proposal.\n",
1966 * check transform ID in ISAKMP.
1969 check_trns_isakmp(t_id
)
1973 case IPSECDOI_KEY_IKE
:
1976 plog(LLV_ERROR
, LOCATION
, NULL
,
1977 "invalid transform-id=%u in proto_id=%u.\n",
1978 t_id
, IPSECDOI_KEY_IKE
);
1985 * check transform ID in AH.
1992 case IPSECDOI_AH_MD5
:
1993 case IPSECDOI_AH_SHA
:
1994 case IPSECDOI_AH_SHA256
:
1995 case IPSECDOI_AH_SHA384
:
1996 case IPSECDOI_AH_SHA512
:
1998 case IPSECDOI_AH_DES
:
1999 plog(LLV_ERROR
, LOCATION
, NULL
,
2000 "not support transform-id=%u in AH.\n", t_id
);
2003 plog(LLV_ERROR
, LOCATION
, NULL
,
2004 "invalid transform-id=%u in AH.\n", t_id
);
2011 * check transform ID in ESP.
2014 check_trns_esp(t_id
)
2018 case IPSECDOI_ESP_DES
:
2019 case IPSECDOI_ESP_3DES
:
2020 case IPSECDOI_ESP_NULL
:
2021 case IPSECDOI_ESP_RC5
:
2022 case IPSECDOI_ESP_CAST
:
2023 case IPSECDOI_ESP_BLOWFISH
:
2024 case IPSECDOI_ESP_AES
:
2025 case IPSECDOI_ESP_TWOFISH
:
2027 case IPSECDOI_ESP_DES_IV32
:
2028 case IPSECDOI_ESP_DES_IV64
:
2029 case IPSECDOI_ESP_IDEA
:
2030 case IPSECDOI_ESP_3IDEA
:
2031 case IPSECDOI_ESP_RC4
:
2032 plog(LLV_ERROR
, LOCATION
, NULL
,
2033 "not support transform-id=%u in ESP.\n", t_id
);
2036 plog(LLV_ERROR
, LOCATION
, NULL
,
2037 "invalid transform-id=%u in ESP.\n", t_id
);
2044 * check transform ID in IPCOMP.
2047 check_trns_ipcomp(t_id
)
2051 case IPSECDOI_IPCOMP_OUI
:
2052 case IPSECDOI_IPCOMP_DEFLATE
:
2053 case IPSECDOI_IPCOMP_LZS
:
2056 plog(LLV_ERROR
, LOCATION
, NULL
,
2057 "invalid transform-id=%u in IPCOMP.\n", t_id
);
2064 * check data attributes in IKE.
2067 check_attr_isakmp(trns
)
2068 struct isakmp_pl_t
*trns
;
2070 struct isakmp_data
*d
;
2075 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2076 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2079 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2080 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2081 lorv
= ntohs(d
->lorv
);
2083 plog(LLV_DEBUG
, LOCATION
, NULL
,
2084 "type=%s, flag=0x%04x, lorv=%s\n",
2085 s_oakley_attr(type
), flag
,
2086 s_oakley_attr_v(type
, lorv
));
2089 * some of the attributes must be encoded in TV.
2090 * see RFC2409 Appendix A "Attribute Classes".
2093 case OAKLEY_ATTR_ENC_ALG
:
2094 case OAKLEY_ATTR_HASH_ALG
:
2095 case OAKLEY_ATTR_AUTH_METHOD
:
2096 case OAKLEY_ATTR_GRP_DESC
:
2097 case OAKLEY_ATTR_GRP_TYPE
:
2098 case OAKLEY_ATTR_SA_LD_TYPE
:
2099 case OAKLEY_ATTR_PRF
:
2100 case OAKLEY_ATTR_KEY_LEN
:
2101 case OAKLEY_ATTR_FIELD_SIZE
:
2102 if (!flag
) { /* TLV*/
2103 plog(LLV_ERROR
, LOCATION
, NULL
,
2104 "oakley attribute %d must be TV.\n",
2111 /* sanity check for TLV. length must be specified. */
2112 if (!flag
&& lorv
== 0) { /*TLV*/
2113 plog(LLV_ERROR
, LOCATION
, NULL
,
2114 "invalid length %d for TLV attribute %d.\n",
2120 case OAKLEY_ATTR_ENC_ALG
:
2121 if (!alg_oakley_encdef_ok(lorv
)) {
2122 plog(LLV_ERROR
, LOCATION
, NULL
,
2123 "invalied encryption algorithm=%d.\n",
2129 case OAKLEY_ATTR_HASH_ALG
:
2130 if (!alg_oakley_hashdef_ok(lorv
)) {
2131 plog(LLV_ERROR
, LOCATION
, NULL
,
2132 "invalied hash algorithm=%d.\n",
2138 case OAKLEY_ATTR_AUTH_METHOD
:
2140 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2141 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2142 #ifdef ENABLE_HYBRID
2143 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2144 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
:
2145 #if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2146 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
:
2148 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
2150 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
2152 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2153 #ifdef ENABLE_HYBRID
2154 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2155 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
2156 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2157 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2158 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
:
2159 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
2160 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
:
2161 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
2162 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
:
2163 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
2165 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2166 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2167 plog(LLV_ERROR
, LOCATION
, NULL
,
2168 "auth method %s isn't supported.\n",
2169 s_oakley_attr_method(lorv
));
2172 plog(LLV_ERROR
, LOCATION
, NULL
,
2173 "invalid auth method %d.\n",
2179 case OAKLEY_ATTR_GRP_DESC
:
2180 if (!alg_oakley_dhdef_ok(lorv
)) {
2181 plog(LLV_ERROR
, LOCATION
, NULL
,
2182 "invalid DH group %d.\n",
2188 case OAKLEY_ATTR_GRP_TYPE
:
2190 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2193 plog(LLV_ERROR
, LOCATION
, NULL
,
2194 "unsupported DH group type %d.\n",
2200 case OAKLEY_ATTR_GRP_PI
:
2201 case OAKLEY_ATTR_GRP_GEN_ONE
:
2202 /* sanity checks? */
2205 case OAKLEY_ATTR_GRP_GEN_TWO
:
2206 case OAKLEY_ATTR_GRP_CURVE_A
:
2207 case OAKLEY_ATTR_GRP_CURVE_B
:
2208 plog(LLV_ERROR
, LOCATION
, NULL
,
2209 "attr type=%u isn't supported.\n", type
);
2212 case OAKLEY_ATTR_SA_LD_TYPE
:
2214 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2215 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2218 plog(LLV_ERROR
, LOCATION
, NULL
,
2219 "invalid life type %d.\n", lorv
);
2224 case OAKLEY_ATTR_SA_LD
:
2225 /* should check the value */
2228 case OAKLEY_ATTR_PRF
:
2229 case OAKLEY_ATTR_KEY_LEN
:
2232 case OAKLEY_ATTR_FIELD_SIZE
:
2233 plog(LLV_ERROR
, LOCATION
, NULL
,
2234 "attr type=%u isn't supported.\n", type
);
2237 case OAKLEY_ATTR_GRP_ORDER
:
2240 case OAKLEY_ATTR_GSS_ID
:
2244 plog(LLV_ERROR
, LOCATION
, NULL
,
2245 "invalid attribute type %d.\n", type
);
2251 d
= (struct isakmp_data
*)((char *)d
2254 tlen
-= (sizeof(*d
) + lorv
);
2255 d
= (struct isakmp_data
*)((char *)d
2256 + sizeof(*d
) + lorv
);
2264 * check data attributes in IPSEC AH/ESP.
2268 struct isakmp_pl_t
*trns
;
2270 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2274 check_attr_esp(trns
)
2275 struct isakmp_pl_t
*trns
;
2277 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2281 check_attr_ipsec(proto_id
, trns
)
2283 struct isakmp_pl_t
*trns
;
2285 struct isakmp_data
*d
;
2289 int attrseen
[16]; /* XXX magic number */
2291 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2292 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2293 memset(attrseen
, 0, sizeof(attrseen
));
2296 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2297 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2298 lorv
= ntohs(d
->lorv
);
2300 plog(LLV_DEBUG
, LOCATION
, NULL
,
2301 "type=%s, flag=0x%04x, lorv=%s\n",
2302 s_ipsecdoi_attr(type
), flag
,
2303 s_ipsecdoi_attr_v(type
, lorv
));
2305 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2309 case IPSECDOI_ATTR_ENC_MODE
:
2311 plog(LLV_ERROR
, LOCATION
, NULL
,
2312 "must be TV when ENC_MODE.\n");
2317 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2318 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2321 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2322 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2323 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2324 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2325 plog(LLV_DEBUG
, LOCATION
, NULL
,
2326 "UDP encapsulation requested\n");
2330 plog(LLV_ERROR
, LOCATION
, NULL
,
2331 "invalid encryption mode=%u.\n",
2337 case IPSECDOI_ATTR_AUTH
:
2339 plog(LLV_ERROR
, LOCATION
, NULL
,
2340 "must be TV when AUTH.\n");
2345 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2346 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2347 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2349 plog(LLV_ERROR
, LOCATION
, NULL
,
2350 "auth algorithm %u conflicts "
2351 "with transform %u.\n",
2356 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2357 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2358 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2362 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2363 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2364 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2368 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2369 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2370 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2374 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2375 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2376 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2380 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2381 case IPSECDOI_ATTR_AUTH_KPDK
:
2382 plog(LLV_ERROR
, LOCATION
, NULL
,
2383 "auth algorithm %u isn't supported.\n",
2387 plog(LLV_ERROR
, LOCATION
, NULL
,
2388 "invalid auth algorithm=%u.\n",
2394 case IPSECDOI_ATTR_SA_LD_TYPE
:
2396 plog(LLV_ERROR
, LOCATION
, NULL
,
2397 "must be TV when LD_TYPE.\n");
2402 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2403 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2406 plog(LLV_ERROR
, LOCATION
, NULL
,
2407 "invalid life type %d.\n", lorv
);
2412 case IPSECDOI_ATTR_SA_LD
:
2414 /* i.e. ISAKMP_GEN_TV */
2415 plog(LLV_DEBUG
, LOCATION
, NULL
,
2416 "life duration was in TLV.\n");
2418 /* i.e. ISAKMP_GEN_TLV */
2420 plog(LLV_ERROR
, LOCATION
, NULL
,
2421 "invalid length of LD\n");
2427 case IPSECDOI_ATTR_GRP_DESC
:
2429 plog(LLV_ERROR
, LOCATION
, NULL
,
2430 "must be TV when GRP_DESC.\n");
2434 if (!alg_oakley_dhdef_ok(lorv
)) {
2435 plog(LLV_ERROR
, LOCATION
, NULL
,
2436 "invalid group description=%u.\n",
2442 case IPSECDOI_ATTR_KEY_LENGTH
:
2444 plog(LLV_ERROR
, LOCATION
, NULL
,
2445 "must be TV when KEY_LENGTH.\n");
2450 case IPSECDOI_ATTR_KEY_ROUNDS
:
2451 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2452 case IPSECDOI_ATTR_COMP_PRIVALG
:
2453 plog(LLV_ERROR
, LOCATION
, NULL
,
2454 "attr type=%u isn't supported.\n", type
);
2458 plog(LLV_ERROR
, LOCATION
, NULL
,
2459 "invalid attribute type %d.\n", type
);
2465 d
= (struct isakmp_data
*)((char *)d
2468 tlen
-= (sizeof(*d
) + lorv
);
2469 d
= (struct isakmp_data
*)((caddr_t
)d
2470 + sizeof(*d
) + lorv
);
2474 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2475 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2476 plog(LLV_ERROR
, LOCATION
, NULL
,
2477 "attr AUTH must be present for AH.\n");
2481 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2482 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2483 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2484 plog(LLV_ERROR
, LOCATION
, NULL
,
2485 "attr AUTH must be present for ESP NULL encryption.\n");
2493 check_attr_ipcomp(trns
)
2494 struct isakmp_pl_t
*trns
;
2496 struct isakmp_data
*d
;
2500 int attrseen
[16]; /* XXX magic number */
2502 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2503 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2504 memset(attrseen
, 0, sizeof(attrseen
));
2507 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2508 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2509 lorv
= ntohs(d
->lorv
);
2511 plog(LLV_DEBUG
, LOCATION
, NULL
,
2512 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2515 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2519 case IPSECDOI_ATTR_ENC_MODE
:
2521 plog(LLV_ERROR
, LOCATION
, NULL
,
2522 "must be TV when ENC_MODE.\n");
2527 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2528 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2531 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2532 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2533 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2534 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2535 plog(LLV_DEBUG
, LOCATION
, NULL
,
2536 "UDP encapsulation requested\n");
2540 plog(LLV_ERROR
, LOCATION
, NULL
,
2541 "invalid encryption mode=%u.\n",
2547 case IPSECDOI_ATTR_SA_LD_TYPE
:
2549 plog(LLV_ERROR
, LOCATION
, NULL
,
2550 "must be TV when LD_TYPE.\n");
2555 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2556 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2559 plog(LLV_ERROR
, LOCATION
, NULL
,
2560 "invalid life type %d.\n", lorv
);
2565 case IPSECDOI_ATTR_SA_LD
:
2567 /* i.e. ISAKMP_GEN_TV */
2568 plog(LLV_DEBUG
, LOCATION
, NULL
,
2569 "life duration was in TLV.\n");
2571 /* i.e. ISAKMP_GEN_TLV */
2573 plog(LLV_ERROR
, LOCATION
, NULL
,
2574 "invalid length of LD\n");
2580 case IPSECDOI_ATTR_GRP_DESC
:
2582 plog(LLV_ERROR
, LOCATION
, NULL
,
2583 "must be TV when GRP_DESC.\n");
2587 if (!alg_oakley_dhdef_ok(lorv
)) {
2588 plog(LLV_ERROR
, LOCATION
, NULL
,
2589 "invalid group description=%u.\n",
2595 case IPSECDOI_ATTR_AUTH
:
2596 plog(LLV_ERROR
, LOCATION
, NULL
,
2597 "invalid attr type=%u.\n", type
);
2600 case IPSECDOI_ATTR_KEY_LENGTH
:
2601 case IPSECDOI_ATTR_KEY_ROUNDS
:
2602 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2603 case IPSECDOI_ATTR_COMP_PRIVALG
:
2604 plog(LLV_ERROR
, LOCATION
, NULL
,
2605 "attr type=%u isn't supported.\n", type
);
2609 plog(LLV_ERROR
, LOCATION
, NULL
,
2610 "invalid attribute type %d.\n", type
);
2616 d
= (struct isakmp_data
*)((char *)d
2619 tlen
-= (sizeof(*d
) + lorv
);
2620 d
= (struct isakmp_data
*)((caddr_t
)d
2621 + sizeof(*d
) + lorv
);
2626 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2627 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2628 plog(LLV_ERROR
, LOCATION
, NULL
,
2629 "attr AUTH must be present for AH.\n", type
);
2639 * create phase1 proposal from remote configuration.
2640 * NOT INCLUDING isakmp general header of SA payload
2643 ipsecdoi_setph1proposal(props
)
2644 struct isakmpsa
*props
;
2649 /* count total size of SA minus isakmp general header */
2650 /* not including isakmp general header of SA payload */
2651 sablen
= sizeof(struct ipsecdoi_sa_b
);
2652 sablen
+= setph1prop(props
, NULL
);
2654 mysa
= vmalloc(sablen
);
2656 plog(LLV_ERROR
, LOCATION
, NULL
,
2657 "failed to allocate my sa buffer\n");
2661 /* create SA payload */
2662 /* not including isakmp general header */
2663 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2664 (ALIGNED_CAST(struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2666 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2672 setph1prop(props
, buf
)
2673 struct isakmpsa
*props
;
2676 struct isakmp_pl_p
*prop
= NULL
;
2677 struct isakmpsa
*s
= NULL
;
2678 int proplen
, trnslen
;
2679 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2683 proplen
= sizeof(*prop
);
2685 /* create proposal */
2686 prop
= (struct isakmp_pl_p
*)p
;
2687 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2688 prop
->p_no
= props
->prop_no
;
2689 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2697 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 */
2713 /* update proposal length */
2715 prop
->h
.len
= htons(proplen
);
2716 prop
->num_t
= trns_num
;
2724 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
);
2754 struct isakmpsa
*sa
;
2761 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2763 attrlen
+= sizeof(struct isakmp_data
)
2764 + sizeof(struct isakmp_data
);
2765 if (sa
->lifetime
> 0xffff)
2766 attrlen
+= sizeof(lifetime
);
2768 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2769 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2770 if (sa
->lifetime
> 0xffff) {
2771 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2775 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2782 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2784 attrlen
+= sizeof(struct isakmp_data
)
2785 + sizeof(struct isakmp_data
);
2786 if (sa
->lifebyte
> 0xffff)
2787 attrlen
+= sizeof(lifebyte
);
2789 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2790 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2791 if (sa
->lifebyte
> 0xffff) {
2792 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2796 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2803 attrlen
+= sizeof(struct isakmp_data
);
2805 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2808 attrlen
+= sizeof(struct isakmp_data
);
2810 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2812 if (sa
->authmethod
) {
2815 #ifdef ENABLE_HYBRID
2816 authmethod
= switch_authmethod(sa
->authmethod
);
2818 authmethod
= sa
->authmethod
;
2820 attrlen
+= sizeof(struct isakmp_data
);
2822 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2825 attrlen
+= sizeof(struct isakmp_data
);
2827 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2829 switch (sa
->dh_group
) {
2830 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2831 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2832 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2833 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2834 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2835 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2836 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2837 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2838 /* don't attach group type for known groups */
2839 attrlen
+= sizeof(struct isakmp_data
);
2841 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2845 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2846 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2847 /* don't attach group type for known groups */
2848 attrlen
+= sizeof(struct isakmp_data
);
2850 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2851 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2860 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2861 sa
->gssid
!= NULL
) {
2862 attrlen
+= sizeof(struct isakmp_data
);
2864 * Older versions of racoon just placed the ISO-Latin-1
2865 * string on the wire directly. Check to see if we are
2866 * configured to be compatible with this behavior. Otherwise,
2867 * we encode the GSS ID as UTF-16LE for Windows 2000
2868 * compatibility, which requires twice the number of octets.
2870 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
)
2871 attrlen
+= sa
->gssid
->l
;
2873 attrlen
+= sa
->gssid
->l
* 2;
2875 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %zu, "
2876 "val '%.*s'\n", sa
->gssid
->l
, (int)sa
->gssid
->l
,
2878 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
2879 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2880 (caddr_t
)sa
->gssid
->v
,
2883 size_t dstleft
= sa
->gssid
->l
* 2;
2884 size_t srcleft
= sa
->gssid
->l
;
2885 const char *src
= (const char *)sa
->gssid
->v
;
2886 char *odst
, *dst
= racoon_malloc(dstleft
);
2890 cd
= iconv_open("utf-16le", "latin1");
2891 if (cd
== (iconv_t
) -1) {
2892 plog(LLV_ERROR
, LOCATION
, NULL
,
2893 "unable to initialize "
2894 "latin1 -> utf-16le "
2895 "converstion descriptor: %s\n",
2897 attrlen
-= sa
->gssid
->l
* 2;
2901 rv
= iconv(cd
, (__iconv_const
char **)&src
,
2902 &srcleft
, &dst
, &dstleft
);
2905 plog(LLV_ERROR
, LOCATION
, NULL
,
2906 "unable to convert GSS ID "
2907 "from latin1 -> utf-16le: "
2908 "%s\n", strerror(errno
));
2910 /* should never happen */
2911 plog(LLV_ERROR
, LOCATION
, NULL
,
2912 "%zd character%s in GSS ID "
2913 "cannot be represented "
2915 rv
, rv
== 1 ? "" : "s");
2917 (void) iconv_close(cd
);
2918 attrlen
-= sa
->gssid
->l
* 2;
2921 (void) iconv_close(cd
);
2923 /* XXX Check srcleft and dstleft? */
2925 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2926 odst
, sa
->gssid
->l
* 2);
2933 #endif /* HAVE_GSSAPI */
2939 setph2proposal0(iph2
, pp
, pr
)
2940 const struct ph2handle
*iph2
;
2941 const struct saprop
*pp
;
2942 const struct saproto
*pr
;
2945 struct isakmp_pl_p
*prop
;
2946 struct isakmp_pl_t
*trns
;
2951 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2952 const u_int8_t
*spi
;
2954 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2958 /* create proposal */
2959 prop
= (struct isakmp_pl_p
*)p
->v
;
2960 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2961 prop
->p_no
= pp
->prop_no
;
2962 prop
->proto_id
= pr
->proto_id
;
2965 spi
= (const u_int8_t
*)&pr
->spi
;
2966 switch (pr
->proto_id
) {
2967 case IPSECDOI_PROTO_IPCOMP
:
2969 * draft-shacham-ippcp-rfc2393bis-05.txt:
2970 * construct 16bit SPI (CPI).
2971 * XXX we may need to provide a configuration option to
2972 * generate 32bit SPI. otherwise we cannot interoeprate
2973 * with nodes that uses 32bit SPI, in case we are initiator.
2975 prop
->spi_size
= sizeof(u_int16_t
);
2976 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2977 p
->l
-= sizeof(pr
->spi
);
2978 p
->l
+= sizeof(u_int16_t
);
2981 prop
->spi_size
= sizeof(pr
->spi
);
2984 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2986 /* create transform */
2987 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2990 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2992 switch (pr
->proto_id
) {
2993 case IPSECDOI_PROTO_IPSEC_ESP
:
2995 * don't build a null encryption
2996 * with no authentication transform.
2998 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2999 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
3005 *np_t
= ISAKMP_NPTYPE_T
;
3009 /* get attribute length */
3012 attrlen
+= sizeof(struct isakmp_data
)
3013 + sizeof(struct isakmp_data
);
3014 if (pp
->lifetime
> 0xffff)
3015 attrlen
+= sizeof(u_int32_t
);
3017 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3018 attrlen
+= sizeof(struct isakmp_data
)
3019 + sizeof(struct isakmp_data
);
3020 if (pp
->lifebyte
> 0xffff)
3021 attrlen
+= sizeof(u_int32_t
);
3023 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
3025 attrlen
+= sizeof(struct isakmp_data
);
3027 switch (pr
->proto_id
) {
3028 case IPSECDOI_PROTO_IPSEC_ESP
:
3029 /* non authentication mode ? */
3030 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3031 attrlen
+= sizeof(struct isakmp_data
);
3033 case IPSECDOI_PROTO_IPSEC_AH
:
3034 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
3035 plog(LLV_ERROR
, LOCATION
, NULL
,
3036 "no authentication algorithm found "
3037 "but protocol is AH.\n");
3041 attrlen
+= sizeof(struct isakmp_data
);
3043 case IPSECDOI_PROTO_IPCOMP
:
3046 plog(LLV_ERROR
, LOCATION
, NULL
,
3047 "invalid protocol: %d\n", pr
->proto_id
);
3052 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3053 attrlen
+= sizeof(struct isakmp_data
);
3055 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
3058 prop
= (struct isakmp_pl_p
*)p
->v
;
3060 /* set transform's values */
3061 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3062 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
3063 trns
->t_no
= tr
->trns_no
;
3064 trns
->t_id
= tr
->trns_id
;
3066 /* set attributes */
3067 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
3070 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3071 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
3072 if (pp
->lifetime
> 0xffff) {
3073 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
3074 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3075 (caddr_t
)&v
, sizeof(v
));
3077 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3082 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3083 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3084 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
3085 if (pp
->lifebyte
> 0xffff) {
3086 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
3087 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3088 (caddr_t
)&v
, sizeof(v
));
3090 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3095 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
3098 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
3100 /* mandatory check has done above. */
3101 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3102 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
3103 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
3105 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3106 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
3107 iph2
->sainfo
->pfs_group
);
3109 /* update length of this transform. */
3110 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3111 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
3113 /* save buffer to pre-next payload */
3116 trnsoff
+= (sizeof(*trns
) + attrlen
);
3120 plog(LLV_ERROR
, LOCATION
, NULL
,
3121 "no suitable proposal was created.\n");
3125 /* update length of this protocol. */
3126 prop
->h
.len
= htons(p
->l
);
3132 * create phase2 proposal from policy configuration.
3133 * NOT INCLUDING isakmp general header of SA payload.
3134 * This function is called by initiator only.
3137 ipsecdoi_setph2proposal(iph2
)
3138 struct ph2handle
*iph2
;
3140 struct saprop
*proposal
, *a
;
3141 struct saproto
*b
= NULL
;
3143 struct ipsecdoi_sa_b
*sab
;
3144 struct isakmp_pl_p
*prop
;
3145 size_t propoff
; /* for previous field of type of next payload. */
3147 proposal
= iph2
->proposal
;
3149 iph2
->sa
= vmalloc(sizeof(*sab
));
3150 if (iph2
->sa
== NULL
) {
3151 plog(LLV_ERROR
, LOCATION
, NULL
,
3152 "failed to allocate my sa buffer\n");
3156 /* create SA payload */
3157 sab
= ALIGNED_CAST(struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
3158 sab
->doi
= htonl(IPSEC_DOI
);
3159 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3163 for (a
= proposal
; a
; a
= a
->next
) {
3164 for (b
= a
->head
; b
; b
= b
->next
) {
3166 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3167 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3168 plog (LLV_INFO
, LOCATION
, NULL
,
3169 "NAT detected -> UDP encapsulation "
3170 "(ENC_MODE %d->%d).\n",
3172 b
->encmode
+udp_diff
);
3173 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3174 b
->encmode
+= udp_diff
;
3179 q
= setph2proposal0(iph2
, a
, b
);
3185 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
3186 if (iph2
->sa
== NULL
) {
3187 plog(LLV_ERROR
, LOCATION
, NULL
,
3188 "failed to allocate my sa buffer\n");
3193 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
3195 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
3197 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3199 propoff
= iph2
->sa
->l
- q
->l
;
3209 * return 1 if all of the given protocols are tunnel mode.
3212 ipsecdoi_tunnelmode(iph2
)
3213 struct ph2handle
*iph2
;
3216 struct saproto
*pr
= NULL
;
3218 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
3219 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3220 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
3221 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
3222 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
3231 * return 1 if any of the given protocols are transport mode.
3234 ipsecdoi_any_transportmode(pp
)
3237 struct saproto
*pr
= NULL
;
3239 for (; pp
; pp
= pp
->next
) {
3240 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3241 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TRNS
||
3242 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
||
3243 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
3252 * return 1 if all of the given protocols are transport mode.
3255 ipsecdoi_transportmode(pp
)
3258 struct saproto
*pr
= NULL
;
3260 for (; pp
; pp
= pp
->next
) {
3261 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3262 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
3271 ipsecdoi_get_defaultlifetime()
3273 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3277 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3278 int proto_id
, enc
, auth
, comp
;
3280 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3282 case IPSECDOI_PROTO_IPSEC_ESP
:
3283 if (enc
== 0 || comp
!= 0) {
3284 plog(LLV_ERROR
, LOCATION
, NULL
,
3285 "illegal algorithm defined "
3286 "ESP enc=%s auth=%s comp=%s.\n",
3287 TMPALGTYPE2STR(enc
),
3288 TMPALGTYPE2STR(auth
),
3289 TMPALGTYPE2STR(comp
));
3293 case IPSECDOI_PROTO_IPSEC_AH
:
3294 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3295 plog(LLV_ERROR
, LOCATION
, NULL
,
3296 "illegal algorithm defined "
3297 "AH enc=%s auth=%s comp=%s.\n",
3298 TMPALGTYPE2STR(enc
),
3299 TMPALGTYPE2STR(auth
),
3300 TMPALGTYPE2STR(comp
));
3304 case IPSECDOI_PROTO_IPCOMP
:
3305 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3306 plog(LLV_ERROR
, LOCATION
, NULL
,
3307 "illegal algorithm defined "
3308 "IPcomp enc=%s auth=%s comp=%s.\n",
3309 TMPALGTYPE2STR(enc
),
3310 TMPALGTYPE2STR(auth
),
3311 TMPALGTYPE2STR(comp
));
3316 plog(LLV_ERROR
, LOCATION
, NULL
,
3317 "invalid ipsec protocol %d\n", proto_id
);
3320 #undef TMPALGTYPE2STR
3330 return IPSECDOI_PROTO_IPSEC_AH
;
3332 return IPSECDOI_PROTO_IPSEC_ESP
;
3333 case IPPROTO_IPCOMP
:
3334 return IPSECDOI_PROTO_IPCOMP
;
3336 return -1; /* XXX */
3344 case IPSECDOI_PROTO_IPSEC_AH
:
3346 case IPSECDOI_PROTO_IPSEC_ESP
:
3348 case IPSECDOI_PROTO_IPCOMP
:
3349 return IPPROTO_IPCOMP
;
3351 return -1; /* XXX */
3355 * Check if a subnet id is valid for comparison
3356 * with an address id ( address length mask )
3364 ipsecdoi_subnetisaddr_v4( subnet
, address
)
3365 const vchar_t
*subnet
;
3366 const vchar_t
*address
;
3368 struct in_addr
*mask
;
3370 if (address
->l
!= sizeof(struct in_addr
))
3373 if (subnet
->l
!= (sizeof(struct in_addr
)*2))
3376 mask
= ALIGNED_CAST(struct in_addr
*)(subnet
->v
+ sizeof(struct in_addr
));
3378 if (mask
->s_addr
!=0xffffffff)
3381 return memcmp(subnet
->v
,address
->v
,address
->l
);
3387 ipsecdoi_subnetisaddr_v6( subnet
, address
)
3388 const vchar_t
*subnet
;
3389 const vchar_t
*address
;
3391 struct in6_addr
*mask
;
3394 if (address
->l
!= sizeof(struct in6_addr
))
3397 if (subnet
->l
!= (sizeof(struct in6_addr
)*2))
3400 mask
= ALIGNED_CAST(struct in6_addr
*)(subnet
->v
+ sizeof(struct in6_addr
));
3402 for (i
=0; i
<16; i
++)
3403 if(mask
->s6_addr
[i
]!=0xff)
3406 return memcmp(subnet
->v
,address
->v
,address
->l
);
3413 * Check and Compare two IDs
3414 * - specify 0 for exact if wildcards are allowed
3418 * = -1 for integrity error
3422 ipsecdoi_chkcmpids( idt
, ids
, exact
)
3423 const vchar_t
*idt
; /* id cmp target */
3424 const vchar_t
*ids
; /* id cmp source */
3427 struct ipsecdoi_id_b
*id_bt
;
3428 struct ipsecdoi_id_b
*id_bs
;
3433 /* handle wildcard IDs */
3435 if (idt
== NULL
|| ids
== NULL
)
3439 plog(LLV_DEBUG
, LOCATION
, NULL
,
3440 "check and compare ids : values matched (ANONYMOUS)\n" );
3445 plog(LLV_DEBUG
, LOCATION
, NULL
,
3446 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3451 /* make sure the ids are of the same type */
3453 id_bt
= (struct ipsecdoi_id_b
*) idt
->v
;
3454 id_bs
= (struct ipsecdoi_id_b
*) ids
->v
;
3456 ident_t
.v
= idt
->v
+ sizeof(*id_bt
);
3457 ident_t
.l
= idt
->l
- sizeof(*id_bt
);
3458 ident_s
.v
= ids
->v
+ sizeof(*id_bs
);
3459 ident_s
.l
= ids
->l
- sizeof(*id_bs
);
3461 if (id_bs
->type
!= id_bt
->type
)
3464 * special exception for comparing
3465 * address to subnet id types when
3466 * the netmask is address length
3469 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR
)&&
3470 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)) {
3471 result
= ipsecdoi_subnetisaddr_v4(&ident_t
,&ident_s
);
3475 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)&&
3476 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR
)) {
3477 result
= ipsecdoi_subnetisaddr_v4(&ident_s
,&ident_t
);
3482 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR
)&&
3483 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)) {
3484 result
= ipsecdoi_subnetisaddr_v6(&ident_t
,&ident_s
);
3488 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)&&
3489 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR
)) {
3490 result
= ipsecdoi_subnetisaddr_v6(&ident_s
,&ident_t
);
3494 plog(LLV_DEBUG
, LOCATION
, NULL
,
3495 "check and compare ids : id type mismatch %s != %s\n",
3496 s_ipsecdoi_ident(id_bs
->type
),
3497 s_ipsecdoi_ident(id_bt
->type
));
3502 if(id_bs
->proto_id
!= id_bt
->proto_id
){
3503 plog(LLV_DEBUG
, LOCATION
, NULL
,
3504 "check and compare ids : proto_id mismatch %d != %d\n",
3505 id_bs
->proto_id
, id_bt
->proto_id
);
3510 /* compare the ID data. */
3512 switch (id_bt
->type
) {
3513 case IPSECDOI_ID_DER_ASN1_DN
:
3514 case IPSECDOI_ID_DER_ASN1_GN
:
3515 /* compare asn1 ids */
3516 result
= eay_cmp_asn1dn(&ident_t
, &ident_s
);
3519 case IPSECDOI_ID_IPV4_ADDR
:
3520 /* validate lengths */
3521 if ((ident_t
.l
!= sizeof(struct in_addr
))||
3522 (ident_s
.l
!= sizeof(struct in_addr
)))
3526 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3527 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3528 /* validate lengths */
3529 if ((ident_t
.l
!= (sizeof(struct in_addr
)*2))||
3530 (ident_s
.l
!= (sizeof(struct in_addr
)*2)))
3535 case IPSECDOI_ID_IPV6_ADDR
:
3536 /* validate lengths */
3537 if ((ident_t
.l
!= sizeof(struct in6_addr
))||
3538 (ident_s
.l
!= sizeof(struct in6_addr
)))
3542 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3543 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3544 /* validate lengths */
3545 if ((ident_t
.l
!= (sizeof(struct in6_addr
)*2))||
3546 (ident_s
.l
!= (sizeof(struct in6_addr
)*2)))
3550 case IPSECDOI_ID_FQDN
:
3551 case IPSECDOI_ID_USER_FQDN
:
3552 case IPSECDOI_ID_KEY_ID
:
3556 plog(LLV_ERROR
, LOCATION
, NULL
,
3557 "Unhandled id type %i specified for comparison\n",
3562 /* validate matching data and length */
3563 if (ident_t
.l
== ident_s
.l
)
3564 result
= memcmp(ident_t
.v
,ident_s
.v
,ident_t
.l
);
3570 /* debug level output */
3571 if(loglevel
>= LLV_DEBUG
) {
3572 char *idstrt
= ipsecdoi_id2str(idt
);
3573 char *idstrs
= ipsecdoi_id2str(ids
);
3576 plog(LLV_DEBUG
, LOCATION
, NULL
,
3577 "check and compare ids : values matched (%s)\n",
3578 s_ipsecdoi_ident(id_bs
->type
) );
3580 plog(LLV_DEBUG
, LOCATION
, NULL
,
3581 "check and compare ids : value mismatch (%s)\n",
3582 s_ipsecdoi_ident(id_bs
->type
));
3584 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid target: \'%s\'\n", idstrt
);
3585 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid source: \'%s\'\n", idstrs
);
3587 racoon_free(idstrs
);
3588 racoon_free(idstrt
);
3599 /* id integrity error */
3600 plog(LLV_DEBUG
, LOCATION
, NULL
, "check and compare ids : %s integrity error\n",
3601 s_ipsecdoi_ident(id_bs
->type
));
3602 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid target: length = \'%zu\'\n", ident_t
.l
);
3603 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid source: length = \'%zu\'\n", ident_s
.l
);
3610 * check the following:
3611 * - In main mode with pre-shared key, only address type can be used.
3612 * - if proper type for phase 1 ?
3613 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3614 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3615 * - if ID payload sent from peer is equal to the ID expected by me.
3617 * both of "id" and "id_p" should be ID payload without general header,
3620 ipsecdoi_checkid1(iph1
)
3621 struct ph1handle
*iph1
;
3623 struct ipsecdoi_id_b
*id_b
;
3624 struct sockaddr_storage
*sa
;
3627 if (iph1
->id_p
== NULL
) {
3628 plog(LLV_ERROR
, LOCATION
, NULL
,
3629 "invalid iph1 passed id_p == NULL\n");
3630 return ISAKMP_INTERNAL_ERROR
;
3632 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3633 plog(LLV_ERROR
, LOCATION
, NULL
,
3634 "invalid value passed as \"ident\" (len=%lu)\n",
3635 (u_long
)iph1
->id_p
->l
);
3636 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3639 id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3641 /* In main mode with pre-shared key, only address type can be used.
3642 * If NAT Traversal being used and peer is behind nat and
3643 * natt version = 02 - allow non-address ID type.
3645 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
3646 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3648 && (iph1
->natt_flags
& NAT_DETECTED_PEER
) == 0
3651 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3652 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3653 plog(LLV_ERROR
, LOCATION
, NULL
,
3654 "Expecting IP address type in main mode, "
3655 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3656 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3660 /* if proper type for phase 1 ? */
3661 switch (id_b
->type
) {
3662 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3663 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3664 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3665 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3666 plog(LLV_WARNING
, LOCATION
, NULL
,
3667 "such ID type %s is not proper.\n",
3668 s_ipsecdoi_ident(id_b
->type
));
3672 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3673 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
||
3674 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3676 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3677 plog(LLV_WARNING
, LOCATION
, NULL
,
3678 "protocol ID and Port mismatched. "
3679 "proto_id:%d port:%d\n",
3680 id_b
->proto_id
, ntohs(id_b
->port
));
3683 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3685 * copmaring with expected port.
3686 * always permit if port is equal to PORT_ISAKMP
3688 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3692 switch (iph1
->remote
->ss_family
) {
3694 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3698 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3702 plog(LLV_ERROR
, LOCATION
, NULL
,
3703 "invalid family: %d\n",
3704 iph1
->remote
->ss_family
);
3705 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3707 if (ntohs(id_b
->port
) != port
) {
3708 plog(LLV_WARNING
, LOCATION
, NULL
,
3709 "port %d expected, but %d\n",
3710 port
, ntohs(id_b
->port
));
3717 /* compare with the ID if specified. */
3718 if (genlist_next(iph1
->rmconf
->idvl_p
, 0)) {
3719 vchar_t
*ident0
= NULL
;
3724 struct genlist_entry
*gpb
;
3726 for (id
= genlist_next (iph1
->rmconf
->idvl_p
, &gpb
); id
; id
= genlist_next (0, &gpb
)) {
3727 /* check the type of both IDs */
3728 if (id
->idtype
!= doi2idtype(id_b
->type
))
3729 continue; /* ID type mismatch */
3733 /* compare defined ID with the ID sent by peer. */
3736 ident0
= getidval(id
->idtype
, id
->id
);
3738 switch (id
->idtype
) {
3741 ident
.v
= iph1
->id_p
->v
+ sizeof(*id_b
);
3742 ident
.l
= iph1
->id_p
->l
- sizeof(*id_b
);
3743 if (eay_cmp_asn1dn(ident0
, &ident
) == 0)
3746 plog(LLV_WARNING
, LOCATION
, NULL
, "ASN1DN ID matching not implemented - passed.\n");
3747 goto matched
; //%%%%%% hack for now until we have code to do this.
3750 case IDTYPE_ADDRESS
:
3751 sa
= ALIGNED_CAST(struct sockaddr_storage
*)ident0
->v
;
3752 sa2
= (caddr_t
)(id_b
+ 1);
3753 switch (sa
->ss_family
) {
3755 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3756 continue; /* ID value mismatch */
3757 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3758 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) == 0)
3763 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3764 continue; /* ID value mismatch */
3765 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3766 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) == 0)
3775 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
) == 0)
3780 if (ident0
!= NULL
) {
3784 plog(LLV_WARNING
, LOCATION
, NULL
, "No ID match.\n");
3785 if (iph1
->rmconf
->verify_identifier
)
3786 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3787 matched
: /* ID value match */
3796 * create ID payload for phase 1 and set into iph1->id.
3797 * NOT INCLUDING isakmp general header.
3798 * see, RFC2407 4.6.2.1
3801 ipsecdoi_setid1(iph1
)
3802 struct ph1handle
*iph1
;
3804 vchar_t
*ret
= NULL
;
3805 struct ipsecdoi_id_b id_b
;
3806 vchar_t
*ident
= NULL
;
3807 struct sockaddr_storage
*ipid
= NULL
;
3814 switch (iph1
->rmconf
->idvtype
) {
3816 id_b
.type
= IPSECDOI_ID_FQDN
;
3817 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3819 case IDTYPE_USERFQDN
:
3820 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3821 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3824 case IDTYPE_KEYIDUSE
:
3825 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3826 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3829 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3830 if (iph1
->rmconf
->idv
) {
3831 /* XXX it must be encoded to asn1dn. */
3832 ident
= vdup(iph1
->rmconf
->idv
);
3834 if (oakley_getmycert(iph1
) < 0) {
3835 plog(LLV_ERROR
, LOCATION
, NULL
,
3836 "failed to get own CERT.\n");
3839 #if TARGET_OS_EMBEDDED
3841 SecCertificateRef certificate
;
3846 certificate
= crypto_cssm_x509cert_get_SecCertificateRef(&iph1
->cert
->cert
);
3847 if (certificate
== NULL
) {
3848 plog(LLV_ERROR
, LOCATION
, NULL
,
3849 "failed to get SecCertificateRef\n");
3852 subject
= SecCertificateCopySubjectSequence(certificate
);
3853 if (subject
== NULL
) {
3854 plog(LLV_ERROR
, LOCATION
, NULL
,
3855 "failed to get subjectName\n");
3856 CFRelease(certificate
);
3859 len
= CFDataGetLength(subject
);
3860 namePtr
= CFDataGetBytePtr(subject
);
3861 ident
= vmalloc(len
);
3862 if (ident
== NULL
) {
3863 plog(LLV_ERROR
, LOCATION
, NULL
,
3864 "failed to get subjectName\n");
3865 CFRelease(certificate
);
3869 memcpy(ident
->v
, namePtr
, len
);
3870 CFRelease(certificate
);
3875 ident
= eay_get_x509asn1subjectname(&iph1
->cert
->cert
);
3879 case IDTYPE_ADDRESS
:
3881 * if the value of the id type was set by the configuration
3882 * file, then use it. otherwise the value is get from local
3883 * ip address by using ike negotiation.
3885 if (iph1
->rmconf
->idv
)
3886 ipid
= ALIGNED_CAST(struct sockaddr_storage
*)iph1
->rmconf
->idv
->v
;
3896 /* use IP address */
3897 switch (ipid
->ss_family
) {
3899 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3900 l
= sizeof(struct in_addr
);
3901 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3905 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3906 l
= sizeof(struct in6_addr
);
3907 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3911 plog(LLV_ERROR
, LOCATION
, NULL
,
3912 "invalid address family.\n");
3915 id_b
.proto_id
= IPPROTO_UDP
;
3916 id_b
.port
= htons(PORT_ISAKMP
);
3919 plog(LLV_ERROR
, LOCATION
, NULL
,
3920 "failed to get ID buffer.\n");
3923 memcpy(ident
->v
, p
, ident
->l
);
3927 plog(LLV_ERROR
, LOCATION
, NULL
,
3928 "failed to get ID buffer.\n");
3932 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3934 plog(LLV_ERROR
, LOCATION
, NULL
,
3935 "failed to get ID buffer.\n");
3939 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3940 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3944 plog(LLV_DEBUG
, LOCATION
, NULL
,
3945 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3946 plogdump(LLV_DEBUG
, iph1
->id
->v
, iph1
->id
->l
);
3954 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3963 vchar_t
*new = NULL
;
3967 else if (lcconf
->ident
[type
])
3968 new = vdup(lcconf
->ident
[type
]);
3973 /* it's only called by cfparse.y. */
3975 set_identifier(vpp
, type
, value
)
3976 vchar_t
**vpp
, *value
;
3979 return set_identifier_qual(vpp
, type
, value
, IDQUAL_UNSPEC
);
3983 set_identifier_qual(vpp
, type
, value
, qual
)
3984 vchar_t
**vpp
, *value
;
3988 vchar_t
*new = NULL
;
3990 /* simply return if value is null. */
3992 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3993 plog(LLV_ERROR
, LOCATION
, NULL
,
3994 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
4002 case IDTYPE_USERFQDN
:
4004 plog(LLV_ERROR
, LOCATION
, NULL
,
4005 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
4008 case IDTYPE_KEYIDUSE
:
4009 #ifdef ENABLE_HYBRID
4012 /* length is adjusted since QUOTEDSTRING teminates NULL. */
4013 new = vmalloc(value
->l
- 1);
4016 memcpy(new->v
, value
->v
, new->l
);
4020 * If no qualifier is specified: IDQUAL_UNSPEC. It means
4021 * to use a file for backward compatibility sake.
4025 case IDQUAL_UNSPEC
: {
4030 fp
= fopen(value
->v
, "r");
4032 plog(LLV_ERROR
, LOCATION
, NULL
,
4033 "can not open %s\n", value
->v
);
4037 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
4038 new = vrealloc(new, tlen
+ len
);
4043 memcpy(new->v
+ tlen
, b
, len
);
4051 new = vmalloc(value
->l
- 1);
4053 plog(LLV_ERROR
, LOCATION
, NULL
,
4054 "can not allocate memory");
4057 memcpy(new->v
, value
->v
, new->l
);
4061 plog(LLV_ERROR
, LOCATION
, NULL
,
4062 "unknown qualifier");
4067 case IDTYPE_ADDRESS
: {
4068 struct sockaddr_storage
*sa
;
4070 /* length is adjusted since QUOTEDSTRING teminates NULL. */
4074 sa
= str2saddr(value
->v
, NULL
);
4076 plog(LLV_ERROR
, LOCATION
, NULL
,
4077 "invalid ip address %s\n", value
->v
);
4081 new = vmalloc(sysdep_sa_len((struct sockaddr
*)sa
));
4086 memcpy(new->v
, sa
, new->l
);
4092 if (value
->v
[0] == '~')
4093 /* Hex-encoded ASN1 strings */
4094 new = eay_hex2asn1dn(value
->v
+ 1, - 1);
4096 /* DN encoded strings */
4097 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
4102 if (loglevel
>= LLV_DEBUG
) {
4105 unsigned char *ptr
= (unsigned char *) new->v
, *buf
;
4109 xn
= d2i_X509_NAME(NULL
, (void *)&ptr
, new->l
);
4110 bio
= BIO_new(BIO_s_mem());
4112 X509_NAME_print_ex(bio
, xn
, 0, 0);
4113 len
= BIO_get_mem_data(bio
, &ptr
);
4116 plog(LLV_DEBUG
, LOCATION
, NULL
, "Parsed DN: %s\n", ptr
);
4122 plog(LLV_DEBUG
, LOCATION
, NULL
, "Setting ID type ASN1DN from string not supported\n");
4135 * create ID payload for phase 2, and set into iph2->id and id_p. There are
4136 * NOT INCLUDING isakmp general header.
4137 * this function is for initiator. responder will get to copy from payload.
4138 * responder ID type is always address type.
4139 * see, RFC2407 4.6.2.1
4142 ipsecdoi_setid2(iph2
)
4143 struct ph2handle
*iph2
;
4145 struct secpolicy
*sp
;
4147 /* check there is phase 2 handler ? */
4148 sp
= getspbyspid(iph2
->spid
);
4150 plog(LLV_ERROR
, LOCATION
, NULL
,
4151 "no policy found for spid:%u.\n", iph2
->spid
);
4155 iph2
->id
= ipsecdoi_sockaddr2id(&sp
->spidx
.src
,
4156 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
4157 if (iph2
->id
== NULL
) {
4158 plog(LLV_ERROR
, LOCATION
, NULL
,
4159 "failed to get ID for %s\n",
4160 spidx2str(&sp
->spidx
));
4163 if (((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR
||
4164 (ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
) &&
4165 iph2
->side
== RESPONDER
&&
4166 iph2
->ph1
&& (iph2
->ph1
->natt_flags
& NAT_DETECTED_ME
) &&
4167 lcconf
->ext_nat_id
) {
4169 if (!(iph2
->id
= vdup(lcconf
->ext_nat_id
))) {
4173 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
4174 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
4175 plogdump(LLV_DEBUG
, iph2
->id
->v
, iph2
->id
->l
);
4178 iph2
->id_p
= ipsecdoi_sockaddr2id(&sp
->spidx
.dst
,
4179 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
4180 if (iph2
->id_p
== NULL
) {
4181 plog(LLV_ERROR
, LOCATION
, NULL
,
4182 "failed to get ID for %s\n",
4183 spidx2str(&sp
->spidx
));
4187 plog(LLV_DEBUG
, LOCATION
, NULL
,
4188 "use remote ID type %s\n",
4189 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
4190 plogdump(LLV_DEBUG
, iph2
->id
->v
, iph2
->id
->l
);
4196 * set address type of ID.
4197 * NOT INCLUDING general header.
4200 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
4201 struct sockaddr_storage
*saddr
;
4206 int type
, len1
, len2
;
4211 * Q. When type is SUBNET, is it allowed to be ::1/128.
4212 * A. Yes. (consensus at bake-off)
4214 switch (saddr
->ss_family
) {
4216 len1
= sizeof(struct in_addr
);
4217 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
4218 type
= IPSECDOI_ID_IPV4_ADDR
;
4221 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
4222 len2
= sizeof(struct in_addr
);
4224 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
4225 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
4229 len1
= sizeof(struct in6_addr
);
4230 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
4231 type
= IPSECDOI_ID_IPV6_ADDR
;
4234 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
4235 len2
= sizeof(struct in6_addr
);
4237 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
4238 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
4242 plog(LLV_ERROR
, LOCATION
, NULL
,
4243 "invalid family: %d.\n", saddr
->ss_family
);
4248 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4250 plog(LLV_ERROR
, LOCATION
, NULL
,
4251 "failed to get ID buffer.\n");
4255 memset(new->v
, 0, new->l
);
4257 /* set the part of header. */
4258 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4260 /* set ul_proto and port */
4262 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4263 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4265 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4266 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4267 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4268 port
== IPSEC_PORT_ANY
? 0 : port
;
4269 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
4275 u_char
*p
= (unsigned char *) new->v
+
4276 sizeof(struct ipsecdoi_id_b
) + len1
;
4277 u_int bits
= prefixlen
;
4285 *p
= ~((1 << (8 - bits
)) - 1);
4292 ipsecdoi_sockrange2id(laddr
, haddr
, ul_proto
)
4293 struct sockaddr_storage
*laddr
, *haddr
;
4297 int type
, len1
, len2
;
4300 if (laddr
->ss_family
!= haddr
->ss_family
) {
4301 plog(LLV_ERROR
, LOCATION
, NULL
, "Address family mismatch\n");
4305 switch (laddr
->ss_family
) {
4307 type
= IPSECDOI_ID_IPV4_ADDR_RANGE
;
4308 len1
= sizeof(struct in_addr
);
4309 len2
= sizeof(struct in_addr
);
4313 type
= IPSECDOI_ID_IPV6_ADDR_RANGE
;
4314 len1
= sizeof(struct in6_addr
);
4315 len2
= sizeof(struct in6_addr
);
4319 plog(LLV_ERROR
, LOCATION
, NULL
,
4320 "invalid family: %d.\n", laddr
->ss_family
);
4325 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4327 plog(LLV_ERROR
, LOCATION
, NULL
,
4328 "failed to get ID buffer.\n");
4332 memset(new->v
, 0, new->l
);
4333 /* set the part of header. */
4334 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4336 /* set ul_proto and port */
4338 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4339 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4341 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4342 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4343 port
= ((struct sockaddr_in
*)(laddr
))->sin_port
;
4344 (ALIGNED_CAST(struct ipsecdoi_id_b
*)new->v
)->port
=
4345 port
== IPSEC_PORT_ANY
? 0 : port
;
4346 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
),
4347 (caddr_t
)&((struct sockaddr_in
*)(laddr
))->sin_addr
,
4349 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
,
4350 (caddr_t
)&((struct sockaddr_in
*)haddr
)->sin_addr
,
4357 * create sockaddr_storage structure from ID payload (buf).
4358 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4359 * see, RFC2407 4.6.2.1
4362 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
4364 struct sockaddr_storage
*saddr
;
4365 u_int8_t
*prefixlen
;
4366 u_int16_t
*ul_proto
;
4368 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)buf
->v
;
4372 * When a ID payload of subnet type with a IP address of full bit
4373 * masked, it has to be processed as host address.
4374 * e.g. below 2 type are same.
4375 * type = ipv6 subnet, data = 2001::1/128
4376 * type = ipv6 address, data = 2001::1
4378 switch (id_b
->type
) {
4379 case IPSECDOI_ID_IPV4_ADDR
:
4380 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4381 saddr
->ss_len
= sizeof(struct sockaddr_in
);
4382 saddr
->ss_family
= AF_INET
;
4383 ((struct sockaddr_in
*)saddr
)->sin_port
=
4386 : id_b
->port
); /* see sockaddr2id() */
4387 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
4388 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4391 case IPSECDOI_ID_IPV6_ADDR
:
4392 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4393 saddr
->ss_len
= sizeof(struct sockaddr_in6
);
4394 saddr
->ss_family
= AF_INET6
;
4395 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
4398 : id_b
->port
); /* see sockaddr2id() */
4399 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
4400 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4404 plog(LLV_ERROR
, LOCATION
, NULL
,
4405 "unsupported ID type %d\n", id_b
->type
);
4406 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
4409 /* get prefix length */
4410 switch (id_b
->type
) {
4411 case IPSECDOI_ID_IPV4_ADDR
:
4412 plen
= sizeof(struct in_addr
) << 3;
4415 case IPSECDOI_ID_IPV6_ADDR
:
4416 plen
= sizeof(struct in6_addr
) << 3;
4419 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4421 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4426 int alen
= sizeof(struct in_addr
);
4428 switch (id_b
->type
) {
4429 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4430 alen
= sizeof(struct in_addr
);
4433 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4434 alen
= sizeof(struct in6_addr
);
4441 return ISAKMP_INTERNAL_ERROR
;
4443 /* get subnet mask length */
4447 p
= (unsigned char *) buf
->v
4448 + sizeof(struct ipsecdoi_id_b
)
4451 for (; *p
== 0xff; p
++) {
4474 *ul_proto
= id_b
->proto_id
== 0
4476 : id_b
->proto_id
; /* see sockaddr2id() */
4482 * make printable string from ID payload except of general header.
4492 static char buf
[BUFLEN
];
4493 struct ipsecdoi_id_b
*id_b
= ALIGNED_CAST(struct ipsecdoi_id_b
*)id
->v
;
4494 struct sockaddr_storage saddr
;
4497 bzero(&saddr
, sizeof(saddr
));
4499 switch (id_b
->type
) {
4500 case IPSECDOI_ID_IPV4_ADDR
:
4501 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4502 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4504 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4505 saddr
.ss_family
= AF_INET
;
4506 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4507 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4508 id
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4511 case IPSECDOI_ID_IPV6_ADDR
:
4512 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4513 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4514 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4515 saddr
.ss_family
= AF_INET6
;
4516 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4517 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4518 id
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4519 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4520 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4521 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4527 switch (id_b
->type
) {
4528 case IPSECDOI_ID_IPV4_ADDR
:
4530 case IPSECDOI_ID_IPV6_ADDR
:
4532 len
= snprintf( buf
, sizeof(buf
), "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4535 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4537 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4542 int alen
= sizeof(struct in_addr
);
4544 switch (id_b
->type
) {
4545 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4546 alen
= sizeof(struct in_addr
);
4549 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4550 alen
= sizeof(struct in6_addr
);
4561 /* get subnet mask length */
4565 p
= (unsigned char *) id
->v
4566 + sizeof(struct ipsecdoi_id_b
)
4569 for (; *p
== 0xff; p
++) {
4588 len
= snprintf( buf
, sizeof(buf
), "%s/%i", saddrwop2str((struct sockaddr
*)&saddr
), plen
);
4592 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4594 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4596 saddr
.ss_len
= sizeof(struct sockaddr_in
);
4597 saddr
.ss_family
= AF_INET
;
4598 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4599 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4600 id
->v
+ sizeof(*id_b
) + sizeof(struct in_addr
),
4601 sizeof(struct in_addr
));
4604 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4610 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4612 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4614 saddr
.ss_len
= sizeof(struct sockaddr_in6
);
4615 saddr
.ss_family
= AF_INET6
;
4616 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4617 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4618 id
->v
+ sizeof(*id_b
) + sizeof(struct in6_addr
),
4619 sizeof(struct in6_addr
));
4620 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4621 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4622 ? (ALIGNED_CAST(struct sockaddr_in6
*)id_b
)->sin6_scope_id
4626 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4632 case IPSECDOI_ID_FQDN
:
4633 case IPSECDOI_ID_USER_FQDN
:
4634 len
= id
->l
- sizeof(*id_b
);
4637 memcpy(buf
, id
->v
+ sizeof(*id_b
), len
);
4640 case IPSECDOI_ID_DER_ASN1_DN
:
4641 case IPSECDOI_ID_DER_ASN1_GN
:
4644 X509_NAME
*xn
= NULL
;
4647 dat
= id
->v
+ sizeof(*id_b
);
4648 len
= id
->l
- sizeof(*id_b
);
4650 if (d2i_X509_NAME(&xn
, (void*) &dat
, len
) != NULL
) {
4651 BIO
*bio
= BIO_new(BIO_s_mem());
4652 X509_NAME_print_ex(bio
, xn
, 0, 0);
4653 len
= BIO_get_mem_data(bio
, &dat
);
4656 memcpy(buf
,dat
,len
);
4663 plog(LLV_ERROR
, LOCATION
, NULL
,
4664 "unable to extract asn1dn from id\n");
4666 len
= snprintf(buf
, sizeof(buf
), "<ASN1-DN>");
4672 /* currently unhandled id types */
4673 case IPSECDOI_ID_KEY_ID
:
4674 len
= snprintf( buf
, sizeof(buf
), "<KEY-ID>");
4678 plog(LLV_ERROR
, LOCATION
, NULL
,
4679 "unknown ID type %d\n", id_b
->type
);
4683 len
= snprintf( buf
, sizeof(buf
), "<?>");
4685 ret
= racoon_malloc(len
+1);
4687 memcpy(ret
,buf
,len
);
4695 * set IPsec data attributes into a proposal.
4696 * NOTE: MUST called per a transform.
4699 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4700 struct isakmp_pl_t
*t
;
4705 struct isakmp_data
*d
, *prev
;
4711 tr
->trns_no
= t
->t_no
;
4712 tr
->trns_id
= t
->t_id
;
4714 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4715 prev
= (struct isakmp_data
*)NULL
;
4716 d
= (struct isakmp_data
*)(t
+ 1);
4719 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4720 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4722 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4726 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4727 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4729 plog(LLV_DEBUG
, LOCATION
, NULL
,
4730 "type=%s, flag=0x%04x, lorv=%s\n",
4731 s_ipsecdoi_attr(type
), flag
,
4732 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4735 case IPSECDOI_ATTR_SA_LD_TYPE
:
4737 int type
= ntohs(d
->lorv
);
4739 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4740 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4744 plog(LLV_WARNING
, LOCATION
, NULL
,
4745 "invalid life duration type. "
4747 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4752 case IPSECDOI_ATTR_SA_LD
:
4754 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4755 IPSECDOI_ATTR_SA_LD_TYPE
) {
4756 plog(LLV_ERROR
, LOCATION
, NULL
,
4757 "life duration must follow ltype\n");
4763 vchar_t
*ld_buf
= NULL
;
4766 /* i.e. ISAKMP_GEN_TV */
4767 ld_buf
= vmalloc(sizeof(d
->lorv
));
4768 if (ld_buf
== NULL
) {
4769 plog(LLV_ERROR
, LOCATION
, NULL
,
4770 "failed to get LD buffer.\n");
4773 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4775 int len
= ntohs(d
->lorv
);
4776 /* i.e. ISAKMP_GEN_TLV */
4777 ld_buf
= vmalloc(len
);
4778 if (ld_buf
== NULL
) {
4779 plog(LLV_ERROR
, LOCATION
, NULL
,
4780 "failed to get LD buffer.\n");
4783 memcpy(ld_buf
->v
, d
+ 1, len
);
4786 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4787 t
= ipsecdoi_set_ld(ld_buf
);
4790 plog(LLV_ERROR
, LOCATION
, NULL
,
4791 "invalid life duration.\n");
4794 /* lifetime must be equal in a proposal. */
4795 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4797 else if (pp
->lifetime
!= t
) {
4798 plog(LLV_ERROR
, LOCATION
, NULL
,
4799 "lifetime mismatched "
4801 "prev:%ld curr:%u.\n",
4802 (long)pp
->lifetime
, t
);
4806 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4807 t
= ipsecdoi_set_ld(ld_buf
);
4810 plog(LLV_ERROR
, LOCATION
, NULL
,
4811 "invalid life duration.\n");
4814 /* lifebyte must be equal in a proposal. */
4815 if (pp
->lifebyte
== 0)
4817 else if (pp
->lifebyte
!= t
) {
4818 plog(LLV_ERROR
, LOCATION
, NULL
,
4819 "lifebyte mismatched "
4821 "prev:%d curr:%u.\n",
4828 plog(LLV_ERROR
, LOCATION
, NULL
,
4829 "invalid life type: %d\n", life_t
);
4835 case IPSECDOI_ATTR_GRP_DESC
:
4837 * RFC2407: 4.5 IPSEC Security Association Attributes
4838 * Specifies the Oakley Group to be used in a PFS QM
4839 * negotiation. For a list of supported values, see
4840 * Appendix A of [IKE].
4842 if (pp
->pfs_group
== 0)
4843 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4844 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4845 plog(LLV_ERROR
, LOCATION
, NULL
,
4846 "pfs_group mismatched "
4847 "in a proposal.\n");
4852 case IPSECDOI_ATTR_ENC_MODE
:
4854 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4855 plog(LLV_ERROR
, LOCATION
, NULL
,
4856 "multiple encmode exist "
4857 "in a transform.\n");
4860 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4863 case IPSECDOI_ATTR_AUTH
:
4864 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4865 plog(LLV_ERROR
, LOCATION
, NULL
,
4866 "multiple authtype exist "
4867 "in a transform.\n");
4870 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4873 case IPSECDOI_ATTR_KEY_LENGTH
:
4874 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4875 plog(LLV_ERROR
, LOCATION
, NULL
,
4876 "key length defined but not ESP");
4879 tr
->encklen
= ntohs(d
->lorv
);
4882 case IPSECDOI_ATTR_KEY_ROUNDS
:
4883 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4884 case IPSECDOI_ATTR_COMP_PRIVALG
:
4892 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4894 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4895 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4905 ipsecdoi_authalg2trnsid(alg
)
4909 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4910 return IPSECDOI_AH_MD5
;
4911 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4912 return IPSECDOI_AH_SHA
;
4913 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4914 return IPSECDOI_AH_SHA256
;
4915 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4916 return IPSECDOI_AH_SHA384
;
4917 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4918 return IPSECDOI_AH_SHA512
;
4919 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4920 return IPSECDOI_AH_DES
;
4921 case IPSECDOI_ATTR_AUTH_KPDK
:
4922 return IPSECDOI_AH_MD5
; /* XXX */
4924 plog(LLV_ERROR
, LOCATION
, NULL
,
4925 "invalid authentication algorithm:%d\n", alg
);
4932 fixup_initiator_sa(match
, received
)
4933 struct isakmpsa
*match
, *received
;
4935 if (received
->gssid
!= NULL
)
4936 match
->gssid
= vdup(received
->gssid
);
4942 static int rm_idtype2doi
[] = {
4943 255, /* IDTYPE_UNDEFINED, 0 */
4944 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4945 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4946 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4947 255, /* IDTYPE_ADDRESS, 4
4948 * it expands into 4 types by another function. */
4949 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4953 * convert idtype to DOI value.
4961 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4962 return rm_idtype2doi
[idtype
];
4971 case IPSECDOI_ID_FQDN
:
4972 return(IDTYPE_FQDN
);
4973 case IPSECDOI_ID_USER_FQDN
:
4974 return(IDTYPE_USERFQDN
);
4975 case IPSECDOI_ID_KEY_ID
:
4976 return(IDTYPE_KEYID
);
4977 case IPSECDOI_ID_DER_ASN1_DN
:
4978 return(IDTYPE_ASN1DN
);
4979 case IPSECDOI_ID_IPV4_ADDR
:
4980 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4981 case IPSECDOI_ID_IPV6_ADDR
:
4982 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4983 return(IDTYPE_ADDRESS
);
4985 plog(LLV_WARNING
, LOCATION
, NULL
,
4986 "Inproper idtype:%s in this function.\n",
4987 s_ipsecdoi_ident(doi
));
4988 return(IDTYPE_ADDRESS
); /* XXX */
4993 #ifdef ENABLE_HYBRID
4995 switch_authmethod(authmethod
)
4998 switch(authmethod
) {
4999 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
5000 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
;
5002 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
5003 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
;
5005 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
5006 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
;
5008 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
5009 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
;
5011 /* Those are not implemented */
5012 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
5013 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
;
5015 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
5016 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
;
5018 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
5019 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
;