Module Name: src Committed By: martin Date: Thu Jul 25 08:58:21 UTC 2019
Modified Files: src/crypto/dist/ipsec-tools/src/setkey [netbsd-8]: parse.y token.l src/sys/netipsec [netbsd-8]: key.c src/tests/net/ipsec [netbsd-8]: t_ipsec_misc.sh Log Message: Pull up following revision(s) (requested by ozaki-r in ticket #1306): crypto/dist/ipsec-tools/src/setkey/parse.y: revision 1.23 sys/netipsec/key.c: revision 1.265 crypto/dist/ipsec-tools/src/setkey/token.l: revision 1.23 tests/net/ipsec/t_ipsec_misc.sh: revision 1.23 ipsec: fix a regression of the update API The update API updates an SA by creating a new SA and removing an existing SA. The previous change removed a newly added SA wrongly if an existing SA had been created by the getspi API. setkey: enable to use the getspi API If a specified SPI is not zero, tell the kernel to use the SPI by using SADB_EXT_SPIRANGE. Otherwise, the kernel picks a random SPI. It enables to mimic racoon. tests: add tests for getspi and udpate To generate a diff of this commit: cvs rdiff -u -r1.18.4.1 -r1.18.4.2 \ src/crypto/dist/ipsec-tools/src/setkey/parse.y cvs rdiff -u -r1.19.8.1 -r1.19.8.2 \ src/crypto/dist/ipsec-tools/src/setkey/token.l cvs rdiff -u -r1.163.2.11 -r1.163.2.12 src/sys/netipsec/key.c cvs rdiff -u -r1.6.2.3 -r1.6.2.4 src/tests/net/ipsec/t_ipsec_misc.sh Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/crypto/dist/ipsec-tools/src/setkey/parse.y diff -u src/crypto/dist/ipsec-tools/src/setkey/parse.y:1.18.4.1 src/crypto/dist/ipsec-tools/src/setkey/parse.y:1.18.4.2 --- src/crypto/dist/ipsec-tools/src/setkey/parse.y:1.18.4.1 Sat Oct 21 19:43:53 2017 +++ src/crypto/dist/ipsec-tools/src/setkey/parse.y Thu Jul 25 08:58:21 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: parse.y,v 1.18.4.1 2017/10/21 19:43:53 snj Exp $ */ +/* $NetBSD: parse.y,v 1.18.4.2 2019/07/25 08:58:21 martin Exp $ */ /* $KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $ */ @@ -115,7 +115,7 @@ static int setkeymsg_add __P((unsigned i } %token EOT SLASH BLCL ELCL -%token ADD UPDATE GET DELETE DELETEALL FLUSH DUMP EXIT +%token ADD UPDATE GET GETSPI DELETE DELETEALL FLUSH DUMP EXIT %token PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI %token F_MODE MODE F_REQID @@ -162,6 +162,7 @@ command : add_command | update_command | get_command + | getspi_command | delete_command | deleteall_command | flush_command @@ -261,6 +262,17 @@ get_command } ; + /* getspi command */ +getspi_command + : GETSPI ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT + { + int status; + + status = setkeymsg_add(SADB_GETSPI, $5, $3, $4); + if (status < 0) + return -1; + } + /* flush */ flush_command : FLUSH protocol_spec EOT @@ -1409,6 +1421,21 @@ setkeymsg_add(type, satype, srcs, dsts) } #endif + /* SPI == 0 allows the kernel to pick a random SPI */ + if (type == SADB_GETSPI && p_spi != 0) { + struct sadb_spirange spirange; + u_int slen = sizeof(struct sadb_spirange); + + memset(&spirange, 0, sizeof(spirange)); + spirange.sadb_spirange_len = PFKEY_UNIT64(slen); + spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; + spirange.sadb_spirange_min = p_spi; + spirange.sadb_spirange_max = p_spi; + + memcpy(buf + l, &spirange, slen); + l += slen; + } + len = sizeof(struct sadb_sa); m_sa.sadb_sa_len = PFKEY_UNIT64(len); m_sa.sadb_sa_exttype = SADB_EXT_SA; Index: src/crypto/dist/ipsec-tools/src/setkey/token.l diff -u src/crypto/dist/ipsec-tools/src/setkey/token.l:1.19.8.1 src/crypto/dist/ipsec-tools/src/setkey/token.l:1.19.8.2 --- src/crypto/dist/ipsec-tools/src/setkey/token.l:1.19.8.1 Sat Oct 21 19:43:53 2017 +++ src/crypto/dist/ipsec-tools/src/setkey/token.l Thu Jul 25 08:58:21 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: token.l,v 1.19.8.1 2017/10/21 19:43:53 snj Exp $ */ +/* $NetBSD: token.l,v 1.19.8.2 2019/07/25 08:58:21 martin Exp $ */ /* $KAME: token.l,v 1.44 2003/10/21 07:20:58 itojun Exp $ */ @@ -120,6 +120,7 @@ update { return(UPDATE); } delete { return(DELETE); } deleteall { return(DELETEALL); } get { return(GET); } +getspi { return(GETSPI); } flush { return(FLUSH); } dump { return(DUMP); } exit { return(EXIT); } Index: src/sys/netipsec/key.c diff -u src/sys/netipsec/key.c:1.163.2.11 src/sys/netipsec/key.c:1.163.2.12 --- src/sys/netipsec/key.c:1.163.2.11 Mon Jul 22 18:07:07 2019 +++ src/sys/netipsec/key.c Thu Jul 25 08:58:21 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.163.2.11 2019/07/22 18:07:07 martin Exp $ */ +/* $NetBSD: key.c,v 1.163.2.12 2019/07/25 08:58:21 martin Exp $ */ /* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $ */ /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.163.2.11 2019/07/22 18:07:07 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.163.2.12 2019/07/25 08:58:21 martin Exp $"); /* * This code is referred to RFC 2367 @@ -3517,7 +3517,8 @@ out: * others : found, pointer to a SA. */ static struct secasvar * -key_lookup_and_remove_sav(struct secashead *sah, u_int32_t spi) +key_lookup_and_remove_sav(struct secashead *sah, u_int32_t spi, + const struct secasvar *hint) { struct secasvar *sav = NULL; u_int state; @@ -3529,6 +3530,8 @@ key_lookup_and_remove_sav(struct secashe KASSERT(sav->state == state); if (sav->spi == spi) { + if (hint != NULL && hint != sav) + continue; sav->state = SADB_SASTATE_DEAD; SAVLIST_WRITER_REMOVE(sav); SAVLUT_WRITER_REMOVE(sav); @@ -5777,7 +5780,8 @@ key_api_update(struct socket *so, struct * We need to lookup and remove the sav atomically, so get it again * here by a special API while we have a reference to it. */ - oldsav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi); + oldsav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi, sav); + KASSERT(oldsav == NULL || oldsav == sav); /* We can release the reference because of oldsav */ KEY_SA_UNREF(&sav); if (oldsav == NULL) { @@ -6191,7 +6195,7 @@ key_api_delete(struct socket *so, struct sah = key_getsah_ref(&saidx, CMP_HEAD); if (sah != NULL) { /* get a SA with SPI. */ - sav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi); + sav = key_lookup_and_remove_sav(sah, sa0->sadb_sa_spi, NULL); key_sah_unref(sah); } Index: src/tests/net/ipsec/t_ipsec_misc.sh diff -u src/tests/net/ipsec/t_ipsec_misc.sh:1.6.2.3 src/tests/net/ipsec/t_ipsec_misc.sh:1.6.2.4 --- src/tests/net/ipsec/t_ipsec_misc.sh:1.6.2.3 Tue Nov 21 11:11:20 2017 +++ src/tests/net/ipsec/t_ipsec_misc.sh Thu Jul 25 08:58:21 2019 @@ -1,4 +1,4 @@ -# $NetBSD: t_ipsec_misc.sh,v 1.6.2.3 2017/11/21 11:11:20 martin Exp $ +# $NetBSD: t_ipsec_misc.sh,v 1.6.2.4 2019/07/25 08:58:21 martin Exp $ # # Copyright (c) 2017 Internet Initiative Japan Inc. # All rights reserved. @@ -40,9 +40,16 @@ setup_sasp() local lifetime=$5 local update=$6 local tmpfile=./tmp + local saadd=add + local saadd_algo_args="$algo_args" local extra= - if [ "$update" = sa ]; then + if [ "$update" = getspi ]; then + saadd=getspi + saadd_algo_args= + fi + + if [ "$update" = sa -o "$update" = getspi ]; then extra="update $ip_local $ip_peer $proto 10000 $algo_args; update $ip_peer $ip_local $proto 10001 $algo_args;" elif [ "$update" = sp ]; then @@ -51,8 +58,8 @@ setup_sasp() export RUMP_SERVER=$SOCK_LOCAL cat > $tmpfile <<-EOF - add $ip_local $ip_peer $proto 10000 -lh $lifetime -ls $lifetime $algo_args; - add $ip_peer $ip_local $proto 10001 -lh $lifetime -ls $lifetime $algo_args; + $saadd $ip_local $ip_peer $proto 10000 -lh $lifetime -ls $lifetime $saadd_algo_args; + $saadd $ip_peer $ip_local $proto 10001 -lh $lifetime -ls $lifetime $saadd_algo_args; spdadd $ip_local $ip_peer any -P out ipsec $proto/transport//require; $extra EOF @@ -67,8 +74,8 @@ setup_sasp() export RUMP_SERVER=$SOCK_PEER cat > $tmpfile <<-EOF - add $ip_local $ip_peer $proto 10000 -lh $lifetime -ls $lifetime $algo_args; - add $ip_peer $ip_local $proto 10001 -lh $lifetime -ls $lifetime $algo_args; + $saadd $ip_local $ip_peer $proto 10000 -lh $lifetime -ls $lifetime $saadd_algo_args; + $saadd $ip_peer $ip_local $proto 10001 -lh $lifetime -ls $lifetime $saadd_algo_args; spdadd $ip_peer $ip_local any -P out ipsec $proto/transport//require; $extra EOF @@ -370,6 +377,71 @@ add_test_update() atf_add_test_case ${name} } +test_getspi_update() +{ + local proto=$1 + local algo=$2 + local ip_local=10.0.0.1 + local ip_peer=10.0.0.2 + local algo_args="$(generate_algo_args $proto $algo)" + local proto_cap=$(echo $proto | tr 'a-z' 'A-Z') + local outfile=./out + + rump_server_crypto_start $SOCK_LOCAL netipsec + rump_server_crypto_start $SOCK_PEER netipsec + rump_server_add_iface $SOCK_LOCAL shmif0 $BUS + rump_server_add_iface $SOCK_PEER shmif0 $BUS + + export RUMP_SERVER=$SOCK_LOCAL + atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0 + atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24 + + export RUMP_SERVER=$SOCK_PEER + atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0 + atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24 + + setup_sasp $proto "$algo_args" $ip_local $ip_peer 100 getspi + + extract_new_packets $BUS > $outfile + + export RUMP_SERVER=$SOCK_LOCAL + atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer + + extract_new_packets $BUS > $outfile + atf_check -s exit:0 -o match:"$ip_local > $ip_peer: $proto_cap" \ + cat $outfile + atf_check -s exit:0 -o match:"$ip_peer > $ip_local: $proto_cap" \ + cat $outfile +} + +add_test_getspi_update() +{ + local proto=$1 + local algo=$2 + local _algo=$(echo $algo | sed 's/-//g') + local name= desc= + + desc="Tests trying to getspi and udpate SA of $proto ($algo)" + name="ipsec_getspi_update_sa_${proto}_${_algo}" + + atf_test_case ${name} cleanup + eval " + ${name}_head() { + atf_set descr \"$desc\" + atf_set require.progs rump_server setkey + } + ${name}_body() { + test_getspi_update $proto $algo + rump_server_destroy_ifaces + } + ${name}_cleanup() { + \$DEBUG && dump + cleanup + } + " + atf_add_test_case ${name} +} + add_sa() { local proto=$1 @@ -717,6 +789,7 @@ atf_init_test_cases() add_test_lifetime ipv6 esp $algo add_test_update esp $algo sa add_test_update esp $algo sp + add_test_getspi_update esp $algo add_test_spi esp $algo new delete add_test_spi esp $algo old delete add_test_spi esp $algo new timeout @@ -728,6 +801,7 @@ atf_init_test_cases() add_test_lifetime ipv6 ah $algo add_test_update ah $algo sa add_test_update ah $algo sp + add_test_getspi_update ah $algo add_test_spi ah $algo new delete add_test_spi ah $algo old delete add_test_spi ah $algo new timeout