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