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