Annotation of embedaddon/ipsec-tools/src/racoon/isakmp_quick.c, revision 1.1
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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>