# $NetBSD: t_misc.sh,v 1.12 2022/06/13 07:59:15 martin Exp $ # # Copyright (c) 2018 Ryota Ozaki # 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. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. # BUS=bus SOCK_LOCAL=unix://wg_local SOCK_PEER=unix://wg_peer atf_test_case wg_rekey cleanup wg_rekey_head() { atf_set "descr" "tests of rekeying of wg(4)" atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" } wg_rekey_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 local rekey_after_time=3 local latest_handshake= setup_servers export RUMP_SERVER=$SOCK_LOCAL atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time export RUMP_SERVER=$SOCK_PEER atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_LOCAL $ping $ip_wg_peer latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \ | awk -F ': ' '/latest-handshake/ {print $2;}') $DEBUG && echo $latest_handshake sleep 1 $ping $ip_wg_peer atf_expect_fail "PR kern/56252" # No reinitiation is performed atf_check -s exit:0 -o match:"$latest_handshake" \ $HIJACKING wgconfig wg0 show peer peer0 # Wait for a reinitiation to be performed sleep $rekey_after_time $ping $ip_wg_peer # A reinitiation should be performed atf_check -s exit:0 -o not-match:"$latest_handshake" \ $HIJACKING wgconfig wg0 show peer peer0 latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \ | awk -F ': ' '/latest-handshake/ {print $2;}') $DEBUG && echo $latest_handshake # Wait for a reinitiation to be performed again sleep $((rekey_after_time+1)) $ping $ip_wg_peer # A reinitiation should be performed atf_check -s exit:0 -o not-match:"$latest_handshake" \ $HIJACKING wgconfig wg0 show peer peer0 destroy_wg_interfaces atf_fail "failed to trigger PR kern/56252" } wg_rekey_cleanup() { $DEBUG && dump cleanup } atf_test_case wg_handshake_timeout cleanup wg_handshake_timeout_head() { atf_set "descr" "tests of handshake timeout of wg(4)" atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" } wg_handshake_timeout_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 local rekey_after_time=3 local outfile=./out local rekey_timeout=3 local rekey_attempt_time=8 local n= setup_servers export RUMP_SERVER=$SOCK_LOCAL atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time export RUMP_SERVER=$SOCK_PEER atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 # Resolve arp export RUMP_SERVER=$SOCK_LOCAL $ping $ip_peer export RUMP_SERVER=$SOCK_PEER $ifconfig shmif0 down export RUMP_SERVER=$SOCK_LOCAL extract_new_packets $BUS > $outfile # Should fail atf_check -s not-exit:0 -o match:'100.0% packet loss' \ rump.ping -n -c 1 -w 1 $ip_wg_peer sleep $((rekey_attempt_time + rekey_timeout)) extract_new_packets $BUS > $outfile $DEBUG && cat $outfile n=$(grep "$ip_local.$port > $ip_peer.$port" $outfile |wc -l) atf_expect_fail "PR kern/56252" # Give up handshaking after three attempts atf_check_equal $n 3 export RUMP_SERVER=$SOCK_PEER $ifconfig shmif0 up export RUMP_SERVER=$SOCK_LOCAL destroy_wg_interfaces atf_fail "failed to trigger PR kern/56252" } wg_handshake_timeout_cleanup() { $DEBUG && dump cleanup } atf_test_case wg_cookie cleanup wg_cookie_head() { atf_set "descr" "tests of cookie messages of the wg(4) protocol" atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" } wg_cookie_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 local outfile=./out local rekey_timeout=5 setup_servers # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER # Emulate load on the peer atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.force_underload=1 export RUMP_SERVER=$SOCK_LOCAL extract_new_packets $BUS > $outfile $DEBUG && cat $outfile # The peer doesn't return a response message but a cookie message # and a session doesn't start $ping_fail $ip_wg_peer atf_expect_fail "PR kern/56252" extract_new_packets $BUS > $outfile $DEBUG && cat $outfile # XXX length 64 indicates the message is a cookie message atf_check -s exit:0 \ -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 64" \ cat $outfile $DEBUG && $HIJACKING wgconfig wg0 show all atf_check -s exit:0 -o match:"latest-handshake: \(never\)" \ $HIJACKING wgconfig wg0 # Wait for restarting a session sleep $rekey_timeout # The second attempt should be success because the init message has # a valid cookie. $ping $ip_wg_peer $DEBUG && $HIJACKING wgconfig wg0 show all atf_check -s exit:0 -o not-match:"latest-handshake: \(never\)" \ $HIJACKING wgconfig wg0 destroy_wg_interfaces atf_fail "failed to trigger PR kern/56252" } wg_cookie_cleanup() { $DEBUG && dump cleanup } atf_test_case wg_mobility cleanup wg_mobility_head() { atf_set "descr" "tests of the mobility of wg(4)" atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" } wg_mobility_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_peer_new=192.168.1.3 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 local outfile=./out setup_servers # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" # Initially, the local doesn't know the endpoint of the peer add_peer wg0 peer0 $key_pub_peer "" $ip_wg_peer/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 extract_new_packets $BUS > $outfile $DEBUG && cat $outfile # Ping from the local to the peer doesn't work because the local # doesn't know the endpoint of the peer export RUMP_SERVER=$SOCK_LOCAL $ping_fail $ip_wg_peer atf_expect_fail "PR kern/56252" extract_new_packets $BUS > $outfile $DEBUG && cat $outfile export RUMP_SERVER=$SOCK_PEER $ping $ip_wg_local extract_new_packets $BUS > $outfile $DEBUG && cat $outfile atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile # Change the IP address of the peer setup_common shmif0 inet $ip_peer_new 24 $ifconfig -w 10 # Ping from the local to the peer doesn't work because the local # doesn't know the change of the IP address of the peer export RUMP_SERVER=$SOCK_LOCAL $ping_fail $ip_wg_peer extract_new_packets $BUS > $outfile $DEBUG && cat $outfile atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile # Ping from the peer to the local works because the local notices # the change and updates the IP address of the peer export RUMP_SERVER=$SOCK_PEER $ping $ip_wg_local extract_new_packets $BUS > $outfile $DEBUG && cat $outfile atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer_new.$port" cat $outfile atf_check -s exit:0 -o match:"$ip_peer_new.$port > $ip_local.$port" cat $outfile atf_check -s exit:0 -o not-match:"$ip_local.$port > $ip_peer.$port" cat $outfile destroy_wg_interfaces atf_fail "failed to trigger PR kern/56252" } wg_mobility_cleanup() { $DEBUG && dump cleanup } atf_test_case wg_keepalive cleanup wg_keepalive_head() { atf_set "descr" "tests keepalive messages" atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" } wg_keepalive_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_peer_new=192.168.1.3 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 local outfile=./out local keepalive_timeout=3 setup_servers # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 # Shorten keepalive_timeout of the peer atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.keepalive_timeout=$keepalive_timeout export RUMP_SERVER=$SOCK_LOCAL extract_new_packets $BUS > $outfile $DEBUG && cat $outfile $ping $ip_wg_peer extract_new_packets $BUS > $outfile $DEBUG && cat $outfile sleep $((keepalive_timeout + 1)) $ping $ip_wg_peer extract_new_packets $BUS > $outfile $DEBUG && cat $outfile # XXX length 32 indicates the message is a keepalive (empty) message atf_check -s exit:0 -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 32" \ cat $outfile destroy_wg_interfaces } wg_keepalive_cleanup() { $DEBUG && dump cleanup } atf_test_case wg_psk cleanup wg_psk_head() { atf_set "descr" "tests preshared-key" atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" } test_psk_common() { } wg_psk_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_peer_new=192.168.1.3 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 local outfile=./out local pskfile=./psk local rekey_after_time=3 setup_servers export RUMP_SERVER=$SOCK_LOCAL atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time export RUMP_SERVER=$SOCK_PEER atf_check -s exit:0 -o ignore \ rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys key_psk=$(wg-keygen --psk) $DEBUG && echo $key_psk export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" echo "$key_psk" > $pskfile export RUMP_SERVER=$SOCK_LOCAL # The local always has the preshared key add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 \ $pskfile "$key_psk" $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER # First, try the peer without the preshared key add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_LOCAL extract_new_packets $BUS > $outfile $DEBUG && cat $outfile $ping_fail $ip_wg_peer extract_new_packets $BUS > $outfile $DEBUG && cat $outfile # Next, try with the preshared key export RUMP_SERVER=$SOCK_PEER delete_peer wg0 peer0 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 \ $pskfile "$key_psk" $ifconfig -w 10 # Need a rekey atf_check -s exit:0 sleep $((rekey_after_time + 1)) export RUMP_SERVER=$SOCK_LOCAL extract_new_packets $BUS > $outfile $DEBUG && cat $outfile $ping $ip_wg_peer extract_new_packets $BUS > $outfile $DEBUG && cat $outfile # Then, try again without the preshared key just in case export RUMP_SERVER=$SOCK_PEER delete_peer wg0 peer0 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 # Need a rekey atf_check -s exit:0 sleep $((rekey_after_time + 1)) export RUMP_SERVER=$SOCK_LOCAL $ping_fail $ip_wg_peer rm -f $pskfile destroy_wg_interfaces } wg_psk_cleanup() { $DEBUG && dump cleanup } atf_test_case wg_malformed cleanup wg_malformed_head() { atf_set "descr" "tests malformed packet headers" atf_set "require.progs" "nc" "rump_server" "wgconfig" "wg-keygen" atf_set "timeout" "100" } wg_malformed_body() { local ifconfig="atf_check -s exit:0 rump.ifconfig" local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1" local ip_local=192.168.1.1 local ip_peer=192.168.1.2 local ip_wg_local=10.0.0.1 local ip_wg_peer=10.0.0.2 local port=51820 setup_servers # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer generate_keys export RUMP_SERVER=$SOCK_LOCAL setup_common shmif0 inet $ip_local 24 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_PEER setup_common shmif0 inet $ip_peer 24 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 $ifconfig -w 10 export RUMP_SERVER=$SOCK_LOCAL $ping $ip_wg_peer printf 'send malformed packets\n' $HIJACKING ping -c 1 -n $ip_peer printf 'x' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf 'xy' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf 'xyz' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf 'xyzw' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x00\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x00\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x01\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x01\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x02\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x02\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x03\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x03\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x04\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf '\x04\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port printf 'done sending malformed packets\n' $ping $ip_wg_peer } wg_malformed_cleanup() { $DEBUG && dump cleanup } atf_init_test_cases() { atf_add_test_case wg_rekey atf_add_test_case wg_handshake_timeout atf_add_test_case wg_cookie atf_add_test_case wg_mobility atf_add_test_case wg_keepalive atf_add_test_case wg_psk atf_add_test_case wg_malformed }