Commit Graph

224 Commits (c71202ffdb92202cc53bd520ee45f438d2edded4)

Author SHA1 Message Date
John Safranek 7325678553 echoserver: keep the EOF reply owed across a rekey
wolfSSH_ChannelIdRead() has no rekey guard, so a drained channel still
reports zero mid-rekey and the drain loop calls the reply in. That send
returns WS_REKEYING before it prepares a packet, so nothing is queued.

- take the send's status instead of discarding it
- latch eofAnswered and ChildRunning on every status but WS_REKEYING, so
  the reply is retried on a later pass; the KEX traffic wakes it
- a short send is left latching: it bundled the EOF and set eofTxd, so a
  retry queues nothing and the loop would stall in an untimed select
  waiting on a peer that has already half-closed
- same change in the Espressif copy
2026-08-31 11:53:29 -05:00
John Safranek fc3b0a86bd Take the worker's status before the EOF drain
The drain runs between wolfSSH_worker() and the get_error() that classifies
its result, and its reads and sends latch their own status: WS_WINDOW_FULL
and WS_WANT_WRITE from a send, WS_REKEYING from a read. The ladder then read
the drain's status as the worker's, matched no arm, and ended the session
with the backlog unsent and no EOF.

- Read the error once, right after the worker returns
2026-08-31 11:53:29 -05:00
John Safranek ad08a10ba6 Hold the EOF drain's unsent tail across passes
A chunk read out of the channel is gone from it, so breaking the drain on
a non-positive send dropped whatever the send had not taken, and the echo
back to a half-closing peer came up short.

- Keep the chunk and its offset across worker passes, and read the next
  chunk only once the last one is out
- Give the drain its own buffer; the read path below it reuses
  channelBuffer in the same pass
- Answer the EOF off a drained flag, since a held tail means a zero read
  count no longer marks an emptied channel
2026-08-31 11:53:29 -05:00
John Safranek ff59c723ec Handle the EOF status in apps and examples
Every in-tree caller of wolfSSH_worker() now recognises a peer half-close.
wolfsshd's shell loop and both echoservers need it: all three ladders end in
"else if (rc != WS_WANT_READ) break", and wolfsshd's reaches
kill(childPid, SIGKILL), so without it a client half-close kills the command
it just finished feeding.

- wolfsshd closes the child's stdin off the channel's own EOF state instead of
  off a worker return of zero, which no longer happens on a half-close.
- The echoservers answer the half-close off wolfSSH_ChannelGetEof() rather
  than the WS_EOF status: the flush inside wolfSSH_worker() can supersede that
  status, and it is raised once. They hand back the backlog first, finish a
  short send, and only send the EOF once the channel is empty. Answering is
  not conditional on the shell build, where an echo session is the default.
- The SFTP loops peek before leaving, so a half-close with requests still
  buffered is served rather than dropped, and they report an ordinary session
  end as success.
- The clients -- examples/client, scpclient, sftpclient, apps/wolfssh -- treat
  it as the graceful case instead of an error. apps/wolfssh counts it as a
  finished flush as well, since one worker pass can drain the queue and
  consume the peer's EOF together.
- portfwd relays it to the local socket with shutdown(SHUT_WR) so a local
  reader waiting on end-of-input returns, once the backlog has genuinely been
  handed over: a read cut short by a rekey leaves the half-close for a later
  pass.
- The Windows half of wolfsshd does not answer with an EOF of its own. That
  latches eofTxd and the child's remaining output would be refused, which is
  the defect this series removes from the library.
- The mplabx port drains before tearing down, the way its SFTP read path
  already did; its worker arm was unreachable for a half-close until now.
2026-08-31 11:53:29 -05:00
John Safranek ad059d7d0e echoserver: only continue the rekey drain on an empty read
wolfSSH_ChannelIdRead() returns a negative value for a real error, and
the rekey arm treated that the same as a zero read. Restrict the
continue to cnt_r == 0 so an error still ends the loop.
2026-08-28 18:26:25 -05:00
John Safranek 59a1ef8eec echoserver: close the agent socket on reset and handle a rekey
The worker drops back to APP_STATE_LISTEN when an agent connection ends,
but never closes the socket. The next accept() overwrites agentFd, so
every agent connection after the first leaks the previous descriptor. The
forward path has the same gap on its connection-reset arm, where the
socket is closed but fwdFd keeps the closed number.

