diff -urpN ipsec-tools-0.6.5.orig/configure.ac ipsec-tools-0.6.5.p1/configure.ac --- ipsec-tools-0.6.5.orig/configure.ac 2006-03-02 12:15:22.000000000 -0600 +++ ipsec-tools-0.6.5.p1/configure.ac 2006-03-02 14:43:59.000000000 -0600 @@ -588,6 +588,41 @@ AC_CHECK_TYPE([ipsec_policy_t], #include ]) +# 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 +#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.5.orig/src/libipsec/pfkey.c ipsec-tools-0.6.5.p1/src/libipsec/pfkey.c --- ipsec-tools-0.6.5.orig/src/libipsec/pfkey.c 2006-03-02 12:15:22.000000000 -0600 +++ ipsec-tools-0.6.5.p1/src/libipsec/pfkey.c 2006-03-02 15:03:10.000000000 -0600 @@ -1969,6 +1969,9 @@ pfkey_align(msg, mhp) #ifdef SADB_X_EXT_PACKET case SADB_X_EXT_PACKET: #endif +#ifdef SADB_X_EXT_SEC_CTX + case SADB_X_EXT_SEC_CTX: +#endif mhp[ext->sadb_ext_type] = (void *)ext; break; diff -urpN ipsec-tools-0.6.5.orig/src/libipsec/pfkey_dump.c ipsec-tools-0.6.5.p1/src/libipsec/pfkey_dump.c --- ipsec-tools-0.6.5.orig/src/libipsec/pfkey_dump.c 2006-03-02 12:15:22.000000000 -0600 +++ ipsec-tools-0.6.5.p1/src/libipsec/pfkey_dump.c 2006-03-02 14:45:44.000000000 -0600 @@ -243,6 +243,9 @@ pfkey_sadump1(m, withports) 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; @@ -279,6 +282,9 @@ pfkey_sadump1(m, withports) 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]; @@ -433,6 +439,19 @@ pfkey_sadump1(m, withports) 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); @@ -470,6 +489,9 @@ 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 + struct sadb_x_sec_ctx *m_sec_ctx; +#endif struct sockaddr *sa; u_int16_t sport = 0, dport = 0; @@ -492,6 +514,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 @@ -596,6 +621,18 @@ pfkey_spdump1(m, withports) (u_long)m_lfth->sadb_lifetime_usetime); } +#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("\tspid=%ld seq=%ld pid=%ld\n", (u_long)m_xpl->sadb_x_policy_id, diff -urpN ipsec-tools-0.6.5.orig/src/setkey/parse.y ipsec-tools-0.6.5.p1/src/setkey/parse.y --- ipsec-tools-0.6.5.orig/src/setkey/parse.y 2006-03-02 12:15:22.000000000 -0600 +++ ipsec-tools-0.6.5.p1/src/setkey/parse.y 2006-03-02 14:47:06.000000000 -0600 @@ -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 prefix protocol_spec upper_spec %type 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); @@ -792,6 +808,16 @@ upper_misc_spec } ; +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 { @@ -939,7 +965,27 @@ setkeymsg_spdaddr(type, upper, policy, s 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)); + + m_sec_ctx.sadb_x_sec_exttype = + SADB_X_EXT_SEC_CTX; + 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); @@ -1268,6 +1314,25 @@ setkeymsg_add(type, satype, srcs, dsts) l += slen; } +#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)); + m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; + 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; @@ -1513,6 +1578,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.5.orig/src/setkey/setkey.8 ipsec-tools-0.6.5.p1/src/setkey/setkey.8 --- ipsec-tools-0.6.5.orig/src/setkey/setkey.8 2006-03-02 12:15:22.000000000 -0600 +++ ipsec-tools-0.6.5.p1/src/setkey/setkey.8 2006-03-02 14:46:18.000000000 -0600 @@ -218,7 +218,7 @@ on the command line achieves the same fu .It Xo .Li spdadd .Op Fl 46n -.Ar src_range Ar dst_range Ar upperspec Ar policy +.Ar src_range Ar dst_range Ar upperspec Ar label Ar policy .Li ; .Xc Add an SPD entry. @@ -368,6 +368,20 @@ Specify hard/soft life time duration of .It Fl bh Ar bytes .It Fl bs Ar bytes Specify hard/soft life time duration of the SA measured in bytes transported. +.\" +.It Fl ctx Ar doi Ar algorithm Ar context-name +Specify an access control label. The access control label is interpreted +by the LSM (e.g., SELinux). Ultimately, it enables MAC on network +communications. +.Bl -tag -width Fl -compact +.It Ar doi +The domain of interpretation, which is used by the +IKE daemon to identify the domain in which negotiation takes place. +.It Ar algorithm +Indicates the LSM for which the label is generated (e.g., SELinux). +.It Ar context-name +The string representation of the label that is interpreted by the LSM. +.El .El .\" .Pp @@ -488,6 +502,27 @@ to use with IPsec. You have to consider carefully what to use. .\" .Pp +.It Ar label +.Ar label +is the access control label for the policy. This label is interpreted +by the LSM (e.g., SELinux). Ultimately, it enables MAC on network +communications. When a policy contains an access control label, SAs +negotiated with this policy will contain the label. It's format: +.Bl -tag -width Fl -compact +.\" +.It Fl ctx Ar doi Ar algorithm Ar context-name +.Bl -tag -width Fl -compact +.It Ar doi +The domain of interpretation, which is used by the +IKE daemon to identify the domain in which negotiation takes place. +.It Ar algorithm +Indicates the LSM for which the label is generated (e.g., SELinux). +.It Ar context-name +The string representation of the label that is interpreted by the LSM. +.El +.El +.\" +.Pp .It Ar policy .Ar policy is in one of the following three formats: @@ -796,6 +831,14 @@ spdadd 10.0.11.41/32[21] 10.0.11.33/32[a -P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ; add 10.1.10.34 10.1.10.36 tcp 0x1000 -A tcp-md5 "TCP-MD5 BGP secret" ; + +add 10.0.11.41 10.0.11.33 esp 0x10001 + -ctx 1 1 "system_u:system_r:unconfined_t:SystemLow-SystemHigh" + -E des-cbc 0x3ffe05014819ffff; + +spdadd 10.0.11.41 10.0.11.33 any + -ctx 1 1 "system_u:system_r:unconfined_t:SystemLow-SystemHigh" + -P out ipsec esp/transport//require ; .Ed .\" .Sh SEE ALSO diff -urpN ipsec-tools-0.6.5.orig/src/setkey/token.l ipsec-tools-0.6.5.p1/src/setkey/token.l --- ipsec-tools-0.6.5.orig/src/setkey/token.l 2006-03-02 12:15:22.000000000 -0600 +++ ipsec-tools-0.6.5.p1/src/setkey/token.l 2006-03-02 14:46:53.000000000 -0600 @@ -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); } 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 +#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 + +#include +#include +#include + +#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; +}