spidx.ul_proto = IPSEC_ULPROTO_ANY;
/* get inbound policy */
- sp_in = getsp_r(&spidx);
+ sp_in = getsp_r(&spidx, iph2);
if (sp_in == NULL || sp_in->policy == IPSEC_POLICY_GENERATE) {
if (iph2->ph1->rmconf->gen_policy) {
if (sp_in)
"no policy found: %s\n", spidx2str(&spidx));
return ISAKMP_INTERNAL_ERROR;
}
- } else {
- /* Refresh existing generated policies
- */
- if (iph2->ph1->rmconf->gen_policy) {
- plog(LLV_INFO, LOCATION, NULL,
- "Update the generated policy : %s\n",
- spidx2str(&spidx));
- iph2->spidx_gen = racoon_malloc(sizeof(spidx));
- if (!iph2->spidx_gen) {
- plog(LLV_ERROR, LOCATION, NULL,
- "buffer allocation failed.\n");
- return ISAKMP_INTERNAL_ERROR;
- }
- memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
- }
}
/* get outbound policy */
spidx.prefs = spidx.prefd;
spidx.prefd = pref;
- sp_out = getsp_r(&spidx);
+ sp_out = getsp_r(&spidx, iph2);
if (!sp_out) {
plog(LLV_WARNING, LOCATION, NULL,
"no outbound policy found: %s\n",
static void save_params __P((void));
static void saverestore_params __P((int));
static void cleanup_pidfile __P((void));
-static int launchedbylaunchd(void);
+int launchedbylaunchd __P((void));
pid_t racoon_pid = 0;
int print_pid = 1; /* for racoon only */
}
-static int
+int
launchedbylaunchd(){
int launchdlaunched = 1;
launch_data_t checkin_response = NULL;
case ISAKMP_CERT_X509SIGN:
case ISAKMP_CERT_KERBEROS:
case ISAKMP_CERT_SPKI:
+ if (iph1->cr_p) {
+ oakley_delcert(iph1->cr_p);
+ iph1->cr_p = NULL;
+ }
c = &iph1->cr_p;
break;
case ISAKMP_CERT_X509KE:
VPTRINIT(cert->pl);
racoon_free(cert);
}
-
+
/*
* compute IV and set to ph1handle
* IV = hash(g^xi | g^xr)
*/
#if 1
struct secpolicy *
-getsp_r(spidx)
+getsp_r(spidx, iph2)
struct policyindex *spidx;
+ struct ph2handle *iph2;
{
struct secpolicy *p;
+ int mismatched_outer_addr = 0;
for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
- if (!cmpspidxwild(spidx, &p->spidx))
- return p;
+ if (!cmpspidxwild(spidx, &p->spidx)) {
+ if (spidx->dir != IPSEC_DIR_ANY) {
+ struct ipsecrequest *isr;
+ for (isr = p->req; isr != NULL; isr = isr->next) {
+ if (isr->saidx.mode != IPSEC_MODE_TUNNEL) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "%s, skipping policy. dir %d, mode %d\n",
+ __FUNCTION__, spidx->dir, isr->saidx.mode);
+ continue;
+ }
+
+ // for tunnel mode: verify the outer ip addresses match the phase2's addresses
+ if (spidx->dir == IPSEC_DIR_INBOUND) {
+ // TODO: look out for wildcards
+ if (!cmpsaddrwop(iph2->dst, (struct sockaddr *)&isr->saidx.src) &&
+ !cmpsaddrwop(iph2->src, (struct sockaddr *)&isr->saidx.dst)) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "%s, inbound policy outer addresses matched phase2's addresses\n",
+ __FUNCTION__);
+ return p;
+ } else {
+ mismatched_outer_addr = 1;
+ }
+ } else if (spidx->dir == IPSEC_DIR_OUTBOUND) {
+ // TODO: look out for wildcards
+ if (!cmpsaddrwop(iph2->src, (struct sockaddr *)&isr->saidx.src) &&
+ !cmpsaddrwop(iph2->dst, (struct sockaddr *)&isr->saidx.dst)) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "%s, outbound policy outer addresses matched phase2's addresses\n",
+ __FUNCTION__);
+ return p;
+ } else {
+ mismatched_outer_addr = 1;
+ }
+ } else {
+ mismatched_outer_addr = 1;
+ }
+ if (mismatched_outer_addr) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "%s, policy outer addresses matched phase2's addresses: dir %d\n",
+ __FUNCTION__, spidx->dir);
+ plog(LLV_DEBUG, LOCATION, NULL, "src1: %s\n",
+ saddr2str(iph2->src));
+ plog(LLV_DEBUG, LOCATION, NULL, "src2: %s\n",
+ saddr2str((struct sockaddr *)&isr->saidx.src));
+ plog(LLV_DEBUG, LOCATION, NULL, "dst1: %s\n",
+ saddr2str(iph2->dst));
+ plog(LLV_DEBUG, LOCATION, NULL, "dst2: %s\n",
+ saddr2str((struct sockaddr *)&isr->saidx.dst));
+ }
+ }
+ }
+ if (!mismatched_outer_addr) {
+ return p;
+ }
+ }
}
return NULL;
struct ph2handle;
struct policyindex;
extern struct secpolicy *getsp __P((struct policyindex *));
-extern struct secpolicy *getsp_r __P((struct policyindex *));
+extern struct secpolicy *getsp_r __P((struct policyindex *, struct ph2handle *));
struct secpolicy *getspbyspid __P((u_int32_t));
extern int cmpspidxstrict __P((struct policyindex *, struct policyindex *));
extern int cmpspidxwild __P((struct policyindex *, struct policyindex *));
#include <resolv.h>
#include <TargetConditionals.h>
+#if __APPLE__
+#include <vproc_priv.h>
+#endif
#include "libpfkey.h"
extern pid_t racoon_pid;
+extern int launchedbylaunchd(void);
static void close_session __P((void));
static void check_rtsock __P((void *));
static void initfds __P((void));
initfds();
}
+#ifdef __APPLE__
+static int64_t racoon_keepalive = -1;
+
+/*
+ * This is used to (manually) update racoon's launchd keepalive, which is needed because racoon is (mostly)
+ * launched on demand and for <rdar://problem/8773022> requires a keepalive on dirty/failure exits.
+ * The launchd plist can't be used for this because RunOnLoad is required to have keepalive on a failure exit.
+ */
+int64_t
+launchd_update_racoon_keepalive (Boolean enabled)
+{
+ if (launchedbylaunchd()) {
+ vproc_t vp = vprocmgr_lookup_vproc("com.apple.racoon");
+ if (vp) {
+ int64_t val = (__typeof__(val))enabled;
+ if (vproc_swap_integer(vp,
+ VPROC_GSK_BASIC_KEEPALIVE,
+ &val,
+ &racoon_keepalive)) {
+ plog(LLV_ERROR2, LOCATION, NULL,
+ "failed to swap launchd keepalive integer %d\n", enabled);
+ }
+ vproc_release(vp);
+ }
+ }
+ return racoon_keepalive;
+}
+#endif // __APPLE__
+
int
session(void)
{
"cannot open %s", pid_file);
}
}
-
+
+#ifdef __APPLE__
+#if !TARGET_OS_EMBEDDED
+ // enable keepalive for recovery (from crashes and bad exits... after init)
+ (void)launchd_update_racoon_keepalive(true);
+#endif // !TARGET_OS_EMBEDDED
+#endif // __APPLE__
+
while (1) {
if (!TAILQ_EMPTY(&lcconf->saved_msg_queue))
pfkey_post_handler();
close_sockets();
backupsa_clean();
+#ifdef __APPLE__
+#if !TARGET_OS_EMBEDDED
+ // a clean exit, so disable launchd keepalive
+ (void)launchd_update_racoon_keepalive(false);
+#endif // !TARGET_OS_EMBEDDED
+#endif // __APPLE__
+
plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
exit(0);
}