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 2019 Joyent, Inc.
16#
17
18# we can't presume /usr/bin/timeout is there
19timeout_cmd() {
20    $* &
21    sleep 3
22    kill $!
23    # we want to pause a while to make sure the monitor log is
24    # updated...
25    sleep 2
26}
27
28if [[ `id -u` -ne 0 ]]; then
29    echo "Error: need to be root or have effective UID of root." >&2
30    exit 255
31fi
32
33if [[ ! -x "$(type -p curl)" ]]; then
34    echo "Error: curl binary not found." >&2
35    exit 255
36fi
37
38# NOTE: If multihomed, this may fail in interesting ways...
39MY_IP=`netstat -in -f inet | egrep -v "Name|lo0" | awk '{print $4}' | head -1`
40TEST_REMOTE_DST1=10.90.1.25
41TEST_REMOTE_DST2=10.19.84.2
42TEST_REMOTE_DST3=10.19.84.3
43TEST_REMOTE_DST4=10.19.84.4
44
45T1_SRC=10.21.12.4
46T1_DST=10.21.12.5
47T1_PREFIX=10.21.12.0/24
48T2_SRC=10.51.50.4
49T2_DST=10.51.50.5
50T2_PREFIX=10.51.50.0/24
51
52CURL_DST3_LPORT=10001
53CURL_DST4_LPORT=10002
54CURL_DST1_LPORT=10003
55CURL_PORT=80
56
57MONITOR_LOG=/tmp/ipseckey-monitor.$$
58
59EACQ_PROG=/opt/os-tests/tests/pf_key/eacq-enabler
60
61$EACQ_PROG &
62eapid=$!
63
64echo "Warning, this trashes IPsec policy."
65ipsecconf -Fq
66
67# Setup the IPsec policy...
68ipsecconf -qa - << EOF
69# Global policy...
70# Remote-port-based policy.  Use different algorithms...
71{ raddr $TEST_REMOTE_DST3 rport $CURL_PORT ulp tcp } ipsec { encr_algs aes encr_auth_algs sha512 }
72
73# Unique policy...
74{ raddr $TEST_REMOTE_DST4 rport $CURL_PORT ulp tcp } ipsec { encr_algs aes encr_auth_algs sha256 sa unique }
75
76# Simple IP address policy.  Use an AH + ESP for it.
77{ raddr $TEST_REMOTE_DST1 } ipsec { auth_algs sha512 encr_algs aes(256) }
78{ raddr $TEST_REMOTE_DST2 } ipsec { auth_algs sha384 encr_algs aes(256) }
79
80# Tunnel policy...
81{ tunnel rush0 raddr $T1_PREFIX negotiate tunnel } ipsec { encr_algs aes-gcm(256) }
82# NULL-encryption...
83{ tunnel vh0 raddr $T2_PREFIX negotiate tunnel } ipsec {encr_auth_algs hmac-sha384 }
84EOF
85
86# Plumb the tunnels
87dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST1 rush0
88dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST2 vh0
89ipadm create-addr -t -T static -a local=$T1_SRC,remote=$T1_DST rush0/v4
90ipadm create-addr -t -T static -a local=$T2_SRC,remote=$T2_DST vh0/v4
91route add $T1_PREFIX $T1_DST
92route add $T2_PREFIX $T2_DST
93
94ipseckey flush
95ipseckey -np monitor > $MONITOR_LOG &
96IPSECKEY_PID=$!
97
98# give the monitor some time to get set up
99sleep 3
100
101# Launch pings to various addresses (each requiring an ACQUIRE).
102
103timeout_cmd ping -svn $TEST_REMOTE_DST1 1024 1
104timeout_cmd ping -svn $TEST_REMOTE_DST2 1024 1
105timeout_cmd ping -svn $T1_DST 1024 1
106timeout_cmd ping -svn $T2_DST 1024 1
107
108# Now try some curls to trigger local port and unique policy.
109
110# port-only for DST3
111timeout_cmd curl --local-port $CURL_DST3_LPORT \
112    http://$TEST_REMOTE_DST3:$CURL_PORT
113# unique for DST4
114timeout_cmd curl --local-port $CURL_DST4_LPORT \
115    http://$TEST_REMOTE_DST4:$CURL_PORT
116# Nothing specced for DST1
117timeout_cmd curl --local-port $CURL_DST1_LPORT \
118    http://$TEST_REMOTE_DST1:$CURL_PORT
119
120# Clean up.
121kill $IPSECKEY_PID
122kill $eapid
123# Unplumb the tunnels
124route delete $T2_PREFIX $T2_DST
125route delete $T1_PREFIX $T1_DST
126ipadm delete-addr vh0/v4
127ipadm delete-addr rush0/v4
128ipadm delete-if vh0
129ipadm delete-if rush0
130dladm delete-iptun vh0
131dladm delete-iptun rush0
132# Flush policy
133ipsecconf -Fq
134# Use SMF to restore anything that may have been there.  "restart" on
135# a disabled service is a NOP, but an enabled one will get
136# /etc/inet/ipsecinit.conf reloaded.
137svcadm restart ipsec/policy
138
139# give the monitor some time to finish up
140sleep 5
141
142# Process MONITOR_LOG's output...
143echo "Checking for unique local port only in one ACQUIRE case."
144egrep "$CURL_DST3_LPORT|$CURL_DST4_LPORT|$CURL_DST1_LPORT" \
145    $MONITOR_LOG > /tmp/egrep.$$
146grep $CURL_DST4_LPORT $MONITOR_LOG > /tmp/grep.$$ || {
147    echo "unique port $CURL_DST4_LPORT missing from monitor log."
148    exit 1
149}
150diff /tmp/grep.$$ /tmp/egrep.$$
151if [[ $? != 0 ]]; then
152    echo "More than just the one unique port $CURL_DST4_LPORT found."
153    exit 1
154fi
155
156# Split out extended (file.0) and regular (file.1) ACQUIREs.
157# NOTE: "+7" is dependent on "ipseckey monitor"'s first output where it gets
158# the "PROMISC" reply.
159
160mkdir /tmp/raw.$$
161savedir=$PWD
162cd /tmp/raw.$$
163tail +7 $MONITOR_LOG | \
164    awk 'BEGIN { out=0; } /Read/ {out++;} { print >> (out % 2) }'
165cd $savedir
166
167# Pluck out the address extension from the two ACQUIRE types.
168# NOTE: Add any new in-ACQUIRE address types here if more arrive.
169egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/0 > /tmp/extended-addresses.$$
170egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/1 > /tmp/regular-addresses.$$
171
172# There should be NO differences between address fields from regular vs.
173# extended ACQUIREs. If there are, it's a bug (or an older version of illumos).
174diff /tmp/extended-addresses.$$ /tmp/regular-addresses.$$
175if [[ $? != 0 ]]; then
176    echo "Address fields in ACQUIRE differ."
177    rc=1
178else
179    rc=0
180fi
181
182/bin/rm -rf /tmp/*-addresses.$$ /tmp/raw.$$
183/bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ /tmp/addrs.$$ $MONITOR_LOG
184
185exit $rc
186