1/* $Id: proposal.c,v 1.13.8.5 2005/07/28 05:05:52 manubsd Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include "config.h" 33 34#include <sys/param.h> 35#include <sys/types.h> 36#include <sys/socket.h> 37#include <sys/queue.h> 38 39#include <netinet/in.h> 40#ifdef HAVE_NETINET6_IPSEC 41# include <netinet6/ipsec.h> 42#else 43# include <netinet/ipsec.h> 44#endif 45 46#include <stdlib.h> 47#include <stdio.h> 48#include <string.h> 49#include <errno.h> 50 51#include "var.h" 52#include "misc.h" 53#include "vmbuf.h" 54#include "plog.h" 55#include "sockmisc.h" 56#include "debug.h" 57 58#include "policy.h" 59#include "pfkey.h" 60#include "isakmp_var.h" 61#include "isakmp.h" 62#include "ipsec_doi.h" 63#include "algorithm.h" 64#include "proposal.h" 65#include "sainfo.h" 66#include "localconf.h" 67#include "remoteconf.h" 68#include "oakley.h" 69#include "handler.h" 70#include "strnames.h" 71#include "gcmalloc.h" 72#ifdef ENABLE_NATT 73#include "nattraversal.h" 74#endif 75#include "ikev2_rfc.h" 76 77/* %%% 78 * modules for ipsec sa spec 79 */ 80struct saprop * 81newsaprop() 82{ 83 struct saprop *new; 84 85 new = racoon_calloc(1, sizeof(*new)); 86 if (new == NULL) 87 return NULL; 88 89 return new; 90} 91 92struct saproto * 93newsaproto() 94{ 95 struct saproto *new; 96 97 new = racoon_calloc(1, sizeof(*new)); 98 if (new == NULL) 99 return NULL; 100 101 return new; 102} 103 104/* set saprop to last part of the prop tree */ 105void 106inssaprop(head, new) 107 struct saprop **head; 108 struct saprop *new; 109{ 110 struct saprop *p; 111 112 if (*head == NULL) { 113 *head = new; 114 return; 115 } 116 117 for (p = *head; p->next; p = p->next) 118 ; 119 p->next = new; 120 121 return; 122} 123 124/* set saproto to the end of the proto tree in saprop */ 125void 126inssaproto(pp, new) 127 struct saprop *pp; 128 struct saproto *new; 129{ 130 struct saproto *p; 131 132 for (p = pp->head; p && p->next; p = p->next) 133 ; 134 if (p == NULL) 135 pp->head = new; 136 else 137 p->next = new; 138 139 return; 140} 141 142/* set saproto to the top of the proto tree in saprop */ 143void 144inssaprotorev(pp, new) 145 struct saprop *pp; 146 struct saproto *new; 147{ 148 new->next = pp->head; 149 pp->head = new; 150 151 return; 152} 153 154struct satrns * 155newsatrns() 156{ 157 struct satrns *new; 158 159 new = racoon_calloc(1, sizeof(*new)); 160 if (new == NULL) 161 return NULL; 162 163 return new; 164} 165 166/* set saproto to last part of the proto tree in saprop */ 167void 168inssatrns(pr, new) 169 struct saproto *pr; 170 struct satrns *new; 171{ 172 struct satrns *tr; 173 174 for (tr = pr->head; tr && tr->next; tr = tr->next) 175 ; 176 if (tr == NULL) 177 pr->head = new; 178 else 179 tr->next = new; 180 181 return; 182} 183 184int 185satrns_remove_from_list(struct satrns **listptr, struct satrns *trns) 186{ 187 188 struct satrns **ptr = listptr; 189 190 if (ptr == NULL) 191 return -1; 192 193 while (*ptr) { 194 if (*ptr == trns) { 195 *ptr = trns->next; 196 ptr = &trns->next; 197 trns->next = NULL; 198 return 0; 199 } 200 ptr = &((*ptr)->next); 201 } 202 return -1; 203} 204 205#ifdef ENABLE_NATT 206static void 207saprop_udp_encap (struct saproto *pr) 208{ 209 switch (pr->encmode) { 210 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC: 211 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT: 212 pr->encmode = IPSECDOI_ATTR_ENC_MODE_TUNNEL; 213 pr->udp_encap = 1; 214 break; 215 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC: 216 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT: 217 pr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS; 218 pr->udp_encap = 1; 219 break; 220 } 221} 222 223static void 224saprop_adjust_encmode (struct saproto *pr2, struct saproto *pr1) 225{ 226 int prev; 227 228 if (natt_udp_encap(pr2->encmode)) { 229 prev = pr2->encmode; 230 saprop_udp_encap(pr2); 231 plog(ASL_LEVEL_INFO, "Adjusting my encmode %s(%d)->%s(%d)\n", 232 s_ipsecdoi_encmode(prev), 233 prev, 234 s_ipsecdoi_encmode(pr2->encmode), 235 pr2->encmode); 236 } 237 if (natt_udp_encap(pr1->encmode)) { 238 prev = pr1->encmode; 239 saprop_udp_encap(pr1); 240 plog(ASL_LEVEL_INFO, "Adjusting peer's encmode %s(%d)->%s(%d)\n", 241 s_ipsecdoi_encmode(prev), 242 prev, 243 s_ipsecdoi_encmode(pr1->encmode), 244 pr1->encmode); 245 } 246} 247#endif // ENABLE_NATT 248 249/* 250 * take a single match between saprop. allocate a new proposal and return it 251 * for future use (like picking single proposal from a bundle). 252 * pp1: peer's proposal. 253 * pp2: my proposal. 254 * NOTE: In the case of initiator, must be ensured that there is no 255 * modification of the proposal by calling cmp_aproppair_i() before 256 * this function. 257 * XXX cannot understand the comment! 258 */ 259struct saprop * 260cmpsaprop_alloc(ph1, pp1, pp2, side) 261 phase1_handle_t *ph1; 262 const struct saprop *pp1, *pp2; 263 int side; 264{ 265 struct saprop *newpp = NULL; 266 struct saproto *pr1, *pr2, *newpr = NULL; 267 struct satrns *tr1, *tr2, *newtr; 268 const int ordermatters = 0; 269 int npr1, npr2; 270 int spisizematch; 271 272 newpp = newsaprop(); 273 if (newpp == NULL) { 274 plog(ASL_LEVEL_ERR, 275 "failed to allocate saprop.\n"); 276 return NULL; 277 } 278 newpp->prop_no = pp1->prop_no; 279 280 /* see proposal.h about lifetime/key length and PFS selection. */ 281 282 /* check time/bytes lifetime and PFS */ 283 switch (ph1->rmconf->pcheck_level) { 284 case PROP_CHECK_OBEY: 285 newpp->lifetime = pp1->lifetime; 286 newpp->lifebyte = pp1->lifebyte; 287 newpp->pfs_group = pp1->pfs_group; 288 break; 289 290 case PROP_CHECK_STRICT: 291 if (pp1->lifetime > pp2->lifetime) { 292 plog(ASL_LEVEL_ERR, 293 "long lifetime proposed: " 294 "my:%d peer:%d\n", 295 (int)pp2->lifetime, (int)pp1->lifetime); 296 goto err; 297 } 298 if (pp1->lifebyte > pp2->lifebyte) { 299 plog(ASL_LEVEL_ERR, 300 "long lifebyte proposed: " 301 "my:%d peer:%d\n", 302 pp2->lifebyte, pp1->lifebyte); 303 goto err; 304 } 305 newpp->lifetime = pp1->lifetime; 306 newpp->lifebyte = pp1->lifebyte; 307 308 prop_pfs_check: 309 if (pp2->pfs_group != 0 && pp1->pfs_group != pp2->pfs_group) { 310 plog(ASL_LEVEL_ERR, 311 "pfs group mismatched: " 312 "my:%d peer:%d\n", 313 pp2->pfs_group, pp1->pfs_group); 314 goto err; 315 } 316 newpp->pfs_group = pp1->pfs_group; 317 break; 318 319 case PROP_CHECK_CLAIM: 320 /* lifetime */ 321 if (pp1->lifetime <= pp2->lifetime) { 322 newpp->lifetime = pp1->lifetime; 323 } else { 324 newpp->lifetime = pp2->lifetime; 325 newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC; 326 plog(ASL_LEVEL_NOTICE, 327 "use own lifetime: " 328 "my:%d peer:%d\n", 329 (int)pp2->lifetime, (int)pp1->lifetime); 330 } 331 332 /* lifebyte */ 333 if (pp1->lifebyte > pp2->lifebyte) { 334 newpp->lifebyte = pp2->lifebyte; 335 newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC; 336 plog(ASL_LEVEL_NOTICE, 337 "use own lifebyte: " 338 "my:%d peer:%d\n", 339 pp2->lifebyte, pp1->lifebyte); 340 } 341 newpp->lifebyte = pp1->lifebyte; 342 343 goto prop_pfs_check; 344 break; 345 346 case PROP_CHECK_EXACT: 347 if (pp1->lifetime != pp2->lifetime) { 348 plog(ASL_LEVEL_ERR, 349 "lifetime mismatched: " 350 "my:%d peer:%d\n", 351 (int)pp2->lifetime, (int)pp1->lifetime); 352 goto err; 353 } 354 355 if (pp1->lifebyte != pp2->lifebyte) { 356 plog(ASL_LEVEL_ERR, 357 "lifebyte mismatched: " 358 "my:%d peer:%d\n", 359 pp2->lifebyte, pp1->lifebyte); 360 goto err; 361 } 362 if (pp1->pfs_group != pp2->pfs_group) { 363 plog(ASL_LEVEL_ERR, 364 "pfs group mismatched: " 365 "my:%d peer:%d\n", 366 pp2->pfs_group, pp1->pfs_group); 367 goto err; 368 } 369 newpp->lifetime = pp1->lifetime; 370 newpp->lifebyte = pp1->lifebyte; 371 newpp->pfs_group = pp1->pfs_group; 372 break; 373 374 default: 375 plog(ASL_LEVEL_ERR, 376 "invalid pcheck_level why?.\n"); 377 goto err; 378 } 379 380 npr1 = npr2 = 0; 381 for (pr1 = pp1->head; pr1; pr1 = pr1->next) 382 npr1++; 383 for (pr2 = pp2->head; pr2; pr2 = pr2->next) 384 npr2++; 385 if (npr1 != npr2) 386 goto err; 387 388 /* check protocol order */ 389 pr1 = pp1->head; 390 pr2 = pp2->head; 391 392 while (1) { 393 if (!ordermatters) { 394 /* 395 * XXX does not work if we have multiple proposals 396 * with the same proto_id 397 */ 398 switch (side) { 399 case RESPONDER: 400 if (!pr2) 401 break; 402 for (pr1 = pp1->head; pr1; pr1 = pr1->next) { 403 if (pr1->proto_id == pr2->proto_id) 404 break; 405 } 406 break; 407 case INITIATOR: 408 if (!pr1) 409 break; 410 for (pr2 = pp2->head; pr2; pr2 = pr2->next) { 411 if (pr2->proto_id == pr1->proto_id) 412 break; 413 } 414 break; 415 } 416 } 417 if (!pr1 || !pr2) 418 break; 419 420 if (pr1->proto_id != pr2->proto_id) { 421 plog(ASL_LEVEL_ERR, 422 "proto_id mismatched: " 423 "my:%s peer:%s\n", 424 s_ipsecdoi_proto(pr2->proto_id), 425 s_ipsecdoi_proto(pr1->proto_id)); 426 goto err; 427 } 428 spisizematch = 0; 429 if (pr1->spisize == pr2->spisize) 430 spisizematch = 1; 431 else if (pr1->proto_id == IPSECDOI_PROTO_IPCOMP) { 432 /* 433 * draft-shacham-ippcp-rfc2393bis-05.txt: 434 * need to accept 16bit and 32bit SPI (CPI) for IPComp. 435 */ 436 if (pr1->spisize == sizeof(u_int16_t) && 437 pr2->spisize == sizeof(u_int32_t)) { 438 spisizematch = 1; 439 } else if (pr2->spisize == sizeof(u_int16_t) && 440 pr1->spisize == sizeof(u_int32_t)) { 441 spisizematch = 1; 442 } 443 if (spisizematch) { 444 plog(ASL_LEVEL_ERR, 445 "IPComp SPI size promoted " 446 "from 16bit to 32bit\n"); 447 } 448 } 449 if (!spisizematch) { 450 plog(ASL_LEVEL_ERR, 451 "spisize mismatched: " 452 "my:%d peer:%d\n", 453 (int)pr2->spisize, (int)pr1->spisize); 454 goto err; 455 } 456 457#ifdef ENABLE_NATT 458 if (ph1->natt_flags & NAT_DETECTED) { 459 saprop_adjust_encmode(pr2, pr1); 460 } 461#endif 462 463 if (pr1->encmode != pr2->encmode) { 464 plog(ASL_LEVEL_ERR, 465 "encmode mismatched: " 466 "my:%s peer:%s\n", 467 s_ipsecdoi_encmode(pr2->encmode), 468 s_ipsecdoi_encmode(pr1->encmode)); 469 goto err; 470 } 471 472 for (tr1 = pr1->head; tr1; tr1 = tr1->next) { 473 for (tr2 = pr2->head; tr2; tr2 = tr2->next) { 474 if (cmpsatrns(pr1->proto_id, tr1, tr2) == 0) 475 goto found; 476 } 477 } 478 479 goto err; 480 481 found: 482 newpr = newsaproto(); 483 if (newpr == NULL) { 484 plog(ASL_LEVEL_ERR, 485 "failed to allocate saproto.\n"); 486 goto err; 487 } 488 newpr->proto_id = pr1->proto_id; 489 newpr->spisize = pr1->spisize; 490 newpr->encmode = pr1->encmode; 491 newpr->spi = pr2->spi; /* copy my SPI */ 492 newpr->spi_p = pr1->spi; /* copy peer's SPI */ 493 newpr->reqid_in = pr2->reqid_in; 494 newpr->reqid_out = pr2->reqid_out; 495#ifdef ENABLE_NATT 496 newpr->udp_encap = pr1->udp_encap | pr2->udp_encap; 497#endif 498 499 newtr = newsatrns(); 500 if (newtr == NULL) { 501 plog(ASL_LEVEL_ERR, 502 "failed to allocate satrns.\n"); 503 racoon_free(newpr); 504 goto err; 505 } 506 newtr->trns_no = tr1->trns_no; 507 newtr->trns_id = tr1->trns_id; 508 newtr->encklen = tr1->encklen; 509 newtr->authtype = tr1->authtype; 510 511 inssatrns(newpr, newtr); 512 inssaproto(newpp, newpr); 513 514 pr1 = pr1->next; 515 pr2 = pr2->next; 516 } 517 518 /* XXX should check if we have visited all items or not */ 519 if (!ordermatters) { 520 switch (side) { 521 case RESPONDER: 522 if (!pr2) 523 pr1 = NULL; 524 break; 525 case INITIATOR: 526 if (!pr1) 527 pr2 = NULL; 528 break; 529 } 530 } 531 532 /* should be matched all protocols in a proposal */ 533 if (pr1 != NULL || pr2 != NULL) 534 goto err; 535 536 return newpp; 537 538err: 539 flushsaprop(newpp); 540 return NULL; 541} 542 543/* take a single match between saprop. returns 0 if pp1 equals to pp2. */ 544int 545cmpsaprop(pp1, pp2) 546 const struct saprop *pp1, *pp2; 547{ 548 if (pp1->pfs_group != pp2->pfs_group) { 549 plog(ASL_LEVEL_WARNING, 550 "pfs_group mismatch. mine:%d peer:%d\n", 551 pp1->pfs_group, pp2->pfs_group); 552 /* FALLTHRU */ 553 } 554 555 if (pp1->lifetime > pp2->lifetime) { 556 plog(ASL_LEVEL_WARNING, 557 "less lifetime proposed. mine:%d peer:%d\n", 558 (int)pp1->lifetime, (int)pp2->lifetime); 559 /* FALLTHRU */ 560 } 561 if (pp1->lifebyte > pp2->lifebyte) { 562 plog(ASL_LEVEL_WARNING, 563 "less lifebyte proposed. mine:%d peer:%d\n", 564 pp1->lifebyte, pp2->lifebyte); 565 /* FALLTHRU */ 566 } 567 568 return 0; 569} 570 571/* 572 * take a single match between satrns. returns 0 if tr1 equals to tr2. 573 * tr1: peer's satrns 574 * tr2: my satrns 575 */ 576int 577cmpsatrns(proto_id, tr1, tr2) 578 int proto_id; 579 const struct satrns *tr1, *tr2; 580{ 581 if (tr1->trns_id != tr2->trns_id) { 582 plog(ASL_LEVEL_DEBUG, 583 "trns_id mismatched: " 584 "my:%s peer:%s\n", 585 s_ipsecdoi_trns(proto_id, tr2->trns_id), 586 s_ipsecdoi_trns(proto_id, tr1->trns_id)); 587 return 1; 588 } 589 590 if (tr1->authtype != tr2->authtype) { 591 plog(ASL_LEVEL_DEBUG, 592 "authtype mismatched: " 593 "my:%s peer:%s\n", 594 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr2->authtype), 595 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr1->authtype)); 596 return 1; 597 } 598 599 /* XXX 600 * At this moment for interoperability, the responder obey 601 * the initiator. It should be defined a notify message. 602 */ 603 if (tr1->encklen > tr2->encklen) { 604 plog(ASL_LEVEL_WARNING, 605 "less key length proposed, " 606 "mine:%d peer:%d. Use initiaotr's one.\n", 607 tr2->encklen, tr1->encklen); 608 /* FALLTHRU */ 609 } 610 611 return 0; 612} 613 614int 615set_satrnsbysainfo(struct saproto *pr, struct sainfo *sainfo, u_int8_t ike_version, int pfs_group) 616{ 617 struct sainfoalg *a, *b; 618 struct satrns *newtr; 619 int t; 620 621 switch (pr->proto_id) { 622 case IPSECDOI_PROTO_IPSEC_AH: 623 if (sainfo->algs[algclass_ipsec_auth] == NULL) { 624 plog(ASL_LEVEL_ERR, 625 "no auth algorithm found\n"); 626 goto err; 627 } 628 t = 1; 629 for (a = sainfo->algs[algclass_ipsec_auth]; a; a = a->next) { 630 631 if (a->alg == IPSECDOI_ATTR_AUTH_NONE) 632 continue; 633 634 /* allocate satrns */ 635 newtr = newsatrns(); 636 if (newtr == NULL) { 637 plog(ASL_LEVEL_ERR, 638 "failed to allocate satrns.\n"); 639 goto err; 640 } 641 642 newtr->trns_no = t++; 643 newtr->trns_id = ipsecdoi_authalg2trnsid(a->alg); // IKEv1 only 644 newtr->authtype = a->alg; 645 646 inssatrns(pr, newtr); 647 } 648 break; 649 case IPSECDOI_PROTO_IPSEC_ESP: 650 if (sainfo->algs[algclass_ipsec_enc] == NULL) { 651 plog(ASL_LEVEL_ERR, 652 "no encryption algorithm found\n"); 653 goto err; 654 } 655 t = 1; 656 if (ike_version == ISAKMP_VERSION_NUMBER_IKEV1) { 657 for (a = sainfo->algs[algclass_ipsec_enc]; a; a = a->next) { 658 for (b = sainfo->algs[algclass_ipsec_auth]; b; b = b->next) { 659 /* allocate satrns */ 660 newtr = newsatrns(); 661 if (newtr == NULL) { 662 plog(ASL_LEVEL_ERR, 663 "failed to allocate satrns.\n"); 664 goto err; 665 } 666 667 newtr->trns_no = t++; 668 newtr->trns_id = a->alg; 669 newtr->encklen = a->encklen; 670 newtr->authtype = b->alg; 671 672 inssatrns(pr, newtr); 673 } 674 } 675 } 676 break; 677 case IPSECDOI_PROTO_IPCOMP: 678 if (sainfo->algs[algclass_ipsec_comp] == NULL) { 679 plog(ASL_LEVEL_ERR, 680 "no ipcomp algorithm found\n"); 681 goto err; 682 } 683 t = 1; 684 for (a = sainfo->algs[algclass_ipsec_comp]; a; a = a->next) { 685 686 /* allocate satrns */ 687 newtr = newsatrns(); 688 if (newtr == NULL) { 689 plog(ASL_LEVEL_ERR, 690 "failed to allocate satrns.\n"); 691 goto err; 692 } 693 694 newtr->trns_no = t++; 695 newtr->trns_id = a->alg; 696 newtr->authtype = IPSECDOI_ATTR_AUTH_NONE; /*no auth*/ 697 698 inssatrns(pr, newtr); 699 } 700 break; 701 default: 702 plog(ASL_LEVEL_ERR, 703 "unknown proto_id (%d).\n", pr->proto_id); 704 goto err; 705 } 706 707 /* no proposal found */ 708 if (pr->head == NULL) { 709 plog(ASL_LEVEL_ERR, "no algorithms found.\n"); 710 return -1; 711 } 712 713 return 0; 714 715err: 716 flushsatrns(pr->head); 717 return -1; 718} 719 720struct saprop * 721aproppair2saprop(p0) 722 struct prop_pair *p0; 723{ 724 struct prop_pair *p, *t; 725 struct saprop *newpp; 726 struct saproto *newpr; 727 struct satrns *newtr; 728 u_int8_t *spi; 729 730 if (p0 == NULL) 731 return NULL; 732 733 /* allocate ipsec a sa proposal */ 734 newpp = newsaprop(); 735 if (newpp == NULL) { 736 plog(ASL_LEVEL_ERR, 737 "failed to allocate saprop.\n"); 738 return NULL; 739 } 740 newpp->prop_no = p0->prop->p_no; 741 /* lifetime & lifebyte must be updated later */ 742 743 for (p = p0; p; p = p->next) { 744 745 /* allocate ipsec sa protocol */ 746 newpr = newsaproto(); 747 if (newpr == NULL) { 748 plog(ASL_LEVEL_ERR, 749 "failed to allocate saproto.\n"); 750 goto err; 751 } 752 753 /* check spi size */ 754 /* XXX should be handled isakmp cookie */ 755 if (sizeof(newpr->spi) < p->prop->spi_size) { 756 plog(ASL_LEVEL_ERR, 757 "invalid spi size %d.\n", p->prop->spi_size); 758 racoon_free(newpr); 759 goto err; 760 } 761 762 /* 763 * XXX SPI bits are left-filled, for use with IPComp. 764 * we should be switching to variable-length spi field... 765 */ 766 newpr->proto_id = p->prop->proto_id; 767 newpr->spisize = p->prop->spi_size; 768 memset(&newpr->spi, 0, sizeof(newpr->spi)); 769 spi = (u_int8_t *)&newpr->spi; 770 spi += sizeof(newpr->spi); 771 spi -= p->prop->spi_size; 772 memcpy(spi, p->prop + 1, p->prop->spi_size); 773 newpr->reqid_in = 0; 774 newpr->reqid_out = 0; 775 776 for (t = p; t; t = t->tnext) { 777 778 plog(ASL_LEVEL_DEBUG, 779 "prop#=%d prot-id=%s spi-size=%d " 780 "#trns=%d trns#=%d trns-id=%s\n", 781 t->prop->p_no, 782 s_ipsecdoi_proto(t->prop->proto_id), 783 t->prop->spi_size, t->prop->num_t, 784 t->trns->t_no, 785 s_ipsecdoi_trns(t->prop->proto_id, 786 t->trns->t_id)); 787 788 /* allocate ipsec sa transform */ 789 newtr = newsatrns(); 790 if (newtr == NULL) { 791 plog(ASL_LEVEL_ERR, 792 "failed to allocate satrns.\n"); 793 racoon_free(newpr); 794 goto err; 795 } 796 797 if (ipsecdoi_t2satrns(t->trns, 798 newpp, newpr, newtr) < 0) { 799 flushsaprop(newpp); 800 racoon_free(newtr); 801 racoon_free(newpr); 802 return NULL; 803 } 804 805 inssatrns(newpr, newtr); 806 } 807 808 /* 809 * If the peer does not specify encryption mode, use 810 * transport mode by default. This is to conform to 811 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies 812 * that unspecified == transport), as well as RFC2407 813 * (unspecified == implementation dependent default). 814 */ 815 if (newpr->encmode == 0) 816 newpr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS; 817 818 inssaproto(newpp, newpr); 819 } 820 821 return newpp; 822 823err: 824 flushsaprop(newpp); 825 return NULL; 826} 827 828void 829flushsaprop(head) 830 struct saprop *head; 831{ 832 struct saprop *p, *save; 833 834 for (p = head; p != NULL; p = save) { 835 save = p->next; 836 flushsaproto(p->head); 837 racoon_free(p); 838 } 839 840 return; 841} 842 843void 844flushsaproto(head) 845 struct saproto *head; 846{ 847 struct saproto *p, *save; 848 849 for (p = head; p != NULL; p = save) { 850 save = p->next; 851 flushsatrns(p->head); 852 vfree(p->keymat); 853 vfree(p->keymat_p); 854 racoon_free(p); 855 } 856 857 return; 858} 859 860void 861flushsatrns(head) 862 struct satrns *head; 863{ 864 struct satrns *p, *save; 865 866 for (p = head; p != NULL; p = save) { 867 save = p->next; 868 racoon_free(p); 869 } 870 871 return; 872} 873 874/* 875 * print multiple proposals 876 */ 877void 878printsaprop(pri, pp) 879 const int pri; 880 const struct saprop *pp; 881{ 882 const struct saprop *p; 883 884 if (pp == NULL) { 885 plog(pri, "(null)"); 886 return; 887 } 888 889 for (p = pp; p; p = p->next) { 890 printsaprop0(pri, p); 891 } 892 893 return; 894} 895 896/* 897 * print one proposal. 898 */ 899void 900printsaprop0(pri, pp) 901 int pri; 902 const struct saprop *pp; 903{ 904 const struct saproto *p; 905 906 if (pp == NULL) 907 return; 908 909 for (p = pp->head; p; p = p->next) { 910 printsaproto(pri, p); 911 } 912 913 return; 914} 915 916void 917printsaproto(pri, pr) 918 const int pri; 919 const struct saproto *pr; 920{ 921 struct satrns *tr; 922 923 if (pr == NULL) 924 return; 925 926 plog(pri, 927 " (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx " 928 "encmode=%s reqid=%d:%d)\n", 929 s_ipsecdoi_proto(pr->proto_id), 930 (int)pr->spisize, 931 (unsigned long)ntohl(pr->spi), 932 (unsigned long)ntohl(pr->spi_p), 933 s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE, pr->encmode), 934 (int)pr->reqid_in, (int)pr->reqid_out); 935 936 for (tr = pr->head; tr; tr = tr->next) { 937 printsatrns(pri, pr->proto_id, tr); 938 } 939 940 return; 941} 942 943void 944printsatrns(pri, proto_id, tr) 945 const int pri; 946 const int proto_id; 947 const struct satrns *tr; 948{ 949 if (tr == NULL) 950 return; 951 952 switch (proto_id) { 953 case IPSECDOI_PROTO_IPSEC_AH: 954 plog(pri, 955 " (trns_id=%s authtype=%s)\n", 956 s_ipsecdoi_trns(proto_id, tr->trns_id), 957 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype)); 958 break; 959 case IPSECDOI_PROTO_IPSEC_ESP: 960 plog(pri, 961 " (trns_id=%s encklen=%d authtype=%s)\n", 962 s_ipsecdoi_trns(proto_id, tr->trns_id), 963 tr->encklen, 964 s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype)); 965 break; 966 case IPSECDOI_PROTO_IPCOMP: 967 plog(pri, 968 " (trns_id=%s)\n", 969 s_ipsecdoi_trns(proto_id, tr->trns_id)); 970 break; 971 default: 972 plog(pri, 973 "(unknown proto_id %d)\n", proto_id); 974 } 975 976 return; 977} 978 979void 980print_proppair0(pri, p, level) 981 int pri; 982 struct prop_pair *p; 983 int level; 984{ 985 char spc[21]; 986 987 memset(spc, ' ', sizeof(spc)); 988 spc[sizeof(spc) - 1] = '\0'; 989 if (level < 20) { 990 spc[level] = '\0'; 991 } 992 993 plog(pri, 994 "%s%p: next=%p tnext=%p\n", spc, p, p->next, p->tnext); 995 if (p->next) 996 print_proppair0(pri, p->next, level + 1); 997 if (p->tnext) 998 print_proppair0(pri, p->tnext, level + 1); 999} 1000 1001void 1002print_proppair(pri, p) 1003 int pri; 1004 struct prop_pair *p; 1005{ 1006 print_proppair0(pri, p, 1); 1007} 1008 1009int 1010set_proposal_from_policy(iph2, sp_main, sp_sub) 1011 phase2_handle_t *iph2; 1012 struct secpolicy *sp_main, *sp_sub; 1013{ 1014 struct saprop *newpp; 1015 struct ipsecrequest *req; 1016 int encmodesv = IPSEC_MODE_TRANSPORT; /* use only when complex_bundle */ 1017 1018 newpp = newsaprop(); 1019 if (newpp == NULL) { 1020 plog(ASL_LEVEL_ERR, 1021 "failed to allocate saprop.\n"); 1022 goto err; 1023 } 1024 newpp->prop_no = 1; 1025 newpp->lifetime = iph2->sainfo->lifetime; 1026 newpp->lifebyte = iph2->sainfo->lifebyte; 1027 newpp->pfs_group = iph2->sainfo->pfs_group; 1028 1029 //%%%% to do - verify DH group is OK - tried that here and iphone failed to connect 1030 1031 if (lcconf->complex_bundle) 1032 goto skip1; 1033 1034 /* 1035 * decide the encryption mode of this SA bundle. 1036 * the mode becomes tunnel mode when there is even one policy 1037 * of tunnel mode in the SPD. otherwise the mode becomes 1038 * transport mode. 1039 */ 1040 encmodesv = IPSEC_MODE_TRANSPORT; 1041 for (req = sp_main->req; req; req = req->next) { 1042 if (req->saidx.mode == IPSEC_MODE_TUNNEL) { 1043 encmodesv = pfkey2ipsecdoi_mode(req->saidx.mode); 1044#ifdef ENABLE_NATT 1045 if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED)) 1046 encmodesv += iph2->ph1->natt_options->mode_udp_diff; 1047#endif 1048 break; 1049 } 1050 } 1051 1052 skip1: 1053 //%%%%%%s IKEv2 - no support for bundle - fix this - return error if bundle ??? 1054 // %%%% need special handling for ipcomp 1055 for (req = sp_main->req; req; req = req->next) { 1056 struct saproto *newpr; 1057 caddr_t paddr = NULL; 1058 1059 /* 1060 * check if SA bundle ? 1061 * nested SAs negotiation is NOT supported. 1062 * me +--- SA1 ---+ peer1 1063 * me +--- SA2 --------------+ peer2 1064 */ 1065 if (req->saidx.src.ss_len && req->saidx.dst.ss_len) { 1066 /* check the end of ip addresses of SA */ 1067 if (iph2->side == INITIATOR) 1068 paddr = (caddr_t)&req->saidx.dst; 1069 else 1070 paddr = (caddr_t)&req->saidx.src; 1071 } 1072 1073 /* allocate ipsec sa protocol */ 1074 newpr = newsaproto(); 1075 if (newpr == NULL) { 1076 plog(ASL_LEVEL_ERR, 1077 "failed to allocate saproto.\n"); 1078 goto err; 1079 } 1080 1081 newpr->proto_id = ipproto2doi(req->saidx.proto); 1082 if (newpr->proto_id == IPSECDOI_PROTO_IPCOMP) 1083 newpr->spisize = 2; 1084 else 1085 newpr->spisize = 4; 1086 if (lcconf->complex_bundle) { 1087 encmodesv = newpr->encmode = pfkey2ipsecdoi_mode(req->saidx.mode); 1088#ifdef ENABLE_NATT 1089 if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED)) 1090 newpr->encmode += iph2->ph1->natt_options->mode_udp_diff; 1091#endif 1092 } 1093 else 1094 encmodesv = newpr->encmode = encmodesv; 1095 if (iph2->side == INITIATOR) 1096 newpr->reqid_out = req->saidx.reqid; 1097 else 1098 newpr->reqid_in = req->saidx.reqid; 1099 1100 if (set_satrnsbysainfo(newpr, iph2->sainfo, iph2->version, newpp->pfs_group) < 0) { 1101 plog(ASL_LEVEL_ERR, 1102 "failed to get algorithms.\n"); 1103 racoon_free(newpr); 1104 goto err; 1105 } 1106 1107 /* set new saproto */ 1108 inssaprotorev(newpp, newpr); 1109 } 1110 1111 /* get reqid_in from inbound policy */ 1112 if (sp_sub) { 1113 struct saproto *pr; 1114 1115 req = sp_sub->req; 1116 pr = newpp->head; 1117 while (req && pr) { 1118 if (iph2->side == INITIATOR) 1119 pr->reqid_in = req->saidx.reqid; 1120 else 1121 pr->reqid_out = req->saidx.reqid; 1122 pr = pr->next; 1123 req = req->next; 1124 } 1125 if (pr || req) { 1126 plog(ASL_LEVEL_NOTICE, 1127 "There is a difference " 1128 "between the in/out bound policies in SPD.\n"); 1129 } 1130 } 1131 1132 iph2->proposal = newpp; 1133 1134 ike_session_update_mode(iph2); 1135 1136 printsaprop0(ASL_LEVEL_DEBUG, newpp); 1137 1138 return 0; 1139err: 1140 if (newpp) 1141 flushsaprop(newpp); 1142 return -1; 1143} 1144 1145/* 1146 * generate a policy from peer's proposal. 1147 * this function unconditionally chooses the first proposal the in SA payload 1148 * passed by peer. 1149 */ 1150int 1151set_proposal_from_proposal(iph2) 1152 phase2_handle_t *iph2; 1153{ 1154 struct saprop *newpp = NULL, *pp0, *pp_peer = NULL; 1155 struct saproto *newpr = NULL, *pr; 1156 struct prop_pair **pair; 1157 int error = -1; 1158 int i; 1159 1160 /* get proposal pair */ 1161 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) 1162 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2); 1163 if (pair == NULL) 1164 goto end; 1165 1166 /* 1167 * make my proposal according as the client proposal. 1168 * XXX assumed there is only one proposal even if it's the SA bundle. 1169 */ 1170 for (i = 0; i < MAXPROPPAIRLEN; i++) { 1171 if (pair[i] == NULL) 1172 continue; 1173 1174 if (pp_peer != NULL) 1175 flushsaprop(pp_peer); 1176 1177 pp_peer = aproppair2saprop(pair[i]); 1178 if (pp_peer == NULL) 1179 goto end; 1180 1181 pp0 = newsaprop(); 1182 if (pp0 == NULL) { 1183 plog(ASL_LEVEL_ERR, 1184 "failed to allocate saprop.\n"); 1185 goto end; 1186 } 1187 pp0->prop_no = 1; 1188 pp0->lifetime = iph2->sainfo->lifetime; 1189 pp0->lifebyte = iph2->sainfo->lifebyte; 1190 pp0->pfs_group = iph2->sainfo->pfs_group; 1191 1192 if (pp_peer->next != NULL) { 1193 plog(ASL_LEVEL_ERR, 1194 "pp_peer is inconsistency, ignore it.\n"); 1195 /*FALLTHROUGH*/ 1196 } 1197 1198 for (pr = pp_peer->head; pr; pr = pr->next) { 1199 1200 newpr = newsaproto(); 1201 if (newpr == NULL) { 1202 plog(ASL_LEVEL_ERR, 1203 "failed to allocate saproto.\n"); 1204 racoon_free(pp0); 1205 goto end; 1206 } 1207 newpr->proto_id = pr->proto_id; 1208 newpr->spisize = pr->spisize; 1209 newpr->encmode = pr->encmode; 1210 newpr->spi = 0; 1211 newpr->spi_p = pr->spi; /* copy peer's SPI */ 1212 newpr->reqid_in = 0; 1213 newpr->reqid_out = 0; 1214 1215 if (set_satrnsbysainfo(newpr, iph2->sainfo, iph2->version, 0) < 0) { 1216 plog(ASL_LEVEL_ERR, 1217 "failed to get algorithms.\n"); 1218 racoon_free(newpr); 1219 racoon_free(pp0); 1220 goto end; 1221 } 1222 inssaproto(pp0, newpr); 1223 } 1224 1225 inssaprop(&newpp, pp0); 1226 } 1227 1228 plog(ASL_LEVEL_DEBUG, "make a proposal from peer's:\n"); 1229 printsaprop0(ASL_LEVEL_DEBUG, newpp); 1230 1231 iph2->proposal = newpp; 1232 1233 ike_session_update_mode(iph2); 1234 1235 error = 0; 1236 1237end: 1238 if (error && newpp) 1239 flushsaprop(newpp); 1240 1241 if (pp_peer) 1242 flushsaprop(pp_peer); 1243 if (pair) 1244 free_proppair(pair); 1245 return error; 1246} 1247 1248int 1249tunnel_mode_prop(p) 1250 struct saprop *p; 1251{ 1252 struct saproto *pr; 1253 1254 for (pr = p->head; pr; pr = pr->next) 1255 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) 1256 return 1; 1257 return 0; 1258} 1259 1260struct satrns * 1261dupsatrns_1(struct satrns *tr) 1262{ 1263 struct satrns *newtr; 1264 1265 newtr = racoon_calloc(1, sizeof(*newtr)); 1266 if (newtr == NULL) 1267 return NULL; 1268 newtr->trns_no = tr->trns_no; 1269 newtr->trns_type = tr->trns_type; 1270 newtr->trns_id = tr->trns_id; 1271 newtr->encklen = tr->encklen; 1272 newtr->authtype = tr->authtype; 1273 1274 return newtr; 1275} 1276 1277void 1278dupsatrns(newpr, head) 1279 struct saproto *newpr; 1280 struct satrns *head; 1281{ 1282 struct satrns *p, *newtr; 1283 1284 for (p = head; p != NULL; p = p->next) { 1285 newtr = newsatrns(); 1286 if (newtr) { 1287 newtr->trns_no = p->trns_no; 1288 newtr->trns_type = p->trns_type; 1289 newtr->trns_id = p->trns_id; 1290 newtr->encklen = p->encklen; 1291 newtr->authtype = p->authtype; 1292 inssatrns(newpr, newtr); 1293 } else { 1294 break; 1295 } 1296 1297 } 1298 1299 return; 1300} 1301 1302void 1303dupsaproto(newpp, head, ignore_spis) 1304 struct saprop *newpp; 1305 struct saproto *head; 1306 int ignore_spis; 1307{ 1308 struct saproto *p, *newpr; 1309 1310 for (p = head; p != NULL; p = p->next) { 1311 newpr = newsaproto(); 1312 if (newpr) { 1313 newpr->proto_id = p->proto_id; 1314 newpr->spisize = p->spisize; 1315 newpr->encmode = p->encmode; 1316 newpr->udp_encap = p->udp_encap; 1317 if (!ignore_spis) { 1318 newpr->spi = p->spi; 1319 newpr->spi_p = p->spi_p; 1320 newpr->reqid_in = p->reqid_in; 1321 newpr->reqid_out = p->reqid_out; 1322 } 1323 dupsatrns(newpr, p->head); 1324 inssaproto(newpp, newpr); 1325 } else { 1326 break; 1327 } 1328 1329 } 1330 1331 return; 1332} 1333 1334struct saprop * 1335dupsaprop(head, ignore_spis) 1336 struct saprop *head; 1337 int ignore_spis; 1338{ 1339 struct saprop *p, *newpp; 1340 1341 for (p = head, newpp = NULL; p != NULL; p = p->next) { 1342 struct saprop *tmp = newsaprop(); 1343 if (tmp) { 1344 tmp->prop_no = p->prop_no; 1345 tmp->lifetime = p->lifetime; 1346 tmp->lifebyte = p->lifebyte; 1347 tmp->pfs_group = p->pfs_group; 1348 tmp->claim = p->claim; 1349 dupsaproto(tmp, p->head, ignore_spis); 1350 inssaprop(&newpp, tmp); 1351 } else { 1352 break; 1353 } 1354 } 1355 1356 return newpp; 1357} 1358