Annotation of embedaddon/ipsec-tools/src/racoon/pfkey.c, revision 1.1
1.1 ! misho 1: /* $NetBSD: pfkey.c,v 1.57 2011/03/15 13:20:14 vanhu Exp $ */
! 2:
! 3: /* $Id: pfkey.c,v 1.57 2011/03/15 13:20:14 vanhu Exp $ */
! 4:
! 5: /*
! 6: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. Neither the name of the project nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: #include "config.h"
! 35:
! 36: #include <stdlib.h>
! 37: #include <string.h>
! 38: #include <stdio.h>
! 39: #include <netdb.h>
! 40: #include <errno.h>
! 41: #ifdef HAVE_UNISTD_H
! 42: #include <unistd.h>
! 43: #endif
! 44: #include <netdb.h>
! 45: #include <netinet/in.h>
! 46: #include <arpa/inet.h>
! 47:
! 48: #ifdef ENABLE_NATT
! 49: # ifdef __linux__
! 50: # include <linux/udp.h>
! 51: # endif
! 52: # if defined(__NetBSD__) || defined(__FreeBSD__) || \
! 53: (defined(__APPLE__) && defined(__MACH__))
! 54: # include <netinet/udp.h>
! 55: # endif
! 56: #endif
! 57:
! 58: #include <sys/types.h>
! 59: #include <sys/param.h>
! 60: #include <sys/socket.h>
! 61: #include <sys/queue.h>
! 62: #include <sys/sysctl.h>
! 63:
! 64: #include <net/route.h>
! 65: #include <net/pfkeyv2.h>
! 66:
! 67: #include <netinet/in.h>
! 68: #include PATH_IPSEC_H
! 69: #include <fcntl.h>
! 70:
! 71: #include "libpfkey.h"
! 72:
! 73: #include "var.h"
! 74: #include "misc.h"
! 75: #include "vmbuf.h"
! 76: #include "plog.h"
! 77: #include "sockmisc.h"
! 78: #include "session.h"
! 79: #include "debug.h"
! 80:
! 81: #include "schedule.h"
! 82: #include "localconf.h"
! 83: #include "remoteconf.h"
! 84: #include "handler.h"
! 85: #include "policy.h"
! 86: #include "proposal.h"
! 87: #include "isakmp_var.h"
! 88: #include "isakmp.h"
! 89: #include "isakmp_inf.h"
! 90: #include "ipsec_doi.h"
! 91: #include "oakley.h"
! 92: #include "pfkey.h"
! 93: #include "algorithm.h"
! 94: #include "sainfo.h"
! 95: #include "admin.h"
! 96: #include "evt.h"
! 97: #include "privsep.h"
! 98: #include "strnames.h"
! 99: #include "backupsa.h"
! 100: #include "gcmalloc.h"
! 101: #include "nattraversal.h"
! 102: #include "crypto_openssl.h"
! 103: #include "grabmyaddr.h"
! 104:
! 105: #if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
! 106: #define SADB_X_EALG_AESCBC SADB_X_EALG_RIJNDAELCBC
! 107: #endif
! 108:
! 109: /* prototype */
! 110: static u_int ipsecdoi2pfkey_aalg __P((u_int));
! 111: static u_int ipsecdoi2pfkey_ealg __P((u_int));
! 112: static u_int ipsecdoi2pfkey_calg __P((u_int));
! 113: static u_int ipsecdoi2pfkey_alg __P((u_int, u_int));
! 114: static u_int keylen_aalg __P((u_int));
! 115: static u_int keylen_ealg __P((u_int, int));
! 116:
! 117: static int pk_recvgetspi __P((caddr_t *));
! 118: static int pk_recvupdate __P((caddr_t *));
! 119: static int pk_recvadd __P((caddr_t *));
! 120: static int pk_recvdelete __P((caddr_t *));
! 121: static int pk_recvacquire __P((caddr_t *));
! 122: static int pk_recvexpire __P((caddr_t *));
! 123: static int pk_recvflush __P((caddr_t *));
! 124: static int getsadbpolicy __P((caddr_t *, int *, int, struct ph2handle *));
! 125: static int pk_recvspdupdate __P((caddr_t *));
! 126: static int pk_recvspdadd __P((caddr_t *));
! 127: static int pk_recvspddelete __P((caddr_t *));
! 128: static int pk_recvspdexpire __P((caddr_t *));
! 129: static int pk_recvspdget __P((caddr_t *));
! 130: static int pk_recvspddump __P((caddr_t *));
! 131: static int pk_recvspdflush __P((caddr_t *));
! 132: #if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
! 133: static int pk_recvmigrate __P((caddr_t *));
! 134: #endif
! 135: static struct sadb_msg *pk_recv __P((int, int *));
! 136:
! 137: static int (*pkrecvf[]) __P((caddr_t *)) = {
! 138: NULL,
! 139: pk_recvgetspi,
! 140: pk_recvupdate,
! 141: pk_recvadd,
! 142: pk_recvdelete,
! 143: NULL, /* SADB_GET */
! 144: pk_recvacquire,
! 145: NULL, /* SABD_REGISTER */
! 146: pk_recvexpire,
! 147: pk_recvflush,
! 148: NULL, /* SADB_DUMP */
! 149: NULL, /* SADB_X_PROMISC */
! 150: NULL, /* SADB_X_PCHANGE */
! 151: pk_recvspdupdate,
! 152: pk_recvspdadd,
! 153: pk_recvspddelete,
! 154: pk_recvspdget,
! 155: NULL, /* SADB_X_SPDACQUIRE */
! 156: pk_recvspddump,
! 157: pk_recvspdflush,
! 158: NULL, /* SADB_X_SPDSETIDX */
! 159: pk_recvspdexpire,
! 160: NULL, /* SADB_X_SPDDELETE2 */
! 161: NULL, /* SADB_X_NAT_T_NEW_MAPPING */
! 162: #if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
! 163: pk_recvmigrate,
! 164: #else
! 165: NULL, /* SADB_X_MIGRATE */
! 166: #endif
! 167: #if (SADB_MAX > 24)
! 168: #error "SADB extra message?"
! 169: #endif
! 170: };
! 171:
! 172: static int addnewsp __P((caddr_t *, struct sockaddr *, struct sockaddr *));
! 173:
! 174: /* cope with old kame headers - ugly */
! 175: #ifndef SADB_X_AALG_MD5
! 176: #define SADB_X_AALG_MD5 SADB_AALG_MD5
! 177: #endif
! 178: #ifndef SADB_X_AALG_SHA
! 179: #define SADB_X_AALG_SHA SADB_AALG_SHA
! 180: #endif
! 181: #ifndef SADB_X_AALG_NULL
! 182: #define SADB_X_AALG_NULL SADB_AALG_NULL
! 183: #endif
! 184:
! 185: #ifndef SADB_X_EALG_BLOWFISHCBC
! 186: #define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC
! 187: #endif
! 188: #ifndef SADB_X_EALG_CAST128CBC
! 189: #define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC
! 190: #endif
! 191: #ifndef SADB_X_EALG_RC5CBC
! 192: #ifdef SADB_EALG_RC5CBC
! 193: #define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC
! 194: #endif
! 195: #endif
! 196:
! 197: /*
! 198: * PF_KEY packet handler
! 199: * 0: success
! 200: * -1: fail
! 201: */
! 202: static int
! 203: pfkey_handler(ctx, fd)
! 204: void *ctx;
! 205: int fd;
! 206: {
! 207: struct sadb_msg *msg;
! 208: int len;
! 209: caddr_t mhp[SADB_EXT_MAX + 1];
! 210: int error = -1;
! 211:
! 212: /* receive pfkey message. */
! 213: len = 0;
! 214: msg = (struct sadb_msg *) pk_recv(fd, &len);
! 215: if (msg == NULL) {
! 216: if (len < 0) {
! 217: /* do not report EAGAIN as error; well get
! 218: * called from main loop later. and it's normal
! 219: * when spd dump is received during reload and
! 220: * this function is called in loop. */
! 221: if (errno == EAGAIN)
! 222: goto end;
! 223:
! 224: plog(LLV_ERROR, LOCATION, NULL,
! 225: "failed to recv from pfkey (%s)\n",
! 226: strerror(errno));
! 227: goto end;
! 228: } else {
! 229: /* short message - msg not ready */
! 230: return 0;
! 231: }
! 232: }
! 233:
! 234: plog(LLV_DEBUG, LOCATION, NULL, "got pfkey %s message\n",
! 235: s_pfkey_type(msg->sadb_msg_type));
! 236: plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3);
! 237:
! 238: /* validity check */
! 239: if (msg->sadb_msg_errno) {
! 240: int pri;
! 241:
! 242: /* when SPD is empty, treat the state as no error. */
! 243: if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
! 244: msg->sadb_msg_errno == ENOENT)
! 245: pri = LLV_DEBUG;
! 246: else
! 247: pri = LLV_ERROR;
! 248:
! 249: plog(pri, LOCATION, NULL,
! 250: "pfkey %s failed: %s\n",
! 251: s_pfkey_type(msg->sadb_msg_type),
! 252: strerror(msg->sadb_msg_errno));
! 253:
! 254: goto end;
! 255: }
! 256:
! 257: /* check pfkey message. */
! 258: if (pfkey_align(msg, mhp)) {
! 259: plog(LLV_ERROR, LOCATION, NULL,
! 260: "libipsec failed pfkey align (%s)\n",
! 261: ipsec_strerror());
! 262: goto end;
! 263: }
! 264: if (pfkey_check(mhp)) {
! 265: plog(LLV_ERROR, LOCATION, NULL,
! 266: "libipsec failed pfkey check (%s)\n",
! 267: ipsec_strerror());
! 268: goto end;
! 269: }
! 270: msg = (struct sadb_msg *)mhp[0];
! 271:
! 272: /* safety check */
! 273: if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
! 274: plog(LLV_ERROR, LOCATION, NULL,
! 275: "unknown PF_KEY message type=%u\n",
! 276: msg->sadb_msg_type);
! 277: goto end;
! 278: }
! 279:
! 280: if (pkrecvf[msg->sadb_msg_type] == NULL) {
! 281: plog(LLV_INFO, LOCATION, NULL,
! 282: "unsupported PF_KEY message %s\n",
! 283: s_pfkey_type(msg->sadb_msg_type));
! 284: goto end;
! 285: }
! 286:
! 287: if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
! 288: goto end;
! 289:
! 290: error = 1;
! 291: end:
! 292: if (msg)
! 293: racoon_free(msg);
! 294: return(error);
! 295: }
! 296:
! 297: /*
! 298: * dump SADB
! 299: */
! 300: vchar_t *
! 301: pfkey_dump_sadb(satype)
! 302: int satype;
! 303: {
! 304: int s;
! 305: vchar_t *buf = NULL;
! 306: pid_t pid = getpid();
! 307: struct sadb_msg *msg = NULL;
! 308: size_t bl, ml;
! 309: int len;
! 310: int bufsiz;
! 311:
! 312: if ((s = privsep_socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
! 313: plog(LLV_ERROR, LOCATION, NULL,
! 314: "libipsec failed pfkey open: %s\n",
! 315: ipsec_strerror());
! 316: return NULL;
! 317: }
! 318:
! 319: if ((bufsiz = pfkey_set_buffer_size(s, lcconf->pfkey_buffer_size)) < 0) {
! 320: plog(LLV_ERROR, LOCATION, NULL,
! 321: "libipsec failed pfkey set buffer size to %d: %s\n",
! 322: lcconf->pfkey_buffer_size, ipsec_strerror());
! 323: return NULL;
! 324: } else if (bufsiz < lcconf->pfkey_buffer_size) {
! 325: plog(LLV_WARNING, LOCATION, NULL,
! 326: "pfkey socket receive buffer set to %dKB, instead of %d\n",
! 327: bufsiz, lcconf->pfkey_buffer_size);
! 328: }
! 329:
! 330: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n");
! 331: if (pfkey_send_dump(s, satype) < 0) {
! 332: plog(LLV_ERROR, LOCATION, NULL,
! 333: "libipsec failed dump: %s\n", ipsec_strerror());
! 334: goto fail;
! 335: }
! 336:
! 337: while (1) {
! 338: if (msg)
! 339: racoon_free(msg);
! 340: msg = pk_recv(s, &len);
! 341: if (msg == NULL) {
! 342: if (len < 0)
! 343: goto done;
! 344: else
! 345: continue;
! 346: }
! 347:
! 348: if (msg->sadb_msg_type != SADB_DUMP || msg->sadb_msg_pid != pid)
! 349: {
! 350: plog(LLV_DEBUG, LOCATION, NULL,
! 351: "discarding non-sadb dump msg %p, our pid=%i\n", msg, pid);
! 352: plog(LLV_DEBUG, LOCATION, NULL,
! 353: "type %i, pid %i\n", msg->sadb_msg_type, msg->sadb_msg_pid);
! 354: continue;
! 355: }
! 356:
! 357:
! 358: ml = msg->sadb_msg_len << 3;
! 359: bl = buf ? buf->l : 0;
! 360: buf = vrealloc(buf, bl + ml);
! 361: if (buf == NULL) {
! 362: plog(LLV_ERROR, LOCATION, NULL,
! 363: "failed to reallocate buffer to dump.\n");
! 364: goto fail;
! 365: }
! 366: memcpy(buf->v + bl, msg, ml);
! 367:
! 368: if (msg->sadb_msg_seq == 0)
! 369: break;
! 370: }
! 371: goto done;
! 372:
! 373: fail:
! 374: if (buf)
! 375: vfree(buf);
! 376: buf = NULL;
! 377: done:
! 378: if (msg)
! 379: racoon_free(msg);
! 380: close(s);
! 381: return buf;
! 382: }
! 383:
! 384: #ifdef ENABLE_ADMINPORT
! 385: /*
! 386: * flush SADB
! 387: */
! 388: void
! 389: pfkey_flush_sadb(proto)
! 390: u_int proto;
! 391: {
! 392: int satype;
! 393:
! 394: /* convert to SADB_SATYPE */
! 395: if ((satype = admin2pfkey_proto(proto)) < 0)
! 396: return;
! 397:
! 398: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_flush\n");
! 399: if (pfkey_send_flush(lcconf->sock_pfkey, satype) < 0) {
! 400: plog(LLV_ERROR, LOCATION, NULL,
! 401: "libipsec failed send flush (%s)\n", ipsec_strerror());
! 402: return;
! 403: }
! 404:
! 405: return;
! 406: }
! 407: #endif
! 408:
! 409: /*
! 410: * These are the SATYPEs that we manage. We register to get
! 411: * PF_KEY messages related to these SATYPEs, and we also use
! 412: * this list to determine which SATYPEs to delete SAs for when
! 413: * we receive an INITIAL-CONTACT.
! 414: */
! 415: const struct pfkey_satype pfkey_satypes[] = {
! 416: { SADB_SATYPE_AH, "AH" },
! 417: { SADB_SATYPE_ESP, "ESP" },
! 418: { SADB_X_SATYPE_IPCOMP, "IPCOMP" },
! 419: };
! 420: const int pfkey_nsatypes =
! 421: sizeof(pfkey_satypes) / sizeof(pfkey_satypes[0]);
! 422:
! 423: /*
! 424: * PF_KEY initialization
! 425: */
! 426: int
! 427: pfkey_init()
! 428: {
! 429: int i, reg_fail;
! 430: int bufsiz;
! 431:
! 432: if ((lcconf->sock_pfkey = pfkey_open()) < 0) {
! 433: plog(LLV_ERROR, LOCATION, NULL,
! 434: "libipsec failed pfkey open (%s)\n", ipsec_strerror());
! 435: return -1;
! 436: }
! 437: if ((bufsiz = pfkey_set_buffer_size(lcconf->sock_pfkey,
! 438: lcconf->pfkey_buffer_size)) < 0) {
! 439: plog(LLV_ERROR, LOCATION, NULL,
! 440: "libipsec failed to set pfkey buffer size to %d (%s)\n",
! 441: lcconf->pfkey_buffer_size, ipsec_strerror());
! 442: return -1;
! 443: } else if (bufsiz < lcconf->pfkey_buffer_size) {
! 444: plog(LLV_WARNING, LOCATION, NULL,
! 445: "pfkey socket receive buffer set to %dKB, instead of %d\n",
! 446: bufsiz, lcconf->pfkey_buffer_size);
! 447: }
! 448:
! 449: if (fcntl(lcconf->sock_pfkey, F_SETFL, O_NONBLOCK) == -1)
! 450: plog(LLV_WARNING, LOCATION, NULL,
! 451: "failed to set the pfkey socket to NONBLOCK\n");
! 452:
! 453: for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
! 454: plog(LLV_DEBUG, LOCATION, NULL,
! 455: "call pfkey_send_register for %s\n",
! 456: pfkey_satypes[i].ps_name);
! 457: if (pfkey_send_register(lcconf->sock_pfkey,
! 458: pfkey_satypes[i].ps_satype) < 0 ||
! 459: pfkey_recv_register(lcconf->sock_pfkey) < 0) {
! 460: plog(LLV_WARNING, LOCATION, NULL,
! 461: "failed to register %s (%s)\n",
! 462: pfkey_satypes[i].ps_name,
! 463: ipsec_strerror());
! 464: reg_fail++;
! 465: }
! 466: }
! 467:
! 468: if (reg_fail == pfkey_nsatypes) {
! 469: plog(LLV_ERROR, LOCATION, NULL,
! 470: "failed to regist any protocol.\n");
! 471: pfkey_close(lcconf->sock_pfkey);
! 472: return -1;
! 473: }
! 474:
! 475: initsp();
! 476:
! 477: if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
! 478: plog(LLV_ERROR, LOCATION, NULL,
! 479: "libipsec sending spddump failed: %s\n",
! 480: ipsec_strerror());
! 481: pfkey_close(lcconf->sock_pfkey);
! 482: return -1;
! 483: }
! 484: #if 0
! 485: if (pfkey_promisc_toggle(1) < 0) {
! 486: pfkey_close(lcconf->sock_pfkey);
! 487: return -1;
! 488: }
! 489: #endif
! 490: monitor_fd(lcconf->sock_pfkey, pfkey_handler, NULL, 0);
! 491: return 0;
! 492: }
! 493:
! 494: int
! 495: pfkey_reload()
! 496: {
! 497: flushsp();
! 498:
! 499: if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
! 500: plog(LLV_ERROR, LOCATION, NULL,
! 501: "libipsec sending spddump failed: %s\n",
! 502: ipsec_strerror());
! 503: return -1;
! 504: }
! 505:
! 506: while (pfkey_handler(NULL, lcconf->sock_pfkey) > 0)
! 507: continue;
! 508:
! 509: return 0;
! 510: }
! 511:
! 512: /* %%% for conversion */
! 513: /* IPSECDOI_ATTR_AUTH -> SADB_AALG */
! 514: static u_int
! 515: ipsecdoi2pfkey_aalg(hashtype)
! 516: u_int hashtype;
! 517: {
! 518: switch (hashtype) {
! 519: case IPSECDOI_ATTR_AUTH_HMAC_MD5:
! 520: return SADB_AALG_MD5HMAC;
! 521: case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
! 522: return SADB_AALG_SHA1HMAC;
! 523: case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
! 524: #if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
! 525: return SADB_X_AALG_SHA2_256;
! 526: #else
! 527: return SADB_X_AALG_SHA2_256HMAC;
! 528: #endif
! 529: case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
! 530: #if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
! 531: return SADB_X_AALG_SHA2_384;
! 532: #else
! 533: return SADB_X_AALG_SHA2_384HMAC;
! 534: #endif
! 535: case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
! 536: #if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
! 537: return SADB_X_AALG_SHA2_512;
! 538: #else
! 539: return SADB_X_AALG_SHA2_512HMAC;
! 540: #endif
! 541: case IPSECDOI_ATTR_AUTH_KPDK: /* need special care */
! 542: return SADB_AALG_NONE;
! 543:
! 544: /* not supported */
! 545: case IPSECDOI_ATTR_AUTH_DES_MAC:
! 546: plog(LLV_ERROR, LOCATION, NULL,
! 547: "Not supported hash type: %u\n", hashtype);
! 548: return ~0;
! 549:
! 550: case 0: /* reserved */
! 551: default:
! 552: return SADB_AALG_NONE;
! 553:
! 554: plog(LLV_ERROR, LOCATION, NULL,
! 555: "Invalid hash type: %u\n", hashtype);
! 556: return ~0;
! 557: }
! 558: /*NOTREACHED*/
! 559: }
! 560:
! 561: /* IPSECDOI_ESP -> SADB_EALG */
! 562: static u_int
! 563: ipsecdoi2pfkey_ealg(t_id)
! 564: u_int t_id;
! 565: {
! 566: switch (t_id) {
! 567: case IPSECDOI_ESP_DES_IV64: /* sa_flags |= SADB_X_EXT_OLD */
! 568: return SADB_EALG_DESCBC;
! 569: case IPSECDOI_ESP_DES:
! 570: return SADB_EALG_DESCBC;
! 571: case IPSECDOI_ESP_3DES:
! 572: return SADB_EALG_3DESCBC;
! 573: #ifdef SADB_X_EALG_RC5CBC
! 574: case IPSECDOI_ESP_RC5:
! 575: return SADB_X_EALG_RC5CBC;
! 576: #endif
! 577: case IPSECDOI_ESP_CAST:
! 578: return SADB_X_EALG_CAST128CBC;
! 579: case IPSECDOI_ESP_BLOWFISH:
! 580: return SADB_X_EALG_BLOWFISHCBC;
! 581: case IPSECDOI_ESP_DES_IV32: /* flags |= (SADB_X_EXT_OLD|
! 582: SADB_X_EXT_IV4B)*/
! 583: return SADB_EALG_DESCBC;
! 584: case IPSECDOI_ESP_NULL:
! 585: return SADB_EALG_NULL;
! 586: #ifdef SADB_X_EALG_AESCBC
! 587: case IPSECDOI_ESP_AES:
! 588: return SADB_X_EALG_AESCBC;
! 589: #endif
! 590: #ifdef SADB_X_EALG_TWOFISHCBC
! 591: case IPSECDOI_ESP_TWOFISH:
! 592: return SADB_X_EALG_TWOFISHCBC;
! 593: #endif
! 594: #ifdef SADB_X_EALG_CAMELLIACBC
! 595: case IPSECDOI_ESP_CAMELLIA:
! 596: return SADB_X_EALG_CAMELLIACBC;
! 597: #endif
! 598:
! 599: /* not supported */
! 600: case IPSECDOI_ESP_3IDEA:
! 601: case IPSECDOI_ESP_IDEA:
! 602: case IPSECDOI_ESP_RC4:
! 603: plog(LLV_ERROR, LOCATION, NULL,
! 604: "Not supported transform: %u\n", t_id);
! 605: return ~0;
! 606:
! 607: case 0: /* reserved */
! 608: default:
! 609: plog(LLV_ERROR, LOCATION, NULL,
! 610: "Invalid transform id: %u\n", t_id);
! 611: return ~0;
! 612: }
! 613: /*NOTREACHED*/
! 614: }
! 615:
! 616: /* IPCOMP -> SADB_CALG */
! 617: static u_int
! 618: ipsecdoi2pfkey_calg(t_id)
! 619: u_int t_id;
! 620: {
! 621: switch (t_id) {
! 622: case IPSECDOI_IPCOMP_OUI:
! 623: return SADB_X_CALG_OUI;
! 624: case IPSECDOI_IPCOMP_DEFLATE:
! 625: return SADB_X_CALG_DEFLATE;
! 626: case IPSECDOI_IPCOMP_LZS:
! 627: return SADB_X_CALG_LZS;
! 628:
! 629: case 0: /* reserved */
! 630: default:
! 631: plog(LLV_ERROR, LOCATION, NULL,
! 632: "Invalid transform id: %u\n", t_id);
! 633: return ~0;
! 634: }
! 635: /*NOTREACHED*/
! 636: }
! 637:
! 638: /* IPSECDOI_PROTO -> SADB_SATYPE */
! 639: u_int
! 640: ipsecdoi2pfkey_proto(proto)
! 641: u_int proto;
! 642: {
! 643: switch (proto) {
! 644: case IPSECDOI_PROTO_IPSEC_AH:
! 645: return SADB_SATYPE_AH;
! 646: case IPSECDOI_PROTO_IPSEC_ESP:
! 647: return SADB_SATYPE_ESP;
! 648: case IPSECDOI_PROTO_IPCOMP:
! 649: return SADB_X_SATYPE_IPCOMP;
! 650:
! 651: default:
! 652: plog(LLV_ERROR, LOCATION, NULL,
! 653: "Invalid ipsec_doi proto: %u\n", proto);
! 654: return ~0;
! 655: }
! 656: /*NOTREACHED*/
! 657: }
! 658:
! 659: static u_int
! 660: ipsecdoi2pfkey_alg(algclass, type)
! 661: u_int algclass, type;
! 662: {
! 663: switch (algclass) {
! 664: case IPSECDOI_ATTR_AUTH:
! 665: return ipsecdoi2pfkey_aalg(type);
! 666: case IPSECDOI_PROTO_IPSEC_ESP:
! 667: return ipsecdoi2pfkey_ealg(type);
! 668: case IPSECDOI_PROTO_IPCOMP:
! 669: return ipsecdoi2pfkey_calg(type);
! 670: default:
! 671: plog(LLV_ERROR, LOCATION, NULL,
! 672: "Invalid ipsec_doi algclass: %u\n", algclass);
! 673: return ~0;
! 674: }
! 675: /*NOTREACHED*/
! 676: }
! 677:
! 678: /* SADB_SATYPE -> IPSECDOI_PROTO */
! 679: u_int
! 680: pfkey2ipsecdoi_proto(satype)
! 681: u_int satype;
! 682: {
! 683: switch (satype) {
! 684: case SADB_SATYPE_AH:
! 685: return IPSECDOI_PROTO_IPSEC_AH;
! 686: case SADB_SATYPE_ESP:
! 687: return IPSECDOI_PROTO_IPSEC_ESP;
! 688: case SADB_X_SATYPE_IPCOMP:
! 689: return IPSECDOI_PROTO_IPCOMP;
! 690:
! 691: default:
! 692: plog(LLV_ERROR, LOCATION, NULL,
! 693: "Invalid pfkey proto: %u\n", satype);
! 694: return ~0;
! 695: }
! 696: /*NOTREACHED*/
! 697: }
! 698:
! 699: /* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
! 700: u_int
! 701: ipsecdoi2pfkey_mode(mode)
! 702: u_int mode;
! 703: {
! 704: switch (mode) {
! 705: case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
! 706: #ifdef ENABLE_NATT
! 707: case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
! 708: case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
! 709: #endif
! 710: return IPSEC_MODE_TUNNEL;
! 711: case IPSECDOI_ATTR_ENC_MODE_TRNS:
! 712: #ifdef ENABLE_NATT
! 713: case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
! 714: case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
! 715: #endif
! 716: return IPSEC_MODE_TRANSPORT;
! 717: default:
! 718: plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
! 719: return ~0;
! 720: }
! 721: /*NOTREACHED*/
! 722: }
! 723:
! 724: /* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
! 725: u_int
! 726: pfkey2ipsecdoi_mode(mode)
! 727: u_int mode;
! 728: {
! 729: switch (mode) {
! 730: case IPSEC_MODE_TUNNEL:
! 731: return IPSECDOI_ATTR_ENC_MODE_TUNNEL;
! 732: case IPSEC_MODE_TRANSPORT:
! 733: return IPSECDOI_ATTR_ENC_MODE_TRNS;
! 734: case IPSEC_MODE_ANY:
! 735: return IPSECDOI_ATTR_ENC_MODE_ANY;
! 736: default:
! 737: plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
! 738: return ~0;
! 739: }
! 740: /*NOTREACHED*/
! 741: }
! 742:
! 743: /* default key length for encryption algorithm */
! 744: static u_int
! 745: keylen_aalg(hashtype)
! 746: u_int hashtype;
! 747: {
! 748: int res;
! 749:
! 750: if (hashtype == 0)
! 751: return SADB_AALG_NONE;
! 752:
! 753: res = alg_ipsec_hmacdef_hashlen(hashtype);
! 754: if (res == -1) {
! 755: plog(LLV_ERROR, LOCATION, NULL,
! 756: "invalid hmac algorithm %u.\n", hashtype);
! 757: return ~0;
! 758: }
! 759: return res;
! 760: }
! 761:
! 762: /* default key length for encryption algorithm */
! 763: static u_int
! 764: keylen_ealg(enctype, encklen)
! 765: u_int enctype;
! 766: int encklen;
! 767: {
! 768: int res;
! 769:
! 770: res = alg_ipsec_encdef_keylen(enctype, encklen);
! 771: if (res == -1) {
! 772: plog(LLV_ERROR, LOCATION, NULL,
! 773: "invalid encryption algorithm %u.\n", enctype);
! 774: return ~0;
! 775: }
! 776: return res;
! 777: }
! 778:
! 779: void
! 780: pk_fixup_sa_addresses(mhp)
! 781: caddr_t *mhp;
! 782: {
! 783: struct sockaddr *src, *dst;
! 784:
! 785: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 786: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 787: set_port(src, PORT_ISAKMP);
! 788: set_port(dst, PORT_ISAKMP);
! 789:
! 790: #ifdef ENABLE_NATT
! 791: if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
! 792: /* NAT-T is enabled for this SADB entry; copy
! 793: * the ports from NAT-T extensions */
! 794: if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL)
! 795: set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
! 796: if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
! 797: set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
! 798: }
! 799: #endif
! 800: }
! 801:
! 802: int
! 803: pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
! 804: e_type, e_keylen, a_type, a_keylen, flags)
! 805: u_int proto_id;
! 806: u_int t_id;
! 807: u_int hashtype;
! 808: u_int *e_type;
! 809: u_int *e_keylen;
! 810: u_int *a_type;
! 811: u_int *a_keylen;
! 812: u_int *flags;
! 813: {
! 814: *flags = 0;
! 815: switch (proto_id) {
! 816: case IPSECDOI_PROTO_IPSEC_ESP:
! 817: if ((*e_type = ipsecdoi2pfkey_ealg(t_id)) == ~0)
! 818: goto bad;
! 819: if ((*e_keylen = keylen_ealg(t_id, *e_keylen)) == ~0)
! 820: goto bad;
! 821: *e_keylen >>= 3;
! 822:
! 823: if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
! 824: goto bad;
! 825: if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
! 826: goto bad;
! 827: *a_keylen >>= 3;
! 828:
! 829: if (*e_type == SADB_EALG_NONE) {
! 830: plog(LLV_ERROR, LOCATION, NULL, "no ESP algorithm.\n");
! 831: goto bad;
! 832: }
! 833: break;
! 834:
! 835: case IPSECDOI_PROTO_IPSEC_AH:
! 836: if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
! 837: goto bad;
! 838: if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
! 839: goto bad;
! 840: *a_keylen >>= 3;
! 841:
! 842: if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
! 843: && hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
! 844: /* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
! 845: *a_type = SADB_X_AALG_MD5;
! 846: *flags |= SADB_X_EXT_OLD;
! 847: }
! 848: *e_type = SADB_EALG_NONE;
! 849: *e_keylen = 0;
! 850: if (*a_type == SADB_AALG_NONE) {
! 851: plog(LLV_ERROR, LOCATION, NULL, "no AH algorithm.\n");
! 852: goto bad;
! 853: }
! 854: break;
! 855:
! 856: case IPSECDOI_PROTO_IPCOMP:
! 857: if ((*e_type = ipsecdoi2pfkey_calg(t_id)) == ~0)
! 858: goto bad;
! 859: *e_keylen = 0;
! 860:
! 861: *flags = SADB_X_EXT_RAWCPI;
! 862:
! 863: *a_type = SADB_AALG_NONE;
! 864: *a_keylen = 0;
! 865: if (*e_type == SADB_X_CALG_NONE) {
! 866: plog(LLV_ERROR, LOCATION, NULL, "no IPCOMP algorithm.\n");
! 867: goto bad;
! 868: }
! 869: break;
! 870:
! 871: default:
! 872: plog(LLV_ERROR, LOCATION, NULL, "unknown IPsec protocol.\n");
! 873: goto bad;
! 874: }
! 875:
! 876: return 0;
! 877:
! 878: bad:
! 879: errno = EINVAL;
! 880: return -1;
! 881: }
! 882:
! 883: /*%%%*/
! 884: /* send getspi message per ipsec protocol per remote address */
! 885: /*
! 886: * the local address and remote address in ph1handle are dealed
! 887: * with destination address and source address respectively.
! 888: * Because SPI is decided by responder.
! 889: */
! 890: int
! 891: pk_sendgetspi(iph2)
! 892: struct ph2handle *iph2;
! 893: {
! 894: struct sockaddr *src = NULL, *dst = NULL;
! 895: u_int satype, mode;
! 896: struct saprop *pp;
! 897: struct saproto *pr;
! 898: u_int32_t minspi, maxspi;
! 899: u_int8_t natt_type = 0;
! 900: u_int16_t sport = 0, dport = 0;
! 901:
! 902: if (iph2->side == INITIATOR)
! 903: pp = iph2->proposal;
! 904: else
! 905: pp = iph2->approval;
! 906:
! 907: if (iph2->sa_src && iph2->sa_dst) {
! 908: /* MIPv6: Use SA addresses, not IKE ones */
! 909: src = dupsaddr(iph2->sa_src);
! 910: dst = dupsaddr(iph2->sa_dst);
! 911: } else {
! 912: /* Common case: SA addresses and IKE ones are the same */
! 913: src = dupsaddr(iph2->src);
! 914: dst = dupsaddr(iph2->dst);
! 915: }
! 916:
! 917: if (src == NULL || dst == NULL) {
! 918: racoon_free(src);
! 919: racoon_free(dst);
! 920: return -1;
! 921: }
! 922:
! 923: for (pr = pp->head; pr != NULL; pr = pr->next) {
! 924:
! 925: /* validity check */
! 926: satype = ipsecdoi2pfkey_proto(pr->proto_id);
! 927: if (satype == ~0) {
! 928: plog(LLV_ERROR, LOCATION, NULL,
! 929: "invalid proto_id %d\n", pr->proto_id);
! 930: racoon_free(src);
! 931: racoon_free(dst);
! 932: return -1;
! 933: }
! 934: /* this works around a bug in Linux kernel where it allocates 4 byte
! 935: spi's for IPCOMP */
! 936: else if (satype == SADB_X_SATYPE_IPCOMP) {
! 937: minspi = 0x100;
! 938: maxspi = 0xffff;
! 939: }
! 940: else {
! 941: minspi = 0;
! 942: maxspi = 0;
! 943: }
! 944: mode = ipsecdoi2pfkey_mode(pr->encmode);
! 945: if (mode == ~0) {
! 946: plog(LLV_ERROR, LOCATION, NULL,
! 947: "invalid encmode %d\n", pr->encmode);
! 948: racoon_free(src);
! 949: racoon_free(dst);
! 950: return -1;
! 951: }
! 952:
! 953: #ifdef ENABLE_NATT
! 954: if (pr->udp_encap) {
! 955: natt_type = iph2->ph1->natt_options->encaps_type;
! 956: sport=extract_port(src);
! 957: dport=extract_port(dst);
! 958: }
! 959: #endif
! 960:
! 961: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
! 962: if (pfkey_send_getspi_nat(
! 963: lcconf->sock_pfkey,
! 964: satype,
! 965: mode,
! 966: dst, /* src of SA */
! 967: src, /* dst of SA */
! 968: natt_type,
! 969: dport,
! 970: sport,
! 971: minspi, maxspi,
! 972: pr->reqid_in, iph2->seq) < 0) {
! 973: plog(LLV_ERROR, LOCATION, NULL,
! 974: "ipseclib failed send getspi (%s)\n",
! 975: ipsec_strerror());
! 976: racoon_free(src);
! 977: racoon_free(dst);
! 978: return -1;
! 979: }
! 980: plog(LLV_DEBUG, LOCATION, NULL,
! 981: "pfkey GETSPI sent: %s\n",
! 982: sadbsecas2str(dst, src, satype, 0, mode));
! 983: }
! 984:
! 985: racoon_free(src);
! 986: racoon_free(dst);
! 987: return 0;
! 988: }
! 989:
! 990: /*
! 991: * receive GETSPI from kernel.
! 992: */
! 993: static int
! 994: pk_recvgetspi(mhp)
! 995: caddr_t *mhp;
! 996: {
! 997: struct sadb_msg *msg;
! 998: struct sadb_sa *sa;
! 999: struct ph2handle *iph2;
! 1000: struct sockaddr *src, *dst;
! 1001: int proto_id;
! 1002: int allspiok, notfound;
! 1003: struct saprop *pp;
! 1004: struct saproto *pr;
! 1005:
! 1006: /* validity check */
! 1007: if (mhp[SADB_EXT_SA] == NULL
! 1008: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 1009: || mhp[SADB_EXT_ADDRESS_SRC] == NULL) {
! 1010: plog(LLV_ERROR, LOCATION, NULL,
! 1011: "inappropriate sadb getspi message passed.\n");
! 1012: return -1;
! 1013: }
! 1014: msg = (struct sadb_msg *)mhp[0];
! 1015: sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
! 1016: pk_fixup_sa_addresses(mhp);
! 1017: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
! 1018: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 1019:
! 1020: /* the message has to be processed or not ? */
! 1021: if (msg->sadb_msg_pid != getpid()) {
! 1022: plog(LLV_DEBUG, LOCATION, NULL,
! 1023: "%s message is not interesting "
! 1024: "because pid %d is not mine.\n",
! 1025: s_pfkey_type(msg->sadb_msg_type),
! 1026: msg->sadb_msg_pid);
! 1027: return -1;
! 1028: }
! 1029:
! 1030: iph2 = getph2byseq(msg->sadb_msg_seq);
! 1031: if (iph2 == NULL) {
! 1032: plog(LLV_DEBUG, LOCATION, NULL,
! 1033: "seq %d of %s message not interesting.\n",
! 1034: msg->sadb_msg_seq,
! 1035: s_pfkey_type(msg->sadb_msg_type));
! 1036: return -1;
! 1037: }
! 1038:
! 1039: if (iph2->status != PHASE2ST_GETSPISENT) {
! 1040: plog(LLV_ERROR, LOCATION, NULL,
! 1041: "status mismatch (db:%d msg:%d)\n",
! 1042: iph2->status, PHASE2ST_GETSPISENT);
! 1043: return -1;
! 1044: }
! 1045:
! 1046: /* set SPI, and check to get all spi whether or not */
! 1047: allspiok = 1;
! 1048: notfound = 1;
! 1049: proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
! 1050: pp = iph2->side == INITIATOR ? iph2->proposal : iph2->approval;
! 1051:
! 1052: for (pr = pp->head; pr != NULL; pr = pr->next) {
! 1053: if (pr->proto_id == proto_id && pr->spi == 0) {
! 1054: pr->spi = sa->sadb_sa_spi;
! 1055: notfound = 0;
! 1056: plog(LLV_DEBUG, LOCATION, NULL,
! 1057: "pfkey GETSPI succeeded: %s\n",
! 1058: sadbsecas2str(dst, src,
! 1059: msg->sadb_msg_satype,
! 1060: sa->sadb_sa_spi,
! 1061: ipsecdoi2pfkey_mode(pr->encmode)));
! 1062: }
! 1063: if (pr->spi == 0)
! 1064: allspiok = 0; /* not get all spi */
! 1065: }
! 1066:
! 1067: if (notfound) {
! 1068: plog(LLV_ERROR, LOCATION, NULL,
! 1069: "get spi for unknown address %s\n",
! 1070: saddrwop2str(dst));
! 1071: return -1;
! 1072: }
! 1073:
! 1074: if (allspiok) {
! 1075: /* update status */
! 1076: iph2->status = PHASE2ST_GETSPIDONE;
! 1077: if (isakmp_post_getspi(iph2) < 0) {
! 1078: plog(LLV_ERROR, LOCATION, NULL,
! 1079: "failed to start post getspi.\n");
! 1080: remph2(iph2);
! 1081: delph2(iph2);
! 1082: iph2 = NULL;
! 1083: return -1;
! 1084: }
! 1085: }
! 1086:
! 1087: return 0;
! 1088: }
! 1089:
! 1090: /*
! 1091: * set inbound SA
! 1092: */
! 1093: int
! 1094: pk_sendupdate(iph2)
! 1095: struct ph2handle *iph2;
! 1096: {
! 1097: struct saproto *pr;
! 1098: struct pfkey_send_sa_args sa_args;
! 1099:
! 1100: /* sanity check */
! 1101: if (iph2->approval == NULL) {
! 1102: plog(LLV_ERROR, LOCATION, NULL,
! 1103: "no approvaled SAs found.\n");
! 1104: return -1;
! 1105: }
! 1106:
! 1107: /* fill in some needed for pfkey_send_update2 */
! 1108: memset (&sa_args, 0, sizeof (sa_args));
! 1109: sa_args.so = lcconf->sock_pfkey;
! 1110: if (iph2->lifetime_secs)
! 1111: sa_args.l_addtime = iph2->lifetime_secs;
! 1112: else
! 1113: sa_args.l_addtime = iph2->approval->lifetime;
! 1114: sa_args.seq = iph2->seq;
! 1115: sa_args.wsize = 4;
! 1116:
! 1117: if (iph2->sa_src && iph2->sa_dst) {
! 1118: /* MIPv6: Use SA addresses, not IKE ones */
! 1119: sa_args.dst = dupsaddr(iph2->sa_src);
! 1120: sa_args.src = dupsaddr(iph2->sa_dst);
! 1121: } else {
! 1122: /* Common case: SA addresses and IKE ones are the same */
! 1123: sa_args.dst = dupsaddr(iph2->src);
! 1124: sa_args.src = dupsaddr(iph2->dst);
! 1125: }
! 1126:
! 1127: if (sa_args.src == NULL || sa_args.dst == NULL) {
! 1128: racoon_free(sa_args.src);
! 1129: racoon_free(sa_args.dst);
! 1130: return -1;
! 1131: }
! 1132:
! 1133: for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
! 1134: /* validity check */
! 1135: sa_args.satype = ipsecdoi2pfkey_proto(pr->proto_id);
! 1136: if (sa_args.satype == ~0) {
! 1137: plog(LLV_ERROR, LOCATION, NULL,
! 1138: "invalid proto_id %d\n", pr->proto_id);
! 1139: racoon_free(sa_args.src);
! 1140: racoon_free(sa_args.dst);
! 1141: return -1;
! 1142: }
! 1143: else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
! 1144: /* IPCOMP has no replay window */
! 1145: sa_args.wsize = 0;
! 1146: }
! 1147: #ifdef ENABLE_SAMODE_UNSPECIFIED
! 1148: sa_args.mode = IPSEC_MODE_ANY;
! 1149: #else
! 1150: sa_args.mode = ipsecdoi2pfkey_mode(pr->encmode);
! 1151: if (sa_args.mode == ~0) {
! 1152: plog(LLV_ERROR, LOCATION, NULL,
! 1153: "invalid encmode %d\n", pr->encmode);
! 1154: racoon_free(sa_args.src);
! 1155: racoon_free(sa_args.dst);
! 1156: return -1;
! 1157: }
! 1158: #endif
! 1159: /* set algorithm type and key length */
! 1160: sa_args.e_keylen = pr->head->encklen;
! 1161: if (pfkey_convertfromipsecdoi(
! 1162: pr->proto_id,
! 1163: pr->head->trns_id,
! 1164: pr->head->authtype,
! 1165: &sa_args.e_type, &sa_args.e_keylen,
! 1166: &sa_args.a_type, &sa_args.a_keylen,
! 1167: &sa_args.flags) < 0){
! 1168: racoon_free(sa_args.src);
! 1169: racoon_free(sa_args.dst);
! 1170: return -1;
! 1171: }
! 1172:
! 1173: #if 0
! 1174: sa_args.l_bytes = iph2->approval->lifebyte * 1024,
! 1175: #else
! 1176: sa_args.l_bytes = 0;
! 1177: #endif
! 1178:
! 1179: #ifdef HAVE_SECCTX
! 1180: if (*iph2->approval->sctx.ctx_str) {
! 1181: sa_args.ctxdoi = iph2->approval->sctx.ctx_doi;
! 1182: sa_args.ctxalg = iph2->approval->sctx.ctx_alg;
! 1183: sa_args.ctxstrlen = iph2->approval->sctx.ctx_strlen;
! 1184: sa_args.ctxstr = iph2->approval->sctx.ctx_str;
! 1185: }
! 1186: #endif /* HAVE_SECCTX */
! 1187:
! 1188: #ifdef ENABLE_NATT
! 1189: if (pr->udp_encap) {
! 1190: sa_args.l_natt_type = iph2->ph1->natt_options->encaps_type;
! 1191: sa_args.l_natt_sport = extract_port(iph2->ph1->remote);
! 1192: sa_args.l_natt_dport = extract_port(iph2->ph1->local);
! 1193: sa_args.l_natt_oa = iph2->natoa_src;
! 1194: #ifdef SADB_X_EXT_NAT_T_FRAG
! 1195: sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
! 1196: #endif
! 1197: }
! 1198: #endif
! 1199:
! 1200: /* more info to fill in */
! 1201: sa_args.spi = pr->spi;
! 1202: sa_args.reqid = pr->reqid_in;
! 1203: sa_args.keymat = pr->keymat->v;
! 1204:
! 1205: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update2\n");
! 1206: if (pfkey_send_update2(&sa_args) < 0) {
! 1207: plog(LLV_ERROR, LOCATION, NULL,
! 1208: "libipsec failed send update (%s)\n",
! 1209: ipsec_strerror());
! 1210: racoon_free(sa_args.src);
! 1211: racoon_free(sa_args.dst);
! 1212: return -1;
! 1213: }
! 1214:
! 1215: if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
! 1216: continue;
! 1217:
! 1218: /*
! 1219: * It maybe good idea to call backupsa_to_file() after
! 1220: * racoon will receive the sadb_update messages.
! 1221: * But it is impossible because there is not key in the
! 1222: * information from the kernel.
! 1223: */
! 1224:
! 1225: /* change some things before backing up */
! 1226: sa_args.wsize = 4;
! 1227: sa_args.l_bytes = iph2->approval->lifebyte * 1024;
! 1228:
! 1229: if (backupsa_to_file(&sa_args) < 0) {
! 1230: plog(LLV_ERROR, LOCATION, NULL,
! 1231: "backuped SA failed: %s\n",
! 1232: sadbsecas2str(sa_args.src, sa_args.dst,
! 1233: sa_args.satype, sa_args.spi, sa_args.mode));
! 1234: }
! 1235: plog(LLV_DEBUG, LOCATION, NULL,
! 1236: "backuped SA: %s\n",
! 1237: sadbsecas2str(sa_args.src, sa_args.dst,
! 1238: sa_args.satype, sa_args.spi, sa_args.mode));
! 1239: }
! 1240:
! 1241: racoon_free(sa_args.src);
! 1242: racoon_free(sa_args.dst);
! 1243: return 0;
! 1244: }
! 1245:
! 1246: static int
! 1247: pk_recvupdate(mhp)
! 1248: caddr_t *mhp;
! 1249: {
! 1250: struct sadb_msg *msg;
! 1251: struct sadb_sa *sa;
! 1252: struct sockaddr *src, *dst;
! 1253: struct ph2handle *iph2;
! 1254: u_int proto_id, encmode, sa_mode;
! 1255: int incomplete = 0;
! 1256: struct saproto *pr;
! 1257:
! 1258: /* ignore this message because of local test mode. */
! 1259: if (f_local)
! 1260: return 0;
! 1261:
! 1262: /* sanity check */
! 1263: if (mhp[0] == NULL
! 1264: || mhp[SADB_EXT_SA] == NULL
! 1265: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 1266: || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
! 1267: plog(LLV_ERROR, LOCATION, NULL,
! 1268: "inappropriate sadb update message passed.\n");
! 1269: return -1;
! 1270: }
! 1271: msg = (struct sadb_msg *)mhp[0];
! 1272: pk_fixup_sa_addresses(mhp);
! 1273: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 1274: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 1275: sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
! 1276:
! 1277: sa_mode = mhp[SADB_X_EXT_SA2] == NULL
! 1278: ? IPSEC_MODE_ANY
! 1279: : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
! 1280:
! 1281: /* the message has to be processed or not ? */
! 1282: if (msg->sadb_msg_pid != getpid()) {
! 1283: plog(LLV_DEBUG, LOCATION, NULL,
! 1284: "%s message is not interesting "
! 1285: "because pid %d is not mine.\n",
! 1286: s_pfkey_type(msg->sadb_msg_type),
! 1287: msg->sadb_msg_pid);
! 1288: return -1;
! 1289: }
! 1290:
! 1291: iph2 = getph2byseq(msg->sadb_msg_seq);
! 1292: if (iph2 == NULL) {
! 1293: plog(LLV_DEBUG, LOCATION, NULL,
! 1294: "seq %d of %s message not interesting.\n",
! 1295: msg->sadb_msg_seq,
! 1296: s_pfkey_type(msg->sadb_msg_type));
! 1297: return -1;
! 1298: }
! 1299:
! 1300: if (iph2->status != PHASE2ST_ADDSA) {
! 1301: plog(LLV_ERROR, LOCATION, NULL,
! 1302: "status mismatch (db:%d msg:%d)\n",
! 1303: iph2->status, PHASE2ST_ADDSA);
! 1304: return -1;
! 1305: }
! 1306:
! 1307: /* check to complete all keys ? */
! 1308: for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
! 1309: proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
! 1310: if (proto_id == ~0) {
! 1311: plog(LLV_ERROR, LOCATION, NULL,
! 1312: "invalid proto_id %d\n", msg->sadb_msg_satype);
! 1313: return -1;
! 1314: }
! 1315: encmode = pfkey2ipsecdoi_mode(sa_mode);
! 1316: if (encmode == ~0) {
! 1317: plog(LLV_ERROR, LOCATION, NULL,
! 1318: "invalid encmode %d\n", sa_mode);
! 1319: return -1;
! 1320: }
! 1321:
! 1322: if (pr->proto_id == proto_id
! 1323: && pr->spi == sa->sadb_sa_spi) {
! 1324: pr->ok = 1;
! 1325: plog(LLV_DEBUG, LOCATION, NULL,
! 1326: "pfkey UPDATE succeeded: %s\n",
! 1327: sadbsecas2str(dst, src,
! 1328: msg->sadb_msg_satype,
! 1329: sa->sadb_sa_spi,
! 1330: sa_mode));
! 1331:
! 1332: plog(LLV_INFO, LOCATION, NULL,
! 1333: "IPsec-SA established: %s\n",
! 1334: sadbsecas2str(dst, src,
! 1335: msg->sadb_msg_satype, sa->sadb_sa_spi,
! 1336: sa_mode));
! 1337: }
! 1338:
! 1339: if (pr->ok == 0)
! 1340: incomplete = 1;
! 1341: }
! 1342:
! 1343: if (incomplete)
! 1344: return 0;
! 1345:
! 1346: /* turn off the timer for calling pfkey_timeover() */
! 1347: sched_cancel(&iph2->sce);
! 1348:
! 1349: /* update status */
! 1350: iph2->status = PHASE2ST_ESTABLISHED;
! 1351: evt_phase2(iph2, EVT_PHASE2_UP, NULL);
! 1352:
! 1353: #ifdef ENABLE_STATS
! 1354: gettimeofday(&iph2->end, NULL);
! 1355: syslog(LOG_NOTICE, "%s(%s): %8.6f",
! 1356: "phase2", "quick", timedelta(&iph2->start, &iph2->end));
! 1357: #endif
! 1358:
! 1359: /* turn off schedule */
! 1360: sched_cancel(&iph2->scr);
! 1361:
! 1362: /*
! 1363: * since we are going to reuse the phase2 handler, we need to
! 1364: * remain it and refresh all the references between ph1 and ph2 to use.
! 1365: */
! 1366: sched_schedule(&iph2->sce, iph2->approval->lifetime,
! 1367: isakmp_ph2expire_stub);
! 1368:
! 1369: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1370: return 0;
! 1371: }
! 1372:
! 1373: /*
! 1374: * set outbound SA
! 1375: */
! 1376: int
! 1377: pk_sendadd(iph2)
! 1378: struct ph2handle *iph2;
! 1379: {
! 1380: struct saproto *pr;
! 1381: struct pfkey_send_sa_args sa_args;
! 1382:
! 1383: /* sanity check */
! 1384: if (iph2->approval == NULL) {
! 1385: plog(LLV_ERROR, LOCATION, NULL,
! 1386: "no approvaled SAs found.\n");
! 1387: return -1;
! 1388: }
! 1389:
! 1390: /* fill in some needed for pfkey_send_update2 */
! 1391: memset (&sa_args, 0, sizeof (sa_args));
! 1392: sa_args.so = lcconf->sock_pfkey;
! 1393: if (iph2->lifetime_secs)
! 1394: sa_args.l_addtime = iph2->lifetime_secs;
! 1395: else
! 1396: sa_args.l_addtime = iph2->approval->lifetime;
! 1397: sa_args.seq = iph2->seq;
! 1398: sa_args.wsize = 4;
! 1399:
! 1400: if (iph2->sa_src && iph2->sa_dst) {
! 1401: /* MIPv6: Use SA addresses, not IKE ones */
! 1402: sa_args.src = dupsaddr(iph2->sa_src);
! 1403: sa_args.dst = dupsaddr(iph2->sa_dst);
! 1404: } else {
! 1405: /* Common case: SA addresses and IKE ones are the same */
! 1406: sa_args.src = dupsaddr(iph2->src);
! 1407: sa_args.dst = dupsaddr(iph2->dst);
! 1408: }
! 1409:
! 1410: if (sa_args.src == NULL || sa_args.dst == NULL) {
! 1411: racoon_free(sa_args.src);
! 1412: racoon_free(sa_args.dst);
! 1413: return -1;
! 1414: }
! 1415:
! 1416: for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
! 1417: /* validity check */
! 1418: sa_args.satype = ipsecdoi2pfkey_proto(pr->proto_id);
! 1419: if (sa_args.satype == ~0) {
! 1420: plog(LLV_ERROR, LOCATION, NULL,
! 1421: "invalid proto_id %d\n", pr->proto_id);
! 1422: racoon_free(sa_args.src);
! 1423: racoon_free(sa_args.dst);
! 1424: return -1;
! 1425: }
! 1426: else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
! 1427: /* no replay window for IPCOMP */
! 1428: sa_args.wsize = 0;
! 1429: }
! 1430: #ifdef ENABLE_SAMODE_UNSPECIFIED
! 1431: sa_args.mode = IPSEC_MODE_ANY;
! 1432: #else
! 1433: sa_args.mode = ipsecdoi2pfkey_mode(pr->encmode);
! 1434: if (sa_args.mode == ~0) {
! 1435: plog(LLV_ERROR, LOCATION, NULL,
! 1436: "invalid encmode %d\n", pr->encmode);
! 1437: racoon_free(sa_args.src);
! 1438: racoon_free(sa_args.dst);
! 1439: return -1;
! 1440: }
! 1441: #endif
! 1442:
! 1443: /* set algorithm type and key length */
! 1444: sa_args.e_keylen = pr->head->encklen;
! 1445: if (pfkey_convertfromipsecdoi(
! 1446: pr->proto_id,
! 1447: pr->head->trns_id,
! 1448: pr->head->authtype,
! 1449: &sa_args.e_type, &sa_args.e_keylen,
! 1450: &sa_args.a_type, &sa_args.a_keylen,
! 1451: &sa_args.flags) < 0){
! 1452: racoon_free(sa_args.src);
! 1453: racoon_free(sa_args.dst);
! 1454: return -1;
! 1455: }
! 1456:
! 1457: #if 0
! 1458: sa_args.l_bytes = iph2->approval->lifebyte * 1024,
! 1459: #else
! 1460: sa_args.l_bytes = 0;
! 1461: #endif
! 1462:
! 1463: #ifdef HAVE_SECCTX
! 1464: if (*iph2->approval->sctx.ctx_str) {
! 1465: sa_args.ctxdoi = iph2->approval->sctx.ctx_doi;
! 1466: sa_args.ctxalg = iph2->approval->sctx.ctx_alg;
! 1467: sa_args.ctxstrlen = iph2->approval->sctx.ctx_strlen;
! 1468: sa_args.ctxstr = iph2->approval->sctx.ctx_str;
! 1469: }
! 1470: #endif /* HAVE_SECCTX */
! 1471:
! 1472: #ifdef ENABLE_NATT
! 1473: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add2 "
! 1474: "(NAT flavor)\n");
! 1475:
! 1476: if (pr->udp_encap) {
! 1477: sa_args.l_natt_type = UDP_ENCAP_ESPINUDP;
! 1478: sa_args.l_natt_sport = extract_port(iph2->ph1->local);
! 1479: sa_args.l_natt_dport = extract_port(iph2->ph1->remote);
! 1480: sa_args.l_natt_oa = iph2->natoa_dst;
! 1481: #ifdef SADB_X_EXT_NAT_T_FRAG
! 1482: sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
! 1483: #endif
! 1484: }
! 1485: #endif
! 1486: /* more info to fill in */
! 1487: sa_args.spi = pr->spi_p;
! 1488: sa_args.reqid = pr->reqid_out;
! 1489: sa_args.keymat = pr->keymat_p->v;
! 1490:
! 1491: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add2\n");
! 1492: if (pfkey_send_add2(&sa_args) < 0) {
! 1493: plog(LLV_ERROR, LOCATION, NULL,
! 1494: "libipsec failed send add (%s)\n",
! 1495: ipsec_strerror());
! 1496: racoon_free(sa_args.src);
! 1497: racoon_free(sa_args.dst);
! 1498: return -1;
! 1499: }
! 1500:
! 1501: if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
! 1502: continue;
! 1503:
! 1504: /*
! 1505: * It maybe good idea to call backupsa_to_file() after
! 1506: * racoon will receive the sadb_update messages.
! 1507: * But it is impossible because there is not key in the
! 1508: * information from the kernel.
! 1509: */
! 1510: if (backupsa_to_file(&sa_args) < 0) {
! 1511: plog(LLV_ERROR, LOCATION, NULL,
! 1512: "backuped SA failed: %s\n",
! 1513: sadbsecas2str(sa_args.src, sa_args.dst,
! 1514: sa_args.satype, sa_args.spi, sa_args.mode));
! 1515: }
! 1516: plog(LLV_DEBUG, LOCATION, NULL,
! 1517: "backuped SA: %s\n",
! 1518: sadbsecas2str(sa_args.src, sa_args.dst,
! 1519: sa_args.satype, sa_args.spi, sa_args.mode));
! 1520: }
! 1521: racoon_free(sa_args.src);
! 1522: racoon_free(sa_args.dst);
! 1523: return 0;
! 1524: }
! 1525:
! 1526: static int
! 1527: pk_recvadd(mhp)
! 1528: caddr_t *mhp;
! 1529: {
! 1530: struct sadb_msg *msg;
! 1531: struct sadb_sa *sa;
! 1532: struct sockaddr *src, *dst;
! 1533: struct ph2handle *iph2;
! 1534: u_int sa_mode;
! 1535:
! 1536: /* ignore this message because of local test mode. */
! 1537: if (f_local)
! 1538: return 0;
! 1539:
! 1540: /* sanity check */
! 1541: if (mhp[0] == NULL
! 1542: || mhp[SADB_EXT_SA] == NULL
! 1543: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 1544: || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
! 1545: plog(LLV_ERROR, LOCATION, NULL,
! 1546: "inappropriate sadb add message passed.\n");
! 1547: return -1;
! 1548: }
! 1549: msg = (struct sadb_msg *)mhp[0];
! 1550: pk_fixup_sa_addresses(mhp);
! 1551: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 1552: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 1553: sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
! 1554:
! 1555: sa_mode = mhp[SADB_X_EXT_SA2] == NULL
! 1556: ? IPSEC_MODE_ANY
! 1557: : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
! 1558:
! 1559: /* the message has to be processed or not ? */
! 1560: if (msg->sadb_msg_pid != getpid()) {
! 1561: plog(LLV_DEBUG, LOCATION, NULL,
! 1562: "%s message is not interesting "
! 1563: "because pid %d is not mine.\n",
! 1564: s_pfkey_type(msg->sadb_msg_type),
! 1565: msg->sadb_msg_pid);
! 1566: return -1;
! 1567: }
! 1568:
! 1569: iph2 = getph2byseq(msg->sadb_msg_seq);
! 1570: if (iph2 == NULL) {
! 1571: plog(LLV_DEBUG, LOCATION, NULL,
! 1572: "seq %d of %s message not interesting.\n",
! 1573: msg->sadb_msg_seq,
! 1574: s_pfkey_type(msg->sadb_msg_type));
! 1575: return -1;
! 1576: }
! 1577:
! 1578: /*
! 1579: * NOTE don't update any status of phase2 handle
! 1580: * because they must be updated by SADB_UPDATE message
! 1581: */
! 1582:
! 1583: plog(LLV_INFO, LOCATION, NULL,
! 1584: "IPsec-SA established: %s\n",
! 1585: sadbsecas2str(src, dst,
! 1586: msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
! 1587:
! 1588: plog(LLV_DEBUG, LOCATION, NULL, "===\n");
! 1589: return 0;
! 1590: }
! 1591:
! 1592: static int
! 1593: pk_recvexpire(mhp)
! 1594: caddr_t *mhp;
! 1595: {
! 1596: struct sadb_msg *msg;
! 1597: struct sadb_sa *sa;
! 1598: struct sockaddr *src, *dst;
! 1599: struct ph2handle *iph2;
! 1600: u_int proto_id, sa_mode;
! 1601:
! 1602: /* sanity check */
! 1603: if (mhp[0] == NULL
! 1604: || mhp[SADB_EXT_SA] == NULL
! 1605: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 1606: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 1607: || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
! 1608: && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
! 1609: plog(LLV_ERROR, LOCATION, NULL,
! 1610: "inappropriate sadb expire message passed.\n");
! 1611: return -1;
! 1612: }
! 1613: msg = (struct sadb_msg *)mhp[0];
! 1614: sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
! 1615: pk_fixup_sa_addresses(mhp);
! 1616: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 1617: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 1618:
! 1619: sa_mode = mhp[SADB_X_EXT_SA2] == NULL
! 1620: ? IPSEC_MODE_ANY
! 1621: : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
! 1622:
! 1623: proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
! 1624: if (proto_id == ~0) {
! 1625: plog(LLV_ERROR, LOCATION, NULL,
! 1626: "invalid proto_id %d\n", msg->sadb_msg_satype);
! 1627: return -1;
! 1628: }
! 1629:
! 1630: plog(LLV_INFO, LOCATION, NULL,
! 1631: "IPsec-SA expired: %s\n",
! 1632: sadbsecas2str(src, dst,
! 1633: msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
! 1634:
! 1635: iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
! 1636: if (iph2 == NULL) {
! 1637: /*
! 1638: * Ignore it because two expire messages are come up.
! 1639: * phase2 handler has been deleted already when 2nd message
! 1640: * is received.
! 1641: */
! 1642: plog(LLV_DEBUG, LOCATION, NULL,
! 1643: "no such a SA found: %s\n",
! 1644: sadbsecas2str(src, dst,
! 1645: msg->sadb_msg_satype, sa->sadb_sa_spi,
! 1646: sa_mode));
! 1647: return 0;
! 1648: }
! 1649:
! 1650: /* resent expiry message? */
! 1651: if (iph2->status > PHASE2ST_ESTABLISHED)
! 1652: return 0;
! 1653:
! 1654: /* still negotiating? */
! 1655: if (iph2->status < PHASE2ST_ESTABLISHED) {
! 1656: /* not a hard timeout? */
! 1657: if (mhp[SADB_EXT_LIFETIME_HARD] == NULL)
! 1658: return 0;
! 1659:
! 1660: /*
! 1661: * We were negotiating for that SA (w/o much success
! 1662: * from current status) and kernel has decided our time
! 1663: * is over trying (xfrm_larval_drop controls that and
! 1664: * is enabled by default on Linux >= 2.6.28 kernels).
! 1665: */
! 1666: plog(LLV_WARNING, LOCATION, NULL,
! 1667: "PF_KEY EXPIRE message received from kernel for SA"
! 1668: " being negotiated. Stopping negotiation.\n");
! 1669: }
! 1670:
! 1671: /* turn off the timer for calling isakmp_ph2expire() */
! 1672: sched_cancel(&iph2->sce);
! 1673:
! 1674: if (iph2->status == PHASE2ST_ESTABLISHED &&
! 1675: iph2->side == INITIATOR) {
! 1676: struct ph1handle *iph1hint;
! 1677: /*
! 1678: * Active phase 2 expired and we were initiator.
! 1679: * Begin new phase 2 exchange, so we can keep on sending
! 1680: * traffic.
! 1681: */
! 1682:
! 1683: /* update status for re-use */
! 1684: iph1hint = iph2->ph1;
! 1685: initph2(iph2);
! 1686: iph2->status = PHASE2ST_STATUS2;
! 1687:
! 1688: /* start quick exchange */
! 1689: if (isakmp_post_acquire(iph2, iph1hint, FALSE) < 0) {
! 1690: plog(LLV_ERROR, LOCATION, iph2->dst,
! 1691: "failed to begin ipsec sa "
! 1692: "re-negotication.\n");
! 1693: remph2(iph2);
! 1694: delph2(iph2);
! 1695: return -1;
! 1696: }
! 1697:
! 1698: return 0;
! 1699: }
! 1700:
! 1701: /*
! 1702: * We are responder or the phase 2 was not established.
! 1703: * Just remove the ph2handle to reflect SADB.
! 1704: */
! 1705: iph2->status = PHASE2ST_EXPIRED;
! 1706: remph2(iph2);
! 1707: delph2(iph2);
! 1708:
! 1709: return 0;
! 1710: }
! 1711:
! 1712: static int
! 1713: pk_recvacquire(mhp)
! 1714: caddr_t *mhp;
! 1715: {
! 1716: struct sadb_msg *msg;
! 1717: struct sadb_x_policy *xpl;
! 1718: struct secpolicy *sp_out = NULL, *sp_in = NULL;
! 1719: struct ph2handle *iph2;
! 1720: struct sockaddr *src, *dst; /* IKE addresses (for exchanges) */
! 1721: struct sockaddr *sp_src, *sp_dst; /* SP addresses (selectors). */
! 1722: struct sockaddr *sa_src = NULL, *sa_dst = NULL ; /* SA addresses */
! 1723: #ifdef HAVE_SECCTX
! 1724: struct sadb_x_sec_ctx *m_sec_ctx;
! 1725: #endif /* HAVE_SECCTX */
! 1726: struct policyindex spidx;
! 1727:
! 1728: /* ignore this message because of local test mode. */
! 1729: if (f_local)
! 1730: return 0;
! 1731:
! 1732: /* sanity check */
! 1733: if (mhp[0] == NULL
! 1734: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 1735: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 1736: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 1737: plog(LLV_ERROR, LOCATION, NULL,
! 1738: "inappropriate sadb acquire message passed.\n");
! 1739: return -1;
! 1740: }
! 1741: msg = (struct sadb_msg *)mhp[0];
! 1742: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 1743: /* acquire does not have nat-t ports; so do not bother setting
! 1744: * the default port 500; just use the port zero for wildcard
! 1745: * matching the get a valid natted destination */
! 1746: sp_src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 1747: sp_dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 1748:
! 1749: #ifdef HAVE_SECCTX
! 1750: m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 1751:
! 1752: if (m_sec_ctx != NULL) {
! 1753: plog(LLV_INFO, LOCATION, NULL, "security context doi: %u\n",
! 1754: m_sec_ctx->sadb_x_ctx_doi);
! 1755: plog(LLV_INFO, LOCATION, NULL,
! 1756: "security context algorithm: %u\n",
! 1757: m_sec_ctx->sadb_x_ctx_alg);
! 1758: plog(LLV_INFO, LOCATION, NULL, "security context length: %u\n",
! 1759: m_sec_ctx->sadb_x_ctx_len);
! 1760: plog(LLV_INFO, LOCATION, NULL, "security context: %s\n",
! 1761: ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)));
! 1762: }
! 1763: #endif /* HAVE_SECCTX */
! 1764:
! 1765: /* ignore if type is not IPSEC_POLICY_IPSEC */
! 1766: if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
! 1767: plog(LLV_DEBUG, LOCATION, NULL,
! 1768: "ignore ACQUIRE message. type is not IPsec.\n");
! 1769: return 0;
! 1770: }
! 1771:
! 1772: /* ignore it if src or dst are multicast addresses. */
! 1773: if ((sp_dst->sa_family == AF_INET
! 1774: && IN_MULTICAST(ntohl(((struct sockaddr_in *)sp_dst)->sin_addr.s_addr)))
! 1775: #ifdef INET6
! 1776: || (sp_dst->sa_family == AF_INET6
! 1777: && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sp_dst)->sin6_addr))
! 1778: #endif
! 1779: ) {
! 1780: plog(LLV_DEBUG, LOCATION, NULL,
! 1781: "ignore due to multicast destination address: %s.\n",
! 1782: saddrwop2str(sp_dst));
! 1783: return 0;
! 1784: }
! 1785:
! 1786: if ((sp_src->sa_family == AF_INET
! 1787: && IN_MULTICAST(ntohl(((struct sockaddr_in *)sp_src)->sin_addr.s_addr)))
! 1788: #ifdef INET6
! 1789: || (sp_src->sa_family == AF_INET6
! 1790: && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sp_src)->sin6_addr))
! 1791: #endif
! 1792: ) {
! 1793: plog(LLV_DEBUG, LOCATION, NULL,
! 1794: "ignore due to multicast source address: %s.\n",
! 1795: saddrwop2str(sp_src));
! 1796: return 0;
! 1797: }
! 1798:
! 1799: /* search for proper policyindex */
! 1800: sp_out = getspbyspid(xpl->sadb_x_policy_id);
! 1801: if (sp_out == NULL) {
! 1802: plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
! 1803: xpl->sadb_x_policy_id);
! 1804: return -1;
! 1805: }
! 1806: plog(LLV_DEBUG, LOCATION, NULL,
! 1807: "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
! 1808:
! 1809: /* Before going further, let first get the source and destination
! 1810: * address that would be used for IKE negotiation. The logic is:
! 1811: * - if SP from SPD image contains local and remote hints, we
! 1812: * use them (provided by MIGRATE).
! 1813: * - otherwise, we use the ones from the ipsecrequest, which means:
! 1814: * - the addresses from the request for transport mode
! 1815: * - the endpoints addresses for tunnel mode
! 1816: *
! 1817: * Note that:
! 1818: * 1) racoon does not support negotiation of bundles which
! 1819: * simplifies the lookup for the addresses in the ipsecrequest
! 1820: * list, as we expect only one.
! 1821: * 2) We do source and destination parts all together and do not
! 1822: * accept semi-defined information. This is just a decision,
! 1823: * there might be needs.
! 1824: *
! 1825: * --arno
! 1826: */
! 1827: if (sp_out->req && sp_out->req->saidx.mode == IPSEC_MODE_TUNNEL) {
! 1828: /* For Tunnel mode, SA addresses are the endpoints */
! 1829: src = (struct sockaddr *) &sp_out->req->saidx.src;
! 1830: dst = (struct sockaddr *) &sp_out->req->saidx.dst;
! 1831: } else {
! 1832: /* Otherwise use requested addresses.
! 1833: *
! 1834: * We need to explicitly setup sa_src and sa_dst too,
! 1835: * since the SA ports are different from IKE port. And
! 1836: * src/dst ports will be overwritten when the matching
! 1837: * phase1 is found. */
! 1838: src = sa_src = sp_src;
! 1839: dst = sa_dst = sp_dst;
! 1840: }
! 1841: if (sp_out->local && sp_out->remote) {
! 1842: /* hints available, let's use them */
! 1843: sa_src = src;
! 1844: sa_dst = dst;
! 1845: src = (struct sockaddr *) sp_out->local;
! 1846: dst = (struct sockaddr *) sp_out->remote;
! 1847: }
! 1848:
! 1849: /*
! 1850: * If there is a phase 2 handler against the policy identifier in
! 1851: * the acquire message, and if
! 1852: * 1. its state is less than PHASE2ST_ESTABLISHED, then racoon
! 1853: * should ignore such a acquire message because the phase 2
! 1854: * is just negotiating.
! 1855: * 2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
! 1856: * has to prcesss such a acquire message because racoon may
! 1857: * lost the expire message.
! 1858: */
! 1859: iph2 = getph2byid(src, dst, xpl->sadb_x_policy_id);
! 1860: if (iph2 != NULL) {
! 1861: if (iph2->status < PHASE2ST_ESTABLISHED) {
! 1862: plog(LLV_DEBUG, LOCATION, NULL,
! 1863: "ignore the acquire because ph2 found\n");
! 1864: return -1;
! 1865: }
! 1866: if (iph2->status == PHASE2ST_EXPIRED)
! 1867: iph2 = NULL;
! 1868: /*FALLTHROUGH*/
! 1869: }
! 1870:
! 1871: /* Check we are listening on source address. If not, ignore. */
! 1872: if (myaddr_getsport(src) == -1) {
! 1873: plog(LLV_DEBUG, LOCATION, NULL,
! 1874: "Not listening on source address %s. Ignoring ACQUIRE.\n",
! 1875: saddrwop2str(src));
! 1876: return 0;
! 1877: }
! 1878:
! 1879: /* get inbound policy */
! 1880: {
! 1881:
! 1882: memset(&spidx, 0, sizeof(spidx));
! 1883: spidx.dir = IPSEC_DIR_INBOUND;
! 1884: memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
! 1885: memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
! 1886: spidx.prefs = sp_out->spidx.prefd;
! 1887: spidx.prefd = sp_out->spidx.prefs;
! 1888: spidx.ul_proto = sp_out->spidx.ul_proto;
! 1889:
! 1890: #ifdef HAVE_SECCTX
! 1891: if (m_sec_ctx) {
! 1892: spidx.sec_ctx.ctx_doi = m_sec_ctx->sadb_x_ctx_doi;
! 1893: spidx.sec_ctx.ctx_alg = m_sec_ctx->sadb_x_ctx_alg;
! 1894: spidx.sec_ctx.ctx_strlen = m_sec_ctx->sadb_x_ctx_len;
! 1895: memcpy(spidx.sec_ctx.ctx_str,
! 1896: ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)),
! 1897: spidx.sec_ctx.ctx_strlen);
! 1898: }
! 1899: #endif /* HAVE_SECCTX */
! 1900:
! 1901: sp_in = getsp(&spidx);
! 1902: if (sp_in) {
! 1903: plog(LLV_DEBUG, LOCATION, NULL,
! 1904: "suitable inbound SP found: %s.\n",
! 1905: spidx2str(&sp_in->spidx));
! 1906: } else {
! 1907: plog(LLV_NOTIFY, LOCATION, NULL,
! 1908: "no in-bound policy found: %s\n",
! 1909: spidx2str(&spidx));
! 1910: }
! 1911: }
! 1912:
! 1913: /* allocate a phase 2 */
! 1914: iph2 = newph2();
! 1915: if (iph2 == NULL) {
! 1916: plog(LLV_ERROR, LOCATION, NULL,
! 1917: "failed to allocate phase2 entry.\n");
! 1918: return -1;
! 1919: }
! 1920: iph2->side = INITIATOR;
! 1921: iph2->spid = xpl->sadb_x_policy_id;
! 1922: iph2->satype = msg->sadb_msg_satype;
! 1923: iph2->seq = msg->sadb_msg_seq;
! 1924: iph2->status = PHASE2ST_STATUS2;
! 1925:
! 1926: /* set address used by IKE for the negotiation (might differ from
! 1927: * SA address, i.e. might not be tunnel endpoints or addresses
! 1928: * of transport mode SA) */
! 1929: iph2->dst = dupsaddr(dst);
! 1930: if (iph2->dst == NULL) {
! 1931: delph2(iph2);
! 1932: return -1;
! 1933: }
! 1934: iph2->src = dupsaddr(src);
! 1935: if (iph2->src == NULL) {
! 1936: delph2(iph2);
! 1937: return -1;
! 1938: }
! 1939:
! 1940: /* If sa_src and sa_dst have been set, this mean we have to
! 1941: * set iph2->sa_src and iph2->sa_dst to provide the addresses
! 1942: * of the SA because iph2->src and iph2->dst are only the ones
! 1943: * used for the IKE exchanges. Those that need these addresses
! 1944: * are for instance pk_sendupdate() or pk_sendgetspi() */
! 1945: if (sa_src) {
! 1946: iph2->sa_src = dupsaddr(sa_src);
! 1947: iph2->sa_dst = dupsaddr(sa_dst);
! 1948: }
! 1949:
! 1950: if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
! 1951: delph2(iph2);
! 1952: return -1;
! 1953: }
! 1954:
! 1955: #ifdef HAVE_SECCTX
! 1956: if (m_sec_ctx) {
! 1957: set_secctx_in_proposal(iph2, spidx);
! 1958: }
! 1959: #endif /* HAVE_SECCTX */
! 1960:
! 1961: insph2(iph2);
! 1962:
! 1963: /* start isakmp initiation by using ident exchange */
! 1964: /* XXX should be looped if there are multiple phase 2 handler. */
! 1965: if (isakmp_post_acquire(iph2, NULL, TRUE) < 0) {
! 1966: plog(LLV_ERROR, LOCATION, NULL,
! 1967: "failed to begin ipsec sa negotication.\n");
! 1968: remph2(iph2);
! 1969: delph2(iph2);
! 1970: return -1;
! 1971: }
! 1972:
! 1973: return 0;
! 1974: }
! 1975:
! 1976: static int
! 1977: pk_recvdelete(mhp)
! 1978: caddr_t *mhp;
! 1979: {
! 1980: struct sadb_msg *msg;
! 1981: struct sadb_sa *sa;
! 1982: struct sockaddr *src, *dst;
! 1983: struct ph2handle *iph2 = NULL;
! 1984: u_int proto_id;
! 1985:
! 1986: /* ignore this message because of local test mode. */
! 1987: if (f_local)
! 1988: return 0;
! 1989:
! 1990: /* sanity check */
! 1991: if (mhp[0] == NULL
! 1992: || mhp[SADB_EXT_SA] == NULL
! 1993: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 1994: || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
! 1995: plog(LLV_ERROR, LOCATION, NULL,
! 1996: "inappropriate sadb delete message passed.\n");
! 1997: return -1;
! 1998: }
! 1999: msg = (struct sadb_msg *)mhp[0];
! 2000: sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
! 2001: pk_fixup_sa_addresses(mhp);
! 2002: src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
! 2003: dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
! 2004:
! 2005: /* the message has to be processed or not ? */
! 2006: if (msg->sadb_msg_pid == getpid()) {
! 2007: plog(LLV_DEBUG, LOCATION, NULL,
! 2008: "%s message is not interesting "
! 2009: "because the message was originated by me.\n",
! 2010: s_pfkey_type(msg->sadb_msg_type));
! 2011: return -1;
! 2012: }
! 2013:
! 2014: proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
! 2015: if (proto_id == ~0) {
! 2016: plog(LLV_ERROR, LOCATION, NULL,
! 2017: "invalid proto_id %d\n", msg->sadb_msg_satype);
! 2018: return -1;
! 2019: }
! 2020:
! 2021: iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
! 2022: if (iph2 == NULL) {
! 2023: /* ignore */
! 2024: plog(LLV_ERROR, LOCATION, NULL,
! 2025: "no iph2 found: %s\n",
! 2026: sadbsecas2str(src, dst, msg->sadb_msg_satype,
! 2027: sa->sadb_sa_spi, IPSEC_MODE_ANY));
! 2028: return 0;
! 2029: }
! 2030:
! 2031: plog(LLV_ERROR, LOCATION, NULL,
! 2032: "pfkey DELETE received: %s\n",
! 2033: sadbsecas2str(src, dst,
! 2034: msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
! 2035:
! 2036: /* send delete information */
! 2037: if (iph2->status == PHASE2ST_ESTABLISHED)
! 2038: isakmp_info_send_d2(iph2);
! 2039:
! 2040: remph2(iph2);
! 2041: delph2(iph2);
! 2042:
! 2043: return 0;
! 2044: }
! 2045:
! 2046: static int
! 2047: pk_recvflush(mhp)
! 2048: caddr_t *mhp;
! 2049: {
! 2050: /* ignore this message because of local test mode. */
! 2051: if (f_local)
! 2052: return 0;
! 2053:
! 2054: /* sanity check */
! 2055: if (mhp[0] == NULL) {
! 2056: plog(LLV_ERROR, LOCATION, NULL,
! 2057: "inappropriate sadb flush message passed.\n");
! 2058: return -1;
! 2059: }
! 2060:
! 2061: flushph2();
! 2062:
! 2063: return 0;
! 2064: }
! 2065:
! 2066: static int
! 2067: getsadbpolicy(policy0, policylen0, type, iph2)
! 2068: caddr_t *policy0;
! 2069: int *policylen0, type;
! 2070: struct ph2handle *iph2;
! 2071: {
! 2072: struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
! 2073: struct sockaddr *src = NULL, *dst = NULL;
! 2074: struct sadb_x_policy *xpl;
! 2075: struct sadb_x_ipsecrequest *xisr;
! 2076: struct saproto *pr;
! 2077: struct saproto **pr_rlist;
! 2078: int rlist_len = 0;
! 2079: caddr_t policy, p;
! 2080: int policylen;
! 2081: int xisrlen;
! 2082: u_int satype, mode;
! 2083: int len = 0;
! 2084: #ifdef HAVE_SECCTX
! 2085: int ctxlen = 0;
! 2086: #endif /* HAVE_SECCTX */
! 2087:
! 2088:
! 2089: /* get policy buffer size */
! 2090: policylen = sizeof(struct sadb_x_policy);
! 2091: if (type != SADB_X_SPDDELETE) {
! 2092: if (iph2->sa_src && iph2->sa_dst) {
! 2093: src = iph2->sa_src; /* MIPv6: Use SA addresses, */
! 2094: dst = iph2->sa_dst; /* not IKE ones */
! 2095: } else {
! 2096: src = iph2->src; /* Common case: SA addresses */
! 2097: dst = iph2->dst; /* and IKE ones are the same */
! 2098: }
! 2099:
! 2100: for (pr = iph2->approval->head; pr; pr = pr->next) {
! 2101: xisrlen = sizeof(*xisr);
! 2102: if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
! 2103: xisrlen += (sysdep_sa_len(src) +
! 2104: sysdep_sa_len(dst));
! 2105: }
! 2106:
! 2107: policylen += PFKEY_ALIGN8(xisrlen);
! 2108: }
! 2109: }
! 2110:
! 2111: #ifdef HAVE_SECCTX
! 2112: if (*spidx->sec_ctx.ctx_str) {
! 2113: ctxlen = sizeof(struct sadb_x_sec_ctx)
! 2114: + PFKEY_ALIGN8(spidx->sec_ctx.ctx_strlen);
! 2115: policylen += ctxlen;
! 2116: }
! 2117: #endif /* HAVE_SECCTX */
! 2118:
! 2119: /* make policy structure */
! 2120: policy = racoon_malloc(policylen);
! 2121: memset((void*)policy, 0xcd, policylen);
! 2122: if (!policy) {
! 2123: plog(LLV_ERROR, LOCATION, NULL,
! 2124: "buffer allocation failed.\n");
! 2125: return -1;
! 2126: }
! 2127:
! 2128: xpl = (struct sadb_x_policy *)policy;
! 2129: xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
! 2130: xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
! 2131: xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
! 2132: xpl->sadb_x_policy_dir = spidx->dir;
! 2133: xpl->sadb_x_policy_id = 0;
! 2134: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 2135: xpl->sadb_x_policy_priority = PRIORITY_DEFAULT;
! 2136: #endif
! 2137: len++;
! 2138:
! 2139: #ifdef HAVE_SECCTX
! 2140: if (*spidx->sec_ctx.ctx_str) {
! 2141: struct sadb_x_sec_ctx *p;
! 2142:
! 2143: p = (struct sadb_x_sec_ctx *)(xpl + len);
! 2144: memset(p, 0, ctxlen);
! 2145: p->sadb_x_sec_len = PFKEY_UNIT64(ctxlen);
! 2146: p->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
! 2147: p->sadb_x_ctx_len = spidx->sec_ctx.ctx_strlen;
! 2148: p->sadb_x_ctx_doi = spidx->sec_ctx.ctx_doi;
! 2149: p->sadb_x_ctx_alg = spidx->sec_ctx.ctx_alg;
! 2150:
! 2151: memcpy(p + 1,spidx->sec_ctx.ctx_str,spidx->sec_ctx.ctx_strlen);
! 2152: len += ctxlen;
! 2153: }
! 2154: #endif /* HAVE_SECCTX */
! 2155:
! 2156: /* no need to append policy information any more if type is SPDDELETE */
! 2157: if (type == SADB_X_SPDDELETE)
! 2158: goto end;
! 2159:
! 2160: xisr = (struct sadb_x_ipsecrequest *)(xpl + len);
! 2161:
! 2162: /* The order of things is reversed for use in add policy messages */
! 2163: for (pr = iph2->approval->head; pr; pr = pr->next) rlist_len++;
! 2164: pr_rlist = racoon_malloc((rlist_len+1)*sizeof(struct saproto*));
! 2165: if (!pr_rlist) {
! 2166: plog(LLV_ERROR, LOCATION, NULL,
! 2167: "buffer allocation failed.\n");
! 2168: return -1;
! 2169: }
! 2170: pr_rlist[rlist_len--] = NULL;
! 2171: for (pr = iph2->approval->head; pr; pr = pr->next) pr_rlist[rlist_len--] = pr;
! 2172: rlist_len = 0;
! 2173:
! 2174: for (pr = pr_rlist[rlist_len++]; pr; pr = pr_rlist[rlist_len++]) {
! 2175:
! 2176: satype = doi2ipproto(pr->proto_id);
! 2177: if (satype == ~0) {
! 2178: plog(LLV_ERROR, LOCATION, NULL,
! 2179: "invalid proto_id %d\n", pr->proto_id);
! 2180: goto err;
! 2181: }
! 2182: mode = ipsecdoi2pfkey_mode(pr->encmode);
! 2183: if (mode == ~0) {
! 2184: plog(LLV_ERROR, LOCATION, NULL,
! 2185: "invalid encmode %d\n", pr->encmode);
! 2186: goto err;
! 2187: }
! 2188:
! 2189: /*
! 2190: * the policy level cannot be unique because the policy
! 2191: * is defined later than SA, so req_id cannot be bound to SA.
! 2192: */
! 2193: xisr->sadb_x_ipsecrequest_proto = satype;
! 2194: xisr->sadb_x_ipsecrequest_mode = mode;
! 2195: if(iph2->proposal->head->reqid_in > 0){
! 2196: xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
! 2197: xisr->sadb_x_ipsecrequest_reqid = iph2->proposal->head->reqid_in;
! 2198: }else{
! 2199: xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
! 2200: xisr->sadb_x_ipsecrequest_reqid = 0;
! 2201: }
! 2202: p = (caddr_t)(xisr + 1);
! 2203:
! 2204: xisrlen = sizeof(*xisr);
! 2205:
! 2206: if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
! 2207: int src_len, dst_len;
! 2208:
! 2209: src_len = sysdep_sa_len(src);
! 2210: dst_len = sysdep_sa_len(dst);
! 2211: xisrlen += src_len + dst_len;
! 2212:
! 2213: memcpy(p, src, src_len);
! 2214: p += src_len;
! 2215:
! 2216: memcpy(p, dst, dst_len);
! 2217: p += dst_len;
! 2218: }
! 2219:
! 2220: xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
! 2221: xisr = (struct sadb_x_ipsecrequest *)p;
! 2222:
! 2223: }
! 2224: racoon_free(pr_rlist);
! 2225:
! 2226: end:
! 2227: *policy0 = policy;
! 2228: *policylen0 = policylen;
! 2229:
! 2230: return 0;
! 2231:
! 2232: err:
! 2233: if (policy)
! 2234: racoon_free(policy);
! 2235: if (pr_rlist) racoon_free(pr_rlist);
! 2236:
! 2237: return -1;
! 2238: }
! 2239:
! 2240: int
! 2241: pk_sendspdupdate2(iph2)
! 2242: struct ph2handle *iph2;
! 2243: {
! 2244: struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
! 2245: caddr_t policy = NULL;
! 2246: int policylen = 0;
! 2247: u_int64_t ltime, vtime;
! 2248:
! 2249: ltime = iph2->approval->lifetime;
! 2250: vtime = 0;
! 2251:
! 2252: if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
! 2253: plog(LLV_ERROR, LOCATION, NULL,
! 2254: "getting sadb policy failed.\n");
! 2255: return -1;
! 2256: }
! 2257:
! 2258: if (pfkey_send_spdupdate2(
! 2259: lcconf->sock_pfkey,
! 2260: (struct sockaddr *)&spidx->src,
! 2261: spidx->prefs,
! 2262: (struct sockaddr *)&spidx->dst,
! 2263: spidx->prefd,
! 2264: spidx->ul_proto,
! 2265: ltime, vtime,
! 2266: policy, policylen, 0) < 0) {
! 2267: plog(LLV_ERROR, LOCATION, NULL,
! 2268: "libipsec failed send spdupdate2 (%s)\n",
! 2269: ipsec_strerror());
! 2270: goto end;
! 2271: }
! 2272: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdupdate2\n");
! 2273:
! 2274: end:
! 2275: if (policy)
! 2276: racoon_free(policy);
! 2277:
! 2278: return 0;
! 2279: }
! 2280:
! 2281: static int
! 2282: pk_recvspdupdate(mhp)
! 2283: caddr_t *mhp;
! 2284: {
! 2285: struct sadb_address *saddr, *daddr;
! 2286: struct sadb_x_policy *xpl;
! 2287: struct sadb_lifetime *lt;
! 2288: struct policyindex spidx;
! 2289: struct secpolicy *sp;
! 2290: struct sockaddr *local=NULL, *remote=NULL;
! 2291: u_int64_t created;
! 2292: int ret;
! 2293:
! 2294: /* sanity check */
! 2295: if (mhp[0] == NULL
! 2296: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 2297: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 2298: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 2299: plog(LLV_ERROR, LOCATION, NULL,
! 2300: "inappropriate sadb spdupdate message passed.\n");
! 2301: return -1;
! 2302: }
! 2303: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 2304: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 2305: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 2306: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 2307: if(lt != NULL)
! 2308: created = lt->sadb_lifetime_addtime;
! 2309: else
! 2310: created = 0;
! 2311:
! 2312: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 2313: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2314: saddr + 1,
! 2315: daddr + 1,
! 2316: saddr->sadb_address_prefixlen,
! 2317: daddr->sadb_address_prefixlen,
! 2318: saddr->sadb_address_proto,
! 2319: xpl->sadb_x_policy_priority,
! 2320: created,
! 2321: &spidx);
! 2322: #else
! 2323: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2324: saddr + 1,
! 2325: daddr + 1,
! 2326: saddr->sadb_address_prefixlen,
! 2327: daddr->sadb_address_prefixlen,
! 2328: saddr->sadb_address_proto,
! 2329: created,
! 2330: &spidx);
! 2331: #endif
! 2332:
! 2333: #ifdef HAVE_SECCTX
! 2334: if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
! 2335: struct sadb_x_sec_ctx *ctx;
! 2336:
! 2337: ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 2338: spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
! 2339: spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
! 2340: spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
! 2341: memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
! 2342: }
! 2343: #endif /* HAVE_SECCTX */
! 2344:
! 2345: sp = getsp(&spidx);
! 2346: if (sp == NULL) {
! 2347: plog(LLV_DEBUG, LOCATION, NULL,
! 2348: "this policy did not exist for removal: \"%s\"\n",
! 2349: spidx2str(&spidx));
! 2350: } else {
! 2351: /* preserve hints before deleting the SP */
! 2352: local = sp->local;
! 2353: remote = sp->remote;
! 2354: sp->local = NULL;
! 2355: sp->remote = NULL;
! 2356:
! 2357: remsp(sp);
! 2358: delsp(sp);
! 2359: }
! 2360:
! 2361: /* Add new SP (with old hints) */
! 2362: ret = addnewsp(mhp, local, remote);
! 2363:
! 2364: if (local != NULL)
! 2365: racoon_free(local);
! 2366: if (remote != NULL)
! 2367: racoon_free(remote);
! 2368:
! 2369: if (ret < 0)
! 2370: return -1;
! 2371:
! 2372: return 0;
! 2373: }
! 2374:
! 2375: /*
! 2376: * this function has to be used by responder side.
! 2377: */
! 2378: int
! 2379: pk_sendspdadd2(iph2)
! 2380: struct ph2handle *iph2;
! 2381: {
! 2382: struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
! 2383: caddr_t policy = NULL;
! 2384: int policylen = 0;
! 2385: u_int64_t ltime, vtime;
! 2386:
! 2387: ltime = iph2->approval->lifetime;
! 2388: vtime = 0;
! 2389:
! 2390: if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
! 2391: plog(LLV_ERROR, LOCATION, NULL,
! 2392: "getting sadb policy failed.\n");
! 2393: return -1;
! 2394: }
! 2395:
! 2396: if (pfkey_send_spdadd2(
! 2397: lcconf->sock_pfkey,
! 2398: (struct sockaddr *)&spidx->src,
! 2399: spidx->prefs,
! 2400: (struct sockaddr *)&spidx->dst,
! 2401: spidx->prefd,
! 2402: spidx->ul_proto,
! 2403: ltime, vtime,
! 2404: policy, policylen, 0) < 0) {
! 2405: plog(LLV_ERROR, LOCATION, NULL,
! 2406: "libipsec failed send spdadd2 (%s)\n",
! 2407: ipsec_strerror());
! 2408: goto end;
! 2409: }
! 2410: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdadd2\n");
! 2411:
! 2412: end:
! 2413: if (policy)
! 2414: racoon_free(policy);
! 2415:
! 2416: return 0;
! 2417: }
! 2418:
! 2419: static int
! 2420: pk_recvspdadd(mhp)
! 2421: caddr_t *mhp;
! 2422: {
! 2423: struct sadb_address *saddr, *daddr;
! 2424: struct sadb_x_policy *xpl;
! 2425: struct sadb_lifetime *lt;
! 2426: struct policyindex spidx;
! 2427: struct secpolicy *sp;
! 2428: struct sockaddr *local = NULL, *remote = NULL;
! 2429: u_int64_t created;
! 2430: int ret;
! 2431:
! 2432: /* sanity check */
! 2433: if (mhp[0] == NULL
! 2434: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 2435: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 2436: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 2437: plog(LLV_ERROR, LOCATION, NULL,
! 2438: "inappropriate sadb spdadd message passed.\n");
! 2439: return -1;
! 2440: }
! 2441: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 2442: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 2443: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 2444: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 2445: if(lt != NULL)
! 2446: created = lt->sadb_lifetime_addtime;
! 2447: else
! 2448: created = 0;
! 2449:
! 2450: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 2451: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2452: saddr + 1,
! 2453: daddr + 1,
! 2454: saddr->sadb_address_prefixlen,
! 2455: daddr->sadb_address_prefixlen,
! 2456: saddr->sadb_address_proto,
! 2457: xpl->sadb_x_policy_priority,
! 2458: created,
! 2459: &spidx);
! 2460: #else
! 2461: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2462: saddr + 1,
! 2463: daddr + 1,
! 2464: saddr->sadb_address_prefixlen,
! 2465: daddr->sadb_address_prefixlen,
! 2466: saddr->sadb_address_proto,
! 2467: created,
! 2468: &spidx);
! 2469: #endif
! 2470:
! 2471: #ifdef HAVE_SECCTX
! 2472: if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
! 2473: struct sadb_x_sec_ctx *ctx;
! 2474:
! 2475: ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 2476: spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
! 2477: spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
! 2478: spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
! 2479: memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
! 2480: }
! 2481: #endif /* HAVE_SECCTX */
! 2482:
! 2483: sp = getsp(&spidx);
! 2484: if (sp != NULL) {
! 2485: plog(LLV_ERROR, LOCATION, NULL,
! 2486: "such policy already exists. "
! 2487: "anyway replace it: %s\n",
! 2488: spidx2str(&spidx));
! 2489:
! 2490: /* preserve hints before deleting the SP */
! 2491: local = sp->local;
! 2492: remote = sp->remote;
! 2493: sp->local = NULL;
! 2494: sp->remote = NULL;
! 2495:
! 2496: remsp(sp);
! 2497: delsp(sp);
! 2498: }
! 2499:
! 2500: /* Add new SP (with old hints) */
! 2501: ret = addnewsp(mhp, local, remote);
! 2502:
! 2503: if (local != NULL)
! 2504: racoon_free(local);
! 2505: if (remote != NULL)
! 2506: racoon_free(remote);
! 2507:
! 2508: if (ret < 0)
! 2509: return -1;
! 2510:
! 2511: return 0;
! 2512: }
! 2513:
! 2514: /*
! 2515: * this function has to be used by responder side.
! 2516: */
! 2517: int
! 2518: pk_sendspddelete(iph2)
! 2519: struct ph2handle *iph2;
! 2520: {
! 2521: struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
! 2522: caddr_t policy = NULL;
! 2523: int policylen;
! 2524:
! 2525: if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
! 2526: plog(LLV_ERROR, LOCATION, NULL,
! 2527: "getting sadb policy failed.\n");
! 2528: return -1;
! 2529: }
! 2530:
! 2531: if (pfkey_send_spddelete(
! 2532: lcconf->sock_pfkey,
! 2533: (struct sockaddr *)&spidx->src,
! 2534: spidx->prefs,
! 2535: (struct sockaddr *)&spidx->dst,
! 2536: spidx->prefd,
! 2537: spidx->ul_proto,
! 2538: policy, policylen, 0) < 0) {
! 2539: plog(LLV_ERROR, LOCATION, NULL,
! 2540: "libipsec failed send spddelete (%s)\n",
! 2541: ipsec_strerror());
! 2542: goto end;
! 2543: }
! 2544: plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spddelete\n");
! 2545:
! 2546: end:
! 2547: if (policy)
! 2548: racoon_free(policy);
! 2549:
! 2550: return 0;
! 2551: }
! 2552:
! 2553: static int
! 2554: pk_recvspddelete(mhp)
! 2555: caddr_t *mhp;
! 2556: {
! 2557: struct sadb_address *saddr, *daddr;
! 2558: struct sadb_x_policy *xpl;
! 2559: struct sadb_lifetime *lt;
! 2560: struct policyindex spidx;
! 2561: struct secpolicy *sp;
! 2562: u_int64_t created;
! 2563:
! 2564: /* sanity check */
! 2565: if (mhp[0] == NULL
! 2566: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 2567: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 2568: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 2569: plog(LLV_ERROR, LOCATION, NULL,
! 2570: "inappropriate sadb spddelete message passed.\n");
! 2571: return -1;
! 2572: }
! 2573: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 2574: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 2575: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 2576: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 2577: if(lt != NULL)
! 2578: created = lt->sadb_lifetime_addtime;
! 2579: else
! 2580: created = 0;
! 2581:
! 2582: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 2583: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2584: saddr + 1,
! 2585: daddr + 1,
! 2586: saddr->sadb_address_prefixlen,
! 2587: daddr->sadb_address_prefixlen,
! 2588: saddr->sadb_address_proto,
! 2589: xpl->sadb_x_policy_priority,
! 2590: created,
! 2591: &spidx);
! 2592: #else
! 2593: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2594: saddr + 1,
! 2595: daddr + 1,
! 2596: saddr->sadb_address_prefixlen,
! 2597: daddr->sadb_address_prefixlen,
! 2598: saddr->sadb_address_proto,
! 2599: created,
! 2600: &spidx);
! 2601: #endif
! 2602:
! 2603: #ifdef HAVE_SECCTX
! 2604: if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
! 2605: struct sadb_x_sec_ctx *ctx;
! 2606:
! 2607: ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 2608: spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
! 2609: spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
! 2610: spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
! 2611: memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
! 2612: }
! 2613: #endif /* HAVE_SECCTX */
! 2614:
! 2615: sp = getsp(&spidx);
! 2616: if (sp == NULL) {
! 2617: plog(LLV_ERROR, LOCATION, NULL,
! 2618: "no policy found: %s\n",
! 2619: spidx2str(&spidx));
! 2620: return -1;
! 2621: }
! 2622:
! 2623: remsp(sp);
! 2624: delsp(sp);
! 2625:
! 2626: return 0;
! 2627: }
! 2628:
! 2629: static int
! 2630: pk_recvspdexpire(mhp)
! 2631: caddr_t *mhp;
! 2632: {
! 2633: struct sadb_address *saddr, *daddr;
! 2634: struct sadb_x_policy *xpl;
! 2635: struct sadb_lifetime *lt;
! 2636: struct policyindex spidx;
! 2637: struct secpolicy *sp;
! 2638: u_int64_t created;
! 2639:
! 2640: /* sanity check */
! 2641: if (mhp[0] == NULL
! 2642: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 2643: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 2644: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 2645: plog(LLV_ERROR, LOCATION, NULL,
! 2646: "inappropriate sadb spdexpire message passed.\n");
! 2647: return -1;
! 2648: }
! 2649: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 2650: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 2651: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 2652: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 2653: if(lt != NULL)
! 2654: created = lt->sadb_lifetime_addtime;
! 2655: else
! 2656: created = 0;
! 2657:
! 2658: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 2659: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2660: saddr + 1,
! 2661: daddr + 1,
! 2662: saddr->sadb_address_prefixlen,
! 2663: daddr->sadb_address_prefixlen,
! 2664: saddr->sadb_address_proto,
! 2665: xpl->sadb_x_policy_priority,
! 2666: created,
! 2667: &spidx);
! 2668: #else
! 2669: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2670: saddr + 1,
! 2671: daddr + 1,
! 2672: saddr->sadb_address_prefixlen,
! 2673: daddr->sadb_address_prefixlen,
! 2674: saddr->sadb_address_proto,
! 2675: created,
! 2676: &spidx);
! 2677: #endif
! 2678:
! 2679: #ifdef HAVE_SECCTX
! 2680: if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
! 2681: struct sadb_x_sec_ctx *ctx;
! 2682:
! 2683: ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 2684: spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
! 2685: spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
! 2686: spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
! 2687: memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
! 2688: }
! 2689: #endif /* HAVE_SECCTX */
! 2690:
! 2691: sp = getsp(&spidx);
! 2692: if (sp == NULL) {
! 2693: plog(LLV_ERROR, LOCATION, NULL,
! 2694: "no policy found: %s\n",
! 2695: spidx2str(&spidx));
! 2696: return -1;
! 2697: }
! 2698:
! 2699: remsp(sp);
! 2700: delsp(sp);
! 2701:
! 2702: return 0;
! 2703: }
! 2704:
! 2705: static int
! 2706: pk_recvspdget(mhp)
! 2707: caddr_t *mhp;
! 2708: {
! 2709: /* sanity check */
! 2710: if (mhp[0] == NULL) {
! 2711: plog(LLV_ERROR, LOCATION, NULL,
! 2712: "inappropriate sadb spdget message passed.\n");
! 2713: return -1;
! 2714: }
! 2715:
! 2716: return 0;
! 2717: }
! 2718:
! 2719: static int
! 2720: pk_recvspddump(mhp)
! 2721: caddr_t *mhp;
! 2722: {
! 2723: struct sadb_msg *msg;
! 2724: struct sadb_address *saddr, *daddr;
! 2725: struct sadb_x_policy *xpl;
! 2726: struct sadb_lifetime *lt;
! 2727: struct policyindex spidx;
! 2728: struct secpolicy *sp;
! 2729: struct sockaddr *local=NULL, *remote=NULL;
! 2730: u_int64_t created;
! 2731: int ret;
! 2732:
! 2733: /* sanity check */
! 2734: if (mhp[0] == NULL) {
! 2735: plog(LLV_ERROR, LOCATION, NULL,
! 2736: "inappropriate sadb spddump message passed.\n");
! 2737: return -1;
! 2738: }
! 2739: msg = (struct sadb_msg *)mhp[0];
! 2740: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 2741: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 2742: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 2743: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 2744: if(lt != NULL)
! 2745: created = lt->sadb_lifetime_addtime;
! 2746: else
! 2747: created = 0;
! 2748:
! 2749: if (saddr == NULL || daddr == NULL || xpl == NULL) {
! 2750: plog(LLV_ERROR, LOCATION, NULL,
! 2751: "inappropriate sadb spddump message passed.\n");
! 2752: return -1;
! 2753: }
! 2754:
! 2755: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 2756: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2757: saddr + 1,
! 2758: daddr + 1,
! 2759: saddr->sadb_address_prefixlen,
! 2760: daddr->sadb_address_prefixlen,
! 2761: saddr->sadb_address_proto,
! 2762: xpl->sadb_x_policy_priority,
! 2763: created,
! 2764: &spidx);
! 2765: #else
! 2766: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 2767: saddr + 1,
! 2768: daddr + 1,
! 2769: saddr->sadb_address_prefixlen,
! 2770: daddr->sadb_address_prefixlen,
! 2771: saddr->sadb_address_proto,
! 2772: created,
! 2773: &spidx);
! 2774: #endif
! 2775:
! 2776: #ifdef HAVE_SECCTX
! 2777: if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
! 2778: struct sadb_x_sec_ctx *ctx;
! 2779:
! 2780: ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 2781: spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
! 2782: spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
! 2783: spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
! 2784: memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
! 2785: }
! 2786: #endif /* HAVE_SECCTX */
! 2787:
! 2788: sp = getsp(&spidx);
! 2789: if (sp != NULL) {
! 2790: plog(LLV_ERROR, LOCATION, NULL,
! 2791: "such policy already exists. "
! 2792: "anyway replace it: %s\n",
! 2793: spidx2str(&spidx));
! 2794:
! 2795: /* preserve hints before deleting the SP */
! 2796: local = sp->local;
! 2797: remote = sp->remote;
! 2798: sp->local = NULL;
! 2799: sp->remote = NULL;
! 2800:
! 2801: remsp(sp);
! 2802: delsp(sp);
! 2803: }
! 2804:
! 2805: /* Add new SP (with old hints) */
! 2806: ret = addnewsp(mhp, local, remote);
! 2807:
! 2808: if (local != NULL)
! 2809: racoon_free(local);
! 2810: if (remote != NULL)
! 2811: racoon_free(remote);
! 2812:
! 2813: if (ret < 0)
! 2814: return -1;
! 2815:
! 2816: return 0;
! 2817: }
! 2818:
! 2819: static int
! 2820: pk_recvspdflush(mhp)
! 2821: caddr_t *mhp;
! 2822: {
! 2823: /* sanity check */
! 2824: if (mhp[0] == NULL) {
! 2825: plog(LLV_ERROR, LOCATION, NULL,
! 2826: "inappropriate sadb spdflush message passed.\n");
! 2827: return -1;
! 2828: }
! 2829:
! 2830: flushsp();
! 2831:
! 2832: return 0;
! 2833: }
! 2834:
! 2835: #if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
! 2836:
! 2837: /* MIGRATE support (pk_recvmigrate() is the handler of MIGRATE message).
! 2838: *
! 2839: * pk_recvmigrate()
! 2840: * 1) some preprocessing and checks
! 2841: * 2) parsing of sadb_x_kmaddress extension
! 2842: * 3) SP lookup using selectors and content of policy extension from MIGRATE
! 2843: * 4) resolution of current local and remote IKE addresses
! 2844: * 5) Use of addresses to get Phase 1 handler if any
! 2845: * 6) Update of IKE addresses in Phase 1 (iph1->local and iph1->remote)
! 2846: * 7) Update of IKE addresses in Phase 2 (iph2->src and iph2->dst)
! 2847: * 8) Update of IKE addresses in SP (sp->local and sp->remote)
! 2848: * 9) Loop on sadb_x_ipsecrequests pairs from MIGRATE
! 2849: * - update of associated ipsecrequests entries in sp->req (should be
! 2850: * only one as racoon does not support bundles), i.e. update of
! 2851: * tunnel endpoints when required.
! 2852: * - If tunnel mode endpoints have been updated, lookup of associated
! 2853: * Phase 2 handle to also update sa_src and sa_dst entries
! 2854: *
! 2855: * XXX Note that we do not support yet the update of SA addresses for transport
! 2856: * mode, but only the update of SA addresses for tunnel mode (endpoints).
! 2857: * Reasons are:
! 2858: * - there is no initial need for MIPv6
! 2859: * - racoon does not support bundles
! 2860: * - this would imply more work to deal with sainfo update (if feasible).
! 2861: */
! 2862:
! 2863: /* Generic argument structure for migration callbacks */
! 2864: struct migrate_args {
! 2865: struct sockaddr *local;
! 2866: struct sockaddr *remote;
! 2867: };
! 2868:
! 2869: /*
! 2870: * Update local and remote addresses of given Phase 1. Schedule removal
! 2871: * if negotiation was going on and restart a one from updated address.
! 2872: *
! 2873: * -1 is returned on error. 0 if everything went right.
! 2874: */
! 2875: static int
! 2876: migrate_ph1_ike_addresses(iph1, arg)
! 2877: struct ph1handle *iph1;
! 2878: void *arg;
! 2879: {
! 2880: struct migrate_args *ma = (struct migrate_args *) arg;
! 2881: struct remoteconf *rmconf;
! 2882: u_int16_t port;
! 2883:
! 2884: /* Already up-to-date? */
! 2885: if (cmpsaddr(iph1->local, ma->local) == CMPSADDR_MATCH &&
! 2886: cmpsaddr(iph1->remote, ma->remote) == CMPSADDR_MATCH)
! 2887: return 0;
! 2888:
! 2889: if (iph1->status < PHASE1ST_ESTABLISHED) {
! 2890: /* Bad luck! We received a MIGRATE *while* negotiating
! 2891: * Phase 1 (i.e. it was not established yet). If we act as
! 2892: * initiator we need to restart the negotiation. As
! 2893: * responder, our best bet is to update our addresses
! 2894: * and wait for the initiator to do something */
! 2895: plog(LLV_WARNING, LOCATION, NULL, "MIGRATE received *during* "
! 2896: "Phase 1 negotiation (%s).\n",
! 2897: saddr2str_fromto("%s => %s", ma->local, ma->remote));
! 2898:
! 2899: /* If we are not acting as initiator, let's just leave and
! 2900: * let the remote peer handle the restart */
! 2901: rmconf = getrmconf(ma->remote, 0);
! 2902: if (rmconf == NULL || !rmconf->passive) {
! 2903: iph1->status = PHASE1ST_EXPIRED;
! 2904: isakmp_ph1delete(iph1);
! 2905:
! 2906: /* This is unlikely, but let's just check if a Phase 1
! 2907: * for the new addresses already exist */
! 2908: if (getph1byaddr(ma->local, ma->remote, 0)) {
! 2909: plog(LLV_WARNING, LOCATION, NULL, "No need "
! 2910: "to start a new Phase 1 negotiation. One "
! 2911: "already exists.\n");
! 2912: return 0;
! 2913: }
! 2914:
! 2915: plog(LLV_WARNING, LOCATION, NULL, "As initiator, "
! 2916: "restarting it.\n");
! 2917: /* Note that the insertion of the new Phase 1 will not
! 2918: * interfere with the fact we are called from enumph1,
! 2919: * because it is inserted as first element. --arno */
! 2920: isakmp_ph1begin_i(rmconf, ma->local, ma->remote);
! 2921:
! 2922: return 0;
! 2923: }
! 2924: }
! 2925:
! 2926: if (iph1->local != NULL) {
! 2927: plog(LLV_DEBUG, LOCATION, NULL, "Migrating Phase 1 local "
! 2928: "address from %s\n",
! 2929: saddr2str_fromto("%s to %s", iph1->local, ma->local));
! 2930: port = extract_port(iph1->local);
! 2931: racoon_free(iph1->local);
! 2932: } else
! 2933: port = 0;
! 2934:
! 2935: iph1->local = dupsaddr(ma->local);
! 2936: if (iph1->local == NULL) {
! 2937: plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
! 2938: "Phase 1 local address.\n");
! 2939: return -1;
! 2940: }
! 2941: set_port(iph1->local, port);
! 2942:
! 2943: if (iph1->remote != NULL) {
! 2944: plog(LLV_DEBUG, LOCATION, NULL, "Migrating Phase 1 remote "
! 2945: "address from %s\n",
! 2946: saddr2str_fromto("%s to %s", iph1->remote, ma->remote));
! 2947: port = extract_port(iph1->remote);
! 2948: racoon_free(iph1->remote);
! 2949: } else
! 2950: port = 0;
! 2951:
! 2952: iph1->remote = dupsaddr(ma->remote);
! 2953: if (iph1->remote == NULL) {
! 2954: plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
! 2955: "Phase 1 remote address.\n");
! 2956: return -1;
! 2957: }
! 2958: set_port(iph1->remote, port);
! 2959:
! 2960: return 0;
! 2961: }
! 2962:
! 2963: /* Update src and dst of all current Phase 2 handles.
! 2964: * with provided local and remote addresses.
! 2965: * Our intent is NOT to modify IPsec SA endpoints but IKE
! 2966: * addresses so we need to take care to separate those if
! 2967: * they are different. -1 is returned on error. 0 if everything
! 2968: * went right.
! 2969: *
! 2970: * Note: we do not maintain port information as it is not
! 2971: * expected to be meaningful --arno
! 2972: */
! 2973: static int
! 2974: migrate_ph2_ike_addresses(iph2, arg)
! 2975: struct ph2handle *iph2;
! 2976: void *arg;
! 2977: {
! 2978: struct migrate_args *ma = (struct migrate_args *) arg;
! 2979: struct ph1handle *iph1;
! 2980:
! 2981: /* If Phase 2 has an associated Phase 1, migrate addresses */
! 2982: if (iph2->ph1)
! 2983: migrate_ph1_ike_addresses(iph2->ph1, arg);
! 2984:
! 2985: /* Already up-to-date? */
! 2986: if (cmpsaddr(iph2->src, ma->local) == CMPSADDR_MATCH &&
! 2987: cmpsaddr(iph2->dst, ma->remote) == CMPSADDR_MATCH)
! 2988: return 0;
! 2989:
! 2990: /* save src/dst as sa_src/sa_dst before rewriting */
! 2991: if (iph2->sa_src == NULL && iph2->sa_dst == NULL) {
! 2992: iph2->sa_src = iph2->src;
! 2993: iph2->sa_dst = iph2->dst;
! 2994: iph2->src = NULL;
! 2995: iph2->dst = NULL;
! 2996: }
! 2997:
! 2998: if (iph2->src != NULL)
! 2999: racoon_free(iph2->src);
! 3000: iph2->src = dupsaddr(ma->local);
! 3001: if (iph2->src == NULL) {
! 3002: plog(LLV_ERROR, LOCATION, NULL,
! 3003: "unable to allocate Phase 2 src address.\n");
! 3004: return -1;
! 3005: }
! 3006:
! 3007: if (iph2->dst != NULL)
! 3008: racoon_free(iph2->dst);
! 3009: iph2->dst = dupsaddr(ma->remote);
! 3010: if (iph2->dst == NULL) {
! 3011: plog(LLV_ERROR, LOCATION, NULL,
! 3012: "unable to allocate Phase 2 dst address.\n");
! 3013: return -1;
! 3014: }
! 3015:
! 3016: return 0;
! 3017: }
! 3018:
! 3019: /* Consider existing Phase 2 handles with given spid and update their source
! 3020: * and destination addresses for SA. As racoon does not support bundles, if
! 3021: * we modify multiple occurrences, this probably imply rekeying has happened.
! 3022: *
! 3023: * Both addresses passed to the function are expected not to be NULL and of
! 3024: * same family. -1 is returned on error. 0 if everything went right.
! 3025: *
! 3026: * Specific care is needed to support Phase 2 for which negotiation has
! 3027: * already started but are which not yet established.
! 3028: */
! 3029: static int
! 3030: migrate_ph2_sa_addresses(iph2, args)
! 3031: struct ph2handle *iph2;
! 3032: void *args;
! 3033: {
! 3034: struct migrate_args *ma = (struct migrate_args *) args;
! 3035:
! 3036: if (iph2->sa_src != NULL) {
! 3037: racoon_free(iph2->sa_src);
! 3038: iph2->sa_src = NULL;
! 3039: }
! 3040:
! 3041: if (iph2->sa_dst != NULL) {
! 3042: racoon_free(iph2->sa_dst);
! 3043: iph2->sa_dst = NULL;
! 3044: }
! 3045:
! 3046: iph2->sa_src = dupsaddr(ma->local);
! 3047: if (iph2->sa_src == NULL) {
! 3048: plog(LLV_ERROR, LOCATION, NULL,
! 3049: "unable to allocate Phase 2 sa_src address.\n");
! 3050: return -1;
! 3051: }
! 3052:
! 3053: iph2->sa_dst = dupsaddr(ma->remote);
! 3054: if (iph2->sa_dst == NULL) {
! 3055: plog(LLV_ERROR, LOCATION, NULL,
! 3056: "unable to allocate Phase 2 sa_dst address.\n");
! 3057: return -1;
! 3058: }
! 3059:
! 3060: if (iph2->status < PHASE2ST_ESTABLISHED) {
! 3061: struct remoteconf *rmconf;
! 3062: /* We were negotiating for that SA when we received the MIGRATE.
! 3063: * We cannot simply update the addresses and let the exchange
! 3064: * go on. We have to restart the whole negotiation if we are
! 3065: * the initiator. Otherwise (acting as responder), we just need
! 3066: * to delete our ph2handle and wait for the initiator to start
! 3067: * a new negotiation. */
! 3068:
! 3069: if (iph2->ph1 && iph2->ph1->rmconf)
! 3070: rmconf = iph2->ph1->rmconf;
! 3071: else
! 3072: rmconf = getrmconf(iph2->dst, 0);
! 3073:
! 3074: if (rmconf && !rmconf->passive) {
! 3075: struct ph1handle *iph1hint;
! 3076:
! 3077: plog(LLV_WARNING, LOCATION, iph2->dst, "MIGRATE received "
! 3078: "*during* IPsec SA negotiation. As initiator, "
! 3079: "restarting it.\n");
! 3080:
! 3081: /* Turn off expiration timer ...*/
! 3082: sched_cancel(&iph2->sce);
! 3083: iph2->status = PHASE2ST_EXPIRED;
! 3084:
! 3085: /* ... clean Phase 2 handle ... */
! 3086: iph1hint = iph2->ph1;
! 3087: initph2(iph2);
! 3088: iph2->status = PHASE2ST_STATUS2;
! 3089:
! 3090: /* and start a new negotiation */
! 3091: if (isakmp_post_acquire(iph2, iph1hint, FALSE) < 0) {
! 3092: plog(LLV_ERROR, LOCATION, iph2->dst, "failed "
! 3093: "to begin IPsec SA renegotiation after "
! 3094: "MIGRATE reception.\n");
! 3095: remph2(iph2);
! 3096: delph2(iph2);
! 3097: return -1;
! 3098: }
! 3099: } else {
! 3100: plog(LLV_WARNING, LOCATION, iph2->dst, "MIGRATE received "
! 3101: "*during* IPsec SA negotiation. As responder, let's"
! 3102: "wait for the initiator to act.\n");
! 3103:
! 3104: /* Simply schedule deletion */
! 3105: isakmp_ph2expire(iph2);
! 3106: }
! 3107: }
! 3108:
! 3109: return 0;
! 3110: }
! 3111:
! 3112: /* Update SP hints (local and remote addresses) for future IKE
! 3113: * negotiations of SA associated with that SP. -1 is returned
! 3114: * on error. 0 if everything went right.
! 3115: *
! 3116: * Note: we do not maintain port information as it is not
! 3117: * expected to be meaningful --arno
! 3118: */
! 3119: static int
! 3120: migrate_sp_ike_addresses(sp, local, remote)
! 3121: struct secpolicy *sp;
! 3122: struct sockaddr *local, *remote;
! 3123: {
! 3124: if (sp == NULL || local == NULL || remote == NULL)
! 3125: return -1;
! 3126:
! 3127: if (sp->local != NULL)
! 3128: racoon_free(sp->local);
! 3129:
! 3130: sp->local = dupsaddr(local);
! 3131: if (sp->local == NULL) {
! 3132: plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
! 3133: "local hint for SP.\n");
! 3134: return -1;
! 3135: }
! 3136:
! 3137: if (sp->remote != NULL)
! 3138: racoon_free(sp->remote);
! 3139:
! 3140: sp->remote = dupsaddr(remote);
! 3141: if (sp->remote == NULL) {
! 3142: plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
! 3143: "remote hint for SP.\n");
! 3144: return -1;
! 3145: }
! 3146:
! 3147: return 0;
! 3148: }
! 3149:
! 3150: /* Given current ipsecrequest (isr_cur) to be migrated in considered
! 3151: tree, the function first checks that it matches the expected one
! 3152: (xisr_old) provided in MIGRATE message and then updates the addresses
! 3153: if it is tunnel mode (with content of xisr_new). Various other checks
! 3154: are performed. For transport mode, structures are not modified, only
! 3155: the checks are done. -1 is returned on error. */
! 3156: static int
! 3157: migrate_ph2_one_isr(spid, isr_cur, xisr_old, xisr_new)
! 3158: u_int32_t spid;
! 3159: struct ipsecrequest *isr_cur;
! 3160: struct sadb_x_ipsecrequest *xisr_old, *xisr_new;
! 3161: {
! 3162: struct secasindex *saidx = &isr_cur->saidx;
! 3163: struct sockaddr *osaddr, *odaddr, *nsaddr, *ndaddr;
! 3164: struct ph2selector ph2sel;
! 3165: struct migrate_args ma;
! 3166:
! 3167: /* First, check that mode and proto do match */
! 3168: if (xisr_old->sadb_x_ipsecrequest_proto != saidx->proto ||
! 3169: xisr_old->sadb_x_ipsecrequest_mode != saidx->mode ||
! 3170: xisr_new->sadb_x_ipsecrequest_proto != saidx->proto ||
! 3171: xisr_new->sadb_x_ipsecrequest_mode != saidx->mode)
! 3172: return -1;
! 3173:
! 3174: /* Then, verify reqid if necessary */
! 3175: if (isr_cur->saidx.reqid &&
! 3176: (xisr_old->sadb_x_ipsecrequest_reqid != IPSEC_LEVEL_UNIQUE ||
! 3177: xisr_new->sadb_x_ipsecrequest_reqid != IPSEC_LEVEL_UNIQUE ||
! 3178: isr_cur->saidx.reqid != xisr_old->sadb_x_ipsecrequest_reqid ||
! 3179: isr_cur->saidx.reqid != xisr_new->sadb_x_ipsecrequest_reqid))
! 3180: return -1;
! 3181:
! 3182: /* If not tunnel mode, our work is over */
! 3183: if (saidx->mode != IPSEC_MODE_TUNNEL) {
! 3184: plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3185: "non tunnel mode isr, skipping SA address migration.\n");
! 3186: return 0;
! 3187: }
! 3188:
! 3189: /* Tunnel mode: let's check addresses do match and then update them. */
! 3190: osaddr = (struct sockaddr *)(xisr_old + 1);
! 3191: odaddr = (struct sockaddr *)(((u_int8_t *)osaddr) + sysdep_sa_len(osaddr));
! 3192: nsaddr = (struct sockaddr *)(xisr_new + 1);
! 3193: ndaddr = (struct sockaddr *)(((u_int8_t *)nsaddr) + sysdep_sa_len(nsaddr));
! 3194:
! 3195: /* Check family does match */
! 3196: if (osaddr->sa_family != odaddr->sa_family ||
! 3197: nsaddr->sa_family != ndaddr->sa_family)
! 3198: return -1;
! 3199:
! 3200: /* Check family does match */
! 3201: if (saidx->src.ss_family != osaddr->sa_family)
! 3202: return -1;
! 3203:
! 3204: /* We log IPv4 to IPv6 and IPv6 to IPv4 switches */
! 3205: if (nsaddr->sa_family != osaddr->sa_family)
! 3206: plog(LLV_INFO, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3207: "changing address families (%d to %d) for endpoints.\n",
! 3208: osaddr->sa_family, nsaddr->sa_family);
! 3209:
! 3210: if (cmpsaddr(osaddr, (struct sockaddr *) &saidx->src) != CMPSADDR_MATCH ||
! 3211: cmpsaddr(odaddr, (struct sockaddr *) &saidx->dst) != CMPSADDR_MATCH) {
! 3212: plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3213: "mismatch of addresses in saidx and xisr.\n");
! 3214: return -1;
! 3215: }
! 3216:
! 3217: /* Excellent. Let's grab associated Phase 2 handle (if any)
! 3218: * and update its sa_src and sa_dst entries. Note that we
! 3219: * make the assumption that racoon does not support bundles
! 3220: * and make the lookup using spid: we blindly update
! 3221: * sa_src and sa_dst for _all_ found Phase 2 handles */
! 3222: memset(&ph2sel, 0, sizeof(ph2sel));
! 3223: ph2sel.spid = spid;
! 3224:
! 3225: memset(&ma, 0, sizeof(ma));
! 3226: ma.local = nsaddr;
! 3227: ma.remote = ndaddr;
! 3228:
! 3229: if (enumph2(&ph2sel, migrate_ph2_sa_addresses, &ma) < 0)
! 3230: return -1;
! 3231:
! 3232: /* Now we can do the update of endpoints in secasindex */
! 3233: memcpy(&saidx->src, nsaddr, sysdep_sa_len(nsaddr));
! 3234: memcpy(&saidx->dst, ndaddr, sysdep_sa_len(ndaddr));
! 3235:
! 3236: return 0;
! 3237: }
! 3238:
! 3239: /* Process the raw (unparsed yet) list of sadb_x_ipsecrequests of MIGRATE
! 3240: * message. For each sadb_x_ipsecrequest pair (old followed by new),
! 3241: * the corresponding ipsecrequest entry in the SP is updated. Associated
! 3242: * existing Phase 2 handle is also updated (if any) */
! 3243: static int
! 3244: migrate_sp_isr_list(sp, xisr_list, xisr_list_len)
! 3245: struct secpolicy *sp;
! 3246: struct sadb_x_ipsecrequest *xisr_list;
! 3247: int xisr_list_len;
! 3248: {
! 3249: struct sadb_x_ipsecrequest *xisr_new, *xisr_old = xisr_list;
! 3250: int xisr_old_len, xisr_new_len;
! 3251: struct ipsecrequest *isr_cur;
! 3252:
! 3253: isr_cur = sp->req; /* ipsecrequest list from from sp */
! 3254:
! 3255: while (xisr_list_len > 0 && isr_cur != NULL) {
! 3256: /* Get old xisr (length field is in bytes) */
! 3257: xisr_old_len = xisr_old->sadb_x_ipsecrequest_len;
! 3258: if (xisr_old_len < sizeof(*xisr_old) ||
! 3259: xisr_old_len + sizeof(*xisr_new) > xisr_list_len) {
! 3260: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3261: "invalid ipsecrequest length. Exiting.\n");
! 3262: return -1;
! 3263: }
! 3264:
! 3265: /* Get new xisr with updated info */
! 3266: xisr_new = (struct sadb_x_ipsecrequest *)(((u_int8_t *)xisr_old) + xisr_old_len);
! 3267: xisr_new_len = xisr_new->sadb_x_ipsecrequest_len;
! 3268: if (xisr_new_len < sizeof(*xisr_new) ||
! 3269: xisr_new_len + xisr_old_len > xisr_list_len) {
! 3270: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3271: "invalid ipsecrequest length. Exiting.\n");
! 3272: return -1;
! 3273: }
! 3274:
! 3275: /* Start by migrating current ipsecrequest from SP */
! 3276: if (migrate_ph2_one_isr(sp->id, isr_cur, xisr_old, xisr_new) == -1) {
! 3277: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3278: "Unable to match and migrate isr. Exiting.\n");
! 3279: return -1;
! 3280: }
! 3281:
! 3282: /* Update pointers for next round */
! 3283: xisr_list_len -= xisr_old_len + xisr_new_len;
! 3284: xisr_old = (struct sadb_x_ipsecrequest *)(((u_int8_t *)xisr_new) +
! 3285: xisr_new_len);
! 3286:
! 3287: isr_cur = isr_cur->next; /* Get next ipsecrequest from SP */
! 3288: }
! 3289:
! 3290: /* Check we had the same amount of pairs in the MIGRATE
! 3291: as the number of ipsecrequests in the SP */
! 3292: if ((xisr_list_len != 0) || isr_cur != NULL) {
! 3293: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3294: "number of ipsecrequest does not match the one in SP.\n");
! 3295: return -1;
! 3296: }
! 3297:
! 3298: return 0;
! 3299: }
! 3300:
! 3301: /* Parse sadb_x_kmaddress extension and make local and remote
! 3302: * parameters point to the new addresses (zero copy). -1 is
! 3303: * returned on error, meaning that addresses are not usable */
! 3304: static int
! 3305: parse_kmaddress(kmaddr, local, remote)
! 3306: struct sadb_x_kmaddress *kmaddr;
! 3307: struct sockaddr **local, **remote;
! 3308: {
! 3309: int addrslen, local_len=0;
! 3310: struct ph1handle *iph1;
! 3311:
! 3312: if (kmaddr == NULL)
! 3313: return -1;
! 3314:
! 3315: /* Grab addresses in sadb_x_kmaddress extension */
! 3316: addrslen = PFKEY_EXTLEN(kmaddr) - sizeof(*kmaddr);
! 3317: if (addrslen < sizeof(struct sockaddr))
! 3318: return -1;
! 3319:
! 3320: *local = (struct sockaddr *)(kmaddr + 1);
! 3321:
! 3322: switch ((*local)->sa_family) {
! 3323: case AF_INET:
! 3324: local_len = sizeof(struct sockaddr_in);
! 3325: break;
! 3326: #ifdef INET6
! 3327: case AF_INET6:
! 3328: local_len = sizeof(struct sockaddr_in6);
! 3329: break;
! 3330: #endif
! 3331: default:
! 3332: return -1;
! 3333: }
! 3334:
! 3335: if (addrslen != PFKEY_ALIGN8(2*local_len))
! 3336: return -1;
! 3337:
! 3338: *remote = (struct sockaddr *)(((u_int8_t *)(*local)) + local_len);
! 3339:
! 3340: if ((*local)->sa_family != (*remote)->sa_family)
! 3341: return -1;
! 3342:
! 3343: return 0;
! 3344: }
! 3345:
! 3346: /* Handler of PF_KEY MIGRATE message. Helpers are above */
! 3347: static int
! 3348: pk_recvmigrate(mhp)
! 3349: caddr_t *mhp;
! 3350: {
! 3351: struct sadb_address *saddr, *daddr;
! 3352: struct sockaddr *old_saddr, *new_saddr;
! 3353: struct sockaddr *old_daddr, *new_daddr;
! 3354: struct sockaddr *old_local, *old_remote;
! 3355: struct sockaddr *local, *remote;
! 3356: struct sadb_x_kmaddress *kmaddr;
! 3357: struct sadb_x_policy *xpl;
! 3358: struct sadb_x_ipsecrequest *xisr_list;
! 3359: struct sadb_lifetime *lt;
! 3360: struct policyindex spidx;
! 3361: struct secpolicy *sp;
! 3362: struct ipsecrequest *isr_cur;
! 3363: struct secasindex *oldsaidx;
! 3364: struct ph2handle *iph2;
! 3365: struct ph1handle *iph1;
! 3366: struct ph2selector ph2sel;
! 3367: struct ph1selector ph1sel;
! 3368: u_int32_t spid;
! 3369: u_int64_t created;
! 3370: int xisr_list_len;
! 3371: int ulproto;
! 3372: struct migrate_args ma;
! 3373:
! 3374: /* Some sanity checks */
! 3375:
! 3376: if (mhp[0] == NULL
! 3377: || mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 3378: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 3379: || mhp[SADB_X_EXT_KMADDRESS] == NULL
! 3380: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 3381: plog(LLV_ERROR, LOCATION, NULL,
! 3382: "SADB_X_MIGRATE: invalid MIGRATE message received.\n");
! 3383: return -1;
! 3384: }
! 3385: kmaddr = (struct sadb_x_kmaddress *)mhp[SADB_X_EXT_KMADDRESS];
! 3386: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 3387: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 3388: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 3389: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 3390: if (lt != NULL)
! 3391: created = lt->sadb_lifetime_addtime;
! 3392: else
! 3393: created = 0;
! 3394:
! 3395: if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
! 3396: plog(LLV_WARNING, LOCATION, NULL,"SADB_X_MIGRATE: "
! 3397: "found non IPsec policy in MIGRATE message. Exiting.\n");
! 3398: return -1;
! 3399: }
! 3400:
! 3401: if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
! 3402: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3403: "invalid size for sadb_x_policy. Exiting.\n");
! 3404: return -1;
! 3405: }
! 3406:
! 3407: /* Some logging to help debbugging */
! 3408: if (xpl->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
! 3409: plog(LLV_DEBUG, LOCATION, NULL,
! 3410: "SADB_X_MIGRATE: Outbound SA being migrated.\n");
! 3411: else
! 3412: plog(LLV_DEBUG, LOCATION, NULL,
! 3413: "SADB_X_MIGRATE: Inbound SA being migrated.\n");
! 3414:
! 3415: /* validity check */
! 3416: xisr_list = (struct sadb_x_ipsecrequest *)(xpl + 1);
! 3417: xisr_list_len = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
! 3418: if (xisr_list_len < sizeof(*xisr_list)) {
! 3419: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3420: "invalid sadb_x_policy message length. Exiting.\n");
! 3421: return -1;
! 3422: }
! 3423:
! 3424: if (parse_kmaddress(kmaddr, &local, &remote) == -1) {
! 3425: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
! 3426: "invalid sadb_x_kmaddress extension. Exiting.\n");
! 3427: return -1;
! 3428: }
! 3429:
! 3430: /* 0 means ANY */
! 3431: if (saddr->sadb_address_proto == 0)
! 3432: ulproto = IPSEC_ULPROTO_ANY;
! 3433: else
! 3434: ulproto = saddr->sadb_address_proto;
! 3435:
! 3436: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 3437: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 3438: saddr + 1,
! 3439: daddr + 1,
! 3440: saddr->sadb_address_prefixlen,
! 3441: daddr->sadb_address_prefixlen,
! 3442: ulproto,
! 3443: xpl->sadb_x_policy_priority,
! 3444: created,
! 3445: &spidx);
! 3446: #else
! 3447: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 3448: saddr + 1,
! 3449: daddr + 1,
! 3450: saddr->sadb_address_prefixlen,
! 3451: daddr->sadb_address_prefixlen,
! 3452: ulproto,
! 3453: created,
! 3454: &spidx);
! 3455: #endif
! 3456:
! 3457: /* Everything seems ok, let's get the SP.
! 3458: *
! 3459: * XXX We could also do the lookup using the spid from xpl.
! 3460: * I don't know which one is better. --arno */
! 3461: sp = getsp(&spidx);
! 3462: if (sp == NULL) {
! 3463: plog(LLV_ERROR, LOCATION, NULL,
! 3464: "SADB_X_MIGRATE: Passed policy does not exist: %s\n",
! 3465: spidx2str(&spidx));
! 3466: return -1;
! 3467: }
! 3468:
! 3469: /* Get the best source and destination addresses used for IKE
! 3470: * negotiation, to find and migrate existing Phase 1 */
! 3471: if (sp->local && sp->remote) {
! 3472: /* hints available, let's use them */
! 3473: old_local = (struct sockaddr *)sp->local;
! 3474: old_remote = (struct sockaddr *)sp->remote;
! 3475: } else if (sp->req && sp->req->saidx.mode == IPSEC_MODE_TUNNEL) {
! 3476: /* Tunnel mode and no hint, use endpoints */
! 3477: old_local = (struct sockaddr *)&sp->req->saidx.src;
! 3478: old_remote = (struct sockaddr *)&sp->req->saidx.dst;
! 3479: } else {
! 3480: /* default, use selectors as fallback */
! 3481: old_local = (struct sockaddr *)&sp->spidx.src;
! 3482: old_remote = (struct sockaddr *)&sp->spidx.dst;
! 3483: }
! 3484:
! 3485: /* We migrate all Phase 1 that match our old local and remote
! 3486: * addresses (no matter their state).
! 3487: *
! 3488: * XXX In fact, we should probably havea special treatment for
! 3489: * Phase 1 that are being established when we receive a MIGRATE.
! 3490: * This can happen if a movement occurs during the initial IKE
! 3491: * negotiation. In that case, I wonder if should restart the
! 3492: * negotiation from the new address or just update things like
! 3493: * we do it now.
! 3494: *
! 3495: * XXX while looking at getph1byaddr(), the comment at the
! 3496: * beginning of the function expects comparison to happen
! 3497: * without ports considerations but it uses CMPSADDR() which
! 3498: * relies either on cmpsaddrstrict() or cmpsaddrwop() based
! 3499: * on NAT-T support being activated. That make me wonder if I
! 3500: * should force ports to 0 (ANY) in local and remote values
! 3501: * used below.
! 3502: *
! 3503: * -- arno */
! 3504:
! 3505: /* Apply callback data ...*/
! 3506: memset(&ma, 0, sizeof(ma));
! 3507: ma.local = local;
! 3508: ma.remote = remote;
! 3509:
! 3510: /* Fill phase1 match criteria ... */
! 3511: memset(&ph1sel, 0, sizeof(ph1sel));
! 3512: ph1sel.local = old_local;
! 3513: ph1sel.remote = old_remote;
! 3514:
! 3515:
! 3516: /* Have matching Phase 1 found and addresses updated. As this is a
! 3517: * time consuming task on a busy responder, and MIGRATE messages
! 3518: * are always sent for *both* inbound and outbound (and possibly
! 3519: * forward), we only do that for outbound SP. */
! 3520: if (xpl->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND &&
! 3521: enumph1(&ph1sel, migrate_ph1_ike_addresses, &ma) < 0) {
! 3522: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: Unable "
! 3523: "to migrate Phase 1 addresses.\n");
! 3524: return -1;
! 3525: }
! 3526:
! 3527: /* We can now update IKE addresses in Phase 2 handle. */
! 3528: memset(&ph2sel, 0, sizeof(ph2sel));
! 3529: ph2sel.spid = sp->id;
! 3530: if (enumph2(&ph2sel, migrate_ph2_ike_addresses, &ma) < 0) {
! 3531: plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: Unable "
! 3532: "to migrate Phase 2 IKE addresses.\n");
! 3533: return -1;
! 3534: }
! 3535:
! 3536: /* and _then_ in SP. */
! 3537: if (migrate_sp_ike_addresses(sp, local, remote) < 0) {
! 3538: plog(LLV_ERROR, LOCATION, NULL,
! 3539: "SADB_X_MIGRATE: Unable to migrate SP IKE addresses.\n");
! 3540: return -1;
! 3541: }
! 3542:
! 3543: /* Loop on sadb_x_ipsecrequest list to possibly update sp->req
! 3544: * entries and associated live Phase 2 handles (their sa_src
! 3545: * and sa_dst) */
! 3546: if (migrate_sp_isr_list(sp, xisr_list, xisr_list_len) < 0) {
! 3547: plog(LLV_ERROR, LOCATION, NULL,
! 3548: "SADB_X_MIGRATE: Unable to migrate isr list.\n");
! 3549: return -1;
! 3550: }
! 3551:
! 3552: return 0;
! 3553: }
! 3554: #endif
! 3555:
! 3556: /*
! 3557: * send error against acquire message to kernel.
! 3558: */
! 3559: int
! 3560: pk_sendeacquire(iph2)
! 3561: struct ph2handle *iph2;
! 3562: {
! 3563: struct sadb_msg *newmsg;
! 3564: int len;
! 3565:
! 3566: len = sizeof(struct sadb_msg);
! 3567: newmsg = racoon_calloc(1, len);
! 3568: if (newmsg == NULL) {
! 3569: plog(LLV_ERROR, LOCATION, NULL,
! 3570: "failed to get buffer to send acquire.\n");
! 3571: return -1;
! 3572: }
! 3573:
! 3574: memset(newmsg, 0, len);
! 3575: newmsg->sadb_msg_version = PF_KEY_V2;
! 3576: newmsg->sadb_msg_type = SADB_ACQUIRE;
! 3577: newmsg->sadb_msg_errno = ENOENT; /* XXX */
! 3578: newmsg->sadb_msg_satype = iph2->satype;
! 3579: newmsg->sadb_msg_len = PFKEY_UNIT64(len);
! 3580: newmsg->sadb_msg_reserved = 0;
! 3581: newmsg->sadb_msg_seq = iph2->seq;
! 3582: newmsg->sadb_msg_pid = (u_int32_t)getpid();
! 3583:
! 3584: /* send message */
! 3585: len = pfkey_send(lcconf->sock_pfkey, newmsg, len);
! 3586:
! 3587: racoon_free(newmsg);
! 3588:
! 3589: return 0;
! 3590: }
! 3591:
! 3592: /*
! 3593: * check if the algorithm is supported or not.
! 3594: * OUT 0: ok
! 3595: * -1: ng
! 3596: */
! 3597: int
! 3598: pk_checkalg(class, calg, keylen)
! 3599: int class, calg, keylen;
! 3600: {
! 3601: int sup, error;
! 3602: u_int alg;
! 3603: struct sadb_alg alg0;
! 3604:
! 3605: switch (algclass2doi(class)) {
! 3606: case IPSECDOI_PROTO_IPSEC_ESP:
! 3607: sup = SADB_EXT_SUPPORTED_ENCRYPT;
! 3608: break;
! 3609: case IPSECDOI_ATTR_AUTH:
! 3610: sup = SADB_EXT_SUPPORTED_AUTH;
! 3611: break;
! 3612: case IPSECDOI_PROTO_IPCOMP:
! 3613: plog(LLV_DEBUG, LOCATION, NULL,
! 3614: "no check of compression algorithm; "
! 3615: "not supported in sadb message.\n");
! 3616: return 0;
! 3617: default:
! 3618: plog(LLV_ERROR, LOCATION, NULL,
! 3619: "invalid algorithm class.\n");
! 3620: return -1;
! 3621: }
! 3622: alg = ipsecdoi2pfkey_alg(algclass2doi(class), algtype2doi(class, calg));
! 3623: if (alg == ~0)
! 3624: return -1;
! 3625:
! 3626: if (keylen == 0) {
! 3627: if (ipsec_get_keylen(sup, alg, &alg0)) {
! 3628: plog(LLV_ERROR, LOCATION, NULL,
! 3629: "%s.\n", ipsec_strerror());
! 3630: return -1;
! 3631: }
! 3632: keylen = alg0.sadb_alg_minbits;
! 3633: }
! 3634:
! 3635: error = ipsec_check_keylen(sup, alg, keylen);
! 3636: if (error)
! 3637: plog(LLV_ERROR, LOCATION, NULL,
! 3638: "%s.\n", ipsec_strerror());
! 3639:
! 3640: return error;
! 3641: }
! 3642:
! 3643: /*
! 3644: * differences with pfkey_recv() in libipsec/pfkey.c:
! 3645: * - never performs busy wait loop.
! 3646: * - returns NULL and set *lenp to negative on fatal failures
! 3647: * - returns NULL and set *lenp to non-negative on non-fatal failures
! 3648: * - returns non-NULL on success
! 3649: */
! 3650: static struct sadb_msg *
! 3651: pk_recv(so, lenp)
! 3652: int so;
! 3653: int *lenp;
! 3654: {
! 3655: struct sadb_msg buf, *newmsg;
! 3656: int reallen;
! 3657: int retry = 0;
! 3658:
! 3659: *lenp = -1;
! 3660: do
! 3661: {
! 3662: plog(LLV_DEBUG, LOCATION, NULL, "pk_recv: retry[%d] recv() \n", retry );
! 3663: *lenp = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT);
! 3664: retry++;
! 3665: }
! 3666: while (*lenp < 0 && errno == EAGAIN && retry < 3);
! 3667:
! 3668: if (*lenp < 0)
! 3669: return NULL; /*fatal*/
! 3670:
! 3671: else if (*lenp < sizeof(buf))
! 3672: return NULL;
! 3673:
! 3674: reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
! 3675: if (reallen < sizeof(buf)) {
! 3676: *lenp = -1;
! 3677: errno = EIO;
! 3678: return NULL; /*fatal*/
! 3679: }
! 3680: if ((newmsg = racoon_calloc(1, reallen)) == NULL)
! 3681: return NULL;
! 3682:
! 3683: *lenp = recv(so, (caddr_t)newmsg, reallen, MSG_PEEK);
! 3684: if (*lenp < 0) {
! 3685: racoon_free(newmsg);
! 3686: return NULL; /*fatal*/
! 3687: } else if (*lenp != reallen) {
! 3688: racoon_free(newmsg);
! 3689: return NULL;
! 3690: }
! 3691:
! 3692: *lenp = recv(so, (caddr_t)newmsg, reallen, 0);
! 3693: if (*lenp < 0) {
! 3694: racoon_free(newmsg);
! 3695: return NULL; /*fatal*/
! 3696: } else if (*lenp != reallen) {
! 3697: racoon_free(newmsg);
! 3698: return NULL;
! 3699: }
! 3700:
! 3701: return newmsg;
! 3702: }
! 3703:
! 3704: /* see handler.h */
! 3705: u_int32_t
! 3706: pk_getseq()
! 3707: {
! 3708: return eay_random();
! 3709: }
! 3710:
! 3711: static int
! 3712: addnewsp(mhp, local, remote)
! 3713: caddr_t *mhp;
! 3714: struct sockaddr *local, *remote;
! 3715: {
! 3716: struct secpolicy *new = NULL;
! 3717: struct sadb_address *saddr, *daddr;
! 3718: struct sadb_x_policy *xpl;
! 3719: struct sadb_lifetime *lt;
! 3720: u_int64_t created;
! 3721:
! 3722: /* sanity check */
! 3723: if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
! 3724: || mhp[SADB_EXT_ADDRESS_DST] == NULL
! 3725: || mhp[SADB_X_EXT_POLICY] == NULL) {
! 3726: plog(LLV_ERROR, LOCATION, NULL,
! 3727: "inappropriate sadb spd management message passed.\n");
! 3728: goto bad;
! 3729: }
! 3730:
! 3731: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 3732: daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 3733: xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
! 3734: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 3735: if(lt != NULL)
! 3736: created = lt->sadb_lifetime_addtime;
! 3737: else
! 3738: created = 0;
! 3739: lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
! 3740: if(lt != NULL)
! 3741: created = lt->sadb_lifetime_addtime;
! 3742: else
! 3743: created = 0;
! 3744:
! 3745: #ifdef __linux__
! 3746: /* bsd skips over per-socket policies because there will be no
! 3747: * src and dst extensions in spddump messages. On Linux the only
! 3748: * way to achieve the same is check for policy id.
! 3749: */
! 3750: if (xpl->sadb_x_policy_id % 8 >= 3) return 0;
! 3751: #endif
! 3752:
! 3753: new = newsp();
! 3754: if (new == NULL) {
! 3755: plog(LLV_ERROR, LOCATION, NULL,
! 3756: "failed to allocate buffer\n");
! 3757: goto bad;
! 3758: }
! 3759:
! 3760: new->spidx.dir = xpl->sadb_x_policy_dir;
! 3761: new->id = xpl->sadb_x_policy_id;
! 3762: new->policy = xpl->sadb_x_policy_type;
! 3763: new->req = NULL;
! 3764:
! 3765: /* check policy */
! 3766: switch (xpl->sadb_x_policy_type) {
! 3767: case IPSEC_POLICY_DISCARD:
! 3768: case IPSEC_POLICY_NONE:
! 3769: case IPSEC_POLICY_ENTRUST:
! 3770: case IPSEC_POLICY_BYPASS:
! 3771: break;
! 3772:
! 3773: case IPSEC_POLICY_IPSEC:
! 3774: {
! 3775: int tlen;
! 3776: struct sadb_x_ipsecrequest *xisr;
! 3777: struct ipsecrequest **p_isr = &new->req;
! 3778:
! 3779: /* validity check */
! 3780: if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
! 3781: plog(LLV_ERROR, LOCATION, NULL,
! 3782: "invalid msg length.\n");
! 3783: goto bad;
! 3784: }
! 3785:
! 3786: tlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
! 3787: xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
! 3788:
! 3789: while (tlen > 0) {
! 3790:
! 3791: /* length check */
! 3792: if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
! 3793: plog(LLV_ERROR, LOCATION, NULL,
! 3794: "invalid msg length.\n");
! 3795: goto bad;
! 3796: }
! 3797:
! 3798: /* allocate request buffer */
! 3799: *p_isr = newipsecreq();
! 3800: if (*p_isr == NULL) {
! 3801: plog(LLV_ERROR, LOCATION, NULL,
! 3802: "failed to get new ipsecreq.\n");
! 3803: goto bad;
! 3804: }
! 3805:
! 3806: /* set values */
! 3807: (*p_isr)->next = NULL;
! 3808:
! 3809: switch (xisr->sadb_x_ipsecrequest_proto) {
! 3810: case IPPROTO_ESP:
! 3811: case IPPROTO_AH:
! 3812: case IPPROTO_IPCOMP:
! 3813: break;
! 3814: default:
! 3815: plog(LLV_ERROR, LOCATION, NULL,
! 3816: "invalid proto type: %u\n",
! 3817: xisr->sadb_x_ipsecrequest_proto);
! 3818: goto bad;
! 3819: }
! 3820: (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
! 3821:
! 3822: switch (xisr->sadb_x_ipsecrequest_mode) {
! 3823: case IPSEC_MODE_TRANSPORT:
! 3824: case IPSEC_MODE_TUNNEL:
! 3825: break;
! 3826: case IPSEC_MODE_ANY:
! 3827: default:
! 3828: plog(LLV_ERROR, LOCATION, NULL,
! 3829: "invalid mode: %u\n",
! 3830: xisr->sadb_x_ipsecrequest_mode);
! 3831: goto bad;
! 3832: }
! 3833: (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
! 3834:
! 3835: switch (xisr->sadb_x_ipsecrequest_level) {
! 3836: case IPSEC_LEVEL_DEFAULT:
! 3837: case IPSEC_LEVEL_USE:
! 3838: case IPSEC_LEVEL_REQUIRE:
! 3839: break;
! 3840: case IPSEC_LEVEL_UNIQUE:
! 3841: (*p_isr)->saidx.reqid =
! 3842: xisr->sadb_x_ipsecrequest_reqid;
! 3843: break;
! 3844:
! 3845: default:
! 3846: plog(LLV_ERROR, LOCATION, NULL,
! 3847: "invalid level: %u\n",
! 3848: xisr->sadb_x_ipsecrequest_level);
! 3849: goto bad;
! 3850: }
! 3851: (*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
! 3852:
! 3853: /* set IP addresses if there */
! 3854: if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
! 3855: struct sockaddr *paddr;
! 3856:
! 3857: paddr = (struct sockaddr *)(xisr + 1);
! 3858: bcopy(paddr, &(*p_isr)->saidx.src,
! 3859: sysdep_sa_len(paddr));
! 3860:
! 3861: paddr = (struct sockaddr *)((caddr_t)paddr
! 3862: + sysdep_sa_len(paddr));
! 3863: bcopy(paddr, &(*p_isr)->saidx.dst,
! 3864: sysdep_sa_len(paddr));
! 3865: }
! 3866:
! 3867: (*p_isr)->sp = new;
! 3868:
! 3869: /* initialization for the next. */
! 3870: p_isr = &(*p_isr)->next;
! 3871: tlen -= xisr->sadb_x_ipsecrequest_len;
! 3872:
! 3873: /* validity check */
! 3874: if (tlen < 0) {
! 3875: plog(LLV_ERROR, LOCATION, NULL,
! 3876: "becoming tlen < 0\n");
! 3877: }
! 3878:
! 3879: xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
! 3880: + xisr->sadb_x_ipsecrequest_len);
! 3881: }
! 3882: }
! 3883: break;
! 3884: default:
! 3885: plog(LLV_ERROR, LOCATION, NULL,
! 3886: "invalid policy type.\n");
! 3887: goto bad;
! 3888: }
! 3889:
! 3890: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 3891: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 3892: saddr + 1,
! 3893: daddr + 1,
! 3894: saddr->sadb_address_prefixlen,
! 3895: daddr->sadb_address_prefixlen,
! 3896: saddr->sadb_address_proto,
! 3897: xpl->sadb_x_policy_priority,
! 3898: created,
! 3899: &new->spidx);
! 3900: #else
! 3901: KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
! 3902: saddr + 1,
! 3903: daddr + 1,
! 3904: saddr->sadb_address_prefixlen,
! 3905: daddr->sadb_address_prefixlen,
! 3906: saddr->sadb_address_proto,
! 3907: created,
! 3908: &new->spidx);
! 3909: #endif
! 3910:
! 3911: #ifdef HAVE_SECCTX
! 3912: if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
! 3913: struct sadb_x_sec_ctx *ctx;
! 3914:
! 3915: ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
! 3916: new->spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
! 3917: new->spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
! 3918: new->spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
! 3919: memcpy(new->spidx.sec_ctx.ctx_str,ctx + 1,ctx->sadb_x_ctx_len);
! 3920: }
! 3921: #endif /* HAVE_SECCTX */
! 3922:
! 3923: /* Set local and remote hints for that SP, if available */
! 3924: if (local && remote) {
! 3925: new->local = dupsaddr(local);
! 3926: new->remote = dupsaddr(remote);
! 3927: }
! 3928:
! 3929: inssp(new);
! 3930:
! 3931: return 0;
! 3932: bad:
! 3933: if (new != NULL) {
! 3934: if (new->req != NULL)
! 3935: racoon_free(new->req);
! 3936: racoon_free(new);
! 3937: }
! 3938: return -1;
! 3939: }
! 3940:
! 3941: /* proto/mode/src->dst spi */
! 3942: const char *
! 3943: sadbsecas2str(src, dst, proto, spi, mode)
! 3944: struct sockaddr *src, *dst;
! 3945: int proto;
! 3946: u_int32_t spi;
! 3947: int mode;
! 3948: {
! 3949: static char buf[256];
! 3950: u_int doi_proto, doi_mode = 0;
! 3951: char *p;
! 3952: int blen, i;
! 3953:
! 3954: doi_proto = pfkey2ipsecdoi_proto(proto);
! 3955: if (doi_proto == ~0)
! 3956: return NULL;
! 3957: if (mode) {
! 3958: doi_mode = pfkey2ipsecdoi_mode(mode);
! 3959: if (doi_mode == ~0)
! 3960: return NULL;
! 3961: }
! 3962:
! 3963: blen = sizeof(buf) - 1;
! 3964: p = buf;
! 3965:
! 3966: i = snprintf(p, blen, "%s%s%s ",
! 3967: s_ipsecdoi_proto(doi_proto),
! 3968: mode ? "/" : "",
! 3969: mode ? s_ipsecdoi_encmode(doi_mode) : "");
! 3970: if (i < 0 || i >= blen)
! 3971: return NULL;
! 3972: p += i;
! 3973: blen -= i;
! 3974:
! 3975: i = snprintf(p, blen, "%s->", saddr2str(src));
! 3976: if (i < 0 || i >= blen)
! 3977: return NULL;
! 3978: p += i;
! 3979: blen -= i;
! 3980:
! 3981: i = snprintf(p, blen, "%s ", saddr2str(dst));
! 3982: if (i < 0 || i >= blen)
! 3983: return NULL;
! 3984: p += i;
! 3985: blen -= i;
! 3986:
! 3987: if (spi) {
! 3988: snprintf(p, blen, "spi=%lu(0x%lx)", (unsigned long)ntohl(spi),
! 3989: (unsigned long)ntohl(spi));
! 3990: }
! 3991:
! 3992: return buf;
! 3993: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>