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