A rekey was treated as a read failure and ended the session. It cannot
just be skipped either: wolfSSH_worker() reports WS_REKEYING in place of
WS_CHAN_RXD while keying, and nothing raises the data report again, so
ignoring it strands whatever arrived in that call and the peer waits on
an answer that never comes. This is the hazard the library already calls
out for WS_EXTDATA, which is exempted from the same override.

- close agentFd and clear it on both the read-zero and the
  ECONNRESET/ECONNABORTED arms
- clear fwdFd on the forward reset arm, matching the read-zero arm
- clear agentCtx.appFd and fwdCtx.appFd wherever the worker closes the
  socket, so the stored copy cannot outlive the descriptor
- drain the channel on WS_REKEYING as well as WS_CHAN_RXD, and take an
  empty read as "nothing buffered" rather than a failure on that path.
  wolfSSH_ChannelIdRead() has no isKeying gate and the window credit it
  owes is parked until the rekey completes
2026-08-28 18:26:25 -05:00
John Safranek 26ccac3cdd examples, tests: terminate the ES_ERROR messages with a newline
ES_ERROR() passes its arguments straight to fprintf(stderr, ...), so a
message with no trailing newline runs into whatever the shell or the
test harness prints next.

- 7 sites in the echoserver, 6 in tests/auth.c, 8 in the Espressif copy
  of the echoserver, which carries the same macro and takes this kind of
  cross-cutting fix (e91ff50d, ab8058d7)
- the two wrapped format strings already ended with a newline
2026-08-28 18:22:34 -05:00
John Safranek 3b43e485dd Split SFTP confinement from the start path
- 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
2026-08-20 09:56:48 -06:00
Yosuke Shimizu e91ff50def Fix a one byte heap overflow in LoadTpmSshKey 2026-08-13 11:59:57 -07:00
Yosuke Shimizu 255dd926d9 Adopt the certificate loading APIs in the examples and apps 2026-08-12 16:06:39 -07:00
Emma Stensland 244c82c86d Add remaining ML-DSA composite signature algorithms 2026-08-10 14:51:37 -07:00
Emma Stensland 866f7392cd Add ML-DSA44-Ed25519 composite signature support 2026-08-10 14:51:37 -07:00
Ruby Martin ab8058d7cd check return value of WFTELL() 2026-08-10 10:19:45 -07:00
Ruby Martin 97bbe42263 Add WFSEEK return value checks where previously discarded 2026-08-10 10:19:45 -07: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 0883b9b868 examples/echoserver: check key load errors
- Test wolfSSH_ReadKey_buffer() and wc_CertPemToDer() results and skip
  the entry; a malformed file gave PwMapNew() a NULL buf and an
  indeterminate length.
- NULL-check both WMALLOC() results, and guard the load_file() size so
  a missing file no longer reaches WMALLOC(0).
- Fall through to the loop's existing WFREE()/advance so both buffers
  are freed on every path.

Issue: F-7204
2026-08-02 22:10:24 -05:00
John Safranek 4caf4558f4 Fix echoserver remote-forward listener accept
- ssh_worker() cached fwdCtx.listenFd at entry, while still -1
- The listener is only made later, from WOLFSSH_FWD_REMOTE_SETUP
- FD_SET() and accept() then got a bogus fd, failing with EBADF,
  which broke the worker loop and dropped the session
- Read listenFd from the context at each use, guarded on validity
- agentListenFd has the same shape but is set up before ssh_worker()

Issue: ZD-21867
2026-07-23 15:54:30 -06:00
Yosuke Shimizu 5acbeaeaee Run threaded api-test SFTP/SCP tests on Windows 2026-07-22 17:29:27 -05:00
aidan garske d18e282457 F-4583 - Remove vestigial zero-length read in echoserver global_req 2026-07-20 17:24:02 -05:00
Emma Stensland 1f674b0ec7 SSHD/Echoserver: Fix memory leaks and public-key lookup 2026-07-17 20:01:44 -05:00
Emma Stensland c56dc1027f added ml-dsa plain key and cert algorithms 2026-07-06 16:51:21 -05:00
Yosuke Shimizu 673b2d25e7 Report allocated port in tcpip-forward reply
- Reply to a port-0 (dynamic) tcpip-forward with the bound port.
- Add WS_FWD_PORT_CHECK (1024) as the status/port boundary in WS_FwdCbError.
- Callback returns a WS_FwdCbError status below it, the port at or above it.
- DoGlobalRequestFwd reports the port and rejects a port-0 setup with none.
- Map a callback rejection to WS_RESOURCE_E so a no-reply request keeps the link.
- Update the echoserver reference callbacks (examples and Espressif) to
  recover the OS-chosen port with getsockname() and return it under the new
  convention.
