Commit Graph

121 Commits (e91ff50def9701d991eb3c49ed104ef6a4787fc4)

Author SHA1 Message Date
Yosuke Shimizu e91ff50def Fix a one byte heap overflow in LoadTpmSshKey 2026-08-13 11:59:57 -07:00
Yosuke Shimizu ca6a036edc Replace the matching certificate slot instead of appending a duplicate 2026-08-12 15:43:01 -07:00
John Safranek ddd9c1a761 Guard IdentifyAsn1Key test on TEST_INTERNAL
- IdentifyAsn1Key is WOLFSSH_LOCAL, so the check and its DER blob
  only build when linking the test library.
2026-08-11 11:55:02 -05:00
Yosuke Shimizu 53538e8261 Report a failed PEM decode as WS_PARSE_E, not WS_BAD_FILE_E 2026-08-10 15:11:39 -07:00
John Safranek 28185e4d90 scp: reject NULL message in SetScpErrorMsg
- check message for NULL alongside ssh
- drop the always-true valueSz guard
- cover both NULL arguments in test_wolfSSH_SCP_CB

Issue: F-7510
2026-08-10 10:31:07 -06:00
Yosuke Shimizu c2d169872e Add certificate loading APIs with content-based format detection 2026-08-05 23:02:51 -07:00
John Safranek e4cccaf02b tests: retry stateful SFTP calls in read staging
- add sftp_retry_remove()/sftp_retry_close() so Close and Remove are
  driven to completion instead of abandoned mid-operation
- split the retry predicate: Open and SendWritePacket keep state only on
  WS_WANT_READ/WS_WANT_WRITE, LS adds WS_REKEYING, Close and Remove gate
  on NoticeError()
- assert the staging close; keep the post-read cleanup best effort, as
  the reads are skipped rather than completed on WS_REKEYING
- route the WOLFSSH_TEST_INTERNAL write cleanup through the helpers
- shrink the staging chunk to 512 bytes
2026-08-05 10:54:31 -06:00
John Safranek 36da2e1b5a tests: harden SFTP read target staging
- Clamp the staging write chunk to the bytes remaining and derive the
  try cap from the chunk count, so the loop lands exactly on
  WOLFSSH_MAX_SFTP_RW for any value of the macro.
- Retry the staging Open and the LS on WS_WANT_READ, WS_WANT_WRITE,
  and WS_REKEYING, matching the rekey tolerance used elsewhere in the
  function.
- Assert the staging Open, the LS, and the listing match rather than
  keying the read block on them, so neither a failed create nor a
  connection stuck in WANT/REKEYING until the try cap can drop the
  read coverage without failing the test.
- Remove any stale file before the staging Open, so the reads never
  target a file staged by a prior aborted run.
- Size the read buffer from WOLFSSH_MAX_SFTP_RW, the amount staged and
  the largest amount read, instead of the listed file size, and drop
  the listed-size guard on the 18 byte read.
- Guard the listing name compare against a NULL fName.
- Verify every read returns the staged fill byte, not just a valid
  length; the check is a macro so a failure reports the calling
  read's line.
2026-08-05 10:54:31 -06:00
John Safranek 153c220a11 tests: fix api.test SFTP read target race
- Opening the listing's first entry raced with tests/testsuite.test,
  which creates and removes files in the same directory under
  "make -j check"; the entry could be gone before the open.
- Stage the read target over SFTP, select it from the listing by name,
  and remove it afterward.
- Check the listing with AssertNotNull; a missing entry used to skip
  the whole test body.
2026-08-05 10:54:31 -06:00
John Safranek 719cc31b60 scp: reuse GetScpFileName buffer instead of realloc
- Track the scpFileName allocation size in a new scpFileNameCap field,
  so GetScpFileName() and ScpCheckForRename() reuse the buffer whenever
  the name plus its terminator fits, instead of testing against the
  previous name length
- Pass scpFileNameCap to the send callback, which writes into
  scpFileName and needs the capacity; scpFileNameSz is now the name
  length on every path, including the source path
- Free and reallocate the transfer buffer in ScpSourceInit(), clearing
  the size fields alongside the pointers they describe
- Wrap a long line in ScpProcessEntry()
- Add test_ScpGetFileName covering the reuse-vs-realloc branch, the
  exact-fit boundary, a grow-by-one that catches an off-by-one in the
  reuse condition, and a source-path buffer holding no name yet
