X-Git-Url: https://git.saurik.com/apple/ipsec.git/blobdiff_plain/05434fec7cb5667469bfde135b4d0a93524a9bc0..c8d8bee0bee0298e25cb827876f57e58cc0a938c:/ipsec-tools/racoon/pfkey_racoon.c diff --git a/ipsec-tools/racoon/pfkey_racoon.c b/ipsec-tools/racoon/pfkey_racoon.c index 76ecbc3..63c61dd 100644 --- a/ipsec-tools/racoon/pfkey_racoon.c +++ b/ipsec-tools/racoon/pfkey_racoon.c @@ -30,6 +30,7 @@ */ #include "config.h" +#include "racoon_types.h" #include #include @@ -44,12 +45,7 @@ #include #ifdef ENABLE_NATT -# ifdef __linux__ -# include -# endif -# if defined(__NetBSD__) || defined(__FreeBSD__) -# include -# endif +#include #endif #include @@ -59,11 +55,7 @@ #include #include -#ifdef __APPLE__ -#include -#else #include -#endif #include #ifndef HAVE_NETINET6_IPSEC @@ -80,6 +72,8 @@ #include "plog.h" #include "sockmisc.h" #include "debug.h" +#include "fsm.h" +#include "ike_session.h" #include "schedule.h" #include "localconf.h" @@ -95,47 +89,50 @@ #include "algorithm.h" #include "sainfo.h" #include "proposal.h" -#include "admin.h" -#include "privsep.h" #include "strnames.h" -#include "backupsa.h" #include "gcmalloc.h" #include "nattraversal.h" #include "crypto_openssl.h" #include "grabmyaddr.h" #include "vpn_control.h" #include "vpn_control_var.h" +#include "ike_session.h" +#include "ipsecSessionTracer.h" +#include "ipsecMessageTracer.h" +#include "power_mgmt.h" +#include "session.h" #if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC) #define SADB_X_EALG_AESCBC SADB_X_EALG_RIJNDAELCBC #endif /* prototype */ -static u_int ipsecdoi2pfkey_aalg __P((u_int)); -static u_int ipsecdoi2pfkey_ealg __P((u_int)); -static u_int ipsecdoi2pfkey_calg __P((u_int)); -static u_int ipsecdoi2pfkey_alg __P((u_int, u_int)); -static u_int keylen_aalg __P((u_int)); -static u_int keylen_ealg __P((u_int, int)); - -static int pk_recvgetspi __P((caddr_t *)); -static int pk_recvupdate __P((caddr_t *)); -static int pk_recvadd __P((caddr_t *)); -static int pk_recvdelete __P((caddr_t *)); -static int pk_recvacquire __P((caddr_t *)); -static int pk_recvexpire __P((caddr_t *)); -static int pk_recvflush __P((caddr_t *)); -static int getsadbpolicy __P((caddr_t *, int *, int, struct ph2handle *)); -static int pk_recvspdupdate __P((caddr_t *)); -static int pk_recvspdadd __P((caddr_t *)); -static int pk_recvspddelete __P((caddr_t *)); -static int pk_recvspdexpire __P((caddr_t *)); -static int pk_recvspdget __P((caddr_t *)); -static int pk_recvspddump __P((caddr_t *)); -static int pk_recvspdflush __P((caddr_t *)); -static struct sadb_msg *pk_recv __P((int, int *)); - -static int (*pkrecvf[]) __P((caddr_t *)) = { +static u_int ipsecdoi2pfkey_aalg (u_int); +static u_int ipsecdoi2pfkey_ealg (u_int); +static u_int ipsecdoi2pfkey_calg (u_int); +static u_int ipsecdoi2pfkey_alg (u_int, u_int); +static u_int keylen_aalg (u_int); +static u_int keylen_ealg (u_int, int); + +static int pk_recvgetspi (caddr_t *); +static int pk_recvupdate (caddr_t *); +static int pk_recvadd (caddr_t *); +static int pk_recvdelete (caddr_t *); +static int pk_recvacquire (caddr_t *); +static int pk_recvexpire (caddr_t *); +static int pk_recvflush (caddr_t *); +static int getsadbpolicy (caddr_t *, int *, int, phase2_handle_t *); +static int pk_recvspdupdate (caddr_t *); +static int pk_recvspdadd (caddr_t *); +static int pk_recvspddelete (caddr_t *); +static int pk_recvspdexpire (caddr_t *); +static int pk_recvspdget (caddr_t *); +static int pk_recvspddump (caddr_t *); +static int pk_recvspdflush (caddr_t *); +static int pk_recvgetsastat (caddr_t *); +static struct sadb_msg *pk_recv (int, ssize_t *); + +static int (*pkrecvf[]) (caddr_t *) = { NULL, pk_recvgetspi, pk_recvupdate, @@ -159,14 +156,16 @@ pk_recvspdflush, NULL, /* SADB_X_SPDSETIDX */ pk_recvspdexpire, NULL, /* SADB_X_SPDDELETE2 */ -NULL, /* SADB_X_NAT_T_NEW_MAPPING */ -NULL, /* SADB_X_MIGRATE */ -#if (SADB_MAX > 24) -#error "SADB extra message?" +pk_recvgetsastat, /* SADB_GETSASTAT */ +NULL, /* SADB_X_SPDENABLE */ +NULL, /* SADB_X_SPDDISNABLE */ +NULL, /* SADB_MIGRATE */ +#if (SADB_MAX > 26) +#warning "SADB extra message?" #endif }; -static int addnewsp __P((caddr_t *)); +static int addnewsp (caddr_t *); /* cope with old kame headers - ugly */ #ifndef SADB_X_AALG_MD5 @@ -191,82 +190,60 @@ static int addnewsp __P((caddr_t *)); #endif #endif -/* - * PF_KEY packet handler - * 0: success - * -1: fail - */ int -pfkey_handler() -{ +pfkey_process(msg) struct sadb_msg *msg; - int len; +{ caddr_t mhp[SADB_EXT_MAX + 1]; int error = -1; - - /* receive pfkey message. */ - len = 0; - msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len); - if (msg == NULL) { - if (len < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to recv from pfkey (%s)\n", - strerror(errno)); - goto end; - } else { - /* short message - msg not ready */ - return 0; - } - } - - plog(LLV_DEBUG, LOCATION, NULL, "get pfkey %s message\n", - s_pfkey_type(msg->sadb_msg_type)); - plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3); + + // Special debug use only - creates large logs + // plogdump(ASL_LEVEL_DEBUG, msg, msg->sadb_msg_len << 3, "get pfkey %s message\n", + // s_pfkey_type(msg->sadb_msg_type)); /* validity check */ + /* check pfkey message. */ + if (pfkey_align(msg, mhp)) { + plog(ASL_LEVEL_ERR, + "libipsec failed pfkey align (%s)\n", + ipsec_strerror()); + goto end; + } + if (pfkey_check(mhp)) { + plog(ASL_LEVEL_ERR, + "libipsec failed pfkey check (%s)\n", + ipsec_strerror()); + goto end; + } + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + if (msg->sadb_msg_errno) { int pri; /* when SPD is empty, treat the state as no error. */ if (msg->sadb_msg_type == SADB_X_SPDDUMP && msg->sadb_msg_errno == ENOENT) - pri = LLV_DEBUG; + pri = ASL_LEVEL_DEBUG; else - pri = LLV_ERROR; + pri = ASL_LEVEL_ERR; - plog(pri, LOCATION, NULL, + plog(pri, "pfkey %s failed: %s\n", s_pfkey_type(msg->sadb_msg_type), strerror(msg->sadb_msg_errno)); - goto end; } - - /* check pfkey message. */ - if (pfkey_align(msg, mhp)) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed pfkey align (%s)\n", - ipsec_strerror()); - goto end; - } - if (pfkey_check(mhp)) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed pfkey check (%s)\n", - ipsec_strerror()); - goto end; - } - msg = (struct sadb_msg *)mhp[0]; - + /* safety check */ if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "unknown PF_KEY message type=%u\n", msg->sadb_msg_type); goto end; } if (pkrecvf[msg->sadb_msg_type] == NULL) { - plog(LLV_INFO, LOCATION, NULL, + plog(ASL_LEVEL_INFO, "unsupported PF_KEY message %s\n", s_pfkey_type(msg->sadb_msg_type)); goto end; @@ -282,6 +259,78 @@ end: return(error); } +/* + * PF_KEY packet handler + * 0: success + * -1: fail + */ + +//%%%%%%%%%%%%%%%%%% need to handle errors encountered here - this no longer returns a result +void +pfkey_handler(void *unused) +{ + struct sadb_msg *msg; + ssize_t len; + + if (slept_at || woke_at) { + plog(ASL_LEVEL_DEBUG, + "ignoring pfkey port until power-mgmt event is handled.\n"); + return; + } + + /* receive pfkey message. */ + len = 0; + msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len); + + if (msg == NULL) { + if (len < 0) { + plog(ASL_LEVEL_ERR, + "failed to recv from pfkey (%s)\n", + strerror(errno)); + return; + } else { + /* short message - msg not ready */ + plog(ASL_LEVEL_DEBUG, "recv short message from pfkey\n"); + return; + } + } + pfkey_process(msg); +} + +void +pfkey_post_handler() +{ + struct saved_msg_elem *elem; + struct saved_msg_elem *elem_tmp = NULL; + + if (slept_at || woke_at) { + plog(ASL_LEVEL_DEBUG, + "ignoring (saved) pfkey messages until power-mgmt event is handled.\n"); + return; + } + + TAILQ_FOREACH_SAFE(elem, &lcconf->saved_msg_queue, chain, elem_tmp) { + pfkey_process((struct sadb_msg *)elem->msg); + TAILQ_REMOVE(&lcconf->saved_msg_queue, elem, chain); + racoon_free(elem); + + } +} + +int +pfkey_save_msg(msg) + struct sadb_msg *msg; +{ + struct saved_msg_elem *elem; + + elem = (struct saved_msg_elem *)racoon_calloc(sizeof(struct saved_msg_elem), 1); + if (elem == NULL) + return -1; + elem->msg = msg; + TAILQ_INSERT_TAIL(&lcconf->saved_msg_queue, elem, chain); + return 0; +} + /* * dump SADB */ @@ -294,18 +343,18 @@ pfkey_dump_sadb(satype) pid_t pid = getpid(); struct sadb_msg *msg = NULL; size_t bl, ml; - int len; + ssize_t len; - if ((s = privsep_pfkey_open()) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + if ((s = pfkey_open()) < 0) { + plog(ASL_LEVEL_ERR, "libipsec failed pfkey open: %s\n", ipsec_strerror()); return NULL; } - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_dump\n"); if (pfkey_send_dump(s, satype) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "libipsec failed dump: %s\n", ipsec_strerror()); goto fail; } @@ -321,14 +370,25 @@ pfkey_dump_sadb(satype) continue; } - if (msg->sadb_msg_type != SADB_DUMP || msg->sadb_msg_pid != pid) + /* + * for multi-processor system this had to be added because the messages can + * be interleaved - they won't all be dump messages + */ + if (msg->sadb_msg_type != SADB_DUMP) { /* save for later processing */ + pfkey_save_msg(msg); + msg = NULL; + continue; + } + + // ignore dump messages that aren't racoon's + if (msg->sadb_msg_pid != pid) continue; ml = msg->sadb_msg_len << 3; bl = buf ? buf->l : 0; buf = vrealloc(buf, bl + ml); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to reallocate buffer to dump.\n"); goto fail; } @@ -347,34 +407,10 @@ done: if (msg) racoon_free(msg); if (s >= 0) - privsep_pfkey_close(s); + pfkey_close_sock(s); return buf; } -#ifdef ENABLE_ADMINPORT -/* - * flush SADB - */ -void -pfkey_flush_sadb(proto) - u_int proto; -{ - int satype; - - /* convert to SADB_SATYPE */ - if ((satype = admin2pfkey_proto(proto)) < 0) - return; - - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_flush\n"); - if (pfkey_send_flush(lcconf->sock_pfkey, satype) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed send flush (%s)\n", ipsec_strerror()); - return; - } - - return; -} -#endif /* * These are the SATYPEs that we manage. We register to get @@ -394,24 +430,24 @@ const int pfkey_nsatypes = * PF_KEY initialization */ int -pfkey_init() +pfkey_init(void) { - int i, reg_fail; + int i, reg_fail, sock; - if ((lcconf->sock_pfkey = privsep_pfkey_open()) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + if ((lcconf->sock_pfkey = pfkey_open()) < 0) { + plog(ASL_LEVEL_ERR, "libipsec failed pfkey open (%s)\n", ipsec_strerror()); return -1; } for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "call pfkey_send_register for %s\n", pfkey_satypes[i].ps_name); if (pfkey_send_register(lcconf->sock_pfkey, pfkey_satypes[i].ps_satype) < 0 || pfkey_recv_register(lcconf->sock_pfkey) < 0) { - plog(LLV_WARNING, LOCATION, NULL, + plog(ASL_LEVEL_WARNING, "failed to register %s (%s)\n", pfkey_satypes[i].ps_name, ipsec_strerror()); @@ -420,30 +456,50 @@ pfkey_init() } if (reg_fail == pfkey_nsatypes) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to regist any protocol.\n"); - pfkey_close(lcconf->sock_pfkey); + close(lcconf->sock_pfkey); return -1; } - - initsp(); + initsp(); + + lcconf->pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_pfkey, 0, dispatch_get_main_queue()); + if (lcconf->pfkey_source == NULL) { + plog(ASL_LEVEL_ERR, "could not create pfkey socket source."); + return -1; + } + dispatch_source_set_event_handler_f(lcconf->pfkey_source, pfkey_handler); + sock = lcconf->sock_pfkey; + dispatch_source_set_cancel_handler(lcconf->pfkey_source, + ^{ + pfkey_close_sock(sock); + }); + dispatch_resume(lcconf->pfkey_source); if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "libipsec sending spddump failed: %s\n", ipsec_strerror()); - pfkey_close(lcconf->sock_pfkey); + pfkey_close(); return -1; } #if 0 if (pfkey_promisc_toggle(1) < 0) { - pfkey_close(lcconf->sock_pfkey); + pfkey_close(); return -1; } #endif + return 0; } +void +pfkey_close(void) +{ + dispatch_source_cancel(lcconf->pfkey_source); + lcconf->pfkey_source = NULL; +} + /* %%% for conversion */ /* IPSECDOI_ATTR_AUTH -> SADB_AALG */ static u_int @@ -451,44 +507,46 @@ ipsecdoi2pfkey_aalg(hashtype) u_int hashtype; { switch (hashtype) { - case IPSECDOI_ATTR_AUTH_HMAC_MD5: - return SADB_AALG_MD5HMAC; - case IPSECDOI_ATTR_AUTH_HMAC_SHA1: - return SADB_AALG_SHA1HMAC; - case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256: + case IPSECDOI_ATTR_AUTH_HMAC_MD5: + case IPSECDOI_ATTR_AUTH_HMAC_MD5_96: + return SADB_AALG_MD5HMAC; + case IPSECDOI_ATTR_AUTH_HMAC_SHA1: + case IPSECDOI_ATTR_AUTH_HMAC_SHA1_96: + return SADB_AALG_SHA1HMAC; + case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256: #if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC) - return SADB_X_AALG_SHA2_256; + return SADB_X_AALG_SHA2_256; #else - return SADB_X_AALG_SHA2_256HMAC; + return SADB_X_AALG_SHA2_256HMAC; #endif - case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384: + case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384: #if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC) - return SADB_X_AALG_SHA2_384; + return SADB_X_AALG_SHA2_384; #else - return SADB_X_AALG_SHA2_384HMAC; + return SADB_X_AALG_SHA2_384HMAC; #endif - case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512: + case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512: #if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC) - return SADB_X_AALG_SHA2_512; + return SADB_X_AALG_SHA2_512; #else - return SADB_X_AALG_SHA2_512HMAC; + return SADB_X_AALG_SHA2_512HMAC; #endif - case IPSECDOI_ATTR_AUTH_KPDK: /* need special care */ - return SADB_AALG_NONE; - - /* not supported */ - case IPSECDOI_ATTR_AUTH_DES_MAC: - plog(LLV_ERROR, LOCATION, NULL, - "Not supported hash type: %u\n", hashtype); - return ~0; - - case 0: /* reserved */ - default: - return SADB_AALG_NONE; - - plog(LLV_ERROR, LOCATION, NULL, - "Invalid hash type: %u\n", hashtype); - return ~0; + case IPSECDOI_ATTR_AUTH_KPDK: /* need special care */ + return SADB_AALG_NONE; + + /* not supported */ + case IPSECDOI_ATTR_AUTH_DES_MAC: + plog(ASL_LEVEL_ERR, + "Not supported hash type: %u\n", hashtype); + return ~0; + + case 0: /* reserved */ + default: + return SADB_AALG_NONE; + + plog(ASL_LEVEL_ERR, + "Invalid hash type: %u\n", hashtype); + return ~0; } /*NOTREACHED*/ } @@ -531,13 +589,13 @@ ipsecdoi2pfkey_ealg(t_id) case IPSECDOI_ESP_3IDEA: case IPSECDOI_ESP_IDEA: case IPSECDOI_ESP_RC4: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Not supported transform: %u\n", t_id); return ~0; case 0: /* reserved */ default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid transform id: %u\n", t_id); return ~0; } @@ -559,7 +617,7 @@ ipsecdoi2pfkey_calg(t_id) case 0: /* reserved */ default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid transform id: %u\n", t_id); return ~0; } @@ -580,7 +638,7 @@ ipsecdoi2pfkey_proto(proto) return SADB_X_SATYPE_IPCOMP; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid ipsec_doi proto: %u\n", proto); return ~0; } @@ -599,7 +657,7 @@ ipsecdoi2pfkey_alg(algclass, type) case IPSECDOI_PROTO_IPCOMP: return ipsecdoi2pfkey_calg(type); default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid ipsec_doi algclass: %u\n", algclass); return ~0; } @@ -620,7 +678,7 @@ pfkey2ipsecdoi_proto(satype) return IPSECDOI_PROTO_IPCOMP; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid pfkey proto: %u\n", satype); return ~0; } @@ -646,7 +704,7 @@ ipsecdoi2pfkey_mode(mode) #endif return IPSEC_MODE_TRANSPORT; default: - plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode); + plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode); return ~0; } /*NOTREACHED*/ @@ -665,7 +723,7 @@ pfkey2ipsecdoi_mode(mode) case IPSEC_MODE_ANY: return IPSECDOI_ATTR_ENC_MODE_ANY; default: - plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode); + plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode); return ~0; } /*NOTREACHED*/ @@ -683,7 +741,7 @@ keylen_aalg(hashtype) res = alg_ipsec_hmacdef_hashlen(hashtype); if (res == -1) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid hmac algorithm %u.\n", hashtype); return ~0; } @@ -700,7 +758,7 @@ keylen_ealg(enctype, encklen) res = alg_ipsec_encdef_keylen(enctype, encklen); if (res == -1) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid encryption algorithm %u.\n", enctype); return ~0; } @@ -708,8 +766,9 @@ keylen_ealg(enctype, encklen) } int -pfkey_convertfromipsecdoi(proto_id, t_id, hashtype, +pfkey_convertfromipsecdoi(iph2, proto_id, t_id, hashtype, e_type, e_keylen, a_type, a_keylen, flags) + phase2_handle_t *iph2; u_int proto_id; u_int t_id; u_int hashtype; @@ -733,9 +792,9 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype, if ((*a_keylen = keylen_aalg(hashtype)) == ~0) goto bad; *a_keylen >>= 3; - + if (*e_type == SADB_EALG_NONE) { - plog(LLV_ERROR, LOCATION, NULL, "no ESP algorithm.\n"); + plog(ASL_LEVEL_ERR, "no ESP algorithm.\n"); goto bad; } break; @@ -756,7 +815,7 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype, *e_type = SADB_EALG_NONE; *e_keylen = 0; if (*a_type == SADB_AALG_NONE) { - plog(LLV_ERROR, LOCATION, NULL, "no AH algorithm.\n"); + plog(ASL_LEVEL_ERR, "no AH algorithm.\n"); goto bad; } break; @@ -771,13 +830,13 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype, *a_type = SADB_AALG_NONE; *a_keylen = 0; if (*e_type == SADB_X_CALG_NONE) { - plog(LLV_ERROR, LOCATION, NULL, "no IPCOMP algorithm.\n"); + plog(ASL_LEVEL_ERR, "no IPCOMP algorithm.\n"); goto bad; } break; default: - plog(LLV_ERROR, LOCATION, NULL, "unknown IPsec protocol.\n"); + plog(ASL_LEVEL_ERR, "unknown IPsec protocol.\n"); goto bad; } @@ -794,25 +853,23 @@ pfkey_timeover_stub(p) void *p; { - pfkey_timeover((struct ph2handle *)p); + pfkey_timeover((phase2_handle_t *)p); } void pfkey_timeover(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "%s give up to get IPsec-SA due to time up to wait.\n", - saddrwop2str(iph2->dst)); + saddrwop2str((struct sockaddr *)iph2->dst)); SCHED_KILL(iph2->sce); /* If initiator side, send error to kernel by SADB_ACQUIRE. */ if (iph2->side == INITIATOR) pk_sendeacquire(iph2); - unbindph12(iph2); - remph2(iph2); - delph2(iph2); + ike_session_unlink_phase2(iph2); return; } @@ -826,9 +883,9 @@ pfkey_timeover(iph2) */ int pk_sendgetspi(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { - struct sockaddr *src = NULL, *dst = NULL; + struct sockaddr_storage *src = NULL, *dst = NULL; u_int satype, mode; struct saprop *pp; struct saproto *pr; @@ -859,7 +916,7 @@ pk_sendgetspi(iph2) /* validity check */ satype = ipsecdoi2pfkey_proto(pr->proto_id); if (satype == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto_id %d\n", pr->proto_id); return -1; } @@ -875,12 +932,12 @@ pk_sendgetspi(iph2) } mode = ipsecdoi2pfkey_mode(pr->encmode); if (mode == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid encmode %d\n", pr->encmode); return -1; } - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_getspi\n"); if (pfkey_send_getspi( lcconf->sock_pfkey, satype, @@ -888,13 +945,14 @@ pk_sendgetspi(iph2) dst, /* src of SA */ src, /* dst of SA */ minspi, maxspi, - pr->reqid_in, iph2->seq) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + pr->reqid_in, 0, 0, iph2->seq, 0) < 0) { + plog(ASL_LEVEL_ERR, "ipseclib failed send getspi (%s)\n", ipsec_strerror()); return -1; } - plog(LLV_DEBUG, LOCATION, NULL, + + plog(ASL_LEVEL_DEBUG, "pfkey GETSPI sent: %s\n", sadbsecas2str(dst, src, satype, 0, mode)); } @@ -911,8 +969,8 @@ pk_recvgetspi(mhp) { struct sadb_msg *msg; struct sadb_sa *sa; - struct ph2handle *iph2; - struct sockaddr *dst; + phase2_handle_t *iph2; + struct sockaddr_storage *dst; int proto_id; int allspiok, notfound; struct saprop *pp; @@ -921,17 +979,17 @@ pk_recvgetspi(mhp) /* validity check */ if (mhp[SADB_EXT_SA] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "inappropriate sadb getspi message passed.\n"); + plog(ASL_LEVEL_ERR, + "Inappropriate sadb getspi message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; - sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; - dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */ + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA]; + dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */ /* the message has to be processed or not ? */ if (msg->sadb_msg_pid != getpid()) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "%s message is not interesting " "because pid %d is not mine.\n", s_pfkey_type(msg->sadb_msg_type), @@ -939,21 +997,44 @@ pk_recvgetspi(mhp) return -1; } - iph2 = getph2byseq(msg->sadb_msg_seq); + iph2 = ike_session_getph2byseq(msg->sadb_msg_seq); if (iph2 == NULL) { - plog(LLV_DEBUG, LOCATION, NULL, - "seq %d of %s message not interesting.\n", + plog(ASL_LEVEL_DEBUG, + "Seq %d of %s message not interesting.\n", msg->sadb_msg_seq, s_pfkey_type(msg->sadb_msg_type)); return -1; } - if (iph2->status != PHASE2ST_GETSPISENT) { - plog(LLV_ERROR, LOCATION, NULL, - "status mismatch (db:%d msg:%d)\n", - iph2->status, PHASE2ST_GETSPISENT); + if (iph2->is_dying) { + plog(ASL_LEVEL_ERR, + "Status mismatch Phase 2 dying (db:%d)\n", + iph2->status); return -1; } + + switch (iph2->version) { + case ISAKMP_VERSION_NUMBER_IKEV1: + if (iph2->status != IKEV1_STATE_QUICK_I_GETSPISENT && + iph2->status != IKEV1_STATE_QUICK_R_GETSPISENT) { + plog(ASL_LEVEL_ERR, "Status mismatch (db:%d)\n", iph2->status); + return -1; + } + // check the underlying iph2->ph1 + if (!iph2->ph1) { + if (!ike_session_update_ph2_ph1bind(iph2)) { + plog(ASL_LEVEL_ERR, + "Can't proceed with getspi for %s. no suitable ISAKMP-SA found \n", + saddrwop2str((struct sockaddr *)iph2->dst)); + ike_session_unlink_phase2(iph2); + return -1; + } + } + break; + default: + plog(ASL_LEVEL_ERR, "Internal error: invalid IKE major version %d\n", iph2->version); + return -1; + } /* set SPI, and check to get all spi whether or not */ allspiok = 1; @@ -965,7 +1046,7 @@ pk_recvgetspi(mhp) if (pr->proto_id == proto_id && pr->spi == 0) { pr->spi = sa->sadb_sa_spi; notfound = 0; - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "pfkey GETSPI succeeded: %s\n", sadbsecas2str(iph2->dst, iph2->src, msg->sadb_msg_satype, @@ -977,26 +1058,25 @@ pk_recvgetspi(mhp) } if (notfound) { - plog(LLV_ERROR, LOCATION, NULL, - "get spi for unknown address %s\n", - saddrwop2str(iph2->dst)); + plog(ASL_LEVEL_ERR, + "Get spi for unknown address %s\n", + saddrwop2str((struct sockaddr *)iph2->dst)); + ike_session_unlink_phase2(iph2); return -1; } if (allspiok) { - /* update status */ - iph2->status = PHASE2ST_GETSPIDONE; - if (isakmp_post_getspi(iph2) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to start post getspi.\n"); - unbindph12(iph2); - remph2(iph2); - delph2(iph2); - iph2 = NULL; - return -1; - } - } - + switch (iph2->version) { + case ISAKMP_VERSION_NUMBER_IKEV1: + if (isakmp_post_getspi(iph2) < 0) { + plog(ASL_LEVEL_ERR, "IKEv1 post getspi failed.\n"); + ike_session_unlink_phase2(iph2); + iph2 = NULL; + return -1; + } + break; + } + } return 0; } @@ -1005,21 +1085,22 @@ pk_recvgetspi(mhp) */ int pk_sendupdate(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { struct saproto *pr; - struct sockaddr *src = NULL, *dst = NULL; + struct sockaddr_storage *src = NULL, *dst = NULL; u_int e_type, e_keylen, a_type, a_keylen, flags; u_int satype, mode; u_int64_t lifebyte = 0; u_int wsize = 4; /* XXX static size of window */ int proxy = 0; struct ph2natt natt; + int authtype; /* sanity check */ if (iph2->approval == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "no approvaled SAs found.\n"); + plog(ASL_LEVEL_ERR, + "No approved SAs found.\n"); } if (iph2->side == INITIATOR) @@ -1041,8 +1122,8 @@ pk_sendupdate(iph2) /* validity check */ satype = ipsecdoi2pfkey_proto(pr->proto_id); if (satype == ~0) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid proto_id %d\n", pr->proto_id); + plog(ASL_LEVEL_ERR, + "Invalid proto_id %d\n", pr->proto_id); return -1; } else if (satype == SADB_X_SATYPE_IPCOMP) { @@ -1054,18 +1135,21 @@ pk_sendupdate(iph2) #else mode = ipsecdoi2pfkey_mode(pr->encmode); if (mode == ~0) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid encmode %d\n", pr->encmode); + plog(ASL_LEVEL_ERR, + "Invalid encmode %d\n", pr->encmode); return -1; } #endif /* set algorithm type and key length */ e_keylen = pr->head->encklen; + authtype = pr->head->authtype; + a_keylen = 0; if (pfkey_convertfromipsecdoi( + iph2, pr->proto_id, pr->head->trns_id, - pr->head->authtype, + authtype, &e_type, &e_keylen, &a_type, &a_keylen, &flags) < 0) return -1; @@ -1076,19 +1160,31 @@ pk_sendupdate(iph2) lifebyte = 0; #endif -#ifdef __APPLE__ #ifdef ENABLE_NATT - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n"); + //plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_update: e_type %d, e_klen %d, a_type %d, a_klen %d\n", + e_type, e_keylen, a_type, a_keylen); if (pr->udp_encap) { memset (&natt, 0, sizeof (natt)); natt.sport = extract_port (iph2->ph1->remote); flags |= SADB_X_EXT_NATT; - if (iph2->ph1->natt_flags & NAT_DETECTED_ME) - flags |= SADB_X_EXT_NATT_KEEPALIVE; - else if (iph2->ph1->rmconf->natt_multiple_user == TRUE && + if (iph2->ph1->rmconf->natt_multiple_user == TRUE && mode == IPSEC_MODE_TRANSPORT && - src->sa_family == AF_INET) - flags |= SADB_X_EXT_NATT_MULTIPLEUSERS; + src->ss_family == AF_INET) { + flags |= SADB_X_EXT_NATT_MULTIPLEUSERS; + if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) { + // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE + flags |= SADB_X_EXT_NATT_DETECTED_PEER; + } + } else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) { + if (iph2->ph1->rmconf->natt_keepalive == TRUE) + flags |= SADB_X_EXT_NATT_KEEPALIVE; + } else { + if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) { + // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE + flags |= SADB_X_EXT_NATT_DETECTED_PEER; + } + } } else { memset (&natt, 0, sizeof (natt)); } @@ -1105,14 +1201,14 @@ pk_sendupdate(iph2) pr->keymat->v, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq, natt.sport) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + iph2->seq, natt.sport, 0) < 0) { + plog(ASL_LEVEL_ERR, "libipsec failed send update (%s)\n", ipsec_strerror()); return -1; } #else - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n"); if (pfkey_send_update( lcconf->sock_pfkey, satype, @@ -1125,95 +1221,15 @@ pk_sendupdate(iph2) pr->keymat->v, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq, 0) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + iph2->seq, 0, 0) < 0) { + plog(ASL_LEVEL_ERR, "libipsec failed send update (%s)\n", ipsec_strerror()); return -1; } #endif /* ENABLE_NATT */ -#else -#ifdef ENABLE_NATT - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update_nat\n"); - if (pr->udp_encap) { - memset (&natt, 0, sizeof (natt)); - natt.type = iph2->ph1->natt_options->encaps_type; - natt.sport = extract_port (iph2->ph1->remote); - natt.dport = extract_port (iph2->ph1->local); - natt.oa = NULL; // FIXME: Here comes OA!!! - natt.frag = iph2->ph1->rmconf->esp_frag; - } else { - memset (&natt, 0, sizeof (natt)); - } - if (pfkey_send_update_nat( - lcconf->sock_pfkey, - satype, - mode, - dst, - src, - pr->spi, - pr->reqid_in, - wsize, - pr->keymat->v, - e_type, e_keylen, a_type, a_keylen, flags, - 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq, - natt.type, natt.sport, natt.dport, natt.oa, - natt.frag) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed send update_nat (%s)\n", - ipsec_strerror()); - return -1; - } -#else - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n"); - if (pfkey_send_update( - lcconf->sock_pfkey, - satype, - mode, - dst, - src, - pr->spi, - pr->reqid_in, - wsize, - pr->keymat->v, - e_type, e_keylen, a_type, a_keylen, flags, - 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed send update (%s)\n", - ipsec_strerror()); - return -1; - } -#endif /* ENABLE_NATT */ -#endif /* __APPLE__ */ - if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]) - continue; - - /* - * It maybe good idea to call backupsa_to_file() after - * racoon will receive the sadb_update messages. - * But it is impossible because there is not key in the - * information from the kernel. - */ - if (backupsa_to_file(satype, mode, dst, src, - pr->spi, pr->reqid_in, 4, - pr->keymat->v, - e_type, e_keylen, a_type, a_keylen, flags, - 0, iph2->approval->lifebyte * 1024, - iph2->approval->lifetime, 0, - iph2->seq) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "backuped SA failed: %s\n", - sadbsecas2str(dst, src, - satype, pr->spi, mode)); - } - plog(LLV_DEBUG, LOCATION, NULL, - "backuped SA: %s\n", - sadbsecas2str(dst, src, - satype, pr->spi, mode)); } return 0; @@ -1225,8 +1241,8 @@ pk_recvupdate(mhp) { struct sadb_msg *msg; struct sadb_sa *sa; - struct sockaddr *src, *dst; - struct ph2handle *iph2; + struct sockaddr_storage *src, *dst; + phase2_handle_t *iph2; u_int proto_id, encmode, sa_mode; int incomplete = 0; struct saproto *pr; @@ -1240,22 +1256,22 @@ pk_recvupdate(mhp) || mhp[SADB_EXT_SA] == NULL || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb update message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; - src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); - dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); - sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA]; sa_mode = mhp[SADB_X_EXT_SA2] == NULL ? IPSEC_MODE_ANY - : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode; + : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode; /* the message has to be processed or not ? */ if (msg->sadb_msg_pid != getpid()) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "%s message is not interesting " "because pid %d is not mine.\n", s_pfkey_type(msg->sadb_msg_type), @@ -1263,19 +1279,26 @@ pk_recvupdate(mhp) return -1; } - iph2 = getph2byseq(msg->sadb_msg_seq); + iph2 = ike_session_getph2byseq(msg->sadb_msg_seq); if (iph2 == NULL) { - plog(LLV_DEBUG, LOCATION, NULL, - "seq %d of %s message not interesting.\n", + plog(ASL_LEVEL_DEBUG, + "Seq %d of %s message not interesting.\n", msg->sadb_msg_seq, s_pfkey_type(msg->sadb_msg_type)); return -1; } - if (iph2->status != PHASE2ST_ADDSA) { - plog(LLV_ERROR, LOCATION, NULL, - "status mismatch (db:%d msg:%d)\n", - iph2->status, PHASE2ST_ADDSA); + if (iph2->is_dying) { + plog(ASL_LEVEL_ERR, + "Status mismatch Phase 2 dying (db:%d)\n", + iph2->status); + return -1; + } + if (iph2->status != IKEV1_STATE_QUICK_I_ADDSA && + iph2->status != IKEV1_STATE_QUICK_R_ADDSA) { + plog(ASL_LEVEL_ERR, + "Status mismatch (db:%d)\n", + iph2->status); return -1; } @@ -1283,13 +1306,13 @@ pk_recvupdate(mhp) for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype); if (proto_id == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto_id %d\n", msg->sadb_msg_satype); return -1; } encmode = pfkey2ipsecdoi_mode(sa_mode); if (encmode == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid encmode %d\n", sa_mode); return -1; } @@ -1297,14 +1320,14 @@ pk_recvupdate(mhp) if (pr->proto_id == proto_id && pr->spi == sa->sadb_sa_spi) { pr->ok = 1; - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "pfkey UPDATE succeeded: %s\n", sadbsecas2str(iph2->dst, iph2->src, msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode)); - plog(LLV_INFO, LOCATION, NULL, + plog(ASL_LEVEL_INFO, "IPsec-SA established: %s\n", sadbsecas2str(iph2->dst, iph2->src, msg->sadb_msg_satype, sa->sadb_sa_spi, @@ -1322,16 +1345,34 @@ pk_recvupdate(mhp) SCHED_KILL(iph2->sce); /* update status */ - iph2->status = PHASE2ST_ESTABLISHED; + fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_ESTABLISHED); + + if (iph2->side == INITIATOR) { + IPSECSESSIONTRACEREVENT(iph2->parent_session, + IPSECSESSIONEVENTCODE_IKEV1_PH2_INIT_SUCC, + CONSTSTR("Initiator, Quick-Mode"), + CONSTSTR(NULL)); + } else { + IPSECSESSIONTRACEREVENT(iph2->parent_session, + IPSECSESSIONEVENTCODE_IKEV1_PH2_RESP_SUCC, + CONSTSTR("Responder, Quick-Mode"), + CONSTSTR(NULL)); + } + + ike_session_ph2_established(iph2); + IPSECLOGASLMSG("IPSec Phase 2 established (Initiated by %s).\n", + (iph2->side == INITIATOR)? "me" : "peer"); + #ifdef ENABLE_STATS gettimeofday(&iph2->end, NULL); - syslog(LOG_NOTICE, "%s(%s): %8.6f", - "phase2", "quick", timedelta(&iph2->start, &iph2->end)); + plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f", + "Phase 2", "quick", timedelta(&iph2->start, &iph2->end)); #endif /* count up */ - iph2->ph1->ph2cnt++; + if (iph2->ph1) + iph2->ph1->ph2cnt++; /* turn off schedule */ if (iph2->scr) @@ -1341,12 +1382,12 @@ pk_recvupdate(mhp) * since we are going to reuse the phase2 handler, we need to * remain it and refresh all the references between ph1 and ph2 to use. */ - unbindph12(iph2); + ike_session_unbindph12(iph2); //%%%%% fix this iph2->sce = sched_new(iph2->approval->lifetime, isakmp_ph2expire_stub, iph2); - plog(LLV_DEBUG, LOCATION, NULL, "===\n"); + plog(ASL_LEVEL_DEBUG, "===\n"); return 0; } @@ -1355,20 +1396,21 @@ pk_recvupdate(mhp) */ int pk_sendadd(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { struct saproto *pr; - struct sockaddr *src = NULL, *dst = NULL; + struct sockaddr_storage *src = NULL, *dst = NULL; u_int e_type, e_keylen, a_type, a_keylen, flags; u_int satype, mode; u_int64_t lifebyte = 0; u_int wsize = 4; /* XXX static size of window */ int proxy = 0; struct ph2natt natt; + int authtype; /* sanity check */ if (iph2->approval == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "no approvaled SAs found.\n"); } @@ -1391,7 +1433,7 @@ pk_sendadd(iph2) /* validity check */ satype = ipsecdoi2pfkey_proto(pr->proto_id); if (satype == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto_id %d\n", pr->proto_id); return -1; } @@ -1404,7 +1446,7 @@ pk_sendadd(iph2) #else mode = ipsecdoi2pfkey_mode(pr->encmode); if (mode == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid encmode %d\n", pr->encmode); return -1; } @@ -1412,10 +1454,13 @@ pk_sendadd(iph2) /* set algorithm type and key length */ e_keylen = pr->head->encklen; + authtype = pr->head->authtype; + a_keylen = 0; if (pfkey_convertfromipsecdoi( + iph2, pr->proto_id, pr->head->trns_id, - pr->head->authtype, + authtype, &e_type, &e_keylen, &a_type, &a_keylen, &flags) < 0) return -1; @@ -1426,20 +1471,32 @@ pk_sendadd(iph2) lifebyte = 0; #endif -#ifdef __APPLE__ #ifdef ENABLE_NATT - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n"); + //plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_add: e_type %d, e_klen %d, a_type %d, a_klen %d\n", + e_type, e_keylen, a_type, a_keylen); if (pr->udp_encap) { memset (&natt, 0, sizeof (natt)); natt.dport = extract_port (iph2->ph1->remote); flags |= SADB_X_EXT_NATT; - if (iph2->ph1->natt_flags & NAT_DETECTED_ME) - flags |= SADB_X_EXT_NATT_KEEPALIVE; - else if (iph2->ph1->rmconf->natt_multiple_user == TRUE && + if (iph2->ph1->rmconf->natt_multiple_user == TRUE && mode == IPSEC_MODE_TRANSPORT && - dst->sa_family == AF_INET) - flags |= SADB_X_EXT_NATT_MULTIPLEUSERS; + src->ss_family == AF_INET) { + flags |= SADB_X_EXT_NATT_MULTIPLEUSERS; + if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) { + // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE + flags |= SADB_X_EXT_NATT_DETECTED_PEER; + } + } else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) { + if (iph2->ph1->rmconf->natt_keepalive == TRUE) + flags |= SADB_X_EXT_NATT_KEEPALIVE; + } else { + if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) { + // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE + flags |= SADB_X_EXT_NATT_DETECTED_PEER; + } + } } else { memset (&natt, 0, sizeof (natt)); @@ -1460,14 +1517,14 @@ pk_sendadd(iph2) pr->keymat_p->v, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq,natt.dport) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + iph2->seq,natt.dport, 0) < 0) { + plog(ASL_LEVEL_ERR, "libipsec failed send add (%s)\n", ipsec_strerror()); return -1; } #else - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n"); /* Remove port information, it is not used without NAT-T */ //set_port(src, 0); @@ -1485,105 +1542,13 @@ pk_sendadd(iph2) pr->keymat_p->v, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq, 0) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed send add (%s)\n", - ipsec_strerror()); - return -1; - } -#endif /* ENABLE_NATT */ -#else /* __APPLE__ */ -#ifdef ENABLE_NATT - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add_nat\n"); - - if (pr->udp_encap) { - memset (&natt, 0, sizeof (natt)); - natt.type = UDP_ENCAP_ESPINUDP; - natt.sport = extract_port (iph2->ph1->local); - natt.dport = extract_port (iph2->ph1->remote); - natt.oa = NULL; // FIXME: Here comes OA!!! - natt.frag = iph2->ph1->rmconf->esp_frag; - } else { - memset (&natt, 0, sizeof (natt)); - - /* Remove port information, that SA doesn't use it */ - set_port(src, 0); - set_port(dst, 0); - } - - if (pfkey_send_add_nat( - lcconf->sock_pfkey, - satype, - mode, - src, - dst, - pr->spi_p, - pr->reqid_out, - wsize, - pr->keymat_p->v, - e_type, e_keylen, a_type, a_keylen, flags, - 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq, - natt.type, natt.sport, natt.dport, natt.oa, - natt.frag) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "libipsec failed send add_nat (%s)\n", - ipsec_strerror()); - return -1; - } -#else - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n"); - - /* Remove port information, it is not used without NAT-T */ - set_port(src, 0); - set_port(dst, 0); - - if (pfkey_send_add( - lcconf->sock_pfkey, - satype, - mode, - src, - dst, - pr->spi_p, - pr->reqid_out, - wsize, - pr->keymat_p->v, - e_type, e_keylen, a_type, a_keylen, flags, - 0, lifebyte, iph2->approval->lifetime, 0, - iph2->seq) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + iph2->seq, 0, 0) < 0) { + plog(ASL_LEVEL_ERR, "libipsec failed send add (%s)\n", ipsec_strerror()); return -1; } #endif /* ENABLE_NATT */ -#endif /* __APPLE__ */ - - if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]) - continue; - - /* - * It maybe good idea to call backupsa_to_file() after - * racoon will receive the sadb_update messages. - * But it is impossible because there is not key in the - * information from the kernel. - */ - if (backupsa_to_file(satype, mode, src, dst, - pr->spi_p, pr->reqid_out, 4, - pr->keymat_p->v, - e_type, e_keylen, a_type, a_keylen, flags, - 0, iph2->approval->lifebyte * 1024, - iph2->approval->lifetime, 0, - iph2->seq) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "backuped SA failed: %s\n", - sadbsecas2str(src, dst, - satype, pr->spi_p, mode)); - } - plog(LLV_DEBUG, LOCATION, NULL, - "backuped SA: %s\n", - sadbsecas2str(src, dst, - satype, pr->spi_p, mode)); } return 0; @@ -1595,8 +1560,8 @@ pk_recvadd(mhp) { struct sadb_msg *msg; struct sadb_sa *sa; - struct sockaddr *src, *dst; - struct ph2handle *iph2; + struct sockaddr_storage *src, *dst; + phase2_handle_t *iph2; u_int sa_mode; /* ignore this message because of local test mode. */ @@ -1608,22 +1573,22 @@ pk_recvadd(mhp) || mhp[SADB_EXT_SA] == NULL || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb add message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; - src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); - dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); - sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA]; sa_mode = mhp[SADB_X_EXT_SA2] == NULL ? IPSEC_MODE_ANY - : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode; + : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode; /* the message has to be processed or not ? */ if (msg->sadb_msg_pid != getpid()) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "%s message is not interesting " "because pid %d is not mine.\n", s_pfkey_type(msg->sadb_msg_type), @@ -1631,30 +1596,31 @@ pk_recvadd(mhp) return -1; } - iph2 = getph2byseq(msg->sadb_msg_seq); + iph2 = ike_session_getph2byseq(msg->sadb_msg_seq); if (iph2 == NULL) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "seq %d of %s message not interesting.\n", msg->sadb_msg_seq, s_pfkey_type(msg->sadb_msg_type)); return -1; } - /* * NOTE don't update any status of phase2 handle * because they must be updated by SADB_UPDATE message */ - plog(LLV_INFO, LOCATION, NULL, + plog(ASL_LEVEL_INFO, "IPsec-SA established: %s\n", sadbsecas2str(iph2->src, iph2->dst, msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode)); + ike_session_cleanup_other_established_ph2s(iph2->parent_session, iph2); + #ifdef ENABLE_VPNCONTROL_PORT { u_int32_t address; - if (iph2->dst->sa_family == AF_INET) + if (iph2->dst->ss_family == AF_INET) address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr; else address = 0; @@ -1662,7 +1628,7 @@ pk_recvadd(mhp) } #endif - plog(LLV_DEBUG, LOCATION, NULL, "===\n"); + plog(ASL_LEVEL_DEBUG, "===\n"); return 0; } @@ -1672,8 +1638,8 @@ pk_recvexpire(mhp) { struct sadb_msg *msg; struct sadb_sa *sa; - struct sockaddr *src, *dst; - struct ph2handle *iph2; + struct sockaddr_storage *src, *dst; + phase2_handle_t *iph2; u_int proto_id, sa_mode; /* sanity check */ @@ -1683,46 +1649,46 @@ pk_recvexpire(mhp) || mhp[SADB_EXT_ADDRESS_DST] == NULL || (mhp[SADB_EXT_LIFETIME_HARD] != NULL && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb expire message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; - sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; - src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); - dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA]; + src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); sa_mode = mhp[SADB_X_EXT_SA2] == NULL ? IPSEC_MODE_ANY - : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode; + : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode; proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype); if (proto_id == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto_id %d\n", msg->sadb_msg_satype); return -1; } - plog(LLV_INFO, LOCATION, NULL, + plog(ASL_LEVEL_INFO, "IPsec-SA expired: %s\n", sadbsecas2str(src, dst, msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode)); - iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi); + iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi); if (iph2 == NULL) { /* * Ignore it because two expire messages are come up. * phase2 handler has been deleted already when 2nd message * is received. */ - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "no such a SA found: %s\n", sadbsecas2str(src, dst, msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode)); return 0; } - if (iph2->status != PHASE2ST_ESTABLISHED) { + if (iph2->is_dying || !FSM_STATE_IS_ESTABLISHED(iph2->status)) { /* * If the status is not equal to PHASE2ST_ESTABLISHED, * racoon ignores this expire message. There are two reason. @@ -1731,34 +1697,31 @@ pk_recvexpire(mhp) * without receiving a expire message. Another is that racoon * may receive the multiple expire messages from the kernel. */ - plog(LLV_WARNING, LOCATION, NULL, - "the expire message is received " - "but the handler has not been established.\n"); + plog(ASL_LEVEL_WARNING, + "The expire message is received but the handler %s (status = 0x%x).\n", + iph2->is_dying ? "is dying" : "has not been established", iph2->status); return 0; } /* turn off the timer for calling isakmp_ph2expire() */ SCHED_KILL(iph2->sce); - - iph2->status = PHASE2ST_EXPIRED; - - /* INITIATOR, begin phase 2 exchange. */ + + fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED); + + /* INITIATOR, begin phase 2 exchange only if there's no other established ph2. */ /* allocate buffer for status management of pfkey message */ - if (iph2->side == INITIATOR) { + if (iph2->side == INITIATOR && + !ike_session_has_other_established_ph2(iph2->parent_session, iph2) && + !ike_session_drop_rekey(iph2->parent_session, IKE_SESSION_REKEY_TYPE_PH2)) { - initph2(iph2); - - /* update status for re-use */ - iph2->status = PHASE2ST_STATUS2; + ike_session_initph2(iph2); /* start isakmp initiation by using ident exchange */ if (isakmp_post_acquire(iph2) < 0) { - plog(LLV_ERROR, LOCATION, iph2->dst, + plog(ASL_LEVEL_ERR, "failed to begin ipsec sa " - "re-negotication.\n"); - unbindph12(iph2); - remph2(iph2); - delph2(iph2); + "re-negotiation.\n"); + ike_session_unlink_phase2(iph2); return -1; } @@ -1766,12 +1729,11 @@ pk_recvexpire(mhp) /*NOTREACHED*/ } + /* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */ /* RESPONDER always delete ph2handle, keep silent. RESPONDER doesn't * manage IPsec SA, so delete the list */ - unbindph12(iph2); - remph2(iph2); - delph2(iph2); + ike_session_unlink_phase2(iph2); return 0; } @@ -1783,10 +1745,10 @@ pk_recvacquire(mhp) struct sadb_msg *msg; struct sadb_x_policy *xpl; struct secpolicy *sp_out = NULL, *sp_in = NULL; -#define MAXNESTEDSA 5 /* XXX */ - struct ph2handle *iph2[MAXNESTEDSA]; - struct sockaddr *src, *dst; - int n; /* # of phase 2 handler */ + phase2_handle_t *iph2; + struct sockaddr_storage *src, *dst; + ike_session_t *session = NULL; + struct remoteconf *rmconf; /* ignore this message because of local test mode. */ if (f_local) @@ -1797,36 +1759,36 @@ pk_recvacquire(mhp) || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL || mhp[SADB_X_EXT_POLICY] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb acquire message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; - src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); - dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); /* ignore if type is not IPSEC_POLICY_IPSEC */ if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "ignore ACQUIRE message. type is not IPsec.\n"); return 0; } /* ignore it if src is multicast address */ { - struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); - if ((sa->sa_family == AF_INET + if ((sa->ss_family == AF_INET && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr))) #ifdef INET6 - || (sa->sa_family == AF_INET6 + || (sa->ss_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr)) #endif ) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "ignore due to multicast address: %s.\n", - saddrwop2str(sa)); + saddrwop2str((struct sockaddr *)sa)); return 0; } } @@ -1841,10 +1803,16 @@ pk_recvacquire(mhp) * than one in the policy, so kernel will drop them; * => therefore this acquire is not for us! --Aidas */ - struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); struct myaddrs *p; int do_listen = 0; + char * str; for (p = lcconf->myaddrs; p; p = p->next) { + str = saddr2str((struct sockaddr *)p->addr); + plog(ASL_LEVEL_DEBUG, + "checking listen addrs: %s", str); + if (!cmpsaddrwop(p->addr, sa)) { do_listen = 1; break; @@ -1852,9 +1820,9 @@ pk_recvacquire(mhp) } if (!do_listen) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "ignore because do not listen on source address : %s.\n", - saddrwop2str(sa)); + saddrwop2str((struct sockaddr *)sa)); return 0; } } @@ -1866,147 +1834,168 @@ pk_recvacquire(mhp) * should ignore such a acquire message because the phase 2 * is just negotiating. * 2. its state is equal to PHASE2ST_ESTABLISHED, then racoon - * has to prcesss such a acquire message because racoon may - * lost the expire message. + * has to process such a acquire message because racoon may + * have lost the expire message. */ - iph2[0] = getph2byid(src, dst, xpl->sadb_x_policy_id); - if (iph2[0] != NULL) { - if (iph2[0]->status < PHASE2ST_ESTABLISHED) { - plog(LLV_DEBUG, LOCATION, NULL, + iph2 = ike_session_getph2byid(src, dst, xpl->sadb_x_policy_id); + if (iph2 != NULL) { + session = iph2->parent_session; + if (!FSM_STATE_IS_ESTABLISHED(iph2->status)) { + plog(ASL_LEVEL_DEBUG, "ignore the acquire because ph2 found\n"); return -1; } - if (iph2[0]->status == PHASE2ST_EXPIRED) - iph2[0] = NULL; + if (FSM_STATE_IS_EXPIRED(iph2->status)) + iph2 = NULL; /*FALLTHROUGH*/ } /* search for proper policyindex */ sp_out = getspbyspid(xpl->sadb_x_policy_id); if (sp_out == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n", + plog(ASL_LEVEL_ERR, "no policy found: id:%d.\n", xpl->sadb_x_policy_id); return -1; } - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx)); /* get inbound policy */ { - struct policyindex spidx; - - spidx.dir = IPSEC_DIR_INBOUND; - memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src)); - memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst)); - spidx.prefs = sp_out->spidx.prefd; - spidx.prefd = sp_out->spidx.prefs; - spidx.ul_proto = sp_out->spidx.ul_proto; - - sp_in = getsp(&spidx); - if (sp_in) { - plog(LLV_DEBUG, LOCATION, NULL, - "suitable inbound SP found: %s.\n", - spidx2str(&sp_in->spidx)); - } else { - plog(LLV_NOTIFY, LOCATION, NULL, - "no in-bound policy found: %s\n", - spidx2str(&spidx)); - } + struct policyindex spidx; + + spidx.dir = IPSEC_DIR_INBOUND; + memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src)); + memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst)); + spidx.prefs = sp_out->spidx.prefd; + spidx.prefd = sp_out->spidx.prefs; + spidx.ul_proto = sp_out->spidx.ul_proto; + + sp_in = getsp(&spidx); + if (sp_in) { + plog(ASL_LEVEL_DEBUG, + "Suitable inbound SP found: %s.\n", + spidx2str(&sp_in->spidx)); + } else { + plog(ASL_LEVEL_NOTICE, + "No in-bound policy found: %s\n", + spidx2str(&spidx)); + } } - - memset(iph2, 0, MAXNESTEDSA); - - n = 0; - + /* allocate a phase 2 */ - iph2[n] = newph2(); - if (iph2[n] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate phase2 entry.\n"); + rmconf = getrmconf(dst); + if (rmconf == NULL) { + plog(ASL_LEVEL_ERR, "No configuration found for %s.\n", + saddrwop2str((struct sockaddr *)dst)); return -1; } - iph2[n]->side = INITIATOR; - iph2[n]->spid = xpl->sadb_x_policy_id; - iph2[n]->satype = msg->sadb_msg_satype; - iph2[n]->seq = msg->sadb_msg_seq; - iph2[n]->status = PHASE2ST_STATUS2; + iph2 = ike_session_newph2(rmconf->ike_version, PHASE2_TYPE_SA); + if (iph2 == NULL) { + plog(ASL_LEVEL_ERR, + "Failed to allocate Phase 2 entry.\n"); + return -1; + } + plog(ASL_LEVEL_DEBUG, "Got new Phase 2 version %d\n", iph2->version); + iph2->version = rmconf->ike_version; + iph2->side = INITIATOR; + iph2->spid = xpl->sadb_x_policy_id; + + iph2->satype = msg->sadb_msg_satype; + iph2->seq = msg->sadb_msg_seq; /* set end addresses of SA */ - iph2[n]->dst = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST])); - if (iph2[n]->dst == NULL) { - delph2(iph2[n]); + // Wcast_align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + iph2->src = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC])); + if (iph2->src == NULL) { + ike_session_delph2(iph2); return -1; } - iph2[n]->src = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC])); - if (iph2[n]->src == NULL) { - delph2(iph2[n]); + iph2->dst = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST])); + if (iph2->dst == NULL) { + ike_session_delph2(iph2); return -1; + } + + if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) { + fsm_set_state(&iph2->status, IKEV1_STATE_QUICK_I_START); } - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "new acquire %s\n", spidx2str(&sp_out->spidx)); /* get sainfo */ { - vchar_t *idsrc, *iddst; - - idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src, - sp_out->spidx.prefs, sp_out->spidx.ul_proto); - if (idsrc == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get ID for %s\n", - spidx2str(&sp_out->spidx)); - delph2(iph2[n]); - return -1; - } - iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst, - sp_out->spidx.prefd, sp_out->spidx.ul_proto); - if (iddst == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get ID for %s\n", - spidx2str(&sp_out->spidx)); - vfree(idsrc); - delph2(iph2[n]); - return -1; - } - iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, 0); - vfree(idsrc); - vfree(iddst); - if (iph2[n]->sainfo == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get sainfo.\n"); - delph2(iph2[n]); - return -1; - /* XXX should use the algorithm list from register message */ - } + vchar_t *idsrc, *iddst; + + idsrc = ipsecdoi_sockaddr2id(&sp_out->spidx.src, + sp_out->spidx.prefs, sp_out->spidx.ul_proto); + if (idsrc == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get ID for %s\n", + spidx2str(&sp_out->spidx)); + ike_session_delph2(iph2); + return -1; + } + iddst = ipsecdoi_sockaddr2id(&sp_out->spidx.dst, + sp_out->spidx.prefd, sp_out->spidx.ul_proto); + if (iddst == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get ID for %s\n", + spidx2str(&sp_out->spidx)); + vfree(idsrc); + ike_session_delph2(iph2); + return -1; + } + iph2->sainfo = getsainfo(idsrc, iddst, NULL, 0); + vfree(idsrc); + vfree(iddst); + if (iph2->sainfo == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get sainfo.\n"); + ike_session_delph2(iph2); + return -1; + /* XXX should use the algorithm list from register message */ + } } + retain_sainfo(iph2->sainfo); - if (set_proposal_from_policy(iph2[n], sp_out, sp_in) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to create saprop.\n"); - delph2(iph2[n]); + if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) { + plog(ASL_LEVEL_ERR, + "failed to create saprop.\n"); + ike_session_delph2(iph2); return -1; } - insph2(iph2[n]); + + if (session == NULL) + session = ike_session_get_session(iph2->src, iph2->dst, 1, NULL); + if (session == NULL) + fatal_error(-1); + + if (ike_session_link_phase2(session, iph2)) + fatal_error(-1); //????? fix ??? /* start isakmp initiation by using ident exchange */ /* XXX should be looped if there are multiple phase 2 handler. */ - if (isakmp_post_acquire(iph2[n]) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to begin ipsec sa negotication.\n"); + if (isakmp_post_acquire(iph2) < 0) { + plog(ASL_LEVEL_ERR, + "failed to begin ipsec sa negotiation.\n"); goto err; } + +#if !TARGET_OS_EMBEDDED + if ( lcconf->vt == NULL){ + if (!(lcconf->vt = vproc_transaction_begin(NULL))) + plog(ASL_LEVEL_ERR, + "vproc_transaction_begin returns NULL.\n"); + } +#endif + return 0; err: - while (n >= 0) { - unbindph12(iph2[n]); - remph2(iph2[n]); - delph2(iph2[n]); - iph2[n] = NULL; - n--; - } + ike_session_unlink_phase2(iph2); return -1; } @@ -2016,8 +2005,8 @@ pk_recvdelete(mhp) { struct sadb_msg *msg; struct sadb_sa *sa; - struct sockaddr *src, *dst; - struct ph2handle *iph2 = NULL; + struct sockaddr_storage *src, *dst; + phase2_handle_t *iph2 = NULL; u_int proto_id; /* ignore this message because of local test mode. */ @@ -2026,21 +2015,20 @@ pk_recvdelete(mhp) /* sanity check */ if (mhp[0] == NULL - || mhp[SADB_EXT_SA] == NULL || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb delete message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; - sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; - src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); - dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA]; + src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); /* the message has to be processed or not ? */ if (msg->sadb_msg_pid == getpid()) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "%s message is not interesting " "because the message was originated by me.\n", s_pfkey_type(msg->sadb_msg_type)); @@ -2049,33 +2037,44 @@ pk_recvdelete(mhp) proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype); if (proto_id == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto_id %d\n", msg->sadb_msg_satype); return -1; } - iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi); + plog(ASL_LEVEL_DEBUG, "SADB delete message: proto-id %d\n", proto_id); + plog(ASL_LEVEL_DEBUG, "src: %s\n", saddr2str((struct sockaddr *)src)); + plog(ASL_LEVEL_DEBUG, "dst: %s\n", saddr2str((struct sockaddr *)dst)); + + if (!sa) { + ike_session_deleteallph2(src, dst, proto_id); + ike_session_deleteallph1(src, dst); + return 0; + } + + iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi); if (iph2 == NULL) { /* ignore */ - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "no iph2 found: %s\n", sadbsecas2str(src, dst, msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY)); return 0; } - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "pfkey DELETE received: %s\n", sadbsecas2str(iph2->src, iph2->dst, msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY)); /* send delete information */ - if (iph2->status == PHASE2ST_ESTABLISHED) + + /* TODO: Look into handling this properly. Currently, if we get here, we can end up sending delete messages to the server for their own SAs, which is rejected. */ + /*if (FSM_STATE_IS_ESTABLISHED(iph2->status)) isakmp_info_send_d2(iph2); - unbindph12(iph2); - remph2(iph2); - delph2(iph2); + ike_session_cleanup_ph1s_by_ph2(iph2); + ike_session_unlink_phase2(iph2);*/ return 0; } @@ -2084,18 +2083,15 @@ static int pk_recvflush(mhp) caddr_t *mhp; { - /* ignore this message because of local test mode. */ - if (f_local) - return 0; - /* sanity check */ if (mhp[0] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb flush message passed.\n"); return -1; } - flushph2(); + ike_session_flush_all_phase2(false); + ike_session_flush_all_phase1(false); return 0; } @@ -2104,9 +2100,9 @@ static int getsadbpolicy(policy0, policylen0, type, iph2) caddr_t *policy0; int *policylen0, type; - struct ph2handle *iph2; + phase2_handle_t *iph2; { - struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen; + struct policyindex *spidx = iph2->spidx_gen; struct sadb_x_policy *xpl; struct sadb_x_ipsecrequest *xisr; struct saproto *pr; @@ -2121,8 +2117,8 @@ getsadbpolicy(policy0, policylen0, type, iph2) for (pr = iph2->approval->head; pr; pr = pr->next) { xisrlen = sizeof(*xisr); if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) { - xisrlen += (sysdep_sa_len(iph2->src) - + sysdep_sa_len(iph2->dst)); + xisrlen += (sysdep_sa_len((struct sockaddr *)iph2->src) + + sysdep_sa_len((struct sockaddr *)iph2->dst)); } policylen += PFKEY_ALIGN8(xisrlen); @@ -2132,12 +2128,12 @@ getsadbpolicy(policy0, policylen0, type, iph2) /* make policy structure */ policy = racoon_malloc(policylen); if (!policy) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "buffer allocation failed.\n"); return -1; } - xpl = (struct sadb_x_policy *)policy; + xpl = ALIGNED_CAST(struct sadb_x_policy *)policy; xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen); xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC; @@ -2157,13 +2153,13 @@ getsadbpolicy(policy0, policylen0, type, iph2) satype = doi2ipproto(pr->proto_id); if (satype == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto_id %d\n", pr->proto_id); goto err; } mode = ipsecdoi2pfkey_mode(pr->encmode); if (mode == ~0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid encmode %d\n", pr->encmode); goto err; } @@ -2183,8 +2179,8 @@ getsadbpolicy(policy0, policylen0, type, iph2) if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) { int src_len, dst_len; - src_len = sysdep_sa_len(iph2->src); - dst_len = sysdep_sa_len(iph2->dst); + src_len = sysdep_sa_len((struct sockaddr *)iph2->src); + dst_len = sysdep_sa_len((struct sockaddr *)iph2->dst); xisrlen += src_len + dst_len; memcpy(p, iph2->src, src_len); @@ -2212,9 +2208,9 @@ err: int pk_sendspdupdate2(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { - struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen; + struct policyindex *spidx = iph2->spidx_gen; caddr_t policy = NULL; int policylen = 0; u_int64_t ltime, vtime; @@ -2223,26 +2219,26 @@ pk_sendspdupdate2(iph2) vtime = 0; if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "getting sadb policy failed.\n"); return -1; } if (pfkey_send_spdupdate2( lcconf->sock_pfkey, - (struct sockaddr *)&spidx->src, + &spidx->src, spidx->prefs, - (struct sockaddr *)&spidx->dst, + &spidx->dst, spidx->prefd, spidx->ul_proto, ltime, vtime, policy, policylen, 0) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "libipsec failed send spdupdate2 (%s)\n", ipsec_strerror()); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdupdate2\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdupdate2\n"); end: if (policy) @@ -2265,13 +2261,13 @@ pk_recvspdupdate(mhp) || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL || mhp[SADB_X_EXT_POLICY] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spdupdate message passed.\n"); return -1; } - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; #ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, @@ -2294,7 +2290,7 @@ pk_recvspdupdate(mhp) sp = getsp(&spidx); if (sp == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "such policy does not already exist: \"%s\"\n", spidx2str(&spidx)); } else { @@ -2313,9 +2309,9 @@ pk_recvspdupdate(mhp) */ int pk_sendspdadd2(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { - struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen; + struct policyindex *spidx = iph2->spidx_gen; caddr_t policy = NULL; int policylen = 0; u_int64_t ltime, vtime; @@ -2324,26 +2320,26 @@ pk_sendspdadd2(iph2) vtime = 0; if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "getting sadb policy failed.\n"); return -1; } if (pfkey_send_spdadd2( lcconf->sock_pfkey, - (struct sockaddr *)&spidx->src, + &spidx->src, spidx->prefs, - (struct sockaddr *)&spidx->dst, + &spidx->dst, spidx->prefd, spidx->ul_proto, ltime, vtime, policy, policylen, 0) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "libipsec failed send spdadd2 (%s)\n", ipsec_strerror()); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdadd2\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdadd2\n"); end: if (policy) @@ -2366,13 +2362,13 @@ pk_recvspdadd(mhp) || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL || mhp[SADB_X_EXT_POLICY] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spdadd message passed.\n"); return -1; } - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; #ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, @@ -2395,7 +2391,7 @@ pk_recvspdadd(mhp) sp = getsp(&spidx); if (sp != NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "such policy already exists. " "anyway replace it: %s\n", spidx2str(&spidx)); @@ -2414,32 +2410,32 @@ pk_recvspdadd(mhp) */ int pk_sendspddelete(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { - struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen; + struct policyindex *spidx = iph2->spidx_gen; caddr_t policy = NULL; int policylen; if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "getting sadb policy failed.\n"); return -1; } if (pfkey_send_spddelete( lcconf->sock_pfkey, - (struct sockaddr *)&spidx->src, + &spidx->src, spidx->prefs, - (struct sockaddr *)&spidx->dst, + &spidx->dst, spidx->prefd, spidx->ul_proto, policy, policylen, 0) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "libipsec failed send spddelete (%s)\n", ipsec_strerror()); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spddelete\n"); + plog(ASL_LEVEL_DEBUG, "call pfkey_send_spddelete\n"); end: if (policy) @@ -2462,13 +2458,13 @@ pk_recvspddelete(mhp) || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL || mhp[SADB_X_EXT_POLICY] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spddelete message passed.\n"); return -1; } - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; #ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, @@ -2491,12 +2487,14 @@ pk_recvspddelete(mhp) sp = getsp(&spidx); if (sp == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "no policy found: %s\n", spidx2str(&spidx)); return -1; } + ike_session_purgephXbyspid(xpl->sadb_x_policy_id, true); + remsp(sp); delsp(sp); @@ -2517,13 +2515,13 @@ pk_recvspdexpire(mhp) || mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL || mhp[SADB_X_EXT_POLICY] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spdexpire message passed.\n"); return -1; } - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; #ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, @@ -2546,12 +2544,14 @@ pk_recvspdexpire(mhp) sp = getsp(&spidx); if (sp == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "no policy found: %s\n", spidx2str(&spidx)); return -1; } + ike_session_purgephXbyspid(xpl->sadb_x_policy_id, false); + remsp(sp); delsp(sp); @@ -2564,7 +2564,7 @@ pk_recvspdget(mhp) { /* sanity check */ if (mhp[0] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spdget message passed.\n"); return -1; } @@ -2584,18 +2584,18 @@ pk_recvspddump(mhp) /* sanity check */ if (mhp[0] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spddump message passed.\n"); return -1; } - msg = (struct sadb_msg *)mhp[0]; + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; + daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; if (saddr == NULL || daddr == NULL || xpl == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spddump message passed.\n"); return -1; } @@ -2621,7 +2621,7 @@ pk_recvspddump(mhp) sp = getsp(&spidx); if (sp != NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "such policy already exists. " "anyway replace it: %s\n", spidx2str(&spidx)); @@ -2641,11 +2641,13 @@ pk_recvspdflush(mhp) { /* sanity check */ if (mhp[0] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spdflush message passed.\n"); return -1; } + ike_session_flush_all_phase2(false); + ike_session_flush_all_phase1(false); flushsp(); return 0; @@ -2656,7 +2658,7 @@ pk_recvspdflush(mhp) */ int pk_sendeacquire(iph2) - struct ph2handle *iph2; + phase2_handle_t *iph2; { struct sadb_msg *newmsg; int len; @@ -2664,7 +2666,7 @@ pk_sendeacquire(iph2) len = sizeof(struct sadb_msg); newmsg = racoon_calloc(1, len); if (newmsg == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get buffer to send acquire.\n"); return -1; } @@ -2687,6 +2689,145 @@ pk_sendeacquire(iph2) return 0; } +int +pk_sendget_inbound_sastats(ike_session_t *session) +{ + u_int32_t max_stats; + u_int32_t seq; + + if (!session) { + plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__); + return -1; + } + + session->traffic_monitor.num_in_curr_req = 0; + bzero(session->traffic_monitor.in_curr_req, sizeof(session->traffic_monitor.in_curr_req)); + max_stats = (sizeof(session->traffic_monitor.in_curr_req) / sizeof(session->traffic_monitor.in_curr_req[0])); + + // get list of SAs + if ((session->traffic_monitor.num_in_curr_req = ike_session_get_sas_for_stats(session, + IPSEC_DIR_INBOUND, + &seq, + session->traffic_monitor.in_curr_req, + max_stats))) { + u_int64_t session_ids[] = {(u_int64_t)session, 0}; + + //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__); + + if (pfkey_send_getsastats(lcconf->sock_pfkey, + seq, + session_ids, + 1, + IPSEC_DIR_INBOUND, + session->traffic_monitor.in_curr_req, + session->traffic_monitor.num_in_curr_req) < 0) { + return -1; + } + //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__); + + return session->traffic_monitor.num_in_curr_req; + } + return 0; +} + +int +pk_sendget_outbound_sastats(ike_session_t *session) +{ + u_int32_t max_stats; + u_int32_t seq; + + if (!session) { + plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__); + return -1; + } + + session->traffic_monitor.num_out_curr_req = 0; + bzero(session->traffic_monitor.out_curr_req, sizeof(session->traffic_monitor.out_curr_req)); + max_stats = (sizeof(session->traffic_monitor.out_curr_req) / sizeof(session->traffic_monitor.out_curr_req[0])); + + // get list of SAs + if ((session->traffic_monitor.num_out_curr_req = ike_session_get_sas_for_stats(session, + IPSEC_DIR_OUTBOUND, + &seq, + session->traffic_monitor.out_curr_req, + max_stats))) { + u_int64_t session_ids[] = {(u_int64_t)session, 0}; + + //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__); + + if (pfkey_send_getsastats(lcconf->sock_pfkey, + seq, + session_ids, + 1, + IPSEC_DIR_OUTBOUND, + session->traffic_monitor.out_curr_req, + session->traffic_monitor.num_out_curr_req) < 0) { + return -1; + } + //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__); + + return session->traffic_monitor.num_out_curr_req; + } + return 0; +} + +/* + * receive GETSPDSTAT from kernel. + */ +static int +pk_recvgetsastat(mhp) +caddr_t *mhp; +{ + struct sadb_msg *msg; + struct sadb_session_id *session_id; + struct sadb_sastat *stat_resp; + ike_session_t *session; + + /* validity check */ + if (mhp[0] == NULL || + mhp[SADB_EXT_SESSION_ID] == NULL || + mhp[SADB_EXT_SASTAT] == NULL) { + plog(ASL_LEVEL_ERR, + "inappropriate sadb getsastat response.\n"); + return -1; + } + msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to structs in an aligned buffer + session_id = ALIGNED_CAST(struct sadb_session_id *)mhp[SADB_EXT_SESSION_ID]; + stat_resp = ALIGNED_CAST(struct sadb_sastat *)mhp[SADB_EXT_SASTAT]; + + /* the message has to be processed or not ? */ + if (msg->sadb_msg_pid != getpid()) { + plog(ASL_LEVEL_DEBUG, + "%s message is not interesting " + "because pid %d is not mine.\n", + s_pfkey_type(msg->sadb_msg_type), + msg->sadb_msg_pid); + return -1; + } + if (!session_id->sadb_session_id_v[0]) { + plog(ASL_LEVEL_DEBUG, + "%s message is bad " + "because session-id[0] is invalid.\n", + s_pfkey_type(msg->sadb_msg_type)); + return -1; + } + session = ALIGNED_CAST(__typeof__(session))session_id->sadb_session_id_v[0]; + + if (!stat_resp->sadb_sastat_list_len) { + plog(ASL_LEVEL_DEBUG, + "%s message is bad " + "because it has no sastats.\n", + s_pfkey_type(msg->sadb_msg_type)); + return -1; + } + + ike_session_update_traffic_idle_status(session, + stat_resp->sadb_sastat_dir, + (struct sastat *)(stat_resp + 1), + stat_resp->sadb_sastat_list_len); + return 0; +} + /* * check if the algorithm is supported or not. * OUT 0: ok @@ -2708,12 +2849,9 @@ pk_checkalg(class, calg, keylen) sup = SADB_EXT_SUPPORTED_AUTH; break; case IPSECDOI_PROTO_IPCOMP: - plog(LLV_DEBUG, LOCATION, NULL, - "compression algorithm can not be checked " - "because sadb message doesn't support it.\n"); return 0; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid algorithm class.\n"); return -1; } @@ -2723,7 +2861,7 @@ pk_checkalg(class, calg, keylen) if (keylen == 0) { if (ipsec_get_keylen(sup, alg, &alg0)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "%s.\n", ipsec_strerror()); return -1; } @@ -2732,7 +2870,7 @@ pk_checkalg(class, calg, keylen) error = ipsec_check_keylen(sup, alg, keylen); if (error) - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "%s.\n", ipsec_strerror()); return error; @@ -2747,8 +2885,8 @@ pk_checkalg(class, calg, keylen) */ static struct sadb_msg * pk_recv(so, lenp) -int so; -int *lenp; + int so; + ssize_t *lenp; { struct sadb_msg *newmsg; int reallen = 0; @@ -2759,11 +2897,16 @@ int *lenp; if (reallen == 0) return NULL; - + if ((newmsg = racoon_calloc(1, reallen)) == NULL) return NULL; - - *lenp = recv(so, (caddr_t)newmsg, reallen, 0); + + while ((*lenp = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { + if (errno == EINTR) + continue; + plog(ASL_LEVEL_ERR, "failed to recv pfkey message: %s\n", strerror(errno)); + break; + } if (*lenp < 0) { racoon_free(newmsg); return NULL; /*fatal*/ @@ -2771,11 +2914,10 @@ int *lenp; racoon_free(newmsg); return NULL; } - + return newmsg; } - /* see handler.h */ u_int32_t pk_getseq() @@ -2795,26 +2937,18 @@ addnewsp(mhp) if (mhp[SADB_EXT_ADDRESS_SRC] == NULL || mhp[SADB_EXT_ADDRESS_DST] == NULL || mhp[SADB_X_EXT_POLICY] == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "inappropriate sadb spd management message passed.\n"); return -1; } - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; - daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; - xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; - -#ifdef __linux__ - /* bsd skips over per-socket policies because there will be no - * src and dst extensions in spddump messages. On Linux the only - * way to achieve the same is check for policy id. - */ - if (xpl->sadb_x_policy_id % 8 >= 3) return 0; -#endif + saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer + daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; + xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; new = newsp(); if (new == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to allocate buffer\n"); return -1; } @@ -2841,7 +2975,7 @@ addnewsp(mhp) /* validity check */ if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid msg length.\n"); return -1; } @@ -2853,7 +2987,7 @@ addnewsp(mhp) /* length check */ if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid msg length.\n"); return -1; } @@ -2861,7 +2995,7 @@ addnewsp(mhp) /* allocate request buffer */ *p_isr = newipsecreq(); if (*p_isr == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get new ipsecreq.\n"); return -1; } @@ -2875,7 +3009,7 @@ addnewsp(mhp) case IPPROTO_IPCOMP: break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid proto type: %u\n", xisr->sadb_x_ipsecrequest_proto); return -1; @@ -2888,7 +3022,7 @@ addnewsp(mhp) break; case IPSEC_MODE_ANY: default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid mode: %u\n", xisr->sadb_x_ipsecrequest_mode); return -1; @@ -2906,7 +3040,7 @@ addnewsp(mhp) break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid level: %u\n", xisr->sadb_x_ipsecrequest_level); return -1; @@ -2935,17 +3069,17 @@ addnewsp(mhp) /* validity check */ if (tlen < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "becoming tlen < 0\n"); } - xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr + xisr = ALIGNED_CAST(struct sadb_x_ipsecrequest *)((caddr_t)xisr + xisr->sadb_x_ipsecrequest_len); } } break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid policy type.\n"); return -1; } @@ -2977,7 +3111,7 @@ addnewsp(mhp) /* proto/mode/src->dst spi */ const char * sadbsecas2str(src, dst, proto, spi, mode) - struct sockaddr *src, *dst; + struct sockaddr_storage *src, *dst; int proto; u_int32_t spi; int mode; @@ -3008,13 +3142,13 @@ sadbsecas2str(src, dst, proto, spi, mode) p += i; blen -= i; - i = snprintf(p, blen, "%s->", saddr2str(src)); + i = snprintf(p, blen, "%s->", saddr2str((struct sockaddr *)src)); if (i < 0 || i >= blen) return NULL; p += i; blen -= i; - i = snprintf(p, blen, "%s ", saddr2str(dst)); + i = snprintf(p, blen, "%s ", saddr2str((struct sockaddr *)dst)); if (i < 0 || i >= blen) return NULL; p += i;