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
This commit is contained in:
martin 2019-07-25 08:58:21 +00:00
parent 0da30bf03c
commit 34255fb043
4 changed files with 120 additions and 14 deletions

View File

@ -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 int, unsigned int,
}
%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;

View File

@ -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); }

View File

@ -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 secashead *sah, u_int32_t spi)
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 mbuf *m, const struct sadb_msghdr *mhp)
* 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 mbuf *m,
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);
}

View File

@ -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