1 /* $KAME: ipsec_doi.c,v 1.154 2001/12/31 20:13:40 thorpej 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
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
36 #include <netkey/key_var.h>
37 #include <netinet/in.h>
39 #ifdef IPV6_INRIA_VERSION
40 #include <netinet/ipsec.h>
42 #include <netinet6/ipsec.h>
50 #if TIME_WITH_SYS_TIME
51 # include <sys/time.h>
55 # include <sys/time.h>
68 #include "isakmp_var.h"
70 #include "ipsec_doi.h"
72 #include "remoteconf.h"
73 #include "localconf.h"
77 #include "algorithm.h"
80 #include "crypto_openssl.h"
88 int verbose_proposal_check
= 1;
90 static vchar_t
*get_ph1approval
__P((struct ph1handle
*, struct prop_pair
**));
91 static struct isakmpsa
*get_ph1approvalx
__P((struct prop_pair
*,
92 struct isakmpsa
*, struct isakmpsa
*));
93 static void print_ph1mismatched
__P((struct prop_pair
*, struct isakmpsa
*));
94 static int t2isakmpsa
__P((struct isakmp_pl_t
*, struct isakmpsa
*));
95 static int cmp_aproppair_i
__P((struct prop_pair
*, struct prop_pair
*));
96 static struct prop_pair
*get_ph2approval
__P((struct ph2handle
*,
97 struct prop_pair
**));
98 static struct prop_pair
*get_ph2approvalx
__P((struct ph2handle
*,
100 static void free_proppair0
__P((struct prop_pair
*));
102 static int get_transform
103 __P((struct isakmp_pl_p
*, struct prop_pair
**, int *));
104 static u_int32_t ipsecdoi_set_ld
__P((vchar_t
*));
106 static int check_doi
__P((u_int32_t
));
107 static int check_situation
__P((u_int32_t
));
109 static int check_prot_main
__P((int));
110 static int check_prot_quick
__P((int));
111 static int (*check_protocol
[]) __P((int)) = {
112 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
113 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
116 static int check_spi_size
__P((int, int));
118 static int check_trns_isakmp
__P((int));
119 static int check_trns_ah
__P((int));
120 static int check_trns_esp
__P((int));
121 static int check_trns_ipcomp
__P((int));
122 static int (*check_transform
[]) __P((int)) = {
124 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
125 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
126 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
127 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
130 static int check_attr_isakmp
__P((struct isakmp_pl_t
*));
131 static int check_attr_ah
__P((struct isakmp_pl_t
*));
132 static int check_attr_esp
__P((struct isakmp_pl_t
*));
133 static int check_attr_ipsec
__P((int, struct isakmp_pl_t
*));
134 static int check_attr_ipcomp
__P((struct isakmp_pl_t
*));
135 static int (*check_attributes
[]) __P((struct isakmp_pl_t
*)) = {
137 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
138 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
139 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
140 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
143 static int setph1prop
__P((struct isakmpsa
*, caddr_t
));
144 static int setph1trns
__P((struct isakmpsa
*, caddr_t
));
145 static int setph1attr
__P((struct isakmpsa
*, caddr_t
));
146 static vchar_t
*setph2proposal0
__P((const struct ph2handle
*,
147 const struct saprop
*, const struct saproto
*));
149 static vchar_t
*getidval
__P((int, vchar_t
*));
152 static struct isakmpsa
*fixup_initiator_sa
__P((struct isakmpsa
*,
158 * check phase 1 SA payload.
159 * make new SA payload to be replyed not including general header.
160 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
162 * positive: the pointer to new buffer of SA payload.
163 * network byte order.
164 * NULL : error occurd.
167 ipsecdoi_checkph1proposal(sa
, iph1
)
169 struct ph1handle
*iph1
;
171 vchar_t
*newsa
; /* new SA payload approved. */
172 struct prop_pair
**pair
;
174 /* get proposal pair */
175 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
179 /* check and get one SA for use */
180 newsa
= get_ph1approval(iph1
, pair
);
187 iph1
->sa_ret
= newsa
;
193 * acceptable check for remote configuration.
194 * return a new SA payload to be reply to peer.
197 get_ph1approval(iph1
, pair
)
198 struct ph1handle
*iph1
;
199 struct prop_pair
**pair
;
202 struct isakmpsa
*sa
, tsa
;
203 struct prop_pair
*s
, *p
;
207 iph1
->approval
= NULL
;
209 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
212 for (s
= pair
[i
]; s
; s
= s
->next
) {
213 prophlen
= sizeof(struct isakmp_pl_p
)
215 /* compare proposal and select one */
216 for (p
= s
; p
; p
= p
->tnext
) {
217 sa
= get_ph1approvalx(p
, iph1
->rmconf
->proposal
,
226 * if there is no suitable proposal, racoon complains about all of
227 * mismatched items in those proposal.
229 if (verbose_proposal_check
) {
230 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
233 for (s
= pair
[i
]; s
; s
= s
->next
) {
234 prophlen
= sizeof(struct isakmp_pl_p
)
236 for (p
= s
; p
; p
= p
->tnext
) {
237 print_ph1mismatched(p
,
238 iph1
->rmconf
->proposal
);
243 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable proposal found.\n");
248 plog(LLV_DEBUG
, LOCATION
, NULL
, "an acceptable proposal found.\n");
250 /* check DH group settings */
252 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
256 plog(LLV_WARNING
, LOCATION
, NULL
,
257 "invalid DH parameter found, use default.\n");
258 oakley_dhgrp_free(sa
->dhgrp
);
261 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
268 if (sa
->gssid
!= NULL
)
269 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id in new sa '%s'\n",
271 if (iph1
-> side
== INITIATOR
) {
272 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
273 iph1
->gi_i
= vdup(iph1
->rmconf
->proposal
->gssid
);
274 if (tsa
.gssid
!= NULL
)
275 iph1
->gi_r
= vdup(tsa
.gssid
);
276 iph1
->approval
= fixup_initiator_sa(sa
, &tsa
);
278 if (tsa
.gssid
!= NULL
) {
279 iph1
->gi_r
= vdup(tsa
.gssid
);
280 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
282 vdup(iph1
->rmconf
->proposal
->gssid
);
284 iph1
->gi_i
= gssapi_get_default_id(iph1
);
285 if (sa
->gssid
== NULL
&& iph1
->gi_i
!= NULL
)
286 sa
->gssid
= vdup(iph1
->gi_i
);
290 if (iph1
->gi_i
!= NULL
)
291 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIi is %*s\n",
292 iph1
->gi_i
->l
, iph1
->gi_i
->v
);
293 if (iph1
->gi_r
!= NULL
)
294 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIr is %*s\n",
295 iph1
->gi_r
->l
, iph1
->gi_r
->v
);
300 newsa
= get_sabyproppair(p
, iph1
);
302 iph1
->approval
= NULL
;
308 * compare peer's single proposal and all of my proposal.
309 * and select one if suiatable.
310 * p : one of peer's proposal.
311 * proposal: my proposals.
313 static struct isakmpsa
*
314 get_ph1approvalx(p
, proposal
, sap
)
316 struct isakmpsa
*proposal
, *sap
;
319 struct isakmp_pl_p
*prop
= p
->prop
;
321 struct isakmp_pl_t
*trns
= p
->trns
;
322 struct isakmpsa sa
, *s
, *tsap
;
324 plog(LLV_DEBUG
, LOCATION
, NULL
,
325 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
326 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
327 prop
->spi_size
, prop
->num_t
);
329 plog(LLV_DEBUG
, LOCATION
, NULL
,
330 "trns#=%d, trns-id=%s\n",
332 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
334 tsap
= sap
!= NULL
? sap
: &sa
;
336 memset(tsap
, 0, sizeof(*tsap
));
337 if (t2isakmpsa(trns
, tsap
) < 0)
339 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
340 plog(LLV_DEBUG
, LOCATION
, NULL
, "Compared: DB:Peer\n");
341 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifetime = %ld:%ld)\n",
342 s
->lifetime
, tsap
->lifetime
);
343 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifebyte = %ld:%ld)\n",
344 s
->lifebyte
, tsap
->lifebyte
);
345 plog(LLV_DEBUG
, LOCATION
, NULL
, "enctype = %s:%s\n",
346 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
348 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
350 plog(LLV_DEBUG
, LOCATION
, NULL
, "(encklen = %d:%d)\n",
351 s
->encklen
, tsap
->encklen
);
352 plog(LLV_DEBUG
, LOCATION
, NULL
, "hashtype = %s:%s\n",
353 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
355 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
357 plog(LLV_DEBUG
, LOCATION
, NULL
, "authmethod = %s:%s\n",
358 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
360 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
362 plog(LLV_DEBUG
, LOCATION
, NULL
, "dh_group = %s:%s\n",
363 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
365 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
368 /* XXX to be considered */
369 if (tsap
->lifetime
> s
->lifetime
) ;
370 if (tsap
->lifebyte
> s
->lifebyte
) ;
373 * if responder side and peer's key length in proposal
374 * is bigger than mine, it might be accepted.
376 if(tsap
->enctype
== s
->enctype
377 && tsap
->authmethod
== s
->authmethod
378 && tsap
->hashtype
== s
->hashtype
379 && tsap
->dh_group
== s
->dh_group
380 && tsap
->encklen
== s
->encklen
)
384 if (tsap
->dhgrp
!= NULL
)
385 oakley_dhgrp_free(tsap
->dhgrp
);
390 * print all of items in peer's proposal which are mismatched to my proposal.
391 * p : one of peer's proposal.
392 * proposal: my proposals.
395 print_ph1mismatched(p
, proposal
)
397 struct isakmpsa
*proposal
;
399 struct isakmpsa sa
, *s
;
401 memset(&sa
, 0, sizeof(sa
));
402 if (t2isakmpsa(p
->trns
, &sa
) < 0)
404 for (s
= proposal
; s
; s
= s
->next
) {
405 if (sa
.enctype
!= s
->enctype
) {
406 plog(LLV_ERROR
, LOCATION
, NULL
,
408 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
410 s
->prop_no
, s
->trns_no
,
411 p
->prop
->p_no
, p
->trns
->t_no
,
412 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
414 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
417 if (sa
.authmethod
!= s
->authmethod
) {
418 plog(LLV_ERROR
, LOCATION
, NULL
,
419 "rejected authmethod: "
420 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
422 s
->prop_no
, s
->trns_no
,
423 p
->prop
->p_no
, p
->trns
->t_no
,
424 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
426 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
429 if (sa
.hashtype
!= s
->hashtype
) {
430 plog(LLV_ERROR
, LOCATION
, NULL
,
431 "rejected hashtype: "
432 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
434 s
->prop_no
, s
->trns_no
,
435 p
->prop
->p_no
, p
->trns
->t_no
,
436 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
438 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
441 if (sa
.dh_group
!= s
->dh_group
) {
442 plog(LLV_ERROR
, LOCATION
, NULL
,
443 "rejected dh_group: "
444 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
446 s
->prop_no
, s
->trns_no
,
447 p
->prop
->p_no
, p
->trns
->t_no
,
448 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
450 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
455 if (sa
.dhgrp
!= NULL
)
456 oakley_dhgrp_free(sa
.dhgrp
);
460 * get ISAKMP data attributes
464 struct isakmp_pl_t
*trns
;
467 struct isakmp_data
*d
, *prev
;
476 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
477 prev
= (struct isakmp_data
*)NULL
;
478 d
= (struct isakmp_data
*)(trns
+ 1);
481 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
482 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
484 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
490 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
491 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
493 plog(LLV_DEBUG
, LOCATION
, NULL
,
494 "type=%s, flag=0x%04x, lorv=%s\n",
495 s_oakley_attr(type
), flag
,
496 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
498 /* get variable-sized item */
500 case OAKLEY_ATTR_GRP_PI
:
501 case OAKLEY_ATTR_GRP_GEN_ONE
:
502 case OAKLEY_ATTR_GRP_GEN_TWO
:
503 case OAKLEY_ATTR_GRP_CURVE_A
:
504 case OAKLEY_ATTR_GRP_CURVE_B
:
505 case OAKLEY_ATTR_SA_LD
:
506 case OAKLEY_ATTR_GRP_ORDER
:
509 p
= (u_char
*)&d
->lorv
;
511 len
= ntohs(d
->lorv
);
512 p
= (u_char
*)(d
+ 1);
517 memcpy(val
->v
, p
, len
);
525 case OAKLEY_ATTR_ENC_ALG
:
526 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
529 case OAKLEY_ATTR_HASH_ALG
:
530 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
533 case OAKLEY_ATTR_AUTH_METHOD
:
534 sa
->authmethod
= ntohs(d
->lorv
);
537 case OAKLEY_ATTR_GRP_DESC
:
538 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
541 case OAKLEY_ATTR_GRP_TYPE
:
543 int type
= (int)ntohs(d
->lorv
);
544 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
545 sa
->dhgrp
->type
= type
;
550 case OAKLEY_ATTR_GRP_PI
:
551 sa
->dhgrp
->prime
= val
;
554 case OAKLEY_ATTR_GRP_GEN_ONE
:
557 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
559 int len
= ntohs(d
->lorv
);
563 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
564 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
568 case OAKLEY_ATTR_GRP_GEN_TWO
:
571 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
573 int len
= ntohs(d
->lorv
);
577 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
578 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
582 case OAKLEY_ATTR_GRP_CURVE_A
:
583 sa
->dhgrp
->curve_a
= val
;
586 case OAKLEY_ATTR_GRP_CURVE_B
:
587 sa
->dhgrp
->curve_b
= val
;
590 case OAKLEY_ATTR_SA_LD_TYPE
:
592 int type
= (int)ntohs(d
->lorv
);
594 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
595 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
599 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
604 case OAKLEY_ATTR_SA_LD
:
606 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
607 OAKLEY_ATTR_SA_LD_TYPE
) {
608 plog(LLV_ERROR
, LOCATION
, NULL
,
609 "life duration must follow ltype\n");
614 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
615 sa
->lifetime
= ipsecdoi_set_ld(val
);
617 if (sa
->lifetime
== 0) {
618 plog(LLV_ERROR
, LOCATION
, NULL
,
619 "invalid life duration.\n");
623 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
624 sa
->lifebyte
= ipsecdoi_set_ld(val
);
626 if (sa
->lifetime
== 0) {
627 plog(LLV_ERROR
, LOCATION
, NULL
,
628 "invalid life duration.\n");
634 plog(LLV_ERROR
, LOCATION
, NULL
,
635 "invalid life type: %d\n", life_t
);
640 case OAKLEY_ATTR_KEY_LEN
:
642 int len
= ntohs(d
->lorv
);
644 plog(LLV_ERROR
, LOCATION
, NULL
,
645 "keylen %d: not multiple of 8\n",
649 sa
->encklen
= (u_int16_t
)len
;
653 case OAKLEY_ATTR_PRF
:
654 case OAKLEY_ATTR_FIELD_SIZE
:
658 case OAKLEY_ATTR_GRP_ORDER
:
659 sa
->dhgrp
->order
= val
;
662 case OAKLEY_ATTR_GSS_ID
:
664 int len
= ntohs(d
->lorv
);
666 sa
->gssid
= vmalloc(len
);
667 memcpy(sa
->gssid
->v
, d
+ 1, len
);
668 plog(LLV_DEBUG
, LOCATION
, NULL
,
669 "received gss id '%s' (len %d)\n", sa
->gssid
->v
,
682 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
684 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
685 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
689 /* key length must not be specified on some algorithms */
691 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
692 #ifdef HAVE_OPENSSL_IDEA_H
693 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_IDEA
695 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
696 plog(LLV_ERROR
, LOCATION
, NULL
,
697 "keylen must not be specified "
698 "for encryption algorithm %d\n",
711 * check phase 2 SA payload and select single proposal.
712 * make new SA payload to be replyed not including general header.
713 * This function is called by responder only.
719 ipsecdoi_selectph2proposal(iph2
)
720 struct ph2handle
*iph2
;
722 struct prop_pair
**pair
;
723 struct prop_pair
*ret
;
725 /* get proposal pair */
726 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
730 /* check and select a proposal. */
731 ret
= get_ph2approval(iph2
, pair
);
736 /* make a SA to be replayed. */
737 /* SPI must be updated later. */
738 iph2
->sa_ret
= get_sabyproppair(ret
, iph2
->ph1
);
740 if (iph2
->sa_ret
== NULL
)
747 * check phase 2 SA payload returned from responder.
748 * This function is called by initiator only.
754 ipsecdoi_checkph2proposal(iph2
)
755 struct ph2handle
*iph2
;
757 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
762 /* get proposal pair of SA sent. */
763 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
765 plog(LLV_ERROR
, LOCATION
, NULL
,
766 "failed to get prop pair.\n");
770 /* XXX should check the number of transform */
772 /* get proposal pair of SA replyed */
773 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
775 plog(LLV_ERROR
, LOCATION
, NULL
,
776 "failed to get prop pair.\n");
780 /* check proposal is only one ? */
783 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
790 plog(LLV_ERROR
, LOCATION
, NULL
,
791 "no proposal received.\n");
795 plog(LLV_ERROR
, LOCATION
, NULL
,
796 "some proposals received.\n");
800 if (spair
[n
] == NULL
) {
801 plog(LLV_WARNING
, LOCATION
, NULL
,
802 "invalid proposal number:%d received.\n", i
);
806 if (rpair
[n
]->tnext
!= NULL
) {
807 plog(LLV_ERROR
, LOCATION
, NULL
,
808 "multi transforms replyed.\n");
812 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
813 plog(LLV_ERROR
, LOCATION
, NULL
,
814 "proposal mismathed.\n");
819 * check and select a proposal.
820 * ensure that there is no modification of the proposal by
823 p
= get_ph2approval(iph2
, rpair
);
827 /* make a SA to be replayed. */
829 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
831 if (iph2
->sa_ret
== NULL
)
838 free_proppair(rpair
);
840 free_proppair(spair
);
846 * compare two prop_pair which is assumed to have same proposal number.
847 * the case of bundle or single SA, NOT multi transforms.
848 * a: a proposal that is multi protocols and single transform, usually replyed.
849 * b: a proposal that is multi protocols and multi transform, usually sent.
850 * NOTE: this function is for initiator.
854 * XXX cannot understand the comment!
857 cmp_aproppair_i(a
, b
)
858 struct prop_pair
*a
, *b
;
860 struct prop_pair
*p
, *q
, *r
;
863 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
864 for (r
= q
; r
; r
= r
->tnext
) {
866 if (p
->trns
->t_no
== r
->trns
->t_no
)
870 /* no suitable transform found */
871 plog(LLV_ERROR
, LOCATION
, NULL
,
872 "no suitable transform found.\n");
877 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
878 plog(LLV_WARNING
, LOCATION
, NULL
,
879 "proposal #%d mismatched, "
881 r
->prop
->p_no
, p
->prop
->p_no
);
885 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
886 plog(LLV_ERROR
, LOCATION
, NULL
,
887 "proto_id mismathed: my:%d peer:%d\n",
888 r
->prop
->proto_id
, p
->prop
->proto_id
);
892 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
893 plog(LLV_ERROR
, LOCATION
, NULL
,
894 "invalid spi size: %d.\n",
899 /* check #of transforms */
900 if (p
->prop
->num_t
!= 1) {
901 plog(LLV_WARNING
, LOCATION
, NULL
,
902 "#of transform is %d, "
903 "but expected 1.\n", p
->prop
->num_t
);
907 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
908 plog(LLV_WARNING
, LOCATION
, NULL
,
909 "transform number has been modified.\n");
912 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
913 plog(LLV_WARNING
, LOCATION
, NULL
,
914 "reserved field should be zero.\n");
918 /* compare attribute */
919 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
920 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
921 plog(LLV_WARNING
, LOCATION
, NULL
,
922 "attribute has been modified.\n");
926 if ((p
&& !q
) || (!p
&& q
)) {
927 /* # of protocols mismatched */
928 plog(LLV_ERROR
, LOCATION
, NULL
,
929 "#of protocols mismatched.\n");
937 * acceptable check for policy configuration.
938 * return a new SA payload to be reply to peer.
940 static struct prop_pair
*
941 get_ph2approval(iph2
, pair
)
942 struct ph2handle
*iph2
;
943 struct prop_pair
**pair
;
945 struct prop_pair
*ret
;
948 iph2
->approval
= NULL
;
950 plog(LLV_DEBUG
, LOCATION
, NULL
,
951 "begin compare proposals.\n");
953 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
956 plog(LLV_DEBUG
, LOCATION
, NULL
,
957 "pair[%d]: %p\n", i
, pair
[i
]);
958 print_proppair(LLV_DEBUG
, pair
[i
]);;
960 /* compare proposal and select one */
961 ret
= get_ph2approvalx(iph2
, pair
[i
]);
968 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable policy found.\n");
974 * compare my proposal and peers just one proposal.
977 static struct prop_pair
*
978 get_ph2approvalx(iph2
, pp
)
979 struct ph2handle
*iph2
;
980 struct prop_pair
*pp
;
982 struct prop_pair
*ret
= NULL
;
983 struct saprop
*pr0
, *pr
= NULL
;
984 struct saprop
*q1
, *q2
;
986 pr0
= aproppair2saprop(pp
);
990 for (q1
= pr0
; q1
; q1
= q1
->next
) {
991 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
992 plog(LLV_DEBUG
, LOCATION
, NULL
,
993 "peer's single bundle:\n");
994 printsaprop0(LLV_DEBUG
, q1
);
995 plog(LLV_DEBUG
, LOCATION
, NULL
,
996 "my single bundle:\n");
997 printsaprop0(LLV_DEBUG
, q2
);
999 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1003 plog(LLV_ERROR
, LOCATION
, NULL
,
1007 /* no proposal matching */
1014 plog(LLV_DEBUG
, LOCATION
, NULL
, "matched\n");
1015 iph2
->approval
= pr
;
1019 struct prop_pair
*p
, *n
, *x
;
1023 for (p
= pp
; p
; p
= p
->next
) {
1025 * find a proposal with matching proto_id.
1026 * we have analyzed validity already, in cmpsaprop_alloc().
1028 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1029 if (sp
->proto_id
== p
->prop
->proto_id
)
1037 for (x
= p
; x
; x
= x
->tnext
)
1038 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1043 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1045 plog(LLV_ERROR
, LOCATION
, NULL
,
1046 "failed to get buffer.\n");
1053 /* need to preserve the order */
1054 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1056 if (x
&& x
->prop
== n
->prop
) {
1057 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1068 /* #of transforms should be updated ? */
1077 struct prop_pair
**pair
;
1081 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1082 free_proppair0(pair
[i
]);
1089 free_proppair0(pair
)
1090 struct prop_pair
*pair
;
1092 struct prop_pair
*p
, *q
, *r
, *s
;
1094 for (p
= pair
; p
; p
= q
) {
1096 for (r
= p
; r
; r
= s
) {
1104 * get proposal pairs from SA payload.
1105 * tiny check for proposal payload.
1108 get_proppair(sa
, mode
)
1112 struct prop_pair
**pair
;
1113 int num_p
= 0; /* number of proposal for use */
1117 struct ipsecdoi_sa_b
*sab
= (struct ipsecdoi_sa_b
*)sa
->v
;
1119 plog(LLV_DEBUG
, LOCATION
, NULL
, "total SA len=%d\n", sa
->l
);
1120 plogdump(LLV_DEBUG
, sa
->v
, sa
->l
);
1122 /* check SA payload size */
1123 if (sa
->l
< sizeof(*sab
)) {
1124 plog(LLV_ERROR
, LOCATION
, NULL
,
1125 "Invalid SA length = %d.\n", sa
->l
);
1130 if (check_doi(ntohl(sab
->doi
)) < 0)
1133 /* check SITUATION */
1134 if (check_situation(ntohl(sab
->sit
)) < 0)
1137 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1139 plog(LLV_ERROR
, LOCATION
, NULL
,
1140 "failed to get buffer.\n");
1143 memset(pair
, 0, sizeof(pair
));
1145 bp
= (caddr_t
)(sab
+ 1);
1146 tlen
= sa
->l
- sizeof(*sab
);
1149 struct isakmp_pl_p
*prop
;
1151 vchar_t
*pbuf
= NULL
;
1152 struct isakmp_parse_t
*pa
;
1154 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1158 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1159 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1161 /* check the value of next payload */
1162 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1163 plog(LLV_ERROR
, LOCATION
, NULL
,
1164 "Invalid payload type=%u\n", pa
->type
);
1169 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1172 plog(LLV_DEBUG
, LOCATION
, NULL
,
1173 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1176 plog(LLV_ERROR
, LOCATION
, NULL
,
1177 "invalid proposal with length %d\n", proplen
);
1182 /* check Protocol ID */
1183 if (!check_protocol
[mode
]) {
1184 plog(LLV_ERROR
, LOCATION
, NULL
,
1185 "unsupported mode %d\n", mode
);
1189 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1192 /* check SPI length when IKE. */
1193 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1197 if (get_transform(prop
, pair
, &num_p
) < 0) {
1208 struct prop_pair
*p
, *q
;
1210 /* check for proposals with no transforms */
1211 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1215 plog(LLV_DEBUG
, LOCATION
, NULL
, "pair %d:\n", i
);
1216 print_proppair(LLV_DEBUG
, pair
[i
]);
1218 notrans
= nprop
= 0;
1219 for (p
= pair
[i
]; p
; p
= p
->next
) {
1220 if (p
->trns
== NULL
) {
1224 for (q
= p
; q
; q
= q
->tnext
)
1230 * XXX at this moment, we cannot accept proposal group
1231 * with multiple proposals. this should be fixed.
1233 if (pair
[i
]->next
) {
1234 plog(LLV_WARNING
, LOCATION
, NULL
,
1235 "proposal #%u ignored "
1236 "(multiple proposal not supported)\n",
1237 pair
[i
]->prop
->p_no
);
1243 for (p
= pair
[i
]; p
; p
= q
) {
1250 plog(LLV_DEBUG
, LOCATION
, NULL
,
1251 "proposal #%u: %d transform\n",
1252 pair
[i
]->prop
->p_no
, nprop
);
1257 /* bark if no proposal is found. */
1259 plog(LLV_ERROR
, LOCATION
, NULL
,
1260 "no Proposal found.\n");
1268 * check transform payload.
1270 * positive: return the pointer to the payload of valid transform.
1271 * 0 : No valid transform found.
1274 get_transform(prop
, pair
, num_p
)
1275 struct isakmp_pl_p
*prop
;
1276 struct prop_pair
**pair
;
1279 int tlen
; /* total length of all transform in a proposal */
1281 struct isakmp_pl_t
*trns
;
1283 vchar_t
*pbuf
= NULL
;
1284 struct isakmp_parse_t
*pa
;
1285 struct prop_pair
*p
= NULL
, *q
;
1288 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1289 tlen
= ntohs(prop
->h
.len
)
1290 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1291 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1295 /* check and get transform for use */
1297 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1298 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1303 /* check the value of next payload */
1304 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1305 plog(LLV_ERROR
, LOCATION
, NULL
,
1306 "Invalid payload type=%u\n", pa
->type
);
1310 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1313 plog(LLV_DEBUG
, LOCATION
, NULL
,
1314 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1316 /* check transform ID */
1317 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1318 plog(LLV_WARNING
, LOCATION
, NULL
,
1319 "unsupported proto_id %u\n",
1323 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1324 plog(LLV_WARNING
, LOCATION
, NULL
,
1325 "unsupported proto_id %u\n",
1330 if (!check_transform
[prop
->proto_id
]
1331 || !check_attributes
[prop
->proto_id
]) {
1332 plog(LLV_WARNING
, LOCATION
, NULL
,
1333 "unsupported proto_id %u\n",
1337 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1340 /* check data attributes */
1341 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1344 p
= racoon_calloc(1, sizeof(*p
));
1346 plog(LLV_ERROR
, LOCATION
, NULL
,
1347 "failed to get buffer.\n");
1354 /* need to preserve the order */
1355 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1357 if (q
&& q
->prop
== p
->prop
) {
1358 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1365 pair
[prop
->p_no
] = p
;
1377 * make a new SA payload from prop_pair.
1378 * NOTE: this function make spi value clear.
1381 get_sabyproppair(pair
, iph1
)
1382 struct prop_pair
*pair
;
1383 struct ph1handle
*iph1
;
1387 u_int8_t
*np_p
= NULL
;
1388 struct prop_pair
*p
;
1389 int prophlen
, trnslen
;
1392 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1393 for (p
= pair
; p
; p
= p
->next
) {
1394 newtlen
+= (sizeof(struct isakmp_pl_p
)
1396 + ntohs(p
->trns
->h
.len
));
1399 newsa
= vmalloc(newtlen
);
1400 if (newsa
== NULL
) {
1401 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1406 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1408 /* update some of values in SA header */
1409 ((struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1410 ((struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1411 bp
+= sizeof(struct ipsecdoi_sa_b
);
1413 /* create proposal payloads */
1414 for (p
= pair
; p
; p
= p
->next
) {
1415 prophlen
= sizeof(struct isakmp_pl_p
)
1416 + p
->prop
->spi_size
;
1417 trnslen
= ntohs(p
->trns
->h
.len
);
1420 *np_p
= ISAKMP_NPTYPE_P
;
1422 /* create proposal */
1424 memcpy(bp
, p
->prop
, prophlen
);
1425 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1426 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1427 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1428 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1429 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1432 /* create transform */
1433 memcpy(bp
, p
->trns
, trnslen
);
1434 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1435 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1443 * update responder's spi
1446 ipsecdoi_updatespi(iph2
)
1447 struct ph2handle
*iph2
;
1449 struct prop_pair
**pair
, *p
;
1456 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1459 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1463 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1464 /* multiple transform must be filtered by selectph2proposal.*/
1468 pp
= iph2
->approval
;
1470 /* create proposal payloads */
1471 for (p
= pair
[i
]; p
; p
= p
->next
) {
1473 * find a proposal/transform with matching proto_id/t_id.
1474 * we have analyzed validity already, in cmpsaprop_alloc().
1476 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1477 if (p
->prop
->proto_id
== pr
->proto_id
&&
1478 p
->trns
->t_id
== pr
->head
->trns_id
) {
1486 * XXX SPI bits are left-filled, for use with IPComp.
1487 * we should be switching to variable-length spi field...
1489 spi
= (u_int8_t
*)&pr
->spi
;
1490 spi
+= sizeof(pr
->spi
);
1492 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1497 free_proppair(pair
);
1502 * make a new SA payload from prop_pair.
1505 get_sabysaprop(pp0
, sa0
)
1509 struct prop_pair
**pair
;
1512 u_int8_t
*np_p
= NULL
;
1513 struct prop_pair
*p
= NULL
;
1517 int prophlen
, trnslen
;
1520 /* get proposal pair */
1521 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1525 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1526 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1528 if (pair
[pp
->prop_no
] == NULL
)
1531 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1532 newtlen
+= (sizeof(struct isakmp_pl_p
)
1535 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1536 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1537 if (tr
->trns_no
== p
->trns
->t_no
)
1543 newtlen
+= ntohs(p
->trns
->h
.len
);
1548 newsa
= vmalloc(newtlen
);
1549 if (newsa
== NULL
) {
1550 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1555 /* some of values of SA must be updated in the out of this function */
1556 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1557 bp
+= sizeof(struct ipsecdoi_sa_b
);
1559 /* create proposal payloads */
1560 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1562 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1563 prophlen
= sizeof(struct isakmp_pl_p
)
1564 + p
->prop
->spi_size
;
1566 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1567 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1568 if (tr
->trns_no
== p
->trns
->t_no
)
1574 trnslen
= ntohs(p
->trns
->h
.len
);
1577 *np_p
= ISAKMP_NPTYPE_P
;
1579 /* create proposal */
1581 memcpy(bp
, p
->prop
, prophlen
);
1582 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1583 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1584 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1585 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1588 /* create transform */
1589 memcpy(bp
, p
->trns
, trnslen
);
1590 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1591 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1601 * If some error happens then return 0. Although 0 means that lifetime is zero,
1602 * such a value should not be accepted.
1603 * Also 0 of lifebyte should not be included in a packet although 0 means not
1607 ipsecdoi_set_ld(buf
)
1617 ld
= ntohs(*(u_int16_t
*)buf
->v
);
1620 ld
= ntohl(*(u_int32_t
*)buf
->v
);
1623 plog(LLV_ERROR
, LOCATION
, NULL
,
1624 "length %d of life duration "
1625 "isn't supported.\n", buf
->l
);
1644 plog(LLV_ERROR
, LOCATION
, NULL
,
1645 "invalid value of DOI 0x%08x.\n", doi
);
1655 check_situation(sit
)
1659 case IPSECDOI_SIT_IDENTITY_ONLY
:
1662 case IPSECDOI_SIT_SECRECY
:
1663 case IPSECDOI_SIT_INTEGRITY
:
1664 plog(LLV_ERROR
, LOCATION
, NULL
,
1665 "situation 0x%08x unsupported yet.\n", sit
);
1669 plog(LLV_ERROR
, LOCATION
, NULL
,
1670 "invalid situation 0x%08x.\n", sit
);
1677 * check protocol id in main mode
1680 check_prot_main(proto_id
)
1684 case IPSECDOI_PROTO_ISAKMP
:
1688 plog(LLV_ERROR
, LOCATION
, NULL
,
1689 "Illegal protocol id=%u.\n", proto_id
);
1696 * check protocol id in quick mode
1699 check_prot_quick(proto_id
)
1703 case IPSECDOI_PROTO_IPSEC_AH
:
1704 case IPSECDOI_PROTO_IPSEC_ESP
:
1707 case IPSECDOI_PROTO_IPCOMP
:
1711 plog(LLV_ERROR
, LOCATION
, NULL
,
1712 "invalid protocol id %d.\n", proto_id
);
1719 check_spi_size(proto_id
, size
)
1723 case IPSECDOI_PROTO_ISAKMP
:
1726 plog(LLV_WARNING
, LOCATION
, NULL
,
1727 "SPI size isn't zero, but IKE proposal.\n");
1731 case IPSECDOI_PROTO_IPSEC_AH
:
1732 case IPSECDOI_PROTO_IPSEC_ESP
:
1734 plog(LLV_ERROR
, LOCATION
, NULL
,
1735 "invalid SPI size=%d for IPSEC proposal.\n",
1741 case IPSECDOI_PROTO_IPCOMP
:
1742 if (size
!= 2 && size
!= 4) {
1743 plog(LLV_ERROR
, LOCATION
, NULL
,
1744 "invalid SPI size=%d for IPCOMP proposal.\n",
1758 * check transform ID in ISAKMP.
1761 check_trns_isakmp(t_id
)
1765 case IPSECDOI_KEY_IKE
:
1768 plog(LLV_ERROR
, LOCATION
, NULL
,
1769 "invalid transform-id=%u in proto_id=%u.\n",
1770 t_id
, IPSECDOI_KEY_IKE
);
1777 * check transform ID in AH.
1784 case IPSECDOI_AH_MD5
:
1785 case IPSECDOI_AH_SHA
:
1787 case IPSECDOI_AH_DES
:
1788 plog(LLV_ERROR
, LOCATION
, NULL
,
1789 "not support transform-id=%u in AH.\n", t_id
);
1792 plog(LLV_ERROR
, LOCATION
, NULL
,
1793 "invalid transform-id=%u in AH.\n", t_id
);
1800 * check transform ID in ESP.
1803 check_trns_esp(t_id
)
1807 case IPSECDOI_ESP_DES
:
1808 case IPSECDOI_ESP_3DES
:
1809 case IPSECDOI_ESP_NULL
:
1810 case IPSECDOI_ESP_RC5
:
1811 case IPSECDOI_ESP_CAST
:
1812 case IPSECDOI_ESP_BLOWFISH
:
1813 case IPSECDOI_ESP_RIJNDAEL
:
1814 case IPSECDOI_ESP_TWOFISH
:
1816 case IPSECDOI_ESP_DES_IV32
:
1817 case IPSECDOI_ESP_DES_IV64
:
1818 case IPSECDOI_ESP_IDEA
:
1819 case IPSECDOI_ESP_3IDEA
:
1820 case IPSECDOI_ESP_RC4
:
1821 plog(LLV_ERROR
, LOCATION
, NULL
,
1822 "not support transform-id=%u in ESP.\n", t_id
);
1825 plog(LLV_ERROR
, LOCATION
, NULL
,
1826 "invalid transform-id=%u in ESP.\n", t_id
);
1833 * check transform ID in IPCOMP.
1836 check_trns_ipcomp(t_id
)
1840 case IPSECDOI_IPCOMP_OUI
:
1841 case IPSECDOI_IPCOMP_DEFLATE
:
1842 case IPSECDOI_IPCOMP_LZS
:
1845 plog(LLV_ERROR
, LOCATION
, NULL
,
1846 "invalid transform-id=%u in IPCOMP.\n", t_id
);
1853 * check data attributes in IKE.
1856 check_attr_isakmp(trns
)
1857 struct isakmp_pl_t
*trns
;
1859 struct isakmp_data
*d
;
1864 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
1865 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
1868 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
1869 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
1870 lorv
= ntohs(d
->lorv
);
1872 plog(LLV_DEBUG
, LOCATION
, NULL
,
1873 "type=%s, flag=0x%04x, lorv=%s\n",
1874 s_oakley_attr(type
), flag
,
1875 s_oakley_attr_v(type
, lorv
));
1878 * some of the attributes must be encoded in TV.
1879 * see RFC2409 Appendix A "Attribute Classes".
1882 case OAKLEY_ATTR_ENC_ALG
:
1883 case OAKLEY_ATTR_HASH_ALG
:
1884 case OAKLEY_ATTR_AUTH_METHOD
:
1885 case OAKLEY_ATTR_GRP_DESC
:
1886 case OAKLEY_ATTR_GRP_TYPE
:
1887 case OAKLEY_ATTR_SA_LD_TYPE
:
1888 case OAKLEY_ATTR_PRF
:
1889 case OAKLEY_ATTR_KEY_LEN
:
1890 case OAKLEY_ATTR_FIELD_SIZE
:
1891 if (!flag
) { /* TLV*/
1892 plog(LLV_ERROR
, LOCATION
, NULL
,
1893 "oakley attribute %d must be TV.\n",
1900 /* sanity check for TLV. length must be specified. */
1901 if (!flag
&& lorv
== 0) { /*TLV*/
1902 plog(LLV_ERROR
, LOCATION
, NULL
,
1903 "invalid length %d for TLV attribute %d.\n",
1909 case OAKLEY_ATTR_ENC_ALG
:
1910 if (!alg_oakley_encdef_ok(lorv
)) {
1911 plog(LLV_ERROR
, LOCATION
, NULL
,
1912 "invalied encryption algorithm=%d.\n",
1918 case OAKLEY_ATTR_HASH_ALG
:
1919 if (!alg_oakley_hashdef_ok(lorv
)) {
1920 plog(LLV_ERROR
, LOCATION
, NULL
,
1921 "invalied hash algorithm=%d.\n",
1927 case OAKLEY_ATTR_AUTH_METHOD
:
1929 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
1930 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
1931 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
1933 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
1934 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
1935 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
1936 plog(LLV_ERROR
, LOCATION
, NULL
,
1937 "auth method %d isn't supported.\n",
1941 plog(LLV_ERROR
, LOCATION
, NULL
,
1942 "invalid auth method %d.\n",
1948 case OAKLEY_ATTR_GRP_DESC
:
1949 if (!alg_oakley_dhdef_ok(lorv
)) {
1950 plog(LLV_ERROR
, LOCATION
, NULL
,
1951 "invalid DH group %d.\n",
1957 case OAKLEY_ATTR_GRP_TYPE
:
1959 case OAKLEY_ATTR_GRP_TYPE_MODP
:
1962 plog(LLV_ERROR
, LOCATION
, NULL
,
1963 "unsupported DH group type %d.\n",
1969 case OAKLEY_ATTR_GRP_PI
:
1970 case OAKLEY_ATTR_GRP_GEN_ONE
:
1971 /* sanity checks? */
1974 case OAKLEY_ATTR_GRP_GEN_TWO
:
1975 case OAKLEY_ATTR_GRP_CURVE_A
:
1976 case OAKLEY_ATTR_GRP_CURVE_B
:
1977 plog(LLV_ERROR
, LOCATION
, NULL
,
1978 "attr type=%u isn't supported.\n", type
);
1981 case OAKLEY_ATTR_SA_LD_TYPE
:
1983 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
1984 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
1987 plog(LLV_ERROR
, LOCATION
, NULL
,
1988 "invalid life type %d.\n", lorv
);
1993 case OAKLEY_ATTR_SA_LD
:
1994 /* should check the value */
1997 case OAKLEY_ATTR_PRF
:
1998 case OAKLEY_ATTR_KEY_LEN
:
2001 case OAKLEY_ATTR_FIELD_SIZE
:
2002 plog(LLV_ERROR
, LOCATION
, NULL
,
2003 "attr type=%u isn't supported.\n", type
);
2006 case OAKLEY_ATTR_GRP_ORDER
:
2009 case OAKLEY_ATTR_GSS_ID
:
2013 plog(LLV_ERROR
, LOCATION
, NULL
,
2014 "invalid attribute type %d.\n", type
);
2020 d
= (struct isakmp_data
*)((char *)d
2023 tlen
-= (sizeof(*d
) + lorv
);
2024 d
= (struct isakmp_data
*)((char *)d
2025 + sizeof(*d
) + lorv
);
2033 * check data attributes in IPSEC AH/ESP.
2037 struct isakmp_pl_t
*trns
;
2039 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2043 check_attr_esp(trns
)
2044 struct isakmp_pl_t
*trns
;
2046 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2050 check_attr_ipsec(proto_id
, trns
)
2052 struct isakmp_pl_t
*trns
;
2054 struct isakmp_data
*d
;
2058 int attrseen
[16]; /* XXX magic number */
2060 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2061 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2062 memset(attrseen
, 0, sizeof(attrseen
));
2065 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2066 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2067 lorv
= ntohs(d
->lorv
);
2069 plog(LLV_DEBUG
, LOCATION
, NULL
,
2070 "type=%s, flag=0x%04x, lorv=%s\n",
2071 s_ipsecdoi_attr(type
), flag
,
2072 s_ipsecdoi_attr_v(type
, lorv
));
2074 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2078 case IPSECDOI_ATTR_ENC_MODE
:
2080 plog(LLV_ERROR
, LOCATION
, NULL
,
2081 "must be TV when ENC_MODE.\n");
2086 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2087 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2090 plog(LLV_ERROR
, LOCATION
, NULL
,
2091 "invalid encryption mode=%u.\n",
2097 case IPSECDOI_ATTR_AUTH
:
2099 plog(LLV_ERROR
, LOCATION
, NULL
,
2100 "must be TV when AUTH.\n");
2105 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2106 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
2107 && trns
->t_id
!= IPSECDOI_AH_MD5
) {
2109 plog(LLV_ERROR
, LOCATION
, NULL
,
2110 "auth algorithm %u conflicts "
2111 "with transform %u.\n",
2116 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2117 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2118 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2122 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2123 case IPSECDOI_ATTR_AUTH_KPDK
:
2124 plog(LLV_ERROR
, LOCATION
, NULL
,
2125 "auth algorithm %u isn't supported.\n",
2129 plog(LLV_ERROR
, LOCATION
, NULL
,
2130 "invalid auth algorithm=%u.\n",
2136 case IPSECDOI_ATTR_SA_LD_TYPE
:
2138 plog(LLV_ERROR
, LOCATION
, NULL
,
2139 "must be TV when LD_TYPE.\n");
2144 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2145 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2148 plog(LLV_ERROR
, LOCATION
, NULL
,
2149 "invalid life type %d.\n", lorv
);
2154 case IPSECDOI_ATTR_SA_LD
:
2156 /* i.e. ISAKMP_GEN_TV */
2157 plog(LLV_DEBUG
, LOCATION
, NULL
,
2158 "life duration was in TLV.\n");
2160 /* i.e. ISAKMP_GEN_TLV */
2162 plog(LLV_ERROR
, LOCATION
, NULL
,
2163 "invalid length of LD\n");
2169 case IPSECDOI_ATTR_GRP_DESC
:
2171 plog(LLV_ERROR
, LOCATION
, NULL
,
2172 "must be TV when GRP_DESC.\n");
2176 if (!alg_oakley_dhdef_ok(lorv
)) {
2177 plog(LLV_ERROR
, LOCATION
, NULL
,
2178 "invalid group description=%u.\n",
2184 case IPSECDOI_ATTR_KEY_LENGTH
:
2186 plog(LLV_ERROR
, LOCATION
, NULL
,
2187 "must be TV when KEY_LENGTH.\n");
2192 case IPSECDOI_ATTR_KEY_ROUNDS
:
2193 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2194 case IPSECDOI_ATTR_COMP_PRIVALG
:
2195 plog(LLV_ERROR
, LOCATION
, NULL
,
2196 "attr type=%u isn't supported.\n", type
);
2200 plog(LLV_ERROR
, LOCATION
, NULL
,
2201 "invalid attribute type %d.\n", type
);
2207 d
= (struct isakmp_data
*)((char *)d
2210 tlen
-= (sizeof(*d
) + lorv
);
2211 d
= (struct isakmp_data
*)((caddr_t
)d
2212 + sizeof(*d
) + lorv
);
2216 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
2217 && !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2218 plog(LLV_ERROR
, LOCATION
, NULL
,
2219 "attr AUTH must be present for AH.\n", type
);
2227 check_attr_ipcomp(trns
)
2228 struct isakmp_pl_t
*trns
;
2230 struct isakmp_data
*d
;
2234 int attrseen
[16]; /* XXX magic number */
2236 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2237 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2238 memset(attrseen
, 0, sizeof(attrseen
));
2241 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2242 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2243 lorv
= ntohs(d
->lorv
);
2245 plog(LLV_DEBUG
, LOCATION
, NULL
,
2246 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2249 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2253 case IPSECDOI_ATTR_ENC_MODE
:
2255 plog(LLV_ERROR
, LOCATION
, NULL
,
2256 "must be TV when ENC_MODE.\n");
2261 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2262 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2265 plog(LLV_ERROR
, LOCATION
, NULL
,
2266 "invalid encryption mode=%u.\n",
2272 case IPSECDOI_ATTR_SA_LD_TYPE
:
2274 plog(LLV_ERROR
, LOCATION
, NULL
,
2275 "must be TV when LD_TYPE.\n");
2280 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2281 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2284 plog(LLV_ERROR
, LOCATION
, NULL
,
2285 "invalid life type %d.\n", lorv
);
2290 case IPSECDOI_ATTR_SA_LD
:
2292 /* i.e. ISAKMP_GEN_TV */
2293 plog(LLV_DEBUG
, LOCATION
, NULL
,
2294 "life duration was in TLV.\n");
2296 /* i.e. ISAKMP_GEN_TLV */
2298 plog(LLV_ERROR
, LOCATION
, NULL
,
2299 "invalid length of LD\n");
2305 case IPSECDOI_ATTR_GRP_DESC
:
2307 plog(LLV_ERROR
, LOCATION
, NULL
,
2308 "must be TV when GRP_DESC.\n");
2312 if (!alg_oakley_dhdef_ok(lorv
)) {
2313 plog(LLV_ERROR
, LOCATION
, NULL
,
2314 "invalid group description=%u.\n",
2320 case IPSECDOI_ATTR_AUTH
:
2321 plog(LLV_ERROR
, LOCATION
, NULL
,
2322 "invalid attr type=%u.\n", type
);
2325 case IPSECDOI_ATTR_KEY_LENGTH
:
2326 case IPSECDOI_ATTR_KEY_ROUNDS
:
2327 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2328 case IPSECDOI_ATTR_COMP_PRIVALG
:
2329 plog(LLV_ERROR
, LOCATION
, NULL
,
2330 "attr type=%u isn't supported.\n", type
);
2334 plog(LLV_ERROR
, LOCATION
, NULL
,
2335 "invalid attribute type %d.\n", type
);
2341 d
= (struct isakmp_data
*)((char *)d
2344 tlen
-= (sizeof(*d
) + lorv
);
2345 d
= (struct isakmp_data
*)((caddr_t
)d
2346 + sizeof(*d
) + lorv
);
2351 if (proto_id
== IPSECDOI_PROTO_IPCOMP
2352 && !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2353 plog(LLV_ERROR
, LOCATION
, NULL
,
2354 "attr AUTH must be present for AH.\n", type
);
2364 * create phase1 proposal from remote configuration.
2365 * NOT INCLUDING isakmp general header of SA payload
2368 ipsecdoi_setph1proposal(props
)
2369 struct isakmpsa
*props
;
2374 /* count total size of SA minus isakmp general header */
2375 /* not including isakmp general header of SA payload */
2376 sablen
= sizeof(struct ipsecdoi_sa_b
);
2377 sablen
+= setph1prop(props
, NULL
);
2379 mysa
= vmalloc(sablen
);
2381 plog(LLV_ERROR
, LOCATION
, NULL
,
2382 "failed to allocate my sa buffer\n");
2386 /* create SA payload */
2387 /* not including isakmp general header */
2388 ((struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2389 ((struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2391 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2397 setph1prop(props
, buf
)
2398 struct isakmpsa
*props
;
2401 struct isakmp_pl_p
*prop
= NULL
;
2402 struct isakmpsa
*s
= NULL
;
2403 int proplen
, trnslen
;
2404 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2408 proplen
= sizeof(*prop
);
2410 /* create proposal */
2411 prop
= (struct isakmp_pl_p
*)p
;
2412 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2413 prop
->p_no
= props
->prop_no
;
2414 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2422 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2424 *np_t
= ISAKMP_NPTYPE_T
;
2426 trnslen
= setph1trns(s
, p
);
2429 /* save buffer to pre-next payload */
2430 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2433 /* count up transform length */
2438 /* update proposal length */
2440 prop
->h
.len
= htons(proplen
);
2441 prop
->num_t
= trns_num
;
2449 struct isakmpsa
*sa
;
2452 struct isakmp_pl_t
*trns
= NULL
;
2453 int trnslen
, attrlen
;
2456 trnslen
= sizeof(*trns
);
2458 /* create transform */
2459 trns
= (struct isakmp_pl_t
*)p
;
2460 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2461 trns
->t_no
= sa
->trns_no
;
2462 trns
->t_id
= IPSECDOI_KEY_IKE
;
2466 attrlen
= setph1attr(sa
, p
);
2472 trns
->h
.len
= htons(trnslen
);
2479 struct isakmpsa
*sa
;
2486 attrlen
+= sizeof(struct isakmp_data
)
2487 + sizeof(struct isakmp_data
);
2488 if (sa
->lifetime
> 0xffff)
2489 attrlen
+= sizeof(sa
->lifetime
);
2491 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2492 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2493 if (sa
->lifetime
> 0xffff) {
2494 u_int32_t v
= htonl((u_int32_t
)sa
->lifetime
);
2495 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2496 (caddr_t
)&v
, sizeof(v
));
2498 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2505 attrlen
+= sizeof(struct isakmp_data
)
2506 + sizeof(struct isakmp_data
);
2507 if (sa
->lifebyte
> 0xffff)
2508 attrlen
+= sizeof(sa
->lifebyte
);
2510 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2511 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2512 if (sa
->lifebyte
> 0xffff) {
2513 u_int32_t v
= htonl((u_int32_t
)sa
->lifebyte
);
2514 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2515 (caddr_t
)&v
, sizeof(v
));
2517 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2524 attrlen
+= sizeof(struct isakmp_data
);
2526 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2529 attrlen
+= sizeof(struct isakmp_data
);
2531 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2533 if (sa
->authmethod
) {
2534 attrlen
+= sizeof(struct isakmp_data
);
2536 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, sa
->authmethod
);
2539 attrlen
+= sizeof(struct isakmp_data
);
2541 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2543 switch (sa
->dh_group
) {
2544 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2545 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2546 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2547 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2548 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2549 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2550 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2551 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2552 /* don't attach group type for known groups */
2553 attrlen
+= sizeof(struct isakmp_data
);
2555 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2559 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2560 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2561 /* don't attach group type for known groups */
2562 attrlen
+= sizeof(struct isakmp_data
);
2564 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2565 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2574 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2575 sa
->gssid
!= NULL
) {
2576 attrlen
+= sizeof(struct isakmp_data
);
2577 attrlen
+= sa
->gssid
->l
;
2579 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %d, "
2580 "val '%s'\n", sa
->gssid
->l
, sa
->gssid
->v
);
2581 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2582 (caddr_t
)sa
->gssid
->v
,
2592 setph2proposal0(iph2
, pp
, pr
)
2593 const struct ph2handle
*iph2
;
2594 const struct saprop
*pp
;
2595 const struct saproto
*pr
;
2598 struct isakmp_pl_p
*prop
;
2599 struct isakmp_pl_t
*trns
;
2604 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2605 const u_int8_t
*spi
;
2607 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2611 /* create proposal */
2612 prop
= (struct isakmp_pl_p
*)p
->v
;
2613 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2614 prop
->p_no
= pp
->prop_no
;
2615 prop
->proto_id
= pr
->proto_id
;
2618 spi
= (const u_int8_t
*)&pr
->spi
;
2619 switch (pr
->proto_id
) {
2620 case IPSECDOI_PROTO_IPCOMP
:
2622 * draft-shacham-ippcp-rfc2393bis-05.txt:
2623 * construct 16bit SPI (CPI).
2624 * XXX we may need to provide a configuration option to
2625 * generate 32bit SPI. otherwise we cannot interoeprate
2626 * with nodes that uses 32bit SPI, in case we are initiator.
2628 prop
->spi_size
= sizeof(u_int16_t
);
2629 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2630 p
->l
-= sizeof(pr
->spi
);
2631 p
->l
+= sizeof(u_int16_t
);
2634 prop
->spi_size
= sizeof(pr
->spi
);
2637 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2639 /* create transform */
2640 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2643 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2646 *np_t
= ISAKMP_NPTYPE_T
;
2650 /* get attribute length */
2653 attrlen
+= sizeof(struct isakmp_data
)
2654 + sizeof(struct isakmp_data
);
2655 if (pp
->lifetime
> 0xffff)
2656 attrlen
+= sizeof(u_int32_t
);
2658 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2659 attrlen
+= sizeof(struct isakmp_data
)
2660 + sizeof(struct isakmp_data
);
2661 if (pp
->lifebyte
> 0xffff)
2662 attrlen
+= sizeof(u_int32_t
);
2664 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2666 attrlen
+= sizeof(struct isakmp_data
);
2668 switch (pr
->proto_id
) {
2669 case IPSECDOI_PROTO_IPSEC_ESP
:
2670 /* non authentication mode ? */
2671 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2672 attrlen
+= sizeof(struct isakmp_data
);
2674 case IPSECDOI_PROTO_IPSEC_AH
:
2675 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2676 plog(LLV_ERROR
, LOCATION
, NULL
,
2677 "no authentication algorithm found "
2678 "but protocol is AH.\n");
2682 attrlen
+= sizeof(struct isakmp_data
);
2684 case IPSECDOI_PROTO_IPCOMP
:
2687 plog(LLV_ERROR
, LOCATION
, NULL
,
2688 "invalid protocol: %d\n", pr
->proto_id
);
2693 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2694 attrlen
+= sizeof(struct isakmp_data
);
2696 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2699 prop
= (struct isakmp_pl_p
*)p
->v
;
2701 /* set transform's values */
2702 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2703 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2704 trns
->t_no
= tr
->trns_no
;
2705 trns
->t_id
= tr
->trns_id
;
2707 /* set attributes */
2708 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
2711 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2712 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
2713 if (pp
->lifetime
> 0xffff) {
2714 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
2715 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2716 (caddr_t
)&v
, sizeof(v
));
2718 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2723 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2724 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2725 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
2726 if (pp
->lifebyte
> 0xffff) {
2727 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
2728 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2729 (caddr_t
)&v
, sizeof(v
));
2731 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2736 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
2739 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
2741 /* mandatory check has done above. */
2742 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2743 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
2744 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
2746 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2747 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
2748 iph2
->sainfo
->pfs_group
);
2750 /* update length of this transform. */
2751 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2752 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
2754 /* save buffer to pre-next payload */
2757 trnsoff
+= (sizeof(*trns
) + attrlen
);
2760 /* update length of this protocol. */
2761 prop
->h
.len
= htons(p
->l
);
2767 * create phase2 proposal from policy configuration.
2768 * NOT INCLUDING isakmp general header of SA payload.
2769 * This function is called by initiator only.
2772 ipsecdoi_setph2proposal(iph2
)
2773 struct ph2handle
*iph2
;
2775 struct saprop
*proposal
, *a
;
2776 struct saproto
*b
= NULL
;
2778 struct ipsecdoi_sa_b
*sab
;
2779 struct isakmp_pl_p
*prop
;
2780 size_t propoff
; /* for previous field of type of next payload. */
2782 proposal
= iph2
->proposal
;
2784 iph2
->sa
= vmalloc(sizeof(*sab
));
2785 if (iph2
->sa
== NULL
) {
2786 plog(LLV_ERROR
, LOCATION
, NULL
,
2787 "failed to allocate my sa buffer\n");
2791 /* create SA payload */
2792 sab
= (struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
2793 sab
->doi
= htonl(IPSEC_DOI
);
2794 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
2798 for (a
= proposal
; a
; a
= a
->next
) {
2799 for (b
= a
->head
; b
; b
= b
->next
) {
2800 q
= setph2proposal0(iph2
, a
, b
);
2806 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
2807 if (iph2
->sa
== NULL
) {
2808 plog(LLV_ERROR
, LOCATION
, NULL
,
2809 "failed to allocate my sa buffer\n");
2814 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
2816 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
2818 prop
->h
.np
= ISAKMP_NPTYPE_P
;
2820 propoff
= iph2
->sa
->l
- q
->l
;
2830 * return 1 if all of the proposed protocols are transport mode.
2833 ipsecdoi_transportmode(iph2
)
2834 struct ph2handle
*iph2
;
2837 struct saproto
*pr
= NULL
;
2839 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
2840 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
2841 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
)
2850 ipsecdoi_get_defaultlifetime()
2852 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
2856 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
2857 int proto_id
, enc
, auth
, comp
;
2859 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
2861 case IPSECDOI_PROTO_IPSEC_ESP
:
2862 if (enc
== 0 || comp
!= 0) {
2863 plog(LLV_ERROR
, LOCATION
, NULL
,
2864 "illegal algorithm defined "
2865 "ESP enc=%s auth=%s comp=%s.\n",
2866 TMPALGTYPE2STR(enc
),
2867 TMPALGTYPE2STR(auth
),
2868 TMPALGTYPE2STR(comp
));
2872 case IPSECDOI_PROTO_IPSEC_AH
:
2873 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
2874 plog(LLV_ERROR
, LOCATION
, NULL
,
2875 "illegal algorithm defined "
2876 "AH enc=%s auth=%s comp=%s.\n",
2877 TMPALGTYPE2STR(enc
),
2878 TMPALGTYPE2STR(auth
),
2879 TMPALGTYPE2STR(comp
));
2883 case IPSECDOI_PROTO_IPCOMP
:
2884 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
2885 plog(LLV_ERROR
, LOCATION
, NULL
,
2886 "illegal algorithm defined "
2887 "IPcomp enc=%s auth=%s comp=%s.\n",
2888 TMPALGTYPE2STR(enc
),
2889 TMPALGTYPE2STR(auth
),
2890 TMPALGTYPE2STR(comp
));
2895 plog(LLV_ERROR
, LOCATION
, NULL
,
2896 "invalid ipsec protocol %d\n", proto_id
);
2899 #undef TMPALGTYPE2STR
2909 return IPSECDOI_PROTO_IPSEC_AH
;
2911 return IPSECDOI_PROTO_IPSEC_ESP
;
2912 case IPPROTO_IPCOMP
:
2913 return IPSECDOI_PROTO_IPCOMP
;
2915 return -1; /* XXX */
2923 case IPSECDOI_PROTO_IPSEC_AH
:
2925 case IPSECDOI_PROTO_IPSEC_ESP
:
2927 case IPSECDOI_PROTO_IPCOMP
:
2928 return IPPROTO_IPCOMP
;
2930 return -1; /* XXX */
2934 * check the following:
2935 * - In main mode with pre-shared key, only address type can be used.
2936 * - if proper type for phase 1 ?
2937 * - if phase 1 ID payload conformed RFC2407 4.6.2.
2938 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
2939 * - if ID payload sent from peer is equal to the ID expected by me.
2941 * both of "id" and "id_p" should be ID payload without general header,
2944 ipsecdoi_checkid1(iph1
)
2945 struct ph1handle
*iph1
;
2947 struct ipsecdoi_id_b
*id_b
;
2949 if (iph1
->id_p
== NULL
) {
2950 plog(LLV_ERROR
, LOCATION
, NULL
,
2951 "invalid iph1 passed id_p == NULL\n");
2952 return ISAKMP_INTERNAL_ERROR
;
2954 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
2955 plog(LLV_ERROR
, LOCATION
, NULL
,
2956 "invalid value passed as \"ident\" (len=%lu)\n",
2957 (u_long
)iph1
->id_p
->l
);
2958 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
2961 id_b
= (struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
2963 /* In main mode with pre-shared key, only address type can be used. */
2964 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
2965 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
) {
2966 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
2967 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
2968 plog(LLV_ERROR
, LOCATION
, NULL
,
2969 "Expecting IP address type in main mode, "
2970 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
2971 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
2975 /* if proper type for phase 1 ? */
2976 switch (id_b
->type
) {
2977 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
2978 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
2979 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
2980 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
2981 plog(LLV_WARNING
, LOCATION
, NULL
,
2982 "such ID type %s is not proper.\n",
2983 s_ipsecdoi_ident(id_b
->type
));
2987 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
2988 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
2989 && id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
2991 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
2992 plog(LLV_WARNING
, LOCATION
, NULL
,
2993 "protocol ID and Port mismatched. "
2994 "proto_id:%d port:%d\n",
2995 id_b
->proto_id
, ntohs(id_b
->port
));
2998 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3000 * copmaring with expecting port.
3001 * always permit if port is equal to PORT_ISAKMP
3003 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3007 switch (iph1
->remote
->sa_family
) {
3009 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3013 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3017 plog(LLV_ERROR
, LOCATION
, NULL
,
3018 "invalid family: %d\n",
3019 iph1
->remote
->sa_family
);
3020 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3022 if (ntohs(id_b
->port
) != port
) {
3023 plog(LLV_WARNING
, LOCATION
, NULL
,
3024 "port %d expected, but %d\n",
3025 port
, ntohs(id_b
->port
));
3032 /* compare with the ID if specified. */
3033 if (iph1
->rmconf
->idv_p
) {
3034 vchar_t
*ident0
= NULL
;
3037 /* check the type of both IDs */
3038 if (iph1
->rmconf
->idvtype_p
!= doi2idtype(id_b
->type
)) {
3039 plog(LLV_WARNING
, LOCATION
, NULL
,
3040 "ID type mismatched.\n");
3041 if (iph1
->rmconf
->verify_identifier
)
3042 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3045 /* compare defined ID with the ID sent by peer. */
3046 ident0
= getidval(iph1
->rmconf
->idvtype_p
, iph1
->rmconf
->idv_p
);
3048 switch (iph1
->rmconf
->idvtype_p
) {
3050 ident
.v
= (caddr_t
)(id_b
+ 1);
3051 ident
.l
= ident0
->l
;
3052 if (eay_cmp_asn1dn(ident0
, &ident
)) {
3053 plog(LLV_WARNING
, LOCATION
, NULL
,
3054 "ID value mismatched.\n");
3055 if (iph1
->rmconf
->verify_identifier
)
3056 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3060 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
)) {
3061 plog(LLV_WARNING
, LOCATION
, NULL
,
3062 "ID value mismatched.\n");
3063 if (iph1
->rmconf
->verify_identifier
)
3064 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3075 * create ID payload for phase 1 and set into iph1->id.
3076 * NOT INCLUDING isakmp general header.
3077 * see, RFC2407 4.6.2.1
3080 ipsecdoi_setid1(iph1
)
3081 struct ph1handle
*iph1
;
3083 vchar_t
*ret
= NULL
;
3084 struct ipsecdoi_id_b id_b
;
3085 vchar_t
*ident
= NULL
;
3086 struct sockaddr
*ipid
= NULL
;
3093 switch (iph1
->rmconf
->idvtype
) {
3095 id_b
.type
= IPSECDOI_ID_FQDN
;
3096 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3098 case IDTYPE_USERFQDN
:
3099 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3100 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3103 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3104 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3106 #ifdef HAVE_SIGNING_C
3108 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3109 if (iph1
->rmconf
->idv
) {
3110 /* XXX it must be encoded to asn1dn. */
3111 ident
= vdup(iph1
->rmconf
->idv
);
3113 if (oakley_getmycert(iph1
) < 0) {
3114 plog(LLV_ERROR
, LOCATION
, NULL
,
3115 "failed to get own CERT.\n");
3118 ident
= eay_get_x509asn1subjectname(&iph1
->cert
->cert
);
3122 case IDTYPE_ADDRESS
:
3124 * if the value of the id type was set by the configuration
3125 * file, then use it. otherwise the value is get from local
3126 * ip address by using ike negotiation.
3128 if (iph1
->rmconf
->idv
)
3129 ipid
= (struct sockaddr
*)iph1
->rmconf
->idv
->v
;
3139 /* use IP address */
3140 switch (ipid
->sa_family
) {
3142 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3143 l
= sizeof(struct in_addr
);
3144 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3148 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3149 l
= sizeof(struct in6_addr
);
3150 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3154 plog(LLV_ERROR
, LOCATION
, NULL
,
3155 "invalid address family.\n");
3158 id_b
.proto_id
= IPPROTO_UDP
;
3159 id_b
.port
= htons(PORT_ISAKMP
);
3162 plog(LLV_ERROR
, LOCATION
, NULL
,
3163 "failed to get ID buffer.\n");
3166 memcpy(ident
->v
, p
, ident
->l
);
3170 plog(LLV_ERROR
, LOCATION
, NULL
,
3171 "failed to get ID buffer.\n");
3175 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3177 plog(LLV_ERROR
, LOCATION
, NULL
,
3178 "failed to get ID buffer.\n");
3182 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3183 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3187 plog(LLV_DEBUG
, LOCATION
, NULL
,
3188 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3196 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3205 vchar_t
*new = NULL
;
3209 else if (lcconf
->ident
[type
])
3210 new = vdup(lcconf
->ident
[type
]);
3215 /* it's only called by cfparse.y. */
3217 set_identifier(vpp
, type
, value
)
3218 vchar_t
**vpp
, *value
;
3221 vchar_t
*new = NULL
;
3223 /* simply return if value is null. */
3229 case IDTYPE_USERFQDN
:
3230 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3231 new = vmalloc(value
->l
- 1);
3234 memcpy(new->v
, value
->v
, new->l
);
3242 fp
= fopen(value
->v
, "r");
3244 plog(LLV_ERROR
, LOCATION
, NULL
,
3245 "can not open %s\n", value
->v
);
3249 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3250 new = vrealloc(new, tlen
+ len
);
3255 memcpy(new->v
+ tlen
, b
, len
);
3260 case IDTYPE_ADDRESS
:
3262 struct sockaddr
*sa
;
3264 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3268 sa
= str2saddr(value
->v
, NULL
);
3270 plog(LLV_ERROR
, LOCATION
, NULL
,
3271 "invalid ip address %s\n", value
->v
);
3275 new = vmalloc(sa
->sa_len
);
3278 memcpy(new->v
, sa
, new->l
);
3282 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
3294 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3295 * NOT INCLUDING isakmp general header.
3296 * this function is for initiator. responder will get to copy from payload.
3297 * responder ID type is always address type.
3298 * see, RFC2407 4.6.2.1
3301 ipsecdoi_setid2(iph2
)
3302 struct ph2handle
*iph2
;
3304 struct secpolicy
*sp
;
3306 /* check there is phase 2 handler ? */
3307 sp
= getspbyspid(iph2
->spid
);
3309 plog(LLV_ERROR
, LOCATION
, NULL
,
3310 "no policy found for spid:%lu.\n", iph2
->spid
);
3314 if (!iph2
->sainfo
->idv
) {
3315 iph2
->id
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.src
,
3316 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
3317 if (iph2
->id
== NULL
) {
3318 plog(LLV_ERROR
, LOCATION
, NULL
,
3319 "failed to get ID for %s\n",
3320 spidx2str(&sp
->spidx
));
3323 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
3324 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
3326 struct ipsecdoi_id_b id_b
;
3329 id_b
.type
= idtype2doi(iph2
->sainfo
->idvtype
);
3333 ident
= getidval(iph2
->sainfo
->idvtype
, iph2
->sainfo
->idv
);
3335 plog(LLV_ERROR
, LOCATION
, NULL
,
3336 "failed to get ID value.\n");
3339 iph2
->id
= vmalloc(sizeof(id_b
) + ident
->l
);
3340 if (iph2
->id
== NULL
) {
3341 plog(LLV_ERROR
, LOCATION
, NULL
,
3342 "failed to get ID buffer.\n");
3347 memcpy(iph2
->id
->v
, &id_b
, sizeof(id_b
));
3348 memcpy(iph2
->id
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3353 iph2
->id_p
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.dst
,
3354 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
3355 if (iph2
->id_p
== NULL
) {
3356 plog(LLV_ERROR
, LOCATION
, NULL
,
3357 "failed to get ID for %s\n",
3358 spidx2str(&sp
->spidx
));
3363 plog(LLV_DEBUG
, LOCATION
, NULL
,
3364 "use remote ID type %s\n",
3365 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
3371 * set address type of ID.
3372 * NOT INCLUDING general header.
3375 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
3376 struct sockaddr
*saddr
;
3381 int type
, len1
, len2
;
3386 * Q. When type is SUBNET, is it allowed to be ::1/128.
3387 * A. Yes. (consensus at bake-off)
3389 switch (saddr
->sa_family
) {
3391 len1
= sizeof(struct in_addr
);
3392 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
3393 type
= IPSECDOI_ID_IPV4_ADDR
;
3396 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
3397 len2
= sizeof(struct in_addr
);
3399 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
3400 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
3404 len1
= sizeof(struct in6_addr
);
3405 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
3406 type
= IPSECDOI_ID_IPV6_ADDR
;
3409 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
3410 len2
= sizeof(struct in6_addr
);
3412 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
3413 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
3417 plog(LLV_ERROR
, LOCATION
, NULL
,
3418 "invalid family: %d.\n", saddr
->sa_family
);
3423 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
3425 plog(LLV_ERROR
, LOCATION
, NULL
,
3426 "failed to get ID buffer.\n");
3430 memset(new->v
, 0, new->l
);
3432 /* set the part of header. */
3433 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
3435 /* set ul_proto and port */
3437 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3438 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3440 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
3441 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
3442 ((struct ipsecdoi_id_b
*)new->v
)->port
=
3443 port
== IPSEC_PORT_ANY
? 0 : port
;
3444 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
3450 u_char
*p
= new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
;
3451 u_int bits
= prefixlen
;
3459 *p
= ~((1 << (8 - bits
)) - 1);
3466 * create sockaddr structure from ID payload (buf).
3467 * buffers (saddr, prefixlen, ul_proto) must be allocated.
3468 * see, RFC2407 4.6.2.1
3471 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
3473 struct sockaddr
*saddr
;
3474 u_int8_t
*prefixlen
;
3475 u_int16_t
*ul_proto
;
3477 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)buf
->v
;
3481 * When a ID payload of subnet type with a IP address of full bit
3482 * masked, it has to be processed as host address.
3483 * e.g. below 2 type are same.
3484 * type = ipv6 subnet, data = 2001::1/128
3485 * type = ipv6 address, data = 2001::1
3487 switch (id_b
->type
) {
3488 case IPSECDOI_ID_IPV4_ADDR
:
3489 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3490 saddr
->sa_len
= sizeof(struct sockaddr_in
);
3491 saddr
->sa_family
= AF_INET
;
3492 ((struct sockaddr_in
*)saddr
)->sin_port
=
3495 : id_b
->port
); /* see sockaddr2id() */
3496 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
3497 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
3500 case IPSECDOI_ID_IPV6_ADDR
:
3501 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3502 saddr
->sa_len
= sizeof(struct sockaddr_in6
);
3503 saddr
->sa_family
= AF_INET6
;
3504 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
3507 : id_b
->port
); /* see sockaddr2id() */
3508 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
3509 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
3513 plog(LLV_ERROR
, LOCATION
, NULL
,
3514 "unsupported ID type %d\n", id_b
->type
);
3515 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3518 /* get prefix length */
3519 switch (id_b
->type
) {
3520 case IPSECDOI_ID_IPV4_ADDR
:
3521 plen
= sizeof(struct in_addr
) << 3;
3524 case IPSECDOI_ID_IPV6_ADDR
:
3525 plen
= sizeof(struct in6_addr
) << 3;
3528 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3530 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3535 int alen
= sizeof(struct in_addr
);
3537 switch (id_b
->type
) {
3538 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3539 alen
= sizeof(struct in_addr
);
3542 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3543 alen
= sizeof(struct in6_addr
);
3550 return ISAKMP_INTERNAL_ERROR
;
3552 /* get subnet mask length */
3557 + sizeof(struct ipsecdoi_id_b
)
3560 for (; *p
== 0xff; p
++) {
3583 *ul_proto
= id_b
->proto_id
== 0
3585 : id_b
->proto_id
; /* see sockaddr2id() */
3591 * make printable string from ID payload except of general header.
3597 static char buf
[256];
3606 * set IPsec data attributes into a proposal.
3607 * NOTE: MUST called per a transform.
3610 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
3611 struct isakmp_pl_t
*t
;
3616 struct isakmp_data
*d
, *prev
;
3622 tr
->trns_no
= t
->t_no
;
3623 tr
->trns_id
= t
->t_id
;
3625 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
3626 prev
= (struct isakmp_data
*)NULL
;
3627 d
= (struct isakmp_data
*)(t
+ 1);
3630 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
3631 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3633 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
3637 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
3638 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
3640 plog(LLV_DEBUG
, LOCATION
, NULL
,
3641 "type=%s, flag=0x%04x, lorv=%s\n",
3642 s_ipsecdoi_attr(type
), flag
,
3643 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
3646 case IPSECDOI_ATTR_SA_LD_TYPE
:
3648 int type
= ntohs(d
->lorv
);
3650 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
3651 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
3655 plog(LLV_WARNING
, LOCATION
, NULL
,
3656 "invalid life duration type. "
3658 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
3663 case IPSECDOI_ATTR_SA_LD
:
3665 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
3666 IPSECDOI_ATTR_SA_LD_TYPE
) {
3667 plog(LLV_ERROR
, LOCATION
, NULL
,
3668 "life duration must follow ltype\n");
3674 vchar_t
*ld_buf
= NULL
;
3677 /* i.e. ISAKMP_GEN_TV */
3678 ld_buf
= vmalloc(sizeof(d
->lorv
));
3679 if (ld_buf
== NULL
) {
3680 plog(LLV_ERROR
, LOCATION
, NULL
,
3681 "failed to get LD buffer.\n");
3684 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
3686 int len
= ntohs(d
->lorv
);
3687 /* i.e. ISAKMP_GEN_TLV */
3688 ld_buf
= vmalloc(len
);
3689 if (ld_buf
== NULL
) {
3690 plog(LLV_ERROR
, LOCATION
, NULL
,
3691 "failed to get LD buffer.\n");
3694 memcpy(ld_buf
->v
, d
+ 1, len
);
3697 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
3698 t
= ipsecdoi_set_ld(ld_buf
);
3701 plog(LLV_ERROR
, LOCATION
, NULL
,
3702 "invalid life duration.\n");
3705 /* lifetime must be equal in a proposal. */
3706 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
3708 else if (pp
->lifetime
!= t
) {
3709 plog(LLV_ERROR
, LOCATION
, NULL
,
3710 "lifetime mismatched "
3712 "prev:%ld curr:%ld.\n",
3717 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
3718 t
= ipsecdoi_set_ld(ld_buf
);
3721 plog(LLV_ERROR
, LOCATION
, NULL
,
3722 "invalid life duration.\n");
3725 /* lifebyte must be equal in a proposal. */
3726 if (pp
->lifebyte
== 0)
3728 else if (pp
->lifebyte
!= t
) {
3729 plog(LLV_ERROR
, LOCATION
, NULL
,
3730 "lifebyte mismatched "
3732 "prev:%ld curr:%ld.\n",
3739 plog(LLV_ERROR
, LOCATION
, NULL
,
3740 "invalid life type: %d\n", life_t
);
3746 case IPSECDOI_ATTR_GRP_DESC
:
3748 * RFC2407: 4.5 IPSEC Security Association Attributes
3749 * Specifies the Oakley Group to be used in a PFS QM
3750 * negotiation. For a list of supported values, see
3751 * Appendix A of [IKE].
3753 if (pp
->pfs_group
== 0)
3754 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
3755 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
3756 plog(LLV_ERROR
, LOCATION
, NULL
,
3757 "pfs_group mismatched "
3758 "in a proposal.\n");
3763 case IPSECDOI_ATTR_ENC_MODE
:
3765 && pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
3766 plog(LLV_ERROR
, LOCATION
, NULL
,
3767 "multiple encmode exist "
3768 "in a transform.\n");
3771 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
3774 case IPSECDOI_ATTR_AUTH
:
3775 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
3776 plog(LLV_ERROR
, LOCATION
, NULL
,
3777 "multiple authtype exist "
3778 "in a transform.\n");
3781 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
3784 case IPSECDOI_ATTR_KEY_LENGTH
:
3785 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
3786 plog(LLV_ERROR
, LOCATION
, NULL
,
3787 "key length defined but not ESP");
3790 tr
->encklen
= ntohs(d
->lorv
);
3793 case IPSECDOI_ATTR_KEY_ROUNDS
:
3794 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
3795 case IPSECDOI_ATTR_COMP_PRIVALG
:
3803 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
3805 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
3806 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
3816 ipsecdoi_authalg2trnsid(alg
)
3820 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
3821 return IPSECDOI_AH_MD5
;
3822 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
3823 return IPSECDOI_AH_SHA
;
3824 case IPSECDOI_ATTR_AUTH_DES_MAC
:
3825 return IPSECDOI_AH_DES
;
3826 case IPSECDOI_ATTR_AUTH_KPDK
:
3827 return IPSECDOI_AH_MD5
; /* XXX */
3829 plog(LLV_ERROR
, LOCATION
, NULL
,
3830 "invalid authentication algorithm:%d\n", alg
);
3837 fixup_initiator_sa(match
, received
)
3838 struct isakmpsa
*match
, *received
;
3840 struct isakmpsa
*newsa
;
3842 if (received
->gssid
== NULL
)
3845 newsa
= newisakmpsa();
3846 memcpy(newsa
, match
, sizeof *newsa
);
3848 if (match
->dhgrp
!= NULL
) {
3849 newsa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
3850 memcpy(newsa
->dhgrp
, match
->dhgrp
, sizeof (struct dhgroup
));
3853 newsa
->rmconf
= NULL
;
3855 newsa
->gssid
= vdup(received
->gssid
);
3861 static int rm_idtype2doi
[] = {
3863 IPSECDOI_ID_USER_FQDN
,
3865 -1, /* it's type of "address"
3866 * it expands into 4 types by another function. */
3867 IPSECDOI_ID_DER_ASN1_DN
,
3871 * convert idtype to DOI value.
3879 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
3880 return rm_idtype2doi
[idtype
];
3889 case IPSECDOI_ID_FQDN
:
3890 return(IDTYPE_FQDN
);
3891 case IPSECDOI_ID_USER_FQDN
:
3892 return(IDTYPE_USERFQDN
);
3893 case IPSECDOI_ID_KEY_ID
:
3894 return(IDTYPE_KEYID
);
3895 case IPSECDOI_ID_DER_ASN1_DN
:
3896 return(IDTYPE_ASN1DN
);
3897 case IPSECDOI_ID_IPV4_ADDR
:
3898 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3899 case IPSECDOI_ID_IPV6_ADDR
:
3900 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3901 return(IDTYPE_ADDRESS
);
3903 plog(LLV_WARNING
, LOCATION
, NULL
,
3904 "Inproper idtype:%d in this function.\n",
3905 s_ipsecdoi_ident(doi
));
3906 return(IDTYPE_ADDRESS
); /* XXX */