1 /* $NetBSD: ipsec_doi.c,v 1.54 2025/03/08 16:39:08 christos Exp $ */
2
3 /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */
4
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
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.
20 *
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.
32 */
33
34 #include "config.h"
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39
40 #include <netinet/in.h>
41
42 #include PATH_IPSEC_H
43
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
59
60 #include "var.h"
61 #include "vmbuf.h"
62 #include "misc.h"
63 #include "plog.h"
64 #include "debug.h"
65
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"
82
83 #ifdef ENABLE_NATT
84 #include "nattraversal.h"
85 #endif
86
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
96
97 static vchar_t *get_ph1approval(struct ph1handle *, uint32_t, uint32_t,
98 struct prop_pair **);
99 static int get_ph1approvalx(struct remoteconf *, void *);
100
101 static int t2isakmpsa(struct isakmp_pl_t *, struct isakmpsa *, uint32_t);
102 static int cmp_aproppair_i(struct prop_pair *, struct prop_pair *);
103 static struct prop_pair *get_ph2approval(struct ph2handle *,
104 struct prop_pair **);
105 static struct prop_pair *get_ph2approvalx(struct ph2handle *,
106 struct prop_pair *);
107 static void free_proppair0(struct prop_pair *);
108 static struct prop_pair ** get_proppair_and_doi_sit(vchar_t *, int,
109 uint32_t *, uint32_t *);
110
111 static int get_transform(struct isakmp_pl_p *, struct prop_pair **, int *);
112 static uint32_t ipsecdoi_set_ld(vchar_t *);
113
114 static int check_doi(uint32_t);
115 static int check_situation(uint32_t);
116
117 static int check_prot_main(int);
118 static int check_prot_quick(int);
119 static int (*check_protocol[])(int) = {
120 check_prot_main, /* IPSECDOI_TYPE_PH1 */
121 check_prot_quick, /* IPSECDOI_TYPE_PH2 */
122 };
123
124 static int check_spi_size(int, int);
125
126 static int check_trns_isakmp(int);
127 static int check_trns_ah(int);
128 static int check_trns_esp(int);
129 static int check_trns_ipcomp(int);
130 static int (*check_transform[])(int) = {
131 0,
132 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
133 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
134 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
135 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
136 };
137
138 static int check_attr_isakmp(struct isakmp_pl_t *);
139 static int check_attr_ah(struct isakmp_pl_t *);
140 static int check_attr_esp(struct isakmp_pl_t *);
141 static int check_attr_ipsec(int, struct isakmp_pl_t *);
142 static int check_attr_ipcomp(struct isakmp_pl_t *);
143 static int (*check_attributes[])(struct isakmp_pl_t *) = {
144 0,
145 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
146 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
147 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
148 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
149 };
150
151 static int setph1prop(struct isakmpsa *, caddr_t);
152 static int setph1trns(struct isakmpsa *, caddr_t);
153 static int setph1attr(struct isakmpsa *, caddr_t);
154 static vchar_t *setph2proposal0(const struct ph2handle *,
155 const struct saprop *, const struct saproto *);
156
157 struct ph1approvalx_ctx {
158 struct prop_pair *p;
159 struct isakmpsa *sa;
160 };
161
162 /*%%%*/
163 /*
164 * check phase 1 SA payload.
165 * make new SA payload to be replyed not including general header.
166 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
167 * OUT:
168 * positive: the pointer to new buffer of SA payload.
169 * network byte order.
170 * NULL : error occurd.
171 */
172 int
ipsecdoi_checkph1proposal(vchar_t * sa,struct ph1handle * iph1)173 ipsecdoi_checkph1proposal(vchar_t *sa, struct ph1handle *iph1)
174 {
175 vchar_t *newsa; /* new SA payload approved. */
176 struct prop_pair **pair;
177 uint32_t doitype, sittype;
178
179 /* get proposal pair */
180 pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1,
181 &doitype, &sittype);
182 if (pair == NULL)
183 return -1;
184
185 /* check and get one SA for use */
186 newsa = get_ph1approval(iph1, doitype, sittype, pair);
187 free_proppair(pair);
188
189 if (newsa == NULL)
190 return -1;
191
192 iph1->sa_ret = newsa;
193 return 0;
194 }
195
196 static void
print_ph1proposal(struct prop_pair * pair,struct isakmpsa * s)197 print_ph1proposal(struct prop_pair *pair, struct isakmpsa *s)
198 {
199 struct isakmp_pl_p *prop = pair->prop;
200 struct isakmp_pl_t *trns = pair->trns;
201
202 plog(LLV_DEBUG, LOCATION, NULL,
203 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
204 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
205 prop->spi_size, prop->num_t);
206 plog(LLV_DEBUG, LOCATION, NULL,
207 "trns#=%d, trns-id=%s\n",
208 trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id));
209 plog(LLV_DEBUG, LOCATION, NULL,
210 " lifetime = %ld\n", (long) s->lifetime);
211 plog(LLV_DEBUG, LOCATION, NULL,
212 " lifebyte = %zu\n", s->lifebyte);
213 plog(LLV_DEBUG, LOCATION, NULL,
214 " enctype = %s\n",
215 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype));
216 plog(LLV_DEBUG, LOCATION, NULL,
217 " encklen = %d\n", s->encklen);
218 plog(LLV_DEBUG, LOCATION, NULL,
219 " hashtype = %s\n",
220 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype));
221 plog(LLV_DEBUG, LOCATION, NULL,
222 " authmethod = %s\n",
223 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod));
224 plog(LLV_DEBUG, LOCATION, NULL,
225 " dh_group = %s\n",
226 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group));
227 }
228
229
230 /*
231 * acceptable check for remote configuration.
232 * return a new SA payload to be reply to peer.
233 */
234
235 static vchar_t *
get_ph1approval(struct ph1handle * iph1,uint32_t doitype,uint32_t sittype,struct prop_pair ** pair)236 get_ph1approval(struct ph1handle *iph1, uint32_t doitype, uint32_t sittype,
237 struct prop_pair **pair)
238 {
239 vchar_t *newsa;
240 struct ph1approvalx_ctx ctx;
241 struct prop_pair *s, *p;
242 struct rmconfselector rmsel;
243 struct isakmpsa *sa;
244 int i;
245
246 memset(&rmsel, 0, sizeof(rmsel));
247 rmsel.remote = iph1->remote;
248
249 if (iph1->approval) {
250 delisakmpsa(iph1->approval);
251 iph1->approval = NULL;
252 }
253
254 for (i = 0; i < MAXPROPPAIRLEN; i++) {
255 if (pair[i] == NULL)
256 continue;
257 for (s = pair[i]; s; s = s->next) {
258 /* compare proposal and select one */
259 for (p = s; p; p = p->tnext) {
260 sa = newisakmpsa();
261 ctx.p = p;
262 ctx.sa = sa;
263 if (t2isakmpsa(p->trns, sa,
264 iph1->vendorid_mask) < 0)
265 continue;
266 print_ph1proposal(p, sa);
267 if (iph1->rmconf != NULL) {
268 if (get_ph1approvalx(iph1->rmconf, &ctx))
269 goto found;
270 } else {
271 if (enumrmconf(&rmsel, get_ph1approvalx, &ctx))
272 goto found;
273 }
274 delisakmpsa(sa);
275 }
276 }
277 }
278
279 plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
280
281 return NULL;
282
283 found:
284 sa = ctx.sa;
285 plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
286
287 /* check DH group settings */
288 if (sa->dhgrp) {
289 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
290 /* it's ok */
291 goto saok;
292 }
293 plog(LLV_WARNING, LOCATION, NULL,
294 "invalid DH parameter found, use default.\n");
295 oakley_dhgrp_free(sa->dhgrp);
296 sa->dhgrp=NULL;
297 }
298
299 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
300 sa->dhgrp = NULL;
301 delisakmpsa(sa);
302 return NULL;
303 }
304
305 saok:
306 #ifdef HAVE_GSSAPI
307 if (sa->gssid != NULL)
308 plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
309 (int)sa->gssid->l, sa->gssid->v);
310 if (iph1->side == INITIATOR) {
311 if (iph1->rmconf->proposal->gssid != NULL)
312 iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
313 if (sa->gssid != NULL)
314 iph1->gi_r = vdup(sa->gssid);
315 } else {
316 if (sa->gssid != NULL) {
317 iph1->gi_r = vdup(sa->gssid);
318 iph1->gi_i = gssapi_get_id(iph1);
319 }
320 }
321 if (iph1->gi_i != NULL)
322 plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
323 (int)iph1->gi_i->l, iph1->gi_i->v);
324 if (iph1->gi_r != NULL)
325 plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
326 (int)iph1->gi_r->l, iph1->gi_r->v);
327 #endif
328 plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
329 s_oakley_attr_method(sa->authmethod));
330
331 newsa = get_sabyproppair(doitype, sittype, p);
332 if (newsa == NULL)
333 delisakmpsa(sa);
334 else
335 iph1->approval = sa;
336
337 return newsa;
338 }
339
340 /*
341 * compare peer's single proposal and all of my proposal.
342 * and select one if suiatable.
343 */
344 static int
get_ph1approvalx(struct remoteconf * rmconf,void * ctx)345 get_ph1approvalx(struct remoteconf *rmconf, void *ctx)
346 {
347 struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx;
348 struct isakmpsa *sa;
349
350 /* do the hard work */
351 sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal);
352 if (sa == NULL)
353 return 0;
354
355 /* duplicate and modify the found SA to match proposal */
356 sa = dupisakmpsa(sa);
357
358 switch (rmconf->pcheck_level) {
359 case PROP_CHECK_OBEY:
360 sa->lifetime = pctx->sa->lifetime;
361 sa->lifebyte = pctx->sa->lifebyte;
362 sa->encklen = pctx->sa->encklen;
363 break;
364 case PROP_CHECK_CLAIM:
365 case PROP_CHECK_STRICT:
366 if (pctx->sa->lifetime < sa->lifetime)
367 sa->lifetime = pctx->sa->lifetime;
368 if (pctx->sa->lifebyte < sa->lifebyte)
369 sa->lifebyte = pctx->sa->lifebyte;
370 if (pctx->sa->encklen > sa->encklen)
371 sa->encklen = pctx->sa->encklen;
372 break;
373 default:
374 break;
375 }
376
377 /* replace the proposal with our approval sa */
378 delisakmpsa(pctx->sa);
379 pctx->sa = sa;
380
381 return 1;
382 }
383
384 /*
385 * get ISAKMP data attributes
386 */
387 static int
t2isakmpsa(struct isakmp_pl_t * trns,struct isakmpsa * sa,uint32_t vendorid_mask)388 t2isakmpsa(struct isakmp_pl_t *trns, struct isakmpsa *sa,
389 uint32_t vendorid_mask)
390 {
391 struct isakmp_data *d, *prev;
392 int flag, type;
393 int error = -1;
394 int life_t;
395 int keylen = 0;
396 vchar_t *val = NULL;
397 int len, tlen;
398 u_char *p;
399
400 tlen = ntohs(trns->h.len) - sizeof(*trns);
401 prev = (struct isakmp_data *)NULL;
402 d = (struct isakmp_data *)(trns + 1);
403
404 /* default */
405 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
406 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
407 sa->lifebyte = 0;
408 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
409 if (!sa->dhgrp)
410 goto err;
411
412 while (tlen > 0) {
413
414 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
415 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
416
417 plog(LLV_DEBUG, LOCATION, NULL,
418 "type=%s, flag=0x%04x, lorv=%s\n",
419 s_oakley_attr(type), flag,
420 s_oakley_attr_v(type, ntohs(d->lorv)));
421
422 /* get variable-sized item */
423 switch (type) {
424 case OAKLEY_ATTR_GRP_PI:
425 case OAKLEY_ATTR_GRP_GEN_ONE:
426 case OAKLEY_ATTR_GRP_GEN_TWO:
427 case OAKLEY_ATTR_GRP_CURVE_A:
428 case OAKLEY_ATTR_GRP_CURVE_B:
429 case OAKLEY_ATTR_SA_LD:
430 case OAKLEY_ATTR_GRP_ORDER:
431 if (flag) { /*TV*/
432 len = 2;
433 p = (u_char *)&d->lorv;
434 } else { /*TLV*/
435 len = ntohs(d->lorv);
436 p = (u_char *)(d + 1);
437 }
438 val = vmalloc(len);
439 if (!val)
440 return -1;
441 memcpy(val->v, p, len);
442 break;
443
444 default:
445 break;
446 }
447
448 switch (type) {
449 case OAKLEY_ATTR_ENC_ALG:
450 sa->enctype = (uint16_t)ntohs(d->lorv);
451 break;
452
453 case OAKLEY_ATTR_HASH_ALG:
454 sa->hashtype = (uint16_t)ntohs(d->lorv);
455 break;
456
457 case OAKLEY_ATTR_AUTH_METHOD:
458 sa->authmethod = ntohs(d->lorv);
459 #ifdef HAVE_GSSAPI
460 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL &&
461 (vendorid_mask & VENDORID_GSSAPI_MASK))
462 sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB;
463 #endif
464 break;
465
466 case OAKLEY_ATTR_GRP_DESC:
467 sa->dh_group = (uint16_t)ntohs(d->lorv);
468 break;
469
470 case OAKLEY_ATTR_GRP_TYPE:
471 {
472 int xtype = (int)ntohs(d->lorv);
473 if (xtype == OAKLEY_ATTR_GRP_TYPE_MODP)
474 sa->dhgrp->type = xtype;
475 else
476 return -1;
477 break;
478 }
479 case OAKLEY_ATTR_GRP_PI:
480 sa->dhgrp->prime = val;
481 break;
482
483 case OAKLEY_ATTR_GRP_GEN_ONE:
484 vfree(val);
485 if (!flag)
486 sa->dhgrp->gen1 = ntohs(d->lorv);
487 else {
488 int xlen = ntohs(d->lorv);
489 sa->dhgrp->gen1 = 0;
490 if (xlen > 4)
491 return -1;
492 memcpy(&sa->dhgrp->gen1, d + 1, xlen);
493 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
494 }
495 break;
496
497 case OAKLEY_ATTR_GRP_GEN_TWO:
498 vfree(val);
499 if (!flag)
500 sa->dhgrp->gen2 = ntohs(d->lorv);
501 else {
502 int xlen = ntohs(d->lorv);
503 sa->dhgrp->gen2 = 0;
504 if (xlen > 4)
505 return -1;
506 memcpy(&sa->dhgrp->gen2, d + 1, xlen);
507 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
508 }
509 break;
510
511 case OAKLEY_ATTR_GRP_CURVE_A:
512 sa->dhgrp->curve_a = val;
513 break;
514
515 case OAKLEY_ATTR_GRP_CURVE_B:
516 sa->dhgrp->curve_b = val;
517 break;
518
519 case OAKLEY_ATTR_SA_LD_TYPE:
520 {
521 int xtype = (int)ntohs(d->lorv);
522 switch (xtype) {
523 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
524 case OAKLEY_ATTR_SA_LD_TYPE_KB:
525 life_t = xtype;
526 break;
527 default:
528 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
529 break;
530 }
531 break;
532 }
533 case OAKLEY_ATTR_SA_LD:
534 if (!prev
535 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
536 OAKLEY_ATTR_SA_LD_TYPE) {
537 plog(LLV_ERROR, LOCATION, NULL,
538 "life duration must follow ltype\n");
539 break;
540 }
541
542 switch (life_t) {
543 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
544 sa->lifetime = ipsecdoi_set_ld(val);
545 vfree(val);
546 if (sa->lifetime == 0) {
547 plog(LLV_ERROR, LOCATION, NULL,
548 "invalid life duration.\n");
549 goto err;
550 }
551 break;
552 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
553 sa->lifebyte = ipsecdoi_set_ld(val);
554 vfree(val);
555 if (sa->lifebyte == 0) {
556 plog(LLV_ERROR, LOCATION, NULL,
557 "invalid life duration.\n");
558 goto err;
559 }
560 break;
561 default:
562 vfree(val);
563 plog(LLV_ERROR, LOCATION, NULL,
564 "invalid life type: %d\n", life_t);
565 goto err;
566 }
567 break;
568
569 case OAKLEY_ATTR_KEY_LEN:
570 {
571 int xlen = ntohs(d->lorv);
572 if (xlen % 8 != 0) {
573 plog(LLV_ERROR, LOCATION, NULL,
574 "keylen %d: not multiple of 8\n",
575 xlen);
576 goto err;
577 }
578 sa->encklen = (uint16_t)xlen;
579 keylen++;
580 break;
581 }
582 case OAKLEY_ATTR_PRF:
583 case OAKLEY_ATTR_FIELD_SIZE:
584 /* unsupported */
585 break;
586
587 case OAKLEY_ATTR_GRP_ORDER:
588 sa->dhgrp->order = val;
589 break;
590 #ifdef HAVE_GSSAPI
591 case OAKLEY_ATTR_GSS_ID:
592 {
593 int xerror = -1;
594 iconv_t cd = (iconv_t) -1;
595 size_t srcleft, dstleft, rv;
596 __iconv_const char *src;
597 char *dst;
598 int xlen = ntohs(d->lorv);
599
600 /*
601 * Older verions of racoon just placed the
602 * ISO-Latin-1 string on the wire directly.
603 * Check to see if we are configured to be
604 * compatible with this behavior.
605 */
606 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
607 if ((sa->gssid = vmalloc(xlen)) == NULL) {
608 plog(LLV_ERROR, LOCATION, NULL,
609 "failed to allocate memory\n");
610 goto out;
611 }
612 memcpy(sa->gssid->v, d + 1, xlen);
613 plog(LLV_DEBUG, LOCATION, NULL,
614 "received old-style gss "
615 "id '%.*s' (len %zu)\n",
616 (int)sa->gssid->l, sa->gssid->v,
617 sa->gssid->l);
618 xerror = 0;
619 goto out;
620 }
621
622 /*
623 * For Windows 2000 compatibility, we expect
624 * the GSS ID attribute on the wire to be
625 * encoded in UTF-16LE. Internally, we work
626 * in ISO-Latin-1. Therefore, we should need
627 * 1/2 the specified length, which should always
628 * be a multiple of 2 octets.
629 */
630 cd = iconv_open("latin1", "utf-16le");
631 if (cd == (iconv_t) -1) {
632 plog(LLV_ERROR, LOCATION, NULL,
633 "unable to initialize utf-16le -> latin1 "
634 "conversion descriptor: %s\n",
635 strerror(errno));
636 goto out;
637 }
638
639 if ((sa->gssid = vmalloc(xlen / 2)) == NULL) {
640 plog(LLV_ERROR, LOCATION, NULL,
641 "failed to allocate memory\n");
642 goto out;
643 }
644
645 src = (__iconv_const char *)(d + 1);
646 srcleft = xlen;
647
648 dst = sa->gssid->v;
649 dstleft = xlen / 2;
650
651 rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
652 &dst, &dstleft);
653 if (rv != 0) {
654 if (rv == (size_t)-1) {
655 plog(LLV_ERROR, LOCATION, NULL,
656 "unable to convert GSS ID from "
657 "utf-16le -> latin1: %s\n",
658 strerror(errno));
659 } else {
660 plog(LLV_ERROR, LOCATION, NULL,
661 "%zd character%s in GSS ID cannot "
662 "be represented in latin1\n",
663 rv, rv == 1 ? "" : "s");
664 }
665 goto out;
666 }
667
668 /* XXX dstleft should always be 0; assert it? */
669 sa->gssid->l = (xlen / 2) - dstleft;
670
671 plog(LLV_DEBUG, LOCATION, NULL,
672 "received gss id '%.*s' (len %zu)\n",
673 (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
674
675 xerror = 0;
676 out:
677 if (cd != (iconv_t)-1)
678 (void)iconv_close(cd);
679
680 if ((xerror != 0) && (sa->gssid != NULL)) {
681 vfree(sa->gssid);
682 sa->gssid = NULL;
683 }
684 break;
685 }
686 #endif /* HAVE_GSSAPI */
687
688 default:
689 break;
690 }
691
692 prev = d;
693 if (flag) {
694 tlen -= sizeof(*d);
695 d = (struct isakmp_data *)((char *)d + sizeof(*d));
696 } else {
697 tlen -= (sizeof(*d) + ntohs(d->lorv));
698 d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
699 }
700 }
701
702 /* key length must not be specified on some algorithms */
703 if (keylen) {
704 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
705 #ifdef HAVE_OPENSSL_IDEA_H
706 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
707 #endif
708 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
709 plog(LLV_ERROR, LOCATION, NULL,
710 "keylen must not be specified "
711 "for encryption algorithm %d\n",
712 sa->enctype);
713 return -1;
714 }
715 }
716
717 return 0;
718 err:
719 return error;
720 }
721
722 /*%%%*/
723 /*
724 * check phase 2 SA payload and select single proposal.
725 * make new SA payload to be replyed not including general header.
726 * This function is called by responder only.
727 * OUT:
728 * 0: succeed.
729 * -1: error occured.
730 */
731 int
ipsecdoi_selectph2proposal(struct ph2handle * iph2)732 ipsecdoi_selectph2proposal(struct ph2handle *iph2)
733 {
734 struct prop_pair **pair;
735 struct prop_pair *ret;
736 uint32_t doitype, sittype;
737
738 /* get proposal pair */
739 pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
740 &doitype, &sittype);
741 if (pair == NULL)
742 return -1;
743
744 /* check and select a proposal. */
745 ret = get_ph2approval(iph2, pair);
746 free_proppair(pair);
747 if (ret == NULL)
748 return -1;
749
750 /* make a SA to be replayed. */
751 /* SPI must be updated later. */
752 iph2->sa_ret = get_sabyproppair(doitype, sittype, ret);
753 free_proppair0(ret);
754 if (iph2->sa_ret == NULL)
755 return -1;
756
757 return 0;
758 }
759
760 /*
761 * check phase 2 SA payload returned from responder.
762 * This function is called by initiator only.
763 * OUT:
764 * 0: valid.
765 * -1: invalid.
766 */
767 int
ipsecdoi_checkph2proposal(struct ph2handle * iph2)768 ipsecdoi_checkph2proposal(struct ph2handle *iph2)
769 {
770 struct prop_pair **rpair = NULL, **spair = NULL;
771 struct prop_pair *p;
772 int i, n, num;
773 int error = -1;
774 vchar_t *sa_ret = NULL;
775 uint32_t doitype, sittype;
776
777 /* get proposal pair of SA sent. */
778 spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
779 &doitype, &sittype);
780 if (spair == NULL) {
781 plog(LLV_ERROR, LOCATION, NULL,
782 "failed to get prop pair.\n");
783 goto end;
784 }
785
786 /* XXX should check the number of transform */
787
788 /* get proposal pair of SA replayed */
789 rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
790 if (rpair == NULL) {
791 plog(LLV_ERROR, LOCATION, NULL,
792 "failed to get prop pair.\n");
793 goto end;
794 }
795
796 /* check proposal is only one ? */
797 n = 0;
798 num = 0;
799 for (i = 0; i < MAXPROPPAIRLEN; i++) {
800 if (rpair[i]) {
801 n = i;
802 num++;
803 }
804 }
805 if (num == 0) {
806 plog(LLV_ERROR, LOCATION, NULL,
807 "no proposal received.\n");
808 goto end;
809 }
810 if (num != 1) {
811 plog(LLV_ERROR, LOCATION, NULL,
812 "some proposals received.\n");
813 goto end;
814 }
815
816 if (spair[n] == NULL) {
817 plog(LLV_WARNING, LOCATION, NULL,
818 "invalid proposal number:%d received.\n", i);
819 }
820
821
822 if (rpair[n]->tnext != NULL) {
823 plog(LLV_ERROR, LOCATION, NULL,
824 "multi transforms replyed.\n");
825 goto end;
826 }
827
828 if (cmp_aproppair_i(rpair[n], spair[n])) {
829 plog(LLV_ERROR, LOCATION, NULL,
830 "proposal mismathed.\n");
831 goto end;
832 }
833
834 /*
835 * check and select a proposal.
836 * ensure that there is no modification of the proposal by
837 * cmp_aproppair_i()
838 */
839 p = get_ph2approval(iph2, rpair);
840 if (p == NULL)
841 goto end;
842
843 /* make a SA to be replayed. */
844 sa_ret = iph2->sa_ret;
845 iph2->sa_ret = get_sabyproppair(doitype, sittype, p);
846 free_proppair0(p);
847 if (iph2->sa_ret == NULL)
848 goto end;
849
850 error = 0;
851
852 end:
853 if (rpair)
854 free_proppair(rpair);
855 if (spair)
856 free_proppair(spair);
857 if (sa_ret)
858 vfree(sa_ret);
859
860 return error;
861 }
862
863 /*
864 * compare two prop_pair which is assumed to have same proposal number.
865 * the case of bundle or single SA, NOT multi transforms.
866 * a: a proposal that is multi protocols and single transform, usually replyed.
867 * b: a proposal that is multi protocols and multi transform, usually sent.
868 * NOTE: this function is for initiator.
869 * OUT
870 * 0: equal
871 * 1: not equal
872 * XXX cannot understand the comment!
873 */
874 static int
cmp_aproppair_i(struct prop_pair * a,struct prop_pair * b)875 cmp_aproppair_i(struct prop_pair *a, struct prop_pair *b)
876 {
877 struct prop_pair *p, *q, *r;
878 int len;
879
880 for (p = a, q = b; p && q; p = p->next, q = q->next) {
881 for (r = q; r; r = r->tnext) {
882 /* compare trns */
883 if (p->trns->t_no == r->trns->t_no)
884 break;
885 }
886 if (!r) {
887 /* no suitable transform found */
888 plog(LLV_ERROR, LOCATION, NULL,
889 "no suitable transform found.\n");
890 return -1;
891 }
892
893 /* compare prop */
894 if (p->prop->p_no != r->prop->p_no) {
895 plog(LLV_WARNING, LOCATION, NULL,
896 "proposal #%d mismatched, "
897 "expected #%d.\n",
898 r->prop->p_no, p->prop->p_no);
899 /*FALLTHROUGH*/
900 }
901
902 if (p->prop->proto_id != r->prop->proto_id) {
903 plog(LLV_ERROR, LOCATION, NULL,
904 "proto_id mismathed: my:%d peer:%d\n",
905 r->prop->proto_id, p->prop->proto_id);
906 return -1;
907 }
908
909 if (p->prop->spi_size != r->prop->spi_size) {
910 plog(LLV_ERROR, LOCATION, NULL,
911 "invalid spi size: %d.\n",
912 p->prop->spi_size);
913 return -1;
914 }
915
916 /* check #of transforms */
917 if (p->prop->num_t != 1) {
918 plog(LLV_WARNING, LOCATION, NULL,
919 "#of transform is %d, "
920 "but expected 1.\n", p->prop->num_t);
921 /*FALLTHROUGH*/
922 }
923
924 if (p->trns->t_id != r->trns->t_id) {
925 plog(LLV_WARNING, LOCATION, NULL,
926 "transform number has been modified.\n");
927 /*FALLTHROUGH*/
928 }
929 if (p->trns->reserved != r->trns->reserved) {
930 plog(LLV_WARNING, LOCATION, NULL,
931 "reserved field should be zero.\n");
932 /*FALLTHROUGH*/
933 }
934
935 /* compare attribute */
936 len = ntohs(r->trns->h.len) - sizeof(*p->trns);
937 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
938 plog(LLV_WARNING, LOCATION, NULL,
939 "attribute has been modified.\n");
940 /*FALLTHROUGH*/
941 }
942 }
943 if ((p && !q) || (!p && q)) {
944 /* # of protocols mismatched */
945 plog(LLV_ERROR, LOCATION, NULL,
946 "#of protocols mismatched.\n");
947 return -1;
948 }
949
950 return 0;
951 }
952
953 /*
954 * acceptable check for policy configuration.
955 * return a new SA payload to be reply to peer.
956 */
957 static struct prop_pair *
get_ph2approval(struct ph2handle * iph2,struct prop_pair ** pair)958 get_ph2approval(struct ph2handle *iph2, struct prop_pair **pair)
959 {
960 struct prop_pair *ret;
961 int i;
962
963 iph2->approval = NULL;
964
965 plog(LLV_DEBUG, LOCATION, NULL,
966 "begin compare proposals.\n");
967
968 for (i = 0; i < MAXPROPPAIRLEN; i++) {
969 if (pair[i] == NULL)
970 continue;
971 plog(LLV_DEBUG, LOCATION, NULL,
972 "pair[%d]: %p\n", i, pair[i]);
973 print_proppair(LLV_DEBUG, pair[i]);
974
975 /* compare proposal and select one */
976 ret = get_ph2approvalx(iph2, pair[i]);
977 if (ret != NULL) {
978 /* found */
979 return ret;
980 }
981 }
982
983 plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
984
985 return NULL;
986 }
987
988 /*
989 * compare my proposal and peers just one proposal.
990 * set a approval.
991 */
992 static struct prop_pair *
get_ph2approvalx(struct ph2handle * iph2,struct prop_pair * pp)993 get_ph2approvalx(struct ph2handle *iph2, struct prop_pair *pp)
994 {
995 struct prop_pair *ret = NULL;
996 struct saprop *pr0, *pr = NULL;
997 struct saprop *q1, *q2;
998
999 pr0 = aproppair2saprop(pp);
1000 if (pr0 == NULL)
1001 return NULL;
1002
1003 for (q1 = pr0; q1; q1 = q1->next) {
1004 for (q2 = iph2->proposal; q2; q2 = q2->next) {
1005 plog(LLV_DEBUG, LOCATION, NULL,
1006 "peer's single bundle:\n");
1007 printsaprop0(LLV_DEBUG, q1);
1008 plog(LLV_DEBUG, LOCATION, NULL,
1009 "my single bundle:\n");
1010 printsaprop0(LLV_DEBUG, q2);
1011
1012 pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1013 if (pr != NULL)
1014 goto found;
1015
1016 plog(LLV_ERROR, LOCATION, NULL,
1017 "not matched\n");
1018 }
1019 }
1020 /* no proposal matching */
1021 err:
1022 flushsaprop(pr0);
1023 return NULL;
1024
1025 found:
1026 flushsaprop(pr0);
1027 plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
1028 iph2->approval = pr;
1029
1030 {
1031 struct saproto *sp;
1032 struct prop_pair *p, *x;
1033 struct prop_pair *n = NULL;
1034
1035 ret = NULL;
1036
1037 for (p = pp; p; p = p->next) {
1038 /*
1039 * find a proposal with matching proto_id.
1040 * we have analyzed validity already, in cmpsaprop_alloc().
1041 */
1042 for (sp = pr->head; sp; sp = sp->next) {
1043 if (sp->proto_id == p->prop->proto_id)
1044 break;
1045 }
1046 if (!sp)
1047 goto err;
1048 if (sp->head->next)
1049 goto err; /* XXX */
1050
1051 for (x = p; x; x = x->tnext)
1052 if (sp->head->trns_no == x->trns->t_no)
1053 break;
1054 if (!x)
1055 goto err; /* XXX */
1056
1057 n = racoon_calloc(1, sizeof(struct prop_pair));
1058 if (n == NULL) {
1059 plog(LLV_ERROR, LOCATION, NULL,
1060 "failed to get buffer.\n");
1061 goto err;
1062 }
1063
1064 n->prop = x->prop;
1065 n->trns = x->trns;
1066
1067 /* need to preserve the order */
1068 for (x = ret; x && x->next; x = x->next)
1069 ;
1070 if (x && x->prop == n->prop) {
1071 for (/*nothing*/; x && x->tnext; x = x->tnext)
1072 ;
1073 x->tnext = n;
1074 } else {
1075 if (x)
1076 x->next = n;
1077 else {
1078 ret = n;
1079 }
1080 }
1081
1082 /* #of transforms should be updated ? */
1083 }
1084 }
1085
1086 return ret;
1087 }
1088
1089 void
free_proppair(struct prop_pair ** pair)1090 free_proppair(struct prop_pair **pair)
1091 {
1092 int i;
1093
1094 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1095 free_proppair0(pair[i]);
1096 pair[i] = NULL;
1097 }
1098 racoon_free(pair);
1099 }
1100
1101 static void
free_proppair0(struct prop_pair * pair)1102 free_proppair0(struct prop_pair *pair)
1103 {
1104 struct prop_pair *p, *q, *r, *s;
1105
1106 p = pair;
1107 while (p) {
1108 q = p->next;
1109 r = p;
1110 while (r) {
1111 s = r->tnext;
1112 racoon_free(r);
1113 r = s;
1114 }
1115 p = q;
1116 }
1117 }
1118
1119 /*
1120 * get proposal pairs from SA payload.
1121 * tiny check for proposal payload.
1122 */
1123 static struct prop_pair **
get_proppair_and_doi_sit(vchar_t * sa,int mode,uint32_t * doitype,uint32_t * sittype)1124 get_proppair_and_doi_sit(vchar_t *sa, int mode, uint32_t *doitype,
1125 uint32_t *sittype)
1126 {
1127 struct prop_pair **pair = NULL;
1128 int num_p = 0; /* number of proposal for use */
1129 size_t tlen;
1130 caddr_t bp;
1131 int i;
1132 struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
1133
1134 plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
1135 plogdump(LLV_DEBUG, sa->v, sa->l);
1136
1137 /* check SA payload size */
1138 if (sa->l < sizeof(*sab)) {
1139 plog(LLV_ERROR, LOCATION, NULL,
1140 "Invalid SA length = %zu.\n", sa->l);
1141 goto bad;
1142 }
1143
1144 /* check DOI */
1145 if (check_doi(ntohl(sab->doi)) < 0)
1146 goto bad;
1147 if (doitype != NULL)
1148 *doitype = ntohl(sab->doi);
1149
1150 /* check SITUATION */
1151 if (check_situation(ntohl(sab->sit)) < 0)
1152 goto bad;
1153 if (sittype != NULL)
1154 *sittype = ntohl(sab->sit);
1155
1156 pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1157 if (pair == NULL) {
1158 plog(LLV_ERROR, LOCATION, NULL,
1159 "failed to get buffer.\n");
1160 goto bad;
1161 }
1162
1163 bp = (caddr_t)(sab + 1);
1164 tlen = sa->l - sizeof(*sab);
1165
1166 {
1167 struct isakmp_pl_p *prop;
1168 int proplen;
1169 vchar_t *pbuf = NULL;
1170 struct isakmp_parse_t *pa;
1171
1172 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1173 if (pbuf == NULL)
1174 goto bad;
1175
1176 for (pa = (struct isakmp_parse_t *)pbuf->v;
1177 pa->type != ISAKMP_NPTYPE_NONE;
1178 pa++) {
1179 /* check the value of next payload */
1180 if (pa->type != ISAKMP_NPTYPE_P) {
1181 plog(LLV_ERROR, LOCATION, NULL,
1182 "Invalid payload type=%u\n", pa->type);
1183 vfree(pbuf);
1184 goto bad;
1185 }
1186
1187 prop = (struct isakmp_pl_p *)pa->ptr;
1188 proplen = pa->len;
1189
1190 plog(LLV_DEBUG, LOCATION, NULL,
1191 "proposal #%u len=%d\n", prop->p_no, proplen);
1192
1193 if (proplen == 0) {
1194 plog(LLV_ERROR, LOCATION, NULL,
1195 "invalid proposal with length %d\n", proplen);
1196 vfree(pbuf);
1197 goto bad;
1198 }
1199
1200 /* check Protocol ID */
1201 if (!check_protocol[mode]) {
1202 plog(LLV_ERROR, LOCATION, NULL,
1203 "unsupported mode %d\n", mode);
1204 continue;
1205 }
1206
1207 if (check_protocol[mode](prop->proto_id) < 0)
1208 continue;
1209
1210 /* check SPI length when IKE. */
1211 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1212 continue;
1213
1214 /* get transform */
1215 if (get_transform(prop, pair, &num_p) < 0) {
1216 vfree(pbuf);
1217 goto bad;
1218 }
1219 }
1220 vfree(pbuf);
1221 pbuf = NULL;
1222 }
1223
1224 {
1225 int notrans, nprop;
1226 struct prop_pair *p, *q;
1227
1228 /* check for proposals with no transforms */
1229 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1230 if (!pair[i])
1231 continue;
1232
1233 plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
1234 print_proppair(LLV_DEBUG, pair[i]);
1235
1236 notrans = nprop = 0;
1237 for (p = pair[i]; p; p = p->next) {
1238 if (p->trns == NULL) {
1239 notrans++;
1240 break;
1241 }
1242 for (q = p; q; q = q->tnext)
1243 nprop++;
1244 }
1245
1246 #if 0
1247 /*
1248 * XXX at this moment, we cannot accept proposal group
1249 * with multiple proposals. this should be fixed.
1250 */
1251 if (pair[i]->next) {
1252 plog(LLV_WARNING, LOCATION, NULL,
1253 "proposal #%u ignored "
1254 "(multiple proposal not supported)\n",
1255 pair[i]->prop->p_no);
1256 notrans++;
1257 }
1258 #endif
1259
1260 if (notrans) {
1261 for (p = pair[i]; p; p = q) {
1262 q = p->next;
1263 racoon_free(p);
1264 }
1265 pair[i] = NULL;
1266 num_p--;
1267 } else {
1268 plog(LLV_DEBUG, LOCATION, NULL,
1269 "proposal #%u: %d transform\n",
1270 pair[i]->prop->p_no, nprop);
1271 }
1272 }
1273 }
1274
1275 /* bark if no proposal is found. */
1276 if (num_p <= 0) {
1277 plog(LLV_ERROR, LOCATION, NULL,
1278 "no Proposal found.\n");
1279 goto bad;
1280 }
1281
1282 return pair;
1283 bad:
1284 if (pair != NULL)
1285 racoon_free(pair);
1286 return NULL;
1287 }
1288
1289 struct prop_pair **
get_proppair(vchar_t * sa,int mode)1290 get_proppair(vchar_t *sa, int mode)
1291 {
1292 return get_proppair_and_doi_sit(sa, mode, NULL, NULL);
1293 }
1294
1295
1296 /*
1297 * check transform payload.
1298 * OUT:
1299 * positive: return the pointer to the payload of valid transform.
1300 * 0 : No valid transform found.
1301 */
1302 static int
get_transform(struct isakmp_pl_p * prop,struct prop_pair ** pair,int * num_p)1303 get_transform(struct isakmp_pl_p *prop, struct prop_pair **pair, int *num_p)
1304 {
1305 int tlen; /* total length of all transform in a proposal */
1306 caddr_t bp;
1307 struct isakmp_pl_t *trns;
1308 int trnslen;
1309 vchar_t *pbuf = NULL;
1310 struct isakmp_parse_t *pa;
1311 struct prop_pair *p = NULL, *q;
1312 int num_t;
1313
1314 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1315 tlen = ntohs(prop->h.len)
1316 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1317 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1318 if (pbuf == NULL)
1319 return -1;
1320
1321 /* check and get transform for use */
1322 num_t = 0;
1323 for (pa = (struct isakmp_parse_t *)pbuf->v;
1324 pa->type != ISAKMP_NPTYPE_NONE;
1325 pa++) {
1326
1327 num_t++;
1328
1329 /* check the value of next payload */
1330 if (pa->type != ISAKMP_NPTYPE_T) {
1331 plog(LLV_ERROR, LOCATION, NULL,
1332 "Invalid payload type=%u\n", pa->type);
1333 break;
1334 }
1335
1336 trns = (struct isakmp_pl_t *)pa->ptr;
1337 trnslen = pa->len;
1338
1339 plog(LLV_DEBUG, LOCATION, NULL,
1340 "transform #%u len=%u\n", trns->t_no, trnslen);
1341
1342 /* check transform ID */
1343 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1344 plog(LLV_WARNING, LOCATION, NULL,
1345 "unsupported proto_id %u\n",
1346 prop->proto_id);
1347 continue;
1348 }
1349 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1350 plog(LLV_WARNING, LOCATION, NULL,
1351 "unsupported proto_id %u\n",
1352 prop->proto_id);
1353 continue;
1354 }
1355
1356 if (!check_transform[prop->proto_id]
1357 || !check_attributes[prop->proto_id]) {
1358 plog(LLV_WARNING, LOCATION, NULL,
1359 "unsupported proto_id %u\n",
1360 prop->proto_id);
1361 continue;
1362 }
1363 if (check_transform[prop->proto_id](trns->t_id) < 0)
1364 continue;
1365
1366 /* check data attributes */
1367 if (check_attributes[prop->proto_id](trns) != 0)
1368 continue;
1369
1370 p = racoon_calloc(1, sizeof(*p));
1371 if (p == NULL) {
1372 plog(LLV_ERROR, LOCATION, NULL,
1373 "failed to get buffer.\n");
1374 vfree(pbuf);
1375 return -1;
1376 }
1377 p->prop = prop;
1378 p->trns = trns;
1379
1380 /* need to preserve the order */
1381 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1382 ;
1383 if (q && q->prop == p->prop) {
1384 for (/*nothing*/; q && q->tnext; q = q->tnext)
1385 ;
1386 q->tnext = p;
1387 } else {
1388 if (q)
1389 q->next = p;
1390 else {
1391 pair[prop->p_no] = p;
1392 (*num_p)++;
1393 }
1394 }
1395 }
1396
1397 vfree(pbuf);
1398
1399 return 0;
1400 }
1401
1402 /*
1403 * make a new SA payload from prop_pair.
1404 * NOTE: this function make spi value clear.
1405 */
1406 vchar_t *
get_sabyproppair(uint32_t doitype,uint32_t sittype,struct prop_pair * pair)1407 get_sabyproppair(uint32_t doitype, uint32_t sittype, struct prop_pair *pair)
1408 {
1409 vchar_t *newsa;
1410 int newtlen;
1411 uint8_t *np_p = NULL;
1412 struct prop_pair *p;
1413 int prophlen, trnslen;
1414 caddr_t bp;
1415
1416 newtlen = sizeof(struct ipsecdoi_sa_b);
1417 for (p = pair; p; p = p->next) {
1418 newtlen += sizeof(struct isakmp_pl_p);
1419 newtlen += p->prop->spi_size;
1420 newtlen += ntohs(p->trns->h.len);
1421 }
1422
1423 newsa = vmalloc(newtlen);
1424 if (newsa == NULL) {
1425 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1426 return NULL;
1427 }
1428 bp = newsa->v;
1429
1430 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1431
1432 /* update some of values in SA header */
1433 ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype);
1434 ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype);
1435 bp += sizeof(struct ipsecdoi_sa_b);
1436
1437 /* create proposal payloads */
1438 for (p = pair; p; p = p->next) {
1439 prophlen = sizeof(struct isakmp_pl_p)
1440 + p->prop->spi_size;
1441 trnslen = ntohs(p->trns->h.len);
1442
1443 if (np_p)
1444 *np_p = ISAKMP_NPTYPE_P;
1445
1446 /* create proposal */
1447
1448 memcpy(bp, p->prop, prophlen);
1449 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1450 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1451 ((struct isakmp_pl_p *)bp)->num_t = 1;
1452 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1453 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1454 bp += prophlen;
1455
1456 /* create transform */
1457 memcpy(bp, p->trns, trnslen);
1458 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1459 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1460 bp += trnslen;
1461 }
1462
1463 return newsa;
1464 }
1465
1466 /*
1467 * update responder's spi
1468 */
1469 int
ipsecdoi_updatespi(struct ph2handle * iph2)1470 ipsecdoi_updatespi(struct ph2handle *iph2)
1471 {
1472 struct prop_pair **pair, *p;
1473 struct saprop *pp;
1474 struct saproto *pr;
1475 int i;
1476 int error = -1;
1477 uint8_t *spi;
1478
1479 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1480 if (pair == NULL)
1481 return -1;
1482 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1483 if (pair[i])
1484 break;
1485 }
1486 if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1487 /* multiple transform must be filtered by selectph2proposal.*/
1488 goto end;
1489 }
1490
1491 pp = iph2->approval;
1492
1493 /* create proposal payloads */
1494 for (p = pair[i]; p; p = p->next) {
1495 /*
1496 * find a proposal/transform with matching proto_id/t_id.
1497 * we have analyzed validity already, in cmpsaprop_alloc().
1498 */
1499 for (pr = pp->head; pr; pr = pr->next) {
1500 if (p->prop->proto_id == pr->proto_id &&
1501 p->trns->t_id == pr->head->trns_id) {
1502 break;
1503 }
1504 }
1505 if (!pr)
1506 goto end;
1507
1508 /*
1509 * XXX SPI bits are left-filled, for use with IPComp.
1510 * we should be switching to variable-length spi field...
1511 */
1512 spi = (uint8_t *)&pr->spi;
1513 spi += sizeof(pr->spi);
1514 spi -= pr->spisize;
1515 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1516 }
1517
1518 error = 0;
1519 end:
1520 free_proppair(pair);
1521 return error;
1522 }
1523
1524 /*
1525 * make a new SA payload from prop_pair.
1526 */
1527 vchar_t *
get_sabysaprop(struct saprop * pp0,vchar_t * sa0)1528 get_sabysaprop(struct saprop *pp0, vchar_t *sa0)
1529 {
1530 struct prop_pair **pair = NULL;
1531 vchar_t *newsa = NULL;
1532 size_t newtlen;
1533 uint8_t *np_p = NULL;
1534 struct prop_pair *p = NULL;
1535 struct saprop *pp;
1536 struct saproto *pr;
1537 struct satrns *tr;
1538 int prophlen, trnslen;
1539 caddr_t bp;
1540 int error = -1;
1541
1542 /* get proposal pair */
1543 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1544 if (pair == NULL)
1545 goto out;
1546
1547 newtlen = sizeof(struct ipsecdoi_sa_b);
1548 for (pp = pp0; pp; pp = pp->next) {
1549
1550 if (pair[pp->prop_no] == NULL)
1551 goto out;
1552
1553 for (pr = pp->head; pr; pr = pr->next) {
1554 newtlen += (sizeof(struct isakmp_pl_p)
1555 + pr->spisize);
1556
1557 for (tr = pr->head; tr; tr = tr->next) {
1558 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1559 if (tr->trns_no == p->trns->t_no)
1560 break;
1561 }
1562 if (p == NULL)
1563 goto out;
1564
1565 newtlen += ntohs(p->trns->h.len);
1566 }
1567 }
1568 }
1569
1570 newsa = vmalloc(newtlen);
1571 if (newsa == NULL) {
1572 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1573 goto out;
1574 }
1575 bp = newsa->v;
1576
1577 /* some of values of SA must be updated in the out of this function */
1578 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1579 bp += sizeof(struct ipsecdoi_sa_b);
1580
1581 /* create proposal payloads */
1582 for (pp = pp0; pp; pp = pp->next) {
1583
1584 for (pr = pp->head; pr; pr = pr->next) {
1585 prophlen = sizeof(struct isakmp_pl_p)
1586 + p->prop->spi_size;
1587
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;
1592 }
1593 if (p == NULL)
1594 goto out;
1595
1596 trnslen = ntohs(p->trns->h.len);
1597
1598 if (np_p)
1599 *np_p = ISAKMP_NPTYPE_P;
1600
1601 /* create proposal */
1602
1603 memcpy(bp, p->prop, prophlen);
1604 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1605 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1606 ((struct isakmp_pl_p *)bp)->num_t = 1;
1607 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1608 bp += prophlen;
1609
1610 /* create transform */
1611 memcpy(bp, p->trns, trnslen);
1612 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1613 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1614 bp += trnslen;
1615 }
1616 }
1617 }
1618
1619 error = 0;
1620 out:
1621 if (pair != NULL)
1622 racoon_free(pair);
1623
1624 if (error != 0) {
1625 if (newsa != NULL) {
1626 vfree(newsa);
1627 newsa = NULL;
1628 }
1629 }
1630
1631 return newsa;
1632 }
1633
1634 /*
1635 * If some error happens then return 0. Although 0 means that lifetime is zero,
1636 * such a value should not be accepted.
1637 * Also 0 of lifebyte should not be included in a packet although 0 means not
1638 * to care of it.
1639 */
1640 static uint32_t
ipsecdoi_set_ld(vchar_t * buf)1641 ipsecdoi_set_ld(vchar_t *buf)
1642 {
1643 uint32_t ld;
1644
1645 if (buf == 0)
1646 return 0;
1647
1648 switch (buf->l) {
1649 case 2:
1650 ld = ntohs(*(uint16_t *)buf->v);
1651 break;
1652 case 4:
1653 ld = ntohl(*(uint32_t *)buf->v);
1654 break;
1655 default:
1656 plog(LLV_ERROR, LOCATION, NULL,
1657 "length %zu of life duration "
1658 "isn't supported.\n", buf->l);
1659 return 0;
1660 }
1661
1662 return ld;
1663 }
1664
1665 /*
1666 * parse responder-lifetime attributes from payload
1667 */
1668 int
ipsecdoi_parse_responder_lifetime(struct isakmp_pl_n * notify,uint32_t * lifetime_sec,uint32_t * lifetime_kb)1669 ipsecdoi_parse_responder_lifetime(struct isakmp_pl_n *notify,
1670 uint32_t *lifetime_sec, uint32_t *lifetime_kb)
1671 {
1672 struct isakmp_data *d;
1673 int flag, type, tlen, ld_type = -1;
1674 uint16_t lorv;
1675 uint32_t value;
1676
1677 tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
1678 d = (struct isakmp_data *)((char *)(notify + 1) +
1679 notify->spi_size);
1680
1681 while (tlen >= sizeof(struct isakmp_data)) {
1682 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
1683 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
1684 lorv = ntohs(d->lorv);
1685
1686 plog(LLV_DEBUG, LOCATION, NULL,
1687 "type=%s, flag=0x%04x, lorv=%s\n",
1688 s_ipsecdoi_attr(type), flag,
1689 s_ipsecdoi_attr_v(type, lorv));
1690
1691 switch (type) {
1692 case IPSECDOI_ATTR_SA_LD_TYPE:
1693 if (! flag) {
1694 plog(LLV_ERROR, LOCATION, NULL,
1695 "must be TV when LD_TYPE.\n");
1696 return -1;
1697 }
1698 ld_type = lorv;
1699 break;
1700 case IPSECDOI_ATTR_SA_LD:
1701 if (flag)
1702 value = lorv;
1703 else if (lorv == 2)
1704 value = ntohs(*(uint16_t *)(d + 1));
1705 else if (lorv == 4)
1706 value = ntohl(*(uint32_t *)(d + 1));
1707 else {
1708 plog(LLV_ERROR, LOCATION, NULL,
1709 "payload length %d for lifetime "
1710 "data length is unsupported.\n", lorv);
1711 return -1;
1712 }
1713
1714 switch (ld_type) {
1715 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
1716 if (lifetime_sec != NULL)
1717 *lifetime_sec = value;
1718 plog(LLV_INFO, LOCATION, NULL,
1719 "received RESPONDER-LIFETIME: %d "
1720 "seconds\n", value);
1721 break;
1722 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
1723 if (lifetime_kb != NULL)
1724 *lifetime_kb = value;
1725 plog(LLV_INFO, LOCATION, NULL,
1726 "received RESPONDER-LIFETIME: %d "
1727 "kbytes\n", value);
1728 break;
1729 default:
1730 plog(LLV_ERROR, LOCATION, NULL,
1731 "lifetime data received without "
1732 "lifetime data type.\n");
1733 return -1;
1734 }
1735 break;
1736 }
1737
1738 if (flag) {
1739 tlen -= sizeof(*d);
1740 d = (struct isakmp_data *)((char *)d
1741 + sizeof(*d));
1742 } else {
1743 tlen -= (sizeof(*d) + lorv);
1744 d = (struct isakmp_data *)((char *)d
1745 + sizeof(*d) + lorv);
1746 }
1747 }
1748
1749 return 0;
1750 }
1751
1752
1753 /*%%%*/
1754 /*
1755 * check DOI
1756 */
1757 static int
check_doi(uint32_t doi)1758 check_doi(uint32_t doi)
1759 {
1760 switch (doi) {
1761 case IPSEC_DOI:
1762 return 0;
1763 default:
1764 plog(LLV_ERROR, LOCATION, NULL,
1765 "invalid value of DOI 0x%08x.\n", doi);
1766 return -1;
1767 }
1768 /* NOT REACHED */
1769 }
1770
1771 /*
1772 * check situation
1773 */
1774 static int
check_situation(uint32_t sit)1775 check_situation(uint32_t sit)
1776 {
1777 switch (sit) {
1778 case IPSECDOI_SIT_IDENTITY_ONLY:
1779 return 0;
1780
1781 case IPSECDOI_SIT_SECRECY:
1782 case IPSECDOI_SIT_INTEGRITY:
1783 plog(LLV_ERROR, LOCATION, NULL,
1784 "situation 0x%08x unsupported yet.\n", sit);
1785 return -1;
1786
1787 default:
1788 plog(LLV_ERROR, LOCATION, NULL,
1789 "invalid situation 0x%08x.\n", sit);
1790 return -1;
1791 }
1792 /* NOT REACHED */
1793 }
1794
1795 /*
1796 * check protocol id in main mode
1797 */
1798 static int
check_prot_main(int proto_id)1799 check_prot_main(int proto_id)
1800 {
1801 switch (proto_id) {
1802 case IPSECDOI_PROTO_ISAKMP:
1803 return 0;
1804
1805 default:
1806 plog(LLV_ERROR, LOCATION, NULL,
1807 "Illegal protocol id=%u.\n", proto_id);
1808 return -1;
1809 }
1810 /* NOT REACHED */
1811 }
1812
1813 /*
1814 * check protocol id in quick mode
1815 */
1816 static int
check_prot_quick(int proto_id)1817 check_prot_quick(int proto_id)
1818 {
1819 switch (proto_id) {
1820 case IPSECDOI_PROTO_IPSEC_AH:
1821 case IPSECDOI_PROTO_IPSEC_ESP:
1822 return 0;
1823
1824 case IPSECDOI_PROTO_IPCOMP:
1825 return 0;
1826
1827 default:
1828 plog(LLV_ERROR, LOCATION, NULL,
1829 "invalid protocol id %d.\n", proto_id);
1830 return -1;
1831 }
1832 /* NOT REACHED */
1833 }
1834
1835 static int
check_spi_size(int proto_id,int size)1836 check_spi_size(int proto_id, int size)
1837 {
1838 switch (proto_id) {
1839 case IPSECDOI_PROTO_ISAKMP:
1840 if (size != 0) {
1841 /* WARNING */
1842 plog(LLV_WARNING, LOCATION, NULL,
1843 "SPI size isn't zero, but IKE proposal.\n");
1844 }
1845 return 0;
1846
1847 case IPSECDOI_PROTO_IPSEC_AH:
1848 case IPSECDOI_PROTO_IPSEC_ESP:
1849 if (size != 4) {
1850 plog(LLV_ERROR, LOCATION, NULL,
1851 "invalid SPI size=%d for IPSEC proposal.\n",
1852 size);
1853 return -1;
1854 }
1855 return 0;
1856
1857 case IPSECDOI_PROTO_IPCOMP:
1858 if (size != 2 && size != 4) {
1859 plog(LLV_ERROR, LOCATION, NULL,
1860 "invalid SPI size=%d for IPCOMP proposal.\n",
1861 size);
1862 return -1;
1863 }
1864 return 0;
1865
1866 default:
1867 /* ??? */
1868 return -1;
1869 }
1870 /* NOT REACHED */
1871 }
1872
1873 /*
1874 * check transform ID in ISAKMP.
1875 */
1876 static int
check_trns_isakmp(int t_id)1877 check_trns_isakmp(int t_id)
1878 {
1879 switch (t_id) {
1880 case IPSECDOI_KEY_IKE:
1881 return 0;
1882 default:
1883 plog(LLV_ERROR, LOCATION, NULL,
1884 "invalid transform-id=%u in proto_id=%u.\n",
1885 t_id, IPSECDOI_KEY_IKE);
1886 return -1;
1887 }
1888 /* NOT REACHED */
1889 }
1890
1891 /*
1892 * check transform ID in AH.
1893 */
1894 static int
check_trns_ah(int t_id)1895 check_trns_ah(int t_id)
1896 {
1897 switch (t_id) {
1898 case IPSECDOI_AH_MD5:
1899 case IPSECDOI_AH_SHA:
1900 case IPSECDOI_AH_SHA256:
1901 case IPSECDOI_AH_SHA384:
1902 case IPSECDOI_AH_SHA512:
1903 return 0;
1904 case IPSECDOI_AH_DES:
1905 plog(LLV_ERROR, LOCATION, NULL,
1906 "not support transform-id=%u in AH.\n", t_id);
1907 return -1;
1908 default:
1909 plog(LLV_ERROR, LOCATION, NULL,
1910 "invalid transform-id=%u in AH.\n", t_id);
1911 return -1;
1912 }
1913 /* NOT REACHED */
1914 }
1915
1916 /*
1917 * check transform ID in ESP.
1918 */
1919 static int
check_trns_esp(int t_id)1920 check_trns_esp(int t_id)
1921 {
1922 switch (t_id) {
1923 case IPSECDOI_ESP_DES:
1924 case IPSECDOI_ESP_3DES:
1925 case IPSECDOI_ESP_NULL:
1926 case IPSECDOI_ESP_RC5:
1927 case IPSECDOI_ESP_CAST:
1928 case IPSECDOI_ESP_BLOWFISH:
1929 case IPSECDOI_ESP_AES:
1930 case IPSECDOI_ESP_AESGCM16:
1931 case IPSECDOI_ESP_TWOFISH:
1932 case IPSECDOI_ESP_CAMELLIA:
1933 return 0;
1934 case IPSECDOI_ESP_DES_IV32:
1935 case IPSECDOI_ESP_DES_IV64:
1936 case IPSECDOI_ESP_IDEA:
1937 case IPSECDOI_ESP_3IDEA:
1938 case IPSECDOI_ESP_RC4:
1939 plog(LLV_ERROR, LOCATION, NULL,
1940 "not support transform-id=%u in ESP.\n", t_id);
1941 return -1;
1942 default:
1943 plog(LLV_ERROR, LOCATION, NULL,
1944 "invalid transform-id=%u in ESP.\n", t_id);
1945 return -1;
1946 }
1947 /* NOT REACHED */
1948 }
1949
1950 /*
1951 * check transform ID in IPCOMP.
1952 */
1953 static int
check_trns_ipcomp(int t_id)1954 check_trns_ipcomp(int t_id)
1955 {
1956 switch (t_id) {
1957 case IPSECDOI_IPCOMP_OUI:
1958 case IPSECDOI_IPCOMP_DEFLATE:
1959 case IPSECDOI_IPCOMP_LZS:
1960 return 0;
1961 default:
1962 plog(LLV_ERROR, LOCATION, NULL,
1963 "invalid transform-id=%u in IPCOMP.\n", t_id);
1964 return -1;
1965 }
1966 /* NOT REACHED */
1967 }
1968
1969 /*
1970 * check data attributes in IKE.
1971 */
1972 static int
check_attr_isakmp(struct isakmp_pl_t * trns)1973 check_attr_isakmp(struct isakmp_pl_t *trns)
1974 {
1975 struct isakmp_data *d;
1976 int tlen;
1977 int flag, type;
1978 uint16_t lorv;
1979
1980 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
1981 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
1982
1983 while (tlen > 0) {
1984 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
1985 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
1986 lorv = ntohs(d->lorv);
1987
1988 plog(LLV_DEBUG, LOCATION, NULL,
1989 "type=%s, flag=0x%04x, lorv=%s\n",
1990 s_oakley_attr(type), flag,
1991 s_oakley_attr_v(type, lorv));
1992
1993 /*
1994 * some of the attributes must be encoded in TV.
1995 * see RFC2409 Appendix A "Attribute Classes".
1996 */
1997 switch (type) {
1998 case OAKLEY_ATTR_ENC_ALG:
1999 case OAKLEY_ATTR_HASH_ALG:
2000 case OAKLEY_ATTR_AUTH_METHOD:
2001 case OAKLEY_ATTR_GRP_DESC:
2002 case OAKLEY_ATTR_GRP_TYPE:
2003 case OAKLEY_ATTR_SA_LD_TYPE:
2004 case OAKLEY_ATTR_PRF:
2005 case OAKLEY_ATTR_KEY_LEN:
2006 case OAKLEY_ATTR_FIELD_SIZE:
2007 if (!flag) { /* TLV*/
2008 plog(LLV_ERROR, LOCATION, NULL,
2009 "oakley attribute %d must be TV.\n",
2010 type);
2011 return -1;
2012 }
2013 break;
2014 }
2015
2016 /* sanity check for TLV. length must be specified. */
2017 if (!flag && lorv == 0) { /*TLV*/
2018 plog(LLV_ERROR, LOCATION, NULL,
2019 "invalid length %d for TLV attribute %d.\n",
2020 lorv, type);
2021 return -1;
2022 }
2023
2024 switch (type) {
2025 case OAKLEY_ATTR_ENC_ALG:
2026 if (!alg_oakley_encdef_ok(lorv)) {
2027 plog(LLV_ERROR, LOCATION, NULL,
2028 "invalied encryption algorithm=%d.\n",
2029 lorv);
2030 return -1;
2031 }
2032 break;
2033
2034 case OAKLEY_ATTR_HASH_ALG:
2035 if (!alg_oakley_hashdef_ok(lorv)) {
2036 plog(LLV_ERROR, LOCATION, NULL,
2037 "invalied hash algorithm=%d.\n",
2038 lorv);
2039 return -1;
2040 }
2041 break;
2042
2043 case OAKLEY_ATTR_AUTH_METHOD:
2044 switch (lorv) {
2045 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2046 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2047 #ifdef ENABLE_HYBRID
2048 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2049 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2050 #endif
2051 #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
2052 /* These two authentication method IDs overlap. */
2053 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2054 /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
2055 #endif
2056 break;
2057 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2058 #ifdef ENABLE_HYBRID
2059 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2060 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2061 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2062 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2063 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
2064 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2065 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2066 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2067 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2068 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2069 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
2070 #endif
2071 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2072 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2073 plog(LLV_ERROR, LOCATION, NULL,
2074 "auth method %s isn't supported.\n",
2075 s_oakley_attr_method(lorv));
2076 return -1;
2077 default:
2078 plog(LLV_ERROR, LOCATION, NULL,
2079 "invalid auth method %d.\n",
2080 lorv);
2081 return -1;
2082 }
2083 break;
2084
2085 case OAKLEY_ATTR_GRP_DESC:
2086 if (!alg_oakley_dhdef_ok(lorv)) {
2087 plog(LLV_ERROR, LOCATION, NULL,
2088 "invalid DH group %d.\n",
2089 lorv);
2090 return -1;
2091 }
2092 break;
2093
2094 case OAKLEY_ATTR_GRP_TYPE:
2095 switch (lorv) {
2096 case OAKLEY_ATTR_GRP_TYPE_MODP:
2097 break;
2098 default:
2099 plog(LLV_ERROR, LOCATION, NULL,
2100 "unsupported DH group type %d.\n",
2101 lorv);
2102 return -1;
2103 }
2104 break;
2105
2106 case OAKLEY_ATTR_GRP_PI:
2107 case OAKLEY_ATTR_GRP_GEN_ONE:
2108 /* sanity checks? */
2109 break;
2110
2111 case OAKLEY_ATTR_GRP_GEN_TWO:
2112 case OAKLEY_ATTR_GRP_CURVE_A:
2113 case OAKLEY_ATTR_GRP_CURVE_B:
2114 plog(LLV_ERROR, LOCATION, NULL,
2115 "attr type=%u isn't supported.\n", type);
2116 return -1;
2117
2118 case OAKLEY_ATTR_SA_LD_TYPE:
2119 switch (lorv) {
2120 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2121 case OAKLEY_ATTR_SA_LD_TYPE_KB:
2122 break;
2123 default:
2124 plog(LLV_ERROR, LOCATION, NULL,
2125 "invalid life type: %d.\n", lorv);
2126 return -1;
2127 }
2128 break;
2129
2130 case OAKLEY_ATTR_SA_LD:
2131 /* should check the value */
2132 break;
2133
2134 case OAKLEY_ATTR_PRF:
2135 case OAKLEY_ATTR_KEY_LEN:
2136 break;
2137
2138 case OAKLEY_ATTR_FIELD_SIZE:
2139 plog(LLV_ERROR, LOCATION, NULL,
2140 "attr type=%u isn't supported.\n", type);
2141 return -1;
2142
2143 case OAKLEY_ATTR_GRP_ORDER:
2144 break;
2145
2146 case OAKLEY_ATTR_GSS_ID:
2147 break;
2148
2149 default:
2150 plog(LLV_ERROR, LOCATION, NULL,
2151 "invalid attribute type %d.\n", type);
2152 return -1;
2153 }
2154
2155 if (flag) {
2156 tlen -= sizeof(*d);
2157 d = (struct isakmp_data *)((char *)d
2158 + sizeof(*d));
2159 } else {
2160 tlen -= (sizeof(*d) + lorv);
2161 d = (struct isakmp_data *)((char *)d
2162 + sizeof(*d) + lorv);
2163 }
2164 }
2165
2166 return 0;
2167 }
2168
2169 /*
2170 * check data attributes in IPSEC AH/ESP.
2171 */
2172 static int
check_attr_ah(struct isakmp_pl_t * trns)2173 check_attr_ah(struct isakmp_pl_t *trns)
2174 {
2175 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2176 }
2177
2178 static int
check_attr_esp(struct isakmp_pl_t * trns)2179 check_attr_esp(struct isakmp_pl_t *trns)
2180 {
2181 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2182 }
2183
2184 static int
check_attr_ipsec(int proto_id,struct isakmp_pl_t * trns)2185 check_attr_ipsec(int proto_id, struct isakmp_pl_t *trns)
2186 {
2187 struct isakmp_data *d;
2188 int tlen;
2189 int flag, type = 0;
2190 uint16_t lorv;
2191 int attrseen[16]; /* XXX magic number */
2192
2193 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2194 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2195 memset(attrseen, 0, sizeof(attrseen));
2196
2197 while (tlen > 0) {
2198 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2199 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2200 lorv = ntohs(d->lorv);
2201
2202 plog(LLV_DEBUG, LOCATION, NULL,
2203 "type=%s, flag=0x%04x, lorv=%s\n",
2204 s_ipsecdoi_attr(type), flag,
2205 s_ipsecdoi_attr_v(type, lorv));
2206
2207 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2208 attrseen[type]++;
2209
2210 switch (type) {
2211 case IPSECDOI_ATTR_ENC_MODE:
2212 if (! flag) {
2213 plog(LLV_ERROR, LOCATION, NULL,
2214 "must be TV when ENC_MODE.\n");
2215 return -1;
2216 }
2217
2218 switch (lorv) {
2219 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2220 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2221 break;
2222 #ifdef ENABLE_NATT
2223 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2224 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2225 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2226 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2227 plog(LLV_DEBUG, LOCATION, NULL,
2228 "UDP encapsulation requested\n");
2229 break;
2230 #endif
2231 default:
2232 plog(LLV_ERROR, LOCATION, NULL,
2233 "invalid encryption mode=%u.\n",
2234 lorv);
2235 return -1;
2236 }
2237 break;
2238
2239 case IPSECDOI_ATTR_AUTH:
2240 if (! flag) {
2241 plog(LLV_ERROR, LOCATION, NULL,
2242 "must be TV when AUTH.\n");
2243 return -1;
2244 }
2245
2246 switch (lorv) {
2247 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2248 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2249 trns->t_id != IPSECDOI_AH_MD5) {
2250 ahmismatch:
2251 plog(LLV_ERROR, LOCATION, NULL,
2252 "auth algorithm %u conflicts "
2253 "with transform %u.\n",
2254 lorv, trns->t_id);
2255 return -1;
2256 }
2257 break;
2258 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2259 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2260 if (trns->t_id != IPSECDOI_AH_SHA)
2261 goto ahmismatch;
2262 }
2263 break;
2264 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2265 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2266 if (trns->t_id != IPSECDOI_AH_SHA256)
2267 goto ahmismatch;
2268 }
2269 break;
2270 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2271 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2272 if (trns->t_id != IPSECDOI_AH_SHA384)
2273 goto ahmismatch;
2274 }
2275 break;
2276 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2277 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2278 if (trns->t_id != IPSECDOI_AH_SHA512)
2279 goto ahmismatch;
2280 }
2281 break;
2282 case IPSECDOI_ATTR_AUTH_DES_MAC:
2283 case IPSECDOI_ATTR_AUTH_KPDK:
2284 plog(LLV_ERROR, LOCATION, NULL,
2285 "auth algorithm %u isn't supported.\n",
2286 lorv);
2287 return -1;
2288 default:
2289 plog(LLV_ERROR, LOCATION, NULL,
2290 "invalid auth algorithm=%u.\n",
2291 lorv);
2292 return -1;
2293 }
2294 break;
2295
2296 case IPSECDOI_ATTR_SA_LD_TYPE:
2297 if (! flag) {
2298 plog(LLV_ERROR, LOCATION, NULL,
2299 "must be TV when LD_TYPE.\n");
2300 return -1;
2301 }
2302
2303 switch (lorv) {
2304 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2305 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2306 break;
2307 default:
2308 plog(LLV_ERROR, LOCATION, NULL,
2309 "invalid life type %d.\n", lorv);
2310 return -1;
2311 }
2312 break;
2313
2314 case IPSECDOI_ATTR_SA_LD:
2315 if (flag) {
2316 /* i.e. ISAKMP_GEN_TV */
2317 plog(LLV_DEBUG, LOCATION, NULL,
2318 "life duration was in TLV.\n");
2319 } else {
2320 /* i.e. ISAKMP_GEN_TLV */
2321 if (lorv == 0) {
2322 plog(LLV_ERROR, LOCATION, NULL,
2323 "invalid length of LD\n");
2324 return -1;
2325 }
2326 }
2327 break;
2328
2329 case IPSECDOI_ATTR_GRP_DESC:
2330 if (! flag) {
2331 plog(LLV_ERROR, LOCATION, NULL,
2332 "must be TV when GRP_DESC.\n");
2333 return -1;
2334 }
2335
2336 if (!alg_oakley_dhdef_ok(lorv)) {
2337 plog(LLV_ERROR, LOCATION, NULL,
2338 "invalid group description=%u.\n",
2339 lorv);
2340 return -1;
2341 }
2342 break;
2343
2344 case IPSECDOI_ATTR_KEY_LENGTH:
2345 if (! flag) {
2346 plog(LLV_ERROR, LOCATION, NULL,
2347 "must be TV when KEY_LENGTH.\n");
2348 return -1;
2349 }
2350 break;
2351
2352 #ifdef HAVE_SECCTX
2353 case IPSECDOI_ATTR_SECCTX:
2354 if (flag) {
2355 plog(LLV_ERROR, LOCATION, NULL,
2356 "SECCTX must be in TLV.\n");
2357 return -1;
2358 }
2359 break;
2360 #endif
2361
2362 case IPSECDOI_ATTR_KEY_ROUNDS:
2363 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2364 case IPSECDOI_ATTR_COMP_PRIVALG:
2365 plog(LLV_ERROR, LOCATION, NULL,
2366 "attr type=%u isn't supported.\n", type);
2367 return -1;
2368
2369 default:
2370 plog(LLV_ERROR, LOCATION, NULL,
2371 "invalid attribute type %d.\n", type);
2372 return -1;
2373 }
2374
2375 if (flag) {
2376 tlen -= sizeof(*d);
2377 d = (struct isakmp_data *)((char *)d
2378 + sizeof(*d));
2379 } else {
2380 tlen -= (sizeof(*d) + lorv);
2381 d = (struct isakmp_data *)((caddr_t)d
2382 + sizeof(*d) + lorv);
2383 }
2384 }
2385
2386 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2387 !attrseen[IPSECDOI_ATTR_AUTH]) {
2388 plog(LLV_ERROR, LOCATION, NULL,
2389 "attr AUTH must be present for AH.\n");
2390 return -1;
2391 }
2392
2393 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2394 trns->t_id == IPSECDOI_ESP_NULL &&
2395 !attrseen[IPSECDOI_ATTR_AUTH]) {
2396 plog(LLV_ERROR, LOCATION, NULL,
2397 "attr AUTH must be present for ESP NULL encryption.\n");
2398 return -1;
2399 }
2400
2401 return 0;
2402 }
2403
2404 static int
check_attr_ipcomp(struct isakmp_pl_t * trns)2405 check_attr_ipcomp(struct isakmp_pl_t *trns)
2406 {
2407 struct isakmp_data *d;
2408 int tlen;
2409 int flag, type = 0;
2410 uint16_t lorv;
2411 int attrseen[16]; /* XXX magic number */
2412
2413 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2414 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2415 memset(attrseen, 0, sizeof(attrseen));
2416
2417 while (tlen > 0) {
2418 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2419 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2420 lorv = ntohs(d->lorv);
2421
2422 plog(LLV_DEBUG, LOCATION, NULL,
2423 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2424 type, flag, lorv);
2425
2426 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2427 attrseen[type]++;
2428
2429 switch (type) {
2430 case IPSECDOI_ATTR_ENC_MODE:
2431 if (! flag) {
2432 plog(LLV_ERROR, LOCATION, NULL,
2433 "must be TV when ENC_MODE.\n");
2434 return -1;
2435 }
2436
2437 switch (lorv) {
2438 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2439 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2440 break;
2441 #ifdef ENABLE_NATT
2442 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2443 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2444 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2445 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2446 plog(LLV_DEBUG, LOCATION, NULL,
2447 "UDP encapsulation requested\n");
2448 break;
2449 #endif
2450 default:
2451 plog(LLV_ERROR, LOCATION, NULL,
2452 "invalid encryption mode=%u.\n",
2453 lorv);
2454 return -1;
2455 }
2456 break;
2457
2458 case IPSECDOI_ATTR_SA_LD_TYPE:
2459 if (! flag) {
2460 plog(LLV_ERROR, LOCATION, NULL,
2461 "must be TV when LD_TYPE.\n");
2462 return -1;
2463 }
2464
2465 switch (lorv) {
2466 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2467 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2468 break;
2469 default:
2470 plog(LLV_ERROR, LOCATION, NULL,
2471 "invalid life type %d.\n", lorv);
2472 return -1;
2473 }
2474 break;
2475
2476 case IPSECDOI_ATTR_SA_LD:
2477 if (flag) {
2478 /* i.e. ISAKMP_GEN_TV */
2479 plog(LLV_DEBUG, LOCATION, NULL,
2480 "life duration was in TLV.\n");
2481 } else {
2482 /* i.e. ISAKMP_GEN_TLV */
2483 if (lorv == 0) {
2484 plog(LLV_ERROR, LOCATION, NULL,
2485 "invalid length of LD\n");
2486 return -1;
2487 }
2488 }
2489 break;
2490
2491 case IPSECDOI_ATTR_GRP_DESC:
2492 if (! flag) {
2493 plog(LLV_ERROR, LOCATION, NULL,
2494 "must be TV when GRP_DESC.\n");
2495 return -1;
2496 }
2497
2498 if (!alg_oakley_dhdef_ok(lorv)) {
2499 plog(LLV_ERROR, LOCATION, NULL,
2500 "invalid group description=%u.\n",
2501 lorv);
2502 return -1;
2503 }
2504 break;
2505
2506 case IPSECDOI_ATTR_AUTH:
2507 plog(LLV_ERROR, LOCATION, NULL,
2508 "invalid attr type=%u.\n", type);
2509 return -1;
2510
2511 case IPSECDOI_ATTR_KEY_LENGTH:
2512 case IPSECDOI_ATTR_KEY_ROUNDS:
2513 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2514 case IPSECDOI_ATTR_COMP_PRIVALG:
2515 plog(LLV_ERROR, LOCATION, NULL,
2516 "attr type=%u isn't supported.\n", type);
2517 return -1;
2518
2519 default:
2520 plog(LLV_ERROR, LOCATION, NULL,
2521 "invalid attribute type %d.\n", type);
2522 return -1;
2523 }
2524
2525 if (flag) {
2526 tlen -= sizeof(*d);
2527 d = (struct isakmp_data *)((char *)d
2528 + sizeof(*d));
2529 } else {
2530 tlen -= (sizeof(*d) + lorv);
2531 d = (struct isakmp_data *)((caddr_t)d
2532 + sizeof(*d) + lorv);
2533 }
2534 }
2535
2536 #if 0
2537 if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2538 !attrseen[IPSECDOI_ATTR_AUTH]) {
2539 plog(LLV_ERROR, LOCATION, NULL,
2540 "attr AUTH must be present for AH.\n", type);
2541 return -1;
2542 }
2543 #endif
2544
2545 return 0;
2546 }
2547
2548 /* %%% */
2549 /*
2550 * create phase1 proposal from remote configuration.
2551 * NOT INCLUDING isakmp general header of SA payload
2552 */
2553 vchar_t *
ipsecdoi_setph1proposal(struct remoteconf * rmconf,struct isakmpsa * props)2554 ipsecdoi_setph1proposal(struct remoteconf *rmconf, struct isakmpsa *props)
2555 {
2556 vchar_t *mysa;
2557 int sablen;
2558
2559 /* count total size of SA minus isakmp general header */
2560 /* not including isakmp general header of SA payload */
2561 sablen = sizeof(struct ipsecdoi_sa_b);
2562 sablen += setph1prop(props, NULL);
2563
2564 mysa = vmalloc(sablen);
2565 if (mysa == NULL) {
2566 plog(LLV_ERROR, LOCATION, NULL,
2567 "failed to allocate my sa buffer\n");
2568 return NULL;
2569 }
2570
2571 /* create SA payload */
2572 /* not including isakmp general header */
2573 ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
2574 ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
2575
2576 (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2577
2578 return mysa;
2579 }
2580
2581 static int
setph1prop(struct isakmpsa * props,caddr_t buf)2582 setph1prop(struct isakmpsa *props, caddr_t buf)
2583 {
2584 struct isakmp_pl_p *prop = NULL;
2585 struct isakmpsa *s = NULL;
2586 int proplen, trnslen;
2587 uint8_t *np_t; /* pointer next trns type in previous header */
2588 int trns_num;
2589 caddr_t p = buf;
2590
2591 proplen = sizeof(*prop);
2592 if (buf) {
2593 /* create proposal */
2594 prop = (struct isakmp_pl_p *)p;
2595 prop->h.np = ISAKMP_NPTYPE_NONE;
2596 prop->p_no = props->prop_no;
2597 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2598 prop->spi_size = 0;
2599 p += sizeof(*prop);
2600 }
2601
2602 np_t = NULL;
2603 trns_num = 0;
2604
2605 for (s = props; s != NULL; s = s->next) {
2606 if (np_t)
2607 *np_t = ISAKMP_NPTYPE_T;
2608
2609 trnslen = setph1trns(s, p);
2610 proplen += trnslen;
2611 if (buf) {
2612 /* save buffer to pre-next payload */
2613 np_t = &((struct isakmp_pl_t *)p)->h.np;
2614 p += trnslen;
2615
2616 /* count up transform length */
2617 trns_num++;
2618 }
2619 }
2620
2621 /* update proposal length */
2622 if (buf) {
2623 prop->h.len = htons(proplen);
2624 prop->num_t = trns_num;
2625 }
2626
2627 return proplen;
2628 }
2629
2630 static int
setph1trns(struct isakmpsa * sa,caddr_t buf)2631 setph1trns(struct isakmpsa *sa, caddr_t buf)
2632 {
2633 struct isakmp_pl_t *trns = NULL;
2634 int trnslen, attrlen;
2635 caddr_t p = buf;
2636
2637 trnslen = sizeof(*trns);
2638 if (buf) {
2639 /* create transform */
2640 trns = (struct isakmp_pl_t *)p;
2641 trns->h.np = ISAKMP_NPTYPE_NONE;
2642 trns->t_no = sa->trns_no;
2643 trns->t_id = IPSECDOI_KEY_IKE;
2644 p += sizeof(*trns);
2645 }
2646
2647 attrlen = setph1attr(sa, p);
2648 trnslen += attrlen;
2649 if (buf)
2650 p += attrlen;
2651
2652 if (buf)
2653 trns->h.len = htons(trnslen);
2654
2655 return trnslen;
2656 }
2657
2658 static int
setph1attr(struct isakmpsa * sa,caddr_t buf)2659 setph1attr(struct isakmpsa *sa, caddr_t buf)
2660 {
2661 caddr_t p = buf;
2662 int attrlen = 0;
2663
2664 if (sa->lifetime) {
2665 uint32_t lifetime = htonl((uint32_t)sa->lifetime);
2666
2667 attrlen += sizeof(struct isakmp_data)
2668 + sizeof(struct isakmp_data);
2669 if (sa->lifetime > 0xffff)
2670 attrlen += sizeof(lifetime);
2671 if (buf) {
2672 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2673 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2674 if (sa->lifetime > 0xffff) {
2675 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2676 (caddr_t)&lifetime,
2677 sizeof(lifetime));
2678 } else {
2679 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2680 sa->lifetime);
2681 }
2682 }
2683 }
2684
2685 if (sa->lifebyte) {
2686 uint32_t lifebyte = htonl((uint32_t)sa->lifebyte);
2687
2688 attrlen += sizeof(struct isakmp_data)
2689 + sizeof(struct isakmp_data);
2690 if (sa->lifebyte > 0xffff)
2691 attrlen += sizeof(lifebyte);
2692 if (buf) {
2693 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2694 OAKLEY_ATTR_SA_LD_TYPE_KB);
2695 if (sa->lifebyte > 0xffff) {
2696 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2697 (caddr_t)&lifebyte,
2698 sizeof(lifebyte));
2699 } else {
2700 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2701 sa->lifebyte);
2702 }
2703 }
2704 }
2705
2706 if (sa->enctype) {
2707 attrlen += sizeof(struct isakmp_data);
2708 if (buf)
2709 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2710 }
2711 if (sa->encklen) {
2712 attrlen += sizeof(struct isakmp_data);
2713 if (buf)
2714 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2715 }
2716 if (sa->authmethod) {
2717 int authmethod;
2718
2719 authmethod = isakmpsa_switch_authmethod(sa->authmethod);
2720 authmethod &= 0xffff;
2721 attrlen += sizeof(struct isakmp_data);
2722 if (buf)
2723 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
2724 }
2725 if (sa->hashtype) {
2726 attrlen += sizeof(struct isakmp_data);
2727 if (buf)
2728 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2729 }
2730 switch (sa->dh_group) {
2731 case OAKLEY_ATTR_GRP_DESC_MODP768:
2732 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2733 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2734 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2735 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2736 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2737 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2738 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2739 /* don't attach group type for known groups */
2740 attrlen += sizeof(struct isakmp_data);
2741 if (buf) {
2742 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2743 sa->dh_group);
2744 }
2745 break;
2746 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2747 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2748 /* don't attach group type for known groups */
2749 attrlen += sizeof(struct isakmp_data);
2750 if (buf) {
2751 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2752 OAKLEY_ATTR_GRP_TYPE_EC2N);
2753 }
2754 break;
2755 case 0:
2756 default:
2757 break;
2758 }
2759
2760 #ifdef HAVE_GSSAPI
2761 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2762 sa->gssid != NULL) {
2763 attrlen += sizeof(struct isakmp_data);
2764 /*
2765 * Older versions of racoon just placed the ISO-Latin-1
2766 * string on the wire directly. Check to see if we are
2767 * configured to be compatible with this behavior. Otherwise,
2768 * we encode the GSS ID as UTF-16LE for Windows 2000
2769 * compatibility, which requires twice the number of octets.
2770 */
2771 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
2772 attrlen += sa->gssid->l;
2773 else
2774 attrlen += sa->gssid->l * 2;
2775 if (buf) {
2776 plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
2777 "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
2778 sa->gssid->v);
2779 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
2780 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2781 (caddr_t)sa->gssid->v,
2782 sa->gssid->l);
2783 } else {
2784 size_t dstleft = sa->gssid->l * 2;
2785 size_t srcleft = sa->gssid->l;
2786 const char *src = (const char *)sa->gssid->v;
2787 char *odst, *dst = racoon_malloc(dstleft);
2788 iconv_t cd;
2789 size_t rv;
2790
2791 cd = iconv_open("utf-16le", "latin1");
2792 if (cd == (iconv_t) -1) {
2793 plog(LLV_ERROR, LOCATION, NULL,
2794 "unable to initialize "
2795 "latin1 -> utf-16le "
2796 "converstion descriptor: %s\n",
2797 strerror(errno));
2798 attrlen -= sa->gssid->l * 2;
2799 goto gssid_done;
2800 }
2801 odst = dst;
2802 rv = iconv(cd, (__iconv_const char **)(intptr_t)&src,
2803 &srcleft, &dst, &dstleft);
2804 if (rv != 0) {
2805 if (rv == (size_t)-1) {
2806 plog(LLV_ERROR, LOCATION, NULL,
2807 "unable to convert GSS ID "
2808 "from latin1 -> utf-16le: "
2809 "%s\n", strerror(errno));
2810 } else {
2811 /* should never happen */
2812 plog(LLV_ERROR, LOCATION, NULL,
2813 "%zd character%s in GSS ID "
2814 "cannot be represented "
2815 "in utf-16le\n",
2816 rv, rv == 1 ? "" : "s");
2817 }
2818 (void) iconv_close(cd);
2819 attrlen -= sa->gssid->l * 2;
2820 goto gssid_done;
2821 }
2822 (void) iconv_close(cd);
2823
2824 /* XXX Check srcleft and dstleft? */
2825
2826 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2827 odst, sa->gssid->l * 2);
2828
2829 racoon_free(odst);
2830 }
2831 }
2832 }
2833 gssid_done:
2834 #endif /* HAVE_GSSAPI */
2835
2836 return attrlen;
2837 }
2838
2839 static vchar_t *
setph2proposal0(const struct ph2handle * iph2,const struct saprop * pp,const struct saproto * pr)2840 setph2proposal0(const struct ph2handle *iph2, const struct saprop *pp,
2841 const struct saproto *pr)
2842 {
2843 vchar_t *p;
2844 struct isakmp_pl_p *prop;
2845 struct isakmp_pl_t *trns;
2846 struct satrns *tr;
2847 int attrlen;
2848 size_t trnsoff;
2849 caddr_t x;
2850 uint8_t *np_t; /* pointer next trns type in previous header */
2851 const uint8_t *spi;
2852 #ifdef HAVE_SECCTX
2853 int truectxlen = 0;
2854 #endif
2855
2856 p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2857 if (p == NULL)
2858 return NULL;
2859
2860 /* create proposal */
2861 prop = (struct isakmp_pl_p *)p->v;
2862 prop->h.np = ISAKMP_NPTYPE_NONE;
2863 prop->p_no = pp->prop_no;
2864 prop->proto_id = pr->proto_id;
2865 prop->num_t = 1;
2866
2867 spi = (const uint8_t *)&pr->spi;
2868 switch (pr->proto_id) {
2869 case IPSECDOI_PROTO_IPCOMP:
2870 /*
2871 * draft-shacham-ippcp-rfc2393bis-05.txt:
2872 * construct 16bit SPI (CPI).
2873 * XXX we may need to provide a configuration option to
2874 * generate 32bit SPI. otherwise we cannot interoeprate
2875 * with nodes that uses 32bit SPI, in case we are initiator.
2876 */
2877 prop->spi_size = sizeof(uint16_t);
2878 spi += sizeof(pr->spi) - sizeof(uint16_t);
2879 p->l -= sizeof(pr->spi);
2880 p->l += sizeof(uint16_t);
2881 break;
2882 default:
2883 prop->spi_size = sizeof(pr->spi);
2884 break;
2885 }
2886 memcpy(prop + 1, spi, prop->spi_size);
2887
2888 /* create transform */
2889 trnsoff = sizeof(*prop) + prop->spi_size;
2890 np_t = NULL;
2891
2892 for (tr = pr->head; tr; tr = tr->next) {
2893
2894 switch (pr->proto_id) {
2895 case IPSECDOI_PROTO_IPSEC_ESP:
2896 /*
2897 * don't build a null encryption
2898 * with no authentication transform.
2899 */
2900 if (tr->trns_id == IPSECDOI_ESP_NULL &&
2901 tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
2902 continue;
2903 break;
2904 }
2905
2906 if (np_t) {
2907 *np_t = ISAKMP_NPTYPE_T;
2908 prop->num_t++;
2909 }
2910
2911 /* get attribute length */
2912 attrlen = 0;
2913 if (pp->lifetime) {
2914 attrlen += sizeof(struct isakmp_data)
2915 + sizeof(struct isakmp_data);
2916 if (pp->lifetime > 0xffff)
2917 attrlen += sizeof(uint32_t);
2918 }
2919 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2920 attrlen += sizeof(struct isakmp_data)
2921 + sizeof(struct isakmp_data);
2922 if (pp->lifebyte > 0xffff)
2923 attrlen += sizeof(uint32_t);
2924 }
2925 attrlen += sizeof(struct isakmp_data); /* enc mode */
2926 if (tr->encklen)
2927 attrlen += sizeof(struct isakmp_data);
2928
2929 switch (pr->proto_id) {
2930 case IPSECDOI_PROTO_IPSEC_ESP:
2931 /* non authentication mode ? */
2932 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2933 attrlen += sizeof(struct isakmp_data);
2934 break;
2935 case IPSECDOI_PROTO_IPSEC_AH:
2936 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
2937 plog(LLV_ERROR, LOCATION, NULL,
2938 "no authentication algorithm found "
2939 "but protocol is AH.\n");
2940 vfree(p);
2941 return NULL;
2942 }
2943 attrlen += sizeof(struct isakmp_data);
2944 break;
2945 case IPSECDOI_PROTO_IPCOMP:
2946 break;
2947 default:
2948 plog(LLV_ERROR, LOCATION, NULL,
2949 "invalid protocol: %d\n", pr->proto_id);
2950 vfree(p);
2951 return NULL;
2952 }
2953
2954 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
2955 attrlen += sizeof(struct isakmp_data);
2956
2957 #ifdef HAVE_SECCTX
2958 /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
2959 * The string may be smaller than MAX_CTXSTR_SIZ.
2960 */
2961 if (*pp->sctx.ctx_str) {
2962 truectxlen = sizeof(struct security_ctx) -
2963 (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
2964 attrlen += sizeof(struct isakmp_data) + truectxlen;
2965 }
2966 #endif /* HAVE_SECCTX */
2967
2968 p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
2969 if (p == NULL)
2970 return NULL;
2971 prop = (struct isakmp_pl_p *)p->v;
2972
2973 /* set transform's values */
2974 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2975 trns->h.np = ISAKMP_NPTYPE_NONE;
2976 trns->t_no = tr->trns_no;
2977 trns->t_id = tr->trns_id;
2978
2979 /* set attributes */
2980 x = p->v + trnsoff + sizeof(*trns);
2981
2982 if (pp->lifetime) {
2983 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2984 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
2985 if (pp->lifetime > 0xffff) {
2986 uint32_t v = htonl((uint32_t)pp->lifetime);
2987 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2988 (caddr_t)&v, sizeof(v));
2989 } else {
2990 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2991 pp->lifetime);
2992 }
2993 }
2994
2995 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2996 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2997 IPSECDOI_ATTR_SA_LD_TYPE_KB);
2998 if (pp->lifebyte > 0xffff) {
2999 uint32_t v = htonl((uint32_t)pp->lifebyte);
3000 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3001 (caddr_t)&v, sizeof(v));
3002 } else {
3003 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3004 pp->lifebyte);
3005 }
3006 }
3007
3008 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
3009
3010 if (tr->encklen)
3011 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
3012
3013 /* mandatory check has done above. */
3014 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3015 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
3016 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
3017
3018 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3019 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
3020 iph2->sainfo->pfs_group);
3021
3022 #ifdef HAVE_SECCTX
3023 if (*pp->sctx.ctx_str) {
3024 struct security_ctx secctx;
3025 secctx = pp->sctx;
3026 secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
3027 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
3028 (caddr_t)&secctx, truectxlen);
3029 }
3030 #endif
3031 /* update length of this transform. */
3032 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3033 trns->h.len = htons(sizeof(*trns) + attrlen);
3034
3035 /* save buffer to pre-next payload */
3036 np_t = &trns->h.np;
3037
3038 trnsoff += (sizeof(*trns) + attrlen);
3039 }
3040
3041 if (np_t == NULL) {
3042 plog(LLV_ERROR, LOCATION, NULL,
3043 "no suitable proposal was created.\n");
3044 return NULL;
3045 }
3046
3047 /* update length of this protocol. */
3048 prop->h.len = htons(p->l);
3049
3050 return p;
3051 }
3052
3053 /*
3054 * create phase2 proposal from policy configuration.
3055 * NOT INCLUDING isakmp general header of SA payload.
3056 * This function is called by initiator only.
3057 */
3058 int
ipsecdoi_setph2proposal(struct ph2handle * iph2)3059 ipsecdoi_setph2proposal(struct ph2handle *iph2)
3060 {
3061 struct saprop *proposal, *a;
3062 struct saproto *b = NULL;
3063 vchar_t *q;
3064 struct ipsecdoi_sa_b *sab;
3065 struct isakmp_pl_p *prop;
3066 size_t propoff; /* for previous field of type of next payload. */
3067
3068 proposal = iph2->proposal;
3069
3070 iph2->sa = vmalloc(sizeof(*sab));
3071 if (iph2->sa == NULL) {
3072 plog(LLV_ERROR, LOCATION, NULL,
3073 "failed to allocate my sa buffer\n");
3074 return -1;
3075 }
3076
3077 /* create SA payload */
3078 sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
3079 sab->doi = htonl(IPSEC_DOI);
3080 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
3081
3082 prop = NULL;
3083 propoff = 0;
3084 for (a = proposal; a; a = a->next) {
3085 for (b = a->head; b; b = b->next) {
3086 #ifdef ENABLE_NATT
3087 if (iph2->ph1->natt_flags & NAT_DETECTED) {
3088 int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
3089 plog (LLV_INFO, LOCATION, NULL,
3090 "NAT detected -> UDP encapsulation "
3091 "(ENC_MODE %d->%d).\n",
3092 b->encmode,
3093 b->encmode+udp_diff);
3094 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3095 b->encmode += udp_diff;
3096 b->udp_encap = 1;
3097 }
3098 #endif
3099
3100 q = setph2proposal0(iph2, a, b);
3101 if (q == NULL) {
3102 VPTRINIT(iph2->sa);
3103 return -1;
3104 }
3105
3106 iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
3107 if (iph2->sa == NULL) {
3108 plog(LLV_ERROR, LOCATION, NULL,
3109 "failed to allocate my sa buffer\n");
3110 if (q)
3111 vfree(q);
3112 return -1;
3113 }
3114 memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3115 if (propoff != 0) {
3116 prop = (struct isakmp_pl_p *)(iph2->sa->v +
3117 propoff);
3118 prop->h.np = ISAKMP_NPTYPE_P;
3119 }
3120 propoff = iph2->sa->l - q->l;
3121
3122 vfree(q);
3123 }
3124 }
3125
3126 return 0;
3127 }
3128
3129 /*
3130 * return 1 if all of the given protocols are transport mode.
3131 */
3132 int
ipsecdoi_transportmode(struct saprop * pp)3133 ipsecdoi_transportmode(struct saprop *pp)
3134 {
3135 struct saproto *pr = NULL;
3136
3137 for (; pp; pp = pp->next) {
3138 for (pr = pp->head; pr; pr = pr->next) {
3139 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
3140 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
3141 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
3142 return 0;
3143 }
3144 }
3145
3146 return 1;
3147 }
3148
3149 int
ipsecdoi_get_defaultlifetime(void)3150 ipsecdoi_get_defaultlifetime(void)
3151 {
3152 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3153 }
3154
3155 int
ipsecdoi_checkalgtypes(int proto_id,int enc,int auth,int comp)3156 ipsecdoi_checkalgtypes(int proto_id, int enc, int auth, int comp)
3157 {
3158 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3159 switch (proto_id) {
3160 case IPSECDOI_PROTO_IPSEC_ESP:
3161 if (enc == 0 || comp != 0) {
3162 plog(LLV_ERROR, LOCATION, NULL,
3163 "illegal algorithm defined "
3164 "ESP enc=%s auth=%s comp=%s.\n",
3165 TMPALGTYPE2STR(enc),
3166 TMPALGTYPE2STR(auth),
3167 TMPALGTYPE2STR(comp));
3168 return -1;
3169 }
3170 break;
3171 case IPSECDOI_PROTO_IPSEC_AH:
3172 if (enc != 0 || auth == 0 || comp != 0) {
3173 plog(LLV_ERROR, LOCATION, NULL,
3174 "illegal algorithm defined "
3175 "AH enc=%s auth=%s comp=%s.\n",
3176 TMPALGTYPE2STR(enc),
3177 TMPALGTYPE2STR(auth),
3178 TMPALGTYPE2STR(comp));
3179 return -1;
3180 }
3181 break;
3182 case IPSECDOI_PROTO_IPCOMP:
3183 if (enc != 0 || auth != 0 || comp == 0) {
3184 plog(LLV_ERROR, LOCATION, NULL,
3185 "illegal algorithm defined "
3186 "IPcomp enc=%s auth=%s comp=%s.\n",
3187 TMPALGTYPE2STR(enc),
3188 TMPALGTYPE2STR(auth),
3189 TMPALGTYPE2STR(comp));
3190 return -1;
3191 }
3192 break;
3193 default:
3194 plog(LLV_ERROR, LOCATION, NULL,
3195 "invalid ipsec protocol %d\n", proto_id);
3196 return -1;
3197 }
3198 #undef TMPALGTYPE2STR
3199 return 0;
3200 }
3201
3202 int
ipproto2doi(int proto)3203 ipproto2doi(int proto)
3204 {
3205 switch (proto) {
3206 case IPPROTO_AH:
3207 return IPSECDOI_PROTO_IPSEC_AH;
3208 case IPPROTO_ESP:
3209 return IPSECDOI_PROTO_IPSEC_ESP;
3210 case IPPROTO_IPCOMP:
3211 return IPSECDOI_PROTO_IPCOMP;
3212 }
3213 return -1; /* XXX */
3214 }
3215
3216 int
doi2ipproto(int proto)3217 doi2ipproto(int proto)
3218 {
3219 switch (proto) {
3220 case IPSECDOI_PROTO_IPSEC_AH:
3221 return IPPROTO_AH;
3222 case IPSECDOI_PROTO_IPSEC_ESP:
3223 return IPPROTO_ESP;
3224 case IPSECDOI_PROTO_IPCOMP:
3225 return IPPROTO_IPCOMP;
3226 }
3227 return -1; /* XXX */
3228 }
3229
3230 /*
3231 * Check if a subnet id is valid for comparison
3232 * with an address id ( address length mask )
3233 * and compare them
3234 * Return value
3235 * = 0 for match
3236 * = 1 for mismatch
3237 */
3238
3239 static int
ipsecdoi_subnetisaddr_v4(const vchar_t * subnet,const vchar_t * address)3240 ipsecdoi_subnetisaddr_v4(const vchar_t *subnet, const vchar_t *address)
3241 {
3242 struct in_addr *mask;
3243
3244 if (address->l != sizeof(struct in_addr))
3245 return 1;
3246
3247 if (subnet->l != (sizeof(struct in_addr)*2))
3248 return 1;
3249
3250 mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
3251
3252 if (mask->s_addr!=0xffffffff)
3253 return 1;
3254
3255 return memcmp(subnet->v,address->v,address->l);
3256 }
3257
3258 #ifdef INET6
3259
3260 static int
ipsecdoi_subnetisaddr_v6(const vchar_t * subnet,const vchar_t * address)3261 ipsecdoi_subnetisaddr_v6(const vchar_t *subnet, const vchar_t *address)
3262 {
3263 struct in6_addr *mask;
3264 int i;
3265
3266 if (address->l != sizeof(struct in6_addr))
3267 return 1;
3268
3269 if (subnet->l != (sizeof(struct in6_addr)*2))
3270 return 1;
3271
3272 mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
3273
3274 for (i=0; i<16; i++)
3275 if(mask->s6_addr[i]!=0xff)
3276 return 1;
3277
3278 return memcmp(subnet->v,address->v,address->l);
3279 }
3280
3281 #endif
3282
3283 /*
3284 * Check and Compare two IDs
3285 * - specify 0 for exact if wildcards are allowed
3286 * Return value
3287 * = 0 for match
3288 * = 1 for misatch
3289 * = -1 for integrity error
3290 */
3291
3292 int
ipsecdoi_chkcmpids(const vchar_t * idt,const vchar_t * ids,int exact)3293 ipsecdoi_chkcmpids(const vchar_t *idt, const vchar_t *ids, int exact)
3294 {
3295 struct ipsecdoi_id_b *id_bt;
3296 struct ipsecdoi_id_b *id_bs;
3297 vchar_t ident_t;
3298 vchar_t ident_s;
3299 int result;
3300
3301 /* handle wildcard IDs */
3302
3303 if (idt == NULL || ids == NULL)
3304 {
3305 if( !exact )
3306 {
3307 plog(LLV_DEBUG, LOCATION, NULL,
3308 "check and compare ids : values matched (ANONYMOUS)\n" );
3309 return 0;
3310 }
3311 else
3312 {
3313 plog(LLV_DEBUG, LOCATION, NULL,
3314 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3315 return -1;
3316 }
3317 }
3318
3319 /* make sure the ids are of the same type */
3320
3321 id_bt = (struct ipsecdoi_id_b *) idt->v;
3322 id_bs = (struct ipsecdoi_id_b *) ids->v;
3323
3324 ident_t.v = idt->v + sizeof(*id_bt);
3325 ident_t.l = idt->l - sizeof(*id_bt);
3326 ident_s.v = ids->v + sizeof(*id_bs);
3327 ident_s.l = ids->l - sizeof(*id_bs);
3328
3329 if (id_bs->type != id_bt->type)
3330 {
3331 /*
3332 * special exception for comparing
3333 * address to subnet id types when
3334 * the netmask is address length
3335 */
3336
3337 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3338 (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3339 result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3340 goto cmpid_result;
3341 }
3342
3343 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3344 (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3345 result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3346 goto cmpid_result;
3347 }
3348
3349 #ifdef INET6
3350 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3351 (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3352 result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3353 goto cmpid_result;
3354 }
3355
3356 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3357 (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3358 result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3359 goto cmpid_result;
3360 }
3361 #endif
3362 plog(LLV_DEBUG, LOCATION, NULL,
3363 "check and compare ids : id type mismatch %s != %s\n",
3364 s_ipsecdoi_ident(id_bs->type),
3365 s_ipsecdoi_ident(id_bt->type));
3366
3367 return 1;
3368 }
3369
3370 if(id_bs->proto_id != id_bt->proto_id){
3371 plog(LLV_DEBUG, LOCATION, NULL,
3372 "check and compare ids : proto_id mismatch %d != %d\n",
3373 id_bs->proto_id, id_bt->proto_id);
3374
3375 return 1;
3376 }
3377
3378 /* compare the ID data. */
3379
3380 switch (id_bt->type) {
3381 case IPSECDOI_ID_DER_ASN1_DN:
3382 case IPSECDOI_ID_DER_ASN1_GN:
3383 /* compare asn1 ids */
3384 result = eay_cmp_asn1dn(&ident_t, &ident_s);
3385 goto cmpid_result;
3386
3387 case IPSECDOI_ID_IPV4_ADDR:
3388 /* validate lengths */
3389 if ((ident_t.l != sizeof(struct in_addr))||
3390 (ident_s.l != sizeof(struct in_addr)))
3391 goto cmpid_invalid;
3392 break;
3393
3394 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3395 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3396 /* validate lengths */
3397 if ((ident_t.l != (sizeof(struct in_addr)*2))||
3398 (ident_s.l != (sizeof(struct in_addr)*2)))
3399 goto cmpid_invalid;
3400 break;
3401
3402 #ifdef INET6
3403 case IPSECDOI_ID_IPV6_ADDR:
3404 /* validate lengths */
3405 if ((ident_t.l != sizeof(struct in6_addr))||
3406 (ident_s.l != sizeof(struct in6_addr)))
3407 goto cmpid_invalid;
3408 break;
3409
3410 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3411 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3412 /* validate lengths */
3413 if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3414 (ident_s.l != (sizeof(struct in6_addr)*2)))
3415 goto cmpid_invalid;
3416 break;
3417 #endif
3418 case IPSECDOI_ID_FQDN:
3419 case IPSECDOI_ID_USER_FQDN:
3420 case IPSECDOI_ID_KEY_ID:
3421 break;
3422
3423 default:
3424 plog(LLV_ERROR, LOCATION, NULL,
3425 "Unhandled id type %i specified for comparison\n",
3426 id_bt->type);
3427 return -1;
3428 }
3429
3430 /* validate matching data and length */
3431 if (ident_t.l == ident_s.l)
3432 result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3433 else
3434 result = 1;
3435
3436 cmpid_result:
3437
3438 /* debug level output */
3439 if(loglevel >= LLV_DEBUG) {
3440 char *idstrt = ipsecdoi_id2str(idt);
3441 char *idstrs = ipsecdoi_id2str(ids);
3442
3443 if (!result)
3444 plog(LLV_DEBUG, LOCATION, NULL,
3445 "check and compare ids : values matched (%s)\n",
3446 s_ipsecdoi_ident(id_bs->type) );
3447 else
3448 plog(LLV_DEBUG, LOCATION, NULL,
3449 "check and compare ids : value mismatch (%s)\n",
3450 s_ipsecdoi_ident(id_bs->type));
3451
3452 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
3453 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
3454
3455 racoon_free(idstrs);
3456 racoon_free(idstrt);
3457 }
3458
3459 /* return result */
3460 if( !result )
3461 return 0;
3462 else
3463 return 1;
3464
3465 cmpid_invalid:
3466
3467 /* id integrity error */
3468 plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
3469 s_ipsecdoi_ident(id_bs->type));
3470 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
3471 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
3472
3473 return -1;
3474 }
3475
3476 /*
3477 * check the following:
3478 * - In main mode with pre-shared key, only address type can be used.
3479 * - if proper type for phase 1 ?
3480 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3481 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3482 * - if ID payload sent from peer is equal to the ID expected by me.
3483 *
3484 * both of "id" and "id_p" should be ID payload without general header,
3485 */
3486 int
ipsecdoi_checkid1(struct ph1handle * iph1)3487 ipsecdoi_checkid1(struct ph1handle *iph1)
3488 {
3489 struct ipsecdoi_id_b *id_b;
3490
3491 if (iph1->id_p == NULL) {
3492 plog(LLV_ERROR, LOCATION, NULL,
3493 "invalid iph1 passed id_p == NULL\n");
3494 return ISAKMP_INTERNAL_ERROR;
3495 }
3496 if (iph1->id_p->l < sizeof(*id_b)) {
3497 plog(LLV_ERROR, LOCATION, NULL,
3498 "invalid value passed as \"ident\" (len=%lu)\n",
3499 (u_long)iph1->id_p->l);
3500 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3501 }
3502
3503 id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3504
3505 /* In main mode with pre-shared key, only address type can be used. */
3506 if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3507 iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3508 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3509 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3510 plog(LLV_ERROR, LOCATION, NULL,
3511 "Expecting IP address type in main mode, "
3512 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3513 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3514 }
3515 }
3516
3517 /* if proper type for phase 1 ? */
3518 switch (id_b->type) {
3519 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3520 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3521 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3522 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3523 plog(LLV_WARNING, LOCATION, NULL,
3524 "such ID type %s is not proper.\n",
3525 s_ipsecdoi_ident(id_b->type));
3526 /*FALLTHROUGH*/
3527 }
3528
3529 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3530 if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3531 id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3532
3533 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3534 plog(LLV_WARNING, LOCATION, NULL,
3535 "protocol ID and Port mismatched. "
3536 "proto_id:%d port:%d\n",
3537 id_b->proto_id, ntohs(id_b->port));
3538 /*FALLTHROUGH*/
3539
3540 } else if (id_b->proto_id == IPPROTO_UDP) {
3541 /*
3542 * copmaring with expecting port.
3543 * always permit if port is equal to PORT_ISAKMP
3544 */
3545 if (ntohs(id_b->port) != PORT_ISAKMP) {
3546 uint16_t port;
3547
3548 port = extract_port(iph1->remote);
3549 if (ntohs(id_b->port) != port) {
3550 plog(LLV_WARNING, LOCATION, NULL,
3551 "port %d expected, but %d\n",
3552 port, ntohs(id_b->port));
3553 /*FALLTHROUGH*/
3554 }
3555 }
3556 }
3557 }
3558
3559 /* resolve remote configuration if not done yet */
3560 if (resolveph1rmconf(iph1) < 0)
3561 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3562
3563 if (iph1->rmconf == NULL)
3564 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3565
3566 return 0;
3567 }
3568
3569 /*
3570 * create ID payload for phase 1 and set into iph1->id.
3571 * NOT INCLUDING isakmp general header.
3572 * see, RFC2407 4.6.2.1
3573 */
3574 int
ipsecdoi_setid1(struct ph1handle * iph1)3575 ipsecdoi_setid1(struct ph1handle *iph1)
3576 {
3577 vchar_t *ret = NULL;
3578 struct ipsecdoi_id_b id_b;
3579 vchar_t *ident = NULL;
3580 struct sockaddr *ipid = NULL;
3581
3582 /* init */
3583 id_b.proto_id = 0;
3584 id_b.port = 0;
3585 ident = NULL;
3586
3587 switch (iph1->rmconf->idvtype) {
3588 case IDTYPE_FQDN:
3589 id_b.type = IPSECDOI_ID_FQDN;
3590 ident = vdup(iph1->rmconf->idv);
3591 break;
3592 case IDTYPE_USERFQDN:
3593 id_b.type = IPSECDOI_ID_USER_FQDN;
3594 ident = vdup(iph1->rmconf->idv);
3595 break;
3596 case IDTYPE_KEYID:
3597 id_b.type = IPSECDOI_ID_KEY_ID;
3598 ident = vdup(iph1->rmconf->idv);
3599 break;
3600 case IDTYPE_ASN1DN:
3601 id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3602 if (iph1->rmconf->idv) {
3603 /* XXX it must be encoded to asn1dn. */
3604 ident = vdup(iph1->rmconf->idv);
3605 } else {
3606 if (oakley_getmycert(iph1) < 0) {
3607 plog(LLV_ERROR, LOCATION, NULL,
3608 "failed to get own CERT.\n");
3609 goto err;
3610 }
3611 ident = eay_get_x509asn1subjectname(iph1->cert);
3612 }
3613 break;
3614 case IDTYPE_ADDRESS:
3615 /*
3616 * if the value of the id type was set by the configuration
3617 * file, then use it. otherwise the value is get from local
3618 * ip address by using ike negotiation.
3619 */
3620 if (iph1->rmconf->idv)
3621 ipid = (struct sockaddr *)iph1->rmconf->idv->v;
3622 /*FALLTHROUGH*/
3623 default:
3624 {
3625 int l;
3626 caddr_t p;
3627
3628 if (ipid == NULL)
3629 ipid = iph1->local;
3630
3631 /* use IP address */
3632 switch (ipid->sa_family) {
3633 case AF_INET:
3634 id_b.type = IPSECDOI_ID_IPV4_ADDR;
3635 l = sizeof(struct in_addr);
3636 p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3637 break;
3638 #ifdef INET6
3639 case AF_INET6:
3640 id_b.type = IPSECDOI_ID_IPV6_ADDR;
3641 l = sizeof(struct in6_addr);
3642 p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3643 break;
3644 #endif
3645 default:
3646 plog(LLV_ERROR, LOCATION, NULL,
3647 "invalid address family.\n");
3648 goto err;
3649 }
3650 id_b.proto_id = IPPROTO_UDP;
3651 id_b.port = htons(PORT_ISAKMP);
3652 ident = vmalloc(l);
3653 if (!ident) {
3654 plog(LLV_ERROR, LOCATION, NULL,
3655 "failed to get ID buffer.\n");
3656 return -1;
3657 }
3658 memcpy(ident->v, p, ident->l);
3659 }
3660 }
3661 if (!ident) {
3662 plog(LLV_ERROR, LOCATION, NULL,
3663 "failed to get ID buffer.\n");
3664 return -1;
3665 }
3666
3667 ret = vmalloc(sizeof(id_b) + ident->l);
3668 if (ret == NULL) {
3669 plog(LLV_ERROR, LOCATION, NULL,
3670 "failed to get ID buffer.\n");
3671 goto err;
3672 }
3673
3674 memcpy(ret->v, &id_b, sizeof(id_b));
3675 memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3676
3677 iph1->id = ret;
3678
3679 plog(LLV_DEBUG, LOCATION, NULL,
3680 "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3681 if (ident)
3682 vfree(ident);
3683 return 0;
3684
3685 err:
3686 if (ident)
3687 vfree(ident);
3688 plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3689 return -1;
3690 }
3691
3692 /* it's only called by cfparse.y. */
3693 int
set_identifier(vchar_t ** vpp,int type,const vchar_t * const value)3694 set_identifier(vchar_t **vpp, int type, const vchar_t * const value)
3695 {
3696 return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
3697 }
3698
3699 int
set_identifier_qual(vchar_t ** vpp,int type,const vchar_t * const value,int qual)3700 set_identifier_qual(vchar_t **vpp, int type, const vchar_t * const value,
3701 int qual)
3702 {
3703 vchar_t *new = NULL;
3704
3705 /* simply return if value is null. */
3706 if (!value){
3707 if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
3708 plog(LLV_ERROR, LOCATION, NULL,
3709 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3710 return -1;
3711 }
3712 return 0;
3713 }
3714
3715 switch (type) {
3716 case IDTYPE_FQDN:
3717 case IDTYPE_USERFQDN:
3718 if(value->l <= 1){
3719 plog(LLV_ERROR, LOCATION, NULL,
3720 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3721 return -1;
3722 }
3723 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3724 new = vmalloc(value->l - 1);
3725 if (new == NULL)
3726 return -1;
3727 memcpy(new->v, value->v, new->l);
3728 break;
3729 case IDTYPE_KEYID:
3730 /*
3731 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3732 * to use a file for backward compatibility sake.
3733 */
3734 switch(qual) {
3735 case IDQUAL_FILE:
3736 case IDQUAL_UNSPEC: {
3737 FILE *fp;
3738 char b[512];
3739 int tlen, len;
3740
3741 fp = fopen(value->v, "r");
3742 if (fp == NULL) {
3743 plog(LLV_ERROR, LOCATION, NULL,
3744 "can not open %s\n", value->v);
3745 return -1;
3746 }
3747 tlen = 0;
3748 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3749 new = vrealloc(new, tlen + len);
3750 if (!new) {
3751 fclose(fp);
3752 return -1;
3753 }
3754 memcpy(new->v + tlen, b, len);
3755 tlen += len;
3756 }
3757 fclose(fp);
3758 break;
3759 }
3760
3761 case IDQUAL_TAG:
3762 new = vmalloc(value->l - 1);
3763 if (new == NULL) {
3764 plog(LLV_ERROR, LOCATION, NULL,
3765 "can not allocate memory");
3766 return -1;
3767 }
3768 memcpy(new->v, value->v, new->l);
3769 break;
3770
3771 default:
3772 plog(LLV_ERROR, LOCATION, NULL,
3773 "unknown qualifier");
3774 return -1;
3775 }
3776 break;
3777
3778 case IDTYPE_ADDRESS: {
3779 struct sockaddr *sa;
3780
3781 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3782 if (value->l == 0)
3783 break;
3784
3785 sa = str2saddr(value->v, NULL);
3786 if (sa == NULL) {
3787 plog(LLV_ERROR, LOCATION, NULL,
3788 "invalid ip address %s\n", value->v);
3789 return -1;
3790 }
3791
3792 new = vmalloc(sysdep_sa_len(sa));
3793 if (new == NULL) {
3794 racoon_free(sa);
3795 return -1;
3796 }
3797 memcpy(new->v, sa, new->l);
3798 racoon_free(sa);
3799 break;
3800 }
3801 case IDTYPE_ASN1DN:
3802 if (value->v[0] == '~')
3803 /* Hex-encoded ASN1 strings */
3804 new = eay_hex2asn1dn(value->v + 1, - 1);
3805 else
3806 /* DN encoded strings */
3807 new = eay_str2asn1dn(value->v, value->l - 1);
3808
3809 if (new == NULL)
3810 return -1;
3811
3812 if (loglevel >= LLV_DEBUG) {
3813 X509_NAME *xn;
3814 BIO *bio;
3815 unsigned char *ptr = (unsigned char *) new->v;
3816 size_t len;
3817 char save;
3818
3819 xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
3820 bio = BIO_new(BIO_s_mem());
3821
3822 X509_NAME_print_ex(bio, xn, 0, 0);
3823 len = BIO_get_mem_data(bio, &ptr);
3824 save = ptr[len];
3825 ptr[len] = 0;
3826 plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
3827 ptr[len] = save;
3828 X509_NAME_free(xn);
3829 BIO_free(bio);
3830 }
3831
3832 break;
3833 }
3834
3835 *vpp = new;
3836
3837 return 0;
3838 }
3839
3840 /*
3841 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3842 * NOT INCLUDING isakmp general header.
3843 * this function is for initiator. responder will get to copy from payload.
3844 * responder ID type is always address type.
3845 * see, RFC2407 4.6.2.1
3846 */
3847 int
ipsecdoi_setid2(struct ph2handle * iph2)3848 ipsecdoi_setid2(struct ph2handle *iph2)
3849 {
3850 struct secpolicy *sp;
3851
3852 /* check there is phase 2 handler ? */
3853 sp = getspbyspid(iph2->spid);
3854 if (sp == NULL) {
3855 plog(LLV_ERROR, LOCATION, NULL,
3856 "no policy found for spid:%u.\n", iph2->spid);
3857 return -1;
3858 }
3859
3860 if (!ipsecdoi_transportmode(iph2->proposal))
3861 iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
3862 sp->spidx.prefs, sp->spidx.ul_proto);
3863 else if (iph2->sa_src != NULL) {
3864 /* He have a specific hint indicating that the transport
3865 * mode SA will be negotiated using addresses that differ
3866 * with the one from the SA. We need to indicate that to
3867 * our peer by setting the SA address as ID.
3868 * This is typically the case for the bootstrapping of the
3869 * transport mode SA protecting BU/BA for MIPv6 traffic
3870 *
3871 * --arno*/
3872 iph2->id = ipsecdoi_sockaddr2id(iph2->sa_src,
3873 IPSECDOI_PREFIX_HOST,
3874 sp->spidx.ul_proto);
3875 } else
3876 iph2->id = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
3877 sp->spidx.ul_proto);
3878
3879 if (iph2->id == NULL) {
3880 plog(LLV_ERROR, LOCATION, NULL,
3881 "failed to get ID for %s\n",
3882 spidx2str(&sp->spidx));
3883 return -1;
3884 }
3885 plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
3886 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
3887
3888 /* remote side */
3889 if (!ipsecdoi_transportmode(iph2->proposal))
3890 iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
3891 sp->spidx.prefd, sp->spidx.ul_proto);
3892 else if (iph2->sa_dst != NULL) {
3893 /* See comment above for local side. */
3894 iph2->id_p = ipsecdoi_sockaddr2id(iph2->sa_dst,
3895 IPSECDOI_PREFIX_HOST,
3896 sp->spidx.ul_proto);
3897 } else
3898 iph2->id_p = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
3899 sp->spidx.ul_proto);
3900
3901 if (iph2->id_p == NULL) {
3902 plog(LLV_ERROR, LOCATION, NULL,
3903 "failed to get ID for %s\n",
3904 spidx2str(&sp->spidx));
3905 VPTRINIT(iph2->id);
3906 return -1;
3907 }
3908 plog(LLV_DEBUG, LOCATION, NULL,
3909 "use remote ID type %s\n",
3910 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
3911
3912 return 0;
3913 }
3914
3915 /*
3916 * set address type of ID.
3917 * NOT INCLUDING general header.
3918 */
3919 vchar_t *
ipsecdoi_sockaddr2id(struct sockaddr * saddr,u_int prefixlen,u_int ul_proto)3920 ipsecdoi_sockaddr2id(struct sockaddr *saddr, u_int prefixlen, u_int ul_proto)
3921 {
3922 vchar_t *new;
3923 int type, len1, len2;
3924 caddr_t sa;
3925 u_short port;
3926
3927 /*
3928 * Q. When type is SUBNET, is it allowed to be ::1/128.
3929 * A. Yes. (consensus at bake-off)
3930 */
3931 switch (saddr->sa_family) {
3932 case AF_INET:
3933 len1 = sizeof(struct in_addr);
3934 if (prefixlen >= (sizeof(struct in_addr) << 3)) {
3935 type = IPSECDOI_ID_IPV4_ADDR;
3936 len2 = 0;
3937 } else {
3938 type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
3939 len2 = sizeof(struct in_addr);
3940 }
3941 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
3942 port = ((struct sockaddr_in *)(saddr))->sin_port;
3943 break;
3944 #ifdef INET6
3945 case AF_INET6:
3946 len1 = sizeof(struct in6_addr);
3947 if (prefixlen >= (sizeof(struct in6_addr) << 3)) {
3948 type = IPSECDOI_ID_IPV6_ADDR;
3949 len2 = 0;
3950 } else {
3951 type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
3952 len2 = sizeof(struct in6_addr);
3953 }
3954 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
3955 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
3956 break;
3957 #endif
3958 default:
3959 plog(LLV_ERROR, LOCATION, NULL,
3960 "invalid family: %d.\n", saddr->sa_family);
3961 return NULL;
3962 }
3963
3964 /* get ID buffer */
3965 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
3966 if (new == NULL) {
3967 plog(LLV_ERROR, LOCATION, NULL,
3968 "failed to get ID buffer.\n");
3969 return NULL;
3970 }
3971
3972 memset(new->v, 0, new->l);
3973
3974 /* set the part of header. */
3975 ((struct ipsecdoi_id_b *)new->v)->type = type;
3976
3977 /* set ul_proto and port */
3978 /*
3979 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3980 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
3981 */
3982 ((struct ipsecdoi_id_b *)new->v)->proto_id =
3983 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
3984 ((struct ipsecdoi_id_b *)new->v)->port =
3985 port == IPSEC_PORT_ANY ? 0 : port;
3986 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
3987
3988 /* set address */
3989
3990 /* set prefix */
3991 if (len2) {
3992 u_char *p = (unsigned char *) new->v +
3993 sizeof(struct ipsecdoi_id_b) + len1;
3994 u_int bits = prefixlen;
3995
3996 while (bits >= 8) {
3997 *p++ = 0xff;
3998 bits -= 8;
3999 }
4000
4001 if (bits > 0)
4002 *p = ~((1 << (8 - bits)) - 1);
4003 }
4004
4005 return new;
4006 }
4007
4008 vchar_t *
ipsecdoi_sockrange2id(struct sockaddr * laddr,struct sockaddr * haddr,u_int ul_proto)4009 ipsecdoi_sockrange2id(struct sockaddr *laddr, struct sockaddr *haddr,
4010 u_int ul_proto)
4011 {
4012 vchar_t *new;
4013 int type, len1, len2;
4014 u_short port;
4015
4016 if (laddr->sa_family != haddr->sa_family) {
4017 plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
4018 return NULL;
4019 }
4020
4021 switch (laddr->sa_family) {
4022 case AF_INET:
4023 type = IPSECDOI_ID_IPV4_ADDR_RANGE;
4024 len1 = sizeof(struct in_addr);
4025 len2 = sizeof(struct in_addr);
4026 break;
4027 #ifdef INET6
4028 case AF_INET6:
4029 type = IPSECDOI_ID_IPV6_ADDR_RANGE;
4030 len1 = sizeof(struct in6_addr);
4031 len2 = sizeof(struct in6_addr);
4032 break;
4033 #endif
4034 default:
4035 plog(LLV_ERROR, LOCATION, NULL,
4036 "invalid family: %d.\n", laddr->sa_family);
4037 return NULL;
4038 }
4039
4040 /* get ID buffer */
4041 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4042 if (new == NULL) {
4043 plog(LLV_ERROR, LOCATION, NULL,
4044 "failed to get ID buffer.\n");
4045 return NULL;
4046 }
4047
4048 memset(new->v, 0, new->l);
4049 /* set the part of header. */
4050 ((struct ipsecdoi_id_b *)new->v)->type = type;
4051
4052 /* set ul_proto and port */
4053 /*
4054 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4055 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4056 */
4057 ((struct ipsecdoi_id_b *)new->v)->proto_id =
4058 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4059 port = ((struct sockaddr_in *)(laddr))->sin_port;
4060 ((struct ipsecdoi_id_b *)new->v)->port =
4061 port == IPSEC_PORT_ANY ? 0 : port;
4062 memcpy(new->v + sizeof(struct ipsecdoi_id_b),
4063 (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
4064 len1);
4065 memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
4066 (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
4067 len2);
4068 return new;
4069 }
4070
4071
4072 /*
4073 * create sockaddr structure from ID payload (buf).
4074 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4075 * see, RFC2407 4.6.2.1
4076 */
4077 int
ipsecdoi_id2sockaddr(vchar_t * buf,struct sockaddr * saddr,uint8_t * prefixlen,uint16_t * ul_proto)4078 ipsecdoi_id2sockaddr(vchar_t *buf, struct sockaddr *saddr,
4079 uint8_t *prefixlen, uint16_t *ul_proto)
4080 {
4081 struct ipsecdoi_id_b *id_b = NULL;
4082 u_int plen = 0;
4083
4084 if (buf == NULL)
4085 return ISAKMP_INTERNAL_ERROR;
4086
4087 id_b = (struct ipsecdoi_id_b *)buf->v;
4088
4089 /*
4090 * When a ID payload of subnet type with a IP address of full bit
4091 * masked, it has to be processed as host address.
4092 * e.g. below 2 type are same.
4093 * type = ipv6 subnet, data = 2001::1/128
4094 * type = ipv6 address, data = 2001::1
4095 */
4096 switch (id_b->type) {
4097 case IPSECDOI_ID_IPV4_ADDR:
4098 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4099 #ifndef __linux__
4100 saddr->sa_len = sizeof(struct sockaddr_in);
4101 #endif
4102 saddr->sa_family = AF_INET;
4103 ((struct sockaddr_in *)saddr)->sin_port =
4104 (id_b->port == 0
4105 ? IPSEC_PORT_ANY
4106 : id_b->port); /* see sockaddr2id() */
4107 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
4108 buf->v + sizeof(*id_b), sizeof(struct in_addr));
4109 break;
4110 #ifdef INET6
4111 case IPSECDOI_ID_IPV6_ADDR:
4112 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4113 #ifndef __linux__
4114 saddr->sa_len = sizeof(struct sockaddr_in6);
4115 #endif
4116 saddr->sa_family = AF_INET6;
4117 ((struct sockaddr_in6 *)saddr)->sin6_port =
4118 (id_b->port == 0
4119 ? IPSEC_PORT_ANY
4120 : id_b->port); /* see sockaddr2id() */
4121 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
4122 buf->v + sizeof(*id_b), sizeof(struct in6_addr));
4123 ((struct sockaddr_in6 *)saddr)->sin6_scope_id =
4124 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)saddr)->sin6_addr)
4125 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4126 : 0);
4127
4128 break;
4129 #endif
4130 default:
4131 plog(LLV_ERROR, LOCATION, NULL,
4132 "unsupported ID type %d\n", id_b->type);
4133 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
4134 }
4135
4136 /* get prefix length */
4137 switch (id_b->type) {
4138 case IPSECDOI_ID_IPV4_ADDR:
4139 plen = sizeof(struct in_addr) << 3;
4140 break;
4141 #ifdef INET6
4142 case IPSECDOI_ID_IPV6_ADDR:
4143 plen = sizeof(struct in6_addr) << 3;
4144 break;
4145 #endif
4146 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4147 #ifdef INET6
4148 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4149 #endif
4150 {
4151 u_char *p;
4152 u_int max;
4153 int alen = sizeof(struct in_addr);
4154
4155 switch (id_b->type) {
4156 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4157 alen = sizeof(struct in_addr);
4158 break;
4159 #ifdef INET6
4160 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4161 alen = sizeof(struct in6_addr);
4162 break;
4163 #endif
4164 }
4165
4166 /* sanity check */
4167 if (buf->l < alen)
4168 return ISAKMP_INTERNAL_ERROR;
4169
4170 /* get subnet mask length */
4171 plen = 0;
4172 max = alen <<3;
4173
4174 p = (unsigned char *) buf->v
4175 + sizeof(struct ipsecdoi_id_b)
4176 + alen;
4177
4178 for (; *p == 0xff; p++) {
4179 plen += 8;
4180 if (plen >= max)
4181 break;
4182 }
4183
4184 if (plen < max) {
4185 u_int l = 0;
4186 u_char b = ~(*p);
4187
4188 while (b) {
4189 b >>= 1;
4190 l++;
4191 }
4192
4193 l = 8 - l;
4194 plen += l;
4195 }
4196 }
4197 break;
4198 }
4199
4200 *prefixlen = plen;
4201 *ul_proto = id_b->proto_id == 0
4202 ? IPSEC_ULPROTO_ANY
4203 : id_b->proto_id; /* see sockaddr2id() */
4204
4205 return 0;
4206 }
4207
4208 /*
4209 * make printable string from ID payload except of general header.
4210 */
4211 char *
ipsecdoi_id2str(const vchar_t * id)4212 ipsecdoi_id2str(const vchar_t *id)
4213 {
4214 #define BUFLEN 512
4215 char * ret = NULL;
4216 int len = 0;
4217 char *dat;
4218 static char buf[BUFLEN];
4219 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
4220 union sockaddr_any saddr;
4221 u_int plen = 0;
4222
4223 switch (id_b->type) {
4224 case IPSECDOI_ID_IPV4_ADDR:
4225 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4226 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4227
4228 #ifndef __linux__
4229 saddr.sa.sa_len = sizeof(struct sockaddr_in);
4230 #endif
4231 saddr.sa.sa_family = AF_INET;
4232 saddr.sin.sin_port = IPSEC_PORT_ANY;
4233 memcpy(&saddr.sin.sin_addr,
4234 id->v + sizeof(*id_b), sizeof(struct in_addr));
4235 break;
4236 #ifdef INET6
4237 case IPSECDOI_ID_IPV6_ADDR:
4238 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4239 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4240
4241 #ifndef __linux__
4242 saddr.sa.sa_len = sizeof(struct sockaddr_in6);
4243 #endif
4244 saddr.sa.sa_family = AF_INET6;
4245 saddr.sin6.sin6_port = IPSEC_PORT_ANY;
4246 memcpy(&saddr.sin6.sin6_addr,
4247 id->v + sizeof(*id_b), sizeof(struct in6_addr));
4248 saddr.sin6.sin6_scope_id =
4249 (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
4250 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4251 : 0);
4252 break;
4253 #endif
4254 }
4255
4256 switch (id_b->type) {
4257 case IPSECDOI_ID_IPV4_ADDR:
4258 #ifdef INET6
4259 case IPSECDOI_ID_IPV6_ADDR:
4260 #endif
4261 len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
4262 break;
4263
4264 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4265 #ifdef INET6
4266 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4267 #endif
4268 {
4269 u_char *p;
4270 u_int max;
4271 int alen = sizeof(struct in_addr);
4272
4273 switch (id_b->type) {
4274 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4275 alen = sizeof(struct in_addr);
4276 break;
4277 #ifdef INET6
4278 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4279 alen = sizeof(struct in6_addr);
4280 break;
4281 #endif
4282 }
4283
4284 /* sanity check */
4285 if (id->l < alen) {
4286 len = 0;
4287 break;
4288 }
4289
4290 /* get subnet mask length */
4291 plen = 0;
4292 max = alen <<3;
4293
4294 p = (unsigned char *) id->v
4295 + sizeof(struct ipsecdoi_id_b)
4296 + alen;
4297
4298 for (; *p == 0xff; p++) {
4299 plen += 8;
4300 if (plen >= max)
4301 break;
4302 }
4303
4304 if (plen < max) {
4305 u_int l = 0;
4306 u_char b = ~(*p);
4307
4308 while (b) {
4309 b >>= 1;
4310 l++;
4311 }
4312
4313 l = 8 - l;
4314 plen += l;
4315 }
4316
4317 len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
4318 }
4319 break;
4320
4321 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4322
4323 len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
4324
4325 #ifndef __linux__
4326 saddr.sa.sa_len = sizeof(struct sockaddr_in);
4327 #endif
4328 saddr.sa.sa_family = AF_INET;
4329 saddr.sin.sin_port = IPSEC_PORT_ANY;
4330 memcpy(&saddr.sin.sin_addr,
4331 id->v + sizeof(*id_b) + sizeof(struct in_addr),
4332 sizeof(struct in_addr));
4333
4334 len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
4335 break;
4336
4337 #ifdef INET6
4338 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4339 len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
4340
4341 #ifndef __linux__
4342 saddr.sa.sa_len = sizeof(struct sockaddr_in6);
4343 #endif
4344 saddr.sa.sa_family = AF_INET6;
4345 saddr.sin6.sin6_port = IPSEC_PORT_ANY;
4346 memcpy(&saddr.sin6.sin6_addr,
4347 id->v + sizeof(*id_b) + sizeof(struct in6_addr),
4348 sizeof(struct in6_addr));
4349 saddr.sin6.sin6_scope_id =
4350 (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
4351 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4352 : 0);
4353
4354 len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
4355 break;
4356 #endif
4357
4358 case IPSECDOI_ID_FQDN:
4359 case IPSECDOI_ID_USER_FQDN:
4360 len = id->l - sizeof(*id_b);
4361 if (len > BUFLEN)
4362 len = BUFLEN;
4363 memcpy(buf, id->v + sizeof(*id_b), len);
4364 break;
4365
4366 case IPSECDOI_ID_DER_ASN1_DN:
4367 case IPSECDOI_ID_DER_ASN1_GN:
4368 {
4369 X509_NAME *xn = NULL;
4370
4371 dat = id->v + sizeof(*id_b);
4372 len = id->l - sizeof(*id_b);
4373
4374 if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
4375 BIO *bio = BIO_new(BIO_s_mem());
4376 X509_NAME_print_ex(bio, xn, 0, 0);
4377 len = BIO_get_mem_data(bio, &dat);
4378 if (len > BUFLEN)
4379 len = BUFLEN;
4380 memcpy(buf,dat,len);
4381 BIO_free(bio);
4382 X509_NAME_free(xn);
4383 } else {
4384 plog(LLV_ERROR, LOCATION, NULL,
4385 "unable to extract asn1dn from id\n");
4386
4387 len = sprintf(buf, "<ASN1-DN>");
4388 }
4389
4390 break;
4391 }
4392
4393 /* currently unhandled id types */
4394 case IPSECDOI_ID_KEY_ID:
4395 len = sprintf( buf, "<KEY-ID>");
4396 break;
4397
4398 default:
4399 plog(LLV_ERROR, LOCATION, NULL,
4400 "unknown ID type %d\n", id_b->type);
4401 }
4402
4403 if (!len)
4404 len = sprintf( buf, "<?>");
4405
4406 ret = racoon_malloc(len+1);
4407 if (ret != NULL) {
4408 memcpy(ret,buf,len);
4409 ret[len]=0;
4410 }
4411
4412 return ret;
4413 }
4414
4415 /*
4416 * set IPsec data attributes into a proposal.
4417 * NOTE: MUST called per a transform.
4418 */
4419 int
ipsecdoi_t2satrns(struct isakmp_pl_t * t,struct saprop * pp,struct saproto * pr,struct satrns * tr)4420 ipsecdoi_t2satrns(struct isakmp_pl_t *t, struct saprop *pp,
4421 struct saproto *pr, struct satrns *tr)
4422 {
4423 struct isakmp_data *d, *prev;
4424 int flag, type;
4425 int error = -1;
4426 int life_t;
4427 int tlen;
4428
4429 tr->trns_no = t->t_no;
4430 tr->trns_id = t->t_id;
4431
4432 tlen = ntohs(t->h.len) - sizeof(*t);
4433 prev = (struct isakmp_data *)NULL;
4434 d = (struct isakmp_data *)(t + 1);
4435
4436 /* default */
4437 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4438 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
4439 pp->lifebyte = 0;
4440 tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
4441
4442 while (tlen > 0) {
4443
4444 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
4445 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
4446
4447 plog(LLV_DEBUG, LOCATION, NULL,
4448 "type=%s, flag=0x%04x, lorv=%s\n",
4449 s_ipsecdoi_attr(type), flag,
4450 s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
4451
4452 switch (type) {
4453 case IPSECDOI_ATTR_SA_LD_TYPE:
4454 {
4455 int xtype = ntohs(d->lorv);
4456 switch (xtype) {
4457 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4458 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4459 life_t = xtype;
4460 break;
4461 default:
4462 plog(LLV_WARNING, LOCATION, NULL,
4463 "invalid life duration type. "
4464 "use default\n");
4465 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4466 break;
4467 }
4468 break;
4469 }
4470 case IPSECDOI_ATTR_SA_LD:
4471 if (prev == NULL
4472 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
4473 IPSECDOI_ATTR_SA_LD_TYPE) {
4474 plog(LLV_ERROR, LOCATION, NULL,
4475 "life duration must follow ltype\n");
4476 break;
4477 }
4478
4479 {
4480 uint32_t tt;
4481 vchar_t *ld_buf = NULL;
4482
4483 if (flag) {
4484 /* i.e. ISAKMP_GEN_TV */
4485 ld_buf = vmalloc(sizeof(d->lorv));
4486 if (ld_buf == NULL) {
4487 plog(LLV_ERROR, LOCATION, NULL,
4488 "failed to get LD buffer.\n");
4489 goto end;
4490 }
4491 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
4492 } else {
4493 int len = ntohs(d->lorv);
4494 /* i.e. ISAKMP_GEN_TLV */
4495 ld_buf = vmalloc(len);
4496 if (ld_buf == NULL) {
4497 plog(LLV_ERROR, LOCATION, NULL,
4498 "failed to get LD buffer.\n");
4499 goto end;
4500 }
4501 memcpy(ld_buf->v, d + 1, len);
4502 }
4503 switch (life_t) {
4504 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4505 tt = ipsecdoi_set_ld(ld_buf);
4506 vfree(ld_buf);
4507 if (tt == 0) {
4508 plog(LLV_ERROR, LOCATION, NULL,
4509 "invalid life duration.\n");
4510 goto end;
4511 }
4512 /* lifetime must be equal in a proposal. */
4513 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
4514 pp->lifetime = tt;
4515 else if (pp->lifetime != tt) {
4516 plog(LLV_ERROR, LOCATION, NULL,
4517 "lifetime mismatched "
4518 "in a proposal, "
4519 "prev:%ld curr:%u.\n",
4520 (long)pp->lifetime, tt);
4521 goto end;
4522 }
4523 break;
4524 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4525 tt = ipsecdoi_set_ld(ld_buf);
4526 vfree(ld_buf);
4527 if (tt == 0) {
4528 plog(LLV_ERROR, LOCATION, NULL,
4529 "invalid life duration.\n");
4530 goto end;
4531 }
4532 /* lifebyte must be equal in a proposal. */
4533 if (pp->lifebyte == 0)
4534 pp->lifebyte = tt;
4535 else if (pp->lifebyte != tt) {
4536 plog(LLV_ERROR, LOCATION, NULL,
4537 "lifebyte mismatched "
4538 "in a proposal, "
4539 "prev:%d curr:%u.\n",
4540 pp->lifebyte, tt);
4541 goto end;
4542 }
4543 break;
4544 default:
4545 vfree(ld_buf);
4546 plog(LLV_ERROR, LOCATION, NULL,
4547 "invalid life type: %d\n", life_t);
4548 goto end;
4549 }
4550 }
4551 break;
4552
4553 case IPSECDOI_ATTR_GRP_DESC:
4554 /*
4555 * RFC2407: 4.5 IPSEC Security Association Attributes
4556 * Specifies the Oakley Group to be used in a PFS QM
4557 * negotiation. For a list of supported values, see
4558 * Appendix A of [IKE].
4559 */
4560 if (pp->pfs_group == 0)
4561 pp->pfs_group = (uint16_t)ntohs(d->lorv);
4562 else if (pp->pfs_group != (uint16_t)ntohs(d->lorv)) {
4563 plog(LLV_ERROR, LOCATION, NULL,
4564 "pfs_group mismatched "
4565 "in a proposal.\n");
4566 goto end;
4567 }
4568 break;
4569
4570 case IPSECDOI_ATTR_ENC_MODE:
4571 if (pr->encmode &&
4572 pr->encmode != (uint16_t)ntohs(d->lorv)) {
4573 plog(LLV_ERROR, LOCATION, NULL,
4574 "multiple encmode exist "
4575 "in a transform.\n");
4576 goto end;
4577 }
4578 pr->encmode = (uint16_t)ntohs(d->lorv);
4579 break;
4580
4581 case IPSECDOI_ATTR_AUTH:
4582 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
4583 plog(LLV_ERROR, LOCATION, NULL,
4584 "multiple authtype exist "
4585 "in a transform.\n");
4586 goto end;
4587 }
4588 tr->authtype = (uint16_t)ntohs(d->lorv);
4589 break;
4590
4591 case IPSECDOI_ATTR_KEY_LENGTH:
4592 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
4593 plog(LLV_ERROR, LOCATION, NULL,
4594 "key length defined but not ESP");
4595 goto end;
4596 }
4597 tr->encklen = ntohs(d->lorv);
4598 break;
4599 #ifdef HAVE_SECCTX
4600 case IPSECDOI_ATTR_SECCTX:
4601 {
4602 int len = ntohs(d->lorv);
4603 memcpy(&pp->sctx, d + 1, len);
4604 pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
4605 break;
4606 }
4607 #endif /* HAVE_SECCTX */
4608 case IPSECDOI_ATTR_KEY_ROUNDS:
4609 case IPSECDOI_ATTR_COMP_DICT_SIZE:
4610 case IPSECDOI_ATTR_COMP_PRIVALG:
4611 default:
4612 break;
4613 }
4614
4615 prev = d;
4616 if (flag) {
4617 tlen -= sizeof(*d);
4618 d = (struct isakmp_data *)((char *)d + sizeof(*d));
4619 } else {
4620 tlen -= (sizeof(*d) + ntohs(d->lorv));
4621 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
4622 }
4623 }
4624
4625 error = 0;
4626 end:
4627 return error;
4628 }
4629
4630 int
ipsecdoi_authalg2trnsid(int alg)4631 ipsecdoi_authalg2trnsid(int alg)
4632 {
4633 switch (alg) {
4634 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
4635 return IPSECDOI_AH_MD5;
4636 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
4637 return IPSECDOI_AH_SHA;
4638 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
4639 return IPSECDOI_AH_SHA256;
4640 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
4641 return IPSECDOI_AH_SHA384;
4642 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
4643 return IPSECDOI_AH_SHA512;
4644 case IPSECDOI_ATTR_AUTH_DES_MAC:
4645 return IPSECDOI_AH_DES;
4646 case IPSECDOI_ATTR_AUTH_KPDK:
4647 return IPSECDOI_AH_MD5; /* XXX */
4648 default:
4649 plog(LLV_ERROR, LOCATION, NULL,
4650 "invalid authentication algorithm:%d\n", alg);
4651 }
4652 return -1;
4653 }
4654
4655 static int rm_idtype2doi[] = {
4656 255, /* IDTYPE_UNDEFINED, 0 */
4657 IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
4658 IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
4659 IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
4660 255, /* IDTYPE_ADDRESS, 4
4661 * it expands into 4 types by another function. */
4662 IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
4663 };
4664
4665 /*
4666 * convert idtype to DOI value.
4667 * OUT 255 : NG
4668 * other: converted.
4669 */
4670 int
idtype2doi(int idtype)4671 idtype2doi(int idtype)
4672 {
4673 if (ARRAYLEN(rm_idtype2doi) > idtype)
4674 return rm_idtype2doi[idtype];
4675 return 255;
4676 }
4677
4678 int
doi2idtype(int doi)4679 doi2idtype(int doi)
4680 {
4681 switch(doi) {
4682 case IPSECDOI_ID_FQDN:
4683 return(IDTYPE_FQDN);
4684 case IPSECDOI_ID_USER_FQDN:
4685 return(IDTYPE_USERFQDN);
4686 case IPSECDOI_ID_KEY_ID:
4687 return(IDTYPE_KEYID);
4688 case IPSECDOI_ID_DER_ASN1_DN:
4689 return(IDTYPE_ASN1DN);
4690 case IPSECDOI_ID_IPV4_ADDR:
4691 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4692 case IPSECDOI_ID_IPV6_ADDR:
4693 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4694 return(IDTYPE_ADDRESS);
4695 default:
4696 plog(LLV_WARNING, LOCATION, NULL,
4697 "Inproper idtype:%s in this function.\n",
4698 s_ipsecdoi_ident(doi));
4699 return(IDTYPE_ADDRESS); /* XXX */
4700 }
4701 /*NOTREACHED*/
4702 }
4703