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"
86 #include "nattraversal.h"
89 static int switch_authmethod(int);
95 #ifdef HAVE_ICONV_2ND_CONST
96 #define __iconv_const const
102 int verbose_proposal_check
= 1;
104 static vchar_t
*get_ph1approval
__P((struct ph1handle
*, struct prop_pair
**));
105 static struct isakmpsa
*get_ph1approvalx
__P((struct prop_pair
*,
106 struct isakmpsa
*, struct isakmpsa
*, int));
107 static void print_ph1mismatched
__P((struct prop_pair
*, struct isakmpsa
*));
108 static int t2isakmpsa
__P((struct isakmp_pl_t
*, struct isakmpsa
*));
109 static int cmp_aproppair_i
__P((struct prop_pair
*, struct prop_pair
*));
110 static struct prop_pair
*get_ph2approval
__P((struct ph2handle
*,
111 struct prop_pair
**));
112 static struct prop_pair
*get_ph2approvalx
__P((struct ph2handle
*,
113 struct prop_pair
*));
114 static void free_proppair0
__P((struct prop_pair
*));
116 static int get_transform
117 __P((struct isakmp_pl_p
*, struct prop_pair
**, int *));
118 static u_int32_t ipsecdoi_set_ld
__P((vchar_t
*));
120 static int check_doi
__P((u_int32_t
));
121 static int check_situation
__P((u_int32_t
));
123 static int check_prot_main
__P((int));
124 static int check_prot_quick
__P((int));
125 static int (*check_protocol
[]) __P((int)) = {
126 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
127 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
130 static int check_spi_size
__P((int, int));
132 static int check_trns_isakmp
__P((int));
133 static int check_trns_ah
__P((int));
134 static int check_trns_esp
__P((int));
135 static int check_trns_ipcomp
__P((int));
136 static int (*check_transform
[]) __P((int)) = {
138 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
139 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
140 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
141 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
144 static int check_attr_isakmp
__P((struct isakmp_pl_t
*));
145 static int check_attr_ah
__P((struct isakmp_pl_t
*));
146 static int check_attr_esp
__P((struct isakmp_pl_t
*));
147 static int check_attr_ipsec
__P((int, struct isakmp_pl_t
*));
148 static int check_attr_ipcomp
__P((struct isakmp_pl_t
*));
149 static int (*check_attributes
[]) __P((struct isakmp_pl_t
*)) = {
151 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
152 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
153 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
154 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
157 static int setph1prop
__P((struct isakmpsa
*, caddr_t
));
158 static int setph1trns
__P((struct isakmpsa
*, caddr_t
));
159 static int setph1attr
__P((struct isakmpsa
*, caddr_t
));
160 static vchar_t
*setph2proposal0
__P((const struct ph2handle
*,
161 const struct saprop
*, const struct saproto
*));
163 static vchar_t
*getidval
__P((int, vchar_t
*));
166 static struct isakmpsa
*fixup_initiator_sa
__P((struct isakmpsa
*,
172 * check phase 1 SA payload.
173 * make new SA payload to be replyed not including general header.
174 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
176 * positive: the pointer to new buffer of SA payload.
177 * network byte order.
178 * NULL : error occurd.
181 ipsecdoi_checkph1proposal(sa
, iph1
)
183 struct ph1handle
*iph1
;
185 vchar_t
*newsa
; /* new SA payload approved. */
186 struct prop_pair
**pair
;
188 /* get proposal pair */
189 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
193 /* check and get one SA for use */
194 newsa
= get_ph1approval(iph1
, pair
);
201 iph1
->sa_ret
= newsa
;
207 * acceptable check for remote configuration.
208 * return a new SA payload to be reply to peer.
211 get_ph1approval(iph1
, pair
)
212 struct ph1handle
*iph1
;
213 struct prop_pair
**pair
;
216 struct isakmpsa
*sa
, tsa
;
217 struct prop_pair
*s
, *p
;
221 if (iph1
->approval
) {
222 delisakmpsa(iph1
->approval
);
223 iph1
->approval
= NULL
;
226 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
229 for (s
= pair
[i
]; s
; s
= s
->next
) {
231 sizeof(struct isakmp_pl_p
) + s
->prop
->spi_size
;
233 /* compare proposal and select one */
234 for (p
= s
; p
; p
= p
->tnext
) {
235 if ((sa
= get_ph1approvalx(p
,
236 iph1
->rmconf
->proposal
, &tsa
,
237 iph1
->rmconf
->pcheck_level
)) != NULL
)
244 * if there is no suitable proposal, racoon complains about all of
245 * mismatched items in those proposal.
247 if (verbose_proposal_check
) {
248 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
251 for (s
= pair
[i
]; s
; s
= s
->next
) {
252 prophlen
= sizeof(struct isakmp_pl_p
)
254 for (p
= s
; p
; p
= p
->tnext
) {
255 print_ph1mismatched(p
,
256 iph1
->rmconf
->proposal
);
261 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable proposal found.\n");
266 plog(LLV_DEBUG
, LOCATION
, NULL
, "an acceptable proposal found.\n");
268 /* check DH group settings */
270 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
274 plog(LLV_WARNING
, LOCATION
, NULL
,
275 "invalid DH parameter found, use default.\n");
276 oakley_dhgrp_free(sa
->dhgrp
);
280 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
288 if (sa
->gssid
!= NULL
)
289 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id in new sa '%.*s'\n",
290 (int)sa
->gssid
->l
, sa
->gssid
->v
);
291 if (iph1
-> side
== INITIATOR
) {
292 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
293 iph1
->gi_i
= vdup(iph1
->rmconf
->proposal
->gssid
);
294 if (tsa
.gssid
!= NULL
)
295 iph1
->gi_r
= vdup(tsa
.gssid
);
296 iph1
->approval
= fixup_initiator_sa(sa
, &tsa
);
298 if (tsa
.gssid
!= NULL
) {
299 iph1
->gi_r
= vdup(tsa
.gssid
);
300 iph1
->gi_i
= gssapi_get_id(iph1
);
301 if (sa
->gssid
== NULL
&& iph1
->gi_i
!= NULL
)
302 sa
->gssid
= vdup(iph1
->gi_i
);
306 if (iph1
->gi_i
!= NULL
)
307 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIi is %.*s\n",
308 (int)iph1
->gi_i
->l
, iph1
->gi_i
->v
);
309 if (iph1
->gi_r
!= NULL
)
310 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIr is %.*s\n",
311 (int)iph1
->gi_r
->l
, iph1
->gi_r
->v
);
316 plog(LLV_DEBUG
, LOCATION
, NULL
, "agreed on %s auth.\n",
317 s_oakley_attr_method(iph1
->approval
->authmethod
));
320 newsa
= get_sabyproppair(p
, iph1
);
322 delisakmpsa(iph1
->approval
);
323 iph1
->approval
= NULL
;
330 * compare peer's single proposal and all of my proposal.
331 * and select one if suiatable.
332 * p : one of peer's proposal.
333 * proposal: my proposals.
335 static struct isakmpsa
*
336 get_ph1approvalx(p
, proposal
, sap
, check_level
)
338 struct isakmpsa
*proposal
, *sap
;
341 struct isakmp_pl_p
*prop
= p
->prop
;
342 struct isakmp_pl_t
*trns
= p
->trns
;
343 struct isakmpsa sa
, *s
, *tsap
;
347 plog(LLV_DEBUG
, LOCATION
, NULL
,
348 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
349 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
350 prop
->spi_size
, prop
->num_t
);
352 plog(LLV_DEBUG
, LOCATION
, NULL
,
353 "trns#=%d, trns-id=%s\n",
355 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
357 tsap
= sap
!= NULL
? sap
: &sa
;
359 memset(tsap
, 0, sizeof(*tsap
));
360 if (t2isakmpsa(trns
, tsap
) < 0)
362 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
364 authmethod
= switch_authmethod(s
->authmethod
);
365 tsap_authmethod
= switch_authmethod(tsap
->authmethod
);
367 authmethod
= s
->authmethod
;
368 tsap_authmethod
= tsap
->authmethod
;
370 plog(LLV_DEBUG
, LOCATION
, NULL
, "Compared: DB:Peer\n");
371 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifetime = %ld:%ld)\n",
372 (long)s
->lifetime
, (long)tsap
->lifetime
);
373 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifebyte = %zu:%zu)\n",
374 s
->lifebyte
, tsap
->lifebyte
);
375 plog(LLV_DEBUG
, LOCATION
, NULL
, "enctype = %s:%s\n",
376 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
378 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
380 plog(LLV_DEBUG
, LOCATION
, NULL
, "(encklen = %d:%d)\n",
381 s
->encklen
, tsap
->encklen
);
382 plog(LLV_DEBUG
, LOCATION
, NULL
, "hashtype = %s:%s\n",
383 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
385 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
387 plog(LLV_DEBUG
, LOCATION
, NULL
, "authmethod = %s:%s\n",
388 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
390 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
392 plog(LLV_DEBUG
, LOCATION
, NULL
, "dh_group = %s:%s\n",
393 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
395 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
398 /* XXX to be considered ? */
399 if (tsap
->lifebyte
> s
->lifebyte
) ;
402 * if responder side and peer's key length in proposal
403 * is bigger than mine, it might be accepted.
405 if(tsap
->enctype
== s
->enctype
&&
406 (tsap
->authmethod
== authmethod
|| tsap_authmethod
== authmethod
) &&
407 tsap
->hashtype
== s
->hashtype
&&
408 tsap
->dh_group
== s
->dh_group
&&
409 tsap
->encklen
== s
->encklen
) {
410 switch(check_level
) {
411 case PROP_CHECK_OBEY
:
415 case PROP_CHECK_STRICT
:
416 if ((tsap
->lifetime
> s
->lifetime
) ||
417 (tsap
->lifebyte
> s
->lifebyte
))
422 case PROP_CHECK_CLAIM
:
423 if (tsap
->lifetime
< s
->lifetime
)
424 s
->lifetime
= tsap
->lifetime
;
425 if (tsap
->lifebyte
< s
->lifebyte
)
426 s
->lifebyte
= tsap
->lifebyte
;
430 case PROP_CHECK_EXACT
:
431 if ((tsap
->lifetime
!= s
->lifetime
) ||
432 (tsap
->lifebyte
!= s
->lifebyte
))
438 plog(LLV_ERROR
, LOCATION
, NULL
,
439 "Unexpected proposal_check value\n");
447 if (tsap
->dhgrp
!= NULL
){
448 oakley_dhgrp_free(tsap
->dhgrp
);
452 if ((s
= dupisakmpsa(s
)) != NULL
) {
453 switch(check_level
) {
454 case PROP_CHECK_OBEY
:
455 s
->lifetime
= tsap
->lifetime
;
456 s
->lifebyte
= tsap
->lifebyte
;
459 case PROP_CHECK_STRICT
:
460 s
->lifetime
= tsap
->lifetime
;
461 s
->lifebyte
= tsap
->lifebyte
;
464 case PROP_CHECK_CLAIM
:
465 if (tsap
->lifetime
< s
->lifetime
)
466 s
->lifetime
= tsap
->lifetime
;
467 if (tsap
->lifebyte
< s
->lifebyte
)
468 s
->lifebyte
= tsap
->lifebyte
;
474 // hack to get around cisco rekeys
475 if (tsap
->authmethod
!= authmethod
&& tsap_authmethod
== authmethod
) {
476 s
->authmethod
= tsap
->authmethod
;
483 * print all of items in peer's proposal which are mismatched to my proposal.
484 * p : one of peer's proposal.
485 * proposal: my proposals.
488 print_ph1mismatched(p
, proposal
)
490 struct isakmpsa
*proposal
;
492 struct isakmpsa sa
, *s
;
494 memset(&sa
, 0, sizeof(sa
));
495 if (t2isakmpsa(p
->trns
, &sa
) < 0)
497 for (s
= proposal
; s
; s
= s
->next
) {
498 if (sa
.enctype
!= s
->enctype
) {
499 plog(LLV_ERROR
, LOCATION
, NULL
,
501 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
503 s
->prop_no
, s
->trns_no
,
504 p
->prop
->p_no
, p
->trns
->t_no
,
505 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
507 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
510 if (sa
.authmethod
!= s
->authmethod
) {
511 plog(LLV_ERROR
, LOCATION
, NULL
,
512 "rejected authmethod: "
513 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
515 s
->prop_no
, s
->trns_no
,
516 p
->prop
->p_no
, p
->trns
->t_no
,
517 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
519 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
522 if (sa
.hashtype
!= s
->hashtype
) {
523 plog(LLV_ERROR
, LOCATION
, NULL
,
524 "rejected hashtype: "
525 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
527 s
->prop_no
, s
->trns_no
,
528 p
->prop
->p_no
, p
->trns
->t_no
,
529 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
531 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
534 if (sa
.dh_group
!= s
->dh_group
) {
535 plog(LLV_ERROR
, LOCATION
, NULL
,
536 "rejected dh_group: "
537 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
539 s
->prop_no
, s
->trns_no
,
540 p
->prop
->p_no
, p
->trns
->t_no
,
541 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
543 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
548 if (sa
.dhgrp
!= NULL
){
549 oakley_dhgrp_free(sa
.dhgrp
);
555 * get ISAKMP data attributes
559 struct isakmp_pl_t
*trns
;
562 struct isakmp_data
*d
, *prev
;
571 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
572 prev
= (struct isakmp_data
*)NULL
;
573 d
= (struct isakmp_data
*)(trns
+ 1);
576 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
577 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
579 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
585 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
586 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
588 plog(LLV_DEBUG
, LOCATION
, NULL
,
589 "type=%s, flag=0x%04x, lorv=%s\n",
590 s_oakley_attr(type
), flag
,
591 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
593 /* get variable-sized item */
595 case OAKLEY_ATTR_GRP_PI
:
596 case OAKLEY_ATTR_GRP_GEN_ONE
:
597 case OAKLEY_ATTR_GRP_GEN_TWO
:
598 case OAKLEY_ATTR_GRP_CURVE_A
:
599 case OAKLEY_ATTR_GRP_CURVE_B
:
600 case OAKLEY_ATTR_SA_LD
:
601 case OAKLEY_ATTR_GRP_ORDER
:
604 p
= (u_char
*)&d
->lorv
;
606 len
= ntohs(d
->lorv
);
607 p
= (u_char
*)(d
+ 1);
612 memcpy(val
->v
, p
, len
);
620 case OAKLEY_ATTR_ENC_ALG
:
621 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
624 case OAKLEY_ATTR_HASH_ALG
:
625 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
628 case OAKLEY_ATTR_AUTH_METHOD
:
629 sa
->authmethod
= ntohs(d
->lorv
);
632 case OAKLEY_ATTR_GRP_DESC
:
633 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
636 case OAKLEY_ATTR_GRP_TYPE
:
638 int type
= (int)ntohs(d
->lorv
);
639 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
640 sa
->dhgrp
->type
= type
;
645 case OAKLEY_ATTR_GRP_PI
:
646 sa
->dhgrp
->prime
= val
;
649 case OAKLEY_ATTR_GRP_GEN_ONE
:
652 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
654 int len
= ntohs(d
->lorv
);
658 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
659 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
663 case OAKLEY_ATTR_GRP_GEN_TWO
:
666 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
668 int len
= ntohs(d
->lorv
);
672 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
673 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
677 case OAKLEY_ATTR_GRP_CURVE_A
:
678 sa
->dhgrp
->curve_a
= val
;
681 case OAKLEY_ATTR_GRP_CURVE_B
:
682 sa
->dhgrp
->curve_b
= val
;
685 case OAKLEY_ATTR_SA_LD_TYPE
:
687 int type
= (int)ntohs(d
->lorv
);
689 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
690 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
694 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
699 case OAKLEY_ATTR_SA_LD
:
701 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
702 OAKLEY_ATTR_SA_LD_TYPE
) {
703 plog(LLV_ERROR
, LOCATION
, NULL
,
704 "life duration must follow ltype\n");
709 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
710 sa
->lifetime
= ipsecdoi_set_ld(val
);
712 if (sa
->lifetime
== 0) {
713 plog(LLV_ERROR
, LOCATION
, NULL
,
714 "invalid life duration.\n");
718 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
719 sa
->lifebyte
= ipsecdoi_set_ld(val
);
721 if (sa
->lifebyte
== 0) {
722 plog(LLV_ERROR
, LOCATION
, NULL
,
723 "invalid life duration.\n");
729 plog(LLV_ERROR
, LOCATION
, NULL
,
730 "invalid life type: %d\n", life_t
);
735 case OAKLEY_ATTR_KEY_LEN
:
737 int len
= ntohs(d
->lorv
);
739 plog(LLV_ERROR
, LOCATION
, NULL
,
740 "keylen %d: not multiple of 8\n",
744 sa
->encklen
= (u_int16_t
)len
;
748 case OAKLEY_ATTR_PRF
:
749 case OAKLEY_ATTR_FIELD_SIZE
:
753 case OAKLEY_ATTR_GRP_ORDER
:
754 sa
->dhgrp
->order
= val
;
757 case OAKLEY_ATTR_GSS_ID
:
760 iconv_t cd
= (iconv_t
) -1;
761 size_t srcleft
, dstleft
, rv
;
762 __iconv_const
char *src
;
764 int len
= ntohs(d
->lorv
);
767 * Older verions of racoon just placed the
768 * ISO-Latin-1 string on the wire directly.
769 * Check to see if we are configured to be
770 * compatible with this behavior.
772 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
773 if ((sa
->gssid
= vmalloc(len
)) == NULL
) {
774 plog(LLV_ERROR
, LOCATION
, NULL
,
775 "failed to allocate memory\n");
778 memcpy(sa
->gssid
->v
, d
+ 1, len
);
779 plog(LLV_DEBUG
, LOCATION
, NULL
,
780 "received old-style gss "
781 "id '%.*s' (len %zu)\n",
782 (int)sa
->gssid
->l
, sa
->gssid
->v
,
789 * For Windows 2000 compatibility, we expect
790 * the GSS ID attribute on the wire to be
791 * encoded in UTF-16LE. Internally, we work
792 * in ISO-Latin-1. Therefore, we should need
793 * 1/2 the specified length, which should always
794 * be a multiple of 2 octets.
796 cd
= iconv_open("latin1", "utf-16le");
797 if (cd
== (iconv_t
) -1) {
798 plog(LLV_ERROR
, LOCATION
, NULL
,
799 "unable to initialize utf-16le -> latin1 "
800 "conversion descriptor: %s\n",
805 if ((sa
->gssid
= vmalloc(len
/ 2)) == NULL
) {
806 plog(LLV_ERROR
, LOCATION
, NULL
,
807 "failed to allocate memory\n");
811 src
= (__iconv_const
char *)(d
+ 1);
817 rv
= iconv(cd
, (__iconv_const
char **)&src
, &srcleft
,
821 plog(LLV_ERROR
, LOCATION
, NULL
,
822 "unable to convert GSS ID from "
823 "utf-16le -> latin1: %s\n",
826 plog(LLV_ERROR
, LOCATION
, NULL
,
827 "%zd character%s in GSS ID cannot "
828 "be represented in latin1\n",
829 rv
, rv
== 1 ? "" : "s");
834 /* XXX dstleft should always be 0; assert it? */
835 sa
->gssid
->l
= (len
/ 2) - dstleft
;
837 plog(LLV_DEBUG
, LOCATION
, NULL
,
838 "received gss id '%.*s' (len %zu)\n",
839 (int)sa
->gssid
->l
, sa
->gssid
->v
, sa
->gssid
->l
);
843 if (cd
!= (iconv_t
)-1)
844 (void)iconv_close(cd
);
846 if ((error
!= 0) && (sa
->gssid
!= NULL
)) {
852 #endif /* HAVE_GSSAPI */
861 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
863 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
864 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
868 /* key length must not be specified on some algorithms */
870 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
871 #ifdef HAVE_OPENSSL_IDEA_H
872 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_IDEA
874 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
875 plog(LLV_ERROR
, LOCATION
, NULL
,
876 "keylen must not be specified "
877 "for encryption algorithm %d\n",
890 * check phase 2 SA payload and select single proposal.
891 * make new SA payload to be replyed not including general header.
892 * This function is called by responder only.
898 ipsecdoi_selectph2proposal(iph2
)
899 struct ph2handle
*iph2
;
901 struct prop_pair
**pair
;
902 struct prop_pair
*ret
;
904 /* get proposal pair */
905 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
909 /* check and select a proposal. */
910 ret
= get_ph2approval(iph2
, pair
);
915 /* make a SA to be replayed. */
916 /* SPI must be updated later. */
917 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
919 if (iph2
->sa_ret
== NULL
)
926 * check phase 2 SA payload returned from responder.
927 * This function is called by initiator only.
933 ipsecdoi_checkph2proposal(iph2
)
934 struct ph2handle
*iph2
;
936 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
940 vchar_t
*sa_ret
= NULL
;
942 /* get proposal pair of SA sent. */
943 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
945 plog(LLV_ERROR
, LOCATION
, NULL
,
946 "failed to get prop pair.\n");
950 /* XXX should check the number of transform */
952 /* get proposal pair of SA replayed */
953 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
955 plog(LLV_ERROR
, LOCATION
, NULL
,
956 "failed to get prop pair.\n");
960 /* check proposal is only one ? */
963 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
970 plog(LLV_ERROR
, LOCATION
, NULL
,
971 "no proposal received.\n");
975 plog(LLV_ERROR
, LOCATION
, NULL
,
976 "some proposals received.\n");
980 if (spair
[n
] == NULL
) {
981 plog(LLV_WARNING
, LOCATION
, NULL
,
982 "invalid proposal number:%d received.\n", i
);
986 if (rpair
[n
]->tnext
!= NULL
) {
987 plog(LLV_ERROR
, LOCATION
, NULL
,
988 "multi transforms replyed.\n");
992 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
993 plog(LLV_ERROR
, LOCATION
, NULL
,
994 "proposal mismathed.\n");
999 * check and select a proposal.
1000 * ensure that there is no modification of the proposal by
1003 p
= get_ph2approval(iph2
, rpair
);
1007 /* make a SA to be replayed. */
1008 sa_ret
= iph2
->sa_ret
;
1009 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
1011 if (iph2
->sa_ret
== NULL
)
1018 free_proppair(rpair
);
1020 free_proppair(spair
);
1028 * compare two prop_pair which is assumed to have same proposal number.
1029 * the case of bundle or single SA, NOT multi transforms.
1030 * a: a proposal that is multi protocols and single transform, usually replyed.
1031 * b: a proposal that is multi protocols and multi transform, usually sent.
1032 * NOTE: this function is for initiator.
1036 * XXX cannot understand the comment!
1039 cmp_aproppair_i(a
, b
)
1040 struct prop_pair
*a
, *b
;
1042 struct prop_pair
*p
, *q
, *r
;
1045 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
1046 for (r
= q
; r
; r
= r
->tnext
) {
1048 if (p
->trns
->t_no
== r
->trns
->t_no
)
1052 /* no suitable transform found */
1053 plog(LLV_ERROR
, LOCATION
, NULL
,
1054 "no suitable transform found.\n");
1059 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
1060 plog(LLV_WARNING
, LOCATION
, NULL
,
1061 "proposal #%d mismatched, "
1063 r
->prop
->p_no
, p
->prop
->p_no
);
1067 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
1068 plog(LLV_ERROR
, LOCATION
, NULL
,
1069 "proto_id mismathed: my:%d peer:%d\n",
1070 r
->prop
->proto_id
, p
->prop
->proto_id
);
1074 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
1075 plog(LLV_ERROR
, LOCATION
, NULL
,
1076 "invalid spi size: %d.\n",
1081 /* check #of transforms */
1082 if (p
->prop
->num_t
!= 1) {
1083 plog(LLV_WARNING
, LOCATION
, NULL
,
1084 "#of transform is %d, "
1085 "but expected 1.\n", p
->prop
->num_t
);
1089 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
1090 plog(LLV_WARNING
, LOCATION
, NULL
,
1091 "transform number has been modified.\n");
1094 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
1095 plog(LLV_WARNING
, LOCATION
, NULL
,
1096 "reserved field should be zero.\n");
1100 /* compare attribute */
1101 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
1102 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
1103 plog(LLV_WARNING
, LOCATION
, NULL
,
1104 "attribute has been modified.\n");
1108 if ((p
&& !q
) || (!p
&& q
)) {
1109 /* # of protocols mismatched */
1110 plog(LLV_ERROR
, LOCATION
, NULL
,
1111 "#of protocols mismatched.\n");
1119 * acceptable check for policy configuration.
1120 * return a new SA payload to be reply to peer.
1122 static struct prop_pair
*
1123 get_ph2approval(iph2
, pair
)
1124 struct ph2handle
*iph2
;
1125 struct prop_pair
**pair
;
1127 struct prop_pair
*ret
;
1130 iph2
->approval
= NULL
;
1132 plog(LLV_DEBUG
, LOCATION
, NULL
,
1133 "begin compare proposals.\n");
1135 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1136 if (pair
[i
] == NULL
)
1138 plog(LLV_DEBUG
, LOCATION
, NULL
,
1139 "pair[%d]: %p\n", i
, pair
[i
]);
1140 print_proppair(LLV_DEBUG
, pair
[i
]);;
1142 /* compare proposal and select one */
1143 ret
= get_ph2approvalx(iph2
, pair
[i
]);
1150 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable policy found.\n");
1156 * compare my proposal and peers just one proposal.
1159 static struct prop_pair
*
1160 get_ph2approvalx(iph2
, pp
)
1161 struct ph2handle
*iph2
;
1162 struct prop_pair
*pp
;
1164 struct prop_pair
*ret
= NULL
;
1165 struct saprop
*pr0
, *pr
= NULL
;
1166 struct saprop
*q1
, *q2
;
1168 pr0
= aproppair2saprop(pp
);
1172 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1173 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1174 plog(LLV_DEBUG
, LOCATION
, NULL
,
1175 "peer's single bundle:\n");
1176 printsaprop0(LLV_DEBUG
, q1
);
1177 plog(LLV_DEBUG
, LOCATION
, NULL
,
1178 "my single bundle:\n");
1179 printsaprop0(LLV_DEBUG
, q2
);
1181 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1185 plog(LLV_ERROR
, LOCATION
, NULL
,
1189 /* no proposal matching */
1196 plog(LLV_DEBUG
, LOCATION
, NULL
, "matched\n");
1197 iph2
->approval
= pr
;
1201 struct prop_pair
*p
, *x
;
1202 struct prop_pair
*n
= NULL
;
1206 for (p
= pp
; p
; p
= p
->next
) {
1208 * find a proposal with matching proto_id.
1209 * we have analyzed validity already, in cmpsaprop_alloc().
1211 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1212 if (sp
->proto_id
== p
->prop
->proto_id
)
1220 for (x
= p
; x
; x
= x
->tnext
)
1221 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1226 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1228 plog(LLV_ERROR
, LOCATION
, NULL
,
1229 "failed to get buffer.\n");
1236 /* need to preserve the order */
1237 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1239 if (x
&& x
->prop
== n
->prop
) {
1240 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1251 /* #of transforms should be updated ? */
1260 struct prop_pair
**pair
;
1264 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1265 free_proppair0(pair
[i
]);
1272 free_proppair0(pair
)
1273 struct prop_pair
*pair
;
1275 struct prop_pair
*p
, *q
, *r
, *s
;
1291 * get proposal pairs from SA payload.
1292 * tiny check for proposal payload.
1295 get_proppair(sa
, mode
)
1299 struct prop_pair
**pair
= NULL
;
1300 int num_p
= 0; /* number of proposal for use */
1304 struct ipsecdoi_sa_b
*sab
= (struct ipsecdoi_sa_b
*)sa
->v
;
1306 plog(LLV_DEBUG
, LOCATION
, NULL
, "total SA len=%zu\n", sa
->l
);
1307 plogdump(LLV_DEBUG
, sa
->v
, sa
->l
);
1309 /* check SA payload size */
1310 if (sa
->l
< sizeof(*sab
)) {
1311 plog(LLV_ERROR
, LOCATION
, NULL
,
1312 "Invalid SA length = %zu.\n", sa
->l
);
1317 if (check_doi(ntohl(sab
->doi
)) < 0)
1320 /* check SITUATION */
1321 if (check_situation(ntohl(sab
->sit
)) < 0)
1324 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1326 plog(LLV_ERROR
, LOCATION
, NULL
,
1327 "failed to get buffer.\n");
1330 memset(pair
, 0, sizeof(pair
));
1332 bp
= (caddr_t
)(sab
+ 1);
1333 tlen
= sa
->l
- sizeof(*sab
);
1336 struct isakmp_pl_p
*prop
;
1338 vchar_t
*pbuf
= NULL
;
1339 struct isakmp_parse_t
*pa
;
1341 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1345 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1346 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1348 /* check the value of next payload */
1349 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1350 plog(LLV_ERROR
, LOCATION
, NULL
,
1351 "Invalid payload type=%u\n", pa
->type
);
1356 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1359 plog(LLV_DEBUG
, LOCATION
, NULL
,
1360 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1363 plog(LLV_ERROR
, LOCATION
, NULL
,
1364 "invalid proposal with length %d\n", proplen
);
1369 /* check Protocol ID */
1370 if (!check_protocol
[mode
]) {
1371 plog(LLV_ERROR
, LOCATION
, NULL
,
1372 "unsupported mode %d\n", mode
);
1376 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1379 /* check SPI length when IKE. */
1380 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1384 if (get_transform(prop
, pair
, &num_p
) < 0) {
1395 struct prop_pair
*p
, *q
;
1397 /* check for proposals with no transforms */
1398 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1402 plog(LLV_DEBUG
, LOCATION
, NULL
, "pair %d:\n", i
);
1403 print_proppair(LLV_DEBUG
, pair
[i
]);
1405 notrans
= nprop
= 0;
1406 for (p
= pair
[i
]; p
; p
= p
->next
) {
1407 if (p
->trns
== NULL
) {
1411 for (q
= p
; q
; q
= q
->tnext
)
1417 * XXX at this moment, we cannot accept proposal group
1418 * with multiple proposals. this should be fixed.
1420 if (pair
[i
]->next
) {
1421 plog(LLV_WARNING
, LOCATION
, NULL
,
1422 "proposal #%u ignored "
1423 "(multiple proposal not supported)\n",
1424 pair
[i
]->prop
->p_no
);
1430 for (p
= pair
[i
]; p
; p
= q
) {
1437 plog(LLV_DEBUG
, LOCATION
, NULL
,
1438 "proposal #%u: %d transform\n",
1439 pair
[i
]->prop
->p_no
, nprop
);
1444 /* bark if no proposal is found. */
1446 plog(LLV_ERROR
, LOCATION
, NULL
,
1447 "no Proposal found.\n");
1459 * check transform payload.
1461 * positive: return the pointer to the payload of valid transform.
1462 * 0 : No valid transform found.
1465 get_transform(prop
, pair
, num_p
)
1466 struct isakmp_pl_p
*prop
;
1467 struct prop_pair
**pair
;
1470 int tlen
; /* total length of all transform in a proposal */
1472 struct isakmp_pl_t
*trns
;
1474 vchar_t
*pbuf
= NULL
;
1475 struct isakmp_parse_t
*pa
;
1476 struct prop_pair
*p
= NULL
, *q
;
1479 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1480 tlen
= ntohs(prop
->h
.len
)
1481 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1482 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1486 /* check and get transform for use */
1488 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1489 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1494 /* check the value of next payload */
1495 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1496 plog(LLV_ERROR
, LOCATION
, NULL
,
1497 "Invalid payload type=%u\n", pa
->type
);
1501 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1504 plog(LLV_DEBUG
, LOCATION
, NULL
,
1505 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1507 /* check transform ID */
1508 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1509 plog(LLV_WARNING
, LOCATION
, NULL
,
1510 "unsupported proto_id %u\n",
1514 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1515 plog(LLV_WARNING
, LOCATION
, NULL
,
1516 "unsupported proto_id %u\n",
1521 if (!check_transform
[prop
->proto_id
]
1522 || !check_attributes
[prop
->proto_id
]) {
1523 plog(LLV_WARNING
, LOCATION
, NULL
,
1524 "unsupported proto_id %u\n",
1528 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1531 /* check data attributes */
1532 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1535 p
= racoon_calloc(1, sizeof(*p
));
1537 plog(LLV_ERROR
, LOCATION
, NULL
,
1538 "failed to get buffer.\n");
1545 /* need to preserve the order */
1546 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1548 if (q
&& q
->prop
== p
->prop
) {
1549 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1556 pair
[prop
->p_no
] = p
;
1568 * make a new SA payload from prop_pair.
1569 * NOTE: this function make spi value clear.
1572 get_sabyproppair(pair
, iph1
)
1573 struct prop_pair
*pair
;
1574 struct ph1handle
*iph1
;
1578 u_int8_t
*np_p
= NULL
;
1579 struct prop_pair
*p
;
1580 int prophlen
, trnslen
;
1583 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1584 for (p
= pair
; p
; p
= p
->next
) {
1585 newtlen
+= sizeof(struct isakmp_pl_p
);
1586 newtlen
+= p
->prop
->spi_size
;
1587 newtlen
+= ntohs(p
->trns
->h
.len
);
1590 newsa
= vmalloc(newtlen
);
1591 if (newsa
== NULL
) {
1592 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1597 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1599 /* update some of values in SA header */
1600 ((struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1601 ((struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1602 bp
+= sizeof(struct ipsecdoi_sa_b
);
1604 /* create proposal payloads */
1605 for (p
= pair
; p
; p
= p
->next
) {
1606 prophlen
= sizeof(struct isakmp_pl_p
)
1607 + p
->prop
->spi_size
;
1608 trnslen
= ntohs(p
->trns
->h
.len
);
1611 *np_p
= ISAKMP_NPTYPE_P
;
1613 /* create proposal */
1615 memcpy(bp
, p
->prop
, prophlen
);
1616 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1617 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1618 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1619 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1620 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1623 /* create transform */
1624 memcpy(bp
, p
->trns
, trnslen
);
1625 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1626 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1634 * update responder's spi
1637 ipsecdoi_updatespi(iph2
)
1638 struct ph2handle
*iph2
;
1640 struct prop_pair
**pair
, *p
;
1647 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1650 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1654 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1655 /* multiple transform must be filtered by selectph2proposal.*/
1659 pp
= iph2
->approval
;
1661 /* create proposal payloads */
1662 for (p
= pair
[i
]; p
; p
= p
->next
) {
1664 * find a proposal/transform with matching proto_id/t_id.
1665 * we have analyzed validity already, in cmpsaprop_alloc().
1667 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1668 if (p
->prop
->proto_id
== pr
->proto_id
&&
1669 p
->trns
->t_id
== pr
->head
->trns_id
) {
1677 * XXX SPI bits are left-filled, for use with IPComp.
1678 * we should be switching to variable-length spi field...
1680 spi
= (u_int8_t
*)&pr
->spi
;
1681 spi
+= sizeof(pr
->spi
);
1683 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1688 free_proppair(pair
);
1693 * make a new SA payload from prop_pair.
1696 get_sabysaprop(pp0
, sa0
)
1700 struct prop_pair
**pair
= NULL
;
1701 vchar_t
*newsa
= NULL
;
1703 u_int8_t
*np_p
= NULL
;
1704 struct prop_pair
*p
= NULL
;
1708 int prophlen
, trnslen
;
1712 /* get proposal pair */
1713 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1717 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1718 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1720 if (pair
[pp
->prop_no
] == NULL
)
1723 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1724 newtlen
+= (sizeof(struct isakmp_pl_p
)
1727 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1728 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1729 if (tr
->trns_no
== p
->trns
->t_no
)
1735 newtlen
+= ntohs(p
->trns
->h
.len
);
1740 newsa
= vmalloc(newtlen
);
1741 if (newsa
== NULL
) {
1742 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1747 /* some of values of SA must be updated in the out of this function */
1748 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1749 bp
+= sizeof(struct ipsecdoi_sa_b
);
1751 /* create proposal payloads */
1752 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1754 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1755 prophlen
= sizeof(struct isakmp_pl_p
)
1756 + p
->prop
->spi_size
;
1758 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1759 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1760 if (tr
->trns_no
== p
->trns
->t_no
)
1766 trnslen
= ntohs(p
->trns
->h
.len
);
1769 *np_p
= ISAKMP_NPTYPE_P
;
1771 /* create proposal */
1773 memcpy(bp
, p
->prop
, prophlen
);
1774 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1775 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1776 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1777 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1780 /* create transform */
1781 memcpy(bp
, p
->trns
, trnslen
);
1782 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1783 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1795 if (newsa
!= NULL
) {
1805 * If some error happens then return 0. Although 0 means that lifetime is zero,
1806 * such a value should not be accepted.
1807 * Also 0 of lifebyte should not be included in a packet although 0 means not
1811 ipsecdoi_set_ld(buf
)
1821 ld
= ntohs(*(u_int16_t
*)buf
->v
);
1824 ld
= ntohl(*(u_int32_t
*)buf
->v
);
1827 plog(LLV_ERROR
, LOCATION
, NULL
,
1828 "length %zu of life duration "
1829 "isn't supported.\n", buf
->l
);
1848 plog(LLV_ERROR
, LOCATION
, NULL
,
1849 "invalid value of DOI 0x%08x.\n", doi
);
1859 check_situation(sit
)
1863 case IPSECDOI_SIT_IDENTITY_ONLY
:
1866 case IPSECDOI_SIT_SECRECY
:
1867 case IPSECDOI_SIT_INTEGRITY
:
1868 plog(LLV_ERROR
, LOCATION
, NULL
,
1869 "situation 0x%08x unsupported yet.\n", sit
);
1873 plog(LLV_ERROR
, LOCATION
, NULL
,
1874 "invalid situation 0x%08x.\n", sit
);
1881 * check protocol id in main mode
1884 check_prot_main(proto_id
)
1888 case IPSECDOI_PROTO_ISAKMP
:
1892 plog(LLV_ERROR
, LOCATION
, NULL
,
1893 "Illegal protocol id=%u.\n", proto_id
);
1900 * check protocol id in quick mode
1903 check_prot_quick(proto_id
)
1907 case IPSECDOI_PROTO_IPSEC_AH
:
1908 case IPSECDOI_PROTO_IPSEC_ESP
:
1911 case IPSECDOI_PROTO_IPCOMP
:
1915 plog(LLV_ERROR
, LOCATION
, NULL
,
1916 "invalid protocol id %d.\n", proto_id
);
1923 check_spi_size(proto_id
, size
)
1927 case IPSECDOI_PROTO_ISAKMP
:
1930 plog(LLV_WARNING
, LOCATION
, NULL
,
1931 "SPI size isn't zero, but IKE proposal.\n");
1935 case IPSECDOI_PROTO_IPSEC_AH
:
1936 case IPSECDOI_PROTO_IPSEC_ESP
:
1938 plog(LLV_ERROR
, LOCATION
, NULL
,
1939 "invalid SPI size=%d for IPSEC proposal.\n",
1945 case IPSECDOI_PROTO_IPCOMP
:
1946 if (size
!= 2 && size
!= 4) {
1947 plog(LLV_ERROR
, LOCATION
, NULL
,
1948 "invalid SPI size=%d for IPCOMP proposal.\n",
1962 * check transform ID in ISAKMP.
1965 check_trns_isakmp(t_id
)
1969 case IPSECDOI_KEY_IKE
:
1972 plog(LLV_ERROR
, LOCATION
, NULL
,
1973 "invalid transform-id=%u in proto_id=%u.\n",
1974 t_id
, IPSECDOI_KEY_IKE
);
1981 * check transform ID in AH.
1988 case IPSECDOI_AH_MD5
:
1989 case IPSECDOI_AH_SHA
:
1990 case IPSECDOI_AH_SHA256
:
1991 case IPSECDOI_AH_SHA384
:
1992 case IPSECDOI_AH_SHA512
:
1994 case IPSECDOI_AH_DES
:
1995 plog(LLV_ERROR
, LOCATION
, NULL
,
1996 "not support transform-id=%u in AH.\n", t_id
);
1999 plog(LLV_ERROR
, LOCATION
, NULL
,
2000 "invalid transform-id=%u in AH.\n", t_id
);
2007 * check transform ID in ESP.
2010 check_trns_esp(t_id
)
2014 case IPSECDOI_ESP_DES
:
2015 case IPSECDOI_ESP_3DES
:
2016 case IPSECDOI_ESP_NULL
:
2017 case IPSECDOI_ESP_RC5
:
2018 case IPSECDOI_ESP_CAST
:
2019 case IPSECDOI_ESP_BLOWFISH
:
2020 case IPSECDOI_ESP_AES
:
2021 case IPSECDOI_ESP_TWOFISH
:
2023 case IPSECDOI_ESP_DES_IV32
:
2024 case IPSECDOI_ESP_DES_IV64
:
2025 case IPSECDOI_ESP_IDEA
:
2026 case IPSECDOI_ESP_3IDEA
:
2027 case IPSECDOI_ESP_RC4
:
2028 plog(LLV_ERROR
, LOCATION
, NULL
,
2029 "not support transform-id=%u in ESP.\n", t_id
);
2032 plog(LLV_ERROR
, LOCATION
, NULL
,
2033 "invalid transform-id=%u in ESP.\n", t_id
);
2040 * check transform ID in IPCOMP.
2043 check_trns_ipcomp(t_id
)
2047 case IPSECDOI_IPCOMP_OUI
:
2048 case IPSECDOI_IPCOMP_DEFLATE
:
2049 case IPSECDOI_IPCOMP_LZS
:
2052 plog(LLV_ERROR
, LOCATION
, NULL
,
2053 "invalid transform-id=%u in IPCOMP.\n", t_id
);
2060 * check data attributes in IKE.
2063 check_attr_isakmp(trns
)
2064 struct isakmp_pl_t
*trns
;
2066 struct isakmp_data
*d
;
2071 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2072 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2075 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2076 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2077 lorv
= ntohs(d
->lorv
);
2079 plog(LLV_DEBUG
, LOCATION
, NULL
,
2080 "type=%s, flag=0x%04x, lorv=%s\n",
2081 s_oakley_attr(type
), flag
,
2082 s_oakley_attr_v(type
, lorv
));
2085 * some of the attributes must be encoded in TV.
2086 * see RFC2409 Appendix A "Attribute Classes".
2089 case OAKLEY_ATTR_ENC_ALG
:
2090 case OAKLEY_ATTR_HASH_ALG
:
2091 case OAKLEY_ATTR_AUTH_METHOD
:
2092 case OAKLEY_ATTR_GRP_DESC
:
2093 case OAKLEY_ATTR_GRP_TYPE
:
2094 case OAKLEY_ATTR_SA_LD_TYPE
:
2095 case OAKLEY_ATTR_PRF
:
2096 case OAKLEY_ATTR_KEY_LEN
:
2097 case OAKLEY_ATTR_FIELD_SIZE
:
2098 if (!flag
) { /* TLV*/
2099 plog(LLV_ERROR
, LOCATION
, NULL
,
2100 "oakley attribute %d must be TV.\n",
2107 /* sanity check for TLV. length must be specified. */
2108 if (!flag
&& lorv
== 0) { /*TLV*/
2109 plog(LLV_ERROR
, LOCATION
, NULL
,
2110 "invalid length %d for TLV attribute %d.\n",
2116 case OAKLEY_ATTR_ENC_ALG
:
2117 if (!alg_oakley_encdef_ok(lorv
)) {
2118 plog(LLV_ERROR
, LOCATION
, NULL
,
2119 "invalied encryption algorithm=%d.\n",
2125 case OAKLEY_ATTR_HASH_ALG
:
2126 if (!alg_oakley_hashdef_ok(lorv
)) {
2127 plog(LLV_ERROR
, LOCATION
, NULL
,
2128 "invalied hash algorithm=%d.\n",
2134 case OAKLEY_ATTR_AUTH_METHOD
:
2136 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2137 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2138 #ifdef ENABLE_HYBRID
2139 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2140 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
:
2141 #if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2142 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
:
2144 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
2146 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
2148 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2149 #ifdef ENABLE_HYBRID
2150 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2151 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
2152 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2153 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2154 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
:
2155 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
2156 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
:
2157 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
2158 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
:
2159 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
2161 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2162 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2163 plog(LLV_ERROR
, LOCATION
, NULL
,
2164 "auth method %s isn't supported.\n",
2165 s_oakley_attr_method(lorv
));
2168 plog(LLV_ERROR
, LOCATION
, NULL
,
2169 "invalid auth method %d.\n",
2175 case OAKLEY_ATTR_GRP_DESC
:
2176 if (!alg_oakley_dhdef_ok(lorv
)) {
2177 plog(LLV_ERROR
, LOCATION
, NULL
,
2178 "invalid DH group %d.\n",
2184 case OAKLEY_ATTR_GRP_TYPE
:
2186 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2189 plog(LLV_ERROR
, LOCATION
, NULL
,
2190 "unsupported DH group type %d.\n",
2196 case OAKLEY_ATTR_GRP_PI
:
2197 case OAKLEY_ATTR_GRP_GEN_ONE
:
2198 /* sanity checks? */
2201 case OAKLEY_ATTR_GRP_GEN_TWO
:
2202 case OAKLEY_ATTR_GRP_CURVE_A
:
2203 case OAKLEY_ATTR_GRP_CURVE_B
:
2204 plog(LLV_ERROR
, LOCATION
, NULL
,
2205 "attr type=%u isn't supported.\n", type
);
2208 case OAKLEY_ATTR_SA_LD_TYPE
:
2210 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2211 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2214 plog(LLV_ERROR
, LOCATION
, NULL
,
2215 "invalid life type %d.\n", lorv
);
2220 case OAKLEY_ATTR_SA_LD
:
2221 /* should check the value */
2224 case OAKLEY_ATTR_PRF
:
2225 case OAKLEY_ATTR_KEY_LEN
:
2228 case OAKLEY_ATTR_FIELD_SIZE
:
2229 plog(LLV_ERROR
, LOCATION
, NULL
,
2230 "attr type=%u isn't supported.\n", type
);
2233 case OAKLEY_ATTR_GRP_ORDER
:
2236 case OAKLEY_ATTR_GSS_ID
:
2240 plog(LLV_ERROR
, LOCATION
, NULL
,
2241 "invalid attribute type %d.\n", type
);
2247 d
= (struct isakmp_data
*)((char *)d
2250 tlen
-= (sizeof(*d
) + lorv
);
2251 d
= (struct isakmp_data
*)((char *)d
2252 + sizeof(*d
) + lorv
);
2260 * check data attributes in IPSEC AH/ESP.
2264 struct isakmp_pl_t
*trns
;
2266 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2270 check_attr_esp(trns
)
2271 struct isakmp_pl_t
*trns
;
2273 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2277 check_attr_ipsec(proto_id
, trns
)
2279 struct isakmp_pl_t
*trns
;
2281 struct isakmp_data
*d
;
2285 int attrseen
[16]; /* XXX magic number */
2287 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2288 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2289 memset(attrseen
, 0, sizeof(attrseen
));
2292 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2293 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2294 lorv
= ntohs(d
->lorv
);
2296 plog(LLV_DEBUG
, LOCATION
, NULL
,
2297 "type=%s, flag=0x%04x, lorv=%s\n",
2298 s_ipsecdoi_attr(type
), flag
,
2299 s_ipsecdoi_attr_v(type
, lorv
));
2301 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2305 case IPSECDOI_ATTR_ENC_MODE
:
2307 plog(LLV_ERROR
, LOCATION
, NULL
,
2308 "must be TV when ENC_MODE.\n");
2313 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2314 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2317 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2318 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2319 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2320 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2321 plog(LLV_DEBUG
, LOCATION
, NULL
,
2322 "UDP encapsulation requested\n");
2326 plog(LLV_ERROR
, LOCATION
, NULL
,
2327 "invalid encryption mode=%u.\n",
2333 case IPSECDOI_ATTR_AUTH
:
2335 plog(LLV_ERROR
, LOCATION
, NULL
,
2336 "must be TV when AUTH.\n");
2341 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2342 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2343 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2345 plog(LLV_ERROR
, LOCATION
, NULL
,
2346 "auth algorithm %u conflicts "
2347 "with transform %u.\n",
2352 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2353 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2354 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2358 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2359 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2360 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2364 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2365 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2366 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2370 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2371 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2372 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2376 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2377 case IPSECDOI_ATTR_AUTH_KPDK
:
2378 plog(LLV_ERROR
, LOCATION
, NULL
,
2379 "auth algorithm %u isn't supported.\n",
2383 plog(LLV_ERROR
, LOCATION
, NULL
,
2384 "invalid auth algorithm=%u.\n",
2390 case IPSECDOI_ATTR_SA_LD_TYPE
:
2392 plog(LLV_ERROR
, LOCATION
, NULL
,
2393 "must be TV when LD_TYPE.\n");
2398 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2399 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2402 plog(LLV_ERROR
, LOCATION
, NULL
,
2403 "invalid life type %d.\n", lorv
);
2408 case IPSECDOI_ATTR_SA_LD
:
2410 /* i.e. ISAKMP_GEN_TV */
2411 plog(LLV_DEBUG
, LOCATION
, NULL
,
2412 "life duration was in TLV.\n");
2414 /* i.e. ISAKMP_GEN_TLV */
2416 plog(LLV_ERROR
, LOCATION
, NULL
,
2417 "invalid length of LD\n");
2423 case IPSECDOI_ATTR_GRP_DESC
:
2425 plog(LLV_ERROR
, LOCATION
, NULL
,
2426 "must be TV when GRP_DESC.\n");
2430 if (!alg_oakley_dhdef_ok(lorv
)) {
2431 plog(LLV_ERROR
, LOCATION
, NULL
,
2432 "invalid group description=%u.\n",
2438 case IPSECDOI_ATTR_KEY_LENGTH
:
2440 plog(LLV_ERROR
, LOCATION
, NULL
,
2441 "must be TV when KEY_LENGTH.\n");
2446 case IPSECDOI_ATTR_KEY_ROUNDS
:
2447 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2448 case IPSECDOI_ATTR_COMP_PRIVALG
:
2449 plog(LLV_ERROR
, LOCATION
, NULL
,
2450 "attr type=%u isn't supported.\n", type
);
2454 plog(LLV_ERROR
, LOCATION
, NULL
,
2455 "invalid attribute type %d.\n", type
);
2461 d
= (struct isakmp_data
*)((char *)d
2464 tlen
-= (sizeof(*d
) + lorv
);
2465 d
= (struct isakmp_data
*)((caddr_t
)d
2466 + sizeof(*d
) + lorv
);
2470 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2471 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2472 plog(LLV_ERROR
, LOCATION
, NULL
,
2473 "attr AUTH must be present for AH.\n");
2477 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2478 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2479 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2480 plog(LLV_ERROR
, LOCATION
, NULL
,
2481 "attr AUTH must be present for ESP NULL encryption.\n");
2489 check_attr_ipcomp(trns
)
2490 struct isakmp_pl_t
*trns
;
2492 struct isakmp_data
*d
;
2496 int attrseen
[16]; /* XXX magic number */
2498 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2499 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2500 memset(attrseen
, 0, sizeof(attrseen
));
2503 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2504 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2505 lorv
= ntohs(d
->lorv
);
2507 plog(LLV_DEBUG
, LOCATION
, NULL
,
2508 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2511 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2515 case IPSECDOI_ATTR_ENC_MODE
:
2517 plog(LLV_ERROR
, LOCATION
, NULL
,
2518 "must be TV when ENC_MODE.\n");
2523 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2524 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2527 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2528 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2529 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2530 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2531 plog(LLV_DEBUG
, LOCATION
, NULL
,
2532 "UDP encapsulation requested\n");
2536 plog(LLV_ERROR
, LOCATION
, NULL
,
2537 "invalid encryption mode=%u.\n",
2543 case IPSECDOI_ATTR_SA_LD_TYPE
:
2545 plog(LLV_ERROR
, LOCATION
, NULL
,
2546 "must be TV when LD_TYPE.\n");
2551 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2552 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2555 plog(LLV_ERROR
, LOCATION
, NULL
,
2556 "invalid life type %d.\n", lorv
);
2561 case IPSECDOI_ATTR_SA_LD
:
2563 /* i.e. ISAKMP_GEN_TV */
2564 plog(LLV_DEBUG
, LOCATION
, NULL
,
2565 "life duration was in TLV.\n");
2567 /* i.e. ISAKMP_GEN_TLV */
2569 plog(LLV_ERROR
, LOCATION
, NULL
,
2570 "invalid length of LD\n");
2576 case IPSECDOI_ATTR_GRP_DESC
:
2578 plog(LLV_ERROR
, LOCATION
, NULL
,
2579 "must be TV when GRP_DESC.\n");
2583 if (!alg_oakley_dhdef_ok(lorv
)) {
2584 plog(LLV_ERROR
, LOCATION
, NULL
,
2585 "invalid group description=%u.\n",
2591 case IPSECDOI_ATTR_AUTH
:
2592 plog(LLV_ERROR
, LOCATION
, NULL
,
2593 "invalid attr type=%u.\n", type
);
2596 case IPSECDOI_ATTR_KEY_LENGTH
:
2597 case IPSECDOI_ATTR_KEY_ROUNDS
:
2598 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2599 case IPSECDOI_ATTR_COMP_PRIVALG
:
2600 plog(LLV_ERROR
, LOCATION
, NULL
,
2601 "attr type=%u isn't supported.\n", type
);
2605 plog(LLV_ERROR
, LOCATION
, NULL
,
2606 "invalid attribute type %d.\n", type
);
2612 d
= (struct isakmp_data
*)((char *)d
2615 tlen
-= (sizeof(*d
) + lorv
);
2616 d
= (struct isakmp_data
*)((caddr_t
)d
2617 + sizeof(*d
) + lorv
);
2622 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2623 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2624 plog(LLV_ERROR
, LOCATION
, NULL
,
2625 "attr AUTH must be present for AH.\n", type
);
2635 * create phase1 proposal from remote configuration.
2636 * NOT INCLUDING isakmp general header of SA payload
2639 ipsecdoi_setph1proposal(props
)
2640 struct isakmpsa
*props
;
2645 /* count total size of SA minus isakmp general header */
2646 /* not including isakmp general header of SA payload */
2647 sablen
= sizeof(struct ipsecdoi_sa_b
);
2648 sablen
+= setph1prop(props
, NULL
);
2650 mysa
= vmalloc(sablen
);
2652 plog(LLV_ERROR
, LOCATION
, NULL
,
2653 "failed to allocate my sa buffer\n");
2657 /* create SA payload */
2658 /* not including isakmp general header */
2659 ((struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2660 ((struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2662 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2668 setph1prop(props
, buf
)
2669 struct isakmpsa
*props
;
2672 struct isakmp_pl_p
*prop
= NULL
;
2673 struct isakmpsa
*s
= NULL
;
2674 int proplen
, trnslen
;
2675 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2679 proplen
= sizeof(*prop
);
2681 /* create proposal */
2682 prop
= (struct isakmp_pl_p
*)p
;
2683 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2684 prop
->p_no
= props
->prop_no
;
2685 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2693 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2695 *np_t
= ISAKMP_NPTYPE_T
;
2697 trnslen
= setph1trns(s
, p
);
2700 /* save buffer to pre-next payload */
2701 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2704 /* count up transform length */
2709 /* update proposal length */
2711 prop
->h
.len
= htons(proplen
);
2712 prop
->num_t
= trns_num
;
2720 struct isakmpsa
*sa
;
2723 struct isakmp_pl_t
*trns
= NULL
;
2724 int trnslen
, attrlen
;
2727 trnslen
= sizeof(*trns
);
2729 /* create transform */
2730 trns
= (struct isakmp_pl_t
*)p
;
2731 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2732 trns
->t_no
= sa
->trns_no
;
2733 trns
->t_id
= IPSECDOI_KEY_IKE
;
2737 attrlen
= setph1attr(sa
, p
);
2743 trns
->h
.len
= htons(trnslen
);
2750 struct isakmpsa
*sa
;
2757 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2759 attrlen
+= sizeof(struct isakmp_data
)
2760 + sizeof(struct isakmp_data
);
2761 if (sa
->lifetime
> 0xffff)
2762 attrlen
+= sizeof(lifetime
);
2764 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2765 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2766 if (sa
->lifetime
> 0xffff) {
2767 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2771 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2778 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2780 attrlen
+= sizeof(struct isakmp_data
)
2781 + sizeof(struct isakmp_data
);
2782 if (sa
->lifebyte
> 0xffff)
2783 attrlen
+= sizeof(lifebyte
);
2785 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2786 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2787 if (sa
->lifebyte
> 0xffff) {
2788 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2792 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2799 attrlen
+= sizeof(struct isakmp_data
);
2801 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2804 attrlen
+= sizeof(struct isakmp_data
);
2806 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2808 if (sa
->authmethod
) {
2811 #ifdef ENABLE_HYBRID
2812 authmethod
= switch_authmethod(sa
->authmethod
);
2814 authmethod
= sa
->authmethod
;
2816 attrlen
+= sizeof(struct isakmp_data
);
2818 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2821 attrlen
+= sizeof(struct isakmp_data
);
2823 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2825 switch (sa
->dh_group
) {
2826 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2827 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2828 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2829 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2830 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2831 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2832 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2833 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2834 /* don't attach group type for known groups */
2835 attrlen
+= sizeof(struct isakmp_data
);
2837 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2841 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2842 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2843 /* don't attach group type for known groups */
2844 attrlen
+= sizeof(struct isakmp_data
);
2846 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2847 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2856 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2857 sa
->gssid
!= NULL
) {
2858 attrlen
+= sizeof(struct isakmp_data
);
2860 * Older versions of racoon just placed the ISO-Latin-1
2861 * string on the wire directly. Check to see if we are
2862 * configured to be compatible with this behavior. Otherwise,
2863 * we encode the GSS ID as UTF-16LE for Windows 2000
2864 * compatibility, which requires twice the number of octets.
2866 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
)
2867 attrlen
+= sa
->gssid
->l
;
2869 attrlen
+= sa
->gssid
->l
* 2;
2871 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %zu, "
2872 "val '%.*s'\n", sa
->gssid
->l
, (int)sa
->gssid
->l
,
2874 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
2875 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2876 (caddr_t
)sa
->gssid
->v
,
2879 size_t dstleft
= sa
->gssid
->l
* 2;
2880 size_t srcleft
= sa
->gssid
->l
;
2881 const char *src
= (const char *)sa
->gssid
->v
;
2882 char *odst
, *dst
= racoon_malloc(dstleft
);
2886 cd
= iconv_open("utf-16le", "latin1");
2887 if (cd
== (iconv_t
) -1) {
2888 plog(LLV_ERROR
, LOCATION
, NULL
,
2889 "unable to initialize "
2890 "latin1 -> utf-16le "
2891 "converstion descriptor: %s\n",
2893 attrlen
-= sa
->gssid
->l
* 2;
2897 rv
= iconv(cd
, (__iconv_const
char **)&src
,
2898 &srcleft
, &dst
, &dstleft
);
2901 plog(LLV_ERROR
, LOCATION
, NULL
,
2902 "unable to convert GSS ID "
2903 "from latin1 -> utf-16le: "
2904 "%s\n", strerror(errno
));
2906 /* should never happen */
2907 plog(LLV_ERROR
, LOCATION
, NULL
,
2908 "%zd character%s in GSS ID "
2909 "cannot be represented "
2911 rv
, rv
== 1 ? "" : "s");
2913 (void) iconv_close(cd
);
2914 attrlen
-= sa
->gssid
->l
* 2;
2917 (void) iconv_close(cd
);
2919 /* XXX Check srcleft and dstleft? */
2921 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2922 odst
, sa
->gssid
->l
* 2);
2929 #endif /* HAVE_GSSAPI */
2935 setph2proposal0(iph2
, pp
, pr
)
2936 const struct ph2handle
*iph2
;
2937 const struct saprop
*pp
;
2938 const struct saproto
*pr
;
2941 struct isakmp_pl_p
*prop
;
2942 struct isakmp_pl_t
*trns
;
2947 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2948 const u_int8_t
*spi
;
2950 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2954 /* create proposal */
2955 prop
= (struct isakmp_pl_p
*)p
->v
;
2956 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2957 prop
->p_no
= pp
->prop_no
;
2958 prop
->proto_id
= pr
->proto_id
;
2961 spi
= (const u_int8_t
*)&pr
->spi
;
2962 switch (pr
->proto_id
) {
2963 case IPSECDOI_PROTO_IPCOMP
:
2965 * draft-shacham-ippcp-rfc2393bis-05.txt:
2966 * construct 16bit SPI (CPI).
2967 * XXX we may need to provide a configuration option to
2968 * generate 32bit SPI. otherwise we cannot interoeprate
2969 * with nodes that uses 32bit SPI, in case we are initiator.
2971 prop
->spi_size
= sizeof(u_int16_t
);
2972 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2973 p
->l
-= sizeof(pr
->spi
);
2974 p
->l
+= sizeof(u_int16_t
);
2977 prop
->spi_size
= sizeof(pr
->spi
);
2980 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2982 /* create transform */
2983 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2986 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2988 switch (pr
->proto_id
) {
2989 case IPSECDOI_PROTO_IPSEC_ESP
:
2991 * don't build a null encryption
2992 * with no authentication transform.
2994 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2995 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
3001 *np_t
= ISAKMP_NPTYPE_T
;
3005 /* get attribute length */
3008 attrlen
+= sizeof(struct isakmp_data
)
3009 + sizeof(struct isakmp_data
);
3010 if (pp
->lifetime
> 0xffff)
3011 attrlen
+= sizeof(u_int32_t
);
3013 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3014 attrlen
+= sizeof(struct isakmp_data
)
3015 + sizeof(struct isakmp_data
);
3016 if (pp
->lifebyte
> 0xffff)
3017 attrlen
+= sizeof(u_int32_t
);
3019 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
3021 attrlen
+= sizeof(struct isakmp_data
);
3023 switch (pr
->proto_id
) {
3024 case IPSECDOI_PROTO_IPSEC_ESP
:
3025 /* non authentication mode ? */
3026 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3027 attrlen
+= sizeof(struct isakmp_data
);
3029 case IPSECDOI_PROTO_IPSEC_AH
:
3030 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
3031 plog(LLV_ERROR
, LOCATION
, NULL
,
3032 "no authentication algorithm found "
3033 "but protocol is AH.\n");
3037 attrlen
+= sizeof(struct isakmp_data
);
3039 case IPSECDOI_PROTO_IPCOMP
:
3042 plog(LLV_ERROR
, LOCATION
, NULL
,
3043 "invalid protocol: %d\n", pr
->proto_id
);
3048 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3049 attrlen
+= sizeof(struct isakmp_data
);
3051 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
3054 prop
= (struct isakmp_pl_p
*)p
->v
;
3056 /* set transform's values */
3057 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3058 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
3059 trns
->t_no
= tr
->trns_no
;
3060 trns
->t_id
= tr
->trns_id
;
3062 /* set attributes */
3063 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
3066 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3067 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
3068 if (pp
->lifetime
> 0xffff) {
3069 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
3070 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3071 (caddr_t
)&v
, sizeof(v
));
3073 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3078 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3079 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3080 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
3081 if (pp
->lifebyte
> 0xffff) {
3082 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
3083 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3084 (caddr_t
)&v
, sizeof(v
));
3086 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3091 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
3094 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
3096 /* mandatory check has done above. */
3097 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3098 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
3099 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
3101 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3102 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
3103 iph2
->sainfo
->pfs_group
);
3105 /* update length of this transform. */
3106 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3107 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
3109 /* save buffer to pre-next payload */
3112 trnsoff
+= (sizeof(*trns
) + attrlen
);
3116 plog(LLV_ERROR
, LOCATION
, NULL
,
3117 "no suitable proposal was created.\n");
3121 /* update length of this protocol. */
3122 prop
->h
.len
= htons(p
->l
);
3128 * create phase2 proposal from policy configuration.
3129 * NOT INCLUDING isakmp general header of SA payload.
3130 * This function is called by initiator only.
3133 ipsecdoi_setph2proposal(iph2
)
3134 struct ph2handle
*iph2
;
3136 struct saprop
*proposal
, *a
;
3137 struct saproto
*b
= NULL
;
3139 struct ipsecdoi_sa_b
*sab
;
3140 struct isakmp_pl_p
*prop
;
3141 size_t propoff
; /* for previous field of type of next payload. */
3143 proposal
= iph2
->proposal
;
3145 iph2
->sa
= vmalloc(sizeof(*sab
));
3146 if (iph2
->sa
== NULL
) {
3147 plog(LLV_ERROR
, LOCATION
, NULL
,
3148 "failed to allocate my sa buffer\n");
3152 /* create SA payload */
3153 sab
= (struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
3154 sab
->doi
= htonl(IPSEC_DOI
);
3155 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3159 for (a
= proposal
; a
; a
= a
->next
) {
3160 for (b
= a
->head
; b
; b
= b
->next
) {
3162 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3163 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3164 plog (LLV_INFO
, LOCATION
, NULL
,
3165 "NAT detected -> UDP encapsulation "
3166 "(ENC_MODE %d->%d).\n",
3168 b
->encmode
+udp_diff
);
3169 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3170 b
->encmode
+= udp_diff
;
3175 q
= setph2proposal0(iph2
, a
, b
);
3181 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
3182 if (iph2
->sa
== NULL
) {
3183 plog(LLV_ERROR
, LOCATION
, NULL
,
3184 "failed to allocate my sa buffer\n");
3189 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
3191 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
3193 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3195 propoff
= iph2
->sa
->l
- q
->l
;
3206 * return 1 if all of the given protocols are tunnel mode.
3209 ipsecdoi_tunnelmode(iph2
)
3210 struct ph2handle
*iph2
;
3213 struct saproto
*pr
= NULL
;
3215 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
3216 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3217 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
3218 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
3219 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
3228 * return 1 if any of the given protocols are transport mode.
3231 ipsecdoi_any_transportmode(pp
)
3234 struct saproto
*pr
= NULL
;
3236 for (; pp
; pp
= pp
->next
) {
3237 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3238 if (pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_TRNS
||
3239 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
||
3240 pr
->encmode
== IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
3250 * return 1 if all of the given protocols are transport mode.
3253 ipsecdoi_transportmode(pp
)
3256 struct saproto
*pr
= NULL
;
3258 for (; pp
; pp
= pp
->next
) {
3259 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3260 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
3269 ipsecdoi_get_defaultlifetime()
3271 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3275 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3276 int proto_id
, enc
, auth
, comp
;
3278 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3280 case IPSECDOI_PROTO_IPSEC_ESP
:
3281 if (enc
== 0 || comp
!= 0) {
3282 plog(LLV_ERROR
, LOCATION
, NULL
,
3283 "illegal algorithm defined "
3284 "ESP enc=%s auth=%s comp=%s.\n",
3285 TMPALGTYPE2STR(enc
),
3286 TMPALGTYPE2STR(auth
),
3287 TMPALGTYPE2STR(comp
));
3291 case IPSECDOI_PROTO_IPSEC_AH
:
3292 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3293 plog(LLV_ERROR
, LOCATION
, NULL
,
3294 "illegal algorithm defined "
3295 "AH enc=%s auth=%s comp=%s.\n",
3296 TMPALGTYPE2STR(enc
),
3297 TMPALGTYPE2STR(auth
),
3298 TMPALGTYPE2STR(comp
));
3302 case IPSECDOI_PROTO_IPCOMP
:
3303 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3304 plog(LLV_ERROR
, LOCATION
, NULL
,
3305 "illegal algorithm defined "
3306 "IPcomp enc=%s auth=%s comp=%s.\n",
3307 TMPALGTYPE2STR(enc
),
3308 TMPALGTYPE2STR(auth
),
3309 TMPALGTYPE2STR(comp
));
3314 plog(LLV_ERROR
, LOCATION
, NULL
,
3315 "invalid ipsec protocol %d\n", proto_id
);
3318 #undef TMPALGTYPE2STR
3328 return IPSECDOI_PROTO_IPSEC_AH
;
3330 return IPSECDOI_PROTO_IPSEC_ESP
;
3331 case IPPROTO_IPCOMP
:
3332 return IPSECDOI_PROTO_IPCOMP
;
3334 return -1; /* XXX */
3342 case IPSECDOI_PROTO_IPSEC_AH
:
3344 case IPSECDOI_PROTO_IPSEC_ESP
:
3346 case IPSECDOI_PROTO_IPCOMP
:
3347 return IPPROTO_IPCOMP
;
3349 return -1; /* XXX */
3353 * Check if a subnet id is valid for comparison
3354 * with an address id ( address length mask )
3362 ipsecdoi_subnetisaddr_v4( subnet
, address
)
3363 const vchar_t
*subnet
;
3364 const vchar_t
*address
;
3366 struct in_addr
*mask
;
3368 if (address
->l
!= sizeof(struct in_addr
))
3371 if (subnet
->l
!= (sizeof(struct in_addr
)*2))
3374 mask
= (struct in_addr
*)(subnet
->v
+ sizeof(struct in_addr
));
3376 if (mask
->s_addr
!=0xffffffff)
3379 return memcmp(subnet
->v
,address
->v
,address
->l
);
3385 ipsecdoi_subnetisaddr_v6( subnet
, address
)
3386 const vchar_t
*subnet
;
3387 const vchar_t
*address
;
3389 struct in6_addr
*mask
;
3392 if (address
->l
!= sizeof(struct in6_addr
))
3395 if (subnet
->l
!= (sizeof(struct in6_addr
)*2))
3398 mask
= (struct in6_addr
*)(subnet
->v
+ sizeof(struct in6_addr
));
3400 for (i
=0; i
<16; i
++)
3401 if(mask
->s6_addr
[i
]!=0xff)
3404 return memcmp(subnet
->v
,address
->v
,address
->l
);
3410 * Check and Compare two IDs
3411 * - specify 0 for exact if wildcards are allowed
3415 * = -1 for integrity error
3419 ipsecdoi_chkcmpids( idt
, ids
, exact
)
3420 const vchar_t
*idt
; /* id cmp target */
3421 const vchar_t
*ids
; /* id cmp source */
3424 struct ipsecdoi_id_b
*id_bt
;
3425 struct ipsecdoi_id_b
*id_bs
;
3430 /* handle wildcard IDs */
3432 if (idt
== NULL
|| ids
== NULL
)
3436 plog(LLV_DEBUG
, LOCATION
, NULL
,
3437 "check and compare ids : values matched (ANONYMOUS)\n" );
3442 plog(LLV_DEBUG
, LOCATION
, NULL
,
3443 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3448 /* make sure the ids are of the same type */
3450 id_bt
= (struct ipsecdoi_id_b
*) idt
->v
;
3451 id_bs
= (struct ipsecdoi_id_b
*) ids
->v
;
3453 ident_t
.v
= idt
->v
+ sizeof(*id_bt
);
3454 ident_t
.l
= idt
->l
- sizeof(*id_bt
);
3455 ident_s
.v
= ids
->v
+ sizeof(*id_bs
);
3456 ident_s
.l
= ids
->l
- sizeof(*id_bs
);
3458 if (id_bs
->type
!= id_bt
->type
)
3461 * special exception for comparing
3462 * address to subnet id types when
3463 * the netmask is address length
3466 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR
)&&
3467 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)) {
3468 result
= ipsecdoi_subnetisaddr_v4(&ident_t
,&ident_s
);
3472 if ((id_bs
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
)&&
3473 (id_bt
->type
== IPSECDOI_ID_IPV4_ADDR
)) {
3474 result
= ipsecdoi_subnetisaddr_v4(&ident_s
,&ident_t
);
3479 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR
)&&
3480 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)) {
3481 result
= ipsecdoi_subnetisaddr_v6(&ident_t
,&ident_s
);
3485 if ((id_bs
->type
== IPSECDOI_ID_IPV6_ADDR_SUBNET
)&&
3486 (id_bt
->type
== IPSECDOI_ID_IPV6_ADDR
)) {
3487 result
= ipsecdoi_subnetisaddr_v6(&ident_s
,&ident_t
);
3491 plog(LLV_DEBUG
, LOCATION
, NULL
,
3492 "check and compare ids : id type mismatch %s != %s\n",
3493 s_ipsecdoi_ident(id_bs
->type
),
3494 s_ipsecdoi_ident(id_bt
->type
));
3499 if(id_bs
->proto_id
!= id_bt
->proto_id
){
3500 plog(LLV_DEBUG
, LOCATION
, NULL
,
3501 "check and compare ids : proto_id mismatch %d != %d\n",
3502 id_bs
->proto_id
, id_bt
->proto_id
);
3507 /* compare the ID data. */
3509 switch (id_bt
->type
) {
3510 case IPSECDOI_ID_DER_ASN1_DN
:
3511 case IPSECDOI_ID_DER_ASN1_GN
:
3512 /* compare asn1 ids */
3513 result
= eay_cmp_asn1dn(&ident_t
, &ident_s
);
3516 case IPSECDOI_ID_IPV4_ADDR
:
3517 /* validate lengths */
3518 if ((ident_t
.l
!= sizeof(struct in_addr
))||
3519 (ident_s
.l
!= sizeof(struct in_addr
)))
3523 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3524 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3525 /* validate lengths */
3526 if ((ident_t
.l
!= (sizeof(struct in_addr
)*2))||
3527 (ident_s
.l
!= (sizeof(struct in_addr
)*2)))
3532 case IPSECDOI_ID_IPV6_ADDR
:
3533 /* validate lengths */
3534 if ((ident_t
.l
!= sizeof(struct in6_addr
))||
3535 (ident_s
.l
!= sizeof(struct in6_addr
)))
3539 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3540 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3541 /* validate lengths */
3542 if ((ident_t
.l
!= (sizeof(struct in6_addr
)*2))||
3543 (ident_s
.l
!= (sizeof(struct in6_addr
)*2)))
3547 case IPSECDOI_ID_FQDN
:
3548 case IPSECDOI_ID_USER_FQDN
:
3549 case IPSECDOI_ID_KEY_ID
:
3553 plog(LLV_ERROR
, LOCATION
, NULL
,
3554 "Unhandled id type %i specified for comparison\n",
3559 /* validate matching data and length */
3560 if (ident_t
.l
== ident_s
.l
)
3561 result
= memcmp(ident_t
.v
,ident_s
.v
,ident_t
.l
);
3567 /* debug level output */
3568 if(loglevel
>= LLV_DEBUG
) {
3569 char *idstrt
= ipsecdoi_id2str(idt
);
3570 char *idstrs
= ipsecdoi_id2str(ids
);
3573 plog(LLV_DEBUG
, LOCATION
, NULL
,
3574 "check and compare ids : values matched (%s)\n",
3575 s_ipsecdoi_ident(id_bs
->type
) );
3577 plog(LLV_DEBUG
, LOCATION
, NULL
,
3578 "check and compare ids : value mismatch (%s)\n",
3579 s_ipsecdoi_ident(id_bs
->type
));
3581 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid target: \'%s\'\n", idstrt
);
3582 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid source: \'%s\'\n", idstrs
);
3584 racoon_free(idstrs
);
3585 racoon_free(idstrt
);
3596 /* id integrity error */
3597 plog(LLV_DEBUG
, LOCATION
, NULL
, "check and compare ids : %s integrity error\n",
3598 s_ipsecdoi_ident(id_bs
->type
));
3599 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid target: length = \'%zu\'\n", ident_t
.l
);
3600 plog(LLV_DEBUG
, LOCATION
, NULL
, "cmpid source: length = \'%zu\'\n", ident_s
.l
);
3606 * check the following:
3607 * - In main mode with pre-shared key, only address type can be used.
3608 * - if proper type for phase 1 ?
3609 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3610 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3611 * - if ID payload sent from peer is equal to the ID expected by me.
3613 * both of "id" and "id_p" should be ID payload without general header,
3616 ipsecdoi_checkid1(iph1
)
3617 struct ph1handle
*iph1
;
3619 struct ipsecdoi_id_b
*id_b
;
3620 struct sockaddr
*sa
;
3623 if (iph1
->id_p
== NULL
) {
3624 plog(LLV_ERROR
, LOCATION
, NULL
,
3625 "invalid iph1 passed id_p == NULL\n");
3626 return ISAKMP_INTERNAL_ERROR
;
3628 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3629 plog(LLV_ERROR
, LOCATION
, NULL
,
3630 "invalid value passed as \"ident\" (len=%lu)\n",
3631 (u_long
)iph1
->id_p
->l
);
3632 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3635 id_b
= (struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3637 /* In main mode with pre-shared key, only address type can be used.
3638 * If NAT Traversal being used and peer is behind nat and
3639 * natt version = 02 - allow non-address ID type.
3641 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
3642 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3644 && (iph1
->natt_flags
& NAT_DETECTED_PEER
) == 0
3647 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3648 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3649 plog(LLV_ERROR
, LOCATION
, NULL
,
3650 "Expecting IP address type in main mode, "
3651 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3652 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3656 /* if proper type for phase 1 ? */
3657 switch (id_b
->type
) {
3658 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3659 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3660 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3661 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3662 plog(LLV_WARNING
, LOCATION
, NULL
,
3663 "such ID type %s is not proper.\n",
3664 s_ipsecdoi_ident(id_b
->type
));
3668 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3669 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
||
3670 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3672 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3673 plog(LLV_WARNING
, LOCATION
, NULL
,
3674 "protocol ID and Port mismatched. "
3675 "proto_id:%d port:%d\n",
3676 id_b
->proto_id
, ntohs(id_b
->port
));
3679 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3681 * copmaring with expected port.
3682 * always permit if port is equal to PORT_ISAKMP
3684 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3688 switch (iph1
->remote
->sa_family
) {
3690 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3694 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3698 plog(LLV_ERROR
, LOCATION
, NULL
,
3699 "invalid family: %d\n",
3700 iph1
->remote
->sa_family
);
3701 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3703 if (ntohs(id_b
->port
) != port
) {
3704 plog(LLV_WARNING
, LOCATION
, NULL
,
3705 "port %d expected, but %d\n",
3706 port
, ntohs(id_b
->port
));
3713 /* compare with the ID if specified. */
3714 if (genlist_next(iph1
->rmconf
->idvl_p
, 0)) {
3715 vchar_t
*ident0
= NULL
;
3718 struct genlist_entry
*gpb
;
3720 for (id
= genlist_next (iph1
->rmconf
->idvl_p
, &gpb
); id
; id
= genlist_next (0, &gpb
)) {
3721 /* check the type of both IDs */
3722 if (id
->idtype
!= doi2idtype(id_b
->type
))
3723 continue; /* ID type mismatch */
3727 /* compare defined ID with the ID sent by peer. */
3730 ident0
= getidval(id
->idtype
, id
->id
);
3732 switch (id
->idtype
) {
3734 ident
.v
= iph1
->id_p
->v
+ sizeof(*id_b
);
3735 ident
.l
= iph1
->id_p
->l
- sizeof(*id_b
);
3736 if (eay_cmp_asn1dn(ident0
, &ident
) == 0)
3739 case IDTYPE_ADDRESS
:
3740 sa
= (struct sockaddr
*)ident0
->v
;
3741 sa2
= (caddr_t
)(id_b
+ 1);
3742 switch (sa
->sa_family
) {
3744 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3745 continue; /* ID value mismatch */
3746 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3747 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) == 0)
3752 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3753 continue; /* ID value mismatch */
3754 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3755 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) == 0)
3764 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
) == 0)
3769 if (ident0
!= NULL
) {
3773 plog(LLV_WARNING
, LOCATION
, NULL
, "No ID match.\n");
3774 if (iph1
->rmconf
->verify_identifier
)
3775 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3776 matched
: /* ID value match */
3785 * create ID payload for phase 1 and set into iph1->id.
3786 * NOT INCLUDING isakmp general header.
3787 * see, RFC2407 4.6.2.1
3790 ipsecdoi_setid1(iph1
)
3791 struct ph1handle
*iph1
;
3793 vchar_t
*ret
= NULL
;
3794 struct ipsecdoi_id_b id_b
;
3795 vchar_t
*ident
= NULL
;
3796 struct sockaddr
*ipid
= NULL
;
3803 switch (iph1
->rmconf
->idvtype
) {
3805 id_b
.type
= IPSECDOI_ID_FQDN
;
3806 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3808 case IDTYPE_USERFQDN
:
3809 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3810 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3814 case IDTYPE_KEYIDUSE
:
3816 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3817 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3820 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3821 if (iph1
->rmconf
->idv
) {
3822 /* XXX it must be encoded to asn1dn. */
3823 ident
= vdup(iph1
->rmconf
->idv
);
3825 if (oakley_getmycert(iph1
) < 0) {
3826 plog(LLV_ERROR
, LOCATION
, NULL
,
3827 "failed to get own CERT.\n");
3830 ident
= eay_get_x509asn1subjectname(&iph1
->cert
->cert
);
3833 case IDTYPE_ADDRESS
:
3835 * if the value of the id type was set by the configuration
3836 * file, then use it. otherwise the value is get from local
3837 * ip address by using ike negotiation.
3839 if (iph1
->rmconf
->idv
)
3840 ipid
= (struct sockaddr
*)iph1
->rmconf
->idv
->v
;
3850 /* use IP address */
3851 switch (ipid
->sa_family
) {
3853 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3854 l
= sizeof(struct in_addr
);
3855 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3859 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3860 l
= sizeof(struct in6_addr
);
3861 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3865 plog(LLV_ERROR
, LOCATION
, NULL
,
3866 "invalid address family.\n");
3869 id_b
.proto_id
= IPPROTO_UDP
;
3870 id_b
.port
= htons(PORT_ISAKMP
);
3873 plog(LLV_ERROR
, LOCATION
, NULL
,
3874 "failed to get ID buffer.\n");
3877 memcpy(ident
->v
, p
, ident
->l
);
3881 plog(LLV_ERROR
, LOCATION
, NULL
,
3882 "failed to get ID buffer.\n");
3886 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3888 plog(LLV_ERROR
, LOCATION
, NULL
,
3889 "failed to get ID buffer.\n");
3893 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3894 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3898 plog(LLV_DEBUG
, LOCATION
, NULL
,
3899 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3907 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3916 vchar_t
*new = NULL
;
3920 else if (lcconf
->ident
[type
])
3921 new = vdup(lcconf
->ident
[type
]);
3926 /* it's only called by cfparse.y. */
3928 set_identifier(vpp
, type
, value
)
3929 vchar_t
**vpp
, *value
;
3932 return set_identifier_qual(vpp
, type
, value
, IDQUAL_UNSPEC
);
3936 set_identifier_qual(vpp
, type
, value
, qual
)
3937 vchar_t
**vpp
, *value
;
3941 vchar_t
*new = NULL
;
3943 /* simply return if value is null. */
3945 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3946 plog(LLV_ERROR
, LOCATION
, NULL
,
3947 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3955 case IDTYPE_USERFQDN
:
3957 plog(LLV_ERROR
, LOCATION
, NULL
,
3958 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3962 case IDTYPE_KEYIDUSE
:
3964 #ifdef ENABLE_HYBRID
3967 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3968 new = vmalloc(value
->l
- 1);
3971 memcpy(new->v
, value
->v
, new->l
);
3975 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3976 * to use a file for backward compatibility sake.
3980 case IDQUAL_UNSPEC
: {
3985 fp
= fopen(value
->v
, "r");
3987 plog(LLV_ERROR
, LOCATION
, NULL
,
3988 "can not open %s\n", value
->v
);
3992 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3993 new = vrealloc(new, tlen
+ len
);
3998 memcpy(new->v
+ tlen
, b
, len
);
4006 new = vmalloc(value
->l
- 1);
4008 plog(LLV_ERROR
, LOCATION
, NULL
,
4009 "can not allocate memory");
4012 memcpy(new->v
, value
->v
, new->l
);
4016 plog(LLV_ERROR
, LOCATION
, NULL
,
4017 "unknown qualifier");
4022 case IDTYPE_ADDRESS
: {
4023 struct sockaddr
*sa
;
4025 /* length is adjusted since QUOTEDSTRING teminates NULL. */
4029 sa
= str2saddr(value
->v
, NULL
);
4031 plog(LLV_ERROR
, LOCATION
, NULL
,
4032 "invalid ip address %s\n", value
->v
);
4036 new = vmalloc(sysdep_sa_len(sa
));
4041 memcpy(new->v
, sa
, new->l
);
4046 if (value
->v
[0] == '~')
4047 /* Hex-encoded ASN1 strings */
4048 new = eay_hex2asn1dn(value
->v
+ 1, - 1);
4050 /* DN encoded strings */
4051 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
4056 if (loglevel
>= LLV_DEBUG
) {
4059 unsigned char *ptr
= (unsigned char *) new->v
, *buf
;
4063 xn
= d2i_X509_NAME(NULL
, (void *)&ptr
, new->l
);
4064 bio
= BIO_new(BIO_s_mem());
4066 X509_NAME_print_ex(bio
, xn
, 0, 0);
4067 len
= BIO_get_mem_data(bio
, &ptr
);
4070 plog(LLV_DEBUG
, LOCATION
, NULL
, "Parsed DN: %s\n", ptr
);
4085 * create ID payload for phase 2, and set into iph2->id and id_p. There are
4086 * NOT INCLUDING isakmp general header.
4087 * this function is for initiator. responder will get to copy from payload.
4088 * responder ID type is always address type.
4089 * see, RFC2407 4.6.2.1
4092 ipsecdoi_setid2(iph2
)
4093 struct ph2handle
*iph2
;
4095 struct secpolicy
*sp
;
4097 /* check there is phase 2 handler ? */
4098 sp
= getspbyspid(iph2
->spid
);
4100 plog(LLV_ERROR
, LOCATION
, NULL
,
4101 "no policy found for spid:%u.\n", iph2
->spid
);
4105 iph2
->id
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.src
,
4106 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
4107 if (iph2
->id
== NULL
) {
4108 plog(LLV_ERROR
, LOCATION
, NULL
,
4109 "failed to get ID for %s\n",
4110 spidx2str(&sp
->spidx
));
4113 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
4114 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
4117 iph2
->id_p
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.dst
,
4118 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
4119 if (iph2
->id_p
== NULL
) {
4120 plog(LLV_ERROR
, LOCATION
, NULL
,
4121 "failed to get ID for %s\n",
4122 spidx2str(&sp
->spidx
));
4126 plog(LLV_DEBUG
, LOCATION
, NULL
,
4127 "use remote ID type %s\n",
4128 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
4134 * set address type of ID.
4135 * NOT INCLUDING general header.
4138 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
4139 struct sockaddr
*saddr
;
4144 int type
, len1
, len2
;
4149 * Q. When type is SUBNET, is it allowed to be ::1/128.
4150 * A. Yes. (consensus at bake-off)
4152 switch (saddr
->sa_family
) {
4154 len1
= sizeof(struct in_addr
);
4155 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
4156 type
= IPSECDOI_ID_IPV4_ADDR
;
4159 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
4160 len2
= sizeof(struct in_addr
);
4162 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
4163 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
4167 len1
= sizeof(struct in6_addr
);
4168 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
4169 type
= IPSECDOI_ID_IPV6_ADDR
;
4172 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
4173 len2
= sizeof(struct in6_addr
);
4175 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
4176 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
4180 plog(LLV_ERROR
, LOCATION
, NULL
,
4181 "invalid family: %d.\n", saddr
->sa_family
);
4186 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4188 plog(LLV_ERROR
, LOCATION
, NULL
,
4189 "failed to get ID buffer.\n");
4193 memset(new->v
, 0, new->l
);
4195 /* set the part of header. */
4196 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4198 /* set ul_proto and port */
4200 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4201 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4203 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4204 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4205 ((struct ipsecdoi_id_b
*)new->v
)->port
=
4206 port
== IPSEC_PORT_ANY
? 0 : port
;
4207 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
4213 u_char
*p
= (unsigned char *) new->v
+
4214 sizeof(struct ipsecdoi_id_b
) + len1
;
4215 u_int bits
= prefixlen
;
4223 *p
= ~((1 << (8 - bits
)) - 1);
4230 ipsecdoi_sockrange2id(laddr
, haddr
, ul_proto
)
4231 struct sockaddr
*laddr
, *haddr
;
4235 int type
, len1
, len2
;
4238 if (laddr
->sa_family
!= haddr
->sa_family
) {
4239 plog(LLV_ERROR
, LOCATION
, NULL
, "Address family mismatch\n");
4243 switch (laddr
->sa_family
) {
4245 type
= IPSECDOI_ID_IPV4_ADDR_RANGE
;
4246 len1
= sizeof(struct in_addr
);
4247 len2
= sizeof(struct in_addr
);
4251 type
= IPSECDOI_ID_IPV6_ADDR_RANGE
;
4252 len1
= sizeof(struct in6_addr
);
4253 len2
= sizeof(struct in6_addr
);
4257 plog(LLV_ERROR
, LOCATION
, NULL
,
4258 "invalid family: %d.\n", laddr
->sa_family
);
4263 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
4265 plog(LLV_ERROR
, LOCATION
, NULL
,
4266 "failed to get ID buffer.\n");
4270 memset(new->v
, 0, new->l
);
4271 /* set the part of header. */
4272 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
4274 /* set ul_proto and port */
4276 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4277 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4279 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
4280 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
4281 port
= ((struct sockaddr_in
*)(laddr
))->sin_port
;
4282 ((struct ipsecdoi_id_b
*)new->v
)->port
=
4283 port
== IPSEC_PORT_ANY
? 0 : port
;
4284 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
),
4285 (caddr_t
)&((struct sockaddr_in
*)(laddr
))->sin_addr
,
4287 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
,
4288 (caddr_t
)&((struct sockaddr_in
*)haddr
)->sin_addr
,
4295 * create sockaddr structure from ID payload (buf).
4296 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4297 * see, RFC2407 4.6.2.1
4300 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
4302 struct sockaddr
*saddr
;
4303 u_int8_t
*prefixlen
;
4304 u_int16_t
*ul_proto
;
4306 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)buf
->v
;
4310 * When a ID payload of subnet type with a IP address of full bit
4311 * masked, it has to be processed as host address.
4312 * e.g. below 2 type are same.
4313 * type = ipv6 subnet, data = 2001::1/128
4314 * type = ipv6 address, data = 2001::1
4316 switch (id_b
->type
) {
4317 case IPSECDOI_ID_IPV4_ADDR
:
4318 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4320 saddr
->sa_len
= sizeof(struct sockaddr_in
);
4322 saddr
->sa_family
= AF_INET
;
4323 ((struct sockaddr_in
*)saddr
)->sin_port
=
4326 : id_b
->port
); /* see sockaddr2id() */
4327 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
4328 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4331 case IPSECDOI_ID_IPV6_ADDR
:
4332 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4334 saddr
->sa_len
= sizeof(struct sockaddr_in6
);
4336 saddr
->sa_family
= AF_INET6
;
4337 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
4340 : id_b
->port
); /* see sockaddr2id() */
4341 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
4342 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4346 plog(LLV_ERROR
, LOCATION
, NULL
,
4347 "unsupported ID type %d\n", id_b
->type
);
4348 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
4351 /* get prefix length */
4352 switch (id_b
->type
) {
4353 case IPSECDOI_ID_IPV4_ADDR
:
4354 plen
= sizeof(struct in_addr
) << 3;
4357 case IPSECDOI_ID_IPV6_ADDR
:
4358 plen
= sizeof(struct in6_addr
) << 3;
4361 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4363 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4368 int alen
= sizeof(struct in_addr
);
4370 switch (id_b
->type
) {
4371 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4372 alen
= sizeof(struct in_addr
);
4375 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4376 alen
= sizeof(struct in6_addr
);
4383 return ISAKMP_INTERNAL_ERROR
;
4385 /* get subnet mask length */
4389 p
= (unsigned char *) buf
->v
4390 + sizeof(struct ipsecdoi_id_b
)
4393 for (; *p
== 0xff; p
++) {
4416 *ul_proto
= id_b
->proto_id
== 0
4418 : id_b
->proto_id
; /* see sockaddr2id() */
4424 * make printable string from ID payload except of general header.
4434 static char buf
[BUFLEN
];
4435 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)id
->v
;
4436 struct sockaddr_storage saddr
;
4439 bzero(&saddr
, sizeof(saddr
));
4441 switch (id_b
->type
) {
4442 case IPSECDOI_ID_IPV4_ADDR
:
4443 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4444 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4447 ((struct sockaddr
*)&saddr
)->sa_len
= sizeof(struct sockaddr_in
);
4449 ((struct sockaddr
*)&saddr
)->sa_family
= AF_INET
;
4450 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4451 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4452 id
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
4455 case IPSECDOI_ID_IPV6_ADDR
:
4456 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4457 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4460 ((struct sockaddr
*)&saddr
)->sa_len
= sizeof(struct sockaddr_in6
);
4462 ((struct sockaddr
*)&saddr
)->sa_family
= AF_INET6
;
4463 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4464 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4465 id
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
4466 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4467 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4468 ? ((struct sockaddr_in6
*)id_b
)->sin6_scope_id
4474 switch (id_b
->type
) {
4475 case IPSECDOI_ID_IPV4_ADDR
:
4477 case IPSECDOI_ID_IPV6_ADDR
:
4479 len
= snprintf( buf
, sizeof(buf
), "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4482 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4484 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4489 int alen
= sizeof(struct in_addr
);
4491 switch (id_b
->type
) {
4492 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4493 alen
= sizeof(struct in_addr
);
4496 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4497 alen
= sizeof(struct in6_addr
);
4508 /* get subnet mask length */
4512 p
= (unsigned char *) id
->v
4513 + sizeof(struct ipsecdoi_id_b
)
4516 for (; *p
== 0xff; p
++) {
4535 len
= snprintf( buf
, sizeof(buf
), "%s/%i", saddrwop2str((struct sockaddr
*)&saddr
), plen
);
4539 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
4541 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4544 ((struct sockaddr
*)&saddr
)->sa_len
= sizeof(struct sockaddr_in
);
4546 ((struct sockaddr
*)&saddr
)->sa_family
= AF_INET
;
4547 ((struct sockaddr_in
*)&saddr
)->sin_port
= IPSEC_PORT_ANY
;
4548 memcpy(&((struct sockaddr_in
*)&saddr
)->sin_addr
,
4549 id
->v
+ sizeof(*id_b
) + sizeof(struct in_addr
),
4550 sizeof(struct in_addr
));
4553 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4559 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
4561 len
= snprintf( buf
, sizeof(buf
), "%s-", saddrwop2str((struct sockaddr
*)&saddr
));
4564 ((struct sockaddr
*)&saddr
)->sa_len
= sizeof(struct sockaddr_in6
);
4566 ((struct sockaddr
*)&saddr
)->sa_family
= AF_INET6
;
4567 ((struct sockaddr_in6
*)&saddr
)->sin6_port
= IPSEC_PORT_ANY
;
4568 memcpy(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
,
4569 id
->v
+ sizeof(*id_b
) + sizeof(struct in6_addr
),
4570 sizeof(struct in6_addr
));
4571 ((struct sockaddr_in6
*)&saddr
)->sin6_scope_id
=
4572 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)&saddr
)->sin6_addr
)
4573 ? ((struct sockaddr_in6
*)id_b
)->sin6_scope_id
4577 len
+= snprintf( buf
+ len
, sizeof(buf
) - len
, "%s", saddrwop2str((struct sockaddr
*)&saddr
));
4583 case IPSECDOI_ID_FQDN
:
4584 case IPSECDOI_ID_USER_FQDN
:
4585 len
= id
->l
- sizeof(*id_b
);
4588 memcpy(buf
, id
->v
+ sizeof(*id_b
), len
);
4591 case IPSECDOI_ID_DER_ASN1_DN
:
4592 case IPSECDOI_ID_DER_ASN1_GN
:
4594 X509_NAME
*xn
= NULL
;
4596 dat
= id
->v
+ sizeof(*id_b
);
4597 len
= id
->l
- sizeof(*id_b
);
4599 if (d2i_X509_NAME(&xn
, (void*) &dat
, len
) != NULL
) {
4600 BIO
*bio
= BIO_new(BIO_s_mem());
4601 X509_NAME_print_ex(bio
, xn
, 0, 0);
4602 len
= BIO_get_mem_data(bio
, &dat
);
4605 memcpy(buf
,dat
,len
);
4609 plog(LLV_ERROR
, LOCATION
, NULL
,
4610 "unable to extract asn1dn from id\n");
4612 len
= snprintf(buf
, sizeof(buf
), "<ASN1-DN>");
4618 /* currently unhandled id types */
4619 case IPSECDOI_ID_KEY_ID
:
4620 len
= snprintf( buf
, sizeof(buf
), "<KEY-ID>");
4624 plog(LLV_ERROR
, LOCATION
, NULL
,
4625 "unknown ID type %d\n", id_b
->type
);
4629 len
= snprintf( buf
, sizeof(buf
), "<?>");
4631 ret
= racoon_malloc(len
+1);
4633 memcpy(ret
,buf
,len
);
4641 * set IPsec data attributes into a proposal.
4642 * NOTE: MUST called per a transform.
4645 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4646 struct isakmp_pl_t
*t
;
4651 struct isakmp_data
*d
, *prev
;
4657 tr
->trns_no
= t
->t_no
;
4658 tr
->trns_id
= t
->t_id
;
4660 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4661 prev
= (struct isakmp_data
*)NULL
;
4662 d
= (struct isakmp_data
*)(t
+ 1);
4665 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4666 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4668 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4672 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4673 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4675 plog(LLV_DEBUG
, LOCATION
, NULL
,
4676 "type=%s, flag=0x%04x, lorv=%s\n",
4677 s_ipsecdoi_attr(type
), flag
,
4678 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4681 case IPSECDOI_ATTR_SA_LD_TYPE
:
4683 int type
= ntohs(d
->lorv
);
4685 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4686 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4690 plog(LLV_WARNING
, LOCATION
, NULL
,
4691 "invalid life duration type. "
4693 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4698 case IPSECDOI_ATTR_SA_LD
:
4700 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4701 IPSECDOI_ATTR_SA_LD_TYPE
) {
4702 plog(LLV_ERROR
, LOCATION
, NULL
,
4703 "life duration must follow ltype\n");
4709 vchar_t
*ld_buf
= NULL
;
4712 /* i.e. ISAKMP_GEN_TV */
4713 ld_buf
= vmalloc(sizeof(d
->lorv
));
4714 if (ld_buf
== NULL
) {
4715 plog(LLV_ERROR
, LOCATION
, NULL
,
4716 "failed to get LD buffer.\n");
4719 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4721 int len
= ntohs(d
->lorv
);
4722 /* i.e. ISAKMP_GEN_TLV */
4723 ld_buf
= vmalloc(len
);
4724 if (ld_buf
== NULL
) {
4725 plog(LLV_ERROR
, LOCATION
, NULL
,
4726 "failed to get LD buffer.\n");
4729 memcpy(ld_buf
->v
, d
+ 1, len
);
4732 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4733 t
= ipsecdoi_set_ld(ld_buf
);
4736 plog(LLV_ERROR
, LOCATION
, NULL
,
4737 "invalid life duration.\n");
4740 /* lifetime must be equal in a proposal. */
4741 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4743 else if (pp
->lifetime
!= t
) {
4744 plog(LLV_ERROR
, LOCATION
, NULL
,
4745 "lifetime mismatched "
4747 "prev:%ld curr:%u.\n",
4748 (long)pp
->lifetime
, t
);
4752 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4753 t
= ipsecdoi_set_ld(ld_buf
);
4756 plog(LLV_ERROR
, LOCATION
, NULL
,
4757 "invalid life duration.\n");
4760 /* lifebyte must be equal in a proposal. */
4761 if (pp
->lifebyte
== 0)
4763 else if (pp
->lifebyte
!= t
) {
4764 plog(LLV_ERROR
, LOCATION
, NULL
,
4765 "lifebyte mismatched "
4767 "prev:%d curr:%u.\n",
4774 plog(LLV_ERROR
, LOCATION
, NULL
,
4775 "invalid life type: %d\n", life_t
);
4781 case IPSECDOI_ATTR_GRP_DESC
:
4783 * RFC2407: 4.5 IPSEC Security Association Attributes
4784 * Specifies the Oakley Group to be used in a PFS QM
4785 * negotiation. For a list of supported values, see
4786 * Appendix A of [IKE].
4788 if (pp
->pfs_group
== 0)
4789 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4790 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4791 plog(LLV_ERROR
, LOCATION
, NULL
,
4792 "pfs_group mismatched "
4793 "in a proposal.\n");
4798 case IPSECDOI_ATTR_ENC_MODE
:
4800 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4801 plog(LLV_ERROR
, LOCATION
, NULL
,
4802 "multiple encmode exist "
4803 "in a transform.\n");
4806 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4809 case IPSECDOI_ATTR_AUTH
:
4810 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4811 plog(LLV_ERROR
, LOCATION
, NULL
,
4812 "multiple authtype exist "
4813 "in a transform.\n");
4816 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4819 case IPSECDOI_ATTR_KEY_LENGTH
:
4820 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4821 plog(LLV_ERROR
, LOCATION
, NULL
,
4822 "key length defined but not ESP");
4825 tr
->encklen
= ntohs(d
->lorv
);
4828 case IPSECDOI_ATTR_KEY_ROUNDS
:
4829 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4830 case IPSECDOI_ATTR_COMP_PRIVALG
:
4838 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4840 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4841 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4851 ipsecdoi_authalg2trnsid(alg
)
4855 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4856 return IPSECDOI_AH_MD5
;
4857 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4858 return IPSECDOI_AH_SHA
;
4859 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4860 return IPSECDOI_AH_SHA256
;
4861 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4862 return IPSECDOI_AH_SHA384
;
4863 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4864 return IPSECDOI_AH_SHA512
;
4865 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4866 return IPSECDOI_AH_DES
;
4867 case IPSECDOI_ATTR_AUTH_KPDK
:
4868 return IPSECDOI_AH_MD5
; /* XXX */
4870 plog(LLV_ERROR
, LOCATION
, NULL
,
4871 "invalid authentication algorithm:%d\n", alg
);
4878 fixup_initiator_sa(match
, received
)
4879 struct isakmpsa
*match
, *received
;
4881 if (received
->gssid
!= NULL
)
4882 match
->gssid
= vdup(received
->gssid
);
4888 static int rm_idtype2doi
[] = {
4889 255, /* IDTYPE_UNDEFINED, 0 */
4890 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4891 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4892 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4893 255, /* IDTYPE_ADDRESS, 4
4894 * it expands into 4 types by another function. */
4895 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4899 * convert idtype to DOI value.
4907 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4908 return rm_idtype2doi
[idtype
];
4917 case IPSECDOI_ID_FQDN
:
4918 return(IDTYPE_FQDN
);
4919 case IPSECDOI_ID_USER_FQDN
:
4920 return(IDTYPE_USERFQDN
);
4921 case IPSECDOI_ID_KEY_ID
:
4922 return(IDTYPE_KEYID
);
4923 case IPSECDOI_ID_DER_ASN1_DN
:
4924 return(IDTYPE_ASN1DN
);
4925 case IPSECDOI_ID_IPV4_ADDR
:
4926 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4927 case IPSECDOI_ID_IPV6_ADDR
:
4928 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4929 return(IDTYPE_ADDRESS
);
4931 plog(LLV_WARNING
, LOCATION
, NULL
,
4932 "Inproper idtype:%s in this function.\n",
4933 s_ipsecdoi_ident(doi
));
4934 return(IDTYPE_ADDRESS
); /* XXX */
4939 #ifdef ENABLE_HYBRID
4941 switch_authmethod(authmethod
)
4944 switch(authmethod
) {
4945 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
4946 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
;
4948 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
4949 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
;
4951 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
4952 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
;
4954 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
4955 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
;
4957 /* Those are not implemented */
4958 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
4959 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
;
4961 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
4962 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
;
4964 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
4965 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
;