wolfSSH_shutdown() returns WS_WANT_WRITE when the channel EOF, exit and
close messages are still queued on the non-blocking socket. Masking that
to WS_SUCCESS reported a clean exit for a session whose close messages
never reached the peer.
Mask a want write from the drain worker only, where the close messages
are already sent. The want read masking stays on both, wolfSSH_shutdown()
runs a worker of its own and passes that want read back.
- --enable-sshclient defaults to no, so the app was built only by the
configs that use --enable-all, and never under the multi-compiler
warning flags. Add it to the multi-compiler matrix.
- Add scripts/sshclient.test, run by make check. It covers the client's
sessions and the -E log file against the echoserver.
- The script is not gated on BUILD_SSHCLIENT. It exits 77 when the
client app or the echoserver isn't there, so every build runs it and
the ones without the app report it as a skip.
- Check the client and the echoserver by asking each for its usage
message, not by looking for the file. Both are libtool wrapper
scripts in the build tree, and a wrapper outlives a reconfigure that
drops the program it wraps, then runs only far enough to say so.
- The echoserver runs in echo mode and the client's stdin comes from a
fifo written a piece at a time, so the session carries data and ends
on its own. Each client run has a watchdog.
- Rename sshd-test.yml's job to cover both apps. That workflow builds
the client app along with wolfsshd.
- Check that the command reaches the server, now that the client sends
it rather than discarding it.
- Make the SINGLE_THREADED guard a preprocessor #error. The runtime
err_sys() only caught the misconfiguration in an autotools build that
got as far as running; the #error catches it at compile time for the
IDE and plain Makefile builds too.
- Treat WS_WANT_READ and WS_WANT_WRITE out of wolfSSH_worker() as a
clean shutdown. The socket is non-blocking, so the peer having
nothing ready is not a session failure.
- -E was parsed into config.logFile and printed by -G, never read.
- Install a logging callback that writes to the named file, following
what wolfsshd does for its own -E.
- Turn logging on with wolfSSH_Debugging_ON(). Installing the callback
is not enough on its own, the file came out empty in any build that
wasn't --enable-debug, including the --enable-all builds where the
library has all of its logging compiled in. wolfsshd turns logging on
the same way.
- Match DefaultLoggingCb()'s format, timestamp and level tag, so a log
written to the file and one written to stderr are comparable. That
function's GetLogStr() is private to the library, so the level names
are repeated in the app.
- Parse the command line and open the file in main(), before
wolfSSH_Init(), so the start up messages land in the file.
- Close the file after wolfSSH_Cleanup(). The callback cannot be
uninstalled, so it ran with a closed stream and segfaulted on exit.
It falls back to stderr.
- Name the stream logFileStream, apart from struct config's logFile,
which is the path it was opened from.
- Drop the always true condition around the session threads.
CHANNEL_PACKET_OVERHEAD_MAX is a hand-computed copy of
CHANNEL_PACKET_OVERHEAD_SZ, needed because the expression bottoms out in
wolfCrypt enum constants that #if reads as zero. Nothing tied the two
together, so a term added to the expression would leave the #error
guarding DEFAULT_MAX_PACKET_SZ silently ineffective.
Assert the bound in internal.c, where both are ordinary constant
expressions, with a negative-array-size typedef.
The refusals added for names the peer cannot use changed the return
contract of a public API whose block comment still promised only
WS_SUCCESS. There is no dox_comments entry, so that comment is all an
embedder has.
- Spell out each WS_BAD_ARGUMENT case, the keep-the-stored-name rule,
and that a refused call leaves the selected type alone.
- api.c asserts connectChannelId across the refusals. It is the field
SendChannelRequest() switches on, so moving the checks back below the
assignment would otherwise pass.
A window-change arriving before any pty-req had nothing to resize, but
the size was stored and the resize callback run anyway. Dropbear refuses
the same request for the same reason.
- Reject it with the existing rej path, so no reply is sent for a
request RFC 4254 sec 6.7 says takes none, and the session continues.
- unit.c covers the rejection, and now drives a real pty-req, which
had no coverage on the receive side at all.
The four pty-req and window-change dimensions were decoded straight into
the WOLFSSH fields and handed to the resize callback unchecked. The
consumers copy them into the unsigned short fields of a struct winsize
for TIOCSWINSZ, so anything above 65535 wraps, and 0x10000 arrives as a
0x0 terminal.
- Add SetTerminalSize() and route both the pty-req and window-change
branches through it, so pty-req stops decoding straight into the
WOLFSSH fields.
- Clamp all four to TERMINAL_DIMENSION_MAX. Others truncate at the
ioctl and accept it, but wolfSSH hands the word32 values to
termResizeCb first, so an unclamped dimension escapes the library
rather than being cut down on the way to the ioctl.
- Take a zero dimension as sent. Others do too, and a zero is how a
peer reports a dimension it has no information about.
- unit.c drives all four dimensions from one table, covering the zero,
single-zero and wrapping cases, in an error code range no other case
in the function claims.
F-8833 recommended ignoring a zero dimension. That is declined above:
Others take zeros as sent, and a zero is how a peer reports a dimension
it has no information about. The finding's symptom, a 0x0 terminal, is
also reached by a route it did not identify, a dimension above 65535
wrapping, and the clamp closes that one.
Issue: F-8833
DoPacket stepped to the next packet using payloadIdx, which handlers
set to however much they read. The default case reads none of an
unimplemented message's payload, leaving the cursor short by that much.
- Advance inputBuffer.idx by UINT32_SZ + curSz from the packet start,
the length DoReceive already bounds-checked, so a handler that
ignores trailing bytes cannot move the next packet's start.
- Snapshot curSz on entry beside the packet start, so the frame is
computed entirely from entry-time state. Reading it back after the
handler switch would describe the next packet if a handler ever
re-entered the receive path.
- Covers DoIgnore, DoDebug, DoUnimplemented, DoChannelSuccess and
DoChannelFailure, which are all short on a padded payload.
- Clamp to the buffer length on the WS_BUFFER_E path.
- unit.c pins the cursor across an unimplemented message, driving
DoPacket through a new wolfSSH_TestDoPacket() hook. The ShrinkBuffer()
noted below zeroes the cursor, so DoReceive() cannot be in the path.
Note the short cursor is not currently observable: DoReceive calls
ShrinkBuffer() with forcedFree, which drops the rest of the buffer
after every packet. This is hardening, not a live desync.
Issue: F-8825
wolfSSH_SetChannelType() discarded an exec or subsystem name it could
not use and still returned WS_SUCCESS. SendChannelRequest() then omits
the name field entirely, which the peer rejects as malformed, dropping
the connection. Both an oversized name and an empty one reach it; the
empty case is reachable from the command line as "wolfssh -c ''".
- Return WS_BAD_ARGUMENT for a name at or above WOLFSSH_MAX_CHN_NAMESZ,
matching how the function already reports a bad type or side.
- Return WS_BAD_ARGUMENT when no name is given and none was stored by
an earlier call, and when a size arrives with no name behind it.
- Keep returning WS_SUCCESS when an earlier call stored a name, which
is what the SFTP and SCP retry loops depend on.
- Return before setting connectChannelId so a rejected call leaves
no state behind, as the server-side exec rejection does.
- Keep the stored name intact when a later call is refused.
- api.c asserts each refusal, and the largest name still admitted.
MAX_PACKET_SZ caps the whole SSH binary packet, but the channel
maxPacketSz it was compared against counts only channel payload. A
peer honoring the advertised 35000 overruns the receiver's own check.
- Derive MAX_CHANNEL_PACKET_SZ in internal.h: MAX_PACKET_SZ less the
transport framing, the CHANNEL_EXTENDED_DATA header, the worst-case
padding BundlePacket() picks, and MAX_HMAC_SZ. 34899 by default.
- Name that overhead twice, once for the compiler and once as a
literal for the preprocessor, which reads the wolfCrypt enum
constants in the first form as zero. The #error guarding
DEFAULT_MAX_PACKET_SZ uses the second rather than its own copy.
- MAX_CHANNEL_PACKET_SZ is derived rather than a tunable, so it is
not overridable; an override defeated the bound it enforces.
- wolfSSH_CTX_SetWindowPacketSize() bounds maxPacketSz against that
instead of MAX_PACKET_SZ; DEFAULT_MAX_PACKET_SZ is unaffected.
- api.c tests the new edge and that MAX_PACKET_SZ is now rejected.
Issue: F-8835
- The startup banner's password line and its argument are dropped
from the printf; ssh host, username and the two forward endpoints
remain.
- userPassword has internal linkage, and portfwd_worker() zeroes it
with wc_ForceZero() as soon as wolfSSH_connect() returns, on both
the success and the failure path.
- portfwd.c includes wolfssl/wolfcrypt/memory.h.
Issue: F-11673
- BuildUserAuthRequestEd25519() signs with wolfSSH_AGENT_SignRequest()
when the agent is enabled, writing the returned signature blob
length-prefixed into the reserved payload and advancing idx past it.
The capacity handed to the agent is the room the prepare phase set
aside: two lengths plus the signature and public key type sizes.
- The buffer the local signing path fills is allocated in that path
rather than at the top of the function; sig starts NULL and the
small-stack free at the tail already null-checks it.
- PrepareUserAuthRequestEd25519() notes that the agent holds the
private key and loads none locally.
- tests/regress.c gains TestAgentEd25519UserAuthEmitsSignature(),
TestAgentEd25519UserAuthPropagatesAgentError() and
TestAgentEd25519UserAuthRejectsOversizeSignature(), which drive
SendUserAuthRequest() over a mock agent and parse the emitted
USERAUTH_REQUEST down to its signature field.
- InitAgentEd25519Ctx() takes the signature size the mock agent
answers with, so a caller can hand back a blob past the capacity.
- ParsePayloadLen() and BuildExtInfoSigAlgs() move to the shared test
helper section so the new tests and the existing callers share them.
Issue: F-11660
- GetOpenSshPublicKey() calls NameToId() and enters the key-type
switch only when GetStringRef() returns WS_SUCCESS, and returns
that result otherwise.
- publicKeyType starts NULL and keyId starts ID_UNKNOWN.
- tests/api.c adds test_GetOpenSshPublicKey_type(), gated on
WOLFSSH_TPM and WOLFSSH_TEST_INTERNAL, covering a truncated type
string, a truncated length prefix, an empty type, an unsupported
type and a well-formed ssh-rsa blob.
- Each case asserts idx alongside the return code: UINT32_SZ for a
truncated type string, 0 for a truncated length prefix, and the
full blob size for the empty type, the unsupported type and the
ssh-rsa key.
Issue: F-11650
- wolfSSH_SFTP_Put() adds WOLFSSH_FXF_TRUNC to the destination open
only when the write offset is zero.
- STATE_PUT_LOOKUP_OFFSET clears a saved offset when the local file
is no larger than it.
- A new STATE_PUT_STAT_REMOTE stats the destination when the saved
offset is nonzero, and clears the offset unless the reported size
matches it exactly, or the stat returns WS_SFTP_STATUS_NOT_OK or
WS_PERMISSIONS. Other stat failures re-save the offset and move to
STATE_PUT_CLEANUP; a want-read or want-write keeps the state.
WS_SFTP_PUT_STATE carries the attributes both states read.
- The Windows server open maps WOLFSSH_FXF_CREAT to OPEN_ALWAYS and
reserves CREATE_ALWAYS for an open that also asked for
WOLFSSH_FXF_TRUNC; the disabled TRUNCATE_EXISTING mapping is
dropped.
- tests/api.c adds test_wolfSSH_SFTP_PutResume(), five cases over the
resume paths, built where the hosted file wrappers are available.
Issue: F-11659
- DoReceive() validates the peeked packet_length in
PROCESS_PACKET_LENGTH: UINT32_SZ plus curSz for non-AEAD, curSz
alone for AEAD, against peerBlockSz floored at MIN_BLOCK_SZ. A
non-zero remainder sets ssh->error to WS_BUFFER_E and returns
WS_FATAL_ERROR.
- BuildMacTestPacketPrefix() in unit.c takes padLen from the caller
and pads to a block-aligned total; test_DoReceive_VerifyMacFailure,
test_DoReceive_AeadTagFailure, and
test_DoReceive_RejectsShortPadding follow.
- BuildPacket() in regress.c pads to 16.
- test_DoReceive_RejectsMisalignedPacket,
test_DoReceive_RejectsMisalignedCtr, and
test_DoReceive_RejectsMisalignedAead cover the cleartext, AES-CTR,
and AES-GCM paths.
Issue: F-8834
QNX system images fix the host key's owner and modes, and the daemon cannot
change either, so the secure gate refuses to load a key the integrator has no
way to correct. Add a hand-defined WOLFSSH_NO_HOSTKEY_PERMS, further
conditional on QNX, that hands only that policy to the platform.
- Fold the macro and the QNX test into the internal
WOLFSSHD_HOSTKEY_RELAX_PERMS in wolfsshd.c.
- Add a relaxPerms argument to wolfSSHD_OpenSecureFile() that skips the owner,
mode and ancestor-directory checks.
- Keep the structural checks: lstat, O_NOFOLLOW, S_ISREG and the dev/ino
recheck, so a symlink, a non-regular file or a swap during the open is still
refused.
- Set it only on the host key load, leaving the host cert, UserCAKeysFile,
authorized_keys and shadow gates unchanged.
- Log at startup when the guard is built in.
- Add six test_OpenSecureFile scenarios for the relaxed path, unreachable at
runtime off QNX and so otherwise uncovered.
Issue: ZD-22308
wolfSSHD_GetUserConf returned the first matching Match block whole, so a
keyword named only in a later matching block was dropped and the outcome
depended on the order the blocks were written.
- track in a new setMask which keywords a node set itself, so a value
inherited from the globals can be told from one the block named, with a
compile time check that no option tag shifts out of the mask
- resolve into a fresh config seeded from the globals, letting every
matching block contribute the keywords no earlier block claimed
- the resolved config now belongs to the caller, so wolfsshd and the auth
paths free it and the tests compare values rather than node identity
- put sshd_match_overlap_test.sh back in the suite
Issue: ZD-22324
OpenSSH resolves sshd_config one keyword at a time, scanning every Match
block that applies. wolfSSHD_GetUserConf returns the first matching block
whole, so a setting made only in a later matching block is dropped.
- add test_GetUserConfMatchOverlapCompose, covering a user matched by both
a Match User and a Match Group block, in either order
- add sshd_match_overlap_test.sh, the same case against a live daemon,
where the group block's ForceCommand is the setting that goes missing
- both fail until per keyword composition lands, so the unit test runs
last and the script stays commented out of run_all_sshd_tests.sh
- IsShadowExpired() in auth.c returns 1 when a shadow entry's
sp_expire date has arrived, its sp_lstchg is 0, or the day is at or
past sp_lstchg + sp_max. Negative fields leave the matching check
off; a negative day count, standing for an unavailable clock,
denies the entries that carry aging. WSSHD_SECS_PER_DAY converts
WTIME() into the unit those fields use. The helper is compiled
under HAVE_SHADOW and !WOLFSSH_USE_PAM, as its caller is.
- CheckPasswordUnix() runs the shadow entry it looked up through the
helper and, after an otherwise successful hash compare, logs the
denial and returns WSSHD_AUTH_FAILURE.
- auth.h declares IsShadowExpired() for the unit test build.
- test_configuration.c adds test_IsShadowExpired() over a table of
aging fields and day counts, and test_CheckPasswordUnix_expired()
for the denial of a correct password.
- The CheckPasswordUnix() tests share one driver,
wsshd_test_CheckPasswordUnixCase(), with the crypt() setup in
wsshd_test_LoadShadowHash() and the three fail-closed shadow
lookups gathered into test_CheckPasswordUnix_failClosed().
Issue: F-10577
- wolfssh/internal.h derives WOLFSSH_NO_PUBKEY_AUTH when RSA, ECDSA,
Ed25519, and ML-DSA are all disabled.
- DoUserAuthRequestPublicKey(), the publickey dispatch in
DoUserAuthRequest(), the ID_USERAUTH_PUBLICKEY case in
DoUserAuthFailure(), Prepare/BuildUserAuthRequestPublicKey(), and
GetAllowedAuth() are all guarded by that macro.
- The DoUserAuthFailure() and GetAllowedAuth() guards previously
omitted Ed25519 and ML-DSA; the DoUserAuthFailure() guard also
carried a WOLFSSH_TPM term, which is dropped.
Issue: F-10542
- STATE_PUT_WRITE logs, sets ret to WS_FATAL_ERROR, clears
state->handleSz and moves to STATE_PUT_CLOSE_LOCAL when
wolfSSH_SFTP_SendWritePacket() returns a non-positive size and
NoticeError() is false.
- ssh->error takes that return value, or WS_FATAL_ERROR for a size of
zero, when ssh->error is still WS_SUCCESS.
- The write loop is followed by a continue when ret is not
WS_SUCCESS.
- tests/unit.c gains WOLFSSH_TEST_SFTP_PUT, the SftpBuildReply()
helper, and test_SftpClientPutWriteStatusFail(), which drives
wolfSSH_SFTP_Put() over a staged handle reply and a write answered
by an FXP_STATUS failure.
Issue: F-10543
wolfSSL master now rejects a private scalar outside [1, n-1] when importing
one, so the zeroed key that test_IdentifyAsn1Key_EccPrivOnlyDerFailure builds
fails in wc_EccPrivateKeyDecode instead of reaching the wc_ecc_make_pub
fallback in IdentifyAsn1Key. The identify call then reports the key as
unidentified, WS_UNIMPLEMENTED_E, rather than WS_CRYPTO_FAILED, and the test
failed against any wolfSSL built from master.
- decode the corrupted DER first and expect the rejection the linked wolfSSL
performs, so the assertion stays strict on either library
stop_wolfsshd killed $PID unconditionally. With the daemon already gone the
kill failed, and under "set -e" that aborted the caller -- in
sshd_forcedcmd_test.sh before PID was cleared, so the ForceCommand-SFTP
scenario was silently skipped, the EXIT trap killed the dead pid a second
time, and the script exited 1.
- Guard on a non-empty PID, ignore a failed kill and return 0, so the
function is safe to call from an EXIT trap.
- Clear PID after stopping, so a second call cannot kill a recycled pid.
- Remove the temp key dir even when no daemon was recorded, so a daemon that
failed to start does not leak it.
- Collapse sshd_forcedcmd_test.sh's cleanup() wrapper to a bare
trap stop_wolfsshd EXIT now that the function guards itself.
- Check the cd back to the test directory in sshd_x509_upn_fail.sh; the log
it counts after the client run is the one there.
sshd_privdrop_fail_test.sh runs from apps/wolfsshd/test and handed the
example clients relative key paths, but the clients call
ChangeToWolfSshRoot() before parsing arguments. Every client died at
"Error setting private key" and the test blamed the privilege drop.
- Anchor the key, payload and client paths at the script's own directory.
- Rename the saved directory to TESTDIR so a later cd cannot clobber it.
- Report "no fork at all" separately in the timeout diagnostic.
- Print the client's own output at every failure exit, so a client that
never connects cannot be read as a daemon fault.
- Keep the client logs like log.txt, gitignored and removed on success.
Eight scripts saved their starting directory in PWD, which the shell
rewrites on every cd, so the "cd $PWD" restore landed in the repository
root. sshd_forcedcmd_test.sh's second scenario and the log count in
sshd_x509_upn_fail.sh silently never did what they cover.
- Save the starting directory in TESTDIR, as sshd_pubkey_reject_test.sh does.
- Quote "$TESTDIR" at every cd, now that the saved value is really used.
- Stop the daemon from a trap in sshd_forcedcmd_test.sh, so its now reachable
second scenario cannot leave one on the shared port when set -e aborts.
- Take start_wolfsshd's before and after daemon PID snapshots from pgrep -x
instead of scraping every digit run out of "ps -e", which mixed the TIME
field's clock digits in with the PID and, with a leftover daemon running,
stopped the wrong process.
- Let both snapshot pipelines fail, so a set -e caller survives no daemon
being up and a daemon that dies after sudo returns is reported by the
caller's own empty-PID check.
grep -c prints 0 and exits 1 when nothing matches, so the "|| echo 0"
fallback fired too and the count became "0\n0". The arithmetic error
unwound bash out of the test block, skipping the last eleven tests while
the summary still printed a pass and exited 0.
- Use the bare grep -c result and default only the empty case.
- Add a RUN_COMPLETE sentinel at the end of each branch that runs tests.
- Check the sentinel before the summary so an abort exits non-zero.
- Kill lingering daemons by process name, so the teardown does not kill
the run itself before that check when invoked by a path holding
"wolfsshd".
- Chaining each path off root formats one 256 byte buffer into another,
which GCC cannot prove fits, failing every Linux build with
-Werror=format-truncation.
- Sizing cwd to leave room for the suffixes bounds the paths by the
declared sizes. A cwd too deep to fit fails WGETCWD and skips as
before.
- Add wolfSSH_SFTP_SetConfinePath and a separate sftpConfinePath, so
the start path only says where a session begins, and only an
explicit confinement root rejects out-of-tree requests.
- Have GetAndCleanPath take the WOLFSSH and enforce the confinement
root, resolving relative requests against the start path.
- Factor the shared canonicalize-and-store work out of
wolfSSH_SFTP_SetDefaultPath into CanonicalizePath and StorePath.
- Give the echoserver -D to opt a session into confinement; without
it the -d home directory only says where SFTP starts.
- Document both settings, and the symlink and TOCTOU caveats, once in
wolfsftp.h, noting the confinement root itself is trusted.
- Cover the split in api.c, and in regress.c start a session in a
subdirectory of the confinement root: a sibling of the start
directory is reachable, anything above the root is not.
Issue: ZD-22308
- PostSignRequest() allocates the signature buffer from agent->heap,
sized from the identity's modulus mpint for RSA and from
ECDSA_ASN_SIG_SZ for ECDSA, and frees it before returning. A modulus
longer than RSA_MAX_SIZE, or a key type that sets no size, returns
WS_BUFFER_E.
- wolfSSH_AGENT_SignRequest() reads the agent's reply into a heap
buffer of WOLFSSH_AGENT_MAX_RSP_SZ, a new overridable define in
agent.c, freed after the last use of agent->msg.
- tests/api.c carries a 3072-bit RSA key and a P-521 key as hex string
components, and build_string() and build_mpint() helpers that write
the message fields. AgentTestCtx.response sizes from
AGENT_TEST_BUF_SZ.
- test_wolfSSH_agent_signrequest_rsa_3072() and
test_wolfSSH_agent_signrequest_ecc_p521() add their identity through
the agent callbacks and sign with it, then clear the stored private
exponent or point and sign again.
test_wolfSSH_agent_signrequest_rsa_too_large() adds an identity whose
modulus exceeds RSA_MAX_SIZE and expects WS_BUFFER_E.
- The comment on test_wolfSSH_agent_signrequest_oversize_rsa_key()
describes the identity that test uses.
Issue: F-10541
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.
- LoadRootCaPemBuffer() loads every block a PEM CA buffer holds as a
root CA, skipping the ones that fail. It returns WS_SUCCESS when
any loaded, WS_PARSE_E when all failed, and WS_BAD_FILE_E when the
buffer holds no block.
- A block runs header to footer with the next header capping the
footer search, so wc_PemToDer() gets the block rather than the rest
of the buffer. A header that nothing closes is skipped and the walk
resumes at its end; each form's header is re-sought only from
behind the one just read.
- A block takes the plain or the trusted form, whichever header leads
picking the type. FindInBuffer() searches a length-delimited
buffer, so an embedded NUL does not end the search.
- wolfSSH_ProcessBuffer() routes a PEM BUFTYPE_CA there and, like
DoPemCert(), gives WS_BAD_FILETYPE_E for the trusted form as a
certificate; SniffCertForm() reads its header as X.509 PEM.
- internal.h defines WOLFSSH_HAVE_TRUSTED_CERT_PEM under
WOLFSSH_CERTS with wolfSSL 5.8.0 or newer and declares
IsTrustedCertPem(); ssh.h documents the cert buffer calls.
- tests/api.c adds catBuffers(), makeTrustedPem() and
assertCaInstalled(), with tests for the bundle, trusted file and
trusted ReadCert paths.
- Assemble the split offset with wResolveOffset() in the Harmony wPread
and wPwrite, and seek with the resolved value.
- Assemble the split offset with wResolveOffset() in the Zephyr wPread
and wPwrite, and seek with the resolved value.
- Define WOLFSSH_MAX_FILE_OFFSET as 0x7FFFFFFF in the Harmony block, so
the ceiling comes from SYS_FS_FileSeek's int32_t offset rather than
from off_t.
- Add test_PreadPwriteOffsetCeiling() covering ports whose seek type
cannot reach 4 GiB, including a read back at an in-range offset.
- Add test_ResolveOffset() covering offset assembly, both sides of the
ceiling, and the NULL guards.
Issue: F-8823
- test.h's static Base16_Decode collides with wolfSSL's public one
when coding.h lands first, breaking --enable-tpm builds.
- Include coding.h in test.h, keeping the local copy only when
WOLFSSL_BASE16 is absent; --enable-wolfssh alone does not set it.
- api.c includes coding.h too, dropping its hand-declared
Base64_Encode_NoNl, which would now be a duplicate.
- No job compiled a wolfSSH test binary with WOLFSSH_TPM defined, so a
test guarded on it compiled out everywhere and could not gate a
merge. This job enables TPM but only builds; the jobs that run make
check do not enable it.
- Add a make check step. automake's check-am builds every check_PROGRAM
regardless of the TESTS override, so this is the only job that
compiles wolfSSH's tests with TPM support.
- Override TESTS to run only tests/api.test, the one suite with
TPM-specific tests. kex.test also aborts in the example client, which
demands -K in a TPM build.
- Restrict it to one matrix cell. The 2x2x2 matrix varies the simulator
and the host key, neither of which these tests touch.
- Assert -DWOLFSSH_TPM in AM_CPPFLAGS first. A build without it
compiles the guarded tests out and still exits 0, a hollow pass.
- Dump tests/api.log on failure and archive it.
- sftpclient passes userEcc to ClientUsePubKey(), and scpclient to
both ClientSetPrivateKey() and ClientUsePubKey(), in place of a
hardcoded 0.
- scpclient gains a userEcc; it and client default it to 1 under
WOLFSSH_NO_RSA, as sftpclient already did.
- ClientSetPrivateKey() and ClientUsePubKey() name the missing
algorithm on stderr and return WS_NOT_COMPILED when the built-in
key they select is compiled out.
- Both skip the built-in load entirely when neither RSA nor ECC is
compiled in, clearing the key size and type and returning success
so password-only authentication still runs. ClientUsePubKey()'s
buffer pointer moves inside the guard so it is not left unused.
Issue: F-8829