[redhat-lspp] [PATCH 2/2] Leveraging IPSec for MAC of Linux network communications

Joy Latten latten at austin.ibm.com
Tue Mar 21 17:03:12 UTC 2006


A feature using IPSec security associations to implicitly label network
packets has been accepted into the 2.6.16 kernel. This feature
integrates IPSec with SELinux to extend SELinux's mandatory access
control support from a single system to a network of systems via network
communications. This feature will also be used for acquiring LSPP
certification. The modifications consisted of a patch to the kernel and
to the userspace ipsec-tools. 

This submission contains the modifications made to ipsec-tools.
The patch has been divided into two parts to make for quick and easier
reviewing. The first part contains the modifications made to the setkey
utility allowing for the inclusion of an access control label when
adding a security policy and/or a security association. The second part
contains the modification made to racoon to allow negotiations to
include an access control label. 

Setkey has been modified to parse the security context and use the
SADB_X_EXT_SEC_CTX extension in pfkey. Racoon has been modified to
negotiate security context as well as use the SADB_X_EXT_SEC_CTX
extension. A security context is entered as a parameter when configuring
the security policy with setkey. The security context is also entered as
a parameter when configuring security association with setkey or it is
negotiated when racoon determines security association. The initiating
racoon uses the security context associated with the policy, that was
delivered in the acquire message, for negotiating. The responding racoon
peeks into the proposal for the security context so that he can include
it as a selector to retrieve corresponding policy. When examining the
initiator and responder proposals, if security contexts are used, they
must match exactly, otherwise racoon's negotiations fail and an SA will
not be established. 

The defines, HAVE_SECCTX and SADB_X_EXT_SEC_CTX in the code contain the
changes made to ipsec-tools.

For those interested in more information about the design, the following
text was taken from Trent's write-up for kernel submission.

This patch series implements per packet access control 
        via the extension of the Linux Security Modules (LSM) 
        interface by hooks in the XFRM and pfkey subsystems that
        leverage IPSec security associations to label packets. 
        Extensions to the SELinux LSM are included that leverage 
        the patch for this purpose.
        
        This kernel patch implements the changes necessary to 
        the XFRM subsystem, pfkey interface, ipv4/ipv6, and 
        xfrm_user interface to restrict a socket to use only 
        authorized security associations (or no security association) 
        to send/receive network packets.

        Patch Purpose:
        The patch is designed to enable access control per 
        packets based on the strongly authenticated IPSec security
        association. Such access controls augment the existing ones
        based on network interface and IP address. The former
        are very coarse-grained, and the latter can be spoofed. By 
        using IPSec, the system can control access to remote
        hosts based on cryptographic keys generated using the IPSec
        mechanism. This enables access control on a per-machine 
        basis or per-application if the remote machine is running 
        the same mechanism and trusted to enforce the access 
        control policy.

        Patch design approach:
        
        The overall approach is that policy (xfrm_policy) entries 
        set by user-level programs (e.g., setkey for ipsec-tools) 
        are extended with a security context that is used at policy
        selection time in the XFRM subsystem to restrict the sockets
        that can send/receive packets via security associations
        (xfrm_states) that are built from those policies.  
        
        A presentation available at
      
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
        from the SELinux symposium describes the overall approach.
        
        Patch implementation details: 
        On output, the policy retrieved (via xfrm_policy_lookup
        or xfrm_sk_policy_lookup) must be authorized for the 
        security context of the socket and the same security 
        context is required for resultant security association
        (retrieved or negotiated via racoon in ipsec-tools).  
        This is enforced in xfrm_state_find. On input, the policy
        retrieved must also be authorized for the socket
        (at __xfrm_policy_check), and the security context of
        the policy must also match the security association 
        being used.
        
        The patch has virtually no impact on packets that do not 
        use IPSec. The existing Netfilter (outgoing) and 
        LSM rcv_skb hooks are used as before.
        
        Also, if IPSec is used without security contexts, the 
        impact is minimal. The LSM must allow such policies to be
        selected for the combination of socket and remote machine, 
        but subsequent IPSec processing proceeds as in the original
        case.
        
        Testing:
        The pfkey interface is tested using the ipsec-tools.
        Ipsec-tools have been modified that supports assignment of
        xfrm_policy entries and security associations with security
        contexts via setkey and the negotiation using the security
        contexts via racoon.

