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