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