Regards,
Joy Latten
---------------------------------------------------------------------------

diff -urpN ipsec-tools-0.6.5.p1/src/libipsec/libpfkey.h
ipsec-tools-0.6.5.p2/src/libipsec/libpfkey.h
--- ipsec-tools-0.6.5.p1/src/libipsec/libpfkey.h	2006-03-02
14:43:32.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/libipsec/libpfkey.h	2006-03-02
14:51:51.000000000 -0600
@@ -88,21 +88,25 @@ int pfkey_send_getspi __P((int, u_int, u
 int pfkey_send_update __P((int, u_int, u_int, struct sockaddr *,
 	struct sockaddr *, u_int32_t, u_int32_t, u_int,
 	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
-	u_int64_t, u_int64_t, u_int32_t));
+	u_int64_t, u_int64_t, u_int32_t,
+	u_int8_t, u_int8_t, caddr_t, u_int16_t));
 int pfkey_send_update_nat __P((int, u_int, u_int, struct sockaddr *,
 	struct sockaddr *, u_int32_t, u_int32_t, u_int,
 	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
 	u_int64_t, u_int64_t, u_int32_t,
-	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t));
+	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t,
+	u_int8_t, u_int8_t, caddr_t, u_int16_t));
 int pfkey_send_add __P((int, u_int, u_int, struct sockaddr *,
 	struct sockaddr *, u_int32_t, u_int32_t, u_int,
 	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
-	u_int64_t, u_int64_t, u_int32_t));
+	u_int64_t, u_int64_t, u_int32_t,
+	u_int8_t, u_int8_t, caddr_t, u_int16_t));
 int pfkey_send_add_nat __P((int, u_int, u_int, struct sockaddr *,
 	struct sockaddr *, u_int32_t, u_int32_t, u_int,
 	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
 	u_int64_t, u_int64_t, u_int32_t,
-	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t));
+	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t,
+	u_int8_t, u_int8_t, caddr_t, u_int16_t));
 int pfkey_send_delete __P((int, u_int, u_int,
 	struct sockaddr *, struct sockaddr *, u_int32_t));
 int pfkey_send_delete_all __P((int, u_int, u_int,
diff -urpN ipsec-tools-0.6.5.p1/src/libipsec/pfkey.c
ipsec-tools-0.6.5.p2/src/libipsec/pfkey.c
--- ipsec-tools-0.6.5.p1/src/libipsec/pfkey.c	2006-03-02
15:03:10.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/libipsec/pfkey.c	2006-03-02
15:00:45.000000000 -0600
@@ -62,7 +62,8 @@ static int pfkey_send_x1 __P((int, u_int
 	struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t,
 	u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t,
 	u_int32_t, u_int32_t, u_int32_t,
-	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t));
+	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t,
+	u_int8_t, u_int8_t, caddr_t, u_int16_t));
 static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
 	struct sockaddr *, struct sockaddr *, u_int32_t));
 static int pfkey_send_x3 __P((int, u_int, u_int));
@@ -81,6 +82,10 @@ static caddr_t pfkey_setsadbkey __P((cad
 static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int,
u_int32_t,
 	u_int32_t, u_int32_t, u_int32_t));
 static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t,
u_int32_t));
+#ifdef SADB_X_EXT_SEC_CTX
+static caddr_t pfkey_setsecctx __P((caddr_t, caddr_t, u_int, u_int8_t, 
+	u_int8_t, caddr_t, u_int16_t));
+#endif
 
 #ifdef SADB_X_EXT_NAT_T_TYPE
 static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int,
u_int8_t));
@@ -494,7 +499,9 @@ pfkey_send_getspi(so, satype, mode, src,
 int
 pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
-		l_alloc, l_bytes, l_addtime, l_usetime, seq)
+		l_alloc, l_bytes, l_addtime, l_usetime, seq, 
+		ctxdoi, ctxalg, ctxstr, ctxstrlen)
+		
 	int so;
 	u_int satype, mode, wsize;
 	struct sockaddr *src, *dst;