- Add regress coverage for the allocated-port and rejection paths.

Issue: F-5573

Co-authored-by: John Safranek <john@wolfssl.com>
2026-06-25 13:27:00 -07:00
aidan garske 633f627422 Use shared wolfTPM2_SetKeyBlobFromBuffer parser and guard TPM signing args 2026-06-16 13:59:52 -07:00
aidan garske a2c28c9c3c Add TPM 2.0 resident server host keys for ECDSA and RSA 2026-06-16 13:59:52 -07:00
John Safranek d43dfd5b83 Coverity: Uninitialized scalar variable
1. Remove the check on authType, it is covered already.
2. Add Keyboard Setup to the existing check on authType.
3. Add a branch for User Auth None so it reaches its handler
   in the map loop rather than the new error case.
4. Add else case for an error.

Fixes CID: 637345
2026-06-16 10:20:06 -07:00
John Safranek 834e60fb77 Echoserver Channel Regrouping
Refactor of the echoserver example only; library is unchanged.

1. Collapse FwdStates and AGENT_STATE_* into a single WS_AppState
   (INIT/LISTEN/CONNECT/CONNECTED). FWD_STATE_DIRECT becomes an
   isDirect flag, cleared after connect.
2. Hoist the fields shared by the forwarding, agent, and shell paths
   into a common WS_AppCtx (privateData, listenFd, appFd, channelId,
   state, buffer). Shell only uses buffer.
3. Feature-specific remainder stays in WS_AgentCbActionCtx (name) and
   WS_FwdCbActionCtx (host/origin name+port, isDirect). Drop the unused
   pid field; inline getpid() at the call site.
4. wolfSSH_AGENT_DefaultActions and wolfSSH_FwdDefaultActions now take
   a WS_AppCtx* and reach feature-specific state via
   appCtx->privateData. echoserver_test() is updated to register the
   WS_AppCtx (not the old CbCtx) with wolfSSH_set_agent_cb_ctx and
   wolfSSH_SetFwdCbCtx.
5. Reindent ssh_worker()'s #ifdef blocks and add /* WOLFSSH_xxx */
   markers.
6. fwd.test.expect: redirect echoserver and portfwd output to log files
   and sync on portfwd's -R ready file instead of matching "sampled" in
   the pty. Under --enable-debug the WLOG volume fills the pty and
   stalls portfwd in select() before channel-open.
2026-05-05 09:05:09 -07:00
Yosuke Shimizu 651e4cae8a Add kex integration test for ed25519 server key 2026-04-16 15:14:42 +09:00
aidan garske 09144d0c7a Add more wolfSSH CI workflows 2026-03-03 21:22:39 -08:00
John Safranek 08ce58ce7c Forwarding Test
1. Add a test script and expect script for testing forwarding.
2. Update portfwd to have a ready file option.
3. Fix echoserver error string, needed NL.
2026-02-26 15:02:19 -08:00
John Safranek 5cd81c9f1f Agent Update
1. Fix a couple unused variable warnings.
2. In wolfSSH_AGENT_DefaultActions(), fix comparison to the result of
   snprintf() treating normal result as an error. Reset the return code
   for the error state of the socket() command. Better cleanup of agent
   startup failures.
2026-02-26 14:37:07 -08:00
John Safranek 78e38999a1 Fix Test Term Size
When running the build tests, the terminal size gets set to 0x0. When
then tests finish, things like vim start to misbehave until you change
your term window size.

1. Echoserver will not change the terminal size when in echo mode.
2. Do not update the modes when the echo server is not in echo mode.
3. Do not set the terminal update callback context when the echo server
   is not in echo mode.
4. Update the guards around the above three items to match the guards for
   the modes update function.
2026-01-13 11:33:03 -08:00
John Safranek 8951bd9209 Release v1.4.22
1. Update copyright date to 2026.
2025-12-29 16:53:33 -08:00
hanshenrik 44dc148dbd replace sys/errno.h with errno.h
Historically, some systems have used <sys/errno.h> in place of <errno.h>, but the C standard,
 all the way back to C89/Ansi C, specifies that the correct name is `errno.h` -
and most modern compilers create a sys/errno.h compatibility shim sys/errno.h -
but musl-gcc does not have this compatibility shim,
 reasoning that sys/errno.h is non-standard, and fails to compile:
