Return to pfkey.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
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: }