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