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