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