]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
add ppp-over-tls tests (with pppd as the reference peer implementation)
authorDaniel Lenski <dlenski@gmail.com>
Fri, 22 May 2020 03:47:59 +0000 (20:47 -0700)
committerDaniel Lenski <dlenski@gmail.com>
Mon, 29 Mar 2021 02:27:01 +0000 (19:27 -0700)
These test OpenConnect's ability to communicate with the standard pppd using
PPP-over-TLS, with a variety of PPP negotiation options:

  ± IPv4
  ± IPv6
  ± DNS and NBNS server negotiation
  ± PPP header protocol/address field compression
  ± Van Jacobson header compression (always rejected by OpenConnect)

These tests use socat to create TLS socket pairs, connecting `openconnect
--protocol=nullppp` to one end and `pppd` to the other.

I tried and failed to combine socat and pppd invocations, but pppd seemingly
cannot handle being wrapped by libsocket_wrapper.so (nor libuid_wrapper.so;
it must run as root).

`pppd sync` (non-HDLC framing) appears to have trouble reacting to incoming
packets in this configuration, so OpenConnect has to invoke retry timers during
negotiation. This seems to be a bug in pppd, rather than a flaw in OpenConnect's
implementation of PPP. Added logging of the time that each run takes.

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
configure.ac
tests/Makefile.am
tests/common.sh
tests/ppp-over-tls [new file with mode: 0755]

index 6133ae23d7d9b088c7d84b24ed15069e91fe5beb..b8d97d54d6e89af93be0bed85684ed6eae27efd9 100644 (file)
@@ -644,6 +644,11 @@ AC_ARG_ENABLE([dsa-tests],
        [], [enable_dsa_tests=yes])
 AM_CONDITIONAL(TEST_DSA, [test "$enable_dsa_tests" = "yes"])
 
+AC_ARG_ENABLE([ppp-tests],
+       AS_HELP_STRING([--enable-ppp-tests], [Enable PPP tests (which require socat and pppd, and must run as root)]),
+       [enable_ppp_tests=yes])
+AM_CONDITIONAL(TEST_PPP, [test "$enable_ppp_tests" = "yes"])
+
 AM_CONDITIONAL(OPENCONNECT_GNUTLS,  [ test "$ssl_library" = "GnuTLS" ])
 AM_CONDITIONAL(OPENCONNECT_OPENSSL, [ test "$ssl_library" = "OpenSSL" ])
 AM_CONDITIONAL(OPENCONNECT_ESP, [ test "$esp" != "" ])
@@ -1157,6 +1162,8 @@ SUMMARY([Java bindings], [$with_java])
 SUMMARY([Build docs], [$build_www])
 SUMMARY([Unit tests], [$have_cwrap])
 SUMMARY([Net namespace tests], [$have_netns])
+SUMMARY([DSA tests], [$enable_dsa_tests])
+SUMMARY([PPP tests], [$enable_ppp_tests])
 SUMMARY([Insecure debugging], [$insecure_debugging])
 SUMMARY([NSIS installer], [$build_nsis])
 
index 99d34482ba09ddf2365b01151c1f420e714e14cd..5493e6ca8e7baf06ddcf136899d30202b47aa97a 100644 (file)
@@ -54,6 +54,10 @@ if HAVE_NETNS
 dist_check_SCRIPTS += dtls-psk sigterm
 endif
 
+if TEST_PPP
+dist_check_SCRIPTS += ppp-over-tls
+endif
+
 if HAVE_CWRAP
 dist_check_SCRIPTS += auth-username-pass auth-certificate auth-nonascii cert-fingerprint id-test obsolete-server-crypto pfs
 
index 31c27cd0d31ea941621687dca4b75cfb6cd64a7e..96d52e5f1943c8f4b2663565b118c3bd96165c51 100644 (file)
@@ -30,6 +30,8 @@ if test "${DISABLE_ASAN_BROKEN_TESTS}" = 1 && test "${PRELOAD}" = 1;then
 fi
 
 OCSERV=/usr/sbin/ocserv
+PPPD=/usr/sbin/pppd
+test $(id -u) -eq 0 && SUDO= || SUDO=sudo
 
 top_builddir=${top_builddir:-..}
 SOCKDIR="./sockwrap.$$.tmp"
@@ -38,6 +40,7 @@ export SOCKET_WRAPPER_DIR=$SOCKDIR
 export SOCKET_WRAPPER_DEFAULT_IFACE=2
 ADDRESS=127.0.0.$SOCKET_WRAPPER_DEFAULT_IFACE
 OPENCONNECT="${OPENCONNECT:-${top_builddir}/openconnect}"${EXEEXT}
+LOGFILE="$SOCKDIR/log.$$.tmp"
 OCCTL_SOCKET="${OCCTL_SOCKET:-./occtl-comp-$$.socket}"
 
 certdir="${srcdir}/certs"
@@ -66,6 +69,25 @@ launch_simple_sr_server() {
        LD_PRELOAD=libsocket_wrapper.so:libuid_wrapper.so UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $OCSERV $* &
 }
 
