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