[redhat-lspp] [PATCH] ipsec-tools 0.6 support for IPSec labels

George Wilson ltcgcw at us.ibm.com
Wed Sep 14 00:09:21 UTC 2005


Please find attached a patch against ipsec-tools 0.6 in support of the IPSec
implicit network labels patch posted to netdev.  Trent Jaeger and Joy Latten
produced this patch, and Joy recently brought it up to 0.6.  This level has
NOT been tested.  Joy will post configuration instructions tomorrow.  Please
try the patch and post feedback.  Once the kernel patch is upstream, this
patch will go to ipsec-tools-devel.

-- 
George Wilson <ltcgcw at us.ibm.com>
IBM Linux Technology Center
-------------- next part --------------
diff -urpN ipsec-tools-0.6.1rc1.orig/configure.ac ipsec-tools-0.6.1rc1/configure.ac
--- ipsec-tools-0.6.1rc1.orig/configure.ac	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/configure.ac	2005-09-06 15:25:10.000000000 -0500
@@ -583,6 +583,41 @@ AC_CHECK_TYPE([ipsec_policy_t], 
 	      	#include <netinet6/ipsec.h>
 	      ])
 
+# Check if kernel support is available for Security Context, defaults to no.
+kernel_secctx="no"
+
+AC_MSG_CHECKING(kernel Security Context support)
+case $host_os in
+linux*)
+# Linux kernel Security Context check
+AC_EGREP_CPP(yes,
+[#include <linux/pfkeyv2.h>
+#ifdef SADB_X_EXT_SEC_CTX
+yes
+#endif
+], [kernel_secctx="yes"])
+	;;
+esac
+AC_MSG_RESULT($kernel_secctx)
+
+AC_MSG_CHECKING(whether to support Security Context)
+AC_ARG_ENABLE(security-context,
+	[  --enable-security-context    enable Security Context(yes/no/kernel)],
+	[if test "$enable_security-context" = "kernel"; then
+		enable_security_context=$kernel_secctx; fi],
+	[enable_security_context=$kernel_secctx])
+AC_MSG_RESULT($enable_security_context)
+
+if test "$enable_security_context" = "yes"; then
+	if test "$kernel_secctx" = "no" ; then
+		AC_MSG_ERROR([Security Context requested, but no kernel support! Aborting.])
+	else
+		AC_DEFINE([HAVE_SECCTX], [], [Enable Security Context])
+		SECCTX_OBJS="security.o"
+		AC_SUBST(SECCTX_OBJS)
+	fi
+fi
+
 CFLAGS="$CFLAGS $CFLAGS_ADD"
 CPPFLAGS="$CPPFLAGS $CPPFLAGS_ADD"
 
diff -urpN ipsec-tools-0.6.1rc1.orig/src/libipsec/libpfkey.h ipsec-tools-0.6.1rc1/src/libipsec/libpfkey.h
--- ipsec-tools-0.6.1rc1.orig/src/libipsec/libpfkey.h	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/libipsec/libpfkey.h	2005-09-06 15:48:17.000000000 -0500
@@ -87,21 +87,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.1rc1.orig/src/libipsec/pfkey.c ipsec-tools-0.6.1rc1/src/libipsec/pfkey.c
--- ipsec-tools-0.6.1rc1.orig/src/libipsec/pfkey.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/libipsec/pfkey.c	2005-09-06 15:56:52.000000000 -0500
@@ -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 */
@@ -1966,6 +2010,9 @@ pfkey_align(msg, mhp)
 #ifdef SADB_X_EXT_TAG
 		case SADB_X_EXT_TAG:
 #endif
+#ifdef SADB_X_EXT_SEC_CTX
+		case SADB_X_EXT_SEC_CTX:
+#endif
 			mhp[ext->sadb_ext_type] = (void *)ext;
 			break;
 		default:
@@ -2401,3 +2448,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.1rc1.orig/src/libipsec/pfkey_dump.c ipsec-tools-0.6.1rc1/src/libipsec/pfkey_dump.c
--- ipsec-tools-0.6.1rc1.orig/src/libipsec/pfkey_dump.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/libipsec/pfkey_dump.c	2005-09-06 15:27:49.000000000 -0500
@@ -225,6 +225,9 @@ pfkey_sadump(m)
 	struct sadb_ident *m_sid, *m_did;
 	struct sadb_sens *m_sens;
 #endif
+#ifdef SADB_X_EXT_SEC_CTX
+	struct sadb_x_sec_ctx *m_sec_ctx;
+#endif
 #ifdef SADB_X_EXT_NAT_T_TYPE
 	struct sadb_x_nat_t_type *natt_type;
 	struct sadb_x_nat_t_port *natt_sport, *natt_dport;
