1#!/usr/bin/ksh
2
3#
4# This file and its contents are supplied under the terms of the
5# Common Development and Distribution License ("CDDL"), version 1.0.
6# You may only use this file in accordance with the terms of version
7# 1.0 of the CDDL.
8#
9# A full copy of the text of the CDDL should have accompanied this
10# source.  A copy of the CDDL is also available via the Internet at
11# http://www.illumos.org/license/CDDL.
12#
13
14#
15# Copyright (c) 2017 Joyent, Inc.
16#
17
18if [ `id -u` -ne 0 ]; then
19	echo "Need to be root or have effective UID of root."
20	exit 255
21fi
22
23# NOTE: If multihomed, this may fail in interesting ways...
24MY_IP=`netstat -in -f inet | egrep -v "Name|lo0" | awk '{print $4}' | head -1`
25TEST_REMOTE_DST1=10.90.1.25
26TEST_REMOTE_DST2=10.19.84.2
27TEST_REMOTE_DST3=10.19.84.3
28TEST_REMOTE_DST4=10.19.84.4
29
30T1_SRC=10.21.12.4
31T1_DST=10.21.12.5
32T1_PREFIX=10.21.12.0/24
33T2_SRC=10.51.50.4
34T2_DST=10.51.50.5
35T2_PREFIX=10.51.50.0/24
36
37MONITOR_LOG=/tmp/ipseckey-monitor.$$
38
39EACQ_PROG=/opt/os-tests/tests/pf_key/eacq-enabler
40
41$EACQ_PROG &
42eapid=$!
43
44echo "Warning, this trashes IPsec policy."
45ipsecconf -Fq
46
47# Setup the IPsec policy...
48ipsecconf -qa - << EOF
49# Global policy...
50# Remote-port-based policy.  Use different algorithms...
51{ raddr $TEST_REMOTE_DST3 rport 23 ulp tcp } ipsec { encr_algs aes encr_auth_algs sha512 }
52
53# Unique policy...
54{ raddr $TEST_REMOTE_DST4 rport 23 ulp tcp } ipsec { encr_algs aes encr_auth_algs sha256 sa unique }
55
56# Simple IP address policy.  Use an AH + ESP for it.
57{ raddr $TEST_REMOTE_DST1 } ipsec { auth_algs sha512 encr_algs aes(256) }
58{ raddr $TEST_REMOTE_DST2 } ipsec { auth_algs sha384 encr_algs aes(256) }
59
60# Tunnel policy...
61{ tunnel rush0 raddr $T1_PREFIX negotiate tunnel } ipsec { encr_algs aes-gcm(256) }
62# NULL-encryption...
63{ tunnel vh0 raddr $T2_PREFIX negotiate tunnel } ipsec {encr_auth_algs hmac-sha384 }
64EOF
65
66# Plumb the tunnels
67dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST1 rush0
68dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST2 vh0
69ipadm create-addr -t -T static -a local=$T1_SRC,remote=$T1_DST rush0/v4
70ipadm create-addr -t -T static -a local=$T2_SRC,remote=$T2_DST vh0/v4
71route add $T1_PREFIX $T1_DST
72route add $T2_PREFIX $T2_DST
73
74ipseckey flush
75ipseckey -np monitor > $MONITOR_LOG &
76IPSECKEY_PID=$!
77
78# Launch pings and telnets to different addresses (each requiring an ACQUIRE).
79ping -svn $TEST_REMOTE_DST1 1024 1 2>&1 > /dev/null &
80p1=$!
81ping -svn $TEST_REMOTE_DST2 1024 1 2>&1 > /dev/null &
82p2=$!
83ping -svn $T1_DST 1024 1 2>&1 > /dev/null &
84p3=$!
85ping -svn $T2_DST 1024 1 2>&1 > /dev/null &
86p4=$!
87
88echo "Waiting for pings..."
89pwait $p1 $p2 $p3 $p4
90
91# Now try some telnets to trigger port and unique policy.
92# port-only for DST3
93telnet $TEST_REMOTE_DST3 &
94tpid=$!
95t1port=`pfiles $tpid | grep sockname | awk '{print $5}'`
96echo "First local port == $t1port"
97sleep 10 ; kill $tpid
98# unique for DST4
99telnet $TEST_REMOTE_DST4 &
100tpid=$!
101t2port=`pfiles $tpid | grep sockname | awk '{print $5}'`
102echo "Second local port == $t2port"
103sleep 10 ; kill $tpid
104# Nothing specced for DST1
105telnet $TEST_REMOTE_DST1 &
106tpid=$!
107t3port=`pfiles $tpid | grep sockname | awk '{print $5}'`
108echo "Third local port == $t3port"
109sleep 10 ; kill $tpid
110
111# Clean up.
112kill $IPSECKEY_PID
113kill $eapid
114# Unplumb the tunnels
115route delete $T2_PREFIX $T2_DST
116route delete $T1_PREFIX $T1_DST
117ipadm delete-addr vh0/v4
118ipadm delete-addr rush0/v4
119ipadm delete-if vh0
120ipadm delete-if rush0
121dladm delete-iptun vh0
122dladm delete-iptun rush0
123# Flush policy
124ipsecconf -Fq
125# Use SMF to restore anything that may have been there.  "restart" on
126# a disabled service is a NOP, but an enabled one will get
127# /etc/inet/ipsecinit.conf reloaded.
128svcadm restart ipsec/policy
129
130# Process MONITOR_LOG's output...
131echo "Checking for unique local port only in one ACQUIRE case."
132egrep "$t1port|$t2port|$t3port" $MONITOR_LOG > /tmp/egrep.$$
133grep $t2port $MONITOR_LOG > /tmp/grep.$$
134diff /tmp/grep.$$ /tmp/egrep.$$
135if [[ $? != 0 ]]; then
136    echo "More than just the one unique port, $tport2, found in monitor output."
137    /bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ $MONITOR_LOG
138    exit 1
139fi
140
141# Split out extended (file.0) and regular (file.1) ACQUIREs.
142# NOTE: "+7" is dependent on "ipseckey monitor"'s first output where it gets
143# the "PROMISC" reply.
144
145mkdir /tmp/raw.$$
146savedir=$PWD
147cd /tmp/raw.$$
148tail +7 $MONITOR_LOG | \
149    awk 'BEGIN { out=0; } /Read/ {out++;} { print >> (out % 2) }'
150cd $savedir
151
152# Pluck out the address extension from the two ACQUIRE types.
153# NOTE: Add any new in-ACQUIRE address types here if more arrive.
154egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/0 > /tmp/extended-addresses.$$
155egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/1 > /tmp/regular-addresses.$$
156
157# There should be NO differences between address fields from regular vs.
158# extended ACQUIREs. If there are, it's a bug (or an older version of illumos).
159diff /tmp/extended-addresses.$$ /tmp/regular-addresses.$$
160if [[ $? != 0 ]]; then
161    echo "Address fields in ACQUIRE differ."
162    rc=1
163else
164    rc=0
165fi
166
167/bin/rm -rf /tmp/*-addresses.$$ /tmp/raw.$$
168/bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ /tmp/addrs.$$ $MONITOR_LOG
169
170exit $rc
171