@@ -504,13 +511,17 @@ pfkey_send_update(so, satype, mode, src,
 	u_int32_t l_alloc;
 	u_int64_t l_bytes, l_addtime, l_usetime;
 	u_int32_t seq;
+	u_int8_t ctxdoi, ctxalg;
+	caddr_t ctxstr;
+	u_int16_t ctxstrlen;
 {
 	int len;
 	if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
 			reqid, wsize,
 			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)) < 0)
+			(u_int)l_usetime, seq, 0, 0, 0, NULL, 0,
+			ctxdoi, ctxalg, ctxstr, ctxstrlen)) < 0)
 		return -1;
 
 	return len;
@@ -522,7 +533,7 @@ pfkey_send_update_nat(so, satype, mode, 
 		      keymat, e_type, e_keylen, a_type, a_keylen, flags,
 		      l_alloc, l_bytes, l_addtime, l_usetime, seq,
 		      l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
-		      l_natt_frag)
+		      l_natt_frag, ctxdoi, ctxalg, ctxstr, ctxstrlen)
 	int so;
 	u_int satype, mode, wsize;
 	struct sockaddr *src, *dst;
@@ -536,6 +547,9 @@ pfkey_send_update_nat(so, satype, mode, 
 	u_int16_t l_natt_sport, l_natt_dport;
 	struct sockaddr *l_natt_oa;
 	u_int16_t l_natt_frag;
+	u_int8_t ctxdoi, ctxalg;
+	caddr_t ctxstr;
+	u_int16_t ctxstrlen;
 {
 	int len;
 	if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
@@ -543,7 +557,8 @@ pfkey_send_update_nat(so, satype, mode, 
 			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, l_natt_type, l_natt_sport, 
-			l_natt_dport, l_natt_oa, l_natt_frag)) < 0)
+			l_natt_dport, l_natt_oa, l_natt_frag,
+			ctxdoi, ctxalg, ctxstr, ctxstrlen)) < 0)
 		return -1;
 
 	return len;
@@ -560,7 +575,9 @@ pfkey_send_update_nat(so, satype, mode, 
 int
 pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
-		l_alloc, l_bytes, l_addtime, l_usetime, seq)
+		l_alloc, l_bytes, l_addtime, l_usetime, seq,
+		ctxdoi, ctxalg, ctxstr, ctxstrlen)
+
 	int so;
 	u_int satype, mode, wsize;
 	struct sockaddr *src, *dst;
@@ -570,13 +587,17 @@ pfkey_send_add(so, satype, mode, src, ds
 	u_int32_t l_alloc;
 	u_int64_t l_bytes, l_addtime, l_usetime;
 	u_int32_t seq;
+	u_int8_t ctxdoi, ctxalg;
+	caddr_t ctxstr;
+	u_int16_t ctxstrlen;
 {
 	int len;
 	if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
 			reqid, wsize,
 			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)) < 0)
+			(u_int)l_usetime, seq, 0, 0, 0, NULL, 0,
+			ctxdoi, ctxalg, ctxstr, ctxstrlen)) < 0)
 		return -1;
 
 	return len;
@@ -588,7 +609,7 @@ pfkey_send_add_nat(so, satype, mode, src
 		   keymat, e_type, e_keylen, a_type, a_keylen, flags,
 		   l_alloc, l_bytes, l_addtime, l_usetime, seq,
 		   l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
-		   l_natt_frag)
+		   l_natt_frag, ctxdoi, ctxalg, ctxstr, ctxstrlen)
 	int so;
 	u_int satype, mode, wsize;
 	struct sockaddr *src, *dst;
@@ -602,6 +623,9 @@ pfkey_send_add_nat(so, satype, mode, src
 	u_int16_t l_natt_sport, l_natt_dport;
 	struct sockaddr *l_natt_oa;
 	u_int16_t l_natt_frag;
+	u_int8_t ctxdoi, ctxalg;
+	caddr_t ctxstr;
+	u_int16_t ctxstrlen;
 {
 	int len;
 	if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
@@ -609,7 +633,8 @@ pfkey_send_add_nat(so, satype, mode, src
 			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, l_natt_type, l_natt_sport, 
-			l_natt_dport, l_natt_oa, l_natt_frag)) < 0)
+			l_natt_dport, l_natt_oa, l_natt_frag,
+			ctxdoi, ctxalg, ctxstr, ctxstrlen)) < 0)
 		return -1;
 
 	return len;