@@ -260,6 +263,9 @@ pfkey_sadump(m)
 	m_did = (void *)mhp[SADB_EXT_IDENTITY_DST];
 	m_sens = (void *)mhp[SADB_EXT_SENSITIVITY];
 #endif
+#ifdef SADB_X_EXT_SEC_CTX
+	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+#endif
 #ifdef SADB_X_EXT_NAT_T_TYPE
 	natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
 	natt_sport = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
@@ -407,6 +413,19 @@ pfkey_sadump(m)
 			0 : m_lfts->sadb_lifetime_allocations));
 	}
 
+#ifdef SADB_X_EXT_SEC_CTX
+	if (m_sec_ctx != NULL) {
+		printf("\tsecurity context doi: %u\n",
+					m_sec_ctx->sadb_x_ctx_doi);
+		printf("\tsecurity context algorithm: %u\n",
+					m_sec_ctx->sadb_x_ctx_alg);
+		printf("\tsecurity context length: %u\n",
+					m_sec_ctx->sadb_x_ctx_len);
+		printf("\tsecurity context: %s\n",
+			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
+	}
+#endif
+
 	printf("\tsadb_seq=%lu pid=%lu ",
 		(u_long)m->sadb_msg_seq,
 		(u_long)m->sadb_msg_pid);
@@ -444,6 +463,10 @@ pfkey_spdump1(m, withports)
 #endif
 	struct sadb_x_policy *m_xpl;
 	struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL;
+#ifdef SADB_X_EXT_SEC_CTX
+	// TJ: 
+	struct sadb_x_sec_ctx *m_sec_ctx;
+#endif
 	struct sockaddr *sa;
 	u_int16_t sport = 0, dport = 0;
 
@@ -466,6 +489,9 @@ pfkey_spdump1(m, withports)
 	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
 	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
 
+#ifdef SADB_X_EXT_SEC_CTX
+	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+#endif
 #ifdef __linux__
 	/* *bsd indicates per-socket policies by omiting src and dst 
 	 * extensions. Linux always includes them, but we can catch it
@@ -570,6 +596,19 @@ pfkey_spdump1(m, withports)
 			(u_long)m_lfth->sadb_lifetime_usetime);
 	}
 
+#ifdef SADB_X_EXT_SEC_CTX
+	/* TJ: security context */
+	if (m_sec_ctx != NULL) {
+		printf("\tsecurity context doi: %u\n",
+					m_sec_ctx->sadb_x_ctx_doi);
+		printf("\tsecurity context algorithm: %u\n",
+					m_sec_ctx->sadb_x_ctx_alg);
+		printf("\tsecurity context length: %u\n",
+					m_sec_ctx->sadb_x_ctx_len);
+		printf("\tsecurity context: %s\n",
+			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
+	}
+#endif
 
 	printf("\tspid=%ld seq=%ld pid=%ld\n",
 		(u_long)m_xpl->sadb_x_policy_id,
diff -urpN ipsec-tools-0.6.1rc1.orig/src/racoon/backupsa.c ipsec-tools-0.6.1rc1/src/racoon/backupsa.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/backupsa.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/backupsa.c	2005-09-06 15:28:27.000000000 -0500
@@ -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.1rc1.orig/src/racoon/cftoken.l ipsec-tools-0.6.1rc1/src/racoon/cftoken.l
--- ipsec-tools-0.6.1rc1.orig/src/racoon/cftoken.l	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/cftoken.l	2005-09-06 15:28:39.000000000 -0500
@@ -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.1rc1.orig/src/racoon/ipsec_doi.c ipsec-tools-0.6.1rc1/src/racoon/ipsec_doi.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/ipsec_doi.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/ipsec_doi.c	2005-09-06 15:28:51.000000000 -0500
@@ -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);
@@ -4137,6 +4167,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.1rc1.orig/src/racoon/ipsec_doi.h ipsec-tools-0.6.1rc1/src/racoon/ipsec_doi.h
--- ipsec-tools-0.6.1rc1.orig/src/racoon/ipsec_doi.h	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/ipsec_doi.h	2005-09-06 15:29:04.000000000 -0500
@@ -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.1rc1.orig/src/racoon/isakmp.c ipsec-tools-0.6.1rc1/src/racoon/isakmp.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/isakmp.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/isakmp.c	2005-09-06 16:59:17.000000000 -0500
@@ -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.1rc1.orig/src/racoon/isakmp_quick.c ipsec-tools-0.6.1rc1/src/racoon/isakmp_quick.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/isakmp_quick.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/isakmp_quick.c	2005-09-06 15:29:27.000000000 -0500
@@ -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.1rc1.orig/src/racoon/Makefile.am ipsec-tools-0.6.1rc1/src/racoon/Makefile.am
--- ipsec-tools-0.6.1rc1.orig/src/racoon/Makefile.am	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/Makefile.am	2005-09-06 15:29:44.000000000 -0500
@@ -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.1rc1.orig/src/racoon/pfkey.c ipsec-tools-0.6.1rc1/src/racoon/pfkey.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/pfkey.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/pfkey.c	2005-09-06 15:29:57.000000000 -0500
@@ -1005,6 +1005,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) {
@@ -1066,6 +1070,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) {
@@ -1093,7 +1106,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());
@@ -1113,7 +1127,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());
@@ -1297,6 +1312,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) {
@@ -1358,6 +1376,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");
 
@@ -1390,7 +1417,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());
@@ -1415,7 +1443,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());
@@ -1753,6 +1782,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) {
@@ -1966,6 +2000,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);
@@ -1980,6 +2018,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);
@@ -1998,12 +2043,33 @@ 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) {
 
@@ -2144,6 +2210,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,
@@ -2245,6 +2323,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,
@@ -2341,6 +2431,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,
@@ -2396,6 +2498,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,
@@ -2471,6 +2585,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,
@@ -2828,6 +2954,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.1rc1.orig/src/racoon/policy.c ipsec-tools-0.6.1rc1/src/racoon/policy.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/policy.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/policy.c	2005-09-06 15:30:15.000000000 -0500
@@ -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;
 }
 
