From: Joy L. <la...@au...> - 2007-09-07 20:35:38
|
This patch enables racoon to create SAs over loopback in a labeled networking environment only. Currently, labeled SAs are created between two machines to apply MAC/MLS to network communications. Unfortunately, racoon's not being able to create labeled SAs over loopback has been considered a hole. This patch attempts to eliminate that hole. No encryption nor authentication is required. It is the label that is needed most. Thus, sainfo is not used. Info from policy and ACQUIRE are used to determine SA. I have tested this via stress tests to ensure all works and nothing is broken. I shall run an additional stress test over weekend. Let me know if this patch is ok. Regards, Joy diff -urpN ipsec-tools/src/racoon/handler.h ipsec.tools.patch/src/racoon/handler.h --- ipsec-tools/src/racoon/handler.h 2006-09-09 11:22:09.000000000 -0500 +++ ipsec.tools.patch/src/racoon/handler.h 2007-09-07 13:14:23.000000000 -0500 @@ -284,6 +284,9 @@ struct ph2handle { u_int8_t flags; /* Flags for phase 2 */ u_int32_t msgid; /* msgid for phase 2 */ +#ifdef HAVE_SECCTX + u_int8_t loopback; /* loopback SA */ +#endif /* HAVE_SECCTX */ struct sainfo *sainfo; /* place holder of sainfo */ struct saprop *proposal; /* SA(s) proposal. */ diff -urpN ipsec-tools/src/racoon/pfkey.c ipsec.tools.patch/src/racoon/pfkey.c --- ipsec-tools/src/racoon/pfkey.c 2007-07-18 07:07:52.000000000 -0500 +++ ipsec.tools.patch/src/racoon/pfkey.c 2007-09-07 13:14:08.000000000 -0500 @@ -972,6 +972,56 @@ pk_recvgetspi(mhp) return -1; } +#ifdef HAVE_SECCTX + if (iph2->loopback == 1) { + struct sockaddr *src; + + src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); + if (cmpsaddrstrict(src, dst) == 0) { + struct pfkey_send_sa_args sa_args; + u_int satype; + + /* yep, this is loopback. install SA */ + satype = ipsecdoi2pfkey_proto(iph2->proposal->head->proto_id); + if (satype == ~0) { + plog(LLV_ERROR, LOCATION, NULL, + "invalid proto_id %d\n", + iph2->proposal->head->proto_id); + return -1; + } + + memset(&sa_args, 0, sizeof(sa_args)); + sa_args.so = lcconf->sock_pfkey; + sa_args.satype = satype; + sa_args.mode = IPSEC_MODE_TRANSPORT; + sa_args.src = src; + sa_args.dst = dst; + sa_args.spi = sa->sadb_sa_spi; + sa_args.reqid = iph2->proposal->head->reqid_in; + sa_args.keymat = NULL; + sa_args.e_type = SADB_EALG_NULL; + sa_args.a_type = SADB_AALG_NONE; + sa_args.l_addtime = iph2->proposal->lifetime; + sa_args.seq = iph2->seq; + sa_args.ctxdoi = iph2->proposal->sctx.ctx_doi; + sa_args.ctxalg = iph2->proposal->sctx.ctx_alg; + sa_args.ctxstr = iph2->proposal->sctx.ctx_str; + sa_args.ctxstrlen = iph2->proposal->sctx.ctx_strlen; + + iph2->status = PHASE2ST_ADDSA; + if (pfkey_send_update2(&sa_args) < 0) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to update loopback SA: %s\n", + ipsec_strerror()); + remph2(iph2); + delph2(iph2); + return -1; + } + } + return 0; + } +#endif /* HAVE SECCTX */ + /* set SPI, and check to get all spi whether or not */ allspiok = 1; notfound = 1; @@ -1222,6 +1272,25 @@ pk_recvupdate(mhp) return -1; } +#ifdef HAVE_SECCTX + /* get update for loopback here */ + if (iph2->loopback == 1 && (cmpsaddrstrict(src, dst) == 0)) { + plog(LLV_INFO, LOCATION, NULL, + "IPsec-SA established without ISAKMP: %s\n", + sadbsecas2str(iph2->dst, iph2->src, + msg->sadb_msg_satype, sa->sadb_sa_spi, + IPSEC_MODE_TRANSPORT)); + + /* turn off the timer for calling pfkey_timeover() */ + SCHED_KILL(iph2->sce); + + iph2->sce = sched_new(iph2->proposal->lifetime, + isakmp_ph2expire_stub, iph2); + + iph2->status = PHASE2ST_ESTABLISHED; + return 0; + } +#endif /* check to complete all keys ? */ for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype); @@ -1641,7 +1710,7 @@ pk_recvacquire(mhp) struct sadb_x_sec_ctx *m_sec_ctx; #endif /* HAVE_SECCTX */ struct policyindex spidx; - + int do_listen; /* ignore this message because of local test mode. */ if (f_local) @@ -1714,7 +1783,6 @@ pk_recvacquire(mhp) */ struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); struct myaddrs *p; - int do_listen = 0; for (p = lcconf->myaddrs; p; p = p->next) { if (!cmpsaddrwop(p->addr, sa)) { do_listen = 1; @@ -1828,6 +1896,67 @@ pk_recvacquire(mhp) plog(LLV_DEBUG, LOCATION, NULL, "new acquire %s\n", spidx2str(&sp_out->spidx)); +#ifdef HAVE_SECCTX + /* + * If the src address in the ACQUIRE is one we listen on and + * the src and dst addresses are the same, then assume this + * packet arrived over loopback and just get an SPI and + * install the SA. + */ + if (do_listen && m_sec_ctx && (cmpsaddrstrict(src, dst) == 0)) { + struct saprop *newpp; + struct saproto *newpr; + iph2[n]->loopback = 1; + newpp = newsaprop(); + if (newpp == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to allocate saprop.\n"); + delph2(iph2[n]); + return -1; + } + /* allocate to hold reqid */ + newpr = newsaproto(); + if (newpr == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to allocate saproto.\n"); + delph2(iph2[n]); + return -1; + } + + newpr->reqid_out = sp_out->req->saidx.reqid; + newpr->reqid_in = sp_in->req->saidx.reqid; + newpr->proto_id = ipproto2doi(sp_out->req->saidx.proto); + + inssaprotorev(newpp, newpr); + iph2[n]->proposal = newpp; + printsaprop0(LLV_DEBUG, newpp); + + set_secctx_in_proposal(iph2[n], spidx); + iph2[n]->proposal->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT; + + insph2(iph2[n]); + + iph2[n]->status = PHASE2ST_GETSPISENT; + plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n"); + if (pfkey_send_getspi( lcconf->sock_pfkey, iph2[n]->satype, + IPSEC_MODE_TRANSPORT, dst, src, 0, 0, + newpr->reqid_in, iph2[n]->seq) < 0) { + plog(LLV_ERROR, LOCATION, NULL, + "ipseclib failed send getspi (%s)\n", + ipsec_strerror()); + delph2(iph2[n]); + return -1; + } + iph2[n]->sce = sched_new(lcconf->wait_ph2complete, + pfkey_timeover_stub, iph2[n]); + plog(LLV_DEBUG, LOCATION, NULL, + "pfkey GETSPI sent: %s\n", + sadbsecas2str(dst, src, iph2[n]->satype, 0, + IPSEC_MODE_TRANSPORT)); + return 0; + } +#endif /* HAVE_SECCTX */ + /* get sainfo */ { vchar_t *idsrc, *iddst; |