@@ -1202,7 +1227,7 @@ pfkey_send_x1(so, type, satype, mode, sr
 		keymat, e_type, e_keylen, a_type, a_keylen, flags,
 		l_alloc, l_bytes, l_addtime, l_usetime, seq,
 	        l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa, 
-		l_natt_frag)
+		l_natt_frag, ctxdoi, ctxalg, ctxstr, ctxstrlen)
 	int so;
 	u_int type, satype, mode;
 	struct sockaddr *src, *dst, *l_natt_oa;
@@ -1214,6 +1239,9 @@ pfkey_send_x1(so, type, satype, mode, sr
 	u_int16_t l_natt_sport, l_natt_dport;
 	u_int8_t l_natt_type;
 	u_int16_t l_natt_frag;
+	u_int8_t ctxdoi, ctxalg;
+	caddr_t ctxstr;
+	u_int16_t ctxstrlen;
 {
 	struct sadb_msg *newmsg;
 	int len;
@@ -1302,6 +1330,12 @@ pfkey_send_x1(so, type, satype, mode, sr
 	if (a_type != SADB_AALG_NONE)
 		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
 
+#ifdef SADB_X_EXT_SEC_CTX 
+	if (ctxstr != NULL)
+		len += (sizeof(struct sadb_x_sec_ctx)
+		    + PFKEY_ALIGN8(ctxstrlen));
+#endif
+
 #ifdef SADB_X_EXT_NAT_T_TYPE
 	/* add nat-t packets */
 	if (l_natt_type) {
@@ -1392,6 +1426,16 @@ pfkey_send_x1(so, type, satype, mode, sr
 		free(newmsg);
 		return -1;
 	}
+#ifdef SADB_X_EXT_SEC_CTX 
+	if (ctxstr != NULL) {
+		p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, ctxdoi, 
+				ctxalg, ctxstr, ctxstrlen);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+	}
+#endif
 
 #ifdef SADB_X_EXT_NAT_T_TYPE
 	/* Add nat-t messages */
@@ -2408,3 +2452,35 @@ pfkey_set_natt_frag(buf, lim, type, l_na
 	return(buf + len);
 }
 #endif
+
+#ifdef SADB_X_EXT_SEC_CTX 
+static caddr_t
+pfkey_setsecctx(buf, lim, type, ctx_doi, ctx_alg, sec_ctx, sec_ctxlen)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type;
+	u_int8_t ctx_doi, ctx_alg;
+	caddr_t sec_ctx;
+	u_int16_t sec_ctxlen;
+{
+	struct sadb_x_sec_ctx *p;
+	u_int len;
+
+	p = (struct sadb_x_sec_ctx *)buf;
+	len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
+	
+	if (buf + len > lim)
+		return NULL;
+	
+	memset(p, 0, len);
+	p->sadb_x_sec_len = PFKEY_UNIT64(len);
+	p->sadb_x_sec_exttype = type;
+	p->sadb_x_ctx_len = sec_ctxlen;
+	p->sadb_x_ctx_doi = ctx_doi;
+	p->sadb_x_ctx_alg = ctx_alg;
+		
+	memcpy(p + 1, sec_ctx, sec_ctxlen);
+
+	return buf + len;
+}
+#endif 
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/backupsa.c
ipsec-tools-0.6.5.p2/src/racoon/backupsa.c
--- ipsec-tools-0.6.5.p1/src/racoon/backupsa.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/backupsa.c	2006-03-02
14:52:47.000000000 -0600
@@ -331,7 +331,8 @@ do { \
 				wsize,
 				keymat,
 				e_type, e_keylen, a_type, a_keylen, flags,
-				0, l_bytes, l_addtime, 0, seq) < 0) {
+				0, l_bytes, l_addtime, 0, seq,
+				0, 0, NULL, 0) < 0) {
 			plog(LLV_ERROR, LOCATION, NULL,
 				"restore SA filed line#%d in %s: %s\n",
 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/cftoken.l
ipsec-tools-0.6.5.p2/src/racoon/cftoken.l
--- ipsec-tools-0.6.5.p1/src/racoon/cftoken.l	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/cftoken.l	2006-03-02
14:52:58.000000000 -0600
@@ -70,6 +70,7 @@
 #include "isakmp_var.h"
 #include "isakmp.h"
 #include "ipsec_doi.h"
+#include "policy.h"
 #include "proposal.h"
 #include "nattraversal.h"
 #ifdef GC
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/ipsec_doi.c
ipsec-tools-0.6.5.p2/src/racoon/ipsec_doi.c
--- ipsec-tools-0.6.5.p1/src/racoon/ipsec_doi.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/ipsec_doi.c	2006-03-02
14:53:08.000000000 -0600
@@ -2379,6 +2379,15 @@ 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:
@@ -2882,6 +2891,10 @@ 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)
@@ -2983,6 +2996,16 @@ 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)
@@ -3038,6 +3061,13 @@ 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);
@@ -4154,6 +4184,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
 		case IPSECDOI_ATTR_KEY_ROUNDS:
 		case IPSECDOI_ATTR_COMP_DICT_SIZE:
 		case IPSECDOI_ATTR_COMP_PRIVALG:
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/ipsec_doi.h
ipsec-tools-0.6.5.p2/src/racoon/ipsec_doi.h
--- ipsec-tools-0.6.5.p1/src/racoon/ipsec_doi.h	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/ipsec_doi.h	2006-03-02
14:53:13.000000000 -0600
@@ -133,6 +133,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-0.6.5.p1/src/racoon/isakmp.c
ipsec-tools-0.6.5.p2/src/racoon/isakmp.c
--- ipsec-tools-0.6.5.p1/src/racoon/isakmp.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/isakmp.c	2006-03-02
14:53:23.000000000 -0600
@@ -84,11 +84,11 @@
 #include "oakley.h"
 #include "evt.h"
 #include "handler.h"
