Annotation of embedaddon/ipsec-tools/src/racoon/isakmp.c, revision 1.1
1.1 ! misho 1: /* $NetBSD: isakmp.c,v 1.71 2011/03/15 13:20:14 vanhu Exp $ */
! 2:
! 3: /* Id: isakmp.c,v 1.74 2006/05/07 21:32:59 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: #include <sys/queue.h>
! 40:
! 41: #include <netinet/in.h>
! 42: #include <arpa/inet.h>
! 43:
! 44: #include PATH_IPSEC_H
! 45:
! 46: #include <stdlib.h>
! 47: #include <stdio.h>
! 48: #include <string.h>
! 49: #include <errno.h>
! 50: #if TIME_WITH_SYS_TIME
! 51: # include <sys/time.h>
! 52: # include <time.h>
! 53: #else
! 54: # if HAVE_SYS_TIME_H
! 55: # include <sys/time.h>
! 56: # else
! 57: # include <time.h>
! 58: # endif
! 59: #endif
! 60: #include <netdb.h>
! 61: #ifdef HAVE_UNISTD_H
! 62: #include <unistd.h>
! 63: #endif
! 64: #include <ctype.h>
! 65: #ifdef ENABLE_HYBRID
! 66: #include <resolv.h>
! 67: #endif
! 68:
! 69: #include "var.h"
! 70: #include "misc.h"
! 71: #include "vmbuf.h"
! 72: #include "plog.h"
! 73: #include "sockmisc.h"
! 74: #include "schedule.h"
! 75: #include "session.h"
! 76: #include "debug.h"
! 77:
! 78: #include "remoteconf.h"
! 79: #include "localconf.h"
! 80: #include "grabmyaddr.h"
! 81: #include "admin.h"
! 82: #include "privsep.h"
! 83: #include "isakmp_var.h"
! 84: #include "isakmp.h"
! 85: #include "oakley.h"
! 86: #include "evt.h"
! 87: #include "handler.h"
! 88: #include "ipsec_doi.h"
! 89: #include "pfkey.h"
! 90: #include "crypto_openssl.h"
! 91: #include "policy.h"
! 92: #include "algorithm.h"
! 93: #include "proposal.h"
! 94: #include "sainfo.h"
! 95: #include "isakmp_ident.h"
! 96: #include "isakmp_agg.h"
! 97: #include "isakmp_base.h"
! 98: #include "isakmp_quick.h"
! 99: #include "isakmp_inf.h"
! 100: #include "isakmp_newg.h"
! 101: #ifdef ENABLE_HYBRID
! 102: #include "vendorid.h"
! 103: #include "isakmp_xauth.h"
! 104: #include "isakmp_unity.h"
! 105: #include "isakmp_cfg.h"
! 106: #endif
! 107: #ifdef ENABLE_FRAG
! 108: #include "isakmp_frag.h"
! 109: #endif
! 110: #include "strnames.h"
! 111:
! 112: #include <fcntl.h>
! 113:
! 114: #ifdef ENABLE_NATT
! 115: # include "nattraversal.h"
! 116: #endif
! 117: # ifdef __linux__
! 118: # include <linux/udp.h>
! 119: # include <linux/ip.h>
! 120: # ifndef SOL_UDP
! 121: # define SOL_UDP 17
! 122: # endif
! 123: # endif /* __linux__ */
! 124: # if defined(__NetBSD__) || defined(__FreeBSD__) || \
! 125: (defined(__APPLE__) && defined(__MACH__))
! 126: # include <netinet/in.h>
! 127: # include <netinet/udp.h>
! 128: # include <netinet/in_systm.h>
! 129: # include <netinet/ip.h>
! 130: # define SOL_UDP IPPROTO_UDP
! 131: # endif /* __NetBSD__ / __FreeBSD__ */
! 132:
! 133: static int nostate1 __P((struct ph1handle *, vchar_t *));
! 134: static int nostate2 __P((struct ph2handle *, vchar_t *));
! 135:
! 136: extern caddr_t val2str(const char *, size_t);
! 137:
! 138: static int (*ph1exchange[][2][PHASE1ST_MAX])
! 139: __P((struct ph1handle *, vchar_t *)) = {
! 140: /* error */
! 141: { { 0 }, { 0 }, },
! 142: /* Identity Protection exchange */
! 143: {
! 144: { nostate1, ident_i1send, nostate1, ident_i2recv, ident_i2send,
! 145: ident_i3recv, ident_i3send, ident_i4recv, ident_i4send, nostate1, nostate1,},
! 146: { nostate1, ident_r1recv, ident_r1send, ident_r2recv, ident_r2send,
! 147: ident_r3recv, ident_r3send, nostate1, nostate1, nostate1, nostate1, },
! 148: },
! 149: /* Aggressive exchange */
! 150: {
! 151: { nostate1, agg_i1send, nostate1, agg_i2recv, agg_i2send,
! 152: nostate1, nostate1, nostate1, nostate1, nostate1, nostate1, },
! 153: { nostate1, agg_r1recv, agg_r1send, agg_r2recv, agg_r2send,
! 154: nostate1, nostate1, nostate1, nostate1, nostate1, nostate1, },
! 155: },
! 156: /* Base exchange */
! 157: {
! 158: { nostate1, base_i1send, nostate1, base_i2recv, base_i2send,
! 159: base_i3recv, base_i3send, nostate1, nostate1, nostate1, nostate1, },
! 160: { nostate1, base_r1recv, base_r1send, base_r2recv, base_r2send,
! 161: nostate1, nostate1, nostate1, nostate1, nostate1, nostate1, },
! 162: },
! 163: };
! 164:
! 165: static int (*ph2exchange[][2][PHASE2ST_MAX])
! 166: __P((struct ph2handle *, vchar_t *)) = {
! 167: /* error */
! 168: { { 0 }, { 0 }, },
! 169: /* Quick mode for IKE */
! 170: {
! 171: { nostate2, nostate2, quick_i1prep, nostate2, quick_i1send,
! 172: quick_i2recv, quick_i2send, quick_i3recv, nostate2, nostate2, },
! 173: { nostate2, quick_r1recv, quick_r1prep, nostate2, quick_r2send,
! 174: quick_r3recv, quick_r3prep, quick_r3send, nostate2, nostate2, }
! 175: },
! 176: };
! 177:
! 178: static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 }; /* used to verify the r_ck. */
! 179:
! 180: static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
! 181: static int ph1_main __P((struct ph1handle *, vchar_t *));
! 182: static int quick_main __P((struct ph2handle *, vchar_t *));
! 183: static int isakmp_ph1begin_r __P((vchar_t *,
! 184: struct sockaddr *, struct sockaddr *, u_int8_t));
! 185: static int isakmp_ph2begin_i __P((struct ph1handle *, struct ph2handle *));
! 186: static int isakmp_ph2begin_r __P((struct ph1handle *, vchar_t *));
! 187: static int etypesw1 __P((int));
! 188: static int etypesw2 __P((int));
! 189: static int isakmp_ph1resend __P((struct ph1handle *));
! 190: static int isakmp_ph2resend __P((struct ph2handle *));
! 191:
! 192: #ifdef ENABLE_FRAG
! 193: static int frag_handler(struct ph1handle *,
! 194: vchar_t *, struct sockaddr *, struct sockaddr *);
! 195: #endif
! 196:
! 197: /*
! 198: * isakmp packet handler
! 199: */
! 200: static int
! 201: isakmp_handler(ctx, so_isakmp)
! 202: void *ctx;
! 203: int so_isakmp;
! 204: {
! 205: struct isakmp isakmp;
! 206: union {
! 207: char buf[sizeof (isakmp) + 4];
! 208: u_int32_t non_esp[2];
! 209: struct {
! 210: struct udphdr udp;
! 211: #ifdef __linux
! 212: struct iphdr ip;
! 213: #else
! 214: struct ip ip;
! 215: #endif
! 216: char buf[sizeof(isakmp) + 4];
! 217: } lbuf;
! 218: } x;
! 219: struct sockaddr_storage remote;
! 220: struct sockaddr_storage local;
! 221: unsigned int remote_len = sizeof(remote);
! 222: unsigned int local_len = sizeof(local);
! 223: int len = 0, extralen = 0;
! 224: vchar_t *buf = NULL, *tmpbuf = NULL;
! 225: int error = -1, res;
! 226:
! 227: /* read message by MSG_PEEK */
! 228: while ((len = recvfromto(so_isakmp, x.buf, sizeof(x),
! 229: MSG_PEEK, (struct sockaddr *)&remote, &remote_len,
! 230: (struct sockaddr *)&local, &local_len)) < 0) {
! 231: if (errno == EINTR)
! 232: continue;
! 233: plog(LLV_ERROR, LOCATION, NULL,
! 234: "failed to receive isakmp packet: %s\n",
! 235: strerror (errno));
! 236: goto end;
! 237: }
! 238:
! 239: /* keep-alive packet - ignore */
! 240: if (len == 1 && (x.buf[0]&0xff) == 0xff) {
! 241: /* Pull the keep-alive packet */
! 242: if ((len = recvfrom(so_isakmp, (char *)x.buf, 1,
! 243: 0, (struct sockaddr *)&remote, &remote_len)) != 1) {
! 244: plog(LLV_ERROR, LOCATION, NULL,
! 245: "failed to receive keep alive packet: %s\n",
! 246: strerror (errno));
! 247: }
! 248: goto end;
! 249: }
! 250:
! 251: /* Lucent IKE in UDP encapsulation */
! 252: {
! 253: #ifdef __linux__
! 254: if (ntohs(x.lbuf.udp.dest) == 501) {
! 255: extralen += sizeof(x.lbuf.udp) + x.lbuf.ip.ihl;
! 256: }
! 257: #else
! 258: if (ntohs(x.lbuf.udp.uh_dport) == 501) {
! 259: extralen += sizeof(x.lbuf.udp) + x.lbuf.ip.ip_hl;
! 260: }
! 261: #endif
! 262: }
! 263:
! 264: #ifdef ENABLE_NATT
! 265: /* we don't know about portchange yet,
! 266: look for non-esp marker instead */
! 267: if (x.non_esp[0] == 0 && x.non_esp[1] != 0)
! 268: extralen = NON_ESP_MARKER_LEN;
! 269: #endif
! 270:
! 271: /* now we know if there is an extra non-esp
! 272: marker at the beginning or not */
! 273: memcpy ((char *)&isakmp, x.buf + extralen, sizeof (isakmp));
! 274:
! 275: /* check isakmp header length, as well as sanity of header length */
! 276: if (len < sizeof(isakmp) || ntohl(isakmp.len) < sizeof(isakmp)) {
! 277: plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
! 278: "packet shorter than isakmp header size (%u, %u, %zu)\n",
! 279: len, ntohl(isakmp.len), sizeof(isakmp));
! 280: /* dummy receive */
! 281: if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
! 282: 0, (struct sockaddr *)&remote, &remote_len)) < 0) {
! 283: plog(LLV_ERROR, LOCATION, NULL,
! 284: "failed to receive isakmp packet: %s\n",
! 285: strerror (errno));
! 286: }
! 287: goto end;
! 288: }
! 289:
! 290: /* reject it if the size is tooooo big. */
! 291: if (ntohl(isakmp.len) > 0xffff) {
! 292: plog(LLV_ERROR, LOCATION, NULL,
! 293: "the length in the isakmp header is too big.\n");
! 294: if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
! 295: 0, (struct sockaddr *)&remote, &remote_len)) < 0) {
! 296: plog(LLV_ERROR, LOCATION, NULL,
! 297: "failed to receive isakmp packet: %s\n",
! 298: strerror (errno));
! 299: }
! 300: goto end;
! 301: }
! 302:
! 303: /* read real message */
! 304: if ((tmpbuf = vmalloc(ntohl(isakmp.len) + extralen)) == NULL) {
! 305: plog(LLV_ERROR, LOCATION, NULL,
! 306: "failed to allocate reading buffer (%u Bytes)\n",
! 307: ntohl(isakmp.len) + extralen);
! 308: /* dummy receive */
! 309: if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
! 310: 0, (struct sockaddr *)&remote, &remote_len)) < 0) {
! 311: plog(LLV_ERROR, LOCATION, NULL,
! 312: "failed to receive isakmp packet: %s\n",
! 313: strerror (errno));
! 314: }
! 315: goto end;
! 316: }
! 317:
! 318: while ((len = recvfromto(so_isakmp, (char *)tmpbuf->v, tmpbuf->l,
! 319: 0, (struct sockaddr *)&remote, &remote_len,
! 320: (struct sockaddr *)&local, &local_len)) < 0) {
! 321: if (errno == EINTR)
! 322: continue;
! 323: plog(LLV_ERROR, LOCATION, NULL,
! 324: "failed to receive isakmp packet: %s\n",
! 325: strerror (errno));
! 326: goto end;
! 327: }
! 328:
! 329: if ((buf = vmalloc(len - extralen)) == NULL) {
! 330: plog(LLV_ERROR, LOCATION, NULL,
! 331: "failed to allocate reading buffer (%u Bytes)\n",
! 332: (len - extralen));
! 333: goto end;
! 334: }
! 335:
! 336: memcpy (buf->v, tmpbuf->v + extralen, buf->l);
! 337:
! 338: len -= extralen;
! 339:
! 340: if (len != buf->l) {
! 341: plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
! 342: "received invalid length (%d != %zu), why ?\n",
! 343: len, buf->l);
! 344: goto end;
! 345: }
! 346:
! 347: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 348: plog(LLV_DEBUG, LOCATION, NULL,
! 349: "%d bytes message received %s\n",
! 350: len, saddr2str_fromto("from %s to %s",
! 351: (struct sockaddr *)&remote,
! 352: (struct sockaddr *)&local));
! 353: plogdump(LLV_DEBUG, buf->v, buf->l);
! 354:
! 355: /* avoid packets with malicious port/address */
! 356: if (extract_port((struct sockaddr *)&remote) == 0) {
! 357: plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
! 358: "src port == 0 (valid as UDP but not with IKE)\n");
! 359: goto end;
! 360: }
! 361:
! 362: /* XXX: check sender whether to be allowed or not to accept */
! 363:
! 364: /* XXX: I don't know how to check isakmp half connection attack. */
! 365:
! 366: /* simply reply if the packet was processed. */
! 367: res=check_recvdpkt((struct sockaddr *)&remote,(struct sockaddr *)&local, buf);
! 368: if (res) {
! 369: plog(LLV_NOTIFY, LOCATION, NULL,
! 370: "the packet is retransmitted by %s (%d).\n",
! 371: saddr2str((struct sockaddr *)&remote), res);
! 372: error = 0;
! 373: goto end;
! 374: }
! 375:
! 376: /* isakmp main routine */
! 377: if (isakmp_main(buf, (struct sockaddr *)&remote,
! 378: (struct sockaddr *)&local) != 0) goto end;
! 379:
! 380: error = 0;
! 381:
! 382: end:
! 383: if (tmpbuf != NULL)
! 384: vfree(tmpbuf);
! 385: if (buf != NULL)
! 386: vfree(buf);
! 387: return error;
! 388: }
! 389:
! 390: /*
! 391: * main processing to handle isakmp payload
! 392: */
! 393: static int
! 394: isakmp_main(msg, remote, local)
! 395: vchar_t *msg;
! 396: struct sockaddr *remote, *local;
! 397: {
! 398: struct isakmp *isakmp = (struct isakmp *)msg->v;
! 399: isakmp_index *index = (isakmp_index *)isakmp;
! 400: u_int32_t msgid = isakmp->msgid;
! 401: struct ph1handle *iph1;
! 402:
! 403: #ifdef HAVE_PRINT_ISAKMP_C
! 404: isakmp_printpacket(msg, remote, local, 0);
! 405: #endif
! 406:
! 407: /* the initiator's cookie must not be zero */
! 408: if (memcmp(&isakmp->i_ck, r_ck0, sizeof(cookie_t)) == 0) {
! 409: plog(LLV_ERROR, LOCATION, remote,
! 410: "malformed cookie received.\n");
! 411: return -1;
! 412: }
! 413:
! 414: /* Check the Major and Minor Version fields. */
! 415: /*
! 416: * XXX Is is right to check version here ?
! 417: * I think it may no be here because the version depends
! 418: * on exchange status.
! 419: */
! 420: if (isakmp->v < ISAKMP_VERSION_NUMBER) {
! 421: if (ISAKMP_GETMAJORV(isakmp->v) < ISAKMP_MAJOR_VERSION) {
! 422: plog(LLV_ERROR, LOCATION, remote,
! 423: "invalid major version %d.\n",
! 424: ISAKMP_GETMAJORV(isakmp->v));
! 425: return -1;
! 426: }
! 427: #if ISAKMP_MINOR_VERSION > 0
! 428: if (ISAKMP_GETMINORV(isakmp->v) < ISAKMP_MINOR_VERSION) {
! 429: plog(LLV_ERROR, LOCATION, remote,
! 430: "invalid minor version %d.\n",
! 431: ISAKMP_GETMINORV(isakmp->v));
! 432: return -1;
! 433: }
! 434: #endif
! 435: }
! 436:
! 437: /* check the Flags field. */
! 438: /* XXX How is the exclusive check, E and A ? */
! 439: if (isakmp->flags & ~(ISAKMP_FLAG_E | ISAKMP_FLAG_C | ISAKMP_FLAG_A)) {
! 440: plog(LLV_ERROR, LOCATION, remote,
! 441: "invalid flag 0x%02x.\n", isakmp->flags);
! 442: return -1;
! 443: }
! 444:
! 445: /* ignore commit bit. */
! 446: if (ISSET(isakmp->flags, ISAKMP_FLAG_C)) {
! 447: if (isakmp->msgid == 0) {
! 448: isakmp_info_send_nx(isakmp, remote, local,
! 449: ISAKMP_NTYPE_INVALID_FLAGS, NULL);
! 450: plog(LLV_ERROR, LOCATION, remote,
! 451: "Commit bit on phase1 forbidden.\n");
! 452: return -1;
! 453: }
! 454: }
! 455:
! 456: iph1 = getph1byindex(index);
! 457: if (iph1 != NULL) {
! 458: /* validity check */
! 459: if (memcmp(&isakmp->r_ck, r_ck0, sizeof(cookie_t)) == 0 &&
! 460: iph1->side == INITIATOR) {
! 461: plog(LLV_DEBUG, LOCATION, remote,
! 462: "malformed cookie received or "
! 463: "the initiator's cookies collide.\n");
! 464: return -1;
! 465: }
! 466:
! 467: #ifdef ENABLE_NATT
! 468: /* Floating ports for NAT-T */
! 469: if (NATT_AVAILABLE(iph1) &&
! 470: ! (iph1->natt_flags & NAT_PORTS_CHANGED) &&
! 471: ((cmpsaddr(iph1->remote, remote) != CMPSADDR_MATCH) ||
! 472: (cmpsaddr(iph1->local, local) != CMPSADDR_MATCH)))
! 473: {
! 474: /* prevent memory leak */
! 475: racoon_free(iph1->remote);
! 476: racoon_free(iph1->local);
! 477: iph1->remote = NULL;
! 478: iph1->local = NULL;
! 479:
! 480: /* copy-in new addresses */
! 481: iph1->remote = dupsaddr(remote);
! 482: if (iph1->remote == NULL) {
! 483: plog(LLV_ERROR, LOCATION, iph1->remote,
! 484: "phase1 failed: dupsaddr failed.\n");
! 485: remph1(iph1);
! 486: delph1(iph1);
! 487: return -1;
! 488: }
! 489: iph1->local = dupsaddr(local);
! 490: if (iph1->local == NULL) {
! 491: plog(LLV_ERROR, LOCATION, iph1->remote,
! 492: "phase1 failed: dupsaddr failed.\n");
! 493: remph1(iph1);
! 494: delph1(iph1);
! 495: return -1;
! 496: }
! 497:
! 498: /* set the flag to prevent further port floating
! 499: (FIXME: should we allow it? E.g. when the NAT gw
! 500: is rebooted?) */
! 501: iph1->natt_flags |= NAT_PORTS_CHANGED | NAT_ADD_NON_ESP_MARKER;
! 502:
! 503: /* print some neat info */
! 504: plog (LLV_INFO, LOCATION, NULL,
! 505: "NAT-T: ports changed to: %s\n",
! 506: saddr2str_fromto ("%s<->%s", iph1->remote, iph1->local));
! 507:
! 508: natt_keepalive_add_ph1 (iph1);
! 509: }
! 510: #endif
! 511:
! 512: /* must be same addresses in one stream of a phase at least. */
! 513: if (cmpsaddr(iph1->remote, remote) != CMPSADDR_MATCH) {
! 514: char *saddr_db, *saddr_act;
! 515:
! 516: saddr_db = racoon_strdup(saddr2str(iph1->remote));
! 517: saddr_act = racoon_strdup(saddr2str(remote));
! 518: STRDUP_FATAL(saddr_db);
! 519: STRDUP_FATAL(saddr_act);
! 520:
! 521: plog(LLV_WARNING, LOCATION, remote,
! 522: "remote address mismatched. db=%s, act=%s\n",
! 523: saddr_db, saddr_act);
! 524:
! 525: racoon_free(saddr_db);
! 526: racoon_free(saddr_act);
! 527: }
! 528:
! 529: /*
! 530: * don't check of exchange type here because other type will be
! 531: * with same index, for example, informational exchange.
! 532: */
! 533:
! 534: /* XXX more acceptable check */
! 535: }
! 536:
! 537: switch (isakmp->etype) {
! 538: case ISAKMP_ETYPE_IDENT:
! 539: case ISAKMP_ETYPE_AGG:
! 540: case ISAKMP_ETYPE_BASE:
! 541: /* phase 1 validity check */
! 542: if (isakmp->msgid != 0) {
! 543: plog(LLV_ERROR, LOCATION, remote,
! 544: "message id should be zero in phase1.\n");
! 545: return -1;
! 546: }
! 547:
! 548: /* search for isakmp status record of phase 1 */
! 549: if (iph1 == NULL) {
! 550: /*
! 551: * the packet must be the 1st message from a initiator
! 552: * or the 2nd message from the responder.
! 553: */
! 554:
! 555: /* search for phase1 handle by index without r_ck */
! 556: iph1 = getph1byindex0(index);
! 557: if (iph1 == NULL) {
! 558: /*it must be the 1st message from a initiator.*/
! 559: if (memcmp(&isakmp->r_ck, r_ck0,
! 560: sizeof(cookie_t)) != 0) {
! 561:
! 562: plog(LLV_DEBUG, LOCATION, remote,
! 563: "malformed cookie received "
! 564: "or the spi expired.\n");
! 565: return -1;
! 566: }
! 567:
! 568: /* it must be responder's 1st exchange. */
! 569: if (isakmp_ph1begin_r(msg, remote, local,
! 570: isakmp->etype) < 0)
! 571: return -1;
! 572: break;
! 573:
! 574: /*NOTREACHED*/
! 575: }
! 576:
! 577: /* it must be the 2nd message from the responder. */
! 578: if (iph1->side != INITIATOR) {
! 579: plog(LLV_DEBUG, LOCATION, remote,
! 580: "malformed cookie received. "
! 581: "it has to be as the initiator. %s\n",
! 582: isakmp_pindex(&iph1->index, 0));
! 583: return -1;
! 584: }
! 585: }
! 586:
! 587: /*
! 588: * Don't delete phase 1 handler when the exchange type
! 589: * in handler is not equal to packet's one because of no
! 590: * authencication completed.
! 591: */
! 592: if (iph1->etype != isakmp->etype) {
! 593: plog(LLV_ERROR, LOCATION, iph1->remote,
! 594: "exchange type is mismatched: "
! 595: "db=%s packet=%s, ignore it.\n",
! 596: s_isakmp_etype(iph1->etype),
! 597: s_isakmp_etype(isakmp->etype));
! 598: return -1;
! 599: }
! 600:
! 601: #ifdef ENABLE_FRAG
! 602: if (isakmp->np == ISAKMP_NPTYPE_FRAG)
! 603: return frag_handler(iph1, msg, remote, local);
! 604: #endif
! 605:
! 606: /* call main process of phase 1 */
! 607: if (ph1_main(iph1, msg) < 0) {
! 608: plog(LLV_ERROR, LOCATION, iph1->remote,
! 609: "phase1 negotiation failed.\n");
! 610: remph1(iph1);
! 611: delph1(iph1);
! 612: return -1;
! 613: }
! 614: break;
! 615:
! 616: case ISAKMP_ETYPE_AUTH:
! 617: plog(LLV_INFO, LOCATION, remote,
! 618: "unsupported exchange %d received.\n",
! 619: isakmp->etype);
! 620: break;
! 621:
! 622: case ISAKMP_ETYPE_INFO:
! 623: case ISAKMP_ETYPE_ACKINFO:
! 624: /*
! 625: * iph1 must be present for Information message.
! 626: * if iph1 is null then trying to get the phase1 status
! 627: * as the packet from responder againt initiator's 1st
! 628: * exchange in phase 1.
! 629: * NOTE: We think such informational exchange should be ignored.
! 630: */
! 631: if (iph1 == NULL) {
! 632: iph1 = getph1byindex0(index);
! 633: if (iph1 == NULL) {
! 634: plog(LLV_ERROR, LOCATION, remote,
! 635: "unknown Informational "
! 636: "exchange received.\n");
! 637: return -1;
! 638: }
! 639: if (cmpsaddr(iph1->remote, remote) != CMPSADDR_MATCH) {
! 640: plog(LLV_WARNING, LOCATION, remote,
! 641: "remote address mismatched. "
! 642: "db=%s\n",
! 643: saddr2str(iph1->remote));
! 644: }
! 645: }
! 646:
! 647: #ifdef ENABLE_FRAG
! 648: if (isakmp->np == ISAKMP_NPTYPE_FRAG)
! 649: return frag_handler(iph1, msg, remote, local);
! 650: #endif
! 651:
! 652: if (isakmp_info_recv(iph1, msg) < 0)
! 653: return -1;
! 654: break;
! 655:
! 656: case ISAKMP_ETYPE_QUICK:
! 657: {
! 658: struct ph2handle *iph2;
! 659:
! 660: if (iph1 == NULL) {
! 661: isakmp_info_send_nx(isakmp, remote, local,
! 662: ISAKMP_NTYPE_INVALID_COOKIE, NULL);
! 663: plog(LLV_ERROR, LOCATION, remote,
! 664: "can't start the quick mode, "
! 665: "there is no ISAKMP-SA, %s\n",
! 666: isakmp_pindex((isakmp_index *)&isakmp->i_ck,
! 667: isakmp->msgid));
! 668: return -1;
! 669: }
! 670: #ifdef ENABLE_HYBRID
! 671: /* Reinit the IVM if it's still there */
! 672: if (iph1->mode_cfg && iph1->mode_cfg->ivm) {
! 673: oakley_delivm(iph1->mode_cfg->ivm);
! 674: iph1->mode_cfg->ivm = NULL;
! 675: }
! 676: #endif
! 677: #ifdef ENABLE_FRAG
! 678: if (isakmp->np == ISAKMP_NPTYPE_FRAG)
! 679: return frag_handler(iph1, msg, remote, local);
! 680: #endif
! 681:
! 682: /* check status of phase 1 whether negotiated or not. */
! 683: if (iph1->status != PHASE1ST_ESTABLISHED &&
! 684: iph1->status != PHASE1ST_DYING) {
! 685: plog(LLV_ERROR, LOCATION, remote,
! 686: "can't start the quick mode, "
! 687: "there is no valid ISAKMP-SA, %s\n",
! 688: isakmp_pindex(&iph1->index, iph1->msgid));
! 689: return -1;
! 690: }
! 691:
! 692: /* search isakmp phase 2 stauts record. */
! 693: iph2 = getph2bymsgid(iph1, msgid);
! 694: if (iph2 == NULL) {
! 695: /* it must be new negotiation as responder */
! 696: if (isakmp_ph2begin_r(iph1, msg) < 0)
! 697: return -1;
! 698: return 0;
! 699: /*NOTREACHED*/
! 700: }
! 701:
! 702: /* commit bit. */
! 703: /* XXX
! 704: * we keep to set commit bit during negotiation.
! 705: * When SA is configured, bit will be reset.
! 706: * XXX
! 707: * don't initiate commit bit. should be fixed in the future.
! 708: */
! 709: if (ISSET(isakmp->flags, ISAKMP_FLAG_C))
! 710: iph2->flags |= ISAKMP_FLAG_C;
! 711:
! 712: /* call main process of quick mode */
! 713: if (quick_main(iph2, msg) < 0) {
! 714: plog(LLV_ERROR, LOCATION, iph1->remote,
! 715: "phase2 negotiation failed.\n");
! 716: remph2(iph2);
! 717: delph2(iph2);
! 718: return -1;
! 719: }
! 720: }
! 721: break;
! 722:
! 723: case ISAKMP_ETYPE_NEWGRP:
! 724: if (iph1 == NULL) {
! 725: plog(LLV_ERROR, LOCATION, remote,
! 726: "Unknown new group mode exchange, "
! 727: "there is no ISAKMP-SA.\n");
! 728: return -1;
! 729: }
! 730:
! 731: #ifdef ENABLE_FRAG
! 732: if (isakmp->np == ISAKMP_NPTYPE_FRAG)
! 733: return frag_handler(iph1, msg, remote, local);
! 734: #endif
! 735:
! 736: isakmp_newgroup_r(iph1, msg);
! 737: break;
! 738:
! 739: #ifdef ENABLE_HYBRID
! 740: case ISAKMP_ETYPE_CFG:
! 741: if (iph1 == NULL) {
! 742: plog(LLV_ERROR, LOCATION, NULL,
! 743: "mode config %d from %s, "
! 744: "but we have no ISAKMP-SA.\n",
! 745: isakmp->etype, saddr2str(remote));
! 746: return -1;
! 747: }
! 748:
! 749: #ifdef ENABLE_FRAG
! 750: if (isakmp->np == ISAKMP_NPTYPE_FRAG)
! 751: return frag_handler(iph1, msg, remote, local);
! 752: #endif
! 753:
! 754: isakmp_cfg_r(iph1, msg);
! 755: break;
! 756: #endif
! 757:
! 758: case ISAKMP_ETYPE_NONE:
! 759: default:
! 760: plog(LLV_ERROR, LOCATION, NULL,
! 761: "Invalid exchange type %d from %s.\n",
! 762: isakmp->etype, saddr2str(remote));
! 763: return -1;
! 764: }
! 765:
! 766: return 0;
! 767: }
! 768:
! 769: /*
! 770: * main function of phase 1.
! 771: */
! 772: static int
! 773: ph1_main(iph1, msg)
! 774: struct ph1handle *iph1;
! 775: vchar_t *msg;
! 776: {
! 777: int error;
! 778: #ifdef ENABLE_STATS
! 779: struct timeval start, end;
! 780: #endif
! 781:
! 782: /* ignore a packet */
! 783: if (iph1->status >= PHASE1ST_ESTABLISHED)
! 784: return 0;
! 785:
! 786: #ifdef ENABLE_STATS
! 787: gettimeofday(&start, NULL);
! 788: #endif
! 789: /* receive */
! 790: if (ph1exchange[etypesw1(iph1->etype)]
! 791: [iph1->side]
! 792: [iph1->status] == NULL) {
! 793: plog(LLV_ERROR, LOCATION, iph1->remote,
! 794: "why isn't the function defined.\n");
! 795: return -1;
! 796: }
! 797: error = (ph1exchange[etypesw1(iph1->etype)]
! 798: [iph1->side]
! 799: [iph1->status])(iph1, msg);
! 800: if (error != 0) {
! 801:
! 802: /* XXX
! 803: * When an invalid packet is received on phase1, it should
! 804: * be selected to process this packet. That is to respond
! 805: * with a notify and delete phase 1 handler, OR not to respond
! 806: * and keep phase 1 handler. However, in PHASE1ST_START when
! 807: * acting as RESPONDER we must not keep phase 1 handler or else
! 808: * it will stay forever.
! 809: */
! 810:
! 811: if (iph1->side == RESPONDER && iph1->status == PHASE1ST_START) {
! 812: plog(LLV_ERROR, LOCATION, iph1->remote,
! 813: "failed to pre-process ph1 packet (side: %d, status %d).\n",
! 814: iph1->side, iph1->status);
! 815: return -1;
! 816: } else {
! 817: /* ignore the error and keep phase 1 handler */
! 818: return 0;
! 819: }
! 820: }
! 821:
! 822: #ifndef ENABLE_FRAG
! 823: /* free resend buffer */
! 824: if (iph1->sendbuf == NULL) {
! 825: plog(LLV_ERROR, LOCATION, NULL,
! 826: "no buffer found as sendbuf\n");
! 827: return -1;
! 828: }
! 829: #endif
! 830:
! 831: VPTRINIT(iph1->sendbuf);
! 832:
! 833: /* turn off schedule */
! 834: sched_cancel(&iph1->scr);
! 835:
! 836: /* send */
! 837: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 838: if ((ph1exchange[etypesw1(iph1->etype)]
! 839: [iph1->side]
! 840: [iph1->status])(iph1, msg) != 0) {
! 841: plog(LLV_ERROR, LOCATION, iph1->remote,
! 842: "failed to process ph1 packet (side: %d, status: %d).\n",
! 843: iph1->side, iph1->status);
! 844: return -1;
! 845: }
! 846:
! 847: #ifdef ENABLE_STATS
! 848: gettimeofday(&end, NULL);
! 849: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 850: "phase1", s_isakmp_state(iph1->etype, iph1->side, iph1->status),
! 851: timedelta(&start, &end));
! 852: #endif
! 853: if (iph1->status == PHASE1ST_ESTABLISHED) {
! 854:
! 855: #ifdef ENABLE_STATS
! 856: gettimeofday(&iph1->end, NULL);
! 857: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 858: "phase1", s_isakmp_etype(iph1->etype),
! 859: timedelta(&iph1->start, &iph1->end));
! 860: #endif
! 861:
! 862: /* save created date. */
! 863: (void)time(&iph1->created);
! 864:
! 865: /* migrate ph2s from dying ph1s */
! 866: migrate_dying_ph12(iph1);
! 867:
! 868: /* add to the schedule to expire, and seve back pointer. */
! 869: if (ph1_rekey_enabled(iph1)) {
! 870: sched_schedule(&iph1->sce,
! 871: iph1->approval->lifetime *
! 872: PFKEY_SOFT_LIFETIME_RATE / 100,
! 873: isakmp_ph1dying_stub);
! 874: } else {
! 875: sched_schedule(&iph1->sce, iph1->approval->lifetime,
! 876: isakmp_ph1expire_stub);
! 877: }
! 878:
! 879: #ifdef ENABLE_HYBRID
! 880: if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
! 881: switch (iph1->approval->authmethod) {
! 882: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
! 883: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
! 884: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
! 885: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
! 886: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
! 887: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
! 888: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
! 889: xauth_sendreq(iph1);
! 890: /* XXX Don't process INITIAL_CONTACT */
! 891: iph1->rmconf->ini_contact = 0;
! 892: break;
! 893: default:
! 894: break;
! 895: }
! 896: }
! 897: #endif
! 898: #ifdef ENABLE_DPD
! 899: /* Schedule the r_u_there.... */
! 900: if(iph1->dpd_support && iph1->rmconf->dpd_interval)
! 901: isakmp_sched_r_u(iph1, 0);
! 902: #endif
! 903:
! 904: /* INITIAL-CONTACT processing */
! 905: /* don't anything if local test mode. */
! 906: if (!f_local
! 907: && iph1->rmconf->ini_contact && !getcontacted(iph1->remote)) {
! 908: /* send INITIAL-CONTACT */
! 909: isakmp_info_send_n1(iph1,
! 910: ISAKMP_NTYPE_INITIAL_CONTACT, NULL);
! 911: /* insert a node into contacted list. */
! 912: if (inscontacted(iph1->remote) == -1) {
! 913: plog(LLV_ERROR, LOCATION, iph1->remote,
! 914: "failed to add contacted list.\n");
! 915: /* ignore */
! 916: }
! 917: }
! 918: if (iph1->initial_contact_received)
! 919: isakmp_info_recv_initialcontact(iph1, NULL);
! 920:
! 921: log_ph1established(iph1);
! 922: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 923:
! 924: /*
! 925: * SA up shell script hook: do it now,except if
! 926: * ISAKMP mode config was requested. In the later
! 927: * case it is done when we receive the configuration.
! 928: */
! 929: if ((iph1->status == PHASE1ST_ESTABLISHED) &&
! 930: !iph1->rmconf->mode_cfg) {
! 931: switch (iph1->approval->authmethod) {
! 932: #ifdef ENABLE_HYBRID
! 933: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
! 934: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
! 935: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
! 936: /* Unimplemeted... */
! 937: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
! 938: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
! 939: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
! 940: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
! 941: break;
! 942: #endif
! 943: default:
! 944: script_hook(iph1, SCRIPT_PHASE1_UP);
! 945: break;
! 946: }
! 947: }
! 948: }
! 949:
! 950: return 0;
! 951: }
! 952:
! 953: /*
! 954: * main function of quick mode.
! 955: */
! 956: static int
! 957: quick_main(iph2, msg)
! 958: struct ph2handle *iph2;
! 959: vchar_t *msg;
! 960: {
! 961: struct isakmp *isakmp = (struct isakmp *)msg->v;
! 962: int error;
! 963: #ifdef ENABLE_STATS
! 964: struct timeval start, end;
! 965: #endif
! 966:
! 967: /* ignore a packet */
! 968: if (iph2->status == PHASE2ST_ESTABLISHED
! 969: || iph2->status == PHASE2ST_GETSPISENT)
! 970: return 0;
! 971:
! 972: #ifdef ENABLE_STATS
! 973: gettimeofday(&start, NULL);
! 974: #endif
! 975:
! 976: /* receive */
! 977: if (ph2exchange[etypesw2(isakmp->etype)]
! 978: [iph2->side]
! 979: [iph2->status] == NULL) {
! 980: plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
! 981: "why isn't the function defined.\n");
! 982: return -1;
! 983: }
! 984: error = (ph2exchange[etypesw2(isakmp->etype)]
! 985: [iph2->side]
! 986: [iph2->status])(iph2, msg);
! 987: if (error != 0) {
! 988: plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
! 989: "failed to pre-process ph2 packet (side: %d, status %d).\n",
! 990: iph2->side, iph2->status);
! 991: if (error == ISAKMP_INTERNAL_ERROR)
! 992: return 0;
! 993: isakmp_info_send_n1(iph2->ph1, error, NULL);
! 994: return -1;
! 995: }
! 996:
! 997: /* when using commit bit, status will be reached here. */
! 998: if (iph2->status == PHASE2ST_ADDSA)
! 999: return 0;
! 1000:
! 1001: /* free resend buffer */
! 1002: if (iph2->sendbuf == NULL) {
! 1003: plog(LLV_ERROR, LOCATION, NULL,
! 1004: "no buffer found as sendbuf\n");
! 1005: return -1;
! 1006: }
! 1007: VPTRINIT(iph2->sendbuf);
! 1008:
! 1009: /* turn off schedule */
! 1010: sched_cancel(&iph2->scr);
! 1011:
! 1012: /* send */
! 1013: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1014: if ((ph2exchange[etypesw2(isakmp->etype)]
! 1015: [iph2->side]
! 1016: [iph2->status])(iph2, msg) != 0) {
! 1017: plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
! 1018: "failed to process ph2 packet (side: %d, status: %d).\n",
! 1019: iph2->side, iph2->status);
! 1020: return -1;
! 1021: }
! 1022:
! 1023: #ifdef ENABLE_STATS
! 1024: gettimeofday(&end, NULL);
! 1025: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 1026: "phase2",
! 1027: s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
! 1028: timedelta(&start, &end));
! 1029: #endif
! 1030:
! 1031: return 0;
! 1032: }
! 1033:
! 1034: /* new negotiation of phase 1 for initiator */
! 1035: struct ph1handle *
! 1036: isakmp_ph1begin_i(rmconf, remote, local)
! 1037: struct remoteconf *rmconf;
! 1038: struct sockaddr *remote, *local;
! 1039: {
! 1040: struct ph1handle *iph1;
! 1041: #ifdef ENABLE_STATS
! 1042: struct timeval start, end;
! 1043: #endif
! 1044:
! 1045: /* get new entry to isakmp status table. */
! 1046: iph1 = newph1();
! 1047: if (iph1 == NULL)
! 1048: return NULL;
! 1049:
! 1050: iph1->status = PHASE1ST_START;
! 1051: iph1->rmconf = rmconf;
! 1052: iph1->side = INITIATOR;
! 1053: iph1->version = ISAKMP_VERSION_NUMBER;
! 1054: iph1->msgid = 0;
! 1055: iph1->flags = 0;
! 1056: iph1->ph2cnt = 0;
! 1057: #ifdef HAVE_GSSAPI
! 1058: iph1->gssapi_state = NULL;
! 1059: #endif
! 1060: #ifdef ENABLE_HYBRID
! 1061: if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
! 1062: delph1(iph1);
! 1063: return NULL;
! 1064: }
! 1065: #endif
! 1066: #ifdef ENABLE_FRAG
! 1067:
! 1068: if(rmconf->ike_frag == ISAKMP_FRAG_FORCE)
! 1069: iph1->frag = 1;
! 1070: else
! 1071: iph1->frag = 0;
! 1072: iph1->frag_chain = NULL;
! 1073: #endif
! 1074: iph1->approval = NULL;
! 1075:
! 1076: /* XXX copy remote address */
! 1077: if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
! 1078: delph1(iph1);
! 1079: return NULL;
! 1080: }
! 1081:
! 1082: (void)insph1(iph1);
! 1083:
! 1084: /* start phase 1 exchange */
! 1085: iph1->etype = rmconf->etypes->type;
! 1086:
! 1087: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1088: {
! 1089: char *a;
! 1090:
! 1091: a = racoon_strdup(saddr2str(iph1->local));
! 1092: STRDUP_FATAL(a);
! 1093:
! 1094: plog(LLV_INFO, LOCATION, NULL,
! 1095: "initiate new phase 1 negotiation: %s<=>%s\n",
! 1096: a, saddr2str(iph1->remote));
! 1097: racoon_free(a);
! 1098: }
! 1099: plog(LLV_INFO, LOCATION, NULL,
! 1100: "begin %s mode.\n",
! 1101: s_isakmp_etype(iph1->etype));
! 1102:
! 1103: #ifdef ENABLE_STATS
! 1104: gettimeofday(&iph1->start, NULL);
! 1105: gettimeofday(&start, NULL);
! 1106: #endif
! 1107: /* start exchange */
! 1108: if ((ph1exchange[etypesw1(iph1->etype)]
! 1109: [iph1->side]
! 1110: [iph1->status])(iph1, NULL) != 0) {
! 1111: /* failed to start phase 1 negotiation */
! 1112: remph1(iph1);
! 1113: delph1(iph1);
! 1114:
! 1115: return NULL;
! 1116: }
! 1117:
! 1118: #ifdef ENABLE_STATS
! 1119: gettimeofday(&end, NULL);
! 1120: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 1121: "phase1",
! 1122: s_isakmp_state(iph1->etype, iph1->side, iph1->status),
! 1123: timedelta(&start, &end));
! 1124: #endif
! 1125:
! 1126: return iph1;
! 1127: }
! 1128:
! 1129: /* new negotiation of phase 1 for responder */
! 1130: static int
! 1131: isakmp_ph1begin_r(msg, remote, local, etype)
! 1132: vchar_t *msg;
! 1133: struct sockaddr *remote, *local;
! 1134: u_int8_t etype;
! 1135: {
! 1136: struct isakmp *isakmp = (struct isakmp *)msg->v;
! 1137: struct ph1handle *iph1;
! 1138: struct rmconfselector rmsel;
! 1139: #ifdef ENABLE_STATS
! 1140: struct timeval start, end;
! 1141: #endif
! 1142:
! 1143: /* check if this etype is allowed */
! 1144: memset(&rmsel, 0, sizeof(rmsel));
! 1145: rmsel.remote = remote;
! 1146: if (enumrmconf(&rmsel, check_etypeok, (void *) (intptr_t) etype) == 0) {
! 1147: plog(LLV_ERROR, LOCATION, remote,
! 1148: "exchange %s not allowed in any applicable rmconf.\n",
! 1149: s_isakmp_etype(etype));
! 1150: return -1;
! 1151: }
! 1152:
! 1153: /* get new entry to isakmp status table. */
! 1154: iph1 = newph1();
! 1155: if (iph1 == NULL)
! 1156: return -1;
! 1157:
! 1158: memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(iph1->index.i_ck));
! 1159: iph1->status = PHASE1ST_START;
! 1160: iph1->flags = 0;
! 1161: iph1->side = RESPONDER;
! 1162: iph1->etype = etype;
! 1163: iph1->version = isakmp->v;
! 1164: iph1->msgid = 0;
! 1165: #ifdef HAVE_GSSAPI
! 1166: iph1->gssapi_state = NULL;
! 1167: #endif
! 1168: #ifdef ENABLE_HYBRID
! 1169: if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
! 1170: delph1(iph1);
! 1171: return -1;
! 1172: }
! 1173: #endif
! 1174: #ifdef ENABLE_FRAG
! 1175: iph1->frag = 0;
! 1176: iph1->frag_chain = NULL;
! 1177: #endif
! 1178: iph1->approval = NULL;
! 1179:
! 1180: #ifdef ENABLE_NATT
! 1181: /* RFC3947 says that we MUST accept new phases1 on NAT-T floated port.
! 1182: * We have to setup this flag now to correctly generate the first reply.
! 1183: * Don't know if a better check could be done for that ?
! 1184: */
! 1185: if(extract_port(local) == lcconf->port_isakmp_natt)
! 1186: iph1->natt_flags |= (NAT_PORTS_CHANGED);
! 1187: #endif
! 1188:
! 1189: /* copy remote address; remote and local always contain
! 1190: * port numbers so rmconf is not needed */
! 1191: if (copy_ph1addresses(iph1, NULL, remote, local) < 0) {
! 1192: delph1(iph1);
! 1193: return -1;
! 1194: }
! 1195: (void)insph1(iph1);
! 1196:
! 1197: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1198: {
! 1199: char *a;
! 1200:
! 1201: a = racoon_strdup(saddr2str(iph1->local));
! 1202: STRDUP_FATAL(a);
! 1203:
! 1204: plog(LLV_INFO, LOCATION, NULL,
! 1205: "respond new phase 1 negotiation: %s<=>%s\n",
! 1206: a, saddr2str(iph1->remote));
! 1207: racoon_free(a);
! 1208: }
! 1209: plog(LLV_INFO, LOCATION, NULL,
! 1210: "begin %s mode.\n", s_isakmp_etype(etype));
! 1211:
! 1212: #ifdef ENABLE_STATS
! 1213: gettimeofday(&iph1->start, NULL);
! 1214: gettimeofday(&start, NULL);
! 1215: #endif
! 1216:
! 1217: #ifndef ENABLE_FRAG
! 1218:
! 1219: /* start exchange */
! 1220: if ((ph1exchange[etypesw1(iph1->etype)]
! 1221: [iph1->side]
! 1222: [iph1->status])(iph1, msg) < 0
! 1223: || (ph1exchange[etypesw1(iph1->etype)]
! 1224: [iph1->side]
! 1225: [iph1->status])(iph1, msg) < 0) {
! 1226: plog(LLV_ERROR, LOCATION, remote,
! 1227: "failed to process ph1 packet (side: %d, status: %d).\n",
! 1228: iph1->side, iph1->status);
! 1229: remph1(iph1);
! 1230: delph1(iph1);
! 1231: return -1;
! 1232: }
! 1233:
! 1234: #ifdef ENABLE_STATS
! 1235: gettimeofday(&end, NULL);
! 1236: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 1237: "phase1",
! 1238: s_isakmp_state(iph1->etype, iph1->side, iph1->status),
! 1239: timedelta(&start, &end));
! 1240: #endif
! 1241:
! 1242: return 0;
! 1243:
! 1244: #else /* ENABLE_FRAG */
! 1245:
! 1246: /* now that we have a phase1 handle, feed back into our
! 1247: * main receive function to catch fragmented packets
! 1248: */
! 1249:
! 1250: return isakmp_main(msg, remote, local);
! 1251:
! 1252: #endif /* ENABLE_FRAG */
! 1253:
! 1254: }
! 1255:
! 1256: /* new negotiation of phase 2 for initiator */
! 1257: static int
! 1258: isakmp_ph2begin_i(iph1, iph2)
! 1259: struct ph1handle *iph1;
! 1260: struct ph2handle *iph2;
! 1261: {
! 1262: #ifdef ENABLE_HYBRID
! 1263: if (xauth_check(iph1) != 0) {
! 1264: plog(LLV_ERROR, LOCATION, NULL,
! 1265: "Attempt to start phase 2 whereas Xauth failed\n");
! 1266: return -1;
! 1267: }
! 1268: #endif
! 1269:
! 1270: /* fixup ph2 ports for this ph1 */
! 1271: if (extract_port(iph2->src) == 0)
! 1272: set_port(iph2->src, extract_port(iph1->local));
! 1273: if (extract_port(iph2->dst) == 0)
! 1274: set_port(iph2->dst, extract_port(iph1->remote));
! 1275:
! 1276: /* found ISAKMP-SA. */
! 1277: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1278: plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
! 1279: {
! 1280: char *a;
! 1281: a = racoon_strdup(saddr2str(iph2->src));
! 1282: STRDUP_FATAL(a);
! 1283:
! 1284: plog(LLV_INFO, LOCATION, NULL,
! 1285: "initiate new phase 2 negotiation: %s<=>%s\n",
! 1286: a, saddr2str(iph2->dst));
! 1287: racoon_free(a);
! 1288: }
! 1289:
! 1290: #ifdef ENABLE_STATS
! 1291: gettimeofday(&iph2->start, NULL);
! 1292: #endif
! 1293: if (iph2->status != PHASE2ST_EXPIRED) /* Phase 1 is already bound (ongoing rekeying) */
! 1294: bindph12(iph1, iph2);
! 1295: iph2->status = PHASE2ST_STATUS2;
! 1296:
! 1297: if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
! 1298: [iph2->side]
! 1299: [iph2->status])(iph2, NULL) < 0) {
! 1300: /* release ipsecsa handler due to internal error. */
! 1301: remph2(iph2);
! 1302: return -1;
! 1303: }
! 1304: return 0;
! 1305: }
! 1306:
! 1307: /* new negotiation of phase 2 for responder */
! 1308: static int
! 1309: isakmp_ph2begin_r(iph1, msg)
! 1310: struct ph1handle *iph1;
! 1311: vchar_t *msg;
! 1312: {
! 1313: struct isakmp *isakmp = (struct isakmp *)msg->v;
! 1314: struct ph2handle *iph2 = 0;
! 1315: int error;
! 1316: #ifdef ENABLE_STATS
! 1317: struct timeval start, end;
! 1318: #endif
! 1319: #ifdef ENABLE_HYBRID
! 1320: if (xauth_check(iph1) != 0) {
! 1321: plog(LLV_ERROR, LOCATION, NULL,
! 1322: "Attempt to start phase 2 whereas Xauth failed\n");
! 1323: return -1;
! 1324: }
! 1325: #endif
! 1326:
! 1327: iph2 = newph2();
! 1328: if (iph2 == NULL) {
! 1329: plog(LLV_ERROR, LOCATION, NULL,
! 1330: "failed to allocate phase2 entry.\n");
! 1331: return -1;
! 1332: }
! 1333:
! 1334: iph2->side = RESPONDER;
! 1335: iph2->status = PHASE2ST_START;
! 1336: iph2->flags = isakmp->flags;
! 1337: iph2->msgid = isakmp->msgid;
! 1338: iph2->seq = pk_getseq();
! 1339: iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
! 1340: if (iph2->ivm == NULL) {
! 1341: delph2(iph2);
! 1342: return -1;
! 1343: }
! 1344: iph2->dst = dupsaddr(iph1->remote); /* XXX should be considered */
! 1345: if (iph2->dst == NULL) {
! 1346: delph2(iph2);
! 1347: return -1;
! 1348: }
! 1349: iph2->src = dupsaddr(iph1->local); /* XXX should be considered */
! 1350: if (iph2->src == NULL) {
! 1351: delph2(iph2);
! 1352: return -1;
! 1353: }
! 1354:
! 1355: /* add new entry to isakmp status table */
! 1356: insph2(iph2);
! 1357: bindph12(iph1, iph2);
! 1358:
! 1359: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1360: {
! 1361: char *a;
! 1362:
! 1363: a = racoon_strdup(saddr2str(iph2->src));
! 1364: STRDUP_FATAL(a);
! 1365:
! 1366: plog(LLV_INFO, LOCATION, NULL,
! 1367: "respond new phase 2 negotiation: %s<=>%s\n",
! 1368: a, saddr2str(iph2->dst));
! 1369: racoon_free(a);
! 1370: }
! 1371:
! 1372: #ifdef ENABLE_STATS
! 1373: gettimeofday(&start, NULL);
! 1374: #endif
! 1375:
! 1376: error = (ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
! 1377: [iph2->side]
! 1378: [iph2->status])(iph2, msg);
! 1379: if (error != 0) {
! 1380: plog(LLV_ERROR, LOCATION, iph1->remote,
! 1381: "failed to pre-process ph2 packet (side: %d, status: %d).\n",
! 1382: iph2->side, iph2->status);
! 1383: if (error != ISAKMP_INTERNAL_ERROR)
! 1384: isakmp_info_send_n1(iph2->ph1, error, NULL);
! 1385: /*
! 1386: * release handler because it's wrong that ph2handle is kept
! 1387: * after failed to check message for responder's.
! 1388: */
! 1389: remph2(iph2);
! 1390: delph2(iph2);
! 1391: return -1;
! 1392: }
! 1393:
! 1394: /* send */
! 1395: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1396: if ((ph2exchange[etypesw2(isakmp->etype)]
! 1397: [iph2->side]
! 1398: [iph2->status])(iph2, msg) < 0) {
! 1399: plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
! 1400: "failed to process ph2 packet (side: %d, status: %d).\n",
! 1401: iph2->side, iph2->status);
! 1402: /* don't release handler */
! 1403: return -1;
! 1404: }
! 1405: #ifdef ENABLE_STATS
! 1406: gettimeofday(&end, NULL);
! 1407: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 1408: "phase2",
! 1409: s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
! 1410: timedelta(&start, &end));
! 1411: #endif
! 1412:
! 1413: return 0;
! 1414: }
! 1415:
! 1416: /*
! 1417: * parse ISAKMP payloads, without ISAKMP base header.
! 1418: */
! 1419: vchar_t *
! 1420: isakmp_parsewoh(np0, gen, len)
! 1421: int np0;
! 1422: struct isakmp_gen *gen;
! 1423: int len;
! 1424: {
! 1425: u_char np = np0 & 0xff;
! 1426: int tlen, plen;
! 1427: vchar_t *result;
! 1428: struct isakmp_parse_t *p, *ep;
! 1429:
! 1430: plog(LLV_DEBUG, LOCATION, NULL, "begin.\n");
! 1431:
! 1432: /*
! 1433: * 5 is a magic number, but any value larger than 2 should be fine
! 1434: * as we do vrealloc() in the following loop.
! 1435: */
! 1436: result = vmalloc(sizeof(struct isakmp_parse_t) * 5);
! 1437: if (result == NULL) {
! 1438: plog(LLV_ERROR, LOCATION, NULL,
! 1439: "failed to get buffer.\n");
! 1440: return NULL;
! 1441: }
! 1442: p = (struct isakmp_parse_t *)result->v;
! 1443: ep = (struct isakmp_parse_t *)(result->v + result->l - sizeof(*ep));
! 1444:
! 1445: tlen = len;
! 1446:
! 1447: /* parse through general headers */
! 1448: while (0 < tlen && np != ISAKMP_NPTYPE_NONE) {
! 1449: if (tlen <= sizeof(struct isakmp_gen)) {
! 1450: /* don't send information, see isakmp_ident_r1() */
! 1451: plog(LLV_ERROR, LOCATION, NULL,
! 1452: "invalid length of payload\n");
! 1453: vfree(result);
! 1454: return NULL;
! 1455: }
! 1456:
! 1457: plog(LLV_DEBUG, LOCATION, NULL,
! 1458: "seen nptype=%u(%s)\n", np, s_isakmp_nptype(np));
! 1459:
! 1460: p->type = np;
! 1461: p->len = ntohs(gen->len);
! 1462: if (p->len < sizeof(struct isakmp_gen) || p->len > tlen) {
! 1463: plog(LLV_DEBUG, LOCATION, NULL,
! 1464: "invalid length of payload\n");
! 1465: vfree(result);
! 1466: return NULL;
! 1467: }
! 1468: p->ptr = gen;
! 1469: p++;
! 1470: if (ep <= p) {
! 1471: int off;
! 1472:
! 1473: off = p - (struct isakmp_parse_t *)result->v;
! 1474: result = vrealloc(result, result->l * 2);
! 1475: if (result == NULL) {
! 1476: plog(LLV_DEBUG, LOCATION, NULL,
! 1477: "failed to realloc buffer.\n");
! 1478: vfree(result);
! 1479: return NULL;
! 1480: }
! 1481: ep = (struct isakmp_parse_t *)
! 1482: (result->v + result->l - sizeof(*ep));
! 1483: p = (struct isakmp_parse_t *)result->v;
! 1484: p += off;
! 1485: }
! 1486:
! 1487: np = gen->np;
! 1488: plen = ntohs(gen->len);
! 1489: gen = (struct isakmp_gen *)((caddr_t)gen + plen);
! 1490: tlen -= plen;
! 1491: }
! 1492: p->type = ISAKMP_NPTYPE_NONE;
! 1493: p->len = 0;
! 1494: p->ptr = NULL;
! 1495:
! 1496: plog(LLV_DEBUG, LOCATION, NULL, "succeed.\n");
! 1497:
! 1498: return result;
! 1499: }
! 1500:
! 1501: /*
! 1502: * parse ISAKMP payloads, including ISAKMP base header.
! 1503: */
! 1504: vchar_t *
! 1505: isakmp_parse(buf)
! 1506: vchar_t *buf;
! 1507: {
! 1508: struct isakmp *isakmp = (struct isakmp *)buf->v;
! 1509: struct isakmp_gen *gen;
! 1510: int tlen;
! 1511: vchar_t *result;
! 1512: u_char np;
! 1513:
! 1514: np = isakmp->np;
! 1515: gen = (struct isakmp_gen *)(buf->v + sizeof(*isakmp));
! 1516: tlen = buf->l - sizeof(struct isakmp);
! 1517: result = isakmp_parsewoh(np, gen, tlen);
! 1518:
! 1519: return result;
! 1520: }
! 1521:
! 1522: /* %%% */
! 1523: int
! 1524: isakmp_init()
! 1525: {
! 1526: /* initialize a isakmp status table */
! 1527: initph1tree();
! 1528: initph2tree();
! 1529: initctdtree();
! 1530: init_recvdpkt();
! 1531:
! 1532: return 0;
! 1533: }
! 1534:
! 1535: /*
! 1536: * make strings containing i_cookie + r_cookie + msgid
! 1537: */
! 1538: const char *
! 1539: isakmp_pindex(index, msgid)
! 1540: const isakmp_index *index;
! 1541: const u_int32_t msgid;
! 1542: {
! 1543: static char buf[64];
! 1544: const u_char *p;
! 1545: int i, j;
! 1546:
! 1547: memset(buf, 0, sizeof(buf));
! 1548:
! 1549: /* copy index */
! 1550: p = (const u_char *)index;
! 1551: for (j = 0, i = 0; i < sizeof(isakmp_index); i++) {
! 1552: snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]);
! 1553: j += 2;
! 1554: switch (i) {
! 1555: case 7:
! 1556: buf[j++] = ':';
! 1557: }
! 1558: }
! 1559:
! 1560: if (msgid == 0)
! 1561: return buf;
! 1562:
! 1563: /* copy msgid */
! 1564: snprintf((char *)&buf[j], sizeof(buf) - j, ":%08x", ntohs(msgid));
! 1565:
! 1566: return buf;
! 1567: }
! 1568:
! 1569: /* open ISAKMP sockets. */
! 1570: int
! 1571: isakmp_open(struct sockaddr *addr, int udp_encap)
! 1572: {
! 1573: const int yes = 1;
! 1574: int ifnum = 0, encap_ifnum = 0, fd;
! 1575: struct sockaddr_in *sin = (struct sockaddr_in *) addr;
! 1576: #ifdef INET6
! 1577: struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
! 1578: int pktinfo;
! 1579: #endif
! 1580: #ifdef ENABLE_NATT
! 1581: int option = -1;
! 1582: #endif
! 1583:
! 1584: /* warn if wildcard address - should we forbid this? */
! 1585: switch (addr->sa_family) {
! 1586: case AF_INET:
! 1587: if (sin->sin_addr.s_addr == 0)
! 1588: plog(LLV_WARNING, LOCATION, NULL,
! 1589: "listening to wildcard address,"
! 1590: "broadcast IKE packet may kill you\n");
! 1591: break;
! 1592: #ifdef INET6
! 1593: case AF_INET6:
! 1594: if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
! 1595: plog(LLV_DEBUG, LOCATION, NULL,
! 1596: "ignoring multicast address %s\n",
! 1597: saddr2str(addr));
! 1598: return -1;
! 1599: }
! 1600:
! 1601: if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
! 1602: plog(LLV_WARNING, LOCATION, NULL,
! 1603: "listening to wildcard address, "
! 1604: "broadcast IKE packet may kill you\n");
! 1605: break;
! 1606: #endif
! 1607: default:
! 1608: plog(LLV_ERROR, LOCATION, NULL,
! 1609: "unsupported address family %d\n",
! 1610: addr->sa_family);
! 1611: return -1;
! 1612: }
! 1613:
! 1614: if ((fd = privsep_socket(addr->sa_family, SOCK_DGRAM, 0)) < 0) {
! 1615: plog(LLV_ERROR, LOCATION, NULL,
! 1616: "socket(%s)\n", strerror(errno));
! 1617: return -1;
! 1618: }
! 1619: close_on_exec(fd);
! 1620: if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
! 1621: plog(LLV_WARNING, LOCATION, NULL,
! 1622: "failed to put socket in non-blocking mode\n");
! 1623:
! 1624: /* receive my interface address on inbound packets. */
! 1625: switch (addr->sa_family) {
! 1626: case AF_INET:
! 1627: if (setsockopt(fd, IPPROTO_IP,
! 1628: #ifdef __linux__
! 1629: IP_PKTINFO,
! 1630: #else
! 1631: IP_RECVDSTADDR,
! 1632: #endif
! 1633: (const void *) &yes, sizeof(yes)) < 0) {
! 1634: plog(LLV_ERROR, LOCATION, NULL,
! 1635: "setsockopt IP_RECVDSTADDR (%s)\n",
! 1636: strerror(errno));
! 1637: goto err;
! 1638: }
! 1639:
! 1640: #ifdef ENABLE_NATT
! 1641: if (udp_encap)
! 1642: option = UDP_ENCAP_ESPINUDP;
! 1643: #if defined(ENABLE_NATT_00) || defined(ENABLE_NATT_01)
! 1644: else
! 1645: option = UDP_ENCAP_ESPINUDP_NON_IKE;
! 1646: #endif
! 1647: if (option == -1)
! 1648: break;
! 1649:
! 1650: if (setsockopt(fd, SOL_UDP,
! 1651: UDP_ENCAP, &option,
! 1652: sizeof(option)) < 0) {
! 1653: plog(LLV_WARNING, LOCATION, NULL,
! 1654: "setsockopt(%s): UDP_ENCAP %s\n",
! 1655: option == UDP_ENCAP_ESPINUDP ? "UDP_ENCAP_ESPINUDP" : "UDP_ENCAP_ESPINUDP_NON_IKE",
! 1656: strerror(errno));
! 1657: } else {
! 1658: plog(LLV_INFO, LOCATION, NULL,
! 1659: "%s used for NAT-T\n",
! 1660: saddr2str(addr));
! 1661: }
! 1662: #endif
! 1663: break;
! 1664:
! 1665: #ifdef INET6
! 1666: case AF_INET6:
! 1667: #if defined(INET6_ADVAPI)
! 1668: #ifdef IPV6_RECVPKTINFO
! 1669: pktinfo = IPV6_RECVPKTINFO;
! 1670: #else /* old adv. API */
! 1671: pktinfo = IPV6_PKTINFO;
! 1672: #endif /* IPV6_RECVPKTINFO */
! 1673: #else
! 1674: pktinfo = IPV6_RECVDSTADDR;
! 1675: #endif
! 1676: if (setsockopt(fd, IPPROTO_IPV6, pktinfo,
! 1677: (const void *) &yes, sizeof(yes)) < 0) {
! 1678: plog(LLV_ERROR, LOCATION, NULL,
! 1679: "setsockopt IPV6_RECVDSTADDR (%d):%s\n",
! 1680: pktinfo, strerror(errno));
! 1681: goto err;
! 1682: }
! 1683:
! 1684: #ifdef IPV6_USE_MIN_MTU
! 1685: if (setsockopt(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
! 1686: (void *) &yes, sizeof(yes)) < 0) {
! 1687: plog(LLV_ERROR, LOCATION, NULL,
! 1688: "setsockopt IPV6_USE_MIN_MTU (%s)\n",
! 1689: strerror(errno));
! 1690: goto err;
! 1691: }
! 1692: #endif
! 1693: break;
! 1694: #endif
! 1695: }
! 1696:
! 1697: if (setsockopt(fd, SOL_SOCKET,
! 1698: #ifdef __linux__
! 1699: SO_REUSEADDR,
! 1700: #else
! 1701: SO_REUSEPORT,
! 1702: #endif
! 1703: (void *) &yes, sizeof(yes)) < 0) {
! 1704: plog(LLV_ERROR, LOCATION, NULL,
! 1705: "failed to set REUSE flag on %s (%s).\n",
! 1706: saddr2str(addr), strerror(errno));
! 1707: goto err;
! 1708: }
! 1709:
! 1710: if (setsockopt_bypass(fd, addr->sa_family) < 0)
! 1711: goto err;
! 1712:
! 1713: if (privsep_bind(fd, addr, sysdep_sa_len(addr)) < 0) {
! 1714: plog(LLV_ERROR, LOCATION, addr,
! 1715: "failed to bind to address %s (%s).\n",
! 1716: saddr2str(addr), strerror(errno));
! 1717: goto err;
! 1718: }
! 1719:
! 1720: plog(LLV_INFO, LOCATION, NULL,
! 1721: "%s used as isakmp port (fd=%d)\n",
! 1722: saddr2str(addr), fd);
! 1723:
! 1724: monitor_fd(fd, isakmp_handler, NULL, 1);
! 1725: return fd;
! 1726:
! 1727: err:
! 1728: close(fd);
! 1729: return -1;
! 1730: }
! 1731:
! 1732: void
! 1733: isakmp_close(int fd)
! 1734: {
! 1735: unmonitor_fd(fd);
! 1736: close(fd);
! 1737: }
! 1738:
! 1739: int
! 1740: isakmp_send(iph1, sbuf)
! 1741: struct ph1handle *iph1;
! 1742: vchar_t *sbuf;
! 1743: {
! 1744: int len = 0;
! 1745: int s;
! 1746: vchar_t *vbuf = NULL, swap;
! 1747:
! 1748: #ifdef ENABLE_NATT
! 1749: size_t extralen = NON_ESP_MARKER_USE(iph1) ? NON_ESP_MARKER_LEN : 0;
! 1750:
! 1751: /* Check if NON_ESP_MARKER_LEN is already there (happens when resending packets)
! 1752: */
! 1753: if(extralen == NON_ESP_MARKER_LEN &&
! 1754: *(u_int32_t *)sbuf->v == 0)
! 1755: extralen = 0;
! 1756:
! 1757: #ifdef ENABLE_FRAG
! 1758: /*
! 1759: * Do not add the non ESP marker for a packet that will
! 1760: * be fragmented. The non ESP marker should appear in
! 1761: * all fragment's packets, but not in the fragmented packet
! 1762: */
! 1763: if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN)
! 1764: extralen = 0;
! 1765: #endif
! 1766: if (extralen)
! 1767: plog (LLV_DEBUG, LOCATION, NULL, "Adding NON-ESP marker\n");
! 1768:
! 1769: /* If NAT-T port floating is in use, 4 zero bytes (non-ESP marker)
! 1770: must added just before the packet itself. For this we must
! 1771: allocate a new buffer and release it at the end. */
! 1772: if (extralen) {
! 1773: if ((vbuf = vmalloc (sbuf->l + extralen)) == NULL) {
! 1774: plog(LLV_ERROR, LOCATION, NULL,
! 1775: "vbuf allocation failed\n");
! 1776: return -1;
! 1777: }
! 1778: *(u_int32_t *)vbuf->v = 0;
! 1779: memcpy (vbuf->v + extralen, sbuf->v, sbuf->l);
! 1780: /* ensures that the modified buffer will be sent back to the caller, so
! 1781: * add_recvdpkt() will add the correct buffer
! 1782: */
! 1783: swap = *sbuf;
! 1784: *sbuf = *vbuf;
! 1785: *vbuf = swap;
! 1786: vfree(vbuf);
! 1787: }
! 1788: #endif
! 1789:
! 1790: /* select the socket to be sent */
! 1791: s = myaddr_getfd(iph1->local);
! 1792: if (s == -1)
! 1793: return -1;
! 1794:
! 1795: plog (LLV_DEBUG, LOCATION, NULL, "%zu bytes %s\n", sbuf->l,
! 1796: saddr2str_fromto("from %s to %s", iph1->local, iph1->remote));
! 1797:
! 1798: #ifdef ENABLE_FRAG
! 1799: if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN) {
! 1800: if (isakmp_sendfrags(iph1, sbuf) == -1) {
! 1801: plog(LLV_ERROR, LOCATION, NULL,
! 1802: "isakmp_sendfrags failed\n");
! 1803: return -1;
! 1804: }
! 1805: } else
! 1806: #endif
! 1807: {
! 1808: len = sendfromto(s, sbuf->v, sbuf->l,
! 1809: iph1->local, iph1->remote, lcconf->count_persend);
! 1810:
! 1811: if (len == -1) {
! 1812: plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
! 1813: return -1;
! 1814: }
! 1815: }
! 1816:
! 1817: return 0;
! 1818: }
! 1819:
! 1820: /* called from scheduler */
! 1821: static void
! 1822: isakmp_ph1resend_stub(p)
! 1823: struct sched *p;
! 1824: {
! 1825: struct ph1handle *iph1 = container_of(p, struct ph1handle, scr);
! 1826:
! 1827: if (isakmp_ph1resend(iph1) < 0) {
! 1828: remph1(iph1);
! 1829: delph1(iph1);
! 1830: }
! 1831: }
! 1832:
! 1833: static int
! 1834: isakmp_ph1resend(iph1)
! 1835: struct ph1handle *iph1;
! 1836: {
! 1837: /* Note: NEVER do the rem/del here, it will be done by the caller or by the _stub function
! 1838: */
! 1839: if (iph1->retry_counter <= 0) {
! 1840: plog(LLV_ERROR, LOCATION, NULL,
! 1841: "phase1 negotiation failed due to time up. %s\n",
! 1842: isakmp_pindex(&iph1->index, iph1->msgid));
! 1843: /* XXX is the peer really "dead" here ??? */
! 1844: script_hook(iph1, SCRIPT_PHASE1_DEAD);
! 1845: evt_phase1(iph1, EVT_PHASE1_NO_RESPONSE, NULL);
! 1846:
! 1847: return -1;
! 1848: }
! 1849:
! 1850: if (isakmp_send(iph1, iph1->sendbuf) < 0){
! 1851: plog(LLV_ERROR, LOCATION, NULL,
! 1852: "phase1 negotiation failed due to send error. %s\n",
! 1853: isakmp_pindex(&iph1->index, iph1->msgid));
! 1854: evt_phase1(iph1, EVT_PHASE1_NO_RESPONSE, NULL);
! 1855: return -1;
! 1856: }
! 1857:
! 1858: plog(LLV_DEBUG, LOCATION, NULL,
! 1859: "resend phase1 packet %s\n",
! 1860: isakmp_pindex(&iph1->index, iph1->msgid));
! 1861:
! 1862: iph1->retry_counter--;
! 1863:
! 1864: sched_schedule(&iph1->scr, lcconf->retry_interval,
! 1865: isakmp_ph1resend_stub);
! 1866:
! 1867: return 0;
! 1868: }
! 1869:
! 1870: int
! 1871: isakmp_ph1send(iph1)
! 1872: struct ph1handle *iph1;
! 1873: {
! 1874: iph1->retry_counter = lcconf->retry_counter;
! 1875: return isakmp_ph1resend(iph1);
! 1876: }
! 1877:
! 1878: /* called from scheduler */
! 1879: static void
! 1880: isakmp_ph2resend_stub(p)
! 1881: struct sched *p;
! 1882: {
! 1883: struct ph2handle *iph2 = container_of(p, struct ph2handle, scr);
! 1884:
! 1885: if (isakmp_ph2resend(iph2) < 0) {
! 1886: remph2(iph2);
! 1887: delph2(iph2);
! 1888: }
! 1889: }
! 1890:
! 1891: static int
! 1892: isakmp_ph2resend(iph2)
! 1893: struct ph2handle *iph2;
! 1894: {
! 1895: /* Note: NEVER do the unbind/rem/del here, it will be done by the caller or by the _stub function
! 1896: */
! 1897: if (iph2->ph1->status >= PHASE1ST_EXPIRED) {
! 1898: plog(LLV_ERROR, LOCATION, NULL,
! 1899: "phase2 negotiation failed due to phase1 expired. %s\n",
! 1900: isakmp_pindex(&iph2->ph1->index, iph2->msgid));
! 1901: return -1;
! 1902: }
! 1903:
! 1904: if (iph2->retry_counter <= 0) {
! 1905: plog(LLV_ERROR, LOCATION, NULL,
! 1906: "phase2 negotiation failed due to time up. %s\n",
! 1907: isakmp_pindex(&iph2->ph1->index, iph2->msgid));
! 1908: evt_phase2(iph2, EVT_PHASE2_NO_RESPONSE, NULL);
! 1909: unbindph12(iph2);
! 1910: return -1;
! 1911: }
! 1912:
! 1913: if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0){
! 1914: plog(LLV_ERROR, LOCATION, NULL,
! 1915: "phase2 negotiation failed due to send error. %s\n",
! 1916: isakmp_pindex(&iph2->ph1->index, iph2->msgid));
! 1917: evt_phase2(iph2, EVT_PHASE2_NO_RESPONSE, NULL);
! 1918: return -1;
! 1919: }
! 1920:
! 1921: plog(LLV_DEBUG, LOCATION, NULL,
! 1922: "resend phase2 packet %s\n",
! 1923: isakmp_pindex(&iph2->ph1->index, iph2->msgid));
! 1924:
! 1925: iph2->retry_counter--;
! 1926:
! 1927: sched_schedule(&iph2->scr, lcconf->retry_interval,
! 1928: isakmp_ph2resend_stub);
! 1929:
! 1930: return 0;
! 1931: }
! 1932:
! 1933: int
! 1934: isakmp_ph2send(iph2)
! 1935: struct ph2handle *iph2;
! 1936: {
! 1937: iph2->retry_counter = lcconf->retry_counter;
! 1938: return isakmp_ph2resend(iph2);
! 1939: }
! 1940:
! 1941: /* called from scheduler */
! 1942: void
! 1943: isakmp_ph1dying_stub(p)
! 1944: struct sched *p;
! 1945: {
! 1946:
! 1947: isakmp_ph1dying(container_of(p, struct ph1handle, sce));
! 1948: }
! 1949:
! 1950: void
! 1951: isakmp_ph1dying(iph1)
! 1952: struct ph1handle *iph1;
! 1953: {
! 1954: struct ph1handle *new_iph1;
! 1955: struct ph2handle *p;
! 1956: struct remoteconf *rmconf;
! 1957:
! 1958: if (iph1->status >= PHASE1ST_DYING)
! 1959: return;
! 1960:
! 1961: /* Going away in after a while... */
! 1962: iph1->status = PHASE1ST_DYING;
! 1963:
! 1964: /* Any fresh phase1s? */
! 1965: new_iph1 = getph1(iph1, iph1->local, iph1->remote, 1);
! 1966: if (new_iph1 == NULL) {
! 1967: LIST_FOREACH(p, &iph1->ph2tree, ph1bind) {
! 1968: if (p->status != PHASE2ST_ESTABLISHED)
! 1969: continue;
! 1970:
! 1971: plog(LLV_INFO, LOCATION, NULL,
! 1972: "renegotiating phase1 to %s due to "
! 1973: "active phase2\n",
! 1974: saddrwop2str(iph1->remote));
! 1975:
! 1976: if (iph1->side == INITIATOR)
! 1977: isakmp_ph1begin_i(iph1->rmconf, iph1->remote,
! 1978: iph1->local);
! 1979:
! 1980: break;
! 1981: }
! 1982: } else {
! 1983: migrate_ph12(iph1, new_iph1);
! 1984: }
! 1985:
! 1986: /* Schedule for expiration */
! 1987: sched_schedule(&iph1->sce, iph1->approval->lifetime *
! 1988: (100 - PFKEY_SOFT_LIFETIME_RATE) / 100,
! 1989: isakmp_ph1expire_stub);
! 1990: }
! 1991:
! 1992: /* called from scheduler */
! 1993: void
! 1994: isakmp_ph1expire_stub(p)
! 1995: struct sched *p;
! 1996: {
! 1997: isakmp_ph1expire(container_of(p, struct ph1handle, sce));
! 1998: }
! 1999:
! 2000: void
! 2001: isakmp_ph1expire(iph1)
! 2002: struct ph1handle *iph1;
! 2003: {
! 2004: char *src, *dst;
! 2005:
! 2006: if (iph1->status < PHASE1ST_EXPIRED) {
! 2007: src = racoon_strdup(saddr2str(iph1->local));
! 2008: dst = racoon_strdup(saddr2str(iph1->remote));
! 2009: STRDUP_FATAL(src);
! 2010: STRDUP_FATAL(dst);
! 2011:
! 2012: plog(LLV_INFO, LOCATION, NULL,
! 2013: "ISAKMP-SA expired %s-%s spi:%s\n",
! 2014: src, dst,
! 2015: isakmp_pindex(&iph1->index, 0));
! 2016: racoon_free(src);
! 2017: racoon_free(dst);
! 2018: iph1->status = PHASE1ST_EXPIRED;
! 2019: }
! 2020:
! 2021: isakmp_ph1delete(iph1);
! 2022: }
! 2023:
! 2024: /* called from scheduler */
! 2025: void
! 2026: isakmp_ph1delete_stub(p)
! 2027: struct sched *p;
! 2028: {
! 2029:
! 2030: isakmp_ph1delete(container_of(p, struct ph1handle, sce));
! 2031: }
! 2032:
! 2033: void
! 2034: isakmp_ph1delete(iph1)
! 2035: struct ph1handle *iph1;
! 2036: {
! 2037: struct ph2handle *p, *next;
! 2038: struct ph1handle *new_iph1;
! 2039: char *src, *dst;
! 2040:
! 2041: /* Migrate established phase2s. Any fresh phase1s? */
! 2042: new_iph1 = getph1(iph1, iph1->local, iph1->remote, 1);
! 2043: if (new_iph1 != NULL)
! 2044: migrate_ph12(iph1, new_iph1);
! 2045:
! 2046: /* Discard any left phase2s */
! 2047: for (p = LIST_FIRST(&iph1->ph2tree); p; p = next) {
! 2048: next = LIST_NEXT(p, ph1bind);
! 2049: if (p->status == PHASE2ST_ESTABLISHED)
! 2050: isakmp_info_send_d2(p);
! 2051: /* remove all ph2 handles,
! 2052: * as ph1handle will be expired soon
! 2053: */
! 2054: delete_spd(p, 1);
! 2055: remph2(p);
! 2056: delph2(p);
! 2057: }
! 2058:
! 2059: src = racoon_strdup(saddr2str(iph1->local));
! 2060: dst = racoon_strdup(saddr2str(iph1->remote));
! 2061: STRDUP_FATAL(src);
! 2062: STRDUP_FATAL(dst);
! 2063:
! 2064: plog(LLV_INFO, LOCATION, NULL,
! 2065: "ISAKMP-SA deleted %s-%s spi:%s\n",
! 2066: src, dst, isakmp_pindex(&iph1->index, 0));
! 2067:
! 2068: evt_phase1(iph1, EVT_PHASE1_DOWN, NULL);
! 2069: if (new_iph1 == NULL && ph1_rekey_enabled(iph1))
! 2070: script_hook(iph1, SCRIPT_PHASE1_DEAD);
! 2071:
! 2072: racoon_free(src);
! 2073: racoon_free(dst);
! 2074:
! 2075: remph1(iph1);
! 2076: delph1(iph1);
! 2077: }
! 2078:
! 2079: /* called from scheduler.
! 2080: * this function will call only isakmp_ph2delete().
! 2081: * phase 2 handler remain forever if kernel doesn't cry a expire of phase 2 SA
! 2082: * by something cause. That's why this function is called after phase 2 SA
! 2083: * expires in the userland.
! 2084: */
! 2085: void
! 2086: isakmp_ph2expire_stub(p)
! 2087: struct sched *p;
! 2088: {
! 2089:
! 2090: isakmp_ph2expire(container_of(p, struct ph2handle, sce));
! 2091: }
! 2092:
! 2093: void
! 2094: isakmp_ph2expire(iph2)
! 2095: struct ph2handle *iph2;
! 2096: {
! 2097: char *src, *dst;
! 2098:
! 2099: src = racoon_strdup(saddrwop2str(iph2->src));
! 2100: dst = racoon_strdup(saddrwop2str(iph2->dst));
! 2101: STRDUP_FATAL(src);
! 2102: STRDUP_FATAL(dst);
! 2103:
! 2104: plog(LLV_INFO, LOCATION, NULL,
! 2105: "phase2 sa expired %s-%s\n", src, dst);
! 2106: racoon_free(src);
! 2107: racoon_free(dst);
! 2108:
! 2109: iph2->status = PHASE2ST_EXPIRED;
! 2110: sched_schedule(&iph2->sce, 1, isakmp_ph2delete_stub);
! 2111: }
! 2112:
! 2113: /* called from scheduler */
! 2114: void
! 2115: isakmp_ph2delete_stub(p)
! 2116: struct sched *p;
! 2117: {
! 2118:
! 2119: isakmp_ph2delete(container_of(p, struct ph2handle, sce));
! 2120: }
! 2121:
! 2122: void
! 2123: isakmp_ph2delete(iph2)
! 2124: struct ph2handle *iph2;
! 2125: {
! 2126: char *src, *dst;
! 2127:
! 2128: src = racoon_strdup(saddrwop2str(iph2->src));
! 2129: dst = racoon_strdup(saddrwop2str(iph2->dst));
! 2130: STRDUP_FATAL(src);
! 2131: STRDUP_FATAL(dst);
! 2132:
! 2133: plog(LLV_INFO, LOCATION, NULL,
! 2134: "phase2 sa deleted %s-%s\n", src, dst);
! 2135: racoon_free(src);
! 2136: racoon_free(dst);
! 2137:
! 2138: remph2(iph2);
! 2139: delph2(iph2);
! 2140:
! 2141: return;
! 2142: }
! 2143:
! 2144: /* %%%
! 2145: * Interface between PF_KEYv2 and ISAKMP
! 2146: */
! 2147: /*
! 2148: * receive ACQUIRE from kernel, and begin either phase1 or phase2.
! 2149: * if phase1 has been finished, begin phase2.
! 2150: */
! 2151: int
! 2152: isakmp_post_acquire(iph2, iph1hint, nopassive)
! 2153: struct ph2handle *iph2;
! 2154: struct ph1handle *iph1hint;
! 2155: int nopassive;
! 2156: {
! 2157: struct remoteconf *rmconf;
! 2158: struct ph1handle *iph1 = NULL;
! 2159:
! 2160: plog(LLV_DEBUG, LOCATION, NULL, "in post_acquire\n");
! 2161:
! 2162: /* Search appropriate configuration with masking port. Note that
! 2163: * we always use iph2->dst, and not iph2->sa_dst.
! 2164: *
! 2165: * XXX One possible need for using iph2->sa_dst if not NULL would
! 2166: * be for selecting a remote configuration based on a stable
! 2167: * address of a mobile node (not a CoA provided by MIGRATE/KMADDRESS
! 2168: * as iph2->dst hint). This scenario would require additional changes,
! 2169: * so no need to bother yet. --arno */
! 2170:
! 2171: if (iph1hint == NULL || iph1hint->rmconf == NULL) {
! 2172: rmconf = getrmconf(iph2->dst, nopassive ? GETRMCONF_F_NO_PASSIVE : 0);
! 2173: if (rmconf == NULL) {
! 2174: plog(LLV_ERROR, LOCATION, NULL,
! 2175: "no configuration found for %s.\n",
! 2176: saddrwop2str(iph2->dst));
! 2177: return -1;
! 2178: }
! 2179: } else {
! 2180: rmconf = iph1hint->rmconf;
! 2181: }
! 2182:
! 2183: /* if passive mode, ignore the acquire message */
! 2184: if (nopassive && rmconf->passive) {
! 2185: plog(LLV_DEBUG, LOCATION, NULL,
! 2186: "because of passive mode, "
! 2187: "ignore the acquire message for %s.\n",
! 2188: saddrwop2str(iph2->dst));
! 2189: return 0;
! 2190: }
! 2191:
! 2192: /*
! 2193: * XXX Searching by IP addresses + ports might fail on
! 2194: * some cases, we should use the ISAKMP identity to search
! 2195: * matching ISAKMP.
! 2196: */
! 2197: iph1 = getph1(iph1hint, iph2->src, iph2->dst, 0);
! 2198:
! 2199: /* no ISAKMP-SA found. */
! 2200: if (iph1 == NULL) {
! 2201: iph2->retry_checkph1 = lcconf->retry_checkph1;
! 2202: sched_schedule(&iph2->sce, 1, isakmp_chkph1there_stub);
! 2203: plog(LLV_INFO, LOCATION, NULL,
! 2204: "IPsec-SA request for %s queued "
! 2205: "due to no phase1 found.\n",
! 2206: saddrwop2str(iph2->dst));
! 2207:
! 2208: /* start phase 1 negotiation as a initiator. */
! 2209: if (isakmp_ph1begin_i(rmconf, iph2->dst, iph2->src) == NULL) {
! 2210: sched_cancel(&iph2->sce);
! 2211: return -1;
! 2212: }
! 2213:
! 2214: return 0;
! 2215: /*NOTREACHED*/
! 2216: }
! 2217:
! 2218: /* found ISAKMP-SA, but on negotiation. */
! 2219: if (iph1->status < PHASE1ST_ESTABLISHED) {
! 2220: iph2->retry_checkph1 = lcconf->retry_checkph1;
! 2221: sched_schedule(&iph2->sce, 1, isakmp_chkph1there_stub);
! 2222: plog(LLV_INFO, LOCATION, iph2->dst,
! 2223: "request for establishing IPsec-SA was queued "
! 2224: "due to no phase1 found.\n");
! 2225: return 0;
! 2226: /*NOTREACHED*/
! 2227: }
! 2228:
! 2229: /* found established ISAKMP-SA */
! 2230: /* i.e. iph1->status == PHASE1ST_ESTABLISHED */
! 2231:
! 2232: /* found ISAKMP-SA. */
! 2233: plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
! 2234:
! 2235: /* begin quick mode */
! 2236: if (isakmp_ph2begin_i(iph1, iph2))
! 2237: return -1;
! 2238:
! 2239: return 0;
! 2240: }
! 2241:
! 2242: int
! 2243: isakmp_get_sainfo(iph2, sp_out, sp_in)
! 2244: struct ph2handle *iph2;
! 2245: struct secpolicy *sp_out, *sp_in;
! 2246: {
! 2247: struct remoteconf *conf;
! 2248: uint32_t remoteid = 0;
! 2249:
! 2250: plog(LLV_DEBUG, LOCATION, NULL,
! 2251: "new acquire %s\n", spidx2str(&sp_out->spidx));
! 2252:
! 2253: /* get sainfo */
! 2254: {
! 2255: vchar_t *idsrc, *iddst;
! 2256:
! 2257: idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src,
! 2258: sp_out->spidx.prefs, sp_out->spidx.ul_proto);
! 2259: if (idsrc == NULL) {
! 2260: plog(LLV_ERROR, LOCATION, NULL,
! 2261: "failed to get ID for %s\n",
! 2262: spidx2str(&sp_out->spidx));
! 2263: return -1;
! 2264: }
! 2265: iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst,
! 2266: sp_out->spidx.prefd, sp_out->spidx.ul_proto);
! 2267: if (iddst == NULL) {
! 2268: plog(LLV_ERROR, LOCATION, NULL,
! 2269: "failed to get ID for %s\n",
! 2270: spidx2str(&sp_out->spidx));
! 2271: vfree(idsrc);
! 2272: return -1;
! 2273: }
! 2274:
! 2275: conf = getrmconf(iph2->dst, 0);
! 2276: if (conf != NULL)
! 2277: remoteid = conf->ph1id;
! 2278: else
! 2279: plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
! 2280:
! 2281: iph2->sainfo = getsainfo(idsrc, iddst, NULL, NULL, remoteid);
! 2282: vfree(idsrc);
! 2283: vfree(iddst);
! 2284: if (iph2->sainfo == NULL) {
! 2285: plog(LLV_ERROR, LOCATION, NULL,
! 2286: "failed to get sainfo.\n");
! 2287: return -1;
! 2288: /* XXX should use the algorithm list from register message */
! 2289: }
! 2290:
! 2291: plog(LLV_DEBUG, LOCATION, NULL,
! 2292: "selected sainfo: %s\n", sainfo2str(iph2->sainfo));
! 2293: }
! 2294:
! 2295: if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) {
! 2296: plog(LLV_ERROR, LOCATION, NULL,
! 2297: "failed to create saprop.\n");
! 2298: return -1;
! 2299: }
! 2300:
! 2301: return 0;
! 2302: }
! 2303:
! 2304:
! 2305: /*
! 2306: * receive GETSPI from kernel.
! 2307: */
! 2308: int
! 2309: isakmp_post_getspi(iph2)
! 2310: struct ph2handle *iph2;
! 2311: {
! 2312: #ifdef ENABLE_STATS
! 2313: struct timeval start, end;
! 2314: #endif
! 2315:
! 2316: /* don't process it because there is no suitable phase1-sa. */
! 2317: if (iph2->ph1->status >= PHASE1ST_EXPIRED) {
! 2318: plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
! 2319: "the negotiation is stopped, "
! 2320: "because there is no suitable ISAKMP-SA.\n");
! 2321: return -1;
! 2322: }
! 2323:
! 2324: #ifdef ENABLE_STATS
! 2325: gettimeofday(&start, NULL);
! 2326: #endif
! 2327: if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
! 2328: [iph2->side]
! 2329: [iph2->status])(iph2, NULL) != 0)
! 2330: return -1;
! 2331: #ifdef ENABLE_STATS
! 2332: gettimeofday(&end, NULL);
! 2333: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 2334: "phase2",
! 2335: s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
! 2336: timedelta(&start, &end));
! 2337: #endif
! 2338:
! 2339: return 0;
! 2340: }
! 2341:
! 2342: /* called by scheduler */
! 2343: void
! 2344: isakmp_chkph1there_stub(p)
! 2345: struct sched *p;
! 2346: {
! 2347: isakmp_chkph1there(container_of(p, struct ph2handle, sce));
! 2348: }
! 2349:
! 2350: void
! 2351: isakmp_chkph1there(iph2)
! 2352: struct ph2handle *iph2;
! 2353: {
! 2354: struct ph1handle *iph1;
! 2355:
! 2356: iph2->retry_checkph1--;
! 2357: if (iph2->retry_checkph1 < 0) {
! 2358: plog(LLV_ERROR, LOCATION, iph2->dst,
! 2359: "phase2 negotiation failed "
! 2360: "due to time up waiting for phase1. %s\n",
! 2361: sadbsecas2str(iph2->dst, iph2->src,
! 2362: iph2->satype, 0, 0));
! 2363: plog(LLV_INFO, LOCATION, NULL,
! 2364: "delete phase 2 handler.\n");
! 2365:
! 2366: /* send acquire to kernel as error */
! 2367: pk_sendeacquire(iph2);
! 2368:
! 2369: remph2(iph2);
! 2370: delph2(iph2);
! 2371:
! 2372: return;
! 2373: }
! 2374:
! 2375: /* Search isakmp status table by address and port */
! 2376: iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
! 2377:
! 2378: /* XXX Even if ph1 as responder is there, should we not start
! 2379: * phase 2 negotiation ? */
! 2380: if (iph1 != NULL
! 2381: && iph1->status == PHASE1ST_ESTABLISHED) {
! 2382: /* found isakmp-sa */
! 2383:
! 2384: plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: got a ph1 handler, setting ports.\n");
! 2385: plog(LLV_DEBUG2, LOCATION, NULL, "iph1->local: %s\n", saddr2str(iph1->local));
! 2386: plog(LLV_DEBUG2, LOCATION, NULL, "iph1->remote: %s\n", saddr2str(iph1->remote));
! 2387: plog(LLV_DEBUG2, LOCATION, NULL, "before:\n");
! 2388: plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(iph2->src));
! 2389: plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
! 2390: set_port(iph2->src, extract_port(iph1->local));
! 2391: set_port(iph2->dst, extract_port(iph1->remote));
! 2392: plog(LLV_DEBUG2, LOCATION, NULL, "After:\n");
! 2393: plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(iph2->src));
! 2394: plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
! 2395:
! 2396: /* begin quick mode */
! 2397: (void)isakmp_ph2begin_i(iph1, iph2);
! 2398: return;
! 2399: }
! 2400:
! 2401: plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: no established ph1 handler found\n");
! 2402:
! 2403: /* no isakmp-sa found */
! 2404: sched_schedule(&iph2->sce, 1, isakmp_chkph1there_stub);
! 2405:
! 2406: return;
! 2407: }
! 2408:
! 2409: /* copy variable data into ALLOCATED buffer. */
! 2410: caddr_t
! 2411: isakmp_set_attr_v(buf, type, val, len)
! 2412: caddr_t buf;
! 2413: int type;
! 2414: caddr_t val;
! 2415: int len;
! 2416: {
! 2417: struct isakmp_data *data;
! 2418:
! 2419: data = (struct isakmp_data *)buf;
! 2420: data->type = htons((u_int16_t)type | ISAKMP_GEN_TLV);
! 2421: data->lorv = htons((u_int16_t)len);
! 2422: memcpy(data + 1, val, len);
! 2423:
! 2424: return buf + sizeof(*data) + len;
! 2425: }
! 2426:
! 2427: /* copy fixed length data into ALLOCATED buffer. */
! 2428: caddr_t
! 2429: isakmp_set_attr_l(buf, type, val)
! 2430: caddr_t buf;
! 2431: int type;
! 2432: u_int32_t val;
! 2433: {
! 2434: struct isakmp_data *data;
! 2435:
! 2436: data = (struct isakmp_data *)buf;
! 2437: data->type = htons((u_int16_t)type | ISAKMP_GEN_TV);
! 2438: data->lorv = htons((u_int16_t)val);
! 2439:
! 2440: return buf + sizeof(*data);
! 2441: }
! 2442:
! 2443: /* add a variable data attribute to the buffer by reallocating it. */
! 2444: vchar_t *
! 2445: isakmp_add_attr_v(buf0, type, val, len)
! 2446: vchar_t *buf0;
! 2447: int type;
! 2448: caddr_t val;
! 2449: int len;
! 2450: {
! 2451: vchar_t *buf = NULL;
! 2452: struct isakmp_data *data;
! 2453: int tlen;
! 2454: int oldlen = 0;
! 2455:
! 2456: tlen = sizeof(*data) + len;
! 2457:
! 2458: if (buf0) {
! 2459: oldlen = buf0->l;
! 2460: buf = vrealloc(buf0, oldlen + tlen);
! 2461: } else
! 2462: buf = vmalloc(tlen);
! 2463: if (!buf) {
! 2464: plog(LLV_ERROR, LOCATION, NULL,
! 2465: "failed to get a attribute buffer.\n");
! 2466: return NULL;
! 2467: }
! 2468:
! 2469: data = (struct isakmp_data *)(buf->v + oldlen);
! 2470: data->type = htons((u_int16_t)type | ISAKMP_GEN_TLV);
! 2471: data->lorv = htons((u_int16_t)len);
! 2472: memcpy(data + 1, val, len);
! 2473:
! 2474: return buf;
! 2475: }
! 2476:
! 2477: /* add a fixed data attribute to the buffer by reallocating it. */
! 2478: vchar_t *
! 2479: isakmp_add_attr_l(buf0, type, val)
! 2480: vchar_t *buf0;
! 2481: int type;
! 2482: u_int32_t val;
! 2483: {
! 2484: vchar_t *buf = NULL;
! 2485: struct isakmp_data *data;
! 2486: int tlen;
! 2487: int oldlen = 0;
! 2488:
! 2489: tlen = sizeof(*data);
! 2490:
! 2491: if (buf0) {
! 2492: oldlen = buf0->l;
! 2493: buf = vrealloc(buf0, oldlen + tlen);
! 2494: } else
! 2495: buf = vmalloc(tlen);
! 2496: if (!buf) {
! 2497: plog(LLV_ERROR, LOCATION, NULL,
! 2498: "failed to get a attribute buffer.\n");
! 2499: return NULL;
! 2500: }
! 2501:
! 2502: data = (struct isakmp_data *)(buf->v + oldlen);
! 2503: data->type = htons((u_int16_t)type | ISAKMP_GEN_TV);
! 2504: data->lorv = htons((u_int16_t)val);
! 2505:
! 2506: return buf;
! 2507: }
! 2508:
! 2509: /*
! 2510: * calculate cookie and set.
! 2511: */
! 2512: int
! 2513: isakmp_newcookie(place, remote, local)
! 2514: caddr_t place;
! 2515: struct sockaddr *remote;
! 2516: struct sockaddr *local;
! 2517: {
! 2518: vchar_t *buf = NULL, *buf2 = NULL;
! 2519: char *p;
! 2520: int blen;
! 2521: int alen;
! 2522: caddr_t sa1, sa2;
! 2523: time_t t;
! 2524: int error = -1;
! 2525: u_short port;
! 2526:
! 2527:
! 2528: if (remote->sa_family != local->sa_family) {
! 2529: plog(LLV_ERROR, LOCATION, NULL,
! 2530: "address family mismatch, remote:%d local:%d\n",
! 2531: remote->sa_family, local->sa_family);
! 2532: goto end;
! 2533: }
! 2534: switch (remote->sa_family) {
! 2535: case AF_INET:
! 2536: alen = sizeof(struct in_addr);
! 2537: sa1 = (caddr_t)&((struct sockaddr_in *)remote)->sin_addr;
! 2538: sa2 = (caddr_t)&((struct sockaddr_in *)local)->sin_addr;
! 2539: break;
! 2540: #ifdef INET6
! 2541: case AF_INET6:
! 2542: alen = sizeof(struct in6_addr);
! 2543: sa1 = (caddr_t)&((struct sockaddr_in6 *)remote)->sin6_addr;
! 2544: sa2 = (caddr_t)&((struct sockaddr_in6 *)local)->sin6_addr;
! 2545: break;
! 2546: #endif
! 2547: default:
! 2548: plog(LLV_ERROR, LOCATION, NULL,
! 2549: "invalid family: %d\n", remote->sa_family);
! 2550: goto end;
! 2551: }
! 2552: blen = (alen + sizeof(u_short)) * 2
! 2553: + sizeof(time_t) + lcconf->secret_size;
! 2554: buf = vmalloc(blen);
! 2555: if (buf == NULL) {
! 2556: plog(LLV_ERROR, LOCATION, NULL,
! 2557: "failed to get a cookie.\n");
! 2558: goto end;
! 2559: }
! 2560: p = buf->v;
! 2561:
! 2562: /* copy my address */
! 2563: memcpy(p, sa1, alen);
! 2564: p += alen;
! 2565: port = ((struct sockaddr_in *)remote)->sin_port;
! 2566: memcpy(p, &port, sizeof(u_short));
! 2567: p += sizeof(u_short);
! 2568:
! 2569: /* copy target address */
! 2570: memcpy(p, sa2, alen);
! 2571: p += alen;
! 2572: port = ((struct sockaddr_in *)local)->sin_port;
! 2573: memcpy(p, &port, sizeof(u_short));
! 2574: p += sizeof(u_short);
! 2575:
! 2576: /* copy time */
! 2577: t = time(0);
! 2578: memcpy(p, (caddr_t)&t, sizeof(t));
! 2579: p += sizeof(t);
! 2580:
! 2581: /* copy random value */
! 2582: buf2 = eay_set_random(lcconf->secret_size);
! 2583: if (buf2 == NULL)
! 2584: goto end;
! 2585: memcpy(p, buf2->v, lcconf->secret_size);
! 2586: p += lcconf->secret_size;
! 2587: vfree(buf2);
! 2588:
! 2589: buf2 = eay_sha1_one(buf);
! 2590: memcpy(place, buf2->v, sizeof(cookie_t));
! 2591:
! 2592: sa1 = val2str(place, sizeof (cookie_t));
! 2593: plog(LLV_DEBUG, LOCATION, NULL, "new cookie:\n%s\n", sa1);
! 2594: racoon_free(sa1);
! 2595:
! 2596: error = 0;
! 2597: end:
! 2598: if (buf != NULL)
! 2599: vfree(buf);
! 2600: if (buf2 != NULL)
! 2601: vfree(buf2);
! 2602: return error;
! 2603: }
! 2604:
! 2605: /*
! 2606: * save partner's(payload) data into phhandle.
! 2607: */
! 2608: int
! 2609: isakmp_p2ph(buf, gen)
! 2610: vchar_t **buf;
! 2611: struct isakmp_gen *gen;
! 2612: {
! 2613: /* XXX to be checked in each functions for logging. */
! 2614: if (*buf) {
! 2615: plog(LLV_WARNING, LOCATION, NULL,
! 2616: "ignore this payload, same payload type exist.\n");
! 2617: return -1;
! 2618: }
! 2619:
! 2620: *buf = vmalloc(ntohs(gen->len) - sizeof(*gen));
! 2621: if (*buf == NULL) {
! 2622: plog(LLV_ERROR, LOCATION, NULL,
! 2623: "failed to get buffer.\n");
! 2624: return -1;
! 2625: }
! 2626: memcpy((*buf)->v, gen + 1, (*buf)->l);
! 2627:
! 2628: return 0;
! 2629: }
! 2630:
! 2631: u_int32_t
! 2632: isakmp_newmsgid2(iph1)
! 2633: struct ph1handle *iph1;
! 2634: {
! 2635: u_int32_t msgid2;
! 2636:
! 2637: do {
! 2638: msgid2 = eay_random();
! 2639: } while (getph2bymsgid(iph1, msgid2));
! 2640:
! 2641: return msgid2;
! 2642: }
! 2643:
! 2644: /*
! 2645: * set values into allocated buffer of isakmp header for phase 1
! 2646: */
! 2647: static caddr_t
! 2648: set_isakmp_header(vbuf, iph1, nptype, etype, flags, msgid)
! 2649: vchar_t *vbuf;
! 2650: struct ph1handle *iph1;
! 2651: int nptype;
! 2652: u_int8_t etype;
! 2653: u_int8_t flags;
! 2654: u_int32_t msgid;
! 2655: {
! 2656: struct isakmp *isakmp;
! 2657:
! 2658: if (vbuf->l < sizeof(*isakmp))
! 2659: return NULL;
! 2660:
! 2661: isakmp = (struct isakmp *)vbuf->v;
! 2662:
! 2663: memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
! 2664: memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
! 2665: isakmp->np = nptype;
! 2666: isakmp->v = iph1->version;
! 2667: isakmp->etype = etype;
! 2668: isakmp->flags = flags;
! 2669: isakmp->msgid = msgid;
! 2670: isakmp->len = htonl(vbuf->l);
! 2671:
! 2672: return vbuf->v + sizeof(*isakmp);
! 2673: }
! 2674:
! 2675: /*
! 2676: * set values into allocated buffer of isakmp header for phase 1
! 2677: */
! 2678: caddr_t
! 2679: set_isakmp_header1(vbuf, iph1, nptype)
! 2680: vchar_t *vbuf;
! 2681: struct ph1handle *iph1;
! 2682: int nptype;
! 2683: {
! 2684: return set_isakmp_header (vbuf, iph1, nptype, iph1->etype, iph1->flags, iph1->msgid);
! 2685: }
! 2686:
! 2687: /*
! 2688: * set values into allocated buffer of isakmp header for phase 2
! 2689: */
! 2690: caddr_t
! 2691: set_isakmp_header2(vbuf, iph2, nptype)
! 2692: vchar_t *vbuf;
! 2693: struct ph2handle *iph2;
! 2694: int nptype;
! 2695: {
! 2696: return set_isakmp_header (vbuf, iph2->ph1, nptype, ISAKMP_ETYPE_QUICK, iph2->flags, iph2->msgid);
! 2697: }
! 2698:
! 2699: /*
! 2700: * set values into allocated buffer of isakmp payload.
! 2701: */
! 2702: caddr_t
! 2703: set_isakmp_payload(buf, src, nptype)
! 2704: caddr_t buf;
! 2705: vchar_t *src;
! 2706: int nptype;
! 2707: {
! 2708: struct isakmp_gen *gen;
! 2709: caddr_t p = buf;
! 2710:
! 2711: plog(LLV_DEBUG, LOCATION, NULL, "add payload of len %zu, next type %d\n",
! 2712: src->l, nptype);
! 2713:
! 2714: gen = (struct isakmp_gen *)p;
! 2715: gen->np = nptype;
! 2716: gen->len = htons(sizeof(*gen) + src->l);
! 2717: p += sizeof(*gen);
! 2718: memcpy(p, src->v, src->l);
! 2719: p += src->l;
! 2720:
! 2721: return p;
! 2722: }
! 2723:
! 2724: static int
! 2725: etypesw1(etype)
! 2726: int etype;
! 2727: {
! 2728: switch (etype) {
! 2729: case ISAKMP_ETYPE_IDENT:
! 2730: return 1;
! 2731: case ISAKMP_ETYPE_AGG:
! 2732: return 2;
! 2733: case ISAKMP_ETYPE_BASE:
! 2734: return 3;
! 2735: default:
! 2736: return 0;
! 2737: }
! 2738: /*NOTREACHED*/
! 2739: }
! 2740:
! 2741: static int
! 2742: etypesw2(etype)
! 2743: int etype;
! 2744: {
! 2745: switch (etype) {
! 2746: case ISAKMP_ETYPE_QUICK:
! 2747: return 1;
! 2748: default:
! 2749: return 0;
! 2750: }
! 2751: /*NOTREACHED*/
! 2752: }
! 2753:
! 2754: #ifdef HAVE_PRINT_ISAKMP_C
! 2755: /* for print-isakmp.c */
! 2756: char *snapend;
! 2757: extern void isakmp_print __P((const u_char *, u_int, const u_char *));
! 2758:
! 2759: char *getname __P((const u_char *));
! 2760: #ifdef INET6
! 2761: char *getname6 __P((const u_char *));
! 2762: #endif
! 2763: int safeputchar __P((int));
! 2764:
! 2765: /*
! 2766: * Return a name for the IP address pointed to by ap. This address
! 2767: * is assumed to be in network byte order.
! 2768: */
! 2769: char *
! 2770: getname(ap)
! 2771: const u_char *ap;
! 2772: {
! 2773: struct sockaddr_in addr;
! 2774: static char ntop_buf[NI_MAXHOST];
! 2775:
! 2776: memset(&addr, 0, sizeof(addr));
! 2777: #ifndef __linux__
! 2778: addr.sin_len = sizeof(struct sockaddr_in);
! 2779: #endif
! 2780: addr.sin_family = AF_INET;
! 2781: memcpy(&addr.sin_addr, ap, sizeof(addr.sin_addr));
! 2782: if (getnameinfo((struct sockaddr *)&addr, sizeof(addr),
! 2783: ntop_buf, sizeof(ntop_buf), NULL, 0,
! 2784: NI_NUMERICHOST | niflags))
! 2785: strlcpy(ntop_buf, "?", sizeof(ntop_buf));
! 2786:
! 2787: return ntop_buf;
! 2788: }
! 2789:
! 2790: #ifdef INET6
! 2791: /*
! 2792: * Return a name for the IP6 address pointed to by ap. This address
! 2793: * is assumed to be in network byte order.
! 2794: */
! 2795: char *
! 2796: getname6(ap)
! 2797: const u_char *ap;
! 2798: {
! 2799: struct sockaddr_in6 addr;
! 2800: static char ntop_buf[NI_MAXHOST];
! 2801:
! 2802: memset(&addr, 0, sizeof(addr));
! 2803: addr.sin6_len = sizeof(struct sockaddr_in6);
! 2804: addr.sin6_family = AF_INET6;
! 2805: memcpy(&addr.sin6_addr, ap, sizeof(addr.sin6_addr));
! 2806: if (getnameinfo((struct sockaddr *)&addr, addr.sin6_len,
! 2807: ntop_buf, sizeof(ntop_buf), NULL, 0,
! 2808: NI_NUMERICHOST | niflags))
! 2809: strlcpy(ntop_buf, "?", sizeof(ntop_buf));
! 2810:
! 2811: return ntop_buf;
! 2812: }
! 2813: #endif /* INET6 */
! 2814:
! 2815: int
! 2816: safeputchar(c)
! 2817: int c;
! 2818: {
! 2819: unsigned char ch;
! 2820:
! 2821: ch = (unsigned char)(c & 0xff);
! 2822: if (c < 0x80 && isprint(c))
! 2823: return printf("%c", c & 0xff);
! 2824: else
! 2825: return printf("\\%03o", c & 0xff);
! 2826: }
! 2827:
! 2828: void
! 2829: isakmp_printpacket(msg, from, my, decoded)
! 2830: vchar_t *msg;
! 2831: struct sockaddr *from;
! 2832: struct sockaddr *my;
! 2833: int decoded;
! 2834: {
! 2835: #ifdef YIPS_DEBUG
! 2836: struct timeval tv;
! 2837: int s;
! 2838: char hostbuf[NI_MAXHOST];
! 2839: char portbuf[NI_MAXSERV];
! 2840: struct isakmp *isakmp;
! 2841: vchar_t *buf;
! 2842: #endif
! 2843:
! 2844: if (loglevel < LLV_DEBUG)
! 2845: return;
! 2846:
! 2847: #ifdef YIPS_DEBUG
! 2848: plog(LLV_DEBUG, LOCATION, NULL, "begin.\n");
! 2849:
! 2850: gettimeofday(&tv, NULL);
! 2851: s = tv.tv_sec % 3600;
! 2852: printf("%02d:%02d.%06u ", s / 60, s % 60, (u_int32_t)tv.tv_usec);
! 2853:
! 2854: if (from) {
! 2855: if (getnameinfo(from, sysdep_sa_len(from), hostbuf, sizeof(hostbuf),
! 2856: portbuf, sizeof(portbuf),
! 2857: NI_NUMERICHOST | NI_NUMERICSERV | niflags)) {
! 2858: strlcpy(hostbuf, "?", sizeof(hostbuf));
! 2859: strlcpy(portbuf, "?", sizeof(portbuf));
! 2860: }
! 2861: printf("%s:%s", hostbuf, portbuf);
! 2862: } else
! 2863: printf("?");
! 2864: printf(" -> ");
! 2865: if (my) {
! 2866: if (getnameinfo(my, sysdep_sa_len(my), hostbuf, sizeof(hostbuf),
! 2867: portbuf, sizeof(portbuf),
! 2868: NI_NUMERICHOST | NI_NUMERICSERV | niflags)) {
! 2869: strlcpy(hostbuf, "?", sizeof(hostbuf));
! 2870: strlcpy(portbuf, "?", sizeof(portbuf));
! 2871: }
! 2872: printf("%s:%s", hostbuf, portbuf);
! 2873: } else
! 2874: printf("?");
! 2875: printf(": ");
! 2876:
! 2877: buf = vdup(msg);
! 2878: if (!buf) {
! 2879: printf("(malloc fail)\n");
! 2880: return;
! 2881: }
! 2882: if (decoded) {
! 2883: isakmp = (struct isakmp *)buf->v;
! 2884: if (isakmp->flags & ISAKMP_FLAG_E) {
! 2885: #if 0
! 2886: int pad;
! 2887: pad = *(u_char *)(buf->v + buf->l - 1);
! 2888: if (buf->l < pad && 2 < vflag)
! 2889: printf("(wrong padding)");
! 2890: #endif
! 2891: isakmp->flags &= ~ISAKMP_FLAG_E;
! 2892: }
! 2893: }
! 2894:
! 2895: snapend = buf->v + buf->l;
! 2896: isakmp_print(buf->v, buf->l, NULL);
! 2897: vfree(buf);
! 2898: printf("\n");
! 2899: fflush(stdout);
! 2900:
! 2901: return;
! 2902: #endif
! 2903: }
! 2904: #endif /*HAVE_PRINT_ISAKMP_C*/
! 2905:
! 2906: int
! 2907: copy_ph1addresses(iph1, rmconf, remote, local)
! 2908: struct ph1handle *iph1;
! 2909: struct remoteconf *rmconf;
! 2910: struct sockaddr *remote, *local;
! 2911: {
! 2912: u_int16_t port;
! 2913:
! 2914: /* address portion must be grabbed from real remote address "remote" */
! 2915: iph1->remote = dupsaddr(remote);
! 2916: if (iph1->remote == NULL)
! 2917: return -1;
! 2918:
! 2919: /*
! 2920: * if remote has no port # (in case of initiator - from ACQUIRE msg)
! 2921: * - if remote.conf specifies port #, use that
! 2922: * - if remote.conf does not, use 500
! 2923: * if remote has port # (in case of responder - from recvfrom(2))
! 2924: * respect content of "remote".
! 2925: */
! 2926: if (extract_port(iph1->remote) == 0) {
! 2927: port = 0;
! 2928: if (rmconf != NULL)
! 2929: port = extract_port(rmconf->remote);
! 2930: if (port == 0)
! 2931: port = PORT_ISAKMP;
! 2932: set_port(iph1->remote, port);
! 2933: }
! 2934:
! 2935: if (local == NULL)
! 2936: iph1->local = getlocaladdr(iph1->remote);
! 2937: else
! 2938: iph1->local = dupsaddr(local);
! 2939: if (iph1->local == NULL)
! 2940: return -1;
! 2941:
! 2942: if (extract_port(iph1->local) == 0) {
! 2943: port = myaddr_getsport(iph1->local);
! 2944: if (port == 0)
! 2945: port = PORT_ISAKMP;
! 2946: set_port(iph1->local, PORT_ISAKMP);
! 2947: }
! 2948:
! 2949: #ifdef ENABLE_NATT
! 2950: if (extract_port(iph1->local) == lcconf->port_isakmp_natt) {
! 2951: plog(LLV_DEBUG, LOCATION, NULL, "Marking ports as changed\n");
! 2952: iph1->natt_flags |= NAT_ADD_NON_ESP_MARKER;
! 2953: }
! 2954: #endif
! 2955:
! 2956: return 0;
! 2957: }
! 2958:
! 2959: static int
! 2960: nostate1(iph1, msg)
! 2961: struct ph1handle *iph1;
! 2962: vchar_t *msg;
! 2963: {
! 2964: plog(LLV_ERROR, LOCATION, iph1->remote, "wrong state %u.\n",
! 2965: iph1->status);
! 2966: return -1;
! 2967: }
! 2968:
! 2969: static int
! 2970: nostate2(iph2, msg)
! 2971: struct ph2handle *iph2;
! 2972: vchar_t *msg;
! 2973: {
! 2974: plog(LLV_ERROR, LOCATION, iph2->ph1->remote, "wrong state %u.\n",
! 2975: iph2->status);
! 2976: return -1;
! 2977: }
! 2978:
! 2979: void
! 2980: log_ph1established(iph1)
! 2981: const struct ph1handle *iph1;
! 2982: {
! 2983: char *src, *dst;
! 2984:
! 2985: src = racoon_strdup(saddr2str(iph1->local));
! 2986: dst = racoon_strdup(saddr2str(iph1->remote));
! 2987: STRDUP_FATAL(src);
! 2988: STRDUP_FATAL(dst);
! 2989:
! 2990: plog(LLV_INFO, LOCATION, NULL,
! 2991: "ISAKMP-SA established %s-%s spi:%s\n",
! 2992: src, dst,
! 2993: isakmp_pindex(&iph1->index, 0));
! 2994:
! 2995: evt_phase1(iph1, EVT_PHASE1_UP, NULL);
! 2996: if(!iph1->rmconf->mode_cfg)
! 2997: evt_phase1(iph1, EVT_PHASE1_MODE_CFG, NULL);
! 2998:
! 2999: racoon_free(src);
! 3000: racoon_free(dst);
! 3001:
! 3002: return;
! 3003: }
! 3004:
! 3005: struct payload_list *
! 3006: isakmp_plist_append_full (struct payload_list *plist, vchar_t *payload,
! 3007: u_int8_t payload_type, u_int8_t free_payload)
! 3008: {
! 3009: if (! plist) {
! 3010: plist = racoon_malloc (sizeof (struct payload_list));
! 3011: plist->prev = NULL;
! 3012: }
! 3013: else {
! 3014: plist->next = racoon_malloc (sizeof (struct payload_list));
! 3015: plist->next->prev = plist;
! 3016: plist = plist->next;
! 3017: }
! 3018:
! 3019: plist->next = NULL;
! 3020: plist->payload = payload;
! 3021: plist->payload_type = payload_type;
! 3022: plist->free_payload = free_payload;
! 3023:
! 3024: return plist;
! 3025: }
! 3026:
! 3027: vchar_t *
! 3028: isakmp_plist_set_all (struct payload_list **plist, struct ph1handle *iph1)
! 3029: {
! 3030: struct payload_list *ptr = *plist, *first;
! 3031: size_t tlen = sizeof (struct isakmp), n = 0;
! 3032: vchar_t *buf = NULL;
! 3033: char *p;
! 3034:
! 3035: /* Seek to the first item. */
! 3036: while (ptr->prev) ptr = ptr->prev;
! 3037: first = ptr;
! 3038:
! 3039: /* Compute the whole length. */
! 3040: while (ptr) {
! 3041: tlen += ptr->payload->l + sizeof (struct isakmp_gen);
! 3042: ptr = ptr->next;
! 3043: }
! 3044:
! 3045: buf = vmalloc(tlen);
! 3046: if (buf == NULL) {
! 3047: plog(LLV_ERROR, LOCATION, NULL,
! 3048: "failed to get buffer to send.\n");
! 3049: goto end;
! 3050: }
! 3051:
! 3052: ptr = first;
! 3053:
! 3054: p = set_isakmp_header1(buf, iph1, ptr->payload_type);
! 3055: if (p == NULL)
! 3056: goto end;
! 3057:
! 3058: while (ptr)
! 3059: {
! 3060: p = set_isakmp_payload (p, ptr->payload, ptr->next ? ptr->next->payload_type : ISAKMP_NPTYPE_NONE);
! 3061: first = ptr;
! 3062: ptr = ptr->next;
! 3063: if (first->free_payload)
! 3064: vfree(first->payload);
! 3065: racoon_free (first);
! 3066: /* ptr->prev = NULL; first = NULL; ... omitted. */
! 3067: n++;
! 3068: }
! 3069:
! 3070: *plist = NULL;
! 3071:
! 3072: return buf;
! 3073: end:
! 3074: if (buf != NULL)
! 3075: vfree(buf);
! 3076: return NULL;
! 3077: }
! 3078:
! 3079: #ifdef ENABLE_FRAG
! 3080: int
! 3081: frag_handler(iph1, msg, remote, local)
! 3082: struct ph1handle *iph1;
! 3083: vchar_t *msg;
! 3084: struct sockaddr *remote;
! 3085: struct sockaddr *local;
! 3086: {
! 3087: vchar_t *newmsg;
! 3088:
! 3089: if (isakmp_frag_extract(iph1, msg) == 1) {
! 3090: if ((newmsg = isakmp_frag_reassembly(iph1)) == NULL) {
! 3091: plog(LLV_ERROR, LOCATION, remote,
! 3092: "Packet reassembly failed\n");
! 3093: return -1;
! 3094: }
! 3095: return isakmp_main(newmsg, remote, local);
! 3096: }
! 3097:
! 3098: return 0;
! 3099: }
! 3100: #endif
! 3101:
! 3102: void
! 3103: script_hook(iph1, script)
! 3104: struct ph1handle *iph1;
! 3105: int script;
! 3106: {
! 3107: #define IP_MAX 40
! 3108: #define PORT_MAX 6
! 3109: char addrstr[IP_MAX];
! 3110: char portstr[PORT_MAX];
! 3111: char **envp = NULL;
! 3112: int envc = 1;
! 3113: char **c;
! 3114:
! 3115: if (iph1 == NULL ||
! 3116: iph1->rmconf == NULL ||
! 3117: iph1->rmconf->script[script] == NULL)
! 3118: return;
! 3119:
! 3120: #ifdef ENABLE_HYBRID
! 3121: (void)isakmp_cfg_setenv(iph1, &envp, &envc);
! 3122: #endif
! 3123:
! 3124: /* local address */
! 3125: GETNAMEINFO(iph1->local, addrstr, portstr);
! 3126:
! 3127: if (script_env_append(&envp, &envc, "LOCAL_ADDR", addrstr) != 0) {
! 3128: plog(LLV_ERROR, LOCATION, NULL, "Cannot set LOCAL_ADDR\n");
! 3129: goto out;
! 3130: }
! 3131:
! 3132: if (script_env_append(&envp, &envc, "LOCAL_PORT", portstr) != 0) {
! 3133: plog(LLV_ERROR, LOCATION, NULL, "Cannot set LOCAL_PORT\n");
! 3134: goto out;
! 3135: }
! 3136:
! 3137: /* Peer address */
! 3138: if (iph1->remote != NULL) {
! 3139: GETNAMEINFO(iph1->remote, addrstr, portstr);
! 3140:
! 3141: if (script_env_append(&envp, &envc,
! 3142: "REMOTE_ADDR", addrstr) != 0) {
! 3143: plog(LLV_ERROR, LOCATION, NULL,
! 3144: "Cannot set REMOTE_ADDR\n");
! 3145: goto out;
! 3146: }
! 3147:
! 3148: if (script_env_append(&envp, &envc,
! 3149: "REMOTE_PORT", portstr) != 0) {
! 3150: plog(LLV_ERROR, LOCATION, NULL,
! 3151: "Cannot set REMOTEL_PORT\n");
! 3152: goto out;
! 3153: }
! 3154: }
! 3155:
! 3156: /* Peer identity. */
! 3157: if (iph1->id_p != NULL) {
! 3158: if (script_env_append(&envp, &envc, "REMOTE_ID",
! 3159: ipsecdoi_id2str(iph1->id_p)) != 0) {
! 3160: plog(LLV_ERROR, LOCATION, NULL,
! 3161: "Cannot set REMOTE_ID\n");
! 3162: goto out;
! 3163: }
! 3164: }
! 3165:
! 3166: if (privsep_script_exec(iph1->rmconf->script[script]->v,
! 3167: script, envp) != 0)
! 3168: plog(LLV_ERROR, LOCATION, NULL,
! 3169: "Script %s execution failed\n", script_names[script]);
! 3170:
! 3171: out:
! 3172: for (c = envp; *c; c++)
! 3173: racoon_free(*c);
! 3174:
! 3175: racoon_free(envp);
! 3176:
! 3177: return;
! 3178: }
! 3179:
! 3180: int
! 3181: script_env_append(envp, envc, name, value)
! 3182: char ***envp;
! 3183: int *envc;
! 3184: char *name;
! 3185: char *value;
! 3186: {
! 3187: char *envitem;
! 3188: char **newenvp;
! 3189: int newenvc;
! 3190:
! 3191: envitem = racoon_malloc(strlen(name) + 1 + strlen(value) + 1);
! 3192: if (envitem == NULL) {
! 3193: plog(LLV_ERROR, LOCATION, NULL,
! 3194: "Cannot allocate memory: %s\n", strerror(errno));
! 3195: return -1;
! 3196: }
! 3197: sprintf(envitem, "%s=%s", name, value);
! 3198:
! 3199: newenvc = (*envc) + 1;
! 3200: newenvp = racoon_realloc(*envp, newenvc * sizeof(char *));
! 3201: if (newenvp == NULL) {
! 3202: plog(LLV_ERROR, LOCATION, NULL,
! 3203: "Cannot allocate memory: %s\n", strerror(errno));
! 3204: racoon_free(envitem);
! 3205: return -1;
! 3206: }
! 3207:
! 3208: newenvp[newenvc - 2] = envitem;
! 3209: newenvp[newenvc - 1] = NULL;
! 3210:
! 3211: *envp = newenvp;
! 3212: *envc = newenvc;
! 3213: return 0;
! 3214: }
! 3215:
! 3216: int
! 3217: script_exec(script, name, envp)
! 3218: char *script;
! 3219: int name;
! 3220: char *const envp[];
! 3221: {
! 3222: char *argv[] = { NULL, NULL, NULL };
! 3223:
! 3224: argv[0] = script;
! 3225: argv[1] = script_names[name];
! 3226: argv[2] = NULL;
! 3227:
! 3228: switch (fork()) {
! 3229: case 0:
! 3230: execve(argv[0], argv, envp);
! 3231: plog(LLV_ERROR, LOCATION, NULL,
! 3232: "execve(\"%s\") failed: %s\n",
! 3233: argv[0], strerror(errno));
! 3234: _exit(1);
! 3235: break;
! 3236: case -1:
! 3237: plog(LLV_ERROR, LOCATION, NULL,
! 3238: "Cannot fork: %s\n", strerror(errno));
! 3239: return -1;
! 3240: break;
! 3241: default:
! 3242: break;
! 3243: }
! 3244: return 0;
! 3245:
! 3246: }
! 3247:
! 3248: void
! 3249: purge_remote(iph1)
! 3250: struct ph1handle *iph1;
! 3251: {
! 3252: vchar_t *buf = NULL;
! 3253: struct sadb_msg *msg, *next, *end;
! 3254: struct sadb_sa *sa;
! 3255: struct sockaddr *src, *dst;
! 3256: caddr_t mhp[SADB_EXT_MAX + 1];
! 3257: u_int proto_id;
! 3258: struct ph2handle *iph2;
! 3259: struct ph1handle *new_iph1;
! 3260:
! 3261: plog(LLV_INFO, LOCATION, NULL,
! 3262: "purging ISAKMP-SA spi=%s.\n",
! 3263: isakmp_pindex(&(iph1->index), iph1->msgid));
! 3264:
! 3265: /* Mark as expired. */
! 3266: iph1->status = PHASE1ST_EXPIRED;
! 3267:
! 3268: /* Check if we have another, still valid, phase1 SA. */
! 3269: new_iph1 = getph1(iph1, iph1->local, iph1->remote, GETPH1_F_ESTABLISHED);
! 3270:
! 3271: /*
! 3272: * Delete all orphaned or binded to the deleting ph1handle phase2 SAs.
! 3273: * Keep all others phase2 SAs.
! 3274: */
! 3275: buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
! 3276: if (buf == NULL) {
! 3277: plog(LLV_DEBUG, LOCATION, NULL,
! 3278: "pfkey_dump_sadb returned nothing.\n");
! 3279: return;
! 3280: }
! 3281:
! 3282: msg = (struct sadb_msg *)buf->v;
! 3283: end = (struct sadb_msg *)(buf->v + buf->l);
! 3284:
! 3285: while (msg < end) {
! 3286: if ((msg->sadb_msg_len << 3) < sizeof(*msg))
! 3287: break;
! 3288: next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
! 3289: if (msg->sadb_msg_type != SADB_DUMP) {
! 3290: msg = next;
! 3291: continue;
! 3292: }
! 3293:
! 3294: if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
! 3295: plog(LLV_ERROR, LOCATION, NULL,
! 3296: "pfkey_check (%s)\n", ipsec_strerror());
! 3297: msg = next;
! 3298: continue;
! 3299: }
! 3300:
! 3301: sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
! 3302: if (!sa ||
! 3303: !mhp[SADB_EXT_ADDRESS_SRC] ||
! 3304: !mhp[SADB_EXT_ADDRESS_DST]) {
! 3305: msg = next;
! 3306: continue;
! 3307: }
! 3308: pk_fixup_sa_addresses(mhp);
! 3309: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 3310: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 3311:
! 3312: if (sa->sadb_sa_state != SADB_SASTATE_LARVAL &&
! 3313: sa->sadb_sa_state != SADB_SASTATE_MATURE &&
! 3314: sa->sadb_sa_state != SADB_SASTATE_DYING) {
! 3315: msg = next;
! 3316: continue;
! 3317: }
! 3318:
! 3319: /*
! 3320: * check in/outbound SAs.
! 3321: * Select only SAs where src == local and dst == remote (outgoing)
! 3322: * or src == remote and dst == local (incoming).
! 3323: */
! 3324: if ((cmpsaddr(iph1->local, src) != CMPSADDR_MATCH ||
! 3325: cmpsaddr(iph1->remote, dst) != CMPSADDR_MATCH) &&
! 3326: (cmpsaddr(iph1->local, dst) != CMPSADDR_MATCH ||
! 3327: cmpsaddr(iph1->remote, src) != CMPSADDR_MATCH)) {
! 3328: msg = next;
! 3329: continue;
! 3330: }
! 3331:
! 3332: proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
! 3333: iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
! 3334:
! 3335: /* Check if there is another valid ISAKMP-SA */
! 3336: if (new_iph1 != NULL) {
! 3337:
! 3338: if (iph2 == NULL) {
! 3339: /* No handler... still send a pfkey_delete message, but log this !*/
! 3340: plog(LLV_INFO, LOCATION, NULL,
! 3341: "Unknown IPsec-SA spi=%u, hmmmm?\n",
! 3342: ntohl(sa->sadb_sa_spi));
! 3343: }else{
! 3344:
! 3345: /*
! 3346: * If we have a new ph1, do not purge IPsec-SAs binded
! 3347: * to a different ISAKMP-SA
! 3348: */
! 3349: if (iph2->ph1 != NULL && iph2->ph1 != iph1){
! 3350: msg = next;
! 3351: continue;
! 3352: }
! 3353:
! 3354: /* If the ph2handle is established, do not purge IPsec-SA */
! 3355: if (iph2->status == PHASE2ST_ESTABLISHED ||
! 3356: iph2->status == PHASE2ST_EXPIRED) {
! 3357:
! 3358: plog(LLV_INFO, LOCATION, NULL,
! 3359: "keeping IPsec-SA spi=%u - found valid ISAKMP-SA spi=%s.\n",
! 3360: ntohl(sa->sadb_sa_spi),
! 3361: isakmp_pindex(&(new_iph1->index), new_iph1->msgid));
! 3362: msg = next;
! 3363: continue;
! 3364: }
! 3365: }
! 3366: }
! 3367:
! 3368:
! 3369: pfkey_send_delete(lcconf->sock_pfkey,
! 3370: msg->sadb_msg_satype,
! 3371: IPSEC_MODE_ANY,
! 3372: src, dst, sa->sadb_sa_spi);
! 3373:
! 3374: /* delete a relative phase 2 handle. */
! 3375: if (iph2 != NULL) {
! 3376: delete_spd(iph2, 0);
! 3377: remph2(iph2);
! 3378: delph2(iph2);
! 3379: }
! 3380:
! 3381: plog(LLV_INFO, LOCATION, NULL,
! 3382: "purged IPsec-SA spi=%u.\n",
! 3383: ntohl(sa->sadb_sa_spi));
! 3384:
! 3385: msg = next;
! 3386: }
! 3387:
! 3388: if (buf)
! 3389: vfree(buf);
! 3390:
! 3391: /* Mark the phase1 handler as EXPIRED */
! 3392: plog(LLV_INFO, LOCATION, NULL,
! 3393: "purged ISAKMP-SA spi=%s.\n",
! 3394: isakmp_pindex(&(iph1->index), iph1->msgid));
! 3395:
! 3396: isakmp_ph1delete(iph1);
! 3397: }
! 3398:
! 3399: void
! 3400: delete_spd(iph2, created)
! 3401: struct ph2handle *iph2;
! 3402: u_int64_t created;
! 3403: {
! 3404: struct policyindex spidx;
! 3405: struct sockaddr_storage addr;
! 3406: u_int8_t pref;
! 3407: struct sockaddr *src;
! 3408: struct sockaddr *dst;
! 3409: int error;
! 3410: int idi2type = 0;/* switch whether copy IDs into id[src,dst]. */
! 3411:
! 3412: if (iph2 == NULL)
! 3413: return;
! 3414:
! 3415: /* Delete the SPD entry if we generated it
! 3416: */
! 3417: if (! iph2->generated_spidx )
! 3418: return;
! 3419:
! 3420: src = iph2->src;
! 3421: dst = iph2->dst;
! 3422:
! 3423: plog(LLV_INFO, LOCATION, NULL,
! 3424: "deleting a generated policy.\n");
! 3425:
! 3426: memset(&spidx, 0, sizeof(spidx));
! 3427: iph2->spidx_gen = (caddr_t )&spidx;
! 3428:
! 3429: /* make inbound policy */
! 3430: iph2->src = dst;
! 3431: iph2->dst = src;
! 3432: spidx.dir = IPSEC_DIR_INBOUND;
! 3433: spidx.ul_proto = 0;
! 3434:
! 3435: /*
! 3436: * Note: code from get_proposal_r
! 3437: */
! 3438:
! 3439: #define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
! 3440:
! 3441: /*
! 3442: * make destination address in spidx from either ID payload
! 3443: * or phase 1 address into a address in spidx.
! 3444: */
! 3445: if (iph2->id != NULL
! 3446: && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
! 3447: || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
! 3448: || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
! 3449: || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
! 3450: /* get a destination address of a policy */
! 3451: error = ipsecdoi_id2sockaddr(iph2->id,
! 3452: (struct sockaddr *)&spidx.dst,
! 3453: &spidx.prefd, &spidx.ul_proto);
! 3454: if (error)
! 3455: goto purge;
! 3456:
! 3457: #ifdef INET6
! 3458: /*
! 3459: * get scopeid from the SA address.
! 3460: * note that the phase 1 source address is used as
! 3461: * a destination address to search for a inbound
! 3462: * policy entry because rcoon is responder.
! 3463: */
! 3464: if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
! 3465: if ((error =
! 3466: setscopeid((struct sockaddr *)&spidx.dst,
! 3467: iph2->src)) != 0)
! 3468: goto purge;
! 3469: }
! 3470: #endif
! 3471:
! 3472: if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
! 3473: || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
! 3474: idi2type = _XIDT(iph2->id);
! 3475:
! 3476: } else {
! 3477:
! 3478: plog(LLV_DEBUG, LOCATION, NULL,
! 3479: "get a destination address of SP index "
! 3480: "from phase1 address "
! 3481: "due to no ID payloads found "
! 3482: "OR because ID type is not address.\n");
! 3483:
! 3484: /*
! 3485: * copy the SOURCE address of IKE into the
! 3486: * DESTINATION address of the key to search the
! 3487: * SPD because the direction of policy is inbound.
! 3488: */
! 3489: memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
! 3490: switch (spidx.dst.ss_family) {
! 3491: case AF_INET:
! 3492: spidx.prefd =
! 3493: sizeof(struct in_addr) << 3;
! 3494: break;
! 3495: #ifdef INET6
! 3496: case AF_INET6:
! 3497: spidx.prefd =
! 3498: sizeof(struct in6_addr) << 3;
! 3499: break;
! 3500: #endif
! 3501: default:
! 3502: spidx.prefd = 0;
! 3503: break;
! 3504: }
! 3505: }
! 3506:
! 3507: /* make source address in spidx */
! 3508: if (iph2->id_p != NULL
! 3509: && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
! 3510: || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
! 3511: || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
! 3512: || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
! 3513: /* get a source address of inbound SA */
! 3514: error = ipsecdoi_id2sockaddr(iph2->id_p,
! 3515: (struct sockaddr *)&spidx.src,
! 3516: &spidx.prefs, &spidx.ul_proto);
! 3517: if (error)
! 3518: goto purge;
! 3519:
! 3520: #ifdef INET6
! 3521: /*
! 3522: * get scopeid from the SA address.
! 3523: * for more detail, see above of this function.
! 3524: */
! 3525: if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
! 3526: error =
! 3527: setscopeid((struct sockaddr *)&spidx.src,
! 3528: iph2->dst);
! 3529: if (error)
! 3530: goto purge;
! 3531: }
! 3532: #endif
! 3533:
! 3534: /* make sa_[src,dst] if both ID types are IP address and same */
! 3535: if (_XIDT(iph2->id_p) == idi2type
! 3536: && spidx.dst.ss_family == spidx.src.ss_family) {
! 3537: iph2->sa_src =
! 3538: dupsaddr((struct sockaddr *)&spidx.dst);
! 3539: if (iph2->sa_src == NULL) {
! 3540: plog(LLV_ERROR, LOCATION, NULL,
! 3541: "allocation failed\n");
! 3542: goto purge;
! 3543: }
! 3544: iph2->sa_dst =
! 3545: dupsaddr((struct sockaddr *)&spidx.src);
! 3546: if (iph2->sa_dst == NULL) {
! 3547: plog(LLV_ERROR, LOCATION, NULL,
! 3548: "allocation failed\n");
! 3549: goto purge;
! 3550: }
! 3551: }
! 3552:
! 3553: } else {
! 3554: plog(LLV_DEBUG, LOCATION, NULL,
! 3555: "get a source address of SP index "
! 3556: "from phase1 address "
! 3557: "due to no ID payloads found "
! 3558: "OR because ID type is not address.\n");
! 3559:
! 3560: /* see above comment. */
! 3561: memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
! 3562: switch (spidx.src.ss_family) {
! 3563: case AF_INET:
! 3564: spidx.prefs =
! 3565: sizeof(struct in_addr) << 3;
! 3566: break;
! 3567: #ifdef INET6
! 3568: case AF_INET6:
! 3569: spidx.prefs =
! 3570: sizeof(struct in6_addr) << 3;
! 3571: break;
! 3572: #endif
! 3573: default:
! 3574: spidx.prefs = 0;
! 3575: break;
! 3576: }
! 3577: }
! 3578:
! 3579: #undef _XIDT
! 3580:
! 3581: plog(LLV_DEBUG, LOCATION, NULL,
! 3582: "get a src address from ID payload "
! 3583: "%s prefixlen=%u ul_proto=%u\n",
! 3584: saddr2str((struct sockaddr *)&spidx.src),
! 3585: spidx.prefs, spidx.ul_proto);
! 3586: plog(LLV_DEBUG, LOCATION, NULL,
! 3587: "get dst address from ID payload "
! 3588: "%s prefixlen=%u ul_proto=%u\n",
! 3589: saddr2str((struct sockaddr *)&spidx.dst),
! 3590: spidx.prefd, spidx.ul_proto);
! 3591:
! 3592: /*
! 3593: * convert the ul_proto if it is 0
! 3594: * because 0 in ID payload means a wild card.
! 3595: */
! 3596: if (spidx.ul_proto == 0)
! 3597: spidx.ul_proto = IPSEC_ULPROTO_ANY;
! 3598:
! 3599: #undef _XIDT
! 3600:
! 3601: /* Check if the generated SPD has the same timestamp as the SA.
! 3602: * If timestamps are different, this means that the SPD entry has been
! 3603: * refreshed by another SA, and should NOT be deleted with the current SA.
! 3604: */
! 3605: if( created ){
! 3606: struct secpolicy *p;
! 3607:
! 3608: p = getsp(&spidx);
! 3609: if(p != NULL){
! 3610: /* just do no test if p is NULL, because this probably just means
! 3611: * that the policy has already be deleted for some reason.
! 3612: */
! 3613: if(p->spidx.created != created)
! 3614: goto purge;
! 3615: }
! 3616: }
! 3617:
! 3618: /* End of code from get_proposal_r
! 3619: */
! 3620:
! 3621: if (pk_sendspddelete(iph2) < 0) {
! 3622: plog(LLV_ERROR, LOCATION, NULL,
! 3623: "pfkey spddelete(inbound) failed.\n");
! 3624: }else{
! 3625: plog(LLV_DEBUG, LOCATION, NULL,
! 3626: "pfkey spddelete(inbound) sent.\n");
! 3627: }
! 3628:
! 3629: #ifdef HAVE_POLICY_FWD
! 3630: /* make forward policy if required */
! 3631: if (tunnel_mode_prop(iph2->approval)) {
! 3632: spidx.dir = IPSEC_DIR_FWD;
! 3633: if (pk_sendspddelete(iph2) < 0) {
! 3634: plog(LLV_ERROR, LOCATION, NULL,
! 3635: "pfkey spddelete(forward) failed.\n");
! 3636: }else{
! 3637: plog(LLV_DEBUG, LOCATION, NULL,
! 3638: "pfkey spddelete(forward) sent.\n");
! 3639: }
! 3640: }
! 3641: #endif
! 3642:
! 3643: /* make outbound policy */
! 3644: iph2->src = src;
! 3645: iph2->dst = dst;
! 3646: spidx.dir = IPSEC_DIR_OUTBOUND;
! 3647: addr = spidx.src;
! 3648: spidx.src = spidx.dst;
! 3649: spidx.dst = addr;
! 3650: pref = spidx.prefs;
! 3651: spidx.prefs = spidx.prefd;
! 3652: spidx.prefd = pref;
! 3653:
! 3654: if (pk_sendspddelete(iph2) < 0) {
! 3655: plog(LLV_ERROR, LOCATION, NULL,
! 3656: "pfkey spddelete(outbound) failed.\n");
! 3657: }else{
! 3658: plog(LLV_DEBUG, LOCATION, NULL,
! 3659: "pfkey spddelete(outbound) sent.\n");
! 3660: }
! 3661: purge:
! 3662: iph2->spidx_gen=NULL;
! 3663: }
! 3664:
! 3665:
! 3666: #ifdef INET6
! 3667: u_int32_t
! 3668: setscopeid(sp_addr0, sa_addr0)
! 3669: struct sockaddr *sp_addr0, *sa_addr0;
! 3670: {
! 3671: struct sockaddr_in6 *sp_addr, *sa_addr;
! 3672:
! 3673: sp_addr = (struct sockaddr_in6 *)sp_addr0;
! 3674: sa_addr = (struct sockaddr_in6 *)sa_addr0;
! 3675:
! 3676: if (!IN6_IS_ADDR_LINKLOCAL(&sp_addr->sin6_addr)
! 3677: && !IN6_IS_ADDR_SITELOCAL(&sp_addr->sin6_addr)
! 3678: && !IN6_IS_ADDR_MULTICAST(&sp_addr->sin6_addr))
! 3679: return 0;
! 3680:
! 3681: /* this check should not be here ? */
! 3682: if (sa_addr->sin6_family != AF_INET6) {
! 3683: plog(LLV_ERROR, LOCATION, NULL,
! 3684: "can't get scope ID: family mismatch\n");
! 3685: return -1;
! 3686: }
! 3687:
! 3688: if (!IN6_IS_ADDR_LINKLOCAL(&sa_addr->sin6_addr)) {
! 3689: plog(LLV_ERROR, LOCATION, NULL,
! 3690: "scope ID is not supported except of lladdr.\n");
! 3691: return -1;
! 3692: }
! 3693:
! 3694: sp_addr->sin6_scope_id = sa_addr->sin6_scope_id;
! 3695:
! 3696: return 0;
! 3697: }
! 3698: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>