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
);
739 if (iph2
->sa_ret
== NULL
)
746 * check phase 2 SA payload returned from responder.
747 * This function is called by initiator only.
753 ipsecdoi_checkph2proposal(iph2
)
754 struct ph2handle
*iph2
;
756 struct prop_pair
**rpair
= NULL
, **spair
= NULL
;
761 /* get proposal pair of SA sent. */
762 spair
= get_proppair(iph2
->sa
, IPSECDOI_TYPE_PH2
);
764 plog(LLV_ERROR
, LOCATION
, NULL
,
765 "failed to get prop pair.\n");
769 /* XXX should check the number of transform */
771 /* get proposal pair of SA replyed */
772 rpair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
774 plog(LLV_ERROR
, LOCATION
, NULL
,
775 "failed to get prop pair.\n");
779 /* check proposal is only one ? */
782 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
789 plog(LLV_ERROR
, LOCATION
, NULL
,
790 "no proposal received.\n");
794 plog(LLV_ERROR
, LOCATION
, NULL
,
795 "some proposals received.\n");
799 if (spair
[n
] == NULL
) {
800 plog(LLV_WARNING
, LOCATION
, NULL
,
801 "invalid proposal number:%d received.\n", i
);
805 if (rpair
[n
]->tnext
!= NULL
) {
806 plog(LLV_ERROR
, LOCATION
, NULL
,
807 "multi transforms replyed.\n");
811 if (cmp_aproppair_i(rpair
[n
], spair
[n
])) {
812 plog(LLV_ERROR
, LOCATION
, NULL
,
813 "proposal mismathed.\n");
818 * check and select a proposal.
819 * ensure that there is no modification of the proposal by
822 p
= get_ph2approval(iph2
, rpair
);
826 /* make a SA to be replayed. */
828 iph2
->sa_ret
= get_sabyproppair(p
, iph2
->ph1
);
830 if (iph2
->sa_ret
== NULL
)
837 free_proppair(rpair
);
839 free_proppair(spair
);
845 * compare two prop_pair which is assumed to have same proposal number.
846 * the case of bundle or single SA, NOT multi transforms.
847 * a: a proposal that is multi protocols and single transform, usually replyed.
848 * b: a proposal that is multi protocols and multi transform, usually sent.
849 * NOTE: this function is for initiator.
853 * XXX cannot understand the comment!
856 cmp_aproppair_i(a
, b
)
857 struct prop_pair
*a
, *b
;
859 struct prop_pair
*p
, *q
, *r
;
862 for (p
= a
, q
= b
; p
&& q
; p
= p
->next
, q
= q
->next
) {
863 for (r
= q
; r
; r
= r
->tnext
) {
865 if (p
->trns
->t_no
== r
->trns
->t_no
)
869 /* no suitable transform found */
870 plog(LLV_ERROR
, LOCATION
, NULL
,
871 "no suitable transform found.\n");
876 if (p
->prop
->p_no
!= r
->prop
->p_no
) {
877 plog(LLV_WARNING
, LOCATION
, NULL
,
878 "proposal #%d mismatched, "
880 r
->prop
->p_no
, p
->prop
->p_no
);
884 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
885 plog(LLV_ERROR
, LOCATION
, NULL
,
886 "proto_id mismathed: my:%d peer:%d\n",
887 r
->prop
->proto_id
, p
->prop
->proto_id
);
891 if (p
->prop
->proto_id
!= r
->prop
->proto_id
) {
892 plog(LLV_ERROR
, LOCATION
, NULL
,
893 "invalid spi size: %d.\n",
898 /* check #of transforms */
899 if (p
->prop
->num_t
!= 1) {
900 plog(LLV_WARNING
, LOCATION
, NULL
,
901 "#of transform is %d, "
902 "but expected 1.\n", p
->prop
->num_t
);
906 if (p
->trns
->t_id
!= r
->trns
->t_id
) {
907 plog(LLV_WARNING
, LOCATION
, NULL
,
908 "transform number has been modified.\n");
911 if (p
->trns
->reserved
!= r
->trns
->reserved
) {
912 plog(LLV_WARNING
, LOCATION
, NULL
,
913 "reserved field should be zero.\n");
917 /* compare attribute */
918 len
= ntohs(r
->trns
->h
.len
) - sizeof(*p
->trns
);
919 if (memcmp(p
->trns
+ 1, r
->trns
+ 1, len
) != 0) {
920 plog(LLV_WARNING
, LOCATION
, NULL
,
921 "attribute has been modified.\n");
925 if ((p
&& !q
) || (!p
&& q
)) {
926 /* # of protocols mismatched */
927 plog(LLV_ERROR
, LOCATION
, NULL
,
928 "#of protocols mismatched.\n");
936 * acceptable check for policy configuration.
937 * return a new SA payload to be reply to peer.
939 static struct prop_pair
*
940 get_ph2approval(iph2
, pair
)
941 struct ph2handle
*iph2
;
942 struct prop_pair
**pair
;
944 struct prop_pair
*ret
;
947 iph2
->approval
= NULL
;
949 plog(LLV_DEBUG
, LOCATION
, NULL
,
950 "begin compare proposals.\n");
952 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
955 plog(LLV_DEBUG
, LOCATION
, NULL
,
956 "pair[%d]: %p\n", i
, pair
[i
]);
957 print_proppair(LLV_DEBUG
, pair
[i
]);;
959 /* compare proposal and select one */
960 ret
= get_ph2approvalx(iph2
, pair
[i
]);
967 plog(LLV_ERROR
, LOCATION
, NULL
, "no suitable policy found.\n");
973 * compare my proposal and peers just one proposal.
976 static struct prop_pair
*
977 get_ph2approvalx(iph2
, pp
)
978 struct ph2handle
*iph2
;
979 struct prop_pair
*pp
;
981 struct prop_pair
*ret
= NULL
;
982 struct saprop
*pr0
, *pr
= NULL
;
983 struct saprop
*q1
, *q2
;
985 pr0
= aproppair2saprop(pp
);
989 for (q1
= pr0
; q1
; q1
= q1
->next
) {
990 for (q2
= iph2
->proposal
; q2
; q2
= q2
->next
) {
991 plog(LLV_DEBUG
, LOCATION
, NULL
,
992 "peer's single bundle:\n");
993 printsaprop0(LLV_DEBUG
, q1
);
994 plog(LLV_DEBUG
, LOCATION
, NULL
,
995 "my single bundle:\n");
996 printsaprop0(LLV_DEBUG
, q2
);
998 pr
= cmpsaprop_alloc(iph2
->ph1
, q1
, q2
, iph2
->side
);
1002 plog(LLV_ERROR
, LOCATION
, NULL
,
1006 /* no proposal matching */
1013 plog(LLV_DEBUG
, LOCATION
, NULL
, "matched\n");
1014 iph2
->approval
= pr
;
1018 struct prop_pair
*p
, *n
, *x
;
1022 for (p
= pp
; p
; p
= p
->next
) {
1024 * find a proposal with matching proto_id.
1025 * we have analyzed validity already, in cmpsaprop_alloc().
1027 for (sp
= pr
->head
; sp
; sp
= sp
->next
) {
1028 if (sp
->proto_id
== p
->prop
->proto_id
)
1036 for (x
= p
; x
; x
= x
->tnext
)
1037 if (sp
->head
->trns_no
== x
->trns
->t_no
)
1042 n
= racoon_calloc(1, sizeof(struct prop_pair
));
1044 plog(LLV_ERROR
, LOCATION
, NULL
,
1045 "failed to get buffer.\n");
1052 /* need to preserve the order */
1053 for (x
= ret
; x
&& x
->next
; x
= x
->next
)
1055 if (x
&& x
->prop
== n
->prop
) {
1056 for (/*nothing*/; x
&& x
->tnext
; x
= x
->tnext
)
1067 /* #of transforms should be updated ? */
1076 struct prop_pair
**pair
;
1080 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1081 free_proppair0(pair
[i
]);
1088 free_proppair0(pair
)
1089 struct prop_pair
*pair
;
1091 struct prop_pair
*p
, *q
, *r
, *s
;
1093 for (p
= pair
; p
; p
= q
) {
1095 for (r
= p
; r
; r
= s
) {
1103 * get proposal pairs from SA payload.
1104 * tiny check for proposal payload.
1107 get_proppair(sa
, mode
)
1111 struct prop_pair
**pair
;
1112 int num_p
= 0; /* number of proposal for use */
1116 struct ipsecdoi_sa_b
*sab
= (struct ipsecdoi_sa_b
*)sa
->v
;
1118 plog(LLV_DEBUG
, LOCATION
, NULL
, "total SA len=%d\n", sa
->l
);
1119 plogdump(LLV_DEBUG
, sa
->v
, sa
->l
);
1121 /* check SA payload size */
1122 if (sa
->l
< sizeof(*sab
)) {
1123 plog(LLV_ERROR
, LOCATION
, NULL
,
1124 "Invalid SA length = %d.\n", sa
->l
);
1129 if (check_doi(ntohl(sab
->doi
)) < 0)
1132 /* check SITUATION */
1133 if (check_situation(ntohl(sab
->sit
)) < 0)
1136 pair
= racoon_calloc(1, MAXPROPPAIRLEN
* sizeof(*pair
));
1138 plog(LLV_ERROR
, LOCATION
, NULL
,
1139 "failed to get buffer.\n");
1142 memset(pair
, 0, sizeof(pair
));
1144 bp
= (caddr_t
)(sab
+ 1);
1145 tlen
= sa
->l
- sizeof(*sab
);
1148 struct isakmp_pl_p
*prop
;
1150 vchar_t
*pbuf
= NULL
;
1151 struct isakmp_parse_t
*pa
;
1153 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_P
, (struct isakmp_gen
*)bp
, tlen
);
1157 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1158 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1160 /* check the value of next payload */
1161 if (pa
->type
!= ISAKMP_NPTYPE_P
) {
1162 plog(LLV_ERROR
, LOCATION
, NULL
,
1163 "Invalid payload type=%u\n", pa
->type
);
1168 prop
= (struct isakmp_pl_p
*)pa
->ptr
;
1171 plog(LLV_DEBUG
, LOCATION
, NULL
,
1172 "proposal #%u len=%d\n", prop
->p_no
, proplen
);
1175 plog(LLV_ERROR
, LOCATION
, NULL
,
1176 "invalid proposal with length %d\n", proplen
);
1181 /* check Protocol ID */
1182 if (!check_protocol
[mode
]) {
1183 plog(LLV_ERROR
, LOCATION
, NULL
,
1184 "unsupported mode %d\n", mode
);
1188 if (check_protocol
[mode
](prop
->proto_id
) < 0)
1191 /* check SPI length when IKE. */
1192 if (check_spi_size(prop
->proto_id
, prop
->spi_size
) < 0)
1196 if (get_transform(prop
, pair
, &num_p
) < 0) {
1207 struct prop_pair
*p
, *q
;
1209 /* check for proposals with no transforms */
1210 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1214 plog(LLV_DEBUG
, LOCATION
, NULL
, "pair %d:\n", i
);
1215 print_proppair(LLV_DEBUG
, pair
[i
]);
1217 notrans
= nprop
= 0;
1218 for (p
= pair
[i
]; p
; p
= p
->next
) {
1219 if (p
->trns
== NULL
) {
1223 for (q
= p
; q
; q
= q
->tnext
)
1229 * XXX at this moment, we cannot accept proposal group
1230 * with multiple proposals. this should be fixed.
1232 if (pair
[i
]->next
) {
1233 plog(LLV_WARNING
, LOCATION
, NULL
,
1234 "proposal #%u ignored "
1235 "(multiple proposal not supported)\n",
1236 pair
[i
]->prop
->p_no
);
1242 for (p
= pair
[i
]; p
; p
= q
) {
1249 plog(LLV_DEBUG
, LOCATION
, NULL
,
1250 "proposal #%u: %d transform\n",
1251 pair
[i
]->prop
->p_no
, nprop
);
1256 /* bark if no proposal is found. */
1258 plog(LLV_ERROR
, LOCATION
, NULL
,
1259 "no Proposal found.\n");
1267 * check transform payload.
1269 * positive: return the pointer to the payload of valid transform.
1270 * 0 : No valid transform found.
1273 get_transform(prop
, pair
, num_p
)
1274 struct isakmp_pl_p
*prop
;
1275 struct prop_pair
**pair
;
1278 int tlen
; /* total length of all transform in a proposal */
1280 struct isakmp_pl_t
*trns
;
1282 vchar_t
*pbuf
= NULL
;
1283 struct isakmp_parse_t
*pa
;
1284 struct prop_pair
*p
= NULL
, *q
;
1287 bp
= (caddr_t
)prop
+ sizeof(struct isakmp_pl_p
) + prop
->spi_size
;
1288 tlen
= ntohs(prop
->h
.len
)
1289 - (sizeof(struct isakmp_pl_p
) + prop
->spi_size
);
1290 pbuf
= isakmp_parsewoh(ISAKMP_NPTYPE_T
, (struct isakmp_gen
*)bp
, tlen
);
1294 /* check and get transform for use */
1296 for (pa
= (struct isakmp_parse_t
*)pbuf
->v
;
1297 pa
->type
!= ISAKMP_NPTYPE_NONE
;
1302 /* check the value of next payload */
1303 if (pa
->type
!= ISAKMP_NPTYPE_T
) {
1304 plog(LLV_ERROR
, LOCATION
, NULL
,
1305 "Invalid payload type=%u\n", pa
->type
);
1309 trns
= (struct isakmp_pl_t
*)pa
->ptr
;
1312 plog(LLV_DEBUG
, LOCATION
, NULL
,
1313 "transform #%u len=%u\n", trns
->t_no
, trnslen
);
1315 /* check transform ID */
1316 if (prop
->proto_id
>= ARRAYLEN(check_transform
)) {
1317 plog(LLV_WARNING
, LOCATION
, NULL
,
1318 "unsupported proto_id %u\n",
1322 if (prop
->proto_id
>= ARRAYLEN(check_attributes
)) {
1323 plog(LLV_WARNING
, LOCATION
, NULL
,
1324 "unsupported proto_id %u\n",
1329 if (!check_transform
[prop
->proto_id
]
1330 || !check_attributes
[prop
->proto_id
]) {
1331 plog(LLV_WARNING
, LOCATION
, NULL
,
1332 "unsupported proto_id %u\n",
1336 if (check_transform
[prop
->proto_id
](trns
->t_id
) < 0)
1339 /* check data attributes */
1340 if (check_attributes
[prop
->proto_id
](trns
) != 0)
1343 p
= racoon_calloc(1, sizeof(*p
));
1345 plog(LLV_ERROR
, LOCATION
, NULL
,
1346 "failed to get buffer.\n");
1353 /* need to preserve the order */
1354 for (q
= pair
[prop
->p_no
]; q
&& q
->next
; q
= q
->next
)
1356 if (q
&& q
->prop
== p
->prop
) {
1357 for (/*nothing*/; q
&& q
->tnext
; q
= q
->tnext
)
1364 pair
[prop
->p_no
] = p
;
1376 * make a new SA payload from prop_pair.
1377 * NOTE: this function make spi value clear.
1380 get_sabyproppair(pair
, iph1
)
1381 struct prop_pair
*pair
;
1382 struct ph1handle
*iph1
;
1386 u_int8_t
*np_p
= NULL
;
1387 struct prop_pair
*p
;
1388 int prophlen
, trnslen
;
1391 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1392 for (p
= pair
; p
; p
= p
->next
) {
1393 newtlen
+= (sizeof(struct isakmp_pl_p
)
1395 + ntohs(p
->trns
->h
.len
));
1398 newsa
= vmalloc(newtlen
);
1399 if (newsa
== NULL
) {
1400 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1405 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1407 /* update some of values in SA header */
1408 ((struct ipsecdoi_sa_b
*)bp
)->doi
= htonl(iph1
->rmconf
->doitype
);
1409 ((struct ipsecdoi_sa_b
*)bp
)->sit
= htonl(iph1
->rmconf
->sittype
);
1410 bp
+= sizeof(struct ipsecdoi_sa_b
);
1412 /* create proposal payloads */
1413 for (p
= pair
; p
; p
= p
->next
) {
1414 prophlen
= sizeof(struct isakmp_pl_p
)
1415 + p
->prop
->spi_size
;
1416 trnslen
= ntohs(p
->trns
->h
.len
);
1419 *np_p
= ISAKMP_NPTYPE_P
;
1421 /* create proposal */
1423 memcpy(bp
, p
->prop
, prophlen
);
1424 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1425 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1426 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1427 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1428 memset(bp
+ sizeof(struct isakmp_pl_p
), 0, p
->prop
->spi_size
);
1431 /* create transform */
1432 memcpy(bp
, p
->trns
, trnslen
);
1433 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1434 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1442 * update responder's spi
1445 ipsecdoi_updatespi(iph2
)
1446 struct ph2handle
*iph2
;
1448 struct prop_pair
**pair
, *p
;
1455 pair
= get_proppair(iph2
->sa_ret
, IPSECDOI_TYPE_PH2
);
1458 for (i
= 0; i
< MAXPROPPAIRLEN
; i
++) {
1462 if (i
== MAXPROPPAIRLEN
|| pair
[i
]->tnext
) {
1463 /* multiple transform must be filtered by selectph2proposal.*/
1467 pp
= iph2
->approval
;
1469 /* create proposal payloads */
1470 for (p
= pair
[i
]; p
; p
= p
->next
) {
1472 * find a proposal/transform with matching proto_id/t_id.
1473 * we have analyzed validity already, in cmpsaprop_alloc().
1475 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1476 if (p
->prop
->proto_id
== pr
->proto_id
&&
1477 p
->trns
->t_id
== pr
->head
->trns_id
) {
1485 * XXX SPI bits are left-filled, for use with IPComp.
1486 * we should be switching to variable-length spi field...
1488 spi
= (u_int8_t
*)&pr
->spi
;
1489 spi
+= sizeof(pr
->spi
);
1491 memcpy((caddr_t
)p
->prop
+ sizeof(*p
->prop
), spi
, pr
->spisize
);
1496 free_proppair(pair
);
1501 * make a new SA payload from prop_pair.
1504 get_sabysaprop(pp0
, sa0
)
1508 struct prop_pair
**pair
;
1511 u_int8_t
*np_p
= NULL
;
1512 struct prop_pair
*p
= NULL
;
1516 int prophlen
, trnslen
;
1519 /* get proposal pair */
1520 pair
= get_proppair(sa0
, IPSECDOI_TYPE_PH2
);
1524 newtlen
= sizeof(struct ipsecdoi_sa_b
);
1525 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1527 if (pair
[pp
->prop_no
] == NULL
)
1530 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1531 newtlen
+= (sizeof(struct isakmp_pl_p
)
1534 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1535 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1536 if (tr
->trns_no
== p
->trns
->t_no
)
1542 newtlen
+= ntohs(p
->trns
->h
.len
);
1547 newsa
= vmalloc(newtlen
);
1548 if (newsa
== NULL
) {
1549 plog(LLV_ERROR
, LOCATION
, NULL
, "failed to get newsa.\n");
1554 /* some of values of SA must be updated in the out of this function */
1555 ((struct isakmp_gen
*)bp
)->len
= htons(newtlen
);
1556 bp
+= sizeof(struct ipsecdoi_sa_b
);
1558 /* create proposal payloads */
1559 for (pp
= pp0
; pp
; pp
= pp
->next
) {
1561 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
1562 prophlen
= sizeof(struct isakmp_pl_p
)
1563 + p
->prop
->spi_size
;
1565 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
1566 for (p
= pair
[pp
->prop_no
]; p
; p
= p
->tnext
) {
1567 if (tr
->trns_no
== p
->trns
->t_no
)
1573 trnslen
= ntohs(p
->trns
->h
.len
);
1576 *np_p
= ISAKMP_NPTYPE_P
;
1578 /* create proposal */
1580 memcpy(bp
, p
->prop
, prophlen
);
1581 ((struct isakmp_pl_p
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1582 ((struct isakmp_pl_p
*)bp
)->h
.len
= htons(prophlen
+ trnslen
);
1583 ((struct isakmp_pl_p
*)bp
)->num_t
= 1;
1584 np_p
= &((struct isakmp_pl_p
*)bp
)->h
.np
;
1587 /* create transform */
1588 memcpy(bp
, p
->trns
, trnslen
);
1589 ((struct isakmp_pl_t
*)bp
)->h
.np
= ISAKMP_NPTYPE_NONE
;
1590 ((struct isakmp_pl_t
*)bp
)->h
.len
= htons(trnslen
);
1600 * If some error happens then return 0. Although 0 means that lifetime is zero,
1601 * such a value should not be accepted.
1602 * Also 0 of lifebyte should not be included in a packet although 0 means not
1606 ipsecdoi_set_ld(buf
)
1616 ld
= ntohs(*(u_int16_t
*)buf
->v
);
1619 ld
= ntohl(*(u_int32_t
*)buf
->v
);
1622 plog(LLV_ERROR
, LOCATION
, NULL
,
1623 "length %d of life duration "
1624 "isn't supported.\n", buf
->l
);
1643 plog(LLV_ERROR
, LOCATION
, NULL
,
1644 "invalid value of DOI 0x%08x.\n", doi
);
1654 check_situation(sit
)
1658 case IPSECDOI_SIT_IDENTITY_ONLY
:
1661 case IPSECDOI_SIT_SECRECY
:
1662 case IPSECDOI_SIT_INTEGRITY
:
1663 plog(LLV_ERROR
, LOCATION
, NULL
,
1664 "situation 0x%08x unsupported yet.\n", sit
);
1668 plog(LLV_ERROR
, LOCATION
, NULL
,
1669 "invalid situation 0x%08x.\n", sit
);
1676 * check protocol id in main mode
1679 check_prot_main(proto_id
)
1683 case IPSECDOI_PROTO_ISAKMP
:
1687 plog(LLV_ERROR
, LOCATION
, NULL
,
1688 "Illegal protocol id=%u.\n", proto_id
);
1695 * check protocol id in quick mode
1698 check_prot_quick(proto_id
)
1702 case IPSECDOI_PROTO_IPSEC_AH
:
1703 case IPSECDOI_PROTO_IPSEC_ESP
:
1706 case IPSECDOI_PROTO_IPCOMP
:
1710 plog(LLV_ERROR
, LOCATION
, NULL
,
1711 "invalid protocol id %d.\n", proto_id
);
1718 check_spi_size(proto_id
, size
)
1722 case IPSECDOI_PROTO_ISAKMP
:
1725 plog(LLV_WARNING
, LOCATION
, NULL
,
1726 "SPI size isn't zero, but IKE proposal.\n");
1730 case IPSECDOI_PROTO_IPSEC_AH
:
1731 case IPSECDOI_PROTO_IPSEC_ESP
:
1733 plog(LLV_ERROR
, LOCATION
, NULL
,
1734 "invalid SPI size=%d for IPSEC proposal.\n",
1740 case IPSECDOI_PROTO_IPCOMP
:
1741 if (size
!= 2 && size
!= 4) {
1742 plog(LLV_ERROR
, LOCATION
, NULL
,
1743 "invalid SPI size=%d for IPCOMP proposal.\n",
1757 * check transform ID in ISAKMP.
1760 check_trns_isakmp(t_id
)
1764 case IPSECDOI_KEY_IKE
:
1767 plog(LLV_ERROR
, LOCATION
, NULL
,
1768 "invalid transform-id=%u in proto_id=%u.\n",
1769 t_id
, IPSECDOI_KEY_IKE
);
1776 * check transform ID in AH.
1783 case IPSECDOI_AH_MD5
:
1784 case IPSECDOI_AH_SHA
:
1786 case IPSECDOI_AH_DES
:
1787 plog(LLV_ERROR
, LOCATION
, NULL
,
1788 "not support transform-id=%u in AH.\n", t_id
);
1791 plog(LLV_ERROR
, LOCATION
, NULL
,
1792 "invalid transform-id=%u in AH.\n", t_id
);
1799 * check transform ID in ESP.
1802 check_trns_esp(t_id
)
1806 case IPSECDOI_ESP_DES
:
1807 case IPSECDOI_ESP_3DES
:
1808 case IPSECDOI_ESP_NULL
:
1809 case IPSECDOI_ESP_RC5
:
1810 case IPSECDOI_ESP_CAST
:
1811 case IPSECDOI_ESP_BLOWFISH
:
1812 case IPSECDOI_ESP_RIJNDAEL
:
1813 case IPSECDOI_ESP_TWOFISH
:
1815 case IPSECDOI_ESP_DES_IV32
:
1816 case IPSECDOI_ESP_DES_IV64
:
1817 case IPSECDOI_ESP_IDEA
:
1818 case IPSECDOI_ESP_3IDEA
:
1819 case IPSECDOI_ESP_RC4
:
1820 plog(LLV_ERROR
, LOCATION
, NULL
,
1821 "not support transform-id=%u in ESP.\n", t_id
);
1824 plog(LLV_ERROR
, LOCATION
, NULL
,
1825 "invalid transform-id=%u in ESP.\n", t_id
);
1832 * check transform ID in IPCOMP.
1835 check_trns_ipcomp(t_id
)
1839 case IPSECDOI_IPCOMP_OUI
:
1840 case IPSECDOI_IPCOMP_DEFLATE
:
1841 case IPSECDOI_IPCOMP_LZS
:
1844 plog(LLV_ERROR
, LOCATION
, NULL
,
1845 "invalid transform-id=%u in IPCOMP.\n", t_id
);
1852 * check data attributes in IKE.
1855 check_attr_isakmp(trns
)
1856 struct isakmp_pl_t
*trns
;
1858 struct isakmp_data
*d
;
1863 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
1864 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
1867 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
1868 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
1869 lorv
= ntohs(d
->lorv
);
1871 plog(LLV_DEBUG
, LOCATION
, NULL
,
1872 "type=%s, flag=0x%04x, lorv=%s\n",
1873 s_oakley_attr(type
), flag
,
1874 s_oakley_attr_v(type
, lorv
));
1877 * some of the attributes must be encoded in TV.
1878 * see RFC2409 Appendix A "Attribute Classes".
1881 case OAKLEY_ATTR_ENC_ALG
:
1882 case OAKLEY_ATTR_HASH_ALG
:
1883 case OAKLEY_ATTR_AUTH_METHOD
:
1884 case OAKLEY_ATTR_GRP_DESC
:
1885 case OAKLEY_ATTR_GRP_TYPE
:
1886 case OAKLEY_ATTR_SA_LD_TYPE
:
1887 case OAKLEY_ATTR_PRF
:
1888 case OAKLEY_ATTR_KEY_LEN
:
1889 case OAKLEY_ATTR_FIELD_SIZE
:
1890 if (!flag
) { /* TLV*/
1891 plog(LLV_ERROR
, LOCATION
, NULL
,
1892 "oakley attribute %d must be TV.\n",
1899 /* sanity check for TLV. length must be specified. */
1900 if (!flag
&& lorv
== 0) { /*TLV*/
1901 plog(LLV_ERROR
, LOCATION
, NULL
,
1902 "invalid length %d for TLV attribute %d.\n",
1908 case OAKLEY_ATTR_ENC_ALG
:
1909 if (!alg_oakley_encdef_ok(lorv
)) {
1910 plog(LLV_ERROR
, LOCATION
, NULL
,
1911 "invalied encryption algorithm=%d.\n",
1917 case OAKLEY_ATTR_HASH_ALG
:
1918 if (!alg_oakley_hashdef_ok(lorv
)) {
1919 plog(LLV_ERROR
, LOCATION
, NULL
,
1920 "invalied hash algorithm=%d.\n",
1926 case OAKLEY_ATTR_AUTH_METHOD
:
1928 case OAKLEY_ATTR_AUTH_METHOD_PSKEY
:
1929 case OAKLEY_ATTR_AUTH_METHOD_RSASIG
:
1930 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
:
1932 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG
:
1933 case OAKLEY_ATTR_AUTH_METHOD_RSAENC
:
1934 case OAKLEY_ATTR_AUTH_METHOD_RSAREV
:
1935 plog(LLV_ERROR
, LOCATION
, NULL
,
1936 "auth method %d isn't supported.\n",
1940 plog(LLV_ERROR
, LOCATION
, NULL
,
1941 "invalid auth method %d.\n",
1947 case OAKLEY_ATTR_GRP_DESC
:
1948 if (!alg_oakley_dhdef_ok(lorv
)) {
1949 plog(LLV_ERROR
, LOCATION
, NULL
,
1950 "invalid DH group %d.\n",
1956 case OAKLEY_ATTR_GRP_TYPE
:
1958 case OAKLEY_ATTR_GRP_TYPE_MODP
:
1961 plog(LLV_ERROR
, LOCATION
, NULL
,
1962 "unsupported DH group type %d.\n",
1968 case OAKLEY_ATTR_GRP_PI
:
1969 case OAKLEY_ATTR_GRP_GEN_ONE
:
1970 /* sanity checks? */
1973 case OAKLEY_ATTR_GRP_GEN_TWO
:
1974 case OAKLEY_ATTR_GRP_CURVE_A
:
1975 case OAKLEY_ATTR_GRP_CURVE_B
:
1976 plog(LLV_ERROR
, LOCATION
, NULL
,
1977 "attr type=%u isn't supported.\n", type
);
1980 case OAKLEY_ATTR_SA_LD_TYPE
:
1982 case OAKLEY_ATTR_SA_LD_TYPE_SEC
:
1983 case OAKLEY_ATTR_SA_LD_TYPE_KB
:
1986 plog(LLV_ERROR
, LOCATION
, NULL
,
1987 "invalid life type %d.\n", lorv
);
1992 case OAKLEY_ATTR_SA_LD
:
1993 /* should check the value */
1996 case OAKLEY_ATTR_PRF
:
1997 case OAKLEY_ATTR_KEY_LEN
:
2000 case OAKLEY_ATTR_FIELD_SIZE
:
2001 plog(LLV_ERROR
, LOCATION
, NULL
,
2002 "attr type=%u isn't supported.\n", type
);
2005 case OAKLEY_ATTR_GRP_ORDER
:
2008 case OAKLEY_ATTR_GSS_ID
:
2012 plog(LLV_ERROR
, LOCATION
, NULL
,
2013 "invalid attribute type %d.\n", type
);
2019 d
= (struct isakmp_data
*)((char *)d
2022 tlen
-= (sizeof(*d
) + lorv
);
2023 d
= (struct isakmp_data
*)((char *)d
2024 + sizeof(*d
) + lorv
);
2032 * check data attributes in IPSEC AH/ESP.
2036 struct isakmp_pl_t
*trns
;
2038 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH
, trns
);
2042 check_attr_esp(trns
)
2043 struct isakmp_pl_t
*trns
;
2045 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP
, trns
);
2049 check_attr_ipsec(proto_id
, trns
)
2051 struct isakmp_pl_t
*trns
;
2053 struct isakmp_data
*d
;
2057 int attrseen
[16]; /* XXX magic number */
2059 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2060 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2061 memset(attrseen
, 0, sizeof(attrseen
));
2064 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2065 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2066 lorv
= ntohs(d
->lorv
);
2068 plog(LLV_DEBUG
, LOCATION
, NULL
,
2069 "type=%s, flag=0x%04x, lorv=%s\n",
2070 s_ipsecdoi_attr(type
), flag
,
2071 s_ipsecdoi_attr_v(type
, lorv
));
2073 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2077 case IPSECDOI_ATTR_ENC_MODE
:
2079 plog(LLV_ERROR
, LOCATION
, NULL
,
2080 "must be TV when ENC_MODE.\n");
2085 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2086 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2087 case IPSECDOI_ATTR_ENC_MODE_UDP_TUNNEL
:
2088 case IPSECDOI_ATTR_ENC_MODE_UDP_TRNS
:
2091 plog(LLV_ERROR
, LOCATION
, NULL
,
2092 "invalid encryption mode=%u.\n",
2098 case IPSECDOI_ATTR_AUTH
:
2100 plog(LLV_ERROR
, LOCATION
, NULL
,
2101 "must be TV when AUTH.\n");
2106 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
2107 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
2108 && trns
->t_id
!= IPSECDOI_AH_MD5
) {
2110 plog(LLV_ERROR
, LOCATION
, NULL
,
2111 "auth algorithm %u conflicts "
2112 "with transform %u.\n",
2117 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
2118 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
) {
2119 if (trns
->t_id
!= IPSECDOI_AH_SHA
)
2123 case IPSECDOI_ATTR_AUTH_DES_MAC
:
2124 case IPSECDOI_ATTR_AUTH_KPDK
:
2125 plog(LLV_ERROR
, LOCATION
, NULL
,
2126 "auth algorithm %u isn't supported.\n",
2130 plog(LLV_ERROR
, LOCATION
, NULL
,
2131 "invalid auth algorithm=%u.\n",
2137 case IPSECDOI_ATTR_SA_LD_TYPE
:
2139 plog(LLV_ERROR
, LOCATION
, NULL
,
2140 "must be TV when LD_TYPE.\n");
2145 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2146 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2149 plog(LLV_ERROR
, LOCATION
, NULL
,
2150 "invalid life type %d.\n", lorv
);
2155 case IPSECDOI_ATTR_SA_LD
:
2157 /* i.e. ISAKMP_GEN_TV */
2158 plog(LLV_DEBUG
, LOCATION
, NULL
,
2159 "life duration was in TLV.\n");
2161 /* i.e. ISAKMP_GEN_TLV */
2163 plog(LLV_ERROR
, LOCATION
, NULL
,
2164 "invalid length of LD\n");
2170 case IPSECDOI_ATTR_GRP_DESC
:
2172 plog(LLV_ERROR
, LOCATION
, NULL
,
2173 "must be TV when GRP_DESC.\n");
2177 if (!alg_oakley_dhdef_ok(lorv
)) {
2178 plog(LLV_ERROR
, LOCATION
, NULL
,
2179 "invalid group description=%u.\n",
2185 case IPSECDOI_ATTR_KEY_LENGTH
:
2187 plog(LLV_ERROR
, LOCATION
, NULL
,
2188 "must be TV when KEY_LENGTH.\n");
2193 case IPSECDOI_ATTR_KEY_ROUNDS
:
2194 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2195 case IPSECDOI_ATTR_COMP_PRIVALG
:
2196 plog(LLV_ERROR
, LOCATION
, NULL
,
2197 "attr type=%u isn't supported.\n", type
);
2201 plog(LLV_ERROR
, LOCATION
, NULL
,
2202 "invalid attribute type %d.\n", type
);
2208 d
= (struct isakmp_data
*)((char *)d
2211 tlen
-= (sizeof(*d
) + lorv
);
2212 d
= (struct isakmp_data
*)((caddr_t
)d
2213 + sizeof(*d
) + lorv
);
2217 if (proto_id
== IPSECDOI_PROTO_IPSEC_AH
2218 && !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2219 plog(LLV_ERROR
, LOCATION
, NULL
,
2220 "attr AUTH must be present for AH.\n", type
);
2228 check_attr_ipcomp(trns
)
2229 struct isakmp_pl_t
*trns
;
2231 struct isakmp_data
*d
;
2235 int attrseen
[16]; /* XXX magic number */
2237 tlen
= ntohs(trns
->h
.len
) - sizeof(struct isakmp_pl_t
);
2238 d
= (struct isakmp_data
*)((caddr_t
)trns
+ sizeof(struct isakmp_pl_t
));
2239 memset(attrseen
, 0, sizeof(attrseen
));
2242 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
2243 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
2244 lorv
= ntohs(d
->lorv
);
2246 plog(LLV_DEBUG
, LOCATION
, NULL
,
2247 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2250 if (type
< sizeof(attrseen
)/sizeof(attrseen
[0]))
2254 case IPSECDOI_ATTR_ENC_MODE
:
2256 plog(LLV_ERROR
, LOCATION
, NULL
,
2257 "must be TV when ENC_MODE.\n");
2262 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2263 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2264 case IPSECDOI_ATTR_ENC_MODE_UDP_TUNNEL
:
2265 case IPSECDOI_ATTR_ENC_MODE_UDP_TRNS
:
2268 plog(LLV_ERROR
, LOCATION
, NULL
,
2269 "invalid encryption mode=%u.\n",
2275 case IPSECDOI_ATTR_SA_LD_TYPE
:
2277 plog(LLV_ERROR
, LOCATION
, NULL
,
2278 "must be TV when LD_TYPE.\n");
2283 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
2284 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
2287 plog(LLV_ERROR
, LOCATION
, NULL
,
2288 "invalid life type %d.\n", lorv
);
2293 case IPSECDOI_ATTR_SA_LD
:
2295 /* i.e. ISAKMP_GEN_TV */
2296 plog(LLV_DEBUG
, LOCATION
, NULL
,
2297 "life duration was in TLV.\n");
2299 /* i.e. ISAKMP_GEN_TLV */
2301 plog(LLV_ERROR
, LOCATION
, NULL
,
2302 "invalid length of LD\n");
2308 case IPSECDOI_ATTR_GRP_DESC
:
2310 plog(LLV_ERROR
, LOCATION
, NULL
,
2311 "must be TV when GRP_DESC.\n");
2315 if (!alg_oakley_dhdef_ok(lorv
)) {
2316 plog(LLV_ERROR
, LOCATION
, NULL
,
2317 "invalid group description=%u.\n",
2323 case IPSECDOI_ATTR_AUTH
:
2324 plog(LLV_ERROR
, LOCATION
, NULL
,
2325 "invalid attr type=%u.\n", type
);
2328 case IPSECDOI_ATTR_KEY_LENGTH
:
2329 case IPSECDOI_ATTR_KEY_ROUNDS
:
2330 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
2331 case IPSECDOI_ATTR_COMP_PRIVALG
:
2332 plog(LLV_ERROR
, LOCATION
, NULL
,
2333 "attr type=%u isn't supported.\n", type
);
2337 plog(LLV_ERROR
, LOCATION
, NULL
,
2338 "invalid attribute type %d.\n", type
);
2344 d
= (struct isakmp_data
*)((char *)d
2347 tlen
-= (sizeof(*d
) + lorv
);
2348 d
= (struct isakmp_data
*)((caddr_t
)d
2349 + sizeof(*d
) + lorv
);
2354 if (proto_id
== IPSECDOI_PROTO_IPCOMP
2355 && !attrseen
[IPSECDOI_ATTR_AUTH
]) {
2356 plog(LLV_ERROR
, LOCATION
, NULL
,
2357 "attr AUTH must be present for AH.\n", type
);
2367 * create phase1 proposal from remote configuration.
2368 * NOT INCLUDING isakmp general header of SA payload
2371 ipsecdoi_setph1proposal(props
)
2372 struct isakmpsa
*props
;
2377 /* count total size of SA minus isakmp general header */
2378 /* not including isakmp general header of SA payload */
2379 sablen
= sizeof(struct ipsecdoi_sa_b
);
2380 sablen
+= setph1prop(props
, NULL
);
2382 mysa
= vmalloc(sablen
);
2384 plog(LLV_ERROR
, LOCATION
, NULL
,
2385 "failed to allocate my sa buffer\n");
2389 /* create SA payload */
2390 /* not including isakmp general header */
2391 ((struct ipsecdoi_sa_b
*)mysa
->v
)->doi
= htonl(props
->rmconf
->doitype
);
2392 ((struct ipsecdoi_sa_b
*)mysa
->v
)->sit
= htonl(props
->rmconf
->sittype
);
2394 (void)setph1prop(props
, mysa
->v
+ sizeof(struct ipsecdoi_sa_b
));
2400 setph1prop(props
, buf
)
2401 struct isakmpsa
*props
;
2404 struct isakmp_pl_p
*prop
= NULL
;
2405 struct isakmpsa
*s
= NULL
;
2406 int proplen
, trnslen
;
2407 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2411 proplen
= sizeof(*prop
);
2413 /* create proposal */
2414 prop
= (struct isakmp_pl_p
*)p
;
2415 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2416 prop
->p_no
= props
->prop_no
;
2417 prop
->proto_id
= IPSECDOI_PROTO_ISAKMP
;
2425 for (s
= props
; s
!= NULL
; s
= s
->next
) {
2427 *np_t
= ISAKMP_NPTYPE_T
;
2429 trnslen
= setph1trns(s
, p
);
2432 /* save buffer to pre-next payload */
2433 np_t
= &((struct isakmp_pl_t
*)p
)->h
.np
;
2436 /* count up transform length */
2441 /* update proposal length */
2443 prop
->h
.len
= htons(proplen
);
2444 prop
->num_t
= trns_num
;
2452 struct isakmpsa
*sa
;
2455 struct isakmp_pl_t
*trns
= NULL
;
2456 int trnslen
, attrlen
;
2459 trnslen
= sizeof(*trns
);
2461 /* create transform */
2462 trns
= (struct isakmp_pl_t
*)p
;
2463 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2464 trns
->t_no
= sa
->trns_no
;
2465 trns
->t_id
= IPSECDOI_KEY_IKE
;
2469 attrlen
= setph1attr(sa
, p
);
2475 trns
->h
.len
= htons(trnslen
);
2482 struct isakmpsa
*sa
;
2489 attrlen
+= sizeof(struct isakmp_data
)
2490 + sizeof(struct isakmp_data
);
2491 if (sa
->lifetime
> 0xffff)
2492 attrlen
+= sizeof(sa
->lifetime
);
2494 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2495 OAKLEY_ATTR_SA_LD_TYPE_SEC
);
2496 if (sa
->lifetime
> 0xffff) {
2497 u_int32_t v
= htonl((u_int32_t
)sa
->lifetime
);
2498 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2499 (caddr_t
)&v
, sizeof(v
));
2501 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2508 attrlen
+= sizeof(struct isakmp_data
)
2509 + sizeof(struct isakmp_data
);
2510 if (sa
->lifebyte
> 0xffff)
2511 attrlen
+= sizeof(sa
->lifebyte
);
2513 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD_TYPE
,
2514 OAKLEY_ATTR_SA_LD_TYPE_KB
);
2515 if (sa
->lifebyte
> 0xffff) {
2516 u_int32_t v
= htonl((u_int32_t
)sa
->lifebyte
);
2517 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_SA_LD
,
2518 (caddr_t
)&v
, sizeof(v
));
2520 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_SA_LD
,
2527 attrlen
+= sizeof(struct isakmp_data
);
2529 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_ENC_ALG
, sa
->enctype
);
2532 attrlen
+= sizeof(struct isakmp_data
);
2534 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_KEY_LEN
, sa
->encklen
);
2536 if (sa
->authmethod
) {
2537 attrlen
+= sizeof(struct isakmp_data
);
2539 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_AUTH_METHOD
, sa
->authmethod
);
2542 attrlen
+= sizeof(struct isakmp_data
);
2544 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_HASH_ALG
, sa
->hashtype
);
2546 switch (sa
->dh_group
) {
2547 case OAKLEY_ATTR_GRP_DESC_MODP768
:
2548 case OAKLEY_ATTR_GRP_DESC_MODP1024
:
2549 case OAKLEY_ATTR_GRP_DESC_MODP1536
:
2550 case OAKLEY_ATTR_GRP_DESC_MODP2048
:
2551 case OAKLEY_ATTR_GRP_DESC_MODP3072
:
2552 case OAKLEY_ATTR_GRP_DESC_MODP4096
:
2553 case OAKLEY_ATTR_GRP_DESC_MODP6144
:
2554 case OAKLEY_ATTR_GRP_DESC_MODP8192
:
2555 /* don't attach group type for known groups */
2556 attrlen
+= sizeof(struct isakmp_data
);
2558 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_DESC
,
2562 case OAKLEY_ATTR_GRP_DESC_EC2N155
:
2563 case OAKLEY_ATTR_GRP_DESC_EC2N185
:
2564 /* don't attach group type for known groups */
2565 attrlen
+= sizeof(struct isakmp_data
);
2567 p
= isakmp_set_attr_l(p
, OAKLEY_ATTR_GRP_TYPE
,
2568 OAKLEY_ATTR_GRP_TYPE_EC2N
);
2577 if (sa
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
&&
2578 sa
->gssid
!= NULL
) {
2579 attrlen
+= sizeof(struct isakmp_data
);
2580 attrlen
+= sa
->gssid
->l
;
2582 plog(LLV_DEBUG
, LOCATION
, NULL
, "gss id attr: len %d, "
2583 "val '%s'\n", sa
->gssid
->l
, sa
->gssid
->v
);
2584 p
= isakmp_set_attr_v(p
, OAKLEY_ATTR_GSS_ID
,
2585 (caddr_t
)sa
->gssid
->v
,
2595 setph2proposal0(iph2
, pp
, pr
)
2596 const struct ph2handle
*iph2
;
2597 const struct saprop
*pp
;
2598 const struct saproto
*pr
;
2601 struct isakmp_pl_p
*prop
;
2602 struct isakmp_pl_t
*trns
;
2607 u_int8_t
*np_t
; /* pointer next trns type in previous header */
2608 const u_int8_t
*spi
;
2610 p
= vmalloc(sizeof(*prop
) + sizeof(pr
->spi
));
2614 /* create proposal */
2615 prop
= (struct isakmp_pl_p
*)p
->v
;
2616 prop
->h
.np
= ISAKMP_NPTYPE_NONE
;
2617 prop
->p_no
= pp
->prop_no
;
2618 prop
->proto_id
= pr
->proto_id
;
2621 spi
= (const u_int8_t
*)&pr
->spi
;
2622 switch (pr
->proto_id
) {
2623 case IPSECDOI_PROTO_IPCOMP
:
2625 * draft-shacham-ippcp-rfc2393bis-05.txt:
2626 * construct 16bit SPI (CPI).
2627 * XXX we may need to provide a configuration option to
2628 * generate 32bit SPI. otherwise we cannot interoeprate
2629 * with nodes that uses 32bit SPI, in case we are initiator.
2631 prop
->spi_size
= sizeof(u_int16_t
);
2632 spi
+= sizeof(pr
->spi
) - sizeof(u_int16_t
);
2633 p
->l
-= sizeof(pr
->spi
);
2634 p
->l
+= sizeof(u_int16_t
);
2637 prop
->spi_size
= sizeof(pr
->spi
);
2640 memcpy(prop
+ 1, spi
, prop
->spi_size
);
2642 /* create transform */
2643 trnsoff
= sizeof(*prop
) + prop
->spi_size
;
2646 for (tr
= pr
->head
; tr
; tr
= tr
->next
) {
2649 *np_t
= ISAKMP_NPTYPE_T
;
2653 /* get attribute length */
2656 attrlen
+= sizeof(struct isakmp_data
)
2657 + sizeof(struct isakmp_data
);
2658 if (pp
->lifetime
> 0xffff)
2659 attrlen
+= sizeof(u_int32_t
);
2661 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2662 attrlen
+= sizeof(struct isakmp_data
)
2663 + sizeof(struct isakmp_data
);
2664 if (pp
->lifebyte
> 0xffff)
2665 attrlen
+= sizeof(u_int32_t
);
2667 attrlen
+= sizeof(struct isakmp_data
); /* enc mode */
2669 attrlen
+= sizeof(struct isakmp_data
);
2671 switch (pr
->proto_id
) {
2672 case IPSECDOI_PROTO_IPSEC_ESP
:
2673 /* non authentication mode ? */
2674 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2675 attrlen
+= sizeof(struct isakmp_data
);
2677 case IPSECDOI_PROTO_IPSEC_AH
:
2678 if (tr
->authtype
== IPSECDOI_ATTR_AUTH_NONE
) {
2679 plog(LLV_ERROR
, LOCATION
, NULL
,
2680 "no authentication algorithm found "
2681 "but protocol is AH.\n");
2685 attrlen
+= sizeof(struct isakmp_data
);
2687 case IPSECDOI_PROTO_IPCOMP
:
2690 plog(LLV_ERROR
, LOCATION
, NULL
,
2691 "invalid protocol: %d\n", pr
->proto_id
);
2696 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2697 attrlen
+= sizeof(struct isakmp_data
);
2699 p
= vrealloc(p
, p
->l
+ sizeof(*trns
) + attrlen
);
2702 prop
= (struct isakmp_pl_p
*)p
->v
;
2704 /* set transform's values */
2705 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2706 trns
->h
.np
= ISAKMP_NPTYPE_NONE
;
2707 trns
->t_no
= tr
->trns_no
;
2708 trns
->t_id
= tr
->trns_id
;
2710 /* set attributes */
2711 x
= x0
= p
->v
+ trnsoff
+ sizeof(*trns
);
2714 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2715 IPSECDOI_ATTR_SA_LD_TYPE_SEC
);
2716 if (pp
->lifetime
> 0xffff) {
2717 u_int32_t v
= htonl((u_int32_t
)pp
->lifetime
);
2718 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2719 (caddr_t
)&v
, sizeof(v
));
2721 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2726 if (pp
->lifebyte
&& pp
->lifebyte
!= IPSECDOI_ATTR_SA_LD_KB_MAX
) {
2727 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD_TYPE
,
2728 IPSECDOI_ATTR_SA_LD_TYPE_KB
);
2729 if (pp
->lifebyte
> 0xffff) {
2730 u_int32_t v
= htonl((u_int32_t
)pp
->lifebyte
);
2731 x
= isakmp_set_attr_v(x
, IPSECDOI_ATTR_SA_LD
,
2732 (caddr_t
)&v
, sizeof(v
));
2734 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_SA_LD
,
2739 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_ENC_MODE
, pr
->encmode
);
2742 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_KEY_LENGTH
, tr
->encklen
);
2744 /* mandatory check has done above. */
2745 if ((pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
&& tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
)
2746 || pr
->proto_id
== IPSECDOI_PROTO_IPSEC_AH
)
2747 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_AUTH
, tr
->authtype
);
2749 if (alg_oakley_dhdef_ok(iph2
->sainfo
->pfs_group
))
2750 x
= isakmp_set_attr_l(x
, IPSECDOI_ATTR_GRP_DESC
,
2751 iph2
->sainfo
->pfs_group
);
2753 /* update length of this transform. */
2754 trns
= (struct isakmp_pl_t
*)(p
->v
+ trnsoff
);
2755 trns
->h
.len
= htons(sizeof(*trns
) + attrlen
);
2757 /* save buffer to pre-next payload */
2760 trnsoff
+= (sizeof(*trns
) + attrlen
);
2763 /* update length of this protocol. */
2764 prop
->h
.len
= htons(p
->l
);
2770 * create phase2 proposal from policy configuration.
2771 * NOT INCLUDING isakmp general header of SA payload.
2772 * This function is called by initiator only.
2775 ipsecdoi_setph2proposal(iph2
)
2776 struct ph2handle
*iph2
;
2778 struct saprop
*proposal
, *a
;
2779 struct saproto
*b
= NULL
;
2781 struct ipsecdoi_sa_b
*sab
;
2782 struct isakmp_pl_p
*prop
;
2783 size_t propoff
; /* for previous field of type of next payload. */
2785 proposal
= iph2
->proposal
;
2787 iph2
->sa
= vmalloc(sizeof(*sab
));
2788 if (iph2
->sa
== NULL
) {
2789 plog(LLV_ERROR
, LOCATION
, NULL
,
2790 "failed to allocate my sa buffer\n");
2794 /* create SA payload */
2795 sab
= (struct ipsecdoi_sa_b
*)iph2
->sa
->v
;
2796 sab
->doi
= htonl(IPSEC_DOI
);
2797 sab
->sit
= htonl(IPSECDOI_SIT_IDENTITY_ONLY
); /* XXX configurable ? */
2801 for (a
= proposal
; a
; a
= a
->next
) {
2802 for (b
= a
->head
; b
; b
= b
->next
) {
2805 * Hack to fix encmode, we may have detected a nat since
2806 * we last set pr->encmode. We need to fix this if
2807 * we now have a NAT. NAT-T doesn't work with AH.
2809 if (iph2
->ph1
&& natd_hasnat(iph2
->ph1
) &&
2810 b
->proto_id
!= IPSECDOI_PROTO_IPSEC_AH
)
2814 case IPSECDOI_ATTR_ENC_MODE_TUNNEL
:
2815 b
->encmode
= IPSECDOI_ATTR_ENC_MODE_UDP_TUNNEL
;
2817 case IPSECDOI_ATTR_ENC_MODE_TRNS
:
2818 b
->encmode
= IPSECDOI_ATTR_ENC_MODE_UDP_TRNS
;
2824 q
= setph2proposal0(iph2
, a
, b
);
2830 iph2
->sa
= vrealloc(iph2
->sa
, iph2
->sa
->l
+ q
->l
);
2831 if (iph2
->sa
== NULL
) {
2832 plog(LLV_ERROR
, LOCATION
, NULL
,
2833 "failed to allocate my sa buffer\n");
2838 memcpy(iph2
->sa
->v
+ iph2
->sa
->l
- q
->l
, q
->v
, q
->l
);
2840 prop
= (struct isakmp_pl_p
*)(iph2
->sa
->v
+
2842 prop
->h
.np
= ISAKMP_NPTYPE_P
;
2844 propoff
= iph2
->sa
->l
- q
->l
;
2854 * return 1 if all of the proposed protocols are transport mode.
2857 ipsecdoi_transportmode(iph2
)
2858 struct ph2handle
*iph2
;
2861 struct saproto
*pr
= NULL
;
2863 for (pp
= iph2
->proposal
; pp
; pp
= pp
->next
) {
2864 for (pr
= pp
->head
; pr
; pr
= pr
->next
) {
2865 if (pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_TRNS
&&
2866 pr
->encmode
!= IPSECDOI_ATTR_ENC_MODE_UDP_TRNS
)
2875 ipsecdoi_get_defaultlifetime()
2877 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
2881 ipsecdoi_checkalgtypes(proto_id
, enc
, auth
, comp
)
2882 int proto_id
, enc
, auth
, comp
;
2884 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
2886 case IPSECDOI_PROTO_IPSEC_ESP
:
2887 if (enc
== 0 || comp
!= 0) {
2888 plog(LLV_ERROR
, LOCATION
, NULL
,
2889 "illegal algorithm defined "
2890 "ESP enc=%s auth=%s comp=%s.\n",
2891 TMPALGTYPE2STR(enc
),
2892 TMPALGTYPE2STR(auth
),
2893 TMPALGTYPE2STR(comp
));
2897 case IPSECDOI_PROTO_IPSEC_AH
:
2898 if (enc
!= 0 || auth
== 0 || comp
!= 0) {
2899 plog(LLV_ERROR
, LOCATION
, NULL
,
2900 "illegal algorithm defined "
2901 "AH enc=%s auth=%s comp=%s.\n",
2902 TMPALGTYPE2STR(enc
),
2903 TMPALGTYPE2STR(auth
),
2904 TMPALGTYPE2STR(comp
));
2908 case IPSECDOI_PROTO_IPCOMP
:
2909 if (enc
!= 0 || auth
!= 0 || comp
== 0) {
2910 plog(LLV_ERROR
, LOCATION
, NULL
,
2911 "illegal algorithm defined "
2912 "IPcomp enc=%s auth=%s comp=%s.\n",
2913 TMPALGTYPE2STR(enc
),
2914 TMPALGTYPE2STR(auth
),
2915 TMPALGTYPE2STR(comp
));
2920 plog(LLV_ERROR
, LOCATION
, NULL
,
2921 "invalid ipsec protocol %d\n", proto_id
);
2924 #undef TMPALGTYPE2STR
2934 return IPSECDOI_PROTO_IPSEC_AH
;
2936 return IPSECDOI_PROTO_IPSEC_ESP
;
2937 case IPPROTO_IPCOMP
:
2938 return IPSECDOI_PROTO_IPCOMP
;
2940 return -1; /* XXX */
2948 case IPSECDOI_PROTO_IPSEC_AH
:
2950 case IPSECDOI_PROTO_IPSEC_ESP
:
2952 case IPSECDOI_PROTO_IPCOMP
:
2953 return IPPROTO_IPCOMP
;
2955 return -1; /* XXX */
2959 * check the following:
2960 * - In main mode with pre-shared key, only address type can be used.
2961 * - if proper type for phase 1 ?
2962 * - if phase 1 ID payload conformed RFC2407 4.6.2.
2963 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
2964 * - if ID payload sent from peer is equal to the ID expected by me.
2966 * both of "id" and "id_p" should be ID payload without general header,
2969 ipsecdoi_checkid1(iph1
)
2970 struct ph1handle
*iph1
;
2972 struct ipsecdoi_id_b
*id_b
;
2974 if (iph1
->id_p
== NULL
) {
2975 plog(LLV_ERROR
, LOCATION
, NULL
,
2976 "invalid iph1 passed id_p == NULL\n");
2977 return ISAKMP_INTERNAL_ERROR
;
2979 if (iph1
->id_p
->l
< sizeof(*id_b
)) {
2980 plog(LLV_ERROR
, LOCATION
, NULL
,
2981 "invalid value passed as \"ident\" (len=%lu)\n",
2982 (u_long
)iph1
->id_p
->l
);
2983 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
2986 id_b
= (struct ipsecdoi_id_b
*)iph1
->id_p
->v
;
2988 /* In main mode with pre-shared key, only address type can be used. */
2989 if (iph1
->etype
== ISAKMP_ETYPE_IDENT
2990 && iph1
->approval
->authmethod
== OAKLEY_ATTR_AUTH_METHOD_PSKEY
) {
2991 if (id_b
->type
!= IPSECDOI_ID_IPV4_ADDR
2992 && id_b
->type
!= IPSECDOI_ID_IPV6_ADDR
) {
2993 plog(LLV_ERROR
, LOCATION
, NULL
,
2994 "Expecting IP address type in main mode, "
2995 "but %s.\n", s_ipsecdoi_ident(id_b
->type
));
2996 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3000 /* if proper type for phase 1 ? */
3001 switch (id_b
->type
) {
3002 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3003 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3004 case IPSECDOI_ID_IPV4_ADDR_RANGE
:
3005 case IPSECDOI_ID_IPV6_ADDR_RANGE
:
3006 plog(LLV_WARNING
, LOCATION
, NULL
,
3007 "such ID type %s is not proper.\n",
3008 s_ipsecdoi_ident(id_b
->type
));
3012 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3013 if (id_b
->type
== IPSECDOI_ID_IPV4_ADDR
3014 && id_b
->type
== IPSECDOI_ID_IPV6_ADDR
) {
3016 if (id_b
->proto_id
== 0 && ntohs(id_b
->port
) != 0) {
3017 plog(LLV_WARNING
, LOCATION
, NULL
,
3018 "protocol ID and Port mismatched. "
3019 "proto_id:%d port:%d\n",
3020 id_b
->proto_id
, ntohs(id_b
->port
));
3023 } else if (id_b
->proto_id
== IPPROTO_UDP
) {
3025 * copmaring with expecting port.
3026 * always permit if port is equal to PORT_ISAKMP
3028 if (ntohs(id_b
->port
) != PORT_ISAKMP
) {
3032 switch (iph1
->remote
->sa_family
) {
3034 port
= ((struct sockaddr_in
*)iph1
->remote
)->sin_port
;
3038 port
= ((struct sockaddr_in6
*)iph1
->remote
)->sin6_port
;
3042 plog(LLV_ERROR
, LOCATION
, NULL
,
3043 "invalid family: %d\n",
3044 iph1
->remote
->sa_family
);
3045 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3047 if (ntohs(id_b
->port
) != port
) {
3048 plog(LLV_WARNING
, LOCATION
, NULL
,
3049 "port %d expected, but %d\n",
3050 port
, ntohs(id_b
->port
));
3057 /* compare with the ID if specified. */
3058 if (iph1
->rmconf
->idv_p
) {
3059 vchar_t
*ident0
= NULL
;
3062 /* check the type of both IDs */
3063 if (iph1
->rmconf
->idvtype_p
!= doi2idtype(id_b
->type
)) {
3064 plog(LLV_WARNING
, LOCATION
, NULL
,
3065 "ID type mismatched.\n");
3066 if (iph1
->rmconf
->verify_identifier
)
3067 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3070 /* compare defined ID with the ID sent by peer. */
3071 ident0
= getidval(iph1
->rmconf
->idvtype_p
, iph1
->rmconf
->idv_p
);
3073 switch (iph1
->rmconf
->idvtype_p
) {
3075 ident
.v
= (caddr_t
)(id_b
+ 1);
3076 ident
.l
= ident0
->l
;
3077 if (eay_cmp_asn1dn(ident0
, &ident
)) {
3078 plog(LLV_WARNING
, LOCATION
, NULL
,
3079 "ID value mismatched.\n");
3080 if (iph1
->rmconf
->verify_identifier
)
3081 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3085 if (memcmp(ident0
->v
, id_b
+ 1, ident0
->l
)) {
3086 plog(LLV_WARNING
, LOCATION
, NULL
,
3087 "ID value mismatched.\n");
3088 if (iph1
->rmconf
->verify_identifier
)
3089 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3100 * create ID payload for phase 1 and set into iph1->id.
3101 * NOT INCLUDING isakmp general header.
3102 * see, RFC2407 4.6.2.1
3105 ipsecdoi_setid1(iph1
)
3106 struct ph1handle
*iph1
;
3108 vchar_t
*ret
= NULL
;
3109 struct ipsecdoi_id_b id_b
;
3110 vchar_t
*ident
= NULL
;
3111 struct sockaddr
*ipid
= NULL
;
3118 switch (iph1
->rmconf
->idvtype
) {
3120 id_b
.type
= IPSECDOI_ID_FQDN
;
3121 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3123 case IDTYPE_USERFQDN
:
3124 id_b
.type
= IPSECDOI_ID_USER_FQDN
;
3125 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3128 id_b
.type
= IPSECDOI_ID_KEY_ID
;
3129 ident
= getidval(iph1
->rmconf
->idvtype
, iph1
->rmconf
->idv
);
3131 #ifdef HAVE_SIGNING_C
3133 id_b
.type
= IPSECDOI_ID_DER_ASN1_DN
;
3134 if (iph1
->rmconf
->idv
) {
3135 /* XXX it must be encoded to asn1dn. */
3136 ident
= vdup(iph1
->rmconf
->idv
);
3138 if (oakley_getmycert(iph1
) < 0) {
3139 plog(LLV_ERROR
, LOCATION
, NULL
,
3140 "failed to get own CERT.\n");
3143 ident
= eay_get_x509asn1subjectname(&iph1
->cert
->cert
);
3147 case IDTYPE_ADDRESS
:
3149 * if the value of the id type was set by the configuration
3150 * file, then use it. otherwise the value is get from local
3151 * ip address by using ike negotiation.
3153 if (iph1
->rmconf
->idv
)
3154 ipid
= (struct sockaddr
*)iph1
->rmconf
->idv
->v
;
3164 /* use IP address */
3165 switch (ipid
->sa_family
) {
3167 id_b
.type
= IPSECDOI_ID_IPV4_ADDR
;
3168 l
= sizeof(struct in_addr
);
3169 p
= (caddr_t
)&((struct sockaddr_in
*)ipid
)->sin_addr
;
3173 id_b
.type
= IPSECDOI_ID_IPV6_ADDR
;
3174 l
= sizeof(struct in6_addr
);
3175 p
= (caddr_t
)&((struct sockaddr_in6
*)ipid
)->sin6_addr
;
3179 plog(LLV_ERROR
, LOCATION
, NULL
,
3180 "invalid address family.\n");
3183 id_b
.proto_id
= IPPROTO_UDP
;
3184 id_b
.port
= htons(PORT_ISAKMP
);
3187 plog(LLV_ERROR
, LOCATION
, NULL
,
3188 "failed to get ID buffer.\n");
3191 memcpy(ident
->v
, p
, ident
->l
);
3195 plog(LLV_ERROR
, LOCATION
, NULL
,
3196 "failed to get ID buffer.\n");
3200 ret
= vmalloc(sizeof(id_b
) + ident
->l
);
3202 plog(LLV_ERROR
, LOCATION
, NULL
,
3203 "failed to get ID buffer.\n");
3207 memcpy(ret
->v
, &id_b
, sizeof(id_b
));
3208 memcpy(ret
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3212 plog(LLV_DEBUG
, LOCATION
, NULL
,
3213 "use ID type of %s\n", s_ipsecdoi_ident(id_b
.type
));
3221 plog(LLV_ERROR
, LOCATION
, NULL
, "failed get my ID\n");
3230 vchar_t
*new = NULL
;
3234 else if (lcconf
->ident
[type
])
3235 new = vdup(lcconf
->ident
[type
]);
3240 /* it's only called by cfparse.y. */
3242 set_identifier(vpp
, type
, value
)
3243 vchar_t
**vpp
, *value
;
3246 vchar_t
*new = NULL
;
3248 /* simply return if value is null. */
3254 case IDTYPE_USERFQDN
:
3255 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3256 new = vmalloc(value
->l
- 1);
3259 memcpy(new->v
, value
->v
, new->l
);
3267 fp
= fopen(value
->v
, "r");
3269 plog(LLV_ERROR
, LOCATION
, NULL
,
3270 "can not open %s\n", value
->v
);
3274 while ((len
= fread(b
, 1, sizeof(b
), fp
)) != 0) {
3275 new = vrealloc(new, tlen
+ len
);
3280 memcpy(new->v
+ tlen
, b
, len
);
3285 case IDTYPE_ADDRESS
:
3287 struct sockaddr
*sa
;
3289 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3293 sa
= str2saddr(value
->v
, NULL
);
3295 plog(LLV_ERROR
, LOCATION
, NULL
,
3296 "invalid ip address %s\n", value
->v
);
3300 new = vmalloc(sa
->sa_len
);
3303 memcpy(new->v
, sa
, new->l
);
3307 new = eay_str2asn1dn(value
->v
, value
->l
- 1);
3319 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3320 * NOT INCLUDING isakmp general header.
3321 * this function is for initiator. responder will get to copy from payload.
3322 * responder ID type is always address type.
3323 * see, RFC2407 4.6.2.1
3326 ipsecdoi_setid2(iph2
)
3327 struct ph2handle
*iph2
;
3329 struct secpolicy
*sp
;
3331 /* check there is phase 2 handler ? */
3332 sp
= getspbyspid(iph2
->spid
);
3334 plog(LLV_ERROR
, LOCATION
, NULL
,
3335 "no policy found for spid:%lu.\n", iph2
->spid
);
3339 if (!iph2
->sainfo
->idv
) {
3340 iph2
->id
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.src
,
3341 sp
->spidx
.prefs
, sp
->spidx
.ul_proto
);
3342 if (iph2
->id
== NULL
) {
3343 plog(LLV_ERROR
, LOCATION
, NULL
,
3344 "failed to get ID for %s\n",
3345 spidx2str(&sp
->spidx
));
3348 plog(LLV_DEBUG
, LOCATION
, NULL
, "use local ID type %s\n",
3349 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id
->v
)->type
));
3351 struct ipsecdoi_id_b id_b
;
3354 id_b
.type
= idtype2doi(iph2
->sainfo
->idvtype
);
3355 if (id_b
.type
== 255) {
3356 plog(LLV_ERROR
, LOCATION
, NULL
,
3357 "failed to convert ID type to DOI.\n");
3363 ident
= getidval(iph2
->sainfo
->idvtype
, iph2
->sainfo
->idv
);
3365 plog(LLV_ERROR
, LOCATION
, NULL
,
3366 "failed to get ID value.\n");
3369 iph2
->id
= vmalloc(sizeof(id_b
) + ident
->l
);
3370 if (iph2
->id
== NULL
) {
3371 plog(LLV_ERROR
, LOCATION
, NULL
,
3372 "failed to get ID buffer.\n");
3377 memcpy(iph2
->id
->v
, &id_b
, sizeof(id_b
));
3378 memcpy(iph2
->id
->v
+ sizeof(id_b
), ident
->v
, ident
->l
);
3383 iph2
->id_p
= ipsecdoi_sockaddr2id((struct sockaddr
*)&sp
->spidx
.dst
,
3384 sp
->spidx
.prefd
, sp
->spidx
.ul_proto
);
3385 if (iph2
->id_p
== NULL
) {
3386 plog(LLV_ERROR
, LOCATION
, NULL
,
3387 "failed to get ID for %s\n",
3388 spidx2str(&sp
->spidx
));
3393 plog(LLV_DEBUG
, LOCATION
, NULL
,
3394 "use remote ID type %s\n",
3395 s_ipsecdoi_ident(((struct ipsecdoi_id_b
*)iph2
->id_p
->v
)->type
));
3401 * set address type of ID.
3402 * NOT INCLUDING general header.
3405 ipsecdoi_sockaddr2id(saddr
, prefixlen
, ul_proto
)
3406 struct sockaddr
*saddr
;
3411 int type
, len1
, len2
;
3416 * Q. When type is SUBNET, is it allowed to be ::1/128.
3417 * A. Yes. (consensus at bake-off)
3419 switch (saddr
->sa_family
) {
3421 len1
= sizeof(struct in_addr
);
3422 if (prefixlen
== (sizeof(struct in_addr
) << 3)) {
3423 type
= IPSECDOI_ID_IPV4_ADDR
;
3426 type
= IPSECDOI_ID_IPV4_ADDR_SUBNET
;
3427 len2
= sizeof(struct in_addr
);
3429 sa
= (caddr_t
)&((struct sockaddr_in
*)(saddr
))->sin_addr
;
3430 port
= ((struct sockaddr_in
*)(saddr
))->sin_port
;
3434 len1
= sizeof(struct in6_addr
);
3435 if (prefixlen
== (sizeof(struct in6_addr
) << 3)) {
3436 type
= IPSECDOI_ID_IPV6_ADDR
;
3439 type
= IPSECDOI_ID_IPV6_ADDR_SUBNET
;
3440 len2
= sizeof(struct in6_addr
);
3442 sa
= (caddr_t
)&((struct sockaddr_in6
*)(saddr
))->sin6_addr
;
3443 port
= ((struct sockaddr_in6
*)(saddr
))->sin6_port
;
3447 plog(LLV_ERROR
, LOCATION
, NULL
,
3448 "invalid family: %d.\n", saddr
->sa_family
);
3453 new = vmalloc(sizeof(struct ipsecdoi_id_b
) + len1
+ len2
);
3455 plog(LLV_ERROR
, LOCATION
, NULL
,
3456 "failed to get ID buffer.\n");
3460 memset(new->v
, 0, new->l
);
3462 /* set the part of header. */
3463 ((struct ipsecdoi_id_b
*)new->v
)->type
= type
;
3465 /* set ul_proto and port */
3467 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3468 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3470 ((struct ipsecdoi_id_b
*)new->v
)->proto_id
=
3471 ul_proto
== IPSEC_ULPROTO_ANY
? 0 : ul_proto
;
3472 ((struct ipsecdoi_id_b
*)new->v
)->port
=
3473 port
== IPSEC_PORT_ANY
? 0 : port
;
3474 memcpy(new->v
+ sizeof(struct ipsecdoi_id_b
), sa
, len1
);
3480 u_char
*p
= new->v
+ sizeof(struct ipsecdoi_id_b
) + len1
;
3481 u_int bits
= prefixlen
;
3489 *p
= ~((1 << (8 - bits
)) - 1);
3496 * create sockaddr structure from ID payload (buf).
3497 * buffers (saddr, prefixlen, ul_proto) must be allocated.
3498 * see, RFC2407 4.6.2.1
3501 ipsecdoi_id2sockaddr(buf
, saddr
, prefixlen
, ul_proto
)
3503 struct sockaddr
*saddr
;
3504 u_int8_t
*prefixlen
;
3505 u_int16_t
*ul_proto
;
3507 struct ipsecdoi_id_b
*id_b
= (struct ipsecdoi_id_b
*)buf
->v
;
3511 * When a ID payload of subnet type with a IP address of full bit
3512 * masked, it has to be processed as host address.
3513 * e.g. below 2 type are same.
3514 * type = ipv6 subnet, data = 2001::1/128
3515 * type = ipv6 address, data = 2001::1
3517 switch (id_b
->type
) {
3518 case IPSECDOI_ID_IPV4_ADDR
:
3519 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3520 saddr
->sa_len
= sizeof(struct sockaddr_in
);
3521 saddr
->sa_family
= AF_INET
;
3522 ((struct sockaddr_in
*)saddr
)->sin_port
=
3525 : id_b
->port
); /* see sockaddr2id() */
3526 memcpy(&((struct sockaddr_in
*)saddr
)->sin_addr
,
3527 buf
->v
+ sizeof(*id_b
), sizeof(struct in_addr
));
3530 case IPSECDOI_ID_IPV6_ADDR
:
3531 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3532 saddr
->sa_len
= sizeof(struct sockaddr_in6
);
3533 saddr
->sa_family
= AF_INET6
;
3534 ((struct sockaddr_in6
*)saddr
)->sin6_port
=
3537 : id_b
->port
); /* see sockaddr2id() */
3538 memcpy(&((struct sockaddr_in6
*)saddr
)->sin6_addr
,
3539 buf
->v
+ sizeof(*id_b
), sizeof(struct in6_addr
));
3543 plog(LLV_ERROR
, LOCATION
, NULL
,
3544 "unsupported ID type %d\n", id_b
->type
);
3545 return ISAKMP_NTYPE_INVALID_ID_INFORMATION
;
3548 /* get prefix length */
3549 switch (id_b
->type
) {
3550 case IPSECDOI_ID_IPV4_ADDR
:
3551 plen
= sizeof(struct in_addr
) << 3;
3554 case IPSECDOI_ID_IPV6_ADDR
:
3555 plen
= sizeof(struct in6_addr
) << 3;
3558 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3560 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3565 int alen
= sizeof(struct in_addr
);
3567 switch (id_b
->type
) {
3568 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3569 alen
= sizeof(struct in_addr
);
3572 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3573 alen
= sizeof(struct in6_addr
);
3580 return ISAKMP_INTERNAL_ERROR
;
3582 /* get subnet mask length */
3587 + sizeof(struct ipsecdoi_id_b
)
3590 for (; *p
== 0xff; p
++) {
3613 *ul_proto
= id_b
->proto_id
== 0
3615 : id_b
->proto_id
; /* see sockaddr2id() */
3621 * make printable string from ID payload except of general header.
3627 static char buf
[256];
3636 * set IPsec data attributes into a proposal.
3637 * NOTE: MUST called per a transform.
3640 ipsecdoi_t2satrns(t
, pp
, pr
, tr
)
3641 struct isakmp_pl_t
*t
;
3646 struct isakmp_data
*d
, *prev
;
3652 tr
->trns_no
= t
->t_no
;
3653 tr
->trns_id
= t
->t_id
;
3655 tlen
= ntohs(t
->h
.len
) - sizeof(*t
);
3656 prev
= (struct isakmp_data
*)NULL
;
3657 d
= (struct isakmp_data
*)(t
+ 1);
3660 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
3661 pp
->lifetime
= IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
;
3663 tr
->authtype
= IPSECDOI_ATTR_AUTH_NONE
;
3667 type
= ntohs(d
->type
) & ~ISAKMP_GEN_MASK
;
3668 flag
= ntohs(d
->type
) & ISAKMP_GEN_MASK
;
3670 plog(LLV_DEBUG
, LOCATION
, NULL
,
3671 "type=%s, flag=0x%04x, lorv=%s\n",
3672 s_ipsecdoi_attr(type
), flag
,
3673 s_ipsecdoi_attr_v(type
, ntohs(d
->lorv
)));
3676 case IPSECDOI_ATTR_SA_LD_TYPE
:
3678 int type
= ntohs(d
->lorv
);
3680 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
3681 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
3685 plog(LLV_WARNING
, LOCATION
, NULL
,
3686 "invalid life duration type. "
3688 life_t
= IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT
;
3693 case IPSECDOI_ATTR_SA_LD
:
3695 || (ntohs(prev
->type
) & ~ISAKMP_GEN_MASK
) !=
3696 IPSECDOI_ATTR_SA_LD_TYPE
) {
3697 plog(LLV_ERROR
, LOCATION
, NULL
,
3698 "life duration must follow ltype\n");
3704 vchar_t
*ld_buf
= NULL
;
3707 /* i.e. ISAKMP_GEN_TV */
3708 ld_buf
= vmalloc(sizeof(d
->lorv
));
3709 if (ld_buf
== NULL
) {
3710 plog(LLV_ERROR
, LOCATION
, NULL
,
3711 "failed to get LD buffer.\n");
3714 memcpy(ld_buf
->v
, &d
->lorv
, sizeof(d
->lorv
));
3716 int len
= ntohs(d
->lorv
);
3717 /* i.e. ISAKMP_GEN_TLV */
3718 ld_buf
= vmalloc(len
);
3719 if (ld_buf
== NULL
) {
3720 plog(LLV_ERROR
, LOCATION
, NULL
,
3721 "failed to get LD buffer.\n");
3724 memcpy(ld_buf
->v
, d
+ 1, len
);
3727 case IPSECDOI_ATTR_SA_LD_TYPE_SEC
:
3728 t
= ipsecdoi_set_ld(ld_buf
);
3731 plog(LLV_ERROR
, LOCATION
, NULL
,
3732 "invalid life duration.\n");
3735 /* lifetime must be equal in a proposal. */
3736 if (pp
->lifetime
== IPSECDOI_ATTR_SA_LD_SEC_DEFAULT
)
3738 else if (pp
->lifetime
!= t
) {
3739 plog(LLV_ERROR
, LOCATION
, NULL
,
3740 "lifetime mismatched "
3742 "prev:%ld curr:%ld.\n",
3747 case IPSECDOI_ATTR_SA_LD_TYPE_KB
:
3748 t
= ipsecdoi_set_ld(ld_buf
);
3751 plog(LLV_ERROR
, LOCATION
, NULL
,
3752 "invalid life duration.\n");
3755 /* lifebyte must be equal in a proposal. */
3756 if (pp
->lifebyte
== 0)
3758 else if (pp
->lifebyte
!= t
) {
3759 plog(LLV_ERROR
, LOCATION
, NULL
,
3760 "lifebyte mismatched "
3762 "prev:%ld curr:%ld.\n",
3769 plog(LLV_ERROR
, LOCATION
, NULL
,
3770 "invalid life type: %d\n", life_t
);
3776 case IPSECDOI_ATTR_GRP_DESC
:
3778 * RFC2407: 4.5 IPSEC Security Association Attributes
3779 * Specifies the Oakley Group to be used in a PFS QM
3780 * negotiation. For a list of supported values, see
3781 * Appendix A of [IKE].
3783 if (pp
->pfs_group
== 0)
3784 pp
->pfs_group
= (u_int16_t
)ntohs(d
->lorv
);
3785 else if (pp
->pfs_group
!= (u_int16_t
)ntohs(d
->lorv
)) {
3786 plog(LLV_ERROR
, LOCATION
, NULL
,
3787 "pfs_group mismatched "
3788 "in a proposal.\n");
3793 case IPSECDOI_ATTR_ENC_MODE
:
3795 && pr
->encmode
!= (u_int16_t
)ntohs(d
->lorv
)) {
3796 plog(LLV_ERROR
, LOCATION
, NULL
,
3797 "multiple encmode exist "
3798 "in a transform.\n");
3801 pr
->encmode
= (u_int16_t
)ntohs(d
->lorv
);
3804 case IPSECDOI_ATTR_AUTH
:
3805 if (tr
->authtype
!= IPSECDOI_ATTR_AUTH_NONE
) {
3806 plog(LLV_ERROR
, LOCATION
, NULL
,
3807 "multiple authtype exist "
3808 "in a transform.\n");
3811 tr
->authtype
= (u_int16_t
)ntohs(d
->lorv
);
3814 case IPSECDOI_ATTR_KEY_LENGTH
:
3815 if (pr
->proto_id
!= IPSECDOI_PROTO_IPSEC_ESP
) {
3816 plog(LLV_ERROR
, LOCATION
, NULL
,
3817 "key length defined but not ESP");
3820 tr
->encklen
= ntohs(d
->lorv
);
3823 case IPSECDOI_ATTR_KEY_ROUNDS
:
3824 case IPSECDOI_ATTR_COMP_DICT_SIZE
:
3825 case IPSECDOI_ATTR_COMP_PRIVALG
:
3833 d
= (struct isakmp_data
*)((char *)d
+ sizeof(*d
));
3835 tlen
-= (sizeof(*d
) + ntohs(d
->lorv
));
3836 d
= (struct isakmp_data
*)((caddr_t
)d
+ sizeof(*d
) + ntohs(d
->lorv
));
3846 ipsecdoi_authalg2trnsid(alg
)
3850 case IPSECDOI_ATTR_AUTH_HMAC_MD5
:
3851 return IPSECDOI_AH_MD5
;
3852 case IPSECDOI_ATTR_AUTH_HMAC_SHA1
:
3853 return IPSECDOI_AH_SHA
;
3854 case IPSECDOI_ATTR_AUTH_DES_MAC
:
3855 return IPSECDOI_AH_DES
;
3856 case IPSECDOI_ATTR_AUTH_KPDK
:
3857 return IPSECDOI_AH_MD5
; /* XXX */
3859 plog(LLV_ERROR
, LOCATION
, NULL
,
3860 "invalid authentication algorithm:%d\n", alg
);
3867 fixup_initiator_sa(match
, received
)
3868 struct isakmpsa
*match
, *received
;
3870 struct isakmpsa
*newsa
;
3872 if (received
->gssid
== NULL
)
3875 newsa
= newisakmpsa();
3876 memcpy(newsa
, match
, sizeof *newsa
);
3878 if (match
->dhgrp
!= NULL
) {
3879 newsa
->dhgrp
= racoon_calloc(1, sizeof(struct dhgroup
));
3880 memcpy(newsa
->dhgrp
, match
->dhgrp
, sizeof (struct dhgroup
));
3883 newsa
->rmconf
= NULL
;
3885 newsa
->gssid
= vdup(received
->gssid
);
3891 static int rm_idtype2doi
[] = {
3893 IPSECDOI_ID_USER_FQDN
,
3895 255, /* it's type of "address"
3896 * it expands into 4 types by another function. */
3897 IPSECDOI_ID_DER_ASN1_DN
,
3901 * convert idtype to DOI value.
3909 if (ARRAYLEN(rm_idtype2doi
) > idtype
)
3910 return rm_idtype2doi
[idtype
];
3919 case IPSECDOI_ID_FQDN
:
3920 return(IDTYPE_FQDN
);
3921 case IPSECDOI_ID_USER_FQDN
:
3922 return(IDTYPE_USERFQDN
);
3923 case IPSECDOI_ID_KEY_ID
:
3924 return(IDTYPE_KEYID
);
3925 case IPSECDOI_ID_DER_ASN1_DN
:
3926 return(IDTYPE_ASN1DN
);
3927 case IPSECDOI_ID_IPV4_ADDR
:
3928 case IPSECDOI_ID_IPV4_ADDR_SUBNET
:
3929 case IPSECDOI_ID_IPV6_ADDR
:
3930 case IPSECDOI_ID_IPV6_ADDR_SUBNET
:
3931 return(IDTYPE_ADDRESS
);
3933 plog(LLV_WARNING
, LOCATION
, NULL
,
3934 "Inproper idtype:%d in this function.\n",
3935 s_ipsecdoi_ident(doi
));
3936 return(IDTYPE_ADDRESS
); /* XXX */