+#include "policy.h"
 #include "proposal.h"
 #include "ipsec_doi.h"
 #include "pfkey.h"
 #include "crypto_openssl.h"
-#include "policy.h"
 #include "isakmp_ident.h"
 #include "isakmp_agg.h"
 #include "isakmp_base.h"
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/isakmp_quick.c
ipsec-tools-0.6.5.p2/src/racoon/isakmp_quick.c
--- ipsec-tools-0.6.5.p1/src/racoon/isakmp_quick.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/isakmp_quick.c	2006-03-02
14:53:30.000000000 -0600
@@ -2037,6 +2037,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) {
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/Makefile.am
ipsec-tools-0.6.5.p2/src/racoon/Makefile.am
--- ipsec-tools-0.6.5.p1/src/racoon/Makefile.am	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/Makefile.am	2006-03-02
14:53:42.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
+racoon_LDADD = $(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) \
+	$(SECCTX_OBJS) $(LEXLIB) 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-0.6.5.p1/src/racoon/pfkey.c
ipsec-tools-0.6.5.p2/src/racoon/pfkey.c
--- ipsec-tools-0.6.5.p1/src/racoon/pfkey.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/pfkey.c	2006-03-02
14:53:56.000000000 -0600
@@ -1009,6 +1009,10 @@ pk_sendupdate(iph2)
 	u_int wsize = 4;  /* XXX static size of window */ 
 	int proxy = 0;
 	struct ph2natt natt;
+	u_int8_t ctxdoi = 0, ctxalg = 0;
+	u_int16_t ctxstrlen = 0;
+	caddr_t ctxstr = NULL;
+	
 
 	/* sanity check */
 	if (iph2->approval == NULL) {
@@ -1070,6 +1074,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) {
@@ -1097,7 +1110,8 @@ pk_sendupdate(iph2)
 				0, lifebyte, iph2->approval->lifetime, 0,
 				iph2->seq,
 				natt.type, natt.sport, natt.dport, natt.oa,
-				natt.frag) < 0) {
+				natt.frag,
+				ctxdoi, ctxalg, ctxstr, ctxstrlen) < 0) {
 			plog(LLV_ERROR, LOCATION, NULL,
 				"libipsec failed send update_nat (%s)\n",
 				ipsec_strerror());
@@ -1117,7 +1131,8 @@ pk_sendupdate(iph2)
 				pr->keymat->v,
 				e_type, e_keylen, a_type, a_keylen, flags,
 				0, lifebyte, iph2->approval->lifetime, 0,
-				iph2->seq) < 0) {
+				iph2->seq,
+				ctxdoi, ctxalg, ctxstr, ctxstrlen) < 0) {
 			plog(LLV_ERROR, LOCATION, NULL,
 				"libipsec failed send update (%s)\n",
 				ipsec_strerror());
@@ -1301,6 +1316,9 @@ pk_sendadd(iph2)
 	u_int wsize = 4; /* XXX static size of window */ 
 	int proxy = 0;
 	struct ph2natt natt;
+	u_int8_t ctxdoi = 0, ctxalg = 0;
+	u_int16_t ctxstrlen = 0;
+	caddr_t ctxstr = NULL;
 
 	/* sanity check */
 	if (iph2->approval == NULL) {
@@ -1362,6 +1380,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");
 
@@ -1394,7 +1421,8 @@ pk_sendadd(iph2)
 				0, lifebyte, iph2->approval->lifetime, 0,
 				iph2->seq,
 				natt.type, natt.sport, natt.dport, natt.oa,
-				natt.frag) < 0) {
+				natt.frag,
+				ctxdoi, ctxalg, ctxstr, ctxstrlen) < 0) {
 			plog(LLV_ERROR, LOCATION, NULL,
 				"libipsec failed send add_nat (%s)\n",
 				ipsec_strerror());
@@ -1419,7 +1447,8 @@ 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) {
+				iph2->seq,
+				ctxdoi, ctxalg, ctxstr, ctxstrlen) < 0) {
 			plog(LLV_ERROR, LOCATION, NULL,
 				"libipsec failed send add (%s)\n",
 				ipsec_strerror());
@@ -1757,6 +1786,11 @@ pk_recvacquire(mhp)
 	spidx.prefs = sp_out->spidx.prefd;
 	spidx.prefd = sp_out->spidx.prefs;
 	spidx.ul_proto = sp_out->spidx.ul_proto;
+#ifdef HAVE_SECCTX
+	if (*sp_out->spidx.sec_ctx.ctx_str)
+		memcpy(&spidx.sec_ctx, &sp_out->spidx.sec_ctx, 
+			sizeof(spidx.sec_ctx));
+#endif
 
 	sp_in = getsp(&spidx);
 	if (sp_in) {
@@ -1970,6 +2004,10 @@ getsadbpolicy(policy0, policylen0, type,
 	int policylen;
 	int xisrlen;
 	u_int satype, mode;
+	int len = 0;
+#ifdef HAVE_SECCTX
+	int ctxlen = 0;
+#endif
 
 	/* get policy buffer size */
 	policylen = sizeof(struct sadb_x_policy);
@@ -1984,6 +2022,13 @@ getsadbpolicy(policy0, policylen0, type,
 			policylen += PFKEY_ALIGN8(xisrlen);
 		}
 	}
+#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
 
 	/* make policy structure */
 	policy = racoon_malloc(policylen);
@@ -2002,12 +2047,31 @@ 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);
 
 	for (pr = iph2->approval->head; pr; pr = pr->next) {
 
@@ -2148,6 +2212,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 SEC_CTX */
+		
 	sp = getsp(&spidx);
 	if (sp == NULL) {
 		plog(LLV_ERROR, LOCATION, NULL,
@@ -2249,6 +2325,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,
@@ -2345,6 +2433,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,
@@ -2400,6 +2500,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,
@@ -2475,6 +2587,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,
@@ -2832,6 +2956,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-0.6.5.p1/src/racoon/policy.c
ipsec-tools-0.6.5.p2/src/racoon/policy.c
--- ipsec-tools-0.6.5.p1/src/racoon/policy.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/policy.c	2006-03-02
14:54:04.000000000 -0600
@@ -203,6 +203,14 @@ 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
+	 || a->sec_ctx.ctx_strlen != b->sec_ctx.ctx_strlen
+	 || (memcmp(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str, 
+	     a->sec_ctx.ctx_strlen) != 0))
+		return 1;
+#endif
 	return 0;
 }
 
@@ -273,6 +281,15 @@ 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
+	 || a->sec_ctx.ctx_strlen != b->sec_ctx.ctx_strlen
+	 || (memcmp(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str, 
+	     a->sec_ctx.ctx_strlen) != 0))
+		return 1;
+#endif
+
 	return 0;
 }
 