- Add test_wolfSSH_SCP_RecursiveTwoFiles, a real "scp -r" transfer of
  two files, covering the scpFileHeaderSent reset on the recursive
  path added in the duplicate-header fix; it clears leftovers from an
  aborted run up front and bounds its recv so a regression fails
  instead of hanging. Not built on Windows, where a recursive transfer
  through the default callbacks does not reproduce the sent file
2026-08-04 12:20:49 -04:00
John Safranek c2da5989ec scp: fix duplicate file header on send
- Gate header on new scpFileHeaderSent flag, not scpFileOffset==0
- A send callback returning 0 bytes first no longer re-sends header
- Skip zero-length SCP_SEND_FILE send to avoid empty CHANNEL_DATA
- Abort on a second consecutive 0-byte send callback return with file
  data outstanding; skipping the send would otherwise spin
  SCP_SEND_FILE -> SCP_TRANSFER with no socket I/O
- Reset offset/bufferedSz/flags in ScpSourceInit for connection reuse
- Document the WS_CallbackScpSend contract, including when a 0 return
  is valid, next to the typedef
- Add test_wolfSSH_SCP_SendZeroFirst regression (func_args scp_send hook)
- Zero func_args in kex.c/testsuite.c so the new scp_send field is not read uninitialized

Issue: ZD-22176
2026-08-04 12:20:49 -04:00
John Safranek 50da369585 DoPemKey: pass isPrivate through to key identification
- IdentifyAsn1Key() was called with a literal 1, so a public PEM decoded
  by wc_PubKeyPemToDer() was run through the private-key decoders and
  never identified.
- Add test_wolfSSH_ReadPublicKey_pem() covering a public RSA PEM read
  through wolfSSH_ReadPublicKey_buffer(). The read itself only compiles
  with WOLFSSH_TPM, so the test also asserts the isPrivate 0 vs 1
  difference in IdentifyAsn1Key() directly, which every build runs.

Issue: F-7209
2026-08-02 22:10:24 -05:00
John Safranek 5133a1ea39 DoSshPubKey: fix off-by-one null terminator
c[inSz-1] = 0 clobbered the last byte of the copied key data instead
of terminating the string after it, truncating public keys by one
character.

Issue: F-7205
2026-08-02 22:10:24 -05:00
Yosuke Shimizu 06b0499c59 fix: keep wc_RsaSSL_Sign()'s result signed in SignHashRsa 2026-07-28 16:17:11 -07:00
Yosuke Shimizu 029d412e1f Add OpenSSH certificate user authentication 2026-07-27 23:30:20 -07:00
John Safranek 9382811225 Add client-side remote port forwarding
- Add wolfSSH_FwdRemoteSetup/Cancel to request tcpip-forward
- Add SendGlobalRequestFwd to frame the request per RFC 4254
- Add portfwd -r reverse mode, driven by the fwd and req-success cbs
- Wait for the peer's reply before -R reports ready, and take the
  bound port from it; with -f 0 that reply is the only source
- Accept -f 0 in reverse mode, where it asks the peer to pick the port
- Cancel names the port the peer bound, not the one requested, so a
  peer keyed on its listener's port can still find it
- Add a req-failure cb so a refused forward is reported, not waited on

Issue: ZD-21867
2026-07-23 15:54:30 -06:00
John Safranek 35ef7b2cd5 userauth: fix auth-cap counting gaps
- Charge abandoned keyboard INFO_REQUEST before method dispatch so a
  peer can't dodge the cap; drop unused "counted" param.
- Exempt the opening "none" probe in DoUserAuthRequestNone() under
  WOLFSSH_ALLOW_USERAUTH_NONE, matching ssh.h contract.
- unit.c: add keyboard restart, setup-rejection, and none-exemption
  MaxAuthAttempts scenarios.
- api.c: assert "none" cipher/MAC accepted under WOLFSSH_ALLOW_NONE_CIPHER.
2026-07-23 14:51:31 -06:00
John Safranek 928bcd1ce2 Validate algo-list setters, reject none MAC/enc
- Setters stored caller string verbatim; "none" cipher/MAC risked cleartext
- Add CheckAlgoList()/NameToIdType() to validate each token by category
- Set* now returns WS_INVALID_ALGO_ID on bad/NULL input, list unchanged
- "none" is rejected in the key list, and allowed for cipher/MAC only under
  WOLFSSH_ALLOW_NONE_CIPHER
- Names unknown to the build are skipped rather than rejected, so a portable
  superset list still works; a known name in the wrong category fails
