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
);
279 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
286 if (sa
->gssid
!= NULL
)
287 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id in new sa '%.*s'\n",
288 sa
->gssid
->l
, sa
->gssid
->v
);
289 if (iph1
-> side
== INITIATOR
) {
290 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
291 iph1
->gi_i
= vdup(iph1
->rmconf
->proposal
->gssid
);
292 if (tsa
.gssid
!= NULL
)
293 iph1
->gi_r
= vdup(tsa
.gssid
);
294 iph1
->approval
= fixup_initiator_sa(sa
, &tsa
);
296 if (tsa
.gssid
!= NULL
) {
297 iph1
->gi_r
= vdup(tsa
.gssid
);
298 iph1
->gi_i
= gssapi_get_id(iph1
);
299 if (sa
->gssid
== NULL
&& iph1
->gi_i
!= NULL
)
300 sa
->gssid
= vdup(iph1
->gi_i
);
304 if (iph1
->gi_i
!= NULL
)
305 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIi is %.*s\n",
306 iph1
->gi_i
->l
, iph1
->gi_i
->v
);
307 if (iph1
->gi_r
!= NULL
)
308 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIr is %.*s\n",
309 iph1
->gi_r
->l
, iph1
->gi_r
->v
);
314 newsa
= get_sabyproppair(p
, iph1
);
316 delisakmpsa(iph1
->approval
);
317 iph1
->approval
= NULL
;
324 * compare peer's single proposal and all of my proposal.
325 * and select one if suiatable.
326 * p : one of peer's proposal.
327 * proposal: my proposals.
329 static struct isakmpsa
*
330 get_ph1approvalx(p
, proposal
, sap
, check_level
)
332 struct isakmpsa
*proposal
, *sap
;
335 struct isakmp_pl_p
*prop
= p
->prop
;
336 struct isakmp_pl_t
*trns
= p
->trns
;
337 struct isakmpsa sa
, *s
, *tsap
;
340 plog(LLV_DEBUG
, LOCATION
, NULL
,
341 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
342 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
343 prop
->spi_size
, prop
->num_t
);
345 plog(LLV_DEBUG
, LOCATION
, NULL
,
346 "trns#=%d, trns-id=%s\n",
348 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
350 tsap
= sap
!= NULL
? sap
: &sa
;
352 memset(tsap
, 0, sizeof(*tsap
));
353 if (t2isakmpsa(trns
, tsap
) < 0)
355 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
357 authmethod
= switch_authmethod(s
->authmethod
);
359 authmethod
= s
->authmethod
;
361 plog(LLV_DEBUG
, LOCATION
, NULL
, "Compared: DB:Peer\n");
362 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifetime = %ld:%ld)\n",
363 (long)s
->lifetime
, (long)tsap
->lifetime
);
364 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifebyte = %zu:%zu)\n",
365 s
->lifebyte
, tsap
->lifebyte
);
366 plog(LLV_DEBUG
, LOCATION
, NULL
, "enctype = %s:%s\n",
367 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
369 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
371 plog(LLV_DEBUG
, LOCATION
, NULL
, "(encklen = %d:%d)\n",
372 s
->encklen
, tsap
->encklen
);
373 plog(LLV_DEBUG
, LOCATION
, NULL
, "hashtype = %s:%s\n",
374 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
376 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
378 plog(LLV_DEBUG
, LOCATION
, NULL
, "authmethod = %s:%s\n",
379 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
381 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
383 plog(LLV_DEBUG
, LOCATION
, NULL
, "dh_group = %s:%s\n",
384 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
386 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
389 /* XXX to be considered ? */
390 if (tsap
->lifebyte
> s
->lifebyte
) ;
393 * if responder side and peer's key length in proposal
394 * is bigger than mine, it might be accepted.
396 if(tsap
->enctype
== s
->enctype
&&
397 tsap
->authmethod
== authmethod
&&
398 tsap
->hashtype
== s
->hashtype
&&
399 tsap
->dh_group
== s
->dh_group
&&
400 tsap
->encklen
== s
->encklen
) {
401 switch(check_level
) {
402 case PROP_CHECK_OBEY
:
406 case PROP_CHECK_STRICT
:
407 if ((tsap
->lifetime
> s
->lifetime
) ||
408 (tsap
->lifebyte
> s
->lifebyte
))
413 case PROP_CHECK_CLAIM
:
414 if (tsap
->lifetime
< s
->lifetime
)
415 s
->lifetime
= tsap
->lifetime
;
416 if (tsap
->lifebyte
< s
->lifebyte
)
417 s
->lifebyte
= tsap
->lifebyte
;
421 case PROP_CHECK_EXACT
:
422 if ((tsap
->lifetime
!= s
->lifetime
) ||
423 (tsap
->lifebyte
!= s
->lifebyte
))
429 plog(LLV_ERROR
, LOCATION
, NULL
,
430 "Unexpected proposal_check value\n");
438 if (tsap
->dhgrp
!= NULL
)
439 oakley_dhgrp_free(tsap
->dhgrp
);
441 if ((s
= dupisakmpsa(s
)) != NULL
) {
442 switch(check_level
) {
443 case PROP_CHECK_OBEY
:
444 s
->lifetime
= tsap
->lifetime
;
445 s
->lifebyte
= tsap
->lifebyte
;
448 case PROP_CHECK_STRICT
:
449 s
->lifetime
= tsap
->lifetime
;
450 s
->lifebyte
= tsap
->lifebyte
;
453 case PROP_CHECK_CLAIM
:
454 if (tsap
->lifetime
< s
->lifetime
)
455 s
->lifetime
= tsap
->lifetime
;
456 if (tsap
->lifebyte
< s
->lifebyte
)
457 s
->lifebyte
= tsap
->lifebyte
;
469 * print all of items in peer's proposal which are mismatched to my proposal.
470 * p : one of peer's proposal.
471 * proposal: my proposals.
474 print_ph1mismatched(p
, proposal
)
476 struct isakmpsa
*proposal
;
478 struct isakmpsa sa
, *s
;
480 memset(&sa
, 0, sizeof(sa
));
481 if (t2isakmpsa(p
->trns
, &sa
) < 0)
483 for (s
= proposal
; s
; s
= s
->next
) {
484 if (sa
.enctype
!= s
->enctype
) {
485 plog(LLV_ERROR
, LOCATION
, NULL
,
487 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
489 s
->prop_no
, s
->trns_no
,
490 p
->prop
->p_no
, p
->trns
->t_no
,
491 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
493 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
496 if (sa
.authmethod
!= s
->authmethod
) {
497 plog(LLV_ERROR
, LOCATION
, NULL
,
498 "rejected authmethod: "
499 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
501 s
->prop_no
, s
->trns_no
,
502 p
->prop
->p_no
, p
->trns
->t_no
,
503 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
505 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
508 if (sa
.hashtype
!= s
->hashtype
) {
509 plog(LLV_ERROR
, LOCATION
, NULL
,
510 "rejected hashtype: "
511 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
513 s
->prop_no
, s
->trns_no
,
514 p
->prop
->p_no
, p
->trns
->t_no
,
515 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
517 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
520 if (sa
.dh_group
!= s
->dh_group
) {
521 plog(LLV_ERROR
, LOCATION
, NULL
,
522 "rejected dh_group: "
523 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
525 s
->prop_no
, s
->trns_no
,
526 p
->prop
->p_no
, p
->trns
->t_no
,
527 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
529 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
534 if (sa
.dhgrp
!= NULL
)
535 oakley_dhgrp_free(sa
.dhgrp
);
539 * get ISAKMP data attributes
543 struct isakmp_pl_t
*trns
;
546 struct isakmp_data
*d
, *prev
;
555 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
556 prev
= (struct isakmp_data
*)NULL
;
557 d
= (struct isakmp_data
*)(trns
+ 1);
560 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
561 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
563 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
569 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
570 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
572 plog(LLV_DEBUG
, LOCATION
, NULL
,
573 "type=%s, flag=0x%04x, lorv=%s\n",
574 s_oakley_attr(type
), flag
,
575 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
577 /* get variable-sized item */
579 case OAKLEY_ATTR_GRP_PI
:
580 case OAKLEY_ATTR_GRP_GEN_ONE
:
581 case OAKLEY_ATTR_GRP_GEN_TWO
:
582 case OAKLEY_ATTR_GRP_CURVE_A
:
583 case OAKLEY_ATTR_GRP_CURVE_B
:
584 case OAKLEY_ATTR_SA_LD
:
585 case OAKLEY_ATTR_GRP_ORDER
:
588 p
= (u_char
*)&d
->lorv
;
590 len
= ntohs(d
->lorv
);
591 p
= (u_char
*)(d
+ 1);
596 memcpy(val
->v
, p
, len
);
604 case OAKLEY_ATTR_ENC_ALG
:
605 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
608 case OAKLEY_ATTR_HASH_ALG
:
609 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
612 case OAKLEY_ATTR_AUTH_METHOD
:
613 sa
->authmethod
= ntohs(d
->lorv
);
616 case OAKLEY_ATTR_GRP_DESC
:
617 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
620 case OAKLEY_ATTR_GRP_TYPE
:
622 int type
= (int)ntohs(d
->lorv
);
623 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
624 sa
->dhgrp
->type
= type
;
629 case OAKLEY_ATTR_GRP_PI
:
630 sa
->dhgrp
->prime
= val
;
633 case OAKLEY_ATTR_GRP_GEN_ONE
:
636 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
638 int len
= ntohs(d
->lorv
);
642 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
643 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
647 case OAKLEY_ATTR_GRP_GEN_TWO
:
650 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
652 int len
= ntohs(d
->lorv
);
656 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
657 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
661 case OAKLEY_ATTR_GRP_CURVE_A
:
662 sa
->dhgrp
->curve_a
= val
;
665 case OAKLEY_ATTR_GRP_CURVE_B
:
666 sa
->dhgrp
->curve_b
= val
;
669 case OAKLEY_ATTR_SA_LD_TYPE
:
671 int type
= (int)ntohs(d
->lorv
);
673 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
674 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
678 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
683 case OAKLEY_ATTR_SA_LD
:
685 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
686 OAKLEY_ATTR_SA_LD_TYPE
) {
687 plog(LLV_ERROR
, LOCATION
, NULL
,
688 "life duration must follow ltype\n");
693 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
694 sa
->lifetime
= ipsecdoi_set_ld(val
);
696 if (sa
->lifetime
== 0) {
697 plog(LLV_ERROR
, LOCATION
, NULL
,
698 "invalid life duration.\n");
702 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
703 sa
->lifebyte
= ipsecdoi_set_ld(val
);
705 if (sa
->lifebyte
== 0) {
706 plog(LLV_ERROR
, LOCATION
, NULL
,
707 "invalid life duration.\n");
713 plog(LLV_ERROR
, LOCATION
, NULL
,
714 "invalid life type: %d\n", life_t
);
719 case OAKLEY_ATTR_KEY_LEN
:
721 int len
= ntohs(d
->lorv
);
723 plog(LLV_ERROR
, LOCATION
, NULL
,
724 "keylen %d: not multiple of 8\n",
728 sa
->encklen
= (u_int16_t
)len
;
732 case OAKLEY_ATTR_PRF
:
733 case OAKLEY_ATTR_FIELD_SIZE
:
737 case OAKLEY_ATTR_GRP_ORDER
:
738 sa
->dhgrp
->order
= val
;
741 case OAKLEY_ATTR_GSS_ID
:
744 size_t srcleft
, dstleft
, rv
;
745 __iconv_const
char *src
;
747 int len
= ntohs(d
->lorv
);
750 * Older verions of racoon just placed the
751 * ISO-Latin-1 string on the wire directly.
752 * Check to see if we are configured to be
753 * compatible with this behavior.
755 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
756 sa
->gssid
= vmalloc(len
);
757 memcpy(sa
->gssid
->v
, d
+ 1, len
);
758 plog(LLV_DEBUG
, LOCATION
, NULL
,
759 "received old-style gss id '%.*s' (len %d)\n",
760 sa
->gssid
->l
, sa
->gssid
->v
, sa
->gssid
->l
);
765 * For Windows 2000 compatibility, we expect
766 * the GSS ID attribute on the wire to be
767 * encoded in UTF-16LE. Internally, we work
768 * in ISO-Latin-1. Therefore, we should need
769 * 1/2 the specified length, which should always
770 * be a multiple of 2 octets.
772 cd
= iconv_open("latin1", "utf-16le");
773 if (cd
== (iconv_t
) -1) {
774 plog(LLV_ERROR
, LOCATION
, NULL
,
775 "unable to initialize utf-16le -> latin1 "
776 "conversion descriptor: %s\n",
781 sa
->gssid
= vmalloc(len
/ 2);
783 src
= (__iconv_const
char *)(d
+ 1);
789 rv
= iconv(cd
, (__iconv_const
char **)&src
, &srcleft
,
793 plog(LLV_ERROR
, LOCATION
, NULL
,
794 "unable to convert GSS ID from "
795 "utf-16le -> latin1: %s\n",
798 plog(LLV_ERROR
, LOCATION
, NULL
,
799 "%zd character%s in GSS ID cannot "
800 "be represented in latin1\n",
801 rv
, rv
== 1 ? "" : "s");
803 (void) iconv_close(cd
);
808 (void) iconv_close(cd
);
810 /* XXX dstleft should always be 0; assert it? */
811 sa
->gssid
->l
= (len
/ 2) - dstleft
;
813 plog(LLV_DEBUG
, LOCATION
, NULL
,
814 "received gss id '%.*s' (len %d)\n",
815 sa
->gssid
->l
, sa
->gssid
->v
, sa
->gssid
->l
);
818 #endif /* HAVE_GSSAPI */
827 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
829 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
830 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
834 /* key length must not be specified on some algorithms */
836 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
837 #ifdef HAVE_OPENSSL_IDEA_H
838 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_IDEA
840 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
841 plog(LLV_ERROR
, LOCATION
, NULL
,
842 "keylen must not be specified "
843 "for encryption algorithm %d\n",
856 * check phase 2 SA payload and select single proposal.
857 * make new SA payload to be replyed not including general header.
858 * This function is called by responder only.
864 ipsecdoi_selectph2proposal(iph2
)
865 struct ph2handle
*iph2
;
867 struct prop_pair
**pair
;
868 struct prop_pair
*ret
;
870 /* get proposal pair */
871 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
875 /* check and select a proposal. */
876 ret
= get_ph2approval(iph2
, pair
);
881 /* make a SA to be replayed. */
882 /* SPI must be updated later. */
883 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
885 if (iph2
->sa_ret
== NULL
)
892 * check phase 2 SA payload returned from responder.
893 * This function is called by initiator only.
899 ipsecdoi_checkph2proposal(iph2
)
900 struct ph2handle
*iph2
;
902 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
906 vchar_t
*sa_ret
= NULL
;
908 /* get proposal pair of SA sent. */
909 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
911 plog(LLV_ERROR
, LOCATION
, NULL
,
912 "failed to get prop pair.\n");
916 /* XXX should check the number of transform */
918 /* get proposal pair of SA replayed */
919 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
921 plog(LLV_ERROR
, LOCATION
, NULL
,
922 "failed to get prop pair.\n");
926 /* check proposal is only one ? */
929 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
936 plog(LLV_ERROR
, LOCATION
, NULL
,
937 "no proposal received.\n");
941 plog(LLV_ERROR
, LOCATION
, NULL
,
942 "some proposals received.\n");
946 if (spair
[n
] == NULL
) {
947 plog(LLV_WARNING
, LOCATION
, NULL
,
948 "invalid proposal number:%d received.\n", i
);
952 if (rpair
[n
]->tnext
!= NULL
) {
953 plog(LLV_ERROR
, LOCATION
, NULL
,
954 "multi transforms replyed.\n");
958 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
959 plog(LLV_ERROR
, LOCATION
, NULL
,
960 "proposal mismathed.\n");
965 * check and select a proposal.
966 * ensure that there is no modification of the proposal by
969 p
= get_ph2approval(iph2
, rpair
);
973 /* make a SA to be replayed. */
974 sa_ret
= iph2
->sa_ret
;
975 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
977 if (iph2
->sa_ret
== NULL
)
984 free_proppair(rpair
);
986 free_proppair(spair
);
994 * compare two prop_pair which is assumed to have same proposal number.
995 * the case of bundle or single SA, NOT multi transforms.
996 * a: a proposal that is multi protocols and single transform, usually replyed.
997 * b: a proposal that is multi protocols and multi transform, usually sent.
998 * NOTE: this function is for initiator.
1002 * XXX cannot understand the comment!
1005 cmp_aproppair_i(a
, b
)
1006 struct prop_pair
*a
, *b
;
1008 struct prop_pair
*p
, *q
, *r
;
1011 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
1012 for (r
= q
; r
; r
= r
->tnext
) {
1014 if (p
->trns
->t_no
== r
->trns
->t_no
)
1018 /* no suitable transform found */
1019 plog(LLV_ERROR
, LOCATION
, NULL
,
1020 "no suitable transform found.\n");
1025 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
1026 plog(LLV_WARNING
, LOCATION
, NULL
,
1027 "proposal #%d mismatched, "
1029 r
->prop
->p_no
, p
->prop
->p_no
);
1033 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
1034 plog(LLV_ERROR
, LOCATION
, NULL
,
1035 "proto_id mismathed: my:%d peer:%d\n",
1036 r
->prop
->proto_id
, p
->prop
->proto_id
);
1040 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
1041 plog(LLV_ERROR
, LOCATION
, NULL
,
1042 "invalid spi size: %d.\n",
1047 /* check #of transforms */
1048 if (p
->prop
->num_t
!= 1) {
1049 plog(LLV_WARNING
, LOCATION
, NULL
,
1050 "#of transform is %d, "
1051 "but expected 1.\n", p
->prop
->num_t
);
1055 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
1056 plog(LLV_WARNING
, LOCATION
, NULL
,
1057 "transform number has been modified.\n");
1060 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
1061 plog(LLV_WARNING
, LOCATION
, NULL
,
1062 "reserved field should be zero.\n");
1066 /* compare attribute */
1067 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
1068 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
1069 plog(LLV_WARNING
, LOCATION
, NULL
,
1070 "attribute has been modified.\n");
1074 if ((p
&& !q
) || (!p
&& q
)) {
1075 /* # of protocols mismatched */
1076 plog(LLV_ERROR
, LOCATION
, NULL
,
1077 "#of protocols mismatched.\n");
1085 * acceptable check for policy configuration.
1086 * return a new SA payload to be reply to peer.
1088 static struct prop_pair
*
1089 get_ph2approval(iph2
, pair
)
1090 struct ph2handle
*iph2
;
1091 struct prop_pair
**pair
;
1093 struct prop_pair
*ret
;
1096 iph2
->approval
= NULL
;
1098 plog(LLV_DEBUG
, LOCATION
, NULL
,
1099 "begin compare proposals.\n");
1101 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1102 if (pair
[i
] == NULL
)
1104 plog(LLV_DEBUG
, LOCATION
, NULL
,
1105 "pair[%d]: %p\n", i
, pair
[i
]);
1106 print_proppair(LLV_DEBUG
, pair
[i
]);;
1108 /* compare proposal and select one */
1109 ret
= get_ph2approvalx(iph2
, pair
[i
]);
1116 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable policy found.\n");
1122 * compare my proposal and peers just one proposal.
1125 static struct prop_pair
*
1126 get_ph2approvalx(iph2
, pp
)
1127 struct ph2handle
*iph2
;
1128 struct prop_pair
*pp
;
1130 struct prop_pair
*ret
= NULL
;
1131 struct saprop
*pr0
, *pr
= NULL
;
1132 struct saprop
*q1
, *q2
;
1134 pr0
= aproppair2saprop(pp
);
1138 for (q1
= pr0
; q1
; q1
= q1
->next
) {
1139 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
1140 plog(LLV_DEBUG
, LOCATION
, NULL
,
1141 "peer's single bundle:\n");
1142 printsaprop0(LLV_DEBUG
, q1
);
1143 plog(LLV_DEBUG
, LOCATION
, NULL
,
1144 "my single bundle:\n");
1145 printsaprop0(LLV_DEBUG
, q2
);
1147 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1151 plog(LLV_ERROR
, LOCATION
, NULL
,
1155 /* no proposal matching */
1162 plog(LLV_DEBUG
, LOCATION
, NULL
, "matched\n");
1163 iph2
->approval
= pr
;
1167 struct prop_pair
*p
, *n
, *x
;
1171 for (p
= pp
; p
; p
= p
->next
) {
1173 * find a proposal with matching proto_id.
1174 * we have analyzed validity already, in cmpsaprop_alloc().
1176 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1177 if (sp
->proto_id
== p
->prop
->proto_id
)
1185 for (x
= p
; x
; x
= x
->tnext
)
1186 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1191 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1193 plog(LLV_ERROR
, LOCATION
, NULL
,
1194 "failed to get buffer.\n");
1201 /* need to preserve the order */
1202 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1204 if (x
&& x
->prop
== n
->prop
) {
1205 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1216 /* #of transforms should be updated ? */
1225 struct prop_pair
**pair
;
1229 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1230 free_proppair0(pair
[i
]);
1237 free_proppair0(pair
)
1238 struct prop_pair
*pair
;
1240 struct prop_pair
*p
, *q
, *r
, *s
;
1256 * get proposal pairs from SA payload.
1257 * tiny check for proposal payload.
1260 get_proppair(sa
, mode
)
1264 struct prop_pair
**pair
;
1265 int num_p
= 0; /* number of proposal for use */
1269 struct ipsecdoi_sa_b
*sab
= (struct ipsecdoi_sa_b
*)sa
->v
;
1271 plog(LLV_DEBUG
, LOCATION
, NULL
, "total SA len=%zu\n", sa
->l
);
1272 plogdump(LLV_DEBUG
, sa
->v
, sa
->l
);
1274 /* check SA payload size */
1275 if (sa
->l
< sizeof(*sab
)) {
1276 plog(LLV_ERROR
, LOCATION
, NULL
,
1277 "Invalid SA length = %zu.\n", sa
->l
);
1282 if (check_doi(ntohl(sab
->doi
)) < 0)
1285 /* check SITUATION */
1286 if (check_situation(ntohl(sab
->sit
)) < 0)
1289 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1291 plog(LLV_ERROR
, LOCATION
, NULL
,
1292 "failed to get buffer.\n");
1295 memset(pair
, 0, sizeof(pair
));
1297 bp
= (caddr_t
)(sab
+ 1);
1298 tlen
= sa
->l
- sizeof(*sab
);
1301 struct isakmp_pl_p
*prop
;
1303 vchar_t
*pbuf
= NULL
;
1304 struct isakmp_parse_t
*pa
;
1306 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1310 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1311 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1313 /* check the value of next payload */
1314 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1315 plog(LLV_ERROR
, LOCATION
, NULL
,
1316 "Invalid payload type=%u\n", pa
->type
);
1321 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1324 plog(LLV_DEBUG
, LOCATION
, NULL
,
1325 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1328 plog(LLV_ERROR
, LOCATION
, NULL
,
1329 "invalid proposal with length %d\n", proplen
);
1334 /* check Protocol ID */
1335 if (!check_protocol
[mode
]) {
1336 plog(LLV_ERROR
, LOCATION
, NULL
,
1337 "unsupported mode %d\n", mode
);
1341 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1344 /* check SPI length when IKE. */
1345 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1349 if (get_transform(prop
, pair
, &num_p
) < 0) {
1360 struct prop_pair
*p
, *q
;
1362 /* check for proposals with no transforms */
1363 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1367 plog(LLV_DEBUG
, LOCATION
, NULL
, "pair %d:\n", i
);
1368 print_proppair(LLV_DEBUG
, pair
[i
]);
1370 notrans
= nprop
= 0;
1371 for (p
= pair
[i
]; p
; p
= p
->next
) {
1372 if (p
->trns
== NULL
) {
1376 for (q
= p
; q
; q
= q
->tnext
)
1382 * XXX at this moment, we cannot accept proposal group
1383 * with multiple proposals. this should be fixed.
1385 if (pair
[i
]->next
) {
1386 plog(LLV_WARNING
, LOCATION
, NULL
,
1387 "proposal #%u ignored "
1388 "(multiple proposal not supported)\n",
1389 pair
[i
]->prop
->p_no
);
1395 for (p
= pair
[i
]; p
; p
= q
) {
1402 plog(LLV_DEBUG
, LOCATION
, NULL
,
1403 "proposal #%u: %d transform\n",
1404 pair
[i
]->prop
->p_no
, nprop
);
1409 /* bark if no proposal is found. */
1411 plog(LLV_ERROR
, LOCATION
, NULL
,
1412 "no Proposal found.\n");
1420 * check transform payload.
1422 * positive: return the pointer to the payload of valid transform.
1423 * 0 : No valid transform found.
1426 get_transform(prop
, pair
, num_p
)
1427 struct isakmp_pl_p
*prop
;
1428 struct prop_pair
**pair
;
1431 int tlen
; /* total length of all transform in a proposal */
1433 struct isakmp_pl_t
*trns
;
1435 vchar_t
*pbuf
= NULL
;
1436 struct isakmp_parse_t
*pa
;
1437 struct prop_pair
*p
= NULL
, *q
;
1440 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1441 tlen
= ntohs(prop
->h
.len
)
1442 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1443 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1447 /* check and get transform for use */
1449 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1450 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1455 /* check the value of next payload */
1456 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1457 plog(LLV_ERROR
, LOCATION
, NULL
,
1458 "Invalid payload type=%u\n", pa
->type
);
1462 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1465 plog(LLV_DEBUG
, LOCATION
, NULL
,
1466 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1468 /* check transform ID */
1469 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1470 plog(LLV_WARNING
, LOCATION
, NULL
,
1471 "unsupported proto_id %u\n",
1475 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1476 plog(LLV_WARNING
, LOCATION
, NULL
,
1477 "unsupported proto_id %u\n",
1482 if (!check_transform
[prop
->proto_id
]
1483 || !check_attributes
[prop
->proto_id
]) {
1484 plog(LLV_WARNING
, LOCATION
, NULL
,
1485 "unsupported proto_id %u\n",
1489 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1492 /* check data attributes */
1493 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1496 p
= racoon_calloc(1, sizeof(*p
));
1498 plog(LLV_ERROR
, LOCATION
, NULL
,
1499 "failed to get buffer.\n");
1506 /* need to preserve the order */
1507 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1509 if (q
&& q
->prop
== p
->prop
) {
1510 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1517 pair
[prop
->p_no
] = p
;
1529 * make a new SA payload from prop_pair.
1530 * NOTE: this function make spi value clear.
1533 get_sabyproppair(pair
, iph1
)
1534 struct prop_pair
*pair
;
1535 struct ph1handle
*iph1
;
1539 u_int8_t
*np_p
= NULL
;
1540 struct prop_pair
*p
;
1541 int prophlen
, trnslen
;
1544 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1545 for (p
= pair
; p
; p
= p
->next
) {
1546 newtlen
+= sizeof(struct isakmp_pl_p
);
1547 newtlen
+= p
->prop
->spi_size
;
1548 newtlen
+= ntohs(p
->trns
->h
.len
);
1551 newsa
= vmalloc(newtlen
);
1552 if (newsa
== NULL
) {
1553 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1558 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1560 /* update some of values in SA header */
1561 ((struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1562 ((struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1563 bp
+= sizeof(struct ipsecdoi_sa_b
);
1565 /* create proposal payloads */
1566 for (p
= pair
; p
; p
= p
->next
) {
1567 prophlen
= sizeof(struct isakmp_pl_p
)
1568 + p
->prop
->spi_size
;
1569 trnslen
= ntohs(p
->trns
->h
.len
);
1572 *np_p
= ISAKMP_NPTYPE_P
;
1574 /* create proposal */
1576 memcpy(bp
, p
->prop
, prophlen
);
1577 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1578 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1579 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1580 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1581 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1584 /* create transform */
1585 memcpy(bp
, p
->trns
, trnslen
);
1586 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1587 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1595 * update responder's spi
1598 ipsecdoi_updatespi(iph2
)
1599 struct ph2handle
*iph2
;
1601 struct prop_pair
**pair
, *p
;
1608 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1611 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1615 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1616 /* multiple transform must be filtered by selectph2proposal.*/
1620 pp
= iph2
->approval
;
1622 /* create proposal payloads */
1623 for (p
= pair
[i
]; p
; p
= p
->next
) {
1625 * find a proposal/transform with matching proto_id/t_id.
1626 * we have analyzed validity already, in cmpsaprop_alloc().
1628 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1629 if (p
->prop
->proto_id
== pr
->proto_id
&&
1630 p
->trns
->t_id
== pr
->head
->trns_id
) {
1638 * XXX SPI bits are left-filled, for use with IPComp.
1639 * we should be switching to variable-length spi field...
1641 spi
= (u_int8_t
*)&pr
->spi
;
1642 spi
+= sizeof(pr
->spi
);
1644 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1649 free_proppair(pair
);
1654 * make a new SA payload from prop_pair.
1657 get_sabysaprop(pp0
, sa0
)
1661 struct prop_pair
**pair
;
1664 u_int8_t
*np_p
= NULL
;
1665 struct prop_pair
*p
= NULL
;
1669 int prophlen
, trnslen
;
1672 /* get proposal pair */
1673 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1677 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1678 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1680 if (pair
[pp
->prop_no
] == NULL
)
1683 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1684 newtlen
+= (sizeof(struct isakmp_pl_p
)
1687 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1688 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1689 if (tr
->trns_no
== p
->trns
->t_no
)
1695 newtlen
+= ntohs(p
->trns
->h
.len
);
1700 newsa
= vmalloc(newtlen
);
1701 if (newsa
== NULL
) {
1702 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1707 /* some of values of SA must be updated in the out of this function */
1708 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1709 bp
+= sizeof(struct ipsecdoi_sa_b
);
1711 /* create proposal payloads */
1712 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1714 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1715 prophlen
= sizeof(struct isakmp_pl_p
)
1716 + p
->prop
->spi_size
;
1718 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1719 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1720 if (tr
->trns_no
== p
->trns
->t_no
)
1726 trnslen
= ntohs(p
->trns
->h
.len
);
1729 *np_p
= ISAKMP_NPTYPE_P
;
1731 /* create proposal */
1733 memcpy(bp
, p
->prop
, prophlen
);
1734 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1735 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1736 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1737 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1740 /* create transform */
1741 memcpy(bp
, p
->trns
, trnslen
);
1742 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1743 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1753 * If some error happens then return 0. Although 0 means that lifetime is zero,
1754 * such a value should not be accepted.
1755 * Also 0 of lifebyte should not be included in a packet although 0 means not
1759 ipsecdoi_set_ld(buf
)
1769 ld
= ntohs(*(u_int16_t
*)buf
->v
);
1772 ld
= ntohl(*(u_int32_t
*)buf
->v
);
1775 plog(LLV_ERROR
, LOCATION
, NULL
,
1776 "length %zu of life duration "
1777 "isn't supported.\n", buf
->l
);
1796 plog(LLV_ERROR
, LOCATION
, NULL
,
1797 "invalid value of DOI 0x%08x.\n", doi
);
1807 check_situation(sit
)
1811 case IPSECDOI_SIT_IDENTITY_ONLY
:
1814 case IPSECDOI_SIT_SECRECY
:
1815 case IPSECDOI_SIT_INTEGRITY
:
1816 plog(LLV_ERROR
, LOCATION
, NULL
,
1817 "situation 0x%08x unsupported yet.\n", sit
);
1821 plog(LLV_ERROR
, LOCATION
, NULL
,
1822 "invalid situation 0x%08x.\n", sit
);
1829 * check protocol id in main mode
1832 check_prot_main(proto_id
)
1836 case IPSECDOI_PROTO_ISAKMP
:
1840 plog(LLV_ERROR
, LOCATION
, NULL
,
1841 "Illegal protocol id=%u.\n", proto_id
);
1848 * check protocol id in quick mode
1851 check_prot_quick(proto_id
)
1855 case IPSECDOI_PROTO_IPSEC_AH
:
1856 case IPSECDOI_PROTO_IPSEC_ESP
:
1859 case IPSECDOI_PROTO_IPCOMP
:
1863 plog(LLV_ERROR
, LOCATION
, NULL
,
1864 "invalid protocol id %d.\n", proto_id
);
1871 check_spi_size(proto_id
, size
)
1875 case IPSECDOI_PROTO_ISAKMP
:
1878 plog(LLV_WARNING
, LOCATION
, NULL
,
1879 "SPI size isn't zero, but IKE proposal.\n");
1883 case IPSECDOI_PROTO_IPSEC_AH
:
1884 case IPSECDOI_PROTO_IPSEC_ESP
:
1886 plog(LLV_ERROR
, LOCATION
, NULL
,
1887 "invalid SPI size=%d for IPSEC proposal.\n",
1893 case IPSECDOI_PROTO_IPCOMP
:
1894 if (size
!= 2 && size
!= 4) {
1895 plog(LLV_ERROR
, LOCATION
, NULL
,
1896 "invalid SPI size=%d for IPCOMP proposal.\n",
1910 * check transform ID in ISAKMP.
1913 check_trns_isakmp(t_id
)
1917 case IPSECDOI_KEY_IKE
:
1920 plog(LLV_ERROR
, LOCATION
, NULL
,
1921 "invalid transform-id=%u in proto_id=%u.\n",
1922 t_id
, IPSECDOI_KEY_IKE
);
1929 * check transform ID in AH.
1936 case IPSECDOI_AH_MD5
:
1937 case IPSECDOI_AH_SHA
:
1938 case IPSECDOI_AH_SHA256
:
1939 case IPSECDOI_AH_SHA384
:
1940 case IPSECDOI_AH_SHA512
:
1942 case IPSECDOI_AH_DES
:
1943 plog(LLV_ERROR
, LOCATION
, NULL
,
1944 "not support transform-id=%u in AH.\n", t_id
);
1947 plog(LLV_ERROR
, LOCATION
, NULL
,
1948 "invalid transform-id=%u in AH.\n", t_id
);
1955 * check transform ID in ESP.
1958 check_trns_esp(t_id
)
1962 case IPSECDOI_ESP_DES
:
1963 case IPSECDOI_ESP_3DES
:
1964 case IPSECDOI_ESP_NULL
:
1965 case IPSECDOI_ESP_RC5
:
1966 case IPSECDOI_ESP_CAST
:
1967 case IPSECDOI_ESP_BLOWFISH
:
1968 case IPSECDOI_ESP_AES
:
1969 case IPSECDOI_ESP_TWOFISH
:
1971 case IPSECDOI_ESP_DES_IV32
:
1972 case IPSECDOI_ESP_DES_IV64
:
1973 case IPSECDOI_ESP_IDEA
:
1974 case IPSECDOI_ESP_3IDEA
:
1975 case IPSECDOI_ESP_RC4
:
1976 plog(LLV_ERROR
, LOCATION
, NULL
,
1977 "not support transform-id=%u in ESP.\n", t_id
);
1980 plog(LLV_ERROR
, LOCATION
, NULL
,
1981 "invalid transform-id=%u in ESP.\n", t_id
);
1988 * check transform ID in IPCOMP.
1991 check_trns_ipcomp(t_id
)
1995 case IPSECDOI_IPCOMP_OUI
:
1996 case IPSECDOI_IPCOMP_DEFLATE
:
1997 case IPSECDOI_IPCOMP_LZS
:
2000 plog(LLV_ERROR
, LOCATION
, NULL
,
2001 "invalid transform-id=%u in IPCOMP.\n", t_id
);
2008 * check data attributes in IKE.
2011 check_attr_isakmp(trns
)
2012 struct isakmp_pl_t
*trns
;
2014 struct isakmp_data
*d
;
2019 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2020 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2023 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2024 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2025 lorv
= ntohs(d
->lorv
);
2027 plog(LLV_DEBUG
, LOCATION
, NULL
,
2028 "type=%s, flag=0x%04x, lorv=%s\n",
2029 s_oakley_attr(type
), flag
,
2030 s_oakley_attr_v(type
, lorv
));
2033 * some of the attributes must be encoded in TV.
2034 * see RFC2409 Appendix A "Attribute Classes".
2037 case OAKLEY_ATTR_ENC_ALG
:
2038 case OAKLEY_ATTR_HASH_ALG
:
2039 case OAKLEY_ATTR_AUTH_METHOD
:
2040 case OAKLEY_ATTR_GRP_DESC
:
2041 case OAKLEY_ATTR_GRP_TYPE
:
2042 case OAKLEY_ATTR_SA_LD_TYPE
:
2043 case OAKLEY_ATTR_PRF
:
2044 case OAKLEY_ATTR_KEY_LEN
:
2045 case OAKLEY_ATTR_FIELD_SIZE
:
2046 if (!flag
) { /* TLV*/
2047 plog(LLV_ERROR
, LOCATION
, NULL
,
2048 "oakley attribute %d must be TV.\n",
2055 /* sanity check for TLV. length must be specified. */
2056 if (!flag
&& lorv
== 0) { /*TLV*/
2057 plog(LLV_ERROR
, LOCATION
, NULL
,
2058 "invalid length %d for TLV attribute %d.\n",
2064 case OAKLEY_ATTR_ENC_ALG
:
2065 if (!alg_oakley_encdef_ok(lorv
)) {
2066 plog(LLV_ERROR
, LOCATION
, NULL
,
2067 "invalied encryption algorithm=%d.\n",
2073 case OAKLEY_ATTR_HASH_ALG
:
2074 if (!alg_oakley_hashdef_ok(lorv
)) {
2075 plog(LLV_ERROR
, LOCATION
, NULL
,
2076 "invalied hash algorithm=%d.\n",
2082 case OAKLEY_ATTR_AUTH_METHOD
:
2084 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
2085 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
2086 #ifdef ENABLE_HYBRID
2087 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
:
2089 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
2091 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
2092 #ifdef ENABLE_HYBRID
2093 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
:
2094 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
2095 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
2097 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
2098 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
2099 plog(LLV_ERROR
, LOCATION
, NULL
,
2100 "auth method %d isn't supported.\n",
2104 plog(LLV_ERROR
, LOCATION
, NULL
,
2105 "invalid auth method %d.\n",
2111 case OAKLEY_ATTR_GRP_DESC
:
2112 if (!alg_oakley_dhdef_ok(lorv
)) {
2113 plog(LLV_ERROR
, LOCATION
, NULL
,
2114 "invalid DH group %d.\n",
2120 case OAKLEY_ATTR_GRP_TYPE
:
2122 case OAKLEY_ATTR_GRP_TYPE_MODP
:
2125 plog(LLV_ERROR
, LOCATION
, NULL
,
2126 "unsupported DH group type %d.\n",
2132 case OAKLEY_ATTR_GRP_PI
:
2133 case OAKLEY_ATTR_GRP_GEN_ONE
:
2134 /* sanity checks? */
2137 case OAKLEY_ATTR_GRP_GEN_TWO
:
2138 case OAKLEY_ATTR_GRP_CURVE_A
:
2139 case OAKLEY_ATTR_GRP_CURVE_B
:
2140 plog(LLV_ERROR
, LOCATION
, NULL
,
2141 "attr type=%u isn't supported.\n", type
);
2144 case OAKLEY_ATTR_SA_LD_TYPE
:
2146 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
2147 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
2150 plog(LLV_ERROR
, LOCATION
, NULL
,
2151 "invalid life type %d.\n", lorv
);
2156 case OAKLEY_ATTR_SA_LD
:
2157 /* should check the value */
2160 case OAKLEY_ATTR_PRF
:
2161 case OAKLEY_ATTR_KEY_LEN
:
2164 case OAKLEY_ATTR_FIELD_SIZE
:
2165 plog(LLV_ERROR
, LOCATION
, NULL
,
2166 "attr type=%u isn't supported.\n", type
);
2169 case OAKLEY_ATTR_GRP_ORDER
:
2172 case OAKLEY_ATTR_GSS_ID
:
2176 plog(LLV_ERROR
, LOCATION
, NULL
,
2177 "invalid attribute type %d.\n", type
);
2183 d
= (struct isakmp_data
*)((char *)d
2186 tlen
-= (sizeof(*d
) + lorv
);
2187 d
= (struct isakmp_data
*)((char *)d
2188 + sizeof(*d
) + lorv
);
2196 * check data attributes in IPSEC AH/ESP.
2200 struct isakmp_pl_t
*trns
;
2202 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2206 check_attr_esp(trns
)
2207 struct isakmp_pl_t
*trns
;
2209 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2213 check_attr_ipsec(proto_id
, trns
)
2215 struct isakmp_pl_t
*trns
;
2217 struct isakmp_data
*d
;
2221 int attrseen
[16]; /* XXX magic number */
2223 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2224 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2225 memset(attrseen
, 0, sizeof(attrseen
));
2228 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2229 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2230 lorv
= ntohs(d
->lorv
);
2232 plog(LLV_DEBUG
, LOCATION
, NULL
,
2233 "type=%s, flag=0x%04x, lorv=%s\n",
2234 s_ipsecdoi_attr(type
), flag
,
2235 s_ipsecdoi_attr_v(type
, lorv
));
2237 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2241 case IPSECDOI_ATTR_ENC_MODE
:
2243 plog(LLV_ERROR
, LOCATION
, NULL
,
2244 "must be TV when ENC_MODE.\n");
2249 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2250 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2253 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2254 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2255 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2256 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2257 plog(LLV_DEBUG
, LOCATION
, NULL
,
2258 "UDP encapsulation requested\n");
2262 plog(LLV_ERROR
, LOCATION
, NULL
,
2263 "invalid encryption mode=%u.\n",
2269 case IPSECDOI_ATTR_AUTH
:
2271 plog(LLV_ERROR
, LOCATION
, NULL
,
2272 "must be TV when AUTH.\n");
2277 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2278 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2279 trns
->t_id
!= IPSECDOI_AH_MD5
) {
2281 plog(LLV_ERROR
, LOCATION
, NULL
,
2282 "auth algorithm %u conflicts "
2283 "with transform %u.\n",
2288 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2289 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2290 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2294 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
2295 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2296 if (trns
->t_id
!= IPSECDOI_AH_SHA256
)
2300 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
2301 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2302 if (trns
->t_id
!= IPSECDOI_AH_SHA384
)
2306 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
2307 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2308 if (trns
->t_id
!= IPSECDOI_AH_SHA512
)
2312 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2313 case IPSECDOI_ATTR_AUTH_KPDK
:
2314 plog(LLV_ERROR
, LOCATION
, NULL
,
2315 "auth algorithm %u isn't supported.\n",
2319 plog(LLV_ERROR
, LOCATION
, NULL
,
2320 "invalid auth algorithm=%u.\n",
2326 case IPSECDOI_ATTR_SA_LD_TYPE
:
2328 plog(LLV_ERROR
, LOCATION
, NULL
,
2329 "must be TV when LD_TYPE.\n");
2334 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2335 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2338 plog(LLV_ERROR
, LOCATION
, NULL
,
2339 "invalid life type %d.\n", lorv
);
2344 case IPSECDOI_ATTR_SA_LD
:
2346 /* i.e. ISAKMP_GEN_TV */
2347 plog(LLV_DEBUG
, LOCATION
, NULL
,
2348 "life duration was in TLV.\n");
2350 /* i.e. ISAKMP_GEN_TLV */
2352 plog(LLV_ERROR
, LOCATION
, NULL
,
2353 "invalid length of LD\n");
2359 case IPSECDOI_ATTR_GRP_DESC
:
2361 plog(LLV_ERROR
, LOCATION
, NULL
,
2362 "must be TV when GRP_DESC.\n");
2366 if (!alg_oakley_dhdef_ok(lorv
)) {
2367 plog(LLV_ERROR
, LOCATION
, NULL
,
2368 "invalid group description=%u.\n",
2374 case IPSECDOI_ATTR_KEY_LENGTH
:
2376 plog(LLV_ERROR
, LOCATION
, NULL
,
2377 "must be TV when KEY_LENGTH.\n");
2382 case IPSECDOI_ATTR_KEY_ROUNDS
:
2383 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2384 case IPSECDOI_ATTR_COMP_PRIVALG
:
2385 plog(LLV_ERROR
, LOCATION
, NULL
,
2386 "attr type=%u isn't supported.\n", type
);
2390 plog(LLV_ERROR
, LOCATION
, NULL
,
2391 "invalid attribute type %d.\n", type
);
2397 d
= (struct isakmp_data
*)((char *)d
2400 tlen
-= (sizeof(*d
) + lorv
);
2401 d
= (struct isakmp_data
*)((caddr_t
)d
2402 + sizeof(*d
) + lorv
);
2406 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
&&
2407 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2408 plog(LLV_ERROR
, LOCATION
, NULL
,
2409 "attr AUTH must be present for AH.\n");
2413 if (proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&&
2414 trns
->t_id
== IPSECDOI_ESP_NULL
&&
2415 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2416 plog(LLV_ERROR
, LOCATION
, NULL
,
2417 "attr AUTH must be present for ESP NULL encryption.\n");
2425 check_attr_ipcomp(trns
)
2426 struct isakmp_pl_t
*trns
;
2428 struct isakmp_data
*d
;
2432 int attrseen
[16]; /* XXX magic number */
2434 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2435 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2436 memset(attrseen
, 0, sizeof(attrseen
));
2439 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2440 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2441 lorv
= ntohs(d
->lorv
);
2443 plog(LLV_DEBUG
, LOCATION
, NULL
,
2444 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2447 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2451 case IPSECDOI_ATTR_ENC_MODE
:
2453 plog(LLV_ERROR
, LOCATION
, NULL
,
2454 "must be TV when ENC_MODE.\n");
2459 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2460 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2463 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2464 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2465 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2466 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2467 plog(LLV_DEBUG
, LOCATION
, NULL
,
2468 "UDP encapsulation requested\n");
2472 plog(LLV_ERROR
, LOCATION
, NULL
,
2473 "invalid encryption mode=%u.\n",
2479 case IPSECDOI_ATTR_SA_LD_TYPE
:
2481 plog(LLV_ERROR
, LOCATION
, NULL
,
2482 "must be TV when LD_TYPE.\n");
2487 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2488 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2491 plog(LLV_ERROR
, LOCATION
, NULL
,
2492 "invalid life type %d.\n", lorv
);
2497 case IPSECDOI_ATTR_SA_LD
:
2499 /* i.e. ISAKMP_GEN_TV */
2500 plog(LLV_DEBUG
, LOCATION
, NULL
,
2501 "life duration was in TLV.\n");
2503 /* i.e. ISAKMP_GEN_TLV */
2505 plog(LLV_ERROR
, LOCATION
, NULL
,
2506 "invalid length of LD\n");
2512 case IPSECDOI_ATTR_GRP_DESC
:
2514 plog(LLV_ERROR
, LOCATION
, NULL
,
2515 "must be TV when GRP_DESC.\n");
2519 if (!alg_oakley_dhdef_ok(lorv
)) {
2520 plog(LLV_ERROR
, LOCATION
, NULL
,
2521 "invalid group description=%u.\n",
2527 case IPSECDOI_ATTR_AUTH
:
2528 plog(LLV_ERROR
, LOCATION
, NULL
,
2529 "invalid attr type=%u.\n", type
);
2532 case IPSECDOI_ATTR_KEY_LENGTH
:
2533 case IPSECDOI_ATTR_KEY_ROUNDS
:
2534 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2535 case IPSECDOI_ATTR_COMP_PRIVALG
:
2536 plog(LLV_ERROR
, LOCATION
, NULL
,
2537 "attr type=%u isn't supported.\n", type
);
2541 plog(LLV_ERROR
, LOCATION
, NULL
,
2542 "invalid attribute type %d.\n", type
);
2548 d
= (struct isakmp_data
*)((char *)d
2551 tlen
-= (sizeof(*d
) + lorv
);
2552 d
= (struct isakmp_data
*)((caddr_t
)d
2553 + sizeof(*d
) + lorv
);
2558 if (proto_id
== IPSECDOI_PROTO_IPCOMP
&&
2559 !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2560 plog(LLV_ERROR
, LOCATION
, NULL
,
2561 "attr AUTH must be present for AH.\n", type
);
2571 * create phase1 proposal from remote configuration.
2572 * NOT INCLUDING isakmp general header of SA payload
2575 ipsecdoi_setph1proposal(props
)
2576 struct isakmpsa
*props
;
2581 /* count total size of SA minus isakmp general header */
2582 /* not including isakmp general header of SA payload */
2583 sablen
= sizeof(struct ipsecdoi_sa_b
);
2584 sablen
+= setph1prop(props
, NULL
);
2586 mysa
= vmalloc(sablen
);
2588 plog(LLV_ERROR
, LOCATION
, NULL
,
2589 "failed to allocate my sa buffer\n");
2593 /* create SA payload */
2594 /* not including isakmp general header */
2595 ((struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2596 ((struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2598 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2604 setph1prop(props
, buf
)
2605 struct isakmpsa
*props
;
2608 struct isakmp_pl_p
*prop
= NULL
;
2609 struct isakmpsa
*s
= NULL
;
2610 int proplen
, trnslen
;
2611 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2615 proplen
= sizeof(*prop
);
2617 /* create proposal */
2618 prop
= (struct isakmp_pl_p
*)p
;
2619 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2620 prop
->p_no
= props
->prop_no
;
2621 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2629 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2631 *np_t
= ISAKMP_NPTYPE_T
;
2633 trnslen
= setph1trns(s
, p
);
2636 /* save buffer to pre-next payload */
2637 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2640 /* count up transform length */
2645 /* update proposal length */
2647 prop
->h
.len
= htons(proplen
);
2648 prop
->num_t
= trns_num
;
2656 struct isakmpsa
*sa
;
2659 struct isakmp_pl_t
*trns
= NULL
;
2660 int trnslen
, attrlen
;
2663 trnslen
= sizeof(*trns
);
2665 /* create transform */
2666 trns
= (struct isakmp_pl_t
*)p
;
2667 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2668 trns
->t_no
= sa
->trns_no
;
2669 trns
->t_id
= IPSECDOI_KEY_IKE
;
2673 attrlen
= setph1attr(sa
, p
);
2679 trns
->h
.len
= htons(trnslen
);
2686 struct isakmpsa
*sa
;
2693 u_int32_t lifetime
= htonl((u_int32_t
)sa
->lifetime
);
2695 attrlen
+= sizeof(struct isakmp_data
)
2696 + sizeof(struct isakmp_data
);
2697 if (sa
->lifetime
> 0xffff)
2698 attrlen
+= sizeof(lifetime
);
2700 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2701 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2702 if (sa
->lifetime
> 0xffff) {
2703 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2707 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2714 u_int32_t lifebyte
= htonl((u_int32_t
)sa
->lifebyte
);
2716 attrlen
+= sizeof(struct isakmp_data
)
2717 + sizeof(struct isakmp_data
);
2718 if (sa
->lifebyte
> 0xffff)
2719 attrlen
+= sizeof(lifebyte
);
2721 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2722 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2723 if (sa
->lifebyte
> 0xffff) {
2724 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2728 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2735 attrlen
+= sizeof(struct isakmp_data
);
2737 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2740 attrlen
+= sizeof(struct isakmp_data
);
2742 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2744 if (sa
->authmethod
) {
2747 #ifdef ENABLE_HYBRID
2748 authmethod
= switch_authmethod(sa
->authmethod
);
2750 authmethod
= sa
->authmethod
;
2752 attrlen
+= sizeof(struct isakmp_data
);
2754 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, authmethod
);
2757 attrlen
+= sizeof(struct isakmp_data
);
2759 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2761 switch (sa
->dh_group
) {
2762 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2763 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2764 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2765 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2766 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2767 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2768 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2769 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2770 /* don't attach group type for known groups */
2771 attrlen
+= sizeof(struct isakmp_data
);
2773 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2777 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2778 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2779 /* don't attach group type for known groups */
2780 attrlen
+= sizeof(struct isakmp_data
);
2782 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2783 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2792 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2793 sa
->gssid
!= NULL
) {
2794 attrlen
+= sizeof(struct isakmp_data
);
2796 * Older versions of racoon just placed the ISO-Latin-1
2797 * string on the wire directly. Check to see if we are
2798 * configured to be compatible with this behavior. Otherwise,
2799 * we encode the GSS ID as UTF-16LE for Windows 2000
2800 * compatibility, which requires twice the number of octets.
2802 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
)
2803 attrlen
+= sa
->gssid
->l
;
2805 attrlen
+= sa
->gssid
->l
* 2;
2807 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %d, "
2808 "val '%.*s'\n", sa
->gssid
->l
, sa
->gssid
->l
,
2810 if (lcconf
->gss_id_enc
== LC_GSSENC_LATIN1
) {
2811 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2812 (caddr_t
)sa
->gssid
->v
,
2815 size_t dstleft
= sa
->gssid
->l
* 2;
2816 size_t srcleft
= sa
->gssid
->l
;
2817 const char *src
= (const char *)sa
->gssid
->v
;
2818 char *odst
, *dst
= racoon_malloc(dstleft
);
2822 cd
= iconv_open("utf-16le", "latin1");
2823 if (cd
== (iconv_t
) -1) {
2824 plog(LLV_ERROR
, LOCATION
, NULL
,
2825 "unable to initialize "
2826 "latin1 -> utf-16le "
2827 "converstion descriptor: %s\n",
2829 attrlen
-= sa
->gssid
->l
* 2;
2833 rv
= iconv(cd
, (__iconv_const
char **)&src
,
2834 &srcleft
, &dst
, &dstleft
);
2837 plog(LLV_ERROR
, LOCATION
, NULL
,
2838 "unable to convert GSS ID "
2839 "from latin1 -> utf-16le: "
2840 "%s\n", strerror(errno
));
2842 /* should never happen */
2843 plog(LLV_ERROR
, LOCATION
, NULL
,
2844 "%zd character%s in GSS ID "
2845 "cannot be represented "
2847 rv
, rv
== 1 ? "" : "s");
2849 (void) iconv_close(cd
);
2850 attrlen
-= sa
->gssid
->l
* 2;
2853 (void) iconv_close(cd
);
2855 /* XXX Check srcleft and dstleft? */
2857 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2858 odst
, sa
->gssid
->l
* 2);
2865 #endif /* HAVE_GSSAPI */
2871 setph2proposal0(iph2
, pp
, pr
)
2872 const struct ph2handle
*iph2
;
2873 const struct saprop
*pp
;
2874 const struct saproto
*pr
;
2877 struct isakmp_pl_p
*prop
;
2878 struct isakmp_pl_t
*trns
;
2883 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2884 const u_int8_t
*spi
;
2886 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2890 /* create proposal */
2891 prop
= (struct isakmp_pl_p
*)p
->v
;
2892 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2893 prop
->p_no
= pp
->prop_no
;
2894 prop
->proto_id
= pr
->proto_id
;
2897 spi
= (const u_int8_t
*)&pr
->spi
;
2898 switch (pr
->proto_id
) {
2899 case IPSECDOI_PROTO_IPCOMP
:
2901 * draft-shacham-ippcp-rfc2393bis-05.txt:
2902 * construct 16bit SPI (CPI).
2903 * XXX we may need to provide a configuration option to
2904 * generate 32bit SPI. otherwise we cannot interoeprate
2905 * with nodes that uses 32bit SPI, in case we are initiator.
2907 prop
->spi_size
= sizeof(u_int16_t
);
2908 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2909 p
->l
-= sizeof(pr
->spi
);
2910 p
->l
+= sizeof(u_int16_t
);
2913 prop
->spi_size
= sizeof(pr
->spi
);
2916 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2918 /* create transform */
2919 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2922 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2924 switch (pr
->proto_id
) {
2925 case IPSECDOI_PROTO_IPSEC_ESP
:
2927 * don't build a null encryption
2928 * with no authentication transform.
2930 if (tr
->trns_id
== IPSECDOI_ESP_NULL
&&
2931 tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
)
2937 *np_t
= ISAKMP_NPTYPE_T
;
2941 /* get attribute length */
2944 attrlen
+= sizeof(struct isakmp_data
)
2945 + sizeof(struct isakmp_data
);
2946 if (pp
->lifetime
> 0xffff)
2947 attrlen
+= sizeof(u_int32_t
);
2949 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2950 attrlen
+= sizeof(struct isakmp_data
)
2951 + sizeof(struct isakmp_data
);
2952 if (pp
->lifebyte
> 0xffff)
2953 attrlen
+= sizeof(u_int32_t
);
2955 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2957 attrlen
+= sizeof(struct isakmp_data
);
2959 switch (pr
->proto_id
) {
2960 case IPSECDOI_PROTO_IPSEC_ESP
:
2961 /* non authentication mode ? */
2962 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2963 attrlen
+= sizeof(struct isakmp_data
);
2965 case IPSECDOI_PROTO_IPSEC_AH
:
2966 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2967 plog(LLV_ERROR
, LOCATION
, NULL
,
2968 "no authentication algorithm found "
2969 "but protocol is AH.\n");
2973 attrlen
+= sizeof(struct isakmp_data
);
2975 case IPSECDOI_PROTO_IPCOMP
:
2978 plog(LLV_ERROR
, LOCATION
, NULL
,
2979 "invalid protocol: %d\n", pr
->proto_id
);
2984 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2985 attrlen
+= sizeof(struct isakmp_data
);
2987 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2990 prop
= (struct isakmp_pl_p
*)p
->v
;
2992 /* set transform's values */
2993 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2994 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2995 trns
->t_no
= tr
->trns_no
;
2996 trns
->t_id
= tr
->trns_id
;
2998 /* set attributes */
2999 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
3002 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3003 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
3004 if (pp
->lifetime
> 0xffff) {
3005 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
3006 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3007 (caddr_t
)&v
, sizeof(v
));
3009 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3014 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
3015 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
3016 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
3017 if (pp
->lifebyte
> 0xffff) {
3018 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
3019 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
3020 (caddr_t
)&v
, sizeof(v
));
3022 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
3027 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
3030 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
3032 /* mandatory check has done above. */
3033 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
3034 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
3035 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
3037 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
3038 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
3039 iph2
->sainfo
->pfs_group
);
3041 /* update length of this transform. */
3042 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
3043 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
3045 /* save buffer to pre-next payload */
3048 trnsoff
+= (sizeof(*trns
) + attrlen
);
3052 plog(LLV_ERROR
, LOCATION
, NULL
,
3053 "no suitable proposal was created.\n");
3057 /* update length of this protocol. */
3058 prop
->h
.len
= htons(p
->l
);
3064 * create phase2 proposal from policy configuration.
3065 * NOT INCLUDING isakmp general header of SA payload.
3066 * This function is called by initiator only.
3069 ipsecdoi_setph2proposal(iph2
)
3070 struct ph2handle
*iph2
;
3072 struct saprop
*proposal
, *a
;
3073 struct saproto
*b
= NULL
;
3075 struct ipsecdoi_sa_b
*sab
;
3076 struct isakmp_pl_p
*prop
;
3077 size_t propoff
; /* for previous field of type of next payload. */
3079 proposal
= iph2
->proposal
;
3081 iph2
->sa
= vmalloc(sizeof(*sab
));
3082 if (iph2
->sa
== NULL
) {
3083 plog(LLV_ERROR
, LOCATION
, NULL
,
3084 "failed to allocate my sa buffer\n");
3088 /* create SA payload */
3089 sab
= (struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
3090 sab
->doi
= htonl(IPSEC_DOI
);
3091 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
3095 for (a
= proposal
; a
; a
= a
->next
) {
3096 for (b
= a
->head
; b
; b
= b
->next
) {
3098 if (iph2
->ph1
->natt_flags
& NAT_DETECTED
) {
3099 int udp_diff
= iph2
->ph1
->natt_options
->mode_udp_diff
;
3100 plog (LLV_INFO
, LOCATION
, NULL
,
3101 "NAT detected -> UDP encapsulation "
3102 "(ENC_MODE %d->%d).\n",
3104 b
->encmode
+udp_diff
);
3105 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3106 b
->encmode
+= udp_diff
;
3111 q
= setph2proposal0(iph2
, a
, b
);
3117 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
3118 if (iph2
->sa
== NULL
) {
3119 plog(LLV_ERROR
, LOCATION
, NULL
,
3120 "failed to allocate my sa buffer\n");
3125 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
3127 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
3129 prop
->h
.np
= ISAKMP_NPTYPE_P
;
3131 propoff
= iph2
->sa
->l
- q
->l
;
3142 * return 1 if all of the given protocols are transport mode.
3145 ipsecdoi_tunnelmode(iph2
)
3146 struct ph2handle
*iph2
;
3149 struct saproto
*pr
= NULL
;
3151 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
3152 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3153 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
3154 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
3155 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
3165 * return 1 if all of the given protocols are transport mode.
3168 ipsecdoi_transportmode(pp
)
3171 struct saproto
*pr
= NULL
;
3173 for (; pp
; pp
= pp
->next
) {
3174 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
3175 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
3184 ipsecdoi_get_defaultlifetime()
3186 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3190 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
3191 int proto_id
, enc
, auth
, comp
;
3193 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3195 case IPSECDOI_PROTO_IPSEC_ESP
:
3196 if (enc
== 0 || comp
!= 0) {
3197 plog(LLV_ERROR
, LOCATION
, NULL
,
3198 "illegal algorithm defined "
3199 "ESP enc=%s auth=%s comp=%s.\n",
3200 TMPALGTYPE2STR(enc
),
3201 TMPALGTYPE2STR(auth
),
3202 TMPALGTYPE2STR(comp
));
3206 case IPSECDOI_PROTO_IPSEC_AH
:
3207 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
3208 plog(LLV_ERROR
, LOCATION
, NULL
,
3209 "illegal algorithm defined "
3210 "AH enc=%s auth=%s comp=%s.\n",
3211 TMPALGTYPE2STR(enc
),
3212 TMPALGTYPE2STR(auth
),
3213 TMPALGTYPE2STR(comp
));
3217 case IPSECDOI_PROTO_IPCOMP
:
3218 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
3219 plog(LLV_ERROR
, LOCATION
, NULL
,
3220 "illegal algorithm defined "
3221 "IPcomp enc=%s auth=%s comp=%s.\n",
3222 TMPALGTYPE2STR(enc
),
3223 TMPALGTYPE2STR(auth
),
3224 TMPALGTYPE2STR(comp
));
3229 plog(LLV_ERROR
, LOCATION
, NULL
,
3230 "invalid ipsec protocol %d\n", proto_id
);
3233 #undef TMPALGTYPE2STR
3243 return IPSECDOI_PROTO_IPSEC_AH
;
3245 return IPSECDOI_PROTO_IPSEC_ESP
;
3246 case IPPROTO_IPCOMP
:
3247 return IPSECDOI_PROTO_IPCOMP
;
3249 return -1; /* XXX */
3257 case IPSECDOI_PROTO_IPSEC_AH
:
3259 case IPSECDOI_PROTO_IPSEC_ESP
:
3261 case IPSECDOI_PROTO_IPCOMP
:
3262 return IPPROTO_IPCOMP
;
3264 return -1; /* XXX */
3268 * check the following:
3269 * - In main mode with pre-shared key, only address type can be used.
3270 * - if proper type for phase 1 ?
3271 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3272 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3273 * - if ID payload sent from peer is equal to the ID expected by me.
3275 * both of "id" and "id_p" should be ID payload without general header,
3278 ipsecdoi_checkid1(iph1
)
3279 struct ph1handle
*iph1
;
3281 struct ipsecdoi_id_b
*id_b
;
3282 struct sockaddr
*sa
;
3285 if (iph1
->id_p
== NULL
) {
3286 plog(LLV_ERROR
, LOCATION
, NULL
,
3287 "invalid iph1 passed id_p == NULL\n");
3288 return ISAKMP_INTERNAL_ERROR
;
3290 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3291 plog(LLV_ERROR
, LOCATION
, NULL
,
3292 "invalid value passed as \"ident\" (len=%lu)\n",
3293 (u_long
)iph1
->id_p
->l
);
3294 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3297 id_b
= (struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3299 /* In main mode with pre-shared key, only address type can be used.
3300 * If NAT Traversal being used and peer is behind nat and
3301 * natt version = 02 - allow non-address ID type.
3303 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
3304 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3306 && (iph1
->natt_flags
& NAT_DETECTED_PEER
) == 0
3309 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3310 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3311 plog(LLV_ERROR
, LOCATION
, NULL
,
3312 "Expecting IP address type in main mode, "
3313 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3314 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3318 /* if proper type for phase 1 ? */
3319 switch (id_b
->type
) {
3320 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3321 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3322 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3323 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3324 plog(LLV_WARNING
, LOCATION
, NULL
,
3325 "such ID type %s is not proper.\n",
3326 s_ipsecdoi_ident(id_b
->type
));
3330 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3331 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
|| // %%%% BUG_FIX - should be || not &&
3332 id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3334 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3335 plog(LLV_WARNING
, LOCATION
, NULL
,
3336 "protocol ID and Port mismatched. "
3337 "proto_id:%d port:%d\n",
3338 id_b
->proto_id
, ntohs(id_b
->port
));
3341 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3343 * copmaring with expected port.
3344 * always permit if port is equal to PORT_ISAKMP
3346 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3350 switch (iph1
->remote
->sa_family
) {
3352 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3356 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3360 plog(LLV_ERROR
, LOCATION
, NULL
,
3361 "invalid family: %d\n",
3362 iph1
->remote
->sa_family
);
3363 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3365 if (ntohs(id_b
->port
) != port
) {
3366 plog(LLV_WARNING
, LOCATION
, NULL
,
3367 "port %d expected, but %d\n",
3368 port
, ntohs(id_b
->port
));
3375 /* compare with the ID if specified. */
3376 if (genlist_next(iph1
->rmconf
->idvl_p
, 0)) {
3377 vchar_t
*ident0
= NULL
;
3380 struct genlist_entry
*gpb
;
3382 for (id
= genlist_next (iph1
->rmconf
->idvl_p
, &gpb
); id
; id
= genlist_next (0, &gpb
)) {
3383 /* check the type of both IDs */
3384 if (id
->idtype
!= doi2idtype(id_b
->type
))
3385 continue; /* ID type mismatch */
3389 /* compare defined ID with the ID sent by peer. */
3392 ident0
= getidval(id
->idtype
, id
->id
);
3394 switch (id
->idtype
) {
3396 ident
.v
= (caddr_t
)(id_b
+ 1);
3397 ident
.l
= iph1
->id_p
->l
- 1; /* had ident.l = ident0->l; but why?? */
3398 /* is the actual packet contents length sometimes wrong? */
3399 if (eay_cmp_asn1dn(ident0
, &ident
) == 0)
3402 case IDTYPE_ADDRESS
:
3403 sa
= (struct sockaddr
*)ident0
->v
;
3404 sa2
= (caddr_t
)(id_b
+ 1);
3405 switch (sa
->sa_family
) {
3407 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3408 continue; /* ID value mismatch */
3409 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3410 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) == 0)
3415 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3416 continue; /* ID value mismatch */
3417 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3418 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) == 0)
3427 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
) == 0)
3432 if (ident0
!= NULL
) {
3436 plog(LLV_WARNING
, LOCATION
, NULL
, "No ID match.\n");
3437 if (iph1
->rmconf
->verify_identifier
)
3438 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3439 matched
: /* ID value match */
3448 * create ID payload for phase 1 and set into iph1->id.
3449 * NOT INCLUDING isakmp general header.
3450 * see, RFC2407 4.6.2.1
3453 ipsecdoi_setid1(iph1
)
3454 struct ph1handle
*iph1
;
3456 vchar_t
*ret
= NULL
;
3457 struct ipsecdoi_id_b id_b
;
3458 vchar_t
*ident
= NULL
;
3459 struct sockaddr
*ipid
= NULL
;
3466 switch (iph1
->rmconf
->idvtype
) {
3468 id_b
.type
= IPSECDOI_ID_FQDN
;
3469 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3471 case IDTYPE_USERFQDN
:
3472 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3473 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3477 case IDTYPE_KEYIDUSE
:
3479 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3480 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3483 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3484 if (iph1
->rmconf
->idv
) {
3485 /* XXX it must be encoded to asn1dn. */
3486 ident
= vdup(iph1
->rmconf
->idv
);
3488 if (oakley_getmycert(iph1
) < 0) {
3489 plog(LLV_ERROR
, LOCATION
, NULL
,
3490 "failed to get own CERT.\n");
3493 ident
= eay_get_x509asn1subjectname(&iph1
->cert
->cert
);
3496 case IDTYPE_ADDRESS
:
3498 * if the value of the id type was set by the configuration
3499 * file, then use it. otherwise the value is get from local
3500 * ip address by using ike negotiation.
3502 if (iph1
->rmconf
->idv
)
3503 ipid
= (struct sockaddr
*)iph1
->rmconf
->idv
->v
;
3513 /* use IP address */
3514 switch (ipid
->sa_family
) {
3516 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3517 l
= sizeof(struct in_addr
);
3518 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3522 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3523 l
= sizeof(struct in6_addr
);
3524 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3528 plog(LLV_ERROR
, LOCATION
, NULL
,
3529 "invalid address family.\n");
3532 id_b
.proto_id
= IPPROTO_UDP
;
3533 id_b
.port
= htons(PORT_ISAKMP
);
3536 plog(LLV_ERROR
, LOCATION
, NULL
,
3537 "failed to get ID buffer.\n");
3540 memcpy(ident
->v
, p
, ident
->l
);
3544 plog(LLV_ERROR
, LOCATION
, NULL
,
3545 "failed to get ID buffer.\n");
3549 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3551 plog(LLV_ERROR
, LOCATION
, NULL
,
3552 "failed to get ID buffer.\n");
3556 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3557 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3561 plog(LLV_DEBUG
, LOCATION
, NULL
,
3562 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3570 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3579 vchar_t
*new = NULL
;
3583 else if (lcconf
->ident
[type
])
3584 new = vdup(lcconf
->ident
[type
]);
3589 /* it's only called by cfparse.y. */
3591 set_identifier(vpp
, type
, value
)
3592 vchar_t
**vpp
, *value
;
3595 vchar_t
*new = NULL
;
3597 /* simply return if value is null. */
3599 if( type
== IDTYPE_FQDN
|| type
== IDTYPE_USERFQDN
){
3600 plog(LLV_ERROR
, LOCATION
, NULL
,
3601 "No %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3609 case IDTYPE_USERFQDN
:
3611 plog(LLV_ERROR
, LOCATION
, NULL
,
3612 "Empty %s\n", type
== IDTYPE_FQDN
? "fqdn":"user fqdn");
3616 case IDTYPE_KEYIDUSE
:
3618 #ifdef ENABLE_HYBRID
3621 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3622 new = vmalloc(value
->l
- 1);
3625 memcpy(new->v
, value
->v
, new->l
);
3633 fp
= fopen(value
->v
, "r");
3635 plog(LLV_ERROR
, LOCATION
, NULL
,
3636 "can not open %s\n", value
->v
);
3640 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3641 new = vrealloc(new, tlen
+ len
);
3646 memcpy(new->v
+ tlen
, b
, len
);
3651 case IDTYPE_ADDRESS
:
3653 struct sockaddr
*sa
;
3655 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3659 sa
= str2saddr(value
->v
, NULL
);
3661 plog(LLV_ERROR
, LOCATION
, NULL
,
3662 "invalid ip address %s\n", value
->v
);
3666 new = vmalloc(sysdep_sa_len(sa
));
3669 memcpy(new->v
, sa
, new->l
);
3673 if (value
->v
[0] == '~')
3674 /* Hex-encoded ASN1 strings */
3675 new = eay_hex2asn1dn(value
->v
+ 1, - 1);
3677 /* DN encoded strings */
3678 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
3683 if (loglevel
>= LLV_DEBUG
) {
3686 unsigned char *ptr
= (unsigned char *) new->v
, *buf
;
3690 xn
= d2i_X509_NAME(NULL
, (void *)&ptr
, new->l
);
3691 bio
= BIO_new(BIO_s_mem());
3693 X509_NAME_print_ex(bio
, xn
, 0, 0);
3694 len
= BIO_get_mem_data(bio
, &ptr
);
3697 plog(LLV_DEBUG
, LOCATION
, NULL
, "Parsed DN: %s\n", ptr
);
3712 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3713 * NOT INCLUDING isakmp general header.
3714 * this function is for initiator. responder will get to copy from payload.
3715 * responder ID type is always address type.
3716 * see, RFC2407 4.6.2.1
3719 ipsecdoi_setid2(iph2
)
3720 struct ph2handle
*iph2
;
3722 struct secpolicy
*sp
;
3724 /* check there is phase 2 handler ? */
3725 sp
= getspbyspid(iph2
->spid
);
3727 plog(LLV_ERROR
, LOCATION
, NULL
,
3728 "no policy found for spid:%u.\n", iph2
->spid
);
3732 iph2
->id
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.src
,
3733 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
3734 if (iph2
->id
== NULL
) {
3735 plog(LLV_ERROR
, LOCATION
, NULL
,
3736 "failed to get ID for %s\n",
3737 spidx2str(&sp
->spidx
));
3740 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
3741 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
3744 iph2
->id_p
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.dst
,
3745 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
3746 if (iph2
->id_p
== NULL
) {
3747 plog(LLV_ERROR
, LOCATION
, NULL
,
3748 "failed to get ID for %s\n",
3749 spidx2str(&sp
->spidx
));
3753 plog(LLV_DEBUG
, LOCATION
, NULL
,
3754 "use remote ID type %s\n",
3755 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
3761 * set address type of ID.
3762 * NOT INCLUDING general header.
3765 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
3766 struct sockaddr
*saddr
;
3771 int type
, len1
, len2
;
3776 * Q. When type is SUBNET, is it allowed to be ::1/128.
3777 * A. Yes. (consensus at bake-off)
3779 switch (saddr
->sa_family
) {
3781 len1
= sizeof(struct in_addr
);
3786 prefixlen
== (sizeof(struct in_addr
) << 3)
3789 type
= IPSECDOI_ID_IPV4_ADDR
;
3792 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
3793 len2
= sizeof(struct in_addr
);
3795 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
3796 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
3800 len1
= sizeof(struct in6_addr
);
3805 prefixlen
== (sizeof(struct in6_addr
) << 3)
3808 type
= IPSECDOI_ID_IPV6_ADDR
;
3811 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
3812 len2
= sizeof(struct in6_addr
);
3814 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
3815 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
3819 plog(LLV_ERROR
, LOCATION
, NULL
,
3820 "invalid family: %d.\n", saddr
->sa_family
);
3825 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
3827 plog(LLV_ERROR
, LOCATION
, NULL
,
3828 "failed to get ID buffer.\n");
3832 memset(new->v
, 0, new->l
);
3834 /* set the part of header. */
3835 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
3837 /* set ul_proto and port */
3839 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3840 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3842 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
3843 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
3844 ((struct ipsecdoi_id_b
*)new->v
)->port
=
3845 port
== IPSEC_PORT_ANY
? 0 : port
;
3846 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
3852 u_char
*p
= (unsigned char *) new->v
+
3853 sizeof(struct ipsecdoi_id_b
) + len1
;
3854 u_int bits
= prefixlen
;
3862 *p
= ~((1 << (8 - bits
)) - 1);
3869 * create sockaddr structure from ID payload (buf).
3870 * buffers (saddr, prefixlen, ul_proto) must be allocated.
3871 * see, RFC2407 4.6.2.1
3874 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
3876 struct sockaddr
*saddr
;
3877 u_int8_t
*prefixlen
;
3878 u_int16_t
*ul_proto
;
3880 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)buf
->v
;
3884 * When a ID payload of subnet type with a IP address of full bit
3885 * masked, it has to be processed as host address.
3886 * e.g. below 2 type are same.
3887 * type = ipv6 subnet, data = 2001::1/128
3888 * type = ipv6 address, data = 2001::1
3890 switch (id_b
->type
) {
3891 case IPSECDOI_ID_IPV4_ADDR
:
3892 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3894 saddr
->sa_len
= sizeof(struct sockaddr_in
);
3896 saddr
->sa_family
= AF_INET
;
3897 ((struct sockaddr_in
*)saddr
)->sin_port
=
3900 : id_b
->port
); /* see sockaddr2id() */
3901 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
3902 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
3905 case IPSECDOI_ID_IPV6_ADDR
:
3906 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3908 saddr
->sa_len
= sizeof(struct sockaddr_in6
);
3910 saddr
->sa_family
= AF_INET6
;
3911 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
3914 : id_b
->port
); /* see sockaddr2id() */
3915 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
3916 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
3920 plog(LLV_ERROR
, LOCATION
, NULL
,
3921 "unsupported ID type %d\n", id_b
->type
);
3922 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3925 /* get prefix length */
3926 switch (id_b
->type
) {
3927 case IPSECDOI_ID_IPV4_ADDR
:
3928 plen
= sizeof(struct in_addr
) << 3;
3931 case IPSECDOI_ID_IPV6_ADDR
:
3932 plen
= sizeof(struct in6_addr
) << 3;
3935 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3937 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3942 int alen
= sizeof(struct in_addr
);
3944 switch (id_b
->type
) {
3945 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3946 alen
= sizeof(struct in_addr
);
3949 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3950 alen
= sizeof(struct in6_addr
);
3957 return ISAKMP_INTERNAL_ERROR
;
3959 /* get subnet mask length */
3963 p
= (unsigned char *) buf
->v
3964 + sizeof(struct ipsecdoi_id_b
)
3967 for (; *p
== 0xff; p
++) {
3990 *ul_proto
= id_b
->proto_id
== 0
3992 : id_b
->proto_id
; /* see sockaddr2id() */
3998 * make printable string from ID payload except of general header.
4004 static char buf
[256];
4013 * set IPsec data attributes into a proposal.
4014 * NOTE: MUST called per a transform.
4017 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
4018 struct isakmp_pl_t
*t
;
4023 struct isakmp_data
*d
, *prev
;
4029 tr
->trns_no
= t
->t_no
;
4030 tr
->trns_id
= t
->t_id
;
4032 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
4033 prev
= (struct isakmp_data
*)NULL
;
4034 d
= (struct isakmp_data
*)(t
+ 1);
4037 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4038 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
4040 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
4044 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
4045 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
4047 plog(LLV_DEBUG
, LOCATION
, NULL
,
4048 "type=%s, flag=0x%04x, lorv=%s\n",
4049 s_ipsecdoi_attr(type
), flag
,
4050 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
4053 case IPSECDOI_ATTR_SA_LD_TYPE
:
4055 int type
= ntohs(d
->lorv
);
4057 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4058 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4062 plog(LLV_WARNING
, LOCATION
, NULL
,
4063 "invalid life duration type. "
4065 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
4070 case IPSECDOI_ATTR_SA_LD
:
4072 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
4073 IPSECDOI_ATTR_SA_LD_TYPE
) {
4074 plog(LLV_ERROR
, LOCATION
, NULL
,
4075 "life duration must follow ltype\n");
4081 vchar_t
*ld_buf
= NULL
;
4084 /* i.e. ISAKMP_GEN_TV */
4085 ld_buf
= vmalloc(sizeof(d
->lorv
));
4086 if (ld_buf
== NULL
) {
4087 plog(LLV_ERROR
, LOCATION
, NULL
,
4088 "failed to get LD buffer.\n");
4091 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
4093 int len
= ntohs(d
->lorv
);
4094 /* i.e. ISAKMP_GEN_TLV */
4095 ld_buf
= vmalloc(len
);
4096 if (ld_buf
== NULL
) {
4097 plog(LLV_ERROR
, LOCATION
, NULL
,
4098 "failed to get LD buffer.\n");
4101 memcpy(ld_buf
->v
, d
+ 1, len
);
4104 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
4105 t
= ipsecdoi_set_ld(ld_buf
);
4108 plog(LLV_ERROR
, LOCATION
, NULL
,
4109 "invalid life duration.\n");
4112 /* lifetime must be equal in a proposal. */
4113 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
4115 else if (pp
->lifetime
!= t
) {
4116 plog(LLV_ERROR
, LOCATION
, NULL
,
4117 "lifetime mismatched "
4119 "prev:%ld curr:%u.\n",
4120 (long)pp
->lifetime
, t
);
4124 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
4125 t
= ipsecdoi_set_ld(ld_buf
);
4128 plog(LLV_ERROR
, LOCATION
, NULL
,
4129 "invalid life duration.\n");
4132 /* lifebyte must be equal in a proposal. */
4133 if (pp
->lifebyte
== 0)
4135 else if (pp
->lifebyte
!= t
) {
4136 plog(LLV_ERROR
, LOCATION
, NULL
,
4137 "lifebyte mismatched "
4139 "prev:%d curr:%u.\n",
4146 plog(LLV_ERROR
, LOCATION
, NULL
,
4147 "invalid life type: %d\n", life_t
);
4153 case IPSECDOI_ATTR_GRP_DESC
:
4155 * RFC2407: 4.5 IPSEC Security Association Attributes
4156 * Specifies the Oakley Group to be used in a PFS QM
4157 * negotiation. For a list of supported values, see
4158 * Appendix A of [IKE].
4160 if (pp
->pfs_group
== 0)
4161 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
4162 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
4163 plog(LLV_ERROR
, LOCATION
, NULL
,
4164 "pfs_group mismatched "
4165 "in a proposal.\n");
4170 case IPSECDOI_ATTR_ENC_MODE
:
4172 pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
4173 plog(LLV_ERROR
, LOCATION
, NULL
,
4174 "multiple encmode exist "
4175 "in a transform.\n");
4178 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
4181 case IPSECDOI_ATTR_AUTH
:
4182 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
4183 plog(LLV_ERROR
, LOCATION
, NULL
,
4184 "multiple authtype exist "
4185 "in a transform.\n");
4188 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
4191 case IPSECDOI_ATTR_KEY_LENGTH
:
4192 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
4193 plog(LLV_ERROR
, LOCATION
, NULL
,
4194 "key length defined but not ESP");
4197 tr
->encklen
= ntohs(d
->lorv
);
4200 case IPSECDOI_ATTR_KEY_ROUNDS
:
4201 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
4202 case IPSECDOI_ATTR_COMP_PRIVALG
:
4210 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
4212 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
4213 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
4223 ipsecdoi_authalg2trnsid(alg
)
4227 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
4228 return IPSECDOI_AH_MD5
;
4229 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
4230 return IPSECDOI_AH_SHA
;
4231 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256
:
4232 return IPSECDOI_AH_SHA256
;
4233 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384
:
4234 return IPSECDOI_AH_SHA384
;
4235 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512
:
4236 return IPSECDOI_AH_SHA512
;
4237 case IPSECDOI_ATTR_AUTH_DES_MAC
:
4238 return IPSECDOI_AH_DES
;
4239 case IPSECDOI_ATTR_AUTH_KPDK
:
4240 return IPSECDOI_AH_MD5
; /* XXX */
4242 plog(LLV_ERROR
, LOCATION
, NULL
,
4243 "invalid authentication algorithm:%d\n", alg
);
4250 fixup_initiator_sa(match
, received
)
4251 struct isakmpsa
*match
, *received
;
4253 if (received
->gssid
!= NULL
)
4254 match
->gssid
= vdup(received
->gssid
);
4260 static int rm_idtype2doi
[] = {
4261 255, /* IDTYPE_UNDEFINED, 0 */
4262 IPSECDOI_ID_FQDN
, /* IDTYPE_FQDN, 1 */
4263 IPSECDOI_ID_USER_FQDN
, /* IDTYPE_USERFQDN, 2 */
4264 IPSECDOI_ID_KEY_ID
, /* IDTYPE_KEYID, 3 */
4265 255, /* IDTYPE_ADDRESS, 4
4266 * it expands into 4 types by another function. */
4267 IPSECDOI_ID_DER_ASN1_DN
, /* IDTYPE_ASN1DN, 5 */
4268 #ifdef ENABLE_HYBRID
4269 255, /* IDTYPE_LOGIN, 6 */
4274 * convert idtype to DOI value.
4282 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
4283 return rm_idtype2doi
[idtype
];
4292 case IPSECDOI_ID_FQDN
:
4293 return(IDTYPE_FQDN
);
4294 case IPSECDOI_ID_USER_FQDN
:
4295 return(IDTYPE_USERFQDN
);
4296 case IPSECDOI_ID_KEY_ID
:
4297 return(IDTYPE_KEYID
);
4298 case IPSECDOI_ID_DER_ASN1_DN
:
4299 return(IDTYPE_ASN1DN
);
4300 case IPSECDOI_ID_IPV4_ADDR
:
4301 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
4302 case IPSECDOI_ID_IPV6_ADDR
:
4303 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
4304 return(IDTYPE_ADDRESS
);
4306 plog(LLV_WARNING
, LOCATION
, NULL
,
4307 "Inproper idtype:%s in this function.\n",
4308 s_ipsecdoi_ident(doi
));
4309 return(IDTYPE_ADDRESS
); /* XXX */
4314 #ifdef ENABLE_HYBRID
4316 switch_authmethod(authmethod
)
4319 switch(authmethod
) {
4320 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R
:
4321 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
;
4323 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R
:
4324 authmethod
= OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
;
4326 /* Those are not implemented */
4327 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R
:
4328 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I
;
4330 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R
:
4331 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I
;
4333 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R
:
4334 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I
;
4336 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R
:
4337 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I
;
4339 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R
:
4340 authmethod
= OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I
;