diff --git a/.gitignore b/.gitignore index ceb666563..b3000f1e5 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,8 @@ examples/scpclient/wolfscp apps/wolfssh/wolfssh apps/wolfsshd/wolfsshd apps/wolfsshd/test/test_configuration +apps/wolfsshd/test/log.txt +apps/wolfsshd/test/sshd_config_* # test output tests/*.test diff --git a/apps/wolfsshd/auth.c b/apps/wolfsshd/auth.c index 60cef92ed..195353912 100644 --- a/apps/wolfsshd/auth.c +++ b/apps/wolfsshd/auth.c @@ -363,7 +363,8 @@ static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz, WOLFS char* storedHash; char* storedHashCpy = NULL; - if (usr == NULL || pw == NULL) { + /* Allow zero length passwords, but not NULL pointers. */ + if (usr == NULL || (pw == NULL && pwSz != 0)) { ret = WS_BAD_ARGUMENT; } @@ -373,7 +374,9 @@ static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz, WOLFS ret = WS_MEMORY_E; } else { - XMEMCPY(pwStr, pw, pwSz); + if (pwSz > 0) { + XMEMCPY(pwStr, pw, pwSz); + } pwStr[pwSz] = 0; } } diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 8f81f5477..ddb0d20d3 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -146,9 +146,10 @@ else if [ "$USING_LOCAL_HOST" == 1 ]; then run_test "sshd_forcedcmd_test.sh" run_test "sshd_window_full_test.sh" + run_test "sshd_empty_password_test.sh" else printf "Skipping tests that need to setup local SSHD\n" - SKIPPED=$((SKIPPED+2)) + SKIPPED=$((SKIPPED+3)) fi # these tests run with X509 sshd-config loaded diff --git a/apps/wolfsshd/test/sshd_empty_password_test.sh b/apps/wolfsshd/test/sshd_empty_password_test.sh new file mode 100755 index 000000000..614c438a6 --- /dev/null +++ b/apps/wolfsshd/test/sshd_empty_password_test.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +# Test for empty-password handling. + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "expecting host and port as arguments" + echo "$0 127.0.0.1 22222" + exit 1 +fi + +TEST_HOST="$1" +TEST_PORT="$2" +if [ ! -z "$3" ]; then + USER="$3" +else + USER=`whoami` +fi +PWD=`pwd` + +source ./start_sshd.sh + +cat < sshd_config_test_emptypw +Port $TEST_PORT +Protocol 2 +LoginGraceTime 600 +PermitRootLogin yes +PasswordAuthentication yes +PermitEmptyPasswords yes +UsePrivilegeSeparation no +UseDNS no +HostKey $PWD/../../../keys/server-key.pem +EOF + +# Fresh log so we only see this run's output. +sudo rm -f ./log.txt + +start_wolfsshd "sshd_config_test_emptypw" +if [ -z "$PID" ]; then + echo "Failed to start wolfsshd" + exit 1 +fi + +TEST_CLIENT="../../../examples/client/client" + +# Send an empty password +timeout 10 $TEST_CLIENT -u "$USER" -P "" -c 'true' \ + -h "$TEST_HOST" -p "$TEST_PORT" > /dev/null 2>&1 + +# Let wolfsshd flush the log before we stop it. +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 -----" + sudo cat ./log.txt + exit 1 +fi + +if ! sudo grep -q "Password incorrect" ./log.txt; then + echo "FAIL: empty-password code path was not exercised" + echo "(expected '[SSHD] Password incorrect.' in log)" + echo "----- log.txt -----" + sudo cat ./log.txt + exit 1 +fi + +exit 0