- Reject empty list elements apart from one trailing comma, which would
  otherwise reach KEXINIT as a zero-length name
- Give ID_NONE a block size so the none cipher no longer divides by zero in
  BundlePacket(), and skip the zero-length key derivations it implies
- Treat an empty peer server-sig-algs as no extension rather than a fatal
  parse error
- The "at least one X" guards checked the implementation macros but not the
  soft-disable macros that gate joining the canned default list, so a build
  whose only survivors are soft-disabled got an empty default list: KEXINIT
  advertised nothing and CheckAlgoList() rejected it. Reachable as
  -DWOLFSSH_NO_HMAC_SHA2_256 -DWOLFSSH_NO_HMAC_SHA2_512 and as
  -DWOLFSSH_NO_AES_GCM -DWOLFSSH_NO_AES_CTR; both now fail at compile time
  naming the soft-disable macro to define
- Zero MAC algorithms is already a hard #error, so assert the queried MAC
  list in test_wolfSSH_SetAlgoList() rather than returning early, which was
  hiding the KEX/KEY/CIPHER coverage behind an unreachable guard

Issue: 2474
2026-07-23 14:09:19 -06:00
John Safranek 212e976c2b Add server-side max failed userauth attempt limit
- accept() userauth loop had no cap on failed attempts
- Add maxAuthAttempts (CTX, default 6) and per-session authFailures
- CountUserAuthFailure() counts only genuine pw/pubkey/kbd-int failures
- On limit: send SSH_MSG_DISCONNECT, fail accept; SetMaxAuthAttempts(<=0)=default

Issue: 2473
2026-07-23 14:09:19 -06:00
Yosuke Shimizu 5acbeaeaee Run threaded api-test SFTP/SCP tests on Windows 2026-07-22 17:29:27 -05:00
Yosuke Shimizu 0b819b0b48 wolfterm: bound escBuf saves and clear esc state on OSC resume
Harden the partial-sequence reassembly in wolfSSH_DoControlSeq and fix an
escape-state leak in the wolfSSH_ConvertConsole OSC resume path
(USE_WINDOWS_API console handling).

- Tighten both escBuf partial-save branches to reject bufSz - *idx >=
  WOLFSSL_MAX_ESCBUF before the WMEMCPY and log via WLOG. escBuf is
  WOLFSSL_MAX_ESCBUF bytes, so a save of exactly that length fills it with
  no room for later state; rejecting the boundary keeps the two branches
  consistent and matches the resume check.

- Add the capacity guard to the initial-parse CSI save branch, which
  previously copied into escBuf with no bound. In the default build getArgs
  caps the advance below WOLFSSL_MAX_ESCBUF so the copy was already safe;
  the guard prevents a custom WOLFSSH_MAX_CONSOLE_ARGS > WOLFSSL_MAX_ESCBUF
  build from overflowing escBuf.

- Clear escState to WC_ESC_NONE when a resumed OSC sequence completes, not
  just escBufSz. Without this escState stayed WS_ESC_OSC and the next call
  re-entered OSC parsing on plain bytes instead of printing them.

