From 754317b6bf569ad6c935eaadb885e1bdf8ec332d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 19 Aug 2026 12:03:28 -0700 Subject: [PATCH] Use wolfssh-options in the test scripts The scripts now read the build options from the probe instead of grepping usage text, config.log and daemon logs. Drops the usage lines only tests read. --- apps/wolfsshd/test/run_all_sshd_tests.sh | 19 ++++++------- apps/wolfsshd/test/ssh_kex_algos.sh | 19 ++++++------- apps/wolfsshd/test/sshd_bad_sftp_test.sh | 6 +++++ .../wolfsshd/test/sshd_empty_password_test.sh | 12 +++++---- apps/wolfsshd/test/sshd_large_sftp_test.sh | 6 +++++ apps/wolfsshd/test/sshd_ossh_cert_test.sh | 3 ++- apps/wolfsshd/test/sshd_scp_fail.sh | 6 +++++ apps/wolfsshd/test/sshd_x509_upn_fail.sh | 7 +++-- apps/wolfsshd/test/wolfssh_options.sh | 26 ++++++++++++++++++ apps/wolfsshd/wolfsshd.c | 10 ++----- examples/client/client.c | 9 ++----- scripts/external.test | 10 ++++--- scripts/fwd.test | 7 ++++- scripts/get-put.test | 27 ++++++++++--------- scripts/scp.test | 17 ++++++------ scripts/sftp.test | 13 +++++---- 16 files changed, 125 insertions(+), 72 deletions(-) create mode 100755 apps/wolfsshd/test/wolfssh_options.sh diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 7f34ee00..f1ee3e33 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -16,6 +16,9 @@ test_cases=( # Set defaults USER=$USER +# Build options for this tree; defines WOLFSSH_OPTIONS and wolfssh_has. +. ./wolfssh_options.sh + # Parse arguments MATCH="" EXCLUDE="" @@ -424,16 +427,14 @@ else stop_wolfsshd fi - # ML-DSA composite host key test. Runs when we control the local daemon. - # The client side uses an ECC key since we only test the host key here. - # sshd_config_test_mldsa has no other host key, so a build without ML-DSA - # cannot start the daemon at all; check for support out here rather than - # letting the test script skip, which would come too late. ML-DSA comes from - # wolfSSL (HAVE_DILITHIUM) and has no wolfSSH configure option, so probe the - # client's algorithm list. The closed port keeps the probe from connecting. + # ML-DSA composite host key test. Runs when we control the local daemon; + # the client uses an ECC key since only the host key is under test. + # sshd_config_test_mldsa has no other host key, so an ML-DSA-less build + # cannot start the daemon; check out here, not in the test script. The + # check is the composite, not the umbrella: the ECDSA half can be missing + # on its own. if [ "$USING_LOCAL_HOST" == 1 ]; then - if ../../../examples/client/client -E -u "$USER" -h 127.0.0.1 -p 1 \ - 2>/dev/null | grep -q "ssh-mldsa87-es384@wolfssl.com"; then + if wolfssh_has MLDSA87_ES384; then start_wolfsshd "sshd_config_test_mldsa" run_test "sshd_mldsa_composite_test.sh" printf "Shutting down test wolfSSHd\n" diff --git a/apps/wolfsshd/test/ssh_kex_algos.sh b/apps/wolfsshd/test/ssh_kex_algos.sh index f6ec9d0f..74b2ec52 100755 --- a/apps/wolfsshd/test/ssh_kex_algos.sh +++ b/apps/wolfsshd/test/ssh_kex_algos.sh @@ -3,6 +3,7 @@ # sshd local test ROOT_PWD=$(pwd) +. ./wolfssh_options.sh cd ../../.. TEST_CLIENT="./apps/wolfssh/wolfssh" @@ -18,18 +19,18 @@ HOST_IP="$1" HOST_PORT="$2" USER_SET="$3" -# check if wolfssh app was compiled -OUTPUT=$("$TEST_CLIENT" -V) -RESULT=$? -if [ "$RESULT" != 0 ]; then +# check if wolfssh app was compiled. test_if_supported also drives the example +# client, and libtool can leave a script behind, so run each rather than -x. +if ! wolfssh_has SSHCLIENT || [ ! -x "$TEST_CLIENT" ] \ + || [ ! -x ./examples/client/client ] \ + || "$TEST_CLIENT" -V 2>&1 | grep -q "does not exist" \ + || ./examples/client/client "-?" 2>&1 | grep -q "does not exist"; then echo "wolfSSH app not compiled in"; exit 77 fi # Debug mode needs to be on to inspect the debug output -printf "$OUTPUT" | grep "DEBUG" -RESULT=$? -if [ "$RESULT" != 0 ]; then +if ! wolfssh_has DEBUG; then echo "wolfSSH app not compiled with debug mode"; exit 77 fi @@ -59,8 +60,8 @@ printf "\n" # host key algorithms sent. find_substring_of_algos() { # Extract the substring between start and end lines - SUBSTRING=$(printf "$OUTPUT" | grep -A100 "Server Host Key Algorithms") - SUBSTRING=$(printf "$SUBSTRING" | grep -v -A95 "DKI: Enc Algorithms") + SUBSTRING=$(printf '%s\n' "$OUTPUT" | grep -A100 "Server Host Key Algorithms") + SUBSTRING=$(printf '%s\n' "$SUBSTRING" | grep -v -A95 "DKI: Enc Algorithms") } # take input argument $1 and checks if it is in the SUBSTRING diff --git a/apps/wolfsshd/test/sshd_bad_sftp_test.sh b/apps/wolfsshd/test/sshd_bad_sftp_test.sh index c5a74a39..362de3bf 100755 --- a/apps/wolfsshd/test/sshd_bad_sftp_test.sh +++ b/apps/wolfsshd/test/sshd_bad_sftp_test.sh @@ -3,6 +3,7 @@ # sshd local test PWD=`pwd` +. ./wolfssh_options.sh cd ../../.. TEST_SFTP_CLIENT="./examples/sftpclient/wolfsftp" @@ -16,6 +17,11 @@ if [ -z "$1" ] || [ -z "$2" ]; then exit 1 fi +if ! wolfssh_has SFTP || [ ! -x "$TEST_SFTP_CLIENT" ]; then + echo "SFTP client not available in this build, skipping" + exit 77 +fi + mkdir test-$$ mkdir test-$$/subfolder diff --git a/apps/wolfsshd/test/sshd_empty_password_test.sh b/apps/wolfsshd/test/sshd_empty_password_test.sh index 614c438a..c5474290 100755 --- a/apps/wolfsshd/test/sshd_empty_password_test.sh +++ b/apps/wolfsshd/test/sshd_empty_password_test.sh @@ -8,6 +8,13 @@ if [ -z "$1" ] || [ -z "$2" ]; then exit 1 fi +# A password login can only be checked when a backend was compiled in. +. ./wolfssh_options.sh +if ! wolfssh_has PAM && ! wolfssh_has LIBCRYPT && ! wolfssh_has LIBLOGIN; then + echo "SKIP: wolfsshd built without a password check backend" + exit 77 +fi + TEST_HOST="$1" TEST_PORT="$2" if [ ! -z "$3" ]; then @@ -51,11 +58,6 @@ sleep 1 stop_wolfsshd # log.txt is owned by root (wolfsshd ran via sudo); use sudo to read it. -if sudo grep -q "No compiled in password check" ./log.txt; then - echo "SKIP: wolfsshd built without libcrypt/liblogin support" - exit 77 -fi - if sudo grep -q "Error checking password" ./log.txt; then echo "FAIL: empty-password NULL-guard regression detected" echo "----- log.txt -----" diff --git a/apps/wolfsshd/test/sshd_large_sftp_test.sh b/apps/wolfsshd/test/sshd_large_sftp_test.sh index 71be8368..6699eae2 100755 --- a/apps/wolfsshd/test/sshd_large_sftp_test.sh +++ b/apps/wolfsshd/test/sshd_large_sftp_test.sh @@ -3,6 +3,7 @@ # sshd local test PWD=`pwd` +. ./wolfssh_options.sh cd ../../.. TEST_SFTP_CLIENT="./examples/sftpclient/wolfsftp" @@ -16,6 +17,11 @@ if [ -z "$1" ] || [ -z "$2" ]; then exit 1 fi +if ! wolfssh_has SFTP || [ ! -x "$TEST_SFTP_CLIENT" ]; then + echo "SFTP client not available in this build, skipping" + exit 77 +fi + # wolfSSHd confines SFTP access to the user's home directory, so the remote # file must live under it. Resolve the same home directory wolfSSHd uses # (the passwd entry), falling back to $HOME. diff --git a/apps/wolfsshd/test/sshd_ossh_cert_test.sh b/apps/wolfsshd/test/sshd_ossh_cert_test.sh index f78a2960..5fce73c2 100755 --- a/apps/wolfsshd/test/sshd_ossh_cert_test.sh +++ b/apps/wolfsshd/test/sshd_ossh_cert_test.sh @@ -28,13 +28,14 @@ set +m # quiet job-control "Terminated" notices when stopping the daemon PWD0=$(pwd) +. ./wolfssh_options.sh cd ../../.. ROOT=$(pwd) skip() { echo "$1"; cd "$PWD0"; exit 77; } # Only meaningful when wolfSSHd was built with OpenSSH certificate support. -grep -q "WOLFSSH_OSSH_CERTS" config.log 2>/dev/null || \ +wolfssh_has OSSH_CERTS || \ skip "wolfSSHd not built with --enable-ossh-certs, skipping" WOLFSSHD="$ROOT/apps/wolfsshd/wolfsshd" diff --git a/apps/wolfsshd/test/sshd_scp_fail.sh b/apps/wolfsshd/test/sshd_scp_fail.sh index 05797257..02569853 100755 --- a/apps/wolfsshd/test/sshd_scp_fail.sh +++ b/apps/wolfsshd/test/sshd_scp_fail.sh @@ -3,6 +3,7 @@ # sshd local test PWD=`pwd` +. ./wolfssh_options.sh cd ../../.. TEST_SCP_CLIENT="./examples/scpclient/wolfscp" @@ -16,6 +17,11 @@ if [ -z "$1" ] || [ -z "$2" ]; then exit 1 fi +if ! wolfssh_has SCP || [ ! -x "$TEST_SCP_CLIENT" ]; then + echo "SCP client not available in this build, skipping" + exit 77 +fi + mkdir test-$$ OUTDIR="`pwd`/test-$$" diff --git a/apps/wolfsshd/test/sshd_x509_upn_fail.sh b/apps/wolfsshd/test/sshd_x509_upn_fail.sh index 559356dd..0a19dcdb 100755 --- a/apps/wolfsshd/test/sshd_x509_upn_fail.sh +++ b/apps/wolfsshd/test/sshd_x509_upn_fail.sh @@ -6,11 +6,10 @@ # "example". The wolfSSHd UPN domain check must therefore reject the cert. PWD=`pwd` +. ./wolfssh_options.sh -# The UPN domain check is compiled only when wolfSSL is built with FPKI. Probe -# the daemon binary's help output, which prints an FPKI marker under the same -# build guard, and skip when the check is not present. -if ! ../wolfsshd "-?" 2>&1 | grep -q "FPKI"; then +# The UPN domain check is compiled only when wolfSSL is built with FPKI. +if ! wolfssh_has FPKI; then echo "wolfSSHd built without FPKI; UPN domain check not compiled in, skipping" exit 77 fi diff --git a/apps/wolfsshd/test/wolfssh_options.sh b/apps/wolfsshd/test/wolfssh_options.sh new file mode 100755 index 00000000..0c99fafb --- /dev/null +++ b/apps/wolfsshd/test/wolfssh_options.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Build option probe for the wolfSSHd test scripts. Source it before any cd, +# since it resolves the tree from the script's own location: +# +# . ./wolfssh_options.sh +# if ! wolfssh_has SFTP; then +# echo "built without SFTP, skipping" +# exit 77 +# fi +# +# The tests run from this directory, so the one path to the build tree lives +# here. WOLFSSH_ROOT is absolute, so it survives their cd ../../.. . A probe +# that will not run is a build problem, not an option being off. + +WOLFSSH_ROOT=$(cd "$(dirname "$0")/../../.." && pwd) || exit 1 +WOLFSSH_OPTIONS=$("$WOLFSSH_ROOT/apps/wolfssh-options") || { + echo "fail: could not run $WOLFSSH_ROOT/apps/wolfssh-options" + exit 1 +} + +# Whole line match, so one option name cannot match another that has it as a +# prefix. +wolfssh_has() { + echo "$WOLFSSH_OPTIONS" | grep -qx "$1" +} diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 5b023955..a294661a 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -195,19 +195,13 @@ static void ShowUsage(void) printf("wolfSSHd %s linked with wolfSSL %s\n", LIBWOLFSSH_VERSION_STRING, LIBWOLFSSL_VERSION_STRING); printf(" -? display this help and exit\n"); - printf(" -f Configuration file to use, default is " - "/etc/ssh/sshd_config\n"); + printf(" -f Configuration file to use, default is:\n" + " /etc/ssh/sshd_config\n"); printf(" -p Port number to listen on\n"); printf(" -d Turn on debug mode\n"); printf(" -D Run in foreground (do not detach)\n"); printf(" -h host private key file to use\n"); printf(" -E append to log file\n"); -#ifdef WOLFSSL_FPKI - /* build-capability note, separated from the option list; also greppable by - * test scripts, for the cert UPN domain check (AuthorizedUPNDomains) */ - printf("\n"); - printf("Build features: FPKI certificate UPN domain checking\n"); -#endif } diff --git a/examples/client/client.c b/examples/client/client.c index f9321bda..b397075e 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -101,8 +101,8 @@ static void ShowUsage(void) printf(" -x exit after successful connection without doing\n" " read/write\n"); #ifdef WOLFSSH_TEST_BLOCK - printf("-N non-blocking sockets required when compiled with " - "WOLFSSH_TEST_BLOCK\n"); + printf(" -N non-blocking sockets, required when compiled with\n" + " WOLFSSH_TEST_BLOCK\n"); #else printf(" -N use non-blocking sockets\n"); #endif @@ -129,11 +129,6 @@ static void ShowUsage(void) printf(" -k set the list of key algos\n"); printf(" -C set the list of encrypt algos\n"); printf(" -q turn off debugging output\n"); -#ifndef WOLFSSH_HAVE_SYMLINK - /* report disabled symlink checking so test scripts can skip the - * symlink-rejection cases the server would otherwise follow */ - printf(" symlink checking off (e.g. WOLFSSH_NO_SYMLINK_CHECK)\n"); -#endif } diff --git a/scripts/external.test b/scripts/external.test index d7c50752..7dbc2e78 100755 --- a/scripts/external.test +++ b/scripts/external.test @@ -13,10 +13,14 @@ else fi # test for nonblocking only -./examples/client/client -h | grep WOLFSSH_TEST_BLOCK -if [ $? -eq 0 ] +WOLFSSH_OPTIONS=$(./apps/wolfssh-options) || { + echo "fail: could not run ./apps/wolfssh-options" + exit 1 +} + +if echo "$WOLFSSH_OPTIONS" | grep -qx "TEST_BLOCK" then - echo "macro NO_WOLFSSH_CLIENT was used" + echo "macro WOLFSSH_TEST_BLOCK was used" echo "skipping for now" exit 77 fi diff --git a/scripts/fwd.test b/scripts/fwd.test index 1b1c9eb8..fb094955 100755 --- a/scripts/fwd.test +++ b/scripts/fwd.test @@ -42,7 +42,12 @@ then fi ## test for nonblocking only -if ./examples/client/client "-?" 2>&1 | grep WOLFSSH_TEST_BLOCK >/dev/null 2>&1 +WOLFSSH_OPTIONS=$(./apps/wolfssh-options) || { + echo "fail: could not run ./apps/wolfssh-options" + exit 1 +} + +if echo "$WOLFSSH_OPTIONS" | grep -qx "TEST_BLOCK" then echo "skipping: non-blocking test" exit 77 diff --git a/scripts/get-put.test b/scripts/get-put.test index 9fedb6a7..10a30561 100755 --- a/scripts/get-put.test +++ b/scripts/get-put.test @@ -6,25 +6,28 @@ then exit 1 fi +WOLFSSH_OPTIONS=$(./apps/wolfssh-options) || { + echo "fail: could not run ./apps/wolfssh-options" + exit 1 +} + # test SFTP client is working (that NO_WOLFSSH_CLIENT was not used) +if ! echo "$WOLFSSH_OPTIONS" | grep -qx "CLIENT" +then + echo "macro NO_WOLFSSH_CLIENT was used" + echo "skipping test" + exit 77 +fi + ./examples/sftpclient/wolfsftp -h if [ $? -ne 0 ] then - ./examples/sftpclient/wolfsftp -h | grep NO_WOLFSSH_CLIENT - if [ $? -eq 0 ] - then - echo "macro NO_WOLFSSH_CLIENT was used" - echo "skipping test" - exit 77 - else - echo "wolfSFTP client not compiled in or not working" - exit 1 - fi + echo "wolfSFTP client not compiled in or not working" + exit 1 fi # test for nonblocking only -./examples/client/client -h | grep WOLFSSH_TEST_BLOCK -if [ $? -eq 0 ] +if echo "$WOLFSSH_OPTIONS" | grep -qx "TEST_BLOCK" then echo "macro WOLFSSH_TEST_BLOCK was used" exit 77 diff --git a/scripts/scp.test b/scripts/scp.test index fe7efe1f..20f9737e 100755 --- a/scripts/scp.test +++ b/scripts/scp.test @@ -10,8 +10,12 @@ ready_file=`pwd`/wolfssh_scp_ready$$ # test for nonblocking only - wolfscp does not support -N flag for non-blocking # mode, so we must skip when TEST_BLOCK is enabled -./examples/client/client -h | grep WOLFSSH_TEST_BLOCK -if [ $? -eq 0 ] +WOLFSSH_OPTIONS=$(./apps/wolfssh-options) || { + echo "fail: could not run ./apps/wolfssh-options" + exit 1 +} + +if echo "$WOLFSSH_OPTIONS" | grep -qx "TEST_BLOCK" then echo "WOLFSSH_TEST_BLOCK detected" echo "wolfscp client does not support non-blocking mode, skipping test" @@ -192,12 +196,9 @@ if test $RESULT -eq 0; then exit 1 fi -# The symlink-rejection guard is compiled out by WOLFSSH_NO_SYMLINK_CHECK, which -# the example client reports in its usage output (-?). Skip this test when it is -# set: the server then follows symlinks by design and the check below would -# false-fail. -./examples/client/client '-?' | grep WOLFSSH_NO_SYMLINK_CHECK -if [ $? -eq 0 ]; then +# Without the symlink-rejection guard the server follows symlinks by design, +# so the check below would false-fail. +if ! echo "$WOLFSSH_OPTIONS" | grep -qx "SYMLINK_CHECK"; then echo "symlink checking disabled, skipping symlink test" else echo "Test that the server refuses to follow a symlink (server to local)" diff --git a/scripts/sftp.test b/scripts/sftp.test index 261810ac..4e6a5763 100755 --- a/scripts/sftp.test +++ b/scripts/sftp.test @@ -10,9 +10,13 @@ nonblockingOnly=0 [ ! -x ./examples/sftpclient/wolfsftp ] && echo -e "\n\nwolfSFTP client doesn't exist" && exit 1 +WOLFSSH_OPTIONS=$(./apps/wolfssh-options) || { + echo "fail: could not run ./apps/wolfssh-options" + exit 1 +} + # test for if the SFTP client works -./examples/sftpclient/wolfsftp -h | grep NO_WOLFSSH_CLIENT -if [ $? -eq 0 ] +if ! echo "$WOLFSSH_OPTIONS" | grep -qx "CLIENT" then echo "macro NO_WOLFSSH_CLIENT was used" echo "skipping test" @@ -20,10 +24,9 @@ then fi # test for nonblocking only -./examples/client/client -h | grep WOLFSSH_TEST_BLOCK -if [ $? -eq 0 ] +if echo "$WOLFSSH_OPTIONS" | grep -qx "TEST_BLOCK" then - echo "macro NO_WOLFSSH_CLIENT was used" + echo "macro WOLFSSH_TEST_BLOCK was used" nonblockingOnly=1 fi