diff --git a/.github/workflows/sshd-test.yml b/.github/workflows/sshd-test.yml index 13d33710..3336e451 100644 --- a/.github/workflows/sshd-test.yml +++ b/.github/workflows/sshd-test.yml @@ -106,3 +106,20 @@ jobs: touch sshd_config.txt ./configure --enable-all LDFLAGS="-L${{ github.workspace }}/build-dir/lib" CPPFLAGS="-I${{ github.workspace }}/build-dir/include -DWOLFSSH_NO_FPKI -DWOLFSSH_NO_SFTP_TIMEOUT -DWOLFSSH_MAX_SFTP_RW=4000000 -DMAX_PATH_SZ=120" --enable-static --disable-shared && make sudo timeout --preserve-status -s 2 5 valgrind --error-exitcode=1 --leak-check=full ./apps/wolfsshd/wolfsshd -D -f sshd_config -h ./keys/server-key.pem -d -p 22222 + + - name: configure with debug + working-directory: ./wolfssh/ + run : | + ./configure --enable-all --enable-debug LDFLAGS="-L${{ github.workspace }}/build-dir/lib" CPPFLAGS="-I${{ github.workspace }}/build-dir/include -DWOLFSSH_NO_FPKI -DWOLFSSH_NO_SFTP_TIMEOUT -DWOLFSSH_MAX_SFTP_RW=4000000 -DMAX_PATH_SZ=120" + + - name: make + working-directory: ./wolfssh/ + run: make + + # ssh_kex_algos.sh requires debug output otherwise it is skipped + - name: Run wolfSSHd tests with debug + working-directory: ./wolfssh/apps/wolfsshd/test + run: | + git log -3 + sudo ./run_all_sshd_tests.sh --match ssh_kex_algos.sh + diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index d6ffb458..7e6fcca7 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -2,14 +2,60 @@ echo "Running all wolfSSHd tests" -if [ -z "$1" ]; then - USER=$USER -else - USER=$1 -fi +# Define an array of test cases +test_cases=( + "sshd_exec_test.sh" + "sshd_term_size_test.sh" + "sshd_large_sftp_test.sh" + "sshd_bad_sftp_test.sh" + "sshd_term_close_test.sh" + "ssh_kex_algos.sh" +) + +# Set defaults +USER=$USER + +# Parse arguments +MATCH="" +EXCLUDE="" +while [[ "$#" -gt 0 ]]; do + case "$1" in + --match) + MATCH="$2" + shift 2 + ;; + + --exclude) + EXCLUDE="$2" + shift 2 + ;; + + --user) + USER="$2" + shift 2 + ;; -TEST_HOST=$2 -TEST_PORT=$3 + --host) + TEST_HOST="$2" + shift 2 + ;; + + --port) + TEST_PORT="$2" + shift 2 + ;; + + *) + echo "Unknown option: $1" + echo "Expecting --host | --port | --user | --match | --exclude " + echo "All test cases:" + for test in "${test_cases[@]}"; do + echo " $test" + done + exit 1 + ;; + esac +done TOTAL=0 SKIPPED=0 @@ -57,41 +103,62 @@ run_test() { fi } -run_test "sshd_exec_test.sh" -run_test "sshd_term_size_test.sh" -run_test "sshd_large_sftp_test.sh" -run_test "sshd_bad_sftp_test.sh" -run_test "sshd_term_close_test.sh" +# Run the tests +if [[ -n "$MATCH" ]]; then + if [[ " ${test_cases[*]} " =~ " $MATCH " ]]; then + echo "Running test: $MATCH" + run_test "$MATCH" + else + echo "Error: Test '$MATCH' not found." + exit 1 + fi + + if [ "$USING_LOCAL_HOST" == 1 ]; then + printf "Shutting down test wolfSSHd\n" + stop_wolfsshd + fi +else + echo "Running all tests..." + for test in "${test_cases[@]}"; do + if [[ "$test" != "$EXCLUDE" ]]; then + echo "Running test: $test" + run_test "$test" + else + echo "Test '$test' is excluded. Skipping." + SKIPPED=$((SKIPPED+1)) + fi + done -#Github actions needs resolved for these test cases -#run_test "error_return.sh" -#run_test "sshd_login_grace_test.sh" + #Github actions needs resolved for these test cases + #run_test "error_return.sh" + #run_test "sshd_login_grace_test.sh" -# add aditional tests here, check on var USING_LOCAL_HOST if can make sshd -# server start/restart with changes + # add aditional tests here, check on var USING_LOCAL_HOST if can make sshd + # server start/restart with changes -if [ "$USING_LOCAL_HOST" == 1 ]; then - printf "Shutting down test wolfSSHd\n" - stop_wolfsshd -fi + if [ "$USING_LOCAL_HOST" == 1 ]; then + printf "Shutting down test wolfSSHd\n" + stop_wolfsshd + fi -# these tests require setting up an sshd -if [ "$USING_LOCAL_HOST" == 1 ]; then - run_test "sshd_forcedcmd_test.sh" - run_test "sshd_window_full_test.sh" -else - printf "Skipping tests that need to setup local SSHD\n" - SKIPPED=$((SKIPPED+2)) -fi + # these tests require setting up an sshd + if [ "$USING_LOCAL_HOST" == 1 ]; then + run_test "sshd_forcedcmd_test.sh" + run_test "sshd_window_full_test.sh" + else + printf "Skipping tests that need to setup local SSHD\n" + SKIPPED=$((SKIPPED+2)) + fi -# these tests run with X509 sshd-config loaded -if [ "$USING_LOCAL_HOST" == 1 ]; then - start_wolfsshd "sshd_config_test_x509" -fi -run_test "sshd_x509_test.sh" -if [ "$USING_LOCAL_HOST" == 1 ]; then - printf "Shutting down test wolfSSHd\n" - stop_wolfsshd + # these tests run with X509 sshd-config loaded + if [ "$USING_LOCAL_HOST" == 1 ]; then + start_wolfsshd "sshd_config_test_x509" + fi + run_test "sshd_x509_test.sh" + if [ "$USING_LOCAL_HOST" == 1 ]; then + printf "Shutting down test wolfSSHd\n" + stop_wolfsshd + fi fi printf "All tests ran, $TOTAL passed, $SKIPPED skipped\n" diff --git a/apps/wolfsshd/test/ssh_kex_algos.sh b/apps/wolfsshd/test/ssh_kex_algos.sh new file mode 100755 index 00000000..0bae8c4b --- /dev/null +++ b/apps/wolfsshd/test/ssh_kex_algos.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +# sshd local test + +ROOT_PWD=$(pwd) +cd ../../.. + +TEST_CLIENT="./apps/wolfssh/wolfssh" +PRIVATE_KEY="./keys/hansel-key-ecc.der" +PUBLIC_KEY="./keys/hansel-key-ecc.pub" + +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then + echo "expecting host and port as arguments" + echo "$0 127.0.0.1 22222 $USER" + exit 1 +fi +HOST_IP="$1" +HOST_PORT="$2" +USER_SET="$3" + +# check if wolfssh app was compiled +OUTPUT=$("$TEST_CLIENT" -V) +RESULT=$? +if [ "$RESULT" != 0 ]; 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 + echo "wolfSSH app not compiled with debug mode"; + exit 77 +fi + +# returns variable SUPPORTED as 1 or 0 +test_if_supported() { + SUPPORTED=0 + TEXT=$(./examples/client/client -E -u $USER_SET | grep "$1") + if [ $? = 0 ]; then + SUPPORTED=1 + fi + printf "$1 , $SUPPORTED\n" +} + +# test which algo's are supported +printf "Algo , Supported?\n" +test_if_supported "p256" +HAVE_P256=$SUPPORTED +test_if_supported "p384" +HAVE_P384=$SUPPORTED +test_if_supported "p521" +HAVE_P521=$SUPPORTED +printf "\n" + + +# Looks through the variable OUTPUT for the block of text containg the server +# host key algorithms sent. +find_substring_of_algos() { + # Extract the substring between start and end lines + SUBSTRING=$(printf "$OUTPUT" | grep -A20 "Server Host Key Algorithms") + SUBSTRING=$(printf "$SUBSTRING" | grep -v -A15 "DKI: Enc Algorithms") +} + +# take input argument $1 and checks if it is in the SUBSTRING +test_for_algo_name() { + #printf "substring found = $substring" + if echo "$SUBSTRING" | grep -q "$1"; then + printf "Found $1\n" + EXISTS=1 + else + printf "Did not find $1\n" + EXISTS=0 + fi +} + +# Expecting to find the algo name $1 +test_for_algo_name_success() { + test_for_algo_name "$1" + if [ $EXISTS != 1 ]; then + printf "Error finding algo name $1\n" + printf "Searched in :\n$SUBSTRING\n" + exit 1 + fi +} + +# Expecting to not find the algo name $1 +test_for_algo_name_fail() { + test_for_algo_name "$1" + if [ $EXISTS = 1 ]; then + printf "Error expected to not find algo name $1\n" + printf "Searched in :\n$SUBSTRING\n" + exit 1 + fi +} + +echo "$TEST_CLIENT -p $HOST_PORT $USER_SET@$HOST_IP" +OUTPUT=$(timeout 1 "$TEST_CLIENT" -p "$HOST_PORT" "$USER_SET"@"$HOST_IP" 2>&1) +find_substring_of_algos + +if [ $HAVE_P256 = 1 ]; then + test_for_algo_name_success "ecdsa-sha2-nistp256" +else + test_for_algo_name_fail "ecdsa-sha2-nistp256" +fi + +if [ $HAVE_P384 = 1 ]; then + test_for_algo_name_success "ecdsa-sha2-nistp384" +else + test_for_algo_name_fail "ecdsa-sha2-nistp384" +fi + +if [ $HAVE_P521 = 1 ]; then + test_for_algo_name_success "ecdsa-sha2-nistp521" +else + test_for_algo_name_fail "ecdsa-sha2-nistp521" +fi + +exit 0 + diff --git a/src/internal.c b/src/internal.c index 7550de0f..fb645fa7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -750,9 +750,18 @@ static const char cannedKeyAlgoNames[] = #ifndef WOLFSSH_NO_RSA_SHA2_256 "rsa-sha2-256," #endif/* WOLFSSH_NO_RSA_SHA2_256 */ +#ifndef WOLFSSH_NO_RSA_SHA2_512 + "rsa-sha2-512", +#endif /* WOLFSSH_NO_RSA_SHA2_512 */ #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 "ecdsa-sha2-nistp256," #endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP256 */ +#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384 + "ecdsa-sha2-nistp384," +#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP384 */ +#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521 + "ecdsa-sha2-nistp521," +#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP521 */ #ifdef WOLFSSH_CERTS #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 "x509v3-ecdsa-sha2-nistp256," diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 731a9688..84a8d17d 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -154,12 +154,14 @@ extern "C" { #define WOLFSSH_NO_ECDH_SHA2_NISTP256 #endif #if defined(WOLFSSH_NO_ECDH) \ - || !defined(WOLFSSL_SHA384) || !defined(HAVE_ECC384) + || !defined(WOLFSSL_SHA384) || \ + (!defined(HAVE_ECC384) && !defined(HAVE_ALL_CURVES)) #undef WOLFSSH_NO_ECDH_SHA2_NISTP384 #define WOLFSSH_NO_ECDH_SHA2_NISTP384 #endif #if defined(WOLFSSH_NO_ECDH) \ - || !defined(WOLFSSL_SHA512) || !defined(HAVE_ECC521) + || !defined(WOLFSSL_SHA512) || \ + (!defined(HAVE_ECC521) && !defined(HAVE_ALL_CURVES)) #undef WOLFSSH_NO_ECDH_SHA2_NISTP521 #define WOLFSSH_NO_ECDH_SHA2_NISTP521 #endif @@ -218,12 +220,14 @@ extern "C" { #define WOLFSSH_NO_ECDSA_SHA2_NISTP256 #endif #if defined(WOLFSSH_NO_ECDSA) || \ - !defined(WOLFSSL_SHA384) || !defined(HAVE_ECC384) + !defined(WOLFSSL_SHA384) || \ + (!defined(HAVE_ECC384) && !defined(HAVE_ALL_CURVES)) #undef WOLFSSH_NO_ECDSA_SHA2_NISTP384 #define WOLFSSH_NO_ECDSA_SHA2_NISTP384 #endif #if defined(WOLFSSH_NO_ECDSA) || \ - !defined(WOLFSSL_SHA512) || !defined(HAVE_ECC521) + !defined(WOLFSSL_SHA512) || \ + (!defined(HAVE_ECC521) && !defined(HAVE_ALL_CURVES)) #undef WOLFSSH_NO_ECDSA_SHA2_NISTP521 #define WOLFSSH_NO_ECDSA_SHA2_NISTP521 #endif