```
$ CC=musl-gcc ./configure --enable-static --disable-shared --enable-scp --enable-sftp --enable-shell --with-wolfssl=wolfssl/install-musl
(...)
$ make
make -j17  all-am
make[1]: Entering directory '/home/hans/projects/wolfssh'
  CC       examples/client/common.o
  CC       examples/client/client.o
  CC       src/libwolfssh_la-ssh.lo
  CC       src/libwolfssh_la-internal.lo
  CC       src/libwolfssh_la-log.lo
  CC       src/libwolfssh_la-port.lo
  CC       src/libwolfssh_la-io.lo
  CC       src/libwolfssh_la-wolfscp.lo
  CC       src/libwolfssh_la-wolfsftp.lo
  CC       examples/echoserver/echoserver.o
  CC       src/libwolfssh_la-wolfterm.lo
  CC       examples/sftpclient/sftpclient.o
  CC       examples/scpclient/scpclient.o
In file included from examples/echoserver/echoserver.c:91:
/usr/include/x86_64-linux-musl/sys/errno.h:1:2: error: #warning redirecting incorrect #include <sys/errno.h> to <errno.h> [-Werror=cpp]
    1 | #warning redirecting incorrect #include <sys/errno.h> to <errno.h>
      |  ^~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:1452: examples/echoserver/echoserver.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make[1]: Leaving directory '/home/hans/projects/wolfssh'
make: *** [Makefile:1020: all] Error 2
```

so, unless we need to support pre-C89 (35+ year old C) compilers,
we can just replace sys/errno.h with errno.h.
2025-11-22 17:40:20 +01:00
John Safranek 50aa10d717
Merge pull request #793 from JacobBarthelmeh/rekey
sanity checks on message types during rekey
2025-10-06 13:54:03 -07:00
JacobBarthelmeh 2a11471bb7 refactor introducing more use of NoticeError 2025-09-16 13:30:25 -06:00
gojimmypi dccc62bafd
Rename wolfssh test certs 2025-09-03 11:10:53 -07:00
JacobBarthelmeh 8a8ee954d3 in want write case with example echoserver do not wait on select for data 2025-07-25 11:32:02 -06:00
JacobBarthelmeh a6e523886f fix for clang scan-build warning of variable not used 2025-07-25 11:32:02 -06:00
JacobBarthelmeh 01dd6ec3dc fixes for SFTP want read/write cases 2025-07-25 11:32:02 -06:00
JacobBarthelmeh 88d4eae96a remove keyboard auth callback and use generic auth callback 2025-07-25 11:31:02 -06:00
JacobBarthelmeh 1422697e43 add check for want write in example echoserver to handle new test case 2025-05-20 16:55:42 -06:00
JacobBarthelmeh 71cda6d16c add test case for want write return from highwater callback 2025-05-20 15:18:27 -06:00
Andrew Hutchings c368efb8b2 Make Keyboard Interactive a compile time option
Now an off-by-default compile-time option. This saves resources and
confusion if you are not expecting it.

ZD #19704
2025-04-22 13:12:42 +01:00
Anthony Hu 03afce7236 Forgive a socket error 2025-04-03 19:19:36 -04:00
aidan garske a52c3b120e Used W port.h file operations for keyblob and added username argument so can append any username needed. 2025-04-02 10:33:27 -07:00
aidan garske 69e266178f Used port.h macros 2025-04-01 21:58:49 -07:00
aidan garske 77c8db6cc2 Rebase for tpm public key authentication with wolfssh 2025-04-01 16:44:55 -07:00
Andrew Hutchings f73a76e064 Add DH Group 16 and HMAC-SHA2-512
This adds the `diffie-hellman-group16-sha512` key exchange and
`hmac-sha2-512` mac support.

Echoserver can now take `-x` for key exchange and `-m` for mac setting,
 and `-c` for cipher so that this can be used in the test suite.
2025-02-12 07:06:51 +00:00
Andrew Hutchings a4733ecd95 RFC-4256 Keyboard-Interactive authentication
This implements Keyboard-Interactive authentication.

Adds an additional callback set by `wolfSSH_KeyboarAuthPrompts()` which
will set a callback in the server to ask the application to provide the
prompt details for the client.
2025-02-11 14:19:52 +00:00
JacobBarthelmeh b8e6f595b4 show version of wolfSSL linked to 2024-09-27 14:36:42 -06:00