+launch_simple_pppd() {
+       CERT="$1"
+       KEY="$2"
+       shift 2
+       LD_PRELOAD=libsocket_wrapper.so socat \
+                PTY,rawer,b9600,link="$SOCKDIR/pppd.$$.pty" \
+                OPENSSL-LISTEN:443,verify=0,cert="$CERT",key="$KEY" 2>&1 &
+       PID=$!
+
+       sleep 3 # Wait for socat to create the PTY link
+
+       # It would be preferable to invoke `pppd notty` directly using socat, but it seemingly cannot handle
+       # being wrapped by libsocket_wrapper.so.
+       # pppd's option parsing is notably brittle: it must have the actual PTY device node, not a symlink
+       $SUDO $PPPD $(readlink "$SOCKDIR/pppd.$$.pty") noauth local debug nodetach logfile "$LOGFILE" $* 2>&1 &
+
+       # XX: Caller needs to use PID, rather than $!
+}
+
 wait_server() {
        trap "kill $1" 1 15 2
        sleep 5
diff --git a/tests/ppp-over-tls b/tests/ppp-over-tls
new file mode 100755 (executable)
index 0000000..1556b8a
--- /dev/null
@@ -0,0 +1,98 @@
+#!/bin/sh
+#
+# Copyright © 2020 Daniel Lenski
+#
+# This file is part of openconnect.
+#
+# This is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>
+
+srcdir=${srcdir:-.}
+top_builddir=${top_builddir:-..}
+
+. `dirname $0`/common.sh
+
+CERT=$certdir/server-cert.pem
+KEY=$certdir/server-key.pem
+
+echo "Testing PPP ... "
+
+echo -n "Connecting to PPP peer (HDLC/RFC1662, IPv4+IPv6, DNS, extraneous VJ and CCP)... "
+launch_simple_pppd $CERT $KEY 10.0.0.1:10.0.0.101 ms-dns 1.1.1.1 ms-dns 8.8.8.8 +ipv6 2>&1
+wait_server $PID
+start=$(date +%s)
+LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q --protocol=nullppp $ADDRESS:443 -u test --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --cookie "hdlc" >/dev/null 2>&1
+took=$(( $(date +%s) - start ))
+if grep -qF "rcvd [IPCP ConfAck " $LOGFILE && grep -qF "sent [IPCP ConfAck " $LOGFILE && grep -qF "rcvd [IPV6CP ConfAck " $LOGFILE && grep -qF "sent [IPV6CP ConfAck " $LOGFILE; then
+    echo "ok (took $took seconds)"
+else
+    fail $PID "Did not negotiate IPCP and IP6CP successfully."
+fi
+
+cleanup
+
+echo -n "Connecting to PPP peer (HDLC/RFC1662, IPv4+IPv6, DNS, extraneous VJ and CCP, no header compression)... "
+launch_simple_pppd $CERT $KEY 10.0.0.1:10.0.0.101 ms-dns 1.1.1.1 ms-dns 8.8.8.8 +ipv6 nopcomp noaccomp 2>&1
+wait_server $PID
+start=$(date +%s)
+LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q --protocol=nullppp $ADDRESS:443 -u test --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --cookie "hdlc" >/dev/null 2>&1
+took=$(( $(date +%s) - start ))
+if grep -qF "rcvd [IPCP ConfAck " $LOGFILE && grep -qF "sent [IPCP ConfAck " $LOGFILE && grep -qF "rcvd [IPV6CP ConfAck " $LOGFILE && grep -qF "sent [IPV6CP ConfAck " $LOGFILE; then
+    echo "ok (took $took seconds)"
+else
+    fail $PID "Did not negotiate IPCP and IP6CP successfully."
+fi
+
+cleanup
+
+echo -n "Connecting to PPP peer (sync/no-HDLC, IPv4+IPv6, DNS, extraneous VJ and CCP)... "
+launch_simple_pppd $CERT $KEY sync 10.0.0.1:10.0.0.101 ms-dns 1.1.1.1 ms-dns 8.8.8.8 +ipv6 2>&1
+wait_server $PID
+start=$(date +%s)
+LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q --protocol=nullppp $ADDRESS:443 -u test --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 >/dev/null 2>&1
+took=$(( $(date +%s) - start ))
+if grep -qF "rcvd [IPCP ConfAck " $LOGFILE && grep -qF "sent [IPCP ConfAck " $LOGFILE && grep -qF "rcvd [IPV6CP ConfAck " $LOGFILE && grep -qF "sent [IPV6CP ConfAck " $LOGFILE; then
+    echo "ok (took $took seconds)"
+else
+    fail $PID "Did not negotiate IPCP and IP6CP successfully."
+fi
+
+cleanup
+
+echo -n "Connecting to PPP peer (sync/no-HDLC, IPv4 only)... "
+launch_simple_pppd $CERT $KEY sync novj noccp 10.0.0.1:10.0.0.101 noipv6 2>&1
+wait_server $PID
+start=$(date +%s)
+LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q --protocol=nullppp $ADDRESS:443 -u test --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 >/dev/null 2>&1
+took=$(( $(date +%s) - start ))
+if grep -qF "rcvd [IPCP ConfAck " $LOGFILE && grep -qF "sent [IPCP ConfAck " $LOGFILE; then
+    echo "ok (took $took seconds)"
+else
+    fail $PID "Did not negotiate IPCP successfully."
+fi
+
+echo -n "Connecting to PPP peer (sync/no-HDLC, IPv6 only)... "
+launch_simple_pppd $CERT $KEY sync novj noccp noip +ipv6 2>&1
+wait_server $PID
+start=$(date +%s)
+LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q --protocol=nullppp $ADDRESS:443 -u test --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 >/dev/null 2>&1
+took=$(( $(date +%s) - start ))
+if grep -qF "rcvd [IPV6CP ConfAck " $LOGFILE && grep -qF "sent [IPV6CP ConfAck " $LOGFILE; then
+    echo "ok (took $took seconds)"
+else
+    fail $PID "Did not negotiate IP6CP successfully."
+fi
+
+cleanup
+
+exit 0