From: Joy L. <la...@au...> - 2006-11-01 00:16:06
|
This patchset adds to ipsec-tools the ability for racoon to negotiate and establish SAs that include a security context, in particular an SELinux security context. This leverages IPSec to establish MAC in Linux networking. This patchset was built and generated against the ipsec-tools code in cvs at Modifications to the man pages were integrated earlier this year when the setkey patch to add security contexts was accepted. No modifications were made to racoon's configuration, so there were no changes to racoon.conf man page. The following patch is the second of two. This patch, allows racoon to pass security contexts in its proposals. When an ipsec policy contains a security context, the Linux kernel will include a security context in the ACQUIRE message it sends to racoon. The initiating racoon, includes this security context in its proposal. The responding racoon usually pulls up a corresponding ipsec policy and sets a proposal from the policy. In this new scheme, racoon needs to pull up the policy that matches not only the policyindex, but the security context too. It is possible for a traffic stream to have multiple policies differentiated only by the security contexts. So, responding racoon peeks into the received proposal for the security context and includes it in policyindex to ensure we pull up the correct policy. The responding racoon uses this security context in his own proposal too. The resulting SA pairs are established containing this security context. The routine, within_range() checks to make sure that the "proposed" security context is "within_range" of the security context in the policy. This is an selinux specific check. The routine, avc_has_perm() checks selinux policy to see if the proposed SA security context has permission to use the security context in the policy. If not, it could indicate a process is trying to establish an SA that it doesn't have permission to. For example, a top secret process is trying to send something to a secret process and it is not permitted to based on selinux policy's permisions. When this happens, negotiations will fail because racoon could not find a policy. This functionality has been used/tested by several LSPP developers and continues to undergo testing at this time. This patchset was built and generated against the ipsec-tools code in cvs at anoncvs.netbsd.org. Please let me know if this is correct or not and if all appears ok or not. Regards, Joy Latten ------------------------------------------------------------------ diff -urpN ipsec-tools.part1/configure.ac ipsec-tools.part2/configure.ac --- ipsec-tools.part1/configure.ac 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/configure.ac 2006-10-30 17:36:41.000000000 -0600 @@ -768,6 +768,7 @@ if test "$enable_security_context" = "ye AC_DEFINE([HAVE_SECCTX], [], [Enable Security Context]) SECCTX_OBJS="security.o" AC_SUBST(SECCTX_OBJS) + LIBS="$LIBS -lselinux" fi fi diff -urpN ipsec-tools.part1/src/libipsec/pfkey.c ipsec-tools.part2/src/libipsec/pfkey.c --- ipsec-tools.part1/src/libipsec/pfkey.c 2006-10-30 18:05:37.000000000 -0600 +++ ipsec-tools.part2/src/libipsec/pfkey.c 2006-10-31 09:19:30.000000000 -0600 @@ -599,7 +599,7 @@ pfkey_send_add(so, satype, mode, src, ds keymat, e_type, e_keylen, a_type, a_keylen, flags, l_alloc, (u_int)l_bytes, (u_int)l_addtime, (u_int)l_usetime, seq, 0, 0, 0, NULL, 0, - ctxdoi, ctxalg, ctxstr, ctxstrlen)) < 0) + ctxdoi, ctxalg, ctxstr, ctxstrlen)) < 0) return -1; return len; diff -urpN ipsec-tools.part1/src/racoon/cftoken.l ipsec-tools.part2/src/racoon/cftoken.l --- ipsec-tools.part1/src/racoon/cftoken.l 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/cftoken.l 2006-10-31 09:50:50.000000000 -0600 @@ -72,6 +72,7 @@ #include "isakmp_var.h" #include "isakmp.h" #include "ipsec_doi.h" +#include "policy.h" #include "proposal.h" #include "remoteconf.h" #ifdef GC diff -urpN ipsec-tools.part1/src/racoon/ipsec_doi.c ipsec-tools.part2/src/racoon/ipsec_doi.c --- ipsec-tools.part1/src/racoon/ipsec_doi.c 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/ipsec_doi.c 2006-10-30 18:32:24.000000000 -0600 @@ -2439,6 +2439,16 @@ ahmismatch: } break; +#ifdef HAVE_SECCTX + case IPSECDOI_ATTR_SECCTX: + if (flag) { + plog(LLV_ERROR, LOCATION, NULL, + "SECCTX must be in TLV.\n"); + return -1; + } + break; +#endif + case IPSECDOI_ATTR_KEY_ROUNDS: case IPSECDOI_ATTR_COMP_DICT_SIZE: case IPSECDOI_ATTR_COMP_PRIVALG: @@ -2942,6 +2952,9 @@ setph2proposal0(iph2, pp, pr) caddr_t x0, x; u_int8_t *np_t; /* pointer next trns type in previous header */ const u_int8_t *spi; +#ifdef HAVE_SECCTX + int truectxlen = 0; +#endif p = vmalloc(sizeof(*prop) + sizeof(pr->spi)); if (p == NULL) @@ -3044,6 +3057,17 @@ setph2proposal0(iph2, pp, pr) if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group)) attrlen += sizeof(struct isakmp_data); +#ifdef HAVE_SECCTX + /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ]. + * The string may be smaller than MAX_CTXSTR_SIZ. + */ + if (*pp->sctx.ctx_str) { + truectxlen = sizeof(struct security_ctx) - + (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen); + attrlen += sizeof(struct isakmp_data) + truectxlen; + } +#endif /* HAVE_SECCTX */ + p = vrealloc(p, p->l + sizeof(*trns) + attrlen); if (p == NULL) return NULL; @@ -3098,6 +3122,11 @@ setph2proposal0(iph2, pp, pr) x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC, iph2->sainfo->pfs_group); +#ifdef HAVE_SECCTX + if (*pp->sctx.ctx_str) + x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX, + (caddr_t)&pp->sctx, truectxlen); +#endif /* update length of this transform. */ trns = (struct isakmp_pl_t *)(p->v + trnsoff); trns->h.len = htons(sizeof(*trns) + attrlen); @@ -4645,7 +4674,14 @@ ipsecdoi_t2satrns(t, pp, pr, tr) } tr->encklen = ntohs(d->lorv); break; - +#ifdef HAVE_SECCTX + case IPSECDOI_ATTR_SECCTX: + { + int len = ntohs(d->lorv); + memcpy(&pp->sctx, d + 1, len); + break; + } +#endif /* HAVE_SECCTX */ case IPSECDOI_ATTR_KEY_ROUNDS: case IPSECDOI_ATTR_COMP_DICT_SIZE: case IPSECDOI_ATTR_COMP_PRIVALG: diff -urpN ipsec-tools.part1/src/racoon/ipsec_doi.h ipsec-tools.part2/src/racoon/ipsec_doi.h --- ipsec-tools.part1/src/racoon/ipsec_doi.h 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/ipsec_doi.h 2006-10-30 17:36:41.000000000 -0600 @@ -136,6 +136,10 @@ #define IPSECDOI_ATTR_COMP_DICT_SIZE 8 /* B */ #define IPSECDOI_ATTR_COMP_PRIVALG 9 /* V */ +#ifdef HAVE_SECCTX +#define IPSECDOI_ATTR_SECCTX 10 /* V */ +#endif + /* 4.6.1 Security Association Payload */ struct ipsecdoi_pl_sa { struct isakmp_gen h; diff -urpN ipsec-tools.part1/src/racoon/isakmp_inf.c ipsec-tools.part2/src/racoon/isakmp_inf.c --- ipsec-tools.part1/src/racoon/isakmp_inf.c 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/isakmp_inf.c 2006-10-30 18:25:33.000000000 -0600 @@ -78,6 +78,7 @@ #include "remoteconf.h" #include "sockmisc.h" #include "handler.h" +#include "policy.h" #include "proposal.h" #include "isakmp_var.h" #include "evt.h" diff -urpN ipsec-tools.part1/src/racoon/isakmp_quick.c ipsec-tools.part2/src/racoon/isakmp_quick.c --- ipsec-tools.part1/src/racoon/isakmp_quick.c 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/isakmp_quick.c 2006-10-30 18:25:55.000000000 -0600 @@ -73,6 +73,7 @@ #include "localconf.h" #include "remoteconf.h" #include "handler.h" +#include "policy.h" #include "proposal.h" #include "isakmp_var.h" #include "isakmp.h" @@ -2088,6 +2089,19 @@ get_proposal_r(iph2) if (spidx.ul_proto == 0) spidx.ul_proto = IPSEC_ULPROTO_ANY; +#ifdef HAVE_SECCTX + /* + * Need to use security context in spidx to ensure the correct + * policy is selected. The only way to get the security context + * is to look into the proposal sent by peer ahead of time. + */ + if (get_security_context(iph2->sa, &spidx)) { + plog(LLV_ERROR, LOCATION, NULL, + "error occurred trying to get security context.\n"); + return ISAKMP_INTERNAL_ERROR; + } +#endif /* HAVE_SECCTX */ + /* get inbound policy */ sp_in = getsp_r(&spidx); if (sp_in == NULL) { @@ -2166,6 +2180,12 @@ get_proposal_r(iph2) return ISAKMP_INTERNAL_ERROR; } +#ifdef HAVE_SECCTX + if (spidx.sec_ctx.ctx_str) { + set_secctx_in_proposal(iph2, spidx); + } +#endif /* HAVE_SECCTX */ + return 0; } diff -urpN ipsec-tools.part1/src/racoon/Makefile.am ipsec-tools.part2/src/racoon/Makefile.am --- ipsec-tools.part1/src/racoon/Makefile.am 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/Makefile.am 2006-10-30 18:36:12.000000000 -0600 @@ -31,12 +31,12 @@ racoon_SOURCES = \ safefile.c backupsa.c genlist.c rsalist.c \ cftoken.l cfparse.y prsa_tok.l prsa_par.y EXTRA_racoon_SOURCES = isakmp_xauth.c isakmp_cfg.c isakmp_unity.c throttle.c \ - isakmp_frag.c nattraversal.c $(MISSING_ALGOS) + isakmp_frag.c nattraversal.c security.c $(MISSING_ALGOS) racoon_LDFLAGS = ../libipsec/libipsec.la racoon_LDADD = $(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) $(LEXLIB) \ - vmbuf.o sockmisc.o misc.o + $(SECCTX_OBJS) vmbuf.o sockmisc.o misc.o racoon_DEPENDENCIES = ../libipsec/libipsec.la \ - $(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) \ + $(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) $(SECCTX_OBJS) \ vmbuf.o sockmisc.o misc.o racoonctl_SOURCES = racoonctl.c str2val.c diff -urpN ipsec-tools.part1/src/racoon/pfkey.c ipsec-tools.part2/src/racoon/pfkey.c --- ipsec-tools.part1/src/racoon/pfkey.c 2006-10-30 17:23:44.000000000 -0600 +++ ipsec-tools.part2/src/racoon/pfkey.c 2006-10-30 18:50:00.000000000 -0600 @@ -85,6 +85,7 @@ #include "localconf.h" #include "remoteconf.h" #include "handler.h" +#include "policy.h" #include "proposal.h" #include "isakmp_var.h" #include "isakmp.h" @@ -92,7 +93,6 @@ #include "ipsec_doi.h" #include "oakley.h" #include "pfkey.h" -#include "policy.h" #include "algorithm.h" #include "sainfo.h" #include "admin.h" @@ -1100,6 +1100,15 @@ pk_sendupdate(iph2) lifebyte = 0; #endif +#ifdef HAVE_SECCTX + if (*iph2->approval->sctx.ctx_str) { + ctxdoi = iph2->approval->sctx.ctx_doi; + ctxalg = iph2->approval->sctx.ctx_alg; + ctxstrlen = iph2->approval->sctx.ctx_strlen; + ctxstr = iph2->approval->sctx.ctx_str; + } +#endif /* HAVE_SECCTX */ + #ifdef ENABLE_NATT plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update_nat\n"); if (pr->udp_encap) { @@ -1402,6 +1411,15 @@ pk_sendadd(iph2) lifebyte = 0; #endif +#ifdef HAVE_SECCTX + if (*iph2->approval->sctx.ctx_str) { + ctxdoi = iph2->approval->sctx.ctx_doi; + ctxalg = iph2->approval->sctx.ctx_alg; + ctxstrlen = iph2->approval->sctx.ctx_strlen; + ctxstr = iph2->approval->sctx.ctx_str; + } +#endif /* HAVE_SECCTX */ + #ifdef ENABLE_NATT plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add_nat\n"); @@ -1686,6 +1704,11 @@ pk_recvacquire(mhp) struct sockaddr *src, *dst; int n; /* # of phase 2 handler */ int remoteid=0; +#ifdef HAVE_SECCTX + struct sadb_x_sec_ctx *m_sec_ctx; +#endif /* HAVE_SECCTX */ + struct policyindex spidx; + /* ignore this message because of local test mode. */ if (f_local) @@ -1705,6 +1728,22 @@ pk_recvacquire(mhp) src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); +#ifdef HAVE_SECCTX + m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + + if (m_sec_ctx != NULL) { + plog(LLV_INFO, LOCATION, NULL, "security context doi: %u\n", + m_sec_ctx->sadb_x_ctx_doi); + plog(LLV_INFO, LOCATION, NULL, + "security context algorithm: %u\n", + m_sec_ctx->sadb_x_ctx_alg); + plog(LLV_INFO, LOCATION, NULL, "security context length: %u\n", + m_sec_ctx->sadb_x_ctx_len); + plog(LLV_INFO, LOCATION, NULL, "security context: %s\n", + ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx))); + } +#endif /* HAVE_SECCTX */ + /* ignore if type is not IPSEC_POLICY_IPSEC */ if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) { plog(LLV_DEBUG, LOCATION, NULL, @@ -1792,8 +1831,8 @@ pk_recvacquire(mhp) /* get inbound policy */ { - struct policyindex spidx; + memset(&spidx, 0, sizeof(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)); @@ -1801,6 +1840,17 @@ pk_recvacquire(mhp) spidx.prefd = sp_out->spidx.prefs; spidx.ul_proto = sp_out->spidx.ul_proto; +#ifdef HAVE_SECCTX + if (m_sec_ctx) { + spidx.sec_ctx.ctx_doi = m_sec_ctx->sadb_x_ctx_doi; + spidx.sec_ctx.ctx_alg = m_sec_ctx->sadb_x_ctx_alg; + spidx.sec_ctx.ctx_strlen = m_sec_ctx->sadb_x_ctx_len; + memcpy(spidx.sec_ctx.ctx_str, + ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)), + spidx.sec_ctx.ctx_strlen); + } +#endif /* HAVE_SECCTX */ + sp_in = getsp(&spidx); if (sp_in) { plog(LLV_DEBUG, LOCATION, NULL, @@ -1899,6 +1949,12 @@ pk_recvacquire(mhp) delph2(iph2[n]); return -1; } +#ifdef HAVE_SECCTX + if (m_sec_ctx) { + set_secctx_in_proposal(iph2[n], spidx); + } +#endif /* HAVE_SECCTX */ + insph2(iph2[n]); /* start isakmp initiation by using ident exchange */ @@ -2028,6 +2084,11 @@ getsadbpolicy(policy0, policylen0, type, int policylen; int xisrlen; u_int satype, mode; + int len = 0; +#ifdef HAVE_SECCTX + int ctxlen = 0; +#endif /* HAVE_SECCTX */ + /* get policy buffer size */ policylen = sizeof(struct sadb_x_policy); @@ -2043,6 +2104,14 @@ getsadbpolicy(policy0, policylen0, type, } } +#ifdef HAVE_SECCTX + if (*spidx->sec_ctx.ctx_str) { + ctxlen = sizeof(struct sadb_x_sec_ctx) + + PFKEY_ALIGN8(spidx->sec_ctx.ctx_strlen); + policylen += ctxlen; + } +#endif /* HAVE_SECCTX */ + /* make policy structure */ policy = racoon_malloc(policylen); memset((void*)policy, 0xcd, policylen); @@ -2061,12 +2130,30 @@ getsadbpolicy(policy0, policylen0, type, #ifdef HAVE_PFKEY_POLICY_PRIORITY xpl->sadb_x_policy_priority = PRIORITY_DEFAULT; #endif + len++; + +#ifdef HAVE_SECCTX + if (*spidx->sec_ctx.ctx_str) { + struct sadb_x_sec_ctx *p; + + p = (struct sadb_x_sec_ctx *)(xpl + len); + memset(p, 0, ctxlen); + p->sadb_x_sec_len = PFKEY_UNIT64(ctxlen); + p->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; + p->sadb_x_ctx_len = spidx->sec_ctx.ctx_strlen; + p->sadb_x_ctx_doi = spidx->sec_ctx.ctx_doi; + p->sadb_x_ctx_alg = spidx->sec_ctx.ctx_alg; + + memcpy(p + 1,spidx->sec_ctx.ctx_str,spidx->sec_ctx.ctx_strlen); + len += ctxlen; + } +#endif /* HAVE_SECCTX */ /* no need to append policy information any more if type is SPDDELETE */ if (type == SADB_X_SPDDELETE) goto end; - xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); + xisr = (struct sadb_x_ipsecrequest *)(xpl + len); /* The order of things is reversed for use in add policy messages */ for (pr = iph2->approval->head; pr; pr = pr->next) rlist_len++; @@ -2228,6 +2315,18 @@ pk_recvspdupdate(mhp) &spidx); #endif +#ifdef HAVE_SECCTX + if (mhp[SADB_X_EXT_SEC_CTX] != NULL) { + struct sadb_x_sec_ctx *ctx; + + ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg; + spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi; + spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len; + memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len); + } +#endif /* HAVE_SECCTX */ + sp = getsp(&spidx); if (sp == NULL) { plog(LLV_ERROR, LOCATION, NULL, @@ -2329,6 +2428,18 @@ pk_recvspdadd(mhp) &spidx); #endif +#ifdef HAVE_SECCTX + if (mhp[SADB_X_EXT_SEC_CTX] != NULL) { + struct sadb_x_sec_ctx *ctx; + + ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg; + spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi; + spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len; + memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len); + } +#endif /* HAVE_SECCTX */ + sp = getsp(&spidx); if (sp != NULL) { plog(LLV_ERROR, LOCATION, NULL, @@ -2425,6 +2536,18 @@ pk_recvspddelete(mhp) &spidx); #endif +#ifdef HAVE_SECCTX + if (mhp[SADB_X_EXT_SEC_CTX] != NULL) { + struct sadb_x_sec_ctx *ctx; + + ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg; + spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi; + spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len; + memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len); + } +#endif /* HAVE_SECCTX */ + sp = getsp(&spidx); if (sp == NULL) { plog(LLV_ERROR, LOCATION, NULL, @@ -2480,6 +2603,18 @@ pk_recvspdexpire(mhp) &spidx); #endif +#ifdef HAVE_SECCTX + if (mhp[SADB_X_EXT_SEC_CTX] != NULL) { + struct sadb_x_sec_ctx *ctx; + + ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg; + spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi; + spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len; + memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len); + } +#endif /* HAVE_SECCTX */ + sp = getsp(&spidx); if (sp == NULL) { plog(LLV_ERROR, LOCATION, NULL, @@ -2555,6 +2690,18 @@ pk_recvspddump(mhp) &spidx); #endif +#ifdef HAVE_SECCTX + if (mhp[SADB_X_EXT_SEC_CTX] != NULL) { + struct sadb_x_sec_ctx *ctx; + + ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg; + spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi; + spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len; + memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len); + } +#endif /* HAVE_SECCTX */ + sp = getsp(&spidx); if (sp != NULL) { plog(LLV_ERROR, LOCATION, NULL, @@ -2924,6 +3071,18 @@ addnewsp(mhp) &new->spidx); #endif +#ifdef HAVE_SECCTX + if (mhp[SADB_X_EXT_SEC_CTX] != NULL) { + struct sadb_x_sec_ctx *ctx; + + ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX]; + new->spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg; + new->spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi; + new->spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len; + memcpy(new->spidx.sec_ctx.ctx_str,ctx + 1,ctx->sadb_x_ctx_len); + } +#endif /* HAVE_SECCTX */ + inssp(new); return 0; diff -urpN ipsec-tools.part1/src/racoon/policy.c ipsec-tools.part2/src/racoon/policy.c --- ipsec-tools.part1/src/racoon/policy.c 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/policy.c 2006-10-30 17:36:41.000000000 -0600 @@ -205,6 +205,12 @@ cmpspidxstrict(a, b) (struct sockaddr *)&b->dst)) return 1; +#ifdef HAVE_SECCTX + if (a->sec_ctx.ctx_alg != b->sec_ctx.ctx_alg + || a->sec_ctx.ctx_doi != b->sec_ctx.ctx_doi + || !within_range(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str)) + return 1; +#endif return 0; } @@ -275,6 +281,12 @@ cmpspidxwild(a, b) if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2)) return 1; +#ifdef HAVE_SECCTX + if (a->sec_ctx.ctx_alg != b->sec_ctx.ctx_alg + || a->sec_ctx.ctx_doi != b->sec_ctx.ctx_doi + || !within_range(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str)) + return 1; +#endif return 0; } @@ -464,8 +476,17 @@ spidx2str(spidx) p += i; blen -= i; - snprintf(p, blen, "proto=%s dir=%s", + i = snprintf(p, blen, "proto=%s dir=%s", s_proto(spidx->ul_proto), s_direction(spidx->dir)); +#ifdef HAVE_SECCTX + if (spidx->sec_ctx.ctx_strlen) { + p += i; + blen -= i; + snprintf(p, blen, " sec_ctx:doi=%d,alg=%d,len=%d,str=%s", + spidx->sec_ctx.ctx_doi, spidx->sec_ctx.ctx_alg, + spidx->sec_ctx.ctx_strlen, spidx->sec_ctx.ctx_str); + } +#endif return buf; } diff -urpN ipsec-tools.part1/src/racoon/policy.h ipsec-tools.part2/src/racoon/policy.h --- ipsec-tools.part1/src/racoon/policy.h 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/policy.h 2006-10-30 17:36:41.000000000 -0600 @@ -36,6 +36,19 @@ #include <sys/queue.h> + +#ifdef HAVE_SECCTX +#define MAX_CTXSTR_SIZE 50 +struct security_ctx { + u_int8_t ctx_doi; /* Security Context DOI */ + u_int8_t ctx_alg; /* Security Context Algorithm */ + u_int16_t ctx_strlen; /* Security Context stringlength + * (includes terminating NULL) + */ + char ctx_str[MAX_CTXSTR_SIZE]; /* Security Context string */ +}; +#endif + /* refs. ipsec.h */ /* * Security Policy Index @@ -52,6 +65,9 @@ struct policyindex { u_int8_t prefd; /* prefix length in bits for dst */ u_int16_t ul_proto; /* upper layer Protocol */ u_int32_t priority; /* priority for the policy */ +#ifdef HAVE_SECCTX + struct security_ctx sec_ctx; /* Security Context */ +#endif }; /* Security Policy Data Base */ @@ -133,5 +149,11 @@ extern void initsp __P((void)); extern struct ipsecrequest *newipsecreq __P((void)); extern const char *spidx2str __P((const struct policyindex *)); +#ifdef HAVE_SECCTX +#include <selinux/selinux.h> +extern int get_security_context __P((vchar_t *, struct policyindex *)); +extern int within_range __P((security_context_t, security_context_t)); +extern void set_secctx_in_proposal __P((struct ph2handle *, struct policyindex)); +#endif #endif /* _POLICY_H */ diff -urpN ipsec-tools.part1/src/racoon/proposal.c ipsec-tools.part2/src/racoon/proposal.c --- ipsec-tools.part1/src/racoon/proposal.c 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/proposal.c 2006-10-30 17:36:41.000000000 -0600 @@ -315,6 +315,57 @@ cmpsaprop_alloc(ph1, pp1, pp2, side) goto err; } +#ifdef HAVE_SECCTX + /* check the security_context properties. + * It is possible for one side to have a security context + * and the other side doesn't. If so, this is an error. + */ + + if (*pp1->sctx.ctx_str && !(*pp2->sctx.ctx_str)) { + plog(LLV_ERROR, LOCATION, NULL, + "My proposal missing security context\n"); + goto err; + } + if (!(*pp1->sctx.ctx_str) && *pp2->sctx.ctx_str) { + plog(LLV_ERROR, LOCATION, NULL, + "Peer is missing security context\n"); + goto err; + } + + if (*pp1->sctx.ctx_str && *pp2->sctx.ctx_str) { + if (pp1->sctx.ctx_doi == pp2->sctx.ctx_doi) + newpp->sctx.ctx_doi = pp1->sctx.ctx_doi; + else { + plog(LLV_ERROR, LOCATION, NULL, + "sec doi mismatched: my:%d peer:%d\n", + pp2->sctx.ctx_doi, pp1->sctx.ctx_doi); + goto err; + } + + if (pp1->sctx.ctx_alg == pp2->sctx.ctx_alg) + newpp->sctx.ctx_alg = pp1->sctx.ctx_alg; + else { + plog(LLV_ERROR, LOCATION, NULL, + "sec alg mismatched: my:%d peer:%d\n", + pp2->sctx.ctx_alg, pp1->sctx.ctx_alg); + goto err; + } + + if ((pp1->sctx.ctx_strlen != pp2->sctx.ctx_strlen) || + memcmp(pp1->sctx.ctx_str, pp2->sctx.ctx_str, + pp1->sctx.ctx_strlen) != 0) { + plog(LLV_ERROR, LOCATION, NULL, + "sec ctx string mismatched: my:%s peer:%s\n", + pp2->sctx.ctx_str, pp1->sctx.ctx_str); + goto err; + } else { + newpp->sctx.ctx_strlen = pp1->sctx.ctx_strlen; + memcpy(newpp->sctx.ctx_str, pp1->sctx.ctx_str, + pp1->sctx.ctx_strlen); + } + } +#endif /* HAVE_SECCTX */ + npr1 = npr2 = 0; for (pr1 = pp1->head; pr1; pr1 = pr1->next) npr1++; @@ -1137,6 +1188,15 @@ set_proposal_from_proposal(iph2) pp0->lifebyte = iph2->sainfo->lifebyte; pp0->pfs_group = iph2->sainfo->pfs_group; +#ifdef HAVE_SECCTX + if (*pp_peer->sctx.ctx_str) { + pp0->sctx.ctx_doi = pp_peer->sctx.ctx_doi; + pp0->sctx.ctx_alg = pp_peer->sctx.ctx_alg; + pp0->sctx.ctx_strlen = pp_peer->sctx.ctx_strlen; + memcpy(pp0->sctx.ctx_str, pp_peer->sctx.ctx_str, + pp_peer->sctx.ctx_strlen); + } +#endif /* HAVE_SECCTX */ if (pp_peer->next != NULL) { plog(LLV_ERROR, LOCATION, NULL, diff -urpN ipsec-tools.part1/src/racoon/proposal.h ipsec-tools.part2/src/racoon/proposal.h --- ipsec-tools.part1/src/racoon/proposal.h 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/proposal.h 2006-10-30 17:36:41.000000000 -0600 @@ -62,7 +62,9 @@ struct saprop { int pfs_group; /* pfs group */ int claim; /* flag to send RESPONDER-LIFETIME. */ /* XXX assumed DOI values are 1 or 2. */ - +#ifdef HAVE_SECCTX + struct security_ctx sctx; /* security context structure */ +#endif struct saproto *head; struct saprop *next; }; diff -urpN ipsec-tools.part1/src/racoon/remoteconf.c ipsec-tools.part2/src/racoon/remoteconf.c --- ipsec-tools.part1/src/racoon/remoteconf.c 2006-10-30 17:09:25.000000000 -0600 +++ ipsec-tools.part2/src/racoon/remoteconf.c 2006-10-30 17:36:41.000000000 -0600 @@ -71,6 +71,7 @@ #include "remoteconf.h" #include "localconf.h" #include "grabmyaddr.h" +#include "policy.h" #include "proposal.h" #include "vendorid.h" #include "gcmalloc.h" diff -urpN ipsec-tools.part1/src/racoon/security.c ipsec-tools.part2/src/racoon/security.c --- ipsec-tools.part1/src/racoon/security.c 1969-12-31 18:00:00.000000000 -0600 +++ ipsec-tools.part2/src/racoon/security.c 2006-10-30 17:36:41.000000000 -0600 @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2005 International Business Machines Corporation + * Copyright (c) 2005 by Trusted Computer Solutions, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "config.h" + +#include <sys/types.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <selinux/selinux.h> +#include <selinux/flask.h> +#include <selinux/av_permissions.h> +#include <selinux/avc.h> +#include <selinux/context.h> + +#include "var.h" +#include "vmbuf.h" +#include "misc.h" +#include "plog.h" + +#include "isakmp_var.h" +#include "isakmp.h" +#include "ipsec_doi.h" +#include "policy.h" +#include "proposal.h" +#include "strnames.h" +#include "handler.h" + +/* + * Get the security context information from SA. + */ +int +get_security_context(sa, p) + vchar_t *sa; + struct policyindex *p; +{ + int len = 0; + int flag, type = 0; + u_int16_t lorv; + caddr_t bp; + vchar_t *pbuf = NULL; + vchar_t *tbuf = NULL; + struct isakmp_parse_t *pa; + struct isakmp_parse_t *ta; + struct isakmp_pl_p *prop; + struct isakmp_pl_t *trns; + struct isakmp_data *d; + struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v; + + /* check SA payload size */ + if (sa->l < sizeof(*sab)) { + plog(LLV_ERROR, LOCATION, NULL, + "Invalid SA length = %zu.\n", sa->l); + return -1; + } + + bp = (caddr_t)(sab + 1); /* here bp points to first proposal payload */ + len = sa->l - sizeof(*sab); + + pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, len); + if (pbuf == NULL) + return -1; + + pa = (struct isakmp_parse_t *)pbuf->v; + /* check the value of next payload */ + if (pa->type != ISAKMP_NPTYPE_P) { + plog(LLV_ERROR, LOCATION, NULL, + "Invalid payload type=%u\n", pa->type); + vfree(pbuf); + return -1; + } + + if (pa->len == 0) { + plog(LLV_ERROR, LOCATION, NULL, + "invalid proposal with length %d\n", pa->len); + vfree(pbuf); + return -1; + } + + /* our first proposal */ + prop = (struct isakmp_pl_p *)pa->ptr; + + /* now get transform */ + bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size; + len = ntohs(prop->h.len) - + (sizeof(struct isakmp_pl_p) + prop->spi_size); + tbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, len); + if (tbuf == NULL) + return -1; + + ta = (struct isakmp_parse_t *)tbuf->v; + if (ta->type != ISAKMP_NPTYPE_T) { + plog(LLV_ERROR, LOCATION, NULL, + "Invalid payload type=%u\n", ta->type); + return -1; + } + + trns = (struct isakmp_pl_t *)ta->ptr; + + len = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t); + d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t)); + + while (len > 0) { + type = ntohs(d->type) & ~ISAKMP_GEN_MASK; + flag = ntohs(d->type) & ISAKMP_GEN_MASK; + lorv = ntohs(d->lorv); + + if (type != IPSECDOI_ATTR_SECCTX) { + if (flag) { + len -= sizeof(*d); + d = (struct isakmp_data *)((char *)d + + sizeof(*d)); + } else { + len -= (sizeof(*d) + lorv); + d = (struct isakmp_data *)((caddr_t)d + + sizeof(*d) + lorv); + } + } else { + flag = ntohs(d->type & ISAKMP_GEN_MASK); + if (flag) { + plog(LLV_ERROR, LOCATION, NULL, + "SECCTX must be in TLV.\n"); + return -1; + } + memcpy(&p->sec_ctx, d + 1, lorv); + return 0; + } + } + return 0; +} + +void +set_secctx_in_proposal(iph2, spidx) + struct ph2handle *iph2; + struct policyindex spidx; +{ + iph2->proposal->sctx.ctx_doi = spidx.sec_ctx.ctx_doi; + iph2->proposal->sctx.ctx_alg = spidx.sec_ctx.ctx_alg; + iph2->proposal->sctx.ctx_strlen = spidx.sec_ctx.ctx_strlen; + memcpy(iph2->proposal->sctx.ctx_str, spidx.sec_ctx.ctx_str, + spidx.sec_ctx.ctx_strlen); +} + + +/* + * function: init_avc + * description: function performs the steps necessary to initialize the + * userspace avc. + * input: void + * return: 0 if avc was successfully initialized + * 1 if the avc could not be initialized + */ + +static int +init_avc(void) +{ + int rtn = 0; + + if (!is_selinux_mls_enabled()) { + plog(LLV_ERROR, LOCATION, NULL, + "racoon: MLS support is not enabled.\n"); + return 1; + } + + rtn = avc_init("racoon", NULL, NULL, NULL, NULL); + if (rtn != 0) { + plog(LLV_ERROR, LOCATION, NULL, + "racoon: could not initialize avc.\n"); + rtn = 1; + } + return rtn; +} + +/* + * function: within_range + * description: function determines if the specified sl is within the + * configured range for a policy rule. + * input: security_context *sl SL + char *range Range + * return: 1 if the sl is within the range + * 0 if the sl is not within the range or an error + * occurred which prevented the determination + */ + +int +within_range(security_context_t sl, security_context_t range) +{ + int rtn = 1; + security_id_t slsid; + security_id_t rangesid; + struct av_decision avd; + security_class_t tclass; + access_vector_t av; + + if (!*range) /* This policy doesn't have security context */ + return 1; + + rtn = init_avc(); + if (rtn != 0) { + plog(LLV_ERROR, LOCATION, NULL, + "within_range: couldn't initialize the AVC\n"); + return 0; + } + + /* + * Get the sids for the sl and range contexts + */ + rtn = avc_context_to_sid(sl, &slsid); + if (rtn != 0) { + plog(LLV_ERROR, LOCATION, NULL, + "within_range: Unable to retrieve " + "sid for sl context(%s).\n", sl); + return 0; + } + rtn = avc_context_to_sid(range, &rangesid); + if (rtn != 0) { + plog(LLV_ERROR, LOCATION, NULL, + "within_range: Unable to retrieve " + "sid for range context (%s).\n", range); + sidput(slsid); + return 0; + } + + /* + * Straight up test between sl and range + */ + tclass = SECCLASS_ASSOCIATION; + av = ASSOCIATION__POLMATCH; + rtn = avc_has_perm(slsid, rangesid, tclass, av, NULL, &avd); + if (rtn != 0) { + plog(LLV_INFO, LOCATION, NULL, + "within_range: The sl is not within range\n"); + sidput(slsid); + sidput(rangesid); + return 0; + } + plog(LLV_DEBUG, LOCATION, NULL, + "within_range: The sl (%s) is within range (%s)\n", sl, range); + return 1; +} |