@@ -462,8 +479,18 @@ 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-0.6.5.p1/src/racoon/policy.h
ipsec-tools-0.6.5.p2/src/racoon/policy.h
--- ipsec-tools-0.6.5.p1/src/racoon/policy.h	2006-03-02
14:43:32.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/policy.h	2006-03-02
14:54:09.000000000 -0600
@@ -34,6 +34,18 @@
 
 #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
@@ -50,6 +62,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 */
@@ -131,5 +146,6 @@ extern void initsp __P((void));
 extern struct ipsecrequest *newipsecreq __P((void));
 
 extern const char *spidx2str __P((const struct policyindex *));
+extern int get_security_context __P((vchar_t *, struct policyindex *));
 
 #endif /* _POLICY_H */
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/proposal.c
ipsec-tools-0.6.5.p2/src/racoon/proposal.c
--- ipsec-tools-0.6.5.p1/src/racoon/proposal.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/proposal.c	2006-03-02
14:54:22.000000000 -0600
@@ -311,6 +311,60 @@ 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,
+				"security-context 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++;
@@ -960,7 +1014,7 @@ set_proposal_from_policy(iph2, sp_main, 
 	struct saprop *newpp;
 	struct ipsecrequest *req;
 	int encmodesv = IPSEC_MODE_TRANSPORT; /* use only when complex_bundle
*/
-
+	
 	newpp = newsaprop();
 	if (newpp == NULL) {
 		plog(LLV_ERROR, LOCATION, NULL,
@@ -971,6 +1025,15 @@ set_proposal_from_policy(iph2, sp_main, 
 	newpp->lifetime = iph2->sainfo->lifetime;
 	newpp->lifebyte = iph2->sainfo->lifebyte;
 	newpp->pfs_group = iph2->sainfo->pfs_group;
+#ifdef HAVE_SECCTX
+	if (*sp_main->spidx.sec_ctx.ctx_str) {
+		newpp->sctx.ctx_doi = sp_main->spidx.sec_ctx.ctx_doi;
+		newpp->sctx.ctx_alg = sp_main->spidx.sec_ctx.ctx_alg;
+		newpp->sctx.ctx_strlen = sp_main->spidx.sec_ctx.ctx_strlen;
+		memcpy(newpp->sctx.ctx_str, sp_main->spidx.sec_ctx.ctx_str, 
+			sp_main->spidx.sec_ctx.ctx_strlen);
+	}
+#endif /* HAVE_SECCTX */
 
 	if (lcconf->complex_bundle)
 		goto skip1;
@@ -1125,7 +1188,17 @@ set_proposal_from_proposal(iph2)
 		pp0->lifetime = iph2->sainfo->lifetime;
 		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,
 				"pp_peer is inconsistency, ignore it.\n");
diff -urpN ipsec-tools-0.6.5.p1/src/racoon/proposal.h
ipsec-tools-0.6.5.p2/src/racoon/proposal.h
--- ipsec-tools-0.6.5.p1/src/racoon/proposal.h	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/proposal.h	2006-03-02
14:54:28.000000000 -0600
@@ -60,7 +60,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-0.6.5.p1/src/racoon/remoteconf.c
ipsec-tools-0.6.5.p2/src/racoon/remoteconf.c
--- ipsec-tools-0.6.5.p1/src/racoon/remoteconf.c	2006-03-02
14:43:31.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/remoteconf.c	2006-03-02
14:54:41.000000000 -0600
@@ -66,6 +66,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-0.6.5.p1/src/racoon/security.c
ipsec-tools-0.6.5.p2/src/racoon/security.c
--- ipsec-tools-0.6.5.p1/src/racoon/security.c	1969-12-31
18:00:00.000000000 -0600
+++ ipsec-tools-0.6.5.p2/src/racoon/security.c	2006-03-02
14:54:47.000000000 -0600
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2005 International Business Machines Corporation
+ * 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 "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 "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;
+}




More information about the redhat-lspp mailing list