1 /* $KAME: ipsec_doi.c,v 1.158 2002/09/27 05:55:52 itojun 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"
83 #include "isakmp_natd.h"
89 int verbose_proposal_check
= 1;
91 static vchar_t
*get_ph1approval
__P((struct ph1handle
*, struct prop_pair
**));
92 static struct isakmpsa
*get_ph1approvalx
__P((struct prop_pair
*,
93 struct isakmpsa
*, struct isakmpsa
*));
94 static void print_ph1mismatched
__P((struct prop_pair
*, struct isakmpsa
*));
95 static int t2isakmpsa
__P((struct isakmp_pl_t
*, struct isakmpsa
*));
96 static int cmp_aproppair_i
__P((struct prop_pair
*, struct prop_pair
*));
97 static struct prop_pair
*get_ph2approval
__P((struct ph2handle
*,
98 struct prop_pair
**));
99 static struct prop_pair
*get_ph2approvalx
__P((struct ph2handle
*,
100 struct prop_pair
*));
101 static void free_proppair0
__P((struct prop_pair
*));
103 static int get_transform
104 __P((struct isakmp_pl_p
*, struct prop_pair
**, int *));
105 static u_int32_t ipsecdoi_set_ld
__P((vchar_t
*));
107 static int check_doi
__P((u_int32_t
));
108 static int check_situation
__P((u_int32_t
));
110 static int check_prot_main
__P((int));
111 static int check_prot_quick
__P((int));
112 static int (*check_protocol
[]) __P((int)) = {
113 check_prot_main
, /* IPSECDOI_TYPE_PH1 */
114 check_prot_quick
, /* IPSECDOI_TYPE_PH2 */
117 static int check_spi_size
__P((int, int));
119 static int check_trns_isakmp
__P((int));
120 static int check_trns_ah
__P((int));
121 static int check_trns_esp
__P((int));
122 static int check_trns_ipcomp
__P((int));
123 static int (*check_transform
[]) __P((int)) = {
125 check_trns_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
126 check_trns_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
127 check_trns_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
128 check_trns_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
131 static int check_attr_isakmp
__P((struct isakmp_pl_t
*));
132 static int check_attr_ah
__P((struct isakmp_pl_t
*));
133 static int check_attr_esp
__P((struct isakmp_pl_t
*));
134 static int check_attr_ipsec
__P((int, struct isakmp_pl_t
*));
135 static int check_attr_ipcomp
__P((struct isakmp_pl_t
*));
136 static int (*check_attributes
[]) __P((struct isakmp_pl_t
*)) = {
138 check_attr_isakmp
, /* IPSECDOI_PROTO_ISAKMP */
139 check_attr_ah
, /* IPSECDOI_PROTO_IPSEC_AH */
140 check_attr_esp
, /* IPSECDOI_PROTO_IPSEC_ESP */
141 check_attr_ipcomp
, /* IPSECDOI_PROTO_IPCOMP */
144 static int setph1prop
__P((struct isakmpsa
*, caddr_t
));
145 static int setph1trns
__P((struct isakmpsa
*, caddr_t
));
146 static int setph1attr
__P((struct isakmpsa
*, caddr_t
));
147 static vchar_t
*setph2proposal0
__P((const struct ph2handle
*,
148 const struct saprop
*, const struct saproto
*));
150 static vchar_t
*getidval
__P((int, vchar_t
*));
153 static struct isakmpsa
*fixup_initiator_sa
__P((struct isakmpsa
*,
159 * check phase 1 SA payload.
160 * make new SA payload to be replyed not including general header.
161 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
163 * positive: the pointer to new buffer of SA payload.
164 * network byte order.
165 * NULL : error occurd.
168 ipsecdoi_checkph1proposal(sa
, iph1
)
170 struct ph1handle
*iph1
;
172 vchar_t
*newsa
; /* new SA payload approved. */
173 struct prop_pair
**pair
;
175 /* get proposal pair */
176 pair
= get_proppair(sa
, IPSECDOI_TYPE_PH1
);
180 /* check and get one SA for use */
181 newsa
= get_ph1approval(iph1
, pair
);
188 iph1
->sa_ret
= newsa
;
194 * acceptable check for remote configuration.
195 * return a new SA payload to be reply to peer.
198 get_ph1approval(iph1
, pair
)
199 struct ph1handle
*iph1
;
200 struct prop_pair
**pair
;
203 struct isakmpsa
*sa
, tsa
;
204 struct prop_pair
*s
, *p
;
208 iph1
->approval
= NULL
;
210 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
213 for (s
= pair
[i
]; s
; s
= s
->next
) {
214 prophlen
= sizeof(struct isakmp_pl_p
)
216 /* compare proposal and select one */
217 for (p
= s
; p
; p
= p
->tnext
) {
218 sa
= get_ph1approvalx(p
, iph1
->rmconf
->proposal
,
227 * if there is no suitable proposal, racoon complains about all of
228 * mismatched items in those proposal.
230 if (verbose_proposal_check
) {
231 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
234 for (s
= pair
[i
]; s
; s
= s
->next
) {
235 prophlen
= sizeof(struct isakmp_pl_p
)
237 for (p
= s
; p
; p
= p
->tnext
) {
238 print_ph1mismatched(p
,
239 iph1
->rmconf
->proposal
);
244 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable proposal found.\n");
249 plog(LLV_DEBUG
, LOCATION
, NULL
, "an acceptable proposal found.\n");
251 /* check DH group settings */
253 if (sa
->dhgrp
->prime
&& sa
->dhgrp
->gen1
) {
257 plog(LLV_WARNING
, LOCATION
, NULL
,
258 "invalid DH parameter found, use default.\n");
259 oakley_dhgrp_free(sa
->dhgrp
);
262 if (oakley_setdhgroup(sa
->dh_group
, &sa
->dhgrp
) == -1) {
269 if (sa
->gssid
!= NULL
)
270 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id in new sa '%s'\n",
272 if (iph1
-> side
== INITIATOR
) {
273 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
274 iph1
->gi_i
= vdup(iph1
->rmconf
->proposal
->gssid
);
275 if (tsa
.gssid
!= NULL
)
276 iph1
->gi_r
= vdup(tsa
.gssid
);
277 iph1
->approval
= fixup_initiator_sa(sa
, &tsa
);
279 if (tsa
.gssid
!= NULL
) {
280 iph1
->gi_r
= vdup(tsa
.gssid
);
281 if (iph1
->rmconf
->proposal
->gssid
!= NULL
)
283 vdup(iph1
->rmconf
->proposal
->gssid
);
285 iph1
->gi_i
= gssapi_get_default_id(iph1
);
286 if (sa
->gssid
== NULL
&& iph1
->gi_i
!= NULL
)
287 sa
->gssid
= vdup(iph1
->gi_i
);
291 if (iph1
->gi_i
!= NULL
)
292 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIi is %*s\n",
293 iph1
->gi_i
->l
, iph1
->gi_i
->v
);
294 if (iph1
->gi_r
!= NULL
)
295 plog(LLV_DEBUG
, LOCATION
, NULL
, "GIr is %*s\n",
296 iph1
->gi_r
->l
, iph1
->gi_r
->v
);
301 newsa
= get_sabyproppair(p
, iph1
);
303 iph1
->approval
= NULL
;
309 * compare peer's single proposal and all of my proposal.
310 * and select one if suiatable.
311 * p : one of peer's proposal.
312 * proposal: my proposals.
314 static struct isakmpsa
*
315 get_ph1approvalx(p
, proposal
, sap
)
317 struct isakmpsa
*proposal
, *sap
;
319 struct isakmp_pl_p
*prop
= p
->prop
;
320 struct isakmp_pl_t
*trns
= p
->trns
;
321 struct isakmpsa sa
, *s
, *tsap
;
323 plog(LLV_DEBUG
, LOCATION
, NULL
,
324 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
325 prop
->p_no
, s_ipsecdoi_proto(prop
->proto_id
),
326 prop
->spi_size
, prop
->num_t
);
328 plog(LLV_DEBUG
, LOCATION
, NULL
,
329 "trns#=%d, trns-id=%s\n",
331 s_ipsecdoi_trns(prop
->proto_id
, trns
->t_id
));
333 tsap
= sap
!= NULL
? sap
: &sa
;
335 memset(tsap
, 0, sizeof(*tsap
));
336 if (t2isakmpsa(trns
, tsap
) < 0)
338 for (s
= proposal
; s
!= NULL
; s
= s
->next
) {
339 plog(LLV_DEBUG
, LOCATION
, NULL
, "Compared: DB:Peer\n");
340 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifetime = %ld:%ld)\n",
341 s
->lifetime
, tsap
->lifetime
);
342 plog(LLV_DEBUG
, LOCATION
, NULL
, "(lifebyte = %ld:%ld)\n",
343 s
->lifebyte
, tsap
->lifebyte
);
344 plog(LLV_DEBUG
, LOCATION
, NULL
, "enctype = %s:%s\n",
345 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
347 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
349 plog(LLV_DEBUG
, LOCATION
, NULL
, "(encklen = %d:%d)\n",
350 s
->encklen
, tsap
->encklen
);
351 plog(LLV_DEBUG
, LOCATION
, NULL
, "hashtype = %s:%s\n",
352 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
354 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
356 plog(LLV_DEBUG
, LOCATION
, NULL
, "authmethod = %s:%s\n",
357 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
359 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
361 plog(LLV_DEBUG
, LOCATION
, NULL
, "dh_group = %s:%s\n",
362 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
364 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
367 /* XXX to be considered */
368 if (tsap
->lifetime
> s
->lifetime
) ;
369 if (tsap
->lifebyte
> s
->lifebyte
) ;
372 * if responder side and peer's key length in proposal
373 * is bigger than mine, it might be accepted.
375 if(tsap
->enctype
== s
->enctype
376 && tsap
->authmethod
== s
->authmethod
377 && tsap
->hashtype
== s
->hashtype
378 && tsap
->dh_group
== s
->dh_group
379 && tsap
->encklen
== s
->encklen
)
383 if (tsap
->dhgrp
!= NULL
)
384 oakley_dhgrp_free(tsap
->dhgrp
);
389 * print all of items in peer's proposal which are mismatched to my proposal.
390 * p : one of peer's proposal.
391 * proposal: my proposals.
394 print_ph1mismatched(p
, proposal
)
396 struct isakmpsa
*proposal
;
398 struct isakmpsa sa
, *s
;
400 memset(&sa
, 0, sizeof(sa
));
401 if (t2isakmpsa(p
->trns
, &sa
) < 0)
403 for (s
= proposal
; s
; s
= s
->next
) {
404 if (sa
.enctype
!= s
->enctype
) {
405 plog(LLV_ERROR
, LOCATION
, NULL
,
407 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
409 s
->prop_no
, s
->trns_no
,
410 p
->prop
->p_no
, p
->trns
->t_no
,
411 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
413 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG
,
416 if (sa
.authmethod
!= s
->authmethod
) {
417 plog(LLV_ERROR
, LOCATION
, NULL
,
418 "rejected authmethod: "
419 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
421 s
->prop_no
, s
->trns_no
,
422 p
->prop
->p_no
, p
->trns
->t_no
,
423 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
425 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD
,
428 if (sa
.hashtype
!= s
->hashtype
) {
429 plog(LLV_ERROR
, LOCATION
, NULL
,
430 "rejected hashtype: "
431 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
433 s
->prop_no
, s
->trns_no
,
434 p
->prop
->p_no
, p
->trns
->t_no
,
435 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
437 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG
,
440 if (sa
.dh_group
!= s
->dh_group
) {
441 plog(LLV_ERROR
, LOCATION
, NULL
,
442 "rejected dh_group: "
443 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
445 s
->prop_no
, s
->trns_no
,
446 p
->prop
->p_no
, p
->trns
->t_no
,
447 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
449 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC
,
454 if (sa
.dhgrp
!= NULL
)
455 oakley_dhgrp_free(sa
.dhgrp
);
459 * get ISAKMP data attributes
463 struct isakmp_pl_t
*trns
;
466 struct isakmp_data
*d
, *prev
;
475 tlen
= ntohs(trns
->h
.len
) - sizeof(*trns
);
476 prev
= (struct isakmp_data
*)NULL
;
477 d
= (struct isakmp_data
*)(trns
+ 1);
480 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
481 sa
->lifetime
= OAKLEY_ATTR_SA_LD_SEC_DEFAULT
;
483 sa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
489 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
490 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
492 plog(LLV_DEBUG
, LOCATION
, NULL
,
493 "type=%s, flag=0x%04x, lorv=%s\n",
494 s_oakley_attr(type
), flag
,
495 s_oakley_attr_v(type
, ntohs(d
->lorv
)));
497 /* get variable-sized item */
499 case OAKLEY_ATTR_GRP_PI
:
500 case OAKLEY_ATTR_GRP_GEN_ONE
:
501 case OAKLEY_ATTR_GRP_GEN_TWO
:
502 case OAKLEY_ATTR_GRP_CURVE_A
:
503 case OAKLEY_ATTR_GRP_CURVE_B
:
504 case OAKLEY_ATTR_SA_LD
:
505 case OAKLEY_ATTR_GRP_ORDER
:
508 p
= (u_char
*)&d
->lorv
;
510 len
= ntohs(d
->lorv
);
511 p
= (u_char
*)(d
+ 1);
516 memcpy(val
->v
, p
, len
);
524 case OAKLEY_ATTR_ENC_ALG
:
525 sa
->enctype
= (u_int16_t
)ntohs(d
->lorv
);
528 case OAKLEY_ATTR_HASH_ALG
:
529 sa
->hashtype
= (u_int16_t
)ntohs(d
->lorv
);
532 case OAKLEY_ATTR_AUTH_METHOD
:
533 sa
->authmethod
= ntohs(d
->lorv
);
536 case OAKLEY_ATTR_GRP_DESC
:
537 sa
->dh_group
= (u_int16_t
)ntohs(d
->lorv
);
540 case OAKLEY_ATTR_GRP_TYPE
:
542 int type
= (int)ntohs(d
->lorv
);
543 if (type
== OAKLEY_ATTR_GRP_TYPE_MODP
)
544 sa
->dhgrp
->type
= type
;
549 case OAKLEY_ATTR_GRP_PI
:
550 sa
->dhgrp
->prime
= val
;
553 case OAKLEY_ATTR_GRP_GEN_ONE
:
556 sa
->dhgrp
->gen1
= ntohs(d
->lorv
);
558 int len
= ntohs(d
->lorv
);
562 memcpy(&sa
->dhgrp
->gen1
, d
+ 1, len
);
563 sa
->dhgrp
->gen1
= ntohl(sa
->dhgrp
->gen1
);
567 case OAKLEY_ATTR_GRP_GEN_TWO
:
570 sa
->dhgrp
->gen2
= ntohs(d
->lorv
);
572 int len
= ntohs(d
->lorv
);
576 memcpy(&sa
->dhgrp
->gen2
, d
+ 1, len
);
577 sa
->dhgrp
->gen2
= ntohl(sa
->dhgrp
->gen2
);
581 case OAKLEY_ATTR_GRP_CURVE_A
:
582 sa
->dhgrp
->curve_a
= val
;
585 case OAKLEY_ATTR_GRP_CURVE_B
:
586 sa
->dhgrp
->curve_b
= val
;
589 case OAKLEY_ATTR_SA_LD_TYPE
:
591 int type
= (int)ntohs(d
->lorv
);
593 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
594 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
598 life_t
= OAKLEY_ATTR_SA_LD_TYPE_DEFAULT
;
603 case OAKLEY_ATTR_SA_LD
:
605 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
606 OAKLEY_ATTR_SA_LD_TYPE
) {
607 plog(LLV_ERROR
, LOCATION
, NULL
,
608 "life duration must follow ltype\n");
613 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
614 sa
->lifetime
= ipsecdoi_set_ld(val
);
616 if (sa
->lifetime
== 0) {
617 plog(LLV_ERROR
, LOCATION
, NULL
,
618 "invalid life duration.\n");
622 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
623 sa
->lifebyte
= ipsecdoi_set_ld(val
);
625 if (sa
->lifetime
== 0) {
626 plog(LLV_ERROR
, LOCATION
, NULL
,
627 "invalid life duration.\n");
633 plog(LLV_ERROR
, LOCATION
, NULL
,
634 "invalid life type: %d\n", life_t
);
639 case OAKLEY_ATTR_KEY_LEN
:
641 int len
= ntohs(d
->lorv
);
643 plog(LLV_ERROR
, LOCATION
, NULL
,
644 "keylen %d: not multiple of 8\n",
648 sa
->encklen
= (u_int16_t
)len
;
652 case OAKLEY_ATTR_PRF
:
653 case OAKLEY_ATTR_FIELD_SIZE
:
657 case OAKLEY_ATTR_GRP_ORDER
:
658 sa
->dhgrp
->order
= val
;
661 case OAKLEY_ATTR_GSS_ID
:
663 int len
= ntohs(d
->lorv
);
665 sa
->gssid
= vmalloc(len
);
666 memcpy(sa
->gssid
->v
, d
+ 1, len
);
667 plog(LLV_DEBUG
, LOCATION
, NULL
,
668 "received gss id '%s' (len %d)\n", sa
->gssid
->v
,
681 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
683 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
684 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
) + ntohs(d
->lorv
));
688 /* key length must not be specified on some algorithms */
690 if (sa
->enctype
== OAKLEY_ATTR_ENC_ALG_DES
691 #ifdef HAVE_OPENSSL_IDEA_H
692 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_IDEA
694 || sa
->enctype
== OAKLEY_ATTR_ENC_ALG_3DES
) {
695 plog(LLV_ERROR
, LOCATION
, NULL
,
696 "keylen must not be specified "
697 "for encryption algorithm %d\n",
710 * check phase 2 SA payload and select single proposal.
711 * make new SA payload to be replyed not including general header.
712 * This function is called by responder only.
718 ipsecdoi_selectph2proposal(iph2
)
719 struct ph2handle
*iph2
;
721 struct prop_pair
**pair
;
722 struct prop_pair
*ret
;
724 /* get proposal pair */
725 pair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
729 /* check and select a proposal. */
730 ret
= get_ph2approval(iph2
, pair
);
735 /* make a SA to be replayed. */
736 /* SPI must be updated later. */
737 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
:
2088 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2089 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2090 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2091 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2094 plog(LLV_ERROR
, LOCATION
, NULL
,
2095 "invalid encryption mode=%u.\n",
2101 case IPSECDOI_ATTR_AUTH
:
2103 plog(LLV_ERROR
, LOCATION
, NULL
,
2104 "must be TV when AUTH.\n");
2109 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2110 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
2111 && trns
->t_id
!= IPSECDOI_AH_MD5
) {
2113 plog(LLV_ERROR
, LOCATION
, NULL
,
2114 "auth algorithm %u conflicts "
2115 "with transform %u.\n",
2120 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2121 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2122 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2126 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2127 case IPSECDOI_ATTR_AUTH_KPDK
:
2128 plog(LLV_ERROR
, LOCATION
, NULL
,
2129 "auth algorithm %u isn't supported.\n",
2133 plog(LLV_ERROR
, LOCATION
, NULL
,
2134 "invalid auth algorithm=%u.\n",
2140 case IPSECDOI_ATTR_SA_LD_TYPE
:
2142 plog(LLV_ERROR
, LOCATION
, NULL
,
2143 "must be TV when LD_TYPE.\n");
2148 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2149 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2152 plog(LLV_ERROR
, LOCATION
, NULL
,
2153 "invalid life type %d.\n", lorv
);
2158 case IPSECDOI_ATTR_SA_LD
:
2160 /* i.e. ISAKMP_GEN_TV */
2161 plog(LLV_DEBUG
, LOCATION
, NULL
,
2162 "life duration was in TLV.\n");
2164 /* i.e. ISAKMP_GEN_TLV */
2166 plog(LLV_ERROR
, LOCATION
, NULL
,
2167 "invalid length of LD\n");
2173 case IPSECDOI_ATTR_GRP_DESC
:
2175 plog(LLV_ERROR
, LOCATION
, NULL
,
2176 "must be TV when GRP_DESC.\n");
2180 if (!alg_oakley_dhdef_ok(lorv
)) {
2181 plog(LLV_ERROR
, LOCATION
, NULL
,
2182 "invalid group description=%u.\n",
2188 case IPSECDOI_ATTR_KEY_LENGTH
:
2190 plog(LLV_ERROR
, LOCATION
, NULL
,
2191 "must be TV when KEY_LENGTH.\n");
2196 case IPSECDOI_ATTR_KEY_ROUNDS
:
2197 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2198 case IPSECDOI_ATTR_COMP_PRIVALG
:
2199 plog(LLV_ERROR
, LOCATION
, NULL
,
2200 "attr type=%u isn't supported.\n", type
);
2204 plog(LLV_ERROR
, LOCATION
, NULL
,
2205 "invalid attribute type %d.\n", type
);
2211 d
= (struct isakmp_data
*)((char *)d
2214 tlen
-= (sizeof(*d
) + lorv
);
2215 d
= (struct isakmp_data
*)((caddr_t
)d
2216 + sizeof(*d
) + lorv
);
2220 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
2221 && !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2222 plog(LLV_ERROR
, LOCATION
, NULL
,
2223 "attr AUTH must be present for AH.\n", type
);
2231 check_attr_ipcomp(trns
)
2232 struct isakmp_pl_t
*trns
;
2234 struct isakmp_data
*d
;
2238 int attrseen
[16]; /* XXX magic number */
2240 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2241 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2242 memset(attrseen
, 0, sizeof(attrseen
));
2245 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2246 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2247 lorv
= ntohs(d
->lorv
);
2249 plog(LLV_DEBUG
, LOCATION
, NULL
,
2250 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2253 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2257 case IPSECDOI_ATTR_ENC_MODE
:
2259 plog(LLV_ERROR
, LOCATION
, NULL
,
2260 "must be TV when ENC_MODE.\n");
2265 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2266 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2267 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
:
2268 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
:
2269 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
:
2270 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
:
2273 plog(LLV_ERROR
, LOCATION
, NULL
,
2274 "invalid encryption mode=%u.\n",
2280 case IPSECDOI_ATTR_SA_LD_TYPE
:
2282 plog(LLV_ERROR
, LOCATION
, NULL
,
2283 "must be TV when LD_TYPE.\n");
2288 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2289 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2292 plog(LLV_ERROR
, LOCATION
, NULL
,
2293 "invalid life type %d.\n", lorv
);
2298 case IPSECDOI_ATTR_SA_LD
:
2300 /* i.e. ISAKMP_GEN_TV */
2301 plog(LLV_DEBUG
, LOCATION
, NULL
,
2302 "life duration was in TLV.\n");
2304 /* i.e. ISAKMP_GEN_TLV */
2306 plog(LLV_ERROR
, LOCATION
, NULL
,
2307 "invalid length of LD\n");
2313 case IPSECDOI_ATTR_GRP_DESC
:
2315 plog(LLV_ERROR
, LOCATION
, NULL
,
2316 "must be TV when GRP_DESC.\n");
2320 if (!alg_oakley_dhdef_ok(lorv
)) {
2321 plog(LLV_ERROR
, LOCATION
, NULL
,
2322 "invalid group description=%u.\n",
2328 case IPSECDOI_ATTR_AUTH
:
2329 plog(LLV_ERROR
, LOCATION
, NULL
,
2330 "invalid attr type=%u.\n", type
);
2333 case IPSECDOI_ATTR_KEY_LENGTH
:
2334 case IPSECDOI_ATTR_KEY_ROUNDS
:
2335 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2336 case IPSECDOI_ATTR_COMP_PRIVALG
:
2337 plog(LLV_ERROR
, LOCATION
, NULL
,
2338 "attr type=%u isn't supported.\n", type
);
2342 plog(LLV_ERROR
, LOCATION
, NULL
,
2343 "invalid attribute type %d.\n", type
);
2349 d
= (struct isakmp_data
*)((char *)d
2352 tlen
-= (sizeof(*d
) + lorv
);
2353 d
= (struct isakmp_data
*)((caddr_t
)d
2354 + sizeof(*d
) + lorv
);
2359 if (proto_id
== IPSECDOI_PROTO_IPCOMP
2360 && !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2361 plog(LLV_ERROR
, LOCATION
, NULL
,
2362 "attr AUTH must be present for AH.\n", type
);
2372 * create phase1 proposal from remote configuration.
2373 * NOT INCLUDING isakmp general header of SA payload
2376 ipsecdoi_setph1proposal(props
)
2377 struct isakmpsa
*props
;
2382 /* count total size of SA minus isakmp general header */
2383 /* not including isakmp general header of SA payload */
2384 sablen
= sizeof(struct ipsecdoi_sa_b
);
2385 sablen
+= setph1prop(props
, NULL
);
2387 mysa
= vmalloc(sablen
);
2389 plog(LLV_ERROR
, LOCATION
, NULL
,
2390 "failed to allocate my sa buffer\n");
2394 /* create SA payload */
2395 /* not including isakmp general header */
2396 ((struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2397 ((struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2399 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2405 setph1prop(props
, buf
)
2406 struct isakmpsa
*props
;
2409 struct isakmp_pl_p
*prop
= NULL
;
2410 struct isakmpsa
*s
= NULL
;
2411 int proplen
, trnslen
;
2412 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2416 proplen
= sizeof(*prop
);
2418 /* create proposal */
2419 prop
= (struct isakmp_pl_p
*)p
;
2420 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2421 prop
->p_no
= props
->prop_no
;
2422 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2430 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2432 *np_t
= ISAKMP_NPTYPE_T
;
2434 trnslen
= setph1trns(s
, p
);
2437 /* save buffer to pre-next payload */
2438 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2441 /* count up transform length */
2446 /* update proposal length */
2448 prop
->h
.len
= htons(proplen
);
2449 prop
->num_t
= trns_num
;
2457 struct isakmpsa
*sa
;
2460 struct isakmp_pl_t
*trns
= NULL
;
2461 int trnslen
, attrlen
;
2464 trnslen
= sizeof(*trns
);
2466 /* create transform */
2467 trns
= (struct isakmp_pl_t
*)p
;
2468 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2469 trns
->t_no
= sa
->trns_no
;
2470 trns
->t_id
= IPSECDOI_KEY_IKE
;
2474 attrlen
= setph1attr(sa
, p
);
2480 trns
->h
.len
= htons(trnslen
);
2487 struct isakmpsa
*sa
;
2494 attrlen
+= sizeof(struct isakmp_data
)
2495 + sizeof(struct isakmp_data
);
2496 if (sa
->lifetime
> 0xffff)
2497 attrlen
+= sizeof(sa
->lifetime
);
2499 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2500 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2501 if (sa
->lifetime
> 0xffff) {
2502 u_int32_t v
= htonl((u_int32_t
)sa
->lifetime
);
2503 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2504 (caddr_t
)&v
, sizeof(v
));
2506 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2513 attrlen
+= sizeof(struct isakmp_data
)
2514 + sizeof(struct isakmp_data
);
2515 if (sa
->lifebyte
> 0xffff)
2516 attrlen
+= sizeof(sa
->lifebyte
);
2518 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2519 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2520 if (sa
->lifebyte
> 0xffff) {
2521 u_int32_t v
= htonl((u_int32_t
)sa
->lifebyte
);
2522 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2523 (caddr_t
)&v
, sizeof(v
));
2525 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2532 attrlen
+= sizeof(struct isakmp_data
);
2534 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2537 attrlen
+= sizeof(struct isakmp_data
);
2539 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2541 if (sa
->authmethod
) {
2542 attrlen
+= sizeof(struct isakmp_data
);
2544 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, sa
->authmethod
);
2547 attrlen
+= sizeof(struct isakmp_data
);
2549 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2551 switch (sa
->dh_group
) {
2552 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2553 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2554 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2555 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2556 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2557 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2558 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2559 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2560 /* don't attach group type for known groups */
2561 attrlen
+= sizeof(struct isakmp_data
);
2563 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2567 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2568 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2569 /* don't attach group type for known groups */
2570 attrlen
+= sizeof(struct isakmp_data
);
2572 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2573 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2582 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2583 sa
->gssid
!= NULL
) {
2584 attrlen
+= sizeof(struct isakmp_data
);
2585 attrlen
+= sa
->gssid
->l
;
2587 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %d, "
2588 "val '%s'\n", sa
->gssid
->l
, sa
->gssid
->v
);
2589 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2590 (caddr_t
)sa
->gssid
->v
,
2600 setph2proposal0(iph2
, pp
, pr
)
2601 const struct ph2handle
*iph2
;
2602 const struct saprop
*pp
;
2603 const struct saproto
*pr
;
2606 struct isakmp_pl_p
*prop
;
2607 struct isakmp_pl_t
*trns
;
2612 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2613 const u_int8_t
*spi
;
2615 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2619 /* create proposal */
2620 prop
= (struct isakmp_pl_p
*)p
->v
;
2621 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2622 prop
->p_no
= pp
->prop_no
;
2623 prop
->proto_id
= pr
->proto_id
;
2626 spi
= (const u_int8_t
*)&pr
->spi
;
2627 switch (pr
->proto_id
) {
2628 case IPSECDOI_PROTO_IPCOMP
:
2630 * draft-shacham-ippcp-rfc2393bis-05.txt:
2631 * construct 16bit SPI (CPI).
2632 * XXX we may need to provide a configuration option to
2633 * generate 32bit SPI. otherwise we cannot interoeprate
2634 * with nodes that uses 32bit SPI, in case we are initiator.
2636 prop
->spi_size
= sizeof(u_int16_t
);
2637 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2638 p
->l
-= sizeof(pr
->spi
);
2639 p
->l
+= sizeof(u_int16_t
);
2642 prop
->spi_size
= sizeof(pr
->spi
);
2645 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2647 /* create transform */
2648 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2651 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2654 *np_t
= ISAKMP_NPTYPE_T
;
2658 /* get attribute length */
2661 attrlen
+= sizeof(struct isakmp_data
)
2662 + sizeof(struct isakmp_data
);
2663 if (pp
->lifetime
> 0xffff)
2664 attrlen
+= sizeof(u_int32_t
);
2666 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2667 attrlen
+= sizeof(struct isakmp_data
)
2668 + sizeof(struct isakmp_data
);
2669 if (pp
->lifebyte
> 0xffff)
2670 attrlen
+= sizeof(u_int32_t
);
2672 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2674 attrlen
+= sizeof(struct isakmp_data
);
2676 switch (pr
->proto_id
) {
2677 case IPSECDOI_PROTO_IPSEC_ESP
:
2678 /* non authentication mode ? */
2679 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2680 attrlen
+= sizeof(struct isakmp_data
);
2682 case IPSECDOI_PROTO_IPSEC_AH
:
2683 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2684 plog(LLV_ERROR
, LOCATION
, NULL
,
2685 "no authentication algorithm found "
2686 "but protocol is AH.\n");
2690 attrlen
+= sizeof(struct isakmp_data
);
2692 case IPSECDOI_PROTO_IPCOMP
:
2695 plog(LLV_ERROR
, LOCATION
, NULL
,
2696 "invalid protocol: %d\n", pr
->proto_id
);
2701 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2702 attrlen
+= sizeof(struct isakmp_data
);
2704 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2707 prop
= (struct isakmp_pl_p
*)p
->v
;
2709 /* set transform's values */
2710 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2711 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2712 trns
->t_no
= tr
->trns_no
;
2713 trns
->t_id
= tr
->trns_id
;
2715 /* set attributes */
2716 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
2719 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2720 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
2721 if (pp
->lifetime
> 0xffff) {
2722 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
2723 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2724 (caddr_t
)&v
, sizeof(v
));
2726 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2731 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2732 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2733 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
2734 if (pp
->lifebyte
> 0xffff) {
2735 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
2736 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2737 (caddr_t
)&v
, sizeof(v
));
2739 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2744 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
2747 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
2749 /* mandatory check has done above. */
2750 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2751 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
2752 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
2754 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2755 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
2756 iph2
->sainfo
->pfs_group
);
2758 /* update length of this transform. */
2759 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2760 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
2762 /* save buffer to pre-next payload */
2765 trnsoff
+= (sizeof(*trns
) + attrlen
);
2768 /* update length of this protocol. */
2769 prop
->h
.len
= htons(p
->l
);
2775 * create phase2 proposal from policy configuration.
2776 * NOT INCLUDING isakmp general header of SA payload.
2777 * This function is called by initiator only.
2780 ipsecdoi_setph2proposal(iph2
)
2781 struct ph2handle
*iph2
;
2783 struct saprop
*proposal
, *a
;
2784 struct saproto
*b
= NULL
;
2786 struct ipsecdoi_sa_b
*sab
;
2787 struct isakmp_pl_p
*prop
;
2788 size_t propoff
; /* for previous field of type of next payload. */
2790 proposal
= iph2
->proposal
;
2792 iph2
->sa
= vmalloc(sizeof(*sab
));
2793 if (iph2
->sa
== NULL
) {
2794 plog(LLV_ERROR
, LOCATION
, NULL
,
2795 "failed to allocate my sa buffer\n");
2799 /* create SA payload */
2800 sab
= (struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
2801 sab
->doi
= htonl(IPSEC_DOI
);
2802 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
2806 for (a
= proposal
; a
; a
= a
->next
) {
2807 for (b
= a
->head
; b
; b
= b
->next
) {
2810 * Hack to fix encmode, we may have detected a nat since
2811 * we last set pr->encmode. We need to fix this if
2812 * we now have a NAT. NAT-T doesn't work with AH.
2815 if (iph2
->ph1
&& (nattype
= natd_hasnat(iph2
->ph1
)) &&
2816 b
->proto_id
!= IPSECDOI_PROTO_IPSEC_AH
)
2821 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2822 if (nattype
== natt_type_rfc
||
2823 nattype
== natt_type_apple
)
2824 b
->encmode
= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
;
2826 b
->encmode
= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
;
2828 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2829 if (nattype
== natt_type_rfc
||
2830 nattype
== natt_type_apple
)
2831 b
->encmode
= IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
;
2833 b
->encmode
= IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
;
2839 q
= setph2proposal0(iph2
, a
, b
);
2845 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
2846 if (iph2
->sa
== NULL
) {
2847 plog(LLV_ERROR
, LOCATION
, NULL
,
2848 "failed to allocate my sa buffer\n");
2853 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
2855 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
2857 prop
->h
.np
= ISAKMP_NPTYPE_P
;
2859 propoff
= iph2
->sa
->l
- q
->l
;
2869 * return 1 if all of the proposed protocols are tunnel mode.
2872 ipsecdoi_tunnelmode(iph2
)
2873 struct ph2handle
*iph2
;
2876 struct saproto
*pr
= NULL
;
2878 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
2879 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
2880 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TUNNEL
&&
2881 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC
&&
2882 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT
)
2891 * return 1 if all of the proposed protocols are transport mode.
2894 ipsecdoi_transportmode(iph2
)
2895 struct ph2handle
*iph2
;
2898 struct saproto
*pr
= NULL
;
2900 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
2901 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
2902 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
&&
2903 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC
&&
2904 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT
)
2914 ipsecdoi_get_defaultlifetime()
2916 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
2920 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
2921 int proto_id
, enc
, auth
, comp
;
2923 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
2925 case IPSECDOI_PROTO_IPSEC_ESP
:
2926 if (enc
== 0 || comp
!= 0) {
2927 plog(LLV_ERROR
, LOCATION
, NULL
,
2928 "illegal algorithm defined "
2929 "ESP enc=%s auth=%s comp=%s.\n",
2930 TMPALGTYPE2STR(enc
),
2931 TMPALGTYPE2STR(auth
),
2932 TMPALGTYPE2STR(comp
));
2936 case IPSECDOI_PROTO_IPSEC_AH
:
2937 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
2938 plog(LLV_ERROR
, LOCATION
, NULL
,
2939 "illegal algorithm defined "
2940 "AH enc=%s auth=%s comp=%s.\n",
2941 TMPALGTYPE2STR(enc
),
2942 TMPALGTYPE2STR(auth
),
2943 TMPALGTYPE2STR(comp
));
2947 case IPSECDOI_PROTO_IPCOMP
:
2948 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
2949 plog(LLV_ERROR
, LOCATION
, NULL
,
2950 "illegal algorithm defined "
2951 "IPcomp enc=%s auth=%s comp=%s.\n",
2952 TMPALGTYPE2STR(enc
),
2953 TMPALGTYPE2STR(auth
),
2954 TMPALGTYPE2STR(comp
));
2959 plog(LLV_ERROR
, LOCATION
, NULL
,
2960 "invalid ipsec protocol %d\n", proto_id
);
2963 #undef TMPALGTYPE2STR
2973 return IPSECDOI_PROTO_IPSEC_AH
;
2975 return IPSECDOI_PROTO_IPSEC_ESP
;
2976 case IPPROTO_IPCOMP
:
2977 return IPSECDOI_PROTO_IPCOMP
;
2979 return -1; /* XXX */
2987 case IPSECDOI_PROTO_IPSEC_AH
:
2989 case IPSECDOI_PROTO_IPSEC_ESP
:
2991 case IPSECDOI_PROTO_IPCOMP
:
2992 return IPPROTO_IPCOMP
;
2994 return -1; /* XXX */
2998 * check the following:
2999 * - In main mode with pre-shared key, only address type can be used.
3000 * - if proper type for phase 1 ?
3001 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3002 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3003 * - if ID payload sent from peer is equal to the ID expected by me.
3005 * both of "id" and "id_p" should be ID payload without general header,
3008 ipsecdoi_checkid1(iph1
)
3009 struct ph1handle
*iph1
;
3011 struct ipsecdoi_id_b
*id_b
;
3012 struct sockaddr
*sa
;
3015 if (iph1
->id_p
== NULL
) {
3016 plog(LLV_ERROR
, LOCATION
, NULL
,
3017 "invalid iph1 passed id_p == NULL\n");
3018 return ISAKMP_INTERNAL_ERROR
;
3020 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
3021 plog(LLV_ERROR
, LOCATION
, NULL
,
3022 "invalid value passed as \"ident\" (len=%lu)\n",
3023 (u_long
)iph1
->id_p
->l
);
3024 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3027 id_b
= (struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
3029 /* In main mode with pre-shared key, only address type can be used.
3030 If NAT Traversal draft 02 being used - allow this. */
3031 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
3032 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
3033 && !natd_hasnat(iph1
)) {
3034 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
3035 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
3036 plog(LLV_ERROR
, LOCATION
, NULL
,
3037 "Expecting IP address type in main mode, "
3038 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
3039 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3043 /* if proper type for phase 1 ? */
3044 switch (id_b
->type
) {
3045 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3046 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3047 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3048 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3049 plog(LLV_WARNING
, LOCATION
, NULL
,
3050 "such ID type %s is not proper.\n",
3051 s_ipsecdoi_ident(id_b
->type
));
3055 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3056 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
3057 && id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3059 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3060 plog(LLV_WARNING
, LOCATION
, NULL
,
3061 "protocol ID and Port mismatched. "
3062 "proto_id:%d port:%d\n",
3063 id_b
->proto_id
, ntohs(id_b
->port
));
3066 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3068 * copmaring with expecting port.
3069 * always permit if port is equal to PORT_ISAKMP
3071 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3075 switch (iph1
->remote
->sa_family
) {
3077 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3081 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3085 plog(LLV_ERROR
, LOCATION
, NULL
,
3086 "invalid family: %d\n",
3087 iph1
->remote
->sa_family
);
3088 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3090 if (ntohs(id_b
->port
) != port
) {
3091 plog(LLV_WARNING
, LOCATION
, NULL
,
3092 "port %d expected, but %d\n",
3093 port
, ntohs(id_b
->port
));
3100 /* compare with the ID if specified. */
3101 if (iph1
->rmconf
->idv_p
) {
3102 vchar_t
*ident0
= NULL
;
3105 /* check the type of both IDs */
3106 if (iph1
->rmconf
->idvtype_p
!= doi2idtype(id_b
->type
)) {
3107 plog(LLV_WARNING
, LOCATION
, NULL
,
3108 "ID type mismatched.\n");
3109 if (iph1
->rmconf
->verify_identifier
)
3110 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3113 /* compare defined ID with the ID sent by peer. */
3114 ident0
= getidval(iph1
->rmconf
->idvtype_p
, iph1
->rmconf
->idv_p
);
3116 switch (iph1
->rmconf
->idvtype_p
) {
3118 ident
.v
= (caddr_t
)(id_b
+ 1);
3119 ident
.l
= ident0
->l
;
3120 if (eay_cmp_asn1dn(ident0
, &ident
))
3123 case IDTYPE_ADDRESS
:
3124 sa
= (struct sockaddr
*)ident0
->v
;
3125 sa2
= (caddr_t
)(id_b
+ 1);
3126 switch (sa
->sa_family
) {
3128 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in_addr
))
3131 sa1
= (caddr_t
)&((struct sockaddr_in
*)sa
)->sin_addr
;
3132 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
3137 if (iph1
->id_p
->l
- sizeof(*id_b
) != sizeof(struct in6_addr
))
3139 sa1
= (caddr_t
)&((struct sockaddr_in6
*)sa
)->sin6_addr
;
3140 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
3149 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
)) {
3151 plog(LLV_WARNING
, LOCATION
, NULL
,
3152 "ID value mismatched.\n");
3153 if (iph1
->rmconf
->verify_identifier
) {
3155 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3167 * create ID payload for phase 1 and set into iph1->id.
3168 * NOT INCLUDING isakmp general header.
3169 * see, RFC2407 4.6.2.1
3172 ipsecdoi_setid1(iph1
)
3173 struct ph1handle
*iph1
;
3175 vchar_t
*ret
= NULL
;
3176 struct ipsecdoi_id_b id_b
;
3177 vchar_t
*ident
= NULL
;
3178 struct sockaddr
*ipid
= NULL
;
3185 switch (iph1
->rmconf
->idvtype
) {
3187 id_b
.type
= IPSECDOI_ID_FQDN
;
3188 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3190 case IDTYPE_USERFQDN
:
3191 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3192 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3195 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3196 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3198 #ifdef HAVE_SIGNING_C
3200 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3201 if (iph1
->rmconf
->idv
) {
3202 /* XXX it must be encoded to asn1dn. */
3203 ident
= vdup(iph1
->rmconf
->idv
);
3205 if (oakley_getmycert(iph1
) < 0) {
3206 plog(LLV_ERROR
, LOCATION
, NULL
,
3207 "failed to get own CERT.\n");
3210 ident
= eay_get_x509asn1subjectname(&iph1
->cert
->cert
);
3214 case IDTYPE_ADDRESS
:
3216 * if the value of the id type was set by the configuration
3217 * file, then use it. otherwise the value is get from local
3218 * ip address by using ike negotiation.
3220 if (iph1
->rmconf
->idv
)
3221 ipid
= (struct sockaddr
*)iph1
->rmconf
->idv
->v
;
3231 /* use IP address */
3232 switch (ipid
->sa_family
) {
3234 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3235 l
= sizeof(struct in_addr
);
3236 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3240 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3241 l
= sizeof(struct in6_addr
);
3242 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3246 plog(LLV_ERROR
, LOCATION
, NULL
,
3247 "invalid address family.\n");
3250 id_b
.proto_id
= IPPROTO_UDP
;
3251 id_b
.port
= htons(PORT_ISAKMP
);
3254 plog(LLV_ERROR
, LOCATION
, NULL
,
3255 "failed to get ID buffer.\n");
3258 memcpy(ident
->v
, p
, ident
->l
);
3262 plog(LLV_ERROR
, LOCATION
, NULL
,
3263 "failed to get ID buffer.\n");
3267 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3269 plog(LLV_ERROR
, LOCATION
, NULL
,
3270 "failed to get ID buffer.\n");
3274 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3275 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3279 plog(LLV_DEBUG
, LOCATION
, NULL
,
3280 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3288 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3297 vchar_t
*new = NULL
;
3301 else if (lcconf
->ident
[type
])
3302 new = vdup(lcconf
->ident
[type
]);
3307 /* it's only called by cfparse.y. */
3309 set_identifier(vpp
, type
, value
)
3310 vchar_t
**vpp
, *value
;
3313 vchar_t
*new = NULL
;
3315 /* simply return if value is null. */
3321 case IDTYPE_USERFQDN
:
3322 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3323 new = vmalloc(value
->l
- 1);
3326 memcpy(new->v
, value
->v
, new->l
);
3334 fp
= fopen(value
->v
, "r");
3336 plog(LLV_ERROR
, LOCATION
, NULL
,
3337 "can not open %s\n", value
->v
);
3341 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3342 new = vrealloc(new, tlen
+ len
);
3347 memcpy(new->v
+ tlen
, b
, len
);
3352 case IDTYPE_ADDRESS
:
3354 struct sockaddr
*sa
;
3356 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3360 sa
= str2saddr(value
->v
, NULL
);
3362 plog(LLV_ERROR
, LOCATION
, NULL
,
3363 "invalid ip address %s\n", value
->v
);
3367 new = vmalloc(sa
->sa_len
);
3370 memcpy(new->v
, sa
, new->l
);
3374 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
3386 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3387 * NOT INCLUDING isakmp general header.
3388 * this function is for initiator. responder will get to copy from payload.
3389 * responder ID type is always address type.
3390 * see, RFC2407 4.6.2.1
3393 ipsecdoi_setid2(iph2
)
3394 struct ph2handle
*iph2
;
3396 struct secpolicy
*sp
;
3398 /* check there is phase 2 handler ? */
3399 sp
= getspbyspid(iph2
->spid
);
3401 plog(LLV_ERROR
, LOCATION
, NULL
,
3402 "no policy found for spid:%lu.\n", iph2
->spid
);
3406 if (!iph2
->sainfo
->idv
) {
3407 iph2
->id
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.src
,
3408 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
3409 if (iph2
->id
== NULL
) {
3410 plog(LLV_ERROR
, LOCATION
, NULL
,
3411 "failed to get ID for %s\n",
3412 spidx2str(&sp
->spidx
));
3415 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
3416 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
3418 struct ipsecdoi_id_b id_b
;
3421 id_b
.type
= idtype2doi(iph2
->sainfo
->idvtype
);
3422 if (id_b
.type
== 255) {
3423 plog(LLV_ERROR
, LOCATION
, NULL
,
3424 "failed to convert ID type to DOI.\n");
3430 ident
= getidval(iph2
->sainfo
->idvtype
, iph2
->sainfo
->idv
);
3432 plog(LLV_ERROR
, LOCATION
, NULL
,
3433 "failed to get ID value.\n");
3436 iph2
->id
= vmalloc(sizeof(id_b
) + ident
->l
);
3437 if (iph2
->id
== NULL
) {
3438 plog(LLV_ERROR
, LOCATION
, NULL
,
3439 "failed to get ID buffer.\n");
3444 memcpy(iph2
->id
->v
, &id_b
, sizeof(id_b
));
3445 memcpy(iph2
->id
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3450 iph2
->id_p
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.dst
,
3451 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
3452 if (iph2
->id_p
== NULL
) {
3453 plog(LLV_ERROR
, LOCATION
, NULL
,
3454 "failed to get ID for %s\n",
3455 spidx2str(&sp
->spidx
));
3460 plog(LLV_DEBUG
, LOCATION
, NULL
,
3461 "use remote ID type %s\n",
3462 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
3468 * set address type of ID.
3469 * NOT INCLUDING general header.
3472 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
3473 struct sockaddr
*saddr
;
3478 int type
, len1
, len2
;
3483 * Q. When type is SUBNET, is it allowed to be ::1/128.
3484 * A. Yes. (consensus at bake-off)
3486 switch (saddr
->sa_family
) {
3488 len1
= sizeof(struct in_addr
);
3489 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
3490 type
= IPSECDOI_ID_IPV4_ADDR
;
3493 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
3494 len2
= sizeof(struct in_addr
);
3496 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
3497 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
3501 len1
= sizeof(struct in6_addr
);
3502 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
3503 type
= IPSECDOI_ID_IPV6_ADDR
;
3506 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
3507 len2
= sizeof(struct in6_addr
);
3509 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
3510 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
3514 plog(LLV_ERROR
, LOCATION
, NULL
,
3515 "invalid family: %d.\n", saddr
->sa_family
);
3520 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
3522 plog(LLV_ERROR
, LOCATION
, NULL
,
3523 "failed to get ID buffer.\n");
3527 memset(new->v
, 0, new->l
);
3529 /* set the part of header. */
3530 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
3532 /* set ul_proto and port */
3534 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3535 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3537 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
3538 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
3539 ((struct ipsecdoi_id_b
*)new->v
)->port
=
3540 port
== IPSEC_PORT_ANY
? 0 : port
;
3541 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
3547 u_char
*p
= new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
;
3548 u_int bits
= prefixlen
;
3556 *p
= ~((1 << (8 - bits
)) - 1);
3563 * create sockaddr structure from ID payload (buf).
3564 * buffers (saddr, prefixlen, ul_proto) must be allocated.
3565 * see, RFC2407 4.6.2.1
3568 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
3570 struct sockaddr
*saddr
;
3571 u_int8_t
*prefixlen
;
3572 u_int16_t
*ul_proto
;
3574 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)buf
->v
;
3578 * When a ID payload of subnet type with a IP address of full bit
3579 * masked, it has to be processed as host address.
3580 * e.g. below 2 type are same.
3581 * type = ipv6 subnet, data = 2001::1/128
3582 * type = ipv6 address, data = 2001::1
3584 switch (id_b
->type
) {
3585 case IPSECDOI_ID_IPV4_ADDR
:
3586 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3587 saddr
->sa_len
= sizeof(struct sockaddr_in
);
3588 saddr
->sa_family
= AF_INET
;
3589 ((struct sockaddr_in
*)saddr
)->sin_port
=
3592 : id_b
->port
); /* see sockaddr2id() */
3593 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
3594 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
3597 case IPSECDOI_ID_IPV6_ADDR
:
3598 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3599 saddr
->sa_len
= sizeof(struct sockaddr_in6
);
3600 saddr
->sa_family
= AF_INET6
;
3601 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
3604 : id_b
->port
); /* see sockaddr2id() */
3605 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
3606 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
3610 plog(LLV_ERROR
, LOCATION
, NULL
,
3611 "unsupported ID type %d\n", id_b
->type
);
3612 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3615 /* get prefix length */
3616 switch (id_b
->type
) {
3617 case IPSECDOI_ID_IPV4_ADDR
:
3618 plen
= sizeof(struct in_addr
) << 3;
3621 case IPSECDOI_ID_IPV6_ADDR
:
3622 plen
= sizeof(struct in6_addr
) << 3;
3625 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3627 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3632 int alen
= sizeof(struct in_addr
);
3634 switch (id_b
->type
) {
3635 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3636 alen
= sizeof(struct in_addr
);
3639 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3640 alen
= sizeof(struct in6_addr
);
3647 return ISAKMP_INTERNAL_ERROR
;
3649 /* get subnet mask length */
3654 + sizeof(struct ipsecdoi_id_b
)
3657 for (; *p
== 0xff; p
++) {
3680 *ul_proto
= id_b
->proto_id
== 0
3682 : id_b
->proto_id
; /* see sockaddr2id() */
3688 * make printable string from ID payload except of general header.
3694 static char buf
[256];
3703 * set IPsec data attributes into a proposal.
3704 * NOTE: MUST called per a transform.
3707 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
3708 struct isakmp_pl_t
*t
;
3713 struct isakmp_data
*d
, *prev
;
3719 tr
->trns_no
= t
->t_no
;
3720 tr
->trns_id
= t
->t_id
;
3722 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
3723 prev
= (struct isakmp_data
*)NULL
;
3724 d
= (struct isakmp_data
*)(t
+ 1);
3727 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
3728 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3730 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
3734 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
3735 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
3737 plog(LLV_DEBUG
, LOCATION
, NULL
,
3738 "type=%s, flag=0x%04x, lorv=%s\n",
3739 s_ipsecdoi_attr(type
), flag
,
3740 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
3743 case IPSECDOI_ATTR_SA_LD_TYPE
:
3745 int type
= ntohs(d
->lorv
);
3747 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
3748 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
3752 plog(LLV_WARNING
, LOCATION
, NULL
,
3753 "invalid life duration type. "
3755 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
3760 case IPSECDOI_ATTR_SA_LD
:
3762 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
3763 IPSECDOI_ATTR_SA_LD_TYPE
) {
3764 plog(LLV_ERROR
, LOCATION
, NULL
,
3765 "life duration must follow ltype\n");
3771 vchar_t
*ld_buf
= NULL
;
3774 /* i.e. ISAKMP_GEN_TV */
3775 ld_buf
= vmalloc(sizeof(d
->lorv
));
3776 if (ld_buf
== NULL
) {
3777 plog(LLV_ERROR
, LOCATION
, NULL
,
3778 "failed to get LD buffer.\n");
3781 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
3783 int len
= ntohs(d
->lorv
);
3784 /* i.e. ISAKMP_GEN_TLV */
3785 ld_buf
= vmalloc(len
);
3786 if (ld_buf
== NULL
) {
3787 plog(LLV_ERROR
, LOCATION
, NULL
,
3788 "failed to get LD buffer.\n");
3791 memcpy(ld_buf
->v
, d
+ 1, len
);
3794 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
3795 t
= ipsecdoi_set_ld(ld_buf
);
3798 plog(LLV_ERROR
, LOCATION
, NULL
,
3799 "invalid life duration.\n");
3802 /* lifetime must be equal in a proposal. */
3803 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
3805 else if (pp
->lifetime
!= t
) {
3806 plog(LLV_ERROR
, LOCATION
, NULL
,
3807 "lifetime mismatched "
3809 "prev:%ld curr:%ld.\n",
3814 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
3815 t
= ipsecdoi_set_ld(ld_buf
);
3818 plog(LLV_ERROR
, LOCATION
, NULL
,
3819 "invalid life duration.\n");
3822 /* lifebyte must be equal in a proposal. */
3823 if (pp
->lifebyte
== 0)
3825 else if (pp
->lifebyte
!= t
) {
3826 plog(LLV_ERROR
, LOCATION
, NULL
,
3827 "lifebyte mismatched "
3829 "prev:%ld curr:%ld.\n",
3836 plog(LLV_ERROR
, LOCATION
, NULL
,
3837 "invalid life type: %d\n", life_t
);
3843 case IPSECDOI_ATTR_GRP_DESC
:
3845 * RFC2407: 4.5 IPSEC Security Association Attributes
3846 * Specifies the Oakley Group to be used in a PFS QM
3847 * negotiation. For a list of supported values, see
3848 * Appendix A of [IKE].
3850 if (pp
->pfs_group
== 0)
3851 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
3852 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
3853 plog(LLV_ERROR
, LOCATION
, NULL
,
3854 "pfs_group mismatched "
3855 "in a proposal.\n");
3860 case IPSECDOI_ATTR_ENC_MODE
:
3862 && pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
3863 plog(LLV_ERROR
, LOCATION
, NULL
,
3864 "multiple encmode exist "
3865 "in a transform.\n");
3868 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
3871 case IPSECDOI_ATTR_AUTH
:
3872 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
3873 plog(LLV_ERROR
, LOCATION
, NULL
,
3874 "multiple authtype exist "
3875 "in a transform.\n");
3878 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
3881 case IPSECDOI_ATTR_KEY_LENGTH
:
3882 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
3883 plog(LLV_ERROR
, LOCATION
, NULL
,
3884 "key length defined but not ESP");
3887 tr
->encklen
= ntohs(d
->lorv
);
3890 case IPSECDOI_ATTR_KEY_ROUNDS
:
3891 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
3892 case IPSECDOI_ATTR_COMP_PRIVALG
:
3900 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
3902 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
3903 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
3913 ipsecdoi_authalg2trnsid(alg
)
3917 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
3918 return IPSECDOI_AH_MD5
;
3919 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
3920 return IPSECDOI_AH_SHA
;
3921 case IPSECDOI_ATTR_AUTH_DES_MAC
:
3922 return IPSECDOI_AH_DES
;
3923 case IPSECDOI_ATTR_AUTH_KPDK
:
3924 return IPSECDOI_AH_MD5
; /* XXX */
3926 plog(LLV_ERROR
, LOCATION
, NULL
,
3927 "invalid authentication algorithm:%d\n", alg
);
3934 fixup_initiator_sa(match
, received
)
3935 struct isakmpsa
*match
, *received
;
3937 struct isakmpsa
*newsa
;
3939 if (received
->gssid
== NULL
)
3942 newsa
= newisakmpsa();
3943 memcpy(newsa
, match
, sizeof *newsa
);
3945 if (match
->dhgrp
!= NULL
) {
3946 newsa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
3947 memcpy(newsa
->dhgrp
, match
->dhgrp
, sizeof (struct dhgroup
));
3950 newsa
->rmconf
= NULL
;
3952 newsa
->gssid
= vdup(received
->gssid
);
3958 static int rm_idtype2doi
[] = {
3960 IPSECDOI_ID_USER_FQDN
,
3962 255, /* it's type of "address"
3963 * it expands into 4 types by another function. */
3964 IPSECDOI_ID_DER_ASN1_DN
,
3968 * convert idtype to DOI value.
3976 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
3977 return rm_idtype2doi
[idtype
];
3986 case IPSECDOI_ID_FQDN
:
3987 return(IDTYPE_FQDN
);
3988 case IPSECDOI_ID_USER_FQDN
:
3989 return(IDTYPE_USERFQDN
);
3990 case IPSECDOI_ID_KEY_ID
:
3991 return(IDTYPE_KEYID
);
3992 case IPSECDOI_ID_DER_ASN1_DN
:
3993 return(IDTYPE_ASN1DN
);
3994 case IPSECDOI_ID_IPV4_ADDR
:
3995 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3996 case IPSECDOI_ID_IPV6_ADDR
:
3997 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3998 return(IDTYPE_ADDRESS
);
4000 plog(LLV_WARNING
, LOCATION
, NULL
,
4001 "Inproper idtype:%d in this function.\n",
4002 s_ipsecdoi_ident(doi
));
4003 return(IDTYPE_ADDRESS
); /* XXX */