Extend test_wolfSSH_ConvertConsole with a CSI sequence split across three
calls (ESC[ | args | command char), a trailing plain byte that must be
printed once state is cleared, and a single buffer whose CSI args run to
the end and complete on the next byte.
2026-07-21 12:57:31 -05:00
Yosuke Shimizu 1f70747236 certman: enforce leaf is end-entity in VerifyCerts_buffer 2026-07-20 19:50:11 -05:00
aidan garske 1b276273e9 Allocate channelName dynamically to shrink WOLFSSH struct by ~4KB 2026-07-20 17:43:42 -05:00
aidan garske 091310a1eb F-3881 - Reserve separator and NUL in RealPath segment bound check 2026-07-20 17:24:02 -05:00
Yosuke Shimizu 6dd249beb5 Reject SFTP resume names that fill the whole name field 2026-07-17 14:06:19 -06:00
Eric Blankenhorn 28701904c1 Harden DoOpenSshKey parsing 2026-07-06 16:55:54 -05:00
Yosuke Shimizu c8a347de85 Reject symlinks in default SCP send callback 2026-06-23 14:37:57 -07:00
Yosuke Shimizu f2b4f43c20 Sanitize control bytes in formatted log messages 2026-06-18 13:52:00 -07:00
Yosuke Shimizu 2425f7c594 Bound OSC index before reads in wolfSSH_DoOSC 2026-06-18 11:00:42 -07:00
Yosuke Shimizu 1efd64743c wolfssh/scp: complete rekey that starts mid-transfer 2026-06-16 15:56:50 -07:00
Yosuke Shimizu cb9bb7a2a7 Fix SFTP client states dropping unsent bytes after partial channel send 2026-06-16 11:21:19 -07:00
David Garske ba09b582ba
Merge pull request #1007 from ejohnstown/hex2octal
Convert file permission hex constants to octal
2026-06-09 14:22:34 -07:00
Yosuke Shimizu d49b15f51a SFTP path confinement and status-reply refactor 2026-06-09 10:46:17 -07:00
John Safranek 3abdc22355 Convert file permission hex constants to octal
- Replace hex literals (0x1ED, 0x124, 0x4000, etc.) with octal
  equivalents (0755, 0444, 040000) in SCP/SFTP attribute handling
2026-06-08 10:39:48 -07:00
Yosuke Shimizu 5a19e449c6 Add upper limit of max window size and packet size, Add unit tests 2026-06-08 08:53:53 -07:00
Yosuke Shimizu aa04eca815 Fix SFTP rekey transparency in buffer_read and buffer_send 2026-06-04 14:36:20 -07:00
John Safranek 63a63cf0fb CERTMAN_VerifyCerts_buffer: reject certsCount=0
- Without the guard, inner loops short-circuit and WS_SUCCESS
  is returned without any verification.
- Add test case covering the new and existing bad-arg paths.

Issue: F-409
2026-05-21 11:42:43 -07:00
Yosuke Shimizu 7d7d04dc70 Fix minor issues and Add unit test for wrong padded OpenSSH key 2026-05-12 13:14:56 -07:00
John Safranek 3a5aa65369 Small Test Reorganization
1. Collect all the test function wrappers in internal.c to one location
   at the end of the file.
2. Update API test to check other algos if RSA or ECDSA are disabled.
3. Added guarded tests TestClientBuffersIdempotent() for WOLFSSH_NO_RSA
   and WOLFSSH_NO_ECDSA_SHA2_NISTP256. If both are set, the test is
   skipped.
2026-04-24 09:43:56 -07:00
John Safranek aad92b54ea Fix warning for unchecked errno in api.c test
Replace rewind() with fseek(f, 0, SEEK_SET) in the test helper
function. rewind() internally clears errno, which scan-build flags
as overwriting a previously unchecked errno value. fseek() to
offset 0 is functionally equivalent without the implicit errno
reset.
2026-04-22 10:27:06 -07:00
John Safranek afedde7a1d Fix Potential Double Free
Static analysis indicated the potential to double-free a pointer in the
`wolfSSH_CTX_UseCert_buffer()` test. Loading the second cert after
freeing the first cert could fail and the test cleanup would free the
pointer again. Just set pointer to null after freeing.
2026-04-22 10:27:06 -07:00
Yosuke Shimizu b007310fa2 Fix wolfSSH_RealPath tests 2026-04-21 16:01:41 -07:00
Yosuke Shimizu 9e3eee1276 Fix existing tests 2026-04-15 11:04:09 +09:00
Eric Blankenhorn 0bb1d1b5b7 Add test case test_wolfSSH_CTX_UsePrivateKey_buffer_pem 2026-04-06 16:13:41 -05:00
aidan garske 09144d0c7a Add more wolfSSH CI workflows 2026-03-03 21:22:39 -08:00
John Safranek 8951bd9209 Release v1.4.22
1. Update copyright date to 2026.
2025-12-29 16:53:33 -08:00
Andrew Hutchings 190dda3aa9 Fix agent test setup
Instantiate a wolfSSH_AGENT_CTX before invoking wolfSSH_AGENT_SignRequest so the regression tests exercise the intended paths instead of failing with WS_AGENT_NULL_E.
2025-10-22 15:31:46 +01:00
Andrew Hutchings 662247394f Add agent sign request regression tests
Exercise agent write failures, non-signature responses, oversized signatures, and the happy path to cover the recent wolfSSH_AGENT_SignRequest hardening.
2025-10-22 15:10:58 +01:00
JacobBarthelmeh cc17941a61 adjust test case to account for re-keying return 2025-09-16 14:16:16 -06:00
JacobBarthelmeh 2a11471bb7 refactor introducing more use of NoticeError 2025-09-16 13:30:25 -06:00