@@ -460,8 +477,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.1rc1.orig/src/racoon/policy.h ipsec-tools-0.6.1rc1/src/racoon/policy.h
--- ipsec-tools-0.6.1rc1.orig/src/racoon/policy.h	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/policy.h	2005-09-06 15:30:24.000000000 -0500
@@ -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.1rc1.orig/src/racoon/proposal.c ipsec-tools-0.6.1rc1/src/racoon/proposal.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/proposal.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/proposal.c	2005-09-06 15:30:37.000000000 -0500
@@ -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.1rc1.orig/src/racoon/proposal.h ipsec-tools-0.6.1rc1/src/racoon/proposal.h
--- ipsec-tools-0.6.1rc1.orig/src/racoon/proposal.h	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/proposal.h	2005-09-06 15:30:48.000000000 -0500
@@ -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;
+#endif
 	struct saproto *head;
 	struct saprop *next;
 };
diff -urpN ipsec-tools-0.6.1rc1.orig/src/racoon/remoteconf.c ipsec-tools-0.6.1rc1/src/racoon/remoteconf.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/remoteconf.c	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/racoon/remoteconf.c	2005-09-06 15:31:10.000000000 -0500
@@ -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.1rc1.orig/src/racoon/security.c ipsec-tools-0.6.1rc1/src/racoon/security.c
--- ipsec-tools-0.6.1rc1.orig/src/racoon/security.c	1969-12-31 18:00:00.000000000 -0600
+++ ipsec-tools-0.6.1rc1/src/racoon/security.c	2005-09-06 15:31:20.000000000 -0500
@@ -0,0 +1,126 @@
+#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;
+}
Binary files ipsec-tools-0.6.1rc1.orig/src/racoon/.sockmisc.c.swp and ipsec-tools-0.6.1rc1/src/racoon/.sockmisc.c.swp differ
diff -urpN ipsec-tools-0.6.1rc1.orig/src/setkey/parse.y ipsec-tools-0.6.1rc1/src/setkey/parse.y
--- ipsec-tools-0.6.1rc1.orig/src/setkey/parse.y	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/setkey/parse.y	2005-09-06 16:53:21.000000000 -0500
@@ -78,6 +78,15 @@ const char *p_key_auth;
 time_t p_lt_hard, p_lt_soft;
 size_t p_lb_hard, p_lb_soft;
 
+struct security_ctx {
+        __u8 doi;
+        __u8 alg;
+        __u16 len;
+        char *buf;
+};
+
+struct security_ctx sec_ctx;
+
 static u_int p_natt_type;
 static struct addrinfo * p_natt_oa = NULL;
 
@@ -124,6 +133,7 @@ static int setkeymsg_add __P((unsigned i
 %token F_POLICY PL_REQUESTS
 %token F_AIFLAGS
 %token TAGGED
+%token SECURITY_CTX
 
 %type <num> prefix protocol_spec upper_spec
 %type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
@@ -533,12 +543,18 @@ extension
 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
 	|	F_LIFEBYTE_HARD DECSTRING { p_lb_hard = $2; }
 	|	F_LIFEBYTE_SOFT DECSTRING { p_lb_soft = $2; }
+	|       SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
+		sec_ctx.doi = $2;
+		sec_ctx.alg = $3;
+		sec_ctx.len = $4.len+1;
+		sec_ctx.buf = $4.buf;
+	}
 	;
 
 	/* definition about command for SPD management */
 	/* spdadd */
 spdadd_command
-	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
+	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
 		{
 			int status;
 			struct addrinfo *src, *dst;
@@ -570,7 +586,7 @@ spdadd_command
 				return -1;
 			}
 
-			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
+			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$12,
 			    src, $4, dst, $7);
 			freeaddrinfo(src);
 			freeaddrinfo(dst);
