1 /* $NetBSD: isakmp_quick.c,v 1.30 2025/03/07 15:55:29 christos Exp $ */ 2 3 /* Id: isakmp_quick.c,v 1.29 2006/08/22 18:17:17 manubsd Exp */ 4 5 /* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "config.h" 35 36 #include <sys/types.h> 37 #include <sys/param.h> 38 #include <sys/socket.h> 39 40 #include <netinet/in.h> 41 42 #include <stdlib.h> 43 #include <stdio.h> 44 #include <string.h> 45 #include <errno.h> 46 #if TIME_WITH_SYS_TIME 47 # include <sys/time.h> 48 # include <time.h> 49 #else 50 # if HAVE_SYS_TIME_H 51 # include <sys/time.h> 52 # else 53 # include <time.h> 54 # endif 55 #endif 56 57 #include PATH_IPSEC_H 58 59 #include "var.h" 60 #include "vmbuf.h" 61 #include "schedule.h" 62 #include "misc.h" 63 #include "plog.h" 64 #include "debug.h" 65 66 #include "localconf.h" 67 #include "remoteconf.h" 68 #include "handler.h" 69 #include "policy.h" 70 #include "proposal.h" 71 #include "isakmp_var.h" 72 #include "isakmp.h" 73 #include "isakmp_inf.h" 74 #include "isakmp_quick.h" 75 #include "oakley.h" 76 #include "ipsec_doi.h" 77 #include "crypto_openssl.h" 78 #include "pfkey.h" 79 #include "policy.h" 80 #include "algorithm.h" 81 #include "sockmisc.h" 82 #include "proposal.h" 83 #include "sainfo.h" 84 #include "admin.h" 85 #include "strnames.h" 86 87 #ifdef ENABLE_HYBRID 88 #include <resolv.h> 89 #include "isakmp_xauth.h" 90 #include "isakmp_cfg.h" 91 #endif 92 93 #ifdef ENABLE_NATT 94 #include "nattraversal.h" 95 #endif 96 97 /* quick mode */ 98 static vchar_t *quick_ir1mx(struct ph2handle *, vchar_t *, vchar_t *); 99 static int get_sainfo_r(struct ph2handle *); 100 static int get_proposal_r(struct ph2handle *); 101 static int ph2_recv_n(struct ph2handle *, struct isakmp_gen *); 102 static void quick_timeover_stub(struct sched *); 103 static void quick_timeover(struct ph2handle *); 104 105 /* called from scheduler */ 106 static void 107 quick_timeover_stub(struct sched *p) 108 { 109 quick_timeover(container_of(p, struct ph2handle, sce)); 110 } 111 112 static void 113 quick_timeover(struct ph2handle *iph2) 114 { 115 plog(LLV_ERROR, LOCATION, NULL, 116 "%s give up to get IPsec-SA due to time up to wait.\n", 117 saddrwop2str(iph2->dst)); 118 119 /* If initiator side, send error to kernel by SADB_ACQUIRE. */ 120 if (iph2->side == INITIATOR) 121 pk_sendeacquire(iph2); 122 123 remph2(iph2); 124 delph2(iph2); 125 } 126 127 /* %%% 129 * Quick Mode 130 */ 131 /* 132 * begin Quick Mode as initiator. send pfkey getspi message to kernel. 133 */ 134 /*ARGSUSED*/ 135 int 136 quick_i1prep(struct ph2handle *iph2, vchar_t *msg __unused) /* must be null pointer */ 137 { 138 int error = ISAKMP_INTERNAL_ERROR; 139 140 /* validity check */ 141 if (iph2->status != PHASE2ST_STATUS2) { 142 plog(LLV_ERROR, LOCATION, NULL, 143 "status mismatched %d.\n", iph2->status); 144 goto end; 145 } 146 147 iph2->msgid = isakmp_newmsgid2(iph2->ph1); 148 iph2->ivm = oakley_newiv2(iph2->ph1, iph2->msgid); 149 if (iph2->ivm == NULL) 150 return 0; 151 152 iph2->status = PHASE2ST_GETSPISENT; 153 154 /* don't anything if local test mode. */ 155 if (f_local) { 156 error = 0; 157 goto end; 158 } 159 160 /* send getspi message */ 161 if (pk_sendgetspi(iph2) < 0) 162 goto end; 163 164 plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n"); 165 166 sched_schedule(&iph2->sce, lcconf->wait_ph2complete, 167 quick_timeover_stub); 168 169 error = 0; 170 171 end: 172 return error; 173 } 174 175 /* 176 * send to responder 177 * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ] 178 */ 179 int 180 quick_i1send(struct ph2handle *iph2, vchar_t *msg) /* must be null pointer */ 181 { 182 vchar_t *body = NULL; 183 vchar_t *hash = NULL; 184 struct isakmp_gen *gen; 185 char *p; 186 size_t tlen; 187 int error = ISAKMP_INTERNAL_ERROR; 188 int natoa = ISAKMP_NPTYPE_NONE; 189 int pfsgroup, idci, idcr; 190 int np; 191 struct ipsecdoi_id_b *id, *id_p; 192 #ifdef ENABLE_NATT 193 vchar_t *nat_oai = NULL; 194 vchar_t *nat_oar = NULL; 195 #endif 196 197 /* validity check */ 198 if (msg != NULL) { 199 plog(LLV_ERROR, LOCATION, NULL, 200 "msg has to be NULL in this function.\n"); 201 goto end; 202 } 203 if (iph2->status != PHASE2ST_GETSPIDONE) { 204 plog(LLV_ERROR, LOCATION, NULL, 205 "status mismatched %d.\n", iph2->status); 206 goto end; 207 } 208 209 /* create SA payload for my proposal */ 210 if (ipsecdoi_setph2proposal(iph2) < 0) 211 goto end; 212 213 /* generate NONCE value */ 214 iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size); 215 if (iph2->nonce == NULL) 216 goto end; 217 218 /* 219 * DH value calculation is kicked out into cfparse.y. 220 * because pfs group can not be negotiated, it's only to be checked 221 * acceptable. 222 */ 223 /* generate KE value if need */ 224 pfsgroup = iph2->proposal->pfs_group; 225 if (pfsgroup) { 226 /* DH group settting if PFS is required. */ 227 if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) { 228 plog(LLV_ERROR, LOCATION, NULL, 229 "failed to set DH value.\n"); 230 goto end; 231 } 232 if (oakley_dh_generate(iph2->pfsgrp, 233 &iph2->dhpub, &iph2->dhpriv) < 0) { 234 goto end; 235 } 236 } 237 238 /* generate ID value */ 239 if (ipsecdoi_setid2(iph2) < 0) { 240 plog(LLV_ERROR, LOCATION, NULL, 241 "failed to get ID.\n"); 242 goto end; 243 } 244 plog(LLV_DEBUG, LOCATION, NULL, "IDci:\n"); 245 plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l); 246 plog(LLV_DEBUG, LOCATION, NULL, "IDcr:\n"); 247 plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l); 248 249 /* 250 * we do not attach IDci nor IDcr, under the following condition: 251 * - all proposals are transport mode 252 * - no MIP6 or proxy 253 * - id payload suggests to encrypt all the traffic (no specific 254 * protocol type) 255 * - SA endpoints and IKE addresses for the nego are the same 256 * (iph2->src/dst) 257 */ 258 id = (struct ipsecdoi_id_b *)iph2->id->v; 259 id_p = (struct ipsecdoi_id_b *)iph2->id_p->v; 260 if (id->proto_id == 0 && 261 id_p->proto_id == 0 && 262 iph2->ph1->rmconf->support_proxy == 0 && 263 iph2->sa_src == NULL && iph2->sa_dst == NULL && 264 ipsecdoi_transportmode(iph2->proposal)) { 265 idci = idcr = 0; 266 } else 267 idci = idcr = 1; 268 269 #ifdef ENABLE_NATT 270 /* 271 * RFC3947 5.2. if we propose UDP-Encapsulated-Transport 272 * we should send NAT-OA 273 */ 274 if (ipsecdoi_transportmode(iph2->proposal) 275 && (iph2->ph1->natt_flags & NAT_DETECTED)) { 276 natoa = iph2->ph1->natt_options->payload_nat_oa; 277 278 nat_oai = ipsecdoi_sockaddr2id(iph2->src, 279 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY); 280 nat_oar = ipsecdoi_sockaddr2id(iph2->dst, 281 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY); 282 283 if (nat_oai == NULL || nat_oar == NULL) { 284 plog(LLV_ERROR, LOCATION, NULL, 285 "failed to generate NAT-OA payload.\n"); 286 goto end; 287 } 288 289 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n"); 290 plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l); 291 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n"); 292 plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l); 293 } else { 294 natoa = ISAKMP_NPTYPE_NONE; 295 } 296 #endif 297 298 /* create SA;NONCE payload, and KE if need, and IDii, IDir. */ 299 tlen = + sizeof(*gen) + iph2->sa->l 300 + sizeof(*gen) + iph2->nonce->l; 301 if (pfsgroup) 302 tlen += (sizeof(*gen) + iph2->dhpub->l); 303 if (idci) 304 tlen += sizeof(*gen) + iph2->id->l; 305 if (idcr) 306 tlen += sizeof(*gen) + iph2->id_p->l; 307 #ifdef ENABLE_NATT 308 if (natoa != ISAKMP_NPTYPE_NONE) 309 tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l; 310 #endif 311 312 body = vmalloc(tlen); 313 if (body == NULL) { 314 plog(LLV_ERROR, LOCATION, NULL, 315 "failed to get buffer to send.\n"); 316 goto end; 317 } 318 319 p = body->v; 320 321 /* add SA payload */ 322 p = set_isakmp_payload(p, iph2->sa, ISAKMP_NPTYPE_NONCE); 323 324 /* add NONCE payload */ 325 if (pfsgroup) 326 np = ISAKMP_NPTYPE_KE; 327 else if (idci || idcr) 328 np = ISAKMP_NPTYPE_ID; 329 else 330 np = natoa; 331 p = set_isakmp_payload(p, iph2->nonce, np); 332 333 /* add KE payload if need. */ 334 np = (idci || idcr) ? ISAKMP_NPTYPE_ID : natoa; 335 if (pfsgroup) 336 p = set_isakmp_payload(p, iph2->dhpub, np); 337 338 /* IDci */ 339 np = (idcr) ? ISAKMP_NPTYPE_ID : natoa; 340 if (idci) 341 p = set_isakmp_payload(p, iph2->id, np); 342 343 /* IDcr */ 344 if (idcr) 345 p = set_isakmp_payload(p, iph2->id_p, natoa); 346 347 #ifdef ENABLE_NATT 348 /* NAT-OA */ 349 if (natoa != ISAKMP_NPTYPE_NONE) { 350 p = set_isakmp_payload(p, nat_oai, natoa); 351 p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE); 352 } 353 #endif 354 355 /* generate HASH(1) */ 356 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body); 357 if (hash == NULL) 358 goto end; 359 360 /* send isakmp payload */ 361 iph2->sendbuf = quick_ir1mx(iph2, body, hash); 362 if (iph2->sendbuf == NULL) 363 goto end; 364 365 /* send the packet, add to the schedule to resend */ 366 if (isakmp_ph2send(iph2) == -1) 367 goto end; 368 369 /* change status of isakmp status entry */ 370 iph2->status = PHASE2ST_MSG1SENT; 371 372 error = 0; 373 374 end: 375 if (body != NULL) 376 vfree(body); 377 if (hash != NULL) 378 vfree(hash); 379 #ifdef ENABLE_NATT 380 if (nat_oai != NULL) 381 vfree(nat_oai); 382 if (nat_oar != NULL) 383 vfree(nat_oar); 384 #endif 385 386 return error; 387 } 388 389 /* 390 * receive from responder 391 * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ] 392 */ 393 int 394 quick_i2recv(struct ph2handle *iph2, vchar_t *msg0) 395 { 396 vchar_t *msg = NULL; 397 vchar_t *hbuf = NULL; /* for hash computing. */ 398 vchar_t *pbuf = NULL; /* for payload parsing */ 399 vchar_t *idci = NULL; 400 vchar_t *idcr = NULL; 401 struct isakmp_parse_t *pa; 402 struct isakmp *isakmp = (struct isakmp *)msg0->v; 403 struct isakmp_pl_hash *hash = NULL; 404 char *p; 405 int tlen; 406 int error = ISAKMP_INTERNAL_ERROR; 407 408 /* validity check */ 409 if (iph2->status != PHASE2ST_MSG1SENT) { 410 plog(LLV_ERROR, LOCATION, NULL, 411 "status mismatched %d.\n", iph2->status); 412 goto end; 413 } 414 415 /* decrypt packet */ 416 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { 417 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 418 "Packet wasn't encrypted.\n"); 419 goto end; 420 } 421 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive); 422 if (msg == NULL) 423 goto end; 424 425 /* create buffer for validating HASH(2) */ 426 /* 427 * ordering rule: 428 * 1. the first one must be HASH 429 * 2. the second one must be SA (added in isakmp-oakley-05!) 430 * 3. two IDs must be considered as IDci, then IDcr 431 */ 432 pbuf = isakmp_parse(msg); 433 if (pbuf == NULL) 434 goto end; 435 pa = (struct isakmp_parse_t *)pbuf->v; 436 437 /* HASH payload is fixed postion */ 438 if (pa->type != ISAKMP_NPTYPE_HASH) { 439 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 440 "received invalid next payload type %d, " 441 "expecting %d.\n", 442 pa->type, ISAKMP_NPTYPE_HASH); 443 goto end; 444 } 445 hash = (struct isakmp_pl_hash *)pa->ptr; 446 pa++; 447 448 /* 449 * this restriction was introduced in isakmp-oakley-05. 450 * we do not check this for backward compatibility. 451 * TODO: command line/config file option to enable/disable this code 452 */ 453 /* HASH payload is fixed postion */ 454 if (pa->type != ISAKMP_NPTYPE_SA) { 455 plog(LLV_WARNING, LOCATION, iph2->ph1->remote, 456 "received invalid next payload type %d, " 457 "expecting %d.\n", 458 pa->type, ISAKMP_NPTYPE_HASH); 459 } 460 461 /* allocate buffer for computing HASH(2) */ 462 tlen = iph2->nonce->l 463 + ntohl(isakmp->len) - sizeof(*isakmp); 464 hbuf = vmalloc(tlen); 465 if (hbuf == NULL) { 466 plog(LLV_ERROR, LOCATION, NULL, 467 "failed to get hash buffer.\n"); 468 goto end; 469 } 470 p = hbuf->v + iph2->nonce->l; /* retain the space for Ni_b */ 471 472 /* 473 * parse the payloads. 474 * copy non-HASH payloads into hbuf, so that we can validate HASH. 475 */ 476 iph2->sa_ret = NULL; 477 tlen = 0; /* count payload length except of HASH payload. */ 478 for (; pa->type; pa++) { 479 480 /* copy to buffer for HASH */ 481 /* Don't modify the payload */ 482 memcpy(p, pa->ptr, pa->len); 483 484 switch (pa->type) { 485 case ISAKMP_NPTYPE_SA: 486 if (iph2->sa_ret != NULL) { 487 plog(LLV_ERROR, LOCATION, NULL, 488 "Ignored, multiple SA " 489 "isn't supported.\n"); 490 break; 491 } 492 if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0) { 493 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 494 "duplicate ISAKMP_NPTYPE_SA.\n"); 495 goto end; 496 } 497 break; 498 499 case ISAKMP_NPTYPE_NONCE: 500 if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) { 501 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 502 "duplicate ISAKMP_NPTYPE_NONCE.\n"); 503 goto end; 504 } 505 break; 506 507 case ISAKMP_NPTYPE_KE: 508 if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) { 509 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 510 "duplicate ISAKMP_NPTYPE_KE.\n"); 511 goto end; 512 } 513 break; 514 515 case ISAKMP_NPTYPE_ID: 516 if (idci == NULL) { 517 if (isakmp_p2ph(&idci, pa->ptr) < 0) 518 goto end; 519 } else if (idcr == NULL) { 520 if (isakmp_p2ph(&idcr, pa->ptr) < 0) 521 goto end; 522 } else { 523 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 524 "too many ISAKMP_NPTYPE_ID payloads.\n"); 525 goto end; 526 } 527 break; 528 529 case ISAKMP_NPTYPE_N: 530 ph2_recv_n(iph2, pa->ptr); 531 break; 532 533 #ifdef ENABLE_NATT 534 case ISAKMP_NPTYPE_NATOA_DRAFT: 535 case ISAKMP_NPTYPE_NATOA_RFC: 536 { 537 struct sockaddr_storage addr; 538 struct sockaddr *daddr; 539 uint8_t prefix; 540 uint16_t ul_proto; 541 vchar_t *vp = NULL; 542 543 if (isakmp_p2ph(&vp, pa->ptr) < 0) 544 goto end; 545 546 error = ipsecdoi_id2sockaddr(vp, 547 (struct sockaddr *) &addr, 548 &prefix, &ul_proto); 549 550 vfree(vp); 551 552 if (error) 553 goto end; 554 555 daddr = dupsaddr((struct sockaddr *) &addr); 556 if (daddr == NULL) 557 goto end; 558 559 if (iph2->natoa_src == NULL) 560 iph2->natoa_src = daddr; 561 else if (iph2->natoa_dst == NULL) 562 iph2->natoa_dst = daddr; 563 else { 564 racoon_free(daddr); 565 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 566 "too many ISAKMP_NPTYPE_NATOA payloads.\n"); 567 goto end; 568 } 569 } 570 break; 571 #endif 572 573 default: 574 /* don't send information, see ident_r1recv() */ 575 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 576 "ignore the packet, " 577 "received unexpecting payload type %d.\n", 578 pa->type); 579 goto end; 580 } 581 582 p += pa->len; 583 584 /* compute true length of payload. */ 585 tlen += pa->len; 586 } 587 588 /* payload existency check */ 589 if (hash == NULL || iph2->sa_ret == NULL || iph2->nonce_p == NULL) { 590 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 591 "few isakmp message received.\n"); 592 goto end; 593 } 594 595 /* identity check */ 596 if (idci != NULL) { 597 struct sockaddr_storage proposed_addr, got_addr; 598 uint8_t proposed_prefix, got_prefix; 599 uint16_t proposed_ulproto, got_ulproto; 600 601 error = ipsecdoi_id2sockaddr(iph2->id, 602 (struct sockaddr *) &proposed_addr, 603 &proposed_prefix, &proposed_ulproto); 604 if (error) 605 goto end; 606 607 error = ipsecdoi_id2sockaddr(idci, 608 (struct sockaddr *) &got_addr, 609 &got_prefix, &got_ulproto); 610 if (error) 611 goto end; 612 613 if (proposed_prefix != got_prefix 614 || proposed_ulproto != got_ulproto) { 615 plog(LLV_DEBUG, LOCATION, NULL, 616 "IDci prefix/ulproto does not match proposal.\n"); 617 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED; 618 goto end; 619 } 620 #ifdef ENABLE_NATT 621 set_port(iph2->natoa_src, 622 extract_port((struct sockaddr *) &proposed_addr)); 623 #endif 624 625 if (cmpsaddr((struct sockaddr *) &proposed_addr, 626 (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) { 627 plog(LLV_DEBUG, LOCATION, NULL, 628 "IDci matches proposal.\n"); 629 #ifdef ENABLE_NATT 630 } else if (iph2->natoa_src != NULL 631 && cmpsaddr(iph2->natoa_src, 632 (struct sockaddr *) &got_addr) == 0) { 633 plog(LLV_DEBUG, LOCATION, NULL, 634 "IDci matches NAT-OAi.\n"); 635 #endif 636 } else { 637 plog(LLV_ERROR, LOCATION, NULL, 638 "mismatched IDci was returned.\n"); 639 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED; 640 goto end; 641 } 642 } 643 if (idcr != NULL) { 644 struct sockaddr_storage proposed_addr, got_addr; 645 uint8_t proposed_prefix, got_prefix; 646 uint16_t proposed_ulproto, got_ulproto; 647 648 error = ipsecdoi_id2sockaddr(iph2->id_p, 649 (struct sockaddr *) &proposed_addr, 650 &proposed_prefix, &proposed_ulproto); 651 if (error) 652 goto end; 653 654 error = ipsecdoi_id2sockaddr(idcr, 655 (struct sockaddr *) &got_addr, 656 &got_prefix, &got_ulproto); 657 if (error) 658 goto end; 659 660 if (proposed_prefix != got_prefix 661 || proposed_ulproto != got_ulproto) { 662 plog(LLV_DEBUG, LOCATION, NULL, 663 "IDcr prefix/ulproto does not match proposal.\n"); 664 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED; 665 goto end; 666 } 667 668 #ifdef ENABLE_NATT 669 set_port(iph2->natoa_dst, 670 extract_port((struct sockaddr *) &proposed_addr)); 671 #endif 672 673 if (cmpsaddr((struct sockaddr *) &proposed_addr, 674 (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) { 675 plog(LLV_DEBUG, LOCATION, NULL, 676 "IDcr matches proposal.\n"); 677 #ifdef ENABLE_NATT 678 } else if (iph2->natoa_dst != NULL 679 && cmpsaddr(iph2->natoa_dst, 680 (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) { 681 plog(LLV_DEBUG, LOCATION, NULL, 682 "IDcr matches NAT-OAr.\n"); 683 #endif 684 } else { 685 plog(LLV_ERROR, LOCATION, NULL, 686 "mismatched IDcr was returned.\n"); 687 error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED; 688 goto end; 689 } 690 } 691 692 /* Fixed buffer for calculating HASH */ 693 memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l); 694 plog(LLV_DEBUG, LOCATION, NULL, 695 "HASH allocated:hbuf->l=%zu actual:tlen=%zu\n", 696 hbuf->l, tlen + iph2->nonce->l); 697 /* adjust buffer length for HASH */ 698 hbuf->l = iph2->nonce->l + tlen; 699 700 /* validate HASH(2) */ 701 { 702 char *r_hash; 703 vchar_t *my_hash = NULL; 704 int result; 705 706 r_hash = (char *)hash + sizeof(*hash); 707 708 plog(LLV_DEBUG, LOCATION, NULL, "HASH(2) received:"); 709 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash)); 710 711 my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf); 712 if (my_hash == NULL) 713 goto end; 714 715 result = memcmp(my_hash->v, r_hash, my_hash->l); 716 vfree(my_hash); 717 718 if (result) { 719 plog(LLV_DEBUG, LOCATION, iph2->ph1->remote, 720 "HASH(2) mismatch.\n"); 721 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION; 722 goto end; 723 } 724 } 725 726 /* validity check SA payload sent from responder */ 727 if (ipsecdoi_checkph2proposal(iph2) < 0) { 728 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 729 "proposal check failed.\n"); 730 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; 731 goto end; 732 } 733 734 /* change status of isakmp status entry */ 735 iph2->status = PHASE2ST_STATUS6; 736 737 error = 0; 738 739 end: 740 if (hbuf) 741 vfree(hbuf); 742 if (pbuf) 743 vfree(pbuf); 744 if (msg) 745 vfree(msg); 746 if (idci) 747 vfree(idci); 748 if (idcr) 749 vfree(idcr); 750 751 if (error) { 752 VPTRINIT(iph2->sa_ret); 753 VPTRINIT(iph2->nonce_p); 754 VPTRINIT(iph2->dhpub_p); 755 VPTRINIT(iph2->id); 756 VPTRINIT(iph2->id_p); 757 #ifdef ENABLE_NATT 758 if (iph2->natoa_src) { 759 racoon_free(iph2->natoa_src); 760 iph2->natoa_src = NULL; 761 } 762 if (iph2->natoa_dst) { 763 racoon_free(iph2->natoa_dst); 764 iph2->natoa_dst = NULL; 765 } 766 #endif 767 } 768 769 return error; 770 } 771 772 /* 773 * send to responder 774 * HDR*, HASH(3) 775 */ 776 int 777 quick_i2send(struct ph2handle *iph2, vchar_t *msg0) 778 { 779 vchar_t *msg = NULL; 780 vchar_t *buf = NULL; 781 vchar_t *hash = NULL; 782 char *p = NULL; 783 int tlen; 784 int error = ISAKMP_INTERNAL_ERROR; 785 786 /* validity check */ 787 if (iph2->status != PHASE2ST_STATUS6) { 788 plog(LLV_ERROR, LOCATION, NULL, 789 "status mismatched %d.\n", iph2->status); 790 goto end; 791 } 792 793 /* generate HASH(3) */ 794 { 795 vchar_t *tmp = NULL; 796 797 plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) generate\n"); 798 799 tmp = vmalloc(iph2->nonce->l + iph2->nonce_p->l); 800 if (tmp == NULL) { 801 plog(LLV_ERROR, LOCATION, NULL, 802 "failed to get hash buffer.\n"); 803 goto end; 804 } 805 memcpy(tmp->v, iph2->nonce->v, iph2->nonce->l); 806 memcpy(tmp->v + iph2->nonce->l, iph2->nonce_p->v, iph2->nonce_p->l); 807 808 hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp); 809 vfree(tmp); 810 811 if (hash == NULL) 812 goto end; 813 } 814 815 /* create buffer for isakmp payload */ 816 tlen = sizeof(struct isakmp) 817 + sizeof(struct isakmp_gen) + hash->l; 818 buf = vmalloc(tlen); 819 if (buf == NULL) { 820 plog(LLV_ERROR, LOCATION, NULL, 821 "failed to get buffer to send.\n"); 822 goto end; 823 } 824 825 /* create isakmp header */ 826 p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH); 827 if (p == NULL) 828 goto end; 829 830 /* add HASH(3) payload */ 831 p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_NONE); 832 833 #ifdef HAVE_PRINT_ISAKMP_C 834 isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1); 835 #endif 836 837 /* encoding */ 838 iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv); 839 if (iph2->sendbuf == NULL) 840 goto end; 841 842 /* if there is commit bit, need resending */ 843 if (ISSET(iph2->flags, ISAKMP_FLAG_C)) { 844 /* send the packet, add to the schedule to resend */ 845 if (isakmp_ph2send(iph2) == -1) 846 goto end; 847 } else { 848 /* send the packet */ 849 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) 850 goto end; 851 } 852 853 /* the sending message is added to the received-list. */ 854 if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, 855 iph2->sendbuf, msg0) == -1) { 856 plog(LLV_ERROR , LOCATION, NULL, 857 "failed to add a response packet to the tree.\n"); 858 goto end; 859 } 860 861 /* compute both of KEYMATs */ 862 if (oakley_compute_keymat(iph2, INITIATOR) < 0) 863 goto end; 864 865 iph2->status = PHASE2ST_ADDSA; 866 867 /* don't anything if local test mode. */ 868 if (f_local) { 869 error = 0; 870 goto end; 871 } 872 873 /* if there is commit bit don't set up SA now. */ 874 if (ISSET(iph2->flags, ISAKMP_FLAG_C)) { 875 iph2->status = PHASE2ST_COMMIT; 876 error = 0; 877 goto end; 878 } 879 880 /* Do UPDATE for initiator */ 881 plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n"); 882 if (pk_sendupdate(iph2) < 0) { 883 plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n"); 884 goto end; 885 } 886 plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n"); 887 888 /* Do ADD for responder */ 889 if (pk_sendadd(iph2) < 0) { 890 plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n"); 891 goto end; 892 } 893 plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n"); 894 895 error = 0; 896 897 end: 898 if (buf != NULL) 899 vfree(buf); 900 if (msg != NULL) 901 vfree(msg); 902 if (hash != NULL) 903 vfree(hash); 904 905 return error; 906 } 907 908 /* 909 * receive from responder 910 * HDR#*, HASH(4), notify 911 */ 912 int 913 quick_i3recv(struct ph2handle *iph2, vchar_t *msg0) 914 { 915 vchar_t *msg = NULL; 916 vchar_t *pbuf = NULL; /* for payload parsing */ 917 struct isakmp_parse_t *pa; 918 struct isakmp_pl_hash *hash = NULL; 919 vchar_t *notify = NULL; 920 int error = ISAKMP_INTERNAL_ERROR; 921 922 /* validity check */ 923 if (iph2->status != PHASE2ST_COMMIT) { 924 plog(LLV_ERROR, LOCATION, NULL, 925 "status mismatched %d.\n", iph2->status); 926 goto end; 927 } 928 929 /* decrypt packet */ 930 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { 931 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 932 "Packet wasn't encrypted.\n"); 933 goto end; 934 } 935 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive); 936 if (msg == NULL) 937 goto end; 938 939 /* validate the type of next payload */ 940 pbuf = isakmp_parse(msg); 941 if (pbuf == NULL) 942 goto end; 943 944 for (pa = (struct isakmp_parse_t *)pbuf->v; 945 pa->type != ISAKMP_NPTYPE_NONE; 946 pa++) { 947 948 switch (pa->type) { 949 case ISAKMP_NPTYPE_HASH: 950 hash = (struct isakmp_pl_hash *)pa->ptr; 951 break; 952 case ISAKMP_NPTYPE_N: 953 if (notify != NULL) { 954 plog(LLV_WARNING, LOCATION, NULL, 955 "Ignoring multiples notifications\n"); 956 break; 957 } 958 ph2_recv_n(iph2, pa->ptr); 959 notify = vmalloc(pa->len); 960 if (notify == NULL) { 961 plog(LLV_ERROR, LOCATION, NULL, 962 "failed to get notify buffer.\n"); 963 goto end; 964 } 965 memcpy(notify->v, pa->ptr, notify->l); 966 break; 967 default: 968 /* don't send information, see ident_r1recv() */ 969 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 970 "ignore the packet, " 971 "received unexpecting payload type %d.\n", 972 pa->type); 973 goto end; 974 } 975 } 976 977 /* payload existency check */ 978 if (hash == NULL) { 979 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 980 "few isakmp message received.\n"); 981 goto end; 982 } 983 984 /* validate HASH(4) */ 985 { 986 char *r_hash; 987 vchar_t *my_hash = NULL; 988 vchar_t *tmp = NULL; 989 int result; 990 991 r_hash = (char *)hash + sizeof(*hash); 992 993 plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) validate:"); 994 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash)); 995 996 my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify); 997 vfree(tmp); 998 if (my_hash == NULL) 999 goto end; 1000 1001 result = memcmp(my_hash->v, r_hash, my_hash->l); 1002 vfree(my_hash); 1003 1004 if (result) { 1005 plog(LLV_DEBUG, LOCATION, iph2->ph1->remote, 1006 "HASH(4) mismatch.\n"); 1007 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION; 1008 goto end; 1009 } 1010 } 1011 1012 iph2->status = PHASE2ST_ADDSA; 1013 iph2->flags ^= ISAKMP_FLAG_C; /* reset bit */ 1014 1015 /* don't anything if local test mode. */ 1016 if (f_local) { 1017 error = 0; 1018 goto end; 1019 } 1020 1021 /* Do UPDATE for initiator */ 1022 plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n"); 1023 if (pk_sendupdate(iph2) < 0) { 1024 plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n"); 1025 goto end; 1026 } 1027 plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n"); 1028 1029 /* Do ADD for responder */ 1030 if (pk_sendadd(iph2) < 0) { 1031 plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n"); 1032 goto end; 1033 } 1034 plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n"); 1035 1036 error = 0; 1037 1038 end: 1039 if (msg != NULL) 1040 vfree(msg); 1041 if (pbuf != NULL) 1042 vfree(pbuf); 1043 if (notify != NULL) 1044 vfree(notify); 1045 1046 return error; 1047 } 1048 1049 /* 1050 * receive from initiator 1051 * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ] 1052 */ 1053 int 1054 quick_r1recv(struct ph2handle *iph2, vchar_t *msg0) 1055 { 1056 vchar_t *msg = NULL; 1057 vchar_t *hbuf = NULL; /* for hash computing. */ 1058 vchar_t *pbuf = NULL; /* for payload parsing */ 1059 struct isakmp_parse_t *pa; 1060 struct isakmp *isakmp = (struct isakmp *)msg0->v; 1061 struct isakmp_pl_hash *hash = NULL; 1062 char *p; 1063 int tlen; 1064 int f_id_order; /* for ID payload detection */ 1065 int error = ISAKMP_INTERNAL_ERROR; 1066 1067 /* validity check */ 1068 if (iph2->status != PHASE2ST_START) { 1069 plog(LLV_ERROR, LOCATION, NULL, 1070 "status mismatched %d.\n", iph2->status); 1071 goto end; 1072 } 1073 1074 /* decrypting */ 1075 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { 1076 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1077 "Packet wasn't encrypted.\n"); 1078 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED; 1079 goto end; 1080 } 1081 /* decrypt packet */ 1082 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive); 1083 if (msg == NULL) { 1084 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1085 "Packet decryption failed.\n"); 1086 goto end; 1087 } 1088 1089 /* create buffer for using to validate HASH(1) */ 1090 /* 1091 * ordering rule: 1092 * 1. the first one must be HASH 1093 * 2. the second one must be SA (added in isakmp-oakley-05!) 1094 * 3. two IDs must be considered as IDci, then IDcr 1095 */ 1096 pbuf = isakmp_parse(msg); 1097 if (pbuf == NULL) 1098 goto end; 1099 pa = (struct isakmp_parse_t *)pbuf->v; 1100 1101 /* HASH payload is fixed postion */ 1102 if (pa->type != ISAKMP_NPTYPE_HASH) { 1103 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1104 "received invalid next payload type %d, " 1105 "expecting %d.\n", 1106 pa->type, ISAKMP_NPTYPE_HASH); 1107 error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX; 1108 goto end; 1109 } 1110 hash = (struct isakmp_pl_hash *)pa->ptr; 1111 pa++; 1112 1113 /* 1114 * this restriction was introduced in isakmp-oakley-05. 1115 * we do not check this for backward compatibility. 1116 * TODO: command line/config file option to enable/disable this code 1117 */ 1118 /* HASH payload is fixed postion */ 1119 if (pa->type != ISAKMP_NPTYPE_SA) { 1120 plog(LLV_WARNING, LOCATION, iph2->ph1->remote, 1121 "received invalid next payload type %d, " 1122 "expecting %d.\n", 1123 pa->type, ISAKMP_NPTYPE_SA); 1124 error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX; 1125 } 1126 1127 /* allocate buffer for computing HASH(1) */ 1128 tlen = ntohl(isakmp->len) - sizeof(*isakmp); 1129 hbuf = vmalloc(tlen); 1130 if (hbuf == NULL) { 1131 plog(LLV_ERROR, LOCATION, NULL, 1132 "failed to get hash buffer.\n"); 1133 goto end; 1134 } 1135 p = hbuf->v; 1136 1137 /* 1138 * parse the payloads. 1139 * copy non-HASH payloads into hbuf, so that we can validate HASH. 1140 */ 1141 iph2->sa = NULL; /* we don't support multi SAs. */ 1142 iph2->nonce_p = NULL; 1143 iph2->dhpub_p = NULL; 1144 iph2->id_p = NULL; 1145 iph2->id = NULL; 1146 tlen = 0; /* count payload length except of HASH payload. */ 1147 1148 /* 1149 * IDi2 MUST be immediatelly followed by IDr2. We allowed the 1150 * illegal case, but logged. First ID payload is to be IDi2. 1151 * And next ID payload is to be IDr2. 1152 */ 1153 f_id_order = 0; 1154 1155 for (; pa->type; pa++) { 1156 1157 /* copy to buffer for HASH */ 1158 /* Don't modify the payload */ 1159 memcpy(p, pa->ptr, pa->len); 1160 1161 if (pa->type != ISAKMP_NPTYPE_ID) 1162 f_id_order = 0; 1163 1164 switch (pa->type) { 1165 case ISAKMP_NPTYPE_SA: 1166 if (iph2->sa != NULL) { 1167 plog(LLV_ERROR, LOCATION, NULL, 1168 "Multi SAs isn't supported.\n"); 1169 goto end; 1170 } 1171 if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0) { 1172 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1173 "duplicate ISAKMP_NPTYPE_SA.\n"); 1174 goto end; 1175 } 1176 break; 1177 1178 case ISAKMP_NPTYPE_NONCE: 1179 if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) { 1180 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1181 "duplicate ISAKMP_NPTYPE_NONCE.\n"); 1182 goto end; 1183 } 1184 break; 1185 1186 case ISAKMP_NPTYPE_KE: 1187 if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) { 1188 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1189 "duplicate ISAKMP_NPTYPE_KE.\n"); 1190 goto end; 1191 } 1192 break; 1193 1194 case ISAKMP_NPTYPE_ID: 1195 if (iph2->id_p == NULL) { 1196 /* for IDci */ 1197 f_id_order++; 1198 1199 if (isakmp_p2ph(&iph2->id_p, pa->ptr) < 0) 1200 goto end; 1201 1202 } else if (iph2->id == NULL) { 1203 /* for IDcr */ 1204 if (f_id_order == 0) { 1205 plog(LLV_ERROR, LOCATION, NULL, 1206 "IDr2 payload is not " 1207 "immediatelly followed " 1208 "by IDi2. We allowed.\n"); 1209 /* XXX we allowed in this case. */ 1210 } 1211 1212 if (isakmp_p2ph(&iph2->id, pa->ptr) < 0) 1213 goto end; 1214 } else { 1215 plog(LLV_ERROR, LOCATION, NULL, 1216 "received too many ID payloads.\n"); 1217 plogdump(LLV_ERROR, iph2->id->v, iph2->id->l); 1218 error = ISAKMP_NTYPE_INVALID_ID_INFORMATION; 1219 goto end; 1220 } 1221 break; 1222 1223 case ISAKMP_NPTYPE_N: 1224 ph2_recv_n(iph2, pa->ptr); 1225 break; 1226 1227 #ifdef ENABLE_NATT 1228 case ISAKMP_NPTYPE_NATOA_DRAFT: 1229 case ISAKMP_NPTYPE_NATOA_RFC: 1230 { 1231 struct sockaddr_storage addr; 1232 struct sockaddr *daddr; 1233 uint8_t prefix; 1234 uint16_t ul_proto; 1235 vchar_t *vp = NULL; 1236 1237 if (isakmp_p2ph(&vp, pa->ptr) < 0) 1238 goto end; 1239 1240 error = ipsecdoi_id2sockaddr(vp, 1241 (struct sockaddr *) &addr, 1242 &prefix, &ul_proto); 1243 1244 vfree(vp); 1245 1246 if (error) 1247 goto end; 1248 1249 daddr = dupsaddr((struct sockaddr *) &addr); 1250 if (daddr == NULL) 1251 goto end; 1252 1253 if (iph2->natoa_dst == NULL) 1254 iph2->natoa_dst = daddr; 1255 else if (iph2->natoa_src == NULL) 1256 iph2->natoa_src = daddr; 1257 else { 1258 racoon_free(daddr); 1259 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1260 "received too many NAT-OA payloads.\n"); 1261 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED; 1262 goto end; 1263 } 1264 } 1265 break; 1266 #endif 1267 1268 default: 1269 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1270 "ignore the packet, " 1271 "received unexpecting payload type %d.\n", 1272 pa->type); 1273 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED; 1274 goto end; 1275 } 1276 1277 p += pa->len; 1278 1279 /* compute true length of payload. */ 1280 tlen += pa->len; 1281 } 1282 1283 /* payload existency check */ 1284 if (hash == NULL || iph2->sa == NULL || iph2->nonce_p == NULL) { 1285 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1286 "few isakmp message received.\n"); 1287 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED; 1288 goto end; 1289 } 1290 1291 if (iph2->id_p) { 1292 plog(LLV_DEBUG, LOCATION, NULL, "received IDci2:"); 1293 plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l); 1294 } 1295 if (iph2->id) { 1296 plog(LLV_DEBUG, LOCATION, NULL, "received IDcr2:"); 1297 plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l); 1298 } 1299 1300 /* adjust buffer length for HASH */ 1301 hbuf->l = tlen; 1302 1303 /* validate HASH(1) */ 1304 { 1305 char *r_hash; 1306 vchar_t *my_hash = NULL; 1307 int result; 1308 1309 r_hash = (caddr_t)hash + sizeof(*hash); 1310 1311 plog(LLV_DEBUG, LOCATION, NULL, "HASH(1) validate:"); 1312 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash)); 1313 1314 my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf); 1315 if (my_hash == NULL) 1316 goto end; 1317 1318 result = memcmp(my_hash->v, r_hash, my_hash->l); 1319 vfree(my_hash); 1320 1321 if (result) { 1322 plog(LLV_DEBUG, LOCATION, iph2->ph1->remote, 1323 "HASH(1) mismatch.\n"); 1324 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION; 1325 goto end; 1326 } 1327 } 1328 1329 /* get sainfo */ 1330 error = get_sainfo_r(iph2); 1331 if (error) { 1332 plog(LLV_ERROR, LOCATION, NULL, 1333 "failed to get sainfo.\n"); 1334 goto end; 1335 } 1336 1337 1338 /* check the existence of ID payload and create responder's proposal */ 1339 error = get_proposal_r(iph2); 1340 switch (error) { 1341 case -2: 1342 /* generate a policy template from peer's proposal */ 1343 if (set_proposal_from_proposal(iph2)) { 1344 plog(LLV_ERROR, LOCATION, NULL, 1345 "failed to generate a proposal template " 1346 "from client's proposal.\n"); 1347 error = ISAKMP_INTERNAL_ERROR; 1348 goto end; 1349 } 1350 /*FALLTHROUGH*/ 1351 case 0: 1352 /* select single proposal or reject it. */ 1353 if (ipsecdoi_selectph2proposal(iph2) < 0) { 1354 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1355 "no proposal chosen.\n"); 1356 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; 1357 goto end; 1358 } 1359 break; 1360 default: 1361 plog(LLV_ERROR, LOCATION, NULL, 1362 "failed to get proposal for responder.\n"); 1363 goto end; 1364 } 1365 1366 /* check KE and attribute of PFS */ 1367 if (iph2->dhpub_p != NULL && iph2->approval->pfs_group == 0) { 1368 plog(LLV_ERROR, LOCATION, NULL, 1369 "no PFS is specified, but peer sends KE.\n"); 1370 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; 1371 goto end; 1372 } 1373 if (iph2->dhpub_p == NULL && iph2->approval->pfs_group != 0) { 1374 plog(LLV_ERROR, LOCATION, NULL, 1375 "PFS is specified, but peer doesn't sends KE.\n"); 1376 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; 1377 goto end; 1378 } 1379 1380 /* 1381 * save the packet from the initiator in order to resend the 1382 * responder's first packet against this packet. 1383 */ 1384 iph2->msg1 = vdup(msg0); 1385 1386 /* change status of isakmp status entry */ 1387 iph2->status = PHASE2ST_STATUS2; 1388 1389 error = 0; 1390 1391 end: 1392 if (hbuf) 1393 vfree(hbuf); 1394 if (msg) 1395 vfree(msg); 1396 if (pbuf) 1397 vfree(pbuf); 1398 1399 if (error) { 1400 VPTRINIT(iph2->sa); 1401 VPTRINIT(iph2->nonce_p); 1402 VPTRINIT(iph2->dhpub_p); 1403 VPTRINIT(iph2->id); 1404 VPTRINIT(iph2->id_p); 1405 #ifdef ENABLE_NATT 1406 if (iph2->natoa_src) { 1407 racoon_free(iph2->natoa_src); 1408 iph2->natoa_src = NULL; 1409 } 1410 if (iph2->natoa_dst) { 1411 racoon_free(iph2->natoa_dst); 1412 iph2->natoa_dst = NULL; 1413 } 1414 #endif 1415 } 1416 1417 return error; 1418 } 1419 1420 /* 1421 * call pfkey_getspi. 1422 */ 1423 /*ARGSUSED*/ 1424 int 1425 quick_r1prep(struct ph2handle *iph2, vchar_t *msg __unused) 1426 { 1427 int error = ISAKMP_INTERNAL_ERROR; 1428 1429 /* validity check */ 1430 if (iph2->status != PHASE2ST_STATUS2) { 1431 plog(LLV_ERROR, LOCATION, NULL, 1432 "status mismatched %d.\n", iph2->status); 1433 goto end; 1434 } 1435 1436 iph2->status = PHASE2ST_GETSPISENT; 1437 1438 /* send getspi message */ 1439 if (pk_sendgetspi(iph2) < 0) 1440 goto end; 1441 1442 plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n"); 1443 1444 sched_schedule(&iph2->sce, lcconf->wait_ph2complete, 1445 quick_timeover_stub); 1446 1447 error = 0; 1448 1449 end: 1450 return error; 1451 } 1452 1453 /* 1454 * send to initiator 1455 * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ] 1456 */ 1457 int 1458 quick_r2send(struct ph2handle *iph2, vchar_t *msg) 1459 { 1460 vchar_t *body = NULL; 1461 vchar_t *hash = NULL; 1462 struct isakmp_gen *gen; 1463 char *p; 1464 size_t tlen; 1465 int error = ISAKMP_INTERNAL_ERROR; 1466 int natoa = ISAKMP_NPTYPE_NONE; 1467 int pfsgroup; 1468 uint8_t *np_p = NULL; 1469 #ifdef ENABLE_NATT 1470 vchar_t *nat_oai = NULL; 1471 vchar_t *nat_oar = NULL; 1472 #endif 1473 1474 /* validity check */ 1475 if (msg != NULL) { 1476 plog(LLV_ERROR, LOCATION, NULL, 1477 "msg has to be NULL in this function.\n"); 1478 goto end; 1479 } 1480 if (iph2->status != PHASE2ST_GETSPIDONE) { 1481 plog(LLV_ERROR, LOCATION, NULL, 1482 "status mismatched %d.\n", iph2->status); 1483 goto end; 1484 } 1485 1486 /* update responders SPI */ 1487 if (ipsecdoi_updatespi(iph2) < 0) { 1488 plog(LLV_ERROR, LOCATION, NULL, "failed to update spi.\n"); 1489 goto end; 1490 } 1491 1492 /* generate NONCE value */ 1493 iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size); 1494 if (iph2->nonce == NULL) 1495 goto end; 1496 1497 /* generate KE value if need */ 1498 pfsgroup = iph2->approval->pfs_group; 1499 if (iph2->dhpub_p != NULL && pfsgroup != 0) { 1500 /* DH group settting if PFS is required. */ 1501 if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) { 1502 plog(LLV_ERROR, LOCATION, NULL, 1503 "failed to set DH value.\n"); 1504 goto end; 1505 } 1506 /* generate DH public value */ 1507 if (oakley_dh_generate(iph2->pfsgrp, 1508 &iph2->dhpub, &iph2->dhpriv) < 0) { 1509 goto end; 1510 } 1511 } 1512 1513 #ifdef ENABLE_NATT 1514 /* 1515 * RFC3947 5.2. if we chose UDP-Encapsulated-Transport 1516 * we should send NAT-OA 1517 */ 1518 if (ipsecdoi_transportmode(iph2->proposal) 1519 && (iph2->ph1->natt_flags & NAT_DETECTED)) { 1520 natoa = iph2->ph1->natt_options->payload_nat_oa; 1521 1522 nat_oai = ipsecdoi_sockaddr2id(iph2->dst, 1523 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY); 1524 nat_oar = ipsecdoi_sockaddr2id(iph2->src, 1525 IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY); 1526 1527 if (nat_oai == NULL || nat_oar == NULL) { 1528 plog(LLV_ERROR, LOCATION, NULL, 1529 "failed to generate NAT-OA payload.\n"); 1530 goto end; 1531 } 1532 1533 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n"); 1534 plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l); 1535 plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n"); 1536 plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l); 1537 } 1538 #endif 1539 1540 /* create SA;NONCE payload, and KE and ID if need */ 1541 tlen = sizeof(*gen) + iph2->sa_ret->l 1542 + sizeof(*gen) + iph2->nonce->l; 1543 if (iph2->dhpub_p != NULL && pfsgroup != 0) 1544 tlen += (sizeof(*gen) + iph2->dhpub->l); 1545 if (iph2->id_p != NULL) 1546 tlen += (sizeof(*gen) + iph2->id_p->l 1547 + sizeof(*gen) + iph2->id->l); 1548 #ifdef ENABLE_NATT 1549 if (natoa != ISAKMP_NPTYPE_NONE) 1550 tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l; 1551 #endif 1552 1553 body = vmalloc(tlen); 1554 if (body == NULL) { 1555 plog(LLV_ERROR, LOCATION, NULL, 1556 "failed to get buffer to send.\n"); 1557 goto end; 1558 } 1559 p = body->v; 1560 1561 /* make SA payload */ 1562 p = set_isakmp_payload(body->v, iph2->sa_ret, ISAKMP_NPTYPE_NONCE); 1563 1564 /* add NONCE payload */ 1565 np_p = &((struct isakmp_gen *)p)->np; /* XXX */ 1566 p = set_isakmp_payload(p, iph2->nonce, 1567 (iph2->dhpub_p != NULL && pfsgroup != 0) 1568 ? ISAKMP_NPTYPE_KE 1569 : (iph2->id_p != NULL 1570 ? ISAKMP_NPTYPE_ID 1571 : natoa)); 1572 1573 /* add KE payload if need. */ 1574 if (iph2->dhpub_p != NULL && pfsgroup != 0) { 1575 np_p = &((struct isakmp_gen *)p)->np; /* XXX */ 1576 p = set_isakmp_payload(p, iph2->dhpub, 1577 (iph2->id_p == NULL) 1578 ? natoa 1579 : ISAKMP_NPTYPE_ID); 1580 } 1581 1582 /* add ID payloads received. */ 1583 if (iph2->id_p != NULL) { 1584 /* IDci */ 1585 p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID); 1586 /* IDcr */ 1587 np_p = &((struct isakmp_gen *)p)->np; /* XXX */ 1588 p = set_isakmp_payload(p, iph2->id, natoa); 1589 } 1590 1591 #ifdef ENABLE_NATT 1592 /* NAT-OA */ 1593 if (natoa != ISAKMP_NPTYPE_NONE) { 1594 p = set_isakmp_payload(p, nat_oai, natoa); 1595 p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE); 1596 } 1597 #endif 1598 1599 /* add a RESPONDER-LIFETIME notify payload if needed */ 1600 { 1601 vchar_t *data = NULL; 1602 struct saprop *pp = iph2->approval; 1603 struct saproto *pr; 1604 1605 if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_SEC) { 1606 uint32_t v = htonl((uint32_t)pp->lifetime); 1607 data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE, 1608 IPSECDOI_ATTR_SA_LD_TYPE_SEC); 1609 if (!data) 1610 goto end; 1611 data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD, 1612 (caddr_t)&v, sizeof(v)); 1613 if (!data) 1614 goto end; 1615 } 1616 if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_KB) { 1617 uint32_t v = htonl((uint32_t)pp->lifebyte); 1618 data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE, 1619 IPSECDOI_ATTR_SA_LD_TYPE_KB); 1620 if (!data) 1621 goto end; 1622 data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD, 1623 (caddr_t)&v, sizeof(v)); 1624 if (!data) 1625 goto end; 1626 } 1627 1628 /* 1629 * XXX Is there only single RESPONDER-LIFETIME payload in a IKE message 1630 * in the case of SA bundle ? 1631 */ 1632 if (data) { 1633 for (pr = pp->head; pr; pr = pr->next) { 1634 body = isakmp_add_pl_n(body, &np_p, 1635 ISAKMP_NTYPE_RESPONDER_LIFETIME, pr, data); 1636 if (!body) { 1637 vfree(data); 1638 return error; /* XXX */ 1639 } 1640 } 1641 vfree(data); 1642 } 1643 } 1644 1645 /* generate HASH(2) */ 1646 { 1647 vchar_t *tmp; 1648 1649 tmp = vmalloc(iph2->nonce_p->l + body->l); 1650 if (tmp == NULL) { 1651 plog(LLV_ERROR, LOCATION, NULL, 1652 "failed to get hash buffer.\n"); 1653 goto end; 1654 } 1655 memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l); 1656 memcpy(tmp->v + iph2->nonce_p->l, body->v, body->l); 1657 1658 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, tmp); 1659 vfree(tmp); 1660 1661 if (hash == NULL) 1662 goto end; 1663 } 1664 1665 /* send isakmp payload */ 1666 iph2->sendbuf = quick_ir1mx(iph2, body, hash); 1667 if (iph2->sendbuf == NULL) 1668 goto end; 1669 1670 /* send the packet, add to the schedule to resend */ 1671 if (isakmp_ph2send(iph2) == -1) 1672 goto end; 1673 1674 /* the sending message is added to the received-list. */ 1675 if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, iph2->msg1) == -1) { 1676 plog(LLV_ERROR , LOCATION, NULL, 1677 "failed to add a response packet to the tree.\n"); 1678 goto end; 1679 } 1680 1681 /* change status of isakmp status entry */ 1682 iph2->status = PHASE2ST_MSG1SENT; 1683 1684 error = 0; 1685 1686 end: 1687 if (body != NULL) 1688 vfree(body); 1689 if (hash != NULL) 1690 vfree(hash); 1691 #ifdef ENABLE_NATT 1692 if (nat_oai != NULL) 1693 vfree(nat_oai); 1694 if (nat_oar != NULL) 1695 vfree(nat_oar); 1696 #endif 1697 1698 return error; 1699 } 1700 1701 /* 1702 * receive from initiator 1703 * HDR*, HASH(3) 1704 1705 */ 1706 int 1707 quick_r3recv(struct ph2handle *iph2, vchar_t *msg0) 1708 { 1709 vchar_t *msg = NULL; 1710 vchar_t *pbuf = NULL; /* for payload parsing */ 1711 struct isakmp_parse_t *pa; 1712 struct isakmp_pl_hash *hash = NULL; 1713 int error = ISAKMP_INTERNAL_ERROR; 1714 1715 /* validity check */ 1716 if (iph2->status != PHASE2ST_MSG1SENT) { 1717 plog(LLV_ERROR, LOCATION, NULL, 1718 "status mismatched %d.\n", iph2->status); 1719 goto end; 1720 } 1721 1722 /* decrypt packet */ 1723 if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { 1724 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1725 "Packet wasn't encrypted.\n"); 1726 goto end; 1727 } 1728 msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive); 1729 if (msg == NULL) 1730 goto end; 1731 1732 /* validate the type of next payload */ 1733 pbuf = isakmp_parse(msg); 1734 if (pbuf == NULL) 1735 goto end; 1736 1737 for (pa = (struct isakmp_parse_t *)pbuf->v; 1738 pa->type != ISAKMP_NPTYPE_NONE; 1739 pa++) { 1740 1741 switch (pa->type) { 1742 case ISAKMP_NPTYPE_HASH: 1743 hash = (struct isakmp_pl_hash *)pa->ptr; 1744 break; 1745 case ISAKMP_NPTYPE_N: 1746 ph2_recv_n(iph2, pa->ptr); 1747 break; 1748 default: 1749 /* don't send information, see ident_r1recv() */ 1750 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1751 "ignore the packet, " 1752 "received unexpecting payload type %d.\n", 1753 pa->type); 1754 goto end; 1755 } 1756 } 1757 1758 /* payload existency check */ 1759 if (hash == NULL) { 1760 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1761 "few isakmp message received.\n"); 1762 goto end; 1763 } 1764 1765 /* validate HASH(3) */ 1766 /* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */ 1767 { 1768 char *r_hash; 1769 vchar_t *my_hash = NULL; 1770 vchar_t *tmp = NULL; 1771 int result; 1772 1773 r_hash = (char *)hash + sizeof(*hash); 1774 1775 plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) validate:"); 1776 plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash)); 1777 1778 tmp = vmalloc(iph2->nonce_p->l + iph2->nonce->l); 1779 if (tmp == NULL) { 1780 plog(LLV_ERROR, LOCATION, NULL, 1781 "failed to get hash buffer.\n"); 1782 goto end; 1783 } 1784 memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l); 1785 memcpy(tmp->v + iph2->nonce_p->l, iph2->nonce->v, iph2->nonce->l); 1786 1787 my_hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp); 1788 vfree(tmp); 1789 if (my_hash == NULL) 1790 goto end; 1791 1792 result = memcmp(my_hash->v, r_hash, my_hash->l); 1793 vfree(my_hash); 1794 1795 if (result) { 1796 plog(LLV_ERROR, LOCATION, iph2->ph1->remote, 1797 "HASH(3) mismatch.\n"); 1798 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION; 1799 goto end; 1800 } 1801 } 1802 1803 /* if there is commit bit, don't set up SA now. */ 1804 if (ISSET(iph2->flags, ISAKMP_FLAG_C)) { 1805 iph2->status = PHASE2ST_COMMIT; 1806 } else 1807 iph2->status = PHASE2ST_STATUS6; 1808 1809 error = 0; 1810 1811 end: 1812 if (pbuf != NULL) 1813 vfree(pbuf); 1814 if (msg != NULL) 1815 vfree(msg); 1816 1817 return error; 1818 } 1819 1820 /* 1821 * send to initiator 1822 * HDR#*, HASH(4), notify 1823 */ 1824 int 1825 quick_r3send(struct ph2handle *iph2, vchar_t *msg0) 1826 { 1827 vchar_t *buf = NULL; 1828 vchar_t *myhash = NULL; 1829 struct isakmp_pl_n *n; 1830 vchar_t *notify = NULL; 1831 char *p; 1832 size_t tlen; 1833 int error = ISAKMP_INTERNAL_ERROR; 1834 1835 /* validity check */ 1836 if (iph2->status != PHASE2ST_COMMIT) { 1837 plog(LLV_ERROR, LOCATION, NULL, 1838 "status mismatched %d.\n", iph2->status); 1839 goto end; 1840 } 1841 1842 /* generate HASH(4) */ 1843 /* XXX What can I do in the case of multiple different SA */ 1844 plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) generate\n"); 1845 1846 /* XXX What should I do if there are multiple SAs ? */ 1847 tlen = sizeof(struct isakmp_pl_n) + iph2->approval->head->spisize; 1848 notify = vmalloc(tlen); 1849 if (notify == NULL) { 1850 plog(LLV_ERROR, LOCATION, NULL, 1851 "failed to get notify buffer.\n"); 1852 goto end; 1853 } 1854 n = (struct isakmp_pl_n *)notify->v; 1855 n->h.np = ISAKMP_NPTYPE_NONE; 1856 n->h.len = htons(tlen); 1857 n->doi = htonl(IPSEC_DOI); 1858 n->proto_id = iph2->approval->head->proto_id; 1859 n->spi_size = sizeof(iph2->approval->head->spisize); 1860 n->type = htons(ISAKMP_NTYPE_CONNECTED); 1861 memcpy(n + 1, &iph2->approval->head->spi, iph2->approval->head->spisize); 1862 1863 myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify); 1864 if (myhash == NULL) 1865 goto end; 1866 1867 /* create buffer for isakmp payload */ 1868 tlen = sizeof(struct isakmp) 1869 + sizeof(struct isakmp_gen) + myhash->l 1870 + notify->l; 1871 buf = vmalloc(tlen); 1872 if (buf == NULL) { 1873 plog(LLV_ERROR, LOCATION, NULL, 1874 "failed to get buffer to send.\n"); 1875 goto end; 1876 } 1877 1878 /* create isakmp header */ 1879 p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH); 1880 if (p == NULL) 1881 goto end; 1882 1883 /* add HASH(4) payload */ 1884 p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N); 1885 1886 /* add notify payload */ 1887 memcpy(p, notify->v, notify->l); 1888 1889 #ifdef HAVE_PRINT_ISAKMP_C 1890 isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1); 1891 #endif 1892 1893 /* encoding */ 1894 iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv); 1895 if (iph2->sendbuf == NULL) 1896 goto end; 1897 1898 /* send the packet */ 1899 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) 1900 goto end; 1901 1902 /* the sending message is added to the received-list. */ 1903 if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, msg0) == -1) { 1904 plog(LLV_ERROR , LOCATION, NULL, 1905 "failed to add a response packet to the tree.\n"); 1906 goto end; 1907 } 1908 1909 iph2->status = PHASE2ST_COMMIT; 1910 1911 error = 0; 1912 1913 end: 1914 if (buf != NULL) 1915 vfree(buf); 1916 if (myhash != NULL) 1917 vfree(myhash); 1918 if (notify != NULL) 1919 vfree(notify); 1920 1921 return error; 1922 } 1923 1924 int 1925 tunnel_mode_prop(struct saprop *p) 1926 { 1927 struct saproto *pr; 1928 1929 for (pr = p->head; pr; pr = pr->next) 1930 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) 1931 return 1; 1932 return 0; 1933 } 1934 1935 /* 1936 * set SA to kernel. 1937 */ 1938 /*ARGSUSED*/ 1939 int 1940 quick_r3prep(struct ph2handle *iph2, vchar_t *msg0 __unused) 1941 { 1942 int error = ISAKMP_INTERNAL_ERROR; 1943 1944 /* validity check */ 1945 if (iph2->status != PHASE2ST_STATUS6) { 1946 plog(LLV_ERROR, LOCATION, NULL, 1947 "status mismatched %d.\n", iph2->status); 1948 goto end; 1949 } 1950 1951 /* compute both of KEYMATs */ 1952 if (oakley_compute_keymat(iph2, RESPONDER) < 0) 1953 goto end; 1954 1955 iph2->status = PHASE2ST_ADDSA; 1956 iph2->flags ^= ISAKMP_FLAG_C; /* reset bit */ 1957 1958 /* don't anything if local test mode. */ 1959 if (f_local) { 1960 error = 0; 1961 goto end; 1962 } 1963 1964 /* Do UPDATE as responder */ 1965 plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n"); 1966 if (pk_sendupdate(iph2) < 0) { 1967 plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n"); 1968 goto end; 1969 } 1970 plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n"); 1971 1972 /* Do ADD for responder */ 1973 if (pk_sendadd(iph2) < 0) { 1974 plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n"); 1975 goto end; 1976 } 1977 plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n"); 1978 1979 /* 1980 * set policies into SPD if the policy is generated 1981 * from peer's policy. 1982 */ 1983 if (iph2->spidx_gen) { 1984 1985 struct policyindex *spidx; 1986 struct sockaddr_storage addr; 1987 uint8_t pref; 1988 struct sockaddr *src = iph2->src; 1989 struct sockaddr *dst = iph2->dst; 1990 1991 /* make inbound policy */ 1992 iph2->src = dst; 1993 iph2->dst = src; 1994 if (pk_sendspdupdate2(iph2) < 0) { 1995 plog(LLV_ERROR, LOCATION, NULL, 1996 "pfkey spdupdate2(inbound) failed.\n"); 1997 goto end; 1998 } 1999 plog(LLV_DEBUG, LOCATION, NULL, 2000 "pfkey spdupdate2(inbound) sent.\n"); 2001 2002 spidx = (struct policyindex *)iph2->spidx_gen; 2003 #ifdef HAVE_POLICY_FWD 2004 /* make forward policy if required */ 2005 if (tunnel_mode_prop(iph2->approval)) { 2006 spidx->dir = IPSEC_DIR_FWD; 2007 if (pk_sendspdupdate2(iph2) < 0) { 2008 plog(LLV_ERROR, LOCATION, NULL, 2009 "pfkey spdupdate2(forward) failed.\n"); 2010 goto end; 2011 } 2012 plog(LLV_DEBUG, LOCATION, NULL, 2013 "pfkey spdupdate2(forward) sent.\n"); 2014 } 2015 #endif 2016 2017 /* make outbound policy */ 2018 iph2->src = src; 2019 iph2->dst = dst; 2020 spidx->dir = IPSEC_DIR_OUTBOUND; 2021 addr = spidx->src; 2022 spidx->src = spidx->dst; 2023 spidx->dst = addr; 2024 pref = spidx->prefs; 2025 spidx->prefs = spidx->prefd; 2026 spidx->prefd = pref; 2027 2028 if (pk_sendspdupdate2(iph2) < 0) { 2029 plog(LLV_ERROR, LOCATION, NULL, 2030 "pfkey spdupdate2(outbound) failed.\n"); 2031 goto end; 2032 } 2033 plog(LLV_DEBUG, LOCATION, NULL, 2034 "pfkey spdupdate2(outbound) sent.\n"); 2035 2036 /* spidx_gen is unnecessary any more */ 2037 delsp_bothdir((struct policyindex *)iph2->spidx_gen); 2038 racoon_free(iph2->spidx_gen); 2039 iph2->spidx_gen = NULL; 2040 iph2->generated_spidx=1; 2041 } 2042 2043 error = 0; 2044 2045 end: 2046 return error; 2047 } 2048 2049 /* 2050 * create HASH, body (SA, NONCE) payload with isakmp header. 2051 */ 2052 static vchar_t * 2053 quick_ir1mx(struct ph2handle *iph2, vchar_t *body, vchar_t *hash) 2054 { 2055 struct isakmp *isakmp; 2056 vchar_t *buf = NULL, *new = NULL; 2057 char *p; 2058 size_t tlen; 2059 struct isakmp_gen *gen; 2060 int error = ISAKMP_INTERNAL_ERROR; 2061 2062 /* create buffer for isakmp payload */ 2063 tlen = sizeof(*isakmp) 2064 + sizeof(*gen) + hash->l 2065 + body->l; 2066 buf = vmalloc(tlen); 2067 if (buf == NULL) { 2068 plog(LLV_ERROR, LOCATION, NULL, 2069 "failed to get buffer to send.\n"); 2070 goto end; 2071 } 2072 2073 /* re-set encryption flag, for serurity. */ 2074 iph2->flags |= ISAKMP_FLAG_E; 2075 2076 /* set isakmp header */ 2077 p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH); 2078 if (p == NULL) 2079 goto end; 2080 2081 /* add HASH payload */ 2082 /* XXX is next type always SA ? */ 2083 p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_SA); 2084 2085 /* add body payload */ 2086 memcpy(p, body->v, body->l); 2087 2088 #ifdef HAVE_PRINT_ISAKMP_C 2089 isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1); 2090 #endif 2091 2092 /* encoding */ 2093 new = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv); 2094 2095 if (new == NULL) 2096 goto end; 2097 2098 vfree(buf); 2099 2100 buf = new; 2101 2102 error = 0; 2103 2104 end: 2105 if (error && buf != NULL) { 2106 vfree(buf); 2107 buf = NULL; 2108 } 2109 2110 return buf; 2111 } 2112 2113 /* 2114 * get remote's sainfo. 2115 * NOTE: this function is for responder. 2116 */ 2117 static int 2118 get_sainfo_r(struct ph2handle *iph2) 2119 { 2120 vchar_t *idsrc = NULL, *iddst = NULL, *client = NULL; 2121 int error = ISAKMP_INTERNAL_ERROR; 2122 2123 if (iph2->id == NULL) { 2124 idsrc = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST, 2125 IPSEC_ULPROTO_ANY); 2126 } else { 2127 idsrc = vdup(iph2->id); 2128 } 2129 if (idsrc == NULL) { 2130 plog(LLV_ERROR, LOCATION, NULL, 2131 "failed to set ID for source.\n"); 2132 goto end; 2133 } 2134 2135 if (iph2->id_p == NULL) { 2136 iddst = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST, 2137 IPSEC_ULPROTO_ANY); 2138 } else { 2139 iddst = vdup(iph2->id_p); 2140 } 2141 if (iddst == NULL) { 2142 plog(LLV_ERROR, LOCATION, NULL, 2143 "failed to set ID for destination.\n"); 2144 goto end; 2145 } 2146 2147 #ifdef ENABLE_HYBRID 2148 2149 /* clientaddr check : obtain modecfg address */ 2150 if (iph2->ph1->mode_cfg != NULL) { 2151 if ((iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) || 2152 (iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)){ 2153 struct sockaddr saddr; 2154 saddr.sa_family = AF_INET; 2155 #ifndef __linux__ 2156 saddr.sa_len = sizeof(struct sockaddr_in); 2157 #endif 2158 ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY; 2159 memcpy(&((struct sockaddr_in *)&saddr)->sin_addr, 2160 &iph2->ph1->mode_cfg->addr4, sizeof(struct in_addr)); 2161 client = ipsecdoi_sockaddr2id(&saddr, 32, IPSEC_ULPROTO_ANY); 2162 } 2163 } 2164 2165 /* clientaddr check, fallback to peer address */ 2166 if (client == NULL) 2167 { 2168 client = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST, 2169 IPSEC_ULPROTO_ANY); 2170 } 2171 #endif 2172 2173 /* obtain a matching sainfo section */ 2174 iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, client, iph2->ph1->rmconf->ph1id); 2175 if (iph2->sainfo == NULL) { 2176 plog(LLV_ERROR, LOCATION, NULL, 2177 "failed to get sainfo.\n"); 2178 goto end; 2179 } 2180 2181 #ifdef ENABLE_HYBRID 2182 /* xauth group inclusion check */ 2183 if (iph2->sainfo->group != NULL) 2184 if(group_check(iph2->ph1,&iph2->sainfo->group->v,1)) 2185 goto end; 2186 #endif 2187 2188 plog(LLV_DEBUG, LOCATION, NULL, 2189 "selected sainfo: %s\n", sainfo2str(iph2->sainfo)); 2190 2191 error = 0; 2192 end: 2193 if (idsrc) 2194 vfree(idsrc); 2195 if (iddst) 2196 vfree(iddst); 2197 if (client) 2198 vfree(client); 2199 2200 return error; 2201 } 2202 2203 /* 2204 * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types 2205 * are IP address and same address family. 2206 * Then get remote's policy from SPD copied from kernel. 2207 * If the type of ID payload is address or subnet type, then the index is 2208 * made from the payload. If there is no ID payload, or the type of ID 2209 * payload is NOT address type, then the index is made from the address 2210 * pair of phase 1. 2211 * NOTE: This function is only for responder. 2212 */ 2213 static int 2214 get_proposal_r(struct ph2handle *iph2) 2215 { 2216 struct policyindex spidx; 2217 struct secpolicy *sp_in, *sp_out; 2218 int idi2type = 0; /* switch whether copy IDs into id[src,dst]. */ 2219 int error = ISAKMP_INTERNAL_ERROR; 2220 2221 /* check the existence of ID payload */ 2222 if ((iph2->id_p != NULL && iph2->id == NULL) 2223 || (iph2->id_p == NULL && iph2->id != NULL)) { 2224 plog(LLV_ERROR, LOCATION, NULL, 2225 "Both IDs wasn't found in payload.\n"); 2226 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; 2227 } 2228 2229 /* make sure if sa_[src, dst] are null. */ 2230 if (iph2->sa_src || iph2->sa_dst) { 2231 plog(LLV_ERROR, LOCATION, NULL, 2232 "Why do ID[src,dst] exist already.\n"); 2233 return ISAKMP_INTERNAL_ERROR; 2234 } 2235 2236 memset(&spidx, 0, sizeof(spidx)); 2237 2238 #define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type 2239 2240 /* make a spidx; a key to search SPD */ 2241 spidx.dir = IPSEC_DIR_INBOUND; 2242 spidx.ul_proto = 0; 2243 2244 /* 2245 * make destination address in spidx from either ID payload 2246 * or phase 1 address into a address in spidx. 2247 */ 2248 if (iph2->id != NULL 2249 && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR 2250 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR 2251 || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET 2252 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) { 2253 /* get a destination address of a policy */ 2254 error = ipsecdoi_id2sockaddr(iph2->id, 2255 (struct sockaddr *)&spidx.dst, 2256 &spidx.prefd, &spidx.ul_proto); 2257 if (error) 2258 return error; 2259 2260 #ifdef INET6 2261 /* 2262 * get scopeid from the SA address. 2263 * note that the phase 1 source address is used as 2264 * a destination address to search for a inbound policy entry 2265 * because rcoon is responder. 2266 */ 2267 if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) { 2268 error = setscopeid((struct sockaddr *)&spidx.dst, 2269 iph2->src); 2270 if (error) 2271 return error; 2272 } 2273 #endif 2274 2275 if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR 2276 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) 2277 idi2type = _XIDT(iph2->id); 2278 2279 } else { 2280 2281 plog(LLV_DEBUG, LOCATION, NULL, 2282 "get a destination address of SP index " 2283 "from phase1 address " 2284 "due to no ID payloads found " 2285 "OR because ID type is not address.\n"); 2286 2287 /* 2288 * copy the SOURCE address of IKE into the DESTINATION address 2289 * of the key to search the SPD because the direction of policy 2290 * is inbound. 2291 */ 2292 memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src)); 2293 switch (spidx.dst.ss_family) { 2294 case AF_INET: 2295 spidx.prefd = sizeof(struct in_addr) << 3; 2296 break; 2297 #ifdef INET6 2298 case AF_INET6: 2299 spidx.prefd = sizeof(struct in6_addr) << 3; 2300 break; 2301 #endif 2302 default: 2303 spidx.prefd = 0; 2304 break; 2305 } 2306 } 2307 2308 /* make source address in spidx */ 2309 if (iph2->id_p != NULL 2310 && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR 2311 || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR 2312 || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET 2313 || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) { 2314 /* get a source address of inbound SA */ 2315 error = ipsecdoi_id2sockaddr(iph2->id_p, 2316 (struct sockaddr *)&spidx.src, 2317 &spidx.prefs, &spidx.ul_proto); 2318 if (error) 2319 return error; 2320 2321 #ifdef INET6 2322 /* 2323 * get scopeid from the SA address. 2324 * for more detail, see above of this function. 2325 */ 2326 if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) { 2327 error = setscopeid((struct sockaddr *)&spidx.src, 2328 iph2->dst); 2329 if (error) 2330 return error; 2331 } 2332 #endif 2333 2334 /* Before setting iph2->[sa_src, sa_dst] with the addresses 2335 * provided in ID payloads, we check: 2336 * - they are both addresses of same family 2337 * - sainfo has not been selected only based on ID payload 2338 * information but also based on specific Phase 1 2339 * credentials (iph2->sainfo->id_i is defined), i.e. 2340 * local configuration _explicitly_ expect that user 2341 * (e.g. from asn1dn "C=FR, ...") with those IDs) */ 2342 if (_XIDT(iph2->id_p) == idi2type && 2343 spidx.dst.ss_family == spidx.src.ss_family && 2344 iph2->sainfo && iph2->sainfo->id_i) { 2345 2346 iph2->sa_src = dupsaddr((struct sockaddr *)&spidx.dst); 2347 if (iph2->sa_src == NULL) { 2348 plog(LLV_ERROR, LOCATION, NULL, 2349 "buffer allocation failed.\n"); 2350 return ISAKMP_INTERNAL_ERROR; 2351 } 2352 2353 iph2->sa_dst = dupsaddr((struct sockaddr *)&spidx.src); 2354 if (iph2->sa_dst == NULL) { 2355 plog(LLV_ERROR, LOCATION, NULL, 2356 "buffer allocation failed.\n"); 2357 return ISAKMP_INTERNAL_ERROR; 2358 } 2359 } else { 2360 plog(LLV_DEBUG, LOCATION, NULL, 2361 "Either family (%d - %d), types (%d - %d) of ID " 2362 "from initiator differ or matching sainfo " 2363 "has no id_i defined for the peer. Not filling " 2364 "iph2->sa_src and iph2->sa_dst.\n", 2365 spidx.src.ss_family, spidx.dst.ss_family, 2366 _XIDT(iph2->id_p),idi2type); 2367 } 2368 } else { 2369 plog(LLV_DEBUG, LOCATION, NULL, 2370 "get a source address of SP index from Phase 1" 2371 "addresses due to no ID payloads found" 2372 "OR because ID type is not address.\n"); 2373 2374 /* see above comment. */ 2375 memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst)); 2376 switch (spidx.src.ss_family) { 2377 case AF_INET: 2378 spidx.prefs = sizeof(struct in_addr) << 3; 2379 break; 2380 #ifdef INET6 2381 case AF_INET6: 2382 spidx.prefs = sizeof(struct in6_addr) << 3; 2383 break; 2384 #endif 2385 default: 2386 spidx.prefs = 0; 2387 break; 2388 } 2389 } 2390 2391 #undef _XIDT 2392 2393 plog(LLV_DEBUG, LOCATION, NULL, 2394 "get src address from ID payload " 2395 "%s prefixlen=%u ul_proto=%u\n", 2396 saddr2str((struct sockaddr *)&spidx.src), 2397 spidx.prefs, spidx.ul_proto); 2398 plog(LLV_DEBUG, LOCATION, NULL, 2399 "get dst address from ID payload " 2400 "%s prefixlen=%u ul_proto=%u\n", 2401 saddr2str((struct sockaddr *)&spidx.dst), 2402 spidx.prefd, spidx.ul_proto); 2403 2404 /* 2405 * convert the ul_proto if it is 0 2406 * because 0 in ID payload means a wild card. 2407 */ 2408 if (spidx.ul_proto == 0) 2409 spidx.ul_proto = IPSEC_ULPROTO_ANY; 2410 2411 #ifdef HAVE_SECCTX 2412 /* 2413 * Need to use security context in spidx to ensure the correct 2414 * policy is selected. The only way to get the security context 2415 * is to look into the proposal sent by peer ahead of time. 2416 */ 2417 if (get_security_context(iph2->sa, &spidx)) { 2418 plog(LLV_ERROR, LOCATION, NULL, 2419 "error occurred trying to get security context.\n"); 2420 return ISAKMP_INTERNAL_ERROR; 2421 } 2422 #endif /* HAVE_SECCTX */ 2423 2424 /* get inbound policy */ 2425 sp_in = getsp_r(&spidx); 2426 if (sp_in == NULL) { 2427 if (iph2->ph1->rmconf->gen_policy) { 2428 plog(LLV_INFO, LOCATION, NULL, 2429 "no policy found, " 2430 "try to generate the policy : %s\n", 2431 spidx2str(&spidx)); 2432 iph2->spidx_gen = racoon_malloc(sizeof(spidx)); 2433 if (!iph2->spidx_gen) { 2434 plog(LLV_ERROR, LOCATION, NULL, 2435 "buffer allocation failed.\n"); 2436 return ISAKMP_INTERNAL_ERROR; 2437 } 2438 memcpy(iph2->spidx_gen, &spidx, sizeof(spidx)); 2439 return -2; /* special value */ 2440 } 2441 plog(LLV_ERROR, LOCATION, NULL, 2442 "no policy found: %s\n", spidx2str(&spidx)); 2443 return ISAKMP_INTERNAL_ERROR; 2444 } 2445 /* Refresh existing generated policies 2446 */ 2447 if (iph2->ph1->rmconf->gen_policy) { 2448 plog(LLV_INFO, LOCATION, NULL, 2449 "Update the generated policy : %s\n", 2450 spidx2str(&spidx)); 2451 iph2->spidx_gen = racoon_malloc(sizeof(spidx)); 2452 if (!iph2->spidx_gen) { 2453 plog(LLV_ERROR, LOCATION, NULL, 2454 "buffer allocation failed.\n"); 2455 return ISAKMP_INTERNAL_ERROR; 2456 } 2457 memcpy(iph2->spidx_gen, &spidx, sizeof(spidx)); 2458 } 2459 2460 /* get outbound policy */ 2461 { 2462 struct sockaddr_storage addr; 2463 uint8_t pref; 2464 2465 spidx.dir = IPSEC_DIR_OUTBOUND; 2466 addr = spidx.src; 2467 spidx.src = spidx.dst; 2468 spidx.dst = addr; 2469 pref = spidx.prefs; 2470 spidx.prefs = spidx.prefd; 2471 spidx.prefd = pref; 2472 2473 sp_out = getsp_r(&spidx); 2474 if (!sp_out) { 2475 plog(LLV_WARNING, LOCATION, NULL, 2476 "no outbound policy found: %s\n", 2477 spidx2str(&spidx)); 2478 } 2479 } 2480 2481 plog(LLV_DEBUG, LOCATION, NULL, 2482 "suitable SP found:%s\n", spidx2str(&spidx)); 2483 2484 /* 2485 * In the responder side, the inbound policy should be using IPsec. 2486 * outbound policy is not checked currently. 2487 */ 2488 if (sp_in->policy != IPSEC_POLICY_IPSEC) { 2489 plog(LLV_ERROR, LOCATION, NULL, 2490 "policy found, but no IPsec required: %s\n", 2491 spidx2str(&spidx)); 2492 return ISAKMP_INTERNAL_ERROR; 2493 } 2494 2495 /* set new proposal derived from a policy into the iph2->proposal. */ 2496 if (set_proposal_from_policy(iph2, sp_in, sp_out) < 0) { 2497 plog(LLV_ERROR, LOCATION, NULL, 2498 "failed to create saprop.\n"); 2499 return ISAKMP_INTERNAL_ERROR; 2500 } 2501 2502 #ifdef HAVE_SECCTX 2503 if (spidx.sec_ctx.ctx_str) { 2504 set_secctx_in_proposal(iph2, spidx); 2505 } 2506 #endif /* HAVE_SECCTX */ 2507 2508 iph2->spid = sp_in->id; 2509 2510 return 0; 2511 } 2512 2513 /* 2514 * handle a notification payload inside phase2 exchange. 2515 * phase2 is always encrypted, so it does not need to be checked 2516 * for explicitely. 2517 */ 2518 static int 2519 ph2_recv_n(struct ph2handle *iph2, struct isakmp_gen *gen) 2520 { 2521 struct ph1handle *iph1 = iph2->ph1; 2522 struct isakmp_pl_n *notify = (struct isakmp_pl_n *) gen; 2523 u_int type; 2524 int check_level; 2525 2526 type = ntohs(notify->type); 2527 switch (type) { 2528 case ISAKMP_NTYPE_CONNECTED: 2529 break; 2530 case ISAKMP_NTYPE_INITIAL_CONTACT: 2531 return isakmp_info_recv_initialcontact(iph1, iph2); 2532 case ISAKMP_NTYPE_RESPONDER_LIFETIME: 2533 ipsecdoi_parse_responder_lifetime(notify, 2534 &iph2->lifetime_secs, &iph2->lifetime_kb); 2535 2536 if (iph1 != NULL && iph1->rmconf != NULL) { 2537 check_level = iph1->rmconf->pcheck_level; 2538 } else { 2539 if (iph1 != NULL) 2540 plog(LLV_DEBUG, LOCATION, NULL, 2541 "No phase1 rmconf found !\n"); 2542 else 2543 plog(LLV_DEBUG, LOCATION, NULL, 2544 "No phase1 found !\n"); 2545 check_level = PROP_CHECK_EXACT; 2546 } 2547 2548 switch (check_level) { 2549 case PROP_CHECK_OBEY: 2550 break; 2551 case PROP_CHECK_STRICT: 2552 case PROP_CHECK_CLAIM: 2553 if (iph2->sainfo == NULL 2554 || iph2->sainfo->lifetime <= iph2->lifetime_secs) { 2555 plog(LLV_WARNING, LOCATION, NULL, 2556 "RESPONDER-LIFETIME: lifetime mismatch\n"); 2557 iph2->lifetime_secs = 0; 2558 } 2559 break; 2560 case PROP_CHECK_EXACT: 2561 if (iph2->sainfo == NULL 2562 || iph2->sainfo->lifetime != iph2->lifetime_secs) { 2563 plog(LLV_WARNING, LOCATION, NULL, 2564 "RESPONDER-LIFETIME: lifetime mismatch\n"); 2565 iph2->lifetime_secs = 0; 2566 } 2567 break; 2568 } 2569 break; 2570 default: 2571 isakmp_log_notify(iph2->ph1, notify, "phase2 exchange"); 2572 isakmp_info_send_n2(iph2, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, 2573 NULL); 2574 break; 2575 } 2576 return 0; 2577 } 2578 2579