No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / racoon / ipsec_doi.c
blob8bd3115b2584f7c37191a1d7c841b7cf0215e947
1 /* $NetBSD: ipsec_doi.c,v 1.42 2009/05/18 17:40:38 tteras Exp $ */
3 /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "config.h"
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
40 #include <netinet/in.h>
42 #include PATH_IPSEC_H
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <errno.h>
48 #include <netdb.h>
49 #if TIME_WITH_SYS_TIME
50 # include <sys/time.h>
51 # include <time.h>
52 #else
53 # if HAVE_SYS_TIME_H
54 # include <sys/time.h>
55 # else
56 # include <time.h>
57 # endif
58 #endif
60 #include "var.h"
61 #include "vmbuf.h"
62 #include "misc.h"
63 #include "plog.h"
64 #include "debug.h"
66 #include "cfparse_proto.h"
67 #include "isakmp_var.h"
68 #include "isakmp.h"
69 #include "ipsec_doi.h"
70 #include "oakley.h"
71 #include "remoteconf.h"
72 #include "localconf.h"
73 #include "sockmisc.h"
74 #include "handler.h"
75 #include "policy.h"
76 #include "algorithm.h"
77 #include "sainfo.h"
78 #include "proposal.h"
79 #include "crypto_openssl.h"
80 #include "strnames.h"
81 #include "gcmalloc.h"
83 #ifdef ENABLE_NATT
84 #include "nattraversal.h"
85 #endif
87 #ifdef HAVE_GSSAPI
88 #include <iconv.h>
89 #include "gssapi.h"
90 #ifdef HAVE_ICONV_2ND_CONST
91 #define __iconv_const const
92 #else
93 #define __iconv_const
94 #endif
95 #endif
97 static vchar_t *get_ph1approval __P((struct ph1handle *, u_int32_t, u_int32_t,
98 struct prop_pair **));
99 static int get_ph1approvalx __P((struct remoteconf *, void *));
101 static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *, u_int32_t));
102 static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
103 static struct prop_pair *get_ph2approval __P((struct ph2handle *,
104 struct prop_pair **));
105 static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
106 struct prop_pair *));
107 static void free_proppair0 __P((struct prop_pair *));
108 static struct prop_pair ** get_proppair_and_doi_sit __P((vchar_t *, int,
109 u_int32_t *, u_int32_t *));
111 static int get_transform
112 __P((struct isakmp_pl_p *, struct prop_pair **, int *));
113 static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
115 static int check_doi __P((u_int32_t));
116 static int check_situation __P((u_int32_t));
118 static int check_prot_main __P((int));
119 static int check_prot_quick __P((int));
120 static int (*check_protocol[]) __P((int)) = {
121 check_prot_main, /* IPSECDOI_TYPE_PH1 */
122 check_prot_quick, /* IPSECDOI_TYPE_PH2 */
125 static int check_spi_size __P((int, int));
127 static int check_trns_isakmp __P((int));
128 static int check_trns_ah __P((int));
129 static int check_trns_esp __P((int));
130 static int check_trns_ipcomp __P((int));
131 static int (*check_transform[]) __P((int)) = {
133 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
134 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
135 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
136 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
139 static int check_attr_isakmp __P((struct isakmp_pl_t *));
140 static int check_attr_ah __P((struct isakmp_pl_t *));
141 static int check_attr_esp __P((struct isakmp_pl_t *));
142 static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
143 static int check_attr_ipcomp __P((struct isakmp_pl_t *));
144 static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
146 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
147 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
148 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
149 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
152 static int setph1prop __P((struct isakmpsa *, caddr_t));
153 static int setph1trns __P((struct isakmpsa *, caddr_t));
154 static int setph1attr __P((struct isakmpsa *, caddr_t));
155 static vchar_t *setph2proposal0 __P((const struct ph2handle *,
156 const struct saprop *, const struct saproto *));
158 struct ph1approvalx_ctx {
159 struct prop_pair *p;
160 struct isakmpsa *sa;
163 /*%%%*/
165 * check phase 1 SA payload.
166 * make new SA payload to be replyed not including general header.
167 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
168 * OUT:
169 * positive: the pointer to new buffer of SA payload.
170 * network byte order.
171 * NULL : error occurd.
174 ipsecdoi_checkph1proposal(sa, iph1)
175 vchar_t *sa;
176 struct ph1handle *iph1;
178 vchar_t *newsa; /* new SA payload approved. */
179 struct prop_pair **pair;
180 u_int32_t doitype, sittype;
182 /* get proposal pair */
183 pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1,
184 &doitype, &sittype);
185 if (pair == NULL)
186 return -1;
188 /* check and get one SA for use */
189 newsa = get_ph1approval(iph1, doitype, sittype, pair);
190 free_proppair(pair);
192 if (newsa == NULL)
193 return -1;
195 iph1->sa_ret = newsa;
196 return 0;
199 static void
200 print_ph1proposal(pair, s)
201 struct prop_pair *pair;
202 struct isakmpsa *s;
204 struct isakmp_pl_p *prop = pair->prop;
205 struct isakmp_pl_t *trns = pair->trns;
207 plog(LLV_DEBUG, LOCATION, NULL,
208 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
209 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
210 prop->spi_size, prop->num_t);
211 plog(LLV_DEBUG, LOCATION, NULL,
212 "trns#=%d, trns-id=%s\n",
213 trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id));
214 plog(LLV_DEBUG, LOCATION, NULL,
215 " lifetime = %ld\n", (long) s->lifetime);
216 plog(LLV_DEBUG, LOCATION, NULL,
217 " lifebyte = %zu\n", s->lifebyte);
218 plog(LLV_DEBUG, LOCATION, NULL,
219 " enctype = %s\n",
220 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype));
221 plog(LLV_DEBUG, LOCATION, NULL,
222 " encklen = %d\n", s->encklen);
223 plog(LLV_DEBUG, LOCATION, NULL,
224 " hashtype = %s\n",
225 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype));
226 plog(LLV_DEBUG, LOCATION, NULL,
227 " authmethod = %s\n",
228 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod));
229 plog(LLV_DEBUG, LOCATION, NULL,
230 " dh_group = %s\n",
231 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group));
236 * acceptable check for remote configuration.
237 * return a new SA payload to be reply to peer.
240 static vchar_t *
241 get_ph1approval(iph1, doitype, sittype, pair)
242 struct ph1handle *iph1;
243 u_int32_t doitype, sittype;
244 struct prop_pair **pair;
246 vchar_t *newsa;
247 struct ph1approvalx_ctx ctx;
248 struct prop_pair *s, *p;
249 struct rmconfselector rmsel;
250 struct isakmpsa *sa;
251 int i;
253 memset(&rmsel, 0, sizeof(rmsel));
254 rmsel.remote = iph1->remote;
256 if (iph1->approval) {
257 delisakmpsa(iph1->approval);
258 iph1->approval = NULL;
261 for (i = 0; i < MAXPROPPAIRLEN; i++) {
262 if (pair[i] == NULL)
263 continue;
264 for (s = pair[i]; s; s = s->next) {
265 /* compare proposal and select one */
266 for (p = s; p; p = p->tnext) {
267 struct isakmp_pl_p *prop = p->prop;
269 sa = newisakmpsa();
270 ctx.p = p;
271 ctx.sa = sa;
272 if (t2isakmpsa(p->trns, sa,
273 iph1->vendorid_mask) < 0)
274 continue;
275 print_ph1proposal(p, sa);
276 if (iph1->rmconf != NULL) {
277 if (get_ph1approvalx(iph1->rmconf, &ctx))
278 goto found;
279 } else {
280 if (enumrmconf(&rmsel, get_ph1approvalx, &ctx))
281 goto found;
283 delisakmpsa(sa);
288 plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
290 return NULL;
292 found:
293 sa = ctx.sa;
294 plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
296 /* check DH group settings */
297 if (sa->dhgrp) {
298 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
299 /* it's ok */
300 goto saok;
302 plog(LLV_WARNING, LOCATION, NULL,
303 "invalid DH parameter found, use default.\n");
304 oakley_dhgrp_free(sa->dhgrp);
305 sa->dhgrp=NULL;
308 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
309 sa->dhgrp = NULL;
310 delisakmpsa(sa);
311 return NULL;
314 saok:
315 #ifdef HAVE_GSSAPI
316 if (sa->gssid != NULL)
317 plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
318 (int)sa->gssid->l, sa->gssid->v);
319 if (iph1->side == INITIATOR) {
320 if (iph1->rmconf->proposal->gssid != NULL)
321 iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
322 if (sa->gssid != NULL)
323 iph1->gi_r = vdup(sa->gssid);
324 } else {
325 if (sa->gssid != NULL) {
326 iph1->gi_r = vdup(sa->gssid);
327 iph1->gi_i = gssapi_get_id(iph1);
330 if (iph1->gi_i != NULL)
331 plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
332 (int)iph1->gi_i->l, iph1->gi_i->v);
333 if (iph1->gi_r != NULL)
334 plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
335 (int)iph1->gi_r->l, iph1->gi_r->v);
336 #endif
337 plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
338 s_oakley_attr_method(sa->authmethod));
340 newsa = get_sabyproppair(doitype, sittype, p);
341 if (newsa == NULL)
342 delisakmpsa(sa);
343 else
344 iph1->approval = sa;
346 return newsa;
350 * compare peer's single proposal and all of my proposal.
351 * and select one if suiatable.
353 static int
354 get_ph1approvalx(rmconf, ctx)
355 struct remoteconf *rmconf;
356 void *ctx;
358 struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx;
359 struct isakmpsa *sa;
361 /* do the hard work */
362 sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal);
363 if (sa == NULL)
364 return 0;
366 /* duplicate and modify the found SA to match proposal */
367 sa = dupisakmpsa(sa);
369 switch (rmconf->pcheck_level) {
370 case PROP_CHECK_OBEY:
371 sa->lifetime = pctx->sa->lifetime;
372 sa->lifebyte = pctx->sa->lifebyte;
373 break;
374 case PROP_CHECK_CLAIM:
375 if (pctx->sa->lifetime < sa->lifetime)
376 sa->lifetime = pctx->sa->lifetime;
377 if (pctx->sa->lifebyte < sa->lifebyte)
378 sa->lifebyte = pctx->sa->lifebyte;
379 break;
380 default:
381 break;
384 /* replace the proposal with our approval sa */
385 delisakmpsa(pctx->sa);
386 pctx->sa = sa;
388 return 1;
392 * get ISAKMP data attributes
394 static int
395 t2isakmpsa(trns, sa, vendorid_mask)
396 struct isakmp_pl_t *trns;
397 struct isakmpsa *sa;
398 u_int32_t vendorid_mask;
400 struct isakmp_data *d, *prev;
401 int flag, type;
402 int error = -1;
403 int life_t;
404 int keylen = 0;
405 vchar_t *val = NULL;
406 int len, tlen;
407 u_char *p;
409 tlen = ntohs(trns->h.len) - sizeof(*trns);
410 prev = (struct isakmp_data *)NULL;
411 d = (struct isakmp_data *)(trns + 1);
413 /* default */
414 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
415 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
416 sa->lifebyte = 0;
417 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
418 if (!sa->dhgrp)
419 goto err;
421 while (tlen > 0) {
423 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
424 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
426 plog(LLV_DEBUG, LOCATION, NULL,
427 "type=%s, flag=0x%04x, lorv=%s\n",
428 s_oakley_attr(type), flag,
429 s_oakley_attr_v(type, ntohs(d->lorv)));
431 /* get variable-sized item */
432 switch (type) {
433 case OAKLEY_ATTR_GRP_PI:
434 case OAKLEY_ATTR_GRP_GEN_ONE:
435 case OAKLEY_ATTR_GRP_GEN_TWO:
436 case OAKLEY_ATTR_GRP_CURVE_A:
437 case OAKLEY_ATTR_GRP_CURVE_B:
438 case OAKLEY_ATTR_SA_LD:
439 case OAKLEY_ATTR_GRP_ORDER:
440 if (flag) { /*TV*/
441 len = 2;
442 p = (u_char *)&d->lorv;
443 } else { /*TLV*/
444 len = ntohs(d->lorv);
445 p = (u_char *)(d + 1);
447 val = vmalloc(len);
448 if (!val)
449 return -1;
450 memcpy(val->v, p, len);
451 break;
453 default:
454 break;
457 switch (type) {
458 case OAKLEY_ATTR_ENC_ALG:
459 sa->enctype = (u_int16_t)ntohs(d->lorv);
460 break;
462 case OAKLEY_ATTR_HASH_ALG:
463 sa->hashtype = (u_int16_t)ntohs(d->lorv);
464 break;
466 case OAKLEY_ATTR_AUTH_METHOD:
467 sa->authmethod = ntohs(d->lorv);
468 #ifdef HAVE_GSSAPI
469 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL &&
470 (vendorid_mask & VENDORID_GSSAPI_MASK))
471 sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB;
472 #endif
473 break;
475 case OAKLEY_ATTR_GRP_DESC:
476 sa->dh_group = (u_int16_t)ntohs(d->lorv);
477 break;
479 case OAKLEY_ATTR_GRP_TYPE:
481 int type = (int)ntohs(d->lorv);
482 if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
483 sa->dhgrp->type = type;
484 else
485 return -1;
486 break;
488 case OAKLEY_ATTR_GRP_PI:
489 sa->dhgrp->prime = val;
490 break;
492 case OAKLEY_ATTR_GRP_GEN_ONE:
493 vfree(val);
494 if (!flag)
495 sa->dhgrp->gen1 = ntohs(d->lorv);
496 else {
497 int len = ntohs(d->lorv);
498 sa->dhgrp->gen1 = 0;
499 if (len > 4)
500 return -1;
501 memcpy(&sa->dhgrp->gen1, d + 1, len);
502 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
504 break;
506 case OAKLEY_ATTR_GRP_GEN_TWO:
507 vfree(val);
508 if (!flag)
509 sa->dhgrp->gen2 = ntohs(d->lorv);
510 else {
511 int len = ntohs(d->lorv);
512 sa->dhgrp->gen2 = 0;
513 if (len > 4)
514 return -1;
515 memcpy(&sa->dhgrp->gen2, d + 1, len);
516 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
518 break;
520 case OAKLEY_ATTR_GRP_CURVE_A:
521 sa->dhgrp->curve_a = val;
522 break;
524 case OAKLEY_ATTR_GRP_CURVE_B:
525 sa->dhgrp->curve_b = val;
526 break;
528 case OAKLEY_ATTR_SA_LD_TYPE:
530 int type = (int)ntohs(d->lorv);
531 switch (type) {
532 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
533 case OAKLEY_ATTR_SA_LD_TYPE_KB:
534 life_t = type;
535 break;
536 default:
537 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
538 break;
540 break;
542 case OAKLEY_ATTR_SA_LD:
543 if (!prev
544 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
545 OAKLEY_ATTR_SA_LD_TYPE) {
546 plog(LLV_ERROR, LOCATION, NULL,
547 "life duration must follow ltype\n");
548 break;
551 switch (life_t) {
552 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
553 sa->lifetime = ipsecdoi_set_ld(val);
554 vfree(val);
555 if (sa->lifetime == 0) {
556 plog(LLV_ERROR, LOCATION, NULL,
557 "invalid life duration.\n");
558 goto err;
560 break;
561 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
562 sa->lifebyte = ipsecdoi_set_ld(val);
563 vfree(val);
564 if (sa->lifebyte == 0) {
565 plog(LLV_ERROR, LOCATION, NULL,
566 "invalid life duration.\n");
567 goto err;
569 break;
570 default:
571 vfree(val);
572 plog(LLV_ERROR, LOCATION, NULL,
573 "invalid life type: %d\n", life_t);
574 goto err;
576 break;
578 case OAKLEY_ATTR_KEY_LEN:
580 int len = ntohs(d->lorv);
581 if (len % 8 != 0) {
582 plog(LLV_ERROR, LOCATION, NULL,
583 "keylen %d: not multiple of 8\n",
584 len);
585 goto err;
587 sa->encklen = (u_int16_t)len;
588 keylen++;
589 break;
591 case OAKLEY_ATTR_PRF:
592 case OAKLEY_ATTR_FIELD_SIZE:
593 /* unsupported */
594 break;
596 case OAKLEY_ATTR_GRP_ORDER:
597 sa->dhgrp->order = val;
598 break;
599 #ifdef HAVE_GSSAPI
600 case OAKLEY_ATTR_GSS_ID:
602 int error = -1;
603 iconv_t cd = (iconv_t) -1;
604 size_t srcleft, dstleft, rv;
605 __iconv_const char *src;
606 char *dst;
607 int len = ntohs(d->lorv);
610 * Older verions of racoon just placed the
611 * ISO-Latin-1 string on the wire directly.
612 * Check to see if we are configured to be
613 * compatible with this behavior.
615 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
616 if ((sa->gssid = vmalloc(len)) == NULL) {
617 plog(LLV_ERROR, LOCATION, NULL,
618 "failed to allocate memory\n");
619 goto out;
621 memcpy(sa->gssid->v, d + 1, len);
622 plog(LLV_DEBUG, LOCATION, NULL,
623 "received old-style gss "
624 "id '%.*s' (len %zu)\n",
625 (int)sa->gssid->l, sa->gssid->v,
626 sa->gssid->l);
627 error = 0;
628 goto out;
632 * For Windows 2000 compatibility, we expect
633 * the GSS ID attribute on the wire to be
634 * encoded in UTF-16LE. Internally, we work
635 * in ISO-Latin-1. Therefore, we should need
636 * 1/2 the specified length, which should always
637 * be a multiple of 2 octets.
639 cd = iconv_open("latin1", "utf-16le");
640 if (cd == (iconv_t) -1) {
641 plog(LLV_ERROR, LOCATION, NULL,
642 "unable to initialize utf-16le -> latin1 "
643 "conversion descriptor: %s\n",
644 strerror(errno));
645 goto out;
648 if ((sa->gssid = vmalloc(len / 2)) == NULL) {
649 plog(LLV_ERROR, LOCATION, NULL,
650 "failed to allocate memory\n");
651 goto out;
654 src = (__iconv_const char *)(d + 1);
655 srcleft = len;
657 dst = sa->gssid->v;
658 dstleft = len / 2;
660 rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
661 &dst, &dstleft);
662 if (rv != 0) {
663 if (rv == -1) {
664 plog(LLV_ERROR, LOCATION, NULL,
665 "unable to convert GSS ID from "
666 "utf-16le -> latin1: %s\n",
667 strerror(errno));
668 } else {
669 plog(LLV_ERROR, LOCATION, NULL,
670 "%zd character%s in GSS ID cannot "
671 "be represented in latin1\n",
672 rv, rv == 1 ? "" : "s");
674 goto out;
677 /* XXX dstleft should always be 0; assert it? */
678 sa->gssid->l = (len / 2) - dstleft;
680 plog(LLV_DEBUG, LOCATION, NULL,
681 "received gss id '%.*s' (len %zu)\n",
682 (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
684 error = 0;
685 out:
686 if (cd != (iconv_t)-1)
687 (void)iconv_close(cd);
689 if ((error != 0) && (sa->gssid != NULL)) {
690 vfree(sa->gssid);
691 sa->gssid = NULL;
693 break;
695 #endif /* HAVE_GSSAPI */
697 default:
698 break;
701 prev = d;
702 if (flag) {
703 tlen -= sizeof(*d);
704 d = (struct isakmp_data *)((char *)d + sizeof(*d));
705 } else {
706 tlen -= (sizeof(*d) + ntohs(d->lorv));
707 d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
711 /* key length must not be specified on some algorithms */
712 if (keylen) {
713 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
714 #ifdef HAVE_OPENSSL_IDEA_H
715 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
716 #endif
717 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
718 plog(LLV_ERROR, LOCATION, NULL,
719 "keylen must not be specified "
720 "for encryption algorithm %d\n",
721 sa->enctype);
722 return -1;
726 return 0;
727 err:
728 return error;
731 /*%%%*/
733 * check phase 2 SA payload and select single proposal.
734 * make new SA payload to be replyed not including general header.
735 * This function is called by responder only.
736 * OUT:
737 * 0: succeed.
738 * -1: error occured.
741 ipsecdoi_selectph2proposal(iph2)
742 struct ph2handle *iph2;
744 struct prop_pair **pair;
745 struct prop_pair *ret;
746 u_int32_t doitype, sittype;
748 /* get proposal pair */
749 pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
750 &doitype, &sittype);
751 if (pair == NULL)
752 return -1;
754 /* check and select a proposal. */
755 ret = get_ph2approval(iph2, pair);
756 free_proppair(pair);
757 if (ret == NULL)
758 return -1;
760 /* make a SA to be replayed. */
761 /* SPI must be updated later. */
762 iph2->sa_ret = get_sabyproppair(doitype, sittype, ret);
763 free_proppair0(ret);
764 if (iph2->sa_ret == NULL)
765 return -1;
767 return 0;
771 * check phase 2 SA payload returned from responder.
772 * This function is called by initiator only.
773 * OUT:
774 * 0: valid.
775 * -1: invalid.
778 ipsecdoi_checkph2proposal(iph2)
779 struct ph2handle *iph2;
781 struct prop_pair **rpair = NULL, **spair = NULL;
782 struct prop_pair *p;
783 int i, n, num;
784 int error = -1;
785 vchar_t *sa_ret = NULL;
786 u_int32_t doitype, sittype;
788 /* get proposal pair of SA sent. */
789 spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
790 &doitype, &sittype);
791 if (spair == NULL) {
792 plog(LLV_ERROR, LOCATION, NULL,
793 "failed to get prop pair.\n");
794 goto end;
797 /* XXX should check the number of transform */
799 /* get proposal pair of SA replayed */
800 rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
801 if (rpair == NULL) {
802 plog(LLV_ERROR, LOCATION, NULL,
803 "failed to get prop pair.\n");
804 goto end;
807 /* check proposal is only one ? */
808 n = 0;
809 num = 0;
810 for (i = 0; i < MAXPROPPAIRLEN; i++) {
811 if (rpair[i]) {
812 n = i;
813 num++;
816 if (num == 0) {
817 plog(LLV_ERROR, LOCATION, NULL,
818 "no proposal received.\n");
819 goto end;
821 if (num != 1) {
822 plog(LLV_ERROR, LOCATION, NULL,
823 "some proposals received.\n");
824 goto end;
827 if (spair[n] == NULL) {
828 plog(LLV_WARNING, LOCATION, NULL,
829 "invalid proposal number:%d received.\n", i);
833 if (rpair[n]->tnext != NULL) {
834 plog(LLV_ERROR, LOCATION, NULL,
835 "multi transforms replyed.\n");
836 goto end;
839 if (cmp_aproppair_i(rpair[n], spair[n])) {
840 plog(LLV_ERROR, LOCATION, NULL,
841 "proposal mismathed.\n");
842 goto end;
846 * check and select a proposal.
847 * ensure that there is no modification of the proposal by
848 * cmp_aproppair_i()
850 p = get_ph2approval(iph2, rpair);
851 if (p == NULL)
852 goto end;
854 /* make a SA to be replayed. */
855 sa_ret = iph2->sa_ret;
856 iph2->sa_ret = get_sabyproppair(doitype, sittype, p);
857 free_proppair0(p);
858 if (iph2->sa_ret == NULL)
859 goto end;
861 error = 0;
863 end:
864 if (rpair)
865 free_proppair(rpair);
866 if (spair)
867 free_proppair(spair);
868 if (sa_ret)
869 vfree(sa_ret);
871 return error;
875 * compare two prop_pair which is assumed to have same proposal number.
876 * the case of bundle or single SA, NOT multi transforms.
877 * a: a proposal that is multi protocols and single transform, usually replyed.
878 * b: a proposal that is multi protocols and multi transform, usually sent.
879 * NOTE: this function is for initiator.
880 * OUT
881 * 0: equal
882 * 1: not equal
883 * XXX cannot understand the comment!
885 static int
886 cmp_aproppair_i(a, b)
887 struct prop_pair *a, *b;
889 struct prop_pair *p, *q, *r;
890 int len;
892 for (p = a, q = b; p && q; p = p->next, q = q->next) {
893 for (r = q; r; r = r->tnext) {
894 /* compare trns */
895 if (p->trns->t_no == r->trns->t_no)
896 break;
898 if (!r) {
899 /* no suitable transform found */
900 plog(LLV_ERROR, LOCATION, NULL,
901 "no suitable transform found.\n");
902 return -1;
905 /* compare prop */
906 if (p->prop->p_no != r->prop->p_no) {
907 plog(LLV_WARNING, LOCATION, NULL,
908 "proposal #%d mismatched, "
909 "expected #%d.\n",
910 r->prop->p_no, p->prop->p_no);
911 /*FALLTHROUGH*/
914 if (p->prop->proto_id != r->prop->proto_id) {
915 plog(LLV_ERROR, LOCATION, NULL,
916 "proto_id mismathed: my:%d peer:%d\n",
917 r->prop->proto_id, p->prop->proto_id);
918 return -1;
921 if (p->prop->spi_size != r->prop->spi_size) {
922 plog(LLV_ERROR, LOCATION, NULL,
923 "invalid spi size: %d.\n",
924 p->prop->spi_size);
925 return -1;
928 /* check #of transforms */
929 if (p->prop->num_t != 1) {
930 plog(LLV_WARNING, LOCATION, NULL,
931 "#of transform is %d, "
932 "but expected 1.\n", p->prop->num_t);
933 /*FALLTHROUGH*/
936 if (p->trns->t_id != r->trns->t_id) {
937 plog(LLV_WARNING, LOCATION, NULL,
938 "transform number has been modified.\n");
939 /*FALLTHROUGH*/
941 if (p->trns->reserved != r->trns->reserved) {
942 plog(LLV_WARNING, LOCATION, NULL,
943 "reserved field should be zero.\n");
944 /*FALLTHROUGH*/
947 /* compare attribute */
948 len = ntohs(r->trns->h.len) - sizeof(*p->trns);
949 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
950 plog(LLV_WARNING, LOCATION, NULL,
951 "attribute has been modified.\n");
952 /*FALLTHROUGH*/
955 if ((p && !q) || (!p && q)) {
956 /* # of protocols mismatched */
957 plog(LLV_ERROR, LOCATION, NULL,
958 "#of protocols mismatched.\n");
959 return -1;
962 return 0;
966 * acceptable check for policy configuration.
967 * return a new SA payload to be reply to peer.
969 static struct prop_pair *
970 get_ph2approval(iph2, pair)
971 struct ph2handle *iph2;
972 struct prop_pair **pair;
974 struct prop_pair *ret;
975 int i;
977 iph2->approval = NULL;
979 plog(LLV_DEBUG, LOCATION, NULL,
980 "begin compare proposals.\n");
982 for (i = 0; i < MAXPROPPAIRLEN; i++) {
983 if (pair[i] == NULL)
984 continue;
985 plog(LLV_DEBUG, LOCATION, NULL,
986 "pair[%d]: %p\n", i, pair[i]);
987 print_proppair(LLV_DEBUG, pair[i]);;
989 /* compare proposal and select one */
990 ret = get_ph2approvalx(iph2, pair[i]);
991 if (ret != NULL) {
992 /* found */
993 return ret;
997 plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
999 return NULL;
1003 * compare my proposal and peers just one proposal.
1004 * set a approval.
1006 static struct prop_pair *
1007 get_ph2approvalx(iph2, pp)
1008 struct ph2handle *iph2;
1009 struct prop_pair *pp;
1011 struct prop_pair *ret = NULL;
1012 struct saprop *pr0, *pr = NULL;
1013 struct saprop *q1, *q2;
1015 pr0 = aproppair2saprop(pp);
1016 if (pr0 == NULL)
1017 return NULL;
1019 for (q1 = pr0; q1; q1 = q1->next) {
1020 for (q2 = iph2->proposal; q2; q2 = q2->next) {
1021 plog(LLV_DEBUG, LOCATION, NULL,
1022 "peer's single bundle:\n");
1023 printsaprop0(LLV_DEBUG, q1);
1024 plog(LLV_DEBUG, LOCATION, NULL,
1025 "my single bundle:\n");
1026 printsaprop0(LLV_DEBUG, q2);
1028 pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1029 if (pr != NULL)
1030 goto found;
1032 plog(LLV_ERROR, LOCATION, NULL,
1033 "not matched\n");
1036 /* no proposal matching */
1037 err:
1038 flushsaprop(pr0);
1039 return NULL;
1041 found:
1042 flushsaprop(pr0);
1043 plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
1044 iph2->approval = pr;
1047 struct saproto *sp;
1048 struct prop_pair *p, *x;
1049 struct prop_pair *n = NULL;
1051 ret = NULL;
1053 for (p = pp; p; p = p->next) {
1055 * find a proposal with matching proto_id.
1056 * we have analyzed validity already, in cmpsaprop_alloc().
1058 for (sp = pr->head; sp; sp = sp->next) {
1059 if (sp->proto_id == p->prop->proto_id)
1060 break;
1062 if (!sp)
1063 goto err;
1064 if (sp->head->next)
1065 goto err; /* XXX */
1067 for (x = p; x; x = x->tnext)
1068 if (sp->head->trns_no == x->trns->t_no)
1069 break;
1070 if (!x)
1071 goto err; /* XXX */
1073 n = racoon_calloc(1, sizeof(struct prop_pair));
1074 if (n == NULL) {
1075 plog(LLV_ERROR, LOCATION, NULL,
1076 "failed to get buffer.\n");
1077 goto err;
1080 n->prop = x->prop;
1081 n->trns = x->trns;
1083 /* need to preserve the order */
1084 for (x = ret; x && x->next; x = x->next)
1086 if (x && x->prop == n->prop) {
1087 for (/*nothing*/; x && x->tnext; x = x->tnext)
1089 x->tnext = n;
1090 } else {
1091 if (x)
1092 x->next = n;
1093 else {
1094 ret = n;
1098 /* #of transforms should be updated ? */
1102 return ret;
1105 void
1106 free_proppair(pair)
1107 struct prop_pair **pair;
1109 int i;
1111 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1112 free_proppair0(pair[i]);
1113 pair[i] = NULL;
1115 racoon_free(pair);
1118 static void
1119 free_proppair0(pair)
1120 struct prop_pair *pair;
1122 struct prop_pair *p, *q, *r, *s;
1124 p = pair;
1125 while (p) {
1126 q = p->next;
1127 r = p;
1128 while (r) {
1129 s = r->tnext;
1130 racoon_free(r);
1131 r = s;
1133 p = q;
1138 * get proposal pairs from SA payload.
1139 * tiny check for proposal payload.
1141 static struct prop_pair **
1142 get_proppair_and_doi_sit(sa, mode, doitype, sittype)
1143 vchar_t *sa;
1144 int mode;
1145 u_int32_t *doitype, *sittype;
1147 struct prop_pair **pair = NULL;
1148 int num_p = 0; /* number of proposal for use */
1149 int tlen;
1150 caddr_t bp;
1151 int i;
1152 struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
1154 plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
1155 plogdump(LLV_DEBUG, sa->v, sa->l);
1157 /* check SA payload size */
1158 if (sa->l < sizeof(*sab)) {
1159 plog(LLV_ERROR, LOCATION, NULL,
1160 "Invalid SA length = %zu.\n", sa->l);
1161 goto bad;
1164 /* check DOI */
1165 if (check_doi(ntohl(sab->doi)) < 0)
1166 goto bad;
1167 if (doitype != NULL)
1168 *doitype = ntohl(sab->doi);
1170 /* check SITUATION */
1171 if (check_situation(ntohl(sab->sit)) < 0)
1172 goto bad;
1173 if (sittype != NULL)
1174 *sittype = ntohl(sab->sit);
1176 pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1177 if (pair == NULL) {
1178 plog(LLV_ERROR, LOCATION, NULL,
1179 "failed to get buffer.\n");
1180 goto bad;
1182 memset(pair, 0, sizeof(pair));
1184 bp = (caddr_t)(sab + 1);
1185 tlen = sa->l - sizeof(*sab);
1188 struct isakmp_pl_p *prop;
1189 int proplen;
1190 vchar_t *pbuf = NULL;
1191 struct isakmp_parse_t *pa;
1193 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1194 if (pbuf == NULL)
1195 goto bad;
1197 for (pa = (struct isakmp_parse_t *)pbuf->v;
1198 pa->type != ISAKMP_NPTYPE_NONE;
1199 pa++) {
1200 /* check the value of next payload */
1201 if (pa->type != ISAKMP_NPTYPE_P) {
1202 plog(LLV_ERROR, LOCATION, NULL,
1203 "Invalid payload type=%u\n", pa->type);
1204 vfree(pbuf);
1205 goto bad;
1208 prop = (struct isakmp_pl_p *)pa->ptr;
1209 proplen = pa->len;
1211 plog(LLV_DEBUG, LOCATION, NULL,
1212 "proposal #%u len=%d\n", prop->p_no, proplen);
1214 if (proplen == 0) {
1215 plog(LLV_ERROR, LOCATION, NULL,
1216 "invalid proposal with length %d\n", proplen);
1217 vfree(pbuf);
1218 goto bad;
1221 /* check Protocol ID */
1222 if (!check_protocol[mode]) {
1223 plog(LLV_ERROR, LOCATION, NULL,
1224 "unsupported mode %d\n", mode);
1225 continue;
1228 if (check_protocol[mode](prop->proto_id) < 0)
1229 continue;
1231 /* check SPI length when IKE. */
1232 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1233 continue;
1235 /* get transform */
1236 if (get_transform(prop, pair, &num_p) < 0) {
1237 vfree(pbuf);
1238 goto bad;
1241 vfree(pbuf);
1242 pbuf = NULL;
1246 int notrans, nprop;
1247 struct prop_pair *p, *q;
1249 /* check for proposals with no transforms */
1250 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1251 if (!pair[i])
1252 continue;
1254 plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
1255 print_proppair(LLV_DEBUG, pair[i]);
1257 notrans = nprop = 0;
1258 for (p = pair[i]; p; p = p->next) {
1259 if (p->trns == NULL) {
1260 notrans++;
1261 break;
1263 for (q = p; q; q = q->tnext)
1264 nprop++;
1267 #if 0
1269 * XXX at this moment, we cannot accept proposal group
1270 * with multiple proposals. this should be fixed.
1272 if (pair[i]->next) {
1273 plog(LLV_WARNING, LOCATION, NULL,
1274 "proposal #%u ignored "
1275 "(multiple proposal not supported)\n",
1276 pair[i]->prop->p_no);
1277 notrans++;
1279 #endif
1281 if (notrans) {
1282 for (p = pair[i]; p; p = q) {
1283 q = p->next;
1284 racoon_free(p);
1286 pair[i] = NULL;
1287 num_p--;
1288 } else {
1289 plog(LLV_DEBUG, LOCATION, NULL,
1290 "proposal #%u: %d transform\n",
1291 pair[i]->prop->p_no, nprop);
1296 /* bark if no proposal is found. */
1297 if (num_p <= 0) {
1298 plog(LLV_ERROR, LOCATION, NULL,
1299 "no Proposal found.\n");
1300 goto bad;
1303 return pair;
1304 bad:
1305 if (pair != NULL)
1306 racoon_free(pair);
1307 return NULL;
1310 struct prop_pair **
1311 get_proppair(sa, mode)
1312 vchar_t *sa;
1313 int mode;
1315 return get_proppair_and_doi_sit(sa, mode, NULL, NULL);
1320 * check transform payload.
1321 * OUT:
1322 * positive: return the pointer to the payload of valid transform.
1323 * 0 : No valid transform found.
1325 static int
1326 get_transform(prop, pair, num_p)
1327 struct isakmp_pl_p *prop;
1328 struct prop_pair **pair;
1329 int *num_p;
1331 int tlen; /* total length of all transform in a proposal */
1332 caddr_t bp;
1333 struct isakmp_pl_t *trns;
1334 int trnslen;
1335 vchar_t *pbuf = NULL;
1336 struct isakmp_parse_t *pa;
1337 struct prop_pair *p = NULL, *q;
1338 int num_t;
1340 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1341 tlen = ntohs(prop->h.len)
1342 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1343 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1344 if (pbuf == NULL)
1345 return -1;
1347 /* check and get transform for use */
1348 num_t = 0;
1349 for (pa = (struct isakmp_parse_t *)pbuf->v;
1350 pa->type != ISAKMP_NPTYPE_NONE;
1351 pa++) {
1353 num_t++;
1355 /* check the value of next payload */
1356 if (pa->type != ISAKMP_NPTYPE_T) {
1357 plog(LLV_ERROR, LOCATION, NULL,
1358 "Invalid payload type=%u\n", pa->type);
1359 break;
1362 trns = (struct isakmp_pl_t *)pa->ptr;
1363 trnslen = pa->len;
1365 plog(LLV_DEBUG, LOCATION, NULL,
1366 "transform #%u len=%u\n", trns->t_no, trnslen);
1368 /* check transform ID */
1369 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1370 plog(LLV_WARNING, LOCATION, NULL,
1371 "unsupported proto_id %u\n",
1372 prop->proto_id);
1373 continue;
1375 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1376 plog(LLV_WARNING, LOCATION, NULL,
1377 "unsupported proto_id %u\n",
1378 prop->proto_id);
1379 continue;
1382 if (!check_transform[prop->proto_id]
1383 || !check_attributes[prop->proto_id]) {
1384 plog(LLV_WARNING, LOCATION, NULL,
1385 "unsupported proto_id %u\n",
1386 prop->proto_id);
1387 continue;
1389 if (check_transform[prop->proto_id](trns->t_id) < 0)
1390 continue;
1392 /* check data attributes */
1393 if (check_attributes[prop->proto_id](trns) != 0)
1394 continue;
1396 p = racoon_calloc(1, sizeof(*p));
1397 if (p == NULL) {
1398 plog(LLV_ERROR, LOCATION, NULL,
1399 "failed to get buffer.\n");
1400 vfree(pbuf);
1401 return -1;
1403 p->prop = prop;
1404 p->trns = trns;
1406 /* need to preserve the order */
1407 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1409 if (q && q->prop == p->prop) {
1410 for (/*nothing*/; q && q->tnext; q = q->tnext)
1412 q->tnext = p;
1413 } else {
1414 if (q)
1415 q->next = p;
1416 else {
1417 pair[prop->p_no] = p;
1418 (*num_p)++;
1423 vfree(pbuf);
1425 return 0;
1429 * make a new SA payload from prop_pair.
1430 * NOTE: this function make spi value clear.
1432 vchar_t *
1433 get_sabyproppair(doitype, sittype, pair)
1434 u_int32_t doitype, sittype;
1435 struct prop_pair *pair;
1437 vchar_t *newsa;
1438 int newtlen;
1439 u_int8_t *np_p = NULL;
1440 struct prop_pair *p;
1441 int prophlen, trnslen;
1442 caddr_t bp;
1444 newtlen = sizeof(struct ipsecdoi_sa_b);
1445 for (p = pair; p; p = p->next) {
1446 newtlen += sizeof(struct isakmp_pl_p);
1447 newtlen += p->prop->spi_size;
1448 newtlen += ntohs(p->trns->h.len);
1451 newsa = vmalloc(newtlen);
1452 if (newsa == NULL) {
1453 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1454 return NULL;
1456 bp = newsa->v;
1458 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1460 /* update some of values in SA header */
1461 ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype);
1462 ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype);
1463 bp += sizeof(struct ipsecdoi_sa_b);
1465 /* create proposal payloads */
1466 for (p = pair; p; p = p->next) {
1467 prophlen = sizeof(struct isakmp_pl_p)
1468 + p->prop->spi_size;
1469 trnslen = ntohs(p->trns->h.len);
1471 if (np_p)
1472 *np_p = ISAKMP_NPTYPE_P;
1474 /* create proposal */
1476 memcpy(bp, p->prop, prophlen);
1477 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1478 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1479 ((struct isakmp_pl_p *)bp)->num_t = 1;
1480 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1481 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1482 bp += prophlen;
1484 /* create transform */
1485 memcpy(bp, p->trns, trnslen);
1486 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1487 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1488 bp += trnslen;
1491 return newsa;
1495 * update responder's spi
1498 ipsecdoi_updatespi(iph2)
1499 struct ph2handle *iph2;
1501 struct prop_pair **pair, *p;
1502 struct saprop *pp;
1503 struct saproto *pr;
1504 int i;
1505 int error = -1;
1506 u_int8_t *spi;
1508 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1509 if (pair == NULL)
1510 return -1;
1511 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1512 if (pair[i])
1513 break;
1515 if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1516 /* multiple transform must be filtered by selectph2proposal.*/
1517 goto end;
1520 pp = iph2->approval;
1522 /* create proposal payloads */
1523 for (p = pair[i]; p; p = p->next) {
1525 * find a proposal/transform with matching proto_id/t_id.
1526 * we have analyzed validity already, in cmpsaprop_alloc().
1528 for (pr = pp->head; pr; pr = pr->next) {
1529 if (p->prop->proto_id == pr->proto_id &&
1530 p->trns->t_id == pr->head->trns_id) {
1531 break;
1534 if (!pr)
1535 goto end;
1538 * XXX SPI bits are left-filled, for use with IPComp.
1539 * we should be switching to variable-length spi field...
1541 spi = (u_int8_t *)&pr->spi;
1542 spi += sizeof(pr->spi);
1543 spi -= pr->spisize;
1544 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1547 error = 0;
1548 end:
1549 free_proppair(pair);
1550 return error;
1554 * make a new SA payload from prop_pair.
1556 vchar_t *
1557 get_sabysaprop(pp0, sa0)
1558 struct saprop *pp0;
1559 vchar_t *sa0;
1561 struct prop_pair **pair = NULL;
1562 vchar_t *newsa = NULL;
1563 int newtlen;
1564 u_int8_t *np_p = NULL;
1565 struct prop_pair *p = NULL;
1566 struct saprop *pp;
1567 struct saproto *pr;
1568 struct satrns *tr;
1569 int prophlen, trnslen;
1570 caddr_t bp;
1571 int error = -1;
1573 /* get proposal pair */
1574 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1575 if (pair == NULL)
1576 goto out;
1578 newtlen = sizeof(struct ipsecdoi_sa_b);
1579 for (pp = pp0; pp; pp = pp->next) {
1581 if (pair[pp->prop_no] == NULL)
1582 goto out;
1584 for (pr = pp->head; pr; pr = pr->next) {
1585 newtlen += (sizeof(struct isakmp_pl_p)
1586 + pr->spisize);
1588 for (tr = pr->head; tr; tr = tr->next) {
1589 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1590 if (tr->trns_no == p->trns->t_no)
1591 break;
1593 if (p == NULL)
1594 goto out;
1596 newtlen += ntohs(p->trns->h.len);
1601 newsa = vmalloc(newtlen);
1602 if (newsa == NULL) {
1603 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1604 goto out;
1606 bp = newsa->v;
1608 /* some of values of SA must be updated in the out of this function */
1609 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1610 bp += sizeof(struct ipsecdoi_sa_b);
1612 /* create proposal payloads */
1613 for (pp = pp0; pp; pp = pp->next) {
1615 for (pr = pp->head; pr; pr = pr->next) {
1616 prophlen = sizeof(struct isakmp_pl_p)
1617 + p->prop->spi_size;
1619 for (tr = pr->head; tr; tr = tr->next) {
1620 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1621 if (tr->trns_no == p->trns->t_no)
1622 break;
1624 if (p == NULL)
1625 goto out;
1627 trnslen = ntohs(p->trns->h.len);
1629 if (np_p)
1630 *np_p = ISAKMP_NPTYPE_P;
1632 /* create proposal */
1634 memcpy(bp, p->prop, prophlen);
1635 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1636 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1637 ((struct isakmp_pl_p *)bp)->num_t = 1;
1638 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1639 bp += prophlen;
1641 /* create transform */
1642 memcpy(bp, p->trns, trnslen);
1643 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1644 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1645 bp += trnslen;
1650 error = 0;
1651 out:
1652 if (pair != NULL)
1653 racoon_free(pair);
1655 if (error != 0) {
1656 if (newsa != NULL) {
1657 vfree(newsa);
1658 newsa = NULL;
1662 return newsa;
1666 * If some error happens then return 0. Although 0 means that lifetime is zero,
1667 * such a value should not be accepted.
1668 * Also 0 of lifebyte should not be included in a packet although 0 means not
1669 * to care of it.
1671 static u_int32_t
1672 ipsecdoi_set_ld(buf)
1673 vchar_t *buf;
1675 u_int32_t ld;
1677 if (buf == 0)
1678 return 0;
1680 switch (buf->l) {
1681 case 2:
1682 ld = ntohs(*(u_int16_t *)buf->v);
1683 break;
1684 case 4:
1685 ld = ntohl(*(u_int32_t *)buf->v);
1686 break;
1687 default:
1688 plog(LLV_ERROR, LOCATION, NULL,
1689 "length %zu of life duration "
1690 "isn't supported.\n", buf->l);
1691 return 0;
1694 return ld;
1698 * parse responder-lifetime attributes from payload
1701 ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb)
1702 struct isakmp_pl_n *notify;
1703 u_int32_t *lifetime_sec;
1704 u_int32_t *lifetime_kb;
1706 struct isakmp_data *d;
1707 int flag, type, tlen, ld_type = -1;
1708 u_int16_t lorv;
1709 u_int32_t value;
1711 tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
1712 d = (struct isakmp_data *)((char *)(notify + 1) +
1713 notify->spi_size);
1715 while (tlen >= sizeof(struct isakmp_data)) {
1716 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
1717 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
1718 lorv = ntohs(d->lorv);
1720 plog(LLV_DEBUG, LOCATION, NULL,
1721 "type=%s, flag=0x%04x, lorv=%s\n",
1722 s_ipsecdoi_attr(type), flag,
1723 s_ipsecdoi_attr_v(type, lorv));
1725 switch (type) {
1726 case IPSECDOI_ATTR_SA_LD_TYPE:
1727 if (! flag) {
1728 plog(LLV_ERROR, LOCATION, NULL,
1729 "must be TV when LD_TYPE.\n");
1730 return -1;
1732 ld_type = lorv;
1733 break;
1734 case IPSECDOI_ATTR_SA_LD:
1735 if (flag)
1736 value = lorv;
1737 else if (lorv == 2)
1738 value = ntohs(*(u_int16_t *)(d + 1));
1739 else if (lorv == 4)
1740 value = ntohl(*(u_int32_t *)(d + 1));
1741 else {
1742 plog(LLV_ERROR, LOCATION, NULL,
1743 "payload length %d for lifetime "
1744 "data length is unsupported.\n", lorv);
1745 return -1;
1748 switch (ld_type) {
1749 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
1750 if (lifetime_sec != NULL)
1751 *lifetime_sec = value;
1752 plog(LLV_INFO, LOCATION, NULL,
1753 "received RESPONDER-LIFETIME: %d "
1754 "seconds\n", value);
1755 break;
1756 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
1757 if (lifetime_kb != NULL)
1758 *lifetime_kb = value;
1759 plog(LLV_INFO, LOCATION, NULL,
1760 "received RESPONDER-LIFETIME: %d "
1761 "kbytes\n", value);
1762 break;
1763 default:
1764 plog(LLV_ERROR, LOCATION, NULL,
1765 "lifetime data received without "
1766 "lifetime data type.\n");
1767 return -1;
1769 break;
1772 if (flag) {
1773 tlen -= sizeof(*d);
1774 d = (struct isakmp_data *)((char *)d
1775 + sizeof(*d));
1776 } else {
1777 tlen -= (sizeof(*d) + lorv);
1778 d = (struct isakmp_data *)((char *)d
1779 + sizeof(*d) + lorv);
1783 return 0;
1787 /*%%%*/
1789 * check DOI
1791 static int
1792 check_doi(doi)
1793 u_int32_t doi;
1795 switch (doi) {
1796 case IPSEC_DOI:
1797 return 0;
1798 default:
1799 plog(LLV_ERROR, LOCATION, NULL,
1800 "invalid value of DOI 0x%08x.\n", doi);
1801 return -1;
1803 /* NOT REACHED */
1807 * check situation
1809 static int
1810 check_situation(sit)
1811 u_int32_t sit;
1813 switch (sit) {
1814 case IPSECDOI_SIT_IDENTITY_ONLY:
1815 return 0;
1817 case IPSECDOI_SIT_SECRECY:
1818 case IPSECDOI_SIT_INTEGRITY:
1819 plog(LLV_ERROR, LOCATION, NULL,
1820 "situation 0x%08x unsupported yet.\n", sit);
1821 return -1;
1823 default:
1824 plog(LLV_ERROR, LOCATION, NULL,
1825 "invalid situation 0x%08x.\n", sit);
1826 return -1;
1828 /* NOT REACHED */
1832 * check protocol id in main mode
1834 static int
1835 check_prot_main(proto_id)
1836 int proto_id;
1838 switch (proto_id) {
1839 case IPSECDOI_PROTO_ISAKMP:
1840 return 0;
1842 default:
1843 plog(LLV_ERROR, LOCATION, NULL,
1844 "Illegal protocol id=%u.\n", proto_id);
1845 return -1;
1847 /* NOT REACHED */
1851 * check protocol id in quick mode
1853 static int
1854 check_prot_quick(proto_id)
1855 int proto_id;
1857 switch (proto_id) {
1858 case IPSECDOI_PROTO_IPSEC_AH:
1859 case IPSECDOI_PROTO_IPSEC_ESP:
1860 return 0;
1862 case IPSECDOI_PROTO_IPCOMP:
1863 return 0;
1865 default:
1866 plog(LLV_ERROR, LOCATION, NULL,
1867 "invalid protocol id %d.\n", proto_id);
1868 return -1;
1870 /* NOT REACHED */
1873 static int
1874 check_spi_size(proto_id, size)
1875 int proto_id, size;
1877 switch (proto_id) {
1878 case IPSECDOI_PROTO_ISAKMP:
1879 if (size != 0) {
1880 /* WARNING */
1881 plog(LLV_WARNING, LOCATION, NULL,
1882 "SPI size isn't zero, but IKE proposal.\n");
1884 return 0;
1886 case IPSECDOI_PROTO_IPSEC_AH:
1887 case IPSECDOI_PROTO_IPSEC_ESP:
1888 if (size != 4) {
1889 plog(LLV_ERROR, LOCATION, NULL,
1890 "invalid SPI size=%d for IPSEC proposal.\n",
1891 size);
1892 return -1;
1894 return 0;
1896 case IPSECDOI_PROTO_IPCOMP:
1897 if (size != 2 && size != 4) {
1898 plog(LLV_ERROR, LOCATION, NULL,
1899 "invalid SPI size=%d for IPCOMP proposal.\n",
1900 size);
1901 return -1;
1903 return 0;
1905 default:
1906 /* ??? */
1907 return -1;
1909 /* NOT REACHED */
1913 * check transform ID in ISAKMP.
1915 static int
1916 check_trns_isakmp(t_id)
1917 int t_id;
1919 switch (t_id) {
1920 case IPSECDOI_KEY_IKE:
1921 return 0;
1922 default:
1923 plog(LLV_ERROR, LOCATION, NULL,
1924 "invalid transform-id=%u in proto_id=%u.\n",
1925 t_id, IPSECDOI_KEY_IKE);
1926 return -1;
1928 /* NOT REACHED */
1932 * check transform ID in AH.
1934 static int
1935 check_trns_ah(t_id)
1936 int t_id;
1938 switch (t_id) {
1939 case IPSECDOI_AH_MD5:
1940 case IPSECDOI_AH_SHA:
1941 case IPSECDOI_AH_SHA256:
1942 case IPSECDOI_AH_SHA384:
1943 case IPSECDOI_AH_SHA512:
1944 return 0;
1945 case IPSECDOI_AH_DES:
1946 plog(LLV_ERROR, LOCATION, NULL,
1947 "not support transform-id=%u in AH.\n", t_id);
1948 return -1;
1949 default:
1950 plog(LLV_ERROR, LOCATION, NULL,
1951 "invalid transform-id=%u in AH.\n", t_id);
1952 return -1;
1954 /* NOT REACHED */
1958 * check transform ID in ESP.
1960 static int
1961 check_trns_esp(t_id)
1962 int t_id;
1964 switch (t_id) {
1965 case IPSECDOI_ESP_DES:
1966 case IPSECDOI_ESP_3DES:
1967 case IPSECDOI_ESP_NULL:
1968 case IPSECDOI_ESP_RC5:
1969 case IPSECDOI_ESP_CAST:
1970 case IPSECDOI_ESP_BLOWFISH:
1971 case IPSECDOI_ESP_AES:
1972 case IPSECDOI_ESP_TWOFISH:
1973 case IPSECDOI_ESP_CAMELLIA:
1974 return 0;
1975 case IPSECDOI_ESP_DES_IV32:
1976 case IPSECDOI_ESP_DES_IV64:
1977 case IPSECDOI_ESP_IDEA:
1978 case IPSECDOI_ESP_3IDEA:
1979 case IPSECDOI_ESP_RC4:
1980 plog(LLV_ERROR, LOCATION, NULL,
1981 "not support transform-id=%u in ESP.\n", t_id);
1982 return -1;
1983 default:
1984 plog(LLV_ERROR, LOCATION, NULL,
1985 "invalid transform-id=%u in ESP.\n", t_id);
1986 return -1;
1988 /* NOT REACHED */
1992 * check transform ID in IPCOMP.
1994 static int
1995 check_trns_ipcomp(t_id)
1996 int t_id;
1998 switch (t_id) {
1999 case IPSECDOI_IPCOMP_OUI:
2000 case IPSECDOI_IPCOMP_DEFLATE:
2001 case IPSECDOI_IPCOMP_LZS:
2002 return 0;
2003 default:
2004 plog(LLV_ERROR, LOCATION, NULL,
2005 "invalid transform-id=%u in IPCOMP.\n", t_id);
2006 return -1;
2008 /* NOT REACHED */
2012 * check data attributes in IKE.
2014 static int
2015 check_attr_isakmp(trns)
2016 struct isakmp_pl_t *trns;
2018 struct isakmp_data *d;
2019 int tlen;
2020 int flag, type;
2021 u_int16_t lorv;
2023 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2024 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2026 while (tlen > 0) {
2027 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2028 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2029 lorv = ntohs(d->lorv);
2031 plog(LLV_DEBUG, LOCATION, NULL,
2032 "type=%s, flag=0x%04x, lorv=%s\n",
2033 s_oakley_attr(type), flag,
2034 s_oakley_attr_v(type, lorv));
2037 * some of the attributes must be encoded in TV.
2038 * see RFC2409 Appendix A "Attribute Classes".
2040 switch (type) {
2041 case OAKLEY_ATTR_ENC_ALG:
2042 case OAKLEY_ATTR_HASH_ALG:
2043 case OAKLEY_ATTR_AUTH_METHOD:
2044 case OAKLEY_ATTR_GRP_DESC:
2045 case OAKLEY_ATTR_GRP_TYPE:
2046 case OAKLEY_ATTR_SA_LD_TYPE:
2047 case OAKLEY_ATTR_PRF:
2048 case OAKLEY_ATTR_KEY_LEN:
2049 case OAKLEY_ATTR_FIELD_SIZE:
2050 if (!flag) { /* TLV*/
2051 plog(LLV_ERROR, LOCATION, NULL,
2052 "oakley attribute %d must be TV.\n",
2053 type);
2054 return -1;
2056 break;
2059 /* sanity check for TLV. length must be specified. */
2060 if (!flag && lorv == 0) { /*TLV*/
2061 plog(LLV_ERROR, LOCATION, NULL,
2062 "invalid length %d for TLV attribute %d.\n",
2063 lorv, type);
2064 return -1;
2067 switch (type) {
2068 case OAKLEY_ATTR_ENC_ALG:
2069 if (!alg_oakley_encdef_ok(lorv)) {
2070 plog(LLV_ERROR, LOCATION, NULL,
2071 "invalied encryption algorithm=%d.\n",
2072 lorv);
2073 return -1;
2075 break;
2077 case OAKLEY_ATTR_HASH_ALG:
2078 if (!alg_oakley_hashdef_ok(lorv)) {
2079 plog(LLV_ERROR, LOCATION, NULL,
2080 "invalied hash algorithm=%d.\n",
2081 lorv);
2082 return -1;
2084 break;
2086 case OAKLEY_ATTR_AUTH_METHOD:
2087 switch (lorv) {
2088 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2089 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2090 #ifdef ENABLE_HYBRID
2091 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2092 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2093 #endif
2094 #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
2095 /* These two authentication method IDs overlap. */
2096 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2097 /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
2098 #endif
2099 break;
2100 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2101 #ifdef ENABLE_HYBRID
2102 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2103 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2104 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2105 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2106 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
2107 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2108 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2109 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2110 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2111 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2112 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
2113 #endif
2114 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2115 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2116 plog(LLV_ERROR, LOCATION, NULL,
2117 "auth method %s isn't supported.\n",
2118 s_oakley_attr_method(lorv));
2119 return -1;
2120 default:
2121 plog(LLV_ERROR, LOCATION, NULL,
2122 "invalid auth method %d.\n",
2123 lorv);
2124 return -1;
2126 break;
2128 case OAKLEY_ATTR_GRP_DESC:
2129 if (!alg_oakley_dhdef_ok(lorv)) {
2130 plog(LLV_ERROR, LOCATION, NULL,
2131 "invalid DH group %d.\n",
2132 lorv);
2133 return -1;
2135 break;
2137 case OAKLEY_ATTR_GRP_TYPE:
2138 switch (lorv) {
2139 case OAKLEY_ATTR_GRP_TYPE_MODP:
2140 break;
2141 default:
2142 plog(LLV_ERROR, LOCATION, NULL,
2143 "unsupported DH group type %d.\n",
2144 lorv);
2145 return -1;
2147 break;
2149 case OAKLEY_ATTR_GRP_PI:
2150 case OAKLEY_ATTR_GRP_GEN_ONE:
2151 /* sanity checks? */
2152 break;
2154 case OAKLEY_ATTR_GRP_GEN_TWO:
2155 case OAKLEY_ATTR_GRP_CURVE_A:
2156 case OAKLEY_ATTR_GRP_CURVE_B:
2157 plog(LLV_ERROR, LOCATION, NULL,
2158 "attr type=%u isn't supported.\n", type);
2159 return -1;
2161 case OAKLEY_ATTR_SA_LD_TYPE:
2162 switch (lorv) {
2163 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2164 case OAKLEY_ATTR_SA_LD_TYPE_KB:
2165 break;
2166 default:
2167 plog(LLV_ERROR, LOCATION, NULL,
2168 "invalid life type %d.\n", lorv);
2169 return -1;
2171 break;
2173 case OAKLEY_ATTR_SA_LD:
2174 /* should check the value */
2175 break;
2177 case OAKLEY_ATTR_PRF:
2178 case OAKLEY_ATTR_KEY_LEN:
2179 break;
2181 case OAKLEY_ATTR_FIELD_SIZE:
2182 plog(LLV_ERROR, LOCATION, NULL,
2183 "attr type=%u isn't supported.\n", type);
2184 return -1;
2186 case OAKLEY_ATTR_GRP_ORDER:
2187 break;
2189 case OAKLEY_ATTR_GSS_ID:
2190 break;
2192 default:
2193 plog(LLV_ERROR, LOCATION, NULL,
2194 "invalid attribute type %d.\n", type);
2195 return -1;
2198 if (flag) {
2199 tlen -= sizeof(*d);
2200 d = (struct isakmp_data *)((char *)d
2201 + sizeof(*d));
2202 } else {
2203 tlen -= (sizeof(*d) + lorv);
2204 d = (struct isakmp_data *)((char *)d
2205 + sizeof(*d) + lorv);
2209 return 0;
2213 * check data attributes in IPSEC AH/ESP.
2215 static int
2216 check_attr_ah(trns)
2217 struct isakmp_pl_t *trns;
2219 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2222 static int
2223 check_attr_esp(trns)
2224 struct isakmp_pl_t *trns;
2226 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2229 static int
2230 check_attr_ipsec(proto_id, trns)
2231 int proto_id;
2232 struct isakmp_pl_t *trns;
2234 struct isakmp_data *d;
2235 int tlen;
2236 int flag, type = 0;
2237 u_int16_t lorv;
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));
2244 while (tlen > 0) {
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=%s, flag=0x%04x, lorv=%s\n",
2251 s_ipsecdoi_attr(type), flag,
2252 s_ipsecdoi_attr_v(type, lorv));
2254 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2255 attrseen[type]++;
2257 switch (type) {
2258 case IPSECDOI_ATTR_ENC_MODE:
2259 if (! flag) {
2260 plog(LLV_ERROR, LOCATION, NULL,
2261 "must be TV when ENC_MODE.\n");
2262 return -1;
2265 switch (lorv) {
2266 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2267 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2268 break;
2269 #ifdef ENABLE_NATT
2270 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2271 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2272 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2273 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2274 plog(LLV_DEBUG, LOCATION, NULL,
2275 "UDP encapsulation requested\n");
2276 break;
2277 #endif
2278 default:
2279 plog(LLV_ERROR, LOCATION, NULL,
2280 "invalid encryption mode=%u.\n",
2281 lorv);
2282 return -1;
2284 break;
2286 case IPSECDOI_ATTR_AUTH:
2287 if (! flag) {
2288 plog(LLV_ERROR, LOCATION, NULL,
2289 "must be TV when AUTH.\n");
2290 return -1;
2293 switch (lorv) {
2294 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2295 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2296 trns->t_id != IPSECDOI_AH_MD5) {
2297 ahmismatch:
2298 plog(LLV_ERROR, LOCATION, NULL,
2299 "auth algorithm %u conflicts "
2300 "with transform %u.\n",
2301 lorv, trns->t_id);
2302 return -1;
2304 break;
2305 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2306 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2307 if (trns->t_id != IPSECDOI_AH_SHA)
2308 goto ahmismatch;
2310 break;
2311 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2312 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2313 if (trns->t_id != IPSECDOI_AH_SHA256)
2314 goto ahmismatch;
2316 break;
2317 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2318 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2319 if (trns->t_id != IPSECDOI_AH_SHA384)
2320 goto ahmismatch;
2322 break;
2323 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2324 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2325 if (trns->t_id != IPSECDOI_AH_SHA512)
2326 goto ahmismatch;
2328 break;
2329 case IPSECDOI_ATTR_AUTH_DES_MAC:
2330 case IPSECDOI_ATTR_AUTH_KPDK:
2331 plog(LLV_ERROR, LOCATION, NULL,
2332 "auth algorithm %u isn't supported.\n",
2333 lorv);
2334 return -1;
2335 default:
2336 plog(LLV_ERROR, LOCATION, NULL,
2337 "invalid auth algorithm=%u.\n",
2338 lorv);
2339 return -1;
2341 break;
2343 case IPSECDOI_ATTR_SA_LD_TYPE:
2344 if (! flag) {
2345 plog(LLV_ERROR, LOCATION, NULL,
2346 "must be TV when LD_TYPE.\n");
2347 return -1;
2350 switch (lorv) {
2351 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2352 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2353 break;
2354 default:
2355 plog(LLV_ERROR, LOCATION, NULL,
2356 "invalid life type %d.\n", lorv);
2357 return -1;
2359 break;
2361 case IPSECDOI_ATTR_SA_LD:
2362 if (flag) {
2363 /* i.e. ISAKMP_GEN_TV */
2364 plog(LLV_DEBUG, LOCATION, NULL,
2365 "life duration was in TLV.\n");
2366 } else {
2367 /* i.e. ISAKMP_GEN_TLV */
2368 if (lorv == 0) {
2369 plog(LLV_ERROR, LOCATION, NULL,
2370 "invalid length of LD\n");
2371 return -1;
2374 break;
2376 case IPSECDOI_ATTR_GRP_DESC:
2377 if (! flag) {
2378 plog(LLV_ERROR, LOCATION, NULL,
2379 "must be TV when GRP_DESC.\n");
2380 return -1;
2383 if (!alg_oakley_dhdef_ok(lorv)) {
2384 plog(LLV_ERROR, LOCATION, NULL,
2385 "invalid group description=%u.\n",
2386 lorv);
2387 return -1;
2389 break;
2391 case IPSECDOI_ATTR_KEY_LENGTH:
2392 if (! flag) {
2393 plog(LLV_ERROR, LOCATION, NULL,
2394 "must be TV when KEY_LENGTH.\n");
2395 return -1;
2397 break;
2399 #ifdef HAVE_SECCTX
2400 case IPSECDOI_ATTR_SECCTX:
2401 if (flag) {
2402 plog(LLV_ERROR, LOCATION, NULL,
2403 "SECCTX must be in TLV.\n");
2404 return -1;
2406 break;
2407 #endif
2409 case IPSECDOI_ATTR_KEY_ROUNDS:
2410 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2411 case IPSECDOI_ATTR_COMP_PRIVALG:
2412 plog(LLV_ERROR, LOCATION, NULL,
2413 "attr type=%u isn't supported.\n", type);
2414 return -1;
2416 default:
2417 plog(LLV_ERROR, LOCATION, NULL,
2418 "invalid attribute type %d.\n", type);
2419 return -1;
2422 if (flag) {
2423 tlen -= sizeof(*d);
2424 d = (struct isakmp_data *)((char *)d
2425 + sizeof(*d));
2426 } else {
2427 tlen -= (sizeof(*d) + lorv);
2428 d = (struct isakmp_data *)((caddr_t)d
2429 + sizeof(*d) + lorv);
2433 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2434 !attrseen[IPSECDOI_ATTR_AUTH]) {
2435 plog(LLV_ERROR, LOCATION, NULL,
2436 "attr AUTH must be present for AH.\n");
2437 return -1;
2440 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2441 trns->t_id == IPSECDOI_ESP_NULL &&
2442 !attrseen[IPSECDOI_ATTR_AUTH]) {
2443 plog(LLV_ERROR, LOCATION, NULL,
2444 "attr AUTH must be present for ESP NULL encryption.\n");
2445 return -1;
2448 return 0;
2451 static int
2452 check_attr_ipcomp(trns)
2453 struct isakmp_pl_t *trns;
2455 struct isakmp_data *d;
2456 int tlen;
2457 int flag, type = 0;
2458 u_int16_t lorv;
2459 int attrseen[16]; /* XXX magic number */
2461 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2462 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2463 memset(attrseen, 0, sizeof(attrseen));
2465 while (tlen > 0) {
2466 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2467 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2468 lorv = ntohs(d->lorv);
2470 plog(LLV_DEBUG, LOCATION, NULL,
2471 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2472 type, flag, lorv);
2474 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2475 attrseen[type]++;
2477 switch (type) {
2478 case IPSECDOI_ATTR_ENC_MODE:
2479 if (! flag) {
2480 plog(LLV_ERROR, LOCATION, NULL,
2481 "must be TV when ENC_MODE.\n");
2482 return -1;
2485 switch (lorv) {
2486 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2487 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2488 break;
2489 #ifdef ENABLE_NATT
2490 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2491 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2492 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2493 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2494 plog(LLV_DEBUG, LOCATION, NULL,
2495 "UDP encapsulation requested\n");
2496 break;
2497 #endif
2498 default:
2499 plog(LLV_ERROR, LOCATION, NULL,
2500 "invalid encryption mode=%u.\n",
2501 lorv);
2502 return -1;
2504 break;
2506 case IPSECDOI_ATTR_SA_LD_TYPE:
2507 if (! flag) {
2508 plog(LLV_ERROR, LOCATION, NULL,
2509 "must be TV when LD_TYPE.\n");
2510 return -1;
2513 switch (lorv) {
2514 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2515 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2516 break;
2517 default:
2518 plog(LLV_ERROR, LOCATION, NULL,
2519 "invalid life type %d.\n", lorv);
2520 return -1;
2522 break;
2524 case IPSECDOI_ATTR_SA_LD:
2525 if (flag) {
2526 /* i.e. ISAKMP_GEN_TV */
2527 plog(LLV_DEBUG, LOCATION, NULL,
2528 "life duration was in TLV.\n");
2529 } else {
2530 /* i.e. ISAKMP_GEN_TLV */
2531 if (lorv == 0) {
2532 plog(LLV_ERROR, LOCATION, NULL,
2533 "invalid length of LD\n");
2534 return -1;
2537 break;
2539 case IPSECDOI_ATTR_GRP_DESC:
2540 if (! flag) {
2541 plog(LLV_ERROR, LOCATION, NULL,
2542 "must be TV when GRP_DESC.\n");
2543 return -1;
2546 if (!alg_oakley_dhdef_ok(lorv)) {
2547 plog(LLV_ERROR, LOCATION, NULL,
2548 "invalid group description=%u.\n",
2549 lorv);
2550 return -1;
2552 break;
2554 case IPSECDOI_ATTR_AUTH:
2555 plog(LLV_ERROR, LOCATION, NULL,
2556 "invalid attr type=%u.\n", type);
2557 return -1;
2559 case IPSECDOI_ATTR_KEY_LENGTH:
2560 case IPSECDOI_ATTR_KEY_ROUNDS:
2561 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2562 case IPSECDOI_ATTR_COMP_PRIVALG:
2563 plog(LLV_ERROR, LOCATION, NULL,
2564 "attr type=%u isn't supported.\n", type);
2565 return -1;
2567 default:
2568 plog(LLV_ERROR, LOCATION, NULL,
2569 "invalid attribute type %d.\n", type);
2570 return -1;
2573 if (flag) {
2574 tlen -= sizeof(*d);
2575 d = (struct isakmp_data *)((char *)d
2576 + sizeof(*d));
2577 } else {
2578 tlen -= (sizeof(*d) + lorv);
2579 d = (struct isakmp_data *)((caddr_t)d
2580 + sizeof(*d) + lorv);
2584 #if 0
2585 if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2586 !attrseen[IPSECDOI_ATTR_AUTH]) {
2587 plog(LLV_ERROR, LOCATION, NULL,
2588 "attr AUTH must be present for AH.\n", type);
2589 return -1;
2591 #endif
2593 return 0;
2596 /* %%% */
2598 * create phase1 proposal from remote configuration.
2599 * NOT INCLUDING isakmp general header of SA payload
2601 vchar_t *
2602 ipsecdoi_setph1proposal(rmconf, props)
2603 struct remoteconf *rmconf;
2604 struct isakmpsa *props;
2606 vchar_t *mysa;
2607 int sablen;
2609 /* count total size of SA minus isakmp general header */
2610 /* not including isakmp general header of SA payload */
2611 sablen = sizeof(struct ipsecdoi_sa_b);
2612 sablen += setph1prop(props, NULL);
2614 mysa = vmalloc(sablen);
2615 if (mysa == NULL) {
2616 plog(LLV_ERROR, LOCATION, NULL,
2617 "failed to allocate my sa buffer\n");
2618 return NULL;
2621 /* create SA payload */
2622 /* not including isakmp general header */
2623 ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
2624 ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
2626 (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2628 return mysa;
2631 static int
2632 setph1prop(props, buf)
2633 struct isakmpsa *props;
2634 caddr_t buf;
2636 struct isakmp_pl_p *prop = NULL;
2637 struct isakmpsa *s = NULL;
2638 int proplen, trnslen;
2639 u_int8_t *np_t; /* pointer next trns type in previous header */
2640 int trns_num;
2641 caddr_t p = buf;
2643 proplen = sizeof(*prop);
2644 if (buf) {
2645 /* create proposal */
2646 prop = (struct isakmp_pl_p *)p;
2647 prop->h.np = ISAKMP_NPTYPE_NONE;
2648 prop->p_no = props->prop_no;
2649 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2650 prop->spi_size = 0;
2651 p += sizeof(*prop);
2654 np_t = NULL;
2655 trns_num = 0;
2657 for (s = props; s != NULL; s = s->next) {
2658 if (np_t)
2659 *np_t = ISAKMP_NPTYPE_T;
2661 trnslen = setph1trns(s, p);
2662 proplen += trnslen;
2663 if (buf) {
2664 /* save buffer to pre-next payload */
2665 np_t = &((struct isakmp_pl_t *)p)->h.np;
2666 p += trnslen;
2668 /* count up transform length */
2669 trns_num++;
2673 /* update proposal length */
2674 if (buf) {
2675 prop->h.len = htons(proplen);
2676 prop->num_t = trns_num;
2679 return proplen;
2682 static int
2683 setph1trns(sa, buf)
2684 struct isakmpsa *sa;
2685 caddr_t buf;
2687 struct isakmp_pl_t *trns = NULL;
2688 int trnslen, attrlen;
2689 caddr_t p = buf;
2691 trnslen = sizeof(*trns);
2692 if (buf) {
2693 /* create transform */
2694 trns = (struct isakmp_pl_t *)p;
2695 trns->h.np = ISAKMP_NPTYPE_NONE;
2696 trns->t_no = sa->trns_no;
2697 trns->t_id = IPSECDOI_KEY_IKE;
2698 p += sizeof(*trns);
2701 attrlen = setph1attr(sa, p);
2702 trnslen += attrlen;
2703 if (buf)
2704 p += attrlen;
2706 if (buf)
2707 trns->h.len = htons(trnslen);
2709 return trnslen;
2712 static int
2713 setph1attr(sa, buf)
2714 struct isakmpsa *sa;
2715 caddr_t buf;
2717 caddr_t p = buf;
2718 int attrlen = 0;
2720 if (sa->lifetime) {
2721 u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
2723 attrlen += sizeof(struct isakmp_data)
2724 + sizeof(struct isakmp_data);
2725 if (sa->lifetime > 0xffff)
2726 attrlen += sizeof(lifetime);
2727 if (buf) {
2728 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2729 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2730 if (sa->lifetime > 0xffff) {
2731 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2732 (caddr_t)&lifetime,
2733 sizeof(lifetime));
2734 } else {
2735 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2736 sa->lifetime);
2741 if (sa->lifebyte) {
2742 u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
2744 attrlen += sizeof(struct isakmp_data)
2745 + sizeof(struct isakmp_data);
2746 if (sa->lifebyte > 0xffff)
2747 attrlen += sizeof(lifebyte);
2748 if (buf) {
2749 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2750 OAKLEY_ATTR_SA_LD_TYPE_KB);
2751 if (sa->lifebyte > 0xffff) {
2752 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2753 (caddr_t)&lifebyte,
2754 sizeof(lifebyte));
2755 } else {
2756 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2757 sa->lifebyte);
2762 if (sa->enctype) {
2763 attrlen += sizeof(struct isakmp_data);
2764 if (buf)
2765 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2767 if (sa->encklen) {
2768 attrlen += sizeof(struct isakmp_data);
2769 if (buf)
2770 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2772 if (sa->authmethod) {
2773 int authmethod;
2775 authmethod = isakmpsa_switch_authmethod(sa->authmethod);
2776 authmethod &= 0xffff;
2777 attrlen += sizeof(struct isakmp_data);
2778 if (buf)
2779 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
2781 if (sa->hashtype) {
2782 attrlen += sizeof(struct isakmp_data);
2783 if (buf)
2784 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2786 switch (sa->dh_group) {
2787 case OAKLEY_ATTR_GRP_DESC_MODP768:
2788 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2789 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2790 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2791 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2792 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2793 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2794 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2795 /* don't attach group type for known groups */
2796 attrlen += sizeof(struct isakmp_data);
2797 if (buf) {
2798 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2799 sa->dh_group);
2801 break;
2802 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2803 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2804 /* don't attach group type for known groups */
2805 attrlen += sizeof(struct isakmp_data);
2806 if (buf) {
2807 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2808 OAKLEY_ATTR_GRP_TYPE_EC2N);
2810 break;
2811 case 0:
2812 default:
2813 break;
2816 #ifdef HAVE_GSSAPI
2817 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2818 sa->gssid != NULL) {
2819 attrlen += sizeof(struct isakmp_data);
2821 * Older versions of racoon just placed the ISO-Latin-1
2822 * string on the wire directly. Check to see if we are
2823 * configured to be compatible with this behavior. Otherwise,
2824 * we encode the GSS ID as UTF-16LE for Windows 2000
2825 * compatibility, which requires twice the number of octets.
2827 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
2828 attrlen += sa->gssid->l;
2829 else
2830 attrlen += sa->gssid->l * 2;
2831 if (buf) {
2832 plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
2833 "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
2834 sa->gssid->v);
2835 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
2836 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2837 (caddr_t)sa->gssid->v,
2838 sa->gssid->l);
2839 } else {
2840 size_t dstleft = sa->gssid->l * 2;
2841 size_t srcleft = sa->gssid->l;
2842 const char *src = (const char *)sa->gssid->v;
2843 char *odst, *dst = racoon_malloc(dstleft);
2844 iconv_t cd;
2845 size_t rv;
2847 cd = iconv_open("utf-16le", "latin1");
2848 if (cd == (iconv_t) -1) {
2849 plog(LLV_ERROR, LOCATION, NULL,
2850 "unable to initialize "
2851 "latin1 -> utf-16le "
2852 "converstion descriptor: %s\n",
2853 strerror(errno));
2854 attrlen -= sa->gssid->l * 2;
2855 goto gssid_done;
2857 odst = dst;
2858 rv = iconv(cd, (__iconv_const char **)&src,
2859 &srcleft, &dst, &dstleft);
2860 if (rv != 0) {
2861 if (rv == -1) {
2862 plog(LLV_ERROR, LOCATION, NULL,
2863 "unable to convert GSS ID "
2864 "from latin1 -> utf-16le: "
2865 "%s\n", strerror(errno));
2866 } else {
2867 /* should never happen */
2868 plog(LLV_ERROR, LOCATION, NULL,
2869 "%zd character%s in GSS ID "
2870 "cannot be represented "
2871 "in utf-16le\n",
2872 rv, rv == 1 ? "" : "s");
2874 (void) iconv_close(cd);
2875 attrlen -= sa->gssid->l * 2;
2876 goto gssid_done;
2878 (void) iconv_close(cd);
2880 /* XXX Check srcleft and dstleft? */
2882 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2883 odst, sa->gssid->l * 2);
2885 racoon_free(odst);
2889 gssid_done:
2890 #endif /* HAVE_GSSAPI */
2892 return attrlen;
2895 static vchar_t *
2896 setph2proposal0(iph2, pp, pr)
2897 const struct ph2handle *iph2;
2898 const struct saprop *pp;
2899 const struct saproto *pr;
2901 vchar_t *p;
2902 struct isakmp_pl_p *prop;
2903 struct isakmp_pl_t *trns;
2904 struct satrns *tr;
2905 int attrlen;
2906 size_t trnsoff;
2907 caddr_t x0, x;
2908 u_int8_t *np_t; /* pointer next trns type in previous header */
2909 const u_int8_t *spi;
2910 #ifdef HAVE_SECCTX
2911 int truectxlen = 0;
2912 #endif
2914 p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2915 if (p == NULL)
2916 return NULL;
2918 /* create proposal */
2919 prop = (struct isakmp_pl_p *)p->v;
2920 prop->h.np = ISAKMP_NPTYPE_NONE;
2921 prop->p_no = pp->prop_no;
2922 prop->proto_id = pr->proto_id;
2923 prop->num_t = 1;
2925 spi = (const u_int8_t *)&pr->spi;
2926 switch (pr->proto_id) {
2927 case IPSECDOI_PROTO_IPCOMP:
2929 * draft-shacham-ippcp-rfc2393bis-05.txt:
2930 * construct 16bit SPI (CPI).
2931 * XXX we may need to provide a configuration option to
2932 * generate 32bit SPI. otherwise we cannot interoeprate
2933 * with nodes that uses 32bit SPI, in case we are initiator.
2935 prop->spi_size = sizeof(u_int16_t);
2936 spi += sizeof(pr->spi) - sizeof(u_int16_t);
2937 p->l -= sizeof(pr->spi);
2938 p->l += sizeof(u_int16_t);
2939 break;
2940 default:
2941 prop->spi_size = sizeof(pr->spi);
2942 break;
2944 memcpy(prop + 1, spi, prop->spi_size);
2946 /* create transform */
2947 trnsoff = sizeof(*prop) + prop->spi_size;
2948 np_t = NULL;
2950 for (tr = pr->head; tr; tr = tr->next) {
2952 switch (pr->proto_id) {
2953 case IPSECDOI_PROTO_IPSEC_ESP:
2955 * don't build a null encryption
2956 * with no authentication transform.
2958 if (tr->trns_id == IPSECDOI_ESP_NULL &&
2959 tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
2960 continue;
2961 break;
2964 if (np_t) {
2965 *np_t = ISAKMP_NPTYPE_T;
2966 prop->num_t++;
2969 /* get attribute length */
2970 attrlen = 0;
2971 if (pp->lifetime) {
2972 attrlen += sizeof(struct isakmp_data)
2973 + sizeof(struct isakmp_data);
2974 if (pp->lifetime > 0xffff)
2975 attrlen += sizeof(u_int32_t);
2977 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2978 attrlen += sizeof(struct isakmp_data)
2979 + sizeof(struct isakmp_data);
2980 if (pp->lifebyte > 0xffff)
2981 attrlen += sizeof(u_int32_t);
2983 attrlen += sizeof(struct isakmp_data); /* enc mode */
2984 if (tr->encklen)
2985 attrlen += sizeof(struct isakmp_data);
2987 switch (pr->proto_id) {
2988 case IPSECDOI_PROTO_IPSEC_ESP:
2989 /* non authentication mode ? */
2990 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2991 attrlen += sizeof(struct isakmp_data);
2992 break;
2993 case IPSECDOI_PROTO_IPSEC_AH:
2994 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
2995 plog(LLV_ERROR, LOCATION, NULL,
2996 "no authentication algorithm found "
2997 "but protocol is AH.\n");
2998 vfree(p);
2999 return NULL;
3001 attrlen += sizeof(struct isakmp_data);
3002 break;
3003 case IPSECDOI_PROTO_IPCOMP:
3004 break;
3005 default:
3006 plog(LLV_ERROR, LOCATION, NULL,
3007 "invalid protocol: %d\n", pr->proto_id);
3008 vfree(p);
3009 return NULL;
3012 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3013 attrlen += sizeof(struct isakmp_data);
3015 #ifdef HAVE_SECCTX
3016 /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
3017 * The string may be smaller than MAX_CTXSTR_SIZ.
3019 if (*pp->sctx.ctx_str) {
3020 truectxlen = sizeof(struct security_ctx) -
3021 (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
3022 attrlen += sizeof(struct isakmp_data) + truectxlen;
3024 #endif /* HAVE_SECCTX */
3026 p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
3027 if (p == NULL)
3028 return NULL;
3029 prop = (struct isakmp_pl_p *)p->v;
3031 /* set transform's values */
3032 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3033 trns->h.np = ISAKMP_NPTYPE_NONE;
3034 trns->t_no = tr->trns_no;
3035 trns->t_id = tr->trns_id;
3037 /* set attributes */
3038 x = x0 = p->v + trnsoff + sizeof(*trns);
3040 if (pp->lifetime) {
3041 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3042 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
3043 if (pp->lifetime > 0xffff) {
3044 u_int32_t v = htonl((u_int32_t)pp->lifetime);
3045 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3046 (caddr_t)&v, sizeof(v));
3047 } else {
3048 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3049 pp->lifetime);
3053 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3054 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3055 IPSECDOI_ATTR_SA_LD_TYPE_KB);
3056 if (pp->lifebyte > 0xffff) {
3057 u_int32_t v = htonl((u_int32_t)pp->lifebyte);
3058 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3059 (caddr_t)&v, sizeof(v));
3060 } else {
3061 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3062 pp->lifebyte);
3066 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
3068 if (tr->encklen)
3069 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
3071 /* mandatory check has done above. */
3072 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3073 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
3074 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
3076 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3077 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
3078 iph2->sainfo->pfs_group);
3080 #ifdef HAVE_SECCTX
3081 if (*pp->sctx.ctx_str) {
3082 struct security_ctx secctx;
3083 secctx = pp->sctx;
3084 secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
3085 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
3086 (caddr_t)&secctx, truectxlen);
3088 #endif
3089 /* update length of this transform. */
3090 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3091 trns->h.len = htons(sizeof(*trns) + attrlen);
3093 /* save buffer to pre-next payload */
3094 np_t = &trns->h.np;
3096 trnsoff += (sizeof(*trns) + attrlen);
3099 if (np_t == NULL) {
3100 plog(LLV_ERROR, LOCATION, NULL,
3101 "no suitable proposal was created.\n");
3102 return NULL;
3105 /* update length of this protocol. */
3106 prop->h.len = htons(p->l);
3108 return p;
3112 * create phase2 proposal from policy configuration.
3113 * NOT INCLUDING isakmp general header of SA payload.
3114 * This function is called by initiator only.
3117 ipsecdoi_setph2proposal(iph2)
3118 struct ph2handle *iph2;
3120 struct saprop *proposal, *a;
3121 struct saproto *b = NULL;
3122 vchar_t *q;
3123 struct ipsecdoi_sa_b *sab;
3124 struct isakmp_pl_p *prop;
3125 size_t propoff; /* for previous field of type of next payload. */
3127 proposal = iph2->proposal;
3129 iph2->sa = vmalloc(sizeof(*sab));
3130 if (iph2->sa == NULL) {
3131 plog(LLV_ERROR, LOCATION, NULL,
3132 "failed to allocate my sa buffer\n");
3133 return -1;
3136 /* create SA payload */
3137 sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
3138 sab->doi = htonl(IPSEC_DOI);
3139 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
3141 prop = NULL;
3142 propoff = 0;
3143 for (a = proposal; a; a = a->next) {
3144 for (b = a->head; b; b = b->next) {
3145 #ifdef ENABLE_NATT
3146 if (iph2->ph1->natt_flags & NAT_DETECTED) {
3147 int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
3148 plog (LLV_INFO, LOCATION, NULL,
3149 "NAT detected -> UDP encapsulation "
3150 "(ENC_MODE %d->%d).\n",
3151 b->encmode,
3152 b->encmode+udp_diff);
3153 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3154 b->encmode += udp_diff;
3155 b->udp_encap = 1;
3157 #endif
3159 q = setph2proposal0(iph2, a, b);
3160 if (q == NULL) {
3161 VPTRINIT(iph2->sa);
3162 return -1;
3165 iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
3166 if (iph2->sa == NULL) {
3167 plog(LLV_ERROR, LOCATION, NULL,
3168 "failed to allocate my sa buffer\n");
3169 if (q)
3170 vfree(q);
3171 return -1;
3173 memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3174 if (propoff != 0) {
3175 prop = (struct isakmp_pl_p *)(iph2->sa->v +
3176 propoff);
3177 prop->h.np = ISAKMP_NPTYPE_P;
3179 propoff = iph2->sa->l - q->l;
3181 vfree(q);
3185 return 0;
3189 * return 1 if all of the given protocols are transport mode.
3192 ipsecdoi_transportmode(pp)
3193 struct saprop *pp;
3195 struct saproto *pr = NULL;
3197 for (; pp; pp = pp->next) {
3198 for (pr = pp->head; pr; pr = pr->next) {
3199 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
3200 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
3201 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
3202 return 0;
3206 return 1;
3210 ipsecdoi_get_defaultlifetime()
3212 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3216 ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3217 int proto_id, enc, auth, comp;
3219 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3220 switch (proto_id) {
3221 case IPSECDOI_PROTO_IPSEC_ESP:
3222 if (enc == 0 || comp != 0) {
3223 plog(LLV_ERROR, LOCATION, NULL,
3224 "illegal algorithm defined "
3225 "ESP enc=%s auth=%s comp=%s.\n",
3226 TMPALGTYPE2STR(enc),
3227 TMPALGTYPE2STR(auth),
3228 TMPALGTYPE2STR(comp));
3229 return -1;
3231 break;
3232 case IPSECDOI_PROTO_IPSEC_AH:
3233 if (enc != 0 || auth == 0 || comp != 0) {
3234 plog(LLV_ERROR, LOCATION, NULL,
3235 "illegal algorithm defined "
3236 "AH enc=%s auth=%s comp=%s.\n",
3237 TMPALGTYPE2STR(enc),
3238 TMPALGTYPE2STR(auth),
3239 TMPALGTYPE2STR(comp));
3240 return -1;
3242 break;
3243 case IPSECDOI_PROTO_IPCOMP:
3244 if (enc != 0 || auth != 0 || comp == 0) {
3245 plog(LLV_ERROR, LOCATION, NULL,
3246 "illegal algorithm defined "
3247 "IPcomp enc=%s auth=%s comp=%s.\n",
3248 TMPALGTYPE2STR(enc),
3249 TMPALGTYPE2STR(auth),
3250 TMPALGTYPE2STR(comp));
3251 return -1;
3253 break;
3254 default:
3255 plog(LLV_ERROR, LOCATION, NULL,
3256 "invalid ipsec protocol %d\n", proto_id);
3257 return -1;
3259 #undef TMPALGTYPE2STR
3260 return 0;
3264 ipproto2doi(proto)
3265 int proto;
3267 switch (proto) {
3268 case IPPROTO_AH:
3269 return IPSECDOI_PROTO_IPSEC_AH;
3270 case IPPROTO_ESP:
3271 return IPSECDOI_PROTO_IPSEC_ESP;
3272 case IPPROTO_IPCOMP:
3273 return IPSECDOI_PROTO_IPCOMP;
3275 return -1; /* XXX */
3279 doi2ipproto(proto)
3280 int proto;
3282 switch (proto) {
3283 case IPSECDOI_PROTO_IPSEC_AH:
3284 return IPPROTO_AH;
3285 case IPSECDOI_PROTO_IPSEC_ESP:
3286 return IPPROTO_ESP;
3287 case IPSECDOI_PROTO_IPCOMP:
3288 return IPPROTO_IPCOMP;
3290 return -1; /* XXX */
3294 * Check if a subnet id is valid for comparison
3295 * with an address id ( address length mask )
3296 * and compare them
3297 * Return value
3298 * = 0 for match
3299 * = 1 for mismatch
3303 ipsecdoi_subnetisaddr_v4( subnet, address )
3304 const vchar_t *subnet;
3305 const vchar_t *address;
3307 struct in_addr *mask;
3309 if (address->l != sizeof(struct in_addr))
3310 return 1;
3312 if (subnet->l != (sizeof(struct in_addr)*2))
3313 return 1;
3315 mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
3317 if (mask->s_addr!=0xffffffff)
3318 return 1;
3320 return memcmp(subnet->v,address->v,address->l);
3323 #ifdef INET6
3326 ipsecdoi_subnetisaddr_v6( subnet, address )
3327 const vchar_t *subnet;
3328 const vchar_t *address;
3330 struct in6_addr *mask;
3331 int i;
3333 if (address->l != sizeof(struct in6_addr))
3334 return 1;
3336 if (subnet->l != (sizeof(struct in6_addr)*2))
3337 return 1;
3339 mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
3341 for (i=0; i<16; i++)
3342 if(mask->s6_addr[i]!=0xff)
3343 return 1;
3345 return memcmp(subnet->v,address->v,address->l);
3348 #endif
3351 * Check and Compare two IDs
3352 * - specify 0 for exact if wildcards are allowed
3353 * Return value
3354 * = 0 for match
3355 * = 1 for misatch
3356 * = -1 for integrity error
3360 ipsecdoi_chkcmpids( idt, ids, exact )
3361 const vchar_t *idt; /* id cmp target */
3362 const vchar_t *ids; /* id cmp source */
3363 int exact;
3365 struct ipsecdoi_id_b *id_bt;
3366 struct ipsecdoi_id_b *id_bs;
3367 vchar_t ident_t;
3368 vchar_t ident_s;
3369 int result;
3371 /* handle wildcard IDs */
3373 if (idt == NULL || ids == NULL)
3375 if( !exact )
3377 plog(LLV_DEBUG, LOCATION, NULL,
3378 "check and compare ids : values matched (ANONYMOUS)\n" );
3379 return 0;
3381 else
3383 plog(LLV_DEBUG, LOCATION, NULL,
3384 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3385 return -1;
3389 /* make sure the ids are of the same type */
3391 id_bt = (struct ipsecdoi_id_b *) idt->v;
3392 id_bs = (struct ipsecdoi_id_b *) ids->v;
3394 ident_t.v = idt->v + sizeof(*id_bt);
3395 ident_t.l = idt->l - sizeof(*id_bt);
3396 ident_s.v = ids->v + sizeof(*id_bs);
3397 ident_s.l = ids->l - sizeof(*id_bs);
3399 if (id_bs->type != id_bt->type)
3402 * special exception for comparing
3403 * address to subnet id types when
3404 * the netmask is address length
3407 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3408 (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3409 result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3410 goto cmpid_result;
3413 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3414 (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3415 result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3416 goto cmpid_result;
3419 #ifdef INET6
3420 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3421 (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3422 result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3423 goto cmpid_result;
3426 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3427 (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3428 result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3429 goto cmpid_result;
3431 #endif
3432 plog(LLV_DEBUG, LOCATION, NULL,
3433 "check and compare ids : id type mismatch %s != %s\n",
3434 s_ipsecdoi_ident(id_bs->type),
3435 s_ipsecdoi_ident(id_bt->type));
3437 return 1;
3440 if(id_bs->proto_id != id_bt->proto_id){
3441 plog(LLV_DEBUG, LOCATION, NULL,
3442 "check and compare ids : proto_id mismatch %d != %d\n",
3443 id_bs->proto_id, id_bt->proto_id);
3445 return 1;
3448 /* compare the ID data. */
3450 switch (id_bt->type) {
3451 case IPSECDOI_ID_DER_ASN1_DN:
3452 case IPSECDOI_ID_DER_ASN1_GN:
3453 /* compare asn1 ids */
3454 result = eay_cmp_asn1dn(&ident_t, &ident_s);
3455 goto cmpid_result;
3457 case IPSECDOI_ID_IPV4_ADDR:
3458 /* validate lengths */
3459 if ((ident_t.l != sizeof(struct in_addr))||
3460 (ident_s.l != sizeof(struct in_addr)))
3461 goto cmpid_invalid;
3462 break;
3464 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3465 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3466 /* validate lengths */
3467 if ((ident_t.l != (sizeof(struct in_addr)*2))||
3468 (ident_s.l != (sizeof(struct in_addr)*2)))
3469 goto cmpid_invalid;
3470 break;
3472 #ifdef INET6
3473 case IPSECDOI_ID_IPV6_ADDR:
3474 /* validate lengths */
3475 if ((ident_t.l != sizeof(struct in6_addr))||
3476 (ident_s.l != sizeof(struct in6_addr)))
3477 goto cmpid_invalid;
3478 break;
3480 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3481 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3482 /* validate lengths */
3483 if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3484 (ident_s.l != (sizeof(struct in6_addr)*2)))
3485 goto cmpid_invalid;
3486 break;
3487 #endif
3488 case IPSECDOI_ID_FQDN:
3489 case IPSECDOI_ID_USER_FQDN:
3490 case IPSECDOI_ID_KEY_ID:
3491 break;
3493 default:
3494 plog(LLV_ERROR, LOCATION, NULL,
3495 "Unhandled id type %i specified for comparison\n",
3496 id_bt->type);
3497 return -1;
3500 /* validate matching data and length */
3501 if (ident_t.l == ident_s.l)
3502 result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3503 else
3504 result = 1;
3506 cmpid_result:
3508 /* debug level output */
3509 if(loglevel >= LLV_DEBUG) {
3510 char *idstrt = ipsecdoi_id2str(idt);
3511 char *idstrs = ipsecdoi_id2str(ids);
3513 if (!result)
3514 plog(LLV_DEBUG, LOCATION, NULL,
3515 "check and compare ids : values matched (%s)\n",
3516 s_ipsecdoi_ident(id_bs->type) );
3517 else
3518 plog(LLV_DEBUG, LOCATION, NULL,
3519 "check and compare ids : value mismatch (%s)\n",
3520 s_ipsecdoi_ident(id_bs->type));
3522 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
3523 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
3525 racoon_free(idstrs);
3526 racoon_free(idstrt);
3529 /* return result */
3530 if( !result )
3531 return 0;
3532 else
3533 return 1;
3535 cmpid_invalid:
3537 /* id integrity error */
3538 plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
3539 s_ipsecdoi_ident(id_bs->type));
3540 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
3541 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
3543 return -1;
3547 * check the following:
3548 * - In main mode with pre-shared key, only address type can be used.
3549 * - if proper type for phase 1 ?
3550 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3551 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3552 * - if ID payload sent from peer is equal to the ID expected by me.
3554 * both of "id" and "id_p" should be ID payload without general header,
3557 ipsecdoi_checkid1(iph1)
3558 struct ph1handle *iph1;
3560 struct ipsecdoi_id_b *id_b;
3562 if (iph1->id_p == NULL) {
3563 plog(LLV_ERROR, LOCATION, NULL,
3564 "invalid iph1 passed id_p == NULL\n");
3565 return ISAKMP_INTERNAL_ERROR;
3567 if (iph1->id_p->l < sizeof(*id_b)) {
3568 plog(LLV_ERROR, LOCATION, NULL,
3569 "invalid value passed as \"ident\" (len=%lu)\n",
3570 (u_long)iph1->id_p->l);
3571 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3574 id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3576 /* In main mode with pre-shared key, only address type can be used. */
3577 if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3578 iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3579 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3580 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3581 plog(LLV_ERROR, LOCATION, NULL,
3582 "Expecting IP address type in main mode, "
3583 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3584 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3588 /* if proper type for phase 1 ? */
3589 switch (id_b->type) {
3590 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3591 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3592 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3593 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3594 plog(LLV_WARNING, LOCATION, NULL,
3595 "such ID type %s is not proper.\n",
3596 s_ipsecdoi_ident(id_b->type));
3597 /*FALLTHROUGH*/
3600 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3601 if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3602 id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3604 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3605 plog(LLV_WARNING, LOCATION, NULL,
3606 "protocol ID and Port mismatched. "
3607 "proto_id:%d port:%d\n",
3608 id_b->proto_id, ntohs(id_b->port));
3609 /*FALLTHROUGH*/
3611 } else if (id_b->proto_id == IPPROTO_UDP) {
3613 * copmaring with expecting port.
3614 * always permit if port is equal to PORT_ISAKMP
3616 if (ntohs(id_b->port) != PORT_ISAKMP) {
3617 u_int16_t port;
3619 port = extract_port(iph1->remote);
3620 if (ntohs(id_b->port) != port) {
3621 plog(LLV_WARNING, LOCATION, NULL,
3622 "port %d expected, but %d\n",
3623 port, ntohs(id_b->port));
3624 /*FALLTHROUGH*/
3630 /* resolve remote configuration if not done yet */
3631 if (resolveph1rmconf(iph1) < 0)
3632 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3634 if (iph1->rmconf == NULL)
3635 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3637 return 0;
3641 * create ID payload for phase 1 and set into iph1->id.
3642 * NOT INCLUDING isakmp general header.
3643 * see, RFC2407 4.6.2.1
3646 ipsecdoi_setid1(iph1)
3647 struct ph1handle *iph1;
3649 vchar_t *ret = NULL;
3650 struct ipsecdoi_id_b id_b;
3651 vchar_t *ident = NULL;
3652 struct sockaddr *ipid = NULL;
3654 /* init */
3655 id_b.proto_id = 0;
3656 id_b.port = 0;
3657 ident = NULL;
3659 switch (iph1->rmconf->idvtype) {
3660 case IDTYPE_FQDN:
3661 id_b.type = IPSECDOI_ID_FQDN;
3662 ident = vdup(iph1->rmconf->idv);
3663 break;
3664 case IDTYPE_USERFQDN:
3665 id_b.type = IPSECDOI_ID_USER_FQDN;
3666 ident = vdup(iph1->rmconf->idv);
3667 break;
3668 case IDTYPE_KEYID:
3669 id_b.type = IPSECDOI_ID_KEY_ID;
3670 ident = vdup(iph1->rmconf->idv);
3671 break;
3672 case IDTYPE_ASN1DN:
3673 id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3674 if (iph1->rmconf->idv) {
3675 /* XXX it must be encoded to asn1dn. */
3676 ident = vdup(iph1->rmconf->idv);
3677 } else {
3678 if (oakley_getmycert(iph1) < 0) {
3679 plog(LLV_ERROR, LOCATION, NULL,
3680 "failed to get own CERT.\n");
3681 goto err;
3683 ident = eay_get_x509asn1subjectname(iph1->cert);
3685 break;
3686 case IDTYPE_ADDRESS:
3688 * if the value of the id type was set by the configuration
3689 * file, then use it. otherwise the value is get from local
3690 * ip address by using ike negotiation.
3692 if (iph1->rmconf->idv)
3693 ipid = (struct sockaddr *)iph1->rmconf->idv->v;
3694 /*FALLTHROUGH*/
3695 default:
3697 int l;
3698 caddr_t p;
3700 if (ipid == NULL)
3701 ipid = iph1->local;
3703 /* use IP address */
3704 switch (ipid->sa_family) {
3705 case AF_INET:
3706 id_b.type = IPSECDOI_ID_IPV4_ADDR;
3707 l = sizeof(struct in_addr);
3708 p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3709 break;
3710 #ifdef INET6
3711 case AF_INET6:
3712 id_b.type = IPSECDOI_ID_IPV6_ADDR;
3713 l = sizeof(struct in6_addr);
3714 p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3715 break;
3716 #endif
3717 default:
3718 plog(LLV_ERROR, LOCATION, NULL,
3719 "invalid address family.\n");
3720 goto err;
3722 id_b.proto_id = IPPROTO_UDP;
3723 id_b.port = htons(PORT_ISAKMP);
3724 ident = vmalloc(l);
3725 if (!ident) {
3726 plog(LLV_ERROR, LOCATION, NULL,
3727 "failed to get ID buffer.\n");
3728 return -1;
3730 memcpy(ident->v, p, ident->l);
3733 if (!ident) {
3734 plog(LLV_ERROR, LOCATION, NULL,
3735 "failed to get ID buffer.\n");
3736 return -1;
3739 ret = vmalloc(sizeof(id_b) + ident->l);
3740 if (ret == NULL) {
3741 plog(LLV_ERROR, LOCATION, NULL,
3742 "failed to get ID buffer.\n");
3743 goto err;
3746 memcpy(ret->v, &id_b, sizeof(id_b));
3747 memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3749 iph1->id = ret;
3751 plog(LLV_DEBUG, LOCATION, NULL,
3752 "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3753 if (ident)
3754 vfree(ident);
3755 return 0;
3757 err:
3758 if (ident)
3759 vfree(ident);
3760 plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3761 return -1;
3764 /* it's only called by cfparse.y. */
3766 set_identifier(vpp, type, value)
3767 vchar_t **vpp, *value;
3768 int type;
3770 return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
3774 set_identifier_qual(vpp, type, value, qual)
3775 vchar_t **vpp, *value;
3776 int type;
3777 int qual;
3779 vchar_t *new = NULL;
3781 /* simply return if value is null. */
3782 if (!value){
3783 if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
3784 plog(LLV_ERROR, LOCATION, NULL,
3785 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3786 return -1;
3788 return 0;
3791 switch (type) {
3792 case IDTYPE_FQDN:
3793 case IDTYPE_USERFQDN:
3794 if(value->l <= 1){
3795 plog(LLV_ERROR, LOCATION, NULL,
3796 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3797 return -1;
3799 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3800 new = vmalloc(value->l - 1);
3801 if (new == NULL)
3802 return -1;
3803 memcpy(new->v, value->v, new->l);
3804 break;
3805 case IDTYPE_KEYID:
3807 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3808 * to use a file for backward compatibility sake.
3810 switch(qual) {
3811 case IDQUAL_FILE:
3812 case IDQUAL_UNSPEC: {
3813 FILE *fp;
3814 char b[512];
3815 int tlen, len;
3817 fp = fopen(value->v, "r");
3818 if (fp == NULL) {
3819 plog(LLV_ERROR, LOCATION, NULL,
3820 "can not open %s\n", value->v);
3821 return -1;
3823 tlen = 0;
3824 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3825 new = vrealloc(new, tlen + len);
3826 if (!new) {
3827 fclose(fp);
3828 return -1;
3830 memcpy(new->v + tlen, b, len);
3831 tlen += len;
3833 break;
3836 case IDQUAL_TAG:
3837 new = vmalloc(value->l - 1);
3838 if (new == NULL) {
3839 plog(LLV_ERROR, LOCATION, NULL,
3840 "can not allocate memory");
3841 return -1;
3843 memcpy(new->v, value->v, new->l);
3844 break;
3846 default:
3847 plog(LLV_ERROR, LOCATION, NULL,
3848 "unknown qualifier");
3849 return -1;
3851 break;
3853 case IDTYPE_ADDRESS: {
3854 struct sockaddr *sa;
3856 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3857 if (value->l == 0)
3858 break;
3860 sa = str2saddr(value->v, NULL);
3861 if (sa == NULL) {
3862 plog(LLV_ERROR, LOCATION, NULL,
3863 "invalid ip address %s\n", value->v);
3864 return -1;
3867 new = vmalloc(sysdep_sa_len(sa));
3868 if (new == NULL) {
3869 racoon_free(sa);
3870 return -1;
3872 memcpy(new->v, sa, new->l);
3873 racoon_free(sa);
3874 break;
3876 case IDTYPE_ASN1DN:
3877 if (value->v[0] == '~')
3878 /* Hex-encoded ASN1 strings */
3879 new = eay_hex2asn1dn(value->v + 1, - 1);
3880 else
3881 /* DN encoded strings */
3882 new = eay_str2asn1dn(value->v, value->l - 1);
3884 if (new == NULL)
3885 return -1;
3887 if (loglevel >= LLV_DEBUG) {
3888 X509_NAME *xn;
3889 BIO *bio;
3890 unsigned char *ptr = (unsigned char *) new->v, *buf;
3891 size_t len;
3892 char save;
3894 xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
3895 bio = BIO_new(BIO_s_mem());
3897 X509_NAME_print_ex(bio, xn, 0, 0);
3898 len = BIO_get_mem_data(bio, &ptr);
3899 save = ptr[len];
3900 ptr[len] = 0;
3901 plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
3902 ptr[len] = save;
3903 X509_NAME_free(xn);
3904 BIO_free(bio);
3907 break;
3910 *vpp = new;
3912 return 0;
3916 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3917 * NOT INCLUDING isakmp general header.
3918 * this function is for initiator. responder will get to copy from payload.
3919 * responder ID type is always address type.
3920 * see, RFC2407 4.6.2.1
3923 ipsecdoi_setid2(iph2)
3924 struct ph2handle *iph2;
3926 struct secpolicy *sp;
3928 /* check there is phase 2 handler ? */
3929 sp = getspbyspid(iph2->spid);
3930 if (sp == NULL) {
3931 plog(LLV_ERROR, LOCATION, NULL,
3932 "no policy found for spid:%u.\n", iph2->spid);
3933 return -1;
3936 if (!ipsecdoi_transportmode(iph2->proposal))
3937 iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
3938 sp->spidx.prefs, sp->spidx.ul_proto);
3939 else if (iph2->sa_src != NULL) {
3940 /* He have a specific hint indicating that the transport
3941 * mode SA will be negotiated using addresses that differ
3942 * with the one from the SA. We need to indicate that to
3943 * our peer by setting the SA address as ID.
3944 * This is typically the case for the bootstrapping of the
3945 * transport mode SA protecting BU/BA for MIPv6 traffic
3947 * --arno*/
3948 iph2->id = ipsecdoi_sockaddr2id(iph2->sa_src,
3949 IPSECDOI_PREFIX_HOST,
3950 sp->spidx.ul_proto);
3951 } else
3952 iph2->id = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
3953 sp->spidx.ul_proto);
3955 if (iph2->id == NULL) {
3956 plog(LLV_ERROR, LOCATION, NULL,
3957 "failed to get ID for %s\n",
3958 spidx2str(&sp->spidx));
3959 return -1;
3961 plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
3962 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
3964 /* remote side */
3965 if (!ipsecdoi_transportmode(iph2->proposal))
3966 iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
3967 sp->spidx.prefd, sp->spidx.ul_proto);
3968 else if (iph2->sa_dst != NULL) {
3969 /* See comment above for local side. */
3970 iph2->id_p = ipsecdoi_sockaddr2id(iph2->sa_dst,
3971 IPSECDOI_PREFIX_HOST,
3972 sp->spidx.ul_proto);
3973 } else
3974 iph2->id_p = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
3975 sp->spidx.ul_proto);
3977 if (iph2->id_p == NULL) {
3978 plog(LLV_ERROR, LOCATION, NULL,
3979 "failed to get ID for %s\n",
3980 spidx2str(&sp->spidx));
3981 VPTRINIT(iph2->id);
3982 return -1;
3984 plog(LLV_DEBUG, LOCATION, NULL,
3985 "use remote ID type %s\n",
3986 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
3988 return 0;
3992 * set address type of ID.
3993 * NOT INCLUDING general header.
3995 vchar_t *
3996 ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
3997 struct sockaddr *saddr;
3998 u_int prefixlen;
3999 u_int ul_proto;
4001 vchar_t *new;
4002 int type, len1, len2;
4003 caddr_t sa;
4004 u_short port;
4007 * Q. When type is SUBNET, is it allowed to be ::1/128.
4008 * A. Yes. (consensus at bake-off)
4010 switch (saddr->sa_family) {
4011 case AF_INET:
4012 len1 = sizeof(struct in_addr);
4013 if (prefixlen >= (sizeof(struct in_addr) << 3)) {
4014 type = IPSECDOI_ID_IPV4_ADDR;
4015 len2 = 0;
4016 } else {
4017 type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
4018 len2 = sizeof(struct in_addr);
4020 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
4021 port = ((struct sockaddr_in *)(saddr))->sin_port;
4022 break;
4023 #ifdef INET6
4024 case AF_INET6:
4025 len1 = sizeof(struct in6_addr);
4026 if (prefixlen >= (sizeof(struct in6_addr) << 3)) {
4027 type = IPSECDOI_ID_IPV6_ADDR;
4028 len2 = 0;
4029 } else {
4030 type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
4031 len2 = sizeof(struct in6_addr);
4033 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
4034 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
4035 break;
4036 #endif
4037 default:
4038 plog(LLV_ERROR, LOCATION, NULL,
4039 "invalid family: %d.\n", saddr->sa_family);
4040 return NULL;
4043 /* get ID buffer */
4044 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4045 if (new == NULL) {
4046 plog(LLV_ERROR, LOCATION, NULL,
4047 "failed to get ID buffer.\n");
4048 return NULL;
4051 memset(new->v, 0, new->l);
4053 /* set the part of header. */
4054 ((struct ipsecdoi_id_b *)new->v)->type = type;
4056 /* set ul_proto and port */
4058 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4059 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4061 ((struct ipsecdoi_id_b *)new->v)->proto_id =
4062 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4063 ((struct ipsecdoi_id_b *)new->v)->port =
4064 port == IPSEC_PORT_ANY ? 0 : port;
4065 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
4067 /* set address */
4069 /* set prefix */
4070 if (len2) {
4071 u_char *p = (unsigned char *) new->v +
4072 sizeof(struct ipsecdoi_id_b) + len1;
4073 u_int bits = prefixlen;
4075 while (bits >= 8) {
4076 *p++ = 0xff;
4077 bits -= 8;
4080 if (bits > 0)
4081 *p = ~((1 << (8 - bits)) - 1);
4084 return new;
4087 vchar_t *
4088 ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
4089 struct sockaddr *laddr, *haddr;
4090 u_int ul_proto;
4092 vchar_t *new;
4093 int type, len1, len2;
4094 u_short port;
4096 if (laddr->sa_family != haddr->sa_family) {
4097 plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
4098 return NULL;
4101 switch (laddr->sa_family) {
4102 case AF_INET:
4103 type = IPSECDOI_ID_IPV4_ADDR_RANGE;
4104 len1 = sizeof(struct in_addr);
4105 len2 = sizeof(struct in_addr);
4106 break;
4107 #ifdef INET6
4108 case AF_INET6:
4109 type = IPSECDOI_ID_IPV6_ADDR_RANGE;
4110 len1 = sizeof(struct in6_addr);
4111 len2 = sizeof(struct in6_addr);
4112 break;
4113 #endif
4114 default:
4115 plog(LLV_ERROR, LOCATION, NULL,
4116 "invalid family: %d.\n", laddr->sa_family);
4117 return NULL;
4120 /* get ID buffer */
4121 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4122 if (new == NULL) {
4123 plog(LLV_ERROR, LOCATION, NULL,
4124 "failed to get ID buffer.\n");
4125 return NULL;
4128 memset(new->v, 0, new->l);
4129 /* set the part of header. */
4130 ((struct ipsecdoi_id_b *)new->v)->type = type;
4132 /* set ul_proto and port */
4134 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4135 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4137 ((struct ipsecdoi_id_b *)new->v)->proto_id =
4138 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4139 port = ((struct sockaddr_in *)(laddr))->sin_port;
4140 ((struct ipsecdoi_id_b *)new->v)->port =
4141 port == IPSEC_PORT_ANY ? 0 : port;
4142 memcpy(new->v + sizeof(struct ipsecdoi_id_b),
4143 (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
4144 len1);
4145 memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
4146 (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
4147 len2);
4148 return new;
4153 * create sockaddr structure from ID payload (buf).
4154 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4155 * see, RFC2407 4.6.2.1
4158 ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
4159 vchar_t *buf;
4160 struct sockaddr *saddr;
4161 u_int8_t *prefixlen;
4162 u_int16_t *ul_proto;
4164 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
4165 u_int plen = 0;
4168 * When a ID payload of subnet type with a IP address of full bit
4169 * masked, it has to be processed as host address.
4170 * e.g. below 2 type are same.
4171 * type = ipv6 subnet, data = 2001::1/128
4172 * type = ipv6 address, data = 2001::1
4174 switch (id_b->type) {
4175 case IPSECDOI_ID_IPV4_ADDR:
4176 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4177 #ifndef __linux__
4178 saddr->sa_len = sizeof(struct sockaddr_in);
4179 #endif
4180 saddr->sa_family = AF_INET;
4181 ((struct sockaddr_in *)saddr)->sin_port =
4182 (id_b->port == 0
4183 ? IPSEC_PORT_ANY
4184 : id_b->port); /* see sockaddr2id() */
4185 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
4186 buf->v + sizeof(*id_b), sizeof(struct in_addr));
4187 break;
4188 #ifdef INET6
4189 case IPSECDOI_ID_IPV6_ADDR:
4190 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4191 #ifndef __linux__
4192 saddr->sa_len = sizeof(struct sockaddr_in6);
4193 #endif
4194 saddr->sa_family = AF_INET6;
4195 ((struct sockaddr_in6 *)saddr)->sin6_port =
4196 (id_b->port == 0
4197 ? IPSEC_PORT_ANY
4198 : id_b->port); /* see sockaddr2id() */
4199 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
4200 buf->v + sizeof(*id_b), sizeof(struct in6_addr));
4201 ((struct sockaddr_in6 *)saddr)->sin6_scope_id =
4202 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)saddr)->sin6_addr)
4203 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4204 : 0);
4206 break;
4207 #endif
4208 default:
4209 plog(LLV_ERROR, LOCATION, NULL,
4210 "unsupported ID type %d\n", id_b->type);
4211 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
4214 /* get prefix length */
4215 switch (id_b->type) {
4216 case IPSECDOI_ID_IPV4_ADDR:
4217 plen = sizeof(struct in_addr) << 3;
4218 break;
4219 #ifdef INET6
4220 case IPSECDOI_ID_IPV6_ADDR:
4221 plen = sizeof(struct in6_addr) << 3;
4222 break;
4223 #endif
4224 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4225 #ifdef INET6
4226 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4227 #endif
4229 u_char *p;
4230 u_int max;
4231 int alen = sizeof(struct in_addr);
4233 switch (id_b->type) {
4234 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4235 alen = sizeof(struct in_addr);
4236 break;
4237 #ifdef INET6
4238 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4239 alen = sizeof(struct in6_addr);
4240 break;
4241 #endif
4244 /* sanity check */
4245 if (buf->l < alen)
4246 return ISAKMP_INTERNAL_ERROR;
4248 /* get subnet mask length */
4249 plen = 0;
4250 max = alen <<3;
4252 p = (unsigned char *) buf->v
4253 + sizeof(struct ipsecdoi_id_b)
4254 + alen;
4256 for (; *p == 0xff; p++) {
4257 plen += 8;
4258 if (plen >= max)
4259 break;
4262 if (plen < max) {
4263 u_int l = 0;
4264 u_char b = ~(*p);
4266 while (b) {
4267 b >>= 1;
4268 l++;
4271 l = 8 - l;
4272 plen += l;
4275 break;
4278 *prefixlen = plen;
4279 *ul_proto = id_b->proto_id == 0
4280 ? IPSEC_ULPROTO_ANY
4281 : id_b->proto_id; /* see sockaddr2id() */
4283 return 0;
4287 * make printable string from ID payload except of general header.
4289 char *
4290 ipsecdoi_id2str(id)
4291 const vchar_t *id;
4293 #define BUFLEN 512
4294 char * ret = NULL;
4295 int len = 0;
4296 char *dat;
4297 static char buf[BUFLEN];
4298 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
4299 union sockaddr_any saddr;
4300 u_int plen = 0;
4302 switch (id_b->type) {
4303 case IPSECDOI_ID_IPV4_ADDR:
4304 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4305 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4307 #ifndef __linux__
4308 saddr.sa.sa_len = sizeof(struct sockaddr_in);
4309 #endif
4310 saddr.sa.sa_family = AF_INET;
4311 saddr.sin.sin_port = IPSEC_PORT_ANY;
4312 memcpy(&saddr.sin.sin_addr,
4313 id->v + sizeof(*id_b), sizeof(struct in_addr));
4314 break;
4315 #ifdef INET6
4316 case IPSECDOI_ID_IPV6_ADDR:
4317 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4318 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4320 #ifndef __linux__
4321 saddr.sa.sa_len = sizeof(struct sockaddr_in6);
4322 #endif
4323 saddr.sa.sa_family = AF_INET6;
4324 saddr.sin6.sin6_port = IPSEC_PORT_ANY;
4325 memcpy(&saddr.sin6.sin6_addr,
4326 id->v + sizeof(*id_b), sizeof(struct in6_addr));
4327 saddr.sin6.sin6_scope_id =
4328 (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
4329 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4330 : 0);
4331 break;
4332 #endif
4335 switch (id_b->type) {
4336 case IPSECDOI_ID_IPV4_ADDR:
4337 #ifdef INET6
4338 case IPSECDOI_ID_IPV6_ADDR:
4339 #endif
4340 len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
4341 break;
4343 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4344 #ifdef INET6
4345 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4346 #endif
4348 u_char *p;
4349 u_int max;
4350 int alen = sizeof(struct in_addr);
4352 switch (id_b->type) {
4353 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4354 alen = sizeof(struct in_addr);
4355 break;
4356 #ifdef INET6
4357 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4358 alen = sizeof(struct in6_addr);
4359 break;
4360 #endif
4363 /* sanity check */
4364 if (id->l < alen) {
4365 len = 0;
4366 break;
4369 /* get subnet mask length */
4370 plen = 0;
4371 max = alen <<3;
4373 p = (unsigned char *) id->v
4374 + sizeof(struct ipsecdoi_id_b)
4375 + alen;
4377 for (; *p == 0xff; p++) {
4378 plen += 8;
4379 if (plen >= max)
4380 break;
4383 if (plen < max) {
4384 u_int l = 0;
4385 u_char b = ~(*p);
4387 while (b) {
4388 b >>= 1;
4389 l++;
4392 l = 8 - l;
4393 plen += l;
4396 len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
4398 break;
4400 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4402 len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
4404 #ifndef __linux__
4405 saddr.sa.sa_len = sizeof(struct sockaddr_in);
4406 #endif
4407 saddr.sa.sa_family = AF_INET;
4408 saddr.sin.sin_port = IPSEC_PORT_ANY;
4409 memcpy(&saddr.sin.sin_addr,
4410 id->v + sizeof(*id_b) + sizeof(struct in_addr),
4411 sizeof(struct in_addr));
4413 len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
4414 break;
4416 #ifdef INET6
4417 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4418 len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
4420 #ifndef __linux__
4421 saddr.sa.sa_len = sizeof(struct sockaddr_in6);
4422 #endif
4423 saddr.sa.sa_family = AF_INET6;
4424 saddr.sin6.sin6_port = IPSEC_PORT_ANY;
4425 memcpy(&saddr.sin6.sin6_addr,
4426 id->v + sizeof(*id_b) + sizeof(struct in6_addr),
4427 sizeof(struct in6_addr));
4428 saddr.sin6.sin6_scope_id =
4429 (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
4430 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4431 : 0);
4433 len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
4434 break;
4435 #endif
4437 case IPSECDOI_ID_FQDN:
4438 case IPSECDOI_ID_USER_FQDN:
4439 len = id->l - sizeof(*id_b);
4440 if (len > BUFLEN)
4441 len = BUFLEN;
4442 memcpy(buf, id->v + sizeof(*id_b), len);
4443 break;
4445 case IPSECDOI_ID_DER_ASN1_DN:
4446 case IPSECDOI_ID_DER_ASN1_GN:
4448 X509_NAME *xn = NULL;
4450 dat = id->v + sizeof(*id_b);
4451 len = id->l - sizeof(*id_b);
4453 if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
4454 BIO *bio = BIO_new(BIO_s_mem());
4455 X509_NAME_print_ex(bio, xn, 0, 0);
4456 len = BIO_get_mem_data(bio, &dat);
4457 if (len > BUFLEN)
4458 len = BUFLEN;
4459 memcpy(buf,dat,len);
4460 BIO_free(bio);
4461 X509_NAME_free(xn);
4462 } else {
4463 plog(LLV_ERROR, LOCATION, NULL,
4464 "unable to extract asn1dn from id\n");
4466 len = sprintf(buf, "<ASN1-DN>");
4469 break;
4472 /* currently unhandled id types */
4473 case IPSECDOI_ID_KEY_ID:
4474 len = sprintf( buf, "<KEY-ID>");
4475 break;
4477 default:
4478 plog(LLV_ERROR, LOCATION, NULL,
4479 "unknown ID type %d\n", id_b->type);
4482 if (!len)
4483 len = sprintf( buf, "<?>");
4485 ret = racoon_malloc(len+1);
4486 if (ret != NULL) {
4487 memcpy(ret,buf,len);
4488 ret[len]=0;
4491 return ret;
4495 * set IPsec data attributes into a proposal.
4496 * NOTE: MUST called per a transform.
4499 ipsecdoi_t2satrns(t, pp, pr, tr)
4500 struct isakmp_pl_t *t;
4501 struct saprop *pp;
4502 struct saproto *pr;
4503 struct satrns *tr;
4505 struct isakmp_data *d, *prev;
4506 int flag, type;
4507 int error = -1;
4508 int life_t;
4509 int tlen;
4511 tr->trns_no = t->t_no;
4512 tr->trns_id = t->t_id;
4514 tlen = ntohs(t->h.len) - sizeof(*t);
4515 prev = (struct isakmp_data *)NULL;
4516 d = (struct isakmp_data *)(t + 1);
4518 /* default */
4519 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4520 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
4521 pp->lifebyte = 0;
4522 tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
4524 while (tlen > 0) {
4526 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
4527 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
4529 plog(LLV_DEBUG, LOCATION, NULL,
4530 "type=%s, flag=0x%04x, lorv=%s\n",
4531 s_ipsecdoi_attr(type), flag,
4532 s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
4534 switch (type) {
4535 case IPSECDOI_ATTR_SA_LD_TYPE:
4537 int type = ntohs(d->lorv);
4538 switch (type) {
4539 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4540 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4541 life_t = type;
4542 break;
4543 default:
4544 plog(LLV_WARNING, LOCATION, NULL,
4545 "invalid life duration type. "
4546 "use default\n");
4547 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4548 break;
4550 break;
4552 case IPSECDOI_ATTR_SA_LD:
4553 if (prev == NULL
4554 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
4555 IPSECDOI_ATTR_SA_LD_TYPE) {
4556 plog(LLV_ERROR, LOCATION, NULL,
4557 "life duration must follow ltype\n");
4558 break;
4562 u_int32_t t;
4563 vchar_t *ld_buf = NULL;
4565 if (flag) {
4566 /* i.e. ISAKMP_GEN_TV */
4567 ld_buf = vmalloc(sizeof(d->lorv));
4568 if (ld_buf == NULL) {
4569 plog(LLV_ERROR, LOCATION, NULL,
4570 "failed to get LD buffer.\n");
4571 goto end;
4573 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
4574 } else {
4575 int len = ntohs(d->lorv);
4576 /* i.e. ISAKMP_GEN_TLV */
4577 ld_buf = vmalloc(len);
4578 if (ld_buf == NULL) {
4579 plog(LLV_ERROR, LOCATION, NULL,
4580 "failed to get LD buffer.\n");
4581 goto end;
4583 memcpy(ld_buf->v, d + 1, len);
4585 switch (life_t) {
4586 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4587 t = ipsecdoi_set_ld(ld_buf);
4588 vfree(ld_buf);
4589 if (t == 0) {
4590 plog(LLV_ERROR, LOCATION, NULL,
4591 "invalid life duration.\n");
4592 goto end;
4594 /* lifetime must be equal in a proposal. */
4595 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
4596 pp->lifetime = t;
4597 else if (pp->lifetime != t) {
4598 plog(LLV_ERROR, LOCATION, NULL,
4599 "lifetime mismatched "
4600 "in a proposal, "
4601 "prev:%ld curr:%u.\n",
4602 (long)pp->lifetime, t);
4603 goto end;
4605 break;
4606 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4607 t = ipsecdoi_set_ld(ld_buf);
4608 vfree(ld_buf);
4609 if (t == 0) {
4610 plog(LLV_ERROR, LOCATION, NULL,
4611 "invalid life duration.\n");
4612 goto end;
4614 /* lifebyte must be equal in a proposal. */
4615 if (pp->lifebyte == 0)
4616 pp->lifebyte = t;
4617 else if (pp->lifebyte != t) {
4618 plog(LLV_ERROR, LOCATION, NULL,
4619 "lifebyte mismatched "
4620 "in a proposal, "
4621 "prev:%d curr:%u.\n",
4622 pp->lifebyte, t);
4623 goto end;
4625 break;
4626 default:
4627 vfree(ld_buf);
4628 plog(LLV_ERROR, LOCATION, NULL,
4629 "invalid life type: %d\n", life_t);
4630 goto end;
4633 break;
4635 case IPSECDOI_ATTR_GRP_DESC:
4637 * RFC2407: 4.5 IPSEC Security Association Attributes
4638 * Specifies the Oakley Group to be used in a PFS QM
4639 * negotiation. For a list of supported values, see
4640 * Appendix A of [IKE].
4642 if (pp->pfs_group == 0)
4643 pp->pfs_group = (u_int16_t)ntohs(d->lorv);
4644 else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
4645 plog(LLV_ERROR, LOCATION, NULL,
4646 "pfs_group mismatched "
4647 "in a proposal.\n");
4648 goto end;
4650 break;
4652 case IPSECDOI_ATTR_ENC_MODE:
4653 if (pr->encmode &&
4654 pr->encmode != (u_int16_t)ntohs(d->lorv)) {
4655 plog(LLV_ERROR, LOCATION, NULL,
4656 "multiple encmode exist "
4657 "in a transform.\n");
4658 goto end;
4660 pr->encmode = (u_int16_t)ntohs(d->lorv);
4661 break;
4663 case IPSECDOI_ATTR_AUTH:
4664 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
4665 plog(LLV_ERROR, LOCATION, NULL,
4666 "multiple authtype exist "
4667 "in a transform.\n");
4668 goto end;
4670 tr->authtype = (u_int16_t)ntohs(d->lorv);
4671 break;
4673 case IPSECDOI_ATTR_KEY_LENGTH:
4674 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
4675 plog(LLV_ERROR, LOCATION, NULL,
4676 "key length defined but not ESP");
4677 goto end;
4679 tr->encklen = ntohs(d->lorv);
4680 break;
4681 #ifdef HAVE_SECCTX
4682 case IPSECDOI_ATTR_SECCTX:
4684 int len = ntohs(d->lorv);
4685 memcpy(&pp->sctx, d + 1, len);
4686 pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
4687 break;
4689 #endif /* HAVE_SECCTX */
4690 case IPSECDOI_ATTR_KEY_ROUNDS:
4691 case IPSECDOI_ATTR_COMP_DICT_SIZE:
4692 case IPSECDOI_ATTR_COMP_PRIVALG:
4693 default:
4694 break;
4697 prev = d;
4698 if (flag) {
4699 tlen -= sizeof(*d);
4700 d = (struct isakmp_data *)((char *)d + sizeof(*d));
4701 } else {
4702 tlen -= (sizeof(*d) + ntohs(d->lorv));
4703 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
4707 error = 0;
4708 end:
4709 return error;
4713 ipsecdoi_authalg2trnsid(alg)
4714 int alg;
4716 switch (alg) {
4717 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
4718 return IPSECDOI_AH_MD5;
4719 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
4720 return IPSECDOI_AH_SHA;
4721 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
4722 return IPSECDOI_AH_SHA256;
4723 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
4724 return IPSECDOI_AH_SHA384;
4725 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
4726 return IPSECDOI_AH_SHA512;
4727 case IPSECDOI_ATTR_AUTH_DES_MAC:
4728 return IPSECDOI_AH_DES;
4729 case IPSECDOI_ATTR_AUTH_KPDK:
4730 return IPSECDOI_AH_MD5; /* XXX */
4731 default:
4732 plog(LLV_ERROR, LOCATION, NULL,
4733 "invalid authentication algorithm:%d\n", alg);
4735 return -1;
4738 static int rm_idtype2doi[] = {
4739 255, /* IDTYPE_UNDEFINED, 0 */
4740 IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
4741 IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
4742 IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
4743 255, /* IDTYPE_ADDRESS, 4
4744 * it expands into 4 types by another function. */
4745 IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
4749 * convert idtype to DOI value.
4750 * OUT 255 : NG
4751 * other: converted.
4754 idtype2doi(idtype)
4755 int idtype;
4757 if (ARRAYLEN(rm_idtype2doi) > idtype)
4758 return rm_idtype2doi[idtype];
4759 return 255;
4763 doi2idtype(doi)
4764 int doi;
4766 switch(doi) {
4767 case IPSECDOI_ID_FQDN:
4768 return(IDTYPE_FQDN);
4769 case IPSECDOI_ID_USER_FQDN:
4770 return(IDTYPE_USERFQDN);
4771 case IPSECDOI_ID_KEY_ID:
4772 return(IDTYPE_KEYID);
4773 case IPSECDOI_ID_DER_ASN1_DN:
4774 return(IDTYPE_ASN1DN);
4775 case IPSECDOI_ID_IPV4_ADDR:
4776 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4777 case IPSECDOI_ID_IPV6_ADDR:
4778 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4779 return(IDTYPE_ADDRESS);
4780 default:
4781 plog(LLV_WARNING, LOCATION, NULL,
4782 "Inproper idtype:%s in this function.\n",
4783 s_ipsecdoi_ident(doi));
4784 return(IDTYPE_ADDRESS); /* XXX */
4786 /*NOTREACHED*/