@@ -589,7 +605,7 @@ spdadd_command
 	;
 
 spddelete_command
-	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
+	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
 		{
 			int status;
 			struct addrinfo *src, *dst;
@@ -617,7 +633,7 @@ spddelete_command
 				return -1;
 			}
 
-			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
+			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$12,
 			    src, $4, dst, $7);
 			freeaddrinfo(src);
 			freeaddrinfo(dst);
@@ -793,6 +809,17 @@ upper_misc_spec
 		}
 	;
 
+/* TJ: added this */
+context_spec
+        :       /* NOTHING */
+        |       SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
+	                sec_ctx.doi = $2;
+		        sec_ctx.alg = $3;
+		        sec_ctx.len = $4.len+1;
+		        sec_ctx.buf = $4.buf;
+  	        }
+        ;
+
 policy_spec
 	:	F_POLICY policy_requests
 		{
@@ -1130,6 +1157,30 @@ setkeymsg_addr(type, satype, srcs, dsts,
 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
 			    sizeof(m_addr), sa, salen);
 
+#ifdef SADB_X_EXT_SEC_CTX
+			/* Add security context label */
+			if (sec_ctx.doi)
+			  {
+			    struct sadb_x_sec_ctx m_sec_ctx;
+			    u_int slen = sizeof(struct sadb_x_sec_ctx);
+			    
+			    memset(&m_sec_ctx, 0, slen);
+			    
+			    m_sec_ctx.sadb_x_sec_len =
+			    PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len));
+
+			    printf("sadb_x_sec_len is %d\n", 
+				    m_sec_ctx.sadb_x_sec_len);
+			    m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+			    printf("sadb_x_ctx_len is %d\n", sec_ctx.len);
+			    m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
+			    m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
+			    m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
+			    setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, 
+				      slen, (caddr_t)sec_ctx.buf, sec_ctx.len); 
+			  }
+#endif 
+
 			msg->sadb_msg_len = PFKEY_UNIT64(l);
 
 			sendkeymsg(buf, l);
@@ -1269,6 +1320,28 @@ setkeymsg_add(type, satype, srcs, dsts)
 		l += slen;
 	}
 
+#ifdef SADB_X_EXT_SEC_CTX
+	/* TJ: Add security context label */
+	if (sec_ctx.doi)
+	{
+		struct sadb_x_sec_ctx m_sec_ctx;
+		u_int slen = sizeof(struct sadb_x_sec_ctx);
+
+		memset(&m_sec_ctx, 0, slen);
+
+		m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen +
+					PFKEY_ALIGN8(sec_ctx.len));
+		printf("sadb_x_sec_len is %d\n", m_sec_ctx.sadb_x_sec_len);
+		m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		printf("sadb_x_ctx_len is %d\n", sec_ctx.len);
+		m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
+		m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
+		m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
+		setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen,
+			  (caddr_t)sec_ctx.buf, sec_ctx.len); 
+	}
+#endif
+
 	len = sizeof(struct sadb_sa);
 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
@@ -1514,6 +1587,8 @@ parse_init()
 	p_lt_hard = p_lt_soft = 0;
 	p_lb_hard = p_lb_soft = 0;
 
+	memset(&sec_ctx, 0, sizeof(struct security_ctx));
+
 	p_aiflags = 0;
 	p_aifamily = PF_UNSPEC;
 
diff -urpN ipsec-tools-0.6.1rc1.orig/src/setkey/token.l ipsec-tools-0.6.1rc1/src/setkey/token.l
--- ipsec-tools-0.6.1rc1.orig/src/setkey/token.l	2005-09-06 15:21:42.000000000 -0500
+++ ipsec-tools-0.6.1rc1/src/setkey/token.l	2005-09-06 15:32:12.000000000 -0500
@@ -236,6 +236,7 @@ nocyclic-seq	{ return(NOCYCLICSEQ); }
 {hyphen}ls	{ return(F_LIFETIME_SOFT); }
 {hyphen}bh	{ return(F_LIFEBYTE_HARD); }
 {hyphen}bs	{ return(F_LIFEBYTE_SOFT); }
+{hyphen}ctx	{ return(SECURITY_CTX); }
 
 	/* ... */
 any		{ return(ANY); }


More information about the redhat-lspp mailing list