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