mirror of https://github.com/wolfSSL/wolfssh.git
wolfsshd: bind certificate auth to user, fail closed without FPKI
parent
cb9bb7a2a7
commit
eef8281609
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
id: cache-wolfssl
|
||||
with:
|
||||
path: build-dir/
|
||||
key: wolfssh-x509-interop-wolfssl-${{ env.WOLFSSL_REF }}-ubuntu-latest
|
||||
key: wolfssh-x509-interop-wolfssl-${{ env.WOLFSSL_REF }}-all-ubuntu-latest
|
||||
lookup-only: true
|
||||
|
||||
- name: Checkout, build, and install wolfSSL
|
||||
|
|
@ -35,7 +35,18 @@ jobs:
|
|||
repository: wolfssl/wolfssl
|
||||
ref: ${{ env.WOLFSSL_REF }}
|
||||
path: wolfssl
|
||||
configure: --enable-ssh --enable-keygen --enable-ed25519 --enable-curve25519
|
||||
# --enable-all defines WOLFSSL_FPKI, which compiles the UPN-vs-username
|
||||
# binding in wolfSSHd (apps/wolfsshd/auth.c). The client cert carries
|
||||
# UPN:fred@example, so user "fred" is bound to the certificate. The
|
||||
# wolfSSHd build still passes -DWOLFSSH_NO_FPKI below so the strict
|
||||
# FPKI profile (FASCN) is not required of the fred test certificate.
|
||||
#
|
||||
# Coverage note: this FPKI build exercises only the WOLFSSL_FPKI
|
||||
# success/binding path of RequestAuthentication. The non-FPKI
|
||||
# fail-closed reject branch (apps/wolfsshd/auth.c) is intentionally
|
||||
# not run here; it is verified at compile time and would need a
|
||||
# separate non-FPKI build to exercise at runtime.
|
||||
configure: --enable-all
|
||||
check: false
|
||||
install: true
|
||||
|
||||
|
|
@ -86,7 +97,7 @@ jobs:
|
|||
uses: actions/cache@v5
|
||||
with:
|
||||
path: build-dir/
|
||||
key: wolfssh-x509-interop-wolfssl-${{ env.WOLFSSL_REF }}-ubuntu-latest
|
||||
key: wolfssh-x509-interop-wolfssl-${{ env.WOLFSSL_REF }}-all-ubuntu-latest
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Restore PKIX-SSH cache
|
||||
|
|
@ -199,6 +210,39 @@ jobs:
|
|||
exit
|
||||
EOF
|
||||
|
||||
- name: Negative test - fred cert must not authenticate as another user
|
||||
working-directory: ./wolfssh/
|
||||
run: |
|
||||
# Regression guard for the cert principal-binding fix: a certificate
|
||||
# issued for "fred" (UPN:fred@example) must not be accepted for a
|
||||
# different SSH username. PreferredAuthentications=publickey plus
|
||||
# BatchMode keep this to a single publickey attempt with no password
|
||||
# fallback. The preceding positive tests already proved connectivity
|
||||
# and that fred's cert works; here we additionally require the failure
|
||||
# to be an authentication denial, so an unrelated ssh error (transport,
|
||||
# host-key, option change) cannot masquerade as a passing negative test.
|
||||
sudo useradd -m otheruser
|
||||
set +e
|
||||
../build-dir/bin/ssh -o StrictHostKeyChecking=accept-new \
|
||||
-o PreferredAuthentications=publickey \
|
||||
-o BatchMode=yes -o NumberOfPasswordPrompts=0 \
|
||||
-p 22222 -F ssh-pkixssh-config \
|
||||
-i ./keys/fred-key.pem otheruser@127.0.0.1 exit \
|
||||
> ssh-neg.out 2> ssh-neg.err
|
||||
rc=$?
|
||||
set -e
|
||||
cat ssh-neg.err || true
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "SECURITY FAILURE: fred certificate authenticated as otheruser"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -qi "permission denied" ssh-neg.err; then
|
||||
echo "Negative test inconclusive: ssh failed but not with an auth"
|
||||
echo "denial (possible transport/config error, not a binding reject)"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: fred certificate correctly rejected for otheruser (auth denied)"
|
||||
|
||||
- name: Show wolfSSHd log on failure
|
||||
if: failure()
|
||||
working-directory: ./wolfssh/
|
||||
|
|
|
|||
|
|
@ -1341,10 +1341,10 @@ static int RequestAuthentication(WS_UserAuthData* authData,
|
|||
ret = WOLFSSH_USERAUTH_REJECTED;
|
||||
}
|
||||
else {
|
||||
wolfSSH_Log(WS_LOG_INFO,
|
||||
"[SSHD] Relying on CA for public key check");
|
||||
#ifdef WIN32
|
||||
/* Still need to get users token on Windows */
|
||||
wolfSSH_Log(WS_LOG_INFO,
|
||||
"[SSHD] Relying on CA for public key check");
|
||||
rc = SetupUserTokenWin(usr, &authData->sf.publicKey,
|
||||
wolfSSHD_ConfigGetUserCAKeysFile(usrConf), authCtx);
|
||||
if (rc == WSSHD_AUTH_SUCCESS) {
|
||||
|
|
@ -1356,8 +1356,23 @@ static int RequestAuthentication(WS_UserAuthData* authData,
|
|||
"[SSHD] Error getting users token.");
|
||||
ret = WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
#else
|
||||
#elif defined(WOLFSSL_FPKI)
|
||||
/* The UPN-vs-username check above already bound the certificate
|
||||
* to the requested user, so the CA-verified chain is
|
||||
* sufficient. */
|
||||
wolfSSH_Log(WS_LOG_INFO,
|
||||
"[SSHD] Relying on CA for public key check");
|
||||
ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||
#else
|
||||
/* Without FPKI the certificate UPN/principal cannot be read, so
|
||||
* the requested user cannot be bound to the certificate. Fail
|
||||
* closed: require AuthorizedKeysFile (per-user key/cert mapping)
|
||||
* or a wolfSSL build with FPKI. */
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Certificate authentication cannot bind the requested "
|
||||
"user without FPKI or AuthorizedKeysFile; rejecting "
|
||||
"(user=%s)", usr);
|
||||
ret = WOLFSSH_USERAUTH_REJECTED;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue